/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
** version 4.0.0.  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
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
**
** This file is all you need to compile SQLite.  To use SQLite in other
** programs, you need this file and the "sqlite4.h" header file that defines
** the programming interface to the SQLite library.  (If you do not have 
** the "sqlite4.h" header file at hand, you will find a copy embedded within
** the text of this file.  Search for "Begin file sqlite4.h" to find the start
** of the embedded sqlite4.h header file.) Additional code files may be needed
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite4" command-line shell is also in a
** separate file. This file contains only code for the core SQLite library.
*/
#define SQLITE4_CORE 1
#define SQLITE4_AMALGAMATION 1
#ifndef SQLITE4_PRIVATE
# define SQLITE4_PRIVATE static
#endif
#ifndef SQLITE4_API
# define SQLITE4_API
#endif
/************** Begin file sqliteInt.h ***************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

#define SQLITE4_OMIT_PROGRESS_CALLBACK 1
#define SQLITE4_OMIT_VIRTUALTABLE 1
#define SQLITE4_OMIT_LOCALTIME 1

/*
** These #defines should enable >2GB file support on POSIX if the
** underlying operating system supports it.  If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Ticket #2739:  The _LARGEFILE_SOURCE macro must appear before any
** system #includes.  Hence, this block of code must be the very first
** code in all source files.
**
** Large file support can be disabled using the -DSQLITE4_DISABLE_LFS switch
** on the compiler command line.  This is necessary if you are compiling
** on a recent machine (ex: Red Hat 7.2) but you want your code to work
** on an older machine (ex: Red Hat 6.0).  If you compile on Red Hat 7.2
** without this option, LFS is enable.  But LFS does not exist in the kernel
** in Red Hat 6.0, so the code won't work.  Hence, for maximum binary
** portability you should omit LFS.
**
** Similar is true for Mac OS X.  LFS is only supported on Mac OS X 9 and later.
*/
#ifndef SQLITE4_DISABLE_LFS
# define _LARGE_FILE       1
# ifndef _FILE_OFFSET_BITS
#   define _FILE_OFFSET_BITS 64
# endif
# define _LARGEFILE_SOURCE 1
#endif

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
*/
#ifdef _HAVE_SQLITE4_CONFIG_H
#include "config.h"
#endif

/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
/************** Begin file sqliteLimit.h *************************************/
/*
** 2007 May 7
**
** 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 defines various limits of what SQLite can process.
*/

/*
** The maximum length of a TEXT or BLOB in bytes.   This also
** limits the size of a row in a table or index.
**
** The hard limit is the ability of a 32-bit signed integer
** to count the size: 2^31-1 or 2147483647.
*/
#ifndef SQLITE4_MAX_LENGTH
# define SQLITE4_MAX_LENGTH 1000000000
#endif

/*
** This is the maximum number of
**
**    * Columns in a table
**    * Columns in an index
**    * Columns in a view
**    * Terms in the SET clause of an UPDATE statement
**    * Terms in the result set of a SELECT statement
**    * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
**    * Terms in the VALUES clause of an INSERT statement
**
** The hard upper limit here is 32676.  Most database people will
** tell you that in a well-normalized database, you usually should
** not have more than a dozen or so columns in any table.  And if
** that is the case, there is no point in having more than a few
** dozen values in any of the other situations described above.
*/
#ifndef SQLITE4_MAX_COLUMN
# define SQLITE4_MAX_COLUMN 2000
#endif

/*
** The maximum length of a single SQL statement in bytes.
**
** It used to be the case that setting this value to zero would
** turn the limit off.  That is no longer true.  It is not possible
** to turn this limit off.
*/
#ifndef SQLITE4_MAX_SQL_LENGTH
# define SQLITE4_MAX_SQL_LENGTH 1000000000
#endif

/*
** The maximum depth of an expression tree. This is limited to 
** some extent by SQLITE4_MAX_SQL_LENGTH. But sometime you might 
** want to place more severe limits on the complexity of an 
** expression.
**
** A value of 0 used to mean that the limit was not enforced.
** But that is no longer true.  The limit is now strictly enforced
** at all times.
*/
#ifndef SQLITE4_MAX_EXPR_DEPTH
# define SQLITE4_MAX_EXPR_DEPTH 1000
#endif

/*
** The maximum number of terms in a compound SELECT statement.
** The code generator for compound SELECT statements does one
** level of recursion for each term.  A stack overflow can result
** if the number of terms is too large.  In practice, most SQL
** never has more than 3 or 4 terms.  Use a value of 0 to disable
** any limit on the number of terms in a compount SELECT.
*/
#ifndef SQLITE4_MAX_COMPOUND_SELECT
# define SQLITE4_MAX_COMPOUND_SELECT 500
#endif

/*
** The maximum number of opcodes in a VDBE program.
** Not currently enforced.
*/
#ifndef SQLITE4_MAX_VDBE_OP
# define SQLITE4_MAX_VDBE_OP 25000
#endif

/*
** The maximum number of arguments to an SQL function.
*/
#ifndef SQLITE4_MAX_FUNCTION_ARG
# define SQLITE4_MAX_FUNCTION_ARG 127
#endif

/*
** The maximum number of in-memory pages to use for the main database
** table and for temporary tables.  The SQLITE4_DEFAULT_CACHE_SIZE
*/
#ifndef SQLITE4_DEFAULT_CACHE_SIZE
# define SQLITE4_DEFAULT_CACHE_SIZE  2000
#endif
#ifndef SQLITE4_DEFAULT_TEMP_CACHE_SIZE
# define SQLITE4_DEFAULT_TEMP_CACHE_SIZE  500
#endif

/*
** The default number of frames to accumulate in the log file before
** checkpointing the database in WAL mode.
*/
#ifndef SQLITE4_DEFAULT_WAL_AUTOCHECKPOINT
# define SQLITE4_DEFAULT_WAL_AUTOCHECKPOINT  1000
#endif

/*
** The maximum number of attached databases.  This must be between 0
** and 62.  The upper bound on 62 is because a 64-bit integer bitmap
** is used internally to track attached databases.
*/
#ifndef SQLITE4_MAX_ATTACHED
# define SQLITE4_MAX_ATTACHED 10
#endif


/*
** The maximum value of a ?nnn wildcard that the parser will accept.
*/
#ifndef SQLITE4_MAX_VARIABLE_NUMBER
# define SQLITE4_MAX_VARIABLE_NUMBER 999
#endif

/* Maximum page size.  The upper bound on this value is 65536.  This a limit
** imposed by the use of 16-bit offsets within each page.
**
** Earlier versions of SQLite allowed the user to change this value at
** compile time. This is no longer permitted, on the grounds that it creates
** a library that is technically incompatible with an SQLite library 
** compiled with a different limit. If a process operating on a database 
** with a page-size of 65536 bytes crashes, then an instance of SQLite 
** compiled with the default page-size limit will not be able to rollback 
** the aborted transaction. This could lead to database corruption.
*/
#ifdef SQLITE4_MAX_PAGE_SIZE
# undef SQLITE4_MAX_PAGE_SIZE
#endif
#define SQLITE4_MAX_PAGE_SIZE 65536


/*
** The default size of a database page.
*/
#ifndef SQLITE4_DEFAULT_PAGE_SIZE
# define SQLITE4_DEFAULT_PAGE_SIZE 1024
#endif
#if SQLITE4_DEFAULT_PAGE_SIZE>SQLITE4_MAX_PAGE_SIZE
# undef SQLITE4_DEFAULT_PAGE_SIZE
# define SQLITE4_DEFAULT_PAGE_SIZE SQLITE4_MAX_PAGE_SIZE
#endif

/*
** Ordinarily, if no value is explicitly provided, SQLite creates databases
** with page size SQLITE4_DEFAULT_PAGE_SIZE. However, based on certain
** device characteristics (sector-size and atomic write() support),
** SQLite may choose a larger value. This constant is the maximum value
** SQLite will choose on its own.
*/
#ifndef SQLITE4_MAX_DEFAULT_PAGE_SIZE
# define SQLITE4_MAX_DEFAULT_PAGE_SIZE 8192
#endif
#if SQLITE4_MAX_DEFAULT_PAGE_SIZE>SQLITE4_MAX_PAGE_SIZE
# undef SQLITE4_MAX_DEFAULT_PAGE_SIZE
# define SQLITE4_MAX_DEFAULT_PAGE_SIZE SQLITE4_MAX_PAGE_SIZE
#endif


/*
** Maximum number of pages in one database file.
**
** This is really just the default value for the max_page_count pragma.
** This value can be lowered (or raised) at run-time using that the
** max_page_count macro.
*/
#ifndef SQLITE4_MAX_PAGE_COUNT
# define SQLITE4_MAX_PAGE_COUNT 1073741823
#endif

/*
** Maximum length (in bytes) of the pattern in a LIKE or GLOB
** operator.
*/
#ifndef SQLITE4_MAX_LIKE_PATTERN_LENGTH
# define SQLITE4_MAX_LIKE_PATTERN_LENGTH 50000
#endif

/*
** Maximum depth of recursion for triggers.
**
** A value of 1 means that a trigger program will not be able to itself
** fire any triggers. A value of 0 means that no trigger programs at all 
** may be executed.
*/
#ifndef SQLITE4_MAX_TRIGGER_DEPTH
# define SQLITE4_MAX_TRIGGER_DEPTH 1000
#endif

/************** End of sqliteLimit.h *****************************************/
/************** Continuing where we left off in sqliteInt.h ******************/

/* Disable nuisance warnings on Borland compilers */
#if defined(__BORLANDC__)
#pragma warn -rch /* unreachable code */
#pragma warn -ccc /* Condition is always true or false */
#pragma warn -aus /* Assigned value is never used */
#pragma warn -csu /* Comparing signed and unsigned */
#pragma warn -spa /* Suspicious pointer arithmetic */
#endif

/* Needed for various definitions... */
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif

/*
** Include standard header files as necessary
*/
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif

/*
** The following macros are used to cast pointers to integers and
** integers to pointers.  The way you do this varies from one compiler
** to the next, so we have developed the following set of #if statements
** to generate appropriate macros for a wide range of compilers.
**
** The correct "ANSI" way to do this is to use the intptr_t type. 
** Unfortunately, that typedef is not available on all compilers, or
** if it is available, it requires an #include of specific headers
** that vary from one machine to the next.
**
** Ticket #3860:  The llvm-gcc-4.2 compiler from Apple chokes on
** the ((void*)&((char*)0)[X]) construct.  But MSVC chokes on ((void*)(X)).
** So we have to define the macros in different ways depending on the
** compiler.
*/
#if defined(__PTRDIFF_TYPE__)  /* This case should work for GCC */
# define SQLITE4_INT_TO_PTR(X)  ((void*)(__PTRDIFF_TYPE__)(X))
# define SQLITE4_PTR_TO_INT(X)  ((int)(__PTRDIFF_TYPE__)(X))
#elif !defined(__GNUC__)       /* Works for compilers other than LLVM */
# define SQLITE4_INT_TO_PTR(X)  ((void*)&((char*)0)[X])
# define SQLITE4_PTR_TO_INT(X)  ((int)(((char*)X)-(char*)0))
#elif defined(HAVE_STDINT_H)   /* Use this case if we have ANSI headers */
# define SQLITE4_INT_TO_PTR(X)  ((void*)(intptr_t)(X))
# define SQLITE4_PTR_TO_INT(X)  ((int)(intptr_t)(X))
#else                          /* Generates a warning - but it always works */
# define SQLITE4_INT_TO_PTR(X)  ((void*)(X))
# define SQLITE4_PTR_TO_INT(X)  ((int)(X))
#endif

/*
** The SQLITE4_THREADSAFE macro must be defined as 0, 1, or 2.
** 0 means mutexes are permanently disable and the library is never
** threadsafe.  1 means the library is serialized which is the highest
** level of threadsafety.  2 means the libary is multithreaded - multiple
** threads can use SQLite as long as no two threads try to use the same
** database connection at the same time.
**
** Older versions of SQLite used an optional THREADSAFE macro.
** We support that for legacy.
*/
#if !defined(SQLITE4_THREADSAFE)
#if defined(THREADSAFE)
# define SQLITE4_THREADSAFE THREADSAFE
#else
# define SQLITE4_THREADSAFE 1 /* IMP: R-07272-22309 */
#endif
#endif

/*
** Powersafe overwrite is on by default.  But can be turned off using
** the -DSQLITE4_POWERSAFE_OVERWRITE=0 command-line option.
*/
#ifndef SQLITE4_POWERSAFE_OVERWRITE
# define SQLITE4_POWERSAFE_OVERWRITE 1
#endif

/*
** The SQLITE4_DEFAULT_MEMSTATUS macro must be defined as either 0 or 1.
** It determines whether or not the features related to 
** SQLITE4_CONFIG_MEMSTATUS are available by default or not. This value can
** be overridden at runtime using the sqlite4_config() API.
*/
#if !defined(SQLITE4_DEFAULT_MEMSTATUS)
# define SQLITE4_DEFAULT_MEMSTATUS 1
#endif

/*
** Exactly one of the following macros must be defined in order to
** specify which memory allocation subsystem to use.
**
**     SQLITE4_SYSTEM_MALLOC          // Use normal system malloc()
**     SQLITE4_WIN32_MALLOC           // Use Win32 native heap API
**     SQLITE4_MEMDEBUG               // Debugging version of system malloc()
**
** On Windows, if the SQLITE4_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 three.)
**
** If none of the above are defined, then set SQLITE4_SYSTEM_MALLOC as
** the default.
*/
#if defined(SQLITE4_SYSTEM_MALLOC)+defined(SQLITE4_WIN32_MALLOC)\
   +defined(SQLITE4_MEMDEBUG)>1
# error "At most one of the following compile-time configuration options\
 is allows: SQLITE4_SYSTEM_MALLOC, SQLITE4_WIN32_MALLOC, SQLITE4_MEMDEBUG"
#endif
#if defined(SQLITE4_SYSTEM_MALLOC)+defined(SQLITE4_WIN32_MALLOC)\
   +defined(SQLITE4_MEMDEBUG)==0
# define SQLITE4_SYSTEM_MALLOC 1
#endif

/*
** If SQLITE4_MALLOC_SOFT_LIMIT is not zero, then try to keep the
** sizes of memory allocations below this value where possible.
*/
#if !defined(SQLITE4_MALLOC_SOFT_LIMIT)
# define SQLITE4_MALLOC_SOFT_LIMIT 1024
#endif

/*
** We need to define _XOPEN_SOURCE as follows in order to enable
** recursive mutexes on most Unix systems.  But Mac OS X is different.
** The _XOPEN_SOURCE define causes problems for Mac OS X we are told,
** so it is omitted there.  See ticket #2673.
**
** Later we learn that _XOPEN_SOURCE is poorly or incorrectly
** implemented on some systems.  So we avoid defining it at all
** if it is already defined or if it is unneeded because we are
** not doing a threadsafe build.  Ticket #2681.
**
** See also ticket #2741.
*/
#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)\
     && SQLITE4_THREADSAFE
#  define _XOPEN_SOURCE 500  /* Needed to enable pthread recursive mutexes */
#endif

/*
** The TCL headers are only needed when compiling the TCL bindings.
*/
#if defined(SQLITE4_TCL) || defined(TCLSH)
# include <tcl.h>
#endif

/*
** Many people are failing to set -DNDEBUG=1 when compiling SQLite.
** Setting NDEBUG makes the code smaller and run faster.  So the following
** lines are added to automatically set NDEBUG unless the -DSQLITE4_DEBUG=1
** option is set.  Thus NDEBUG becomes an opt-in rather than an opt-out
** feature.
*/
#if !defined(NDEBUG) && !defined(SQLITE4_DEBUG) 
# define NDEBUG 1
#endif

/*
** The testcase() macro is used to aid in coverage testing.  When 
** doing coverage testing, the condition inside the argument to
** testcase() must be evaluated both true and false in order to
** get full branch coverage.  The testcase() macro is inserted
** to help ensure adequate test coverage in places where simple
** condition/decision coverage is inadequate.  For example, testcase()
** can be used to make sure boundary values are tested.  For
** bitmask tests, testcase() can be used to make sure each bit
** is significant and used at least once.  On switch statements
** where multiple cases go to the same block of code, testcase()
** can insure that all cases are evaluated.
**
*/
#ifdef SQLITE4_COVERAGE_TEST
SQLITE4_PRIVATE   void sqlite4Coverage(int);
# define testcase(X)  if( X ){ sqlite4Coverage(__LINE__); }
#else
# define testcase(X)
#endif

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

/*
** Sometimes we need a small amount of code such as a variable initialization
** to setup for a later assert() statement.  We do not want this code to
** appear when assert() is disabled.  The following macro is therefore
** used to contain that setup code.  The "VVA" acronym stands for
** "Verification, Validation, and Accreditation".  In other words, the
** code within VVA_ONLY() will only run during verification processes.
*/
#ifndef NDEBUG
# define VVA_ONLY(X)  X
#else
# define VVA_ONLY(X)
#endif

/*
** The ALWAYS and NEVER macros surround boolean expressions which 
** are intended to always be true or false, respectively.  Such
** expressions could be omitted from the code completely.  But they
** are included in a few cases in order to enhance the resilience
** of SQLite to unexpected behavior - to make the code "self-healing"
** or "ductile" rather than being "brittle" and crashing at the first
** hint of unplanned behavior.
**
** In other words, ALWAYS and NEVER are added for defensive code.
**
** When doing coverage testing ALWAYS and NEVER are hard-coded to
** be true and false so that the unreachable code then specify will
** not be counted as untested code.
*/
#if defined(SQLITE4_COVERAGE_TEST)
# define ALWAYS(X)      (1)
# define NEVER(X)       (0)
#elif !defined(NDEBUG)
# define ALWAYS(X)      ((X)?1:(assert(0),0))
# define NEVER(X)       ((X)?(assert(0),1):0)
#else
# define ALWAYS(X)      (X)
# define NEVER(X)       (X)
#endif

/************** Include sqlite4.h in the middle of sqliteInt.h ***************/
/************** Begin file sqlite4.h *****************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This header file defines the interface that the SQLite4 library
** presents to client programs.  If a C-function, structure, datatype,
** or constant definition does not appear in this file, then it is
** not a published API of SQLite, is subject to change without
** notice, and should not be referenced by programs that use SQLite.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
** the version number) and changes its name to "sqlite4.h" as
** part of the build process.
*/
#ifndef _SQLITE4_H_
#define _SQLITE4_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
*/
#if 0
extern "C" {
#endif


/*
** Add the ability to override 'extern'
*/
#ifndef SQLITE4_EXTERN
# define SQLITE4_EXTERN extern
#endif

#ifndef SQLITE4_API
# define SQLITE4_API
#endif


/*
** Ensure these symbols were not defined by some previous header file.
*/
#ifdef SQLITE4_VERSION
# undef SQLITE4_VERSION
#endif
#ifdef SQLITE4_VERSION_NUMBER
# undef SQLITE4_VERSION_NUMBER
#endif

/*
** CAPIREF: 64-Bit Integer Types
** KEYWORDS: sqlite4_int64 sqlite4_uint64
**
** Because there is no cross-platform way to specify 64-bit integer types
** SQLite includes typedefs for 64-bit signed and unsigned integers.
**
** ^The sqlite4_int64 and sqlite_int64 types can store integer values
** between -9223372036854775808 and +9223372036854775807 inclusive.  ^The
** sqlite4_uint64 and sqlite_uint64 types can store integer values 
** between 0 and +18446744073709551615 inclusive.
*/
#ifdef SQLITE4_INT64_TYPE
  typedef SQLITE4_INT64_TYPE sqlite4_int64_t;
  typedef unsigned SQLITE4_INT64_TYPE sqlite4_uint64_t;
#elif defined(_MSC_VER) || defined(__BORLANDC__)
  typedef __int64 sqlite4_int64_t;
  typedef unsigned __int64 sqlite4_uint64_t;
#else
  typedef long long int sqlite4_int64_t;
  typedef unsigned long long int sqlite4_uint64_t;
#endif
typedef sqlite4_int64_t sqlite4_int64;
typedef sqlite4_uint64_t sqlite4_uint64;

/*
** CAPIREF: String length type
**
** A type for measuring the length of the string.  Like size_t but
** does not require &lt;stddef.h&gt;
*/
typedef int sqlite4_size_t;
typedef struct sqlite4_kvstore sqlite4_kvstore;

/*
** CAPI4REF: Representation Of Numbers
**
** Every number in SQLite is represented in memory by an instance of
** the following object.
*/
typedef struct sqlite4_num sqlite4_num;
struct sqlite4_num {
  unsigned char sign;     /* Sign of the overall value */
  unsigned char approx;   /* True if the value is approximate */
  short e;                /* The exponent. */
  sqlite4_uint64 m;       /* The significant */
};

/*
** Available memory allocator object subtypes:
*/
typedef enum {
  SQLITE4_MM_SYSTEM = 1,     /* Use the system malloc() */
  SQLITE4_MM_ONESIZE = 2,    /* All allocations map to a fixed size */
  SQLITE4_MM_OVERFLOW = 3,   /* Two allocators. Use A first; failover to B */
  SQLITE4_MM_COMPACT = 4,    /* Like memsys3 from SQLite3 */
  SQLITE4_MM_ROBSON = 5,     /* Like memsys5 from SQLite3 */
  SQLITE4_MM_LINEAR = 6,     /* Allocate from a fixed buffer w/o free */
  SQLITE4_MM_BESPOKE = 7,    /* Caller-defined implementation */
  SQLITE4_MM_DEBUG,          /* Debugging memory allocator */
  SQLITE4_MM_STATS           /* Keep memory statistics */
} sqlite4_mm_type;

/*
** Base class for the memory allocator object.
**
** Implementations may extend this with additional
** fields specific to its own needs.  This needs to be public so that
** applications can supply their on customized memory allocators.
*/
typedef struct sqlite4_mm sqlite4_mm;
typedef struct sqlite4_mm_methods sqlite4_mm_methods;
struct sqlite4_mm {
  const struct sqlite4_mm_methods *pMethods;
};
struct sqlite4_mm_methods {
  int iVersion;
  void *(*xMalloc)(sqlite4_mm*, sqlite4_size_t);
  void *(*xRealloc)(sqlite4_mm*, void*, sqlite4_size_t);
  void (*xFree)(sqlite4_mm*, void*);
  sqlite4_size_t (*xMsize)(sqlite4_mm*, void*);
  int (*xMember)(sqlite4_mm*, const void*);
  void (*xBenign)(sqlite4_mm*, int);
  sqlite4_int64 (*xStat)(sqlite4_mm*, unsigned eType, unsigned bFlags);
  int (*xCtrl)(sqlite4_mm*, unsigned eType, va_list);
  void (*xFinal)(sqlite4_mm*);
};

/*
** Return a pointer to the default memory allocator, which is basically
** a wrapper around system malloc()/realloc()/free().
*/
SQLITE4_API sqlite4_mm *sqlite4_mm_default(void);

/*
** Allocate a new memory manager.  Return NULL if unable.
*/
SQLITE4_API sqlite4_mm *sqlite4_mm_new(sqlite4_mm_type, ...);

/*
** Free the sqlite4_mm object.
**
** All outstanding memory for the allocator must be freed prior to
** invoking this interface, or else the behavior is undefined.
*/
SQLITE4_API void sqlite4_mm_destroy(sqlite4_mm*);

/*
** Core memory allocation routines:
*/
SQLITE4_API void *sqlite4_mm_malloc(sqlite4_mm*, sqlite4_size_t);
SQLITE4_API void *sqlite4_mm_realloc(sqlite4_mm*, void*, sqlite4_size_t);
SQLITE4_API void sqlite4_mm_free(sqlite4_mm*, void*);

/*
** Return the size of a memory allocation.
**
** All memory allocators in SQLite4 must be able to report their size.
** When using system malloc() on system that lack the malloc_usable_size()
** routine or its equivalent, then the sqlite4_mm object allocates 8 extra
** bytes for each memory allocation and stores the allocation size in those
** initial 8 bytes.
*/
SQLITE4_API sqlite4_size_t sqlite4_mm_msize(sqlite4_mm*, void*);

/*
** Check to see if pOld is a memory allocation from pMM.  If it is, return
** 1.  If not, return 0.  If we cannot determine an answer, return -1.
**
** If pOld is not a valid memory allocation or is a memory allocation that
** has previously been freed, then the result of this routine is undefined.
*/
SQLITE4_API int sqlite4_mm_member(sqlite4_mm *pMM, const void *pOld);

/*
** Allowed values for the second parameter ("eType") to sqlite4_mm_stat().
*/
#define SQLITE4_MMSTAT_OUT        1
#define SQLITE4_MMSTAT_OUT_HW     2
#define SQLITE4_MMSTAT_UNITS      3
#define SQLITE4_MMSTAT_UNITS_HW   4
#define SQLITE4_MMSTAT_SIZE       5
#define SQLITE4_MMSTAT_SZFAULT    6
#define SQLITE4_MMSTAT_MEMFAULT   7
#define SQLITE4_MMSTAT_FAULT      8

/*
** Bits for the bit vector third parameter ("flags") to sqlite4_mm_type()
*/
#define SQLITE4_MMSTAT_RESET      0x01

/*
** Return statistics or status information about a memory allocator.
** Not all memory allocators provide all stat values.  Some memory
** allocators provides no states at all.  If a particular stat for
** a memory allocator is unavailable, then -1 is returned.
*/
SQLITE4_API sqlite4_int64 sqlite4_mm_stat(sqlite4_mm *pMM, int eType, unsigned flags);

/*
** Send a control message into a memory allocator.
*/
SQLITE4_API int sqlite4_mm_control(sqlite4_mm *pMM, int eType, ...);
SQLITE4_API int sqlite4_mm_control_va(sqlite4_mm *pMM, int eType, va_list ap);

/*
** Enable or disable benign failure mode.  Benign failure mode can be
** nested.  In benign failure mode, OOM errors do not necessarily propagate
** back out to the application but can be dealt with internally.  Memory
** allocations that occur in benign failure mode are considered "optional".
*/
SQLITE4_API void sqlite4_mm_benign_failures(sqlite4_mm*, int bEnable);

/*
** CAPIREF: Buffer Object
*/
typedef struct sqlite4_buffer sqlite4_buffer;
struct sqlite4_buffer {
  sqlite4_mm *pMM;
  void *p;
  sqlite4_size_t n;
};

SQLITE4_API void sqlite4_buffer_init(sqlite4_buffer *, sqlite4_mm *);
SQLITE4_API void sqlite4_buffer_clear(sqlite4_buffer *);
SQLITE4_API int sqlite4_buffer_resize(sqlite4_buffer *, sqlite4_size_t);
SQLITE4_API int sqlite4_buffer_append(sqlite4_buffer *, const void *, sqlite4_size_t);
SQLITE4_API int sqlite4_buffer_set(sqlite4_buffer *, const void *, sqlite4_size_t);

/*
** CAPIREF: Translate Text Encodings
**
** This API function is used to translate between utf-8 and utf-16 text
** encodings. 
**
** The translated output is stored in the sqlite4_buffer object indicated 
** by the first argument. If no error occurs, the value returned is a copy
** of the sqlite4_buffer.p value (a pointer to the blob of memory containing
** the actual translated data). Or, if an out-of-memory error occurs, the
** buffer is zeroed and a NULL pointer returned. 
**
** The input data is specified by the second and third arguments. The second
** is a pointer to the buffer containing the input text. If the third 
** parameter is non-negative, it is the size of the input buffer in bytes. 
** Otherwise, if the third parameter is a negative value, the input buffer
** is read up until the first nul-terminator character (codepoint 0).
**
** The required translation is specified by the fourth argument, which must
** be passed one of the SQLITE4_TRANSLATE_* constants.
*/
#define SQLITE4_TRANSLATE_UTF8_UTF16   1    /* utf-8 to native-endian utf-16 */
#define SQLITE4_TRANSLATE_UTF16_UTF8   2    /* native-endian utf-16 to utf-8 */
#define SQLITE4_TRANSLATE_UTF8_UTF16LE 3    /* utf-8 to little-endian utf-16 */
#define SQLITE4_TRANSLATE_UTF16LE_UTF8 4    /* native-endian utf-16 to utf-8 */
#define SQLITE4_TRANSLATE_UTF8_UTF16BE 5    /* utf-8 to big-endian utf-16 */
#define SQLITE4_TRANSLATE_UTF16BE_UTF8 6    /* native-endian utf-16 to utf-8 */
SQLITE4_API void *sqlite4_translate(sqlite4_buffer *, const void *p, int n, int eTrans);

/*
** CAPIREF: Run-time Environment Object
**
** An instance of the following object defines the run-time environment 
** for an SQLite4 database connection.  This object defines the interface
** to appropriate mutex routines, memory allocation routines, a
** pseudo-random number generator, real-time clock, and the key-value
** backend stores.
*/
typedef struct sqlite4_env sqlite4_env;

/*
** CAPIREF: Find the default run-time environment
**
** Return a pointer to the default run-time environment.
*/
SQLITE4_API sqlite4_env *sqlite4_env_default(void);

/*
** CAPIREF: Size of an sqlite4_env object
**
** Return the number of bytes of memory needed to hold an sqlite4_env
** object.  This number varies from one machine to another, and from
** one release of SQLite to another.
*/
SQLITE4_API int sqlite4_env_size(void);

/*
** CAPIREF: Configure a run-time environment
*/
SQLITE4_API int sqlite4_env_config(sqlite4_env*, int op, ...);

/*
** CAPIREF: Configuration options for sqlite4_env_config().
*/
#define SQLITE4_ENVCONFIG_INIT          1   /* size, template */
#define SQLITE4_ENVCONFIG_SINGLETHREAD  2   /* */
#define SQLITE4_ENVCONFIG_MULTITHREAD   3   /* */
#define SQLITE4_ENVCONFIG_SERIALIZED    4   /* */
#define SQLITE4_ENVCONFIG_MUTEX         5   /* sqlite4_mutex_methods* */
#define SQLITE4_ENVCONFIG_GETMUTEX      6   /* sqlite4_mutex_methods* */
#define SQLITE4_ENVCONFIG_SETMM         7   /* sqlite4_mm* */
#define SQLITE4_ENVCONFIG_GETMM         8   /* sqlite4_mm** */
#define SQLITE4_ENVCONFIG_MEMSTATUS     9   /* boolean */
#define SQLITE4_ENVCONFIG_LOOKASIDE    10   /* size, count */
#define SQLITE4_ENVCONFIG_LOG          11   /* xLog, pArg */
#define SQLITE4_ENVCONFIG_KVSTORE_PUSH 12   /* name, factory */
#define SQLITE4_ENVCONFIG_KVSTORE_POP  13   /* name */
#define SQLITE4_ENVCONFIG_KVSTORE_GET  14   /* name, *factory */

/*
** CAPIREF: Compile-Time Library Version Numbers
**
** ^(The [SQLITE4_VERSION] C preprocessor macro in the sqlite4.h header
** evaluates to a string literal that is the SQLite version in the
** format "X.Y.Z" where X is the major version number (always 3 for
** SQLite3) and Y is the minor version number and Z is the release number.)^
** ^(The [SQLITE4_VERSION_NUMBER] C preprocessor macro resolves to an integer
** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
** numbers used in [SQLITE4_VERSION].)^
** The SQLITE4_VERSION_NUMBER for any given release of SQLite will also
** be larger than the release from which it is derived.  Either Y will
** be held constant and Z will be incremented or else Y will be incremented
** and Z will be reset to zero.
**
** Since version 3.6.18, SQLite source code has been stored in the
** <a href="http://www.fossil-scm.org/">Fossil configuration management
** system</a>.  ^The SQLITE4_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
** within its configuration management system.  ^The SQLITE4_SOURCE_ID
** string contains the date and time of the check-in (UTC) and an SHA1
** hash of the entire source tree.
**
** See also: [sqlite4_libversion()],
** [sqlite4_libversion_number()], [sqlite4_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE4_VERSION        "4.0.0"
#define SQLITE4_VERSION_NUMBER 4000000
#define SQLITE4_SOURCE_ID      "2014-09-19 18:48:23 90c09b04513a40871a97d7aa4a7221af7489281c"

/*
** CAPIREF: Run-Time Library Version Numbers
** KEYWORDS: sqlite4_version, sqlite4_sourceid
**
** These interfaces provide the same information as the [SQLITE4_VERSION],
** [SQLITE4_VERSION_NUMBER], and [SQLITE4_SOURCE_ID] C preprocessor macros
** but are associated with the library instead of the header file.  ^(Cautious
** programmers might include assert() statements in their application to
** verify that values returned by these interfaces match the macros in
** the header, and thus insure that the application is
** compiled with matching library and header files.
**
** <blockquote><pre>
** assert( sqlite4_libversion_number()==SQLITE4_VERSION_NUMBER );
** assert( strcmp(sqlite4_sourceid(),SQLITE4_SOURCE_ID)==0 );
** assert( strcmp(sqlite4_libversion(),SQLITE4_VERSION)==0 );
** </pre></blockquote>)^
**
** ^The sqlite4_libversion() function returns a pointer to a string
** constant that contains the text of [SQLITE4_VERSION].  ^The
** sqlite4_libversion_number() function returns an integer equal to
** [SQLITE4_VERSION_NUMBER].  ^The sqlite4_sourceid() function returns 
** a pointer to a string constant whose value is the same as the 
** [SQLITE4_SOURCE_ID] C preprocessor macro.
**
** See also: [sqlite_version()] and [sqlite_source_id()].
*/
SQLITE4_API const char *sqlite4_libversion(void);
SQLITE4_API const char *sqlite4_sourceid(void);
SQLITE4_API int sqlite4_libversion_number(void);

/*
** CAPIREF: Run-Time Library Compilation Options Diagnostics
**
** ^The sqlite4_compileoption_used() function returns 0 or 1 
** indicating whether the specified option was defined at 
** compile time.  ^The SQLITE4_ prefix may be omitted from the 
** option name passed to sqlite4_compileoption_used().  
**
** ^The sqlite4_compileoption_get() function allows iterating
** over the list of options that were defined at compile time by
** returning the N-th compile time option string.  ^If N is out of range,
** sqlite4_compileoption_get() returns a NULL pointer.  ^The SQLITE4_ 
** prefix is omitted from any strings returned by 
** sqlite4_compileoption_get().
**
** ^Support for the diagnostic functions sqlite4_compileoption_used()
** and sqlite4_compileoption_get() may be omitted by specifying the 
** [SQLITE4_OMIT_COMPILEOPTION_DIAGS] option at compile time.
**
** See also: SQL functions [sqlite_compileoption_used()] and
** [sqlite_compileoption_get()] and the [compile_options pragma].
*/
#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS
SQLITE4_API int sqlite4_compileoption_used(const char *zOptName);
SQLITE4_API const char *sqlite4_compileoption_get(int N);
#endif

/*
** CAPIREF: Test To See If The Library Is Threadsafe
**
** ^The sqlite4_threadsafe(E) function returns zero if the [sqlite4_env]
** object is configured in such a way that it should only be used by a
** single thread at a time.  In other words, this routine returns zero
** if the environment is configured as [SQLITE4_ENVCONFIG_SINGLETHREAD].
**
** ^The sqlite4_threadsafe(E) function returns one if multiple
** [database connection] objects associated with E can be used at the
** same time in different threads, so long as no single [database connection]
** object is used by two or more threads at the same time.  This
** corresponds to [SQLITE4_ENVCONFIG_MULTITHREAD].
**
** ^The sqlite4_threadsafe(E) function returns two if the same
** [database connection] can be used at the same time from two or more
** separate threads.  This setting corresponds to 
** [SQLITE4_ENVCONFIG_SERIALIZED].
**
** Note that SQLite4 is always threadsafe in this sense: Two or more
** objects each associated with different [sqlite4_env] objects can
** always be used at the same time in separate threads.
*/
SQLITE4_API int sqlite4_threadsafe(sqlite4_env*);

/*
** CAPIREF: Database Connection Handle
** KEYWORDS: {database connection} {database connections}
**
** Each open SQLite database is represented by a pointer to an instance of
** the opaque structure named "sqlite4".  It is useful to think of an sqlite4
** pointer as an object.  The [sqlite4_open()]
** interface is its constructors, and [sqlite4_close()]
** is its destructor.  There are many other interfaces (such as
** [sqlite4_prepare], [sqlite4_create_function()], and
** [sqlite4_busy_timeout()] to name but three) that are methods on an
** sqlite4 object.
*/
typedef struct sqlite4 sqlite4;

/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point.
*/
#ifdef SQLITE4_OMIT_FLOATING_POINT
# define double sqlite4_int64
#endif

/*
** CAPIREF: Closing A Database Connection
**
** ^The sqlite4_close() routine is the destructor for the [sqlite4] object.
** ^Calls to sqlite4_close() return SQLITE4_OK if the [sqlite4] object is
** successfully destroyed and all associated resources are deallocated.
**
** Applications must [sqlite4_finalize | finalize] all [prepared statements]
** and [sqlite4_blob_close | close] all [BLOB handles] associated with
** the [sqlite4] object prior to attempting to close the object.  ^If
** sqlite4_close() is called on a [database connection] that still has
** outstanding [prepared statements] or [BLOB handles], then it returns
** SQLITE4_BUSY.
**
** ^If [sqlite4_close()] is invoked while a transaction is open,
** the transaction is automatically rolled back.
**
** The C parameter to [sqlite4_close(C,F)] must be either a NULL
** pointer or an [sqlite4] object pointer obtained
** from [sqlite4_open()] and not previously closed.
** ^Calling sqlite4_close() with a NULL pointer argument is a 
** harmless no-op.
**
** The second parameter passed to sqlite4_close() is currently unused. It
** is reserved for future functionality.
*/
SQLITE4_API int sqlite4_close(sqlite4 *, unsigned int flags);

/*
** CAPIREF: Dynamically Typed Value Object
** KEYWORDS: {protected sqlite4_value} {unprotected sqlite4_value}
**
** SQLite uses the sqlite4_value object to represent all values
** that can be stored in a database table. SQLite uses dynamic typing
** for the values it stores.  ^Values stored in sqlite4_value objects
** can be integers, floating point values, strings, BLOBs, or NULL.
**
** An sqlite4_value object may be either "protected" or "unprotected".
** Some interfaces require a protected sqlite4_value.  Other interfaces
** will accept either a protected or an unprotected sqlite4_value.
** Every interface that accepts sqlite4_value arguments specifies
** whether or not it requires a protected sqlite4_value.
**
** The terms "protected" and "unprotected" refer to whether or not
** a mutex is held.  An internal mutex is held for a protected
** sqlite4_value object but no mutex is held for an unprotected
** sqlite4_value object.  If SQLite is compiled to be single-threaded
** (with [SQLITE4_THREADSAFE=0] and with [sqlite4_threadsafe()] returning 0)
** or if SQLite is run in one of reduced mutex modes 
** [SQLITE4_CONFIG_SINGLETHREAD] or [SQLITE4_CONFIG_MULTITHREAD]
** then there is no distinction between protected and unprotected
** sqlite4_value objects and they can be used interchangeably.  However,
** for maximum code portability it is recommended that applications
** still make the distinction between protected and unprotected
** sqlite4_value objects even when not strictly required.
**
** ^The sqlite4_value objects that are passed as parameters into the
** implementation of [application-defined SQL functions] are protected.
** ^The sqlite4_value object returned by
** [sqlite4_column_value()] is unprotected.
** Unprotected sqlite4_value objects may only be used with
** [sqlite4_result_value()] and [sqlite4_bind_value()].
** The [sqlite4_value_blob | sqlite4_value_type()] family of
** interfaces require protected sqlite4_value objects.
*/
typedef struct Mem sqlite4_value;

/*
** CAPIREF: One-Step Query Execution Interface
**
** The sqlite4_exec() interface is a convenience wrapper around
** [sqlite4_prepare()], [sqlite4_step()], and [sqlite4_finalize()],
** that allows an application to run multiple statements of SQL
** without having to use a lot of C code. 
**
** ^The sqlite4_exec() interface runs zero or more UTF-8 encoded,
** semicolon-separated SQL statements passed into its 2nd argument,
** in the context of the [database connection] passed in as its 1st
** argument.  ^If the callback function of the 3rd argument to
** sqlite4_exec() is not NULL, then it is invoked for each result row
** coming out of the evaluated SQL statements.  ^The 4th argument to
** sqlite4_exec() is relayed through to the 1st argument of each
** callback invocation.  ^If the callback pointer to sqlite4_exec()
** is NULL, then no callback is ever invoked and result rows are
** ignored.
**
** ^If an error occurs while evaluating the SQL statements passed into
** sqlite4_exec(), then execution of the current statement stops, an
** error code is returned to the user and no subsequent statements are 
** executed.
**
** ^If an sqlite4_exec() callback returns non-zero, the sqlite4_exec()
** routine returns SQLITE4_ABORT without invoking the callback again and
** without running any subsequent SQL statements.
**
** ^The 2nd argument to the sqlite4_exec() callback function is the
** number of columns in the result.  ^The 3rd argument to the sqlite4_exec()
** callback is an array of pointers to protected sqlite4_value objects 
** containing the values for each column of the current row. 
** ^The 4th argument to the sqlite4_exec() callback is an array of pointers 
** to strings where each entry represents the name of corresponding result 
** column as obtained from [sqlite4_column_name()].
**
** ^If the 2nd parameter to sqlite4_exec() is a NULL pointer, a pointer
** to an empty string, or a pointer that contains only whitespace and/or 
** SQL comments, then no SQL statements are evaluated and the database
** is not changed.
**
** Restrictions:
**
** <ul>
** <li> The application must insure that the 1st parameter to sqlite4_exec()
**      is a valid and open [database connection].
** <li> The application must not close [database connection] specified by
**      the 1st parameter to sqlite4_exec() while sqlite4_exec() is running.
** <li> The application must not modify the SQL statement text passed into
**      the 2nd parameter of sqlite4_exec() while sqlite4_exec() is running.
** </ul>
*/
SQLITE4_API int sqlite4_exec(
  sqlite4 *,                      /* An open database */
  const char *zSql,               /* SQL to be evaluated */
  int (*)(void*,int,sqlite4_value**,const char**),    /* Callback function */
  void *                          /* Context for callback */
);

/*
** CAPIREF: Result Codes
** KEYWORDS: SQLITE4_OK {error code} {error codes}
** KEYWORDS: {result code} {result codes}
**
** Many SQLite functions return an integer result code from the set shown
** here in order to indicate success or failure.
**
** New error codes may be added in future versions of SQLite.
**
** See also: [SQLITE4_IOERR_READ | extended result codes],
** [sqlite4_vtab_on_conflict()] [SQLITE4_ROLLBACK | result codes].
*/
#define SQLITE4_OK           0   /* Successful result */
#define SQLITE4_ERROR        1   /* SQL error or missing database */
#define SQLITE4_INTERNAL     2   /* Internal logic error in SQLite */
#define SQLITE4_PERM         3   /* Access permission denied */
#define SQLITE4_ABORT        4   /* Callback routine requested an abort */
#define SQLITE4_BUSY         5   /* The database file is locked */
#define SQLITE4_LOCKED       6   /* A table in the database is locked */
#define SQLITE4_NOMEM        7   /* A malloc() failed */
#define SQLITE4_READONLY     8   /* Attempt to write a readonly database */
#define SQLITE4_INTERRUPT    9   /* Stopped terminated by sqlite4_interrupt()*/
#define SQLITE4_IOERR       10   /* Some kind of disk I/O error occurred */
#define SQLITE4_CORRUPT     11   /* The database disk image is malformed */
#define SQLITE4_NOTFOUND    12   /* Unknown opcode in sqlite4_file_control() */
#define SQLITE4_FULL        13   /* Insertion failed because database is full */
#define SQLITE4_CANTOPEN    14   /* Unable to open the database file */
#define SQLITE4_PROTOCOL    15   /* Database lock protocol error */
#define SQLITE4_EMPTY       16   /* Database is empty */
#define SQLITE4_SCHEMA      17   /* The database schema changed */
#define SQLITE4_TOOBIG      18   /* String or BLOB exceeds size limit */
#define SQLITE4_CONSTRAINT  19   /* Abort due to constraint violation */
#define SQLITE4_MISMATCH    20   /* Data type mismatch */
#define SQLITE4_MISUSE      21   /* Library used incorrectly */
#define SQLITE4_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE4_AUTH        23   /* Authorization denied */
#define SQLITE4_FORMAT      24   /* Auxiliary database format error */
#define SQLITE4_RANGE       25   /* 2nd param to sqlite4_bind out of range */
#define SQLITE4_NOTADB      26   /* File opened that is not a database file */
#define SQLITE4_NOTICE      27   /* Notifications from sqlite4_log() */
#define SQLITE4_WARNING     28   /* Warnings from sqlite4_log() */
#define SQLITE4_ROW         100  /* sqlite4_step() has another row ready */
#define SQLITE4_DONE        101  /* sqlite4_step() has finished executing */
#define SQLITE4_INEXACT     102  /* xSeek method of storage finds nearby ans */

/*
** CAPIREF: Extended Result Codes
** KEYWORDS: {extended error code} {extended error codes}
** KEYWORDS: {extended result code} {extended result codes}
**
** In its default configuration, SQLite API routines return one of 26 integer
** [SQLITE4_OK | result codes].  However, experience has shown that many of
** these result codes are too coarse-grained.  They do not provide as
** much information about problems as programmers might like.  In an effort to
** address this, newer versions of SQLite (version 3.3.8 and later) include
** support for additional result codes that provide more detailed information
** about errors. The extended result codes are enabled or disabled
** on a per database connection basis using the
** [sqlite4_extended_result_codes()] API.
**
** Some of the available extended result codes are listed here.
** One may expect the number of extended result codes will be expand
** over time.  Software that uses extended result codes should expect
** to see new result codes in future releases of SQLite.
**
** The SQLITE4_OK result code will never be extended.  It will always
** be exactly zero.
*/
#define SQLITE4_IOERR_READ              (SQLITE4_IOERR | (1<<8))
#define SQLITE4_IOERR_SHORT_READ        (SQLITE4_IOERR | (2<<8))
#define SQLITE4_IOERR_WRITE             (SQLITE4_IOERR | (3<<8))
#define SQLITE4_IOERR_FSYNC             (SQLITE4_IOERR | (4<<8))
#define SQLITE4_IOERR_DIR_FSYNC         (SQLITE4_IOERR | (5<<8))
#define SQLITE4_IOERR_TRUNCATE          (SQLITE4_IOERR | (6<<8))
#define SQLITE4_IOERR_FSTAT             (SQLITE4_IOERR | (7<<8))
#define SQLITE4_IOERR_UNLOCK            (SQLITE4_IOERR | (8<<8))
#define SQLITE4_IOERR_RDLOCK            (SQLITE4_IOERR | (9<<8))
#define SQLITE4_IOERR_DELETE            (SQLITE4_IOERR | (10<<8))
#define SQLITE4_IOERR_BLOCKED           (SQLITE4_IOERR | (11<<8))
#define SQLITE4_IOERR_NOMEM             (SQLITE4_IOERR | (12<<8))
#define SQLITE4_IOERR_ACCESS            (SQLITE4_IOERR | (13<<8))
#define SQLITE4_IOERR_CHECKRESERVEDLOCK (SQLITE4_IOERR | (14<<8))
#define SQLITE4_IOERR_LOCK              (SQLITE4_IOERR | (15<<8))
#define SQLITE4_IOERR_CLOSE             (SQLITE4_IOERR | (16<<8))
#define SQLITE4_IOERR_DIR_CLOSE         (SQLITE4_IOERR | (17<<8))
#define SQLITE4_IOERR_SHMOPEN           (SQLITE4_IOERR | (18<<8))
#define SQLITE4_IOERR_SHMSIZE           (SQLITE4_IOERR | (19<<8))
#define SQLITE4_IOERR_SHMLOCK           (SQLITE4_IOERR | (20<<8))
#define SQLITE4_IOERR_SHMMAP            (SQLITE4_IOERR | (21<<8))
#define SQLITE4_IOERR_SEEK              (SQLITE4_IOERR | (22<<8))
#define SQLITE4_LOCKED_SHAREDCACHE      (SQLITE4_LOCKED |  (1<<8))
#define SQLITE4_BUSY_RECOVERY           (SQLITE4_BUSY   |  (1<<8))
#define SQLITE4_CANTOPEN_NOTEMPDIR      (SQLITE4_CANTOPEN | (1<<8))
#define SQLITE4_CORRUPT_VTAB            (SQLITE4_CORRUPT | (1<<8))
#define SQLITE4_READONLY_RECOVERY       (SQLITE4_READONLY | (1<<8))
#define SQLITE4_READONLY_CANTLOCK       (SQLITE4_READONLY | (2<<8))
#define SQLITE4_WARNING_AUTOINDEX       (SQLITE4_WARNING | (1<<8))

/*
** CAPIREF: Flags For File Open Operations
**
** These bit values are intended for use as options in the
** [sqlite4_open()] interface
*/
#define SQLITE4_OPEN_READONLY         0x00000001  /* Ok for sqlite4_open() */
#define SQLITE4_OPEN_READWRITE        0x00000002  /* Ok for sqlite4_open() */
#define SQLITE4_OPEN_CREATE           0x00000004  /* Ok for sqlite4_open() */

/* NB:  The above must not overlap with the SQLITE4_KVOPEN_xxxxx flags
** defined below */


/*
** CAPIREF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite4_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks
** at the internal representation of an [sqlite4_mutex].  It only
** deals with pointers to the [sqlite4_mutex] object.
**
** Mutexes are created using [sqlite4_mutex_alloc()].
*/
typedef struct sqlite4_mutex sqlite4_mutex;
struct sqlite4_mutex {
  struct sqlite4_mutex_methods *pMutexMethods;
  /* Subclasses will typically add additional fields */
};

/*
** CAPIREF: Initialize An SQLite Environment
**
** ^The sqlite4_initialize(A) routine initializes an sqlite4_env object A.
** ^The sqlite4_shutdown(A) routine
** deallocates any resources that were allocated by sqlite4_initialize(A).
** A parameter value of NULL means to use the default environment.
** All environment objects are required to be initialized before use
** (even the default environment).
**
** A call to sqlite4_initialize(A) is an "effective" call if it is
** the first time sqlite4_initialize(A) is invoked during the lifetime of
** A, or if it is the first time sqlite4_initialize(A) is invoked
** following a call to sqlite4_shutdown(A).  ^(Only an effective call
** of sqlite4_initialize(A) does any initialization or A.  All other calls
** are harmless no-ops.)^
**
** A call to sqlite4_shutdown(A) is an "effective" call if it is the first
** call to sqlite4_shutdown(A) since the last sqlite4_initialize(A).  ^(Only
** an effective call to sqlite4_shutdown(A) does any deinitialization.
** All other valid calls to sqlite4_shutdown(A) are harmless no-ops.)^ Like
** sqlite4_initialize(), sqlite4_shutdown() accepts a NULL parameter to mean
** the default environment.
**
** The sqlite4_initialize(A) interface is threadsafe, but sqlite4_shutdown(A)
** is not.  The sqlite4_shutdown(A) interface must only be called from a
** single thread.  All open [database connections] must be closed and all
** other SQLite resources must be deallocated prior to invoking
** sqlite4_shutdown(A).
**
** ^The sqlite4_initialize(A) routine returns [SQLITE4_OK] on success.
** ^If for some reason, sqlite4_initialize(A) is unable to initialize
** the sqlite4_env object A (perhaps it is unable to allocate a needed
** resource such as a mutex) it returns an [error code] other than [SQLITE4_OK].
**
** ^The sqlite4_initialize() routine is called internally by many other
** SQLite interfaces so that an application usually does not need to
** invoke sqlite4_initialize() directly.  For example, [sqlite4_open()]
** calls sqlite4_initialize() so the SQLite library will be automatically
** initialized when [sqlite4_open()] is called if it has not be initialized
** already.  ^However, if SQLite is compiled with the [SQLITE4_OMIT_AUTOINIT]
** compile-time option, then the automatic calls to sqlite4_initialize()
** are omitted and the application must call sqlite4_initialize() directly
** prior to using any other SQLite interface.  For maximum portability,
** it is recommended that applications always invoke sqlite4_initialize()
** directly prior to using any other SQLite interface.  Future releases
** of SQLite may require this.  In other words, the behavior exhibited
** when SQLite is compiled with [SQLITE4_OMIT_AUTOINIT] might become the
** default behavior in some future release of SQLite.
*/
SQLITE4_API int sqlite4_initialize(sqlite4_env*);
SQLITE4_API int sqlite4_shutdown(sqlite4_env*);

/*
** CAPIREF: Configure database connections
**
** The sqlite4_db_config() interface is used to make configuration
** changes to a [database connection].  The interface is similar to
** [sqlite4_env_config()] except that the changes apply to a single
** [database connection] (specified in the first argument).
**
** The second argument to sqlite4_db_config(D,V,...)  is the
** [SQLITE4_DBCONFIG_LOOKASIDE | configuration verb] - an integer code 
** that indicates what aspect of the [database connection] is being configured.
** Subsequent arguments vary depending on the configuration verb.
**
** ^Calls to sqlite4_db_config() return SQLITE4_OK if and only if
** the call is considered successful.
*/
SQLITE4_API int sqlite4_db_config(sqlite4*, int op, ...);

/*
** CAPIREF: Run-time environment of a database connection
**
** Return the sqlite4_env object to which the database connection
** belongs.
*/
SQLITE4_API sqlite4_env *sqlite4_db_env(sqlite4*);

/*
** CAPIREF: Database Connection Configuration Options
**
** These constants are the available integer configuration options that
** can be passed as the second argument to the [sqlite4_db_config()] interface.
**
** New configuration options may be added in future releases of SQLite.
** Existing configuration options might be discontinued.  Applications
** should check the return code from [sqlite4_db_config()] to make sure that
** the call worked.  ^The [sqlite4_db_config()] interface will return a
** non-zero [error code] if a discontinued or unsupported configuration option
** is invoked.
**
** <dl>
** <dt>SQLITE4_DBCONFIG_LOOKASIDE</dt>
** <dd> ^This option takes three additional arguments that determine the 
** [lookaside memory allocator] configuration for the [database connection].
** ^The first argument (the third parameter to [sqlite4_db_config()] is a
** pointer to a memory buffer to use for lookaside memory.
** ^The first argument after the SQLITE4_DBCONFIG_LOOKASIDE verb
** may be NULL in which case SQLite will allocate the
** lookaside buffer itself using [sqlite4_malloc()]. ^The second argument is the
** size of each lookaside buffer slot.  ^The third argument is the number of
** slots.  The size of the buffer in the first argument must be greater than
** or equal to the product of the second and third arguments.  The buffer
** must be aligned to an 8-byte boundary.  ^If the second argument to
** SQLITE4_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
** rounded down to the next smaller multiple of 8.  ^(The lookaside memory
** configuration for a database connection can only be changed when that
** connection is not currently using lookaside memory, or in other words
** when the "current value" returned by
** [sqlite4_db_status](D,[SQLITE4_CONFIG_LOOKASIDE],...) is zero.
** Any attempt to change the lookaside memory configuration when lookaside
** memory is in use leaves the configuration unchanged and returns 
** [SQLITE4_BUSY].)^</dd>
**
** <dt>SQLITE4_DBCONFIG_ENABLE_FKEY</dt>
** <dd> ^This option is used to enable or disable the enforcement of
** [foreign key constraints].  There should be two additional arguments.
** The first argument is an integer which is 0 to disable FK enforcement,
** positive to enable FK enforcement or negative to leave FK enforcement
** unchanged.  The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether FK enforcement is off or on
** following this call.  The second parameter may be a NULL pointer, in
** which case the FK enforcement setting is not reported back. </dd>
**
** <dt>SQLITE4_DBCONFIG_ENABLE_TRIGGER</dt>
** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
** There should be two additional arguments.
** The first argument is an integer which is 0 to disable triggers,
** positive to enable triggers or negative to leave the setting unchanged.
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call.  The second parameter may be a NULL pointer, in
** which case the trigger setting is not reported back. </dd>
**
** </dl>
*/
#define SQLITE4_DBCONFIG_LOOKASIDE       1001  /* void* int int */
#define SQLITE4_DBCONFIG_ENABLE_FKEY     1002  /* int int* */
#define SQLITE4_DBCONFIG_ENABLE_TRIGGER  1003  /* int int* */


/*
** CAPIREF: Count The Number Of Rows Modified
**
** ^This function returns the number of database rows that were changed
** or inserted or deleted by the most recently completed SQL statement
** on the [database connection] specified by the first parameter.
** ^(Only changes that are directly specified by the [INSERT], [UPDATE],
** or [DELETE] statement are counted.  Auxiliary changes caused by
** triggers or [foreign key actions] are not counted.)^ Use the
** [sqlite4_total_changes()] function to find the total number of changes
** including changes caused by triggers and foreign key actions.
**
** ^Changes to a view that are simulated by an [INSTEAD OF trigger]
** are not counted.  Only real table changes are counted.
**
** ^(A "row change" is a change to a single row of a single table
** caused by an INSERT, DELETE, or UPDATE statement.  Rows that
** are changed as side effects of [REPLACE] constraint resolution,
** rollback, ABORT processing, [DROP TABLE], or by any other
** mechanisms do not count as direct row changes.)^
**
** A "trigger context" is a scope of execution that begins and
** ends with the script of a [CREATE TRIGGER | trigger]. 
** Most SQL statements are
** evaluated outside of any trigger.  This is the "top level"
** trigger context.  If a trigger fires from the top level, a
** new trigger context is entered for the duration of that one
** trigger.  Subtriggers create subcontexts for their duration.
**
** ^Calling [sqlite4_exec()] or [sqlite4_step()] recursively does
** not create a new trigger context.
**
** ^This function returns the number of direct row changes in the
** most recent INSERT, UPDATE, or DELETE statement within the same
** trigger context.
**
** ^Thus, when called from the top level, this function returns the
** number of changes in the most recent INSERT, UPDATE, or DELETE
** that also occurred at the top level.  ^(Within the body of a trigger,
** the sqlite4_changes() interface can be called to find the number of
** changes in the most recently completed INSERT, UPDATE, or DELETE
** statement within the body of the same trigger.
** However, the number returned does not include changes
** caused by subtriggers since those have their own context.)^
**
** See also the [sqlite4_total_changes()] interface, the
** [count_changes pragma], and the [changes() SQL function].
**
** If a separate thread makes changes on the same database connection
** while [sqlite4_changes()] is running then the value returned
** is unpredictable and not meaningful.
*/
SQLITE4_API int sqlite4_changes(sqlite4*);

/*
** CAPIREF: Total Number Of Rows Modified
**
** ^This function returns the number of row changes caused by [INSERT],
** [UPDATE] or [DELETE] statements since the [database connection] was opened.
** ^(The count returned by sqlite4_total_changes() includes all changes
** from all [CREATE TRIGGER | trigger] contexts and changes made by
** [foreign key actions]. However,
** the count does not include changes used to implement [REPLACE] constraints,
** do rollbacks or ABORT processing, or [DROP TABLE] processing.  The
** count does not include rows of views that fire an [INSTEAD OF trigger],
** though if the INSTEAD OF trigger makes changes of its own, those changes 
** are counted.)^
** ^The sqlite4_total_changes() function counts the changes as soon as
** the statement that makes them is completed (when the statement handle
** is passed to [sqlite4_reset()] or [sqlite4_finalize()]).
**
** See also the [sqlite4_changes()] interface, the
** [count_changes pragma], and the [total_changes() SQL function].
**
** If a separate thread makes changes on the same database connection
** while [sqlite4_total_changes()] is running then the value
** returned is unpredictable and not meaningful.
*/
SQLITE4_API int sqlite4_total_changes(sqlite4*);

/*
** CAPIREF: Interrupt A Long-Running Query
**
** ^This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically
** called in response to a user action such as pressing "Cancel"
** or Ctrl-C where the user wants a long query operation to halt
** immediately.
**
** ^It is safe to call this routine from a thread different from the
** thread that is currently running the database operation.  But it
** is not safe to call this routine with a [database connection] that
** is closed or might close before sqlite4_interrupt() returns.
**
** ^If an SQL operation is very nearly finished at the time when
** sqlite4_interrupt() is called, then it might not have an opportunity
** to be interrupted and might continue to completion.
**
** ^An SQL operation that is interrupted will return [SQLITE4_INTERRUPT].
** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE
** that is inside an explicit transaction, then the entire transaction
** will be rolled back automatically.
**
** ^The sqlite4_interrupt(D) call is in effect until all currently running
** SQL statements on [database connection] D complete.  ^Any new SQL statements
** that are started after the sqlite4_interrupt() call and before the 
** running statements reaches zero are interrupted as if they had been
** running prior to the sqlite4_interrupt() call.  ^New SQL statements
** that are started after the running statement count reaches zero are
** not effected by the sqlite4_interrupt().
** ^A call to sqlite4_interrupt(D) that occurs when there are no running
** SQL statements is a no-op and has no effect on SQL statements
** that are started after the sqlite4_interrupt() call returns.
**
** If the database connection closes while [sqlite4_interrupt()]
** is running then bad things will likely happen.
*/
SQLITE4_API void sqlite4_interrupt(sqlite4*);

/*
** CAPIREF: Determine If An SQL Statement Is Complete
**
** This routine is useful when processing command-line input to determine 
** if the currently entered text appears to form a complete SQL statement 
** or if additional input is needed before sending the text into
** SQLite for parsing.  ^This routine returns 1 if the input string
** appears to be a complete SQL statement, or 0 otherwise. ^A statement 
** is judged to be complete if it ends with a semicolon token and is not 
** a prefix of a well-formed CREATE TRIGGER statement. ^Semicolons that 
** are embedded within string literals or quoted identifier names or 
** comments are not independent tokens (they are part of the token in which 
** they are embedded) and thus do not count as a statement terminator. 
** ^Whitespace and comments that follow the final semicolon are ignored.
**
** ^This routine does not parse the SQL statements thus will not detect 
** syntactically incorrect SQL.
**
** The argument passed to [sqlite4_complete()] must be a pointer to a 
** zero-terminated UTF-8 string.
*/
SQLITE4_API int sqlite4_complete(const char *sql);


/*
** CAPIREF: Formatted String Printing Functions
**
** These routines are work-alikes of the "printf()" family of functions
** from the standard C library.
**
** ^The sqlite4_mprintf() and sqlite4_vmprintf() routines write their
** results into memory obtained from [sqlite4_malloc()].
** The strings returned by these two routines should be
** released by [sqlite4_free()].  ^Both routines return a
** NULL pointer if [sqlite4_malloc()] is unable to allocate enough
** memory to hold the resulting string.
**
** ^(The sqlite4_snprintf() routine is similar to "snprintf()" from
** the standard C library.  The result is written into the
** buffer supplied as the first parameter whose size is given by
** the second parameter.)^  The return value from sqltie4_snprintf()
** is the number of bytes actually written into the buffer, not
** counting the zero terminator.  The buffer is always zero-terminated
** as long as it it at least one byte in length.
**
** The sqlite4_snprintf() differs from the standard library snprintf()
** routine in two ways:  (1) sqlite4_snprintf() returns the number of
** bytes actually written, not the number of bytes that would have been
** written if the buffer had been infinitely long.  (2) If the buffer is
** at least one byte long, sqlite4_snprintf() always zero-terminates its
** result.
**
** ^As long as the buffer size is greater than zero, sqlite4_snprintf()
** guarantees that the buffer is always zero-terminated.  ^The second
** parameter "n" is the total size of the buffer, including space for
** the zero terminator.  So the longest string that can be completely
** written will be n-1 characters.
**
** ^The sqlite4_vsnprintf() routine is a varargs version of sqlite4_snprintf().
**
** These routines all implement some additional formatting
** options that are useful for constructing SQL statements.
** All of the usual printf() formatting options apply.  In addition, there
** is are "%q", "%Q", and "%z" options.
**
** ^(The %q option works like %s in that it substitutes a nul-terminated
** string from the argument list.  But %q also doubles every '\'' character.
** %q is designed for use inside a string literal.)^  By doubling each '\''
** character it escapes that character and allows it to be inserted into
** the string.
**
** For example, assume the string variable zText contains text as follows:
**
** <blockquote><pre>
**  char *zText = "It's a happy day!";
** </pre></blockquote>
**
** One can use this text in an SQL statement as follows:
**
** <blockquote><pre>
**  char *zSQL = sqlite4_mprintf("INSERT INTO table VALUES('%q')", zText);
**  sqlite4_exec(db, zSQL, 0, 0, 0);
**  sqlite4_free(zSQL);
** </pre></blockquote>
**
** Because the %q format string is used, the '\'' character in zText
** is escaped and the SQL generated is as follows:
**
** <blockquote><pre>
**  INSERT INTO table1 VALUES('It''s a happy day!')
** </pre></blockquote>
**
** This is correct.  Had we used %s instead of %q, the generated SQL
** would have looked like this:
**
** <blockquote><pre>
**  INSERT INTO table1 VALUES('It's a happy day!');
** </pre></blockquote>
**
** This second example is an SQL syntax error.  As a general rule you should
** always use %q instead of %s when inserting text into a string literal.
**
** ^(The %Q option works like %q except it also adds single quotes around
** the outside of the total string.  Additionally, if the parameter in the
** argument list is a NULL pointer, %Q substitutes the text "NULL" (without
** single quotes).)^  So, for example, one could say:
**
** <blockquote><pre>
**  char *zSQL = sqlite4_mprintf("INSERT INTO table VALUES(%Q)", zText);
**  sqlite4_exec(db, zSQL, 0, 0, 0);
**  sqlite4_free(zSQL);
** </pre></blockquote>
**
** The code above will render a correct SQL statement in the zSQL
** variable even if the zText variable is a NULL pointer.
**
** ^(The "%z" formatting option works like "%s" but with the
** addition that after the string has been read and copied into
** the result, [sqlite4_free()] is called on the input string.)^
*/
SQLITE4_API char *sqlite4_mprintf(sqlite4_env*, const char*,...);
SQLITE4_API char *sqlite4_vmprintf(sqlite4_env*, const char*, va_list);
SQLITE4_API sqlite4_size_t sqlite4_snprintf(char*,sqlite4_size_t,const char*, ...);
SQLITE4_API sqlite4_size_t sqlite4_vsnprintf(char*,sqlite4_size_t,const char*, va_list);

/*
** CAPIREF: Memory Allocation Subsystem
**
** The SQLite core uses these three routines for all of its own
** internal memory allocation needs.
**
** ^The sqlite4_malloc() routine returns a pointer to a block
** of memory at least N bytes in length, where N is the parameter.
** ^If sqlite4_malloc() is unable to obtain sufficient free
** memory, it returns a NULL pointer.  ^If the parameter N to
** sqlite4_malloc() is zero or negative then sqlite4_malloc() returns
** a NULL pointer.
**
** ^Calling sqlite4_free() with a pointer previously returned
** by sqlite4_malloc() or sqlite4_realloc() releases that memory so
** that it might be reused.  ^The sqlite4_free() routine is
** a no-op if is called with a NULL pointer.  Passing a NULL pointer
** to sqlite4_free() is harmless.  After being freed, memory
** should neither be read nor written.  Even reading previously freed
** memory might result in a segmentation fault or other severe error.
** Memory corruption, a segmentation fault, or other severe error
** might result if sqlite4_free() is called with a non-NULL pointer that
** was not obtained from sqlite4_malloc() or sqlite4_realloc().
**
** ^(The sqlite4_realloc() interface attempts to resize a
** prior memory allocation to be at least N bytes, where N is the
** second parameter.  The memory allocation to be resized is the first
** parameter.)^ ^ If the first parameter to sqlite4_realloc()
** is a NULL pointer then its behavior is identical to calling
** sqlite4_malloc(N) where N is the second parameter to sqlite4_realloc().
** ^If the second parameter to sqlite4_realloc() is zero or
** negative then the behavior is exactly the same as calling
** sqlite4_free(P) where P is the first parameter to sqlite4_realloc().
** ^sqlite4_realloc() returns a pointer to a memory allocation
** of at least N bytes in size or NULL if sufficient memory is unavailable.
** ^If M is the size of the prior allocation, then min(N,M) bytes
** of the prior allocation are copied into the beginning of buffer returned
** by sqlite4_realloc() and the prior allocation is freed.
** ^If sqlite4_realloc() returns NULL, then the prior allocation
** is not freed.
**
** ^The memory returned by sqlite4_malloc() and sqlite4_realloc()
** is always aligned to at least an 8 byte boundary, or to a
** 4 byte boundary if the [SQLITE4_4_BYTE_ALIGNED_MALLOC] compile-time
** option is used.
**
** The pointer arguments to [sqlite4_free()] and [sqlite4_realloc()]
** must be either NULL or else pointers obtained from a prior
** invocation of [sqlite4_malloc()] or [sqlite4_realloc()] that have
** not yet been released.
**
** The application must not read or write any part of
** a block of memory after it has been released using
** [sqlite4_free()] or [sqlite4_realloc()].
*/
SQLITE4_API void *sqlite4_malloc(sqlite4_env*, sqlite4_size_t);
SQLITE4_API void *sqlite4_realloc(sqlite4_env*, void*, sqlite4_size_t);
SQLITE4_API void sqlite4_free(sqlite4_env*, void*);

/*
** CAPIREF: Pseudo-Random Number Generator
**
** ^A call to this routine stores N bytes of pseudo-randomness into buffer P.
*/
SQLITE4_API void sqlite4_randomness(sqlite4_env*, int N, void *P);

/*
** CAPIREF: Compile-Time Authorization Callbacks
**
** These routines are used to register and deregister authorization 
** callbacks with the database connection passed as the first argument. 
**
** Each database connection has a stack of authorization callbacks, which
** may be empty. Calling sqlite4_authorizer_push() adds an authorization
** callback to the top of the stack, and calling sqlite4_authorizer_pop()
** removes the topmost authorizer. When an authorization callback is 
** pushed onto the stack, the application may pass a pointer to a destructor 
** function as the fourth argument to sqlite3_authorizer_push(). If the
** destructor function pointer is not NULL, then it is invoked with a copy
** of the second argument to sqlite4_authorizer_push() as the only argument
** when the authorizer function is popped off the stack, or when the database
** connection is closed.
**
** If an error occurs within a call to sqlite4_authorizer_push(), then
** an SQLite error code is returned and no authorizer callback is added
** to the stack. If a destructor function was specified, then in this case
** it is invoked before the sqlite4_authorizer_push() call returns.
**
** Authorization callbacks are invoked by SQLite4 from within 
** sqlite4_prepare() and, when repreparing statements, from within 
** sqlite3_step(). During SQL statement compilation (or recompilation), 
** SQLite4 invokes the authorization callbacks for each action required
** to execute the statement. "Actions" are things like reading a value
** from a specific table column, modifying, inserting or deleting a row 
** within a specific database table, or creating or dropping a schema 
** object. The complete list of actions [SQLITE4_CREATE_INDEX | is here].
**
** The first parameter passed to an authorizer callback is a copy of the 
** second parameter passed to the sqlite4_authorizer_push() interface. The
** second parameter to the callback is an integer [SQLITE4_COPY | action code]
** that specifies the particular action to be authorized. The third through 
** sixth parameters to the callback are zero-terminated strings that contain 
** additional details about the action to be authorized.
**
** An authorization callback must return one of SQLITE4_OK, SQLITE4_IGNORE,
** SQLITE4_DENY or SQLITE4_ALLOW. If any other value is returned, it is an
** error. In this case, statement compilation fails and SQLITE4_ERROR is
** returned to the user.
**
** If an authorization callback returns SQLITE4_OK or SQLITE4_ALLOW, then
** SQLite4 interprets this as an indication that permission is granted for 
** the specified action. If SQLITE4_DENY is returned, then permission has 
** been denied and statement compilation fails. If SQLITE4_IGNORE is returned, 
** and the requested action is to read a table column ([SQLITE4_READ]), then
** permission is denied but statement compilation is allowed to continue. 
** In this case, instead of reading the required value from a table column, 
** the database engine substitues an SQL NULL value instead. If SQLITE4_IGNORE 
** is returned by an authorization callback requesting anything other than to 
** read a table column, then statement compilation is allowed to continue,
** but the requested action is silently omitted.
**
** If there is more than one authorization callback on the stack when a
** statement is compiled (or recompiled), then the callback on the top of
** the stack is invoked first. If it returns other than SQLITE4_OK, then no 
** further callbacks are issued and the value returned is interpreted by 
** SQLite4 as described above. Or, if it does return SQLITE4_OK, then the
** next callback on the stack is invoked, and so on.
**
** The difference between SQLITE4_OK and SQLITE4_ALLOW is as follows - if
** an authorization callback returns SQLITE4_ALLOW, then no further callbacks
** are invoked for the action. The action is authorized.
**
** An authorizer callback must not do anything that will modify the state
** of the database connection that invoked the authorizer callback. Note that 
** [sqlite4_prepare()] and [sqlite4_step()] both modify the state of their 
** database connections for the meaning of "modify" in this paragraph.
*/
SQLITE4_API int sqlite4_authorizer_push(
  sqlite4*,
  void *pCtx,
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
  void (*xDestroy)(void*)
);
SQLITE4_API int sqlite4_authorizer_pop(sqlite4*);

/*
** CAPIREF: Authorizer Return Codes
**
** The [sqlite4_set_authorizer | authorizer callback function] must
** return either [SQLITE4_OK] or one of these two constants in order
** to signal SQLite whether or not the action is permitted.  See the
** [sqlite4_set_authorizer | authorizer documentation] for additional
** information.
**
** Note that SQLITE4_IGNORE is also used as a [SQLITE4_ROLLBACK | return code]
** from the [sqlite4_vtab_on_conflict()] interface.
*/
#define SQLITE4_DENY   1   /* Abort the SQL statement with an error */
#define SQLITE4_IGNORE 2   /* Don't allow access, but don't generate an error */
#define SQLITE4_ALLOW  3   /* Allow access, do not invoke further callbacks */

/*
** CAPIREF: Authorizer Action Codes
**
** The [sqlite4_set_authorizer()] interface registers a callback function
** that is invoked to authorize certain SQL statement actions.  The
** second parameter to the callback is an integer code that specifies
** what action is being authorized.  These are the integer action codes that
** the authorizer callback may be passed.
**
** These action code values signify what kind of operation is to be
** authorized.  The 3rd and 4th parameters to the authorization
** callback function will be parameters or NULL depending on which of these
** codes is used as the second parameter.  ^(The 5th parameter to the
** authorizer callback is the name of the database ("main", "temp",
** etc.) if applicable.)^  ^The 6th parameter to the authorizer callback
** is the name of the inner-most trigger or view that is responsible for
** the access attempt or NULL if this access attempt is directly from
** top-level SQL code.
*/
/******************************************* 3rd ************ 4th ***********/
#define SQLITE4_CREATE_INDEX          1   /* Index Name      Table Name      */
#define SQLITE4_CREATE_TABLE          2   /* Table Name      NULL            */
#define SQLITE4_CREATE_TEMP_INDEX     3   /* Index Name      Table Name      */
#define SQLITE4_CREATE_TEMP_TABLE     4   /* Table Name      NULL            */
#define SQLITE4_CREATE_TEMP_TRIGGER   5   /* Trigger Name    Table Name      */
#define SQLITE4_CREATE_TEMP_VIEW      6   /* View Name       NULL            */
#define SQLITE4_CREATE_TRIGGER        7   /* Trigger Name    Table Name      */
#define SQLITE4_CREATE_VIEW           8   /* View Name       NULL            */
#define SQLITE4_DELETE                9   /* Table Name      NULL            */
#define SQLITE4_DROP_INDEX           10   /* Index Name      Table Name      */
#define SQLITE4_DROP_TABLE           11   /* Table Name      NULL            */
#define SQLITE4_DROP_TEMP_INDEX      12   /* Index Name      Table Name      */
#define SQLITE4_DROP_TEMP_TABLE      13   /* Table Name      NULL            */
#define SQLITE4_DROP_TEMP_TRIGGER    14   /* Trigger Name    Table Name      */
#define SQLITE4_DROP_TEMP_VIEW       15   /* View Name       NULL            */
#define SQLITE4_DROP_TRIGGER         16   /* Trigger Name    Table Name      */
#define SQLITE4_DROP_VIEW            17   /* View Name       NULL            */
#define SQLITE4_INSERT               18   /* Table Name      NULL            */
#define SQLITE4_PRAGMA               19   /* Pragma Name     NULL            */
#define SQLITE4_READ                 20   /* Table Name      Column Name     */
#define SQLITE4_SELECT               21   /* NULL            NULL            */
#define SQLITE4_TRANSACTION          22   /* Operation       NULL            */
#define SQLITE4_UPDATE               23   /* Table Name      Column Name     */
#define SQLITE4_ATTACH               24   /* Filename        NULL            */
#define SQLITE4_DETACH               25   /* Database Name   NULL            */
#define SQLITE4_ALTER_TABLE          26   /* Database Name   Table Name      */
#define SQLITE4_REINDEX              27   /* Index Name      NULL            */
#define SQLITE4_ANALYZE              28   /* Table Name      NULL            */
#define SQLITE4_CREATE_VTABLE        29   /* Table Name      Module Name     */
#define SQLITE4_DROP_VTABLE          30   /* Table Name      Module Name     */
#define SQLITE4_FUNCTION             31   /* NULL            Function Name   */
#define SQLITE4_SAVEPOINT            32   /* Operation       Savepoint Name  */
#define SQLITE4_COPY                  0   /* No longer used */

/*
** CAPIREF: Tracing And Profiling Functions
**
** These routines register callback functions that can be used for
** tracing and profiling the execution of SQL statements.
**
** ^The callback function registered by sqlite4_trace() is invoked at
** various times when an SQL statement is being run by [sqlite4_step()].
** ^The sqlite4_trace() callback is invoked with a UTF-8 rendering of the
** SQL statement text as the statement first begins executing.
** ^(Additional sqlite4_trace() callbacks might occur
** as each triggered subprogram is entered.  The callbacks for triggers
** contain a UTF-8 SQL comment that identifies the trigger.)^
**
** ^The callback function registered by sqlite4_profile() is invoked
** as each SQL statement finishes.  ^The profile callback contains
** the original statement text and an estimate of wall-clock time
** of how long that statement took to run.  ^The profile callback
** time is in units of nanoseconds, however the current implementation
** is only capable of millisecond resolution so the six least significant
** digits in the time are meaningless.  Future versions of SQLite
** might provide greater resolution on the profiler callback.  The
** sqlite4_profile() function is considered experimental and is
** subject to change in future versions of SQLite.
*/
SQLITE4_API void sqlite4_trace(
  sqlite4*, 
  void *, 
  void(*xTrace)(void*,const char*), 
  void(*xDestroy)(void*)
);
SQLITE4_API void sqlite4_profile(
  sqlite4*,
  void *,
  void(*xProfile)(void*,const char*,sqlite4_uint64),
  void(*xDestroy)(void*)
);

/*
** CAPIREF: Opening A New Database Connection
**
** ^These routines open an SQLite4 database file as specified by the 
** URI argument.
** ^(A [database connection] handle is usually
** returned in *ppDb, even if an error occurs.  The only exception is that
** if SQLite is unable to allocate memory to hold the [sqlite4] object,
** a NULL will be written into *ppDb instead of a pointer to the [sqlite4]
** object.)^ ^(If the database is opened (and/or created) successfully, then
** [SQLITE4_OK] is returned.  Otherwise an [error code] is returned.)^ ^The
** [sqlite4_errmsg()] routine can be used to obtain
** an English language description of the error following a failure of any
** of the sqlite4_open() routines.
**
** Whether or not an error occurs when it is opened, resources
** associated with the [database connection] handle should be released by
** passing it to [sqlite4_close()] when it is no longer required.
**
*/
SQLITE4_API int sqlite4_open(
  sqlite4_env *pEnv,     /* Run-time environment. NULL means use the default */
  const char *filename,  /* Database filename (UTF-8) */
  sqlite4 **ppDb,        /* OUT: SQLite db handle */
  ...                    /* Optional parameters.  Zero terminates options */
);

/*
** CAPIREF: Obtain Values For URI Parameters
**
** These are utility routines, useful to VFS implementations, that check
** to see if a database file was a URI that contained a specific query 
** parameter, and if so obtains the value of that query parameter.
**
** If F is the database filename pointer passed into the xOpen() method of 
** a VFS implementation when the flags parameter to xOpen() has one or 
** more of the [SQLITE4_OPEN_URI] or [SQLITE4_OPEN_MAIN_DB] bits set and
** P is the name of the query parameter, then
** sqlite4_uri_parameter(F,P) returns the value of the P
** parameter if it exists or a NULL pointer if P does not appear as a 
** query parameter on F.  If P is a query parameter of F
** has no explicit value, then sqlite4_uri_parameter(F,P) returns
** a pointer to an empty string.
**
** The sqlite4_uri_boolean(F,P,B) routine assumes that P is a boolean
** parameter and returns true (1) or false (0) according to the value
** of P.  The value of P is true if it is "yes" or "true" or "on" or 
** a non-zero number and is false otherwise.  If P is not a query parameter
** on F then sqlite4_uri_boolean(F,P,B) returns (B!=0).
**
** The sqlite4_uri_int64(F,P,D) routine converts the value of P into a
** 64-bit signed integer and returns that integer, or D if P does not
** exist.  If the value of P is something other than an integer, then
** zero is returned.
** 
** If F is a NULL pointer, then sqlite4_uri_parameter(F,P) returns NULL and
** sqlite4_uri_boolean(F,P,B) returns B.  If F is not a NULL pointer and
** is not a database file pathname pointer that SQLite passed into the xOpen
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
*/
SQLITE4_API const char *sqlite4_uri_parameter(const char *zFilename, const char *zParam);
SQLITE4_API int sqlite4_uri_boolean(const char *zFile, const char *zParam, int bDefault);
SQLITE4_API sqlite4_int64 sqlite4_uri_int64(const char*, const char*, sqlite4_int64);


/*
** CAPIREF: Error Codes And Messages
**
** ^The sqlite4_errcode() interface returns the numeric 
** [extended result code] for the most recent failed sqlite4_* API call
** associated with a [database connection]. If a prior API call failed
** but the most recent API call succeeded, the return value from
** sqlite4_errcode() is undefined.
**
** ^The sqlite4_errmsg() routine returns English-language text that 
** describes the error, as a UTF-8 encoded string. ^(Memory to hold the 
** error message string is managed internally. The application does not 
** need to worry about freeing the result. However, the error string 
** might be overwritten or deallocated by subsequent calls to other 
** SQLite interface functions.)^
**
** When the serialized [threading mode] is in use, it might be the
** case that a second error occurs on a separate thread in between
** the time of the first error and the call to these interfaces.
** When that happens, the second error will be reported since these
** interfaces always report the most recent result.  To avoid
** this, each thread can obtain exclusive use of the [database connection] D
** by invoking [sqlite4_mutex_enter]([sqlite4_db_mutex](D)) before beginning
** to use D and invoking [sqlite4_mutex_leave]([sqlite4_db_mutex](D)) after
** all calls to the interfaces listed here are completed.
**
** If an SQLite API call fails with SQLITE4_MISUSE, that means the 
** interface was invoked incorrectly by the application. In that case, the
** error code and message may or may not be set.
*/
SQLITE4_API int sqlite4_errcode(sqlite4 *db);
SQLITE4_API const char *sqlite4_errmsg(sqlite4*);

/*
** CAPIREF: SQL Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
** An instance of this object represents a single SQL statement.
** This object is variously known as a "prepared statement" or a
** "compiled SQL statement" or simply as a "statement".
**
** The life of a statement object goes something like this:
**
** <ol>
** <li> Create the object using [sqlite4_prepare()] or a related
**      function.
** <li> Bind values to [host parameters] using the sqlite4_bind_*()
**      interfaces.
** <li> Run the SQL by calling [sqlite4_step()] one or more times.
** <li> Reset the statement using [sqlite4_reset()] then go back
**      to step 2.  Do this zero or more times.
** <li> Destroy the object using [sqlite4_finalize()].
** </ol>
**
** Refer to documentation on individual methods above for additional
** information.
*/
typedef struct sqlite4_stmt sqlite4_stmt;

/*
** CAPIREF: Run-time Limits
**
** ^(This interface allows the size of various constructs to be limited
** on a connection by connection basis.  The first parameter is the
** [database connection] whose limit is to be set or queried.  The
** second parameter is one of the [limit categories] that define a
** class of constructs to be size limited.  The third parameter is the
** new limit for that construct.)^
**
** ^If the new limit is a negative number, the limit is unchanged.
** ^(For each limit category SQLITE4_LIMIT_<i>NAME</i> there is a 
** [limits | hard upper bound]
** set at compile-time by a C preprocessor macro called
** [limits | SQLITE4_MAX_<i>NAME</i>].
** (The "_LIMIT_" in the name is changed to "_MAX_".))^
** ^Attempts to increase a limit above its hard upper bound are
** silently truncated to the hard upper bound.
**
** ^Regardless of whether or not the limit was changed, the 
** [sqlite4_limit()] interface returns the prior value of the limit.
** ^Hence, to find the current value of a limit without changing it,
** simply invoke this interface with the third parameter set to -1.
**
** Run-time limits are intended for use in applications that manage
** both their own internal database and also databases that are controlled
** by untrusted external sources.  An example application might be a
** web browser that has its own databases for storing history and
** separate databases controlled by JavaScript applications downloaded
** off the Internet.  The internal databases can be given the
** large, default limits.  Databases managed by external sources can
** be given much smaller limits designed to prevent a denial of service
** attack.  Developers might also want to use the [sqlite4_set_authorizer()]
** interface to further control untrusted SQL.  The size of the database
** created by an untrusted script can be contained using the
** [max_page_count] [PRAGMA].
**
** New run-time limit categories may be added in future releases.
*/
SQLITE4_API int sqlite4_limit(sqlite4*, int id, int newVal);

/*
** CAPIREF: Run-Time Limit Categories
** KEYWORDS: {limit category} {*limit categories}
**
** These constants define various performance limits
** that can be lowered at run-time using [sqlite4_limit()].
** The synopsis of the meanings of the various limits is shown below.
** Additional information is available at [limits | Limits in SQLite].
**
** <dl>
** [[SQLITE4_LIMIT_LENGTH]] ^(<dt>SQLITE4_LIMIT_LENGTH</dt>
** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
**
** [[SQLITE4_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE4_LIMIT_SQL_LENGTH</dt>
** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
**
** [[SQLITE4_LIMIT_COLUMN]] ^(<dt>SQLITE4_LIMIT_COLUMN</dt>
** <dd>The maximum number of columns in a table definition or in the
** result set of a [SELECT] or the maximum number of columns in an index
** or in an ORDER BY or GROUP BY clause.</dd>)^
**
** [[SQLITE4_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE4_LIMIT_EXPR_DEPTH</dt>
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
**
** [[SQLITE4_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE4_LIMIT_COMPOUND_SELECT</dt>
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
**
** [[SQLITE4_LIMIT_VDBE_OP]] ^(<dt>SQLITE4_LIMIT_VDBE_OP</dt>
** <dd>The maximum number of instructions in a virtual machine program
** used to implement an SQL statement.  This limit is not currently
** enforced, though that might be added in some future release of
** SQLite.</dd>)^
**
** [[SQLITE4_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE4_LIMIT_FUNCTION_ARG</dt>
** <dd>The maximum number of arguments on a function.</dd>)^
**
** [[SQLITE4_LIMIT_ATTACHED]] ^(<dt>SQLITE4_LIMIT_ATTACHED</dt>
** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
**
** [[SQLITE4_LIMIT_LIKE_PATTERN_LENGTH]]
** ^(<dt>SQLITE4_LIMIT_LIKE_PATTERN_LENGTH</dt>
** <dd>The maximum length of the pattern argument to the [LIKE] or
** [GLOB] operators.</dd>)^
**
** [[SQLITE4_LIMIT_VARIABLE_NUMBER]]
** ^(<dt>SQLITE4_LIMIT_VARIABLE_NUMBER</dt>
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
**
** [[SQLITE4_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE4_LIMIT_TRIGGER_DEPTH</dt>
** <dd>The maximum depth of recursion for triggers.</dd>)^
** </dl>
*/
#define SQLITE4_LIMIT_LENGTH                    0
#define SQLITE4_LIMIT_SQL_LENGTH                1
#define SQLITE4_LIMIT_COLUMN                    2
#define SQLITE4_LIMIT_EXPR_DEPTH                3
#define SQLITE4_LIMIT_COMPOUND_SELECT           4
#define SQLITE4_LIMIT_VDBE_OP                   5
#define SQLITE4_LIMIT_FUNCTION_ARG              6
#define SQLITE4_LIMIT_ATTACHED                  7
#define SQLITE4_LIMIT_LIKE_PATTERN_LENGTH       8
#define SQLITE4_LIMIT_VARIABLE_NUMBER           9
#define SQLITE4_LIMIT_TRIGGER_DEPTH            10

/*
** CAPIREF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
**
** The first argument, "db", is a [database connection] obtained from a
** prior successful call to [sqlite4_open()]. The database connection 
** must not have been closed.
**
** The second argument, "zSql", is the statement to be compiled, encoded
** as either UTF-8 or UTF-16.  The sqlite4_prepare() interface uses UTF-8
** , and sqlite4_prepare16() uses UTF-16.
**
** ^If the nByte argument is less than zero, then zSql is read up to the
** first zero terminator. ^If nByte is non-negative, then it is the maximum
** number of  bytes read from zSql.  ^When nByte is non-negative, the
** zSql string ends at either the first '\000' or '\u0000' character or
** the nByte-th byte, whichever comes first. If the caller knows
** that the supplied string is nul-terminated, then there is a small
** performance advantage to be gained by passing an nByte parameter that
** is equal to the number of bytes in the input string <i>including</i>
** the nul-terminator bytes as this saves SQLite from having to
** make a copy of the input string.
**
** ^If pnUsed is not NULL then *pnUsed is set to the number of bytes read
** from zSql. That is, the offset within zSql of the first byte past the
** end of the SQL statement compiled. 
**
** ^*ppStmt is left pointing to a compiled [prepared statement] that can be
** executed using [sqlite4_step()].  ^If there is an error, *ppStmt is set
** to NULL.  ^If the input text contains no SQL (if the input is an empty
** string or a comment) then *ppStmt is set to NULL. The calling procedure 
** is responsible for deleting the compiled SQL statement using 
** [sqlite4_finalize()] after it has finished with it. ppStmt may not be NULL.
**
** ^On success, the sqlite4_prepare() family of routines return [SQLITE4_OK];
** otherwise an [error code] is returned.
*/
SQLITE4_API int sqlite4_prepare(
  sqlite4 *db,            /* Database handle */
  const char *zSql,       /* SQL statement, UTF-8 encoded */
  int nByte,              /* Maximum length of zSql in bytes. */
  sqlite4_stmt **ppStmt,  /* OUT: Statement handle */
  int *pnUsed             /* OUT: Number of bytes read from zSql */
);

/*
** CAPIREF: Retrieving Statement SQL
**
** ^This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
** compiled using either [sqlite4_prepare()] or [sqlite4_prepare16_v2()].
*/
SQLITE4_API const char *sqlite4_stmt_sql(sqlite4_stmt *pStmt);

/*
** CAPIREF: Determine If An SQL Statement Writes The Database
**
** ^The sqlite4_stmt_readonly(X) interface returns true (non-zero) if
** and only if the [prepared statement] X makes no direct changes to
** the content of the database file.
**
** Note that [application-defined SQL functions] or
** [virtual tables] might change the database indirectly as a side effect.  
** ^(For example, if an application defines a function "eval()" that 
** calls [sqlite4_exec()], then the following SQL statement would
** change the database file through side-effects:
**
** <blockquote><pre>
**    SELECT eval('DELETE FROM t1') FROM t2;
** </pre></blockquote>
**
** But because the [SELECT] statement does not change the database file
** directly, sqlite4_stmt_readonly() would still return true.)^
**
** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
** [SAVEPOINT], and [RELEASE] cause sqlite4_stmt_readonly() to return true,
** since the statements themselves do not actually modify the database but
** rather they control the timing of when other statements modify the 
** database.  ^The [ATTACH] and [DETACH] statements also cause
** sqlite4_stmt_readonly() to return true since, while those statements
** change the configuration of a database connection, they do not make 
** changes to the content of the database files on disk.
*/
SQLITE4_API int sqlite4_stmt_readonly(sqlite4_stmt *pStmt);

/*
** CAPIREF: Determine If A Prepared Statement Has Been Reset
**
** ^The sqlite4_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using 
** [sqlite4_step(S)] but has not run to completion and/or has not 
** been reset using [sqlite4_reset(S)].  ^The sqlite4_stmt_busy(S)
** interface returns false if S is a NULL pointer.  If S is not a 
** NULL pointer and is not a pointer to a valid [prepared statement]
** object, then the behavior is undefined and probably undesirable.
**
** This interface can be used in combination [sqlite4_next_stmt()]
** to locate all prepared statements associated with a database 
** connection that are in need of being reset.  This can be used,
** for example, in diagnostic routines to search for prepared 
** statements that are holding a transaction open.
*/
SQLITE4_API int sqlite4_stmt_busy(sqlite4_stmt*);

/*
** CAPIREF: SQL Function Context Object
**
** The context in which an SQL function executes is stored in an
** sqlite4_context object.  ^A pointer to an sqlite4_context object
** is always first parameter to [application-defined SQL functions].
** The application-defined SQL function implementation will pass this
** pointer through into calls to [sqlite4_result_int | sqlite4_result()],
** [sqlite4_aggregate_context()], [sqlite4_context_appdata()],
** [sqlite4_context_db_handle()], [sqlite4_auxdata_fetch()],
** and/or [sqlite4_auxdata_store()].
*/
typedef struct sqlite4_context sqlite4_context;

/*
** CAPIREF: Binding Values To Prepared Statements
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
**
** ^(In the SQL statement text input to [sqlite4_prepare()] and its variants,
** literals may be replaced by a [parameter] that matches one of following
** templates:
**
** <ul>
** <li>  ?
** <li>  ?NNN
** <li>  :VVV
** <li>  @VVV
** <li>  $VVV
** </ul>
**
** In the templates above, NNN represents an integer literal,
** and VVV represents an alphanumeric identifier.)^  ^The values of these
** parameters (also called "host parameter names" or "SQL parameters")
** can be set using the sqlite4_bind_*() routines defined here.
**
** ^The first argument to the sqlite4_bind_*() routines is always
** a pointer to the [sqlite4_stmt] object returned from
** [sqlite4_prepare()] or its variants.
**
** ^The second argument is the index of the SQL parameter to be set.
** ^The leftmost SQL parameter has an index of 1.  ^When the same named
** SQL parameter is used more than once, second and subsequent
** occurrences have the same index as the first occurrence.
** ^The index for named parameters can be looked up using the
** [sqlite4_bind_parameter_index()] API if desired.  ^The index
** for "?NNN" parameters is the value of NNN.
** ^The NNN value must be between 1 and the [sqlite4_limit()]
** parameter [SQLITE4_LIMIT_VARIABLE_NUMBER] (default value: 999).
**
** ^The third argument is the value to bind to the parameter.
**
** ^(In those routines that have a fourth argument, its value is the
** number of bytes in the parameter.  To be clear: the value is the
** number of <u>bytes</u> in the value, not the number of characters.)^
** ^If the fourth parameter is negative, the length of the string is
** the number of bytes up to the first zero terminator.
** If a non-negative fourth parameter is provided to sqlite4_bind_text()
** or sqlite4_bind_text16() then that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL
** terminated.  If any NUL characters occur at byte offsets less than 
** the value of the fourth parameter then the resulting string value will
** contain embedded NULs.  The result of expressions involving strings
** with embedded NULs is undefined.
**
** ^The fifth argument to sqlite4_bind_blob(), sqlite4_bind_text(), and
** sqlite4_bind_text16() is a destructor used to dispose of the BLOB or
** string after SQLite has finished with it.  ^The destructor is called
** to dispose of the BLOB or string even if the call to sqlite4_bind_blob(),
** sqlite4_bind_text(), or sqlite4_bind_text16() fails.  
** ^If the fifth argument is
** the special value [SQLITE4_STATIC], then SQLite assumes that the
** information is in static, unmanaged space and does not need to be freed.
** ^If the fifth argument has the value [SQLITE4_TRANSIENT], then
** SQLite makes its own private copy of the data immediately, before
** the sqlite4_bind_*() routine returns.
**
** ^If any of the sqlite4_bind_*() routines are called with a NULL pointer
** for the [prepared statement] or with a prepared statement for which
** [sqlite4_step()] has been called more recently than [sqlite4_reset()],
** then the call will return [SQLITE4_MISUSE].  If any sqlite4_bind_()
** routine is passed a [prepared statement] that has been finalized, the
** result is undefined and probably harmful.
**
** ^Bindings are not cleared by the [sqlite4_reset()] routine.
** ^Unbound parameters are interpreted as NULL.
**
** ^The sqlite4_bind_* routines return [SQLITE4_OK] on success or an
** [error code] if anything goes wrong.
** ^[SQLITE4_RANGE] is returned if the parameter
** index is out of range.  ^[SQLITE4_NOMEM] is returned if malloc() fails.
**
** See also: [sqlite4_bind_parameter_count()],
** [sqlite4_bind_parameter_name()], and [sqlite4_bind_parameter_index()].
*/
SQLITE4_API int sqlite4_bind_blob(sqlite4_stmt*, int, const void*, int n, 
                      void(*)(void*,void*),void*);
SQLITE4_API int sqlite4_bind_double(sqlite4_stmt*, int, double);
SQLITE4_API int sqlite4_bind_int(sqlite4_stmt*, int, int);
SQLITE4_API int sqlite4_bind_int64(sqlite4_stmt*, int, sqlite4_int64);
SQLITE4_API int sqlite4_bind_null(sqlite4_stmt*, int);
SQLITE4_API int sqlite4_bind_text(sqlite4_stmt*, int, const char*, int n,
                      void(*)(void*,void*),void*);
SQLITE4_API int sqlite4_bind_text16(sqlite4_stmt*, int, const void*, int,
                        void(*)(void*,void*),void*);
SQLITE4_API int sqlite4_bind_value(sqlite4_stmt*, int, const sqlite4_value*);

/*
** CAPIREF: Number Of SQL Parameters
**
** ^This routine can be used to find the number of [SQL parameters]
** in a [prepared statement].  SQL parameters are tokens of the
** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as
** placeholders for values that are [sqlite4_bind_blob | bound]
** to the parameters at a later time.
**
** ^(This routine actually returns the index of the largest (rightmost)
** parameter. For all forms except ?NNN, this will correspond to the
** number of unique parameters.  If parameters of the ?NNN form are used,
** there may be gaps in the list.)^
**
** See also: [sqlite4_bind_blob|sqlite4_bind()],
** [sqlite4_bind_parameter_name()], and
** [sqlite4_bind_parameter_index()].
*/
SQLITE4_API int sqlite4_bind_parameter_count(sqlite4_stmt*);

/*
** CAPIREF: Name Of A Host Parameter
**
** ^The sqlite4_bind_parameter_name(P,N) interface returns
** the name of the N-th [SQL parameter] in the [prepared statement] P.
** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA"
** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA"
** respectively.
** In other words, the initial ":" or "$" or "@" or "?"
** is included as part of the name.)^
** ^Parameters of the form "?" without a following integer have no name
** and are referred to as "nameless" or "anonymous parameters".
**
** ^The first host parameter has an index of 1, not 0.
**
** ^If the value N is out of range or if the N-th parameter is
** nameless, then NULL is returned.  ^The returned string is
** always in UTF-8 encoding even if the named parameter was
** originally specified as UTF-16 in [sqlite4_prepare16()] or
** [sqlite4_prepare16_v2()].
**
** See also: [sqlite4_bind_blob|sqlite4_bind()],
** [sqlite4_bind_parameter_count()], and
** [sqlite4_bind_parameter_index()].
*/
SQLITE4_API const char *sqlite4_bind_parameter_name(sqlite4_stmt*, int);

/*
** CAPIREF: Index Of A Parameter With A Given Name
**
** ^Return the index of an SQL parameter given its name.  ^The
** index value returned is suitable for use as the second
** parameter to [sqlite4_bind_blob|sqlite4_bind()].  ^A zero
** is returned if no matching parameter is found.  ^The parameter
** name must be given in UTF-8 even if the original statement
** was prepared from UTF-16 text using [sqlite4_prepare16_v2()].
**
** See also: [sqlite4_bind_blob|sqlite4_bind()],
** [sqlite4_bind_parameter_count()], and
** [sqlite4_bind_parameter_index()].
*/
SQLITE4_API int sqlite4_bind_parameter_index(sqlite4_stmt*, const char *zName);

/*
** CAPIREF: Reset All Bindings On A Prepared Statement
**
** ^Contrary to the intuition of many, [sqlite4_reset()] does not reset
** the [sqlite4_bind_blob | bindings] on a [prepared statement].
** ^Use this routine to reset all host parameters to NULL.
*/
SQLITE4_API int sqlite4_clear_bindings(sqlite4_stmt*);

/*
** CAPIREF: Number Of Columns In A Result Set
**
** ^Return the number of columns in the result set returned by the
** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
** statement that does not return data (for example an [UPDATE]).
**
** See also: [sqlite4_data_count()]
*/
SQLITE4_API int sqlite4_column_count(sqlite4_stmt *pStmt);

/*
** CAPIREF: Column Names In A Result Set
**
** ^This routine returns the name assigned to a particular column
** in the result set of a [SELECT] statement. ^The first parameter is the
** [prepared statement] that implements the [SELECT] statement. ^The second
** parameter is the column number. ^The leftmost column is number 0.
**
** ^The name of a result column is the value of the "AS" clause for
** that column, if there is an AS clause.  If there is no AS clause
** then the name of the column is unspecified and may change from
** one release of SQLite to the next.
**
** ^The returned string pointer is valid until either the [prepared statement]
** is destroyed by [sqlite4_finalize()] or until the statement is automatically
** reprepared by the first call to [sqlite4_step()] for a particular run.
**
** ^If a memory allocation fails during the processing of this routine
** then a NULL pointer is returned.
*/
SQLITE4_API const char *sqlite4_column_name(sqlite4_stmt*, int N);

/*
** CAPIREF: Source Of Data In A Query Result
**
** ^These routines provide a means to determine the database, table, and
** table column that is the origin of a particular result column in
** [SELECT] statement. Specifically, the sqlite4_column_database_name()
** routine returns the database name, the _table_name() routine returns
** the table name and _origin_name() returns the column name.
** ^The returned string is valid until the [prepared statement] is destroyed
** using [sqlite4_finalize()] or until the statement is automatically
** reprepared by the first call to [sqlite4_step()] for a particular run.
**
** ^The names returned are the original un-aliased names of the
** database, table, and column.
**
** ^The first argument to these interfaces is a [prepared statement].
** ^These functions return information about the Nth result column returned by
** the statement, where N is the second function argument.
** ^The left-most column is column 0 for these routines.
**
** ^If the Nth column returned by the statement is an expression or
** subquery and is not a column value, then all of these functions return
** NULL.  ^These routine might also return NULL if a memory allocation error
** occurs.  ^Otherwise, they return the name of the attached database, table,
** or column that query result column was extracted from.
**
** ^These APIs are only available if the library was compiled with the
** [SQLITE4_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
**
** If two or more threads call one or more of these routines against the same
** prepared statement and column at the same time then the results are
** undefined.
**
** If two or more threads call one or more
** [sqlite4_column_database_name | column metadata interfaces]
** for the same [prepared statement] and result column
** at the same time then the results are undefined.
*/
SQLITE4_API const char *sqlite4_column_database_name(sqlite4_stmt*,int);
SQLITE4_API const char *sqlite4_column_table_name(sqlite4_stmt*,int);
SQLITE4_API const char *sqlite4_column_origin_name(sqlite4_stmt*,int);

/*
** CAPIREF: Declared Datatype Of A Query Result
**
** ^(The first parameter is a [prepared statement].
** If this statement is a [SELECT] statement and the Nth column of the
** returned result set of that [SELECT] is a table column (not an
** expression or subquery) then the declared type of the table
** column is returned.)^  ^If the Nth column of the result set is an
** expression or subquery, then a NULL pointer is returned.
** ^The returned string is always UTF-8 encoded.
**
** ^(For example, given the database schema:
**
** CREATE TABLE t1(c1 VARIANT);
**
** and the following statement to be compiled:
**
** SELECT c1 + 1, c1 FROM t1;
**
** this routine would return the string "VARIANT" for the second result
** column (i==1), and a NULL pointer for the first result column (i==0).)^
**
** ^SQLite uses dynamic run-time typing.  ^So just because a column
** is declared to contain a particular type does not mean that the
** data stored in that column is of the declared type.  SQLite is
** strongly typed, but the typing is dynamic not static.  ^Type
** is associated with individual values, not with the containers
** used to hold those values.
*/
SQLITE4_API const char *sqlite4_column_decltype(sqlite4_stmt*,int);

/*
** CAPIREF: Evaluate An SQL Statement
**
** After a [prepared statement] has been prepared using [sqlite4_prepare()],
** this function must be called one or more times to evaluate the statement.
**
** ^This routine can return any of the other [result codes] or
** [extended result codes].
**
** ^[SQLITE4_BUSY] means that the database engine was unable to acquire the
** database locks it needs to do its job.  ^If the statement is a [COMMIT]
** or occurs outside of an explicit transaction, then you can retry the
** statement.  If the statement is not a [COMMIT] and occurs within an
** explicit transaction then you should rollback the transaction before
** continuing.
**
** ^[SQLITE4_DONE] means that the statement has finished executing
** successfully.  sqlite4_step() should not be called again on this virtual
** machine without first calling [sqlite4_reset()] to reset the virtual
** machine back to its initial state.
**
** ^If the SQL statement being executed returns any data, then [SQLITE4_ROW]
** is returned each time a new row of data is ready for processing by the
** caller. The values may be accessed using the [column access functions].
** sqlite4_step() is called again to retrieve the next row of data.
**
** ^[SQLITE4_ERROR] means that a run-time error (such as a constraint
** violation) has occurred.  sqlite4_step() should not be called again on
** the VM. More information may be found by calling [sqlite4_errmsg()].
**
** [SQLITE4_MISUSE] means that the this routine was called inappropriately.
** Perhaps it was called on a [prepared statement] that has
** already been [sqlite4_finalize | finalized] or on one that had
** previously returned [SQLITE4_ERROR] or [SQLITE4_DONE].  Or it could
** be the case that the same database connection is being used by two or
** more threads at the same moment in time.
*/
SQLITE4_API int sqlite4_step(sqlite4_stmt*);

/*
** CAPIREF: Number of columns in a result set
**
** ^The sqlite4_data_count(P) interface returns the number of columns in the
** current row of the result set of [prepared statement] P.
** ^If prepared statement P does not have results ready to return
** (via calls to the [sqlite4_column_int | sqlite4_column_*()] of
** interfaces) then sqlite4_data_count(P) returns 0.
** ^The sqlite4_data_count(P) routine also returns 0 if P is a NULL pointer.
** ^The sqlite4_data_count(P) routine returns 0 if the previous call to
** [sqlite4_step](P) returned [SQLITE4_DONE].  ^The sqlite4_data_count(P)
** will return non-zero if previous call to [sqlite4_step](P) returned
** [SQLITE4_ROW], except in the case of the [PRAGMA incremental_vacuum]
** where it always returns zero since each step of that multi-step
** pragma returns 0 columns of data.
**
** See also: [sqlite4_column_count()]
*/
SQLITE4_API int sqlite4_data_count(sqlite4_stmt *pStmt);

/*
** CAPIREF: Fundamental Datatypes
** KEYWORDS: SQLITE4_TEXT
**
** ^(Every value in SQLite has one of five fundamental datatypes:
**
** <ul>
** <li> 64-bit signed integer
** <li> 64-bit IEEE floating point number
** <li> string
** <li> BLOB
** <li> NULL
** </ul>)^
**
** These constants are codes for each of those types.
*/
#define SQLITE4_INTEGER  1
#define SQLITE4_FLOAT    2
#define SQLITE4_TEXT     3
#define SQLITE4_BLOB     4
#define SQLITE4_NULL     5

/*
** CAPIREF: Result Values From A Query
** KEYWORDS: {column access functions}
**
** These routines form the "result set" interface.
**
** ^These routines return information about a single column of the current
** result row of a query.  ^In every case the first argument is a pointer
** to the [prepared statement] that is being evaluated (the [sqlite4_stmt*]
** that was returned from [sqlite4_prepare()].
** and the second argument is the index of the column for which information
** should be returned. ^The leftmost column of the result set has the index 0.
** ^The number of columns in the result can be determined using
** [sqlite4_column_count()].
**
** If the SQL statement does not currently point to a valid row, or if the
** column index is out of range, the result is undefined.
** These routines may only be called when the most recent call to
** [sqlite4_step()] has returned [SQLITE4_ROW] and neither
** [sqlite4_reset()] nor [sqlite4_finalize()] have been called subsequently.
** If any of these routines are called after [sqlite4_reset()] or
** [sqlite4_finalize()] or after [sqlite4_step()] has returned
** something other than [SQLITE4_ROW], the results are undefined.
** If [sqlite4_step()] or [sqlite4_reset()] or [sqlite4_finalize()]
** are called from a different thread while any of these routines
** are pending, then the results are undefined.
**
** ^The sqlite4_column_type() routine returns the
** [SQLITE4_INTEGER | datatype code] for the initial data type
** of the result column.  ^The returned value is one of [SQLITE4_INTEGER],
** [SQLITE4_FLOAT], [SQLITE4_TEXT], [SQLITE4_BLOB], or [SQLITE4_NULL].
** The value
** returned by sqlite4_column_type() is only meaningful if no type
** conversions have occurred as described below.  After a type conversion,
** the value returned by sqlite4_column_type() is undefined.  Future
** versions of SQLite may change the behavior of sqlite4_column_type()
** following a type conversion.
**
** ^The values returned by [sqlite4_column_bytes()] and 
** [sqlite4_column_bytes16()] do not include the zero terminators at the end
** of the string.  ^For clarity: the values returned by
** [sqlite4_column_bytes()] and [sqlite4_column_bytes16()] are the number of
** bytes in the string, not the number of characters.
**
** The sqlite4_column_text(), sqlite4_column_text16() and sqlite4_column_blob()
** functions return a pointer to a buffer containing the text or blob value.
** If the third parameter passed is not NULL, then the location it points to 
** is set to the number of bytes of text or blob content in the returned 
** buffer. To be clear, for a text value, the output parameter is set to the
** number of bytes of content, not the number of characters.
**
** ^Strings returned by sqlite4_column_text() and sqlite4_column_text16(),
** even empty strings, are always zero-terminated. The terminator byte or 
** bytes is not included in the number of bytes of content returned via
** the output parameter. The return value from sqlite4_column_blob() for 
** a zero-length BLOB is a NULL pointer. ^The pointers returned are valid 
** until a type conversion occurs (see below), or until [sqlite4_step()], 
** [sqlite4_reset()] or [sqlite4_finalize()] is called. ^The memory space 
** used to hold strings and BLOBs is freed automatically.  Do <b>not</b> 
** pass the pointers returned [sqlite4_column_blob()], 
** [sqlite4_column_text()], etc. into [sqlite4_free()].
**
** ^The object returned by [sqlite4_column_value()] is an
** [unprotected sqlite4_value] object.  An unprotected sqlite4_value object
** may only be used with [sqlite4_bind_value()] and [sqlite4_result_value()].
** If the [unprotected sqlite4_value] object returned by
** [sqlite4_column_value()] is used in any other way, including calls
** to routines like [sqlite4_value_int()], [sqlite4_value_text()],
** or [sqlite4_value_bytes()], then the behavior is undefined.
**
** These routines attempt to convert the value where appropriate.  ^For
** example, if the internal representation is FLOAT and a text result
** is requested, [sqlite4_snprintf()] is used internally to perform the
** conversion automatically.  ^(The following table details the conversions
** that are applied:
**
** <blockquote>
** <table border="1">
** <tr><th> Internal<br>Type <th> Requested<br>Type <th>  Conversion
**
** <tr><td>  NULL    <td> INTEGER   <td> Result is 0
** <tr><td>  NULL    <td>  FLOAT    <td> Result is 0.0
** <tr><td>  NULL    <td>   TEXT    <td> Result is NULL pointer
** <tr><td>  NULL    <td>   BLOB    <td> Result is NULL pointer
** <tr><td> INTEGER  <td>  FLOAT    <td> Convert from integer to float
** <tr><td> INTEGER  <td>   TEXT    <td> ASCII rendering of the integer
** <tr><td> INTEGER  <td>   BLOB    <td> Same as INTEGER->TEXT
** <tr><td>  FLOAT   <td> INTEGER   <td> Convert from float to integer
** <tr><td>  FLOAT   <td>   TEXT    <td> ASCII rendering of the float
** <tr><td>  FLOAT   <td>   BLOB    <td> Same as FLOAT->TEXT
** <tr><td>  TEXT    <td> INTEGER   <td> Use atoi()
** <tr><td>  TEXT    <td>  FLOAT    <td> Use atof()
** <tr><td>  TEXT    <td>   BLOB    <td> No change
** <tr><td>  BLOB    <td> INTEGER   <td> Convert to TEXT then use atoi()
** <tr><td>  BLOB    <td>  FLOAT    <td> Convert to TEXT then use atof()
** <tr><td>  BLOB    <td>   TEXT    <td> Add a zero terminator if needed
** </table>
** </blockquote>)^
**
** The table above makes reference to standard C library functions atoi()
** and atof().  SQLite does not really use these functions.  It has its
** own equivalent internal routines.  The atoi() and atof() names are
** used in the table for brevity and because they are familiar to most
** C programmers.
**
** Note that when type conversions occur, pointers returned by prior
** calls to sqlite4_column_blob(), sqlite4_column_text(), and/or
** sqlite4_column_text16() may be invalidated.
** Type conversions and pointer invalidations might occur
** in the following cases:
**
** <ul>
** <li> The initial content is a BLOB and sqlite4_column_text() or
**      sqlite4_column_text16() is called.  A zero-terminator might
**      need to be added to the string.
** <li> The initial content is UTF-8 text and sqlite4_column_text16() is 
**      called. The content must be converted to UTF-16.
** <li> The initial content is UTF-16 text and sqlite4_column_text() is 
**      called.  The content must be converted to UTF-8.
** </ul>
**
** ^Conversions between UTF-16be and UTF-16le are always done in place and do
** not invalidate a prior pointer, though of course the content of the buffer
** that the prior pointer references will have been modified.  Other kinds
** of conversion are done in place when it is possible, but sometimes they
** are not possible and in those cases prior pointers are invalidated.
**
** ^(If a memory allocation error occurs during the evaluation of any
** of these routines, a default value is returned.  The default value
** is either the integer 0, the floating point number 0.0, or a NULL
** pointer.  Subsequent calls to [sqlite4_errcode()] will return
** [SQLITE4_NOMEM].)^
*/
SQLITE4_API const void *sqlite4_column_blob(sqlite4_stmt*, int iCol, int *pnByte);
SQLITE4_API double sqlite4_column_double(sqlite4_stmt*, int iCol);
SQLITE4_API int sqlite4_column_int(sqlite4_stmt*, int iCol);
SQLITE4_API sqlite4_int64 sqlite4_column_int64(sqlite4_stmt*, int iCol);
SQLITE4_API const char *sqlite4_column_text(sqlite4_stmt*, int iCol, int *pnByte);
SQLITE4_API const void *sqlite4_column_text16(sqlite4_stmt*, int iCol, int *pnByte);
SQLITE4_API int sqlite4_column_type(sqlite4_stmt*, int iCol);
SQLITE4_API sqlite4_value *sqlite4_column_value(sqlite4_stmt*, int iCol);

/*
** CAPIREF: Destroy A Prepared Statement Object
**
** ^The sqlite4_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors
** or if the statement is never been evaluated, then sqlite4_finalize() returns
** SQLITE4_OK.  ^If the most recent evaluation of statement S failed, then
** sqlite4_finalize(S) returns the appropriate [error code] or
** [extended error code].
**
** ^The sqlite4_finalize(S) routine can be called at any point during
** the life cycle of [prepared statement] S:
** before statement S is ever evaluated, after
** one or more calls to [sqlite4_reset()], or after any call
** to [sqlite4_step()] regardless of whether or not the statement has
** completed execution.
**
** ^Invoking sqlite4_finalize() on a NULL pointer is a harmless no-op.
**
** The application must finalize every [prepared statement] in order to avoid
** resource leaks.  It is a grievous error for the application to try to use
** a prepared statement after it has been finalized.  Any use of a prepared
** statement after it has been finalized can result in undefined and
** undesirable behavior such as segfaults and heap corruption.
*/
SQLITE4_API int sqlite4_finalize(sqlite4_stmt *pStmt);

/*
** CAPIREF: Reset A Prepared Statement Object
**
** The sqlite4_reset() function is called to reset a [prepared statement]
** object back to its initial state, ready to be re-executed.
** ^Any SQL statement variables that had values bound to them using
** the [sqlite4_bind_blob | sqlite4_bind_*() API] retain their values.
** Use [sqlite4_clear_bindings()] to reset the bindings.
**
** ^The [sqlite4_reset(S)] interface resets the [prepared statement] S
** back to the beginning of its program.
**
** ^If the most recent call to [sqlite4_step(S)] for the
** [prepared statement] S returned [SQLITE4_ROW] or [SQLITE4_DONE],
** or if [sqlite4_step(S)] has never before been called on S,
** then [sqlite4_reset(S)] returns [SQLITE4_OK].
**
** ^If the most recent call to [sqlite4_step(S)] for the
** [prepared statement] S indicated an error, then
** [sqlite4_reset(S)] returns an appropriate [error code].
**
** ^The [sqlite4_reset(S)] interface does not change the values
** of any [sqlite4_bind_blob|bindings] on the [prepared statement] S.
*/
SQLITE4_API int sqlite4_reset(sqlite4_stmt *pStmt);

/*
** CAPIREF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routine}
** KEYWORDS: {application-defined SQL function}
** KEYWORDS: {application-defined SQL functions}
**
** ^This function is used to add new SQL scalar or aggregate functions. 
**
** ^The first parameter is the [database connection] to which the SQL
** function is to be added.  ^If an application uses more than one database
** connection then application-defined SQL functions must be added
** to each database connection separately.
**
** ^The second parameter is the name of the SQL function to be created or
** redefined.  ^The length of the name is limited to 255 bytes in a UTF-8
** representation, exclusive of the zero-terminator.  ^Note that the name
** length limit is in bytes, not characters. ^Any attempt to create a 
** function with a longer name will result in [SQLITE4_MISUSE] being returned.
**
** ^The third parameter (nArg) is the number of arguments that the SQL 
** function or aggregate takes. ^If this parameter is -1, then the SQL 
** function or aggregate may take any number of arguments between 0 and 
** the limit set by [sqlite4_limit]([SQLITE4_LIMIT_FUNCTION_ARG]).  If 
** the third parameter is less than -1 or greater than 127 then the 
** behavior is undefined.
**
** ^(The fourth parameter is a context pointer. The implementation of the
** function can gain access to this pointer using [sqlite4_context_appdata()].)^
**
** ^The fifth, sixth and seventh parameters, xFunc, xStep and xFinal, are
** pointers to C-language functions that implement the SQL function or
** aggregate. ^A scalar SQL function requires an implementation of the xFunc
** callback only; NULL pointers must be passed as the xStep and xFinal
** parameters. ^An aggregate SQL function requires an implementation of xStep
** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing
** SQL function or aggregate, pass NULL pointers for all three function
** callbacks.
**
** ^(If the eighth parameter is not NULL, then it is destructor for the 
** application data pointer. The destructor is invoked when the function 
** is deleted, either by being overloaded or when the database connection 
** closes.)^ ^The destructor is also invoked if the call to
** sqlite4_create_function() fails. ^When the destructor callback 
** is invoked, it is passed a single argument which is a copy of the 
** application data pointer which was the fifth parameter to 
** sqlite4_create_function().
**
** ^It is permitted to register multiple implementations of the same
** functions with the same name but differing numbers of arguments. ^SQLite 
** will use the implementation that most closely matches the way in which the
** SQL function is used.  ^A function implementation with a non-negative
** nArg parameter is a better match than a function implementation with
** a negative nArg.
**
** ^Built-in functions may be overloaded by new application-defined functions.
**
** ^An application-defined function is permitted to call other
** SQLite interfaces.  However, such calls must not
** close the database connection nor finalize or reset the prepared
** statement in which the function is running.
*/
SQLITE4_API int sqlite4_create_function(
  sqlite4 *db,
  const char *zFunctionName,
  int nArg,
  void *pApp,
  void (*xFunc)(sqlite4_context*,int,sqlite4_value**),
  void (*xStep)(sqlite4_context*,int,sqlite4_value**),
  void (*xFinal)(sqlite4_context*),
  void(*xDestroy)(void*)
);

/*
** CAPIREF: Text Encodings
**
** These constant define integer codes that represent the various
** text encodings supported by SQLite.
*/
#define SQLITE4_UTF8           1
#define SQLITE4_UTF16LE        2
#define SQLITE4_UTF16BE        3
#define SQLITE4_UTF16          4    /* Use native byte order */

/*
** CAPIREF: Obtaining SQL Function Parameter Values
**
** The C-language implementation of SQL functions and aggregates uses
** this set of interface routines to access the parameter values on
** the function or aggregate.
**
** The xFunc (for scalar functions) or xStep (for aggregates) parameters
** to [sqlite4_create_function()] and [sqlite4_create_function16()]
** define callbacks that implement the SQL functions and aggregates.
** The 3rd parameter to these callbacks is an array of pointers to
** [protected sqlite4_value] objects.  There is one [sqlite4_value] object for
** each parameter to the SQL function.  These routines are used to
** extract values from the [sqlite4_value] objects.
**
** These routines work only with [protected sqlite4_value] objects.
** Any attempt to use these routines on an [unprotected sqlite4_value]
** object results in undefined behavior.
**
** ^These routines work just like the corresponding [column access functions]
** except that  these routines take a single [protected sqlite4_value] object
** pointer instead of a [sqlite4_stmt*] pointer and an integer column number.
**
** ^The sqlite4_value_text16() interface extracts a UTF-16 string
** in the native byte-order of the host machine.  ^The
** sqlite4_value_text16be() and sqlite4_value_text16le() interfaces
** extract UTF-16 strings as big-endian and little-endian respectively.
**
** ^(The sqlite4_value_numeric_type() interface attempts to apply
** numeric affinity to the value.  This means that an attempt is
** made to convert the value to an integer or floating point.  If
** such a conversion is possible without loss of information (in other
** words, if the value is a string that looks like a number)
** then the conversion is performed.  Otherwise no conversion occurs.
** The [SQLITE4_INTEGER | datatype] after conversion is returned.)^
**
** Please pay particular attention to the fact that the pointer returned
** from [sqlite4_value_blob()], [sqlite4_value_text()], or
** [sqlite4_value_text16()] can be invalidated by a subsequent call to
** [sqlite4_value_text()] or [sqlite4_value_text16()].
**
** These routines must be called from the same thread as
** the SQL function that supplied the [sqlite4_value*] parameters.
*/
SQLITE4_API const void *sqlite4_value_blob(sqlite4_value*, int *pnByte);
SQLITE4_API double sqlite4_value_double(sqlite4_value*);
SQLITE4_API int sqlite4_value_int(sqlite4_value*);
SQLITE4_API sqlite4_int64 sqlite4_value_int64(sqlite4_value*);
SQLITE4_API const char *sqlite4_value_text(sqlite4_value*, int *pnByte);
SQLITE4_API const void *sqlite4_value_text16(sqlite4_value*, int *pnByte);
SQLITE4_API const void *sqlite4_value_text16le(sqlite4_value*, int *pnByte);
SQLITE4_API const void *sqlite4_value_text16be(sqlite4_value*, int *pnByte);
SQLITE4_API int sqlite4_value_type(sqlite4_value*);
SQLITE4_API int sqlite4_value_numeric_type(sqlite4_value*);
SQLITE4_API sqlite4_num sqlite4_value_num(sqlite4_value*);

/*
** CAPIREF: Obtain Aggregate Function Context
**
** Implementations of aggregate SQL functions use this
** routine to allocate memory for storing their state.
**
** ^The first time the sqlite4_aggregate_context(C,N) routine is called 
** for a particular aggregate function, SQLite
** allocates N of memory, zeroes out that memory, and returns a pointer
** to the new memory. ^On second and subsequent calls to
** sqlite4_aggregate_context() for the same aggregate function instance,
** the same buffer is returned.  Sqlite3_aggregate_context() is normally
** called once for each invocation of the xStep callback and then one
** last time when the xFinal callback is invoked.  ^(When no rows match
** an aggregate query, the xStep() callback of the aggregate function
** implementation is never called and xFinal() is called exactly once.
** In those cases, sqlite4_aggregate_context() might be called for the
** first time from within xFinal().)^
**
** ^The sqlite4_aggregate_context(C,N) routine returns a NULL pointer if N is
** less than or equal to zero or if a memory allocate error occurs.
**
** ^(The amount of space allocated by sqlite4_aggregate_context(C,N) is
** determined by the N parameter on first successful call.  Changing the
** value of N in subsequent call to sqlite4_aggregate_context() within
** the same aggregate function instance will not resize the memory
** allocation.)^
**
** ^SQLite automatically frees the memory allocated by 
** sqlite4_aggregate_context() when the aggregate query concludes.
**
** The first parameter must be a copy of the
** [sqlite4_context | SQL function context] that is the first parameter
** to the xStep or xFinal callback routine that implements the aggregate
** function.
**
** This routine must be called from the same thread in which
** the aggregate SQL function is running.
*/
SQLITE4_API void *sqlite4_aggregate_context(sqlite4_context*, int nBytes);

/*
** CAPIREF: User Data For Functions
**
** ^The sqlite4_context_appdata() interface returns a copy of
** the pointer that was the pUserData parameter (the 5th parameter)
** passed to the [sqlite4_create_function()] or [sqlite4_create_function16()] 
** call that registered the application defined function.
**
** This routine must be called from the same thread in which the 
** application-defined function is running.
*/
SQLITE4_API void *sqlite4_context_appdata(sqlite4_context*);

/*
** CAPIREF: Database Connection For Functions
**
** ^The sqlite4_context_db_handle() interface returns a copy of
** the pointer to the [database connection] (the 1st parameter)
** of the [sqlite4_create_function()]
** and [sqlite4_create_function16()] routines that originally
** registered the application defined function.
*/
SQLITE4_API sqlite4 *sqlite4_context_db_handle(sqlite4_context*);
SQLITE4_API sqlite4_env *sqlite4_context_env(sqlite4_context*);

/*
** CAPIREF: Function Auxiliary Data
**
** The following two functions may be used by scalar SQL functions to
** associate metadata with argument values. If the same value is passed to
** multiple invocations of the same SQL function during query execution, under
** some circumstances the associated metadata may be preserved. This may
** be used, for example, to add a regular-expression matching scalar
** function. The compiled version of the regular expression is stored as
** metadata associated with the SQL value passed as the regular expression
** pattern.  The compiled regular expression can be reused on multiple
** invocations of the same function so that the original pattern string
** does not need to be recompiled on each invocation.
**
** ^The sqlite4_auxdata_fetch() interface returns a pointer to the metadata
** associated by the sqlite4_auxdata_store() function with the Nth argument
** value to the application-defined function. ^If no metadata has been ever
** been set for the Nth argument of the function, or if the corresponding
** function parameter has changed since the meta-data was set,
** then sqlite4_auxdata_fetch() returns a NULL pointer.
**
** ^The sqlite4_auxdata_store() interface saves the metadata
** pointed to by its 3rd parameter as the metadata for the N-th
** argument of the application-defined function.  Subsequent
** calls to sqlite4_auxdata_fetch() might return this data, if it has
** not been destroyed.
** ^If it is not NULL, SQLite will invoke the destructor
** function given by the 4th parameter to sqlite4_auxdata_store() on
** the metadata when the corresponding function parameter changes
** or when the SQL statement completes, whichever comes first.
**
** SQLite is free to call the destructor and drop metadata on any
** parameter of any function at any time.  ^The only guarantee is that
** the destructor will be called before the metadata is dropped.
**
** ^(In practice, metadata is preserved between function calls for
** expressions that are constant at compile time. This includes literal
** values and [parameters].)^
**
** These routines must be called from the same thread in which
** the SQL function is running.
*/
SQLITE4_API void *sqlite4_auxdata_fetch(sqlite4_context*, int N);
SQLITE4_API void sqlite4_auxdata_store(sqlite4_context*, int N, void*,
                         void (*)(void*,void*),void*);


/*
** CAPIREF: Constants Defining Special Destructor Behavior
**
** These are special values for the destructor that is passed in as the
** final argument to routines like [sqlite4_result_blob()].  ^If the destructor
** argument is SQLITE4_STATIC, it means that the content pointer is constant
** and will never change.  It does not need to be destroyed.  ^The
** SQLITE4_TRANSIENT value means that the content will likely change in
** the near future and that SQLite should make its own private copy of
** the content before returning.
**
** The typedef is necessary to work around problems in certain
** C++ compilers.  See ticket #2191.
*/
typedef void (*sqlite4_destructor_type)(void*,void*);
SQLITE4_API void sqlite4_dynamic(void*,void*);
#define SQLITE4_STATIC      ((sqlite4_destructor_type)0)
#define SQLITE4_TRANSIENT   ((sqlite4_destructor_type)-1)
#define SQLITE4_DYNAMIC     (sqlite4_dynamic)


/*
** CAPIREF: Setting The Result Of An SQL Function
**
** These routines are used by the xFunc or xFinal callbacks that
** implement SQL functions and aggregates.  See
** [sqlite4_create_function()] and [sqlite4_create_function16()]
** for additional information.
**
** These functions work very much like the [parameter binding] family of
** functions used to bind values to host parameters in prepared statements.
** Refer to the [SQL parameter] documentation for additional information.
**
** ^The sqlite4_result_blob() interface sets the result from
** an application-defined function to be the BLOB whose content is pointed
** to by the second parameter and which is N bytes long where N is the
** third parameter.
**
** ^The sqlite4_result_double() interface sets the result from
** an application-defined function to be a floating point value specified
** by its 2nd argument.
**
** ^The sqlite4_result_error() and sqlite4_result_error16() functions
** cause the implemented SQL function to throw an exception.
** ^SQLite uses the string pointed to by the
** 2nd parameter of sqlite4_result_error() or sqlite4_result_error16()
** as the text of an error message.  ^SQLite interprets the error
** message string from sqlite4_result_error() as UTF-8. ^SQLite
** interprets the string from sqlite4_result_error16() as UTF-16 in native
** byte order.  ^If the third parameter to sqlite4_result_error()
** or sqlite4_result_error16() is negative then SQLite takes as the error
** message all text up through the first zero character.
** ^If the third parameter to sqlite4_result_error() or
** sqlite4_result_error16() is non-negative then SQLite takes that many
** bytes (not characters) from the 2nd parameter as the error message.
** ^The sqlite4_result_error() and sqlite4_result_error16()
** routines make a private copy of the error message text before
** they return.  Hence, the calling function can deallocate or
** modify the text after they return without harm.
** ^The sqlite4_result_error_code() function changes the error code
** returned by SQLite as a result of an error in a function.  ^By default,
** the error code is SQLITE4_ERROR.
** ^A subsequent call to sqlite4_result_error()
** or sqlite4_result_error16() resets the error code to SQLITE4_ERROR.
**
** ^The sqlite4_result_toobig() interface causes SQLite to throw an error
** indicating that a string or BLOB is too long to represent.
**
** ^The sqlite4_result_nomem() interface causes SQLite to throw an error
** indicating that a memory allocation failed.
**
** ^The sqlite4_result_int() interface sets the return value
** of the application-defined function to be the 32-bit signed integer
** value given in the 2nd argument.
** ^The sqlite4_result_int64() interface sets the return value
** of the application-defined function to be the 64-bit signed integer
** value given in the 2nd argument.
**
** ^The sqlite4_result_null() interface sets the return value
** of the application-defined function to be NULL.
**
** ^The sqlite4_result_text(), sqlite4_result_text16(),
** sqlite4_result_text16le(), and sqlite4_result_text16be() interfaces
** set the return value of the application-defined function to be
** a text string which is represented as UTF-8, UTF-16 native byte order,
** UTF-16 little endian, or UTF-16 big endian, respectively.
** ^SQLite takes the text result from the application from
** the 2nd parameter of the sqlite4_result_text* interfaces.
** ^If the 3rd parameter to the sqlite4_result_text* interfaces
** is negative, then SQLite takes result text from the 2nd parameter
** through the first zero character.
** ^If the 3rd parameter to the sqlite4_result_text* interfaces
** is non-negative, then as many bytes (not characters) of the text
** pointed to by the 2nd parameter are taken as the application-defined
** function result.  If the 3rd parameter is non-negative, then it
** must be the byte offset into the string where the NUL terminator would
** appear if the string where NUL terminated.  If any NUL characters occur
** in the string at a byte offset that is less than the value of the 3rd
** parameter, then the resulting string will contain embedded NULs and the
** result of expressions operating on strings with embedded NULs is undefined.
** ^If the 4th parameter to the sqlite4_result_text* interfaces
** or sqlite4_result_blob is a non-NULL pointer, then SQLite calls that
** function as the destructor on the text or BLOB result when it has
** finished using that result.
** ^If the 4th parameter to the sqlite4_result_text* interfaces or to
** sqlite4_result_blob is the special constant SQLITE4_STATIC, then SQLite
** assumes that the text or BLOB result is in constant space and does not
** copy the content of the parameter nor call a destructor on the content
** when it has finished using that result.
** ^If the 4th parameter to the sqlite4_result_text* interfaces
** or sqlite4_result_blob is the special constant SQLITE4_TRANSIENT
** then SQLite makes a copy of the result into space obtained from
** from [sqlite4_malloc()] before it returns.
**
** ^The sqlite4_result_value() interface sets the result of
** the application-defined function to be a copy the
** [unprotected sqlite4_value] object specified by the 2nd parameter.  ^The
** sqlite4_result_value() interface makes a copy of the [sqlite4_value]
** so that the [sqlite4_value] specified in the parameter may change or
** be deallocated after sqlite4_result_value() returns without harm.
** ^A [protected sqlite4_value] object may always be used where an
** [unprotected sqlite4_value] object is required, so either
** kind of [sqlite4_value] object can be used with this interface.
**
** If these routines are called from within the different thread
** than the one containing the application-defined function that received
** the [sqlite4_context] pointer, the results are undefined.
*/
SQLITE4_API void sqlite4_result_blob(sqlite4_context*, const void*, int,
                         void(*)(void*,void*),void*);
SQLITE4_API void sqlite4_result_double(sqlite4_context*, double);
SQLITE4_API void sqlite4_result_error(sqlite4_context*, const char*, int);
SQLITE4_API void sqlite4_result_error16(sqlite4_context*, const void*, int);
SQLITE4_API void sqlite4_result_error_toobig(sqlite4_context*);
SQLITE4_API void sqlite4_result_error_nomem(sqlite4_context*);
SQLITE4_API void sqlite4_result_error_code(sqlite4_context*, int);
SQLITE4_API void sqlite4_result_int(sqlite4_context*, int);
SQLITE4_API void sqlite4_result_int64(sqlite4_context*, sqlite4_int64);
SQLITE4_API void sqlite4_result_null(sqlite4_context*);
SQLITE4_API void sqlite4_result_num(sqlite4_context*, sqlite4_num);
SQLITE4_API void sqlite4_result_text(sqlite4_context*, const char*, int,
                         void(*)(void*,void*),void*);
SQLITE4_API void sqlite4_result_text16(sqlite4_context*, const void*, int,
                           void(*)(void*,void*),void*);
SQLITE4_API void sqlite4_result_text16le(sqlite4_context*, const void*, int,
                             void(*)(void*,void*),void*);
SQLITE4_API void sqlite4_result_text16be(sqlite4_context*, const void*, int,
                             void(*)(void*,void*),void*);
SQLITE4_API void sqlite4_result_value(sqlite4_context*, sqlite4_value*);

/*
** CAPIREF: Define New Collation Sequences
**
** ^This function adds, removes, or modifies a [collation] associated
** with the [database connection] specified as the first argument.
**
** ^The name of the collation is passed as the second argument. Collation
** names are case-independent, any two names that are equal according 
** to [sqlite4_strnicmp()] are considered to refer to the same collation.
**
** ^The third argument, pArg, is an application data pointer. A copy of
** this pointer is passed as the first argument to the two collation
** callback functions whenever they are invoked.
**
** The fourth argument passed to sqlite4_create_collation() is a comparison
** routine. The two sqlite4_value* arguments passed always point to objects
** containing values of type TEXT. The final argument (type "int*") is an
** output parameter. Assuming no error occurs, the callback implementation
** is expected to set the output parameter to a negative value, zero, or
** a positive value if the first sqlite4_value argument is smaller, equal
** to, or larger than the second, respectively, before returning SQLITE4_OK.
** Or, if an error does occur, an SQLite error code should be returned.
** The value of the output paramete is ignored by SQLite if any error occurs.
**
** The fifth argument, xMakeKey, is a pointer to a function that generates
** a sort key based on the sqlite4_value* passed as its second parameter.
** The second parameter always points to an object containing a value of
** type text. The fifth parameter passed to xMakeKey is an output parameter.
** Assuming no error occurs, the xMakeKey implementation should set the 
** value of the output parameter to the size of the sort key in bytes and
** return SQLITE4_OK. Or, if an error does occur, an error code should be
** returned. The output parameter is ignored in this case.
**
** The third and fourth parameters passed to each invocation of the xMakeKey
** function are the size of and a pointer to an output buffer, respectively.
** If the output buffer is large enough to store the entire sort key, then
** the xMakeKey implementation should populate it with the sort key value
** before returning. Otherwise, if it is not large enough, SQLite will
** detect this and invoke the xMakeKey callback a second time with a larger
** buffer.
**
** The xCompare and xMakeKey callbacks must return consistent results.
** Specifically, according to xCompare, for any text values A, B and C:
**
** <ol>
**   <li> If A==B then B==A.
**   <li> If A==B and B==C then A==C.
**   <li> If A&lt;B then B&gt;A.
**   <li> If A&lt;B and B&lt;C then A&lt;C.
** </ol>
**
** Additionally, for two text values A and B where A is smaller than, equal 
** to, or larger than B, the sort key of A must also be smaller than, equal
** to, or larger than the sort key of B, respectively. Sort keys are 
** compared using memcmp(). If one sort key is a prefix of another, it is
** considered to be smaller.
**
** If a collation does not behave as described above, the behaviour of
** SQLite is undefined.
**
** If it is not NULL, the final argument passed to sqlite4_create_collation()
** is a pointer to a destructor function. The destructor function is invoked
** to indicate that SQLite is no longer using the collation, either because
** it has been replaced by a new collation of the same name or because the
** database connection is being closed. The caller should use the destructor
** function to dispose of any dynamically allocated resources associated with
** the collation. The destructor function is invoked exactly once for each
** call to sqlite4_create_collation.
**
** If the sqlite4_create_collation call fails for any reason, an error code
** is returned and the collation sequence is not registered with the database
** handle. If a destructor function was provided, then in this case it is
** invoked before the sqlite4_create_collation() function returns.
**
** See also:  [sqlite4_collation_needed()] and [sqlite4_collation_needed16()].
*/
SQLITE4_API int sqlite4_create_collation(
  sqlite4*, 
  const char *zName, 
  void *pArg,
  int(*xCompare)(void*, sqlite4_value*, sqlite4_value*, int*),
  int(*xMakeKey)(void*, sqlite4_value*, int, void*, int*),
  void(*xDestroy)(void*)
);

/*
** CAPIREF: Collation Needed Callbacks
**
** This function is used to register a callback that is invoked by
** the SQL compiler whenever an undefined collation sequence is defined.
** If the callback registers the required collation sequence with the
** database handle by calling [sqlite4_create_collation]() before returning, 
** then compilation of the statement proceeds. Otherwise, statement 
** compilation fails and an error is returned to the user.
**
** Each database handle may have at most one collation needed callback
** registered at a time. If this function is called on a database handle
** for which a collation needed callback has already been registered, the
** new callback replaces the old.
**
** The first argument to this function is the database handle to register
** the callback with. The second is a context pointer, a copy of which is
** passed as the first argument to the collation needed callback each time 
** it is invoked. The third argument is a pointer to the collation needed
** callback function to register.
**
** When the collation needed callback is invoked, the first argument is
** a copy of the context pointer passed to sqlite4_collation_needed(). The
** second is the database handle with which the callback should, if 
** possible, register the required collation. The third argument is a 
** pointer to a nul-terminated string containing the name of the required
** collation.
**
** If it is not NULL, the fourth argument passed to sqlite4_collation_needed()
** is a destructor function to be invoked when the callback is no longer
** required. In other words, when the database handle is closed or
** when the callback is overridden by a subsequent call to
** sqlite4_collation_needed().
**
** If an error occurs within this function, an error code is returned and
** the collation needed function is not registered with the database handle. 
** In this case the destructor function, if any, is invoked before the
** call to sqlite4_collation_needed() returns. If no error occurs, SQLITE4_OK
** is returned.
*/
SQLITE4_API int sqlite4_collation_needed(
  sqlite4*, 
  void*,
  void(*xFactory)(void*,sqlite4*,const char*),
  void(*xDestroy)(void*)
);

/*
** CAPIREF: Suspend Execution For A Short Time
**
** The sqlite4_sleep() function causes the current thread to suspend execution
** for at least a number of milliseconds specified in its parameter.
**
** If the operating system does not support sleep requests with
** millisecond time resolution, then the time will be rounded up to
** the nearest second. The number of milliseconds of sleep actually
** requested from the operating system is returned.
**
** ^SQLite implements this interface by calling the xSleep()
** method of the default [sqlite4_vfs] object.  If the xSleep() method
** of the default VFS is not implemented correctly, or not implemented at
** all, then the behavior of sqlite4_sleep() may deviate from the description
** in the previous paragraphs.
*/
SQLITE4_API int sqlite4_sleep(int);

/*
** CAPIREF: Test For An Open Transaction
** KEYWORDS: {autocommit mode}
**
** ^The sqlite4_db_transaction_status() interface returns non-zero if
** the database connection passed as the only argument is currently within
** an explicitly started transaction. An explicit transaction is opened
** using a [BEGIN] command, and usually concluded using a [COMMIT] or
** [ROLLBACK].
**
** If certain kinds of errors occur on a statement within an explicit
** transaction (errors including [SQLITE4_FULL], [SQLITE4_IOERR],
** [SQLITE4_NOMEM], [SQLITE4_BUSY], and [SQLITE4_INTERRUPT]) then the
** transaction might be rolled back automatically.  The only way to
** find out whether SQLite automatically rolled back the transaction after
** an error is to use this function.
**
** If another thread opens or closes a transaction on this database 
** connection while this routine is running, then the return value is 
** undefined.
*/
SQLITE4_API int sqlite4_db_transaction_status(sqlite4*);

/*
** CAPIREF: Find The Database Handle Of A Prepared Statement
**
** ^The sqlite4_db_handle interface returns the [database connection] handle
** to which a [prepared statement] belongs.  ^The [database connection]
** returned by sqlite4_db_handle is the same [database connection]
** that was the first argument
** to the [sqlite4_prepare()] call (or its variants) that was used to
** create the statement in the first place.
*/
SQLITE4_API sqlite4 *sqlite4_db_handle(sqlite4_stmt*);

/*
** CAPIREF: Return The Filename For A Database Connection
**
** ^The sqlite4_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D.  ^The main database file
** has the name "main".  If there is no attached database N on the database
** connection D, or if database N is a temporary or in-memory database, then
** a NULL pointer is returned.
**
** ^The filename returned by this function is the output of the
** xFullPathname method of the [VFS].  ^In other words, the filename
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
*/
SQLITE4_API const char *sqlite4_db_filename(sqlite4 *db, const char *zDbName);

/*
** CAPIREF: Find the next prepared statement
**
** ^This interface returns a pointer to the next [prepared statement] after
** pStmt associated with the [database connection] pDb.  ^If pStmt is NULL
** then this interface returns a pointer to the first prepared statement
** associated with the database connection pDb.  ^If no prepared statement
** satisfies the conditions of this routine, it returns NULL.
**
** The [database connection] pointer D in a call to
** [sqlite4_next_stmt(D,S)] must refer to an open database
** connection and in particular must not be a NULL pointer.
*/
SQLITE4_API sqlite4_stmt *sqlite4_next_stmt(sqlite4 *pDb, sqlite4_stmt *pStmt);

/*
** CAPIREF: Free Memory Used By A Database Connection
**
** ^The sqlite4_db_release_memory(D) interface attempts to free as much heap
** memory as possible from database connection D.
*/
SQLITE4_API int sqlite4_db_release_memory(sqlite4*);

/*
** CAPIREF: Extract Metadata About A Column Of A Table
**
** ^This routine returns metadata about a specific column of a specific
** database table accessible using the [database connection] handle
** passed as the first function argument.
**
** ^The column is identified by the second, third and fourth parameters to
** this function. ^The second parameter is either the name of the database
** (i.e. "main", "temp", or an attached database) containing the specified
** table or NULL. ^If it is NULL, then all attached databases are searched
** for the table using the same algorithm used by the database engine to
** resolve unqualified table references.
**
** ^The third and fourth parameters to this function are the table and column
** name of the desired column, respectively. Neither of these parameters
** may be NULL.
**
** ^Metadata is returned by writing to the memory locations passed as the 5th
** and subsequent parameters to this function. ^Any of these arguments may be
** NULL, in which case the corresponding element of metadata is omitted.
**
** ^(<blockquote>
** <table border="1">
** <tr><th> Parameter <th> Output<br>Type <th>  Description
**
** <tr><td> 5th <td> const char* <td> Data type
** <tr><td> 6th <td> const char* <td> Name of default collation sequence
** <tr><td> 7th <td> int         <td> True if column has a NOT NULL constraint
** <tr><td> 8th <td> int         <td> True if column is part of the PRIMARY KEY
** <tr><td> 9th <td> int         <td> True if column is [AUTOINCREMENT]
** </table>
** </blockquote>)^
**
** ^The memory pointed to by the character pointers returned for the
** declaration type and collation sequence is valid only until the next
** call to any SQLite API function.
**
** ^If the specified table is actually a view, an [error code] is returned.
**
** ^If the specified column is "rowid", "oid" or "_rowid_" and an
** [INTEGER PRIMARY KEY] column has been explicitly declared, then the output
** parameters are set for the explicitly declared column. ^(If there is no
** explicitly declared [INTEGER PRIMARY KEY] column, then the output
** parameters are set as follows:
**
** <pre>
**     data type: "INTEGER"
**     collation sequence: "BINARY"
**     not null: 0
**     primary key: 1
**     auto increment: 0
** </pre>)^
**
** ^(This function may load one or more schemas from database files. If an
** error occurs during this process, or if the requested table or column
** cannot be found, an [error code] is returned and an error message left
** in the [database connection] (to be retrieved using sqlite4_errmsg()).)^
**
** ^This API is only available if the library was compiled with the
** [SQLITE4_ENABLE_COLUMN_METADATA] C-preprocessor symbol defined.
*/
SQLITE4_API int sqlite4_table_column_metadata(
  sqlite4 *db,                /* Connection handle */
  const char *zDbName,        /* Database name or NULL */
  const char *zTableName,     /* Table name */
  const char *zColumnName,    /* Column name */
  char const **pzDataType,    /* OUTPUT: Declared data type */
  char const **pzCollSeq,     /* OUTPUT: Collation sequence name */
  int *pNotNull,              /* OUTPUT: True if NOT NULL constraint exists */
  int *pPrimaryKey,           /* OUTPUT: True if column part of PK */
  int *pAutoinc               /* OUTPUT: True if column is auto-increment */
);

/*
** CAPIREF: Load An Extension
**
** ^This interface loads an SQLite extension library from the named file.
**
** ^The sqlite4_load_extension() interface attempts to load an SQLite 
** extension library contained in the file zFile.
**
** ^The entry point is zProc. ^zProc may be 0, in which case the name 
** of the entry point defaults to "sqlite4_extension_init". ^The 
** sqlite4_load_extension() interface returns [SQLITE4_OK] on success 
** and [SQLITE4_ERROR] if something goes wrong.
**
** ^Extension loading must be enabled using [sqlite4_enable_load_extension()] 
** prior to calling this API, otherwise an error will be returned.
**
** This function sets the values returned by sqlite4_errcode() and
** sqlite4_errmsg() before returning.
**
** See also the [load_extension() SQL function].
*/
SQLITE4_API int sqlite4_load_extension(
  sqlite4 *db,          /* Load the extension into this database connection */
  const char *zFile,    /* Name of the shared library containing extension */
  const char *zProc     /* Entry point.  Derived from zFile if 0 */
);

/*
** CAPIREF: Enable Or Disable Extension Loading
**
** ^So as not to open security holes in older applications that are
** unprepared to deal with extension loading, and as a means of disabling
** extension loading while evaluating user-entered SQL, the following API
** is provided to turn the [sqlite4_load_extension()] mechanism on and off.
**
** ^Extension loading is off by default. See ticket #1863.
** ^Call the sqlite4_enable_load_extension() routine with onoff==1
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
*/
SQLITE4_API int sqlite4_enable_load_extension(sqlite4 *db, int onoff);

/*
** The interface to the virtual-table mechanism is currently considered
** to be experimental.  The interface might change in incompatible ways.
** If this is a problem for you, do not use the interface at this time.
**
** When the virtual-table mechanism stabilizes, we will declare the
** interface fixed, support it indefinitely, and remove this comment.
*/

/*
** Structures used by the virtual table interface
*/
typedef struct sqlite4_vtab sqlite4_vtab;
typedef struct sqlite4_index_info sqlite4_index_info;
typedef struct sqlite4_vtab_cursor sqlite4_vtab_cursor;
typedef struct sqlite4_module sqlite4_module;

/*
** CAPIREF: Virtual Table Object
** KEYWORDS: sqlite4_module {virtual table module}
**
** This structure, sometimes called a "virtual table module", 
** defines the implementation of a [virtual tables].  
** This structure consists mostly of methods for the module.
**
** ^A virtual table module is created by filling in a persistent
** instance of this structure and passing a pointer to that instance
** to [sqlite4_create_module()] or [sqlite4_create_module_v2()].
** ^The registration remains valid until it is replaced by a different
** module or until the [database connection] closes.  The content
** of this structure must not change while it is registered with
** any database connection.
*/
struct sqlite4_module {
  int iVersion;
  int (*xCreate)(sqlite4*, void *pAux,
               int argc, const char *const*argv,
               sqlite4_vtab **ppVTab, char**);
  int (*xConnect)(sqlite4*, void *pAux,
               int argc, const char *const*argv,
               sqlite4_vtab **ppVTab, char**);
  int (*xBestIndex)(sqlite4_vtab *pVTab, sqlite4_index_info*);
  int (*xDisconnect)(sqlite4_vtab *pVTab);
  int (*xDestroy)(sqlite4_vtab *pVTab);
  int (*xOpen)(sqlite4_vtab *pVTab, sqlite4_vtab_cursor **ppCursor);
  int (*xClose)(sqlite4_vtab_cursor*);
  int (*xFilter)(sqlite4_vtab_cursor*, int idxNum, const char *idxStr,
                int argc, sqlite4_value **argv);
  int (*xNext)(sqlite4_vtab_cursor*);
  int (*xEof)(sqlite4_vtab_cursor*);
  int (*xColumn)(sqlite4_vtab_cursor*, sqlite4_context*, int);
  int (*xRowid)(sqlite4_vtab_cursor*, sqlite4_int64 *pRowid);
  int (*xUpdate)(sqlite4_vtab *, int, sqlite4_value **, sqlite4_int64 *);
  int (*xBegin)(sqlite4_vtab *pVTab);
  int (*xSync)(sqlite4_vtab *pVTab);
  int (*xCommit)(sqlite4_vtab *pVTab);
  int (*xRollback)(sqlite4_vtab *pVTab);
  int (*xFindFunction)(sqlite4_vtab *pVtab, int nArg, const char *zName,
                       void (**pxFunc)(sqlite4_context*,int,sqlite4_value**),
                       void **ppArg);
  int (*xRename)(sqlite4_vtab *pVtab, const char *zNew);
  /* The methods above are in version 1 of the sqlite_module object. Those 
  ** below are for version 2 and greater. */
  int (*xSavepoint)(sqlite4_vtab *pVTab, int);
  int (*xRelease)(sqlite4_vtab *pVTab, int);
  int (*xRollbackTo)(sqlite4_vtab *pVTab, int);
};

/*
** CAPIREF: Virtual Table Indexing Information
** KEYWORDS: sqlite4_index_info
**
** The sqlite4_index_info structure and its substructures is used as part
** of the [virtual table] interface to
** pass information into and receive the reply from the [xBestIndex]
** method of a [virtual table module].  The fields under **Inputs** are the
** inputs to xBestIndex and are read-only.  xBestIndex inserts its
** results into the **Outputs** fields.
**
** ^(The aConstraint[] array records WHERE clause constraints of the form:
**
** <blockquote>column OP expr</blockquote>
**
** where OP is =, &lt;, &lt;=, &gt;, or &gt;=.)^  ^(The particular operator is
** stored in aConstraint[].op using one of the
** [SQLITE4_INDEX_CONSTRAINT_EQ | SQLITE4_INDEX_CONSTRAINT_ values].)^
** ^(The index of the column is stored in
** aConstraint[].iColumn.)^  ^(aConstraint[].usable is TRUE if the
** expr on the right-hand side can be evaluated (and thus the constraint
** is usable) and false if it cannot.)^
**
** ^The optimizer automatically inverts terms of the form "expr OP column"
** and makes other simplifications to the WHERE clause in an attempt to
** get as many WHERE clause terms into the form shown above as possible.
** ^The aConstraint[] array only reports WHERE clause terms that are
** relevant to the particular virtual table being queried.
**
** ^Information about the ORDER BY clause is stored in aOrderBy[].
** ^Each term of aOrderBy records a column of the ORDER BY clause.
**
** The [xBestIndex] method must fill aConstraintUsage[] with information
** about what parameters to pass to xFilter.  ^If argvIndex>0 then
** the right-hand side of the corresponding aConstraint[] is evaluated
** and becomes the argvIndex-th entry in argv.  ^(If aConstraintUsage[].omit
** is true, then the constraint is assumed to be fully handled by the
** virtual table and is not checked again by SQLite.)^
**
** ^The idxNum and idxPtr values are recorded and passed into the
** [xFilter] method.
** ^[sqlite4_free()] is used to free idxPtr if and only if
** needToFreeIdxPtr is true.
**
** ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in
** the correct order to satisfy the ORDER BY clause so that no separate
** sorting step is required.
**
** ^The estimatedCost value is an estimate of the cost of doing the
** particular lookup.  A full scan of a table with N entries should have
** a cost of N.  A binary search of a table of N entries should have a
** cost of approximately log(N).
*/
struct sqlite4_index_info {
  /* Inputs */
  int nConstraint;           /* Number of entries in aConstraint */
  struct sqlite4_index_constraint {
     int iColumn;              /* Column on left-hand side of constraint */
     unsigned char op;         /* Constraint operator */
     unsigned char usable;     /* True if this constraint is usable */
     int iTermOffset;          /* Used internally - xBestIndex should ignore */
  } *aConstraint;            /* Table of WHERE clause constraints */
  int nOrderBy;              /* Number of terms in the ORDER BY clause */
  struct sqlite4_index_orderby {
     int iColumn;              /* Column number */
     unsigned char desc;       /* True for DESC.  False for ASC. */
  } *aOrderBy;               /* The ORDER BY clause */
  /* Outputs */
  struct sqlite4_index_constraint_usage {
    int argvIndex;           /* if >0, constraint is part of argv to xFilter */
    unsigned char omit;      /* Do not code a test for this constraint */
  } *aConstraintUsage;
  int idxNum;                /* Number used to identify the index */
  char *idxStr;              /* String, possibly obtained from sqlite4_malloc */
  int needToFreeIdxStr;      /* Free idxStr using sqlite4_free() if true */
  int orderByConsumed;       /* True if output is already ordered */
  double estimatedCost;      /* Estimated cost of using this index */
};

/*
** CAPIREF: Virtual Table Constraint Operator Codes
**
** These macros defined the allowed values for the
** [sqlite4_index_info].aConstraint[].op field.  Each value represents
** an operator that is part of a constraint term in the wHERE clause of
** a query that uses a [virtual table].
*/
#define SQLITE4_INDEX_CONSTRAINT_EQ    2
#define SQLITE4_INDEX_CONSTRAINT_GT    4
#define SQLITE4_INDEX_CONSTRAINT_LE    8
#define SQLITE4_INDEX_CONSTRAINT_LT    16
#define SQLITE4_INDEX_CONSTRAINT_GE    32
#define SQLITE4_INDEX_CONSTRAINT_MATCH 64

/*
** CAPIREF: Register A Virtual Table Implementation
**
** ^These routines are used to register a new [virtual table module] name.
** ^Module names must be registered before
** creating a new [virtual table] using the module and before using a
** preexisting [virtual table] for the module.
**
** ^The module name is registered on the [database connection] specified
** by the first parameter.  ^The name of the module is given by the 
** second parameter.  ^The third parameter is a pointer to
** the implementation of the [virtual table module].   ^The fourth
** parameter is an arbitrary client data pointer that is passed through
** into the [xCreate] and [xConnect] methods of the virtual table module
** when a new virtual table is be being created or reinitialized.
**
** ^The sqlite4_create_module_v2() interface has a fifth parameter which
** is a pointer to a destructor for the pClientData.  ^SQLite will
** invoke the destructor function (if it is not NULL) when SQLite
** no longer needs the pClientData pointer.  ^The destructor will also
** be invoked if the call to sqlite4_create_module_v2() fails.
** ^The sqlite4_create_module()
** interface is equivalent to sqlite4_create_module_v2() with a NULL
** destructor.
*/
SQLITE4_API int sqlite4_create_module(
  sqlite4 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite4_module *p,   /* Methods for the module */
  void *pClientData          /* Client data for xCreate/xConnect */
);
SQLITE4_API int sqlite4_create_module_v2(
  sqlite4 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite4_module *p,   /* Methods for the module */
  void *pClientData,         /* Client data for xCreate/xConnect */
  void(*xDestroy)(void*)     /* Module destructor function */
);

/*
** CAPIREF: Virtual Table Instance Object
** KEYWORDS: sqlite4_vtab
**
** Every [virtual table module] implementation uses a subclass
** of this object to describe a particular instance
** of the [virtual table].  Each subclass will
** be tailored to the specific needs of the module implementation.
** The purpose of this superclass is to define certain fields that are
** common to all module implementations.
**
** ^Virtual tables methods can set an error message by assigning a
** string obtained from [sqlite4_mprintf()] to zErrMsg.  The method should
** take care that any prior string is freed by a call to [sqlite4_free()]
** prior to assigning a new string to zErrMsg.  ^After the error message
** is delivered up to the client application, the string will be automatically
** freed by sqlite4_free() and the zErrMsg field will be zeroed.
*/
struct sqlite4_vtab {
  const sqlite4_module *pModule;  /* The module for this virtual table */
  int nRef;                       /* NO LONGER USED */
  char *zErrMsg;                  /* Error message from sqlite4_mprintf() */
  /* Virtual table implementations will typically add additional fields */
};

/*
** CAPIREF: Virtual Table Cursor Object
** KEYWORDS: sqlite4_vtab_cursor {virtual table cursor}
**
** Every [virtual table module] implementation uses a subclass of the
** following structure to describe cursors that point into the
** [virtual table] and are used
** to loop through the virtual table.  Cursors are created using the
** [sqlite4_module.xOpen | xOpen] method of the module and are destroyed
** by the [sqlite4_module.xClose | xClose] method.  Cursors are used
** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods
** of the module.  Each module implementation will define
** the content of a cursor structure to suit its own needs.
**
** This superclass exists in order to define fields of the cursor that
** are common to all implementations.
*/
struct sqlite4_vtab_cursor {
  sqlite4_vtab *pVtab;      /* Virtual table of this cursor */
  /* Virtual table implementations will typically add additional fields */
};

/*
** CAPIREF: Declare The Schema Of A Virtual Table
**
** ^The [xCreate] and [xConnect] methods of a
** [virtual table module] call this interface
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
SQLITE4_API int sqlite4_declare_vtab(sqlite4*, const char *zSQL);

/*
** CAPIREF: Overload A Function For A Virtual Table
**
** ^(Virtual tables can provide alternative implementations of functions
** using the [xFindFunction] method of the [virtual table module].  
** But global versions of those functions
** must exist in order to be overloaded.)^
**
** ^(This API makes sure a global version of a function with a particular
** name and number of parameters exists.  If no such function exists
** before this API is called, a new function is created.)^  ^The implementation
** of the new function always causes an exception to be thrown.  So
** the new function is not good for anything by itself.  Its only
** purpose is to be a placeholder function that can be overloaded
** by a [virtual table].
*/
SQLITE4_API int sqlite4_overload_function(sqlite4*, const char *zFuncName, int nArg);

/*
** CAPIREF: Mutexes
**
** The SQLite core uses these routines for thread
** synchronization. Though they are intended for internal
** use by SQLite, code that links against SQLite is
** permitted to use any of these routines.
**
** The SQLite source code contains multiple implementations
** of these mutex routines.  An appropriate implementation
** is selected automatically at compile-time.  ^(The following
** implementations are available in the SQLite core:
**
** <ul>
** <li>   SQLITE4_MUTEX_PTHREADS
** <li>   SQLITE4_MUTEX_W32
** <li>   SQLITE4_MUTEX_NOOP
** </ul>)^
**
** ^The SQLITE4_MUTEX_NOOP implementation is a set of routines
** that does no real locking and is appropriate for use in
** a single-threaded application.  ^The SQLITE4_MUTEX_PTHREADS
** and SQLITE4_MUTEX_W32 implementations
** are appropriate for use on Unix and Windows.
**
** ^(If SQLite is compiled with the SQLITE4_MUTEX_APPDEF preprocessor
** macro defined (with "-DSQLITE4_MUTEX_APPDEF=1"), then no mutex
** implementation is included with the library. In this case the
** application must supply a custom mutex implementation using the
** [SQLITE4_CONFIG_MUTEX] option of the sqlite4_env_config() function
** before calling sqlite4_initialize() or any other public sqlite4_
** function that calls sqlite4_initialize().)^
**
** ^The sqlite4_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it. ^If it returns NULL
** that means that a mutex could not be allocated.  ^SQLite
** will unwind its stack and return an error.  ^(The argument
** to sqlite4_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li>  SQLITE4_MUTEX_FAST
** <li>  SQLITE4_MUTEX_RECURSIVE
** </ul>)^
**
** ^The new mutex is recursive when SQLITE4_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE4_MUTEX_FAST is used.
** The mutex implementation does not need to make a distinction
** between SQLITE4_MUTEX_RECURSIVE and SQLITE4_MUTEX_FAST if it does
** not want to.  ^SQLite will only request a recursive mutex in
** cases where it really needs one.  ^If a faster non-recursive mutex
** implementation is available on the host platform, the mutex subsystem
** might return such a mutex in response to SQLITE4_MUTEX_FAST.
**
** ^The sqlite4_mutex_free() routine deallocates a previously
** allocated mutex. 
**
** ^The sqlite4_mutex_enter() and sqlite4_mutex_try() routines attempt
** to enter a mutex.  ^If another thread is already within the mutex,
** sqlite4_mutex_enter() will block and sqlite4_mutex_try() will return
** SQLITE4_BUSY.  ^The sqlite4_mutex_try() interface returns [SQLITE4_OK]
** upon successful entry.  ^(Mutexes created using
** SQLITE4_MUTEX_RECURSIVE can be entered multiple times by the same thread.
** In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter.)^  ^(If the same thread tries to enter any other
** kind of mutex more than once, the behavior is undefined.
** SQLite will never exhibit
** such behavior in its own use of mutexes.)^
**
** ^(Some systems (for example, Windows 95) do not support the operation
** implemented by sqlite4_mutex_try().  On those systems, sqlite4_mutex_try()
** will always return SQLITE4_BUSY.  The SQLite core only ever uses
** sqlite4_mutex_try() as an optimization so this is acceptable behavior.)^
**
** ^The sqlite4_mutex_leave() routine exits a mutex that was
** previously entered by the same thread.   ^(The behavior
** is undefined if the mutex is not currently entered by the
** calling thread or is not currently allocated.  SQLite will
** never do either.)^
**
** ^If the argument to sqlite4_mutex_enter(), sqlite4_mutex_try(), or
** sqlite4_mutex_leave() is a NULL pointer, then all three routines
** behave as no-ops.
**
** See also: [sqlite4_mutex_held()] and [sqlite4_mutex_notheld()].
*/
SQLITE4_API sqlite4_mutex *sqlite4_mutex_alloc(sqlite4_env*, int);
SQLITE4_API void sqlite4_mutex_free(sqlite4_mutex*);
SQLITE4_API void sqlite4_mutex_enter(sqlite4_mutex*);
SQLITE4_API int sqlite4_mutex_try(sqlite4_mutex*);
SQLITE4_API void sqlite4_mutex_leave(sqlite4_mutex*);

/*
** CAPIREF: Mutex Methods Object
**
** An instance of this structure defines the low-level routines
** used to allocate and use mutexes.
**
** Usually, the default mutex implementations provided by SQLite are
** sufficient, however the user has the option of substituting a custom
** implementation for specialized deployments or systems for which SQLite
** does not provide a suitable implementation. In this case, the user
** creates and populates an instance of this structure to pass
** to sqlite4_env_config() along with the [SQLITE4_CONFIG_MUTEX] option.
** Additionally, an instance of this structure can be used as an
** output variable when querying the system for the current mutex
** implementation, using the [SQLITE4_CONFIG_GETMUTEX] option.
**
** ^The xMutexInit method defined by this structure is invoked as
** part of system initialization by the sqlite4_initialize() function.
** ^The xMutexInit routine is called by SQLite exactly once for each
** effective call to [sqlite4_initialize()].
**
** ^The xMutexEnd method defined by this structure is invoked as
** part of system shutdown by the sqlite4_shutdown() function. The
** implementation of this method is expected to release all outstanding
** resources obtained by the mutex methods implementation, especially
** those obtained by the xMutexInit method.  ^The xMutexEnd()
** interface is invoked exactly once for each call to [sqlite4_shutdown()].
**
** ^(The remaining seven methods defined by this structure (xMutexAlloc,
** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and
** xMutexNotheld) implement the following interfaces (respectively):
**
** <ul>
**   <li>  [sqlite4_mutex_alloc()] </li>
**   <li>  [sqlite4_mutex_free()] </li>
**   <li>  [sqlite4_mutex_enter()] </li>
**   <li>  [sqlite4_mutex_try()] </li>
**   <li>  [sqlite4_mutex_leave()] </li>
**   <li>  [sqlite4_mutex_held()] </li>
**   <li>  [sqlite4_mutex_notheld()] </li>
** </ul>)^
**
** The only difference is that the public sqlite4_XXX functions enumerated
** above silently ignore any invocations that pass a NULL pointer instead
** of a valid mutex handle. The implementations of the methods defined
** by this structure are not required to handle this case, the results
** of passing a NULL pointer instead of a valid mutex handle are undefined
** (i.e. it is acceptable to provide an implementation that segfaults if
** it is passed a NULL pointer).
**
** The xMutexInit() method must be threadsafe.  ^It must be harmless to
** invoke xMutexInit() multiple times within the same process and without
** intervening calls to xMutexEnd().  Second and subsequent calls to
** xMutexInit() must be no-ops.
**
** ^xMutexInit() must not use SQLite memory allocation ([sqlite4_malloc()]
** and its associates).  ^Similarly, xMutexAlloc() must not use SQLite memory
** allocation for a static mutex.  ^However xMutexAlloc() may use SQLite
** memory allocation for a fast or recursive mutex.
**
** ^SQLite will invoke the xMutexEnd() method when [sqlite4_shutdown()] is
** called, but only if the prior call to xMutexInit returned SQLITE4_OK.
** If xMutexInit fails in any way, it is expected to clean up after itself
** prior to returning.
*/
typedef struct sqlite4_mutex_methods sqlite4_mutex_methods;
struct sqlite4_mutex_methods {
  int (*xMutexInit)(void*);
  int (*xMutexEnd)(void*);
  sqlite4_mutex *(*xMutexAlloc)(void*,int);
  void (*xMutexFree)(sqlite4_mutex *);
  void (*xMutexEnter)(sqlite4_mutex *);
  int (*xMutexTry)(sqlite4_mutex *);
  void (*xMutexLeave)(sqlite4_mutex *);
  int (*xMutexHeld)(sqlite4_mutex *);
  int (*xMutexNotheld)(sqlite4_mutex *);
  void *pMutexEnv;
};

/*
** CAPIREF: Mutex Verification Routines
**
** The sqlite4_mutex_held() and sqlite4_mutex_notheld() routines
** are intended for use inside assert() statements.  ^The SQLite core
** never uses these routines except inside an assert() and applications
** are advised to follow the lead of the core.  ^The SQLite core only
** provides implementations for these routines when it is compiled
** with the SQLITE4_DEBUG flag.  ^External mutex implementations
** are only required to provide these routines if SQLITE4_DEBUG is
** defined and if NDEBUG is not defined.
**
** ^These routines should return true if the mutex in their argument
** is held or not held, respectively, by the calling thread.
**
** ^The implementation is not required to provide versions of these
** routines that actually work. If the implementation does not provide working
** versions of these routines, it should at least provide stubs that always
** return true so that one does not get spurious assertion failures.
**
** ^If the argument to sqlite4_mutex_held() is a NULL pointer then
** the routine should return 1.   This seems counter-intuitive since
** clearly the mutex cannot be held if it does not exist.  But
** the reason the mutex does not exist is because the build is not
** using mutexes.  And we do not want the assert() containing the
** call to sqlite4_mutex_held() to fail, so a non-zero return is
** the appropriate thing to do.  ^The sqlite4_mutex_notheld()
** interface should also return 1 when given a NULL pointer.
*/
#ifndef NDEBUG
SQLITE4_API int sqlite4_mutex_held(sqlite4_mutex*);
SQLITE4_API int sqlite4_mutex_notheld(sqlite4_mutex*);
#endif

/*
** CAPIREF: Mutex Types
**
** The [sqlite4_mutex_alloc()] interface takes a single argument
** which is one of these integer constants.
**
** The set of static mutexes may change from one SQLite release to the
** next.  Applications that override the built-in mutex logic must be
** prepared to accommodate additional static mutexes.
*/
#define SQLITE4_MUTEX_FAST             0
#define SQLITE4_MUTEX_RECURSIVE        1
#define SQLITE4_MUTEX_STATIC_KV        2    /* For use by KV layers*/

/*
** CAPIREF: Retrieve the mutex for a database connection
**
** ^This interface returns a pointer the [sqlite4_mutex] object that 
** serializes access to the [database connection] given in the argument
** when the [threading mode] is Serialized.
** ^If the [threading mode] is Single-thread or Multi-thread then this
** routine returns a NULL pointer.
*/
SQLITE4_API sqlite4_mutex *sqlite4_db_mutex(sqlite4*);

/*
** CAPIREF: Low-Level Control Of Database Backends
**
** ^The [sqlite4_kvstore_control()] interface makes a direct call to the
** xControl method of the key-value store associated with the particular 
** database identified by the second argument. ^The name of the database 
** is "main" for the main database or "temp" for the TEMP database, or the 
** name that appears after the AS keyword for databases that were added 
** using the [ATTACH] SQL command. ^A NULL pointer can be used in place 
** of "main" to refer to the main database file.
**
** ^The third and fourth parameters to this routine are passed directly 
** through to the second and third parameters of the
** sqlite4_kv_methods.xControl method. ^The return value of the xControl
** call becomes the return value of this routine.
**
** ^If the second parameter (zDbName) does not match the name of any
** open database file, then SQLITE4_ERROR is returned.  ^This error
** code is not remembered and will not be recalled by [sqlite4_errcode()]
** or [sqlite4_errmsg()]. The underlying xControl method might also return 
** SQLITE4_ERROR. There is no way to distinguish between an incorrect zDbName 
** and an SQLITE4_ERROR return from the underlying xControl method.
*/
SQLITE4_API int sqlite4_kvstore_control(sqlite4*, const char *zDbName, int op, void*);

/*
** <dl>
** <dt>SQLITE4_KVCTRL_LSM_HANDLE</dt><dd>
**
** <dt>SQLITE4_KVCTRL_SYNCHRONOUS</dt><dd>
** This op is used to configure or query the synchronous level of the 
** database backend (either OFF, NORMAL or FULL). The fourth parameter passed 
** to kvstore_control should be of type (int *). Call the value that the
** parameter points to N. If N is initially 0, 1 or 2, then the database 
** backend should attempt to change the synchronous level to OFF, NORMAL 
** or FULL, respectively. Regardless of its initial value, N is set to 
** the current (possibly updated) synchronous level before returning (
** 0, 1 or 2).
*/
#define SQLITE4_KVCTRL_LSM_HANDLE       1
#define SQLITE4_KVCTRL_SYNCHRONOUS      2
#define SQLITE4_KVCTRL_LSM_FLUSH        3
#define SQLITE4_KVCTRL_LSM_MERGE        4
#define SQLITE4_KVCTRL_LSM_CHECKPOINT   5

/*
** CAPIREF: Testing Interface
**
** ^The sqlite4_test_control() interface is used to read out internal
** state of SQLite and to inject faults into SQLite for testing
** purposes.  ^The first parameter is an operation code that determines
** the number, meaning, and operation of all subsequent parameters.
**
** This interface is not for use by applications.  It exists solely
** for verifying the correct operation of the SQLite library.  Depending
** on how the SQLite library is compiled, this interface might not exist.
**
** The details of the operation codes, their meanings, the parameters
** they take, and what they do are all subject to change without notice.
** Unlike most of the SQLite API, this function is not guaranteed to
** operate consistently from one release to the next.
*/
SQLITE4_API int sqlite4_test_control(int op, ...);

/*
** CAPIREF: Testing Interface Operation Codes
**
** These constants are the valid operation code parameters used
** as the first argument to [sqlite4_test_control()].
**
** These parameters and their meanings are subject to change
** without notice.  These values are for testing purposes only.
** Applications should not use any of these parameters or the
** [sqlite4_test_control()] interface.
*/
#define SQLITE4_TESTCTRL_FIRST                    1
#define SQLITE4_TESTCTRL_FAULT_INSTALL            2
#define SQLITE4_TESTCTRL_ASSERT                   3
#define SQLITE4_TESTCTRL_ALWAYS                   4
#define SQLITE4_TESTCTRL_RESERVE                  5
#define SQLITE4_TESTCTRL_OPTIMIZATIONS            6
#define SQLITE4_TESTCTRL_ISKEYWORD                7
#define SQLITE4_TESTCTRL_LOCALTIME_FAULT          8
#define SQLITE4_TESTCTRL_EXPLAIN_STMT             9
#define SQLITE4_TESTCTRL_PRNG_GET                 10  /* pEnv, *pi64 */
#define SQLITE4_TESTCTRL_PRNG_SET                 11  /* pEnv, i64   */
#define SQLITE4_TESTCTRL_LAST                     11

/*
** CAPIREF: SQLite Runtime Status
**
** ^This interface is used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks.  ^The first argument is an integer code for
** the specific parameter to measure.  ^(Recognized integer codes
** are of the form [status parameters | SQLITE4_STATUS_...].)^
** ^The current value of the parameter is returned into *pCurrent.
** ^The highest recorded value is returned in *pHighwater.  ^If the
** resetFlag is true, then the highest record value is reset after
** *pHighwater is written.  ^(Some parameters do not record the highest
** value.  For those parameters
** nothing is written into *pHighwater and the resetFlag is ignored.)^
** ^(Other parameters record only the highwater mark and not the current
** value.  For these latter parameters nothing is written into *pCurrent.)^
**
** ^The sqlite4_status() routine returns SQLITE4_OK on success and a
** non-zero [error code] on failure.
**
** This routine is threadsafe but is not atomic.  This routine can be
** called while other threads are running the same or different SQLite
** interfaces.  However the values returned in *pCurrent and
** *pHighwater reflect the status of SQLite at different points in time
** and it is possible that another thread might change the parameter
** in between the times when *pCurrent and *pHighwater are written.
**
** See also: [sqlite4_db_status()]
*/
SQLITE4_API int sqlite4_env_status(
  sqlite4_env *pEnv,
  int op,
  sqlite4_uint64 *pCurrent,
  sqlite4_uint64 *pHighwater,
  int resetFlag
);


/*
** CAPIREF: Status Parameters
** KEYWORDS: {status parameters}
**
** These integer constants designate various run-time status parameters
** that can be returned by [sqlite4_status()].
**
** <dl>
** [[SQLITE4_STATUS_MEMORY_USED]] ^(<dt>SQLITE4_STATUS_MEMORY_USED</dt>
** <dd>This parameter is the current amount of memory checked out
** using [sqlite4_malloc()], either directly or indirectly.  The
** figure includes calls made to [sqlite4_malloc()] by the application
** and internal memory usage by the SQLite library.  Scratch memory
** controlled by [SQLITE4_CONFIG_SCRATCH] and auxiliary page-cache
** memory controlled by [SQLITE4_CONFIG_PAGECACHE] is not included in
** this parameter.  The amount returned is the sum of the allocation
** sizes as reported by the xSize method in [sqlite4_mem_methods].</dd>)^
**
** [[SQLITE4_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE4_STATUS_MALLOC_SIZE</dt>
** <dd>This parameter records the largest memory allocation request
** handed to [sqlite4_malloc()] or [sqlite4_realloc()] (or their
** internal equivalents).  Only the value returned in the
** *pHighwater parameter to [sqlite4_status()] is of interest.  
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** [[SQLITE4_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE4_STATUS_MALLOC_COUNT</dt>
** <dd>This parameter records the number of separate memory allocations
** currently checked out.</dd>)^
**
** [[SQLITE4_STATUS_PARSER_STACK]] ^(<dt>SQLITE4_STATUS_PARSER_STACK</dt>
** <dd>This parameter records the deepest parser stack.  It is only
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
** </dl>
**
** New status parameters may be added from time to time.
*/
#define SQLITE4_ENVSTATUS_MEMORY_USED          0
#define SQLITE4_ENVSTATUS_MALLOC_SIZE          1
#define SQLITE4_ENVSTATUS_MALLOC_COUNT         2
#define SQLITE4_ENVSTATUS_PARSER_STACK         3

/*
** CAPIREF: Database Connection Status
**
** ^This interface is used to retrieve runtime status information 
** about a single [database connection].  ^The first argument is the
** database connection object to be interrogated.  ^The second argument
** is an integer constant, taken from the set of
** [SQLITE4_DBSTATUS options], that
** determines the parameter to interrogate.  The set of 
** [SQLITE4_DBSTATUS options] is likely
** to grow in future releases of SQLite.
**
** ^The current value of the requested parameter is written into *pCur
** and the highest instantaneous value is written into *pHiwtr.  ^If
** the resetFlg is true, then the highest instantaneous value is
** reset back down to the current value.
**
** ^The sqlite4_db_status() routine returns SQLITE4_OK on success and a
** non-zero [error code] on failure.
**
** See also: [sqlite4_status()] and [sqlite4_stmt_status()].
*/
SQLITE4_API int sqlite4_db_status(sqlite4*, int op, int *pCur, int *pHiwtr, int resetFlg);

/*
** CAPIREF: Status Parameters for database connections
** KEYWORDS: {SQLITE4_DBSTATUS options}
**
** These constants are the available integer "verbs" that can be passed as
** the second argument to the [sqlite4_db_status()] interface.
**
** New verbs may be added in future releases of SQLite. Existing verbs
** might be discontinued. Applications should check the return code from
** [sqlite4_db_status()] to make sure that the call worked.
** The [sqlite4_db_status()] interface will return a non-zero error code
** if a discontinued or unsupported verb is invoked.
**
** <dl>
** [[SQLITE4_DBSTATUS_LOOKASIDE_USED]]
** ^(<dt>SQLITE4_DBSTATUS_LOOKASIDE_USED</dt>
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
** [[SQLITE4_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE4_DBSTATUS_LOOKASIDE_HIT</dt>
** <dd>This parameter returns the number malloc attempts that were 
** satisfied using lookaside memory. Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE4_DBSTATUS_LOOKASIDE_MISS_SIZE]]
** ^(<dt>SQLITE4_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to the amount of
** memory requested being larger than the lookaside slot size.
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE4_DBSTATUS_LOOKASIDE_MISS_FULL]]
** ^(<dt>SQLITE4_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
** <dd>This parameter returns the number malloc attempts that might have
** been satisfied using lookaside memory but failed due to all lookaside
** memory already being in use.
** Only the high-water value is meaningful;
** the current value is always zero.)^
**
** [[SQLITE4_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE4_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE4_DBSTATUS_CACHE_USED is always 0.
**
** [[SQLITE4_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE4_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used to store the schema for all databases associated
** with the connection - main, temp, and any [ATTACH]-ed databases.)^ 
** ^The full amount of memory used by the schemas is reported, even if the
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE4_DBSTATUS_SCHEMA_USED is always 0.
**
** [[SQLITE4_DBSTATUS_STMT_USED]] ^(<dt>SQLITE4_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** and lookaside memory used by all prepared statements associated with
** the database connection.)^
** ^The highwater mark associated with SQLITE4_DBSTATUS_STMT_USED is always 0.
** </dd>
**
** [[SQLITE4_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE4_DBSTATUS_CACHE_HIT</dt>
** <dd>This parameter returns the number of pager cache hits that have
** occurred.)^ ^The highwater mark associated with SQLITE4_DBSTATUS_CACHE_HIT 
** is always 0.
** </dd>
**
** [[SQLITE4_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE4_DBSTATUS_CACHE_MISS</dt>
** <dd>This parameter returns the number of pager cache misses that have
** occurred.)^ ^The highwater mark associated with SQLITE4_DBSTATUS_CACHE_MISS 
** is always 0.
** </dd>
** </dl>
*/
#define SQLITE4_DBSTATUS_LOOKASIDE_USED       0
#define SQLITE4_DBSTATUS_CACHE_USED           1
#define SQLITE4_DBSTATUS_SCHEMA_USED          2
#define SQLITE4_DBSTATUS_STMT_USED            3
#define SQLITE4_DBSTATUS_LOOKASIDE_HIT        4
#define SQLITE4_DBSTATUS_LOOKASIDE_MISS_SIZE  5
#define SQLITE4_DBSTATUS_LOOKASIDE_MISS_FULL  6
#define SQLITE4_DBSTATUS_CACHE_HIT            7
#define SQLITE4_DBSTATUS_CACHE_MISS           8
#define SQLITE4_DBSTATUS_MAX                  8   /* Largest defined DBSTATUS */


/*
** CAPIREF: Prepared Statement Status
**
** ^(Each prepared statement maintains various
** [SQLITE4_STMTSTATUS counters] that measure the number
** of times it has performed specific operations.)^  These counters can
** be used to monitor the performance characteristics of the prepared
** statements.  For example, if the number of table steps greatly exceeds
** the number of table searches or result rows, that would tend to indicate
** that the prepared statement is using a full table scan rather than
** an index.  
**
** ^(This interface is used to retrieve and reset counter values from
** a [prepared statement].  The first argument is the prepared statement
** object to be interrogated.  The second argument
** is an integer code for a specific [SQLITE4_STMTSTATUS counter]
** to be interrogated.)^
** ^The current value of the requested counter is returned.
** ^If the resetFlg is true, then the counter is reset to zero after this
** interface call returns.
**
** See also: [sqlite4_status()] and [sqlite4_db_status()].
*/
SQLITE4_API int sqlite4_stmt_status(sqlite4_stmt*, int op,int resetFlg);

/*
** CAPIREF: Status Parameters for prepared statements
** KEYWORDS: {SQLITE4_STMTSTATUS counter} {SQLITE4_STMTSTATUS counters}
**
** These preprocessor macros define integer codes that name counter
** values associated with the [sqlite4_stmt_status()] interface.
** The meanings of the various counters are as follows:
**
** <dl>
** [[SQLITE4_STMTSTATUS_FULLSCAN_STEP]]
** <dt>SQLITE4_STMTSTATUS_FULLSCAN_STEP</dt>
** <dd>^This is the number of times that SQLite has stepped forward in
** a table as part of a full table scan.  Large numbers for this counter
** may indicate opportunities for performance improvement through 
** careful use of indices.</dd>
**
** [[SQLITE4_STMTSTATUS_SORT]] <dt>SQLITE4_STMTSTATUS_SORT</dt>
** <dd>^This is the number of sort operations that have occurred.
** A non-zero value in this counter may indicate an opportunity to
** improvement performance through careful use of indices.</dd>
**
** [[SQLITE4_STMTSTATUS_AUTOINDEX]] <dt>SQLITE4_STMTSTATUS_AUTOINDEX</dt>
** <dd>^This is the number of rows inserted into transient indices that
** were created automatically in order to help joins run faster.
** A non-zero value in this counter may indicate an opportunity to
** improvement performance by adding permanent indices that do not
** need to be reinitialized each time the statement is run.</dd>
** </dl>
*/
#define SQLITE4_STMTSTATUS_FULLSCAN_STEP     1
#define SQLITE4_STMTSTATUS_SORT              2
#define SQLITE4_STMTSTATUS_AUTOINDEX         3


/*
** CAPIREF: String Comparison
**
** ^The [sqlite4_strnicmp()] API allows applications and extensions to
** compare the contents of two buffers containing UTF-8 strings in a
** case-independent fashion, using the same definition of case independence 
** that SQLite uses internally when comparing identifiers.
*/
SQLITE4_API int sqlite4_stricmp(const char*, const char*);
SQLITE4_API int sqlite4_strnicmp(const char *, const char *, int);

SQLITE4_API int sqlite4_tolower(int);

/*
** CAPIREF: Error Logging Interface
**
** ^The [sqlite4_log()] interface writes a message into the error log
** established by the [SQLITE4_CONFIG_LOG] option to [sqlite4_env_config()].
** ^If logging is enabled, the zFormat string and subsequent arguments are
** used with [sqlite4_snprintf()] to generate the final output string.
**
** The sqlite4_log() interface is intended for use by extensions such as
** virtual tables, collating functions, and SQL functions.  While there is
** nothing to prevent an application from calling sqlite4_log(), doing so
** is considered bad form.
**
** The zFormat string must not be NULL.
**
** To avoid deadlocks and other threading problems, the sqlite4_log() routine
** will not use dynamically allocated memory.  The log message is stored in
** a fixed-length buffer on the stack.  If the log message is longer than
** a few hundred characters, it will be truncated to the length of the
** buffer.
*/
SQLITE4_API void sqlite4_log(sqlite4_env*, int iErrCode, const char *zFormat, ...);

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

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

/*
** CAPIREF: Determine The Virtual Table Conflict Policy
**
** This function may only be called from within a call to the [xUpdate] method
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
** value returned is one of [SQLITE4_ROLLBACK], [SQLITE4_IGNORE],
** [SQLITE4_FAIL],
** [SQLITE4_ABORT], or [SQLITE4_REPLACE], according to the [ON CONFLICT] mode
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
SQLITE4_API int sqlite4_vtab_on_conflict(sqlite4 *);

/*
** CAPIREF: Conflict resolution modes
**
** These constants are returned by [sqlite4_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode
** is for the SQL statement being evaluated.
**
** Note that the [SQLITE4_IGNORE] constant is also used as a potential
** return value from the [sqlite4_set_authorizer()] callback and that
** [SQLITE4_ABORT] is also a [result code].
*/
#define SQLITE4_ROLLBACK 1
/* #define SQLITE4_IGNORE 2 // Also used by sqlite4_authorizer() callback */
#define SQLITE4_FAIL     3
/* #define SQLITE4_ABORT 4  // Also an error code */
#define SQLITE4_REPLACE  5


/*
** CAPI4REF:  Length of a key-value storage key or data field
**
** The length of the key or data for a key-value storage entry is
** stored in a variable of this type.
*/
typedef int sqlite4_kvsize;

/*
** CAPI4REF: Key-Value Storage Engine Object
**
** An instance of a subclass of the following object defines a
** connection to a storage engine.
*/
struct sqlite4_kvstore {
  const struct sqlite4_kv_methods *pStoreVfunc;  /* Methods */
  sqlite4_env *pEnv;                      /* Runtime environment for kvstore */
  int iTransLevel;                        /* Current transaction level */
  unsigned kvId;                          /* Unique ID used for tracing */
  unsigned fTrace;                        /* True to enable tracing */
  char zKVName[12];                       /* Used for debugging */
  /* Subclasses will typically append additional fields */
};

/*
** CAPI4REF:  Key-Value Storage Engine Cursor Object
**
** An instance of a subclass of the following object defines a cursor
** used to scan through a key-value storage engine.
*/
typedef struct sqlite4_kvcursor sqlite4_kvcursor;
struct sqlite4_kvcursor {
  sqlite4_kvstore *pStore;                /* The owner of this cursor */
  const struct sqlite4_kv_methods *pStoreVfunc;  /* Methods */
  sqlite4_env *pEnv;                      /* Runtime environment  */
  int iTransLevel;                        /* Current transaction level */
  unsigned curId;                         /* Unique ID for tracing */
  unsigned fTrace;                        /* True to enable tracing */
  /* Subclasses will typically add additional fields */
};

/*
** CAPI4REF: Key-value storage engine virtual method table
**
** A Key-Value storage engine is defined by an instance of the following
** object.
*/
struct sqlite4_kv_methods {
  int iVersion;
  int szSelf;
  int (*xReplace)(
         sqlite4_kvstore*,
         const unsigned char *pKey, sqlite4_kvsize nKey,
         const unsigned char *pData, sqlite4_kvsize nData);
  int (*xOpenCursor)(sqlite4_kvstore*, sqlite4_kvcursor**);
  int (*xSeek)(sqlite4_kvcursor*,
               const unsigned char *pKey, sqlite4_kvsize nKey, int dir);
  int (*xNext)(sqlite4_kvcursor*);
  int (*xPrev)(sqlite4_kvcursor*);
  int (*xDelete)(sqlite4_kvcursor*);
  int (*xKey)(sqlite4_kvcursor*,
              const unsigned char **ppKey, sqlite4_kvsize *pnKey);
  int (*xData)(sqlite4_kvcursor*, sqlite4_kvsize ofst, sqlite4_kvsize n,
               const unsigned char **ppData, sqlite4_kvsize *pnData);
  int (*xReset)(sqlite4_kvcursor*);
  int (*xCloseCursor)(sqlite4_kvcursor*);
  int (*xBegin)(sqlite4_kvstore*, int);
  int (*xCommitPhaseOne)(sqlite4_kvstore*, int);
  int (*xCommitPhaseTwo)(sqlite4_kvstore*, int);
  int (*xRollback)(sqlite4_kvstore*, int);
  int (*xRevert)(sqlite4_kvstore*, int);
  int (*xClose)(sqlite4_kvstore*);
  int (*xControl)(sqlite4_kvstore*, int, void*);
  int (*xGetMeta)(sqlite4_kvstore*, unsigned int *);
  int (*xPutMeta)(sqlite4_kvstore*, unsigned int);
  int (*xGetMethod)(sqlite4_kvstore*, const char *, void **ppArg,
      void (**pxFunc)(sqlite4_context *, int, sqlite4_value **),
      void (**pxDestroy)(void *)
  );
};
typedef struct sqlite4_kv_methods sqlite4_kv_methods;

/*
** CAPI4REF: Key-value storage engine open flags
**
** Allowed values to the flags parameter of an [sqlite4_kvfactory] object.
**
** The flags parameter to the sqlite4_kvfactory fuction (the fourth parameter)
** is an OR-ed combination of these values and the
** [SQLITE4_OPEN_READONLY | SQLITE4_OPEN_xxxxx] flags that appear as 
** arguments to [sqlite4_open()].
*/
#define SQLITE4_KVOPEN_TEMPORARY       0x00010000  /* A temporary database */
#define SQLITE4_KVOPEN_NO_TRANSACTIONS 0x00020000  /* No transactions needed */

/*
** CAPIREF: Key-value storage object factory
**
** New key/value storage engines can be added to SQLite4 at run-time.
** In order to create a new KV storage engine, the application must 
** supply a "factory" function that creates an instance of the
** sqlite4_kvstore object.  This typedef defines the signature
** of that factory function.
*/
typedef int (*sqlite4_kvfactory)(
  sqlite4_env *pEnv,             /* The environment to use */
  sqlite4_kvstore **ppKVStore,   /* OUT: New KV store returned here */
  const char *zFilename,         /* Name of database file to open */
  unsigned flags                 /* Bit flags */
);

/*
** CAPI4REF: Operations On SQLite Number Objects
*/
SQLITE4_API sqlite4_num sqlite4_num_add(sqlite4_num, sqlite4_num);
SQLITE4_API sqlite4_num sqlite4_num_sub(sqlite4_num, sqlite4_num);
SQLITE4_API sqlite4_num sqlite4_num_mul(sqlite4_num, sqlite4_num);
SQLITE4_API sqlite4_num sqlite4_num_div(sqlite4_num, sqlite4_num);
SQLITE4_API int sqlite4_num_isinf(sqlite4_num);
SQLITE4_API int sqlite4_num_isnan(sqlite4_num);
SQLITE4_API sqlite4_num sqlite4_num_round(sqlite4_num, int iDigit);
SQLITE4_API int sqlite4_num_compare(sqlite4_num, sqlite4_num);
SQLITE4_API sqlite4_num sqlite4_num_from_text(const char*, int n, unsigned flags, int*);
SQLITE4_API sqlite4_num sqlite4_num_from_int64(sqlite4_int64);
SQLITE4_API sqlite4_num sqlite4_num_from_double(double);
SQLITE4_API int sqlite4_num_to_int32(sqlite4_num, int*);
SQLITE4_API sqlite4_int64 sqlite4_num_to_int64(sqlite4_num, int *);
SQLITE4_API int sqlite4_num_to_double(sqlite4_num, double *);
SQLITE4_API int sqlite4_num_to_text(sqlite4_num, char*, int);

/*
** CAPI4REF: Flags For Text-To-Numeric Conversion
*/
#define SQLITE4_PREFIX_ONLY         0x10
#define SQLITE4_IGNORE_WHITESPACE   0x20
#define SQLITE4_NEGATIVE            0x40
#define SQLITE4_INTEGER_ONLY        0x80

typedef struct sqlite4_tokenizer sqlite4_tokenizer;

/*
** CAPI4REF: Register an FTS tokenizer implementation
**
** xTokenize:
**   This function does the actual tokenization of an input string. For
**   each token in the input, the callback function is invoked once. The
**   arguments passed to the callback by the tokenizer must be as follows:
**
**     xCallback(ctx, iWeight, zToken, nToken, iSrc, nSrc);
**
**   ctx     - Copy of the first argument passed to xTokenize.
**   iOff    - Offset of token in document.
**   iWeight - Weight assigned to the token by the tokenizer. Larger values
**             indicate more important tokens. 
**   zToken  - Pointer to buffer containing token text. 
**   nToken  - Number of bytes in zToken.
**   iSrc    - Byte offset in source document of the start of this token.
**   nSrc    - Bytes of text in source document tokenized to this token.
*/
SQLITE4_API int sqlite4_create_tokenizer(
  sqlite4 *db,
  const char *zName,
  void *pCtx,
  int (*xCreate)(void*, const char**, int, sqlite4_tokenizer**),
  int (*xTokenize)(void*, sqlite4_tokenizer*,
      const char*, int, 
      int(*x)(void *ctx, int iWeight, int iOff, 
              const char *zToken, int nToken, int iSrc, int nSrc)
  ),
  int (*xDestroy)(sqlite4_tokenizer *)
);

/*
** CAPI4REF: Register a matchinfo function.
*/
SQLITE4_API int sqlite4_create_mi_function(
  sqlite4 *db,
  const char *zFunc,
  int nArg,
  int enc,
  void *p,
  void (*xFunc)(sqlite4_context*,int,sqlite4_value **),
  void (*xDestroy)(void *)
);

/*
** CAPIREF: Matchinfo APIs.
**
** Special functions that may be called from within matchinfo UDFs. All
** return an SQLite error code - SQLITE4_OK if successful, or some other
** error code otherwise.
**
** sqlite4_mi_column_count():
**   Set *pn to the number of columns in the queried table.
**
** sqlite4_mi_phrase_count():
**   Set *pn to the number of phrases in the query.
**
** sqlite4_mi_stream_count():
**   Set *pn to the number of streams in the FTS index.
**
** sqlite4_mi_phrase_token_count():
**   Set *pn to the number of tokens in phrase iP of the query.
**
** sqlite4_mi_size():
**   Set *pn to the number of tokens belonging to stream iS in the value 
**   stored in column iC of the current row. 
**
**   Either or both of iS and iC may be negative. If iC is negative, then the
**   output value is the total number of tokens for the specified stream (or
**   streams) across all table columns. Similarly, if iS is negative, the 
**   output value is the total number of tokens in the specified column or 
**   columns, regardless of stream.
**
** sqlite4_mi_total_size():
**   Similar to sqlite4_mi_size(), except the output parameter is set to
**   the total number of tokens belonging to the specified column(s) 
**   and stream(s) in all rows of the table, not just the current row.
**
** sqlite4_mi_total_rows():
**   Set *pn to the total number of rows in the indexed table.
**
** sqlite4_mi_row_count():
**   Set the output parameter to the total number of rows in the table that
**   contain at least one instance of the phrase identified by parameter
**   iP in the column(s) and stream(s) identified by parameters iC and iS.
**
** sqlite4_mi_match_count():
**   Set the output parameter to the total number of occurences of phrase
**   iP in the current row that belong to the column(s) and stream(s) 
**   identified by parameters iC and iS.
**
**   Parameter iP may also be negative. In this case, the output value is
**   set to the total number of occurrences of all query phrases in the
**   current row, subject to the constraints imposed by iC and iS.
**
** sqlite4_mi_match_detail():
**   This function is used to access the details of the iMatch'th match
**   (of any phrase) in the current row. Matches are sorted in order of
**   occurrence. If parameter iMatch is equal to or greater than the number 
**   of matches in the current row, SQLITE_NOTFOUND is returned. Otherwise,
**   unless an error occurs, SQLITE4_OK is returned and the *piOff, *piC, *piS,
**   and *piP output parameters are set to the token offset, column number,
**   stream number and phrase number respectively.
**
**   It is anticipated that this function be used to iterate through matches 
**   in order of occurrence. It is optimized so that it is fastest when 
**   called with the iMatch parameter set to 0, P or P+1, where P is the 
**   iMatch value passed to the previous call.
**
** sqlite4_mi_column_value():
**   Set *ppVal to point to an sqlite4_value object containing the value
**   read from column iCol of the current row. This object is valid until
**   the function callback returns.
**
** sqlite4_mi_tokenize():
**   Use the tokenizer associated with the FTS index to tokenize the
**   document in buffer zDoc (size nDoc bytes). Invoke callback function
**   x() once for each token, in the same way as the xTokenizer() method
**   of a tokenizer implementation.
*/
SQLITE4_API int sqlite4_mi_column_count(sqlite4_context *, int *pn);
SQLITE4_API int sqlite4_mi_phrase_count(sqlite4_context *, int *pn);
SQLITE4_API int sqlite4_mi_stream_count(sqlite4_context *, int *pn);
SQLITE4_API int sqlite4_mi_phrase_token_count(sqlite4_context *, int iP, int *pn);

SQLITE4_API int sqlite4_mi_total_size(sqlite4_context *, int iC, int iS, int *pn);
SQLITE4_API int sqlite4_mi_total_rows(sqlite4_context *, int *pn);

SQLITE4_API int sqlite4_mi_row_count(sqlite4_context *, int iC, int iS, int iP, int *pn);

SQLITE4_API int sqlite4_mi_size(sqlite4_context *, int iC, int iS, int *pn);
SQLITE4_API int sqlite4_mi_match_count(sqlite4_context *, int iC, int iS, int iP, int *pn);
SQLITE4_API int sqlite4_mi_match_detail(
    sqlite4_context *, int iMatch, int *piOff, int *piC, int *piS, int *piP
);
SQLITE4_API int sqlite4_mi_column_value(sqlite4_context *, int iC, sqlite4_value **ppVal);

SQLITE4_API int sqlite4_mi_tokenize(sqlite4_context *, const char *zDoc, int nDoc, 
  void *p, int(*x)(void *, int, int, const char *, int, int, int)
);



/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
*/
#ifdef SQLITE4_OMIT_FLOATING_POINT
# undef double
#endif

#if 0
}  /* End of the 'extern "C"' block */
#endif
#endif

/*
** 2010 August 30
**
** 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.
**
*************************************************************************
*/

#ifndef _SQLITE3RTREE_H_
#define _SQLITE3RTREE_H_


#if 0
extern "C" {
#endif

typedef struct sqlite4_rtree_geometry sqlite4_rtree_geometry;

/*
** Register a geometry callback named zGeom that can be used as part of an
** R-Tree geometry query as follows:
**
**   SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
*/
SQLITE4_API int sqlite4_rtree_geometry_callback(
  sqlite4 *db,
  const char *zGeom,
  int (*xGeom)(sqlite4_rtree_geometry *, int nCoord, double *aCoord, int *pRes),
  void *pContext
);


/*
** A pointer to a structure of the following type is passed as the first
** argument to callbacks registered using rtree_geometry_callback().
*/
struct sqlite4_rtree_geometry {
  void *pContext;                 /* Copy of pContext passed to s_r_g_c() */
  int nParam;                     /* Size of array aParam[] */
  double *aParam;                 /* Parameters passed to SQL geom function */
  void *pUser;                    /* Callback implementation user data */
  void (*xDelUser)(void *);       /* Called by SQLite to clean up pUser */
};


#if 0
}  /* end of the 'extern "C"' block */
#endif

#endif  /* ifndef _SQLITE3RTREE_H_ */


/************** End of sqlite4.h *********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include hash.h in the middle of sqliteInt.h ******************/
/************** Begin file hash.h ********************************************/
/*
** 2001 September 22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This is the header file for the generic hash-table implemenation
** used in SQLite.
*/
#ifndef _SQLITE4_HASH_H_
#define _SQLITE4_HASH_H_

/* Forward declarations of structures. */
typedef struct Hash Hash;
typedef struct HashElem HashElem;

/* A complete hash table is an instance of the following structure.
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly.  Change this structure only by using the routines below.
** However, some of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
**
** All elements of the hash table are on a single doubly-linked list.
** Hash.first points to the head of this list.
**
** There are Hash.htsize buckets.  Each bucket points to a spot in
** the global doubly-linked list.  The contents of the bucket are the
** element pointed to plus the next _ht.count-1 elements in the list.
**
** Hash.htsize and Hash.ht may be zero.  In that case lookup is done
** by a linear search of the global list.  For small tables, the 
** Hash.ht table is never allocated because if there are few elements
** in the table, it is faster to do a linear search than to manage
** the hash table.
*/
struct Hash {
  sqlite4_env *pEnv;        /* Memory allocation environment */
  unsigned int (*xHash)(const char *, int);
  int (*xCmp)(const char *, const char *, int);
  unsigned int htsize;      /* Number of buckets in the hash table */
  unsigned int count;       /* Number of entries in this table */
  HashElem *first;          /* The first element of the array */
  struct _ht {              /* the hash table */
    int count;                 /* Number of entries with this hash */
    HashElem *chain;           /* Pointer to first entry with this hash */
  } *ht;
};

/* Each element in the hash table is an instance of the following 
** structure.  All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
** be opaque because it is used by macros.
*/
struct HashElem {
  HashElem *next, *prev;       /* Next and previous elements in the table */
  void *data;                  /* Data associated with this element */
  const char *pKey; int nKey;  /* Key associated with this element */
};

/*
** Access routines.  To delete, insert a NULL pointer.
*/
SQLITE4_PRIVATE void sqlite4HashInit(sqlite4_env *pEnv, Hash*, int);
SQLITE4_PRIVATE void *sqlite4HashInsert(Hash*, const char *pKey, int nKey, void *pData);
SQLITE4_PRIVATE void *sqlite4HashFind(const Hash*, const char *pKey, int nKey);
SQLITE4_PRIVATE void sqlite4HashClear(Hash*);

/*
** Macros for looping over all elements of a hash table.  The idiom is
** like this:
**
**   Hash h;
**   HashElem *p;
**   ...
**   for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
**     SomeStructure *pData = sqliteHashData(p);
**     // do something with pData
**   }
*/
#define sqliteHashFirst(H)  ((H)->first)
#define sqliteHashNext(E)   ((E)->next)
#define sqliteHashData(E)   ((E)->data)
#define sqliteHashKey(E)    ((E)->pKey)
#define sqliteHashKeysize(E) ((E)->nKey)

/*
** Number of entries in a hash table
*/
/* #define sqliteHashCount(H)  ((H)->count) // NOT USED */

#endif /* _SQLITE4_HASH_H_ */

/************** End of hash.h ************************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include parse.h in the middle of sqliteInt.h *****************/
/************** Begin file parse.h *******************************************/
#define TK_SEMI                            1
#define TK_EXPLAIN                         2
#define TK_QUERY                           3
#define TK_PLAN                            4
#define TK_BEGIN                           5
#define TK_TRANSACTION                     6
#define TK_DEFERRED                        7
#define TK_IMMEDIATE                       8
#define TK_EXCLUSIVE                       9
#define TK_COMMIT                         10
#define TK_END                            11
#define TK_ROLLBACK                       12
#define TK_SAVEPOINT                      13
#define TK_RELEASE                        14
#define TK_TO                             15
#define TK_TABLE                          16
#define TK_CREATE                         17
#define TK_IF                             18
#define TK_NOT                            19
#define TK_EXISTS                         20
#define TK_TEMP                           21
#define TK_LP                             22
#define TK_RP                             23
#define TK_AS                             24
#define TK_COMMA                          25
#define TK_ID                             26
#define TK_INDEXED                        27
#define TK_ABORT                          28
#define TK_ACTION                         29
#define TK_AFTER                          30
#define TK_ANALYZE                        31
#define TK_ASC                            32
#define TK_ATTACH                         33
#define TK_BEFORE                         34
#define TK_BY                             35
#define TK_CASCADE                        36
#define TK_CAST                           37
#define TK_COLUMNKW                       38
#define TK_CONFLICT                       39
#define TK_DATABASE                       40
#define TK_DESC                           41
#define TK_DETACH                         42
#define TK_EACH                           43
#define TK_FAIL                           44
#define TK_FOR                            45
#define TK_IGNORE                         46
#define TK_INITIALLY                      47
#define TK_INSTEAD                        48
#define TK_LIKE_KW                        49
#define TK_MATCH                          50
#define TK_NO                             51
#define TK_KEY                            52
#define TK_OF                             53
#define TK_OFFSET                         54
#define TK_PRAGMA                         55
#define TK_RAISE                          56
#define TK_REPLACE                        57
#define TK_RESTRICT                       58
#define TK_ROW                            59
#define TK_TRIGGER                        60
#define TK_VIEW                           61
#define TK_VIRTUAL                        62
#define TK_REINDEX                        63
#define TK_RENAME                         64
#define TK_CTIME_KW                       65
#define TK_ANY                            66
#define TK_OR                             67
#define TK_AND                            68
#define TK_IS                             69
#define TK_BETWEEN                        70
#define TK_IN                             71
#define TK_ISNULL                         72
#define TK_NOTNULL                        73
#define TK_NE                             74
#define TK_EQ                             75
#define TK_GT                             76
#define TK_LE                             77
#define TK_LT                             78
#define TK_GE                             79
#define TK_ESCAPE                         80
#define TK_BITAND                         81
#define TK_BITOR                          82
#define TK_LSHIFT                         83
#define TK_RSHIFT                         84
#define TK_PLUS                           85
#define TK_MINUS                          86
#define TK_STAR                           87
#define TK_SLASH                          88
#define TK_REM                            89
#define TK_CONCAT                         90
#define TK_COLLATE                        91
#define TK_BITNOT                         92
#define TK_STRING                         93
#define TK_JOIN_KW                        94
#define TK_CONSTRAINT                     95
#define TK_DEFAULT                        96
#define TK_NULL                           97
#define TK_PRIMARY                        98
#define TK_UNIQUE                         99
#define TK_CHECK                          100
#define TK_REFERENCES                     101
#define TK_AUTOINCR                       102
#define TK_ON                             103
#define TK_INSERT                         104
#define TK_DELETE                         105
#define TK_UPDATE                         106
#define TK_SET                            107
#define TK_DEFERRABLE                     108
#define TK_FOREIGN                        109
#define TK_DROP                           110
#define TK_UNION                          111
#define TK_ALL                            112
#define TK_EXCEPT                         113
#define TK_INTERSECT                      114
#define TK_SELECT                         115
#define TK_DISTINCT                       116
#define TK_DOT                            117
#define TK_FROM                           118
#define TK_JOIN                           119
#define TK_USING                          120
#define TK_ORDER                          121
#define TK_GROUP                          122
#define TK_HAVING                         123
#define TK_LIMIT                          124
#define TK_WHERE                          125
#define TK_INTO                           126
#define TK_VALUES                         127
#define TK_INTEGER                        128
#define TK_FLOAT                          129
#define TK_BLOB                           130
#define TK_REGISTER                       131
#define TK_VARIABLE                       132
#define TK_CASE                           133
#define TK_WHEN                           134
#define TK_THEN                           135
#define TK_ELSE                           136
#define TK_INDEX                          137
#define TK_COVERING                       138
#define TK_ALTER                          139
#define TK_ADD                            140
#define TK_TO_TEXT                        141
#define TK_TO_BLOB                        142
#define TK_TO_NUMERIC                     143
#define TK_TO_INT                         144
#define TK_TO_REAL                        145
#define TK_ISNOT                          146
#define TK_END_OF_FILE                    147
#define TK_ILLEGAL                        148
#define TK_SPACE                          149
#define TK_UNCLOSED_STRING                150
#define TK_FUNCTION                       151
#define TK_COLUMN                         152
#define TK_AGG_FUNCTION                   153
#define TK_AGG_COLUMN                     154
#define TK_CONST_FUNC                     155
#define TK_UMINUS                         156
#define TK_UPLUS                          157

/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>
#include <ctype.h>    /* FIXME - can we omit this one? */

/*
** If compiling for a processor that lacks floating point support,
** substitute integer for floating-point
*/
#ifdef SQLITE4_OMIT_FLOATING_POINT
# define double sqlite4_int64
# define float sqlite4_int64
# define LONGDOUBLE_TYPE sqlite4_int64
# ifndef SQLITE4_BIG_DBL
#   define SQLITE4_BIG_DBL (((sqlite4_int64)1)<<50)
# endif
# define SQLITE4_OMIT_DATETIME_FUNCS 1
# define SQLITE4_OMIT_TRACE 1
# undef SQLITE4_MIXED_ENDIAN_64BIT_FLOAT
# undef SQLITE4_HAVE_ISNAN
#endif
#ifndef SQLITE4_BIG_DBL
# define SQLITE4_BIG_DBL (1e99)
#endif

/*
** OMIT_TEMPDB is set to 1 if SQLITE4_OMIT_TEMPDB is defined, or 0
** afterward. Having this macro allows us to cause the C compiler 
** to omit code used by TEMP tables without messy #ifndef statements.
*/
#ifdef SQLITE4_OMIT_TEMPDB
#define OMIT_TEMPDB 1
#else
#define OMIT_TEMPDB 0
#endif

/*
** Provide a default value for SQLITE4_TEMP_STORE in case it is not specified
** on the command-line
*/
#ifndef SQLITE4_TEMP_STORE
# define SQLITE4_TEMP_STORE 1
#endif

/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves.
*/
#ifndef offsetof
#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
#endif

/* 
** Macros to compute minimum and maximum of two numbers.
*/
#define MIN(A,B) ((A)<(B)?(A):(B))
#define MAX(A,B) ((A)>(B)?(A):(B))

/*
** Check to see if this machine uses EBCDIC.  (Yes, believe it or
** not, there are still machines out there that use EBCDIC.)
*/
#if 'A' == '\301'
# define SQLITE4_EBCDIC 1
#else
# define SQLITE4_ASCII 1
#endif

/*
** Integers of known sizes.  These typedefs might change for architectures
** where the sizes very.  Preprocessor macros are available so that the
** types can be conveniently redefined at compile-type.  Like this:
**
**         cc '-DUINTPTR_TYPE=long long int' ...
*/
#ifndef UINT32_TYPE
# ifdef HAVE_UINT32_T
#  define UINT32_TYPE uint32_t
# else
#  define UINT32_TYPE unsigned int
# endif
#endif
#ifndef UINT16_TYPE
# ifdef HAVE_UINT16_T
#  define UINT16_TYPE uint16_t
# else
#  define UINT16_TYPE unsigned short int
# endif
#endif
#ifndef INT16_TYPE
# ifdef HAVE_INT16_T
#  define INT16_TYPE int16_t
# else
#  define INT16_TYPE short int
# endif
#endif
#ifndef UINT8_TYPE
# ifdef HAVE_UINT8_T
#  define UINT8_TYPE uint8_t
# else
#  define UINT8_TYPE unsigned char
# endif
#endif
#ifndef INT8_TYPE
# ifdef HAVE_INT8_T
#  define INT8_TYPE int8_t
# else
#  define INT8_TYPE signed char
# endif
#endif
#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif
typedef sqlite4_int64 i64;          /* 8-byte signed integer */
typedef sqlite4_uint64 u64;         /* 8-byte unsigned integer */
typedef UINT32_TYPE u32;           /* 4-byte unsigned integer */
typedef UINT16_TYPE u16;           /* 2-byte unsigned integer */
typedef INT16_TYPE i16;            /* 2-byte signed integer */
typedef UINT8_TYPE u8;             /* 1-byte unsigned integer */
typedef INT8_TYPE i8;              /* 1-byte signed integer */

/*
** SQLITE4_MAX_U32 is a u64 constant that is the maximum u64 value
** that can be stored in a u32 without loss of data.  The value
** is 0x00000000ffffffff.  But because of quirks of some compilers, we
** have to specify the value in the less intuitive manner shown:
*/
#define SQLITE4_MAX_U32  ((((u64)1)<<32)-1)

/*
** In the sqlite4_num object, the maximum exponent value.  Values
** larger than this are +Inf, or -Inf, or NaN.
*/
#define SQLITE4_MX_EXP   999    /* Maximum exponent */
#define SQLITE4_NAN_EXP 2000    /* Exponent to use for NaN */

/*
** The datatype used to store estimates of the number of rows in a
** table or index.  This is an unsigned integer type.  For 99.9% of
** the world, a 32-bit integer is sufficient.  But a 64-bit integer
** can be used at compile-time if desired.
*/
#ifdef SQLITE4_64BIT_STATS
 typedef u64 tRowcnt;    /* 64-bit only if requested at compile-time */
#else
 typedef u32 tRowcnt;    /* 32-bit is the default */
#endif

/*
** Macros to determine whether the machine is big or little endian,
** evaluated at runtime.
*/
#ifdef SQLITE4_AMALGAMATION
SQLITE4_PRIVATE const int sqlite4one = 1;
#else
SQLITE4_PRIVATE const int sqlite4one;
#endif
#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
                             || defined(__x86_64) || defined(__x86_64__)
# define SQLITE4_BIGENDIAN    0
# define SQLITE4_LITTLEENDIAN 1
# define SQLITE4_UTF16NATIVE  SQLITE4_UTF16LE
#else
# define SQLITE4_BIGENDIAN    (*(char *)(&sqlite4one)==0)
# define SQLITE4_LITTLEENDIAN (*(char *)(&sqlite4one)==1)
# define SQLITE4_UTF16NATIVE (SQLITE4_BIGENDIAN?SQLITE4_UTF16BE:SQLITE4_UTF16LE)
#endif

/*
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/
#define LARGEST_INT64  (0xffffffff|(((i64)0x7fffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
#define LARGEST_UINT64  (0xffffffff|(((u64)0xffffffff)<<32))

/*
** Constants for the largest and smallest possible 32-bit signed integers.
*/
#define LARGEST_INT32  0x7fffffff
#define SMALLEST_INT32 (-LARGEST_INT32 - 1) 

/* 
** Round up a number to the next larger multiple of 8.  This is used
** to force 8-byte alignment on 64-bit architectures.
*/
#define ROUND8(x)     (((x)+7)&~7)

/*
** Round down to the nearest multiple of 8
*/
#define ROUNDDOWN8(x) ((x)&~7)

/*
** Min and max macros.
*/
#define SQLITE4_MIN(a,b) (((a)<(b)) ? (a) : (b))
#define SQLITE4_MAX(a,b) (((a)>(b)) ? (a) : (b))

/*
** Assert that the pointer X is aligned to an 8-byte boundary.  This
** macro is used only within assert() to verify that the code gets
** all alignment restrictions correct.
**
** Except, if SQLITE4_4_BYTE_ALIGNED_MALLOC is defined, then the
** underlying malloc() implemention might return us 4-byte aligned
** pointers.  In that case, only verify 4-byte alignment.
*/
#ifdef SQLITE4_4_BYTE_ALIGNED_MALLOC
# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&3)==0)
#else
# define EIGHT_BYTE_ALIGNMENT(X)   ((((char*)(X) - (char*)0)&7)==0)
#endif


/*
** Name of the master database table.  The master database table
** is a special table that holds the names and attributes of all
** user tables and indices.
*/
#define MASTER_NAME       "sqlite_master"
#define TEMP_MASTER_NAME  "sqlite_temp_master"

/*
** The root-page of the master database table.
*/
#define MASTER_ROOT       1
#define KVSTORE_ROOT      0x7fffffff

#define IsKvstore(pTab) ((pTab)->pIndex && (pTab)->pIndex->tnum==KVSTORE_ROOT)

/*
** The name of the schema table.
*/
#define SCHEMA_TABLE(x)  ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)

/*
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))

/*
** Determine if the argument is a power of two
*/
#define IsPowerOfTwo(X) (((X)&((X)-1))==0)

/*
** The following macros are used to suppress compiler warnings and to
** make it clear to human readers when a function parameter is deliberately 
** left unused within the body of a function. This usually happens when
** a function is called via a function pointer. For example the 
** implementation of an SQL aggregate step callback may not use the
** parameter indicating the number of arguments passed to the aggregate,
** if it knows that this is enforced elsewhere.
**
** When a function parameter is not used at all within the body of a function,
** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
** However, these macros may also be used to suppress warnings related to
** parameters that may or may not be used depending on compilation options.
** For example those parameters only used in assert() statements. In these
** cases the parameters are named as per the usual conventions.
*/
#define UNUSED_PARAMETER(x) (void)(x)
#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)

/*
** Forward references to structures
*/
typedef struct AggInfo AggInfo;
typedef struct AggInfoCol AggInfoCol;
typedef struct AggInfoFunc AggInfoFunc;
typedef struct Authorizer Authorizer;
typedef struct AuthContext AuthContext;
typedef struct AutoincInfo AutoincInfo;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
typedef struct CreateIndex CreateIndex;
typedef struct Db Db;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct ExprListItem ExprListItem;
typedef struct ExprSpan ExprSpan;
typedef struct FKey FKey;
typedef struct FuncDef FuncDef;
typedef struct FuncDefTable FuncDefTable;
typedef struct Fts5Tokenizer Fts5Tokenizer;
typedef struct Fts5Index Fts5Index;
typedef struct Fts5Info Fts5Info;
typedef struct Fts5Cursor Fts5Cursor;
typedef struct IdList IdList;
typedef struct IdListItem IdListItem;
typedef struct Index Index;
typedef struct IndexSample IndexSample;
typedef struct KeyClass KeyClass;
typedef struct KeyInfo KeyInfo;
typedef struct Lookaside Lookaside;
typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
typedef struct Parse Parse;
typedef struct ParseYColCache ParseYColCache;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct Sqlite4InitInfo Sqlite4InitInfo;
typedef struct SrcList SrcList;
typedef struct SrcListItem SrcListItem;
typedef struct StrAccum StrAccum;
typedef struct Table Table;
typedef struct Token Token;
typedef struct Trigger Trigger;
typedef struct TriggerPrg TriggerPrg;
typedef struct TriggerStep TriggerStep;
typedef struct VTable VTable;
typedef struct VtabCtx VtabCtx;
typedef struct Walker Walker;
typedef struct WherePlan WherePlan;
typedef struct WhereInfo WhereInfo;
typedef struct WhereLevel WhereLevel;


/************** Include vdbe.h in the middle of sqliteInt.h ******************/
/************** Begin file vdbe.h ********************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
*/
#ifndef _SQLITE4_VDBE_H_
#define _SQLITE4_VDBE_H_
/* #include <stdio.h> */

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
** in the source file sqliteVdbe.c are allowed to see the insides
** of this structure.
*/
typedef struct Vdbe Vdbe;

/*
** The names of the following types declared in vdbeInt.h are required
** for the VdbeOp definition.
*/
typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
typedef struct SubProgram SubProgram;
typedef struct VdbeCursor VdbeCursor;

/*
** A single instruction of the virtual machine has an opcode
** and as many as three operands.  The instruction is recorded
** as an instance of the following structure:
*/
struct VdbeOp {
  u8 opcode;          /* What operation to perform */
  signed char p4type; /* One of the P4_xxx constants for p4 */
  u8 opflags;         /* Mask of the OPFLG_* flags in opcodes.h */
  u8 p5;              /* Fifth parameter is an unsigned character */
  int p1;             /* First operand */
  int p2;             /* Second parameter (often the jump destination) */
  int p3;             /* The third parameter */
  union {             /* fourth parameter */
    int i;                 /* Integer value if p4type==P4_INT32 */
    void *p;               /* Generic pointer */
    char *z;               /* Pointer to data for string (char array) types */
    sqlite4_num *pNum;     /* Used when p4type is P4_NUM */
    FuncDef *pFunc;        /* Used when p4type is P4_FUNCDEF */
    VdbeFunc *pVdbeFunc;   /* Used when p4type is P4_VDBEFUNC */
    CollSeq *pColl;        /* Used when p4type is P4_COLLSEQ */
    Mem *pMem;             /* Used when p4type is P4_MEM */
    VTable *pVtab;         /* Used when p4type is P4_VTAB */
    KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
    int *ai;               /* Used when p4type is P4_INTARRAY */
    SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
    Fts5Info *pFtsInfo;    /* Used when p4type is P4_FTS5INDEXINFO */
    int (*xAdvance)(VdbeCursor*);  /* Used with p4type==P4_ADVANCE */
  } p4;
#ifdef SQLITE4_DEBUG
  char *zComment;          /* Comment to improve readability */
#endif
#ifdef VDBE_PROFILE
  int cnt;                 /* Number of times this instruction was executed */
  u64 cycles;              /* Total time spent executing this instruction */
#endif
};
typedef struct VdbeOp VdbeOp;


/*
** A sub-routine used to implement a trigger program.
*/
struct SubProgram {
  VdbeOp *aOp;                  /* Array of opcodes for sub-program */
  int nOp;                      /* Elements in aOp[] */
  int nMem;                     /* Number of memory cells required */
  int nCsr;                     /* Number of cursors required */
  int nOnce;                    /* Number of OP_Once instructions */
  void *token;                  /* id that may be used to recursive triggers */
  SubProgram *pNext;            /* Next sub-program already visited */
};

/*
** A smaller version of VdbeOp used for the VdbeAddOpList() function because
** it takes up less space.
*/
struct VdbeOpList {
  u8 opcode;          /* What operation to perform */
  signed char p1;     /* First operand */
  signed char p2;     /* Second parameter (often the jump destination) */
  signed char p3;     /* Third parameter */
};
typedef struct VdbeOpList VdbeOpList;

/*
** Allowed values of VdbeOp.p4type.  All values are less than 1 so that
** they can be used unambiguously in the "length" parameter of various
** interfaces.
*/
#define P4_NOTUSED       0   /* The P4 parameter is not used */
#define P4_TRANSIENT     0   /* P4 is a pointer to a transient string */
#define P4_DYNAMIC     (-1)  /* Pointer to a string obtained from malloc() */
#define P4_STATIC      (-2)  /* Pointer to a static string */
#define P4_COLLSEQ     (-3)  /* P4 is a pointer to a CollSeq structure */
#define P4_FUNCDEF     (-4)  /* P4 is a pointer to a FuncDef structure */
#define P4_KEYINFO     (-5)  /* P4 is a pointer to a KeyInfo structure */
#define P4_VDBEFUNC    (-6)  /* P4 is a pointer to a VdbeFunc structure */
#define P4_MEM         (-7)  /* P4 is a pointer to a Mem*    structure */
#define P4_VTAB        (-8)  /* P4 is a pointer to an sqlite4_vtab structure */
#define P4_NUM         (-9)  /* P4 is a pointer to an sqlite4_num structure */
#define P4_INT32      (-10)  /* P4 is a 32-bit signed integer */
#define P4_INTARRAY   (-11)  /* P4 is a vector of 32-bit integers */
#define P4_SUBPROGRAM (-12)  /* P4 is a pointer to a SubProgram structure */
#define P4_ADVANCE    (-13)  /* P4 is a pointer to BtreeNext() or BtreePrev() */
#define P4_FTS5INFO   (-14)  /* P4 points to an Fts5Info structure */

/* 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
** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used.  It still
** gets freed when the Vdbe is finalized so it still should be obtained
** from a single sqliteMalloc().  But no copy is made and the calling
** function should *not* try to free the KeyInfo.
*/
#define P4_KEYINFO_HANDOFF  (-124)
#define P4_KEYINFO_STATIC   (-125)

/*
** The Vdbe.aColName array contains 5n Mem structures, where n is the 
** number of columns of data returned by the statement.
*/
#define COLNAME_NAME     0
#define COLNAME_DECLTYPE 1
#define COLNAME_DATABASE 2
#define COLNAME_TABLE    3
#define COLNAME_COLUMN   4
#ifdef SQLITE4_ENABLE_COLUMN_METADATA
# define COLNAME_N        5      /* Number of COLNAME_xxx symbols */
#else
# ifdef SQLITE4_OMIT_DECLTYPE
#   define COLNAME_N      1      /* Store only the name */
# else
#   define COLNAME_N      2      /* Store the name and decltype */
# endif
#endif

/*
** The following macro converts a relative address in the p2 field
** of a VdbeOp structure into a negative number so that 
** sqlite4VdbeAddOpList() knows that the address is relative.  Calling
** the macro again restores the address.
*/
#define ADDR(X)  (-1-(X))

/*
** The makefile scans the vdbe.c source file and creates the "opcodes.h"
** header file that defines a number for each opcode used by the VDBE.
*/
/************** Include opcodes.h in the middle of vdbe.h ********************/
/************** Begin file opcodes.h *****************************************/
/* Automatically generated.  Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_Goto                                 1
#define OP_Gosub                                2
#define OP_Return                               3
#define OP_Yield                                4
#define OP_HaltIfNull                           5
#define OP_Halt                                 6
#define OP_Integer                              7
#define OP_Num                                  8
#define OP_String8                             93   /* same as TK_STRING   */
#define OP_String                               9
#define OP_Null                                10
#define OP_Blob                                11
#define OP_Variable                            12
#define OP_Move                                13
#define OP_Copy                                14
#define OP_SCopy                               15
#define OP_ResultRow                           16
#define OP_Concat                              90   /* same as TK_CONCAT   */
#define OP_Add                                 85   /* same as TK_PLUS     */
#define OP_Subtract                            86   /* same as TK_MINUS    */
#define OP_Multiply                            87   /* same as TK_STAR     */
#define OP_Divide                              88   /* same as TK_SLASH    */
#define OP_Remainder                           89   /* same as TK_REM      */
#define OP_CollSeq                             17
#define OP_KVMethod                            18
#define OP_Mifunction                          20
#define OP_Function                            21
#define OP_BitAnd                              81   /* same as TK_BITAND   */
#define OP_BitOr                               82   /* same as TK_BITOR    */
#define OP_ShiftLeft                           83   /* same as TK_LSHIFT   */
#define OP_ShiftRight                          84   /* same as TK_RSHIFT   */
#define OP_AddImm                              22
#define OP_MustBeInt                           23
#define OP_RealAffinity                        24
#define OP_ToText                             141   /* same as TK_TO_TEXT  */
#define OP_ToBlob                             142   /* same as TK_TO_BLOB  */
#define OP_ToNumeric                          143   /* same as TK_TO_NUMERIC*/
#define OP_ToInt                              144   /* same as TK_TO_INT   */
#define OP_ToReal                             145   /* same as TK_TO_REAL  */
#define OP_Eq                                  75   /* same as TK_EQ       */
#define OP_Ne                                  74   /* same as TK_NE       */
#define OP_Lt                                  78   /* same as TK_LT       */
#define OP_Le                                  77   /* same as TK_LE       */
#define OP_Gt                                  76   /* same as TK_GT       */
#define OP_Ge                                  79   /* same as TK_GE       */
#define OP_Permutation                         25
#define OP_Compare                             26
#define OP_Jump                                27
#define OP_And                                 68   /* same as TK_AND      */
#define OP_Or                                  67   /* same as TK_OR       */
#define OP_Not                                 19   /* same as TK_NOT      */
#define OP_BitNot                              92   /* same as TK_BITNOT   */
#define OP_Once                                28
#define OP_If                                  29
#define OP_IfNot                               30
#define OP_IsNull                              72   /* same as TK_ISNULL   */
#define OP_NotNull                             73   /* same as TK_NOTNULL  */
#define OP_Column                              31
#define OP_MakeKey                             32
#define OP_MakeRecord                          33
#define OP_Affinity                            34
#define OP_Count                               35
#define OP_Savepoint                           36
#define OP_Transaction                         37
#define OP_ReadCookie                          38
#define OP_SetCookie                           39
#define OP_VerifyCookie                        40
#define OP_OpenRead                            41
#define OP_OpenWrite                           42
#define OP_OpenAutoindex                       43
#define OP_OpenEphemeral                       44
#define OP_SorterOpen                          45
#define OP_Close                               46
#define OP_SeekPk                              47
#define OP_SeekLt                              48
#define OP_SeekLe                              49
#define OP_SeekGe                              50
#define OP_SeekGt                              51
#define OP_NotExists                           52
#define OP_NotFound                            53
#define OP_Found                               54
#define OP_IsUnique                            55
#define OP_Sequence                            56
#define OP_NewRowid                            57
#define OP_NewIdxid                            58
#define OP_Delete                              59
#define OP_ResetCount                          60
#define OP_GrpCompare                          61
#define OP_SorterData                          62
#define OP_RowKey                              63
#define OP_RowData                             64
#define OP_AnalyzeKey                          65
#define OP_Rowid                               66
#define OP_NullRow                             69
#define OP_Last                                70
#define OP_SorterSort                          71
#define OP_Sort                                80
#define OP_Rewind                              91
#define OP_SorterNext                          94
#define OP_Prev                                95
#define OP_Next                                96
#define OP_Insert                              97
#define OP_IdxDelete                           98
#define OP_IdxRowkey                           99
#define OP_IdxLT                              100
#define OP_IdxLE                              101
#define OP_IdxGE                              102
#define OP_IdxGT                              103
#define OP_Clear                              104
#define OP_ParseSchema                        105
#define OP_LoadAnalysis                       106
#define OP_DropTable                          107
#define OP_DropIndex                          108
#define OP_DropTrigger                        109
#define OP_RowSetTest                         110
#define OP_RowSetAdd                          111
#define OP_RowSetRead                         112
#define OP_Program                            113
#define OP_Param                              114
#define OP_FkCounter                          115
#define OP_FkIfZero                           116
#define OP_MemMax                             117
#define OP_IfPos                              118
#define OP_IfNeg                              119
#define OP_IfZero                             120
#define OP_AggStep                            121
#define OP_AggFinal                           122
#define OP_JournalMode                        123
#define OP_Expire                             124
#define OP_VBegin                             125
#define OP_VCreate                            126
#define OP_VDestroy                           127
#define OP_VOpen                              128
#define OP_VFilter                            129
#define OP_VColumn                            130
#define OP_VNext                              131
#define OP_VRename                            132
#define OP_VUpdate                            133
#define OP_Trace                              134
#define OP_FtsUpdate                          135
#define OP_FtsCksum                           136
#define OP_FtsOpen                            137
#define OP_FtsNext                            138
#define OP_FtsPk                              139
#define OP_Noop                               140
#define OP_Explain                            146


/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP            0x0001  /* jump:  P2 holds jmp target */
#define OPFLG_OUT2_PRERELEASE 0x0002  /* out2-prerelease: */
#define OPFLG_IN1             0x0004  /* in1:   P1 is an input */
#define OPFLG_IN2             0x0008  /* in2:   P2 is an input */
#define OPFLG_IN3             0x0010  /* in3:   P3 is an input */
#define OPFLG_OUT2            0x0020  /* out2:  P2 is an output */
#define OPFLG_OUT3            0x0040  /* out3:  P3 is an output */
#define OPFLG_INITIALIZER {\
/*   0 */ 0x00, 0x01, 0x01, 0x04, 0x04, 0x10, 0x00, 0x02,\
/*   8 */ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x24, 0x24,\
/*  16 */ 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x04, 0x05,\
/*  24 */ 0x04, 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00,\
/*  32 */ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x10,\
/*  40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
/*  48 */ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,\
/*  56 */ 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,\
/*  64 */ 0x00, 0x00, 0x02, 0x4c, 0x4c, 0x00, 0x01, 0x01,\
/*  72 */ 0x05, 0x05, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,\
/*  80 */ 0x01, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,\
/*  88 */ 0x4c, 0x4c, 0x4c, 0x01, 0x24, 0x02, 0x01, 0x01,\
/*  96 */ 0x01, 0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01,\
/* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x14,\
/* 112 */ 0x04, 0x01, 0x02, 0x00, 0x01, 0x08, 0x05, 0x05,\
/* 120 */ 0x05, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,\
/* 128 */ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\
/* 136 */ 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04,\
/* 144 */ 0x04, 0x04, 0x00,}

/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
SQLITE4_PRIVATE Vdbe *sqlite4VdbeCreate(sqlite4*);
SQLITE4_PRIVATE int sqlite4VdbeAddOp0(Vdbe*,int);
SQLITE4_PRIVATE int sqlite4VdbeAddOp1(Vdbe*,int,int);
SQLITE4_PRIVATE int sqlite4VdbeAddOp2(Vdbe*,int,int,int);
SQLITE4_PRIVATE int sqlite4VdbeAddOp3(Vdbe*,int,int,int,int);
SQLITE4_PRIVATE int sqlite4VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
SQLITE4_PRIVATE int sqlite4VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
SQLITE4_PRIVATE int sqlite4VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
SQLITE4_PRIVATE void sqlite4VdbeAddParseSchemaOp(Vdbe*,int,char*);
SQLITE4_PRIVATE void sqlite4VdbeChangeP1(Vdbe*, u32 addr, int P1);
SQLITE4_PRIVATE void sqlite4VdbeChangeP2(Vdbe*, u32 addr, int P2);
SQLITE4_PRIVATE void sqlite4VdbeChangeP3(Vdbe*, u32 addr, int P3);
SQLITE4_PRIVATE void sqlite4VdbeChangeP5(Vdbe*, u8 P5);
SQLITE4_PRIVATE void sqlite4VdbeJumpHere(Vdbe*, int addr);
SQLITE4_PRIVATE void sqlite4VdbeChangeToNoop(Vdbe*, int addr);
SQLITE4_PRIVATE void sqlite4VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
SQLITE4_PRIVATE void sqlite4VdbeUsesStorage(Vdbe*, int);
SQLITE4_PRIVATE VdbeOp *sqlite4VdbeGetOp(Vdbe*, int);
SQLITE4_PRIVATE int sqlite4VdbeMakeLabel(Vdbe*);
SQLITE4_PRIVATE void sqlite4VdbeRunOnlyOnce(Vdbe*);
SQLITE4_PRIVATE void sqlite4VdbeDelete(Vdbe*);
SQLITE4_PRIVATE void sqlite4VdbeDeleteObject(sqlite4*,Vdbe*);
SQLITE4_PRIVATE void sqlite4VdbeMakeReady(Vdbe*,Parse*);
SQLITE4_PRIVATE int sqlite4VdbeFinalize(Vdbe*);
SQLITE4_PRIVATE void sqlite4VdbeResolveLabel(Vdbe*, int);
SQLITE4_PRIVATE int sqlite4VdbeCurrentAddr(Vdbe*);
#ifdef SQLITE4_DEBUG
SQLITE4_PRIVATE   int sqlite4VdbeAssertMayAbort(Vdbe *, int);
SQLITE4_PRIVATE   void sqlite4VdbeTrace(Vdbe*,FILE*);
#endif
SQLITE4_PRIVATE void sqlite4VdbeResetStepResult(Vdbe*);
SQLITE4_PRIVATE void sqlite4VdbeRewind(Vdbe*);
SQLITE4_PRIVATE int sqlite4VdbeReset(Vdbe*);
SQLITE4_PRIVATE void sqlite4VdbeSetNumCols(Vdbe*,int);
SQLITE4_PRIVATE int sqlite4VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*,void*));
SQLITE4_PRIVATE void sqlite4VdbeCountChanges(Vdbe*);
SQLITE4_PRIVATE sqlite4 *sqlite4VdbeDb(Vdbe*);
SQLITE4_PRIVATE void sqlite4VdbeSetSql(Vdbe*, const char *z, int n);
SQLITE4_PRIVATE void sqlite4VdbeSwap(Vdbe*,Vdbe*);
SQLITE4_PRIVATE VdbeOp *sqlite4VdbeTakeOpArray(Vdbe*, int*, int*);
SQLITE4_PRIVATE sqlite4_value *sqlite4VdbeGetValue(Vdbe*, int, u8);
SQLITE4_PRIVATE void sqlite4VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE4_OMIT_TRACE
SQLITE4_PRIVATE   char *sqlite4VdbeExpandSql(Vdbe*, const char*);
#endif
SQLITE4_PRIVATE sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol);

#ifndef SQLITE4_OMIT_TRIGGER
SQLITE4_PRIVATE void sqlite4VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif

SQLITE4_PRIVATE int sqlite4VdbeEncodeKey(
  sqlite4 *db,                 /* The database connection */
  Mem *aIn,                    /* Values to be encoded */
  int nIn,                     /* Number of entries in aIn[] */
  int iTabno,                  /* The table this key applies to */
  KeyInfo *pKeyInfo,           /* Collating sequence information */
  u8 **pzOut,                  /* Write the resulting key here */
  int *pnOut,                  /* Number of bytes in the key */
  int nExtra                   /* Append extra bytes on end of key */
);

#ifndef NDEBUG
SQLITE4_PRIVATE   void sqlite4VdbeComment(Vdbe*, const char*, ...);
# define VdbeComment(X)  sqlite4VdbeComment X
SQLITE4_PRIVATE   void sqlite4VdbeNoopComment(Vdbe*, const char*, ...);
# define VdbeNoopComment(X)  sqlite4VdbeNoopComment X
#else
# define VdbeComment(X)
# define VdbeNoopComment(X)
#endif

#endif

/************** End of vdbe.h ************************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include kv.h in the middle of sqliteInt.h ********************/
/************** Begin file kv.h **********************************************/
/*
** 2012 January 20
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This header file defines the interface to the KV storage engine(s).
**
** Notes on the storage subsystem interface:
** 
** The storage subsystem is a key/value database.  All keys and values are
** binary with arbitrary content.  Keys are unique.  Keys compare in
** memcmp() order.  Shorter keys appear first.
** 
** The xBegin, xCommit, and xRollback methods change the transaction level
** of the store.  The transaction level is a non-negative integer that is
** initialized to zero.  The transaction level must be at least 1 in order
** for content to be read.  The transaction level must be at least 2 for 
** content to be modified.
** 
** The xBegin method increases transaction level.  The increase may be no
** more than 1 unless the transaction level is initially 0 in which case
** it can be increased immediately to 2.  Increasing the transaction level
** to 1 or more makes a "snapshot" of the database file such that changes
** made by other connections are not visible.  Calls to xBegin may fail
** with SQLITE4_BUSY if the initial transaction level is 0 or 1.
** 
** A read-only database will fail an attempt to increase xBegin above 1.  An
** implementation that does not support nested transactions will fail any
** attempt to increase the transaction level above 2.
** 
** The xCommitPhaseOne and xCommitPhaseTwo methods implement a 2-phase
** commit that lowers the transaction level to the value given in the
** second argument, making all the changes made at higher transaction levels
** permanent.  A rollback is still possible following phase one.  If
** possible, errors should be reported during phase one so that a
** multiple-database transaction can still be rolled back if the
** phase one fails on a different database.  Implementations that do not
** support two-phase commit can implement xCommitPhaseOne as a no-op function
** returning SQLITE4_OK.
** 
** The xRollback method lowers the transaction level to the value given in
** its argument and reverts or undoes all changes made at higher transaction
** levels.  An xRollback to level N causes the database to revert to the state
** it was in on the most recent xBegin to level N+1.
** 
** The xRevert(N) method causes the state of the database file to go back
** to what it was immediately after the most recent xCommit(N).  Higher-level
** subtransactions are cancelled.  This call is equivalent to xRollback(N-1)
** followed by xBegin(N) but is atomic and might be more efficient.
** 
** The xReplace method replaces the value for an existing entry with the
** given key, or creates a new entry with the given key and value if no
** prior entry exists with the given key.  The key and value pointers passed
** into xReplace belong to the caller and will likely be destroyed when the
** call to xReplace returns so the xReplace routine must make its own
** copy of that information if it needs to retain it after returning.
** 
** A cursor is at all times pointing to ether an entry in the database or
** to EOF.  EOF means "no entry".  Cursor operations other than xCloseCursor 
** will fail if the transaction level is less than 1.
** 
** The xSeek method moves a cursor to an entry in the database that matches
** the supplied key as closely as possible.  If the dir argument is 0, then
** the match must be exact or else the seek fails and the cursor is left
** pointing to EOF.  If dir is negative, then an exact match is
** found if it is available, otherwise the cursor is positioned at the largest
** entry that is less than the search key or to EOF if the store contains no
** entry less than the search key.  If dir is positive, then an exist match
** is found if it is available, otherwise the cursor is left pointing the
** the smallest entry that is larger than the search key, or to EOF if there
** are no entries larger than the search key.
**
** The return code from xSeek might be one of the following:
**
**    SQLITE4_OK        The cursor is left pointing to any entry that
**                      exactly matchings the probe key.
**
**    SQLITE4_INEXACT   The cursor is left pointing to the nearest entry
**                      to the probe it could find, either before or after
**                      the probe, according to the dir argument.
**
**    SQLITE4_NOTFOUND  No suitable entry could be found.  Either dir==0 and
**                      there was no exact match, or dir<0 and the probe is
**                      smaller than every entry in the database, or dir>0 and
**                      the probe is larger than every entry in the database.
**
** xSeek might also return some error code like SQLITE4_IOERR or
** SQLITE4_NOMEM.
** 
** The xNext method will only be called following an xSeek with a positive dir,
** or another xNext.  The xPrev method will only be called following an xSeek
** with a negative dir or another xPrev.  Both xNext and xPrev will return
** SQLITE4_OK on success and SQLITE4_NOTFOUND if they run off the end of the
** database.  Both routines might also return error codes such as
** SQLITE4_IOERR, SQLITE4_CORRUPT, or SQLITE4_NOMEM.
** 
** Values returned by xKey and xData are guaranteed to remain stable until
** the next xSeek, xNext, xPrev, xReset, xDelete, or xCloseCursor on the same
** cursor.  This is true even if the transaction level is reduced to zero,
** or if the content of the entry is changed by xInsert, xDelete on a different
** cursor, or xRollback.  The content returned by repeated calls to xKey and
** xData is allowed (but is not required) to change if xInsert, xDelete, or
** xRollback are invoked in between the calls, but the content returned by
** every call must be stable until the cursor moves, or is reset or closed.
** The cursor owns the values returned by xKey and xData and will take
** responsiblity for freeing memory used to hold those values when appropriate.
** 
** The xDelete method deletes the entry that the cursor is currently
** pointing at.  However, subsequent xNext or xPrev calls behave as if the
** entries is not actually deleted until the cursor moves.  In other words
** it is acceptable to xDelete an entry out from under a cursor.  Subsequent
** xNext or xPrev calls on that cursor will work the same as if the entry
** had not been deleted.  Two cursors can be pointing to the same entry and
** one cursor can xDelete and the other cursor is expected to continue
** functioning normally, including responding correctly to subsequent
** xNext and xPrev calls.
** 
** The xGetMethod method allows a key-value store to implement custom PRAGMA 
** commands, or override existing built-in PRAGMAs. Each time the user prepares
** a PRAGMA statement, the xGetMethod method of the corresponding key-value
** store is invoked with the name of the requested PRAGMA passed as the second
** argument.
** 
** If the key-value store will implement the specified PRAGMA, it should 
** populate the output variables and return SQLITE4_OK. If the named PRAGMA 
** is not one that the key-value store implements, it should return 
** SQLITE4_NOTFOUND. If an error occurs, any other SQLite error code may be 
** returned.
** 
** If the xGetMethod invocation returns SQLITE4_OK, the second of the three
** output parameters (pxFunc) should be set to point to a function that will
** be invoked when the prepared statement is executed (i.e. from within an
** sqlite4_step() call). The parameters passed to it are similar to those
** passed to [user-defined function] implementations. The sqlite4_value 
** arguments, if any, are the values specified as part of the PRAGMA 
** statement. The first of the output parameters (ppArg) is used to return
** the context pointer made available to the implementation of the *pxFunc 
** function via sqlite4_context_appdata(). If it is not set to NULL, the
** final output parameter (pxDestroy) may be used to specify a callback that
** is invoked when the SQL statement is finalized. The argument passed to
** the *pxDestroy invocation, if any, is a copy of *ppArg.
** 
** If the xGetMethod invocation returns SQLITE4_OK, then any built-in pragma
** of the same name is not executed.
*/

/* Typedefs of datatypes */
typedef struct sqlite4_kvstore KVStore;
typedef struct sqlite4_kv_methods KVStoreMethods;
typedef struct sqlite4_kvcursor KVCursor;
typedef unsigned char KVByteArray;
typedef sqlite4_kvsize KVSize;

SQLITE4_PRIVATE int sqlite4OpenBtree(sqlite4_env*, KVStore**, const char *, unsigned);
SQLITE4_PRIVATE int sqlite4KVStoreOpenMem(sqlite4_env*, KVStore**, const char *, unsigned);
SQLITE4_PRIVATE int sqlite4KVStoreOpenLsm(sqlite4_env*, KVStore**, const char *, unsigned);
SQLITE4_PRIVATE int sqlite4KVStoreOpen(
  sqlite4*,
  const char *zLabel, 
  const char *zUri,
  KVStore**,
  unsigned flags
);
SQLITE4_PRIVATE int sqlite4KVStoreReplace(
 KVStore*,
 const KVByteArray *pKey, KVSize nKey,
 const KVByteArray *pData, KVSize nData
);
SQLITE4_PRIVATE int sqlite4KVStoreOpenCursor(KVStore *p, KVCursor **ppKVCursor);
SQLITE4_PRIVATE int sqlite4KVCursorSeek(
  KVCursor *p,
  const KVByteArray *pKey, KVSize nKey,
  int dir
);
SQLITE4_PRIVATE int sqlite4KVCursorNext(KVCursor *p);
SQLITE4_PRIVATE int sqlite4KVCursorPrev(KVCursor *p);
SQLITE4_PRIVATE int sqlite4KVCursorDelete(KVCursor *p);
SQLITE4_PRIVATE int sqlite4KVCursorReset(KVCursor *p);
SQLITE4_PRIVATE int sqlite4KVCursorKey(KVCursor *p, const KVByteArray **ppKey, KVSize *pnKey);
SQLITE4_PRIVATE int sqlite4KVCursorData(
  KVCursor *p,
  KVSize ofst,
  KVSize n,
  const KVByteArray **ppData,
  KVSize *pnData
);
SQLITE4_PRIVATE int sqlite4KVCursorClose(KVCursor *p);
SQLITE4_PRIVATE int sqlite4KVStoreBegin(KVStore *p, int iLevel);
SQLITE4_PRIVATE int sqlite4KVStoreCommitPhaseOne(KVStore *p, int iLevel);
SQLITE4_PRIVATE int sqlite4KVStoreCommitPhaseTwo(KVStore *p, int iLevel);
SQLITE4_PRIVATE int sqlite4KVStoreCommit(KVStore *p, int iLevel);
SQLITE4_PRIVATE int sqlite4KVStoreRollback(KVStore *p, int iLevel);
SQLITE4_PRIVATE int sqlite4KVStoreRevert(KVStore *p, int iLevel);
SQLITE4_PRIVATE int sqlite4KVStoreClose(KVStore *p);

SQLITE4_PRIVATE int sqlite4KVStoreGetMeta(KVStore *p, int, int, unsigned int*);
SQLITE4_PRIVATE int sqlite4KVStorePutMeta(sqlite4*, KVStore *p, int, int, unsigned int*);

SQLITE4_PRIVATE int sqlite4KVStorePutSchema(KVStore *p, unsigned int iVal);
SQLITE4_PRIVATE int sqlite4KVStoreGetSchema(KVStore *p, unsigned int *piVal);

#ifdef SQLITE4_DEBUG
SQLITE4_PRIVATE   void sqlite4KVStoreDump(KVStore *p);
#endif

/************** End of kv.h **************************************************/
/************** Continuing where we left off in sqliteInt.h ******************/

/************** Include os.h in the middle of sqliteInt.h ********************/
/************** Begin file os.h **********************************************/
/*
** 2001 September 16
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This header file (together with is companion C source-code file
** "os.c") attempt to abstract the underlying operating system so that
** the SQLite library will work on both POSIX and windows systems.
**
** This header file is #include-ed by sqliteInt.h and thus ends up
** being included by every source file.
*/
#ifndef _SQLITE4_OS_H_
#define _SQLITE4_OS_H_

/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system.  After the following block of preprocess macros,
** all of SQLITE4_OS_UNIX, SQLITE4_OS_WIN, SQLITE4_OS_WINRT, and SQLITE4_OS_OTHER 
** will defined to either 1 or 0.  One of the four will be 1.  The other 
** three will be 0.
*/
#if defined(SQLITE4_OS_OTHER)
# if SQLITE4_OS_OTHER==1
#   undef SQLITE4_OS_UNIX
#   define SQLITE4_OS_UNIX 0
#   undef SQLITE4_OS_WIN
#   define SQLITE4_OS_WIN 0
#   undef SQLITE4_OS_WINRT
#   define SQLITE4_OS_WINRT 0
# else
#   undef SQLITE4_OS_OTHER
# endif
#endif
#if !defined(SQLITE4_OS_UNIX) && !defined(SQLITE4_OS_OTHER)
# define SQLITE4_OS_OTHER 0
# ifndef SQLITE4_OS_WIN
#   if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) \
                       || defined(__MINGW32__) || defined(__BORLANDC__)
#     define SQLITE4_OS_WIN 1
#     define SQLITE4_OS_UNIX 0
#     define SQLITE4_OS_WINRT 0
#   else
#     define SQLITE4_OS_WIN 0
#     define SQLITE4_OS_UNIX 1
#     define SQLITE4_OS_WINRT 0
#  endif
# else
#  define SQLITE4_OS_UNIX 0
#  define SQLITE4_OS_WINRT 0
# endif
#else
# ifndef SQLITE4_OS_WIN
#  define SQLITE4_OS_WIN 0
# endif
#endif

/*
** Define the maximum size of a temporary filename
*/
#if SQLITE4_OS_WIN
# include <windows.h>
# define SQLITE4_TEMPNAME_SIZE (MAX_PATH+50)
#else
# define SQLITE4_TEMPNAME_SIZE 200
#endif

/*
** OS Interface functions.
*/
SQLITE4_PRIVATE int sqlite4OsInit(sqlite4_env*);
SQLITE4_PRIVATE int sqlite4OsRandomness(sqlite4_env*, int, unsigned char*);
SQLITE4_PRIVATE int sqlite4OsCurrentTime(sqlite4_env*, sqlite4_uint64*);

#endif /* _SQLITE4_OS_H_ */

/************** End of os.h **************************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
/************** Include mutex.h in the middle of sqliteInt.h *****************/
/************** Begin file mutex.h *******************************************/
/*
** 2007 August 28
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains the common header for all mutex implementations.
** The sqliteInt.h header #includes this file so that it is available
** to all source files.  We break it out in an effort to keep the code
** better organized.
**
** NOTE:  source files should *not* #include this header file directly.
** Source files should #include the sqliteInt.h file and let that file
** include this one indirectly.
*/


/*
** Figure out what version of the code to use.  The choices are
**
**   SQLITE4_MUTEX_OMIT         No mutex logic.  Not even stubs.  The
**                             mutexes implemention cannot be overridden
**                             at start-time.
**
**   SQLITE4_MUTEX_NOOP         For single-threaded applications.  No
**                             mutual exclusion is provided.  But this
**                             implementation can be overridden at
**                             start-time.
**
**   SQLITE4_MUTEX_PTHREADS     For multi-threaded applications on Unix.
**
**   SQLITE4_MUTEX_W32          For multi-threaded applications on Win32.
*/
#if !SQLITE4_THREADSAFE
# define SQLITE4_MUTEX_OMIT
#endif
#if SQLITE4_THREADSAFE && !defined(SQLITE4_MUTEX_NOOP)
#  if SQLITE4_OS_UNIX
#    define SQLITE4_MUTEX_PTHREADS
#  elif SQLITE4_OS_WIN
#    define SQLITE4_MUTEX_W32
#  else
#    define SQLITE4_MUTEX_NOOP
#  endif
#endif

#ifdef SQLITE4_MUTEX_OMIT
/*
** If this is a no-op implementation, implement everything as macros.
*/
#define sqlite4_mutex_alloc(X,Y)  ((sqlite4_mutex*)8)
#define sqlite4_mutex_free(X)
#define sqlite4_mutex_enter(X)    
#define sqlite4_mutex_try(X)      SQLITE4_OK
#define sqlite4_mutex_leave(X)    
#define sqlite4_mutex_held(X)     ((void)(X),1)
#define sqlite4_mutex_notheld(X)  ((void)(X),1)
#define sqlite4MutexAlloc(X,Y)    ((sqlite4_mutex*)8)
#define sqlite4MutexInit(E)       SQLITE4_OK
#define sqlite4MutexEnd(E)
#define MUTEX_LOGIC(X)
#else
#define MUTEX_LOGIC(X)            X
#endif /* defined(SQLITE4_MUTEX_OMIT) */

/************** End of mutex.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/


/*
** Each database file to be accessed by the system is an instance
** of the following structure.  There are normally two of these structures
** in the sqlite.aDb[] array.  aDb[0] is the main database file and
** aDb[1] is the database file used to hold temporary tables.  Additional
** databases may be attached.
*/
struct Db {
  char *zName;         /* Name of this database */
  KVStore *pKV;        /* KV store for the database file */
  u8 inTrans;          /* 0: not writable.  1: Transaction.  2: Checkpoint */
  u8 chngFlag;         /* True if modified */
  Schema *pSchema;     /* Pointer to database schema (possibly shared) */
};

/*
** Each SQL function is defined by an instance of the following
** structure.  A pointer to this structure is stored in the sqlite.aFunc
** hash table.  When multiple functions have the same name, the hash table
** points to a linked list of these structures.
*/
struct FuncDef {
  i16 nArg;            /* Number of arguments.  -1 means unlimited */
  u8 flags;            /* Some combination of SQLITE4_FUNC_* */
  void *pUserData;     /* User data parameter */
  FuncDef *pSameName;  /* Next with a different name but the same hash */
  void (*xFunc)(sqlite4_context*,int,sqlite4_value**); /* Regular function */
  void (*xStep)(sqlite4_context*,int,sqlite4_value**); /* Aggregate step */
  void (*xFinalize)(sqlite4_context*);                 /* Aggregate finalizer */
  char *zName;         /* SQL name of the function. */
  FuncDef *pNextName;  /* Next function with a different name */
  u8 bMatchinfo;       /* True for matchinfo function */
  void (*xDestroy)(void *);       /* Users destructor function */
};

/*
** A table of SQL functions.  
**
** The content is a linked list of FuncDef structures with branches.  When
** there are two or more FuncDef objects with the same name, they are 
** connected using FuncDef.pSameName.  FuncDef objects with different names
** are connected using FuncDef.pNextName.
*/
struct FuncDefTable {
  FuncDef *pFirst;     /* First function definition */
  FuncDef *pLast;      /* Last function definition */
  FuncDef *pSame;      /* Tail of pSameName list for pLast */
};

/*
** An instance of the following structure stores a database schema.
**
** Most Schema objects are associated with a database file.  The exception is
** the Schema for the TEMP databaes (sqlite4.aDb[1]) which is free-standing.
** 
** Schema objects are automatically deallocated when the last database that
** references them is destroyed.   The TEMP Schema is manually freed by
** sqlite4_close().
*
** A thread must be holding a mutex on the corresponding database in order
** to access Schema content.  This implies that the thread must also be
** holding a mutex on the sqlite4 connection pointer that owns the database
** For a TEMP Schema, only the connection mutex is required.
*/
struct Schema {
  int schema_cookie;   /* Database schema version number for this file */
  int iGeneration;     /* Generation counter.  Incremented with each change */
  Hash tblHash;        /* All tables indexed by name */
  Hash idxHash;        /* All (named) indices indexed by name */
  Hash trigHash;       /* All triggers indexed by name */
  Hash fkeyHash;       /* All foreign keys by referenced table name */
  Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
  u8 file_format;      /* Schema format version for this file */
  u8 enc;              /* Text encoding used by this database */
  u16 flags;           /* Flags associated with this schema */
  int cache_size;      /* Number of pages to use in the cache */
};

/*
** These macros can be used to test, set, or clear bits in the 
** Db.pSchema->flags field.
*/
#define DbHasProperty(D,I,P)     (((D)->aDb[I].pSchema->flags&(P))==(P))
#define DbHasAnyProperty(D,I,P)  (((D)->aDb[I].pSchema->flags&(P))!=0)
#define DbSetProperty(D,I,P)     (D)->aDb[I].pSchema->flags|=(P)
#define DbClearProperty(D,I,P)   (D)->aDb[I].pSchema->flags&=~(P)

/*
** Allowed values for the DB.pSchema->flags field.
**
** The DB_SchemaLoaded flag is set after the database schema has been
** read into internal hash tables.
**
** DB_UnresetViews means that one or more views have column names that
** have been filled out.  If the schema changes, these column names might
** changes and so the view will need to be reset.
*/
#define DB_SchemaLoaded    0x0001  /* The schema has been loaded */
#define DB_UnresetViews    0x0002  /* Some views have defined column names */
#define DB_Empty           0x0004  /* The file is empty (length 0 bytes) */

/*
** The number of different kinds of things that can be limited
** using the sqlite4_limit() interface.
*/
#define SQLITE4_N_LIMIT (SQLITE4_LIMIT_TRIGGER_DEPTH+1)

/*
** Lookaside malloc is a set of fixed-size buffers that can be used
** to satisfy small transient memory allocation requests for objects
** associated with a particular database connection.  The use of
** lookaside malloc provides a significant performance enhancement
** (approx 10%) by avoiding numerous malloc/free requests while parsing
** SQL statements.
**
** The Lookaside structure holds configuration information about the
** lookaside malloc subsystem.  Each available memory allocation in
** the lookaside subsystem is stored on a linked list of LookasideSlot
** objects.
**
** Lookaside allocations are only allowed for objects that are associated
** with a particular database connection.  Hence, schema information cannot
** be stored in lookaside because in shared cache mode the schema information
** is shared by multiple database connections.  Therefore, while parsing
** schema information, the Lookaside.bEnabled flag is cleared so that
** lookaside allocations are not used to construct the schema objects.
*/
struct Lookaside {
  u16 sz;                 /* Size of each buffer in bytes */
  u8 bEnabled;            /* False to disable new lookaside allocations */
  u8 bMalloced;           /* True if pStart obtained from sqlite4_malloc() */
  int nOut;               /* Number of buffers currently checked out */
  int mxOut;              /* Highwater mark for nOut */
  int anStat[3];          /* 0: hits.  1: size misses.  2: full misses */
  LookasideSlot *pFree;   /* List of available buffers */
  void *pStart;           /* First byte of available memory space */
  void *pEnd;             /* First byte past end of available space */
};
struct LookasideSlot {
  LookasideSlot *pNext;    /* Next buffer in the list of free buffers */
};

/*
** Information used during initialization.
*/
struct Sqlite4InitInfo {
  int iDb;                    /* When back is being initialized */
  int newTnum;                /* Rootpage of table being initialized */
  u8 busy;                    /* TRUE if currently initializing */
  u8 orphanTrigger;           /* Last statement is orphaned TEMP trigger */
};


/*
** Each database connection is an instance of the following structure.
**
** The sqlite.nChange does not count changes within triggers and keeps no
** context.  It is reset at start of sqlite4_exec.
** The sqlite.lsChange represents the number of changes made by the last
** insert, update, or delete statement.  It remains constant throughout the
** length of a statement and is then updated by OP_SetCounts.  It keeps a
** context stack so that the count of changes
** within a trigger is not seen outside the trigger.  Changes to views do not
** affect the value of lsChange.
** The sqlite.csChange keeps track of the number of current changes (since
** the last statement) and is used to update sqlite_lsChange.
**
** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16
** store the most recent error code and, if applicable, string. The
** internal function sqlite4Error() is used to set these variables
** consistently.
*/
struct sqlite4 {
  sqlite4_env *pEnv;            /* The run-time environment */
  int nDb;                      /* Number of backends currently in use */
  Db *aDb;                      /* All backends */
  int flags;                    /* Miscellaneous flags. See below */
  unsigned int openFlags;       /* Flags passed to sqlite4_vfs.xOpen() */
  int errCode;                  /* Most recent error code (SQLITE4_*) */
  u8 temp_store;                /* 1: file 2: memory 0: default */
  u8 mallocFailed;              /* True if we have seen a malloc failure */
  u8 dfltLockMode;              /* Default locking-mode for attached dbs */
  signed char nextAutovac;      /* Autovac setting after VACUUM if >=0 */
  u8 suppressErr;               /* Do not issue error messages if true */
  u8 vtabOnConflict;            /* Value to return for s3_vtab_on_conflict() */
  int nextPagesize;             /* Pagesize after VACUUM if >0 */
  int nTable;                   /* Number of tables in the database */
  CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
  u32 magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Value returned by sqlite4_changes() */
  int nTotalChange;             /* Value returned by sqlite4_total_changes() */
  sqlite4_mutex *mutex;         /* Connection mutex */
  int aLimit[SQLITE4_N_LIMIT];   /* Limits */
  Sqlite4InitInfo init;         /* Information used during initialization */
  int nExtension;               /* Number of loaded extensions */
  void **aExtension;            /* Array of shared library handles */
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  int activeVdbeCnt;            /* Number of VDBEs currently executing */
  int writeVdbeCnt;             /* Number of active VDBEs that are writing */
  int vdbeExecCnt;              /* Number of nested calls to VdbeExec() */
  void (*xTrace)(void*,const char*);        /* Trace function */
  void (*xTraceDestroy)(void*);             /* Destructor for trace function */
  void *pTraceArg;                          /* Argument to the trace function */
  void (*xProfile)(void*,const char*,u64);  /* Profiling function */
  void (*xProfileDestroy)(void*);           /* Profile function destructor */
  void *pProfileArg;                        /* Argument to profile function */
#ifndef SQLITE4_OMIT_WAL
  int (*xWalCallback)(void *, sqlite4 *, const char *, int);
  void *pWalArg;
#endif
  void(*xCollNeeded)(void*,sqlite4*,const char*);
  void(*xCollNeededDestroy)(void*);
  void *pCollNeededArg;
  sqlite4_value *pErr;          /* Most recent error message */
  char *zErrMsg;                /* Most recent error message (UTF-8 encoded) */
  char *zErrMsg16;              /* Most recent error message (UTF-16 encoded) */
  union {
    volatile int isInterrupted; /* True if sqlite4_interrupt has been called */
    double notUsed1;            /* Spacer */
  } u1;
  Lookaside lookaside;          /* Lookaside malloc configuration */
#ifndef SQLITE4_OMIT_AUTHORIZATION
  Authorizer *pAuth;            /* Head of authorizer callback stack */
#endif
#ifndef SQLITE4_OMIT_PROGRESS_CALLBACK
  int (*xProgress)(void *);     /* The progress callback */
  void *pProgressArg;           /* Argument to the progress callback */
  int nProgressOps;             /* Number of opcodes for progress callback */
#endif
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  Hash aModule;                 /* populated by sqlite4_create_module() */
  VtabCtx *pVtabCtx;            /* Context for active vtab connect/create */
  VTable **aVTrans;             /* Virtual tables with open transactions */
  int nVTrans;                  /* Allocated size of aVTrans */
  VTable *pDisconnect;    /* Disconnect these in next sqlite4_prepare() */
#endif
  FuncDefTable aFunc;            /* Hash table of connection functions */
  Hash aCollSeq;                /* All collating sequences */
  Db aDbStatic[2];              /* Static space for the 2 default backends */
  Savepoint *pSavepoint;        /* List of active savepoints */
  int nSavepoint;               /* Number of open savepoints */
  int nStatement;               /* Number of nested statement-transactions  */
  i64 nDeferredCons;            /* Net deferred constraints this transaction. */
  int *pnBytesFreed;            /* If not NULL, increment this in DbFree() */

#ifdef SQLITE4_ENABLE_UNLOCK_NOTIFY
  /* The following variables are all protected by the STATIC_MASTER 
  ** mutex, not by sqlite4.mutex. They are used by code in notify.c. 
  **
  ** When X.pUnlockConnection==Y, that means that X is waiting for Y to
  ** unlock so that it can proceed.
  **
  ** When X.pBlockingConnection==Y, that means that something that X tried
  ** tried to do recently failed with an SQLITE4_LOCKED error due to locks
  ** held by Y.
  */
  sqlite4 *pBlockingConnection; /* Connection that caused SQLITE4_LOCKED */
  sqlite4 *pUnlockConnection;           /* Connection to watch for unlock */
  void *pUnlockArg;                     /* Argument to xUnlockNotify */
  void (*xUnlockNotify)(void **, int);  /* Unlock notify callback */
  sqlite4 *pNextBlocked;        /* Next in list of all blocked connections */
#endif

#ifndef SQLITE_OMIT_FTS5
  Fts5Tokenizer *pTokenizer;      /* First in list of tokenizers */
#endif
};

/*
** A macro to discover the encoding of a database.
*/
#define ENC(db) ((db)->aDb[0].pSchema->enc)

/*
** Possible values for the sqlite4.flags.
*/
#define SQLITE4_VdbeTrace      0x00000100  /* True to trace VDBE execution */
#define SQLITE4_SqlTrace       0x00000200  /* Debug print SQL as it executes */
#define SQLITE4_VdbeListing    0x00000400  /* Debug listings of VDBE programs */
#define SQLITE4_KvTrace        0x00000800  /* Trace Key/value storage calls */
#define SQLITE4_VdbeAddopTrace 0x00001000  /* Trace sqlite4VdbeAddOp() calls */
#define SQLITE4_InternChanges  0x00010000  /* Uncommitted Hash table changes */
#define SQLITE4_WriteSchema    0x00020000  /* OK to update SQLITE4_MASTER */
#define SQLITE4_IgnoreChecks   0x00040000  /* Dont enforce check constraints */
#define SQLITE4_RecoveryMode   0x00080000  /* Ignore schema errors */
#define SQLITE4_ReverseOrder   0x01000000  /* Reverse unordered SELECTs */
#define SQLITE4_RecTriggers    0x02000000  /* Enable recursive triggers */
#define SQLITE4_ForeignKeys    0x04000000  /* Enable foreign key constraints */
#define SQLITE4_AutoIndex      0x08000000  /* Enable automatic indexes */
#define SQLITE4_PreferBuiltin  0x10000000  /* Preference to built-in funcs */
#define SQLITE4_EnableTrigger  0x40000000  /* True to enable triggers */

/*
** Bits of the sqlite4.flags field that are used by the
** sqlite4_test_control(SQLITE4_TESTCTRL_OPTIMIZATIONS,...) interface.
** These must be the low-order bits of the flags field.
*/
#define SQLITE4_QueryFlattener 0x01     /* Disable query flattening */
#define SQLITE4_ColumnCache    0x02     /* Disable the column cache */
#define SQLITE4_IndexSort      0x04     /* Disable indexes for sorting */
#define SQLITE4_IndexSearch    0x08     /* Disable indexes for searching */
#define SQLITE4_IndexCover     0x10     /* Disable index covering table */
#define SQLITE4_GroupByOrder   0x20     /* Disable GROUPBY cover of ORDERBY */
#define SQLITE4_FactorOutConst 0x40     /* Disable factoring out constants */
#define SQLITE4_IdxRealAsInt   0x80     /* Store REAL as INT in indices */
#define SQLITE4_DistinctOpt    0x80     /* DISTINCT using indexes */
#define SQLITE4_OptMask        0xff     /* Mask of all disablable opts */

/*
** Some new things pulled in from SQLite3 use these macros. todo: Replace
** them with working versions.
*/
#define OptimizationDisabled(db, mask)  0
#define OptimizationEnabled(db, mask)  1

/*
** Possible values for the sqlite.magic field.
** The numbers are obtained at random and have no special meaning, other
** than being distinct from one another.
*/
#define SQLITE4_MAGIC_OPEN    0x4d06c919  /* Database is open */
#define SQLITE4_MAGIC_CLOSED  0x5f2246b4  /* Database is closed */
#define SQLITE4_MAGIC_SICK    0xcaad9e61  /* Error and awaiting close */
#define SQLITE4_MAGIC_BUSY    0xb07f8c8c  /* Database currently in use */
#define SQLITE4_MAGIC_ERROR   0x912e4c46  /* An SQLITE4_MISUSE error occurred */

/*
** Possible values for FuncDef.flags
*/
#define SQLITE4_FUNC_LIKE     0x01 /* Candidate for the LIKE optimization */
#define SQLITE4_FUNC_CASE     0x02 /* Case-sensitive LIKE-type function */
#define SQLITE4_FUNC_EPHEM    0x04 /* Ephemeral.  Delete with VDBE */
#define SQLITE4_FUNC_NEEDCOLL 0x08 /* sqlite4GetFuncCollSeq() might be called */
#define SQLITE4_FUNC_PRIVATE  0x10 /* Allowed for internal use only */
#define SQLITE4_FUNC_COUNT    0x20 /* Built-in count(*) aggregate */
#define SQLITE4_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() func */

/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
** used to create the initializers for the FuncDef structures.
**
**   FUNCTION(zName, nArg, iArg, bNC, xFunc)
**     Used to create a scalar function definition of a function zName 
**     implemented by C function xFunc that accepts nArg arguments. The
**     value passed as iArg is cast to a (void*) and made available
**     as the user-data (sqlite4_context_appdata()) for the function. If 
**     argument bNC is true, then the SQLITE4_FUNC_NEEDCOLL flag is set.
**
**   AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
**     Used to create an aggregate function definition implemented by
**     the C functions xStep and xFinal. The first four parameters
**     are interpreted in the same way as the first 4 parameters to
**     FUNCTION().
**
**   LIKEFUNC(zName, nArg, pArg, flags)
**     Used to create a scalar function definition of a function zName 
**     that accepts nArg arguments and is implemented by a call to C 
**     function likeFunc. Argument pArg is cast to a (void *) and made
**     available as the function user-data (sqlite4_context_appdata()). The
**     FuncDef.flags variable is set to the value passed as the flags
**     parameter.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
  {nArg, bNC*SQLITE4_FUNC_NEEDCOLL, \
   SQLITE4_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0}
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
  {nArg, bNC*SQLITE4_FUNC_NEEDCOLL, \
   pArg, 0, xFunc, 0, 0, #zName, 0, 0}
#define LIKEFUNC(zName, nArg, arg, flags) \
  {nArg, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0}
#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \
  {nArg, nc*SQLITE4_FUNC_NEEDCOLL, \
   SQLITE4_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0}

/*
** All current savepoints are stored in a linked list starting at
** sqlite4.pSavepoint. The first element in the list is the most recently
** opened savepoint. Savepoints are added to the list by the vdbe
** OP_Savepoint instruction.
*/
struct Savepoint {
  char *zName;                        /* Savepoint name (nul-terminated) */
  i64 nDeferredCons;                  /* Number of deferred fk violations */
  Savepoint *pNext;                   /* Parent savepoint (if any) */
};

/*
** The following are used as the second parameter to sqlite4Savepoint(),
** and as the P1 argument to the OP_Savepoint instruction.
*/
#define SAVEPOINT_BEGIN      0
#define SAVEPOINT_RELEASE    1
#define SAVEPOINT_ROLLBACK   2


/*
** Each SQLite module (virtual table definition) is defined by an
** instance of the following structure, stored in the sqlite4.aModule
** hash table.
*/
struct Module {
  const sqlite4_module *pModule;       /* Callback pointers */
  const char *zName;                   /* Name passed to create_module() */
  void *pAux;                          /* pAux passed to create_module() */
  void (*xDestroy)(void *);            /* Module destructor function */
};

/*
** information about each column of an SQL table is held in an instance
** of this structure.
*/
struct Column {
  char *zName;     /* Name of this column */
  Expr *pDflt;     /* Default value of this column */
  char *zDflt;     /* Original text of the default value */
  char *zType;     /* Data type for this column */
  char *zColl;     /* Collating sequence.  If NULL, use the default */
  u16 iPrimKey;    /* Index of in the primary key.  0 if not part of PK */
  u8 notNull;      /* True if there is a NOT NULL constraint */
  char affinity;   /* One of the SQLITE4_AFF_... values */
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  u8 isHidden;     /* True if this column is 'hidden' */
#endif
};

/*
** A "Collating Sequence" is defined by an instance of the following
** structure. Conceptually, a collating sequence consists of a name and
** a comparison routine that defines the order of that sequence.
**
** There may two separate implementations of the collation function, one
** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that
** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
** native byte order. When a collation sequence is invoked, SQLite selects
** the version that will require the least expensive encoding
** translations, if any.
**
** The CollSeq.pUser member variable is an extra parameter that passed in
** as the first argument to the UTF-8 comparison function, xCmp.
** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function,
** xCmp16.
**
** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the
** collating sequence is undefined.  Indices built on an undefined
** collating sequence may not be read or written.
*/
struct CollSeq {
  char *zName;          /* Name of the collating sequence, UTF-8 encoded */
  void *pUser;          /* First argument to xCmp() */
  int (*xCmp)(void*, sqlite4_value*, sqlite4_value*, int*);
  int (*xMkKey)(void*, sqlite4_value*, int, void*, int*);
  void (*xDel)(void*);  /* Destructor for pUser */
};

/*
** A sort order can be either ASC or DESC.
*/
#define SQLITE4_SO_ASC       0  /* Sort in ascending order */
#define SQLITE4_SO_DESC      1  /* Sort in ascending order */

/*
** Column affinity types.
**
** These used to have mnemonic name like 'i' for SQLITE4_AFF_INTEGER and
** 't' for SQLITE4_AFF_TEXT.  But we can save a little space and improve
** the speed a little by numbering the values consecutively.  
**
** But rather than start with 0 or 1, we begin with 'a'.  That way,
** when multiple affinity types are concatenated into a string and
** used as the P4 operand, they will be more readable.
**
** Note also that the numeric types are grouped together so that testing
** for a numeric type is a single comparison.
*/
#define SQLITE4_AFF_TEXT     'a'
#define SQLITE4_AFF_NONE     'b'
#define SQLITE4_AFF_NUMERIC  'c'
#define SQLITE4_AFF_INTEGER  'd'
#define SQLITE4_AFF_REAL     'e'

#define sqlite4IsNumericAffinity(X)  ((X)>=SQLITE4_AFF_NUMERIC)

/*
** The SQLITE4_AFF_MASK values masks off the significant bits of an
** affinity value. 
*/
#define SQLITE4_AFF_MASK     0x67

/*
** Additional bit values that can be ORed with an affinity without
** changing the affinity.
*/
#define SQLITE4_JUMPIFNULL  0x08  /* jumps if either operand is NULL */
#define SQLITE4_STOREP2     0x10  /* Store result in reg[P2] rather than jump */
#define SQLITE4_NULLEQ      0x80  /* NULL=NULL */

/*
** An object of this type is created for each virtual table present in
** the database schema. 
**
** If the database schema is shared, then there is one instance of this
** structure for each database connection (sqlite4*) that uses the shared
** schema. This is because each database connection requires its own unique
** instance of the sqlite4_vtab* handle used to access the virtual table 
** implementation. sqlite4_vtab* handles can not be shared between 
** database connections, even when the rest of the in-memory database 
** schema is shared, as the implementation often stores the database
** connection handle passed to it via the xConnect() or xCreate() method
** during initialization internally. This database connection handle may
** then be used by the virtual table implementation to access real tables 
** within the database. So that they appear as part of the callers 
** transaction, these accesses need to be made via the same database 
** connection as that used to execute SQL operations on the virtual table.
**
** All VTable objects that correspond to a single table in a shared
** database schema are initially stored in a linked-list pointed to by
** the Table.pVTable member variable of the corresponding Table object.
** When an sqlite4_prepare() operation is required to access the virtual
** table, it searches the list for the VTable that corresponds to the
** database connection doing the preparing so as to use the correct
** sqlite4_vtab* handle in the compiled query.
**
** When an in-memory Table object is deleted (for example when the
** schema is being reloaded for some reason), the VTable objects are not 
** deleted and the sqlite4_vtab* handles are not xDisconnect()ed 
** immediately. Instead, they are moved from the Table.pVTable list to
** another linked list headed by the sqlite4.pDisconnect member of the
** corresponding sqlite4 structure. They are then deleted/xDisconnected 
** next time a statement is prepared using said sqlite4*. This is done
** to avoid deadlock issues involving multiple sqlite4.mutex mutexes.
** Refer to comments above function sqlite4VtabUnlockList() for an
** explanation as to why it is safe to add an entry to an sqlite4.pDisconnect
** list without holding the corresponding sqlite4.mutex mutex.
**
** The memory for objects of this type is always allocated by 
** sqlite4DbMalloc(), using the connection handle stored in VTable.db as 
** the first argument.
*/
struct VTable {
  sqlite4 *db;              /* Database connection associated with this table */
  Module *pMod;             /* Pointer to module implementation */
  sqlite4_vtab *pVtab;      /* Pointer to vtab instance */
  int nRef;                 /* Number of pointers to this structure */
  u8 bConstraint;           /* True if constraints are supported */
  int iSavepoint;           /* Depth of the SAVEPOINT stack */
  VTable *pNext;            /* Next in linked list (see above) */
};

/*
** Each SQL table is represented in memory by an instance of the
** following structure.
*/
struct Table {
  char *zName;         /* Name of the table or view */
  int nCol;            /* Number of columns in this table */
  Column *aCol;        /* Information about each column */
  Index *pIndex;       /* List of SQL indexes on this table. */
  tRowcnt nRowEst;     /* Estimated rows in table - from sqlite_stat1 table */
  Select *pSelect;     /* NULL for tables.  Points to definition if a view. */
  u16 nRef;            /* Number of pointers to this Table */
  u8 tabFlags;         /* Mask of TF_* values */
  FKey *pFKey;         /* Linked list of all foreign keys in this table */
  char *zColAff;       /* String defining the affinity of each column */
#ifndef SQLITE4_OMIT_CHECK
  Expr *pCheck;        /* The AND of all CHECK constraints */
#endif
#ifndef SQLITE4_OMIT_ALTERTABLE
  int addColOffset;    /* Offset in CREATE TABLE stmt to add a new column */
#endif
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  VTable *pVTable;     /* List of VTable objects. */
  int nModuleArg;      /* Number of arguments to the module */
  char **azModuleArg;  /* Text of all module args. [0] is module name */
#endif
  Trigger *pTrigger;   /* List of triggers stored in pSchema */
  Schema *pSchema;     /* Schema that contains this table */
  Table *pNextZombie;  /* Next on the Parse.pZombieTab list */
};

/*
** Allowed values for Tabe.tabFlags.
*/
#define TF_Readonly        0x01    /* Read-only system table */
#define TF_Ephemeral       0x02    /* An ephemeral table */
#define TF_HasPrimaryKey   0x04    /* Table has a primary key */
#define TF_Autoincrement   0x08    /* Integer primary key is autoincrement */
#define TF_Virtual         0x10    /* Is a virtual table */
#define TF_NeedMetadata    0x20    /* aCol[].zType and aCol[].pColl missing */



/*
** Test to see whether or not a table is a virtual table.  This is
** done as a macro so that it will be optimized out when virtual
** table support is omitted from the build.
*/
#ifndef SQLITE4_OMIT_VIRTUALTABLE
#  define IsVirtual(X)      (((X)->tabFlags & TF_Virtual)!=0)
#  define IsHiddenColumn(X) ((X)->isHidden)
#else
#  define IsVirtual(X)      0
#  define IsHiddenColumn(X) 0
#endif

/* Test to see if a table is actually a view. */
#ifndef SQLITE4_OMIT_VIEW
#  define IsView(X)         ((X)->pSelect!=0)
#else
#  define IsView(X)         0
#endif

/*
** Each foreign key constraint is an instance of the following structure.
**
** A foreign key is associated with two tables.  The "from" table is
** the table that contains the REFERENCES clause that creates the foreign
** key.  The "to" table is the table that is named in the REFERENCES clause.
** Consider this example:
**
**     CREATE TABLE ex1(
**       a INTEGER PRIMARY KEY,
**       b INTEGER CONSTRAINT fk1 REFERENCES ex2(x)
**     );
**
** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2".
**
** Each REFERENCES clause generates an instance of the following structure
** which is attached to the from-table.  The to-table need not exist when
** the from-table is created.  The existence of the to-table is not checked.
*/
struct FKey {
  Table *pFrom;     /* Table containing the REFERENCES clause (aka: Child) */
  FKey *pNextFrom;  /* Next foreign key in pFrom */
  char *zTo;        /* Name of table that the key points to (aka: Parent) */
  FKey *pNextTo;    /* Next foreign key on table named zTo */
  FKey *pPrevTo;    /* Previous foreign key on table named zTo */
  int nCol;         /* Number of columns in this key */
  /* EV: R-30323-21917 */
  u8 isDeferred;    /* True if constraint checking is deferred till COMMIT */
  u8 aAction[2];          /* ON DELETE and ON UPDATE actions, respectively */
  Trigger *apTrigger[2];  /* Triggers for aAction[] actions */
  struct sColMap {  /* Mapping of columns in pFrom to columns in zTo */
    int iFrom;         /* Index of column in pFrom */
    char *zCol;        /* Name of column in zTo.  If 0 use PRIMARY KEY */
  } aCol[1];        /* One entry for each of nCol column s */
};

/*
** SQLite supports many different ways to resolve a constraint
** error.  ROLLBACK processing means that a constraint violation
** causes the operation in process to fail and for the current transaction
** to be rolled back.  ABORT processing means the operation in process
** fails and any prior changes from that one operation are backed out,
** but the transaction is not rolled back.  FAIL processing means that
** the operation in progress stops and returns an error code.  But prior
** changes due to the same operation are not backed out and no rollback
** occurs.  IGNORE means that the particular row that caused the constraint
** error is not inserted or updated.  Processing continues and no error
** is returned.  REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed.  Processing continues and no error is reported.
**
** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
** same as ROLLBACK for DEFERRED keys.  SETNULL means that the foreign
** key is set to NULL.  CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
** 
** The following symbolic values are used to record which type
** of action to take.
*/
#define OE_None     0   /* There is no constraint to check */
#define OE_Rollback 1   /* Fail the operation and rollback the transaction */
#define OE_Abort    2   /* Back out changes but do no rollback transaction */
#define OE_Fail     3   /* Stop the operation but leave all prior changes */
#define OE_Ignore   4   /* Ignore the error. Do not do the INSERT or UPDATE */
#define OE_Replace  5   /* Delete existing record, then do INSERT or UPDATE */

#define OE_Restrict 6   /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
#define OE_SetNull  7   /* Set the foreign key value to NULL */
#define OE_SetDflt  8   /* Set the foreign key value to its default */
#define OE_Cascade  9   /* Cascade the changes */

#define OE_Default  99  /* Do whatever the default action is */


/*
** An instance of the following structure describes an index key.  It 
** includes information such as sort order and collating sequence for
** each key, and the number of primary key fields appended to the end.
*/
struct KeyInfo {
  u16 nField;         /* Total number of entries in aColl[] */
  u16 nPK;            /* Number of primary key entries at the end of aColl[] */
  u16 nData;          /* Number of columns of data in KV entry value */
  u8 *aSortOrder;     /* Sort order for each column.  May be NULL */
  CollSeq *aColl[1];  /* Collating sequence for each term of the key */
};

/*
** Each SQL index is represented in memory by an
** instance of the following structure.
**
** The columns of the table that are to be indexed are described
** by the aiColumn[] field of this structure.  For example, suppose
** we have the following table and index:
**
**     CREATE TABLE Ex1(c1 int, c2 int, c3 text);
**     CREATE INDEX Ex2 ON Ex1(c3,c1);
**
** In the Table structure describing Ex1, nCol==3 because there are
** three columns in the table.  In the Index structure describing
** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed.
** The value of aiColumn is {2, 0}.  aiColumn[0]==2 because the 
** first column to be indexed (c3) has an index of 2 in Ex1.aCol[].
** The second column to be indexed (c1) has an index of 0 in
** Ex1.aCol[], hence Ex2.aiColumn[1]==0.
**
** The Index.onError field determines whether or not the indexed columns
** must be unique and what to do if they are not.  When Index.onError=OE_None,
** it means this is not a unique index.  Otherwise it is a unique index
** and the value of Index.onError indicate the which conflict resolution 
** algorithm to employ whenever an attempt is made to insert a non-unique
** element.
*/
struct Index {
  char *zName;     /* Name of this index */
  int nColumn;     /* Number of columns in the table used by this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  int nCover;      /* Number of covering columns in this index */
  int *aiCover;    /* Which columns are covered by this index */
  tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
  Table *pTable;   /* The SQL table being indexed */
  int tnum;        /* Page containing root of this index in database file */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 eIndexType;   /* SQLITE4_INDEX_USER, UNIQUE or PRIMARYKEY */
  u8 fIndex;       /* One or more of the IDX_* flags below */
  char *zColAff;   /* String defining the affinity of each column */
  Index *pNext;    /* The next index associated with the same table */
  Schema *pSchema; /* Schema containing this index */
  u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
  char **azColl;   /* Array of collation sequence names for index */
#ifdef SQLITE4_ENABLE_STAT3
  int nSample;             /* Number of elements in aSample[] */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
  Fts5Index *pFts; /* Fts5 data (or NULL if this is not an fts index) */

  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
};

/* Index.eIndexType must be set to one of the following. */
#define SQLITE4_INDEX_USER       0 /* Index created by CREATE INDEX statement */
#define SQLITE4_INDEX_UNIQUE     1 /* Index created by UNIQUE constraint */
#define SQLITE4_INDEX_PRIMARYKEY 2 /* Index is the tables PRIMARY KEY */
#define SQLITE4_INDEX_FTS5       3 /* Index is an FTS5 index */
#define SQLITE4_INDEX_TEMP       4 /* Index is an automatic index */

/* Allowed values for Index.fIndex */
#define IDX_IntPK             0x01 /* An INTEGER PRIMARY KEY index */
#define IDX_Unordered         0x02 /* Implemented as a hashing index */

/*
** Each sample stored in the sqlite_stat3 table is represented in memory 
** using a structure of this type.  See documentation at the top of the
** analyze.c source file for additional information.
*/
struct IndexSample {
  u8 *aVal;         /* Pointer to index-key encoded value blob */
  int nVal;         /* Size of array aKey[] in bytes */
  tRowcnt nEq;      /* Est. number of rows where the key equals this sample */
  tRowcnt nLt;      /* Est. number of rows where key is less than this sample */
  tRowcnt nDLt;     /* Est. number of distinct keys less than this sample */
};

/*
** Each token coming out of the lexer is an instance of
** this structure.  Tokens are also used as part of an expression.
**
** Note if Token.z==0 then Token.dyn and Token.n are undefined and
** may contain random values.  Do not make any assumptions about Token.dyn
** and Token.n when Token.z==0.
*/
struct Token {
  const char *z;     /* Text of the token.  Not NULL-terminated! */
  unsigned int n;    /* Number of characters in this token */
};

/*
** An instance of this structure holds the results of parsing the first
** part of a CREATE INDEX statement. Instances exist only transiently 
** during parsing.
*/
struct CreateIndex {
  int bUnique;                    /* True if the UNIQUE keyword was present */
  int bIfnotexist;                /* True if IF NOT EXISTS was present */
  Token tCreate;                  /* CREATE token */
  Token tName1;                   /* First part of two part name */
  Token tName2;                   /* Second part of two part name */
  SrcList *pTblName;              /* Table index is created on */ 
};

/*
** One for each column used in source tables.
*/
struct AggInfoCol {
  Table *pTab;             /* Source table */
  int iTable;              /* Cursor number of the source table */
  int iColumn;             /* Column number within the source table */
  int iSorterColumn;       /* Column number in the sorting index */
  int iMem;                /* Memory location that acts as accumulator */
  Expr *pExpr;             /* The original expression */
};

/*
** One for each aggregate function.
*/
struct AggInfoFunc {
  Expr *pExpr;             /* Expression encoding the function */
  FuncDef *pFunc;          /* The aggregate function implementation */
  int iMem;                /* Memory location that acts as accumulator */
  int iDistinct;           /* Ephemeral table used to enforce DISTINCT */
};

/*
** An instance of this structure contains information needed to generate
** code for a SELECT that contains aggregate functions.
**
** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
** pointer to this structure.  The Expr.iColumn field is the index in
** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
** code for that node.
**
** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the
** original Select structure that describes the SELECT statement.  These
** fields do not need to be freed when deallocating the AggInfo structure.
*/
struct AggInfo {
  u8 directMode;          /* Direct rendering mode means take data directly
                          ** from source tables rather than from accumulators */
  u8 useSortingIdx;       /* In direct mode, reference the sorting index rather
                          ** than the source table */
  int sortingIdx;         /* Cursor number of the sorting index */
  ExprList *pGroupBy;     /* The group by clause */
  int nSortingColumn;     /* Number of columns in the sorting index */
  AggInfoCol *aCol;       /* For each column used in source tables. */
  int nColumn;            /* Number of used entries in aCol[] */
  int nColumnAlloc;       /* Number of slots allocated for aCol[] */
  int nAccumulator;       /* Number of columns that show through to the output.
                          ** Additional columns are used only as parameters to
                          ** aggregate functions */
  AggInfoFunc *aFunc;     /* For each aggregate function */
  int nFunc;              /* Number of entries in aFunc[] */
  int nFuncAlloc;         /* Number of slots allocated for aFunc[] */
};

/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits.  But if SQLITE4_MAX_VARIABLE_NUMBER is greater
** than 32767 we have to make it 32-bit.  16-bit is preferred because
** it uses less memory in the Expr object, which is a big memory user
** in systems with lots of prepared statements.  And few applications
** need more than about 10 or 20 variables.  But some extreme users want
** to have prepared statements with over 32767 variables, and for them
** the option is available (at compile-time).
*/
#if SQLITE4_MAX_VARIABLE_NUMBER<=32767
typedef i16 ynVar;
#else
typedef int ynVar;
#endif

/*
** Each node of an expression in the parse tree is an instance
** of this structure.
**
** Expr.op is the opcode. The integer parser token codes are reused
** as opcodes here. For example, the parser defines TK_GE to be an integer
** code representing the ">=" operator. This same integer code is reused
** to represent the greater-than-or-equal-to operator in the expression
** tree.
**
** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB, 
** or TK_STRING), then Expr.token contains the text of the SQL literal. If
** the expression is a variable (TK_VARIABLE), then Expr.token contains the 
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
** then Expr.token contains the name of the function.
**
** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
** binary operator. Either or both may be NULL.
**
** Expr.x.pList is a list of arguments if the expression is an SQL function,
** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
** Expr.x.pSelect is used if the expression is a sub-select or an expression of
** the form "<lhs> IN (SELECT ...)". If the EP_xIsSelect bit is set in the
** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is 
** valid.
**
** An expression of the form ID or ID.ID refers to a column in a table.
** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is
** the integer cursor number of a VDBE cursor pointing to that table and
** Expr.iColumn is the column number for the specific column.  If the
** expression is used as a result in an aggregate SELECT, then the
** value is also stored in the Expr.iAgg column in the aggregate so that
** it can be accessed after all aggregates are computed.
**
** If the expression is an unbound variable marker (a question mark 
** character '?' in the original SQL) then the Expr.iTable holds the index 
** number for that variable.
**
** If the expression is a subquery then Expr.iColumn holds an integer
** register number containing the result of the subquery.  If the
** subquery gives a constant result, then iTable is -1.  If the subquery
** gives a different answer at different times during statement processing
** then iTable is the address of a subroutine that computes the subquery.
**
** If the Expr is of type OP_Column, and the table it is selecting from
** is a disk table or the "old.*" pseudo-table, then pTab points to the
** corresponding table definition.
**
** ALLOCATION NOTES:
**
** Expr objects can use a lot of memory space in database schema.  To
** help reduce memory requirements, sometimes an Expr object will be
** truncated.  And to reduce the number of memory allocations, sometimes
** two or more Expr objects will be stored in a single memory allocation,
** together with Expr.zToken strings.
**
** If the EP_Reduced and EP_TokenOnly flags are set when
** an Expr object is truncated.  When EP_Reduced is set, then all
** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
** are contained within the same memory allocation.  Note, however, that
** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately
** allocated, regardless of whether or not EP_Reduced is set.
*/
struct Expr {
  u8 op;                 /* Operation performed by this node */
  char affinity;         /* The affinity of the column or 0 if not a column */
  u16 flags;             /* Various flags.  EP_* See below */
  union {
    char *zToken;          /* Token value. Zero terminated and dequoted */
    int iValue;            /* Non-negative integer value if EP_IntValue */
  } u;

  /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
  ** space is allocated for the fields below this point. An attempt to
  ** access them will result in a segfault or malfunction. 
  *********************************************************************/

  Expr *pLeft;           /* Left subnode */
  Expr *pRight;          /* Right subnode */
  union {
    ExprList *pList;     /* Function arguments or in "<expr> IN (<expr-list)" */
    Select *pSelect;     /* Used for sub-selects and "<expr> IN (<select>)" */
  } x;
  CollSeq *pColl;        /* The collation type of the column or 0 */

  /* If the EP_Reduced flag is set in the Expr.flags mask, then no
  ** space is allocated for the fields below this point. An attempt to
  ** access them will result in a segfault or malfunction.
  *********************************************************************/

  int iTable;            /* TK_COLUMN: cursor number of table holding column
                         ** TK_REGISTER: register number
                         ** TK_TRIGGER: 1 -> new, 0 -> old */
  ynVar iColumn;         /* TK_COLUMN: column index.  -1 for rowid.
                         ** TK_VARIABLE: variable number (always >= 1). */
  i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
  i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
  u8 flags2;             /* Second set of flags.  EP2_... */
  u8 op2;                /* If a TK_REGISTER, the original value of Expr.op */
  AggInfo *pAggInfo;     /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
  Table *pTab;           /* Table for TK_COLUMN expressions. */
  Index *pIdx;           /* Fts index used by MATCH expressions */
#if SQLITE4_MAX_EXPR_DEPTH>0
  int nHeight;           /* Height of the tree headed by this node */
#endif
};

/*
** The following are the meanings of bits in the Expr.flags field.
*/
#define EP_FromJoin   0x0001  /* Originated in ON or USING clause of a join */
#define EP_Agg        0x0002  /* Contains one or more aggregate functions */
#define EP_Resolved   0x0004  /* IDs have been resolved to COLUMNs */
#define EP_Error      0x0008  /* Expression contains one or more errors */
#define EP_Distinct   0x0010  /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect  0x0020  /* pSelect is correlated, not constant */
#define EP_InfixFunc  0x0080  /* True for an infix function: LIKE, GLOB, etc */
#define EP_ExpCollate 0x0100  /* Collating sequence specified explicitly */
#define EP_FixedDest  0x0200  /* Result needed in a specific register */
#define EP_IntValue   0x0400  /* Integer value contained in u.iValue */
#define EP_xIsSelect  0x0800  /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Hint       0x1000  /* Optimizer hint. Not required for correctness */
#define EP_Reduced    0x2000  /* Expr struct is EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly  0x4000  /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
#define EP_Static     0x8000  /* Held in memory not obtained from malloc() */

/*
** The following are the meanings of bits in the Expr.flags2 field.
*/
#define EP2_MallocedToken  0x0001  /* Need to sqlite4DbFree() Expr.zToken */
#define EP2_Irreducible    0x0002  /* Cannot EXPRDUP_REDUCE this Expr */

/*
** The pseudo-routine sqlite4ExprSetIrreducible sets the EP2_Irreducible
** flag on an expression structure.  This flag is used for VV&A only.  The
** routine is implemented as a macro that only works when in debugging mode,
** so as not to burden production code.
*/
#ifdef SQLITE4_DEBUG
# define ExprSetIrreducible(X)  (X)->flags2 |= EP2_Irreducible
#else
# define ExprSetIrreducible(X)
#endif

/*
** These macros can be used to test, set, or clear bits in the 
** Expr.flags field.
*/
#define ExprHasProperty(E,P)     (((E)->flags&(P))==(P))
#define ExprHasAnyProperty(E,P)  (((E)->flags&(P))!=0)
#define ExprSetProperty(E,P)     (E)->flags|=(P)
#define ExprClearProperty(E,P)   (E)->flags&=~(P)

/*
** Macros to determine the number of bytes required by a normal Expr 
** struct, an Expr struct with the EP_Reduced flag set in Expr.flags 
** and an Expr struct with the EP_TokenOnly flag set.
*/
#define EXPR_FULLSIZE           sizeof(Expr)           /* Full size */
#define EXPR_REDUCEDSIZE        offsetof(Expr,iTable)  /* Common features */
#define EXPR_TOKENONLYSIZE      offsetof(Expr,pLeft)   /* Fewer features */

/*
** Flags passed to the sqlite4ExprDup() function. See the header comment 
** above sqlite4ExprDup() for details.
*/
#define EXPRDUP_REDUCE         0x0001  /* Used reduced-size Expr nodes */

/*
** One entry for each expression.
*/
struct ExprListItem {
  Expr *pExpr;           /* The list of expressions */
  char *zName;           /* Token associated with this expression */
  char *zSpan;           /* Original text of the expression */
  u8 sortOrder;          /* 1 for DESC or 0 for ASC */
  u8 done;               /* A flag to indicate when processing is finished */
  u16 iOrderByCol;       /* For ORDER BY, column number in result set */
  u16 iAlias;            /* Index into Parse.aAlias[] for zName */
};

/*
** A list of expressions.  Each expression may optionally have a
** name.  An expr/name combination can be used in several ways, such
** as the list of "expr AS ID" fields following a "SELECT" or in the
** list of "ID = expr" items in an UPDATE.  A list of expressions can
** also be used as the argument to a function, in which case the a.zName
** field is not used.
*/
struct ExprList {
  int nExpr;             /* Number of expressions on the list */
  int nAlloc;            /* Number of entries allocated below */
  int iECursor;          /* VDBE Cursor associated with this ExprList */
  ExprListItem *a;       /* One entry for each expression */
};

/*
** An instance of this structure is used by the parser to record both
** the parse tree for an expression and the span of input text for an
** expression.
*/
struct ExprSpan {
  Expr *pExpr;          /* The expression parse tree */
  const char *zStart;   /* First character of input text */
  const char *zEnd;     /* One character past the end of input text */
};

struct IdListItem {
  char *zName;      /* Name of the identifier */
  int idx;          /* Index in some Table.aCol[] of a column named zName */
};


/*
** An instance of this structure can hold a simple list of identifiers,
** such as the list "a,b,c" in the following statements:
**
**      INSERT INTO t(a,b,c) VALUES ...;
**      CREATE INDEX idx ON t(a,b,c);
**      CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...;
**
** The IdList.a.idx field is used when the IdList represents the list of
** column names after a table name in an INSERT statement.  In the statement
**
**     INSERT INTO t(a,b,c) ...
**
** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
*/
struct IdList {
  IdListItem *a;
  int nId;         /* Number of identifiers on the list */
  int nAlloc;      /* Number of entries allocated for a[] below */
};

/*
** The bitmask datatype defined below is used for various optimizations.
**
** Changing this from a 64-bit to a 32-bit type limits the number of
** tables in a join to 32 instead of 64.  But it also reduces the size
** of the library by 738 bytes on ix86.
*/
typedef u64 Bitmask;

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  ((int)(sizeof(Bitmask)*8))

/*
** One entry for each identifier on the list.
*/
struct SrcListItem {
  char *zDatabase;  /* Name of database holding this table */
  char *zName;      /* Name of the table */
  char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
  Table *pTab;      /* An SQL table corresponding to zName */
  Select *pSelect;  /* A SELECT statement used in place of a table name */
  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 SQLITE4_OMIT_EXPLAIN
  u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
#endif
  int iCursor;      /* The VDBE cursor number used to access this table */
  Expr *pOn;        /* The ON clause of a join */
  IdList *pUsing;   /* The USING clause of a join */
  Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
  char *zIndex;     /* Identifier from "INDEXED BY <zIndex>" clause */
  Index *pIndex;    /* Index structure corresponding to zIndex, if any */
};

/*
** The following structure describes the FROM clause of a SELECT statement.
** Each table or subquery in the FROM clause is a separate element of
** the SrcList.a[] array.
**
** With the addition of multiple database support, the following structure
** can also be used to describe a particular table such as the table that
** is modified by an INSERT, DELETE, or UPDATE statement.  In standard SQL,
** such a table must be a simple name: ID.  But in SQLite, the table can
** now be identified by a database name, a dot, then the table name: ID.ID.
**
** The jointype starts out showing the join type between the current table
** and the next table on the list.  The parser builds the list this way.
** But sqlite4SrcListShiftJoinType() later shifts the jointypes so that each
** jointype expresses the join between the table and the previous table.
**
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used, or
** if the table uses an implicit primary key and it is accessed.
*/
struct SrcList {
  i16 nSrc;        /* Number of tables or subqueries in the FROM clause */
  i16 nAlloc;      /* Number of entries allocated in a[] below */
  SrcListItem a[1]; /* One entry for each identifier on the list */
};

/*
** Permitted values of the SrcList.a.jointype field
*/
#define JT_INNER     0x0001    /* Any kind of inner or cross join */
#define JT_CROSS     0x0002    /* Explicit use of the CROSS keyword */
#define JT_NATURAL   0x0004    /* True for a "natural" join */
#define JT_LEFT      0x0008    /* Left outer join */
#define JT_RIGHT     0x0010    /* Right outer join */
#define JT_OUTER     0x0020    /* The "OUTER" keyword is present */
#define JT_ERROR     0x0040    /* unknown or unsupported join type */


/*
** A WherePlan object holds information that describes a lookup
** strategy.
**
** This object is intended to be opaque outside of the where.c module.
** It is included here only so that that compiler will know how big it
** is.  None of the fields in this object should be used outside of
** the where.c module.
**
** Within the union, pIdx is only used when wsFlags&WHERE_INDEXED is true.
** pTerm is only used when wsFlags&WHERE_MULTI_OR is true.  And pVtabIdx
** is only used when wsFlags&WHERE_VIRTUALTABLE is true.  It is never the
** case that more than one of these conditions is true.
*/
struct WherePlan {
  u32 wsFlags;                   /* WHERE_* flags that describe the strategy */
  u32 nEq;                       /* Number of == constraints */
  double nRow;                   /* Estimated number of rows (for EQP) */
  union {
    Index *pIdx;                   /* Index when WHERE_INDEXED is true */
    struct WhereTerm *pTerm;       /* WHERE clause term for OR-search */
    sqlite4_index_info *pVtabIdx;  /* Virtual table index to use */
  } u;
};

#if 0
/*
** For each nested loop in a WHERE clause implementation, the WhereInfo
** structure contains a single instance of this structure.  This structure
** is intended to be private the the where.c module and should not be
** access or modified by other modules.
**
** The pIdxInfo field is used to help pick the best index on a
** virtual table.  The pIdxInfo pointer contains indexing
** information for the i-th table in the FROM clause before reordering.
** All the pIdxInfo pointers are freed by whereInfoFree() in where.c.
** All other information in the i-th WhereLevel object for the i-th table
** after FROM clause ordering.
*/
struct WhereLevel {
  WherePlan plan;       /* query plan for this element of the FROM clause */
  int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
  int iTabCur;          /* The VDBE cursor used to access the table */
  int iIdxCur;          /* The VDBE cursor used to access pIdx */
  int addrBrk;          /* Jump here to break out of the loop */
  int addrNxt;          /* Jump here to start the next IN combination */
  int addrCont;         /* Jump here to continue with the next loop cycle */
  int addrFirst;        /* First instruction of interior of the loop */
  u8 iFrom;             /* Which entry in the FROM clause */
  u8 op, p5;            /* Opcode and P5 of the opcode that ends the loop */
  int p1, p2;           /* Operands of the opcode used to ends the loop */
  union {               /* Information that depends on plan.wsFlags */
    struct {
      int nIn;              /* Number of entries in aInLoop[] */
      struct InLoop {
        int iCur;              /* The VDBE cursor used by this IN operator */
        int addrInTop;         /* Top of the IN loop */
      } *aInLoop;           /* Information about each nested IN operator */
    } in;                 /* Used when plan.wsFlags&WHERE_IN_ABLE */
  } u;

  /* The following field is really not part of the current level.  But
  ** we need a place to cache virtual table index information for each
  ** virtual table in the FROM clause and the WhereLevel structure is
  ** a convenient place since there is one WhereLevel for each FROM clause
  ** element.
  */
  sqlite4_index_info *pIdxInfo;  /* Index info for n-th source table */
};
#endif

#if 0
/*
** Flags appropriate for the wctrlFlags parameter of sqlite4WhereBegin()
** and the WhereInfo.wctrlFlags member.
*/
#define WHERE_ORDERBY_NORMAL   0x0000 /* No-op */
#define WHERE_ORDERBY_MIN      0x0001 /* ORDER BY processing for min() func */
#define WHERE_ORDERBY_MAX      0x0002 /* ORDER BY processing for max() func */
#define WHERE_ONEPASS_DESIRED  0x0004 /* Want to do one-pass UPDATE/DELETE */
#define WHERE_DUPLICATES_OK    0x0008 /* Ok to return a row more than once */
#define WHERE_OMIT_OPEN_CLOSE  0x0010 /* Table cursors are already open */
#define WHERE_NO_AUTOINDEX     0x0020 /* Do not use an auto-index search */
#define WHERE_ONETABLE_ONLY    0x0040 /* Only code the 1st table in pTabList */
#define WHERE_AND_ONLY         0x0080 /* Don't use indices for OR terms */
#endif


/*
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
** and the WhereInfo.wctrlFlags member.
*/
#define WHERE_ORDERBY_NORMAL   0x0000 /* No-op */
#define WHERE_ORDERBY_MIN      0x0001 /* ORDER BY processing for min() func */
#define WHERE_ORDERBY_MAX      0x0002 /* ORDER BY processing for max() func */
#define WHERE_ONEPASS_DESIRED  0x0004 /* Want to do one-pass UPDATE/DELETE */
#define WHERE_DUPLICATES_OK    0x0008 /* Ok to return a row more than once */
#define WHERE_OMIT_OPEN_CLOSE  0x0010 /* Table cursors are already open */
#define WHERE_FORCE_TABLE      0x0020 /* Do not use an index-only search */
#define WHERE_ONETABLE_ONLY    0x0040 /* Only code the 1st table in pTabList */
#define WHERE_AND_ONLY         0x0080 /* Don't use indices for OR terms */
#define WHERE_GROUPBY          0x0100 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY       0x0200 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT    0x0400 /* All output needs to be distinct */



/*
** The WHERE clause processing routine has two halves.  The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop.  An instance of
** this structure is returned by the first half and passed
** into the second half to give some continuity.
*/
#if 0
struct WhereInfo {
  Parse *pParse;       /* Parsing and code generating context */
  u16 wctrlFlags;      /* Flags originally passed to sqlite4WhereBegin() */
  u8 okOnePass;        /* Ok to use one-pass algorithm for UPDATE or DELETE */
  u8 untestedTerms;    /* Not all WHERE terms resolved by outer loop */
  u8 eDistinct;
  SrcList *pTabList;             /* List of tables in the join */
  int iTop;                      /* The very beginning of the WHERE loop */
  int iContinue;                 /* Jump here to continue with next record */
  int iBreak;                    /* Jump here to break out of the loop */
  int nLevel;                    /* Number of nested loop */
  struct WhereClause *pWC;       /* Decomposition of the WHERE clause */
  double savedNQueryLoop;        /* pParse->nQueryLoop outside the WHERE loop */
  double nRowOut;                /* Estimated number of output rows */
  WhereLevel a[1];               /* Information about each nest loop in WHERE */
};
#endif

#define WHERE_DISTINCT_NOOP      0
#define WHERE_DISTINCT_UNIQUE    1
#define WHERE_DISTINCT_ORDERED   2
#define WHERE_DISTINCT_UNORDERED 3

/*
** 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
** a list of named expression (pEList).  The named expression list may
** be NULL.  The pSrc corresponds to the FROM clause of a SELECT or
** to the table being operated on by INSERT, UPDATE, or DELETE.  The
** pEList corresponds to the result set of a SELECT and is NULL for
** other statements.
**
** NameContexts can be nested.  When resolving names, the inner-most 
** context is searched first.  If no match is found, the next outer
** context is checked.  If there is still no match, the next context
** is checked.  This process continues until either a match is found
** or all contexts are check.  When a match is found, the nRef member of
** the context containing the match is incremented. 
**
** Each subquery gets a new NameContext.  The pNext field points to the
** NameContext in the parent query.  Thus the process of scanning the
** NameContext list corresponds to searching through successively outer
** subqueries looking for a match.
*/
struct NameContext {
  Parse *pParse;       /* The parser */
  SrcList *pSrcList;   /* One or more tables used to resolve names */
  ExprList *pEList;    /* Optional list of named expressions */
  int nRef;            /* Number of names resolved by this context */
  int nErr;            /* Number of errors encountered while resolving names */
  u8 allowAgg;         /* Aggregate functions allowed here */
  u8 hasAgg;           /* True if aggregates are seen */
  u8 isCheck;          /* True if resolving names in a CHECK constraint */
  int nDepth;          /* Depth of subquery recursion. 1 for no recursion */
  AggInfo *pAggInfo;   /* Information about aggregates at this level */
  NameContext *pNext;  /* Next outer name context.  NULL for outermost */
};

/*
** An instance of the following structure contains all information
** needed to generate code for a single SELECT statement.
**
** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
** If there is a LIMIT clause, the parser sets nLimit to the value of the
** limit and nOffset to the value of the offset (or 0 if there is not
** offset).  But later on, nLimit and nOffset become the memory locations
** in the VDBE that record the limit and offset counters.
**
** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
** These addresses must be stored so that we can go back and fill in
** the P4_KEYINFO and P2 parameters later.  Neither the KeyInfo nor
** the number of columns in P2 can be computed at the same time
** as the OP_OpenEphm instruction is coded because not
** enough information about the compound query is known at that point.
** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
** for the result set.  The KeyInfo for addrOpenTran[2] contains collating
** sequences for the ORDER BY clause.
*/
struct Select {
  ExprList *pEList;      /* The fields of the result */
  u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  char affinity;         /* EncodeData with this affinity for SRT_Set */
  u16 selFlags;          /* Various SF_* values */
  SrcList *pSrc;         /* The FROM clause */
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  Select *pPrior;        /* Prior select in a compound select statement */
  Select *pNext;         /* Next select to the left in a compound */
  Select *pRightmost;    /* Right-most select in a compound select statement */
  Expr *pLimit;          /* LIMIT expression. NULL means not used. */
  Expr *pOffset;         /* OFFSET expression. NULL means not used. */
  int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  int addrOpenEphm[3];   /* OP_OpenEphem opcodes related to this select */
  double nSelectRow;     /* Estimated number of result rows */
};

/*
** Allowed values for Select.selFlags.  The "SF" prefix stands for
** "Select Flag".
*/
#define SF_Distinct        0x01  /* Output should be DISTINCT */
#define SF_Resolved        0x02  /* Identifiers have been resolved */
#define SF_Aggregate       0x04  /* Contains aggregate functions */
#define SF_UsesEphemeral   0x08  /* Uses the OpenEphemeral opcode */
#define SF_Expanded        0x10  /* sqlite4SelectExpand() called on this */
#define SF_HasTypeInfo     0x20  /* FROM subqueries have Table metadata */
#define SF_UseSorter       0x40  /* Sort using a sorter */
#define SF_Values          0x80  /* Synthesized from VALUES clause */


/*
** The results of a select can be distributed in several ways.  The
** "SRT" prefix means "SELECT Result Type".
*/
#define SRT_Union        1  /* Store result as keys in an index */
#define SRT_Except       2  /* Remove result from a UNION index */
#define SRT_Exists       3  /* Store 1 if the result is not empty */
#define SRT_Discard      4  /* Do not save the results anywhere */

/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)

#define SRT_Output       5  /* Output each row of result */
#define SRT_Mem          6  /* Store result in a memory cell */
#define SRT_Set          7  /* Store results as keys in an index */
#define SRT_Table        8  /* Store result as data with an automatic rowid */
#define SRT_EphemTab     9  /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine   10  /* Generate a single row of result */

/*
** A structure used to customize the behavior of sqlite4Select(). See
** comments above sqlite4Select() for details.
*/
typedef struct SelectDest SelectDest;
struct SelectDest {
  u8 eDest;         /* How to dispose of the results */
  u8 affinity;      /* Affinity used when eDest==SRT_Set */
  int iParm;        /* A parameter used by the eDest disposal method */
  int iMem;         /* Base register where results are written */
  int nMem;         /* Number of registers allocated */
};

/*
** During code generation of statements that do inserts into AUTOINCREMENT 
** tables, the following information is attached to the Table.u.autoInc.p
** pointer of each autoincrement table to record some side information that
** the code generator needs.  We have to keep per-table autoincrement
** information in case inserts are down within triggers.  Triggers do not
** normally coordinate their activities, but we do need to coordinate the
** loading and saving of autoincrement information.
*/
struct AutoincInfo {
  AutoincInfo *pNext;   /* Next info block in a list of them all */
  Table *pTab;          /* Table this info block refers to */
  int iDb;              /* Index in sqlite4.aDb[] of database holding pTab */
  int regCtr;           /* Memory register holding the rowid counter */
};

/*
** Size of the column cache
*/
#ifndef SQLITE4_N_COLCACHE
# define SQLITE4_N_COLCACHE 10
#endif

/*
** At least one instance of the following structure is created for each 
** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
** statement. All such objects are stored in the linked list headed at
** Parse.pTriggerPrg and deleted once statement compilation has been
** completed.
**
** A Vdbe sub-program that implements the body and WHEN clause of trigger
** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of
** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable.
** The Parse.pTriggerPrg list never contains two entries with the same
** values for both pTrigger and orconf.
**
** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
** accessed (or set to 0 for triggers fired as a result of INSERT 
** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
** a mask of new.* columns used by the program.
*/
struct TriggerPrg {
  Trigger *pTrigger;      /* Trigger this program was coded from */
  int orconf;             /* Default ON CONFLICT policy */
  SubProgram *pProgram;   /* Program implementing pTrigger/orconf */
  u32 aColmask[2];        /* Masks of old.*, new.* columns accessed */
  TriggerPrg *pNext;      /* Next entry in Parse.pTriggerPrg list */
};

/*
** The yDbMask datatype for the bitmask of all attached databases.
*/
#if SQLITE4_MAX_ATTACHED>30
  typedef sqlite4_uint64 yDbMask;
#else
  typedef unsigned int yDbMask;
#endif

/*
** Internal column cache for Parse objects. One of these is used
** for each column cache entry.
*/
struct ParseYColCache {
  int iTable;           /* Table cursor number */
  int iColumn;          /* Table column number */
  u8 tempReg;           /* iReg is a temp register that needs to be freed */
  int iLevel;           /* Nesting level */
  int iReg;             /* Reg with value of this column. 0 means none. */
  int lru;              /* Least recently used entry has the smallest value */
};


/*
** An SQL parser context.  A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
**
** The structure is divided into two parts.  When the parser and code
** generate call themselves recursively, the first part of the structure
** is constant but the second part is reset at the beginning and end of
** each recursion.
*/
struct Parse {
  sqlite4 *db;         /* The main database structure */
  int rc;              /* Return code from execution */
  char *zErrMsg;       /* An error message */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
  u8 checkSchema;      /* Causes schema cookie check after an error */
  u8 nested;           /* Number of nested calls to the parser/code generator */
  u8 nTempReg;         /* Number of temporary registers in aTempReg[] */
  u8 nTempInUse;       /* Number of aTempReg[] currently checked out */
  int aTempReg[8];     /* Holding area for temporary registers */
  int nRangeReg;       /* Size of the temporary register block */
  int iRangeReg;       /* First register in temporary register block */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nOnce;           /* Number of OP_Once instructions so far */
  int ckBase;          /* Base register of data during check constraints */
  int iCacheLevel;     /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
  int iCacheCnt;       /* Counter used to generate aColCache[].lru values */
  int iNewidxReg;      /* First argument to OP_NewIdxid */
  u8 nColCache;        /* Number of entries in aColCache[] */
  u8 iColCache;        /* Next entry in aColCache[] to replace */
  ParseYColCache aColCache[SQLITE4_N_COLCACHE]; /* One per colcache entry */
  yDbMask writeMask;   /* Start a write transaction on these databases */
  yDbMask cookieMask;  /* Bitmask of schema verified databases */
  u8 isMultiWrite;     /* True if statement may affect/insert multiple rows */
  u8 mayAbort;         /* True if statement may throw an ABORT exception */
  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE4_MAX_ATTACHED+2];  /* Values of cookies to verify */
  int regRowid;        /* Register holding rowid of CREATE TABLE entry */
  int *pPKRoot;        /* if !=0, CREATE TABLE should store root of PK here */
  AutoincInfo *pAinc;  /* Information about AUTOINCREMENT counters */
  int nMaxArg;         /* Max args passed to user function by sub-program */

  /* Information used while coding trigger programs. */
  Parse *pToplevel;    /* Parse structure for main program (or NULL) */
  Table *pTriggerTab;  /* Table triggers are being coded for */
  u32 oldmask;         /* Mask of old.* columns referenced */
  u32 newmask;         /* Mask of new.* columns referenced */
  u8 eTriggerOp;       /* TK_UPDATE, TK_INSERT or TK_DELETE */
  u8 eOrconf;          /* Default ON CONFLICT policy for trigger steps */
  u8 disableTriggers;  /* True to disable triggers */
  double nQueryLoop;   /* Estimated number of iterations of a query */

  /* Above is constant between recursions.  Below is reset before and after
  ** each recursion */

  int nVar;            /* Number of '?' variables seen in the SQL so far */
  int nzVar;           /* Number of available slots in azVar[] */
  char **azVar;        /* Pointers to names of parameters */
  Vdbe *pReprepare;    /* VM being reprepared (sqlite4Reprepare()) */
  int nAlias;          /* Number of aliased result set columns */
  int *aAlias;         /* Register used to hold aliased result */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */
  Token sNameToken;    /* Token with unqualified schema object name */
  Token sLastToken;    /* The last token parsed */
  const char *zTail;   /* All SQL text past the last semicolon parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  Token sArg;                /* Complete text of a module argument */
  u8 declareVtab;            /* True if inside sqlite4_declare_vtab() */
  int nVtabLock;             /* Number of virtual tables to lock */
  Table **apVtabLock;        /* Pointer to virtual tables needing locking */
#endif
  int nHeight;            /* Expression tree height of current sub-select */
  Table *pZombieTab;      /* List of Table objects to delete after code gen */
  TriggerPrg *pTriggerPrg;    /* Linked list of coded triggers */

#ifndef SQLITE4_OMIT_EXPLAIN
  int iSelectId;
  int iNextSelectId;
#endif
};

#ifdef SQLITE4_OMIT_VIRTUALTABLE
  #define IN_DECLARE_VTAB 0
#else
  #define IN_DECLARE_VTAB (pParse->declareVtab)
#endif

/*
** An instance of the following structure can be declared on a stack and used
** to save the Parse.zAuthContext value so that it can be restored later.
*/
struct AuthContext {
  const char *zAuthContext;   /* Put saved Parse.zAuthContext here */
  Parse *pParse;              /* The Parse structure */
};

/*
** Bitfield flags for P5 value in OP_Insert and OP_Delete
*/
#define OPFLAG_NCHANGE       0x01    /* Set to update db->nChange */
#define OPFLAG_ISUPDATE      0x02    /* This OP_Insert is an sql UPDATE */
#define OPFLAG_USEKEY        0x04    /* Optimize OP_EncodeData using key content */
#define OPFLAG_SEQCOUNT      0x08    /* Append sequence number to key */
#define OPFLAG_CLEARCACHE    0x10    /* Clear pseudo-table cache in OP_Column */

/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger. 
 *
 * Pointers to instances of struct Trigger are stored in two ways.
 * 1. In the "trigHash" hash table (part of the sqlite4* that represents the 
 *    database). This allows Trigger structures to be retrieved by name.
 * 2. All triggers associated with a single table form a linked list, using the
 *    pNext member of struct Trigger. A pointer to the first element of the
 *    linked list is stored as the "pTrigger" member of the associated
 *    struct Table.
 *
 * The "step_list" member points to the first element of a linked list
 * containing the SQL statements specified as the trigger program.
 */
struct Trigger {
  char *zName;            /* The name of the trigger                        */
  char *table;            /* The table or view to which the trigger applies */
  u8 op;                  /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
  u8 tr_tm;               /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
  Expr *pWhen;            /* The WHEN clause of the expression (may be NULL) */
  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                             the <column-list> is stored here */
  Schema *pSchema;        /* Schema containing the trigger */
  Schema *pTabSchema;     /* Schema containing the table */
  TriggerStep *step_list; /* Link list of trigger program steps             */
  Trigger *pNext;         /* Next trigger associated with the table */
};

/*
** A trigger is either a BEFORE or an AFTER trigger.  The following constants
** determine which. 
**
** If there are multiple triggers, you might of some BEFORE and some AFTER.
** In that cases, the constants below can be ORed together.
*/
#define TRIGGER_BEFORE  1
#define TRIGGER_AFTER   2

/*
 * An instance of struct TriggerStep is used to store a single SQL statement
 * that is a part of a trigger-program. 
 *
 * Instances of struct TriggerStep are stored in a singly linked list (linked
 * using the "pNext" member) referenced by the "step_list" member of the 
 * associated struct Trigger instance. The first element of the linked list is
 * the first step of the trigger-program.
 * 
 * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
 * "SELECT" statement. The meanings of the other members is determined by the 
 * value of "op" as follows:
 *
 * (op == TK_INSERT)
 * orconf    -> stores the ON CONFLICT algorithm
 * pSelect   -> If this is an INSERT INTO ... SELECT ... statement, then
 *              this stores a pointer to the SELECT statement. Otherwise NULL.
 * target    -> A token holding the quoted name of the table to insert into.
 * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
 *              this stores values to be inserted. Otherwise NULL.
 * pIdList   -> If this is an INSERT INTO ... (<column-names>) VALUES ... 
 *              statement, then this stores the column-names to be
 *              inserted into.
 *
 * (op == TK_DELETE)
 * target    -> A token holding the quoted name of the table to delete from.
 * pWhere    -> The WHERE clause of the DELETE statement if one is specified.
 *              Otherwise NULL.
 * 
 * (op == TK_UPDATE)
 * target    -> A token holding the quoted name of the table to update rows of.
 * pWhere    -> The WHERE clause of the UPDATE statement if one is specified.
 *              Otherwise NULL.
 * pExprList -> A list of the columns to update and the expressions to update
 *              them to. See sqlite4Update() documentation of "pChanges"
 *              argument.
 * 
 */
struct TriggerStep {
  u8 op;               /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
  u8 orconf;           /* OE_Rollback etc. */
  Trigger *pTrig;      /* The trigger that this step is a part of */
  Select *pSelect;     /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
  Token target;        /* Target table for DELETE, UPDATE, INSERT */
  Expr *pWhere;        /* The WHERE clause for DELETE or UPDATE steps */
  ExprList *pExprList; /* SET clause for UPDATE.  VALUES clause for INSERT */
  IdList *pIdList;     /* Column names for INSERT */
  TriggerStep *pNext;  /* Next in the link-list */
  TriggerStep *pLast;  /* Last element in link-list. Valid for 1st elem only */
};

/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.  
*/
typedef struct DbFixer DbFixer;
struct DbFixer {
  Parse *pParse;      /* The parsing context.  Error messages written here */
  const char *zDb;    /* Make sure all objects are contained in this database */
  const char *zType;  /* Type of the container - used for error messages */
  const Token *pName; /* Name of the container - used for error messages */
};

/*
** An objected used to accumulate the text of a string where we
** do not necessarily know how big the string will be in the end.
*/
struct StrAccum {
  sqlite4 *db;         /* Optional database for lookaside.  Can be NULL */
  sqlite4_env *pEnv;   /* Malloc context */
  char *zBase;         /* A base allocation.  Not from malloc. */
  char *zText;         /* The string collected so far */
  int  nChar;          /* Length of the string so far */
  int  nAlloc;         /* Amount of space allocated in zText */
  int  mxAlloc;        /* Maximum allowed string length */
  u8   mallocFailed;   /* Becomes true if any memory allocation fails */
  u8   useMalloc;      /* 0: none,  1: sqlite4DbMalloc,  2: sqlite4_malloc */
  u8   tooBig;         /* Becomes true if string size exceeds limits */
};

/*
** A pointer to this structure is used to communicate information
** from sqlite4Init and OP_ParseSchema into the sqlite4InitCallback.
*/
typedef struct {
  sqlite4 *db;        /* The database being initialized */
  int iDb;            /* 0 for main database.  1 for TEMP, 2.. for ATTACHed */
  char **pzErrMsg;    /* Error message stored here */
  int rc;             /* Result code stored here */
} InitData;

/*
** A pluggable storage engine
*/
typedef struct KVFactory {
  struct KVFactory *pNext;       /* Next in list of all storage engines */
  const char *zName;             /* Name of this factory */
  sqlite4_kvfactory xFactory;    /* Function to make an sqlite4_kvstore obj */
  int isPerm;                    /* True if a built-in.  Cannot be popped */
} KVFactory;

/*
** An instance of this structure defines the run-time environment.
*/
struct sqlite4_env {
  int nByte;                        /* Size of this object in bytes */
  int iVersion;                     /* Version number of this structure */
  int bMemstat;                     /* True to enable memory status */
  int bCoreMutex;                   /* True to enable core mutexing */
  int bFullMutex;                   /* True to enable full mutexing */
  int mxStrlen;                     /* Maximum string length */
  int szLookaside;                  /* Default lookaside buffer size */
  int nLookaside;                   /* Default lookaside buffer count */
  sqlite4_mm *pMM;                  /* Memory allocator for this environment */
  sqlite4_mutex_methods mutex;      /* Low-level mutex interface */
  void *pHeap;                      /* Heap storage space */
  int nHeap;                        /* Size of pHeap[] */
  int mnReq, mxReq;                 /* Min and max heap requests sizes */
  int mxParserStack;                /* maximum depth of the parser stack */
  KVFactory *pFactory;              /* List of factories */
  int (*xRandomness)(sqlite4_env*, int, unsigned char*);
  int (*xCurrentTime)(sqlite4_env*, sqlite4_uint64*);
  /* The above might be initialized to non-zero.  The following need to always
  ** initially be zero, however. */
  int isInit;                       /* True after initialization has finished */
  sqlite4_mutex *pFactoryMutex;     /* Mutex for pFactory */
  sqlite4_mutex *pPrngMutex;        /* Mutex for the PRNG */
  u32 prngX, prngY;                 /* State of the PRNG */
  void (*xLog)(void*,int,const char*); /* Function for logging */
  void *pLogArg;                       /* First argument to xLog() */
  int bLocaltimeFault;              /* True to fail localtime() calls */
  sqlite4_mutex *pMemMutex;         /* Mutex for nowValue[] and mxValue[] */
  sqlite4_uint64 nowValue[4];       /* sqlite4_env_status() current values */
  sqlite4_uint64 mxValue[4];        /* sqlite4_env_status() max values */
  FuncDefTable aGlobalFuncs;        /* Lookup table of global functions */
};

/*
** Context pointer passed down through the tree-walk.
*/
struct Walker {
  int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
  int (*xSelectCallback)(Walker*,Select*);  /* Callback for SELECTs */
  Parse *pParse;                            /* Parser context.  */
  union {                                   /* Extra data for callback */
    NameContext *pNC;                          /* Naming context */
    int i;                                     /* Integer value */
  } u;
};

/*
** An instance of this structure is used as the p4 argument to some fts5
** related vdbe opcodes.
*/
struct Fts5Info {
  int iDb;                        /* Database containing this index */
  int iRoot;                      /* Root page number of index */
  int iTbl;                       /* Root page number of indexed table */
  int nCol;                       /* Number of columns in indexed table */
  char **azCol;                   /* Column names for table */
  Fts5Tokenizer *pTokenizer;      /* Tokenizer module */
  sqlite4_tokenizer *p;           /* Tokenizer instance */
};

SQLITE4_PRIVATE int sqlite4WalkExpr(Walker*, Expr*);
SQLITE4_PRIVATE int sqlite4WalkExprList(Walker*, ExprList*);
SQLITE4_PRIVATE int sqlite4WalkSelect(Walker*, Select*);
SQLITE4_PRIVATE int sqlite4WalkSelectExpr(Walker*, Select*);
SQLITE4_PRIVATE int sqlite4WalkSelectFrom(Walker*, Select*);

/*
** Return code from the parse-tree walking primitives and their
** callbacks.
*/
#define WRC_Continue    0   /* Continue down into children */
#define WRC_Prune       1   /* Omit children but continue walking siblings */
#define WRC_Abort       2   /* Abandon the tree walk */

/*
** Assuming zIn points to the first byte of a UTF-8 character,
** advance zIn to point to the first byte of the next UTF-8 character.
*/
#define SQLITE4_SKIP_UTF8(zIn) {                       \
  if( (*(unsigned char *)(zIn++))>=0xc0 ){             \
    while( (*zIn & 0xc0)==0x80 ){ zIn++; }             \
  }                                                    \
}

/*
** Default memory allocator
*/
SQLITE4_PRIVATE sqlite4_mm sqlite4MMSystem;

/*
** The SQLITE4_*_BKPT macros are substitutes for the error codes with
** the same name but without the _BKPT suffix.  These macros invoke
** routines that report the line-number on which the error originated
** using sqlite4_log().  The routines also provide a convenient place
** to set a debugger breakpoint.
*/
SQLITE4_PRIVATE int sqlite4CorruptError(int);
SQLITE4_PRIVATE int sqlite4MisuseError(int);
SQLITE4_PRIVATE int sqlite4CantopenError(int);
#define SQLITE4_CORRUPT_BKPT sqlite4CorruptError(__LINE__)
#define SQLITE4_MISUSE_BKPT sqlite4MisuseError(__LINE__)
#define SQLITE4_CANTOPEN_BKPT sqlite4CantopenError(__LINE__)


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


/*
** The following macros mimic the standard library functions toupper(),
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
** sqlite versions only work for ASCII characters, regardless of locale.
*/
#ifdef SQLITE4_ASCII
# define sqlite4Toupper(x)  ((x)&~(sqlite4CtypeMap[(unsigned char)(x)]&0x20))
# define sqlite4Isspace(x)   (sqlite4CtypeMap[(unsigned char)(x)]&0x01)
# define sqlite4Isalnum(x)   (sqlite4CtypeMap[(unsigned char)(x)]&0x06)
# define sqlite4Isalpha(x)   (sqlite4CtypeMap[(unsigned char)(x)]&0x02)
# define sqlite4Isdigit(x)   (sqlite4CtypeMap[(unsigned char)(x)]&0x04)
# define sqlite4Isxdigit(x)  (sqlite4CtypeMap[(unsigned char)(x)]&0x08)
# define sqlite4Tolower(x)   (sqlite4UpperToLower[(unsigned char)(x)])
#else
# define sqlite4Toupper(x)   toupper((unsigned char)(x))
# define sqlite4Isspace(x)   isspace((unsigned char)(x))
# define sqlite4Isalnum(x)   isalnum((unsigned char)(x))
# define sqlite4Isalpha(x)   isalpha((unsigned char)(x))
# define sqlite4Isdigit(x)   isdigit((unsigned char)(x))
# define sqlite4Isxdigit(x)  isxdigit((unsigned char)(x))
# define sqlite4Tolower(x)   tolower((unsigned char)(x))
#endif

/*
** Internal function prototypes
*/
SQLITE4_PRIVATE int sqlite4Strlen30(const char*);

SQLITE4_PRIVATE int sqlite4MallocInit(sqlite4_env*);
SQLITE4_PRIVATE void sqlite4MallocEnd(sqlite4_env*);
SQLITE4_PRIVATE void *sqlite4Malloc(sqlite4_env*, int);
SQLITE4_PRIVATE void *sqlite4MallocZero(sqlite4_env*, int);
SQLITE4_PRIVATE void *sqlite4DbMallocZero(sqlite4*, int);
SQLITE4_PRIVATE void *sqlite4DbMallocRaw(sqlite4*, int);
SQLITE4_PRIVATE char *sqlite4DbStrDup(sqlite4*,const char*);
SQLITE4_PRIVATE char *sqlite4DbStrNDup(sqlite4*,const char*, int);
SQLITE4_PRIVATE void *sqlite4Realloc(sqlite4_env*, void*, int);
SQLITE4_PRIVATE void *sqlite4DbReallocOrFree(sqlite4 *, void *, int);
SQLITE4_PRIVATE void *sqlite4DbRealloc(sqlite4 *, void *, int);
SQLITE4_PRIVATE void sqlite4DbFree(sqlite4*, void*);
SQLITE4_PRIVATE int sqlite4MallocSize(sqlite4_env*, void*);
SQLITE4_PRIVATE int sqlite4DbMallocSize(sqlite4*, void*);
SQLITE4_PRIVATE void sqlite4MemSetDefault(sqlite4_env*);
SQLITE4_PRIVATE void sqlite4BenignMallocHooks(sqlite4_env*,void (*)(void), void (*)(void));

/*
** On systems with ample stack space and that support alloca(), make
** use of alloca() to obtain space for large automatic objects.  By default,
** obtain space from malloc().
**
** The alloca() routine never returns NULL.  This will cause code paths
** that deal with sqlite4StackAlloc() failures to be unreachable.
*/
#ifdef SQLITE4_USE_ALLOCA
# define sqlite4StackAllocRaw(D,N)   alloca(N)
# define sqlite4StackAllocZero(D,N)  memset(alloca(N), 0, N)
# define sqlite4StackFree(D,P)       
#else
# define sqlite4StackAllocRaw(D,N)   sqlite4DbMallocRaw(D,N)
# define sqlite4StackAllocZero(D,N)  sqlite4DbMallocZero(D,N)
# define sqlite4StackFree(D,P)       sqlite4DbFree(D,P)
#endif

#ifdef SQLITE4_ENABLE_MEMSYS3
SQLITE4_PRIVATE const sqlite4_mem_methods *sqlite4MemGetMemsys3(void);
#endif
#ifdef SQLITE4_ENABLE_MEMSYS5
SQLITE4_PRIVATE const sqlite4_mem_methods *sqlite4MemGetMemsys5(void);
#endif


#ifndef SQLITE4_MUTEX_OMIT
SQLITE4_PRIVATE   sqlite4_mutex_methods const *sqlite4DefaultMutex(void);
SQLITE4_PRIVATE   sqlite4_mutex_methods const *sqlite4NoopMutex(void);
SQLITE4_PRIVATE   sqlite4_mutex *sqlite4MutexAlloc(sqlite4_env*,int);
SQLITE4_PRIVATE   int sqlite4MutexInit(sqlite4_env*);
SQLITE4_PRIVATE   int sqlite4MutexEnd(sqlite4_env*);
#endif

SQLITE4_PRIVATE void sqlite4StatusAdd(sqlite4_env*, int, sqlite4_int64);
SQLITE4_PRIVATE void sqlite4StatusSet(sqlite4_env*, int, sqlite4_uint64);

#ifndef SQLITE4_OMIT_FLOATING_POINT
SQLITE4_PRIVATE   int sqlite4IsNaN(double);
SQLITE4_PRIVATE   int sqlite4IsInf(double);
#else
# define sqlite4IsNaN(X)  0
# define sqlite4IsInf(X)  0
#endif

SQLITE4_PRIVATE void sqlite4BlobToHex(int, const u8*, char*);
SQLITE4_PRIVATE void sqlite4VXPrintf(StrAccum*, int, const char*, va_list);
#ifndef SQLITE4_OMIT_TRACE
SQLITE4_PRIVATE void sqlite4XPrintf(StrAccum*, const char*, ...);
#endif
SQLITE4_PRIVATE char *sqlite4MPrintf(sqlite4*,const char*, ...);
SQLITE4_PRIVATE char *sqlite4VMPrintf(sqlite4*,const char*, va_list);
SQLITE4_PRIVATE char *sqlite4MAppendf(sqlite4*,char*,const char*,...);
#if defined(SQLITE4_TEST) || defined(SQLITE4_DEBUG)
SQLITE4_PRIVATE   void sqlite4DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE4_TEST)
SQLITE4_PRIVATE   void *sqlite4TestTextToPtr(const char*);
#endif

/* Output formatting for SQLITE4_TESTCTRL_EXPLAIN */
#if defined(SQLITE4_ENABLE_TREE_EXPLAIN)
SQLITE4_PRIVATE   void sqlite4ExplainBegin(Vdbe*);
SQLITE4_PRIVATE   void sqlite4ExplainPrintf(Vdbe*, const char*, ...);
SQLITE4_PRIVATE   void sqlite4ExplainNL(Vdbe*);
SQLITE4_PRIVATE   void sqlite4ExplainPush(Vdbe*);
SQLITE4_PRIVATE   void sqlite4ExplainPop(Vdbe*);
SQLITE4_PRIVATE   void sqlite4ExplainFinish(Vdbe*);
SQLITE4_PRIVATE   void sqlite4ExplainSelect(Vdbe*, Select*);
SQLITE4_PRIVATE   void sqlite4ExplainExpr(Vdbe*, Expr*);
SQLITE4_PRIVATE   void sqlite4ExplainExprList(Vdbe*, ExprList*);
SQLITE4_PRIVATE   const char *sqlite4VdbeExplanation(Vdbe*);
#else
# define sqlite4ExplainBegin(X)
# define sqlite4ExplainSelect(A,B)
# define sqlite4ExplainExpr(A,B)
# define sqlite4ExplainExprList(A,B)
# define sqlite4ExplainFinish(X)
# define sqlite4VdbeExplanation(X) 0
#endif


SQLITE4_PRIVATE void sqlite4SetString(char **, sqlite4*, const char*, ...);
SQLITE4_PRIVATE void sqlite4ErrorMsg(Parse*, const char*, ...);
SQLITE4_PRIVATE int sqlite4Dequote(char*);
SQLITE4_PRIVATE int sqlite4KeywordCode(const unsigned char*, int);
SQLITE4_PRIVATE int sqlite4RunParser(Parse*, const char*, char **);
SQLITE4_PRIVATE void sqlite4FinishCoding(Parse*);
SQLITE4_PRIVATE int sqlite4GetTempReg(Parse*);
SQLITE4_PRIVATE void sqlite4ReleaseTempReg(Parse*,int);
SQLITE4_PRIVATE int sqlite4GetTempRange(Parse*,int);
SQLITE4_PRIVATE void sqlite4ReleaseTempRange(Parse*,int,int);
SQLITE4_PRIVATE void sqlite4ClearTempRegCache(Parse*);
SQLITE4_PRIVATE Expr *sqlite4ExprAlloc(sqlite4*,int,const Token*,int);
SQLITE4_PRIVATE Expr *sqlite4Expr(sqlite4*,int,const char*);
SQLITE4_PRIVATE void sqlite4ExprAttachSubtrees(sqlite4*,Expr*,Expr*,Expr*);
SQLITE4_PRIVATE Expr *sqlite4PExpr(Parse*, int, Expr*, Expr*, const Token*);
SQLITE4_PRIVATE Expr *sqlite4ExprAnd(sqlite4*,Expr*, Expr*);
SQLITE4_PRIVATE Expr *sqlite4ExprFunction(Parse*,ExprList*, Token*);
SQLITE4_PRIVATE void sqlite4ExprAssignVarNumber(Parse*, Expr*);
SQLITE4_PRIVATE void sqlite4ExprDelete(sqlite4*, Expr*);
SQLITE4_PRIVATE ExprList *sqlite4ExprListAppend(Parse*,ExprList*,Expr*);
SQLITE4_PRIVATE void sqlite4ExprListSetName(Parse*,ExprList*,Token*,int);
SQLITE4_PRIVATE void sqlite4ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
SQLITE4_PRIVATE void sqlite4ExprListDelete(sqlite4*, ExprList*);
SQLITE4_PRIVATE int sqlite4Init(sqlite4*, char**);
SQLITE4_PRIVATE int sqlite4InitCallback(void*, int, sqlite4_value**, const char**);
SQLITE4_PRIVATE void sqlite4Pragma(Parse*,Token*,Token*,ExprList*);
SQLITE4_PRIVATE void sqlite4ResetInternalSchema(sqlite4*, int);
SQLITE4_PRIVATE void sqlite4BeginParse(Parse*,int);
SQLITE4_PRIVATE void sqlite4CommitInternalChanges(sqlite4*);
SQLITE4_PRIVATE Table *sqlite4ResultSetOfSelect(Parse*,Select*);
SQLITE4_PRIVATE void sqlite4OpenMasterTable(Parse *, int);
SQLITE4_PRIVATE void sqlite4StartTable(Parse*,Token*,Token*,int,int,int,int);
SQLITE4_PRIVATE void sqlite4AddColumn(Parse*,Token*);
SQLITE4_PRIVATE void sqlite4AddNotNull(Parse*, int);
SQLITE4_PRIVATE void sqlite4AddPrimaryKey(Parse*, ExprList*, int, int, int);
SQLITE4_PRIVATE void sqlite4AddCheckConstraint(Parse*, Expr*);
SQLITE4_PRIVATE void sqlite4AddColumnType(Parse*,Token*);
SQLITE4_PRIVATE void sqlite4AddDefaultValue(Parse*,ExprSpan*);
SQLITE4_PRIVATE void sqlite4AddCollateType(Parse*, Token*);
SQLITE4_PRIVATE void sqlite4EndTable(Parse*,Token*,Token*,Select*);
SQLITE4_PRIVATE int sqlite4ParseUri(sqlite4_env*,const char*,unsigned int*,char**,char **);
SQLITE4_PRIVATE int sqlite4CodeOnce(Parse *);

SQLITE4_PRIVATE RowSet *sqlite4RowSetInit(sqlite4 *, void *, unsigned int);
SQLITE4_PRIVATE void sqlite4RowSetClear(RowSet *);
SQLITE4_PRIVATE void sqlite4RowSetInsert(RowSet *, u8 *, int);
SQLITE4_PRIVATE int sqlite4RowSetNext(RowSet *);
SQLITE4_PRIVATE const u8 *sqlite4RowSetRead(RowSet *, int *);
SQLITE4_PRIVATE int sqlite4RowSetTest(RowSet *, u8, u8 *, int);

SQLITE4_PRIVATE void sqlite4CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);

#if !defined(SQLITE4_OMIT_VIEW) || !defined(SQLITE4_OMIT_VIRTUALTABLE)
SQLITE4_PRIVATE   int sqlite4ViewGetColumnNames(Parse*,Table*);
#else
# define sqlite4ViewGetColumnNames(A,B) 0
#endif

SQLITE4_PRIVATE void sqlite4DropTable(Parse*, SrcList*, int, int);
SQLITE4_PRIVATE void sqlite4CodeDropTable(Parse*, Table*, int, int);
SQLITE4_PRIVATE void sqlite4DeleteTable(sqlite4*, Table*);
#ifndef SQLITE4_OMIT_AUTOINCREMENT
SQLITE4_PRIVATE   void sqlite4AutoincrementBegin(Parse *pParse);
SQLITE4_PRIVATE   void sqlite4AutoincrementEnd(Parse *pParse);
#else
# define sqlite4AutoincrementBegin(X)
# define sqlite4AutoincrementEnd(X)
#endif
SQLITE4_PRIVATE void sqlite4Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
SQLITE4_PRIVATE void *sqlite4ArrayAllocate(sqlite4*,void*,int,int,int*,int*,int*);
SQLITE4_PRIVATE IdList *sqlite4IdListAppend(sqlite4*, IdList*, Token*);
SQLITE4_PRIVATE int sqlite4IdListIndex(IdList*,const char*);
SQLITE4_PRIVATE SrcList *sqlite4SrcListEnlarge(sqlite4*, SrcList*, int, int);
SQLITE4_PRIVATE SrcList *sqlite4SrcListAppend(sqlite4*, SrcList*, Token*, Token*);
SQLITE4_PRIVATE SrcList *sqlite4SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
                                      Token*, Select*, Expr*, IdList*);
SQLITE4_PRIVATE void sqlite4SrcListIndexedBy(Parse *, SrcList *, Token *);
SQLITE4_PRIVATE int sqlite4IndexedByLookup(Parse *, SrcListItem *);
SQLITE4_PRIVATE void sqlite4SrcListShiftJoinType(SrcList*);
SQLITE4_PRIVATE void sqlite4SrcListAssignCursors(Parse*, SrcList*);
SQLITE4_PRIVATE void sqlite4IdListDelete(sqlite4*, IdList*);
SQLITE4_PRIVATE void sqlite4SrcListDelete(sqlite4*, SrcList*);
SQLITE4_PRIVATE Index *sqlite4CreateIndex(Parse*,CreateIndex*,ExprList*,IdList*,int,Token*,int,int);
SQLITE4_PRIVATE void sqlite4DropIndex(Parse*, SrcList*, int);
SQLITE4_PRIVATE int sqlite4Select(Parse*, Select*, SelectDest*);
SQLITE4_PRIVATE Select *sqlite4SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                         Expr*,ExprList*,int,Expr*,Expr*);
SQLITE4_PRIVATE void sqlite4SelectDelete(sqlite4*, Select*);
SQLITE4_PRIVATE Table *sqlite4SrcListLookup(Parse*, SrcList*);
SQLITE4_PRIVATE int sqlite4IsReadOnly(Parse*, Table*, int);
SQLITE4_PRIVATE void sqlite4OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE4_ENABLE_UPDATE_DELETE_LIMIT) \
    && !defined(SQLITE4_OMIT_SUBQUERY)
SQLITE4_PRIVATE Expr *sqlite4LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
#endif
SQLITE4_PRIVATE void sqlite4DeleteFrom(Parse*, SrcList*, Expr*);
SQLITE4_PRIVATE void sqlite4Update(Parse*, SrcList*, ExprList*, Expr*, int);
SQLITE4_PRIVATE WhereInfo *sqlite4WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);

SQLITE4_PRIVATE void sqlite4WhereEnd(WhereInfo*);
SQLITE4_PRIVATE u64 sqlite4WhereOutputRowCount(WhereInfo*);
SQLITE4_PRIVATE int sqlite4WhereIsDistinct(WhereInfo*);
SQLITE4_PRIVATE int sqlite4WhereIsOrdered(WhereInfo*);
SQLITE4_PRIVATE int sqlite4WhereContinueLabel(WhereInfo*);
SQLITE4_PRIVATE int sqlite4WhereBreakLabel(WhereInfo*);
SQLITE4_PRIVATE int sqlite4WhereOkOnePass(WhereInfo*);
SQLITE4_PRIVATE int sqlite4ExprCodeGetColumn(Parse*, Table*, int, int, int);
SQLITE4_PRIVATE void sqlite4ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
SQLITE4_PRIVATE void sqlite4ExprCodeMove(Parse*, int, int, int);
SQLITE4_PRIVATE void sqlite4ExprCodeCopy(Parse*, int, int, int);
SQLITE4_PRIVATE void sqlite4ExprCacheStore(Parse*, int, int, int);
SQLITE4_PRIVATE void sqlite4ExprCachePush(Parse*);
SQLITE4_PRIVATE void sqlite4ExprCachePop(Parse*, int);
SQLITE4_PRIVATE void sqlite4ExprCacheRemove(Parse*, int, int);
SQLITE4_PRIVATE void sqlite4ExprCacheClear(Parse*);
SQLITE4_PRIVATE void sqlite4ExprCacheAffinityChange(Parse*, int, int);
SQLITE4_PRIVATE int sqlite4ExprCode(Parse*, Expr*, int);
SQLITE4_PRIVATE int sqlite4ExprCodeTemp(Parse*, Expr*, int*);
SQLITE4_PRIVATE int sqlite4ExprCodeTarget(Parse*, Expr*, int);
SQLITE4_PRIVATE int sqlite4ExprCodeAndCache(Parse*, Expr*, int);
SQLITE4_PRIVATE void sqlite4ExprCodeConstants(Parse*, Expr*);
SQLITE4_PRIVATE int sqlite4ExprCodeExprList(Parse*, ExprList*, int, int);
SQLITE4_PRIVATE void sqlite4ExprIfTrue(Parse*, Expr*, int, int);
SQLITE4_PRIVATE void sqlite4ExprIfFalse(Parse*, Expr*, int, int);
SQLITE4_PRIVATE Table *sqlite4FindTable(sqlite4*,const char*, const char*);
SQLITE4_PRIVATE Table *sqlite4LocateTable(Parse*,int isView,const char*, const char*);
SQLITE4_PRIVATE Index *sqlite4FindIndex(sqlite4*,const char*, const char*);
SQLITE4_PRIVATE void sqlite4UnlinkAndDeleteTable(sqlite4*,int,const char*);
SQLITE4_PRIVATE void sqlite4UnlinkAndDeleteIndex(sqlite4*,int,const char*);
SQLITE4_PRIVATE void sqlite4Vacuum(Parse*);
SQLITE4_PRIVATE int sqlite4RunVacuum(char**, sqlite4*);
SQLITE4_PRIVATE char *sqlite4NameFromToken(sqlite4*, Token*);
SQLITE4_PRIVATE int sqlite4ExprCompare(Expr*, Expr*);
SQLITE4_PRIVATE int sqlite4ExprListCompare(ExprList*, ExprList*);
SQLITE4_PRIVATE void sqlite4ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE4_PRIVATE void sqlite4ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE4_PRIVATE Vdbe *sqlite4GetVdbe(Parse*);
SQLITE4_PRIVATE void sqlite4CodeVerifySchema(Parse*, int);
SQLITE4_PRIVATE void sqlite4CodeVerifyNamedSchema(Parse*, const char *zDb);
SQLITE4_PRIVATE void sqlite4BeginTransaction(Parse*, int);
SQLITE4_PRIVATE void sqlite4EndTransaction(Parse *, int);
SQLITE4_PRIVATE void sqlite4Savepoint(Parse*, int, Token*);
SQLITE4_PRIVATE void sqlite4CloseSavepoints(sqlite4 *);
SQLITE4_PRIVATE int sqlite4ExprIsConstant(Expr*);
SQLITE4_PRIVATE int sqlite4ExprIsConstantNotJoin(Expr*);
SQLITE4_PRIVATE int sqlite4ExprIsConstantOrFunction(Expr*);
SQLITE4_PRIVATE int sqlite4ExprIsInteger(Expr*, int*);
SQLITE4_PRIVATE int sqlite4ExprCanBeNull(const Expr*);
SQLITE4_PRIVATE void sqlite4ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
SQLITE4_PRIVATE int sqlite4ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE4_PRIVATE void sqlite4GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int);
SQLITE4_PRIVATE void sqlite4GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
SQLITE4_PRIVATE void sqlite4EncodeIndexKey(Parse *, Index *, int, Index *, int, int, int);
SQLITE4_PRIVATE void sqlite4EncodeIndexValue(Parse*, int, Index*, int);
SQLITE4_PRIVATE void sqlite4GenerateConstraintChecks(Parse*,Table*,int,int,
                                     int*,int,int,int,int,int*);
SQLITE4_PRIVATE void sqlite4CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
SQLITE4_PRIVATE int sqlite4OpenTableAndIndices(Parse*, Table*, int, int);
SQLITE4_PRIVATE void sqlite4BeginWriteOperation(Parse*, int, int);
SQLITE4_PRIVATE void sqlite4MultiWrite(Parse*);
SQLITE4_PRIVATE void sqlite4MayAbort(Parse*);
SQLITE4_PRIVATE void sqlite4HaltConstraint(Parse*, int, char*, int);
SQLITE4_PRIVATE Expr *sqlite4ExprDup(sqlite4*,Expr*,int);
SQLITE4_PRIVATE ExprList *sqlite4ExprListDup(sqlite4*,ExprList*,int);
SQLITE4_PRIVATE SrcList *sqlite4SrcListDup(sqlite4*,SrcList*,int);
SQLITE4_PRIVATE IdList *sqlite4IdListDup(sqlite4*,IdList*);
SQLITE4_PRIVATE Select *sqlite4SelectDup(sqlite4*,Select*,int);
SQLITE4_PRIVATE void sqlite4FuncDefInsert(FuncDefTable*, FuncDef*, int);
SQLITE4_PRIVATE FuncDef *sqlite4FindFunction(sqlite4*,const char*,int,int,int);
SQLITE4_PRIVATE void sqlite4RegisterBuiltinFunctions(sqlite4*);
SQLITE4_PRIVATE void sqlite4RegisterDateTimeFunctions(sqlite4_env*);
SQLITE4_PRIVATE void sqlite4RegisterGlobalFunctions(sqlite4_env*);
SQLITE4_PRIVATE int sqlite4SafetyCheckOk(sqlite4*);
SQLITE4_PRIVATE int sqlite4SafetyCheckSickOrOk(sqlite4*);
SQLITE4_PRIVATE void sqlite4ChangeCookie(Parse*, int);

#if !defined(SQLITE4_OMIT_VIEW) && !defined(SQLITE4_OMIT_TRIGGER)
SQLITE4_PRIVATE void sqlite4MaterializeView(Parse*, Table*, Expr*, int);
#else
# define sqlite4MaterializeView(w,x,y,z)
#endif

#ifndef SQLITE4_OMIT_TRIGGER
SQLITE4_PRIVATE   void sqlite4BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
                           Expr*,int, int);
SQLITE4_PRIVATE   void sqlite4FinishTrigger(Parse*, TriggerStep*, Token*);
SQLITE4_PRIVATE   void sqlite4DropTrigger(Parse*, SrcList*, int);
SQLITE4_PRIVATE   void sqlite4DropTriggerPtr(Parse*, Trigger*);
SQLITE4_PRIVATE   Trigger *sqlite4TriggersExist(Parse *, Table*, int, ExprList*, int *pMask);
SQLITE4_PRIVATE   Trigger *sqlite4TriggerList(Parse *, Table *);
SQLITE4_PRIVATE   void sqlite4CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
                            int, int, int);
SQLITE4_PRIVATE   void sqlite4CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
  void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
SQLITE4_PRIVATE   void sqlite4DeleteTriggerStep(sqlite4*, TriggerStep*);
SQLITE4_PRIVATE   TriggerStep *sqlite4TriggerSelectStep(sqlite4*,Select*);
SQLITE4_PRIVATE   TriggerStep *sqlite4TriggerInsertStep(sqlite4*,Token*, IdList*,
                                        ExprList*,Select*,u8);
SQLITE4_PRIVATE   TriggerStep *sqlite4TriggerUpdateStep(sqlite4*,Token*,ExprList*, Expr*, u8);
SQLITE4_PRIVATE   TriggerStep *sqlite4TriggerDeleteStep(sqlite4*,Token*, Expr*);
SQLITE4_PRIVATE   void sqlite4DeleteTrigger(sqlite4*, Trigger*);
SQLITE4_PRIVATE   void sqlite4UnlinkAndDeleteTrigger(sqlite4*,int,const char*);
SQLITE4_PRIVATE   u32 sqlite4TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
# define sqlite4ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
#else
# define sqlite4TriggersExist(B,C,D,E,F) 0
# define sqlite4DeleteTrigger(A,B)
# define sqlite4DropTriggerPtr(A,B)
# define sqlite4UnlinkAndDeleteTrigger(A,B,C)
# define sqlite4CodeRowTrigger(A,B,C,D,E,F,G,H,I)
# define sqlite4CodeRowTriggerDirect(A,B,C,D,E,F)
# define sqlite4TriggerList(X, Y) 0
# define sqlite4ParseToplevel(p) p
# define sqlite4TriggerColmask(A,B,C,D,E,F,G) 0
#endif

SQLITE4_PRIVATE int sqlite4JoinType(Parse*, Token*, Token*, Token*);
SQLITE4_PRIVATE void sqlite4CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
SQLITE4_PRIVATE void sqlite4DeferForeignKey(Parse*, int);
#ifndef SQLITE4_OMIT_AUTHORIZATION
SQLITE4_PRIVATE   void sqlite4AuthRead(Parse*,Expr*,Schema*,SrcList*);
SQLITE4_PRIVATE   int sqlite4AuthCheck(Parse*,int, const char*, const char*, const char*);
SQLITE4_PRIVATE   void sqlite4AuthContextPush(Parse*, AuthContext*, const char*);
SQLITE4_PRIVATE   void sqlite4AuthContextPop(AuthContext*);
SQLITE4_PRIVATE   int sqlite4AuthReadCol(Parse*, const char *, const char *, int);
SQLITE4_PRIVATE   void sqlite4AuthFreeAll(sqlite4 *db);
#else
# define sqlite4AuthRead(a,b,c,d)
# define sqlite4AuthCheck(a,b,c,d,e)    SQLITE4_OK
# define sqlite4AuthContextPush(a,b,c)
# define sqlite4AuthContextPop(a)  ((void)(a))
# define sqlite4AuthFreeAll(a)
#endif
SQLITE4_PRIVATE void sqlite4Attach(Parse*, Expr*, Expr*, Expr*);
SQLITE4_PRIVATE void sqlite4Detach(Parse*, Expr*);
SQLITE4_PRIVATE int sqlite4FixInit(DbFixer*, Parse*, int, const char*, const Token*);
SQLITE4_PRIVATE int sqlite4FixSrcList(DbFixer*, SrcList*);
SQLITE4_PRIVATE int sqlite4FixSelect(DbFixer*, Select*);
SQLITE4_PRIVATE int sqlite4FixExpr(DbFixer*, Expr*);
SQLITE4_PRIVATE int sqlite4FixExprList(DbFixer*, ExprList*);
SQLITE4_PRIVATE int sqlite4FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE4_PRIVATE int sqlite4GetInt32(const char *, int*);
SQLITE4_PRIVATE int sqlite4Atoi(const char*);
SQLITE4_PRIVATE int sqlite4Utf16ByteLen(const void *pData, int nChar);
SQLITE4_PRIVATE int sqlite4Utf8CharLen(const char *pData, int nByte);
SQLITE4_PRIVATE u32 sqlite4Utf8Read(const char*, const char**);

/*
** Routines to read and write variable-length integers.  These used to
** be defined locally, but now we use the varint routines in the util.c
** file.  Code should use the MACRO forms below, as the Varint32 versions
** are coded to assume the single byte case is already handled (which 
** the MACRO form does).
*/
SQLITE4_PRIVATE int sqlite4PutVarint(unsigned char*, u64);
SQLITE4_PRIVATE int sqlite4PutVarint32(unsigned char*, u32);
SQLITE4_PRIVATE u8 sqlite4GetVarint(const unsigned char *, u64 *);
SQLITE4_PRIVATE int sqlite4GetVarint32(const unsigned char *, u32 *);
SQLITE4_PRIVATE int sqlite4VarintLen(u64 v);
SQLITE4_PRIVATE int sqlite4GetVarint64(const unsigned char*, int, sqlite4_uint64 *pResult);
SQLITE4_PRIVATE int sqlite4PutVarint64(unsigned char*, sqlite4_uint64);

/*
** The header of a record consists of a sequence variable-length integers.
** These integers are almost always small and are encoded as a single byte.
** The following macros take advantage this fact to provide a fast encode
** and decode of the integers in a record header.  It is faster for the common
** case where the integer is a single byte.  It is a little slower when the
** integer is two or more bytes.  But overall it is faster.
**
** The following expressions are equivalent:
**
**     x = sqlite4GetVarint32( A, &B );
**     x = sqlite4PutVarint32( A, B );
**
**     x = getVarint32( A, B );
**     x = putVarint32( A, B );
**
*/
#define getVarint32(A,B)  \
  (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite4GetVarint32((A),(u32 *)&(B)))
#define putVarint32(A,B)  \
  (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1\
  :sqlite4PutVarint32((A),(B)))
#define getVarint    sqlite4GetVarint
#define putVarint    sqlite4PutVarint


SQLITE4_PRIVATE const char *sqlite4IndexAffinityStr(Vdbe *, Index *);
SQLITE4_PRIVATE void sqlite4TableAffinityStr(Vdbe *, Table *);
SQLITE4_PRIVATE char sqlite4CompareAffinity(Expr *pExpr, char aff2);
SQLITE4_PRIVATE int sqlite4IndexAffinityOk(Expr *pExpr, char idx_affinity);
SQLITE4_PRIVATE char sqlite4ExprAffinity(Expr *pExpr);
SQLITE4_PRIVATE int sqlite4Atoi64(const char*, i64*, int, u8);
SQLITE4_PRIVATE void sqlite4Error(sqlite4*, int, const char*,...);
SQLITE4_PRIVATE void *sqlite4HexToBlob(sqlite4*, const char *z, int n);
SQLITE4_PRIVATE u8 sqlite4HexToInt(int h);
SQLITE4_PRIVATE int sqlite4TwoPartName(Parse *, Token *, Token *, Token **);
SQLITE4_PRIVATE const char *sqlite4ErrStr(int);
SQLITE4_PRIVATE int sqlite4ReadSchema(Parse *pParse);
SQLITE4_PRIVATE CollSeq *sqlite4FindCollSeq(sqlite4*,const char*,int);
SQLITE4_PRIVATE CollSeq *sqlite4LocateCollSeq(Parse *pParse, const char*zName);
SQLITE4_PRIVATE CollSeq *sqlite4ExprCollSeq(Parse *pParse, Expr *pExpr);
SQLITE4_PRIVATE Expr *sqlite4ExprSetColl(Expr*, CollSeq*);
SQLITE4_PRIVATE Expr *sqlite4ExprSetCollByToken(Parse *pParse, Expr*, Token*);
SQLITE4_PRIVATE int sqlite4CheckCollSeq(Parse *, CollSeq *);
SQLITE4_PRIVATE int sqlite4CheckObjectName(Parse *, const char *);
SQLITE4_PRIVATE void sqlite4VdbeSetChanges(sqlite4 *, int);
SQLITE4_PRIVATE int sqlite4AddInt64(i64*,i64);
SQLITE4_PRIVATE int sqlite4SubInt64(i64*,i64);
SQLITE4_PRIVATE int sqlite4MulInt64(i64*,i64);
SQLITE4_PRIVATE int sqlite4AbsInt32(int);
#ifdef SQLITE4_ENABLE_8_3_NAMES
SQLITE4_PRIVATE void sqlite4FileSuffix3(const char*, char*);
#else
# define sqlite4FileSuffix3(X,Y)
#endif
SQLITE4_PRIVATE u8 sqlite4GetBoolean(const char *z);

SQLITE4_PRIVATE const void *sqlite4ValueText(sqlite4_value*, u8);
SQLITE4_PRIVATE int sqlite4ValueBytes(sqlite4_value*, u8);
SQLITE4_PRIVATE void sqlite4ValueSetStr(sqlite4_value*, int, const void *,u8, 
                        void(*)(void*,void*),void*);
SQLITE4_PRIVATE void sqlite4ValueFree(sqlite4_value*);
SQLITE4_PRIVATE sqlite4_value *sqlite4ValueNew(sqlite4 *);
SQLITE4_PRIVATE char *sqlite4Utf16to8(sqlite4 *, const void*, int, u8);
#ifdef SQLITE4_ENABLE_STAT3
SQLITE4_PRIVATE char *sqlite4Utf8to16(sqlite4 *, u8, char *, int, int *);
#endif
SQLITE4_PRIVATE int sqlite4ValueFromExpr(sqlite4 *, Expr *, u8, u8, sqlite4_value **);
SQLITE4_PRIVATE void sqlite4ValueApplyAffinity(sqlite4_value *, u8, u8);
#ifndef SQLITE4_AMALGAMATION
SQLITE4_PRIVATE const unsigned char sqlite4OpcodeProperty[];
SQLITE4_PRIVATE const unsigned char sqlite4UpperToLower[];
SQLITE4_PRIVATE const unsigned char sqlite4CtypeMap[];
SQLITE4_PRIVATE const Token sqlite4IntTokens[];
SQLITE4_PRIVATE struct sqlite4_env sqlite4DefaultEnv;
SQLITE4_PRIVATE struct KVFactory sqlite4BuiltinFactory;
#endif
SQLITE4_PRIVATE void sqlite4Reindex(Parse*, Token*, Token*);
SQLITE4_PRIVATE void sqlite4AlterFunctions(sqlite4_env*);
SQLITE4_PRIVATE void sqlite4AlterRenameTable(Parse*, SrcList*, Token*);
SQLITE4_PRIVATE int sqlite4GetToken(const unsigned char *, int *);
SQLITE4_PRIVATE void sqlite4NestedParse(Parse*, const char*, ...);
SQLITE4_PRIVATE void sqlite4ExpirePreparedStatements(sqlite4*);
SQLITE4_PRIVATE int sqlite4CodeSubselect(Parse *, Expr *, int);
SQLITE4_PRIVATE void sqlite4SelectPrep(Parse*, Select*, NameContext*);
SQLITE4_PRIVATE int sqlite4ResolveExprNames(NameContext*, Expr*);
SQLITE4_PRIVATE void sqlite4ResolveSelectNames(Parse*, Select*, NameContext*);
SQLITE4_PRIVATE int sqlite4ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
SQLITE4_PRIVATE void sqlite4ColumnDefault(Vdbe *, Table *, int, int);
SQLITE4_PRIVATE void sqlite4AlterFinishAddColumn(Parse *, Token *);
SQLITE4_PRIVATE void sqlite4AlterBeginAddColumn(Parse *, SrcList *);
SQLITE4_PRIVATE CollSeq *sqlite4GetCollSeq(sqlite4*, CollSeq *, const char*);
SQLITE4_PRIVATE char sqlite4AffinityType(const char*);
SQLITE4_PRIVATE void sqlite4Analyze(Parse*, Token*, Token*);
SQLITE4_PRIVATE int sqlite4FindDb(sqlite4*, Token*);
SQLITE4_PRIVATE int sqlite4FindDbName(sqlite4 *, const char *);
SQLITE4_PRIVATE int sqlite4AnalysisLoad(sqlite4*,int iDB);
SQLITE4_PRIVATE void sqlite4DeleteIndexSamples(sqlite4*,Index*);
SQLITE4_PRIVATE void sqlite4DefaultRowEst(Index*);
SQLITE4_PRIVATE void sqlite4RegisterLikeFunctions(sqlite4*, int);
SQLITE4_PRIVATE int sqlite4IsLikeFunction(sqlite4*,Expr*,int*,char*);
SQLITE4_PRIVATE void sqlite4SchemaClear(sqlite4_env*,Schema*);
SQLITE4_PRIVATE Schema *sqlite4SchemaGet(sqlite4*);
SQLITE4_PRIVATE int sqlite4SchemaToIndex(sqlite4 *db, Schema *);
SQLITE4_PRIVATE KeyInfo *sqlite4IndexKeyinfo(Parse *, Index *);
SQLITE4_PRIVATE int sqlite4CreateFunc(sqlite4 *, const char *, int, void *, 
  void (*)(sqlite4_context*,int,sqlite4_value **),
  void (*)(sqlite4_context*,int,sqlite4_value **), void (*)(sqlite4_context*),
  void (*)(void *)
);
SQLITE4_PRIVATE int sqlite4ApiExit(sqlite4 *db, int);
SQLITE4_PRIVATE int sqlite4OpenTempDatabase(Parse *);

SQLITE4_PRIVATE void sqlite4StrAccumInit(StrAccum*, char*, int, int);
SQLITE4_PRIVATE void sqlite4StrAccumAppend(StrAccum*,const char*,int);
SQLITE4_PRIVATE void sqlite4AppendSpace(StrAccum*,int);
SQLITE4_PRIVATE char *sqlite4StrAccumFinish(StrAccum*);
SQLITE4_PRIVATE void sqlite4StrAccumReset(StrAccum*);
SQLITE4_PRIVATE void sqlite4SelectDestInit(SelectDest*,int,int);
SQLITE4_PRIVATE Expr *sqlite4CreateColumnExpr(sqlite4 *, SrcList *, int, int);

SQLITE4_PRIVATE void sqlite4OpenPrimaryKey(Parse*, int iCur, int iDb, Table*, int);
SQLITE4_PRIVATE void sqlite4OpenIndex(Parse*, int iCur, int iDb, Index*, int);
SQLITE4_PRIVATE int sqlite4OpenAllIndexes(Parse *, Table *, int, int);
SQLITE4_PRIVATE void sqlite4CloseAllIndexes(Parse *, Table *, int);
SQLITE4_PRIVATE Index *sqlite4FindPrimaryKey(Table *, int *);

/*
** The interface to the LEMON-generated parser
*/
SQLITE4_PRIVATE void *sqlite4ParserAlloc(void*(*)(void*,size_t), void*);
SQLITE4_PRIVATE void sqlite4ParserFree(void*, void(*)(void*,void*));
SQLITE4_PRIVATE void sqlite4Parser(void*, int, Token, Parse*);
#ifdef YYTRACKMAXSTACKDEPTH
SQLITE4_PRIVATE   int sqlite4ParserStackPeak(void*);
#endif

#ifdef SQLITE4_TEST
SQLITE4_PRIVATE   int sqlite4Utf8To8(char*);
#endif

#ifdef SQLITE4_OMIT_VIRTUALTABLE
#  define sqlite4VtabClear(Y)
#  define sqlite4VtabSync(X,Y) SQLITE4_OK
#  define sqlite4VtabRollback(X)
#  define sqlite4VtabCommit(X)
#  define sqlite4VtabInSync(db) 0
#  define sqlite4VtabLock(X) 
#  define sqlite4VtabUnlock(X)
#  define sqlite4VtabUnlockList(X)
#  define sqlite4VtabSavepoint(X, Y, Z) SQLITE4_OK
#  define sqlite4GetVTable(X,Y)  ((VTable*)0)
#else
SQLITE4_PRIVATE    void sqlite4VtabClear(sqlite4 *db, Table*);
SQLITE4_PRIVATE    int sqlite4VtabSync(sqlite4 *db, char **);
SQLITE4_PRIVATE    int sqlite4VtabRollback(sqlite4 *db);
SQLITE4_PRIVATE    int sqlite4VtabCommit(sqlite4 *db);
SQLITE4_PRIVATE    void sqlite4VtabLock(VTable *);
SQLITE4_PRIVATE    void sqlite4VtabUnlock(VTable *);
SQLITE4_PRIVATE    void sqlite4VtabUnlockList(sqlite4*);
SQLITE4_PRIVATE    int sqlite4VtabSavepoint(sqlite4 *, int, int);
SQLITE4_PRIVATE    VTable *sqlite4GetVTable(sqlite4*, Table*);
#  define sqlite4VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
#endif
SQLITE4_PRIVATE void sqlite4VtabMakeWritable(Parse*,Table*);
SQLITE4_PRIVATE void sqlite4VtabBeginParse(Parse*, Token*, Token*, Token*);
SQLITE4_PRIVATE void sqlite4VtabFinishParse(Parse*, Token*);
SQLITE4_PRIVATE void sqlite4VtabArgInit(Parse*);
SQLITE4_PRIVATE void sqlite4VtabArgExtend(Parse*, Token*);
SQLITE4_PRIVATE int sqlite4VtabCallCreate(sqlite4*, int, const char *, char **);
SQLITE4_PRIVATE int sqlite4VtabCallConnect(Parse*, Table*);
SQLITE4_PRIVATE int sqlite4VtabCallDestroy(sqlite4*, int, const char *);
SQLITE4_PRIVATE int sqlite4VtabBegin(sqlite4 *, VTable *);
SQLITE4_PRIVATE FuncDef *sqlite4VtabOverloadFunction(sqlite4 *,FuncDef*, int nArg, Expr*);
SQLITE4_PRIVATE void sqlite4InvalidFunction(sqlite4_context*,int,sqlite4_value**);
SQLITE4_PRIVATE int sqlite4VdbeParameterIndex(Vdbe*, const char*, int);
SQLITE4_PRIVATE int sqlite4TransferBindings(sqlite4_stmt *, sqlite4_stmt *);
SQLITE4_PRIVATE int sqlite4Reprepare(Vdbe*);
SQLITE4_PRIVATE void sqlite4ExprListCheckLength(Parse*, ExprList*, const char*);
SQLITE4_PRIVATE CollSeq *sqlite4BinaryCompareCollSeq(Parse *, Expr *, Expr *);

/* Declarations for functions in fkey.c. All of these are replaced by
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
** key functionality is available. If OMIT_TRIGGER is defined but
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
** this case foreign keys are parsed, but no other functionality is 
** provided (enforcement of FK constraints requires the triggers sub-system).
*/
#if !defined(SQLITE4_OMIT_FOREIGN_KEY) && !defined(SQLITE4_OMIT_TRIGGER)
SQLITE4_PRIVATE   void sqlite4FkCheck(Parse*, Table*, int, int);
SQLITE4_PRIVATE   void sqlite4FkDropTable(Parse*, SrcList *, Table*);
SQLITE4_PRIVATE   void sqlite4FkActions(Parse*, Table*, ExprList*, int);
SQLITE4_PRIVATE   int sqlite4FkRequired(Parse*, Table*, int*);
SQLITE4_PRIVATE   u32 sqlite4FkOldmask(Parse*, Table*);
SQLITE4_PRIVATE   FKey *sqlite4FkReferences(Table *);
#else
  #define sqlite4FkActions(a,b,c,d)
  #define sqlite4FkCheck(a,b,c,d)
  #define sqlite4FkDropTable(a,b,c)
  #define sqlite4FkOldmask(a,b)      0
  #define sqlite4FkRequired(a,b,c) 0
#endif
#ifndef SQLITE4_OMIT_FOREIGN_KEY
SQLITE4_PRIVATE   void sqlite4FkDelete(sqlite4 *, Table*);
#else
  #define sqlite4FkDelete(a,b)
#endif


/*
** Available fault injectors.  Should be numbered beginning with 0.
*/
#define SQLITE4_FAULTINJECTOR_MALLOC     0
#define SQLITE4_FAULTINJECTOR_COUNT      1

/*
** The interface to the code in fault.c used for identifying "benign"
** malloc failures. This is only present if SQLITE4_OMIT_BUILTIN_TEST
** is not defined.
*/
#ifndef SQLITE4_OMIT_BUILTIN_TEST
SQLITE4_PRIVATE   void sqlite4BeginBenignMalloc(sqlite4_env*);
SQLITE4_PRIVATE   void sqlite4EndBenignMalloc(sqlite4_env*);
#else
  #define sqlite4BeginBenignMalloc(X)
  #define sqlite4EndBenignMalloc(X)
#endif

#define IN_INDEX_ROWID           1
#define IN_INDEX_EPH             2
#define IN_INDEX_INDEX_ASC       3
#define IN_INDEX_INDEX_DESC      4
SQLITE4_PRIVATE int sqlite4FindInIndex(Parse *, Expr *, int*, int*);
SQLITE4_PRIVATE Index *sqlite4FindExistingInIndex(Parse *, Expr *, int);


#if SQLITE4_MAX_EXPR_DEPTH>0
SQLITE4_PRIVATE   void sqlite4ExprSetHeight(Parse *pParse, Expr *p);
SQLITE4_PRIVATE   int sqlite4SelectExprHeight(Select *);
SQLITE4_PRIVATE   int sqlite4ExprCheckHeight(Parse*, int);
#else
  #define sqlite4ExprSetHeight(x,y)
  #define sqlite4SelectExprHeight(x) 0
  #define sqlite4ExprCheckHeight(x,y)
#endif

SQLITE4_PRIVATE u32 sqlite4Get4byte(const u8*);
SQLITE4_PRIVATE void sqlite4Put4byte(u8*, u32);

#ifdef SQLITE4_ENABLE_UNLOCK_NOTIFY
SQLITE4_PRIVATE   void sqlite4ConnectionBlocked(sqlite4 *, sqlite4 *);
SQLITE4_PRIVATE   void sqlite4ConnectionUnlocked(sqlite4 *db);
SQLITE4_PRIVATE   void sqlite4ConnectionClosed(sqlite4 *db);
#else
  #define sqlite4ConnectionBlocked(x,y)
  #define sqlite4ConnectionUnlocked(x)
  #define sqlite4ConnectionClosed(x)
#endif

#ifdef SQLITE4_DEBUG
SQLITE4_PRIVATE   void sqlite4ParserTrace(FILE*, char *);
#endif

/*
** If the SQLITE4_ENABLE IOTRACE exists then the global variable
** sqlite4IoTrace is a pointer to a printf-like routine used to
** print I/O tracing messages. 
*/
#ifdef SQLITE4_ENABLE_IOTRACE
# define IOTRACE(A)  if( sqlite4IoTrace ){ sqlite4IoTrace A; }
SQLITE4_PRIVATE   void sqlite4VdbeIOTraceSql(Vdbe*);
SQLITE4_PRIVATE void (*sqlite4IoTrace)(const char*,...);
#else
# define IOTRACE(A)
# define sqlite4VdbeIOTraceSql(X)
#endif

/*
** These routines are available for the mem2.c debugging memory allocator
** only.  They are used to verify that different "types" of memory
** allocations are properly tracked by the system.
**
** sqlite4MemdebugSetType() sets the "type" of an allocation to one of
** the MEMTYPE_* macros defined below.  The type must be a bitmask with
** a single bit set.
**
** sqlite4MemdebugHasType() returns true if any of the bits in its second
** argument match the type set by the previous sqlite4MemdebugSetType().
** sqlite4MemdebugHasType() is intended for use inside assert() statements.
**
** sqlite4MemdebugNoType() returns true if none of the bits in its second
** argument match the type set by the previous sqlite4MemdebugSetType().
**
** Perhaps the most important point is the difference between MEMTYPE_HEAP
** and MEMTYPE_LOOKASIDE.  If an allocation is MEMTYPE_LOOKASIDE, that means
** it might have been allocated by lookaside, except the allocation was
** too large or lookaside was already full.  It is important to verify
** that allocations that might have been satisfied by lookaside are not
** passed back to non-lookaside free() routines.  Asserts such as the
** example above are placed on the non-lookaside free() routines to verify
** this constraint. 
**
** All of this is no-op for a production build.  It only comes into
** play when the SQLITE4_MEMDEBUG compile-time option is used.
*/
#ifdef SQLITE4_MEMDEBUG
SQLITE4_PRIVATE   void sqlite4MemdebugSetType(void*,u8);
SQLITE4_PRIVATE   int sqlite4MemdebugHasType(const void*,u8);
SQLITE4_PRIVATE   int sqlite4MemdebugNoType(const void*,u8);
#else
# define sqlite4MemdebugSetType(X,Y)  /* no-op */
# define sqlite4MemdebugHasType(X,Y)  1
# define sqlite4MemdebugNoType(X,Y)   1
#endif
#define MEMTYPE_HEAP       0x01  /* General heap allocations */
#define MEMTYPE_LOOKASIDE  0x02  /* Might have been lookaside memory */
#define MEMTYPE_SCRATCH    0x04  /* Scratch allocations */
#define MEMTYPE_DB         0x10  /* Uses sqlite4DbMalloc, not sqlite_malloc */

SQLITE4_PRIVATE int sqlite4InitFts5(sqlite4 *db);
SQLITE4_PRIVATE int sqlite4InitFts5Func(sqlite4 *db);
SQLITE4_PRIVATE void sqlite4ShutdownFts5(sqlite4 *db);
SQLITE4_PRIVATE void sqlite4CreateUsingIndex(Parse*, CreateIndex*, ExprList*, Token*, Token*);

SQLITE4_PRIVATE int sqlite4Fts5IndexSz(void);
SQLITE4_PRIVATE void sqlite4Fts5IndexInit(Parse *, Index *, ExprList *);
SQLITE4_PRIVATE void sqlite4Fts5IndexFree(sqlite4 *, Index *);

SQLITE4_PRIVATE int sqlite4Fts5Update(sqlite4 *, Fts5Info *, int, Mem *, Mem *, int, char **);
SQLITE4_PRIVATE void sqlite4Fts5FreeInfo(sqlite4 *db, Fts5Info *);
SQLITE4_PRIVATE void sqlite4Fts5CodeUpdate(Parse *, Index *pIdx, int, int, int, int);
SQLITE4_PRIVATE void sqlite4Fts5CodeCksum(Parse *, Index *, int, int, int);
SQLITE4_PRIVATE void sqlite4Fts5CodeQuery(Parse *, Index *, int, int, int);

SQLITE4_PRIVATE int sqlite4Fts5Pk(Fts5Cursor *, int, KVByteArray **, KVSize *);
SQLITE4_PRIVATE int sqlite4Fts5Next(Fts5Cursor *pCsr);

SQLITE4_PRIVATE int sqlite4Fts5EntryCksum(sqlite4 *, Fts5Info *, Mem *, Mem *, i64 *);
SQLITE4_PRIVATE int sqlite4Fts5RowCksum(sqlite4 *, Fts5Info *, Mem *, Mem *, i64 *);
SQLITE4_PRIVATE int sqlite4Fts5Open(sqlite4*, Fts5Info*, const char*, int, Fts5Cursor**,char**);
SQLITE4_PRIVATE int sqlite4Fts5Valid(Fts5Cursor *);
SQLITE4_PRIVATE void sqlite4Fts5Close(Fts5Cursor *);

#endif /* _SQLITEINT_H_ */

/************** End of sqliteInt.h *******************************************/
/************** Begin file global.c ******************************************/
/*
** 2008 June 13
**
** 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 definitions of global variables and contants.
*/

/* An array to map all upper-case characters into their corresponding
** lower-case character. 
**
** SQLite only considers US-ASCII (or EBCDIC) characters.  We do not
** handle case conversions for the UTF character set since the tables
** involved are nearly as big or bigger than SQLite itself.
*/
SQLITE4_PRIVATE const unsigned char sqlite4UpperToLower[] = {
#ifdef SQLITE4_ASCII
      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17,
     18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
     36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
     54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
    104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
    122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
    108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
    126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
    144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
    162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
    180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
    198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
    216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
    234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
    252,253,254,255
#endif
#ifdef SQLITE4_EBCDIC
      0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, /* 0x */
     16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
     32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
     48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
     64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
     80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
     96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */
    112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */
    128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
    144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */
    160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
    176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
    192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
    208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
    224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */
    239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */
#endif
};

/*
** The following 256 byte lookup table is used to support SQLites built-in
** equivalents to the following standard library functions:
**
**   isspace()                        0x01
**   isalpha()                        0x02
**   isdigit()                        0x04
**   isalnum()                        0x06
**   isxdigit()                       0x08
**   toupper()                        0x20
**   SQLite identifier character      0x40
**
** Bit 0x20 is set if the mapped character requires translation to upper
** case. i.e. if the character is a lower-case ASCII character.
** If x is a lower-case ASCII character, then its upper-case equivalent
** is (x - 0x20). Therefore toupper() can be implemented as:
**
**   (x & ~(map[x]&0x20))
**
** Standard function tolower() is implemented using the sqlite4UpperToLower[]
** array. tolower() is used more often than toupper() by SQLite.
**
** Bit 0x40 is set if the character non-alphanumeric and can be used in an 
** SQLite identifier.  Identifiers are alphanumerics, "_", "$", and any
** non-ASCII UTF character. Hence the test for whether or not a character is
** part of an identifier is 0x46.
**
** SQLite's versions are identical to the standard versions assuming a
** locale of "C". They are implemented as macros in sqliteInt.h.
*/
#ifdef SQLITE4_ASCII
SQLITE4_PRIVATE const unsigned char sqlite4CtypeMap[256] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 00..07    ........ */
  0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,  /* 08..0f    ........ */
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 10..17    ........ */
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 18..1f    ........ */
  0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,  /* 20..27     !"#$%&' */
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 28..2f    ()*+,-./ */
  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,  /* 30..37    01234567 */
  0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 38..3f    89:;<=>? */

  0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02,  /* 40..47    @ABCDEFG */
  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  /* 48..4f    HIJKLMNO */
  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  /* 50..57    PQRSTUVW */
  0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40,  /* 58..5f    XYZ[\]^_ */
  0x00, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22,  /* 60..67    `abcdefg */
  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,  /* 68..6f    hijklmno */
  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,  /* 70..77    pqrstuvw */
  0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,  /* 78..7f    xyz{|}~. */

  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* 80..87    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* 88..8f    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* 90..97    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* 98..9f    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* a0..a7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* a8..af    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* b0..b7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* b8..bf    ........ */

  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* c0..c7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* c8..cf    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* d0..d7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* d8..df    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e0..e7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* e8..ef    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  /* f0..f7    ........ */
  0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40   /* f8..ff    ........ */
};
#endif


/*
** Constant tokens for values 0 and 1.
*/
SQLITE4_PRIVATE const Token sqlite4IntTokens[] = {
   { "0", 1 },
   { "1", 1 }
};

/*
** Properties of opcodes.  The OPFLG_INITIALIZER macro is
** created by mkopcodeh.awk during compilation.  Data is obtained
** from the comments following the "case OP_xxxx:" statements in
** the vdbe.c file.  
*/
SQLITE4_PRIVATE const unsigned char sqlite4OpcodeProperty[] = OPFLG_INITIALIZER;

/************** End of global.c **********************************************/
/************** Begin file env.c *********************************************/
/*
** 2013 January 7
**
** 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 used to help implement the sqlite4_env object.
*/


/*
** Default factory objects
*/
static KVFactory memFactory = {
   0,
   "temp",
   sqlite4KVStoreOpenMem,
   1
};
static KVFactory btFactory = {
   &memFactory,
   "bt",
   sqlite4OpenBtree,
   1
};
SQLITE4_PRIVATE KVFactory sqlite4BuiltinFactory = {
   &btFactory,
   "main",
   sqlite4KVStoreOpenLsm,
   1
};

/*
** The following singleton contains the global configuration for
** the SQLite library.
*/
SQLITE4_PRIVATE struct sqlite4_env sqlite4DefaultEnv = {
   sizeof(sqlite4_env),       /* nByte */
   1,                         /* iVersion */
   SQLITE4_DEFAULT_MEMSTATUS, /* bMemstat */
   1,                         /* bCoreMutex */
   SQLITE4_THREADSAFE==1,     /* bFullMutex */
   0x7ffffffe,                /* mxStrlen */
   0,                         /* szLookaside */
   0,                         /* nLookaside */
   &sqlite4MMSystem,          /* pMM */
   {0,0,0,0,0,0,0,0,0,0},     /* mutex */
   (void*)0,                  /* pHeap */
   0,                         /* nHeap */
   0, 0,                      /* mnHeap, mxHeap */
   0,                         /* mxParserStack */
   &sqlite4BuiltinFactory,    /* pFactory */
   sqlite4OsRandomness,       /* xRandomness */
   sqlite4OsCurrentTime,      /* xCurrentTime */
   /* All the rest should always be initialized to zero */
   0,                         /* isInit */
   0,                         /* pFactoryMutex */
   0,                         /* pPrngMutex */
   0, 0,                      /* prngX, prngY */
   0,                         /* xLog */
   0,                         /* pLogArg */
   0,                         /* bLocaltimeFault */
   0,                         /* pMemMutex */
   {0,0,0,0},                 /* nowValue[] */
   {0,0,0,0},                 /* mxValue[] */
   {0,}                       /* hashGlobalFunc */
};

/*
** Return the default environment
*/
SQLITE4_API sqlite4_env *sqlite4_env_default(void){ return &sqlite4DefaultEnv; }

/*
** Initialize SQLite.  
**
** This routine must be called to initialize the run-time environment
** As long as you do not compile with SQLITE4_OMIT_AUTOINIT
** this routine will be called automatically by key routines such as
** sqlite4_open().  
**
** This routine is a no-op except on its very first call for a given
** sqlite4_env object, or for the first call after a call to sqlite4_shutdown.
**
** This routine is not threadsafe.  It should be called from a single
** thread to initialized the library in a multi-threaded system.  Other
** threads should avoid using the sqlite4_env object until after it has
** completely initialized.
*/
SQLITE4_API int sqlite4_initialize(sqlite4_env *pEnv){
  int rc;                                      /* Result code */

  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;

  /* If SQLite is already completely initialized, then this call
  ** to sqlite4_initialize() should be a no-op.  But the initialization
  ** must be complete.  So isInit must not be set until the very end
  ** of this routine.
  */
  if( pEnv->isInit ) return SQLITE4_OK;

  /* Initialize the mutex subsystem
  */
  rc = sqlite4MutexInit(pEnv);
  if( rc ){
    sqlite4MallocEnd(pEnv);
    return rc;
  }

  /* Initialize the memory allocation subsystem
  */
  rc = sqlite4MallocInit(pEnv);
  if( rc ) return rc;

  /* Create required mutexes
  */
  if( pEnv->bCoreMutex ){
    pEnv->pMemMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST);
    pEnv->pPrngMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST);
    pEnv->pFactoryMutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST);
    if( pEnv->pMemMutex==0
     || pEnv->pPrngMutex==0
     || pEnv->pFactoryMutex==0
    ){
      rc = SQLITE4_NOMEM;
    }
  }else{
    pEnv->pMemMutex = 0;
    pEnv->pPrngMutex = 0;
  }
  pEnv->isInit = 1;

  sqlite4OsInit(pEnv);

  /* Register global functions */
  if( rc==SQLITE4_OK ){
    sqlite4RegisterGlobalFunctions(pEnv);
  }

  /* The following is just a sanity check to make sure SQLite has
  ** been compiled correctly.  It is important to run this code, but
  ** we don't want to run it too often and soak up CPU cycles for no
  ** reason.  So we run it once during initialization.
  */
#ifndef NDEBUG
#ifndef SQLITE4_OMIT_FLOATING_POINT
  /* This section of code's only "output" is via assert() statements. */
  if ( rc==SQLITE4_OK ){
    u64 x = (((u64)1)<<63)-1;
    double y;
    assert(sizeof(x)==8);
    assert(sizeof(x)==sizeof(y));
    memcpy(&y, &x, 8);
    assert( sqlite4IsNaN(y) );
  }
#endif
#endif

  return rc;
}

/*
** Undo the effects of sqlite4_initialize().  Must not be called while
** there are outstanding database connections or memory allocations or
** while any part of SQLite is otherwise in use in any thread.  This
** routine is not threadsafe.  But it is safe to invoke this routine
** on when SQLite is already shut down.  If SQLite is already shut down
** when this routine is invoked, then this routine is a harmless no-op.
*/
SQLITE4_API int sqlite4_shutdown(sqlite4_env *pEnv){
  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
  if( pEnv->isInit ){
    KVFactory *pMkr;
    sqlite4_mutex_free(pEnv->pFactoryMutex);
    sqlite4_mutex_free(pEnv->pPrngMutex);
    sqlite4_mutex_free(pEnv->pMemMutex);
    pEnv->pMemMutex = 0;
    while( (pMkr = pEnv->pFactory)!=0 && pMkr->isPerm==0 ){
      KVFactory *pNext = pMkr->pNext;
      sqlite4_free(pEnv, pMkr);
      pEnv->pFactory = pNext;
    }
    sqlite4MutexEnd(pEnv);
    sqlite4MallocEnd(pEnv);
    pEnv->isInit = 0;
  }
  return SQLITE4_OK;
}

/*
** Return the size of an sqlite4_env object
*/
SQLITE4_API int sqlite4_env_size(void){ return sizeof(sqlite4_env); }

/*
** This API allows applications to modify the configuration described by
** an sqlite4_env object.
*/
SQLITE4_API int sqlite4_env_config(sqlite4_env *pEnv, int op, ...){
  va_list ap;
  int rc = SQLITE4_OK;

  if( pEnv==0 ) pEnv = sqlite4_env_default();

  va_start(ap, op);
  switch( op ){
    /*
    ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_INIT, template);
    **
    ** Turn bulk memory into a new sqlite4_env object.  The template is
    ** a prior sqlite4_env that is used as a template in initializing the
    ** new sqlite4_env object.  The size of the bulk memory must be at
    ** least as many bytes as returned from sqlite4_env_size().
    */
    case SQLITE4_ENVCONFIG_INIT: {
      /* Disable all mutexing */
      sqlite4_env *pTemplate = va_arg(ap, sqlite4_env*);
      int n = pTemplate->nByte;
      if( n>sizeof(sqlite4_env) ) n = sizeof(sqlite4_env);
      memcpy(pEnv, pTemplate, n);
      pEnv->pFactory = &sqlite4BuiltinFactory;
      pEnv->isInit = 0;
      break;
    }

    /* Mutex configuration options are only available in a threadsafe
    ** compile. 
    */
#if defined(SQLITE4_THREADSAFE) && SQLITE4_THREADSAFE>0
    /*
    ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_SINGLETHREAD);
    **
    ** Configure this environment for a single-threaded application.
    */
    case SQLITE4_ENVCONFIG_SINGLETHREAD: {
      /* Disable all mutexing */
      if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; }
      pEnv->bCoreMutex = 0;
      pEnv->bFullMutex = 0;
      break;
    }

    /*
    ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_MULTITHREAD);
    **
    ** Configure this environment for a multi-threaded application where
    ** the same database connection is never used by more than a single
    ** thread at a time.
    */
    case SQLITE4_ENVCONFIG_MULTITHREAD: {
      /* Disable mutexing of database connections */
      /* Enable mutexing of core data structures */
      if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; }
      pEnv->bCoreMutex = 1;
      pEnv->bFullMutex = 0;
      break;
    }

    /*
    ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_SERIALIZED);
    **
    ** Configure this environment for an unrestricted multi-threaded
    ** application where any thread can do whatever it wants with any
    ** database connection at any time.
    */
    case SQLITE4_ENVCONFIG_SERIALIZED: {
      /* Enable all mutexing */
      if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; }
      pEnv->bCoreMutex = 1;
      pEnv->bFullMutex = 1;
      break;
    }

    /*
    ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_MUTEXT, sqlite4_mutex_methods*)
    **
    ** Configure this environment to use the mutex routines specified by the
    ** argument.
    */
    case SQLITE4_ENVCONFIG_MUTEX: {
      /* Specify an alternative mutex implementation */
      if( pEnv->isInit ){ rc = SQLITE4_MISUSE; break; }
      pEnv->mutex = *va_arg(ap, sqlite4_mutex_methods*);
      break;
    }

    /*
    ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_GETMUTEX, sqlite4_mutex_methods*)
    **
    ** Copy the mutex routines in use by this environment into the structure
    ** given in the argument.
    */
    case SQLITE4_ENVCONFIG_GETMUTEX: {
      /* Retrieve the current mutex implementation */
      *va_arg(ap, sqlite4_mutex_methods*) = pEnv->mutex;
      break;
    }
#endif


    /*
    ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_SETMM, sqlite4_mm*)
    **
    ** Set the memory allocator to be used by this environment.
    */
    case SQLITE4_ENVCONFIG_SETMM: {
      if( pEnv->isInit ) return SQLITE4_MISUSE;
      pEnv->pMM = va_arg(ap, sqlite4_mm*);
      break;
    }

    /*
    ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_GETMM, sqlite4_mm**)
    **
    ** Copy the memory allocation routines in use by this environment
    ** into the structure given in the argument.
    */
    case SQLITE4_ENVCONFIG_GETMM: {
      *va_arg(ap, sqlite4_mm**) = pEnv->pMM;
      break;
    }

    /* sqlite4_env_config(p, SQLITE4_ENVCONFIG_MEMSTAT, int onoff);
    **
    ** Enable or disable collection of memory usage statistics according to
    ** the onoff parameter.  
    */
    case SQLITE4_ENVCONFIG_MEMSTATUS: {
      /* Enable or disable the malloc status collection */
      pEnv->bMemstat = va_arg(ap, int);
      break;
    }

    /*
    ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_LOOKASIDE, size, count);
    **
    ** Set the default lookaside memory settings for all subsequent
    ** database connections constructed in this environment.  The size
    ** parameter is the size of each lookaside memory buffer and the
    ** count parameter is the number of lookaside buffers.  Set both
    ** to zero to disable lookaside memory.
    */
    case SQLITE4_ENVCONFIG_LOOKASIDE: {
      pEnv->szLookaside = va_arg(ap, int);
      pEnv->nLookaside = va_arg(ap, int);
      break;
    }
    
    /*
    ** sqlite4_env_config(p, SQLITE4_ENVCONFIG_LOG, xOutput, pArg);
    **
    ** Set the log function that is called in response to sqlite4_log()
    ** calls.
    */
    case SQLITE4_ENVCONFIG_LOG: {
      /* MSVC is picky about pulling func ptrs from va lists.
      ** http://support.microsoft.com/kb/47961
      ** pEnv->xLog = va_arg(ap, void(*)(void*,int,const char*));
      */
      typedef void(*LOGFUNC_t)(void*,int,const char*);
      pEnv->xLog = va_arg(ap, LOGFUNC_t);
      pEnv->pLogArg = va_arg(ap, void*);
      break;
    }

    /*
    ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_PUSH, zName,xFactory);
    **
    ** Push a new KVStore factory onto the factory stack.  The new factory
    ** takes priority over prior factories.
    */
    case SQLITE4_ENVCONFIG_KVSTORE_PUSH: {
      const char *zName = va_arg(ap, const char*);
      int nName = sqlite4Strlen30(zName);
      KVFactory *pMkr = sqlite4_malloc(pEnv, sizeof(*pMkr)+nName+1);
      char *z;
      if( pMkr==0 ) return SQLITE4_NOMEM;
      z = (char*)&pMkr[1];
      memcpy(z, zName, nName+1);
      memset(pMkr, 0, sizeof(*pMkr));
      pMkr->zName = z;
      pMkr->xFactory = va_arg(ap, sqlite4_kvfactory);
      sqlite4_mutex_enter(pEnv->pFactoryMutex);
      pMkr->pNext = pEnv->pFactory;
      pEnv->pFactory = pMkr;
      sqlite4_mutex_leave(pEnv->pFactoryMutex);
      break;
    }

    /*
    ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_POP, zName, &pxFact);
    **
    ** Remove a KVStore factory from the stack.
    */
    /*
    ** sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_KVSTORE_GET, zName, &pxFact);
    **
    ** Get the current factory pointer with the given name but leave the
    ** factory on the stack.
    */
    case SQLITE4_ENVCONFIG_KVSTORE_POP:
    case SQLITE4_ENVCONFIG_KVSTORE_GET: {
      typedef int (**PxFact)(sqlite4_env*,KVStore**,const char*,unsigned);
      const char *zName = va_arg(ap, const char*);
      KVFactory *pMkr, **ppPrev;
      PxFact pxFact;

      pxFact = va_arg(ap,PxFact);
      *pxFact = 0;
      sqlite4_mutex_enter(pEnv->pFactoryMutex);
      ppPrev = &pEnv->pFactory;
      pMkr = *ppPrev;
      while( pMkr && strcmp(zName, pMkr->zName)!=0 ){
        ppPrev = &pMkr->pNext;
        pMkr = *ppPrev;
      }
      if( pMkr ){
        *pxFact = pMkr->xFactory;
        if( op==SQLITE4_ENVCONFIG_KVSTORE_POP && pMkr->isPerm==0 ){
          *ppPrev = pMkr->pNext;
          sqlite4_free(pEnv, pMkr);
        }
      }
      sqlite4_mutex_leave(pEnv->pFactoryMutex);
      break;
    }


    default: {
      rc = SQLITE4_ERROR;
      break;
    }
  }
  va_end(ap);
  return rc;
}

/************** End of env.c *************************************************/
/************** Begin file ctime.c *******************************************/
/*
** 2010 February 23
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements routines used to report what compile-time options
** SQLite was built with.
*/

#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS


/*
** An array of names of all compile-time options.  This array should 
** be sorted A-Z.
**
** This array looks large, but in a typical installation actually uses
** only a handful of compile-time options, so most times this array is usually
** rather short and uses little memory space.
*/
static const char * const azCompileOpt[] = {

/* These macros are provided to "stringify" the value of the define
** for those options in which the value is meaningful. */
#define CTIMEOPT_VAL_(opt) #opt
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)

#ifdef SQLITE4_32BIT_ROWID
  "32BIT_ROWID",
#endif
#ifdef SQLITE4_4_BYTE_ALIGNED_MALLOC
  "4_BYTE_ALIGNED_MALLOC",
#endif
#ifdef SQLITE4_CASE_SENSITIVE_LIKE
  "CASE_SENSITIVE_LIKE",
#endif
#ifdef SQLITE4_CHECK_PAGES
  "CHECK_PAGES",
#endif
#ifdef SQLITE4_COVERAGE_TEST
  "COVERAGE_TEST",
#endif
#ifdef SQLITE4_DEBUG
  "DEBUG",
#endif
#ifdef SQLITE4_DEFAULT_LOCKING_MODE
  "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE4_DEFAULT_LOCKING_MODE),
#endif
#ifdef SQLITE4_DISABLE_DIRSYNC
  "DISABLE_DIRSYNC",
#endif
#ifdef SQLITE4_DISABLE_LFS
  "DISABLE_LFS",
#endif
#ifdef SQLITE4_ENABLE_ATOMIC_WRITE
  "ENABLE_ATOMIC_WRITE",
#endif
#ifdef SQLITE4_ENABLE_CEROD
  "ENABLE_CEROD",
#endif
#ifdef SQLITE4_ENABLE_COLUMN_METADATA
  "ENABLE_COLUMN_METADATA",
#endif
#ifdef SQLITE4_ENABLE_EXPENSIVE_ASSERT
  "ENABLE_EXPENSIVE_ASSERT",
#endif
#ifdef SQLITE4_ENABLE_FTS1
  "ENABLE_FTS1",
#endif
#ifdef SQLITE4_ENABLE_FTS2
  "ENABLE_FTS2",
#endif
#ifdef SQLITE4_ENABLE_FTS3
  "ENABLE_FTS3",
#endif
#ifdef SQLITE4_ENABLE_FTS3_PARENTHESIS
  "ENABLE_FTS3_PARENTHESIS",
#endif
#ifdef SQLITE4_ENABLE_FTS4
  "ENABLE_FTS4",
#endif
#ifdef SQLITE4_ENABLE_ICU
  "ENABLE_ICU",
#endif
#ifdef SQLITE4_ENABLE_IOTRACE
  "ENABLE_IOTRACE",
#endif
#ifdef SQLITE4_ENABLE_LOAD_EXTENSION
  "ENABLE_LOAD_EXTENSION",
#endif
#ifdef SQLITE4_ENABLE_LOCKING_STYLE
  "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE4_ENABLE_LOCKING_STYLE),
#endif
#ifdef SQLITE4_ENABLE_MEMSYS3
  "ENABLE_MEMSYS3",
#endif
#ifdef SQLITE4_ENABLE_MEMSYS5
  "ENABLE_MEMSYS5",
#endif
#ifdef SQLITE4_ENABLE_OVERSIZE_CELL_CHECK
  "ENABLE_OVERSIZE_CELL_CHECK",
#endif
#ifdef SQLITE4_ENABLE_RTREE
  "ENABLE_RTREE",
#endif
#ifdef SQLITE4_ENABLE_STAT3
  "ENABLE_STAT3",
#endif
#ifdef SQLITE4_ENABLE_UNLOCK_NOTIFY
  "ENABLE_UNLOCK_NOTIFY",
#endif
#ifdef SQLITE4_ENABLE_UPDATE_DELETE_LIMIT
  "ENABLE_UPDATE_DELETE_LIMIT",
#endif
#ifdef SQLITE4_HAS_CODEC
  "HAS_CODEC",
#endif
#ifdef SQLITE4_HAVE_ISNAN
  "HAVE_ISNAN",
#endif
#ifdef SQLITE4_HOMEGROWN_RECURSIVE_MUTEX
  "HOMEGROWN_RECURSIVE_MUTEX",
#endif
#ifdef SQLITE4_IGNORE_AFP_LOCK_ERRORS
  "IGNORE_AFP_LOCK_ERRORS",
#endif
#ifdef SQLITE4_IGNORE_FLOCK_LOCK_ERRORS
  "IGNORE_FLOCK_LOCK_ERRORS",
#endif
#ifdef SQLITE4_INT64_TYPE
  "INT64_TYPE",
#endif
#ifdef SQLITE4_LOCK_TRACE
  "LOCK_TRACE",
#endif
#ifdef SQLITE4_MAX_SCHEMA_RETRY
  "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE4_MAX_SCHEMA_RETRY),
#endif
#ifdef SQLITE4_MEMDEBUG
  "MEMDEBUG",
#endif
#ifdef SQLITE4_MIXED_ENDIAN_64BIT_FLOAT
  "MIXED_ENDIAN_64BIT_FLOAT",
#endif
#ifdef SQLITE4_NO_SYNC
  "NO_SYNC",
#endif
#ifdef SQLITE4_OMIT_ALTERTABLE
  "OMIT_ALTERTABLE",
#endif
#ifdef SQLITE4_OMIT_ANALYZE
  "OMIT_ANALYZE",
#endif
#ifdef SQLITE4_OMIT_ATTACH
  "OMIT_ATTACH",
#endif
#ifdef SQLITE4_OMIT_AUTHORIZATION
  "OMIT_AUTHORIZATION",
#endif
#ifdef SQLITE4_OMIT_AUTOINCREMENT
  "OMIT_AUTOINCREMENT",
#endif
#ifdef SQLITE4_OMIT_AUTOINIT
  "OMIT_AUTOINIT",
#endif
#ifdef SQLITE4_OMIT_AUTOMATIC_INDEX
  "OMIT_AUTOMATIC_INDEX",
#endif
#ifdef SQLITE4_OMIT_AUTORESET
  "OMIT_AUTORESET",
#endif
#ifdef SQLITE4_OMIT_BETWEEN_OPTIMIZATION
  "OMIT_BETWEEN_OPTIMIZATION",
#endif
#ifdef SQLITE4_OMIT_BLOB_LITERAL
  "OMIT_BLOB_LITERAL",
#endif
#ifdef SQLITE4_OMIT_BUILTIN_TEST
  "OMIT_BUILTIN_TEST",
#endif
#ifdef SQLITE4_OMIT_CAST
  "OMIT_CAST",
#endif
#ifdef SQLITE4_OMIT_CHECK
  "OMIT_CHECK",
#endif
/* // redundant
** #ifdef SQLITE4_OMIT_COMPILEOPTION_DIAGS
**   "OMIT_COMPILEOPTION_DIAGS",
** #endif
*/
#ifdef SQLITE4_OMIT_COMPLETE
  "OMIT_COMPLETE",
#endif
#ifdef SQLITE4_OMIT_COMPOUND_SELECT
  "OMIT_COMPOUND_SELECT",
#endif
#ifdef SQLITE4_OMIT_DATETIME_FUNCS
  "OMIT_DATETIME_FUNCS",
#endif
#ifdef SQLITE4_OMIT_DECLTYPE
  "OMIT_DECLTYPE",
#endif
#ifdef SQLITE4_OMIT_DEPRECATED
  "OMIT_DEPRECATED",
#endif
#ifdef SQLITE4_OMIT_DISKIO
  "OMIT_DISKIO",
#endif
#ifdef SQLITE4_OMIT_EXPLAIN
  "OMIT_EXPLAIN",
#endif
#ifdef SQLITE4_OMIT_FLAG_PRAGMAS
  "OMIT_FLAG_PRAGMAS",
#endif
#ifdef SQLITE4_OMIT_FLOATING_POINT
  "OMIT_FLOATING_POINT",
#endif
#ifdef SQLITE4_OMIT_FOREIGN_KEY
  "OMIT_FOREIGN_KEY",
#endif
#ifdef SQLITE4_OMIT_GET_TABLE
  "OMIT_GET_TABLE",
#endif
#ifdef SQLITE4_OMIT_INTEGRITY_CHECK
  "OMIT_INTEGRITY_CHECK",
#endif
#ifdef SQLITE4_OMIT_LIKE_OPTIMIZATION
  "OMIT_LIKE_OPTIMIZATION",
#endif
#ifdef SQLITE4_OMIT_LOAD_EXTENSION
  "OMIT_LOAD_EXTENSION",
#endif
#ifdef SQLITE4_OMIT_LOCALTIME
  "OMIT_LOCALTIME",
#endif
#ifdef SQLITE4_OMIT_LOOKASIDE
  "OMIT_LOOKASIDE",
#endif
#ifdef SQLITE4_OMIT_MEMORYDB
  "OMIT_MEMORYDB",
#endif
#ifdef SQLITE4_OMIT_OR_OPTIMIZATION
  "OMIT_OR_OPTIMIZATION",
#endif
#ifdef SQLITE4_OMIT_PAGER_PRAGMAS
  "OMIT_PAGER_PRAGMAS",
#endif
#ifdef SQLITE4_OMIT_PRAGMA
  "OMIT_PRAGMA",
#endif
#ifdef SQLITE4_OMIT_PROGRESS_CALLBACK
  "OMIT_PROGRESS_CALLBACK",
#endif
#ifdef SQLITE4_OMIT_QUICKBALANCE
  "OMIT_QUICKBALANCE",
#endif
#ifdef SQLITE4_OMIT_REINDEX
  "OMIT_REINDEX",
#endif
#ifdef SQLITE4_OMIT_SCHEMA_PRAGMAS
  "OMIT_SCHEMA_PRAGMAS",
#endif
#ifdef SQLITE4_OMIT_SCHEMA_VERSION_PRAGMAS
  "OMIT_SCHEMA_VERSION_PRAGMAS",
#endif
#ifdef SQLITE4_OMIT_SUBQUERY
  "OMIT_SUBQUERY",
#endif
#ifdef SQLITE4_OMIT_TCL_VARIABLE
  "OMIT_TCL_VARIABLE",
#endif
#ifdef SQLITE4_OMIT_TEMPDB
  "OMIT_TEMPDB",
#endif
#ifdef SQLITE4_OMIT_TRACE
  "OMIT_TRACE",
#endif
#ifdef SQLITE4_OMIT_TRIGGER
  "OMIT_TRIGGER",
#endif
#ifdef SQLITE4_OMIT_TRUNCATE_OPTIMIZATION
  "OMIT_TRUNCATE_OPTIMIZATION",
#endif
#ifdef SQLITE4_OMIT_UTF16
  "OMIT_UTF16",
#endif
#ifdef SQLITE4_OMIT_VIEW
  "OMIT_VIEW",
#endif
#ifdef SQLITE4_OMIT_VIRTUALTABLE
  "OMIT_VIRTUALTABLE",
#endif
#ifdef SQLITE4_PERFORMANCE_TRACE
  "PERFORMANCE_TRACE",
#endif
#ifdef SQLITE4_PROXY_DEBUG
  "PROXY_DEBUG",
#endif
#ifdef SQLITE4_SECURE_DELETE
  "SECURE_DELETE",
#endif
#ifdef SQLITE4_SMALL_STACK
  "SMALL_STACK",
#endif
#ifdef SQLITE4_SOUNDEX
  "SOUNDEX",
#endif
#ifdef SQLITE4_TCL
  "TCL",
#endif
#ifdef SQLITE4_TEMP_STORE
  "TEMP_STORE=" CTIMEOPT_VAL(SQLITE4_TEMP_STORE),
#endif
#ifdef SQLITE4_TEST
  "TEST",
#endif
#ifdef SQLITE4_THREADSAFE
  "THREADSAFE=" CTIMEOPT_VAL(SQLITE4_THREADSAFE),
#endif
#ifdef SQLITE4_USE_ALLOCA
  "USE_ALLOCA",
#endif
#ifdef SQLITE4_ZERO_MALLOC
  "ZERO_MALLOC"
#endif
};

/*
** Given the name of a compile-time option, return true if that option
** was used and false if not.
**
** The name can optionally begin with "SQLITE4_" but the "SQLITE4_" prefix
** is not required for a match.
*/
SQLITE4_API int sqlite4_compileoption_used(const char *zOptName){
  int i, n;
  if( sqlite4_strnicmp(zOptName, "SQLITE4_", 8)==0 ) zOptName += 8;
  n = sqlite4Strlen30(zOptName);

  /* Since ArraySize(azCompileOpt) is normally in single digits, a
  ** linear search is adequate.  No need for a binary search. */
  for(i=0; i<ArraySize(azCompileOpt); i++){
    if(   (sqlite4_strnicmp(zOptName, azCompileOpt[i], n)==0)
       && ( (azCompileOpt[i][n]==0) || (azCompileOpt[i][n]=='=') ) ) return 1;
  }
  return 0;
}

/*
** Return the N-th compile-time option string.  If N is out of range,
** return a NULL pointer.
*/
SQLITE4_API const char *sqlite4_compileoption_get(int N){
  if( N>=0 && N<ArraySize(azCompileOpt) ){
    return azCompileOpt[N];
  }
  return 0;
}

#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */

/************** End of ctime.c ***********************************************/
/************** Begin file status.c ******************************************/
/*
** 2008 June 18
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This module implements the sqlite4_status() interface and related
** functionality.
*/
/************** Include vdbeInt.h in the middle of status.c ******************/
/************** Begin file vdbeInt.h *****************************************/
/*
** 2003 September 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This is the header file for information that is private to the
** VDBE.  This information used to all be at the top of the single
** source code file "vdbe.c".  When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
** of the following structure.
*/
typedef struct VdbeOp Op;

/*
** Boolean values
*/
typedef unsigned char Bool;

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

/* Opaque type used by the explainer */
typedef struct Explain Explain;

/* Opaque type used by vdbecodec.c */
typedef struct RowDecoder RowDecoder;

/*
** A cursor is a pointer into a single database.
** The cursor can seek to an entry with a particular key, or
** loop over all entries.  You can also insert new
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
** 
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
*/
struct VdbeCursor {
  sqlite4 *db;          /* The connection that owns this cursor */
  KVCursor *pKVCur;     /* The cursor structure of the storage engine */
  KVStore *pTmpKV;      /* Separate file holding a temporary table */
  KeyInfo *pKeyInfo;    /* Info about index keys needed by index cursors */
  int iDb;              /* Index of cursor database in db->aDb[] (or -1) */
  int iRoot;            /* Root page of the table */
  int nField;           /* Number of fields in the header */
  Bool nullRow;         /* True if pointing to a row with no data */
  Bool rowChnged;       /* True if row has changed out from under pDecoder */
  i64 seqCount;         /* Sequence counter */
  VdbeSorter *pSorter;  /* Sorter object for OP_SorterOpen cursors */
  Fts5Cursor *pFts;     /* Fts5 cursor object (or NULL) */
  RowDecoder *pDecoder;              /* Decoder for row content */
  sqlite4_vtab_cursor *pVtabCursor;  /* The cursor for a virtual table */
  const sqlite4_module *pModule;     /* Module for cursor pVtabCursor */
  sqlite4_buffer sSeekKey;           /* Key for deferred seek */
};

/* Methods for the VdbeCursor object */
SQLITE4_PRIVATE void sqlite4VdbeFreeCursor(VdbeCursor*);
SQLITE4_PRIVATE int sqlite4VdbeSeekEnd(VdbeCursor*, int);
SQLITE4_PRIVATE int sqlite4VdbeNext(VdbeCursor*);
SQLITE4_PRIVATE int sqlite4VdbePrevious(VdbeCursor*);
SQLITE4_PRIVATE int sqlite4VdbeCursorMoveto(VdbeCursor *);


/*
** When a sub-program is executed (OP_Program), a structure of this type
** is allocated to store the current value of the program counter, as
** well as the current memory cell array and various other frame specific
** values stored in the Vdbe struct. When the sub-program is finished, 
** these values are copied back to the Vdbe from the VdbeFrame structure,
** restoring the state of the VM to as it was before the sub-program
** began executing.
**
** The memory for a VdbeFrame object is allocated and managed by a memory
** cell in the parent (calling) frame. When the memory cell is deleted or
** overwritten, the VdbeFrame object is not freed immediately. Instead, it
** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
** this instead of deleting the VdbeFrame immediately is to avoid recursive
** calls to sqlite4VdbeMemRelease() when the memory cells belonging to the
** child frame are released.
**
** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
** set to NULL if the currently executing frame is the main program.
*/
typedef struct VdbeFrame VdbeFrame;
struct VdbeFrame {
  Vdbe *v;                /* VM this frame belongs to */
  int pc;                 /* Program Counter in parent (calling) frame */
  Op *aOp;                /* Program instructions for parent frame */
  int nOp;                /* Size of aOp array */
  Mem *aMem;              /* Array of memory cells for parent frame */
  int nMem;               /* Number of entries in aMem */
  u8 *aOnceFlag;          /* Array of OP_Once flags for parent frame */
  int nOnceFlag;          /* Number of entries in aOnceFlag */
  VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
  u16 nCursor;            /* Number of entries in apCsr */
  void *token;            /* Copy of SubProgram.token */
  int nChildMem;          /* Number of memory cells for child frame */
  int nChildCsr;          /* Number of cursors for child frame */
  int nChange;            /* Statement changes (Vdbe.nChanges)     */
  VdbeFrame *pParent;     /* Parent of this frame, or NULL if parent is main */
};

#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])

/*
** A value for VdbeCursor.cacheValid that means the cache is always invalid.
*/
#define CACHE_STALE 0

/*
** Internally, the vdbe manipulates nearly all SQL values as Mem
** structures. Each Mem struct may cache multiple representations (string,
** integer etc.) of the same value.
*/
struct Mem {
  sqlite4 *db;        /* The associated database connection */
  char *z;            /* String or BLOB value */
  union {
    sqlite4_num num;    /* Numeric value used by MEM_Int and/or MEM_Real */
    FuncDef *pDef;      /* Used only when flags==MEM_Agg */
    RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
    VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */
  } u;
  int n;              /* Number of characters in string value, excluding '\0' */
  u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
  u8  type;           /* One of SQLITE4_NULL, _TEXT, _INTEGER, etc */
  u8  enc;            /* SQLITE4_UTF8, SQLITE4_UTF16BE, SQLITE4_UTF16LE */
#ifdef SQLITE4_DEBUG
  Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
  void *pFiller;      /* So that sizeof(Mem) is a multiple of 8 */
#endif
  void (*xDel)(void*,void*); /* Function to delete Mem.z */
  void *pDelArg;             /* First argument to xDel() */
  char *zMalloc;      /* Dynamic buffer allocated by sqlite4_malloc() */
};

/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** No other flags may be set in this case.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
** database (see below for exceptions). If the MEM_Term flag is also
** set, then the string is nul terminated. The MEM_Int and MEM_Real 
** flags may coexist with the MEM_Str flag.
*/
#define MEM_Null      0x0001   /* Value is NULL */
#define MEM_Str       0x0002   /* Value is a string */
#define MEM_Int       0x0004   /* Value is an integer */
#define MEM_Real      0x0008   /* Value is a real number */
#define MEM_Blob      0x0010   /* Value is a BLOB */
#define MEM_RowSet    0x0020   /* Value is a RowSet object */
#define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
#define MEM_Invalid   0x0080   /* Value is undefined */
#define MEM_TypeMask  0x00ff   /* Mask of type bits */

/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
** policy for Mem.z.  The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
#define MEM_Term      0x0200   /* String rep is nul terminated */
#define MEM_Dyn       0x0400   /* Need to call sqliteFree() on Mem.z */
#define MEM_Static    0x0800   /* Mem.z points to a static string */
#define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
#define MEM_Agg       0x2000   /* Mem.z points to an agg function context */

/*
** Clear any existing type flags from a Mem and replace them with f
*/
#define MemSetTypeFlag(p, f) \
   ((p)->flags = ((p)->flags&~(MEM_TypeMask))|f)

/*
** Return true if a memory cell is not marked as invalid.  This macro
** is for use inside assert() statements only.
*/
#ifdef SQLITE4_DEBUG
#define memIsValid(M)  ((M)->flags & MEM_Invalid)==0
#endif


/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
** additional information about auxiliary information bound to arguments
** of the function.  This is used to implement the sqlite4_auxdata_fetch()
** and sqlite4_auxdata_store() APIs.  The "auxdata" is some auxiliary data
** that can be associated with a constant argument to a function.  This
** allows functions such as "regexp" to compile their constant regular
** expression argument once and reused the compiled code for multiple
** invocations.
*/
struct VdbeFunc {
  FuncDef *pFunc;               /* The definition of the function */
  int nAux;                     /* Number of entries allocated for apAux[] */
  struct AuxData {
    void *pAux;                   /* Aux data for the i-th argument */
    void (*xDelete)(void*,void*); /* Destructor for the aux data */
    void *pDeleteArg;             /* First argument to xDelete */
  } apAux[1];                   /* One slot for each function argument */
};

/*
** The "context" argument for a installable function.  A pointer to an
** instance of this structure is the first argument to the routines used
** implement the SQL functions.
**
** There is a typedef for this structure in sqlite.h.  So all routines,
** even the public interface to SQLite, can use a pointer to this structure.
** But this file is the only place where the internal details of this
** structure are known.
**
** This structure is defined inside of vdbeInt.h because it uses substructures
** (Mem) which are only defined there.
*/
struct sqlite4_context {
  FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
  VdbeFunc *pVdbeFunc;  /* Auxilary data, if created. */
  Mem s;                /* The return value is stored here */
  Mem *pMem;            /* Memory cell used to store aggregate context */
  int isError;          /* Error code returned by the function. */
  CollSeq *pColl;       /* Collating sequence */
  Fts5Cursor *pFts;     /* fts5 cursor for matchinfo functions */
};

/*
** An Explain object accumulates indented output which is helpful
** in describing recursive data structures.
*/
struct Explain {
  Vdbe *pVdbe;       /* Attach the explanation to this Vdbe */
  StrAccum str;      /* The string being accumulated */
  int nIndent;       /* Number of elements in aIndent */
  u16 aIndent[100];  /* Levels of indentation */
  char zBase[100];   /* Initial space */
};

/*
** An instance of the virtual machine.  This structure contains the complete
** state of the virtual machine.
**
** The "sqlite4_stmt" structure pointer that is returned by sqlite4_prepare()
** is really a pointer to an instance of this structure.
**
** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
** any virtual table method invocations made by the vdbe program. It is
** set to 2 for xDestroy method calls and 1 for all other methods. This
** variable is used for two purposes: to allow xDestroy methods to execute
** "DROP TABLE" statements and to prevent some nasty side effects of
** malloc failure when SQLite is invoked recursively by a virtual table 
** method function.
*/
struct Vdbe {
  sqlite4 *db;            /* The database connection that owns this statement */
  Op *aOp;                /* Space to hold the virtual machine's program */
  Mem *aMem;              /* The memory locations */
  Mem **apArg;            /* Arguments to currently executing user function */
  Mem *aColName;          /* Column names to return */
  Mem *pResultSet;        /* Pointer to an array of results */
  int nMem;               /* Number of memory locations currently allocated */
  int nOp;                /* Number of instructions in the program */
  int nOpAlloc;           /* Number of slots allocated for aOp[] */
  int nLabel;             /* Number of labels used */
  int nLabelAlloc;        /* Number of slots allocated in aLabel[] */
  int *aLabel;            /* Space to hold the labels */
  u16 nResColumn;         /* Number of columns in one row of the result set */
  u16 nCursor;            /* Number of slots in apCsr[] */
  u32 magic;              /* Magic number for sanity checking */
  char *zErrMsg;          /* Error message written here */
  Vdbe *pPrev,*pNext;     /* Linked list of VDBEs with the same Vdbe.db */
  VdbeCursor **apCsr;     /* One element of this array for each open cursor */
  Mem *aVar;              /* Values for the OP_Variable opcode. */
  char **azVar;           /* Name of variables */
  ynVar nVar;             /* Number of entries in aVar[] */
  ynVar nzVar;            /* Number of entries in azVar[] */
  u32 cacheCtr;           /* VdbeCursor row cache generation counter */
  int pc;                 /* The program counter */
  int rc;                 /* Value to return */
  u8 errorAction;         /* Recovery action to do in case of an error */
  u8 explain;             /* True if EXPLAIN present on SQL command */
  u8 changeCntOn;         /* True to update the change-counter */
  u8 expired;             /* True if the VM needs to be recompiled */
  u8 runOnlyOnce;         /* Automatically expire on reset */
  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
  u8 inVtabMethod;        /* See comments above */
  u8 needSavepoint;       /* True if a change might abort and needs savepoint */
  u8 readOnly;            /* True for read-only statements */
  int nChange;            /* Number of db changes made since last reset */
  yDbMask stmtTransMask;  /* db->aDb[] entries that have a subtransaction */
  int aCounter[3];        /* Counters used by sqlite4_stmt_status() */
#ifndef SQLITE4_OMIT_TRACE
  u64 startTime;          /* Time when query started - used for profiling */
#endif
  i64 nFkConstraint;      /* Number of imm. FK constraints this VM */
  i64 nStmtDefCons;       /* Number of def. constraints when stmt started */
  char *zSql;             /* Text of the SQL statement that generated this */
  void *pFree;            /* Free this when deleting the vdbe */
#ifdef SQLITE4_DEBUG
  FILE *trace;            /* Write an execution trace here, if not NULL */
#endif
#ifdef SQLITE4_ENABLE_TREE_EXPLAIN
  Explain *pExplain;      /* The explainer */
  char *zExplain;         /* Explanation of data structures */
#endif
  VdbeFrame *pFrame;      /* Parent frame */
  VdbeFrame *pDelFrame;   /* List of frame objects to free on VM reset */
  int nFrame;             /* Number of frames in pFrame list */
  u32 expmask;            /* Binding to these vars invalidates VM */
  SubProgram *pProgram;   /* Linked list of all sub-programs used by VM */
  int nOnceFlag;          /* Size of array aOnceFlag[] */
  u8 *aOnceFlag;          /* Flags for OP_Once */
};

/*
** The following are allowed values for Vdbe.magic
*/
#define VDBE_MAGIC_INIT     0x26bceaa5    /* Building a VDBE program */
#define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */
#define VDBE_MAGIC_HALT     0x519c2973    /* VDBE has completed execution */
#define VDBE_MAGIC_DEAD     0xb606c3c8    /* The VDBE has been deallocated */

/*
** Function prototypes
*/
void sqliteVdbePopStack(Vdbe*,int);
#if defined(SQLITE4_DEBUG) || defined(VDBE_PROFILE)
SQLITE4_PRIVATE void sqlite4VdbePrintOp(FILE*, int, Op*);
#endif
SQLITE4_PRIVATE void sqlite4VdbeDeleteAuxData(VdbeFunc*, int);

SQLITE4_PRIVATE int sqlite4VdbeDecoderCreate(
  sqlite4 *db,                /* The database connection */
  VdbeCursor *pCur,           /* Cursor associated with this decoder */
  KVCursor *pKVCur,           /* Alternative cursor if pCur is NULL */
  int mxCol,                  /* Maximum number of columns in aIn[] */
  RowDecoder **ppOut          /* The newly generated decoder object */
);
SQLITE4_PRIVATE int sqlite4VdbeDecoderDestroy(RowDecoder *pDecoder);
SQLITE4_PRIVATE int sqlite4VdbeDecoderGetColumn(
  RowDecoder *pDecoder,        /* The decoder for the whole string */
  int iVal,                    /* Index of the value to decode.  First is 0 */
  Mem *pDefault,               /* The default value.  Often NULL */
  Mem *pOut                    /* Write the result here */
);
SQLITE4_PRIVATE int sqlite4VdbeEncodeData(
  sqlite4 *db,                /* The database connection */
  Mem *aIn,                   /* Array of values to encode */
  int *aPermute,              /* Permutation (or NULL) */
  int nIn,                    /* Number of entries in aIn[] */
  u8 **pzOut,                 /* The output data record */
  int *pnOut                  /* Bytes of content in pzOut */
);
SQLITE4_PRIVATE int sqlite4VdbeEncodeIntKey(u8 *aBuf,sqlite4_int64 v);
SQLITE4_PRIVATE int sqlite4VdbeDecodeNumericKey(const KVByteArray*, KVSize, sqlite4_num*);
SQLITE4_PRIVATE int sqlite4VdbeShortKey(const u8 *, int, int, int *);
SQLITE4_PRIVATE int sqlite4MemCompare(Mem*, Mem*, const CollSeq*,int*);
SQLITE4_PRIVATE int sqlite4VdbeExec(Vdbe*);
SQLITE4_PRIVATE int sqlite4VdbeList(Vdbe*);
SQLITE4_PRIVATE int sqlite4VdbeHalt(Vdbe*);
SQLITE4_PRIVATE int sqlite4VdbeChangeEncoding(Mem *, int);
SQLITE4_PRIVATE int sqlite4VdbeMemTooBig(Mem*);
SQLITE4_PRIVATE int sqlite4VdbeMemCopy(Mem*, const Mem*);
SQLITE4_PRIVATE void sqlite4VdbeMemShallowCopy(Mem*, const Mem*, int);
SQLITE4_PRIVATE void sqlite4VdbeMemMove(Mem*, Mem*);
SQLITE4_PRIVATE int sqlite4VdbeMemNulTerminate(Mem*);
SQLITE4_PRIVATE int sqlite4VdbeMemSetStr(Mem*, const char*, int, u8,
                         void(*)(void*,void*),void*);
SQLITE4_PRIVATE void sqlite4VdbeMemSetInt64(Mem*, i64);
#ifdef SQLITE4_OMIT_FLOATING_POINT
# define sqlite4VdbeMemSetDouble sqlite4VdbeMemSetInt64
#else
SQLITE4_PRIVATE   void sqlite4VdbeMemSetDouble(Mem*, double);
#endif
SQLITE4_PRIVATE void sqlite4VdbeMemSetNull(Mem*);
SQLITE4_PRIVATE void sqlite4VdbeMemSetNum(Mem *, sqlite4_num, int);
SQLITE4_PRIVATE int sqlite4VdbeMemMakeWriteable(Mem*);
SQLITE4_PRIVATE int sqlite4VdbeMemStringify(Mem*, int);
SQLITE4_PRIVATE i64 sqlite4VdbeIntValue(Mem*);
SQLITE4_PRIVATE int sqlite4VdbeMemIntegerify(Mem*);
SQLITE4_PRIVATE double sqlite4VdbeRealValue(Mem*);
SQLITE4_PRIVATE sqlite4_num sqlite4VdbeNumValue(Mem *);
SQLITE4_PRIVATE void sqlite4VdbeIntegerAffinity(Mem*);
SQLITE4_PRIVATE int sqlite4VdbeMemNumerify(Mem*);
SQLITE4_PRIVATE void sqlite4VdbeMemSetRowSet(Mem *pMem);

SQLITE4_PRIVATE void sqlite4VdbeMemRelease(Mem *p);
SQLITE4_PRIVATE void sqlite4VdbeMemReleaseExternal(Mem *p);
#define VdbeMemRelease(X)  \
  if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
    sqlite4VdbeMemReleaseExternal(X);
SQLITE4_PRIVATE int sqlite4VdbeMemFinalize(Mem*, FuncDef*);
SQLITE4_PRIVATE const char *sqlite4OpcodeName(int);
SQLITE4_PRIVATE int sqlite4VdbeMemGrow(Mem *pMem, int n, int preserve);
SQLITE4_PRIVATE int sqlite4VdbeCloseStatement(Vdbe *, int);
SQLITE4_PRIVATE void sqlite4VdbeFrameDelete(VdbeFrame*);
SQLITE4_PRIVATE int sqlite4VdbeFrameRestore(VdbeFrame *);
SQLITE4_PRIVATE void sqlite4VdbeMemStoreType(Mem *pMem);
SQLITE4_PRIVATE int sqlite4VdbeTransferError(Vdbe *p);
SQLITE4_PRIVATE int sqlite4VdbeRollback(sqlite4 *db, int iLevel);
SQLITE4_PRIVATE int sqlite4VdbeCommit(sqlite4 *db, int iLevel);

#ifdef SQLITE4_DEBUG
SQLITE4_PRIVATE void sqlite4VdbeMemAboutToChange(Vdbe*,Mem*);
#endif

#ifndef SQLITE4_OMIT_FOREIGN_KEY
SQLITE4_PRIVATE int sqlite4VdbeCheckFk(Vdbe *, int);
#else
# define sqlite4VdbeCheckFk(p,i) 0
#endif

SQLITE4_PRIVATE int sqlite4VdbeMemTranslate(Mem*, u8);
#ifdef SQLITE4_DEBUG
SQLITE4_PRIVATE   void sqlite4VdbePrintSql(Vdbe*);
SQLITE4_PRIVATE   void sqlite4VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
#endif
SQLITE4_PRIVATE int sqlite4VdbeMemHandleBom(Mem *pMem);


#endif /* !defined(_VDBEINT_H_) */

/************** End of vdbeInt.h *********************************************/
/************** Continuing where we left off in status.c *********************/

/*
** Add N to the value of a status record.  It is assumed that the
** caller holds appropriate locks.
*/
SQLITE4_PRIVATE void sqlite4StatusAdd(sqlite4_env *pEnv, int op, sqlite4_int64 N){
  assert( op>=0 && op<ArraySize(pEnv->nowValue) );
  pEnv->nowValue[op] += N;
  if( pEnv->nowValue[op]>pEnv->mxValue[op] ){
    pEnv->mxValue[op] = pEnv->nowValue[op];
  }
}

/*
** Set the value of a status to X.
*/
SQLITE4_PRIVATE void sqlite4StatusSet(sqlite4_env *pEnv, int op, sqlite4_uint64 X){
  assert( op>=0 && op<ArraySize(pEnv->nowValue) );
  pEnv->nowValue[op] = X;
  if( pEnv->nowValue[op]>pEnv->mxValue[op] ){
    pEnv->mxValue[op] = pEnv->nowValue[op];
  }
}

/*
** Query status information.
**
** This implementation assumes that reading or writing an aligned
** 32-bit integer is an atomic operation.  If that assumption is not true,
** then this routine is not threadsafe.
*/
SQLITE4_API int sqlite4_env_status(
  sqlite4_env *pEnv,
  int op,
  sqlite4_uint64 *pCurrent,
  sqlite4_uint64 *pHighwater,
  int resetFlag
){
  if( pEnv==0 ) pEnv = sqlite4_env_default();
  if( op<0 || op>=ArraySize(pEnv->nowValue) ){
    return SQLITE4_MISUSE_BKPT;
  }
  *pCurrent = pEnv->nowValue[op];
  *pHighwater = pEnv->mxValue[op];
  if( resetFlag ){
    pEnv->mxValue[op] = pEnv->nowValue[op];
  }
  return SQLITE4_OK;
}

/*
** Query status information for a single database connection
*/
SQLITE4_API int sqlite4_db_status(
  sqlite4 *db,          /* The database connection whose status is desired */
  int op,               /* Status verb */
  int *pCurrent,        /* Write current value here */
  int *pHighwater,      /* Write high-water mark here */
  int resetFlag         /* Reset high-water mark if true */
){
  int rc = SQLITE4_OK;   /* Return code */
  sqlite4_env *pEnv;
  sqlite4_mutex_enter(db->mutex);
  pEnv = db->pEnv;
  switch( op ){
    case SQLITE4_DBSTATUS_LOOKASIDE_USED: {
      *pCurrent = db->lookaside.nOut;
      *pHighwater = db->lookaside.mxOut;
      if( resetFlag ){
        db->lookaside.mxOut = db->lookaside.nOut;
      }
      break;
    }

    case SQLITE4_DBSTATUS_LOOKASIDE_HIT:
    case SQLITE4_DBSTATUS_LOOKASIDE_MISS_SIZE:
    case SQLITE4_DBSTATUS_LOOKASIDE_MISS_FULL: {
      testcase( op==SQLITE4_DBSTATUS_LOOKASIDE_HIT );
      testcase( op==SQLITE4_DBSTATUS_LOOKASIDE_MISS_SIZE );
      testcase( op==SQLITE4_DBSTATUS_LOOKASIDE_MISS_FULL );
      assert( (op-SQLITE4_DBSTATUS_LOOKASIDE_HIT)>=0 );
      assert( (op-SQLITE4_DBSTATUS_LOOKASIDE_HIT)<3 );
      *pCurrent = 0;
      *pHighwater = db->lookaside.anStat[op - SQLITE4_DBSTATUS_LOOKASIDE_HIT];
      if( resetFlag ){
        db->lookaside.anStat[op - SQLITE4_DBSTATUS_LOOKASIDE_HIT] = 0;
      }
      break;
    }

    /* 
    ** Return an approximation for the amount of memory currently used
    ** by all pagers associated with the given database connection.  The
    ** highwater mark is meaningless and is returned as zero.
    */
    case SQLITE4_DBSTATUS_CACHE_USED: {
      int totalUsed = 0;
      *pCurrent = totalUsed;
      *pHighwater = 0;
      break;
    }

    /*
    ** *pCurrent gets an accurate estimate of the amount of memory used
    ** to store the schema for all databases (main, temp, and any ATTACHed
    ** databases.  *pHighwater is set to zero.
    */
    case SQLITE4_DBSTATUS_SCHEMA_USED: {
      int i;                      /* Used to iterate through schemas */
      int nByte = 0;              /* Used to accumulate return value */

      db->pnBytesFreed = &nByte;
      for(i=0; i<db->nDb; i++){
        Schema *pSchema = db->aDb[i].pSchema;
        if( ALWAYS(pSchema!=0) ){
          HashElem *p;

          nByte += sizeof(HashElem) * (
              pSchema->tblHash.count 
            + pSchema->trigHash.count
            + pSchema->idxHash.count
            + pSchema->fkeyHash.count
          );
          nByte += sqlite4MallocSize(pEnv, pSchema->tblHash.ht);
          nByte += sqlite4MallocSize(pEnv, pSchema->trigHash.ht);
          nByte += sqlite4MallocSize(pEnv, pSchema->idxHash.ht);
          nByte += sqlite4MallocSize(pEnv, pSchema->fkeyHash.ht);

          for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
            sqlite4DeleteTrigger(db, (Trigger*)sqliteHashData(p));
          }
          for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
            sqlite4DeleteTable(db, (Table *)sqliteHashData(p));
          }
        }
      }
      db->pnBytesFreed = 0;

      *pHighwater = 0;
      *pCurrent = nByte;
      break;
    }

    /*
    ** *pCurrent gets an accurate estimate of the amount of memory used
    ** to store all prepared statements.
    ** *pHighwater is set to zero.
    */
    case SQLITE4_DBSTATUS_STMT_USED: {
      struct Vdbe *pVdbe;         /* Used to iterate through VMs */
      int nByte = 0;              /* Used to accumulate return value */

      db->pnBytesFreed = &nByte;
      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
        sqlite4VdbeDeleteObject(db, pVdbe);
      }
      db->pnBytesFreed = 0;

      *pHighwater = 0;
      *pCurrent = nByte;

      break;
    }

    /*
    ** Set *pCurrent to the total cache hits or misses encountered by all
    ** pagers the database handle is connected to. *pHighwater is always set 
    ** to zero.
    */
    case SQLITE4_DBSTATUS_CACHE_HIT:
    case SQLITE4_DBSTATUS_CACHE_MISS: {
      int nRet = 0;
      *pHighwater = 0;
      *pCurrent = nRet;
      break;
    }

    default: {
      rc = SQLITE4_ERROR;
    }
  }
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/************** End of status.c **********************************************/
/************** Begin file date.c ********************************************/
/*
** 2003 October 31
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement date and time
** functions for SQLite.  
**
** There is only one exported symbol in this file - the function
** sqlite4RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** SQLite processes all times and dates as Julian Day numbers.  The
** dates and times are stored as the number of days since noon
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
** calendar system. 
**
** 1970-01-01 00:00:00 is JD 2440587.5
** 2000-01-01 00:00:00 is JD 2451544.5
**
** This implemention requires years to be expressed as a 4-digit number
** which means that only dates between 0000-01-01 and 9999-12-31 can
** be represented, even though julian day numbers allow a much wider
** range of dates.
**
** The Gregorian calendar system is used for all dates and times,
** even those that predate the Gregorian calendar.  Historians usually
** use the Julian calendar for dates prior to 1582-10-15 and for some
** dates afterwards, depending on locale.  Beware of this difference.
**
** The conversion algorithms are implemented based on descriptions
** in the following text:
**
**      Jean Meeus
**      Astronomical Algorithms, 2nd Edition, 1998
**      ISBM 0-943396-61-1
**      Willmann-Bell, Inc
**      Richmond, Virginia (USA)
*/
/* #include <stdlib.h> */
/* #include <assert.h> */
#include <time.h>

#ifndef SQLITE4_OMIT_DATETIME_FUNCS


/*
** A structure for holding a single date and time.
*/
typedef struct DateTime DateTime;
struct DateTime {
  sqlite4_uint64 iJD;   /* The julian day number times 86400000 */
  int Y, M, D;          /* Year, month, and day */
  int h, m;             /* Hour and minutes */
  int tz;               /* Timezone offset in minutes */
  sqlite4_num s;        /* Seconds */
  char validYMD;        /* True (1) if Y,M,D are valid */
  char validHMS;        /* True (1) if h,m,s are valid */
  char validJD;         /* True (1) if iJD is valid */
  char validTZ;         /* True (1) if tz is valid */
};


/*
** Convert zDate into one or more integers.  Additional arguments
** come in groups of 5 as follows:
**
**       N       number of digits in the integer
**       min     minimum allowed value of the integer
**       max     maximum allowed value of the integer
**       nextC   first character after the integer
**       pVal    where to write the integers value.
**
** Conversions continue until one with nextC==0 is encountered.
** The function returns the number of successful conversions.
*/
static int getDigits(const char *zDate, ...){
  va_list ap;
  int val;
  int N;
  int min;
  int max;
  int nextC;
  int *pVal;
  int cnt = 0;
  va_start(ap, zDate);
  do{
    N = va_arg(ap, int);
    min = va_arg(ap, int);
    max = va_arg(ap, int);
    nextC = va_arg(ap, int);
    pVal = va_arg(ap, int*);
    val = 0;
    while( N-- ){
      if( !sqlite4Isdigit(*zDate) ){
        goto end_getDigits;
      }
      val = val*10 + *zDate - '0';
      zDate++;
    }
    if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
      goto end_getDigits;
    }
    *pVal = val;
    zDate++;
    cnt++;
  }while( nextC );
end_getDigits:
  va_end(ap);
  return cnt;
}

/*
** Parse a timezone extension on the end of a date-time.
** The extension is of the form:
**
**        (+/-)HH:MM
**
** Or the "zulu" notation:
**
**        Z
**
** If the parse is successful, write the number of minutes
** of change in p->tz and return 0.  If a parser error occurs,
** return non-zero.
**
** A missing specifier is not considered an error.
*/
static int parseTimezone(const char *zDate, DateTime *p){
  int sgn = 0;
  int nHr, nMn;
  int c;
  while( sqlite4Isspace(*zDate) ){ zDate++; }
  p->tz = 0;
  c = *zDate;
  if( c=='-' ){
    sgn = -1;
  }else if( c=='+' ){
    sgn = +1;
  }else if( c=='Z' || c=='z' ){
    zDate++;
    goto zulu_time;
  }else{
    return c!=0;
  }
  zDate++;
  if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
    return 1;
  }
  zDate += 5;
  p->tz = sgn*(nMn + nHr*60);
zulu_time:
  while( sqlite4Isspace(*zDate) ){ zDate++; }
  return *zDate!=0;
}

/*
** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
** The HH, MM, and SS must each be exactly 2 digits.  The
** fractional seconds FFFF can be one or more digits.
**
** Return 1 if there is a parsing error and 0 on success.
*/
static int parseHhMmSs(const char *zDate, DateTime *p){
  int h, m, s;
  sqlite4_num ms = {0,0,0,0};
  if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
    return 1;
  }
  zDate += 5;
  if( *zDate==':' ){
    zDate++;
    if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
      return 1;
    }
    zDate += 2;

    if( *zDate=='.' ){
      int iMs = 0;
      int nDigit = 1;
      while( sqlite4Isdigit(zDate[nDigit]) ){
        iMs = iMs * 10 + (zDate[nDigit] - '0');
        nDigit++;
      }
      if( nDigit>1 ){
        ms = sqlite4_num_from_int64(iMs);
        assert( ms.e==0 );
        ms.e += (1-nDigit);
        zDate += nDigit;
      }
    }
  }else{
    s = 0;
  }
  p->validJD = 0;
  p->validHMS = 1;
  p->h = h;
  p->m = m;
  p->s = sqlite4_num_add(sqlite4_num_from_int64(s), ms);
  if( parseTimezone(zDate, p) ) return 1;
  p->validTZ = (p->tz!=0)?1:0;
  return 0;
}

/*
** Convert from YYYY-MM-DD HH:MM:SS to julian day.  We always assume
** that the YYYY-MM-DD is according to the Gregorian calendar.
**
** Reference:  Meeus page 61
*/
static void computeJD(DateTime *p){
  int Y, M, D, A, B, X1, X2;

  if( p->validJD ) return;
  if( p->validYMD ){
    Y = p->Y;
    M = p->M;
    D = p->D;
  }else{
    Y = 2000;  /* If no YMD specified, assume 2000-Jan-01 */
    M = 1;
    D = 1;
  }
  if( M<=2 ){
    Y--;
    M += 12;
  }
  A = Y/100;
  B = 2 - A + (A/4);
  X1 = 36525*(Y+4716)/100;
  X2 = 306001*(M+1)/10000;
  p->iJD = (sqlite4_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
  p->validJD = 1;
  if( p->validHMS ){
    p->iJD += p->h*3600000 + p->m*60000;
    p->iJD += sqlite4_num_to_int64(
        sqlite4_num_mul(p->s, sqlite4_num_from_int64(1000)), 0
    );
    if( p->validTZ ){
      p->iJD -= p->tz*60000;
      p->validYMD = 0;
      p->validHMS = 0;
      p->validTZ = 0;
    }
  }
}

/*
** Parse dates of the form
**
**     YYYY-MM-DD HH:MM:SS.FFF
**     YYYY-MM-DD HH:MM:SS
**     YYYY-MM-DD HH:MM
**     YYYY-MM-DD
**
** Write the result into the DateTime structure and return 0
** on success and 1 if the input string is not a well-formed
** date.
*/
static int parseYyyyMmDd(const char *zDate, DateTime *p){
  int Y, M, D, neg;

  if( zDate[0]=='-' ){
    zDate++;
    neg = 1;
  }else{
    neg = 0;
  }
  if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
    return 1;
  }
  zDate += 10;
  while( sqlite4Isspace(*zDate) || 'T'==*(u8*)zDate ){ zDate++; }
  if( parseHhMmSs(zDate, p)==0 ){
    /* We got the time */
  }else if( *zDate==0 ){
    p->validHMS = 0;
  }else{
    return 1;
  }
  p->validJD = 0;
  p->validYMD = 1;
  p->Y = neg ? -Y : Y;
  p->M = M;
  p->D = D;
  if( p->validTZ ){
    computeJD(p);
  }
  return 0;
}

/*
** Set the time to the current time reported by the VFS.
**
** Return the number of errors.
*/
static int setDateTimeToCurrent(sqlite4_context *context, DateTime *p){
  if( sqlite4OsCurrentTime(0, &p->iJD)==SQLITE4_OK ){
    p->validJD = 1;
    return 0;
  }else{
    return 1;
  }
}

/*
** Attempt to parse the given string into a Julian Day Number.  Return
** the number of errors.
**
** The following are acceptable forms for the input string:
**
**      YYYY-MM-DD HH:MM:SS.FFF  +/-HH:MM
**      DDDD.DD 
**      now
**
** In the first form, the +/-HH:MM is always optional.  The fractional
** seconds extension (the ".FFF") is optional.  The seconds portion
** (":SS.FFF") is option.  The year and date can be omitted as long
** as there is a time string.  The time string can be omitted as long
** as there is a year and date.
*/
static int parseDateOrTime(
  sqlite4_context *context, 
  const char *zDate, 
  DateTime *p
){
  if( parseYyyyMmDd(zDate,p)==0 ){
    return 0;
  }else if( parseHhMmSs(zDate, p)==0 ){
    return 0;
  }else if( sqlite4_stricmp(zDate,"now")==0){
    return setDateTimeToCurrent(context, p);
  }else{
    sqlite4_num num;
    num = sqlite4_num_from_text(zDate, -1, SQLITE4_IGNORE_WHITESPACE, 0);
    if( sqlite4_num_isnan(num)==0 ){
      static const sqlite4_num one_half = {0, 0, -1, 5};

      num = sqlite4_num_mul(num, sqlite4_num_from_int64(86400000));
      num = sqlite4_num_add(num, one_half);
      p->iJD = sqlite4_num_to_int64(num, 0);
      p->validJD = 1;
      return 0;
    }
  }
  return 1;
}

/*
** Compute the Year, Month, and Day from the julian day number.
*/
static void computeYMD(DateTime *p){
  int Z, A, B, C, D, E, X1;
  if( p->validYMD ) return;
  if( !p->validJD ){
    p->Y = 2000;
    p->M = 1;
    p->D = 1;
  }else{
    Z = (int)((p->iJD + 43200000)/86400000);
    A = (int)((Z - 1867216.25)/36524.25);
    A = Z + 1 + A - (A/4);
    B = A + 1524;
    C = (int)((B - 122.1)/365.25);
    D = (36525*C)/100;
    E = (int)((B-D)/30.6001);
    X1 = (int)(30.6001*E);
    p->D = B - D - X1;
    p->M = E<14 ? E-1 : E-13;
    p->Y = p->M>2 ? C - 4716 : C - 4715;
  }
  p->validYMD = 1;
}

/*
** Compute the Hour, Minute, and Seconds from the julian day number.
*/
static void computeHMS(DateTime *p){
  int s;
  if( p->validHMS ) return;
  computeJD(p);
  s = (int)((p->iJD + 43200000) % 86400000);
  p->s = sqlite4_num_div(
      sqlite4_num_from_int64(s), sqlite4_num_from_int64(1000)
  );
  s = (int)sqlite4_num_to_int64(p->s, 0);
  p->s = sqlite4_num_sub(p->s, sqlite4_num_from_int64(s));
  p->h = s/3600;
  s -= p->h*3600;
  p->m = s/60;
  p->s = sqlite4_num_add(p->s, sqlite4_num_from_int64(s - p->m*60));
  p->validHMS = 1;
}

/*
** Compute both YMD and HMS
*/
static void computeYMD_HMS(DateTime *p){
  computeYMD(p);
  computeHMS(p);
}

/*
** Clear the YMD and HMS and the TZ
*/
static void clearYMD_HMS_TZ(DateTime *p){
  p->validYMD = 0;
  p->validHMS = 0;
  p->validTZ = 0;
}

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

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


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

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

  x = *p;
  computeYMD_HMS(&x);
  if( x.Y<1971 || x.Y>=2038 ){
    x.Y = 2000;
    x.M = 1;
    x.D = 1;
    x.h = 0;
    x.m = 0;
    x.s = 0.0;
  } else {
    int s = (int)(x.s + 0.5);
    x.s = s;
  }
  x.tz = 0;
  x.validJD = 0;
  computeJD(&x);
  t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
  if( osLocaltime(&t, &sLocal) ){
    sqlite4_result_error(pCtx, "local time unavailable", -1);
    *pRc = SQLITE4_ERROR;
    return 0;
  }
  y.Y = sLocal.tm_year + 1900;
  y.M = sLocal.tm_mon + 1;
  y.D = sLocal.tm_mday;
  y.h = sLocal.tm_hour;
  y.m = sLocal.tm_min;
  y.s = sLocal.tm_sec;
  y.validYMD = 1;
  y.validHMS = 1;
  y.validJD = 0;
  y.validTZ = 0;
  computeJD(&y);
  *pRc = SQLITE4_OK;
  return y.iJD - x.iJD;
}
#endif /* SQLITE4_OMIT_LOCALTIME */

static sqlite4_int64 multiplyAndRound(sqlite4_num a, i64 b){
  static const sqlite4_num aRnd[2] = { {0, 0, -1, 5}, {1, 0, -1, 5} };
  sqlite4_num res;

  res = sqlite4_num_mul(a, sqlite4_num_from_int64(b));
  assert( res.sign==0 || res.sign==1 );
  res = sqlite4_num_add(res, aRnd[res.sign]);
  return sqlite4_num_to_int64(res, 0);
}

/*
** Process a modifier to a date-time stamp.  The modifiers are
** as follows:
**
**     NNN days
**     NNN hours
**     NNN minutes
**     NNN.NNNN seconds
**     NNN months
**     NNN years
**     start of month
**     start of year
**     start of week
**     start of day
**     weekday N
**     unixepoch
**     localtime
**     utc
**
** Return 0 on success and 1 if there is any kind of error. If the error
** is in a system call (i.e. localtime()), then an error message is written
** to context pCtx. If the error is an unrecognized modifier, no error is
** written to pCtx.
*/
static int parseModifier(
  sqlite4_context *pCtx,          /* Leave error message here */
  const char *zMod,               /* date-time modifier */
  DateTime *p                     /* Update the value this points to */
){
  int rc = 1;
  int n;
  char *z, zBuf[30];
  z = zBuf;
  for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
    z[n] = (char)sqlite4UpperToLower[(u8)zMod[n]];
  }
  z[n] = 0;
  switch( z[0] ){
#ifndef SQLITE4_OMIT_LOCALTIME
    case 'l': {
      /*    localtime
      **
      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
      ** show local time.
      */
      if( strcmp(z, "localtime")==0 ){
        computeJD(p);
        p->iJD += localtimeOffset(p, pCtx, &rc);
        clearYMD_HMS_TZ(p);
      }
      break;
    }
#endif
    case 'u': {
      /*
      **    unixepoch
      **
      ** Treat the current value of p->iJD as the number of
      ** seconds since 1970.  Convert to a real julian day number.
      */
      if( strcmp(z, "unixepoch")==0 && p->validJD ){
        p->iJD = (p->iJD + 43200)/86400 + 21086676*(i64)10000000;
        clearYMD_HMS_TZ(p);
        rc = 0;
      }
#ifndef SQLITE4_OMIT_LOCALTIME
      else if( strcmp(z, "utc")==0 ){
        sqlite4_int64 c1;
        computeJD(p);
        c1 = localtimeOffset(p, pCtx, &rc);
        if( rc==SQLITE4_OK ){
          p->iJD -= c1;
          clearYMD_HMS_TZ(p);
          p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
        }
      }
#endif
      break;
    }
    case 'w': {
      /*
      **    weekday N
      **
      ** Move the date to the same time on the next occurrence of
      ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
      ** date is already on the appropriate weekday, this is a no-op.
      */
      if( strncmp(z, "weekday ", 8)==0 ){
        int bLossy;
        int iWeekday;
        sqlite4_int64 Z;
        sqlite4_num w;
        int n;

        for(n=8; sqlite4Isspace(z[n]); n++);
        if( z[n]==0 ) break;
        w = sqlite4_num_from_text(&z[8], -1, SQLITE4_IGNORE_WHITESPACE, 0);
        if( sqlite4_num_isnan(w) ) break;
        iWeekday = (int)sqlite4_num_to_int64(w, &bLossy);
        if( bLossy || iWeekday<0 || iWeekday>6 ) break;

        computeYMD_HMS(p);
        p->validTZ = 0;
        p->validJD = 0;
        computeJD(p);
        Z = ((p->iJD + 129600000)/86400000) % 7;
        if( Z>iWeekday ) Z -= 7;
        p->iJD += (iWeekday - Z)*86400000;
        clearYMD_HMS_TZ(p);
        rc = 0;
      }
      break;
    }
    case 's': {
      /*
      **    start of TTTTT
      **
      ** Move the date backwards to the beginning of the current day,
      ** or month or year.
      */
      if( strncmp(z, "start of ", 9)!=0 ) break;
      z += 9;
      computeYMD(p);
      p->validHMS = 1;
      p->h = p->m = 0;
      memset(&p->s, 0, sizeof(sqlite4_num));
      p->validTZ = 0;
      p->validJD = 0;
      if( strcmp(z,"month")==0 ){
        p->D = 1;
        rc = 0;
      }else if( strcmp(z,"year")==0 ){
        computeYMD(p);
        p->M = 1;
        p->D = 1;
        rc = 0;
      }else if( strcmp(z,"day")==0 ){
        rc = 0;
      }
      break;
    }
    case '+':
    case '-':
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9': {
      sqlite4_num num;

      for(n=1; z[n] && z[n]!=':' && !sqlite4Isspace(z[n]); n++){}
      num = sqlite4_num_from_text(z, n, SQLITE4_IGNORE_WHITESPACE, 0);
      if( sqlite4_num_isnan(num) ){
        rc = 1;
        break;
      }

      if( z[n]==':' ){
        /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
        ** specified number of hours, minutes, seconds, and fractional seconds
        ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
        ** omitted.
        */
        const char *z2 = z;
        DateTime tx;
        sqlite4_int64 day;
        if( !sqlite4Isdigit(*z2) ) z2++;
        memset(&tx, 0, sizeof(tx));
        if( parseHhMmSs(z2, &tx) ) break;
        computeJD(&tx);
        tx.iJD -= 43200000;
        day = tx.iJD/86400000;
        tx.iJD -= day*86400000;
        if( z[0]=='-' ) tx.iJD = -tx.iJD;
        computeJD(p);
        clearYMD_HMS_TZ(p);
        p->iJD += tx.iJD;
        rc = 0;
        break;
      }

      z += n;
      while( sqlite4Isspace(*z) ) z++;
      n = sqlite4Strlen30(z);
      if( n>10 || n<3 ) break;
      if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
      computeJD(p);
      rc = 0;

      if( n==3 && strcmp(z,"day")==0 ){
        p->iJD += multiplyAndRound(num, 86400000);
      }else if( n==4 && strcmp(z,"hour")==0 ){
        p->iJD += multiplyAndRound(num, 86400000 / 24);
      }else if( n==6 && strcmp(z,"minute")==0 ){
        p->iJD += multiplyAndRound(num, 86400000 / (24 * 60));
      }else if( n==6 && strcmp(z,"second")==0 ){
        p->iJD += multiplyAndRound(num, 86400000 / (24 * 60 * 60));
      }else if( n==5 && strcmp(z,"month")==0 ){
        int bLossy;
        int nMonth;
        int x;
        nMonth = sqlite4_num_to_int64(num, &bLossy);
        computeYMD_HMS(p);
        p->M += nMonth;
        x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
        p->Y += x;
        p->M -= x*12;
        p->validJD = 0;
        computeJD(p);
        if( bLossy ){
          num = sqlite4_num_sub(num, sqlite4_num_from_int64(nMonth));
          p->iJD += multiplyAndRound(num, (i64)30*86400000);
        }
      }else if( n==4 && strcmp(z,"year")==0 ){
        int bLossy;
        int nYear;
        nYear = sqlite4_num_to_int64(num, &bLossy);
        computeYMD_HMS(p);
        p->Y += nYear;
        p->validJD = 0;
        computeJD(p);
        if( bLossy ){
          num = sqlite4_num_sub(num, sqlite4_num_from_int64(nYear));
          p->iJD += multiplyAndRound(num, (i64)365*86400000);
        }
      }else{
        rc = 1;
      }
      clearYMD_HMS_TZ(p);
      break;
    }
    default: {
      break;
    }
  }
  return rc;
}

/*
** Process time function arguments.  argv[0] is a date-time stamp.
** argv[1] and following are modifiers.  Parse them all and write
** the resulting time into the DateTime structure p.  Return 0
** on success and 1 if there are any errors.
**
** If there are zero parameters (if even argv[0] is undefined)
** then assume a default value of "now" for argv[0].
*/
static int isDate(
  sqlite4_context *context, 
  int argc, 
  sqlite4_value **argv, 
  DateTime *p
){
  static const sqlite4_num ms_per_day = {0, 0, 0, 86400000};

  int i;
  const char *z;
  int eType;
  memset(p, 0, sizeof(*p));
  if( argc==0 ){
    return setDateTimeToCurrent(context, p);
  }
  eType = sqlite4_value_type(argv[0]);
  if( eType==SQLITE4_FLOAT || eType==SQLITE4_INTEGER ){
    sqlite4_num jd = sqlite4_num_mul(sqlite4_value_num(argv[0]), ms_per_day);
    p->iJD = sqlite4_num_to_int64(sqlite4_num_round(jd, 0), 0);
    p->validJD = 1;
  }else{
    z = sqlite4_value_text(argv[0], 0);
    if( !z || parseDateOrTime(context, z, p) ){
      return 1;
    }
  }
  for(i=1; i<argc; i++){
    z = sqlite4_value_text(argv[i], 0);
    if( z==0 || parseModifier(context, z, p) ) return 1;
  }
  return 0;
}


/*
** The following routines implement the various date and time functions
** of SQLite.
*/

/*
**    julianday( TIMESTRING, MOD, MOD, ...)
**
** Return the julian day number of the date specified in the arguments
*/
static void juliandayFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  static const sqlite4_num ms_per_day = {0, 0, 0, 86400000};
  DateTime x;

  if( isDate(context, argc, argv, &x)==0 ){
    computeJD(&x);
    sqlite4_result_num(context, 
        sqlite4_num_div(sqlite4_num_from_int64(x.iJD), ms_per_day)
    );
  }
}

/*
**    datetime( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD HH:MM:SS
*/
static void datetimeFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  DateTime x;
  if( isDate(context, argc, argv, &x)==0 ){
    char zBuf[100];
    computeYMD_HMS(&x);
    sqlite4_snprintf(zBuf,sizeof(zBuf), "%04d-%02d-%02d %02d:%02d:%02d",
        x.Y, x.M, x.D, x.h, x.m, (int)(sqlite4_num_to_int64(x.s,0))
    );
    sqlite4_result_text(context, zBuf, -1, SQLITE4_TRANSIENT, 0);
  }
}

/*
**    time( TIMESTRING, MOD, MOD, ...)
**
** Return HH:MM:SS
*/
static void timeFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  DateTime x;
  if( isDate(context, argc, argv, &x)==0 ){
    char zBuf[100];
    computeHMS(&x);
    sqlite4_snprintf(zBuf,sizeof(zBuf), "%02d:%02d:%02d", x.h, x.m, 
        (int)(sqlite4_num_to_int64(x.s,0))
    );
    sqlite4_result_text(context, zBuf, -1, SQLITE4_TRANSIENT, 0);
  }
}

/*
**    date( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD
*/
static void dateFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  DateTime x;
  if( isDate(context, argc, argv, &x)==0 ){
    char zBuf[100];
    computeYMD(&x);
    sqlite4_snprintf(zBuf,sizeof(zBuf), "%04d-%02d-%02d", x.Y, x.M, x.D);
    sqlite4_result_text(context, zBuf, -1, SQLITE4_TRANSIENT, 0);
  }
}

/*
**    strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
**
** Return a string described by FORMAT.  Conversions as follows:
**
**   %d  day of month
**   %f  ** fractional seconds  SS.SSS
**   %H  hour 00-24
**   %j  day of year 000-366
**   %J  ** Julian day number
**   %m  month 01-12
**   %M  minute 00-59
**   %s  seconds since 1970-01-01
**   %S  seconds 00-59
**   %w  day of week 0-6  sunday==0
**   %W  week of year 00-53
**   %Y  year 0000-9999
**   %%  %
*/
static void strftimeFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  DateTime x;
  u64 n;
  size_t i,j;
  char *z;
  sqlite4 *db;
  const char *zFmt = sqlite4_value_text(argv[0], 0);
  char zBuf[100];
  if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
  db = sqlite4_context_db_handle(context);
  for(i=0, n=1; zFmt[i]; i++, n++){
    if( zFmt[i]=='%' ){
      switch( zFmt[i+1] ){
        case 'd':
        case 'H':
        case 'm':
        case 'M':
        case 'S':
        case 'W':
          n++;
          /* fall thru */
        case 'w':
        case '%':
          break;
        case 'f':
          n += 8;
          break;
        case 'j':
          n += 3;
          break;
        case 'Y':
          n += 8;
          break;
        case 's':
        case 'J':
          n += 50;
          break;
        default:
          return;  /* ERROR.  return a NULL */
      }
      i++;
    }
  }
  testcase( n==sizeof(zBuf)-1 );
  testcase( n==sizeof(zBuf) );
  testcase( n==(u64)db->aLimit[SQLITE4_LIMIT_LENGTH]+1 );
  testcase( n==(u64)db->aLimit[SQLITE4_LIMIT_LENGTH] );
  if( n<sizeof(zBuf) ){
    z = zBuf;
  }else if( n>(u64)db->aLimit[SQLITE4_LIMIT_LENGTH] ){
    sqlite4_result_error_toobig(context);
    return;
  }else{
    z = sqlite4DbMallocRaw(db, (int)n);
    if( z==0 ){
      sqlite4_result_error_nomem(context);
      return;
    }
  }
  computeJD(&x);
  computeYMD_HMS(&x);
  for(i=j=0; zFmt[i]; i++){
    if( zFmt[i]!='%' ){
      z[j++] = zFmt[i];
    }else{
      i++;
      switch( zFmt[i] ){
        case 'd':  sqlite4_snprintf(&z[j],3,"%02d",x.D); j+=2; break;
        case 'f': {
          sqlite4_num rnd = x.s;
          int i1;
          rnd.e += 3;
          i1 = sqlite4_num_to_int64(rnd, 0);
          j += sqlite4_snprintf(&z[j], 7, "%02d.%03d", i1 / 1000, i1 % 1000);
          break;
        }
        case 'H':  sqlite4_snprintf(&z[j],3,"%02d",x.h); j+=2; break;
        case 'W': /* Fall thru */
        case 'j': {
          int nDay;             /* Number of days since 1st day of year */
          DateTime y = x;
          y.validJD = 0;
          y.M = 1;
          y.D = 1;
          computeJD(&y);
          nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
          if( zFmt[i]=='W' ){
            int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
            wd = (int)(((x.iJD+43200000)/86400000)%7);
            sqlite4_snprintf(&z[j],3,"%02d",(nDay+7-wd)/7);
            j += 2;
          }else{
            sqlite4_snprintf(&z[j],4,"%03d",nDay+1);
            j += 3;
          }
          break;
        }
        case 'J': {
          j += sqlite4_snprintf(&z[j],20,"%.16g",x.iJD/86400000.0);
          break;
        }
        case 'm':  sqlite4_snprintf(&z[j],3,"%02d",x.M); j+=2; break;
        case 'M':  sqlite4_snprintf(&z[j],3,"%02d",x.m); j+=2; break;
        case 's': {
          j += sqlite4_snprintf(&z[j],30,"%lld",
                                (i64)(x.iJD/1000 - 21086676*(i64)10000));
          break;
        }
        case 'S':  
          sqlite4_snprintf(&z[j], 3, "%02d", (int)sqlite4_num_to_int64(x.s, 0));
          j+=2; 
          break;
        case 'w': {
          z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
          break;
        }
        case 'Y': {
          sqlite4_snprintf(&z[j],5,"%04d",x.Y); j+=sqlite4Strlen30(&z[j]);
          break;
        }
        default:   z[j++] = '%'; break;
      }
    }
  }
  z[j] = 0;
  sqlite4_result_text(context, z, -1,
                      z==zBuf ? SQLITE4_TRANSIENT : SQLITE4_DYNAMIC, 0);
}

/*
** current_time()
**
** This function returns the same value as time('now').
*/
static void ctimeFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **NotUsed2
){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  timeFunc(context, 0, 0);
}

/*
** current_date()
**
** This function returns the same value as date('now').
*/
static void cdateFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **NotUsed2
){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  dateFunc(context, 0, 0);
}

/*
** current_timestamp()
**
** This function returns the same value as datetime('now').
*/
static void ctimestampFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **NotUsed2
){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  datetimeFunc(context, 0, 0);
}
#endif /* !defined(SQLITE4_OMIT_DATETIME_FUNCS) */

#ifdef SQLITE4_OMIT_DATETIME_FUNCS
/*
** If the library is compiled to omit the full-scale date and time
** handling (to get a smaller binary), the following minimal version
** of the functions current_time(), current_date() and current_timestamp()
** are included instead. This is to support column declarations that
** include "DEFAULT CURRENT_TIME" etc.
**
** This function uses the C-library functions time(), gmtime()
** and strftime(). The format string to pass to strftime() is supplied
** as the user-data for the function.
*/
static void currentTimeFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  time_t t;
  char *zFormat = (char *)sqlite4_context_appdata(context);
  sqlite4 *db;
  sqlite4_int64 iT;
  struct tm *pTm;
  struct tm sNow;
  char zBuf[20];

  UNUSED_PARAMETER(argc);
  UNUSED_PARAMETER(argv);

  db = sqlite4_context_db_handle(context);
  if( sqlite4OsCurrentTime(db->pEnv, &iT) ) return;
  t = iT/1000 - 10000*(sqlite4_int64)21086676;
#ifdef HAVE_GMTIME_R
  pTm = gmtime_r(&t, &sNow);
#else
  sqlite4_mutex_enter(sqlite4MutexAlloc(SQLITE4_MUTEX_STATIC_MASTER));
  pTm = gmtime(&t);
  if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
  sqlite4_mutex_leave(sqlite4MutexAlloc(SQLITE4_MUTEX_STATIC_MASTER));
#endif
  if( pTm ){
    strftime(zBuf, 20, zFormat, &sNow);
    sqlite4_result_text(context, zBuf, -1, SQLITE4_TRANSIENT, 0);
  }
}
#endif

/*
** This function registered all of the above C functions as SQL
** functions.  This should be the only routine in this file with
** external linkage.
*/
SQLITE4_PRIVATE void sqlite4RegisterDateTimeFunctions(sqlite4_env *pEnv){
  static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE4_OMIT_DATETIME_FUNCS
    FUNCTION(julianday,        -1, 0, 0, juliandayFunc ),
    FUNCTION(date,             -1, 0, 0, dateFunc      ),
    FUNCTION(time,             -1, 0, 0, timeFunc      ),
    FUNCTION(datetime,         -1, 0, 0, datetimeFunc  ),
    FUNCTION(strftime,         -1, 0, 0, strftimeFunc  ),
    FUNCTION(current_time,      0, 0, 0, ctimeFunc     ),
    FUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
    FUNCTION(current_date,      0, 0, 0, cdateFunc     ),
#else
    STR_FUNCTION(current_time,      0, "%H:%M:%S",          0, currentTimeFunc),
    STR_FUNCTION(current_date,      0, "%Y-%m-%d",          0, currentTimeFunc),
    STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
#endif
  };
  int i;
  FuncDefTable *pFuncTab = &pEnv->aGlobalFuncs;
  FuncDef *aFunc = (FuncDef*)aDateTimeFuncs;

  for(i=0; i<ArraySize(aDateTimeFuncs); i++){
    sqlite4FuncDefInsert(pFuncTab, &aFunc[i], 1);
  }
}

/************** End of date.c ************************************************/
/************** Begin file math.c ********************************************/
/*
** 2011 November 21
**
** The authors renounce all claim of copyright to this code and dedicate
** this code to the public domain.  In place of 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.
**
*************************************************************************
**
** Routines for doing math operations on sqlite4_num objects.
*/

#define SQLITE4_MX_EXP   999    /* Maximum exponent */
#define SQLITE4_NAN_EXP 2000    /* Exponent to use for NaN */

/*
** 1/10th the maximum value of an unsigned 64-bit integer
*/
#define TENTH_MAX (LARGEST_UINT64/10)

/*
** Adjust the significand and exponent of pA and pB so that the
** exponent is the same.
*/
static void adjustExponent(sqlite4_num *pA, sqlite4_num *pB){
  if( pA->e<pB->e ){
    sqlite4_num *t = pA;
    pA = pB;
    pB = t;
  }
  if( pB->m==0 ){
    pB->e = pA->e;
    return;
  }
  if( pA->m==0 ){
    pA->e = pB->e;
    return;
  }
  if( pA->e > pB->e+40 ){
    pB->approx = 1;
    pB->e = pA->e;
    pB->m = 0;
    return;
  }
  while( pA->e>pB->e && pB->m%10==0  ){
    pB->m /= 10;
    pB->e++;
  }
  while( pA->e>pB->e && pA->m<=TENTH_MAX ){
    pA->m *= 10;
    pA->e--;
  }
  while( pA->e>pB->e ){
    pB->m /= 10;
    pB->e++;
    pB->approx = 1;
  }
}

/*
** Add two numbers and return the result.
*/
SQLITE4_API sqlite4_num sqlite4_num_add(sqlite4_num A, sqlite4_num B){
  sqlite4_uint64 r;
  if( A.sign!=B.sign ){
    if( A.sign ){
      A.sign = 0;
      return sqlite4_num_sub(B,A);
    }else{
      B.sign = 0;
      return sqlite4_num_sub(A,B);
    }
  }
  if( A.e>SQLITE4_MX_EXP ){
    if( B.e>SQLITE4_MX_EXP && B.m==0 ) return B;
    return A;
  }
  if( B.e>SQLITE4_MX_EXP ){
    return B;
  }
  adjustExponent(&A, &B);
  r = A.m+B.m;
  A.approx |= B.approx;
  if( r>=A.m ){
    A.m = r;
  }else{
    if( A.approx==0 && (A.m%10)!=0 ) A.approx = 1;
    A.m /= 10;
    A.e++;
    if( A.e>SQLITE4_MX_EXP ) return A;
    if( A.approx==0 && (B.m%10)!=0 ) A.approx = 1;
    A.m += B.m/10;
  }
  return A;
}

/*
** Subtract the second number from the first and return the result.
*/
SQLITE4_API sqlite4_num sqlite4_num_sub(sqlite4_num A, sqlite4_num B){
  if( A.sign!=B.sign ){
    B.sign = A.sign;
    return sqlite4_num_add(A,B);
  }
  if( A.e>SQLITE4_MX_EXP || B.e>SQLITE4_MX_EXP ){
    A.e = SQLITE4_NAN_EXP;
    A.m = 0;
    return A;
  }
  adjustExponent(&A, &B);
  if( B.m > A.m ){
    sqlite4_num t = A;
    A = B;
    B = t;
    A.sign = 1-A.sign;
  }
  A.m -= B.m;
  A.approx |= B.approx;
  return A;
}

/*
** Return true if multiplying x and y will cause 64-bit unsigned overflow.
*/
static int multWillOverflow(sqlite4_uint64 x, sqlite4_uint64 y){
  sqlite4_uint64 xHi, xLo, yHi, yLo;
  xHi = x>>32;
  yHi = y>>32;
  if( xHi*yHi ) return 1;
  xLo = x & 0xffffffff;
  yLo = y & 0xffffffff;
  if( (xHi*yLo + yHi*xLo + (xLo*yLo>>32))>0xffffffff ) return 1;
  return 0;
}

/*
** Multiply two numbers and return the result.
*/
SQLITE4_API sqlite4_num sqlite4_num_mul(sqlite4_num A, sqlite4_num B){
  sqlite4_num r;

  if( A.e>SQLITE4_MX_EXP || B.e>SQLITE4_MX_EXP ){
    r.sign = A.sign ^ B.sign;
    r.m = (A.m && B.m) ? 1 : 0;
    r.e = SQLITE4_MX_EXP+1;
    r.approx = 0;
    return r;
  }
  if( A.m==0 ) return A;
  if( B.m==0 ) return B;
  while( A.m%10==0 ){ A.m /= 10; A.e++; }
  while( B.m%10==0 ){ B.m /= 10; B.e++; }
  while( A.m%5==0 && B.m%2==0 ){ A.m /= 5; A.e++; B.m /= 2; }
  while( B.m%5==0 && A.m%2==0 ){ B.m /= 5; B.e++; A.m /= 2; }
  r.sign = A.sign ^ B.sign;
  r.approx = A.approx | B.approx;
  while( multWillOverflow(A.m, B.m) ){
    r.approx = 1;
    if( A.m>B.m ){
      A.m /= 10;
      A.e++;
    }else{
      B.m /= 10;
      B.e++;
    }
  }
  r.m = A.m*B.m;
  r.e = A.e + B.e;
  return r;
}

/*
** Divide two numbers and return the result.
*/
SQLITE4_API sqlite4_num sqlite4_num_div(sqlite4_num A, sqlite4_num B){
  sqlite4_num r;
  if( A.e>SQLITE4_MX_EXP ){
    A.m = 0;
    return A;
  }
  if( B.e>SQLITE4_MX_EXP ){
    if( B.m!=0 ){
      r.m = 0;
      r.e = 0;
      r.sign = 0;
      r.approx = 1;
      return r;
    }
    return B;
  }
  if( B.m==0 ){
    r.sign = A.sign ^ B.sign;
    r.e = SQLITE4_NAN_EXP;
    r.m = 0;
    r.approx = 1;
    return r;
  }
  if( A.m==0 ){
    return A;
  }
  while( A.m<TENTH_MAX ){
    A.m *= 10;
    A.e--;
  }
  while( B.m%10==0 ){
    B.m /= 10;
    B.e++;
  }
  r.sign = A.sign ^ B.sign;
  r.approx = A.approx | B.approx;
  if( r.approx==0 && A.m%B.m!=0 ) r.approx = 1;
  r.m = A.m/B.m;
  r.e = A.e - B.e;
  return r;
}

/*
** Test if A is infinite.
*/
SQLITE4_API int sqlite4_num_isinf(sqlite4_num A){
  return A.e>SQLITE4_MX_EXP && A.m!=0;
}

/*
** Test if A is NaN.
*/
SQLITE4_API int sqlite4_num_isnan(sqlite4_num A){
  return A.e>SQLITE4_MX_EXP && A.m==0; 
}

/*
** Compare numbers A and B.  Return:
**
**    1     if A<B
**    2     if A==B
**    3     if A>B
**    0     the values are not comparible.
**
** NaN values are always incompariable.  Also +inf returns 0 when 
** compared with +inf and -inf returns 0 when compared with -inf.
*/
SQLITE4_API int sqlite4_num_compare(sqlite4_num A, sqlite4_num B){
  if( A.e>SQLITE4_MX_EXP ){
    if( A.m==0 ) return 0;
    if( B.e>SQLITE4_MX_EXP ){
      if( B.m==0 ) return 0;
      if( B.sign==A.sign ) return 0;
    }
    return A.sign ? 1 : 3;
  }
  if( B.e>SQLITE4_MX_EXP ){
    if( B.m==0 ) return 0;
    return B.sign ? 3 : 1;
  }
  if( A.sign!=B.sign ){
    if ( A.m==0 && B.m==0 ) return 2;
    return A.sign ? 1 : 3;
  }
  adjustExponent(&A, &B);
  if( A.sign ){
    sqlite4_num t = A;
    A = B;
    B = t;
  }
  if( A.e!=B.e ){
    return A.e<B.e ? 1 : 3;
  }
  if( A.m!=B.m ){
    return A.m<B.m ? 1 : 3;
  }
  return 2;
}

/*
** Round the value so that it has at most N digits to the right of the
** decimal point.
*/
SQLITE4_API sqlite4_num sqlite4_num_round(sqlite4_num x, int N){
  if( N<0 ) N = 0;
  if( x.e >= -N ) return x;
  if( x.e < -(N+30) ){
    memset(&x, 0, sizeof(x));
    return x;
  }
  while( x.e < -(N+1) ){
    x.m /= 10;
    x.e++;
  }
  x.m = (x.m+5)/10;
  x.e++;
  return x;
}

/*
** Convert text into a number and return that number.
**
** When converting from UTF16, this routine only looks at the
** least significant byte of each character.  It is assumed that
** the most significant byte of every character in the string
** is 0.  If that assumption is violated, then this routine can
** yield an anomalous result.  If the most significant byte of
** the final character is beyond the nIn examined bytes, then 
** it is treated as 0.
**
** Conversion stops at the first \000 character.  At most nIn bytes
** of zIn are examined.  Or if nIn is negative, up to a billion bytes
** are scanned, which we assume is more than will be found in any valid
** numeric string.
**
** If the value does not contain a decimal point or exponent, and is
** within the range of a signed 64-bit integer, it is guaranteed that
** the exponent of the returned value is zero.
*/
SQLITE4_API sqlite4_num sqlite4_num_from_text(
  const char *zIn,                /* Pointer to text to parse */
  int nIn,                        /* Size of zIn in bytes or (-ve) */
  unsigned flags,                 /* Conversion flags */
  int *pbReal                     /* OUT: True if text looks like a real */
){
  /* Return this value (NaN) if a parse error occurs. */
  static const sqlite4_num error_value = {0, 0, SQLITE4_MX_EXP+1, 0};

  static const i64 L10 = (LARGEST_INT64 / 10);
  int aMaxFinal[2] = {7, 8};
  static int one = 1;             /* Used to test machine endianness */
  int bRnd = 1;                   /* If mantissa overflows, round it */
  int bReal = 0;                  /* If text looks like a real */
  int seenRadix = 0;              /* True after decimal point has been parsed */
  int seenDigit = 0;              /* True after first non-zero digit parsed */
  int incr = 1;                   /* 1 for utf-8, 2 for utf-16 */
  sqlite4_num r;                  /* Value to return */
  char c;
  int i;

  assert( L10==922337203685477580 );
  
  memset(&r, 0, sizeof(r));
  if( nIn<0 ) nIn = 1000000000;
  c = flags & 0xf;
  if( c==0 || c==SQLITE4_UTF8 ){
    incr = 1;
  }else{
    if( c==SQLITE4_UTF16 ){ c = (3 - *(char*)&one); }
    assert( c==SQLITE4_UTF16LE || c==SQLITE4_UTF16BE );
    incr = 2;
    if( c==SQLITE4_UTF16BE ){
      zIn += 1;
      nIn -= 1;
    }
  }
  
  /* If the IGNORE_WHITESPACE flag is set, ignore any leading whitespace. */
  i = 0;
  if( flags & SQLITE4_IGNORE_WHITESPACE ){
    while( i<nIn && sqlite4Isspace(zIn[i]) ) i+=incr;
  }
  if( nIn<=i ) return error_value;

  /* Check for a leading '+' or '-' symbol. */
  if( zIn[i]=='-' ){
    r.sign = 1;
    i += incr;
  }else if( zIn[i]=='+' ){
    i += incr;
  }else if( flags & SQLITE4_NEGATIVE ){
    r.sign = 1;
  }
  if( nIn<=i ) return error_value;

  /* Check for the string "inf". This is a special case. */
  if( (flags & SQLITE4_INTEGER_ONLY)==0 
   && (nIn-i)>=incr*3
   && ((c=zIn[i])=='i' || c=='I')
   && ((c=zIn[i+incr])=='n' || c=='N')
   && ((c=zIn[i+incr*2])=='f' || c=='F')
  ){
    r.e = SQLITE4_MX_EXP+1;
    r.m = 1;
    bReal = 1;
    i += incr*3;
    goto finished;
  }

  for( ; i<nIn && (c = zIn[i])!=0; i+=incr){
    if( c>='0' && c<='9' ){
      int iDigit = (c - '0');

      if( iDigit==0 && seenDigit==0 ){
        /* Handle leading zeroes. If they occur to the right of the decimal
        ** point they can just be ignored. Otherwise, decrease the exponent
        ** by one.  */
        if( seenRadix ) r.e--;
        continue;
      }

      seenDigit = 1;
      if( r.e>0 || r.m>L10 || (r.m==L10 && iDigit>aMaxFinal[r.sign]) ){
        /* Mantissa overflow. */
        if( seenRadix==0 ) r.e++;
        if( iDigit!=0 ){ r.approx = 1; }
        if( bRnd ){
          if( iDigit>5 && r.m<((u64)LARGEST_INT64 + r.sign)) r.m++;
          bRnd = 0;
        }
        bReal = 1;
      }else{
        if( seenRadix ) r.e -= 1;
        r.m = (r.m*10) + iDigit;
      }

    }else{
      if( flags & SQLITE4_INTEGER_ONLY ) goto finished;

      if( c=='.' ){
        /* Permit only a single radix in each number */
        if( seenRadix ) goto finished;
        seenRadix = 1;
        bReal = 1;
      }else if( c=='e' || c=='E' ){
        int f = (flags & (SQLITE4_PREFIX_ONLY|SQLITE4_IGNORE_WHITESPACE));
        sqlite4_num exp;
        if( incr==2 ) f |= SQLITE4_UTF16LE; 
        if( (i+incr)>=nIn ) goto finished;
        i += incr;
        exp = sqlite4_num_from_text(&zIn[i], nIn-i, f, 0);
        if( sqlite4_num_isnan(exp) ) goto finished;
        if( exp.e || exp.m>999 ) goto finished;
        bReal = 1;
        r.e += (int)(exp.m) * (exp.sign ? -1 : 1);
        i = nIn;
        break;
      }else{
        goto finished;
      }
    }
  }

finished:

  /* Check for a parse error. If one has occurred, set the return value
  ** to NaN.  */
  if( (flags & SQLITE4_PREFIX_ONLY)==0 && i<nIn && zIn[i] ){
    if( flags & SQLITE4_IGNORE_WHITESPACE ){
      while( i<nIn && sqlite4Isspace(zIn[i]) ) i += incr;
    }
    if( i<nIn && zIn[i] ){
      r.e = SQLITE4_MX_EXP+1;
      r.m = 0;
    }
  }


  if( pbReal ) *pbReal = bReal;
  return r;
}

/*
** Convert an sqlite4_int64 to a number and return that number.
*/
SQLITE4_API sqlite4_num sqlite4_num_from_int64(sqlite4_int64 n){
  sqlite4_num r;
  r.approx = 0;
  r.e = 0;
  r.sign = n < 0;
  if( n>=0 ){
    r.m = n;
  }else if( n!=SMALLEST_INT64 ){
    r.m = -n;
  }else{
    r.m = 1+(u64)LARGEST_INT64;
  }
  return r;
}

/*
** Return an sqlite4_num containing a value as close as possible to the
** double value passed as the only argument.
**
** TODO: This is an inefficient placeholder implementation only.
*/
SQLITE4_API sqlite4_num sqlite4_num_from_double(double d){
  const double large = (double)LARGEST_UINT64;
  const double large10 = (double)TENTH_MAX;
  sqlite4_num x = {0, 0, 0, 0};

  /* TODO: How should this be set? */
  x.approx = 1;

  if( d<0.0 ){
    x.sign = 1;
    d = d*-1.0;
  }

  while( d>large || (d>1.0 && d==(i64)d) ){
    d = d / 10.0;
    x.e++;
  }

  while( d<large10 && d!=(double)((i64)d) ){
    d = d * 10.0;
    x.e--;
  }
  x.m = (u64)d;

  return x;
}

/*
** Convert the number passed as the first argument to a signed 32-bit
** integer and return the value. If the second argument is not NULL,
** then set the value that it points to 1 if data was lost as part
** of the conversion, or 0 otherwise.
**
** Values round towards 0. If the number is outside the range that a
** signed 32-bit integer can represent, it is clamped to be inside
** that range.
*/
SQLITE4_API int sqlite4_num_to_int32(sqlite4_num num, int *pbLossy){
  sqlite4_int64 iVal; 
  iVal = sqlite4_num_to_int64(num, pbLossy);
  if( iVal<SMALLEST_INT32 ){
    if( pbLossy ) *pbLossy = 1;
    return SMALLEST_INT32;
  }else if( iVal>LARGEST_INT32 ){
    if( pbLossy ) *pbLossy = 1;
    return LARGEST_INT32;
  }else{
    return (int)iVal;
  }
}

SQLITE4_API int sqlite4_num_to_double(sqlite4_num num, double *pr){
  double rRet;
  int i;
  rRet = num.m;
  if( num.sign ) rRet = rRet*-1;
  for(i=0; i<num.e; i++){
    rRet = rRet * 10.0;
  }
  for(i=num.e; i<0; i++){
    rRet = rRet / 10.0;
  }
  *pr = rRet;
  return SQLITE4_OK;
}

/*
** Convert the number passed as the first argument to a signed 64-bit
** integer and return the value. If the second argument is not NULL,
** then set the value that it points to 1 if data was lost as part
** of the conversion, or 0 otherwise.
**
** Values round towards 0. If the number is outside the range that a
** signed 64-bit integer can represent, it is clamped to be inside
** that range.
*/
SQLITE4_API sqlite4_int64 sqlite4_num_to_int64(sqlite4_num num, int *pbLossy){
  static const i64 L10 = (LARGEST_INT64 / 10);
  u64 iRet;
  int i;
  iRet = num.m;

  if( pbLossy ) *pbLossy = num.approx;
  for(i=0; i<num.e; i++){
    if( iRet>L10 ) goto overflow;
    iRet = iRet * 10;
  }
  for(i=num.e; i<0; i++){
    if( pbLossy && (iRet % 10) ) *pbLossy = 1;
    iRet = iRet / 10;
  }

  if( num.sign ){
    if( iRet>(u64)LARGEST_INT64+1 ) goto overflow;
    return -(i64)iRet;
  }else{
    if( iRet>(u64)LARGEST_INT64 ) goto overflow; 
    return (i64)iRet;
  }

overflow:
  if( pbLossy ) *pbLossy = 1;
  return num.sign ? -LARGEST_INT64-1 : LARGEST_INT64;
}


/*
** Convert an integer into text in the buffer supplied. The
** text is zero-terminated and right-justified in the buffer.
** A pointer to the first character of text is returned.
**
** The buffer needs to be at least 21 bytes in length.
*/
static char *renderInt(sqlite4_uint64 v, char *zBuf, int nBuf){
  int i = nBuf-1;;
  zBuf[i--] = 0;
  do{
    zBuf[i--] = (v%10) + '0';
    v /= 10;
  }while( v>0 );
  return zBuf+(i+1);
}

/*
** Remove trailing zeros from a string.
*/
static void removeTrailingZeros(char *z, int *pN){
  int i = *pN;
  while( i>0 && z[i-1]=='0' ) i--;
  z[i] = 0;
  *pN = i;
}

/*
** Convert a number into text.  Store the result in zOut[].  The
** zOut buffer must be at laest 30 characters in length.  The output
** will be zero-terminated.
*/
SQLITE4_API int sqlite4_num_to_text(sqlite4_num x, char *zOut, int bReal){
  char zBuf[24];
  char *zNum;
  int n;
  static const char zeros[] = "0000000000000000000000000";

  char *z = zOut;
  
  if( x.sign && x.m>0 ){
    /* Add initial "-" for negative non-zero values */
    z[0] = '-';
    z++;
  }
  if( x.e>SQLITE4_MX_EXP ){
    /* Handle NaN and infinite values */
    if( x.m==0 ){
      memcpy(z, "NaN", 4);
    }else{
      memcpy(z, "inf", 4);
    }
    return (z - zOut)+3;
  }
  if( x.m==0 ){
    if( bReal ){
      memcpy(z, "0.0", 4);
    }else{
      memcpy(z, "0", 2);
    }
    return 1+(z-zOut);
  }
  zNum = renderInt(x.m, zBuf, sizeof(zBuf));
  n = &zBuf[sizeof(zBuf)-1] - zNum;
  if( x.e>=0 && x.e+n<=25 ){
    /* Integer values with up to 25 digits */
    memcpy(z, zNum, n+1);
    z += n;
    if( x.e>0 ){
      memcpy(z, zeros, x.e);
      z += x.e;
      z[0] = 0;
    }
    if( bReal ){
      memcpy(z, ".0", 3);
      z += 2;
    }
    return (z - zOut);
  }
  if( x.e<0 && n+x.e > 0 ){
    /* Fractional values where the decimal point occurs within the
    ** significant digits.  ex:  12.345 */
    int m = n+x.e;
    memcpy(z, zNum, m);
    z += m;
    zNum += m;
    n -= m;
    removeTrailingZeros(zNum, &n);
    if( n>0 ){
      z[0] = '.';
      z++;
      memcpy(z, zNum, n);
      z += n;
      z[0] = 0;
    }else{
      if( bReal ){
        memcpy(z, ".0", 3);
        z += 2;
      }else{
        z[0] = 0;
      }
    }
    return (z - zOut);
  }
  if( x.e<0 && x.e >= -n-5 ){
    /* Values less than 1 and with no more than 5 subsequent zeros prior
    ** to the first significant digit.  Ex:  0.0000012345 */
    int j = -(n + x.e);
    memcpy(z, "0.", 2);
    z += 2;
    if( j>0 ){
      memcpy(z, zeros, j);
      z += j;
    }
    removeTrailingZeros(zNum, &n);
    memcpy(z, zNum, n);
    z += n;
    z[0] = 0;
    return (z - zOut);
  }
  /* Exponential notation from here to the end.  ex:  1.234e-15 */
  z[0] = zNum[0];
  z++;
  if( n>1 ){
    int nOrig = n;
    removeTrailingZeros(zNum, &n);
    x.e += nOrig - n;
  }
  if( n!=1 ){
    /* Two or or more significant digits.  ex: 1.23e17 */
    *z++ = '.';
    memcpy(z, zNum+1, n-1);
    z += n-1;
    x.e += n-1;
  }
  *z++ = 'e';
  if( x.e<0 ){
    *z++ = '-';
    x.e = -x.e;
  }else{
    *z++ = '+';
  }
  zNum = renderInt(x.e&0x7fff, zBuf, sizeof(zBuf));
  while( (z[0] = zNum[0])!=0 ){ z++; zNum++; }
  return (z-zOut);
}

/************** End of math.c ************************************************/
/************** Begin file os.c **********************************************/
/*
** 2005 November 29
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains OS interface code that is common to all
** architectures.
*/
#define _SQLITE4_OS_C_ 1
#undef _SQLITE4_OS_C_

#if SQLITE4_OS_UNIX
#include <sys/time.h>
#endif

/*
** The following variable, if set to a non-zero value, is interpreted as
** the number of seconds since 1970 and is used to set the result of
** sqlite4OsCurrentTime() during testing.
*/
SQLITE4_API unsigned int sqlite4_current_time = 0; /* Fake system time */
SQLITE4_PRIVATE int sqlite4OsCurrentTime(sqlite4_env *pEnv, sqlite4_uint64 *pTimeOut){
  static const sqlite4_uint64 unixEpoch = 24405875*(sqlite4_int64)8640000;
  int rc = SQLITE4_OK;
  if( sqlite4_current_time ){
    *pTimeOut = unixEpoch + (sqlite4_uint64)sqlite4_current_time * 1000;
    return SQLITE4_OK;
  }
#if SQLITE4_OS_UNIX
  struct timeval sNow;
  if( gettimeofday(&sNow, 0)==0 ){
    *pTimeOut = unixEpoch + 1000*(sqlite4_int64)sNow.tv_sec + sNow.tv_usec/1000;
  }else{
    rc = SQLITE4_ERROR;
  }
  UNUSED_PARAMETER(pEnv);
#endif
#if SQLITE4_OS_WIN
  FILETIME ft;
  static const sqlite4_int64 winFiletimeEpoch =
                                 23058135*(sqlite4_int64)8640000;
  /* 2^32 - to avoid use of LL and warnings in gcc */
  static const sqlite4_int64 max32BitValue = 
      (sqlite4_int64)2000000000 + (sqlite4_int64)2000000000
         + (sqlite4_int64)294967296;
  GetSystemTimeAsFileTime( &ft );
  *pTimeOut = winFiletimeEpoch +
                ((((sqlite4_int64)ft.dwHighDateTime)*max32BitValue) + 
                   (sqlite4_int64)ft.dwLowDateTime)/(sqlite4_int64)10000;
  UNUSED_PARAMETER(pEnv);
#endif
  return rc;
}

/*
** Write nByte bytes of randomness into zBufOut[].  This is used to initialize
** the PRNGs.  nByte will always be 8.
*/
SQLITE4_PRIVATE int sqlite4OsRandomness(sqlite4_env *pEnv, int nByte, unsigned char *zBufOut){
  static sqlite4_uint64 cnt = 0;
  unsigned char *p;
  int i;
  sqlite4_uint64 now;
  sqlite4_uint64 x = 0;

#if 0 && SQLITE4_OS_UNIX
  int fd = open("/dev/urandom", O_RDONLY, 0);
  if( fd>=0 ){
    read(fd, zBufOut, nByte);
    close(fd);
  }
  x = getpid();
#endif
  sqlite4OsCurrentTime(pEnv, &now);
  x ^= now;
  memset(zBufOut, 0, nByte);
  cnt++;
  x ^= cnt;
  p = (unsigned char*)&x;
  for(i=0; i<8; i++) zBufOut[i%nByte] ^= p[i];
    
  return SQLITE4_OK;
}

/*
** This function is a wrapper around the OS specific implementation of
** sqlite4_os_init(). The purpose of the wrapper is to provide the
** ability to simulate a malloc failure, so that the handling of an
** error in sqlite4_os_init() by the upper layers can be tested.
*/
SQLITE4_PRIVATE int sqlite4OsInit(sqlite4_env *pEnv){
  void *p = sqlite4_malloc(pEnv, 10);
  if( p==0 ) return SQLITE4_NOMEM;
  sqlite4_free(pEnv, p);
  sqlite4OsRandomness(pEnv, 8, (unsigned char*)&pEnv->prngX);
  return SQLITE4_OK; /*sqlite4_os_init();*/
}

/************** End of os.c **************************************************/
/************** Begin file fault.c *******************************************/
/*
** 2008 Jan 22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code to support the concept of "benign" 
** malloc failures (when the xMalloc() or xRealloc() method of the
** sqlite4_mem_methods structure fails to allocate a block of memory
** and returns 0). 
**
** Most malloc failures are non-benign. After they occur, SQLite
** abandons the current operation and returns an error code (usually
** SQLITE4_NOMEM) to the user. However, sometimes a fault is not necessarily
** fatal. For example, if a malloc fails while resizing a hash table, this 
** is completely recoverable simply by not carrying out the resize. The 
** hash table will continue to function normally.  So a malloc failure 
** during a hash table resize is a benign fault.
*/


#ifndef SQLITE4_OMIT_BUILTIN_TEST
/*
** This (sqlite4EndBenignMalloc()) is called by SQLite code to indicate that
** subsequent malloc failures are benign. A call to sqlite4EndBenignMalloc()
** indicates that subsequent malloc failures are non-benign.
*/
SQLITE4_PRIVATE void sqlite4BeginBenignMalloc(sqlite4_env *pEnv){
  sqlite4_mm_benign_failures(pEnv->pMM, 1);
}
SQLITE4_PRIVATE void sqlite4EndBenignMalloc(sqlite4_env *pEnv){
  sqlite4_mm_benign_failures(pEnv->pMM, 0);
}
#endif   /* #ifndef SQLITE4_OMIT_BUILTIN_TEST */

/************** End of fault.c ***********************************************/
/************** Begin file mem.c *********************************************/
/*
** 2013-01-01
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains the implementation of the "sqlite4_mm" memory
** allocator object.
*/

/*************************************************************************
** The SQLITE4_MM_SYSTEM memory allocator.  This allocator uses the
** malloc/realloc/free from the system library.  It also tries to use
** the memory allocation sizer from the system library if such a routine
** exists.  If there is no msize in the system library, then each allocation
** is increased in size by 8 bytes and the size of the allocation is stored
** in those initial 8 bytes.
**
** C-preprocessor macro summary:
**
**    HAVE_MALLOC_USABLE_SIZE     The configure script sets this symbol if
**                                the malloc_usable_size() interface exists
**                                on the target platform.  Or, this symbol
**                                can be set manually, if desired.
**                                If an equivalent interface exists by
**                                a different name, using a separate -D
**                                option to rename it.  This symbol will
**                                be enabled automatically on windows
**                                systems, and malloc_usable_size() will
**                                be redefined to _msize(), unless the
**                                SQLITE4_WITHOUT_MSIZE macro is defined.
**    
**    SQLITE4_WITHOUT_ZONEMALLOC   Some older macs lack support for the zone
**                                memory allocator.  Set this symbol to enable
**                                building on older macs.
**
**    SQLITE4_WITHOUT_MSIZE        Set this symbol to disable the use of
**                                _msize() on windows systems.  This might
**                                be necessary when compiling for Delphi,
**                                for example.
*/

/*
** Windows systems have malloc_usable_size() but it is called _msize().
** The use of _msize() is automatic, but can be disabled by compiling
** with -DSQLITE4_WITHOUT_MSIZE
*/
#if !defined(HAVE_MALLOC_USABLE_SIZE) && SQLITE4_OS_WIN \
      && !defined(SQLITE4_WITHOUT_MSIZE)
# define HAVE_MALLOC_USABLE_SIZE 1
# define SQLITE4_MALLOCSIZE _msize
#endif

#if defined(__APPLE__) && !defined(SQLITE4_WITHOUT_ZONEMALLOC)

/*
** Use the zone allocator available on apple products unless the
** SQLITE4_WITHOUT_ZONEMALLOC symbol is defined.
*/
#include <sys/sysctl.h>
#include <malloc/malloc.h>
#include <libkern/OSAtomic.h>
static malloc_zone_t* _sqliteZone_;
#define SQLITE4_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
#define SQLITE4_FREE(x) malloc_zone_free(_sqliteZone_, (x));
#define SQLITE4_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
#define SQLITE4_MALLOCSIZE(x) \
        (_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))

#else /* if not __APPLE__ */

/*
** Use standard C library malloc and free on non-Apple systems.  
** Also used by Apple systems if SQLITE4_WITHOUT_ZONEMALLOC is defined.
*/
#define SQLITE4_MALLOC(x)    malloc(x)
#define SQLITE4_FREE(x)      free(x)
#define SQLITE4_REALLOC(x,y) realloc((x),(y))

#ifdef HAVE_MALLOC_USABLE_SIZE
# ifndef SQLITE4_MALLOCSIZE
#  include <malloc.h>
#  define SQLITE4_MALLOCSIZE(x) malloc_usable_size(x)
# endif
#else
# undef SQLITE4_MALLOCSIZE
#endif

#endif /* __APPLE__ or not __APPLE__ */

/*
** Implementations of core routines
*/
static void *mmSysMalloc(sqlite4_mm *pMM, sqlite4_size_t iSize){
#ifdef SQLITE4_MALLOCSIZE
  return SQLITE4_MALLOC(iSize);
#else
  unsigned char *pRes = SQLITE4_MALLOC(iSize+8);
  if( pRes ){
    *(sqlite4_size_t*)pRes = iSize;
    pRes += 8;
  }
  return pRes;
#endif
}
static void *mmSysRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSz){
#ifdef SQLITE4_MALLOCSIZE
  return SQLITE4_REALLOC(pOld, iSz);
#else
  unsigned char *pRes;
  if( pOld==0 ) return mmSysMalloc(pMM, iSz);
  pRes = (unsigned char*)pOld;
  pRes -= 8;
  pRes = SQLITE4_REALLOC(pRes, iSz+8);
  if( pRes ){
    *(sqlite4_size_t*)pRes = iSz;
    pRes += 8;
  }
  return pRes;
#endif 
}
static void mmSysFree(sqlite4_mm *pNotUsed, void *pOld){
#ifdef SQLITE4_MALLOCSIZE
  SQLITE4_FREE(pOld);
#else
  unsigned char *pRes;
  if( pOld==0 ) return;
  pRes = (unsigned char *)pOld;
  pRes -= 8;
  SQLITE4_FREE(pRes);
#endif
}
static sqlite4_size_t mmSysMsize(sqlite4_mm *pNotUsed, void *pOld){
#ifdef SQLITE4_MALLOCSIZE
  return SQLITE4_MALLOCSIZE(pOld);
#else
  unsigned char *pX;
  if( pOld==0 ) return 0;
  pX = (unsigned char *)pOld;
  pX -= 8;
  return *(sqlite4_size_t*)pX;
#endif
}

static const sqlite4_mm_methods mmSysMethods = {
  /* iVersion */    1,
  /* xMalloc  */    mmSysMalloc,
  /* xRealloc */    mmSysRealloc,
  /* xFree    */    mmSysFree,
  /* xMsize   */    mmSysMsize,
  /* xMember  */    0,
  /* xBenign  */    0,
  /* xStat    */    0,
  /* xCtrl    */    0,
  /* xFinal   */    0
};
SQLITE4_PRIVATE sqlite4_mm sqlite4MMSystem =  {
  /* pMethods */    &mmSysMethods
};

/* The system memory allocator is the default. */
SQLITE4_API sqlite4_mm *sqlite4_mm_default(void){ return &sqlite4MMSystem; }

/*************************************************************************
** The SQLITE4_MM_OVERFLOW memory allocator.
**
** This memory allocator has two child memory allocators, A and B.  Always
** try to fulfill the request using A first, then overflow to B if the request
** on A fails.  The A allocator must support the xMember method.
*/
struct mmOvfl {
  sqlite4_mm base;    /* Base class - must be first */
  int (*xMemberOfA)(sqlite4_mm*, const void*);
  sqlite4_mm *pA;     /* Primary memory allocator */
  sqlite4_mm *pB;     /* Backup memory allocator in case pA fails */
};

static void *mmOvflMalloc(sqlite4_mm *pMM, sqlite4_size_t iSz){
  const struct mmOvfl *pOvfl = (const struct mmOvfl*)pMM;
  void *pRes;
  pRes = pOvfl->pA->pMethods->xMalloc(pOvfl->pA, iSz);
  if( pRes==0 ){
    pRes = pOvfl->pB->pMethods->xMalloc(pOvfl->pB, iSz);
  }
  return pRes;
}
static void *mmOvflRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSz){
  const struct mmOvfl *pOvfl;
  void *pRes, *pAlt;
  if( pOld==0 ) return mmOvflMalloc(pMM, iSz);
  pOvfl = (const struct mmOvfl*)pMM;
  if( pOvfl->xMemberOfA(pOvfl->pA, pOld) ){
    pRes = pOvfl->pA->pMethods->xRealloc(pOvfl->pA, pOld, iSz);
    if( pRes==0 && (pAlt = pOvfl->pB->pMethods->xMalloc(pOvfl->pB, iSz))!=0 ){
      sqlite4_size_t nOld = pOvfl->pA->pMethods->xMsize(pOvfl->pA, pOld);
      assert( nOld<iSz );
      memcpy(pAlt, pOld, (size_t)nOld);
      pOvfl->pA->pMethods->xFree(pOvfl->pA, pOld);
      pRes = pAlt;
    }
  }else{
    pRes = pOvfl->pB->pMethods->xRealloc(pOvfl->pB, pOld, iSz);
  }
  return pRes;
}
static void mmOvflFree(sqlite4_mm *pMM, void *pOld){
  const struct mmOvfl *pOvfl;
  if( pOld==0 ) return;
  pOvfl = (const struct mmOvfl*)pMM;
  if( pOvfl->xMemberOfA(pOvfl->pA, pOld) ){
    pOvfl->pA->pMethods->xFree(pOvfl->pA, pOld);
  }else{
    pOvfl->pB->pMethods->xFree(pOvfl->pB, pOld);
  }
}
static sqlite4_size_t mmOvflMsize(sqlite4_mm *pMM, void *pOld){
  const struct mmOvfl *pOvfl;
  sqlite4_size_t iSz;
  if( pOld==0 ) return 0;
  pOvfl = (const struct mmOvfl*)pMM;
  if( pOvfl->xMemberOfA(pOvfl->pA, pOld) ){
    iSz = sqlite4_mm_msize(pOvfl->pA, pOld);
  }else{
    iSz = sqlite4_mm_msize(pOvfl->pB, pOld);
  }
  return iSz;
}
static int mmOvflMember(sqlite4_mm *pMM, const void *pOld){
  const struct mmOvfl *pOvfl;
  int iRes;
  if( pOld==0 ) return 0;
  pOvfl = (const struct mmOvfl*)pMM;
  if( pOvfl->xMemberOfA(pOvfl->pA, pOld) ){
    iRes = 1;
  }else{
    iRes = sqlite4_mm_member(pOvfl->pB, pOld);
  }
  return iRes;
}
static void mmOvflBenign(sqlite4_mm *pMM, int bEnable){
  struct mmOvfl *pOvfl = (struct mmOvfl*)pMM;
  sqlite4_mm_benign_failures(pOvfl->pA, bEnable);
  sqlite4_mm_benign_failures(pOvfl->pB, bEnable);
}
static void mmOvflFinal(sqlite4_mm *pMM){
  struct mmOvfl *pOvfl = (struct mmOvfl*)pMM;
  sqlite4_mm *pA = pOvfl->pA;
  sqlite4_mm *pB = pOvfl->pB;
  mmOvflFree(pMM, pMM);
  sqlite4_mm_destroy(pA);
  sqlite4_mm_destroy(pB);
}
static const sqlite4_mm_methods mmOvflMethods = {
  /* iVersion */    1,
  /* xMalloc  */    mmOvflMalloc,
  /* xRealloc */    mmOvflRealloc,
  /* xFree    */    mmOvflFree,
  /* xMsize   */    mmOvflMsize,
  /* xMember  */    mmOvflMember,
  /* xBenign  */    mmOvflBenign,
  /* xStat    */    0,
  /* xCtrl    */    0,
  /* xFinal   */    mmOvflFinal
};
static sqlite4_mm *mmOvflNew(sqlite4_mm *pA, sqlite4_mm *pB){
  struct mmOvfl *pOvfl;
  if( pA->pMethods->xMember==0 ) return 0;
  pOvfl = sqlite4_mm_malloc(pA, sizeof(*pOvfl));
  if( pOvfl==0 ){
    pOvfl = sqlite4_mm_malloc(pB, sizeof(*pOvfl));
  }
  if( pOvfl ){
    pOvfl->base.pMethods = &mmOvflMethods;
    pOvfl->xMemberOfA = pA->pMethods->xMember;
    pOvfl->pA = pA;
    pOvfl->pB = pB;
  }
  return &pOvfl->base;
}

/*************************************************************************
** The SQLITE4_MM_STATS memory allocator.
*/

/*
** Number of available statistics. Statistics are assigned ids starting at
** one, not zero.
*/
#define MM_STATS_NSTAT 8

struct mmStats {
  sqlite4_mm base;                /* Base class.  Must be first. */
  sqlite4_mm *p;                  /* Underlying allocator object */
  sqlite4_mutex *mutex;           /* Mutex protecting aStat[] (or NULL) */

  i64 nOut;                       /* Number of bytes outstanding */
  i64 nOutHw;                     /* Highwater mark of nOut */
  i64 nUnit;                      /* Number of allocations outstanding */
  i64 nUnitHw;                    /* Highwater mark of nUnit */
  i64 nMaxRequest;                /* Largest request seen so far */
  i64 nFault;                     /* Number of malloc or realloc failures */
};

static void updateStatsMalloc(
  struct mmStats *pStats, 
  void *pNew, 
  sqlite4_size_t iSz
){
  /* Statistic SQLITE4_MMSTAT_SIZE records the largest allocation request
  ** that has been made so far. So if iSz is larger than the current value,
  ** set MMSTAT_SIZE to iSz now. This statistic is updated regardless of 
  ** whether or not the allocation succeeded.  */ 
  if( iSz>pStats->nMaxRequest ){
    pStats->nMaxRequest = iSz;
  }

  /* If the allocation succeeded, increase the number of allocations and
  ** bytes outstanding accordingly. Also update the highwater marks if
  ** required. If the allocation failed, increment the fault count.  */
  if( pNew ){
    pStats->nOut += sqlite4_mm_msize(pStats->p, pNew);
    pStats->nUnit += 1;
    if( pStats->nOut>pStats->nOutHw ) pStats->nOutHw = pStats->nOut;
    if( pStats->nUnit>pStats->nUnitHw ) pStats->nUnitHw = pStats->nUnit;
  }else{
    pStats->nFault++;
  }
}

static void *mmStatsMalloc(sqlite4_mm *pMM, sqlite4_size_t iSz){
  struct mmStats *pStats = (struct mmStats*)pMM;
  void *pRet;

  pRet = sqlite4_mm_malloc(pStats->p, iSz);
  sqlite4_mutex_enter(pStats->mutex);
  updateStatsMalloc(pStats, pRet, iSz);
  sqlite4_mutex_leave(pStats->mutex);
  return pRet;
}

static void mmStatsFree(sqlite4_mm *pMM, void *pOld){
  struct mmStats *pStats = (struct mmStats*)pMM;
  sqlite4_mutex_enter(pStats->mutex);
  if( pOld ){
    sqlite4_size_t nByte = sqlite4_mm_msize(pMM, pOld);
    pStats->nOut -= nByte;
    pStats->nUnit -= 1;
  }
  sqlite4_mutex_leave(pStats->mutex);
  sqlite4_mm_free(pStats->p, pOld);
}

static void *mmStatsRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSz){
  struct mmStats *pStats = (struct mmStats*)pMM;
  sqlite4_size_t nOrig = (pOld ? sqlite4_mm_msize(pStats->p, pOld) : 0);
  void *pRet;

  pRet = sqlite4_mm_realloc(pStats->p, pOld, iSz);

  sqlite4_mutex_enter(pStats->mutex);
  if( pRet ){
    pStats->nOut -= nOrig;
    if( pOld ) pStats->nUnit--;
  }
  updateStatsMalloc(pStats, pRet, iSz);
  sqlite4_mutex_leave(pStats->mutex);

  return pRet;
}

static sqlite4_size_t mmStatsMsize(sqlite4_mm *pMM, void *pOld){
  struct mmStats *pStats = (struct mmStats*)pMM;
  return sqlite4_mm_msize(pStats->p, pOld);
}

static int mmStatsMember(sqlite4_mm *pMM, const void *pOld){
  struct mmStats *pStats = (struct mmStats*)pMM;
  return sqlite4_mm_member(pStats->p, pOld);
}

/*
** sqlite4_mm_methods.xBenign method.
*/
static void mmStatsBenign(sqlite4_mm *pMM, int bBenign){
  struct mmStats *pStats = (struct mmStats *)pMM;
  sqlite4_mm_benign_failures(pStats->p, bBenign);
}


static sqlite4_int64 mmStatsStat(
  sqlite4_mm *pMM, 
  unsigned int eType, 
  unsigned int flags
){
  struct mmStats *pStats = (struct mmStats*)pMM;
  i64 iRet = 0;
  sqlite4_mutex_enter(pStats->mutex);
  switch( eType ){
    case SQLITE4_MMSTAT_OUT: {
      iRet = pStats->nOut;
      break;
    }
    case SQLITE4_MMSTAT_OUT_HW: {
      iRet = pStats->nOutHw;
      if( flags & SQLITE4_MMSTAT_RESET ) pStats->nOutHw = pStats->nOut;
      break;
    }
    case SQLITE4_MMSTAT_UNITS: {
      iRet = pStats->nUnit;
      break;
    }
    case SQLITE4_MMSTAT_UNITS_HW: {
      iRet = pStats->nUnitHw;
      if( flags & SQLITE4_MMSTAT_RESET ) pStats->nUnitHw = pStats->nUnit;
      break;
    }
    case SQLITE4_MMSTAT_SIZE: {
      iRet = pStats->nMaxRequest;
      if( flags & SQLITE4_MMSTAT_RESET ) pStats->nMaxRequest = 0;
      break;
    }
    case SQLITE4_MMSTAT_MEMFAULT:
    case SQLITE4_MMSTAT_FAULT: {
      iRet = pStats->nFault;
      if( flags & SQLITE4_MMSTAT_RESET ) pStats->nFault = 0;
      break;
    }
  }
  sqlite4_mutex_leave(pStats->mutex);
  return iRet;
}

static int mmStatsCtrl(sqlite4_mm *pMM, unsigned int eType, va_list ap){
  struct mmStats *pStats = (struct mmStats*)pMM;
  return sqlite4_mm_control_va(pStats->p, eType, ap);
}

/*
** Destroy the allocator object passed as the first argument.
*/
static void mmStatsFinal(sqlite4_mm *pMM){
  struct mmStats *pStats = (struct mmStats*)pMM;
  sqlite4_mm *p = pStats->p;
  sqlite4_mm_free(p, pStats);
  sqlite4_mm_destroy(p);
}

static const sqlite4_mm_methods mmStatsMethods = {
  /* iVersion */    1,
  /* xMalloc  */    mmStatsMalloc,
  /* xRealloc */    mmStatsRealloc,
  /* xFree    */    mmStatsFree,
  /* xMsize   */    mmStatsMsize,
  /* xMember  */    mmStatsMember,
  /* xBenign  */    mmStatsBenign,
  /* xStat    */    mmStatsStat,
  /* xCtrl    */    mmStatsCtrl,
  /* xFinal   */    mmStatsFinal
};

/*
** Allocate a new stats allocator.
*/
static sqlite4_mm *mmStatsNew(sqlite4_mm *p){
  struct mmStats *pNew;

  pNew = (struct mmStats *)sqlite4_mm_malloc(p, sizeof(*pNew));
  if( pNew ){
    memset(pNew, 0, sizeof(*pNew));
    pNew->p = p;
    pNew->base.pMethods = &mmStatsMethods;
  }

  return (sqlite4_mm *)pNew;
}


/*************************************************************************
** The SQLITE4_MM_ONESIZE memory allocator.
**
** All memory allocations are rounded up to a single size, "sz".  A request
** for an allocation larger than sz bytes fails.  All allocations come out
** of a single initial buffer with "cnt" chunks of "sz" bytes each.
**
** Space to hold the sqlite4_mm object comes from the first block in the
** allocation space.
*/
struct mmOnesz {
  sqlite4_mm base;            /* Base class.  Must be first. */
  const void *pSpace;         /* Space to allocate */
  const void *pLast;          /* Last possible allocation */
  struct mmOneszBlock *pFree; /* List of free blocks */
  int sz;                     /* Size of each allocation */
  unsigned nFailSize;         /* Failures due to size */
  unsigned nFailMem;          /* Failures due to OOM */
  unsigned nSlot;             /* Number of available slots */
  unsigned nUsed;             /* Current number of slots in use */
  unsigned nUsedHw;           /* Highwater mark for slots in use */
  sqlite4_size_t mxSize;      /* Maximum request size */
};

/* A free block in the buffer */
struct mmOneszBlock {
  struct mmOneszBlock *pNext;  /* Next on the freelist */
};

static void *mmOneszMalloc(sqlite4_mm *pMM, sqlite4_size_t iSz){
  struct mmOnesz *pOnesz = (struct mmOnesz*)pMM;
  void *pRes;
  if( iSz>pOnesz->mxSize ) pOnesz->mxSize = iSz;
  if( iSz>pOnesz->sz ){ pOnesz->nFailSize++; return 0; }
  if( pOnesz->pFree==0 ){ pOnesz->nFailMem++;  return 0; }
  pOnesz->nUsed++;
  if( pOnesz->nUsed>pOnesz->nUsedHw ) pOnesz->nUsedHw = pOnesz->nUsed;
  pRes = pOnesz->pFree;
  pOnesz->pFree = pOnesz->pFree->pNext;
  return pRes;
}
static void mmOneszFree(sqlite4_mm *pMM, void *pOld){
  struct mmOnesz *pOnesz = (struct mmOnesz*)pMM;
  if( pOld ){
    struct mmOneszBlock *pBlock = (struct mmOneszBlock*)pOld;
    pBlock->pNext = pOnesz->pFree;
    pOnesz->pFree = pBlock;
    pOnesz->nUsed--;
  }
}
static void *mmOneszRealloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSz){
  struct mmOnesz *pOnesz = (struct mmOnesz*)pMM;
  if( pOld==0 ) return mmOneszMalloc(pMM, iSz);
  if( iSz<=0 ){
    mmOneszFree(pMM, pOld);
    return 0;
  }
  if( iSz>pOnesz->sz ) return 0;
  return pOld;
}
static sqlite4_size_t mmOneszMsize(sqlite4_mm *pMM, void *pOld){
  struct mmOnesz *pOnesz = (struct mmOnesz*)pMM;
  return pOld ? pOnesz->sz : 0;  
}
static int mmOneszMember(sqlite4_mm *pMM, const void *pOld){
  struct mmOnesz *pOnesz = (struct mmOnesz*)pMM;
  return pOld && pOld>=pOnesz->pSpace && pOld<=pOnesz->pLast;
}
static sqlite4_int64 mmOneszStat(
  sqlite4_mm *pMM, 
  unsigned int eType, 
  unsigned int flgs
){
  struct mmOnesz *pOnesz = (struct mmOnesz*)pMM;
  sqlite4_int64 x = -1;
  switch( eType ){
    case SQLITE4_MMSTAT_OUT: {
      x = pOnesz->nUsed*pOnesz->sz;
      break;
    }
    case SQLITE4_MMSTAT_OUT_HW: {
      x = pOnesz->nUsedHw*pOnesz->sz;
      if( flgs & SQLITE4_MMSTAT_RESET ) pOnesz->nUsedHw = pOnesz->nUsed;
      break;
    }
    case SQLITE4_MMSTAT_UNITS: {
      x = pOnesz->nUsed;
      break;
    }
    case SQLITE4_MMSTAT_UNITS_HW: {
      x = pOnesz->nUsedHw;
      if( flgs & SQLITE4_MMSTAT_RESET ) pOnesz->nUsedHw = pOnesz->nUsed;
      break;
    }
    case SQLITE4_MMSTAT_SIZE: {
      x = pOnesz->mxSize;
      if( flgs & SQLITE4_MMSTAT_RESET ) pOnesz->mxSize = 0;
      break;
    }
    case SQLITE4_MMSTAT_SZFAULT: {
      x = pOnesz->nFailSize;
      if( flgs & SQLITE4_MMSTAT_RESET ) pOnesz->nFailSize = 0;
      break;
    }
    case SQLITE4_MMSTAT_MEMFAULT: {
      x = pOnesz->nFailMem;
      if( flgs & SQLITE4_MMSTAT_RESET ) pOnesz->nFailMem = 0;
      break;
    }
    case SQLITE4_MMSTAT_FAULT: {
      x = pOnesz->nFailSize + pOnesz->nFailMem;
      if( flgs & SQLITE4_MMSTAT_RESET ){
        pOnesz->nFailSize = 0;
        pOnesz->nFailMem = 0;
      }
      break;
    }
  }
  return x;
}
static const sqlite4_mm_methods mmOneszMethods = {
  /* iVersion */    1,
  /* xMalloc  */    mmOneszMalloc,
  /* xRealloc */    mmOneszRealloc,
  /* xFree    */    mmOneszFree,
  /* xMsize   */    mmOneszMsize,
  /* xMember  */    mmOneszMember,
  /* xBenign  */    0,
  /* xStat    */    mmOneszStat,
  /* xCtrl    */    0,
  /* xFinal   */    0
};
static sqlite4_mm *mmOneszNew(void *pSpace, int sz, int cnt){
  struct mmOnesz *pOnesz;
  unsigned char *pMem;
  int n;
  if( sz<sizeof(struct mmOneszBlock) ) return 0;
  pMem = (unsigned char*)pSpace;
  pOnesz = (struct mmOnesz*)pMem;
  n = (sizeof(*pOnesz) + sz - 1)/sz;
  pMem += sz*n;
  cnt -= n;
  if( cnt<2 ) return 0;
  memset(pOnesz, 0, sizeof(*pOnesz));
  pOnesz->base.pMethods = &mmOneszMethods;
  pOnesz->pSpace = (const void*)pMem;
  pOnesz->sz = sz;
  pOnesz->pLast = (const void*)(pMem + sz*(cnt-2));
  pOnesz->pFree = 0;
  while( cnt ){
    struct mmOneszBlock *pBlock = (struct mmOneszBlock*)pMem;
    pBlock->pNext = pOnesz->pFree;
    pOnesz->pFree = pBlock;
    cnt--;
    pMem += sz;
  }
  return &pOnesz->base;
}

/*************************************************************************
** Main interfaces.
*/
SQLITE4_API void *sqlite4_mm_malloc(sqlite4_mm *pMM, sqlite4_size_t iSize){
  if( pMM==0 ) pMM = &sqlite4MMSystem;
  return pMM->pMethods->xMalloc(pMM,iSize);
}
SQLITE4_API void *sqlite4_mm_realloc(sqlite4_mm *pMM, void *pOld, sqlite4_size_t iSize){
  if( pMM==0 ) pMM = &sqlite4MMSystem;
  return pMM->pMethods->xRealloc(pMM,pOld,iSize);
}
SQLITE4_API void sqlite4_mm_free(sqlite4_mm *pMM, void *pOld){
  if( pMM==0 ) pMM = &sqlite4MMSystem;
  pMM->pMethods->xFree(pMM,pOld);
}
SQLITE4_API sqlite4_size_t sqlite4_mm_msize(sqlite4_mm *pMM, void *pOld){
  if( pMM==0 ) pMM = &sqlite4MMSystem;
  return pMM->pMethods->xMsize(pMM,pOld);
}
SQLITE4_API int sqlite4_mm_member(sqlite4_mm *pMM, const void *pOld){
  return (pMM && pMM->pMethods->xMember!=0) ?
            pMM->pMethods->xMember(pMM,pOld) : -1;
}
SQLITE4_API void sqlite4_mm_benign_failures(sqlite4_mm *pMM, int bEnable){
  if( pMM && pMM->pMethods->xBenign ){
    pMM->pMethods->xBenign(pMM, bEnable);
  }
}
SQLITE4_API sqlite4_int64 sqlite4_mm_stat(sqlite4_mm *pMM, int eStatType, unsigned flags){
  if( pMM==0 ) return -1;
  if( pMM->pMethods->xStat==0 ) return -1;
  return pMM->pMethods->xStat(pMM, eStatType, flags);
}
SQLITE4_API int sqlite4_mm_control_va(sqlite4_mm *pMM, int eCtrlType, va_list ap){
  if( pMM==0 || pMM->pMethods->xCtrl==0 ) return SQLITE4_NOTFOUND;
  return pMM->pMethods->xCtrl(pMM, eCtrlType, ap);
}
SQLITE4_API int sqlite4_mm_control(sqlite4_mm *pMM, int eCtrlType, ...){
  int rc;
  va_list ap;
  va_start(ap, eCtrlType);
  rc = sqlite4_mm_control_va(pMM, eCtrlType, ap);
  va_end(ap);
  return rc;
}
SQLITE4_API void sqlite4_mm_destroy(sqlite4_mm *pMM){
  if( pMM && pMM->pMethods->xFinal ) pMM->pMethods->xFinal(pMM);
}

/*
** Create a new memory allocation object.  eType determines the type of
** memory allocator and the arguments.
*/
SQLITE4_API sqlite4_mm *sqlite4_mm_new(sqlite4_mm_type eType, ...){
  va_list ap;
  sqlite4_mm *pMM;

  va_start(ap, eType);
  switch( eType ){
    case SQLITE4_MM_SYSTEM: {
      pMM = &sqlite4MMSystem;
      break;
    }
    case SQLITE4_MM_OVERFLOW: {
      sqlite4_mm *pA = va_arg(ap, sqlite4_mm*);
      sqlite4_mm *pB = va_arg(ap, sqlite4_mm*);
      pMM = mmOvflNew(pA, pB);
      break;
    }
    case SQLITE4_MM_ONESIZE: {
      void *pSpace = va_arg(ap, void*);
      int sz = va_arg(ap, int);
      int cnt = va_arg(ap, int);
      pMM = mmOneszNew(pSpace, sz, cnt);
      break;
    }
    case SQLITE4_MM_STATS: {
      sqlite4_mm *p = va_arg(ap, sqlite4_mm*);
      pMM = mmStatsNew(p);
      break;
    }
    default: {
      pMM = 0;
      break;
    }
  }
  va_end(ap);
  return pMM;
}

/*************************************************************************
** sqlite4_buffer implementation.
*/

SQLITE4_API void sqlite4_buffer_init(sqlite4_buffer *pBuf, sqlite4_mm *pMM){
  memset(pBuf, 0, sizeof(*pBuf));
  pBuf->pMM = pMM;
}

SQLITE4_API int sqlite4_buffer_resize(sqlite4_buffer *pBuf, sqlite4_size_t nReq){
  sqlite4_size_t nCurrent;                  /* Current buffer size */
  nCurrent = sqlite4_mm_msize(pBuf->pMM, pBuf->p);
  if( nCurrent<nReq ){
    void *pNew = sqlite4_mm_realloc(pBuf->pMM, pBuf->p, nReq);
    if( pNew==0 ) return SQLITE4_NOMEM;
    pBuf->p = pNew;
  }
  pBuf->n = nReq;
  return SQLITE4_OK;
}

SQLITE4_API int sqlite4_buffer_append(
  sqlite4_buffer *pBuf, 
  const void *p, 
  sqlite4_size_t n
){
  int rc;                         /* Return code */
  sqlite4_size_t nOrig = pBuf->n; /* Initial buffer size in bytes */

  rc = sqlite4_buffer_resize(pBuf, nOrig+n);
  if( rc==SQLITE4_OK ){
    memcpy(&((u8 *)pBuf->p)[nOrig], p, n);
  }
  return rc;
}

SQLITE4_API int sqlite4_buffer_set(
  sqlite4_buffer *pBuf, 
  const void *p, 
  sqlite4_size_t n
){
  pBuf->n = 0;
  return sqlite4_buffer_append(pBuf, p, n);
}

SQLITE4_API void sqlite4_buffer_clear(sqlite4_buffer *pBuf){
  sqlite4_mm_free(pBuf->pMM, pBuf->p);
  sqlite4_buffer_init(pBuf, pBuf->pMM);
}

/************** End of mem.c *************************************************/
/************** Begin file mem0.c ********************************************/
/*
** 2008 October 28
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains a no-op memory allocation drivers for use when
** SQLITE4_ZERO_MALLOC is defined.  The allocation drivers implemented
** here always fail.  SQLite will not operate with these drivers.  These
** are merely placeholders.  Real drivers must be substituted using
** sqlite4_config() before SQLite will operate.
*/

/*
** This version of the memory allocator is the default.  It is
** used when no other memory allocator is specified using compile-time
** macros.
*/
#ifdef SQLITE4_ZERO_MALLOC

/*
** No-op versions of all memory allocation routines
*/
static void *sqlite4MemMalloc(void *p, sqlite4_size_t nByte){ return 0; }
static void sqlite4MemFree(void *p, void *pPrior){ return; }
static void *sqlite4MemRealloc(void *p, void *pPrior, sqlite4_size_t nByte){
  return 0;
}
static int sqlite4MemSize(void*p, void *pPrior){ return 0; }
static int sqlite4MemInit(void *NotUsed){ return SQLITE4_OK; }
static void sqlite4MemShutdown(void *NotUsed){ return; }

/*
** This routine is the only routine in this file with external linkage.
**
** Populate the low-level memory allocation function pointers in
** sqlite4DefaultEnv.m with pointers to the routines in this file.
*/
SQLITE4_PRIVATE void sqlite4MemSetDefault(sqlite4_env *pEnv){
  static const sqlite4_mem_methods defaultMethods = {
     sqlite4MemMalloc,
     sqlite4MemFree,
     sqlite4MemRealloc,
     sqlite4MemSize,
     sqlite4MemInit,
     sqlite4MemShutdown,
     0, 
     0,
     0
  };
  pEnv->m = defaultMethods;
  pEnv->m.pMemEnv = (void*)pEnv;
}

#endif /* SQLITE4_ZERO_MALLOC */

/************** End of mem0.c ************************************************/
/************** Begin file mem2.c ********************************************/
/*
** 2007 August 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains low-level memory allocation drivers for when
** SQLite will use the standard C-library malloc/realloc/free interface
** to obtain the memory it needs while adding lots of additional debugging
** information to each allocation in order to help detect and fix memory
** leaks and memory usage errors.
**
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite4_mem_methods object.
*/

/*
** This version of the memory allocator is used only if the
** SQLITE4_MEMDEBUG macro is defined
*/
#ifdef SQLITE4_MEMDEBUG

/*
** The backtrace functionality is only available with GLIBC
*/
#ifdef __GLIBC__
  extern int backtrace(void**,int);
  extern void backtrace_symbols_fd(void*const*,int,int);
#else
# define backtrace(A,B) 1
# define backtrace_symbols_fd(A,B,C)
#endif
/* #include <stdio.h> */

/*
** Each memory allocation looks like this:
**
**  ------------------------------------------------------------------------
**  | Title |  backtrace pointers |  MemBlockHdr |  allocation |  EndGuard |
**  ------------------------------------------------------------------------
**
** The application code sees only a pointer to the allocation.  We have
** to back up from the allocation pointer to find the MemBlockHdr.  The
** MemBlockHdr tells us the size of the allocation and the number of
** backtrace pointers.  There is also a guard word at the end of the
** MemBlockHdr.
*/
struct MemBlockHdr {
  i64 iSize;                          /* Size of this allocation */
  struct MemBlockHdr *pNext, *pPrev;  /* Linked list of all unfreed memory */
  char nBacktrace;                    /* Number of backtraces on this alloc */
  char nBacktraceSlots;               /* Available backtrace slots */
  u8 nTitle;                          /* Bytes of title; includes '\0' */
  u8 eType;                           /* Allocation type code */
  int iForeGuard;                     /* Guard word for sanity */
};

/*
** Guard words
*/
#define FOREGUARD 0x80F5E153
#define REARGUARD 0xE4676B53

/*
** Number of malloc size increments to track.
*/
#define NCSIZE  1000

/*
** All of the static variables used by this module are collected
** into a single structure named "mem".  This is to keep the
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
static struct {
  
  /*
  ** Mutex to control access to the memory allocation subsystem.
  */
  sqlite4_mutex *mutex;

  /*
  ** Head and tail of a linked list of all outstanding allocations
  */
  struct MemBlockHdr *pFirst;
  struct MemBlockHdr *pLast;
  
  /*
  ** The number of levels of backtrace to save in new allocations.
  */
  int nBacktrace;
  void (*xBacktrace)(int, int, void **);

  /*
  ** Title text to insert in front of each block
  */
  int nTitle;        /* Bytes of zTitle to save.  Includes '\0' and padding */
  char zTitle[100];  /* The title text */

  /* 
  ** sqlite4MallocDisallow() increments the following counter.
  ** sqlite4MallocAllow() decrements it.
  */
  int disallow; /* Do not allow memory allocation */

  /*
  ** Gather statistics on the sizes of memory allocations.
  ** nAlloc[i] is the number of allocation attempts of i*8
  ** bytes.  i==NCSIZE is the number of allocation attempts for
  ** sizes more than NCSIZE*8 bytes.
  */
  int nAlloc[NCSIZE];      /* Total number of allocations */
  int nCurrent[NCSIZE];    /* Current number of allocations */
  int mxCurrent[NCSIZE];   /* Highwater mark for nCurrent */

} mem2;


/*
** Adjust memory usage statistics
*/
static void adjustStats(int iSize, int increment){
  int i = ROUND8(iSize)/8;
  if( i>NCSIZE-1 ){
    i = NCSIZE - 1;
  }
  if( increment>0 ){
    mem2.nAlloc[i]++;
    mem2.nCurrent[i]++;
    if( mem2.nCurrent[i]>mem2.mxCurrent[i] ){
      mem2.mxCurrent[i] = mem2.nCurrent[i];
    }
  }else{
    mem2.nCurrent[i]--;
    assert( mem2.nCurrent[i]>=0 );
  }
}

/*
** Given an allocation, find the MemBlockHdr for that allocation.
**
** This routine checks the guards at either end of the allocation and
** if they are incorrect it asserts.
*/
static struct MemBlockHdr *sqlite4MemsysGetHeader(void *pAllocation){
  struct MemBlockHdr *p;
  int *pInt;
  u8 *pU8;
  int nReserve;

  p = (struct MemBlockHdr*)pAllocation;
  p--;
  assert( p->iForeGuard==(int)FOREGUARD );
  nReserve = ROUND8(p->iSize);
  pInt = (int*)pAllocation;
  pU8 = (u8*)pAllocation;
  assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
  /* This checks any of the "extra" bytes allocated due
  ** to rounding up to an 8 byte boundary to ensure 
  ** they haven't been overwritten.
  */
  while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
  return p;
}

/*
** Return the number of bytes currently allocated at address p.
*/
static int sqlite4MemSize(void *pMem, void *p){
  struct MemBlockHdr *pHdr;
  assert( pMem==(void*)&mem2 );
  if( !p ){
    return 0;
  }
  pHdr = sqlite4MemsysGetHeader(p);
  return pHdr->iSize;
}

/*
** Initialize the memory allocation subsystem.
*/
static int sqlite4MemInit(void *pMallocEnv){
  sqlite4_env *pEnv = (sqlite4_env*)pMallocEnv;
  int rc = SQLITE4_OK;
  assert( (sizeof(struct MemBlockHdr)&7) == 0 );
  if( !pEnv->bMemstat ){
    mem2.mutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_FAST);
    if( mem2.mutex==0 && pEnv->bCoreMutex ) rc = SQLITE4_NOMEM;
  }
  return rc;
}

/*
** Deinitialize the memory allocation subsystem.
*/
static void sqlite4MemShutdown(void *NotUsed){
  UNUSED_PARAMETER(NotUsed);
  sqlite4_mutex_free(mem2.mutex);
  mem2.mutex = 0;
}

/*
** Fill a buffer with pseudo-random bytes.  This is used to preset
** the content of a new memory allocation to unpredictable values and
** to clear the content of a freed allocation to unpredictable values.
*/
static void randomFill(char *pBuf, int nByte){
  unsigned int x, y, r;
  x = SQLITE4_PTR_TO_INT(pBuf);
  y = nByte | 1;
  while( nByte >= 4 ){
    x = (x>>1) ^ (-(x&1) & 0xd0000001);
    y = y*1103515245 + 12345;
    r = x ^ y;
    *(int*)pBuf = r;
    pBuf += 4;
    nByte -= 4;
  }
  while( nByte-- > 0 ){
    x = (x>>1) ^ (-(x&1) & 0xd0000001);
    y = y*1103515245 + 12345;
    r = x ^ y;
    *(pBuf++) = r & 0xff;
  }
}

/*
** Allocate nByte bytes of memory.
*/
static void *sqlite4MemMalloc(void *pMem, sqlite4_size_t nByte){
  struct MemBlockHdr *pHdr;
  void **pBt;
  char *z;
  int *pInt;
  void *p = 0;
  int totalSize;
  int nReserve;
  sqlite4_mutex_enter(mem2.mutex);
  assert( mem2.disallow==0 );
  nReserve = ROUND8(nByte);
  totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
               mem2.nBacktrace*sizeof(void*) + mem2.nTitle;
  assert( pMem==(void*)&mem2 );
  p = malloc(totalSize);
  if( p ){
    z = p;
    pBt = (void**)&z[mem2.nTitle];
    pHdr = (struct MemBlockHdr*)&pBt[mem2.nBacktrace];
    pHdr->pNext = 0;
    pHdr->pPrev = mem2.pLast;
    if( mem2.pLast ){
      mem2.pLast->pNext = pHdr;
    }else{
      mem2.pFirst = pHdr;
    }
    mem2.pLast = pHdr;
    pHdr->iForeGuard = FOREGUARD;
    pHdr->eType = MEMTYPE_HEAP;
    pHdr->nBacktraceSlots = mem2.nBacktrace;
    pHdr->nTitle = mem2.nTitle;
    if( mem2.nBacktrace ){
      void *aAddr[40];
      pHdr->nBacktrace = backtrace(aAddr, mem2.nBacktrace+1)-1;
      memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
      assert(pBt[0]);
      if( mem2.xBacktrace ){
        mem2.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
      }
    }else{
      pHdr->nBacktrace = 0;
    }
    if( mem2.nTitle ){
      memcpy(z, mem2.zTitle, mem2.nTitle);
    }
    pHdr->iSize = nByte;
    adjustStats(nByte, +1);
    pInt = (int*)&pHdr[1];
    pInt[nReserve/sizeof(int)] = REARGUARD;
    randomFill((char*)pInt, nByte);
    memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
    p = (void*)pInt;
  }
  sqlite4_mutex_leave(mem2.mutex);
  return p; 
}

/*
** Free memory.
*/
static void sqlite4MemFree(void *pMem, void *pPrior){
  struct MemBlockHdr *pHdr;
  void **pBt;
  char *z;
  assert( pMem==(void*)&mem2 );
  assert( sqlite4DefaultEnv.bMemstat || sqlite4DefaultEnv.bCoreMutex==0 
       || mem2.mutex!=0 );
  pHdr = sqlite4MemsysGetHeader(pPrior);
  pBt = (void**)pHdr;
  pBt -= pHdr->nBacktraceSlots;
  sqlite4_mutex_enter(mem2.mutex);
  if( pHdr->pPrev ){
    assert( pHdr->pPrev->pNext==pHdr );
    pHdr->pPrev->pNext = pHdr->pNext;
  }else{
    assert( mem2.pFirst==pHdr );
    mem2.pFirst = pHdr->pNext;
  }
  if( pHdr->pNext ){
    assert( pHdr->pNext->pPrev==pHdr );
    pHdr->pNext->pPrev = pHdr->pPrev;
  }else{
    assert( mem2.pLast==pHdr );
    mem2.pLast = pHdr->pPrev;
  }
  z = (char*)pBt;
  z -= pHdr->nTitle;
  adjustStats(pHdr->iSize, -1);
  randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
                pHdr->iSize + sizeof(int) + pHdr->nTitle);
  free(z);
  sqlite4_mutex_leave(mem2.mutex);  
}

/*
** Change the size of an existing memory allocation.
**
** For this debugging implementation, we *always* make a copy of the
** allocation into a new place in memory.  In this way, if the 
** higher level code is using pointer to the old allocation, it is 
** much more likely to break and we are much more liking to find
** the error.
*/
static void *sqlite4MemRealloc(void *p, void *pPrior, sqlite4_size_t nByte){
  struct MemBlockHdr *pOldHdr;
  void *pNew;
  assert( p==(void*)&mem2 );
  assert( mem2.disallow==0 );
  assert( (nByte & 7)==0 );     /* EV: R-46199-30249 */
  pOldHdr = sqlite4MemsysGetHeader(pPrior);
  pNew = sqlite4MemMalloc(p, nByte);
  if( pNew ){
    memcpy(pNew, pPrior, nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize);
    if( nByte>pOldHdr->iSize ){
      randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - pOldHdr->iSize);
    }
    sqlite4MemFree(p, pPrior);
  }
  return pNew;
}

/*
** Populate the low-level memory allocation function pointers in
** sqlite4DefaultEnv.m with pointers to the routines in this file.
*/
SQLITE4_PRIVATE void sqlite4MemSetDefault(sqlite4_env *pEnv){
  static const sqlite4_mem_methods defaultMethods = {
     sqlite4MemMalloc,
     sqlite4MemFree,
     sqlite4MemRealloc,
     sqlite4MemSize,
     sqlite4MemInit,
     sqlite4MemShutdown,
     0,
     0,
     &mem2
  };
  pEnv->m = defaultMethods;
}

/*
** Set the "type" of an allocation.
*/
SQLITE4_PRIVATE void sqlite4MemdebugSetType(void *p, u8 eType){
  if( p && sqlite4DefaultEnv.m.xMalloc==sqlite4MemMalloc ){
    struct MemBlockHdr *pHdr;
    pHdr = sqlite4MemsysGetHeader(p);
    assert( pHdr->iForeGuard==FOREGUARD );
    pHdr->eType = eType;
  }
}

/*
** Return TRUE if the mask of type in eType matches the type of the
** allocation p.  Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation.  For example:
**
**     assert( sqlite4MemdebugHasType(p, MEMTYPE_DB) );
*/
SQLITE4_PRIVATE int sqlite4MemdebugHasType(const void *p, u8 eType){
  int rc = 1;
  if( p && sqlite4DefaultEnv.m.xMalloc==sqlite4MemMalloc ){
    struct MemBlockHdr *pHdr;
    pHdr = sqlite4MemsysGetHeader((void*)p);
    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
    if( (pHdr->eType&eType)==0 ){
      rc = 0;
    }
  }
  return rc;
}

/*
** Return TRUE if the mask of type in eType matches no bits of the type of the
** allocation p.  Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation.  For example:
**
**     assert( sqlite4MemdebugNoType(p, MEMTYPE_DB) );
*/
SQLITE4_PRIVATE int sqlite4MemdebugNoType(const void *p, u8 eType){
  int rc = 1;
  if( p && sqlite4DefaultEnv.m.xMalloc==sqlite4MemMalloc ){
    struct MemBlockHdr *pHdr;
    pHdr = sqlite4MemsysGetHeader((void*)p);
    assert( pHdr->iForeGuard==FOREGUARD );         /* Allocation is valid */
    if( (pHdr->eType&eType)!=0 ){
      rc = 0;
    }
  }
  return rc;
}

/*
** Set the number of backtrace levels kept for each allocation.
** A value of zero turns off backtracing.  The number is always rounded
** up to a multiple of 2.
*/
SQLITE4_PRIVATE void sqlite4MemdebugBacktrace(int depth){
  if( depth<0 ){ depth = 0; }
  if( depth>20 ){ depth = 20; }
  depth = (depth+1)&0xfe;
  mem2.nBacktrace = depth;
}

SQLITE4_PRIVATE void sqlite4MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
  mem2.xBacktrace = xBacktrace;
}

/*
** Set the title string for subsequent allocations.
*/
SQLITE4_PRIVATE void sqlite4MemdebugSettitle(const char *zTitle){
  unsigned int n = sqlite4Strlen30(zTitle) + 1;
  sqlite4_mutex_enter(mem2.mutex);
  if( n>=sizeof(mem2.zTitle) ) n = sizeof(mem2.zTitle)-1;
  memcpy(mem2.zTitle, zTitle, n);
  mem2.zTitle[n] = 0;
  mem2.nTitle = ROUND8(n);
  sqlite4_mutex_leave(mem2.mutex);
}

SQLITE4_PRIVATE void sqlite4MemdebugSync(){
  struct MemBlockHdr *pHdr;
  for(pHdr=mem2.pFirst; pHdr; pHdr=pHdr->pNext){
    void **pBt = (void**)pHdr;
    pBt -= pHdr->nBacktraceSlots;
    mem2.xBacktrace(pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
  }
}

/*
** Open the file indicated and write a log of all unfreed memory 
** allocations into that log.
*/
SQLITE4_PRIVATE void sqlite4MemdebugDump(const char *zFilename){
  FILE *out;
  struct MemBlockHdr *pHdr;
  void **pBt;
  int i;
  out = fopen(zFilename, "w");
  if( out==0 ){
    fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
                    zFilename);
    return;
  }
  for(pHdr=mem2.pFirst; pHdr; pHdr=pHdr->pNext){
    char *z = (char*)pHdr;
    z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
    fprintf(out, "**** %lld bytes at %p from %s ****\n", 
            pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
    if( pHdr->nBacktrace ){
      fflush(out);
      pBt = (void**)pHdr;
      pBt -= pHdr->nBacktraceSlots;
      backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
      fprintf(out, "\n");
    }
  }
  fprintf(out, "COUNTS:\n");
  for(i=0; i<NCSIZE-1; i++){
    if( mem2.nAlloc[i] ){
      fprintf(out, "   %5d: %10d %10d %10d\n", 
            i*8, mem2.nAlloc[i], mem2.nCurrent[i], mem2.mxCurrent[i]);
    }
  }
  if( mem2.nAlloc[NCSIZE-1] ){
    fprintf(out, "   %5d: %10d %10d %10d\n",
             NCSIZE*8-8, mem2.nAlloc[NCSIZE-1],
             mem2.nCurrent[NCSIZE-1], mem2.mxCurrent[NCSIZE-1]);
  }
  fclose(out);
}

/*
** Return the number of times sqlite4MemMalloc() has been called.
*/
SQLITE4_PRIVATE int sqlite4MemdebugMallocCount(){
  int i;
  int nTotal = 0;
  for(i=0; i<NCSIZE; i++){
    nTotal += mem2.nAlloc[i];
  }
  return nTotal;
}


#endif /* SQLITE4_MEMDEBUG */

/************** End of mem2.c ************************************************/
/************** Begin file mem3.c ********************************************/
/*
** 2007 October 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite. 
**
** This version of the memory allocation subsystem omits all
** use of malloc(). The SQLite user supplies a block of memory
** before calling sqlite4_initialize() from which allocations
** are made and returned by the xMalloc() and xRealloc() 
** implementations. Once sqlite4_initialize() has been called,
** the amount of memory available to SQLite is fixed and cannot
** be changed.
**
** This version of the memory allocation subsystem is included
** in the build only if SQLITE4_ENABLE_MEMSYS3 is defined.
*/

/*
** This version of the memory allocator is only built into the library
** SQLITE4_ENABLE_MEMSYS3 is defined. Defining this symbol does not
** mean that the library will use a memory-pool by default, just that
** it is available. The mempool allocator is activated by calling
** sqlite4_config().
*/
#ifdef SQLITE4_ENABLE_MEMSYS3

/*
** Maximum size (in Mem3Blocks) of a "small" chunk.
*/
#define MX_SMALL 10


/*
** Number of freelist hash slots
*/
#define N_HASH  61

/*
** A memory allocation (also called a "chunk") consists of two or 
** more blocks where each block is 8 bytes.  The first 8 bytes are 
** a header that is not returned to the user.
**
** A chunk is two or more blocks that is either checked out or
** free.  The first block has format u.hdr.  u.hdr.size4x is 4 times the
** size of the allocation in blocks if the allocation is free.
** The u.hdr.size4x&1 bit is true if the chunk is checked out and
** false if the chunk is on the freelist.  The u.hdr.size4x&2 bit
** is true if the previous chunk is checked out and false if the
** previous chunk is free.  The u.hdr.prevSize field is the size of
** the previous chunk in blocks if the previous chunk is on the
** freelist. If the previous chunk is checked out, then
** u.hdr.prevSize can be part of the data for that chunk and should
** not be read or written.
**
** We often identify a chunk by its index in mem3.aPool[].  When
** this is done, the chunk index refers to the second block of
** the chunk.  In this way, the first chunk has an index of 1.
** A chunk index of 0 means "no such chunk" and is the equivalent
** of a NULL pointer.
**
** The second block of free chunks is of the form u.list.  The
** two fields form a double-linked list of chunks of related sizes.
** Pointers to the head of the list are stored in mem3.aiSmall[] 
** for smaller chunks and mem3.aiHash[] for larger chunks.
**
** The second block of a chunk is user data if the chunk is checked 
** out.  If a chunk is checked out, the user data may extend into
** the u.hdr.prevSize value of the following chunk.
*/
typedef struct Mem3Block Mem3Block;
struct Mem3Block {
  union {
    struct {
      u32 prevSize;   /* Size of previous chunk in Mem3Block elements */
      u32 size4x;     /* 4x the size of current chunk in Mem3Block elements */
    } hdr;
    struct {
      u32 next;       /* Index in mem3.aPool[] of next free chunk */
      u32 prev;       /* Index in mem3.aPool[] of previous free chunk */
    } list;
  } u;
};

/*
** All of the static variables used by this module are collected
** into a single structure named "mem3".  This is to keep the
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
static SQLITE4_WSD struct Mem3Global {
  /*
  ** Memory available for allocation. nPool is the size of the array
  ** (in Mem3Blocks) pointed to by aPool less 2.
  */
  u32 nPool;
  Mem3Block *aPool;

  /*
  ** True if we are evaluating an out-of-memory callback.
  */
  int alarmBusy;
  
  /*
  ** Mutex to control access to the memory allocation subsystem.
  */
  sqlite4_mutex *mutex;
  
  /*
  ** The minimum amount of free space that we have seen.
  */
  u32 mnMaster;

  /*
  ** iMaster is the index of the master chunk.  Most new allocations
  ** occur off of this chunk.  szMaster is the size (in Mem3Blocks)
  ** of the current master.  iMaster is 0 if there is not master chunk.
  ** The master chunk is not in either the aiHash[] or aiSmall[].
  */
  u32 iMaster;
  u32 szMaster;

  /*
  ** Array of lists of free blocks according to the block size 
  ** for smaller chunks, or a hash on the block size for larger
  ** chunks.
  */
  u32 aiSmall[MX_SMALL-1];   /* For sizes 2 through MX_SMALL, inclusive */
  u32 aiHash[N_HASH];        /* For sizes MX_SMALL+1 and larger */
} mem3 = { 97535575 };

/*
** Unlink the chunk at mem3.aPool[i] from list it is currently
** on.  *pRoot is the list that i is a member of.
*/
static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
  u32 next = mem3.aPool[i].u.list.next;
  u32 prev = mem3.aPool[i].u.list.prev;
  assert( sqlite4_mutex_held(mem3.mutex) );
  if( prev==0 ){
    *pRoot = next;
  }else{
    mem3.aPool[prev].u.list.next = next;
  }
  if( next ){
    mem3.aPool[next].u.list.prev = prev;
  }
  mem3.aPool[i].u.list.next = 0;
  mem3.aPool[i].u.list.prev = 0;
}

/*
** Unlink the chunk at index i from 
** whatever list is currently a member of.
*/
static void memsys3Unlink(u32 i){
  u32 size, hash;
  assert( sqlite4_mutex_held(mem3.mutex) );
  assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
  assert( i>=1 );
  size = mem3.aPool[i-1].u.hdr.size4x/4;
  assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
  assert( size>=2 );
  if( size <= MX_SMALL ){
    memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
  }else{
    hash = size % N_HASH;
    memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
  }
}

/*
** Link the chunk at mem3.aPool[i] so that is on the list rooted
** at *pRoot.
*/
static void memsys3LinkIntoList(u32 i, u32 *pRoot){
  assert( sqlite4_mutex_held(mem3.mutex) );
  mem3.aPool[i].u.list.next = *pRoot;
  mem3.aPool[i].u.list.prev = 0;
  if( *pRoot ){
    mem3.aPool[*pRoot].u.list.prev = i;
  }
  *pRoot = i;
}

/*
** Link the chunk at index i into either the appropriate
** small chunk list, or into the large chunk hash table.
*/
static void memsys3Link(u32 i){
  u32 size, hash;
  assert( sqlite4_mutex_held(mem3.mutex) );
  assert( i>=1 );
  assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
  size = mem3.aPool[i-1].u.hdr.size4x/4;
  assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
  assert( size>=2 );
  if( size <= MX_SMALL ){
    memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
  }else{
    hash = size % N_HASH;
    memsys3LinkIntoList(i, &mem3.aiHash[hash]);
  }
}

/*
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
** will already be held (obtained by code in malloc.c) if
** sqlite4DefaultEnv.bMemStat is true.
*/
static void memsys3Enter(void){
  if( sqlite4DefaultEnv.bMemstat==0 && mem3.mutex==0 ){
    mem3.mutex = sqlite4MutexAlloc(SQLITE4_MUTEX_STATIC_MEM);
  }
  sqlite4_mutex_enter(mem3.mutex);
}
static void memsys3Leave(void){
  sqlite4_mutex_leave(mem3.mutex);
}

/*
** Called when we are unable to satisfy an allocation of nBytes.
*/
static void memsys3OutOfMemory(int nByte){
  if( !mem3.alarmBusy ){
    mem3.alarmBusy = 1;
    assert( sqlite4_mutex_held(mem3.mutex) );
    sqlite4_mutex_leave(mem3.mutex);
    sqlite4_release_memory(nByte);
    sqlite4_mutex_enter(mem3.mutex);
    mem3.alarmBusy = 0;
  }
}


/*
** Chunk i is a free chunk that has been unlinked.  Adjust its 
** size parameters for check-out and return a pointer to the 
** user portion of the chunk.
*/
static void *memsys3Checkout(u32 i, u32 nBlock){
  u32 x;
  assert( sqlite4_mutex_held(mem3.mutex) );
  assert( i>=1 );
  assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
  assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
  x = mem3.aPool[i-1].u.hdr.size4x;
  mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
  mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
  mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
  return &mem3.aPool[i];
}

/*
** Carve a piece off of the end of the mem3.iMaster free chunk.
** Return a pointer to the new allocation.  Or, if the master chunk
** is not large enough, return 0.
*/
static void *memsys3FromMaster(u32 nBlock){
  assert( sqlite4_mutex_held(mem3.mutex) );
  assert( mem3.szMaster>=nBlock );
  if( nBlock>=mem3.szMaster-1 ){
    /* Use the entire master */
    void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
    mem3.iMaster = 0;
    mem3.szMaster = 0;
    mem3.mnMaster = 0;
    return p;
  }else{
    /* Split the master block.  Return the tail. */
    u32 newi, x;
    newi = mem3.iMaster + mem3.szMaster - nBlock;
    assert( newi > mem3.iMaster+1 );
    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
    mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
    mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
    mem3.szMaster -= nBlock;
    mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
    mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
    if( mem3.szMaster < mem3.mnMaster ){
      mem3.mnMaster = mem3.szMaster;
    }
    return (void*)&mem3.aPool[newi];
  }
}

/*
** *pRoot is the head of a list of free chunks of the same size
** or same size hash.  In other words, *pRoot is an entry in either
** mem3.aiSmall[] or mem3.aiHash[].  
**
** This routine examines all entries on the given list and tries
** to coalesce each entries with adjacent free chunks.  
**
** If it sees a chunk that is larger than mem3.iMaster, it replaces 
** the current mem3.iMaster with the new larger chunk.  In order for
** this mem3.iMaster replacement to work, the master chunk must be
** linked into the hash tables.  That is not the normal state of
** affairs, of course.  The calling routine must link the master
** chunk before invoking this routine, then must unlink the (possibly
** changed) master chunk once this routine has finished.
*/
static void memsys3Merge(u32 *pRoot){
  u32 iNext, prev, size, i, x;

  assert( sqlite4_mutex_held(mem3.mutex) );
  for(i=*pRoot; i>0; i=iNext){
    iNext = mem3.aPool[i].u.list.next;
    size = mem3.aPool[i-1].u.hdr.size4x;
    assert( (size&1)==0 );
    if( (size&2)==0 ){
      memsys3UnlinkFromList(i, pRoot);
      assert( i > mem3.aPool[i-1].u.hdr.prevSize );
      prev = i - mem3.aPool[i-1].u.hdr.prevSize;
      if( prev==iNext ){
        iNext = mem3.aPool[prev].u.list.next;
      }
      memsys3Unlink(prev);
      size = i + size/4 - prev;
      x = mem3.aPool[prev-1].u.hdr.size4x & 2;
      mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
      mem3.aPool[prev+size-1].u.hdr.prevSize = size;
      memsys3Link(prev);
      i = prev;
    }else{
      size /= 4;
    }
    if( size>mem3.szMaster ){
      mem3.iMaster = i;
      mem3.szMaster = size;
    }
  }
}

/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable.
**
** This function assumes that the necessary mutexes, if any, are
** already held by the caller. Hence "Unsafe".
*/
static void *memsys3MallocUnsafe(int nByte){
  u32 i;
  u32 nBlock;
  u32 toFree;

  assert( sqlite4_mutex_held(mem3.mutex) );
  assert( sizeof(Mem3Block)==8 );
  if( nByte<=12 ){
    nBlock = 2;
  }else{
    nBlock = (nByte + 11)/8;
  }
  assert( nBlock>=2 );

  /* STEP 1:
  ** Look for an entry of the correct size in either the small
  ** chunk table or in the large chunk hash table.  This is
  ** successful most of the time (about 9 times out of 10).
  */
  if( nBlock <= MX_SMALL ){
    i = mem3.aiSmall[nBlock-2];
    if( i>0 ){
      memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
      return memsys3Checkout(i, nBlock);
    }
  }else{
    int hash = nBlock % N_HASH;
    for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
      if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
        memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
        return memsys3Checkout(i, nBlock);
      }
    }
  }

  /* STEP 2:
  ** Try to satisfy the allocation by carving a piece off of the end
  ** of the master chunk.  This step usually works if step 1 fails.
  */
  if( mem3.szMaster>=nBlock ){
    return memsys3FromMaster(nBlock);
  }


  /* STEP 3:  
  ** Loop through the entire memory pool.  Coalesce adjacent free
  ** chunks.  Recompute the master chunk as the largest free chunk.
  ** Then try again to satisfy the allocation by carving a piece off
  ** of the end of the master chunk.  This step happens very
  ** rarely (we hope!)
  */
  for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
    memsys3OutOfMemory(toFree);
    if( mem3.iMaster ){
      memsys3Link(mem3.iMaster);
      mem3.iMaster = 0;
      mem3.szMaster = 0;
    }
    for(i=0; i<N_HASH; i++){
      memsys3Merge(&mem3.aiHash[i]);
    }
    for(i=0; i<MX_SMALL-1; i++){
      memsys3Merge(&mem3.aiSmall[i]);
    }
    if( mem3.szMaster ){
      memsys3Unlink(mem3.iMaster);
      if( mem3.szMaster>=nBlock ){
        return memsys3FromMaster(nBlock);
      }
    }
  }

  /* If none of the above worked, then we fail. */
  return 0;
}

/*
** Free an outstanding memory allocation.
**
** This function assumes that the necessary mutexes, if any, are
** already held by the caller. Hence "Unsafe".
*/
static void memsys3FreeUnsafe(void *pOld){
  Mem3Block *p = (Mem3Block*)pOld;
  int i;
  u32 size, x;
  assert( sqlite4_mutex_held(mem3.mutex) );
  assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
  i = p - mem3.aPool;
  assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
  size = mem3.aPool[i-1].u.hdr.size4x/4;
  assert( i+size<=mem3.nPool+1 );
  mem3.aPool[i-1].u.hdr.size4x &= ~1;
  mem3.aPool[i+size-1].u.hdr.prevSize = size;
  mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
  memsys3Link(i);

  /* Try to expand the master using the newly freed chunk */
  if( mem3.iMaster ){
    while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
      size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
      mem3.iMaster -= size;
      mem3.szMaster += size;
      memsys3Unlink(mem3.iMaster);
      x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
    }
    x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
    while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
      memsys3Unlink(mem3.iMaster+mem3.szMaster);
      mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
      mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
      mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
    }
  }
}

/*
** Return the size of an outstanding allocation, in bytes.  The
** size returned omits the 8-byte header overhead.  This only
** works for chunks that are currently checked out.
*/
static int memsys3Size(void *p){
  Mem3Block *pBlock;
  if( p==0 ) return 0;
  pBlock = (Mem3Block*)p;
  assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
  return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
}

/*
** Round up a request size to the next valid allocation size.
*/
static int memsys3Roundup(int n){
  if( n<=12 ){
    return 12;
  }else{
    return ((n+11)&~7) - 4;
  }
}

/*
** Allocate nBytes of memory.
*/
static void *memsys3Malloc(int nBytes){
  sqlite4_int64 *p;
  assert( nBytes>0 );          /* malloc.c filters out 0 byte requests */
  memsys3Enter();
  p = memsys3MallocUnsafe(nBytes);
  memsys3Leave();
  return (void*)p; 
}

/*
** Free memory.
*/
static void memsys3Free(void *pPrior){
  assert( pPrior );
  memsys3Enter();
  memsys3FreeUnsafe(pPrior);
  memsys3Leave();
}

/*
** Change the size of an existing memory allocation
*/
static void *memsys3Realloc(sqlite4_env*pEnv, void *pPrior, int nBytes){
  int nOld;
  void *p;
  if( pPrior==0 ){
    return sqlite4_malloc(pEnv, nBytes);
  }
  if( nBytes<=0 ){
    sqlite4_free(pEnv, pPrior);
    return 0;
  }
  nOld = memsys3Size(pPrior);
  if( nBytes<=nOld && nBytes>=nOld-128 ){
    return pPrior;
  }
  memsys3Enter();
  p = memsys3MallocUnsafe(nBytes);
  if( p ){
    if( nOld<nBytes ){
      memcpy(p, pPrior, nOld);
    }else{
      memcpy(p, pPrior, nBytes);
    }
    memsys3FreeUnsafe(pPrior);
  }
  memsys3Leave();
  return p;
}

/*
** Initialize this module.
*/
static int memsys3Init(void *NotUsed){
  UNUSED_PARAMETER(NotUsed);
  if( !sqlite4DefaultEnv.pHeap ){
    return SQLITE4_ERROR;
  }

  /* Store a pointer to the memory block in global structure mem3. */
  assert( sizeof(Mem3Block)==8 );
  mem3.aPool = (Mem3Block *)sqlite4DefaultEnv.pHeap;
  mem3.nPool = (sqlite4DefaultEnv.nHeap / sizeof(Mem3Block)) - 2;

  /* Initialize the master block. */
  mem3.szMaster = mem3.nPool;
  mem3.mnMaster = mem3.szMaster;
  mem3.iMaster = 1;
  mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
  mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
  mem3.aPool[mem3.nPool].u.hdr.size4x = 1;

  return SQLITE4_OK;
}

/*
** Deinitialize this module.
*/
static void memsys3Shutdown(void *NotUsed){
  UNUSED_PARAMETER(NotUsed);
  mem3.mutex = 0;
  return;
}



/*
** Open the file indicated and write a log of all unfreed memory 
** allocations into that log.
*/
SQLITE4_PRIVATE void sqlite4Memsys3Dump(const char *zFilename){
#ifdef SQLITE4_DEBUG
  FILE *out;
  u32 i, j;
  u32 size;
  if( zFilename==0 || zFilename[0]==0 ){
    out = stdout;
  }else{
    out = fopen(zFilename, "w");
    if( out==0 ){
      fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
                      zFilename);
      return;
    }
  }
  memsys3Enter();
  fprintf(out, "CHUNKS:\n");
  for(i=1; i<=mem3.nPool; i+=size/4){
    size = mem3.aPool[i-1].u.hdr.size4x;
    if( size/4<=1 ){
      fprintf(out, "%p size error\n", &mem3.aPool[i]);
      assert( 0 );
      break;
    }
    if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
      fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
      assert( 0 );
      break;
    }
    if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
      fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
      assert( 0 );
      break;
    }
    if( size&1 ){
      fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
    }else{
      fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
                  i==mem3.iMaster ? " **master**" : "");
    }
  }
  for(i=0; i<MX_SMALL-1; i++){
    if( mem3.aiSmall[i]==0 ) continue;
    fprintf(out, "small(%2d):", i);
    for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
      fprintf(out, " %p(%d)", &mem3.aPool[j],
              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
    }
    fprintf(out, "\n"); 
  }
  for(i=0; i<N_HASH; i++){
    if( mem3.aiHash[i]==0 ) continue;
    fprintf(out, "hash(%2d):", i);
    for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
      fprintf(out, " %p(%d)", &mem3.aPool[j],
              (mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
    }
    fprintf(out, "\n"); 
  }
  fprintf(out, "master=%d\n", mem3.iMaster);
  fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
  fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
  sqlite4_mutex_leave(mem3.mutex);
  if( out==stdout ){
    fflush(stdout);
  }else{
    fclose(out);
  }
#else
  UNUSED_PARAMETER(zFilename);
#endif
}

/*
** This routine is the only routine in this file with external 
** linkage.
**
** Populate the low-level memory allocation function pointers in
** sqlite4DefaultEnv.m with pointers to the routines in this file. The
** arguments specify the block of memory to manage.
**
** This routine is only called by sqlite4_config(), and therefore
** is not required to be threadsafe (it is not).
*/
SQLITE4_PRIVATE const sqlite4_mem_methods *sqlite4MemGetMemsys3(void){
  static const sqlite4_mem_methods mempoolMethods = {
     memsys3Malloc,
     memsys3Free,
     memsys3Realloc,
     memsys3Size,
     memsys3Roundup,
     memsys3Init,
     memsys3Shutdown,
     0
  };
  return &mempoolMethods;
}

#endif /* SQLITE4_ENABLE_MEMSYS3 */

/************** End of mem3.c ************************************************/
/************** Begin file mem5.c ********************************************/
/*
** 2007 October 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement a memory
** allocation subsystem for use by SQLite. 
**
** This version of the memory allocation subsystem omits all
** use of malloc(). The application gives SQLite a block of memory
** before calling sqlite4_initialize() from which allocations
** are made and returned by the xMalloc() and xRealloc() 
** implementations. Once sqlite4_initialize() has been called,
** the amount of memory available to SQLite is fixed and cannot
** be changed.
**
** This version of the memory allocation subsystem is included
** in the build only if SQLITE4_ENABLE_MEMSYS5 is defined.
**
** This memory allocator uses the following algorithm:
**
**   1.  All memory allocations sizes are rounded up to a power of 2.
**
**   2.  If two adjacent free blocks are the halves of a larger block,
**       then the two blocks are coalesed into the single larger block.
**
**   3.  New memory is allocated from the first available free block.
**
** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
** Concerning Dynamic Storage Allocation". Journal of the Association for
** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
** 
** Let n be the size of the largest allocation divided by the minimum
** allocation size (after rounding all sizes up to a power of 2.)  Let M
** be the maximum amount of memory ever outstanding at one time.  Let
** N be the total amount of memory available for allocation.  Robson
** proved that this memory allocator will never breakdown due to 
** fragmentation as long as the following constraint holds:
**
**      N >=  M*(1 + log2(n)/2) - n + 1
**
** The sqlite4_status() logic tracks the maximum values of n and M so
** that an application can, at any time, verify this constraint.
*/

/*
** This version of the memory allocator is used only when 
** SQLITE4_ENABLE_MEMSYS5 is defined.
*/
#ifdef SQLITE4_ENABLE_MEMSYS5

/*
** A minimum allocation is an instance of the following structure.
** Larger allocations are an array of these structures where the
** size of the array is a power of 2.
**
** The size of this object must be a power of two.  That fact is
** verified in memsys5Init().
*/
typedef struct Mem5Link Mem5Link;
struct Mem5Link {
  int next;       /* Index of next free chunk */
  int prev;       /* Index of previous free chunk */
};

/*
** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since
** mem5.szAtom is always at least 8 and 32-bit integers are used,
** it is not actually possible to reach this limit.
*/
#define LOGMAX 30

/*
** Masks used for mem5.aCtrl[] elements.
*/
#define CTRL_LOGSIZE  0x1f    /* Log2 Size of this block */
#define CTRL_FREE     0x20    /* True if not checked out */

/*
** All of the static variables used by this module are collected
** into a single structure named "mem5".  This is to keep the
** static variables organized and to reduce namespace pollution
** when this module is combined with other in the amalgamation.
*/
static SQLITE4_WSD struct Mem5Global {
  /*
  ** Memory available for allocation
  */
  int szAtom;      /* Smallest possible allocation in bytes */
  int nBlock;      /* Number of szAtom sized blocks in zPool */
  u8 *zPool;       /* Memory available to be allocated */
  
  /*
  ** Mutex to control access to the memory allocation subsystem.
  */
  sqlite4_mutex *mutex;

  /*
  ** Performance statistics
  */
  u64 nAlloc;         /* Total number of calls to malloc */
  u64 totalAlloc;     /* Total of all malloc calls - includes internal frag */
  u64 totalExcess;    /* Total internal fragmentation */
  u32 currentOut;     /* Current checkout, including internal fragmentation */
  u32 currentCount;   /* Current number of distinct checkouts */
  u32 maxOut;         /* Maximum instantaneous currentOut */
  u32 maxCount;       /* Maximum instantaneous currentCount */
  u32 maxRequest;     /* Largest allocation (exclusive of internal frag) */
  
  /*
  ** Lists of free blocks.  aiFreelist[0] is a list of free blocks of
  ** size mem5.szAtom.  aiFreelist[1] holds blocks of size szAtom*2.
  ** and so forth.
  */
  int aiFreelist[LOGMAX+1];

  /*
  ** Space for tracking which blocks are checked out and the size
  ** of each block.  One byte per block.
  */
  u8 *aCtrl;

} mem5;

/*
** Assuming mem5.zPool is divided up into an array of Mem5Link
** structures, return a pointer to the idx-th such lik.
*/
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))

/*
** Unlink the chunk at mem5.aPool[i] from list it is currently
** on.  It should be found on mem5.aiFreelist[iLogsize].
*/
static void memsys5Unlink(int i, int iLogsize){
  int next, prev;
  assert( i>=0 && i<mem5.nBlock );
  assert( iLogsize>=0 && iLogsize<=LOGMAX );
  assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );

  next = MEM5LINK(i)->next;
  prev = MEM5LINK(i)->prev;
  if( prev<0 ){
    mem5.aiFreelist[iLogsize] = next;
  }else{
    MEM5LINK(prev)->next = next;
  }
  if( next>=0 ){
    MEM5LINK(next)->prev = prev;
  }
}

/*
** Link the chunk at mem5.aPool[i] so that is on the iLogsize
** free list.
*/
static void memsys5Link(int i, int iLogsize){
  int x;
  assert( sqlite4_mutex_held(mem5.mutex) );
  assert( i>=0 && i<mem5.nBlock );
  assert( iLogsize>=0 && iLogsize<=LOGMAX );
  assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );

  x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
  MEM5LINK(i)->prev = -1;
  if( x>=0 ){
    assert( x<mem5.nBlock );
    MEM5LINK(x)->prev = i;
  }
  mem5.aiFreelist[iLogsize] = i;
}

/*
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
** will already be held (obtained by code in malloc.c) if
** sqlite4DefaultEnv.bMemStat is true.
*/
static void memsys5Enter(void){
  sqlite4_mutex_enter(mem5.mutex);
}
static void memsys5Leave(void){
  sqlite4_mutex_leave(mem5.mutex);
}

/*
** Return the size of an outstanding allocation, in bytes.  The
** size returned omits the 8-byte header overhead.  This only
** works for chunks that are currently checked out.
*/
static int memsys5Size(void *p){
  int iSize = 0;
  if( p ){
    int i = ((u8 *)p-mem5.zPool)/mem5.szAtom;
    assert( i>=0 && i<mem5.nBlock );
    iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
  }
  return iSize;
}

/*
** Find the first entry on the freelist iLogsize.  Unlink that
** entry and return its index. 
*/
static int memsys5UnlinkFirst(int iLogsize){
  int i;
  int iFirst;

  assert( iLogsize>=0 && iLogsize<=LOGMAX );
  i = iFirst = mem5.aiFreelist[iLogsize];
  assert( iFirst>=0 );
  while( i>0 ){
    if( i<iFirst ) iFirst = i;
    i = MEM5LINK(i)->next;
  }
  memsys5Unlink(iFirst, iLogsize);
  return iFirst;
}

/*
** Return a block of memory of at least nBytes in size.
** Return NULL if unable.  Return NULL if nBytes==0.
**
** The caller guarantees that nByte positive.
**
** The caller has obtained a mutex prior to invoking this
** routine so there is never any chance that two or more
** threads can be in this routine at the same time.
*/
static void *memsys5MallocUnsafe(int nByte){
  int i;           /* Index of a mem5.aPool[] slot */
  int iBin;        /* Index into mem5.aiFreelist[] */
  int iFullSz;     /* Size of allocation rounded up to power of 2 */
  int iLogsize;    /* Log2 of iFullSz/POW2_MIN */

  /* nByte must be a positive */
  assert( nByte>0 );

  /* Keep track of the maximum allocation request.  Even unfulfilled
  ** requests are counted */
  if( (u32)nByte>mem5.maxRequest ){
    mem5.maxRequest = nByte;
  }

  /* Abort if the requested allocation size is larger than the largest
  ** power of two that we can represent using 32-bit signed integers.
  */
  if( nByte > 0x40000000 ){
    return 0;
  }

  /* Round nByte up to the next valid power of two */
  for(iFullSz=mem5.szAtom, iLogsize=0; iFullSz<nByte; iFullSz *= 2, iLogsize++){}

  /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
  ** block.  If not, then split a block of the next larger power of
  ** two in order to create a new free block of size iLogsize.
  */
  for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
  if( iBin>LOGMAX ){
    testcase( sqlite4DefaultEnv.xLog!=0 );
    sqlite4_log(0,SQLITE4_NOMEM, "failed to allocate %u bytes", nByte);
    return 0;
  }
  i = memsys5UnlinkFirst(iBin);
  while( iBin>iLogsize ){
    int newSize;

    iBin--;
    newSize = 1 << iBin;
    mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
    memsys5Link(i+newSize, iBin);
  }
  mem5.aCtrl[i] = iLogsize;

  /* Update allocator performance statistics. */
  mem5.nAlloc++;
  mem5.totalAlloc += iFullSz;
  mem5.totalExcess += iFullSz - nByte;
  mem5.currentCount++;
  mem5.currentOut += iFullSz;
  if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
  if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;

  /* Return a pointer to the allocated memory. */
  return (void*)&mem5.zPool[i*mem5.szAtom];
}

/*
** Free an outstanding memory allocation.
*/
static void memsys5FreeUnsafe(void *pOld){
  u32 size, iLogsize;
  int iBlock;

  /* Set iBlock to the index of the block pointed to by pOld in 
  ** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
  */
  iBlock = ((u8 *)pOld-mem5.zPool)/mem5.szAtom;

  /* Check that the pointer pOld points to a valid, non-free block. */
  assert( iBlock>=0 && iBlock<mem5.nBlock );
  assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 );
  assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );

  iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
  size = 1<<iLogsize;
  assert( iBlock+size-1<(u32)mem5.nBlock );

  mem5.aCtrl[iBlock] |= CTRL_FREE;
  mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
  assert( mem5.currentCount>0 );
  assert( mem5.currentOut>=(size*mem5.szAtom) );
  mem5.currentCount--;
  mem5.currentOut -= size*mem5.szAtom;
  assert( mem5.currentOut>0 || mem5.currentCount==0 );
  assert( mem5.currentCount>0 || mem5.currentOut==0 );

  mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
  while( ALWAYS(iLogsize<LOGMAX) ){
    int iBuddy;
    if( (iBlock>>iLogsize) & 1 ){
      iBuddy = iBlock - size;
    }else{
      iBuddy = iBlock + size;
    }
    assert( iBuddy>=0 );
    if( (iBuddy+(1<<iLogsize))>mem5.nBlock ) break;
    if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
    memsys5Unlink(iBuddy, iLogsize);
    iLogsize++;
    if( iBuddy<iBlock ){
      mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
      mem5.aCtrl[iBlock] = 0;
      iBlock = iBuddy;
    }else{
      mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
      mem5.aCtrl[iBuddy] = 0;
    }
    size *= 2;
  }
  memsys5Link(iBlock, iLogsize);
}

/*
** Allocate nBytes of memory
*/
static void *memsys5Malloc(int nBytes){
  sqlite4_int64 *p = 0;
  if( nBytes>0 ){
    memsys5Enter();
    p = memsys5MallocUnsafe(nBytes);
    memsys5Leave();
  }
  return (void*)p; 
}

/*
** Free memory.
**
** The outer layer memory allocator prevents this routine from
** being called with pPrior==0.
*/
static void memsys5Free(void *pPrior){
  assert( pPrior!=0 );
  memsys5Enter();
  memsys5FreeUnsafe(pPrior);
  memsys5Leave();  
}

/*
** Change the size of an existing memory allocation.
**
** The outer layer memory allocator prevents this routine from
** being called with pPrior==0.  
**
** nBytes is always a value obtained from a prior call to
** memsys5Round().  Hence nBytes is always a non-negative power
** of two.  If nBytes==0 that means that an oversize allocation
** (an allocation larger than 0x40000000) was requested and this
** routine should return 0 without freeing pPrior.
*/
static void *memsys5Realloc(void *pPrior, int nBytes){
  int nOld;
  void *p;
  assert( pPrior!=0 );
  assert( (nBytes&(nBytes-1))==0 );  /* EV: R-46199-30249 */
  assert( nBytes>=0 );
  if( nBytes==0 ){
    return 0;
  }
  nOld = memsys5Size(pPrior);
  if( nBytes<=nOld ){
    return pPrior;
  }
  memsys5Enter();
  p = memsys5MallocUnsafe(nBytes);
  if( p ){
    memcpy(p, pPrior, nOld);
    memsys5FreeUnsafe(pPrior);
  }
  memsys5Leave();
  return p;
}

/*
** Round up a request size to the next valid allocation size.  If
** the allocation is too large to be handled by this allocation system,
** return 0.
**
** All allocations must be a power of two and must be expressed by a
** 32-bit signed integer.  Hence the largest allocation is 0x40000000
** or 1073741824 bytes.
*/
static int memsys5Roundup(int n){
  int iFullSz;
  if( n > 0x40000000 ) return 0;
  for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
  return iFullSz;
}

/*
** Return the ceiling of the logarithm base 2 of iValue.
**
** Examples:   memsys5Log(1) -> 0
**             memsys5Log(2) -> 1
**             memsys5Log(4) -> 2
**             memsys5Log(5) -> 3
**             memsys5Log(8) -> 3
**             memsys5Log(9) -> 4
*/
static int memsys5Log(int iValue){
  int iLog;
  for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
  return iLog;
}

/*
** Initialize the memory allocator.
**
** This routine is not threadsafe.  The caller must be holding a mutex
** to prevent multiple threads from entering at the same time.
*/
static int memsys5Init(void *NotUsed){
  int ii;            /* Loop counter */
  int nByte;         /* Number of bytes of memory available to this allocator */
  u8 *zByte;         /* Memory usable by this allocator */
  int nMinLog;       /* Log base 2 of minimum allocation size in bytes */
  int iOffset;       /* An offset into mem5.aCtrl[] */

  UNUSED_PARAMETER(NotUsed);

  /* For the purposes of this routine, disable the mutex */
  mem5.mutex = 0;

  /* The size of a Mem5Link object must be a power of two.  Verify that
  ** this is case.
  */
  assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 );

  nByte = sqlite4DefaultEnv.nHeap;
  zByte = (u8*)sqlite4DefaultEnv.pHeap;
  assert( zByte!=0 );  /* sqlite4_config() does not allow otherwise */

  /* boundaries on sqlite4DefaultEnv.mnReq are enforced in sqlite4_config() */
  nMinLog = memsys5Log(sqlite4DefaultEnv.mnReq);
  mem5.szAtom = (1<<nMinLog);
  while( (int)sizeof(Mem5Link)>mem5.szAtom ){
    mem5.szAtom = mem5.szAtom << 1;
  }

  mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8)));
  mem5.zPool = zByte;
  mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom];

  for(ii=0; ii<=LOGMAX; ii++){
    mem5.aiFreelist[ii] = -1;
  }

  iOffset = 0;
  for(ii=LOGMAX; ii>=0; ii--){
    int nAlloc = (1<<ii);
    if( (iOffset+nAlloc)<=mem5.nBlock ){
      mem5.aCtrl[iOffset] = ii | CTRL_FREE;
      memsys5Link(iOffset, ii);
      iOffset += nAlloc;
    }
    assert((iOffset+nAlloc)>mem5.nBlock);
  }

  /* If a mutex is required for normal operation, allocate one */
  if( sqlite4DefaultEnv.bMemstat==0 ){
    mem5.mutex = sqlite4MutexAlloc(SQLITE4_MUTEX_STATIC_MEM);
  }

  return SQLITE4_OK;
}

/*
** Deinitialize this module.
*/
static void memsys5Shutdown(void *NotUsed){
  UNUSED_PARAMETER(NotUsed);
  mem5.mutex = 0;
  return;
}

#ifdef SQLITE4_TEST
/*
** Open the file indicated and write a log of all unfreed memory 
** allocations into that log.
*/
SQLITE4_PRIVATE void sqlite4Memsys5Dump(const char *zFilename){
  FILE *out;
  int i, j, n;
  int nMinLog;

  if( zFilename==0 || zFilename[0]==0 ){
    out = stdout;
  }else{
    out = fopen(zFilename, "w");
    if( out==0 ){
      fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
                      zFilename);
      return;
    }
  }
  memsys5Enter();
  nMinLog = memsys5Log(mem5.szAtom);
  for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
    for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
    fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n);
  }
  fprintf(out, "mem5.nAlloc       = %llu\n", mem5.nAlloc);
  fprintf(out, "mem5.totalAlloc   = %llu\n", mem5.totalAlloc);
  fprintf(out, "mem5.totalExcess  = %llu\n", mem5.totalExcess);
  fprintf(out, "mem5.currentOut   = %u\n", mem5.currentOut);
  fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
  fprintf(out, "mem5.maxOut       = %u\n", mem5.maxOut);
  fprintf(out, "mem5.maxCount     = %u\n", mem5.maxCount);
  fprintf(out, "mem5.maxRequest   = %u\n", mem5.maxRequest);
  memsys5Leave();
  if( out==stdout ){
    fflush(stdout);
  }else{
    fclose(out);
  }
}
#endif

/*
** This routine is the only routine in this file with external 
** linkage. It returns a pointer to a static sqlite4_mem_methods
** struct populated with the memsys5 methods.
*/
SQLITE4_PRIVATE const sqlite4_mem_methods *sqlite4MemGetMemsys5(void){
  static const sqlite4_mem_methods memsys5Methods = {
     memsys5Malloc,
     memsys5Free,
     memsys5Realloc,
     memsys5Size,
     memsys5Roundup,
     memsys5Init,
     memsys5Shutdown,
     0
  };
  return &memsys5Methods;
}

#endif /* SQLITE4_ENABLE_MEMSYS5 */

/************** End of mem5.c ************************************************/
/************** Begin file mutex.c *******************************************/
/*
** 2007 August 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement mutexes.
**
** This file contains code that is common across all mutex implementations.
*/

#ifndef SQLITE4_MUTEX_OMIT
/*
** Initialize the mutex system.
*/
SQLITE4_PRIVATE int sqlite4MutexInit(sqlite4_env *pEnv){
  int rc = SQLITE4_OK;
  if( !pEnv->mutex.xMutexAlloc ){
    if( pEnv->bCoreMutex ){
      pEnv->mutex = *sqlite4DefaultMutex();
    }else{
      pEnv->mutex = *sqlite4NoopMutex();
    }
    pEnv->mutex.pMutexEnv = pEnv;
  }
  rc = pEnv->mutex.xMutexInit(pEnv->mutex.pMutexEnv);
  return rc;
}

/*
** Shutdown the mutex system. This call frees resources allocated by
** sqlite4MutexInit().
*/
SQLITE4_PRIVATE int sqlite4MutexEnd(sqlite4_env *pEnv){
  int rc = SQLITE4_OK;
  if( pEnv->mutex.xMutexEnd ){
    rc = pEnv->mutex.xMutexEnd(pEnv->mutex.pMutexEnv);
  }
  return rc;
}

/*
** Retrieve a pointer to a static mutex or allocate a new dynamic one.
*/
SQLITE4_API sqlite4_mutex *sqlite4_mutex_alloc(sqlite4_env *pEnv, int id){
  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
#ifndef SQLITE4_OMIT_AUTOINIT
  if( sqlite4_initialize(pEnv) ) return 0;
#endif
  return pEnv->mutex.xMutexAlloc(pEnv->mutex.pMutexEnv, id);
}

SQLITE4_PRIVATE sqlite4_mutex *sqlite4MutexAlloc(sqlite4_env *pEnv, int id){
  if( !pEnv->bCoreMutex ){
    return 0;
  }
  return pEnv->mutex.xMutexAlloc(pEnv->mutex.pMutexEnv, id);
}

/*
** Free a dynamic mutex.
*/
SQLITE4_API void sqlite4_mutex_free(sqlite4_mutex *p){
  if( p ){
    p->pMutexMethods->xMutexFree(p);
  }
}

/*
** Obtain the mutex p. If some other thread already has the mutex, block
** until it can be obtained.
*/
SQLITE4_API void sqlite4_mutex_enter(sqlite4_mutex *p){
  if( p ){
    p->pMutexMethods->xMutexEnter(p);
  }
}

/*
** Obtain the mutex p. If successful, return SQLITE4_OK. Otherwise, if another
** thread holds the mutex and it cannot be obtained, return SQLITE4_BUSY.
*/
SQLITE4_API int sqlite4_mutex_try(sqlite4_mutex *p){
  int rc = SQLITE4_OK;
  if( p ){
    return p->pMutexMethods->xMutexTry(p);
  }
  return rc;
}

/*
** The sqlite4_mutex_leave() routine exits a mutex that was previously
** entered by the same thread.  The behavior is undefined if the mutex 
** is not currently entered. If a NULL pointer is passed as an argument
** this function is a no-op.
*/
SQLITE4_API void sqlite4_mutex_leave(sqlite4_mutex *p){
  if( p ){
    p->pMutexMethods->xMutexLeave(p);
  }
}

#ifndef NDEBUG
/*
** The sqlite4_mutex_held() and sqlite4_mutex_notheld() routine are
** intended for use inside assert() statements.
*/
SQLITE4_API int sqlite4_mutex_held(sqlite4_mutex *p){
  return p==0 || p->pMutexMethods->xMutexHeld(p);
}
SQLITE4_API int sqlite4_mutex_notheld(sqlite4_mutex *p){
  return p==0 || p->pMutexMethods->xMutexNotheld(p);
}
#endif

#endif /* !defined(SQLITE4_MUTEX_OMIT) */

/************** End of mutex.c ***********************************************/
/************** Begin file mutex_noop.c **************************************/
/*
** 2008 October 07
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement mutexes.
**
** This implementation in this file does not provide any mutual
** exclusion and is thus suitable for use only in applications
** that use SQLite in a single thread.  The routines defined
** here are place-holders.  Applications can substitute working
** mutex routines at start-time using the
**
**     sqlite4_env_config(pEnv, SQLITE4_ENVCONFIG_MUTEX,...)
**
** interface.
**
** If compiled with SQLITE4_DEBUG, then additional logic is inserted
** that does error checking on mutexes to make sure they are being
** called correctly.
*/

#ifndef SQLITE4_MUTEX_OMIT

#ifndef SQLITE4_DEBUG
/*
** Stub routines for all mutex methods.
**
** This routines provide no mutual exclusion or error checking.
*/
static int noopMutexInit(void *p){ UNUSED_PARAMETER(p); return SQLITE4_OK; }
static int noopMutexEnd(void *p){ UNUSED_PARAMETER(p); return SQLITE4_OK; }
static sqlite4_mutex *noopMutexAlloc(void *p, int id){ 
  UNUSED_PARAMETER(p);
  UNUSED_PARAMETER(id);
  return (sqlite4_mutex*)8; 
}
static void noopMutexFree(sqlite4_mutex *p){ UNUSED_PARAMETER(p); return; }
static void noopMutexEnter(sqlite4_mutex *p){ UNUSED_PARAMETER(p); return; }
static int noopMutexTry(sqlite4_mutex *p){
  UNUSED_PARAMETER(p);
  return SQLITE4_OK;
}
static void noopMutexLeave(sqlite4_mutex *p){ UNUSED_PARAMETER(p); return; }

SQLITE4_PRIVATE sqlite4_mutex_methods const *sqlite4NoopMutex(void){
  static const sqlite4_mutex_methods sMutex = {
    noopMutexInit,
    noopMutexEnd,
    noopMutexAlloc,
    noopMutexFree,
    noopMutexEnter,
    noopMutexTry,
    noopMutexLeave,
    0,
    0,
    0
  };
  return &sMutex;
}
#endif /* !SQLITE4_DEBUG */

#ifdef SQLITE4_DEBUG
/*
** In this implementation, error checking is provided for testing
** and debugging purposes.  The mutexes still do not provide any
** mutual exclusion.
*/

/*
** The mutex object
*/
typedef struct sqlite4DebugMutex {
  sqlite4_mutex base;    /* Base class. Must be first */
  sqlite4_env *pEnv;     /* Run-time environment */
  int id;                /* Type of mutex */
  int cnt;               /* Number of entries without a matching leave */
} sqlite4DebugMutex;

/*
** The sqlite4_mutex_held() and sqlite4_mutex_notheld() routine are
** intended for use inside assert() statements.
*/
static int debugMutexHeld(sqlite4_mutex *pX){
  sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX;
  return p==0 || p->cnt>0;
}
static int debugMutexNotheld(sqlite4_mutex *pX){
  sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX;
  return p==0 || p->cnt==0;
}

/*
** Initialize and deinitialize the mutex subsystem.
*/
static int debugMutexInit(void *p){ UNUSED_PARAMETER(p); return SQLITE4_OK; }
static int debugMutexEnd(void *p){ UNUSED_PARAMETER(p); return SQLITE4_OK; }

/*
** The sqlite4_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it.  If it returns NULL
** that means that a mutex could not be allocated. 
*/
static sqlite4_mutex *debugMutexAlloc(void *pX, int id){
  sqlite4_env *pEnv = (sqlite4_env*)pX;
  sqlite4DebugMutex *pNew = 0;

  static sqlite4DebugMutex aStaticMutex[] = {
    { { 0 }, 0, 0, 0 }
  };

  if( id==SQLITE4_MUTEX_STATIC_KV ){
    pNew = &aStaticMutex[0];
    pNew->pEnv = pEnv;
    pNew->base.pMutexMethods = sqlite4NoopMutex();
  }else{
    pNew = sqlite4Malloc(pEnv, sizeof(*pNew));
    if( pNew ){
      pNew->id = id;
      pNew->cnt = 0;
      pNew->pEnv = pEnv;
      pNew->base.pMutexMethods = sqlite4NoopMutex();
    }
  }
  return (sqlite4_mutex*)pNew;
}

/*
** This routine deallocates a previously allocated mutex.
*/
static void debugMutexFree(sqlite4_mutex *pX){
  sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX;
  assert( p->cnt==0 );
  sqlite4_free(p->pEnv, p);
}

/*
** The sqlite4_mutex_enter() and sqlite4_mutex_try() routines attempt
** to enter a mutex.  If another thread is already within the mutex,
** sqlite4_mutex_enter() will block and sqlite4_mutex_try() will return
** SQLITE4_BUSY.  The sqlite4_mutex_try() interface returns SQLITE4_OK
** upon successful entry.  Mutexes created using SQLITE4_MUTEX_RECURSIVE can
** be entered multiple times by the same thread.  In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter.  If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
static void debugMutexEnter(sqlite4_mutex *pX){
  sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX;
  assert( p->id==SQLITE4_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
  p->cnt++;
}
static int debugMutexTry(sqlite4_mutex *pX){
  sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX;
  assert( p->id==SQLITE4_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
  p->cnt++;
  return SQLITE4_OK;
}

/*
** The sqlite4_mutex_leave() routine exits a mutex that was
** previously entered by the same thread.  The behavior
** is undefined if the mutex is not currently entered or
** is not currently allocated.  SQLite will never do either.
*/
static void debugMutexLeave(sqlite4_mutex *pX){
  sqlite4DebugMutex *p = (sqlite4DebugMutex*)pX;
  assert( debugMutexHeld(pX) );
  p->cnt--;
  assert( p->id==SQLITE4_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
}

SQLITE4_PRIVATE sqlite4_mutex_methods const *sqlite4NoopMutex(void){
  static const sqlite4_mutex_methods sMutex = {
    debugMutexInit,
    debugMutexEnd,
    debugMutexAlloc,
    debugMutexFree,
    debugMutexEnter,
    debugMutexTry,
    debugMutexLeave,
    debugMutexHeld,
    debugMutexNotheld, 
    0
  };

  return &sMutex;
}
#endif /* SQLITE4_DEBUG */

/*
** If compiled with SQLITE4_MUTEX_NOOP, then the no-op mutex implementation
** is used regardless of the run-time threadsafety setting.
*/
#ifdef SQLITE4_MUTEX_NOOP
SQLITE4_PRIVATE sqlite4_mutex_methods const *sqlite4DefaultMutex(void){
  return sqlite4NoopMutex();
}
#endif /* defined(SQLITE4_MUTEX_NOOP) */
#endif /* !defined(SQLITE4_MUTEX_OMIT) */

/************** End of mutex_noop.c ******************************************/
/************** Begin file mutex_unix.c **************************************/
/*
** 2007 August 28
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement mutexes for pthreads
*/

/*
** The code in this file is only used if we are compiling threadsafe
** under unix with pthreads.
**
** Note that this implementation requires a version of pthreads that
** supports recursive mutexes.
*/
#ifdef SQLITE4_MUTEX_PTHREADS

#include <pthread.h>

/*
** The sqlite4_mutex.id, sqlite4_mutex.nRef, and sqlite4_mutex.owner fields
** are necessary under two condidtions:  (1) Debug builds and (2) using
** home-grown mutexes.  Encapsulate these conditions into a single #define.
*/
#if defined(SQLITE4_DEBUG) || defined(SQLITE4_HOMEGROWN_RECURSIVE_MUTEX)
# define SQLITE4_MUTEX_NREF 1
#else
# define SQLITE4_MUTEX_NREF 0
#endif

static int pthreadMutexInit(void *p);
static int pthreadMutexEnd(void *p);
static sqlite4_mutex *pthreadMutexAlloc(void *pMutexEnv, int iType);
static void pthreadMutexFree(sqlite4_mutex *pMutex);
static void pthreadMutexEnter(sqlite4_mutex *pMutex);
static int pthreadMutexTry(sqlite4_mutex *pMutex);
static void pthreadMutexLeave(sqlite4_mutex *pMutex);
#ifdef SQLITE4_DEBUG
static int pthreadMutexHeld(sqlite4_mutex *pMutex);
static int pthreadMutexNotheld(sqlite4_mutex *pMutex);
#endif

static const sqlite4_mutex_methods sMutexMethods = {
  pthreadMutexInit,
  pthreadMutexEnd,
  pthreadMutexAlloc,
  pthreadMutexFree,
  pthreadMutexEnter,
  pthreadMutexTry,
  pthreadMutexLeave,
#ifdef SQLITE4_DEBUG
  pthreadMutexHeld,
  pthreadMutexNotheld,
#else
  0,
  0,
#endif
  0
};

/*
** Each recursive mutex is an instance of the following structure.
*/
typedef struct sqlite4UnixMutex {
  sqlite4_mutex base;        /* Base class.  Must be first */
  pthread_mutex_t mutex;     /* Mutex controlling the lock */
#if SQLITE4_MUTEX_NREF
  int id;                    /* Mutex type */
  volatile int nRef;         /* Number of entrances */
  volatile pthread_t owner;  /* Thread that is within this mutex */
  int trace;                 /* True to trace changes */
#endif
} sqlite4UnixMutex;
#if SQLITE4_MUTEX_NREF
#define SQLITE4_MUTEX_INITIALIZER \
  { {&sMutexMethods}, PTHREAD_MUTEX_INITIALIZER, 0, 0, (pthread_t)0, 0 }
#else
#define SQLITE4_MUTEX_INITIALIZER \
  { {&sMutexMethods}, PTHREAD_MUTEX_INITIALIZER }
#endif

/*
** The sqlite4_mutex_held() and sqlite4_mutex_notheld() routine are
** intended for use only inside assert() statements.  On some platforms,
** there might be race conditions that can cause these routines to
** deliver incorrect results.  In particular, if pthread_equal() is
** not an atomic operation, then these routines might delivery
** incorrect results.  On most platforms, pthread_equal() is a 
** comparison of two integers and is therefore atomic.  But we are
** told that HPUX is not such a platform.  If so, then these routines
** will not always work correctly on HPUX.
**
** On those platforms where pthread_equal() is not atomic, SQLite
** should be compiled without -DSQLITE4_DEBUG and with -DNDEBUG to
** make sure no assert() statements are evaluated and hence these
** routines are never called.
*/
#if !defined(NDEBUG) || defined(SQLITE4_DEBUG)
static int pthreadMutexHeld(sqlite4_mutex *pMutex){
  sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex;
  return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
}
static int pthreadMutexNotheld(sqlite4_mutex *pMutex){
  sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex;
  return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
}
#endif

/*
** Initialize and deinitialize the mutex subsystem.
*/
static int pthreadMutexInit(void *p){ UNUSED_PARAMETER(p); return SQLITE4_OK; }
static int pthreadMutexEnd(void *p){ UNUSED_PARAMETER(p); return SQLITE4_OK; }

/*
** The sqlite4_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it.  If it returns NULL
** that means that a mutex could not be allocated.  SQLite
** will unwind its stack and return an error.  The argument
** to sqlite4_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li>  SQLITE4_MUTEX_FAST
** <li>  SQLITE4_MUTEX_RECURSIVE
** <li>  SQLITE4_MUTEX_STATIC_MASTER
** <li>  SQLITE4_MUTEX_STATIC_MEM
** <li>  SQLITE4_MUTEX_STATIC_MEM2
** <li>  SQLITE4_MUTEX_STATIC_PRNG
** <li>  SQLITE4_MUTEX_STATIC_LRU
** <li>  SQLITE4_MUTEX_STATIC_PMEM
** </ul>
**
** The first two constants cause sqlite4_mutex_alloc() to create
** a new mutex.  The new mutex is recursive when SQLITE4_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE4_MUTEX_FAST is used.
** The mutex implementation does not need to make a distinction
** between SQLITE4_MUTEX_RECURSIVE and SQLITE4_MUTEX_FAST if it does
** not want to.  But SQLite will only request a recursive mutex in
** cases where it really needs one.  If a faster non-recursive mutex
** implementation is available on the host platform, the mutex subsystem
** might return such a mutex in response to SQLITE4_MUTEX_FAST.
**
** The other allowed parameters to sqlite4_mutex_alloc() each return
** a pointer to a static preexisting mutex.  Six static mutexes are
** used by the current version of SQLite.  Future versions of SQLite
** may add additional static mutexes.  Static mutexes are for internal
** use by SQLite only.  Applications that use SQLite mutexes should
** use only the dynamic mutexes returned by SQLITE4_MUTEX_FAST or
** SQLITE4_MUTEX_RECURSIVE.
**
** Note that if one of the dynamic mutex parameters (SQLITE4_MUTEX_FAST
** or SQLITE4_MUTEX_RECURSIVE) is used then sqlite4_mutex_alloc()
** returns a different mutex on every call.  But for the static 
** mutex types, the same mutex is returned on every call that has
** the same type number.
*/
static sqlite4_mutex *pthreadMutexAlloc(void *pMutexEnv, int iType){
  sqlite4_env *pEnv = (sqlite4_env*)pMutexEnv;
  sqlite4UnixMutex *p;

  static sqlite4UnixMutex aStaticMutex[] = {
    SQLITE4_MUTEX_INITIALIZER
  };

  switch( iType ){
    case SQLITE4_MUTEX_RECURSIVE: {
      p = sqlite4MallocZero(pEnv, sizeof(*p) );
      if( p ){
#ifdef SQLITE4_HOMEGROWN_RECURSIVE_MUTEX
        /* If recursive mutexes are not available, we will have to
        ** build our own.  See below. */
        pthread_mutex_init(&p->mutex, 0);
#else
        /* Use a recursive mutex if it is available */
        pthread_mutexattr_t recursiveAttr;
        pthread_mutexattr_init(&recursiveAttr);
        pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
        pthread_mutex_init(&p->mutex, &recursiveAttr);
        pthread_mutexattr_destroy(&recursiveAttr);
#endif
#if SQLITE4_MUTEX_NREF
        p->id = iType;
#endif
        p->base.pMutexMethods = &pEnv->mutex;
      }
      break;
    }
    case SQLITE4_MUTEX_FAST: {
      p = sqlite4MallocZero(pEnv, sizeof(*p) );
      if( p ){
#if SQLITE4_MUTEX_NREF
        p->id = iType;
#endif
        pthread_mutex_init(&p->mutex, 0);
        p->base.pMutexMethods = &pEnv->mutex;
        assert( p->base.pMutexMethods->pMutexEnv==(void*)pEnv );
      }
      break;
    }
    default: {
      assert( SQLITE4_MUTEX_RECURSIVE==1 && SQLITE4_MUTEX_FAST==0 );
      assert( (iType-2)<ArraySize(aStaticMutex) );
      p = &aStaticMutex[iType-2];
      break;
    }
  }
  return (sqlite4_mutex*)p;
}


/*
** This routine deallocates a previously
** allocated mutex.  SQLite is careful to deallocate every
** mutex that it allocates.
*/
static void pthreadMutexFree(sqlite4_mutex *pMutex){
  sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex;
  sqlite4_env *pEnv;
  assert( p->nRef==0 );
  assert( p->id==SQLITE4_MUTEX_FAST || p->id==SQLITE4_MUTEX_RECURSIVE );
  pthread_mutex_destroy(&p->mutex);
  pEnv = (sqlite4_env*)p->base.pMutexMethods->pMutexEnv;
  sqlite4_free(pEnv, p);
}

/*
** The sqlite4_mutex_enter() and sqlite4_mutex_try() routines attempt
** to enter a mutex.  If another thread is already within the mutex,
** sqlite4_mutex_enter() will block and sqlite4_mutex_try() will return
** SQLITE4_BUSY.  The sqlite4_mutex_try() interface returns SQLITE4_OK
** upon successful entry.  Mutexes created using SQLITE4_MUTEX_RECURSIVE can
** be entered multiple times by the same thread.  In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter.  If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
static void pthreadMutexEnter(sqlite4_mutex *pMutex){
  sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex;
  assert( p->id==SQLITE4_MUTEX_RECURSIVE || pthreadMutexNotheld(pMutex) );

#ifdef SQLITE4_HOMEGROWN_RECURSIVE_MUTEX
  /* If recursive mutexes are not available, then we have to grow
  ** our own.  This implementation assumes that pthread_equal()
  ** is atomic - that it cannot be deceived into thinking self
  ** and p->owner are equal if p->owner changes between two values
  ** that are not equal to self while the comparison is taking place.
  ** This implementation also assumes a coherent cache - that 
  ** separate processes cannot read different values from the same
  ** address at the same time.  If either of these two conditions
  ** are not met, then the mutexes will fail and problems will result.
  */
  {
    pthread_t self = pthread_self();
    if( p->nRef>0 && pthread_equal(p->owner, self) ){
      p->nRef++;
    }else{
      pthread_mutex_lock(&p->mutex);
      assert( p->nRef==0 );
      p->owner = self;
      p->nRef = 1;
    }
  }
#else
  /* Use the built-in recursive mutexes if they are available.
  */
  pthread_mutex_lock(&p->mutex);
#if SQLITE4_MUTEX_NREF
  assert( p->nRef>0 || p->owner==0 );
  p->owner = pthread_self();
  p->nRef++;
#endif
#endif

#ifdef SQLITE4_DEBUG
  if( p->trace ){
    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
}
static int pthreadMutexTry(sqlite4_mutex *pMutex){
  int rc;
  sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex;
  assert( p->id==SQLITE4_MUTEX_RECURSIVE || pthreadMutexNotheld(pMutex) );

#ifdef SQLITE4_HOMEGROWN_RECURSIVE_MUTEX
  /* If recursive mutexes are not available, then we have to grow
  ** our own.  This implementation assumes that pthread_equal()
  ** is atomic - that it cannot be deceived into thinking self
  ** and p->owner are equal if p->owner changes between two values
  ** that are not equal to self while the comparison is taking place.
  ** This implementation also assumes a coherent cache - that 
  ** separate processes cannot read different values from the same
  ** address at the same time.  If either of these two conditions
  ** are not met, then the mutexes will fail and problems will result.
  */
  {
    pthread_t self = pthread_self();
    if( p->nRef>0 && pthread_equal(p->owner, self) ){
      p->nRef++;
      rc = SQLITE4_OK;
    }else if( pthread_mutex_trylock(&p->mutex)==0 ){
      assert( p->nRef==0 );
      p->owner = self;
      p->nRef = 1;
      rc = SQLITE4_OK;
    }else{
      rc = SQLITE4_BUSY;
    }
  }
#else
  /* Use the built-in recursive mutexes if they are available.
  */
  if( pthread_mutex_trylock(&p->mutex)==0 ){
#if SQLITE4_MUTEX_NREF
    p->owner = pthread_self();
    p->nRef++;
#endif
    rc = SQLITE4_OK;
  }else{
    rc = SQLITE4_BUSY;
  }
#endif

#ifdef SQLITE4_DEBUG
  if( rc==SQLITE4_OK && p->trace ){
    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
  return rc;
}

/*
** The sqlite4_mutex_leave() routine exits a mutex that was
** previously entered by the same thread.  The behavior
** is undefined if the mutex is not currently entered or
** is not currently allocated.  SQLite will never do either.
*/
static void pthreadMutexLeave(sqlite4_mutex *pMutex){
  sqlite4UnixMutex *p = (sqlite4UnixMutex*)pMutex;
  assert( pthreadMutexHeld(pMutex) );
#if SQLITE4_MUTEX_NREF
  p->nRef--;
  if( p->nRef==0 ) p->owner = 0;
#endif
  assert( p->nRef==0 || p->id==SQLITE4_MUTEX_RECURSIVE );

#ifdef SQLITE4_HOMEGROWN_RECURSIVE_MUTEX
  if( p->nRef==0 ){
    pthread_mutex_unlock(&p->mutex);
  }
#else
  pthread_mutex_unlock(&p->mutex);
#endif

#ifdef SQLITE4_DEBUG
  if( p->trace ){
    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
}

SQLITE4_PRIVATE sqlite4_mutex_methods const *sqlite4DefaultMutex(void){
  return &sMutexMethods;
}

#endif /* SQLITE4_MUTEX_PTHREADS */

/************** End of mutex_unix.c ******************************************/
/************** Begin file mutex_w32.c ***************************************/
/*
** 2007 August 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement mutexes for win32
*/

/*
** The code in this file is only used if we are compiling multithreaded
** on a win32 system.
*/
#ifdef SQLITE4_MUTEX_W32

/*
** Each recursive mutex is an instance of the following structure.
*/
struct sqlite4_mutex {
  CRITICAL_SECTION mutex;    /* Mutex controlling the lock */
  int id;                    /* Mutex type */
#ifdef SQLITE4_DEBUG
  volatile int nRef;         /* Number of enterances */
  volatile DWORD owner;      /* Thread holding this mutex */
  int trace;                 /* True to trace changes */
#endif
};
#define SQLITE4_W32_MUTEX_INITIALIZER { 0 }
#ifdef SQLITE4_DEBUG
#define SQLITE3_MUTEX_INITIALIZER { SQLITE4_W32_MUTEX_INITIALIZER, 0, 0L, (DWORD)0, 0 }
#else
#define SQLITE3_MUTEX_INITIALIZER { SQLITE4_W32_MUTEX_INITIALIZER, 0 }
#endif

/*
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
**
** Here is an interesting observation:  Win95, Win98, and WinME lack
** the LockFileEx() API.  But we can still statically link against that
** API as long as we don't call it win running Win95/98/ME.  A call to
** this routine is used to determine if the host is Win95/98/ME or
** WinNT/2K/XP so that we will know whether or not we can safely call
** the LockFileEx() API.
**
** mutexIsNT() is only used for the TryEnterCriticalSection() API call,
** which is only available if your application was compiled with 
** _WIN32_WINNT defined to a value >= 0x0400.  Currently, the only
** call to TryEnterCriticalSection() is #ifdef'ed out, so #ifdef 
** this out as well.
*/
#if 0
#if SQLITE4_OS_WINCE
# define mutexIsNT()  (1)
#else
  static int mutexIsNT(void){
    static int osType = 0;
    if( osType==0 ){
      OSVERSIONINFO sInfo;
      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
      GetVersionEx(&sInfo);
      osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
    }
    return osType==2;
  }
#endif /* SQLITE4_OS_WINCE */
#endif

#ifdef SQLITE4_DEBUG
/*
** The sqlite4_mutex_held() and sqlite4_mutex_notheld() routine are
** intended for use only inside assert() statements.
*/
static int winMutexHeld(sqlite4_mutex *p){
  return p->nRef!=0 && p->owner==GetCurrentThreadId();
}
static int winMutexNotheld2(sqlite4_mutex *p, DWORD tid){
  return p->nRef==0 || p->owner!=tid;
}
static int winMutexNotheld(sqlite4_mutex *p){
  DWORD tid = GetCurrentThreadId(); 
  return winMutexNotheld2(p, tid);
}
#endif


/*
** Initialize and deinitialize the mutex subsystem.
*/
static sqlite4_mutex winMutex_staticMutexes[6] = {
  SQLITE3_MUTEX_INITIALIZER,
  SQLITE3_MUTEX_INITIALIZER,
  SQLITE3_MUTEX_INITIALIZER,
  SQLITE3_MUTEX_INITIALIZER,
  SQLITE3_MUTEX_INITIALIZER,
  SQLITE3_MUTEX_INITIALIZER
};
static int winMutex_isInit = 0;
/* As winMutexInit() and winMutexEnd() are called as part
** of the sqlite4_initialize and sqlite4_shutdown()
** processing, the "interlocked" magic is probably not
** strictly necessary.
*/
static long winMutex_lock = 0;

static int winMutexInit(void){ 
  /* The first to increment to 1 does actual initialization */
  if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
    int i;
    for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
      InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
    }
    winMutex_isInit = 1;
  }else{
    /* Someone else is in the process of initing the static mutexes */
    while( !winMutex_isInit ){
      Sleep(1);
    }
  }
  return SQLITE4_OK; 
}

static int winMutexEnd(void){ 
  /* The first to decrement to 0 does actual shutdown 
  ** (which should be the last to shutdown.) */
  if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
    if( winMutex_isInit==1 ){
      int i;
      for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
        DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
      }
      winMutex_isInit = 0;
    }
  }
  return SQLITE4_OK; 
}

/*
** The sqlite4_mutex_alloc() routine allocates a new
** mutex and returns a pointer to it.  If it returns NULL
** that means that a mutex could not be allocated.  SQLite
** will unwind its stack and return an error.  The argument
** to sqlite4_mutex_alloc() is one of these integer constants:
**
** <ul>
** <li>  SQLITE4_MUTEX_FAST
** <li>  SQLITE4_MUTEX_RECURSIVE
** <li>  SQLITE4_MUTEX_STATIC_MASTER
** <li>  SQLITE4_MUTEX_STATIC_MEM
** <li>  SQLITE4_MUTEX_STATIC_MEM2
** <li>  SQLITE4_MUTEX_STATIC_PRNG
** <li>  SQLITE4_MUTEX_STATIC_LRU
** <li>  SQLITE4_MUTEX_STATIC_PMEM
** </ul>
**
** The first two constants cause sqlite4_mutex_alloc() to create
** a new mutex.  The new mutex is recursive when SQLITE4_MUTEX_RECURSIVE
** is used but not necessarily so when SQLITE4_MUTEX_FAST is used.
** The mutex implementation does not need to make a distinction
** between SQLITE4_MUTEX_RECURSIVE and SQLITE4_MUTEX_FAST if it does
** not want to.  But SQLite will only request a recursive mutex in
** cases where it really needs one.  If a faster non-recursive mutex
** implementation is available on the host platform, the mutex subsystem
** might return such a mutex in response to SQLITE4_MUTEX_FAST.
**
** The other allowed parameters to sqlite4_mutex_alloc() each return
** a pointer to a static preexisting mutex.  Six static mutexes are
** used by the current version of SQLite.  Future versions of SQLite
** may add additional static mutexes.  Static mutexes are for internal
** use by SQLite only.  Applications that use SQLite mutexes should
** use only the dynamic mutexes returned by SQLITE4_MUTEX_FAST or
** SQLITE4_MUTEX_RECURSIVE.
**
** Note that if one of the dynamic mutex parameters (SQLITE4_MUTEX_FAST
** or SQLITE4_MUTEX_RECURSIVE) is used then sqlite4_mutex_alloc()
** returns a different mutex on every call.  But for the static 
** mutex types, the same mutex is returned on every call that has
** the same type number.
*/
static sqlite4_mutex *winMutexAlloc(int iType){
  sqlite4_mutex *p;

  switch( iType ){
    case SQLITE4_MUTEX_FAST:
    case SQLITE4_MUTEX_RECURSIVE: {
      p = sqlite4MallocZero(0, sizeof(*p) );
      if( p ){  
#ifdef SQLITE4_DEBUG
        p->id = iType;
#endif
        InitializeCriticalSection(&p->mutex);
      }
      break;
    }
    default: {
      assert( winMutex_isInit==1 );
      assert( iType-2 >= 0 );
      assert( iType-2 < ArraySize(winMutex_staticMutexes) );
      p = &winMutex_staticMutexes[iType-2];
#ifdef SQLITE4_DEBUG
      p->id = iType;
#endif
      break;
    }
  }
  return p;
}


/*
** This routine deallocates a previously
** allocated mutex.  SQLite is careful to deallocate every
** mutex that it allocates.
*/
static void winMutexFree(sqlite4_mutex *p){
  assert( p );
  assert( p->nRef==0 && p->owner==0 );
  assert( p->id==SQLITE4_MUTEX_FAST || p->id==SQLITE4_MUTEX_RECURSIVE );
  DeleteCriticalSection(&p->mutex);
  sqlite4_free(0, p);
}

/*
** The sqlite4_mutex_enter() and sqlite4_mutex_try() routines attempt
** to enter a mutex.  If another thread is already within the mutex,
** sqlite4_mutex_enter() will block and sqlite4_mutex_try() will return
** SQLITE4_BUSY.  The sqlite4_mutex_try() interface returns SQLITE4_OK
** upon successful entry.  Mutexes created using SQLITE4_MUTEX_RECURSIVE can
** be entered multiple times by the same thread.  In such cases the,
** mutex must be exited an equal number of times before another thread
** can enter.  If the same thread tries to enter any other kind of mutex
** more than once, the behavior is undefined.
*/
static void winMutexEnter(sqlite4_mutex *p){
#ifdef SQLITE4_DEBUG
  DWORD tid = GetCurrentThreadId(); 
  assert( p->id==SQLITE4_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
#endif
  EnterCriticalSection(&p->mutex);
#ifdef SQLITE4_DEBUG
  assert( p->nRef>0 || p->owner==0 );
  p->owner = tid; 
  p->nRef++;
  if( p->trace ){
    printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
}
static int winMutexTry(sqlite4_mutex *p){
#ifndef NDEBUG
  DWORD tid = GetCurrentThreadId(); 
#endif
  int rc = SQLITE4_BUSY;
  assert( p->id==SQLITE4_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
  /*
  ** The sqlite4_mutex_try() routine is very rarely used, and when it
  ** is used it is merely an optimization.  So it is OK for it to always
  ** fail.  
  **
  ** The TryEnterCriticalSection() interface is only available on WinNT.
  ** And some windows compilers complain if you try to use it without
  ** first doing some #defines that prevent SQLite from building on Win98.
  ** For that reason, we will omit this optimization for now.  See
  ** ticket #2685.
  */
#if 0
  if( mutexIsNT() && TryEnterCriticalSection(&p->mutex) ){
    p->owner = tid;
    p->nRef++;
    rc = SQLITE4_OK;
  }
#else
  UNUSED_PARAMETER(p);
#endif
#ifdef SQLITE4_DEBUG
  if( rc==SQLITE4_OK && p->trace ){
    printf("try mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
  return rc;
}

/*
** The sqlite4_mutex_leave() routine exits a mutex that was
** previously entered by the same thread.  The behavior
** is undefined if the mutex is not currently entered or
** is not currently allocated.  SQLite will never do either.
*/
static void winMutexLeave(sqlite4_mutex *p){
#ifndef NDEBUG
  DWORD tid = GetCurrentThreadId();
  assert( p->nRef>0 );
  assert( p->owner==tid );
  p->nRef--;
  if( p->nRef==0 ) p->owner = 0;
  assert( p->nRef==0 || p->id==SQLITE4_MUTEX_RECURSIVE );
#endif
  LeaveCriticalSection(&p->mutex);
#ifdef SQLITE4_DEBUG
  if( p->trace ){
    printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
  }
#endif
}

SQLITE4_PRIVATE sqlite4_mutex_methods const *sqlite4DefaultMutex(void){
  static const sqlite4_mutex_methods sMutex = {
    winMutexInit,
    winMutexEnd,
    winMutexAlloc,
    winMutexFree,
    winMutexEnter,
    winMutexTry,
    winMutexLeave,
#ifdef SQLITE4_DEBUG
    winMutexHeld,
    winMutexNotheld
#else
    0,
    0
#endif
  };

  return &sMutex;
}
#endif /* SQLITE4_MUTEX_W32 */

/************** End of mutex_w32.c *******************************************/
/************** Begin file malloc.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Memory allocation functions used throughout sqlite.
*/
/* #include <stdarg.h> */

/*
** Initialize the memory allocation subsystem.
*/
SQLITE4_PRIVATE int sqlite4MallocInit(sqlite4_env *pEnv){
  /* TODO: SQLite3 has sqlite3_mem_methods.xInit. But src4 does not? */
  return SQLITE4_OK;
}

/*
** Deinitialize the memory allocation subsystem.
*/
SQLITE4_PRIVATE void sqlite4MallocEnd(sqlite4_env *pEnv){
  /* TODO: Should sqlite4_mm_methods.xFinal() be called here? Or some 
  ** reference count decremented? */
}

/*
** Allocate memory.  This routine is like sqlite4_malloc() except that it
** assumes the memory subsystem has already been initialized.
*/
SQLITE4_PRIVATE void *sqlite4Malloc(sqlite4_env *pEnv, int n){
  void *p;                        /* Return value */
  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;

  if( n<=0               /* IMP: R-65312-04917 */ 
   || n>=0x7fffff00
  ){
    /* A memory allocation of a number of bytes which is near the maximum
    ** signed integer value might cause an integer overflow inside of the
    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
    ** 255 bytes of overhead.  SQLite itself will never use anything near
    ** this amount.  The only way to reach the limit is with sqlite4_malloc() */
    p = 0;
  }else{
    p = sqlite4_mm_malloc(pEnv->pMM, n);
  }

  assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
  return p;
}

/*
** This version of the memory allocation is for use by the application.
** First make sure the memory subsystem is initialized, then do the
** allocation.
*/
SQLITE4_API void *sqlite4_malloc(sqlite4_env *pEnv, sqlite4_size_t n){
#ifndef SQLITE4_OMIT_AUTOINIT
  if( sqlite4_initialize(pEnv) ) return 0;
#endif
  return sqlite4Malloc(pEnv, (int)n);
}


/*
** TRUE if p is a lookaside memory allocation from db
*/
#ifndef SQLITE4_OMIT_LOOKASIDE
static int isLookaside(sqlite4 *db, void *p){
  return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
}
#else
#define isLookaside(A,B) 0
#endif

/*
** Return the size of a memory allocation previously obtained from
** sqlite4Malloc() or sqlite4_malloc().
*/
SQLITE4_PRIVATE int sqlite4MallocSize(sqlite4_env *pEnv, void *p){
  assert( sqlite4MemdebugHasType(p, MEMTYPE_HEAP) );
  assert( sqlite4MemdebugNoType(p, MEMTYPE_DB) );

  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
  return sqlite4_mm_msize(pEnv->pMM, p);
}
SQLITE4_PRIVATE int sqlite4DbMallocSize(sqlite4 *db, void *p){
  assert( db==0 || sqlite4_mutex_held(db->mutex) );
  if( db && isLookaside(db, p) ){
    return db->lookaside.sz;
  }else{
    return sqlite4MallocSize(sqlite4_db_env(db), p);
  }
}

/*
** Free memory previously obtained from sqlite4Malloc().
*/
SQLITE4_API void sqlite4_free(sqlite4_env *pEnv, void *p){
  if( p==0 ) return;  /* IMP: R-49053-54554 */
  assert( sqlite4MemdebugNoType(p, MEMTYPE_DB) );
  assert( sqlite4MemdebugHasType(p, MEMTYPE_HEAP) );

  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
  sqlite4_mm_free(pEnv->pMM, p);
}

/*
** Free memory that might be associated with a particular database
** connection.
*/
SQLITE4_PRIVATE void sqlite4DbFree(sqlite4 *db, void *p){
  assert( db==0 || sqlite4_mutex_held(db->mutex) );
  if( db ){
    if( db->pnBytesFreed ){
      *db->pnBytesFreed += sqlite4DbMallocSize(db, p);
      return;
    }
    if( isLookaside(db, p) ){
      LookasideSlot *pBuf = (LookasideSlot*)p;
      pBuf->pNext = db->lookaside.pFree;
      db->lookaside.pFree = pBuf;
      db->lookaside.nOut--;
      return;
    }
  }
  assert( sqlite4MemdebugHasType(p, MEMTYPE_DB) );
  assert( sqlite4MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
  assert( db!=0 || sqlite4MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
  sqlite4MemdebugSetType(p, MEMTYPE_HEAP);
  sqlite4_free(db==0 ? 0 : db->pEnv, p);
}

/*
** Change the size of an existing memory allocation
*/
SQLITE4_PRIVATE void *sqlite4Realloc(sqlite4_env *pEnv, void *pOld, int nBytes){
  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;

  if( pOld==0 ){
    return sqlite4Malloc(pEnv, nBytes); /* IMP: R-28354-25769 */
  }
  if( nBytes<=0 ){
    sqlite4_free(pEnv, pOld); /* IMP: R-31593-10574 */
    return 0;
  }
  if( nBytes>=0x7fffff00 ){
    /* The 0x7ffff00 limit term is explained in comments on sqlite4Malloc() */
    return 0;
  }

  return sqlite4_mm_realloc(pEnv->pMM, pOld, nBytes);
}

/*
** The public interface to sqlite4Realloc.  Make sure that the memory
** subsystem is initialized prior to invoking sqliteRealloc.
*/
SQLITE4_API void *sqlite4_realloc(sqlite4_env *pEnv, void *pOld, sqlite4_size_t n){
#ifndef SQLITE4_OMIT_AUTOINIT
  if( sqlite4_initialize(pEnv) ) return 0;
#endif
  return sqlite4Realloc(pEnv, pOld, (int)n);
}


/*
** Allocate and zero memory.
*/ 
SQLITE4_PRIVATE void *sqlite4MallocZero(sqlite4_env *pEnv, int n){
  void *p = sqlite4Malloc(pEnv, n);
  if( p ){
    memset(p, 0, n);
  }
  return p;
}

/*
** Allocate and zero memory.  If the allocation fails, make
** the mallocFailed flag in the connection pointer.
*/
SQLITE4_PRIVATE void *sqlite4DbMallocZero(sqlite4 *db, int n){
  void *p = sqlite4DbMallocRaw(db, n);
  if( p ){
    memset(p, 0, n);
  }
  return p;
}

/*
** Allocate and zero memory.  If the allocation fails, make
** the mallocFailed flag in the connection pointer.
**
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
** failure on the same database connection) then always return 0.
** Hence for a particular database connection, once malloc starts
** failing, it fails consistently until mallocFailed is reset.
** This is an important assumption.  There are many places in the
** code that do things like this:
**
**         int *a = (int*)sqlite4DbMallocRaw(db, 100);
**         int *b = (int*)sqlite4DbMallocRaw(db, 200);
**         if( b ) a[10] = 9;
**
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
** that all prior mallocs (ex: "a") worked too.
*/
SQLITE4_PRIVATE void *sqlite4DbMallocRaw(sqlite4 *db, int n){
  void *p;
  assert( db==0 || sqlite4_mutex_held(db->mutex) );
  assert( db==0 || db->pnBytesFreed==0 );
#ifndef SQLITE4_OMIT_LOOKASIDE
  if( db ){
    LookasideSlot *pBuf;
    if( db->mallocFailed ){
      return 0;
    }
    if( db->lookaside.bEnabled ){
      if( n>db->lookaside.sz ){
        db->lookaside.anStat[1]++;
      }else if( (pBuf = db->lookaside.pFree)==0 ){
        db->lookaside.anStat[2]++;
      }else{
        db->lookaside.pFree = pBuf->pNext;
        db->lookaside.nOut++;
        db->lookaside.anStat[0]++;
        if( db->lookaside.nOut>db->lookaside.mxOut ){
          db->lookaside.mxOut = db->lookaside.nOut;
        }
        return (void*)pBuf;
      }
    }
  }
#else
  if( db && db->mallocFailed ){
    return 0;
  }
#endif
  p = sqlite4Malloc((db ? db->pEnv: 0), n);
  if( !p && db ){
    db->mallocFailed = 1;
  }
  sqlite4MemdebugSetType(p, MEMTYPE_DB |
         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
  return p;
}

/*
** Resize the block of memory pointed to by p to n bytes. If the
** resize fails, set the mallocFailed flag in the connection object.
*/
SQLITE4_PRIVATE void *sqlite4DbRealloc(sqlite4 *db, void *p, int n){
  void *pNew = 0;
  assert( db!=0 );
  assert( sqlite4_mutex_held(db->mutex) );
  if( db->mallocFailed==0 ){
    if( p==0 ){
      return sqlite4DbMallocRaw(db, n);
    }
    if( isLookaside(db, p) ){
      if( n<=db->lookaside.sz ){
        return p;
      }
      pNew = sqlite4DbMallocRaw(db, n);
      if( pNew ){
        memcpy(pNew, p, db->lookaside.sz);
        sqlite4DbFree(db, p);
      }
    }else{
      assert( sqlite4MemdebugHasType(p, MEMTYPE_DB) );
      assert( sqlite4MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
      sqlite4MemdebugSetType(p, MEMTYPE_HEAP);
      pNew = sqlite4_realloc(db->pEnv, p, n);
      if( !pNew ){
        sqlite4MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
        db->mallocFailed = 1;
      }
      sqlite4MemdebugSetType(pNew, MEMTYPE_DB | 
            (db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
    }
  }
  return pNew;
}

/*
** Attempt to reallocate p.  If the reallocation fails, then free p
** and set the mallocFailed flag in the database connection.
*/
SQLITE4_PRIVATE void *sqlite4DbReallocOrFree(sqlite4 *db, void *p, int n){
  void *pNew;
  pNew = sqlite4DbRealloc(db, p, n);
  if( !pNew ){
    sqlite4DbFree(db, p);
  }
  return pNew;
}

/*
** Make a copy of a string in memory obtained from sqliteMalloc(). These 
** functions call sqlite4MallocRaw() directly instead of sqliteMalloc(). This
** is because when memory debugging is turned on, these two functions are 
** called via macros that record the current file and line number in the
** ThreadData structure.
*/
SQLITE4_PRIVATE char *sqlite4DbStrDup(sqlite4 *db, const char *z){
  char *zNew;
  size_t n;
  if( z==0 ){
    return 0;
  }
  n = sqlite4Strlen30(z) + 1;
  assert( (n&0x7fffffff)==n );
  zNew = sqlite4DbMallocRaw(db, (int)n);
  if( zNew ){
    memcpy(zNew, z, n);
  }
  return zNew;
}
SQLITE4_PRIVATE char *sqlite4DbStrNDup(sqlite4 *db, const char *z, int n){
  char *zNew;
  if( z==0 ){
    return 0;
  }
  assert( (n&0x7fffffff)==n );
  zNew = sqlite4DbMallocRaw(db, n+1);
  if( zNew ){
    memcpy(zNew, z, n);
    zNew[n] = 0;
  }
  return zNew;
}

/*
** Create a string from the zFromat argument and the va_list that follows.
** Store the string in memory obtained from sqliteMalloc() and make *pz
** point to that string.
*/
SQLITE4_PRIVATE void sqlite4SetString(char **pz, sqlite4 *db, const char *zFormat, ...){
  va_list ap;
  char *z;

  va_start(ap, zFormat);
  z = sqlite4VMPrintf(db, zFormat, ap);
  va_end(ap);
  sqlite4DbFree(db, *pz);
  *pz = z;
}


/*
** This function must be called before exiting any API function (i.e. 
** returning control to the user) that has called sqlite4_malloc or
** sqlite4_realloc.
**
** The returned value is normally a copy of the second argument to this
** function. However, if a malloc() failure has occurred since the previous
** invocation SQLITE4_NOMEM is returned instead. 
**
** If the first argument, db, is not NULL and a malloc() error has occurred,
** then the connection error-code (the value returned by sqlite4_errcode())
** is set to SQLITE4_NOMEM.
*/
SQLITE4_PRIVATE int sqlite4ApiExit(sqlite4* db, int rc){
  /* If the db handle is not NULL, then we must hold the connection handle
  ** mutex here. Otherwise the read (and possible write) of db->mallocFailed 
  ** is unsafe, as is the call to sqlite4Error().
  */
  assert( !db || sqlite4_mutex_held(db->mutex) );
  if( db && (db->mallocFailed || rc==SQLITE4_IOERR_NOMEM) ){
    sqlite4Error(db, SQLITE4_NOMEM, 0);
    db->mallocFailed = 0;
    rc = SQLITE4_NOMEM;
  }
  return rc;
}

/************** End of malloc.c **********************************************/
/************** Begin file printf.c ******************************************/
/*
** The "printf" code that follows dates from the 1980's.  It is in
** the public domain.  The original comments are included here for
** completeness.  They are very out-of-date but might be useful as
** an historical reference.  Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
**************************************************************************
**
** This file contains code for a set of "printf"-like routines.  These
** routines format strings much like the printf() from the standard C
** library, though the implementation here has enhancements to support
** SQLlite.
*/

/*
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
#define etRADIX       1 /* Integer types.  %d, %x, %o, and so forth */
#define etFLOAT       2 /* Floating point.  %f */
#define etEXP         3 /* Exponentional notation. %e and %E */
#define etGENERIC     4 /* Floating or exponential, depending on exponent. %g */
#define etSIZE        5 /* Return number of characters processed so far. %n */
#define etSTRING      6 /* Strings. %s */
#define etDYNSTRING   7 /* Dynamically allocated strings. %z */
#define etPERCENT     8 /* Percent symbol. %% */
#define etCHARX       9 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
#define etSQLESCAPE  10 /* Strings with '\'' doubled.  %q */
#define etSQLESCAPE2 11 /* Strings with '\'' doubled and enclosed in '',
                          NULL pointers replaced by SQL NULL.  %Q */
#define etTOKEN      12 /* a pointer to a Token structure */
#define etSRCLIST    13 /* a pointer to a SrcList */
#define etPOINTER    14 /* The %p conversion */
#define etSQLESCAPE3 15 /* %w -> Strings with '\"' doubled */
#define etORDINAL    16 /* %r -> 1st, 2nd, 3rd, 4th, etc.  English only */

#define etINVALID     0 /* Any unrecognized conversion type */


/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;

/*
** Each builtin conversion character (ex: the 'd' in "%d") is described
** by an instance of the following structure
*/
typedef struct et_info {   /* Information about each format field */
  char fmttype;            /* The format field code letter */
  etByte base;             /* The base for radix conversion */
  etByte flags;            /* One or more of FLAG_ constants below */
  etByte type;             /* Conversion paradigm */
  etByte charset;          /* Offset into aDigits[] of the digits string */
  etByte prefix;           /* Offset into aPrefix[] of the prefix string */
} et_info;

/*
** Allowed values for et_info.flags
*/
#define FLAG_SIGNED  1     /* True if the value to convert is signed */
#define FLAG_INTERN  2     /* True if for internal use only */
#define FLAG_STRING  4     /* Allow infinity precision */


/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
static const char aDigits[] = "0123456789abcdef0123456789ABCDEF";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
  {  'd', 10, 1, etRADIX,      0,  0 },
  {  's',  0, 4, etSTRING,     0,  0 },
  {  'g',  0, 1, etGENERIC,    14, 0 },
  {  'z',  0, 4, etDYNSTRING,  0,  0 },
  {  'q',  0, 4, etSQLESCAPE,  0,  0 },
  {  'Q',  0, 4, etSQLESCAPE2, 0,  0 },
  {  'w',  0, 4, etSQLESCAPE3, 0,  0 },
  {  'c',  0, 0, etCHARX,      0,  0 },
  {  'o',  8, 0, etRADIX,      0,  2 },
  {  'u', 10, 0, etRADIX,      0,  0 },
  {  'x', 16, 0, etRADIX,      0,  1 },
  {  'X', 16, 0, etRADIX,      16, 4 },
#ifndef SQLITE4_OMIT_FLOATING_POINT
  {  'f',  0, 1, etFLOAT,      0,  0 },
  {  'e',  0, 1, etEXP,        14, 0 },
  {  'E',  0, 1, etEXP,        30, 0 },
  {  'G',  0, 1, etGENERIC,    30, 0 },
#endif
  {  'i', 10, 1, etRADIX,      0,  0 },
  {  'n',  0, 0, etSIZE,       0,  0 },
  {  '%',  0, 0, etPERCENT,    0,  0 },
  {  'p', 16, 0, etPOINTER,    0,  1 },

/* All the rest have the FLAG_INTERN bit set and are thus for internal
** use only */
  {  'T',  0, 2, etTOKEN,      0,  0 },
  {  'S',  0, 2, etSRCLIST,    0,  0 },
  {  'r', 10, 3, etORDINAL,    0,  0 },
};

/*
** If SQLITE4_OMIT_FLOATING_POINT is defined, then none of the floating point
** conversions will work.
*/
#ifndef SQLITE4_OMIT_FLOATING_POINT
/*
** "*val" is a double such that 0.1 <= *val < 10.0
** Return the ascii code for the leading digit of *val, then
** multiply "*val" by 10.0 to renormalize.
**
** Example:
**     input:     *val = 3.14159
**     output:    *val = 1.4159    function return = '3'
**
** The counter *cnt is incremented each time.  After counter exceeds
** 16 (the number of significant digits in a 64-bit float) '0' is
** always returned.
*/
static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
  int digit;
  LONGDOUBLE_TYPE d;
  if( (*cnt)++ >= 16 ) return '0';
  digit = (int)*val;
  d = digit;
  digit += '0';
  *val = (*val - d)*10.0;
  return (char)digit;
}
#endif /* SQLITE4_OMIT_FLOATING_POINT */

/*
** Append N space characters to the given string buffer.
*/
SQLITE4_PRIVATE void sqlite4AppendSpace(StrAccum *pAccum, int N){
  static const char zSpaces[] = "                             ";
  while( N>=(int)sizeof(zSpaces)-1 ){
    sqlite4StrAccumAppend(pAccum, zSpaces, sizeof(zSpaces)-1);
    N -= sizeof(zSpaces)-1;
  }
  if( N>0 ){
    sqlite4StrAccumAppend(pAccum, zSpaces, N);
  }
}

/*
** On machines with a small stack size, you can redefine the
** SQLITE4_PRINT_BUF_SIZE to be something smaller, if desired.
*/
#ifndef SQLITE4_PRINT_BUF_SIZE
# define SQLITE4_PRINT_BUF_SIZE 70
#endif
#define etBUFSIZE SQLITE4_PRINT_BUF_SIZE  /* Size of the output buffer */

/*
** Render a string given by "fmt" into the StrAccum object.
*/
SQLITE4_PRIVATE void sqlite4VXPrintf(
  StrAccum *pAccum,                  /* Accumulate results here */
  int useExtended,                   /* Allow extended %-conversions */
  const char *fmt,                   /* Format string */
  va_list ap                         /* arguments */
){
  int c;                     /* Next character in the format string */
  char *bufpt;               /* Pointer to the conversion buffer */
  int precision;             /* Precision of the current field */
  int length;                /* Length of the field */
  int idx;                   /* A general purpose loop counter */
  int width;                 /* Width of the current field */
  etByte flag_leftjustify;   /* True if "-" flag is present */
  etByte flag_plussign;      /* True if "+" flag is present */
  etByte flag_blanksign;     /* True if " " flag is present */
  etByte flag_alternateform; /* True if "#" flag is present */
  etByte flag_altform2;      /* True if "!" flag is present */
  etByte flag_zeropad;       /* True if field width constant starts with zero */
  etByte flag_long;          /* True if "l" flag is present */
  etByte flag_longlong;      /* True if the "ll" flag is present */
  etByte done;               /* Loop termination flag */
  etByte xtype = 0;          /* Conversion paradigm */
  char prefix;               /* Prefix character.  "+" or "-" or " " or '\0'. */
  sqlite4_uint64 longvalue;   /* Value for integer types */
  LONGDOUBLE_TYPE realvalue; /* Value for real types */
  const et_info *infop;      /* Pointer to the appropriate info structure */
  char *zOut;                /* Rendering buffer */
  int nOut;                  /* Size of the rendering buffer */
  char *zExtra;              /* Malloced memory used by some conversion */
#ifndef SQLITE4_OMIT_FLOATING_POINT
  int  exp, e2;              /* exponent of real numbers */
  int nsd;                   /* Number of significant digits returned */
  double rounder;            /* Used for rounding floating point values */
  etByte flag_dp;            /* True if decimal point should be shown */
  etByte flag_rtz;           /* True if trailing zeros should be removed */
#endif
  char buf[etBUFSIZE];       /* Conversion buffer */

  bufpt = 0;
  for(; (c=(*fmt))!=0; ++fmt){
    if( c!='%' ){
      int amt;
      bufpt = (char *)fmt;
      amt = 1;
      while( (c=(*++fmt))!='%' && c!=0 ) amt++;
      sqlite4StrAccumAppend(pAccum, bufpt, amt);
      if( c==0 ) break;
    }
    if( (c=(*++fmt))==0 ){
      sqlite4StrAccumAppend(pAccum, "%", 1);
      break;
    }
    /* Find out what flags are present */
    flag_leftjustify = flag_plussign = flag_blanksign = 
     flag_alternateform = flag_altform2 = flag_zeropad = 0;
    done = 0;
    do{
      switch( c ){
        case '-':   flag_leftjustify = 1;     break;
        case '+':   flag_plussign = 1;        break;
        case ' ':   flag_blanksign = 1;       break;
        case '#':   flag_alternateform = 1;   break;
        case '!':   flag_altform2 = 1;        break;
        case '0':   flag_zeropad = 1;         break;
        default:    done = 1;                 break;
      }
    }while( !done && (c=(*++fmt))!=0 );
    /* Get the field width */
    width = 0;
    if( c=='*' ){
      width = va_arg(ap,int);
      if( width<0 ){
        flag_leftjustify = 1;
        width = -width;
      }
      c = *++fmt;
    }else{
      while( c>='0' && c<='9' ){
        width = width*10 + c - '0';
        c = *++fmt;
      }
    }
    /* Get the precision */
    if( c=='.' ){
      precision = 0;
      c = *++fmt;
      if( c=='*' ){
        precision = va_arg(ap,int);
        if( precision<0 ) precision = -precision;
        c = *++fmt;
      }else{
        while( c>='0' && c<='9' ){
          precision = precision*10 + c - '0';
          c = *++fmt;
        }
      }
    }else{
      precision = -1;
    }
    /* Get the conversion type modifier */
    if( c=='l' ){
      flag_long = 1;
      c = *++fmt;
      if( c=='l' ){
        flag_longlong = 1;
        c = *++fmt;
      }else{
        flag_longlong = 0;
      }
    }else{
      flag_long = flag_longlong = 0;
    }
    /* Fetch the info entry for the field */
    infop = &fmtinfo[0];
    xtype = etINVALID;
    for(idx=0; idx<ArraySize(fmtinfo); idx++){
      if( c==fmtinfo[idx].fmttype ){
        infop = &fmtinfo[idx];
        if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
          xtype = infop->type;
        }else{
          return;
        }
        break;
      }
    }
    zExtra = 0;

    /*
    ** At this point, variables are initialized as follows:
    **
    **   flag_alternateform          TRUE if a '#' is present.
    **   flag_altform2               TRUE if a '!' is present.
    **   flag_plussign               TRUE if a '+' is present.
    **   flag_leftjustify            TRUE if a '-' is present or if the
    **                               field width was negative.
    **   flag_zeropad                TRUE if the width began with 0.
    **   flag_long                   TRUE if the letter 'l' (ell) prefixed
    **                               the conversion character.
    **   flag_longlong               TRUE if the letter 'll' (ell ell) prefixed
    **                               the conversion character.
    **   flag_blanksign              TRUE if a ' ' is present.
    **   width                       The specified field width.  This is
    **                               always non-negative.  Zero is the default.
    **   precision                   The specified precision.  The default
    **                               is -1.
    **   xtype                       The class of the conversion.
    **   infop                       Pointer to the appropriate info struct.
    */
    switch( xtype ){
      case etPOINTER:
        flag_longlong = sizeof(char*)==sizeof(i64);
        flag_long = sizeof(char*)==sizeof(long int);
        /* Fall through into the next case */
      case etORDINAL:
      case etRADIX:
        if( infop->flags & FLAG_SIGNED ){
          i64 v;
          if( flag_longlong ){
            v = va_arg(ap,i64);
          }else if( flag_long ){
            v = va_arg(ap,long int);
          }else{
            v = va_arg(ap,int);
          }
          if( v<0 ){
            if( v==SMALLEST_INT64 ){
              longvalue = ((u64)1)<<63;
            }else{
              longvalue = -v;
            }
            prefix = '-';
          }else{
            longvalue = v;
            if( flag_plussign )        prefix = '+';
            else if( flag_blanksign )  prefix = ' ';
            else                       prefix = 0;
          }
        }else{
          if( flag_longlong ){
            longvalue = va_arg(ap,u64);
          }else if( flag_long ){
            longvalue = va_arg(ap,unsigned long int);
          }else{
            longvalue = va_arg(ap,unsigned int);
          }
          prefix = 0;
        }
        if( longvalue==0 ) flag_alternateform = 0;
        if( flag_zeropad && precision<width-(prefix!=0) ){
          precision = width-(prefix!=0);
        }
        if( precision<etBUFSIZE-10 ){
          nOut = etBUFSIZE;
          zOut = buf;
        }else{
          nOut = precision + 10;
          zOut = zExtra = sqlite4Malloc(pAccum->pEnv, nOut);
          if( zOut==0 ){
            pAccum->mallocFailed = 1;
            return;
          }
        }
        bufpt = &zOut[nOut-1];
        if( xtype==etORDINAL ){
          static const char zOrd[] = "thstndrd";
          int x = (int)(longvalue % 10);
          if( x>=4 || (longvalue/10)%10==1 ){
            x = 0;
          }
          *(--bufpt) = zOrd[x*2+1];
          *(--bufpt) = zOrd[x*2];
        }
        {
          register const char *cset;      /* Use registers for speed */
          register int base;
          cset = &aDigits[infop->charset];
          base = infop->base;
          do{                                           /* Convert to ascii */
            *(--bufpt) = cset[longvalue%base];
            longvalue = longvalue/base;
          }while( longvalue>0 );
        }
        length = (int)(&zOut[nOut-1]-bufpt);
        for(idx=precision-length; idx>0; idx--){
          *(--bufpt) = '0';                             /* Zero pad */
        }
        if( prefix ) *(--bufpt) = prefix;               /* Add sign */
        if( flag_alternateform && infop->prefix ){      /* Add "0" or "0x" */
          const char *pre;
          char x;
          pre = &aPrefix[infop->prefix];
          for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
        }
        length = (int)(&zOut[nOut-1]-bufpt);
        break;
      case etFLOAT:
      case etEXP:
      case etGENERIC:
        realvalue = va_arg(ap,double);
#ifdef SQLITE4_OMIT_FLOATING_POINT
        length = 0;
#else
        if( precision<0 ) precision = 6;         /* Set default precision */
        if( realvalue<0.0 ){
          realvalue = -realvalue;
          prefix = '-';
        }else{
          if( flag_plussign )          prefix = '+';
          else if( flag_blanksign )    prefix = ' ';
          else                         prefix = 0;
        }
        if( xtype==etGENERIC && precision>0 ) precision--;
#if 0
        /* Rounding works like BSD when the constant 0.4999 is used.  Wierd! */
        for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
#else
        /* It makes more sense to use 0.5 */
        for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
#endif
        if( xtype==etFLOAT ) realvalue += rounder;
        /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
        exp = 0;
        if( sqlite4IsNaN((double)realvalue) ){
          bufpt = "NaN";
          length = 3;
          break;
        }
        if( realvalue>0.0 ){
          while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
          while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
          while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
          while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; }
          while( realvalue<1.0 ){ realvalue *= 10.0; exp--; }
          if( exp>350 ){
            if( prefix=='-' ){
              bufpt = "-Inf";
            }else if( prefix=='+' ){
              bufpt = "+Inf";
            }else{
              bufpt = "Inf";
            }
            length = sqlite4Strlen30(bufpt);
            break;
          }
        }
        bufpt = buf;
        /*
        ** If the field type is etGENERIC, then convert to either etEXP
        ** or etFLOAT, as appropriate.
        */
        if( xtype!=etFLOAT ){
          realvalue += rounder;
          if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
        }
        if( xtype==etGENERIC ){
          flag_rtz = !flag_alternateform;
          if( exp<-4 || exp>precision ){
            xtype = etEXP;
          }else{
            precision = precision - exp;
            xtype = etFLOAT;
          }
        }else{
          flag_rtz = 0;
        }
        if( xtype==etEXP ){
          e2 = 0;
        }else{
          e2 = exp;
        }
        if( e2+precision+width > etBUFSIZE - 15 ){
          bufpt = zExtra = sqlite4Malloc(pAccum->pEnv, e2+precision+width+15 );
          if( bufpt==0 ){
            pAccum->mallocFailed = 1;
            return;
          }
        }
        zOut = bufpt;
        nsd = 0;
        flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
        /* The sign in front of the number */
        if( prefix ){
          *(bufpt++) = prefix;
        }
        /* Digits prior to the decimal point */
        if( e2<0 ){
          *(bufpt++) = '0';
        }else{
          for(; e2>=0; e2--){
            *(bufpt++) = et_getdigit(&realvalue,&nsd);
          }
        }
        /* The decimal point */
        if( flag_dp ){
          *(bufpt++) = '.';
        }
        /* "0" digits after the decimal point but before the first
        ** significant digit of the number */
        for(e2++; e2<0; precision--, e2++){
          assert( precision>0 );
          *(bufpt++) = '0';
        }
        /* Significant digits after the decimal point */
        while( (precision--)>0 ){
          *(bufpt++) = et_getdigit(&realvalue,&nsd);
        }
        /* Remove trailing zeros and the "." if no digits follow the "." */
        if( flag_rtz && flag_dp ){
          while( bufpt[-1]=='0' ) *(--bufpt) = 0;
          assert( bufpt>zOut );
          if( bufpt[-1]=='.' ){
            if( flag_altform2 ){
              *(bufpt++) = '0';
            }else{
              *(--bufpt) = 0;
            }
          }
        }
        /* Add the "eNNN" suffix */
        if( xtype==etEXP ){
          *(bufpt++) = aDigits[infop->charset];
          if( exp<0 ){
            *(bufpt++) = '-'; exp = -exp;
          }else{
            *(bufpt++) = '+';
          }
          if( exp>=100 ){
            *(bufpt++) = (char)((exp/100)+'0');        /* 100's digit */
            exp %= 100;
          }
          *(bufpt++) = (char)(exp/10+'0');             /* 10's digit */
          *(bufpt++) = (char)(exp%10+'0');             /* 1's digit */
        }
        *bufpt = 0;

        /* The converted number is in buf[] and zero terminated. Output it.
        ** Note that the number is in the usual order, not reversed as with
        ** integer conversions. */
        length = (int)(bufpt-zOut);
        bufpt = zOut;

        /* Special case:  Add leading zeros if the flag_zeropad flag is
        ** set and we are not left justified */
        if( flag_zeropad && !flag_leftjustify && length < width){
          int i;
          int nPad = width - length;
          for(i=width; i>=nPad; i--){
            bufpt[i] = bufpt[i-nPad];
          }
          i = prefix!=0;
          while( nPad-- ) bufpt[i++] = '0';
          length = width;
        }
#endif /* !defined(SQLITE4_OMIT_FLOATING_POINT) */
        break;
      case etSIZE:
        *(va_arg(ap,int*)) = pAccum->nChar;
        length = width = 0;
        break;
      case etPERCENT:
        buf[0] = '%';
        bufpt = buf;
        length = 1;
        break;
      case etCHARX:
        c = va_arg(ap,int);
        buf[0] = (char)c;
        if( precision>=0 ){
          for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
          length = precision;
        }else{
          length =1;
        }
        bufpt = buf;
        break;
      case etSTRING:
      case etDYNSTRING:
        bufpt = va_arg(ap,char*);
        if( bufpt==0 ){
          bufpt = "";
        }else if( xtype==etDYNSTRING ){
          zExtra = bufpt;
        }
        if( precision>=0 ){
          for(length=0; length<precision && bufpt[length]; length++){}
        }else{
          length = sqlite4Strlen30(bufpt);
        }
        break;
      case etSQLESCAPE:
      case etSQLESCAPE2:
      case etSQLESCAPE3: {
        int i, j, k, n, isnull;
        int needQuote;
        char ch;
        char q = ((xtype==etSQLESCAPE3)?'"':'\'');   /* Quote character */
        char *escarg = va_arg(ap,char*);
        isnull = escarg==0;
        if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
        k = precision;
        for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
          if( ch==q )  n++;
        }
        needQuote = !isnull && xtype==etSQLESCAPE2;
        n += i + 1 + needQuote*2;
        if( n>etBUFSIZE ){
          bufpt = zExtra = sqlite4Malloc(pAccum->pEnv, n);
          if( bufpt==0 ){
            pAccum->mallocFailed = 1;
            return;
          }
        }else{
          bufpt = buf;
        }
        j = 0;
        if( needQuote ) bufpt[j++] = q;
        k = i;
        for(i=0; i<k; i++){
          bufpt[j++] = ch = escarg[i];
          if( ch==q ) bufpt[j++] = ch;
        }
        if( needQuote ) bufpt[j++] = q;
        bufpt[j] = 0;
        length = j;
        /* The precision in %q and %Q means how many input characters to
        ** consume, not the length of the output...
        ** if( precision>=0 && precision<length ) length = precision; */
        break;
      }
      case etTOKEN: {
        Token *pToken = va_arg(ap, Token*);
        if( pToken ){
          sqlite4StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
        }
        length = width = 0;
        break;
      }
      case etSRCLIST: {
        SrcList *pSrc = va_arg(ap, SrcList*);
        int k = va_arg(ap, int);
        SrcListItem *pItem = &pSrc->a[k];
        assert( k>=0 && k<pSrc->nSrc );
        if( pItem->zDatabase ){
          sqlite4StrAccumAppend(pAccum, pItem->zDatabase, -1);
          sqlite4StrAccumAppend(pAccum, ".", 1);
        }
        sqlite4StrAccumAppend(pAccum, pItem->zName, -1);
        length = width = 0;
        break;
      }
      default: {
        assert( xtype==etINVALID );
        return;
      }
    }/* End switch over the format type */
    /*
    ** The text of the conversion is pointed to by "bufpt" and is
    ** "length" characters long.  The field width is "width".  Do
    ** the output.
    */
    if( !flag_leftjustify ){
      register int nspace;
      nspace = width-length;
      if( nspace>0 ){
        sqlite4AppendSpace(pAccum, nspace);
      }
    }
    if( length>0 ){
      sqlite4StrAccumAppend(pAccum, bufpt, length);
    }
    if( flag_leftjustify ){
      register int nspace;
      nspace = width-length;
      if( nspace>0 ){
        sqlite4AppendSpace(pAccum, nspace);
      }
    }
    sqlite4_free(pAccum->pEnv, zExtra);
  }/* End for loop over the format string */
} /* End of function */

/*
** Append N bytes of text from z to the StrAccum object.
*/
SQLITE4_PRIVATE void sqlite4StrAccumAppend(StrAccum *p, const char *z, int N){
  assert( z!=0 || N==0 );
  if( p->tooBig | p->mallocFailed ){
    testcase(p->tooBig);
    testcase(p->mallocFailed);
    return;
  }
  assert( p->zText!=0 || p->nChar==0 );
  if( N<0 ){
    N = sqlite4Strlen30(z);
  }
  if( N==0 || NEVER(z==0) ){
    return;
  }
  if( p->nChar+N >= p->nAlloc ){
    char *zNew;
    if( !p->useMalloc ){
      p->tooBig = 1;
      N = p->nAlloc - p->nChar - 1;
      if( N<=0 ){
        return;
      }
    }else{
      char *zOld = (p->zText==p->zBase ? 0 : p->zText);
      i64 szNew = p->nChar;
      szNew += N + 1;
      if( szNew > p->mxAlloc ){
        sqlite4StrAccumReset(p);
        p->tooBig = 1;
        return;
      }else{
        p->nAlloc = (int)szNew;
      }
      if( p->useMalloc==1 ){
        zNew = sqlite4DbRealloc(p->db, zOld, p->nAlloc);
      }else{
        zNew = sqlite4_realloc(p->pEnv, zOld, p->nAlloc);
      }
      if( zNew ){
        if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
        p->zText = zNew;
      }else{
        p->mallocFailed = 1;
        sqlite4StrAccumReset(p);
        return;
      }
    }
  }
  assert( p->zText );
  memcpy(&p->zText[p->nChar], z, N);
  p->nChar += N;
}

/*
** Finish off a string by making sure it is zero-terminated.
** Return a pointer to the resulting string.  Return a NULL
** pointer if any kind of error was encountered.
*/
SQLITE4_PRIVATE char *sqlite4StrAccumFinish(StrAccum *p){
  if( p->zText ){
    p->zText[p->nChar] = 0;
    if( p->useMalloc && p->zText==p->zBase ){
      if( p->useMalloc==1 ){
        p->zText = sqlite4DbMallocRaw(p->db, p->nChar+1 );
      }else{
        p->zText = sqlite4_malloc(p->pEnv, p->nChar+1);
      }
      if( p->zText ){
        memcpy(p->zText, p->zBase, p->nChar+1);
      }else{
        p->mallocFailed = 1;
      }
    }
  }
  return p->zText;
}

/*
** Reset an StrAccum string.  Reclaim all malloced memory.
*/
SQLITE4_PRIVATE void sqlite4StrAccumReset(StrAccum *p){
  if( p->zText!=p->zBase ){
    if( p->useMalloc==1 ){
      sqlite4DbFree(p->db, p->zText);
    }else{
      sqlite4_free(p->pEnv, p->zText);
    }
  }
  p->zText = 0;
}

/*
** Initialize a string accumulator
*/
SQLITE4_PRIVATE void sqlite4StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
  p->zText = p->zBase = zBase;
  p->db = 0;
  p->pEnv = 0;
  p->nChar = 0;
  p->nAlloc = n;
  p->mxAlloc = mx;
  p->useMalloc = 1;
  p->tooBig = 0;
  p->mallocFailed = 0;
}

/*
** Print into memory obtained from sqliteMalloc().  Use the internal
** %-conversion extensions.
*/
SQLITE4_PRIVATE char *sqlite4VMPrintf(sqlite4 *db, const char *zFormat, va_list ap){
  char *z;
  char zBase[SQLITE4_PRINT_BUF_SIZE];
  StrAccum acc;
  assert( db!=0 );
  sqlite4StrAccumInit(&acc, zBase, sizeof(zBase),
                      db->aLimit[SQLITE4_LIMIT_LENGTH]);
  acc.db = db;
  sqlite4VXPrintf(&acc, 1, zFormat, ap);
  z = sqlite4StrAccumFinish(&acc);
  if( acc.mallocFailed ){
    db->mallocFailed = 1;
  }
  return z;
}

/*
** Print into memory obtained from sqliteMalloc().  Use the internal
** %-conversion extensions.
*/
SQLITE4_PRIVATE char *sqlite4MPrintf(sqlite4 *db, const char *zFormat, ...){
  va_list ap;
  char *z;
  va_start(ap, zFormat);
  z = sqlite4VMPrintf(db, zFormat, ap);
  va_end(ap);
  return z;
}

/*
** Like sqlite4MPrintf(), but call sqlite4DbFree() on zStr after formatting
** the string and before returnning.  This routine is intended to be used
** to modify an existing string.  For example:
**
**       x = sqlite4MPrintf(db, x, "prefix %s suffix", x);
**
*/
SQLITE4_PRIVATE char *sqlite4MAppendf(sqlite4 *db, char *zStr, const char *zFormat, ...){
  va_list ap;
  char *z;
  va_start(ap, zFormat);
  z = sqlite4VMPrintf(db, zFormat, ap);
  va_end(ap);
  sqlite4DbFree(db, zStr);
  return z;
}

/*
** Print into memory obtained from sqlite4_malloc().  Omit the internal
** %-conversion extensions.
*/
SQLITE4_API char *sqlite4_vmprintf(sqlite4_env *pEnv, const char *zFormat, va_list ap){
  char *z;
  char zBase[SQLITE4_PRINT_BUF_SIZE];
  StrAccum acc;
#ifndef SQLITE4_OMIT_AUTOINIT
  if( sqlite4_initialize(pEnv) ) return 0;
#endif
  sqlite4StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE4_MAX_LENGTH);
  acc.useMalloc = 2;
  acc.pEnv = pEnv;
  sqlite4VXPrintf(&acc, 0, zFormat, ap);
  z = sqlite4StrAccumFinish(&acc);
  return z;
}

/*
** Print into memory obtained from sqlite4_malloc()().  Omit the internal
** %-conversion extensions.
*/
SQLITE4_API char *sqlite4_mprintf(sqlite4_env *pEnv, const char *zFormat, ...){
  va_list ap;
  char *z;
#ifndef SQLITE4_OMIT_AUTOINIT
  if( sqlite4_initialize(pEnv) ) return 0;
#endif
  va_start(ap, zFormat);
  z = sqlite4_vmprintf(pEnv, zFormat, ap);
  va_end(ap);
  return z;
}

/*
** sqlite4_snprintf() works like snprintf() except that it ignores the
** current locale settings.  This is important for SQLite because we
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
**
** Oops:  The first two arguments of sqlite4_snprintf() are backwards
** from the snprintf() standard.  Unfortunately, it is too late to change
** this without breaking compatibility, so we just have to live with the
** mistake.
**
** sqlite4_vsnprintf() is the varargs version.
*/
SQLITE4_API sqlite4_size_t sqlite4_vsnprintf(
  char *zBuf,              /* Write results here */
  sqlite4_size_t n,        /* Bytes available in zBuf[] */
  const char *zFormat,     /* Format string */
  va_list ap               /* Arguments */
){
  StrAccum acc;
  if( n<=0 ) return 0;
  sqlite4StrAccumInit(&acc, zBuf, n, 0);
  acc.useMalloc = 0;
  sqlite4VXPrintf(&acc, 0, zFormat, ap);
  sqlite4StrAccumFinish(&acc);
  return acc.nChar;
}
SQLITE4_API sqlite4_size_t sqlite4_snprintf(
  char *zBuf,              /* Write results here */
  sqlite4_size_t n,        /* Bytes available in zBuf[] */
  const char *zFormat,     /* Format string */
  ...                      /* Arguments */
){
  va_list ap;
  va_start(ap,zFormat);
  n = sqlite4_vsnprintf(zBuf, n, zFormat, ap);
  va_end(ap);
  return n;
}

/*
** This is the routine that actually formats the sqlite4_log() message.
** We house it in a separate routine from sqlite4_log() to avoid using
** stack space on small-stack systems when logging is disabled.
**
** sqlite4_log() must render into a static buffer.  It cannot dynamically
** allocate memory because it might be called while the memory allocator
** mutex is held.
*/
static void renderLogMsg(
  sqlite4_env *pEnv,                     /* Run-time environment */
  int iErrCode,                          /* Error code */
  const char *zFormat,                   /* Error format string */
  va_list ap                             /* Arguments */
){
  StrAccum acc;                          /* String accumulator */
  char zMsg[SQLITE4_PRINT_BUF_SIZE*3];    /* Complete log message */

  sqlite4StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
  acc.useMalloc = 0;
  sqlite4VXPrintf(&acc, 0, zFormat, ap);
  pEnv->xLog(pEnv->pLogArg, iErrCode, sqlite4StrAccumFinish(&acc));
}

/*
** Format and write a message to the log if logging is enabled.
*/
SQLITE4_API void sqlite4_log(sqlite4_env *pEnv, int iErrCode, const char *zFormat, ...){
  va_list ap;                             /* Vararg list */
  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
  if( pEnv->xLog ){
    va_start(ap, zFormat);
    renderLogMsg(pEnv, iErrCode, zFormat, ap);
    va_end(ap);
  }
}

#if defined(SQLITE4_DEBUG)
/*
** A version of printf() that understands %lld.  Used for debugging.
** The printf() built into some versions of windows does not understand %lld
** and segfaults if you give it a long long int.
*/
SQLITE4_PRIVATE void sqlite4DebugPrintf(const char *zFormat, ...){
  va_list ap;
  StrAccum acc;
  char zBuf[500];
  sqlite4StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
  acc.useMalloc = 0;
  va_start(ap,zFormat);
  sqlite4VXPrintf(&acc, 0, zFormat, ap);
  va_end(ap);
  sqlite4StrAccumFinish(&acc);
  fprintf(stdout,"%s", zBuf);
  fflush(stdout);
}
#endif

#ifndef SQLITE4_OMIT_TRACE
/*
** variable-argument wrapper around sqlite4VXPrintf().
*/
SQLITE4_PRIVATE void sqlite4XPrintf(StrAccum *p, const char *zFormat, ...){
  va_list ap;
  va_start(ap,zFormat);
  sqlite4VXPrintf(p, 1, zFormat, ap);
  va_end(ap);
}
#endif

/*
** Convert an N-byte blob into hex.  The caller is responsible for making
** sure zOut contains at least N*2+1 bytes of usable space.
*/
SQLITE4_PRIVATE void sqlite4BlobToHex(int N, const u8 *zIn, char *zOut){
  while( (N--)>0 ){
    u8 c = *(zIn++);
    *(zOut++) = aDigits[c>>4];
    *(zOut++) = aDigits[c&0x0f];
  }
  *zOut = 0;
}

/************** End of printf.c **********************************************/
/************** Begin file random.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement a pseudo-random number
** generator (PRNG) for SQLite.
**
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
*/


/*
** Get a single 8-bit random value from the PRNG.  The Mutex
** must be held while executing this routine.
*/
static u8 randomByte(sqlite4_env *pEnv){
  pEnv->prngX = (pEnv->prngX>>1) ^ ((-(pEnv->prngX&1)) & 0xd0000001);
  pEnv->prngY = pEnv->prngY*1103515245 + 12345;
  return (u8)((pEnv->prngX ^ pEnv->prngY)&0xff);
}

/*
** Return N random bytes.
*/
SQLITE4_API void sqlite4_randomness(sqlite4_env *pEnv, int N, void *pBuf){
  unsigned char *zBuf = pBuf;
  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
  sqlite4_mutex_enter(pEnv->pPrngMutex);
  while( N-- ){
    *(zBuf++) = randomByte(pEnv);
  }
  sqlite4_mutex_leave(pEnv->pPrngMutex);
}

/************** End of random.c **********************************************/
/************** Begin file utf.c *********************************************/
/*
** 2004 April 13
**
** 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 routines used to translate between UTF-8, 
** UTF-16, UTF-16BE, and UTF-16LE.
**
** Notes on UTF-8:
**
**   Byte-0    Byte-1    Byte-2    Byte-3    Value
**  0xxxxxxx                                 00000000 00000000 0xxxxxxx
**  110yyyyy  10xxxxxx                       00000000 00000yyy yyxxxxxx
**  1110zzzz  10yyyyyy  10xxxxxx             00000000 zzzzyyyy yyxxxxxx
**  11110uuu  10uuzzzz  10yyyyyy  10xxxxxx   000uuuuu zzzzyyyy yyxxxxxx
**
**
** Notes on UTF-16:  (with wwww+1==uuuuu)
**
**      Word-0               Word-1          Value
**  110110ww wwzzzzyy   110111yy yyxxxxxx    000uuuuu zzzzyyyy yyxxxxxx
**  zzzzyyyy yyxxxxxx                        00000000 zzzzyyyy yyxxxxxx
**
**
** BOM or Byte Order Mark:
**     0xff 0xfe   little-endian utf-16 follows
**     0xfe 0xff   big-endian utf-16 follows
**
*/
/* #include <assert.h> */

#ifndef SQLITE4_AMALGAMATION
/*
** The following constant value is used by the SQLITE4_BIGENDIAN and
** SQLITE4_LITTLEENDIAN macros.
*/
SQLITE4_PRIVATE const int sqlite4one = 1;
#endif /* SQLITE4_AMALGAMATION */

/*
** This lookup table is used to help decode the first byte of
** a multi-byte UTF8 character.
*/
static const unsigned char sqlite4Utf8Trans1[] = {
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
};


#define WRITE_UTF8(zOut, c) {                          \
  if( c<0x00080 ){                                     \
    *zOut++ = (u8)(c&0xFF);                            \
  }                                                    \
  else if( c<0x00800 ){                                \
    *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);                \
    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
  }                                                    \
  else if( c<0x10000 ){                                \
    *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);               \
    *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);              \
    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
  }else{                                               \
    *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);             \
    *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);             \
    *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);              \
    *zOut++ = 0x80 + (u8)(c & 0x3F);                   \
  }                                                    \
}

#define WRITE_UTF16LE(zOut, c) {                                    \
  if( c<=0xFFFF ){                                                  \
    *zOut++ = (u8)(c&0x00FF);                                       \
    *zOut++ = (u8)((c>>8)&0x00FF);                                  \
  }else{                                                            \
    *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \
    *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));              \
    *zOut++ = (u8)(c&0x00FF);                                       \
    *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));                         \
  }                                                                 \
}

#define WRITE_UTF16BE(zOut, c) {                                    \
  if( c<=0xFFFF ){                                                  \
    *zOut++ = (u8)((c>>8)&0x00FF);                                  \
    *zOut++ = (u8)(c&0x00FF);                                       \
  }else{                                                            \
    *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));              \
    *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));  \
    *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));                         \
    *zOut++ = (u8)(c&0x00FF);                                       \
  }                                                                 \
}

#define READ_UTF16LE(zIn, TERM, c){                                   \
  c = (*zIn++);                                                       \
  c += ((*zIn++)<<8);                                                 \
  if( c>=0xD800 && c<0xE000 && TERM ){                                \
    int c2 = (*zIn++);                                                \
    c2 += ((*zIn++)<<8);                                              \
    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
  }                                                                   \
}

#define READ_UTF16BE(zIn, TERM, c){                                   \
  c = ((*zIn++)<<8);                                                  \
  c += (*zIn++);                                                      \
  if( c>=0xD800 && c<0xE000 && TERM ){                                \
    int c2 = ((*zIn++)<<8);                                           \
    c2 += (*zIn++);                                                   \
    c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);   \
  }                                                                   \
}

/*
** Translate a single UTF-8 character.  Return the unicode value.
**
** During translation, assume that the byte that zTerm points
** is a 0x00.
**
** Write a pointer to the next unread byte back into *pzNext.
**
** Notes On Invalid UTF-8:
**
**  *  This routine never allows a 7-bit character (0x00 through 0x7f) to
**     be encoded as a multi-byte character.  Any multi-byte character that
**     attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
**
**  *  This routine never allows a UTF16 surrogate value to be encoded.
**     If a multi-byte character attempts to encode a value between
**     0xd800 and 0xe000 then it is rendered as 0xfffd.
**
**  *  Bytes in the range of 0x80 through 0xbf which occur as the first
**     byte of a character are interpreted as single-byte characters
**     and rendered as themselves even though they are technically
**     invalid characters.
**
**  *  This routine accepts an infinite number of different UTF8 encodings
**     for unicode values 0x80 and greater.  It do not change over-length
**     encodings to 0xfffd as some systems recommend.
*/
#define READ_UTF8(zIn, zTerm, c)                           \
  c = *(zIn++);                                            \
  if( c>=0xc0 ){                                           \
    c = sqlite4Utf8Trans1[c-0xc0];                         \
    while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){            \
      c = (c<<6) + (0x3f & *(zIn++));                      \
    }                                                      \
    if( c<0x80                                             \
        || (c&0xFFFFF800)==0xD800                          \
        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }        \
  }
SQLITE4_PRIVATE u32 sqlite4Utf8Read(
  const char *zIn,                /* First byte of UTF-8 character */
  const char **pzNext             /* Write first byte past UTF-8 char here */
){
  unsigned int c;

  /* Same as READ_UTF8() above but without the zTerm parameter.
  ** For this routine, we assume the UTF8 string is always zero-terminated.
  */
  c = *(unsigned char *)(zIn++);
  if( c>=0xc0 ){
    c = sqlite4Utf8Trans1[c-0xc0];
    while( (*zIn & 0xc0)==0x80 ){
      c = (c<<6) + (0x3f & *(zIn++));
    }
    if( c<0x80
        || (c&0xFFFFF800)==0xD800
        || (c&0xFFFFFFFE)==0xFFFE ){  c = 0xFFFD; }
  }
  *pzNext = zIn;
  return c;
}


/*
** Versions of stricmp and strnicmp that work with (simple) unicode
** case mapping.
*/
SQLITE4_API int sqlite4_stricmp(const char *zLeft, const char *zRight){
  unsigned char *a, *b;
  unsigned int ac, bc;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  do{
    READ_UTF8(a, 0, ac);
    ac = sqlite4_tolower(ac);
    READ_UTF8(b, 0, bc);
    bc = sqlite4_tolower(bc);
  }while( ac==bc && ac!=0 );
  return ac - bc;
}
SQLITE4_API int sqlite4_strnicmp(const char *zLeft, const char *zRight, int N){
  unsigned char *a, *b, *aTerm, *bTerm;
  unsigned int ac, bc;
  a = (unsigned char *)zLeft;
  b = (unsigned char *)zRight;
  aTerm = a + N;
  bTerm = b + N;
  do{
    READ_UTF8(a, aTerm, ac);
    ac = sqlite4_tolower(ac);
    READ_UTF8(b, bTerm, bc);
    bc = sqlite4_tolower(bc);
  }while( ac==bc && ac!=0 && a<aTerm );
  return ac - bc;
}

/*
** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
** printed on stderr on the way into and out of sqlite4VdbeMemTranslate().
*/ 
/* #define TRANSLATE_TRACE 1 */


#ifndef SQLITE4_OMIT_UTF16


/*
** This routine transforms the internal text encoding used by pMem to
** desiredEnc. It is an error if the string is already of the desired
** encoding, or if *pMem does not contain a string value.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
  unsigned char *zIn;                   /* Input iterator */
  unsigned char *zTerm;                 /* End of input */

  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  assert( pMem->flags&MEM_Str );
  assert( pMem->enc!=desiredEnc );
  assert( pMem->enc!=0 );
  assert( pMem->n>=0 );

#if defined(TRANSLATE_TRACE) && defined(SQLITE4_DEBUG)
  {
    char zBuf[100];
    sqlite4VdbeMemPrettyPrint(pMem, zBuf);
    fprintf(stderr, "INPUT:  %s\n", zBuf);
  }
#endif

  if( pMem->enc!=SQLITE4_UTF8 && desiredEnc!=SQLITE4_UTF8 ){
    /* If the translation is between UTF-16 little and big endian, then 
    ** all that is required is to swap the byte order.  */
    u8 temp;
    int rc;
    rc = sqlite4VdbeMemMakeWriteable(pMem);
    if( rc!=SQLITE4_OK ){
      assert( rc==SQLITE4_NOMEM );
      return SQLITE4_NOMEM;
    }
    zIn = (u8*)pMem->z;
    zTerm = &zIn[pMem->n&~1];
    while( zIn<zTerm ){
      temp = *zIn;
      *zIn = *(zIn+1);
      zIn++;
      *zIn++ = temp;
    }
    pMem->enc = desiredEnc;
  }else{
    int eTrans;
    sqlite4_buffer buf;
    sqlite4_mm *pMM = sqlite4_db_env(pMem->db)->pMM;

    switch( pMem->enc ){
      case SQLITE4_UTF8:
        if( desiredEnc==SQLITE4_UTF16BE ){
          eTrans = SQLITE4_TRANSLATE_UTF8_UTF16BE;
        }else{
          eTrans = SQLITE4_TRANSLATE_UTF8_UTF16LE;
        }
        break;
      case SQLITE4_UTF16BE:
        eTrans = SQLITE4_TRANSLATE_UTF16BE_UTF8;
        break;
      default:
        assert( pMem->enc==SQLITE4_UTF16LE );
        eTrans = SQLITE4_TRANSLATE_UTF16LE_UTF8;
        break;
    }

    sqlite4_buffer_init(&buf, pMM);
    if( 0==sqlite4_translate(&buf, pMem->z, pMem->n, eTrans) ){
      return SQLITE4_NOMEM;
    }

    sqlite4VdbeMemRelease(pMem);
    pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem);
    pMem->enc = desiredEnc;
    pMem->flags |= (MEM_Term|MEM_Dyn);
    pMem->z = (char*)buf.p;
    pMem->n = (int)buf.n;
    pMem->zMalloc = pMem->z;
  }

#if defined(TRANSLATE_TRACE) && defined(SQLITE4_DEBUG)
  {
    char zBuf[100];
    sqlite4VdbeMemPrettyPrint(pMem, zBuf);
    fprintf(stderr, "OUTPUT: %s\n", zBuf);
  }
#endif
  return SQLITE4_OK;
}

/*
** This routine checks for a byte-order mark at the beginning of the 
** UTF-16 string stored in *pMem. If one is present, it is removed and
** the encoding of the Mem adjusted. This routine does not do any
** byte-swapping, it just sets Mem.enc appropriately.
**
** The allocation (static, dynamic etc.) and encoding of the Mem may be
** changed by this function.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemHandleBom(Mem *pMem){
  int rc = SQLITE4_OK;
  u8 bom = 0;

  assert( pMem->n>=0 );
  if( pMem->n>1 ){
    u8 b1 = *(u8*)pMem->z;
    u8 b2 = *(((u8*)pMem->z) + 1);
    if( b1==0xFE && b2==0xFF ){
      bom = SQLITE4_UTF16BE;
    }
    if( b1==0xFF && b2==0xFE ){
      bom = SQLITE4_UTF16LE;
    }
  }
  
  if( bom ){
    rc = sqlite4VdbeMemMakeWriteable(pMem);
    if( rc==SQLITE4_OK ){
      pMem->n -= 2;
      memmove(pMem->z, &pMem->z[2], pMem->n);
      pMem->z[pMem->n] = '\0';
      pMem->z[pMem->n+1] = '\0';
      pMem->flags |= MEM_Term;
      pMem->enc = bom;
    }
  }
  return rc;
}
#endif /* SQLITE4_OMIT_UTF16 */

/*
** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
** return the number of unicode characters in pZ up to (but not including)
** the first 0x00 byte. If nByte is not less than zero, return the
** number of unicode characters in the first nByte of pZ (or up to 
** the first 0x00, whichever comes first).
*/
SQLITE4_PRIVATE int sqlite4Utf8CharLen(const char *zIn, int nByte){
  int r = 0;
  const u8 *z = (const u8*)zIn;
  const u8 *zTerm;
  if( nByte>=0 ){
    zTerm = &z[nByte];
  }else{
    zTerm = (const u8*)(-1);
  }
  assert( z<=zTerm );
  while( *z!=0 && z<zTerm ){
    SQLITE4_SKIP_UTF8(z);
    r++;
  }
  return r;
}

/* This test function is not currently used by the automated test-suite. 
** Hence it is only available in debug builds.
*/
#if defined(SQLITE4_TEST) && defined(SQLITE4_DEBUG)
/*
** Translate UTF-8 to UTF-8.
**
** This has the effect of making sure that the string is well-formed
** UTF-8.  Miscoded characters are removed.
**
** The translation is done in-place and aborted if the output
** overruns the input.
*/
SQLITE4_PRIVATE int sqlite4Utf8To8(char *zIn){
  char *zOut = zIn;
  char *zStart = zIn;
  u32 c;

  while( zIn[0] && zOut<=zIn ){
    c = sqlite4Utf8Read(zIn, (const char **)&zIn);
    if( c!=0xfffd ){
      WRITE_UTF8(zOut, c);
    }
  }
  *zOut = 0;
  return (int)(zOut - zStart);
}
#endif

#ifndef SQLITE4_OMIT_UTF16
/*
** Convert a UTF-16 string in the native encoding into a UTF-8 string.
** Memory to hold the UTF-8 string is obtained from sqlite4_malloc and must
** be freed by the calling function.
**
** NULL is returned if there is an allocation error.
*/
SQLITE4_PRIVATE char *sqlite4Utf16to8(sqlite4 *db, const void *z, int nByte, u8 enc){
  Mem m;
  memset(&m, 0, sizeof(m));
  m.db = db;
  sqlite4VdbeMemSetStr(&m, z, nByte, enc, SQLITE4_STATIC, 0);
  sqlite4VdbeChangeEncoding(&m, SQLITE4_UTF8);
  if( db->mallocFailed ){
    sqlite4VdbeMemRelease(&m);
    m.z = 0;
  }
  assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
  assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
  assert( (m.flags & MEM_Dyn)!=0 || db->mallocFailed );
  assert( m.z || db->mallocFailed );
  return m.z;
}

/*
** Convert a UTF-8 string to the UTF-16 encoding specified by parameter
** enc. A pointer to the new string is returned, and the value of *pnOut
** is set to the length of the returned string in bytes. The call should
** arrange to call sqlite4DbFree() on the returned pointer when it is
** no longer required.
** 
** If a malloc failure occurs, NULL is returned and the db.mallocFailed
** flag set.
*/
#ifdef SQLITE4_ENABLE_STAT3
SQLITE4_PRIVATE char *sqlite4Utf8to16(sqlite4 *db, u8 enc, char *z, int n, int *pnOut){
  Mem m;
  memset(&m, 0, sizeof(m));
  m.db = db;
  sqlite4VdbeMemSetStr(&m, z, n, SQLITE4_UTF8, SQLITE4_STATIC, 0);
  if( sqlite4VdbeMemTranslate(&m, enc) ){
    assert( db->mallocFailed );
    return 0;
  }
  assert( m.z==m.zMalloc );
  *pnOut = m.n;
  return m.z;
}
#endif

/*
** zIn is a UTF-16 encoded unicode string at least nChar characters long.
** Return the number of bytes in the first nChar unicode characters
** in pZ.  nChar must be non-negative.
*/
SQLITE4_PRIVATE int sqlite4Utf16ByteLen(const void *zIn, int nChar){
  int c;
  unsigned char const *z = zIn;
  int n = 0;
  
  if( SQLITE4_UTF16NATIVE==SQLITE4_UTF16BE ){
    while( n<nChar ){
      READ_UTF16BE(z, 1, c);
      n++;
    }
  }else{
    while( n<nChar ){
      READ_UTF16LE(z, 1, c);
      n++;
    }
  }
  return (int)(z-(unsigned char const *)zIn);
}

/*
** Helper function for sqlite4_translate().
*/
static void translateEncoding(
  int eTrans,                     /* SQLITE4_TRANSLATE_XXX constant */
  const void *pIn, int nIn,       /* Input buffer */
  void *pOut,                     /* Pointer to output buffer */
  sqlite4_size_t *pnOut           /* OUT: Bytes written to output buffer */
){
  u8 *zIn = (u8*)pIn;            /* Input pointer */
  u8 *zTerm = &zIn[nIn];          /* One byte past the end of the input */
  u8 *z = (u8*)pOut;             /* Output pointer */
  int e16;                        /* utf-16 variant */
  unsigned int c;

  if( eTrans==SQLITE4_TRANSLATE_UTF8_UTF16 
   || eTrans==SQLITE4_TRANSLATE_UTF16_UTF8 
  ){
    e16 = SQLITE4_UTF16NATIVE;
  }else if( eTrans==SQLITE4_TRANSLATE_UTF8_UTF16BE 
         || eTrans==SQLITE4_TRANSLATE_UTF16BE_UTF8
  ){
    e16 = SQLITE4_UTF16BE;
  }else{
    e16 = SQLITE4_UTF16LE;
  }

  assert( (SQLITE4_TRANSLATE_UTF8_UTF16 & 0x01)
       && (SQLITE4_TRANSLATE_UTF8_UTF16LE & 0x01)
       && (SQLITE4_TRANSLATE_UTF8_UTF16BE & 0x01)
  );
  if( eTrans & 0x01 ){
    if( e16==SQLITE4_UTF16LE ){
      /* UTF-8 -> UTF-16 Little-endian */
      while( zIn<zTerm ){
        /* c = sqlite4Utf8Read(zIn, zTerm, (const u8**)&zIn); */
        READ_UTF8(zIn, zTerm, c);
        WRITE_UTF16LE(z, c);
      }
    }else{
      assert( e16==SQLITE4_UTF16BE );
      /* UTF-8 -> UTF-16 Big-endian */
      while( zIn<zTerm ){
        /* c = sqlite4Utf8Read(zIn, zTerm, (const u8**)&zIn); */
        READ_UTF8(zIn, zTerm, c);
        WRITE_UTF16BE(z, c);
      }
    }
  }else{
    if( e16==SQLITE4_UTF16LE ){
      /* UTF-16 Little-endian -> UTF-8 */
      while( zIn<zTerm ){
        READ_UTF16LE(zIn, zIn<zTerm, c); 
        WRITE_UTF8(z, c);
      }
    }else{
      /* UTF-16 Big-endian -> UTF-8 */
      while( zIn<zTerm ){
        READ_UTF16BE(zIn, zIn<zTerm, c); 
        WRITE_UTF8(z, c);
      }
    }
  }
  
  *pnOut =  (sqlite4_size_t)(z - (u8*)pOut);
  if( eTrans & 0x01 ) *z++ = 0;
  *z = 0;
}

/*
** Translate the input buffer described by the second and third arguments
** according to the value of parameter eTrans (one of the SQLITE4_TRANSLATE_*
** constants). Write the results into buffer pBuf.
*/
SQLITE4_API void *sqlite4_translate(
  sqlite4_buffer *pBuf,           /* Buffer to store output in */
  const void *p, int n,           /* Input buffer and its size in bytes */
  int eTrans                      /* Requested translation */
){
  int nReq;                       /* Size of required buffer in bytes */

  assert( (SQLITE4_TRANSLATE_UTF8_UTF16 & 0x01)
       && (SQLITE4_TRANSLATE_UTF8_UTF16LE & 0x01)
       && (SQLITE4_TRANSLATE_UTF8_UTF16BE & 0x01)
  );
  if( eTrans & 0x01 ){
    /* When converting from UTF-8 to UTF-16 the maximum growth is caused
    ** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
    ** character. Two bytes are required in the output buffer for the
    ** nul-terminator.  */
    if( n<0 ){
      u8 *z = (u8*)p;
      while( z[0] || z[1] ) z += 2;
      n = z - (u8*)p;
    }
    nReq = n * 2 + 2;
  }else{
    /* When converting from UTF-16, the maximum growth results from
    ** translating a 2-byte character to a 4-byte UTF-8 character.
    ** A single byte is required for the output string
    ** nul-terminator.  */
    if( n<0 ) n = sqlite4Strlen30(p);
    nReq = n * 2 + 1;
  }

  if( SQLITE4_OK!=sqlite4_buffer_resize(pBuf, nReq) ){
    sqlite4_buffer_clear(pBuf);
  }else{
    translateEncoding(eTrans, p, n, pBuf->p, &pBuf->n);
  }

  return pBuf->p;
}

#if defined(SQLITE4_TEST)
/*
** This routine is called from the TCL test function "translate_selftest".
** It checks that the primitives for serializing and deserializing
** characters in each encoding are inverses of each other.
*/
SQLITE4_PRIVATE void sqlite4UtfSelfTest(void){
  unsigned int i, t;
  u8 zBuf[20];
  u8 *z;
  int n;
  unsigned int c;

  for(i=0; i<0x00110000; i++){
    z = zBuf;
    WRITE_UTF8(z, i);
    n = (int)(z-zBuf);
    assert( n>0 && n<=4 );
    z[0] = 0;
    z = zBuf;
    c = sqlite4Utf8Read((char *)z, (const char **)&z);
    t = i;
    if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
    if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
    assert( c==t );
    assert( (z-zBuf)==n );
  }
  for(i=0; i<0x00110000; i++){
    if( i>=0xD800 && i<0xE000 ) continue;
    z = zBuf;
    WRITE_UTF16LE(z, i);
    n = (int)(z-zBuf);
    assert( n>0 && n<=4 );
    z[0] = 0;
    z = zBuf;
    READ_UTF16LE(z, 1, c);
    assert( c==i );
    assert( (z-zBuf)==n );
  }
  for(i=0; i<0x00110000; i++){
    if( i>=0xD800 && i<0xE000 ) continue;
    z = zBuf;
    WRITE_UTF16BE(z, i);
    n = (int)(z-zBuf);
    assert( n>0 && n<=4 );
    z[0] = 0;
    z = zBuf;
    READ_UTF16BE(z, 1, c);
    assert( c==i );
    assert( (z-zBuf)==n );
  }
}
#endif /* SQLITE4_TEST */
#endif /* SQLITE4_OMIT_UTF16 */


/*
** Return true if the argument corresponds to a unicode codepoint
** classified as either a letter or a number. Otherwise false.
**
** The results are undefined if the value passed to this function
** is less than zero.
*/
SQLITE4_API int sqlite4_isalnum(int c){
  /* Each unsigned integer in the following array corresponds to a contiguous
  ** range of unicode codepoints that are not either letters or numbers (i.e.
  ** codepoints for which this function should return 0).
  **
  ** The most significant 22 bits in each 32-bit value contain the first 
  ** codepoint in the range. The least significant 10 bits are used to store
  ** the size of the range (always at least 1). In other words, the value 
  ** ((C<<22) + N) represents a range of N codepoints starting with codepoint 
  ** C. It is not possible to represent a range larger than 1023 codepoints 
  ** using this format.
  */
  const static unsigned int aEntry[] = {
    0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07,
    0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01,
    0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401,
    0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01,
    0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01,
    0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802,
    0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F,
    0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401,
    0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804,
    0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403,
    0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812,
    0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001,
    0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802,
    0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805,
    0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401,
    0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03,
    0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807,
    0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001,
    0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01,
    0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804,
    0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001,
    0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802,
    0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01,
    0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06,
    0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007,
    0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006,
    0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417,
    0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14,
    0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07,
    0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01,
    0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001,
    0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802,
    0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F,
    0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002,
    0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802,
    0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006,
    0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D,
    0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802,
    0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027,
    0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403,
    0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805,
    0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04,
    0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401,
    0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005,
    0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B,
    0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A,
    0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001,
    0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59,
    0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807,
    0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01,
    0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E,
    0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100,
    0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10,
    0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402,
    0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804,
    0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012,
    0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004,
    0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002,
    0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803,
    0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07,
    0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02,
    0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810,
    0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023,
    0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807,
    0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405,
    0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E,
    0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01,
    0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01,
    0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016,
    0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004,
    0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004,
    0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5,
    0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01,
    0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401,
    0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064,
    0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F,
    0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009,
    0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014,
    0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001,
    0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018,
    0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401,
    0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001,
    0x43FFF401,
  };
  static const unsigned int aAscii[4] = {
    0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
  };

  if( c<128 ){
    return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
  }else if( c<(1<<22) ){
    unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
    int iRes;
    int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
    int iLo = 0;
    while( iHi>=iLo ){
      int iTest = (iHi + iLo) / 2;
      if( key >= aEntry[iTest] ){
        iRes = iTest;
        iLo = iTest+1;
      }else{
        iHi = iTest-1;
      }
    }
    assert( aEntry[0]<key );
    assert( key>=aEntry[iRes] );
    return (((unsigned int)c) >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF)));
  }
  return 1;
}

/*
** Interpret the argument as a unicode codepoint. If the codepoint
** is an upper case character that has a lower case equivalent,
** return the codepoint corresponding to the lower case version.
** Otherwise, return a copy of the argument.
**
** The results are undefined if the value passed to this function
** is less than zero.
*/
SQLITE4_API int sqlite4_tolower(int c){
  /* Each entry in the following array defines a rule for folding a range
  ** of codepoints to lower case. The rule applies to a range of nRange
  ** codepoints starting at codepoint iCode.
  **
  ** If the least significant bit in flags is clear, then the rule applies
  ** to all nRange codepoints (i.e. all nRange codepoints are upper case and
  ** need to be folded). Or, if it is set, then the rule only applies to
  ** every second codepoint in the range, starting with codepoint C.
  **
  ** The 7 most significant bits in flags are an index into the aiOff[]
  ** array. If a specific codepoint C does require folding, then its lower
  ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF).
  **
  ** The contents of this array are generated by parsing the CaseFolding.txt
  ** file distributed as part of the "Unicode Character Database". See
  ** http://www.unicode.org for details.
  */
  static const struct TableEntry {
    unsigned short iCode;
    unsigned char flags;
    unsigned char nRange;
  } aEntry[] = {
    {65, 14, 26},          {181, 64, 1},          {192, 14, 23},
    {216, 14, 7},          {256, 1, 48},          {306, 1, 6},
    {313, 1, 16},          {330, 1, 46},          {376, 116, 1},
    {377, 1, 6},           {383, 104, 1},         {385, 50, 1},
    {386, 1, 4},           {390, 44, 1},          {391, 0, 1},
    {393, 42, 2},          {395, 0, 1},           {398, 32, 1},
    {399, 38, 1},          {400, 40, 1},          {401, 0, 1},
    {403, 42, 1},          {404, 46, 1},          {406, 52, 1},
    {407, 48, 1},          {408, 0, 1},           {412, 52, 1},
    {413, 54, 1},          {415, 56, 1},          {416, 1, 6},
    {422, 60, 1},          {423, 0, 1},           {425, 60, 1},
    {428, 0, 1},           {430, 60, 1},          {431, 0, 1},
    {433, 58, 2},          {435, 1, 4},           {439, 62, 1},
    {440, 0, 1},           {444, 0, 1},           {452, 2, 1},
    {453, 0, 1},           {455, 2, 1},           {456, 0, 1},
    {458, 2, 1},           {459, 1, 18},          {478, 1, 18},
    {497, 2, 1},           {498, 1, 4},           {502, 122, 1},
    {503, 134, 1},         {504, 1, 40},          {544, 110, 1},
    {546, 1, 18},          {570, 70, 1},          {571, 0, 1},
    {573, 108, 1},         {574, 68, 1},          {577, 0, 1},
    {579, 106, 1},         {580, 28, 1},          {581, 30, 1},
    {582, 1, 10},          {837, 36, 1},          {880, 1, 4},
    {886, 0, 1},           {902, 18, 1},          {904, 16, 3},
    {908, 26, 1},          {910, 24, 2},          {913, 14, 17},
    {931, 14, 9},          {962, 0, 1},           {975, 4, 1},
    {976, 140, 1},         {977, 142, 1},         {981, 146, 1},
    {982, 144, 1},         {984, 1, 24},          {1008, 136, 1},
    {1009, 138, 1},        {1012, 130, 1},        {1013, 128, 1},
    {1015, 0, 1},          {1017, 152, 1},        {1018, 0, 1},
    {1021, 110, 3},        {1024, 34, 16},        {1040, 14, 32},
    {1120, 1, 34},         {1162, 1, 54},         {1216, 6, 1},
    {1217, 1, 14},         {1232, 1, 88},         {1329, 22, 38},
    {4256, 66, 38},        {4295, 66, 1},         {4301, 66, 1},
    {7680, 1, 150},        {7835, 132, 1},        {7838, 96, 1},
    {7840, 1, 96},         {7944, 150, 8},        {7960, 150, 6},
    {7976, 150, 8},        {7992, 150, 8},        {8008, 150, 6},
    {8025, 151, 8},        {8040, 150, 8},        {8072, 150, 8},
    {8088, 150, 8},        {8104, 150, 8},        {8120, 150, 2},
    {8122, 126, 2},        {8124, 148, 1},        {8126, 100, 1},
    {8136, 124, 4},        {8140, 148, 1},        {8152, 150, 2},
    {8154, 120, 2},        {8168, 150, 2},        {8170, 118, 2},
    {8172, 152, 1},        {8184, 112, 2},        {8186, 114, 2},
    {8188, 148, 1},        {8486, 98, 1},         {8490, 92, 1},
    {8491, 94, 1},         {8498, 12, 1},         {8544, 8, 16},
    {8579, 0, 1},          {9398, 10, 26},        {11264, 22, 47},
    {11360, 0, 1},         {11362, 88, 1},        {11363, 102, 1},
    {11364, 90, 1},        {11367, 1, 6},         {11373, 84, 1},
    {11374, 86, 1},        {11375, 80, 1},        {11376, 82, 1},
    {11378, 0, 1},         {11381, 0, 1},         {11390, 78, 2},
    {11392, 1, 100},       {11499, 1, 4},         {11506, 0, 1},
    {42560, 1, 46},        {42624, 1, 24},        {42786, 1, 14},
    {42802, 1, 62},        {42873, 1, 4},         {42877, 76, 1},
    {42878, 1, 10},        {42891, 0, 1},         {42893, 74, 1},
    {42896, 1, 4},         {42912, 1, 10},        {42922, 72, 1},
    {65313, 14, 26},       
  };
  static const unsigned short aiOff[] = {
   1,     2,     8,     15,    16,    26,    28,    32,    
   37,    38,    40,    48,    63,    64,    69,    71,    
   79,    80,    116,   202,   203,   205,   206,   207,   
   209,   210,   211,   213,   214,   217,   218,   219,   
   775,   7264,  10792, 10795, 23228, 23256, 30204, 54721, 
   54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, 
   57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, 
   65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, 
   65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, 
   65514, 65521, 65527, 65528, 65529, 
  };

  int ret = c;

  assert( c>=0 );
  assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );

  if( c<128 ){
    if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
  }else if( c<65536 ){
    int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
    int iLo = 0;
    int iRes = -1;

    while( iHi>=iLo ){
      int iTest = (iHi + iLo) / 2;
      int cmp = (c - aEntry[iTest].iCode);
      if( cmp>=0 ){
        iRes = iTest;
        iLo = iTest+1;
      }else{
        iHi = iTest-1;
      }
    }
    assert( iRes<0 || c>=aEntry[iRes].iCode );

    if( iRes>=0 ){
      const struct TableEntry *p = &aEntry[iRes];
      if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
        ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
        assert( ret>0 );
      }
    }
  }
  
  else if( c>=66560 && c<66600 ){
    ret = c + 40;
  }

  return ret;
}

/************** End of utf.c *************************************************/
/************** Begin file util.c ********************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
*/
/* #include <stdarg.h> */
#ifndef SQLITE4_OMIT_FLOATING_POINT
# include <math.h>
#endif

/*
** Routine needed to support the testcase() macro.
*/
#ifdef SQLITE4_COVERAGE_TEST
SQLITE4_PRIVATE void sqlite4Coverage(int x){
  static unsigned dummy = 0;
  dummy += (unsigned)x;
}
#endif

#ifndef SQLITE4_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
**
** Use the math library isnan() function if compiled with SQLITE4_HAVE_ISNAN.
** Otherwise, we have our own implementation that works on most systems.
*/
SQLITE4_PRIVATE int sqlite4IsNaN(double x){
  int rc;   /* The value return */
#if !defined(SQLITE4_HAVE_ISNAN)
  /*
  ** Systems that support the isnan() library function should probably
  ** make use of it by compiling with -DSQLITE4_HAVE_ISNAN.  But we have
  ** found that many systems do not have a working isnan() function so
  ** this implementation is provided as an alternative.
  **
  ** This NaN test sometimes fails if compiled on GCC with -ffast-math.
  ** On the other hand, the use of -ffast-math comes with the following
  ** warning:
  **
  **      This option [-ffast-math] should never be turned on by any
  **      -O option since it can result in incorrect output for programs
  **      which depend on an exact implementation of IEEE or ISO 
  **      rules/specifications for math functions.
  **
  ** Under MSVC, this NaN test may fail if compiled with a floating-
  ** point precision mode other than /fp:precise.  From the MSDN 
  ** documentation:
  **
  **      The compiler [with /fp:precise] will properly handle comparisons 
  **      involving NaN. For example, x != x evaluates to true if x is NaN 
  **      ...
  */
#ifdef __FAST_MATH__
# error SQLite will not work correctly with the -ffast-math option of GCC.
#endif
  volatile double y = x;
  volatile double z = y;
  rc = (y!=z);
#else  /* if defined(SQLITE4_HAVE_ISNAN) */
  rc = isnan(x);
#endif /* SQLITE4_HAVE_ISNAN */
  testcase( rc );
  return rc;
}

/*
** If r is not infinity, return 0.  If it is negative infinity return negative.
** Return positive if r is positive infinity.
*/
SQLITE4_PRIVATE int sqlite4IsInf(double r){
  return isinf(r);
}
  
#endif /* SQLITE4_OMIT_FLOATING_POINT */

/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
**
** The value returned will never be negative.  Nor will it ever be greater
** than the actual length of the string.  For very long strings (greater
** than 1GiB) the value returned might be less than the true string length.
*/
SQLITE4_PRIVATE int sqlite4Strlen30(const char *z){
  const char *z2 = z;
  if( z==0 ) return 0;
  while( *z2 ){ z2++; }
  return 0x3fffffff & (int)(z2 - z);
}

/*
** Set the most recent error code and error string for the sqlite
** handle "db". The error code is set to "err_code".
**
** If it is not NULL, string zFormat specifies the format of the
** error string in the style of the printf functions: The following
** format characters are allowed:
**
**      %s      Insert a string
**      %z      A string that should be freed after use
**      %d      Insert an integer
**      %T      Insert a token
**      %S      Insert the first element of a SrcList
**
** zFormat and any string tokens that follow it are assumed to be
** encoded in UTF-8.
**
** To clear the most recent error for sqlite handle "db", sqlite4Error
** should be called with err_code set to SQLITE4_OK and zFormat set
** to NULL.
*/
SQLITE4_PRIVATE void sqlite4Error(sqlite4 *db, int err_code, const char *zFormat, ...){
  if( db && (db->pErr || (db->pErr = sqlite4ValueNew(db))!=0) ){
    db->errCode = err_code;
    if( zFormat ){
      char *z;
      va_list ap;
      va_start(ap, zFormat);
      z = sqlite4VMPrintf(db, zFormat, ap);
      va_end(ap);
      sqlite4ValueSetStr(db->pErr, -1, z, SQLITE4_UTF8, SQLITE4_DYNAMIC, 0);
    }else{
      sqlite4ValueSetStr(db->pErr, 0, 0, SQLITE4_UTF8, SQLITE4_STATIC, 0);
    }
  }
}

/*
** Add an error message to pParse->zErrMsg and increment pParse->nErr.
** The following formatting characters are allowed:
**
**      %s      Insert a string
**      %z      A string that should be freed after use
**      %d      Insert an integer
**      %T      Insert a token
**      %S      Insert the first element of a SrcList
**
** This function should be used to report any error that occurs whilst
** compiling an SQL statement (i.e. within sqlite4_prepare()). The
** last thing the sqlite4_prepare() function does is copy the error
** stored by this function into the database handle using sqlite4Error().
** Function sqlite4Error() should be used during statement execution
** (sqlite4_step() etc.).
*/
SQLITE4_PRIVATE void sqlite4ErrorMsg(Parse *pParse, const char *zFormat, ...){
  char *zMsg;
  va_list ap;
  sqlite4 *db = pParse->db;
  va_start(ap, zFormat);
  zMsg = sqlite4VMPrintf(db, zFormat, ap);
  va_end(ap);
  if( db->suppressErr ){
    sqlite4DbFree(db, zMsg);
  }else{
    pParse->nErr++;
    sqlite4DbFree(db, pParse->zErrMsg);
    pParse->zErrMsg = zMsg;
    pParse->rc = SQLITE4_ERROR;
  }
}

/*
** Convert an SQL-style quoted string into a normal string by removing
** the quote characters.  The conversion is done in-place.  If the
** input does not begin with a quote character, then this routine
** is a no-op.
**
** The input string must be zero-terminated.  A new zero-terminator
** is added to the dequoted string.
**
** The return value is -1 if no dequoting occurs or the length of the
** dequoted string, exclusive of the zero terminator, if dequoting does
** occur.
**
** 2002-Feb-14: This routine is extended to remove MS-Access style
** brackets from around identifers.  For example:  "[a-b-c]" becomes
** "a-b-c".
*/
SQLITE4_PRIVATE int sqlite4Dequote(char *z){
  char quote;
  int i, j;
  if( z==0 ) return -1;
  quote = z[0];
  switch( quote ){
    case '\'':  break;
    case '"':   break;
    case '`':   break;                /* For MySQL compatibility */
    case '[':   quote = ']';  break;  /* For MS SqlServer compatibility */
    default:    return -1;
  }
  for(i=1, j=0; ALWAYS(z[i]); i++){
    if( z[i]==quote ){
      if( z[i+1]==quote ){
        z[j++] = quote;
        i++;
      }else{
        break;
      }
    }else{
      z[j++] = z[i];
    }
  }
  z[j] = 0;
  return j;
}

/*
** Compare the 19-character string zNum against the text representation
** value 2^63:  9223372036854775808.  Return negative, zero, or positive
** if zNum is less than, equal to, or greater than the string.
** Note that zNum must contain exactly 19 characters.
**
** Unlike memcmp() this routine is guaranteed to return the difference
** in the values of the last digit if the only difference is in the
** last digit.  So, for example,
**
**      compare2pow63("9223372036854775800", 1)
**
** will return -8.
*/
static int compare2pow63(const char *zNum, int incr){
  int c = 0;
  int i;
                    /* 012345678901234567 */
  const char *pow63 = "922337203685477580";
  for(i=0; c==0 && i<18; i++){
    c = (zNum[i*incr]-pow63[i])*10;
  }
  if( c==0 ){
    c = zNum[18*incr] - '8';
    testcase( c==(-1) );
    testcase( c==0 );
    testcase( c==(+1) );
  }
  return c;
}


/*
** Convert zNum to a 64-bit signed integer.
**
** If the zNum value is representable as a 64-bit twos-complement 
** integer, then write that value into *pNum and return 0.
**
** If zNum is exactly 9223372036854665808, return 2.  This special
** case is broken out because while 9223372036854665808 cannot be a 
** signed 64-bit integer, its negative -9223372036854665808 can be.
**
** If zNum is too big for a 64-bit integer and is not
** 9223372036854665808 then return 1.
**
** length is the number of bytes in the string (bytes, not characters).
** The string is not necessarily zero-terminated.  The encoding is
** given by enc.
*/
SQLITE4_PRIVATE int sqlite4Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
  int incr = (enc==SQLITE4_UTF8?1:2);
  u64 u = 0;
  int neg = 0; /* assume positive */
  int i;
  int c = 0;
  const char *zStart;
  const char *zEnd = zNum + length;
  if( enc==SQLITE4_UTF16BE ) zNum++;
  while( zNum<zEnd && sqlite4Isspace(*zNum) ) zNum+=incr;
  if( zNum<zEnd ){
    if( *zNum=='-' ){
      neg = 1;
      zNum+=incr;
    }else if( *zNum=='+' ){
      zNum+=incr;
    }
  }
  zStart = zNum;
  while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
  for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
    u = u*10 + c - '0';
  }
  if( u>LARGEST_INT64 ){
    *pNum = SMALLEST_INT64;
  }else if( neg ){
    *pNum = -(i64)u;
  }else{
    *pNum = (i64)u;
  }
  testcase( i==18 );
  testcase( i==19 );
  testcase( i==20 );
  if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){
    /* zNum is empty or contains non-numeric text or is longer
    ** than 19 digits (thus guaranteeing that it is too large) */
    return 1;
  }else if( i<19*incr ){
    /* Less than 19 digits, so we know that it fits in 64 bits */
    assert( u<=LARGEST_INT64 );
    return 0;
  }else{
    /* zNum is a 19-digit numbers.  Compare it against 9223372036854775808. */
    c = compare2pow63(zNum, incr);
    if( c<0 ){
      /* zNum is less than 9223372036854775808 so it fits */
      assert( u<=LARGEST_INT64 );
      return 0;
    }else if( c>0 ){
      /* zNum is greater than 9223372036854775808 so it overflows */
      return 1;
    }else{
      /* zNum is exactly 9223372036854775808.  Fits if negative.  The
      ** special case 2 overflow if positive */
      assert( u-1==LARGEST_INT64 );
      assert( (*pNum)==SMALLEST_INT64 );
      return neg ? 0 : 2;
    }
  }
}

/*
** If zNum represents an integer that will fit in 32-bits, then set
** *pValue to that integer and return true.  Otherwise return false.
**
** Any non-numeric characters that following zNum are ignored.
** This is different from sqlite4Atoi64() which requires the
** input number to be zero-terminated.
*/
SQLITE4_PRIVATE int sqlite4GetInt32(const char *zNum, int *pValue){
  sqlite4_int64 v = 0;
  int i, c;
  int neg = 0;
  if( zNum[0]=='-' ){
    neg = 1;
    zNum++;
  }else if( zNum[0]=='+' ){
    zNum++;
  }
  while( zNum[0]=='0' ) zNum++;
  for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
    v = v*10 + c;
  }

  /* The longest decimal representation of a 32 bit integer is 10 digits:
  **
  **             1234567890
  **     2^31 -> 2147483648
  */
  testcase( i==10 );
  if( i>10 ){
    return 0;
  }
  testcase( v-neg==2147483647 );
  if( v-neg>2147483647 ){
    return 0;
  }
  if( neg ){
    v = -v;
  }
  *pValue = (int)v;
  return 1;
}

/*
** Return a 32-bit integer value extracted from a string.  If the
** string is not an integer, just return 0.
*/
SQLITE4_PRIVATE int sqlite4Atoi(const char *z){
  int x = 0;
  if( z ) sqlite4GetInt32(z, &x);
  return x;
}

/*
** Read or write a four-byte big-endian integer value.
*/
SQLITE4_PRIVATE u32 sqlite4Get4byte(const u8 *p){
  return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
SQLITE4_PRIVATE void sqlite4Put4byte(unsigned char *p, u32 v){
  p[0] = (u8)(v>>24);
  p[1] = (u8)(v>>16);
  p[2] = (u8)(v>>8);
  p[3] = (u8)v;
}



/*
** Translate a single byte of Hex into an integer.
** This routine only works if h really is a valid hexadecimal
** character:  0..9a..fA..F
*/
SQLITE4_PRIVATE u8 sqlite4HexToInt(int h){
  assert( (h>='0' && h<='9') ||  (h>='a' && h<='f') ||  (h>='A' && h<='F') );
#ifdef SQLITE4_ASCII
  h += 9*(1&(h>>6));
#endif
#ifdef SQLITE4_EBCDIC
  h += 9*(1&~(h>>4));
#endif
  return (u8)(h & 0xf);
}

#if !defined(SQLITE4_OMIT_BLOB_LITERAL) || defined(SQLITE4_HAS_CODEC)
/*
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
** value.  Return a pointer to its binary value.  Space to hold the
** binary value has been obtained from malloc and must be freed by
** the calling routine.
*/
SQLITE4_PRIVATE void *sqlite4HexToBlob(sqlite4 *db, const char *z, int n){
  char *zBlob;
  int i;

  zBlob = (char *)sqlite4DbMallocRaw(db, n/2 + 1);
  n--;
  if( zBlob ){
    for(i=0; i<n; i+=2){
      zBlob[i/2] = (sqlite4HexToInt(z[i])<<4) | sqlite4HexToInt(z[i+1]);
    }
    zBlob[i/2] = 0;
  }
  return zBlob;
}
#endif /* !SQLITE4_OMIT_BLOB_LITERAL || SQLITE4_HAS_CODEC */

/*
** Log an error that is an API call on a connection pointer that should
** not have been used.  The "type" of connection pointer is given as the
** argument.  The zType is a word like "NULL" or "closed" or "invalid".
*/
static void logBadConnection(const char *zType){
  sqlite4_log(0, SQLITE4_MISUSE, 
     "API call with %s database connection pointer",
     zType
  );
}

/*
** Check to make sure we have a valid db pointer.  This test is not
** foolproof but it does provide some measure of protection against
** misuse of the interface such as passing in db pointers that are
** NULL or which have been previously closed.  If this routine returns
** 1 it means that the db pointer is valid and 0 if it should not be
** dereferenced for any reason.  The calling function should invoke
** SQLITE4_MISUSE immediately.
**
** sqlite4SafetyCheckOk() requires that the db pointer be valid for
** use.  sqlite4SafetyCheckSickOrOk() allows a db pointer that failed to
** open properly and is not fit for general use but which can be
** used as an argument to sqlite4_errmsg() or sqlite4_close().
*/
SQLITE4_PRIVATE int sqlite4SafetyCheckOk(sqlite4 *db){
  u32 magic;
  if( db==0 ){
    logBadConnection("NULL");
    return 0;
  }
  magic = db->magic;
  if( magic!=SQLITE4_MAGIC_OPEN ){
    if( sqlite4SafetyCheckSickOrOk(db) ){
      testcase( sqlite4DefaultEnv.xLog!=0 );
      logBadConnection("unopened");
    }
    return 0;
  }else{
    return 1;
  }
}
SQLITE4_PRIVATE int sqlite4SafetyCheckSickOrOk(sqlite4 *db){
  u32 magic;
  magic = db->magic;
  if( magic!=SQLITE4_MAGIC_SICK &&
      magic!=SQLITE4_MAGIC_OPEN &&
      magic!=SQLITE4_MAGIC_BUSY ){
    testcase( sqlite4DefaultEnv.xLog!=0 );
    logBadConnection("invalid");
    return 0;
  }else{
    return 1;
  }
}

/*
** Attempt to add, substract, or multiply the 64-bit signed value iB against
** the other 64-bit signed integer at *pA and store the result in *pA.
** Return 0 on success.  Or if the operation would have resulted in an
** overflow, leave *pA unchanged and return 1.
*/
SQLITE4_PRIVATE int sqlite4AddInt64(i64 *pA, i64 iB){
  i64 iA = *pA;
  testcase( iA==0 ); testcase( iA==1 );
  testcase( iB==-1 ); testcase( iB==0 );
  if( iB>=0 ){
    testcase( iA>0 && LARGEST_INT64 - iA == iB );
    testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
    if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
    *pA += iB;
  }else{
    testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
    testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
    if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
    *pA += iB;
  }
  return 0; 
}
SQLITE4_PRIVATE int sqlite4SubInt64(i64 *pA, i64 iB){
  testcase( iB==SMALLEST_INT64+1 );
  if( iB==SMALLEST_INT64 ){
    testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
    if( (*pA)>=0 ) return 1;
    *pA -= iB;
    return 0;
  }else{
    return sqlite4AddInt64(pA, -iB);
  }
}
#define TWOPOWER32 (((i64)1)<<32)
#define TWOPOWER31 (((i64)1)<<31)
SQLITE4_PRIVATE int sqlite4MulInt64(i64 *pA, i64 iB){
  i64 iA = *pA;
  i64 iA1, iA0, iB1, iB0, r;

  iA1 = iA/TWOPOWER32;
  iA0 = iA % TWOPOWER32;
  iB1 = iB/TWOPOWER32;
  iB0 = iB % TWOPOWER32;
  if( iA1*iB1 != 0 ) return 1;
  assert( iA1*iB0==0 || iA0*iB1==0 );
  r = iA1*iB0 + iA0*iB1;
  testcase( r==(-TWOPOWER31)-1 );
  testcase( r==(-TWOPOWER31) );
  testcase( r==TWOPOWER31 );
  testcase( r==TWOPOWER31-1 );
  if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1;
  r *= TWOPOWER32;
  if( sqlite4AddInt64(&r, iA0*iB0) ) return 1;
  *pA = r;
  return 0;
}

/*
** Compute the absolute value of a 32-bit signed integer, of possible.  Or 
** if the integer has a value of -2147483648, return +2147483647
*/
SQLITE4_PRIVATE int sqlite4AbsInt32(int x){
  if( x>=0 ) return x;
  if( x==(int)0x80000000 ) return 0x7fffffff;
  return -x;
}

#ifdef SQLITE4_ENABLE_8_3_NAMES
/*
** If SQLITE4_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 SQLITE4_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
** do the suffix shortening regardless of URI parameter.
**
** Examples:
**
**     test.db-journal    =>   test.nal
**     test.db-wal        =>   test.wal
**     test.db-shm        =>   test.shm
**     test.db-mj7f3319fa =>   test.9fa
*/
SQLITE4_PRIVATE void sqlite4FileSuffix3(const char *zBaseFilename, char *z){
#if SQLITE4_ENABLE_8_3_NAMES<2
  if( sqlite4_uri_boolean(zBaseFilename, "8_3_names", 0) )
#endif
  {
    int i, sz;
    sz = sqlite4Strlen30(z);
    for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
    if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
  }
}
#endif

/************** End of util.c ************************************************/
/************** Begin file varint.c ******************************************/
/*
** 2012 January 17
**
** The authors renounce all claim of copyright to this code and dedicate
** this code to the public domain.  In place of 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 routines used to encode or decode variable-length
** integers.
**
** A variable length integer is an encoding of 64-bit unsigned integers
** into between 1 and 9 bytes.  The encoding is designed so that small
** (and common) values take much less space that larger values.  Additional
** properties:
**
**    *  The length of the varint can be determined after examining just
**       the first byte of the encoding.
**
**    *  Varints compare in numerical order using memcmp().
**
**************************************************************************
** 
** Treat each byte of the encoding as an unsigned integer between 0 and 255.
** Let the bytes of the encoding be called A0, A1, A2, ..., A8.
** 
** DECODE
** 
** If A0 is between 0 and 240 inclusive, then the result is the value of A0.
** 
** If A0 is between 241 and 248 inclusive, then the result is
** 240+256*(A0-241)+A1.
** 
** If A0 is 249 then the result is 2288+256*A1+A2.
** 
** If A0 is 250 then the result is A1..A3 as a 3-byte big-ending integer.
** 
** If A0 is 251 then the result is A1..A4 as a 4-byte big-ending integer.
** 
** If A0 is 252 then the result is A1..A5 as a 5-byte big-ending integer.
** 
** If A0 is 253 then the result is A1..A6 as a 6-byte big-ending integer.
** 
** If A0 is 254 then the result is A1..A7 as a 7-byte big-ending integer.
** 
** If A0 is 255 then the result is A1..A8 as a 8-byte big-ending integer.
** 
** ENCODE
** 
** Let the input value be V.
** 
** If V<=240 then output a single by A0 equal to V.
** 
** If V<=2287 then output A0 as (V-240)/256 + 241 and A1 as (V-240)%256.
** 
** If V<=67823 then output A0 as 249, A1 as (V-2288)/256, and A2 
** as (V-2288)%256.
** 
** If V<=16777215 then output A0 as 250 and A1 through A3 as a big-endian
** 3-byte integer.
** 
** If V<=4294967295 then output A0 as 251 and A1..A4 as a big-ending
** 4-byte integer.
** 
** If V<=1099511627775 then output A0 as 252 and A1..A5 as a big-ending
** 5-byte integer.
** 
** If V<=281474976710655 then output A0 as 253 and A1..A6 as a big-ending
** 6-byte integer.
** 
** If V<=72057594037927935 then output A0 as 254 and A1..A7 as a
** big-ending 7-byte integer.
** 
** Otherwise then output A0 as 255 and A1..A8 as a big-ending 8-byte integer.
** 
** SUMMARY
** 
**    Bytes    Max Value    Digits
**    -------  ---------    ---------
**      1      240           2.3
**      2      2287          3.3
**      3      67823         4.8
**      4      2**24-1       7.2
**      5      2**32-1       9.6
**      6      2**40-1      12.0
**      7      2**48-1      14.4
**      8      2**56-1      16.8
**      9      2**64-1      19.2
** 
*/

/*
** Decode the varint in the first n bytes z[].  Write the integer value
** into *pResult and return the number of bytes in the varint.
**
** If the decode fails because there are not enough bytes in z[] then
** return 0;
*/
SQLITE4_PRIVATE int sqlite4GetVarint64(
  const unsigned char *z,
  int n,
  sqlite4_uint64 *pResult
){
  unsigned int x;
  if( n<1 ) return 0;
  if( z[0]<=240 ){
    *pResult = z[0];
    return 1;
  }
  if( z[0]<=248 ){
    if( n<2 ) return 0;
    *pResult = (z[0]-241)*256 + z[1] + 240;
    return 2;
  }
  if( n<z[0]-246 ) return 0;
  if( z[0]==249 ){
    *pResult = 2288 + 256*z[1] + z[2];
    return 3;
  }
  if( z[0]==250 ){
    *pResult = (z[1]<<16) + (z[2]<<8) + z[3];
    return 4;
  }
  x = (z[1]<<24) + (z[2]<<16) + (z[3]<<8) + z[4];
  if( z[0]==251 ){
    *pResult = x;
    return 5;
  }
  if( z[0]==252 ){
    *pResult = (((sqlite4_uint64)x)<<8) + z[5];
    return 6;
  }
  if( z[0]==253 ){
    *pResult = (((sqlite4_uint64)x)<<16) + (z[5]<<8) + z[6];
    return 7;
  }
  if( z[0]==254 ){
    *pResult = (((sqlite4_uint64)x)<<24) + (z[5]<<16) + (z[6]<<8) + z[7];
    return 8;
  }
  *pResult = (((sqlite4_uint64)x)<<32) +
               (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
  return 9;
}

/*
** Write a 32-bit unsigned integer as 4 big-endian bytes.
*/
static void varintWrite32(unsigned char *z, unsigned int y){
  z[0] = (unsigned char)(y>>24);
  z[1] = (unsigned char)(y>>16);
  z[2] = (unsigned char)(y>>8);
  z[3] = (unsigned char)(y);
}

/*
** Write a varint into z[].  The buffer z[] must be at least 9 characters
** long to accommodate the largest possible varint.  Return the number of
** bytes of z[] used.
*/
SQLITE4_PRIVATE int sqlite4PutVarint64(unsigned char *z, sqlite4_uint64 x){
  unsigned int w, y;
  if( x<=240 ){
    z[0] = (unsigned char)x;
    return 1;
  }
  if( x<=2287 ){
    y = (unsigned int)(x - 240);
    z[0] = (unsigned char)(y/256 + 241);
    z[1] = (unsigned char)(y%256);
    return 2;
  }
  if( x<=67823 ){
    y = (unsigned int)(x - 2288);
    z[0] = 249;
    z[1] = (unsigned char)(y/256);
    z[2] = (unsigned char)(y%256);
    return 3;
  }
  y = (unsigned int)x;
  w = (unsigned int)(x>>32);
  if( w==0 ){
    if( y<=16777215 ){
      z[0] = 250;
      z[1] = (unsigned char)(y>>16);
      z[2] = (unsigned char)(y>>8);
      z[3] = (unsigned char)(y);
      return 4;
    }
    z[0] = 251;
    varintWrite32(z+1, y);
    return 5;
  }
  if( w<=255 ){
    z[0] = 252;
    z[1] = (unsigned char)w;
    varintWrite32(z+2, y);
    return 6;
  }
  if( w<=65535 ){
    z[0] = 253;
    z[1] = (unsigned char)(w>>8);
    z[2] = (unsigned char)w;
    varintWrite32(z+3, y);
    return 7;
  }
  if( w<=16777215 ){
    z[0] = 254;
    z[1] = (unsigned char)(w>>16);
    z[2] = (unsigned char)(w>>8);
    z[3] = (unsigned char)w;
    varintWrite32(z+4, y);
    return 8;
  }
  z[0] = 255;
  varintWrite32(z+1, w);
  varintWrite32(z+5, y);
  return 9;
}

/*
** Return the number of bytes required to encode value v as a varint.
*/
SQLITE4_PRIVATE int sqlite4VarintLen(sqlite4_uint64 v){
  unsigned char aDummy[9];
  return sqlite4PutVarint64(aDummy, v);
}

/*
** Read a varint from buffer z and set *pResult to the value read.
** Return the number of bytes read from the buffer.
*/
SQLITE4_PRIVATE int sqlite4GetVarint32(const unsigned char *z, u32 *pResult){
  sqlite4_uint64 iRes;
  int ret;
  ret = sqlite4GetVarint64(z, 9, &iRes);
  *pResult = (u32)iRes;
  return ret;
}

/*
** Encode v as a varint and write the result to buffer p. Return the
** number of bytes written.
*/
SQLITE4_PRIVATE int sqlite4PutVarint32(unsigned char *p, u32 v){
  return sqlite4PutVarint64(p, v);
}

/*
** Compile this one file with the -DTEST_VARINT option to run the simple
** test case below.  The test program generates 10 million random 64-bit
** values, weighted toward smaller numbers, and for each value it encodes
** and then decodes the varint to verify that the same number comes back.
** It also checks to make sure the if x<y then memcmp(varint(x),varint(y))<0.
*/
#ifdef TEST_VARINT
static unsigned int randInt(void){
  static unsigned int rx = 1;
  static unsigned int ry = 0;
  rx = (rx>>1) ^ (-(rx&1) & 0xd0000001);
  ry = ry*1103515245 + 12345;
  return rx ^ ry;
}
int main(int argc,char **argv){
  sqlite4_uint64 x, y, px;
  int i, n1, n2, pn;
  int nbit;
  unsigned char z[20], zp[20];

  for(i=0; i<10000000; i++){
    x = randInt();
    x = (x<<32) + randInt();
    nbit = randInt()%65;
    if( nbit<64 ){
      x &= (((sqlite4_uint64)1)<<nbit)-1;
    }
    n1 = sqlite4PutVarint64(z, x);
    assert( n1>=1 && n1<=9 );
    n2 = sqlite4GetVarint64(z, n1, &y);
    assert( n1==n2 );
    assert( x==y );
    n2 = sqlite4GetVarint64(z, n1-1, &y);
    assert( n2==0 );
    if( i>0 ){
      int c = memcmp(z,zp,pn<n1?pn:n1);
      if( x<px ){
        assert( c<0 );
      }else if( x>px ){
        assert( c>0 );
      }else{
        assert( c==0 );
      }
    }
    memcpy(zp, z, n1);
    pn = n1;
    px = x;
    /* printf("%24lld 0x%016llx n=%d ok\n",
              (long long int)x, (long long int)x, n1); */
  }
  printf("%d tests with 0 errors\n", i);
  return 0;
}
#endif

/*
** Compile this one file with -DVARINT_TOOL to generate a command-line
** program that converts the integers it finds as arguments into varints
** and hex varints preceded by "=" into integers and then displays the
** results on standard output.
*/
#ifdef VARINT_TOOL
static int hexToInt(char c){
  if( c>='0' && c<='9' ) return c - '0';
  if( c>='a' && c<='f' ) return c - 'a' + 10;
  if( c>='A' && c<='F' ) return c - 'A' + 10;
  return 0;
}
int main(int argc, char **argv){
  int i, j, n;
  sqlite4_uint64 x;
  char out[20];
  if( argc<=1 ){
    printf("Usage: %s N =X ...\n"
           "Convert integer values into varints.\n"
           "Convert hex varint values preceded by '=' into integers.\n", 
           argv[0]);
    return 1;
  }
  for(i=1; i<argc; i++){
    const char *z = argv[i];
    x = 0;
    if( z[0]=='=' ){
      for(j=1; j/2<sizeof(out) && z[j] && z[j+1]; j+=2 ){
        out[j/2] = hexToInt(z[j])*16 + hexToInt(z[j+1]);
      }
      sqlite4GetVarint64(out, j/2, &x);
    }else{
      while( z[0]>='0' && z[0]<='9' ){
        x = x*10 + z[0] - '0';
        z++;
      }
    }
    n = sqlite4PutVarint64(out, x);
    printf("%llu = ", (long long unsigned)x);
    for(j=0; j<n; j++) printf("%02x", out[j]&0xff);
    printf("\n");
  }
  return 0;
}
#endif

/************** End of varint.c **********************************************/
/************** Begin file hash.c ********************************************/
/*
** 2001 September 22
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
*/
/* #include <assert.h> */

/*
** The hashing function.
*/
static unsigned int strHash(const char *z, int nKey){
  int h = 0;
  assert( nKey>=0 );
  while( nKey > 0  ){
    h = (h<<3) ^ h ^ sqlite4UpperToLower[(unsigned char)*z++];
    nKey--;
  }
  return h;
}

static int strCmp(const char *z1, const char *z2, int n){
  return sqlite4_strnicmp(z1, z2, n);
}

static unsigned int binHash(const char *z, int nKey){
  int h = 0;
  assert( nKey>=0 );
  while( nKey > 0  ){
    h = (h<<3) ^ h ^ ((unsigned char)*z++);
    nKey--;
  }
  return h;
}

static int binCmp(const char *z1, const char *z2, int n){
  return memcmp(z1, z2, n);
}

/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
*/
SQLITE4_PRIVATE void sqlite4HashInit(sqlite4_env *pEnv, Hash *pNew, int bBin){
  assert( pNew!=0 );
  pNew->first = 0;
  pNew->count = 0;
  pNew->htsize = 0;
  pNew->ht = 0;
  pNew->pEnv = pEnv;
  if( bBin ){
    pNew->xHash = binHash;
    pNew->xCmp = binCmp;
  }else{
    pNew->xHash = strHash;
    pNew->xCmp = strCmp;
  }
}

/* Remove all entries from a hash table.  Reclaim all memory.
** Call this routine to delete a hash table or to reset a hash table
** to the empty state.
*/
SQLITE4_PRIVATE void sqlite4HashClear(Hash *pH){
  HashElem *elem;         /* For looping over all elements of the table */

  assert( pH!=0 );
  elem = pH->first;
  pH->first = 0;
  sqlite4_free(pH->pEnv, pH->ht);
  pH->ht = 0;
  pH->htsize = 0;
  while( elem ){
    HashElem *next_elem = elem->next;
    sqlite4_free(pH->pEnv, elem);
    elem = next_elem;
  }
  pH->count = 0;
}

/* Link pNew element into the hash table pH.  If pEntry!=0 then also
** insert pNew into the pEntry hash bucket.
*/
static void insertElement(
  Hash *pH,              /* The complete hash table */
  struct _ht *pEntry,    /* The entry into which pNew is inserted */
  HashElem *pNew         /* The element to be inserted */
){
  HashElem *pHead;       /* First element already in pEntry */
  if( pEntry ){
    pHead = pEntry->count ? pEntry->chain : 0;
    pEntry->count++;
    pEntry->chain = pNew;
  }else{
    pHead = 0;
  }
  if( pHead ){
    pNew->next = pHead;
    pNew->prev = pHead->prev;
    if( pHead->prev ){ pHead->prev->next = pNew; }
    else             { pH->first = pNew; }
    pHead->prev = pNew;
  }else{
    pNew->next = pH->first;
    if( pH->first ){ pH->first->prev = pNew; }
    pNew->prev = 0;
    pH->first = pNew;
  }
}


/* Resize the hash table so that it cantains "new_size" buckets.
**
** The hash table might fail to resize if sqlite4_malloc() fails or
** if the new size is the same as the prior size.
** Return TRUE if the resize occurs and false if not.
*/
static int rehash(Hash *pH, unsigned int new_size){
  struct _ht *new_ht;            /* The new hash table */
  HashElem *elem, *next_elem;    /* For looping over existing elements */

#if SQLITE4_MALLOC_SOFT_LIMIT>0
  if( new_size*sizeof(struct _ht)>SQLITE4_MALLOC_SOFT_LIMIT ){
    new_size = SQLITE4_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
  }
  if( new_size==pH->htsize ) return 0;
#endif

  /* The inability to allocates space for a larger hash table is
  ** a performance hit but it is not a fatal error.  So mark the
  ** allocation as a benign.
  */
  sqlite4BeginBenignMalloc(pH->pEnv);
  new_ht = (struct _ht *)sqlite4Malloc(pH->pEnv, new_size*sizeof(struct _ht) );
  sqlite4EndBenignMalloc(pH->pEnv);

  if( new_ht==0 ) return 0;
  sqlite4_free(pH->pEnv, pH->ht);
  pH->ht = new_ht;
  pH->htsize = new_size = sqlite4MallocSize(pH->pEnv, new_ht)/sizeof(struct _ht);
  memset(new_ht, 0, new_size*sizeof(struct _ht));
  for(elem=pH->first, pH->first=0; elem; elem = next_elem){
    unsigned int h = pH->xHash(elem->pKey, elem->nKey) % new_size;
    next_elem = elem->next;
    insertElement(pH, &new_ht[h], elem);
  }
  return 1;
}

/* This function (for internal use only) locates an element in an
** hash table that matches the given key.  The hash for this key has
** already been computed and is passed as the 4th parameter.
*/
static HashElem *findElementGivenHash(
  const Hash *pH,     /* The pH to be searched */
  const char *pKey,   /* The key we are searching for */
  int nKey,           /* Bytes in key (not counting zero terminator) */
  unsigned int h      /* The hash for this key. */
){
  HashElem *elem;                /* Used to loop thru the element list */
  int count;                     /* Number of elements left to test */

  if( pH->ht ){
    struct _ht *pEntry = &pH->ht[h];
    elem = pEntry->chain;
    count = pEntry->count;
  }else{
    elem = pH->first;
    count = pH->count;
  }
  while( count-- && ALWAYS(elem) ){
    if( elem->nKey==nKey && pH->xCmp(elem->pKey,pKey,nKey)==0 ){ 
      return elem;
    }
    elem = elem->next;
  }
  return 0;
}

/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
static void removeElementGivenHash(
  Hash *pH,         /* The pH containing "elem" */
  HashElem* elem,   /* The element to be removed from the pH */
  unsigned int h    /* Hash value for the element */
){
  struct _ht *pEntry;
  if( elem->prev ){
    elem->prev->next = elem->next; 
  }else{
    pH->first = elem->next;
  }
  if( elem->next ){
    elem->next->prev = elem->prev;
  }
  if( pH->ht ){
    pEntry = &pH->ht[h];
    if( pEntry->chain==elem ){
      pEntry->chain = elem->next;
    }
    pEntry->count--;
    assert( pEntry->count>=0 );
  }
  sqlite4_free(pH->pEnv, elem);
  pH->count--;
  if( pH->count<=0 ){
    assert( pH->first==0 );
    assert( pH->count==0 );
    sqlite4HashClear(pH);
  }
}

/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey.  Return the data for this element if it is
** found, or NULL if there is no match.
*/
SQLITE4_PRIVATE void *sqlite4HashFind(const Hash *pH, const char *pKey, int nKey){
  HashElem *elem;    /* The element that matches key */
  unsigned int h;    /* A hash on key */

  assert( pH!=0 );
  assert( pKey!=0 );
  assert( nKey>=0 );
  if( pH->ht ){
    h = pH->xHash(pKey, nKey) % pH->htsize;
  }else{
    h = 0;
  }
  elem = findElementGivenHash(pH, pKey, nKey, h);
  return elem ? elem->data : 0;
}

/* Insert an element into the hash table pH.  The key is pKey,nKey
** and the data is "data".
**
** If no element exists with a matching key, then a new
** element is created and NULL is returned.
**
** If another element already exists with the same key, then the
** new data replaces the old data and the old data is returned.
** The key is not copied in this instance.  If a malloc fails, then
** the new data is returned and the hash table is unchanged.
**
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
SQLITE4_PRIVATE void *sqlite4HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
  unsigned int h;       /* the hash of the key modulo hash table size */
  HashElem *elem;       /* Used to loop thru the element list */
  HashElem *new_elem;   /* New element added to the pH */

  assert( pH!=0 );
  assert( pKey!=0 );
  assert( nKey>=0 );
  if( pH->htsize ){
    h = pH->xHash(pKey, nKey) % pH->htsize;
  }else{
    h = 0;
  }
  elem = findElementGivenHash(pH,pKey,nKey,h);
  if( elem ){
    void *old_data = elem->data;
    if( data==0 ){
      removeElementGivenHash(pH,elem,h);
    }else{
      elem->data = data;
      elem->pKey = pKey;
      assert(nKey==elem->nKey);
    }
    return old_data;
  }
  if( data==0 ) return 0;
  new_elem = (HashElem*)sqlite4Malloc(pH->pEnv, sizeof(HashElem) );
  if( new_elem==0 ) return data;
  new_elem->pKey = pKey;
  new_elem->nKey = nKey;
  new_elem->data = data;
  pH->count++;
  if( pH->count>=10 && pH->count > 2*pH->htsize ){
    if( rehash(pH, pH->count*2) ){
      assert( pH->htsize>0 );
      h = pH->xHash(pKey, nKey) % pH->htsize;
    }
  }
  if( pH->ht ){
    insertElement(pH, &pH->ht[h], new_elem);
  }else{
    insertElement(pH, 0, new_elem);
  }
  return 0;
}

/************** End of hash.c ************************************************/
/************** Begin file opcodes.c *****************************************/
/* Automatically generated.  Do not edit */
/* See the mkopcodec.awk script for details. */
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
SQLITE4_PRIVATE const char *sqlite4OpcodeName(int i){
 static const char *const azName[] = { "?",
     /*   1 */ "Goto",
     /*   2 */ "Gosub",
     /*   3 */ "Return",
     /*   4 */ "Yield",
     /*   5 */ "HaltIfNull",
     /*   6 */ "Halt",
     /*   7 */ "Integer",
     /*   8 */ "Num",
     /*   9 */ "String",
     /*  10 */ "Null",
     /*  11 */ "Blob",
     /*  12 */ "Variable",
     /*  13 */ "Move",
     /*  14 */ "Copy",
     /*  15 */ "SCopy",
     /*  16 */ "ResultRow",
     /*  17 */ "CollSeq",
     /*  18 */ "KVMethod",
     /*  19 */ "Not",
     /*  20 */ "Mifunction",
     /*  21 */ "Function",
     /*  22 */ "AddImm",
     /*  23 */ "MustBeInt",
     /*  24 */ "RealAffinity",
     /*  25 */ "Permutation",
     /*  26 */ "Compare",
     /*  27 */ "Jump",
     /*  28 */ "Once",
     /*  29 */ "If",
     /*  30 */ "IfNot",
     /*  31 */ "Column",
     /*  32 */ "MakeKey",
     /*  33 */ "MakeRecord",
     /*  34 */ "Affinity",
     /*  35 */ "Count",
     /*  36 */ "Savepoint",
     /*  37 */ "Transaction",
     /*  38 */ "ReadCookie",
     /*  39 */ "SetCookie",
     /*  40 */ "VerifyCookie",
     /*  41 */ "OpenRead",
     /*  42 */ "OpenWrite",
     /*  43 */ "OpenAutoindex",
     /*  44 */ "OpenEphemeral",
     /*  45 */ "SorterOpen",
     /*  46 */ "Close",
     /*  47 */ "SeekPk",
     /*  48 */ "SeekLt",
     /*  49 */ "SeekLe",
     /*  50 */ "SeekGe",
     /*  51 */ "SeekGt",
     /*  52 */ "NotExists",
     /*  53 */ "NotFound",
     /*  54 */ "Found",
     /*  55 */ "IsUnique",
     /*  56 */ "Sequence",
     /*  57 */ "NewRowid",
     /*  58 */ "NewIdxid",
     /*  59 */ "Delete",
     /*  60 */ "ResetCount",
     /*  61 */ "GrpCompare",
     /*  62 */ "SorterData",
     /*  63 */ "RowKey",
     /*  64 */ "RowData",
     /*  65 */ "AnalyzeKey",
     /*  66 */ "Rowid",
     /*  67 */ "Or",
     /*  68 */ "And",
     /*  69 */ "NullRow",
     /*  70 */ "Last",
     /*  71 */ "SorterSort",
     /*  72 */ "IsNull",
     /*  73 */ "NotNull",
     /*  74 */ "Ne",
     /*  75 */ "Eq",
     /*  76 */ "Gt",
     /*  77 */ "Le",
     /*  78 */ "Lt",
     /*  79 */ "Ge",
     /*  80 */ "Sort",
     /*  81 */ "BitAnd",
     /*  82 */ "BitOr",
     /*  83 */ "ShiftLeft",
     /*  84 */ "ShiftRight",
     /*  85 */ "Add",
     /*  86 */ "Subtract",
     /*  87 */ "Multiply",
     /*  88 */ "Divide",
     /*  89 */ "Remainder",
     /*  90 */ "Concat",
     /*  91 */ "Rewind",
     /*  92 */ "BitNot",
     /*  93 */ "String8",
     /*  94 */ "SorterNext",
     /*  95 */ "Prev",
     /*  96 */ "Next",
     /*  97 */ "Insert",
     /*  98 */ "IdxDelete",
     /*  99 */ "IdxRowkey",
     /* 100 */ "IdxLT",
     /* 101 */ "IdxLE",
     /* 102 */ "IdxGE",
     /* 103 */ "IdxGT",
     /* 104 */ "Clear",
     /* 105 */ "ParseSchema",
     /* 106 */ "LoadAnalysis",
     /* 107 */ "DropTable",
     /* 108 */ "DropIndex",
     /* 109 */ "DropTrigger",
     /* 110 */ "RowSetTest",
     /* 111 */ "RowSetAdd",
     /* 112 */ "RowSetRead",
     /* 113 */ "Program",
     /* 114 */ "Param",
     /* 115 */ "FkCounter",
     /* 116 */ "FkIfZero",
     /* 117 */ "MemMax",
     /* 118 */ "IfPos",
     /* 119 */ "IfNeg",
     /* 120 */ "IfZero",
     /* 121 */ "AggStep",
     /* 122 */ "AggFinal",
     /* 123 */ "JournalMode",
     /* 124 */ "Expire",
     /* 125 */ "VBegin",
     /* 126 */ "VCreate",
     /* 127 */ "VDestroy",
     /* 128 */ "VOpen",
     /* 129 */ "VFilter",
     /* 130 */ "VColumn",
     /* 131 */ "VNext",
     /* 132 */ "VRename",
     /* 133 */ "VUpdate",
     /* 134 */ "Trace",
     /* 135 */ "FtsUpdate",
     /* 136 */ "FtsCksum",
     /* 137 */ "FtsOpen",
     /* 138 */ "FtsNext",
     /* 139 */ "FtsPk",
     /* 140 */ "Noop",
     /* 141 */ "ToText",
     /* 142 */ "ToBlob",
     /* 143 */ "ToNumeric",
     /* 144 */ "ToInt",
     /* 145 */ "ToReal",
     /* 146 */ "Explain",
  };
  return azName[i];
}
#endif

/************** End of opcodes.c *********************************************/
/************** Begin file lsm_ckpt.c ****************************************/
/*
** 2011-09-11
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code to read and write checkpoints.
**
** A checkpoint represents the database layout at a single point in time.
** It includes a log offset. When an existing database is opened, the
** current state is determined by reading the newest checkpoint and updating
** it with all committed transactions from the log that follow the specified
** offset.
*/
/************** Include lsmInt.h in the middle of lsm_ckpt.c *****************/
/************** Begin file lsmInt.h ******************************************/
/*
** 2011-08-18
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal structure definitions for the LSM module.
*/
#ifndef _LSM_INT_H
#define _LSM_INT_H

/************** Include lsm.h in the middle of lsmInt.h **********************/
/************** Begin file lsm.h *********************************************/
/*
** 2011-08-10
**
** 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 defines the LSM API.
*/
#ifndef _LSM_H
#define _LSM_H
/* #include <stddef.h> */
#if 0
extern "C" {
#endif

/*
** Opaque handle types.
*/
typedef struct lsm_compress lsm_compress;   /* Compression library functions */
typedef struct lsm_compress_factory lsm_compress_factory;
typedef struct lsm_cursor lsm_cursor;       /* Database cursor handle */
typedef struct lsm_db lsm_db;               /* Database connection handle */
typedef struct lsm_env lsm_env;             /* Runtime environment */
typedef struct lsm_file lsm_file;           /* OS file handle */
typedef struct lsm_mutex lsm_mutex;         /* Mutex handle */

/* 64-bit integer type used for file offsets. */
typedef long long int lsm_i64;              /* 64-bit signed integer type */

/* Candidate values for the 3rd argument to lsm_env.xLock() */
#define LSM_LOCK_UNLOCK 0
#define LSM_LOCK_SHARED 1
#define LSM_LOCK_EXCL   2

/* Flags for lsm_env.xOpen() */
#define LSM_OPEN_READONLY 0x0001

/*
** CAPI: Database Runtime Environment
**
** Run-time environment used by LSM
*/
struct lsm_env {
  int nByte;                 /* Size of this structure in bytes */
  int iVersion;              /* Version number of this structure (1) */
  /****** file i/o ***********************************************/
  void *pVfsCtx;
  int (*xFullpath)(lsm_env*, const char *, char *, int *);
  int (*xOpen)(lsm_env*, const char *, int flags, lsm_file **);
  int (*xRead)(lsm_file *, lsm_i64, void *, int);
  int (*xWrite)(lsm_file *, lsm_i64, void *, int);
  int (*xTruncate)(lsm_file *, lsm_i64);
  int (*xSync)(lsm_file *);
  int (*xSectorSize)(lsm_file *);
  int (*xRemap)(lsm_file *, lsm_i64, void **, lsm_i64*);
  int (*xFileid)(lsm_file *, void *pBuf, int *pnBuf);
  int (*xClose)(lsm_file *);
  int (*xUnlink)(lsm_env*, const char *);
  int (*xLock)(lsm_file*, int, int);
  int (*xTestLock)(lsm_file*, int, int, int);
  int (*xShmMap)(lsm_file*, int, int, void **);
  void (*xShmBarrier)(void);
  int (*xShmUnmap)(lsm_file*, int);
  /****** memory allocation ****************************************/
  void *pMemCtx;
  void *(*xMalloc)(lsm_env*, int);            /* malloc(3) function */
  void *(*xRealloc)(lsm_env*, void *, int);   /* realloc(3) function */
  void (*xFree)(lsm_env*, void *);            /* free(3) function */
  sqlite4_size_t (*xSize)(lsm_env*, void *);  /* xSize function */
  /****** mutexes ****************************************************/
  void *pMutexCtx;
  int (*xMutexStatic)(lsm_env*,int,lsm_mutex**); /* Obtain a static mutex */
  int (*xMutexNew)(lsm_env*, lsm_mutex**);       /* Get a new dynamic mutex */
  void (*xMutexDel)(lsm_mutex *);           /* Delete an allocated mutex */
  void (*xMutexEnter)(lsm_mutex *);         /* Grab a mutex */
  int (*xMutexTry)(lsm_mutex *);            /* Attempt to obtain a mutex */
  void (*xMutexLeave)(lsm_mutex *);         /* Leave a mutex */
  int (*xMutexHeld)(lsm_mutex *);           /* Return true if mutex is held */
  int (*xMutexNotHeld)(lsm_mutex *);        /* Return true if mutex not held */
  /****** other ****************************************************/
  int (*xSleep)(lsm_env*, int microseconds);

  /* New fields may be added in future releases, in which case the
  ** iVersion value will increase. */
};

/* 
** Values that may be passed as the second argument to xMutexStatic. 
*/
#define LSM_MUTEX_GLOBAL 1
#define LSM_MUTEX_HEAP   2

/*
** CAPI: LSM Error Codes
*/
#define LSM_OK         0
#define LSM_ERROR      1
#define LSM_BUSY       5
#define LSM_NOMEM      7
#define LSM_READONLY   8
#define LSM_IOERR     10
#define LSM_CORRUPT   11
#define LSM_FULL      13
#define LSM_CANTOPEN  14
#define LSM_PROTOCOL  15
#define LSM_MISUSE    21

#define LSM_MISMATCH  50


#define LSM_IOERR_NOENT (LSM_IOERR | (1<<8))

/* 
** CAPI: Creating and Destroying Database Connection Handles
**
** Open and close a database connection handle.
*/
int lsm_new(lsm_env*, lsm_db **ppDb);
int lsm_close(lsm_db *pDb);

/* 
** CAPI: Connecting to a Database
*/
int lsm_open(lsm_db *pDb, const char *zFilename);

/*
** CAPI: Obtaining pointers to database environments
**
** Return a pointer to the environment used by the database connection 
** passed as the first argument. Assuming the argument is valid, this 
** function always returns a valid environment pointer - it cannot fail.
*/
lsm_env *lsm_get_env(lsm_db *pDb);

/*
** The lsm_default_env() function returns a pointer to the default LSM
** environment for the current platform.
*/
lsm_env *lsm_default_env(void);


/*
** CAPI: Configuring a database connection.
**
** The lsm_config() function is used to configure a database connection.
*/
int lsm_config(lsm_db *, int, ...);

/*
** The following values may be passed as the second argument to lsm_config().
**
** LSM_CONFIG_AUTOFLUSH:
**   A read/write integer parameter. 
**
**   This value determines the amount of data allowed to accumulate in a
**   live in-memory tree before it is marked as old. After committing a
**   transaction, a connection checks if the size of the live in-memory tree,
**   including data structure overhead, is greater than the value of this
**   option in KB. If it is, and there is not already an old in-memory tree,
**   the live in-memory tree is marked as old.
**
**   The maximum allowable value is 1048576 (1GB). There is no minimum 
**   value. If this parameter is set to zero, then an attempt is made to
**   mark the live in-memory tree as old after each transaction is committed.
**
**   The default value is 1024 (1MB).
**
** LSM_CONFIG_PAGE_SIZE:
**   A read/write integer parameter. This parameter may only be set before
**   lsm_open() has been called.
**
** LSM_CONFIG_BLOCK_SIZE:
**   A read/write integer parameter. 
**
**   This parameter may only be set before lsm_open() has been called. It
**   must be set to a power of two between 64 and 65536, inclusive (block 
**   sizes between 64KB and 64MB).
**
**   If the connection creates a new database, the block size of the new
**   database is set to the value of this option in KB. After lsm_open()
**   has been called, querying this parameter returns the actual block
**   size of the opened database.
**
**   The default value is 1024 (1MB blocks).
**
** LSM_CONFIG_SAFETY:
**   A read/write integer parameter. Valid values are 0, 1 (the default) 
**   and 2. This parameter determines how robust the database is in the
**   face of a system crash (e.g. a power failure or operating system 
**   crash). As follows:
**
**     0 (off):    No robustness. A system crash may corrupt the database.
**
**     1 (normal): Some robustness. A system crash may not corrupt the
**                 database file, but recently committed transactions may
**                 be lost following recovery.
**
**     2 (full):   Full robustness. A system crash may not corrupt the
**                 database file. Following recovery the database file
**                 contains all successfully committed transactions.
**
** LSM_CONFIG_AUTOWORK:
**   A read/write integer parameter.
**
** LSM_CONFIG_AUTOCHECKPOINT:
**   A read/write integer parameter.
**
**   If this option is set to non-zero value N, then a checkpoint is
**   automatically attempted after each N KB of data have been written to 
**   the database file.
**
**   The amount of uncheckpointed data already written to the database file
**   is a global parameter. After performing database work (writing to the
**   database file), the process checks if the total amount of uncheckpointed 
**   data exceeds the value of this paramter. If so, a checkpoint is performed.
**   This means that this option may cause the connection to perform a 
**   checkpoint even if the current connection has itself written very little
**   data into the database file.
**
**   The default value is 2048 (checkpoint every 2MB).
**
** LSM_CONFIG_MMAP:
**   A read/write integer parameter. If this value is set to 0, then the 
**   database file is accessed using ordinary read/write IO functions. Or,
**   if it is set to 1, then the database file is memory mapped and accessed
**   that way. If this parameter is set to any value N greater than 1, then
**   up to the first N KB of the file are memory mapped, and any remainder
**   accessed using read/write IO.
**
**   The default value is 1 on 64-bit platforms and 32768 on 32-bit platforms.
**   
**
** LSM_CONFIG_USE_LOG:
**   A read/write boolean parameter. True (the default) to use the log
**   file normally. False otherwise.
**
** LSM_CONFIG_AUTOMERGE:
**   A read/write integer parameter. The minimum number of segments to
**   merge together at a time. Default value 4.
**
** LSM_CONFIG_MAX_FREELIST:
**   A read/write integer parameter. The maximum number of free-list 
**   entries that are stored in a database checkpoint (the others are
**   stored elsewhere in the database).
**
**   There is no reason for an application to configure or query this
**   parameter. It is only present because configuring a small value
**   makes certain parts of the lsm code easier to test.
**
** LSM_CONFIG_MULTIPLE_PROCESSES:
**   A read/write boolean parameter. This parameter may only be set before
**   lsm_open() has been called. If true, the library uses shared-memory
**   and posix advisory locks to co-ordinate access by clients from within
**   multiple processes. Otherwise, if false, all database clients must be 
**   located in the same process. The default value is true.
**
** LSM_CONFIG_SET_COMPRESSION:
**   Set the compression methods used to compress and decompress database
**   content. The argument to this option should be a pointer to a structure
**   of type lsm_compress. The lsm_config() method takes a copy of the 
**   structures contents.
**
**   This option may only be used before lsm_open() is called. Invoking it
**   after lsm_open() has been called results in an LSM_MISUSE error.
**
** LSM_CONFIG_GET_COMPRESSION:
**   Query the compression methods used to compress and decompress database
**   content.
**
** LSM_CONFIG_SET_COMPRESSION_FACTORY:
**   Configure a factory method to be invoked in case of an LSM_MISMATCH
**   error.
**
** LSM_CONFIG_READONLY:
**   A read/write boolean parameter. This parameter may only be set before
**   lsm_open() is called.
*/
#define LSM_CONFIG_AUTOFLUSH                1
#define LSM_CONFIG_PAGE_SIZE                2
#define LSM_CONFIG_SAFETY                   3
#define LSM_CONFIG_BLOCK_SIZE               4
#define LSM_CONFIG_AUTOWORK                 5
#define LSM_CONFIG_MMAP                     7
#define LSM_CONFIG_USE_LOG                  8
#define LSM_CONFIG_AUTOMERGE                9
#define LSM_CONFIG_MAX_FREELIST            10
#define LSM_CONFIG_MULTIPLE_PROCESSES      11
#define LSM_CONFIG_AUTOCHECKPOINT          12
#define LSM_CONFIG_SET_COMPRESSION         13
#define LSM_CONFIG_GET_COMPRESSION         14
#define LSM_CONFIG_SET_COMPRESSION_FACTORY 15
#define LSM_CONFIG_READONLY                16

#define LSM_SAFETY_OFF    0
#define LSM_SAFETY_NORMAL 1
#define LSM_SAFETY_FULL   2

/*
** CAPI: Compression and/or Encryption Hooks
*/
struct lsm_compress {
  void *pCtx;
  unsigned int iId;
  int (*xBound)(void *, int nSrc);
  int (*xCompress)(void *, char *, int *, const char *, int);
  int (*xUncompress)(void *, char *, int *, const char *, int);
  void (*xFree)(void *pCtx);
};

struct lsm_compress_factory {
  void *pCtx;
  int (*xFactory)(void *, lsm_db *, unsigned int);
  void (*xFree)(void *pCtx);
};

#define LSM_COMPRESSION_EMPTY 0
#define LSM_COMPRESSION_NONE  1

/*
** CAPI: Allocating and Freeing Memory
**
** Invoke the memory allocation functions that belong to environment
** pEnv. Or the system defaults if no memory allocation functions have 
** been registered.
*/
void *lsm_malloc(lsm_env*, size_t);
void *lsm_realloc(lsm_env*, void *, size_t);
void lsm_free(lsm_env*, void *);

/*
** CAPI: Querying a Connection For Operational Data
**
** Query a database connection for operational statistics or data.
*/
int lsm_info(lsm_db *, int, ...);

int lsm_get_user_version(lsm_db *, unsigned int *);
int lsm_set_user_version(lsm_db *, unsigned int);

/*
** The following values may be passed as the second argument to lsm_info().
**
** LSM_INFO_NWRITE:
**   The third parameter should be of type (int *). The location pointed
**   to by the third parameter is set to the number of 4KB pages written to
**   the database file during the lifetime of this connection. 
**
** LSM_INFO_NREAD:
**   The third parameter should be of type (int *). The location pointed
**   to by the third parameter is set to the number of 4KB pages read from
**   the database file during the lifetime of this connection.
**
** LSM_INFO_DB_STRUCTURE:
**   The third argument should be of type (char **). The location pointed
**   to is populated with a pointer to a nul-terminated string containing
**   the string representation of a Tcl data-structure reflecting the 
**   current structure of the database file. Specifically, the current state
**   of the worker snapshot. The returned string should be eventually freed 
**   by the caller using lsm_free().
**
**   The returned list contains one element for each level in the database,
**   in order from most to least recent. Each element contains a 
**   single element for each segment comprising the corresponding level,
**   starting with the lhs segment, then each of the rhs segments (if any)
**   in order from most to least recent.
**
**   Each segment element is itself a list of 4 integer values, as follows:
**
**   <ol><li> First page of segment
**       <li> Last page of segment
**       <li> Root page of segment (if applicable)
**       <li> Total number of pages in segment
**   </ol>
**
** LSM_INFO_ARRAY_STRUCTURE:
**   There should be two arguments passed following this option (i.e. a 
**   total of four arguments passed to lsm_info()). The first argument 
**   should be the page number of the first page in a database array 
**   (perhaps obtained from an earlier INFO_DB_STRUCTURE call). The second 
**   trailing argument should be of type (char **). The location pointed 
**   to is populated with a pointer to a nul-terminated string that must 
**   be eventually freed using lsm_free() by the caller.
**
**   The output string contains the text representation of a Tcl list of
**   integers. Each pair of integers represent a range of pages used by
**   the identified array. For example, if the array occupies database
**   pages 993 to 1024, then pages 2048 to 2777, then the returned string
**   will be "993 1024 2048 2777".
**
**   If the specified integer argument does not correspond to the first
**   page of any database array, LSM_ERROR is returned and the output
**   pointer is set to a NULL value.
**
** LSM_INFO_LOG_STRUCTURE:
**   The third argument should be of type (char **). The location pointed
**   to is populated with a pointer to a nul-terminated string containing
**   the string representation of a Tcl data-structure. The returned 
**   string should be eventually freed by the caller using lsm_free().
**
**   The Tcl structure returned is a list of six integers that describe
**   the current structure of the log file.
**
** LSM_INFO_ARRAY_PAGES:
**
** LSM_INFO_PAGE_ASCII_DUMP:
**   As with LSM_INFO_ARRAY_STRUCTURE, there should be two arguments passed
**   with calls that specify this option - an integer page number and a
**   (char **) used to return a nul-terminated string that must be later
**   freed using lsm_free(). In this case the output string is populated
**   with a human-readable description of the page content.
**
**   If the page cannot be decoded, it is not an error. In this case the
**   human-readable output message will report the systems failure to 
**   interpret the page data.
**
** LSM_INFO_PAGE_HEX_DUMP:
**   This argument is similar to PAGE_ASCII_DUMP, except that keys and
**   values are represented using hexadecimal notation instead of ascii.
**
** LSM_INFO_FREELIST:
**   The third argument should be of type (char **). The location pointed
**   to is populated with a pointer to a nul-terminated string containing
**   the string representation of a Tcl data-structure. The returned 
**   string should be eventually freed by the caller using lsm_free().
**
**   The Tcl structure returned is a list containing one element for each
**   free block in the database. The element itself consists of two 
**   integers - the block number and the id of the snapshot that freed it.
**
** LSM_INFO_CHECKPOINT_SIZE:
**   The third argument should be of type (int *). The location pointed to
**   by this argument is populated with the number of KB written to the
**   database file since the most recent checkpoint.
**
** LSM_INFO_TREE_SIZE:
**   If this value is passed as the second argument to an lsm_info() call, it
**   should be followed by two arguments of type (int *) (for a total of four
**   arguments).
**
**   At any time, there are either one or two tree structures held in shared
**   memory that new database clients will access (there may also be additional
**   tree structures being used by older clients - this API does not provide
**   information on them). One tree structure - the current tree - is used to
**   accumulate new data written to the database. The other tree structure -
**   the old tree - is a read-only tree holding older data and may be flushed 
**   to disk at any time.
** 
**   Assuming no error occurs, the location pointed to by the first of the two
**   (int *) arguments is set to the size of the old in-memory tree in KB.
**   The second is set to the size of the current, or live in-memory tree.
**
** LSM_INFO_COMPRESSION_ID:
**   This value should be followed by a single argument of type 
**   (unsigned int *). If successful, the location pointed to is populated 
**   with the database compression id before returning.
*/
#define LSM_INFO_NWRITE           1
#define LSM_INFO_NREAD            2
#define LSM_INFO_DB_STRUCTURE     3
#define LSM_INFO_LOG_STRUCTURE    4
#define LSM_INFO_ARRAY_STRUCTURE  5
#define LSM_INFO_PAGE_ASCII_DUMP  6
#define LSM_INFO_PAGE_HEX_DUMP    7
#define LSM_INFO_FREELIST         8
#define LSM_INFO_ARRAY_PAGES      9
#define LSM_INFO_CHECKPOINT_SIZE 10
#define LSM_INFO_TREE_SIZE       11
#define LSM_INFO_FREELIST_SIZE   12
#define LSM_INFO_COMPRESSION_ID  13


/* 
** CAPI: Opening and Closing Write Transactions
**
** These functions are used to open and close transactions and nested 
** sub-transactions.
**
** The lsm_begin() function is used to open transactions and sub-transactions. 
** A successful call to lsm_begin() ensures that there are at least iLevel 
** nested transactions open. To open a top-level transaction, pass iLevel=1. 
** To open a sub-transaction within the top-level transaction, iLevel=2. 
** Passing iLevel=0 is a no-op.
**
** lsm_commit() is used to commit transactions and sub-transactions. A
** successful call to lsm_commit() ensures that there are at most iLevel 
** nested transactions open. To commit a top-level transaction, pass iLevel=0. 
** To commit all sub-transactions inside the main transaction, pass iLevel=1.
**
** Function lsm_rollback() is used to roll back transactions and
** sub-transactions. A successful call to lsm_rollback() restores the database 
** to the state it was in when the iLevel'th nested sub-transaction (if any) 
** was first opened. And then closes transactions to ensure that there are 
** at most iLevel nested transactions open. Passing iLevel=0 rolls back and 
** closes the top-level transaction. iLevel=1 also rolls back the top-level 
** transaction, but leaves it open. iLevel=2 rolls back the sub-transaction 
** nested directly inside the top-level transaction (and leaves it open).
*/
int lsm_begin(lsm_db *pDb, int iLevel);
int lsm_commit(lsm_db *pDb, int iLevel);
int lsm_rollback(lsm_db *pDb, int iLevel);

/* 
** CAPI: Writing to a Database
**
** Write a new value into the database. If a value with a duplicate key 
** already exists it is replaced.
*/
int lsm_insert(lsm_db*, const void *pKey, int nKey, const void *pVal, int nVal);

/*
** Delete a value from the database. No error is returned if the specified
** key value does not exist in the database.
*/
int lsm_delete(lsm_db *, const void *pKey, int nKey);

/*
** Delete all database entries with keys that are greater than (pKey1/nKey1) 
** and smaller than (pKey2/nKey2). Note that keys (pKey1/nKey1) and
** (pKey2/nKey2) themselves, if they exist in the database, are not deleted.
**
** Return LSM_OK if successful, or an LSM error code otherwise.
*/
int lsm_delete_range(lsm_db *, 
    const void *pKey1, int nKey1, const void *pKey2, int nKey2
);

/*
** CAPI: Explicit Database Work and Checkpointing
**
** This function is called by a thread to work on the database structure.
*/
int lsm_work(lsm_db *pDb, int nMerge, int nKB, int *pnWrite);

int lsm_flush(lsm_db *pDb);

/*
** Attempt to checkpoint the current database snapshot. Return an LSM
** error code if an error occurs or LSM_OK otherwise.
**
** If the current snapshot has already been checkpointed, calling this 
** function is a no-op. In this case if pnKB is not NULL, *pnKB is
** set to 0. Or, if the current snapshot is successfully checkpointed
** by this function and pbKB is not NULL, *pnKB is set to the number
** of bytes written to the database file since the previous checkpoint
** (the same measure as returned by the LSM_INFO_CHECKPOINT_SIZE query).
*/
int lsm_checkpoint(lsm_db *pDb, int *pnKB);

/*
** CAPI: Opening and Closing Database Cursors
**
** Open and close a database cursor.
*/
int lsm_csr_open(lsm_db *pDb, lsm_cursor **ppCsr);
int lsm_csr_close(lsm_cursor *pCsr);

/* 
** CAPI: Positioning Database Cursors
**
** If the fourth parameter is LSM_SEEK_EQ, LSM_SEEK_GE or LSM_SEEK_LE,
** this function searches the database for an entry with key (pKey/nKey). 
** If an error occurs, an LSM error code is returned. Otherwise, LSM_OK.
**
** If no error occurs and the requested key is present in the database, the
** cursor is left pointing to the entry with the specified key. Or, if the 
** specified key is not present in the database the state of the cursor 
** depends on the value passed as the final parameter, as follows:
**
** LSM_SEEK_EQ:
**   The cursor is left at EOF (invalidated). A call to lsm_csr_valid()
**   returns non-zero.
**
** LSM_SEEK_LE:
**   The cursor is left pointing to the largest key in the database that
**   is smaller than (pKey/nKey). If the database contains no keys smaller
**   than (pKey/nKey), the cursor is left at EOF.
**
** LSM_SEEK_GE:
**   The cursor is left pointing to the smallest key in the database that
**   is larger than (pKey/nKey). If the database contains no keys larger
**   than (pKey/nKey), the cursor is left at EOF.
**
** If the fourth parameter is LSM_SEEK_LEFAST, this function searches the
** database in a similar manner to LSM_SEEK_LE, with two differences:
**
** <ol><li>Even if a key can be found (the cursor is not left at EOF), the
** lsm_csr_value() function may not be used (attempts to do so return
** LSM_MISUSE).
**
** <li>The key that the cursor is left pointing to may be one that has 
** been recently deleted from the database. In this case it is
** guaranteed that the returned key is larger than any key currently 
** in the database that is less than or equal to (pKey/nKey).
** </ol>
**
** LSM_SEEK_LEFAST requests are intended to be used to allocate database
** keys.
*/
int lsm_csr_seek(lsm_cursor *pCsr, const void *pKey, int nKey, int eSeek);

int lsm_csr_first(lsm_cursor *pCsr);
int lsm_csr_last(lsm_cursor *pCsr);

/*
** Advance the specified cursor to the next or previous key in the database.
** Return LSM_OK if successful, or an LSM error code otherwise.
**
** Functions lsm_csr_seek(), lsm_csr_first() and lsm_csr_last() are "seek"
** functions. Whether or not lsm_csr_next and lsm_csr_prev may be called
** successfully also depends on the most recent seek function called on
** the cursor. Specifically:
**
** <ul>
** <li> At least one seek function must have been called on the cursor.
** <li> To call lsm_csr_next(), the most recent call to a seek function must
** have been either lsm_csr_first() or a call to lsm_csr_seek() specifying
** LSM_SEEK_GE. 
** <li> To call lsm_csr_prev(), the most recent call to a seek function must
** have been either lsm_csr_first() or a call to lsm_csr_seek() specifying
** LSM_SEEK_GE. 
** </ul>
**
** Otherwise, if the above conditions are not met when lsm_csr_next or 
** lsm_csr_prev is called, LSM_MISUSE is returned and the cursor position
** remains unchanged.
*/
int lsm_csr_next(lsm_cursor *pCsr);
int lsm_csr_prev(lsm_cursor *pCsr);

/*
** Values that may be passed as the fourth argument to lsm_csr_seek().
*/
#define LSM_SEEK_LEFAST   -2
#define LSM_SEEK_LE       -1
#define LSM_SEEK_EQ        0
#define LSM_SEEK_GE        1

/* 
** CAPI: Extracting Data From Database Cursors
**
** Retrieve data from a database cursor.
*/
int lsm_csr_valid(lsm_cursor *pCsr);
int lsm_csr_key(lsm_cursor *pCsr, const void **ppKey, int *pnKey);
int lsm_csr_value(lsm_cursor *pCsr, const void **ppVal, int *pnVal);

/*
** If no error occurs, this function compares the database key passed via
** the pKey/nKey arguments with the key that the cursor passed as the first
** argument currently points to. If the cursors key is less than, equal to
** or greater than pKey/nKey, *piRes is set to less than, equal to or greater
** than zero before returning. LSM_OK is returned in this case.
**
** Or, if an error occurs, an LSM error code is returned and the final 
** value of *piRes is undefined. If the cursor does not point to a valid
** key when this function is called, LSM_MISUSE is returned.
*/
int lsm_csr_cmp(lsm_cursor *pCsr, const void *pKey, int nKey, int *piRes);

/*
** CAPI: Change these!!
**
** Configure a callback to which debugging and other messages should 
** be directed. Only useful for debugging lsm.
*/
void lsm_config_log(lsm_db *, void (*)(void *, int, const char *), void *);

/*
** Configure a callback that is invoked if the database connection ever
** writes to the database file.
*/
void lsm_config_work_hook(lsm_db *, void (*)(lsm_db *, void *), void *);

/* ENDOFAPI */
#if 0
}  /* End of the 'extern "C"' block */
#endif
#endif /* ifndef _LSM_H */

/************** End of lsm.h *************************************************/
/************** Continuing where we left off in lsmInt.h *********************/
/* #include <assert.h> */
/* #include <string.h> */

/* #include <stdarg.h> */
/* #include <stdlib.h> */
/* #include <stdio.h> */
/* #include <ctype.h> */

#include <unistd.h>

#ifdef NDEBUG
# ifdef LSM_DEBUG_EXPENSIVE
#  undef LSM_DEBUG_EXPENSIVE
# endif
# ifdef LSM_DEBUG
#  undef LSM_DEBUG
# endif
#else
# ifndef LSM_DEBUG
#  define LSM_DEBUG
# endif
#endif

/*
** Default values for various data structure parameters. These may be
** overridden by calls to lsm_config().
*/
#define LSM_DFLT_PAGE_SIZE          (4 * 1024)
#define LSM_DFLT_BLOCK_SIZE         (1 * 1024 * 1024)
#define LSM_DFLT_AUTOFLUSH          (1 * 1024 * 1024)
#define LSM_DFLT_AUTOCHECKPOINT     (i64)(2 * 1024 * 1024)
#define LSM_DFLT_AUTOWORK           1
#define LSM_DFLT_LOG_SIZE           (128*1024)
#define LSM_DFLT_AUTOMERGE          4
#define LSM_DFLT_SAFETY             LSM_SAFETY_NORMAL
#define LSM_DFLT_MMAP               (LSM_IS_64_BIT ? 1 : 32768)
#define LSM_DFLT_MULTIPLE_PROCESSES 1
#define LSM_DFLT_USE_LOG            1

/* Initial values for log file checksums. These are only used if the 
** database file does not contain a valid checkpoint.  */
#define LSM_CKSUM0_INIT 42
#define LSM_CKSUM1_INIT 42

#define LSM_META_PAGE_SIZE 4096

/* "mmap" mode is currently only used in environments with 64-bit address 
** spaces. The following macro is used to test for this.  */
#define LSM_IS_64_BIT (sizeof(void*)==8)

#define LSM_AUTOWORK_QUANT 32

typedef struct Database Database;
typedef struct DbLog DbLog;
typedef struct FileSystem FileSystem;
typedef struct Freelist Freelist;
typedef struct FreelistEntry FreelistEntry;
typedef struct Level Level;
typedef struct LogMark LogMark;
typedef struct LogRegion LogRegion;
typedef struct LogWriter LogWriter;
typedef struct LsmString LsmString;
typedef struct Mempool Mempool;
typedef struct Merge Merge;
typedef struct MergeInput MergeInput;
typedef struct MetaPage MetaPage;
typedef struct MultiCursor MultiCursor;
typedef struct Page Page;
typedef struct Redirect Redirect;
typedef struct Segment Segment;
typedef struct SegmentMerger SegmentMerger;
typedef struct ShmChunk ShmChunk;
typedef struct ShmHeader ShmHeader;
typedef struct ShmReader ShmReader;
typedef struct Snapshot Snapshot;
typedef struct TransMark TransMark;
typedef struct Tree Tree;
typedef struct TreeCursor TreeCursor;
typedef struct TreeHeader TreeHeader;
typedef struct TreeMark TreeMark;
typedef struct TreeRoot TreeRoot;

#ifndef _SQLITEINT_H_
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
typedef lsm_i64 i64;
typedef unsigned long long int u64;
#endif

/* A page number is a 64-bit integer. */
typedef i64 Pgno;

#ifdef LSM_DEBUG
int lsmErrorBkpt(int);
#else
# define lsmErrorBkpt(x) (x)
#endif

#define LSM_PROTOCOL_BKPT lsmErrorBkpt(LSM_PROTOCOL)
#define LSM_IOERR_BKPT    lsmErrorBkpt(LSM_IOERR)
#define LSM_NOMEM_BKPT    lsmErrorBkpt(LSM_NOMEM)
#define LSM_CORRUPT_BKPT  lsmErrorBkpt(LSM_CORRUPT)
#define LSM_MISUSE_BKPT   lsmErrorBkpt(LSM_MISUSE)

#define unused_parameter(x) (void)(x)
#define array_size(x) (sizeof(x)/sizeof(x[0]))


/* The size of each shared-memory chunk */
#define LSM_SHM_CHUNK_SIZE (32*1024)

/* The number of bytes reserved at the start of each shm chunk for MM. */
#define LSM_SHM_CHUNK_HDR  (sizeof(ShmChunk))

/* The number of available read locks. */
#define LSM_LOCK_NREADER   6

/* The number of available read-write client locks. */
#define LSM_LOCK_NRWCLIENT   16

/* Lock definitions. 
*/
#define LSM_LOCK_DMS1         1   /* Serialize connect/disconnect ops */
#define LSM_LOCK_DMS2         2   /* Read-write connections */
#define LSM_LOCK_DMS3         3   /* Read-only connections */
#define LSM_LOCK_WRITER       4
#define LSM_LOCK_WORKER       5
#define LSM_LOCK_CHECKPOINTER 6
#define LSM_LOCK_ROTRANS      7
#define LSM_LOCK_READER(i)    ((i) + LSM_LOCK_ROTRANS + 1)
#define LSM_LOCK_RWCLIENT(i)  ((i) + LSM_LOCK_READER(LSM_LOCK_NREADER))

/*
** Hard limit on the number of free-list entries that may be stored in 
** a checkpoint (the remainder are stored as a system record in the LSM).
** See also LSM_CONFIG_MAX_FREELIST.
*/
#define LSM_MAX_FREELIST_ENTRIES 24

#define LSM_MAX_BLOCK_REDIRECTS 16

#define LSM_ATTEMPTS_BEFORE_PROTOCOL 10000


/*
** Each entry stored in the LSM (or in-memory tree structure) has an
** associated mask of the following flags.
*/
#define LSM_START_DELETE 0x01     /* Start of open-ended delete range */
#define LSM_END_DELETE   0x02     /* End of open-ended delete range */
#define LSM_POINT_DELETE 0x04     /* Delete this key */
#define LSM_INSERT       0x08     /* Insert this key and value */
#define LSM_SEPARATOR    0x10     /* True if entry is separator key only */
#define LSM_SYSTEMKEY    0x20     /* True if entry is a system key (FREELIST) */

#define LSM_CONTIGUOUS   0x40     /* Used in lsm_tree.c */

/*
** A string that can grow by appending.
*/
struct LsmString {
  lsm_env *pEnv;              /* Run-time environment */
  int n;                      /* Size of string.  -1 indicates error */
  int nAlloc;                 /* Space allocated for z[] */
  char *z;                    /* The string content */
};

typedef struct LsmFile LsmFile;
struct LsmFile {
  lsm_file *pFile;
  LsmFile *pNext;
};

/*
** An instance of the following type is used to store an ordered list of
** u32 values. 
**
** Note: This is a place-holder implementation. It should be replaced by
** a version that avoids making a single large allocation when the array
** contains a large number of values. For this reason, the internals of 
** this object should only manipulated by the intArrayXXX() functions in 
** lsm_tree.c.
*/
typedef struct IntArray IntArray;
struct IntArray {
  int nAlloc;
  int nArray;
  u32 *aArray;
};

struct Redirect {
  int n;                          /* Number of redirects */
  struct RedirectEntry {
    int iFrom;
    int iTo;
  } *a;
};

/*
** An instance of this structure represents a point in the history of the
** tree structure to roll back to. Refer to comments in lsm_tree.c for 
** details.
*/
struct TreeMark {
  u32 iRoot;                      /* Offset of root node in shm file */
  u32 nHeight;                    /* Current height of tree structure */
  u32 iWrite;                     /* Write offset in shm file */
  u32 nChunk;                     /* Number of chunks in shared-memory file */
  u32 iFirst;                     /* First chunk in linked list */
  u32 iNextShmid;                 /* Next id to allocate */
  int iRollback;                  /* Index in lsm->rollback to revert to */
};

/*
** An instance of this structure represents a point in the database log.
*/
struct LogMark {
  i64 iOff;                       /* Offset into log (see lsm_log.c) */
  int nBuf;                       /* Size of in-memory buffer here */
  u8 aBuf[8];                     /* Bytes of content in aBuf[] */
  u32 cksum0;                     /* Checksum 0 at offset (iOff-nBuf) */
  u32 cksum1;                     /* Checksum 1 at offset (iOff-nBuf) */
};

struct TransMark {
  TreeMark tree;
  LogMark log;
};

/*
** A structure that defines the start and end offsets of a region in the
** log file. The size of the region in bytes is (iEnd - iStart), so if
** iEnd==iStart the region is zero bytes in size.
*/
struct LogRegion {
  i64 iStart;                     /* Start of region in log file */
  i64 iEnd;                       /* End of region in log file */
};

struct DbLog {
  u32 cksum0;                     /* Checksum 0 at offset iOff */
  u32 cksum1;                     /* Checksum 1 at offset iOff */
  i64 iSnapshotId;                /* Log space has been reclaimed to this ss */
  LogRegion aRegion[3];           /* Log file regions (see docs in lsm_log.c) */
};

struct TreeRoot {
  u32 iRoot;
  u32 nHeight;
  u32 nByte;                      /* Total size of this tree in bytes */
  u32 iTransId;
};

/*
** Tree header structure. 
*/
struct TreeHeader {
  u32 iUsedShmid;                 /* Id of first shm chunk used by this tree */
  u32 iNextShmid;                 /* Shm-id of next chunk allocated */
  u32 iFirst;                     /* Chunk number of smallest shm-id */
  u32 nChunk;                     /* Number of chunks in shared-memory file */
  TreeRoot root;                  /* Root and height of current tree */
  u32 iWrite;                     /* Write offset in shm file */
  TreeRoot oldroot;               /* Root and height of the previous tree */
  u32 iOldShmid;                  /* Last shm-id used by previous tree */
  u32 iUsrVersion;                /* get/set_user_version() value */
  i64 iOldLog;                    /* Log offset associated with old tree */
  u32 oldcksum0;
  u32 oldcksum1;
  DbLog log;                      /* Current layout of log file */ 
  u32 aCksum[2];                  /* Checksums 1 and 2. */
};

/*
** Database handle structure.
**
** mLock:
**   A bitmask representing the locks currently held by the connection.
**   An LSM database supports N distinct locks, where N is some number less
**   than or equal to 32. Locks are numbered starting from 1 (see the 
**   definitions for LSM_LOCK_WRITER and co.).
**
**   The least significant 32-bits in mLock represent EXCLUSIVE locks. The
**   most significant are SHARED locks. So, if a connection holds a SHARED
**   lock on lock region iLock, then the following is true:
**
**       (mLock & ((iLock+32-1) << 1))
**
**   Or for an EXCLUSIVE lock:
**
**       (mLock & ((iLock-1) << 1))
** 
** pCsr:
**   Points to the head of a linked list that contains all currently open
**   cursors. Once this list becomes empty, the user has no outstanding
**   cursors and the database handle can be successfully closed.
**
** pCsrCache:
**   This list contains cursor objects that have been closed using
**   lsm_csr_close(). Each time a cursor is closed, it is shifted from 
**   the pCsr list to this list. When a new cursor is opened, this list
**   is inspected to see if there exists a cursor object that can be
**   reused. This is an optimization only.
*/
struct lsm_db {

  /* Database handle configuration */
  lsm_env *pEnv;                            /* runtime environment */
  int (*xCmp)(void *, int, void *, int);    /* Compare function */

  /* Values configured by calls to lsm_config */
  int eSafety;                    /* LSM_SAFETY_OFF, NORMAL or FULL */
  int bAutowork;                  /* Configured by LSM_CONFIG_AUTOWORK */
  int nTreeLimit;                 /* Configured by LSM_CONFIG_AUTOFLUSH */
  int nMerge;                     /* Configured by LSM_CONFIG_AUTOMERGE */
  int bUseLog;                    /* Configured by LSM_CONFIG_USE_LOG */
  int nDfltPgsz;                  /* Configured by LSM_CONFIG_PAGE_SIZE */
  int nDfltBlksz;                 /* Configured by LSM_CONFIG_BLOCK_SIZE */
  int nMaxFreelist;               /* Configured by LSM_CONFIG_MAX_FREELIST */
  int iMmap;                      /* Configured by LSM_CONFIG_MMAP */
  i64 nAutockpt;                  /* Configured by LSM_CONFIG_AUTOCHECKPOINT */
  int bMultiProc;                 /* Configured by L_C_MULTIPLE_PROCESSES */
  int bReadonly;                  /* Configured by LSM_CONFIG_READONLY */
  lsm_compress compress;          /* Compression callbacks */
  lsm_compress_factory factory;   /* Compression callback factory */

  /* Sub-system handles */
  FileSystem *pFS;                /* On-disk portion of database */
  Database *pDatabase;            /* Database shared data */

  int iRwclient;                  /* Read-write client lock held (-1 == none) */

  /* Client transaction context */
  Snapshot *pClient;              /* Client snapshot */
  int iReader;                    /* Read lock held (-1 == unlocked) */
  int bRoTrans;                   /* True if a read-only db trans is open */
  MultiCursor *pCsr;              /* List of all open cursors */
  LogWriter *pLogWriter;          /* Context for writing to the log file */
  int nTransOpen;                 /* Number of opened write transactions */
  int nTransAlloc;                /* Allocated size of aTrans[] array */
  TransMark *aTrans;              /* Array of marks for transaction rollback */
  IntArray rollback;              /* List of tree-nodes to roll back */
  int bDiscardOld;                /* True if lsmTreeDiscardOld() was called */

  MultiCursor *pCsrCache;         /* List of all closed cursors */

  /* Worker context */
  Snapshot *pWorker;              /* Worker snapshot (or NULL) */
  Freelist *pFreelist;            /* See sortedNewToplevel() */
  int bUseFreelist;               /* True to use pFreelist */
  int bIncrMerge;                 /* True if currently doing a merge */

  int bInFactory;                 /* True if within factory.xFactory() */

  /* Debugging message callback */
  void (*xLog)(void *, int, const char *);
  void *pLogCtx;

  /* Work done notification callback */
  void (*xWork)(lsm_db *, void *);
  void *pWorkCtx;

  u64 mLock;                      /* Mask of current locks. See lsmShmLock(). */
  lsm_db *pNext;                  /* Next connection to same database */

  int nShm;                       /* Size of apShm[] array */
  void **apShm;                   /* Shared memory chunks */
  ShmHeader *pShmhdr;             /* Live shared-memory header */
  TreeHeader treehdr;             /* Local copy of tree-header */
  u32 aSnapshot[LSM_META_PAGE_SIZE / sizeof(u32)];
};

struct Segment {
  Pgno iFirst;                     /* First page of this run */
  Pgno iLastPg;                    /* Last page of this run */
  Pgno iRoot;                      /* Root page number (if any) */
  int nSize;                       /* Size of this run in pages */

  Redirect *pRedirect;             /* Block redirects (or NULL) */
};

/*
** iSplitTopic/pSplitKey/nSplitKey:
**   If nRight>0, this buffer contains a copy of the largest key that has
**   already been written to the left-hand-side of the level.
*/
struct Level {
  Segment lhs;                    /* Left-hand (main) segment */
  int nRight;                     /* Size of apRight[] array */
  Segment *aRhs;                  /* Old segments being merged into this */
  int iSplitTopic;                /* Split key topic (if nRight>0) */
  void *pSplitKey;                /* Pointer to split-key (if nRight>0) */
  int nSplitKey;                  /* Number of bytes in split-key */

  u16 iAge;                       /* Number of times data has been written */
  u16 flags;                      /* Mask of LEVEL_XXX bits */
  Merge *pMerge;                  /* Merge operation currently underway */
  Level *pNext;                   /* Next level in tree */
};

/*
** The Level.flags field is set to a combination of the following bits.
**
** LEVEL_FREELIST_ONLY:
**   Set if the level consists entirely of free-list entries. 
**
** LEVEL_INCOMPLETE:
**   This is set while a new toplevel level is being constructed. It is
**   never set for any level other than a new toplevel.
*/
#define LEVEL_FREELIST_ONLY      0x0001
#define LEVEL_INCOMPLETE         0x0002


/*
** A structure describing an ongoing merge. There is an instance of this
** structure for every Level currently undergoing a merge in the worker
** snapshot.
**
** It is assumed that code that uses an instance of this structure has
** access to the associated Level struct.
**
** iOutputOff:
**   The byte offset to write to next within the last page of the 
**   output segment.
*/
struct MergeInput {
  Pgno iPg;                       /* Page on which next input is stored */
  int iCell;                      /* Cell containing next input to merge */
};
struct Merge {
  int nInput;                     /* Number of input runs being merged */
  MergeInput *aInput;             /* Array nInput entries in size */
  MergeInput splitkey;            /* Location in file of current splitkey */
  int nSkip;                      /* Number of separators entries to skip */
  int iOutputOff;                 /* Write offset on output page */
  Pgno iCurrentPtr;               /* Current pointer value */
};

/* 
** The first argument to this macro is a pointer to a Segment structure.
** Returns true if the structure instance indicates that the separators
** array is valid.
*/
#define segmentHasSeparators(pSegment) ((pSegment)->sep.iFirst>0)

/*
** The values that accompany the lock held by a database reader.
*/
struct ShmReader {
  u32 iTreeId;
  i64 iLsmId;
};

/*
** An instance of this structure is stored in the first shared-memory
** page. The shared-memory header.
**
** bWriter:
**   Immediately after opening a write transaction taking the WRITER lock, 
**   each writer client sets this flag. It is cleared right before the 
**   WRITER lock is relinquished. If a subsequent writer finds that this
**   flag is already set when a write transaction is opened, this indicates
**   that a previous writer failed mid-transaction.
**
** iMetaPage:
**   If the database file does not contain a valid, synced, checkpoint, this
**   value is set to 0. Otherwise, it is set to the meta-page number that
**   contains the most recently written checkpoint (either 1 or 2).
**
** hdr1, hdr2:
**   The two copies of the in-memory tree header. Two copies are required
**   in case a writer fails while updating one of them.
*/
struct ShmHeader {
  u32 aSnap1[LSM_META_PAGE_SIZE / 4];
  u32 aSnap2[LSM_META_PAGE_SIZE / 4];
  u32 bWriter;
  u32 iMetaPage;
  TreeHeader hdr1;
  TreeHeader hdr2;
  ShmReader aReader[LSM_LOCK_NREADER];
};

/*
** An instance of this structure is stored at the start of each shared-memory
** chunk except the first (which is the header chunk - see above).
*/
struct ShmChunk {
  u32 iShmid;
  u32 iNext;
};

/*
** Maximum number of shared-memory chunks allowed in the *-shm file. Since
** each shared-memory chunk is 32KB in size, this is a theoretical limit only.
*/
#define LSM_MAX_SHMCHUNKS  (1<<30)

/* Return true if shm-sequence "a" is larger than or equal to "b" */
#define shm_sequence_ge(a, b) (((u32)a-(u32)b) < LSM_MAX_SHMCHUNKS)

#define LSM_APPLIST_SZ 4

/*
** An instance of the following structure stores the in-memory part of
** the current free block list. This structure is to the free block list
** as the in-memory tree is to the users database content. The contents 
** of the free block list is found by merging the in-memory components 
** with those stored in the LSM, just as the contents of the database is
** found by merging the in-memory tree with the user data entries in the
** LSM.
**
** Each FreelistEntry structure in the array represents either an insert
** or delete operation on the free-list. For deletes, the FreelistEntry.iId
** field is set to -1. For inserts, it is set to zero or greater. 
**
** The array of FreelistEntry structures is always sorted in order of
** block number (ascending).
**
** When the in-memory free block list is written into the LSM, each insert
** operation is written separately. The entry key is the bitwise inverse
** of the block number as a 32-bit big-endian integer. This is done so that
** the entries in the LSM are sorted in descending order of block id. 
** The associated value is the snapshot id, formated as a varint.
*/
struct Freelist {
  FreelistEntry *aEntry;          /* Free list entries */
  int nEntry;                     /* Number of valid slots in aEntry[] */
  int nAlloc;                     /* Allocated size of aEntry[] */
};
struct FreelistEntry {
  u32 iBlk;                       /* Block number */
  i64 iId;                        /* Largest snapshot id to use this block */
};

/*
** A snapshot of a database. A snapshot contains all the information required
** to read or write a database file on disk. See the description of struct
** Database below for futher details.
*/
struct Snapshot {
  Database *pDatabase;            /* Database this snapshot belongs to */
  u32 iCmpId;                     /* Id of compression scheme */
  Level *pLevel;                  /* Pointer to level 0 of snapshot (or NULL) */
  i64 iId;                        /* Snapshot id */
  i64 iLogOff;                    /* Log file offset */
  Redirect redirect;              /* Block redirection array */

  /* Used by worker snapshots only */
  int nBlock;                     /* Number of blocks in database file */
  Pgno aiAppend[LSM_APPLIST_SZ];  /* Append point list */
  Freelist freelist;              /* Free block list */
  u32 nWrite;                     /* Total number of pages written to disk */
};
#define LSM_INITIAL_SNAPSHOT_ID 11

/*
** Functions from file "lsm_ckpt.c".
*/
int lsmCheckpointWrite(lsm_db *, int, u32 *);
int lsmCheckpointLevels(lsm_db *, int, void **, int *);
int lsmCheckpointLoadLevels(lsm_db *pDb, void *pVal, int nVal);

int lsmCheckpointRecover(lsm_db *);
int lsmCheckpointDeserialize(lsm_db *, int, u32 *, Snapshot **);

int lsmCheckpointLoadWorker(lsm_db *pDb);
int lsmCheckpointStore(lsm_db *pDb, int);

int lsmCheckpointLoad(lsm_db *pDb, int *);
int lsmCheckpointLoadOk(lsm_db *pDb, int);
int lsmCheckpointClientCacheOk(lsm_db *);

u32 lsmCheckpointNBlock(u32 *);
i64 lsmCheckpointId(u32 *, int);
u32 lsmCheckpointNWrite(u32 *, int);
i64 lsmCheckpointLogOffset(u32 *);
int lsmCheckpointPgsz(u32 *);
int lsmCheckpointBlksz(u32 *);
void lsmCheckpointLogoffset(u32 *aCkpt, DbLog *pLog);
void lsmCheckpointZeroLogoffset(lsm_db *);

int lsmCheckpointSaveWorker(lsm_db *pDb, int);
int lsmDatabaseFull(lsm_db *pDb);
int lsmCheckpointSynced(lsm_db *pDb, i64 *piId, i64 *piLog, u32 *pnWrite);

int lsmCheckpointSize(lsm_db *db, int *pnByte);

int lsmInfoCompressionId(lsm_db *db, u32 *piCmpId);

/* 
** Functions from file "lsm_tree.c".
*/
int lsmTreeNew(lsm_env *, int (*)(void *, int, void *, int), Tree **ppTree);
void lsmTreeRelease(lsm_env *, Tree *);
int lsmTreeInit(lsm_db *);
int lsmTreeRepair(lsm_db *);

void lsmTreeMakeOld(lsm_db *pDb);
void lsmTreeDiscardOld(lsm_db *pDb);
int lsmTreeHasOld(lsm_db *pDb);

int lsmTreeSize(lsm_db *);
int lsmTreeEndTransaction(lsm_db *pDb, int bCommit);
int lsmTreeLoadHeader(lsm_db *pDb, int *);
int lsmTreeLoadHeaderOk(lsm_db *, int);

int lsmTreeInsert(lsm_db *pDb, void *pKey, int nKey, void *pVal, int nVal);
int lsmTreeDelete(lsm_db *db, void *pKey1, int nKey1, void *pKey2, int nKey2);
void lsmTreeRollback(lsm_db *pDb, TreeMark *pMark);
void lsmTreeMark(lsm_db *pDb, TreeMark *pMark);

int lsmTreeCursorNew(lsm_db *pDb, int, TreeCursor **);
void lsmTreeCursorDestroy(TreeCursor *);

int lsmTreeCursorSeek(TreeCursor *pCsr, void *pKey, int nKey, int *pRes);
int lsmTreeCursorNext(TreeCursor *pCsr);
int lsmTreeCursorPrev(TreeCursor *pCsr);
int lsmTreeCursorEnd(TreeCursor *pCsr, int bLast);
void lsmTreeCursorReset(TreeCursor *pCsr);
int lsmTreeCursorKey(TreeCursor *pCsr, int *pFlags, void **ppKey, int *pnKey);
int lsmTreeCursorFlags(TreeCursor *pCsr);
int lsmTreeCursorValue(TreeCursor *pCsr, void **ppVal, int *pnVal);
int lsmTreeCursorValid(TreeCursor *pCsr);
int lsmTreeCursorSave(TreeCursor *pCsr);

void lsmFlagsToString(int flags, char *zFlags);

/* 
** Functions from file "mem.c".
*/
void *lsmMalloc(lsm_env*, size_t);
void lsmFree(lsm_env*, void *);
void *lsmRealloc(lsm_env*, void *, size_t);
void *lsmReallocOrFree(lsm_env*, void *, size_t);
void *lsmReallocOrFreeRc(lsm_env *, void *, size_t, int *);

void *lsmMallocZeroRc(lsm_env*, size_t, int *);
void *lsmMallocRc(lsm_env*, size_t, int *);

void *lsmMallocZero(lsm_env *pEnv, size_t);
char *lsmMallocStrdup(lsm_env *pEnv, const char *);

/* 
** Functions from file "lsm_mutex.c".
*/
int lsmMutexStatic(lsm_env*, int, lsm_mutex **);
int lsmMutexNew(lsm_env*, lsm_mutex **);
void lsmMutexDel(lsm_env*, lsm_mutex *);
void lsmMutexEnter(lsm_env*, lsm_mutex *);
int lsmMutexTry(lsm_env*, lsm_mutex *);
void lsmMutexLeave(lsm_env*, lsm_mutex *);

#ifndef NDEBUG
int lsmMutexHeld(lsm_env *, lsm_mutex *);
int lsmMutexNotHeld(lsm_env *, lsm_mutex *);
#endif

/**************************************************************************
** Start of functions from "lsm_file.c".
*/
int lsmFsOpen(lsm_db *, const char *, int);
int lsmFsOpenLog(lsm_db *, int *);
void lsmFsCloseLog(lsm_db *);
void lsmFsClose(FileSystem *);

int lsmFsConfigure(lsm_db *db);

int lsmFsBlockSize(FileSystem *);
void lsmFsSetBlockSize(FileSystem *, int);

int lsmFsPageSize(FileSystem *);
void lsmFsSetPageSize(FileSystem *, int);

int lsmFsFileid(lsm_db *pDb, void **ppId, int *pnId);

/* Creating, populating, gobbling and deleting sorted runs. */
void lsmFsGobble(lsm_db *, Segment *, Pgno *, int);
int lsmFsSortedDelete(FileSystem *, Snapshot *, int, Segment *);
int lsmFsSortedFinish(FileSystem *, Segment *);
int lsmFsSortedAppend(FileSystem *, Snapshot *, Level *, int, Page **);
int lsmFsSortedPadding(FileSystem *, Snapshot *, Segment *);

/* Functions to retrieve the lsm_env pointer from a FileSystem or Page object */
lsm_env *lsmFsEnv(FileSystem *);
lsm_env *lsmPageEnv(Page *);
FileSystem *lsmPageFS(Page *);

int lsmFsSectorSize(FileSystem *);

void lsmSortedSplitkey(lsm_db *, Level *, int *);

/* Reading sorted run content. */
int lsmFsDbPageLast(FileSystem *pFS, Segment *pSeg, Page **ppPg);
int lsmFsDbPageGet(FileSystem *, Segment *, Pgno, Page **);
int lsmFsDbPageNext(Segment *, Page *, int eDir, Page **);

u8 *lsmFsPageData(Page *, int *);
int lsmFsPageRelease(Page *);
int lsmFsPagePersist(Page *);
void lsmFsPageRef(Page *);
Pgno lsmFsPageNumber(Page *);

int lsmFsNRead(FileSystem *);
int lsmFsNWrite(FileSystem *);

int lsmFsMetaPageGet(FileSystem *, int, int, MetaPage **);
int lsmFsMetaPageRelease(MetaPage *);
u8 *lsmFsMetaPageData(MetaPage *, int *);

#ifdef LSM_DEBUG
int lsmFsDbPageIsLast(Segment *pSeg, Page *pPg);
int lsmFsIntegrityCheck(lsm_db *);
#endif

Pgno lsmFsRedirectPage(FileSystem *, Redirect *, Pgno);

int lsmFsPageWritable(Page *);

/* Functions to read, write and sync the log file. */
int lsmFsWriteLog(FileSystem *pFS, i64 iOff, LsmString *pStr);
int lsmFsSyncLog(FileSystem *pFS);
int lsmFsReadLog(FileSystem *pFS, i64 iOff, int nRead, LsmString *pStr);
int lsmFsTruncateLog(FileSystem *pFS, i64 nByte);
int lsmFsTruncateDb(FileSystem *pFS, i64 nByte);
int lsmFsCloseAndDeleteLog(FileSystem *pFS);

LsmFile *lsmFsDeferClose(FileSystem *pFS);

/* And to sync the db file */
int lsmFsSyncDb(FileSystem *, int);

void lsmFsFlushWaiting(FileSystem *, int *);

/* Used by lsm_info(ARRAY_STRUCTURE) and lsm_config(MMAP) */
int lsmInfoArrayStructure(lsm_db *pDb, int bBlock, Pgno iFirst, char **pzOut);
int lsmInfoArrayPages(lsm_db *pDb, Pgno iFirst, char **pzOut);
int lsmConfigMmap(lsm_db *pDb, int *piParam);

int lsmEnvOpen(lsm_env *, const char *, int, lsm_file **);
int lsmEnvClose(lsm_env *pEnv, lsm_file *pFile);
int lsmEnvLock(lsm_env *pEnv, lsm_file *pFile, int iLock, int eLock);
int lsmEnvTestLock(lsm_env *pEnv, lsm_file *pFile, int iLock, int nLock, int);

int lsmEnvShmMap(lsm_env *, lsm_file *, int, int, void **); 
void lsmEnvShmBarrier(lsm_env *);
void lsmEnvShmUnmap(lsm_env *, lsm_file *, int);

void lsmEnvSleep(lsm_env *, int);

int lsmFsReadSyncedId(lsm_db *db, int, i64 *piVal);

int lsmFsSegmentContainsPg(FileSystem *pFS, Segment *, Pgno, int *);

void lsmFsPurgeCache(FileSystem *);

/*
** End of functions from "lsm_file.c".
**************************************************************************/

/* 
** Functions from file "lsm_sorted.c".
*/
int lsmInfoPageDump(lsm_db *, Pgno, int, char **);
void lsmSortedCleanup(lsm_db *);
int lsmSortedAutoWork(lsm_db *, int nUnit);

int lsmSortedWalkFreelist(lsm_db *, int, int (*)(void *, int, i64), void *);

int lsmSaveWorker(lsm_db *, int);

int lsmFlushTreeToDisk(lsm_db *pDb);

void lsmSortedRemap(lsm_db *pDb);

void lsmSortedFreeLevel(lsm_env *pEnv, Level *);

int lsmSortedAdvanceAll(lsm_db *pDb);

int lsmSortedLoadMerge(lsm_db *, Level *, u32 *, int *);
int lsmSortedLoadFreelist(lsm_db *pDb, void **, int *);

void *lsmSortedSplitKey(Level *pLevel, int *pnByte);

void lsmSortedSaveTreeCursors(lsm_db *);

int lsmMCursorNew(lsm_db *, MultiCursor **);
void lsmMCursorClose(MultiCursor *, int);
int lsmMCursorSeek(MultiCursor *, int, void *, int , int);
int lsmMCursorFirst(MultiCursor *);
int lsmMCursorPrev(MultiCursor *);
int lsmMCursorLast(MultiCursor *);
int lsmMCursorValid(MultiCursor *);
int lsmMCursorNext(MultiCursor *);
int lsmMCursorKey(MultiCursor *, void **, int *);
int lsmMCursorValue(MultiCursor *, void **, int *);
int lsmMCursorType(MultiCursor *, int *);
lsm_db *lsmMCursorDb(MultiCursor *);
void lsmMCursorFreeCache(lsm_db *);

int lsmSaveCursors(lsm_db *pDb);
int lsmRestoreCursors(lsm_db *pDb);

void lsmSortedDumpStructure(lsm_db *pDb, Snapshot *, int, int, const char *);
void lsmFsDumpBlocklists(lsm_db *);

void lsmSortedExpandBtreePage(Page *pPg, int nOrig);

void lsmPutU32(u8 *, u32);
u32 lsmGetU32(u8 *);
u64 lsmGetU64(u8 *);

/*
** Functions from "lsm_varint.c".
*/
int lsmVarintPut32(u8 *, int);
int lsmVarintGet32(u8 *, int *);
int lsmVarintPut64(u8 *aData, i64 iVal);
int lsmVarintGet64(const u8 *aData, i64 *piVal);

int lsmVarintLen32(int);
int lsmVarintSize(u8 c);

/* 
** Functions from file "main.c".
*/
void lsmLogMessage(lsm_db *, int, const char *, ...);
int lsmInfoFreelist(lsm_db *pDb, char **pzOut);

/*
** Functions from file "lsm_log.c".
*/
int lsmLogBegin(lsm_db *pDb);
int lsmLogWrite(lsm_db *, void *, int, void *, int);
int lsmLogCommit(lsm_db *);
void lsmLogEnd(lsm_db *pDb, int bCommit);
void lsmLogTell(lsm_db *, LogMark *);
void lsmLogSeek(lsm_db *, LogMark *);
void lsmLogClose(lsm_db *);

int lsmLogRecover(lsm_db *);
int lsmInfoLogStructure(lsm_db *pDb, char **pzVal);


/**************************************************************************
** Functions from file "lsm_shared.c".
*/

int lsmDbDatabaseConnect(lsm_db*, const char *);
void lsmDbDatabaseRelease(lsm_db *);

int lsmBeginReadTrans(lsm_db *);
int lsmBeginWriteTrans(lsm_db *);
int lsmBeginFlush(lsm_db *);

int lsmDetectRoTrans(lsm_db *db, int *);
int lsmBeginRoTrans(lsm_db *db);

int lsmBeginWork(lsm_db *);
void lsmFinishWork(lsm_db *, int, int *);

int lsmFinishRecovery(lsm_db *);
void lsmFinishReadTrans(lsm_db *);
int lsmFinishWriteTrans(lsm_db *, int);
int lsmFinishFlush(lsm_db *, int);

int lsmSnapshotSetFreelist(lsm_db *, int *, int);

Snapshot *lsmDbSnapshotClient(lsm_db *);
Snapshot *lsmDbSnapshotWorker(lsm_db *);

void lsmSnapshotSetCkptid(Snapshot *, i64);

Level *lsmDbSnapshotLevel(Snapshot *);
void lsmDbSnapshotSetLevel(Snapshot *, Level *);

void lsmDbRecoveryComplete(lsm_db *, int);

int lsmBlockAllocate(lsm_db *, int, int *);
int lsmBlockFree(lsm_db *, int);
int lsmBlockRefree(lsm_db *, int);

void lsmFreelistDeltaBegin(lsm_db *);
void lsmFreelistDeltaEnd(lsm_db *);
int lsmFreelistDelta(lsm_db *pDb);

DbLog *lsmDatabaseLog(lsm_db *pDb);

#ifdef LSM_DEBUG
  int lsmHoldingClientMutex(lsm_db *pDb);
  int lsmShmAssertLock(lsm_db *db, int iLock, int eOp);
  int lsmShmAssertWorker(lsm_db *db);
#endif

void lsmFreeSnapshot(lsm_env *, Snapshot *);


/* Candidate values for the 3rd argument to lsmShmLock() */
#define LSM_LOCK_UNLOCK 0
#define LSM_LOCK_SHARED 1
#define LSM_LOCK_EXCL   2

int lsmShmCacheChunks(lsm_db *db, int nChunk);
int lsmShmLock(lsm_db *db, int iLock, int eOp, int bBlock);
int lsmShmTestLock(lsm_db *db, int iLock, int nLock, int eOp);
void lsmShmBarrier(lsm_db *db);

#ifdef LSM_DEBUG
void lsmShmHasLock(lsm_db *db, int iLock, int eOp);
#else
# define lsmShmHasLock(x,y,z)
#endif

int lsmReadlock(lsm_db *, i64 iLsm, u32 iShmMin, u32 iShmMax);

int lsmLsmInUse(lsm_db *db, i64 iLsmId, int *pbInUse);
int lsmTreeInUse(lsm_db *db, u32 iLsmId, int *pbInUse);
int lsmFreelistAppend(lsm_env *pEnv, Freelist *p, int iBlk, i64 iId);

int lsmDbMultiProc(lsm_db *);
void lsmDbDeferredClose(lsm_db *, lsm_file *, LsmFile *);
LsmFile *lsmDbRecycleFd(lsm_db *);

int lsmWalkFreelist(lsm_db *, int, int (*)(void *, int, i64), void *);

int lsmCheckCompressionId(lsm_db *, u32);


/**************************************************************************
** functions in lsm_str.c
*/
void lsmStringInit(LsmString*, lsm_env *pEnv);
int lsmStringExtend(LsmString*, int);
int lsmStringAppend(LsmString*, const char *, int);
void lsmStringVAppendf(LsmString*, const char *zFormat, va_list, va_list);
void lsmStringAppendf(LsmString*, const char *zFormat, ...);
void lsmStringClear(LsmString*);
char *lsmMallocPrintf(lsm_env*, const char*, ...);
int lsmStringBinAppend(LsmString *pStr, const u8 *a, int n);

int lsmStrlen(const char *zName);



/* 
** Round up a number to the next larger multiple of 8.  This is used
** to force 8-byte alignment on 64-bit architectures.
*/
#define ROUND8(x)     (((x)+7)&~7)

#define LSM_MIN(x,y) ((x)>(y) ? (y) : (x))
#define LSM_MAX(x,y) ((x)>(y) ? (x) : (y))

#endif

/************** End of lsmInt.h **********************************************/
/************** Continuing where we left off in lsm_ckpt.c *******************/

/*
** CHECKPOINT BLOB FORMAT:
**
** A checkpoint blob is a series of unsigned 32-bit integers stored in
** big-endian byte order. As follows:
**
**   Checkpoint header (see the CKPT_HDR_XXX #defines):
**
**     1. The checkpoint id MSW.
**     2. The checkpoint id LSW.
**     3. The number of integer values in the entire checkpoint, including 
**        the two checksum values.
**     4. The compression scheme id.
**     5. The total number of blocks in the database.
**     6. The block size.
**     7. The number of levels.
**     8. The nominal database page size.
**     9. The number of pages (in total) written to the database file.
**
**   Log pointer:
**
**     1. The log offset MSW.
**     2. The log offset LSW.
**     3. Log checksum 0.
**     4. Log checksum 1.
**
**     Note that the "log offset" is not the literal byte offset. Instead,
**     it is the byte offset multiplied by 2, with least significant bit
**     toggled each time the log pointer value is changed. This is to make
**     sure that this field changes each time the log pointer is updated,
**     even if the log file itself is disabled. See lsmTreeMakeOld().
**
**     See ckptExportLog() and ckptImportLog().
**
**   Append points:
**
**     8 integers (4 * 64-bit page numbers). See ckptExportAppendlist().
**
**   For each level in the database, a level record. Formatted as follows:
**
**     0. Age of the level (least significant 16-bits). And flags mask (most
**        significant 16-bits).
**     1. The number of right-hand segments (nRight, possibly 0),
**     2. Segment record for left-hand segment (8 integers defined below),
**     3. Segment record for each right-hand segment (8 integers defined below),
**     4. If nRight>0, The number of segments involved in the merge
**     5. if nRight>0, Current nSkip value (see Merge structure defn.),
**     6. For each segment in the merge:
**        5a. Page number of next cell to read during merge (this field
**            is 64-bits - 2 integers)
**        5b. Cell number of next cell to read during merge
**     7. Page containing current split-key (64-bits - 2 integers).
**     8. Cell within page containing current split-key.
**     9. Current pointer value (64-bits - 2 integers).
**
**   The block redirect array:
**
**     1. Number of redirections (maximum LSM_MAX_BLOCK_REDIRECTS).
**     2. For each redirection:
**        a. "from" block number
**        b. "to" block number
**
**   The in-memory freelist entries. Each entry is either an insert or a
**   delete. The in-memory freelist is to the free-block-list as the
**   in-memory tree is to the users database content.
**
**     1. Number of free-list entries stored in checkpoint header.
**     2. Number of free blocks (in total).
**     3. Total number of blocks freed during database lifetime.
**     4. For each entry:
**        2a. Block number of free block.
**        2b. A 64-bit integer (MSW followed by LSW). -1 for a delete entry,
**            or the associated checkpoint id for an insert.
**
**   The checksum:
**
**     1. Checksum value 1.
**     2. Checksum value 2.
**
** In the above, a segment record consists of the following four 64-bit 
** fields (converted to 2 * u32 by storing the MSW followed by LSW):
**
**     1. First page of array,
**     2. Last page of array,
**     3. Root page of array (or 0),
**     4. Size of array in pages.
*/

/*
** LARGE NUMBERS OF LEVEL RECORDS:
**
** A limit on the number of rhs segments that may be present in the database
** file. Defining this limit ensures that all level records fit within
** the 4096 byte limit for checkpoint blobs.
**
** The number of right-hand-side segments in a database is counted as 
** follows:
**
**   * For each level in the database not undergoing a merge, add 1.
**
**   * For each level in the database that is undergoing a merge, add 
**     the number of segments on the rhs of the level.
**
** A level record not undergoing a merge is 10 integers. A level record 
** with nRhs rhs segments and (nRhs+1) input segments (i.e. including the 
** separators from the next level) is (11*nRhs+20) integers. The maximum
** per right-hand-side level is therefore 21 integers. So the maximum
** size of all level records in a checkpoint is 21*40=820 integers.
**
** TODO: Before pointer values were changed from 32 to 64 bits, the above
** used to come to 420 bytes - leaving significant space for a free-list
** prefix. No more. To fix this, reduce the size of the level records in
** a db snapshot, and improve management of the free-list tail in 
** lsm_sorted.c. 
*/
#define LSM_MAX_RHS_SEGMENTS 40

/*
** LARGE NUMBERS OF FREELIST ENTRIES:
**
** There is also a limit (LSM_MAX_FREELIST_ENTRIES - defined in lsmInt.h)
** on the number of free-list entries stored in a checkpoint. Since each 
** free-list entry consists of 3 integers, the maximum free-list size is 
** 3*100=300 integers. Combined with the limit on rhs segments defined
** above, this ensures that a checkpoint always fits within a 4096 byte
** meta page.
**
** If the database contains more than 100 free blocks, the "overflow" flag
** in the checkpoint header is set and the remainder are stored in the
** system FREELIST entry in the LSM (along with user data). The value
** accompanying the FREELIST key in the LSM is, like a checkpoint, an array
** of 32-bit big-endian integers. As follows:
**
**     For each entry:
**       a. Block number of free block.
**       b. MSW of associated checkpoint id.
**       c. LSW of associated checkpoint id.
**
** The number of entries is not required - it is implied by the size of the
** value blob containing the integer array.
**
** Note that the limit defined by LSM_MAX_FREELIST_ENTRIES is a hard limit.
** The actual value used may be configured using LSM_CONFIG_MAX_FREELIST.
*/

/*
** The argument to this macro must be of type u32. On a little-endian
** architecture, it returns the u32 value that results from interpreting
** the 4 bytes as a big-endian value. On a big-endian architecture, it
** returns the value that would be produced by intepreting the 4 bytes
** of the input value as a little-endian integer.
*/
#define BYTESWAP32(x) ( \
   (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)  \
 + (((x)&0x00FF0000)>>8)  + (((x)&0xFF000000)>>24) \
)

static const int one = 1;
#define LSM_LITTLE_ENDIAN (*(u8 *)(&one))

/* Sizes, in integers, of various parts of the checkpoint. */
#define CKPT_HDR_SIZE         9
#define CKPT_LOGPTR_SIZE      4
#define CKPT_APPENDLIST_SIZE  (LSM_APPLIST_SZ * 2)

/* A #define to describe each integer in the checkpoint header. */
#define CKPT_HDR_ID_MSW   0
#define CKPT_HDR_ID_LSW   1
#define CKPT_HDR_NCKPT    2
#define CKPT_HDR_CMPID    3
#define CKPT_HDR_NBLOCK   4
#define CKPT_HDR_BLKSZ    5
#define CKPT_HDR_NLEVEL   6
#define CKPT_HDR_PGSZ     7
#define CKPT_HDR_NWRITE   8

#define CKPT_HDR_LO_MSW     9
#define CKPT_HDR_LO_LSW    10
#define CKPT_HDR_LO_CKSUM1 11
#define CKPT_HDR_LO_CKSUM2 12

typedef struct CkptBuffer CkptBuffer;

/*
** Dynamic buffer used to accumulate data for a checkpoint.
*/
struct CkptBuffer {
  lsm_env *pEnv;
  int nAlloc;
  u32 *aCkpt;
};

/*
** Calculate the checksum of the checkpoint specified by arguments aCkpt and
** nCkpt. Store the checksum in *piCksum1 and *piCksum2 before returning.
**
** The value of the nCkpt parameter includes the two checksum values at
** the end of the checkpoint. They are not used as inputs to the checksum 
** calculation. The checksum is based on the array of (nCkpt-2) integers
** at aCkpt[].
*/
static void ckptChecksum(u32 *aCkpt, u32 nCkpt, u32 *piCksum1, u32 *piCksum2){
  int i;
  u32 cksum1 = 1;
  u32 cksum2 = 2;

  if( nCkpt % 2 ){
    cksum1 += aCkpt[nCkpt-3] & 0x0000FFFF;
    cksum2 += aCkpt[nCkpt-3] & 0xFFFF0000;
  }

  for(i=0; (i+3)<nCkpt; i+=2){
    cksum1 += cksum2 + aCkpt[i];
    cksum2 += cksum1 + aCkpt[i+1];
  }

  *piCksum1 = cksum1;
  *piCksum2 = cksum2;
}

/*
** Set integer iIdx of the checkpoint accumulating in buffer *p to iVal.
*/
static void ckptSetValue(CkptBuffer *p, int iIdx, u32 iVal, int *pRc){
  if( *pRc ) return;
  if( iIdx>=p->nAlloc ){
    int nNew = LSM_MAX(8, iIdx*2);
    p->aCkpt = (u32 *)lsmReallocOrFree(p->pEnv, p->aCkpt, nNew*sizeof(u32));
    if( !p->aCkpt ){
      *pRc = LSM_NOMEM_BKPT;
      return;
    }
    p->nAlloc = nNew;
  }
  p->aCkpt[iIdx] = iVal;
}

/*
** Argument aInt points to an array nInt elements in size. Switch the 
** endian-ness of each element of the array.
*/
static void ckptChangeEndianness(u32 *aInt, int nInt){
  if( LSM_LITTLE_ENDIAN ){
    int i;
    for(i=0; i<nInt; i++) aInt[i] = BYTESWAP32(aInt[i]);
  }
}

/*
** Object *p contains a checkpoint in native byte-order. The checkpoint is
** nCkpt integers in size, not including any checksum. This function sets
** the two checksum elements of the checkpoint accordingly.
*/
static void ckptAddChecksum(CkptBuffer *p, int nCkpt, int *pRc){
  if( *pRc==LSM_OK ){
    u32 aCksum[2] = {0, 0};
    ckptChecksum(p->aCkpt, nCkpt+2, &aCksum[0], &aCksum[1]);
    ckptSetValue(p, nCkpt, aCksum[0], pRc);
    ckptSetValue(p, nCkpt+1, aCksum[1], pRc);
  }
}

static void ckptAppend64(CkptBuffer *p, int *piOut, i64 iVal, int *pRc){
  int iOut = *piOut;
  ckptSetValue(p, iOut++, (iVal >> 32) & 0xFFFFFFFF, pRc);
  ckptSetValue(p, iOut++, (iVal & 0xFFFFFFFF), pRc);
  *piOut = iOut;
}

static i64 ckptRead64(u32 *a){
  return (((i64)a[0]) << 32) + (i64)a[1];
}

static i64 ckptGobble64(u32 *a, int *piIn){
  int iIn = *piIn;
  *piIn += 2;
  return ckptRead64(&a[iIn]);
}


/*
** Append a 6-value segment record corresponding to pSeg to the checkpoint 
** buffer passed as the third argument.
*/
static void ckptExportSegment(
  Segment *pSeg, 
  CkptBuffer *p, 
  int *piOut, 
  int *pRc
){
  ckptAppend64(p, piOut, pSeg->iFirst, pRc);
  ckptAppend64(p, piOut, pSeg->iLastPg, pRc);
  ckptAppend64(p, piOut, pSeg->iRoot, pRc);
  ckptAppend64(p, piOut, pSeg->nSize, pRc);
}

static void ckptExportLevel(
  Level *pLevel,                  /* Level object to serialize */
  CkptBuffer *p,                  /* Append new level record to this ckpt */
  int *piOut,                     /* IN/OUT: Size of checkpoint so far */
  int *pRc                        /* IN/OUT: Error code */
){
  int iOut = *piOut;
  Merge *pMerge;

  pMerge = pLevel->pMerge;
  ckptSetValue(p, iOut++, (u32)pLevel->iAge + (u32)(pLevel->flags<<16), pRc);
  ckptSetValue(p, iOut++, pLevel->nRight, pRc);
  ckptExportSegment(&pLevel->lhs, p, &iOut, pRc);

  assert( (pLevel->nRight>0)==(pMerge!=0) );
  if( pMerge ){
    int i;
    for(i=0; i<pLevel->nRight; i++){
      ckptExportSegment(&pLevel->aRhs[i], p, &iOut, pRc);
    }
    assert( pMerge->nInput==pLevel->nRight 
         || pMerge->nInput==pLevel->nRight+1 
    );
    ckptSetValue(p, iOut++, pMerge->nInput, pRc);
    ckptSetValue(p, iOut++, pMerge->nSkip, pRc);
    for(i=0; i<pMerge->nInput; i++){
      ckptAppend64(p, &iOut, pMerge->aInput[i].iPg, pRc);
      ckptSetValue(p, iOut++, pMerge->aInput[i].iCell, pRc);
    }
    ckptAppend64(p, &iOut, pMerge->splitkey.iPg, pRc);
    ckptSetValue(p, iOut++, pMerge->splitkey.iCell, pRc);
    ckptAppend64(p, &iOut, pMerge->iCurrentPtr, pRc);
  }

  *piOut = iOut;
}

/*
** Populate the log offset fields of the checkpoint buffer. 4 values.
*/
static void ckptExportLog(
  lsm_db *pDb, 
  int bFlush,
  CkptBuffer *p, 
  int *piOut, 
  int *pRc
){
  int iOut = *piOut;

  assert( iOut==CKPT_HDR_LO_MSW );

  if( bFlush ){
    i64 iOff = pDb->treehdr.iOldLog;
    ckptAppend64(p, &iOut, iOff, pRc);
    ckptSetValue(p, iOut++, pDb->treehdr.oldcksum0, pRc);
    ckptSetValue(p, iOut++, pDb->treehdr.oldcksum1, pRc);
  }else{
    for(; iOut<=CKPT_HDR_LO_CKSUM2; iOut++){
      ckptSetValue(p, iOut, pDb->pShmhdr->aSnap2[iOut], pRc);
    }
  }

  assert( *pRc || iOut==CKPT_HDR_LO_CKSUM2+1 );
  *piOut = iOut;
}

static void ckptExportAppendlist(
  lsm_db *db,                     /* Database connection */
  CkptBuffer *p,                  /* Checkpoint buffer to write to */
  int *piOut,                     /* IN/OUT: Offset within checkpoint buffer */
  int *pRc                        /* IN/OUT: Error code */
){
  int i;
  Pgno *aiAppend = db->pWorker->aiAppend;

  for(i=0; i<LSM_APPLIST_SZ; i++){
    ckptAppend64(p, piOut, aiAppend[i], pRc);
  }
};

static int ckptExportSnapshot( 
  lsm_db *pDb,                    /* Connection handle */
  int bLog,                       /* True to update log-offset fields */
  i64 iId,                        /* Checkpoint id */
  int bCksum,                     /* If true, include checksums */
  void **ppCkpt,                  /* OUT: Buffer containing checkpoint */
  int *pnCkpt                     /* OUT: Size of checkpoint in bytes */
){
  int rc = LSM_OK;                /* Return Code */
  FileSystem *pFS = pDb->pFS;     /* File system object */
  Snapshot *pSnap = pDb->pWorker; /* Worker snapshot */
  int nLevel = 0;                 /* Number of levels in checkpoint */
  int iLevel;                     /* Used to count out nLevel levels */
  int iOut = 0;                   /* Current offset in aCkpt[] */
  Level *pLevel;                  /* Level iterator */
  int i;                          /* Iterator used while serializing freelist */
  CkptBuffer ckpt;

  /* Initialize the output buffer */
  memset(&ckpt, 0, sizeof(CkptBuffer));
  ckpt.pEnv = pDb->pEnv;
  iOut = CKPT_HDR_SIZE;

  /* Write the log offset into the checkpoint. */
  ckptExportLog(pDb, bLog, &ckpt, &iOut, &rc);

  /* Write the append-point list */
  ckptExportAppendlist(pDb, &ckpt, &iOut, &rc);

  /* Figure out how many levels will be written to the checkpoint. */
  for(pLevel=lsmDbSnapshotLevel(pSnap); pLevel; pLevel=pLevel->pNext) nLevel++;

  /* Serialize nLevel levels. */
  iLevel = 0;
  for(pLevel=lsmDbSnapshotLevel(pSnap); iLevel<nLevel; pLevel=pLevel->pNext){
    ckptExportLevel(pLevel, &ckpt, &iOut, &rc);
    iLevel++;
  }

  /* Write the block-redirect list */
  ckptSetValue(&ckpt, iOut++, pSnap->redirect.n, &rc);
  for(i=0; i<pSnap->redirect.n; i++){
    ckptSetValue(&ckpt, iOut++, pSnap->redirect.a[i].iFrom, &rc);
    ckptSetValue(&ckpt, iOut++, pSnap->redirect.a[i].iTo, &rc);
  }

  /* Write the freelist */
  assert( pSnap->freelist.nEntry<=pDb->nMaxFreelist );
  if( rc==LSM_OK ){
    int nFree = pSnap->freelist.nEntry;
    ckptSetValue(&ckpt, iOut++, nFree, &rc);
    for(i=0; i<nFree; i++){
      FreelistEntry *p = &pSnap->freelist.aEntry[i];
      ckptSetValue(&ckpt, iOut++, p->iBlk, &rc);
      ckptSetValue(&ckpt, iOut++, (p->iId >> 32) & 0xFFFFFFFF, &rc);
      ckptSetValue(&ckpt, iOut++, p->iId & 0xFFFFFFFF, &rc);
    }
  }

  /* Write the checkpoint header */
  assert( iId>=0 );
  assert( pSnap->iCmpId==pDb->compress.iId
       || pSnap->iCmpId==LSM_COMPRESSION_EMPTY 
  );
  ckptSetValue(&ckpt, CKPT_HDR_ID_MSW, (u32)(iId>>32), &rc);
  ckptSetValue(&ckpt, CKPT_HDR_ID_LSW, (u32)(iId&0xFFFFFFFF), &rc);
  ckptSetValue(&ckpt, CKPT_HDR_NCKPT, iOut+2, &rc);
  ckptSetValue(&ckpt, CKPT_HDR_CMPID, pDb->compress.iId, &rc);
  ckptSetValue(&ckpt, CKPT_HDR_NBLOCK, pSnap->nBlock, &rc);
  ckptSetValue(&ckpt, CKPT_HDR_BLKSZ, lsmFsBlockSize(pFS), &rc);
  ckptSetValue(&ckpt, CKPT_HDR_NLEVEL, nLevel, &rc);
  ckptSetValue(&ckpt, CKPT_HDR_PGSZ, lsmFsPageSize(pFS), &rc);
  ckptSetValue(&ckpt, CKPT_HDR_NWRITE, pSnap->nWrite, &rc);

  if( bCksum ){
    ckptAddChecksum(&ckpt, iOut, &rc);
  }else{
    ckptSetValue(&ckpt, iOut, 0, &rc);
    ckptSetValue(&ckpt, iOut+1, 0, &rc);
  }
  iOut += 2;
  assert( iOut<=1024 );

#ifdef LSM_LOG_FREELIST
  lsmLogMessage(pDb, rc, 
      "ckptExportSnapshot(): id=%lld freelist: %d", iId, pSnap->freelist.nEntry
  );
  for(i=0; i<pSnap->freelist.nEntry; i++){
  lsmLogMessage(pDb, rc, 
      "ckptExportSnapshot(): iBlk=%d id=%lld", 
      pSnap->freelist.aEntry[i].iBlk,
      pSnap->freelist.aEntry[i].iId
  );
  }
#endif

  *ppCkpt = (void *)ckpt.aCkpt;
  if( pnCkpt ) *pnCkpt = sizeof(u32)*iOut;
  return rc;
}


/*
** Helper function for ckptImport().
*/
static void ckptNewSegment(
  u32 *aIn,
  int *piIn,
  Segment *pSegment               /* Populate this structure */
){
  assert( pSegment->iFirst==0 && pSegment->iLastPg==0 );
  assert( pSegment->nSize==0 && pSegment->iRoot==0 );
  pSegment->iFirst = ckptGobble64(aIn, piIn);
  pSegment->iLastPg = ckptGobble64(aIn, piIn);
  pSegment->iRoot = ckptGobble64(aIn, piIn);
  pSegment->nSize = ckptGobble64(aIn, piIn);
  assert( pSegment->iFirst );
}

static int ckptSetupMerge(lsm_db *pDb, u32 *aInt, int *piIn, Level *pLevel){
  Merge *pMerge;                  /* Allocated Merge object */
  int nInput;                     /* Number of input segments in merge */
  int iIn = *piIn;                /* Next value to read from aInt[] */
  int i;                          /* Iterator variable */
  int nByte;                      /* Number of bytes to allocate */

  /* Allocate the Merge object. If malloc() fails, return LSM_NOMEM. */
  nInput = (int)aInt[iIn++];
  nByte = sizeof(Merge) + sizeof(MergeInput) * nInput;
  pMerge = (Merge *)lsmMallocZero(pDb->pEnv, nByte);
  if( !pMerge ) return LSM_NOMEM_BKPT;
  pLevel->pMerge = pMerge;

  /* Populate the Merge object. */
  pMerge->aInput = (MergeInput *)&pMerge[1];
  pMerge->nInput = nInput;
  pMerge->iOutputOff = -1;
  pMerge->nSkip = (int)aInt[iIn++];
  for(i=0; i<nInput; i++){
    pMerge->aInput[i].iPg = ckptGobble64(aInt, &iIn);
    pMerge->aInput[i].iCell = (int)aInt[iIn++];
  }
  pMerge->splitkey.iPg = ckptGobble64(aInt, &iIn);
  pMerge->splitkey.iCell = (int)aInt[iIn++];
  pMerge->iCurrentPtr = ckptGobble64(aInt, &iIn);

  /* Set *piIn and return LSM_OK. */
  *piIn = iIn;
  return LSM_OK;
}


static int ckptLoadLevels(
  lsm_db *pDb,
  u32 *aIn, 
  int *piIn, 
  int nLevel,
  Level **ppLevel
){
  int i;
  int rc = LSM_OK;
  Level *pRet = 0;
  Level **ppNext;
  int iIn = *piIn;

  ppNext = &pRet;
  for(i=0; rc==LSM_OK && i<nLevel; i++){
    int iRight;
    Level *pLevel;

    /* Allocate space for the Level structure and Level.apRight[] array */
    pLevel = (Level *)lsmMallocZeroRc(pDb->pEnv, sizeof(Level), &rc);
    if( rc==LSM_OK ){
      pLevel->iAge = (u16)(aIn[iIn] & 0x0000FFFF);
      pLevel->flags = (u16)((aIn[iIn]>>16) & 0x0000FFFF);
      iIn++;
      pLevel->nRight = aIn[iIn++];
      if( pLevel->nRight ){
        int nByte = sizeof(Segment) * pLevel->nRight;
        pLevel->aRhs = (Segment *)lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
      }
      if( rc==LSM_OK ){
        *ppNext = pLevel;
        ppNext = &pLevel->pNext;

        /* Allocate the main segment */
        ckptNewSegment(aIn, &iIn, &pLevel->lhs);

        /* Allocate each of the right-hand segments, if any */
        for(iRight=0; iRight<pLevel->nRight; iRight++){
          ckptNewSegment(aIn, &iIn, &pLevel->aRhs[iRight]);
        }

        /* Set up the Merge object, if required */
        if( pLevel->nRight>0 ){
          rc = ckptSetupMerge(pDb, aIn, &iIn, pLevel);
        }
      }
    }
  }

  if( rc!=LSM_OK ){
    /* An OOM must have occurred. Free any level structures allocated and
    ** return the error to the caller. */
    lsmSortedFreeLevel(pDb->pEnv, pRet);
    pRet = 0;
  }

  *ppLevel = pRet;
  *piIn = iIn;
  return rc;
}


int lsmCheckpointLoadLevels(lsm_db *pDb, void *pVal, int nVal){
  int rc = LSM_OK;
  if( nVal>0 ){
    u32 *aIn;

    aIn = lsmMallocRc(pDb->pEnv, nVal, &rc);
    if( aIn ){
      Level *pLevel = 0;
      Level *pParent;

      int nIn;
      int nLevel;
      int iIn = 1;
      memcpy(aIn, pVal, nVal);
      nIn = nVal / sizeof(u32);

      ckptChangeEndianness(aIn, nIn);
      nLevel = aIn[0];
      rc = ckptLoadLevels(pDb, aIn, &iIn, nLevel, &pLevel);
      lsmFree(pDb->pEnv, aIn);
      assert( rc==LSM_OK || pLevel==0 );
      if( rc==LSM_OK ){
        pParent = lsmDbSnapshotLevel(pDb->pWorker);
        assert( pParent );
        while( pParent->pNext ) pParent = pParent->pNext;
        pParent->pNext = pLevel;
      }
    }
  }

  return rc;
}

/*
** Return the data for the LEVELS record.
**
** The size of the checkpoint that can be stored in the database header
** must not exceed 1024 32-bit integers. Normally, it does not. However,
** if it does, part of the checkpoint must be stored in the LSM. This
** routine returns that part.
*/
int lsmCheckpointLevels(
  lsm_db *pDb,                    /* Database handle */
  int nLevel,                     /* Number of levels to write to blob */
  void **paVal,                   /* OUT: Pointer to LEVELS blob */
  int *pnVal                      /* OUT: Size of LEVELS blob in bytes */
){
  Level *p;                       /* Used to iterate through levels */
  int nAll= 0;
  int rc;
  int i;
  int iOut;
  CkptBuffer ckpt;
  assert( nLevel>0 );

  for(p=lsmDbSnapshotLevel(pDb->pWorker); p; p=p->pNext) nAll++;

  assert( nAll>nLevel );
  nAll -= nLevel;
  for(p=lsmDbSnapshotLevel(pDb->pWorker); p && nAll>0; p=p->pNext) nAll--;

  memset(&ckpt, 0, sizeof(CkptBuffer));
  ckpt.pEnv = pDb->pEnv;

  ckptSetValue(&ckpt, 0, nLevel, &rc);
  iOut = 1;
  for(i=0; rc==LSM_OK && i<nLevel; i++){
    ckptExportLevel(p, &ckpt, &iOut, &rc);
    p = p->pNext;
  }
  assert( rc!=LSM_OK || p==0 );

  if( rc==LSM_OK ){
    ckptChangeEndianness(ckpt.aCkpt, iOut);
    *paVal = (void *)ckpt.aCkpt;
    *pnVal = iOut * sizeof(u32);
  }else{
    *pnVal = 0;
    *paVal = 0;
  }

  return rc;
}

/*
** Read the checkpoint id from meta-page pPg.
*/
static i64 ckptLoadId(MetaPage *pPg){
  i64 ret = 0;
  if( pPg ){
    int nData;
    u8 *aData = lsmFsMetaPageData(pPg, &nData);
    ret = (((i64)lsmGetU32(&aData[CKPT_HDR_ID_MSW*4])) << 32) + 
          ((i64)lsmGetU32(&aData[CKPT_HDR_ID_LSW*4]));
  }
  return ret;
}

/*
** Return true if the buffer passed as an argument contains a valid
** checkpoint.
*/
static int ckptChecksumOk(u32 *aCkpt){
  u32 nCkpt = aCkpt[CKPT_HDR_NCKPT];
  u32 cksum1;
  u32 cksum2;

  if( nCkpt<CKPT_HDR_NCKPT || nCkpt>(LSM_META_PAGE_SIZE)/sizeof(u32) ) return 0;
  ckptChecksum(aCkpt, nCkpt, &cksum1, &cksum2);
  return (cksum1==aCkpt[nCkpt-2] && cksum2==aCkpt[nCkpt-1]);
}

/*
** Attempt to load a checkpoint from meta page iMeta.
**
** This function is a no-op if *pRc is set to any value other than LSM_OK
** when it is called. If an error occurs, *pRc is set to an LSM error code
** before returning.
**
** If no error occurs and the checkpoint is successfully loaded, copy it to
** ShmHeader.aSnap1[] and ShmHeader.aSnap2[], and set ShmHeader.iMetaPage 
** to indicate its origin. In this case return 1. Or, if the checkpoint 
** cannot be loaded (because the checksum does not compute), return 0.
*/
static int ckptTryLoad(lsm_db *pDb, MetaPage *pPg, u32 iMeta, int *pRc){
  int bLoaded = 0;                /* Return value */
  if( *pRc==LSM_OK ){
    int rc = LSM_OK;              /* Error code */
    u32 *aCkpt = 0;               /* Pointer to buffer containing checkpoint */
    u32 nCkpt;                    /* Number of elements in aCkpt[] */
    int nData;                    /* Bytes of data in aData[] */
    u8 *aData;                    /* Meta page data */
   
    aData = lsmFsMetaPageData(pPg, &nData);
    nCkpt = (u32)lsmGetU32(&aData[CKPT_HDR_NCKPT*sizeof(u32)]);
    if( nCkpt<=nData/sizeof(u32) && nCkpt>CKPT_HDR_NCKPT ){
      aCkpt = (u32 *)lsmMallocRc(pDb->pEnv, nCkpt*sizeof(u32), &rc);
    }
    if( aCkpt ){
      memcpy(aCkpt, aData, nCkpt*sizeof(u32));
      ckptChangeEndianness(aCkpt, nCkpt);
      if( ckptChecksumOk(aCkpt) ){
        ShmHeader *pShm = pDb->pShmhdr;
        memcpy(pShm->aSnap1, aCkpt, nCkpt*sizeof(u32));
        memcpy(pShm->aSnap2, aCkpt, nCkpt*sizeof(u32));
        memcpy(pDb->aSnapshot, aCkpt, nCkpt*sizeof(u32));
        pShm->iMetaPage = iMeta;
        bLoaded = 1;
      }
    }

    lsmFree(pDb->pEnv, aCkpt);
    *pRc = rc;
  }
  return bLoaded;
}

/*
** Initialize the shared-memory header with an empty snapshot. This function
** is called when no valid snapshot can be found in the database header.
*/
static void ckptLoadEmpty(lsm_db *pDb){
  u32 aCkpt[] = {
    0,                       /* CKPT_HDR_ID_MSW */
    10,                      /* CKPT_HDR_ID_LSW */
    0,                       /* CKPT_HDR_NCKPT */
    LSM_COMPRESSION_EMPTY,   /* CKPT_HDR_CMPID */
    0,                       /* CKPT_HDR_NBLOCK */
    0,                       /* CKPT_HDR_BLKSZ */
    0,                       /* CKPT_HDR_NLEVEL */
    0,                       /* CKPT_HDR_PGSZ */
    0,                       /* CKPT_HDR_NWRITE */
    0, 0, 1234, 5678,        /* The log pointer and initial checksum */
    0,0,0,0, 0,0,0,0,        /* The append list */
    0,                       /* The redirected block list */
    0,                       /* The free block list */
    0, 0                     /* Space for checksum values */
  };
  u32 nCkpt = array_size(aCkpt);
  ShmHeader *pShm = pDb->pShmhdr;

  aCkpt[CKPT_HDR_NCKPT] = nCkpt;
  aCkpt[CKPT_HDR_BLKSZ] = pDb->nDfltBlksz;
  aCkpt[CKPT_HDR_PGSZ] = pDb->nDfltPgsz;
  ckptChecksum(aCkpt, array_size(aCkpt), &aCkpt[nCkpt-2], &aCkpt[nCkpt-1]);

  memcpy(pShm->aSnap1, aCkpt, nCkpt*sizeof(u32));
  memcpy(pShm->aSnap2, aCkpt, nCkpt*sizeof(u32));
  memcpy(pDb->aSnapshot, aCkpt, nCkpt*sizeof(u32));
}

/*
** This function is called as part of database recovery to initialize the
** ShmHeader.aSnap1[] and ShmHeader.aSnap2[] snapshots.
*/
int lsmCheckpointRecover(lsm_db *pDb){
  int rc = LSM_OK;                /* Return Code */
  i64 iId1;                       /* Id of checkpoint on meta-page 1 */
  i64 iId2;                       /* Id of checkpoint on meta-page 2 */
  int bLoaded = 0;                /* True once checkpoint has been loaded */
  int cmp;                        /* True if (iId2>iId1) */
  MetaPage *apPg[2] = {0, 0};     /* Meta-pages 1 and 2 */

  rc = lsmFsMetaPageGet(pDb->pFS, 0, 1, &apPg[0]);
  if( rc==LSM_OK ) rc = lsmFsMetaPageGet(pDb->pFS, 0, 2, &apPg[1]);

  iId1 = ckptLoadId(apPg[0]);
  iId2 = ckptLoadId(apPg[1]);
  cmp = (iId2 > iId1);
  bLoaded = ckptTryLoad(pDb, apPg[cmp?1:0], (cmp?2:1), &rc);
  if( bLoaded==0 ){
    bLoaded = ckptTryLoad(pDb, apPg[cmp?0:1], (cmp?1:2), &rc);
  }

  /* The database does not contain a valid checkpoint. Initialize the shared
  ** memory header with an empty checkpoint.  */
  if( bLoaded==0 ){
    ckptLoadEmpty(pDb);
  }

  lsmFsMetaPageRelease(apPg[0]);
  lsmFsMetaPageRelease(apPg[1]);

  return rc;
}

/* 
** Store the snapshot in pDb->aSnapshot[] in meta-page iMeta.
*/
int lsmCheckpointStore(lsm_db *pDb, int iMeta){
  MetaPage *pPg = 0;
  int rc;

  assert( iMeta==1 || iMeta==2 );
  rc = lsmFsMetaPageGet(pDb->pFS, 1, iMeta, &pPg);
  if( rc==LSM_OK ){
    u8 *aData;
    int nData;
    int nCkpt;

    nCkpt = (int)pDb->aSnapshot[CKPT_HDR_NCKPT];
    aData = lsmFsMetaPageData(pPg, &nData);
    memcpy(aData, pDb->aSnapshot, nCkpt*sizeof(u32));
    ckptChangeEndianness((u32 *)aData, nCkpt);
    rc = lsmFsMetaPageRelease(pPg);
  }
      
  return rc;
}

/*
** Copy the current client snapshot from shared-memory to pDb->aSnapshot[].
*/
int lsmCheckpointLoad(lsm_db *pDb, int *piRead){
  int nRem = LSM_ATTEMPTS_BEFORE_PROTOCOL;
  ShmHeader *pShm = pDb->pShmhdr;
  while( (nRem--)>0 ){
    int nInt;

    nInt = pShm->aSnap1[CKPT_HDR_NCKPT];
    if( nInt<=(LSM_META_PAGE_SIZE / sizeof(u32)) ){
      memcpy(pDb->aSnapshot, pShm->aSnap1, nInt*sizeof(u32));
      if( ckptChecksumOk(pDb->aSnapshot) ){
        if( piRead ) *piRead = 1;
        return LSM_OK;
      }
    }

    nInt = pShm->aSnap2[CKPT_HDR_NCKPT];
    if( nInt<=(LSM_META_PAGE_SIZE / sizeof(u32)) ){
      memcpy(pDb->aSnapshot, pShm->aSnap2, nInt*sizeof(u32));
      if( ckptChecksumOk(pDb->aSnapshot) ){
        if( piRead ) *piRead = 2;
        return LSM_OK;
      }
    }

    lsmShmBarrier(pDb);
  }
  return LSM_PROTOCOL_BKPT;
}

int lsmInfoCompressionId(lsm_db *db, u32 *piCmpId){
  int rc;

  assert( db->pClient==0 && db->pWorker==0 );
  rc = lsmCheckpointLoad(db, 0);
  if( rc==LSM_OK ){
    *piCmpId = db->aSnapshot[CKPT_HDR_CMPID];
  }

  return rc;
}

int lsmCheckpointLoadOk(lsm_db *pDb, int iSnap){
  u32 *aShm;
  assert( iSnap==1 || iSnap==2 );
  aShm = (iSnap==1) ? pDb->pShmhdr->aSnap1 : pDb->pShmhdr->aSnap2;
  return (lsmCheckpointId(pDb->aSnapshot, 0)==lsmCheckpointId(aShm, 0) );
}

int lsmCheckpointClientCacheOk(lsm_db *pDb){
  return ( pDb->pClient 
        && pDb->pClient->iId==lsmCheckpointId(pDb->aSnapshot, 0)
        && pDb->pClient->iId==lsmCheckpointId(pDb->pShmhdr->aSnap1, 0)
        && pDb->pClient->iId==lsmCheckpointId(pDb->pShmhdr->aSnap2, 0)
  );
}

int lsmCheckpointLoadWorker(lsm_db *pDb){
  int rc;
  ShmHeader *pShm = pDb->pShmhdr;
  int nInt1;
  int nInt2;

  /* Must be holding the WORKER lock to do this. Or DMS2. */
  assert( 
      lsmShmAssertLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_EXCL) 
   || lsmShmAssertLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL) 
  );

  /* Check that the two snapshots match. If not, repair them. */
  nInt1 = pShm->aSnap1[CKPT_HDR_NCKPT];
  nInt2 = pShm->aSnap2[CKPT_HDR_NCKPT];
  if( nInt1!=nInt2 || memcmp(pShm->aSnap1, pShm->aSnap2, nInt2*sizeof(u32)) ){
    if( ckptChecksumOk(pShm->aSnap1) ){
      memcpy(pShm->aSnap2, pShm->aSnap1, sizeof(u32)*nInt1);
    }else if( ckptChecksumOk(pShm->aSnap2) ){
      memcpy(pShm->aSnap1, pShm->aSnap2, sizeof(u32)*nInt2);
    }else{
      return LSM_PROTOCOL_BKPT;
    }
  }

  rc = lsmCheckpointDeserialize(pDb, 1, pShm->aSnap1, &pDb->pWorker);
  if( pDb->pWorker ) pDb->pWorker->pDatabase = pDb->pDatabase;

  if( rc==LSM_OK ){
    rc = lsmCheckCompressionId(pDb, pDb->pWorker->iCmpId);
  }

#if 0
  assert( rc!=LSM_OK || lsmFsIntegrityCheck(pDb) );
#endif
  return rc;
}

int lsmCheckpointDeserialize(
  lsm_db *pDb, 
  int bInclFreelist,              /* If true, deserialize free-list */
  u32 *aCkpt, 
  Snapshot **ppSnap
){
  int rc = LSM_OK;
  Snapshot *pNew;

  pNew = (Snapshot *)lsmMallocZeroRc(pDb->pEnv, sizeof(Snapshot), &rc);
  if( rc==LSM_OK ){
    Level *pLvl;
    int nFree;
    int i;
    int nLevel = (int)aCkpt[CKPT_HDR_NLEVEL];
    int iIn = CKPT_HDR_SIZE + CKPT_APPENDLIST_SIZE + CKPT_LOGPTR_SIZE;

    pNew->iId = lsmCheckpointId(aCkpt, 0);
    pNew->nBlock = aCkpt[CKPT_HDR_NBLOCK];
    pNew->nWrite = aCkpt[CKPT_HDR_NWRITE];
    rc = ckptLoadLevels(pDb, aCkpt, &iIn, nLevel, &pNew->pLevel);
    pNew->iLogOff = lsmCheckpointLogOffset(aCkpt);
    pNew->iCmpId = aCkpt[CKPT_HDR_CMPID];

    /* Make a copy of the append-list */
    for(i=0; i<LSM_APPLIST_SZ; i++){
      u32 *a = &aCkpt[CKPT_HDR_SIZE + CKPT_LOGPTR_SIZE + i*2];
      pNew->aiAppend[i] = ckptRead64(a);
    }

    /* Read the block-redirect list */
    pNew->redirect.n = aCkpt[iIn++];
    if( pNew->redirect.n ){
      pNew->redirect.a = lsmMallocZeroRc(pDb->pEnv, 
          (sizeof(struct RedirectEntry) * LSM_MAX_BLOCK_REDIRECTS), &rc
      );
      if( rc==LSM_OK ){
        for(i=0; i<pNew->redirect.n; i++){
          pNew->redirect.a[i].iFrom = aCkpt[iIn++];
          pNew->redirect.a[i].iTo = aCkpt[iIn++];
        }
      }
      for(pLvl=pNew->pLevel; pLvl->pNext; pLvl=pLvl->pNext);
      if( pLvl->nRight ){
        pLvl->aRhs[pLvl->nRight-1].pRedirect = &pNew->redirect;
      }else{
        pLvl->lhs.pRedirect = &pNew->redirect;
      }
    }

    /* Copy the free-list */
    if( rc==LSM_OK && bInclFreelist ){
      nFree = aCkpt[iIn++];
      if( nFree ){
        pNew->freelist.aEntry = (FreelistEntry *)lsmMallocZeroRc(
            pDb->pEnv, sizeof(FreelistEntry)*nFree, &rc
        );
        if( rc==LSM_OK ){
          int i;
          for(i=0; i<nFree; i++){
            FreelistEntry *p = &pNew->freelist.aEntry[i];
            p->iBlk = aCkpt[iIn++];
            p->iId = ((i64)(aCkpt[iIn])<<32) + aCkpt[iIn+1];
            iIn += 2;
          }
          pNew->freelist.nEntry = pNew->freelist.nAlloc = nFree;
        }
      }
    }
  }

  if( rc!=LSM_OK ){
    lsmFreeSnapshot(pDb->pEnv, pNew);
    pNew = 0;
  }

  *ppSnap = pNew;
  return rc;
}

/*
** Connection pDb must be the worker connection in order to call this
** function. It returns true if the database already contains the maximum
** number of levels or false otherwise.
**
** This is used when flushing the in-memory tree to disk. If the database
** is already full, then the caller should invoke lsm_work() or similar
** until it is not full before creating a new level by flushing the in-memory
** tree to disk. Limiting the number of levels in the database ensures that
** the records describing them always fit within the checkpoint blob.
*/
int lsmDatabaseFull(lsm_db *pDb){
  Level *p;
  int nRhs = 0;

  assert( lsmShmAssertLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_EXCL) );
  assert( pDb->pWorker );

  for(p=pDb->pWorker->pLevel; p; p=p->pNext){
    nRhs += (p->nRight ? p->nRight : 1);
  }

  return (nRhs >= LSM_MAX_RHS_SEGMENTS);
}

/*
** The connection passed as the only argument is currently the worker
** connection. Some work has been performed on the database by the connection,
** but no new snapshot has been written into shared memory.
**
** This function updates the shared-memory worker and client snapshots with
** the new snapshot produced by the work performed by pDb.
**
** If successful, LSM_OK is returned. Otherwise, if an error occurs, an LSM
** error code is returned.
*/
int lsmCheckpointSaveWorker(lsm_db *pDb, int bFlush){
  Snapshot *pSnap = pDb->pWorker;
  ShmHeader *pShm = pDb->pShmhdr;
  void *p = 0;
  int n = 0;
  int rc;

  pSnap->iId++;
  rc = ckptExportSnapshot(pDb, bFlush, pSnap->iId, 1, &p, &n);
  if( rc!=LSM_OK ) return rc;
  assert( ckptChecksumOk((u32 *)p) );

  assert( n<=LSM_META_PAGE_SIZE );
  memcpy(pShm->aSnap2, p, n);
  lsmShmBarrier(pDb);
  memcpy(pShm->aSnap1, p, n);
  lsmFree(pDb->pEnv, p);

  assert( lsmFsIntegrityCheck(pDb) );
  return LSM_OK;
}

/*
** This function is used to determine the snapshot-id of the most recently
** checkpointed snapshot. Variable ShmHeader.iMetaPage indicates which of
** the two meta-pages said snapshot resides on (if any). 
**
** If successful, this function loads the snapshot from the meta-page, 
** verifies its checksum and sets *piId to the snapshot-id before returning
** LSM_OK. Or, if the checksum attempt fails, *piId is set to zero and
** LSM_OK returned. If an error occurs, an LSM error code is returned and
** the final value of *piId is undefined.
*/
int lsmCheckpointSynced(lsm_db *pDb, i64 *piId, i64 *piLog, u32 *pnWrite){
  int rc = LSM_OK;
  MetaPage *pPg;
  u32 iMeta;

  iMeta = pDb->pShmhdr->iMetaPage;
  if( iMeta==1 || iMeta==2 ){
    rc = lsmFsMetaPageGet(pDb->pFS, 0, iMeta, &pPg);
    if( rc==LSM_OK ){
      int nCkpt;
      int nData;
      u8 *aData; 

      aData = lsmFsMetaPageData(pPg, &nData);
      assert( nData==LSM_META_PAGE_SIZE );
      nCkpt = lsmGetU32(&aData[CKPT_HDR_NCKPT*sizeof(u32)]);
      if( nCkpt<(LSM_META_PAGE_SIZE/sizeof(u32)) ){
        u32 *aCopy = lsmMallocRc(pDb->pEnv, sizeof(u32) * nCkpt, &rc);
        if( aCopy ){
          memcpy(aCopy, aData, nCkpt*sizeof(u32));
          ckptChangeEndianness(aCopy, nCkpt);
          if( ckptChecksumOk(aCopy) ){
            if( piId ) *piId = lsmCheckpointId(aCopy, 0);
            if( piLog ) *piLog = (lsmCheckpointLogOffset(aCopy) >> 1);
            if( pnWrite ) *pnWrite = aCopy[CKPT_HDR_NWRITE];
          }
          lsmFree(pDb->pEnv, aCopy);
        }
      }
      lsmFsMetaPageRelease(pPg);
    }
  }

  if( (iMeta!=1 && iMeta!=2) || rc!=LSM_OK || pDb->pShmhdr->iMetaPage!=iMeta ){
    if( piId ) *piId = 0;
    if( piLog ) *piLog = 0;
    if( pnWrite ) *pnWrite = 0;
  }
  return rc;
}

/*
** Return the checkpoint-id of the checkpoint array passed as the first
** argument to this function. If the second argument is true, then assume
** that the checkpoint is made up of 32-bit big-endian integers. If it
** is false, assume that the integers are in machine byte order.
*/
i64 lsmCheckpointId(u32 *aCkpt, int bDisk){
  i64 iId;
  if( bDisk ){
    u8 *aData = (u8 *)aCkpt;
    iId = (((i64)lsmGetU32(&aData[CKPT_HDR_ID_MSW*4])) << 32);
    iId += ((i64)lsmGetU32(&aData[CKPT_HDR_ID_LSW*4]));
  }else{
    iId = ((i64)aCkpt[CKPT_HDR_ID_MSW] << 32) + (i64)aCkpt[CKPT_HDR_ID_LSW];
  }
  return iId;
}

u32 lsmCheckpointNBlock(u32 *aCkpt){
  return aCkpt[CKPT_HDR_NBLOCK];
}

u32 lsmCheckpointNWrite(u32 *aCkpt, int bDisk){
  if( bDisk ){
    return lsmGetU32((u8 *)&aCkpt[CKPT_HDR_NWRITE]);
  }else{
    return aCkpt[CKPT_HDR_NWRITE];
  }
}

i64 lsmCheckpointLogOffset(u32 *aCkpt){
  return ((i64)aCkpt[CKPT_HDR_LO_MSW] << 32) + (i64)aCkpt[CKPT_HDR_LO_LSW];
}

int lsmCheckpointPgsz(u32 *aCkpt){ return (int)aCkpt[CKPT_HDR_PGSZ]; }

int lsmCheckpointBlksz(u32 *aCkpt){ return (int)aCkpt[CKPT_HDR_BLKSZ]; }

void lsmCheckpointLogoffset(
  u32 *aCkpt,
  DbLog *pLog
){ 
  pLog->aRegion[2].iStart = (lsmCheckpointLogOffset(aCkpt) >> 1);

  pLog->cksum0 = aCkpt[CKPT_HDR_LO_CKSUM1];
  pLog->cksum1 = aCkpt[CKPT_HDR_LO_CKSUM2];
  pLog->iSnapshotId = lsmCheckpointId(aCkpt, 0);
}

void lsmCheckpointZeroLogoffset(lsm_db *pDb){
  u32 nCkpt;

  nCkpt = pDb->aSnapshot[CKPT_HDR_NCKPT];
  assert( nCkpt>CKPT_HDR_NCKPT );
  assert( nCkpt==pDb->pShmhdr->aSnap1[CKPT_HDR_NCKPT] );
  assert( 0==memcmp(pDb->aSnapshot, pDb->pShmhdr->aSnap1, nCkpt*sizeof(u32)) );
  assert( 0==memcmp(pDb->aSnapshot, pDb->pShmhdr->aSnap2, nCkpt*sizeof(u32)) );

  pDb->aSnapshot[CKPT_HDR_LO_MSW] = 0;
  pDb->aSnapshot[CKPT_HDR_LO_LSW] = 0;
  ckptChecksum(pDb->aSnapshot, nCkpt, 
      &pDb->aSnapshot[nCkpt-2], &pDb->aSnapshot[nCkpt-1]
  );

  memcpy(pDb->pShmhdr->aSnap1, pDb->aSnapshot, nCkpt*sizeof(u32));
  memcpy(pDb->pShmhdr->aSnap2, pDb->aSnapshot, nCkpt*sizeof(u32));
}

/*
** Set the output variable to the number of KB of data written into the
** database file since the most recent checkpoint.
*/
int lsmCheckpointSize(lsm_db *db, int *pnKB){
  int rc = LSM_OK;
  u32 nSynced;

  /* Set nSynced to the number of pages that had been written when the 
  ** database was last checkpointed. */
  rc = lsmCheckpointSynced(db, 0, 0, &nSynced);

  if( rc==LSM_OK ){
    u32 nPgsz = db->pShmhdr->aSnap1[CKPT_HDR_PGSZ];
    u32 nWrite = db->pShmhdr->aSnap1[CKPT_HDR_NWRITE];
    *pnKB = (int)(( ((i64)(nWrite - nSynced) * nPgsz) + 1023) / 1024);
  }

  return rc;
}

/************** End of lsm_ckpt.c ********************************************/
/************** Begin file lsm_file.c ****************************************/
/*
** 2011-08-26
**
** 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.
**
*************************************************************************
** 
** NORMAL DATABASE FILE FORMAT
**
** The following database file format concepts are used by the code in
** this file to read and write the database file.
**
** Pages:
**
**   A database file is divided into pages. The first 8KB of the file consists
**   of two 4KB meta-pages. The meta-page size is not configurable. The 
**   remainder of the file is made up of database pages. The default database
**   page size is 4KB. Database pages are aligned to page-size boundaries,
**   so if the database page size is larger than 8KB there is a gap between
**   the end of the meta pages and the start of the database pages.
**
**   Database pages are numbered based on their position in the file. Page N
**   begins at byte offset ((N-1)*pgsz). This means that page 1 does not 
**   exist - since it would always overlap with the meta pages. If the 
**   page-size is (say) 512 bytes, then the first usable page in the database
**   is page 33.
**
**   It is assumed that the first two meta pages and the data that follows
**   them are located on different disk sectors. So that if a power failure 
**   while writing to a meta page there is no risk of damage to the other
**   meta page or any other part of the database file. TODO: This may need
**   to be revisited.
**
** Blocks:
**
**   The database file is also divided into blocks. The default block size is
**   1MB. When writing to the database file, an attempt is made to write data
**   in contiguous block-sized chunks.
**
**   The first and last page on each block are special in that they are 4 
**   bytes smaller than all other pages. This is because the last four bytes 
**   of space on the first and last pages of each block are reserved for
**   pointers to other blocks (i.e. a 32-bit block number).
**
** Runs:
**
**   A run is a sequence of pages that the upper layer uses to store a 
**   sorted array of database keys (and accompanying data - values, FC 
**   pointers and so on). Given a page within a run, it is possible to
**   navigate to the next page in the run as follows:
**
**     a) if the current page is not the last in a block, the next page 
**        in the run is located immediately after the current page, OR
**
**     b) if the current page is the last page in a block, the next page 
**        in the run is the first page on the block identified by the
**        block pointer stored in the last 4 bytes of the current block.
**
**   It is possible to navigate to the previous page in a similar fashion,
**   using the block pointer embedded in the last 4 bytes of the first page
**   of each block as required.
**
**   The upper layer is responsible for identifying by page number the 
**   first and last page of any run that it needs to navigate - there are
**   no "end-of-run" markers stored or identified by this layer. This is
**   necessary as clients reading different database snapshots may access 
**   different subsets of a run.
**
** THE LOG FILE 
**
** This file opens and closes the log file. But it does not contain any
** logic related to the log file format. Instead, it exports the following
** functions that are used by the code in lsm_log.c to read and write the
** log file:
**
**     lsmFsOpenLog
**     lsmFsWriteLog
**     lsmFsSyncLog
**     lsmFsReadLog
**     lsmFsTruncateLog
**     lsmFsCloseAndDeleteLog
**
** COMPRESSED DATABASE FILE FORMAT
**
** The compressed database file format is very similar to the normal format.
** The file still begins with two 4KB meta-pages (which are never compressed).
** It is still divided into blocks.
**
** The first and last four bytes of each block are reserved for 32-bit 
** pointer values. Similar to the way four bytes are carved from the end of 
** the first and last page of each block in uncompressed databases. From
** the point of view of the upper layer, all pages are the same size - this
** is different from the uncompressed format where the first and last pages
** on each block are 4 bytes smaller than the others.
**
** Pages are stored in variable length compressed form, as follows:
**
**     * 3-byte size field containing the size of the compressed page image
**       in bytes. The most significant bit of each byte of the size field
**       is always set. The remaining 7 bits are used to store a 21-bit
**       integer value (in big-endian order - the first byte in the field
**       contains the most significant 7 bits). Since the maximum allowed 
**       size of a compressed page image is (2^17 - 1) bytes, there are
**       actually 4 unused bits in the size field.
**
**       In other words, if the size of the compressed page image is nSz,
**       the header can be serialized as follows:
**
**         u8 aHdr[3]
**         aHdr[0] = 0x80 | (u8)(nSz >> 14);
**         aHdr[1] = 0x80 | (u8)(nSz >>  7);
**         aHdr[2] = 0x80 | (u8)(nSz >>  0);
**
**     * Compressed page image.
**
**     * A second copy of the 3-byte record header.
**
** A page number is a byte offset into the database file. So the smallest
** possible page number is 8192 (immediately after the two meta-pages).
** The first and root page of a segment are identified by a page number
** corresponding to the byte offset of the first byte in the corresponding
** page record. The last page of a segment is identified by the byte offset
** of the last byte in its record.
**
** Unlike uncompressed pages, compressed page records may span blocks.
**
** Sometimes, in order to avoid touching sectors that contain synced data
** when writing, it is necessary to insert unused space between compressed
** page records. This can be done as follows:
**
**     * For less than 6 bytes of empty space, the first and last byte
**       of the free space contain the total number of free bytes. For
**       example:
**
**         Block of 4 free bytes: 0x04 0x?? 0x?? 0x04
**         Block of 2 free bytes: 0x02 0x02
**         A single free byte:    0x01
**
**     * For 6 or more bytes of empty space, a record similar to a 
**       compressed page record is added to the segment. A padding record
**       is distinguished from a compressed page record by the most 
**       significant bit of the second byte of the size field, which is
**       cleared instead of set. 
*/

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/*
** File-system object. Each database connection allocates a single instance
** of the following structure. It is used for all access to the database and
** log files.
**
** The database file may be accessed via two methods - using mmap() or using
** read() and write() calls. In the general case both methods are used - a
** prefix of the file is mapped into memory and the remainder accessed using
** read() and write(). This is helpful when accessing very large files (or
** files that may grow very large during the lifetime of a database
** connection) on systems with 32-bit address spaces. However, it also requires
** that this object manage two distinct types of Page objects simultaneously -
** those that carry pointers to the mapped file and those that carry arrays
** populated by read() calls.
**
** pFree:
**   The head of a singly-linked list that containing currently unused Page 
**   structures suitable for use as mmap-page handles. Connected by the
**   Page.pFreeNext pointers.
**
** pMapped:
**   The head of a singly-linked list that contains all pages that currently
**   carry pointers to the mapped region. This is used if the region is
**   every remapped - the pointers carried by existing pages can be adjusted
**   to account for the remapping. Connected by the Page.pMappedNext pointers.
**
** pWaiting:
**   When the upper layer wishes to append a new b-tree page to a segment,
**   it allocates a Page object that carries a malloc'd block of memory -
**   regardless of the mmap-related configuration. The page is not assigned
**   a page number at first. When the upper layer has finished constructing
**   the page contents, it calls lsmFsPagePersist() to assign a page number
**   to it. At this point it is likely that N pages have been written to the
**   segment, the (N+1)th page is still outstanding and the b-tree page is
**   assigned page number (N+2). To avoid writing page (N+2) before page 
**   (N+1), the recently completed b-tree page is held in the singly linked
**   list headed by pWaiting until page (N+1) has been written. 
**
**   Function lsmFsFlushWaiting() is responsible for eventually writing 
**   waiting pages to disk.
**
** apHash/nHash:
**   Hash table used to store all Page objects that carry malloc'd arrays,
**   except those b-tree pages that have not yet been assigned page numbers.
**   Once they have been assigned page numbers - they are added to this
**   hash table.
**
**   Hash table overflow chains are connected using the Page.pHashNext
**   pointers.
**
** pLruFirst, pLruLast:
**   The first and last entries in a doubly-linked list of pages. This
**   list contains all pages with malloc'd data that are present in the
**   hash table and have a ref-count of zero.
*/
struct FileSystem {
  lsm_db *pDb;                    /* Database handle that owns this object */
  lsm_env *pEnv;                  /* Environment pointer */
  char *zDb;                      /* Database file name */
  char *zLog;                     /* Database file name */
  int nMetasize;                  /* Size of meta pages in bytes */
  int nPagesize;                  /* Database page-size in bytes */
  int nBlocksize;                 /* Database block-size in bytes */

  /* r/w file descriptors for both files. */
  LsmFile *pLsmFile;              /* Used after lsm_close() to link into list */
  lsm_file *fdDb;                 /* Database file */
  lsm_file *fdLog;                /* Log file */
  int szSector;                   /* Database file sector size */

  /* If this is a compressed database, a pointer to the compression methods.
  ** For an uncompressed database, a NULL pointer.  */
  lsm_compress *pCompress;
  u8 *aIBuffer;                   /* Buffer to compress to */
  u8 *aOBuffer;                   /* Buffer to uncompress from */
  int nBuffer;                    /* Allocated size of above buffers in bytes */

  /* mmap() page related things */
  i64 nMapLimit;                  /* Maximum bytes of file to map */
  void *pMap;                     /* Current mapping of database file */
  i64 nMap;                       /* Bytes mapped at pMap */
  Page *pFree;                    /* Unused Page structures */
  Page *pMapped;                  /* List of Page structs that point to pMap */

  /* Page cache parameters for non-mmap() pages */
  int nCacheMax;                  /* Configured cache size (in pages) */
  int nCacheAlloc;                /* Current cache size (in pages) */
  Page *pLruFirst;                /* Head of the LRU list */
  Page *pLruLast;                 /* Tail of the LRU list */
  int nHash;                      /* Number of hash slots in hash table */
  Page **apHash;                  /* nHash Hash slots */
  Page *pWaiting;                 /* b-tree pages waiting to be written */

  /* Statistics */
  int nOut;                       /* Number of outstanding pages */
  int nWrite;                     /* Total number of pages written */
  int nRead;                      /* Total number of pages read */
};

/*
** Database page handle.
**
** pSeg:
**   When lsmFsSortedAppend() is called on a compressed database, the new
**   page is not assigned a page number or location in the database file
**   immediately. Instead, these are assigned by the lsmFsPagePersist() call
**   right before it writes the compressed page image to disk.
**
**   The lsmFsSortedAppend() function sets the pSeg pointer to point to the
**   segment that the new page will be a part of. It is unset by
**   lsmFsPagePersist() after the page is written to disk.
*/
struct Page {
  u8 *aData;                      /* Buffer containing page data */
  int nData;                      /* Bytes of usable data at aData[] */
  Pgno iPg;                       /* Page number */
  int nRef;                       /* Number of outstanding references */
  int flags;                      /* Combination of PAGE_XXX flags */
  Page *pHashNext;                /* Next page in hash table slot */
  Page *pLruNext;                 /* Next page in LRU list */
  Page *pLruPrev;                 /* Previous page in LRU list */
  FileSystem *pFS;                /* File system that owns this page */

  /* Only used in compressed database mode: */
  int nCompress;                  /* Compressed size (or 0 for uncomp. db) */
  int nCompressPrev;              /* Compressed size of prev page */
  Segment *pSeg;                  /* Segment this page will be written to */

  /* Pointers for singly linked lists */
  Page *pWaitingNext;             /* Next page in FileSystem.pWaiting list */
  Page *pFreeNext;                /* Next page in FileSystem.pFree list */
  Page *pMappedNext;              /* Next page in FileSystem.pMapped list */
};

/*
** Meta-data page handle. There are two meta-data pages at the start of
** the database file, each FileSystem.nMetasize bytes in size.
*/
struct MetaPage {
  int iPg;                        /* Either 1 or 2 */
  int bWrite;                     /* Write back to db file on release */
  u8 *aData;                      /* Pointer to buffer */
  FileSystem *pFS;                /* FileSystem that owns this page */
};

/* 
** Values for LsmPage.flags 
*/
#define PAGE_DIRTY   0x00000001   /* Set if page is dirty */
#define PAGE_FREE    0x00000002   /* Set if Page.aData requires lsmFree() */
#define PAGE_HASPREV 0x00000004   /* Set if page is first on uncomp. block */

/*
** Number of pgsz byte pages omitted from the start of block 1. The start
** of block 1 contains two 4096 byte meta pages (8192 bytes in total).
*/
#define BLOCK1_HDR_SIZE(pgsz)  LSM_MAX(1, 8192/(pgsz))

/*
** If NDEBUG is not defined, set a breakpoint in function lsmIoerrBkpt()
** to catch IO errors (any error returned by a VFS method). 
*/
#ifndef NDEBUG
static void lsmIoerrBkpt(){
  static int nErr = 0;
  nErr++;
}
static int IOERR_WRAPPER(int rc){
  if( rc!=LSM_OK ) lsmIoerrBkpt();
  return rc;
}
#else
# define IOERR_WRAPPER(rc) (rc)
#endif

#ifdef NDEBUG
# define assert_lists_are_ok(x)
#else
static Page *fsPageFindInHash(FileSystem *pFS, Pgno iPg, int *piHash);

static void assert_lists_are_ok(FileSystem *pFS){
#if 0
  Page *p;

  assert( pFS->nMapLimit>=0 );

  /* Check that all pages in the LRU list have nRef==0, pointers to buffers
  ** in heap memory, and corresponding entries in the hash table.  */
  for(p=pFS->pLruFirst; p; p=p->pLruNext){
    assert( p==pFS->pLruFirst || p->pLruPrev!=0 );
    assert( p==pFS->pLruLast || p->pLruNext!=0 );
    assert( p->pLruPrev==0 || p->pLruPrev->pLruNext==p );
    assert( p->pLruNext==0 || p->pLruNext->pLruPrev==p );
    assert( p->nRef==0 );
    assert( p->flags & PAGE_FREE );
    assert( p==fsPageFindInHash(pFS, p->iPg, 0) );
  }
#endif
}
#endif

/*
** Wrappers around the VFS methods of the lsm_env object:
**
**     lsmEnvOpen()
**     lsmEnvRead()
**     lsmEnvWrite()
**     lsmEnvSync()
**     lsmEnvSectorSize()
**     lsmEnvClose()
**     lsmEnvTruncate()
**     lsmEnvUnlink()
**     lsmEnvRemap()
*/
int lsmEnvOpen(lsm_env *pEnv, const char *zFile, int flags, lsm_file **ppNew){
  return pEnv->xOpen(pEnv, zFile, flags, ppNew);
}

static int lsmEnvRead(
  lsm_env *pEnv, 
  lsm_file *pFile, 
  lsm_i64 iOff, 
  void *pRead, 
  int nRead
){
  return IOERR_WRAPPER( pEnv->xRead(pFile, iOff, pRead, nRead) );
}

static int lsmEnvWrite(
  lsm_env *pEnv, 
  lsm_file *pFile, 
  lsm_i64 iOff, 
  const void *pWrite, 
  int nWrite
){
  return IOERR_WRAPPER( pEnv->xWrite(pFile, iOff, (void *)pWrite, nWrite) );
}

static int lsmEnvSync(lsm_env *pEnv, lsm_file *pFile){
  return IOERR_WRAPPER( pEnv->xSync(pFile) );
}

static int lsmEnvSectorSize(lsm_env *pEnv, lsm_file *pFile){
  return pEnv->xSectorSize(pFile);
}

int lsmEnvClose(lsm_env *pEnv, lsm_file *pFile){
  return IOERR_WRAPPER( pEnv->xClose(pFile) );
}

static int lsmEnvTruncate(lsm_env *pEnv, lsm_file *pFile, lsm_i64 nByte){
  return IOERR_WRAPPER( pEnv->xTruncate(pFile, nByte) );
}

static int lsmEnvUnlink(lsm_env *pEnv, const char *zDel){
  return IOERR_WRAPPER( pEnv->xUnlink(pEnv, zDel) );
}

static int lsmEnvRemap(
  lsm_env *pEnv, 
  lsm_file *pFile, 
  i64 szMin,
  void **ppMap,
  i64 *pszMap
){
  return pEnv->xRemap(pFile, szMin, ppMap, pszMap);
}

int lsmEnvLock(lsm_env *pEnv, lsm_file *pFile, int iLock, int eLock){
  if( pFile==0 ) return LSM_OK;
  return pEnv->xLock(pFile, iLock, eLock);
}

int lsmEnvTestLock(
  lsm_env *pEnv, 
  lsm_file *pFile, 
  int iLock, 
  int nLock, 
  int eLock
){
  return pEnv->xTestLock(pFile, iLock, nLock, eLock);
}

int lsmEnvShmMap(
  lsm_env *pEnv, 
  lsm_file *pFile, 
  int iChunk, 
  int sz, 
  void **ppOut
){
  return pEnv->xShmMap(pFile, iChunk, sz, ppOut);
}

void lsmEnvShmBarrier(lsm_env *pEnv){
  return pEnv->xShmBarrier();
}

void lsmEnvShmUnmap(lsm_env *pEnv, lsm_file *pFile, int bDel){
  pEnv->xShmUnmap(pFile, bDel);
}

void lsmEnvSleep(lsm_env *pEnv, int nUs){
  pEnv->xSleep(pEnv, nUs);
}


/*
** Write the contents of string buffer pStr into the log file, starting at
** offset iOff.
*/
int lsmFsWriteLog(FileSystem *pFS, i64 iOff, LsmString *pStr){
  assert( pFS->fdLog );
  return lsmEnvWrite(pFS->pEnv, pFS->fdLog, iOff, pStr->z, pStr->n);
}

/*
** fsync() the log file.
*/
int lsmFsSyncLog(FileSystem *pFS){
  assert( pFS->fdLog );
  return lsmEnvSync(pFS->pEnv, pFS->fdLog);
}

/*
** Read nRead bytes of data starting at offset iOff of the log file. Append
** the results to string buffer pStr.
*/
int lsmFsReadLog(FileSystem *pFS, i64 iOff, int nRead, LsmString *pStr){
  int rc;                         /* Return code */
  assert( pFS->fdLog );
  rc = lsmStringExtend(pStr, nRead);
  if( rc==LSM_OK ){
    rc = lsmEnvRead(pFS->pEnv, pFS->fdLog, iOff, &pStr->z[pStr->n], nRead);
    pStr->n += nRead;
  }
  return rc;
}

/*
** Truncate the log file to nByte bytes in size.
*/
int lsmFsTruncateLog(FileSystem *pFS, i64 nByte){
  if( pFS->fdLog==0 ) return LSM_OK;
  return lsmEnvTruncate(pFS->pEnv, pFS->fdLog, nByte);
}

/*
** Truncate the db file to nByte bytes in size.
*/
int lsmFsTruncateDb(FileSystem *pFS, i64 nByte){
  if( pFS->fdDb==0 ) return LSM_OK;
  return lsmEnvTruncate(pFS->pEnv, pFS->fdDb, nByte);
}

/*
** Close the log file. Then delete it from the file-system. This function
** is called during database shutdown only.
*/
int lsmFsCloseAndDeleteLog(FileSystem *pFS){
  char *zDel;

  if( pFS->fdLog ){
    lsmEnvClose(pFS->pEnv, pFS->fdLog );
    pFS->fdLog = 0;
  }

  zDel = lsmMallocPrintf(pFS->pEnv, "%s-log", pFS->zDb);
  if( zDel ){
    lsmEnvUnlink(pFS->pEnv, zDel);
    lsmFree(pFS->pEnv, zDel);
  }
  return LSM_OK;
}

/*
** Return true if page iReal of the database should be accessed using mmap.
** False otherwise.
*/
static int fsMmapPage(FileSystem *pFS, Pgno iReal){
  return ((i64)iReal*pFS->nPagesize <= pFS->nMapLimit);
}

/*
** Given that there are currently nHash slots in the hash table, return 
** the hash key for file iFile, page iPg.
*/
static int fsHashKey(int nHash, int iPg){
  return (iPg % nHash);
}

/*
** This is a helper function for lsmFsOpen(). It opens a single file on
** disk (either the database or log file).
*/
static lsm_file *fsOpenFile(
  FileSystem *pFS,                /* File system object */
  int bReadonly,                  /* True to open this file read-only */
  int bLog,                       /* True for log, false for db */
  int *pRc                        /* IN/OUT: Error code */
){
  lsm_file *pFile = 0;
  if( *pRc==LSM_OK ){
    int flags = (bReadonly ? LSM_OPEN_READONLY : 0);
    const char *zPath = (bLog ? pFS->zLog : pFS->zDb);

    *pRc = lsmEnvOpen(pFS->pEnv, zPath, flags, &pFile);
  }
  return pFile;
}

/*
** If it is not already open, this function opens the log file. It returns
** LSM_OK if successful (or if the log file was already open) or an LSM
** error code otherwise.
**
** The log file must be opened before any of the following may be called:
**
**     lsmFsWriteLog
**     lsmFsSyncLog
**     lsmFsReadLog
*/
int lsmFsOpenLog(lsm_db *db, int *pbOpen){
  int rc = LSM_OK;
  FileSystem *pFS = db->pFS;

  if( 0==pFS->fdLog ){ 
    pFS->fdLog = fsOpenFile(pFS, db->bReadonly, 1, &rc); 

    if( rc==LSM_IOERR_NOENT && db->bReadonly ){
      rc = LSM_OK;
    }
  }

  if( pbOpen ) *pbOpen = (pFS->fdLog!=0);
  return rc;
}

/*
** Close the log file, if it is open.
*/
void lsmFsCloseLog(lsm_db *db){
  FileSystem *pFS = db->pFS;
  if( pFS->fdLog ){
    lsmEnvClose(pFS->pEnv, pFS->fdLog);
    pFS->fdLog = 0;
  }
}

/*
** Open a connection to a database stored within the file-system.
**
** If parameter bReadonly is true, then open a read-only file-descriptor
** on the database file. It is possible that bReadonly will be false even
** if the user requested that pDb be opened read-only. This is because the
** file-descriptor may later on be recycled by a read-write connection.
** If the db file can be opened for read-write access, it always is. Parameter
** bReadonly is only ever true if it has already been determined that the
** db can only be opened for read-only access.
**
** Return LSM_OK if successful or an lsm error code otherwise.
*/
int lsmFsOpen(
  lsm_db *pDb,                    /* Database connection to open fd for */
  const char *zDb,                /* Full path to database file */
  int bReadonly                   /* True to open db file read-only */
){
  FileSystem *pFS;
  int rc = LSM_OK;
  int nDb = strlen(zDb);
  int nByte;

  assert( pDb->pFS==0 );
  assert( pDb->pWorker==0 && pDb->pClient==0 );

  nByte = sizeof(FileSystem) + nDb+1 + nDb+4+1;
  pFS = (FileSystem *)lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
  if( pFS ){
    LsmFile *pLsmFile;
    pFS->zDb = (char *)&pFS[1];
    pFS->zLog = &pFS->zDb[nDb+1];
    pFS->nPagesize = LSM_DFLT_PAGE_SIZE;
    pFS->nBlocksize = LSM_DFLT_BLOCK_SIZE;
    pFS->nMetasize = 4 * 1024;
    pFS->pDb = pDb;
    pFS->pEnv = pDb->pEnv;

    /* Make a copy of the database and log file names. */
    memcpy(pFS->zDb, zDb, nDb+1);
    memcpy(pFS->zLog, zDb, nDb);
    memcpy(&pFS->zLog[nDb], "-log", 5);

    /* Allocate the hash-table here. At some point, it should be changed
    ** so that it can grow dynamicly. */
    pFS->nCacheMax = 2048*1024 / pFS->nPagesize;
    pFS->nHash = 4096;
    pFS->apHash = lsmMallocZeroRc(pDb->pEnv, sizeof(Page *) * pFS->nHash, &rc);

    /* Open the database file */
    pLsmFile = lsmDbRecycleFd(pDb);
    if( pLsmFile ){
      pFS->pLsmFile = pLsmFile;
      pFS->fdDb = pLsmFile->pFile;
      memset(pLsmFile, 0, sizeof(LsmFile));
    }else{
      pFS->pLsmFile = lsmMallocZeroRc(pDb->pEnv, sizeof(LsmFile), &rc);
      if( rc==LSM_OK ){
        pFS->fdDb = fsOpenFile(pFS, bReadonly, 0, &rc);
      }
    }

    if( rc!=LSM_OK ){
      lsmFsClose(pFS);
      pFS = 0;
    }else{
      pFS->szSector = lsmEnvSectorSize(pFS->pEnv, pFS->fdDb);
    }
  }

  pDb->pFS = pFS;
  return rc;
}

/*
** Configure the file-system object according to the current values of
** the LSM_CONFIG_MMAP and LSM_CONFIG_SET_COMPRESSION options.
*/
int lsmFsConfigure(lsm_db *db){
  FileSystem *pFS = db->pFS;
  if( pFS ){
    lsm_env *pEnv = pFS->pEnv;
    Page *pPg;

    assert( pFS->nOut==0 );
    assert( pFS->pWaiting==0 );
    assert( pFS->pMapped==0 );

    /* Reset any compression/decompression buffers already allocated */
    lsmFree(pEnv, pFS->aIBuffer);
    lsmFree(pEnv, pFS->aOBuffer);
    pFS->nBuffer = 0;

    /* Unmap the file, if it is currently mapped */
    if( pFS->pMap ){
      lsmEnvRemap(pEnv, pFS->fdDb, -1, &pFS->pMap, &pFS->nMap);
      pFS->nMapLimit = 0;
    }

    /* Free all allocated page structures */
    pPg = pFS->pLruFirst;
    while( pPg ){
      Page *pNext = pPg->pLruNext;
      assert( pPg->flags & PAGE_FREE );
      lsmFree(pEnv, pPg->aData);
      lsmFree(pEnv, pPg);
      pPg = pNext;
    }

    pPg = pFS->pFree;
    while( pPg ){
      Page *pNext = pPg->pFreeNext;
      lsmFree(pEnv, pPg);
      pPg = pNext;
    }

    /* Zero pointers that point to deleted page objects */
    pFS->nCacheAlloc = 0;
    pFS->pLruFirst = 0;
    pFS->pLruLast = 0;
    pFS->pFree = 0;
    if( pFS->apHash ){
      memset(pFS->apHash, 0, pFS->nHash*sizeof(pFS->apHash[0]));
    }

    /* Configure the FileSystem object */
    if( db->compress.xCompress ){
      pFS->pCompress = &db->compress;
      pFS->nMapLimit = 0;
    }else{
      pFS->pCompress = 0;
      if( db->iMmap==1 ){
        /* Unlimited */
        pFS->nMapLimit = (i64)1 << 60;
      }else{
        /* iMmap is a limit in KB. Set nMapLimit to the same value in bytes. */
        pFS->nMapLimit = (i64)db->iMmap * 1024;
      }
    }
  }

  return LSM_OK;
}

/*
** Close and destroy a FileSystem object.
*/
void lsmFsClose(FileSystem *pFS){
  if( pFS ){
    Page *pPg;
    lsm_env *pEnv = pFS->pEnv;

    assert( pFS->nOut==0 );
    pPg = pFS->pLruFirst;
    while( pPg ){
      Page *pNext = pPg->pLruNext;
      if( pPg->flags & PAGE_FREE ) lsmFree(pEnv, pPg->aData);
      lsmFree(pEnv, pPg);
      pPg = pNext;
    }

    pPg = pFS->pFree;
    while( pPg ){
      Page *pNext = pPg->pFreeNext;
      if( pPg->flags & PAGE_FREE ) lsmFree(pEnv, pPg->aData);
      lsmFree(pEnv, pPg);
      pPg = pNext;
    }

    if( pFS->fdDb ) lsmEnvClose(pFS->pEnv, pFS->fdDb );
    if( pFS->fdLog ) lsmEnvClose(pFS->pEnv, pFS->fdLog );
    lsmFree(pEnv, pFS->pLsmFile);
    lsmFree(pEnv, pFS->apHash);
    lsmFree(pEnv, pFS->aIBuffer);
    lsmFree(pEnv, pFS->aOBuffer);
    lsmFree(pEnv, pFS);
  }
}

/*
** This function is called when closing a database handle (i.e. lsm_close()) 
** if there exist other connections to the same database within this process.
** In that case the file-descriptor open on the database file is not closed
** when the FileSystem object is destroyed, as this would cause any POSIX
** locks held by the other connections to be silently dropped (see "man close"
** for details). Instead, the file-descriptor is stored in a list by the
** lsm_shared.c module until it is either closed or reused.
**
** This function returns a pointer to an object that can be linked into
** the list described above. The returned object now 'owns' the database
** file descriptr, so that when the FileSystem object is destroyed, it
** will not be closed. 
**
** This function may be called at most once in the life-time of a 
** FileSystem object. The results of any operations involving the database 
** file descriptor are undefined once this function has been called.
**
** None of this is necessary on non-POSIX systems. But we do it anyway in
** the name of using as similar code as possible on all platforms.
*/
LsmFile *lsmFsDeferClose(FileSystem *pFS){
  LsmFile *p = pFS->pLsmFile;
  assert( p->pNext==0 );
  p->pFile = pFS->fdDb;
  pFS->fdDb = 0;
  pFS->pLsmFile = 0;
  return p;
}

/*
** Allocate a buffer and populate it with the output of the xFileid() 
** method of the database file handle. If successful, set *ppId to point 
** to the buffer and *pnId to the number of bytes in the buffer and return
** LSM_OK. Otherwise, set *ppId and *pnId to zero and return an LSM
** error code.
*/
int lsmFsFileid(lsm_db *pDb, void **ppId, int *pnId){
  lsm_env *pEnv = pDb->pEnv;
  FileSystem *pFS = pDb->pFS;
  int rc;
  int nId = 0;
  void *pId;

  rc = pEnv->xFileid(pFS->fdDb, 0, &nId);
  pId = lsmMallocZeroRc(pEnv, nId, &rc);
  if( rc==LSM_OK ) rc = pEnv->xFileid(pFS->fdDb, pId, &nId);

  if( rc!=LSM_OK ){
    lsmFree(pEnv, pId);
    pId = 0;
    nId = 0;
  }

  *ppId = pId;
  *pnId = nId;
  return rc;
}

/*
** Return the nominal page-size used by this file-system. Actual pages
** may be smaller or larger than this value.
*/
int lsmFsPageSize(FileSystem *pFS){
  return pFS->nPagesize;
}

/*
** Return the block-size used by this file-system.
*/
int lsmFsBlockSize(FileSystem *pFS){
  return pFS->nBlocksize;
}

/*
** Configure the nominal page-size used by this file-system. Actual 
** pages may be smaller or larger than this value.
*/
void lsmFsSetPageSize(FileSystem *pFS, int nPgsz){
  pFS->nPagesize = nPgsz;
  pFS->nCacheMax = 2048*1024 / pFS->nPagesize;
}

/*
** Configure the block-size used by this file-system. 
*/
void lsmFsSetBlockSize(FileSystem *pFS, int nBlocksize){
  pFS->nBlocksize = nBlocksize;
}

/*
** Return the page number of the first page on block iBlock. Blocks are
** numbered starting from 1.
**
** For a compressed database, page numbers are byte offsets. The first
** page on each block is the byte offset immediately following the 4-byte
** "previous block" pointer at the start of each block.
*/
static Pgno fsFirstPageOnBlock(FileSystem *pFS, int iBlock){
  Pgno iPg;
  if( pFS->pCompress ){
    if( iBlock==1 ){
      iPg = pFS->nMetasize * 2 + 4;
    }else{
      iPg = pFS->nBlocksize * (Pgno)(iBlock-1) + 4;
    }
  }else{
    const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
    if( iBlock==1 ){
      iPg = 1 + ((pFS->nMetasize*2 + pFS->nPagesize - 1) / pFS->nPagesize);
    }else{
      iPg = 1 + (iBlock-1) * nPagePerBlock;
    }
  }
  return iPg;
}

/*
** Return the page number of the last page on block iBlock. Blocks are
** numbered starting from 1.
**
** For a compressed database, page numbers are byte offsets. The first
** page on each block is the byte offset of the byte immediately before 
** the 4-byte "next block" pointer at the end of each block.
*/
static Pgno fsLastPageOnBlock(FileSystem *pFS, int iBlock){
  if( pFS->pCompress ){
    return pFS->nBlocksize * (Pgno)iBlock - 1 - 4;
  }else{
    const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
    return iBlock * nPagePerBlock;
  }
}

/*
** Return the block number of the block that page iPg is located on. 
** Blocks are numbered starting from 1.
*/
static int fsPageToBlock(FileSystem *pFS, Pgno iPg){
  if( pFS->pCompress ){
    return (iPg / pFS->nBlocksize) + 1;
  }else{
    return 1 + ((iPg-1) / (pFS->nBlocksize / pFS->nPagesize));
  }
}

/*
** Return true if page iPg is the last page on its block.
**
** This function is only called in non-compressed database mode.
*/
static int fsIsLast(FileSystem *pFS, Pgno iPg){
  const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
  assert( !pFS->pCompress );
  return ( iPg && (iPg % nPagePerBlock)==0 );
}

/*
** Return true if page iPg is the first page on its block.
**
** This function is only called in non-compressed database mode.
*/
static int fsIsFirst(FileSystem *pFS, Pgno iPg){
  const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
  assert( !pFS->pCompress );
  return ( (iPg % nPagePerBlock)==1
        || (iPg<nPagePerBlock && iPg==fsFirstPageOnBlock(pFS, 1))
  );
}

/*
** Given a page reference, return a pointer to the buffer containing the 
** pages contents. If parameter pnData is not NULL, set *pnData to the size
** of the buffer in bytes before returning.
*/
u8 *lsmFsPageData(Page *pPage, int *pnData){
  if( pnData ){
    *pnData = pPage->nData;
  }
  return pPage->aData;
}

/*
** Return the page number of a page.
*/
Pgno lsmFsPageNumber(Page *pPage){
  /* assert( (pPage->flags & PAGE_DIRTY)==0 ); */
  return pPage ? pPage->iPg : 0;
}

/*
** Page pPg is currently part of the LRU list belonging to pFS. Remove
** it from the list. pPg->pLruNext and pPg->pLruPrev are cleared by this
** operation.
*/
static void fsPageRemoveFromLru(FileSystem *pFS, Page *pPg){
  assert( pPg->pLruNext || pPg==pFS->pLruLast );
  assert( pPg->pLruPrev || pPg==pFS->pLruFirst );
  if( pPg->pLruNext ){
    pPg->pLruNext->pLruPrev = pPg->pLruPrev;
  }else{
    pFS->pLruLast = pPg->pLruPrev;
  }
  if( pPg->pLruPrev ){
    pPg->pLruPrev->pLruNext = pPg->pLruNext;
  }else{
    pFS->pLruFirst = pPg->pLruNext;
  }
  pPg->pLruPrev = 0;
  pPg->pLruNext = 0;
}

/*
** Page pPg is not currently part of the LRU list belonging to pFS. Add it.
*/
static void fsPageAddToLru(FileSystem *pFS, Page *pPg){
  assert( pPg->pLruNext==0 && pPg->pLruPrev==0 );
  pPg->pLruPrev = pFS->pLruLast;
  if( pPg->pLruPrev ){
    pPg->pLruPrev->pLruNext = pPg;
  }else{
    pFS->pLruFirst = pPg;
  }
  pFS->pLruLast = pPg;
}

/*
** Page pPg is currently stored in the apHash/nHash hash table. Remove it.
*/
static void fsPageRemoveFromHash(FileSystem *pFS, Page *pPg){
  int iHash;
  Page **pp;

  iHash = fsHashKey(pFS->nHash, pPg->iPg);
  for(pp=&pFS->apHash[iHash]; *pp!=pPg; pp=&(*pp)->pHashNext);
  *pp = pPg->pHashNext;
  pPg->pHashNext = 0;
}

/*
** Free a Page object allocated by fsPageBuffer().
*/
static void fsPageBufferFree(Page *pPg){
  pPg->pFS->nCacheAlloc--;
  lsmFree(pPg->pFS->pEnv, pPg->aData);
  lsmFree(pPg->pFS->pEnv, pPg);
}


/*
** Purge the cache of all non-mmap pages with nRef==0.
*/
void lsmFsPurgeCache(FileSystem *pFS){
  Page *pPg;

  pPg = pFS->pLruFirst;
  while( pPg ){
    Page *pNext = pPg->pLruNext;
    assert( pPg->flags & PAGE_FREE );
    fsPageRemoveFromHash(pFS, pPg);
    fsPageBufferFree(pPg);
    pPg = pNext;
  }
  pFS->pLruFirst = 0;
  pFS->pLruLast = 0;

  assert( pFS->nCacheAlloc<=pFS->nOut && pFS->nCacheAlloc>=0 );
}

/*
** Search the hash-table for page iPg. If an entry is round, return a pointer
** to it. Otherwise, return NULL.
**
** Either way, if argument piHash is not NULL set *piHash to the hash slot
** number that page iPg would be stored in before returning.
*/
static Page *fsPageFindInHash(FileSystem *pFS, Pgno iPg, int *piHash){
  Page *p;                        /* Return value */
  int iHash = fsHashKey(pFS->nHash, iPg);

  if( piHash ) *piHash = iHash;
  for(p=pFS->apHash[iHash]; p; p=p->pHashNext){
    if( p->iPg==iPg) break;
  }
  return p;
}

/*
** Allocate and return a non-mmap Page object. If there are already 
** nCacheMax such Page objects outstanding, try to recycle an existing 
** Page instead.
*/
static int fsPageBuffer(
  FileSystem *pFS, 
  Page **ppOut
){
  int rc = LSM_OK;
  Page *pPage = 0;
  if( pFS->pLruFirst==0 || pFS->nCacheAlloc<pFS->nCacheMax ){
    /* Allocate a new Page object */
    pPage = lsmMallocZero(pFS->pEnv, sizeof(Page));
    if( !pPage ){
      rc = LSM_NOMEM_BKPT;
    }else{
      pPage->aData = (u8 *)lsmMalloc(pFS->pEnv, pFS->nPagesize);
      if( !pPage->aData ){
        lsmFree(pFS->pEnv, pPage);
        rc = LSM_NOMEM_BKPT;
        pPage = 0;
      }else{
        pFS->nCacheAlloc++;
      }
    }
  }else{
    /* Reuse an existing Page object */
    u8 *aData;
    pPage = pFS->pLruFirst;
    aData = pPage->aData;
    fsPageRemoveFromLru(pFS, pPage);
    fsPageRemoveFromHash(pFS, pPage);

    memset(pPage, 0, sizeof(Page));
    pPage->aData = aData;
  }

  if( pPage ){
    pPage->flags = PAGE_FREE;
  }
  *ppOut = pPage;
  return rc;
}

/*
** Assuming *pRc is initially LSM_OK, attempt to ensure that the 
** memory-mapped region is at least iSz bytes in size. If it is not already,
** iSz bytes in size, extend it and update the pointers associated with any
** outstanding Page objects.
**
** If *pRc is not LSM_OK when this function is called, it is a no-op. 
** Otherwise, *pRc is set to an lsm error code if an error occurs, or
** left unmodified otherwise.
**
** This function is never called in compressed database mode.
*/
static void fsGrowMapping(
  FileSystem *pFS,                /* File system object */
  i64 iSz,                        /* Minimum size to extend mapping to */
  int *pRc                        /* IN/OUT: Error code */
){
  assert( pFS->pCompress==0 );
  assert( PAGE_HASPREV==4 );

  if( *pRc==LSM_OK && iSz>pFS->nMap ){
    int rc;
    u8 *aOld = pFS->pMap;
    rc = lsmEnvRemap(pFS->pEnv, pFS->fdDb, iSz, &pFS->pMap, &pFS->nMap);
    if( rc==LSM_OK && pFS->pMap!=aOld ){
      Page *pFix;
      i64 iOff = (u8 *)pFS->pMap - aOld;
      for(pFix=pFS->pMapped; pFix; pFix=pFix->pMappedNext){
        pFix->aData += iOff;
      }
      lsmSortedRemap(pFS->pDb);
    }
    *pRc = rc;
  }
}

/*
** fsync() the database file.
*/
int lsmFsSyncDb(FileSystem *pFS, int nBlock){
  return lsmEnvSync(pFS->pEnv, pFS->fdDb);
}

/*
** If block iBlk has been redirected according to the redirections in the
** object passed as the first argument, return the destination block to
** which it is redirected. Otherwise, return a copy of iBlk.
*/
static int fsRedirectBlock(Redirect *p, int iBlk){
  if( p ){
    int i;
    for(i=0; i<p->n; i++){
      if( iBlk==p->a[i].iFrom ) return p->a[i].iTo;
    }
  }
  assert( iBlk!=0 );
  return iBlk;
}

/*
** If page iPg has been redirected according to the redirections in the
** object passed as the second argument, return the destination page to
** which it is redirected. Otherwise, return a copy of iPg.
*/
Pgno lsmFsRedirectPage(FileSystem *pFS, Redirect *pRedir, Pgno iPg){
  Pgno iReal = iPg;

  if( pRedir ){
    const int nPagePerBlock = (
        pFS->pCompress ? pFS->nBlocksize : (pFS->nBlocksize / pFS->nPagesize)
    );
    int iBlk = fsPageToBlock(pFS, iPg);
    int i;
    for(i=0; i<pRedir->n; i++){
      int iFrom = pRedir->a[i].iFrom;
      if( iFrom>iBlk ) break;
      if( iFrom==iBlk ){
        int iTo = pRedir->a[i].iTo;
        iReal = iPg - (Pgno)(iFrom - iTo) * nPagePerBlock;
        if( iTo==1 ){
          iReal += (fsFirstPageOnBlock(pFS, 1)-1);
        }
        break;
      }
    }
  }

  assert( iReal!=0 );
  return iReal;
}

/* Required by the circular fsBlockNext<->fsPageGet dependency. */
static int fsPageGet(FileSystem *, Segment *, Pgno, int, Page **, int *);

/*
** Parameter iBlock is a database file block. This function reads the value 
** stored in the blocks "next block" pointer and stores it in *piNext.
** LSM_OK is returned if everything is successful, or an LSM error code
** otherwise.
*/
static int fsBlockNext(
  FileSystem *pFS,                /* File-system object handle */
  Segment *pSeg,                  /* Use this segment for block redirects */
  int iBlock,                     /* Read field from this block */
  int *piNext                     /* OUT: Next block in linked list */
){
  int rc;
  int iRead;                      /* Read block from here */
  
  if( pSeg ){
    iRead = fsRedirectBlock(pSeg->pRedirect, iBlock);
  }else{
    iRead = iBlock;
  }

  assert( pFS->nMapLimit==0 || pFS->pCompress==0 );
  if( pFS->pCompress ){
    i64 iOff;                     /* File offset to read data from */
    u8 aNext[4];                  /* 4-byte pointer read from db file */

    iOff = (i64)iRead * pFS->nBlocksize - sizeof(aNext);
    rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aNext, sizeof(aNext));
    if( rc==LSM_OK ){
      *piNext = (int)lsmGetU32(aNext);
    }
  }else{
    const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
    Page *pLast;
    rc = fsPageGet(pFS, 0, iRead*nPagePerBlock, 0, &pLast, 0);
    if( rc==LSM_OK ){
      *piNext = lsmGetU32(&pLast->aData[pFS->nPagesize-4]);
      lsmFsPageRelease(pLast);
    }
  }

  if( pSeg ){
    *piNext = fsRedirectBlock(pSeg->pRedirect, *piNext);
  }
  return rc;
}

/*
** Return the page number of the last page on the same block as page iPg.
*/
Pgno fsLastPageOnPagesBlock(FileSystem *pFS, Pgno iPg){
  return fsLastPageOnBlock(pFS, fsPageToBlock(pFS, iPg));
}

/*
** Read nData bytes of data from offset iOff of the database file into
** buffer aData. If this means reading past the end of a block, follow
** the block pointer to the next block and continue reading.
**
** Offset iOff is an absolute offset - not subject to any block redirection.
** However any block pointer followed is. Use pSeg->pRedirect in this case.
**
** This function is only called in compressed database mode.
*/
static int fsReadData(
  FileSystem *pFS,                /* File-system handle */
  Segment *pSeg,                  /* Block redirection */
  i64 iOff,                       /* Read data from this offset */
  u8 *aData,                      /* Buffer to read data into */
  int nData                       /* Number of bytes to read */
){
  i64 iEob;                       /* End of block */
  int nRead;
  int rc;

  assert( pFS->pCompress );

  iEob = fsLastPageOnPagesBlock(pFS, iOff) + 1;
  nRead = LSM_MIN(iEob - iOff, nData);

  rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aData, nRead);
  if( rc==LSM_OK && nRead!=nData ){
    int iBlk;

    rc = fsBlockNext(pFS, pSeg, fsPageToBlock(pFS, iOff), &iBlk);
    if( rc==LSM_OK ){
      i64 iOff2 = fsFirstPageOnBlock(pFS, iBlk);
      rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff2, &aData[nRead], nData-nRead);
    }
  }

  return rc;
}

/*
** Parameter iBlock is a database file block. This function reads the value 
** stored in the blocks "previous block" pointer and stores it in *piPrev.
** LSM_OK is returned if everything is successful, or an LSM error code
** otherwise.
*/
static int fsBlockPrev(
  FileSystem *pFS,                /* File-system object handle */
  Segment *pSeg,                  /* Use this segment for block redirects */
  int iBlock,                     /* Read field from this block */
  int *piPrev                     /* OUT: Previous block in linked list */
){
  int rc = LSM_OK;                /* Return code */

  assert( pFS->nMapLimit==0 || pFS->pCompress==0 );
  assert( iBlock>0 );

  if( pFS->pCompress ){
    i64 iOff = fsFirstPageOnBlock(pFS, iBlock) - 4;
    u8 aPrev[4];                  /* 4-byte pointer read from db file */
    rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aPrev, sizeof(aPrev));
    if( rc==LSM_OK ){
      Redirect *pRedir = (pSeg ? pSeg->pRedirect : 0);
      *piPrev = fsRedirectBlock(pRedir, (int)lsmGetU32(aPrev));
    }
  }else{
    assert( 0 );
  }
  return rc;
}

/*
** Encode and decode routines for record size fields.
*/
static void putRecordSize(u8 *aBuf, int nByte, int bFree){
  aBuf[0] = (u8)(nByte >> 14) | 0x80;
  aBuf[1] = ((u8)(nByte >>  7) & 0x7F) | (bFree ? 0x00 : 0x80);
  aBuf[2] = (u8)nByte | 0x80;
}
static int getRecordSize(u8 *aBuf, int *pbFree){
  int nByte;
  nByte  = (aBuf[0] & 0x7F) << 14;
  nByte += (aBuf[1] & 0x7F) << 7;
  nByte += (aBuf[2] & 0x7F);
  *pbFree = !(aBuf[1] & 0x80);
  return nByte;
}

/*
** Subtract iSub from database file offset iOff and set *piRes to the
** result. If doing so means passing the start of a block, follow the
** block pointer stored in the first 4 bytes of the block.
**
** Offset iOff is an absolute offset - not subject to any block redirection.
** However any block pointer followed is. Use pSeg->pRedirect in this case.
**
** Return LSM_OK if successful or an lsm error code if an error occurs.
*/
static int fsSubtractOffset(
  FileSystem *pFS, 
  Segment *pSeg,
  i64 iOff, 
  int iSub, 
  i64 *piRes
){
  i64 iStart;
  int iBlk = 0;
  int rc;

  assert( pFS->pCompress );

  iStart = fsFirstPageOnBlock(pFS, fsPageToBlock(pFS, iOff));
  if( (iOff-iSub)>=iStart ){
    *piRes = (iOff-iSub);
    return LSM_OK;
  }

  rc = fsBlockPrev(pFS, pSeg, fsPageToBlock(pFS, iOff), &iBlk);
  *piRes = fsLastPageOnBlock(pFS, iBlk) - iSub + (iOff - iStart + 1);
  return rc;
}

/*
** Add iAdd to database file offset iOff and set *piRes to the
** result. If doing so means passing the end of a block, follow the
** block pointer stored in the last 4 bytes of the block.
**
** Offset iOff is an absolute offset - not subject to any block redirection.
** However any block pointer followed is. Use pSeg->pRedirect in this case.
**
** Return LSM_OK if successful or an lsm error code if an error occurs.
*/
static int fsAddOffset(
  FileSystem *pFS, 
  Segment *pSeg,
  i64 iOff, 
  int iAdd, 
  i64 *piRes
){
  i64 iEob;
  int iBlk;
  int rc;

  assert( pFS->pCompress );

  iEob = fsLastPageOnPagesBlock(pFS, iOff);
  if( (iOff+iAdd)<=iEob ){
    *piRes = (iOff+iAdd);
    return LSM_OK;
  }

  rc = fsBlockNext(pFS, pSeg, fsPageToBlock(pFS, iOff), &iBlk);
  *piRes = fsFirstPageOnBlock(pFS, iBlk) + iAdd - (iEob - iOff + 1);
  return rc;
}

/*
** If it is not already allocated, allocate either the FileSystem.aOBuffer (if
** bWrite is true) or the FileSystem.aIBuffer (if bWrite is false). Return
** LSM_OK if successful if the attempt to allocate memory fails.
*/
static int fsAllocateBuffer(FileSystem *pFS, int bWrite){
  u8 **pp;                        /* Pointer to either aIBuffer or aOBuffer */

  assert( pFS->pCompress );

  /* If neither buffer has been allocated, figure out how large they
  ** should be. Store this value in FileSystem.nBuffer.  */
  if( pFS->nBuffer==0 ){
    assert( pFS->aIBuffer==0 && pFS->aOBuffer==0 );
    pFS->nBuffer = pFS->pCompress->xBound(pFS->pCompress->pCtx, pFS->nPagesize);
    if( pFS->nBuffer<(pFS->szSector+6) ){
      pFS->nBuffer = pFS->szSector+6;
    }
  }

  pp = (bWrite ? &pFS->aOBuffer : &pFS->aIBuffer);
  if( *pp==0 ){
    *pp = lsmMalloc(pFS->pEnv, LSM_MAX(pFS->nBuffer, pFS->nPagesize));
    if( *pp==0 ) return LSM_NOMEM_BKPT;
  }

  return LSM_OK;
}

/*
** This function is only called in compressed database mode. It reads and
** uncompresses the compressed data for page pPg from the database and
** populates the pPg->aData[] buffer and pPg->nCompress field.
**
** It is possible that instead of a page record, there is free space
** at offset pPg->iPgno. In this case no data is read from the file, but
** output variable *pnSpace is set to the total number of free bytes.
**
** LSM_OK is returned if successful, or an LSM error code otherwise.
*/
static int fsReadPagedata(
  FileSystem *pFS,                /* File-system handle */
  Segment *pSeg,                  /* pPg is part of this segment */
  Page *pPg,                      /* Page to read and uncompress data for */
  int *pnSpace                    /* OUT: Total bytes of free space */
){
  lsm_compress *p = pFS->pCompress;
  i64 iOff = pPg->iPg;
  u8 aSz[3];
  int rc;

  assert( p && pPg->nCompress==0 );

  if( fsAllocateBuffer(pFS, 0) ) return LSM_NOMEM;

  rc = fsReadData(pFS, pSeg, iOff, aSz, sizeof(aSz));

  if( rc==LSM_OK ){
    int bFree;
    if( aSz[0] & 0x80 ){
      pPg->nCompress = (int)getRecordSize(aSz, &bFree);
    }else{
      pPg->nCompress = (int)aSz[0] - sizeof(aSz)*2;
      bFree = 1;
    }
    if( bFree ){
      if( pnSpace ){
        *pnSpace = pPg->nCompress + sizeof(aSz)*2;
      }else{
        rc = LSM_CORRUPT_BKPT;
      }
    }else{
      rc = fsAddOffset(pFS, pSeg, iOff, 3, &iOff);
      if( rc==LSM_OK ){
        if( pPg->nCompress>pFS->nBuffer ){
          rc = LSM_CORRUPT_BKPT;
        }else{
          rc = fsReadData(pFS, pSeg, iOff, pFS->aIBuffer, pPg->nCompress);
        }
        if( rc==LSM_OK ){
          int n = pFS->nPagesize;
          rc = p->xUncompress(p->pCtx, 
              (char *)pPg->aData, &n, 
              (const char *)pFS->aIBuffer, pPg->nCompress
          );
          if( rc==LSM_OK && n!=pPg->pFS->nPagesize ){
            rc = LSM_CORRUPT_BKPT;
          }
        }
      }
    }
  }
  return rc;
}

/*
** Return a handle for a database page.
**
** If this file-system object is accessing a compressed database it may be
** that there is no page record at database file offset iPg. Instead, there
** may be a free space record. In this case, set *ppPg to NULL and *pnSpace
** to the total number of free bytes before returning.
**
** If no error occurs, LSM_OK is returned. Otherwise, an lsm error code.
*/
static int fsPageGet(
  FileSystem *pFS,                /* File-system handle */
  Segment *pSeg,                  /* Block redirection to use (or NULL) */
  Pgno iPg,                       /* Page id */
  int noContent,                  /* True to not load content from disk */
  Page **ppPg,                    /* OUT: New page handle */
  int *pnSpace                    /* OUT: Bytes of free space */
){
  Page *p;
  int iHash;
  int rc = LSM_OK;

  /* In most cases iReal is the same as iPg. Except, if pSeg->pRedirect is 
  ** not NULL, and the block containing iPg has been redirected, then iReal
  ** is the page number after redirection.  */
  Pgno iReal = lsmFsRedirectPage(pFS, (pSeg ? pSeg->pRedirect : 0), iPg);

  assert_lists_are_ok(pFS);
  assert( iPg>=fsFirstPageOnBlock(pFS, 1) );
  assert( iReal>=fsFirstPageOnBlock(pFS, 1) );
  *ppPg = 0;

  /* Search the hash-table for the page */
  p = fsPageFindInHash(pFS, iReal, &iHash);

  if( p ){
    assert( p->flags & PAGE_FREE );
    if( p->nRef==0 ) fsPageRemoveFromLru(pFS, p);
  }else{

    if( fsMmapPage(pFS, iReal) ){
      i64 iEnd = (i64)iReal * pFS->nPagesize;
      fsGrowMapping(pFS, iEnd, &rc);
      if( rc!=LSM_OK ) return rc;

      if( pFS->pFree ){
        p = pFS->pFree;
        pFS->pFree = p->pFreeNext;
        assert( p->nRef==0 );
      }else{
        p = lsmMallocZeroRc(pFS->pEnv, sizeof(Page), &rc);
        if( rc ) return rc;
        p->pFS = pFS;
      }
      p->aData = &((u8 *)pFS->pMap)[pFS->nPagesize * (iReal-1)];
      p->iPg = iReal;

      /* This page now carries a pointer to the mapping. Link it in to
      ** the FileSystem.pMapped list.  */
      assert( p->pMappedNext==0 );
      p->pMappedNext = pFS->pMapped;
      pFS->pMapped = p;

      assert( pFS->pCompress==0 );
      assert( (p->flags & PAGE_FREE)==0 );
    }else{
      rc = fsPageBuffer(pFS, &p);
      if( rc==LSM_OK ){
        int nSpace = 0;
        p->iPg = iReal;
        p->nRef = 0;
        p->pFS = pFS;
        assert( p->flags==0 || p->flags==PAGE_FREE );

#ifdef LSM_DEBUG
        memset(p->aData, 0x56, pFS->nPagesize);
#endif
        assert( p->pLruNext==0 && p->pLruPrev==0 );
        if( noContent==0 ){
          if( pFS->pCompress ){
            rc = fsReadPagedata(pFS, pSeg, p, &nSpace);
          }else{
            int nByte = pFS->nPagesize;
            i64 iOff = (i64)(iReal-1) * pFS->nPagesize;
            rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, p->aData, nByte);
          }
          pFS->nRead++;
        }

        /* If the xRead() call was successful (or not attempted), link the
        ** page into the page-cache hash-table. Otherwise, if it failed,
        ** free the buffer. */
        if( rc==LSM_OK && nSpace==0 ){
          p->pHashNext = pFS->apHash[iHash];
          pFS->apHash[iHash] = p;
        }else{
          fsPageBufferFree(p);
          p = 0;
          if( pnSpace ) *pnSpace = nSpace;
        }
      }
    }

    assert( (rc==LSM_OK && (p || (pnSpace && *pnSpace)))
         || (rc!=LSM_OK && p==0) 
    );
  }

  if( rc==LSM_OK && p ){
    if( pFS->pCompress==0 && (fsIsLast(pFS, iReal) || fsIsFirst(pFS, iReal)) ){
      p->nData = pFS->nPagesize - 4;
      if( fsIsFirst(pFS, iReal) && p->nRef==0 ){
        p->aData += 4;
        p->flags |= PAGE_HASPREV;
      }
    }else{
      p->nData = pFS->nPagesize;
    }
    pFS->nOut += (p->nRef==0);
    p->nRef++;
  }
  *ppPg = p;
  return rc;
}

/*
** Read the 64-bit checkpoint id of the checkpoint currently stored on meta
** page iMeta of the database file. If no error occurs, store the id value
** in *piVal and return LSM_OK. Otherwise, return an LSM error code and leave
** *piVal unmodified.
**
** If a checkpointer connection is currently updating meta-page iMeta, or an
** earlier checkpointer crashed while doing so, the value read into *piVal
** may be garbage. It is the callers responsibility to deal with this.
*/
int lsmFsReadSyncedId(lsm_db *db, int iMeta, i64 *piVal){
  FileSystem *pFS = db->pFS;
  int rc = LSM_OK;

  assert( iMeta==1 || iMeta==2 );
  if( pFS->nMapLimit>0 ){
    fsGrowMapping(pFS, iMeta*LSM_META_PAGE_SIZE, &rc);
    if( rc==LSM_OK ){
      *piVal = (i64)lsmGetU64(&((u8 *)pFS->pMap)[(iMeta-1)*LSM_META_PAGE_SIZE]);
    }
  }else{
    MetaPage *pMeta = 0;
    rc = lsmFsMetaPageGet(pFS, 0, iMeta, &pMeta);
    if( rc==LSM_OK ){
      *piVal = (i64)lsmGetU64(pMeta->aData);
      lsmFsMetaPageRelease(pMeta);
    }
  }

  return rc;
}


/*
** Return true if the first or last page of segment pRun falls between iFirst
** and iLast, inclusive, and pRun is not equal to pIgnore.
*/
static int fsRunEndsBetween(
  Segment *pRun, 
  Segment *pIgnore, 
  Pgno iFirst, 
  Pgno iLast
){
  return (pRun!=pIgnore && (
        (pRun->iFirst>=iFirst && pRun->iFirst<=iLast)
     || (pRun->iLastPg>=iFirst && pRun->iLastPg<=iLast)
  ));
}

/*
** Return true if level pLevel contains a segment other than pIgnore for
** which the first or last page is between iFirst and iLast, inclusive.
*/
static int fsLevelEndsBetween(
  Level *pLevel, 
  Segment *pIgnore, 
  Pgno iFirst, 
  Pgno iLast
){
  int i;

  if( fsRunEndsBetween(&pLevel->lhs, pIgnore, iFirst, iLast) ){
    return 1;
  }
  for(i=0; i<pLevel->nRight; i++){
    if( fsRunEndsBetween(&pLevel->aRhs[i], pIgnore, iFirst, iLast) ){
      return 1;
    }
  }

  return 0;
}

/*
** Block iBlk is no longer in use by segment pIgnore. If it is not in use
** by any other segment, move it to the free block list.
*/
static int fsFreeBlock(
  FileSystem *pFS,                /* File system object */
  Snapshot *pSnapshot,            /* Worker snapshot */
  Segment *pIgnore,               /* Ignore this run when searching */
  int iBlk                        /* Block number of block to free */
){
  int rc = LSM_OK;                /* Return code */
  int iFirst;                     /* First page on block iBlk */
  int iLast;                      /* Last page on block iBlk */
  Level *pLevel;                  /* Used to iterate through levels */

  int iIn;                        /* Used to iterate through append points */
  int iOut = 0;                   /* Used to output append points */
  Pgno *aApp = pSnapshot->aiAppend;

  iFirst = fsFirstPageOnBlock(pFS, iBlk);
  iLast = fsLastPageOnBlock(pFS, iBlk);

  /* Check if any other run in the snapshot has a start or end page 
  ** within this block. If there is such a run, return early. */
  for(pLevel=lsmDbSnapshotLevel(pSnapshot); pLevel; pLevel=pLevel->pNext){
    if( fsLevelEndsBetween(pLevel, pIgnore, iFirst, iLast) ){
      return LSM_OK;
    }
  }

  /* Remove any entries that lie on this block from the append-list. */
  for(iIn=0; iIn<LSM_APPLIST_SZ; iIn++){
    if( aApp[iIn]<iFirst || aApp[iIn]>iLast ){
      aApp[iOut++] = aApp[iIn];
    }
  }
  while( iOut<LSM_APPLIST_SZ ) aApp[iOut++] = 0;

  if( rc==LSM_OK ){
    rc = lsmBlockFree(pFS->pDb, iBlk);
  }
  return rc;
}

/*
** Delete or otherwise recycle the blocks currently occupied by run pDel.
*/
int lsmFsSortedDelete(
  FileSystem *pFS, 
  Snapshot *pSnapshot,
  int bZero,                      /* True to zero the Segment structure */
  Segment *pDel
){
  if( pDel->iFirst ){
    int rc = LSM_OK;

    int iBlk;
    int iLastBlk;

    iBlk = fsPageToBlock(pFS, pDel->iFirst);
    iLastBlk = fsPageToBlock(pFS, pDel->iLastPg);

    /* Mark all blocks currently used by this sorted run as free */
    while( iBlk && rc==LSM_OK ){
      int iNext = 0;
      if( iBlk!=iLastBlk ){
        rc = fsBlockNext(pFS, pDel, iBlk, &iNext);
      }else if( bZero==0 && pDel->iLastPg!=fsLastPageOnBlock(pFS, iLastBlk) ){
        break;
      }
      rc = fsFreeBlock(pFS, pSnapshot, pDel, iBlk);
      iBlk = iNext;
    }

    if( pDel->pRedirect ){
      assert( pDel->pRedirect==&pSnapshot->redirect );
      pSnapshot->redirect.n = 0;
    }

    if( bZero ) memset(pDel, 0, sizeof(Segment));
  }
  return LSM_OK;
}

/*
** aPgno is an array containing nPgno page numbers. Return the smallest page
** number from the array that falls on block iBlk. Or, if none of the pages
** in aPgno[] fall on block iBlk, return 0.
*/
static Pgno firstOnBlock(FileSystem *pFS, int iBlk, Pgno *aPgno, int nPgno){
  Pgno iRet = 0;
  int i;
  for(i=0; i<nPgno; i++){
    Pgno iPg = aPgno[i];
    if( fsPageToBlock(pFS, iPg)==iBlk && (iRet==0 || iPg<iRet) ){
      iRet = iPg;
    }
  }
  return iRet;
}

#ifndef NDEBUG
/*
** Return true if page iPg, which is a part of segment p, lies on
** a redirected block. 
*/
static int fsPageRedirects(FileSystem *pFS, Segment *p, Pgno iPg){
  return (iPg!=0 && iPg!=lsmFsRedirectPage(pFS, p->pRedirect, iPg));
}

/*
** Return true if the second argument is not NULL and any of the first
** last or root pages lie on a redirected block. 
*/
static int fsSegmentRedirects(FileSystem *pFS, Segment *p){
  return (p && (
      fsPageRedirects(pFS, p, p->iFirst)
   || fsPageRedirects(pFS, p, p->iRoot)
   || fsPageRedirects(pFS, p, p->iLastPg)
  ));
}
#endif

/*
** Argument aPgno is an array of nPgno page numbers. All pages belong to
** the segment pRun. This function gobbles from the start of the run to the
** first page that appears in aPgno[] (i.e. so that the aPgno[] entry is
** the new first page of the run).
*/
void lsmFsGobble(
  lsm_db *pDb,
  Segment *pRun, 
  Pgno *aPgno,
  int nPgno
){
  int rc = LSM_OK;
  FileSystem *pFS = pDb->pFS;
  Snapshot *pSnapshot = pDb->pWorker;
  int iBlk;

  assert( pRun->nSize>0 );
  assert( 0==fsSegmentRedirects(pFS, pRun) );
  assert( nPgno>0 && 0==fsPageRedirects(pFS, pRun, aPgno[0]) );

  iBlk = fsPageToBlock(pFS, pRun->iFirst);
  pRun->nSize += (pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));

  while( rc==LSM_OK ){
    int iNext = 0;
    Pgno iFirst = firstOnBlock(pFS, iBlk, aPgno, nPgno);
    if( iFirst ){
      pRun->iFirst = iFirst;
      break;
    }
    rc = fsBlockNext(pFS, pRun, iBlk, &iNext);
    if( rc==LSM_OK ) rc = fsFreeBlock(pFS, pSnapshot, pRun, iBlk);
    pRun->nSize -= (
        1 + fsLastPageOnBlock(pFS, iBlk) - fsFirstPageOnBlock(pFS, iBlk)
    );
    iBlk = iNext;
  }

  pRun->nSize -= (pRun->iFirst - fsFirstPageOnBlock(pFS, iBlk));
  assert( pRun->nSize>0 );
}

/*
** This function is only used in compressed database mode.
**
** Argument iPg is the page number (byte offset) of a page within segment
** pSeg. The page record, including all headers, is nByte bytes in size.
** Before returning, set *piNext to the page number of the next page in
** the segment, or to zero if iPg is the last.
**
** In other words, do:
**
**   *piNext = iPg + nByte;
**
** But take block overflow and redirection into account.
*/
static int fsNextPageOffset(
  FileSystem *pFS,                /* File system object */
  Segment *pSeg,                  /* Segment to move within */
  Pgno iPg,                       /* Offset of current page */
  int nByte,                      /* Size of current page including headers */
  Pgno *piNext                    /* OUT: Offset of next page. Or zero (EOF) */
){
  Pgno iNext;
  int rc;

  assert( pFS->pCompress );

  rc = fsAddOffset(pFS, pSeg, iPg, nByte-1, &iNext);
  if( pSeg && iNext==pSeg->iLastPg ){
    iNext = 0;
  }else if( rc==LSM_OK ){
    rc = fsAddOffset(pFS, pSeg, iNext, 1, &iNext);
  }

  *piNext = iNext;
  return rc;
}

/*
** This function is only used in compressed database mode.
**
** Argument iPg is the page number of a pagethat appears in segment pSeg.
** This function determines the page number of the previous page in the
** same run. *piPrev is set to the previous page number before returning.
**
** LSM_OK is returned if no error occurs. Otherwise, an lsm error code.
** If any value other than LSM_OK is returned, then the final value of
** *piPrev is undefined.
*/
static int fsGetPageBefore(
  FileSystem *pFS, 
  Segment *pSeg, 
  Pgno iPg, 
  Pgno *piPrev
){
  u8 aSz[3];
  int rc;
  i64 iRead;

  assert( pFS->pCompress );

  rc = fsSubtractOffset(pFS, pSeg, iPg, sizeof(aSz), &iRead);
  if( rc==LSM_OK ) rc = fsReadData(pFS, pSeg, iRead, aSz, sizeof(aSz));

  if( rc==LSM_OK ){
    int bFree;
    int nSz;
    if( aSz[2] & 0x80 ){
      nSz = getRecordSize(aSz, &bFree) + sizeof(aSz)*2;
    }else{
      nSz = (int)(aSz[2] & 0x7F);
      bFree = 1;
    }
    rc = fsSubtractOffset(pFS, pSeg, iPg, nSz, piPrev);
  }

  return rc;
}

/*
** The first argument to this function is a valid reference to a database
** file page that is part of a sorted run. If parameter eDir is -1, this 
** function attempts to locate and load the previous page in the same run. 
** Or, if eDir is +1, it attempts to find the next page in the same run.
** The results of passing an eDir value other than positive or negative one
** are undefined.
**
** If parameter pRun is not NULL then it must point to the run that page
** pPg belongs to. In this case, if pPg is the first or last page of the
** run, and the request is for the previous or next page, respectively,
** *ppNext is set to NULL before returning LSM_OK. If pRun is NULL, then it
** is assumed that the next or previous page, as requested, exists.
**
** If the previous/next page does exist and is successfully loaded, *ppNext
** is set to point to it and LSM_OK is returned. Otherwise, if an error 
** occurs, *ppNext is set to NULL and and lsm error code returned.
**
** Page references returned by this function should be released by the 
** caller using lsmFsPageRelease().
*/
int lsmFsDbPageNext(Segment *pRun, Page *pPg, int eDir, Page **ppNext){
  int rc = LSM_OK;
  FileSystem *pFS = pPg->pFS;
  Pgno iPg = pPg->iPg;

  assert( 0==fsSegmentRedirects(pFS, pRun) );
  if( pFS->pCompress ){
    int nSpace = pPg->nCompress + 2*3;

    do {
      if( eDir>0 ){
        rc = fsNextPageOffset(pFS, pRun, iPg, nSpace, &iPg);
      }else{
        if( iPg==pRun->iFirst ){
          iPg = 0;
        }else{
          rc = fsGetPageBefore(pFS, pRun, iPg, &iPg);
        }
      }

      nSpace = 0;
      if( iPg!=0 ){
        rc = fsPageGet(pFS, pRun, iPg, 0, ppNext, &nSpace);
        assert( (*ppNext==0)==(rc!=LSM_OK || nSpace>0) );
      }else{
        *ppNext = 0;
      }
    }while( nSpace>0 && rc==LSM_OK );

  }else{
    Redirect *pRedir = pRun ? pRun->pRedirect : 0;
    assert( eDir==1 || eDir==-1 );
    if( eDir<0 ){
      if( pRun && iPg==pRun->iFirst ){
        *ppNext = 0;
        return LSM_OK;
      }else if( fsIsFirst(pFS, iPg) ){
        assert( pPg->flags & PAGE_HASPREV );
        iPg = fsLastPageOnBlock(pFS, lsmGetU32(&pPg->aData[-4]));
      }else{
        iPg--;
      }
    }else{
      if( pRun ){
        if( iPg==pRun->iLastPg ){
          *ppNext = 0;
          return LSM_OK;
        }
      }

      if( fsIsLast(pFS, iPg) ){
        int iBlk = fsRedirectBlock(
            pRedir, lsmGetU32(&pPg->aData[pFS->nPagesize-4])
        );
        iPg = fsFirstPageOnBlock(pFS, iBlk);
      }else{
        iPg++;
      }
    }
    rc = fsPageGet(pFS, pRun, iPg, 0, ppNext, 0);
  }

  return rc;
}

/*
** This function is called when creating a new segment to determine if the
** first part of it can be written following an existing segment on an
** already allocated block. If it is possible, the page number of the first
** page to use for the new segment is returned. Otherwise zero.
**
** If argument pLvl is not NULL, then this function will not attempt to
** start the new segment immediately following any segment that is part
** of the right-hand-side of pLvl.
*/
static Pgno findAppendPoint(FileSystem *pFS, Level *pLvl){
  int i;
  Pgno *aiAppend = pFS->pDb->pWorker->aiAppend;
  Pgno iRet = 0;

  for(i=LSM_APPLIST_SZ-1; iRet==0 && i>=0; i--){
    if( (iRet = aiAppend[i]) ){
      if( pLvl ){
        int iBlk = fsPageToBlock(pFS, iRet);
        int j;
        for(j=0; iRet && j<pLvl->nRight; j++){
          if( fsPageToBlock(pFS, pLvl->aRhs[j].iLastPg)==iBlk ){
            iRet = 0;
          }
        }
      }
      if( iRet ) aiAppend[i] = 0;
    }
  }
  return iRet;
}

/*
** Append a page to the left-hand-side of pLvl. Set the ref-count to 1 and
** return a pointer to it. The page is writable until either 
** lsmFsPagePersist() is called on it or the ref-count drops to zero.
*/
int lsmFsSortedAppend(
  FileSystem *pFS, 
  Snapshot *pSnapshot,
  Level *pLvl,
  int bDefer,
  Page **ppOut
){
  int rc = LSM_OK;
  Page *pPg = 0;
  *ppOut = 0;
  int iApp = 0;
  int iNext = 0;
  Segment *p = &pLvl->lhs;
  int iPrev = p->iLastPg;

  assert( p->pRedirect==0 );

  if( pFS->pCompress || bDefer ){
    /* In compressed database mode the page is not assigned a page number
    ** or location in the database file at this point. This will be done
    ** by the lsmFsPagePersist() call.  */
    rc = fsPageBuffer(pFS, &pPg);
    if( rc==LSM_OK ){
      pPg->pFS = pFS;
      pPg->pSeg = p;
      pPg->iPg = 0;
      pPg->flags |= PAGE_DIRTY;
      pPg->nData = pFS->nPagesize;
      assert( pPg->aData );
      if( pFS->pCompress==0 ) pPg->nData -= 4;

      pPg->nRef = 1;
      pFS->nOut++;
    }
  }else{
    if( iPrev==0 ){
      iApp = findAppendPoint(pFS, pLvl);
    }else if( fsIsLast(pFS, iPrev) ){
      int iNext;
      rc = fsBlockNext(pFS, 0, fsPageToBlock(pFS, iPrev), &iNext);
      if( rc!=LSM_OK ) return rc;
      iApp = fsFirstPageOnBlock(pFS, iNext);
    }else{
      iApp = iPrev + 1;
    }

    /* If this is the first page allocated, or if the page allocated is the
    ** last in the block, also allocate the next block here.  */
    if( iApp==0 || fsIsLast(pFS, iApp) ){
      int iNew;                     /* New block number */

      rc = lsmBlockAllocate(pFS->pDb, 0, &iNew);
      if( rc!=LSM_OK ) return rc;
      if( iApp==0 ){
        iApp = fsFirstPageOnBlock(pFS, iNew);
      }else{
        iNext = fsFirstPageOnBlock(pFS, iNew);
      }
    }

    /* Grab the new page. */
    pPg = 0;
    rc = fsPageGet(pFS, 0, iApp, 1, &pPg, 0);
    assert( rc==LSM_OK || pPg==0 );

    /* If this is the first or last page of a block, fill in the pointer 
     ** value at the end of the new page. */
    if( rc==LSM_OK ){
      p->nSize++;
      p->iLastPg = iApp;
      if( p->iFirst==0 ) p->iFirst = iApp;
      pPg->flags |= PAGE_DIRTY;

      if( fsIsLast(pFS, iApp) ){
        lsmPutU32(&pPg->aData[pFS->nPagesize-4], fsPageToBlock(pFS, iNext));
      }else if( fsIsFirst(pFS, iApp) ){
        lsmPutU32(&pPg->aData[-4], fsPageToBlock(pFS, iPrev));
      }
    }
  }

  *ppOut = pPg;
  return rc;
}

/*
** Mark the segment passed as the second argument as finished. Once a segment
** is marked as finished it is not possible to append any further pages to 
** it.
**
** Return LSM_OK if successful or an lsm error code if an error occurs.
*/
int lsmFsSortedFinish(FileSystem *pFS, Segment *p){
  int rc = LSM_OK;
  if( p && p->iLastPg ){
    assert( p->pRedirect==0 );

    /* Check if the last page of this run happens to be the last of a block.
    ** If it is, then an extra block has already been allocated for this run.
    ** Shift this extra block back to the free-block list. 
    **
    ** Otherwise, add the first free page in the last block used by the run
    ** to the lAppend list.
    */
    if( fsLastPageOnPagesBlock(pFS, p->iLastPg)!=p->iLastPg ){
      int i;
      Pgno *aiAppend = pFS->pDb->pWorker->aiAppend;
      for(i=0; i<LSM_APPLIST_SZ; i++){
        if( aiAppend[i]==0 ){
          aiAppend[i] = p->iLastPg+1;
          break;
        }
      }
    }else if( pFS->pCompress==0 ){
      Page *pLast;
      rc = fsPageGet(pFS, 0, p->iLastPg, 0, &pLast, 0);
      if( rc==LSM_OK ){
        int iBlk = (int)lsmGetU32(&pLast->aData[pFS->nPagesize-4]);
        lsmBlockRefree(pFS->pDb, iBlk);
        lsmFsPageRelease(pLast);
      }
    }else{
      int iBlk = 0;
      rc = fsBlockNext(pFS, p, fsPageToBlock(pFS, p->iLastPg), &iBlk);
      if( rc==LSM_OK ){
        lsmBlockRefree(pFS->pDb, iBlk);
      }
    }
  }
  return rc;
}

/*
** Obtain a reference to page number iPg.
**
** Return LSM_OK if successful, or an lsm error code if an error occurs.
*/
int lsmFsDbPageGet(FileSystem *pFS, Segment *pSeg, Pgno iPg, Page **ppPg){
  return fsPageGet(pFS, pSeg, iPg, 0, ppPg, 0);
}

/*
** Obtain a reference to the last page in the segment passed as the 
** second argument.
**
** Return LSM_OK if successful, or an lsm error code if an error occurs.
*/
int lsmFsDbPageLast(FileSystem *pFS, Segment *pSeg, Page **ppPg){
  int rc;
  Pgno iPg = pSeg->iLastPg;
  if( pFS->pCompress ){
    int nSpace;
    iPg++;
    do {
      nSpace = 0;
      rc = fsGetPageBefore(pFS, pSeg, iPg, &iPg);
      if( rc==LSM_OK ){
        rc = fsPageGet(pFS, pSeg, iPg, 0, ppPg, &nSpace);
      }
    }while( rc==LSM_OK && nSpace>0 );

  }else{
    rc = fsPageGet(pFS, pSeg, iPg, 0, ppPg, 0);
  }
  return rc;
}

/*
** Return a reference to meta-page iPg. If successful, LSM_OK is returned
** and *ppPg populated with the new page reference. The reference should
** be released by the caller using lsmFsPageRelease().
**
** Otherwise, if an error occurs, *ppPg is set to NULL and an LSM error 
** code is returned.
*/
int lsmFsMetaPageGet(
  FileSystem *pFS,                /* File-system connection */
  int bWrite,                     /* True for write access, false for read */
  int iPg,                        /* Either 1 or 2 */
  MetaPage **ppPg                 /* OUT: Pointer to MetaPage object */
){
  int rc = LSM_OK;
  MetaPage *pPg;
  assert( iPg==1 || iPg==2 );

  pPg = lsmMallocZeroRc(pFS->pEnv, sizeof(Page), &rc);

  if( pPg ){
    i64 iOff = (iPg-1) * pFS->nMetasize;
    if( pFS->nMapLimit>0 ){
      fsGrowMapping(pFS, 2*pFS->nMetasize, &rc);
      pPg->aData = (u8 *)(pFS->pMap) + iOff;
    }else{
      pPg->aData = lsmMallocRc(pFS->pEnv, pFS->nMetasize, &rc);
      if( rc==LSM_OK && bWrite==0 ){
        rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, pPg->aData, pFS->nMetasize);
      }
#ifndef NDEBUG
      /* pPg->aData causes an uninitialized access via a downstreadm write().
         After discussion on this list, this memory should not, for performance
         reasons, be memset. However, tracking down "real" misuse is more
         difficult with this "false" positive, so it is set when NDEBUG.
      */
      else if( rc==LSM_OK ){
        memset( pPg->aData, 0x77, pFS->nMetasize );
      }
#endif
    }

    if( rc!=LSM_OK ){
      if( pFS->nMapLimit==0 ) lsmFree(pFS->pEnv, pPg->aData);
      lsmFree(pFS->pEnv, pPg);
      pPg = 0;
    }else{
      pPg->iPg = iPg;
      pPg->bWrite = bWrite;
      pPg->pFS = pFS;
    }
  }

  *ppPg = pPg;
  return rc;
}

/*
** Release a meta-page reference obtained via a call to lsmFsMetaPageGet().
*/
int lsmFsMetaPageRelease(MetaPage *pPg){
  int rc = LSM_OK;
  if( pPg ){
    FileSystem *pFS = pPg->pFS;

    if( pFS->nMapLimit==0 ){
      if( pPg->bWrite ){
        i64 iOff = (pPg->iPg==2 ? pFS->nMetasize : 0);
        int nWrite = pFS->nMetasize;
        rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, pPg->aData, nWrite);
      }
      lsmFree(pFS->pEnv, pPg->aData);
    }

    lsmFree(pFS->pEnv, pPg);
  }
  return rc;
}

/*
** Return a pointer to a buffer containing the data associated with the
** meta-page passed as the first argument. If parameter pnData is not NULL,
** set *pnData to the size of the meta-page in bytes before returning.
*/
u8 *lsmFsMetaPageData(MetaPage *pPg, int *pnData){
  if( pnData ) *pnData = pPg->pFS->nMetasize;
  return pPg->aData;
}

/*
** Return true if page is currently writable. This is used in assert() 
** statements only.
*/
#ifndef NDEBUG
int lsmFsPageWritable(Page *pPg){
  return (pPg->flags & PAGE_DIRTY) ? 1 : 0;
}
#endif

/*
** This is called when block iFrom is being redirected to iTo. If page 
** number (*piPg) lies on block iFrom, then calculate the equivalent
** page on block iTo and set *piPg to this value before returning.
*/
static void fsMovePage(
  FileSystem *pFS,                /* File system object */
  int iTo,                        /* Destination block */
  int iFrom,                      /* Source block */
  Pgno *piPg                      /* IN/OUT: Page number */
){
  Pgno iPg = *piPg;
  if( iFrom==fsPageToBlock(pFS, iPg) ){
    const int nPagePerBlock = (
        pFS->pCompress ? pFS ->nBlocksize : (pFS->nBlocksize / pFS->nPagesize)
    );
    *piPg = iPg - (Pgno)(iFrom - iTo) * nPagePerBlock;
  }
}

/*
** Copy the contents of block iFrom to block iTo. 
**
** It is safe to assume that there are no outstanding references to pages 
** on block iTo. And that block iFrom is not currently being written. In
** other words, the data can be read and written directly.
*/
int lsmFsMoveBlock(FileSystem *pFS, Segment *pSeg, int iTo, int iFrom){
  Snapshot *p = pFS->pDb->pWorker;
  int rc = LSM_OK;
  int i;
  i64 nMap;

  i64 iFromOff = (i64)(iFrom-1) * pFS->nBlocksize;
  i64 iToOff = (i64)(iTo-1) * pFS->nBlocksize;
  
  assert( iTo!=1 );
  assert( iFrom>iTo );

  /* Grow the mapping as required. */
  nMap = LSM_MIN(pFS->nMapLimit, (i64)iFrom * pFS->nBlocksize);
  fsGrowMapping(pFS, nMap, &rc);

  if( rc==LSM_OK ){
    const int nPagePerBlock = (pFS->nBlocksize / pFS->nPagesize);
    int nSz = pFS->nPagesize;
    u8 *aBuf = 0;
    u8 *aData = 0;

    for(i=0; rc==LSM_OK && i<nPagePerBlock; i++){
      i64 iOff = iFromOff + i*nSz;

      /* Set aData to point to a buffer containing the from page */
      if( (iOff+nSz)<=pFS->nMapLimit ){
        u8 *aMap = (u8 *)(pFS->pMap);
        aData = &aMap[iOff];
      }else{
        if( aBuf==0 ){
          aBuf = (u8 *)lsmMallocRc(pFS->pEnv, nSz, &rc);
          if( aBuf==0 ) break;
        }
        aData = aBuf;
        rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aData, nSz);
      }

      /* Copy aData to the to page */
      if( rc==LSM_OK ){
        iOff = iToOff + i*nSz;
        if( (iOff+nSz)<=pFS->nMapLimit ){
          u8 *aMap = (u8 *)(pFS->pMap);
          memcpy(&aMap[iOff], aData, nSz);
        }else{
          rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, aData, nSz);
        }
      }
    }
    lsmFree(pFS->pEnv, aBuf);
    lsmFsPurgeCache(pFS);
  }

  /* Update append-point list if necessary */
  for(i=0; i<LSM_APPLIST_SZ; i++){
    fsMovePage(pFS, iTo, iFrom, &p->aiAppend[i]);
  }

  /* Update the Segment structure itself */
  fsMovePage(pFS, iTo, iFrom, &pSeg->iFirst);
  fsMovePage(pFS, iTo, iFrom, &pSeg->iLastPg);
  fsMovePage(pFS, iTo, iFrom, &pSeg->iRoot);

  return rc;
}

/*
** Append raw data to a segment. Return the database file offset that the
** data is written to (this may be used as the page number if the data
** being appended is a new page record).
**
** This function is only used in compressed database mode.
*/
static Pgno fsAppendData(
  FileSystem *pFS,                /* File-system handle */
  Segment *pSeg,                  /* Segment to append to */
  const u8 *aData,                /* Buffer containing data to write */
  int nData,                      /* Size of buffer aData[] in bytes */
  int *pRc                        /* IN/OUT: Error code */
){
  Pgno iRet = 0;
  int rc = *pRc;
  assert( pFS->pCompress );
  if( rc==LSM_OK ){
    int nRem;
    int nWrite;
    Pgno iLastOnBlock;
    Pgno iApp = pSeg->iLastPg+1;

    /* If this is the first data written into the segment, find an append-point
    ** or allocate a new block.  */
    if( iApp==1 ){
      pSeg->iFirst = iApp = findAppendPoint(pFS, 0);
      if( iApp==0 ){
        int iBlk;
        rc = lsmBlockAllocate(pFS->pDb, 0, &iBlk);
        pSeg->iFirst = iApp = fsFirstPageOnBlock(pFS, iBlk);
      }
    }
    iRet = iApp;

    /* Write as much data as is possible at iApp (usually all of it). */
    iLastOnBlock = fsLastPageOnPagesBlock(pFS, iApp);
    if( rc==LSM_OK ){
      int nSpace = iLastOnBlock - iApp + 1;
      nWrite = LSM_MIN(nData, nSpace);
      nRem = nData - nWrite;
      assert( nWrite>=0 );
      if( nWrite!=0 ){
        rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iApp, aData, nWrite);
      }
      iApp += nWrite;
    }

    /* If required, allocate a new block and write the rest of the data
    ** into it. Set the next and previous block pointers to link the new
    ** block to the old.  */
    assert( nRem<=0 || (iApp-1)==iLastOnBlock );
    if( rc==LSM_OK && (iApp-1)==iLastOnBlock ){
      u8 aPtr[4];                 /* Space to serialize a u32 */
      int iBlk;                   /* New block number */

      if( nWrite>0 ){
        /* Allocate a new block. */
        rc = lsmBlockAllocate(pFS->pDb, 0, &iBlk);

        /* Set the "next" pointer on the old block */
        if( rc==LSM_OK ){
          assert( iApp==(fsPageToBlock(pFS, iApp)*pFS->nBlocksize)-4 );
          lsmPutU32(aPtr, iBlk);
          rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iApp, aPtr, sizeof(aPtr));
        }

        /* Set the "prev" pointer on the new block */
        if( rc==LSM_OK ){
          Pgno iWrite;
          lsmPutU32(aPtr, fsPageToBlock(pFS, iApp));
          iWrite = fsFirstPageOnBlock(pFS, iBlk);
          rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iWrite-4, aPtr, sizeof(aPtr));
          if( nRem>0 ) iApp = iWrite;
        }
      }else{
        /* The next block is already allocated. */
        assert( nRem>0 );
        assert( pSeg->pRedirect==0 );
        rc = fsBlockNext(pFS, 0, fsPageToBlock(pFS, iApp), &iBlk);
        iRet = iApp = fsFirstPageOnBlock(pFS, iBlk);
      }

      /* Write the remaining data into the new block */
      if( rc==LSM_OK && nRem>0 ){
        rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iApp, &aData[nWrite], nRem);
        iApp += nRem;
      }
    }

    pSeg->iLastPg = iApp-1;
    *pRc = rc;
  }

  return iRet;
}

/*
** This function is only called in compressed database mode. It 
** compresses the contents of page pPg and writes the result to the 
** buffer at pFS->aOBuffer. The size of the compressed data is stored in
** pPg->nCompress.
**
** If buffer pFS->aOBuffer[] has not been allocated then this function
** allocates it. If this fails, LSM_NOMEM is returned. Otherwise, LSM_OK.
*/
static int fsCompressIntoBuffer(FileSystem *pFS, Page *pPg){
  lsm_compress *p = pFS->pCompress;

  if( fsAllocateBuffer(pFS, 1) ) return LSM_NOMEM;
  assert( pPg->nData==pFS->nPagesize );

  pPg->nCompress = pFS->nBuffer;
  return p->xCompress(p->pCtx, 
      (char *)pFS->aOBuffer, &pPg->nCompress, 
      (const char *)pPg->aData, pPg->nData
  );
}

/*
** Append a new page to segment pSeg. Set output variable *piNew to the
** page number of the new page before returning.
**
** If the new page is the last on its block, then the 'next' block that
** will be used by the segment is allocated here too. In this case output
** variable *piNext is set to the block number of the next block.
**
** If the new page is the first on its block but not the first in the
** entire segment, set output variable *piPrev to the block number of
** the previous block in the segment.
**
** LSM_OK is returned if successful, or an lsm error code otherwise. If
** any value other than LSM_OK is returned, then the final value of all
** output variables is undefined.
*/
static int fsAppendPage(
  FileSystem *pFS, 
  Segment *pSeg,
  Pgno *piNew,
  int *piPrev,
  int *piNext
){
  Pgno iPrev = pSeg->iLastPg;
  int rc;
  assert( iPrev!=0 );

  *piPrev = 0;
  *piNext = 0;

  if( fsIsLast(pFS, iPrev) ){
    /* Grab the first page on the next block (which has already be
    ** allocated). In this case set *piPrev to tell the caller to set
    ** the "previous block" pointer in the first 4 bytes of the page.
    */
    int iNext;
    int iBlk = fsPageToBlock(pFS, iPrev);
    assert( pSeg->pRedirect==0 );
    rc = fsBlockNext(pFS, 0, iBlk, &iNext);
    if( rc!=LSM_OK ) return rc;
    *piNew = fsFirstPageOnBlock(pFS, iNext);
    *piPrev = iBlk;
  }else{
    *piNew = iPrev+1;
    if( fsIsLast(pFS, *piNew) ){
      /* Allocate the next block here. */
      int iBlk;
      rc = lsmBlockAllocate(pFS->pDb, 0, &iBlk);
      if( rc!=LSM_OK ) return rc;
      *piNext = iBlk;
    }
  }

  pSeg->nSize++;
  pSeg->iLastPg = *piNew;
  return LSM_OK;
}

/*
** Flush all pages in the FileSystem.pWaiting list to disk.
*/
void lsmFsFlushWaiting(FileSystem *pFS, int *pRc){
  int rc = *pRc;
  Page *pPg;

  pPg = pFS->pWaiting;
  pFS->pWaiting = 0;

  while( pPg ){
    Page *pNext = pPg->pWaitingNext;
    if( rc==LSM_OK ) rc = lsmFsPagePersist(pPg);
    assert( pPg->nRef==1 );
    lsmFsPageRelease(pPg);
    pPg = pNext;
  }
  *pRc = rc;
}

/*
** If there exists a hash-table entry associated with page iPg, remove it.
*/
static void fsRemoveHashEntry(FileSystem *pFS, Pgno iPg){
  Page *p;
  int iHash = fsHashKey(pFS->nHash, iPg);

  for(p=pFS->apHash[iHash]; p && p->iPg!=iPg; p=p->pHashNext);

  if( p ){
    assert( p->nRef==0 || (p->flags & PAGE_FREE)==0 );
    fsPageRemoveFromHash(pFS, p);
    p->iPg = 0;
    iHash = fsHashKey(pFS->nHash, 0);
    p->pHashNext = pFS->apHash[iHash];
    pFS->apHash[iHash] = p;
  }
}

/*
** If the page passed as an argument is dirty, update the database file
** (or mapping of the database file) with its current contents and mark
** the page as clean.
**
** Return LSM_OK if the operation is a success, or an LSM error code
** otherwise.
*/
int lsmFsPagePersist(Page *pPg){
  int rc = LSM_OK;
  if( pPg && (pPg->flags & PAGE_DIRTY) ){
    FileSystem *pFS = pPg->pFS;

    if( pFS->pCompress ){
      int iHash;                  /* Hash key of assigned page number */
      u8 aSz[3];                  /* pPg->nCompress as a 24-bit big-endian */
      assert( pPg->pSeg && pPg->iPg==0 && pPg->nCompress==0 );

      /* Compress the page image. */
      rc = fsCompressIntoBuffer(pFS, pPg);

      /* Serialize the compressed size into buffer aSz[] */
      putRecordSize(aSz, pPg->nCompress, 0);

      /* Write the serialized page record into the database file. */
      pPg->iPg = fsAppendData(pFS, pPg->pSeg, aSz, sizeof(aSz), &rc);
      fsAppendData(pFS, pPg->pSeg, pFS->aOBuffer, pPg->nCompress, &rc);
      fsAppendData(pFS, pPg->pSeg, aSz, sizeof(aSz), &rc);

      /* Now that it has a page number, insert the page into the hash table */
      iHash = fsHashKey(pFS->nHash, pPg->iPg);
      pPg->pHashNext = pFS->apHash[iHash];
      pFS->apHash[iHash] = pPg;

      pPg->pSeg->nSize += (sizeof(aSz) * 2) + pPg->nCompress;

      pPg->flags &= ~PAGE_DIRTY;
      pFS->nWrite++;
    }else{

      if( pPg->iPg==0 ){
        /* No page number has been assigned yet. This occurs with pages used
        ** in the b-tree hierarchy. They were not assigned page numbers when
        ** they were created as doing so would cause this call to
        ** lsmFsPagePersist() to write an out-of-order page. Instead a page 
        ** number is assigned here so that the page data will be appended
        ** to the current segment.
        */
        Page **pp;
        int iPrev = 0;
        int iNext = 0;
        int iHash;

        assert( pPg->pSeg->iFirst );
        assert( pPg->flags & PAGE_FREE );
        assert( (pPg->flags & PAGE_HASPREV)==0 );
        assert( pPg->nData==pFS->nPagesize-4 );

        rc = fsAppendPage(pFS, pPg->pSeg, &pPg->iPg, &iPrev, &iNext);
        if( rc!=LSM_OK ) return rc;

        assert( pPg->flags & PAGE_FREE );
        iHash = fsHashKey(pFS->nHash, pPg->iPg);
        fsRemoveHashEntry(pFS, pPg->iPg);
        pPg->pHashNext = pFS->apHash[iHash];
        pFS->apHash[iHash] = pPg;
        assert( pPg->pHashNext==0 || pPg->pHashNext->iPg!=pPg->iPg );

        if( iPrev ){
          assert( iNext==0 );
          memmove(&pPg->aData[4], pPg->aData, pPg->nData);
          lsmPutU32(pPg->aData, iPrev);
          pPg->flags |= PAGE_HASPREV;
          pPg->aData += 4;
        }else if( iNext ){
          assert( iPrev==0 );
          lsmPutU32(&pPg->aData[pPg->nData], iNext);
        }else{
          int nData = pPg->nData;
          pPg->nData += 4;
          lsmSortedExpandBtreePage(pPg, nData);
        }

        pPg->nRef++;
        for(pp=&pFS->pWaiting; *pp; pp=&(*pp)->pWaitingNext);
        *pp = pPg;
        assert( pPg->pWaitingNext==0 );

      }else{
        i64 iOff;                   /* Offset to write within database file */

        iOff = (i64)pFS->nPagesize * (i64)(pPg->iPg-1);
        if( fsMmapPage(pFS, pPg->iPg)==0 ){
          u8 *aData = pPg->aData - (pPg->flags & PAGE_HASPREV);
          rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, aData, pFS->nPagesize);
        }else if( pPg->flags & PAGE_FREE ){
          fsGrowMapping(pFS, iOff + pFS->nPagesize, &rc);
          if( rc==LSM_OK ){
            u8 *aTo = &((u8 *)(pFS->pMap))[iOff];
            u8 *aFrom = pPg->aData - (pPg->flags & PAGE_HASPREV);
            memcpy(aTo, aFrom, pFS->nPagesize);
            lsmFree(pFS->pEnv, aFrom);
            pFS->nCacheAlloc--;
            pPg->aData = aTo + (pPg->flags & PAGE_HASPREV);
            pPg->flags &= ~PAGE_FREE;
            fsPageRemoveFromHash(pFS, pPg);
            pPg->pMappedNext = pFS->pMapped;
            pFS->pMapped = pPg;
          }
        }

        lsmFsFlushWaiting(pFS, &rc);
        pPg->flags &= ~PAGE_DIRTY;
        pFS->nWrite++;
      }
    }
  }

  return rc;
}

/*
** For non-compressed databases, this function is a no-op. For compressed
** databases, it adds a padding record to the segment passed as the third
** argument.
**
** The size of the padding records is selected so that the last byte 
** written is the last byte of a disk sector. This means that if a 
** snapshot is taken and checkpointed, subsequent worker processes will
** not write to any sector that contains checkpointed data.
*/
int lsmFsSortedPadding(
  FileSystem *pFS, 
  Snapshot *pSnapshot,
  Segment *pSeg
){
  int rc = LSM_OK;
  if( pFS->pCompress ){
    Pgno iLast2;
    Pgno iLast = pSeg->iLastPg;     /* Current last page of segment */
    int nPad;                       /* Bytes of padding required */
    u8 aSz[3];

    iLast2 = (1 + iLast/pFS->szSector) * pFS->szSector - 1;
    assert( fsPageToBlock(pFS, iLast)==fsPageToBlock(pFS, iLast2) );
    nPad = iLast2 - iLast;

    if( iLast2>fsLastPageOnPagesBlock(pFS, iLast) ){
      nPad -= 4;
    }
    assert( nPad>=0 );

    if( nPad>=6 ){
      pSeg->nSize += nPad;
      nPad -= 6;
      putRecordSize(aSz, nPad, 1);
      fsAppendData(pFS, pSeg, aSz, sizeof(aSz), &rc);
      memset(pFS->aOBuffer, 0, nPad);
      fsAppendData(pFS, pSeg, pFS->aOBuffer, nPad, &rc);
      fsAppendData(pFS, pSeg, aSz, sizeof(aSz), &rc);
    }else if( nPad>0 ){
      u8 aBuf[5] = {0,0,0,0,0};
      aBuf[0] = (u8)nPad;
      aBuf[nPad-1] = (u8)nPad;
      fsAppendData(pFS, pSeg, aBuf, nPad, &rc);
    }

    assert( rc!=LSM_OK 
        || pSeg->iLastPg==fsLastPageOnPagesBlock(pFS, pSeg->iLastPg)
        || ((pSeg->iLastPg + 1) % pFS->szSector)==0
    );
  }

  return rc;
}


/*
** Increment the reference count on the page object passed as the first
** argument.
*/
void lsmFsPageRef(Page *pPg){
  if( pPg ){
    pPg->nRef++;
  }
}

/*
** Release a page-reference obtained using fsPageGet().
*/
int lsmFsPageRelease(Page *pPg){
  int rc = LSM_OK;
  if( pPg ){
    assert( pPg->nRef>0 );
    pPg->nRef--;
    if( pPg->nRef==0 ){
      FileSystem *pFS = pPg->pFS;
      rc = lsmFsPagePersist(pPg);
      pFS->nOut--;

      assert( pPg->pFS->pCompress 
           || fsIsFirst(pPg->pFS, pPg->iPg)==0 
           || (pPg->flags & PAGE_HASPREV)
      );
      pPg->aData -= (pPg->flags & PAGE_HASPREV);
      pPg->flags &= ~PAGE_HASPREV;

      if( (pPg->flags & PAGE_FREE)==0 ){
        /* Removed from mapped list */
        Page **pp;
        for(pp=&pFS->pMapped; (*pp)!=pPg; pp=&(*pp)->pMappedNext);
        *pp = pPg->pMappedNext;
        pPg->pMappedNext = 0;

        /* Add to free list */
        pPg->pFreeNext = pFS->pFree;
        pFS->pFree = pPg;
      }else{
        fsPageAddToLru(pFS, pPg);
      }
    }
  }

  return rc;
}

/*
** Return the total number of pages read from the database file.
*/
int lsmFsNRead(FileSystem *pFS){ return pFS->nRead; }

/*
** Return the total number of pages written to the database file.
*/
int lsmFsNWrite(FileSystem *pFS){ return pFS->nWrite; }

/*
** Return a copy of the environment pointer used by the file-system object.
*/
lsm_env *lsmFsEnv(FileSystem *pFS){ 
  return pFS->pEnv; 
}

/*
** Return a copy of the environment pointer used by the file-system object
** to which this page belongs.
*/
lsm_env *lsmPageEnv(Page *pPg) { 
  return pPg->pFS->pEnv; 
}

/*
** Return a pointer to the file-system object associated with the Page
** passed as the only argument.
*/
FileSystem *lsmPageFS(Page *pPg){
  return pPg->pFS;
}

/*
** Return the sector-size as reported by the log file handle.
*/
int lsmFsSectorSize(FileSystem *pFS){
  return pFS->szSector;
}

/*
** Helper function for lsmInfoArrayStructure().
*/
static Segment *startsWith(Segment *pRun, Pgno iFirst){
  return (iFirst==pRun->iFirst) ? pRun : 0;
}

/*
** Return the segment that starts with page iFirst, if any. If no such segment
** can be found, return NULL.
*/
static Segment *findSegment(Snapshot *pWorker, Pgno iFirst){
  Level *pLvl;                    /* Used to iterate through db levels */
  Segment *pSeg = 0;              /* Pointer to segment to return */

  for(pLvl=lsmDbSnapshotLevel(pWorker); pLvl && pSeg==0; pLvl=pLvl->pNext){
    if( 0==(pSeg = startsWith(&pLvl->lhs, iFirst)) ){
      int i;
      for(i=0; i<pLvl->nRight; i++){
        if( (pSeg = startsWith(&pLvl->aRhs[i], iFirst)) ) break;
      }
    }
  }

  return pSeg;
}

/*
** This function implements the lsm_info(LSM_INFO_ARRAY_STRUCTURE) request.
** If successful, *pzOut is set to point to a nul-terminated string 
** containing the array structure and LSM_OK is returned. The caller should
** eventually free the string using lsmFree().
**
** If an error occurs, *pzOut is set to NULL and an LSM error code returned.
*/
int lsmInfoArrayStructure(
  lsm_db *pDb, 
  int bBlock,                     /* True for block numbers only */
  Pgno iFirst,
  char **pzOut
){
  int rc = LSM_OK;
  Snapshot *pWorker;              /* Worker snapshot */
  Segment *pArray = 0;            /* Array to report on */
  int bUnlock = 0;

  *pzOut = 0;
  if( iFirst==0 ) return LSM_ERROR;

  /* Obtain the worker snapshot */
  pWorker = pDb->pWorker;
  if( !pWorker ){
    rc = lsmBeginWork(pDb);
    if( rc!=LSM_OK ) return rc;
    pWorker = pDb->pWorker;
    bUnlock = 1;
  }

  /* Search for the array that starts on page iFirst */
  pArray = findSegment(pWorker, iFirst);

  if( pArray==0 ){
    /* Could not find the requested array. This is an error. */
    rc = LSM_ERROR;
  }else{
    FileSystem *pFS = pDb->pFS;
    LsmString str;
    int iBlk;
    int iLastBlk;
   
    iBlk = fsPageToBlock(pFS, pArray->iFirst);
    iLastBlk = fsPageToBlock(pFS, pArray->iLastPg);

    lsmStringInit(&str, pDb->pEnv);
    if( bBlock ){
      lsmStringAppendf(&str, "%d", iBlk);
      while( iBlk!=iLastBlk ){
        fsBlockNext(pFS, pArray, iBlk, &iBlk);
        lsmStringAppendf(&str, " %d", iBlk);
      }
    }else{
      lsmStringAppendf(&str, "%d", pArray->iFirst);
      while( iBlk!=iLastBlk ){
        lsmStringAppendf(&str, " %d", fsLastPageOnBlock(pFS, iBlk));
        fsBlockNext(pFS, pArray, iBlk, &iBlk);
        lsmStringAppendf(&str, " %d", fsFirstPageOnBlock(pFS, iBlk));
      }
      lsmStringAppendf(&str, " %d", pArray->iLastPg);
    }

    *pzOut = str.z;
  }

  if( bUnlock ){
    int rcwork = LSM_BUSY;
    lsmFinishWork(pDb, 0, &rcwork);
  }
  return rc;
}

int lsmFsSegmentContainsPg(
  FileSystem *pFS, 
  Segment *pSeg, 
  Pgno iPg, 
  int *pbRes
){
  Redirect *pRedir = pSeg->pRedirect;
  int rc = LSM_OK;
  int iBlk;
  int iLastBlk;
  int iPgBlock;                   /* Block containing page iPg */

  iPgBlock = fsPageToBlock(pFS, pSeg->iFirst);
  iBlk = fsRedirectBlock(pRedir, fsPageToBlock(pFS, pSeg->iFirst));
  iLastBlk = fsRedirectBlock(pRedir, fsPageToBlock(pFS, pSeg->iLastPg));

  while( iBlk!=iLastBlk && iBlk!=iPgBlock && rc==LSM_OK ){
    rc = fsBlockNext(pFS, pSeg, iBlk, &iBlk);
  }

  *pbRes = (iBlk==iPgBlock);
  return rc;
}

/*
** This function implements the lsm_info(LSM_INFO_ARRAY_PAGES) request.
** If successful, *pzOut is set to point to a nul-terminated string 
** containing the array structure and LSM_OK is returned. The caller should
** eventually free the string using lsmFree().
**
** If an error occurs, *pzOut is set to NULL and an LSM error code returned.
*/
int lsmInfoArrayPages(lsm_db *pDb, Pgno iFirst, char **pzOut){
  int rc = LSM_OK;
  Snapshot *pWorker;              /* Worker snapshot */
  Segment *pSeg = 0;              /* Array to report on */
  int bUnlock = 0;

  *pzOut = 0;
  if( iFirst==0 ) return LSM_ERROR;

  /* Obtain the worker snapshot */
  pWorker = pDb->pWorker;
  if( !pWorker ){
    rc = lsmBeginWork(pDb);
    if( rc!=LSM_OK ) return rc;
    pWorker = pDb->pWorker;
    bUnlock = 1;
  }

  /* Search for the array that starts on page iFirst */
  pSeg = findSegment(pWorker, iFirst);

  if( pSeg==0 ){
    /* Could not find the requested array. This is an error. */
    rc = LSM_ERROR;
  }else{
    Page *pPg = 0;
    FileSystem *pFS = pDb->pFS;
    LsmString str;

    lsmStringInit(&str, pDb->pEnv);
    rc = lsmFsDbPageGet(pFS, pSeg, iFirst, &pPg);
    while( rc==LSM_OK && pPg ){
      Page *pNext = 0;
      lsmStringAppendf(&str, " %lld", lsmFsPageNumber(pPg));
      rc = lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
      lsmFsPageRelease(pPg);
      pPg = pNext;
    }

    if( rc!=LSM_OK ){
      lsmFree(pDb->pEnv, str.z);
    }else{
      *pzOut = str.z;
    }
  }

  if( bUnlock ){
    int rcwork = LSM_BUSY;
    lsmFinishWork(pDb, 0, &rcwork);
  }
  return rc;
}

/*
** The following macros are used by the integrity-check code. Associated with
** each block in the database is an 8-bit bit mask (the entry in the aUsed[]
** array). As the integrity-check meanders through the database, it sets the
** following bits to indicate how each block is used.
**
** INTEGRITY_CHECK_FIRST_PG:
**   First page of block is in use by sorted run.
**
** INTEGRITY_CHECK_LAST_PG:
**   Last page of block is in use by sorted run.
**
** INTEGRITY_CHECK_USED:
**   At least one page of the block is in use by a sorted run.
**
** INTEGRITY_CHECK_FREE:
**   The free block list contains an entry corresponding to this block.
*/
#define INTEGRITY_CHECK_FIRST_PG 0x01
#define INTEGRITY_CHECK_LAST_PG  0x02
#define INTEGRITY_CHECK_USED     0x04
#define INTEGRITY_CHECK_FREE     0x08

/*
** Helper function for lsmFsIntegrityCheck()
*/
static void checkBlocks(
  FileSystem *pFS, 
  Segment *pSeg,
  int bExtra,                     /* If true, count the "next" block if any */
  int nUsed,
  u8 *aUsed
){
  if( pSeg ){
    if( pSeg && pSeg->nSize>0 ){
      int rc;
      int iBlk;                   /* Current block (during iteration) */
      int iLastBlk;               /* Last block of segment */
      int iFirstBlk;              /* First block of segment */
      int bLastIsLastOnBlock;     /* True iLast is the last on its block */

      assert( 0==fsSegmentRedirects(pFS, pSeg) );
      iBlk = iFirstBlk = fsPageToBlock(pFS, pSeg->iFirst);
      iLastBlk = fsPageToBlock(pFS, pSeg->iLastPg);

      bLastIsLastOnBlock = (fsLastPageOnBlock(pFS, iLastBlk)==pSeg->iLastPg);
      assert( iBlk>0 );

      do {
        /* iBlk is a part of this sorted run. */
        aUsed[iBlk-1] |= INTEGRITY_CHECK_USED;

        /* If the first page of this block is also part of the segment,
        ** set the flag to indicate that the first page of iBlk is in use.  
        */
        if( fsFirstPageOnBlock(pFS, iBlk)==pSeg->iFirst || iBlk!=iFirstBlk ){
          assert( (aUsed[iBlk-1] & INTEGRITY_CHECK_FIRST_PG)==0 );
          aUsed[iBlk-1] |= INTEGRITY_CHECK_FIRST_PG;
        }

        /* Unless the sorted run finishes before the last page on this block, 
        ** the last page of this block is also in use.  */
        if( iBlk!=iLastBlk || bLastIsLastOnBlock ){
          assert( (aUsed[iBlk-1] & INTEGRITY_CHECK_LAST_PG)==0 );
          aUsed[iBlk-1] |= INTEGRITY_CHECK_LAST_PG;
        }

        /* Special case. The sorted run being scanned is the output run of
        ** a level currently undergoing an incremental merge. The sorted
        ** run ends on the last page of iBlk, but the next block has already
        ** been allocated. So mark it as in use as well.  */
        if( iBlk==iLastBlk && bLastIsLastOnBlock && bExtra ){
          int iExtra = 0;
          rc = fsBlockNext(pFS, pSeg, iBlk, &iExtra);
          assert( rc==LSM_OK );

          assert( aUsed[iExtra-1]==0 );
          aUsed[iExtra-1] |= INTEGRITY_CHECK_USED;
          aUsed[iExtra-1] |= INTEGRITY_CHECK_FIRST_PG;
          aUsed[iExtra-1] |= INTEGRITY_CHECK_LAST_PG;
        }

        /* Move on to the next block in the sorted run. Or set iBlk to zero
        ** in order to break out of the loop if this was the last block in
        ** the run.  */
        if( iBlk==iLastBlk ){
          iBlk = 0;
        }else{
          rc = fsBlockNext(pFS, pSeg, iBlk, &iBlk);
          assert( rc==LSM_OK );
        }
      }while( iBlk );
    }
  }
}

typedef struct CheckFreelistCtx CheckFreelistCtx;
struct CheckFreelistCtx {
  u8 *aUsed;
  int nBlock;
};
static int checkFreelistCb(void *pCtx, int iBlk, i64 iSnapshot){
  CheckFreelistCtx *p = (CheckFreelistCtx *)pCtx;

  assert( iBlk>=1 );
  assert( iBlk<=p->nBlock );
  assert( p->aUsed[iBlk-1]==0 );
  p->aUsed[iBlk-1] = INTEGRITY_CHECK_FREE;
  return 0;
}

/*
** This function checks that all blocks in the database file are accounted
** for. For each block, exactly one of the following must be true:
**
**   + the block is part of a sorted run, or
**   + the block is on the free-block list
**
** This function also checks that there are no references to blocks with
** out-of-range block numbers.
**
** If no errors are found, non-zero is returned. If an error is found, an
** assert() fails.
*/
int lsmFsIntegrityCheck(lsm_db *pDb){
  CheckFreelistCtx ctx;
  FileSystem *pFS = pDb->pFS;
  int i;
  int rc;
  Freelist freelist = {0, 0, 0};
  u8 *aUsed;
  Level *pLevel;
  Snapshot *pWorker = pDb->pWorker;
  int nBlock = pWorker->nBlock;

#if 0 
  static int nCall = 0;
  nCall++;
  printf("%d calls\n", nCall);
#endif

  aUsed = lsmMallocZero(pDb->pEnv, nBlock);
  if( aUsed==0 ){
    /* Malloc has failed. Since this function is only called within debug
    ** builds, this probably means the user is running an OOM injection test.
    ** Regardless, it will not be possible to run the integrity-check at this
    ** time, so assume the database is Ok and return non-zero. */
    return 1;
  }

  for(pLevel=pWorker->pLevel; pLevel; pLevel=pLevel->pNext){
    int i;
    checkBlocks(pFS, &pLevel->lhs, (pLevel->nRight!=0), nBlock, aUsed);
    for(i=0; i<pLevel->nRight; i++){
      checkBlocks(pFS, &pLevel->aRhs[i], 0, nBlock, aUsed);
    }
  }

  /* Mark all blocks in the free-list as used */
  ctx.aUsed = aUsed;
  ctx.nBlock = nBlock;
  rc = lsmWalkFreelist(pDb, 0, checkFreelistCb, (void *)&ctx);

  if( rc==LSM_OK ){
    for(i=0; i<nBlock; i++) assert( aUsed[i]!=0 );
  }

  lsmFree(pDb->pEnv, aUsed);
  lsmFree(pDb->pEnv, freelist.aEntry);

  return 1;
}

#ifndef NDEBUG
/*
** Return true if pPg happens to be the last page in segment pSeg. Or false
** otherwise. This function is only invoked as part of assert() conditions.
*/
int lsmFsDbPageIsLast(Segment *pSeg, Page *pPg){
  if( pPg->pFS->pCompress ){
    Pgno iNext = 0;
    int rc;
    rc = fsNextPageOffset(pPg->pFS, pSeg, pPg->iPg, pPg->nCompress+6, &iNext);
    return (rc!=LSM_OK || iNext==0);
  }
  return (pPg->iPg==pSeg->iLastPg);
}
#endif

/************** End of lsm_file.c ********************************************/
/************** Begin file lsm_log.c *****************************************/
/*
** 2011-08-13
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains the implementation of LSM database logging. Logging
** has one purpose in LSM - to make transactions durable.
**
** When data is written to an LSM database, it is initially stored in an
** in-memory tree structure. Since this structure is in volatile memory,
** if a power failure or application crash occurs it may be lost. To
** prevent loss of data in this case, each time a record is written to the
** in-memory tree an equivalent record is appended to the log on disk.
** If a power failure or application crash does occur, data can be recovered
** by reading the log.
**
** A log file consists of the following types of records representing data
** written into the database:
**
**   LOG_WRITE:  A key-value pair written to the database.
**   LOG_DELETE: A delete key issued to the database.
**   LOG_COMMIT: A transaction commit.
**
** And the following types of records for ancillary purposes..
**
**   LOG_EOF:    A record indicating the end of a log file.
**   LOG_PAD1:   A single byte padding record.
**   LOG_PAD2:   An N byte padding record (N>1).
**   LOG_JUMP:   A pointer to another offset within the log file.
**
** Each transaction written to the log contains one or more LOG_WRITE and/or
** LOG_DELETE records, followed by a LOG_COMMIT record. The LOG_COMMIT record
** contains an 8-byte checksum based on all previous data written to the
** log file.
**
** LOG CHECKSUMS & RECOVERY
**
**   Checksums are found in two types of log records: LOG_COMMIT and
**   LOG_CKSUM records. In order to recover content from a log, a client
**   reads each record from the start of the log, calculating a checksum as
**   it does. Each time a LOG_COMMIT or LOG_CKSUM is encountered, the 
**   recovery process verifies that the checksum stored in the log 
**   matches the calculated checksum. If it does not, the recovery process
**   can stop reading the log.
**
**   If a recovery process reads records (other than COMMIT or CKSUM) 
**   consisting of at least LSM_CKSUM_MAXDATA bytes, then the next record in
**   the log must be either a LOG_CKSUM or LOG_COMMIT record. If it is
**   not, the recovery process also stops reading the log.
**
**   To recover the log file, it must be read twice. The first time to 
**   determine the location of the last valid commit record. And the second
**   time to load data into the in-memory tree.
**
**   Todo: Surely there is a better way...
**
** LOG WRAPPING
**
**   If the log file were never deleted or wrapped, it would be possible to
**   read it from start to end each time is required recovery (i.e each time
**   the number of database clients changes from 0 to 1). Effectively reading
**   the entire history of the database each time. This would quickly become 
**   inefficient. Additionally, since the log file would grow without bound,
**   it wastes storage space.
**
**   Instead, part of each checkpoint written into the database file contains 
**   a log offset (and other information required to read the log starting at
**   at this offset) at which to begin recovery. Offset $O.
**
**   Once a checkpoint has been written and synced into the database file, it
**   is guaranteed that no recovery process will need to read any data before
**   offset $O of the log file. It is therefore safe to begin overwriting
**   any data that occurs before offset $O.
**
**   This implementation separates the log into three regions mapped into
**   the log file - regions 0, 1 and 2. During recovery, regions are read
**   in ascending order (i.e. 0, then 1, then 2). Each region is zero or
**   more bytes in size.
**
**     |---1---|..|--0--|.|--2--|....
**
**   New records are always appended to the end of region 2.
**
**   Initially (when it is empty), all three regions are zero bytes in size.
**   Each of them are located at the beginning of the file. As records are
**   added to the log, region 2 grows, so that the log consists of a zero
**   byte region 1, followed by a zero byte region 0, followed by an N byte
**   region 2. After one or more checkpoints have been written to disk, 
**   the start point of region 2 is moved to $O. For example:
**
**     A) ||.........|--2--|....
**   
**   (both regions 0 and 1 are 0 bytes in size at offset 0).
**
**   Eventually, the log wraps around to write new records into the start.
**   At this point, region 2 is renamed to region 0. Region 0 is renamed
**   to region 2. After appending a few records to the new region 2, the
**   log file looks like this:
**
**     B) ||--2--|...|--0--|....
**
**   (region 1 is still 0 bytes in size, located at offset 0).
**
**   Any checkpoints made at this point may reduce the size of region 0.
**   However, if they do not, and region 2 expands so that it is about to
**   overwrite the start of region 0, then region 2 is renamed to region 1,
**   and a new region 2 created at the end of the file following the existing
**   region 0.
**
**     C) |---1---|..|--0--|.|-2-|
**
**   In this state records are appended to region 2 until checkpoints have
**   contracted regions 0 AND 1 UNTil they are both zero bytes in size. They 
**   are then shifted to the start of the log file, leaving the system in 
**   the equivalent of state A above.
**
**   Alternatively, state B may transition directly to state A if the size
**   of region 0 is reduced to zero bytes before region 2 threatens to 
**   encroach upon it.
**
** LOG_PAD1 & LOG_PAD2 RECORDS
**
**   PAD1 and PAD2 records may appear in a log file at any point. They allow
**   a process writing the log file align the beginning of transactions with 
**   the beginning of disk sectors, which increases robustness.
**
** RECORD FORMATS:
**
**   LOG_EOF:    * A single 0x00 byte.
**
**   LOG_PAD1:   * A single 0x01 byte.
**
**   LOG_PAD2:   * A single 0x02 byte, followed by
**               * The number of unused bytes (N) as a varint,
**               * An N byte block of unused space.
**
**   LOG_COMMIT: * A single 0x03 byte.
**               * An 8-byte checksum.
**
**   LOG_JUMP:   * A single 0x04 byte.
**               * Absolute file offset to jump to, encoded as a varint.
**
**   LOG_WRITE:  * A single 0x06 or 0x07 byte, 
**               * The number of bytes in the key, encoded as a varint, 
**               * The number of bytes in the value, encoded as a varint, 
**               * If the first byte was 0x07, an 8 byte checksum.
**               * The key data,
**               * The value data.
**
**   LOG_DELETE: * A single 0x08 or 0x09 byte, 
**               * The number of bytes in the key, encoded as a varint, 
**               * If the first byte was 0x09, an 8 byte checksum.
**               * The key data.
**
**   Varints are as described in lsm_varint.c (SQLite 4 format).
**
** CHECKSUMS:
**
**   The checksum is calculated using two 32-bit unsigned integers, s0 and
**   s1. The initial value for both is 42. It is updated each time a record
**   is written into the log file by treating the encoded (binary) record as 
**   an array of 32-bit little-endian integers. Then, if x[] is the integer
**   array, updating the checksum accumulators as follows:
**
**     for i from 0 to n-1 step 2:
**       s0 += x[i] + s1;
**       s1 += x[i+1] + s0;
**     endfor
**
**   If the record is not an even multiple of 8-bytes in size it is padded
**   with zeroes to make it so before the checksum is updated.
**
**   The checksum stored in a COMMIT, WRITE or DELETE is based on all bytes
**   up to the start of the 8-byte checksum itself, including the COMMIT,
**   WRITE or DELETE fields that appear before the checksum in the record.
**
** VARINT FORMAT
**
** See lsm_varint.c.
*/

#ifndef _LSM_INT_H
#endif

/* Log record types */
#define LSM_LOG_EOF          0x00
#define LSM_LOG_PAD1         0x01
#define LSM_LOG_PAD2         0x02
#define LSM_LOG_COMMIT       0x03
#define LSM_LOG_JUMP         0x04

#define LSM_LOG_WRITE        0x06
#define LSM_LOG_WRITE_CKSUM  0x07
#define LSM_LOG_DELETE       0x08
#define LSM_LOG_DELETE_CKSUM 0x09

/* Require a checksum every 32KB. */
#define LSM_CKSUM_MAXDATA (32*1024)

/* Do not wrap a log file smaller than this in bytes. */
#define LSM_MIN_LOGWRAP      (128*1024)

/*
** szSector:
**   Commit records must be aligned to end on szSector boundaries. If
**   the safety-mode is set to NORMAL or OFF, this value is 1. Otherwise,
**   if the safety-mode is set to FULL, it is the size of the file-system
**   sectors as reported by lsmFsSectorSize().
*/
struct LogWriter {
  u32 cksum0;                     /* Checksum 0 at offset iOff */
  u32 cksum1;                     /* Checksum 1 at offset iOff */
  int iCksumBuf;                  /* Bytes of buf that have been checksummed */
  i64 iOff;                       /* Offset at start of buffer buf */
  int szSector;                   /* Sector size for this transaction */
  LogRegion jump;                 /* Avoid writing to this region */
  i64 iRegion1End;                /* End of first region written by trans */
  i64 iRegion2Start;              /* Start of second regions written by trans */
  LsmString buf;                  /* Buffer containing data not yet written */
};

/*
** Return the result of interpreting the first 4 bytes in buffer aIn as 
** a 32-bit unsigned little-endian integer.
*/
static u32 getU32le(u8 *aIn){
  return ((u32)aIn[3] << 24) 
       + ((u32)aIn[2] << 16) 
       + ((u32)aIn[1] << 8) 
       + ((u32)aIn[0]);
}


/*
** This function is the same as logCksum(), except that pointer "a" need
** not be aligned to an 8-byte boundary or padded with zero bytes. This
** version is slower, but sometimes more convenient to use.
*/
static void logCksumUnaligned(
  char *z,                        /* Input buffer */
  int n,                          /* Size of input buffer in bytes */
  u32 *pCksum0,                   /* IN/OUT: Checksum value 1 */
  u32 *pCksum1                    /* IN/OUT: Checksum value 2 */
){
  u8 *a = (u8 *)z;
  u32 cksum0 = *pCksum0;
  u32 cksum1 = *pCksum1;
  int nIn = (n/8) * 8;
  int i;

  assert( n>0 );
  for(i=0; i<nIn; i+=8){
    cksum0 += getU32le(&a[i]) + cksum1;
    cksum1 += getU32le(&a[i+4]) + cksum0;
  }

  if( nIn!=n ){
    u8 aBuf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    assert( (n-nIn)<8 && n>nIn );
    memcpy(aBuf, &a[nIn], n-nIn);
    cksum0 += getU32le(aBuf) + cksum1;
    cksum1 += getU32le(&aBuf[4]) + cksum0;
  }

  *pCksum0 = cksum0;
  *pCksum1 = cksum1;
}

/*
** Update pLog->cksum0 and pLog->cksum1 so that the first nBuf bytes in the 
** write buffer (pLog->buf) are included in the checksum.
*/
static void logUpdateCksum(LogWriter *pLog, int nBuf){
  assert( (pLog->iCksumBuf % 8)==0 );
  assert( pLog->iCksumBuf<=nBuf );
  assert( (nBuf % 8)==0 || nBuf==pLog->buf.n );
  if( nBuf>pLog->iCksumBuf ){
    logCksumUnaligned(
        &pLog->buf.z[pLog->iCksumBuf], nBuf-pLog->iCksumBuf, 
        &pLog->cksum0, &pLog->cksum1
    );
  }
  pLog->iCksumBuf = nBuf;
}

static i64 firstByteOnSector(LogWriter *pLog, i64 iOff){
  return (iOff / pLog->szSector) * pLog->szSector;
}
static i64 lastByteOnSector(LogWriter *pLog, i64 iOff){
  return firstByteOnSector(pLog, iOff) + pLog->szSector - 1;
}

/*
** If possible, reclaim log file space. Log file space is reclaimed after
** a snapshot that points to the same data in the database file is synced
** into the db header.
*/
static int logReclaimSpace(lsm_db *pDb){
  int rc;
  int iMeta;
  int bRotrans;                   /* True if there exists some ro-trans */

  /* Test if there exists some other connection with a read-only transaction
  ** open. If there does, then log file space may not be reclaimed.  */
  rc = lsmDetectRoTrans(pDb, &bRotrans);
  if( rc!=LSM_OK || bRotrans ) return rc;

  iMeta = (int)pDb->pShmhdr->iMetaPage;
  if( iMeta==1 || iMeta==2 ){
    DbLog *pLog = &pDb->treehdr.log;
    i64 iSyncedId;

    /* Read the snapshot-id of the snapshot stored on meta-page iMeta. Note
    ** that in theory, the value read is untrustworthy (due to a race 
    ** condition - see comments above lsmFsReadSyncedId()). So it is only 
    ** ever used to conclude that no log space can be reclaimed. If it seems
    ** to indicate that it may be possible to reclaim log space, a
    ** second call to lsmCheckpointSynced() (which does return trustworthy
    ** values) is made below to confirm.  */
    rc = lsmFsReadSyncedId(pDb, iMeta, &iSyncedId);

    if( rc==LSM_OK && pLog->iSnapshotId!=iSyncedId ){
      i64 iSnapshotId = 0;
      i64 iOff = 0;
      rc = lsmCheckpointSynced(pDb, &iSnapshotId, &iOff, 0);
      if( rc==LSM_OK && pLog->iSnapshotId<iSnapshotId ){
        int iRegion;
        for(iRegion=0; iRegion<3; iRegion++){
          LogRegion *p = &pLog->aRegion[iRegion];
          if( iOff>=p->iStart && iOff<=p->iEnd ) break;
          p->iStart = 0;
          p->iEnd = 0;
        }
        assert( iRegion<3 );
        pLog->aRegion[iRegion].iStart = iOff;
        pLog->iSnapshotId = iSnapshotId;
      }
    }
  }
  return rc;
}

/*
** This function is called when a write-transaction is first opened. It
** is assumed that the caller is holding the client-mutex when it is 
** called.
**
** Before returning, this function allocates the LogWriter object that
** will be used to write to the log file during the write transaction.
** LSM_OK is returned if no error occurs, otherwise an LSM error code.
*/
int lsmLogBegin(lsm_db *pDb){
  int rc = LSM_OK;
  LogWriter *pNew;
  LogRegion *aReg;

  if( pDb->bUseLog==0 ) return LSM_OK;

  /* If the log file has not yet been opened, open it now. Also allocate
  ** the LogWriter structure, if it has not already been allocated.  */
  rc = lsmFsOpenLog(pDb, 0);
  if( pDb->pLogWriter==0 ){
    pNew = lsmMallocZeroRc(pDb->pEnv, sizeof(LogWriter), &rc);
    if( pNew ){
      lsmStringInit(&pNew->buf, pDb->pEnv);
      rc = lsmStringExtend(&pNew->buf, 2);
    }
  }else{
    pNew = pDb->pLogWriter;
    assert( (u8 *)(&pNew[1])==(u8 *)(&((&pNew->buf)[1])) );
    memset(pNew, 0, ((u8 *)&pNew->buf) - (u8 *)pNew);
    pNew->buf.n = 0;
  }

  if( rc==LSM_OK ){
    /* The following call detects whether or not a new snapshot has been 
    ** synced into the database file. If so, it updates the contents of
    ** the pDb->treehdr.log structure to reclaim any space in the log
    ** file that is no longer required. 
    **
    ** TODO: Calling this every transaction is overkill. And since the 
    ** call has to read and checksum a snapshot from the database file,
    ** it is expensive. It would be better to figure out a way so that
    ** this is only called occasionally - say for every 32KB written to 
    ** the log file.
    */
    rc = logReclaimSpace(pDb);
  }
  if( rc!=LSM_OK ){
    lsmLogClose(pDb);
    return rc;
  }

  /* Set the effective sector-size for this transaction. Sectors are assumed
  ** to be one byte in size if the safety-mode is OFF or NORMAL, or as
  ** reported by lsmFsSectorSize if it is FULL.  */
  if( pDb->eSafety==LSM_SAFETY_FULL ){
    pNew->szSector = lsmFsSectorSize(pDb->pFS);
    assert( pNew->szSector>0 );
  }else{
    pNew->szSector = 1;
  }

  /* There are now three scenarios:
  **
  **   1) Regions 0 and 1 are both zero bytes in size and region 2 begins
  **      at a file offset greater than LSM_MIN_LOGWRAP. In this case, wrap
  **      around to the start and write data into the start of the log file. 
  **
  **   2) Region 1 is zero bytes in size and region 2 occurs earlier in the 
  **      file than region 0. In this case, append data to region 2, but
  **      remember to jump over region 1 if required.
  **
  **   3) Region 2 is the last in the file. Append to it.
  */
  aReg = &pDb->treehdr.log.aRegion[0];

  assert( aReg[0].iEnd==0 || aReg[0].iEnd>aReg[0].iStart );
  assert( aReg[1].iEnd==0 || aReg[1].iEnd>aReg[1].iStart );

  pNew->cksum0 = pDb->treehdr.log.cksum0;
  pNew->cksum1 = pDb->treehdr.log.cksum1;

  if( aReg[0].iEnd==0 && aReg[1].iEnd==0 && aReg[2].iStart>=LSM_MIN_LOGWRAP ){
    /* Case 1. Wrap around to the start of the file. Write an LSM_LOG_JUMP 
    ** into the log file in this case. Pad it out to 8 bytes using a PAD2
    ** record so that the checksums can be updated immediately.  */
    u8 aJump[] = { 
      LSM_LOG_PAD2, 0x04, 0x00, 0x00, 0x00, 0x00, LSM_LOG_JUMP, 0x00 
    };

    lsmStringBinAppend(&pNew->buf, aJump, sizeof(aJump));
    logUpdateCksum(pNew, pNew->buf.n);
    rc = lsmFsWriteLog(pDb->pFS, aReg[2].iEnd, &pNew->buf);
    pNew->iCksumBuf = pNew->buf.n = 0;

    aReg[2].iEnd += 8;
    pNew->jump = aReg[0] = aReg[2];
    aReg[2].iStart = aReg[2].iEnd = 0;
  }else if( aReg[1].iEnd==0 && aReg[2].iEnd<aReg[0].iEnd ){
    /* Case 2. */
    pNew->iOff = aReg[2].iEnd;
    pNew->jump = aReg[0];
  }else{
    /* Case 3. */
    assert( aReg[2].iStart>=aReg[0].iEnd && aReg[2].iStart>=aReg[1].iEnd );
    pNew->iOff = aReg[2].iEnd;
  }

  if( pNew->jump.iStart ){
    i64 iRound;
    assert( pNew->jump.iStart>pNew->iOff );

    iRound = firstByteOnSector(pNew, pNew->jump.iStart);
    if( iRound>pNew->iOff ) pNew->jump.iStart = iRound;
    pNew->jump.iEnd = lastByteOnSector(pNew, pNew->jump.iEnd);
  }

  pDb->pLogWriter = pNew;
  return rc;
}

/*
** This function is called when a write-transaction is being closed.
** Parameter bCommit is true if the transaction is being committed,
** or false otherwise. The caller must hold the client-mutex to call
** this function.
**
** A call to this function deletes the LogWriter object allocated by
** lsmLogBegin(). If the transaction is being committed, the shared state
** in *pLog is updated before returning.
*/
void lsmLogEnd(lsm_db *pDb, int bCommit){
  DbLog *pLog;
  LogWriter *p;
  p = pDb->pLogWriter;

  if( p==0 ) return;
  pLog = &pDb->treehdr.log;

  if( bCommit ){
    pLog->aRegion[2].iEnd = p->iOff;
    pLog->cksum0 = p->cksum0;
    pLog->cksum1 = p->cksum1;
    if( p->iRegion1End ){
      /* This happens when the transaction had to jump over some other
      ** part of the log.  */
      assert( pLog->aRegion[1].iEnd==0 );
      assert( pLog->aRegion[2].iStart<p->iRegion1End );
      pLog->aRegion[1].iStart = pLog->aRegion[2].iStart;
      pLog->aRegion[1].iEnd = p->iRegion1End;
      pLog->aRegion[2].iStart = p->iRegion2Start;
    }
  }
}

static int jumpIfRequired(
  lsm_db *pDb,
  LogWriter *pLog,
  int nReq,
  int *pbJump
){
  /* Determine if it is necessary to add an LSM_LOG_JUMP to jump over the
  ** jump region before writing the LSM_LOG_WRITE or DELETE record. This
  ** is necessary if there is insufficient room between the current offset
  ** and the jump region to fit the new WRITE/DELETE record and the largest
  ** possible JUMP record with up to 7 bytes of padding (a total of 17 
  ** bytes).  */
  if( (pLog->jump.iStart > (pLog->iOff + pLog->buf.n))
   && (pLog->jump.iStart < (pLog->iOff + pLog->buf.n + (nReq + 17))) 
  ){
    int rc;                       /* Return code */
    i64 iJump;                    /* Offset to jump to */
    u8 aJump[10];                 /* Encoded jump record */
    int nJump;                    /* Valid bytes in aJump[] */
    int nPad;                     /* Bytes of padding required */

    /* Serialize the JUMP record */
    iJump = pLog->jump.iEnd+1;
    aJump[0] = LSM_LOG_JUMP;
    nJump = 1 + lsmVarintPut64(&aJump[1], iJump);

    /* Adding padding to the contents of the buffer so that it will be a 
    ** multiple of 8 bytes in size after the JUMP record is appended. This
    ** is not strictly required, it just makes the keeping the running 
    ** checksum up to date in this file a little simpler.  */
    nPad = (pLog->buf.n + nJump) % 8;
    if( nPad ){
      u8 aPad[7] = {0,0,0,0,0,0,0};
      nPad = 8-nPad;
      if( nPad==1 ){
        aPad[0] = LSM_LOG_PAD1;
      }else{
        aPad[0] = LSM_LOG_PAD2;
        aPad[1] = (nPad-2);
      }
      rc = lsmStringBinAppend(&pLog->buf, aPad, nPad);
      if( rc!=LSM_OK ) return rc;
    }

    /* Append the JUMP record to the buffer. Then flush the buffer to disk
    ** and update the checksums. The next write to the log file (assuming
    ** there is no transaction rollback) will be to offset iJump (just past
    ** the jump region).  */
    rc = lsmStringBinAppend(&pLog->buf, aJump, nJump);
    if( rc!=LSM_OK ) return rc;
    assert( (pLog->buf.n % 8)==0 );
    rc = lsmFsWriteLog(pDb->pFS, pLog->iOff, &pLog->buf);
    if( rc!=LSM_OK ) return rc;
    logUpdateCksum(pLog, pLog->buf.n);
    pLog->iRegion1End = (pLog->iOff + pLog->buf.n);
    pLog->iRegion2Start = iJump;
    pLog->iOff = iJump;
    pLog->iCksumBuf = pLog->buf.n = 0;
    if( pbJump ) *pbJump = 1;
  }

  return LSM_OK;
}

static int logCksumAndFlush(lsm_db *pDb){
  int rc;                         /* Return code */
  LogWriter *pLog = pDb->pLogWriter;

  /* Calculate the checksum value. Append it to the buffer. */
  logUpdateCksum(pLog, pLog->buf.n);
  lsmPutU32((u8 *)&pLog->buf.z[pLog->buf.n], pLog->cksum0);
  pLog->buf.n += 4;
  lsmPutU32((u8 *)&pLog->buf.z[pLog->buf.n], pLog->cksum1);
  pLog->buf.n += 4;

  /* Write the contents of the buffer to disk. */
  rc = lsmFsWriteLog(pDb->pFS, pLog->iOff, &pLog->buf);
  pLog->iOff += pLog->buf.n;
  pLog->iCksumBuf = pLog->buf.n = 0;

  return rc;
}

/*
** Write the contents of the log-buffer to disk. Then write either a CKSUM
** or COMMIT record, depending on the value of parameter eType.
*/
static int logFlush(lsm_db *pDb, int eType){
  int rc;
  int nReq;
  LogWriter *pLog = pDb->pLogWriter;
  
  assert( eType==LSM_LOG_COMMIT );
  assert( pLog );

  /* Commit record is always 9 bytes in size. */
  nReq = 9;
  if( eType==LSM_LOG_COMMIT && pLog->szSector>1 ) nReq += pLog->szSector + 17;
  rc = jumpIfRequired(pDb, pLog, nReq, 0);

  /* If this is a COMMIT, add padding to the log so that the COMMIT record
  ** is aligned against the end of a disk sector. In other words, add padding
  ** so that the first byte following the COMMIT record lies on a different
  ** sector.  */
  if( eType==LSM_LOG_COMMIT && pLog->szSector>1 ){
    int nPad;                     /* Bytes of padding to add */

    /* Determine the value of nPad. */
    nPad = ((pLog->iOff + pLog->buf.n + 9) % pLog->szSector);
    if( nPad ) nPad = pLog->szSector - nPad;
    rc = lsmStringExtend(&pLog->buf, nPad);
    if( rc!=LSM_OK ) return rc;

    while( nPad ){
      if( nPad==1 ){
        pLog->buf.z[pLog->buf.n++] = LSM_LOG_PAD1;
        nPad = 0;
      }else{
        int n = LSM_MIN(200, nPad-2);
        pLog->buf.z[pLog->buf.n++] = LSM_LOG_PAD2;
        pLog->buf.z[pLog->buf.n++] = n;
        nPad -= 2;
        memset(&pLog->buf.z[pLog->buf.n], 0x2B, n);
        pLog->buf.n += n;
        nPad -= n;
      }
    }
  }

  /* Make sure there is room in the log-buffer to add the CKSUM or COMMIT
  ** record. Then add the first byte of it.  */
  rc = lsmStringExtend(&pLog->buf, 9);
  if( rc!=LSM_OK ) return rc;
  pLog->buf.z[pLog->buf.n++] = eType;
  memset(&pLog->buf.z[pLog->buf.n], 0, 8);

  rc = logCksumAndFlush(pDb);

  /* If this is a commit and synchronous=full, sync the log to disk. */
  if( rc==LSM_OK && eType==LSM_LOG_COMMIT && pDb->eSafety==LSM_SAFETY_FULL ){
    rc = lsmFsSyncLog(pDb->pFS);
  }
  return rc;
}

/*
** Append an LSM_LOG_WRITE (if nVal>=0) or LSM_LOG_DELETE (if nVal<0) 
** record to the database log.
*/
int lsmLogWrite(
  lsm_db *pDb,                    /* Database handle */
  void *pKey, int nKey,           /* Database key to write to log */
  void *pVal, int nVal            /* Database value (or nVal<0) to write */
){
  int rc = LSM_OK;
  LogWriter *pLog;                /* Log object to write to */
  int nReq;                       /* Bytes of space required in log */
  int bCksum = 0;                 /* True to embed a checksum in this record */

  if( pDb->bUseLog==0 ) return LSM_OK;
  pLog = pDb->pLogWriter;

  /* Determine how many bytes of space are required, assuming that a checksum
  ** will be embedded in this record (even though it may not be).  */
  nReq = 1 + lsmVarintLen32(nKey) + 8 + nKey;
  if( nVal>=0 ) nReq += lsmVarintLen32(nVal) + nVal;

  /* Jump over the jump region if required. Set bCksum to true to tell the
  ** code below to include a checksum in the record if either (a) writing
  ** this record would mean that more than LSM_CKSUM_MAXDATA bytes of data
  ** have been written to the log since the last checksum, or (b) the jump
  ** is taken.  */
  rc = jumpIfRequired(pDb, pLog, nReq, &bCksum);
  if( (pLog->buf.n+nReq) > LSM_CKSUM_MAXDATA ) bCksum = 1;

  if( rc==LSM_OK ){
    rc = lsmStringExtend(&pLog->buf, nReq);
  }
  if( rc==LSM_OK ){
    u8 *a = (u8 *)&pLog->buf.z[pLog->buf.n];
    
    /* Write the record header - the type byte followed by either 1 (for
    ** DELETE) or 2 (for WRITE) varints.  */
    assert( LSM_LOG_WRITE_CKSUM == (LSM_LOG_WRITE | 0x0001) );
    assert( LSM_LOG_DELETE_CKSUM == (LSM_LOG_DELETE | 0x0001) );
    *(a++) = (nVal>=0 ? LSM_LOG_WRITE : LSM_LOG_DELETE) | (u8)bCksum;
    a += lsmVarintPut32(a, nKey);
    if( nVal>=0 ) a += lsmVarintPut32(a, nVal);

    if( bCksum ){
      pLog->buf.n = (a - (u8 *)pLog->buf.z);
      rc = logCksumAndFlush(pDb);
      a = (u8 *)&pLog->buf.z[pLog->buf.n];
    }

    memcpy(a, pKey, nKey);
    a += nKey;
    if( nVal>=0 ){
      memcpy(a, pVal, nVal);
      a += nVal;
    }
    pLog->buf.n = a - (u8 *)pLog->buf.z;
    assert( pLog->buf.n<=pLog->buf.nAlloc );
  }

  return rc;
}

/*
** Append an LSM_LOG_COMMIT record to the database log.
*/
int lsmLogCommit(lsm_db *pDb){
  if( pDb->bUseLog==0 ) return LSM_OK;
  return logFlush(pDb, LSM_LOG_COMMIT);
}

/*
** Store the current offset and other checksum related information in the
** structure *pMark. Later, *pMark can be passed to lsmLogSeek() to "rewind"
** the LogWriter object to the current log file offset. This is used when
** rolling back savepoint transactions.
*/
void lsmLogTell(
  lsm_db *pDb,                    /* Database handle */
  LogMark *pMark                  /* Populate this object with current offset */
){
  LogWriter *pLog;
  int nCksum;

  if( pDb->bUseLog==0 ) return;
  pLog = pDb->pLogWriter;
  nCksum = pLog->buf.n & 0xFFFFFFF8;
  logUpdateCksum(pLog, nCksum);
  assert( pLog->iCksumBuf==nCksum );
  pMark->nBuf = pLog->buf.n - nCksum;
  memcpy(pMark->aBuf, &pLog->buf.z[nCksum], pMark->nBuf);

  pMark->iOff = pLog->iOff + pLog->buf.n;
  pMark->cksum0 = pLog->cksum0;
  pMark->cksum1 = pLog->cksum1;
}

/*
** Seek (rewind) back to the log file offset stored by an ealier call to
** lsmLogTell() in *pMark.
*/
void lsmLogSeek(
  lsm_db *pDb,                    /* Database handle */
  LogMark *pMark                  /* Object containing log offset to seek to */
){
  LogWriter *pLog;

  if( pDb->bUseLog==0 ) return;
  pLog = pDb->pLogWriter;

  assert( pMark->iOff<=pLog->iOff+pLog->buf.n );
  if( (pMark->iOff & 0xFFFFFFF8)>=pLog->iOff ){
    pLog->buf.n = pMark->iOff - pLog->iOff;
    pLog->iCksumBuf = (pLog->buf.n & 0xFFFFFFF8);
  }else{
    pLog->buf.n = pMark->nBuf;
    memcpy(pLog->buf.z, pMark->aBuf, pMark->nBuf);
    pLog->iCksumBuf = 0;
    pLog->iOff = pMark->iOff - pMark->nBuf;
  }
  pLog->cksum0 = pMark->cksum0;
  pLog->cksum1 = pMark->cksum1;

  if( pMark->iOff > pLog->iRegion1End ) pLog->iRegion1End = 0;
  if( pMark->iOff > pLog->iRegion2Start ) pLog->iRegion2Start = 0;
}

/*
** This function does the work for an lsm_info(LOG_STRUCTURE) request.
*/
int lsmInfoLogStructure(lsm_db *pDb, char **pzVal){
  int rc = LSM_OK;
  char *zVal = 0;

  /* If there is no read or write transaction open, read the latest 
  ** tree-header from shared-memory to report on. If necessary, update
  ** it based on the contents of the database header.  
  **
  ** No locks are taken here - these are passive read operations only.
  */
  if( pDb->pCsr==0 && pDb->nTransOpen==0 ){
    rc = lsmTreeLoadHeader(pDb, 0);
    if( rc==LSM_OK ) rc = logReclaimSpace(pDb);
  }

  if( rc==LSM_OK ){
    DbLog *pLog = &pDb->treehdr.log;
    zVal = lsmMallocPrintf(pDb->pEnv, 
        "%d %d %d %d %d %d", 
        (int)pLog->aRegion[0].iStart, (int)pLog->aRegion[0].iEnd,
        (int)pLog->aRegion[1].iStart, (int)pLog->aRegion[1].iEnd,
        (int)pLog->aRegion[2].iStart, (int)pLog->aRegion[2].iEnd
    );
    if( !zVal ) rc = LSM_NOMEM_BKPT;
  }

  *pzVal = zVal;
  return rc;
}

/*************************************************************************
** Begin code for log recovery.
*/

typedef struct LogReader LogReader;
struct LogReader {
  FileSystem *pFS;                /* File system to read from */
  i64 iOff;                       /* File offset at end of buf content */
  int iBuf;                       /* Current read offset in buf */
  LsmString buf;                  /* Buffer containing file content */

  int iCksumBuf;                  /* Offset in buf corresponding to cksum[01] */
  u32 cksum0;                     /* Checksum 0 at offset iCksumBuf */
  u32 cksum1;                     /* Checksum 1 at offset iCksumBuf */
};

static void logReaderBlob(
  LogReader *p,                   /* Log reader object */
  LsmString *pBuf,                /* Dynamic storage, if required */
  int nBlob,                      /* Number of bytes to read */
  u8 **ppBlob,                    /* OUT: Pointer to blob read */
  int *pRc                        /* IN/OUT: Error code */
){
  static const int LOG_READ_SIZE = 512;
  int rc = *pRc;                  /* Return code */
  int nReq = nBlob;               /* Bytes required */

  while( rc==LSM_OK && nReq>0 ){
    int nAvail;                   /* Bytes of data available in p->buf */
    if( p->buf.n==p->iBuf ){
      int nCksum;                 /* Total bytes requiring checksum */
      int nCarry = 0;             /* Total bytes requiring checksum */

      nCksum = p->iBuf - p->iCksumBuf;
      if( nCksum>0 ){
        nCarry = nCksum % 8;
        nCksum = ((nCksum / 8) * 8);
        if( nCksum>0 ){
          logCksumUnaligned(
              &p->buf.z[p->iCksumBuf], nCksum, &p->cksum0, &p->cksum1
          );
        }
      }
      if( nCarry>0 ) memcpy(p->buf.z, &p->buf.z[p->iBuf-nCarry], nCarry);
      p->buf.n = nCarry;
      p->iBuf = nCarry;

      rc = lsmFsReadLog(p->pFS, p->iOff, LOG_READ_SIZE, &p->buf);
      if( rc!=LSM_OK ) break;
      p->iCksumBuf = 0;
      p->iOff += LOG_READ_SIZE;
    }

    nAvail = p->buf.n - p->iBuf;
    if( ppBlob && nReq==nBlob && nBlob<=nAvail ){
      *ppBlob = (u8 *)&p->buf.z[p->iBuf];
      p->iBuf += nBlob;
      nReq = 0;
    }else{
      int nCopy = LSM_MIN(nAvail, nReq);
      if( nBlob==nReq ){
        if( ppBlob ) *ppBlob = (u8 *)pBuf->z;
        pBuf->n = 0;
      }
      rc = lsmStringBinAppend(pBuf, (u8 *)&p->buf.z[p->iBuf], nCopy);
      nReq -= nCopy;
      p->iBuf += nCopy;
    }
  }

  *pRc = rc;
}

static void logReaderVarint(
  LogReader *p, 
  LsmString *pBuf,
  int *piVal,                     /* OUT: Value read from log */
  int *pRc                        /* IN/OUT: Error code */
){
  if( *pRc==LSM_OK ){
    u8 *aVarint;
    if( p->buf.n==p->iBuf ){
      logReaderBlob(p, 0, 10, &aVarint, pRc);
      if( LSM_OK==*pRc ) p->iBuf -= (10 - lsmVarintGet32(aVarint, piVal));
    }else{
      logReaderBlob(p, pBuf, lsmVarintSize(p->buf.z[p->iBuf]), &aVarint, pRc);
      if( LSM_OK==*pRc ) lsmVarintGet32(aVarint, piVal);
    }
  }
}

static void logReaderByte(LogReader *p, u8 *pByte, int *pRc){
  u8 *pPtr = 0;
  logReaderBlob(p, 0, 1, &pPtr, pRc);
  if( pPtr ) *pByte = *pPtr;
}

static void logReaderCksum(LogReader *p, LsmString *pBuf, int *pbEof, int *pRc){
  if( *pRc==LSM_OK ){
    u8 *pPtr = 0;
    u32 cksum0, cksum1;
    int nCksum = p->iBuf - p->iCksumBuf;

    /* Update in-memory (expected) checksums */
    assert( nCksum>=0 );
    logCksumUnaligned(&p->buf.z[p->iCksumBuf], nCksum, &p->cksum0, &p->cksum1);
    p->iCksumBuf = p->iBuf + 8;
    logReaderBlob(p, pBuf, 8, &pPtr, pRc);

    /* Read the checksums from the log file. Set *pbEof if they do not match. */
    if( pPtr ){
      cksum0 = lsmGetU32(pPtr);
      cksum1 = lsmGetU32(&pPtr[4]);
      *pbEof = (cksum0!=p->cksum0 || cksum1!=p->cksum1);
      p->iCksumBuf = p->iBuf;
    }
  }
}

static void logReaderInit(
  lsm_db *pDb,                    /* Database handle */
  DbLog *pLog,                    /* Log object associated with pDb */
  int bInitBuf,                   /* True if p->buf is uninitialized */
  LogReader *p                    /* Initialize this LogReader object */
){
  p->pFS = pDb->pFS;
  p->iOff = pLog->aRegion[2].iStart;
  p->cksum0 = pLog->cksum0;
  p->cksum1 = pLog->cksum1;
  if( bInitBuf ){ lsmStringInit(&p->buf, pDb->pEnv); }
  p->buf.n = 0;
  p->iCksumBuf = 0;
  p->iBuf = 0;
}

/*
** This function is called after reading the header of a LOG_DELETE or
** LOG_WRITE record. Parameter nByte is the total size of the key and
** value that follow the header just read. Return true if the size and
** position of the record indicate that it should contain a checksum.
*/
static int logRequireCksum(LogReader *p, int nByte){
  return ((p->iBuf + nByte - p->iCksumBuf) > LSM_CKSUM_MAXDATA);
}

/*
** Recover the contents of the log file.
*/
int lsmLogRecover(lsm_db *pDb){
  LsmString buf1;                 /* Key buffer */
  LsmString buf2;                 /* Value buffer */
  LogReader reader;               /* Log reader object */
  int rc = LSM_OK;                /* Return code */
  int nCommit = 0;                /* Number of transactions to recover */
  int iPass;
  int nJump = 0;                  /* Number of LSM_LOG_JUMP records in pass 0 */
  DbLog *pLog;
  int bOpen;

  rc = lsmFsOpenLog(pDb, &bOpen);
  if( rc!=LSM_OK ) return rc;

  rc = lsmTreeInit(pDb);
  if( rc!=LSM_OK ) return rc;

  pLog = &pDb->treehdr.log;
  lsmCheckpointLogoffset(pDb->pShmhdr->aSnap2, pLog);

  logReaderInit(pDb, pLog, 1, &reader);
  lsmStringInit(&buf1, pDb->pEnv);
  lsmStringInit(&buf2, pDb->pEnv);

  /* The outer for() loop runs at most twice. The first iteration is to 
  ** count the number of committed transactions in the log. The second 
  ** iterates through those transactions and updates the in-memory tree 
  ** structure with their contents.  */
  if( bOpen ){
    for(iPass=0; iPass<2 && rc==LSM_OK; iPass++){
      int bEof = 0;

      while( rc==LSM_OK && !bEof ){
        u8 eType = 0;
        logReaderByte(&reader, &eType, &rc);

        switch( eType ){
          case LSM_LOG_PAD1:
            break;

          case LSM_LOG_PAD2: {
            int nPad;
            logReaderVarint(&reader, &buf1, &nPad, &rc);
            logReaderBlob(&reader, &buf1, nPad, 0, &rc);
            break;
          }

          case LSM_LOG_WRITE:
          case LSM_LOG_WRITE_CKSUM: {
            int nKey;
            int nVal;
            u8 *aVal;
            logReaderVarint(&reader, &buf1, &nKey, &rc);
            logReaderVarint(&reader, &buf2, &nVal, &rc);

            if( eType==LSM_LOG_WRITE_CKSUM ){
              logReaderCksum(&reader, &buf1, &bEof, &rc);
            }else{
              bEof = logRequireCksum(&reader, nKey+nVal);
            }
            if( bEof ) break;

            logReaderBlob(&reader, &buf1, nKey, 0, &rc);
            logReaderBlob(&reader, &buf2, nVal, &aVal, &rc);
            if( iPass==1 && rc==LSM_OK ){ 
              rc = lsmTreeInsert(pDb, (u8 *)buf1.z, nKey, aVal, nVal);
            }
            break;
          }

          case LSM_LOG_DELETE:
          case LSM_LOG_DELETE_CKSUM: {
            int nKey; u8 *aKey;
            logReaderVarint(&reader, &buf1, &nKey, &rc);

            if( eType==LSM_LOG_DELETE_CKSUM ){
              logReaderCksum(&reader, &buf1, &bEof, &rc);
            }else{
              bEof = logRequireCksum(&reader, nKey);
            }
            if( bEof ) break;

            logReaderBlob(&reader, &buf1, nKey, &aKey, &rc);
            if( iPass==1 && rc==LSM_OK ){ 
              rc = lsmTreeInsert(pDb, aKey, nKey, NULL, -1);
            }
            break;
          }

          case LSM_LOG_COMMIT:
            logReaderCksum(&reader, &buf1, &bEof, &rc);
            if( bEof==0 ){
              nCommit++;
              assert( nCommit>0 || iPass==1 );
              if( nCommit==0 ) bEof = 1;
            }
            break;

          case LSM_LOG_JUMP: {
            int iOff = 0;
            logReaderVarint(&reader, &buf1, &iOff, &rc);
            if( rc==LSM_OK ){
              if( iPass==1 ){
                if( pLog->aRegion[2].iStart==0 ){
                  assert( pLog->aRegion[1].iStart==0 );
                  pLog->aRegion[1].iEnd = reader.iOff;
                }else{
                  assert( pLog->aRegion[0].iStart==0 );
                  pLog->aRegion[0].iStart = pLog->aRegion[2].iStart;
                  pLog->aRegion[0].iEnd = reader.iOff-reader.buf.n+reader.iBuf;
                }
                pLog->aRegion[2].iStart = iOff;
              }else{
                if( (nJump++)==2 ){
                  bEof = 1;
                }
              }

              reader.iOff = iOff;
              reader.buf.n = reader.iBuf;
            }
            break;
          }

          default:
            /* Including LSM_LOG_EOF */
            bEof = 1;
            break;
        }
      }

      if( rc==LSM_OK && iPass==0 ){
        if( nCommit==0 ){
          if( pLog->aRegion[2].iStart==0 ){
            iPass = 1;
          }else{
            pLog->aRegion[2].iStart = 0;
            iPass = -1;
            lsmCheckpointZeroLogoffset(pDb);
          }
        }
        logReaderInit(pDb, pLog, 0, &reader);
        nCommit = nCommit * -1;
      }
    }
  }

  /* Initialize DbLog object */
  if( rc==LSM_OK ){
    pLog->aRegion[2].iEnd = reader.iOff - reader.buf.n + reader.iBuf;
    pLog->cksum0 = reader.cksum0;
    pLog->cksum1 = reader.cksum1;
  }

  if( rc==LSM_OK ){
    rc = lsmFinishRecovery(pDb);
  }else{
    lsmFinishRecovery(pDb);
  }

  if( pDb->bRoTrans ){
    lsmFsCloseLog(pDb);
  }

  lsmStringClear(&buf1);
  lsmStringClear(&buf2);
  lsmStringClear(&reader.buf);
  return rc;
}

void lsmLogClose(lsm_db *db){
  if( db->pLogWriter ){
    lsmFree(db->pEnv, db->pLogWriter->buf.z);
    lsmFree(db->pEnv, db->pLogWriter);
    db->pLogWriter = 0;
  }
}

/************** End of lsm_log.c *********************************************/
/************** Begin file lsm_main.c ****************************************/
/*
** 2011-08-18
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** The main interface to the LSM module.
*/


#ifdef LSM_DEBUG
/*
** This function returns a copy of its only argument.
**
** When the library is built with LSM_DEBUG defined, this function is called
** whenever an error code is generated (not propagated - generated). So
** if the library is mysteriously returning (say) LSM_IOERR, a breakpoint
** may be set in this function to determine why.
*/
int lsmErrorBkpt(int rc){
  /* Set breakpoint here! */
  return rc;
}

/*
** This function contains various assert() statements that test that the
** lsm_db structure passed as an argument is internally consistent.
*/
static void assert_db_state(lsm_db *pDb){

  /* If there is at least one cursor or a write transaction open, the database
  ** handle must be holding a pointer to a client snapshot. And the reverse 
  ** - if there are no open cursors and no write transactions then there must 
  ** not be a client snapshot.  */
  
  assert( (pDb->pCsr!=0||pDb->nTransOpen>0)==(pDb->iReader>=0||pDb->bRoTrans) );

  assert( (pDb->iReader<0 && pDb->bRoTrans==0) || pDb->pClient!=0 );

  assert( pDb->nTransOpen>=0 );
}
#else
# define assert_db_state(x) 
#endif

/*
** The default key-compare function.
*/
static int xCmp(void *p1, int n1, void *p2, int n2){
  int res;
  res = memcmp(p1, p2, LSM_MIN(n1, n2));
  if( res==0 ) res = (n1-n2);
  return res;
}

static void xLog(void *pCtx, int rc, const char *z){
  (void)(rc);
  (void)(pCtx);
  fprintf(stderr, "%s\n", z);
  fflush(stderr);
}

/*
** Allocate a new db handle.
*/
int lsm_new(lsm_env *pEnv, lsm_db **ppDb){
  lsm_db *pDb;

  /* If the user did not provide an environment, use the default. */
  if( pEnv==0 ) pEnv = lsm_default_env();
  assert( pEnv );

  /* Allocate the new database handle */
  *ppDb = pDb = (lsm_db *)lsmMallocZero(pEnv, sizeof(lsm_db));
  if( pDb==0 ) return LSM_NOMEM_BKPT;

  /* Initialize the new object */
  pDb->pEnv = pEnv;
  pDb->nTreeLimit = LSM_DFLT_AUTOFLUSH;
  pDb->nAutockpt = LSM_DFLT_AUTOCHECKPOINT;
  pDb->bAutowork = LSM_DFLT_AUTOWORK;
  pDb->eSafety = LSM_DFLT_SAFETY;
  pDb->xCmp = xCmp;
  pDb->nDfltPgsz = LSM_DFLT_PAGE_SIZE;
  pDb->nDfltBlksz = LSM_DFLT_BLOCK_SIZE;
  pDb->nMerge = LSM_DFLT_AUTOMERGE;
  pDb->nMaxFreelist = LSM_MAX_FREELIST_ENTRIES;
  pDb->bUseLog = LSM_DFLT_USE_LOG;
  pDb->iReader = -1;
  pDb->iRwclient = -1;
  pDb->bMultiProc = LSM_DFLT_MULTIPLE_PROCESSES;
  pDb->iMmap = LSM_DFLT_MMAP;
  pDb->xLog = xLog;
  pDb->compress.iId = LSM_COMPRESSION_NONE;
  return LSM_OK;
}

lsm_env *lsm_get_env(lsm_db *pDb){
  assert( pDb->pEnv );
  return pDb->pEnv;
}

/*
** If database handle pDb is currently holding a client snapshot, but does
** not have any open cursors or write transactions, release it.
*/
static void dbReleaseClientSnapshot(lsm_db *pDb){
  if( pDb->nTransOpen==0 && pDb->pCsr==0 ){
    lsmFinishReadTrans(pDb);
  }
}

static int getFullpathname(
  lsm_env *pEnv, 
  const char *zRel,
  char **pzAbs
){
  int nAlloc = 0;
  char *zAlloc = 0;
  int nReq = 0;
  int rc;

  do{
    nAlloc = nReq;
    rc = pEnv->xFullpath(pEnv, zRel, zAlloc, &nReq);
    if( nReq>nAlloc ){
      zAlloc = lsmReallocOrFreeRc(pEnv, zAlloc, nReq, &rc);
    }
  }while( nReq>nAlloc && rc==LSM_OK );

  if( rc!=LSM_OK ){
    lsmFree(pEnv, zAlloc);
    zAlloc = 0;
  }
  *pzAbs = zAlloc;
  return rc;
}

/*
** Check that the bits in the db->mLock mask are consistent with the
** value stored in db->iRwclient. An assert shall fail otherwise.
*/
static void assertRwclientLockValue(lsm_db *db){
#ifndef NDEBUG
  u64 msk;                        /* Mask of mLock bits for RWCLIENT locks */
  u64 rwclient = 0;               /* Bit corresponding to db->iRwclient */

  if( db->iRwclient>=0 ){
    rwclient = ((u64)1 << (LSM_LOCK_RWCLIENT(db->iRwclient)-1));
  }
  msk  = ((u64)1 << (LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT)-1)) - 1;
  msk -= (((u64)1 << (LSM_LOCK_RWCLIENT(0)-1)) - 1);

  assert( (db->mLock & msk)==rwclient );
#endif
}

/*
** Open a new connection to database zFilename.
*/
int lsm_open(lsm_db *pDb, const char *zFilename){
  int rc;

  if( pDb->pDatabase ){
    rc = LSM_MISUSE;
  }else{
    char *zFull;

    /* Translate the possibly relative pathname supplied by the user into
    ** an absolute pathname. This is required because the supplied path
    ** is used (either directly or with "-log" appended to it) for more 
    ** than one purpose - to open both the database and log files, and 
    ** perhaps to unlink the log file during disconnection. An absolute
    ** path is required to ensure that the correct files are operated
    ** on even if the application changes the cwd.  */
    rc = getFullpathname(pDb->pEnv, zFilename, &zFull);
    assert( rc==LSM_OK || zFull==0 );

    /* Connect to the database. */
    if( rc==LSM_OK ){
      rc = lsmDbDatabaseConnect(pDb, zFull);
    }

    if( pDb->bReadonly==0 ){
      /* Configure the file-system connection with the page-size and block-size
      ** of this database. Even if the database file is zero bytes in size
      ** on disk, these values have been set in shared-memory by now, and so 
      ** are guaranteed not to change during the lifetime of this connection.  
      */
      if( rc==LSM_OK && LSM_OK==(rc = lsmCheckpointLoad(pDb, 0)) ){
        lsmFsSetPageSize(pDb->pFS, lsmCheckpointPgsz(pDb->aSnapshot));
        lsmFsSetBlockSize(pDb->pFS, lsmCheckpointBlksz(pDb->aSnapshot));
      }
    }

    lsmFree(pDb->pEnv, zFull);
    assertRwclientLockValue(pDb);
  }

  assert( pDb->bReadonly==0 || pDb->bReadonly==1 );
  assert( rc!=LSM_OK || (pDb->pShmhdr==0)==(pDb->bReadonly==1) );

  return rc;
}

int lsm_close(lsm_db *pDb){
  int rc = LSM_OK;
  if( pDb ){
    assert_db_state(pDb);
    if( pDb->pCsr || pDb->nTransOpen ){
      rc = LSM_MISUSE_BKPT;
    }else{
      lsmMCursorFreeCache(pDb);
      lsmFreeSnapshot(pDb->pEnv, pDb->pClient);
      pDb->pClient = 0;

      assertRwclientLockValue(pDb);

      lsmDbDatabaseRelease(pDb);
      lsmLogClose(pDb);
      lsmFsClose(pDb->pFS);
      assert( pDb->mLock==0 );
      
      /* Invoke any destructors registered for the compression or 
      ** compression factory callbacks.  */
      if( pDb->factory.xFree ) pDb->factory.xFree(pDb->factory.pCtx);
      if( pDb->compress.xFree ) pDb->compress.xFree(pDb->compress.pCtx);

      lsmFree(pDb->pEnv, pDb->rollback.aArray);
      lsmFree(pDb->pEnv, pDb->aTrans);
      lsmFree(pDb->pEnv, pDb->apShm);
      lsmFree(pDb->pEnv, pDb);
    }
  }
  return rc;
}

int lsm_config(lsm_db *pDb, int eParam, ...){
  int rc = LSM_OK;
  va_list ap;
  va_start(ap, eParam);

  switch( eParam ){
    case LSM_CONFIG_AUTOFLUSH: {
      /* This parameter is read and written in KB. But all internal 
      ** processing is done in bytes.  */
      int *piVal = va_arg(ap, int *);
      int iVal = *piVal;
      if( iVal>=0 && iVal<=(1024*1024) ){
        pDb->nTreeLimit = iVal*1024;
      }
      *piVal = (pDb->nTreeLimit / 1024);
      break;
    }

    case LSM_CONFIG_AUTOWORK: {
      int *piVal = va_arg(ap, int *);
      if( *piVal>=0 ){
        pDb->bAutowork = *piVal;
      }
      *piVal = pDb->bAutowork;
      break;
    }

    case LSM_CONFIG_AUTOCHECKPOINT: {
      /* This parameter is read and written in KB. But all internal processing
      ** (including the lsm_db.nAutockpt variable) is done in bytes.  */
      int *piVal = va_arg(ap, int *);
      if( *piVal>=0 ){
        int iVal = *piVal;
        pDb->nAutockpt = (i64)iVal * 1024;
      }
      *piVal = (int)(pDb->nAutockpt / 1024);
      break;
    }

    case LSM_CONFIG_PAGE_SIZE: {
      int *piVal = va_arg(ap, int *);
      if( pDb->pDatabase ){
        /* If lsm_open() has been called, this is a read-only parameter. 
        ** Set the output variable to the page-size according to the 
        ** FileSystem object.  */
        *piVal = lsmFsPageSize(pDb->pFS);
      }else{
        if( *piVal>=256 && *piVal<=65536 && ((*piVal-1) & *piVal)==0 ){
          pDb->nDfltPgsz = *piVal;
        }else{
          *piVal = pDb->nDfltPgsz;
        }
      }
      break;
    }

    case LSM_CONFIG_BLOCK_SIZE: {
      /* This parameter is read and written in KB. But all internal 
      ** processing is done in bytes.  */
      int *piVal = va_arg(ap, int *);
      if( pDb->pDatabase ){
        /* If lsm_open() has been called, this is a read-only parameter. 
        ** Set the output variable to the block-size in KB according to the 
        ** FileSystem object.  */
        *piVal = lsmFsBlockSize(pDb->pFS) / 1024;
      }else{
        int iVal = *piVal;
        if( iVal>=64 && iVal<=65536 && ((iVal-1) & iVal)==0 ){
          pDb->nDfltBlksz = iVal * 1024;
        }else{
          *piVal = pDb->nDfltBlksz / 1024;
        }
      }
      break;
    }

    case LSM_CONFIG_SAFETY: {
      int *piVal = va_arg(ap, int *);
      if( *piVal>=0 && *piVal<=2 ){
        pDb->eSafety = *piVal;
      }
      *piVal = pDb->eSafety;
      break;
    }

    case LSM_CONFIG_MMAP: {
      int *piVal = va_arg(ap, int *);
      if( pDb->iReader<0 && *piVal>=0 ){
        pDb->iMmap = *piVal;
        rc = lsmFsConfigure(pDb);
      }
      *piVal = pDb->iMmap;
      break;
    }

    case LSM_CONFIG_USE_LOG: {
      int *piVal = va_arg(ap, int *);
      if( pDb->nTransOpen==0 && (*piVal==0 || *piVal==1) ){
        pDb->bUseLog = *piVal;
      }
      *piVal = pDb->bUseLog;
      break;
    }

    case LSM_CONFIG_AUTOMERGE: {
      int *piVal = va_arg(ap, int *);
      if( *piVal>1 ) pDb->nMerge = *piVal;
      *piVal = pDb->nMerge;
      break;
    }

    case LSM_CONFIG_MAX_FREELIST: {
      int *piVal = va_arg(ap, int *);
      if( *piVal>=2 && *piVal<=LSM_MAX_FREELIST_ENTRIES ){
        pDb->nMaxFreelist = *piVal;
      }
      *piVal = pDb->nMaxFreelist;
      break;
    }

    case LSM_CONFIG_MULTIPLE_PROCESSES: {
      int *piVal = va_arg(ap, int *);
      if( pDb->pDatabase ){
        /* If lsm_open() has been called, this is a read-only parameter. 
        ** Set the output variable to true if this connection is currently
        ** in multi-process mode.  */
        *piVal = lsmDbMultiProc(pDb);
      }else{
        pDb->bMultiProc = *piVal = (*piVal!=0);
      }
      break;
    }

    case LSM_CONFIG_READONLY: {
      int *piVal = va_arg(ap, int *);
      /* If lsm_open() has been called, this is a read-only parameter. */
      if( pDb->pDatabase==0 && *piVal>=0 ){
        pDb->bReadonly = *piVal = (*piVal!=0);
      }
      *piVal = pDb->bReadonly;
      break;
    }

    case LSM_CONFIG_SET_COMPRESSION: {
      lsm_compress *p = va_arg(ap, lsm_compress *);
      if( pDb->iReader>=0 && pDb->bInFactory==0 ){
        /* May not change compression schemes with an open transaction */
        rc = LSM_MISUSE_BKPT;
      }else{
        if( pDb->compress.xFree ){
          /* Invoke any destructor belonging to the current compression. */
          pDb->compress.xFree(pDb->compress.pCtx);
        }
        if( p->xBound==0 ){
          memset(&pDb->compress, 0, sizeof(lsm_compress));
          pDb->compress.iId = LSM_COMPRESSION_NONE;
        }else{
          memcpy(&pDb->compress, p, sizeof(lsm_compress));
        }
        rc = lsmFsConfigure(pDb);
      }
      break;
    }

    case LSM_CONFIG_SET_COMPRESSION_FACTORY: {
      lsm_compress_factory *p = va_arg(ap, lsm_compress_factory *);
      if( pDb->factory.xFree ){
        /* Invoke any destructor belonging to the current factory. */
        pDb->factory.xFree(pDb->factory.pCtx);
      }
      memcpy(&pDb->factory, p, sizeof(lsm_compress_factory));
      break;
    }

    case LSM_CONFIG_GET_COMPRESSION: {
      lsm_compress *p = va_arg(ap, lsm_compress *);
      memcpy(p, &pDb->compress, sizeof(lsm_compress));
      break;
    }

    default:
      rc = LSM_MISUSE;
      break;
  }

  va_end(ap);
  return rc;
}

void lsmAppendSegmentList(LsmString *pStr, char *zPre, Segment *pSeg){
  lsmStringAppendf(pStr, "%s{%d %d %d %d}", zPre, 
        pSeg->iFirst, pSeg->iLastPg, pSeg->iRoot, pSeg->nSize
  );
}

static int infoGetWorker(lsm_db *pDb, Snapshot **pp, int *pbUnlock){
  int rc = LSM_OK;

  assert( *pbUnlock==0 );
  if( !pDb->pWorker ){
    rc = lsmBeginWork(pDb);
    if( rc!=LSM_OK ) return rc;
    *pbUnlock = 1;
  }
  if( pp ) *pp = pDb->pWorker;
  return rc;
}

static void infoFreeWorker(lsm_db *pDb, int bUnlock){
  if( bUnlock ){
    int rcdummy = LSM_BUSY;
    lsmFinishWork(pDb, 0, &rcdummy);
  }
}

int lsmStructList(
  lsm_db *pDb,                    /* Database handle */
  char **pzOut                    /* OUT: Nul-terminated string (tcl list) */
){
  Level *pTopLevel = 0;           /* Top level of snapshot to report on */
  int rc = LSM_OK;
  Level *p;
  LsmString s;
  Snapshot *pWorker;              /* Worker snapshot */
  int bUnlock = 0;

  /* Obtain the worker snapshot */
  rc = infoGetWorker(pDb, &pWorker, &bUnlock);
  if( rc!=LSM_OK ) return rc;

  /* Format the contents of the snapshot as text */
  pTopLevel = lsmDbSnapshotLevel(pWorker);
  lsmStringInit(&s, pDb->pEnv);
  for(p=pTopLevel; rc==LSM_OK && p; p=p->pNext){
    int i;
    lsmStringAppendf(&s, "%s{%d", (s.n ? " " : ""), (int)p->iAge);
    lsmAppendSegmentList(&s, " ", &p->lhs);
    for(i=0; rc==LSM_OK && i<p->nRight; i++){
      lsmAppendSegmentList(&s, " ", &p->aRhs[i]);
    }
    lsmStringAppend(&s, "}", 1);
  }
  rc = s.n>=0 ? LSM_OK : LSM_NOMEM;

  /* Release the snapshot and return */
  infoFreeWorker(pDb, bUnlock);
  *pzOut = s.z;
  return rc;
}

static int infoFreelistCb(void *pCtx, int iBlk, i64 iSnapshot){
  LsmString *pStr = (LsmString *)pCtx;
  lsmStringAppendf(pStr, "%s{%d %lld}", (pStr->n?" ":""), iBlk, iSnapshot);
  return 0;
}

int lsmInfoFreelist(lsm_db *pDb, char **pzOut){
  Snapshot *pWorker;              /* Worker snapshot */
  int bUnlock = 0;
  LsmString s;
  int rc;

  /* Obtain the worker snapshot */
  rc = infoGetWorker(pDb, &pWorker, &bUnlock);
  if( rc!=LSM_OK ) return rc;

  lsmStringInit(&s, pDb->pEnv);
  rc = lsmWalkFreelist(pDb, 0, infoFreelistCb, &s);
  if( rc!=LSM_OK ){
    lsmFree(pDb->pEnv, s.z);
  }else{
    *pzOut = s.z;
  }

  /* Release the snapshot and return */
  infoFreeWorker(pDb, bUnlock);
  return rc;
}

static int infoTreeSize(lsm_db *db, int *pnOldKB, int *pnNewKB){
  ShmHeader *pShm = db->pShmhdr;
  TreeHeader *p = &pShm->hdr1;

  /* The following code suffers from two race conditions, as it accesses and
  ** trusts the contents of shared memory without verifying checksums:
  **
  **   * The two values read - TreeHeader.root.nByte and oldroot.nByte - are 
  **     32-bit fields. It is assumed that reading from one of these
  **     is atomic - that it is not possible to read a partially written
  **     garbage value. However the two values may be mutually inconsistent. 
  **
  **   * TreeHeader.iLogOff is a 64-bit value. And lsmCheckpointLogOffset()
  **     reads a 64-bit value from a snapshot stored in shared memory. It
  **     is assumed that in each case it is possible to read a partially
  **     written garbage value. If this occurs, then the value returned
  **     for the size of the "old" tree may reflect the size of an "old"
  **     tree that was recently flushed to disk.
  **
  ** Given the context in which this function is called (as a result of an
  ** lsm_info(LSM_INFO_TREE_SIZE) request), neither of these are considered to
  ** be problems.
  */
  *pnNewKB = ((int)p->root.nByte + 1023) / 1024;
  if( p->iOldShmid ){
    if( p->iOldLog==lsmCheckpointLogOffset(pShm->aSnap1) ){
      *pnOldKB = 0;
    }else{
      *pnOldKB = ((int)p->oldroot.nByte + 1023) / 1024;
    }
  }else{
    *pnOldKB = 0;
  }

  return LSM_OK;
}

int lsm_info(lsm_db *pDb, int eParam, ...){
  int rc = LSM_OK;
  va_list ap;
  va_start(ap, eParam);

  switch( eParam ){
    case LSM_INFO_NWRITE: {
      int *piVal = va_arg(ap, int *);
      *piVal = lsmFsNWrite(pDb->pFS);
      break;
    }

    case LSM_INFO_NREAD: {
      int *piVal = va_arg(ap, int *);
      *piVal = lsmFsNRead(pDb->pFS);
      break;
    }

    case LSM_INFO_DB_STRUCTURE: {
      char **pzVal = va_arg(ap, char **);
      rc = lsmStructList(pDb, pzVal);
      break;
    }

    case LSM_INFO_ARRAY_STRUCTURE: {
      Pgno pgno = va_arg(ap, Pgno);
      char **pzVal = va_arg(ap, char **);
      rc = lsmInfoArrayStructure(pDb, 0, pgno, pzVal);
      break;
    }

    case LSM_INFO_ARRAY_PAGES: {
      Pgno pgno = va_arg(ap, Pgno);
      char **pzVal = va_arg(ap, char **);
      rc = lsmInfoArrayPages(pDb, pgno, pzVal);
      break;
    }

    case LSM_INFO_PAGE_HEX_DUMP:
    case LSM_INFO_PAGE_ASCII_DUMP: {
      Pgno pgno = va_arg(ap, Pgno);
      char **pzVal = va_arg(ap, char **);
      int bUnlock = 0;
      rc = infoGetWorker(pDb, 0, &bUnlock);
      if( rc==LSM_OK ){
        int bHex = (eParam==LSM_INFO_PAGE_HEX_DUMP);
        rc = lsmInfoPageDump(pDb, pgno, bHex, pzVal);
      }
      infoFreeWorker(pDb, bUnlock);
      break;
    }

    case LSM_INFO_LOG_STRUCTURE: {
      char **pzVal = va_arg(ap, char **);
      rc = lsmInfoLogStructure(pDb, pzVal);
      break;
    }

    case LSM_INFO_FREELIST: {
      char **pzVal = va_arg(ap, char **);
      rc = lsmInfoFreelist(pDb, pzVal);
      break;
    }

    case LSM_INFO_CHECKPOINT_SIZE: {
      int *pnKB = va_arg(ap, int *);
      rc = lsmCheckpointSize(pDb, pnKB);
      break;
    }

    case LSM_INFO_TREE_SIZE: {
      int *pnOld = va_arg(ap, int *);
      int *pnNew = va_arg(ap, int *);
      rc = infoTreeSize(pDb, pnOld, pnNew);
      break;
    }

    case LSM_INFO_COMPRESSION_ID: {
      unsigned int *piOut = va_arg(ap, unsigned int *);
      if( pDb->pClient ){
        *piOut = pDb->pClient->iCmpId;
      }else{
        rc = lsmInfoCompressionId(pDb, piOut);
      }
      break;
    }

    default:
      rc = LSM_MISUSE;
      break;
  }

  va_end(ap);
  return rc;
}

static int doWriteOp(
  lsm_db *pDb,
  int bDeleteRange,
  const void *pKey, int nKey,     /* Key to write or delete */
  const void *pVal, int nVal      /* Value to write. Or nVal==-1 for a delete */
){
  int rc = LSM_OK;                /* Return code */
  int bCommit = 0;                /* True to commit before returning */

  if( pDb->nTransOpen==0 ){
    bCommit = 1;
    rc = lsm_begin(pDb, 1);
  }

  if( rc==LSM_OK ){
    if( bDeleteRange==0 ){
      rc = lsmLogWrite(pDb, (void *)pKey, nKey, (void *)pVal, nVal);
    }else{
      /* TODO */
    }
  }

  lsmSortedSaveTreeCursors(pDb);

  if( rc==LSM_OK ){
    int pgsz = lsmFsPageSize(pDb->pFS);
    int nQuant = LSM_AUTOWORK_QUANT * pgsz;
    int nBefore;
    int nAfter;
    int nDiff;

    if( nQuant>pDb->nTreeLimit ){
      nQuant = pDb->nTreeLimit;
    }

    nBefore = lsmTreeSize(pDb);
    if( bDeleteRange ){
      rc = lsmTreeDelete(pDb, (void *)pKey, nKey, (void *)pVal, nVal);
    }else{
      rc = lsmTreeInsert(pDb, (void *)pKey, nKey, (void *)pVal, nVal);
    }

    nAfter = lsmTreeSize(pDb);
    nDiff = (nAfter/nQuant) - (nBefore/nQuant);
    if( rc==LSM_OK && pDb->bAutowork && nDiff!=0 ){
      rc = lsmSortedAutoWork(pDb, nDiff * LSM_AUTOWORK_QUANT);
    }
  }

  /* If a transaction was opened at the start of this function, commit it. 
  ** Or, if an error has occurred, roll it back.  */
  if( bCommit ){
    if( rc==LSM_OK ){
      rc = lsm_commit(pDb, 0);
    }else{
      lsm_rollback(pDb, 0);
    }
  }

  return rc;
}

/* 
** Write a new value into the database.
*/
int lsm_insert(
  lsm_db *db,                     /* Database connection */
  const void *pKey, int nKey,     /* Key to write or delete */
  const void *pVal, int nVal      /* Value to write. Or nVal==-1 for a delete */
){
  return doWriteOp(db, 0, pKey, nKey, pVal, nVal);
}

/*
** Delete a value from the database. 
*/
int lsm_delete(lsm_db *db, const void *pKey, int nKey){
  return doWriteOp(db, 0, pKey, nKey, 0, -1);
}

/*
** Delete a range of database keys.
*/
int lsm_delete_range(
  lsm_db *db,                     /* Database handle */
  const void *pKey1, int nKey1,   /* Lower bound of range to delete */
  const void *pKey2, int nKey2    /* Upper bound of range to delete */
){
  int rc = LSM_OK;
  if( db->xCmp((void *)pKey1, nKey1, (void *)pKey2, nKey2)<0 ){
    rc = doWriteOp(db, 1, pKey1, nKey1, pKey2, nKey2);
  }
  return rc;
}

/*
** Open a new cursor handle. 
**
** If there are currently no other open cursor handles, and no open write
** transaction, open a read transaction here.
*/
int lsm_csr_open(lsm_db *pDb, lsm_cursor **ppCsr){
  int rc = LSM_OK;                /* Return code */
  MultiCursor *pCsr = 0;          /* New cursor object */

  /* Open a read transaction if one is not already open. */
  assert_db_state(pDb);

  if( pDb->pShmhdr==0 ){
    assert( pDb->bReadonly );
    rc = lsmBeginRoTrans(pDb);
  }else if( pDb->iReader<0 ){
    rc = lsmBeginReadTrans(pDb);
  }

  /* Allocate the multi-cursor. */
  if( rc==LSM_OK ){
    rc = lsmMCursorNew(pDb, &pCsr);
  }

  /* If an error has occured, set the output to NULL and delete any partially
  ** allocated cursor. If this means there are no open cursors, release the
  ** client snapshot.  */
  if( rc!=LSM_OK ){
    lsmMCursorClose(pCsr, 0);
    dbReleaseClientSnapshot(pDb);
  }

  assert_db_state(pDb);
  *ppCsr = (lsm_cursor *)pCsr;
  return rc;
}

/*
** Close a cursor opened using lsm_csr_open().
*/
int lsm_csr_close(lsm_cursor *p){
  if( p ){
    lsm_db *pDb = lsmMCursorDb((MultiCursor *)p);
    assert_db_state(pDb);
    lsmMCursorClose((MultiCursor *)p, 1);
    dbReleaseClientSnapshot(pDb);
    assert_db_state(pDb);
  }
  return LSM_OK;
}

/*
** Attempt to seek the cursor to the database entry specified by pKey/nKey.
** If an error occurs (e.g. an OOM or IO error), return an LSM error code.
** Otherwise, return LSM_OK.
*/
int lsm_csr_seek(lsm_cursor *pCsr, const void *pKey, int nKey, int eSeek){
  return lsmMCursorSeek((MultiCursor *)pCsr, 0, (void *)pKey, nKey, eSeek);
}

int lsm_csr_next(lsm_cursor *pCsr){
  return lsmMCursorNext((MultiCursor *)pCsr);
}

int lsm_csr_prev(lsm_cursor *pCsr){
  return lsmMCursorPrev((MultiCursor *)pCsr);
}

int lsm_csr_first(lsm_cursor *pCsr){
  return lsmMCursorFirst((MultiCursor *)pCsr);
}

int lsm_csr_last(lsm_cursor *pCsr){
  return lsmMCursorLast((MultiCursor *)pCsr);
}

int lsm_csr_valid(lsm_cursor *pCsr){
  return lsmMCursorValid((MultiCursor *)pCsr);
}

int lsm_csr_key(lsm_cursor *pCsr, const void **ppKey, int *pnKey){
  return lsmMCursorKey((MultiCursor *)pCsr, (void **)ppKey, pnKey);
}

int lsm_csr_value(lsm_cursor *pCsr, const void **ppVal, int *pnVal){
  return lsmMCursorValue((MultiCursor *)pCsr, (void **)ppVal, pnVal);
}

void lsm_config_log(
  lsm_db *pDb, 
  void (*xLog)(void *, int, const char *), 
  void *pCtx
){
  pDb->xLog = xLog;
  pDb->pLogCtx = pCtx;
}

void lsm_config_work_hook(
  lsm_db *pDb, 
  void (*xWork)(lsm_db *, void *), 
  void *pCtx
){
  pDb->xWork = xWork;
  pDb->pWorkCtx = pCtx;
}

void lsmLogMessage(lsm_db *pDb, int rc, const char *zFormat, ...){
  if( pDb->xLog ){
    LsmString s;
    va_list ap, ap2;
    lsmStringInit(&s, pDb->pEnv);
    va_start(ap, zFormat);
    va_start(ap2, zFormat);
    lsmStringVAppendf(&s, zFormat, ap, ap2);
    va_end(ap);
    va_end(ap2);
    pDb->xLog(pDb->pLogCtx, rc, s.z);
    lsmStringClear(&s);
  }
}

int lsm_begin(lsm_db *pDb, int iLevel){
  int rc;

  assert_db_state( pDb );
  rc = (pDb->bReadonly ? LSM_READONLY : LSM_OK);

  /* A value less than zero means open one more transaction. */
  if( iLevel<0 ) iLevel = pDb->nTransOpen + 1;
  if( iLevel>pDb->nTransOpen ){
    int i;

    /* Extend the pDb->aTrans[] array if required. */
    if( rc==LSM_OK && pDb->nTransAlloc<iLevel ){
      TransMark *aNew;            /* New allocation */
      int nByte = sizeof(TransMark) * (iLevel+1);
      aNew = (TransMark *)lsmRealloc(pDb->pEnv, pDb->aTrans, nByte);
      if( !aNew ){
        rc = LSM_NOMEM;
      }else{
        nByte = sizeof(TransMark) * (iLevel+1 - pDb->nTransAlloc);
        memset(&aNew[pDb->nTransAlloc], 0, nByte);
        pDb->nTransAlloc = iLevel+1;
        pDb->aTrans = aNew;
      }
    }

    if( rc==LSM_OK && pDb->nTransOpen==0 ){
      rc = lsmBeginWriteTrans(pDb);
    }

    if( rc==LSM_OK ){
      for(i=pDb->nTransOpen; i<iLevel; i++){
        lsmTreeMark(pDb, &pDb->aTrans[i].tree);
        lsmLogTell(pDb, &pDb->aTrans[i].log);
      }
      pDb->nTransOpen = iLevel;
    }
  }

  return rc;
}

int lsm_commit(lsm_db *pDb, int iLevel){
  int rc = LSM_OK;

  assert_db_state( pDb );

  /* A value less than zero means close the innermost nested transaction. */
  if( iLevel<0 ) iLevel = LSM_MAX(0, pDb->nTransOpen - 1);

  if( iLevel<pDb->nTransOpen ){
    if( iLevel==0 ){
      /* Commit the transaction to disk. */
      if( rc==LSM_OK ) rc = lsmLogCommit(pDb);
      if( rc==LSM_OK && pDb->eSafety==LSM_SAFETY_FULL ){
        rc = lsmFsSyncLog(pDb->pFS);
      }
      lsmFinishWriteTrans(pDb, (rc==LSM_OK));
    }
    pDb->nTransOpen = iLevel;
  }
  dbReleaseClientSnapshot(pDb);
  return rc;
}

int lsm_rollback(lsm_db *pDb, int iLevel){
  int rc = LSM_OK;
  assert_db_state( pDb );

  if( pDb->nTransOpen ){
    /* A value less than zero means close the innermost nested transaction. */
    if( iLevel<0 ) iLevel = LSM_MAX(0, pDb->nTransOpen - 1);

    if( iLevel<=pDb->nTransOpen ){
      TransMark *pMark = &pDb->aTrans[(iLevel==0 ? 0 : iLevel-1)];
      lsmTreeRollback(pDb, &pMark->tree);
      if( iLevel ) lsmLogSeek(pDb, &pMark->log);
      pDb->nTransOpen = iLevel;
    }

    if( pDb->nTransOpen==0 ){
      lsmFinishWriteTrans(pDb, 0);
    }
    dbReleaseClientSnapshot(pDb);
  }

  return rc;
}

int lsm_get_user_version(lsm_db *pDb, unsigned int *piUsr){
  int rc = LSM_OK;                /* Return code */

  /* Open a read transaction if one is not already open. */
  assert_db_state(pDb);
  if( pDb->pShmhdr==0 ){
    assert( pDb->bReadonly );
    rc = lsmBeginRoTrans(pDb);
  }else if( pDb->iReader<0 ){
    rc = lsmBeginReadTrans(pDb);
  }

  /* Allocate the multi-cursor. */
  if( rc==LSM_OK ){
    *piUsr = pDb->treehdr.iUsrVersion;
  }

  dbReleaseClientSnapshot(pDb);
  assert_db_state(pDb);
  return rc;
}

int lsm_set_user_version(lsm_db *pDb, unsigned int iUsr){
  int rc = LSM_OK;                /* Return code */
  int bCommit = 0;                /* True to commit before returning */

  if( pDb->nTransOpen==0 ){
    bCommit = 1;
    rc = lsm_begin(pDb, 1);
  }

  if( rc==LSM_OK ){
    pDb->treehdr.iUsrVersion = iUsr;
  }

  /* If a transaction was opened at the start of this function, commit it. 
  ** Or, if an error has occurred, roll it back.  */
  if( bCommit ){
    if( rc==LSM_OK ){
      rc = lsm_commit(pDb, 0);
    }else{
      lsm_rollback(pDb, 0);
    }
  }

  return rc;
}

/************** End of lsm_main.c ********************************************/
/************** Begin file lsm_mem.c *****************************************/
/*
** 2011-08-18
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Helper routines for memory allocation.
*/

/*
** The following routines are called internally by LSM sub-routines. In
** this case a valid environment pointer must be supplied.
*/
void *lsmMalloc(lsm_env *pEnv, size_t N){
  assert( pEnv );
  return pEnv->xMalloc(pEnv, N);
}
void lsmFree(lsm_env *pEnv, void *p){
  assert( pEnv );
  pEnv->xFree(pEnv, p);
}
void *lsmRealloc(lsm_env *pEnv, void *p, size_t N){
  assert( pEnv );
  return pEnv->xRealloc(pEnv, p, N);
}

/*
** Core memory allocation routines for LSM.
*/
void *lsm_malloc(lsm_env *pEnv, size_t N){
  return lsmMalloc(pEnv ? pEnv : lsm_default_env(), N);
}
void lsm_free(lsm_env *pEnv, void *p){
  lsmFree(pEnv ? pEnv : lsm_default_env(), p);
}
void *lsm_realloc(lsm_env *pEnv, void *p, size_t N){
  return lsmRealloc(pEnv ? pEnv : lsm_default_env(), p, N);
}

void *lsmMallocZero(lsm_env *pEnv, size_t N){
  void *pRet;
  assert( pEnv );
  pRet = lsmMalloc(pEnv, N);
  if( pRet ) memset(pRet, 0, N);
  return pRet;
}

void *lsmMallocRc(lsm_env *pEnv, size_t N, int *pRc){
  void *pRet = 0;
  if( *pRc==LSM_OK ){
    pRet = lsmMalloc(pEnv, N);
    if( pRet==0 ){
      *pRc = LSM_NOMEM_BKPT;
    }
  }
  return pRet;
}

void *lsmMallocZeroRc(lsm_env *pEnv, size_t N, int *pRc){
  void *pRet = 0;
  if( *pRc==LSM_OK ){
    pRet = lsmMallocZero(pEnv, N);
    if( pRet==0 ){
      *pRc = LSM_NOMEM_BKPT;
    }
  }
  return pRet;
}

void *lsmReallocOrFree(lsm_env *pEnv, void *p, size_t N){
  void *pNew;
  pNew = lsm_realloc(pEnv, p, N);
  if( !pNew ) lsm_free(pEnv, p);
  return pNew;
}

void *lsmReallocOrFreeRc(lsm_env *pEnv, void *p, size_t N, int *pRc){
  void *pRet = 0;
  if( *pRc ){
    lsmFree(pEnv, p);
  }else{
    pRet = lsmReallocOrFree(pEnv, p, N);
    if( !pRet ) *pRc = LSM_NOMEM_BKPT;
  }
  return pRet;
}

char *lsmMallocStrdup(lsm_env *pEnv, const char *zIn){
  int nByte;
  char *zRet;
  nByte = strlen(zIn);
  zRet = lsmMalloc(pEnv, nByte+1);
  if( zRet ){
    memcpy(zRet, zIn, nByte+1);
  }
  return zRet;
}

/************** End of lsm_mem.c *********************************************/
/************** Begin file lsm_mutex.c ***************************************/
/*
** 2012-01-30
**
** 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.
**
*************************************************************************
**
** Mutex functions for LSM.
*/

/*
** Allocate a new mutex.
*/
int lsmMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
  return pEnv->xMutexNew(pEnv, ppNew);
}

/*
** Return a handle for one of the static mutexes.
*/
int lsmMutexStatic(lsm_env *pEnv, int iMutex, lsm_mutex **ppStatic){
  return pEnv->xMutexStatic(pEnv, iMutex, ppStatic);
}

/*
** Free a mutex allocated by lsmMutexNew().
*/
void lsmMutexDel(lsm_env *pEnv, lsm_mutex *pMutex){
  if( pMutex ) pEnv->xMutexDel(pMutex);
}

/*
** Enter a mutex.
*/
void lsmMutexEnter(lsm_env *pEnv, lsm_mutex *pMutex){
  pEnv->xMutexEnter(pMutex);
}

/*
** Attempt to enter a mutex, but do not block. If successful, return zero.
** Otherwise, if the mutex is already held by some other thread and is not
** entered, return non zero.
**
** Each successful call to this function must be matched by a call to
** lsmMutexLeave().
*/
int lsmMutexTry(lsm_env *pEnv, lsm_mutex *pMutex){
  return pEnv->xMutexTry(pMutex);
}

/*
** Leave a mutex.
*/
void lsmMutexLeave(lsm_env *pEnv, lsm_mutex *pMutex){
  pEnv->xMutexLeave(pMutex);
}

#ifndef NDEBUG
/*
** Return non-zero if the mutex passed as the second argument is held
** by the calling thread, or zero otherwise. If the implementation is not 
** able to tell if the mutex is held by the caller, it should return
** non-zero.
**
** This function is only used as part of assert() statements.
*/
int lsmMutexHeld(lsm_env *pEnv, lsm_mutex *pMutex){
  return pEnv->xMutexHeld ? pEnv->xMutexHeld(pMutex) : 1;
}

/*
** Return non-zero if the mutex passed as the second argument is not 
** held by the calling thread, or zero otherwise. If the implementation 
** is not able to tell if the mutex is held by the caller, it should 
** return non-zero.
**
** This function is only used as part of assert() statements.
*/
int lsmMutexNotHeld(lsm_env *pEnv, lsm_mutex *pMutex){
  return pEnv->xMutexNotHeld ? pEnv->xMutexNotHeld(pMutex) : 1;
}
#endif

/************** End of lsm_mutex.c *******************************************/
/************** Begin file lsm_shared.c **************************************/
/*
** 2012-01-23
**
** 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.
**
*************************************************************************
**
** Utilities used to help multiple LSM clients to coexist within the
** same process space.
*/

/*
** Global data. All global variables used by code in this file are grouped
** into the following structure instance.
**
** pDatabase:
**   Linked list of all Database objects allocated within this process.
**   This list may not be traversed without holding the global mutex (see
**   functions enterGlobalMutex() and leaveGlobalMutex()).
*/
static struct SharedData {
  Database *pDatabase;            /* Linked list of all Database objects */
} gShared;

/*
** Database structure. There is one such structure for each distinct 
** database accessed by this process. They are stored in the singly linked 
** list starting at global variable gShared.pDatabase. Database objects are 
** reference counted. Once the number of connections to the associated
** database drops to zero, they are removed from the linked list and deleted.
**
** pFile:
**   In multi-process mode, this file descriptor is used to obtain locks 
**   and to access shared-memory. In single process mode, its only job is
**   to hold the exclusive lock on the file.
**   
*/
struct Database {
  /* Protected by the global mutex (enterGlobalMutex/leaveGlobalMutex): */
  char *zName;                    /* Canonical path to database file */
  int nName;                      /* strlen(zName) */
  int nDbRef;                     /* Number of associated lsm_db handles */
  Database *pDbNext;              /* Next Database structure in global list */

  /* Protected by the local mutex (pClientMutex) */
  int bReadonly;                  /* True if Database.pFile is read-only */
  int bMultiProc;                 /* True if running in multi-process mode */
  lsm_file *pFile;                /* Used for locks/shm in multi-proc mode */
  LsmFile *pLsmFile;              /* List of deferred closes */
  lsm_mutex *pClientMutex;        /* Protects the apShmChunk[] and pConn */
  int nShmChunk;                  /* Number of entries in apShmChunk[] array */
  void **apShmChunk;              /* Array of "shared" memory regions */
  lsm_db *pConn;                  /* List of connections to this db. */
};

/*
** Functions to enter and leave the global mutex. This mutex is used
** to protect the global linked-list headed at gShared.pDatabase.
*/
static int enterGlobalMutex(lsm_env *pEnv){
  lsm_mutex *p;
  int rc = lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
  if( rc==LSM_OK ) lsmMutexEnter(pEnv, p);
  return rc;
}
static void leaveGlobalMutex(lsm_env *pEnv){
  lsm_mutex *p;
  lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
  lsmMutexLeave(pEnv, p);
}

#ifdef LSM_DEBUG
static int holdingGlobalMutex(lsm_env *pEnv){
  lsm_mutex *p;
  lsmMutexStatic(pEnv, LSM_MUTEX_GLOBAL, &p);
  return lsmMutexHeld(pEnv, p);
}
static void assertNotInFreelist(Freelist *p, int iBlk){
  int i; 
  for(i=0; i<p->nEntry; i++){
    assert( p->aEntry[i].iBlk!=iBlk );
  }
}
#else
# define assertNotInFreelist(x,y)
#endif

/*
** Append an entry to the free-list. If (iId==-1), this is a delete.
*/
int freelistAppend(lsm_db *db, int iBlk, i64 iId){
  lsm_env *pEnv = db->pEnv;
  Freelist *p;
  int i; 

  assert( iId==-1 || iId>=0 );
  p = db->bUseFreelist ? db->pFreelist : &db->pWorker->freelist;

  /* Extend the space allocated for the freelist, if required */
  assert( p->nAlloc>=p->nEntry );
  if( p->nAlloc==p->nEntry ){
    int nNew; 
    int nByte; 
    FreelistEntry *aNew;

    nNew = (p->nAlloc==0 ? 4 : p->nAlloc*2);
    nByte = sizeof(FreelistEntry) * nNew;
    aNew = (FreelistEntry *)lsmRealloc(pEnv, p->aEntry, nByte);
    if( !aNew ) return LSM_NOMEM_BKPT;
    p->nAlloc = nNew;
    p->aEntry = aNew;
  }

  for(i=0; i<p->nEntry; i++){
    assert( i==0 || p->aEntry[i].iBlk > p->aEntry[i-1].iBlk );
    if( p->aEntry[i].iBlk>=iBlk ) break;
  }

  if( i<p->nEntry && p->aEntry[i].iBlk==iBlk ){
    /* Clobber an existing entry */
    p->aEntry[i].iId = iId;
  }else{
    /* Insert a new entry into the list */
    int nByte = sizeof(FreelistEntry)*(p->nEntry-i);
    memmove(&p->aEntry[i+1], &p->aEntry[i], nByte);
    p->aEntry[i].iBlk = iBlk;
    p->aEntry[i].iId = iId;
    p->nEntry++;
  }

  return LSM_OK;
}

/*
** This function frees all resources held by the Database structure passed
** as the only argument.
*/
static void freeDatabase(lsm_env *pEnv, Database *p){
  assert( holdingGlobalMutex(pEnv) );
  if( p ){
    /* Free the mutexes */
    lsmMutexDel(pEnv, p->pClientMutex);

    if( p->pFile ){
      lsmEnvClose(pEnv, p->pFile);
    }

    /* Free the array of shm pointers */
    lsmFree(pEnv, p->apShmChunk);

    /* Free the memory allocated for the Database struct itself */
    lsmFree(pEnv, p);
  }
}

typedef struct DbTruncateCtx DbTruncateCtx;
struct DbTruncateCtx {
  int nBlock;
  i64 iInUse;
};

static int dbTruncateCb(void *pCtx, int iBlk, i64 iSnapshot){
  DbTruncateCtx *p = (DbTruncateCtx *)pCtx;
  if( iBlk!=p->nBlock || (p->iInUse>=0 && iSnapshot>=p->iInUse) ) return 1;
  p->nBlock--;
  return 0;
}

static int dbTruncate(lsm_db *pDb, i64 iInUse){
  int rc = LSM_OK;
#if 0
  int i;
  DbTruncateCtx ctx;

  assert( pDb->pWorker );
  ctx.nBlock = pDb->pWorker->nBlock;
  ctx.iInUse = iInUse;

  rc = lsmWalkFreelist(pDb, 1, dbTruncateCb, (void *)&ctx);
  for(i=ctx.nBlock+1; rc==LSM_OK && i<=pDb->pWorker->nBlock; i++){
    rc = freelistAppend(pDb, i, -1);
  }

  if( rc==LSM_OK ){
#ifdef LSM_LOG_FREELIST
    if( ctx.nBlock!=pDb->pWorker->nBlock ){
      lsmLogMessage(pDb, 0, 
          "dbTruncate(): truncated db to %d blocks",ctx.nBlock
      );
    }
#endif
    pDb->pWorker->nBlock = ctx.nBlock;
  }
#endif
  return rc;
}


/*
** This function is called during database shutdown (when the number of
** connections drops from one to zero). It truncates the database file
** to as small a size as possible without truncating away any blocks that
** contain data.
*/
static int dbTruncateFile(lsm_db *pDb){
  int rc;

  assert( pDb->pWorker==0 );
  assert( lsmShmAssertLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL) );
  rc = lsmCheckpointLoadWorker(pDb);

  if( rc==LSM_OK ){
    DbTruncateCtx ctx;

    /* Walk the database free-block-list in reverse order. Set ctx.nBlock
    ** to the block number of the last block in the database that actually
    ** contains data. */
    ctx.nBlock = pDb->pWorker->nBlock;
    ctx.iInUse = -1;
    rc = lsmWalkFreelist(pDb, 1, dbTruncateCb, (void *)&ctx);

    /* If the last block that contains data is not already the last block in
    ** the database file, truncate the database file so that it is. */
    if( rc==LSM_OK && ctx.nBlock!=pDb->pWorker->nBlock ){
      rc = lsmFsTruncateDb(
          pDb->pFS, (i64)ctx.nBlock*lsmFsBlockSize(pDb->pFS)
      );
    }
  }

  lsmFreeSnapshot(pDb->pEnv, pDb->pWorker);
  pDb->pWorker = 0;
  return rc;
}

static void doDbDisconnect(lsm_db *pDb){
  int rc;

  if( pDb->bReadonly ){
    lsmShmLock(pDb, LSM_LOCK_DMS3, LSM_LOCK_UNLOCK, 0);
  }else{
    /* Block for an exclusive lock on DMS1. This lock serializes all calls
    ** to doDbConnect() and doDbDisconnect() across all processes.  */
    rc = lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL, 1);
    if( rc==LSM_OK ){

      /* Try an exclusive lock on DMS2. If successful, this is the last
      ** connection to the database. In this case flush the contents of the
      ** in-memory tree to disk and write a checkpoint.  */
      rc = lsmShmTestLock(pDb, LSM_LOCK_DMS2, 1, LSM_LOCK_EXCL);
      if( rc==LSM_OK ){
        rc = lsmShmTestLock(pDb, LSM_LOCK_CHECKPOINTER, 1, LSM_LOCK_EXCL);
      }
      if( rc==LSM_OK ){
        int bReadonly = 0;        /* True if there exist read-only conns. */

        /* Flush the in-memory tree, if required. If there is data to flush,
        ** this will create a new client snapshot in Database.pClient. The
        ** checkpoint (serialization) of this snapshot may be written to disk
        ** by the following block.  
        **
        ** There is no need to take a WRITER lock here. That there are no 
        ** other locks on DMS2 guarantees that there are no other read-write
        ** connections at this time (and the lock on DMS1 guarantees that
        ** no new ones may appear).
        */
        rc = lsmTreeLoadHeader(pDb, 0);
        if( rc==LSM_OK && (lsmTreeHasOld(pDb) || lsmTreeSize(pDb)>0) ){
          rc = lsmFlushTreeToDisk(pDb);
        }

        /* Now check if there are any read-only connections. If there are,
        ** then do not truncate the db file or unlink the shared-memory 
        ** region.  */
        if( rc==LSM_OK ){
          rc = lsmShmTestLock(pDb, LSM_LOCK_DMS3, 1, LSM_LOCK_EXCL);
          if( rc==LSM_BUSY ){
            bReadonly = 1;
            rc = LSM_OK;
          }
        }

        /* Write a checkpoint to disk. */
        if( rc==LSM_OK ){
          rc = lsmCheckpointWrite(pDb, (bReadonly==0), 0);
        }

        /* If the checkpoint was written successfully, delete the log file
        ** and, if possible, truncate the database file.  */
        if( rc==LSM_OK ){
          int bRotrans = 0;
          Database *p = pDb->pDatabase;

          /* The log file may only be deleted if there are no clients 
          ** read-only clients running rotrans transactions.  */
          rc = lsmDetectRoTrans(pDb, &bRotrans);
          if( rc==LSM_OK && bRotrans==0 ){
            lsmFsCloseAndDeleteLog(pDb->pFS);
          }

          /* The database may only be truncated if there exist no read-only
          ** clients - either connected or running rotrans transactions. */
          if( bReadonly==0 && bRotrans==0 ){
            dbTruncateFile(pDb);
            if( p->pFile && p->bMultiProc ){
              lsmEnvShmUnmap(pDb->pEnv, p->pFile, 1);
            }
          }
        }
      }
    }

    if( pDb->iRwclient>=0 ){
      lsmShmLock(pDb, LSM_LOCK_RWCLIENT(pDb->iRwclient), LSM_LOCK_UNLOCK, 0);
      pDb->iRwclient = -1;
    }

    lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_UNLOCK, 0);
    lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
  }
  pDb->pShmhdr = 0;
}

static int doDbConnect(lsm_db *pDb){
  const int nUsMax = 100000;      /* Max value for nUs */
  int nUs = 1000;                 /* us to wait between DMS1 attempts */
  int rc;

  /* Obtain a pointer to the shared-memory header */
  assert( pDb->pShmhdr==0 );
  assert( pDb->bReadonly==0 );
  rc = lsmShmCacheChunks(pDb, 1);
  if( rc!=LSM_OK ) return rc;
  pDb->pShmhdr = (ShmHeader *)pDb->apShm[0];

  /* Block for an exclusive lock on DMS1. This lock serializes all calls
  ** to doDbConnect() and doDbDisconnect() across all processes.  */
  while( 1 ){
    rc = lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_EXCL, 1);
    if( rc!=LSM_BUSY ) break;
    lsmEnvSleep(pDb->pEnv, nUs);
    nUs = nUs * 2;
    if( nUs>nUsMax ) nUs = nUsMax;
  }
  if( rc!=LSM_OK ){
    pDb->pShmhdr = 0;
    return rc;
  }

  /* Try an exclusive lock on DMS2/DMS3. If successful, this is the first 
  ** and only connection to the database. In this case initialize the 
  ** shared-memory and run log file recovery.  */
  assert( LSM_LOCK_DMS3==1+LSM_LOCK_DMS2 );
  rc = lsmShmTestLock(pDb, LSM_LOCK_DMS2, 2, LSM_LOCK_EXCL);
  if( rc==LSM_OK ){
    memset(pDb->pShmhdr, 0, sizeof(ShmHeader));
    rc = lsmCheckpointRecover(pDb);
    if( rc==LSM_OK ){
      rc = lsmLogRecover(pDb);
    }
    if( rc==LSM_OK ){
      ShmHeader *pShm = pDb->pShmhdr;
      pShm->aReader[0].iLsmId = lsmCheckpointId(pShm->aSnap1, 0);
      pShm->aReader[0].iTreeId = pDb->treehdr.iUsedShmid;
    }
  }else if( rc==LSM_BUSY ){
    rc = LSM_OK;
  }

  /* Take a shared lock on DMS2. In multi-process mode this lock "cannot" 
  ** fail, as connections may only hold an exclusive lock on DMS2 if they 
  ** first hold an exclusive lock on DMS1. And this connection is currently 
  ** holding the exclusive lock on DSM1. 
  **
  ** However, if some other connection has the database open in single-process
  ** mode, this operation will fail. In this case, return the error to the
  ** caller - the attempt to connect to the db has failed.
  */
  if( rc==LSM_OK ){
    rc = lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_SHARED, 0);
  }

  /* If anything went wrong, unlock DMS2. Otherwise, try to take an exclusive
  ** lock on one of the LSM_LOCK_RWCLIENT() locks. Unlock DMS1 in any case. */
  if( rc!=LSM_OK ){
    pDb->pShmhdr = 0;
  }else{
    int i;
    for(i=0; i<LSM_LOCK_NRWCLIENT; i++){
      int rc2 = lsmShmLock(pDb, LSM_LOCK_RWCLIENT(i), LSM_LOCK_EXCL, 0);
      if( rc2==LSM_OK ) pDb->iRwclient = i;
      if( rc2!=LSM_BUSY ){
        rc = rc2;
        break;
      }
    }
  }
  lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);

  return rc;
}

static int dbOpenSharedFd(lsm_env *pEnv, Database *p, int bRoOk){
  int rc;

  rc = lsmEnvOpen(pEnv, p->zName, 0, &p->pFile);
  if( rc==LSM_IOERR && bRoOk ){
    rc = lsmEnvOpen(pEnv, p->zName, LSM_OPEN_READONLY, &p->pFile);
    p->bReadonly = 1;
  }

  return rc;
}

/*
** Return a reference to the shared Database handle for the database 
** identified by canonical path zName. If this is the first connection to
** the named database, a new Database object is allocated. Otherwise, a
** pointer to an existing object is returned.
**
** If successful, *ppDatabase is set to point to the shared Database 
** structure and LSM_OK returned. Otherwise, *ppDatabase is set to NULL
** and and LSM error code returned.
**
** Each successful call to this function should be (eventually) matched
** by a call to lsmDbDatabaseRelease().
*/
int lsmDbDatabaseConnect(
  lsm_db *pDb,                    /* Database handle */
  const char *zName               /* Full-path to db file */
){
  lsm_env *pEnv = pDb->pEnv;
  int rc;                         /* Return code */
  Database *p = 0;                /* Pointer returned via *ppDatabase */
  int nName = lsmStrlen(zName);

  assert( pDb->pDatabase==0 );
  rc = enterGlobalMutex(pEnv);
  if( rc==LSM_OK ){

    /* Search the global list for an existing object. TODO: Need something
    ** better than the memcmp() below to figure out if a given Database
    ** object represents the requested file.  */
    for(p=gShared.pDatabase; p; p=p->pDbNext){
      if( nName==p->nName && 0==memcmp(zName, p->zName, nName) ) break;
    }

    /* If no suitable Database object was found, allocate a new one. */
    if( p==0 ){
      p = (Database *)lsmMallocZeroRc(pEnv, sizeof(Database)+nName+1, &rc);

      /* If the allocation was successful, fill in other fields and
      ** allocate the client mutex. */ 
      if( rc==LSM_OK ){
        p->bMultiProc = pDb->bMultiProc;
        p->zName = (char *)&p[1];
        p->nName = nName;
        memcpy((void *)p->zName, zName, nName+1);
        rc = lsmMutexNew(pEnv, &p->pClientMutex);
      }

      /* If nothing has gone wrong so far, open the shared fd. And if that
      ** succeeds and this connection requested single-process mode, 
      ** attempt to take the exclusive lock on DMS2.  */
      if( rc==LSM_OK ){
        int bReadonly = (pDb->bReadonly && pDb->bMultiProc);
        rc = dbOpenSharedFd(pDb->pEnv, p, bReadonly);
      }

      if( rc==LSM_OK && p->bMultiProc==0 ){
        assert( p->bReadonly==0 );
        rc = lsmEnvLock(pDb->pEnv, p->pFile, LSM_LOCK_DMS2, LSM_LOCK_EXCL);
      }

      if( rc==LSM_OK ){
        p->pDbNext = gShared.pDatabase;
        gShared.pDatabase = p;
      }else{
        freeDatabase(pEnv, p);
        p = 0;
      }
    }

    if( p ){
      p->nDbRef++;
    }
    leaveGlobalMutex(pEnv);

    if( p ){
      lsmMutexEnter(pDb->pEnv, p->pClientMutex);
      pDb->pNext = p->pConn;
      p->pConn = pDb;
      lsmMutexLeave(pDb->pEnv, p->pClientMutex);
    }
  }

  pDb->pDatabase = p;
  if( rc==LSM_OK ){
    assert( p );
    rc = lsmFsOpen(pDb, zName, p->bReadonly);
  }

  /* If the db handle is read-write, then connect to the system now. Run
  ** recovery as necessary. Or, if this is a read-only database handle,
  ** defer attempting to connect to the system until a read-transaction
  ** is opened.  */
  if( pDb->bReadonly==0 ){
    if( rc==LSM_OK ){
      rc = lsmFsConfigure(pDb);
    }
    if( rc==LSM_OK ){
      rc = doDbConnect(pDb);
    }
  }

  return rc;
}

static void dbDeferClose(lsm_db *pDb){
  if( pDb->pFS ){
    LsmFile *pLsmFile;
    Database *p = pDb->pDatabase;
    pLsmFile = lsmFsDeferClose(pDb->pFS);
    pLsmFile->pNext = p->pLsmFile;
    p->pLsmFile = pLsmFile;
  }
}

LsmFile *lsmDbRecycleFd(lsm_db *db){
  LsmFile *pRet;
  Database *p = db->pDatabase;
  lsmMutexEnter(db->pEnv, p->pClientMutex);
  if( (pRet = p->pLsmFile)!=0 ){
    p->pLsmFile = pRet->pNext;
  }
  lsmMutexLeave(db->pEnv, p->pClientMutex);
  return pRet;
}

/*
** Release a reference to a Database object obtained from 
** lsmDbDatabaseConnect(). There should be exactly one call to this function 
** for each successful call to Find().
*/
void lsmDbDatabaseRelease(lsm_db *pDb){
  Database *p = pDb->pDatabase;
  if( p ){
    lsm_db **ppDb;

    if( pDb->pShmhdr ){
      doDbDisconnect(pDb);
    }

    lsmMutexEnter(pDb->pEnv, p->pClientMutex);
    for(ppDb=&p->pConn; *ppDb!=pDb; ppDb=&((*ppDb)->pNext));
    *ppDb = pDb->pNext;
    dbDeferClose(pDb);
    lsmMutexLeave(pDb->pEnv, p->pClientMutex);

    enterGlobalMutex(pDb->pEnv);
    p->nDbRef--;
    if( p->nDbRef==0 ){
      LsmFile *pIter;
      LsmFile *pNext;
      Database **pp;

      /* Remove the Database structure from the linked list. */
      for(pp=&gShared.pDatabase; *pp!=p; pp=&((*pp)->pDbNext));
      *pp = p->pDbNext;

      /* If they were allocated from the heap, free the shared memory chunks */
      if( p->bMultiProc==0 ){
        int i;
        for(i=0; i<p->nShmChunk; i++){
          lsmFree(pDb->pEnv, p->apShmChunk[i]);
        }
      }

      /* Close any outstanding file descriptors */
      for(pIter=p->pLsmFile; pIter; pIter=pNext){
        pNext = pIter->pNext;
        lsmEnvClose(pDb->pEnv, pIter->pFile);
        lsmFree(pDb->pEnv, pIter);
      }
      freeDatabase(pDb->pEnv, p);
    }
    leaveGlobalMutex(pDb->pEnv);
  }
}

Level *lsmDbSnapshotLevel(Snapshot *pSnapshot){
  return pSnapshot->pLevel;
}

void lsmDbSnapshotSetLevel(Snapshot *pSnap, Level *pLevel){
  pSnap->pLevel = pLevel;
}

/* TODO: Shuffle things around to get rid of this */
static int firstSnapshotInUse(lsm_db *, i64 *);

/* 
** Context object used by the lsmWalkFreelist() utility. 
*/
typedef struct WalkFreelistCtx WalkFreelistCtx;
struct WalkFreelistCtx {
  lsm_db *pDb;
  int bReverse;
  Freelist *pFreelist;
  int iFree;
  int (*xUsr)(void *, int, i64);  /* User callback function */
  void *pUsrctx;                  /* User callback context */
  int bDone;                      /* Set to true after xUsr() returns true */
};

/* 
** Callback used by lsmWalkFreelist().
*/
static int walkFreelistCb(void *pCtx, int iBlk, i64 iSnapshot){
  WalkFreelistCtx *p = (WalkFreelistCtx *)pCtx;
  const int iDir = (p->bReverse ? -1 : 1);
  Freelist *pFree = p->pFreelist;

  assert( p->bDone==0 );
  if( pFree ){
    while( (p->iFree < pFree->nEntry) && p->iFree>=0 ){
      FreelistEntry *pEntry = &pFree->aEntry[p->iFree];
      if( (p->bReverse==0 && pEntry->iBlk>iBlk)
       || (p->bReverse!=0 && pEntry->iBlk<iBlk)
      ){
        break;
      }else{
        p->iFree += iDir;
        if( pEntry->iId>=0 
            && p->xUsr(p->pUsrctx, pEntry->iBlk, pEntry->iId) 
          ){
          p->bDone = 1;
          return 1;
        }
        if( pEntry->iBlk==iBlk ) return 0;
      }
    }
  }

  if( p->xUsr(p->pUsrctx, iBlk, iSnapshot) ){
    p->bDone = 1;
    return 1;
  }
  return 0;
}

/*
** The database handle passed as the first argument must be the worker
** connection. This function iterates through the contents of the current
** free block list, invoking the supplied callback once for each list
** element.
**
** The difference between this function and lsmSortedWalkFreelist() is
** that lsmSortedWalkFreelist() only considers those free-list elements
** stored within the LSM. This function also merges in any in-memory 
** elements.
*/
int lsmWalkFreelist(
  lsm_db *pDb,                    /* Database handle (must be worker) */
  int bReverse,                   /* True to iterate from largest to smallest */
  int (*x)(void *, int, i64),     /* Callback function */
  void *pCtx                      /* First argument to pass to callback */
){
  const int iDir = (bReverse ? -1 : 1);
  int rc;
  int iCtx;

  WalkFreelistCtx ctx[2];

  ctx[0].pDb = pDb;
  ctx[0].bReverse = bReverse;
  ctx[0].pFreelist = &pDb->pWorker->freelist;
  if( ctx[0].pFreelist && bReverse ){
    ctx[0].iFree = ctx[0].pFreelist->nEntry-1;
  }else{
    ctx[0].iFree = 0;
  }
  ctx[0].xUsr = walkFreelistCb;
  ctx[0].pUsrctx = (void *)&ctx[1];
  ctx[0].bDone = 0;

  ctx[1].pDb = pDb;
  ctx[1].bReverse = bReverse;
  ctx[1].pFreelist = pDb->pFreelist;
  if( ctx[1].pFreelist && bReverse ){
    ctx[1].iFree = ctx[1].pFreelist->nEntry-1;
  }else{
    ctx[1].iFree = 0;
  }
  ctx[1].xUsr = x;
  ctx[1].pUsrctx = pCtx;
  ctx[1].bDone = 0;

  rc = lsmSortedWalkFreelist(pDb, bReverse, walkFreelistCb, (void *)&ctx[0]);

  if( ctx[0].bDone==0 ){
    for(iCtx=0; iCtx<2; iCtx++){
      int i;
      WalkFreelistCtx *p = &ctx[iCtx];
      for(i=p->iFree; 
          p->pFreelist && rc==LSM_OK && i<p->pFreelist->nEntry && i>=0;
          i += iDir
         ){
        FreelistEntry *pEntry = &p->pFreelist->aEntry[i];
        if( pEntry->iId>=0 && p->xUsr(p->pUsrctx, pEntry->iBlk, pEntry->iId) ){
          return LSM_OK;
        }
      }
    }
  }

  return rc;
}


typedef struct FindFreeblockCtx FindFreeblockCtx;
struct FindFreeblockCtx {
  i64 iInUse;
  int iRet;
  int bNotOne;
};

static int findFreeblockCb(void *pCtx, int iBlk, i64 iSnapshot){
  FindFreeblockCtx *p = (FindFreeblockCtx *)pCtx;
  if( iSnapshot<p->iInUse && (iBlk!=1 || p->bNotOne==0) ){
    p->iRet = iBlk;
    return 1;
  }
  return 0;
}

static int findFreeblock(lsm_db *pDb, i64 iInUse, int bNotOne, int *piRet){
  int rc;                         /* Return code */
  FindFreeblockCtx ctx;           /* Context object */

  ctx.iInUse = iInUse;
  ctx.iRet = 0;
  ctx.bNotOne = bNotOne;
  rc = lsmWalkFreelist(pDb, 0, findFreeblockCb, (void *)&ctx);
  *piRet = ctx.iRet;

  return rc;
}

/*
** Allocate a new database file block to write data to, either by extending
** the database file or by recycling a free-list entry. The worker snapshot 
** must be held in order to call this function.
**
** If successful, *piBlk is set to the block number allocated and LSM_OK is
** returned. Otherwise, *piBlk is zeroed and an lsm error code returned.
*/
int lsmBlockAllocate(lsm_db *pDb, int iBefore, int *piBlk){
  Snapshot *p = pDb->pWorker;
  int iRet = 0;                   /* Block number of allocated block */
  int rc = LSM_OK;
  i64 iInUse = 0;                 /* Snapshot id still in use */
  i64 iSynced = 0;                /* Snapshot id synced to disk */

  assert( p );

#ifdef LSM_LOG_FREELIST
  {
    static int nCall = 0;
    char *zFree = 0;
    nCall++;
    rc = lsmInfoFreelist(pDb, &zFree);
    if( rc!=LSM_OK ) return rc;
    lsmLogMessage(pDb, 0, "lsmBlockAllocate(): %d freelist: %s", nCall, zFree);
    lsmFree(pDb->pEnv, zFree);
  }
#endif

  /* Set iInUse to the smallest snapshot id that is either:
  **
  **   * Currently in use by a database client,
  **   * May be used by a database client in the future, or
  **   * Is the most recently checkpointed snapshot (i.e. the one that will
  **     be used following recovery if a failure occurs at this point).
  */
  rc = lsmCheckpointSynced(pDb, &iSynced, 0, 0);
  if( rc==LSM_OK && iSynced==0 ) iSynced = p->iId;
  iInUse = iSynced;
  if( rc==LSM_OK && pDb->iReader>=0 ){
    assert( pDb->pClient );
    iInUse = LSM_MIN(iInUse, pDb->pClient->iId);
  }
  if( rc==LSM_OK ) rc = firstSnapshotInUse(pDb, &iInUse);

#ifdef LSM_LOG_FREELIST
  {
    lsmLogMessage(pDb, 0, "lsmBlockAllocate(): "
        "snapshot-in-use: %lld (iSynced=%lld) (client-id=%lld)", 
        iInUse, iSynced, (pDb->iReader>=0 ? pDb->pClient->iId : 0)
    );
  }
#endif


  /* Unless there exists a read-only transaction (which prevents us from
  ** recycling any blocks regardless, query the free block list for a 
  ** suitable block to reuse. 
  **
  ** It might seem more natural to check for a read-only transaction at
  ** the start of this function. However, it is better do wait until after
  ** the call to lsmCheckpointSynced() to do so.
  */
  if( rc==LSM_OK ){
    int bRotrans;
    rc = lsmDetectRoTrans(pDb, &bRotrans);

    if( rc==LSM_OK && bRotrans==0 ){
      rc = findFreeblock(pDb, iInUse, (iBefore>0), &iRet);
    }
  }

  if( iBefore>0 && (iRet<=0 || iRet>=iBefore) ){
    iRet = 0;

  }else if( rc==LSM_OK ){
    /* If a block was found in the free block list, use it and remove it from 
    ** the list. Otherwise, if no suitable block was found, allocate one from
    ** the end of the file.  */
    if( iRet>0 ){
#ifdef LSM_LOG_FREELIST
      lsmLogMessage(pDb, 0, 
          "reusing block %d (snapshot-in-use=%lld)", iRet, iInUse);
#endif
      rc = freelistAppend(pDb, iRet, -1);
      if( rc==LSM_OK ){
        rc = dbTruncate(pDb, iInUse);
      }
    }else{
      iRet = ++(p->nBlock);
#ifdef LSM_LOG_FREELIST
      lsmLogMessage(pDb, 0, "extending file to %d blocks", iRet);
#endif
    }
  }

  assert( iBefore>0 || iRet>0 || rc!=LSM_OK );
  *piBlk = iRet;
  return rc;
}

/*
** Free a database block. The worker snapshot must be held in order to call 
** this function.
**
** If successful, LSM_OK is returned. Otherwise, an lsm error code (e.g. 
** LSM_NOMEM).
*/
int lsmBlockFree(lsm_db *pDb, int iBlk){
  Snapshot *p = pDb->pWorker;
  assert( lsmShmAssertWorker(pDb) );

#ifdef LSM_LOG_FREELIST
  lsmLogMessage(pDb, LSM_OK, "lsmBlockFree(): Free block %d", iBlk);
#endif

  return freelistAppend(pDb, iBlk, p->iId);
}

/*
** Refree a database block. The worker snapshot must be held in order to call 
** this function.
**
** Refreeing is required when a block is allocated using lsmBlockAllocate()
** but then not used. This function is used to push the block back onto
** the freelist. Refreeing a block is different from freeing is, as a refreed
** block may be reused immediately. Whereas a freed block can not be reused 
** until (at least) after the next checkpoint.
*/
int lsmBlockRefree(lsm_db *pDb, int iBlk){
  int rc = LSM_OK;                /* Return code */

#ifdef LSM_LOG_FREELIST
  lsmLogMessage(pDb, LSM_OK, "lsmBlockRefree(): Refree block %d", iBlk);
#endif

  rc = freelistAppend(pDb, iBlk, 0);
  return rc;
}

/*
** If required, copy a database checkpoint from shared memory into the
** database itself.
**
** The WORKER lock must not be held when this is called. This is because
** this function may indirectly call fsync(). And the WORKER lock should
** not be held that long (in case it is required by a client flushing an
** in-memory tree to disk).
*/
int lsmCheckpointWrite(lsm_db *pDb, int bTruncate, u32 *pnWrite){
  int rc;                         /* Return Code */
  u32 nWrite = 0;

  assert( pDb->pWorker==0 );
  assert( 1 || pDb->pClient==0 );
  assert( lsmShmAssertLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_UNLOCK) );

  rc = lsmShmLock(pDb, LSM_LOCK_CHECKPOINTER, LSM_LOCK_EXCL, 0);
  if( rc!=LSM_OK ) return rc;

  rc = lsmCheckpointLoad(pDb, 0);
  if( rc==LSM_OK ){
    int nBlock = lsmCheckpointNBlock(pDb->aSnapshot);
    ShmHeader *pShm = pDb->pShmhdr;
    int bDone = 0;                /* True if checkpoint is already stored */

    /* Check if this checkpoint has already been written to the database
    ** file. If so, set variable bDone to true.  */
    if( pShm->iMetaPage ){
      MetaPage *pPg;              /* Meta page */
      u8 *aData;                  /* Meta-page data buffer */
      int nData;                  /* Size of aData[] in bytes */
      i64 iCkpt;                  /* Id of checkpoint just loaded */
      i64 iDisk;                  /* Id of checkpoint already stored in db */
      iCkpt = lsmCheckpointId(pDb->aSnapshot, 0);
      rc = lsmFsMetaPageGet(pDb->pFS, 0, pShm->iMetaPage, &pPg);
      if( rc==LSM_OK ){
        aData = lsmFsMetaPageData(pPg, &nData);
        iDisk = lsmCheckpointId((u32 *)aData, 1);
        nWrite = lsmCheckpointNWrite((u32 *)aData, 1);
        lsmFsMetaPageRelease(pPg);
      }
      bDone = (iDisk>=iCkpt);
    }

    if( rc==LSM_OK && bDone==0 ){
      int iMeta = (pShm->iMetaPage % 2) + 1;
      if( pDb->eSafety!=LSM_SAFETY_OFF ){
        rc = lsmFsSyncDb(pDb->pFS, nBlock);
      }
      if( rc==LSM_OK ) rc = lsmCheckpointStore(pDb, iMeta);
      if( rc==LSM_OK && pDb->eSafety!=LSM_SAFETY_OFF){
        rc = lsmFsSyncDb(pDb->pFS, 0);
      }
      if( rc==LSM_OK ){
        pShm->iMetaPage = iMeta;
        nWrite = lsmCheckpointNWrite(pDb->aSnapshot, 0) - nWrite;
      }
#ifdef LSM_LOG_WORK
      lsmLogMessage(pDb, 0, "finish checkpoint %d", 
          (int)lsmCheckpointId(pDb->aSnapshot, 0)
      );
#endif
    }

    if( rc==LSM_OK && bTruncate && nBlock>0 ){
      rc = lsmFsTruncateDb(pDb->pFS, (i64)nBlock*lsmFsBlockSize(pDb->pFS));
    }
  }

  lsmShmLock(pDb, LSM_LOCK_CHECKPOINTER, LSM_LOCK_UNLOCK, 0);
  if( pnWrite && rc==LSM_OK ) *pnWrite = nWrite;
  return rc;
}

int lsmBeginWork(lsm_db *pDb){
  int rc;

  /* Attempt to take the WORKER lock */
  rc = lsmShmLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_EXCL, 0);

  /* Deserialize the current worker snapshot */
  if( rc==LSM_OK ){
    rc = lsmCheckpointLoadWorker(pDb);
  }
  return rc;
}

void lsmFreeSnapshot(lsm_env *pEnv, Snapshot *p){
  if( p ){
    lsmSortedFreeLevel(pEnv, p->pLevel);
    lsmFree(pEnv, p->freelist.aEntry);
    lsmFree(pEnv, p->redirect.a);
    lsmFree(pEnv, p);
  }
}

/*
** Attempt to populate one of the read-lock slots to contain lock values
** iLsm/iShm. Or, if such a slot exists already, this function is a no-op.
**
** It is not an error if no slot can be populated because the write-lock
** cannot be obtained. If any other error occurs, return an LSM error code.
** Otherwise, LSM_OK.
**
** This function is called at various points to try to ensure that there
** always exists at least one read-lock slot that can be used by a read-only
** client. And so that, in the usual case, there is an "exact match" available
** whenever a read transaction is opened by any client. At present this
** function is called when:
**
**    * A write transaction that called lsmTreeDiscardOld() is committed, and
**    * Whenever the working snapshot is updated (i.e. lsmFinishWork()).
*/
static int dbSetReadLock(lsm_db *db, i64 iLsm, u32 iShm){
  int rc = LSM_OK;
  ShmHeader *pShm = db->pShmhdr;
  int i;

  /* Check if there is already a slot containing the required values. */
  for(i=0; i<LSM_LOCK_NREADER; i++){
    ShmReader *p = &pShm->aReader[i];
    if( p->iLsmId==iLsm && p->iTreeId==iShm ) return LSM_OK;
  }

  /* Iterate through all read-lock slots, attempting to take a write-lock
  ** on each of them. If a write-lock succeeds, populate the locked slot
  ** with the required values and break out of the loop.  */
  for(i=0; rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
    rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
    if( rc==LSM_BUSY ){
      rc = LSM_OK;
    }else{
      ShmReader *p = &pShm->aReader[i];
      p->iLsmId = iLsm;
      p->iTreeId = iShm;
      lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
      break;
    }
  }

  return rc;
}

/*
** Release the read-lock currently held by connection db.
*/
int dbReleaseReadlock(lsm_db *db){
  int rc = LSM_OK;
  if( db->iReader>=0 ){
    rc = lsmShmLock(db, LSM_LOCK_READER(db->iReader), LSM_LOCK_UNLOCK, 0);
    db->iReader = -1;
  }
  db->bRoTrans = 0;
  return rc;
}


/*
** Argument bFlush is true if the contents of the in-memory tree has just
** been flushed to disk. The significance of this is that once the snapshot
** created to hold the updated state of the database is synced to disk, log
** file space can be recycled.
*/
void lsmFinishWork(lsm_db *pDb, int bFlush, int *pRc){
  int rc = *pRc;
  assert( rc!=0 || pDb->pWorker );
  if( pDb->pWorker ){
    /* If no error has occurred, serialize the worker snapshot and write
    ** it to shared memory.  */
    if( rc==LSM_OK ){
      rc = lsmSaveWorker(pDb, bFlush);
    }

    /* Assuming no error has occurred, update a read lock slot with the
    ** new snapshot id (see comments above function dbSetReadLock()).  */
    if( rc==LSM_OK ){
      if( pDb->iReader<0 ){
        rc = lsmTreeLoadHeader(pDb, 0);
      }
      if( rc==LSM_OK ){
        rc = dbSetReadLock(pDb, pDb->pWorker->iId, pDb->treehdr.iUsedShmid);
      }
    }

    /* Free the snapshot object. */
    lsmFreeSnapshot(pDb->pEnv, pDb->pWorker);
    pDb->pWorker = 0;
  }

  lsmShmLock(pDb, LSM_LOCK_WORKER, LSM_LOCK_UNLOCK, 0);
  *pRc = rc;
}

/*
** Called when recovery is finished.
*/
int lsmFinishRecovery(lsm_db *pDb){
  lsmTreeEndTransaction(pDb, 1);
  return LSM_OK;
}

/*
** Check if the currently configured compression functions
** (LSM_CONFIG_SET_COMPRESSION) are compatible with a database that has its
** compression id set to iReq. Compression routines are compatible if iReq
** is zero (indicating the database is empty), or if it is equal to the 
** compression id of the configured compression routines.
**
** If the check shows that the current compression are incompatible and there
** is a compression factory registered, give it a chance to install new
** compression routines.
**
** If, after any registered factory is invoked, the compression functions
** are still incompatible, return LSM_MISMATCH. Otherwise, LSM_OK.
*/
int lsmCheckCompressionId(lsm_db *pDb, u32 iReq){
  if( iReq!=LSM_COMPRESSION_EMPTY && pDb->compress.iId!=iReq ){
    if( pDb->factory.xFactory ){
      pDb->bInFactory = 1;
      pDb->factory.xFactory(pDb->factory.pCtx, pDb, iReq);
      pDb->bInFactory = 0;
    }
    if( pDb->compress.iId!=iReq ){
      /* Incompatible */
      return LSM_MISMATCH;
    }
  }
  /* Compatible */
  return LSM_OK;
}

/*
** Begin a read transaction. This function is a no-op if the connection
** passed as the only argument already has an open read transaction.
*/
int lsmBeginReadTrans(lsm_db *pDb){
  const int MAX_READLOCK_ATTEMPTS = 10;
  const int nMaxAttempt = (pDb->bRoTrans ? 1 : MAX_READLOCK_ATTEMPTS);

  int rc = LSM_OK;                /* Return code */
  int iAttempt = 0;

  assert( pDb->pWorker==0 );

  while( rc==LSM_OK && pDb->iReader<0 && (iAttempt++)<nMaxAttempt ){
    int iTreehdr = 0;
    int iSnap = 0;
    assert( pDb->pCsr==0 && pDb->nTransOpen==0 );

    /* Load the in-memory tree header. */
    rc = lsmTreeLoadHeader(pDb, &iTreehdr);

    /* Load the database snapshot */
    if( rc==LSM_OK ){
      if( lsmCheckpointClientCacheOk(pDb)==0 ){
        lsmFreeSnapshot(pDb->pEnv, pDb->pClient);
        pDb->pClient = 0;
        lsmMCursorFreeCache(pDb);
        lsmFsPurgeCache(pDb->pFS);
        rc = lsmCheckpointLoad(pDb, &iSnap);
      }else{
        iSnap = 1;
      }
    }

    /* Take a read-lock on the tree and snapshot just loaded. Then check
    ** that the shared-memory still contains the same values. If so, proceed.
    ** Otherwise, relinquish the read-lock and retry the whole procedure
    ** (starting with loading the in-memory tree header).  */
    if( rc==LSM_OK ){
      u32 iShmMax = pDb->treehdr.iUsedShmid;
      u32 iShmMin = pDb->treehdr.iNextShmid+1-LSM_MAX_SHMCHUNKS;
      rc = lsmReadlock(
          pDb, lsmCheckpointId(pDb->aSnapshot, 0), iShmMin, iShmMax
      );
      if( rc==LSM_OK ){
        if( lsmTreeLoadHeaderOk(pDb, iTreehdr)
         && lsmCheckpointLoadOk(pDb, iSnap)
        ){
          /* Read lock has been successfully obtained. Deserialize the 
          ** checkpoint just loaded. TODO: This will be removed after 
          ** lsm_sorted.c is changed to work directly from the serialized
          ** version of the snapshot.  */
          if( pDb->pClient==0 ){
            rc = lsmCheckpointDeserialize(pDb, 0, pDb->aSnapshot,&pDb->pClient);
          }
          assert( (rc==LSM_OK)==(pDb->pClient!=0) );
          assert( pDb->iReader>=0 );

          /* Check that the client has the right compression hooks loaded.
          ** If not, set rc to LSM_MISMATCH.  */
          if( rc==LSM_OK ){
            rc = lsmCheckCompressionId(pDb, pDb->pClient->iCmpId);
          }
        }else{
          rc = dbReleaseReadlock(pDb);
        }
      }

      if( rc==LSM_BUSY ){
        rc = LSM_OK;
      }
    }
#if 0
if( rc==LSM_OK && pDb->pClient ){
  fprintf(stderr, 
      "reading %p: snapshot:%d used-shmid:%d trans-id:%d iOldShmid=%d\n",
      (void *)pDb,
      (int)pDb->pClient->iId, (int)pDb->treehdr.iUsedShmid, 
      (int)pDb->treehdr.root.iTransId,
      (int)pDb->treehdr.iOldShmid
  );
}
#endif
  }

  if( rc==LSM_OK ){
    rc = lsmShmCacheChunks(pDb, pDb->treehdr.nChunk);
  }
  if( rc!=LSM_OK ){
    dbReleaseReadlock(pDb);
  }
  if( pDb->pClient==0 && rc==LSM_OK ) rc = LSM_BUSY;
  return rc;
}

/*
** This function is used by a read-write connection to determine if there
** are currently one or more read-only transactions open on the database
** (in this context a read-only transaction is one opened by a read-only
** connection on a non-live database).
**
** If no error occurs, LSM_OK is returned and *pbExists is set to true if
** some other connection has a read-only transaction open, or false 
** otherwise. If an error occurs an LSM error code is returned and the final
** value of *pbExist is undefined.
*/
int lsmDetectRoTrans(lsm_db *db, int *pbExist){
  int rc;

  /* Only a read-write connection may use this function. */
  assert( db->bReadonly==0 );

  rc = lsmShmTestLock(db, LSM_LOCK_ROTRANS, 1, LSM_LOCK_EXCL);
  if( rc==LSM_BUSY ){
    *pbExist = 1;
    rc = LSM_OK;
  }else{
    *pbExist = 0;
  }

  return rc;
}

/*
** db is a read-only database handle in the disconnected state. This function
** attempts to open a read-transaction on the database. This may involve
** connecting to the database system (opening shared memory etc.).
*/
int lsmBeginRoTrans(lsm_db *db){
  int rc = LSM_OK;

  assert( db->bReadonly && db->pShmhdr==0 );
  assert( db->iReader<0 );

  if( db->bRoTrans==0 ){

    /* Attempt a shared-lock on DMS1. */
    rc = lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_SHARED, 0);
    if( rc!=LSM_OK ) return rc;

    rc = lsmShmTestLock(
        db, LSM_LOCK_RWCLIENT(0), LSM_LOCK_NREADER, LSM_LOCK_SHARED
    );
    if( rc==LSM_OK ){
      /* System is not live. Take a SHARED lock on the ROTRANS byte and
      ** release DMS1. Locking ROTRANS tells all read-write clients that they
      ** may not recycle any disk space from within the database or log files,
      ** as a read-only client may be using it.  */
      rc = lsmShmLock(db, LSM_LOCK_ROTRANS, LSM_LOCK_SHARED, 0);
      lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);

      if( rc==LSM_OK ){
        db->bRoTrans = 1;
        rc = lsmShmCacheChunks(db, 1);
        if( rc==LSM_OK ){
          db->pShmhdr = (ShmHeader *)db->apShm[0];
          memset(db->pShmhdr, 0, sizeof(ShmHeader));
          rc = lsmCheckpointRecover(db);
          if( rc==LSM_OK ){
            rc = lsmLogRecover(db);
          }
        }
      }
    }else if( rc==LSM_BUSY ){
      /* System is live! */
      rc = lsmShmLock(db, LSM_LOCK_DMS3, LSM_LOCK_SHARED, 0);
      lsmShmLock(db, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0);
      if( rc==LSM_OK ){
        rc = lsmShmCacheChunks(db, 1);
        if( rc==LSM_OK ){
          db->pShmhdr = (ShmHeader *)db->apShm[0];
        }
      }
    }

    if( rc==LSM_OK ){
      rc = lsmBeginReadTrans(db);
    }
  }

  return rc;
}

/*
** Close the currently open read transaction.
*/
void lsmFinishReadTrans(lsm_db *pDb){

  /* Worker connections should not be closing read transactions. And
  ** read transactions should only be closed after all cursors and write
  ** transactions have been closed. Finally pClient should be non-NULL
  ** only iff pDb->iReader>=0.  */
  assert( pDb->pWorker==0 );
  assert( pDb->pCsr==0 && pDb->nTransOpen==0 );

  if( pDb->bRoTrans ){
    int i;
    for(i=0; i<pDb->nShm; i++){
      lsmFree(pDb->pEnv, pDb->apShm[i]);
    }
    lsmFree(pDb->pEnv, pDb->apShm);
    pDb->apShm = 0;
    pDb->nShm = 0;
    pDb->pShmhdr = 0;

    lsmShmLock(pDb, LSM_LOCK_ROTRANS, LSM_LOCK_UNLOCK, 0);
  }
  dbReleaseReadlock(pDb);
}

/*
** Open a write transaction.
*/
int lsmBeginWriteTrans(lsm_db *pDb){
  int rc = LSM_OK;                /* Return code */
  ShmHeader *pShm = pDb->pShmhdr; /* Shared memory header */

  assert( pDb->nTransOpen==0 );
  assert( pDb->bDiscardOld==0 );
  assert( pDb->bReadonly==0 );

  /* If there is no read-transaction open, open one now. */
  if( pDb->iReader<0 ){
    rc = lsmBeginReadTrans(pDb);
  }

  /* Attempt to take the WRITER lock */
  if( rc==LSM_OK ){
    rc = lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_EXCL, 0);
  }

  /* If the previous writer failed mid-transaction, run emergency rollback. */
  if( rc==LSM_OK && pShm->bWriter ){
    rc = lsmTreeRepair(pDb);
    if( rc==LSM_OK ) pShm->bWriter = 0;
  }

  /* Check that this connection is currently reading from the most recent
  ** version of the database. If not, return LSM_BUSY.  */
  if( rc==LSM_OK && memcmp(&pShm->hdr1, &pDb->treehdr, sizeof(TreeHeader)) ){
    rc = LSM_BUSY;
  }

  if( rc==LSM_OK ){
    rc = lsmLogBegin(pDb);
  }

  /* If everything was successful, set the "transaction-in-progress" flag
  ** and return LSM_OK. Otherwise, if some error occurred, relinquish the 
  ** WRITER lock and return an error code.  */
  if( rc==LSM_OK ){
    TreeHeader *p = &pDb->treehdr;
    pShm->bWriter = 1;
    p->root.iTransId++;
    if( lsmTreeHasOld(pDb) && p->iOldLog==pDb->pClient->iLogOff ){
      lsmTreeDiscardOld(pDb);
      pDb->bDiscardOld = 1;
    }
  }else{
    lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_UNLOCK, 0);
    if( pDb->pCsr==0 ) lsmFinishReadTrans(pDb);
  }
  return rc;
}

/*
** End the current write transaction. The connection is left with an open
** read transaction. It is an error to call this if there is no open write 
** transaction.
**
** If the transaction was committed, then a commit record has already been
** written into the log file when this function is called. Or, if the
** transaction was rolled back, both the log file and in-memory tree 
** structure have already been restored. In either case, this function 
** merely releases locks and other resources held by the write-transaction.
**
** LSM_OK is returned if successful, or an LSM error code otherwise.
*/
int lsmFinishWriteTrans(lsm_db *pDb, int bCommit){
  int rc = LSM_OK;
  int bFlush = 0;

  lsmLogEnd(pDb, bCommit);
  if( rc==LSM_OK && bCommit && lsmTreeSize(pDb)>pDb->nTreeLimit ){
    bFlush = 1;
    lsmTreeMakeOld(pDb);
  }
  lsmTreeEndTransaction(pDb, bCommit);

  if( rc==LSM_OK ){
    if( bFlush && pDb->bAutowork ){
      rc = lsmSortedAutoWork(pDb, 1);
    }else if( bCommit && pDb->bDiscardOld ){
      rc = dbSetReadLock(pDb, pDb->pClient->iId, pDb->treehdr.iUsedShmid);
    }
  }
  pDb->bDiscardOld = 0;
  lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_UNLOCK, 0);

  if( bFlush && pDb->bAutowork==0 && pDb->xWork ){
    pDb->xWork(pDb, pDb->pWorkCtx);
  }
  return rc;
}


/*
** Return non-zero if the caller is holding the client mutex.
*/
#ifdef LSM_DEBUG
int lsmHoldingClientMutex(lsm_db *pDb){
  return lsmMutexHeld(pDb->pEnv, pDb->pDatabase->pClientMutex);
}
#endif

static int slotIsUsable(ShmReader *p, i64 iLsm, u32 iShmMin, u32 iShmMax){
  return( 
      p->iLsmId && p->iLsmId<=iLsm 
      && shm_sequence_ge(iShmMax, p->iTreeId)
      && shm_sequence_ge(p->iTreeId, iShmMin)
  );
}

/*
** Obtain a read-lock on database version identified by the combination
** of snapshot iLsm and tree iTree. Return LSM_OK if successful, or
** an LSM error code otherwise.
*/
int lsmReadlock(lsm_db *db, i64 iLsm, u32 iShmMin, u32 iShmMax){
  int rc = LSM_OK;
  ShmHeader *pShm = db->pShmhdr;
  int i;

  assert( db->iReader<0 );
  assert( shm_sequence_ge(iShmMax, iShmMin) );

  /* This is a no-op if the read-only transaction flag is set. */
  if( db->bRoTrans ){
    db->iReader = 0;
    return LSM_OK;
  }

  /* Search for an exact match. */
  for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
    ShmReader *p = &pShm->aReader[i];
    if( p->iLsmId==iLsm && p->iTreeId==iShmMax ){
      rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
      if( rc==LSM_OK && p->iLsmId==iLsm && p->iTreeId==iShmMax ){
        db->iReader = i;
      }else if( rc==LSM_BUSY ){
        rc = LSM_OK;
      }
    }
  }

  /* Try to obtain a write-lock on each slot, in order. If successful, set
  ** the slot values to iLsm/iTree.  */
  for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
    rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
    if( rc==LSM_BUSY ){
      rc = LSM_OK;
    }else{
      ShmReader *p = &pShm->aReader[i];
      p->iLsmId = iLsm;
      p->iTreeId = iShmMax;
      rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
      assert( rc!=LSM_BUSY );
      if( rc==LSM_OK ) db->iReader = i;
    }
  }

  /* Search for any usable slot */
  for(i=0; db->iReader<0 && rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
    ShmReader *p = &pShm->aReader[i];
    if( slotIsUsable(p, iLsm, iShmMin, iShmMax) ){
      rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_SHARED, 0);
      if( rc==LSM_OK && slotIsUsable(p, iLsm, iShmMin, iShmMax) ){
        db->iReader = i;
      }else if( rc==LSM_BUSY ){
        rc = LSM_OK;
      }
    }
  }

  if( rc==LSM_OK && db->iReader<0 ){
    rc = LSM_BUSY;
  }
  return rc;
}

/*
** This is used to check if there exists a read-lock locking a particular
** version of either the in-memory tree or database file. 
**
** If iLsmId is non-zero, then it is a snapshot id. If there exists a 
** read-lock using this snapshot or newer, set *pbInUse to true. Or,
** if there is no such read-lock, set it to false.
**
** Or, if iLsmId is zero, then iShmid is a shared-memory sequence id.
** Search for a read-lock using this sequence id or newer. etc.
*/
static int isInUse(lsm_db *db, i64 iLsmId, u32 iShmid, int *pbInUse){
  ShmHeader *pShm = db->pShmhdr;
  int i;
  int rc = LSM_OK;

  for(i=0; rc==LSM_OK && i<LSM_LOCK_NREADER; i++){
    ShmReader *p = &pShm->aReader[i];
    if( p->iLsmId ){
      if( (iLsmId!=0 && p->iLsmId!=0 && iLsmId>=p->iLsmId) 
       || (iLsmId==0 && shm_sequence_ge(p->iTreeId, iShmid))
      ){
        rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
        if( rc==LSM_OK ){
          p->iLsmId = 0;
          lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
        }
      }
    }
  }

  if( rc==LSM_BUSY ){
    *pbInUse = 1;
    return LSM_OK;
  }
  *pbInUse = 0;
  return rc;
}

/*
** This function is called by worker connections to determine the smallest
** snapshot id that is currently in use by a database client. The worker
** connection uses this result to determine whether or not it is safe to
** recycle a database block.
*/
static int firstSnapshotInUse(
  lsm_db *db,                     /* Database handle */
  i64 *piInUse                    /* IN/OUT: Smallest snapshot id in use */
){
  ShmHeader *pShm = db->pShmhdr;
  i64 iInUse = *piInUse;
  int i;

  assert( iInUse>0 );
  for(i=0; i<LSM_LOCK_NREADER; i++){
    ShmReader *p = &pShm->aReader[i];
    if( p->iLsmId ){
      i64 iThis = p->iLsmId;
      if( iThis!=0 && iInUse>iThis ){
        int rc = lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_EXCL, 0);
        if( rc==LSM_OK ){
          p->iLsmId = 0;
          lsmShmLock(db, LSM_LOCK_READER(i), LSM_LOCK_UNLOCK, 0);
        }else if( rc==LSM_BUSY ){
          iInUse = iThis;
        }else{
          /* Some error other than LSM_BUSY. Return the error code to
          ** the caller in this case.  */
          return rc;
        }
      }
    }
  }

  *piInUse = iInUse;
  return LSM_OK;
}

int lsmTreeInUse(lsm_db *db, u32 iShmid, int *pbInUse){
  if( db->treehdr.iUsedShmid==iShmid ){
    *pbInUse = 1;
    return LSM_OK;
  }
  return isInUse(db, 0, iShmid, pbInUse);
}

int lsmLsmInUse(lsm_db *db, i64 iLsmId, int *pbInUse){
  if( db->pClient && db->pClient->iId<=iLsmId ){
    *pbInUse = 1;
    return LSM_OK;
  }
  return isInUse(db, iLsmId, 0, pbInUse);
}

/*
** This function may only be called after a successful call to
** lsmDbDatabaseConnect(). It returns true if the connection is in
** multi-process mode, or false otherwise.
*/
int lsmDbMultiProc(lsm_db *pDb){
  return pDb->pDatabase && pDb->pDatabase->bMultiProc;
}


/*************************************************************************
**************************************************************************
**************************************************************************
**************************************************************************
**************************************************************************
*************************************************************************/

/*
** Ensure that database connection db has cached pointers to at least the 
** first nChunk chunks of shared memory.
*/
int lsmShmCacheChunks(lsm_db *db, int nChunk){
  int rc = LSM_OK;
  if( nChunk>db->nShm ){
    static const int NINCR = 16;
    Database *p = db->pDatabase;
    lsm_env *pEnv = db->pEnv;
    int nAlloc;
    int i;

    /* Ensure that the db->apShm[] array is large enough. If an attempt to
    ** allocate memory fails, return LSM_NOMEM immediately. The apShm[] array
    ** is always extended in multiples of 16 entries - so the actual allocated
    ** size can be inferred from nShm.  */ 
    nAlloc = ((db->nShm + NINCR - 1) / NINCR) * NINCR;
    while( nChunk>=nAlloc ){
      void **apShm;
      nAlloc += NINCR;
      apShm = lsmRealloc(pEnv, db->apShm, sizeof(void*)*nAlloc);
      if( !apShm ) return LSM_NOMEM_BKPT;
      db->apShm = apShm;
    }

    if( db->bRoTrans ){
      for(i=db->nShm; rc==LSM_OK && i<nChunk; i++){
        db->apShm[i] = lsmMallocZeroRc(pEnv, LSM_SHM_CHUNK_SIZE, &rc);
        db->nShm++;
      }

    }else{

      /* Enter the client mutex */
      lsmMutexEnter(pEnv, p->pClientMutex);

      /* Extend the Database objects apShmChunk[] array if necessary. Using the
       ** same pattern as for the lsm_db.apShm[] array above.  */
      nAlloc = ((p->nShmChunk + NINCR - 1) / NINCR) * NINCR;
      while( nChunk>=nAlloc ){
        void **apShm;
        nAlloc +=  NINCR;
        apShm = lsmRealloc(pEnv, p->apShmChunk, sizeof(void*)*nAlloc);
        if( !apShm ){
          rc = LSM_NOMEM_BKPT;
          break;
        }
        p->apShmChunk = apShm;
      }

      for(i=db->nShm; rc==LSM_OK && i<nChunk; i++){
        if( i>=p->nShmChunk ){
          void *pChunk = 0;
          if( p->bMultiProc==0 ){
            /* Single process mode */
            pChunk = lsmMallocZeroRc(pEnv, LSM_SHM_CHUNK_SIZE, &rc);
          }else{
            /* Multi-process mode */
            rc = lsmEnvShmMap(pEnv, p->pFile, i, LSM_SHM_CHUNK_SIZE, &pChunk);
          }
          if( rc==LSM_OK ){
            p->apShmChunk[i] = pChunk;
            p->nShmChunk++;
          }
        }
        if( rc==LSM_OK ){
          db->apShm[i] = p->apShmChunk[i];
          db->nShm++;
        }
      }

      /* Release the client mutex */
      lsmMutexLeave(pEnv, p->pClientMutex);
    }
  }

  return rc;
}

static int lockSharedFile(lsm_env *pEnv, Database *p, int iLock, int eOp){
  int rc = LSM_OK;
  if( p->bMultiProc ){
    rc = lsmEnvLock(pEnv, p->pFile, iLock, eOp);
  }
  return rc;
}

/*
** Test if it would be possible for connection db to obtain a lock of type
** eType on the nLock locks starting at iLock. If so, return LSM_OK. If it
** would not be possible to obtain the lock due to a lock held by another
** connection, return LSM_BUSY. If an IO or other error occurs (i.e. in the 
** lsm_env.xTestLock function), return some other LSM error code.
**
** Note that this function never actually locks the database - it merely
** queries the system to see if there exists a lock that would prevent
** it from doing so.
*/
int lsmShmTestLock(
  lsm_db *db,
  int iLock,
  int nLock,
  int eOp
){
  int rc = LSM_OK;
  lsm_db *pIter;
  Database *p = db->pDatabase;
  int i;
  u64 mask = 0;

  for(i=iLock; i<(iLock+nLock); i++){
    mask |= ((u64)1 << (iLock-1));
    if( eOp==LSM_LOCK_EXCL ) mask |= ((u64)1 << (iLock+32-1));
  }

  lsmMutexEnter(db->pEnv, p->pClientMutex);
  for(pIter=p->pConn; pIter; pIter=pIter->pNext){
    if( pIter!=db && (pIter->mLock & mask) ) break;
  }

  if( pIter ){
    rc = LSM_BUSY;
  }else if( p->bMultiProc ){
    rc = lsmEnvTestLock(db->pEnv, p->pFile, iLock, nLock, eOp);
  }

  lsmMutexLeave(db->pEnv, p->pClientMutex);
  return rc;
}

/*
** Attempt to obtain the lock identified by the iLock and bExcl parameters.
** If successful, return LSM_OK. If the lock cannot be obtained because 
** there exists some other conflicting lock, return LSM_BUSY. If some other
** error occurs, return an LSM error code.
**
** Parameter iLock must be one of LSM_LOCK_WRITER, WORKER or CHECKPOINTER,
** or else a value returned by the LSM_LOCK_READER macro.
*/
int lsmShmLock(
  lsm_db *db, 
  int iLock,
  int eOp,                        /* One of LSM_LOCK_UNLOCK, SHARED or EXCL */
  int bBlock                      /* True for a blocking lock */
){
  lsm_db *pIter;
  const u64 me = ((u64)1 << (iLock-1));
  const u64 ms = ((u64)1 << (iLock+32-1));
  int rc = LSM_OK;
  Database *p = db->pDatabase;

  assert( eOp!=LSM_LOCK_EXCL || p->bReadonly==0 );
  assert( iLock>=1 && iLock<=LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT-1) );
  assert( LSM_LOCK_RWCLIENT(LSM_LOCK_NRWCLIENT-1)<=32 );
  assert( eOp==LSM_LOCK_UNLOCK || eOp==LSM_LOCK_SHARED || eOp==LSM_LOCK_EXCL );

  /* Check for a no-op. Proceed only if this is not one of those. */
  if( (eOp==LSM_LOCK_UNLOCK && (db->mLock & (me|ms))!=0)
   || (eOp==LSM_LOCK_SHARED && (db->mLock & (me|ms))!=ms)
   || (eOp==LSM_LOCK_EXCL   && (db->mLock & me)==0)
  ){
    int nExcl = 0;                /* Number of connections holding EXCLUSIVE */
    int nShared = 0;              /* Number of connections holding SHARED */
    lsmMutexEnter(db->pEnv, p->pClientMutex);

    /* Figure out the locks currently held by this process on iLock, not
    ** including any held by connection db.  */
    for(pIter=p->pConn; pIter; pIter=pIter->pNext){
      assert( (pIter->mLock & me)==0 || (pIter->mLock & ms)!=0 );
      if( pIter!=db ){
        if( pIter->mLock & me ){
          nExcl++;
        }else if( pIter->mLock & ms ){
          nShared++;
        }
      }
    }
    assert( nExcl==0 || nExcl==1 );
    assert( nExcl==0 || nShared==0 );
    assert( nExcl==0 || (db->mLock & (me|ms))==0 );

    switch( eOp ){
      case LSM_LOCK_UNLOCK:
        if( nShared==0 ){
          lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_UNLOCK);
        }
        db->mLock &= ~(me|ms);
        break;

      case LSM_LOCK_SHARED:
        if( nExcl ){
          rc = LSM_BUSY;
        }else{
          if( nShared==0 ){
            rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_SHARED);
          }
          if( rc==LSM_OK ){
            db->mLock |= ms;
            db->mLock &= ~me;
          }
        }
        break;

      default:
        assert( eOp==LSM_LOCK_EXCL );
        if( nExcl || nShared ){
          rc = LSM_BUSY;
        }else{
          rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_EXCL);
          if( rc==LSM_OK ){
            db->mLock |= (me|ms);
          }
        }
        break;
    }

    lsmMutexLeave(db->pEnv, p->pClientMutex);
  }

  return rc;
}

#ifdef LSM_DEBUG

int shmLockType(lsm_db *db, int iLock){
  const u64 me = ((u64)1 << (iLock-1));
  const u64 ms = ((u64)1 << (iLock+32-1));

  if( db->mLock & me ) return LSM_LOCK_EXCL;
  if( db->mLock & ms ) return LSM_LOCK_SHARED;
  return LSM_LOCK_UNLOCK;
}

/*
** The arguments passed to this function are similar to those passed to
** the lsmShmLock() function. However, instead of obtaining a new lock 
** this function returns true if the specified connection already holds 
** (or does not hold) such a lock, depending on the value of eOp. As
** follows:
**
**   (eOp==LSM_LOCK_UNLOCK) -> true if db has no lock on iLock
**   (eOp==LSM_LOCK_SHARED) -> true if db has at least a SHARED lock on iLock.
**   (eOp==LSM_LOCK_EXCL)   -> true if db has an EXCLUSIVE lock on iLock.
*/
int lsmShmAssertLock(lsm_db *db, int iLock, int eOp){
  int ret;
  int eHave;

  assert( iLock>=1 && iLock<=LSM_LOCK_READER(LSM_LOCK_NREADER-1) );
  assert( iLock<=16 );
  assert( eOp==LSM_LOCK_UNLOCK || eOp==LSM_LOCK_SHARED || eOp==LSM_LOCK_EXCL );

  eHave = shmLockType(db, iLock);

  switch( eOp ){
    case LSM_LOCK_UNLOCK:
      ret = (eHave==LSM_LOCK_UNLOCK);
      break;
    case LSM_LOCK_SHARED:
      ret = (eHave!=LSM_LOCK_UNLOCK);
      break;
    case LSM_LOCK_EXCL:
      ret = (eHave==LSM_LOCK_EXCL);
      break;
    default:
      assert( !"bad eOp value passed to lsmShmAssertLock()" );
      break;
  }

  return ret;
}

int lsmShmAssertWorker(lsm_db *db){
  return lsmShmAssertLock(db, LSM_LOCK_WORKER, LSM_LOCK_EXCL) && db->pWorker;
}

/*
** This function does not contribute to library functionality, and is not
** included in release builds. It is intended to be called from within
** an interactive debugger.
**
** When called, this function prints a single line of human readable output
** to stdout describing the locks currently held by the connection. For 
** example:
**
**     (gdb) call print_db_locks(pDb)
**     (shared on dms2) (exclusive on writer) 
*/
void print_db_locks(lsm_db *db){
  int iLock;
  for(iLock=0; iLock<16; iLock++){
    int bOne = 0;
    const char *azLock[] = {0, "shared", "exclusive"};
    const char *azName[] = {
      0, "dms1", "dms2", "writer", "worker", "checkpointer",
      "reader0", "reader1", "reader2", "reader3", "reader4", "reader5"
    };
    int eHave = shmLockType(db, iLock);
    if( azLock[eHave] ){
      printf("%s(%s on %s)", (bOne?" ":""), azLock[eHave], azName[iLock]);
      bOne = 1;
    }
  }
  printf("\n");
}
void print_all_db_locks(lsm_db *db){
  lsm_db *p;
  for(p=db->pDatabase->pConn; p; p=p->pNext){
    printf("%s connection %p ", ((p==db)?"*":""), p);
    print_db_locks(p);
  }
}
#endif

void lsmShmBarrier(lsm_db *db){
  lsmEnvShmBarrier(db->pEnv);
}

int lsm_checkpoint(lsm_db *pDb, int *pnKB){
  int rc;                         /* Return code */
  u32 nWrite = 0;                 /* Number of pages checkpointed */

  /* Attempt the checkpoint. If successful, nWrite is set to the number of
  ** pages written between this and the previous checkpoint.  */
  rc = lsmCheckpointWrite(pDb, 0, &nWrite);

  /* If required, calculate the output variable (KB of data checkpointed). 
  ** Set it to zero if an error occured.  */
  if( pnKB ){
    int nKB = 0;
    if( rc==LSM_OK && nWrite ){
      nKB = (((i64)nWrite * lsmFsPageSize(pDb->pFS)) + 1023) / 1024;
    }
    *pnKB = nKB;
  }

  return rc;
}

/************** End of lsm_shared.c ******************************************/
/************** Begin file lsm_sorted.c **************************************/
/*
** 2011-08-14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** PAGE FORMAT:
**
**   The maximum page size is 65536 bytes.
**
**   Since all records are equal to or larger than 2 bytes in size, and 
**   some space within the page is consumed by the page footer, there must
**   be less than 2^15 records on each page.
**
**   Each page ends with a footer that describes the pages contents. This
**   footer serves as similar purpose to the page header in an SQLite database.
**   A footer is used instead of a header because it makes it easier to
**   populate a new page based on a sorted list of key/value pairs.
**
**   The footer consists of the following values (starting at the end of
**   the page and continuing backwards towards the start). All values are
**   stored as unsigned big-endian integers.
**
**     * Number of records on page (2 bytes).
**     * Flags field (2 bytes).
**     * Left-hand pointer value (8 bytes).
**     * The starting offset of each record (2 bytes per record).
**
**   Records may span pages. Unless it happens to be an exact fit, the part
**   of the final record that starts on page X that does not fit on page X
**   is stored at the start of page (X+1). This means there may be pages where
**   (N==0). And on most pages the first record that starts on the page will
**   not start at byte offset 0. For example:
**
**      aaaaa bbbbb ccc <footer>    cc eeeee fffff g <footer>    gggg....
**
** RECORD FORMAT:
** 
**   The first byte of the record is a flags byte. It is a combination
**   of the following flags (defined in lsmInt.h):
**
**       LSM_START_DELETE
**       LSM_END_DELETE 
**       LSM_POINT_DELETE
**       LSM_INSERT    
**       LSM_SEPARATOR
**       LSM_SYSTEMKEY
**
**   Immediately following the type byte is a pointer to the smallest key 
**   in the next file that is larger than the key in the current record. The 
**   pointer is encoded as a varint. When added to the 32-bit page number 
**   stored in the footer, it is the page number of the page that contains the
**   smallest key in the next sorted file that is larger than this key. 
**
**   Next is the number of bytes in the key, encoded as a varint.
**
**   If the LSM_INSERT flag is set, the number of bytes in the value, as
**   a varint, is next.
**
**   Finally, the blob of data containing the key, and for LSM_INSERT
**   records, the value as well.
*/

#ifndef _LSM_INT_H
#endif

#define LSM_LOG_STRUCTURE 0
#define LSM_LOG_DATA      0

/*
** Macros to help decode record types.
*/
#define rtTopic(eType)       ((eType) & LSM_SYSTEMKEY)
#define rtIsDelete(eType)    (((eType) & 0x0F)==LSM_POINT_DELETE)

#define rtIsSeparator(eType) (((eType) & LSM_SEPARATOR)!=0)
#define rtIsWrite(eType)     (((eType) & LSM_INSERT)!=0)
#define rtIsSystem(eType)    (((eType) & LSM_SYSTEMKEY)!=0)

/*
** The following macros are used to access a page footer.
*/
#define SEGMENT_NRECORD_OFFSET(pgsz)        ((pgsz) - 2)
#define SEGMENT_FLAGS_OFFSET(pgsz)          ((pgsz) - 2 - 2)
#define SEGMENT_POINTER_OFFSET(pgsz)        ((pgsz) - 2 - 2 - 8)
#define SEGMENT_CELLPTR_OFFSET(pgsz, iCell) ((pgsz) - 2 - 2 - 8 - 2 - (iCell)*2)

#define SEGMENT_EOF(pgsz, nEntry) SEGMENT_CELLPTR_OFFSET(pgsz, nEntry)

#define SEGMENT_BTREE_FLAG     0x0001
#define PGFTR_SKIP_NEXT_FLAG   0x0002
#define PGFTR_SKIP_THIS_FLAG   0x0004

typedef struct SegmentPtr SegmentPtr;
typedef struct Blob Blob;

struct Blob {
  lsm_env *pEnv;
  void *pData;
  int nData;
  int nAlloc;
};

/*
** A SegmentPtr object may be used for one of two purposes:
**
**   * To iterate and/or seek within a single Segment (the combination of a 
**     main run and an optional sorted run).
**
**   * To iterate through the separators array of a segment.
*/
struct SegmentPtr {
  Level *pLevel;                /* Level object segment is part of */
  Segment *pSeg;                /* Segment to access */

  /* Current page. See segmentPtrLoadPage(). */
  Page *pPg;                    /* Current page */
  u16 flags;                    /* Copy of page flags field */
  int nCell;                    /* Number of cells on pPg */
  Pgno iPtr;                    /* Base cascade pointer */

  /* Current cell. See segmentPtrLoadCell() */
  int iCell;                    /* Current record within page pPg */
  int eType;                    /* Type of current record */
  Pgno iPgPtr;                  /* Cascade pointer offset */
  void *pKey; int nKey;         /* Key associated with current record */
  void *pVal; int nVal;         /* Current record value (eType==WRITE only) */

  /* Blobs used to allocate buffers for pKey and pVal as required */
  Blob blob1;
  Blob blob2;
};

/*
** Used to iterate through the keys stored in a b-tree hierarchy from start
** to finish. Only First() and Next() operations are required.
**
**   btreeCursorNew()
**   btreeCursorFirst()
**   btreeCursorNext()
**   btreeCursorFree()
**   btreeCursorPosition()
**   btreeCursorRestore()
*/
typedef struct BtreePg BtreePg;
typedef struct BtreeCursor BtreeCursor;
struct BtreePg {
  Page *pPage;
  int iCell;
};
struct BtreeCursor {
  Segment *pSeg;                  /* Iterate through this segments btree */
  FileSystem *pFS;                /* File system to read pages from */
  int nDepth;                     /* Allocated size of aPg[] */
  int iPg;                        /* Current entry in aPg[]. -1 -> EOF. */
  BtreePg *aPg;                   /* Pages from root to current location */

  /* Cache of current entry. pKey==0 for EOF. */
  void *pKey;
  int nKey;
  int eType;
  Pgno iPtr;

  /* Storage for key, if not local */
  Blob blob;
};


/*
** A cursor used for merged searches or iterations through up to one
** Tree structure and any number of sorted files.
**
**   lsmMCursorNew()
**   lsmMCursorSeek()
**   lsmMCursorNext()
**   lsmMCursorPrev()
**   lsmMCursorFirst()
**   lsmMCursorLast()
**   lsmMCursorKey()
**   lsmMCursorValue()
**   lsmMCursorValid()
**
** iFree:
**   This variable is only used by cursors providing input data for a
**   new top-level segment. Such cursors only ever iterate forwards, not
**   backwards.
*/
struct MultiCursor {
  lsm_db *pDb;                    /* Connection that owns this cursor */
  MultiCursor *pNext;             /* Next cursor owned by connection pDb */
  int flags;                      /* Mask of CURSOR_XXX flags */

  int eType;                      /* Cache of current key type */
  Blob key;                       /* Cache of current key (or NULL) */
  Blob val;                       /* Cache of current value */

  /* All the component cursors: */
  TreeCursor *apTreeCsr[2];       /* Up to two tree cursors */
  int iFree;                      /* Next element of free-list (-ve for eof) */
  SegmentPtr *aPtr;               /* Array of segment pointers */
  int nPtr;                       /* Size of array aPtr[] */
  BtreeCursor *pBtCsr;            /* b-tree cursor (db writes only) */

  /* Comparison results */
  int nTree;                      /* Size of aTree[] array */
  int *aTree;                     /* Array of comparison results */

  /* Used by cursors flushing the in-memory tree only */
  void *pSystemVal;               /* Pointer to buffer to free */

  /* Used by worker cursors only */
  Pgno *pPrevMergePtr;
};

/*
** The following constants are used to assign integers to each component
** cursor of a multi-cursor.
*/
#define CURSOR_DATA_TREE0     0   /* Current tree cursor (apTreeCsr[0]) */
#define CURSOR_DATA_TREE1     1   /* The "old" tree, if any (apTreeCsr[1]) */
#define CURSOR_DATA_SYSTEM    2   /* Free-list entries (new-toplevel only) */
#define CURSOR_DATA_SEGMENT   3   /* First segment pointer (aPtr[0]) */

/*
** CURSOR_IGNORE_DELETE
**   If set, this cursor will not visit SORTED_DELETE keys.
**
** CURSOR_FLUSH_FREELIST
**   This cursor is being used to create a new toplevel. It should also 
**   iterate through the contents of the in-memory free block list.
**
** CURSOR_IGNORE_SYSTEM
**   If set, this cursor ignores system keys.
**
** CURSOR_NEXT_OK
**   Set if it is Ok to call lsm_csr_next().
**
** CURSOR_PREV_OK
**   Set if it is Ok to call lsm_csr_prev().
**
** CURSOR_READ_SEPARATORS
**   Set if this cursor should visit the separator keys in segment 
**   aPtr[nPtr-1].
**
** CURSOR_SEEK_EQ
**   Cursor has undergone a successful lsm_csr_seek(LSM_SEEK_EQ) operation.
**   The key and value are stored in MultiCursor.key and MultiCursor.val
**   respectively.
*/
#define CURSOR_IGNORE_DELETE    0x00000001
#define CURSOR_FLUSH_FREELIST   0x00000002
#define CURSOR_IGNORE_SYSTEM    0x00000010
#define CURSOR_NEXT_OK          0x00000020
#define CURSOR_PREV_OK          0x00000040
#define CURSOR_READ_SEPARATORS  0x00000080
#define CURSOR_SEEK_EQ          0x00000100

typedef struct MergeWorker MergeWorker;
typedef struct Hierarchy Hierarchy;

struct Hierarchy {
  Page **apHier;
  int nHier;
};

/*
** aSave:
**   When mergeWorkerNextPage() is called to advance to the next page in
**   the output segment, if the bStore flag for an element of aSave[] is
**   true, it is cleared and the corresponding iPgno value is set to the 
**   page number of the page just completed.
**
**   aSave[0] is used to record the pointer value to be pushed into the
**   b-tree hierarchy. aSave[1] is used to save the page number of the
**   page containing the indirect key most recently written to the b-tree.
**   see mergeWorkerPushHierarchy() for details.
*/
struct MergeWorker {
  lsm_db *pDb;                    /* Database handle */
  Level *pLevel;                  /* Worker snapshot Level being merged */
  MultiCursor *pCsr;              /* Cursor to read new segment contents from */
  int bFlush;                     /* True if this is an in-memory tree flush */
  Hierarchy hier;                 /* B-tree hierarchy under construction */
  Page *pPage;                    /* Current output page */
  int nWork;                      /* Number of calls to mergeWorkerNextPage() */
  Pgno *aGobble;                  /* Gobble point for each input segment */

  Pgno iIndirect;
  struct SavedPgno {
    Pgno iPgno;
    int bStore;
  } aSave[2];
};

#ifdef LSM_DEBUG_EXPENSIVE
static int assertPointersOk(lsm_db *, Segment *, Segment *, int);
static int assertBtreeOk(lsm_db *, Segment *);
static void assertRunInOrder(lsm_db *pDb, Segment *pSeg);
#else
#define assertRunInOrder(x,y)
#define assertBtreeOk(x,y)
#endif


struct FilePage { u8 *aData; int nData; };
static u8 *fsPageData(Page *pPg, int *pnData){
  *pnData = ((struct FilePage *)(pPg))->nData;
  return ((struct FilePage *)(pPg))->aData;
}
/*UNUSED static u8 *fsPageDataPtr(Page *pPg){
  return ((struct FilePage *)(pPg))->aData;
}*/

/*
** Write nVal as a 16-bit unsigned big-endian integer into buffer aOut.
*/
void lsmPutU16(u8 *aOut, u16 nVal){
  aOut[0] = (u8)((nVal>>8) & 0xFF);
  aOut[1] = (u8)(nVal & 0xFF);
}

void lsmPutU32(u8 *aOut, u32 nVal){
  aOut[0] = (u8)((nVal>>24) & 0xFF);
  aOut[1] = (u8)((nVal>>16) & 0xFF);
  aOut[2] = (u8)((nVal>> 8) & 0xFF);
  aOut[3] = (u8)((nVal    ) & 0xFF);
}

int lsmGetU16(u8 *aOut){
  return (aOut[0] << 8) + aOut[1];
}

u32 lsmGetU32(u8 *aOut){
  return ((u32)aOut[0] << 24) 
       + ((u32)aOut[1] << 16) 
       + ((u32)aOut[2] << 8) 
       + ((u32)aOut[3]);
}

u64 lsmGetU64(u8 *aOut){
  return ((u64)aOut[0] << 56) 
       + ((u64)aOut[1] << 48) 
       + ((u64)aOut[2] << 40) 
       + ((u64)aOut[3] << 32) 
       + ((u64)aOut[4] << 24)
       + ((u32)aOut[5] << 16) 
       + ((u32)aOut[6] << 8) 
       + ((u32)aOut[7]);
}

void lsmPutU64(u8 *aOut, u64 nVal){
  aOut[0] = (u8)((nVal>>56) & 0xFF);
  aOut[1] = (u8)((nVal>>48) & 0xFF);
  aOut[2] = (u8)((nVal>>40) & 0xFF);
  aOut[3] = (u8)((nVal>>32) & 0xFF);
  aOut[4] = (u8)((nVal>>24) & 0xFF);
  aOut[5] = (u8)((nVal>>16) & 0xFF);
  aOut[6] = (u8)((nVal>> 8) & 0xFF);
  aOut[7] = (u8)((nVal    ) & 0xFF);
}

static int sortedBlobGrow(lsm_env *pEnv, Blob *pBlob, int nData){
  assert( pBlob->pEnv==pEnv || (pBlob->pEnv==0 && pBlob->pData==0) );
  if( pBlob->nAlloc<nData ){
    pBlob->pData = lsmReallocOrFree(pEnv, pBlob->pData, nData);
    if( !pBlob->pData ) return LSM_NOMEM_BKPT;
    pBlob->nAlloc = nData;
    pBlob->pEnv = pEnv;
  }
  return LSM_OK;
}

static int sortedBlobSet(lsm_env *pEnv, Blob *pBlob, void *pData, int nData){
  if( sortedBlobGrow(pEnv, pBlob, nData) ) return LSM_NOMEM;
  memcpy(pBlob->pData, pData, nData);
  pBlob->nData = nData;
  return LSM_OK;
}

#if 0
static int sortedBlobCopy(Blob *pDest, Blob *pSrc){
  return sortedBlobSet(pDest, pSrc->pData, pSrc->nData);
}
#endif

static void sortedBlobFree(Blob *pBlob){
  assert( pBlob->pEnv || pBlob->pData==0 );
  if( pBlob->pData ) lsmFree(pBlob->pEnv, pBlob->pData);
  memset(pBlob, 0, sizeof(Blob));
}

static int sortedReadData(
  Segment *pSeg,
  Page *pPg,
  int iOff,
  int nByte,
  void **ppData,
  Blob *pBlob
){
  int rc = LSM_OK;
  int iEnd;
  int nData;
  int nCell;
  u8 *aData;

  aData = fsPageData(pPg, &nData);
  nCell = lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]);
  iEnd = SEGMENT_EOF(nData, nCell);
  assert( iEnd>0 && iEnd<nData );

  if( iOff+nByte<=iEnd ){
    *ppData = (void *)&aData[iOff];
  }else{
    int nRem = nByte;
    int i = iOff;
    u8 *aDest;

    /* Make sure the blob is big enough to store the value being loaded. */
    rc = sortedBlobGrow(lsmPageEnv(pPg), pBlob, nByte);
    if( rc!=LSM_OK ) return rc;
    pBlob->nData = nByte;
    aDest = (u8 *)pBlob->pData;
    *ppData = pBlob->pData;

    /* Increment the pointer pages ref-count. */
    lsmFsPageRef(pPg);

    while( rc==LSM_OK ){
      Page *pNext;
      int flags;

      /* Copy data from pPg into the output buffer. */
      int nCopy = LSM_MIN(nRem, iEnd-i);
      if( nCopy>0 ){
        memcpy(&aDest[nByte-nRem], &aData[i], nCopy);
        nRem -= nCopy;
        i += nCopy;
        assert( nRem==0 || i==iEnd );
      }
      assert( nRem>=0 );
      if( nRem==0 ) break;
      i -= iEnd;

      /* Grab the next page in the segment */

      do {
        rc = lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
        if( rc==LSM_OK && pNext==0 ){
          rc = LSM_CORRUPT_BKPT;
        }
        if( rc ) break;
        lsmFsPageRelease(pPg);
        pPg = pNext;
        aData = fsPageData(pPg, &nData);
        flags = lsmGetU16(&aData[SEGMENT_FLAGS_OFFSET(nData)]);
      }while( flags&SEGMENT_BTREE_FLAG );

      iEnd = SEGMENT_EOF(nData, lsmGetU16(&aData[nData-2]));
      assert( iEnd>0 && iEnd<nData );
    }

    lsmFsPageRelease(pPg);
  }

  return rc;
}

static int pageGetNRec(u8 *aData, int nData){
  return (int)lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]);
}

static Pgno pageGetPtr(u8 *aData, int nData){
  return (Pgno)lsmGetU64(&aData[SEGMENT_POINTER_OFFSET(nData)]);
}

static int pageGetFlags(u8 *aData, int nData){
  return (int)lsmGetU16(&aData[SEGMENT_FLAGS_OFFSET(nData)]);
}

static u8 *pageGetCell(u8 *aData, int nData, int iCell){
  return &aData[lsmGetU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, iCell)])];
}

/*
** Return the number of cells on page pPg.
*/
static int pageObjGetNRec(Page *pPg){
  int nData;
  u8 *aData = lsmFsPageData(pPg, &nData);
  return pageGetNRec(aData, nData);
}

/*
** Return the decoded (possibly relative) pointer value stored in cell 
** iCell from page aData/nData.
*/
static Pgno pageGetRecordPtr(u8 *aData, int nData, int iCell){
  Pgno iRet;                      /* Return value */
  u8 *aCell;                      /* Pointer to cell iCell */

  assert( iCell<pageGetNRec(aData, nData) && iCell>=0 );
  aCell = pageGetCell(aData, nData, iCell);
  lsmVarintGet64(&aCell[1], &iRet);
  return iRet;
}

static u8 *pageGetKey(
  Segment *pSeg,                  /* Segment pPg belongs to */
  Page *pPg,                      /* Page to read from */
  int iCell,                      /* Index of cell on page to read */
  int *piTopic,                   /* OUT: Topic associated with this key */
  int *pnKey,                     /* OUT: Size of key in bytes */
  Blob *pBlob                     /* If required, use this for dynamic memory */
){
  u8 *pKey;
  int nDummy;
  int eType;
  u8 *aData;
  int nData;

  aData = fsPageData(pPg, &nData);

  assert( !(pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) );
  assert( iCell<pageGetNRec(aData, nData) );

  pKey = pageGetCell(aData, nData, iCell);
  eType = *pKey++;
  pKey += lsmVarintGet32(pKey, &nDummy);
  pKey += lsmVarintGet32(pKey, pnKey);
  if( rtIsWrite(eType) ){
    pKey += lsmVarintGet32(pKey, &nDummy);
  }
  *piTopic = rtTopic(eType);

  sortedReadData(pSeg, pPg, pKey-aData, *pnKey, (void **)&pKey, pBlob);
  return pKey;
}

static int pageGetKeyCopy(
  lsm_env *pEnv,                  /* Environment handle */
  Segment *pSeg,                  /* Segment pPg belongs to */
  Page *pPg,                      /* Page to read from */
  int iCell,                      /* Index of cell on page to read */
  int *piTopic,                   /* OUT: Topic associated with this key */
  Blob *pBlob                     /* If required, use this for dynamic memory */
){
  int rc = LSM_OK;
  int nKey;
  u8 *aKey;

  aKey = pageGetKey(pSeg, pPg, iCell, piTopic, &nKey, pBlob);
  assert( (void *)aKey!=pBlob->pData || nKey==pBlob->nData );
  if( (void *)aKey!=pBlob->pData ){
    rc = sortedBlobSet(pEnv, pBlob, aKey, nKey);
  }

  return rc;
}

static Pgno pageGetBtreeRef(Page *pPg, int iKey){
  Pgno iRef;
  u8 *aData;
  int nData;
  u8 *aCell;

  aData = fsPageData(pPg, &nData);
  aCell = pageGetCell(aData, nData, iKey);
  assert( aCell[0]==0 );
  aCell++;
  aCell += lsmVarintGet64(aCell, &iRef);
  lsmVarintGet64(aCell, &iRef);
  assert( iRef>0 );
  return iRef;
}

#define GETVARINT64(a, i) (((i)=((u8*)(a))[0])<=240?1:lsmVarintGet64((a), &(i)))
#define GETVARINT32(a, i) (((i)=((u8*)(a))[0])<=240?1:lsmVarintGet32((a), &(i)))

static int pageGetBtreeKey(
  Segment *pSeg,                  /* Segment page pPg belongs to */
  Page *pPg,
  int iKey, 
  Pgno *piPtr, 
  int *piTopic, 
  void **ppKey,
  int *pnKey,
  Blob *pBlob
){
  u8 *aData;
  int nData;
  u8 *aCell;
  int eType;

  aData = fsPageData(pPg, &nData);
  assert( SEGMENT_BTREE_FLAG & pageGetFlags(aData, nData) );
  assert( iKey>=0 && iKey<pageGetNRec(aData, nData) );

  aCell = pageGetCell(aData, nData, iKey);
  eType = *aCell++;
  aCell += GETVARINT64(aCell, *piPtr);

  if( eType==0 ){
    int rc;
    Pgno iRef;                  /* Page number of referenced page */
    Page *pRef;
    aCell += GETVARINT64(aCell, iRef);
    rc = lsmFsDbPageGet(lsmPageFS(pPg), pSeg, iRef, &pRef);
    if( rc!=LSM_OK ) return rc;
    pageGetKeyCopy(lsmPageEnv(pPg), pSeg, pRef, 0, &eType, pBlob);
    lsmFsPageRelease(pRef);
    *ppKey = pBlob->pData;
    *pnKey = pBlob->nData;
  }else{
    aCell += GETVARINT32(aCell, *pnKey);
    *ppKey = aCell;
  }
  if( piTopic ) *piTopic = rtTopic(eType);

  return LSM_OK;
}

static int btreeCursorLoadKey(BtreeCursor *pCsr){
  int rc = LSM_OK;
  if( pCsr->iPg<0 ){
    pCsr->pKey = 0;
    pCsr->nKey = 0;
    pCsr->eType = 0;
  }else{
    Pgno dummy;
    int iPg = pCsr->iPg;
    int iCell = pCsr->aPg[iPg].iCell;
    while( iCell<0 && (--iPg)>=0 ){
      iCell = pCsr->aPg[iPg].iCell-1;
    }
    if( iPg<0 || iCell<0 ) return LSM_CORRUPT_BKPT;

    rc = pageGetBtreeKey(
        pCsr->pSeg,
        pCsr->aPg[iPg].pPage, iCell,
        &dummy, &pCsr->eType, &pCsr->pKey, &pCsr->nKey, &pCsr->blob
    );
    pCsr->eType |= LSM_SEPARATOR;
  }

  return rc;
}

static int btreeCursorPtr(u8 *aData, int nData, int iCell){
  int nCell;

  nCell = pageGetNRec(aData, nData);
  if( iCell>=nCell ){
    return pageGetPtr(aData, nData);
  }
  return pageGetRecordPtr(aData, nData, iCell);
}

static int btreeCursorNext(BtreeCursor *pCsr){
  int rc = LSM_OK;

  BtreePg *pPg = &pCsr->aPg[pCsr->iPg];
  int nCell; 
  u8 *aData;
  int nData;

  assert( pCsr->iPg>=0 );
  assert( pCsr->iPg==pCsr->nDepth-1 );

  aData = fsPageData(pPg->pPage, &nData);
  nCell = pageGetNRec(aData, nData);
  assert( pPg->iCell<=nCell );
  pPg->iCell++;
  if( pPg->iCell==nCell ){
    Pgno iLoad;

    /* Up to parent. */
    lsmFsPageRelease(pPg->pPage);
    pPg->pPage = 0;
    pCsr->iPg--;
    while( pCsr->iPg>=0 ){
      pPg = &pCsr->aPg[pCsr->iPg];
      aData = fsPageData(pPg->pPage, &nData);
      if( pPg->iCell<pageGetNRec(aData, nData) ) break;
      lsmFsPageRelease(pPg->pPage);
      pCsr->iPg--;
    }

    /* Read the key */
    rc = btreeCursorLoadKey(pCsr);

    /* Unless the cursor is at EOF, descend to cell -1 (yes, negative one) of 
    ** the left-most most descendent. */
    if( pCsr->iPg>=0 ){
      pCsr->aPg[pCsr->iPg].iCell++;

      iLoad = btreeCursorPtr(aData, nData, pPg->iCell);
      do {
        Page *pLoad;
        pCsr->iPg++;
        rc = lsmFsDbPageGet(pCsr->pFS, pCsr->pSeg, iLoad, &pLoad);
        pCsr->aPg[pCsr->iPg].pPage = pLoad;
        pCsr->aPg[pCsr->iPg].iCell = 0;
        if( rc==LSM_OK ){
          if( pCsr->iPg==(pCsr->nDepth-1) ) break;
          aData = fsPageData(pLoad, &nData);
          iLoad = btreeCursorPtr(aData, nData, 0);
        }
      }while( rc==LSM_OK && pCsr->iPg<(pCsr->nDepth-1) );
      pCsr->aPg[pCsr->iPg].iCell = -1;
    }

  }else{
    rc = btreeCursorLoadKey(pCsr);
  }

  if( rc==LSM_OK && pCsr->iPg>=0 ){
    aData = fsPageData(pCsr->aPg[pCsr->iPg].pPage, &nData);
    pCsr->iPtr = btreeCursorPtr(aData, nData, pCsr->aPg[pCsr->iPg].iCell+1);
  }

  return rc;
}

static void btreeCursorFree(BtreeCursor *pCsr){
  if( pCsr ){
    int i;
    lsm_env *pEnv = lsmFsEnv(pCsr->pFS);
    for(i=0; i<=pCsr->iPg; i++){
      lsmFsPageRelease(pCsr->aPg[i].pPage);
    }
    sortedBlobFree(&pCsr->blob);
    lsmFree(pEnv, pCsr->aPg);
    lsmFree(pEnv, pCsr);
  }
}

static int btreeCursorFirst(BtreeCursor *pCsr){
  int rc;

  Page *pPg = 0;
  FileSystem *pFS = pCsr->pFS;
  int iPg = pCsr->pSeg->iRoot;

  do {
    rc = lsmFsDbPageGet(pFS, pCsr->pSeg, iPg, &pPg);
    assert( (rc==LSM_OK)==(pPg!=0) );
    if( rc==LSM_OK ){
      u8 *aData;
      int nData;
      int flags;

      aData = fsPageData(pPg, &nData);
      flags = pageGetFlags(aData, nData);
      if( (flags & SEGMENT_BTREE_FLAG)==0 ) break;

      if( (pCsr->nDepth % 8)==0 ){
        int nNew = pCsr->nDepth + 8;
        pCsr->aPg = (BtreePg *)lsmReallocOrFreeRc(
            lsmFsEnv(pFS), pCsr->aPg, sizeof(BtreePg) * nNew, &rc
        );
        if( rc==LSM_OK ){
          memset(&pCsr->aPg[pCsr->nDepth], 0, sizeof(BtreePg) * 8);
        }
      }

      if( rc==LSM_OK ){
        assert( pCsr->aPg[pCsr->nDepth].iCell==0 );
        pCsr->aPg[pCsr->nDepth].pPage = pPg;
        pCsr->nDepth++;
        iPg = pageGetRecordPtr(aData, nData, 0);
      }
    }
  }while( rc==LSM_OK );
  lsmFsPageRelease(pPg);
  pCsr->iPg = pCsr->nDepth-1;

  if( rc==LSM_OK && pCsr->nDepth ){
    pCsr->aPg[pCsr->iPg].iCell = -1;
    rc = btreeCursorNext(pCsr);
  }

  return rc;
}

static void btreeCursorPosition(BtreeCursor *pCsr, MergeInput *p){
  if( pCsr->iPg>=0 ){
    p->iPg = lsmFsPageNumber(pCsr->aPg[pCsr->iPg].pPage);
    p->iCell = ((pCsr->aPg[pCsr->iPg].iCell + 1) << 8) + pCsr->nDepth;
  }else{
    p->iPg = 0;
    p->iCell = 0;
  }
}

static void btreeCursorSplitkey(BtreeCursor *pCsr, MergeInput *p){
  int iCell = pCsr->aPg[pCsr->iPg].iCell;
  if( iCell>=0 ){
    p->iCell = iCell;
    p->iPg = lsmFsPageNumber(pCsr->aPg[pCsr->iPg].pPage);
  }else{
    int i;
    for(i=pCsr->iPg-1; i>=0; i--){
      if( pCsr->aPg[i].iCell>0 ) break;
    }
    assert( i>=0 );
    p->iCell = pCsr->aPg[i].iCell-1;
    p->iPg = lsmFsPageNumber(pCsr->aPg[i].pPage);
  }
}

static int sortedKeyCompare(
  int (*xCmp)(void *, int, void *, int),
  int iLhsTopic, void *pLhsKey, int nLhsKey,
  int iRhsTopic, void *pRhsKey, int nRhsKey
){
  int res = iLhsTopic - iRhsTopic;
  if( res==0 ){
    res = xCmp(pLhsKey, nLhsKey, pRhsKey, nRhsKey);
  }
  return res;
}

static int btreeCursorRestore(
  BtreeCursor *pCsr, 
  int (*xCmp)(void *, int, void *, int),
  MergeInput *p
){
  int rc = LSM_OK;

  if( p->iPg ){
    lsm_env *pEnv = lsmFsEnv(pCsr->pFS);
    int iCell;                    /* Current cell number on leaf page */
    Pgno iLeaf;                   /* Page number of current leaf page */
    int nDepth;                   /* Depth of b-tree structure */
    Segment *pSeg = pCsr->pSeg;

    /* Decode the MergeInput structure */
    iLeaf = p->iPg;
    nDepth = (p->iCell & 0x00FF);
    iCell = (p->iCell >> 8) - 1;

    /* Allocate the BtreeCursor.aPg[] array */
    assert( pCsr->aPg==0 );
    pCsr->aPg = (BtreePg *)lsmMallocZeroRc(pEnv, sizeof(BtreePg) * nDepth, &rc);

    /* Populate the last entry of the aPg[] array */
    if( rc==LSM_OK ){
      Page **pp = &pCsr->aPg[nDepth-1].pPage;
      pCsr->iPg = nDepth-1;
      pCsr->nDepth = nDepth;
      pCsr->aPg[pCsr->iPg].iCell = iCell;
      rc = lsmFsDbPageGet(pCsr->pFS, pSeg, iLeaf, pp);
    }

    /* Populate any other aPg[] array entries */
    if( rc==LSM_OK && nDepth>1 ){
      Blob blob = {0,0,0};
      void *pSeek;
      int nSeek;
      int iTopicSeek;
      int iPg = 0;
      int iLoad = pSeg->iRoot;
      Page *pPg = pCsr->aPg[nDepth-1].pPage;
 
      if( pageObjGetNRec(pPg)==0 ){
        /* This can happen when pPg is the right-most leaf in the b-tree.
        ** In this case, set the iTopicSeek/pSeek/nSeek key to a value
        ** greater than any real key.  */
        assert( iCell==-1 );
        iTopicSeek = 1000;
        pSeek = 0;
        nSeek = 0;
      }else{
        Pgno dummy;
        rc = pageGetBtreeKey(pSeg, pPg,
            0, &dummy, &iTopicSeek, &pSeek, &nSeek, &pCsr->blob
        );
      }

      do {
        Page *pPg;
        rc = lsmFsDbPageGet(pCsr->pFS, pSeg, iLoad, &pPg);
        assert( rc==LSM_OK || pPg==0 );
        if( rc==LSM_OK ){
          u8 *aData;                  /* Buffer containing page data */
          int nData;                  /* Size of aData[] in bytes */
          int iMin;
          int iMax;
          int iCell;

          aData = fsPageData(pPg, &nData);
          assert( (pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) );

          iLoad = pageGetPtr(aData, nData);
          iCell = pageGetNRec(aData, nData); 
          iMax = iCell-1;
          iMin = 0;

          while( iMax>=iMin ){
            int iTry = (iMin+iMax)/2;
            void *pKey; int nKey;         /* Key for cell iTry */
            int iTopic;                   /* Topic for key pKeyT/nKeyT */
            Pgno iPtr;                    /* Pointer for cell iTry */
            int res;                      /* (pSeek - pKeyT) */

            rc = pageGetBtreeKey(
                pSeg, pPg, iTry, &iPtr, &iTopic, &pKey, &nKey, &blob
            );
            if( rc!=LSM_OK ) break;

            res = sortedKeyCompare(
                xCmp, iTopicSeek, pSeek, nSeek, iTopic, pKey, nKey
            );
            assert( res!=0 );

            if( res<0 ){
              iLoad = iPtr;
              iCell = iTry;
              iMax = iTry-1;
            }else{
              iMin = iTry+1;
            }
          }

          pCsr->aPg[iPg].pPage = pPg;
          pCsr->aPg[iPg].iCell = iCell;
          iPg++;
          assert( iPg!=nDepth-1 
               || lsmFsRedirectPage(pCsr->pFS, pSeg->pRedirect, iLoad)==iLeaf
          );
        }
      }while( rc==LSM_OK && iPg<(nDepth-1) );
      sortedBlobFree(&blob);
    }

    /* Load the current key and pointer */
    if( rc==LSM_OK ){
      BtreePg *pBtreePg;
      u8 *aData;
      int nData;

      pBtreePg = &pCsr->aPg[pCsr->iPg];
      aData = fsPageData(pBtreePg->pPage, &nData);
      pCsr->iPtr = btreeCursorPtr(aData, nData, pBtreePg->iCell+1);
      if( pBtreePg->iCell<0 ){
        Pgno dummy;
        int i;
        for(i=pCsr->iPg-1; i>=0; i--){
          if( pCsr->aPg[i].iCell>0 ) break;
        }
        assert( i>=0 );
        rc = pageGetBtreeKey(pSeg,
            pCsr->aPg[i].pPage, pCsr->aPg[i].iCell-1,
            &dummy, &pCsr->eType, &pCsr->pKey, &pCsr->nKey, &pCsr->blob
        );
        pCsr->eType |= LSM_SEPARATOR;

      }else{
        rc = btreeCursorLoadKey(pCsr);
      }
    }
  }
  return rc;
}

static int btreeCursorNew(
  lsm_db *pDb,
  Segment *pSeg,
  BtreeCursor **ppCsr
){
  int rc = LSM_OK;
  BtreeCursor *pCsr;
  
  assert( pSeg->iRoot );
  pCsr = lsmMallocZeroRc(pDb->pEnv, sizeof(BtreeCursor), &rc);
  if( pCsr ){
    pCsr->pFS = pDb->pFS;
    pCsr->pSeg = pSeg;
    pCsr->iPg = -1;
  }

  *ppCsr = pCsr;
  return rc;
}

static void segmentPtrSetPage(SegmentPtr *pPtr, Page *pNext){
  lsmFsPageRelease(pPtr->pPg);
  if( pNext ){
    int nData;
    u8 *aData = fsPageData(pNext, &nData);
    pPtr->nCell = pageGetNRec(aData, nData);
    pPtr->flags = pageGetFlags(aData, nData);
    pPtr->iPtr = pageGetPtr(aData, nData);
  }
  pPtr->pPg = pNext;
}

/*
** Load a new page into the SegmentPtr object pPtr.
*/
static int segmentPtrLoadPage(
  FileSystem *pFS,
  SegmentPtr *pPtr,              /* Load page into this SegmentPtr object */
  int iNew                       /* Page number of new page */
){
  Page *pPg = 0;                 /* The new page */
  int rc;                        /* Return Code */

  rc = lsmFsDbPageGet(pFS, pPtr->pSeg, iNew, &pPg);
  assert( rc==LSM_OK || pPg==0 );
  segmentPtrSetPage(pPtr, pPg);

  return rc;
}

static int segmentPtrReadData(
  SegmentPtr *pPtr,
  int iOff,
  int nByte,
  void **ppData,
  Blob *pBlob
){
  return sortedReadData(pPtr->pSeg, pPtr->pPg, iOff, nByte, ppData, pBlob);
}

static int segmentPtrNextPage(
  SegmentPtr *pPtr,              /* Load page into this SegmentPtr object */
  int eDir                       /* +1 for next(), -1 for prev() */
){
  Page *pNext;                   /* New page to load */
  int rc;                        /* Return code */

  assert( eDir==1 || eDir==-1 );
  assert( pPtr->pPg );
  assert( pPtr->pSeg || eDir>0 );

  rc = lsmFsDbPageNext(pPtr->pSeg, pPtr->pPg, eDir, &pNext);
  assert( rc==LSM_OK || pNext==0 );
  segmentPtrSetPage(pPtr, pNext);
  return rc;
}

static int segmentPtrLoadCell(
  SegmentPtr *pPtr,              /* Load page into this SegmentPtr object */
  int iNew                       /* Cell number of new cell */
){
  int rc = LSM_OK;
  if( pPtr->pPg ){
    u8 *aData;                    /* Pointer to page data buffer */
    int iOff;                     /* Offset in aData[] to read from */
    int nPgsz;                    /* Size of page (aData[]) in bytes */

    assert( iNew<pPtr->nCell );
    pPtr->iCell = iNew;
    aData = fsPageData(pPtr->pPg, &nPgsz);
    iOff = lsmGetU16(&aData[SEGMENT_CELLPTR_OFFSET(nPgsz, pPtr->iCell)]);
    pPtr->eType = aData[iOff];
    iOff++;
    iOff += GETVARINT64(&aData[iOff], pPtr->iPgPtr);
    iOff += GETVARINT32(&aData[iOff], pPtr->nKey);
    if( rtIsWrite(pPtr->eType) ){
      iOff += GETVARINT32(&aData[iOff], pPtr->nVal);
    }
    assert( pPtr->nKey>=0 );

    rc = segmentPtrReadData(
        pPtr, iOff, pPtr->nKey, &pPtr->pKey, &pPtr->blob1
    );
    if( rc==LSM_OK && rtIsWrite(pPtr->eType) ){
      rc = segmentPtrReadData(
          pPtr, iOff+pPtr->nKey, pPtr->nVal, &pPtr->pVal, &pPtr->blob2
      );
    }else{
      pPtr->nVal = 0;
      pPtr->pVal = 0;
    }
  }

  return rc;
}


static Segment *sortedSplitkeySegment(Level *pLevel){
  Merge *pMerge = pLevel->pMerge;
  MergeInput *p = &pMerge->splitkey;
  Segment *pSeg;
  int i;

  for(i=0; i<pMerge->nInput; i++){
    if( p->iPg==pMerge->aInput[i].iPg ) break;
  }
  if( pMerge->nInput==(pLevel->nRight+1) && i>=(pMerge->nInput-1) ){
    pSeg = &pLevel->pNext->lhs;
  }else{
    pSeg = &pLevel->aRhs[i];
  }

  return pSeg;
}

static void sortedSplitkey(lsm_db *pDb, Level *pLevel, int *pRc){
  Segment *pSeg;
  Page *pPg = 0;
  lsm_env *pEnv = pDb->pEnv;      /* Environment handle */
  int rc = *pRc;
  Merge *pMerge = pLevel->pMerge;

  pSeg = sortedSplitkeySegment(pLevel);
  if( rc==LSM_OK ){
    rc = lsmFsDbPageGet(pDb->pFS, pSeg, pMerge->splitkey.iPg, &pPg);
  }
  if( rc==LSM_OK ){
    int iTopic;
    Blob blob = {0, 0, 0, 0};
    u8 *aData;
    int nData;
  
    aData = lsmFsPageData(pPg, &nData);
    if( pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG ){
      void *pKey;
      int nKey;
      Pgno dummy;
      rc = pageGetBtreeKey(pSeg,
          pPg, pMerge->splitkey.iCell, &dummy, &iTopic, &pKey, &nKey, &blob
      );
      if( rc==LSM_OK && blob.pData!=pKey ){
        rc = sortedBlobSet(pEnv, &blob, pKey, nKey);
      }
    }else{
      rc = pageGetKeyCopy(
          pEnv, pSeg, pPg, pMerge->splitkey.iCell, &iTopic, &blob
      );
    }

    pLevel->iSplitTopic = iTopic;
    pLevel->pSplitKey = blob.pData;
    pLevel->nSplitKey = blob.nData;
    lsmFsPageRelease(pPg);
  }

  *pRc = rc;
}

static void segmentPtrReset(SegmentPtr *pPtr){
  lsmFsPageRelease(pPtr->pPg);
  pPtr->pPg = 0;
  pPtr->nCell = 0;
  pPtr->pKey = 0;
  pPtr->nKey = 0;
  pPtr->pVal = 0;
  pPtr->nVal = 0;
  pPtr->eType = 0;
  pPtr->iCell = 0;
  sortedBlobFree(&pPtr->blob1);
  sortedBlobFree(&pPtr->blob2);
}

static int segmentPtrIgnoreSeparators(MultiCursor *pCsr, SegmentPtr *pPtr){
  return (pCsr->flags & CURSOR_READ_SEPARATORS)==0
      || (pPtr!=&pCsr->aPtr[pCsr->nPtr-1]);
}

static int segmentPtrAdvance(
  MultiCursor *pCsr, 
  SegmentPtr *pPtr,
  int bReverse
){
  int eDir = (bReverse ? -1 : 1);
  Level *pLvl = pPtr->pLevel;
  do {
    int rc;
    int iCell;                    /* Number of new cell in page */
    int svFlags = 0;              /* SegmentPtr.eType before advance */

    iCell = pPtr->iCell + eDir;
    assert( pPtr->pPg );
    assert( iCell<=pPtr->nCell && iCell>=-1 );

    if( bReverse && pPtr->pSeg!=&pPtr->pLevel->lhs ){
      svFlags = pPtr->eType;
      assert( svFlags );
    }

    if( iCell>=pPtr->nCell || iCell<0 ){
      do {
        rc = segmentPtrNextPage(pPtr, eDir); 
      }while( rc==LSM_OK 
           && pPtr->pPg 
           && (pPtr->nCell==0 || (pPtr->flags & SEGMENT_BTREE_FLAG) ) 
      );
      if( rc!=LSM_OK ) return rc;
      iCell = bReverse ? (pPtr->nCell-1) : 0;
    }
    rc = segmentPtrLoadCell(pPtr, iCell);
    if( rc!=LSM_OK ) return rc;

    if( svFlags && pPtr->pPg ){
      int res = sortedKeyCompare(pCsr->pDb->xCmp,
          rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey,
          pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
      );
      if( res<0 ) segmentPtrReset(pPtr);
    }

    if( pPtr->pPg==0 && (svFlags & LSM_END_DELETE) ){
      Segment *pSeg = pPtr->pSeg;
      rc = lsmFsDbPageGet(pCsr->pDb->pFS, pSeg, pSeg->iFirst, &pPtr->pPg);
      if( rc!=LSM_OK ) return rc;
      pPtr->eType = LSM_START_DELETE | LSM_POINT_DELETE;
      pPtr->eType |= (pLvl->iSplitTopic ? LSM_SYSTEMKEY : 0);
      pPtr->pKey = pLvl->pSplitKey;
      pPtr->nKey = pLvl->nSplitKey;
    }

  }while( pCsr 
       && pPtr->pPg 
       && segmentPtrIgnoreSeparators(pCsr, pPtr)
       && rtIsSeparator(pPtr->eType)
  );

  return LSM_OK;
}

static void segmentPtrEndPage(
  FileSystem *pFS, 
  SegmentPtr *pPtr, 
  int bLast, 
  int *pRc
){
  if( *pRc==LSM_OK ){
    Segment *pSeg = pPtr->pSeg;
    Page *pNew = 0;
    if( bLast ){
      *pRc = lsmFsDbPageLast(pFS, pSeg, &pNew);
    }else{
      *pRc = lsmFsDbPageGet(pFS, pSeg, pSeg->iFirst, &pNew);
    }
    segmentPtrSetPage(pPtr, pNew);
  }
}


/*
** Try to move the segment pointer passed as the second argument so that it
** points at either the first (bLast==0) or last (bLast==1) cell in the valid
** region of the segment defined by pPtr->iFirst and pPtr->iLast.
**
** Return LSM_OK if successful or an lsm error code if something goes
** wrong (IO error, OOM etc.).
*/
static int segmentPtrEnd(MultiCursor *pCsr, SegmentPtr *pPtr, int bLast){
  Level *pLvl = pPtr->pLevel;
  int rc = LSM_OK;
  FileSystem *pFS = pCsr->pDb->pFS;
  int bIgnore;

  segmentPtrEndPage(pFS, pPtr, bLast, &rc);
  while( rc==LSM_OK && pPtr->pPg 
      && (pPtr->nCell==0 || (pPtr->flags & SEGMENT_BTREE_FLAG))
  ){
    rc = segmentPtrNextPage(pPtr, (bLast ? -1 : 1));
  }

  if( rc==LSM_OK && pPtr->pPg ){
    rc = segmentPtrLoadCell(pPtr, bLast ? (pPtr->nCell-1) : 0);
    if( rc==LSM_OK && bLast && pPtr->pSeg!=&pLvl->lhs ){
      int res = sortedKeyCompare(pCsr->pDb->xCmp,
          rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey,
          pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
      );
      if( res<0 ) segmentPtrReset(pPtr);
    }
  }
  
  bIgnore = segmentPtrIgnoreSeparators(pCsr, pPtr);
  if( rc==LSM_OK && pPtr->pPg && bIgnore && rtIsSeparator(pPtr->eType) ){
    rc = segmentPtrAdvance(pCsr, pPtr, bLast);
  }

#if 0
  if( bLast && rc==LSM_OK && pPtr->pPg
   && pPtr->pSeg==&pLvl->lhs 
   && pLvl->nRight && (pPtr->eType & LSM_START_DELETE)
  ){
    pPtr->iCell++;
    pPtr->eType = LSM_END_DELETE | (pLvl->iSplitTopic);
    pPtr->pKey = pLvl->pSplitKey;
    pPtr->nKey = pLvl->nSplitKey;
    pPtr->pVal = 0;
    pPtr->nVal = 0;
  }
#endif

  return rc;
}

static void segmentPtrKey(SegmentPtr *pPtr, void **ppKey, int *pnKey){
  assert( pPtr->pPg );
  *ppKey = pPtr->pKey;
  *pnKey = pPtr->nKey;
}

#ifdef LSM_DEBUG

static char *keyToString(lsm_env *pEnv, void *pKey, int nKey){
  int i;
  u8 *aKey = (u8 *)pKey;
  char *zRet = (char *)lsmMalloc(pEnv, nKey+1);

  for(i=0; i<nKey; i++){
    zRet[i] = (char)(isalnum(aKey[i]) ? aKey[i] : '.');
  }
  zRet[nKey] = '\0';
  return zRet;
}

/*
** Check that the page that pPtr currently has loaded is the correct page
** to search for key (pKey/nKey). If it is, return 1. Otherwise, an assert
** fails and this function does not return.
*/
static int assertKeyLocation(
  MultiCursor *pCsr, 
  SegmentPtr *pPtr, 
  void *pKey, int nKey
){
  lsm_env *pEnv = lsmFsEnv(pCsr->pDb->pFS);
  Blob blob = {0, 0, 0};
  int eDir;
  int iTopic = 0;                 /* TODO: Fix me */

  for(eDir=-1; eDir<=1; eDir+=2){
    Page *pTest = pPtr->pPg;

    lsmFsPageRef(pTest);
    while( pTest ){
      Segment *pSeg = pPtr->pSeg;
      Page *pNext;

      int rc = lsmFsDbPageNext(pSeg, pTest, eDir, &pNext);
      lsmFsPageRelease(pTest);
      if( rc ) return 1;
      pTest = pNext;

      if( pTest ){
        int nData;
        u8 *aData = fsPageData(pTest, &nData);
        int nCell = pageGetNRec(aData, nData);
        int flags = pageGetFlags(aData, nData);
        if( nCell && 0==(flags&SEGMENT_BTREE_FLAG) ){
          int nPgKey;
          int iPgTopic;
          u8 *pPgKey;
          int res;
          int iCell;

          iCell = ((eDir < 0) ? (nCell-1) : 0);
          pPgKey = pageGetKey(pSeg, pTest, iCell, &iPgTopic, &nPgKey, &blob);
          res = iTopic - iPgTopic;
          if( res==0 ) res = pCsr->pDb->xCmp(pKey, nKey, pPgKey, nPgKey);
          if( (eDir==1 && res>0) || (eDir==-1 && res<0) ){
            /* Taking this branch means something has gone wrong. */
            char *zMsg = lsmMallocPrintf(pEnv, "Key \"%s\" is not on page %d", 
                keyToString(pEnv, pKey, nKey), lsmFsPageNumber(pPtr->pPg)
            );
            fprintf(stderr, "%s\n", zMsg);
            assert( !"assertKeyLocation() failed" );
          }
          lsmFsPageRelease(pTest);
          pTest = 0;
        }
      }
    }
  }

  sortedBlobFree(&blob);
  return 1;
}
#endif

#ifndef NDEBUG
static int assertSeekResult(
  MultiCursor *pCsr,
  SegmentPtr *pPtr,
  int iTopic,
  void *pKey,
  int nKey,
  int eSeek
){
  if( pPtr->pPg ){
    int res;
    res = sortedKeyCompare(pCsr->pDb->xCmp, iTopic, pKey, nKey,
        rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey
    );

    if( eSeek==LSM_SEEK_EQ ) return (res==0);
    if( eSeek==LSM_SEEK_LE ) return (res>=0);
    if( eSeek==LSM_SEEK_GE ) return (res<=0);
  }

  return 1;
}
#endif

static int segmentPtrSearchOversized(
  MultiCursor *pCsr,              /* Cursor context */
  SegmentPtr *pPtr,               /* Pointer to seek */
  int iTopic,                     /* Topic of key to search for */
  void *pKey, int nKey            /* Key to seek to */
){
  int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
  int rc = LSM_OK;

  /* If the OVERSIZED flag is set, then there is no pointer in the
  ** upper level to the next page in the segment that contains at least
  ** one key. So compare the largest key on the current page with the
  ** key being sought (pKey/nKey). If (pKey/nKey) is larger, advance
  ** to the next page in the segment that contains at least one key. 
  */
  while( rc==LSM_OK && (pPtr->flags & PGFTR_SKIP_NEXT_FLAG) ){
    u8 *pLastKey;
    int nLastKey;
    int iLastTopic;
    int res;                      /* Result of comparison */
    Page *pNext;

    /* Load the last key on the current page. */
    pLastKey = pageGetKey(pPtr->pSeg,
        pPtr->pPg, pPtr->nCell-1, &iLastTopic, &nLastKey, &pPtr->blob1
    );

    /* If the loaded key is >= than (pKey/nKey), break out of the loop.
    ** If (pKey/nKey) is present in this array, it must be on the current 
    ** page.  */
    res = sortedKeyCompare(
        xCmp, iLastTopic, pLastKey, nLastKey, iTopic, pKey, nKey
    );
    if( res>=0 ) break;

    /* Advance to the next page that contains at least one key. */
    pNext = pPtr->pPg;
    lsmFsPageRef(pNext);
    while( 1 ){
      Page *pLoad;
      u8 *aData; int nData;

      rc = lsmFsDbPageNext(pPtr->pSeg, pNext, 1, &pLoad);
      lsmFsPageRelease(pNext);
      pNext = pLoad;
      if( pNext==0 ) break;

      assert( rc==LSM_OK );
      aData = lsmFsPageData(pNext, &nData);
      if( (pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG)==0
       && pageGetNRec(aData, nData)>0
      ){
        break;
      }
    }
    if( pNext==0 ) break;
    segmentPtrSetPage(pPtr, pNext);

    /* This should probably be an LSM_CORRUPT error. */
    assert( rc!=LSM_OK || (pPtr->flags & PGFTR_SKIP_THIS_FLAG) );
  }

  return rc;
}

static int ptrFwdPointer(
  Page *pPage,
  int iCell,
  Segment *pSeg,
  Pgno *piPtr,
  int *pbFound
){
  Page *pPg = pPage;
  int iFirst = iCell;
  int rc = LSM_OK;

  do {
    Page *pNext = 0;
    u8 *aData;
    int nData;

    aData = lsmFsPageData(pPg, &nData);
    if( (pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG)==0 ){
      int i;
      int nCell = pageGetNRec(aData, nData);
      for(i=iFirst; i<nCell; i++){
        u8 eType = *pageGetCell(aData, nData, i);
        if( (eType & LSM_START_DELETE)==0 ){
          *pbFound = 1;
          *piPtr = pageGetRecordPtr(aData, nData, i) + pageGetPtr(aData, nData);
          lsmFsPageRelease(pPg);
          return LSM_OK;
        }
      }
    }

    rc = lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
    lsmFsPageRelease(pPg);
    pPg = pNext;
    iFirst = 0;
  }while( pPg && rc==LSM_OK );
  lsmFsPageRelease(pPg);

  *pbFound = 0;
  return rc;
}

static int sortedRhsFirst(MultiCursor *pCsr, Level *pLvl, SegmentPtr *pPtr){
  int rc;
  rc = segmentPtrEnd(pCsr, pPtr, 0);
  while( pPtr->pPg && rc==LSM_OK ){
    int res = sortedKeyCompare(pCsr->pDb->xCmp,
        pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey,
        rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey
    );
    if( res<=0 ) break;
    rc = segmentPtrAdvance(pCsr, pPtr, 0);
  }
  return rc;
}


/*
** This function is called as part of a SEEK_GE op on a multi-cursor if the 
** FC pointer read from segment *pPtr comes from an entry with the 
** LSM_START_DELETE flag set. In this case the pointer value cannot be 
** trusted. Instead, the pointer that should be followed is that associated
** with the next entry in *pPtr that does not have LSM_START_DELETE set.
**
** Why the pointers can't be trusted:
**
**
**
** TODO: This is a stop-gap solution:
** 
**   At the moment, this function is called from within segmentPtrSeek(), 
**   as part of the initial lsmMCursorSeek() call. However, consider a 
**   database where the following has occurred:
**
**      1. A range delete removes keys 1..9999 using a range delete.
**      2. Keys 1 through 9999 are reinserted.
**      3. The levels containing the ops in 1. and 2. above are merged. Call
**         this level N. Level N contains FC pointers to level N+1.
**
**   Then, if the user attempts to query for (key>=2 LIMIT 10), the 
**   lsmMCursorSeek() call will iterate through 9998 entries searching for a 
**   pointer down to the level N+1 that is never actually used. It would be
**   much better if the multi-cursor could do this lazily - only seek to the
**   level (N+1) page after the user has moved the cursor on level N passed
**   the big range-delete.
*/
static int segmentPtrFwdPointer(
  MultiCursor *pCsr,              /* Multi-cursor pPtr belongs to */
  SegmentPtr *pPtr,               /* Segment-pointer to extract FC ptr from */
  Pgno *piPtr                     /* OUT: FC pointer value */
){
  Level *pLvl = pPtr->pLevel;
  Level *pNext = pLvl->pNext;
  Page *pPg = pPtr->pPg;
  int rc;
  int bFound;
  Pgno iOut = 0;

  if( pPtr->pSeg==&pLvl->lhs || pPtr->pSeg==&pLvl->aRhs[pLvl->nRight-1] ){
    if( pNext==0 
        || (pNext->nRight==0 && pNext->lhs.iRoot)
        || (pNext->nRight!=0 && pNext->aRhs[0].iRoot)
      ){
      /* Do nothing. The pointer will not be used anyway. */
      return LSM_OK;
    }
  }else{
    if( pPtr[1].pSeg->iRoot ){
      return LSM_OK;
    }
  }

  /* Search for a pointer within the current segment. */
  lsmFsPageRef(pPg);
  rc = ptrFwdPointer(pPg, pPtr->iCell, pPtr->pSeg, &iOut, &bFound);

  if( rc==LSM_OK && bFound==0 ){
    /* This case happens when pPtr points to the left-hand-side of a segment
    ** currently undergoing an incremental merge. In this case, jump to the
    ** oldest segment in the right-hand-side of the same level and continue
    ** searching. But - do not consider any keys smaller than the levels
    ** split-key. */
    SegmentPtr ptr;

    if( pPtr->pLevel->nRight==0 || pPtr->pSeg!=&pPtr->pLevel->lhs ){
      return LSM_CORRUPT_BKPT;
    }

    memset(&ptr, 0, sizeof(SegmentPtr));
    ptr.pLevel = pPtr->pLevel;
    ptr.pSeg = &ptr.pLevel->aRhs[ptr.pLevel->nRight-1];
    rc = sortedRhsFirst(pCsr, ptr.pLevel, &ptr);
    if( rc==LSM_OK ){
      rc = ptrFwdPointer(ptr.pPg, ptr.iCell, ptr.pSeg, &iOut, &bFound);
      ptr.pPg = 0;
    }
    segmentPtrReset(&ptr);
  }

  *piPtr = iOut;
  return rc;
}

static int segmentPtrSeek(
  MultiCursor *pCsr,              /* Cursor context */
  SegmentPtr *pPtr,               /* Pointer to seek */
  int iTopic,                     /* Key topic to seek to */
  void *pKey, int nKey,           /* Key to seek to */
  int eSeek,                      /* Search bias - see above */
  int *piPtr,                     /* OUT: FC pointer */
  int *pbStop
){
  int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
  int res;                        /* Result of comparison operation */
  int rc = LSM_OK;
  int iMin;
  int iMax;
  Pgno iPtrOut = 0;

  /* If the current page contains an oversized entry, then there are no
  ** pointers to one or more of the subsequent pages in the sorted run.
  ** The following call ensures that the segment-ptr points to the correct 
  ** page in this case.  */
  rc = segmentPtrSearchOversized(pCsr, pPtr, iTopic, pKey, nKey);
  iPtrOut = pPtr->iPtr;

  /* Assert that this page is the right page of this segment for the key
  ** that we are searching for. Do this by loading page (iPg-1) and testing
  ** that pKey/nKey is greater than all keys on that page, and then by 
  ** loading (iPg+1) and testing that pKey/nKey is smaller than all
  ** the keys it houses.  
  **
  ** TODO: With range-deletes in the tree, the test described above may fail.
  */
#if 0
  assert( assertKeyLocation(pCsr, pPtr, pKey, nKey) );
#endif

  assert( pPtr->nCell>0 
       || pPtr->pSeg->nSize==1 
       || lsmFsDbPageIsLast(pPtr->pSeg, pPtr->pPg)
  );
  if( pPtr->nCell==0 ){
    segmentPtrReset(pPtr);
  }else{
    iMin = 0;
    iMax = pPtr->nCell-1;

    while( 1 ){
      int iTry = (iMin+iMax)/2;
      void *pKeyT; int nKeyT;       /* Key for cell iTry */
      int iTopicT;

      assert( iTry<iMax || iMin==iMax );

      rc = segmentPtrLoadCell(pPtr, iTry);
      if( rc!=LSM_OK ) break;

      segmentPtrKey(pPtr, &pKeyT, &nKeyT);
      iTopicT = rtTopic(pPtr->eType);

      res = sortedKeyCompare(xCmp, iTopicT, pKeyT, nKeyT, iTopic, pKey, nKey);
      if( res<=0 ){
        iPtrOut = pPtr->iPtr + pPtr->iPgPtr;
      }

      if( res==0 || iMin==iMax ){
        break;
      }else if( res>0 ){
        iMax = LSM_MAX(iTry-1, iMin);
      }else{
        iMin = iTry+1;
      }
    }

    if( rc==LSM_OK ){
      assert( res==0 || (iMin==iMax && iMin>=0 && iMin<pPtr->nCell) );
      if( res ){
        rc = segmentPtrLoadCell(pPtr, iMin);
      }
      assert( rc!=LSM_OK || res>0 || iPtrOut==(pPtr->iPtr + pPtr->iPgPtr) );

      if( rc==LSM_OK ){
        switch( eSeek ){
          case LSM_SEEK_EQ: {
            int eType = pPtr->eType;
            if( (res<0 && (eType & LSM_START_DELETE))
             || (res>0 && (eType & LSM_END_DELETE))
             || (res==0 && (eType & LSM_POINT_DELETE))
            ){
              *pbStop = 1;
            }else if( res==0 && (eType & LSM_INSERT) ){
              lsm_env *pEnv = pCsr->pDb->pEnv;
              *pbStop = 1;
              pCsr->eType = pPtr->eType;
              rc = sortedBlobSet(pEnv, &pCsr->key, pPtr->pKey, pPtr->nKey);
              if( rc==LSM_OK ){
                rc = sortedBlobSet(pEnv, &pCsr->val, pPtr->pVal, pPtr->nVal);
              }
              pCsr->flags |= CURSOR_SEEK_EQ;
            }
            segmentPtrReset(pPtr);
            break;
          }
          case LSM_SEEK_LE:
            if( res>0 ) rc = segmentPtrAdvance(pCsr, pPtr, 1);
            break;
          case LSM_SEEK_GE: {
            /* Figure out if we need to 'skip' the pointer forward or not */
            if( (res<=0 && (pPtr->eType & LSM_START_DELETE)) 
             || (res>0  && (pPtr->eType & LSM_END_DELETE)) 
            ){
              rc = segmentPtrFwdPointer(pCsr, pPtr, &iPtrOut);
            }
            if( res<0 && rc==LSM_OK ){
              rc = segmentPtrAdvance(pCsr, pPtr, 0);
            }
            break;
          }
        }
      }
    }

    /* If the cursor seek has found a separator key, and this cursor is
    ** supposed to ignore separators keys, advance to the next entry.  */
    if( rc==LSM_OK && pPtr->pPg
     && segmentPtrIgnoreSeparators(pCsr, pPtr) 
     && rtIsSeparator(pPtr->eType)
    ){
      assert( eSeek!=LSM_SEEK_EQ );
      rc = segmentPtrAdvance(pCsr, pPtr, eSeek==LSM_SEEK_LE);
    }
  }

  assert( rc!=LSM_OK || assertSeekResult(pCsr,pPtr,iTopic,pKey,nKey,eSeek) );
  *piPtr = iPtrOut;
  return rc;
}

static int seekInBtree(
  MultiCursor *pCsr,              /* Multi-cursor object */
  Segment *pSeg,                  /* Seek within this segment */
  int iTopic,
  void *pKey, int nKey,           /* Key to seek to */
  Pgno *aPg,                      /* OUT: Page numbers */
  Page **ppPg                     /* OUT: Leaf (sorted-run) page reference */
){
  int i = 0;
  int rc;
  int iPg;
  Page *pPg = 0;
  Blob blob = {0, 0, 0};

  iPg = pSeg->iRoot;
  do {
    Pgno *piFirst = 0;
    if( aPg ){
      aPg[i++] = iPg;
      piFirst = &aPg[i];
    }

    rc = lsmFsDbPageGet(pCsr->pDb->pFS, pSeg, iPg, &pPg);
    assert( rc==LSM_OK || pPg==0 );
    if( rc==LSM_OK ){
      u8 *aData;                  /* Buffer containing page data */
      int nData;                  /* Size of aData[] in bytes */
      int iMin;
      int iMax;
      int nRec;
      int flags;

      aData = fsPageData(pPg, &nData);
      flags = pageGetFlags(aData, nData);
      if( (flags & SEGMENT_BTREE_FLAG)==0 ) break;

      iPg = pageGetPtr(aData, nData);
      nRec = pageGetNRec(aData, nData);

      iMin = 0;
      iMax = nRec-1;
      while( iMax>=iMin ){
        int iTry = (iMin+iMax)/2;
        void *pKeyT; int nKeyT;       /* Key for cell iTry */
        int iTopicT;                  /* Topic for key pKeyT/nKeyT */
        Pgno iPtr;                    /* Pointer associated with cell iTry */
        int res;                      /* (pKey - pKeyT) */

        rc = pageGetBtreeKey(
            pSeg, pPg, iTry, &iPtr, &iTopicT, &pKeyT, &nKeyT, &blob
        );
        if( rc!=LSM_OK ) break;
        if( piFirst && pKeyT==blob.pData ){
          *piFirst = pageGetBtreeRef(pPg, iTry);
          piFirst = 0;
          i++;
        }

        res = sortedKeyCompare(
            pCsr->pDb->xCmp, iTopic, pKey, nKey, iTopicT, pKeyT, nKeyT
        );
        if( res<0 ){
          iPg = iPtr;
          iMax = iTry-1;
        }else{
          iMin = iTry+1;
        }
      }
      lsmFsPageRelease(pPg);
      pPg = 0;
    }
  }while( rc==LSM_OK );

  sortedBlobFree(&blob);
  assert( (rc==LSM_OK)==(pPg!=0) );
  if( ppPg ){
    *ppPg = pPg;
  }else{
    lsmFsPageRelease(pPg);
  }
  return rc;
}

static int seekInSegment(
  MultiCursor *pCsr, 
  SegmentPtr *pPtr,
  int iTopic,
  void *pKey, int nKey,
  int iPg,                        /* Page to search */
  int eSeek,                      /* Search bias - see above */
  int *piPtr,                     /* OUT: FC pointer */
  int *pbStop                     /* OUT: Stop search flag */
){
  int iPtr = iPg;
  int rc = LSM_OK;

  if( pPtr->pSeg->iRoot ){
    Page *pPg;
    assert( pPtr->pSeg->iRoot!=0 );
    rc = seekInBtree(pCsr, pPtr->pSeg, iTopic, pKey, nKey, 0, &pPg);
    if( rc==LSM_OK ) segmentPtrSetPage(pPtr, pPg);
  }else{
    if( iPtr==0 ){
      iPtr = pPtr->pSeg->iFirst;
    }
    if( rc==LSM_OK ){
      rc = segmentPtrLoadPage(pCsr->pDb->pFS, pPtr, iPtr);
    }
  }

  if( rc==LSM_OK ){
    rc = segmentPtrSeek(pCsr, pPtr, iTopic, pKey, nKey, eSeek, piPtr, pbStop);
  }
  return rc;
}

/*
** Seek each segment pointer in the array of (pLvl->nRight+1) at aPtr[].
**
** pbStop:
**   This parameter is only significant if parameter eSeek is set to
**   LSM_SEEK_EQ. In this case, it is set to true before returning if
**   the seek operation is finished. This can happen in two ways:
**   
**     a) A key matching (pKey/nKey) is found, or
**     b) A point-delete or range-delete deleting the key is found.
**
**   In case (a), the multi-cursor CURSOR_SEEK_EQ flag is set and the pCsr->key
**   and pCsr->val blobs populated before returning.
*/
static int seekInLevel(
  MultiCursor *pCsr,              /* Sorted cursor object to seek */
  SegmentPtr *aPtr,               /* Pointer to array of (nRhs+1) SPs */
  int eSeek,                      /* Search bias - see above */
  int iTopic,                     /* Key topic to search for */
  void *pKey, int nKey,           /* Key to search for */
  Pgno *piPgno,                   /* IN/OUT: fraction cascade pointer (or 0) */
  int *pbStop                     /* OUT: See above */
){
  Level *pLvl = aPtr[0].pLevel;   /* Level to seek within */
  int rc = LSM_OK;                /* Return code */
  int iOut = 0;                   /* Pointer to return to caller */
  int res = -1;                   /* Result of xCmp(pKey, split) */
  int nRhs = pLvl->nRight;        /* Number of right-hand-side segments */
  int bStop = 0;

  /* If this is a composite level (one currently undergoing an incremental
  ** merge), figure out if the search key is larger or smaller than the
  ** levels split-key.  */
  if( nRhs ){
    res = sortedKeyCompare(pCsr->pDb->xCmp, iTopic, pKey, nKey, 
        pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
    );
  }

  /* If (res<0), then key pKey/nKey is smaller than the split-key (or this
  ** is not a composite level and there is no split-key). Search the 
  ** left-hand-side of the level in this case.  */
  if( res<0 ){
    int iPtr = 0;
    if( nRhs==0 ) iPtr = *piPgno;

    rc = seekInSegment(
        pCsr, &aPtr[0], iTopic, pKey, nKey, iPtr, eSeek, &iOut, &bStop
    );
    if( rc==LSM_OK && nRhs>0 && eSeek==LSM_SEEK_GE && aPtr[0].pPg==0 ){
      res = 0;
    }
  }
  
  if( res>=0 ){
    int bHit = 0;                 /* True if at least one rhs is not EOF */
    int iPtr = *piPgno;
    int i;
    for(i=1; rc==LSM_OK && i<=nRhs && bStop==0; i++){
      SegmentPtr *pPtr = &aPtr[i];
      iOut = 0;
      rc = seekInSegment(
          pCsr, pPtr, iTopic, pKey, nKey, iPtr, eSeek, &iOut, &bStop
      );
      iPtr = iOut;

      /* If the segment-pointer has settled on a key that is smaller than
      ** the splitkey, invalidate the segment-pointer.  */
      if( pPtr->pPg ){
        res = sortedKeyCompare(pCsr->pDb->xCmp, 
            rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey, 
            pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
        );
        if( res<0 ) segmentPtrReset(pPtr);
      }

      if( aPtr[i].pKey ) bHit = 1;
    }

    if( rc==LSM_OK && eSeek==LSM_SEEK_LE && bHit==0 ){
      rc = segmentPtrEnd(pCsr, &aPtr[0], 1);
    }
  }

  assert( eSeek==LSM_SEEK_EQ || bStop==0 );
  *piPgno = iOut;
  *pbStop = bStop;
  return rc;
}

static void multiCursorGetKey(
  MultiCursor *pCsr, 
  int iKey,
  int *peType,                    /* OUT: Key type (SORTED_WRITE etc.) */
  void **ppKey,                   /* OUT: Pointer to buffer containing key */
  int *pnKey                      /* OUT: Size of *ppKey in bytes */
){
  int nKey = 0;
  void *pKey = 0;
  int eType = 0;

  switch( iKey ){
    case CURSOR_DATA_TREE0:
    case CURSOR_DATA_TREE1: {
      TreeCursor *pTreeCsr = pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0];
      if( lsmTreeCursorValid(pTreeCsr) ){
        lsmTreeCursorKey(pTreeCsr, &eType, &pKey, &nKey);
      }
      break;
    }

    case CURSOR_DATA_SYSTEM: {
      Snapshot *pWorker = pCsr->pDb->pWorker;
      if( pWorker && (pCsr->flags & CURSOR_FLUSH_FREELIST) ){
        int nEntry = pWorker->freelist.nEntry;
        if( pCsr->iFree < (nEntry*2) ){
          FreelistEntry *aEntry = pWorker->freelist.aEntry;
          int i = nEntry - 1 - (pCsr->iFree / 2);
          u32 iKey = 0;

          if( (pCsr->iFree % 2) ){
            eType = LSM_END_DELETE|LSM_SYSTEMKEY;
            iKey = aEntry[i].iBlk-1;
          }else if( aEntry[i].iId>=0 ){
            eType = LSM_INSERT|LSM_SYSTEMKEY;
            iKey = aEntry[i].iBlk;

            /* If the in-memory entry immediately before this one was a
             ** DELETE, and the block number is one greater than the current
             ** block number, mark this entry as an "end-delete-range". */
            if( i<(nEntry-1) && aEntry[i+1].iBlk==iKey+1 && aEntry[i+1].iId<0 ){
              eType |= LSM_END_DELETE;
            }

          }else{
            eType = LSM_START_DELETE|LSM_SYSTEMKEY;
            iKey = aEntry[i].iBlk + 1;
          }

          /* If the in-memory entry immediately after this one is a
          ** DELETE, and the block number is one less than the current
          ** key, mark this entry as an "start-delete-range".  */
          if( i>0 && aEntry[i-1].iBlk==iKey-1 && aEntry[i-1].iId<0 ){
            eType |= LSM_START_DELETE;
          }

          pKey = pCsr->pSystemVal;
          nKey = 4;
          lsmPutU32(pKey, ~iKey);
        }
      }
      break;
    }

    default: {
      int iPtr = iKey - CURSOR_DATA_SEGMENT;
      assert( iPtr>=0 );
      if( iPtr==pCsr->nPtr ){
        if( pCsr->pBtCsr ){
          pKey = pCsr->pBtCsr->pKey;
          nKey = pCsr->pBtCsr->nKey;
          eType = pCsr->pBtCsr->eType;
        }
      }else if( iPtr<pCsr->nPtr ){
        SegmentPtr *pPtr = &pCsr->aPtr[iPtr];
        if( pPtr->pPg ){
          pKey = pPtr->pKey;
          nKey = pPtr->nKey;
          eType = pPtr->eType;
        }
      }
      break;
    }
  }

  if( peType ) *peType = eType;
  if( pnKey ) *pnKey = nKey;
  if( ppKey ) *ppKey = pKey;
}

static int sortedDbKeyCompare(
  MultiCursor *pCsr,
  int iLhsFlags, void *pLhsKey, int nLhsKey,
  int iRhsFlags, void *pRhsKey, int nRhsKey
){
  int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
  int res;

  /* Compare the keys, including the system flag. */
  res = sortedKeyCompare(xCmp, 
    rtTopic(iLhsFlags), pLhsKey, nLhsKey,
    rtTopic(iRhsFlags), pRhsKey, nRhsKey
  );

  /* If a key has the LSM_START_DELETE flag set, but not the LSM_INSERT or
  ** LSM_POINT_DELETE flags, it is considered a delta larger. This prevents
  ** the beginning of an open-ended set from masking a database entry or
  ** delete at a lower level.  */
  if( res==0 && (pCsr->flags & CURSOR_IGNORE_DELETE) ){
    const int m = LSM_POINT_DELETE|LSM_INSERT|LSM_END_DELETE |LSM_START_DELETE;
    int iDel1 = 0;
    int iDel2 = 0;

    if( LSM_START_DELETE==(iLhsFlags & m) ) iDel1 = +1;
    if( LSM_END_DELETE  ==(iLhsFlags & m) ) iDel1 = -1;
    if( LSM_START_DELETE==(iRhsFlags & m) ) iDel2 = +1;
    if( LSM_END_DELETE  ==(iRhsFlags & m) ) iDel2 = -1;

    res = (iDel1 - iDel2);
  }

  return res;
}

static void multiCursorDoCompare(MultiCursor *pCsr, int iOut, int bReverse){
  int i1;
  int i2;
  int iRes;
  void *pKey1; int nKey1; int eType1;
  void *pKey2; int nKey2; int eType2;
  const int mul = (bReverse ? -1 : 1);

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

  multiCursorGetKey(pCsr, i1, &eType1, &pKey1, &nKey1);
  multiCursorGetKey(pCsr, i2, &eType2, &pKey2, &nKey2);

  if( pKey1==0 ){
    iRes = i2;
  }else if( pKey2==0 ){
    iRes = i1;
  }else{
    int res;

    /* Compare the keys */
    res = sortedDbKeyCompare(pCsr,
        eType1, pKey1, nKey1, eType2, pKey2, nKey2
    );

    res = res * mul;
    if( res==0 ){
      /* The two keys are identical. Normally, this means that the key from
      ** the newer run clobbers the old. However, if the newer key is a
      ** separator key, or a range-delete-boundary only, do not allow it
      ** to clobber an older entry.  */
      int nc1 = (eType1 & (LSM_INSERT|LSM_POINT_DELETE))==0;
      int nc2 = (eType2 & (LSM_INSERT|LSM_POINT_DELETE))==0;
      iRes = (nc1 > nc2) ? i2 : i1;
    }else if( res<0 ){
      iRes = i1;
    }else{
      iRes = i2;
    }
  }

  pCsr->aTree[iOut] = iRes;
}

/*
** This function advances segment pointer iPtr belonging to multi-cursor
** pCsr forward (bReverse==0) or backward (bReverse!=0).
**
** If the segment pointer points to a segment that is part of a composite
** level, then the following special case is handled.
**
**   * If iPtr is the lhs of a composite level, and the cursor is being
**     advanced forwards, and segment iPtr is at EOF, move all pointers
**     that correspond to rhs segments of the same level to the first
**     key in their respective data.
*/
static int segmentCursorAdvance(
  MultiCursor *pCsr, 
  int iPtr,
  int bReverse
){
  int rc;
  SegmentPtr *pPtr = &pCsr->aPtr[iPtr];
  Level *pLvl = pPtr->pLevel;
  int bComposite;                 /* True if pPtr is part of composite level */

  /* Advance the segment-pointer object. */
  rc = segmentPtrAdvance(pCsr, pPtr, bReverse);
  if( rc!=LSM_OK ) return rc;

  bComposite = (pLvl->nRight>0 && pCsr->nPtr>pLvl->nRight);
  if( bComposite && pPtr->pPg==0 ){
    int bFix = 0;
    if( (bReverse==0)==(pPtr->pSeg==&pLvl->lhs) ){
      int i;
      if( bReverse ){
        SegmentPtr *pLhs = &pCsr->aPtr[iPtr - 1 - (pPtr->pSeg - pLvl->aRhs)];
        for(i=0; i<pLvl->nRight; i++){
          if( pLhs[i+1].pPg ) break;
        }
        if( i==pLvl->nRight ){
          bFix = 1;
          rc = segmentPtrEnd(pCsr, pLhs, 1);
        }
      }else{
        bFix = 1;
        for(i=0; rc==LSM_OK && i<pLvl->nRight; i++){
          rc = sortedRhsFirst(pCsr, pLvl, &pCsr->aPtr[iPtr+1+i]);
        }
      }
    }

    if( bFix ){
      int i;
      for(i=pCsr->nTree-1; i>0; i--){
        multiCursorDoCompare(pCsr, i, bReverse);
      }
    }
  }

#if 0
  if( bComposite && pPtr->pSeg==&pLvl->lhs       /* lhs of composite level */
   && bReverse==0                                /* csr advanced forwards */
   && pPtr->pPg==0                               /* segment at EOF */
  ){
    int i;
    for(i=0; rc==LSM_OK && i<pLvl->nRight; i++){
      rc = sortedRhsFirst(pCsr, pLvl, &pCsr->aPtr[iPtr+1+i]);
    }
    for(i=pCsr->nTree-1; i>0; i--){
      multiCursorDoCompare(pCsr, i, 0);
    }
  }
#endif

  return rc;
}

static void mcursorFreeComponents(MultiCursor *pCsr){
  int i;
  lsm_env *pEnv = pCsr->pDb->pEnv;

  /* Close the tree cursor, if any. */
  lsmTreeCursorDestroy(pCsr->apTreeCsr[0]);
  lsmTreeCursorDestroy(pCsr->apTreeCsr[1]);

  /* Reset the segment pointers */
  for(i=0; i<pCsr->nPtr; i++){
    segmentPtrReset(&pCsr->aPtr[i]);
  }

  /* And the b-tree cursor, if any */
  btreeCursorFree(pCsr->pBtCsr);

  /* Free allocations */
  lsmFree(pEnv, pCsr->aPtr);
  lsmFree(pEnv, pCsr->aTree);
  lsmFree(pEnv, pCsr->pSystemVal);

  /* Zero fields */
  pCsr->nPtr = 0;
  pCsr->aPtr = 0;
  pCsr->nTree = 0;
  pCsr->aTree = 0;
  pCsr->pSystemVal = 0;
  pCsr->apTreeCsr[0] = 0;
  pCsr->apTreeCsr[1] = 0;
  pCsr->pBtCsr = 0;
}

void lsmMCursorFreeCache(lsm_db *pDb){
  MultiCursor *p;
  MultiCursor *pNext;
  for(p=pDb->pCsrCache; p; p=pNext){
    pNext = p->pNext;
    lsmMCursorClose(p, 0);
  }
  pDb->pCsrCache = 0;
}

/*
** Close the cursor passed as the first argument.
**
** If the bCache parameter is true, then shift the cursor to the pCsrCache
** list for possible reuse instead of actually deleting it.
*/
void lsmMCursorClose(MultiCursor *pCsr, int bCache){
  if( pCsr ){
    lsm_db *pDb = pCsr->pDb;
    MultiCursor **pp;             /* Iterator variable */

    /* The cursor may or may not be currently part of the linked list 
    ** starting at lsm_db.pCsr. If it is, extract it.  */
    for(pp=&pDb->pCsr; *pp; pp=&((*pp)->pNext)){
      if( *pp==pCsr ){
        *pp = pCsr->pNext;
        break;
      }
    }

    if( bCache ){
      int i;                      /* Used to iterate through segment-pointers */

      /* Release any page references held by this cursor. */
      assert( !pCsr->pBtCsr );
      for(i=0; i<pCsr->nPtr; i++){
        SegmentPtr *pPtr = &pCsr->aPtr[i];
        lsmFsPageRelease(pPtr->pPg);
        pPtr->pPg = 0;
      }

      /* Reset the tree cursors */
      lsmTreeCursorReset(pCsr->apTreeCsr[0]);
      lsmTreeCursorReset(pCsr->apTreeCsr[1]);

      /* Add the cursor to the pCsrCache list */
      pCsr->pNext = pDb->pCsrCache;
      pDb->pCsrCache = pCsr;
    }else{
      /* Free the allocation used to cache the current key, if any. */
      sortedBlobFree(&pCsr->key);
      sortedBlobFree(&pCsr->val);

      /* Free the component cursors */
      mcursorFreeComponents(pCsr);

      /* Free the cursor structure itself */
      lsmFree(pDb->pEnv, pCsr);
    }
  }
}

#define TREE_NONE 0
#define TREE_OLD  1
#define TREE_BOTH 2

/*
** Parameter eTree is one of TREE_OLD or TREE_BOTH.
*/
static int multiCursorAddTree(MultiCursor *pCsr, Snapshot *pSnap, int eTree){
  int rc = LSM_OK;
  lsm_db *db = pCsr->pDb;

  /* Add a tree cursor on the 'old' tree, if it exists. */
  if( eTree!=TREE_NONE 
   && lsmTreeHasOld(db) 
   && db->treehdr.iOldLog!=pSnap->iLogOff 
  ){
    rc = lsmTreeCursorNew(db, 1, &pCsr->apTreeCsr[1]);
  }

  /* Add a tree cursor on the 'current' tree, if required. */
  if( rc==LSM_OK && eTree==TREE_BOTH ){
    rc = lsmTreeCursorNew(db, 0, &pCsr->apTreeCsr[0]);
  }

  return rc;
}

static int multiCursorAddRhs(MultiCursor *pCsr, Level *pLvl){
  int i;
  int nRhs = pLvl->nRight;

  assert( pLvl->nRight>0 );
  assert( pCsr->aPtr==0 );
  pCsr->aPtr = lsmMallocZero(pCsr->pDb->pEnv, sizeof(SegmentPtr) * nRhs);
  if( !pCsr->aPtr ) return LSM_NOMEM_BKPT;
  pCsr->nPtr = nRhs;

  for(i=0; i<nRhs; i++){
    pCsr->aPtr[i].pSeg = &pLvl->aRhs[i];
    pCsr->aPtr[i].pLevel = pLvl;
  }

  return LSM_OK;
}

static void multiCursorAddOne(MultiCursor *pCsr, Level *pLvl, int *pRc){
  if( *pRc==LSM_OK ){
    int iPtr = pCsr->nPtr;
    int i;
    pCsr->aPtr[iPtr].pLevel = pLvl;
    pCsr->aPtr[iPtr].pSeg = &pLvl->lhs;
    iPtr++;
    for(i=0; i<pLvl->nRight; i++){
      pCsr->aPtr[iPtr].pLevel = pLvl;
      pCsr->aPtr[iPtr].pSeg = &pLvl->aRhs[i];
      iPtr++;
    }

    if( pLvl->nRight && pLvl->pSplitKey==0 ){
      sortedSplitkey(pCsr->pDb, pLvl, pRc);
    }
    pCsr->nPtr = iPtr;
  }
}

static int multiCursorAddAll(MultiCursor *pCsr, Snapshot *pSnap){
  Level *pLvl;
  int nPtr = 0;
  int rc = LSM_OK;

  for(pLvl=pSnap->pLevel; pLvl; pLvl=pLvl->pNext){
    /* If the LEVEL_INCOMPLETE flag is set, then this function is being
    ** called (indirectly) from within a sortedNewToplevel() call to
    ** construct pLvl. In this case ignore pLvl - this cursor is going to
    ** be used to retrieve a freelist entry from the LSM, and the partially
    ** complete level may confuse it.  */
    if( pLvl->flags & LEVEL_INCOMPLETE ) continue;
    nPtr += (1 + pLvl->nRight);
  }

  assert( pCsr->aPtr==0 );
  pCsr->aPtr = lsmMallocZeroRc(pCsr->pDb->pEnv, sizeof(SegmentPtr) * nPtr, &rc);

  for(pLvl=pSnap->pLevel; pLvl; pLvl=pLvl->pNext){
    if( (pLvl->flags & LEVEL_INCOMPLETE)==0 ){
      multiCursorAddOne(pCsr, pLvl, &rc);
    }
  }

  return rc;
}

static int multiCursorInit(MultiCursor *pCsr, Snapshot *pSnap){
  int rc;
  rc = multiCursorAddAll(pCsr, pSnap);
  if( rc==LSM_OK ){
    rc = multiCursorAddTree(pCsr, pSnap, TREE_BOTH);
  }
  pCsr->flags |= (CURSOR_IGNORE_SYSTEM | CURSOR_IGNORE_DELETE);
  return rc;
}

static MultiCursor *multiCursorNew(lsm_db *db, int *pRc){
  MultiCursor *pCsr;
  pCsr = (MultiCursor *)lsmMallocZeroRc(db->pEnv, sizeof(MultiCursor), pRc);
  if( pCsr ){
    pCsr->pNext = db->pCsr;
    db->pCsr = pCsr;
    pCsr->pDb = db;
  }
  return pCsr;
}


void lsmSortedRemap(lsm_db *pDb){
  MultiCursor *pCsr;
  for(pCsr=pDb->pCsr; pCsr; pCsr=pCsr->pNext){
    int iPtr;
    if( pCsr->pBtCsr ){
      btreeCursorLoadKey(pCsr->pBtCsr);
    }
    for(iPtr=0; iPtr<pCsr->nPtr; iPtr++){
      segmentPtrLoadCell(&pCsr->aPtr[iPtr], pCsr->aPtr[iPtr].iCell);
    }
  }
}

static void multiCursorReadSeparators(MultiCursor *pCsr){
  if( pCsr->nPtr>0 ){
    pCsr->flags |= CURSOR_READ_SEPARATORS;
  }
}

/*
** Have this cursor skip over SORTED_DELETE entries.
*/
static void multiCursorIgnoreDelete(MultiCursor *pCsr){
  if( pCsr ) pCsr->flags |= CURSOR_IGNORE_DELETE;
}

/*
** If the free-block list is not empty, then have this cursor visit a key
** with (a) the system bit set, and (b) the key "FREELIST" and (c) a value 
** blob containing the serialized free-block list.
*/
static int multiCursorVisitFreelist(MultiCursor *pCsr){
  int rc = LSM_OK;
  pCsr->flags |= CURSOR_FLUSH_FREELIST;
  pCsr->pSystemVal = lsmMallocRc(pCsr->pDb->pEnv, 4 + 8, &rc);
  return rc;
}

/*
** Allocate and return a new database cursor.
**
** This method should only be called to allocate user cursors. As it may
** recycle a cursor from lsm_db.pCsrCache.
*/
int lsmMCursorNew(
  lsm_db *pDb,                    /* Database handle */
  MultiCursor **ppCsr             /* OUT: Allocated cursor */
){
  MultiCursor *pCsr = 0;
  int rc = LSM_OK;

  if( pDb->pCsrCache ){
    int bOld;                     /* True if there is an old in-memory tree */

    /* Remove a cursor from the pCsrCache list and add it to the open list. */
    pCsr = pDb->pCsrCache;
    pDb->pCsrCache = pCsr->pNext;
    pCsr->pNext = pDb->pCsr;
    pDb->pCsr = pCsr;

    /* The cursor can almost be used as is, except that the old in-memory
    ** tree cursor may be present and not required, or required and not
    ** present. Fix this if required.  */
    bOld = (lsmTreeHasOld(pDb) && pDb->treehdr.iOldLog!=pDb->pClient->iLogOff);
    if( !bOld && pCsr->apTreeCsr[1] ){
      lsmTreeCursorDestroy(pCsr->apTreeCsr[1]);
      pCsr->apTreeCsr[1] = 0;
    }else if( bOld && !pCsr->apTreeCsr[1] ){
      rc = lsmTreeCursorNew(pDb, 1, &pCsr->apTreeCsr[1]);
    }

    pCsr->flags = (CURSOR_IGNORE_SYSTEM | CURSOR_IGNORE_DELETE);

  }else{
    pCsr = multiCursorNew(pDb, &rc);
    if( rc==LSM_OK ) rc = multiCursorInit(pCsr, pDb->pClient);
  }

  if( rc!=LSM_OK ){
    lsmMCursorClose(pCsr, 0);
    pCsr = 0;
  }
  assert( (rc==LSM_OK)==(pCsr!=0) );
  *ppCsr = pCsr;
  return rc;
}

static int multiCursorGetVal(
  MultiCursor *pCsr, 
  int iVal, 
  void **ppVal, 
  int *pnVal
){
  int rc = LSM_OK;

  *ppVal = 0;
  *pnVal = 0;

  switch( iVal ){
    case CURSOR_DATA_TREE0:
    case CURSOR_DATA_TREE1: {
      TreeCursor *pTreeCsr = pCsr->apTreeCsr[iVal-CURSOR_DATA_TREE0];
      if( lsmTreeCursorValid(pTreeCsr) ){
        lsmTreeCursorValue(pTreeCsr, ppVal, pnVal);
      }else{
        *ppVal = 0;
        *pnVal = 0;
      }
      break;
    }

    case CURSOR_DATA_SYSTEM: {
      Snapshot *pWorker = pCsr->pDb->pWorker;
      if( pWorker 
       && (pCsr->iFree % 2)==0
       && pCsr->iFree < (pWorker->freelist.nEntry*2)
      ){
        int iEntry = pWorker->freelist.nEntry - 1 - (pCsr->iFree / 2);
        u8 *aVal = &((u8 *)(pCsr->pSystemVal))[4];
        lsmPutU64(aVal, pWorker->freelist.aEntry[iEntry].iId);
        *ppVal = aVal;
        *pnVal = 8;
      }
      break;
    }

    default: {
      int iPtr = iVal-CURSOR_DATA_SEGMENT;
      if( iPtr<pCsr->nPtr ){
        SegmentPtr *pPtr = &pCsr->aPtr[iPtr];
        if( pPtr->pPg ){
          *ppVal = pPtr->pVal;
          *pnVal = pPtr->nVal;
        }
      }
    }
  }

  assert( rc==LSM_OK || (*ppVal==0 && *pnVal==0) );
  return rc;
}

static int multiCursorAdvance(MultiCursor *pCsr, int bReverse);

/*
** This function is called by worker connections to walk the part of the
** free-list stored within the LSM data structure.
*/
int lsmSortedWalkFreelist(
  lsm_db *pDb,                    /* Database handle */
  int bReverse,                   /* True to iterate from largest to smallest */
  int (*x)(void *, int, i64),     /* Callback function */
  void *pCtx                      /* First argument to pass to callback */
){
  MultiCursor *pCsr;              /* Cursor used to read db */
  int rc = LSM_OK;                /* Return Code */
  Snapshot *pSnap = 0;

  assert( pDb->pWorker );
  if( pDb->bIncrMerge ){
    rc = lsmCheckpointDeserialize(pDb, 0, pDb->pShmhdr->aSnap1, &pSnap);
    if( rc!=LSM_OK ) return rc;
  }else{
    pSnap = pDb->pWorker;
  }

  pCsr = multiCursorNew(pDb, &rc);
  if( pCsr ){
    rc = multiCursorAddAll(pCsr, pSnap);
    pCsr->flags |= CURSOR_IGNORE_DELETE;
  }
  
  if( rc==LSM_OK ){
    if( bReverse==0 ){
      rc = lsmMCursorLast(pCsr);
    }else{
      rc = lsmMCursorSeek(pCsr, 1, "", 0, LSM_SEEK_GE);
    }

    while( rc==LSM_OK && lsmMCursorValid(pCsr) && rtIsSystem(pCsr->eType) ){
      void *pKey; int nKey;
      void *pVal; int nVal;

      rc = lsmMCursorKey(pCsr, &pKey, &nKey);
      if( rc==LSM_OK ) rc = lsmMCursorValue(pCsr, &pVal, &nVal);
      if( rc==LSM_OK && (nKey!=4 || nVal!=8) ) rc = LSM_CORRUPT_BKPT;

      if( rc==LSM_OK ){
        int iBlk;
        i64 iSnap;
        iBlk = (int)(~(lsmGetU32((u8 *)pKey)));
        iSnap = (i64)lsmGetU64((u8 *)pVal);
        if( x(pCtx, iBlk, iSnap) ) break;
        rc = multiCursorAdvance(pCsr, !bReverse);
      }
    }
  }

  lsmMCursorClose(pCsr, 0);
  if( pSnap!=pDb->pWorker ){
    lsmFreeSnapshot(pDb->pEnv, pSnap);
  }

  return rc;
}

int lsmSortedLoadFreelist(
  lsm_db *pDb,                    /* Database handle (must be worker) */
  void **ppVal,                   /* OUT: Blob containing LSM free-list */
  int *pnVal                      /* OUT: Size of *ppVal blob in bytes */
){
  MultiCursor *pCsr;              /* Cursor used to retreive free-list */
  int rc = LSM_OK;                /* Return Code */

  assert( pDb->pWorker );
  assert( *ppVal==0 && *pnVal==0 );

  pCsr = multiCursorNew(pDb, &rc);
  if( pCsr ){
    rc = multiCursorAddAll(pCsr, pDb->pWorker);
    pCsr->flags |= CURSOR_IGNORE_DELETE;
  }
  
  if( rc==LSM_OK ){
    rc = lsmMCursorLast(pCsr);
    if( rc==LSM_OK 
     && rtIsWrite(pCsr->eType) && rtIsSystem(pCsr->eType)
     && pCsr->key.nData==8 
     && 0==memcmp(pCsr->key.pData, "FREELIST", 8)
    ){
      void *pVal; int nVal;         /* Value read from database */
      rc = lsmMCursorValue(pCsr, &pVal, &nVal);
      if( rc==LSM_OK ){
        *ppVal = lsmMallocRc(pDb->pEnv, nVal, &rc);
        if( *ppVal ){
          memcpy(*ppVal, pVal, nVal);
          *pnVal = nVal;
        }
      }
    }

    lsmMCursorClose(pCsr, 0);
  }

  return rc;
}

static int multiCursorAllocTree(MultiCursor *pCsr){
  int rc = LSM_OK;
  if( pCsr->aTree==0 ){
    int nByte;                    /* Bytes of space to allocate */
    int nMin;                     /* Total number of cursors being merged */

    nMin = CURSOR_DATA_SEGMENT + pCsr->nPtr + (pCsr->pBtCsr!=0);
    pCsr->nTree = 2;
    while( pCsr->nTree<nMin ){
      pCsr->nTree = pCsr->nTree*2;
    }

    nByte = sizeof(int)*pCsr->nTree*2;
    pCsr->aTree = (int *)lsmMallocZeroRc(pCsr->pDb->pEnv, nByte, &rc);
  }
  return rc;
}

static void multiCursorCacheKey(MultiCursor *pCsr, int *pRc){
  if( *pRc==LSM_OK ){
    void *pKey;
    int nKey;
    multiCursorGetKey(pCsr, pCsr->aTree[1], &pCsr->eType, &pKey, &nKey);
    *pRc = sortedBlobSet(pCsr->pDb->pEnv, &pCsr->key, pKey, nKey);
  }
}

#ifdef LSM_DEBUG_EXPENSIVE
static void assertCursorTree(MultiCursor *pCsr){
  int bRev = !!(pCsr->flags & CURSOR_PREV_OK);
  int *aSave = pCsr->aTree;
  int nSave = pCsr->nTree;
  int rc;

  pCsr->aTree = 0;
  pCsr->nTree = 0;
  rc = multiCursorAllocTree(pCsr);
  if( rc==LSM_OK ){
    int i;
    for(i=pCsr->nTree-1; i>0; i--){
      multiCursorDoCompare(pCsr, i, bRev);
    }

    assert( nSave==pCsr->nTree 
        && 0==memcmp(aSave, pCsr->aTree, sizeof(int)*nSave)
    );

    lsmFree(pCsr->pDb->pEnv, pCsr->aTree);
  }

  pCsr->aTree = aSave;
  pCsr->nTree = nSave;
}
#else
# define assertCursorTree(x)
#endif

static int mcursorLocationOk(MultiCursor *pCsr, int bDeleteOk){
  int eType = pCsr->eType;
  int iKey;
  int i;
  int rdmask;
  
  assert( pCsr->flags & (CURSOR_NEXT_OK|CURSOR_PREV_OK) );
  assertCursorTree(pCsr);

  rdmask = (pCsr->flags & CURSOR_NEXT_OK) ? LSM_END_DELETE : LSM_START_DELETE;

  /* If the cursor does not currently point to an actual database key (i.e.
  ** it points to a delete key, or the start or end of a range-delete), and
  ** the CURSOR_IGNORE_DELETE flag is set, skip past this entry.  */
  if( (pCsr->flags & CURSOR_IGNORE_DELETE) && bDeleteOk==0 ){
    if( (eType & LSM_INSERT)==0 ) return 0;
  }

  /* If the cursor points to a system key (free-list entry), and the
  ** CURSOR_IGNORE_SYSTEM flag is set, skip thie entry.  */
  if( (pCsr->flags & CURSOR_IGNORE_SYSTEM) && rtTopic(eType)!=0 ){
    return 0;
  }

#ifndef NDEBUG
  /* This block fires assert() statements to check one of the assumptions
  ** in the comment below - that if the lhs sub-cursor of a level undergoing
  ** a merge is valid, then all the rhs sub-cursors must be at EOF. 
  **
  ** Also assert that all rhs sub-cursors are either at EOF or point to
  ** a key that is not less than the level split-key.  */
  for(i=0; i<pCsr->nPtr; i++){
    SegmentPtr *pPtr = &pCsr->aPtr[i];
    Level *pLvl = pPtr->pLevel;
    if( pLvl->nRight && pPtr->pPg ){
      if( pPtr->pSeg==&pLvl->lhs ){
        int j;
        for(j=0; j<pLvl->nRight; j++) assert( pPtr[j+1].pPg==0 );
      }else{
        int res = sortedKeyCompare(pCsr->pDb->xCmp, 
            rtTopic(pPtr->eType), pPtr->pKey, pPtr->nKey,
            pLvl->iSplitTopic, pLvl->pSplitKey, pLvl->nSplitKey
        );
        assert( res>=0 );
      }
    }
  }
#endif

  /* Now check if this key has already been deleted by a range-delete. If 
  ** so, skip past it.
  **
  ** Assume, for the moment, that the tree contains no levels currently 
  ** undergoing incremental merge, and that this cursor is iterating forwards
  ** through the database keys. The cursor currently points to a key in
  ** level L. This key has already been deleted if any of the sub-cursors
  ** that point to levels newer than L (or to the in-memory tree) point to
  ** a key greater than the current key with the LSM_END_DELETE flag set.
  **
  ** Or, if the cursor is iterating backwards through data keys, if any
  ** such sub-cursor points to a key smaller than the current key with the
  ** LSM_START_DELETE flag set.
  **
  ** Why it works with levels undergoing a merge too:
  **
  ** When a cursor iterates forwards, the sub-cursors for the rhs of a 
  ** level are only activated once the lhs reaches EOF. So when iterating
  ** forwards, the keys visited are the same as if the level was completely
  ** merged.
  **
  ** If the cursor is iterating backwards, then the lhs sub-cursor is not 
  ** initialized until the last of the rhs sub-cursors has reached EOF.
  ** Additionally, if the START_DELETE flag is set on the last entry (in
  ** reverse order - so the entry with the smallest key) of a rhs sub-cursor,
  ** then a pseudo-key equal to the levels split-key with the END_DELETE
  ** flag set is visited by the sub-cursor.
  */ 
  iKey = pCsr->aTree[1];
  for(i=0; i<iKey; i++){
    int csrflags;
    multiCursorGetKey(pCsr, i, &csrflags, 0, 0);
    if( (rdmask & csrflags) ){
      const int SD_ED = (LSM_START_DELETE|LSM_END_DELETE);
      if( (csrflags & SD_ED)==SD_ED 
       || (pCsr->flags & CURSOR_IGNORE_DELETE)==0
      ){
        void *pKey; int nKey;
        multiCursorGetKey(pCsr, i, 0, &pKey, &nKey);
        if( 0==sortedKeyCompare(pCsr->pDb->xCmp,
              rtTopic(eType), pCsr->key.pData, pCsr->key.nData,
              rtTopic(csrflags), pKey, nKey
        )){
          continue;
        }
      }
      return 0;
    }
  }

  /* The current cursor position is one this cursor should visit. Return 1. */
  return 1;
}

static int multiCursorSetupTree(MultiCursor *pCsr, int bRev){
  int rc;

  rc = multiCursorAllocTree(pCsr);
  if( rc==LSM_OK ){
    int i;
    for(i=pCsr->nTree-1; i>0; i--){
      multiCursorDoCompare(pCsr, i, bRev);
    }
  }

  assertCursorTree(pCsr);
  multiCursorCacheKey(pCsr, &rc);

  if( rc==LSM_OK && mcursorLocationOk(pCsr, 0)==0 ){
    rc = multiCursorAdvance(pCsr, bRev);
  }
  return rc;
}


static int multiCursorEnd(MultiCursor *pCsr, int bLast){
  int rc = LSM_OK;
  int i;

  pCsr->flags &= ~(CURSOR_NEXT_OK | CURSOR_PREV_OK);
  pCsr->flags |= (bLast ? CURSOR_PREV_OK : CURSOR_NEXT_OK);
  pCsr->iFree = 0;

  /* Position the two in-memory tree cursors */
  for(i=0; rc==LSM_OK && i<2; i++){
    if( pCsr->apTreeCsr[i] ){
      rc = lsmTreeCursorEnd(pCsr->apTreeCsr[i], bLast);
    }
  }

  for(i=0; rc==LSM_OK && i<pCsr->nPtr; i++){
    SegmentPtr *pPtr = &pCsr->aPtr[i];
    Level *pLvl = pPtr->pLevel;
    int iRhs;
    int bHit = 0;

    if( bLast ){
      for(iRhs=0; iRhs<pLvl->nRight && rc==LSM_OK; iRhs++){
        rc = segmentPtrEnd(pCsr, &pPtr[iRhs+1], 1);
        if( pPtr[iRhs+1].pPg ) bHit = 1;
      }
      if( bHit==0 && rc==LSM_OK ){
        rc = segmentPtrEnd(pCsr, pPtr, 1);
      }else{
        segmentPtrReset(pPtr);
      }
    }else{
      int bLhs = (pPtr->pSeg==&pLvl->lhs);
      assert( pPtr->pSeg==&pLvl->lhs || pPtr->pSeg==&pLvl->aRhs[0] );

      if( bLhs ){
        rc = segmentPtrEnd(pCsr, pPtr, 0);
        if( pPtr->pKey ) bHit = 1;
      }
      for(iRhs=0; iRhs<pLvl->nRight && rc==LSM_OK; iRhs++){
        if( bHit ){
          segmentPtrReset(&pPtr[iRhs+1]);
        }else{
          rc = sortedRhsFirst(pCsr, pLvl, &pPtr[iRhs+bLhs]);
        }
      }
    }
    i += pLvl->nRight;
  }

  /* And the b-tree cursor, if applicable */
  if( rc==LSM_OK && pCsr->pBtCsr ){
    assert( bLast==0 );
    rc = btreeCursorFirst(pCsr->pBtCsr);
  }

  if( rc==LSM_OK ){
    rc = multiCursorSetupTree(pCsr, bLast);
  }
  
  return rc;
}


int mcursorSave(MultiCursor *pCsr){
  int rc = LSM_OK;
  if( pCsr->aTree ){
    int iTree = pCsr->aTree[1];
    if( iTree==CURSOR_DATA_TREE0 || iTree==CURSOR_DATA_TREE1 ){
      multiCursorCacheKey(pCsr, &rc);
    }
  }
  mcursorFreeComponents(pCsr);
  return rc;
}

int mcursorRestore(lsm_db *pDb, MultiCursor *pCsr){
  int rc;
  rc = multiCursorInit(pCsr, pDb->pClient);
  if( rc==LSM_OK && pCsr->key.pData ){
    rc = lsmMCursorSeek(pCsr, 
         rtTopic(pCsr->eType), pCsr->key.pData, pCsr->key.nData, +1
    );
  }
  return rc;
}

int lsmSaveCursors(lsm_db *pDb){
  int rc = LSM_OK;
  MultiCursor *pCsr;

  for(pCsr=pDb->pCsr; rc==LSM_OK && pCsr; pCsr=pCsr->pNext){
    rc = mcursorSave(pCsr);
  }
  return rc;
}

int lsmRestoreCursors(lsm_db *pDb){
  int rc = LSM_OK;
  MultiCursor *pCsr;

  for(pCsr=pDb->pCsr; rc==LSM_OK && pCsr; pCsr=pCsr->pNext){
    rc = mcursorRestore(pDb, pCsr);
  }
  return rc;
}

int lsmMCursorFirst(MultiCursor *pCsr){
  return multiCursorEnd(pCsr, 0);
}

int lsmMCursorLast(MultiCursor *pCsr){
  return multiCursorEnd(pCsr, 1);
}

lsm_db *lsmMCursorDb(MultiCursor *pCsr){
  return pCsr->pDb;
}

void lsmMCursorReset(MultiCursor *pCsr){
  int i;
  lsmTreeCursorReset(pCsr->apTreeCsr[0]);
  lsmTreeCursorReset(pCsr->apTreeCsr[1]);
  for(i=0; i<pCsr->nPtr; i++){
    segmentPtrReset(&pCsr->aPtr[i]);
  }
  pCsr->key.nData = 0;
}

static int treeCursorSeek(
  MultiCursor *pCsr,
  TreeCursor *pTreeCsr, 
  void *pKey, int nKey, 
  int eSeek,
  int *pbStop
){
  int rc = LSM_OK;
  if( pTreeCsr ){
    int res = 0;
    lsmTreeCursorSeek(pTreeCsr, pKey, nKey, &res);
    switch( eSeek ){
      case LSM_SEEK_EQ: {
        int eType = lsmTreeCursorFlags(pTreeCsr);
        if( (res<0 && (eType & LSM_START_DELETE))
         || (res>0 && (eType & LSM_END_DELETE))
         || (res==0 && (eType & LSM_POINT_DELETE))
        ){
          *pbStop = 1;
        }else if( res==0 && (eType & LSM_INSERT) ){
          lsm_env *pEnv = pCsr->pDb->pEnv;
          void *p; int n;         /* Key/value from tree-cursor */
          *pbStop = 1;
          pCsr->flags |= CURSOR_SEEK_EQ;
          rc = lsmTreeCursorKey(pTreeCsr, &pCsr->eType, &p, &n);
          if( rc==LSM_OK ) rc = sortedBlobSet(pEnv, &pCsr->key, p, n);
          if( rc==LSM_OK ) rc = lsmTreeCursorValue(pTreeCsr, &p, &n);
          if( rc==LSM_OK ) rc = sortedBlobSet(pEnv, &pCsr->val, p, n);
        }
        lsmTreeCursorReset(pTreeCsr);
        break;
      }
      case LSM_SEEK_GE:
        if( res<0 && lsmTreeCursorValid(pTreeCsr) ){
          lsmTreeCursorNext(pTreeCsr);
        }
        break;
      default:
        if( res>0 ){
          assert( lsmTreeCursorValid(pTreeCsr) );
          lsmTreeCursorPrev(pTreeCsr);
        }
        break;
    }
  }
  return rc;
}


/*
** Seek the cursor.
*/
int lsmMCursorSeek(
  MultiCursor *pCsr, 
  int iTopic, 
  void *pKey, int nKey, 
  int eSeek
){
  int eESeek = eSeek;             /* Effective eSeek parameter */
  int bStop = 0;                  /* Set to true to halt search operation */
  int rc = LSM_OK;                /* Return code */
  int iPtr = 0;                   /* Used to iterate through pCsr->aPtr[] */
  Pgno iPgno = 0;                 /* FC pointer value */

  assert( pCsr->apTreeCsr[0]==0 || iTopic==0 );
  assert( pCsr->apTreeCsr[1]==0 || iTopic==0 );

  if( eESeek==LSM_SEEK_LEFAST ) eESeek = LSM_SEEK_LE;

  assert( eESeek==LSM_SEEK_EQ || eESeek==LSM_SEEK_LE || eESeek==LSM_SEEK_GE );
  assert( (pCsr->flags & CURSOR_FLUSH_FREELIST)==0 );
  assert( pCsr->nPtr==0 || pCsr->aPtr[0].pLevel );

  pCsr->flags &= ~(CURSOR_NEXT_OK | CURSOR_PREV_OK | CURSOR_SEEK_EQ);
  rc = treeCursorSeek(pCsr, pCsr->apTreeCsr[0], pKey, nKey, eESeek, &bStop);
  if( rc==LSM_OK && bStop==0 ){
    rc = treeCursorSeek(pCsr, pCsr->apTreeCsr[1], pKey, nKey, eESeek, &bStop);
  }

  /* Seek all segment pointers. */
  for(iPtr=0; iPtr<pCsr->nPtr && rc==LSM_OK && bStop==0; iPtr++){
    SegmentPtr *pPtr = &pCsr->aPtr[iPtr];
    assert( pPtr->pSeg==&pPtr->pLevel->lhs );
    rc = seekInLevel(pCsr, pPtr, eESeek, iTopic, pKey, nKey, &iPgno, &bStop);
    iPtr += pPtr->pLevel->nRight;
  }

  if( eSeek!=LSM_SEEK_EQ ){
    if( rc==LSM_OK ){
      rc = multiCursorAllocTree(pCsr);
    }
    if( rc==LSM_OK ){
      int i;
      for(i=pCsr->nTree-1; i>0; i--){
        multiCursorDoCompare(pCsr, i, eESeek==LSM_SEEK_LE);
      }
      if( eSeek==LSM_SEEK_GE ) pCsr->flags |= CURSOR_NEXT_OK;
      if( eSeek==LSM_SEEK_LE ) pCsr->flags |= CURSOR_PREV_OK;
    }

    multiCursorCacheKey(pCsr, &rc);
    if( rc==LSM_OK && eSeek!=LSM_SEEK_LEFAST && 0==mcursorLocationOk(pCsr, 0) ){
      switch( eESeek ){
        case LSM_SEEK_EQ:
          lsmMCursorReset(pCsr);
          break;
        case LSM_SEEK_GE:
          rc = lsmMCursorNext(pCsr);
          break;
        default:
          rc = lsmMCursorPrev(pCsr);
          break;
      }
    }
  }

  return rc;
}

int lsmMCursorValid(MultiCursor *pCsr){
  int res = 0;
  if( pCsr->flags & CURSOR_SEEK_EQ ){
    res = 1;
  }else if( pCsr->aTree ){
    int iKey = pCsr->aTree[1];
    if( iKey==CURSOR_DATA_TREE0 || iKey==CURSOR_DATA_TREE1 ){
      res = lsmTreeCursorValid(pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0]);
    }else{
      void *pKey; 
      multiCursorGetKey(pCsr, iKey, 0, &pKey, 0);
      res = pKey!=0;
    }
  }
  return res;
}

static int mcursorAdvanceOk(
  MultiCursor *pCsr, 
  int bReverse,
  int *pRc
){
  void *pNew;                     /* Pointer to buffer containing new key */
  int nNew;                       /* Size of buffer pNew in bytes */
  int eNewType;                   /* Type of new record */

  if( *pRc ) return 1;

  /* Check the current key value. If it is not greater than (if bReverse==0)
  ** or less than (if bReverse!=0) the key currently cached in pCsr->key, 
  ** then the cursor has not yet been successfully advanced.  
  */
  multiCursorGetKey(pCsr, pCsr->aTree[1], &eNewType, &pNew, &nNew);
  if( pNew ){
    int typemask = (pCsr->flags & CURSOR_IGNORE_DELETE) ? ~(0) : LSM_SYSTEMKEY;
    int res = sortedDbKeyCompare(pCsr,
      eNewType & typemask, pNew, nNew, 
      pCsr->eType & typemask, pCsr->key.pData, pCsr->key.nData
    );

    if( (bReverse==0 && res<=0) || (bReverse!=0 && res>=0) ){
      return 0;
    }

    multiCursorCacheKey(pCsr, pRc);
    assert( pCsr->eType==eNewType );

    /* If this cursor is configured to skip deleted keys, and the current
    ** cursor points to a SORTED_DELETE entry, then the cursor has not been 
    ** successfully advanced.  
    **
    ** Similarly, if the cursor is configured to skip system keys and the
    ** current cursor points to a system key, it has not yet been advanced.
    */
    if( *pRc==LSM_OK && 0==mcursorLocationOk(pCsr, 0) ) return 0;
  }
  return 1;
}

static void flCsrAdvance(MultiCursor *pCsr){
  assert( pCsr->flags & CURSOR_FLUSH_FREELIST );
  if( pCsr->iFree % 2 ){
    pCsr->iFree++;
  }else{
    int nEntry = pCsr->pDb->pWorker->freelist.nEntry;
    FreelistEntry *aEntry = pCsr->pDb->pWorker->freelist.aEntry;

    int i = nEntry - 1 - (pCsr->iFree / 2);

    /* If the current entry is a delete and the "end-delete" key will not
    ** be attached to the next entry, increment iFree by 1 only. */
    if( aEntry[i].iId<0 ){
      while( 1 ){
        if( i==0 || aEntry[i-1].iBlk!=aEntry[i].iBlk-1 ){
          pCsr->iFree--;
          break;
        }
        if( aEntry[i-1].iId>=0 ) break;
        pCsr->iFree += 2;
        i--;
      }
    }
    pCsr->iFree += 2;
  }
}

static int multiCursorAdvance(MultiCursor *pCsr, int bReverse){
  int rc = LSM_OK;                /* Return Code */
  if( lsmMCursorValid(pCsr) ){
    do {
      int iKey = pCsr->aTree[1];

      assertCursorTree(pCsr);

      /* If this multi-cursor is advancing forwards, and the sub-cursor
      ** being advanced is the one that separator keys may be being read
      ** from, record the current absolute pointer value.  */
      if( pCsr->pPrevMergePtr ){
        if( iKey==(CURSOR_DATA_SEGMENT+pCsr->nPtr) ){
          assert( pCsr->pBtCsr );
          *pCsr->pPrevMergePtr = pCsr->pBtCsr->iPtr;
        }else if( pCsr->pBtCsr==0 && pCsr->nPtr>0
               && iKey==(CURSOR_DATA_SEGMENT+pCsr->nPtr-1) 
        ){
          SegmentPtr *pPtr = &pCsr->aPtr[iKey-CURSOR_DATA_SEGMENT];
          *pCsr->pPrevMergePtr = pPtr->iPtr+pPtr->iPgPtr;
        }
      }

      if( iKey==CURSOR_DATA_TREE0 || iKey==CURSOR_DATA_TREE1 ){
        TreeCursor *pTreeCsr = pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0];
        if( bReverse ){
          rc = lsmTreeCursorPrev(pTreeCsr);
        }else{
          rc = lsmTreeCursorNext(pTreeCsr);
        }
      }else if( iKey==CURSOR_DATA_SYSTEM ){
        assert( pCsr->flags & CURSOR_FLUSH_FREELIST );
        assert( bReverse==0 );
        flCsrAdvance(pCsr);
      }else if( iKey==(CURSOR_DATA_SEGMENT+pCsr->nPtr) ){
        assert( bReverse==0 && pCsr->pBtCsr );
        rc = btreeCursorNext(pCsr->pBtCsr);
      }else{
        rc = segmentCursorAdvance(pCsr, iKey-CURSOR_DATA_SEGMENT, bReverse);
      }
      if( rc==LSM_OK ){
        int i;
        for(i=(iKey+pCsr->nTree)/2; i>0; i=i/2){
          multiCursorDoCompare(pCsr, i, bReverse);
        }
        assertCursorTree(pCsr);
      }
    }while( mcursorAdvanceOk(pCsr, bReverse, &rc)==0 );
  }
  return rc;
}

int lsmMCursorNext(MultiCursor *pCsr){
  if( (pCsr->flags & CURSOR_NEXT_OK)==0 ) return LSM_MISUSE_BKPT;
  return multiCursorAdvance(pCsr, 0);
}

int lsmMCursorPrev(MultiCursor *pCsr){
  if( (pCsr->flags & CURSOR_PREV_OK)==0 ) return LSM_MISUSE_BKPT;
  return multiCursorAdvance(pCsr, 1);
}

int lsmMCursorKey(MultiCursor *pCsr, void **ppKey, int *pnKey){
  if( (pCsr->flags & CURSOR_SEEK_EQ) || pCsr->aTree==0 ){
    *pnKey = pCsr->key.nData;
    *ppKey = pCsr->key.pData;
  }else{
    int iKey = pCsr->aTree[1];

    if( iKey==CURSOR_DATA_TREE0 || iKey==CURSOR_DATA_TREE1 ){
      TreeCursor *pTreeCsr = pCsr->apTreeCsr[iKey-CURSOR_DATA_TREE0];
      lsmTreeCursorKey(pTreeCsr, 0, ppKey, pnKey);
    }else{
      int nKey;

#ifndef NDEBUG
      void *pKey;
      int eType;
      multiCursorGetKey(pCsr, iKey, &eType, &pKey, &nKey);
      assert( eType==pCsr->eType );
      assert( nKey==pCsr->key.nData );
      assert( memcmp(pKey, pCsr->key.pData, nKey)==0 );
#endif

      nKey = pCsr->key.nData;
      if( nKey==0 ){
        *ppKey = 0;
      }else{
        *ppKey = pCsr->key.pData;
      }
      *pnKey = nKey; 
    }
  }
  return LSM_OK;
}

/*
** Compare the current key that cursor csr points to with pKey/nKey. Set
** *piRes to the result and return LSM_OK.
*/
int lsm_csr_cmp(lsm_cursor *csr, const void *pKey, int nKey, int *piRes){
  MultiCursor *pCsr = (MultiCursor *)csr;
  void *pCsrkey; int nCsrkey;
  int rc;
  rc = lsmMCursorKey(pCsr, &pCsrkey, &nCsrkey);
  if( rc==LSM_OK ){
    int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
    *piRes = sortedKeyCompare(xCmp, 0, pCsrkey, nCsrkey, 0, (void *)pKey, nKey);
  }
  return rc;
}

int lsmMCursorValue(MultiCursor *pCsr, void **ppVal, int *pnVal){
  void *pVal;
  int nVal;
  int rc;
  if( (pCsr->flags & CURSOR_SEEK_EQ) || pCsr->aTree==0 ){
    rc = LSM_OK;
    nVal = pCsr->val.nData;
    pVal = pCsr->val.pData;
  }else{

    assert( pCsr->aTree );
    assert( mcursorLocationOk(pCsr, (pCsr->flags & CURSOR_IGNORE_DELETE)) );

    rc = multiCursorGetVal(pCsr, pCsr->aTree[1], &pVal, &nVal);
    if( pVal && rc==LSM_OK ){
      rc = sortedBlobSet(pCsr->pDb->pEnv, &pCsr->val, pVal, nVal);
      pVal = pCsr->val.pData;
    }

    if( rc!=LSM_OK ){
      pVal = 0;
      nVal = 0;
    }
  }
  *ppVal = pVal;
  *pnVal = nVal;
  return rc;
}

int lsmMCursorType(MultiCursor *pCsr, int *peType){
  assert( pCsr->aTree );
  multiCursorGetKey(pCsr, pCsr->aTree[1], peType, 0, 0);
  return LSM_OK;
}

/*
** Buffer aData[], size nData, is assumed to contain a valid b-tree 
** hierarchy page image. Return the offset in aData[] of the next free
** byte in the data area (where a new cell may be written if there is
** space).
*/
static int mergeWorkerPageOffset(u8 *aData, int nData){
  int nRec;
  int iOff;
  int nKey;
  int eType;

  nRec = lsmGetU16(&aData[SEGMENT_NRECORD_OFFSET(nData)]);
  iOff = lsmGetU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec-1)]);
  eType = aData[iOff++];
  assert( eType==0 
       || eType==(LSM_SYSTEMKEY|LSM_SEPARATOR) 
       || eType==(LSM_SEPARATOR)
  );

  iOff += lsmVarintGet32(&aData[iOff], &nKey);
  iOff += lsmVarintGet32(&aData[iOff], &nKey);

  return iOff + (eType ? nKey : 0);
}

/*
** Following a checkpoint operation, database pages that are part of the
** checkpointed state of the LSM are deemed read-only. This includes the
** right-most page of the b-tree hierarchy of any separators array under
** construction, and all pages between it and the b-tree root, inclusive.
** This is a problem, as when further pages are appended to the separators
** array, entries must be added to the indicated b-tree hierarchy pages.
**
** This function copies all such b-tree pages to new locations, so that
** they can be modified as required.
**
** The complication is that not all database pages are the same size - due
** to the way the file.c module works some (the first and last in each block)
** are 4 bytes smaller than the others.
*/
static int mergeWorkerMoveHierarchy(
  MergeWorker *pMW,               /* Merge worker */
  int bSep                        /* True for separators run */
){
  lsm_db *pDb = pMW->pDb;         /* Database handle */
  int rc = LSM_OK;                /* Return code */
  int i;
  Page **apHier = pMW->hier.apHier;
  int nHier = pMW->hier.nHier;

  for(i=0; rc==LSM_OK && i<nHier; i++){
    Page *pNew = 0;
    rc = lsmFsSortedAppend(pDb->pFS, pDb->pWorker, pMW->pLevel, 1, &pNew);
    assert( rc==LSM_OK );

    if( rc==LSM_OK ){
      u8 *a1; int n1;
      u8 *a2; int n2;

      a1 = fsPageData(pNew, &n1);
      a2 = fsPageData(apHier[i], &n2);

      assert( n1==n2 || n1+4==n2 );

      if( n1==n2 ){
        memcpy(a1, a2, n2);
      }else{
        int nEntry = pageGetNRec(a2, n2);
        int iEof1 = SEGMENT_EOF(n1, nEntry);
        int iEof2 = SEGMENT_EOF(n2, nEntry);

        memcpy(a1, a2, iEof2 - 4);
        memcpy(&a1[iEof1], &a2[iEof2], n2 - iEof2);
      }

      lsmFsPageRelease(apHier[i]);
      apHier[i] = pNew;

#if 0
      assert( n1==n2 || n1+4==n2 || n2+4==n1 );
      if( n1>=n2 ){
        /* If n1 (size of the new page) is equal to or greater than n2 (the
        ** size of the old page), then copy the data into the new page. If
        ** n1==n2, this could be done with a single memcpy(). However, 
        ** since sometimes n1>n2, the page content and footer must be copied 
        ** separately. */
        int nEntry = pageGetNRec(a2, n2);
        int iEof1 = SEGMENT_EOF(n1, nEntry);
        int iEof2 = SEGMENT_EOF(n2, nEntry);
        memcpy(a1, a2, iEof2);
        memcpy(&a1[iEof1], &a2[iEof2], n2 - iEof2);
        lsmFsPageRelease(apHier[i]);
        apHier[i] = pNew;
      }else{
        lsmPutU16(&a1[SEGMENT_FLAGS_OFFSET(n1)], SEGMENT_BTREE_FLAG);
        lsmPutU16(&a1[SEGMENT_NRECORD_OFFSET(n1)], 0);
        lsmPutU64(&a1[SEGMENT_POINTER_OFFSET(n1)], 0);
        i = i - 1;
        lsmFsPageRelease(pNew);
      }
#endif
    }
  }

#ifdef LSM_DEBUG
  if( rc==LSM_OK ){
    for(i=0; i<nHier; i++) assert( lsmFsPageWritable(apHier[i]) );
  }
#endif

  return rc;
}

/*
** Allocate and populate the MergeWorker.apHier[] array.
*/
static int mergeWorkerLoadHierarchy(MergeWorker *pMW){
  int rc = LSM_OK;
  Segment *pSeg;
  Hierarchy *p;
 
  pSeg = &pMW->pLevel->lhs;
  p = &pMW->hier;

  if( p->apHier==0 && pSeg->iRoot!=0 ){
    FileSystem *pFS = pMW->pDb->pFS;
    lsm_env *pEnv = pMW->pDb->pEnv;
    Page **apHier = 0;
    int nHier = 0;
    int iPg = pSeg->iRoot;

    do {
      Page *pPg = 0;
      u8 *aData;
      int nData;
      int flags;

      rc = lsmFsDbPageGet(pFS, pSeg, iPg, &pPg);
      if( rc!=LSM_OK ) break;

      aData = fsPageData(pPg, &nData);
      flags = pageGetFlags(aData, nData);
      if( flags&SEGMENT_BTREE_FLAG ){
        Page **apNew = (Page **)lsmRealloc(
            pEnv, apHier, sizeof(Page *)*(nHier+1)
        );
        if( apNew==0 ){
          rc = LSM_NOMEM_BKPT;
          break;
        }
        apHier = apNew;
        memmove(&apHier[1], &apHier[0], sizeof(Page *) * nHier);
        nHier++;

        apHier[0] = pPg;
        iPg = pageGetPtr(aData, nData);
      }else{
        lsmFsPageRelease(pPg);
        break;
      }
    }while( 1 );

    if( rc==LSM_OK ){
      u8 *aData;
      int nData;
      aData = fsPageData(apHier[0], &nData);
      pMW->aSave[0].iPgno = pageGetPtr(aData, nData);
      p->nHier = nHier;
      p->apHier = apHier;
      rc = mergeWorkerMoveHierarchy(pMW, 0);
    }else{
      int i;
      for(i=0; i<nHier; i++){
        lsmFsPageRelease(apHier[i]);
      }
      lsmFree(pEnv, apHier);
    }
  }

  return rc;
}

/*
** B-tree pages use almost the same format as regular pages. The 
** differences are:
**
**   1. The record format is (usually, see below) as follows:
**
**         + Type byte (always SORTED_SEPARATOR or SORTED_SYSTEM_SEPARATOR),
**         + Absolute pointer value (varint),
**         + Number of bytes in key (varint),
**         + Blob containing key data.
**
**   2. All pointer values are stored as absolute values (not offsets 
**      relative to the footer pointer value).
**
**   3. Each pointer that is part of a record points to a page that 
**      contains keys smaller than the records key (note: not "equal to or
**      smaller than - smaller than").
**
**   4. The pointer in the page footer of a b-tree page points to a page
**      that contains keys equal to or larger than the largest key on the
**      b-tree page.
**
** The reason for having the page footer pointer point to the right-child
** (instead of the left) is that doing things this way makes the 
** mergeWorkerMoveHierarchy() operation less complicated (since the pointers 
** that need to be updated are all stored as fixed-size integers within the 
** page footer, not varints in page records).
**
** Records may not span b-tree pages. If this function is called to add a
** record larger than (page-size / 4) bytes, then a pointer to the indexed
** array page that contains the main record is added to the b-tree instead.
** In this case the record format is:
**
**         + 0x00 byte (1 byte) 
**         + Absolute pointer value (varint),
**         + Absolute page number of page containing key (varint).
**
** See function seekInBtree() for the code that traverses b-tree pages.
*/

static int mergeWorkerBtreeWrite(
  MergeWorker *pMW,
  u8 eType,
  Pgno iPtr,
  Pgno iKeyPg,
  void *pKey,
  int nKey
){
  Hierarchy *p = &pMW->hier;
  lsm_db *pDb = pMW->pDb;         /* Database handle */
  int rc = LSM_OK;                /* Return Code */
  int iLevel;                     /* Level of b-tree hierachy to write to */
  int nData;                      /* Size of aData[] in bytes */
  u8 *aData;                      /* Page data for level iLevel */
  int iOff;                       /* Offset on b-tree page to write record to */
  int nRec;                       /* Initial number of records on b-tree page */

  /* iKeyPg should be zero for an ordinary b-tree key, or non-zero for an
  ** indirect key. The flags byte for an indirect key is 0x00.  */
  assert( (eType==0)==(iKeyPg!=0) );

  /* The MergeWorker.apHier[] array contains the right-most leaf of the b-tree
  ** hierarchy, the root node, and all nodes that lie on the path between.
  ** apHier[0] is the right-most leaf and apHier[pMW->nHier-1] is the current
  ** root page.
  **
  ** This loop searches for a node with enough space to store the key on,
  ** starting with the leaf and iterating up towards the root. When the loop
  ** exits, the key may be written to apHier[iLevel].  */
  for(iLevel=0; iLevel<=p->nHier; iLevel++){
    int nByte;                    /* Number of free bytes required */

    if( iLevel==p->nHier ){
      /* Extend the array and allocate a new root page. */
      Page **aNew;
      aNew = (Page **)lsmRealloc(
          pMW->pDb->pEnv, p->apHier, sizeof(Page *)*(p->nHier+1)
      );
      if( !aNew ){
        return LSM_NOMEM_BKPT;
      }
      p->apHier = aNew;
    }else{
      Page *pOld;
      int nFree;

      /* If the key will fit on this page, break out of the loop here.
      ** The new entry will be written to page apHier[iLevel]. */
      pOld = p->apHier[iLevel];
      assert( lsmFsPageWritable(pOld) );
      aData = fsPageData(pOld, &nData);
      if( eType==0 ){
        nByte = 2 + 1 + lsmVarintLen32(iPtr) + lsmVarintLen32(iKeyPg);
      }else{
        nByte = 2 + 1 + lsmVarintLen32(iPtr) + lsmVarintLen32(nKey) + nKey;
      }
      nRec = pageGetNRec(aData, nData);
      nFree = SEGMENT_EOF(nData, nRec) - mergeWorkerPageOffset(aData, nData);
      if( nByte<=nFree ) break;

      /* Otherwise, this page is full. Set the right-hand-child pointer
      ** to iPtr and release it.  */
      lsmPutU64(&aData[SEGMENT_POINTER_OFFSET(nData)], iPtr);
      assert( lsmFsPageNumber(pOld)==0 );
      rc = lsmFsPagePersist(pOld);
      if( rc==LSM_OK ){
        iPtr = lsmFsPageNumber(pOld);
        lsmFsPageRelease(pOld);
      }
    }

    /* Allocate a new page for apHier[iLevel]. */
    p->apHier[iLevel] = 0;
    if( rc==LSM_OK ){
      rc = lsmFsSortedAppend(
          pDb->pFS, pDb->pWorker, pMW->pLevel, 1, &p->apHier[iLevel]
      );
    }
    if( rc!=LSM_OK ) return rc;

    aData = fsPageData(p->apHier[iLevel], &nData);
    memset(aData, 0, nData);
    lsmPutU16(&aData[SEGMENT_FLAGS_OFFSET(nData)], SEGMENT_BTREE_FLAG);
    lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], 0);

    if( iLevel==p->nHier ){
      p->nHier++;
      break;
    }
  }

  /* Write the key into page apHier[iLevel]. */
  aData = fsPageData(p->apHier[iLevel], &nData);
  iOff = mergeWorkerPageOffset(aData, nData);
  nRec = pageGetNRec(aData, nData);
  lsmPutU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec)], iOff);
  lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], nRec+1);
  if( eType==0 ){
    aData[iOff++] = 0x00;
    iOff += lsmVarintPut32(&aData[iOff], iPtr);
    iOff += lsmVarintPut32(&aData[iOff], iKeyPg);
  }else{
    aData[iOff++] = eType;
    iOff += lsmVarintPut32(&aData[iOff], iPtr);
    iOff += lsmVarintPut32(&aData[iOff], nKey);
    memcpy(&aData[iOff], pKey, nKey);
  }

  return rc;
}

static int mergeWorkerBtreeIndirect(MergeWorker *pMW){
  int rc = LSM_OK;
  if( pMW->iIndirect ){
    Pgno iKeyPg = pMW->aSave[1].iPgno;
    rc = mergeWorkerBtreeWrite(pMW, 0, pMW->iIndirect, iKeyPg, 0, 0);
    pMW->iIndirect = 0;
  }
  return rc;
}

/*
** Append the database key (iTopic/pKey/nKey) to the b-tree under 
** construction. This key has not yet been written to a segment page.
** The pointer that will accompany the new key in the b-tree - that
** points to the completed segment page that contains keys smaller than
** (pKey/nKey) is currently stored in pMW->aSave[0].iPgno.
*/
static int mergeWorkerPushHierarchy(
  MergeWorker *pMW,               /* Merge worker object */
  int iTopic,                     /* Topic value for this key */
  void *pKey,                     /* Pointer to key buffer */
  int nKey                        /* Size of pKey buffer in bytes */
){
  int rc = LSM_OK;                /* Return Code */
  Pgno iPtr;                      /* Pointer value to accompany pKey/nKey */

  assert( pMW->aSave[0].bStore==0 );
  assert( pMW->aSave[1].bStore==0 );
  rc = mergeWorkerBtreeIndirect(pMW);

  /* Obtain the absolute pointer value to store along with the key in the
  ** page body. This pointer points to a page that contains keys that are
  ** smaller than pKey/nKey.  */
  iPtr = pMW->aSave[0].iPgno;
  assert( iPtr!=0 );

  /* Determine if the indirect format should be used. */
  if( (nKey*4 > lsmFsPageSize(pMW->pDb->pFS)) ){
    pMW->iIndirect = iPtr;
    pMW->aSave[1].bStore = 1;
  }else{
    rc = mergeWorkerBtreeWrite(
        pMW, (u8)(iTopic | LSM_SEPARATOR), iPtr, 0, pKey, nKey
    );
  }

  /* Ensure that the SortedRun.iRoot field is correct. */
  return rc;
}

static int mergeWorkerFinishHierarchy(
  MergeWorker *pMW                /* Merge worker object */
){
  int i;                          /* Used to loop through apHier[] */
  int rc = LSM_OK;                /* Return code */
  Pgno iPtr;                      /* New right-hand-child pointer value */

  iPtr = pMW->aSave[0].iPgno;
  for(i=0; i<pMW->hier.nHier && rc==LSM_OK; i++){
    Page *pPg = pMW->hier.apHier[i];
    int nData;                    /* Size of aData[] in bytes */
    u8 *aData;                    /* Page data for pPg */

    aData = fsPageData(pPg, &nData);
    lsmPutU64(&aData[SEGMENT_POINTER_OFFSET(nData)], iPtr);

    rc = lsmFsPagePersist(pPg);
    iPtr = lsmFsPageNumber(pPg);
    lsmFsPageRelease(pPg);
  }

  if( pMW->hier.nHier ){
    pMW->pLevel->lhs.iRoot = iPtr;
    lsmFree(pMW->pDb->pEnv, pMW->hier.apHier);
    pMW->hier.apHier = 0;
    pMW->hier.nHier = 0;
  }

  return rc;
}

static int mergeWorkerAddPadding(
  MergeWorker *pMW                /* Merge worker object */
){
  FileSystem *pFS = pMW->pDb->pFS;
  return lsmFsSortedPadding(pFS, pMW->pDb->pWorker, &pMW->pLevel->lhs);
}

/*
** Release all page references currently held by the merge-worker passed
** as the only argument. Unless an error has occurred, all pages have
** already been released.
*/
static void mergeWorkerReleaseAll(MergeWorker *pMW){
  int i;
  lsmFsPageRelease(pMW->pPage);
  pMW->pPage = 0;

  for(i=0; i<pMW->hier.nHier; i++){
    lsmFsPageRelease(pMW->hier.apHier[i]);
    pMW->hier.apHier[i] = 0;
  }
  lsmFree(pMW->pDb->pEnv, pMW->hier.apHier);
  pMW->hier.apHier = 0;
  pMW->hier.nHier = 0;
}

static int keyszToSkip(FileSystem *pFS, int nKey){
  int nPgsz;                /* Nominal database page size */
  nPgsz = lsmFsPageSize(pFS);
  return LSM_MIN(((nKey * 4) / nPgsz), 3);
}

/*
** Release the reference to the current output page of merge-worker *pMW
** (reference pMW->pPage). Set the page number values in aSave[] as 
** required (see comments above struct MergeWorker for details).
*/
static int mergeWorkerPersistAndRelease(MergeWorker *pMW){
  int rc;
  int i;

  assert( pMW->pPage || (pMW->aSave[0].bStore==0 && pMW->aSave[1].bStore==0) );

  /* Persist the page */
  rc = lsmFsPagePersist(pMW->pPage);

  /* If required, save the page number. */
  for(i=0; i<2; i++){
    if( pMW->aSave[i].bStore ){
      pMW->aSave[i].iPgno = lsmFsPageNumber(pMW->pPage);
      pMW->aSave[i].bStore = 0;
    }
  }

  /* Release the completed output page. */
  lsmFsPageRelease(pMW->pPage);
  pMW->pPage = 0;
  return rc;
}

/*
** Advance to the next page of an output run being populated by merge-worker
** pMW. The footer of the new page is initialized to indicate that it contains
** zero records. The flags field is cleared. The page footer pointer field
** is set to iFPtr.
**
** If successful, LSM_OK is returned. Otherwise, an error code.
*/
static int mergeWorkerNextPage(
  MergeWorker *pMW,               /* Merge worker object to append page to */
  Pgno iFPtr                      /* Pointer value for footer of new page */
){
  int rc = LSM_OK;                /* Return code */
  Page *pNext = 0;                /* New page appended to run */
  lsm_db *pDb = pMW->pDb;         /* Database handle */

  rc = lsmFsSortedAppend(pDb->pFS, pDb->pWorker, pMW->pLevel, 0, &pNext);
  assert( rc || pMW->pLevel->lhs.iFirst>0 || pMW->pDb->compress.xCompress );

  if( rc==LSM_OK ){
    u8 *aData;                    /* Data buffer belonging to page pNext */
    int nData;                    /* Size of aData[] in bytes */

    rc = mergeWorkerPersistAndRelease(pMW);

    pMW->pPage = pNext;
    pMW->pLevel->pMerge->iOutputOff = 0;
    aData = fsPageData(pNext, &nData);
    lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], 0);
    lsmPutU16(&aData[SEGMENT_FLAGS_OFFSET(nData)], 0);
    lsmPutU64(&aData[SEGMENT_POINTER_OFFSET(nData)], iFPtr);
    pMW->nWork++;
  }

  return rc;
}

/*
** Write a blob of data into an output segment being populated by a 
** merge-worker object. If argument bSep is true, write into the separators
** array. Otherwise, the main array.
**
** This function is used to write the blobs of data for keys and values.
*/
static int mergeWorkerData(
  MergeWorker *pMW,               /* Merge worker object */
  int bSep,                       /* True to write to separators run */
  int iFPtr,                      /* Footer ptr for new pages */
  u8 *aWrite,                     /* Write data from this buffer */
  int nWrite                      /* Size of aWrite[] in bytes */
){
  int rc = LSM_OK;                /* Return code */
  int nRem = nWrite;              /* Number of bytes still to write */

  while( nRem>0 ){
    Merge *pMerge = pMW->pLevel->pMerge;
    int nCopy;                    /* Number of bytes to copy */
    u8 *aData;                    /* Pointer to buffer of current output page */
    int nData;                    /* Size of aData[] in bytes */
    int nRec;                     /* Number of records on current output page */
    int iOff;                     /* Offset in aData[] to write to */

    assert( lsmFsPageWritable(pMW->pPage) );
   
    aData = fsPageData(pMW->pPage, &nData);
    nRec = pageGetNRec(aData, nData);
    iOff = pMerge->iOutputOff;
    nCopy = LSM_MIN(nRem, SEGMENT_EOF(nData, nRec) - iOff);

    memcpy(&aData[iOff], &aWrite[nWrite-nRem], nCopy);
    nRem -= nCopy;

    if( nRem>0 ){
      rc = mergeWorkerNextPage(pMW, iFPtr);
    }else{
      pMerge->iOutputOff = iOff + nCopy;
    }
  }

  return rc;
}


/*
** The MergeWorker passed as the only argument is working to merge two or
** more existing segments together (not to flush an in-memory tree). It
** has not yet written the first key to the first page of the output.
*/
static int mergeWorkerFirstPage(MergeWorker *pMW){
  int rc = LSM_OK;                /* Return code */
  Page *pPg = 0;                  /* First page of run pSeg */
  int iFPtr = 0;                  /* Pointer value read from footer of pPg */
  MultiCursor *pCsr = pMW->pCsr;

  assert( pMW->pPage==0 );

  if( pCsr->pBtCsr ){
    rc = LSM_OK;
    iFPtr = pMW->pLevel->pNext->lhs.iFirst;
  }else if( pCsr->nPtr>0 ){
    Segment *pSeg;
    pSeg = pCsr->aPtr[pCsr->nPtr-1].pSeg;
    rc = lsmFsDbPageGet(pMW->pDb->pFS, pSeg, pSeg->iFirst, &pPg);
    if( rc==LSM_OK ){
      u8 *aData;                    /* Buffer for page pPg */
      int nData;                    /* Size of aData[] in bytes */
      aData = fsPageData(pPg, &nData);
      iFPtr = pageGetPtr(aData, nData);
      lsmFsPageRelease(pPg);
    }
  }

  if( rc==LSM_OK ){
    rc = mergeWorkerNextPage(pMW, iFPtr);
    if( pCsr->pPrevMergePtr ) *pCsr->pPrevMergePtr = iFPtr;
    pMW->aSave[0].bStore = 1;
  }

  return rc;
}

static int mergeWorkerWrite(
  MergeWorker *pMW,               /* Merge worker object to write into */
  int eType,                      /* One of SORTED_SEPARATOR, WRITE or DELETE */
  void *pKey, int nKey,           /* Key value */
  void *pVal, int nVal,           /* Value value */
  int iPtr                        /* Absolute value of page pointer, or 0 */
){
  int rc = LSM_OK;                /* Return code */
  Merge *pMerge;                  /* Persistent part of level merge state */
  int nHdr;                       /* Space required for this record header */
  Page *pPg;                      /* Page to write to */
  u8 *aData;                      /* Data buffer for page pWriter->pPage */
  int nData;                      /* Size of buffer aData[] in bytes */
  int nRec;                       /* Number of records on page pPg */
  int iFPtr;                      /* Value of pointer in footer of pPg */
  int iRPtr = 0;                  /* Value of pointer written into record */
  int iOff;                       /* Current write offset within page pPg */
  Segment *pSeg;                  /* Segment being written */
  int flags = 0;                  /* If != 0, flags value for page footer */
  int bFirst = 0;                 /* True for first key of output run */

  pMerge = pMW->pLevel->pMerge;    
  pSeg = &pMW->pLevel->lhs;

  if( pSeg->iFirst==0 && pMW->pPage==0 ){
    rc = mergeWorkerFirstPage(pMW);
    bFirst = 1;
  }
  pPg = pMW->pPage;
  if( pPg ){
    aData = fsPageData(pPg, &nData);
    nRec = pageGetNRec(aData, nData);
    iFPtr = pageGetPtr(aData, nData);
    iRPtr = iPtr - iFPtr;
  }
     
  /* Figure out how much space is required by the new record. The space
  ** required is divided into two sections: the header and the body. The
  ** header consists of the intial varint fields. The body are the blobs 
  ** of data that correspond to the key and value data. The entire header 
  ** must be stored on the page. The body may overflow onto the next and
  ** subsequent pages.
  **
  ** The header space is:
  **
  **     1) record type - 1 byte.
  **     2) Page-pointer-offset - 1 varint
  **     3) Key size - 1 varint
  **     4) Value size - 1 varint (only if LSM_INSERT flag is set)
  */
  if( rc==LSM_OK ){
    nHdr = 1 + lsmVarintLen32(iRPtr) + lsmVarintLen32(nKey);
    if( rtIsWrite(eType) ) nHdr += lsmVarintLen32(nVal);

    /* If the entire header will not fit on page pPg, or if page pPg is 
    ** marked read-only, advance to the next page of the output run. */
    iOff = pMerge->iOutputOff;
    if( iOff<0 || pPg==0 || iOff+nHdr > SEGMENT_EOF(nData, nRec+1) ){
      iFPtr = *pMW->pCsr->pPrevMergePtr;
      iRPtr = iPtr - iFPtr;
      iOff = 0;
      nRec = 0;
      rc = mergeWorkerNextPage(pMW, iFPtr);
      pPg = pMW->pPage;
    }
  }

  /* If this record header will be the first on the page, and the page is 
  ** not the very first in the entire run, add a copy of the key to the
  ** b-tree hierarchy.
  */
  if( rc==LSM_OK && nRec==0 && bFirst==0 ){
    assert( pMerge->nSkip>=0 );

    if( pMerge->nSkip==0 ){
      rc = mergeWorkerPushHierarchy(pMW, rtTopic(eType), pKey, nKey);
      assert( pMW->aSave[0].bStore==0 );
      pMW->aSave[0].bStore = 1;
      pMerge->nSkip = keyszToSkip(pMW->pDb->pFS, nKey);
    }else{
      pMerge->nSkip--;
      flags = PGFTR_SKIP_THIS_FLAG;
    }

    if( pMerge->nSkip ) flags |= PGFTR_SKIP_NEXT_FLAG;
  }

  /* Update the output segment */
  if( rc==LSM_OK ){
    aData = fsPageData(pPg, &nData);

    /* Update the page footer. */
    lsmPutU16(&aData[SEGMENT_NRECORD_OFFSET(nData)], nRec+1);
    lsmPutU16(&aData[SEGMENT_CELLPTR_OFFSET(nData, nRec)], iOff);
    if( flags ) lsmPutU16(&aData[SEGMENT_FLAGS_OFFSET(nData)], flags);

    /* Write the entry header into the current page. */
    aData[iOff++] = eType;                                               /* 1 */
    iOff += lsmVarintPut32(&aData[iOff], iRPtr);                         /* 2 */
    iOff += lsmVarintPut32(&aData[iOff], nKey);                          /* 3 */
    if( rtIsWrite(eType) ) iOff += lsmVarintPut32(&aData[iOff], nVal);   /* 4 */
    pMerge->iOutputOff = iOff;

    /* Write the key and data into the segment. */
    assert( iFPtr==pageGetPtr(aData, nData) );
    rc = mergeWorkerData(pMW, 0, iFPtr+iRPtr, pKey, nKey);
    if( rc==LSM_OK && rtIsWrite(eType) ){
      if( rc==LSM_OK ){
        rc = mergeWorkerData(pMW, 0, iFPtr+iRPtr, pVal, nVal);
      }
    }
  }

  return rc;
}


/*
** Free all resources allocated by mergeWorkerInit().
*/
static void mergeWorkerShutdown(MergeWorker *pMW, int *pRc){
  int i;                          /* Iterator variable */
  int rc = *pRc;
  MultiCursor *pCsr = pMW->pCsr;

  /* Unless the merge has finished, save the cursor position in the
  ** Merge.aInput[] array. See function mergeWorkerInit() for the 
  ** code to restore a cursor position based on aInput[].  */
  if( rc==LSM_OK && pCsr && lsmMCursorValid(pCsr) ){
    Merge *pMerge = pMW->pLevel->pMerge;
    int bBtree = (pCsr->pBtCsr!=0);
    int iPtr;

    /* pMerge->nInput==0 indicates that this is a FlushTree() operation. */
    assert( pMerge->nInput==0 || pMW->pLevel->nRight>0 );
    assert( pMerge->nInput==0 || pMerge->nInput==(pCsr->nPtr+bBtree) );

    for(i=0; i<(pMerge->nInput-bBtree); i++){
      SegmentPtr *pPtr = &pCsr->aPtr[i];
      if( pPtr->pPg ){
        pMerge->aInput[i].iPg = lsmFsPageNumber(pPtr->pPg);
        pMerge->aInput[i].iCell = pPtr->iCell;
      }else{
        pMerge->aInput[i].iPg = 0;
        pMerge->aInput[i].iCell = 0;
      }
    }
    if( bBtree && pMerge->nInput ){
      assert( i==pCsr->nPtr );
      btreeCursorPosition(pCsr->pBtCsr, &pMerge->aInput[i]);
    }

    /* Store the location of the split-key */
    iPtr = pCsr->aTree[1] - CURSOR_DATA_SEGMENT;
    if( iPtr<pCsr->nPtr ){
      pMerge->splitkey = pMerge->aInput[iPtr];
    }else{
      btreeCursorSplitkey(pCsr->pBtCsr, &pMerge->splitkey);
    }
    
    pMerge->iOutputOff = -1;
  }

  lsmMCursorClose(pCsr, 0);

  /* Persist and release the output page. */
  if( rc==LSM_OK ) rc = mergeWorkerPersistAndRelease(pMW);
  if( rc==LSM_OK ) rc = mergeWorkerBtreeIndirect(pMW);
  if( rc==LSM_OK ) rc = mergeWorkerFinishHierarchy(pMW);
  if( rc==LSM_OK ) rc = mergeWorkerAddPadding(pMW);
  lsmFsFlushWaiting(pMW->pDb->pFS, &rc);
  mergeWorkerReleaseAll(pMW);

  lsmFree(pMW->pDb->pEnv, pMW->aGobble);
  pMW->aGobble = 0;
  pMW->pCsr = 0;

  *pRc = rc;
}

/*
** The cursor passed as the first argument is being used as the input for
** a merge operation. When this function is called, *piFlags contains the
** database entry flags for the current entry. The entry about to be written
** to the output.
**
** Note that this function only has to work for cursors configured to 
** iterate forwards (not backwards).
*/
static void mergeRangeDeletes(MultiCursor *pCsr, int *piVal, int *piFlags){
  int f = *piFlags;
  int iKey = pCsr->aTree[1];
  int i;

  assert( pCsr->flags & CURSOR_NEXT_OK );
  if( pCsr->flags & CURSOR_IGNORE_DELETE ){
    /* The ignore-delete flag is set when the output of the merge will form
    ** the oldest level in the database. In this case there is no point in
    ** retaining any range-delete flags.  */
    assert( (f & LSM_POINT_DELETE)==0 );
    f &= ~(LSM_START_DELETE|LSM_END_DELETE);
  }else{
    for(i=0; i<(CURSOR_DATA_SEGMENT + pCsr->nPtr); i++){
      if( i!=iKey ){
        int eType;
        void *pKey;
        int nKey;
        int res;
        multiCursorGetKey(pCsr, i, &eType, &pKey, &nKey);

        if( pKey ){
          res = sortedKeyCompare(pCsr->pDb->xCmp, 
              rtTopic(pCsr->eType), pCsr->key.pData, pCsr->key.nData,
              rtTopic(eType), pKey, nKey
          );
          assert( res<=0 );
          if( res==0 ){
            if( (f & (LSM_INSERT|LSM_POINT_DELETE))==0 ){
              if( eType & LSM_INSERT ){
                f |= LSM_INSERT;
                *piVal = i;
              }
              else if( eType & LSM_POINT_DELETE ){
                f |= LSM_POINT_DELETE;
              }
            }
            f |= (eType & (LSM_END_DELETE|LSM_START_DELETE));
          }

          if( i>iKey && (eType & LSM_END_DELETE) && res<0 ){
            if( f & (LSM_INSERT|LSM_POINT_DELETE) ){
              f |= (LSM_END_DELETE|LSM_START_DELETE);
            }else{
              f = 0;
            }
            break;
          }
        }
      }
    }

    assert( (f & LSM_INSERT)==0 || (f & LSM_POINT_DELETE)==0 );
    if( (f & LSM_START_DELETE) 
     && (f & LSM_END_DELETE) 
     && (f & LSM_POINT_DELETE )
    ){
      f = 0;
    }
  }

  *piFlags = f;
}

static int mergeWorkerStep(MergeWorker *pMW){
  lsm_db *pDb = pMW->pDb;       /* Database handle */
  MultiCursor *pCsr;            /* Cursor to read input data from */
  int rc = LSM_OK;              /* Return code */
  int eType;                    /* SORTED_SEPARATOR, WRITE or DELETE */
  void *pKey; int nKey;         /* Key */
  Pgno iPtr;
  int iVal;

  pCsr = pMW->pCsr;

  /* Pull the next record out of the source cursor. */
  lsmMCursorKey(pCsr, &pKey, &nKey);
  eType = pCsr->eType;

  /* Figure out if the output record may have a different pointer value
  ** than the previous. This is the case if the current key is identical to
  ** a key that appears in the lowest level run being merged. If so, set 
  ** iPtr to the absolute pointer value. If not, leave iPtr set to zero, 
  ** indicating that the output pointer value should be a copy of the pointer 
  ** value written with the previous key.  */
  iPtr = (pCsr->pPrevMergePtr ? *pCsr->pPrevMergePtr : 0);
  if( pCsr->pBtCsr ){
    BtreeCursor *pBtCsr = pCsr->pBtCsr;
    if( pBtCsr->pKey ){
      int res = rtTopic(pBtCsr->eType) - rtTopic(eType);
      if( res==0 ) res = pDb->xCmp(pBtCsr->pKey, pBtCsr->nKey, pKey, nKey);
      if( 0==res ) iPtr = pBtCsr->iPtr;
      assert( res>=0 );
    }
  }else if( pCsr->nPtr ){
    SegmentPtr *pPtr = &pCsr->aPtr[pCsr->nPtr-1];
    if( pPtr->pPg
     && 0==pDb->xCmp(pPtr->pKey, pPtr->nKey, pKey, nKey)
    ){
      iPtr = pPtr->iPtr+pPtr->iPgPtr;
    }
  }

  iVal = pCsr->aTree[1];
  mergeRangeDeletes(pCsr, &iVal, &eType);

  if( eType!=0 ){
    if( pMW->aGobble ){
      int iGobble = pCsr->aTree[1] - CURSOR_DATA_SEGMENT;
      if( iGobble<pCsr->nPtr && iGobble>=0 ){
        SegmentPtr *pGobble = &pCsr->aPtr[iGobble];
        if( (pGobble->flags & PGFTR_SKIP_THIS_FLAG)==0 ){
          pMW->aGobble[iGobble] = lsmFsPageNumber(pGobble->pPg);
        }
      }
    }

    /* If this is a separator key and we know that the output pointer has not
    ** changed, there is no point in writing an output record. Otherwise,
    ** proceed. */
    if( rc==LSM_OK && (rtIsSeparator(eType)==0 || iPtr!=0) ){
      /* Write the record into the main run. */
      void *pVal; int nVal;
      rc = multiCursorGetVal(pCsr, iVal, &pVal, &nVal);
      if( pVal && rc==LSM_OK ){
        assert( nVal>=0 );
        rc = sortedBlobSet(pDb->pEnv, &pCsr->val, pVal, nVal);
        pVal = pCsr->val.pData;
      }
      if( rc==LSM_OK ){
        rc = mergeWorkerWrite(pMW, eType, pKey, nKey, pVal, nVal, iPtr);
      }
    }
  }

  /* Advance the cursor to the next input record (assuming one exists). */
  assert( lsmMCursorValid(pMW->pCsr) );
  if( rc==LSM_OK ) rc = lsmMCursorNext(pMW->pCsr);

  return rc;
}

static int mergeWorkerDone(MergeWorker *pMW){
  return pMW->pCsr==0 || !lsmMCursorValid(pMW->pCsr);
}

static void sortedFreeLevel(lsm_env *pEnv, Level *p){
  if( p ){
    lsmFree(pEnv, p->pSplitKey);
    lsmFree(pEnv, p->pMerge);
    lsmFree(pEnv, p->aRhs);
    lsmFree(pEnv, p);
  }
}

static void sortedInvokeWorkHook(lsm_db *pDb){
  if( pDb->xWork ){
    pDb->xWork(pDb, pDb->pWorkCtx);
  }
}

static int sortedNewToplevel(
  lsm_db *pDb,                    /* Connection handle */
  int eTree,                      /* One of the TREE_XXX constants */
  int *pnWrite                    /* OUT: Number of database pages written */
){
  int rc = LSM_OK;                /* Return Code */
  MultiCursor *pCsr = 0;
  Level *pNext = 0;               /* The current top level */
  Level *pNew;                    /* The new level itself */
  Segment *pLinked = 0;           /* Delete separators from this segment */
  Level *pDel = 0;                /* Delete this entire level */
  int nWrite = 0;                 /* Number of database pages written */
  Freelist freelist;

  if( eTree!=TREE_NONE ){
    rc = lsmShmCacheChunks(pDb, pDb->treehdr.nChunk);
  }

  assert( pDb->bUseFreelist==0 );
  pDb->pFreelist = &freelist;
  pDb->bUseFreelist = 1;
  memset(&freelist, 0, sizeof(freelist));

  /* Allocate the new level structure to write to. */
  pNext = lsmDbSnapshotLevel(pDb->pWorker);
  pNew = (Level *)lsmMallocZeroRc(pDb->pEnv, sizeof(Level), &rc);
  if( pNew ){
    pNew->pNext = pNext;
    lsmDbSnapshotSetLevel(pDb->pWorker, pNew);
  }

  /* Create a cursor to gather the data required by the new segment. The new
  ** segment contains everything in the tree and pointers to the next segment
  ** in the database (if any).  */
  pCsr = multiCursorNew(pDb, &rc);
  if( pCsr ){
    pCsr->pDb = pDb;
    rc = multiCursorVisitFreelist(pCsr);
    if( rc==LSM_OK ){
      rc = multiCursorAddTree(pCsr, pDb->pWorker, eTree);
    }
    if( rc==LSM_OK && pNext && pNext->pMerge==0 ){
      if( (pNext->flags & LEVEL_FREELIST_ONLY) ){
        pDel = pNext;
        pCsr->aPtr = lsmMallocZeroRc(pDb->pEnv, sizeof(SegmentPtr), &rc);
        multiCursorAddOne(pCsr, pNext, &rc);
      }else if( eTree!=TREE_NONE && pNext->lhs.iRoot ){
        pLinked = &pNext->lhs;
        rc = btreeCursorNew(pDb, pLinked, &pCsr->pBtCsr);
      }
    }

    /* If this will be the only segment in the database, discard any delete
    ** markers present in the in-memory tree.  */
    if( pNext==0 ){
      multiCursorIgnoreDelete(pCsr);
    }
  }

  if( rc!=LSM_OK ){
    lsmMCursorClose(pCsr, 0);
  }else{
    Pgno iLeftPtr = 0;
    Merge merge;                  /* Merge object used to create new level */
    MergeWorker mergeworker;      /* MergeWorker object for the same purpose */

    memset(&merge, 0, sizeof(Merge));
    memset(&mergeworker, 0, sizeof(MergeWorker));

    pNew->pMerge = &merge;
    pNew->flags |= LEVEL_INCOMPLETE;
    mergeworker.pDb = pDb;
    mergeworker.pLevel = pNew;
    mergeworker.pCsr = pCsr;
    pCsr->pPrevMergePtr = &iLeftPtr;

    /* Mark the separators array for the new level as a "phantom". */
    mergeworker.bFlush = 1;

    /* Do the work to create the new merged segment on disk */
    if( rc==LSM_OK ) rc = lsmMCursorFirst(pCsr);
    while( rc==LSM_OK && mergeWorkerDone(&mergeworker)==0 ){
      rc = mergeWorkerStep(&mergeworker);
    }
    mergeWorkerShutdown(&mergeworker, &rc);
    assert( rc!=LSM_OK || mergeworker.nWork==0 || pNew->lhs.iFirst );
    if( rc==LSM_OK && pNew->lhs.iFirst ){
      rc = lsmFsSortedFinish(pDb->pFS, &pNew->lhs);
    }
    nWrite = mergeworker.nWork;
    pNew->flags &= ~LEVEL_INCOMPLETE;
    if( eTree==TREE_NONE ){
      pNew->flags |= LEVEL_FREELIST_ONLY;
    }
    pNew->pMerge = 0;
  }

  if( rc!=LSM_OK || pNew->lhs.iFirst==0 ){
    assert( rc!=LSM_OK || pDb->pWorker->freelist.nEntry==0 );
    lsmDbSnapshotSetLevel(pDb->pWorker, pNext);
    sortedFreeLevel(pDb->pEnv, pNew);
  }else{
    if( pLinked ){
      pLinked->iRoot = 0;
    }else if( pDel ){
      assert( pNew->pNext==pDel );
      pNew->pNext = pDel->pNext;
      lsmFsSortedDelete(pDb->pFS, pDb->pWorker, 1, &pDel->lhs);
      sortedFreeLevel(pDb->pEnv, pDel);
    }

#if LSM_LOG_STRUCTURE
    lsmSortedDumpStructure(pDb, pDb->pWorker, LSM_LOG_DATA, 0, "new-toplevel");
#endif

    if( freelist.nEntry ){
      Freelist *p = &pDb->pWorker->freelist;
      lsmFree(pDb->pEnv, p->aEntry);
      memcpy(p, &freelist, sizeof(freelist));
      freelist.aEntry = 0;
    }else{
      pDb->pWorker->freelist.nEntry = 0;
    }

    assertBtreeOk(pDb, &pNew->lhs);
    sortedInvokeWorkHook(pDb);
  }

  if( pnWrite ) *pnWrite = nWrite;
  pDb->pWorker->nWrite += nWrite;
  pDb->pFreelist = 0;
  pDb->bUseFreelist = 0;
  lsmFree(pDb->pEnv, freelist.aEntry);
  return rc;
}

/*
** The nMerge levels in the LSM beginning with pLevel consist of a
** left-hand-side segment only. Replace these levels with a single new
** level consisting of a new empty segment on the left-hand-side and the
** nMerge segments from the replaced levels on the right-hand-side.
**
** Also, allocate and populate a Merge object and set Level.pMerge to
** point to it.
*/
static int sortedMergeSetup(
  lsm_db *pDb,                    /* Database handle */
  Level *pLevel,                  /* First level to merge */
  int nMerge,                     /* Merge this many levels together */
  Level **ppNew                   /* New, merged, level */
){
  int rc = LSM_OK;                /* Return Code */
  Level *pNew;                    /* New Level object */
  int bUseNext = 0;               /* True to link in next separators */
  Merge *pMerge;                  /* New Merge object */
  int nByte;                      /* Bytes of space allocated at pMerge */

#ifdef LSM_DEBUG
  int iLevel;
  Level *pX = pLevel;
  for(iLevel=0; iLevel<nMerge; iLevel++){
    assert( pX->nRight==0 );
    pX = pX->pNext;
  }
#endif

  /* Allocate the new Level object */
  pNew = (Level *)lsmMallocZeroRc(pDb->pEnv, sizeof(Level), &rc);
  if( pNew ){
    pNew->aRhs = (Segment *)lsmMallocZeroRc(pDb->pEnv, 
                                        nMerge * sizeof(Segment), &rc);
  }

  /* Populate the new Level object */
  if( rc==LSM_OK ){
    Level *pNext = 0;             /* Level following pNew */
    int i;
    int bFreeOnly = 1;
    Level *pTopLevel;
    Level *p = pLevel;
    Level **pp;
    pNew->nRight = nMerge;
    pNew->iAge = pLevel->iAge+1;
    for(i=0; i<nMerge; i++){
      assert( p->nRight==0 );
      pNext = p->pNext;
      pNew->aRhs[i] = p->lhs;
      if( (p->flags & LEVEL_FREELIST_ONLY)==0 ) bFreeOnly = 0;
      sortedFreeLevel(pDb->pEnv, p);
      p = pNext;
    }

    if( bFreeOnly ) pNew->flags |= LEVEL_FREELIST_ONLY;

    /* Replace the old levels with the new. */
    pTopLevel = lsmDbSnapshotLevel(pDb->pWorker);
    pNew->pNext = p;
    for(pp=&pTopLevel; *pp!=pLevel; pp=&((*pp)->pNext));
    *pp = pNew;
    lsmDbSnapshotSetLevel(pDb->pWorker, pTopLevel);

    /* Determine whether or not the next separators will be linked in */
    if( pNext && pNext->pMerge==0 && pNext->lhs.iRoot && pNext 
     && (bFreeOnly==0 || (pNext->flags & LEVEL_FREELIST_ONLY))
    ){
      bUseNext = 1;
    }
  }

  /* Allocate the merge object */
  nByte = sizeof(Merge) + sizeof(MergeInput) * (nMerge + bUseNext);
  pMerge = (Merge *)lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
  if( pMerge ){
    pMerge->aInput = (MergeInput *)&pMerge[1];
    pMerge->nInput = nMerge + bUseNext;
    pNew->pMerge = pMerge;
  }

  *ppNew = pNew;
  return rc;
}

static int mergeWorkerInit(
  lsm_db *pDb,                    /* Db connection to do merge work */
  Level *pLevel,                  /* Level to work on merging */
  MergeWorker *pMW                /* Object to initialize */
){
  int rc = LSM_OK;                /* Return code */
  Merge *pMerge = pLevel->pMerge; /* Persistent part of merge state */
  MultiCursor *pCsr = 0;          /* Cursor opened for pMW */
  Level *pNext = pLevel->pNext;   /* Next level in LSM */

  assert( pDb->pWorker );
  assert( pLevel->pMerge );
  assert( pLevel->nRight>0 );

  memset(pMW, 0, sizeof(MergeWorker));
  pMW->pDb = pDb;
  pMW->pLevel = pLevel;
  pMW->aGobble = lsmMallocZeroRc(pDb->pEnv, sizeof(Pgno) * pLevel->nRight, &rc);

  /* Create a multi-cursor to read the data to write to the new
  ** segment. The new segment contains:
  **
  **   1. Records from LHS of each of the nMerge levels being merged.
  **   2. Separators from either the last level being merged, or the
  **      separators attached to the LHS of the following level, or neither.
  **
  ** If the new level is the lowest (oldest) in the db, discard any
  ** delete keys. Key annihilation.
  */
  pCsr = multiCursorNew(pDb, &rc);
  if( pCsr ){
    pCsr->flags |= CURSOR_NEXT_OK;
    rc = multiCursorAddRhs(pCsr, pLevel);
  }
  if( rc==LSM_OK && pMerge->nInput > pLevel->nRight ){
    rc = btreeCursorNew(pDb, &pNext->lhs, &pCsr->pBtCsr);
  }else if( pNext ){
    multiCursorReadSeparators(pCsr);
  }else{
    multiCursorIgnoreDelete(pCsr);
  }

  assert( rc!=LSM_OK || pMerge->nInput==(pCsr->nPtr+(pCsr->pBtCsr!=0)) );
  pMW->pCsr = pCsr;

  /* Load the b-tree hierarchy into memory. */
  if( rc==LSM_OK ) rc = mergeWorkerLoadHierarchy(pMW);
  if( rc==LSM_OK && pMW->hier.nHier==0 ){
    pMW->aSave[0].iPgno = pLevel->lhs.iFirst;
  }

  /* Position the cursor. */
  if( rc==LSM_OK ){
    pCsr->pPrevMergePtr = &pMerge->iCurrentPtr;
    if( pLevel->lhs.iFirst==0 ){
      /* The output array is still empty. So position the cursor at the very 
      ** start of the input.  */
      rc = multiCursorEnd(pCsr, 0);
    }else{
      /* The output array is non-empty. Position the cursor based on the
      ** page/cell data saved in the Merge.aInput[] array.  */
      int i;
      for(i=0; rc==LSM_OK && i<pCsr->nPtr; i++){
        MergeInput *pInput = &pMerge->aInput[i];
        if( pInput->iPg ){
          SegmentPtr *pPtr;
          assert( pCsr->aPtr[i].pPg==0 );
          pPtr = &pCsr->aPtr[i];
          rc = segmentPtrLoadPage(pDb->pFS, pPtr, pInput->iPg);
          if( rc==LSM_OK && pPtr->nCell>0 ){
            rc = segmentPtrLoadCell(pPtr, pInput->iCell);
          }
        }
      }

      if( rc==LSM_OK && pCsr->pBtCsr ){
        int (*xCmp)(void *, int, void *, int) = pCsr->pDb->xCmp;
        assert( i==pCsr->nPtr );
        rc = btreeCursorRestore(pCsr->pBtCsr, xCmp, &pMerge->aInput[i]);
      }

      if( rc==LSM_OK ){
        rc = multiCursorSetupTree(pCsr, 0);
      }
    }
    pCsr->flags |= CURSOR_NEXT_OK;
  }

  return rc;
}

static int sortedBtreeGobble(
  lsm_db *pDb,                    /* Worker connection */
  MultiCursor *pCsr,              /* Multi-cursor being used for a merge */
  int iGobble                     /* pCsr->aPtr[] entry to operate on */
){
  int rc = LSM_OK;
  if( rtTopic(pCsr->eType)==0 ){
    Segment *pSeg = pCsr->aPtr[iGobble].pSeg;
    Pgno *aPg;
    int nPg;

    /* Seek from the root of the b-tree to the segment leaf that may contain
    ** a key equal to the one multi-cursor currently points to. Record the
    ** page number of each b-tree page and the leaf. The segment may be
    ** gobbled up to (but not including) the first of these page numbers.
    */
    assert( pSeg->iRoot>0 );
    aPg = lsmMallocZeroRc(pDb->pEnv, sizeof(Pgno)*32, &rc);
    if( rc==LSM_OK ){
      rc = seekInBtree(pCsr, pSeg, 
          rtTopic(pCsr->eType), pCsr->key.pData, pCsr->key.nData, aPg, 0
      ); 
    }

    if( rc==LSM_OK ){
      for(nPg=0; aPg[nPg]; nPg++);
      lsmFsGobble(pDb, pSeg, aPg, nPg);
    }

    lsmFree(pDb->pEnv, aPg);
  }
  return rc;
}

/*
** Argument p points to a level of age N. Return the number of levels in
** the linked list starting at p that have age=N (always at least 1).
*/
static int sortedCountLevels(Level *p){
  int iAge = p->iAge;
  int nRet = 0;
  do {
    nRet++;
    p = p->pNext;
  }while( p && p->iAge==iAge );
  return nRet;
}

static int sortedSelectLevel(lsm_db *pDb, int nMerge, Level **ppOut){
  Level *pTopLevel = lsmDbSnapshotLevel(pDb->pWorker);
  int rc = LSM_OK;
  Level *pLevel = 0;            /* Output value */
  Level *pBest = 0;             /* Best level to work on found so far */
  int nBest;                    /* Number of segments merged at pBest */
  Level *pThis = 0;             /* First in run of levels with age=iAge */
  int nThis = 0;                /* Number of levels starting at pThis */

  assert( nMerge>=1 );
  nBest = LSM_MAX(1, nMerge-1);

  /* Find the longest contiguous run of levels not currently undergoing a 
  ** merge with the same age in the structure. Or the level being merged
  ** with the largest number of right-hand segments. Work on it. */
  for(pLevel=pTopLevel; pLevel; pLevel=pLevel->pNext){
    if( pLevel->nRight==0 && pThis && pLevel->iAge==pThis->iAge ){
      nThis++;
    }else{
      if( nThis>nBest ){
        if( (pLevel->iAge!=pThis->iAge+1)
         || (pLevel->nRight==0 && sortedCountLevels(pLevel)<=pDb->nMerge)
        ){
          pBest = pThis;
          nBest = nThis;
        }
      }
      if( pLevel->nRight ){
        if( pLevel->nRight>nBest ){
          nBest = pLevel->nRight;
          pBest = pLevel;
        }
        nThis = 0;
        pThis = 0;
      }else{
        pThis = pLevel;
        nThis = 1;
      }
    }
  }
  if( nThis>nBest ){
    assert( pThis );
    pBest = pThis;
    nBest = nThis;
  }

  if( pBest==0 && nMerge==1 ){
    int nFree = 0;
    int nUsr = 0;
    for(pLevel=pTopLevel; pLevel; pLevel=pLevel->pNext){
      assert( !pLevel->nRight );
      if( pLevel->flags & LEVEL_FREELIST_ONLY ){
        nFree++;
      }else{
        nUsr++;
      }
    }
    if( nUsr>1 ){
      pBest = pTopLevel;
      nBest = nFree + nUsr;
    }
  }

  if( pBest ){
    if( pBest->nRight==0 ){
      rc = sortedMergeSetup(pDb, pBest, nBest, ppOut);
    }else{
      *ppOut = pBest;
    }
  }

  return rc;
}

static int sortedDbIsFull(lsm_db *pDb){
  Level *pTop = lsmDbSnapshotLevel(pDb->pWorker);

  if( lsmDatabaseFull(pDb) ) return 1;
  if( pTop && pTop->iAge==0
   && (pTop->nRight || sortedCountLevels(pTop)>=pDb->nMerge)
  ){
    return 1;
  }
  return 0;
}

typedef struct MoveBlockCtx MoveBlockCtx;
struct MoveBlockCtx {
  int iSeen;                      /* Previous free block on list */
  int iFrom;                      /* Total number of blocks in file */
};

static int moveBlockCb(void *pCtx, int iBlk, i64 iSnapshot){
  MoveBlockCtx *p = (MoveBlockCtx *)pCtx;
  assert( p->iFrom==0 );
  if( iBlk==(p->iSeen-1) ){
    p->iSeen = iBlk;
    return 0;
  }
  p->iFrom = p->iSeen-1;
  return 1;
}

/*
** This function is called to further compact a database for which all 
** of the content has already been merged into a single segment. If 
** possible, it moves the contents of a single block from the end of the
** file to a free-block that lies closer to the start of the file (allowing
** the file to be eventually truncated).
*/
static int sortedMoveBlock(lsm_db *pDb, int *pnWrite){
  Snapshot *p = pDb->pWorker;
  Level *pLvl = lsmDbSnapshotLevel(p);
  int iFrom;                      /* Block to move */
  int iTo;                        /* Destination to move block to */
  int rc;                         /* Return code */

  MoveBlockCtx sCtx;

  assert( pLvl->pNext==0 && pLvl->nRight==0 );
  assert( p->redirect.n<=LSM_MAX_BLOCK_REDIRECTS );

  *pnWrite = 0;

  /* Check that the redirect array is not already full. If it is, return
  ** without moving any database content.  */
  if( p->redirect.n>=LSM_MAX_BLOCK_REDIRECTS ) return LSM_OK;

  /* Find the last block of content in the database file. Do this by 
  ** traversing the free-list in reverse (descending block number) order.
  ** The first block not on the free list is the one that will be moved.
  ** Since the db consists of a single segment, there is no ambiguity as
  ** to which segment the block belongs to.  */
  sCtx.iSeen = p->nBlock+1;
  sCtx.iFrom = 0;
  rc = lsmWalkFreelist(pDb, 1, moveBlockCb, &sCtx);
  if( rc!=LSM_OK || sCtx.iFrom==0 ) return rc;
  iFrom = sCtx.iFrom;

  /* Find the first free block in the database, ignoring block 1. Block
  ** 1 is tricky as it is smaller than the other blocks.  */
  rc = lsmBlockAllocate(pDb, iFrom, &iTo);
  if( rc!=LSM_OK || iTo==0 ) return rc;
  assert( iTo!=1 && iTo<iFrom );

  rc = lsmFsMoveBlock(pDb->pFS, &pLvl->lhs, iTo, iFrom);
  if( rc==LSM_OK ){
    if( p->redirect.a==0 ){
      int nByte = sizeof(struct RedirectEntry) * LSM_MAX_BLOCK_REDIRECTS;
      p->redirect.a = lsmMallocZeroRc(pDb->pEnv, nByte, &rc);
    }
    if( rc==LSM_OK ){

      /* Check if the block just moved was already redirected. */
      int i;
      for(i=0; i<p->redirect.n; i++){
        if( p->redirect.a[i].iTo==iFrom ) break;
      }

      if( i==p->redirect.n ){
        /* Block iFrom was not already redirected. Add a new array entry. */
        memmove(&p->redirect.a[1], &p->redirect.a[0], 
            sizeof(struct RedirectEntry) * p->redirect.n
            );
        p->redirect.a[0].iFrom = iFrom;
        p->redirect.a[0].iTo = iTo;
        p->redirect.n++;
      }else{
        /* Block iFrom was already redirected. Overwrite existing entry. */
        p->redirect.a[i].iTo = iTo;
      }

      rc = lsmBlockFree(pDb, iFrom);

      *pnWrite = lsmFsBlockSize(pDb->pFS) / lsmFsPageSize(pDb->pFS);
      pLvl->lhs.pRedirect = &p->redirect;
    }
  }

#if LSM_LOG_STRUCTURE
  if( rc==LSM_OK ){
    char aBuf[64];
    sprintf(aBuf, "move-block %d/%d", p->redirect.n-1, LSM_MAX_BLOCK_REDIRECTS);
    lsmSortedDumpStructure(pDb, pDb->pWorker, LSM_LOG_DATA, 0, aBuf);
  }
#endif
  return rc;
}

/*
*/
static int mergeInsertFreelistSegments(
  lsm_db *pDb, 
  int nFree,
  MergeWorker *pMW
){
  int rc = LSM_OK;
  if( nFree>0 ){
    MultiCursor *pCsr = pMW->pCsr;
    Level *pLvl = pMW->pLevel;
    SegmentPtr *aNew1;
    Segment *aNew2;

    Level *pIter;
    Level *pNext;
    int i = 0;

    aNew1 = (SegmentPtr *)lsmMallocZeroRc(
        pDb->pEnv, sizeof(SegmentPtr) * (pCsr->nPtr+nFree), &rc
    );
    if( rc ) return rc;
    memcpy(&aNew1[nFree], pCsr->aPtr, sizeof(SegmentPtr)*pCsr->nPtr);
    pCsr->nPtr += nFree;
    lsmFree(pDb->pEnv, pCsr->aTree);
    lsmFree(pDb->pEnv, pCsr->aPtr);
    pCsr->aTree = 0;
    pCsr->aPtr = aNew1;

    aNew2 = (Segment *)lsmMallocZeroRc(
        pDb->pEnv, sizeof(Segment) * (pLvl->nRight+nFree), &rc
    );
    if( rc ) return rc;
    memcpy(&aNew2[nFree], pLvl->aRhs, sizeof(Segment)*pLvl->nRight);
    pLvl->nRight += nFree;
    lsmFree(pDb->pEnv, pLvl->aRhs);
    pLvl->aRhs = aNew2;

    for(pIter=pDb->pWorker->pLevel; rc==LSM_OK && pIter!=pLvl; pIter=pNext){
      Segment *pSeg = &pLvl->aRhs[i];
      memcpy(pSeg, &pIter->lhs, sizeof(Segment));

      pCsr->aPtr[i].pSeg = pSeg;
      pCsr->aPtr[i].pLevel = pLvl;
      rc = segmentPtrEnd(pCsr, &pCsr->aPtr[i], 0);

      pDb->pWorker->pLevel = pNext = pIter->pNext;
      sortedFreeLevel(pDb->pEnv, pIter);
      i++;
    }
    assert( i==nFree );
    assert( rc!=LSM_OK || pDb->pWorker->pLevel==pLvl );

    for(i=nFree; i<pCsr->nPtr; i++){
      pCsr->aPtr[i].pSeg = &pLvl->aRhs[i];
    }

    lsmFree(pDb->pEnv, pMW->aGobble);
    pMW->aGobble = 0;
  }
  return rc;
}

static int sortedWork(
  lsm_db *pDb,                    /* Database handle. Must be worker. */
  int nWork,                      /* Number of pages of work to do */
  int nMerge,                     /* Try to merge this many levels at once */
  int bFlush,                     /* Set if call is to make room for a flush */
  int *pnWrite                    /* OUT: Actual number of pages written */
){
  int rc = LSM_OK;                /* Return Code */
  int nRemaining = nWork;         /* Units of work to do before returning */
  Snapshot *pWorker = pDb->pWorker;

  assert( pWorker );
  if( lsmDbSnapshotLevel(pWorker)==0 ) return LSM_OK;

  while( nRemaining>0 ){
    Level *pLevel = 0;

    /* Find a level to work on. */
    rc = sortedSelectLevel(pDb, nMerge, &pLevel);
    assert( rc==LSM_OK || pLevel==0 );

    if( pLevel==0 ){
      int nDone = 0;
      Level *pTopLevel = lsmDbSnapshotLevel(pDb->pWorker);
      if( bFlush==0 && nMerge==1 && pTopLevel && pTopLevel->pNext==0 ){
        rc = sortedMoveBlock(pDb, &nDone);
      }
      nRemaining -= nDone;

      /* Could not find any work to do. Finished. */
      if( nDone==0 ) break;
    }else{
      int bSave = 0;
      Freelist freelist = {0, 0, 0};
      MergeWorker mergeworker;    /* State used to work on the level merge */

      assert( pDb->bIncrMerge==0 );
      assert( pDb->pFreelist==0 && pDb->bUseFreelist==0 );

      pDb->bIncrMerge = 1;
      rc = mergeWorkerInit(pDb, pLevel, &mergeworker);
      assert( mergeworker.nWork==0 );
      
      while( rc==LSM_OK 
          && 0==mergeWorkerDone(&mergeworker) 
          && (mergeworker.nWork<nRemaining || pDb->bUseFreelist)
      ){
        int eType = rtTopic(mergeworker.pCsr->eType);
        rc = mergeWorkerStep(&mergeworker);

        /* If the cursor now points at the first entry past the end of the
        ** user data (i.e. either to EOF or to the first free-list entry
        ** that will be added to the run), then check if it is possible to
        ** merge in any free-list entries that are either in-memory or in
        ** free-list-only blocks.  */
        if( rc==LSM_OK && nMerge==1 && eType==0
         && (rtTopic(mergeworker.pCsr->eType) || mergeWorkerDone(&mergeworker))
        ){
          int nFree = 0;          /* Number of free-list-only levels to merge */
          Level *pLvl;
          assert( pDb->pFreelist==0 && pDb->bUseFreelist==0 );

          /* Now check if all levels containing data newer than this one
          ** are single-segment free-list only levels. If so, they will be
          ** merged in now.  */
          for(pLvl=pDb->pWorker->pLevel; 
              pLvl!=mergeworker.pLevel && (pLvl->flags & LEVEL_FREELIST_ONLY); 
              pLvl=pLvl->pNext
          ){
            assert( pLvl->nRight==0 );
            nFree++;
          }
          if( pLvl==mergeworker.pLevel ){

            rc = mergeInsertFreelistSegments(pDb, nFree, &mergeworker);
            if( rc==LSM_OK ){
              rc = multiCursorVisitFreelist(mergeworker.pCsr);
            }
            if( rc==LSM_OK ){
              rc = multiCursorSetupTree(mergeworker.pCsr, 0);
              pDb->pFreelist = &freelist;
              pDb->bUseFreelist = 1;
            }
          }
        }
      }
      nRemaining -= LSM_MAX(mergeworker.nWork, 1);

      if( rc==LSM_OK ){
        /* Check if the merge operation is completely finished. If not,
        ** gobble up (declare eligible for recycling) any pages from rhs
        ** segments for which the content has been completely merged into 
        ** the lhs of the level.  */
        if( mergeWorkerDone(&mergeworker)==0 ){
          int i;
          for(i=0; i<pLevel->nRight; i++){
            SegmentPtr *pGobble = &mergeworker.pCsr->aPtr[i];
            if( pGobble->pSeg->iRoot ){
              rc = sortedBtreeGobble(pDb, mergeworker.pCsr, i);
            }else if( mergeworker.aGobble[i] ){
              lsmFsGobble(pDb, pGobble->pSeg, &mergeworker.aGobble[i], 1);
            }
          }
        }else{
          int i;
          int bEmpty;
          mergeWorkerShutdown(&mergeworker, &rc);
          bEmpty = (pLevel->lhs.iFirst==0);

          if( bEmpty==0 && rc==LSM_OK ){
            rc = lsmFsSortedFinish(pDb->pFS, &pLevel->lhs);
          }

          if( pDb->bUseFreelist ){
            Freelist *p = &pDb->pWorker->freelist;
            lsmFree(pDb->pEnv, p->aEntry);
            memcpy(p, &freelist, sizeof(freelist));
            pDb->bUseFreelist = 0;
            pDb->pFreelist = 0;
            bSave = 1;
          }

          for(i=0; i<pLevel->nRight; i++){
            lsmFsSortedDelete(pDb->pFS, pWorker, 1, &pLevel->aRhs[i]);
          }

          if( bEmpty ){
            /* If the new level is completely empty, remove it from the 
            ** database snapshot. This can only happen if all input keys were
            ** annihilated. Since keys are only annihilated if the new level
            ** is the last in the linked list (contains the most ancient of
            ** database content), this guarantees that pLevel->pNext==0.  */ 
            Level *pTop;          /* Top level of worker snapshot */
            Level **pp;           /* Read/write iterator for Level.pNext list */

            assert( pLevel->pNext==0 );

            /* Remove the level from the worker snapshot. */
            pTop = lsmDbSnapshotLevel(pWorker);
            for(pp=&pTop; *pp!=pLevel; pp=&((*pp)->pNext));
            *pp = pLevel->pNext;
            lsmDbSnapshotSetLevel(pWorker, pTop);

            /* Free the Level structure. */
            sortedFreeLevel(pDb->pEnv, pLevel);
          }else{

            /* Free the separators of the next level, if required. */
            if( pLevel->pMerge->nInput > pLevel->nRight ){
              assert( pLevel->pNext->lhs.iRoot );
              pLevel->pNext->lhs.iRoot = 0;
            }

            /* Zero the right-hand-side of pLevel */
            lsmFree(pDb->pEnv, pLevel->aRhs);
            pLevel->nRight = 0;
            pLevel->aRhs = 0;

            /* Free the Merge object */
            lsmFree(pDb->pEnv, pLevel->pMerge);
            pLevel->pMerge = 0;
          }

          if( bSave && rc==LSM_OK ){
            pDb->bIncrMerge = 0;
            rc = lsmSaveWorker(pDb, 0);
          }
        }
      }

      /* Clean up the MergeWorker object initialized above. If no error
      ** has occurred, invoke the work-hook to inform the application that
      ** the database structure has changed. */
      mergeWorkerShutdown(&mergeworker, &rc);
      pDb->bIncrMerge = 0;
      if( rc==LSM_OK ) sortedInvokeWorkHook(pDb);

#if LSM_LOG_STRUCTURE
      lsmSortedDumpStructure(pDb, pDb->pWorker, LSM_LOG_DATA, 0, "work");
#endif
      assertBtreeOk(pDb, &pLevel->lhs);
      assertRunInOrder(pDb, &pLevel->lhs);

      /* If bFlush is true and the database is no longer considered "full",
      ** break out of the loop even if nRemaining is still greater than
      ** zero. The caller has an in-memory tree to flush to disk.  */
      if( bFlush && sortedDbIsFull(pDb)==0 ) break;
    }
  }

  if( pnWrite ) *pnWrite = (nWork - nRemaining);
  pWorker->nWrite += (nWork - nRemaining);

#ifdef LSM_LOG_WORK
  lsmLogMessage(pDb, rc, "sortedWork(): %d pages", (nWork-nRemaining));
#endif
  return rc;
}

/*
** The database connection passed as the first argument must be a worker
** connection. This function checks if there exists an "old" in-memory tree
** ready to be flushed to disk. If so, true is returned. Otherwise false.
**
** If an error occurs, *pRc is set to an LSM error code before returning.
** It is assumed that *pRc is set to LSM_OK when this function is called.
*/
static int sortedTreeHasOld(lsm_db *pDb, int *pRc){
  int rc = LSM_OK;
  int bRet = 0;

  assert( pDb->pWorker );
  if( *pRc==LSM_OK ){
    if( rc==LSM_OK 
        && pDb->treehdr.iOldShmid
        && pDb->treehdr.iOldLog!=pDb->pWorker->iLogOff 
      ){
      bRet = 1;
    }else{
      bRet = 0;
    }
    *pRc = rc;
  }
  assert( *pRc==LSM_OK || bRet==0 );
  return bRet;
}

/*
** Create a new free-list only top-level segment. Return LSM_OK if successful
** or an LSM error code if some error occurs.
*/
static int sortedNewFreelistOnly(lsm_db *pDb){
  return sortedNewToplevel(pDb, TREE_NONE, 0);
}

int lsmSaveWorker(lsm_db *pDb, int bFlush){
  Snapshot *p = pDb->pWorker;
  if( p->freelist.nEntry>pDb->nMaxFreelist ){
    int rc = sortedNewFreelistOnly(pDb);
    if( rc!=LSM_OK ) return rc;
  }
  return lsmCheckpointSaveWorker(pDb, bFlush);
}

static int doLsmSingleWork(
  lsm_db *pDb, 
  int bShutdown,
  int nMerge,                     /* Minimum segments to merge together */
  int nPage,                      /* Number of pages to write to disk */
  int *pnWrite,                   /* OUT: Pages actually written to disk */
  int *pbCkpt                     /* OUT: True if an auto-checkpoint is req. */
){
  Snapshot *pWorker;              /* Worker snapshot */
  int rc = LSM_OK;                /* Return code */
  int bDirty = 0;
  int nMax = nPage;               /* Maximum pages to write to disk */
  int nRem = nPage;
  int bCkpt = 0;

  assert( nPage>0 );

  /* Open the worker 'transaction'. It will be closed before this function
  ** returns.  */
  assert( pDb->pWorker==0 );
  rc = lsmBeginWork(pDb);
  if( rc!=LSM_OK ) return rc;
  pWorker = pDb->pWorker;

  /* If this connection is doing auto-checkpoints, set nMax (and nRem) so
  ** that this call stops writing when the auto-checkpoint is due. The
  ** caller will do the checkpoint, then possibly call this function again. */
  if( bShutdown==0 && pDb->nAutockpt ){
    u32 nSync;
    u32 nUnsync;
    int nPgsz;

    lsmCheckpointSynced(pDb, 0, 0, &nSync);
    nUnsync = lsmCheckpointNWrite(pDb->pShmhdr->aSnap1, 0);
    nPgsz = lsmCheckpointPgsz(pDb->pShmhdr->aSnap1);

    nMax = LSM_MIN(nMax, (pDb->nAutockpt/nPgsz) - (int)(nUnsync-nSync));
    if( nMax<nRem ){
      bCkpt = 1;
      nRem = LSM_MAX(nMax, 0);
    }
  }

  /* If there exists in-memory data ready to be flushed to disk, attempt
  ** to flush it now.  */
  if( pDb->nTransOpen==0 ){
    rc = lsmTreeLoadHeader(pDb, 0);
  }
  if( sortedTreeHasOld(pDb, &rc) ){
    /* sortedDbIsFull() returns non-zero if either (a) there are too many
    ** levels in total in the db, or (b) there are too many levels with the
    ** the same age in the db. Either way, call sortedWork() to merge 
    ** existing segments together until this condition is cleared.  */
    if( sortedDbIsFull(pDb) ){
      int nPg = 0;
      rc = sortedWork(pDb, nRem, nMerge, 1, &nPg);
      nRem -= nPg;
      assert( rc!=LSM_OK || nRem<=0 || !sortedDbIsFull(pDb) );
      bDirty = 1;
    }

    if( rc==LSM_OK && nRem>0 ){
      int nPg = 0;
      rc = sortedNewToplevel(pDb, TREE_OLD, &nPg);
      nRem -= nPg;
      if( rc==LSM_OK ){
        if( pDb->nTransOpen>0 ){
          lsmTreeDiscardOld(pDb);
        }
        rc = lsmSaveWorker(pDb, 1);
        bDirty = 0;
      }
    }
  }

  /* If nPage is still greater than zero, do some merging. */
  if( rc==LSM_OK && nRem>0 && bShutdown==0 ){
    int nPg = 0;
    rc = sortedWork(pDb, nRem, nMerge, 0, &nPg);
    nRem -= nPg;
    if( nPg ) bDirty = 1;
  }

  /* If the in-memory part of the free-list is too large, write a new 
  ** top-level containing just the in-memory free-list entries to disk. */
  if( rc==LSM_OK && pDb->pWorker->freelist.nEntry > pDb->nMaxFreelist ){
    int nPg = 0;
    while( rc==LSM_OK && lsmDatabaseFull(pDb) ){
      rc = sortedWork(pDb, 16, nMerge, 1, &nPg);
      nRem -= nPg;
    }
    if( rc==LSM_OK ){
      rc = sortedNewFreelistOnly(pDb);
    }
    nRem -= nPg;
    if( nPg ) bDirty = 1;
  }

  if( rc==LSM_OK ){
    *pnWrite = (nMax - nRem);
    *pbCkpt = (bCkpt && nRem<=0);
    if( nMerge==1 && pDb->nAutockpt>0 && *pnWrite>0
     && pWorker->pLevel 
     && pWorker->pLevel->nRight==0 
     && pWorker->pLevel->pNext==0 
    ){
      *pbCkpt = 1;
    }
  }

  if( rc==LSM_OK && bDirty ){
    lsmFinishWork(pDb, 0, &rc);
  }else{
    int rcdummy = LSM_BUSY;
    lsmFinishWork(pDb, 0, &rcdummy);
    *pnWrite = 0;
  }
  assert( pDb->pWorker==0 );
  return rc;
}

static int doLsmWork(lsm_db *pDb, int nMerge, int nPage, int *pnWrite){
  int rc = LSM_OK;                /* Return code */
  int nWrite = 0;                 /* Number of pages written */

  assert( nMerge>=1 );

  if( nPage!=0 ){
    int bCkpt = 0;
    do {
      int nThis = 0;
      int nReq = (nPage>=0) ? (nPage-nWrite) : ((int)0x7FFFFFFF);

      bCkpt = 0;
      rc = doLsmSingleWork(pDb, 0, nMerge, nReq, &nThis, &bCkpt);
      nWrite += nThis;
      if( rc==LSM_OK && bCkpt ){
        rc = lsm_checkpoint(pDb, 0);
      }
    }while( rc==LSM_OK && bCkpt && (nWrite<nPage || nPage<0) );
  }

  if( pnWrite ){
    if( rc==LSM_OK ){
      *pnWrite = nWrite;
    }else{
      *pnWrite = 0;
    }
  }
  return rc;
}

/*
** Perform work to merge database segments together.
*/
int lsm_work(lsm_db *pDb, int nMerge, int nKB, int *pnWrite){
  int rc;                         /* Return code */
  int nPgsz;                      /* Nominal page size in bytes */
  int nPage;                      /* Equivalent of nKB in pages */
  int nWrite = 0;                 /* Number of pages written */

  /* This function may not be called if pDb has an open read or write
  ** transaction. Return LSM_MISUSE if an application attempts this.  */
  if( pDb->nTransOpen || pDb->pCsr ) return LSM_MISUSE_BKPT;
  if( nMerge<=0 ) nMerge = pDb->nMerge;

  lsmFsPurgeCache(pDb->pFS);

  /* Convert from KB to pages */
  nPgsz = lsmFsPageSize(pDb->pFS);
  if( nKB>=0 ){
    nPage = ((i64)nKB * 1024 + nPgsz - 1) / nPgsz;
  }else{
    nPage = -1;
  }

  rc = doLsmWork(pDb, nMerge, nPage, &nWrite);
  
  if( pnWrite ){
    /* Convert back from pages to KB */
    *pnWrite = (int)(((i64)nWrite * 1024 + nPgsz - 1) / nPgsz);
  }
  return rc;
}

int lsm_flush(lsm_db *db){
  int rc;

  if( db->nTransOpen>0 || db->pCsr ){
    rc = LSM_MISUSE_BKPT;
  }else{
    rc = lsmBeginWriteTrans(db);
    if( rc==LSM_OK ){
      lsmFlushTreeToDisk(db);
      lsmTreeDiscardOld(db);
      lsmTreeMakeOld(db);
      lsmTreeDiscardOld(db);
    }

    if( rc==LSM_OK ){
      rc = lsmFinishWriteTrans(db, 1);
    }else{
      lsmFinishWriteTrans(db, 0);
    }
    lsmFinishReadTrans(db);
  }

  return rc;
}

/*
** This function is called in auto-work mode to perform merging work on
** the data structure. It performs enough merging work to prevent the
** height of the tree from growing indefinitely assuming that roughly
** nUnit database pages worth of data have been written to the database
** (i.e. the in-memory tree) since the last call.
*/
int lsmSortedAutoWork(
  lsm_db *pDb,                    /* Database handle */
  int nUnit                       /* Pages of data written to in-memory tree */
){
  int rc = LSM_OK;                /* Return code */
  int nDepth = 0;                 /* Current height of tree (longest path) */
  Level *pLevel;                  /* Used to iterate through levels */
  int bRestore = 0;

  assert( pDb->pWorker==0 );
  assert( pDb->nTransOpen>0 );

  /* Determine how many units of work to do before returning. One unit of
  ** work is achieved by writing one page (~4KB) of merged data.  */
  for(pLevel=lsmDbSnapshotLevel(pDb->pClient); pLevel; pLevel=pLevel->pNext){
    /* nDepth += LSM_MAX(1, pLevel->nRight); */
    nDepth += 1;
  }
  if( lsmTreeHasOld(pDb) ){
    nDepth += 1;
    bRestore = 1;
    rc = lsmSaveCursors(pDb);
    if( rc!=LSM_OK ) return rc;
  }

  if( nDepth>0 ){
    int nRemaining;               /* Units of work to do before returning */

    nRemaining = nUnit * nDepth;
#ifdef LSM_LOG_WORK
    lsmLogMessage(pDb, rc, "lsmSortedAutoWork(): %d*%d = %d pages", 
        nUnit, nDepth, nRemaining);
#endif
    assert( nRemaining>=0 );
    rc = doLsmWork(pDb, pDb->nMerge, nRemaining, 0);
    if( rc==LSM_BUSY ) rc = LSM_OK;

    if( bRestore && pDb->pCsr ){
      lsmMCursorFreeCache(pDb);
      lsmFreeSnapshot(pDb->pEnv, pDb->pClient);
      pDb->pClient = 0;
      rc = lsmCheckpointLoad(pDb, 0);
      if( rc==LSM_OK ){
        rc = lsmCheckpointDeserialize(pDb, 0, pDb->aSnapshot, &pDb->pClient);
      }
      if( rc==LSM_OK ){
        rc = lsmRestoreCursors(pDb);
      }
    }
  }

  return rc;
}

/*
** This function is only called during system shutdown. The contents of
** any in-memory trees present (old or current) are written out to disk.
*/
int lsmFlushTreeToDisk(lsm_db *pDb){
  int rc;

  rc = lsmBeginWork(pDb);
  while( rc==LSM_OK && sortedDbIsFull(pDb) ){
    rc = sortedWork(pDb, 256, pDb->nMerge, 1, 0);
  }

  if( rc==LSM_OK ){
    rc = sortedNewToplevel(pDb, TREE_BOTH, 0);
  }

  lsmFinishWork(pDb, 1, &rc);
  return rc;
}

/*
** Return a string representation of the segment passed as the only argument.
** Space for the returned string is allocated using lsmMalloc(), and should
** be freed by the caller using lsmFree().
*/
static char *segToString(lsm_env *pEnv, Segment *pSeg, int nMin){
  int nSize = pSeg->nSize;
  Pgno iRoot = pSeg->iRoot;
  Pgno iFirst = pSeg->iFirst;
  Pgno iLast = pSeg->iLastPg;
  char *z;

  char *z1;
  char *z2;
  int nPad;

  z1 = lsmMallocPrintf(pEnv, "%d.%d", iFirst, iLast);
  if( iRoot ){
    z2 = lsmMallocPrintf(pEnv, "root=%d", iRoot);
  }else{
    z2 = lsmMallocPrintf(pEnv, "size=%d", nSize);
  }

  nPad = nMin - 2 - strlen(z1) - 1 - strlen(z2);
  nPad = LSM_MAX(0, nPad);

  if( iRoot ){
    z = lsmMallocPrintf(pEnv, "/%s %*s%s\\", z1, nPad, "", z2);
  }else{
    z = lsmMallocPrintf(pEnv, "|%s %*s%s|", z1, nPad, "", z2);
  }
  lsmFree(pEnv, z1);
  lsmFree(pEnv, z2);

  return z;
}

static int fileToString(
  lsm_db *pDb,                    /* For xMalloc() */
  char *aBuf, 
  int nBuf, 
  int nMin,
  Segment *pSeg
){
  int i = 0;
  if( pSeg ){
    char *zSeg;

    zSeg = segToString(pDb->pEnv, pSeg, nMin);
    i += sqlite4_snprintf(&aBuf[i], nBuf-i, "%s", zSeg);
    lsmFree(pDb->pEnv, zSeg);

#ifdef LSM_LOG_FREELIST
    lsmInfoArrayStructure(pDb, 1, pSeg->iFirst, &zSeg);
    i += sqlite4_snprintf(&aBuf[i], nBuf-i, "    (%s)", zSeg);
    lsmFree(pDb->pEnv, zSeg);
#endif
  }else{
    aBuf[0] = '\0';
  }

  return i;
}

void sortedDumpPage(lsm_db *pDb, Segment *pRun, Page *pPg, int bVals){
  Blob blob = {0, 0, 0};         /* Blob used for keys */
  LsmString s;
  int i;

  int nRec;
  int iPtr;
  int flags;
  u8 *aData;
  int nData;

  aData = fsPageData(pPg, &nData);

  nRec = pageGetNRec(aData, nData);
  iPtr = pageGetPtr(aData, nData);
  flags = pageGetFlags(aData, nData);

  lsmStringInit(&s, pDb->pEnv);
  lsmStringAppendf(&s,"nCell=%d iPtr=%d flags=%d {", nRec, iPtr, flags);
  if( flags&SEGMENT_BTREE_FLAG ) iPtr = 0;

  for(i=0; i<nRec; i++){
    Page *pRef = 0;               /* Pointer to page iRef */
    int iChar;
    u8 *aKey; int nKey = 0;       /* Key */
    u8 *aVal; int nVal = 0;       /* Value */
    int iTopic;
    u8 *aCell;
    int iPgPtr;
    int eType;

    aCell = pageGetCell(aData, nData, i);
    eType = *aCell++;
    assert( (flags & SEGMENT_BTREE_FLAG) || eType!=0 );
    aCell += lsmVarintGet32(aCell, &iPgPtr);

    if( eType==0 ){
      Pgno iRef;                  /* Page number of referenced page */
      aCell += lsmVarintGet64(aCell, &iRef);
      lsmFsDbPageGet(pDb->pFS, pRun, iRef, &pRef);
      aKey = pageGetKey(pRun, pRef, 0, &iTopic, &nKey, &blob);
    }else{
      aCell += lsmVarintGet32(aCell, &nKey);
      if( rtIsWrite(eType) ) aCell += lsmVarintGet32(aCell, &nVal);
      sortedReadData(0, pPg, (aCell-aData), nKey+nVal, (void **)&aKey, &blob);
      aVal = &aKey[nKey];
      iTopic = eType;
    }

    lsmStringAppendf(&s, "%s%2X:", (i==0?"":" "), iTopic);
    for(iChar=0; iChar<nKey; iChar++){
      lsmStringAppendf(&s, "%c", isalnum(aKey[iChar]) ? aKey[iChar] : '.');
    }
    if( nVal>0 && bVals ){
      lsmStringAppendf(&s, "##");
      for(iChar=0; iChar<nVal; iChar++){
        lsmStringAppendf(&s, "%c", isalnum(aVal[iChar]) ? aVal[iChar] : '.');
      }
    }

    lsmStringAppendf(&s, " %d", iPgPtr+iPtr);
    lsmFsPageRelease(pRef);
  }
  lsmStringAppend(&s, "}", 1);

  lsmLogMessage(pDb, LSM_OK, "      Page %d: %s", lsmFsPageNumber(pPg), s.z);
  lsmStringClear(&s);

  sortedBlobFree(&blob);
}

static void infoCellDump(
  lsm_db *pDb,                    /* Database handle */
  Segment *pSeg,                  /* Segment page belongs to */
  int bIndirect,                  /* True to follow indirect refs */
  Page *pPg,
  int iCell,
  int *peType,
  int *piPgPtr,
  u8 **paKey, int *pnKey,
  u8 **paVal, int *pnVal,
  Blob *pBlob
){
  u8 *aData; int nData;           /* Page data */
  u8 *aKey; int nKey = 0;         /* Key */
  u8 *aVal; int nVal = 0;         /* Value */
  int eType;
  int iPgPtr;
  Page *pRef = 0;                 /* Pointer to page iRef */
  u8 *aCell;

  aData = fsPageData(pPg, &nData);

  aCell = pageGetCell(aData, nData, iCell);
  eType = *aCell++;
  aCell += lsmVarintGet32(aCell, &iPgPtr);

  if( eType==0 ){
    int dummy;
    Pgno iRef;                  /* Page number of referenced page */
    aCell += lsmVarintGet64(aCell, &iRef);
    if( bIndirect ){
      lsmFsDbPageGet(pDb->pFS, pSeg, iRef, &pRef);
      pageGetKeyCopy(pDb->pEnv, pSeg, pRef, 0, &dummy, pBlob);
      aKey = (u8 *)pBlob->pData;
      nKey = pBlob->nData;
      lsmFsPageRelease(pRef);
    }else{
      aKey = (u8 *)"<indirect>";
      nKey = 11;
    }
  }else{
    aCell += lsmVarintGet32(aCell, &nKey);
    if( rtIsWrite(eType) ) aCell += lsmVarintGet32(aCell, &nVal);
    sortedReadData(pSeg, pPg, (aCell-aData), nKey+nVal, (void **)&aKey, pBlob);
    aVal = &aKey[nKey];
  }

  if( peType ) *peType = eType;
  if( piPgPtr ) *piPgPtr = iPgPtr;
  if( paKey ) *paKey = aKey;
  if( paVal ) *paVal = aVal;
  if( pnKey ) *pnKey = nKey;
  if( pnVal ) *pnVal = nVal;
}

static int infoAppendBlob(LsmString *pStr, int bHex, u8 *z, int n){
  int iChar;
  for(iChar=0; iChar<n; iChar++){
    if( bHex ){
      lsmStringAppendf(pStr, "%02X", z[iChar]);
    }else{
      lsmStringAppendf(pStr, "%c", isalnum(z[iChar]) ?z[iChar] : '.');
    }
  }
  return LSM_OK;
}

#define INFO_PAGE_DUMP_DATA     0x01
#define INFO_PAGE_DUMP_VALUES   0x02
#define INFO_PAGE_DUMP_HEX      0x04
#define INFO_PAGE_DUMP_INDIRECT 0x08

static int infoPageDump(
  lsm_db *pDb,                    /* Database handle */
  Pgno iPg,                       /* Page number of page to dump */
  int flags,
  char **pzOut                    /* OUT: lsmMalloc'd string */
){
  int rc = LSM_OK;                /* Return code */
  Page *pPg = 0;                  /* Handle for page iPg */
  int i, j;                       /* Loop counters */
  const int perLine = 16;         /* Bytes per line in the raw hex dump */
  Segment *pSeg = 0;
  Snapshot *pSnap;

  int bValues = (flags & INFO_PAGE_DUMP_VALUES);
  int bHex = (flags & INFO_PAGE_DUMP_HEX);
  int bData = (flags & INFO_PAGE_DUMP_DATA);
  int bIndirect = (flags & INFO_PAGE_DUMP_INDIRECT);

  *pzOut = 0;
  if( iPg==0 ) return LSM_ERROR;

  assert( pDb->pClient || pDb->pWorker );
  pSnap = pDb->pClient;
  if( pSnap==0 ) pSnap = pDb->pWorker;
  if( pSnap->redirect.n>0 ){
    Level *pLvl;
    int bUse = 0;
    for(pLvl=pSnap->pLevel; pLvl->pNext; pLvl=pLvl->pNext);
    pSeg = (pLvl->nRight==0 ? &pLvl->lhs : &pLvl->aRhs[pLvl->nRight-1]);
    rc = lsmFsSegmentContainsPg(pDb->pFS, pSeg, iPg, &bUse);
    if( bUse==0 ){
      pSeg = 0;
    }
  }

  /* iPg is a real page number (not subject to redirection). So it is safe 
  ** to pass a NULL in place of the segment pointer as the second argument
  ** to lsmFsDbPageGet() here.  */
  if( rc==LSM_OK ){
    rc = lsmFsDbPageGet(pDb->pFS, 0, iPg, &pPg);
  }

  if( rc==LSM_OK ){
    Blob blob = {0, 0, 0, 0};
    int nKeyWidth = 0;
    LsmString str;
    int nRec;
    int iPtr;
    int flags;
    int iCell;
    u8 *aData; int nData;         /* Page data and size thereof */

    aData = fsPageData(pPg, &nData);
    nRec = pageGetNRec(aData, nData);
    iPtr = pageGetPtr(aData, nData);
    flags = pageGetFlags(aData, nData);

    lsmStringInit(&str, pDb->pEnv);
    lsmStringAppendf(&str, "Page : %lld  (%d bytes)\n", iPg, nData);
    lsmStringAppendf(&str, "nRec : %d\n", nRec);
    lsmStringAppendf(&str, "iPtr : %d\n", iPtr);
    lsmStringAppendf(&str, "flags: %04x\n", flags);
    lsmStringAppendf(&str, "\n");

    for(iCell=0; iCell<nRec; iCell++){
      int nKey;
      infoCellDump(
          pDb, pSeg, bIndirect, pPg, iCell, 0, 0, 0, &nKey, 0, 0, &blob
      );
      if( nKey>nKeyWidth ) nKeyWidth = nKey;
    }
    if( bHex ) nKeyWidth = nKeyWidth * 2;

    for(iCell=0; iCell<nRec; iCell++){
      u8 *aKey; int nKey = 0;       /* Key */
      u8 *aVal; int nVal = 0;       /* Value */
      int iPgPtr;
      int eType;
      Pgno iAbsPtr;
      char zFlags[8];

      infoCellDump(pDb, pSeg, bIndirect, pPg, iCell, &eType, &iPgPtr,
          &aKey, &nKey, &aVal, &nVal, &blob
      );
      iAbsPtr = iPgPtr + ((flags & SEGMENT_BTREE_FLAG) ? 0 : iPtr);

      lsmFlagsToString(eType, zFlags);
      lsmStringAppendf(&str, "%s %d (%s) ", 
          zFlags, iAbsPtr, (rtTopic(eType) ? "sys" : "usr")
      );
      infoAppendBlob(&str, bHex, aKey, nKey); 
      if( nVal>0 && bValues ){
        lsmStringAppendf(&str, "%*s", nKeyWidth - (nKey*(1+bHex)), "");
        lsmStringAppendf(&str, " ");
        infoAppendBlob(&str, bHex, aVal, nVal); 
      }
      if( rtTopic(eType) ){
        int iBlk = (int)~lsmGetU32(aKey);
        lsmStringAppendf(&str, "  (block=%d", iBlk);
        if( nVal>0 ){
          i64 iSnap = lsmGetU64(aVal);
          lsmStringAppendf(&str, " snapshot=%lld", iSnap);
        }
        lsmStringAppendf(&str, ")");
      }
      lsmStringAppendf(&str, "\n");
    }

    if( bData ){
      lsmStringAppendf(&str, "\n-------------------" 
          "-------------------------------------------------------------\n");
      lsmStringAppendf(&str, "Page %d\n",
          iPg, (iPg-1)*nData, iPg*nData - 1);
      for(i=0; i<nData; i += perLine){
        lsmStringAppendf(&str, "%04x: ", i);
        for(j=0; j<perLine; j++){
          if( i+j>nData ){
            lsmStringAppendf(&str, "   ");
          }else{
            lsmStringAppendf(&str, "%02x ", aData[i+j]);
          }
        }
        lsmStringAppendf(&str, "  ");
        for(j=0; j<perLine; j++){
          if( i+j>nData ){
            lsmStringAppendf(&str, " ");
          }else{
            lsmStringAppendf(&str,"%c", isprint(aData[i+j]) ? aData[i+j] : '.');
          }
        }
        lsmStringAppendf(&str,"\n");
      }
    }

    *pzOut = str.z;
    sortedBlobFree(&blob);
    lsmFsPageRelease(pPg);
  }

  return rc;
}

int lsmInfoPageDump(
  lsm_db *pDb,                    /* Database handle */
  Pgno iPg,                       /* Page number of page to dump */
  int bHex,                       /* True to output key/value in hex form */
  char **pzOut                    /* OUT: lsmMalloc'd string */
){
  int flags = INFO_PAGE_DUMP_DATA | INFO_PAGE_DUMP_VALUES;
  if( bHex ) flags |= INFO_PAGE_DUMP_HEX;
  return infoPageDump(pDb, iPg, flags, pzOut);
}

void sortedDumpSegment(lsm_db *pDb, Segment *pRun, int bVals){
  assert( pDb->xLog );
  if( pRun && pRun->iFirst ){
    int flags = (bVals ? INFO_PAGE_DUMP_VALUES : 0);
    char *zSeg;
    Page *pPg;

    zSeg = segToString(pDb->pEnv, pRun, 0);
    lsmLogMessage(pDb, LSM_OK, "Segment: %s", zSeg);
    lsmFree(pDb->pEnv, zSeg);

    lsmFsDbPageGet(pDb->pFS, pRun, pRun->iFirst, &pPg);
    while( pPg ){
      Page *pNext;
      char *z = 0;
      infoPageDump(pDb, lsmFsPageNumber(pPg), flags, &z);
      lsmLogMessage(pDb, LSM_OK, "%s", z);
      lsmFree(pDb->pEnv, z);
#if 0
      sortedDumpPage(pDb, pRun, pPg, bVals);
#endif
      lsmFsDbPageNext(pRun, pPg, 1, &pNext);
      lsmFsPageRelease(pPg);
      pPg = pNext;
    }
  }
}

/*
** Invoke the log callback zero or more times with messages that describe
** the current database structure.
*/
void lsmSortedDumpStructure(
  lsm_db *pDb,                    /* Database handle (used for xLog callback) */
  Snapshot *pSnap,                /* Snapshot to dump */
  int bKeys,                      /* Output the keys from each segment */
  int bVals,                      /* Output the values from each segment */
  const char *zWhy                /* Caption to print near top of dump */
){
  Snapshot *pDump = pSnap;
  Level *pTopLevel;
  char *zFree = 0;

  assert( pSnap );
  pTopLevel = lsmDbSnapshotLevel(pDump);
  if( pDb->xLog && pTopLevel ){
    static int nCall = 0;
    Level *pLevel;
    int iLevel = 0;

    nCall++;
    lsmLogMessage(pDb, LSM_OK, "Database structure %d (%s)", nCall, zWhy);

#if 0
    if( nCall==1031 || nCall==1032 ) bKeys=1;
#endif

    for(pLevel=pTopLevel; pLevel; pLevel=pLevel->pNext){
      char zLeft[1024];
      char zRight[1024];
      int i = 0;

      Segment *aLeft[24];  
      Segment *aRight[24];

      int nLeft = 0;
      int nRight = 0;

      Segment *pSeg = &pLevel->lhs;
      aLeft[nLeft++] = pSeg;

      for(i=0; i<pLevel->nRight; i++){
        aRight[nRight++] = &pLevel->aRhs[i];
      }

#ifdef LSM_LOG_FREELIST
      if( nRight ){
        memmove(&aRight[1], aRight, sizeof(aRight[0])*nRight);
        aRight[0] = 0;
        nRight++;
      }
#endif

      for(i=0; i<nLeft || i<nRight; i++){
        int iPad = 0;
        char zLevel[32];
        zLeft[0] = '\0';
        zRight[0] = '\0';

        if( i<nLeft ){ 
          fileToString(pDb, zLeft, sizeof(zLeft), 24, aLeft[i]); 
        }
        if( i<nRight ){ 
          fileToString(pDb, zRight, sizeof(zRight), 24, aRight[i]); 
        }

        if( i==0 ){
          sqlite4_snprintf(zLevel, sizeof(zLevel), "L%d: (age=%d) (flags=%.4x)",
              iLevel, (int)pLevel->iAge, (int)pLevel->flags
          );
        }else{
          zLevel[0] = '\0';
        }

        if( nRight==0 ){
          iPad = 10;
        }

        lsmLogMessage(pDb, LSM_OK, "% 25s % *s% -35s %s", 
            zLevel, iPad, "", zLeft, zRight
        );
      }

      iLevel++;
    }

    if( bKeys ){
      for(pLevel=pTopLevel; pLevel; pLevel=pLevel->pNext){
        int i;
        sortedDumpSegment(pDb, &pLevel->lhs, bVals);
        for(i=0; i<pLevel->nRight; i++){
          sortedDumpSegment(pDb, &pLevel->aRhs[i], bVals);
        }
      }
    }
  }

  lsmInfoFreelist(pDb, &zFree);
  lsmLogMessage(pDb, LSM_OK, "Freelist: %s", zFree);
  lsmFree(pDb->pEnv, zFree);

  assert( lsmFsIntegrityCheck(pDb) );
}

void lsmSortedFreeLevel(lsm_env *pEnv, Level *pLevel){
  Level *pNext;
  Level *p;

  for(p=pLevel; p; p=pNext){
    pNext = p->pNext;
    sortedFreeLevel(pEnv, p);
  }
}

void lsmSortedSaveTreeCursors(lsm_db *pDb){
  MultiCursor *pCsr;
  for(pCsr=pDb->pCsr; pCsr; pCsr=pCsr->pNext){
    lsmTreeCursorSave(pCsr->apTreeCsr[0]);
    lsmTreeCursorSave(pCsr->apTreeCsr[1]);
  }
}

void lsmSortedExpandBtreePage(Page *pPg, int nOrig){
  u8 *aData;
  int nData;
  int nEntry;
  int iHdr;

  aData = lsmFsPageData(pPg, &nData);
  nEntry = pageGetNRec(aData, nOrig);
  iHdr = SEGMENT_EOF(nOrig, nEntry);
  memmove(&aData[iHdr + (nData-nOrig)], &aData[iHdr], nOrig-iHdr);
}

#ifdef LSM_DEBUG_EXPENSIVE
static void assertRunInOrder(lsm_db *pDb, Segment *pSeg){
  Page *pPg = 0;
  Blob blob1 = {0, 0, 0, 0};
  Blob blob2 = {0, 0, 0, 0};

  lsmFsDbPageGet(pDb->pFS, pSeg, pSeg->iFirst, &pPg);
  while( pPg ){
    u8 *aData; int nData;
    Page *pNext;

    aData = lsmFsPageData(pPg, &nData);
    if( 0==(pageGetFlags(aData, nData) & SEGMENT_BTREE_FLAG) ){
      int i;
      int nRec = pageGetNRec(aData, nData);
      for(i=0; i<nRec; i++){
        int iTopic1, iTopic2;
        pageGetKeyCopy(pDb->pEnv, pSeg, pPg, i, &iTopic1, &blob1);

        if( i==0 && blob2.nData ){
          assert( sortedKeyCompare(
                pDb->xCmp, iTopic2, blob2.pData, blob2.nData,
                iTopic1, blob1.pData, blob1.nData
          )<0 );
        }

        if( i<(nRec-1) ){
          pageGetKeyCopy(pDb->pEnv, pSeg, pPg, i+1, &iTopic2, &blob2);
          assert( sortedKeyCompare(
                pDb->xCmp, iTopic1, blob1.pData, blob1.nData,
                iTopic2, blob2.pData, blob2.nData
          )<0 );
        }
      }
    }

    lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
    lsmFsPageRelease(pPg);
    pPg = pNext;
  }

  sortedBlobFree(&blob1);
  sortedBlobFree(&blob2);
}
#endif

#ifdef LSM_DEBUG_EXPENSIVE
/*
** This function is only included in the build if LSM_DEBUG_EXPENSIVE is 
** defined. Its only purpose is to evaluate various assert() statements to 
** verify that the database is well formed in certain respects.
**
** More specifically, it checks that the array pOne contains the required 
** pointers to pTwo. Array pTwo must be a main array. pOne may be either a 
** separators array or another main array. If pOne does not contain the 
** correct set of pointers, an assert() statement fails.
*/
static int assertPointersOk(
  lsm_db *pDb,                    /* Database handle */
  Segment *pOne,                  /* Segment containing pointers */
  Segment *pTwo,                  /* Segment containing pointer targets */
  int bRhs                        /* True if pTwo may have been Gobble()d */
){
  int rc = LSM_OK;                /* Error code */
  SegmentPtr ptr1;                /* Iterates through pOne */
  SegmentPtr ptr2;                /* Iterates through pTwo */
  Pgno iPrev;

  assert( pOne && pTwo );

  memset(&ptr1, 0, sizeof(ptr1));
  memset(&ptr2, 0, sizeof(ptr1));
  ptr1.pSeg = pOne;
  ptr2.pSeg = pTwo;
  segmentPtrEndPage(pDb->pFS, &ptr1, 0, &rc);
  segmentPtrEndPage(pDb->pFS, &ptr2, 0, &rc);

  /* Check that the footer pointer of the first page of pOne points to
  ** the first page of pTwo. */
  iPrev = pTwo->iFirst;
  if( ptr1.iPtr!=iPrev && !bRhs ){
    assert( 0 );
  }

  if( rc==LSM_OK && ptr1.nCell>0 ){
    rc = segmentPtrLoadCell(&ptr1, 0);
  }
      
  while( rc==LSM_OK && ptr2.pPg ){
    Pgno iThis;

    /* Advance to the next page of segment pTwo that contains at least
    ** one cell. Break out of the loop if the iterator reaches EOF.  */
    do{
      rc = segmentPtrNextPage(&ptr2, 1);
      assert( rc==LSM_OK );
    }while( rc==LSM_OK && ptr2.pPg && ptr2.nCell==0 );
    if( rc!=LSM_OK || ptr2.pPg==0 ) break;
    iThis = lsmFsPageNumber(ptr2.pPg);

    if( (ptr2.flags & (PGFTR_SKIP_THIS_FLAG|SEGMENT_BTREE_FLAG))==0 ){

      /* Load the first cell in the array pTwo page. */
      rc = segmentPtrLoadCell(&ptr2, 0);

      /* Iterate forwards through pOne, searching for a key that matches the
      ** key ptr2.pKey/nKey. This key should have a pointer to the page that
      ** ptr2 currently points to. */
      while( rc==LSM_OK ){
        int res = rtTopic(ptr1.eType) - rtTopic(ptr2.eType);
        if( res==0 ){
          res = pDb->xCmp(ptr1.pKey, ptr1.nKey, ptr2.pKey, ptr2.nKey);
        }

        if( res<0 ){
          assert( bRhs || ptr1.iPtr+ptr1.iPgPtr==iPrev );
        }else if( res>0 ){
          assert( 0 );
        }else{
          assert( ptr1.iPtr+ptr1.iPgPtr==iThis );
          iPrev = iThis;
          break;
        }

        rc = segmentPtrAdvance(0, &ptr1, 0);
        if( ptr1.pPg==0 ){
          assert( 0 );
        }
      }
    }
  }

  segmentPtrReset(&ptr1);
  segmentPtrReset(&ptr2);
  return LSM_OK;
}

/*
** This function is only included in the build if LSM_DEBUG_EXPENSIVE is 
** defined. Its only purpose is to evaluate various assert() statements to 
** verify that the database is well formed in certain respects.
**
** More specifically, it checks that the b-tree embedded in array pRun
** contains the correct keys. If not, an assert() fails.
*/
static int assertBtreeOk(
  lsm_db *pDb,
  Segment *pSeg
){
  int rc = LSM_OK;                /* Return code */
  if( pSeg->iRoot ){
    Blob blob = {0, 0, 0};        /* Buffer used to cache overflow keys */
    FileSystem *pFS = pDb->pFS;   /* File system to read from */
    Page *pPg = 0;                /* Main run page */
    BtreeCursor *pCsr = 0;        /* Btree cursor */

    rc = btreeCursorNew(pDb, pSeg, &pCsr);
    if( rc==LSM_OK ){
      rc = btreeCursorFirst(pCsr);
    }
    if( rc==LSM_OK ){
      rc = lsmFsDbPageGet(pFS, pSeg, pSeg->iFirst, &pPg);
    }

    while( rc==LSM_OK ){
      Page *pNext;
      u8 *aData;
      int nData;
      int flags;

      rc = lsmFsDbPageNext(pSeg, pPg, 1, &pNext);
      lsmFsPageRelease(pPg);
      pPg = pNext;
      if( pPg==0 ) break;
      aData = fsPageData(pPg, &nData);
      flags = pageGetFlags(aData, nData);
      if( rc==LSM_OK 
       && 0==((SEGMENT_BTREE_FLAG|PGFTR_SKIP_THIS_FLAG) & flags)
       && 0!=pageGetNRec(aData, nData)
      ){
        u8 *pKey;
        int nKey;
        int iTopic;
        pKey = pageGetKey(pSeg, pPg, 0, &iTopic, &nKey, &blob);
        assert( nKey==pCsr->nKey && 0==memcmp(pKey, pCsr->pKey, nKey) );
        assert( lsmFsPageNumber(pPg)==pCsr->iPtr );
        rc = btreeCursorNext(pCsr);
      }
    }
    assert( rc!=LSM_OK || pCsr->pKey==0 );

    if( pPg ) lsmFsPageRelease(pPg);

    btreeCursorFree(pCsr);
    sortedBlobFree(&blob);
  }

  return rc;
}
#endif /* ifdef LSM_DEBUG_EXPENSIVE */

/************** End of lsm_sorted.c ******************************************/
/************** Begin file lsm_str.c *****************************************/
/*
** 2012-04-27
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** Dynamic string functions.
*/

/*
** Turn bulk and uninitialized memory into an LsmString object
*/
void lsmStringInit(LsmString *pStr, lsm_env *pEnv){
  memset(pStr, 0, sizeof(pStr[0]));
  pStr->pEnv = pEnv;
}

/*
** Increase the memory allocated for holding the string.  Realloc as needed.
**
** If a memory allocation error occurs, set pStr->n to -1 and free the existing
** allocation.  If a prior memory allocation has occurred, this routine is a
** no-op.
*/
int lsmStringExtend(LsmString *pStr, int nNew){
  assert( nNew>0 );
  if( pStr->n<0 ) return LSM_NOMEM;
  if( pStr->n + nNew >= pStr->nAlloc ){
    int nAlloc = pStr->n + nNew + 100;
    char *zNew = lsmRealloc(pStr->pEnv, pStr->z, nAlloc);
    if( zNew==0 ){
      lsmFree(pStr->pEnv, pStr->z);
      nAlloc = 0;
      pStr->n = -1;
      pStr->z = 0;
    }else{
      pStr->nAlloc = nAlloc;
      pStr->z = zNew;
    }
  }
  return (pStr->z ? LSM_OK : LSM_NOMEM_BKPT);
}

/*
** Clear an LsmString object, releasing any allocated memory that it holds.
** This also clears the error indication (if any).
*/
void lsmStringClear(LsmString *pStr){
  lsmFree(pStr->pEnv, pStr->z);
  lsmStringInit(pStr, pStr->pEnv);
}

/*
** Append N bytes of text to the end of an LsmString object.  If
** N is negative, append the entire string.
**
** If the string is in an error state, this routine is a no-op.
*/
int lsmStringAppend(LsmString *pStr, const char *z, int N){
  int rc;
  if( N<0 ) N = (int)strlen(z);
  rc = lsmStringExtend(pStr, N+1);
  if( pStr->nAlloc ){
    memcpy(pStr->z+pStr->n, z, N+1);
    pStr->n += N;
  }
  return rc;
}

int lsmStringBinAppend(LsmString *pStr, const u8 *a, int n){
  int rc;
  rc = lsmStringExtend(pStr, n);
  if( pStr->nAlloc ){
    memcpy(pStr->z+pStr->n, a, n);
    pStr->n += n;
  }
  return rc;
}

/*
** Append printf-formatted content to an LsmString.
*/
void lsmStringVAppendf(
  LsmString *pStr, 
  const char *zFormat, 
  va_list ap1,
  va_list ap2
){
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__<199901L)) && \
    !defined(__APPLE__)
  extern int vsnprintf(char *str, size_t size, const char *format, va_list ap)
    /* Compatibility crutch for C89 compilation mode. sqlite4_vsnprintf()
       does not work identically and causes test failures if used here.
       For the time being we are assuming that the target has vsnprintf(),
       but that is not guaranteed to be the case for pure C89 platforms.
    */;
#endif
  int nWrite;
  int nAvail;

  nAvail = pStr->nAlloc - pStr->n;
  nWrite = vsnprintf(pStr->z + pStr->n, nAvail, zFormat, ap1);

  if( nWrite>=nAvail ){
    lsmStringExtend(pStr, nWrite+1);
    if( pStr->nAlloc==0 ) return;
    nWrite = vsnprintf(pStr->z + pStr->n, nWrite+1, zFormat, ap2);
  }

  pStr->n += nWrite;
  pStr->z[pStr->n] = 0;
}

void lsmStringAppendf(LsmString *pStr, const char *zFormat, ...){
  va_list ap, ap2;
  va_start(ap, zFormat);
  va_start(ap2, zFormat);
  lsmStringVAppendf(pStr, zFormat, ap, ap2);
  va_end(ap);
  va_end(ap2);
}

int lsmStrlen(const char *zName){
  int nRet = 0;
  while( zName[nRet] ) nRet++;
  return nRet;
}

/*
** Write into memory obtained from lsm_malloc().
*/
char *lsmMallocPrintf(lsm_env *pEnv, const char *zFormat, ...){
  LsmString s;
  va_list ap, ap2;
  lsmStringInit(&s, pEnv);
  va_start(ap, zFormat);
  va_start(ap2, zFormat);
  lsmStringVAppendf(&s, zFormat, ap, ap2);
  va_end(ap);
  va_end(ap2);
  if( s.n<0 ) return 0;
  return (char *)lsmReallocOrFree(pEnv, s.z, s.n+1);
}

/************** End of lsm_str.c *********************************************/
/************** Begin file lsm_tree.c ****************************************/
/*
** 2011-08-18
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains the implementation of an in-memory tree structure.
**
** Technically the tree is a B-tree of order 4 (in the Knuth sense - each 
** node may have up to 4 children). Keys are stored within B-tree nodes by
** reference. This may be slightly slower than a conventional red-black
** tree, but it is simpler. It is also an easier structure to modify to 
** create a version that supports nested transaction rollback.
**
** This tree does not currently support a delete operation. One is not 
** required. When LSM deletes a key from a database, it inserts a DELETE
** marker into the data structure. As a result, although the value associated
** with a key stored in the in-memory tree structure may be modified, no
** keys are ever removed. 
*/

/*
** MVCC NOTES
**
**   The in-memory tree structure supports SQLite-style MVCC. This means
**   that while one client is writing to the tree structure, other clients
**   may still be querying an older snapshot of the tree.
**
**   One way to implement this is to use an append-only b-tree. In this 
**   case instead of modifying nodes in-place, a copy of the node is made
**   and the required modifications made to the copy. The parent of the
**   node is then modified (to update the pointer so that it points to
**   the new copy), which causes a copy of the parent to be made, and so on.
**   This means that each time the tree is written to a new root node is
**   created. A snapshot is identified by the root node that it uses.
**
**   The problem with the above is that each time the tree is written to,
**   a copy of the node structure modified and all of its ancestor nodes
**   is made. This may prove excessive with large tree structures.
**
**   To reduce this overhead, the data structure used for a tree node is
**   designed so that it may be edited in place exactly once without 
**   affecting existing users. In other words, the node structure is capable
**   of storing two separate versions of the node at the same time.
**   When a node is to be edited, if the node structure already contains 
**   two versions, a copy is made as in the append-only approach. Or, if
**   it only contains a single version, it is edited in place.
**
**   This reduces the overhead so that, roughly, one new node structure
**   must be allocated for each write (on top of those allocations that 
**   would have been required by a non-MVCC tree). Logic: Assume that at 
**   any time, 50% of nodes in the tree already contain 2 versions. When
**   a new entry is written to a node, there is a 50% chance that a copy
**   of the node will be required. And a 25% chance that a copy of its 
**   parent is required. And so on.
**
** ROLLBACK
**
**   The in-memory tree also supports transaction and sub-transaction 
**   rollback. In order to rollback to point in time X, the following is
**   necessary:
**
**     1. All memory allocated since X must be freed, and 
**     2. All "v2" data adding to nodes that existed at X should be zeroed.
**     3. The root node must be restored to its X value.
**
**   The Mempool object used to allocate memory for the tree supports 
**   operation (1) - see the lsmPoolMark() and lsmPoolRevert() functions.
**
**   To support (2), all nodes that have v2 data are part of a singly linked 
**   list, sorted by the age of the v2 data (nodes that have had data added 
**   most recently are at the end of the list). So to zero all v2 data added
**   since X, the linked list is traversed from the first node added following
**   X onwards.
**
*/

#ifndef _LSM_INT_H
#endif

/* #include <string.h> */

#define MAX_DEPTH 32

typedef struct TreeKey TreeKey;
typedef struct TreeNode TreeNode;
typedef struct TreeLeaf TreeLeaf;
typedef struct NodeVersion NodeVersion;

struct TreeOld {
  u32 iShmid;                     /* Last shared-memory chunk in use by old */
  u32 iRoot;                      /* Offset of root node in shm file */
  u32 nHeight;                    /* Height of tree structure */
};

#ifndef NDEBUG
/*
** assert() that a TreeKey.flags value is sane. Usage:
**
**   assert( lsmAssertFlagsOk(pTreeKey->flags) );
*/
static int lsmAssertFlagsOk(u8 keyflags){
  /* At least one flag must be set. Otherwise, what is this key doing? */
  assert( keyflags!=0 );

  /* The POINT_DELETE and INSERT flags cannot both be set. */
  assert( (keyflags & LSM_POINT_DELETE)==0 || (keyflags & LSM_INSERT)==0 );

  /* If both the START_DELETE and END_DELETE flags are set, then the INSERT
  ** flag must also be set. In other words - the three DELETE flags cannot
  ** all be set */
  assert( (keyflags & LSM_END_DELETE)==0 
       || (keyflags & LSM_START_DELETE)==0 
       || (keyflags & LSM_POINT_DELETE)==0 
  );

  return 1;
}

static int assert_delete_ranges_match(lsm_db *);
static int treeCountEntries(lsm_db *db);
#else
# define lsmAssertFlagsOk(x)
#endif

/*
** Container for a key-value pair. Within the *-shm file, each key/value
** pair is stored in a single allocation (which may not actually be 
** contiguous in memory). Layout is the TreeKey structure, followed by
** the nKey bytes of key blob, followed by the nValue bytes of value blob
** (if nValue is non-negative).
*/
struct TreeKey {
  int nKey;                       /* Size of pKey in bytes */
  int nValue;                     /* Size of pValue. Or negative. */
  u8 flags;                       /* Various LSM_XXX flags */
};

#define TKV_KEY(p) ((void *)&(p)[1])
#define TKV_VAL(p) ((void *)(((u8 *)&(p)[1]) + (p)->nKey))

/*
** A single tree node. A node structure may contain up to 3 key/value
** pairs. Internal (non-leaf) nodes have up to 4 children.
**
** TODO: Update the format of this to be more compact. Get it working
** first though...
*/
struct TreeNode {
  u32 aiKeyPtr[3];                /* Array of pointers to TreeKey objects */

  /* The following fields are present for interior nodes only, not leaves. */
  u32 aiChildPtr[4];              /* Array of pointers to child nodes */

  /* The extra child pointer slot. */
  u32 iV2;                        /* Transaction number of v2 */
  u8 iV2Child;                    /* apChild[] entry replaced by pV2Ptr */
  u32 iV2Ptr;                     /* Substitute pointer */
};

struct TreeLeaf {
  u32 aiKeyPtr[3];                /* Array of pointers to TreeKey objects */
};

typedef struct TreeBlob TreeBlob;
struct TreeBlob {
  int n;
  u8 *a;
};

/*
** Cursor for searching a tree structure.
**
** If a cursor does not point to any element (a.k.a. EOF), then the
** TreeCursor.iNode variable is set to a negative value. Otherwise, the
** cursor currently points to key aiCell[iNode] on node apTreeNode[iNode].
**
** Entries in the apTreeNode[] and aiCell[] arrays contain the node and
** index of the TreeNode.apChild[] pointer followed to descend to the 
** current element. Hence apTreeNode[0] always contains the root node of
** the tree.
*/
struct TreeCursor {
  lsm_db *pDb;                    /* Database handle for this cursor */
  TreeRoot *pRoot;                /* Root node and height of tree to access */
  int iNode;                      /* Cursor points at apTreeNode[iNode] */
  TreeNode *apTreeNode[MAX_DEPTH];/* Current position in tree */
  u8 aiCell[MAX_DEPTH];           /* Current position in tree */
  TreeKey *pSave;                 /* Saved key */
  TreeBlob blob;                  /* Dynamic storage for a key */
};

/*
** A value guaranteed to be larger than the largest possible transaction
** id (TreeHeader.iTransId).
*/
#define WORKING_VERSION (1<<30)

static int tblobGrow(lsm_db *pDb, TreeBlob *p, int n, int *pRc){
  if( n>p->n ){
    lsmFree(pDb->pEnv, p->a);
    p->a = lsmMallocRc(pDb->pEnv, n, pRc);
    p->n = n;
  }
  return (p->a==0);
}
static void tblobFree(lsm_db *pDb, TreeBlob *p){
  lsmFree(pDb->pEnv, p->a);
}


/***********************************************************************
** Start of IntArray methods.  */
/*
** Append value iVal to the contents of IntArray *p. Return LSM_OK if 
** successful, or LSM_NOMEM if an OOM condition is encountered.
*/
static int intArrayAppend(lsm_env *pEnv, IntArray *p, u32 iVal){
  assert( p->nArray<=p->nAlloc );
  if( p->nArray>=p->nAlloc ){
    u32 *aNew;
    int nNew = p->nArray ? p->nArray*2 : 128;
    aNew = lsmRealloc(pEnv, p->aArray, nNew*sizeof(u32));
    if( !aNew ) return LSM_NOMEM_BKPT;
    p->aArray = aNew;
    p->nAlloc = nNew;
  }

  p->aArray[p->nArray++] = iVal;
  return LSM_OK;
}

/*
** Zero the IntArray object.
*/
static void intArrayFree(lsm_env *pEnv, IntArray *p){
  p->nArray = 0;
}

/*
** Return the number of entries currently in the int-array object.
*/
static int intArraySize(IntArray *p){
  return p->nArray;
}

/*
** Return a copy of the iIdx'th entry in the int-array.
*/
static u32 intArrayEntry(IntArray *p, int iIdx){
  return p->aArray[iIdx];
}

/*
** Truncate the int-array so that all but the first nVal values are 
** discarded.
*/
static void intArrayTruncate(IntArray *p, int nVal){
  p->nArray = nVal;
}
/* End of IntArray methods.
***********************************************************************/

static int treeKeycmp(void *p1, int n1, void *p2, int n2){
  int res;
  res = memcmp(p1, p2, LSM_MIN(n1, n2));
  if( res==0 ) res = (n1-n2);
  return res;
}

/*
** The pointer passed as the first argument points to an interior node,
** not a leaf. This function returns the offset of the iCell'th child
** sub-tree of the node.
*/
static u32 getChildPtr(TreeNode *p, int iVersion, int iCell){
  assert( iCell>=0 && iCell<=array_size(p->aiChildPtr) );
  if( p->iV2 && p->iV2<=iVersion && iCell==p->iV2Child ) return p->iV2Ptr;
  return p->aiChildPtr[iCell];
}

/*
** Given an offset within the *-shm file, return the associated chunk number.
*/
static int treeOffsetToChunk(u32 iOff){
  assert( LSM_SHM_CHUNK_SIZE==(1<<15) );
  return (int)(iOff>>15);
}

#define treeShmptrUnsafe(pDb, iPtr) \
(&((u8*)((pDb)->apShm[(iPtr)>>15]))[(iPtr) & (LSM_SHM_CHUNK_SIZE-1)])

/*
** Return a pointer to the mapped memory location associated with *-shm 
** file offset iPtr.
*/
static void *treeShmptr(lsm_db *pDb, u32 iPtr){

  assert( (iPtr>>15)<pDb->nShm );
  assert( pDb->apShm[iPtr>>15] );

  return iPtr ? treeShmptrUnsafe(pDb, iPtr) : 0;
}

static ShmChunk * treeShmChunk(lsm_db *pDb, int iChunk){
  return (ShmChunk *)(pDb->apShm[iChunk]);
}

static ShmChunk * treeShmChunkRc(lsm_db *pDb, int iChunk, int *pRc){
  assert( *pRc==LSM_OK );
  if( iChunk<pDb->nShm || LSM_OK==(*pRc = lsmShmCacheChunks(pDb, iChunk+1)) ){
    return (ShmChunk *)(pDb->apShm[iChunk]);
  }
  return 0;
}


#ifndef NDEBUG
static void assertIsWorkingChild(
  lsm_db *db, 
  TreeNode *pNode, 
  TreeNode *pParent, 
  int iCell
){
  TreeNode *p;
  u32 iPtr = getChildPtr(pParent, WORKING_VERSION, iCell);
  p = treeShmptr(db, iPtr);
  assert( p==pNode );
}
#else
# define assertIsWorkingChild(w,x,y,z)
#endif

/* Values for the third argument to treeShmkey(). */
#define TKV_LOADKEY  1
#define TKV_LOADVAL  2

static TreeKey *treeShmkey(
  lsm_db *pDb,                    /* Database handle */
  u32 iPtr,                       /* Shmptr to TreeKey struct */
  int eLoad,                      /* Either zero or a TREEKEY_LOADXXX value */
  TreeBlob *pBlob,                /* Used if dynamic memory is required */
  int *pRc                        /* IN/OUT: Error code */
){
  TreeKey *pRet;

  assert( eLoad==TKV_LOADKEY || eLoad==TKV_LOADVAL );
  pRet = (TreeKey *)treeShmptr(pDb, iPtr);
  if( pRet ){
    int nReq;                     /* Bytes of space required at pRet */
    int nAvail;                   /* Bytes of space available at pRet */

    nReq = sizeof(TreeKey) + pRet->nKey;
    if( eLoad==TKV_LOADVAL && pRet->nValue>0 ){
      nReq += pRet->nValue;
    }
    assert( LSM_SHM_CHUNK_SIZE==(1<<15) );
    nAvail = LSM_SHM_CHUNK_SIZE - (iPtr & (LSM_SHM_CHUNK_SIZE-1));

    if( nAvail<nReq ){
      if( tblobGrow(pDb, pBlob, nReq, pRc)==0 ){
        int nLoad = 0;
        while( *pRc==LSM_OK ){
          ShmChunk *pChunk;
          void *p = treeShmptr(pDb, iPtr);
          int n = LSM_MIN(nAvail, nReq-nLoad);

          memcpy(&pBlob->a[nLoad], p, n);
          nLoad += n;
          if( nLoad==nReq ) break;

          pChunk = treeShmChunk(pDb, treeOffsetToChunk(iPtr));
          assert( pChunk );
          iPtr = (pChunk->iNext * LSM_SHM_CHUNK_SIZE) + LSM_SHM_CHUNK_HDR;
          nAvail = LSM_SHM_CHUNK_SIZE - LSM_SHM_CHUNK_HDR;
        }
      }
      pRet = (TreeKey *)(pBlob->a);
    }
  }

  return pRet;
}

#if defined(LSM_DEBUG) && defined(LSM_EXPENSIVE_ASSERT)
void assert_leaf_looks_ok(TreeNode *pNode){
  assert( pNode->apKey[1] );
}

void assert_node_looks_ok(TreeNode *pNode, int nHeight){
  if( pNode ){
    assert( pNode->apKey[1] );
    if( nHeight>1 ){
      int i;
      assert( getChildPtr(pNode, WORKING_VERSION, 1) );
      assert( getChildPtr(pNode, WORKING_VERSION, 2) );
      for(i=0; i<4; i++){
        assert_node_looks_ok(getChildPtr(pNode, WORKING_VERSION, i), nHeight-1);
      }
    }
  }
}

/*
** Run various assert() statements to check that the working-version of the
** tree is correct in the following respects:
**
**   * todo...
*/
void assert_tree_looks_ok(int rc, Tree *pTree){
}
#else
# define assert_tree_looks_ok(x,y)
#endif

void lsmFlagsToString(int flags, char *zFlags){

  zFlags[0] = (flags & LSM_END_DELETE)   ? ']' : '.';

  /* Only one of LSM_POINT_DELETE, LSM_INSERT and LSM_SEPARATOR should ever
  ** be set. If this is not true, write a '?' to the output.  */
  switch( flags & (LSM_POINT_DELETE|LSM_INSERT|LSM_SEPARATOR) ){
    case 0:                zFlags[1] = '.'; break;
    case LSM_POINT_DELETE: zFlags[1] = '-'; break;
    case LSM_INSERT:       zFlags[1] = '+'; break;
    case LSM_SEPARATOR:    zFlags[1] = '^'; break;
    default:               zFlags[1] = '?'; break;
  }

  zFlags[2] = (flags & LSM_SYSTEMKEY)    ? '*' : '.';
  zFlags[3] = (flags & LSM_START_DELETE) ? '[' : '.';
  zFlags[4] = '\0';
}

#ifdef LSM_DEBUG

/*
** Pointer pBlob points to a buffer containing a blob of binary data
** nBlob bytes long. Append the contents of this blob to *pStr, with
** each octet represented by a 2-digit hexadecimal number. For example,
** if the input blob is three bytes in size and contains {0x01, 0x44, 0xFF},
** then "0144ff" is appended to *pStr.
*/
static void lsmAppendStrBlob(LsmString *pStr, void *pBlob, int nBlob){
  int i;
  lsmStringExtend(pStr, nBlob*2);
  if( pStr->nAlloc==0 ) return;
  for(i=0; i<nBlob; i++){
    u8 c = ((u8*)pBlob)[i];
    if( c>='a' && c<='z' ){
      pStr->z[pStr->n++] = c;
    }else if( c!=0 || nBlob==1 || i!=(nBlob-1) ){
      pStr->z[pStr->n++] = "0123456789abcdef"[(c>>4)&0xf];
      pStr->z[pStr->n++] = "0123456789abcdef"[c&0xf];
    }
  }
  pStr->z[pStr->n] = 0;
}

/*
** Append nIndent space (0x20) characters to string *pStr.
*/
static void lsmAppendIndent(LsmString *pStr, int nIndent){
  int i;
  lsmStringExtend(pStr, nIndent);
  for(i=0; i<nIndent; i++) lsmStringAppend(pStr, " ", 1);
}

static void strAppendFlags(LsmString *pStr, u8 flags){
  char zFlags[8];

  lsmFlagsToString(flags, zFlags);
  zFlags[4] = ':';

  lsmStringAppend(pStr, zFlags, 5);
}

void dump_node_contents(
  lsm_db *pDb,
  u32 iNode,                      /* Print out the contents of this node */
  char *zPath,                    /* Path from root to this node */
  int nPath,                      /* Number of bytes in zPath */
  int nHeight                     /* Height: (0==leaf) (1==parent-of-leaf) */
){
  const char *zSpace = "                                           ";
  int i;
  int rc = LSM_OK;
  LsmString s;
  TreeNode *pNode;
  TreeBlob b = {0, 0};

  pNode = (TreeNode *)treeShmptr(pDb, iNode);

  if( nHeight==0 ){
    /* Append the nIndent bytes of space to string s. */
    lsmStringInit(&s, pDb->pEnv);

    /* Append each key to string s. */
    for(i=0; i<3; i++){
      u32 iPtr = pNode->aiKeyPtr[i];
      if( iPtr ){
        TreeKey *pKey = treeShmkey(pDb, pNode->aiKeyPtr[i],TKV_LOADKEY, &b,&rc);
        strAppendFlags(&s, pKey->flags);
        lsmAppendStrBlob(&s, TKV_KEY(pKey), pKey->nKey);
        lsmStringAppend(&s, "     ", -1);
      }
    }

    printf("% 6d %.*sleaf%.*s: %s\n", 
        iNode, nPath, zPath, 20-nPath-4, zSpace, s.z
    );
    lsmStringClear(&s);
  }else{
    for(i=0; i<4 && nHeight>0; i++){
      u32 iPtr = getChildPtr(pNode, pDb->treehdr.root.iTransId, i);
      zPath[nPath] = i+'0';
      zPath[nPath+1] = '/';

      if( iPtr ){
        dump_node_contents(pDb, iPtr, zPath, nPath+2, nHeight-1);
      }
      if( i!=3 && pNode->aiKeyPtr[i] ){
        TreeKey *pKey = treeShmkey(pDb, pNode->aiKeyPtr[i], TKV_LOADKEY,&b,&rc);
        lsmStringInit(&s, pDb->pEnv);
        strAppendFlags(&s, pKey->flags);
        lsmAppendStrBlob(&s, TKV_KEY(pKey), pKey->nKey);
        printf("% 6d %.*s%.*s: %s\n", 
            iNode, nPath+1, zPath, 20-nPath-1, zSpace, s.z);
        lsmStringClear(&s);
      }
    }
  }

  tblobFree(pDb, &b);
}

void dump_tree_contents(lsm_db *pDb, const char *zCaption){
  char zPath[64];
  TreeRoot *p = &pDb->treehdr.root;
  printf("\n%s\n", zCaption);
  zPath[0] = '/';
  if( p->iRoot ){
    dump_node_contents(pDb, p->iRoot, zPath, 1, p->nHeight-1);
  }
  fflush(stdout);
}

#endif

/*
** Initialize a cursor object, the space for which has already been
** allocated.
*/
static void treeCursorInit(lsm_db *pDb, int bOld, TreeCursor *pCsr){
  memset(pCsr, 0, sizeof(TreeCursor));
  pCsr->pDb = pDb;
  if( bOld ){
    pCsr->pRoot = &pDb->treehdr.oldroot;
  }else{
    pCsr->pRoot = &pDb->treehdr.root;
  }
  pCsr->iNode = -1;
}

/*
** Return a pointer to the mapping of the TreeKey object that the cursor
** is pointing to. 
*/
static TreeKey *csrGetKey(TreeCursor *pCsr, TreeBlob *pBlob, int *pRc){
  TreeKey *pRet;
  lsm_db *pDb = pCsr->pDb;
  u32 iPtr = pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]];

  assert( iPtr );
  pRet = (TreeKey*)treeShmptrUnsafe(pDb, iPtr);
  if( !(pRet->flags & LSM_CONTIGUOUS) ){
    pRet = treeShmkey(pDb, iPtr, TKV_LOADVAL, pBlob, pRc);
  }

  return pRet;
}

/*
** Save the current position of tree cursor pCsr.
*/
int lsmTreeCursorSave(TreeCursor *pCsr){
  int rc = LSM_OK;
  if( pCsr && pCsr->pSave==0 ){
    int iNode = pCsr->iNode;
    if( iNode>=0 ){
      pCsr->pSave = csrGetKey(pCsr, &pCsr->blob, &rc);
    }
    pCsr->iNode = -1;
  }
  return rc;
}

/*
** Restore the position of a saved tree cursor.
*/
static int treeCursorRestore(TreeCursor *pCsr, int *pRes){
  int rc = LSM_OK;
  if( pCsr->pSave ){
    TreeKey *pKey = pCsr->pSave;
    pCsr->pSave = 0;
    if( pRes ){
      rc = lsmTreeCursorSeek(pCsr, TKV_KEY(pKey), pKey->nKey, pRes);
    }
  }
  return rc;
}

/*
** Allocate nByte bytes of space within the *-shm file. If successful, 
** return LSM_OK and set *piPtr to the offset within the file at which
** the allocated space is located.
*/
static u32 treeShmalloc(lsm_db *pDb, int bAlign, int nByte, int *pRc){
  u32 iRet = 0;
  if( *pRc==LSM_OK ){
    const static int CHUNK_SIZE = LSM_SHM_CHUNK_SIZE;
    const static int CHUNK_HDR = LSM_SHM_CHUNK_HDR;
    u32 iWrite;                   /* Current write offset */
    u32 iEof;                     /* End of current chunk */
    int iChunk;                   /* Current chunk */

    assert( nByte <= (CHUNK_SIZE-CHUNK_HDR) );

    /* Check if there is enough space on the current chunk to fit the
    ** new allocation. If not, link in a new chunk and put the new
    ** allocation at the start of it.  */
    iWrite = pDb->treehdr.iWrite;
    if( bAlign ){
      iWrite = (iWrite + 3) & ~0x0003;
      assert( (iWrite % 4)==0 );
    }

    assert( iWrite );
    iChunk = treeOffsetToChunk(iWrite-1);
    iEof = (iChunk+1) * CHUNK_SIZE;
    assert( iEof>=iWrite && (iEof-iWrite)<CHUNK_SIZE );
    if( (iWrite+nByte)>iEof ){
      ShmChunk *pHdr;           /* Header of chunk just finished (iChunk) */
      ShmChunk *pFirst;         /* Header of chunk treehdr.iFirst */
      ShmChunk *pNext;          /* Header of new chunk */
      int iNext = 0;            /* Next chunk */
      int rc = LSM_OK;

      pFirst = treeShmChunk(pDb, pDb->treehdr.iFirst);

      assert( shm_sequence_ge(pDb->treehdr.iUsedShmid, pFirst->iShmid) );
      assert( (pDb->treehdr.iNextShmid+1-pDb->treehdr.nChunk)==pFirst->iShmid );

      /* Check if the chunk at the start of the linked list is still in
      ** use. If not, reuse it. If so, allocate a new chunk by appending
      ** to the *-shm file.  */
      if( pDb->treehdr.iUsedShmid!=pFirst->iShmid ){
        int bInUse;
        rc = lsmTreeInUse(pDb, pFirst->iShmid, &bInUse);
        if( rc!=LSM_OK ){
          *pRc = rc;
          return 0;
        }
        if( bInUse==0 ){
          iNext = pDb->treehdr.iFirst;
          pDb->treehdr.iFirst = pFirst->iNext;
          assert( pDb->treehdr.iFirst );
        }
      }
      if( iNext==0 ) iNext = pDb->treehdr.nChunk++;

      /* Set the header values for the new chunk */
      pNext = treeShmChunkRc(pDb, iNext, &rc);
      if( pNext ){
        pNext->iNext = 0;
        pNext->iShmid = (pDb->treehdr.iNextShmid++);
      }else{
        *pRc = rc;
        return 0;
      }

      /* Set the header values for the chunk just finished */
      pHdr = (ShmChunk *)treeShmptr(pDb, iChunk*CHUNK_SIZE);
      pHdr->iNext = iNext;

      /* Advance to the next chunk */
      iWrite = iNext * CHUNK_SIZE + CHUNK_HDR;
    }

    /* Allocate space at iWrite. */
    iRet = iWrite;
    pDb->treehdr.iWrite = iWrite + nByte;
    pDb->treehdr.root.nByte += nByte;
  }
  return iRet;
}

/*
** Allocate and zero nByte bytes of space within the *-shm file.
*/
static void *treeShmallocZero(lsm_db *pDb, int nByte, u32 *piPtr, int *pRc){
  u32 iPtr;
  void *p;
  iPtr = treeShmalloc(pDb, 1, nByte, pRc);
  p = treeShmptr(pDb, iPtr);
  if( p ){
    assert( *pRc==LSM_OK );
    memset(p, 0, nByte);
    *piPtr = iPtr;
  }
  return p;
}

static TreeNode *newTreeNode(lsm_db *pDb, u32 *piPtr, int *pRc){
  return treeShmallocZero(pDb, sizeof(TreeNode), piPtr, pRc);
}

static TreeLeaf *newTreeLeaf(lsm_db *pDb, u32 *piPtr, int *pRc){
  return treeShmallocZero(pDb, sizeof(TreeLeaf), piPtr, pRc);
}

static TreeKey *newTreeKey(
  lsm_db *pDb, 
  u32 *piPtr, 
  void *pKey, int nKey,           /* Key data */
  void *pVal, int nVal,           /* Value data (or nVal<0 for delete) */
  int *pRc
){
  TreeKey *p;
  u32 iPtr;
  u32 iEnd;
  int nRem;
  u8 *a;
  int n;

  /* Allocate space for the TreeKey structure itself */
  *piPtr = iPtr = treeShmalloc(pDb, 1, sizeof(TreeKey), pRc);
  p = treeShmptr(pDb, iPtr);
  if( *pRc ) return 0;
  p->nKey = nKey;
  p->nValue = nVal;

  /* Allocate and populate the space required for the key and value. */
  n = nRem = nKey;
  a = (u8 *)pKey;
  while( a ){
    while( nRem>0 ){
      u8 *aAlloc;
      int nAlloc;
      u32 iWrite;

      iWrite = (pDb->treehdr.iWrite & (LSM_SHM_CHUNK_SIZE-1));
      iWrite = LSM_MAX(iWrite, LSM_SHM_CHUNK_HDR);
      nAlloc = LSM_MIN((LSM_SHM_CHUNK_SIZE-iWrite), nRem);

      aAlloc = treeShmptr(pDb, treeShmalloc(pDb, 0, nAlloc, pRc));
      if( aAlloc==0 ) break;
      memcpy(aAlloc, &a[n-nRem], nAlloc);
      nRem -= nAlloc;
    }
    a = pVal;
    n = nRem = nVal;
    pVal = 0;
  }

  iEnd = iPtr + sizeof(TreeKey) + nKey + LSM_MAX(0, nVal);
  if( (iPtr & ~(LSM_SHM_CHUNK_SIZE-1))!=(iEnd & ~(LSM_SHM_CHUNK_SIZE-1)) ){
    p->flags = 0;
  }else{
    p->flags = LSM_CONTIGUOUS;
  }

  if( *pRc ) return 0;
#if 0
  printf("store: %d %s\n", (int)iPtr, (char *)pKey);
#endif
  return p;
}

static TreeNode *copyTreeNode(
  lsm_db *pDb, 
  TreeNode *pOld, 
  u32 *piNew, 
  int *pRc
){
  TreeNode *pNew;

  pNew = newTreeNode(pDb, piNew, pRc);
  if( pNew ){
    memcpy(pNew->aiKeyPtr, pOld->aiKeyPtr, sizeof(pNew->aiKeyPtr));
    memcpy(pNew->aiChildPtr, pOld->aiChildPtr, sizeof(pNew->aiChildPtr));
    if( pOld->iV2 ) pNew->aiChildPtr[pOld->iV2Child] = pOld->iV2Ptr;
  }
  return pNew;
}

static TreeNode *copyTreeLeaf(
  lsm_db *pDb, 
  TreeLeaf *pOld, 
  u32 *piNew, 
  int *pRc
){
  TreeLeaf *pNew;
  pNew = newTreeLeaf(pDb, piNew, pRc);
  if( pNew ){
    memcpy(pNew, pOld, sizeof(TreeLeaf));
  }
  return (TreeNode *)pNew;
}

/*
** The tree cursor passed as the second argument currently points to an 
** internal node (not a leaf). Specifically, to a sub-tree pointer. This
** function replaces the sub-tree that the cursor currently points to
** with sub-tree pNew.
**
** The sub-tree may be replaced either by writing the "v2 data" on the
** internal node, or by allocating a new TreeNode structure and then 
** calling this function on the parent of the internal node.
*/
static int treeUpdatePtr(lsm_db *pDb, TreeCursor *pCsr, u32 iNew){
  int rc = LSM_OK;
  if( pCsr->iNode<0 ){
    /* iNew is the new root node */
    pDb->treehdr.root.iRoot = iNew;
  }else{
    /* If this node already has version 2 content, allocate a copy and
    ** update the copy with the new pointer value. Otherwise, store the
    ** new pointer as v2 data within the current node structure.  */

    TreeNode *p;                  /* The node to be modified */
    int iChildPtr;                /* apChild[] entry to modify */

    p = pCsr->apTreeNode[pCsr->iNode];
    iChildPtr = pCsr->aiCell[pCsr->iNode];

    if( p->iV2 ){
      /* The "allocate new TreeNode" option */
      u32 iCopy;
      TreeNode *pCopy;
      pCopy = copyTreeNode(pDb, p, &iCopy, &rc);
      if( pCopy ){
        assert( rc==LSM_OK );
        pCopy->aiChildPtr[iChildPtr] = iNew;
        pCsr->iNode--;
        rc = treeUpdatePtr(pDb, pCsr, iCopy);
      }
    }else{
      /* The "v2 data" option */
      u32 iPtr;
      assert( pDb->treehdr.root.iTransId>0 );

      if( pCsr->iNode ){
        iPtr = getChildPtr(
            pCsr->apTreeNode[pCsr->iNode-1], 
            pDb->treehdr.root.iTransId, pCsr->aiCell[pCsr->iNode-1]
        );
      }else{
        iPtr = pDb->treehdr.root.iRoot;
      }
      rc = intArrayAppend(pDb->pEnv, &pDb->rollback, iPtr);

      if( rc==LSM_OK ){
        p->iV2 = pDb->treehdr.root.iTransId;
        p->iV2Child = (u8)iChildPtr;
        p->iV2Ptr = iNew;
      }
    }
  }

  return rc;
}

/*
** Cursor pCsr points at a node that is part of pTree. This function
** inserts a new key and optionally child node pointer into that node.
**
** The position into which the new key and pointer are inserted is
** determined by the iSlot parameter. The new key will be inserted to
** the left of the key currently stored in apKey[iSlot]. Or, if iSlot is
** greater than the index of the rightmost key in the node.
**
** Pointer pLeftPtr points to a child tree that contains keys that are
** smaller than pTreeKey.
*/
static int treeInsert(
  lsm_db *pDb,                    /* Database handle */
  TreeCursor *pCsr,               /* Cursor indicating path to insert at */
  u32 iLeftPtr,                   /* Left child pointer */
  u32 iTreeKey,                   /* Location of key to insert */
  u32 iRightPtr,                  /* Right child pointer */
  int iSlot                       /* Position to insert key into */
){
  int rc = LSM_OK;
  TreeNode *pNode = pCsr->apTreeNode[pCsr->iNode];

  /* Check if the node is currently full. If so, split pNode in two and
  ** call this function recursively to add a key to the parent. Otherwise, 
  ** insert the new key directly into pNode.  */
  assert( pNode->aiKeyPtr[1] );
  if( pNode->aiKeyPtr[0] && pNode->aiKeyPtr[2] ){
    u32 iLeft; TreeNode *pLeft;   /* New left-hand sibling node */
    u32 iRight; TreeNode *pRight; /* New right-hand sibling node */

    pLeft = newTreeNode(pDb, &iLeft, &rc);
    pRight = newTreeNode(pDb, &iRight, &rc);
    if( rc ) return rc;

    pLeft->aiChildPtr[1] = getChildPtr(pNode, WORKING_VERSION, 0);
    pLeft->aiKeyPtr[1] = pNode->aiKeyPtr[0];
    pLeft->aiChildPtr[2] = getChildPtr(pNode, WORKING_VERSION, 1);

    pRight->aiChildPtr[1] = getChildPtr(pNode, WORKING_VERSION, 2);
    pRight->aiKeyPtr[1] = pNode->aiKeyPtr[2];
    pRight->aiChildPtr[2] = getChildPtr(pNode, WORKING_VERSION, 3);

    if( pCsr->iNode==0 ){
      /* pNode is the root of the tree. Grow the tree by one level. */
      u32 iRoot; TreeNode *pRoot; /* New root node */

      pRoot = newTreeNode(pDb, &iRoot, &rc);
      pRoot->aiKeyPtr[1] = pNode->aiKeyPtr[1];
      pRoot->aiChildPtr[1] = iLeft;
      pRoot->aiChildPtr[2] = iRight;

      pDb->treehdr.root.iRoot = iRoot;
      pDb->treehdr.root.nHeight++;
    }else{

      pCsr->iNode--;
      rc = treeInsert(pDb, pCsr, 
          iLeft, pNode->aiKeyPtr[1], iRight, pCsr->aiCell[pCsr->iNode]
      );
    }

    assert( pLeft->iV2==0 );
    assert( pRight->iV2==0 );
    switch( iSlot ){
      case 0:
        pLeft->aiKeyPtr[0] = iTreeKey;
        pLeft->aiChildPtr[0] = iLeftPtr;
        if( iRightPtr ) pLeft->aiChildPtr[1] = iRightPtr;
        break;
      case 1:
        pLeft->aiChildPtr[3] = (iRightPtr ? iRightPtr : pLeft->aiChildPtr[2]);
        pLeft->aiKeyPtr[2] = iTreeKey;
        pLeft->aiChildPtr[2] = iLeftPtr;
        break;
      case 2:
        pRight->aiKeyPtr[0] = iTreeKey;
        pRight->aiChildPtr[0] = iLeftPtr;
        if( iRightPtr ) pRight->aiChildPtr[1] = iRightPtr;
        break;
      case 3:
        pRight->aiChildPtr[3] = (iRightPtr ? iRightPtr : pRight->aiChildPtr[2]);
        pRight->aiKeyPtr[2] = iTreeKey;
        pRight->aiChildPtr[2] = iLeftPtr;
        break;
    }

  }else{
    TreeNode *pNew;
    u32 *piKey;
    u32 *piChild;
    u32 iStore = 0;
    u32 iNew = 0;
    int i;

    /* Allocate a new version of node pNode. */
    pNew = newTreeNode(pDb, &iNew, &rc);
    if( rc ) return rc;

    piKey = pNew->aiKeyPtr;
    piChild = pNew->aiChildPtr;

    for(i=0; i<iSlot; i++){
      if( pNode->aiKeyPtr[i] ){
        *(piKey++) = pNode->aiKeyPtr[i];
        *(piChild++) = getChildPtr(pNode, WORKING_VERSION, i);
      }
    }

    *piKey++ = iTreeKey;
    *piChild++ = iLeftPtr;

    iStore = iRightPtr;
    for(i=iSlot; i<3; i++){
      if( pNode->aiKeyPtr[i] ){
        *(piKey++) = pNode->aiKeyPtr[i];
        *(piChild++) = iStore ? iStore : getChildPtr(pNode, WORKING_VERSION, i);
        iStore = 0;
      }
    }

    if( iStore ){
      *piChild = iStore;
    }else{
      *piChild = getChildPtr(pNode, WORKING_VERSION, 
          (pNode->aiKeyPtr[2] ? 3 : 2)
      );
    }
    pCsr->iNode--;
    rc = treeUpdatePtr(pDb, pCsr, iNew);
  }

  return rc;
}

static int treeInsertLeaf(
  lsm_db *pDb,                    /* Database handle */
  TreeCursor *pCsr,               /* Cursor structure */
  u32 iTreeKey,                   /* Key pointer to insert */
  int iSlot                       /* Insert key to the left of this */
){
  int rc = LSM_OK;                /* Return code */
  TreeNode *pLeaf = pCsr->apTreeNode[pCsr->iNode];
  TreeLeaf *pNew;
  u32 iNew;

  assert( iSlot>=0 && iSlot<=4 );
  assert( pCsr->iNode>0 );
  assert( pLeaf->aiKeyPtr[1] );

  pCsr->iNode--;

  pNew = newTreeLeaf(pDb, &iNew, &rc);
  if( pNew ){
    if( pLeaf->aiKeyPtr[0] && pLeaf->aiKeyPtr[2] ){
      /* The leaf is full. Split it in two. */
      TreeLeaf *pRight;
      u32 iRight;
      pRight = newTreeLeaf(pDb, &iRight, &rc);
      if( pRight ){
        assert( rc==LSM_OK );
        pNew->aiKeyPtr[1] = pLeaf->aiKeyPtr[0];
        pRight->aiKeyPtr[1] = pLeaf->aiKeyPtr[2];
        switch( iSlot ){
          case 0: pNew->aiKeyPtr[0] = iTreeKey; break;
          case 1: pNew->aiKeyPtr[2] = iTreeKey; break;
          case 2: pRight->aiKeyPtr[0] = iTreeKey; break;
          case 3: pRight->aiKeyPtr[2] = iTreeKey; break;
        }

        rc = treeInsert(pDb, pCsr, iNew, pLeaf->aiKeyPtr[1], iRight, 
            pCsr->aiCell[pCsr->iNode]
        );
      }
    }else{
      int iOut = 0;
      int i;
      for(i=0; i<4; i++){
        if( i==iSlot ) pNew->aiKeyPtr[iOut++] = iTreeKey;
        if( i<3 && pLeaf->aiKeyPtr[i] ){
          pNew->aiKeyPtr[iOut++] = pLeaf->aiKeyPtr[i];
        }
      }
      rc = treeUpdatePtr(pDb, pCsr, iNew);
    }
  }

  return rc;
}

void lsmTreeMakeOld(lsm_db *pDb){

  /* A write transaction must be open. Otherwise the code below that
  ** assumes (pDb->pClient->iLogOff) is current may malfunction. 
  **
  ** Update: currently this assert fails due to lsm_flush(), which does
  ** not set nTransOpen.
  */
  assert( /* pDb->nTransOpen>0 && */ pDb->iReader>=0 );

  if( pDb->treehdr.iOldShmid==0 ){
    pDb->treehdr.iOldLog = (pDb->treehdr.log.aRegion[2].iEnd << 1);
    pDb->treehdr.iOldLog |= (~(pDb->pClient->iLogOff) & (i64)0x0001);

    pDb->treehdr.oldcksum0 = pDb->treehdr.log.cksum0;
    pDb->treehdr.oldcksum1 = pDb->treehdr.log.cksum1;
    pDb->treehdr.iOldShmid = pDb->treehdr.iNextShmid-1;
    memcpy(&pDb->treehdr.oldroot, &pDb->treehdr.root, sizeof(TreeRoot));

    pDb->treehdr.root.iTransId = 1;
    pDb->treehdr.root.iRoot = 0;
    pDb->treehdr.root.nHeight = 0;
    pDb->treehdr.root.nByte = 0;
  }
}

void lsmTreeDiscardOld(lsm_db *pDb){
  assert( lsmShmAssertLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_EXCL) 
       || lsmShmAssertLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_EXCL) 
  );
  pDb->treehdr.iUsedShmid = pDb->treehdr.iOldShmid;
  pDb->treehdr.iOldShmid = 0;
}

int lsmTreeHasOld(lsm_db *pDb){
  return pDb->treehdr.iOldShmid!=0;
}

/*
** This function is called during recovery to initialize the 
** tree header. Only the database connections private copy of the tree-header
** is initialized here - it will be copied into shared memory if log file
** recovery is successful.
*/
int lsmTreeInit(lsm_db *pDb){
  ShmChunk *pOne;
  int rc = LSM_OK;

  memset(&pDb->treehdr, 0, sizeof(TreeHeader));
  pDb->treehdr.root.iTransId = 1;
  pDb->treehdr.iFirst = 1;
  pDb->treehdr.nChunk = 2;
  pDb->treehdr.iWrite = LSM_SHM_CHUNK_SIZE + LSM_SHM_CHUNK_HDR;
  pDb->treehdr.iNextShmid = 2;
  pDb->treehdr.iUsedShmid = 1;

  pOne = treeShmChunkRc(pDb, 1, &rc);
  if( pOne ){
    pOne->iNext = 0;
    pOne->iShmid = 1;
  }
  return rc;
}

static void treeHeaderChecksum(
  TreeHeader *pHdr, 
  u32 *aCksum
){
  u32 cksum1 = 0x12345678;
  u32 cksum2 = 0x9ABCDEF0;
  u32 *a = (u32 *)pHdr;
  int i;

  assert( (offsetof(TreeHeader, aCksum) + sizeof(u32)*2)==sizeof(TreeHeader) );
  assert( (sizeof(TreeHeader) % (sizeof(u32)*2))==0 );

  for(i=0; i<(offsetof(TreeHeader, aCksum) / sizeof(u32)); i+=2){
    cksum1 += a[i];
    cksum2 += (cksum1 + a[i+1]);
  }
  aCksum[0] = cksum1;
  aCksum[1] = cksum2;
}

/*
** Return true if the checksum stored in TreeHeader object *pHdr is 
** consistent with the contents of its other fields.
*/
static int treeHeaderChecksumOk(TreeHeader *pHdr){
  u32 aCksum[2];
  treeHeaderChecksum(pHdr, aCksum);
  return (0==memcmp(aCksum, pHdr->aCksum, sizeof(aCksum)));
}

/*
** This type is used by functions lsmTreeRepair() and treeSortByShmid() to
** make relinking the linked list of shared-memory chunks easier.
*/
typedef struct ShmChunkLoc ShmChunkLoc;
struct ShmChunkLoc {
  ShmChunk *pShm;
  u32 iLoc;
};

/*
** This function checks that the linked list of shared memory chunks 
** that starts at chunk db->treehdr.iFirst:
**
**   1) Includes all chunks in the shared-memory region, and
**   2) Links them together in order of ascending shm-id.
**
** If no error occurs and the conditions above are met, LSM_OK is returned.
**
** If either of the conditions are untrue, LSM_CORRUPT is returned. Or, if
** an error is encountered before the checks are completed, another LSM error
** code (i.e. LSM_IOERR or LSM_NOMEM) may be returned.
*/
static int treeCheckLinkedList(lsm_db *db){
  int rc = LSM_OK;
  int nVisit = 0;
  ShmChunk *p;

  p = treeShmChunkRc(db, db->treehdr.iFirst, &rc);
  while( rc==LSM_OK && p ){
    if( p->iNext ){
      if( p->iNext>=db->treehdr.nChunk ){
        rc = LSM_CORRUPT_BKPT;
      }else{
        ShmChunk *pNext = treeShmChunkRc(db, p->iNext, &rc);
        if( rc==LSM_OK ){
          if( pNext->iShmid!=p->iShmid+1 ){
            rc = LSM_CORRUPT_BKPT;
          }
          p = pNext;
        }
      }
    }else{
      p = 0;
    }
    nVisit++;
  }

  if( rc==LSM_OK && nVisit!=db->treehdr.nChunk-1 ){
    rc = LSM_CORRUPT_BKPT;
  }
  return rc;
}

/*
** Iterate through the current in-memory tree. If there are any v2-pointers
** with transaction ids larger than db->treehdr.iTransId, zero them.
*/
static int treeRepairPtrs(lsm_db *db){
  int rc = LSM_OK;

  if( db->treehdr.root.nHeight>1 ){
    TreeCursor csr;               /* Cursor used to iterate through tree */
    u32 iTransId = db->treehdr.root.iTransId;

    /* Initialize the cursor structure. Also decrement the nHeight variable
    ** in the tree-header. This will prevent the cursor from visiting any
    ** leaf nodes.  */
    db->treehdr.root.nHeight--;
    treeCursorInit(db, 0, &csr);

    rc = lsmTreeCursorEnd(&csr, 0);
    while( rc==LSM_OK && lsmTreeCursorValid(&csr) ){
      TreeNode *pNode = csr.apTreeNode[csr.iNode];
      if( pNode->iV2>iTransId ){
        pNode->iV2Child = 0;
        pNode->iV2Ptr = 0;
        pNode->iV2 = 0;
      }
      rc = lsmTreeCursorNext(&csr);
    }
    tblobFree(csr.pDb, &csr.blob);

    db->treehdr.root.nHeight++;
  }

  return rc;
}

static int treeRepairList(lsm_db *db){
  int rc = LSM_OK;
  int i;
  ShmChunk *p;
  ShmChunk *pMin = 0;
  u32 iMin = 0;

  /* Iterate through all shm chunks. Find the smallest shm-id present in
  ** the shared-memory region. */
  for(i=1; rc==LSM_OK && i<db->treehdr.nChunk; i++){
    p = treeShmChunkRc(db, i, &rc);
    if( p && (pMin==0 || shm_sequence_ge(pMin->iShmid, p->iShmid)) ){
      pMin = p;
      iMin = i;
    }
  }

  /* Fix the shm-id values on any chunks with a shm-id greater than or 
  ** equal to treehdr.iNextShmid. Then do a merge-sort of all chunks to 
  ** fix the ShmChunk.iNext pointers.
  */
  if( rc==LSM_OK ){
    int nSort;
    int nByte;
    u32 iPrevShmid;
    ShmChunkLoc *aSort;

    /* Allocate space for a merge sort. */
    nSort = 1;
    while( nSort < (db->treehdr.nChunk-1) ) nSort = nSort * 2;
    nByte = sizeof(ShmChunkLoc) * nSort * 2;
    aSort = lsmMallocZeroRc(db->pEnv, nByte, &rc);
    iPrevShmid = pMin->iShmid;

    /* Fix all shm-ids, if required. */
    if( rc==LSM_OK ){
      iPrevShmid = pMin->iShmid-1;
      for(i=1; i<db->treehdr.nChunk; i++){
        p = treeShmChunk(db, i);
        aSort[i-1].pShm = p;
        aSort[i-1].iLoc = i;
        if( i!=db->treehdr.iFirst ){
          if( shm_sequence_ge(p->iShmid, db->treehdr.iNextShmid) ){
            p->iShmid = iPrevShmid--;
          }
        }
      }
      if( iMin!=db->treehdr.iFirst ){
        p = treeShmChunk(db, db->treehdr.iFirst);
        p->iShmid = iPrevShmid;
      }
    }

    if( rc==LSM_OK ){
      ShmChunkLoc *aSpace = &aSort[nSort];
      for(i=0; i<nSort; i++){
        if( aSort[i].pShm ){
          assert( shm_sequence_ge(aSort[i].pShm->iShmid, iPrevShmid) );
          assert( aSpace[aSort[i].pShm->iShmid - iPrevShmid].pShm==0 );
          aSpace[aSort[i].pShm->iShmid - iPrevShmid] = aSort[i];
        }
      }

      if( aSpace[nSort-1].pShm ) aSpace[nSort-1].pShm->iNext = 0;
      for(i=0; i<nSort-1; i++){
        if( aSpace[i].pShm ){
          aSpace[i].pShm->iNext = aSpace[i+1].iLoc;
        }
      }

      rc = treeCheckLinkedList(db);
      lsmFree(db->pEnv, aSort);
    }
  }

  return rc;
}

/*
** This function is called as part of opening a write-transaction if the
** writer-flag is already set - indicating that the previous writer 
** failed before ending its transaction.
*/
int lsmTreeRepair(lsm_db *db){
  int rc = LSM_OK;
  TreeHeader hdr;
  ShmHeader *pHdr = db->pShmhdr;

  /* Ensure that the two tree-headers are consistent. Copy one over the other
  ** if necessary. Prefer the data from a tree-header for which the checksum
  ** computes. Or, if they both compute, prefer tree-header-1.  */
  if( memcmp(&pHdr->hdr1, &pHdr->hdr2, sizeof(TreeHeader)) ){
    if( treeHeaderChecksumOk(&pHdr->hdr1) ){
      memcpy(&pHdr->hdr2, &pHdr->hdr1, sizeof(TreeHeader));
    }else{
      memcpy(&pHdr->hdr1, &pHdr->hdr2, sizeof(TreeHeader));
    }
  }

  /* Save the connections current copy of the tree-header. It will be 
  ** restored before returning.  */
  memcpy(&hdr, &db->treehdr, sizeof(TreeHeader));

  /* Walk the tree. Zero any v2 pointers with a transaction-id greater than
  ** the transaction-id currently in the tree-headers.  */
  rc = treeRepairPtrs(db);

  /* Repair the linked list of shared-memory chunks. */
  if( rc==LSM_OK ){
    rc = treeRepairList(db);
  }

  memcpy(&db->treehdr, &hdr, sizeof(TreeHeader));
  return rc;
}

static void treeOverwriteKey(lsm_db *db, TreeCursor *pCsr, u32 iKey, int *pRc){
  if( *pRc==LSM_OK ){
    TreeRoot *p = &db->treehdr.root;
    TreeNode *pNew;
    u32 iNew;
    TreeNode *pNode = pCsr->apTreeNode[pCsr->iNode];
    int iCell = pCsr->aiCell[pCsr->iNode];

    /* Create a copy of this node */
    if( (pCsr->iNode>0 && pCsr->iNode==(p->nHeight-1)) ){
      pNew = copyTreeLeaf(db, (TreeLeaf *)pNode, &iNew, pRc);
    }else{
      pNew = copyTreeNode(db, pNode, &iNew, pRc);
    }

    if( pNew ){
      /* Modify the value in the new version */
      pNew->aiKeyPtr[iCell] = iKey;

      /* Change the pointer in the parent (if any) to point at the new 
       ** TreeNode */
      pCsr->iNode--;
      treeUpdatePtr(db, pCsr, iNew);
    }
  }
}

static int treeNextIsEndDelete(lsm_db *db, TreeCursor *pCsr){
  int iNode = pCsr->iNode;
  int iCell = pCsr->aiCell[iNode]+1;

  /* Cursor currently points to a leaf node. */
  assert( pCsr->iNode==(db->treehdr.root.nHeight-1) );

  while( iNode>=0 ){
    TreeNode *pNode = pCsr->apTreeNode[iNode];
    if( iCell<3 && pNode->aiKeyPtr[iCell] ){
      int rc = LSM_OK;
      TreeKey *pKey = treeShmptr(db, pNode->aiKeyPtr[iCell]);
      assert( rc==LSM_OK );
      return ((pKey->flags & LSM_END_DELETE) ? 1 : 0);
    }
    iNode--;
    iCell = pCsr->aiCell[iNode];
  }

  return 0;
}

static int treePrevIsStartDelete(lsm_db *db, TreeCursor *pCsr){
  int iNode = pCsr->iNode;

  /* Cursor currently points to a leaf node. */
  assert( pCsr->iNode==(db->treehdr.root.nHeight-1) );

  while( iNode>=0 ){
    TreeNode *pNode = pCsr->apTreeNode[iNode];
    int iCell = pCsr->aiCell[iNode]-1;
    if( iCell>=0 && pNode->aiKeyPtr[iCell] ){
      int rc = LSM_OK;
      TreeKey *pKey = treeShmptr(db, pNode->aiKeyPtr[iCell]);
      assert( rc==LSM_OK );
      return ((pKey->flags & LSM_START_DELETE) ? 1 : 0);
    }
    iNode--;
  }

  return 0;
}


static int treeInsertEntry(
  lsm_db *pDb,                    /* Database handle */
  int flags,                      /* Flags associated with entry */
  void *pKey,                     /* Pointer to key data */
  int nKey,                       /* Size of key data in bytes */
  void *pVal,                     /* Pointer to value data (or NULL) */
  int nVal                        /* Bytes in value data (or -ve for delete) */
){
  int rc = LSM_OK;                /* Return Code */
  TreeKey *pTreeKey;              /* New key-value being inserted */
  u32 iTreeKey;
  TreeRoot *p = &pDb->treehdr.root;
  TreeCursor csr;                 /* Cursor to seek to pKey/nKey */
  int res;                        /* Result of seek operation on csr */

  assert( nVal>=0 || pVal==0 );
  assert_tree_looks_ok(LSM_OK, pTree);
  assert( flags==LSM_INSERT       || flags==LSM_POINT_DELETE 
       || flags==LSM_START_DELETE || flags==LSM_END_DELETE 
  );
  assert( (flags & LSM_CONTIGUOUS)==0 );
#if 0
  dump_tree_contents(pDb, "before");
#endif

  if( p->iRoot ){
    TreeKey *pRes;                /* Key at end of seek operation */
    treeCursorInit(pDb, 0, &csr);

    /* Seek to the leaf (or internal node) that the new key belongs on */
    rc = lsmTreeCursorSeek(&csr, pKey, nKey, &res);
    pRes = csrGetKey(&csr, &csr.blob, &rc);
    if( rc!=LSM_OK ) return rc;

    if( flags==LSM_START_DELETE ){
      /* When inserting a start-delete-range entry, if the key that
      ** occurs immediately before the new entry is already a START_DELETE,
      ** then the new entry is not required.  */
      if( (res<=0 && (pRes->flags & LSM_START_DELETE))
       || (res>0  && treePrevIsStartDelete(pDb, &csr))
      ){ 
        goto insert_entry_out;
      }
    }else if( flags==LSM_END_DELETE ){
      /* When inserting an start-delete-range entry, if the key that
      ** occurs immediately after the new entry is already an END_DELETE,
      ** then the new entry is not required.  */
      if( (res<0  && treeNextIsEndDelete(pDb, &csr))
       || (res>=0 && (pRes->flags & LSM_END_DELETE))
      ){
        goto insert_entry_out;
      }
    }

    if( res==0 && (flags & (LSM_END_DELETE|LSM_START_DELETE)) ){
      if( pRes->flags & LSM_INSERT ){
        nVal = pRes->nValue;
        pVal = TKV_VAL(pRes);
      }
      flags = flags | pRes->flags;
    }

    if( flags & (LSM_INSERT|LSM_POINT_DELETE) ){
      if( (res<0 && (pRes->flags & LSM_START_DELETE))
       || (res>0 && (pRes->flags & LSM_END_DELETE)) 
      ){
        flags = flags | (LSM_END_DELETE|LSM_START_DELETE);
      }else if( res==0 ){
        flags = flags | (pRes->flags & (LSM_END_DELETE|LSM_START_DELETE));
      }
    }
  }else{
    memset(&csr, 0, sizeof(TreeCursor));
  }

  /* Allocate and populate a new key-value pair structure */
  pTreeKey = newTreeKey(pDb, &iTreeKey, pKey, nKey, pVal, nVal, &rc);
  if( rc!=LSM_OK ) return rc;
  assert( pTreeKey->flags==0 || pTreeKey->flags==LSM_CONTIGUOUS );
  pTreeKey->flags |= flags;

  if( p->iRoot==0 ){
    /* The tree is completely empty. Add a new root node and install
    ** (pKey/nKey) as the middle entry. Even though it is a leaf at the
    ** moment, use newTreeNode() to allocate the node (i.e. allocate enough
    ** space for the fields used by interior nodes). This is because the
    ** treeInsert() routine may convert this node to an interior node. */
    TreeNode *pRoot = newTreeNode(pDb, &p->iRoot, &rc);
    if( rc==LSM_OK ){
      assert( p->nHeight==0 );
      pRoot->aiKeyPtr[1] = iTreeKey;
      p->nHeight = 1;
    }
  }else{
    if( res==0 ){
      /* The search found a match within the tree. */
      treeOverwriteKey(pDb, &csr, iTreeKey, &rc);
    }else{
      /* The cursor now points to the leaf node into which the new entry should
      ** be inserted. There may or may not be a free slot within the leaf for
      ** the new key-value pair. 
      **
      ** iSlot is set to the index of the key within pLeaf that the new key
      ** should be inserted to the left of (or to a value 1 greater than the
      ** index of the rightmost key if the new key is larger than all keys
      ** currently stored in the node).
      */
      int iSlot = csr.aiCell[csr.iNode] + (res<0);
      if( csr.iNode==0 ){
        rc = treeInsert(pDb, &csr, 0, iTreeKey, 0, iSlot);
      }else{
        rc = treeInsertLeaf(pDb, &csr, iTreeKey, iSlot);
      }
    }
  }

#if 0
  dump_tree_contents(pDb, "after");
#endif
 insert_entry_out:
  tblobFree(pDb, &csr.blob);
  assert_tree_looks_ok(rc, pTree);
  return rc;
}

/*
** Insert a new entry into the in-memory tree.
**
** If the value of the 5th parameter, nVal, is negative, then a delete-marker
** is inserted into the tree. In this case the value pointer, pVal, must be
** NULL.
*/
int lsmTreeInsert(
  lsm_db *pDb,                    /* Database handle */
  void *pKey,                     /* Pointer to key data */
  int nKey,                       /* Size of key data in bytes */
  void *pVal,                     /* Pointer to value data (or NULL) */
  int nVal                        /* Bytes in value data (or -ve for delete) */
){
  int flags;
  if( nVal<0 ){
    flags = LSM_POINT_DELETE;
  }else{
    flags = LSM_INSERT;
  }

  return treeInsertEntry(pDb, flags, pKey, nKey, pVal, nVal);
}

static int treeDeleteEntry(lsm_db *db, TreeCursor *pCsr, u32 iNewptr){
  TreeRoot *p = &db->treehdr.root;
  TreeNode *pNode = pCsr->apTreeNode[pCsr->iNode];
  int iSlot = pCsr->aiCell[pCsr->iNode];
  int bLeaf;
  int rc = LSM_OK;

  assert( pNode->aiKeyPtr[1] );
  assert( pNode->aiKeyPtr[iSlot] );
  assert( iSlot==0 || iSlot==1 || iSlot==2 );
  assert( (pCsr->iNode==(db->treehdr.root.nHeight-1))==(iNewptr==0) );

  bLeaf = (pCsr->iNode==(p->nHeight-1) && p->nHeight>1);
  
  if( pNode->aiKeyPtr[0] || pNode->aiKeyPtr[2] ){
    /* There are currently at least 2 keys on this node. So just create
    ** a new copy of the node with one of the keys removed. If the node
    ** happens to be the root node of the tree, allocate an entire 
    ** TreeNode structure instead of just a TreeLeaf.  */
    TreeNode *pNew;
    u32 iNew;

    if( bLeaf ){
      pNew = (TreeNode *)newTreeLeaf(db, &iNew, &rc);
    }else{
      pNew = newTreeNode(db, &iNew, &rc);
    }
    if( pNew ){
      int i;
      int iOut = 1;
      for(i=0; i<4; i++){
        if( i==iSlot ){
          i++;
          if( bLeaf==0 ) pNew->aiChildPtr[iOut] = iNewptr;
          if( i<3 ) pNew->aiKeyPtr[iOut] = pNode->aiKeyPtr[i];
          iOut++;
        }else if( bLeaf || p->nHeight==1 ){
          if( i<3 && pNode->aiKeyPtr[i] ){
            pNew->aiKeyPtr[iOut++] = pNode->aiKeyPtr[i];
          }
        }else{
          if( getChildPtr(pNode, WORKING_VERSION, i) ){
            pNew->aiChildPtr[iOut] = getChildPtr(pNode, WORKING_VERSION, i);
            if( i<3 ) pNew->aiKeyPtr[iOut] = pNode->aiKeyPtr[i];
            iOut++;
          }
        }
      }
      assert( iOut<=4 );
      assert( bLeaf || pNew->aiChildPtr[0]==0 );
      pCsr->iNode--;
      rc = treeUpdatePtr(db, pCsr, iNew);
    }

  }else if( pCsr->iNode==0 ){
    /* Removing the only key in the root node. iNewptr is the new root. */
    assert( iSlot==1 );
    db->treehdr.root.iRoot = iNewptr;
    db->treehdr.root.nHeight--;

  }else{
    /* There is only one key on this node and the node is not the root
    ** node. Find a peer for this node. Then redistribute the contents of
    ** the peer and the parent cell between the parent and either one or
    ** two new nodes.  */
    TreeNode *pParent;            /* Parent tree node */
    int iPSlot;
    u32 iPeer;                    /* Pointer to peer leaf node */
    int iDir;
    TreeNode *pPeer;              /* The peer leaf node */
    TreeNode *pNew1; u32 iNew1;   /* First new leaf node */

    assert( iSlot==1 );

    pParent = pCsr->apTreeNode[pCsr->iNode-1];
    iPSlot = pCsr->aiCell[pCsr->iNode-1];

    if( iPSlot>0 && getChildPtr(pParent, WORKING_VERSION, iPSlot-1) ){
      iDir = -1;
    }else{
      iDir = +1;
    }
    iPeer = getChildPtr(pParent, WORKING_VERSION, iPSlot+iDir);
    pPeer = (TreeNode *)treeShmptr(db, iPeer);
    assertIsWorkingChild(db, pNode, pParent, iPSlot);

    /* Allocate the first new leaf node. This is always required. */
    if( bLeaf ){
      pNew1 = (TreeNode *)newTreeLeaf(db, &iNew1, &rc);
    }else{
      pNew1 = (TreeNode *)newTreeNode(db, &iNew1, &rc);
    }

    if( pPeer->aiKeyPtr[0] && pPeer->aiKeyPtr[2] ){
      /* Peer node is completely full. This means that two new leaf nodes
      ** and a new parent node are required. */

      TreeNode *pNew2; u32 iNew2; /* Second new leaf node */
      TreeNode *pNewP; u32 iNewP; /* New parent node */

      if( bLeaf ){
        pNew2 = (TreeNode *)newTreeLeaf(db, &iNew2, &rc);
      }else{
        pNew2 = (TreeNode *)newTreeNode(db, &iNew2, &rc);
      }
      pNewP = copyTreeNode(db, pParent, &iNewP, &rc);

      if( iDir==-1 ){
        pNew1->aiKeyPtr[1] = pPeer->aiKeyPtr[0];
        if( bLeaf==0 ){
          pNew1->aiChildPtr[1] = getChildPtr(pPeer, WORKING_VERSION, 0);
          pNew1->aiChildPtr[2] = getChildPtr(pPeer, WORKING_VERSION, 1);
        }

        pNewP->aiChildPtr[iPSlot-1] = iNew1;
        pNewP->aiKeyPtr[iPSlot-1] = pPeer->aiKeyPtr[1];
        pNewP->aiChildPtr[iPSlot] = iNew2;

        pNew2->aiKeyPtr[0] = pPeer->aiKeyPtr[2];
        pNew2->aiKeyPtr[1] = pParent->aiKeyPtr[iPSlot-1];
        if( bLeaf==0 ){
          pNew2->aiChildPtr[0] = getChildPtr(pPeer, WORKING_VERSION, 2);
          pNew2->aiChildPtr[1] = getChildPtr(pPeer, WORKING_VERSION, 3);
          pNew2->aiChildPtr[2] = iNewptr;
        }
      }else{
        pNew1->aiKeyPtr[1] = pParent->aiKeyPtr[iPSlot];
        if( bLeaf==0 ){
          pNew1->aiChildPtr[1] = iNewptr;
          pNew1->aiChildPtr[2] = getChildPtr(pPeer, WORKING_VERSION, 0);
        }

        pNewP->aiChildPtr[iPSlot] = iNew1;
        pNewP->aiKeyPtr[iPSlot] = pPeer->aiKeyPtr[0];
        pNewP->aiChildPtr[iPSlot+1] = iNew2;

        pNew2->aiKeyPtr[0] = pPeer->aiKeyPtr[1];
        pNew2->aiKeyPtr[1] = pPeer->aiKeyPtr[2];
        if( bLeaf==0 ){
          pNew2->aiChildPtr[0] = getChildPtr(pPeer, WORKING_VERSION, 1);
          pNew2->aiChildPtr[1] = getChildPtr(pPeer, WORKING_VERSION, 2);
          pNew2->aiChildPtr[2] = getChildPtr(pPeer, WORKING_VERSION, 3);
        }
      }
      assert( pCsr->iNode>=1 );
      pCsr->iNode -= 2;
      if( rc==LSM_OK ){
        assert( pNew1->aiKeyPtr[1] && pNew2->aiKeyPtr[1] );
        rc = treeUpdatePtr(db, pCsr, iNewP);
      }
    }else{
      int iKOut = 0;
      int iPOut = 0;
      int i;

      pCsr->iNode--;

      if( iDir==1 ){
        pNew1->aiKeyPtr[iKOut++] = pParent->aiKeyPtr[iPSlot];
        if( bLeaf==0 ) pNew1->aiChildPtr[iPOut++] = iNewptr;
      }
      for(i=0; i<3; i++){
        if( pPeer->aiKeyPtr[i] ){
          pNew1->aiKeyPtr[iKOut++] = pPeer->aiKeyPtr[i];
        }
      }
      if( bLeaf==0 ){
        for(i=0; i<4; i++){
          if( getChildPtr(pPeer, WORKING_VERSION, i) ){
            pNew1->aiChildPtr[iPOut++] = getChildPtr(pPeer, WORKING_VERSION, i);
          }
        }
      }
      if( iDir==-1 ){
        iPSlot--;
        pNew1->aiKeyPtr[iKOut++] = pParent->aiKeyPtr[iPSlot];
        if( bLeaf==0 ) pNew1->aiChildPtr[iPOut++] = iNewptr;
        pCsr->aiCell[pCsr->iNode] = iPSlot;
      }

      rc = treeDeleteEntry(db, pCsr, iNew1);
    }
  }

  return rc;
}

/*
** Delete a range of keys from the tree structure (i.e. the lsm_delete_range()
** function, not lsm_delete()).
**
** This is a two step process: 
**
**     1) Remove all entries currently stored in the tree that have keys
**        that fall into the deleted range.
**
**        TODO: There are surely good ways to optimize this step - removing 
**        a range of keys from a b-tree. But for now, this function removes
**        them one at a time using the usual approach.
**
**     2) Unless the largest key smaller than or equal to (pKey1/nKey1) is
**        already marked as START_DELETE, insert a START_DELETE key. 
**        Similarly, unless the smallest key greater than or equal to
**        (pKey2/nKey2) is already START_END, insert a START_END key.
*/
int lsmTreeDelete(
  lsm_db *db,
  void *pKey1, int nKey1,         /* Start of range */
  void *pKey2, int nKey2          /* End of range */
){
  int rc = LSM_OK;
  int bDone = 0;
  TreeRoot *p = &db->treehdr.root;
  TreeBlob blob = {0, 0};

  /* The range must be sensible - that (key1 < key2). */
  assert( treeKeycmp(pKey1, nKey1, pKey2, nKey2)<0 );
  assert( assert_delete_ranges_match(db) );

#if 0
  static int nCall = 0;
  printf("\n");
  nCall++;
  printf("%d delete %s .. %s\n", nCall, (char *)pKey1, (char *)pKey2);
  dump_tree_contents(db, "before delete");
#endif

  /* Step 1. This loop runs until the tree contains no keys within the
  ** range being deleted. Or until an error occurs. */
  while( bDone==0 && rc==LSM_OK ){
    int res;
    TreeCursor csr;               /* Cursor to seek to first key in range */
    void *pDel; int nDel;         /* Key to (possibly) delete this iteration */
#ifndef NDEBUG
    int nEntry = treeCountEntries(db);
#endif

    /* Seek the cursor to the first entry in the tree greater than pKey1. */
    treeCursorInit(db, 0, &csr);
    lsmTreeCursorSeek(&csr, pKey1, nKey1, &res);
    if( res<=0 && lsmTreeCursorValid(&csr) ) lsmTreeCursorNext(&csr);

    /* If there is no such entry, or if it is greater than pKey2, then the
    ** tree now contains no keys in the range being deleted. In this case
    ** break out of the loop.  */
    bDone = 1;
    if( lsmTreeCursorValid(&csr) ){
      lsmTreeCursorKey(&csr, 0, &pDel, &nDel);
      if( treeKeycmp(pDel, nDel, pKey2, nKey2)<0 ) bDone = 0;
    }

    if( bDone==0 ){
      if( csr.iNode==(p->nHeight-1) ){
        /* The element to delete already lies on a leaf node */
        rc = treeDeleteEntry(db, &csr, 0);
      }else{
        /* 1. Overwrite the current key with a copy of the next key in the 
        **    tree (key N).
        **
        ** 2. Seek to key N (cursor will stop at the internal node copy of
        **    N). Move to the next key (original copy of N). Delete
        **    this entry. 
        */
        u32 iKey;
        TreeKey *pKey;
        int iNode = csr.iNode;
        lsmTreeCursorNext(&csr);
        assert( csr.iNode==(p->nHeight-1) );

        iKey = csr.apTreeNode[csr.iNode]->aiKeyPtr[csr.aiCell[csr.iNode]];
        lsmTreeCursorPrev(&csr);

        treeOverwriteKey(db, &csr, iKey, &rc);
        pKey = treeShmkey(db, iKey, TKV_LOADKEY, &blob, &rc);
        if( pKey ){
          rc = lsmTreeCursorSeek(&csr, TKV_KEY(pKey), pKey->nKey, &res);
        }
        if( rc==LSM_OK ){
          assert( res==0 && csr.iNode==iNode );
          rc = lsmTreeCursorNext(&csr);
          if( rc==LSM_OK ){
            rc = treeDeleteEntry(db, &csr, 0);
          }
        }
      }
    }

    /* Clean up any memory allocated by the cursor. */
    tblobFree(db, &csr.blob);
#if 0
    dump_tree_contents(db, "ddd delete");
#endif
    assert( bDone || treeCountEntries(db)==(nEntry-1) );
  }

#if 0
  dump_tree_contents(db, "during delete");
#endif

  /* Now insert the START_DELETE and END_DELETE keys. */
  if( rc==LSM_OK ){
    rc = treeInsertEntry(db, LSM_START_DELETE, pKey1, nKey1, 0, -1);
  }
#if 0
  dump_tree_contents(db, "during delete 2");
#endif
  if( rc==LSM_OK ){
    rc = treeInsertEntry(db, LSM_END_DELETE, pKey2, nKey2, 0, -1);
  }

#if 0
  dump_tree_contents(db, "after delete");
#endif

  tblobFree(db, &blob);
  assert( assert_delete_ranges_match(db) );
  return rc;
}

/*
** Return, in bytes, the amount of memory currently used by the tree 
** structure.
*/
int lsmTreeSize(lsm_db *pDb){
  return pDb->treehdr.root.nByte;
}

/*
** Open a cursor on the in-memory tree pTree.
*/
int lsmTreeCursorNew(lsm_db *pDb, int bOld, TreeCursor **ppCsr){
  TreeCursor *pCsr;
  *ppCsr = pCsr = lsmMalloc(pDb->pEnv, sizeof(TreeCursor));
  if( pCsr ){
    treeCursorInit(pDb, bOld, pCsr);
    return LSM_OK;
  }
  return LSM_NOMEM_BKPT;
}

/*
** Close an in-memory tree cursor.
*/
void lsmTreeCursorDestroy(TreeCursor *pCsr){
  if( pCsr ){
    tblobFree(pCsr->pDb, &pCsr->blob);
    lsmFree(pCsr->pDb->pEnv, pCsr);
  }
}

void lsmTreeCursorReset(TreeCursor *pCsr){
  if( pCsr ){
    pCsr->iNode = -1;
    pCsr->pSave = 0;
  }
}

#ifndef NDEBUG
static int treeCsrCompare(TreeCursor *pCsr, void *pKey, int nKey){
  TreeKey *p;
  int cmp = 0;
  int rc = LSM_OK;
  assert( pCsr->iNode>=0 );
  p = csrGetKey(pCsr, &pCsr->blob, &rc);
  if( p ){
    cmp = treeKeycmp(TKV_KEY(p), p->nKey, pKey, nKey);
  }
  return cmp;
}
#endif


/*
** Attempt to seek the cursor passed as the first argument to key (pKey/nKey)
** in the tree structure. If an exact match for the key is found, leave the
** cursor pointing to it and set *pRes to zero before returning. If an
** exact match cannot be found, do one of the following:
**
**   * Leave the cursor pointing to the smallest element in the tree that 
**     is larger than the key and set *pRes to +1, or
**
**   * Leave the cursor pointing to the largest element in the tree that 
**     is smaller than the key and set *pRes to -1, or
**
**   * If the tree is empty, leave the cursor at EOF and set *pRes to -1.
*/
int lsmTreeCursorSeek(TreeCursor *pCsr, void *pKey, int nKey, int *pRes){
  int rc = LSM_OK;                /* Return code */
  lsm_db *pDb = pCsr->pDb;
  TreeRoot *pRoot = pCsr->pRoot;
  u32 iNodePtr;                   /* Location of current node in search */

  /* Discard any saved position data */
  treeCursorRestore(pCsr, 0);

  iNodePtr = pRoot->iRoot;
  if( iNodePtr==0 ){
    /* Either an error occurred or the tree is completely empty. */
    assert( rc!=LSM_OK || pRoot->iRoot==0 );
    *pRes = -1;
    pCsr->iNode = -1;
  }else{
    TreeBlob b = {0, 0};
    int res = 0;                  /* Result of comparison function */
    int iNode = -1;
    while( iNodePtr ){
      TreeNode *pNode;            /* Node at location iNodePtr */
      int iTest;                  /* Index of second key to test (0 or 2) */
      u32 iTreeKey;
      TreeKey *pTreeKey;          /* Key to compare against */

      pNode = (TreeNode *)treeShmptrUnsafe(pDb, iNodePtr);
      iNode++;
      pCsr->apTreeNode[iNode] = pNode;

      /* Compare (pKey/nKey) with the key in the middle slot of B-tree node
      ** pNode. The middle slot is never empty. If the comparison is a match,
      ** then the search is finished. Break out of the loop. */
      pTreeKey = (TreeKey*)treeShmptrUnsafe(pDb, pNode->aiKeyPtr[1]);
      if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){
        pTreeKey = treeShmkey(pDb, pNode->aiKeyPtr[1], TKV_LOADKEY, &b, &rc);
        if( rc!=LSM_OK ) break;
      }
      res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey);
      if( res==0 ){
        pCsr->aiCell[iNode] = 1;
        break;
      }

      /* Based on the results of the previous comparison, compare (pKey/nKey)
      ** to either the left or right key of the B-tree node, if such a key
      ** exists. */
      iTest = (res>0 ? 0 : 2);
      iTreeKey = pNode->aiKeyPtr[iTest];
      if( iTreeKey ){
        pTreeKey = (TreeKey*)treeShmptrUnsafe(pDb, iTreeKey);
        if( !(pTreeKey->flags & LSM_CONTIGUOUS) ){
          pTreeKey = treeShmkey(pDb, iTreeKey, TKV_LOADKEY, &b, &rc);
          if( rc ) break;
        }
        res = treeKeycmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey);
        if( res==0 ){
          pCsr->aiCell[iNode] = iTest;
          break;
        }
      }else{
        iTest = 1;
      }

      if( iNode<(pRoot->nHeight-1) ){
        iNodePtr = getChildPtr(pNode, pRoot->iTransId, iTest + (res<0));
      }else{
        iNodePtr = 0;
      }
      pCsr->aiCell[iNode] = iTest + (iNodePtr && (res<0));
    }

    *pRes = res;
    pCsr->iNode = iNode;
    tblobFree(pDb, &b);
  }

  /* assert() that *pRes has been set properly */
#ifndef NDEBUG
  if( rc==LSM_OK && lsmTreeCursorValid(pCsr) ){
    int cmp = treeCsrCompare(pCsr, pKey, nKey);
    assert( *pRes==cmp || (*pRes ^ cmp)>0 );
  }
#endif

  return rc;
}

int lsmTreeCursorNext(TreeCursor *pCsr){
#ifndef NDEBUG
  TreeKey *pK1;
  TreeBlob key1 = {0, 0};
#endif
  lsm_db *pDb = pCsr->pDb;
  TreeRoot *pRoot = pCsr->pRoot;
  const int iLeaf = pRoot->nHeight-1;
  int iCell; 
  int rc = LSM_OK; 
  TreeNode *pNode; 

  /* Restore the cursor position, if required */
  int iRestore = 0;
  treeCursorRestore(pCsr, &iRestore);
  if( iRestore>0 ) return LSM_OK;

  /* Save a pointer to the current key. This is used in an assert() at the
  ** end of this function - to check that the 'next' key really is larger
  ** than the current key. */
#ifndef NDEBUG
  pK1 = csrGetKey(pCsr, &key1, &rc);
  if( rc!=LSM_OK ) return rc;
#endif

  assert( lsmTreeCursorValid(pCsr) );
  assert( pCsr->aiCell[pCsr->iNode]<3 );

  pNode = pCsr->apTreeNode[pCsr->iNode];
  iCell = ++pCsr->aiCell[pCsr->iNode];

  /* If the current node is not a leaf, and the current cell has sub-tree
  ** associated with it, descend to the left-most key on the left-most
  ** leaf of the sub-tree.  */
  if( pCsr->iNode<iLeaf && getChildPtr(pNode, pRoot->iTransId, iCell) ){
    do {
      u32 iNodePtr;
      pCsr->iNode++;
      iNodePtr = getChildPtr(pNode, pRoot->iTransId, iCell);
      pNode = (TreeNode *)treeShmptr(pDb, iNodePtr);
      pCsr->apTreeNode[pCsr->iNode] = pNode;
      iCell = pCsr->aiCell[pCsr->iNode] = (pNode->aiKeyPtr[0]==0);
    }while( pCsr->iNode < iLeaf );
  }

  /* Otherwise, the next key is found by following pointer up the tree 
  ** until there is a key immediately to the right of the pointer followed 
  ** to reach the sub-tree containing the current key. */
  else if( iCell>=3 || pNode->aiKeyPtr[iCell]==0 ){
    while( (--pCsr->iNode)>=0 ){
      iCell = pCsr->aiCell[pCsr->iNode];
      if( iCell<3 && pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[iCell] ) break;
    }
  }

#ifndef NDEBUG
  if( pCsr->iNode>=0 ){
    TreeKey *pK2 = csrGetKey(pCsr, &pCsr->blob, &rc);
    assert( rc||treeKeycmp(TKV_KEY(pK2),pK2->nKey,TKV_KEY(pK1),pK1->nKey)>=0 );
  }
  tblobFree(pDb, &key1);
#endif

  return rc;
}

int lsmTreeCursorPrev(TreeCursor *pCsr){
#ifndef NDEBUG
  TreeKey *pK1;
  TreeBlob key1 = {0, 0};
#endif
  lsm_db *pDb = pCsr->pDb;
  TreeRoot *pRoot = pCsr->pRoot;
  const int iLeaf = pRoot->nHeight-1;
  int iCell; 
  int rc = LSM_OK; 
  TreeNode *pNode; 

  /* Restore the cursor position, if required */
  int iRestore = 0;
  treeCursorRestore(pCsr, &iRestore);
  if( iRestore<0 ) return LSM_OK;

  /* Save a pointer to the current key. This is used in an assert() at the
  ** end of this function - to check that the 'next' key really is smaller
  ** than the current key. */
#ifndef NDEBUG
  pK1 = csrGetKey(pCsr, &key1, &rc);
  if( rc!=LSM_OK ) return rc;
#endif

  assert( lsmTreeCursorValid(pCsr) );
  pNode = pCsr->apTreeNode[pCsr->iNode];
  iCell = pCsr->aiCell[pCsr->iNode];
  assert( iCell>=0 && iCell<3 );

  /* If the current node is not a leaf, and the current cell has sub-tree
  ** associated with it, descend to the right-most key on the right-most
  ** leaf of the sub-tree.  */
  if( pCsr->iNode<iLeaf && getChildPtr(pNode, pRoot->iTransId, iCell) ){
    do {
      u32 iNodePtr;
      pCsr->iNode++;
      iNodePtr = getChildPtr(pNode, pRoot->iTransId, iCell);
      pNode = (TreeNode *)treeShmptr(pDb, iNodePtr);
      if( rc!=LSM_OK ) break;
      pCsr->apTreeNode[pCsr->iNode] = pNode;
      iCell = 1 + (pNode->aiKeyPtr[2]!=0) + (pCsr->iNode < iLeaf);
      pCsr->aiCell[pCsr->iNode] = iCell;
    }while( pCsr->iNode < iLeaf );
  }

  /* Otherwise, the next key is found by following pointer up the tree until
  ** there is a key immediately to the left of the pointer followed to reach
  ** the sub-tree containing the current key. */
  else{
    do {
      iCell = pCsr->aiCell[pCsr->iNode]-1;
      if( iCell>=0 && pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[iCell] ) break;
    }while( (--pCsr->iNode)>=0 );
    pCsr->aiCell[pCsr->iNode] = iCell;
  }

#ifndef NDEBUG
  if( pCsr->iNode>=0 ){
    TreeKey *pK2 = csrGetKey(pCsr, &pCsr->blob, &rc);
    assert( rc || treeKeycmp(TKV_KEY(pK2),pK2->nKey,TKV_KEY(pK1),pK1->nKey)<0 );
  }
  tblobFree(pDb, &key1);
#endif

  return rc;
}

/*
** Move the cursor to the first (bLast==0) or last (bLast!=0) entry in the
** in-memory tree.
*/
int lsmTreeCursorEnd(TreeCursor *pCsr, int bLast){
  lsm_db *pDb = pCsr->pDb;
  TreeRoot *pRoot = pCsr->pRoot;
  int rc = LSM_OK;

  u32 iNodePtr;
  pCsr->iNode = -1;

  /* Discard any saved position data */
  treeCursorRestore(pCsr, 0);

  iNodePtr = pRoot->iRoot;
  while( iNodePtr ){
    int iCell;
    TreeNode *pNode;

    pNode = (TreeNode *)treeShmptr(pDb, iNodePtr);
    if( rc ) break;

    if( bLast ){
      iCell = ((pNode->aiKeyPtr[2]==0) ? 2 : 3);
    }else{
      iCell = ((pNode->aiKeyPtr[0]==0) ? 1 : 0);
    }
    pCsr->iNode++;
    pCsr->apTreeNode[pCsr->iNode] = pNode;

    if( pCsr->iNode<pRoot->nHeight-1 ){
      iNodePtr = getChildPtr(pNode, pRoot->iTransId, iCell);
    }else{
      iNodePtr = 0;
    }
    pCsr->aiCell[pCsr->iNode] = iCell - (iNodePtr==0 && bLast);
  }

  return rc;
}

int lsmTreeCursorFlags(TreeCursor *pCsr){
  int flags = 0;
  if( pCsr && pCsr->iNode>=0 ){
    int rc = LSM_OK;
    TreeKey *pKey = (TreeKey *)treeShmptrUnsafe(pCsr->pDb,
        pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]]
    );
    assert( rc==LSM_OK );
    flags = (pKey->flags & ~LSM_CONTIGUOUS);
  }
  return flags;
}

int lsmTreeCursorKey(TreeCursor *pCsr, int *pFlags, void **ppKey, int *pnKey){
  TreeKey *pTreeKey;
  int rc = LSM_OK;

  assert( lsmTreeCursorValid(pCsr) );

  pTreeKey = pCsr->pSave;
  if( !pTreeKey ){
    pTreeKey = csrGetKey(pCsr, &pCsr->blob, &rc);
  }
  if( rc==LSM_OK ){
    *pnKey = pTreeKey->nKey;
    if( pFlags ) *pFlags = pTreeKey->flags;
    *ppKey = (void *)&pTreeKey[1];
  }

  return rc;
}

int lsmTreeCursorValue(TreeCursor *pCsr, void **ppVal, int *pnVal){
  int res = 0;
  int rc;

  rc = treeCursorRestore(pCsr, &res);
  if( res==0 ){
    TreeKey *pTreeKey = csrGetKey(pCsr, &pCsr->blob, &rc);
    if( rc==LSM_OK ){
      if( pTreeKey->flags & LSM_INSERT ){
        *pnVal = pTreeKey->nValue;
        *ppVal = TKV_VAL(pTreeKey);
      }else{
        *ppVal = 0;
        *pnVal = -1;
      }
    }
  }else{
    *ppVal = 0;
    *pnVal = 0;
  }

  return rc;
}

/*
** Return true if the cursor currently points to a valid entry. 
*/
int lsmTreeCursorValid(TreeCursor *pCsr){
  return (pCsr && (pCsr->pSave || pCsr->iNode>=0));
}

/*
** Store a mark in *pMark. Later on, a call to lsmTreeRollback() with a
** pointer to the same TreeMark structure may be used to roll the tree
** contents back to their current state.
*/
void lsmTreeMark(lsm_db *pDb, TreeMark *pMark){
  pMark->iRoot = pDb->treehdr.root.iRoot;
  pMark->nHeight = pDb->treehdr.root.nHeight;
  pMark->iWrite = pDb->treehdr.iWrite;
  pMark->nChunk = pDb->treehdr.nChunk;
  pMark->iNextShmid = pDb->treehdr.iNextShmid;
  pMark->iRollback = intArraySize(&pDb->rollback);
}

/*
** Roll back to mark pMark. Structure *pMark should have been previously
** populated by a call to lsmTreeMark().
*/
void lsmTreeRollback(lsm_db *pDb, TreeMark *pMark){
  int iIdx;
  int nIdx;
  u32 iNext;
  ShmChunk *pChunk;
  u32 iChunk;
  u32 iShmid;

  /* Revert all required v2 pointers. */
  nIdx = intArraySize(&pDb->rollback);
  for(iIdx = pMark->iRollback; iIdx<nIdx; iIdx++){
    TreeNode *pNode;
    pNode = treeShmptr(pDb, intArrayEntry(&pDb->rollback, iIdx));
    assert( pNode );
    pNode->iV2 = 0;
    pNode->iV2Child = 0;
    pNode->iV2Ptr = 0;
  }
  intArrayTruncate(&pDb->rollback, pMark->iRollback);

  /* Restore the free-chunk list. */
  assert( pMark->iWrite!=0 );
  iChunk = treeOffsetToChunk(pMark->iWrite-1);
  pChunk = treeShmChunk(pDb, iChunk);
  iNext = pChunk->iNext;
  pChunk->iNext = 0;

  pChunk = treeShmChunk(pDb, pDb->treehdr.iFirst);
  iShmid = pChunk->iShmid-1;

  while( iNext ){
    u32 iFree = iNext;            /* Current chunk being rollback-freed */
    ShmChunk *pFree;              /* Pointer to chunk iFree */

    pFree = treeShmChunk(pDb, iFree);
    iNext = pFree->iNext;

    if( iFree<pMark->nChunk ){
      pFree->iNext = pDb->treehdr.iFirst;
      pFree->iShmid = iShmid--;
      pDb->treehdr.iFirst = iFree;
    }
  }

  /* Restore the tree-header fields */
  pDb->treehdr.root.iRoot = pMark->iRoot;
  pDb->treehdr.root.nHeight = pMark->nHeight;
  pDb->treehdr.iWrite = pMark->iWrite;
  pDb->treehdr.nChunk = pMark->nChunk;
  pDb->treehdr.iNextShmid = pMark->iNextShmid;
}

/*
** Load the in-memory tree header from shared-memory into pDb->treehdr.
** If the header cannot be loaded, return LSM_PROTOCOL.
**
** If the header is successfully loaded and parameter piRead is not NULL,
** is is set to 1 if the header was loaded from ShmHeader.hdr1, or 2 if
** the header was loaded from ShmHeader.hdr2.
*/
int lsmTreeLoadHeader(lsm_db *pDb, int *piRead){
  int nRem = LSM_ATTEMPTS_BEFORE_PROTOCOL;
  while( (nRem--)>0 ){
    ShmHeader *pShm = pDb->pShmhdr;

    memcpy(&pDb->treehdr, &pShm->hdr1, sizeof(TreeHeader));
    if( treeHeaderChecksumOk(&pDb->treehdr) ){
      if( piRead ) *piRead = 1;
      return LSM_OK;
    }
    memcpy(&pDb->treehdr, &pShm->hdr2, sizeof(TreeHeader));
    if( treeHeaderChecksumOk(&pDb->treehdr) ){
      if( piRead ) *piRead = 2;
      return LSM_OK;
    }

    lsmShmBarrier(pDb);
  }
  return LSM_PROTOCOL_BKPT;
}

int lsmTreeLoadHeaderOk(lsm_db *pDb, int iRead){
  TreeHeader *p = (iRead==1) ? &pDb->pShmhdr->hdr1 : &pDb->pShmhdr->hdr2;
  assert( iRead==1 || iRead==2 );
  return (0==memcmp(pDb->treehdr.aCksum, p->aCksum, sizeof(u32)*2));
}

/*
** This function is called to conclude a transaction. If argument bCommit
** is true, the transaction is committed. Otherwise it is rolled back.
*/
int lsmTreeEndTransaction(lsm_db *pDb, int bCommit){
  ShmHeader *pShm = pDb->pShmhdr;

  treeHeaderChecksum(&pDb->treehdr, pDb->treehdr.aCksum);
  memcpy(&pShm->hdr2, &pDb->treehdr, sizeof(TreeHeader));
  lsmShmBarrier(pDb);
  memcpy(&pShm->hdr1, &pDb->treehdr, sizeof(TreeHeader));
  pShm->bWriter = 0;
  intArrayFree(pDb->pEnv, &pDb->rollback);

  return LSM_OK;
}

#ifndef NDEBUG
static int assert_delete_ranges_match(lsm_db *db){
  int prev = 0;
  TreeBlob blob = {0, 0};
  TreeCursor csr;               /* Cursor used to iterate through tree */
  int rc;

  treeCursorInit(db, 0, &csr);
  for( rc = lsmTreeCursorEnd(&csr, 0);
       rc==LSM_OK && lsmTreeCursorValid(&csr);
       rc = lsmTreeCursorNext(&csr)
  ){
    TreeKey *pKey = csrGetKey(&csr, &blob, &rc);
    if( rc!=LSM_OK ) break;
    assert( ((prev&LSM_START_DELETE)==0)==((pKey->flags&LSM_END_DELETE)==0) );
    prev = pKey->flags;
  }

  tblobFree(csr.pDb, &csr.blob);
  tblobFree(csr.pDb, &blob);

  return 1;
}

static int treeCountEntries(lsm_db *db){
  TreeCursor csr;               /* Cursor used to iterate through tree */
  int rc;
  int nEntry = 0;

  treeCursorInit(db, 0, &csr);
  for( rc = lsmTreeCursorEnd(&csr, 0);
       rc==LSM_OK && lsmTreeCursorValid(&csr);
       rc = lsmTreeCursorNext(&csr)
  ){
    nEntry++;
  }

  tblobFree(csr.pDb, &csr.blob);

  return nEntry;
}
#endif

/************** End of lsm_tree.c ********************************************/
/************** Begin file lsm_unix.c ****************************************/
/*
** 2011-12-03
**
** 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.
**
*************************************************************************
**
** Unix-specific run-time environment implementation for LSM.
*/
#if defined(__GNUC__) || defined(__TINYC__)
/* workaround for ftruncate() visibility on gcc. */
# ifndef _XOPEN_SOURCE
#  define _XOPEN_SOURCE 500
# endif
#endif

/* #include <unistd.h> */
/* #include <sys/types.h> */

/* #include <sys/stat.h> */
/* #include <fcntl.h> */
/* #include <assert.h> */
/* #include <string.h> */

/* #include <stdlib.h> */
/* #include <stdarg.h> */
/* #include <stdio.h> */
/* #include <ctype.h> */

/* #include <unistd.h> */
#include <errno.h>

#include <sys/mman.h>

/* There is no fdatasync() call on Android */
#ifdef __ANDROID__
# define fdatasync(x) fsync(x)
#endif

/*
** An open file is an instance of the following object
*/
typedef struct PosixFile PosixFile;
struct PosixFile {
  lsm_env *pEnv;                  /* The run-time environment */
  const char *zName;              /* Full path to file */
  int fd;                         /* The open file descriptor */
  int shmfd;                      /* Shared memory file-descriptor */
  void *pMap;                     /* Pointer to mapping of file fd */
  off_t nMap;                     /* Size of mapping at pMap in bytes */
  int nShm;                       /* Number of entries in array apShm[] */
  void **apShm;                   /* Array of 32K shared memory segments */
};

static char *posixShmFile(PosixFile *p){
  char *zShm;
  int nName = strlen(p->zName);
  zShm = (char *)lsmMalloc(p->pEnv, nName+4+1);
  if( zShm ){
    memcpy(zShm, p->zName, nName);
    memcpy(&zShm[nName], "-shm", 5);
  }
  return zShm;
}

static int lsmPosixOsOpen(
  lsm_env *pEnv,
  const char *zFile,
  int flags,
  lsm_file **ppFile
){
  int rc = LSM_OK;
  PosixFile *p;

  p = lsm_malloc(pEnv, sizeof(PosixFile));
  if( p==0 ){
    rc = LSM_NOMEM;
  }else{
    int bReadonly = (flags & LSM_OPEN_READONLY);
    int oflags = (bReadonly ? O_RDONLY : (O_RDWR|O_CREAT));
    memset(p, 0, sizeof(PosixFile));
    p->zName = zFile;
    p->pEnv = pEnv;
    p->fd = open(zFile, oflags, 0644);
    if( p->fd<0 ){
      lsm_free(pEnv, p);
      p = 0;
      if( errno==ENOENT ){
        rc = lsmErrorBkpt(LSM_IOERR_NOENT);
      }else{
        rc = LSM_IOERR_BKPT;
      }
    }
  }

  *ppFile = (lsm_file *)p;
  return rc;
}

static int lsmPosixOsWrite(
  lsm_file *pFile,                /* File to write to */
  lsm_i64 iOff,                   /* Offset to write to */
  void *pData,                    /* Write data from this buffer */
  int nData                       /* Bytes of data to write */
){
  int rc = LSM_OK;
  PosixFile *p = (PosixFile *)pFile;
  off_t offset;

  offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
  if( offset!=iOff ){
    rc = LSM_IOERR_BKPT;
  }else{
    ssize_t prc = write(p->fd, pData, (size_t)nData);
    if( prc<0 ) rc = LSM_IOERR_BKPT;
  }

  return rc;
}

static int lsmPosixOsTruncate(
  lsm_file *pFile,                /* File to write to */
  lsm_i64 nSize                   /* Size to truncate file to */
){
  PosixFile *p = (PosixFile *)pFile;
  int rc = LSM_OK;                /* Return code */
  int prc;                        /* Posix Return Code */
  struct stat sStat;              /* Result of fstat() invocation */
  
  prc = fstat(p->fd, &sStat);
  if( prc==0 && sStat.st_size>nSize ){
    prc = ftruncate(p->fd, (off_t)nSize);
  }
  if( prc<0 ) rc = LSM_IOERR_BKPT;

  return rc;
}

static int lsmPosixOsRead(
  lsm_file *pFile,                /* File to read from */
  lsm_i64 iOff,                   /* Offset to read from */
  void *pData,                    /* Read data into this buffer */
  int nData                       /* Bytes of data to read */
){
  int rc = LSM_OK;
  PosixFile *p = (PosixFile *)pFile;
  off_t offset;

  offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
  if( offset!=iOff ){
    rc = LSM_IOERR_BKPT;
  }else{
    ssize_t prc = read(p->fd, pData, (size_t)nData);
    if( prc<0 ){ 
      rc = LSM_IOERR_BKPT;
    }else if( prc<nData ){
      memset(&((u8 *)pData)[prc], 0, nData - prc);
    }

  }

  return rc;
}

static int lsmPosixOsSync(lsm_file *pFile){
  int rc = LSM_OK;

#ifndef LSM_NO_SYNC
  PosixFile *p = (PosixFile *)pFile;
  int prc = 0;

  if( p->pMap ){
    prc = msync(p->pMap, p->nMap, MS_SYNC);
  }
  if( prc==0 ) prc = fdatasync(p->fd);
  if( prc<0 ) rc = LSM_IOERR_BKPT;
#else
  (void)pFile;
#endif

  return rc;
}

static int lsmPosixOsSectorSize(lsm_file *pFile){
  return 512;
}

static int lsmPosixOsRemap(
  lsm_file *pFile, 
  lsm_i64 iMin, 
  void **ppOut,
  lsm_i64 *pnOut
){
  off_t iSz;
  int prc;
  PosixFile *p = (PosixFile *)pFile;
  struct stat buf;

  /* If the file is between 0 and 2MB in size, extend it in chunks of 256K.
  ** Thereafter, in chunks of 1MB at a time.  */
  const int aIncrSz[] = {256*1024, 1024*1024};
  int nIncrSz = aIncrSz[iMin>(2*1024*1024)];

  if( p->pMap ){
    munmap(p->pMap, p->nMap);
    *ppOut = p->pMap = 0;
    *pnOut = p->nMap = 0;
  }

  if( iMin>=0 ){
    memset(&buf, 0, sizeof(buf));
    prc = fstat(p->fd, &buf);
    if( prc!=0 ) return LSM_IOERR_BKPT;
    iSz = buf.st_size;
    if( iSz<iMin ){
      iSz = ((iMin + nIncrSz-1) / nIncrSz) * nIncrSz;
      prc = ftruncate(p->fd, iSz);
      if( prc!=0 ) return LSM_IOERR_BKPT;
    }

    p->pMap = mmap(0, iSz, PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0);
    p->nMap = iSz;
  }

  *ppOut = p->pMap;
  *pnOut = p->nMap;
  return LSM_OK;
}

static int lsmPosixOsFullpath(
  lsm_env *pEnv,
  const char *zName,
  char *zOut,
  int *pnOut
){
  int nBuf = *pnOut;
  int nReq;

  if( zName[0]!='/' ){
    char *z;
    char *zTmp;
    int nTmp = 512;
    zTmp = lsmMalloc(pEnv, nTmp);
    while( zTmp ){
      z = getcwd(zTmp, nTmp);
      if( z || errno!=ERANGE ) break;
      nTmp = nTmp*2;
      zTmp = lsmReallocOrFree(pEnv, zTmp, nTmp);
    }
    if( zTmp==0 ) return LSM_NOMEM_BKPT;
    if( z==0 ) return LSM_IOERR_BKPT;
    assert( z==zTmp );

    nTmp = strlen(zTmp);
    nReq = nTmp + 1 + strlen(zName) + 1;
    if( nReq<=nBuf ){
      memcpy(zOut, zTmp, nTmp);
      zOut[nTmp] = '/';
      memcpy(&zOut[nTmp+1], zName, strlen(zName)+1);
    }
    lsmFree(pEnv, zTmp);
  }else{
    nReq = strlen(zName)+1;
    if( nReq<=nBuf ){
      memcpy(zOut, zName, strlen(zName)+1);
    }
  }

  *pnOut = nReq;
  return LSM_OK;
}

static int lsmPosixOsFileid(
  lsm_file *pFile, 
  void *pBuf,
  int *pnBuf
){
  int prc;
  int nBuf;
  int nReq;
  PosixFile *p = (PosixFile *)pFile;
  struct stat buf;

  nBuf = *pnBuf;
  nReq = (sizeof(buf.st_dev) + sizeof(buf.st_ino));
  *pnBuf = nReq;
  if( nReq>nBuf ) return LSM_OK;

  memset(&buf, 0, sizeof(buf));
  prc = fstat(p->fd, &buf);
  if( prc!=0 ) return LSM_IOERR_BKPT;

  memcpy(pBuf, &buf.st_dev, sizeof(buf.st_dev));
  memcpy(&(((u8 *)pBuf)[sizeof(buf.st_dev)]), &buf.st_ino, sizeof(buf.st_ino));
  return LSM_OK;
}

static int lsmPosixOsUnlink(lsm_env *pEnv, const char *zFile){
  int prc = unlink(zFile);
  return prc ? LSM_IOERR_BKPT : LSM_OK;
}

int lsmPosixOsLock(lsm_file *pFile, int iLock, int eType){
  int rc = LSM_OK;
  PosixFile *p = (PosixFile *)pFile;
  static const short aType[3] = { F_UNLCK, F_RDLCK, F_WRLCK };
  struct flock lock;

  assert( aType[LSM_LOCK_UNLOCK]==F_UNLCK );
  assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
  assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
  assert( eType>=0 && eType<array_size(aType) );
  assert( iLock>0 && iLock<=32 );

  memset(&lock, 0, sizeof(lock));
  lock.l_whence = SEEK_SET;
  lock.l_len = 1;
  lock.l_type = aType[eType];
  lock.l_start = (4096-iLock);

  if( fcntl(p->fd, F_SETLK, &lock) ){
    int e = errno;
    if( e==EACCES || e==EAGAIN ){
      rc = LSM_BUSY;
    }else{
      rc = LSM_IOERR_BKPT;
    }
  }

  return rc;
}

int lsmPosixOsTestLock(lsm_file *pFile, int iLock, int nLock, int eType){
  int rc = LSM_OK;
  PosixFile *p = (PosixFile *)pFile;
  static const short aType[3] = { 0, F_RDLCK, F_WRLCK };
  struct flock lock;

  assert( eType==LSM_LOCK_SHARED || eType==LSM_LOCK_EXCL );
  assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
  assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
  assert( eType>=0 && eType<array_size(aType) );
  assert( iLock>0 && iLock<=32 );

  memset(&lock, 0, sizeof(lock));
  lock.l_whence = SEEK_SET;
  lock.l_len = nLock;
  lock.l_type = aType[eType];
  lock.l_start = (4096-iLock);

  if( fcntl(p->fd, F_GETLK, &lock) ){
    rc = LSM_IOERR_BKPT;
  }else if( lock.l_type!=F_UNLCK ){
    rc = LSM_BUSY;
  }

  return rc;
}

int lsmPosixOsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
  PosixFile *p = (PosixFile *)pFile;

  *ppShm = 0;
  assert( sz==LSM_SHM_CHUNK_SIZE );
  if( iChunk>=p->nShm ){
    int i;
    void **apNew;
    int nNew = iChunk+1;
    off_t nReq = nNew * LSM_SHM_CHUNK_SIZE;
    struct stat sStat;

    /* If the shared-memory file has not been opened, open it now. */
    if( p->shmfd<=0 ){
      char *zShm = posixShmFile(p);
      if( !zShm ) return LSM_NOMEM_BKPT;
      p->shmfd = open(zShm, O_RDWR|O_CREAT, 0644);
      lsmFree(p->pEnv, zShm);
      if( p->shmfd<0 ){ 
        return LSM_IOERR_BKPT;
      }
    }

    /* If the shared-memory file is not large enough to contain the 
    ** requested chunk, cause it to grow.  */
    if( fstat(p->shmfd, &sStat) ){
      return LSM_IOERR_BKPT;
    }
    if( sStat.st_size<nReq ){
      if( ftruncate(p->shmfd, nReq) ){
        return LSM_IOERR_BKPT;
      }
    }

    apNew = (void **)lsmRealloc(p->pEnv, p->apShm, sizeof(void *) * nNew);
    if( !apNew ) return LSM_NOMEM_BKPT;
    for(i=p->nShm; i<nNew; i++){
      apNew[i] = 0;
    }
    p->apShm = apNew;
    p->nShm = nNew;
  }

  if( p->apShm[iChunk]==0 ){
    p->apShm[iChunk] = mmap(0, LSM_SHM_CHUNK_SIZE, 
        PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*LSM_SHM_CHUNK_SIZE
    );
    if( p->apShm[iChunk]==0 ) return LSM_IOERR_BKPT;
  }

  *ppShm = p->apShm[iChunk];
  return LSM_OK;
}

void lsmPosixOsShmBarrier(void){
}

int lsmPosixOsShmUnmap(lsm_file *pFile, int bDelete){
  PosixFile *p = (PosixFile *)pFile;
  if( p->shmfd>0 ){
    int i;
    for(i=0; i<p->nShm; i++){
      if( p->apShm[i] ){
        munmap(p->apShm[i], LSM_SHM_CHUNK_SIZE);
        p->apShm[i] = 0;
      }
    }
    close(p->shmfd);
    p->shmfd = 0;
    if( bDelete ){
      char *zShm = posixShmFile(p);
      if( zShm ) unlink(zShm);
      lsmFree(p->pEnv, zShm);
    }
  }
  return LSM_OK;
}


static int lsmPosixOsClose(lsm_file *pFile){
   PosixFile *p = (PosixFile *)pFile;
   lsmPosixOsShmUnmap(pFile, 0);
   if( p->pMap ) munmap(p->pMap, p->nMap);
   close(p->fd);
   lsm_free(p->pEnv, p->apShm);
   lsm_free(p->pEnv, p);
   return LSM_OK;
}

static int lsmPosixOsSleep(lsm_env *pEnv, int us){
#if 0
  /* Apparently on Android usleep() returns void */
  if( usleep(us) ) return LSM_IOERR;
#endif
  usleep(us);
  return LSM_OK;
}

/****************************************************************************
** Memory allocation routines.
*/
#define BLOCK_HDR_SIZE ROUND8( sizeof(sqlite4_size_t) )

static void *lsmPosixOsMalloc(lsm_env *pEnv, int N){
  unsigned char * m;
  N += BLOCK_HDR_SIZE;
  m = (unsigned char *)malloc(N);
  *((sqlite4_size_t*)m) = N;
  return m + BLOCK_HDR_SIZE;
}

static void lsmPosixOsFree(lsm_env *pEnv, void *p){
  if(p){
    free( ((unsigned char *)p) - BLOCK_HDR_SIZE );
  }
}

static void *lsmPosixOsRealloc(lsm_env *pEnv, void *p, int N){
  unsigned char * m = (unsigned char *)p;
  if(1>N){
    lsmPosixOsFree( pEnv, p );
    return NULL;
  }else if(NULL==p){
    return lsmPosixOsMalloc(pEnv, N);
  }else{
    void * re = NULL;
    m -= BLOCK_HDR_SIZE;
#if 0 /* arguable: don't shrink */
    sqlite4_size_t * sz = (sqlite4_size_t*)m;
    if(*sz >= (sqlite4_size_t)N){
      return p;
    }
#endif
    re = realloc( m, N + BLOCK_HDR_SIZE );
    if(re){
      m = (unsigned char *)re;
      *((sqlite4_size_t*)m) = N;
      return m + BLOCK_HDR_SIZE;
    }else{
      return NULL;
    }
  }
}

static sqlite4_size_t lsmPosixOsMSize(lsm_env *pEnv, void *p){
  unsigned char * m = (unsigned char *)p;
  return *((sqlite4_size_t*)(m-BLOCK_HDR_SIZE));
}
#undef BLOCK_HDR_SIZE


#ifdef LSM_MUTEX_PTHREADS 
/*************************************************************************
** Mutex methods for pthreads based systems.  If LSM_MUTEX_PTHREADS is
** missing then a no-op implementation of mutexes found in lsm_mutex.c
** will be used instead.
*/
/* #include <pthread.h> */

typedef struct PthreadMutex PthreadMutex;
struct PthreadMutex {
  lsm_env *pEnv;
  pthread_mutex_t mutex;
#ifdef LSM_DEBUG
  pthread_t owner;
#endif
};

#ifdef LSM_DEBUG
# define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER, 0 }
#else
# define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER }
#endif

static int lsmPosixOsMutexStatic(
  lsm_env *pEnv,
  int iMutex,
  lsm_mutex **ppStatic
){
  static PthreadMutex sMutex[2] = {
    LSM_PTHREAD_STATIC_MUTEX,
    LSM_PTHREAD_STATIC_MUTEX
  };

  assert( iMutex==LSM_MUTEX_GLOBAL || iMutex==LSM_MUTEX_HEAP );
  assert( LSM_MUTEX_GLOBAL==1 && LSM_MUTEX_HEAP==2 );

  *ppStatic = (lsm_mutex *)&sMutex[iMutex-1];
  return LSM_OK;
}

static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
  PthreadMutex *pMutex;           /* Pointer to new mutex */
  pthread_mutexattr_t attr;       /* Attributes object */

  pMutex = (PthreadMutex *)lsmMallocZero(pEnv, sizeof(PthreadMutex));
  if( !pMutex ) return LSM_NOMEM_BKPT;

  pMutex->pEnv = pEnv;
  pthread_mutexattr_init(&attr);
  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
  pthread_mutex_init(&pMutex->mutex, &attr);
  pthread_mutexattr_destroy(&attr);

  *ppNew = (lsm_mutex *)pMutex;
  return LSM_OK;
}

static void lsmPosixOsMutexDel(lsm_mutex *p){
  PthreadMutex *pMutex = (PthreadMutex *)p;
  pthread_mutex_destroy(&pMutex->mutex);
  lsmFree(pMutex->pEnv, pMutex);
}

static void lsmPosixOsMutexEnter(lsm_mutex *p){
  PthreadMutex *pMutex = (PthreadMutex *)p;
  pthread_mutex_lock(&pMutex->mutex);

#ifdef LSM_DEBUG
  assert( !pthread_equal(pMutex->owner, pthread_self()) );
  pMutex->owner = pthread_self();
  assert( pthread_equal(pMutex->owner, pthread_self()) );
#endif
}

static int lsmPosixOsMutexTry(lsm_mutex *p){
  int ret;
  PthreadMutex *pMutex = (PthreadMutex *)p;
  ret = pthread_mutex_trylock(&pMutex->mutex);
#ifdef LSM_DEBUG
  if( ret==0 ){
    assert( !pthread_equal(pMutex->owner, pthread_self()) );
    pMutex->owner = pthread_self();
    assert( pthread_equal(pMutex->owner, pthread_self()) );
  }
#endif
  return ret;
}

static void lsmPosixOsMutexLeave(lsm_mutex *p){
  PthreadMutex *pMutex = (PthreadMutex *)p;
#ifdef LSM_DEBUG
  assert( pthread_equal(pMutex->owner, pthread_self()) );
  pMutex->owner = 0;
  assert( !pthread_equal(pMutex->owner, pthread_self()) );
#endif
  pthread_mutex_unlock(&pMutex->mutex);
}

#ifdef LSM_DEBUG
static int lsmPosixOsMutexHeld(lsm_mutex *p){
  PthreadMutex *pMutex = (PthreadMutex *)p;
  return pMutex ? pthread_equal(pMutex->owner, pthread_self()) : 1;
}
static int lsmPosixOsMutexNotHeld(lsm_mutex *p){
  PthreadMutex *pMutex = (PthreadMutex *)p;
  return pMutex ? !pthread_equal(pMutex->owner, pthread_self()) : 1;
}
#endif
/*
** End of pthreads mutex implementation.
*************************************************************************/
#else
/*************************************************************************
** Noop mutex implementation
*/
typedef struct NoopMutex NoopMutex;
struct NoopMutex {
  lsm_env *pEnv;                  /* Environment handle (for xFree()) */
  int bHeld;                      /* True if mutex is held */
  int bStatic;                    /* True for a static mutex */
};
static NoopMutex aStaticNoopMutex[2] = {
  {0, 0, 1},
  {0, 0, 1},
};

static int lsmPosixOsMutexStatic(
  lsm_env *pEnv,
  int iMutex,
  lsm_mutex **ppStatic
){
  assert( iMutex>=1 && iMutex<=(int)array_size(aStaticNoopMutex) );
  *ppStatic = (lsm_mutex *)&aStaticNoopMutex[iMutex-1];
  return LSM_OK;
}
static int lsmPosixOsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
  NoopMutex *p;
  p = (NoopMutex *)lsmMallocZero(pEnv, sizeof(NoopMutex));
  if( p ) p->pEnv = pEnv;
  *ppNew = (lsm_mutex *)p;
  return (p ? LSM_OK : LSM_NOMEM_BKPT);
}
static void lsmPosixOsMutexDel(lsm_mutex *pMutex)  { 
  NoopMutex *p = (NoopMutex *)pMutex;
  assert( p->bStatic==0 && p->pEnv );
  lsmFree(p->pEnv, p);
}
static void lsmPosixOsMutexEnter(lsm_mutex *pMutex){ 
  NoopMutex *p = (NoopMutex *)pMutex;
  assert( p->bHeld==0 );
  p->bHeld = 1;
}
static int lsmPosixOsMutexTry(lsm_mutex *pMutex){
  NoopMutex *p = (NoopMutex *)pMutex;
  assert( p->bHeld==0 );
  p->bHeld = 1;
  return 0;
}
static void lsmPosixOsMutexLeave(lsm_mutex *pMutex){ 
  NoopMutex *p = (NoopMutex *)pMutex;
  assert( p->bHeld==1 );
  p->bHeld = 0;
}
#ifdef LSM_DEBUG
static int lsmPosixOsMutexHeld(lsm_mutex *pMutex){ 
  NoopMutex *p = (NoopMutex *)pMutex;
  return p ? p->bHeld : 1;
}
static int lsmPosixOsMutexNotHeld(lsm_mutex *pMutex){ 
  NoopMutex *p = (NoopMutex *)pMutex;
  return p ? !p->bHeld : 1;
}
#endif
/***************************************************************************/
#endif /* else LSM_MUTEX_NONE */

/* Without LSM_DEBUG, the MutexHeld tests are never called */
#ifndef LSM_DEBUG
# define lsmPosixOsMutexHeld    0
# define lsmPosixOsMutexNotHeld 0
#endif

lsm_env *lsm_default_env(void){
  static lsm_env posix_env = {
    sizeof(lsm_env),         /* nByte */
    1,                       /* iVersion */
    /***** file i/o ******************/
    0,                       /* pVfsCtx */
    lsmPosixOsFullpath,      /* xFullpath */
    lsmPosixOsOpen,          /* xOpen */
    lsmPosixOsRead,          /* xRead */
    lsmPosixOsWrite,         /* xWrite */
    lsmPosixOsTruncate,      /* xTruncate */
    lsmPosixOsSync,          /* xSync */
    lsmPosixOsSectorSize,    /* xSectorSize */
    lsmPosixOsRemap,         /* xRemap */
    lsmPosixOsFileid,        /* xFileid */
    lsmPosixOsClose,         /* xClose */
    lsmPosixOsUnlink,        /* xUnlink */
    lsmPosixOsLock,          /* xLock */
    lsmPosixOsTestLock,      /* xTestLock */
    lsmPosixOsShmMap,        /* xShmMap */
    lsmPosixOsShmBarrier,    /* xShmBarrier */
    lsmPosixOsShmUnmap,      /* xShmUnmap */
    /***** memory allocation *********/
    0,                       /* pMemCtx */
    lsmPosixOsMalloc,        /* xMalloc */
    lsmPosixOsRealloc,       /* xRealloc */
    lsmPosixOsFree,          /* xFree */
    lsmPosixOsMSize,         /* xSize */
    /***** mutexes *********************/
    0,                       /* pMutexCtx */
    lsmPosixOsMutexStatic,   /* xMutexStatic */
    lsmPosixOsMutexNew,      /* xMutexNew */
    lsmPosixOsMutexDel,      /* xMutexDel */
    lsmPosixOsMutexEnter,    /* xMutexEnter */
    lsmPosixOsMutexTry,      /* xMutexTry */
    lsmPosixOsMutexLeave,    /* xMutexLeave */
    lsmPosixOsMutexHeld,     /* xMutexHeld */
    lsmPosixOsMutexNotHeld,  /* xMutexNotHeld */
    /***** other *********************/
    lsmPosixOsSleep,         /* xSleep */
  };
  return &posix_env;
}

/************** End of lsm_unix.c ********************************************/
/************** Begin file lsm_varint.c **************************************/

/*
** 2012-02-08
**
** 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.
**
*************************************************************************
**
** SQLite4-compatible varint implementation.
*/

/*************************************************************************
** The following is a copy of the varint.c module from SQLite 4.
*/

/*
** Decode the varint in z[].  Write the integer value into *pResult and
** return the number of bytes in the varint.
*/
static int lsmSqlite4GetVarint64(const unsigned char *z, u64 *pResult){
  unsigned int x;
  if( z[0]<=240 ){
    *pResult = z[0];
    return 1;
  }
  if( z[0]<=248 ){
    *pResult = (z[0]-241)*256 + z[1] + 240;
    return 2;
  }
  if( z[0]==249 ){
    *pResult = 2288 + 256*z[1] + z[2];
    return 3;
  }
  if( z[0]==250 ){
    *pResult = (z[1]<<16) + (z[2]<<8) + z[3];
    return 4;
  }
  x = (z[1]<<24) + (z[2]<<16) + (z[3]<<8) + z[4];
  if( z[0]==251 ){
    *pResult = x;
    return 5;
  }
  if( z[0]==252 ){
    *pResult = (((u64)x)<<8) + z[5];
    return 6;
  }
  if( z[0]==253 ){
    *pResult = (((u64)x)<<16) + (z[5]<<8) + z[6];
    return 7;
  }
  if( z[0]==254 ){
    *pResult = (((u64)x)<<24) + (z[5]<<16) + (z[6]<<8) + z[7];
    return 8;
  }
  *pResult = (((u64)x)<<32) +
               (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
  return 9;
}

/*
** Write a 32-bit unsigned integer as 4 big-endian bytes.
*/
static void lsmVarintWrite32(unsigned char *z, unsigned int y){
  z[0] = (unsigned char)(y>>24);
  z[1] = (unsigned char)(y>>16);
  z[2] = (unsigned char)(y>>8);
  z[3] = (unsigned char)(y);
}

/*
** Write a varint into z[].  The buffer z[] must be at least 9 characters
** long to accommodate the largest possible varint.  Return the number of
** bytes of z[] used.
*/
static int lsmSqlite4PutVarint64(unsigned char *z, u64 x){
  unsigned int w, y;
  if( x<=240 ){
    z[0] = (unsigned char)x;
    return 1;
  }
  if( x<=2287 ){
    y = (unsigned int)(x - 240);
    z[0] = (unsigned char)(y/256 + 241);
    z[1] = (unsigned char)(y%256);
    return 2;
  }
  if( x<=67823 ){
    y = (unsigned int)(x - 2288);
    z[0] = 249;
    z[1] = (unsigned char)(y/256);
    z[2] = (unsigned char)(y%256);
    return 3;
  }
  y = (unsigned int)x;
  w = (unsigned int)(x>>32);
  if( w==0 ){
    if( y<=16777215 ){
      z[0] = 250;
      z[1] = (unsigned char)(y>>16);
      z[2] = (unsigned char)(y>>8);
      z[3] = (unsigned char)(y);
      return 4;
    }
    z[0] = 251;
    lsmVarintWrite32(z+1, y);
    return 5;
  }
  if( w<=255 ){
    z[0] = 252;
    z[1] = (unsigned char)w;
    lsmVarintWrite32(z+2, y);
    return 6;
  }
  if( w<=32767 ){
    z[0] = 253;
    z[1] = (unsigned char)(w>>8);
    z[2] = (unsigned char)w;
    lsmVarintWrite32(z+3, y);
    return 7;
  }
  if( w<=16777215 ){
    z[0] = 254;
    z[1] = (unsigned char)(w>>16);
    z[2] = (unsigned char)(w>>8);
    z[3] = (unsigned char)w;
    lsmVarintWrite32(z+4, y);
    return 8;
  }
  z[0] = 255;
  lsmVarintWrite32(z+1, w);
  lsmVarintWrite32(z+5, y);
  return 9;
}

/*
** End of SQLite 4 code.
*************************************************************************/

int lsmVarintPut64(u8 *aData, i64 iVal){
  return lsmSqlite4PutVarint64(aData, (u64)iVal);
}

int lsmVarintGet64(const u8 *aData, i64 *piVal){
  return lsmSqlite4GetVarint64(aData, (u64 *)piVal);
}

int lsmVarintPut32(u8 *aData, int iVal){
  return lsmSqlite4PutVarint64(aData, (u64)iVal);
}

int lsmVarintGet32(u8 *z, int *piVal){
  u64 i;
  int ret;

  if( z[0]<=240 ){
    *piVal = z[0];
    return 1;
  }
  if( z[0]<=248 ){
    *piVal = (z[0]-241)*256 + z[1] + 240;
    return 2;
  }
  if( z[0]==249 ){
    *piVal = 2288 + 256*z[1] + z[2];
    return 3;
  }
  if( z[0]==250 ){
    *piVal = (z[1]<<16) + (z[2]<<8) + z[3];
    return 4;
  }

  ret = lsmSqlite4GetVarint64(z, &i);
  *piVal = i;
  return ret;
}

int lsmVarintLen32(int n){
  u8 aData[9];
  return lsmVarintPut32(aData, n);
}

/*
** The argument is the first byte of a varint. This function returns the
** total number of bytes in the entire varint (including the first byte).
*/
int lsmVarintSize(u8 c){
  if( c<241 ) return 1;
  if( c<249 ) return 2;
  return (int)(c - 246);
}

/************** End of lsm_varint.c ******************************************/
/************** Begin file kv.c **********************************************/
/*
** 2012 January 21
**
** 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.
**
*************************************************************************
**
** General wrapper functions around the various KV storage engine
** implementations.  It also implements tracing of calls to the KV
** engine and some higher-level ensembles of the low-level storage
** calls.
*/

/*
** Names of error codes used for tracing.
*/
static const char *kvErrName(int e){
  const char *zName;
  switch( e ){
    case SQLITE4_OK:                  zName = "OK";                break;
    case SQLITE4_ERROR:               zName = "ERROR";             break;
    case SQLITE4_INTERNAL:            zName = "INTERNAL";          break;
    case SQLITE4_PERM:                zName = "PERM";              break;
    case SQLITE4_ABORT:               zName = "ABORT";             break;
    case SQLITE4_BUSY:                zName = "BUSY";              break;
    case SQLITE4_LOCKED:              zName = "LOCKED";            break;
    case SQLITE4_NOMEM:               zName = "NOMEM";             break;
    case SQLITE4_READONLY:            zName = "READONLY";          break;
    case SQLITE4_INTERRUPT:           zName = "INTERRUPT";         break;
    case SQLITE4_IOERR:               zName = "IOERR";             break;
    case SQLITE4_CORRUPT:             zName = "CORRUPT";           break;
    case SQLITE4_NOTFOUND:            zName = "NOTFOUND";          break;
    case SQLITE4_FULL:                zName = "FULL";              break;
    case SQLITE4_CANTOPEN:            zName = "CANTOPEN";          break;
    case SQLITE4_PROTOCOL:            zName = "PROTOCOL";          break;
    case SQLITE4_EMPTY:               zName = "EMPTY";             break;
    case SQLITE4_SCHEMA:              zName = "SCHEMA";            break;
    case SQLITE4_TOOBIG:              zName = "TOOBIG";            break;
    case SQLITE4_CONSTRAINT:          zName = "CONSTRAINT";        break;
    case SQLITE4_MISMATCH:            zName = "MISMATCH";          break;
    case SQLITE4_MISUSE:              zName = "MISUSE";            break;
    case SQLITE4_NOLFS:               zName = "NOLFS";             break;
    case SQLITE4_AUTH:                zName = "AUTH";              break;
    case SQLITE4_FORMAT:              zName = "FORMAT";            break;
    case SQLITE4_RANGE:               zName = "RANGE";             break;
    case SQLITE4_NOTADB:              zName = "NOTADB";            break;
    case SQLITE4_ROW:                 zName = "ROW";               break;
    case SQLITE4_DONE:                zName = "DONE";              break;
    case SQLITE4_INEXACT:             zName = "INEXACT";           break;
    default:                         zName = "???";               break;
  }
  return zName;
}

/*
** Do any requested tracing
*/
static void kvTrace(KVStore *p, const char *zFormat, ...){
  if( p->fTrace ){
    va_list ap;
    char *z;

    va_start(ap, zFormat);
    z = sqlite4_vmprintf(p->pEnv, zFormat, ap);
    va_end(ap);
    printf("%s.%s\n", p->zKVName, z);
    fflush(stdout);
    sqlite4_free(p->pEnv, z);
  }
}

/*
** Open a storage engine via URI
*/
SQLITE4_PRIVATE int sqlite4KVStoreOpen(
  sqlite4 *db,             /* The database connection doing the open */
  const char *zName,       /* Symbolic name for this database */
  const char *zUri,        /* URI for this database */
  KVStore **ppKVStore,     /* Write the new KVStore object here */
  unsigned flags           /* Option flags */
){
  KVStore *pNew = 0;
  int rc;
  sqlite4_env *pEnv = &sqlite4DefaultEnv;  /* OR db->pEnv */
  const char *zStorageName;
  KVFactory *pMkr;
  sqlite4_kvfactory xFactory;

  if( (flags & SQLITE4_KVOPEN_TEMPORARY)!=0 || zUri==0 || zUri[0]==0 ){
    zStorageName = "temp";
  }else{
    zStorageName = sqlite4_uri_parameter(zUri, "kv");
    if( zStorageName==0 ){
      if( memcmp(":memory:", zUri, 8)==0 ){
        zStorageName = "temp";
      }else{
        zStorageName = "main";
      }
    }
  }
  *ppKVStore = 0;
  sqlite4_mutex_enter(pEnv->pFactoryMutex);
  for(pMkr=pEnv->pFactory; pMkr && strcmp(zStorageName,pMkr->zName);
      pMkr=pMkr->pNext){}
  xFactory = pMkr ? pMkr->xFactory : 0;
  sqlite4_mutex_leave(pEnv->pFactoryMutex);
  if( xFactory==0 ){
    return SQLITE4_ERROR;
  }
  rc = xFactory(pEnv, &pNew, zUri, flags);
  *ppKVStore = pNew;
  if( pNew ){
    sqlite4_randomness(pEnv, sizeof(pNew->kvId), &pNew->kvId);
    sqlite4_snprintf(pNew->zKVName, sizeof(pNew->zKVName),
                     "%s", zName);
    pNew->fTrace = (db->flags & SQLITE4_KvTrace)!=0;
    kvTrace(pNew, "open(%s,%d,0x%04x)", zUri, pNew->kvId, flags);
  }
  return rc;
}

/* Convert binary data to hex for display in trace messages */
static void binToHex(char *zOut, int mxOut, const KVByteArray *a, KVSize n){
  int i;
  if( n>mxOut/2-1 ) n = mxOut/2-1;
  for(i=0; i<n; i++){
    zOut[i*2] = "0123456789abcdef"[(a[i]>>4)&0xf];
    zOut[i*2+1] = "0123456789abcdef"[a[i]&0xf];
  }
  zOut[i*2] = 0;
}

/*
** The following wrapper functions invoke the underlying methods of
** the storage object and add optional tracing.
*/
SQLITE4_PRIVATE int sqlite4KVStoreReplace(
  KVStore *p,
  const KVByteArray *pKey, KVSize nKey,
  const KVByteArray *pData, KVSize nData
){
  if( p->fTrace ){
    char zKey[52], zData[52];
    binToHex(zKey, sizeof(zKey), pKey, nKey);
    binToHex(zData, sizeof(zData), pData, nData);
    kvTrace(p, "xReplace(%d,%s,%d,%s,%d)",
           p->kvId, zKey, (int)nKey, zData, (int)nData);
  }
  return p->pStoreVfunc->xReplace(p,pKey,nKey,pData,nData);
}
SQLITE4_PRIVATE int sqlite4KVStoreOpenCursor(KVStore *p, KVCursor **ppKVCursor){
  KVCursor *pCur;
  int rc;

  rc = p->pStoreVfunc->xOpenCursor(p, &pCur);
  *ppKVCursor = pCur;
  if( pCur ){
    sqlite4_randomness(pCur->pEnv, sizeof(pCur->curId), &pCur->curId);
    pCur->fTrace = p->fTrace;
    pCur->pStore = p;
  }
  kvTrace(p, "xOpenCursor(%d,%d) -> %s",
          p->kvId, pCur?pCur->curId:-1, kvErrName(rc));
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVCursorSeek(
  KVCursor *p,
  const KVByteArray *pKey, KVSize nKey,
  int dir
){
  int rc;
  assert( dir==0 || dir==(+1) || dir==(-1) || dir==(-2) );  
  rc = p->pStoreVfunc->xSeek(p,pKey,nKey,dir);
  if( p->fTrace ){
    char zKey[52];
    binToHex(zKey, sizeof(zKey), pKey, nKey);
    kvTrace(p->pStore, "xSeek(%d,%s,%d,%d) -> %s",
            p->curId, zKey, (int)nKey, dir, kvErrName(rc));
  }
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVCursorNext(KVCursor *p){
  int rc;
  rc = p->pStoreVfunc->xNext(p);
  kvTrace(p->pStore, "xNext(%d) -> %s", p->curId, kvErrName(rc));
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVCursorPrev(KVCursor *p){
  int rc;
  rc = p->pStoreVfunc->xPrev(p);
  kvTrace(p->pStore, "xPrev(%d) -> %s", p->curId, kvErrName(rc));
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVCursorDelete(KVCursor *p){
  int rc;
  rc = p->pStoreVfunc->xDelete(p);
  kvTrace(p->pStore, "xDelete(%d) -> %s", p->curId, kvErrName(rc));
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVCursorReset(KVCursor *p){
  int rc;
  rc = p->pStoreVfunc->xReset(p);
  kvTrace(p->pStore, "xReset(%d) -> %s", p->curId, kvErrName(rc));
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVCursorKey(KVCursor *p, const KVByteArray **ppKey, KVSize *pnKey){
  int rc;
  rc = p->pStoreVfunc->xKey(p, ppKey, pnKey);
  if( p->fTrace ){
    if( rc==SQLITE4_OK ){
      char zKey[52];
      binToHex(zKey, sizeof(zKey), *ppKey, *pnKey);
      kvTrace(p->pStore, "xKey(%d,%s,%d)", p->curId, zKey, (int)*pnKey);
    }else{
      kvTrace(p->pStore, "xKey(%d,<error-%d>)", p->curId, rc);
    }
  }
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVCursorData(
  KVCursor *p,
  KVSize ofst,
  KVSize n,
  const KVByteArray **ppData,
  KVSize *pnData
){
  int rc;
  rc = p->pStoreVfunc->xData(p, ofst, n, ppData, pnData);
  if( p->fTrace ){
    if( rc==SQLITE4_OK ){
      char zData[52];
      binToHex(zData, sizeof(zData), *ppData, *pnData);
      kvTrace(p->pStore, "xData(%d,%d,%d,%s,%d)",
             p->curId, (int)ofst, (int)n, zData, (int)*pnData);
    }else{
      kvTrace(p->pStore, "xData(%d,%d,%d,<error-%d>)",
             p->curId, (int)ofst, (int)n, rc);
    }
  }
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVCursorClose(KVCursor *p){
  int rc = SQLITE4_OK;
  if( p ){
    KVStore *pStore = p->pStore;
    int curId = p->curId;
    rc = p->pStoreVfunc->xCloseCursor(p);
    kvTrace(pStore, "xCloseCursor(%d) -> %s", curId, kvErrName(rc));
  }
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVStoreBegin(KVStore *p, int iLevel){
  int rc;
  rc = p->pStoreVfunc->xBegin(p, iLevel);
  kvTrace(p, "xBegin(%d,%d) -> %s", p->kvId, iLevel, kvErrName(rc));
  assert( p->iTransLevel==iLevel || rc!=SQLITE4_OK );
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVStoreCommitPhaseOne(KVStore *p, int iLevel){
  int rc;
  assert( iLevel>=0 );
  assert( iLevel<=p->iTransLevel );
  if( p->iTransLevel==iLevel ) return SQLITE4_OK;
  if( p->pStoreVfunc->xCommitPhaseOne ){
    rc = p->pStoreVfunc->xCommitPhaseOne(p, iLevel);
  }else{
    rc = SQLITE4_OK;
  }
  kvTrace(p, "xCommitPhaseOne(%d,%d) -> %s", p->kvId, iLevel, kvErrName(rc));
  assert( p->iTransLevel>iLevel );
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVStoreCommitPhaseTwo(KVStore *p, int iLevel){
  int rc;
  assert( iLevel>=0 );
  assert( iLevel<=p->iTransLevel );
  if( p->iTransLevel==iLevel ) return SQLITE4_OK;
  rc = p->pStoreVfunc->xCommitPhaseTwo(p, iLevel);
  kvTrace(p, "xCommitPhaseTwo(%d,%d) -> %s", p->kvId, iLevel, kvErrName(rc));
  assert( p->iTransLevel==iLevel || rc!=SQLITE4_OK );
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVStoreCommit(KVStore *p, int iLevel){
  int rc;
  rc = sqlite4KVStoreCommitPhaseOne(p, iLevel);
  if( rc==SQLITE4_OK ) rc = sqlite4KVStoreCommitPhaseTwo(p, iLevel);
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVStoreRollback(KVStore *p, int iLevel){
  int rc;
  assert( iLevel>=0 );
  assert( iLevel<=p->iTransLevel );
  rc = p->pStoreVfunc->xRollback(p, iLevel);
  kvTrace(p, "xRollback(%d,%d) -> %s", p->kvId, iLevel, kvErrName(rc));
  assert( p->iTransLevel==iLevel || rc!=SQLITE4_OK );
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVStoreRevert(KVStore *p, int iLevel){
  int rc;
  assert( iLevel>0 );
  assert( iLevel<=p->iTransLevel );
  if( p->pStoreVfunc->xRevert ){
    rc = p->pStoreVfunc->xRevert(p, iLevel);
    kvTrace(p, "xRevert(%d,%d) -> %s", p->kvId, iLevel, kvErrName(rc));
  }else{
    rc = sqlite4KVStoreRollback(p, iLevel-1);
    if( rc==SQLITE4_OK ){
      rc = sqlite4KVStoreBegin(p, iLevel);
    }
  }
  assert( p->iTransLevel==iLevel || rc!=SQLITE4_OK );
  return rc;
}
SQLITE4_PRIVATE int sqlite4KVStoreClose(KVStore *p){
  int rc;
  if( p ){
    kvTrace(p, "xClose(%d)", p->kvId);
    rc = p->pStoreVfunc->xClose(p);
  }
  return rc;
}

/*
** Key for the meta-data
*/
static const KVByteArray metadataKey[] = { 0x00, 0x00 };

static void writeMetaArray(KVByteArray *aMeta, int iElem, u32 iVal){
  int i = sizeof(u32) * iElem;
  aMeta[i+0] = (iVal>>24)&0xff;
  aMeta[i+1] = (iVal>>16)&0xff;
  aMeta[i+2] = (iVal>>8) &0xff;
  aMeta[i+3] = (iVal>>0) &0xff;
}

/*
** Read nMeta unsigned 32-bit integers of metadata beginning at iStart.
*/
SQLITE4_PRIVATE int sqlite4KVStoreGetMeta(KVStore *p, int iStart, int nMeta, unsigned int *a){
  KVCursor *pCur;
  int rc;
  int i, j;
  KVSize nData;
  const KVByteArray *aData;

  rc = sqlite4KVStoreOpenCursor(p, &pCur);
  if( rc==SQLITE4_OK ){
    rc = sqlite4KVCursorSeek(pCur, metadataKey, sizeof(metadataKey), 0);
    if( rc==SQLITE4_NOTFOUND ){
      rc = SQLITE4_OK;
      nData = 0;
    }else if( rc==SQLITE4_OK ){
      rc = sqlite4KVCursorData(pCur, 0, -1, &aData, &nData);
    }
    if( rc==SQLITE4_OK ){
      i = 0;
      j = iStart*4;
      while( i<nMeta && j+3<nData ){
        a[i] = (aData[j]<<24) | (aData[j+1]<<16)
                     | (aData[j+2]<<8) | aData[j+3];
        i++;
        j += 4;
      }
      while( i<nMeta ) a[i++] = 0;
    }
    sqlite4KVCursorClose(pCur);
  }
  return rc;
}

/*
** Store schema cookie value iVal.
*/
SQLITE4_PRIVATE int sqlite4KVStorePutSchema(KVStore *p, unsigned int iVal){
  kvTrace(p, "xPutMeta(%d,%d)", p->kvId, (int)iVal);
  return p->pStoreVfunc->xPutMeta(p, iVal);
}

/*
** Read the schema cookie value into *piVal.
*/
SQLITE4_PRIVATE int sqlite4KVStoreGetSchema(KVStore *p, unsigned int *piVal){
  int rc = p->pStoreVfunc->xGetMeta(p, piVal);
  kvTrace(p, "xGetMeta(%d) -> %d", p->kvId, (int)*piVal);
  return rc;
}

/*
** Write nMeta unsigned 32-bit integers beginning with iStart.
*/
SQLITE4_PRIVATE int sqlite4KVStorePutMeta(
  sqlite4 *db,            /* Database connection.  Needed to malloc */
  KVStore *p,             /* Write to this database */
  int iStart,             /* Start writing here */
  int nMeta,              /* number of 32-bit integers to be written */
  unsigned int *a         /* The integers to write */
){
  KVCursor *pCur;
  int rc;


  rc = sqlite4KVStoreOpenCursor(p, &pCur);
  if( rc==SQLITE4_OK ){
    const KVByteArray *aData;     /* Original database meta-array value */
    KVSize nData;                 /* Size of aData[] in bytes */
    KVByteArray *aNew;            /* New database meta-array value */
    KVSize nNew;                  /* Size of aNew[] in bytes */

    /* Read the current meta-array value from the database */
    rc = sqlite4KVCursorSeek(pCur, metadataKey, sizeof(metadataKey), 0);
    if( rc==SQLITE4_OK ){
      rc = sqlite4KVCursorData(pCur, 0, -1, &aData, &nData);
    }else if( rc==SQLITE4_NOTFOUND ){
      nData = 0;
      aData = 0;
      rc = SQLITE4_OK;
    }

    /* Encode and write the new meta-array value to the database */
    if( rc==SQLITE4_OK ){
      nNew = sizeof(a[0]) * (iStart+nMeta);
      if( nNew<nData ) nNew = nData;
      aNew = sqlite4DbMallocRaw(db, nNew);
      if( aNew==0 ){
        rc = SQLITE4_NOMEM;
      }else{
        int i;
        memcpy(aNew, aData, nData);
        for(i=iStart; i<iStart+nMeta; i++){
          writeMetaArray(aNew, i, a[i]);
        }
        rc = sqlite4KVStoreReplace(p, metadataKey, sizeof(metadataKey),
                                   aNew, nNew);
        sqlite4DbFree(db, aNew);
      }
    }

    sqlite4KVCursorClose(pCur);
  }
  return rc;
}

#if defined(SQLITE4_DEBUG)
/*
** Output binary data for debugging display purposes.
*/
static void outputBinary(
  KVByteArray const *a,
  KVSize n,
  const char *zPrefix
){
  int i;
  char zOut[80];
  static const char base16[] = "0123456789abcdef";
  memset(zOut, ' ', sizeof(zOut));
  zOut[16*3+3+16] = 0;
  while( n>=0 ){
    for(i=0; i<16 && i<n; i++){
      unsigned char v = a[i];
      zOut[i*3] = base16[v>>4];
      zOut[i*3+1] = base16[v&0xf];
      zOut[16*3+3+i] = (v>=0x20 && v<=0x7e) ? v : '.';
    }
    while( i<16 ){
      zOut[i*3] = ' ';
      zOut[i*3+1] = ' ';
      zOut[16*3+3+i] = ' ';
      i++;
    }
    sqlite4DebugPrintf("%.3s %s\n", zPrefix, zOut);
    n -= 16;
    if( n<=0 ) break;
    a += 16;
    zPrefix = "   ";
  }
}

/*
** Dump the entire content of a key-value database
*/
SQLITE4_PRIVATE void sqlite4KVStoreDump(KVStore *pStore){
  int rc;
  int nRow = 0;
  KVCursor *pCur;
  KVSize nKey, nData;
  KVByteArray const *aKey;
  KVByteArray const *aData;
  static const KVByteArray aProbe[] = { 0x00 };

  rc = sqlite4KVStoreOpenCursor(pStore, &pCur);
  if( rc==SQLITE4_OK ){
    rc = sqlite4KVCursorSeek(pCur, aProbe, 1, +1);
    while( rc!=SQLITE4_NOTFOUND ){
      rc = sqlite4KVCursorKey(pCur, &aKey, &nKey);
      if( rc ) break;
      if( nRow>0 ) sqlite4DebugPrintf("\n");
      nRow++;
      outputBinary(aKey, nKey, "K: ");
      rc = sqlite4KVCursorData(pCur, 0, -1, &aData, &nData);
      if( rc ) break;
      outputBinary(aData, nData, "V: ");
      rc = sqlite4KVCursorNext(pCur);
    }
    sqlite4KVCursorClose(pCur);
  }
}
#endif /* SQLITE4_DEBUG */

/************** End of kv.c **************************************************/
/************** Begin file kvmem.c *******************************************/
/*
** 2012 January 20
**
** 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.
**
*************************************************************************
**
** An in-memory key/value storage subsystem that presents the interfadce
** defined by kv.h
*/

/* Forward declarations of object names */
typedef struct KVMemNode KVMemNode;
typedef struct KVMemChng KVMemChng;
typedef struct KVMem KVMem;
typedef struct KVMemCursor KVMemCursor;
typedef struct KVMemData KVMemData;

/*
** The data payload for an entry in the tree.
*/
struct KVMemData {
  int nRef;              /* Number of references to this payload */
  KVSize n;              /* Size of a[] in bytes */
  KVByteArray a[8];      /* The content */
};

/*
** A single row in a key/value memory store is an instance of the following
** object:
*/
struct KVMemNode {
  KVMemData *pData;     /* Content of the row.  NULL means it is deleted. */
  KVMemNode *pBefore;   /* Other elements less than zKey */
  KVMemNode *pAfter;    /* Other elements greater than zKey */
  KVMemNode *pUp;       /* Parent element */
  short int height;     /* Height of this node.  Leaf==1 */
  short int imbalance;  /* Height difference between pBefore and pAfter */
  short int mxTrans;    /* Maximum transaction for which this row is logged */
  short int nRef;       /* Number of references to this node */
  KVSize nKey;          /* Size of aKey[] */
  KVByteArray aKey[2];  /* Key.  Extra space allocated as necessary */
};

/*
** Changes to the tree that might be rolled back are recorded as instances
** of the following object.
*/
struct KVMemChng {
  KVMemChng *pNext;     /* Next entry in the change log */
  KVMemNode *pNode;     /* The node that is changing */
  KVMemData *pData;     /* Old data for the row.  NULL for new content. */
  short int oldTrans;   /* Value of pNode->mxTrans prior to this entry */
};

/*
** A complete in-memory Key/Value tree together with its
** transaction logs is an instance of the following object.
*/
struct KVMem {
  KVStore base;         /* Base class, must be first */
  KVMemNode *pRoot;     /* Root of the tree of content */
  unsigned openFlags;   /* Flags used at open */
  KVMemChng **apLog;    /* Array of transaction logs */
  int nCursor;          /* Number of outstanding cursors */
  int iMagicKVMemBase;  /* Magic number of sanity */
  unsigned int iMeta;   /* Schema cookie value */
};
#define SQLITE4_KVMEMBASE_MAGIC  0xbfcd47d0

/*
** A cursor used for scanning through the tree
*/
struct KVMemCursor {
  KVCursor base;        /* Base class. Must be first */
  KVMem *pOwner;        /* The tree that owns this cursor */
  KVMemNode *pNode;     /* The entry this cursor points to */
  KVMemData *pData;     /* Data returned by xData */
  int iMagicKVMemCur;   /* Magic number for sanity */
};
#define SQLITE4_KVMEMCUR_MAGIC   0xb19bdc1b



/****************************************************************************
** Utility routines.
*/

/* Recompute the KVMemNode.height and KVMemNode.imbalance fields for p.
** Assume that the children of p have correct heights.
*/
static void kvmemRecomputeHeight(KVMemNode *p){
  short int hBefore = p->pBefore ? p->pBefore->height : 0;
  short int hAfter = p->pAfter ? p->pAfter->height : 0;
  p->imbalance = hBefore - hAfter;  /* -: pAfter higher.  +: pBefore higher */
  p->height = (hBefore>hAfter ? hBefore : hAfter)+1;
}

/*
**     P                B
**    / \              / \
**   B   Z    ==>     X   P
**  / \                  / \
** X   Y                Y   Z
**
*/
static KVMemNode *kvmemRotateBefore(KVMemNode *pP){
  KVMemNode *pB = pP->pBefore;
  KVMemNode *pY = pB->pAfter;
  pB->pUp = pP->pUp;
  pB->pAfter = pP;
  pP->pUp = pB;
  pP->pBefore = pY;
  if( pY ) pY->pUp = pP;
  kvmemRecomputeHeight(pP);
  kvmemRecomputeHeight(pB);
  return pB;
}

/*
**     P                A
**    / \              / \
**   X   A    ==>     P   Z
**      / \          / \
**     Y   Z        X   Y
**
*/
static KVMemNode *kvmemRotateAfter(KVMemNode *pP){
  KVMemNode *pA = pP->pAfter;
  KVMemNode *pY = pA->pBefore;
  pA->pUp = pP->pUp;
  pA->pBefore = pP;
  pP->pUp = pA;
  pP->pAfter = pY;
  if( pY ) pY->pUp = pP;
  kvmemRecomputeHeight(pP);
  kvmemRecomputeHeight(pA);
  return pA;
}

/*
** Return a pointer to the pBefore or pAfter pointer in the parent
** of p that points to p.  Or if p is the root node, return pp.
*/
static KVMemNode **kvmemFromPtr(KVMemNode *p, KVMemNode **pp){
  KVMemNode *pUp = p->pUp;
  if( pUp==0 ) return pp;
  assert( pUp->pAfter==p || pUp->pBefore==p );
  if( pUp->pAfter==p ) return &pUp->pAfter;
  return &pUp->pBefore;
}

/*
** Rebalance all nodes starting with p and working up to the root.
** Return the new root.
*/
static KVMemNode *kvmemBalance(KVMemNode *p){
  KVMemNode *pTop = p;
  KVMemNode **pp;
  while( p ){
    kvmemRecomputeHeight(p);
    if( p->imbalance>=2 ){
      KVMemNode *pB = p->pBefore;
      if( pB->imbalance<0 ) p->pBefore = kvmemRotateAfter(pB);
      pp = kvmemFromPtr(p,&p);
      p = *pp = kvmemRotateBefore(p);
    }else if( p->imbalance<=(-2) ){
      KVMemNode *pA = p->pAfter;
      if( pA->imbalance>0 ) p->pAfter = kvmemRotateBefore(pA);
      pp = kvmemFromPtr(p,&p);
      p = *pp = kvmemRotateAfter(p);
    }
    pTop = p;
    p = p->pUp;
  }
  return pTop;
}

/*
** Key comparison routine.  
*/
static int kvmemKeyCompare(
  const KVByteArray *aK1, KVSize nK1,
  const KVByteArray *aK2, KVSize nK2
){
  int c;
  c = memcmp(aK1, aK2, nK1<nK2 ? nK1 : nK2);
  if( c==0 ) c = nK1 - nK2;
  return c;
}

/*
** Create a new KVMemData object
*/
static KVMemData *kvmemDataNew(
  sqlite4_env *pEnv,            /* Memory allocator context */
  const KVByteArray *aData,     /* Data for the new object */
  KVSize nData                  /* Bytes of content in aData[] */
){
  KVMemData *p = sqlite4_malloc(pEnv, sizeof(*p) + nData - 8 );
  if( p ) {
    p->nRef = 1;
    p->n = nData;
    memcpy(p->a, aData, nData);
  }
  return p;
}

/*
** Make a copy of a KVMemData object
*/
static KVMemData *kvmemDataRef(KVMemData *p){
  if( p ) p->nRef++;
  return p;
}

/*
** Dereference a KVMemData object
*/
static void kvmemDataUnref(sqlite4_env *pEnv, KVMemData *p){
  if( p && (--p->nRef)<=0 ) sqlite4_free(pEnv, p);
}

/*
** Reference a KVMemNode object
*/
static KVMemNode *kvmemNodeRef(KVMemNode *p){
  if( p ) p->nRef++;
  return p;
}

/*
** Dereference a KVMemNode object
*/
static void kvmemNodeUnref(sqlite4_env *pEnv, KVMemNode *p){
  if( p && (--p->nRef)<=0 ){
    kvmemDataUnref(pEnv, p->pData);
    sqlite4_free(pEnv, p);
  }
}

/*
** Recursively delete all nodes in a tree
*/
static void kvmemClearTree(sqlite4_env *pEnv, KVMemNode *pNode){
  if( pNode==0 ) return;
  kvmemClearTree(pEnv, pNode->pBefore);
  kvmemClearTree(pEnv, pNode->pAfter);
  kvmemNodeUnref(pEnv, pNode);
}

/*
** Return true if transactions are preserved
*/
#define kvmemTransactional(P) \
   (((P)->openFlags & SQLITE4_KVOPEN_NO_TRANSACTIONS)==0)

/*
** End of utilities
***************************************************************************
** Low-level operations on the tree
*/

/* Find the first node (the one with the smallest key).
*/
static KVMemNode *kvmemFirst(KVMemNode *p){
  if( p ) while( p->pBefore ) p = p->pBefore;
  return p;
}

/* Return the node with the next larger key after p.
*/
static KVMemNode *kvmemNext(KVMemNode *p){
  KVMemNode *pPrev = 0;
  while( p && p->pAfter==pPrev ){
    pPrev = p;
    p = p->pUp;
  }
  if( p && pPrev==0 ){
    p = kvmemFirst(p->pAfter);
  }
  return p;
}

/* Find the last node (the one with the largest key).
*/
static KVMemNode *kvmemLast(KVMemNode *p){
  if( p ) while( p->pAfter ) p = p->pAfter;
  return p;
}

/* Return the node with the next smaller key before p.
*/
static KVMemNode *kvmemPrev(KVMemNode *p){
  KVMemNode *pPrior = 0;
  while( p && p->pBefore==pPrior ){
    pPrior = p;
    p = p->pUp;
  }
  if( p && pPrior==0 ){
    p = kvmemLast(p->pBefore);
  }
  return p;
}

/*
** Create a new change record
*/
static KVMemChng *kvmemNewChng(KVMem *p, KVMemNode *pNode){
  KVMemChng *pChng;
  assert( p->base.iTransLevel>=2 );
  pChng = sqlite4_malloc(p->base.pEnv, sizeof(*pChng) );
  if( pChng ){
    pChng->pNext = p->apLog[p->base.iTransLevel-2];
    p->apLog[p->base.iTransLevel-2] = pChng;
    pChng->pNode = pNode;
    pChng->oldTrans = pNode->mxTrans;
    pNode->mxTrans = p->base.iTransLevel;
    pChng->pData = pNode->pData;
    pNode->pData = 0;
  }
  return pChng;
}

/* Create a new node.
*/
static KVMemNode *kvmemNewNode(
  KVMem *p,
  const KVByteArray *aKey,
  KVSize nKey
){
  KVMemNode *pNode;
  KVMemChng *pChng;
  assert( p->base.iTransLevel>=2 );
  pNode = sqlite4_malloc(p->base.pEnv, sizeof(*pNode)+nKey-2 );
  if( pNode ){
    memset(pNode, 0, sizeof(*pNode));
    memcpy(pNode->aKey, aKey, nKey);
    pNode->nKey = nKey;
    pNode->nRef = 1;
    if( kvmemTransactional(p) ){
      pChng = kvmemNewChng(p, pNode);
      if( pChng==0 ){
        sqlite4_free(p->base.pEnv, pNode);
        pNode = 0;
      }
      assert( pChng==0 || pChng->pData==0 );
    }
  }
  return pNode;
}

#ifdef SQLITE4_DEBUG
/*
** Return the number of times that node pNode occurs in the sub-tree 
** headed by node pSub. This is used to assert() that no node structure
** is linked into the tree more than once.
*/
#if 0
static int countNodeOccurences(KVMemNode *pSub, KVMemNode *pNode){
  int iRet = (pSub==pNode);
  if( pSub ){
    iRet += countNodeOccurences(pSub->pBefore, pNode);
    iRet += countNodeOccurences(pSub->pAfter, pNode);
  }
  return iRet;
}
#endif

/*
** Check that all the pUp pointers in the sub-tree headed by pSub are
** correct. Fail an assert if this is not the case.
*/
static void assertUpPointers(KVMemNode *pSub){
  if( pSub ){
    assert( pSub->pBefore==0 || pSub->pBefore->pUp==pSub );
    assert( pSub->pAfter==0 || pSub->pAfter->pUp==pSub );
    assertUpPointers(pSub->pBefore);
    assertUpPointers(pSub->pAfter);
  }
}

#else
#define assertUpPointers(x)
#endif

/* Remove node pOld from the tree.  pOld must be an element of the tree.
*/
static void kvmemRemoveNode(KVMem *p, KVMemNode *pOld){
  KVMemNode **ppParent;           /* Location of pointer to pOld */
  KVMemNode *pBalance;            /* Node to run kvmemBalance() on */
  kvmemDataUnref(p->base.pEnv, pOld->pData);
  pOld->pData = 0;
  ppParent = kvmemFromPtr(pOld, &p->pRoot);
  if( pOld->pBefore==0 && pOld->pAfter==0 ){
    *ppParent = 0;
    pBalance = pOld->pUp;
  }else if( pOld->pBefore && pOld->pAfter ){
    KVMemNode *pX;                /* Smallest node that is larger than pOld */
    KVMemNode *pY;                /* Left-hand child of pOld */
    pX = kvmemFirst(pOld->pAfter);
    assert( pX->pBefore==0 );
    if( pX==pOld->pAfter ){
      pBalance = pX;
    }else{
      *kvmemFromPtr(pX, 0) = pX->pAfter;
      if( pX->pAfter ) pX->pAfter->pUp = pX->pUp;
      pBalance = pX->pUp;
      pX->pAfter = pOld->pAfter;
      if( pX->pAfter ){
        pX->pAfter->pUp = pX;
      }else{
        assert( pBalance==pOld );
        pBalance = pX;
      }
    }
    pX->pBefore = pY = pOld->pBefore;
    if( pY ) pY->pUp = pX;
    pX->pUp = pOld->pUp;
    *ppParent = pX;
  }else if( pOld->pBefore==0 ){
    *ppParent = pBalance = pOld->pAfter;
    pBalance->pUp = pOld->pUp;
  }else if( pOld->pAfter==0 ){
    *ppParent = pBalance = pOld->pBefore;
    pBalance->pUp = pOld->pUp;
  }
  p->pRoot = kvmemBalance(pBalance);
  kvmemNodeUnref(p->base.pEnv, pOld);
}

/*
** End of low-level access routines
***************************************************************************
** Interface routines follow
*/
  
/*
** Begin a transaction or subtransaction.
**
** If iLevel==1 then begin an outermost read transaction.
**
** If iLevel==2 then begin an outermost write transaction.
**
** If iLevel>2 then begin a nested write transaction.
**
** iLevel may not be less than 1.  After this routine returns successfully
** the transaction level will be equal to iLevel.  The transaction level
** must be at least 1 to read and at least 2 to write.
*/
static int kvmemBegin(KVStore *pKVStore, int iLevel){
  KVMem *p = (KVMem*)pKVStore;
  assert( p->iMagicKVMemBase==SQLITE4_KVMEMBASE_MAGIC );
  assert( iLevel>0 );
  assert( iLevel==2 || iLevel==p->base.iTransLevel+1 );
  if( iLevel>=2 ){
    KVMemChng **apNewLog;
    apNewLog = sqlite4_realloc(p->base.pEnv, p->apLog,
                               sizeof(apNewLog[0])*(iLevel-1) );
    if( apNewLog==0 ) return SQLITE4_NOMEM;
    p->apLog = apNewLog;
    p->apLog[iLevel-2] = 0;
  }
  p->base.iTransLevel = iLevel;
  return SQLITE4_OK;
}

/*
** Commit a transaction or subtransaction.
**
** Make permanent all changes back through the most recent xBegin 
** with the iLevel+1.  If iLevel==0 then make all changes permanent.
** The argument iLevel will always be less than the current transaction
** level when this routine is called.
**
** Commit is divided into two phases.  A rollback is still possible after
** phase one completes.  In this implementation, phase one is a no-op since
** phase two cannot fail.
**
** After this routine returns successfully, the transaction level will be 
** equal to iLevel.
*/
static int kvmemCommitPhaseOne(KVStore *pKVStore, int iLevel){
  return SQLITE4_OK;
}
static int kvmemCommitPhaseTwo(KVStore *pKVStore, int iLevel){
  KVMem *p = (KVMem*)pKVStore;
  assert( p->iMagicKVMemBase==SQLITE4_KVMEMBASE_MAGIC );
  assert( iLevel>=0 );
  assert( iLevel<p->base.iTransLevel );
  assertUpPointers(p->pRoot);
  if( !kvmemTransactional(p) ) return SQLITE4_OK;
  while( p->base.iTransLevel>iLevel && p->base.iTransLevel>1 ){
    KVMemChng *pChng, *pNext;

    if( iLevel<2 ){
      for(pChng=p->apLog[p->base.iTransLevel-2]; pChng; pChng=pNext){
        KVMemNode *pNode = pChng->pNode;
        if( pNode->pData ){
          pNode->mxTrans = pChng->oldTrans;
        }else{
          kvmemRemoveNode(p, pNode);
        }
        kvmemDataUnref(p->base.pEnv, pChng->pData);
        pNext = pChng->pNext;
        sqlite4_free(p->base.pEnv, pChng);
      }
    }else{
      KVMemChng **pp;
      int iFrom = p->base.iTransLevel-2;
      int iTo = p->base.iTransLevel-3;
      assert( iTo>=0 );

      for(pp=&p->apLog[iFrom]; *pp; pp=&((*pp)->pNext)){
        assert( (*pp)->pNode->mxTrans==p->base.iTransLevel 
             || (*pp)->pNode->mxTrans==(p->base.iTransLevel-1)
        );
        (*pp)->pNode->mxTrans = p->base.iTransLevel - 1;
      }
      *pp = p->apLog[iTo];
      p->apLog[iTo] = p->apLog[iFrom];
    }

    p->apLog[p->base.iTransLevel-2] = 0;
    p->base.iTransLevel--;
  }
  assertUpPointers(p->pRoot);
  p->base.iTransLevel = iLevel;
  return SQLITE4_OK;
}

/*
** Rollback a transaction or subtransaction.
**
** Revert all uncommitted changes back through the most recent xBegin or 
** xCommit with the same iLevel.  If iLevel==0 then back out all uncommited
** changes.
**
** After this routine returns successfully, the transaction level will be
** equal to iLevel.
*/
static int kvmemRollback(KVStore *pKVStore, int iLevel){
  KVMem *p = (KVMem*)pKVStore;
  assert( p->iMagicKVMemBase==SQLITE4_KVMEMBASE_MAGIC );
  assert( iLevel>=0 );
  if( !kvmemTransactional(p) ) return SQLITE4_OK;
  while( p->base.iTransLevel>iLevel && p->base.iTransLevel>1 ){
    KVMemChng *pChng, *pNext;
    for(pChng=p->apLog[p->base.iTransLevel-2]; pChng; pChng=pNext){
      KVMemNode *pNode = pChng->pNode;
      if( pChng->pData || pChng->oldTrans>0 ){
        kvmemDataUnref(p->base.pEnv, pNode->pData);
        pNode->pData = pChng->pData;
        pNode->mxTrans = pChng->oldTrans;
      }else{
        kvmemRemoveNode(p, pNode);
      }
      pNext = pChng->pNext;
      sqlite4_free(p->base.pEnv, pChng);
    }
    p->apLog[p->base.iTransLevel-2] = 0;
    p->base.iTransLevel--;
  }
  p->base.iTransLevel = iLevel;
  return SQLITE4_OK;
}

/*
** Revert a transaction back to what it was when it started.
*/
static int kvmemRevert(KVStore *pKVStore, int iLevel){
  int rc = kvmemRollback(pKVStore, iLevel-1);
  if( rc==SQLITE4_OK ){
    rc = kvmemBegin(pKVStore, iLevel);
  }
  return rc;
}

/*
** Implementation of the xReplace(X, aKey, nKey, aData, nData) method.
**
** Insert or replace the entry with the key aKey[0..nKey-1].  The data for
** the new entry is aData[0..nData-1].  Return SQLITE4_OK on success or an
** error code if the insert fails.
**
** The inputs aKey[] and aData[] are only valid until this routine
** returns.  If the storage engine needs to keep that information
** long-term, it will need to make its own copy of these values.
**
** A transaction will always be active when this routine is called.
*/
static int kvmemReplace(
  KVStore *pKVStore,
  const KVByteArray *aKey, KVSize nKey,
  const KVByteArray *aData, KVSize nData
){
  KVMem *p = (KVMem*)pKVStore;
  KVMemNode *pNew, *pNode;
  KVMemData *pData;
  KVMemChng *pChng;
  assert( p->iMagicKVMemBase==SQLITE4_KVMEMBASE_MAGIC );
  assert( p->base.iTransLevel>=2 );
  pData = kvmemDataNew(p->base.pEnv, aData, nData);
  if( pData==0 ) return SQLITE4_NOMEM;
  if( p->pRoot==0 ){
    pNode = pNew = kvmemNewNode(p, aKey, nKey);
    if( pNew==0 ) goto KVMemReplace_nomem;
    pNew->pUp = 0;
  }else{
    pNode = p->pRoot;
    while( pNode ){
      int c = kvmemKeyCompare(aKey, nKey, pNode->aKey, pNode->nKey);
      if( c<0 ){
        if( pNode->pBefore ){
          pNode = pNode->pBefore;
        }else{
          pNode->pBefore = pNew = kvmemNewNode(p, aKey, nKey);
          if( pNew==0 ) goto KVMemReplace_nomem;
          pNew->pUp = pNode;
          break;
        }
      }else if( c>0 ){
        if( pNode->pAfter ){
          pNode = pNode->pAfter;
        }else{
          pNode->pAfter = pNew = kvmemNewNode(p, aKey, nKey);
          if( pNew==0 ) goto KVMemReplace_nomem;
          pNew->pUp = pNode;
          break;
        }
      }else{
        if( kvmemTransactional(p) && pNode->mxTrans!=p->base.iTransLevel ){
          pChng = kvmemNewChng(p, pNode);
          if( pChng==0 ) goto KVMemReplace_nomem;
        }else{
          kvmemDataUnref(p->base.pEnv, pNode->pData);
        }
        pNode->pData = pData;
        return SQLITE4_OK;
      }
    }
  }
  pNew->pData = pData;
  pNew->height = 1;
  p->pRoot = kvmemBalance(pNew);
  return SQLITE4_OK;

KVMemReplace_nomem:
  kvmemDataUnref(p->base.pEnv, pData);
  return SQLITE4_NOMEM;
}

/*
** Create a new cursor object.
*/
static int kvmemOpenCursor(KVStore *pKVStore, KVCursor **ppKVCursor){
  KVMem *p = (KVMem*)pKVStore;
  KVMemCursor *pCur;
  assert( p->iMagicKVMemBase==SQLITE4_KVMEMBASE_MAGIC );
  pCur = sqlite4_malloc(p->base.pEnv, sizeof(*pCur) );
  if( pCur==0 ){
    *ppKVCursor = 0;
    return SQLITE4_NOMEM;
  }
  memset(pCur, 0, sizeof(*pCur));
  pCur->pOwner = p;
  p->nCursor++;
  pCur->iMagicKVMemCur = SQLITE4_KVMEMCUR_MAGIC;
  pCur->base.pStore = pKVStore;
  pCur->base.pStoreVfunc = pKVStore->pStoreVfunc;
  *ppKVCursor = (KVCursor*)pCur;
  return SQLITE4_OK;
}

/*
** Reset a cursor
*/
static int kvmemReset(KVCursor *pKVCursor){
  KVMemCursor *pCur = (KVMemCursor*)pKVCursor;
  assert( pCur->iMagicKVMemCur==SQLITE4_KVMEMCUR_MAGIC );
  kvmemDataUnref(pCur->base.pEnv, pCur->pData);
  pCur->pData = 0;
  kvmemNodeUnref(pCur->base.pEnv, pCur->pNode);
  pCur->pNode = 0;
  return SQLITE4_OK;
}

/*
** Destroy a cursor object
*/
static int kvmemCloseCursor(KVCursor *pKVCursor){
  KVMemCursor *pCur = (KVMemCursor*)pKVCursor;
  if( pCur ){
    assert( pCur->iMagicKVMemCur==SQLITE4_KVMEMCUR_MAGIC );
    assert( pCur->pOwner->iMagicKVMemBase==SQLITE4_KVMEMBASE_MAGIC );
    pCur->pOwner->nCursor--;
    kvmemReset(pKVCursor);
    memset(pCur, 0, sizeof(*pCur));
    sqlite4_free(pCur->base.pEnv, pCur);
  }
  return SQLITE4_OK;
}

/*
** Move a cursor to the next non-deleted node.
*/
static int kvmemNextEntry(KVCursor *pKVCursor){
  KVMemCursor *pCur;
  KVMemNode *pNode;

  pCur = (KVMemCursor*)pKVCursor;
  assert( pCur->iMagicKVMemCur==SQLITE4_KVMEMCUR_MAGIC );
  pNode = pCur->pNode;
  kvmemReset(pKVCursor);
  do{
    pNode = kvmemNext(pNode);
  }while( pNode && pNode->pData==0 );
  if( pNode ){
    pCur->pNode = kvmemNodeRef(pNode);
    pCur->pData = kvmemDataRef(pNode->pData);
  }
  return pNode ? SQLITE4_OK : SQLITE4_NOTFOUND;
}

/*
** Move a cursor to the previous non-deleted node.
*/
static int kvmemPrevEntry(KVCursor *pKVCursor){
  KVMemCursor *pCur;
  KVMemNode *pNode;

  pCur = (KVMemCursor*)pKVCursor;
  assert( pCur->iMagicKVMemCur==SQLITE4_KVMEMCUR_MAGIC );
  pNode = pCur->pNode;
  kvmemReset(pKVCursor);
  do{
    pNode = kvmemPrev(pNode);
  }while( pNode && pNode->pData==0 );
  if( pNode ){
    pCur->pNode = kvmemNodeRef(pNode);
    pCur->pData = kvmemDataRef(pNode->pData);
  }
  return pNode ? SQLITE4_OK : SQLITE4_NOTFOUND;
}

/*
** Seek a cursor.
*/
static int kvmemSeek(
  KVCursor *pKVCursor, 
  const KVByteArray *aKey,
  KVSize nKey,
  int direction
){
  KVMemCursor *pCur;
  KVMemNode *pNode;
  KVMemNode *pBest = 0;
  int c;
  int rc = SQLITE4_NOTFOUND;

  kvmemReset(pKVCursor);
  pCur = (KVMemCursor*)pKVCursor;
  assert( pCur->iMagicKVMemCur==SQLITE4_KVMEMCUR_MAGIC );

  pNode = pCur->pOwner->pRoot;
  while( pNode ){
    c = kvmemKeyCompare(aKey, nKey, pNode->aKey, pNode->nKey);
    if( c==0 ){
      pBest = pNode;
      rc = SQLITE4_OK;
      pNode = 0;
    }else if( c>0 ){
      if( direction<0 ){
        pBest = pNode;
        rc = SQLITE4_INEXACT;
      }
      pNode = pNode->pAfter;
    }else{
      if( direction>0 ){
        pBest = pNode;
        rc = SQLITE4_INEXACT;
      }
      pNode = pNode->pBefore;
    }
  }
  kvmemNodeUnref(pCur->base.pEnv, pCur->pNode);
  kvmemDataUnref(pCur->base.pEnv, pCur->pData);
  if( pBest ){
    pCur->pNode = kvmemNodeRef(pBest);
    pCur->pData = kvmemDataRef(pBest->pData);

    /* The cursor currently points to a deleted node. If parameter 'direction'
    ** was zero (exact matches only), then the search has failed - return
    ** SQLITE4_NOTFOUND. Otherwise, advance to the next (if direction is +ve)
    ** or the previous (if direction is -ve) undeleted node in the tree.  */
    if( pCur->pData==0 ){
      if( direction==0 ){
        rc = SQLITE4_NOTFOUND;
      }else{ 
        if( (direction>0 ? kvmemNextEntry : kvmemPrevEntry)(pKVCursor) ){
          rc = SQLITE4_NOTFOUND;
        }else{
          rc = SQLITE4_INEXACT;
        }
      }
    }

  }else{
    pCur->pNode = 0;
    pCur->pData = 0;
  }
  assert( rc!=SQLITE4_DONE );
  return rc;
}

/*
** Delete the entry that the cursor is pointing to.
**
** Though the entry is "deleted", it still continues to exist as a
** phantom.  Subsequent xNext or xPrev calls will work, as will
** calls to xKey and xData, thought the result from xKey and xData
** are undefined.
*/
static int kvmemDelete(KVCursor *pKVCursor){
  KVMemCursor *pCur;
  KVMemNode *pNode;
  KVMemChng *pChng;
  KVMem *p;

  pCur = (KVMemCursor*)pKVCursor;
  assert( pCur->iMagicKVMemCur==SQLITE4_KVMEMCUR_MAGIC );
  p = pCur->pOwner;
  assert( p->iMagicKVMemBase==SQLITE4_KVMEMBASE_MAGIC );
  assert( p->base.iTransLevel>=2 );
  pNode = pCur->pNode;
  if( pNode==0 ) return SQLITE4_OK;
  if( !kvmemTransactional(p) ){
    kvmemNodeUnref(p->base.pEnv, pNode);
    pCur->pNode = 0;
    kvmemRemoveNode(p, pNode);
  }else if( pNode->pData==0 ){
    /* no-op */
  }else if( pNode->mxTrans<p->base.iTransLevel ){
    pChng = kvmemNewChng(p, pNode);
    if( pChng==0 ) return SQLITE4_NOMEM;
    assert( pNode->pData==0 );
  }else{
    kvmemDataUnref(pCur->base.pEnv, pNode->pData);
    pNode->pData = 0;
  }
  return SQLITE4_OK;
}

/*
** Return the key of the node the cursor is pointing to.
*/
static int kvmemKey(
  KVCursor *pKVCursor,         /* The cursor whose key is desired */
  const KVByteArray **paKey,   /* Make this point to the key */
  KVSize *pN                   /* Make this point to the size of the key */
){
  KVMemCursor *pCur;
  KVMemNode *pNode;

  pCur = (KVMemCursor*)pKVCursor;
  assert( pCur->iMagicKVMemCur==SQLITE4_KVMEMCUR_MAGIC );
  pNode = pCur->pNode;
  if( pNode==0 ){
    *paKey = 0;
    *pN = 0;
    return SQLITE4_DONE;
  }
  *paKey = pNode->aKey;
  *pN = pNode->nKey;
  return SQLITE4_OK;
}

/*
** Return the data of the node the cursor is pointing to.
*/
static int kvmemData(
  KVCursor *pKVCursor,         /* The cursor from which to take the data */
  KVSize ofst,                 /* Offset into the data to begin reading */
  KVSize n,                    /* Number of bytes requested */
  const KVByteArray **paData,  /* Pointer to the data written here */
  KVSize *pNData               /* Number of bytes delivered */
){
  KVMemCursor *pCur;
  KVMemData *pData;

  pCur = (KVMemCursor*)pKVCursor;
  assert( pCur->iMagicKVMemCur==SQLITE4_KVMEMCUR_MAGIC );
  pData = pCur->pData;
  if( pData==0 ){
    *paData = 0;
    *pNData = 0;
    return SQLITE4_DONE;
  }
  *paData = pData->a + ofst;
  *pNData = pData->n - ofst;
  return SQLITE4_OK;
}

/*
** Destructor for the entire in-memory storage tree.
*/
static int kvmemClose(KVStore *pKVStore){
  KVMem *p = (KVMem*)pKVStore;
  sqlite4_env *pEnv;
  if( p==0 ) return SQLITE4_OK;
  assert( p->iMagicKVMemBase==SQLITE4_KVMEMBASE_MAGIC );
  assert( p->nCursor==0 );
  pEnv = p->base.pEnv;
  if( p->base.iTransLevel ){
    kvmemCommitPhaseOne(pKVStore, 0);
    kvmemCommitPhaseTwo(pKVStore, 0);
  }
  sqlite4_free(pEnv, p->apLog);
  kvmemClearTree(pEnv, p->pRoot);
  memset(p, 0, sizeof(*p));
  sqlite4_free(pEnv, p);
  return SQLITE4_OK;
}

static int kvmemControl(KVStore *pKVStore, int op, void *pArg){
  return SQLITE4_NOTFOUND;
}

static int kvmemGetMeta(KVStore *pKVStore, unsigned int *piVal){
  KVMem *p = (KVMem*)pKVStore;
  *piVal = p->iMeta;
  return SQLITE4_OK;
}

static int kvmemPutMeta(KVStore *pKVStore, unsigned int iVal){
  KVMem *p = (KVMem*)pKVStore;
  p->iMeta = iVal;
  return SQLITE4_OK;
}

/* Virtual methods for the in-memory storage engine */
static const KVStoreMethods kvmemMethods = {
  1,                        /* iVersion */
  sizeof(KVStoreMethods),   /* szSelf */
  kvmemReplace,             /* xReplace */
  kvmemOpenCursor,          /* xOpenCursor */
  kvmemSeek,                /* xSeek */
  kvmemNextEntry,           /* xNext */
  kvmemPrevEntry,           /* xPrev */
  kvmemDelete,              /* xDelete */
  kvmemKey,                 /* xKey */
  kvmemData,                /* xData */
  kvmemReset,               /* xReset */
  kvmemCloseCursor,         /* xCloseCursor */
  kvmemBegin,               /* xBegin */
  kvmemCommitPhaseOne,      /* xCommitPhaseOne */
  kvmemCommitPhaseTwo,      /* xCommitPhaseTwo */
  kvmemRollback,            /* xRollback */
  kvmemRevert,              /* xRevert */
  kvmemClose,               /* xClose */
  kvmemControl,             /* xControl */
  kvmemGetMeta,             /* xGetMeta */
  kvmemPutMeta              /* xPutMeta */
};

/*
** Create a new in-memory storage engine and return a pointer to it.
*/
SQLITE4_PRIVATE int sqlite4KVStoreOpenMem(
  sqlite4_env *pEnv,              /* Runtime environment */
  KVStore **ppKVStore,            /* OUT: Write the new KVStore here */
  const char *zName,              /* Name of in-memory storage unit */
  unsigned openFlags              /* Flags */
){
  KVMem *pNew = sqlite4_malloc(pEnv, sizeof(*pNew) );
  if( pNew==0 ) return SQLITE4_NOMEM;
  memset(pNew, 0, sizeof(*pNew));
  pNew->base.pStoreVfunc = &kvmemMethods;
  pNew->base.pEnv = pEnv;
  pNew->iMagicKVMemBase = SQLITE4_KVMEMBASE_MAGIC;
  pNew->openFlags = openFlags;
  *ppKVStore = (KVStore*)pNew;
  return SQLITE4_OK;
}

/************** End of kvmem.c ***********************************************/
/************** Begin file kvlsm.c *******************************************/
/*
** 2012 January 20
**
** 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.
**
*************************************************************************
**
** An in-memory key/value storage subsystem that presents the interfadce
** defined by kv.h
*/

/* Forward declarations of objects */
typedef struct KVLsm KVLsm;
typedef struct KVLsmCsr KVLsmCsr;

/*
** An instance of an open connection to an LSM store.  A subclass of KVStore.
*/
struct KVLsm {
  KVStore base;                   /* Base class, must be first */
  lsm_db *pDb;                    /* LSM database handle */
  lsm_cursor *pCsr;               /* LSM cursor holding read-trans open */
};

/*
** An instance of an open cursor pointing into an LSM store.  A subclass
** of KVCursor.
*/
struct KVLsmCsr {
  KVCursor base;                  /* Base class. Must be first */
  lsm_cursor *pCsr;               /* LSM cursor handle */
};
  
/*
** Begin a transaction or subtransaction.
**
** If iLevel==1 then begin an outermost read transaction.
**
** If iLevel==2 then begin an outermost write transaction.
**
** If iLevel>2 then begin a nested write transaction.
**
** iLevel may not be less than 1.  After this routine returns successfully
** the transaction level will be equal to iLevel.  The transaction level
** must be at least 1 to read and at least 2 to write.
*/
static int kvlsmBegin(KVStore *pKVStore, int iLevel){
  int rc = SQLITE4_OK;
  KVLsm *p = (KVLsm *)pKVStore;

  assert( iLevel>0 );
  if( p->pCsr==0 ){
    rc = lsm_csr_open(p->pDb, &p->pCsr);
  }
  if( rc==SQLITE4_OK && iLevel>=2 && iLevel>=pKVStore->iTransLevel ){
    rc = lsm_begin(p->pDb, iLevel-1);
  }

  if( rc==SQLITE4_OK ){
    pKVStore->iTransLevel = SQLITE4_MAX(iLevel, pKVStore->iTransLevel);
  }else if( pKVStore->iTransLevel==0 ){
    lsm_csr_close(p->pCsr);
    p->pCsr = 0;
  }

  return rc;
}

/*
** Commit a transaction or subtransaction.
**
** Make permanent all changes back through the most recent xBegin 
** with the iLevel+1.  If iLevel==0 then make all changes permanent.
** The argument iLevel will always be less than the current transaction
** level when this routine is called.
**
** Commit is divided into two phases.  A rollback is still possible after
** phase one completes.  In this implementation, phase one is a no-op since
** phase two cannot fail.
**
** After this routine returns successfully, the transaction level will be 
** equal to iLevel.
*/
static int kvlsmCommitPhaseOne(KVStore *pKVStore, int iLevel){
  return SQLITE4_OK;
}
static int kvlsmCommitPhaseTwo(KVStore *pKVStore, int iLevel){
  int rc = SQLITE4_OK;
  KVLsm *p = (KVLsm *)pKVStore;

  if( pKVStore->iTransLevel>iLevel ){
    if( pKVStore->iTransLevel>=2 ){
      rc = lsm_commit(p->pDb, SQLITE4_MAX(0, iLevel-1));
    }
    if( iLevel==0 ){
      lsm_csr_close(p->pCsr);
      p->pCsr = 0;
    }
    if( rc==SQLITE4_OK ){
      pKVStore->iTransLevel = iLevel;
    }
  }
  return rc;
}

/*
** Rollback a transaction or subtransaction.
**
** Revert all uncommitted changes back through the most recent xBegin or 
** xCommit with the same iLevel.  If iLevel==0 then back out all uncommited
** changes.
**
** After this routine returns successfully, the transaction level will be
** equal to iLevel.
*/
static int kvlsmRollback(KVStore *pKVStore, int iLevel){
  int rc = SQLITE4_OK;
  KVLsm *p = (KVLsm *)pKVStore;

  if( pKVStore->iTransLevel>=iLevel ){
    if( pKVStore->iTransLevel>=2 ){
      rc = lsm_rollback(p->pDb, SQLITE4_MAX(0, iLevel-1));
    }
    if( iLevel==0 ){
      lsm_csr_close(p->pCsr);
      p->pCsr = 0;
    }
    if( rc==SQLITE4_OK ){
      pKVStore->iTransLevel = iLevel;
    }
  }
  return rc;
}

/*
** Revert a transaction back to what it was when it started.
*/
static int kvlsmRevert(KVStore *pKVStore, int iLevel){
  return SQLITE4_OK;
}

/*
** Implementation of the xReplace(X, aKey, nKey, aData, nData) method.
**
** Insert or replace the entry with the key aKey[0..nKey-1].  The data for
** the new entry is aData[0..nData-1].  Return SQLITE4_OK on success or an
** error code if the insert fails.
**
** The inputs aKey[] and aData[] are only valid until this routine
** returns.  If the storage engine needs to keep that information
** long-term, it will need to make its own copy of these values.
**
** A transaction will always be active when this routine is called.
*/
static int kvlsmReplace(
  KVStore *pKVStore,
  const KVByteArray *aKey, KVSize nKey,
  const KVByteArray *aData, KVSize nData
){
  KVLsm *p = (KVLsm *)pKVStore;
  return lsm_insert(p->pDb, (void *)aKey, nKey, (void *)aData, nData);
}

/*
** Create a new cursor object.
*/
static int kvlsmOpenCursor(KVStore *pKVStore, KVCursor **ppKVCursor){
  int rc = SQLITE4_OK;
  KVLsm *p = (KVLsm *)pKVStore;
  KVLsmCsr *pCsr;

  pCsr = (KVLsmCsr *)sqlite4_malloc(pKVStore->pEnv, sizeof(KVLsmCsr));
  if( pCsr==0 ){
    rc = SQLITE4_NOMEM;
  }else{
    memset(pCsr, 0, sizeof(KVLsmCsr));
    rc = lsm_csr_open(p->pDb, &pCsr->pCsr);

    if( rc==SQLITE4_OK ){
      pCsr->base.pStore = pKVStore;
      pCsr->base.pStoreVfunc = pKVStore->pStoreVfunc;
    }else{
      sqlite4_free(pCsr->base.pEnv, pCsr);
      pCsr = 0;
    }
  }

  *ppKVCursor = (KVCursor*)pCsr;
  return rc;
}

/*
** Reset a cursor
*/
static int kvlsmReset(KVCursor *pKVCursor){
  return SQLITE4_OK;
}

/*
** Destroy a cursor object
*/
static int kvlsmCloseCursor(KVCursor *pKVCursor){
  KVLsmCsr *pCsr = (KVLsmCsr *)pKVCursor;
  lsm_csr_close(pCsr->pCsr);
  sqlite4_free(pCsr->base.pEnv, pCsr);
  return SQLITE4_OK;
}

/*
** Move a cursor to the next non-deleted node.
*/
static int kvlsmNextEntry(KVCursor *pKVCursor){
  int rc;
  KVLsmCsr *pCsr = (KVLsmCsr *)pKVCursor;

  if( lsm_csr_valid(pCsr->pCsr)==0 ) return SQLITE4_NOTFOUND;
  rc = lsm_csr_next(pCsr->pCsr);
  if( rc==LSM_OK && lsm_csr_valid(pCsr->pCsr)==0 ){
    rc = SQLITE4_NOTFOUND;
  }
  return rc;
}

/*
** Move a cursor to the previous non-deleted node.
*/
static int kvlsmPrevEntry(KVCursor *pKVCursor){
  int rc;
  KVLsmCsr *pCsr = (KVLsmCsr *)pKVCursor;

  if( lsm_csr_valid(pCsr->pCsr)==0 ) return SQLITE4_NOTFOUND;
  rc = lsm_csr_prev(pCsr->pCsr);
  if( rc==LSM_OK && lsm_csr_valid(pCsr->pCsr)==0 ){
    rc = SQLITE4_NOTFOUND;
  }
  return rc;
}

/*
** Seek a cursor.
*/
static int kvlsmSeek(
  KVCursor *pKVCursor, 
  const KVByteArray *aKey,
  KVSize nKey,
  int dir
){
  int rc;
  KVLsmCsr *pCsr = (KVLsmCsr *)pKVCursor;

  assert( dir==0 || dir==1 || dir==-1 || dir==-2 );
  assert( LSM_SEEK_EQ==0 && LSM_SEEK_GE==1 && LSM_SEEK_LE==-1 );
  assert( LSM_SEEK_LEFAST==-2 );

  rc = lsm_csr_seek(pCsr->pCsr, (void *)aKey, nKey, dir);
  if( rc==SQLITE4_OK ){
    if( lsm_csr_valid(pCsr->pCsr)==0 ){
      rc = SQLITE4_NOTFOUND;
    }else{
      const void *pDbKey;
      int nDbKey;

      rc = lsm_csr_key(pCsr->pCsr, &pDbKey, &nDbKey);
      if( rc==SQLITE4_OK && (nDbKey!=nKey || memcmp(pDbKey, aKey, nKey)) ){
        rc = SQLITE4_INEXACT;
      }
    }
  }

  return rc;
}

/*
** Delete the entry that the cursor is pointing to.
**
** Though the entry is "deleted", it still continues to exist as a
** phantom.  Subsequent xNext or xPrev calls will work, as will
** calls to xKey and xData, thought the result from xKey and xData
** are undefined.
*/
static int kvlsmDelete(KVCursor *pKVCursor){
  int rc;
  const void *pKey;
  int nKey;
  KVLsmCsr *pCsr = (KVLsmCsr *)pKVCursor;

  assert( lsm_csr_valid(pCsr->pCsr) );
  rc = lsm_csr_key(pCsr->pCsr, &pKey, &nKey);
  if( rc==SQLITE4_OK ){
    rc = lsm_delete(((KVLsm *)(pKVCursor->pStore))->pDb, pKey, nKey);
  }

  return SQLITE4_OK;
}

/*
** Return the key of the node the cursor is pointing to.
*/
static int kvlsmKey(
  KVCursor *pKVCursor,         /* The cursor whose key is desired */
  const KVByteArray **paKey,   /* Make this point to the key */
  KVSize *pN                   /* Make this point to the size of the key */
){
  KVLsmCsr *pCsr = (KVLsmCsr *)pKVCursor;
  if( 0==lsm_csr_valid(pCsr->pCsr) ) return SQLITE4_DONE;
  return lsm_csr_key(pCsr->pCsr, (const void **)paKey, (int *)pN);
}

/*
** Return the data of the node the cursor is pointing to.
*/
static int kvlsmData(
  KVCursor *pKVCursor,         /* The cursor from which to take the data */
  KVSize ofst,                 /* Offset into the data to begin reading */
  KVSize n,                    /* Number of bytes requested */
  const KVByteArray **paData,  /* Pointer to the data written here */
  KVSize *pNData               /* Number of bytes delivered */
){
  KVLsmCsr *pCsr = (KVLsmCsr *)pKVCursor;
  int rc;
  void *pData;
  int nData;

  rc = lsm_csr_value(pCsr->pCsr, (const void **)&pData, &nData);
  if( rc==SQLITE4_OK ){
    if( n<0 ){
      *paData = pData;
      *pNData = nData;
    }else{
      int nOut = n;
      if( (ofst+n)>nData ) nOut = nData - ofst;
      if( nOut<0 ) nOut = 0;

      *paData = &((u8 *)pData)[n];
      *pNData = nOut;
    }
  }

  return rc;
}

/*
** Destructor for the entire in-memory storage tree.
*/
static int kvlsmClose(KVStore *pKVStore){
  KVLsm *p = (KVLsm *)pKVStore;

  /* If there is an active transaction, roll it back. The important
  ** part is that the read-transaction cursor is closed. Otherwise, the
  ** call to lsm_close() below will fail.  */
  kvlsmRollback(pKVStore, 0);
  assert( p->pCsr==0 );

  lsm_close(p->pDb);
  sqlite4_free(p->base.pEnv, p);
  return SQLITE4_OK;
}

static int kvlsmControl(KVStore *pKVStore, int op, void *pArg){
  int rc = SQLITE4_OK;
  KVLsm *p = (KVLsm *)pKVStore;

  switch( op ){
    case SQLITE4_KVCTRL_LSM_HANDLE: {
      lsm_db **ppOut = (lsm_db **)pArg;
      *ppOut = p->pDb;
      break;
    }

    case SQLITE4_KVCTRL_SYNCHRONOUS: {
      int *peSafety = (int *)pArg;
      int eParam = *peSafety + 1;
      lsm_config(p->pDb, LSM_CONFIG_SAFETY, &eParam);
      *peSafety = eParam-1;
      break;
    }

    case SQLITE4_KVCTRL_LSM_FLUSH: {
      lsm_flush(p->pDb);
      break;
    }

    case SQLITE4_KVCTRL_LSM_MERGE: {
      int nPage = *(int*)pArg;
      int nWrite = 0;
      lsm_work(p->pDb, 0, nPage, &nWrite);
      *(int*)pArg = nWrite;
      break;
    }

    case SQLITE4_KVCTRL_LSM_CHECKPOINT: {
      lsm_checkpoint(p->pDb, 0);
      break;
    }


    default:
      rc = SQLITE4_NOTFOUND;
      break;
  }

  return rc;
}

static int kvlsmGetMeta(KVStore *pKVStore, unsigned int *piVal){
  KVLsm *p = (KVLsm *)pKVStore;
  return lsm_get_user_version(p->pDb, piVal);
}

static int kvlsmPutMeta(KVStore *pKVStore, unsigned int iVal){
  KVLsm *p = (KVLsm *)pKVStore;
  return lsm_set_user_version(p->pDb, iVal);
}

typedef struct PragmaCtx PragmaCtx;
struct PragmaCtx {
  lsm_db *pDb;
  int ePragma;
};

#define KVLSM_LSM_FLUSH      1
#define KVLSM_LSM_WORK       2
#define KVLSM_LSM_CHECKPOINT 3

static void kvlsmPragmaDestroy(void *p){
  sqlite4_free(0, p);
}

static void kvlsmPragma(sqlite4_context *ctx, int nArg, sqlite4_value **apArg){
  PragmaCtx *p = (PragmaCtx *)sqlite4_context_appdata(ctx);
  int rc = SQLITE4_OK;

  switch( p->ePragma ){
    case KVLSM_LSM_FLUSH:
      if( nArg!=0 ) goto wrong_num_args;
      rc = lsm_flush(p->pDb);
      break;

    case KVLSM_LSM_WORK:
      if( nArg!=2 ){
        goto wrong_num_args;
      }else{
        int nMerge = sqlite4_value_int(apArg[0]);
        int nWrite = sqlite4_value_int(apArg[1]);
        rc = lsm_work(p->pDb, nMerge, nWrite, &nWrite);
        sqlite4_result_int(ctx, nWrite);
      }
      break;

    case KVLSM_LSM_CHECKPOINT: {
      int nKB;
      if( nArg!=0 ) goto wrong_num_args;
      rc = lsm_checkpoint(p->pDb, &nKB);
      sqlite4_result_int(ctx, nKB);
      break;
    }
  }

  if( rc!=SQLITE4_OK ){
    sqlite4_result_error_code(ctx, rc);
  }
  return;

 wrong_num_args:
  sqlite4_result_error(ctx, "wrong number of arguments", -1);
}

static int kvlsmGetMethod(
  sqlite4_kvstore *pKVStore, 
  const char *zMethod, 
  void **ppArg,
  void (**pxFunc)(sqlite4_context *, int, sqlite4_value **),
  void (**pxDestroy)(void *)
){
  KVLsm *pLsm = (KVLsm *)pKVStore;
  PragmaCtx *p;
  int ePragma = 0;

  if( 0==sqlite4_strnicmp(zMethod, "lsm_flush", 9) ){
    ePragma = KVLSM_LSM_FLUSH;
  }
  else if( 0==sqlite4_strnicmp(zMethod, "lsm_work", 8) ){
    ePragma = KVLSM_LSM_WORK;
  }
  else if( 0==sqlite4_strnicmp(zMethod, "lsm_checkpoint", 14) ){
    ePragma = KVLSM_LSM_CHECKPOINT;
  }else{
    return SQLITE4_NOTFOUND;
  }

  p = sqlite4_malloc(0, sizeof(PragmaCtx));
  if( p==0 ) return SQLITE4_NOMEM;
  p->ePragma = ePragma;
  p->pDb = pLsm->pDb;

  *ppArg = (void *)p;
  *pxFunc = kvlsmPragma;
  *pxDestroy = kvlsmPragmaDestroy;
  return SQLITE4_OK;
}

/*
** Create a new in-memory storage engine and return a pointer to it.
*/
SQLITE4_PRIVATE int sqlite4KVStoreOpenLsm(
  sqlite4_env *pEnv,          /* Run-time environment */
  KVStore **ppKVStore,        /* OUT: write the new KVStore here */
  const char *zName,          /* Name of the file to open */
  unsigned openFlags          /* Flags */
){

  /* Virtual methods for an LSM data store */
  static const KVStoreMethods kvlsmMethods = {
    1,                            /* iVersion */
    sizeof(KVStoreMethods),       /* szSelf */
    kvlsmReplace,                 /* xReplace */
    kvlsmOpenCursor,              /* xOpenCursor */
    kvlsmSeek,                    /* xSeek */
    kvlsmNextEntry,               /* xNext */
    kvlsmPrevEntry,               /* xPrev */
    kvlsmDelete,                  /* xDelete */
    kvlsmKey,                     /* xKey */
    kvlsmData,                    /* xData */
    kvlsmReset,                   /* xReset */
    kvlsmCloseCursor,             /* xCloseCursor */
    kvlsmBegin,                   /* xBegin */
    kvlsmCommitPhaseOne,          /* xCommitPhaseOne */
    kvlsmCommitPhaseTwo,          /* xCommitPhaseTwo */
    kvlsmRollback,                /* xRollback */
    kvlsmRevert,                  /* xRevert */
    kvlsmClose,                   /* xClose */
    kvlsmControl,                 /* xControl */
    kvlsmGetMeta,                 /* xGetMeta */
    kvlsmPutMeta,                 /* xPutMeta */
    kvlsmGetMethod                /* xGetMethod */
  };

  KVLsm *pNew;
  int rc = SQLITE4_OK;

  pNew = (KVLsm *)sqlite4_malloc(pEnv, sizeof(KVLsm));
  if( pNew==0 ){
    rc = SQLITE4_NOMEM;
  }else{
    struct Config {
      const char *zParam;
      int eParam;
    } aConfig[] = {
      { "lsm_mmap", LSM_CONFIG_MMAP },
      { "lsm_page_size", LSM_CONFIG_PAGE_SIZE },
      { "lsm_block_size", LSM_CONFIG_BLOCK_SIZE },
      { "lsm_multiple_processes", LSM_CONFIG_MULTIPLE_PROCESSES },
      { "lsm_automerge", LSM_CONFIG_AUTOMERGE }
    };

    memset(pNew, 0, sizeof(KVLsm));
    pNew->base.pStoreVfunc = &kvlsmMethods;
    pNew->base.pEnv = pEnv;
    rc = lsm_new(0, &pNew->pDb);
    if( rc==SQLITE4_OK ){
      int i;
      for(i=0; i<ArraySize(aConfig); i++){
        const char *zVal = sqlite4_uri_parameter(zName, aConfig[i].zParam);
        if( zVal ){
          int nVal = sqlite4Atoi(zVal);
          lsm_config(pNew->pDb, aConfig[i].eParam, &nVal);
        }
      }

      rc = lsm_open(pNew->pDb, zName);
    }

    if( rc!=SQLITE4_OK ){
      lsm_close(pNew->pDb);
      sqlite4_free(pEnv, pNew);
      pNew = 0;
    }
  }

  *ppKVStore = (KVStore*)pNew;
  return rc;
}

/************** End of kvlsm.c ***********************************************/
/************** Begin file rowset.c ******************************************/
/*
** 2008 December 3
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This module implements an object called a "RowSet".
**
** The RowSet object is a collection of database keys.  Keys
** are inserted into the RowSet in an arbitrary order.  Inserts
** can be intermixed with tests to see if a given key is present
** in the RowSet.
**
** After all inserts are finished, it is possible to extract the
** elements of the RowSet in sorted order.  Once this extraction
** process has started, no new elements may be inserted.
**
** Hence, the primitive operations for a RowSet are:
**
**    CREATE
**    INSERT
**    TEST
**    SMALLEST
**    DESTROY
**
** The CREATE and DESTROY primitives are the constructor and destructor,
** obviously.  The INSERT primitive adds a new element to the RowSet.
** TEST checks to see if an element is already in the RowSet.  SMALLEST
** extracts the least value from the RowSet.
**
** The INSERT primitive might allocate additional memory.  Memory is
** allocated in chunks so most INSERTs do no allocation.  There is an 
** upper bound on the size of allocated memory.  No memory is freed
** until DESTROY.
**
** The TEST primitive includes a "batch" number.  The TEST primitive
** will only see elements that were inserted before the last change
** in the batch number.  In other words, if an INSERT occurs between
** two TESTs where the TESTs have the same batch nubmer, then the
** value added by the INSERT will not be visible to the second TEST.
** The initial batch number is zero, so if the very first TEST contains
** a non-zero batch number, it will see all prior INSERTs.
**
** No INSERTs may occurs after a SMALLEST.  An assertion will fail if
** that is attempted.
**
** The cost of an INSERT is roughly constant.  (Sometime new memory
** has to be allocated on an INSERT.)  The cost of a TEST with a new
** batch number is O(NlogN) where N is the number of elements in the RowSet.
** The cost of a TEST using the same batch number is O(logN).  The cost
** of the first SMALLEST is O(NlogN).  Second and subsequent SMALLEST
** primitives are constant time.  The cost of DESTROY is O(N).
** There is an added cost of O(N) when switching between TEST and
** SMALLEST primitives.
*/

typedef struct RowSetEntry RowSetEntry;
typedef struct RowSetChunk RowSetChunk;

/*
** Target size for allocation chunks.
*/

/*
** Total size of allocation chunks, and the number of bytes of usable 
** space per chunk.
*/
#define ROWSET_ALLOCATION_SIZE 1024
#define ROWSET_BYTES_PER_CHUNK (ROWSET_ALLOCATION_SIZE - sizeof(RowSetChunk))

/*
** Each entry in a RowSet is an instance of the following object.
*/
struct RowSetEntry {            
  struct RowSetEntry *pRight;     /* Right subtree (larger entries) or list */
  struct RowSetEntry *pLeft;      /* Left subtree (smaller entries) */
  int nKey;                       /* Number of bytes in buffer aKey[] */
  u8 aKey[0];                     /* Buffer containing nKey byte key */
};

/*
** RowSetEntry objects are allocated in large chunks (instances of the
** following structure) to reduce memory allocation overhead.  The
** chunks are kept on a linked list so that they can be deallocated
** when the RowSet is destroyed.
*/
struct RowSetChunk {
  struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */
};

/*
** A RowSet in an instance of the following structure.
**
** A typedef of this structure if found in sqliteInt.h.
*/
struct RowSet {
  struct RowSetChunk *pChunk;    /* List of all chunk allocations */
  sqlite4 *db;                   /* The database connection */
  struct RowSetEntry *pEntry;    /* List of entries using pRight */
  struct RowSetEntry *pLast;     /* Last entry on the pEntry list */
  struct RowSetEntry *pTree;     /* Binary tree of entries */
  u8 *aSpace;                    /* Space for new entries */
  u16 nSpace;                    /* Number of bytes in buffer aSpace */
  u8 isSorted;                   /* True if pEntry is sorted */
  u8 iBatch;                     /* Current insert batch */
};

/*
** Turn bulk memory into a RowSet object.  N bytes of memory
** are available at pSpace.  The db pointer is used as a memory context
** for any subsequent allocations that need to occur.
** Return a pointer to the new RowSet object.
**
** It must be the case that N is sufficient to make a Rowset.  If not
** an assertion fault occurs.
** 
** If N is larger than the minimum, use the surplus as an initial
** allocation of entries available to be filled.
*/
SQLITE4_PRIVATE RowSet *sqlite4RowSetInit(sqlite4 *db, void *pSpace, unsigned int N){
  RowSet *p;
  assert( N >= ROUND8(sizeof(*p)) );
  p = pSpace;
  p->pChunk = 0;
  p->db = db;
  p->pEntry = 0;
  p->pLast = 0;
  p->pTree = 0;
  p->aSpace = 0;
  p->nSpace = 0;
  p->isSorted = 1;
  p->iBatch = 0;
  return p;
}

/*
** Deallocate all chunks from a RowSet.  This frees all memory that
** the RowSet has allocated over its lifetime.  This routine is
** the destructor for the RowSet.
*/
SQLITE4_PRIVATE void sqlite4RowSetClear(RowSet *p){
  struct RowSetChunk *pChunk, *pNextChunk;
  for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
    pNextChunk = pChunk->pNextChunk;
    sqlite4DbFree(p->db, pChunk);
  }
  memset(p, 0, sizeof(RowSet));
  p->isSorted = 1;
}


static u8 *rowsetAllocateChunk(RowSet *p, int nByte){
  int rowChunkSize = ROUND8(sizeof(RowSetChunk));
  RowSetChunk *pNew;              /* New RowSetChunk */
  int nAlloc;                     /* Bytes to request from malloc() */
  nAlloc =  rowChunkSize + nByte;
  pNew = (RowSetChunk *)sqlite4DbMallocRaw(p->db, nAlloc);
  if( !pNew ) return 0;
  pNew->pNextChunk = p->pChunk;
  p->pChunk = pNew;
  return (u8 *)(&pNew[1]);
}

static int rowsetEntryKeyCmp(RowSetEntry *pLeft, const u8 *aKey, int nKey){
  int nCmp = SQLITE4_MIN(pLeft->nKey, nKey);
  int res;
  res = memcmp(pLeft->aKey, aKey, nCmp);
  return (res ? res : (pLeft->nKey - nKey));
}

static int rowsetEntryCmp(RowSetEntry *pLeft, RowSetEntry *pRight){
  return rowsetEntryKeyCmp(pLeft, pRight->aKey, pRight->nKey);
}


/*
** Insert a new database key into a RowSet.
**
** The mallocFailed flag of the database connection is set if a
** memory allocation fails.
*/
SQLITE4_PRIVATE void sqlite4RowSetInsert(RowSet *p, u8 *aKey, int nKey){
  int nByte;                   /* Space (in bytes) required by new entry */
  struct RowSetEntry *pEntry;  /* The new entry */
  struct RowSetEntry *pLast;   /* The last prior entry */
  assert( p!=0 );

  nByte = ROUND8(sizeof(RowSetEntry) + nKey);

  if( nByte>(ROWSET_BYTES_PER_CHUNK/4) ){
    /* This is quite a large key. Store it in a chunk of its own. */
    pEntry = (RowSetEntry *)rowsetAllocateChunk(p, nByte);
  }else{
    if( nByte>p->nSpace ){
      p->aSpace = rowsetAllocateChunk(p, ROWSET_BYTES_PER_CHUNK);
      p->nSpace = ROWSET_BYTES_PER_CHUNK;
    }
    pEntry = (RowSetEntry *)p->aSpace;
    p->aSpace += nByte;
    p->nSpace -= nByte;
  }
  if( pEntry==0 ) return;

  pEntry->pRight = 0;
  pEntry->pLeft = 0;
  pEntry->nKey = nKey;
  memcpy(pEntry->aKey, aKey, nKey);

  pLast = p->pLast;
  if( pLast ){
    if( p->isSorted && rowsetEntryCmp(pEntry, pLast)<0 ){
      p->isSorted = 0;
    }
    pLast->pRight = pEntry;
  }else{
    assert( p->pEntry==0 ); /* Fires if INSERT after SMALLEST */
    p->pEntry = pEntry;
  }
  p->pLast = pEntry;
}

/*
** Merge two lists of RowSetEntry objects.  Remove duplicates.
**
** The input lists are connected via pRight pointers and are 
** assumed to each already be in sorted order.
*/
static struct RowSetEntry *rowSetMerge(
  struct RowSetEntry *pA,    /* First sorted list to be merged */
  struct RowSetEntry *pB     /* Second sorted list to be merged */
){
  struct RowSetEntry head;
  struct RowSetEntry *pTail;

  pTail = &head;
  while( pA && pB ){
    int res;
    assert( pA->pRight==0 || rowsetEntryCmp(pA, pA->pRight)<=0 );
    assert( pB->pRight==0 || rowsetEntryCmp(pB, pB->pRight)<=0 );
    res = rowsetEntryCmp(pA, pB);
    if( res<0 ){
      pTail->pRight = pA;
      pA = pA->pRight;
      pTail = pTail->pRight;
    }else if( res>0 ){
      pTail->pRight = pB;
      pB = pB->pRight;
      pTail = pTail->pRight;
    }else{
      pA = pA->pRight;
    }
  }
  if( pA ){
    assert( pA->pRight==0 || rowsetEntryCmp(pA, pA->pRight)<=0 );
    pTail->pRight = pA;
  }else{
    assert( pB==0 || pB->pRight==0 || rowsetEntryCmp(pB, pB->pRight)<=0 );
    pTail->pRight = pB;
  }
  return head.pRight;
}

/*
** Sort all elements on the pEntry list of the RowSet into ascending order.
*/ 
static void rowSetSort(RowSet *p){
  unsigned int i;
  struct RowSetEntry *pEntry;
  struct RowSetEntry *aBucket[40];

  assert( p->isSorted==0 );
  memset(aBucket, 0, sizeof(aBucket));
  while( p->pEntry ){
    pEntry = p->pEntry;
    p->pEntry = pEntry->pRight;
    pEntry->pRight = 0;
    for(i=0; aBucket[i]; i++){
      pEntry = rowSetMerge(aBucket[i], pEntry);
      aBucket[i] = 0;
    }
    aBucket[i] = pEntry;
  }
  pEntry = 0;
  for(i=0; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
    pEntry = rowSetMerge(pEntry, aBucket[i]);
  }
  p->pEntry = pEntry;
  p->pLast = 0;
  p->isSorted = 1;
}


/*
** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
** Convert this tree into a linked list connected by the pRight pointers
** and return pointers to the first and last elements of the new list.
*/
static void rowSetTreeToList(
  struct RowSetEntry *pIn,         /* Root of the input tree */
  struct RowSetEntry **ppFirst,    /* Write head of the output list here */
  struct RowSetEntry **ppLast      /* Write tail of the output list here */
){
  assert( pIn!=0 );
  if( pIn->pLeft ){
    struct RowSetEntry *p;
    rowSetTreeToList(pIn->pLeft, ppFirst, &p);
    p->pRight = pIn;
  }else{
    *ppFirst = pIn;
  }
  if( pIn->pRight ){
    rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
  }else{
    *ppLast = pIn;
  }
  assert( (*ppLast)->pRight==0 );
}


/*
** Convert a sorted list of elements (connected by pRight) into a binary
** tree with depth of iDepth.  A depth of 1 means the tree contains a single
** node taken from the head of *ppList.  A depth of 2 means a tree with
** three nodes.  And so forth.
**
** Use as many entries from the input list as required and update the
** *ppList to point to the unused elements of the list.  If the input
** list contains too few elements, then construct an incomplete tree
** and leave *ppList set to NULL.
**
** Return a pointer to the root of the constructed binary tree.
*/
static struct RowSetEntry *rowSetNDeepTree(
  struct RowSetEntry **ppList,
  int iDepth
){
  struct RowSetEntry *p;         /* Root of the new tree */
  struct RowSetEntry *pLeft;     /* Left subtree */
  if( *ppList==0 ){
    return 0;
  }
  if( iDepth==1 ){
    p = *ppList;
    *ppList = p->pRight;
    p->pLeft = p->pRight = 0;
    return p;
  }
  pLeft = rowSetNDeepTree(ppList, iDepth-1);
  p = *ppList;
  if( p==0 ){
    return pLeft;
  }
  p->pLeft = pLeft;
  *ppList = p->pRight;
  p->pRight = rowSetNDeepTree(ppList, iDepth-1);
  return p;
}

/*
** Convert a sorted list of elements into a binary tree. Make the tree
** as deep as it needs to be in order to contain the entire list.
*/
static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
  int iDepth;           /* Depth of the tree so far */
  struct RowSetEntry *p;       /* Current tree root */
  struct RowSetEntry *pLeft;   /* Left subtree */

  assert( pList!=0 );
  p = pList;
  pList = p->pRight;
  p->pLeft = p->pRight = 0;
  for(iDepth=1; pList; iDepth++){
    pLeft = p;
    p = pList;
    pList = p->pRight;
    p->pLeft = pLeft;
    p->pRight = rowSetNDeepTree(&pList, iDepth);
  }
  return p;
}

/*
** Convert the list in p->pEntry into a sorted list if it is not
** sorted already.  If there is a binary tree on p->pTree, then
** convert it into a list too and merge it into the p->pEntry list.
*/
static void rowSetToList(RowSet *p){
  if( !p->isSorted ){
    rowSetSort(p);
  }
  if( p->pTree ){
    struct RowSetEntry *pHead, *pTail;
    rowSetTreeToList(p->pTree, &pHead, &pTail);
    p->pTree = 0;
    p->pEntry = rowSetMerge(p->pEntry, pHead);
  }
}

/*
** Extract the smallest element from the RowSet.
** Write the element into *pRowid.  Return 1 on success.  Return
** 0 if the RowSet is already empty.
**
** After this routine has been called, the sqlite4RowSetInsert()
** routine may not be called again.  
*/
SQLITE4_PRIVATE int sqlite4RowSetNext(RowSet *p){
  rowSetToList(p);
  assert( p->pEntry );
  p->pEntry = p->pEntry->pRight;
  return (p->pEntry!=0);
}

SQLITE4_PRIVATE const u8 *sqlite4RowSetRead(RowSet *p, int *pnKey){
  const u8 *aRet = 0;
  rowSetToList(p);
  if( p->pEntry ){
    *pnKey = p->pEntry->nKey;
    aRet = p->pEntry->aKey;
  }
  return aRet;
}

/*
** Check to see if element aKey/nKey has been inserted into the the 
** rowset as part of any insert batch prior to iBatch.  Return 1 or 0.
*/
SQLITE4_PRIVATE int sqlite4RowSetTest(RowSet *pRowSet, u8 iBatch, u8 *aKey, int nKey){
  struct RowSetEntry *p;
  if( iBatch!=pRowSet->iBatch ){
    if( pRowSet->pEntry ){
      rowSetToList(pRowSet);
      pRowSet->pTree = rowSetListToTree(pRowSet->pEntry);
      pRowSet->pEntry = 0;
      pRowSet->pLast = 0;
    }
    pRowSet->iBatch = iBatch;
  }
  p = pRowSet->pTree;
  while( p ){
    int res = rowsetEntryKeyCmp(p, aKey, nKey);
    if( res<0 ){
      p = p->pRight;
    }else if( res>0 ){
      p = p->pLeft;
    }else{
      return 1;
    }
  }
  return 0;
}

/************** End of rowset.c **********************************************/
/************** Begin file kvbt.c ********************************************/
/*
** 2013 September 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** A b-tree key/value storage subsystem that presents the interfadce
** defined by kv.h
*/

/************** Include bt.h in the middle of kvbt.c *************************/
/************** Begin file bt.h **********************************************/
/*
** 2013 September 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
*/

#ifndef __BT_H
#define __BT_H


typedef struct bt_db bt_db;
typedef struct bt_cursor bt_cursor;

/* 
** Values that may be passed as the 4th parameter to BtCsrSeek() 
*/
#define BT_SEEK_LEFAST   -2
#define BT_SEEK_LE       -1
#define BT_SEEK_EQ        0
#define BT_SEEK_GE        1

/*
** Open and close a database connection.
*/
SQLITE4_PRIVATE int sqlite4BtNew(sqlite4_env*, int nExtra, bt_db **ppDb);
SQLITE4_PRIVATE int sqlite4BtClose(bt_db*);
SQLITE4_PRIVATE void *sqlite4BtExtra(bt_db*);

/*
** Attach a database connection to a database file.
*/
SQLITE4_PRIVATE int sqlite4BtOpen(bt_db*, const char *zFilename);

/*
** Begin(), Commit() and Revert() methods. These functions work in the
** same way as the corresponding sqlite4_kv_methods functions. As follows:
**
** Part of the state maintained by a database handle is the transaction
** level - a non-negative integer. If the transaction level is 0, then
** no read or write transaction is currently open. If the transaction
** level is 1, then a read-only transaction is open. If the transaction
** level is 2 or greater, then (L-1) nested write transactions are open,
** where L is the transaction level. Summary:
**
**   L==0    (no transaction is open)
**   L==1    (a read-only transaction is open)
**   L>=2    ((L-1) nested write transactions are open)
**
** If successful, all three methods set the transaction level to the value
** passed as the second argument. They differ as follows:
**
** Begin(): If (L>=iLevel), this is a no-op. Otherwise, open the read and/or
**          write transactions required to set L to iLevel.
**
** Commit(): If (L<=iLevel), this is a no-op. Otherwise, close as many
**           transactions as required to set L to iLevel. Commit any write
**           transactions closed by this action.
**
** Rollback(): If (L<=iLevel), this is a no-op. Otherwise, rollback and 
**             close as many transactions as required to set L to iLevel. 
**             Then, if iLevel is greater than or equal to 2, rollback
**             (but do not close) the innermost remaining sub-transaction.
**
**    SAVEPOINT one;              -- Begin(2)
**      SAVEPOINT two;            -- Begin(3)
**      ROLLBACK TO one;          -- Rollback(2)
**      SAVEPOINT two;            -- Begin(3)
**        SAVEPOINT three;        -- Begin(4)
**        ROLLBACK TO three;      -- Rollback(5)
**        RELEASE three;          -- Commit(3)
**    RELEASE one;                -- Commit(1)
**
** The TransactionLevel() method returns the current transaction level.
*/
SQLITE4_PRIVATE int sqlite4BtBegin(bt_db*, int iLevel);
SQLITE4_PRIVATE int sqlite4BtCommit(bt_db*, int iLevel);
SQLITE4_PRIVATE int sqlite4BtRollback(bt_db*, int iLevel);
SQLITE4_PRIVATE int sqlite4BtTransactionLevel(bt_db*);

/*
** Open and close a database cursor.
*/
SQLITE4_PRIVATE int sqlite4BtCsrOpen(bt_db*, int nExtra, bt_cursor **ppCsr);
SQLITE4_PRIVATE int sqlite4BtCsrClose(bt_cursor *pCsr);
SQLITE4_PRIVATE void *sqlite4BtCsrExtra(bt_cursor *pCsr);

/*
** Return values:
**
**   SQLITE4_OK:
**   SQLITE4_NOTFOUND:
**   SQLITE4_INEXACT:
**   other:
*/
SQLITE4_PRIVATE int sqlite4BtCsrSeek(bt_cursor *pCsr, const void *pK, int nK, int eSeek);

SQLITE4_PRIVATE int sqlite4BtCsrFirst(bt_cursor *pCsr);
SQLITE4_PRIVATE int sqlite4BtCsrLast(bt_cursor *pCsr);

SQLITE4_PRIVATE int sqlite4BtCsrNext(bt_cursor *pCsr);
SQLITE4_PRIVATE int sqlite4BtCsrPrev(bt_cursor *pCsr);

SQLITE4_PRIVATE int sqlite4BtCsrKey(bt_cursor *pCsr, const void **ppK, int *pnK);
SQLITE4_PRIVATE int sqlite4BtCsrData(bt_cursor *pCsr, int, int, const void **ppV, int *pnV);

SQLITE4_PRIVATE int sqlite4BtReplace(bt_db*, const void *pK, int nK, const void *pV, int nV);
SQLITE4_PRIVATE int sqlite4BtDelete(bt_cursor*);

SQLITE4_PRIVATE int sqlite4BtSetCookie(bt_db*, unsigned int iVal);
SQLITE4_PRIVATE int sqlite4BtGetCookie(bt_db*, unsigned int *piVal);


/*
** kvstore xControl() method.
**
** BT_CONTROL_INFO:
**   If the second argument to sqlite4BtControl() is BT_CONTROL_INFO, then
**   the third is expected to be a pointer to an instance of type bt_info.
**   The "output" buffer must already be initialized. Before 
**   sqlite4BtControl() returns it appends debugging information to the
**   buffer. The specific information appended depends on the eType and
**   pgno member variables.
**
** BT_CONTROL_SETVFS:
**   The third argument is assumed to be a pointer to an instance of type
**   bt_env. The database handle takes a copy of this pointer (not a copy 
**   of the object) and uses it for all subsequent IO. It is the 
**   responsibility of the caller to ensure that the pointer is valid for
**   the lifetime of the database connection.
**
** BT_CONTROL_GETVFS:
**   The third argument is assumed to be of type (bt_env**). Before 
**   returning, the value pointed to is populated with a pointer to 
**   to the current bt_env object.
**
** BT_CONTROL_SAFETY:
**   The third argument is interpreted as a pointer to type (int). If
**   the value stored in the (int) location is 0, 1 or 2, then the current
**   b-tree safety level is set to 0, 1 or 2, respectively. Otherwise, the
**   integer value is set to the current safety level.
**
** BT_CONTROL_AUTOCKPT:
**   The third argument is interpreted as a pointer to type (int). If
**   the indicated value is greater than or equal to zero, then the 
**   database connection auto-checkpoint value is set accordingly. If
**   the indicated value is less than zero, it is set to the current
**   auto-checkpoint value before returning.
**
** BT_CONTROL_LOGSIZE:
**   The third argument is interpreted as a pointer to type (int). The
**   value pointer to is set to the number of uncheckpointed frames
**   that stored in the log file according to the snapshot used by the
**   most recently completed transaction or checkpoint operation.
**
** BT_CONTROL_MULTIPROC:
**   The third argument is interpreted as a pointer to type (int).
**
** BT_CONTROL_LOGSIZECB:
**
** BT_CONTROL_CHECKPOINT:
**
** BT_CONTROL_FAST_INSERT_OP:
**   The third argument is currently unused. This file-control causes the 
**   next call to sqlite4BtReplace() or sqlite4BtCsrOpen() to write to or
**   open a cursor on the "fast-insert" tree. Subsequent operations are
**   unaffected.
**  
**   In other words, an app that uses the fast-insert tree exclusively 
**   must execute this file-control before every call to CsrOpen() or 
**   Replace().
*/
#define BT_CONTROL_INFO           7706389
#define BT_CONTROL_SETVFS         7706390
#define BT_CONTROL_GETVFS         7706391
#define BT_CONTROL_SAFETY         7706392
#define BT_CONTROL_AUTOCKPT       7706393
#define BT_CONTROL_LOGSIZE        7706394
#define BT_CONTROL_MULTIPROC      7706395
#define BT_CONTROL_LOGSIZECB      7706396
#define BT_CONTROL_CHECKPOINT     7706397
#define BT_CONTROL_FAST_INSERT_OP 7706498
#define BT_CONTROL_BLKSZ          7706499
#define BT_CONTROL_PAGESZ         7706500

SQLITE4_PRIVATE int sqlite4BtControl(bt_db*, int op, void *pArg);

#define BT_SAFETY_OFF    0
#define BT_SAFETY_NORMAL 1
#define BT_SAFETY_FULL   2

typedef struct bt_info bt_info;
struct bt_info {
  int eType;
  unsigned int pgno;
  sqlite4_buffer output;
};

#define BT_INFO_PAGEDUMP       1
#define BT_INFO_FILENAME       2
#define BT_INFO_HDRDUMP        3
#define BT_INFO_PAGEDUMP_ASCII 4
#define BT_INFO_BLOCK_FREELIST 5
#define BT_INFO_PAGE_FREELIST  6
#define BT_INFO_PAGE_LEAKS     7

typedef struct bt_logsizecb bt_logsizecb;
struct bt_logsizecb {
  void *pCtx;                     /* A copy of this is passed to xLogsize() */
  void (*xLogsize)(void*, int);   /* Callback function */
};

typedef struct bt_checkpoint bt_checkpoint;
struct bt_checkpoint {
  int nFrameBuffer;               /* Minimum number of frames to leave in log */
  int nCkpt;                      /* OUT: Number of frames checkpointed */
};

/*
** File-system interface.
*/
typedef struct bt_env bt_env;
typedef struct bt_file bt_file;

/*
** xFullpath:
*/
struct bt_env {
  void *pVfsCtx;
  int (*xFullpath)(sqlite4_env*,bt_env*, const char *, char **);
  int (*xOpen)(sqlite4_env*,bt_env*, const char *, int flags, bt_file**);
  int (*xSize)(bt_file*, sqlite4_int64*);
  int (*xRead)(bt_file*, sqlite4_int64, void *, int);
  int (*xWrite)(bt_file*, sqlite4_int64, void *, int);
  int (*xTruncate)(bt_file*, sqlite4_int64);
  int (*xSync)(bt_file*);
  int (*xSectorSize)(bt_file*);
  int (*xClose)(bt_file*);
  int (*xUnlink)(sqlite4_env*,bt_env*, const char *);
  int (*xLock)(bt_file*, int, int);
  int (*xTestLock)(bt_file*, int, int, int);
  int (*xShmMap)(bt_file*, int, int, void **);
  void (*xShmBarrier)(bt_file*);
  int (*xShmUnmap)(bt_file*, int);
};

/*
** Flags for xOpen
*/
#define BT_OPEN_DATABASE   0x0001
#define BT_OPEN_LOG        0x0002
#define BT_OPEN_SHARED     0x0004
#define BT_OPEN_READONLY   0x0008

#endif /* ifndef __BT_H */


/************** End of bt.h **************************************************/
/************** Continuing where we left off in kvbt.c ***********************/

/* Forward declarations of objects */
typedef struct KVBt KVBt;
typedef struct KVBtCsr KVBtCsr;

/*
** An instance of an open connection to a bt_db store.  A subclass of KVStore.
*/
struct KVBt {
  KVStore base;                   /* Base class, must be first */
  char *zFilename;                /* File to open */
  int bOpen;                      /* See above */
  int openrc;                     /* See above */
  bt_db *pDb;                     /* Database handle */
};

/*
** An instance of an open cursor pointing into an LSM store.  A subclass
** of KVCursor.
*/
struct KVBtCsr {
  KVCursor base;                  /* Base class. Must be first */
  bt_cursor *pCsr;                /* LSM cursor handle */
};
  
/*
** Begin a transaction or subtransaction.
*/
static int btBegin(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc;
  if( p->openrc ) return p->openrc;
  if( p->bOpen==0 ){
    p->openrc = rc = sqlite4BtOpen(p->pDb, p->zFilename);
    if( rc!=SQLITE4_OK ){
      return rc;
    }
    p->bOpen = 1;
  }
  rc = sqlite4BtBegin(p->pDb, iLevel);
  pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  return rc;
}

/*
** Commit a transaction or subtransaction.
*/
static int btCommitPhaseOne(KVStore *pKVStore, int iLevel){
  return SQLITE4_OK;
}
static int btCommitPhaseTwo(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc;
  assert( p->bOpen==1 );
  rc = sqlite4BtCommit(p->pDb, iLevel);
  pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  return rc;
}

/*
** Rollback a transaction or subtransaction.
*/
static int btRollback(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc = SQLITE4_OK;
  if( p->bOpen==1 ){
    rc = sqlite4BtRollback(p->pDb, iLevel);
    pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  }
  return rc;
}

/*
** Revert a transaction back to what it was when it started.
*/
#if 0
static int btRevert(KVStore *pKVStore, int iLevel){
  KVBt *p = (KVBt *)pKVStore;
  int rc;
  rc = sqlite4BtRevert(p->pDb, iLevel);
  pKVStore->iTransLevel = sqlite4BtTransactionLevel(p->pDb);
  return rc;
}
#endif

/*
** Implementation of the xReplace(X, aKey, nKey, aData, nData) method.
*/
static int btReplace(
  KVStore *pKVStore,
  const KVByteArray *aKey, KVSize nKey,
  const KVByteArray *aData, KVSize nData
){
  KVBt *p = (KVBt *)pKVStore;
  assert( p->bOpen==1 );
  return sqlite4BtReplace(p->pDb, aKey, nKey, aData, nData);
}

/*
** Create a new cursor object.
*/
static int btOpenCursor(KVStore *pKVStore, KVCursor **ppKVCursor){
  KVBt *p = (KVBt *)pKVStore;
  int rc = SQLITE4_OK;
  bt_cursor *pCsr;
  KVBtCsr *pBtcsr;

  assert( p->bOpen==1 );
  rc = sqlite4BtCsrOpen(p->pDb, sizeof(KVBtCsr), &pCsr);
  if( rc!=SQLITE4_OK ){
    pBtcsr = 0;
  }else{
    pBtcsr = (KVBtCsr*)sqlite4BtCsrExtra(pCsr);
    memset(pBtcsr, 0, sizeof(KVBtCsr));
    pBtcsr->base.pStore = pKVStore;
    pBtcsr->base.pStoreVfunc = pKVStore->pStoreVfunc;
    pBtcsr->pCsr = pCsr;
  }

  *ppKVCursor = (KVCursor*)pBtcsr;
  return rc;
}

/*
** Reset a cursor
*/
static int btReset(KVCursor *pKVCursor){
  return SQLITE4_OK;
}

/*
** Destroy a cursor object
*/
static int btCloseCursor(KVCursor *pKVCursor){
  KVBtCsr *pBtcsr = (KVBtCsr *)pKVCursor;
  sqlite4BtCsrClose(pBtcsr->pCsr);
  return SQLITE4_OK;
}

/*
** Move a cursor to the next non-deleted node.
*/
static int btNextEntry(KVCursor *pKVCursor){
  KVBtCsr *pBtcsr = (KVBtCsr *)pKVCursor;
  return sqlite4BtCsrNext(pBtcsr->pCsr);
}

/*
** Move a cursor to the previous non-deleted node.
*/
static int btPrevEntry(KVCursor *pKVCursor){
  KVBtCsr *pBtcsr = (KVBtCsr *)pKVCursor;
  return sqlite4BtCsrPrev(pBtcsr->pCsr);
}

/*
** Seek a cursor.
*/
static int btSeek(
  KVCursor *pKVCursor, 
  const KVByteArray *aKey,
  KVSize nKey,
  int dir
){
  KVBtCsr *pCsr = (KVBtCsr *)pKVCursor;

  assert( dir==0 || dir==1 || dir==-1 || dir==-2 );
  assert( BT_SEEK_EQ==0 && BT_SEEK_GE==1 && BT_SEEK_LE==-1 );
  assert( BT_SEEK_LEFAST==-2 );

  return sqlite4BtCsrSeek(pCsr->pCsr, (void *)aKey, nKey, dir);
}

/*
** Delete the entry that the cursor is pointing to.
**
** Though the entry is "deleted", it still continues to exist as a
** phantom.  Subsequent xNext or xPrev calls will work, as will
** calls to xKey and xData, thought the result from xKey and xData
** are undefined.
*/
static int btDelete(KVCursor *pKVCursor){
  KVBtCsr *pBtcsr = (KVBtCsr *)pKVCursor;
  return sqlite4BtDelete(pBtcsr->pCsr);
}

/*
** Return the key of the node the cursor is pointing to.
*/
static int btKey(
  KVCursor *pKVCursor,         /* The cursor whose key is desired */
  const KVByteArray **paKey,   /* Make this point to the key */
  KVSize *pN                   /* Make this point to the size of the key */
){
  KVBtCsr *pCsr = (KVBtCsr *)pKVCursor;
  return sqlite4BtCsrKey(pCsr->pCsr, (const void **)paKey, (int *)pN);
}

/*
** Return the data of the node the cursor is pointing to.
*/
static int btData(
  KVCursor *pKVCursor,         /* The cursor from which to take the data */
  KVSize ofst,                 /* Offset into the data to begin reading */
  KVSize n,                    /* Number of bytes requested */
  const KVByteArray **paData,  /* Pointer to the data written here */
  KVSize *pN                   /* Number of bytes delivered */
){
  KVBtCsr *pCsr = (KVBtCsr *)pKVCursor;
  return sqlite4BtCsrData(pCsr->pCsr, ofst, n, (const void**)paData, (int*)pN);
}

/*
** Destructor for the entire in-memory storage tree.
*/
static int btClose(KVStore *pKVStore){
  KVBt *p = (KVBt *)pKVStore;
  sqlite4_free(pKVStore->pEnv, p->zFilename);
  return sqlite4BtClose(p->pDb);
}

static int btControl(KVStore *pKVStore, int op, void *pArg){
  KVBt *p = (KVBt *)pKVStore;
  return sqlite4BtControl(p->pDb, op, pArg);
}

static int btGetMeta(KVStore *pKVStore, unsigned int *piVal){
  KVBt *p = (KVBt *)pKVStore;
  assert( p->bOpen==1 );
  return sqlite4BtGetCookie(p->pDb, piVal);
}

static int btPutMeta(KVStore *pKVStore, unsigned int iVal){
  KVBt *p = (KVBt *)pKVStore;
  assert( p->bOpen==1 );
  return sqlite4BtSetCookie(p->pDb, iVal);
}

typedef struct BtPragmaCtx BtPragmaCtx;
struct BtPragmaCtx {
  sqlite4_kvstore *pKVStore;
  int ePragma;
};

/*
** Candidate values for BtPragmaCtx.ePragma
*/
#define BTPRAGMA_PAGESZ     1
#define BTPRAGMA_CHECKPOINT 2

static void btPragmaDestroy(void *pArg){
  BtPragmaCtx *p = (BtPragmaCtx*)pArg;
  sqlite4_free(p->pKVStore->pEnv, p);
}

static void btPragma(
  sqlite4_context *pCtx, 
  int nVal,
  sqlite4_value **apVal
){
  int rc = SQLITE4_OK;            /* Return code */
  BtPragmaCtx *p = (BtPragmaCtx*)sqlite4_context_appdata(pCtx);
  bt_db *db = ((KVBt*)(p->pKVStore))->pDb;

  switch( p->ePragma ){
    case BTPRAGMA_PAGESZ: {
      int pgsz = -1;
      if( nVal>0 ){
        pgsz = sqlite4_value_int(apVal[0]);
      }
      sqlite4BtControl(db, BT_CONTROL_PAGESZ, (void*)&pgsz);
      sqlite4_result_int(pCtx, pgsz);
      break;
    }

    case BTPRAGMA_CHECKPOINT: {
      bt_checkpoint ckpt;
      ckpt.nFrameBuffer = 0;
      ckpt.nCkpt = 0;
      rc = sqlite4BtControl(db, BT_CONTROL_CHECKPOINT, (void*)&ckpt);
      if( rc!=SQLITE4_OK ){
        sqlite4_result_error_code(pCtx, rc);
      }else{
        sqlite4_result_int(pCtx, ckpt.nCkpt);
      }
      break;
    }

    default:
      assert( 0 );
  }
}


static int btGetMethod(
  sqlite4_kvstore *pKVStore, 
  const char *zMethod, 
  void **ppArg,
  void (**pxFunc)(sqlite4_context *, int, sqlite4_value **),
  void (**pxDestroy)(void*)
){
  struct PragmaMethod {
    const char *zPragma;
    int ePragma;
  } aPragma[] = {
    { "page_size", BTPRAGMA_PAGESZ },
    { "checkpoint", BTPRAGMA_CHECKPOINT },
  };
  int i;
  for(i=0; i<ArraySize(aPragma); i++){
    if( sqlite4_stricmp(aPragma[i].zPragma, zMethod)==0 ){
      BtPragmaCtx *pCtx = sqlite4_malloc(pKVStore->pEnv, sizeof(BtPragmaCtx));
      if( pCtx==0 ) return SQLITE4_NOMEM;
      pCtx->ePragma = aPragma[i].ePragma;
      pCtx->pKVStore = pKVStore;
      *ppArg = (void*)pCtx;
      *pxFunc = btPragma;
      *pxDestroy = btPragmaDestroy;
      return SQLITE4_OK;
    }
  }
  return SQLITE4_NOTFOUND;
}

SQLITE4_PRIVATE int sqlite4OpenBtree(
  sqlite4_env *pEnv,              /* The environment to use */
  sqlite4_kvstore **ppKVStore,    /* OUT: New KV store returned here */
  const char *zFilename,          /* Name of database file to open */
  unsigned flags                  /* Bit flags */
){
  static const sqlite4_kv_methods bt_methods = {
    1,                            /* iVersion */
    sizeof(sqlite4_kv_methods),   /* szSelf */
    btReplace,                    /* xReplace */
    btOpenCursor,                 /* xOpenCursor */
    btSeek,                       /* xSeek */
    btNextEntry,                  /* xNext */
    btPrevEntry,                  /* xPrev */
    btDelete,                     /* xDelete */
    btKey,                        /* xKey */
    btData,                       /* xData */
    btReset,                      /* xReset */
    btCloseCursor,                /* xCloseCursor */
    btBegin,                      /* xBegin */
    btCommitPhaseOne,             /* xCommitPhaseOne */
    btCommitPhaseTwo,             /* xCommitPhaseTwo */
    btRollback,                   /* xRollback */
    0,                            /* xRevert */
    btClose,                      /* xClose */
    btControl,                    /* xControl */
    btGetMeta,                    /* xGetMeta */
    btPutMeta,                    /* xPutMeta */
    btGetMethod                   /* xGetMethod */
  };

  KVBt *pNew = 0;
  bt_db *pDb = 0;
  int rc;

  rc = sqlite4BtNew(pEnv, sizeof(KVBt), &pDb);
  if( rc==SQLITE4_OK ){
    bt_env *pBtenv = 0;
    pNew = (KVBt*)sqlite4BtExtra(pDb);
    pNew->base.pStoreVfunc = &bt_methods;
    pNew->base.pEnv = pEnv;
    pNew->pDb = pDb;
    sqlite4BtControl(pDb, BT_CONTROL_GETVFS, (void*)&pBtenv);
    rc = pBtenv->xFullpath(pEnv, pBtenv, zFilename, &pNew->zFilename);
  }

  if( rc!=SQLITE4_OK && pDb ){
    sqlite4BtClose(pDb);
    pNew = 0;
  }
  *ppKVStore = pNew;
  return rc;
}


/************** End of kvbt.c ************************************************/
/************** Begin file bt_lock.c *****************************************/
/*
** 2013 October 18
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/


/************** Include btInt.h in the middle of bt_lock.c *******************/
/************** Begin file btInt.h *******************************************/
/*
** 2013 September 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
*/


/* #define BT_STDERR_DEBUG 1 */

typedef sqlite4_int64 i64;
typedef sqlite4_uint64 u64;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;

typedef struct BtDbHdr BtDbHdr;

/* 
** Special error codes used internally. These must be distinct from SQLite4
** error codes. Which is easy - SQLite4 error codes are all greater than or
** equal to zero.
*/
#define BT_BLOCKFULL -1


/* Number of elements in an array object. */
#define array_size(x) (sizeof(x)/sizeof(x[0]))

/* Number of read-lock slots in shared memory */
#define BT_NREADER 4

#ifndef MIN
# define MIN(a,b) (((a)<(b))?(a):(b))
#endif
#ifndef MAX
# define MAX(a,b) (((a)>(b))?(a):(b))
#endif

/* By default pages are 1024 bytes in size. */
#define BT_DEFAULT_PGSZ 1024

/* By default blocks are 512K bytes in size. */
#define BT_DEFAULT_BLKSZ (512*1024)

/* Default cache size in pages */
#define BT_DEFAULT_CACHESZ 1000

/*
** This structure is the in-memory representation of all data stored in
** the database header at the start of the db file.
**
** pgsz, blksz:
**   Byte offset 0 of the database file is the first byte of both page 1
**   and block 1. Each page is pHdr->pgsz bytes in size. Each block is
**   pHdr->blksz bytes in size. It is guaranteed that the block-size is
**   an integer multiple of the page-size.
**
** iSubBlock, nSubPg:
**   These are likely a stop-gap. When a user executes a 'fast-insert' write,
**   the new key-value pair (or delete marker) is written into a b-tree 
**   stored within block iSubBlock. The root of the tree is always the first
**   page in the block. 
**
**   Variable nSubPg contains the number of pages currently used by the
**   sub-tree, not including any overflow pages. Pages (except overflow 
**   pages) are always allocated contiguously within the block.
**
**   The reason these are likely a stop-gap is that the write-magnification
**   caused by using a b-tree for to populate level-0 sub-trees is too 
**   expensive.
*/
#define BT_DBHDR_STRING "SQLite4 bt database 0001"
struct BtDbHdr {
  char azStr[24];                 /* Copy of BT_DBHDR_STRING */
  u32 pgsz;                       /* Page size in bytes */
  u32 blksz;                      /* Block size in bytes */
  u32 nPg;                        /* Size of database file in pages */

  u32 iRoot;                      /* B-tree root page */
  u32 iMRoot;                     /* Root page of meta-tree */
  u32 iSRoot;                     /* Root page of schedule-tree */

  u32 iSubBlock;                  /* Block containing current sub-tree */
  u32 nSubPg;                     /* Number of non-overflow pages in sub-tree */

  u32 iCookie;                    /* Current value of schema cookie */
  u32 iFreePg;                    /* First page in free-page list trunk */
  u32 iFreeBlk;                   /* First page in free-block list trunk */
};


/*
** This struct defines the format of database "schedule" pages.
**
** eBusy:
*/
typedef struct BtSchedule BtSchedule;
struct BtSchedule {
  u32 eBusy;                      /* One of the BT_SCHEDULE_XXX constants */
  u32 iAge;                       /* Age of input segments */
  u32 iMinLevel;                  /* Minimum level of input segments */
  u32 iMaxLevel;                  /* Maximum level of input segments */
  u32 iOutLevel;                  /* Level at which to write output */
  u32 aBlock[32];                 /* Allocated blocks */

  u32 iNextPg;                    /* Page that contains next input key */
  u32 iNextCell;                  /* Cell that contains next input key */
  u32 iFreeList;                  /* First page of new free-list (if any) */
  u32 aRoot[32];                  /* Root pages for populated blocks */
};

#define BT_SCHEDULE_EMPTY 0
#define BT_SCHEDULE_BUSY  1
#define BT_SCHEDULE_DONE  2

SQLITE4_PRIVATE int sqlite4BtMerge(bt_db *db, BtDbHdr *pHdr, u8 *aSched);

/*************************************************************************
** Interface to bt_pager.c functionality.
*/
typedef struct BtPage BtPage;
typedef struct BtPager BtPager;

/*
** Open and close a pager database connection.
*/
SQLITE4_PRIVATE int sqlite4BtPagerNew(sqlite4_env*, int nExtra, BtPager **pp);
SQLITE4_PRIVATE int sqlite4BtPagerClose(BtPager*);
SQLITE4_PRIVATE void *sqlite4BtPagerExtra(BtPager*);

/*
** Attach a database file to a pager object.
*/
SQLITE4_PRIVATE int sqlite4BtPagerOpen(BtPager*, const char *zFilename);

/*
** Transactions. These methods are more or less the same as their 
** counterparts in bt.h.
*/
SQLITE4_PRIVATE int sqlite4BtPagerBegin(BtPager*, int iLevel);
SQLITE4_PRIVATE int sqlite4BtPagerCommit(BtPager*, int iLevel);
SQLITE4_PRIVATE int sqlite4BtPagerRevert(BtPager*, int iLevel);
SQLITE4_PRIVATE int sqlite4BtPagerRollback(BtPager*, int iLevel);
SQLITE4_PRIVATE int sqlite4BtPagerTransactionLevel(BtPager*);

/*
** Query for the database page size. Requires an open read transaction.
*/
SQLITE4_PRIVATE int sqlite4BtPagerPagesize(BtPager*);

/* 
** Query for the db header values. Requires an open read transaction or
** an active checkpoint.
*/
SQLITE4_PRIVATE BtDbHdr *sqlite4BtPagerDbhdr(BtPager*);
SQLITE4_PRIVATE void sqlite4BtPagerDbhdrDirty(BtPager*);

/*
** Used by checkpointers to specify the header to use during a checkpoint.
*/
SQLITE4_PRIVATE void sqlite4BtPagerSetDbhdr(BtPager *, BtDbHdr *);

/*
** Read, write and trim existing database pages.
*/
SQLITE4_PRIVATE int sqlite4BtPageGet(BtPager*, u32 pgno, BtPage **ppPage);
SQLITE4_PRIVATE int sqlite4BtPageTrimPgno(BtPager*, u32 pgno);
SQLITE4_PRIVATE int sqlite4BtPageWrite(BtPage*);
SQLITE4_PRIVATE int sqlite4BtPageTrim(BtPage*);
SQLITE4_PRIVATE int sqlite4BtPageRelease(BtPage*);
SQLITE4_PRIVATE void sqlite4BtPageReference(BtPage*);

/*
** Allocate new database pages or blocks.
*/
SQLITE4_PRIVATE int sqlite4BtPageAllocate(BtPager*, BtPage **ppPage);
SQLITE4_PRIVATE int sqlite4BtBlockAllocate(BtPager*, int nBlk, u32 *piBlk);

/* Block trim */
SQLITE4_PRIVATE int sqlite4BtBlockTrim(BtPager*, u32);

/*
** Query page references.
*/
SQLITE4_PRIVATE u32 sqlite4BtPagePgno(BtPage*);
SQLITE4_PRIVATE void *sqlite4BtPageData(BtPage*);

/*
** Debugging only. Return number of outstanding page references.
*/
SQLITE4_PRIVATE int sqlite4BtPagerRefcount(BtPager*);

/* 
** Read/write the schema cookie value.
*/
SQLITE4_PRIVATE int sqlite4BtPagerSetCookie(BtPager*, u32 iVal);
SQLITE4_PRIVATE int sqlite4BtPagerGetCookie(BtPager*, u32 *piVal);

/*
** Return a pointer to a buffer containing the name of the pager log file.
*/
#define BT_PAGERFILE_DATABASE 0
#define BT_PAGERFILE_LOG      1
#define BT_PAGERFILE_SHM      2
SQLITE4_PRIVATE const char *sqlite4BtPagerFilename(BtPager*, int ePagerfile);

SQLITE4_PRIVATE bt_env *sqlite4BtPagerGetEnv(BtPager*);
SQLITE4_PRIVATE void sqlite4BtPagerSetEnv(BtPager*, bt_env*);

SQLITE4_PRIVATE void sqlite4BtPagerSetSafety(BtPager*, int*);
SQLITE4_PRIVATE void sqlite4BtPagerSetAutockpt(BtPager*, int*);

SQLITE4_PRIVATE void sqlite4BtPagerLogsize(BtPager*, int*);
SQLITE4_PRIVATE void sqlite4BtPagerMultiproc(BtPager *pPager, int *piVal);
SQLITE4_PRIVATE void sqlite4BtPagerLogsizeCb(BtPager *pPager, bt_logsizecb*);
SQLITE4_PRIVATE int sqlite4BtPagerCheckpoint(BtPager *pPager, bt_checkpoint*);

SQLITE4_PRIVATE int sqlite4BtPagerHdrdump(BtPager *pPager, sqlite4_buffer *pBuf);

/*
** Write a page buffer directly to the database file.
*/
SQLITE4_PRIVATE int sqlite4BtPagerRawWrite(BtPager *pPager, u32 pgno, u8 *aBuf);

/*
** End of bt_pager.c interface.
*************************************************************************/

/*************************************************************************
** File-system interface.
*/

/* Candidate values for the 3rd argument to bt_env.xLock() */
#define BT_LOCK_UNLOCK 0
#define BT_LOCK_SHARED 1
#define BT_LOCK_EXCL   2

/* Size of shared-memory chunks - 48KB. */
#define BT_SHM_CHUNK_SIZE (48*1024)

/* Find the default VFS */
SQLITE4_PRIVATE bt_env *sqlite4BtEnvDefault(void);

/*
** End of file system interface.
*************************************************************************/

/*************************************************************************
** Interface to bt_varint.c functionality.
**
** All this is just copied from SQLite4 proper. It is a bit ridiculous.
*/
SQLITE4_PRIVATE int sqlite4BtVarintPut32(u8 *, int);
SQLITE4_PRIVATE int sqlite4BtVarintGet32(u8 *, int *);
SQLITE4_PRIVATE int sqlite4BtVarintPut64(u8 *aData, i64 iVal);
SQLITE4_PRIVATE int sqlite4BtVarintGet64(const u8 *aData, i64 *piVal);
SQLITE4_PRIVATE int sqlite4BtVarintLen32(int);
SQLITE4_PRIVATE int sqlite4BtVarintSize(u8 c);
/*
** End of bt_varint.c interface.
*************************************************************************/

/*************************************************************************
** Interface to bt_log.c functionality.
*/
typedef struct BtLog BtLog;
SQLITE4_PRIVATE int sqlite4BtLogOpen(BtPager*, int bRecover, BtLog**);
SQLITE4_PRIVATE int sqlite4BtLogClose(BtLog*, int bCleanup);

SQLITE4_PRIVATE int sqlite4BtLogRead(BtLog*, u32 pgno, u8 *aData);
SQLITE4_PRIVATE int sqlite4BtLogWrite(BtLog*, u32 pgno, u8 *aData, u32 nPg);

SQLITE4_PRIVATE int sqlite4BtLogSnapshotOpen(BtLog*);
SQLITE4_PRIVATE int sqlite4BtLogSnapshotClose(BtLog*);

SQLITE4_PRIVATE int sqlite4BtLogSnapshotWrite(BtLog*);
SQLITE4_PRIVATE int sqlite4BtLogSnapshotEndWrite(BtLog*);

SQLITE4_PRIVATE int sqlite4BtLogSize(BtLog*);
SQLITE4_PRIVATE int sqlite4BtLogCheckpoint(BtLog*, int);

SQLITE4_PRIVATE int sqlite4BtLogFrameToIdx(u32 *aLog, u32 iFrame);

#if 0
SQLITE4_PRIVATE int sqlite4BtLogPagesize(BtLog*);
SQLITE4_PRIVATE int sqlite4BtLogPagecount(BtLog*);
SQLITE4_PRIVATE u32 sqlite4BtLogCookie(BtLog*);
#endif
SQLITE4_PRIVATE BtDbHdr *sqlite4BtLogDbhdr(BtLog*);

SQLITE4_PRIVATE int sqlite4BtLogSetCookie(BtLog*, u32 iCookie);
SQLITE4_PRIVATE int sqlite4BtLogDbhdrFlush(BtLog*);
SQLITE4_PRIVATE void sqlite4BtLogReloadDbHdr(BtLog*);

/*
** End of bt_log.c interface.
*************************************************************************/

/*************************************************************************
** Interface to bt_lock.c functionality.
*/
typedef struct BtShared BtShared;
typedef struct BtLock BtLock;
typedef struct BtReadSlot BtReadSlot;
typedef struct BtFile BtFile;

struct BtLock {
  /* These three are set by the bt_pager module and thereafter used by 
  ** the bt_lock, bt_pager and bt_log modules. */
  sqlite4_env *pEnv;              /* SQLite environment */
  bt_env *pVfs;                   /* Bt environment */
  bt_file *pFd;                   /* Database file descriptor */
  int iDebugId;                   /* Sometimes useful when debugging */

  /* Global configuration settings:
  **
  ** nAutoCkpt:
  **   If a transaction is committed and there are this many frames in the
  **   log file, automatically run a checkpoint operation.
  **
  ** iSafetyLevel:
  **   Current safety level. 0==off, 1==normal, 2=full.
  */
  int iSafetyLevel;               /* 0==OFF, 1==NORMAL, 2==FULL */
  int nAutoCkpt;                  /* Auto-checkpoint when log is this large */
  int bRequestMultiProc;          /* Request multi-proc support */
  int nBlksz;                     /* Requested block-size in bytes */
  int nPgsz;                      /* Requested page-size in bytes */

  /* These are used only by the bt_lock module. */
  BtShared *pShared;              /* Shared by all handles on this file */
  BtLock *pNext;                  /* Next connection using pShared */
  u32 mExclLock;                  /* Mask of exclusive locks held */
  u32 mSharedLock;                /* Mask of shared locks held */
  BtFile *pBtFile;                /* Used to defer close if necessary */

  u8 *aUsed;
};

struct BtReadSlot {
  u32 iFirst;
  u32 iLast;
};

/* Connect and disconnect procedures */
SQLITE4_PRIVATE int sqlite4BtLockConnect(BtLock*, int (*xRecover)(BtLock*));
SQLITE4_PRIVATE int sqlite4BtLockDisconnect(BtLock*, int(*xCkpt)(BtLock*), int(*xDel)(BtLock*));

/* Obtain and release the WRITER lock */
SQLITE4_PRIVATE int sqlite4BtLockWriter(BtLock*);
SQLITE4_PRIVATE int sqlite4BtLockWriterUnlock(BtLock*);

/* Obtain and release CHECKPOINTER lock */
SQLITE4_PRIVATE int sqlite4BtLockCkpt(BtLock*);
SQLITE4_PRIVATE int sqlite4BtLockCkptUnlock(BtLock*);

/* Obtain and release READER locks.  */
SQLITE4_PRIVATE int sqlite4BtLockReader(BtLock*, u32 *aLog, u32 iFirst, BtReadSlot *aLock);
SQLITE4_PRIVATE int sqlite4BtLockReaderUnlock(BtLock*);

/* Query READER locks.  */
SQLITE4_PRIVATE int sqlite4BtLockReaderQuery(BtLock*, u32*, BtReadSlot*, u32*, int*);

/* Obtain pointers to shared-memory chunks */
SQLITE4_PRIVATE int sqlite4BtLockShmMap(BtLock*, int iChunk, int nByte, u8 **ppOut);

/*
** End of bt_lock.c interface.
*************************************************************************/

/*************************************************************************
** Utility functions.
*/
SQLITE4_PRIVATE void sqlite4BtPutU32(u8 *a, u32 i);
SQLITE4_PRIVATE u32 sqlite4BtGetU32(const u8 *a);
SQLITE4_PRIVATE void sqlite4BtBufAppendf(sqlite4_buffer *pBuf, const char *zFormat, ...);

/*
** End of utility interface.
*************************************************************************/

#ifdef NDEBUG
# define sqlite4BtDebugReadPage(a,b,c,d)
# define sqlite4BtDebugKV(a,b,c,d,e,f)
# define sqlite4BtDebugReadlock(a,b,c)
# define sqlite4BtDebugPageAlloc(a,b,c)
# define sqlite4BtDebugPageFree(a,b,c,d)
# define btErrorBkpt(x) x
#else
SQLITE4_PRIVATE void sqlite4BtDebugReadPage(BtLock *pLock, u32 pgno, u8 *aData, int pgsz);
SQLITE4_PRIVATE void sqlite4BtDebugKV(BtLock*, const char*,u8 *pK, int nK, u8 *pV, int nV);
SQLITE4_PRIVATE void sqlite4BtDebugReadlock(BtLock *pLock, u32 iFirst, u32 iLast);
SQLITE4_PRIVATE void sqlite4BtDebugPageAlloc(BtLock *pLock, const char*, u32);
SQLITE4_PRIVATE void sqlite4BtDebugPageFree(BtLock *pLock, int, const char*, u32);
int btErrorBkpt(int rc);
#endif


/************** End of btInt.h ***********************************************/
/************** Continuing where we left off in bt_lock.c ********************/

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

#define BT_LOCK_DMS1          0   /* DMS1 */
#define BT_LOCK_DMS2_RW       1   /* DMS2/rw */
#define BT_LOCK_DMS2_RO       2   /* DMS2/ro */
#define BT_LOCK_WRITER        3   /* WRITER lock */
#define BT_LOCK_CKPTER        4   /* CHECKPOINTER lock */
#define BT_LOCK_READER_DBONLY 5   /* Reading the db file only */
#define BT_LOCK_READER0       6   /* Array of BT_NREADER locks */

#define BT_LOCK_UNLOCK     0
#define BT_LOCK_SHARED     1
#define BT_LOCK_EXCL       2

/*
** Global data. All global variables used by code in this file are grouped
** into the following structure instance.
**
** pDatabase:
**   Linked list of all Database objects allocated within this process.
**   This list may not be traversed without holding the global mutex (see
**   functions enterGlobalMutex() and leaveGlobalMutex()).
**
** iDebugId:
**   Each new connection is assigned a "debug-id". This contributes 
**   nothing to the operation of the library, but sometimes makes it 
**   easier to debug various problems.
*/
static struct BtSharedData {
  BtShared *pDatabase;            /* Linked list of all Database objects */
  int iDebugId;                   /* Next free debugging id */
} gBtShared = {0, 0};

struct BtFile {
  BtFile *pNext;
  bt_file *pFd;
};

struct BtShared {
  /* Protected by the global mutex (see btLockMutexEnter()/Leave()) */
  char *zName;                    /* Canonical path to database file */
  int nName;                      /* strlen(zName) */
  int nRef;                       /* Number of handles open on this file */
  BtShared *pNext;                /* Next BtShared structure in global list */

  /* Protected by the local mutex (pClientMutex) */
  sqlite4_mutex *pClientMutex;    /* Protects the apShmChunk[] and pConn */
  int nShmChunk;                  /* Number of entries in apShmChunk[] array */
  u8 **apShmChunk;                /* Array of "shared" memory regions */
  BtLock *pLock;                  /* List of connnections to this db */

  /* Multi-process mode stuff */
  int bMultiProc;                 /* True if running in multi-process mode */
  int bReadonly;                  /* True if Database.pFile is read-only */
  bt_file *pFile;                 /* Used for locks/shm in multi-proc mode */
  BtFile *pBtFile;                /* List of deferred closes */
};

/*
** Grab the global mutex that protects the linked list of BtShared
** objects.
*/
static void btLockMutexEnter(sqlite4_env *pEnv){
  sqlite4_mutex_enter(sqlite4_mutex_alloc(pEnv, SQLITE4_MUTEX_STATIC_KV));
}

/*
** Relinquish the mutex obtained by calling btLockMutexEnter().
*/
static void btLockMutexLeave(sqlite4_env *pEnv){
  sqlite4_mutex_leave(sqlite4_mutex_alloc(pEnv, SQLITE4_MUTEX_STATIC_KV));
}

/*
** Take the specified lock on the shared file-handle associated with
** the connection passed as the first argument.
*/
static int btLockSharedFile(BtLock *p, int iLock, int eOp){
  int rc = SQLITE4_OK;
  BtShared *pShared = p->pShared;

  /* This is a no-op in single process mode */
  assert( (pShared->bMultiProc==0)==(pShared->pFile==0) );
  if( pShared->pFile ){
    rc = p->pVfs->xLock(pShared->pFile, iLock, eOp);
  }
  return rc;
}

static int btLockLockopNonblocking(
  BtLock *p,                      /* BtLock handle */
  int iLock,                      /* Slot to lock */
  int eOp                         /* One of BT_LOCK_UNLOCK, SHARED or EXCL */
){
  const u32 mask = ((u32)1 << iLock);
  int rc = SQLITE4_OK;
  BtShared *pShared = p->pShared;

  assert( iLock>=0 && iLock<(BT_LOCK_READER0 + BT_NREADER) );
  assert( (BT_LOCK_READER0+BT_NREADER)<=32 );
  assert( eOp==BT_LOCK_UNLOCK || eOp==BT_LOCK_SHARED || eOp==BT_LOCK_EXCL );

  /* Check for a no-op. Proceed only if this is not one of those. */
  if( (eOp==BT_LOCK_UNLOCK && (mask & (p->mExclLock|p->mSharedLock))!=0)
   || (eOp==BT_LOCK_SHARED && (mask & p->mSharedLock)==0)
   || (eOp==BT_LOCK_EXCL   && (mask & p->mExclLock)==0)
  ){
    BtLock *pIter;
    int nExcl = 0;                /* Number of connections holding EXCLUSIVE */
    int nShared = 0;              /* Number of connections holding SHARED */
    sqlite4_mutex_enter(pShared->pClientMutex);

    /* Figure out the locks currently held by this process on iLock, not
    ** including any held by this connection.  */
    for(pIter=pShared->pLock; pIter; pIter=pIter->pNext){
      assert( (pIter->mExclLock & pIter->mSharedLock)==0 );
      if( pIter!=p ){
        assert( (pIter->mExclLock & p->mSharedLock)==0 );
        assert( (pIter->mSharedLock & p->mExclLock)==0 );
        if( mask & pIter->mExclLock ){
          nExcl++;
        }else if( mask & pIter->mSharedLock ){
          nShared++;
        }
      }
    }
    assert( nExcl==0 || nExcl==1 );
    assert( nExcl==0 || nShared==0 );

    switch( eOp ){
      case BT_LOCK_UNLOCK:
        if( nShared==0 ){
          btLockSharedFile(p, iLock, BT_LOCK_UNLOCK);
        }
        p->mExclLock &= ~mask;
        p->mSharedLock &= ~mask;
        break;

      case BT_LOCK_SHARED:
        if( nExcl ){
          rc = SQLITE4_BUSY;
        }else{
          if( nShared==0 ){
            rc = btLockSharedFile(p, iLock, BT_LOCK_SHARED);
          }
          /* If no error occurred, set the bit in the mask of SHARED locks
          ** held. Either way, clear the bit in the mask of EXCLUSIVE locks.
          ** The idea here is that when there is any uncertainty as to whether
          ** a lock is held, the corresponding bit is cleared.  */
          if( rc==SQLITE4_OK ) p->mSharedLock |= mask;
          p->mExclLock &= ~mask;
        }
        break;

      default:
        assert( eOp==BT_LOCK_EXCL );
        if( nExcl || nShared ){
          rc = SQLITE4_BUSY;
        }else{
          rc = btLockSharedFile(p, iLock, BT_LOCK_EXCL);
          if( rc==SQLITE4_OK ){
            p->mSharedLock &= ~mask;
            p->mExclLock |= mask;
          }
        }
        break;
    }

    sqlite4_mutex_leave(pShared->pClientMutex);
  }

  return rc;
}

static void btLockDelay(void){
  usleep(10000);
#if 0
  static int nCall = 0;
  nCall++;
  fprintf(stderr, "%d delay\n", nCall);
  fflush(stderr);
#endif
}

/*
** Attempt to obtain the lock identified by the iLock and bExcl parameters.
** If successful, return SQLITE4_OK. If the lock cannot be obtained because 
** there exists some other conflicting lock, return SQLITE4_BUSY. If some 
** other error occurs, return an SQLite4 error code.
**
** Parameter iLock must be one of BT_LOCK_WRITER, WORKER or CHECKPOINTER,
** or else a value returned by the BT_LOCK_READER macro.
*/
static int btLockLockop(
  BtLock *p,                      /* BtLock handle */
  int iLock,                      /* Slot to lock */
  int eOp,                        /* One of BT_LOCK_UNLOCK, SHARED or EXCL */
  int bBlock                      /* True for a blocking lock */
){
  int rc;
  while( 1 ){
    rc = btLockLockopNonblocking(p, iLock, eOp);
    if( rc!=SQLITE4_BUSY || bBlock==0 ) break;
    /* todo: Fix blocking locks */
    btLockDelay();
  }
  return rc;
}

static void btLockSharedDeref(
  sqlite4_env *pEnv, 
  bt_env *pVfs, 
  BtShared *pShared
){
  btLockMutexEnter(pEnv);
  pShared->nRef--;
  if( pShared->nRef==0 ){
    BtShared **ppS;
    for(ppS=&gBtShared.pDatabase; *ppS!=pShared; ppS=&(*ppS)->pNext);
    *ppS = (*ppS)->pNext;
    while( pShared->pBtFile ){
      BtFile *p = pShared->pBtFile;
      pShared->pBtFile = p->pNext;
      pVfs->xClose(p->pFd);
      sqlite4_free(pEnv, p);
    }
    sqlite4_mutex_free(pShared->pClientMutex);

    /* If they were allocated in heap space, free all "shared" memory chunks */
    if( pShared->pFile==0 ){
      int i;
      for(i=0; i<pShared->nShmChunk; i++){
        sqlite4_free(pEnv, pShared->apShmChunk[i]);
      }
    }else{
      pVfs->xClose(pShared->pFile);
    }
    sqlite4_free(pEnv, pShared->apShmChunk);
    sqlite4_free(pEnv, pShared);
  }
  btLockMutexLeave(pEnv);
}

/*
** Connect to the database as a read/write connection. If recovery
** is required (i.e. if this is the first connection to the db), invoke 
** the xRecover() method.
**
** Return SQLITE4_OK if successful, or an SQLite4 error code if an
** error occurs.
*/
SQLITE4_PRIVATE int sqlite4BtLockConnect(BtLock *p, int (*xRecover)(BtLock*)){
  sqlite4_env *pEnv = p->pEnv;
  bt_env *pVfs = p->pVfs;
  int rc = SQLITE4_OK;
  const char *zName;
  int nName;
  BtShared *pShared;

  zName = sqlite4BtPagerFilename((BtPager*)p, BT_PAGERFILE_DATABASE);
  nName = strlen(zName);

  btLockMutexEnter(p->pEnv);
  p->iDebugId = gBtShared.iDebugId++;
  for(pShared=gBtShared.pDatabase; pShared; pShared=pShared->pNext){
    if( pShared->nName==nName && 0==memcmp(zName, pShared->zName, nName) ){
      break;
    }
  }

  if( pShared==0 ){
    sqlite4_mutex *pMutex;
    pShared = (BtShared*)sqlite4_malloc(pEnv, sizeof(BtShared) + nName + 1);
    pMutex = sqlite4_mutex_alloc(pEnv, SQLITE4_MUTEX_RECURSIVE);

    if( pShared==0 || pMutex==0 ){
      sqlite4_free(pEnv, pShared);
      sqlite4_mutex_free(pMutex);
      pShared = 0;
      pMutex = 0;
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }else{
      memset(pShared, 0, sizeof(BtShared));
      pShared->bMultiProc = p->bRequestMultiProc;
      pShared->nName = nName;
      pShared->zName = (char *)&pShared[1];
      memcpy(pShared->zName, zName, nName+1);
      pShared->pNext = gBtShared.pDatabase;
      pShared->pClientMutex = pMutex;
      gBtShared.pDatabase = pShared;
    }
  }
  if( rc==SQLITE4_OK ){
    pShared->nRef++;
  }
  btLockMutexLeave(p->pEnv);

  /* Add this connection to the linked list at BtShared.pLock */
  if( rc==SQLITE4_OK ){
    sqlite4_mutex_enter(pShared->pClientMutex);

    /* If this is a multi-process connection and the shared file-handle
    ** has not yet been opened, open it now. Under the cover of the
    ** client-mutex.  */
    if( pShared->pFile==0 && pShared->bMultiProc ){
      int flags = BT_OPEN_SHARED;
      rc = pVfs->xOpen(pEnv, pVfs, pShared->zName, flags, &pShared->pFile);
    }

    if( rc==SQLITE4_OK ){
      if( pShared->pBtFile ){
        p->pBtFile = pShared->pBtFile;
        pShared->pBtFile = p->pBtFile->pNext;
        p->pBtFile->pNext = 0;
        p->pFd = p->pBtFile->pFd;
      }else{
        p->pBtFile = (BtFile*)sqlite4_malloc(pEnv, sizeof(BtFile));
        if( p->pBtFile ){
          int flags = BT_OPEN_DATABASE;
          p->pBtFile->pNext = 0;
          rc = pVfs->xOpen(pEnv, pVfs, pShared->zName, flags, &p->pFd);
          if( rc==SQLITE4_OK ){
            p->pBtFile->pFd = p->pFd;
          }else{
            sqlite4_free(pEnv, p->pBtFile);
            p->pBtFile = 0;
          }
        }else{
          rc = btErrorBkpt(SQLITE4_NOMEM);
        }
      }
    }

    if( rc==SQLITE4_OK ){
      p->pNext = pShared->pLock;
      pShared->pLock = p;
      p->pShared = pShared;
    }
    sqlite4_mutex_leave(pShared->pClientMutex);
    if( rc!=SQLITE4_OK ){
      btLockSharedDeref(pEnv, pVfs, pShared);
    }
  }

  if( rc==SQLITE4_OK ){
    rc = btLockLockop(p, BT_LOCK_DMS1, BT_LOCK_EXCL, 1);
    if( rc==SQLITE4_OK ){
      rc = btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_EXCL, 0);
      if( rc==SQLITE4_OK ){
        rc = btLockLockop(p, BT_LOCK_DMS2_RO, BT_LOCK_EXCL, 0);
      }
      if( rc==SQLITE4_OK ){
        rc = pVfs->xShmMap(p->pFd, 0, 0, 0);
      }
      if( rc==SQLITE4_OK ){
        rc = xRecover(p);
      }
      btLockLockop(p, BT_LOCK_DMS2_RO, BT_LOCK_UNLOCK, 0);
      btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_UNLOCK, 0);
      if( rc==SQLITE4_OK || rc==SQLITE4_BUSY ){
        rc = btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_SHARED, 0);
      }
      btLockLockop(p, BT_LOCK_DMS1, BT_LOCK_UNLOCK, 0);
    }
  }

  return rc;
}

/*
** Disconnect the read/write connection passed as the first argument
** from the database.
**
** If a checkpoint is required (i.e. if this is the last read/write
** connection to the database), this function invokes xCkpt() to
** request it. If the wal and shm files should be deleted from the
** file-system (i.e. if there are no read/write or read-only connections
** remaining), the xDel() callback is invoked as well.
**
** Return SQLITE4_OK if successful, or an SQLite4 error code if an
** error occurs. Even if an error occurs, the connection should be
** considered to be disconnected. The error code merely indicates
** that an error occurred while checkpointing or deleting the log file.
*/
SQLITE4_PRIVATE int sqlite4BtLockDisconnect(
  BtLock *p,                      /* Locker handle */
  int (*xCkpt)(BtLock*),          /* Callback to checkpoint database */
  int (*xDel)(BtLock*)            /* Callback to delete wal+shm files */
){
  BtShared *pShared = p->pShared;
  BtLock **pp;
  int rc;                         /* Return code */
  
  if( p->pShared==0 ) return SQLITE4_OK;

  sqlite4_mutex_enter(pShared->pClientMutex);
  for(pp=&p->pShared->pLock; *pp!=p; pp=&(*pp)->pNext);
  *pp = (*pp)->pNext;
  sqlite4_mutex_leave(pShared->pClientMutex);

  rc = btLockLockop(p, BT_LOCK_DMS1, BT_LOCK_EXCL, 1);
  if( rc==SQLITE4_OK ){
    rc = btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_EXCL, 0);
    if( rc==SQLITE4_OK ){
      rc = xCkpt(p);
    }
    if( rc==SQLITE4_OK ){
      rc = btLockLockop(p, BT_LOCK_DMS2_RO, BT_LOCK_EXCL, 0);
    }
    if( rc==SQLITE4_OK ){
      rc = xDel(p);
      if( pShared->pFile ) p->pVfs->xShmUnmap(pShared->pFile, 1);
    }
    if( rc==SQLITE4_BUSY ) rc = SQLITE4_OK;
    btLockLockop(p, BT_LOCK_DMS2_RW, BT_LOCK_UNLOCK, 0);
    btLockLockop(p, BT_LOCK_DMS2_RO, BT_LOCK_UNLOCK, 0);
    btLockLockop(p, BT_LOCK_DMS1, BT_LOCK_UNLOCK, 0);
  }

  sqlite4_mutex_enter(pShared->pClientMutex);
  assert( p->pBtFile->pNext==0 );
  p->pBtFile->pNext = pShared->pBtFile;
  pShared->pBtFile = p->pBtFile;
  sqlite4_mutex_leave(pShared->pClientMutex);

  btLockSharedDeref(p->pEnv, p->pVfs, pShared);
  p->pShared = 0;
  return rc;
}

#ifndef NDEBUG
static void assertNoLockedSlots(BtLock *pLock){
  u32 mask = (1 << (BT_LOCK_READER0+BT_NREADER+1)) - (1 << BT_LOCK_READER0);
  assert( (pLock->mExclLock & mask)==0 );
}
#else
# define assertNoLockedSlots(x)
#endif

/* 
** Obtain a READER lock. 
**
** Argument aLog points to an array of 6 frame addresses. These are the 
** first and last frames in each of log regions A, B and C. Argument 
** aLock points to the array of read-lock slots in shared memory.
*/
SQLITE4_PRIVATE int sqlite4BtLockReader(
  BtLock *pLock,                  /* Lock module handle */
  u32 *aLog,                      /* Current log file topology */
  u32 iFirst,                     /* First log frame to lock */
  BtReadSlot *aSlot               /* Array of read-lock slots (in shmem) */
){
  int rc = SQLITE4_BUSY;          /* Return code */
  int i;                          /* Loop counter */
  u32 iLast = aLog[5];            /* Last frame to lock */

  /* If page iFirst does not appear to be part of the log at all, then
  ** the entire log has been checkpointed (and iFirst is the "next" 
  ** frame to use). Handle this case in the same way as an empty 
  ** log file.  
  **
  ** It is also possible that the iFirst value (read from the shared-memory
  ** checkpoint header) is much newer than the aLog[] values (read from
  ** the snapshot header). If so, the caller will figure it out.  */
  if( (iFirst<aLog[0] || iFirst>aLog[1])
   && (iFirst<aLog[2] || iFirst>aLog[3])
   && (iFirst<aLog[4] || iFirst>aLog[5])
  ){
    iLast = 0;
  }

  if( iLast==0 ){
    rc = btLockLockop(pLock, BT_LOCK_READER_DBONLY, BT_LOCK_SHARED, 0);
  }else{
    const int nMaxRetry = 100;
    int nAttempt = 100;           /* Remaining lock attempts */

    for(nAttempt=0; rc==SQLITE4_BUSY && nAttempt<nMaxRetry; nAttempt++){

      int iIdxFirst = sqlite4BtLogFrameToIdx(aLog, iFirst);
      int iIdxLast = sqlite4BtLogFrameToIdx(aLog, iLast);

      assert( iIdxFirst>=0 && iIdxLast>=0 );

      /* Try to find a slot populated with the values required. */
      for(i=0; i<BT_NREADER; i++){
        if( aSlot[i].iFirst==iFirst && aSlot[i].iLast==iLast ){
          break;
        }
      }

      /* Or, if there is no slot with the required values - try to create one */
      if( i==BT_NREADER ){
        for(i=0; i<BT_NREADER; i++){
          rc = btLockLockop(pLock, BT_LOCK_READER0 + i, BT_LOCK_EXCL, 0);
          if( rc==SQLITE4_OK ){
            /* The EXCLUSIVE lock obtained by the successful call to
            ** btLockLockop() is released below by the call to obtain
            ** a SHARED lock on the same locking slot. */
            aSlot[i].iFirst = iFirst;
            aSlot[i].iLast = iLast;
            break;
          }else if( rc!=SQLITE4_BUSY ){
            return rc;
          }
        }
      }

      /* If no existing slot with the required values was found, and the
      ** attempt to create one failed, search for any usable slot. A 
      ** usable slot is one where both the "iFirst" and "iLast" values
      ** occur at the same point or earlier in the log than the required
      ** iFirst/iLast values, respectively.  */
      if( i==BT_NREADER ){
        for(i=0; i<BT_NREADER; i++){
          int iSlotFirst = sqlite4BtLogFrameToIdx(aLog, aSlot[i].iFirst);
          int iSlotLast = sqlite4BtLogFrameToIdx(aLog, aSlot[i].iLast);
          if( iSlotFirst<0 || iSlotLast<0 ) continue;
          if( iSlotFirst<=iIdxFirst && iSlotLast<=iIdxLast ) break;
        }
      }

      if( i<BT_NREADER ){
        rc = btLockLockop(pLock, BT_LOCK_READER0 + i, BT_LOCK_SHARED, 0);
        if( rc==SQLITE4_OK ){
          int iSF = sqlite4BtLogFrameToIdx(aLog, aSlot[i].iFirst);
          int iSL = sqlite4BtLogFrameToIdx(aLog, aSlot[i].iLast);
          if( iSF>iIdxFirst || iSL>iIdxLast || iSF<0 || iSL<0 ){
            btLockLockop(pLock, BT_LOCK_READER0 + i, BT_LOCK_UNLOCK, 0);
            rc = SQLITE4_BUSY;
          }else{
            sqlite4BtDebugReadlock(pLock, aSlot[i].iFirst, aSlot[i].iLast);
          }
        }else if( rc==SQLITE4_BUSY && nAttempt>(nMaxRetry/2) ){
          btLockDelay();
        }
      }
    }
  }

  assertNoLockedSlots(pLock);
  return rc;
}

/*
** Release the READER lock currently held by connection pLock.
*/
SQLITE4_PRIVATE int sqlite4BtLockReaderUnlock(BtLock *pLock){
  int i;

  /* Release any locks held on reader slots. */
  assert( (BT_LOCK_READER_DBONLY+1)==BT_LOCK_READER0 );
  for(i=0; i<BT_NREADER+1; i++){
    btLockLockop(pLock, BT_LOCK_READER_DBONLY + i, BT_LOCK_UNLOCK, 0);
  }

  return SQLITE4_OK;
}

/*
** This function is used to determine which parts of the log and database
** files are currently in use by readers. It is called in two scenarios:
**
**   * by CHECKPOINTER clients, to determine how much of the log may
**     be safely copied into the database file. In this case parameter
**     piDblocked is non-NULL.
**
**   * by WRITER clients, to determine how much of the log is no longer
**     required by any present or future reader. This case can be identified
**     by (piDblocked==NULL).
*/
SQLITE4_PRIVATE int sqlite4BtLockReaderQuery(
  BtLock *pLock,                  /* Lock handle */
  u32 *aLog,                      /* Current log topology */
  BtReadSlot *aSlot,              /* Array of BT_NREADER read slots */
  u32 *piOut,                     /* OUT: Query result */
  int *piDblocked                 /* OUT: True if READER_DB_ONLY is locked */
){
  u32 iOut = 0;
  int iIdxOut = 0;
  int bLast = (piDblocked!=0);
  int rc = SQLITE4_OK;
  int i;

  if( piDblocked ){
    rc = btLockLockop(pLock, BT_LOCK_READER_DBONLY, BT_LOCK_EXCL, 0);
    if( rc==SQLITE4_OK ){
      *piDblocked = 0;
      btLockLockop(pLock, BT_LOCK_READER_DBONLY, BT_LOCK_UNLOCK, 0);
    }else if( rc==SQLITE4_BUSY ){
      *piDblocked = 1;
    }else{
      return rc;
    }
  }

  for(i=0; i<3 && iOut==0; i++){
    int iSlot;
    for(iSlot=0; iSlot<BT_NREADER; iSlot++){
      u32 iVal = (bLast ? aSlot[iSlot].iLast : aSlot[iSlot].iFirst);
      if( iVal ){
        /* Try to zero the slot. */
        rc = btLockLockop(pLock, BT_LOCK_READER0 + iSlot, BT_LOCK_EXCL, 0);
        if( rc==SQLITE4_OK ){
          aSlot[iSlot].iFirst = 0;
          aSlot[iSlot].iLast = 0;
          btLockLockop(pLock, BT_LOCK_READER0 + iSlot, BT_LOCK_UNLOCK, 0);
        }else if( rc==SQLITE4_BUSY ){
          int iIdx = sqlite4BtLogFrameToIdx(aLog, iVal);
          if( iIdx>=0 && (iOut==0 || iIdx<iIdxOut) ){
            iIdxOut = iIdx;
            iOut = iVal;
          }
        }else{
          return rc;
        }
      }
    }
  }

  *piOut = iOut;
  return SQLITE4_OK;
}

SQLITE4_PRIVATE int sqlite4BtLockShmMap(BtLock *pLock, int iChunk, int nByte, u8 **ppOut){
  int rc = SQLITE4_OK;
  BtShared *pShared = pLock->pShared;
  u8 *pOut = 0;

  assert( pShared->bReadonly==0 );

  sqlite4_mutex_enter(pShared->pClientMutex);
  if( pShared->nShmChunk<=iChunk ){
    u8 **apNew;
    int nNew = iChunk+1;
    int nByte = sizeof(u8*)*nNew;

    apNew = (u8**)sqlite4_realloc(pLock->pEnv, pShared->apShmChunk, nByte);
    if( apNew==0 ){
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }else{
      memset(&apNew[pShared->nShmChunk],0,nByte-sizeof(u8*)*pShared->nShmChunk);
      pShared->nShmChunk = nNew;
      pShared->apShmChunk = apNew;
    }
  }

  if( rc==SQLITE4_OK ){

    assert( (pShared->bMultiProc==0)==(pShared->pFile==0) );
    if( pShared->pFile==0 ){
      /* Single process mode. Allocate memory from the heap. */
      if( pShared->apShmChunk[iChunk]==0 ){
        u8 *p = (u8*)sqlite4_malloc(pLock->pEnv, nByte);
        if( p ){
          memset(p, 0, nByte);
          pShared->apShmChunk[iChunk] = p;
        }else{
          rc = btErrorBkpt(SQLITE4_NOMEM);
        }
      }
    }else{
      /* Multi-process mode. Request shared memory from VFS */
      void *pShm = 0;
      rc = pLock->pVfs->xShmMap(pShared->pFile, iChunk, nByte, &pShm);
      pShared->apShmChunk[iChunk] = (u8*)pShm;
    }

    pOut = pShared->apShmChunk[iChunk];
    assert( pOut || rc!=SQLITE4_OK );
  }
  sqlite4_mutex_leave(pShared->pClientMutex);
  
  *ppOut = pOut;
  return rc;
}

/*
** Attempt to obtain the CHECKPOINTER lock. If the attempt is successful,
** return SQLITE4_OK. If the CHECKPOINTER lock cannot be obtained because
** it is held by some other connection, return SQLITE4_BUSY. 
**
** If any other error occurs, return an SQLite4 error code.
*/
SQLITE4_PRIVATE int sqlite4BtLockCkpt(BtLock *pLock){
  return btLockLockop(pLock, BT_LOCK_CKPTER, BT_LOCK_EXCL, 0);
}
SQLITE4_PRIVATE int sqlite4BtLockCkptUnlock(BtLock *pLock){
  return btLockLockop(pLock, BT_LOCK_CKPTER, BT_LOCK_UNLOCK, 0);
}

/*
** Attempt to obtain the WRITER lock. If the attempt is successful,
** return SQLITE4_OK. If the WRITER lock cannot be obtained because
** it is held by some other connection, return SQLITE4_BUSY. 
**
** If any other error occurs, return an SQLite4 error code.
*/
SQLITE4_PRIVATE int sqlite4BtLockWriter(BtLock *pLock){
  return btLockLockop(pLock, BT_LOCK_WRITER, BT_LOCK_EXCL, 0);
}
SQLITE4_PRIVATE int sqlite4BtLockWriterUnlock(BtLock *pLock){
  return btLockLockop(pLock, BT_LOCK_WRITER, BT_LOCK_UNLOCK, 0);
}


/************** End of bt_lock.c *********************************************/
/************** Begin file bt_log.c ******************************************/
/*
** 2013 October 19
**
** 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.
**
*************************************************************************
*/


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

/* Magic values identifying WAL file header */
#define BT_WAL_MAGIC   0xBEE1CA62
#define BT_WAL_VERSION 0x00000001

/* Wrap the log around if there is a block of this many free frames at
** the start of the file.  */
#define BT_NWRAPLOG    100

typedef struct BtCkptHdr BtCkptHdr;
typedef struct BtDbHdrCksum BtDbHdrCksum;
typedef struct BtFrameHdr BtFrameHdr;
typedef struct BtShm BtShm;
typedef struct BtShmHdr BtShmHdr;
typedef struct BtWalHdr BtWalHdr;

/*
** WAL file header. All u32 fields are stored in big-endian order on
** disk. A single WAL file may contain two of these headers - one at
** byte offset 0 and the other at offset <sector-size> (the start of
** the second disk sector in the file, according to the xSectorSize
** VFS method).
*/
struct BtWalHdr {
  u32 iMagic;                     /* Magic number (BT_WAL_MAGIC) */
  u32 iVersion;                   /* File format version */
  u32 iCnt;                       /* 0, 1 or 2 */
  u32 nSector;                    /* Sector size when header written */

  u32 nPgsz;                      /* Database page size in bytes */
  u32 nPg;                        /* Database size in pages at last commit */

  u32 padding;

  u32 iSalt1;                     /* Initial frame cksum-0 value */
  u32 iSalt2;                     /* Initial frame cksum-1 value */
  u32 iFirstFrame;                /* First frame of log (numbered from 1) */

  u32 aCksum[2];                  /* Checksum of all prior fields */
};

/*
** WAL Frame header. All fields are stored in big-endian order.
**
** pgno:
**   Page number for the frame.
**
** iNext:
**   Next frame in logical log.
**   
** nPg:
**   For non-commit frames, zero. For commit frames, the size of the
**   database file in pages at the time of commit (always at least 1).
*/
struct BtFrameHdr {
  u32 pgno;                       /* Page number of this frame */
  u32 iNext;                      /* Next frame pointer */
  u32 nPg;                        /* For commit frames, size of db file */
  u32 aCksum[2];                  /* Frame checksum */
};

#define BT_FRAME_COMMIT 0x80000000

/*
** A database header with checksum fields.
*/
struct BtDbHdrCksum {
  BtDbHdr hdr;
  u32 aCksum[2];
};


/*
** Shared memory header. Shared memory begins with two copies of
** this structure. All fields are stored in machine byte-order.
*/
struct BtShmHdr {
  u32 aLog[6];                    /* First/last frames for each log region */
  int nSector;                    /* Sector size assumed for WAL file */
  int iHashSide;                  /* Hash table side for region (c) of log */
  u32 aFrameCksum[2];             /* Checksum of previous frame */
  u32 iNextFrame;                 /* Location to write next log frame to */
  BtDbHdr dbhdr;                  /* Cached db-header values */

  u32 padding;
  u32 aCksum[2];                  /* Object checksum */
};

/*
** A single instance of this structure follows the two BtShmHdr structures 
** in shared memory.
**
** iWalHdr:
**   This field encodes two pieces of information: the location of the
**   current log file header (slot 0 or slot 1) and the value of the
**   BtWalHdr.iCnt field within it (0, 1 or 2). Encoded as:
**
**           ((iSlot << 2) + iCnt)
**
**   To decode, use:
**
**           iSlot = (ckpthdr.iWalHdr >> 2);
**           iCnt = (ckpthdr.iWalHdr & 0x03);& 0x03);
*/
struct BtCkptHdr {
  u32 iFirstRead;                 /* First uncheckpointed frame */
  u32 iWalHdr;                    /* Description of current wal header */
  u32 iFirstRecover;              /* First recovery frame */
};

struct BtShm {
  BtShmHdr hdr1;
  BtShmHdr hdr2;
  BtCkptHdr ckpt;
  BtReadSlot aReadlock[BT_NREADER];
};

/* 
** Log handle used by bt_pager.c to access functionality implemented by
** this module. 
*/
struct BtLog {
  BtLock *pLock;                  /* Lock object associated with this log */
  bt_file *pFd;                   /* File handle open on WAL file */
  BtShmHdr snapshot;              /* Current snapshot of shm-header */
  int nShm;                       /* Size of apShm[] array */
  u8 **apShm;                     /* Array of mapped shared-memory blocks */
  int nWrapLog;                   /* Wrap if this many free frames at start */
};

typedef u16 ht_slot;

/*
** Number of entries in each hash table bar the first. 
*/
#define HASHTABLE_NFRAME (BT_SHM_CHUNK_SIZE/(sizeof(u32) + 4*sizeof(ht_slot))) 

/* 
** Number of entries in first hash table. The first hash table is 
** smaller than the others as space for the BtShm structure is carved
** from the start of it. The two hash-slot arrays remain the same size, 
** but the number of entries in the page-number array is reduced to the
** value defined below.
*/
#define HASHTABLE_NFRAME_ONE (HASHTABLE_NFRAME - (sizeof(BtShm)/sizeof(u32)))

/*
** Number of slots in a hash table.
*/
#define HASHTABLE_NSLOT (HASHTABLE_NFRAME * 2)

#define HASHTABLE_OFFSET_1 (HASHTABLE_NFRAME * sizeof(u32))
#define HASHTABLE_OFFSET_2 (HASHTABLE_OFFSET_1+HASHTABLE_NSLOT*sizeof(ht_slot))

/*
** Used to calculate hash keys.
*/
#define HASHTABLE_KEY_MUL 383


/*
** The argument to this macro must be of type u32. On a little-endian
** architecture, it returns the u32 value that results from interpreting
** the 4 bytes as a big-endian value. On a big-endian architecture, it
** returns the value that would be produced by intepreting the 4 bytes
** of the input value as a little-endian integer.
*/
#define BYTESWAP32(x) ( \
  (((x)&0x000000FF)<<24) + (((x)&0x0000FF00)<<8)  \
  + (((x)&0x00FF0000)>>8)  + (((x)&0xFF000000)>>24) \
)

/* True if this is a little-endian build */
static const int btOne = 1;
#define BTLOG_LITTLE_ENDIAN (*(u8 *)(&btOne))

/*
** Generate or extend an 8 byte checksum based on the data in
** array aByte[] and the initial values of aIn[0] and aIn[1] (or
** initial values of 0 and 0 if aIn==NULL).
**
** The checksum is written back into aOut[] before returning.
**
** nByte must be a positive multiple of 8.
*/
static void btLogChecksum(
  int nativeCksum,                /* True for native byte-order, else false */
  u8 *a,                          /* Content to be checksummed */
  int nByte,                      /* Bytes of content in a[]. */
  const u32 *aIn,                 /* Initial checksum value input */
  u32 *aOut                       /* OUT: Final checksum value output */
){
  u32 s1, s2;
  u32 *aData = (u32 *)a;
  u32 *aEnd = (u32 *)&a[nByte];

  if( aIn ){
    s1 = aIn[0];
    s2 = aIn[1];
  }else{
    s1 = s2 = 0;
  }

  assert( nByte>=8 );
  assert( (nByte&0x00000007)==0 );

  if( nativeCksum ){
    do {
      s1 += *aData++ + s2;
      s2 += *aData++ + s1;
    }while( aData<aEnd );
  }else{
    do {
      s1 += BYTESWAP32(aData[0]) + s2;
      s2 += BYTESWAP32(aData[1]) + s1;
      aData += 2;
    }while( aData<aEnd );
  }

  aOut[0] = s1;
  aOut[1] = s2;
}

static void btLogChecksum32(
  int nativeCksum,                /* True for native byte-order, else false */
  u8 *a,                          /* Content to be checksummed */
  int nByte,                      /* Bytes of content in a[]. */
  const u32 *aIn,                 /* Initial checksum value input */
  u32 *aOut                       /* OUT: Final checksum value output */
){
  assert( nByte>=8 );
  if( nByte&0x00000007 ){
    btLogChecksum(nativeCksum, a, 8, aIn, aOut);
    btLogChecksum(nativeCksum, &a[4], nByte-4, aOut, aOut);
  }else{
    btLogChecksum(nativeCksum, a, nByte, aIn, aOut);
  }
}

#define BT_ALLOC_DEBUG   0
#define BT_PAGE_DEBUG    0
#define BT_VAL_DEBUG     0
#define BT_HDR_DEBUG     0
#define BT_RECOVER_DEBUG 0

static void btDebugTopology(BtLock *pLock, char *zStr, int iSide, u32 *aLog){
#if BT_PAGE_DEBUG
  fprintf(stderr, "%d:%s: (side=%d) %d..%d  %d..%d  %d..%d\n", 
      pLock->iDebugId, zStr, iSide,
      (int)aLog[0], (int)aLog[1], (int)aLog[2], 
      (int)aLog[3], (int)aLog[4], (int)aLog[5]
  );
  fflush(stderr);
#endif
}

static void btDebugDbhdr(BtLock *pLock, const char *zStr, BtDbHdr *pHdr){
#if BT_HDR_DEBUG
  static int nCall = 0;
  fprintf(stderr, "%d:%d: %s db-header "
      "(pgsz=%d nPg=%d iRoot=%d iCookie=%d iFreePg=%d iFreeBlk=%d)\n",
      pLock->iDebugId, nCall++,
      zStr, (int)pHdr->pgsz, (int)pHdr->nPg, (int)pHdr->iRoot, 
      (int)pHdr->iCookie, (int)pHdr->iFreePg, (int)pHdr->iFreeBlk
  );
  fflush(stderr);
#endif
}

static void btDebugRecoverFrame(BtLock *pLock, u32 iFrame, u32 pgno){
#if BT_RECOVER_DEBUG
  static int nCall = 0;
  fprintf(stderr, "%d:%d: recovered page %d from frame %d\n",
      pLock->iDebugId, nCall++, (int)pgno, (int)iFrame
  );
  fflush(stderr);
#endif
}

#ifndef NDEBUG
SQLITE4_PRIVATE void sqlite4BtDebugReadlock(BtLock *pLock, u32 iFirst, u32 iLast){
#if BT_PAGE_DEBUG
  static int nCall = 0;
  fprintf(stderr, "%d:%d: readlock=(%d..%d)\n",
      pLock->iDebugId, nCall++, (int)iFirst, (int)iLast
  );
  fflush(stderr);
#endif
}
#endif

#ifndef NDEBUG
SQLITE4_PRIVATE void sqlite4BtDebugPageAlloc(BtLock *pLock, const char *zStr, u32 pgno){
#if BT_ALLOC_DEBUG
  static int nCall = 0;
  fprintf(stderr, "%d:%d: allocate page %d from %s\n", 
      pLock->iDebugId, nCall++, pgno, zStr
  );
  fflush(stderr);
#endif
}
#endif

#ifndef NDEBUG
SQLITE4_PRIVATE void sqlite4BtDebugPageFree(
  BtLock *pLock, int bBlock, const char *zStr, u32 pgno
){
#if BT_ALLOC_DEBUG
  static int nCall = 0;
  fprintf(stderr, "%d:%d: trim %s %d (%s)\n", 
      pLock->iDebugId, nCall++, bBlock ? "block" : "page", pgno, zStr
  );
  fflush(stderr);
  assert( pgno<1000000 );
#endif
}
#endif


#ifndef NDEBUG
static void btDebugCheckSnapshot(BtShmHdr *pHdr){
  u32 *aLog = pHdr->aLog;
  assert( pHdr->iNextFrame!=1 ||
      (aLog[0]==0 && aLog[1]==0 && aLog[2]==0 && aLog[3]==0)
  );

  /* Check that the three log regions do not overlap */
  assert( aLog[0]==0 || aLog[2]==0 || aLog[3]<aLog[0] || aLog[2]>aLog[1] );
  assert( aLog[0]==0 || aLog[4]==0 || aLog[5]<aLog[0] || aLog[4]>aLog[1] );
  assert( aLog[2]==0 || aLog[4]==0 || aLog[5]<aLog[2] || aLog[4]>aLog[3] );

  /* Check that the "next frame" does not overlap with any region */
  assert( aLog[0]==0 || pHdr->iNextFrame<aLog[0] ||  pHdr->iNextFrame>aLog[1] );
  assert( aLog[2]==0 || pHdr->iNextFrame<aLog[2] ||  pHdr->iNextFrame>aLog[3] );
  assert( aLog[4]==0 || pHdr->iNextFrame<aLog[4] ||  pHdr->iNextFrame>aLog[5] );
}
#else
#define btDebugCheckSnapshot(x)
#endif

#ifndef NDEBUG
static void btDebugLogSafepoint(BtLock *pLock, u32 iSafe){
#if BT_PAGE_DEBUG
  static int nCall = 0;
  fprintf(stderr, "%d:%d: checkpoint safepoint=%d\n",
      pLock->iDebugId, nCall++, (int)iSafe
  );
  fflush(stderr);
#endif
}
#else
#define btDebugLogSafepoint(x,y)
#endif

static void btDebugCkptPage(BtLock *pLock, u32 pgno, u8 *aData, int pgsz){
#if BT_PAGE_DEBUG
  static int nCall = 0;
  u32 aCksum[2];
  btLogChecksum(1, aData, pgsz, 0, aCksum);
  fprintf(stderr, "%d:%d: Ckpt page %d (cksum=%08x%08x)\n", 
      pLock->iDebugId, nCall++, (int)pgno, aCksum[0], aCksum[1]
  );
  fflush(stderr);
#endif
}

static void btDebugLogPage(
    BtLock *pLock, u32 pgno, u32 iFrame, u8 *aData, int pgsz, int bCommit
){
#if BT_PAGE_DEBUG
  static int nCall = 0;
  u32 aCksum[2];
  btLogChecksum(1, aData, pgsz, 0, aCksum);
  fprintf(stderr, "%d:%d: Log page %d to frame %d (cksum=%08x%08x)%s\n", 
      pLock->iDebugId, nCall++, (int)pgno, (int)iFrame, 
      aCksum[0], aCksum[1], (bCommit ? " commit" : "")
  );
  fflush(stderr);
#endif
}

#ifndef NDEBUG
SQLITE4_PRIVATE void sqlite4BtDebugReadPage(BtLock *pLock, u32 pgno, u8 *aData, int pgsz){
#if BT_PAGE_DEBUG
  static int nCall = 0;
  u32 aCksum[2];
  btLogChecksum(1, aData, pgsz, 0, aCksum);
  fprintf(stderr, "%d:%d: Read page %d (cksum=%08x%08x)\n", pLock->iDebugId,
      nCall++, (int)pgno, aCksum[0], aCksum[1]
  );
  fflush(stderr);
#endif
}
#endif

#ifndef NDEBUG
/* #include <ctype.h> */
#if BT_VAL_DEBUG
static void binToStr(u8 *pIn, int nIn, u8 *pOut, int nOut){
  int i;
  int nCopy = MIN(nIn, (nOut-1));
  for(i=0; i<nCopy; i++){
    if( isprint(pIn[i]) ){
      pOut[i] = pIn[i];
    }else{
      pOut[i] = '.';
    }
  }
  pOut[i] = '\0';
}
#endif
SQLITE4_PRIVATE void sqlite4BtDebugKV(
    BtLock *pLock, const char *zStr, u8 *pK, int nK, u8 *pV, int nV
){
#if BT_VAL_DEBUG
  u8 aKBuf[40];
  u8 aVBuf[40];
  static int nCall = 0;

  binToStr(pK, nK, aKBuf, sizeof(aKBuf));
  if( nV<0 ){
    memcpy(aVBuf, "(delete)", 9);
  }else{
    binToStr(pV, nV, aVBuf, sizeof(aVBuf));
  }
  fprintf(stderr, "%d:%d: %s \"%s\" -> \"%s\" (%d bytes)\n", 
      pLock->iDebugId, nCall++, zStr, aKBuf, aVBuf, nV
  );

  fflush(stderr);
#endif
}
#endif

static void btDebugLogSearch(BtLock *pLock, u32 pgno, u32 iSafe, u32 iFrame){
#if BT_PAGE_DEBUG
  static int nCall = 0;
  fprintf(stderr, "%d:%d: Search log for page %d (safe=%d) - frame %d\n", 
      pLock->iDebugId, nCall++, (int)pgno, (int)iSafe, (int)iFrame
  );
  fflush(stderr);
#endif
}

static void btDebugSetPgno(BtLock *pLock, 
    int iHash, int iSide, u32 *aPgno, int iFrame, int iZero, u32 pgno
){
#if BT_PAGE_DEBUG
  static int nCall = 0;
  fprintf(stderr, "%d:%d: Set iHash=%d/%d aPgno=%p iFrame=%d iZero=%d pgno=%d\n"
      , pLock->iDebugId, nCall++, iHash, iSide,
      (void*)aPgno, iFrame, iZero, (int)pgno
  );
  fflush(stderr);
#endif
}

#ifndef NDEBUG
static void btDebugLogHeader(
    BtLock *pLock, const char *z, BtWalHdr *pHdr, int iHdr
){
#if BT_HDR_DEBUG
  static int nCall = 0;
  fprintf(stderr, 
      "%d:%d: %s log-header %d: (iCnt=%d iFirstFrame=%d nPgsz=%d)\n",
      pLock->iDebugId, nCall++, z, iHdr,
      (int)pHdr->iCnt, (int)pHdr->iFirstFrame, (int)pHdr->nPgsz
  );
  fflush(stderr);
#endif
}
#endif


#ifdef NDEBUG
# define btDebugLogHeader(a,b,c,d)
#endif

/*
** Ensure that shared-memory chunk iChunk is mapped and available in
** the BtLog.apShm[] array. If an error occurs, return an SQLite4 error
** code. Otherwise, SQLITE4_OK.
*/
static int btLogMapShm(BtLog *pLog, int iChunk){
  int rc = SQLITE4_OK;

  if( pLog->nShm<=iChunk ){
    sqlite4_env *pEnv = pLog->pLock->pEnv;
    u8 **apNew;
    int nNew = iChunk+1;

    apNew = (u8**)sqlite4_realloc(pEnv, pLog->apShm, sizeof(u8*)*nNew);
    if( apNew==0 ) return btErrorBkpt(SQLITE4_NOMEM);
    memset(&apNew[pLog->nShm], 0, (nNew-pLog->nShm) * sizeof(u8*));
    pLog->nShm = nNew;
    pLog->apShm = apNew;
  }

  if( pLog->apShm[iChunk]==0 ){
    u8 **pp = &pLog->apShm[iChunk];
    rc = sqlite4BtLockShmMap(pLog->pLock, iChunk, BT_SHM_CHUNK_SIZE, pp);
  }

  return rc;
}

static BtShm *btLogShm(BtLog *pLog){
  return (BtShm*)(pLog->apShm[0]);
}

static int btLogUpdateSharedHdr(BtLog *pLog){
  bt_env *pVfs = pLog->pLock->pVfs;
  BtShmHdr *p = &pLog->snapshot;
  BtShm *pShm = btLogShm(pLog);

  /* Calculate a checksum for the private snapshot object. */
  btLogChecksum32(1, (u8*)p, offsetof(BtShmHdr, aCksum), 0, p->aCksum);

  /* Update the shared object. */
  pVfs->xShmBarrier(pLog->pFd);
  memcpy(&pShm->hdr1, p, sizeof(BtShmHdr));
  pVfs->xShmBarrier(pLog->pFd);
  memcpy(&pShm->hdr2, p, sizeof(BtShmHdr));

  return SQLITE4_OK;
}

static void btLogZeroSnapshot(BtLog *pLog){
  bt_env *pVfs = pLog->pLock->pVfs;
  memset(&pLog->snapshot, 0, sizeof(BtShmHdr));
  pLog->snapshot.nSector = pVfs->xSectorSize(pLog->pFd);
}

/*
** Return the offset of frame iFrame within the log file.
*/
static i64 btLogFrameOffset(BtLog *pLog, int pgsz, u32 iFrame){
  return 
      (i64)pLog->snapshot.nSector*2 
    + (i64)(iFrame-1) * (i64)(pgsz + sizeof(BtFrameHdr));
}

static int btLogSyncFile(BtLog *pLog, bt_file *pFd){
  if( pLog->pLock->iSafetyLevel==BT_SAFETY_OFF ) return SQLITE4_OK;
  bt_env *pVfs = pLog->pLock->pVfs;
  return pVfs->xSync(pFd);
}

static int btLogWriteData(BtLog *pLog, i64 iOff, u8 *aData, int nData){
  bt_env *pVfs = pLog->pLock->pVfs;
  return pVfs->xWrite(pLog->pFd, iOff, aData, nData);
}

static int btLogReadData(BtLog *pLog, i64 iOff, u8 *aData, int nData){
  bt_env *pVfs = pLog->pLock->pVfs;
  return pVfs->xRead(pLog->pFd, iOff, aData, nData);
}

static int btLogReadHeader(BtLog *pLog, int iOff, BtWalHdr *pHdr){
  int rc = btLogReadData(pLog, (i64)iOff, (u8*)pHdr, sizeof(BtWalHdr));
  if( rc==SQLITE4_OK ){
    u32 aCksum[2];
    btLogChecksum(1, (u8*)pHdr, offsetof(BtWalHdr, aCksum), 0, aCksum);
    if( pHdr->iMagic!=BT_WAL_MAGIC 
     || aCksum[0]!=pHdr->aCksum[0] 
     || aCksum[1]!=pHdr->aCksum[1] 
    ){
      rc = SQLITE4_NOTFOUND;
    }else{
      btDebugLogHeader(pLog->pLock, "read", pHdr, iOff!=0);
    }
  }
  return rc;
}

/*
** This function is used as part of recovery. It reads the contents of
** the log file from disk and invokes the xFrame callback for each valid
** frame in the file.
*/
static int btLogTraverse(
  BtLog *pLog,                    /* Log module handle */
  BtWalHdr *pHdr,                 /* Log header read from file */
  int(*xFrame)(BtLog*, void*, u32, BtFrameHdr*), /* Frame callback */
  void *pCtx                      /* Passed as second argument to xFrame */
){
  sqlite4_env *pEnv = pLog->pLock->pEnv;
  const int pgsz = pHdr->nPgsz;
  u32 iFrame = pHdr->iFirstFrame;
  u32 aCksum[2];
  BtFrameHdr fhdr;                /* Frame header */
  u8 *aBuf;                       /* Buffer for frame data */
  int rc = SQLITE4_OK;

  aCksum[0] = pHdr->iSalt1;
  aCksum[1] = pHdr->iSalt2;

  aBuf = sqlite4_malloc(pEnv, pgsz);
  if( aBuf==0 ){
    rc = SQLITE4_NOMEM;
  }

  while( rc==SQLITE4_OK ){
    i64 iOff;
    iOff = btLogFrameOffset(pLog, pgsz, iFrame);

    rc = btLogReadData(pLog, iOff, (u8*)&fhdr, sizeof(BtFrameHdr));
    if( rc==SQLITE4_OK ){
      rc = btLogReadData(pLog, iOff+sizeof(BtFrameHdr), aBuf, pgsz);
    }
    if( rc==SQLITE4_OK ){
      btLogChecksum32(1, (u8*)&fhdr, offsetof(BtFrameHdr,aCksum),aCksum,aCksum);
      btLogChecksum(1, aBuf, pgsz, aCksum, aCksum);
      if( aCksum[0]!=fhdr.aCksum[0] || aCksum[1]!=fhdr.aCksum[1] ) break;
    }
    if( rc==SQLITE4_OK ){
      rc = xFrame(pLog, pCtx, iFrame, &fhdr);
    }

    iFrame = fhdr.iNext;
  }

  sqlite4_free(pEnv, aBuf);
  return rc;
}

/*
** Locate the iHash'th hash table in shared memory. Return it.
*/
static int btLogFindHash(
  BtLog *pLog,                    /* Log handle */
  int iSide,                      /* Which set of hash slots to return */
  int iHash,                      /* Hash table (numbered from 0) to find */
  ht_slot **paHash,               /* OUT: Pointer to hash slots */
  u32 **paPgno,                   /* OUT: Pointer to page number array */
  u32 *piZero                     /* OUT: Frame associated with *paPgno[0] */
){
  int rc;                         /* Return code */

  assert( iSide==0 || iSide==1 );

  rc = btLogMapShm(pLog, iHash);
  if( rc==SQLITE4_OK ){
    u8 *aChunk = pLog->apShm[iHash];
    u32 *aPgno;
    u32 iZero;

    *paHash = (ht_slot*)&aChunk[iSide?HASHTABLE_OFFSET_1:HASHTABLE_OFFSET_2];
    if( iHash==0 ){
      aPgno = (u32*)&aChunk[sizeof(BtShm)];
      iZero = 1;
    }else{
      aPgno = (u32*)aChunk;
      iZero = 1 + HASHTABLE_NFRAME_ONE + (HASHTABLE_NFRAME * (iHash-1));
    }
    *paPgno = aPgno;
    *piZero = iZero;
  }

  return rc;
}


/*
** Return the index of the hash table that contains the entry for frame
** iFrame. 
*/
static int btLogFrameHash(BtLog *pLog, u32 iFrame){
  if( iFrame<=HASHTABLE_NFRAME_ONE ) return 0;
  return 1 + ((iFrame - HASHTABLE_NFRAME_ONE - 1) / HASHTABLE_NFRAME);
}

/*
** Return a hash key for page number pgno.
*/
static int btLogHashKey(BtLog *pLog, u32 pgno){
  assert( pgno>=1 );
  return ((pgno * HASHTABLE_KEY_MUL) % HASHTABLE_NSLOT);
}

static int btLogHashNext(BtLog *pLog, int iSlot){
  return ((iSlot + 1) % HASHTABLE_NSLOT);
}

/*
** Add an entry mapping database page pgno to log frame iFrame to the
** the shared hash table. Return SQLITE4_OK if successful, or an SQLite4
** error code if an error occurs.
*/
static int btLogHashInsert(BtLog *pLog, u32 pgno, u32 iFrame){
  int iHash;                      /* Index of hash table to update */
  int rc = SQLITE4_OK;            /* Return code */
  ht_slot *aHash;                 /* Hash slots */
  u32 *aPgno;                     /* Page array for updated hash table */
  u32 iZero;                      /* Zero-offset of updated hash table */
  int iSide = pLog->snapshot.iHashSide;

  assert( iFrame>=1 && pgno>=1 );

  /* Find the required hash table */
  iHash = btLogFrameHash(pLog, iFrame);
  rc = btLogFindHash(pLog, iSide, iHash, &aHash, &aPgno, &iZero);

  /* Update the hash table */
  if( rc==SQLITE4_OK ){
    int iSlot;
    int nCollide = HASHTABLE_NSLOT*2;
    aPgno[iFrame-iZero] = pgno;
    btDebugSetPgno(pLog->pLock, iHash, iSide, aPgno, iFrame, iZero, pgno);

    if( iFrame==iZero ){
      memset(aHash, 0, sizeof(ht_slot) * HASHTABLE_NSLOT);
    }

    for(iSlot=btLogHashKey(pLog,pgno); ; iSlot=btLogHashNext(pLog, iSlot)){
      if( aHash[iSlot]==0 ){
        aHash[iSlot] = (iFrame-iZero+1);
        break;
      }
      if( (nCollide--)==0 ) return btErrorBkpt(SQLITE4_CORRUPT);
    }
  }

  return rc;
}

/*
** Remove everything following frame iFrame from the iHash'th hash table.
*/
static int btLogHashRollback(BtLog *pLog, int iHash, u32 iFrame){
  ht_slot *aHash;                 /* Hash slots */
  u32 *aPgno;                     /* Page array for updated hash table */
  u32 iZero;                      /* Zero-offset of updated hash table */
  int iSide = pLog->snapshot.iHashSide;
  int rc;

  rc = btLogFindHash(pLog, iSide, iHash, &aHash, &aPgno, &iZero);
  if( rc==SQLITE4_OK ){
    int i;
    ht_slot iMax;
    iMax = (iFrame - iZero) + 1;

    for(i=0; i<HASHTABLE_NSLOT; i++){
      if( aHash[i]>iMax ){
        aPgno[aHash[i]-1] = 0;
        aHash[i] = 0;
      }
    }
  }

  return rc;
}


/*
** Return true if log is completely empty (as it is if a file zero bytes
** in size has been opened or created).
*/
static int btLogIsEmpty(BtLog *pLog){
  return (pLog->snapshot.aLog[4]==0 && pLog->snapshot.iNextFrame==0);
}

typedef struct FrameRecoverCtx FrameRecoverCtx;
struct FrameRecoverCtx {
  u32 iLast;                      /* Frame containing last commit flag in log */
  u32 iNextFrame;                 /* Frame that follows frame iLast */
  u32 iPageOneFrame;              /* Frame containing most recent page 1 */
};

static int btLogRecoverFrame(
  BtLog *pLog,                    /* Log module handle */
  void *pCtx,                     /* Pointer to FrameRecoverCtx */
  u32 iFrame,                     /* Frame number */
  BtFrameHdr *pHdr                /* Frame header */
){
  FrameRecoverCtx *pFRC = (FrameRecoverCtx*)pCtx;

  btDebugRecoverFrame(pLog->pLock, iFrame, pHdr->pgno);

  if( btLogIsEmpty(pLog) ){
    /* This is the first frame recovered. It is therefore both the first
    ** and last frame of log region (c).  */
    pLog->snapshot.aLog[4] = iFrame;
    pLog->snapshot.aLog[5] = iFrame;
  }else{
    u32 iExpect = pLog->snapshot.aLog[5]+1;
    if( iFrame==iExpect ){
      pLog->snapshot.aLog[5] = iFrame;
    }else if( iFrame<iExpect ){
      assert( iFrame==1 );
      assert( pLog->snapshot.aLog[0]==0 && pLog->snapshot.aLog[1]==0 );
      pLog->snapshot.aLog[0] = pLog->snapshot.aLog[4];
      pLog->snapshot.aLog[1] = pLog->snapshot.aLog[5];
      pLog->snapshot.aLog[4] = iFrame;
      pLog->snapshot.aLog[5] = iFrame;
      pLog->snapshot.iHashSide = (pLog->snapshot.iHashSide + 1) % 2;
    }else{
      assert( pLog->snapshot.aLog[2]==0 && pLog->snapshot.aLog[3]==0 );
      pLog->snapshot.aLog[2] = pLog->snapshot.aLog[4];
      pLog->snapshot.aLog[3] = pLog->snapshot.aLog[5];
      pLog->snapshot.aLog[4] = iFrame;
      pLog->snapshot.aLog[5] = iFrame;
    }
  }

  btLogHashInsert(pLog, pHdr->pgno, iFrame);
  if( pHdr->nPg!=0 ){
    pFRC->iLast = iFrame;
    pFRC->iNextFrame = pHdr->iNext;
    memcpy(pLog->snapshot.aFrameCksum, pHdr->aCksum, sizeof(pHdr->aCksum));
    pLog->snapshot.dbhdr.nPg = pHdr->nPg;
  }

  if( pHdr->pgno==1 ){
    pFRC->iPageOneFrame = iFrame;
  }

#if 0
  fprintf(stderr, "recovered frame=%d pgno=%d\n", iFrame, pHdr->pgno);
  fflush(stderr);
#endif
  return 0;
}

/*
** This function is called as part of log recovery. The log file has 
** already been scanned and the log topology (pLog->snapshot.aLog[])
** shared-memory hash tables have been populated with data corresponding
** to the entire set of valid frames recovered from the log file -
** including uncommitted frames. This function removes the uncommitted
** frames from the log topology and shared hash tables.
*/
static int btLogRollbackRecovery(BtLog *pLog, FrameRecoverCtx *pCtx){
  u32 iLast = pCtx->iLast;        /* Last committed frame in log file */
  u32 *aLog = pLog->snapshot.aLog;/* Log file topology */

  while( iLast<aLog[4] || iLast>aLog[5] ){
    if( aLog[2] ){
      aLog[5] = aLog[3];
      aLog[4] = aLog[2];
      if( aLog[0] && aLog[0]<aLog[4] ){
        aLog[3] = aLog[1];
        aLog[2] = aLog[0];
        aLog[0] = aLog[1] = 0;
      }else{
        aLog[2] = aLog[3] = 0;
      }
    }else{
      aLog[5] = aLog[1];
      aLog[4] = aLog[0];
      aLog[0] = aLog[1] = 0;
      pLog->snapshot.iHashSide = (pLog->snapshot.iHashSide + 1) % 2;
    }
  }

  aLog[5] = iLast;
  return btLogHashRollback(pLog, btLogFrameHash(pLog, iLast), iLast);
}

static int btLogDecodeDbhdr(BtLog *pLog, u8 *aData, BtDbHdr *pHdr){
  BtDbHdrCksum hdr;
  u32 aCksum[2] = {0,0};

  if( aData ){
    memcpy(&hdr, aData, sizeof(BtDbHdrCksum));
    btLogChecksum32(1, (u8*)&hdr, offsetof(BtDbHdrCksum, aCksum), 0, aCksum);
  }

  if( aData==0 || aCksum[0]!=hdr.aCksum[0] || aCksum[1]!=hdr.aCksum[1] ){
    return SQLITE4_NOTFOUND;
  }

  memcpy(pHdr, &hdr, sizeof(BtDbHdr));
  return SQLITE4_OK;
}

static void btLogZeroDbhdr(BtLog *pLog, BtDbHdr *pHdr){
  assert( sizeof(pHdr->azStr)==strlen(BT_DBHDR_STRING) );

  memset(pHdr, 0, sizeof(BtDbHdr));
  memcpy(pHdr->azStr, BT_DBHDR_STRING, strlen(BT_DBHDR_STRING));
  pHdr->pgsz = pLog->pLock->nPgsz;
  pHdr->blksz = pLog->pLock->nBlksz;
  pHdr->nPg = 2;
  pHdr->iRoot = 2;
}

static int btLogReadDbhdr(BtLog *pLog, BtDbHdr *pHdr, u32 iFrame){
  BtLock *p = pLog->pLock;        /* BtLock handle */
  int rc;                         /* Return code */
  i64 nByte;                      /* Size of database file in byte */
  u8 aBuffer[sizeof(BtDbHdrCksum)];
  u8 *aData = 0;

  if( iFrame==0 ){
    rc = p->pVfs->xSize(p->pFd, &nByte);
    if( rc==SQLITE4_OK && nByte>0 ){
      rc = p->pVfs->xRead(p->pFd, 0, aBuffer, sizeof(BtDbHdrCksum));
      aData = aBuffer;
    }
  }else{
    i64 iOff = btLogFrameOffset(pLog, pLog->snapshot.dbhdr.pgsz, iFrame);
    iOff += sizeof(BtFrameHdr);
    rc = p->pVfs->xRead(pLog->pFd, iOff, aBuffer, sizeof(BtDbHdrCksum));
    aData = aBuffer;
  }

  if( rc==SQLITE4_OK ){
    rc = btLogDecodeDbhdr(pLog, aData, pHdr);
  }
  return rc;
}

static int btLogUpdateDbhdr(BtLog *pLog, u8 *aData){
  BtDbHdrCksum hdr;

  memcpy(&hdr.hdr, &pLog->snapshot.dbhdr, sizeof(BtDbHdr));
  btLogChecksum32(1, (u8*)&hdr, offsetof(BtDbHdrCksum, aCksum), 0, hdr.aCksum);
  btDebugDbhdr(pLog->pLock, "update", &pLog->snapshot.dbhdr);

  assert( hdr.hdr.iRoot==2 );
  assert( hdr.hdr.pgsz>0 );
  memcpy(aData, &hdr, sizeof(BtDbHdrCksum));

#ifndef NDEBUG
  {
    BtDbHdr tst;
    btLogDecodeDbhdr(pLog, aData, &tst);
    assert( 0==memcmp(&tst, &pLog->snapshot.dbhdr, sizeof(tst)) );
  }
#endif

  return SQLITE4_OK;
}


/*
** Run log recovery. In other words, read the log file from disk and 
** initialize the shared-memory accordingly.
*/
static int btLogRecover(BtLog *pLog){
  bt_env *pVfs = pLog->pLock->pVfs;
  i64 nByte = 0;                  /* Size of log file on disk */
  int rc;                         /* Return code */
  BtWalHdr *pHdr = 0;
  int iSlot = 0;
  FrameRecoverCtx ctx = {0, 0};
  BtWalHdr hdr1;
  BtWalHdr hdr2;

static int nCall = 0;
nCall++;

  /* Read a log file header from the start of the file. */
  rc = pVfs->xSize(pLog->pFd, &nByte);
  if( rc==SQLITE4_OK && nByte>0 ){
    rc = btLogReadHeader(pLog, 0, &hdr1);
    if( rc==SQLITE4_OK ){
      rc = btLogReadHeader(pLog, hdr1.nSector, &hdr2);
      if( rc==SQLITE4_NOTFOUND ){
        pHdr = &hdr1;
      }else if( rc==SQLITE4_OK ){
        int aGreater[3] = {1, 2, 0};
        pHdr = ((hdr2.iCnt==aGreater[hdr1.iCnt]) ? &hdr2 : &hdr1);
      }
      iSlot = (pHdr==&hdr2);
    }else if( rc==SQLITE4_NOTFOUND ){
      int iOff;
      for(iOff=256; iOff<=65536 && rc==SQLITE4_NOTFOUND; iOff=iOff*2){
        rc = btLogReadHeader(pLog, iOff, &hdr1);
      }
      if( rc==SQLITE4_OK ){
        pHdr = &hdr1;
        iSlot = 1;
      }
    }
    if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;
  }

  /* If a header was successfully read from the file, attempt to 
  ** recover frames from the log file. */
  if( pHdr ){

    /* The following iterates through all readable frames in the log file.
    ** It populates pLog->snapshot.aLog[] with the log topology and the
    ** shared hash-tables with the pgno->frame mapping. The FrameRecoverCtx
    ** object is populated with the frame number and "next frame" pointer of
    ** the last commit-frame in the log (if any). Additionally, the
    ** pLog->snapshot.aFrameCksum[] variables are populated with the checksum
    ** beloging to the frame header of the last commit-frame in the log.  */
    rc = btLogTraverse(pLog, pHdr, btLogRecoverFrame, (void*)&ctx);

    if( rc==SQLITE4_OK && ctx.iLast>0 ){
      /* One or more transactions were recovered from the log file. */
      BtShm *pShm = btLogShm(pLog);
      pShm->ckpt.iWalHdr = (iSlot<<2) + pHdr->iCnt;
      pShm->ckpt.iFirstRead = pHdr->iFirstFrame;
      pShm->ckpt.iFirstRecover = pHdr->iFirstFrame;
      rc = btLogRollbackRecovery(pLog, &ctx);
      pLog->snapshot.iNextFrame = ctx.iNextFrame;
      pLog->snapshot.dbhdr.pgsz = pHdr->nPgsz;
      assert( pShm->ckpt.iFirstRead>0 );
    }
    assert( rc!=SQLITE4_NOTFOUND );

    /* Based on the wal-header, the page-size and number of pages in the
    ** database are now known and stored in snapshot.dbhdr. But the other
    ** header field values (iCookie, iRoot etc.) are still unknown. Read
    ** them from page 1 of the database file now.  */
    if( rc==SQLITE4_OK ){
      u32 nPg = pLog->snapshot.dbhdr.nPg;
      rc = btLogReadDbhdr(pLog, &pLog->snapshot.dbhdr, ctx.iPageOneFrame);
      if( ctx.iLast>0 ){
        pLog->snapshot.dbhdr.nPg = nPg;
      }
    }

  }else if( rc==SQLITE4_OK ){
    /* There is no data in the log file. Read the database header directly
    ** from offset 0 of the database file.  */
    btLogZeroSnapshot(pLog);
    rc = btLogReadDbhdr(pLog, &pLog->snapshot.dbhdr, 0);
  }

  if( rc==SQLITE4_NOTFOUND ){
    /* Check the size of the db file. If it is greater than zero bytes in
    ** size, refuse to open the file (as it is probably not a database
    ** file). Or, if it is exactly zero bytes in size, this is a brand
    ** new database.  */
    rc = pVfs->xSize(pLog->pLock->pFd, &nByte);
    if( rc==SQLITE4_OK ){
      if( nByte==0 ){
        btLogZeroDbhdr(pLog, &pLog->snapshot.dbhdr);
      }else{
        rc = btErrorBkpt(SQLITE4_NOTADB);
      }
    }
  }

  if( rc==SQLITE4_OK ){
    btDebugTopology(
        pLog->pLock, "recovered", pLog->snapshot.iHashSide, pLog->snapshot.aLog
    );

    btDebugDbhdr(pLog->pLock, "read", &pLog->snapshot.dbhdr);
  }
  return rc;
}

/*
** Open the log file for pager pPager. If successful, return the BtLog* 
** handle via output variable *ppLog. If parameter bRecover is true, then
** also run database recovery before returning. In this case, the caller
** has already obtained the required locks.
*/
SQLITE4_PRIVATE int sqlite4BtLogOpen(BtPager *pPager, int bRecover, BtLog **ppLog){
  BtLock *pLock = (BtLock*)pPager;
  bt_env *pVfs = pLock->pVfs;
  sqlite4_env *pEnv = pLock->pEnv;
  int rc;                         /* Return code */
  const char *zWal;               /* Name of log file to open */
  BtLog *pLog;                    /* Log handle to return */
  int flags = BT_OPEN_LOG;

  pLog = sqlite4_malloc(pEnv, sizeof(BtLog));
  if( pLog==0 ){
    rc = SQLITE4_NOMEM;
    goto open_out;
  }
  memset(pLog, 0, sizeof(BtLog));
  pLog->pLock = (BtLock*)pPager;
  pLog->nWrapLog = BT_NWRAPLOG;

  zWal = sqlite4BtPagerFilename(pPager, BT_PAGERFILE_LOG);
  rc = pVfs->xOpen(pEnv, pVfs, zWal, flags, &pLog->pFd);

  if( rc==SQLITE4_OK && bRecover ){
    rc = btLogMapShm(pLog, 0);
    if( rc==SQLITE4_OK ){
      BtShm *pShm = btLogShm(pLog);
      memset(pShm, 0, sizeof(BtShm));
      pShm->ckpt.iFirstRead = 1;
      pShm->ckpt.iFirstRecover = 1;
      btLogZeroSnapshot(pLog);
      rc = btLogRecover(pLog);
    }
    if( rc==SQLITE4_OK ){
      rc = btLogUpdateSharedHdr(pLog);
    }
  }

 open_out:
  if( rc!=SQLITE4_OK ){
    sqlite4BtLogClose(pLog, 0);
    pLog = 0;
  }
  *ppLog = pLog;
  return rc;
}

/*
** Close the log file handle BtLog*. 
*/
SQLITE4_PRIVATE int sqlite4BtLogClose(BtLog *pLog, int bCleanup){
  int rc = SQLITE4_OK;
  if( pLog ){
    sqlite4_env *pEnv = pLog->pLock->pEnv;
    bt_env *pVfs = pLog->pLock->pVfs;

    if( pLog->pFd ) pVfs->xClose(pLog->pFd);
    if( bCleanup ){
      BtPager *pPager = (BtPager*)pLog->pLock;
      const char *zWal = sqlite4BtPagerFilename(pPager, BT_PAGERFILE_LOG);
      rc = pVfs->xUnlink(pEnv, pVfs, zWal);
    }

    sqlite4_free(pEnv, pLog->apShm);
    sqlite4_free(pEnv, pLog);
  }

  return rc;
}

static int btLogWriteHeader(BtLog *pLog, int iHdr, BtWalHdr *pHdr){
  int rc;                         /* Return code */
  i64 iOff;                       /* File offset to write to */
  assert( iHdr==0 || iHdr==1 );

  btDebugLogHeader(pLog->pLock, "write", pHdr, iHdr);

  /* Calculate a checksum for the header */
  btLogChecksum(1, (u8*)pHdr, offsetof(BtWalHdr, aCksum), 0, pHdr->aCksum);

  /* Write the object to disk */
  iOff = iHdr * pLog->snapshot.nSector;
  rc = btLogWriteData(pLog, iOff, (u8*)pHdr, sizeof(BtWalHdr));

  return rc;
}

static int btLogHashSearch(
  BtLog *pLog,                    /* Log module handle */
  int iSide,                      /* 0 or 1 - the side of hash table to read */
  int iHash,                      /* Index of hash to query */
  u32 iHi,                        /* Consider no frames after this one */
  u32 pgno,                       /* query for this page number */
  u32 *piFrame                    /* OUT: Frame number for matching entry */
){
  ht_slot *aHash;
  u32 *aPgno;
  u32 iZero;
  int rc;

  rc = btLogFindHash(pLog, iSide, iHash, &aHash, &aPgno, &iZero);
  if( rc==SQLITE4_OK ){
    int nCollide = HASHTABLE_NSLOT*2;
    int iSlot;
    u32 iFrame = 0;
    
    iSlot = btLogHashKey(pLog, pgno); 
    for( ; aHash[iSlot]; iSlot=btLogHashNext(pLog, iSlot)){
      if( aPgno[aHash[iSlot]-1]==pgno ){
        u32 iCandidate = iZero + aHash[iSlot] - 1;
        if( iCandidate<=iHi ) iFrame = iCandidate;
      }
      if( (nCollide--)==0 ) return btErrorBkpt(SQLITE4_CORRUPT);
    }

    *piFrame = iFrame;
    if( iFrame==0 ){
      rc = SQLITE4_NOTFOUND;
    }
  }

  return rc;
}

/*
** If parameter iSafe is non-zero, then this function is being called as
** part of a checkpoint operation. In this case, if there exists a version
** of page pgno within the log at some point past frame iSafe, return
** SQLITE4_NOTFOUND.
*/
int btLogRead(BtLog *pLog, u32 pgno, u8 *aData, u32 iSafe){
  const int pgsz = pLog->snapshot.dbhdr.pgsz;
  int rc = SQLITE4_NOTFOUND;
  u32 iFrame = 0;
  int i;

  u32 *aLog = pLog->snapshot.aLog;
  int iSafeIdx = sqlite4BtLogFrameToIdx(aLog, iSafe);

  /* Loop through regions (c), (b) and (a) of the log file. In that order. */
  for(i=2; i>=0 && rc==SQLITE4_NOTFOUND; i--){
    u32 iLo = pLog->snapshot.aLog[i*2+0];
    if( iLo ){
      u32 iHi = pLog->snapshot.aLog[i*2+1];
      int iSide;
      int iHash;
      int iHashLast;

      iHash = btLogFrameHash(pLog, iHi);
      iHashLast = btLogFrameHash(pLog, iLo);
      iSide = (pLog->snapshot.iHashSide + (i==0)) % 2;

      for( ; rc==SQLITE4_NOTFOUND && iHash>=iHashLast; iHash--){
        rc = btLogHashSearch(pLog, iSide, iHash, iHi, pgno, &iFrame);
        if( rc==SQLITE4_OK ){
          if( iFrame<iLo || iFrame>iHi ){
            rc = SQLITE4_NOTFOUND;
          }else{
            assert( sqlite4BtLogFrameToIdx(aLog, iFrame)>=0 );
            if( iSafeIdx>=0 && sqlite4BtLogFrameToIdx(aLog, iFrame)>iSafeIdx ){
              return SQLITE4_NOTFOUND;
            }
          }
        }
      }
    }
  }

  btDebugLogSearch(pLog->pLock, pgno, iSafe, (rc==SQLITE4_OK ? iFrame : 0));

  if( rc==SQLITE4_OK ){
    bt_env *pVfs = pLog->pLock->pVfs;
    i64 iOff;
    assert( rc==SQLITE4_OK );
    iOff = btLogFrameOffset(pLog, pgsz, iFrame);
    rc = pVfs->xRead(pLog->pFd, iOff + sizeof(BtFrameHdr), aData, pgsz);

#if 0
    fprintf(stderr, "read page %d from offset %d\n", (int)pgno, (int)iOff);
    fflush(stderr);
#endif
  }

  return rc;
}

/*
** Attempt to read data for page pgno from the log file. If successful,
** the data is written into buffer aData[] (which must be at least as
** large as a database page). In this case SQLITE4_OK is returned.
**
** If the log does not contain any version of page pgno, SQLITE4_NOTFOUND
** is returned and the contents of buffer aData[] are not modified.
**
** If any other error occurs, an SQLite4 error code is returned. The final
** state of buffer aData[] is undefined in this case.
*/
SQLITE4_PRIVATE int sqlite4BtLogRead(BtLog *pLog, u32 pgno, u8 *aData){
  if( pLog->snapshot.aLog[4]==0 ){
    assert( pLog->snapshot.aLog[0]==0 && pLog->snapshot.aLog[2]==0 );
    return SQLITE4_NOTFOUND;
  }
  return btLogRead(pLog, pgno, aData, 0);
}

static int btLogZeroHash(BtLog *pLog, int iHash){
  int iSide = pLog->snapshot.iHashSide;
  ht_slot *aHash;
  u32 *aPgno;
  u32 iZero;
  int rc;

  rc = btLogFindHash(pLog, iSide, iHash, &aHash, &aPgno, &iZero);
  if( rc==SQLITE4_OK ){
    memset(aHash, 0, sizeof(ht_slot)*HASHTABLE_NSLOT);
  }
  return rc;
}

static int btLogWriteFrame(BtLog *pLog, int nPad, u32 pgno, u8 *aData, u32 nPg){
  const int pgsz = pLog->snapshot.dbhdr.pgsz;
  u32 *aLog = pLog->snapshot.aLog;
  int rc = SQLITE4_OK;            /* Return code */
  u32 iFrame;                     /* Write this frame (numbered from 1) */
  u32 iNextFrame;                 /* Frame to write following this one */
  i64 iOff;                       /* Offset of log file to write to */
  BtFrameHdr frame;               /* Header for new frame */

  /* Figure out the offset to write the current frame to. */
  iFrame = pLog->snapshot.iNextFrame;
  iOff = btLogFrameOffset(pLog, pgsz, iFrame);

  /* The current frame will be written to location pLog->snapshot.iNextFrame.
  ** This code determines where the following frame will be stored. There
  ** are three possibilities:
  **
  **   1) The next frame follows the current frame (this is the usual case).
  **   2) The next frame is frame 1 - the log wraps around.
  **   3) Following the current frame is a block of frames still in use.
  **      So the next frame will immediately follow this block.
  */
  iNextFrame = pLog->snapshot.iNextFrame + 1;
  if( iFrame!=1 && iFrame==aLog[5]+1
   && aLog[0]==0 && aLog[2]==0 
   && aLog[4]!=0 && aLog[4]>pLog->nWrapLog 
  ){
    /* Case 2) It is possible to wrap the log around */
    iNextFrame = 1;
  }else if( (iNextFrame+nPad)>=aLog[0] && iNextFrame<=aLog[1] ){

    /* Case 3) It is necessary to jump over some existing log. */
    iNextFrame = aLog[1]+nPad+1;
    assert( iNextFrame!=1 );

    if( btLogFrameHash(pLog, iNextFrame)!=btLogFrameHash(pLog, iFrame) ){
      rc = btLogZeroHash(pLog, btLogFrameHash(pLog, iNextFrame));
    }
  }

  if( rc==SQLITE4_OK ){
    if( iNextFrame & 0x80000000 ){
      rc = SQLITE4_FULL;
    }else{
      u32 *a;                     /* Pointer to cksum of previous frame */

      /* Populate the frame header object. */
      memset(&frame, 0, sizeof(frame));
      frame.pgno = pgno;
      frame.iNext = iNextFrame;
      frame.nPg = nPg;
      a = pLog->snapshot.aFrameCksum;
      btLogChecksum32(1,(u8*)&frame,offsetof(BtFrameHdr,aCksum),a,frame.aCksum);
      btLogChecksum(1, aData, pgsz, frame.aCksum, frame.aCksum);

      btDebugLogPage(pLog->pLock, pgno, iFrame, aData, pgsz, nPg);

      /* Write the frame header to the log file. */
      rc = btLogWriteData(pLog, iOff, (u8*)&frame, sizeof(frame));
    }
    pLog->snapshot.iNextFrame = iNextFrame;
  }

  /* Write the frame contents to the log file. */
  if( rc==SQLITE4_OK ){
    rc = btLogWriteData(pLog, iOff+sizeof(frame), aData, pgsz);
  }

  /* Update the wal index hash tables with the (pgno -> iFrame) record. 
  ** If this is a commit frame, update the nPg field as well. */
  if( rc==SQLITE4_OK ){
    if( iFrame==1 ){
      pLog->snapshot.iHashSide = (pLog->snapshot.iHashSide+1) % 2;
    }
    if( nPg ) pLog->snapshot.dbhdr.nPg = nPg;

    rc = btLogHashInsert(pLog, pgno, iFrame);
  }

  /* Update the private copy of the shm-header */
  btDebugCheckSnapshot(&pLog->snapshot);
  BtShmHdr hdr;
  memcpy(&hdr, &pLog->snapshot, sizeof(BtShmHdr));
  if( rc==SQLITE4_OK ){
    if( btLogIsEmpty(pLog) ){
      assert( iFrame==1 );
      aLog[4] = iFrame;
    }else if( iFrame==1 ){
      assert( aLog[0]==0 && aLog[1]==0 && aLog[2]==0 && aLog[3]==0 );
      aLog[0] = aLog[4];
      aLog[1] = aLog[5];
      aLog[4] = iFrame;
    }else if( iFrame!=aLog[5]+1 ){
      assert( iFrame>aLog[5] );
      assert( aLog[2]==0 && aLog[3]==0 );
      aLog[2] = aLog[4];
      aLog[3] = aLog[5];
      aLog[4] = iFrame;
    }

    aLog[5] = iFrame;
    memcpy(pLog->snapshot.aFrameCksum, frame.aCksum, sizeof(frame.aCksum));
  }
  btDebugCheckSnapshot(&pLog->snapshot);

  return rc;
}

/*
** Write a frame to the log file.
*/
SQLITE4_PRIVATE int sqlite4BtLogWrite(BtLog *pLog, u32 pgno, u8 *aData, u32 nPg){
  const int pgsz = pLog->snapshot.dbhdr.pgsz;
  int rc = SQLITE4_OK;

  int nPad = 0;
  if( pLog->pLock->iSafetyLevel==BT_SAFETY_FULL ){
    nPad = (pLog->snapshot.nSector + pgsz-1) / pgsz;
  }

  /* If this is a commit frame and the size of the database has changed,
  ** ensure that the log file contains at least one copy of page 1 written
  ** since the last checkpoint. This is required as a future checkpoint
  ** will need to update the nPg field in the database header located on
  ** page 1. */
  if( nPg /* && nPg!=pLog->snapshot.dbhdr.nPg */ ){
    BtPager *pPager = (BtPager *)(pLog->pLock);
    BtPage *pOne = 0;
    rc = sqlite4BtPageGet(pPager, 1, &pOne);
    if( rc==SQLITE4_OK ){
      rc = sqlite4BtLogWrite(pLog, 1, sqlite4BtPageData(pOne), 0);
      sqlite4BtPageRelease(pOne);
    }
    if( rc!=SQLITE4_OK ) return rc;
  }

  /* Handle a special case - if the log file is completely empty then
  ** this writer must write the first header into the WAL file. */
  if( btLogIsEmpty(pLog) ){
    BtWalHdr hdr;
    memset(&hdr, 0, sizeof(BtWalHdr));

    hdr.iMagic = BT_WAL_MAGIC;
    hdr.iVersion = BT_WAL_VERSION;
    hdr.nSector = pLog->snapshot.nSector;
    hdr.nPgsz = pgsz;
    hdr.iSalt1 = 22;
    hdr.iSalt2 = 23;
    hdr.iFirstFrame = 1;

    rc = btLogWriteHeader(pLog, 0, &hdr);
    if( rc!=SQLITE4_OK ) return rc;

    pLog->snapshot.aFrameCksum[0] = hdr.iSalt1;
    pLog->snapshot.aFrameCksum[1] = hdr.iSalt2;
    pLog->snapshot.iNextFrame = 1;
  }
  btDebugCheckSnapshot(&pLog->snapshot);

  rc = btLogWriteFrame(pLog, nPad, pgno, aData, nPg);

  /* If this is a COMMIT, sync the log and update the shared shm-header. */
  if( nPg ){
    int i;
    for(i=0; i<nPad && rc==SQLITE4_OK; i++){
      rc = btLogWriteFrame(pLog, nPad, pgno, aData, nPg);
    }
    if( rc==SQLITE4_OK && pLog->pLock->iSafetyLevel==BT_SAFETY_FULL ){
      rc = btLogSyncFile(pLog, pLog->pFd);
    }
    if( rc==SQLITE4_OK ) rc = btLogUpdateSharedHdr(pLog);
  }

  return rc;
}

/*
** Return true if the checksum in BtShmHdr.aCksum[] matches the rest
** of the object.
*/
static int btLogChecksumOk(BtShmHdr *pHdr){
  u32 aCksum[2];
  btLogChecksum32(1, (u8*)pHdr, offsetof(BtShmHdr, aCksum), 0, aCksum);
  return (aCksum[0]==pHdr->aCksum[0] && aCksum[1]==pHdr->aCksum[1]);
}

static int btLogSnapshot(BtLog *pLog, BtShmHdr *pHdr){
  int rc;

  rc = btLogMapShm(pLog, 0);
  if( rc==SQLITE4_OK ){
    BtShm *pShm = btLogShm(pLog);
    int nAttempt = 500;

    while( (nAttempt--)>0 ){
      memcpy(pHdr, &pShm->hdr1, sizeof(BtShmHdr));
      if( btLogChecksumOk(pHdr) ) break;
      memcpy(pHdr, &pShm->hdr2, sizeof(BtShmHdr));
      if( btLogChecksumOk(pHdr) ) break;
    }

    if( nAttempt==0 ) rc = SQLITE4_PROTOCOL;
  }

  return rc;
}

static void btLogSnapshotTrim(u32 *aLog, u32 iFirst){
  if( iFirst ){
    int iRegion;
    for(iRegion=0; iRegion<3; iRegion++){
      if( aLog[iRegion*2] ){
        if( iFirst>=aLog[iRegion*2] && iFirst<=aLog[iRegion*2+1] ){
          aLog[iRegion*2] = iFirst;
          break;
        }else{
          aLog[iRegion*2] = 0;
          aLog[iRegion*2+1] = 0;
        }
      }
    }
  }
}

SQLITE4_PRIVATE int sqlite4BtLogSnapshotOpen(BtLog *pLog){
  u32 *aLog = pLog->snapshot.aLog;
  int rc = SQLITE4_NOTFOUND;
  BtShmHdr shmhdr;
  u32 iFirstRead = 0;

  while( rc==SQLITE4_NOTFOUND ){
    BtShm *pShm;

    /* Attempt to read a copy of the BtShmHdr from shared-memory. */
    rc = btLogSnapshot(pLog, &pLog->snapshot);
    btDebugCheckSnapshot(&pLog->snapshot);

    /* Take a read lock on the database */
    if( rc==SQLITE4_OK ){
      BtReadSlot *aReadlock;
      pShm = btLogShm(pLog);

      aReadlock = pShm->aReadlock;
      iFirstRead = pShm->ckpt.iFirstRead;
      rc = sqlite4BtLockReader(pLog->pLock, aLog, iFirstRead, aReadlock);
    }

    /* Check that the BtShmHdr in shared-memory has not changed. If it has,
    ** drop the read-lock and re-attempt the entire operation. */
    if( rc==SQLITE4_OK ){
      rc = btLogSnapshot(pLog, &shmhdr);
    }
    if( rc==SQLITE4_OK ){
      if( iFirstRead!=pShm->ckpt.iFirstRead 
       || memcmp(&shmhdr, &pLog->snapshot, sizeof(BtShmHdr)) 
      ){
        rc = SQLITE4_NOTFOUND;
      }
    }
    
    if( rc!=SQLITE4_OK ){
      sqlite4BtLockReaderUnlock(pLog->pLock);
    }
  }

  if( rc==SQLITE4_OK ){
    btDebugTopology(
        pLog->pLock, "snapshotA", pLog->snapshot.iHashSide, pLog->snapshot.aLog
    );
  }

  /* If a snapshot was successfully read, adjust it so that the aLog[] 
  ** array specifies that no frames before iFirstRead is ever read from 
  ** the log file.  */
  if( rc==SQLITE4_OK ){
    btLogSnapshotTrim(aLog, iFirstRead);
  }

  if( rc==SQLITE4_OK ){
    btDebugTopology(
        pLog->pLock, "snapshotB", pLog->snapshot.iHashSide, pLog->snapshot.aLog
    );
  }

  return rc;
}

SQLITE4_PRIVATE int sqlite4BtLogSnapshotClose(BtLog *pLog){
  sqlite4BtLockReaderUnlock(pLog->pLock);
  return SQLITE4_OK;
}

/*
** The log handle has already successfully opened a read-only snapshot
** when this function is called. This function attempts to upgrade it
** to a read-write snapshot. 
*/
SQLITE4_PRIVATE int sqlite4BtLogSnapshotWrite(BtLog *pLog){
  BtLock *pLock = pLog->pLock;
  int rc;

  rc = sqlite4BtLockWriter(pLock);
  if( rc==SQLITE4_OK ){
    BtShm *pShm = btLogShm(pLog);
    BtShmHdr shmhdr;

    /* Check if this connection is currently reading from the latest
    ** database snapshot. Set rc to SQLITE4_BUSY if it is not.  */
    rc = btLogSnapshot(pLog, &shmhdr);
    if( rc==SQLITE4_OK && memcmp(&pShm->hdr1, &pShm->hdr2, sizeof(BtShmHdr)) ){
      memcpy(&pShm->hdr1, &shmhdr, sizeof(BtShmHdr));
      memcpy(&pShm->hdr2, &shmhdr, sizeof(BtShmHdr));
    }
    if( rc==SQLITE4_OK && pLog->snapshot.iNextFrame!=shmhdr.iNextFrame ){
      rc = SQLITE4_BUSY;
    }

    /* Currently, pLog->snapshot.aLog[] contains a map of the frames
    ** that this connection was required to consider in order to read
    ** from the read-only snapshot. The following block edits this so
    ** that it contains a map of all frames that are currently in use
    ** by any reader, or may be used by any future reader or recovery
    ** process.  */
    if( rc==SQLITE4_OK ){
      u32 *aLog = shmhdr.aLog;
      u32 iRecover = pShm->ckpt.iFirstRecover;
      u32 iRead = 0;

      btDebugTopology(pLog->pLock, "snapshotC", shmhdr.iHashSide, aLog);

      assert( shmhdr.iHashSide==pLog->snapshot.iHashSide );
      btDebugCheckSnapshot(&pLog->snapshot);

      rc = sqlite4BtLockReaderQuery(pLock, aLog, pShm->aReadlock, &iRead, 0);

      if( rc==SQLITE4_OK ){
        /* Now "trim" the snapshot so that it accesses nothing earlier than
        ** either iRecover or iRead (whichever occurs first in the log). */
        u32 iTrim = iRecover;
        if( iRead ){
          int iIdxRead = sqlite4BtLogFrameToIdx(aLog, iRead);
          if( sqlite4BtLogFrameToIdx(aLog, iRecover)>iIdxRead ) iTrim = iRead;
        }

        if( iTrim==0 || iTrim==shmhdr.iNextFrame || btLogIsEmpty(pLog) ){
          memset(aLog, 0, sizeof(u32)*6);
        }else{
          int i;
          for(i=0; i<3; i++){
            int bIn = (aLog[2*i]<=iTrim && iTrim<=aLog[2*i+1]);
            if( bIn ){
              aLog[2*i] = iTrim;
              break;
            }else{
              aLog[2*i] = aLog[2*i+1] = 0;
            }
          }
        }
      }

      btDebugTopology(pLog->pLock, "snapshotD", shmhdr.iHashSide, aLog);

      if( rc==SQLITE4_OK ){
        memcpy(pLog->snapshot.aLog, aLog, sizeof(u32)*6);
      }
      btDebugCheckSnapshot(&pLog->snapshot);
    }
  }

  return rc;
}

SQLITE4_PRIVATE int sqlite4BtLogSnapshotEndWrite(BtLog *pLog){
  return sqlite4BtLockWriterUnlock(pLog->pLock);
}

static void btLogMergeInplace(
  u32 *aLeft, int nLeft,          /* Left hand input array */
  u32 *aRight, int nRight,        /* Right hand input array */
  u32 *aSpace,                    /* Temporary space */
  int *pnOut                      /* OUT: Size of aLeft[] after merge */
){
  int iLeft = 0;
  int iRight = 0;
  int iOut = 0;

  while( iLeft<nLeft || iRight<nRight ){
    u32 v;
    if( iRight==nRight || (iLeft<nLeft && aLeft[iLeft]<aRight[iRight]) ){
      assert( iLeft<nLeft );
      v = aLeft[iLeft++];
    }else{
      assert( iRight<nRight );
      v = aRight[iRight++];
    }
    if( v && (iOut==0 || v!=aSpace[iOut-1]) ) aSpace[iOut++] = v;
  }

  memcpy(aLeft, aSpace, iOut*sizeof(u32));
  memset(&aLeft[iOut], 0, ((nLeft+nRight)-iOut) * sizeof(u32));
  *pnOut = iOut;
}

static void btLogMergeSort(
  u32 *aPgno,                     /* Array to sort */
  int *pnPgno,                    /* IN/OUT: Number of entries in aPgno[] */
  u32 *aSpace                     /* Temporary space */
){
  int nMerge;
  int nPgno = *pnPgno;

  for(nMerge=1; nMerge<nPgno; nMerge=nMerge*2){
    int iLeft;
    for(iLeft=0; iLeft<nPgno; iLeft+=(nMerge*2)){
      u32 *aLeft = &aPgno[iLeft];
      int nLeft = MIN(nMerge, nPgno-iLeft);
      u32 *aRight = &aPgno[iLeft+nMerge];
      int nRight = MIN(nMerge, nPgno-iLeft-nLeft);
      btLogMergeInplace(aLeft, nLeft, aRight, nRight, aSpace, pnPgno);
    }
  }
}

SQLITE4_PRIVATE int sqlite4BtLogFrameToIdx(u32 *aLog, u32 iFrame){
  int i;
  int iRet = 0;
  for(i=0; i<3; i++){
    u32 iFirst = aLog[i*2];
    u32 iLast = aLog[i*2+1];
    if( iFirst ){
      if( iFrame>=iFirst && iFrame<=iLast ){
        iRet += (iFrame - iFirst);
        return iRet;
      }else{
        iRet += (iLast - iFirst) + 1;
      }
    }
  }
  if( i==3 ) return -1;
  return iRet;
}

/*
** Parameters iFirst and iLast are frame numbers for frames that are part 
** of the current log. This function scans the wal-index from iFirst to
** iLast (inclusive) and records the set of page numbers that occur once.
** This set is sorted in ascending order and returned via the output 
** variables *paPgno and *pnPgno.
*/
static int btLogGatherPgno(
  BtLog *pLog,                    /* Log module handle */
  int nFrameBuffer,
  u32 **paPgno,                   /* OUT: s4_malloc'd array of sorted pgno */
  int *pnPgno,                    /* OUT: Number of entries in *paPgno */
  u32 *piLastFrame                /* OUT: Last frame checkpointed */
){
  BtShm *pShm = btLogShm(pLog);
  BtLock *pLock = pLog->pLock;
  u32 *aLog = pLog->snapshot.aLog;/* Log file topology */
  u32 i;
  u32 *aPgno;                     /* Returned array */
  int nPgno;                      /* Elements in aPgno[] */
  u32 *aSpace;                    /* Temporary space used by merge-sort */
  int nMax;
  int rc = SQLITE4_OK;
  int iRegion;
  int bLocked;
  u32 iSafe;                      /* Last frame in log it is safe to gather */

  int iSafeIdx = -1;
  int iFirstIdx = -1;
  int iBufIdx;
  int iIdx = 0;

  *paPgno = 0;
  *pnPgno = 0;
  *piLastFrame = 0;

  rc = sqlite4BtLockReaderQuery(pLock, aLog, pShm->aReadlock, &iSafe, &bLocked);
  if( rc!=SQLITE4_OK || bLocked ) return rc;
  btDebugLogSafepoint(pLock, iSafe);
  btDebugTopology(
      pLock, "checkpointer", pLog->snapshot.iHashSide, pLog->snapshot.aLog
  );

  iFirstIdx = sqlite4BtLogFrameToIdx(aLog, pShm->ckpt.iFirstRecover);
  iSafeIdx = sqlite4BtLogFrameToIdx(aLog, iSafe);
  iBufIdx = sqlite4BtLogFrameToIdx(aLog, pLog->snapshot.aLog[5]) - nFrameBuffer;
  if( iSafeIdx<0 || iBufIdx<iSafeIdx ) iSafeIdx = iBufIdx;
  if( iSafeIdx<0 || (iFirstIdx>=0 && iSafeIdx<iFirstIdx) ) return rc;

  /* Determine an upper limit on the number of distinct page numbers. This
  ** limit is used to allocate space for the returned array.  */
  nMax = iSafeIdx - iFirstIdx +1;

  /* Allocate space to collect all page numbers. */
  aPgno = (u32*)sqlite4_malloc(pLog->pLock->pEnv, sizeof(u32)*nMax*2);
  if( aPgno==0 ) rc = btErrorBkpt(SQLITE4_NOMEM);
  aSpace = &aPgno[nMax];
  nPgno = 0;

  /* Copy the required page numbers into the allocated array */
  for(iRegion=0; iRegion<3; iRegion++){
    u32 iFirst = aLog[iRegion*2];
    u32 iLast = aLog[iRegion*2+1];
    if( iFirst ){

      for(i=iFirst; rc==SQLITE4_OK && i<=iLast; i++, iIdx++){
        int iHash = btLogFrameHash(pLog, i);
        u32 *aPage;
        ht_slot *aHash;
        u32 iZero;

        /* Ensure that the checkpoint does not read any frames from the 
        ** log that occur earlier than iFirstRecover. This is not just 
        ** an optimization - there is a chance that such frames may be 
        ** overwritten by a writer running concurrently with this 
        ** checkpoint.  */
        if( (iFirstIdx>=0 && iIdx<iFirstIdx) 
         || (iSafeIdx>=0 && iIdx>iSafeIdx) 
        ){
          continue;
        }
        *piLastFrame = i;

        /* It doesn't matter which 'side' of the hash table is requested here,
        ** as only the page-number array, not the aHash[] table, will be used.
        ** And it is the same for both sides. Hence the constant 0 passed as
        ** the second argument to btLogFindHash().  */
        rc = btLogFindHash(pLog, 0, iHash, &aHash, &aPage, &iZero);
        if( rc==SQLITE4_OK ){
          aPgno[nPgno++] = aPage[i-iZero];
        }
      }
    }
  }

  /* Sort the contents of the array in ascending order. This step also 
  ** eliminates any  duplicate page numbers. */
  if( rc==SQLITE4_OK ){
    btLogMergeSort(aPgno, &nPgno, aSpace);
    *pnPgno = nPgno;
    *paPgno = aPgno;
  }else{
    sqlite4_free(pLog->pLock->pEnv, aPgno);
    *paPgno = 0;
    *pnPgno = 0;
  }

  return rc;
}

/*
** Return the number of frames in the log file that have not yet been
** copied into the database file, according to the current snapshot.
**
** todo: adjust result for iFirstRead/iFirstRecover.
*/
SQLITE4_PRIVATE int sqlite4BtLogSize(BtLog *pLog){
  return 
      (int)pLog->snapshot.aLog[1] - (int)pLog->snapshot.aLog[0]
    + (pLog->snapshot.aLog[0]!=0)
    + (int)pLog->snapshot.aLog[3] - (int)pLog->snapshot.aLog[2]
    + (pLog->snapshot.aLog[3]!=0)
    + (int)pLog->snapshot.aLog[5] - (int)pLog->snapshot.aLog[4]
    + (pLog->snapshot.aLog[5]!=0)
  ;
}

static int btLogMerge(BtLog *pLog, u8 *aBuf){
  bt_db *db = (bt_db*)sqlite4BtPagerExtra((BtPager*)pLog->pLock);
  return sqlite4BtMerge(db, &pLog->snapshot.dbhdr, aBuf);
}

SQLITE4_PRIVATE int sqlite4BtLogCheckpoint(BtLog *pLog, int nFrameBuffer){
  BtLock *pLock = pLog->pLock;
  int rc;

  /* Take the CHECKPOINTER lock. */
  rc = sqlite4BtLockCkpt(pLock);
  if( rc==SQLITE4_OK ){
    int pgsz;
    bt_env *pVfs = pLock->pVfs;
    bt_file *pFd = pLock->pFd;
    BtShm *pShm;                  /* Pointer to shared-memory region */
    u32 iLast;                    /* Last frame to checkpoint */
    BtFrameHdr fhdr;              /* Frame header of frame iLast */
    u32 *aPgno = 0;               /* Array of page numbers to checkpoint */
    int nPgno;                    /* Number of entries in aPgno[] */
    int i;                        /* Used to loop through aPgno[] */
    u8 *aBuf;                     /* Buffer to load page data into */
    u32 iFirstRead;               /* First frame not checkpointed */

    rc = btLogSnapshot(pLog, &pLog->snapshot);
    sqlite4BtPagerSetDbhdr((BtPager*)pLock, &pLog->snapshot.dbhdr);
    pgsz = pLog->snapshot.dbhdr.pgsz;

    if( rc==SQLITE4_OK ){
      /* Allocate space to load log data into */
      aBuf = sqlite4_malloc(pLock->pEnv, pgsz);
      if( aBuf==0 ) rc = btErrorBkpt(SQLITE4_NOMEM);
    }
    
    /* Figure out the set of page numbers stored in the part of the log 
    ** file being checkpointed. Remove any duplicates and sort them in 
    ** ascending order.  */
    if( rc==SQLITE4_OK ){
      rc = btLogGatherPgno(pLog, nFrameBuffer, &aPgno, &nPgno, &iLast);
    }

    if( rc==SQLITE4_OK && nPgno>0 ){
      i64 iOff = btLogFrameOffset(pLog, pgsz, iLast);

      /* Ensure the log has been synced to disk */
      if( rc==SQLITE4_OK ){
        rc = btLogSyncFile(pLog, pLog->pFd);
      }

      rc = btLogReadData(pLog, iOff, (u8*)&fhdr, sizeof(BtFrameHdr));
      iFirstRead = fhdr.iNext;

      /* Copy data from the log file to the database file. */
      for(i=0; rc==SQLITE4_OK && i<nPgno; i++){
        u32 pgno = aPgno[i];
        rc = btLogRead(pLog, pgno, aBuf, iLast);
        if( rc==SQLITE4_OK ){
          i64 iOff = (i64)pgsz * (pgno-1);
          if( pgno==1 ){
            rc = btLogUpdateDbhdr(pLog, aBuf);
          }else if( pgno==pLog->snapshot.dbhdr.iSRoot ){
            rc = btLogMerge(pLog, aBuf);
          }
          if( rc==SQLITE4_OK ){
            btDebugCkptPage(pLog->pLock, pgno, aBuf, pgsz);
            rc = pVfs->xWrite(pFd, iOff, aBuf, pgsz);
          }
        }else if( rc==SQLITE4_NOTFOUND ){
          rc = SQLITE4_OK;
        }
      }

      /* Sync the database file to disk. */
      if( rc==SQLITE4_OK ){
        rc = btLogSyncFile(pLog, pLog->pLock->pFd);
      }

      /* Update the first field of the checkpoint-header. This tells readers
      ** that they need not consider anything that in the log before this
      ** point (since the data has already been copied into the database
      ** file).  */
      if( rc==SQLITE4_OK ){
        assert( iFirstRead>0 );
        pShm = btLogShm(pLog);
        pShm->ckpt.iFirstRead = iFirstRead;
        pVfs->xShmBarrier(pLog->pFd);
      }

      /* Write a new header into the log file. This tells any future recovery
      ** where it should start reading the log. Once this new header is synced
      ** to disk, the space cleared by this checkpoint operation can be 
      ** reused.  */
      if( rc==SQLITE4_OK ){
        int iSlot = ((pShm->ckpt.iWalHdr >> 2) + 1) % 2;
        BtWalHdr hdr;

        memset(&hdr, 0, sizeof(BtWalHdr));
        hdr.iMagic = BT_WAL_MAGIC;
        hdr.iVersion = BT_WAL_VERSION;
        hdr.iCnt = (((pShm->ckpt.iWalHdr & 0x03) + 1) % 3);
        hdr.nSector = pLog->snapshot.nSector;
        hdr.nPgsz = pgsz;
        hdr.iFirstFrame = iFirstRead;

        hdr.iSalt1 = fhdr.aCksum[0];
        hdr.iSalt2 = fhdr.aCksum[1];
        rc = btLogWriteHeader(pLog, iSlot, &hdr);
        if( rc==SQLITE4_OK ){
          rc = btLogSyncFile(pLog, pLog->pFd);
        }
        if( rc==SQLITE4_OK ){
          pShm->ckpt.iWalHdr = (iSlot<<2) + hdr.iCnt;
        }
      }

      /* Update the second field of the checkpoint header. This tells future
      ** writers that it is now safe to recycle pages before this point
      ** (assuming all live readers are cleared).  */
      if( rc==SQLITE4_OK ){
        pShm->ckpt.iFirstRecover = iFirstRead;
        pVfs->xShmBarrier(pLog->pFd);
      }
    }

    /* Free buffers and drop the checkpointer lock */
    sqlite4_free(pLock->pEnv, aBuf);
    sqlite4_free(pLock->pEnv, aPgno);
    sqlite4BtLockCkptUnlock(pLock);
    sqlite4BtPagerSetDbhdr((BtPager*)pLock, 0);
  }

  return rc;
}

#if 0
/*
** Return the database page size in bytes.
*/
SQLITE4_PRIVATE int sqlite4BtLogPagesize(BtLog *pLog){
  return pLog->snapshot.dbhdr.pgsz;
}

/*
** Return the number of pages in the database at last commit.
*/
SQLITE4_PRIVATE int sqlite4BtLogPagecount(BtLog *pLog){
  return (pLog->snapshot.dbhdr.nPg==1 ? 2 : pLog->snapshot.dbhdr.nPg);
}

/*
** Return the current value of the user cookie.
*/
SQLITE4_PRIVATE u32 sqlite4BtLogCookie(BtLog *pLog){
  return pLog->snapshot.dbhdr.iCookie;
}
#endif

SQLITE4_PRIVATE BtDbHdr *sqlite4BtLogDbhdr(BtLog *pLog){
  return &pLog->snapshot.dbhdr;
}

SQLITE4_PRIVATE void sqlite4BtLogReloadDbHdr(BtLog *pLog){
  BtShm *pShm = btLogShm(pLog);
  memcpy(&pLog->snapshot, &pShm->hdr1, sizeof(BtShmHdr));
}

SQLITE4_PRIVATE int sqlite4BtLogDbhdrFlush(BtLog *pLog){
  BtPager *pPager = (BtPager *)(pLog->pLock);
  BtPage *pOne = 0;
  int rc;

  rc = sqlite4BtPageGet(pPager, 1, &pOne);
  if( rc==SQLITE4_OK ){
    rc = sqlite4BtPageWrite(pOne);
  }
  if( rc==SQLITE4_OK ){
    btLogUpdateDbhdr(pLog, sqlite4BtPageData(pOne));
  }
  sqlite4BtPageRelease(pOne);

  return rc;
} 

/*
** Set the value of the user cookie.
*/
SQLITE4_PRIVATE int sqlite4BtLogSetCookie(BtLog *pLog, u32 iCookie){
  BtPager *pPager = (BtPager *)(pLog->pLock);
  BtPage *pOne = 0;
  int rc;

  rc = sqlite4BtPageGet(pPager, 1, &pOne);
  if( rc==SQLITE4_OK ){
    rc = sqlite4BtPageWrite(pOne);
  }
  if( rc==SQLITE4_OK ){
    pLog->snapshot.dbhdr.iCookie = iCookie;
    btLogUpdateDbhdr(pLog, sqlite4BtPageData(pOne));
  }
  sqlite4BtPageRelease(pOne);

  return rc;
}


/************** End of bt_log.c **********************************************/
/************** Begin file bt_main.c *****************************************/
/*
** 2013 September 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
*/

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

#define BT_MAX_DEPTH 32           /* Maximum possible depth of tree */
#define BT_MAX_DIRECT_OVERFLOW 8  /* Maximum direct overflow pages per cell */

/* Maximum size of a key-prefix stored on an internal node. Parts of the
** code in this file assume that this value can be encoded as a single
** byte SQLite4 varint.  */
#define BT_MAX_INTERNAL_KEY 200   /* Maximum bytes of key on internal node */

/*
** Values that make up the single byte flags field at the start of
** b-tree pages. 
*/
#define BT_PGFLAGS_INTERNAL  0x01  /* True for non-leaf nodes */
#define BT_PGFLAGS_METATREE  0x02  /* True for a meta-tree page */
#define BT_PGFLAGS_SCHEDULE  0x04  /* True for a schedule-tree page */
#define BT_PGFLAGS_LARGEKEYS 0x08  /* True if keys larger than 200 bytes */

/*
** Maximum depth of fast-insert sub-trees.
*/
#define MAX_SUBTREE_DEPTH 8

/* #define BT_STDERR_DEBUG 1 */

typedef struct BtCursor BtCursor;
typedef struct FiCursor FiCursor;
typedef struct FiSubCursor FiSubCursor;

struct bt_db {
  sqlite4_env *pEnv;              /* SQLite environment */
  sqlite4_mm *pMM;                /* Memory allocator for pEnv */
  BtPager *pPager;                /* Underlying page-based database */
  bt_cursor *pAllCsr;             /* List of all open cursors */
  int nMinMerge;
  int nScheduleAlloc;
  int bFastInsertOp;              /* Set by CONTROL_FAST_INSERT_OP */

  BtCursor *pFreeCsr;
};

/*
** Overflow buffer is valid if nKey!=0.
*/
typedef struct BtOvfl BtOvfl;
struct BtOvfl {
  int nKey;
  int nVal;
  sqlite4_buffer buf;
};

/*
** Values that make up the bt_cursor.flags mask.
**
** CSR_NEXT_OK, CSR_PREV_OK:
**   These are only used by fast-insert cursors. The CSR_NEXT_OK flag is
**   set if xNext() may be safely called on the cursor. CSR_PREV_OK is
**   true if xPrev() is Ok.
**
** CSR_VISIT_DEL:
**   If this flag is set, do not skip over delete keys that occur in the
**   merged cursor output. This is used by checkpoint merges.
*/
#define CSR_TYPE_BT   0x0001
#define CSR_TYPE_FAST 0x0002
#define CSR_NEXT_OK   0x0004
#define CSR_PREV_OK   0x0008
#define CSR_VISIT_DEL 0x0010

#define IsBtCsr(pCsr) (((pCsr)->flags & CSR_TYPE_BT)!=0)

/* 
** Base class for both cursor types (BtCursor and FiCursor).
*/
struct bt_cursor {
  int flags;                      /* Cursor flags */
  void *pExtra;                   /* Extra allocated space */
  bt_db *pDb;                     /* Database this cursor belongs to */
  bt_cursor *pNextCsr;            /* Next cursor opened by same db handle */
};

/*
** Database b-tree cursor handle.
*/
struct BtCursor {
  bt_cursor base;                 /* Base cursor class */

  u32 iRoot;                      /* Root page of b-tree this cursor queries */
  int nPg;                        /* Number of valid entries in apPage[] */
  BtOvfl ovfl;                    /* Overflow cache (see above) */

  int bRequireReseek;             /* True if a btCsrReseek() is required */
  int bSkipNext;                  /* True if next CsrNext() is a no-op */
  int bSkipPrev;                  /* True if next CsrPrev() is a no-op */

  BtCursor *pNextFree;            /* Next in list of free BtCursor structures */

  int aiCell[BT_MAX_DEPTH];       /* Current cell of each apPage[] entry */
  BtPage *apPage[BT_MAX_DEPTH];   /* All pages from root to current leaf */
};

/*
** Database f-tree cursor handle.
*/
struct FiSubCursor {
  u8 aPrefix[8];                  /* Meta-tree key prefix for this age/level */
  BtCursor mcsr;                  /* Cursor opened on meta table (scans only) */
  BtCursor csr;                   /* Cursor opened on current sub-tree */
};
struct FiCursor {
  bt_cursor base;                 /* Base cursor class */
  int iBt;                        /* Current sub-tree (or -1 for EOF) */
  int nBt;                        /* Number of entries in aBt[] array */
  FiSubCursor *aSub;              /* Array of sub-tree cursors */
};

/*
** TODO: Rearrange things so these are not required!
*/
static int fiLoadSummary(bt_db *, BtCursor *, const u8 **, int *);
static void btReadSummary(const u8 *, int, u16 *, u16 *, u16 *);
static int btCsrData(BtCursor *, int, int, const void **, int *);
static int btReadSchedule(bt_db *, u8 *, BtSchedule *);
static int btCsrEnd(BtCursor *pCsr, int bLast);
static int btCsrStep(BtCursor *pCsr, int bNext);
static int btCsrKey(BtCursor *pCsr, const void **ppK, int *pnK);
SQLITE4_PRIVATE void sqlite4BtDebugFastTree(bt_db *db, int iCall);


/* 
** Meta-table summary key.
*/
static const u8 aSummaryKey[] = {0xFF, 0xFF, 0xFF, 0xFF};

#ifndef btErrorBkpt
int btErrorBkpt(int rc){
  static int error_cnt = 0;
  error_cnt++;
  return rc;
}
#endif

#if !defined(NDEBUG) 
static void btCheckPageRefs(bt_db *pDb){
  int nActual = 0;                /* Outstanding refs according to pager */
  int nExpect = 0;                /* According to the set of open cursors */
  bt_cursor *pCsr;                /* Iterator variable */

  for(pCsr=pDb->pAllCsr; pCsr; pCsr=pCsr->pNextCsr){
    if( IsBtCsr(pCsr) ){
      BtCursor *p = (BtCursor*)pCsr;
      if( p->nPg>0 ) nExpect += p->nPg;
    }else{
      FiCursor *p = (FiCursor*)pCsr;
      int i;
      for(i=0; i<p->nBt; i++){
        if( p->aSub[i].mcsr.nPg>0 ) nExpect += p->aSub[i].mcsr.nPg;
        if( p->aSub[i].csr.nPg>0 ) nExpect += p->aSub[i].csr.nPg;
      }
    }
  }
  nActual = sqlite4BtPagerRefcount(pDb->pPager);
  assert( nActual==nExpect );
}
#else
# define btCheckPageRefs(x) 
#endif

/*
** Interpret the first 4 bytes of the buffer indicated by the first 
** parameter as a 32-bit unsigned big-endian integer.
*/
SQLITE4_PRIVATE u32 sqlite4BtGetU32(const u8 *a){
  return ((u32)a[0] << 24) + ((u32)a[1] << 16) + ((u32)a[2] << 8) + ((u32)a[3]);
}
#define btGetU32(x) sqlite4BtGetU32(x)

/*
** Interpret the first 2 bytes of the buffer indicated by the first 
** parameter as a 16-bit unsigned big-endian integer.
*/
static u16 btGetU16(const u8 *a){
  return ((u32)a[0] << 8) + (u32)a[1];
}

/*
** Write the value passed as the second argument to the buffer passed
** as the first. Formatted as an unsigned 16-bit big-endian integer.
*/
static void btPutU16(u8 *a, u16 i){
  a[0] = (u8)((i>>8) & 0xFF);
  a[1] = (u8)((i>>0) & 0xFF);
}

/*
** Write the value passed as the second argument to the buffer passed
** as the first. Formatted as an unsigned 32-bit big-endian integer.
*/
SQLITE4_PRIVATE void sqlite4BtPutU32(u8 *a, u32 i){
  a[0] = (u8)((i>>24) & 0xFF);
  a[1] = (u8)((i>>16) & 0xFF);
  a[2] = (u8)((i>>8) & 0xFF);
  a[3] = (u8)((i>>0) & 0xFF);
}
#define btPutU32(x,y) sqlite4BtPutU32(x,y)

struct FakePage { u8 *aData; };
#define btPageData(pPg) (((struct FakePage*)(pPg))->aData)

/*
** Allocate a new database handle.
*/
SQLITE4_PRIVATE int sqlite4BtNew(sqlite4_env *pEnv, int nExtra, bt_db **ppDb){
  static const int MIN_MERGE = 2;
  static const int SCHEDULE_ALLOC = 4;

  bt_db *db = 0;                  /* New database object */
  BtPager *pPager = 0;            /* Pager object for this database */
  int nReq;                       /* Bytes of space required for bt_db object */
  int rc;                         /* Return code */

  nReq = sizeof(bt_db);
  rc = sqlite4BtPagerNew(pEnv, nExtra + nReq, &pPager);
  if( rc==SQLITE4_OK ){
    db = (bt_db*)sqlite4BtPagerExtra(pPager);
    db->pPager = pPager;
    db->pEnv = pEnv;

    db->nMinMerge = MIN_MERGE;
    db->nScheduleAlloc = SCHEDULE_ALLOC;
  }

  *ppDb = db;
  return rc;
}

/*
** Close an existing database handle. Once this function has been 
** called, the handle may not be used for any purpose.
*/
SQLITE4_PRIVATE int sqlite4BtClose(bt_db *db){
  if( db ){
    BtCursor *pCsr;
    BtCursor *pNext;
    for(pCsr=db->pFreeCsr; pCsr; pCsr=pNext){
      pNext = pCsr->pNextFree;
      sqlite4_free(db->pEnv, pCsr);
    }
    sqlite4BtPagerClose(db->pPager);
  }
  return SQLITE4_OK;
}

/*
** Return a pointer to the nExtra bytes of space allocated along with 
** the database handle. 
*/
SQLITE4_PRIVATE void *sqlite4BtExtra(bt_db *db){
  return (void*)&db[1];
}

SQLITE4_PRIVATE int sqlite4BtOpen(bt_db *db, const char *zFilename){
  int rc;
  sqlite4_env_config(db->pEnv, SQLITE4_ENVCONFIG_GETMM, &db->pMM);
  rc = sqlite4BtPagerOpen(db->pPager, zFilename);
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtBegin(bt_db *db, int iLevel){
  int rc;
  rc = sqlite4BtPagerBegin(db->pPager, iLevel);
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtCommit(bt_db *db, int iLevel){
  int rc;
  rc = sqlite4BtPagerCommit(db->pPager, iLevel);
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtRevert(bt_db *db, int iLevel){
  int rc;
  rc = sqlite4BtPagerRevert(db->pPager, iLevel);
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtRollback(bt_db *db, int iLevel){
  int rc;
  rc = sqlite4BtPagerRollback(db->pPager, iLevel);
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtTransactionLevel(bt_db *db){
  return sqlite4BtPagerTransactionLevel(db->pPager);
}

static void btCsrSetup(bt_db *db, u32 iRoot, BtCursor *pCsr){
  memset(pCsr, 0, offsetof(BtCursor, aiCell));
  pCsr->base.flags = CSR_TYPE_BT;
  pCsr->base.pExtra = (void*)&pCsr[1];
  pCsr->base.pDb = db;
  pCsr->iRoot = iRoot;
  pCsr->ovfl.buf.pMM = db->pMM;
}

SQLITE4_PRIVATE int sqlite4BtCsrOpen(bt_db *db, int nExtra, bt_cursor **ppCsr){
  int rc = SQLITE4_OK;            /* Return Code */
  bt_cursor *pRet = 0;

  assert( sqlite4BtPagerTransactionLevel(db->pPager)>0 );

  if( db->bFastInsertOp ){
    int nByte = sizeof(FiCursor) + nExtra;
    FiCursor *pCsr;

    pCsr = (FiCursor*)sqlite4_malloc(db->pEnv, nByte);
    if( pCsr==0 ){
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }else{
      memset(pCsr, 0, nByte);
      pCsr->base.flags = CSR_TYPE_FAST;
      pCsr->base.pExtra = (void*)&pCsr[1];
      pCsr->base.pDb = db;
      pRet = (bt_cursor*)pCsr;
    }

  }else{
    BtCursor *pCsr;                /* New cursor object */
    u32 iRoot = sqlite4BtPagerDbhdr(db->pPager)->iRoot;
    
    if( db->pFreeCsr ){
      pCsr = db->pFreeCsr;
      db->pFreeCsr = pCsr->pNextFree;
    }else{
      int nByte = sizeof(BtCursor) + nExtra;
      pCsr = (BtCursor*)sqlite4_malloc(db->pEnv, nByte);
      if( pCsr==0 ){
        rc = btErrorBkpt(SQLITE4_NOMEM);
        goto csr_open_out;
      }
    }

    btCsrSetup(db, iRoot, pCsr);
    pRet = (bt_cursor*)pCsr;
  }

  assert( (pRet==0)==(rc!=SQLITE4_OK) );
  if( rc==SQLITE4_OK ){
    pRet->pNextCsr = db->pAllCsr;
    db->pAllCsr = pRet;
  }

 csr_open_out:
  *ppCsr = pRet;
  btCheckPageRefs(db);
  db->bFastInsertOp = 0;
  return rc;
}

static void btCsrReleaseAll(BtCursor *pCsr){
  int i;
  for(i=0; i<pCsr->nPg; i++){
    sqlite4BtPageRelease(pCsr->apPage[i]);
  }
  pCsr->nPg = 0;
}


static void btCsrReset(BtCursor *pCsr, int bFreeBuffer){
  btCsrReleaseAll(pCsr);
  if( bFreeBuffer ){
    sqlite4_buffer_clear(&pCsr->ovfl.buf);
  }
  pCsr->bSkipNext = 0;
  pCsr->bSkipPrev = 0;
  pCsr->bRequireReseek = 0;
  pCsr->ovfl.nKey = 0;
}

static void fiCsrReset(FiCursor *pCsr){
  int i;
  bt_db *db = pCsr->base.pDb;
  for(i=0; i<pCsr->nBt; i++){
    btCsrReset(&pCsr->aSub[i].csr, 1);
    btCsrReset(&pCsr->aSub[i].mcsr, 1);
  }
  sqlite4_free(db->pEnv, pCsr->aSub);
  pCsr->aSub = 0;
  pCsr->nBt = 0;
  pCsr->iBt = -1;
}

SQLITE4_PRIVATE int sqlite4BtCsrClose(bt_cursor *pCsr){
  if( pCsr ){
    bt_cursor **pp;
    bt_db *pDb = pCsr->pDb;

    btCheckPageRefs(pDb);

    /* Remove this cursor from the all-cursors list. */
    for(pp=&pDb->pAllCsr; *pp!=pCsr; pp=&(*pp)->pNextCsr);
    *pp = pCsr->pNextCsr;

    if( IsBtCsr(pCsr) ){
      /* A regular b-tree cursor */
      BtCursor *p = (BtCursor*)pCsr;
      btCsrReset(p, 1);
      p->pNextFree = pDb->pFreeCsr;
      pDb->pFreeCsr = p;
    }else{
      /* A fast-insert-tree cursor */
      fiCsrReset((FiCursor*)pCsr);
      sqlite4_free(pDb->pEnv, pCsr);
    }
    btCheckPageRefs(pDb);
  }
  return SQLITE4_OK;
}

SQLITE4_PRIVATE void *sqlite4BtCsrExtra(bt_cursor *pCsr){
  return pCsr->pExtra;
}

/*
** Set pCsr->apPage[pCsr->nPg] to a reference to database page pgno.
*/
static int btCsrDescend(BtCursor *pCsr, u32 pgno, BtPage **ppPg){
  int rc;
  if( pCsr->nPg>=BT_MAX_DEPTH ){
    rc = btErrorBkpt(SQLITE4_CORRUPT);
  }else{
    assert( pCsr->nPg>=0 );
    rc = sqlite4BtPageGet(pCsr->base.pDb->pPager, pgno, ppPg);
    assert( ((*ppPg)==0)==(rc!=SQLITE4_OK) );
    pCsr->apPage[pCsr->nPg] = *ppPg;
    pCsr->nPg++;
  }
  return rc;
}

/*
** Move the cursor from the current page to the parent. Return 
** SQLITE4_NOTFOUND if the cursor already points to the root page,
** or SQLITE4_OK otherwise.
*/
static int btCsrAscend(BtCursor *pCsr, int nLvl){
  int i;
  for(i=0; i<nLvl && ( pCsr->nPg>0 ); i++){
    pCsr->nPg--;
    sqlite4BtPageRelease(pCsr->apPage[pCsr->nPg]);
    pCsr->apPage[pCsr->nPg] = 0;
  }
  return (pCsr->nPg==0 ? SQLITE4_NOTFOUND : SQLITE4_OK);
}

/**************************************************************************
** The functions in this section are used to extract data from buffers
** containing formatted b-tree pages. They do not entirely encapsulate all
** page format details, but go some way to doing so.
*/

static int btCellCount(const u8 *aData, int nData){
  return (int)btGetU16(&aData[nData-2]);
}

static int btFreeSpace(const u8 *aData, int nData){
  return (int)btGetU16(&aData[nData-4]);
}

static int btFreeOffset(const u8 *aData, int nData){
  return (int)btGetU16(&aData[nData-6]);
}

static int btFreeContiguous(const u8 *aData, int nData){
  int nCell = btCellCount(aData, nData);
  return nData - btFreeOffset(aData, nData) - (3+nCell)*2;
}

static u8 btFlags(const u8 *aData){
  return aData[0];
}

static u8 *btCellFind(u8 *aData, int nData, int iCell){
  int iOff = btGetU16(&aData[nData - 6 - iCell*2 - 2]);
  return &aData[iOff];
}

/*
** Return a pointer to the big-endian u16 field that contains the 
** pointer to cell iCell.
*/
static u8* btCellPtrFind(u8 *aData, int nData, int iCell){
  return &aData[nData - 6 - iCell*2 - 2];
}

/*
** Parameters aData and nData describe a buffer containing an internal
** b-tree node. The page number of the iCell'th leftmost child page
** is returned.
*/
static u32 btChildPgno(u8 *aData, int nData, int iCell){
  u32 pgno;                       /* Return value */
  int nCell = btCellCount(aData, nData);

  if( iCell>=nCell ){
    pgno = btGetU32(&aData[1]);
  }else{
    int nKey;
    u8 *pCell = btCellFind(aData, nData, iCell);
    pCell += sqlite4BtVarintGet32(pCell, &nKey);
    pCell += nKey;
    pgno = btGetU32(pCell);
  }

  return pgno;
}

/*
**************************************************************************/

SQLITE4_PRIVATE void sqlite4BtBufAppendf(sqlite4_buffer *pBuf, const char *zFormat, ...){
  char *zAppend;
  va_list ap;

  va_start(ap, zFormat);
  zAppend = sqlite4_vmprintf(0, zFormat, ap);
  va_end(ap);

  sqlite4_buffer_append(pBuf, zAppend, strlen(zAppend));
  sqlite4_free(0, zAppend);
}

/* #include <ctype.h> */

void btBufferAppendBlob(
  sqlite4_buffer *pBuf, 
  int bAscii, 
  u8 *pBlob, int nBlob
){
  int j;
  for(j=0; j<nBlob; j++){
    if( bAscii ){
      sqlite4BtBufAppendf(pBuf, "%c", isalnum((int)pBlob[j]) ? pBlob[j] : '.');
    }else{
      sqlite4BtBufAppendf(pBuf, "%02X", (int)pBlob[j]);
    }
  }
}

/*
** Append a human-readable interpretation of the b-tree page in aData/nData
** to buffer pBuf.
*/
static void btPageToAscii(
  u32 pgno,                       /* Page number */
  int bAscii,                     /* True to print keys and values as ASCII */
  BtPager *pPager,                /* Pager object (or NULL) */
  u8 *aData, int nData,           /* Buffer containing page data */
  sqlite4_buffer *pBuf            /* Output buffer */
){
  BtDbHdr *pHdr = 0;
  int i;
  int nCell = (int)btCellCount(aData, nData);
  u8 flags = btFlags(aData);      /* Page flags */

  sqlite4BtBufAppendf(pBuf, "Page %d: ", pgno);

  if( pPager ) pHdr = sqlite4BtPagerDbhdr(pPager);
  if( pHdr && pgno==pHdr->iSRoot ){
    int i;
    BtSchedule s;
    sqlite4BtBufAppendf(pBuf, "(schedule page) ");
    btReadSchedule(0, aData, &s);

    sqlite4BtBufAppendf(pBuf, "  eBusy=(%s)\n",
        s.eBusy==BT_SCHEDULE_EMPTY ? "empty" :
        s.eBusy==BT_SCHEDULE_BUSY ? "busy" :
        s.eBusy==BT_SCHEDULE_DONE ? "done" : "!ErroR"
    );
    sqlite4BtBufAppendf(pBuf, "  iAge=%d\n", (int)s.iAge);
    sqlite4BtBufAppendf(pBuf, "  iMinLevel=%d\n", (int)s.iMinLevel);
    sqlite4BtBufAppendf(pBuf, "  iMaxLevel=%d\n", (int)s.iMaxLevel);
    sqlite4BtBufAppendf(pBuf, "  iOutLevel=%d\n", (int)s.iOutLevel);
    sqlite4BtBufAppendf(pBuf, "  aBlock=(");
    for(i=0; s.aBlock[i] && i<array_size(s.aBlock); i++){
      sqlite4BtBufAppendf(pBuf, "%s%d", i==0 ? "" : " ", (int)s.aBlock[i]);
    }
    sqlite4BtBufAppendf(pBuf, ")\n");

    sqlite4BtBufAppendf(pBuf, "  iNextPg=%d\n", (int)s.iNextPg);
    sqlite4BtBufAppendf(pBuf, "  iNextCell=%d\n", (int)s.iNextCell);
    sqlite4BtBufAppendf(pBuf, "  iFreeList=%d\n", (int)s.iFreeList);

    sqlite4BtBufAppendf(pBuf, "  aRoot=(");
    for(i=0; s.aBlock[i] && i<array_size(s.aBlock); i++){
      sqlite4BtBufAppendf(pBuf, "%s%d", i==0 ? "" : " ", (int)s.aRoot[i]);
    }
    sqlite4BtBufAppendf(pBuf, ")\n");

  }else{
    sqlite4BtBufAppendf(pBuf, "nCell=%d ", nCell);
    sqlite4BtBufAppendf(pBuf, "iFree=%d ", (int)btFreeOffset(aData, nData));
    sqlite4BtBufAppendf(pBuf, "flags=%d ", (int)btFlags(aData));
    if( btFlags(aData) & BT_PGFLAGS_INTERNAL ){
      sqlite4BtBufAppendf(pBuf, "rchild=%d ", (int)btGetU32(&aData[1]));
    }
    sqlite4BtBufAppendf(pBuf, "cell-offsets=(");
    for(i=0; i<nCell; i++){
      u8 *ptr = btCellPtrFind(aData, nData, i);
      sqlite4BtBufAppendf(pBuf, "%s%d", i==0?"":" ", (int)btGetU16(ptr));
    }
    sqlite4BtBufAppendf(pBuf, ")\n");

    for(i=0; i<nCell; i++){
      u8 *pCell;          /* Cell i */
      int nKey;           /* Number of bytes of key to output */
      u8 *pKey;           /* Buffer containing key. */
      int nVal;           /* Number of bytes of value to output */
      int nDummy;         /* Unused */
      u8 *pVal = 0;       /* Buffer containing value. */
      char celltype = 'A';

      pCell = btCellFind(aData, nData, i);
      pCell += sqlite4BtVarintGet32(pCell, &nKey);
      if( flags & BT_PGFLAGS_INTERNAL ){
        celltype = 'I';
      }else{
        if( nKey==0 ){
          celltype = 'C';
          pCell += sqlite4BtVarintGet32(pCell, &nKey);
        }else if( pCell[nKey]==0 ){
          celltype = 'B';
        }
      }
      sqlite4BtBufAppendf(pBuf, "  Cell %d: [%c] ", i, celltype);

      pKey = pCell;
      pCell += nKey;
      btBufferAppendBlob(pBuf, bAscii, pKey, nKey);
      sqlite4BtBufAppendf(pBuf, "  ");

      switch( celltype ){
        case 'I':
          sqlite4BtBufAppendf(pBuf, "child=%d ", (int)btGetU32(pCell));
          break;

        case 'A':
          pCell += sqlite4BtVarintGet32(pCell, &nVal);
          if( nVal>=2 ){
            nVal -= 2;
            pVal = pCell;
          }else{
            sqlite4BtBufAppendf(pBuf, "delete-key");
          }
          break;

        case 'B':
          assert( pCell[0]==0x00 );
          pCell++;
          pCell += sqlite4BtVarintGet32(pCell, &nVal);
          pVal = pCell;
          pCell += nVal;
          pCell += sqlite4BtVarintGet32(pCell, &nDummy);
          break;

        case 'C':
          pVal = 0;
          break;
      }

      if( pVal ){
        btBufferAppendBlob(pBuf, bAscii, pVal, nVal);
        if( flags & BT_PGFLAGS_METATREE ){
          /* Interpret the meta-tree entry */
          if( nKey==sizeof(aSummaryKey) && 0==memcmp(pKey, aSummaryKey, nKey) ){
            u16 iMin, nLvl, iMerge;
            int j;
            sqlite4BtBufAppendf(pBuf, "  [summary:");
            for(j=0; j<(nVal/6); j++){
              btReadSummary(pVal, j, &iMin, &nLvl, &iMerge);
              sqlite4BtBufAppendf(pBuf, " %d/%d/%d", 
                  (int)iMin, (int)nLvl, (int)iMerge
              );
            }
            sqlite4BtBufAppendf(pBuf, "]");
            
          }else{
            int nPgPerBlk = (pHdr->blksz / pHdr->pgsz);
            u32 iAge = btGetU32(&pKey[0]);
            u32 iLevel = ~btGetU32(&pKey[4]);
            u32 iRoot = btGetU32(pVal);
            sqlite4BtBufAppendf(pBuf, "  [age=%d level=%d root=%d]", 
                (int)iAge, (int)iLevel, (int)iRoot
            );
            sqlite4BtBufAppendf(pBuf, "  (blk=%d)", 1 + (iRoot / nPgPerBlk));
          }
        }
      }

      if( celltype=='B' ){
        int j;
        u8 ctrl = *pCell++;
        int nDirect = (ctrl & 0x0F);
        int nDepth = ((ctrl>>4) & 0x0F);
        sqlite4BtBufAppendf(
            pBuf, "  [overflow: direct=%d depth=%d]", nDirect, nDepth);
        for(j=0; j<=nDirect; j++){
          sqlite4BtBufAppendf(pBuf, " %d", btGetU32(&pCell[j*4]));
        }
      }
      sqlite4BtBufAppendf(pBuf, "\n");
    }

    if( pPager && btFlags(aData) & BT_PGFLAGS_INTERNAL ){
      for(i=0; i<=btCellCount(aData, nData); i++){
        BtPage *pChild;
        u8 *aChild;
        u32 child;

        child = btChildPgno(aData, nData, i);
        sqlite4BtPageGet(pPager, child, &pChild);
        aChild = btPageData(pChild);
        btPageToAscii(child, bAscii, pPager, aChild, nData, pBuf);
        sqlite4BtPageRelease(pChild);
      }
    }
  }
  sqlite4BtBufAppendf(pBuf, "\n");
}

static int btFreelistToAscii(bt_db *db, u32 iFirst, sqlite4_buffer *pBuf){
  int rc = SQLITE4_OK;
  u32 iTrunk = iFirst;
  while( iTrunk && rc==SQLITE4_OK ){
    BtPage *pPg = 0;
    rc = sqlite4BtPageGet(db->pPager, iTrunk, &pPg);
    if( rc==SQLITE4_OK ){
      u8 *aData = btPageData(pPg);
      u32 nFree = btGetU32(aData);
      u32 iNext = btGetU32(&aData[4]);
      int i;

      sqlite4BtBufAppendf(pBuf, "iTrunk=%d ", (int)iTrunk);
      sqlite4BtBufAppendf(pBuf, "nFree=%d iNext=%d (", (int)nFree, (int)iNext);
      for(i=0; i<(int)nFree; i++){
        u32 pgnoFree = btGetU32(&aData[8 + i*sizeof(u32)]);
        sqlite4BtBufAppendf(pBuf, "%s%d", (i==0)?"": " ", (int)pgnoFree);
      }
      sqlite4BtBufAppendf(pBuf, ")\n");

      sqlite4BtPageRelease(pPg);
      iTrunk = iNext;
    }
  }
  return rc;
}

#ifndef NDEBUG
/* #include <stdio.h> */

static void printPage(FILE *f, u32 pgno, u8 *aData, int nData){
  sqlite4_buffer buf;

  sqlite4_buffer_init(&buf, 0);
  btPageToAscii(pgno, 0, 0, aData, nData, &buf);
  sqlite4_buffer_append(&buf, "", 1);

  fprintf(f, "%s", (char*)buf.p);
  sqlite4_buffer_clear(&buf);
}

int printPgdataToStderr(u32 pgno, u8 *aData, int nData){
  printPage(stderr, pgno, aData, nData);
  return 0;
}

int printPgToStderr(BtPage *pPg){
  printPage(stderr, sqlite4BtPagePgno(pPg), btPageData(pPg), 1024);
  return 0;
}

static void btPrintMetaTree(BtPager *pPager, int bAscii, BtDbHdr *pHdr){
  u8 *aData;
  int nData;
  sqlite4_buffer buf;
  BtPage *pPg = 0;

  sqlite4BtPageGet(pPager, pHdr->iMRoot, &pPg);
  aData = btPageData(pPg);
  nData = pHdr->pgsz;
  sqlite4_buffer_init(&buf, 0);
  btPageToAscii(pHdr->iMRoot, bAscii, pPager, aData, nData, &buf);
  sqlite4_buffer_append(&buf, "", 1);

  fprintf(stderr, "%s", (char*)buf.p);
  sqlite4_buffer_clear(&buf);
  sqlite4BtPageRelease(pPg);
}


static void btDumpCsr(sqlite4_buffer *pBuf, BtCursor *pCsr){
  assert( pCsr->nPg>=0 );
  if( pCsr->nPg==0 ){
    sqlite4BtBufAppendf(pBuf, "EOF");
  }else{
    int rc;
    const void *pKey = 0;
    int nKey = 0;

    rc = btCsrKey(pCsr, &pKey, &nKey);
    assert( rc==SQLITE4_OK );
    btBufferAppendBlob(pBuf, 0, (u8*)pKey, nKey);
  }
}

static void fiDumpCsr(FiCursor *pCsr){
  int iBt;

  sqlite4_buffer buf;
  sqlite4_buffer_init(&buf, 0);
  for(iBt=0; iBt<pCsr->nBt; iBt++){
    FiSubCursor *pSub = &pCsr->aSub[iBt];

    sqlite4BtBufAppendf(&buf, "%d prefix: ", iBt);
    btBufferAppendBlob(&buf, 0, pSub->aPrefix, sizeof(pSub->aPrefix));

    sqlite4BtBufAppendf(&buf, "\n%d mcsr  : ", iBt);
    btDumpCsr(&buf, &pSub->mcsr);

    sqlite4BtBufAppendf(&buf, "\n%d csr   : ", iBt);
    btDumpCsr(&buf, &pSub->csr);
    sqlite4BtBufAppendf(&buf, "\n");
  }

  sqlite4_buffer_append(&buf, "", 1);
  fprintf(stderr, "%s", (char*)buf.p);
  sqlite4_buffer_clear(&buf);
}
#endif

#ifndef NDEBUG
/*
** This function is really just a big assert() statement. It contributes 
** nothing to the operation of the library.
**
** The assert() fails if the summary-record is not consistent with the
** actual contents of the meta-tree.
*/
static void assert_summary_ok(bt_db *db, int crc){
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
  BtCursor csr;                   /* Cursor used to load summary record */
  BtCursor mcsr;                  /* Cursor used to scan meta-tree */
  const u8 *aSum; int nSum;       /* Current summary record */
  int i;
  int rc;

  struct AgeData {
    int iMinLevel;                /* Smallest level of this age seen */
    int iMaxLevel;                /* Largest level of this age seen */
  } aData[32];

  if( crc!=SQLITE4_OK ) return;

  for(i=0; i<array_size(aData); i++){
    aData[i].iMinLevel = -1;
    aData[i].iMaxLevel = -1;
  }

  rc = fiLoadSummary(db, &csr, &aSum, &nSum);
  assert( rc==SQLITE4_OK );

  btCsrSetup(db, pHdr->iMRoot, &mcsr);
  for(rc=btCsrEnd(&mcsr, 0); rc==SQLITE4_OK; rc=btCsrStep(&mcsr, 1)){
    const u8 *pKey = 0; int nKey = 0;
    u32 iAge;
    u32 iLevel;
    rc = btCsrKey(&mcsr, (const void **)&pKey, &nKey);
    assert( rc==SQLITE4_OK );

    if( nKey==array_size(aSummaryKey) && memcmp(aSummaryKey, pKey, nKey)==0 ){
      break;
    }
    assert( nKey>=8 );

    iAge = btGetU32(&pKey[0]);
    iLevel = ~btGetU32(&pKey[4]);

    if( aData[iAge].iMinLevel<0 || aData[iAge].iMinLevel>iLevel ){
      aData[iAge].iMinLevel = (int)iLevel;
    }
    if( aData[iAge].iMaxLevel<0 || aData[iAge].iMaxLevel<iLevel ){
      aData[iAge].iMaxLevel = (int)iLevel;
    }
  }
  assert( rc==SQLITE4_OK );

  for(i=0; i<array_size(aData); i++){
    u16 iMin = 0; 
    u16 nLevel = 0;
    u16 iMerge = 0;
    if( i<(nSum/6) ){
      btReadSummary(aSum, i, &iMin, &nLevel, &iMerge);
    }
    if( aData[i].iMinLevel>=0 ){
      int nLevelExpect = aData[i].iMaxLevel - aData[i].iMinLevel + 1;
      assert( (int)iMin==aData[i].iMinLevel 
           || (iMerge!=0 && (int)iMin<aData[i].iMinLevel)
      );
      assert( (int)nLevel==nLevelExpect
           || (iMerge!=0 && nLevel>nLevelExpect)
      );
    }else{
      assert( iMin==0 && nLevel==0 );
    }
  }

  btCsrReset(&csr, 1);
  btCsrReset(&mcsr, 1);
}

static void assert_ficursor_ok(FiCursor *p, int crc){
  int iBt;

  if( crc!=SQLITE4_OK && crc!=SQLITE4_NOTFOUND && crc!=SQLITE4_INEXACT ) return;
  if( (p->base.flags & (CSR_NEXT_OK|CSR_PREV_OK))==0 ) return;

  for(iBt=0; iBt<p->nBt; iBt++){
    FiSubCursor *pSub = &p->aSub[iBt];

    if( pSub->mcsr.nPg>0 ){
      const void *pKey = 0; 
      int nKey = 0;
      assert( pSub->csr.nPg>0 );

      btCsrKey(&pSub->mcsr, &pKey, &nKey);
      assert( nKey>=8 && 0==memcmp(pSub->aPrefix, pKey, 8) );
    }else{
      assert( pSub->csr.nPg==0 );
    }
  }
}

#else
# define assert_summary_ok(x, rc) 
# define assert_ficursor_ok(p, rc)
#endif


/*
** This function compares the key passed via parameters pK and nK to the
** key that cursor pCsr currently points to.
**
** If the cursor key is C, and the user key K, then this function sets:
**
**     *piRes = (C - K).
**
** In other words, *piRes is +ve, zero or -ve if C is respectively larger, 
** equal to or smaller than K.
*/
static int btCellKeyCompare(
  BtCursor *pCsr,                 /* Cursor handle */
  int bLeaf,                      /* True if cursor currently points to leaf */
  const void *aPrefix,
  const void *pK, int nK,         /* Key to compare against cursor key */
  int *piRes                      /* OUT: Result of comparison */
){
  const void *pCsrKey;
  int nCsrKey;
  int nCmp;
  int nAscend = 0;
  int rc = SQLITE4_OK;
  int res;

  if( bLeaf ){
    rc = btCsrKey(pCsr, &pCsrKey, &nCsrKey);
  }else{
    const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);

    u8 *aData = btPageData(pCsr->apPage[pCsr->nPg-1]);
    u8 *pCell = btCellFind(aData, pgsz, pCsr->aiCell[pCsr->nPg-1]);

    pCsrKey = pCell + sqlite4BtVarintGet32(pCell, &nCsrKey);
    if( nCsrKey==0 ){
      int iCell = pCsr->aiCell[pCsr->nPg-1]+1;
      while( 1 ){
        BtPage *pPg;
        u8 *aData = btPageData(pCsr->apPage[pCsr->nPg-1]);
        u32 pgno = btChildPgno(aData, pgsz, iCell);
        nAscend++;
        rc = btCsrDescend(pCsr, pgno, &pPg);
        if( rc!=SQLITE4_OK ) break;
        aData = btPageData(pPg);
        pCsr->aiCell[pCsr->nPg-1] = 0;
        if( (btFlags(aData) & BT_PGFLAGS_INTERNAL)==0 ) break;
        iCell = 0;
      }
      rc = sqlite4BtCsrKey((bt_cursor*)pCsr, &pCsrKey, &nCsrKey);
    }
  }

  if( rc==SQLITE4_OK ){
    if( aPrefix ){
      if( nCsrKey<8 ){
        res = memcmp(pCsrKey, aPrefix, nCsrKey);
        if( res==0 ) res = -1;
      }else{
        res = memcmp(pCsrKey, aPrefix, 8);
        nCsrKey -= 8;
        pCsrKey = (void*)(((u8*)pCsrKey) + 8);
      }
      if( res ) goto keycompare_done;
    }

    nCmp = MIN(nCsrKey, nK);
    res = memcmp(pCsrKey, pK, nCmp);
    if( res==0 ){
      res = nCsrKey - nK;
    }
  }

 keycompare_done:
  btCsrAscend(pCsr, nAscend);
  *piRes = res;
  return rc;
}

/*
** Return an integer representing the result of (K1 - K2).
*/
static int btKeyCompare(
  const void *pKey1, int nKey1, 
  const void *pKey2, int nKey2
){
  int nCmp = MIN(nKey1, nKey2);
  int res;

  res = memcmp(pKey1, pKey2, nCmp);
  if( res==0 ){
    res = nKey1 - nKey2;
  }
  return res;
}


#define BT_CSRSEEK_SEEK   0
#define BT_CSRSEEK_UPDATE 1
#define BT_CSRSEEK_RESEEK 2

static int btCsrSeek(
  BtCursor *pCsr,                 /* Cursor object to seek */
  u8 *aPrefix,                    /* 8-byte key prefix, or NULL */
  const void *pK,                 /* Key to seek for */
  int nK,                         /* Size of key pK in bytes */
  int eSeek,                      /* Seek mode (a BT_SEEK_XXX constant) */
  int eCsrseek
){
  BtPager *pPager = pCsr->base.pDb->pPager;
  const int pgsz = sqlite4BtPagerPagesize(pPager);
  u32 pgno;                       /* Page number for next page to load */
  int rc;                         /* Return Code */

  assert( eSeek==BT_SEEK_EQ || eCsrseek!=BT_CSRSEEK_RESEEK );
  assert( eSeek==BT_SEEK_GE || eCsrseek!=BT_CSRSEEK_UPDATE );

  /* Reset the cursor */
  btCsrReset(pCsr, 0);

  /* Figure out the root page number */
  assert( pCsr->iRoot>1 && pCsr->nPg==0 );
  pgno = pCsr->iRoot;

  while( 1 ){
    /* Load page number pgno into the b-tree cursor. */
    BtPage *pPg;
    rc = sqlite4BtPageGet(pPager, pgno, &pPg);
    pCsr->apPage[pCsr->nPg++] = pPg;

    if( rc==SQLITE4_OK ){
      int nCell;                  /* Number of cells on this page */
      int iHi;                    /* pK/nK is <= than cell iHi */
      int iLo;                    /* pK/nK is > than cell (iLo-1) */
      int res;                    /* Result of comparison */

      u8 *aData = btPageData(pPg);
      u16 *aCellPtr = (u16*)btCellPtrFind(aData, pgsz, 0);
      int bLeaf = ((btFlags(aData) & BT_PGFLAGS_INTERNAL)==0);

      iLo = 0;
      iHi = nCell = btCellCount(aData, pgsz);

      if( btFlags(aData) & BT_PGFLAGS_LARGEKEYS ){
        while( iHi>iLo ){
          int iTst = (iHi+iLo)/2;   /* Cell to compare to pK/nK */
          u8 *pCell = &aData[btGetU16((u8*)(aCellPtr - iTst))];

          pCsr->aiCell[pCsr->nPg-1] = iTst;
          rc = btCellKeyCompare(pCsr, bLeaf, 0, pK, nK, &res);

          if( res<0 ){
            /* Cell iTst is SMALLER than pK/nK */
            iLo = iTst+1;
          }else{
            /* Cell iTst is LARGER than (or equal to) pK/nK */
            iHi = iTst;
            if( res==0 ){
              iHi += !bLeaf;
              break;
            }
          }
        }
      }else{
        while( iHi>iLo ){
          int iTst = (iHi+iLo)/2;   /* Cell to compare to pK/nK */
          u8 *pCell = &aData[btGetU16((u8*)(aCellPtr - iTst))];
          int n = *pCell;

          res = memcmp(&pCell[1], pK, MIN(nK, n));
          if( res<0 || (res==0 && (res = n - nK)<0) ){
            /* Cell iTst is SMALLER than pK/nK */
            iLo = iTst+1;
          }else{
            /* Cell iTst is LARGER than (or equal to) pK/nK */
            iHi = iTst;
            if( res==0 ){
              iHi += !bLeaf;
              break;
            }
          }
        }
      }
      if( rc!=SQLITE4_OK ) break;
      pCsr->aiCell[pCsr->nPg-1] = iHi;

      if( bLeaf==0 ){
        if( iHi==nCell ) pgno = btGetU32(&aData[1]);
        else{
          u8 *pCell = btCellFind(aData, pgsz, iHi);
          pgno = btGetU32(&pCell[1 + (int)*pCell]);
        }
        if( pCsr->nPg==BT_MAX_DEPTH ){
          rc = btErrorBkpt(SQLITE4_CORRUPT);
          break;
        }
      }else{

        if( nCell==0 ){
          rc = SQLITE4_NOTFOUND;
        }else if( res!=0 ){
          if( eSeek==BT_SEEK_EQ ){
            if( eCsrseek==BT_CSRSEEK_RESEEK ){
              rc = SQLITE4_OK;
              if( iHi==nCell ){
                assert( pCsr->aiCell[pCsr->nPg-1]>0 );
                pCsr->aiCell[pCsr->nPg-1]--;
                pCsr->bSkipPrev = 1;
              }else{
                pCsr->bSkipNext = 1;
              }
            }else{
              rc = SQLITE4_NOTFOUND;
            }
          }else{
            assert( BT_SEEK_LEFAST<0 && BT_SEEK_LE<0 );
            if( eSeek<0 ){
              rc = sqlite4BtCsrPrev((bt_cursor*)pCsr);
            }else{
              if( iHi==nCell ){
                if( eCsrseek==BT_CSRSEEK_UPDATE ){
                  rc = SQLITE4_NOTFOUND;
                }else{
                  rc = sqlite4BtCsrNext((bt_cursor*)pCsr);
                }
              }
            }
            if( rc==SQLITE4_OK ) rc = SQLITE4_INEXACT;
          }
        }

        /* The cursor now points to a leaf page. Break out of the loop. */
        break;
      }
    }
  }

  if( rc!=SQLITE4_OK && rc!=SQLITE4_INEXACT && eCsrseek!=BT_CSRSEEK_UPDATE ){
    btCsrReset(pCsr, 0);
  }
  return rc;
}

static int btCsrReseek(BtCursor *pCsr){
  int rc = SQLITE4_OK;
  if( pCsr->bRequireReseek ){
    BtOvfl o;                     /* Copy of initial overflow buffer */
    memcpy(&o, &pCsr->ovfl, sizeof(BtOvfl));

    pCsr->ovfl.buf.n = 0;
    pCsr->ovfl.buf.p = 0;
    pCsr->bSkipNext = 0;
    pCsr->bRequireReseek = 0;

    rc = btCsrSeek(pCsr, 0, o.buf.p, o.nKey, BT_SEEK_EQ, BT_CSRSEEK_RESEEK);
    assert( rc!=SQLITE4_INEXACT );
    if( pCsr->ovfl.buf.p==0 ){
      pCsr->ovfl.buf.p = o.buf.p;
    }else{
      sqlite4_buffer_clear(&o.buf);
    }
  }
  return rc;
}

/*
** This function does the work of both sqlite4BtCsrNext() (if parameter
** bNext is true) and Pref() (if bNext is false).
*/
static int btCsrStep(BtCursor *pCsr, int bNext){
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  int rc = SQLITE4_OK;
  int bRequireDescent = 0;

  rc = btCsrReseek(pCsr);
  if( rc==SQLITE4_OK && pCsr->nPg==0 ){
    rc = SQLITE4_NOTFOUND;
  }
  pCsr->ovfl.nKey = 0;

  if( (pCsr->bSkipNext && bNext) || (pCsr->bSkipPrev && bNext==0) ){
    pCsr->bSkipPrev = pCsr->bSkipNext = 0;
    return rc;
  }
  pCsr->bSkipPrev = pCsr->bSkipNext = 0;

  while( rc==SQLITE4_OK ){
    int iPg = pCsr->nPg-1;
    int iCell = pCsr->aiCell[iPg];

    if( bNext ){
      u8 *aData = (u8*)btPageData(pCsr->apPage[iPg]);
      int nCell = btCellCount(aData, pgsz);
      assert( bRequireDescent==0 || bRequireDescent==1 );
      if( iCell<(nCell+bRequireDescent-1) ){
        pCsr->aiCell[iPg]++;
        break;
      }
    }else{
      if( pCsr->aiCell[iPg]>0 ){
        pCsr->aiCell[iPg]--;
        break;
      }
    }

    rc = btCsrAscend(pCsr, 1);
    bRequireDescent = 1;
  }

  if( bRequireDescent && rc==SQLITE4_OK ){
    u32 pgno;                   /* Child page number */
    u8 *aData = (u8*)btPageData(pCsr->apPage[pCsr->nPg-1]);

    pgno = btChildPgno(aData, pgsz, pCsr->aiCell[pCsr->nPg-1]);

    while( 1 ){
      BtPage *pPg;
      rc = btCsrDescend(pCsr, pgno, &pPg);
      if( rc!=SQLITE4_OK ){
        break;
      }else{
        int nCell;
        aData = (u8*)btPageData(pPg);
        nCell = btCellCount(aData, pgsz);
        if( btFlags(aData) & BT_PGFLAGS_INTERNAL ){
          pCsr->aiCell[pCsr->nPg-1] = (bNext ? 0 : nCell);
          pgno = btChildPgno(aData, pgsz, pCsr->aiCell[pCsr->nPg-1]);
        }else{
          pCsr->aiCell[pCsr->nPg-1] = (bNext ? 0 : nCell-1);
          break;
        }
      }
    }
  }

  return rc;
}


/*
** This function seeks the cursor as required for either sqlite4BtCsrFirst()
** (if parameter bLast is false) or sqlite4BtCsrLast() (if bLast is true).
*/
static int btCsrEnd(BtCursor *pCsr, int bLast){
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  int rc = SQLITE4_OK;            /* Return Code */
  u32 pgno;                       /* Page number for next page to load */

  /* Reset the cursor */
  btCsrReset(pCsr, 0);

  /* Figure out the root page number */
  assert( pCsr->iRoot>1 && pCsr->nPg==0 );
  pgno = pCsr->iRoot;

  while( rc==SQLITE4_OK ){
    /* Load page number pgno into the b-tree */
    BtPage *pPg;
    rc = btCsrDescend(pCsr, pgno, &pPg);
    if( rc==SQLITE4_OK ){
      int nCell;                  /* Number of cells on this page */
      int nByte;
      u8 *pCell;
      u8 *aData = (u8*)btPageData(pPg);

      nCell = btCellCount(aData, pgsz);
      pCsr->aiCell[pCsr->nPg-1] = (bLast ? nCell : 0);

      /* If the cursor has descended to a leaf break out of the loop. */
      if( (aData[0] & BT_PGFLAGS_INTERNAL)==0 ){
        if( nCell==0 ){
          btCsrReset(pCsr, 0);
          rc = SQLITE4_NOTFOUND;
        }
        break;
      }
      
      /* Otherwise, set pgno to the left or rightmost child of the page
      ** just loaded, depending on whether the cursor is seeking to the
      ** start or end of the tree.  */
      if( bLast==0 ){
        pCell = btCellFind(aData, pgsz, 0);
        pCell += sqlite4BtVarintGet32(pCell, &nByte);
        pCell += nByte;
        pgno = btGetU32(pCell);
      }else{
        pgno = btGetU32(&aData[1]);
      }
    }
  }
  if( pCsr->aiCell[pCsr->nPg-1] ) pCsr->aiCell[pCsr->nPg-1]--;
  return rc;
}


static int fiCsrAllocateSubs(bt_db *db, FiCursor *pCsr, int nBt){
  int rc = SQLITE4_OK;            /* Return code */
  if( nBt>pCsr->nBt ){
    int nByte = sizeof(FiSubCursor) * nBt;
    FiSubCursor *aNew;            /* Allocated array */

    aNew = (FiSubCursor*)sqlite4_realloc(db->pEnv, pCsr->aSub, nByte);
    if( aNew ){
      memset(&aNew[pCsr->nBt], 0, sizeof(FiSubCursor)*(nBt-pCsr->nBt));
      pCsr->aSub = aNew;
      pCsr->nBt = nBt;
    }else{
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }
  }

  return rc;
}

/*
** Return the page number of the first page on block iBlk.
*/
static u32 btFirstOfBlock(BtDbHdr *pHdr, u32 iBlk){
  assert( iBlk>0 );
  return (iBlk - 1) * (pHdr->blksz / pHdr->pgsz) + 1;
}

/*
** Return true if the cell that the argument cursor currently points to
** is a delete marker.
*/
static int btCsrIsDelete(BtCursor *pCsr){
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  int bRet;                       /* Return value */
  u8 *aData;
  u8 *pCell;
  int n;

  aData = btPageData(pCsr->apPage[pCsr->nPg-1]);
  pCell = btCellFind(aData, pgsz, pCsr->aiCell[pCsr->nPg-1]);

  pCell += sqlite4BtVarintGet32(pCell, &n);
  if( n==0 ){
    /* Type (c) cell */
    pCell += sqlite4BtVarintGet32(pCell, &n);
    pCell += n;
    pCell += sqlite4BtVarintGet32(pCell, &n);
    pCell += sqlite4BtVarintGet32(pCell, &n);
    bRet = (n==0);
  }else{
    pCell += n;
    pCell += sqlite4BtVarintGet32(pCell, &n);
    bRet = (n==1);
  }

  return bRet;
}

static int fiCsrIsDelete(FiCursor *pCsr){
  int res = 0;
  if( (pCsr->base.flags & CSR_VISIT_DEL)==0 ){
    BtCursor *p = &pCsr->aSub[pCsr->iBt].csr;
    res = btCsrIsDelete(p);
  }
  return res;
}

static int btOverflowArrayRead(
  bt_db *db,
  u8 *pOvfl,
  u8 *aOut,
  int nOut
){
  const int pgsz = sqlite4BtPagerPagesize(db->pPager);
  const int nPgPtr = pgsz / 4;
  int rc = SQLITE4_OK;
  int nDirect;                    /* Number of direct overflow pages */
  int nDepth;                     /* Depth of overflow tree */
  int iOut;                       /* Bytes of data copied so far */
  int iPg;

  nDirect = (int)(pOvfl[0] & 0x0F);
  nDepth = (int)(pOvfl[0]>>4);

  iOut = 0;

  /* Read from the direct overflow pages. And from the overflow tree, if
  ** it has a depth of zero.  */
  for(iPg=0; rc==SQLITE4_OK && iPg<(nDirect+(nDepth==0)) && iOut<nOut; iPg++){
    u32 pgno = btGetU32(&pOvfl[1+iPg*4]);
    BtPage *pPg = 0;
    rc = sqlite4BtPageGet(db->pPager, pgno, &pPg);
    if( rc==SQLITE4_OK ){
      int nCopy = MIN(nOut-iOut, pgsz);
      u8 *a = btPageData(pPg);
      memcpy(&aOut[iOut], a, nCopy);
      sqlite4BtPageRelease(pPg);
      iOut += nCopy;
    }
  }

  /* Read from the overflow tree, if it was not read by the block above. */
  if( nDepth>0 ){
    struct Heir {
      BtPage *pPg;
      int iCell;
    } apHier[8];
    int i;
    u32 pgno;
    memset(apHier, 0, sizeof(apHier));

    /* Initialize the apHier[] array. */
    pgno = btGetU32(&pOvfl[1+nDirect*4]);
    for(i=0; i<nDepth && rc==SQLITE4_OK; i++){
      u8 *a;
      rc = sqlite4BtPageGet(db->pPager, pgno, &apHier[i].pPg);
      if( rc==SQLITE4_OK ){
        a = btPageData(apHier[i].pPg);
        pgno = btGetU32(a);
      }
    }

    /* Loop runs once for each leaf page we read from. */
    while( iOut<nOut ){
      u8 *a;                      /* Data associated with some page */
      BtPage *pLeaf;              /* Leaf page */
      int nCopy;                  /* Bytes of data to read from leaf page */

      int iLvl;

      nCopy =  MIN(nOut-iOut, pgsz);
      assert( nCopy>0 );

      /* Read data from the current leaf page */
      rc = sqlite4BtPageGet(db->pPager, pgno, &pLeaf);
      if( rc!=SQLITE4_OK ) break;
      a = btPageData(pLeaf);
      memcpy(&aOut[iOut], a, nCopy);
      sqlite4BtPageRelease(pLeaf);
      iOut += nCopy;

      /* If all required data has been read, break out of the loop */
      if( iOut>=nOut ) break;

      for(iLvl=nDepth-1; iLvl>=0; iLvl--){
        if( apHier[iLvl].iCell<(nPgPtr-1) ) break;
      }
      if( iLvl<0 ) break; /* SQLITE4_CORRUPT? */
      apHier[iLvl].iCell++;

      for(; iLvl<nDepth && rc==SQLITE4_OK; iLvl++){
        a = btPageData(apHier[iLvl].pPg);
        pgno = btGetU32(&a[apHier[iLvl].iCell * 4]);
        if( iLvl<(nDepth-1) ){
          apHier[iLvl+1].iCell = 0;
          sqlite4BtPageRelease(apHier[iLvl+1].pPg);
          apHier[iLvl+1].pPg = 0;
          rc = sqlite4BtPageGet(db->pPager, pgno, &apHier[iLvl+1].pPg);
        }
      }
    }

    for(i=0; i<nDepth && rc==SQLITE4_OK; i++){
      sqlite4BtPageRelease(apHier[i].pPg);
    }
  }

  return rc;
}



/*
** Buffer the key and value belonging to the current cursor position
** in pCsr->ovfl.
*/
static int btCsrBuffer(BtCursor *pCsr, int bVal){
  int rc = SQLITE4_OK;            /* Return code */
  if( pCsr->ovfl.nKey<=0 ){
    const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
    u8 *aData;                      /* Page data */
    u8 *pCell;                      /* Pointer to cell within aData[] */
    int nReq;                       /* Total required space */
    u8 *aOut;                       /* Output buffer */
    u8 *pKLocal = 0;                /* Pointer to local part of key */
    u8 *pVLocal = 0;                /* Pointer to local part of value, if any */
    int nKLocal = 0;                /* Bytes of key on page */
    int nVLocal = 0;                /* Bytes of value on page */
    int nKOvfl = 0;                 /* Bytes of key on overflow pages */
    int nVOvfl = 0;                 /* Bytes of value on overflow pages */

    aData = (u8*)btPageData(pCsr->apPage[pCsr->nPg-1]);
    pCell = btCellFind(aData, pgsz, pCsr->aiCell[pCsr->nPg-1]);
    pCell += sqlite4BtVarintGet32(pCell, &nKLocal);
    if( nKLocal==0 ){
      /* Type (c) leaf cell. */
      pCell += sqlite4BtVarintGet32(pCell, &nKLocal);
      pKLocal = pCell;
      pCell += nKLocal;
      pCell += sqlite4BtVarintGet32(pCell, &nKOvfl);
      pCell += sqlite4BtVarintGet32(pCell, &nVOvfl);
      if( nVOvfl>0 ) nVOvfl -= 1;

    }else{
      pKLocal = pCell;
      pCell += nKLocal;
      pCell += sqlite4BtVarintGet32(pCell, &nVLocal);
      if( nVLocal==0 ){
        /* Type (b) */
        pCell += sqlite4BtVarintGet32(pCell, &nVLocal);
        pVLocal = pCell;
        pCell += nVLocal;
        pCell += sqlite4BtVarintGet32(pCell, &nVOvfl);
      }else{
        /* Type (a) */
        pVLocal = pCell;
        nVLocal -= 2;
      }
    }

    /* A delete-key */
    if( nVLocal<0 ) nVLocal = 0;

    pCsr->ovfl.nKey = nKLocal + nKOvfl;
    pCsr->ovfl.nVal = nVLocal + nVOvfl;

    nReq = pCsr->ovfl.nKey + pCsr->ovfl.nVal;
    assert( nReq>0 );
    rc = sqlite4_buffer_resize(&pCsr->ovfl.buf, nReq);
    if( rc!=SQLITE4_OK ) return rc;

    /* Copy in local data */
    aOut = (u8*)pCsr->ovfl.buf.p;
    memcpy(aOut, pKLocal, nKLocal);
    memcpy(&aOut[nKLocal], pVLocal, nVLocal);

    /* Load in overflow data */
    if( nKOvfl || nVOvfl ){
      rc = btOverflowArrayRead(
          pCsr->base.pDb, pCell, &aOut[nKLocal + nVLocal], nKOvfl + nVOvfl
          );
    }
  }

  return rc;
}


static int btCsrKey(BtCursor *pCsr, const void **ppK, int *pnK){
  int rc = SQLITE4_OK;

  if( pCsr->bRequireReseek ){
    *ppK = (const void*)pCsr->ovfl.buf.p;
    *pnK = pCsr->ovfl.nKey;
  }else{
    const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
    u8 *aData;
    u8 *pCell;
    int nK;
    int iCell = pCsr->aiCell[pCsr->nPg-1];

    aData = btPageData(pCsr->apPage[pCsr->nPg-1]);
    assert( btCellCount(aData, pgsz)>iCell );
    pCell = btCellFind(aData, pgsz, iCell);
    pCell += sqlite4BtVarintGet32(pCell, &nK);

    if( nK==0 ){
      /* type (c) leaf cell */
      rc = btCsrBuffer(pCsr, 0);
      if( rc==SQLITE4_OK ){
        *ppK = pCsr->ovfl.buf.p;
        *pnK = pCsr->ovfl.nKey;
      }
    }else{
      *ppK = pCell;
      *pnK = nK;
    }
  }

  return rc;
}


static int fiCsrSetCurrent(FiCursor *pCsr){
  const void *pMin = 0;
  int nMin = 0;
  int iMin = -1;
  int i;
  int rc = SQLITE4_OK;
  int mul;

  assert( pCsr->base.flags & (CSR_NEXT_OK | CSR_PREV_OK) );
  mul = ((pCsr->base.flags & CSR_NEXT_OK) ? 1 : -1);

  for(i=0; i<pCsr->nBt && rc==SQLITE4_OK; i++){
    BtCursor *pSub = &pCsr->aSub[i].csr;
    if( pSub->nPg>0 ){
      int nKey;
      const void *pKey;

      rc = btCsrKey(pSub, &pKey, &nKey);
      if( rc==SQLITE4_OK 
          && (iMin<0 || (mul * btKeyCompare(pKey, nKey, pMin, nMin))<0) 
        ){
        pMin = pKey;
        nMin = nKey;
        iMin = i;
      }
    }
  }

  if( iMin<0 && rc==SQLITE4_OK ) rc = SQLITE4_NOTFOUND;
  pCsr->iBt = iMin;
  return rc;
}

static int fiSubCsrCheckPrefix(FiSubCursor *pSub){
  const int nPrefix = sizeof(pSub->aPrefix);
  const void *pK = 0;
  int nK;
  int rc;

  rc = btCsrKey(&pSub->mcsr, &pK, &nK);
  if( rc==SQLITE4_OK && (nK<nPrefix || memcmp(pK, pSub->aPrefix, nPrefix)) ){
    rc = SQLITE4_NOTFOUND;
    btCsrReset(&pSub->mcsr, 0);
  }
  return rc;
}

/*
** Return SQLITE4_OK if the cursor is successfully stepped, or 
** SQLITE4_NOTFOUND if an EOF is encountered.
**
** If an error occurs (e.g. an IO error or OOM condition), return the
** relevant error code.
*/
static int fiSubCsrStep( 
  FiCursor *pCsr,                 /* Parent cursor */
  FiSubCursor *pSub,              /* Sub-cursor to advance */
  int bNext                       /* True for xNext(), false for xPrev() */
){
  int rc;

  rc = btCsrStep(&pSub->csr, bNext);
  if( rc==SQLITE4_NOTFOUND ){
    const void *pV;
    int nV;

#ifndef NDEBUG
    const void *pTmp; int nTmp;
    rc = btCsrKey(&pSub->mcsr, &pTmp, &nTmp);
    assert( rc==SQLITE4_OK && memcmp(pTmp, pSub->aPrefix, 8)==0 );
#endif

    rc = btCsrStep(&pSub->mcsr, bNext);
    if( rc==SQLITE4_OK ){
      rc = btCsrKey(&pSub->mcsr, &pV, &nV);
    }
    if( rc==SQLITE4_OK ){
      rc = fiSubCsrCheckPrefix(pSub);
    }
    if( rc==SQLITE4_OK ){
      rc = btCsrData(&pSub->mcsr, 0, 4, &pV, &nV);
    }
    if( rc==SQLITE4_OK ){
      pSub->csr.iRoot = sqlite4BtGetU32((const u8*)pV);
      rc = btCsrEnd(&pSub->csr, !bNext);
    }
  }
  
  if( bNext==0 ){
    /* If this is an xPrev() operation, check that the cursor has not moved
    ** into a part of the sub-tree that has been gobbled up by an ongoing
    ** merge.  */
    const void *pMin; int nMin;
    const void *pKey; int nKey;

    if( rc==SQLITE4_OK ) rc = btCsrKey(&pSub->mcsr, &pMin, &nMin);
    if( rc==SQLITE4_OK ) rc = btCsrKey(&pSub->csr, &pKey, &nKey);

    if( rc==SQLITE4_OK && btKeyCompare((u8*)pMin+8, nMin-8, pKey, nKey)>0 ){
      rc = SQLITE4_NOTFOUND;
      btCsrReset(&pSub->mcsr, 0);
      btCsrReset(&pSub->csr, 0);
    }
  }

  return rc;
}

/*
** Advance the cursor. The direction (xPrev or xNext) is implied by the
** cursor itself - as fast-insert cursors may only be advanced in one
** direction.
*/
static int fiCsrStep(FiCursor *pCsr){
  int rc = SQLITE4_OK;
  int bNext = (0!=(pCsr->base.flags & CSR_NEXT_OK));
  const void *pKey; int nKey;     /* Current key that cursor points to */
  int i;

#ifndef NDEBUG
  sqlite4_buffer buf;
  sqlite4_buffer_init(&buf, 0);
  sqlite4BtCsrKey(&pCsr->base, &pKey, &nKey);
  sqlite4_buffer_set(&buf, pKey, nKey);
#endif

  assert_ficursor_ok(pCsr, rc);
  assert( pCsr->base.flags & (CSR_NEXT_OK | CSR_PREV_OK) );
  assert( pCsr->iBt>=0 );

  do{
    /* Load the current key in to pKey/nKey. Then advance all sub-cursors 
    ** that share a key with the current sub-cursor. */
    rc = sqlite4BtCsrKey(&pCsr->base, &pKey, &nKey);
    for(i=0; rc==SQLITE4_OK && i<pCsr->nBt; i++){
      FiSubCursor *pSub = &pCsr->aSub[i];
      if( i!=pCsr->iBt && pSub->csr.nPg>0 ){
        const void *p; int n;       /* Key that this sub-cursor points to */
        rc = btCsrKey(&pSub->csr, &p, &n);
        if( rc==SQLITE4_OK && btKeyCompare(p, n, pKey, nKey)==0 ){
          rc = fiSubCsrStep(pCsr, pSub, bNext);
          if( rc==SQLITE4_NOTFOUND ){
            assert( pSub->csr.nPg==0 );
            rc = SQLITE4_OK;
          }
        }
      }
    }

    /* Advance the current sub-cursor */
    if( rc==SQLITE4_OK ){
      rc = fiSubCsrStep(pCsr, &pCsr->aSub[pCsr->iBt], bNext);
      if( rc==SQLITE4_NOTFOUND ){
        assert( pCsr->aSub[pCsr->iBt].csr.nPg==0 );
        rc = SQLITE4_OK;
      }
    }

    /* Figure out a new current bt cursor */
    if( rc==SQLITE4_OK ){
      rc = fiCsrSetCurrent(pCsr);
    }
  }while( rc==SQLITE4_OK && fiCsrIsDelete(pCsr) );

#ifndef NDEBUG
  if( rc==SQLITE4_OK ){
    sqlite4BtCsrKey(&pCsr->base, &pKey, &nKey);
    assert( btKeyCompare(buf.p, buf.n, pKey, nKey) * (bNext?1:-1) < 0 );
  }
  sqlite4_buffer_clear(&buf);
#endif
  assert_ficursor_ok(pCsr, rc);

  return rc;
}

typedef struct FiLevelIter FiLevelIter;
struct FiLevelIter {
  /* Used internally */
  BtCursor csr;                   /* Cursor used to read summary blob */
  const u8 *aSum;                 /* Summary blob */
  int nSum;                       /* Size of summary blob in bytes */

  /* Output values */
  int nSub;                       /* Total number of expected levels */
  int iAge;                       /* Current age */
  int iLvl;                       /* Current level */
  int iSub;                       /* Current sub-cursor */
};

static int fiLevelIterNext(FiLevelIter *p){
  u16 iMin, nLevel;

  p->iSub++;
  p->iLvl--;
  btReadSummary(p->aSum, p->iAge, &iMin, &nLevel, 0);
  while( p->iLvl<(int)iMin ){
    p->iAge++;
    if( p->iAge>=(p->nSum)/6 ) return 1;
    btReadSummary(p->aSum, p->iAge, &iMin, &nLevel, 0);
    p->iLvl = (int)iMin + (int)nLevel - 1;
  }

  assert( p->iSub<p->nSub );
  return 0;
}

static int fiLevelIterInit(bt_db *db, FiLevelIter *p){
  int rc;                         /* Return code */

  memset(p, 0, sizeof(FiLevelIter));
  rc = fiLoadSummary(db, &p->csr, &p->aSum, &p->nSum);
  if( rc==SQLITE4_OK ){
    int iAge;
    for(iAge=0; iAge<(p->nSum/6); iAge++){
      u16 iMin, nLevel;
      btReadSummary(p->aSum, iAge, &iMin, &nLevel, 0);
      p->nSub += nLevel;
      if( iAge==0 ){
        p->iLvl = ((int)iMin + nLevel);
        p->iSub = -1;
      }
    }
  }

  return rc;
}

static void fiLevelIterCleanup(FiLevelIter *p){
  btCsrReset(&p->csr, 1);
}

/*
** Format values iAge and iLvl into an 8 byte prefix as used in the
** meta-tree.
*/
static void fiFormatPrefix(u8 *aPrefix, u32 iAge, u32 iLvl){
  btPutU32(&aPrefix[0], iAge);
  btPutU32(&aPrefix[4], ~(u32)iLvl);
}

/*
** Seek a fast-insert cursor.
*/
static int fiCsrSeek(FiCursor *pCsr, const void *pK, int nK, int eSeek){
  int rc = SQLITE4_NOTFOUND;      /* Return code */
  bt_db *db = pCsr->base.pDb;     /* Database handle */
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);

  assert( eSeek==BT_SEEK_LE || eSeek==BT_SEEK_EQ || eSeek==BT_SEEK_GE );
  assert( (pCsr->base.flags & CSR_VISIT_DEL)==0 || eSeek==BT_SEEK_GE );
  fiCsrReset(pCsr);

  if( pHdr->iMRoot ){
    u8 *pKey;
    FiLevelIter iter;

    /* Initialize the iterator used to skip through database levels */
    rc = fiLevelIterInit(db, &iter);
    if( rc!=SQLITE4_OK ) return rc;
    pKey = sqlite4_malloc(db->pEnv, nK+8);
    if( pKey==0 ) return SQLITE4_NOMEM;

    if( eSeek==BT_SEEK_EQ ){
      FiSubCursor *pSub;
      BtCursor *pM;

      pCsr->base.flags &= ~(CSR_NEXT_OK | CSR_PREV_OK);

      /* A BT_SEEK_EQ is a special case. There is no need to set up a cursor
      ** that can be advanced (in either direction) in this case. All that
      ** is required is to search each level in order for the requested key 
      ** (or a corresponding delete marker). Once a match is found, there
      ** is no need to search any further. As a result, only a single
      ** sub-cursor is required.  */
      rc = fiCsrAllocateSubs(db, pCsr, 1);
      pSub = pCsr->aSub;
      pM = &pSub->mcsr;

      btCsrSetup(db, pHdr->iMRoot, pM);
      while( 0==fiLevelIterNext(&iter) ){

        fiFormatPrefix(pSub->aPrefix, iter.iAge, iter.iLvl);
        memcpy(pKey, pSub->aPrefix, sizeof(pSub->aPrefix));
        rc = btCsrSeek(pM, 0, pKey, nK+8, BT_SEEK_LE, BT_CSRSEEK_SEEK);

        if( rc==SQLITE4_INEXACT ){
          rc = fiSubCsrCheckPrefix(pSub);
        }

        if( rc==SQLITE4_NOTFOUND ){
          /* All keys in this level are greater than pK/nK. */
          /* no-op */
        }else if( rc==SQLITE4_OK || rc==SQLITE4_INEXACT ){
          const void *pV;
          int nV;
          u32 iRoot;
          sqlite4BtCsrData(&pM->base, 0, 4, &pV, &nV);
          iRoot = sqlite4BtGetU32((const u8*)pV);
          btCsrReset(&pSub->csr, 1);
          btCsrSetup(db, iRoot, &pSub->csr);

          rc = btCsrSeek(&pSub->csr, 0, pK, nK, BT_SEEK_EQ, BT_CSRSEEK_SEEK);
          assert( rc!=SQLITE4_INEXACT );
          if( rc!=SQLITE4_NOTFOUND ){
            /* A hit on the requested key or an error has occurred. Either
            ** way, break out of the loop. If this is a hit, set iBt to
            ** zero so that the BtCsrKey() and BtCsrData() routines know
            ** to return data from the first (only) sub-cursor. */
            assert( pCsr->iBt<0 );
            if( rc==SQLITE4_OK ){
              if( 0==btCsrIsDelete(&pSub->csr) ){
                pCsr->iBt = 0;
              }else{
                rc = SQLITE4_NOTFOUND;
              }
            }
            break;
          }
        }
      }
    }else{
      int bMatch = 0;           /* Found an exact match */
      int bHit = 0;             /* Found at least one entry */

      pCsr->base.flags |= (eSeek==BT_SEEK_GE ? CSR_NEXT_OK : CSR_PREV_OK);

      /* Allocate required sub-cursors. */
      if( rc==SQLITE4_OK ){
        rc = fiCsrAllocateSubs(db, pCsr, iter.nSub);
      }

      /* This loop runs once for each sub-cursor */
      while( rc==SQLITE4_OK && 0==fiLevelIterNext(&iter) ){
        FiSubCursor *pSub = &pCsr->aSub[iter.iSub];
        BtCursor *pM = &pSub->mcsr;
        btCsrSetup(db, pHdr->iMRoot, pM);

        fiFormatPrefix(pSub->aPrefix, iter.iAge, iter.iLvl);
        memcpy(pKey, pSub->aPrefix, sizeof(pSub->aPrefix));

        rc = btCsrSeek(pM, 0, pKey, nK+8, BT_SEEK_LE, BT_CSRSEEK_SEEK);
        if( rc==SQLITE4_INEXACT ) rc = fiSubCsrCheckPrefix(pSub);
        if( rc==SQLITE4_NOTFOUND && eSeek==BT_SEEK_GE ){
          rc = btCsrSeek(pM, 0, pSub->aPrefix, sizeof(pSub->aPrefix), 
              BT_SEEK_GE, BT_CSRSEEK_SEEK
          );
          if( rc==SQLITE4_INEXACT ) rc = fiSubCsrCheckPrefix(pSub);
        }

        if( rc==SQLITE4_NOTFOUND ){
          /* No keys to visit in this level */
          assert( pSub->mcsr.nPg==0 );
          assert( pSub->csr.nPg==0 );
          rc = SQLITE4_OK;
        }else if( rc==SQLITE4_OK || rc==SQLITE4_INEXACT ){
          const void *pV; int nV;
          const void *pSeek = pK; 
          int nSeek = nK;

          u32 iRoot;
          sqlite4BtCsrData(&pM->base, 0, 4, &pV, &nV);
          iRoot = sqlite4BtGetU32((const u8*)pV);
          btCsrReset(&pSub->csr, 1);
          btCsrSetup(db, iRoot, &pSub->csr);

          if( eSeek==BT_SEEK_GE ){
            const void *pMin; int nMin;
            rc = btCsrKey(pM, &pMin, &nMin);
            if( rc!=SQLITE4_OK ) break;
            nMin -= 8;
            pMin = (const void*)((const u8*)pMin + 8);
            if( btKeyCompare(pSeek, nSeek, pMin, nMin)<0 ){
              pSeek = pMin;
              nSeek = nMin;
            }
          }

          rc = btCsrSeek(&pSub->csr, 0, pSeek, nSeek, eSeek, BT_CSRSEEK_SEEK);
          if( rc==SQLITE4_NOTFOUND ){
            rc = fiSubCsrStep(pCsr, pSub, (eSeek==BT_SEEK_GE ? 1 : 0));
          }else{
            if( rc==SQLITE4_OK ) bMatch = 1;
            if( rc==SQLITE4_INEXACT ) bHit = 1;
          }

          if( rc==SQLITE4_INEXACT || rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;
        }else{
          /* An error */
        }
      }
      assert( rc!=SQLITE4_OK || iter.iSub==iter.nSub );

      if( rc==SQLITE4_OK ){
        rc = fiCsrSetCurrent(pCsr);
        if( rc==SQLITE4_OK ){
          if( fiCsrIsDelete(pCsr) ){
            rc = fiCsrStep(pCsr);
            if( rc==SQLITE4_OK ) rc = SQLITE4_INEXACT;
          }else if( bMatch==0 ){
            rc = (bHit ? SQLITE4_INEXACT : SQLITE4_NOTFOUND);
          }
        }
      }
    }

    sqlite4_free(db->pEnv, pKey);
    fiLevelIterCleanup(&iter);
  }

  return rc;
}

static int fiCsrEnd(FiCursor *pCsr, int bLast){
  bt_db *db = pCsr->base.pDb;
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
  FiLevelIter iter;         /* Used to iterate through all f-tree levels */
  int rc;                   /* Return code */

  assert( (pCsr->base.flags & CSR_VISIT_DEL)==0 );

  rc = fiLevelIterInit(db, &iter);
  if( rc==SQLITE4_OK ){
    rc = fiCsrAllocateSubs(db, pCsr, iter.nSub);
  }

  while( rc==SQLITE4_OK && 0==fiLevelIterNext(&iter) ){
    FiSubCursor *pSub = &pCsr->aSub[iter.iSub];
    const int n = (int)sizeof(pSub->aPrefix);

    btPutU32(pSub->aPrefix, (u32)iter.iAge);
    btPutU32(&pSub->aPrefix[4], ~(u32)iter.iLvl);

    btCsrSetup(db, pHdr->iMRoot, &pSub->mcsr);
    if( bLast==0 ){
      rc = btCsrSeek(&pSub->mcsr, 0, pSub->aPrefix, n, BT_SEEK_GE, 0);
    }else{
      u8 aPrefix[8];
      btPutU32(aPrefix, (u32)iter.iAge + (iter.iLvl==0 ? 1 : 0));
      btPutU32(&aPrefix[4], ~((u32)iter.iLvl - (u32)1));
      rc = btCsrSeek(&pSub->mcsr, 0, aPrefix, n, BT_SEEK_LE, 0);
      if( rc==SQLITE4_OK ){
        rc = btCsrStep(&pSub->mcsr, 0);
      }
    }
    if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
    if( rc==SQLITE4_OK ) rc = fiSubCsrCheckPrefix(pSub);

    if( rc==SQLITE4_OK ){
      const void *pV;
      int nV;
      int iRoot;
      btCsrData(&pSub->mcsr, 0, 4, &pV, &nV);
      iRoot = sqlite4BtGetU32((const u8*)pV);
      btCsrReset(&pSub->csr, 1);
      btCsrSetup(db, iRoot, &pSub->csr);
      if( bLast ){
        rc = btCsrEnd(&pSub->csr, 1);
      }else{
        const void *pK; int nK;
        rc = btCsrKey(&pSub->mcsr, &pK, &nK);
        if( rc==SQLITE4_OK ){
          rc = btCsrSeek(&pSub->csr, 0, ((u8*)pK)+8, nK-8, BT_SEEK_GE, 0);
          if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
          if( rc==SQLITE4_NOTFOUND ) rc = btErrorBkpt(SQLITE4_CORRUPT);
        }
      }
    }else if( rc==SQLITE4_NOTFOUND ){
      btCsrReset(&pSub->mcsr, 0);
      rc = SQLITE4_OK;
    }
  }
  fiLevelIterCleanup(&iter);

  if( rc==SQLITE4_OK ){
    pCsr->base.flags &= ~(CSR_NEXT_OK | CSR_PREV_OK);
    pCsr->base.flags |= (bLast ? CSR_PREV_OK : CSR_NEXT_OK);
    rc = fiCsrSetCurrent(pCsr);
    if( rc==SQLITE4_OK && btCsrIsDelete(&pCsr->aSub[pCsr->iBt].csr) ){
      rc = fiCsrStep(pCsr);
    }
  }

  return rc;
}

SQLITE4_PRIVATE int sqlite4BtCsrSeek(
  bt_cursor *pBase, 
  const void *pK,                 /* Key to seek for */
  int nK,                         /* Size of key pK in bytes */
  int eSeek                       /* Seek mode (a BT_SEEK_XXX constant) */
){
  int rc;
  btCheckPageRefs(pBase->pDb);
  if( IsBtCsr(pBase) ){
    BtCursor *pCsr = (BtCursor*)pBase;
    rc = btCsrSeek(pCsr, 0, pK, nK, eSeek, BT_CSRSEEK_SEEK);
  }else{
    FiCursor *pCsr = (FiCursor*)pBase;
    rc = fiCsrSeek(pCsr, pK, nK, eSeek);
    assert_ficursor_ok(pCsr, rc);
  }
  btCheckPageRefs(pBase->pDb);
  return rc;
}

/*
** Position cursor pCsr to point to the smallest key in the database.
*/
SQLITE4_PRIVATE int sqlite4BtCsrFirst(bt_cursor *pBase){
  int rc;
  if( IsBtCsr(pBase) ){
    rc = btCsrEnd((BtCursor*)pBase, 0);
  }else{
    rc = fiCsrEnd((FiCursor*)pBase, 0);
    assert_ficursor_ok((FiCursor*)pBase, rc);
  }
  return rc;
}

/*
** Position cursor pCsr to point to the largest key in the database.
*/
SQLITE4_PRIVATE int sqlite4BtCsrLast(bt_cursor *pBase){
  int rc;
  if( IsBtCsr(pBase) ){
    rc = btCsrEnd((BtCursor*)pBase, 1);
  }else{
    rc = fiCsrEnd((FiCursor*)pBase, 1);
    assert_ficursor_ok((FiCursor*)pBase, rc);
  }
  return rc;
}


/*
** Advance to the next entry in the tree.
*/
SQLITE4_PRIVATE int sqlite4BtCsrNext(bt_cursor *pBase){
  int rc;
  if( IsBtCsr(pBase) ){
    rc = btCsrStep((BtCursor*)pBase, 1);
  }else{
    rc = fiCsrStep((FiCursor*)pBase);
  }
  return rc;
}

/*
** Retreat to the previous entry in the tree.
*/
SQLITE4_PRIVATE int sqlite4BtCsrPrev(bt_cursor *pBase){
  int rc;
  if( IsBtCsr(pBase) ){
    rc = btCsrStep((BtCursor*)pBase, 0);
  }else{
    rc = fiCsrStep((FiCursor*)pBase);
  }
  return rc;
}

/*
** Helper function for btOverflowDelete(). 
**
** TODO: This uses recursion. Which is almost certainly not a problem 
** here, but makes some people nervous, so should probably be changed.
*/
static int btOverflowTrimtree(
  const int pgsz, 
  BtPager *pPager, 
  u32 pgno, 
  int nDepth
){
  int rc = SQLITE4_OK;

  assert( nDepth<=8 );
  if( nDepth>0 ){
    const int nPgPtr = pgsz / 4;
    BtPage *pPg;
    u8 *aData;
    int i;

    rc = sqlite4BtPageGet(pPager, pgno, &pPg);
    if( rc!=SQLITE4_OK ) return rc;
    aData = btPageData(pPg);

    for(i=0; rc==SQLITE4_OK && i<nPgPtr; i++){
      u32 child = btGetU32(&aData[i*4]);
      if( child==0 ) break;
      rc = btOverflowTrimtree(pgsz, pPager, child, nDepth-1);
    }

    sqlite4BtPageRelease(pPg);
  }
  
  sqlite4BtPageTrimPgno(pPager, pgno);
  return rc;
}

/*
** Cursor pCsr currently points to a leaf page cell. If the leaf page
** cell contains an overflow array, all overflow pages are trimmed here.
**
** SQLITE4_OK is returned if no error occurs, or an SQLite4 error code
** otherwise.
*/
static int btOverflowDelete(BtCursor *pCsr){
  BtPager *pPager = pCsr->base.pDb->pPager;
  const int pgsz = sqlite4BtPagerPagesize(pPager);
  u8 *aData;
  u8 *pCell;
  u8 *pOvfl = 0;
  int iCell = pCsr->aiCell[pCsr->nPg-1];
  int n;
  int rc = SQLITE4_OK;
  
  aData = (u8*)btPageData(pCsr->apPage[pCsr->nPg-1]);
  assert( btCellCount(aData, pgsz)>iCell );
  pCell = btCellFind(aData, pgsz, iCell);
  pCell += sqlite4BtVarintGet32(pCell, &n);

  if( n==0 ){
    /* Type (c) cell */
    pCell += sqlite4BtVarintGet32(pCell, &n);
    pCell += n;
    pCell += sqlite4BtVarintGet32(pCell, &n);
    pCell += sqlite4BtVarintGet32(pCell, &n);
    pOvfl = pCell;
  }else{
    pCell += n;
    pCell += sqlite4BtVarintGet32(pCell, &n);
    if( n==0 ){
      /* Type (b) cell */
      pCell += sqlite4BtVarintGet32(pCell, &n);
      pCell += n;
      pCell += sqlite4BtVarintGet32(pCell, &n);
      pOvfl = pCell;
    }
  }

  if( pOvfl ){
    int i;
    int nDirect = (int)(pOvfl[0] & 0x0F);
    int nDepth = (int)(pOvfl[0]>>4);

    /* Trim the "direct" pages. */
    for(i=0; rc==SQLITE4_OK && i<(nDirect + (nDepth==0)); i++){
      u32 pgno = btGetU32(&pOvfl[1 + i*4]);
      rc = sqlite4BtPageTrimPgno(pPager, pgno);
    }

    /* Now trim the pages that make up the overflow tree. */
    if( nDepth>0 ){
      u32 rootpgno = btGetU32(&pOvfl[1 + nDirect*4]);
      rc = btOverflowTrimtree(pgsz, pPager, rootpgno, nDepth);
    }
  }

  return rc;
}

static int btCsrData(
  BtCursor *pCsr,                 /* Cursor handle */
  int iOffset,                    /* Offset of requested data */
  int nByte,                      /* Bytes requested (or -ve for all avail.) */
  const void **ppV,               /* OUT: Pointer to data buffer */
  int *pnV                        /* OUT: Size of data buffer in bytes */
){
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  int rc;
  u8 *aData;
  u8 *pCell;
  int nK = 0;
  int nV = 0;

  rc = btCsrReseek(pCsr);
  if( rc==SQLITE4_OK ){
    if( pCsr->bSkipNext || pCsr->bSkipPrev ){
      /* The row has been deleted out from under this cursor. So return
       ** NULL for data.  */
      *ppV = 0;
      *pnV = 0;
    }else{
      int iCell = pCsr->aiCell[pCsr->nPg-1];

      aData = (u8*)btPageData(pCsr->apPage[pCsr->nPg-1]);
      pCell = btCellFind(aData, pgsz, iCell);
      pCell += sqlite4BtVarintGet32(pCell, &nK);
      if( nK>0 ){
        pCell += nK;
        pCell += sqlite4BtVarintGet32(pCell, &nV);
      }

      if( nV==0 ){
        /* Type (b) or (c) cell */
        rc = btCsrBuffer(pCsr, 1);
        if( rc==SQLITE4_OK ){
          u8 *aBuf = (u8*)pCsr->ovfl.buf.p;
          *ppV = &aBuf[pCsr->ovfl.nKey];
          *pnV = pCsr->ovfl.nVal;
        }
      }else{
        /* Type (a) cell */
        *ppV = pCell;
        *pnV = (nV-2);
      }

#ifndef NDEBUG
      if( rc==SQLITE4_OK ){
        const void *pK; int nK;
        rc = sqlite4BtCsrKey((bt_cursor*)pCsr, &pK, &nK);
        if( rc==SQLITE4_OK ){
          BtLock *pLock = (BtLock*)pCsr->base.pDb->pPager;
          sqlite4BtDebugKV(pLock, "select", (u8*)pK, nK, (u8*)*ppV, *pnV);
        }
      }
#endif
    }
  }

  return rc;
}

SQLITE4_PRIVATE int sqlite4BtCsrKey(bt_cursor *pBase, const void **ppK, int *pnK){
  int rc = SQLITE4_OK;            /* Return code */
  
  if( IsBtCsr(pBase) ){
    rc = btCsrKey((BtCursor*)pBase, ppK, pnK);
  }else{
    FiCursor *pCsr = (FiCursor*)pBase;
    assert( pCsr->iBt>=0 );
    rc = btCsrKey(&pCsr->aSub[pCsr->iBt].csr, ppK, pnK);
  }

  return rc;
}

SQLITE4_PRIVATE int sqlite4BtCsrData(
  bt_cursor *pBase,               /* Cursor handle */
  int iOffset,                    /* Offset of requested data */
  int nByte,                      /* Bytes requested (or -ve for all avail.) */
  const void **ppV,               /* OUT: Pointer to data buffer */
  int *pnV                        /* OUT: Size of data buffer in bytes */
){
  int rc = SQLITE4_OK;            /* Return code */
  
  if( IsBtCsr(pBase) ){
    rc = btCsrData((BtCursor*)pBase, iOffset, nByte, ppV, pnV);
  }else{
    FiCursor *pCsr = (FiCursor*)pBase;
    assert( pCsr->iBt>=0 );
    rc = btCsrData(&pCsr->aSub[pCsr->iBt].csr, iOffset, nByte, ppV, pnV);
  }

  return rc;
}

/*
** The argument points to a buffer containing an overflow array. Return
** the size of the overflow array in bytes. 
*/
static int btOverflowArrayLen(u8 *p){
  return 1 + ((int)(p[0] & 0x0F) + 1) * 4;
}

static int btCellSize(u8 *pCell, int bLeaf){
  u8 *p = pCell;
  int nKey;

  p += sqlite4BtVarintGet32(p, &nKey);
  if( bLeaf==0 ){
    /* Internal page cell */
    p += nKey;
    p += 4;
  }else if( nKey==0 ){
    /* Type (c) cell */
    p += sqlite4BtVarintGet32(p, &nKey);
    p += nKey;
    p += sqlite4BtVarintGet32(p, &nKey);
    p += sqlite4BtVarintGet32(p, &nKey);
    p += btOverflowArrayLen(p);
  }else{
    p += nKey;
    p += sqlite4BtVarintGet32(p, &nKey);
    if( nKey==0 ){
      /* Type (b) cell */
      p += sqlite4BtVarintGet32(p, &nKey);
      p += nKey;
      p += sqlite4BtVarintGet32(p, &nKey);
      p += btOverflowArrayLen(p);
    }else if( nKey>=2 ){
      p += (nKey-2);
    }
  }

  return (p-pCell);
}

static u8 *btCellFindSize(u8 *aData, int nData, int iCell, int *pnByte){
  u8 *pCell;

  pCell = btCellFind(aData, nData, iCell);
  *pnByte = btCellSize(pCell, 0==(btFlags(aData) & BT_PGFLAGS_INTERNAL));
  return pCell;
}

/*
** Return a pointer to and the size of the cell that cursor pCsr currently
** points to.
*/
static void fiCsrCell(FiCursor *pCsr, const void **ppCell, int *pnCell){
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  FiSubCursor *pSub;              /* Current sub-cursor */
  u8 *aData;                      /* Current page data */
  int iCell;

  assert( pCsr->iBt>=0 );
  pSub = &pCsr->aSub[pCsr->iBt];
  aData = btPageData(pSub->csr.apPage[pSub->csr.nPg-1]);
  iCell = pSub->csr.aiCell[pSub->csr.nPg-1];

  *ppCell = btCellFindSize(aData, pgsz, iCell, pnCell);
}

/*
** Return true if the cell that the cursor currently points to contains 
** pointers to one or more overflow pages. Or false otherwise.
*/
static int btCsrOverflow(BtCursor *pCsr){
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  u8 *aData;                      /* Current page data */
  int nKey;                       /* First varint in cell */
  int res;                       /* First varint in cell */

  aData = btPageData(pCsr->apPage[pCsr->nPg-1]);
  aData = btCellFind(aData, pgsz, pCsr->aiCell[pCsr->nPg-1]);

  aData += sqlite4BtVarintGet32(aData, &nKey);
  res = (nKey==0 || aData[nKey]==0);
  return res;
}

/*
** Allocate a new page buffer.
*/
static int btNewBuffer(bt_db *pDb, u8 **paBuf){
  const int pgsz = sqlite4BtPagerPagesize(pDb->pPager);
  u8 *aBuf;

  *paBuf = aBuf = sqlite4_malloc(pDb->pEnv, pgsz);
  if( aBuf==0 ) return btErrorBkpt(SQLITE4_NOMEM);

#ifndef NDEBUG
  /* This stops valgrind from complaining about unitialized bytes when (if)
  ** this buffer is eventually written out to disk.  */
  memset(aBuf, 0x66, pgsz);
#endif

  return SQLITE4_OK;
}

/*
** Discard a page buffer allocated using btNewBuffer.
*/
static void btFreeBuffer(bt_db *pDb, u8 *aBuf){
  sqlite4_free(pDb->pEnv, aBuf);
}

/*
** Attach a buffer to an existing page object.
*/
static int btSetBuffer(bt_db *pDb, BtPage *pPg, u8 *aBuf){
  const int pgsz = sqlite4BtPagerPagesize(pDb->pPager);
  int rc;
  rc = sqlite4BtPageWrite(pPg);
  if( rc==SQLITE4_OK ){
    u8 *aData = btPageData(pPg);
    memcpy(aData, aBuf, pgsz);
    sqlite4_free(pDb->pEnv, aBuf);
  }
  return rc;
}

/*
** Defragment the b-tree page passed as the first argument. Return 
** SQLITE4_OK if successful, or an SQLite error code otherwise.
*/
static int btDefragmentPage(bt_db *pDb, BtPage *pPg){
  const int pgsz = sqlite4BtPagerPagesize(pDb->pPager);
  u8 *aData;                      /* Pointer to buffer of pPg */
  u8 *aTmp;                       /* Temporary buffer to assemble new page in */
  int nCell;                      /* Number of cells on page */
  int iWrite;                     /* Write next cell at this offset in aTmp[] */
  int i;                          /* Used to iterate through cells */
  int bLeaf;                      /* True if pPg is a leaf page */
  int nHdr;                       /* Bytes in header of this page */

  if( btNewBuffer(pDb, &aTmp) ) return SQLITE4_NOMEM;

  aData = btPageData(pPg);
  nCell = btCellCount(aData, pgsz);

  bLeaf = 0==(btFlags(aData) & BT_PGFLAGS_INTERNAL);
  nHdr = bLeaf ? 1 : 5;

  /* Set header bytes of new page */
  memcpy(aTmp, aData, nHdr);

  iWrite = nHdr;
  for(i=0; i<nCell; i++){
    int nByte;
    u8 *pCell;
    pCell = btCellFindSize(aData, pgsz, i, &nByte);

    btPutU16(btCellPtrFind(aTmp, pgsz, i), iWrite);
    memcpy(&aTmp[iWrite], pCell, nByte);
    iWrite += nByte;
  }

  /* Write the rest of the page footer */
  btPutU16(&aTmp[pgsz-2], nCell);
  btPutU16(&aTmp[pgsz-4], pgsz - (3+nCell)*2 - iWrite);
  btPutU16(&aTmp[pgsz-6], iWrite);

  btSetBuffer(pDb, pPg, aTmp);
  return SQLITE4_OK;
}

/*
** The following type is used to represent a single cell or cell value
** by the code that updates and rebalances the tree structure. It is
** usually manipulated using the btKV*() functions and macros.
**
** An instance of type KeyValue may represent three different types
** of cell values:
**
**   * (eType==KV_VALUE && pgno!=0): A value for an internal cell. In this case
**     pK points to a buffer nK bytes in size containing the key prefix and 
**     pgno contains the page number of the cells child page.
**
**   * (eType==KV_VALUE && pgno==0): A value for a leaf cell. The 
**     key is identified by (pK/nK) and the value by (pV/nV).
**
**   * (eType==KV_CELL): A formatted leaf cell stored in (pV/nV). This is 
**     used for cells with overflow arrays.
*/
#define KV_VALUE     0
#define KV_CELL      1
typedef struct KeyValue KeyValue;
struct KeyValue {
  int eType;
  const void *pK; int nK;
  const void *pV; int nV;
  u32 pgno;
};

/*
** Return the number of bytes consumed by a cell generated based on *pKV.
**
** If the KeyValue is not already in KV_CELL form, then assume it will
** be formatted as a type (a) cell.
*/
static int btKVCellSize(KeyValue *pKV){
  int nByte;
  assert( pKV->eType==KV_CELL || pKV->eType==KV_VALUE );
  if( pKV->eType==KV_CELL ){
    nByte = pKV->nV;
  }else{
    if( pKV->pgno ){
      nByte = sqlite4BtVarintLen32(pKV->nK) + pKV->nK + 4;
    }else{
      assert( pKV->nV>=0 || pKV->pV==0 );
      nByte = 
        sqlite4BtVarintLen32(pKV->nK) 
        + sqlite4BtVarintLen32(pKV->nV+2)
        + MAX(pKV->nV, 0) + pKV->nK;
    }
  }
  return nByte;
}

/*
** Write a cell based on *pKV to buffer aBuffer. Return the number
** of bytes written.
*/
static int btKVCellWrite(KeyValue *pKV, u8 *aBuf){
  int i = 0;
  if( pKV->eType==KV_CELL ){
    i = pKV->nV;
    memcpy(aBuf, pKV->pV, i);
  }else{
    i += sqlite4BtVarintPut32(&aBuf[i], pKV->nK);
    memcpy(&aBuf[i], pKV->pK, pKV->nK); i += pKV->nK;

    if( pKV->pgno==0 ){
      i += sqlite4BtVarintPut32(&aBuf[i], pKV->nV+2);
      if( pKV->nV>0 ){
        memcpy(&aBuf[i], pKV->pV, pKV->nV); 
        i += pKV->nV;
      }
    }else{
      btPutU32(&aBuf[i], pKV->pgno);
      i += 4;
    }
  }

  assert( i==btKVCellSize(pKV) );
  return i;
}

/*
** Return the number of bytes of leaf page space required by an 
** overflow array containing nContent bytes of content, assuming the 
** page size is pgsz.
*/
static int btOverflowArraySz(int pgsz, int nContent){
  int nPg;
  nPg = (nContent + pgsz - 1) / pgsz;
  if( nPg<=BT_MAX_DIRECT_OVERFLOW ){
    return 1 + nPg*4;
  }
  return 1 + (BT_MAX_DIRECT_OVERFLOW+1) * 4;
}

/*
** Allocate a non-overflow page.
**
** This function is a simple wrapper around sqlite4BtPageAllocate(),
** except that if the database is currenly in fast-insert mode the
** BtDbHdr.nSubPg counter is incremented.
*/
static int btAllocateNonOverflow(bt_db *db, BtPage **ppPg){
  int rc;
  if( db->bFastInsertOp ){
    BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
    u32 iPg;

    sqlite4BtPagerDbhdrDirty(db->pPager);
    iPg = pHdr->nSubPg + btFirstOfBlock(pHdr, pHdr->iSubBlock);
    pHdr->nSubPg++;
    rc = sqlite4BtPageGet(db->pPager, iPg, ppPg);
    if( rc==SQLITE4_OK ){
      rc = sqlite4BtPageWrite(*ppPg);
      if( rc!=SQLITE4_OK ){
        sqlite4BtPageRelease(*ppPg);
      }
    }
  }else{
    rc = sqlite4BtPageAllocate(db->pPager, ppPg);
  }
  return rc;
}

/*
** Trim a non-overflow page.
*/
static int btTrimNonOverflow(bt_db *db, BtPage *pPg){
  int rc;                         /* Return code */
  if( db->bFastInsertOp==0 ){
    rc = sqlite4BtPageTrim(pPg);
  }else{
    rc = sqlite4BtPageRelease(pPg);
  }
  return rc;
}

/*
** Allocate and zero an overflow page.
*/
static int btAllocateAndZero(bt_db *db, BtPage **ppPg){
  BtPage *pPg = 0;                /* Allocated page handle */
  int rc;                         /* Return code */

  rc = sqlite4BtPageAllocate(db->pPager, &pPg);
  if( rc==SQLITE4_OK ){
    const int pgsz = sqlite4BtPagerPagesize(db->pPager);
    memset(btPageData(pPg), 0, pgsz);
  }

  *ppPg = pPg;
  return rc;
}

static int btOverflowArrayPopulate(
  bt_db *db, u8 **ppOut,
  u8 *pBuf1, int nBuf1,
  u8 *pBuf2, int nBuf2
){
  const int pgsz = sqlite4BtPagerPagesize(db->pPager);
  const int nPgPtr = pgsz / 4;
  int rc = SQLITE4_OK;
  int n1 = 0;
  int n2 = 0;
  int iOvfl;
  int nDirect = 0;
  int nDepth = 0;
  int nOvfl;
  int i;
  u8 *aOut = *ppOut;

  struct Heir {
    BtPage *pPg;
    int iCell;
  } apHier[8];
  memset(apHier, 0, sizeof(apHier));

  /* Calculate the number of required overflow pages. And the depth of
  ** the overflow tree.  */
  nOvfl = (nBuf1+nBuf2+pgsz-1) / pgsz;
  nOvfl -= BT_MAX_DIRECT_OVERFLOW;
  while( nOvfl>1 ){
    nDepth++;
    nOvfl = (nOvfl+nPgPtr-1) / nPgPtr;
  }

  for(i=0; rc==SQLITE4_OK && i<nDepth; i++){
    u32 pgno;
    rc = btAllocateAndZero(db, &apHier[i].pPg);
    pgno = sqlite4BtPagePgno(apHier[i].pPg);
    if( i==0 ){
      btPutU32(&aOut[1 + BT_MAX_DIRECT_OVERFLOW*4], pgno);
    }else{
      u8 *a = btPageData(apHier[i-1].pPg);
      btPutU32(a, pgno);
      apHier[i-1].iCell++;
    }
  }

  for(iOvfl=0; rc==SQLITE4_OK && (n1<nBuf1 || n2<nBuf2); iOvfl++){
    int nCopy1, nCopy2;           /* Bytes to copy from pBuf1 and pBuf2 */
    u8 *aData;
    BtPage *pPg;
    u32 pgno;

    rc = sqlite4BtPageAllocate(db->pPager, &pPg);
    if( rc!=SQLITE4_OK ) break;
    aData = btPageData(pPg);
    pgno = sqlite4BtPagePgno(pPg);

    nCopy1 = MIN(pgsz, nBuf1 - n1);
    nCopy2 = MIN(pgsz - nCopy1, nBuf2 - n2);

    memcpy(aData, &pBuf1[n1], nCopy1); n1 += nCopy1;
    memcpy(&aData[nCopy1], &pBuf2[n2], nCopy2); n2 += nCopy2;
    rc = sqlite4BtPageRelease(pPg);
    if( rc!=SQLITE4_OK ) break;

    if( iOvfl<(BT_MAX_DIRECT_OVERFLOW+(nDepth==0)) ){
      btPutU32(&aOut[1 + iOvfl*4], pgno);
      nDirect++;
    }else{
      assert( nDepth>0 );
      for(i=nDepth-1; pgno && i>=0; i--){
        u8 *a = btPageData(apHier[i].pPg);
        if( apHier[i].iCell==nPgPtr ){
          BtPage *pNew = 0;
          rc = sqlite4BtPageRelease(apHier[i].pPg);
          if( rc==SQLITE4_OK ){
            rc = btAllocateAndZero(db, &pNew);
            if( rc==SQLITE4_OK ){
              u8 *a = btPageData(pNew);
              btPutU32(a, pgno);
              pgno = sqlite4BtPagePgno(pNew);
            }
          }

          if( rc!=SQLITE4_OK ){
            pgno = 0;
          }

          apHier[i].pPg = pNew;
          apHier[i].iCell = 1;
        }else{
          btPutU32(&a[apHier[i].iCell*4], pgno);
          apHier[i].iCell++;
          pgno = 0;
        }
      }
    }
  }

  for(i=0; i<nDepth; i++){
    int rc2 = sqlite4BtPageRelease(apHier[i].pPg);
    if( rc==SQLITE4_OK ) rc = rc2;
  }

  if( rc==SQLITE4_OK ){
    if( nDepth==0 ){
      nDirect--;
    }
    assert( nDirect>=0 );
    aOut[0] = (u8)nDirect | (u8)(nDepth<<4) ;
  }

  *ppOut = &aOut[1 + (nDirect+1)*4];
  return rc;
}

/*
** Argument pKV contains a key/value pair destined for a leaf page in
** a database with page size pgsz. Currently it is in KV_VALUE form.
** If the key/value pair is too large to fit entirely within a leaf
** page, this function allocates and writes the required overflow
** pages to the database, and converts pKV to a KV_CELL cell (that
** contains the overflow array).
*/
static int btOverflowAssign(bt_db *db, KeyValue *pKV){
  const int pgsz = sqlite4BtPagerPagesize(db->pPager);
  int nMaxSize = (pgsz - 1 - 6 - 2);
  int nReq;
  int rc = SQLITE4_OK;

  assert( pKV->pgno==0 && pKV->eType==KV_VALUE );

  /* Check if this is a type (a) cell - one that can fit entirely on a 
  ** leaf page. If so, do nothing.  */
  nReq = btKVCellSize(pKV);
  if( nReq > nMaxSize ){
    int nArraySz = btOverflowArraySz(pgsz, pKV->nK + MAX(0, pKV->nV));
    u8 *pBuf = 0;                 /* Buffer containing formatted cell */
    int nKeyOvfl;                 /* Bytes of key that overflow */
    int nValOvfl;                 /* Bytes of value that overflow */

    /* Check if the entire key can fit on a leaf page. If so, this is a
    ** type (b) page - entire key and partial value on the leaf page, 
    ** overflow pages contain the rest of the value.  
    **
    ** This expression uses sqlite4BtVarintLen32() to calculate an upper
    ** bound for the size of the varint that indicates the number of bytes
    ** of the value stored locally.  */
    nReq = 1 + sqlite4BtVarintLen32(pKV->nK) + pKV->nK 
         + 1 + sqlite4BtVarintLen32(pKV->nV) + nArraySz;
    if( nReq<nMaxSize && pKV->nV>=0 ){
      /* nSpc is initialized to the amount of space available to store:
      **
      **    * varint containing number of bytes stored locally (nLVal).
      **    * nLVal bytes of content.
      **    * varint containing number of bytes in overflow pages.
      */
      int nLVal;                  /* Bytes of value data on main page */
      int nSpc = (nMaxSize 
          - sqlite4BtVarintLen32(pKV->nK) - pKV->nK - 1 - nArraySz
      );
      nLVal = nSpc - sqlite4BtVarintLen32(pgsz) - sqlite4BtVarintLen32(pKV->nV);
      nKeyOvfl = 0;
      nValOvfl = pKV->nV - nLVal;
    }else{
      /* Type (c) cell. Both the key and value overflow. */
      int nLKey = nMaxSize 
          - 1                                    /* 0x00 byte */
          - sqlite4BtVarintLen32(pgsz)           /* nLKey */
          - sqlite4BtVarintLen32(pKV->nK)        /* nOKey */
          - sqlite4BtVarintLen32(pKV->nV+1)      /* nVal */
          - nArraySz;                            /* overflow array */

      nValOvfl = pKV->nV;
      nKeyOvfl = pKV->nK - nLKey;
    }

    /* Allocate a pager buffer to store the KV_CELL buffer. Using a pager
    ** buffer is convenient here as (a) it is roughly the right size and
    ** (b) can probably be allocated/deallocated faster than a regular
    ** heap allocation.  */
    rc = btNewBuffer(db, &pBuf);

    if( rc==SQLITE4_OK ){
      int nLVal = (pKV->nV - nValOvfl);
      int nLKey = (pKV->nK - nKeyOvfl);
      u8 *pOut = pBuf;

      if( nKeyOvfl>0 ){
        *pOut++ = 0x00;
      }
      pOut += sqlite4BtVarintPut32(pOut, nLKey);
      memcpy(pOut, pKV->pK, nLKey);
      pOut += nLKey;
      if( nKeyOvfl==0 ){
        /* Type (b) cell */
        assert( pKV->nV>=0 );
        *pOut++ = 0x00;
        pOut += sqlite4BtVarintPut32(pOut, nLVal);
        memcpy(pOut, pKV->pV, nLVal);
        pOut += nLVal;
      }else{
        /* Type (c) cell */
        pOut += sqlite4BtVarintPut32(pOut, nKeyOvfl);
      }
      pOut += sqlite4BtVarintPut32(pOut, nValOvfl + (nKeyOvfl>0));

      rc = btOverflowArrayPopulate(db, &pOut,
          (u8*)(pKV->pK) + nLKey, nKeyOvfl,
          (u8*)(pKV->pV) + nLVal, MAX(0, nValOvfl)
      );
      if( rc==SQLITE4_OK ){
        memset(pKV, 0, sizeof(*pKV));
        pKV->pV = pBuf;
        pKV->nV = pOut - pBuf;
        pKV->eType = KV_CELL;
        pBuf = 0;
        assert( pKV->nV<=nMaxSize );
        assert( pKV->nV==btCellSize((u8*)pKV->pV, 1) );
      }
    }

    if( pBuf ){
      btFreeBuffer(db, pBuf);
    }
  }

  return rc;
}

typedef struct BalanceCtx BalanceCtx;
struct BalanceCtx {
  int pgsz;                       /* Database page size */
  int bLeaf;                      /* True if we are rebalancing leaf data */
  u8 flags;                       /* Flags byte for new sibling pages */
  BtCursor *pCsr;                 /* Cursor identifying where to insert pKV */
  int nKV;                        /* Number of KV pairs */
  KeyValue *apKV;                 /* New KV pairs being inserted */

  /* Populated by btGatherSiblings */
  int nIn;                        /* Number of sibling pages */
  BtPage *apPg[5];                /* Array of sibling pages */

  int nCell;                      /* Number of input cells */

  /* Array populated by btBalanceMeasure */
  int *anCellSz;
  
  /* Populated in btBalance() */
  int anOut[5];                   /* Cell counts for output pages */

  /* Variables used by btBalanceOutput */
  int nOut;                       /* Number of output pages */
  int iOut;                       /* Current output page */
  u8 *apOut[5];                   /* Buffers to assemble output in */
  KeyValue aPCell[5];             /* Cells to push into the parent page */
  u8 *pTmp;                       /* Space for apCell[x].pKey if required */
  int iTmp;                       /* Offset to free space within pTmp */
};

static int btGatherSiblings(BalanceCtx *p){
  BtCursor *pCsr = p->pCsr;
  bt_db * const pDb = pCsr->base.pDb; 
  const int pgsz = sqlite4BtPagerPagesize(pDb->pPager);

  int rc = SQLITE4_OK;
  int nCell;                      /* Number of cells in parent page */
  u8 *aParent;                    /* Buffer of parent page */
  int iChild;                     /* Index of child page within parent */
  int nSib;                       /* Number of siblings */
  int iSib;                       /* Index of left-most sibling page */

  int i;

  aParent = btPageData(pCsr->apPage[pCsr->nPg-2]);
  iChild = pCsr->aiCell[pCsr->nPg-2];
  nCell = btCellCount(aParent, pgsz);

  if( nCell<2 ){
    nSib = nCell+1;
  }else{
    nSib = 3;
  }

  if( iChild==0 ){
    iSib = 0;
  }else if( iChild==nCell ){
    iSib = nCell-(nSib-1);
  }else{
    iSib = iChild-1;
  }

  for(i=0; i<nSib && rc==SQLITE4_OK; i++){
    u32 pgno = btChildPgno(aParent, pgsz, iSib+i);
    rc = sqlite4BtPageGet(pDb->pPager, pgno, &p->apPg[i]);
    assert( (iSib+i)!=iChild || p->apPg[i]==pCsr->apPage[pCsr->nPg-1] );
  }
  p->nIn = nSib;

  pCsr->aiCell[pCsr->nPg-2] = iSib;
  return rc;
}

/*
** Argument pCell points to a cell on an internal node. Decode the
** cell into key-value object *pKV. An internal cell always has
** the same format:
**
**     * Number of bytes in the key (nKey) as a varint.
**     * nKey bytes of key data.
**     * A page pointer, stored as a 32-bit big-endian unsigned.
*/
static void btInternalCellToKeyValue(u8 *pCell, KeyValue *pKV){
  pKV->pK = pCell + sqlite4BtVarintGet32(pCell, &pKV->nK);
  pKV->pgno = btGetU32(&((u8*)pKV->pK)[pKV->nK]);
  pKV->pV = 0;
  pKV->nV = 0;
  pKV->eType = KV_VALUE;
}

static int btSetChildPgno(bt_db *pDb, BtPage *pPg, int iChild, u32 pgno){
  const int pgsz = sqlite4BtPagerPagesize(pDb->pPager);
  int rc;

  rc = sqlite4BtPageWrite(pPg);
  if( rc==SQLITE4_OK ){
    u8 *aData = btPageData(pPg);
    int nCell = btCellCount(aData, pgsz);
    if( iChild>=nCell ){
      btPutU32(&aData[1], pgno);
    }else{
      int nKey;
      u8 *pCell = btCellFind(aData, pgsz, iChild);
      pCell += sqlite4BtVarintGet32(pCell, &nKey);
      pCell += nKey;
      btPutU32(pCell, pgno);
    }
  }

  return rc;
}

/* Called recursively by btBalance(). todo: Fix this! */
static int btInsertAndBalance(BtCursor *, int, KeyValue *);
static int btDeleteFromPage(BtCursor *, int);
static int btBalanceIfUnderfull(BtCursor *pCsr);

static int btBalanceMeasure(
  BalanceCtx *p,                  /* Description of balance operation */
  int iCell,                      /* Cell number in this iteration */
  u8 *pCell, int nByte,           /* Binary cell */
  KeyValue *pKV                   /* Key-value cell */
){
  if( pCell ){
    p->anCellSz[iCell] = nByte;
  }else{
    p->anCellSz[iCell] = btKVCellSize(pKV);
  }
  return SQLITE4_OK;
}

static int btBalanceOutput(
  BalanceCtx *p,                  /* Description of balance operation */
  int iCell,                      /* Cell number in this iteration */
  u8 *pCell, int nByte,           /* Binary cell to copy to output */
  KeyValue *pKV                   /* Key-value cell to write to output */
){
  u8 *aOut = p->apOut[p->iOut];   /* Buffer for current output page */
  int iOff;                       /* Offset of new cell within page */
  int nCell;                      /* Number of cells already on page */

  assert( (pCell==0)!=(pKV==0) );

  if( p->bLeaf==0 && iCell==p->anOut[p->iOut] ){
    /* This cell is destined for the parent page of the siblings being
    ** rebalanced. So instead of writing it to a page buffer it is copied
    ** into the BalanceCtx.aPCell[] array. 
    **
    ** When this cell is eventually written to the parent, the accompanying 
    ** page pointer will be the page number of sibling page p->iOut. This
    ** value will be filled in later. 
    **
    ** The pointer that is currently part of the cell is used as the 
    ** right-child pointer of page p->iOut. This value is written now. */
    int nKey;
    u8 *pKey;
    u8 *pCopy;
    u32 pgno;
    KeyValue *pPKey = &p->aPCell[p->iOut];

    if( pCell ){
      pKey = pCell + sqlite4BtVarintGet32(pCell, &nKey);
      pgno = btGetU32(&pKey[nKey]);
    }else{
      assert( pKV->eType==KV_VALUE );
      pKey = (u8*)pKV->pK;
      nKey = pKV->nK;
      pgno = pKV->pgno;
    }

    pCopy = &p->pTmp[p->iTmp];
    p->iTmp += nKey;
    memcpy(pCopy, pKey, nKey);
    pPKey->pK = pCopy;
    pPKey->nK = nKey;

    btPutU32(&aOut[1], pgno);
    p->iOut++;
  }else{

    /* Write the new cell into the output page. */
    iOff = btFreeOffset(aOut, p->pgsz);
    if( iOff==0 ) iOff = (p->bLeaf ? 1 : 5);
    nCell = btCellCount(aOut, p->pgsz);
    btPutU16(btCellPtrFind(aOut, p->pgsz, nCell), iOff);
    if( pCell ){
      memcpy(&aOut[iOff], pCell, nByte);
      iOff += nByte;
    }else{
      iOff += btKVCellWrite(pKV, &aOut[iOff]);
    }
    btPutU16(&aOut[p->pgsz-2], nCell+1);
    btPutU16(&aOut[p->pgsz-6], iOff);

    if( (iCell+1)==p->anOut[p->iOut] ){
      /* That was the last cell for this page. Fill in the rest of the 
      ** output page footer and the flags byte at the start of the page.  */
      int nFree;                    /* Free space remaining on output page */
      nFree = p->pgsz - iOff - (6 + 2*(nCell+1));
      aOut[0] = p->flags;
      btPutU16(&aOut[p->pgsz-4], nFree);

      /* If the siblings are leaf pages, increment BalanceCtx.iOut here.
      ** for internal nodes, it will be incremented by the next call to
      ** this function, after a divider cell is pushed into the parent 
      ** node.  */
      p->iOut += p->bLeaf;
    }
  }

  return SQLITE4_OK;
}

static int btBalanceVisitCells(
  BalanceCtx *p,
  int (*xVisit)(BalanceCtx*, int, u8*, int, KeyValue*)
){
  const int pgsz = sqlite4BtPagerPagesize(p->pCsr->base.pDb->pPager);
  int rc = SQLITE4_OK;            /* Return code */
  int iPg;                        /* Current page in apPg[] */
  int iCall = 0;
  int i;                          /* Used to iterate through KV pairs */

  BtPage *pIns = p->pCsr->apPage[p->pCsr->nPg-1];
  int iIns = p->pCsr->aiCell[p->pCsr->nPg-1];

  /* Check that page pIns is actually a member of the ctx.apPg[] array. */
#ifndef NDEBUG
  for(i=0; p->apPg[i]!=pIns; i++) assert( i<p->nIn );
#endif

  for(iPg=0; iPg<p->nIn && rc==SQLITE4_OK; iPg++){
    BtPage *pPg;                  /* Current page */
    u8 *aData;                    /* Page data */
    int nCell;                    /* Number of cells on page pPg */
    int iCell;                    /* Current cell in pPg */

    pPg = p->apPg[iPg];
    aData = btPageData(pPg);
    nCell = btCellCount(aData, pgsz);

    for(iCell=0; iCell<nCell && rc==SQLITE4_OK; iCell++){
      int nByte;
      u8 *pCell;

      if( pPg==pIns && iCell==iIns ){
        for(i=0; i<p->nKV; i++){
          assert( iCall<p->nCell );
          rc = xVisit(p, iCall++, 0, 0, &p->apKV[i]);
          if( rc!=SQLITE4_OK ) break;
        }
      }

      pCell = btCellFindSize(aData, pgsz, iCell, &nByte);
      rc = xVisit(p, iCall++, pCell, nByte, 0);
    }

    if( pPg==pIns && iIns==nCell ){
      for(i=0; i<p->nKV && rc==SQLITE4_OK; i++){
        assert( iCall<p->nCell );
        rc = xVisit(p, iCall++, 0, 0, &p->apKV[i]);
      }
    }

    /* If the siblings being balanced are not leaves, and the page just
    ** processed was not the right-most sibling, visit a cell from the
    ** parent page.  */
    if( p->bLeaf==0 && iPg<(p->nIn-1) && rc==SQLITE4_OK ){
      int iPar = p->pCsr->nPg-2;
      u8 *aParent = btPageData(p->pCsr->apPage[iPar]);
      u8 *pCell = btCellFind(aParent, pgsz, p->pCsr->aiCell[iPar] + iPg);
      KeyValue kv;
      btInternalCellToKeyValue(pCell, &kv);
      kv.pgno = btGetU32(&aData[1]);
      rc = xVisit(p, iCall++, 0, 0, &kv);
    }
  }

  assert( rc!=SQLITE4_OK || iCall==p->nCell );
  return rc;
}

/*
** Extract a key-prefix from page pPg, which resides in a database with
** page size pgsz. If parameter bLast is true, the key-prefix is extracted
** from the right-most cell on the page. If bLast is false, the key-prefix
** is extracted from the left-most cell.
**
** A pointer to the key-prefix is returned. Before returning, *pnByte is
** set to the size of the prefix in bytes.
*/
static u8 *btKeyPrefix(const int pgsz, BtPage *pPg, int bLast, int *pnByte){
  u8 *p;
  int n;
  u8 *aData;

  aData = btPageData(pPg);
  p = btCellFind(aData, pgsz, bLast ? btCellCount(aData, pgsz)-1 : 0);
  p += sqlite4BtVarintGet32(p, &n);
  if( n==0 ) p += sqlite4BtVarintGet32(p, &n);

  *pnByte = n;
  return p;
}

/*
** Parameters pLeft and pRight point to a pair of adjacent leaf pages in
** a database with page size pgsz. The keys in pRight are larger than those
** in pLeft. This function populates pKV->pK and pKV->nK with a separator
** key that is:
**
**   * larger than all keys on pLeft, and 
**   * smaller than or equal to all keys on pRight.
*/
static void btPrefixKey(
    const int pgsz, BtPage *pLeft, BtPage *pRight, KeyValue *pKV
){
  int nMax;
  int nMaxPrefix = BT_MAX_INTERNAL_KEY;

  u8 *aLeft; int nLeft;
  u8 *aRight; int nRight;
  int i;

  aLeft = btKeyPrefix(pgsz, pLeft, 1, &nLeft);
  aRight = btKeyPrefix(pgsz, pRight, 0, &nRight);

  nMax = MIN(nLeft, nMaxPrefix);
  for(i=0; i<nMax && aLeft[i]==aRight[i]; i++);
  if( i<nMaxPrefix ){
    pKV->pK = aRight;
    pKV->nK = i + 1;
    assert( pKV->nK<=nRight );
  }
}

int btBalance(
  BtCursor *pCsr,                 /* Cursor pointed to page to rebalance */
  int bLeaf,                      /* True if rebalancing leaf pages */
  int nKV,                        /* Number of entries in apKV[] array */
  KeyValue *apKV                  /* Extra entries to add while rebalancing */
){
  bt_db * const pDb = pCsr->base.pDb; 
  const int pgsz = sqlite4BtPagerPagesize(pDb->pPager);
  const int nSpacePerPage = (pgsz - 1 - 6 - (!bLeaf)*4);

  int iPg;                        /* Used to iterate through pages */
  int iCell;                      /* Used to iterate through cells */

  int anByteOut[5];               /* Bytes of content on each output page */
  BtPage *pPar;                   /* Parent page */
  int iSib;                       /* Index of left-most sibling */

  int rc = SQLITE4_OK;            /* Return code */

  BalanceCtx ctx;
  memset(&ctx, 0, sizeof(ctx));
  ctx.pCsr = pCsr;
  ctx.nKV = nKV;
  ctx.apKV = apKV;
  ctx.pgsz = pgsz;
  ctx.bLeaf = bLeaf;
  ctx.flags = *(u8*)btPageData(pCsr->apPage[pCsr->nPg-1]);

  memset(anByteOut, 0, sizeof(anByteOut));

  /* Gather the sibling pages from which cells will be redistributed into
  ** the ctx.apPg[] array.  */
  assert( bLeaf==0 || bLeaf==1 );
  assert( pCsr->nPg>1 );
  rc = btGatherSiblings(&ctx);
  if( rc!=SQLITE4_OK ) goto rebalance_out;
  pPar = pCsr->apPage[pCsr->nPg-2];
  iSib = pCsr->aiCell[pCsr->nPg-2];

  /* Count the number of input cells. */
  ctx.nCell = nKV;
  for(iPg=0; iPg<ctx.nIn; iPg++){
    u8 *aData = btPageData(ctx.apPg[iPg]);
    ctx.nCell += btCellCount(aData, pgsz);
  }
  if( bLeaf==0 ) ctx.nCell += (ctx.nIn-1);
  assert( ctx.nCell>0 );

  /* Allocate and populate the anCellSz[] array */
  ctx.anCellSz = (int*)sqlite4_malloc(pDb->pEnv, sizeof(int)*ctx.nCell);
  if( ctx.anCellSz==0 ){
    rc = btErrorBkpt(SQLITE4_NOMEM);
    goto rebalance_out;
  }
  rc = btBalanceVisitCells(&ctx, btBalanceMeasure);

  /* Now figure out the number of output pages required. Set ctx.nOut to 
  ** this value. */
  iCell = 0;
  for(iPg=0; iCell<ctx.nCell; iPg++){
    assert( iPg<array_size(ctx.anOut) );
    if( bLeaf==0 && iPg!=0 ){
      /* This cell will be pushed up to the parent node as a divider cell,
      ** not written to any output page.  */
      iCell++;
    }
    assert( anByteOut[iPg]==0 );
    for(/* noop */; iCell<ctx.nCell; iCell++){
      int nByte = (ctx.anCellSz[iCell] + 2);
      if( nByte+anByteOut[iPg]>nSpacePerPage ) break;
      anByteOut[iPg] += nByte;
    }
    ctx.anOut[iPg] = iCell;
  }
  ctx.nOut = iPg;
  assert( ctx.anOut[ctx.nOut-1]==ctx.nCell );

  /* The loop in the previous block populated the anOut[] array in such a
  ** way as to make the (ctx.nOut-1) leftmost pages completely full but 
  ** leave the rightmost page partially empty. Or, if bLeaf==0, perhaps
  ** even completely empty. This block attempts to redistribute cells a bit 
  ** more evenly. 
  */
  iCell = ctx.nCell;
  
  for(iPg=(ctx.nOut-2); iPg>=0; iPg--){
    int iR = iPg+1;
    while( 1 ){
      int nLeft = ctx.anCellSz[ ctx.anOut[iPg]-1 ] + 2;
      int nRight = (bLeaf ? nLeft : (ctx.anCellSz[ ctx.anOut[iPg] ] + 2));

      if( anByteOut[iPg]==nLeft || (anByteOut[iR] + nRight) > anByteOut[iPg] ){
        break;
      }
      ctx.anOut[iPg]--;
      anByteOut[iPg] -= nLeft;
      anByteOut[iR] += nRight;
    }
  }

#ifdef BT_STDERR_DEBUG
  {
    int iDbg;
    fprintf(stderr, 
        "\nbtBalance(): bLeaf=%d nIn=%d anIn[] = ", ctx.bLeaf, ctx.nIn
    );
    for(iDbg=0; iDbg<ctx.nIn; iDbg++){
      u8 *aData = btPageData(ctx.apPg[iDbg]);
      fprintf(stderr, "%d ", btCellCount(aData, pgsz));
    }
    fprintf(stderr, " ->  nOut=%d anOut[] = ", ctx.nOut);
    for(iDbg=0; iDbg<ctx.nOut; iDbg++){
      fprintf(stderr, "%d ", ctx.anOut[iDbg]);
    }
    fprintf(stderr, "\n");
    fflush(stderr);
  }
#endif

  /* Allocate buffers for the output pages. If the pages being balanced
  ** are not leaves, grab one more buffer from the pager layer to use
  ** to temporarily store a copy of the keys destined for the parent
  ** page.  */
  for(iPg=0; iPg<ctx.nOut; iPg++){
    rc = btNewBuffer(pDb, &ctx.apOut[iPg]);
    if( rc!=SQLITE4_OK ) goto rebalance_out;
    memset(ctx.apOut[iPg] + pgsz-6, 0, 6);
  }
  if( bLeaf==0 ){
    rc = btNewBuffer(pDb, &ctx.pTmp);
    if( rc!=SQLITE4_OK ) goto rebalance_out;
  }

  /* Populate the new buffers with the new page images. */
  rc = btBalanceVisitCells(&ctx, btBalanceOutput);
  if( rc!=SQLITE4_OK ) goto rebalance_out;

  if( ctx.bLeaf==0 ){
    /* Set the right-child pointer of the rightmost new sibling to a copy
    ** of the same pointer from the rightmost original sibling.  */
    u8 *aRightSibling = btPageData(ctx.apPg[ctx.nIn-1]);
    memcpy(&(ctx.apOut[ctx.nOut-1])[1], &aRightSibling[1], 4);
  }

  /* Clobber the old pages with the new buffers */
  for(iPg=0; iPg<ctx.nOut; iPg++){
    if( iPg>=ctx.nIn ){
      rc = btAllocateNonOverflow(pDb, &ctx.apPg[iPg]);
      if( rc!=SQLITE4_OK ) goto rebalance_out;
    }
    btSetBuffer(pDb, ctx.apPg[iPg], ctx.apOut[iPg]);
    ctx.apOut[iPg] = 0;
  }
  for(iPg=ctx.nOut; iPg<ctx.nIn; iPg++){
    rc = btTrimNonOverflow(pDb, ctx.apPg[iPg]);
    ctx.apPg[iPg] = 0;
    if( rc!=SQLITE4_OK ) goto rebalance_out;
  }

#ifdef BT_STDERR_DEBUG
  {
    int iDbg;
    for(iDbg=0; iDbg<ctx.nOut; iDbg++){
      u8 *aData = btPageData(ctx.apPg[iDbg]);
      printPage(stderr, sqlite4BtPagePgno(ctx.apPg[iDbg]), aData, pgsz);
    }
  }
#endif

  /* The leaves are written. Now gather the keys and page numbers to
  ** push up into the parent page. This is only required when rebalancing
  ** b-tree leaves. When internal nodes are balanced, the btBalanceOutput
  ** loop accumulates the cells destined for the parent page.  */
  for(iPg=0; iPg<(ctx.nOut-1); iPg++){
    ctx.aPCell[iPg].pgno = sqlite4BtPagePgno(ctx.apPg[iPg]);
    if( bLeaf ){
      assert( ctx.aPCell[iPg].nK==0 );
      btPrefixKey(pgsz, ctx.apPg[iPg], ctx.apPg[iPg+1], &ctx.aPCell[iPg]);
    }
  }

  rc = btSetChildPgno(
      pDb, pPar, iSib+ctx.nIn-1, sqlite4BtPagePgno(ctx.apPg[ctx.nOut-1])
  );
  if( rc==SQLITE4_OK ){
    btCsrAscend(pCsr, 1);
    rc = btDeleteFromPage(pCsr, ctx.nIn-1);
  }
  iPg = pCsr->nPg;
  if( rc==SQLITE4_OK && ctx.nOut>1 ){
    rc = btInsertAndBalance(pCsr, ctx.nOut-1, ctx.aPCell);
  }
  if( rc==SQLITE4_OK && iPg==pCsr->nPg ){
    rc = btBalanceIfUnderfull(pCsr);
  }

#ifdef BT_STDERR_DEBUG
  {
    u8 *aData = btPageData(pPar);
    printPage(stderr, sqlite4BtPagePgno(pPar), aData, pgsz);
  }
#endif

 rebalance_out:
  for(iPg=0; iPg<array_size(ctx.apPg); iPg++){
    sqlite4BtPageRelease(ctx.apPg[iPg]);
  }
  btFreeBuffer(pDb, ctx.pTmp);
  sqlite4_free(pDb->pEnv, ctx.anCellSz);
  return rc;
}

static int btExtendTree(BtCursor *pCsr){
  bt_db * const pDb = pCsr->base.pDb;
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(pDb->pPager);
  const int pgsz = pHdr->pgsz;
  int rc;                         /* Return code */
  BtPage *pNew;                   /* New (and only) child of root page */
  BtPage *pRoot = pCsr->apPage[0];

  assert( pCsr->nPg==1 );

  rc = sqlite4BtPageWrite(pRoot);
  if( rc==SQLITE4_OK ){
    rc = btAllocateNonOverflow(pDb, &pNew);
  }
  if( rc==SQLITE4_OK ){
    u8 *aRoot = btPageData(pRoot);
    u8 *aData = btPageData(pNew);

    memcpy(aData, aRoot, pgsz);
    aRoot[0] = BT_PGFLAGS_INTERNAL;
    if( pHdr->iMRoot==pCsr->iRoot ) aRoot[0] |= BT_PGFLAGS_METATREE;
    btPutU32(&aRoot[1], sqlite4BtPagePgno(pNew));
    btPutU16(&aRoot[pgsz-2], 0);
    btPutU16(&aRoot[pgsz-4], 5);
    btPutU16(&aRoot[pgsz-6], pgsz - 5 - 6);

    pCsr->nPg = 2;
    pCsr->aiCell[1] = pCsr->aiCell[0];
    pCsr->apPage[1] = pNew;
    pCsr->aiCell[0] = 0;
  }

  return rc;
}

/*
** The cursor passed as the first argument points to a leaf page into
** which the array of KV pairs specified by the second and third arguments
** would be inserted, except that there is insufficient free space on
** the page.
**
** If nKV==1, the tree is more than one level high (i.e. the root is not a
** leaf) and the new key is larger than all existing keys on the page,
** handle this in the same way as an SQLite3 "quick-balance" operation.
** Return SQLITE4_OK if successful, or an error code if an error occurs.
**
** If the quick-balance is not attempted, return SQLITE4_NOTFOUND.
*/
static int btTryAppend(BtCursor *pCsr, int nKV, KeyValue *apKV){
  int rc = SQLITE4_NOTFOUND;
  if( nKV==1 && pCsr->nPg>1 ){
    bt_db *pDb = pCsr->base.pDb;
    const int pgsz = sqlite4BtPagerPagesize(pDb->pPager);
    BtPage *pOld = pCsr->apPage[pCsr->nPg-1];
    u8 *aData = btPageData(pOld);
    int nCell = btCellCount(aData, pgsz);
    if( nCell==pCsr->aiCell[pCsr->nPg-1] ){
      KeyValue kv;
      BtPage *pNew = 0;
      rc = btAllocateNonOverflow(pDb, &pNew);
      if( rc==SQLITE4_OK ){
        aData = btPageData(pNew);
        btPutU16(&aData[pgsz-2], 0);
        aData[0] = 0x00;
        pCsr->apPage[pCsr->nPg-1] = pNew;
        pCsr->aiCell[pCsr->nPg-1] = 0;
        rc = btInsertAndBalance(pCsr, 1, apKV);
      }
      if( rc==SQLITE4_OK ){
        rc = btSetChildPgno(pDb, 
            pCsr->apPage[pCsr->nPg-2], pCsr->aiCell[pCsr->nPg-2], 
            sqlite4BtPagePgno(pNew)
        );
      }
      if( rc==SQLITE4_OK ){
        assert( pCsr->apPage[pCsr->nPg-1]==pNew );
        btPrefixKey(pgsz, pOld, pNew, &kv);
        kv.pgno = sqlite4BtPagePgno(pOld);
        kv.pV = 0;
        kv.nV = 0;
        kv.eType = 0;
        rc = btCsrAscend(pCsr, 1);
      }
      if( rc==SQLITE4_OK ){
        rc = btInsertAndBalance(pCsr, 1, &kv);
      }
      if( pNew ) sqlite4BtPageRelease(pOld);
    }
  }
  return rc;
}

/*
** The cursor currently points to a cell on a b-tree page that may or
** may not be a leaf page. This routine modifies the contents of that
** page, balancing the b-tree if necessary. The page is modified as
** follows:
**
**     * nDel entries, starting with the one the cursor points to, are
**       deleted from the page.
**
**     * nKV entries are inserted in their place.
**
** The tree balancing routine is called if this causes the page to
** become either overfull or to contain no entries at all.
*/
static int btInsertAndBalance(
  BtCursor *pCsr,                 /* Cursor identifying page to modify */
  int nKV,                        /* Number of entries in apKV */
  KeyValue *apKV                  /* New cells to insert into the page */
){
  int rc = SQLITE4_OK;
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  u8 *aData;                      /* Page buffer */
  int nCell;                      /* Number of cells on this page already */
  int nFree;                      /* Contiguous free space on this page */
  int nReq = 0;                   /* Space required for type (a) cells */
  int iCell;                      /* Position to insert new key */
  int iWrite;                     /* Byte offset at which to write new cell */
  int i;
  int bLeaf;                      /* True if inserting into leaf page */
  BtPage *pLeaf;

  bLeaf = (apKV[0].pgno==0);
  assert( bLeaf==0 || nKV==1 );

  /* Determine the number of bytes of space required on the current page. */
  for(i=0; i<nKV; i++){
    nReq += btKVCellSize(&apKV[i]) + 2;
  }

  iCell = pCsr->aiCell[pCsr->nPg-1];
  assert( pCsr->nPg>0 );
  pLeaf = pCsr->apPage[pCsr->nPg-1];
  aData = (u8*)btPageData(pLeaf);

  /* Set the bLeaf variable to true if inserting into a leaf page, or
  ** false otherwise. Return SQLITE4_CORRUPT if the page is a leaf but
  ** the KeyValue pairs being inserted are suitable for internal nodes,
  ** or vice-versa.  */
  assert( nKV>0 );
  if( (0==(btFlags(aData) & BT_PGFLAGS_INTERNAL))!=bLeaf ){
    return btErrorBkpt(SQLITE4_CORRUPT);
  }

  nCell = btCellCount(aData, pgsz);
  assert( iCell<=btCellCount(aData, pgsz) );

  if( nCell==0 ){
    /* If the nCell field is zero, then the rest of the header may 
    ** contain invalid values (zeroes - as it may never have been 
    ** initialized). So set our stack variables to values appropriate
    ** to an empty page explicitly here.  */
    iWrite = (bLeaf ? 1 : 5);
    nFree = pgsz - iWrite - 6;
  }else{
    if( btFreeContiguous(aData, pgsz)<nReq && btFreeSpace(aData, pgsz)>=nReq ){
      /* Special case - the new entry will not fit on the page at present
      ** but would if the page were defragmented. So defragment it before
      ** continuing.  */
      rc = btDefragmentPage(pCsr->base.pDb, pLeaf);
      aData = btPageData(pLeaf);
    }

    iWrite = btFreeOffset(aData, pgsz);
    nFree = btFreeContiguous(aData, pgsz);
  }

  if( nFree>=nReq ){
    /* The new entry will fit on the page. So in this case all there
    ** is to do is update this single page. The easy case. */
    rc = sqlite4BtPageWrite(pLeaf);
    if( rc==SQLITE4_OK ){
      aData = btPageData(pLeaf);

      /* Make space within the cell pointer array */
      if( iCell!=nCell ){
        u8 *aFrom = btCellPtrFind(aData, pgsz, nCell-1);
        u8 *aTo = btCellPtrFind(aData, pgsz, nCell-1+nKV);
        memmove(aTo, aFrom, (nCell-iCell) * 2);
      }

      for(i=0; i<nKV; i++){
        /* Write the cell pointer */
        btPutU16(btCellPtrFind(aData, pgsz, iCell+i), iWrite);
      
        /* Write the cell itself */
        iWrite += btKVCellWrite(&apKV[i], &aData[iWrite]);
      }

      /* Set the new total free space */
      if( nCell==0 ){
        btPutU16(&aData[pgsz-4], nFree - nReq);
      }else{
        btPutU16(&aData[pgsz-4], btFreeSpace(aData, pgsz) - nReq);
      }

      /* Increase cell count */
      btPutU16(&aData[pgsz-2], nCell+nKV);

      /* Set the offset to the block of empty space */
      btPutU16(&aData[pgsz-6], iWrite);
    }

  }else{
    /* The new entry will not fit on the leaf page. Entries will have
    ** to be shuffled between existing leaves and new leaves may need
    ** to be added to make space for it. */
    bt_db *db = pCsr->base.pDb;
    if( bLeaf && db->bFastInsertOp ){
      /* This operation will need to allocate further pages. The worst
      ** case scenario is (nDepth+1) pages. If fewer than that remain
      ** available in the block, return BT_BLOCKFULL. */
      BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
      int nPgPerBlk = (pHdr->blksz / pHdr->pgsz);
      if( (nPgPerBlk - pHdr->nSubPg) < pCsr->nPg+1 ){
        sqlite4BtPagerDbhdrDirty(db->pPager);
        rc = BT_BLOCKFULL;
        pHdr->iSubBlock = 0;
      }
    }
    if( rc==SQLITE4_OK && pCsr->nPg==1 ){
      rc = btExtendTree(pCsr);
    }
    if( rc==SQLITE4_OK ){
      rc = btBalance(pCsr, bLeaf, nKV, apKV);
#if 0
      if( bLeaf==0 || SQLITE4_NOTFOUND==(rc = btTryAppend(pCsr, nKV, apKV)) ){
        rc = btBalance(pCsr, bLeaf, nKV, apKV);
      }
#endif
    }
  }

  return rc;
}

static int btDeleteFromPage(BtCursor *pCsr, int nDel){
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  int rc = SQLITE4_OK;            /* Return code */
  BtPage *pPg;                    /* Page to delete entries from */

  pPg = pCsr->apPage[pCsr->nPg-1];
  rc = sqlite4BtPageWrite(pPg);
  if( rc==SQLITE4_OK ){
    int i;                        /* Used to iterate through cells to delete */
    u8 *aData;                    /* Page buffer */
    int nCell;                    /* Number of cells initially on this page */
    int iDel;                     /* Index of cell to delete */
    int nFreed = 0;               /* Total bytes of space freed */

    iDel = pCsr->aiCell[pCsr->nPg-1];
    aData = (u8*)btPageData(pPg);
    nCell = btCellCount(aData, pgsz);

    for(i=iDel; i<(iDel+nDel); i++){
      int nByte;
      btCellFindSize(aData, pgsz, i, &nByte);
      nFreed += nByte + 2;
    }

    if( (iDel+nDel)<nCell ){
      u8 *aTo = btCellPtrFind(aData, pgsz, nCell-1-nDel);
      u8 *aFrom = btCellPtrFind(aData, pgsz, nCell-1);
      memmove(aTo, aFrom, 2*(nCell-(iDel+nDel)));
    }

    /* Decrease cell count */
    btPutU16(&aData[pgsz-2], nCell-nDel);

    /* Increase total free space */
    btPutU16(&aData[pgsz-4], btFreeSpace(aData, pgsz) + nFreed);
  }
  
  return rc;
}

static int btBalanceIfUnderfull(BtCursor *pCsr){
  const int pgsz = sqlite4BtPagerPagesize(pCsr->base.pDb->pPager);
  int rc = SQLITE4_OK;
  int iPg = pCsr->nPg-1;
  BtPage *pPg = pCsr->apPage[iPg];
  u8 *aData = btPageData(pPg);
  int nCell = btCellCount(aData, pgsz);
  int nFree = btFreeSpace(aData, pgsz);
  int bLeaf = (0==(btFlags(aData) & BT_PGFLAGS_INTERNAL));

  if( iPg==0 ){
    /* Root page. If it contains no cells at all and is not already
    ** a leaf, shorten the tree by one here by copying the contents 
    ** of the only child into the root. */
    if( nCell==0 && bLeaf==0 ){
      BtPager *pPager = pCsr->base.pDb->pPager;
      u32 pgno = btChildPgno(aData, pgsz, 0);
      BtPage *pChild;

      rc = sqlite4BtPageWrite(pPg);
      if( rc==SQLITE4_OK ){
        rc = sqlite4BtPageGet(pPager, pgno, &pChild);
      }
      if( rc==SQLITE4_OK ){
        u8 *a = btPageData(pChild);
        memcpy(aData, a, pgsz);
        rc = btTrimNonOverflow(pCsr->base.pDb, pChild);
      }
    }
  }else if( nCell==0 || (nFree>(2*pgsz/3) && bLeaf==0) ){
    rc = btBalance(pCsr, bLeaf, 0, 0);
  }
  return rc;
}

static int btSaveAllCursor(bt_db *pDb, BtCursor *pCsr){
  int rc = SQLITE4_OK;            /* Return code */
  bt_cursor *pIter;               /* Used to iterate through cursors */

  for(pIter=pDb->pAllCsr; rc==SQLITE4_OK && pIter; pIter=pIter->pNextCsr){
    if( IsBtCsr(pIter) ){
      BtCursor *p = (BtCursor*)pIter;
      if( p->nPg>0 ){
        assert( p->bRequireReseek==0 );
        rc = btCsrBuffer(p, 0);
        if( rc==SQLITE4_OK ){
          assert( p->ovfl.buf.p );
          p->bRequireReseek = 1;
          if( p!=pCsr ) btCsrReleaseAll(p);
        }
      }
    }else{
      /* ?? */
    }
  }

  return rc;
}

static int btFastInsertRoot(bt_db *db, BtDbHdr *pHdr, u32 *piRoot);
static int btScheduleMerge(bt_db *db);

static int btReplaceEntry(
  bt_db *db,                      /* Database handle */
  u32 iRoot,                      /* Root page of b-tree to update */
  const void *pK, int nK,         /* Key to insert */
  const void *pV, int nV          /* Value to insert. (nV<0) -> delete */
){
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
  int rc = SQLITE4_OK;            /* Return code */
  BtCursor csr;                  /* Cursor object to seek to insert point */
  u32 iRootPg = iRoot;

  if( iRoot==0 ){
    rc = btFastInsertRoot(db, pHdr, &iRootPg);
  }
  btCsrSetup(db, iRootPg, &csr);

  /* Seek stack cursor csr to the b-tree page that key pK/nK is/would be
  ** stored on.  */
  if( rc==SQLITE4_OK ){
    rc = btCsrSeek(&csr, 0, pK, nK, BT_SEEK_GE, BT_CSRSEEK_UPDATE);
  }

  if( rc==SQLITE4_OK ){
    /* The cursor currently points to an entry with key pK/nK. This call
    ** should therefore replace that entry. So delete it and then re-seek
    ** the cursor.  */
    rc = sqlite4BtDelete(&csr.base);
    if( rc==SQLITE4_OK && (nV>=0 || iRoot==0) ){
      rc = btCsrSeek(&csr, 0, pK, nK, BT_SEEK_GE, BT_CSRSEEK_UPDATE);
      if( rc==SQLITE4_OK ) rc = btErrorBkpt(SQLITE4_CORRUPT);
    }
  }


  if( rc==SQLITE4_NOTFOUND || rc==SQLITE4_INEXACT ){
    if( nV<0 && iRoot!=0 ){
      /* This is a delete on the regular b-tree (not the fast-insert tree).
      ** Nothing more to do.  */
      rc = SQLITE4_OK;
    }else{
      KeyValue kv;
      kv.pgno = 0;
      kv.eType = KV_VALUE;
      kv.pK = pK; kv.nK = nK;
      kv.pV = pV; kv.nV = nV;

      rc = btOverflowAssign(db, &kv);
      if( rc==SQLITE4_OK ){
        do{
          /* Insert the new KV pair into the current leaf. */
          rc = btInsertAndBalance(&csr, 1, &kv);

          /* Unless this is a block-full error, break out of the loop */
          if( rc!=BT_BLOCKFULL ) break;
          assert( iRoot==0 );

          /* Try to schedule a merge operation */
          rc = btScheduleMerge(db);

          if( rc==SQLITE4_OK ){
            rc = btFastInsertRoot(db, pHdr, &iRootPg);
          }
          if( rc==SQLITE4_OK ){
            btCsrReset(&csr, 1);
            btCsrSetup(db, iRootPg, &csr);
            rc = btCsrSeek(&csr, 0, pK, nK, BT_SEEK_GE, BT_CSRSEEK_UPDATE);
          }
        }while( rc==SQLITE4_NOTFOUND || rc==SQLITE4_INEXACT );
      }

      if( kv.eType==KV_CELL ){
        sqlite4_free(db->pEnv, (void*)kv.pV);
      }
    }
  }

  btCsrReset(&csr, 1);
  return rc;
}

static int btAllocateNewRoot(bt_db *db, int flag, u32 *piNew){
  u32 iNew = 0;
  BtPage *pPg;
  int rc;

  assert( flag==BT_PGFLAGS_METATREE || flag==BT_PGFLAGS_SCHEDULE || flag==0 );
  rc = sqlite4BtPageAllocate(db->pPager, &pPg);
  if( rc==SQLITE4_OK ){
    u8 *aData = btPageData(pPg);
    aData[0] = (flag & 0xFF);
    iNew = sqlite4BtPagePgno(pPg);
    sqlite4BtPageRelease(pPg);
  }

  *piNew = iNew;
  return rc;
}

static int btDecodeMetatreeKey(
  BtCursor *pCsr,
  u32 *piAge,
  u32 *piLevel,
  u8 **paKey,
  int *pnKey
){
  u8 *aK; int nK;
  int rc = sqlite4BtCsrKey((bt_cursor*)pCsr, (const void**)&aK, &nK);
  if( rc==SQLITE4_OK ){
    *piAge = btGetU32(&aK[0]);
    *piLevel = ~btGetU32(&aK[4]);
    if( paKey ){
      *paKey = &aK[8];
      *pnKey = nK-8;
    }
  }
  return rc;
}

static void *btMalloc(bt_db *db, int nByte, int *pRc){
  void *pRet = 0;
  if( *pRc==SQLITE4_OK ){
    pRet = sqlite4_malloc(db->pEnv, nByte);
    if( !pRet ) *pRc = btErrorBkpt(SQLITE4_NOMEM);
  }
  return pRet;
}
static void btFree(bt_db *db, void *p){
  sqlite4_free(db->pEnv, p);
}

static int fiLoadSummary(
  bt_db *db, 
  BtCursor *p, 
  const u8 **paSummary, 
  int *pnSummary
){
  static const u8 aZero[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
  int rc;

  btCsrSetup(db, pHdr->iMRoot, p);
  rc = btCsrSeek(
      p, 0, aSummaryKey, sizeof(aSummaryKey), BT_SEEK_EQ, BT_CSRSEEK_SEEK
  );
  if( rc==SQLITE4_OK ){
    rc = btCsrData(p, 0, -1, (const void**)paSummary, pnSummary);
  }else if( rc==SQLITE4_NOTFOUND ){
    *paSummary = aZero;
    *pnSummary = sizeof(aZero);
    rc = SQLITE4_OK;
  }

  return rc;
}

static void btReadSummary(
  const u8 *aSum, int iAge, 
  u16 *piMinLevel,
  u16 *pnLevel,
  u16 *piMergeLevel
){
  if( piMinLevel ) *piMinLevel = btGetU16(&aSum[iAge * 6]);
  if( pnLevel ) *pnLevel = btGetU16(&aSum[iAge * 6 + 2]);
  if( piMergeLevel ) *piMergeLevel = btGetU16(&aSum[iAge * 6 + 4]);
}

static void btWriteSummary(
  u8 *aSum, int iAge,
  u16 iMinLevel,
  u16 nLevel,
  u16 iMergeLevel
){
  btPutU16(&aSum[iAge * 6], iMinLevel);
  btPutU16(&aSum[iAge * 6 + 2], nLevel);
  btPutU16(&aSum[iAge * 6 + 4], iMergeLevel);
}

/*
** Allocate a new level for a new age=0 segment. The new level is always
** one greater than the current largest age=0 level number.
*/
static int btAllocateNewLevel(
  bt_db *db, 
  BtDbHdr *pHdr, 
  u32 *piNext
){

  int rc;                         /* Return code */
  BtCursor csr;                   /* Cursor to read meta-table summary */
  int nByte;                      /* Size of buffer aByte[] */
  const u8 *aByte;                /* Summary data */
  u8 *aNew;                       /* New summary data */

  rc = fiLoadSummary(db, &csr, &aByte, &nByte);

  aNew = (u8*)btMalloc(db, nByte, &rc);
  if( rc==SQLITE4_OK ){
    u16 iMin, nLevel, iMerge;
    btReadSummary(aByte, 0, &iMin, &nLevel, &iMerge);

    memcpy(aNew, aByte, nByte);
    btPutU16(&aNew[2], nLevel+1);
    rc = btReplaceEntry(
        db, pHdr->iMRoot, aSummaryKey, sizeof(aSummaryKey), aNew, nByte
    );
    btFree(db, aNew);

    *piNext = (iMin + nLevel);
  }

  btCsrReset(&csr, 1);
  return rc;
}

static void btWriteSchedule(u8 *aData, BtSchedule *p, int *pRc){
  if( *pRc==SQLITE4_OK ){
    u32 *a = (u32*)p;
    int i;
    for(i=0; i<sizeof(BtSchedule)/sizeof(u32); i++){
      btPutU32(&aData[i*4], a[i]);
    }
  }
}
static int btReadSchedule(bt_db *db, u8 *aData, BtSchedule *p){
  u32 *a = (u32*)p;
  int i;
  for(i=0; i<sizeof(BtSchedule)/sizeof(u32); i++){
    a[i] = btGetU32(&aData[i*4]);
  }
  return SQLITE4_OK;
}

static void btWriteSchedulePage(BtPage *pPg, BtSchedule *p, int *pRc){
  if( *pRc==SQLITE4_OK ){
    int rc = sqlite4BtPageWrite(pPg);
    if( rc==SQLITE4_OK ){
      u8 *aData = btPageData(pPg);
      btWriteSchedule(aData, p, &rc);
    }
    *pRc = rc;
  }
}

static int btAllocateBlock(
  bt_db *db, 
  int nBlk,
  u32 *aiBlk
){
  return sqlite4BtBlockAllocate(db->pPager, nBlk, aiBlk);
}

/*
** This is a helper function for btScheduleMerge(). It determines the
** age and range of levels to be used as inputs by the merge (if any).
*/
static int btFindMerge(
  bt_db *db,                      /* Database handle */
  u32 *piAge,                     /* OUT: Age of input segments to merge */
  u32 *piMinLevel,                /* OUT: Minimum input level value */
  u32 *piMaxLevel,                /* OUT: Maximum input level value */
  u32 *piOutLevel                 /* OUT: Output level value */
){
  BtCursor csr;                   /* Cursor used to read summary record */
  int rc;                         /* Return code */
  const u8 *aSum;
  int nSum;

  rc = fiLoadSummary(db, &csr, &aSum, &nSum);
  if( rc==SQLITE4_OK ){
    int iAge;
    int iBestAge = -1;            /* Best age to merge levels from */
    int nBest = (db->nMinMerge-1);/* Number of levels merged at iBestAge */
    u16 iMin, nLevel, iMerge;     /* Summary of current age */

    rc = SQLITE4_NOTFOUND;
    for(iAge=0; iAge<(nSum/6); iAge++){
      btReadSummary(aSum, iAge, &iMin, &nLevel, &iMerge);
      if( iMerge ){
        int n = 1 + (iMerge-iMin);
        if( n>nBest ){
          *piMinLevel = iMin;
          *piMaxLevel = iMerge;
          *piAge = iAge;
          btReadSummary(aSum, iAge+1, &iMin, &nLevel, &iMerge);
          *piOutLevel = (iMin + nLevel - 1);
          rc = SQLITE4_OK;
        }
        break;
      }else{
        if( nLevel>nBest ){
          iBestAge = iAge;
          nBest = nLevel;
        }
      }
    }

    if( rc==SQLITE4_NOTFOUND && iBestAge>=0 ){
      u8 *aNew;
      int nByte = nSum;
      if( iBestAge+1>=(nSum/6) ) nByte += 6;

      rc = SQLITE4_OK;
      aNew = (u8*)btMalloc(db, nByte, &rc);
      if( rc==SQLITE4_OK ){

        /* Create a copy of the summary record */
        memcpy(aNew, aSum, nSum);
        if( nByte>nSum ) btWriteSummary(aNew, iBestAge+1, 0, 0, 0);

        /* Find the input age and maximum level */
        btReadSummary(aSum, iBestAge, &iMin, &nLevel, &iMerge);
        *piMinLevel = (u32)iMin;
        *piMaxLevel = (u32)(iMin + nLevel - 1);
        *piAge = iBestAge;

        /* Find the output level */
        btReadSummary(aNew, iBestAge+1, &iMin, &nLevel, &iMerge);
        *piOutLevel = iMin + nLevel;
      }
    }
  }

  btCsrReset(&csr, 1);
  return rc;
}

/*
** The connection passed as the first argument to this function currently
** has a write transaction open. The schedule object passed as the second
** is in BT_SCHEDULE_DONE state. This function updates the meta-tree to
** integrate the results of the completed merge into the main fast-insert
** tree structure.
**
** If successful, SQLITE4_OK is returned. If an error occurs, an SQLite
** error code.
*/ 
static int btIntegrateMerge(bt_db *db, BtSchedule *p){
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
  const int nPgPerBlk = (pHdr->blksz / pHdr->pgsz);
  int rc = SQLITE4_OK;
  BtCursor csr;                   /* Cursor for reading various sub-trees */
  BtCursor mcsr;                  /* Cursor for reading the meta-tree */
  const void *pKey = 0;           /* If not NULL, first key to leave in input */
  int nKey = 0;                   /* Size of pKey in bytes */
  const u8 *aSum; int nSum;       /* Summary value */
  sqlite4_buffer buf;             /* Buffer object used for various purposes */
  u32 iLvl;
  int iBlk;

  /* Save the value of the fast-insert flag. It will be restored before
  ** this function returns. Leaving it set here interferes with page 
  ** allocation if the meta-tree needs to be extended.  */
  const int bFastInsertOp = db->bFastInsertOp;
  db->bFastInsertOp = 0;
  
#if 0
  static int nCall = 0; nCall++;
  fprintf(stderr, "BEFORE %d\n", nCall);
  btPrintMetaTree(db->pPager, 1, pHdr);
#endif
  assert_summary_ok(db, SQLITE4_OK);

  memset(&csr, 0, sizeof(csr));
  memset(&mcsr, 0, sizeof(mcsr));
  btCsrSetup(db, pHdr->iMRoot, &mcsr);
  sqlite4_buffer_init(&buf, 0);
  
  if( p->iNextPg ){
    btCsrSetup(db, p->iNextPg, &csr);
    rc = btCsrEnd(&csr, 0);
    if( rc==SQLITE4_OK ){
      csr.aiCell[0] = p->iNextCell;
      rc = btCsrKey(&csr, &pKey, &nKey);
    }
  }

  if( p->iFreeList ){
    u32 iTrunk = p->iFreeList;
    BtCursor delcsr;
    memset(&delcsr, 0, sizeof(BtCursor));
    delcsr.nPg = 1;
    delcsr.base.pDb = db;

    while( rc==SQLITE4_OK && iTrunk!=0 ){
      BtPage *pTrunk = 0;
      rc = sqlite4BtPageGet(db->pPager, iTrunk, &pTrunk);
      if( rc==SQLITE4_OK ){
        u8 *aTData = btPageData(pTrunk);
        int nOvfl = btGetU32(aTData);
        int i;

        for(i=0; i<nOvfl; i++){
          u32 lpgno = btGetU32(&aTData[8 + i*8]);
          delcsr.aiCell[0] = (int)btGetU32(&aTData[8 + i*8 + 4]);
          rc = sqlite4BtPageGet(db->pPager, lpgno, &delcsr.apPage[0]);
          if( rc==SQLITE4_OK ){
            rc = btOverflowDelete(&delcsr);
            sqlite4BtPageRelease(delcsr.apPage[0]);
          }
        }

        iTrunk = btGetU32(&aTData[4]);
        sqlite4BtPageRelease(pTrunk);
      }
    }
  }

  /* The following loop iterates through each of the input levels. Each
  ** level is either removed from the database completely (if the merge
  ** completed) or else modified so that it contains no keys smaller
  ** than (pKey/nKey).  */ 
  for(iLvl=p->iMinLevel; iLvl<=p->iMaxLevel; iLvl++){
    u8 aPrefix[8];
    u32 iRoot = 0;

    /* Seek mcsr to the first sub-tree (smallest keys) in level iLvl. */
    btPutU32(&aPrefix[0], p->iAge);
    btPutU32(&aPrefix[4], ~iLvl);
    rc = btCsrSeek(&mcsr, 0, aPrefix, sizeof(aPrefix), BT_SEEK_GE, 0);
    if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;

    /* Loop through the meta-tree entries that compose level iLvl, deleting 
    ** them as they are visited. If (pKey!=0), stop (and do not delete) the 
    ** first sub-tree for which all keys are larger than pKey.
    **
    ** When the loop exits, variable iRoot is left set to the root page of
    ** the last sub-tree deleted.  */
    while( rc==SQLITE4_OK ){
      const u8 *pMKey; int nMKey;
      rc = btCsrKey(&mcsr, (const void **)&pMKey, &nMKey);

      if( rc==SQLITE4_OK ){
        if( nMKey<sizeof(aPrefix) || memcmp(aPrefix, pMKey, sizeof(aPrefix)) ){
          rc = SQLITE4_NOTFOUND;
        }else{
          rc = SQLITE4_OK;
        }
      }
      if( rc==SQLITE4_OK ){
        if( pKey ){
          int res = btKeyCompare(pMKey + 8, nMKey - 8, pKey, nKey);
          if( res>0 ){
            break;
          }
        }
        if( iRoot ){
          rc = sqlite4BtBlockTrim(db->pPager, 1 + (iRoot / nPgPerBlk));
        }
      }

      if( rc==SQLITE4_OK ){
        const void *pData; int nData;
        btCsrData(&mcsr, 0, 4, &pData, &nData);
        iRoot = btGetU32(pData);
        rc = sqlite4BtDelete(&mcsr.base);
      }

      if( rc==SQLITE4_OK ){
        /* rc = btCsrStep(&mcsr, 1); */
        rc = btCsrSeek(&mcsr, 0, aPrefix, sizeof(aPrefix), BT_SEEK_GE, 0);
        if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
      }
    }
    if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;

    if( rc==SQLITE4_OK && iRoot ){
      if( pKey ){
        int n = sizeof(aPrefix) + nKey;
        rc = sqlite4_buffer_resize(&buf, n);
        if( rc==SQLITE4_OK ){
          u8 aData[4];
          u8 *a = (u8*)buf.p;
          memcpy(a, aPrefix, sizeof(aPrefix));
          memcpy(&a[sizeof(aPrefix)], pKey, nKey);
          btPutU32(aData, iRoot);
          rc = btReplaceEntry(db, pHdr->iMRoot, a, n, aData, sizeof(aData));
        }
      }else{
        rc = sqlite4BtBlockTrim(db->pPager, 1 + (iRoot / nPgPerBlk));
      }
    }
  }

  /* Add new entries for the new output level blocks. */
  for(iBlk=0; 
      rc==SQLITE4_OK && iBlk<array_size(p->aRoot) && p->aRoot[iBlk]; 
      iBlk++
  ){
    btCsrReset(&csr, 1);
    btCsrSetup(db, p->aRoot[iBlk], &csr);
    rc = btCsrEnd(&csr, 0);
    if( rc==SQLITE4_OK ){
      rc = btCsrKey(&csr, &pKey, &nKey);
    }
    if( rc==SQLITE4_OK ){
      rc = sqlite4_buffer_resize(&buf, nKey+8);
    }
    if( rc==SQLITE4_OK ){
      u8 aData[4];
      u8 *a = (u8*)buf.p;
      btPutU32(a, p->iAge+1);
      btPutU32(&a[4], ~p->iOutLevel);
      memcpy(&a[8], pKey, nKey);
      btPutU32(aData, p->aRoot[iBlk]);
      rc = btReplaceEntry(db, pHdr->iMRoot, a, nKey+8, aData, sizeof(aData));
    }
  }

  /* Trim any unused blocks */
  while( rc==SQLITE4_OK && iBlk<array_size(p->aBlock) && p->aBlock[iBlk] ){
    rc = sqlite4BtBlockTrim(db->pPager, p->aBlock[iBlk]);
    iBlk++;
  }

  /* Update the summary record with the outcome of the merge operation.  */
  if( rc==SQLITE4_OK ){
    btCsrReset(&csr, 1);
    rc = fiLoadSummary(db, &csr, &aSum, &nSum);
  }
  if( rc==SQLITE4_OK ){
    rc = sqlite4_buffer_resize(&buf, MAX(nSum, (p->iAge+1+1)*6));
    if( rc==SQLITE4_OK ){
      u16 iMinLevel = 0;
      u16 nLevel = 0;
      u16 iMergeLevel = 0;

      memcpy(buf.p, aSum, nSum);
      if( nSum>(6*(p->iAge+1)) ){
        btReadSummary(aSum, p->iAge+1, &iMinLevel, &nLevel, &iMergeLevel);
      }
      if( (iMinLevel+nLevel)>=p->iOutLevel ){
        nLevel = p->iOutLevel - iMinLevel + 1;
        btWriteSummary((u8*)buf.p, p->iAge+1, iMinLevel, nLevel, iMergeLevel);
      }

      btReadSummary(aSum, p->iAge, &iMinLevel, &nLevel, &iMergeLevel);
      if( p->iNextPg==0 ){
        u16 nNewLevel = nLevel - (1 + p->iMaxLevel - p->iMinLevel);
        iMinLevel = (nNewLevel==0 ? 0 : p->iMaxLevel+1);
        btWriteSummary((u8*)buf.p, p->iAge, iMinLevel, nNewLevel, 0);
      }else{
        btWriteSummary((u8*)buf.p, p->iAge, iMinLevel, nLevel, p->iMaxLevel);
      }

      rc = btReplaceEntry(
          db, pHdr->iMRoot, aSummaryKey, sizeof(aSummaryKey), buf.p, buf.n
      );
    }
  }

  btCsrReset(&csr, 1);
  btCsrReset(&mcsr, 1);
  sqlite4_buffer_clear(&buf);

#if 0
  if( rc==SQLITE4_OK ){
    btPrintMetaTree(db->pPager, 1, pHdr);
    sqlite4BtDebugFastTree(db, nCall);
  }
#endif
  assert_summary_ok(db, SQLITE4_OK);
  db->bFastInsertOp = bFastInsertOp;
  return rc;
}

/*
** If possible, schedule a merge operation. 
**
** The merge operation is selected based on the following criteria:
**
**   * The more levels involved in the merge the better, and
**   * It is better to merge younger segments than older ones.
*/
static int btScheduleMerge(bt_db *db){
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
  BtPage *pPg = 0;                /* Schedule page */
  u8 *aData;                      /* Schedule page data */
  int rc;                         /* Return code */

  /* Details of proposed merge: */
  u32 iAge;                       /* Input age */
  u32 iMin;                       /* Minimum input level number */
  u32 iMax;                       /* Maximum input level number */
  u32 iOutLvl;                    /* Output level number */

  /* Find the schedule page. If there is no schedule page, allocate it now. */
  if( pHdr->iSRoot==0 ){
    rc = sqlite4BtPageAllocate(db->pPager, &pPg);
    if( rc==SQLITE4_OK ){
      u8 *aData = btPageData(pPg);
      memset(aData, 0, pHdr->pgsz);
      sqlite4BtPagerDbhdrDirty(db->pPager);
      pHdr->iSRoot = sqlite4BtPagePgno(pPg);
    }
  }else{
    rc = sqlite4BtPageGet(db->pPager, pHdr->iSRoot, &pPg);
  }

  /* Check if the schedule page is busy. If so, no new merge may be 
  ** scheduled. If the schedule page is not busy, call btFindMerge() to
  ** figure out which levels should be scheduled for merge.  */
  if( rc==SQLITE4_OK ){
    aData = btPageData(pPg);
    
    switch( btGetU32(aData) ){
      case BT_SCHEDULE_BUSY:
        rc = SQLITE4_NOTFOUND;
        break;

      case BT_SCHEDULE_DONE: {
        BtSchedule s;
        rc = btReadSchedule(db, aData, &s);
        if( rc==SQLITE4_OK ){
          rc = btIntegrateMerge(db, &s);
        }
        if( rc==SQLITE4_OK ){
          s.eBusy = BT_SCHEDULE_EMPTY;
          btWriteSchedulePage(pPg, &s, &rc);
        }
        break;
      }

      default: /* BT_SCHEDULE_EMPTY */
        break;
    }

    if( rc==SQLITE4_OK ){
      rc = btFindMerge(db, &iAge, &iMin, &iMax, &iOutLvl);
    }
  }

  if( rc==SQLITE4_OK ){
    BtSchedule s;
    memset(&s, 0, sizeof(BtSchedule));

    s.eBusy = BT_SCHEDULE_BUSY;
    s.iAge = iAge;
    s.iMaxLevel = iMax;
    s.iMinLevel = iMin;
    s.iOutLevel = iOutLvl;
    rc = btAllocateBlock(db, db->nScheduleAlloc, s.aBlock);

    btWriteSchedulePage(pPg, &s, &rc);
  }

  sqlite4BtPageRelease(pPg);
  if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;
  return rc;
}

static int btFastInsertRoot(
  bt_db *db, 
  BtDbHdr *pHdr, 
  u32 *piRoot
){
  int rc = SQLITE4_OK;

  assert( db->bFastInsertOp );
  db->bFastInsertOp = 0;

  /* If the meta-tree has not been created, create it now. */
  if( pHdr->iMRoot==0 ){
    sqlite4BtPagerDbhdrDirty(db->pPager);
    rc = btAllocateNewRoot(db, BT_PGFLAGS_METATREE, &pHdr->iMRoot);
  }

  /* If no writable sub-tree current exists, create one */ 
  if( rc==SQLITE4_OK && pHdr->iSubBlock==0 ){
    u32 iLevel;                   /* Level number for new sub-tree */
    u32 iSubBlock;                /* New block */

    rc = btAllocateNewLevel(db, pHdr, &iLevel);
    if( rc==SQLITE4_OK ){
      rc = btAllocateBlock(db, 1, &iSubBlock);
    }

    if( rc==SQLITE4_OK ){
      u8 aKey[8];
      u8 aVal[4];
      sqlite4BtPagerDbhdrDirty(db->pPager);
      pHdr->iSubBlock = iSubBlock;
      pHdr->nSubPg = 1;           /* Root page is automatically allocated */

      /* The key for the new entry consists of the concatentation of two 
      ** 32-bit big-endian integers - the <age> and <level-no>. The age
      ** of the new segment is 0. The level number is one greater than the
      ** level number of the previous segment.  */
      btPutU32(&aKey[0], 0);
      btPutU32(&aKey[4], ~iLevel);
      btPutU32(&aVal[0], btFirstOfBlock(pHdr, iSubBlock));
      rc = btReplaceEntry(db, pHdr->iMRoot, aKey, 8, aVal, 4);
    }

    if( rc==SQLITE4_OK ){
      u32 iRoot = btFirstOfBlock(pHdr, pHdr->iSubBlock);
      BtPage *pPg = 0;

      rc = sqlite4BtPageGet(db->pPager, iRoot, &pPg);
      if( rc==SQLITE4_OK ) rc = sqlite4BtPageWrite(pPg);
      if( rc==SQLITE4_OK ){
        u8 *aData = btPageData(pPg);
        memset(&aData[pHdr->pgsz-6], 0, 6);
        aData[0] = 0;
      }
      sqlite4BtPageRelease(pPg);
    }
  }

  if( rc==SQLITE4_OK ){
    *piRoot = btFirstOfBlock(pHdr, pHdr->iSubBlock);
  }
  db->bFastInsertOp = 1;
  return rc;
}

/*
** Set up a fast-insert cursor to read the input data for a merge operation.
*/
static int fiSetupMergeCsr(
  bt_db *db,                      /* Database handle */
  BtDbHdr *pHdr,                  /* Current database header values */
  BtSchedule *p,                  /* Description of merge operation */
  FiCursor *pCsr                  /* Populate this object before returning */
){
  int iSub;                       /* Used to loop through component cursors */
  int rc;                         /* Return code */

  memset(pCsr, 0, sizeof(FiCursor));
  pCsr->base.flags = CSR_TYPE_FAST | CSR_NEXT_OK | CSR_VISIT_DEL;
  pCsr->base.pDb = db;
  rc = fiCsrAllocateSubs(db, pCsr, (p->iMaxLevel - p->iMinLevel) + 1);
  assert( rc==SQLITE4_OK || pCsr->nBt==0 );

  /* Initialize each sub-cursor */
  for(iSub=0; iSub<pCsr->nBt && rc==SQLITE4_OK; iSub++){
    u32 iLvl = p->iMaxLevel - iSub;
    FiSubCursor *pSub = &pCsr->aSub[iSub];
    BtCursor *pM = &pSub->mcsr;
    const void *pKey = 0; int nKey = 0;

    /* Seek the meta-tree cursor to the first entry (smallest keys) for the
    ** current level. If an earlier merge operation completely emptied the
    ** level, the sought entry may not exist at all.  */
    fiFormatPrefix(pSub->aPrefix, p->iAge, iLvl);
    btCsrSetup(db, pHdr->iMRoot, pM);
    rc = btCsrSeek(pM, 0, pSub->aPrefix, sizeof(pSub->aPrefix), BT_SEEK_GE, 0);

    if( rc==SQLITE4_INEXACT ){
      const int nPrefix = sizeof(pSub->aPrefix);
      rc = btCsrKey(pM, &pKey, &nKey);
      if( rc==SQLITE4_OK ){
        if( nKey<nPrefix || memcmp(pKey, pSub->aPrefix, nPrefix) ){
          /* Level is completely empty. Nothing to do for this level. */
          btCsrReset(pM, 0);
          rc = SQLITE4_NOTFOUND;
        }else{
          nKey -= nPrefix;
          pKey = (const void*)(((const u8*)pKey) + nPrefix);
        }
      }
    }

    /* Assuming the process above found a block, set up the block cursor and
    ** seek it to the smallest valid key.  */
    if( rc==SQLITE4_OK ){
      const void *pVal = 0; int nVal = 0;
      rc = btCsrData(pM, 0, 4, &pVal, &nVal);
      if( rc==SQLITE4_OK ){
        u32 iRoot = sqlite4BtGetU32((const u8*)pVal);
        btCsrSetup(db, iRoot, &pSub->csr);
        rc = btCsrSeek(&pSub->csr, 0, pKey, nKey, BT_SEEK_GE, 0);
        if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
        if( rc==SQLITE4_NOTFOUND ){
          rc = fiSubCsrStep(0, pSub, 1);
          if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;
        }
      }
    }else if( rc==SQLITE4_NOTFOUND ){
      assert( pSub->csr.nPg==0 );
      assert( pSub->mcsr.nPg==0 );
      rc = SQLITE4_OK;
    }
  }

  if( rc==SQLITE4_OK ){
    rc = fiCsrSetCurrent(pCsr);
  }

  return rc;
}

/*
** An object of type FiWriter is used to write to a fast-insert sub-tree.
*/
typedef struct FiWriter FiWriter;
typedef struct FiWriterPg FiWriterPg;
struct FiWriterPg {
  int bAllocated;                 /* True if between Alloc() and Flush() */
  int nCell;                      /* Number of cells on page */
  int iFree;                      /* Free space offset */
  u8 *aBuf;                       /* Buffer to assemble content in */
};
struct FiWriter {
  bt_db *db;                      /* Database handle */
  BtSchedule *pSched;             /* Schedule object being implemented */
  int pgsz;                       /* Page size in bytes */
  int nPgPerBlk;                  /* Pages per block in this database */
  u32 iBlk;                       /* Block to write to */
  int nOvflPerPage;               /* Overflow pointers per page */

  int nAlloc;                     /* Pages allocated from current block */
  int nWrite;                     /* Pages written to current block */
  int nHier;                      /* Valid entries in apHier[] array */
  FiWriterPg aHier[MAX_SUBTREE_DEPTH];      /* Path from root to current leaf */

  /* Variables used to collect overflow pages freed by merge operation */
  int nOvfl;                      /* Number of pointers already in buffer */
  u8 *aTrunk;                     /* Buffer for current trunk page */
};

/*
** Write the page out to disk.
*/
static int fiWriterFlush(
  FiWriter *p, 
  FiWriterPg *pPg, 
  u32 *pPgno
){
  int rc;                         /* Return code */
  u32 pgno;                       /* New page number */

  assert( pPg->bAllocated==1 );
  assert( p->iBlk>1 );

  pPg->bAllocated = 0;
  pgno = (p->nPgPerBlk * (p->iBlk-1) + 1) + p->nWrite;
  p->nWrite++;
  assert( p->nWrite<=p->nAlloc );
  assert( p->nWrite<=p->nPgPerBlk );
  rc = sqlite4BtPagerRawWrite(p->db->pPager, pgno, pPg->aBuf);
  *pPgno = pgno;
  return rc;
}

static int fiWriterFlushAll(FiWriter *p){
  int i;
  int rc = SQLITE4_OK;
  u32 pgno = 0;

  for(i=0; rc==SQLITE4_OK && i<p->nHier; i++){
    FiWriterPg *pPg = &p->aHier[i];
    if( i!=0 ){
      btPutU32(&pPg->aBuf[1], pgno);
    }
    rc = fiWriterFlush(p, pPg, &pgno);

    btFreeBuffer(p->db, pPg->aBuf);
    pPg->aBuf = 0;
  }

  for(i=0; p->pSched->aBlock[i]!=p->iBlk; i++);
  assert( p->pSched->aRoot[i]==0 );
  p->pSched->aRoot[i] = pgno;

  return rc;
}

static void fiWriterCleanup(FiWriter *p){
}

/*
** Allocate a page buffer to use as part of writing a sub-tree. 
**
** No page number is assigned at this point.
*/
static int fiWriterAlloc(FiWriter *p, int bLeaf, FiWriterPg *pPg){
  int rc = SQLITE4_OK;

  assert( pPg->bAllocated==0 );
  assert( p->nAlloc<p->nPgPerBlk );

  pPg->bAllocated = 1;
  p->nAlloc++;
  pPg->nCell = 0;

  if( pPg->aBuf==0 ){
    rc = btNewBuffer(p->db, &pPg->aBuf);
  }
  if( rc==SQLITE4_OK ){
    if( bLeaf ){
      pPg->iFree = 1;
      pPg->aBuf[0] = 0x00;
    }else{
      pPg->iFree = 5;
      pPg->aBuf[0] = BT_PGFLAGS_INTERNAL;
    }
    btPutU16(&pPg->aBuf[p->pgsz-2], 0);
  }
  return rc;
}

static int fiWriterPush(FiWriter *p, const u8 *pKey, int nKey){
  int rc = SQLITE4_OK;
  int i;                          /* Iterator variable */
  int iIns;                       /* Index in aHier[] to insert new key at */
  int nByte;                      /* Bytes required by new cell */
  int iOff;                       /* Byte offset to write to */
  int nMaxAlloc;                  /* Maximum pages that may be allocated */
  u32 pgno;
  FiWriterPg *pPg;

  nByte = 2 + sqlite4BtVarintLen32(nKey) + nKey + 4;

  nMaxAlloc = MIN((p->nPgPerBlk - p->nAlloc), MAX_SUBTREE_DEPTH);
  for(iIns=1; iIns<p->nHier; iIns++){
    /* Check if the key will fit on page FiWriter.aHier[iIns]. If so,
    ** break out of the loop. */
    int nFree;
    pPg = &p->aHier[iIns];
    nFree = p->pgsz - (pPg->iFree + 6 + pPg->nCell*2);
    if( nFree>=nByte ) break;
  }

  if( (iIns + (iIns==p->nHier))>=nMaxAlloc ){
    rc = BT_BLOCKFULL;
  }
  if( rc==SQLITE4_OK && iIns==p->nHier ){
    p->nHier = iIns+1;
    rc = fiWriterAlloc(p, 0, &p->aHier[iIns]);
  }

  for(i=0; rc==SQLITE4_OK && i<iIns; i++){
    pPg = &p->aHier[i];
    if( i!=0 ){
      btPutU32(&pPg->aBuf[1], pgno);
    }
    rc = fiWriterFlush(p, pPg, &pgno);
    if( rc==SQLITE4_OK ){
      rc = fiWriterAlloc(p, (i==0), pPg);
    }
  }

  /* Write the b+tree cell containing (pKey/nKey) into page p->aHier[iIns]. */
  if( rc==SQLITE4_OK ){
    pPg = &p->aHier[iIns];
    iOff = pPg->iFree;
    btPutU16(btCellPtrFind(pPg->aBuf, p->pgsz, pPg->nCell), (u16)iOff);
    pPg->nCell++;
    btPutU16(&pPg->aBuf[p->pgsz-2], pPg->nCell);
    iOff += sqlite4BtVarintPut32(&pPg->aBuf[iOff], nKey);
    memcpy(&pPg->aBuf[iOff], pKey, nKey);
    iOff += nKey;
    btPutU32(&pPg->aBuf[iOff], pgno);
    iOff += 4;
    pPg->iFree = iOff;
  }

  return rc;
}


/*
** Initialize a writer object that will be used to implement the schedule
** passed as the second argument.
*/
static void fiWriterInit(
  bt_db *db, 
  BtSchedule *pSched, 
  FiWriter *p,
  int *pRc
){
  if( *pRc==SQLITE4_OK ){
    BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
    int i;

    memset(p, 0, sizeof(FiWriter));
    p->db = db;
    p->pSched = pSched;
    p->pgsz = pHdr->pgsz;
    p->nPgPerBlk = (pHdr->blksz / pHdr->pgsz);
    p->nOvflPerPage = ((pHdr->pgsz / 8) - 1);

    /* Find a block to write to */
    for(i=0; pSched->aBlock[i]; i++){
      if( pSched->aRoot[i]==0 ) break;
    }
    if( pSched->aBlock[i]==0 ){
      *pRc = BT_BLOCKFULL;
    }else{
      p->iBlk = pSched->aBlock[i];
    }
  }
}

static int fiWriterFlushOvfl(FiWriter *p, u32 *pPgno){
  u32 pgno;                       /* Page number for new overflow ptr page */
  int rc;

  /* Set the "number of entries" field */
  btPutU32(p->aTrunk, p->nOvfl);

  /* Write the page to disk */
  pgno = (p->nPgPerBlk * (p->iBlk-1) + 1) + p->nWrite;
  p->nWrite++;
  p->nAlloc++;
  rc = sqlite4BtPagerRawWrite(p->db->pPager, pgno, p->aTrunk);

  btPutU32(&p->aTrunk[4], pgno);
  if( pPgno ) *pPgno = pgno;
  p->nOvfl = 0;

  return rc;
}


static int fiWriterFreeOverflow(FiWriter *p, FiCursor *pCsr){
  const void *pKey;               /* Buffer containing current key for pCsr */
  int nKey;                       /* Size of pKey in bytes */
  int rc;
  int i;

  rc = btCsrKey(&pCsr->aSub[pCsr->iBt].csr, &pKey, &nKey);
  for(i=pCsr->iBt+1; i<pCsr->nBt && rc==SQLITE4_OK; i++){
    BtCursor *pSub = &pCsr->aSub[i].csr;
    if( pSub->nPg ){
      const void *pSKey;            /* Current key for pSub */
      int nSKey;                    /* Size of pSKey in bytes */
      rc = btCsrKey(pSub, &pSKey, &nSKey);
      if( rc==SQLITE4_OK 
       && 0==btKeyCompare(pKey, nKey, pSKey, nSKey) 
       && btCsrOverflow(pSub)
      ){
        u32 pgno = sqlite4BtPagePgno(pSub->apPage[pSub->nPg-1]);
        int iCell = pSub->aiCell[pSub->nPg-1];

        if( p->aTrunk==0 ){
          assert( p->nOvfl==0 );
          rc = btNewBuffer(p->db, &p->aTrunk);
          if( rc==SQLITE4_OK ) memset(p->aTrunk, 0, 8);
        }else if( p->nOvflPerPage==p->nOvfl ){
          rc = fiWriterFlushOvfl(p, 0);
          assert( p->nOvfl==0 );
        }
        if( rc==SQLITE4_OK ){
          assert( p->nOvfl<p->nOvflPerPage );
          btPutU32(&p->aTrunk[8 + p->nOvfl*8], pgno);
          btPutU32(&p->aTrunk[8 + p->nOvfl*8 + 4], iCell);
          p->nOvfl++;
        }
      }
    }
  }

  return rc;
}

/*
** Argument aBuf points to a buffer containing a leaf cell. This function
** returns a pointer to the key prefix embedded within the cell. Before
** returning, *pnKey is set to the size of the key prefix in bytes.
*/
static const u8 *btKeyPrefixFromCell(const u8 *aBuf, int *pnKey){
  u8 *p = (u8*)aBuf;
  int nKey;

  p += sqlite4BtVarintGet32(p, &nKey);
  if( nKey==0 ){
    p += sqlite4BtVarintGet32(p, &nKey);
  }

  *pnKey = nKey;
  return p;
}

/*
** Return the size in bytes of the shortest prefix of (pNew/nNew) that
** is greater than (pOld/nOld). Or, if that prefix would be too large
** to store on an internal b+tree node, return 
*/
static int btPrefixLength(
  int pgsz, 
  const u8 *pOld, int nOld, 
  const u8 *pNew, int nNew
){
  int nPrefix;
  int nCmp = MIN(nOld, nNew);
  for(nPrefix=0; nPrefix<nCmp && pOld[nPrefix]==pNew[nPrefix]; nPrefix++);
  if( nPrefix>=(pgsz/4) ) return 0;
  assert( nPrefix<nNew );
  return nPrefix+1;
}

static int fiWriterAdd(FiWriter *p, const void *pCell, int nCell){
  int rc = SQLITE4_OK;
  FiWriterPg *pPg;
  int nReq;                       /* Bytes of space required on leaf page */
  int nFree;                      /* Bytes of space available on leaf page */

  if( p->nHier==0 ){
    assert( p->aHier[0].nCell==0 );
    assert( p->aHier[0].iFree==0 );
    p->nHier++;
    rc = fiWriterAlloc(p, 1, &p->aHier[0]);
    assert( rc!=BT_BLOCKFULL );
  }
  pPg = &p->aHier[0];

  /* Calculate the space required for the cell. And space available on
  ** the current leaf page.  */
  nReq = nCell + 2;
  nFree = p->pgsz - pPg->iFree - (6 + 2*pPg->nCell);

  if( nReq>nFree ){
    /* The current leaf page is finished. Cell pCell/nCell will become
    ** the first cell on the next leaf page.  */
    const u8 *pOld; int nOld;     /* Prefix of last key on current leaf */
    const u8 *pNew; int nNew;     /* Prefix of new key */
    int nPrefix;

    pOld = btCellFind(pPg->aBuf, p->pgsz, btCellCount(pPg->aBuf, p->pgsz)-1);
    pOld = btKeyPrefixFromCell(pOld, &nOld);
    pNew = btKeyPrefixFromCell(pCell, &nNew);

    /* Push the shortest prefix of key (pNew/nNew) that is greater than key
    ** (pOld/nOld) up into the b+tree hierarchy.  */
    nPrefix = btPrefixLength(p->pgsz, pOld, nOld, pNew, nNew);
    rc = fiWriterPush(p, pNew, nPrefix);
  }

  /* Write the leaf cell into the page at FiWriter.aHier[0] */
  if( rc==SQLITE4_OK ){
    memcpy(&pPg->aBuf[pPg->iFree], pCell, nCell);
    btPutU16(btCellPtrFind(pPg->aBuf, p->pgsz, pPg->nCell), pPg->iFree);
    pPg->nCell++;
    btPutU16(&pPg->aBuf[p->pgsz-2], pPg->nCell);
    pPg->iFree += nCell;
  }

  return rc;
}

/*
** This is called by a checkpointer to handle a schedule page.
*/
SQLITE4_PRIVATE int sqlite4BtMerge(bt_db *db, BtDbHdr *pHdr, u8 *aSched){
  BtSchedule s;                   /* Deserialized schedule object */
  int rc = SQLITE4_OK;            /* Return code */

  /* Set up the input cursor. */
  btReadSchedule(db, aSched, &s);
  if( s.eBusy==BT_SCHEDULE_BUSY ){
    FiCursor fcsr;                /* FiCursor used to read input */
    FiWriter writer;              /* FiWriter used to write output */

    rc = fiSetupMergeCsr(db, pHdr, &s, &fcsr);
    assert( rc!=SQLITE4_NOTFOUND );
    assert_ficursor_ok(&fcsr, rc);
    fiWriterInit(db, &s, &writer, &rc);

    /* The following loop runs once for each key copied from the input to
    ** the output segments. It terminates either when the input is exhausted
    ** or when all available output blocks are full.  */
    while( rc==SQLITE4_OK ){
      const void *pCell;          /* Cell to copy to output */
      int nCell;                  /* Size of cell in bytes */

      /* Read the current cell from the input and push it to the output. */
      fiCsrCell(&fcsr, &pCell, &nCell);
      rc = fiWriterAdd(&writer, pCell, nCell);
      if( rc==BT_BLOCKFULL ){
        int nOvflSaved = writer.nOvfl;
        u8 *aTrunkSaved = writer.aTrunk;
        rc = fiWriterFlushAll(&writer);
        fiWriterInit(db, &s, &writer, &rc);
        writer.nOvfl = nOvflSaved;
        writer.aTrunk = aTrunkSaved;
      }else if( rc==SQLITE4_OK ){
        rc = fiWriterFreeOverflow(&writer, &fcsr);
        if( rc==SQLITE4_OK ) rc = fiCsrStep(&fcsr);
      }
    }

    /* Assuming no error has occurred, update the serialized BtSchedule
    ** structure stored in buffer aSched[]. The caller will write this
    ** buffer to the database file as page (pHdr->iSRoot).  */
    if( rc==BT_BLOCKFULL || rc==SQLITE4_NOTFOUND ){

      if( rc==SQLITE4_NOTFOUND ){
        assert( fcsr.iBt<0 );
        s.iNextPg = 0;
        s.iNextCell = 0;
      }else{
        BtCursor *pCsr = &fcsr.aSub[fcsr.iBt].csr;
        assert( pCsr->nPg>0 );
        s.iNextPg = sqlite4BtPagePgno(pCsr->apPage[pCsr->nPg-1]);
        s.iNextCell = pCsr->aiCell[pCsr->nPg-1];
      }
      s.iFreeList = 0;
      s.eBusy = BT_SCHEDULE_DONE;

      assert( s.iFreeList==0 );
      rc = SQLITE4_OK;
      if( writer.aTrunk ){
        rc = fiWriterFlushOvfl(&writer, &s.iFreeList);
      }
      if( rc==SQLITE4_OK ){
        rc = fiWriterFlushAll(&writer);
      }
      if( rc==SQLITE4_OK ){
        btWriteSchedule(aSched, &s, &rc);
      }
    }

    fiWriterCleanup(&writer);
    fiCsrReset(&fcsr);
  }
  return rc;
}

/*
** Insert a new key/value pair or replace an existing one.
**
** This function may modify either the b-tree or fast-insert-tree, depending
** on whether or not the db->bFastInsertOp flag is set.
*/
SQLITE4_PRIVATE int sqlite4BtReplace(bt_db *db, const void *pK, int nK, const void *pV, int nV){
  int rc = SQLITE4_OK;

  /* Debugging output. */
  sqlite4BtDebugKV((BtLock*)db->pPager, "replace", (u8*)pK, nK, (u8*)pV, nV);

  /* Save the position of any open cursors */
  rc = btSaveAllCursor(db, 0);
  assert( rc!=SQLITE4_NOTFOUND && rc!=SQLITE4_INEXACT );
  btCheckPageRefs(db);

  /* Call btReplaceEntry() to update either the main b-tree or the top-level
  ** sub-tree. Pass iRoot=0 to update the sub-tree, or the root page number
  ** of the b-tree to update the b-tree.  */
  if( rc==SQLITE4_OK ){
    u32 iRoot = 0;
    if( !db->bFastInsertOp ){
      BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
      iRoot = pHdr->iRoot;
    }
    if( rc==SQLITE4_OK ){
      rc = btReplaceEntry(db, iRoot, pK, nK, pV, nV);
    }
  }

  btCheckPageRefs(db);
  db->bFastInsertOp = 0;
  return rc;
}

#ifndef NDEBUG
SQLITE4_PRIVATE void sqlite4BtDebugTree(bt_db *db, int iCall, u32 iRoot){
  BtPage *pPg;
  sqlite4_buffer buf;
  int pgsz;

  pgsz = sqlite4BtPagerPagesize(db->pPager);
  sqlite4_buffer_init(&buf, 0);
  sqlite4BtPageGet(db->pPager, iRoot, &pPg);
  btPageToAscii(iRoot, 1, db->pPager, btPageData(pPg), pgsz, &buf);
  fprintf(stderr, "%d TREE at %d:\n", iCall, (int)iRoot);
  fprintf(stderr, "%.*s", buf.n, (char*)buf.p);
  sqlite4_buffer_clear(&buf);
  sqlite4BtPageRelease(pPg);
}

SQLITE4_PRIVATE void sqlite4BtDebugFastTree(bt_db *db, int iCall){
  BtDbHdr *pHdr;
  BtCursor mcsr;
  int rc;

  pHdr = sqlite4BtPagerDbhdr(db->pPager);
  btCsrSetup(db, pHdr->iMRoot, &mcsr);
  for(rc=btCsrEnd(&mcsr, 0); rc==SQLITE4_OK; rc=btCsrStep(&mcsr, 1)){
    u32 iSubRoot;
    const void *pK; int nK;
    rc = btCsrKey(&mcsr, &pK, &nK);
    if( rc!=SQLITE4_OK ) break;
    if( nK==sizeof(aSummaryKey) && 0==memcmp(aSummaryKey, pK, nK) ) break;
    rc = btCsrData(&mcsr, 0, 4, &pK, &nK);
    if( rc!=SQLITE4_OK ) break;

    iSubRoot = btGetU32((const u8*)pK);
    sqlite4BtDebugTree(db, iCall, iSubRoot);
  }
  btCsrReset(&mcsr, 1);
}
#endif   /* ifndef NDEBUG */


/*
** Delete the entry that the cursor currently points to.
*/
SQLITE4_PRIVATE int sqlite4BtDelete(bt_cursor *pBase){
  bt_db *db = pBase->pDb;
  int rc;

  if( IsBtCsr(pBase) ){
    BtCursor *pCsr = (BtCursor*)pBase;

    rc = btCsrReseek(pCsr);
    if( rc==SQLITE4_OK ){
      rc = btSaveAllCursor(db, pCsr);
    }
    if( rc==SQLITE4_OK ){
      rc = btOverflowDelete(pCsr);
    }
    if( rc==SQLITE4_OK ){
      rc =  btDeleteFromPage(pCsr, 1);
    }
    if( rc==SQLITE4_OK ){
      rc = btBalanceIfUnderfull(pCsr);
    }

    btCsrReleaseAll(pCsr);
  }else{
    FiCursor *pCsr = (FiCursor*)pBase;
    BtCursor *pSub = &pCsr->aSub[pCsr->iBt].csr;

    void *pKey;
    int nKey;

    rc = btCsrBuffer(pSub, 0);
    pKey = pSub->ovfl.buf.p;
    nKey = pSub->ovfl.nKey;

    if( rc==SQLITE4_OK ){
      int bFastInsertOp = db->bFastInsertOp;
      db->bFastInsertOp = 1;
      rc = sqlite4BtReplace(db, pKey, nKey, 0, -1);
      db->bFastInsertOp = bFastInsertOp;
    }

  }
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtSetCookie(bt_db *db, unsigned int iVal){
  return sqlite4BtPagerSetCookie(db->pPager, iVal);
}

SQLITE4_PRIVATE int sqlite4BtGetCookie(bt_db *db, unsigned int *piVal){
  return sqlite4BtPagerGetCookie(db->pPager, piVal);
}

static int btControlTransaction(bt_db *db, int *piCtx){
  int rc = SQLITE4_OK;
  int iTrans = sqlite4BtTransactionLevel(db);

  if( iTrans==0 ){
    rc = sqlite4BtBegin(db, 1);
  }
  *piCtx = iTrans;
  return rc;
}

static void btControlTransactionDone(bt_db *db, int iCtx){
  if( iCtx==0 ) sqlite4BtCommit(db, 0);
}

static int btCheckForPageLeaks(bt_db*, sqlite4_buffer*);

static int btControlInfo(bt_db *db, bt_info *pInfo){
  int rc = SQLITE4_OK;

  switch( pInfo->eType ){
    case BT_INFO_PAGEDUMP_ASCII:
    case BT_INFO_PAGEDUMP: {
      int iCtx;                   /* ControlTransaction() context */
      rc = btControlTransaction(db, &iCtx);
      if( rc==SQLITE4_OK ){
        BtPage *pPg = 0;
        rc = sqlite4BtPageGet(db->pPager, pInfo->pgno, &pPg);
        if( rc==SQLITE4_OK ){
          BtPager *p = db->pPager;
          int bAscii = (pInfo->eType==BT_INFO_PAGEDUMP_ASCII);
          u8 *aData;
          int nData;
          aData = btPageData(pPg);
          nData = sqlite4BtPagerPagesize(p);
          btPageToAscii(pInfo->pgno, bAscii, p, aData, nData, &pInfo->output);
          sqlite4_buffer_append(&pInfo->output, "", 1);
          sqlite4BtPageRelease(pPg);
        }
        btControlTransactionDone(db, iCtx);
      }
      break;
    }

    case BT_INFO_FILENAME: {
      const char *zFile;
      zFile = sqlite4BtPagerFilename(db->pPager, BT_PAGERFILE_DATABASE);
      rc = sqlite4_buffer_set(&pInfo->output, zFile, strlen(zFile)+1);
      break;
    }

    case BT_INFO_HDRDUMP: {
      int iCtx;                   /* ControlTransaction() context */
      rc = btControlTransaction(db, &iCtx);
      if( rc==SQLITE4_OK ){
        rc = sqlite4BtPagerHdrdump(db->pPager, &pInfo->output);
        btControlTransactionDone(db, iCtx);
      }
      break;
    }

    case BT_INFO_BLOCK_FREELIST: 
    case BT_INFO_PAGE_FREELIST: {
      int iCtx;                   /* ControlTransaction() context */
      rc = btControlTransaction(db, &iCtx);
      if( rc==SQLITE4_OK ){
        BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
        u32 iFirst = (
            pInfo->eType==BT_INFO_BLOCK_FREELIST?pHdr->iFreeBlk:pHdr->iFreePg
        );
        rc = btFreelistToAscii(db, iFirst, &pInfo->output);
        btControlTransactionDone(db, iCtx);
      }
      break;
    }

    case BT_INFO_PAGE_LEAKS: {
      int iCtx;                   /* ControlTransaction() context */
      rc = btControlTransaction(db, &iCtx);
      if( rc==SQLITE4_OK ){
        rc = btCheckForPageLeaks(db, &pInfo->output);
        btControlTransactionDone(db, iCtx);
      }
      break;
    }

    default: {
      rc = SQLITE4_ERROR;
      break;
    }
  }
  sqlite4_buffer_append(&pInfo->output, "\0", 1);
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtControl(bt_db *db, int op, void *pArg){
  int rc = SQLITE4_OK;

  switch( op ){
    case BT_CONTROL_INFO: {
      bt_info *pInfo = (bt_info*)pArg;
      rc = btControlInfo(db, pInfo);
      break;
    }

    case BT_CONTROL_GETVFS: {
      *((bt_env**)pArg) = sqlite4BtPagerGetEnv(db->pPager);
      break;
    }

    case BT_CONTROL_SETVFS: {
      sqlite4BtPagerSetEnv(db->pPager, (bt_env*)pArg);
      break;
    }

    case BT_CONTROL_SAFETY: {
      int *pInt = (int*)pArg;
      sqlite4BtPagerSetSafety(db->pPager, pInt);
      break;
    }

    case BT_CONTROL_AUTOCKPT: {
      int *pInt = (int*)pArg;
      sqlite4BtPagerSetAutockpt(db->pPager, pInt);
      break;
    }

    case BT_CONTROL_LOGSIZE: {
      int *pInt = (int*)pArg;
      sqlite4BtPagerLogsize(db->pPager, pInt);
      break;
    }
                             
    case BT_CONTROL_MULTIPROC: {
      int *pInt = (int*)pArg;
      sqlite4BtPagerMultiproc(db->pPager, pInt);
      break;
    }

    case BT_CONTROL_LOGSIZECB: {
      bt_logsizecb *p = (bt_logsizecb*)pArg;
      sqlite4BtPagerLogsizeCb(db->pPager, p);
      break;
    }

    case BT_CONTROL_CHECKPOINT: {
      bt_checkpoint *p = (bt_checkpoint*)pArg;
      rc = sqlite4BtPagerCheckpoint(db->pPager, p);
      break;
    }

    case BT_CONTROL_FAST_INSERT_OP: {
      db->bFastInsertOp = 1;
      break;
    }

    case BT_CONTROL_BLKSZ: {
      int *pInt = (int*)pArg;
      ((BtLock*)db->pPager)->nBlksz = *pInt;
      break;
    }

    case BT_CONTROL_PAGESZ: {
      int *pInt = (int*)pArg;
      if( sqlite4BtPagerFilename(db->pPager, BT_PAGERFILE_DATABASE) ){
        int iCtx;                   /* ControlTransaction() context */
        rc = btControlTransaction(db, &iCtx);
        if( rc==SQLITE4_OK ){
          *pInt = (int)(sqlite4BtPagerDbhdr(db->pPager)->pgsz);
          btControlTransactionDone(db, iCtx);
        }
      }else{
        BtLock *pLock = (BtLock*)db->pPager;
        int nNew = *pInt;
        if( ((nNew-1)&nNew)==0 && nNew>=512 && nNew<=32768 ){
          pLock->nPgsz = nNew;
        }
        *pInt = pLock->nPgsz;
      }
      break;
    }

  }

  return rc;
}

static void markBlockAsUsed(
  bt_db *db,
  u32 iBlk,
  u8 *aUsed
){
  if( iBlk ){
    BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
    int nPgPerBlk = (pHdr->blksz / pHdr->pgsz);
    int i;

    for(i=0; i<nPgPerBlk; i++){
      u32 iPg = (iBlk-1) * nPgPerBlk + 1 + i;
      assert( aUsed[iPg]==0 || aUsed[iPg]==1 );
      aUsed[iPg] = 1;
    }
  }
}

/*
** Iterate through the b-tree with root page iRoot. For each page used
** by the b-tree, set the corresponding entry in the aUsed[] array.
*/
static void assert_pages_used(
  bt_db *db,                      /* Database handle */
  u32 iRoot,                      /* Root page of b-tree to iterate through */
  const void *pFirst, int nFirst, /* Starting with this key (if pFirst!=0) */
  int *pRc                        /* IN/OUT: Error code */
){
  if( *pRc==SQLITE4_OK && iRoot ){
    BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
    int nPgPerBlk = (pHdr->blksz / pHdr->pgsz);
    int bMeta = (iRoot==pHdr->iMRoot);
    BtLock *pLock = (BtLock*)(db->pPager);
    u8 *aUsed = pLock->aUsed;
    int rc;
    BtCursor csr;

    btCsrSetup(db, iRoot, &csr);
    if( nFirst==0 ){
      rc = btCsrEnd(&csr, 0);
    }else{
      pLock->aUsed = 0;
      rc = btCsrSeek(&csr, 0, pFirst, nFirst, BT_SEEK_GE, BT_CSRSEEK_SEEK);
      if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
      pLock->aUsed = aUsed;
      csr.ovfl.nKey = 0;
    }

    while( rc==SQLITE4_OK ){
      rc = btCsrBuffer(&csr, 1);
      if( bMeta && rc==SQLITE4_OK ){
        u8 *aKey; int nKey;

        btCsrKey(&csr, (const void**)&aKey, &nKey);
        if( nKey!=sizeof(aSummaryKey) || memcmp(aKey, aSummaryKey, nKey) ){
          u8 *aVal; int nVal;
          u32 iSubRoot;
          u32 iBlk;
          int i;
          btCsrData(&csr, 0, 4, (const void**)&aVal, &nVal);
          iSubRoot = btGetU32(aVal);
          iBlk = (iSubRoot / nPgPerBlk) + 1;
          assert_pages_used(db, iSubRoot, &aKey[8], nKey-8, &rc);
          markBlockAsUsed(db, iBlk, aUsed);
        }
      }
      if( rc==SQLITE4_OK ) rc = btCsrStep(&csr, 1);
    }
  }
}

static void assert_freelist_pages_used(
  bt_db *db, 
  int bBlocklist,                 /* True to examine free-block list */
  u8 *aUsed, 
  int *pRc
){
  if( *pRc==SQLITE4_OK ){
    BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
    u32 iTrunk = (bBlocklist ? pHdr->iFreeBlk : pHdr->iFreePg);
    int rc = SQLITE4_OK;

    while( rc==SQLITE4_OK && iTrunk ){
      BtPage *pPg = 0;
      rc = sqlite4BtPageGet(db->pPager, iTrunk, &pPg);
      if( rc==SQLITE4_OK ){
        int i;
        u32 nFree;
        u8 *aData = btPageData(pPg);

        nFree = btGetU32(aData);
        for(i=0; i<nFree; i++){
          u32 pgno = btGetU32(&aData[8 + i*4]);
          if( bBlocklist ){
            markBlockAsUsed(db, pgno, aUsed);
          }else{
            aUsed[pgno]++;
          }
        }

        iTrunk = btGetU32(&aData[4]);
        sqlite4BtPageRelease(pPg);
      }
    }

    *pRc = rc;
  }
}

static void assert_schedule_page_used(bt_db *db, u8 *aUsed, int *pRc){
  BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
  if( *pRc==SQLITE4_OK && pHdr->iSRoot!=0 ){
    int nPgPerBlk = (pHdr->blksz / pHdr->pgsz);
    BtPage *pPg = 0;
    int rc;

    rc = sqlite4BtPageGet(db->pPager, pHdr->iSRoot, &pPg);
    if( rc==SQLITE4_OK ){
      BtSchedule s;
      int i;

      btReadSchedule(db, btPageData(pPg), &s);
      sqlite4BtPageRelease(pPg);

      assert( s.eBusy!=BT_SCHEDULE_BUSY || s.aRoot[0]==0 );
      if( s.eBusy!=BT_SCHEDULE_EMPTY ){
        for(i=0; rc==SQLITE4_OK && i<array_size(s.aBlock); i++){
          markBlockAsUsed(db, s.aBlock[i], aUsed);
        }
      }
    }

    *pRc = rc;
  }
}

/*
** Check that all pages in the database file are accounted for (not leaked).
** If any problems are detected, append a description of them to the buffer
** passed as the second argument.
*/
static int btCheckForPageLeaks(
  bt_db *db,                      /* Database handle */
  sqlite4_buffer *pBuf            /* Write error messages here */
){
  BtLock *pLock = (BtLock*)(db->pPager);

  static int nCall = 0;
  nCall++;

  if( pLock->aUsed==0 ){
    int rc;
    int iCtx;                     /* ControlTransaction() context */
    rc = btControlTransaction(db, &iCtx);

    if( rc==SQLITE4_OK ){
      BtDbHdr *pHdr = sqlite4BtPagerDbhdr(db->pPager);
      u8 *aUsed;
      int i;

      aUsed = btMalloc(db, pHdr->nPg, &rc);
      if( aUsed ) memset(aUsed, 0, pHdr->nPg);
      aUsed[0] = 1;                 /* Page 1 is always in use */
      pLock->aUsed = &aUsed[-1];

      /* The scheduled-merge page, if it is allocated */
      assert_schedule_page_used(db, pLock->aUsed, &rc);

      /* Walk the main b-tree */
      assert_pages_used(db, pHdr->iRoot, 0, 0, &rc);

      /* Walk the meta-tree */
      assert_pages_used(db, pHdr->iMRoot, 0, 0, &rc);

      /* Walk the free-page list */
      assert_freelist_pages_used(db, 0, pLock->aUsed, &rc);

      /* The free-block list */
      assert_freelist_pages_used(db, 1, pLock->aUsed, &rc);

      for(i=0; i<pHdr->nPg; i++){
        if( aUsed[i]!=1 ){
          sqlite4BtBufAppendf(
              pBuf, "refcount on page %d is %d\n", i+1, (int)aUsed[i]
          );
        }
      }
      btFree(db, aUsed);
      btControlTransactionDone(db, iCtx);
      pLock->aUsed = 0;
    }
  }

  return SQLITE4_OK;
}



/************** End of bt_main.c *********************************************/
/************** Begin file bt_pager.c ****************************************/
/*
** 2013 September 14
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/


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


/* By default auto-checkpoint is 1000 */
#define BT_DEFAULT_AUTOCKPT 1000

#define BT_DEFAULT_SAFETY BT_SAFETY_NORMAL

#define BT_DEFAULT_MULTIPROC 1

typedef struct BtPageHash BtPageHash;

typedef struct BtSavepoint BtSavepoint;
typedef struct BtSavepage BtSavepage;

/*
** Hash table for page references currently in memory. Manipulated using
** the following functions:
**
**     btHashAdd()
**     btHashRemove()
**     btHashSearch()
**     btHashClear()
*/
struct BtPageHash {
  int nEntry;                     /* Number of entries in hash table */
  int nHash;                      /* Size of aHash[] array */
  BtPage **aHash;                 /* Hash array */
};

/*
** There is one object of this type for each open sub-transaction. Stored
** in the BtPager.aSavepoint[] array.
*/
struct BtSavepoint {
  int iLevel;                     /* Transaction level value (always >2) */
  BtSavepage *pSavepage;          /* First in linked list of saved data */
  BtDbHdr hdr;                    /* Database header at start of savepoint */
};

struct BtSavepage {
  BtPage *pPg;                    /* Pointer to page this object belongs to */
  u8 *aData;                      /* Saved data */
  BtSavepage *pNext;              /* Next saved page in the same savepoint */
  int iSavepoint;                 /* Transaction number of savepoint */
  BtSavepage *pNextSavepage;      /* Next saved page on the same BtPage */
};

/*
** See macro btPageData() in bt_main.c for why the aData variable must be
** first in this structure.
*/
struct BtPage {
  u8 *aData;                      /* Pointer to current data. MUST BE FIRST */
  BtPager *pPager;                /* Pager object that owns this page handle */
  u32 pgno;                       /* Current page number */
  int nRef;                       /* Number of references to this page */
  int flags;                      /* Mask of BTPAGE_XXX flags */
  BtPage *pNextHash;              /* Next entry with same hash key */
  BtPage *pNextDirty;             /* Next page in BtPager.pDirty list */
  BtPage *pNextLru;               /* Next page in LRU list */
  BtPage *pPrevLru;               /* Previous page in LRU list */
  BtSavepage *pSavepage;          /* List of saved page images */
};

/*
** Candidate values for BtPage.flags
*/
#define BT_PAGE_DIRTY 0x0001      /* Set for pages in BtPager.pDirty list */

/*
** Pager object.
**
** bDirtyHdr:
*/
struct BtPager {
  BtLock btl;                     /* Variables shared with bt_lock module */
  BtLog *pLog;                    /* Logging module */
  int iTransactionLevel;          /* Current transaction level (see bt.h) */
  char *zFile;                    /* Database file name */
  int nFile;                      /* Length of string zFile in bytes */
  BtPageHash hash;                /* Hash table */
  BtPage *pDirty;                 /* List of all dirty pages */
  BtPage *pLru;                   /* Head of LRU list */
  BtPage *pLruTail;               /* Tail of LRU list */
  int nPageAlloc;                 /* Number of page objects allocated */
  int nPageLimit;                 /* Maximum page objects to allocate */
  int nTotalRef;                  /* Total number of outstanding page refs */
  int bDoAutoCkpt;                /* Do auto-checkpoint after next unlock */
  BtSavepoint *aSavepoint;        /* Savepoint array */
  int nSavepoint;                 /* Number of entries in aSavepoint array */
  BtDbHdr *pHdr;                  /* Header object for current read snapshot */
  int bDirtyHdr;                  /* True if pHdr has been modified */
  void *pLogsizeCtx;              /* A copy of this is passed to xLogsize() */
  void (*xLogsize)(void*, int);   /* Log-size Callback function */
};


/**************************************************************************
** Interface to BtPageHash object.
*/

/*
** Return the hash key for page number pgno in a hash table with nHash
** buckets.
*/
static int hashkey(int nHash, u32 pgno){
  return (pgno % nHash);
}

/*
** Add page pPg to the hash table.
*/
static int btHashAdd(BtPager *p, BtPage *pPg){
  int h;

  /* If required, increase the number of buckets in the hash table. */
  if( p->hash.nEntry>=p->hash.nHash/2 ){
    int i;
    int nNew = (p->hash.nHash ? p->hash.nHash*2 : 256);
    BtPage **aNew;
    BtPage **aOld = p->hash.aHash;

    aNew = (BtPage **)sqlite4_malloc(p->btl.pEnv, nNew*sizeof(BtPage*));
    if( aNew==0 ) return btErrorBkpt(SQLITE4_NOMEM);
    memset(aNew, 0, nNew*sizeof(BtPage*));
    for(i=0; i<p->hash.nHash; i++){
      while( aOld[i] ){
        BtPage *pShift = aOld[i];
        aOld[i] = pShift->pNextHash;
        h = hashkey(nNew, pShift->pgno);
        pShift->pNextHash = aNew[h];
        aNew[h] = pShift;
      }
    }
    p->hash.aHash = aNew;
    p->hash.nHash = nNew;
    sqlite4_free(p->btl.pEnv, aOld);
  }

  /* Add the new entry to the hash table. */
  assert( pPg->pNextHash==0 );
  h = hashkey(p->hash.nHash, pPg->pgno);
  pPg->pNextHash = p->hash.aHash[h];
  p->hash.aHash[h] = pPg;
  p->hash.nEntry++;

  return SQLITE4_OK;
}

/*
** Remove page pPg from the hash table.
*/
static void btHashRemove(BtPager *p, BtPage *pPg){
  BtPage **pp;
  int h = hashkey(p->hash.nHash, pPg->pgno);
  for(pp=&p->hash.aHash[h]; *pp!=pPg; pp = &((*pp)->pNextHash));
  *pp = pPg->pNextHash;
  p->hash.nEntry--;
}

/*
** Search the hash table for a page with page number pgno. If found, return
** a pointer to the BtPage object. Otherwise, return NULL.
*/
static BtPage *btHashSearch(BtPager *p, u32 pgno){
  BtPage *pRet = 0;
  if( p->hash.nHash ){
    int h = hashkey(p->hash.nHash, pgno);
    for(pRet=p->hash.aHash[h]; pRet && pRet->pgno!=pgno; pRet=pRet->pNextHash);
  }
  return pRet;
}

/*
** Remove all entries from the hash-table. And free any allocations made
** by earlier calls to btHashAdd().
*/
static void btHashClear(BtPager *p){
  sqlite4_free(p->btl.pEnv, p->hash.aHash);
  memset(&p->hash, 0, sizeof(BtPageHash));
}

#ifndef NDEBUG
static void btHashIterate(
  BtPager *p, 
  void (*xCall)(void*, BtPage*),
  void *pCtx
){
  int i;
  for(i=0; i<p->hash.nHash; i++){
    BtPage *pPg;
    for(pPg=p->hash.aHash[i]; pPg; pPg=pPg->pNextHash){
      xCall(pCtx, pPg);
    }
  }
}
#endif
/*
** End of BtPageHash object interface.
**************************************************************************/

static void btLruAdd(BtPager *pPager, BtPage *pPg){
  assert( pPg->pPrevLru==0 );
  assert( pPg->pNextLru==0 );
  if( pPager->pLru ){
    pPager->pLruTail->pNextLru = pPg;
    pPg->pPrevLru = pPager->pLruTail;
    pPager->pLruTail = pPg;
  }else{
    pPager->pLru = pPg;
    pPager->pLruTail = pPg;
  }
}

/*
** Remove page pPg from the LRU list. If pPg is not currently part of
** the LRU list, the results are undefined.
*/
static void btLruRemove(BtPager *pPager, BtPage *pPg){
  assert( (pPg==pPager->pLru)==(pPg->pPrevLru==0) );
  assert( (pPg==pPager->pLruTail)==(pPg->pNextLru==0) );

  if( pPg->pNextLru ){
    pPg->pNextLru->pPrevLru = pPg->pPrevLru;
  }else{
    pPager->pLruTail = pPg->pPrevLru;
  }
  if( pPg->pPrevLru ){
    pPg->pPrevLru->pNextLru = pPg->pNextLru;
  }else{
    pPager->pLru = pPg->pNextLru;
  }

  pPg->pNextLru = 0;
  pPg->pPrevLru = 0;
}

/*
** Open a new pager database handle.
*/
SQLITE4_PRIVATE int sqlite4BtPagerNew(sqlite4_env *pEnv, int nExtra, BtPager **pp){
  BtPager *p;
  int nByte;

  nByte = sizeof(BtPager) + nExtra;
  p = (BtPager*)sqlite4_malloc(pEnv, nByte);
  if( !p ) return btErrorBkpt(SQLITE4_NOMEM); 
  memset(p, 0, nByte);

  p->btl.pEnv = pEnv;
  p->btl.pVfs = sqlite4BtEnvDefault();
  p->btl.iSafetyLevel = BT_DEFAULT_SAFETY;
  p->btl.nAutoCkpt = BT_DEFAULT_AUTOCKPT;
  p->btl.bRequestMultiProc = BT_DEFAULT_MULTIPROC;
  p->btl.nBlksz = BT_DEFAULT_BLKSZ;
  p->btl.nPgsz = BT_DEFAULT_PGSZ;
  p->nPageLimit = BT_DEFAULT_CACHESZ;
  *pp = p;
  return SQLITE4_OK;
}

static void btFreePage(BtPager *p, BtPage *pPg){
  if( pPg ){
    sqlite4_free(p->btl.pEnv, pPg->aData);
    sqlite4_free(p->btl.pEnv, pPg);
  }
}

static void btPurgeCache(BtPager *p){
  int i;
  assert( p->iTransactionLevel==0 );
  assert( p->nTotalRef==0 );

  for(i=0; i<p->hash.nHash; i++){
    BtPage *pPg;
    BtPage *pNext;
    for(pPg=p->hash.aHash[i]; pPg; pPg=pNext){
      pNext = pPg->pNextHash;
      btFreePage(p, pPg);
    }
  }
  btHashClear(p);

  p->pLruTail = 0;
  p->pLru = 0;
}

static int btCheckpoint(BtLock *pLock){
  BtPager *p = (BtPager*)pLock;
  if( p->pLog==0 ) return SQLITE4_BUSY;
  return sqlite4BtLogCheckpoint(p->pLog, 0);
}

static int btCleanup(BtLock *pLock){
  BtPager *p = (BtPager*)pLock;
  int rc = sqlite4BtLogClose(p->pLog, 1);
  p->pLog = 0;
  return rc;
}

static int btOpenSavepoints(BtPager *p, int iLevel){
  int rc = SQLITE4_OK;            /* Return code */
  int nReq = iLevel - 2;          /* Required number of savepoints */

  if( nReq>p->nSavepoint ){
    BtSavepoint *aNew;
    int nByte = (nReq * sizeof(BtSavepoint));

    aNew = sqlite4_realloc(p->btl.pEnv, p->aSavepoint, nByte);
    if( aNew ){
      int i;
      for(i=p->nSavepoint; i<nReq; i++){
        aNew[i].pSavepage = 0;
        aNew[i].iLevel = i+3;
        memcpy(&aNew[i].hdr, p->pHdr, sizeof(BtDbHdr));
      }
      p->aSavepoint = aNew;
      p->nSavepoint = nReq;
    }else{
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }
  }

  return rc;
}

#ifndef NDEBUG
static void btDebugCheckSavepagesInOrder(BtPage *pPg, int iMax){
  BtSavepage *p;
  int i = iMax;
  for(p=pPg->pSavepage; p; p=p->pNextSavepage){
    assert( p->iSavepoint<=i );
    i = p->iSavepoint-1;
  }
}
#else
# define btDebugCheckSavepagesInOrder(a,b)
#endif

/*
** If it has not already been added, add page pPg to the innermost
** savepoint.
*/
static int btAddToSavepoint(BtPager *p, BtPage *pPg){
  int rc = SQLITE4_OK;
  BtSavepage *pSavepage;
  int iLevel = p->iTransactionLevel;

  /* Assert that the linked list of BtSavepage objects is sorted in 
  ** descending order of level.  */
  btDebugCheckSavepagesInOrder(pPg, iLevel);

  if( pPg->pSavepage==0 || pPg->pSavepage->iSavepoint!=iLevel ){

    /* Allocate the new BtSavepage structure */
    pSavepage = sqlite4_malloc(p->btl.pEnv, sizeof(BtSavepage));
    if( pSavepage==0 ){
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }else{
      memset(pSavepage, 0, sizeof(BtSavepage));
    }

    /* Populate the new BtSavepage structure */
    if( rc==SQLITE4_OK && (1 || (pPg->flags & BT_PAGE_DIRTY)) ){
      pSavepage->aData = (u8*)sqlite4_malloc(p->btl.pEnv, p->pHdr->pgsz);
      if( pSavepage->aData==0 ){
        sqlite4_free(p->btl.pEnv, pSavepage);
        rc = btErrorBkpt(SQLITE4_NOMEM);
      }else{
        memcpy(pSavepage->aData, pPg->aData, p->pHdr->pgsz);
      }
    }

    /* Link the new BtSavepage structure into the pPg->pSavepage list */
    if( rc==SQLITE4_OK ){
      pSavepage->pPg = pPg;
      pSavepage->iSavepoint = iLevel;

      pSavepage->pNextSavepage = pPg->pSavepage;
      pPg->pSavepage = pSavepage;

      assert( p->aSavepoint[iLevel-3].iLevel==iLevel ); 
      pSavepage->pNext = p->aSavepoint[iLevel-3].pSavepage;
      p->aSavepoint[iLevel-3].pSavepage = pSavepage;
    }
  }

  return rc;
}


/*
** Close enough savepoints (and discard any associated rollback data) to 
** cause the number remaining open to be consistent with transaction
** level iLevel. If the bRollback parameter is true, then the data is
** used to restore page states before is discarded. 
**
** If parameter iLevel is 2 (or lower) this means close all open 
** savepoints.
*/
static int btCloseSavepoints(
  BtPager *p,                     /* Pager handle */
  int iLevel,                     /* New transaction level */
  int bRollback                   /* True to rollback pages */
){
  int nReq = MAX(0, iLevel - 2);

  if( nReq<=p->nSavepoint ){
    int i;
    for(i=p->nSavepoint-1; i>=nReq; i--){
      BtSavepoint *pSavepoint = &p->aSavepoint[i];
      BtSavepage *pSavepg;
      BtSavepage *pNext;

      /* If this is a rollback operation, restore the BtDbHdr object to the
      ** state it was in at the start of this savepoint.  */
      if( bRollback ){
        memcpy(p->pHdr, &pSavepoint->hdr, sizeof(BtDbHdr));
      }

      /* Loop through each of the BtSavepage objects associated with this
      ** savepoint. Detach them from the BtPage objects and free all
      ** allocated memory.  */
      for(pSavepg=pSavepoint->pSavepage; pSavepg; pSavepg=pNext){
        BtPage *pPg = pSavepg->pPg;
        pNext = pSavepg->pNext;

        assert( pSavepg==pPg->pSavepage );
        assert( pSavepg->iSavepoint==pSavepoint->iLevel );

        /* If bRollback is set, restore the page data */
        if( bRollback ){
          memcpy(pPg->aData, pSavepg->aData, p->pHdr->pgsz);
        }else{
          int iNextSaved = (
              pSavepg->pNextSavepage ? pSavepg->pNextSavepage->iSavepoint : 2
          );
          if( iLevel>iNextSaved ){
            assert( iLevel>=3 );
            assert( p->aSavepoint[iLevel-3].iLevel==iLevel ); 
            pSavepg->pNext = p->aSavepoint[iLevel-3].pSavepage;
            pSavepg->iSavepoint = iLevel;
            p->aSavepoint[iLevel-3].pSavepage = pSavepg;
            pSavepg = 0;
          }
        }

        if( pSavepg ){
          /* Detach the BtSavepage from its BtPage object */
          pPg->pSavepage = pSavepg->pNextSavepage;

          /* Free associated memory allocations */
          assert( pSavepg->aData ); /* temp */
          sqlite4_free(p->btl.pEnv, pSavepg->aData);
          sqlite4_free(p->btl.pEnv, pSavepg);
        }
      }

      pSavepoint->pSavepage = 0;
    }

    p->nSavepoint = nReq;
  }

  return SQLITE4_OK;
}


/*
** Close a pager database handle.
*/
SQLITE4_PRIVATE int sqlite4BtPagerClose(BtPager *p){
  int rc;

  if( p->btl.pFd ){
    sqlite4BtPagerRollback(p, 0);
  }

  rc = sqlite4BtLockDisconnect((BtLock*)p, btCheckpoint, btCleanup);
  p->iTransactionLevel = 0;
  btCloseSavepoints(p, 0, 0);
  btPurgeCache(p);
  sqlite4BtLogClose(p->pLog, 0);
  sqlite4_free(p->btl.pEnv, p->zFile);
  sqlite4_free(p->btl.pEnv, p->aSavepoint);
  sqlite4_free(p->btl.pEnv, p);
  return rc;
}

/*
** Return a pointer to the nExtra bytes of space allocated by PagerNew().
*/
SQLITE4_PRIVATE void *sqlite4BtPagerExtra(BtPager *p){
  return (void*)&p[1];
}

/*
** Open the logging module and run recovery on the database. This is 
** called during connection by the bt_lock module.
*/
static int btRecover(BtLock *pLock){
  BtPager *p = (BtPager*)pLock;
  int rc;
  rc = sqlite4BtLogOpen(p, 1, &p->pLog);
  return rc;
}

/*
** Attach a database file to a pager object.
**
** This function may only be called once for each BtPager object. If it
** fails, the BtPager is rendered unusable (and must be closed by the
** caller using BtPagerClose()).
**
** If successful, SQLITE4_OK is returned. Otherwise, an SQLite error code.
*/
SQLITE4_PRIVATE int sqlite4BtPagerOpen(BtPager *p, const char *zFilename){
  int rc;                         /* Return code */
  sqlite4_env *pEnv = p->btl.pEnv;
  bt_env *pVfs = p->btl.pVfs;

  assert( p->btl.pFd==0 && p->zFile==0 );

  rc = pVfs->xFullpath(pEnv, pVfs, zFilename, &p->zFile);
  if( rc==SQLITE4_OK ){
    p->nFile = strlen(p->zFile);
    rc = sqlite4BtLockConnect((BtLock*)p, btRecover);
    if( rc==SQLITE4_OK && p->pLog==0 ){
      rc = sqlite4BtLogOpen(p, 0, &p->pLog);
    }
  }

  if( rc!=SQLITE4_OK ){
    sqlite4BtLockDisconnect((BtLock*)p, btCheckpoint, btCleanup);
    sqlite4BtLogClose(p->pLog, 0);
    p->pLog = 0;
  }

  return rc;
}

/*
** Open a read-transaction.
*/
static int btOpenReadTransaction(BtPager *p){
  int rc;

  assert( p->iTransactionLevel==0 );
  assert( p->btl.pFd );
  assert( p->pHdr==0 );

  rc = sqlite4BtLogSnapshotOpen(p->pLog);

  if( rc==SQLITE4_OK ){
    /* If the read transaction was successfully opened, the transaction 
    ** level is now 1.  */
    p->iTransactionLevel = 1;
    p->pHdr = sqlite4BtLogDbhdr(p->pLog);
  }
  return rc;
}

static int btOpenWriteTransaction(BtPager *p){
  int rc;
  assert( p->iTransactionLevel==1 );
  assert( p->btl.pFd );

  rc = sqlite4BtLogSnapshotWrite(p->pLog);
  return rc;
}

static int btCloseReadTransaction(BtPager *p){
  int rc;
  assert( p->iTransactionLevel==0 );

  assert( p->pHdr );
  p->pHdr = 0;
  rc = sqlite4BtLogSnapshotClose(p->pLog);

  /* Purge the page cache. */
  assert( p->pDirty==0 );
  //btPurgeCache(p);

  if( rc==SQLITE4_OK && p->bDoAutoCkpt ){
    sqlite4BtLogCheckpoint(p->pLog, (p->btl.nAutoCkpt / 2));
  }
  p->bDoAutoCkpt = 0;

  return rc;
}

int btPagerDbhdrFlush(BtPager *p){
  int rc = SQLITE4_OK;
  if( p->bDirtyHdr ){
    rc = sqlite4BtLogDbhdrFlush(p->pLog);
    p->bDirtyHdr = 0;
  }
  return rc;
}

/*
** Commit the current write transaction to disk.
*/
static int btCommitTransaction(BtPager *p){
  int rc = SQLITE4_OK;
  int nLogsize;                   /* Number of frames in log after commit */
  BtPage *pPg;
  BtPage *pNext;
  assert( p->iTransactionLevel>=2 );

  rc = btPagerDbhdrFlush(p);
  btCloseSavepoints(p, 2, 0);

  for(pPg=p->pDirty; rc==SQLITE4_OK && pPg; pPg=pNext){
    int nPg;
    pNext = pPg->pNextDirty;
    nPg = ((pNext==0) ? p->pHdr->nPg : 0);
    rc = sqlite4BtLogWrite(p->pLog, pPg->pgno, pPg->aData, nPg);
    pPg->flags &= ~(BT_PAGE_DIRTY);
    pPg->pNextDirty = 0;
    if( pPg->nRef==0 ) btLruAdd(p, pPg);
  }
  p->pDirty = pPg;
  sqlite4BtLogSnapshotEndWrite(p->pLog);

  nLogsize = sqlite4BtLogSize(p->pLog);

  if( p->btl.nAutoCkpt && nLogsize>=p->btl.nAutoCkpt ){
    p->bDoAutoCkpt = 1;
  }
  if( p->xLogsize ){
    p->xLogsize(p->pLogsizeCtx, nLogsize);
  }

  return rc;
}

static int btLoadPageData(BtPager *p, BtPage *pPg){
  int rc;                         /* Return code */

  /* Try to load data from the logging module. If SQLITE4_OK is returned,
  ** data was loaded successfully. If SQLITE4_NOTFOUND, the required page
  ** is not present in the log and should be loaded from the database
  ** file. Any other error code is returned to the caller.  */
  rc = sqlite4BtLogRead(p->pLog, pPg->pgno, pPg->aData);

  /* If necessary, load data from the database file. */
  if( rc==SQLITE4_NOTFOUND ){
    i64 iOff = (i64)p->pHdr->pgsz * (i64)(pPg->pgno-1);
    rc = p->btl.pVfs->xRead(p->btl.pFd, iOff, pPg->aData, p->pHdr->pgsz);
  }

  return rc;
}

static int btAllocatePage(BtPager *p, BtPage **ppPg){
  int rc = SQLITE4_OK;            /* Return code */
  BtPage *pRet;

  if( p->hash.nEntry>=p->nPageLimit && p->pLru ){
    BtPage **pp;
    int h;

    /* Remove the page from the head of the LRU list. */
    pRet = p->pLru;
    assert( (pRet->pNextLru==0)==(pRet==p->pLruTail) );
    p->pLru = pRet->pNextLru;
    if( p->pLru==0 ){
      p->pLruTail = 0;
    }else{
      p->pLru->pPrevLru = 0;
    }

    /* Remove the page from the hash table. */
    btHashRemove(p, pRet);

    assert( pRet->pPrevLru==0 );
    assert( pRet->nRef==0 );
    assert( pRet->pSavepage==0 );
    pRet->flags = 0;
    pRet->pNextHash = 0;
    pRet->pNextDirty = 0;
    pRet->pNextLru = 0;
  }else{
    u8 *aData = (u8*)sqlite4_malloc(p->btl.pEnv, p->pHdr->pgsz);
    pRet = (BtPage*)sqlite4_malloc(p->btl.pEnv, sizeof(BtPage));

    if( pRet && aData ){
      memset(pRet, 0, sizeof(BtPage));
      pRet->aData = aData;
      pRet->pPager = p;
    }else{
      sqlite4_free(p->btl.pEnv, pRet);
      sqlite4_free(p->btl.pEnv, aData);
      rc = btErrorBkpt(SQLITE4_NOMEM);
      pRet = 0;
    }
  }

  *ppPg = pRet;
  return rc;
}

/*
** Roll back, but do not close, the current write transaction. 
*/
static int btRollbackTransaction(BtPager *p){
  int rc = SQLITE4_OK;
  BtPage *pPg;
  BtPage *pNext;

  assert( p->iTransactionLevel>=2 );
  btCloseSavepoints(p, 2, 0);

  /* Loop through all dirty pages in memory. Discard those with nRef==0.
  ** Reload data from disk for any others.  */
  for(pPg=p->pDirty; pPg; pPg=pNext){
    pNext = pPg->pNextDirty;
    pPg->flags &= ~(BT_PAGE_DIRTY);
    pPg->pNextDirty = 0;
    if( pPg->nRef==0 ){
      btHashRemove(p, pPg);
      btFreePage(p, pPg);
    }else if( rc==SQLITE4_OK && (pPg->pgno<=p->pHdr->nPg) ){
      rc = btLoadPageData(p, pPg);
    }
  }
  p->pDirty = 0;
  sqlite4BtLogReloadDbHdr(p->pLog);

  return rc;
}

/*
** Transactions. These methods are more or less the same as their 
** counterparts in bt.h.
*/
SQLITE4_PRIVATE int sqlite4BtPagerBegin(BtPager *p, int iLevel){
  int rc = SQLITE4_OK;
  assert( p->btl.pFd );

  if( p->iTransactionLevel<iLevel ){
    /* Open a read transaction if one is not already open */
    if( p->iTransactionLevel==0 ){
      rc = btOpenReadTransaction(p);
    }

    /* Open a write transaction if one is required */
    if( rc==SQLITE4_OK && p->iTransactionLevel<2 && iLevel>=2 ){
      rc = btOpenWriteTransaction(p);
    }

    /* Open any required savepoints */
    if( rc==SQLITE4_OK ){
      rc = btOpenSavepoints(p, iLevel);
    }

    /* If nothing has gone wrong, update BtPager.iTransactionLevel */
    if( rc==SQLITE4_OK ){
      assert( p->iTransactionLevel>=1 && iLevel>=p->iTransactionLevel );
      p->iTransactionLevel = iLevel;
    }
  }

  return rc;
}

/*
** The sqlite4_kvstore.xCommit method.
*/
SQLITE4_PRIVATE int sqlite4BtPagerCommit(BtPager *p, int iLevel){
  int rc = SQLITE4_OK;

  assert( p->btl.pFd );
  if( p->iTransactionLevel>=iLevel ){
    btCloseSavepoints(p, iLevel, 0);

    if( p->iTransactionLevel>=2 && iLevel<2 ){
      /* Commit the main write transaction. */
      rc = btCommitTransaction(p);
    }
    p->iTransactionLevel = iLevel;

    if( iLevel==0 ){
      int rc2 = btCloseReadTransaction(p);
      if( rc==SQLITE4_OK ) rc = rc2;
    }
  }
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtPagerRawWrite(BtPager *p, u32 pgno, u8 *aBuf){
  int pgsz = p->pHdr->pgsz;
  i64 iOff = (i64)pgsz * (i64)(pgno-1);
  return p->btl.pVfs->xWrite(p->btl.pFd, iOff, aBuf, pgsz);
}

SQLITE4_PRIVATE int sqlite4BtPagerRollback(BtPager *p, int iLevel){
  int rc = SQLITE4_OK;

  assert( p->btl.pFd );
  if( p->iTransactionLevel>=iLevel ){

    /* If a write transaction is open and the requested level is 2 or
    ** lower, rollback the outermost write transaction. If the requested
    ** level is less than 2, also drop the WRITER lock.  */
    if( p->iTransactionLevel>=2 ){
      if( iLevel<=2 ){
        rc = btRollbackTransaction(p);
        if( iLevel<2 ) sqlite4BtLogSnapshotEndWrite(p->pLog);
      }else{
        rc = btCloseSavepoints(p, iLevel-1, 1);
        p->nSavepoint++;
      }
    }

    if( p->iTransactionLevel>iLevel ){
      p->iTransactionLevel = iLevel;
      if( iLevel==0 ){
        int rc2 = btCloseReadTransaction(p);
        if( rc==SQLITE4_OK ) rc = rc2;
      }
    }
  }

  return rc;
}

SQLITE4_PRIVATE int sqlite4BtPagerRevert(BtPager *p, int iLevel){
  int rc;
  assert( 0 );                    /* TODO: Fix this */

  assert( p->btl.pFd );
  rc = sqlite4BtPagerRollback(p, iLevel);
  if( rc==SQLITE4_OK && iLevel>=2 && p->iTransactionLevel==iLevel ){
    /* Rollback (but do not close) transaction iLevel */
  }
  return rc;
}

/*
** Return the current transaction level.
*/
SQLITE4_PRIVATE int sqlite4BtPagerTransactionLevel(BtPager *p){
  return p->iTransactionLevel;
}

/*
** Query for the database page size. Requires an open read transaction.
*/
SQLITE4_PRIVATE int sqlite4BtPagerPagesize(BtPager *p){
  /* assert( p->iTransactionLevel>=1 && p->btl.pFd ); */
  return (int)p->pHdr->pgsz;
}

/* 
** Query for the root page number. Requires an open read transaction.
*/
SQLITE4_PRIVATE BtDbHdr *sqlite4BtPagerDbhdr(BtPager *p){
  return p->pHdr;
}

SQLITE4_PRIVATE void sqlite4BtPagerDbhdrDirty(BtPager *p){
  p->bDirtyHdr = 1;
}

SQLITE4_PRIVATE void sqlite4BtPagerSetDbhdr(BtPager *p, BtDbHdr *pHdr){
  assert( p->pHdr==0 || pHdr==0 );
  p->pHdr = pHdr;
}

/*
** Request a reference to page pgno of the database.
*/
SQLITE4_PRIVATE int sqlite4BtPageGet(BtPager *p, u32 pgno, BtPage **ppPg){
  int rc = SQLITE4_OK;            /* Return code */
  BtPage *pRet;                   /* Returned page handle */

  if( p->btl.aUsed ){
    p->btl.aUsed[pgno]++;
  }

  /* Search the cache for an existing page. */
  pRet = btHashSearch(p, pgno);

  /* If the page is not in the cache, load it from disk */
  if( pRet==0 ){
    rc = btAllocatePage(p, &pRet);
    if( rc==SQLITE4_OK ){
      pRet->pgno = pgno;
      if( pgno<=p->pHdr->nPg ){
        rc = btLoadPageData(p, pRet);
      }else{
        assert( p->iTransactionLevel>=2 );
        memset(pRet->aData, 0, p->pHdr->pgsz);
      }

      if( rc==SQLITE4_OK ){
        rc = btHashAdd(p, pRet);
      }

      if( rc!=SQLITE4_OK ){
        btFreePage(p, pRet);
        pRet = 0;
      }else{
        sqlite4BtDebugReadPage(&p->btl, pgno, pRet->aData, p->pHdr->pgsz);
      }
    }
  }else if( pRet->nRef==0 && (pRet->flags & BT_PAGE_DIRTY)==0 ){
    btLruRemove(p, pRet);
  }

  assert( (pRet!=0)==(rc==SQLITE4_OK) );
  if( rc==SQLITE4_OK ){
    p->nTotalRef++;
    pRet->nRef++;
  }
  *ppPg = pRet;
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtPageWrite(BtPage *pPg){
  int rc = SQLITE4_OK;
  BtPager *p = pPg->pPager;

  /* If there are savepoints open, add this page to the innermost savepoint */
  if( p->nSavepoint>0 ){
    rc = btAddToSavepoint(p, pPg);
  }

  if( (pPg->flags & BT_PAGE_DIRTY)==0 ){
    pPg->flags |= BT_PAGE_DIRTY;
    pPg->pNextDirty = pPg->pPager->pDirty;
    pPg->pPager->pDirty = pPg;
  }
  return rc;
}

/*
** Add page pgno to the free-page list. If argument pPg is not NULL, then
** it is a reference to page pgno.
*/
static int btFreelistAdd(
  BtPager *p,                     /* Pager object */
  int bBlock,                     /* True if pgno is actually a block number */
  u32 pgno
){
  BtDbHdr *pHdr = sqlite4BtLogDbhdr(p->pLog);
  int rc = SQLITE4_OK;
  int bDone = 0;
  u32 *piFirst = (bBlock ? &pHdr->iFreeBlk : &pHdr->iFreePg);

  /* Check if there is space on the first free-list trunk page. If so,
  ** add the new entry to it. Set variable bDone to indicate that the
  ** page has already been added to the free-list. */
  if( *piFirst ){
    BtPage *pTrunk;
    rc = sqlite4BtPageGet(p, *piFirst, &pTrunk);
    if( rc==SQLITE4_OK ){
      const int nMax = ((pHdr->pgsz - 8) / 4);
      u8 *aData = pTrunk->aData;
      int nFree = (int)sqlite4BtGetU32(aData);

      if( nFree<nMax ){
        rc = sqlite4BtPageWrite(pTrunk);
        if( rc==SQLITE4_OK ){
          sqlite4BtPutU32(&pTrunk->aData[8 + nFree*4], pgno);
          sqlite4BtPutU32(pTrunk->aData, nFree+1);
          bDone = 1;
          sqlite4BtDebugPageFree((BtLock*)p, bBlock, "free-list-leaf", pgno);
        }
      }
      sqlite4BtPageRelease(pTrunk);
    } 
  }

  /* If no error has occurred but the page number has not yet been added 
  ** to the free-list, this page becomes the first trunk in the list.  */
  if( rc==SQLITE4_OK && bDone==0 ){
    BtPage *pTrunk = 0;

    if( bBlock ){
      rc = sqlite4BtPageAllocate(p, &pTrunk);
    }else{
      rc = sqlite4BtPageGet(p, pgno, &pTrunk);
      if( rc==SQLITE4_OK ) rc = sqlite4BtPageWrite(pTrunk);
    }
    if( rc==SQLITE4_OK ){
      sqlite4BtPagerDbhdrDirty(p);
      sqlite4BtPutU32(&pTrunk->aData[0], 0);
      sqlite4BtPutU32(&pTrunk->aData[4], *piFirst);
      *piFirst = pTrunk->pgno;
      sqlite4BtDebugPageFree((BtLock*)p, 0, "free-list-trunk", pTrunk->pgno);
    }
    sqlite4BtPageRelease(pTrunk);
    if( rc==SQLITE4_OK && bBlock ){
      rc = btFreelistAdd(p, 1, pgno);
    }
  }

  return rc;
}

/*
** Attempt to allocate a page from the free-list.
*/
static int btFreelistAlloc(
  BtPager *p,                     /* Pager object */
  int bBlock,                     /* True to allocate a block (not a page) */
  u32 *pPgno                      /* OUT: Page or block number */
){
  BtDbHdr *pHdr = sqlite4BtLogDbhdr(p->pLog);
  int rc = SQLITE4_OK;
  u32 *piFirst = (bBlock ? &pHdr->iFreeBlk : &pHdr->iFreePg);
  u32 pgno = 0;

  assert( *pPgno==0 );
  while( *piFirst && pgno==0 && rc==SQLITE4_OK ){
    BtPage *pTrunk = 0;
    rc = sqlite4BtPageGet(p, *piFirst, &pTrunk);
    if( rc==SQLITE4_OK ){
      rc = sqlite4BtPageWrite(pTrunk);
    }
    if( rc==SQLITE4_OK ){
      u8 *aData = pTrunk->aData;
      u32 nFree = sqlite4BtGetU32(aData);
      if( nFree>0 ){
        pgno = sqlite4BtGetU32(&aData[8 + 4*(nFree-1)]);
        sqlite4BtPutU32(aData, nFree-1);
        sqlite4BtDebugPageAlloc((BtLock*)p, "free-list", pgno);
      }else{
        u32 iNext = sqlite4BtGetU32(&aData[4]);
        sqlite4BtPagerDbhdrDirty(p);
        
        if( bBlock ){
          rc = btFreelistAdd(p, 0, *piFirst);
        }else{
          pgno = *piFirst;
          sqlite4BtDebugPageAlloc((BtLock*)p, "free-list-trunk", pgno);
        }
        *piFirst = iNext;
      }
    }

    sqlite4BtPageRelease(pTrunk);
  }

  *pPgno = pgno;
  return rc;
}

/*
** Decrement the refcount on page pPg. Also, indicate that page pPg is
** no longer in use.
*/
SQLITE4_PRIVATE int sqlite4BtPageTrim(BtPage *pPg){
  int rc;                         /* Return code */
  rc = btFreelistAdd(pPg->pPager, 0, pPg->pgno);
  sqlite4BtPageRelease(pPg);
  return rc;
}

/*
** Page number pgno is no longer in use.
*/
SQLITE4_PRIVATE int sqlite4BtPageTrimPgno(BtPager *pPager, u32 pgno){
  return btFreelistAdd(pPager, 0, pgno);
}

SQLITE4_PRIVATE int sqlite4BtPageRelease(BtPage *pPg){
  if( pPg ){
    BtPager *pPager = pPg->pPager;

    assert( pPg->nRef>=1 );
    pPg->nRef--;
    pPg->pPager->nTotalRef--;

    /* If the refcount is now zero and the page is not dirty, add it to
    ** the LRU list.  */
    if( pPg->nRef==0 && (pPg->flags & BT_PAGE_DIRTY)==0 ){
      btLruAdd(pPager, pPg);
    }
  }
  return SQLITE4_OK;
}

SQLITE4_PRIVATE void sqlite4BtPageReference(BtPage *pPg){
  assert( pPg->nRef>=1 );
  pPg->nRef++;
  pPg->pPager->nTotalRef++;
}

/*
** Allocate a new database page and return a writable reference to it.
*/
SQLITE4_PRIVATE int sqlite4BtPageAllocate(BtPager *p, BtPage **ppPg){
  BtPage *pPg = 0;
  int rc;
  u32 pgno = 0;

  /* Find the page number of the new page. There are two ways a page may
  ** be allocated - from the free-list or by appending it to the end of
  ** the database file. */ 
  rc = btFreelistAlloc(p, 0, &pgno);
  if( rc==SQLITE4_OK && pgno==0 ){
    pgno = p->pHdr->nPg+1;
    sqlite4BtDebugPageAlloc((BtLock*)p, "end-of-file", pgno);
  }

  rc = sqlite4BtPageGet(p, pgno, &pPg);
  if( rc==SQLITE4_OK ){
    rc = sqlite4BtPageWrite(pPg);
    if( rc!=SQLITE4_OK ){
      sqlite4BtPageRelease(pPg);
      pPg = 0;
    }else{
      p->pHdr->nPg = MAX(p->pHdr->nPg, pgno);
    }
  }

#ifdef BT_STDERR_DEBUG
  fprintf(stderr, "allocated page %d\n", pgno);
#endif

  *ppPg = pPg;
  return rc;
}

SQLITE4_PRIVATE int sqlite4BtBlockAllocate(BtPager *p, int nBlk, u32 *aiBlk){
  int rc = SQLITE4_OK;
  BtDbHdr *pHdr = p->pHdr;
  int nPgPerBlk = (pHdr->blksz / pHdr->pgsz);
  int i;

  for(i=0; rc==SQLITE4_OK && i<nBlk; i++){
    u32 iBlk = 0;
    u32 iRoot;
    u32 iFree;

    rc = btFreelistAlloc(p, 1, &iBlk);
    if( rc==SQLITE4_OK && iBlk==0 ){

      /* Figure out the next block in the file. And its root (first) page. */
      iBlk = 1 + (pHdr->nPg + nPgPerBlk - 1) / nPgPerBlk;
      iRoot = (iBlk-1) * nPgPerBlk + 1;
      assert( iBlk>0 );

      for(iFree = pHdr->nPg+1; rc==SQLITE4_OK && iFree<iRoot; iFree++){
        rc = sqlite4BtPageTrimPgno(p, iFree);
      }
      pHdr->nPg = iBlk * nPgPerBlk;
    }

    aiBlk[i] = iBlk;
  }

  return rc;
}

/*
** Trim a block.
*/
SQLITE4_PRIVATE int sqlite4BtBlockTrim(BtPager *p, u32 iBlk){
  return btFreelistAdd(p, 1, iBlk);
}

/*
** Return the current page number of the argument page reference.
*/
SQLITE4_PRIVATE u32 sqlite4BtPagePgno(BtPage *pPg){
  return pPg->pgno;
}

/*
** Return a pointer to the data buffer associated with page pPg.
*/
SQLITE4_PRIVATE void *sqlite4BtPageData(BtPage *pPg){
  return pPg->aData;
}

/* 
** Read the schema cookie value. Requires an open read-transaction.
*/
SQLITE4_PRIVATE int sqlite4BtPagerSetCookie(BtPager *p, u32 iVal){
  assert( p->iTransactionLevel>=2 );
  return sqlite4BtLogSetCookie(p->pLog, iVal);
}

/* 
** Set the schema cookie value. Requires an open write-transaction.
*/
SQLITE4_PRIVATE int sqlite4BtPagerGetCookie(BtPager *p, u32 *piVal){
  assert( p->iTransactionLevel>=1 );
  *piVal = p->pHdr->iCookie;
  return SQLITE4_OK;
}

SQLITE4_PRIVATE const char *sqlite4BtPagerFilename(BtPager *p, int ePagerfile){
  const char *zTail;

  /* If the database file has not yet been opened, return a null pointer. */
  if( p->zFile==0 ) return 0;

  switch( ePagerfile ){
    case BT_PAGERFILE_DATABASE:
      zTail = "";
      break;

    case BT_PAGERFILE_LOG:
      zTail = "-wal";
      break;

    default:
      assert( ePagerfile==BT_PAGERFILE_SHM );
      zTail = "-shm";
      break;
  }
  memcpy(&p->zFile[p->nFile], zTail, strlen(zTail)+1);
  return p->zFile;
}

SQLITE4_PRIVATE bt_env *sqlite4BtPagerGetEnv(BtPager *p){
  return p->btl.pVfs;
}
SQLITE4_PRIVATE void sqlite4BtPagerSetEnv(BtPager *p, bt_env *pVfs){
  p->btl.pVfs = pVfs;
}

SQLITE4_PRIVATE void sqlite4BtPagerSetSafety(BtPager *pPager, int *piVal){
  int iVal = *piVal;
  if( iVal>=0 && iVal<=2 ){
    pPager->btl.iSafetyLevel = iVal;
  }
  *piVal = pPager->btl.iSafetyLevel;
}

SQLITE4_PRIVATE void sqlite4BtPagerSetAutockpt(BtPager *pPager, int *piVal){
  int iVal = *piVal;
  if( iVal>=0 ){
    pPager->btl.nAutoCkpt = iVal;
  }
  *piVal = pPager->btl.nAutoCkpt;
}

SQLITE4_PRIVATE void sqlite4BtPagerLogsize(BtPager *pPager, int *pnFrame){
  *pnFrame = sqlite4BtLogSize(pPager->pLog);
}

SQLITE4_PRIVATE void sqlite4BtPagerMultiproc(BtPager *pPager, int *piVal){
  if( *piVal==0 || *piVal==1 ){
    pPager->btl.bRequestMultiProc = *piVal;
  }
  *piVal = pPager->btl.bRequestMultiProc;
}

SQLITE4_PRIVATE void sqlite4BtPagerLogsizeCb(BtPager *pPager, bt_logsizecb *p){
  pPager->xLogsize = p->xLogsize;
  pPager->pLogsizeCtx = p->pCtx;
}

SQLITE4_PRIVATE int sqlite4BtPagerCheckpoint(BtPager *pPager, bt_checkpoint *pCkpt){
  int rc;
  rc = sqlite4BtLogCheckpoint(pPager->pLog, pCkpt->nFrameBuffer);
  return rc;
}

/*
** It is guaranteed that at least a read-transaction is open when
** this function is called. It appends a text representation of the
** current database header (BtDbHdr) object to the buffer passed as
** the second argument.
**
** An SQLite4 error code is returned if an error (i.e. OOM) occurs,
** or SQLITE4_OK otherwise.
*/
SQLITE4_PRIVATE int sqlite4BtPagerHdrdump(BtPager *pPager, sqlite4_buffer *pBuf){
  BtDbHdr *pHdr = pPager->pHdr;
  int rc = SQLITE4_OK;

  sqlite4BtBufAppendf(pBuf, 
      "pgsz=%d blksz=%d nPg=%d"
      " iRoot=%d iMRoot=%d iSRoot=%d"
      " iSubBlock=%d nSubPg=%d"
      " iCookie=%d iFreePg=%d iFreeBlk=%d",
      pHdr->pgsz, pHdr->blksz, pHdr->nPg, 
      pHdr->iRoot, pHdr->iMRoot, pHdr->iSRoot,
      pHdr->iSubBlock, pHdr->nSubPg,
      pHdr->iCookie, pHdr->iFreePg, pHdr->iFreeBlk
  );

  return rc;
}

#ifndef NDEBUG
SQLITE4_PRIVATE int sqlite4BtPagerRefcount(BtPager *p){
  return p->nTotalRef;
}
#endif


/************** End of bt_pager.c ********************************************/
/************** Begin file bt_unix.c *****************************************/
/*
** 2011-12-03
**
** 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.
**
*************************************************************************
**
** Unix-specific run-time environment implementation for bt.
*/
#if defined(__GNUC__) || defined(__TINYC__)
/* workaround for ftruncate() visibility on gcc. */
# ifndef _XOPEN_SOURCE
#  define _XOPEN_SOURCE 500
# endif
#endif

/* #include <unistd.h> */
/* #include <sys/types.h> */

/* #include <sys/stat.h> */
/* #include <fcntl.h> */
/* #include <assert.h> */
/* #include <string.h> */

/* #include <stdlib.h> */
/* #include <stdarg.h> */
/* #include <stdio.h> */
/* #include <ctype.h> */

/* #include <unistd.h> */
/* #include <errno.h> */

/* #include <sys/mman.h> */

/* There is no fdatasync() call on Android */
#ifdef __ANDROID__
# define fdatasync(x) fsync(x)
#endif

/*
** An open file is an instance of the following object
*/
typedef struct BtPosixFile BtPosixFile;
struct BtPosixFile {
  sqlite4_env *pSqlEnv;
  bt_env *pEnv;                   /* The run-time environment */
  const char *zName;              /* Full path to file */
  int fd;                         /* The open file descriptor */
  int shmfd;                      /* Shared memory file-descriptor */
  int nShm;                       /* Number of entries in array apShm[] */
  void **apShm;                   /* Array of 32K shared memory segments */
};

static char *btPosixShmFile(BtPosixFile *p){
  char *zShm;
  int nName = strlen(p->zName);
  zShm = (char*)sqlite4_malloc(p->pSqlEnv, nName+4+1);
  if( zShm ){
    memcpy(zShm, p->zName, nName);
    memcpy(&zShm[nName], "-shm", 5);
  }
  return zShm;
}

static int btPosixOsOpen(
  sqlite4_env *pSqlEnv,
  bt_env *pEnv,
  const char *zFile,
  int flags,
  bt_file **ppFile
){
  int rc = SQLITE4_OK;
  BtPosixFile *p;

  p = (BtPosixFile*)sqlite4_malloc(pSqlEnv, sizeof(BtPosixFile));
  if( p==0 ){
    rc = btErrorBkpt(SQLITE4_NOMEM);
  }else{
    int bReadonly = (flags & BT_OPEN_READONLY);
    int oflags = (bReadonly ? O_RDONLY : (O_RDWR|O_CREAT));
    memset(p, 0, sizeof(BtPosixFile));
    p->zName = zFile;
    p->pEnv = pEnv;
    p->pSqlEnv = pSqlEnv;
    p->fd = open(zFile, oflags, 0644);
    if( p->fd<0 ){
      sqlite4_free(pSqlEnv, p);
      p = 0;
      rc = btErrorBkpt(SQLITE4_IOERR);
    }
  }

  *ppFile = (bt_file*)p;
  return rc;
}

static int btPosixOsSize(bt_file *pFile, i64 *pnByte){
  int rc = SQLITE4_OK;
  BtPosixFile *p = (BtPosixFile *)pFile;
  struct stat sBuf;

  if( fstat(p->fd, &sBuf)!=0 ){
    rc = SQLITE4_IOERR_FSTAT;
  }else{
    *pnByte = sBuf.st_size;
  }

  return rc;
}

static int btPosixOsWrite(
  bt_file *pFile,                 /* File to write to */
  i64 iOff,                       /* Offset to write to */
  void *pData,                    /* Write data from this buffer */
  int nData                       /* Bytes of data to write */
){
  int rc = SQLITE4_OK;
  BtPosixFile *p = (BtPosixFile *)pFile;
  off_t offset;

  offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
  if( offset!=iOff ){
    rc = btErrorBkpt(SQLITE4_IOERR);
  }else{
    ssize_t prc = write(p->fd, pData, (size_t)nData);
    if( prc<0 ) rc = btErrorBkpt(SQLITE4_IOERR);
  }

  return rc;
}

static int btPosixOsTruncate(
  bt_file *pFile,                /* File to write to */
  i64 nSize                      /* Size to truncate file to */
){
  BtPosixFile *p = (BtPosixFile *)pFile;
  int rc = SQLITE4_OK;                /* Return code */
  int prc;                        /* Posix Return Code */
  struct stat sStat;              /* Result of fstat() invocation */
  
  prc = fstat(p->fd, &sStat);
  if( prc==0 && sStat.st_size>nSize ){
    prc = ftruncate(p->fd, (off_t)nSize);
  }
  if( prc<0 ) rc = btErrorBkpt(SQLITE4_IOERR);

  return rc;
}

static int btPosixOsRead(
  bt_file *pFile,                /* File to read from */
  i64 iOff,                      /* Offset to read from */
  void *pData,                    /* Read data into this buffer */
  int nData                       /* Bytes of data to read */
){
  int rc = SQLITE4_OK;
  BtPosixFile *p = (BtPosixFile *)pFile;
  off_t offset;

  offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
  if( offset!=iOff ){
    rc = btErrorBkpt(SQLITE4_IOERR);
  }else{
    ssize_t prc = read(p->fd, pData, (size_t)nData);
    if( prc<0 ){ 
      rc = btErrorBkpt(SQLITE4_IOERR);
    }else if( prc<nData ){
      memset(&((u8 *)pData)[prc], 0, nData - prc);
    }
  }

  return rc;
}

static int btPosixOsSync(bt_file *pFile){
  int rc = SQLITE4_OK;
#ifndef SQLITE_NO_SYNC
  BtPosixFile *p = (BtPosixFile *)pFile;
  int prc = 0;

#if 0
  if( p->pMap ){
    prc = msync(p->pMap, p->nMap, MS_SYNC);
  }
#endif
  prc = fdatasync(p->fd);
  if( prc<0 ) rc = btErrorBkpt(SQLITE4_IOERR);
#else
  (void)pFile;
#endif

  return rc;
}

static int btPosixOsSectorSize(bt_file *pFile){
  return 512;
}

static int btPosixOsFullpath(
  sqlite4_env *pSqlEnv,
  bt_env *pEnv,
  const char *zName,
  char **pzOut
){
  int rc = SQLITE4_OK;
  char *zOut = 0;
  char *zCwd = 0;
  int nCwd = 0;

  if( zName[0]!='/' ){
    int nTmp = 512;
    char *zTmp = (char*)sqlite4_malloc(pSqlEnv, nTmp);
    while( zTmp ){
      zCwd = getcwd(zTmp, nTmp);
      if( zCwd || errno!=ERANGE ) break;
      sqlite4_free(pSqlEnv, zTmp);
      nTmp = nTmp*2;
      zTmp = sqlite4_malloc(pSqlEnv, nTmp);
    }
    if( zTmp==0 ){
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }else if( zCwd==0 ){
      rc = btErrorBkpt(SQLITE4_IOERR);
    }else{
      assert( zCwd==zTmp );
      nCwd = strlen(zCwd);
    }
  }

  if( rc==SQLITE4_OK ){
    int nReq = nCwd + 1 + strlen(zName) + 1 + 4;
    zOut = sqlite4_malloc(pSqlEnv, nReq);
    if( zOut ){
      int nName = strlen(zName);
      if( nCwd ){
        memcpy(zOut, zCwd, nCwd);
        zOut[nCwd] = '/';
        memcpy(&zOut[nCwd+1], zName, nName+1);
      }else{
        memcpy(zOut, zName, nName+1);
      }
    }else{
      rc = btErrorBkpt(SQLITE4_NOMEM);
    }
  }

  sqlite4_free(pSqlEnv, zCwd);
  *pzOut = zOut;
  return rc;
}

static int btPosixOsUnlink(sqlite4_env *pEnv, bt_env *pVfs, const char *zFile){
  int prc = unlink(zFile);
  return prc ? btErrorBkpt(SQLITE4_IOERR) : SQLITE4_OK;
}

#define btPosixLockToByte(iLock) (100 + (iLock))

int btPosixOsLock(bt_file *pFile, int iLock, int eType){
  int rc = SQLITE4_OK;
  BtPosixFile *p = (BtPosixFile *)pFile;
  static const short aType[3] = { F_UNLCK, F_RDLCK, F_WRLCK };
  struct flock lock;

  assert( aType[BT_LOCK_UNLOCK]==F_UNLCK );
  assert( aType[BT_LOCK_SHARED]==F_RDLCK );
  assert( aType[BT_LOCK_EXCL]==F_WRLCK );
  assert( eType>=0 && eType<(sizeof(aType)/sizeof(aType[0])) );
  assert( iLock>=0 && iLock<=32 );

  memset(&lock, 0, sizeof(lock));
  lock.l_whence = SEEK_SET;
  lock.l_len = 1;
  lock.l_type = aType[eType];
  lock.l_start = btPosixLockToByte(iLock);

  if( fcntl(p->fd, F_SETLK, &lock) ){
    int e = errno;
    if( e==EACCES || e==EAGAIN ){
      rc = SQLITE4_BUSY;
    }else{
      rc = btErrorBkpt(SQLITE4_IOERR);
    }
  }

  return rc;
}

int btPosixOsTestLock(bt_file *pFile, int iLock, int nLock, int eType){
  int rc = SQLITE4_OK;
  BtPosixFile *p = (BtPosixFile *)pFile;
  static const short aType[3] = { 0, F_RDLCK, F_WRLCK };
  struct flock lock;

  assert( eType==BT_LOCK_SHARED || eType==BT_LOCK_EXCL );
  assert( aType[BT_LOCK_SHARED]==F_RDLCK );
  assert( aType[BT_LOCK_EXCL]==F_WRLCK );
  assert( eType>=0 && eType<(sizeof(aType)/sizeof(aType[0])) );
  assert( iLock>=0 && iLock<=32 );

  memset(&lock, 0, sizeof(lock));
  lock.l_whence = SEEK_SET;
  lock.l_len = nLock;
  lock.l_type = aType[eType];
  lock.l_start = btPosixLockToByte(iLock);

  if( fcntl(p->fd, F_GETLK, &lock) ){
    rc = btErrorBkpt(SQLITE4_IOERR);
  }else if( lock.l_type!=F_UNLCK ){
    rc = SQLITE4_BUSY;
  }

  return rc;
}

int btPosixOsShmMap(bt_file *pFile, int iChunk, int sz, void **ppShm){
  BtPosixFile *p = (BtPosixFile *)pFile;

  /* If the shared-memory file has not been opened, open it now. */
  if( p->shmfd<=0 ){
    char *zShm = btPosixShmFile(p);
    if( !zShm ) return btErrorBkpt(SQLITE4_NOMEM);
    p->shmfd = open(zShm, O_RDWR|O_CREAT, 0644);
    sqlite4_free(p->pSqlEnv, zShm);
    if( p->shmfd<0 ){ 
      return btErrorBkpt(SQLITE4_IOERR);
    }
  }

  if( ppShm==0 ){
    assert( p->nShm==0 );
    if( p->nShm ) return btErrorBkpt(SQLITE4_MISUSE);
    if( ftruncate(p->shmfd, 0) ){
      return btErrorBkpt(SQLITE4_IOERR);
    }
  }else{

    *ppShm = 0;
    assert( sz==BT_SHM_CHUNK_SIZE );
    if( iChunk>=p->nShm ){
      int i;
      void **apNew;
      int nNew = iChunk+1;
      off_t nReq = nNew * BT_SHM_CHUNK_SIZE;
      struct stat sStat;

      /* If the shared-memory file is not large enough to contain the 
       ** requested chunk, cause it to grow.  */
      if( fstat(p->shmfd, &sStat) ){
        return btErrorBkpt(SQLITE4_IOERR);
      }
      if( sStat.st_size<nReq ){
        if( ftruncate(p->shmfd, nReq) ){
          return btErrorBkpt(SQLITE4_IOERR);
        }
      }

      apNew = (void**)sqlite4_realloc(p->pSqlEnv, p->apShm, sizeof(void*)*nNew);
      if( !apNew ) return btErrorBkpt(SQLITE4_NOMEM);
      for(i=p->nShm; i<nNew; i++){
        apNew[i] = 0;
      }
      p->apShm = apNew;
      p->nShm = nNew;
    }

    if( p->apShm[iChunk]==0 ){
      p->apShm[iChunk] = mmap(0, BT_SHM_CHUNK_SIZE, 
          PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*BT_SHM_CHUNK_SIZE
      );
      if( p->apShm[iChunk]==0 ) return btErrorBkpt(SQLITE4_IOERR);
    }

    *ppShm = p->apShm[iChunk];
  }
  return SQLITE4_OK;
}

void btPosixOsShmBarrier(bt_file *pFile){
}

int btPosixOsShmUnmap(bt_file *pFile, int bDelete){
  BtPosixFile *p = (BtPosixFile *)pFile;
  if( p->shmfd>0 ){
    int i;
    for(i=0; i<p->nShm; i++){
      if( p->apShm[i] ){
        munmap(p->apShm[i], BT_SHM_CHUNK_SIZE);
        p->apShm[i] = 0;
      }
    }
    close(p->shmfd);
    p->shmfd = 0;
    if( bDelete ){
      char *zShm = btPosixShmFile(p);
      if( zShm ) unlink(zShm);
      sqlite4_free(p->pSqlEnv, zShm);
    }
  }
  return SQLITE4_OK;
}


static int btPosixOsClose(bt_file *pFile){
   BtPosixFile *p = (BtPosixFile *)pFile;
   btPosixOsShmUnmap(pFile, 0);
   close(p->fd);
   sqlite4_free(p->pSqlEnv, p->apShm);
   sqlite4_free(p->pSqlEnv, p);
   return SQLITE4_OK;
}

SQLITE4_PRIVATE bt_env *sqlite4BtEnvDefault(void){
  static bt_env posix_env = {
    0,                            /* pVfsCtx */
    btPosixOsFullpath,            /* xFullpath */
    btPosixOsOpen,                /* xOpen */
    btPosixOsSize,                /* xSize */
    btPosixOsRead,                /* xRead */
    btPosixOsWrite,               /* xWrite */
    btPosixOsTruncate,            /* xTruncate */
    btPosixOsSync,                /* xSync */
    btPosixOsSectorSize,          /* xSectorSize */
    btPosixOsClose,               /* xClose */
    btPosixOsUnlink,              /* xUnlink */
    btPosixOsLock,                /* xLock */
    btPosixOsTestLock,            /* xTestLock */
    btPosixOsShmMap,              /* xShmMap */
    btPosixOsShmBarrier,          /* xShmBarrier */
    btPosixOsShmUnmap             /* xShmUnmap */
  };
  return &posix_env;
}

/************** End of bt_unix.c *********************************************/
/************** Begin file bt_varint.c ***************************************/

/*
** 2012-02-08
**
** 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.
**
*************************************************************************
**
** SQLite4-compatible varint implementation.
*/

/*************************************************************************
** The following is a copy of the varint.c module from SQLite 4.
*/

/*
** Decode the varint in z[].  Write the integer value into *pResult and
** return the number of bytes in the varint.
*/
static int btSqlite4GetVarint64(const unsigned char *z, u64 *pResult){
  unsigned int x;
  if( z[0]<=240 ){
    *pResult = z[0];
    return 1;
  }
  if( z[0]<=248 ){
    *pResult = (z[0]-241)*256 + z[1] + 240;
    return 2;
  }
  if( z[0]==249 ){
    *pResult = 2288 + 256*z[1] + z[2];
    return 3;
  }
  if( z[0]==250 ){
    *pResult = (z[1]<<16) + (z[2]<<8) + z[3];
    return 4;
  }
  x = (z[1]<<24) + (z[2]<<16) + (z[3]<<8) + z[4];
  if( z[0]==251 ){
    *pResult = x;
    return 5;
  }
  if( z[0]==252 ){
    *pResult = (((u64)x)<<8) + z[5];
    return 6;
  }
  if( z[0]==253 ){
    *pResult = (((u64)x)<<16) + (z[5]<<8) + z[6];
    return 7;
  }
  if( z[0]==254 ){
    *pResult = (((u64)x)<<24) + (z[5]<<16) + (z[6]<<8) + z[7];
    return 8;
  }
  *pResult = (((u64)x)<<32) +
               (0xffffffff & ((z[5]<<24) + (z[6]<<16) + (z[7]<<8) + z[8]));
  return 9;
}

/*
** Write a 32-bit unsigned integer as 4 big-endian bytes.
*/
static void btVarintWrite32(unsigned char *z, unsigned int y){
  z[0] = (unsigned char)(y>>24);
  z[1] = (unsigned char)(y>>16);
  z[2] = (unsigned char)(y>>8);
  z[3] = (unsigned char)(y);
}

/*
** Write a varint into z[].  The buffer z[] must be at least 9 characters
** long to accommodate the largest possible varint.  Return the number of
** bytes of z[] used.
*/
static int btSqlite4PutVarint64(unsigned char *z, u64 x){
  unsigned int w, y;
  if( x<=240 ){
    z[0] = (unsigned char)x;
    return 1;
  }
  if( x<=2287 ){
    y = (unsigned int)(x - 240);
    z[0] = (unsigned char)(y/256 + 241);
    z[1] = (unsigned char)(y%256);
    return 2;
  }
  if( x<=67823 ){
    y = (unsigned int)(x - 2288);
    z[0] = 249;
    z[1] = (unsigned char)(y/256);
    z[2] = (unsigned char)(y%256);
    return 3;
  }
  y = (unsigned int)x;
  w = (unsigned int)(x>>32);
  if( w==0 ){
    if( y<=16777215 ){
      z[0] = 250;
      z[1] = (unsigned char)(y>>16);
      z[2] = (unsigned char)(y>>8);
      z[3] = (unsigned char)(y);
      return 4;
    }
    z[0] = 251;
    btVarintWrite32(z+1, y);
    return 5;
  }
  if( w<=255 ){
    z[0] = 252;
    z[1] = (unsigned char)w;
    btVarintWrite32(z+2, y);
    return 6;
  }
  if( w<=32767 ){
    z[0] = 253;
    z[1] = (unsigned char)(w>>8);
    z[2] = (unsigned char)w;
    btVarintWrite32(z+3, y);
    return 7;
  }
  if( w<=16777215 ){
    z[0] = 254;
    z[1] = (unsigned char)(w>>16);
    z[2] = (unsigned char)(w>>8);
    z[3] = (unsigned char)w;
    btVarintWrite32(z+4, y);
    return 8;
  }
  z[0] = 255;
  btVarintWrite32(z+1, w);
  btVarintWrite32(z+5, y);
  return 9;
}

/*
** End of SQLite 4 code.
*************************************************************************/

SQLITE4_PRIVATE int sqlite4BtVarintPut64(u8 *aData, i64 iVal){
  return btSqlite4PutVarint64(aData, (u64)iVal);
}

SQLITE4_PRIVATE int sqlite4BtVarintGet64(const u8 *aData, i64 *piVal){
  return btSqlite4GetVarint64(aData, (u64 *)piVal);
}

SQLITE4_PRIVATE int sqlite4BtVarintPut32(u8 *aData, int iVal){
  return btSqlite4PutVarint64(aData, (u64)iVal);
}

SQLITE4_PRIVATE int sqlite4BtVarintGet32(u8 *z, int *piVal){
  u64 i;
  int ret;

  if( z[0]<=240 ){
    *piVal = z[0];
    return 1;
  }
  if( z[0]<=248 ){
    *piVal = (z[0]-241)*256 + z[1] + 240;
    return 2;
  }
  if( z[0]==249 ){
    *piVal = 2288 + 256*z[1] + z[2];
    return 3;
  }
  if( z[0]==250 ){
    *piVal = (z[1]<<16) + (z[2]<<8) + z[3];
    return 4;
  }

  ret = btSqlite4GetVarint64(z, &i);
  *piVal = i;
  return ret;
}

SQLITE4_PRIVATE int sqlite4BtVarintLen32(int n){
  u8 aData[9];
  return sqlite4BtVarintPut32(aData, n);
}

/*
** The argument is the first byte of a varint. This function returns the
** total number of bytes in the entire varint (including the first byte).
*/
SQLITE4_PRIVATE int sqlite4BtVarintSize(u8 c){
  if( c<241 ) return 1;
  if( c<249 ) return 2;
  return (int)(c - 246);
}

/************** End of bt_varint.c *******************************************/
/************** Begin file vdbemem.c *****************************************/
/*
** 2004 May 26
**
** 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 use to manipulate "Mem" structure.  A "Mem"
** stores a single value in the VDBE.  Mem is an opaque structure visible
** only within the VDBE.  Interface routines refer to a Mem using the
** name sqlite_value
*/

/*
** If pMem is an object with a valid string representation, this routine
** ensures the internal encoding for the string representation is
** 'desiredEnc', one of SQLITE4_UTF8, SQLITE4_UTF16LE or SQLITE4_UTF16BE.
**
** If pMem is not a string object, or the encoding of the string
** representation is already stored using the requested encoding, then this
** routine is a no-op.
**
** SQLITE4_OK is returned if the conversion is successful (or not required).
** SQLITE4_NOMEM may be returned if a malloc() fails during conversion
** between formats.
*/
SQLITE4_PRIVATE int sqlite4VdbeChangeEncoding(Mem *pMem, int desiredEnc){
  int rc;
  assert( (pMem->flags&MEM_RowSet)==0 );
  assert( desiredEnc==SQLITE4_UTF8 || desiredEnc==SQLITE4_UTF16LE
           || desiredEnc==SQLITE4_UTF16BE );
  if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
    return SQLITE4_OK;
  }
  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
#ifdef SQLITE4_OMIT_UTF16
  return SQLITE4_ERROR;
#else

  /* MemTranslate() may return SQLITE4_OK or SQLITE4_NOMEM. If NOMEM is returned,
  ** then the encoding of the value may not have changed.
  */
  rc = sqlite4VdbeMemTranslate(pMem, (u8)desiredEnc);
  assert(rc==SQLITE4_OK    || rc==SQLITE4_NOMEM);
  assert(rc==SQLITE4_OK    || pMem->enc!=desiredEnc);
  assert(rc==SQLITE4_NOMEM || pMem->enc==desiredEnc);
  return rc;
#endif
}

/*
** Make sure pMem->z points to a writable allocation of at least 
** n bytes.
**
** If the memory cell currently contains string or blob data
** and the third argument passed to this function is true, the 
** current content of the cell is preserved. Otherwise, it may
** be discarded.  
**
** This function sets the MEM_Dyn flag and clears any xDel callback.
** It also clears MEM_Ephem and MEM_Static. If the preserve flag is 
** not set, Mem.n is zeroed.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemGrow(Mem *pMem, int n, int preserve){
  assert( 1 >=
    ((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
    (((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) + 
    ((pMem->flags&MEM_Ephem) ? 1 : 0) + 
    ((pMem->flags&MEM_Static) ? 1 : 0)
  );
  assert( (pMem->flags&MEM_RowSet)==0 );

  if( n<32 ) n = 32;
  if( sqlite4DbMallocSize(pMem->db, pMem->zMalloc)<n ){
    if( preserve && pMem->z==pMem->zMalloc ){
      pMem->z = pMem->zMalloc = sqlite4DbReallocOrFree(pMem->db, pMem->z, n);
      preserve = 0;
    }else{
      sqlite4DbFree(pMem->db, pMem->zMalloc);
      pMem->zMalloc = sqlite4DbMallocRaw(pMem->db, n);
    }
  }

  if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
    memcpy(pMem->zMalloc, pMem->z, pMem->n);
  }
  if( pMem->flags&MEM_Dyn && pMem->xDel ){
    assert( pMem->xDel!=SQLITE4_DYNAMIC );
    pMem->xDel(pMem->pDelArg, (void *)(pMem->z));
  }

  pMem->z = pMem->zMalloc;
  if( pMem->z==0 ){
    pMem->flags = MEM_Null;
  }else{
    pMem->flags &= ~(MEM_Ephem|MEM_Static);
  }
  pMem->xDel = 0;
  return (pMem->z ? SQLITE4_OK : SQLITE4_NOMEM);
}

/*
** Make the given Mem object MEM_Dyn.  In other words, make it so
** that any TEXT or BLOB content is stored in memory obtained from
** malloc().  In this way, we know that the memory is safe to be
** overwritten or altered.
**
** Return SQLITE4_OK on success or SQLITE4_NOMEM if malloc fails.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemMakeWriteable(Mem *pMem){
  int f;
  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  assert( (pMem->flags&MEM_RowSet)==0 );
  f = pMem->flags;
  if( (f&(MEM_Str|MEM_Blob)) && pMem->z!=pMem->zMalloc ){
    if( sqlite4VdbeMemGrow(pMem, pMem->n + 2, 1) ){
      return SQLITE4_NOMEM;
    }
    pMem->z[pMem->n] = 0;
    pMem->z[pMem->n+1] = 0;
    pMem->flags |= MEM_Term;
#ifdef SQLITE4_DEBUG
    pMem->pScopyFrom = 0;
#endif
  }

  return SQLITE4_OK;
}


/*
** Make sure the given Mem is \u0000 terminated.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemNulTerminate(Mem *pMem){
  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
    return SQLITE4_OK;   /* Nothing to do */
  }
  if( sqlite4VdbeMemGrow(pMem, pMem->n+2, 1) ){
    return SQLITE4_NOMEM;
  }
  pMem->z[pMem->n] = 0;
  pMem->z[pMem->n+1] = 0;
  pMem->flags |= MEM_Term;
  return SQLITE4_OK;
}

/*
** Add MEM_Str to the set of representations for the given Mem.  Numbers
** are converted using sqlite4_snprintf().  Converting a BLOB to a string
** is a no-op.
**
** Existing representations MEM_Int and MEM_Real are *not* invalidated.
**
** A MEM_Null value will never be passed to this function. This function is
** used for converting values to text for returning to the user (i.e. via
** sqlite4_value_text()), or for ensuring that values to be used as btree
** keys are strings. In the former case a NULL pointer is returned the
** user and the later is an internal programming error.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemStringify(Mem *pMem, int enc){
  int rc = SQLITE4_OK;
  int fg = pMem->flags;
  const int nByte = 32;

  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  assert( !(fg&(MEM_Str|MEM_Blob)) );
  assert( fg&(MEM_Int|MEM_Real) );
  assert( (pMem->flags&MEM_RowSet)==0 );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  if( sqlite4VdbeMemGrow(pMem, nByte, 0) ){
    return SQLITE4_NOMEM;
  }

  /* For a Real or Integer, use sqlite4_mprintf() to produce the UTF-8
  ** string representation of the value. Then, if the required encoding
  ** is UTF-16le or UTF-16be do a translation.
  ** 
  ** FIX ME: It would be better if sqlite4_snprintf() could do UTF-16.
  */
  sqlite4_num_to_text(pMem->u.num, pMem->z, (pMem->flags & MEM_Int)==0);

  pMem->n = sqlite4Strlen30(pMem->z);
  pMem->enc = SQLITE4_UTF8;
  pMem->flags |= MEM_Str|MEM_Term;
  sqlite4VdbeChangeEncoding(pMem, enc);
  return rc;
}

/*
** Memory cell pMem contains the context of an aggregate function.
** This routine calls the finalize method for that function.  The
** result of the aggregate is stored back into pMem.
**
** Return SQLITE4_ERROR if the finalizer reports an error.  SQLITE4_OK
** otherwise.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
  int rc = SQLITE4_OK;
  if( ALWAYS(pFunc && pFunc->xFinalize) ){
    sqlite4_context ctx;
    assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
    assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
    memset(&ctx, 0, sizeof(ctx));
    ctx.s.flags = MEM_Null;
    ctx.s.db = pMem->db;
    ctx.pMem = pMem;
    ctx.pFunc = pFunc;
    pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
    assert( 0==(pMem->flags&MEM_Dyn) && !pMem->xDel );
    sqlite4DbFree(pMem->db, pMem->zMalloc);
    memcpy(pMem, &ctx.s, sizeof(ctx.s));
    rc = ctx.isError;
  }
  return rc;
}

/*
** If the memory cell contains a string value that must be freed by
** invoking an external callback, free it now. Calling this function
** does not free any Mem.zMalloc buffer.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemReleaseExternal(Mem *p){
  assert( p->db==0 || sqlite4_mutex_held(p->db->mutex) );
  if( p->flags&MEM_Agg ){
    sqlite4VdbeMemFinalize(p, p->u.pDef);
    assert( (p->flags & MEM_Agg)==0 );
    sqlite4VdbeMemRelease(p);
  }else if( p->flags&MEM_Dyn && p->xDel ){
    assert( (p->flags&MEM_RowSet)==0 );
    assert( p->xDel!=SQLITE4_DYNAMIC );
    p->xDel(p->pDelArg, (void *)p->z);
    p->xDel = 0;
  }else if( p->flags&MEM_RowSet ){
    sqlite4RowSetClear(p->u.pRowSet);
  }else if( p->flags&MEM_Frame ){
    sqlite4VdbeMemSetNull(p);
  }
}

/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
** (Mem.type==SQLITE4_TEXT).
*/
SQLITE4_PRIVATE void sqlite4VdbeMemRelease(Mem *p){
  VdbeMemRelease(p);
  sqlite4DbFree(p->db, p->zMalloc);
  p->z = 0;
  p->zMalloc = 0;
  p->xDel = 0;
}

/*
** Return some kind of integer value which is the best we can do
** at representing the value that *pMem describes as an integer.
** If pMem is an integer, then the value is exact.  If pMem is
** a floating-point then the value returned is the integer part.
** If pMem is a string or blob, then we make an attempt to convert
** it into a integer and return that.  If pMem represents an
** an SQL-NULL value, return 0.
**
** If pMem represents a string value, its encoding might be changed.
*/
SQLITE4_PRIVATE i64 sqlite4VdbeIntValue(Mem *pMem){
  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );
  return sqlite4_num_to_int64(sqlite4VdbeNumValue(pMem), 0);
}

/*
** Return the best representation of pMem that we can get into a
** double.  If pMem is already a double or an integer, return its
** value.  If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
SQLITE4_PRIVATE double sqlite4VdbeRealValue(Mem *pMem){
  double rVal = 0.0;
  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );
  sqlite4_num_to_double(sqlite4VdbeNumValue(pMem), &rVal);
  return rVal;
}

/*
** Extract and return a numeric value from memory cell pMem. This call
** does not modify the contents or flags of *pMem in any way.
*/
SQLITE4_PRIVATE sqlite4_num sqlite4VdbeNumValue(Mem *pMem){
  if( pMem->flags & (MEM_Real|MEM_Int) ){
    return pMem->u.num;
  }else if( pMem->flags & (MEM_Str|MEM_Blob) ){
    int flags = SQLITE4_PREFIX_ONLY | SQLITE4_IGNORE_WHITESPACE | pMem->enc;
    return sqlite4_num_from_text(pMem->z, pMem->n, flags, 0);
  }else{
    sqlite4_num zero = {0,0,0,0};
    return zero;
  }
}

/*
** The MEM structure is already a MEM_Real.  Try to also make it a
** MEM_Int if we can.
*/
SQLITE4_PRIVATE void sqlite4VdbeIntegerAffinity(Mem *pMem){
  i64 i;
  int bLossy;

  assert( pMem->flags & MEM_Real );
  assert( (pMem->flags & MEM_RowSet)==0 );
  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  i = sqlite4_num_to_int64(pMem->u.num, &bLossy);
  if( bLossy==0 ){
    MemSetTypeFlag(pMem, MEM_Int);
    pMem->u.num = sqlite4_num_from_int64(i);
  }
}

/*
** Convert pMem to type integer.  Invalidate any prior representations.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemIntegerify(Mem *pMem){
  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  assert( (pMem->flags & MEM_RowSet)==0 );
  assert( EIGHT_BYTE_ALIGNMENT(pMem) );

  if( (pMem->flags & MEM_Int)==0 ){
    if( pMem->flags & (MEM_Real|MEM_Null) ){
      pMem->u.num = sqlite4_num_from_int64(sqlite4VdbeIntValue(pMem));
    }else{
      unsigned int flags = pMem->enc |
          SQLITE4_INTEGER_ONLY|SQLITE4_PREFIX_ONLY|SQLITE4_IGNORE_WHITESPACE;
      pMem->u.num = sqlite4_num_from_text(pMem->z, pMem->n, flags, 0);
    }
    MemSetTypeFlag(pMem, MEM_Int);
  }
  return SQLITE4_OK;
}

/*
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
** Invalidate any prior representations.
**
** Every effort is made to force the conversion, even if the input
** is a string that does not look completely like a number.  Convert
** as much of the string as we can and ignore the rest.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemNumerify(Mem *pMem){
  if( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))==0 ){
    int bReal = 0;
    int flags = (pMem->enc | SQLITE4_PREFIX_ONLY | SQLITE4_IGNORE_WHITESPACE);

    assert( (pMem->flags & (MEM_Blob|MEM_Str))!=0 );
    assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
    pMem->u.num = sqlite4_num_from_text(pMem->z, pMem->n, flags, 0);
    sqlite4_num_to_int64(pMem->u.num, &bReal);
    MemSetTypeFlag(pMem, (bReal ? MEM_Real : MEM_Int));
  }
  assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
  pMem->flags &= ~(MEM_Str|MEM_Blob);
  return SQLITE4_OK;
}

/*
** Delete any previous value and set the value stored in *pMem to NULL.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemSetNull(Mem *pMem){
  if( pMem->flags & MEM_Frame ){
    VdbeFrame *pFrame = pMem->u.pFrame;
    pFrame->pParent = pFrame->v->pDelFrame;
    pFrame->v->pDelFrame = pFrame;
  }else if( pMem->flags & MEM_RowSet ){
    sqlite4RowSetClear(pMem->u.pRowSet);
  }
  MemSetTypeFlag(pMem, MEM_Null);
  pMem->type = SQLITE4_NULL;
}

/*
** Delete any previous value and set the value stored in *pMem to val,
** manifest type INTEGER.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemSetInt64(Mem *pMem, i64 val){
  sqlite4VdbeMemRelease(pMem);
  pMem->u.num = sqlite4_num_from_int64(val);
  pMem->flags = MEM_Int;
  pMem->type = SQLITE4_INTEGER;
}

SQLITE4_PRIVATE void sqlite4VdbeMemSetNum(Mem *pMem, sqlite4_num val, int flag){
  assert( flag==MEM_Int || flag==MEM_Real );
  sqlite4VdbeMemRelease(pMem);
  pMem->u.num = val;
  pMem->flags = flag;
  sqlite4VdbeMemStoreType(pMem);
}

#ifndef SQLITE4_OMIT_FLOATING_POINT
/*
** Delete any previous value and set the value stored in *pMem to val,
** manifest type REAL.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemSetDouble(Mem *pMem, double val){
  if( sqlite4IsNaN(val) ){
    sqlite4VdbeMemSetNull(pMem);
  }else{
    sqlite4VdbeMemRelease(pMem);
    pMem->u.num = sqlite4_num_from_double(val);
    pMem->flags = MEM_Real;
    pMem->type = SQLITE4_FLOAT;
  }
}
#endif

/*
** Delete any previous value and set the value of pMem to be an
** empty RowSet object.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemSetRowSet(Mem *pMem){
  sqlite4 *db = pMem->db;
  assert( db!=0 );
  assert( (pMem->flags & MEM_RowSet)==0 );
  sqlite4VdbeMemRelease(pMem);
  sqlite4VdbeMemGrow(pMem, 64, 0);
  if( db->mallocFailed ){
    pMem->flags = MEM_Null;
  }else{
    int nAlloc = sqlite4DbMallocSize(db, pMem->zMalloc);
    pMem->u.pRowSet = sqlite4RowSetInit(db, pMem->zMalloc, nAlloc);
    pMem->flags = MEM_RowSet;
  }
}

/*
** Return true if the Mem object contains a TEXT or BLOB that is
** too large - whose size exceeds SQLITE4_MAX_LENGTH.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemTooBig(Mem *p){
  assert( p->db!=0 );
  if( p->flags & (MEM_Str|MEM_Blob) ){
    int n = p->n;
    return n>p->db->aLimit[SQLITE4_LIMIT_LENGTH];
  }
  return 0; 
}

#ifdef SQLITE4_DEBUG
/*
** This routine prepares a memory cell for modication by breaking
** its link to a shallow copy and by marking any current shallow
** copies of this cell as invalid.
**
** This is used for testing and debugging only - to make sure shallow
** copies are not misused.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
  int i;
  Mem *pX;
  for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){
    if( pX->pScopyFrom==pMem ){
      pX->flags |= MEM_Invalid;
      pX->pScopyFrom = 0;
    }
  }
  pMem->pScopyFrom = 0;
}
#endif /* SQLITE4_DEBUG */

/*
** Size of struct Mem not including the Mem.zMalloc member.
*/
#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))

/*
** Make an shallow copy of pFrom into pTo.  Prior contents of
** pTo are freed.  The pFrom->z field is not duplicated.  If
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
SQLITE4_PRIVATE void sqlite4VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
  assert( (pFrom->flags & MEM_RowSet)==0 );
  VdbeMemRelease(pTo);
  memcpy(pTo, pFrom, MEMCELLSIZE);
  pTo->xDel = 0;
  if( (pFrom->flags&MEM_Static)==0 ){
    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
    assert( srcType==MEM_Ephem || srcType==MEM_Static );
    pTo->flags |= srcType;
  }
}

/*
** Make a full copy of pFrom into pTo.  Prior contents of pTo are
** freed before the copy is made.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemCopy(Mem *pTo, const Mem *pFrom){
  int rc = SQLITE4_OK;

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

  if( pTo->flags&(MEM_Str|MEM_Blob) ){
    if( 0==(pFrom->flags&MEM_Static) ){
      pTo->flags |= MEM_Ephem;
      rc = sqlite4VdbeMemMakeWriteable(pTo);
    }
  }

  return rc;
}

/*
** Transfer the contents of pFrom to pTo. Any existing value in pTo is
** freed. If pFrom contains ephemeral data, a copy is made.
**
** pFrom contains an SQL NULL when this routine returns.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemMove(Mem *pTo, Mem *pFrom){
  assert( pFrom->db==0 || sqlite4_mutex_held(pFrom->db->mutex) );
  assert( pTo->db==0 || sqlite4_mutex_held(pTo->db->mutex) );
  assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db );

  sqlite4VdbeMemRelease(pTo);
  memcpy(pTo, pFrom, sizeof(Mem));
  pFrom->flags = MEM_Null;
  pFrom->xDel = 0;
  pFrom->zMalloc = 0;
}

/*
** Change the value of a Mem to be a string or a BLOB.
**
** The memory management strategy depends on the value of the xDel
** parameter. If the value passed is SQLITE4_TRANSIENT, then the 
** string is copied into a (possibly existing) buffer managed by the 
** Mem structure. Otherwise, any existing buffer is freed and the
** pointer copied.
**
** If the string is too large (if it exceeds the SQLITE4_LIMIT_LENGTH
** size limit) then no memory allocation occurs.  If the string can be
** stored without allocating memory, then it is.  If a memory allocation
** is required to store the string, then value of pMem is unchanged.  In
** either case, SQLITE4_TOOBIG is returned.
*/
SQLITE4_PRIVATE int sqlite4VdbeMemSetStr(
  Mem *pMem,                /* Memory cell to set to string value */
  const char *z,            /* String pointer */
  int n,                    /* Bytes in string, or negative */
  u8 enc,                   /* Encoding of z.  0 for BLOBs */
  void (*xDel)(void*,void*),/* Destructor function */
  void *pDelArg             /* First argument to xDel() */
){
  int nByte = n;      /* New value for pMem->n */
  int iLimit;         /* Maximum allowed string or blob size */
  u16 flags = 0;      /* New value for pMem->flags */

  assert( pMem->db==0 || sqlite4_mutex_held(pMem->db->mutex) );
  assert( (pMem->flags & MEM_RowSet)==0 );

  /* If z is a NULL pointer, set pMem to contain an SQL NULL. */
  if( !z ){
    sqlite4VdbeMemSetNull(pMem);
    return SQLITE4_OK;
  }

  if( pMem->db ){
    iLimit = pMem->db->aLimit[SQLITE4_LIMIT_LENGTH];
  }else{
    iLimit = SQLITE4_MAX_LENGTH;
  }
  flags = (enc==0?MEM_Blob:MEM_Str);
  if( nByte<0 ){
    assert( enc!=0 );
    if( enc==SQLITE4_UTF8 ){
      for(nByte=0; nByte<=iLimit && z[nByte]; nByte++){}
    }else{
      for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
    }
    flags |= MEM_Term;
  }

  /* The following block sets the new values of Mem.z and Mem.xDel. It
  ** also sets a flag in local variable "flags" to indicate the memory
  ** management (one of MEM_Dyn or MEM_Static).
  */
  if( xDel==SQLITE4_TRANSIENT ){
    int nAlloc = nByte;
    if( flags&MEM_Term ){
      nAlloc += (enc==SQLITE4_UTF8?1:2);
    }
    if( nByte>iLimit ){
      return SQLITE4_TOOBIG;
    }
    if( sqlite4VdbeMemGrow(pMem, nAlloc, 0) ){
      return SQLITE4_NOMEM;
    }
    memcpy(pMem->z, z, nAlloc);
  }else if( xDel==SQLITE4_DYNAMIC ){
    sqlite4VdbeMemRelease(pMem);
    pMem->zMalloc = pMem->z = (char *)z;
    pMem->xDel = 0;
  }else{
    sqlite4VdbeMemRelease(pMem);
    pMem->z = (char *)z;
    pMem->xDel = xDel;
    pMem->pDelArg = pDelArg;
    flags |= ((xDel==SQLITE4_STATIC)?MEM_Static:MEM_Dyn);
  }

  pMem->n = nByte;
  pMem->flags = flags;
  pMem->enc = (enc==0 ? SQLITE4_UTF8 : enc);
  pMem->type = (enc==0 ? SQLITE4_BLOB : SQLITE4_TEXT);

#ifndef SQLITE4_OMIT_UTF16
  if( pMem->enc!=SQLITE4_UTF8 && sqlite4VdbeMemHandleBom(pMem) ){
    return SQLITE4_NOMEM;
  }
#endif

  if( nByte>iLimit ){
    return SQLITE4_TOOBIG;
  }

  return SQLITE4_OK;
}

/*
** Compare the values contained by the two memory cells, returning
** negative, zero or positive if pMem1 is less than, equal to, or greater
** than pMem2. Sorting order is NULL's first, followed by numbers (integers
** and reals) sorted numerically, followed by text ordered by the collating
** sequence pColl and finally blob's ordered by memcmp().
**
** Two NULL values are considered equal by this function.
*/
SQLITE4_PRIVATE int sqlite4MemCompare(
  Mem *pMem1, 
  Mem *pMem2, 
  const CollSeq *pColl,
  int *pRes                       /* OUT: Result of comparison operation */
){
  int rc = SQLITE4_OK;
  int f1, f2;
  int combined_flags;

  f1 = pMem1->flags;
  f2 = pMem2->flags;
  combined_flags = f1|f2;
  assert( (combined_flags & MEM_RowSet)==0 );
 
  /* If one value is NULL, it is less than the other. If both values
  ** are NULL, return 0.
  */
  if( combined_flags&MEM_Null ){
    *pRes = (f2&MEM_Null) - (f1&MEM_Null);
    return SQLITE4_OK;
  }

  /* If one value is a number and the other is not, the number is less.
  ** If both are numbers, compare as reals if one is a real, or as integers
  ** if both values are integers.
  */
  if( combined_flags&(MEM_Int|MEM_Real) ){
    if( !(f1&(MEM_Int|MEM_Real)) ){
      *pRes = 1;
    }else if( !(f2&(MEM_Int|MEM_Real)) ){
      *pRes = -1;
    }else{
      *pRes = (sqlite4_num_compare(pMem1->u.num, pMem2->u.num) - 2);
    }
    return SQLITE4_OK;
  }

  /* If one value is a string and the other is a blob, the string is less.
  ** If both are strings, compare using the collating functions.
  */
  if( combined_flags&MEM_Str ){

    if( (f1 & f2 & MEM_Str)==0 ){
      /* This branch is taken if one of the values is not a string. So, if
      ** f1 is a string, then f2 must be a blob. Return -1. Otherwise,
      ** if f2 is a string and f1 is a blob, return +1.  */
      *pRes = (f1 & MEM_Str) ? -1 : +1;
      return SQLITE4_OK;
    }

    assert( pMem1->enc==pMem2->enc );
    assert( pMem1->enc==SQLITE4_UTF8 || 
            pMem1->enc==SQLITE4_UTF16LE || pMem1->enc==SQLITE4_UTF16BE );

    /* The collation sequence must be defined at this point, even if
    ** the user deletes the collation sequence after the vdbe program is
    ** compiled (this was not always the case).
    */
    assert( !pColl || pColl->xCmp );

    if( pColl ){
      int enc = pMem1->enc;
      void *pUser = pColl->pUser;
      rc = pColl->xCmp(pUser, pMem1, pMem2, pRes);
      sqlite4VdbeChangeEncoding(pMem1, enc);
      sqlite4VdbeChangeEncoding(pMem2, enc);
      return rc;
    }

    /* If a NULL pointer was passed as the collate function, fall through
    ** to the blob case and use memcmp().  */
  }
 
  /* Both values must be blobs.  Compare using memcmp().  */
  *pRes = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
  if( *pRes==0 ){
    *pRes = pMem1->n - pMem2->n;
  }
  return rc;
}

/* This function is only available internally, it is not part of the
** external API. It works in a similar way to sqlite4_value_text(),
** except the data returned is in the encoding specified by the second
** parameter, which must be one of SQLITE4_UTF16BE, SQLITE4_UTF16LE or
** SQLITE4_UTF8.
*/
SQLITE4_PRIVATE const void *sqlite4ValueText(sqlite4_value* pVal, u8 enc){
  if( !pVal ) return 0;

  assert( pVal->db==0 || sqlite4_mutex_held(pVal->db->mutex) );
  assert( (pVal->flags & MEM_RowSet)==0 );

  if( pVal->flags&MEM_Null ){
    return 0;
  }
  assert( (MEM_Blob>>3) == MEM_Str );
  pVal->flags |= (pVal->flags & MEM_Blob)>>3;
  if( pVal->flags&MEM_Str ){
    sqlite4VdbeChangeEncoding(pVal, enc);
    sqlite4VdbeMemNulTerminate(pVal); /* IMP: R-31275-44060 */
  }else{
    assert( (pVal->flags&MEM_Blob)==0 );
    sqlite4VdbeMemStringify(pVal, enc);
    assert( 0==(1&SQLITE4_PTR_TO_INT(pVal->z)) );
  }
  assert(pVal->enc==enc || pVal->db==0 || pVal->db->mallocFailed );
  if( pVal->enc==enc ){
    return pVal->z;
  }else{
    return 0;
  }
}

/*
** Create a new sqlite4_value object.
*/
SQLITE4_PRIVATE sqlite4_value *sqlite4ValueNew(sqlite4 *db){
  Mem *p = sqlite4DbMallocZero(db, sizeof(*p));
  if( p ){
    p->flags = MEM_Null;
    p->type = SQLITE4_NULL;
    p->db = db;
  }
  return p;
}

/*
** Create a new sqlite4_value object, containing the value of pExpr.
**
** This only works for very simple expressions that consist of one constant
** token (i.e. "5", "5.1", "'a string'"). If the expression can
** be converted directly into a value, then the value is allocated and
** a pointer written to *ppVal. The caller is responsible for deallocating
** the value by passing it to sqlite4ValueFree() later on. If the expression
** cannot be converted to a value, then *ppVal is set to NULL.
*/
SQLITE4_PRIVATE int sqlite4ValueFromExpr(
  sqlite4 *db,              /* The database connection */
  Expr *pExpr,              /* The expression to evaluate */
  u8 enc,                   /* Encoding to use */
  u8 affinity,              /* Affinity to use */
  sqlite4_value **ppVal     /* Write the new value here */
){
  int op;
  char *zVal = 0;
  sqlite4_value *pVal = 0;
  int negInt = 1;
  const char *zNeg = "";

  if( !pExpr ){
    *ppVal = 0;
    return SQLITE4_OK;
  }
  op = pExpr->op;

  /* op can only be TK_REGISTER if we have compiled with SQLITE4_ENABLE_STAT3.
  ** The ifdef here is to enable us to achieve 100% branch test coverage even
  ** when SQLITE4_ENABLE_STAT3 is omitted.
  */
#ifdef SQLITE4_ENABLE_STAT3
  if( op==TK_REGISTER ) op = pExpr->op2;
#else
  if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
#endif

  /* Handle negative integers in a single step.  This is needed in the
  ** case when the value is -9223372036854775808.
  */
  if( op==TK_UMINUS
   && (pExpr->pLeft->op==TK_INTEGER || pExpr->pLeft->op==TK_FLOAT) ){
    pExpr = pExpr->pLeft;
    op = pExpr->op;
    negInt = -1;
    zNeg = "-";
  }

  if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
    pVal = sqlite4ValueNew(db);
    if( pVal==0 ) goto no_mem;
    if( ExprHasProperty(pExpr, EP_IntValue) ){
      sqlite4VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
    }else{
      zVal = sqlite4MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
      if( zVal==0 ) goto no_mem;
      sqlite4ValueSetStr(pVal, -1, zVal, SQLITE4_UTF8, SQLITE4_DYNAMIC, 0);
      if( op==TK_FLOAT ) pVal->type = SQLITE4_FLOAT;
    }
    if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE4_AFF_NONE ){
      sqlite4ValueApplyAffinity(pVal, SQLITE4_AFF_NUMERIC, SQLITE4_UTF8);
    }else{
      sqlite4ValueApplyAffinity(pVal, affinity, SQLITE4_UTF8);
    }
    if( pVal->flags & (MEM_Int|MEM_Real) ) pVal->flags &= ~MEM_Str;
    if( enc!=SQLITE4_UTF8 ){
      sqlite4VdbeChangeEncoding(pVal, enc);
    }
  }else if( op==TK_UMINUS ) {
    /* This branch happens for multiple negative signs.  Ex: -(-5) */
    if( SQLITE4_OK==sqlite4ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal) ){
      sqlite4VdbeMemNumerify(pVal);
      pVal->u.num = sqlite4_num_mul(pVal->u.num, sqlite4_num_from_int64(-1));
      sqlite4ValueApplyAffinity(pVal, affinity, enc);
    }
  }else if( op==TK_NULL ){
    pVal = sqlite4ValueNew(db);
    if( pVal==0 ) goto no_mem;
  }
#ifndef SQLITE4_OMIT_BLOB_LITERAL
  else if( op==TK_BLOB ){
    int nVal;
    assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
    assert( pExpr->u.zToken[1]=='\'' );
    pVal = sqlite4ValueNew(db);
    if( !pVal ) goto no_mem;
    zVal = &pExpr->u.zToken[2];
    nVal = sqlite4Strlen30(zVal)-1;
    assert( zVal[nVal]=='\'' );
    sqlite4VdbeMemSetStr(pVal, sqlite4HexToBlob(db, zVal, nVal), nVal/2,
                         0, SQLITE4_DYNAMIC, 0);
  }
#endif

  if( pVal ){
    sqlite4VdbeMemStoreType(pVal);
  }
  *ppVal = pVal;
  return SQLITE4_OK;

no_mem:
  db->mallocFailed = 1;
  sqlite4DbFree(db, zVal);
  sqlite4ValueFree(pVal);
  *ppVal = 0;
  return SQLITE4_NOMEM;
}

/*
** Change the string value of an sqlite4_value object
*/
SQLITE4_PRIVATE void sqlite4ValueSetStr(
  sqlite4_value *v,          /* Value to be set */
  int n,                     /* Length of string z */
  const void *z,             /* Text of the new string */
  u8 enc,                    /* Encoding to use */
  void (*xDel)(void*,void*), /* Destructor for the string */
  void *pDelArg              /* First argument to xDel() */
){
  if( v ) sqlite4VdbeMemSetStr((Mem *)v, z, n, enc, xDel, pDelArg);
}

/*
** Free an sqlite4_value object
*/
SQLITE4_PRIVATE void sqlite4ValueFree(sqlite4_value *v){
  if( !v ) return;
  sqlite4VdbeMemRelease((Mem *)v);
  sqlite4DbFree(((Mem*)v)->db, v);
}

/*
** Return the number of bytes in the sqlite4_value object assuming
** that it uses the encoding "enc"
*/
SQLITE4_PRIVATE int sqlite4ValueBytes(sqlite4_value *pVal, u8 enc){
  Mem *p = (Mem*)pVal;
  if( (p->flags & MEM_Blob)!=0 || sqlite4ValueText(pVal, enc) ){
    return p->n;
  }
  return 0;
}

/************** End of vdbemem.c *********************************************/
/************** Begin file vdbeaux.c *****************************************/
/*
** 2003 September 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite4_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
*/


/*
** Create a new virtual database engine.
*/
SQLITE4_PRIVATE Vdbe *sqlite4VdbeCreate(sqlite4 *db){
  Vdbe *p;
  p = sqlite4DbMallocZero(db, sizeof(Vdbe) );
  if( p==0 ) return 0;
  p->db = db;
  if( db->pVdbe ){
    db->pVdbe->pPrev = p;
  }
  p->pNext = db->pVdbe;
  p->pPrev = 0;
  db->pVdbe = p;
  p->magic = VDBE_MAGIC_INIT;
  return p;
}

/*
** Remember the SQL string for a prepared statement.
*/
SQLITE4_PRIVATE void sqlite4VdbeSetSql(Vdbe *p, const char *z, int n){
  if( p==0 ) return;
  assert( p->zSql==0 );
  p->zSql = sqlite4DbStrNDup(p->db, z, n);
}

/*
** Return the SQL associated with a prepared statement
*/
SQLITE4_API const char *sqlite4_stmt_sql(sqlite4_stmt *pStmt){
  Vdbe *p = (Vdbe *)pStmt;
  return p ? p->zSql : 0;
}

/*
** Swap all content between two VDBE structures.
*/
SQLITE4_PRIVATE void sqlite4VdbeSwap(Vdbe *pA, Vdbe *pB){
  Vdbe tmp, *pTmp;
  char *zTmp;
  tmp = *pA;
  *pA = *pB;
  *pB = tmp;
  pTmp = pA->pNext;
  pA->pNext = pB->pNext;
  pB->pNext = pTmp;
  pTmp = pA->pPrev;
  pA->pPrev = pB->pPrev;
  pB->pPrev = pTmp;
  zTmp = pA->zSql;
  pA->zSql = pB->zSql;
  pB->zSql = zTmp;
}

#ifdef SQLITE4_DEBUG
/*
** Turn tracing on or off
*/
SQLITE4_PRIVATE void sqlite4VdbeTrace(Vdbe *p, FILE *trace){
  p->trace = trace;
}
#endif

/*
** Resize the Vdbe.aOp array so that it is at least one op larger than 
** it was.
**
** If an out-of-memory error occurs while resizing the array, return
** SQLITE4_NOMEM. In this case Vdbe.aOp and Vdbe.nOpAlloc remain 
** unchanged (this is so that any opcodes already allocated can be 
** correctly deallocated along with the rest of the Vdbe).
*/
static int growOpArray(Vdbe *p){
  VdbeOp *pNew;
  int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
  pNew = sqlite4DbRealloc(p->db, p->aOp, nNew*sizeof(Op));
  if( pNew ){
    p->nOpAlloc = sqlite4DbMallocSize(p->db, pNew)/sizeof(Op);
    p->aOp = pNew;
  }
  return (pNew ? SQLITE4_OK : SQLITE4_NOMEM);
}

/*
** Add a new instruction to the list of instructions current in the
** VDBE.  Return the address of the new instruction.
**
** Parameters:
**
**    p               Pointer to the VDBE
**
**    op              The opcode for this instruction
**
**    p1, p2, p3      Operands
**
** Use the sqlite4VdbeResolveLabel() function to fix an address and
** the sqlite4VdbeChangeP4() function to change the value of the P4
** operand.
*/
SQLITE4_PRIVATE int sqlite4VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
  int i;
  VdbeOp *pOp;

  i = p->nOp;
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( op>0 && op<0xff );
  if( p->nOpAlloc<=i ){
    if( growOpArray(p) ){
      return 1;
    }
  }
  p->nOp++;
  pOp = &p->aOp[i];
  pOp->opcode = (u8)op;
  pOp->p5 = 0;
  pOp->p1 = p1;
  pOp->p2 = p2;
  pOp->p3 = p3;
  pOp->p4.p = 0;
  pOp->p4type = P4_NOTUSED;
#ifdef SQLITE4_DEBUG
  pOp->zComment = 0;
  if( p->db->flags & SQLITE4_VdbeAddopTrace ){
    sqlite4VdbePrintOp(0, i, &p->aOp[i]);
  }
#endif
#ifdef VDBE_PROFILE
  pOp->cycles = 0;
  pOp->cnt = 0;
#endif
  return i;
}
SQLITE4_PRIVATE int sqlite4VdbeAddOp0(Vdbe *p, int op){
  return sqlite4VdbeAddOp3(p, op, 0, 0, 0);
}
SQLITE4_PRIVATE int sqlite4VdbeAddOp1(Vdbe *p, int op, int p1){
  return sqlite4VdbeAddOp3(p, op, p1, 0, 0);
}
SQLITE4_PRIVATE int sqlite4VdbeAddOp2(Vdbe *p, int op, int p1, int p2){
  return sqlite4VdbeAddOp3(p, op, p1, p2, 0);
}


/*
** Add an opcode that includes the p4 value as a pointer.
*/
SQLITE4_PRIVATE int sqlite4VdbeAddOp4(
  Vdbe *p,            /* Add the opcode to this VM */
  int op,             /* The new opcode */
  int p1,             /* The P1 operand */
  int p2,             /* The P2 operand */
  int p3,             /* The P3 operand */
  const char *zP4,    /* The P4 operand */
  int p4type          /* P4 operand type */
){
  int addr = sqlite4VdbeAddOp3(p, op, p1, p2, p3);
  sqlite4VdbeChangeP4(p, addr, zP4, p4type);
  return addr;
}

/*
** Add an OP_ParseSchema opcode.  This routine is broken out from
** sqlite4VdbeAddOp4() since it needs to also needs to mark all btrees
** as having been used.
**
** The zWhere string must have been obtained from sqlite4_malloc().
** This routine will take ownership of the allocated memory.
*/
SQLITE4_PRIVATE void sqlite4VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
  int j;
  int addr = sqlite4VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
  sqlite4VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
  for(j=0; j<p->db->nDb; j++) sqlite4VdbeUsesStorage(p, j);
}

/*
** Add an opcode that includes the p4 value as an integer.
*/
SQLITE4_PRIVATE int sqlite4VdbeAddOp4Int(
  Vdbe *p,            /* Add the opcode to this VM */
  int op,             /* The new opcode */
  int p1,             /* The P1 operand */
  int p2,             /* The P2 operand */
  int p3,             /* The P3 operand */
  int p4              /* The P4 operand as an integer */
){
  int addr = sqlite4VdbeAddOp3(p, op, p1, p2, p3);
  sqlite4VdbeChangeP4(p, addr, SQLITE4_INT_TO_PTR(p4), P4_INT32);
  return addr;
}

/*
** Create a new symbolic label for an instruction that has yet to be
** coded.  The symbolic label is really just a negative number.  The
** label can be used as the P2 value of an operation.  Later, when
** the label is resolved to a specific address, the VDBE will scan
** through its operation list and change all values of P2 which match
** the label into the resolved address.
**
** The VDBE knows that a P2 value is a label because labels are
** always negative and P2 values are suppose to be non-negative.
** Hence, a negative P2 value is a label that has yet to be resolved.
**
** Zero is returned if a malloc() fails.
*/
SQLITE4_PRIVATE int sqlite4VdbeMakeLabel(Vdbe *p){
  int i;
  i = p->nLabel++;
  assert( p->magic==VDBE_MAGIC_INIT );
  if( i>=p->nLabelAlloc ){
    int n = p->nLabelAlloc*2 + 5;
    p->aLabel = sqlite4DbReallocOrFree(p->db, p->aLabel,
                                       n*sizeof(p->aLabel[0]));
    p->nLabelAlloc = sqlite4DbMallocSize(p->db, p->aLabel)/sizeof(p->aLabel[0]);
  }
  if( p->aLabel ){
    p->aLabel[i] = -1;
  }
  return -1-i;
}

/*
** Resolve label "x" to be the address of the next instruction to
** be inserted.  The parameter "x" must have been obtained from
** a prior call to sqlite4VdbeMakeLabel().
*/
SQLITE4_PRIVATE void sqlite4VdbeResolveLabel(Vdbe *p, int x){
  int j = -1-x;
  assert( p->magic==VDBE_MAGIC_INIT );
  assert( j>=0 && j<p->nLabel );
  if( p->aLabel ){
    p->aLabel[j] = p->nOp;
  }
}

/*
** Mark the VDBE as one that can only be run one time.
*/
SQLITE4_PRIVATE void sqlite4VdbeRunOnlyOnce(Vdbe *p){
  p->runOnlyOnce = 1;
}

#ifdef SQLITE4_DEBUG /* sqlite4AssertMayAbort() logic */

/*
** The following type and function are used to iterate through all opcodes
** in a Vdbe main program and each of the sub-programs (triggers) it may 
** invoke directly or indirectly. It should be used as follows:
**
**   Op *pOp;
**   VdbeOpIter sIter;
**
**   memset(&sIter, 0, sizeof(sIter));
**   sIter.v = v;                            // v is of type Vdbe* 
**   while( (pOp = opIterNext(&sIter)) ){
**     // Do something with pOp
**   }
**   sqlite4DbFree(v->db, sIter.apSub);
** 
*/
typedef struct VdbeOpIter VdbeOpIter;
struct VdbeOpIter {
  Vdbe *v;                   /* Vdbe to iterate through the opcodes of */
  SubProgram **apSub;        /* Array of subprograms */
  int nSub;                  /* Number of entries in apSub */
  int iAddr;                 /* Address of next instruction to return */
  int iSub;                  /* 0 = main program, 1 = first sub-program etc. */
};
static Op *opIterNext(VdbeOpIter *p){
  Vdbe *v = p->v;
  Op *pRet = 0;
  Op *aOp;
  int nOp;

  if( p->iSub<=p->nSub ){

    if( p->iSub==0 ){
      aOp = v->aOp;
      nOp = v->nOp;
    }else{
      aOp = p->apSub[p->iSub-1]->aOp;
      nOp = p->apSub[p->iSub-1]->nOp;
    }
    assert( p->iAddr<nOp );

    pRet = &aOp[p->iAddr];
    p->iAddr++;
    if( p->iAddr==nOp ){
      p->iSub++;
      p->iAddr = 0;
    }
  
    if( pRet->p4type==P4_SUBPROGRAM ){
      int nByte = (p->nSub+1)*sizeof(SubProgram*);
      int j;
      for(j=0; j<p->nSub; j++){
        if( p->apSub[j]==pRet->p4.pProgram ) break;
      }
      if( j==p->nSub ){
        p->apSub = sqlite4DbReallocOrFree(v->db, p->apSub, nByte);
        if( !p->apSub ){
          pRet = 0;
        }else{
          p->apSub[p->nSub++] = pRet->p4.pProgram;
        }
      }
    }
  }

  return pRet;
}

/*
** Check if the program stored in the VM associated with pParse may
** throw an ABORT exception (causing the statement, but not entire transaction
** to be rolled back). This condition is true if the main program or any
** sub-programs contains any of the following:
**
**   *  OP_Halt with P1=SQLITE4_CONSTRAINT and P2=OE_Abort.
**   *  OP_HaltIfNull with P1=SQLITE4_CONSTRAINT and P2=OE_Abort.
**   *  OP_VUpdate
**   *  OP_VRename
**   *  OP_FkCounter with P2==0 (immediate foreign key constraint)
**
** Then check that the value of Parse.mayAbort is true if an
** ABORT may be thrown, or false otherwise. Return true if it does
** match, or false otherwise. This function is intended to be used as
** part of an assert statement in the compiler. Similar to:
**
**   assert( sqlite4VdbeAssertMayAbort(pParse->pVdbe, pParse->mayAbort) );
*/
SQLITE4_PRIVATE int sqlite4VdbeAssertMayAbort(Vdbe *v, int mayAbort){
  int hasAbort = 0;
  Op *pOp;
  VdbeOpIter sIter;
  memset(&sIter, 0, sizeof(sIter));
  sIter.v = v;

  while( (pOp = opIterNext(&sIter))!=0 ){
    int opcode = pOp->opcode;
    if( opcode==OP_VUpdate || opcode==OP_VRename 
#ifndef SQLITE4_OMIT_FOREIGN_KEY
     || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) 
#endif
     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
      && (pOp->p1==SQLITE4_CONSTRAINT && pOp->p2==OE_Abort))
    ){
      hasAbort = 1;
      break;
    }
  }
  sqlite4DbFree(v->db, sIter.apSub);

  /* Return true if hasAbort==mayAbort. Or if a malloc failure occured.
  ** If malloc failed, then the while() loop above may not have iterated
  ** through all opcodes and hasAbort may be set incorrectly. Return
  ** true for this case to prevent the assert() in the callers frame
  ** from failing.  */
  return ( v->db->mallocFailed || hasAbort==mayAbort );
}
#endif /* SQLITE4_DEBUG - the sqlite4AssertMayAbort() function */

/*
** Loop through the program looking for P2 values that are negative
** on jump instructions.  Each such value is a label.  Resolve the
** label by setting the P2 value to its correct non-zero value.
**
** This routine is called once after all opcodes have been inserted.
**
** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument 
** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by 
** sqlite4VdbeMakeReady() to size the Vdbe.apArg[] array.
**
** The Op.opflags field is set on all opcodes.
*/
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
  int i;
  int nMaxArgs = *pMaxFuncArgs;
  Op *pOp;
  int *aLabel = p->aLabel;
  p->readOnly = 1;
  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
    u8 opcode = pOp->opcode;

    pOp->opflags = sqlite4OpcodeProperty[opcode];
    if( opcode==OP_Function || opcode==OP_AggStep ){
      if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
    }else if( (opcode==OP_Transaction && pOp->p2!=0) ){
      p->readOnly = 0;
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    }else if( opcode==OP_VUpdate ){
      if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
    }else if( opcode==OP_VFilter ){
      int n;
      assert( p->nOp - i >= 3 );
      assert( pOp[-1].opcode==OP_Integer );
      n = pOp[-1].p1;
      if( n>nMaxArgs ) nMaxArgs = n;
#endif
    }else if( opcode==OP_Next || opcode==OP_SorterNext ){
      pOp->p4.xAdvance = sqlite4VdbeNext;
      pOp->p4type = P4_ADVANCE;
    }else if( opcode==OP_Prev ){
      pOp->p4.xAdvance = sqlite4VdbePrevious;
      pOp->p4type = P4_ADVANCE;
    }

    if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
      assert( -1-pOp->p2<p->nLabel );
      pOp->p2 = aLabel[-1-pOp->p2];
    }
  }
  sqlite4DbFree(p->db, p->aLabel);
  p->aLabel = 0;

  *pMaxFuncArgs = nMaxArgs;
}

/*
** Return the address of the next instruction to be inserted.
*/
SQLITE4_PRIVATE int sqlite4VdbeCurrentAddr(Vdbe *p){
  assert( p->magic==VDBE_MAGIC_INIT );
  return p->nOp;
}

/*
** This function returns a pointer to the array of opcodes associated with
** the Vdbe passed as the first argument. It is the callers responsibility
** to arrange for the returned array to be eventually freed using the 
** vdbeFreeOpArray() function.
**
** Before returning, *pnOp is set to the number of entries in the returned
** array. Also, *pnMaxArg is set to the larger of its current value and 
** the number of entries in the Vdbe.apArg[] array required to execute the 
** returned program.
*/
SQLITE4_PRIVATE VdbeOp *sqlite4VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
  VdbeOp *aOp = p->aOp;
  assert( aOp && !p->db->mallocFailed );

  resolveP2Values(p, pnMaxArg);
  *pnOp = p->nOp;
  p->aOp = 0;
  return aOp;
}

/*
** Add a whole list of operations to the operation stack.  Return the
** address of the first operation added.
*/
SQLITE4_PRIVATE int sqlite4VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
  int addr;
  assert( p->magic==VDBE_MAGIC_INIT );
  if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){
    return 0;
  }
  addr = p->nOp;
  if( ALWAYS(nOp>0) ){
    int i;
    VdbeOpList const *pIn = aOp;
    for(i=0; i<nOp; i++, pIn++){
      int p2 = pIn->p2;
      VdbeOp *pOut = &p->aOp[i+addr];
      pOut->opcode = pIn->opcode;
      pOut->p1 = pIn->p1;
      if( p2<0 && (sqlite4OpcodeProperty[pOut->opcode] & OPFLG_JUMP)!=0 ){
        pOut->p2 = addr + ADDR(p2);
      }else{
        pOut->p2 = p2;
      }
      pOut->p3 = pIn->p3;
      pOut->p4type = P4_NOTUSED;
      pOut->p4.p = 0;
      pOut->p5 = 0;
#ifdef SQLITE4_DEBUG
      pOut->zComment = 0;
      if( p->db->flags & SQLITE4_VdbeAddopTrace ){
        sqlite4VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
      }
#endif
    }
    p->nOp += nOp;
  }
  return addr;
}

/*
** Change the value of the P1 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqlite4VdbeAddOpList but we want to make a
** few minor changes to the program.
*/
SQLITE4_PRIVATE void sqlite4VdbeChangeP1(Vdbe *p, u32 addr, int val){
  assert( p!=0 );
  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p1 = val;
  }
}

/*
** Change the value of the P2 operand for a specific instruction.
** This routine is useful for setting a jump destination.
*/
SQLITE4_PRIVATE void sqlite4VdbeChangeP2(Vdbe *p, u32 addr, int val){
  assert( p!=0 );
  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p2 = val;
  }
}

/*
** Change the value of the P3 operand for a specific instruction.
*/
SQLITE4_PRIVATE void sqlite4VdbeChangeP3(Vdbe *p, u32 addr, int val){
  assert( p!=0 );
  if( ((u32)p->nOp)>addr ){
    p->aOp[addr].p3 = val;
  }
}

/*
** Change the value of the P5 operand for the most recently
** added operation.
*/
SQLITE4_PRIVATE void sqlite4VdbeChangeP5(Vdbe *p, u8 val){
  assert( p!=0 );
  if( p->aOp ){
    assert( p->nOp>0 );
    p->aOp[p->nOp-1].p5 = val;
  }
}

/*
** Change the P2 operand of instruction addr so that it points to
** the address of the next instruction to be coded.
*/
SQLITE4_PRIVATE void sqlite4VdbeJumpHere(Vdbe *p, int addr){
  assert( addr>=0 || p->db->mallocFailed );
  if( addr>=0 ) sqlite4VdbeChangeP2(p, addr, p->nOp);
}


/*
** If the input FuncDef structure is ephemeral, then free it.  If
** the FuncDef is not ephermal, then do nothing.
*/
static void freeEphemeralFunction(sqlite4 *db, FuncDef *pDef){
  if( ALWAYS(pDef) && (pDef->flags & SQLITE4_FUNC_EPHEM)!=0 ){
    if( pDef->xDestroy ){
      pDef->xDestroy(pDef->pUserData);
    }
    sqlite4DbFree(db, pDef);
  }
}

static void vdbeFreeOpArray(sqlite4 *, Op *, int);

/*
** Delete a P4 value if necessary.
*/
static void freeP4(sqlite4 *db, int p4type, void *p4){
  if( p4 ){
    assert( db );
    switch( p4type ){
      case P4_NUM:
      case P4_DYNAMIC:
      case P4_KEYINFO:
      case P4_INTARRAY:
      case P4_KEYINFO_HANDOFF: {
        sqlite4DbFree(db, p4);
        break;
      }
      case P4_VDBEFUNC: {
        VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
        freeEphemeralFunction(db, pVdbeFunc->pFunc);
        if( db->pnBytesFreed==0 ) sqlite4VdbeDeleteAuxData(pVdbeFunc, 0);
        sqlite4DbFree(db, pVdbeFunc);
        break;
      }
      case P4_FUNCDEF: {
        freeEphemeralFunction(db, (FuncDef*)p4);
        break;
      }
      case P4_MEM: {
        if( db->pnBytesFreed==0 ){
          sqlite4ValueFree((sqlite4_value*)p4);
        }else{
          Mem *p = (Mem*)p4;
          sqlite4DbFree(db, p->zMalloc);
          sqlite4DbFree(db, p);
        }
        break;
      }
      case P4_VTAB : {
        if( db->pnBytesFreed==0 ) sqlite4VtabUnlock((VTable *)p4);
        break;
      }
      case P4_FTS5INFO : {
        sqlite4Fts5FreeInfo(db, (Fts5Info *)p4);
        break;
      }
    }
  }
}

/*
** Free the space allocated for aOp and any p4 values allocated for the
** opcodes contained within. If aOp is not NULL it is assumed to contain 
** nOp entries. 
*/
static void vdbeFreeOpArray(sqlite4 *db, Op *aOp, int nOp){
  if( aOp ){
    Op *pOp;
    for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
      freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE4_DEBUG
      sqlite4DbFree(db, pOp->zComment);
#endif     
    }
  }
  sqlite4DbFree(db, aOp);
}

/*
** Link the SubProgram object passed as the second argument into the linked
** list at Vdbe.pSubProgram. This list is used to delete all sub-program
** objects when the VM is no longer required.
*/
SQLITE4_PRIVATE void sqlite4VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
  p->pNext = pVdbe->pProgram;
  pVdbe->pProgram = p;
}

/*
** Change the opcode at addr into OP_Noop
*/
SQLITE4_PRIVATE void sqlite4VdbeChangeToNoop(Vdbe *p, int addr){
  if( p->aOp ){
    VdbeOp *pOp = &p->aOp[addr];
    sqlite4 *db = p->db;
    freeP4(db, pOp->p4type, pOp->p4.p);
    memset(pOp, 0, sizeof(pOp[0]));
    pOp->opcode = OP_Noop;
  }
}

/*
** Change the value of the P4 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqlite4VdbeAddOpList but we want to make a
** few minor changes to the program.
**
** If n>=0 then the P4 operand is dynamic, meaning that a copy of
** the string is made into memory obtained from sqlite4_malloc().
** A value of n==0 means copy bytes of zP4 up to and including the
** first null byte.  If n>0 then copy n+1 bytes of zP4.
**
** If n==P4_KEYINFO it means that zP4 is a pointer to a KeyInfo structure.
** A copy is made of the KeyInfo structure into memory obtained from
** sqlite4_malloc, to be freed when the Vdbe is finalized.
** n==P4_KEYINFO_HANDOFF indicates that zP4 points to a KeyInfo structure
** stored in memory that the caller has obtained from sqlite4_malloc. The 
** caller should not free the allocation, it will be freed when the Vdbe is
** finalized.
** 
** Other values of n (P4_STATIC, P4_COLLSEQ etc.) indicate that zP4 points
** to a string or structure that is guaranteed to exist for the lifetime of
** the Vdbe. In these cases we can just copy the pointer.
**
** If addr<0 then change P4 on the most recently inserted instruction.
*/
SQLITE4_PRIVATE void sqlite4VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
  Op *pOp;
  sqlite4 *db;
  assert( p!=0 );
  db = p->db;
  assert( p->magic==VDBE_MAGIC_INIT );
  if( p->aOp==0 || db->mallocFailed ){
    if ( n!=P4_KEYINFO && n!=P4_VTAB ) {
      freeP4(db, n, (void*)*(char**)&zP4);
    }
    return;
  }
  assert( p->nOp>0 );
  assert( addr<p->nOp );
  if( addr<0 ){
    addr = p->nOp - 1;
  }
  pOp = &p->aOp[addr];
  freeP4(db, pOp->p4type, pOp->p4.p);
  pOp->p4.p = 0;
  if( n==P4_INT32 ){
    /* Note: this cast is safe, because the origin data point was an int
    ** that was cast to a (const char *). */
    pOp->p4.i = SQLITE4_PTR_TO_INT(zP4);
    pOp->p4type = P4_INT32;
  }else if( zP4==0 ){
    pOp->p4.p = 0;
    pOp->p4type = P4_NOTUSED;
  }else if( n==P4_KEYINFO ){
    KeyInfo *pKeyInfo;
    int nField, nByte;

    nField = ((KeyInfo*)zP4)->nField;
    nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
    pKeyInfo = sqlite4DbMallocRaw(0, nByte);
    pOp->p4.pKeyInfo = pKeyInfo;
    if( pKeyInfo ){
      u8 *aSortOrder;
      memcpy((char*)pKeyInfo, zP4, nByte - nField);
      aSortOrder = pKeyInfo->aSortOrder;
      if( aSortOrder ){
        pKeyInfo->aSortOrder = (unsigned char*)&pKeyInfo->aColl[nField];
        memcpy(pKeyInfo->aSortOrder, aSortOrder, nField);
      }
      pOp->p4type = P4_KEYINFO;
    }else{
      p->db->mallocFailed = 1;
      pOp->p4type = P4_NOTUSED;
    }
  }else if( n==P4_KEYINFO_HANDOFF ){
    pOp->p4.p = (void*)zP4;
    pOp->p4type = P4_KEYINFO;
  }else if( n==P4_VTAB ){
    pOp->p4.p = (void*)zP4;
    pOp->p4type = P4_VTAB;
    sqlite4VtabLock((VTable *)zP4);
    assert( ((VTable *)zP4)->db==p->db );
  }else if( n<0 ){
    pOp->p4.p = (void*)zP4;
    pOp->p4type = (signed char)n;
  }else{
    if( n==0 ) n = sqlite4Strlen30(zP4);
    pOp->p4.z = sqlite4DbStrNDup(p->db, zP4, n);
    pOp->p4type = P4_DYNAMIC;
  }
}

#ifndef NDEBUG
/*
** Change the comment on the the most recently coded instruction.  Or
** insert a No-op and add the comment to that new instruction.  This
** makes the code easier to read during debugging.  None of this happens
** in a production build.
*/
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
  assert( p->nOp>0 || p->aOp==0 );
  assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
  if( p->nOp ){
    assert( p->aOp );
    sqlite4DbFree(p->db, p->aOp[p->nOp-1].zComment);
    p->aOp[p->nOp-1].zComment = sqlite4VMPrintf(p->db, zFormat, ap);
  }
}
SQLITE4_PRIVATE void sqlite4VdbeComment(Vdbe *p, const char *zFormat, ...){
  va_list ap;
  if( p ){
    va_start(ap, zFormat);
    vdbeVComment(p, zFormat, ap);
    va_end(ap);
  }
}
SQLITE4_PRIVATE void sqlite4VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
  va_list ap;
  if( p ){
    sqlite4VdbeAddOp0(p, OP_Noop);
    va_start(ap, zFormat);
    vdbeVComment(p, zFormat, ap);
    va_end(ap);
  }
}
#endif  /* NDEBUG */

/*
** Return the opcode for a given address.  If the address is -1, then
** return the most recently inserted opcode.
**
** If a memory allocation error has occurred prior to the calling of this
** routine, then a pointer to a dummy VdbeOp will be returned.  That opcode
** is readable but not writable, though it is cast to a writable value.
** The return of a dummy opcode allows the call to continue functioning
** after a OOM fault without having to check to see if the return from 
** this routine is a valid pointer.  But because the dummy.opcode is 0,
** dummy will never be written to.  This is verified by code inspection and
** by running with Valgrind.
**
** About the #ifdef SQLITE4_OMIT_TRACE:  Normally, this routine is never called
** unless p->nOp>0.  This is because in the absense of SQLITE4_OMIT_TRACE,
** an OP_Trace instruction is always inserted by sqlite4VdbeGet() as soon as
** a new VDBE is created.  So we are free to set addr to p->nOp-1 without
** having to double-check to make sure that the result is non-negative. But
** if SQLITE4_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
** check the value of p->nOp-1 before continuing.
*/
SQLITE4_PRIVATE VdbeOp *sqlite4VdbeGetOp(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 VdbeOp dummy;  /* Ignore the MSVC warning about no initializer */
  assert( p->magic==VDBE_MAGIC_INIT );
  if( addr<0 ){
#ifdef SQLITE4_OMIT_TRACE
    if( p->nOp==0 ) return (VdbeOp*)&dummy;
#endif
    addr = p->nOp - 1;
  }
  assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
  if( p->db->mallocFailed ){
    return (VdbeOp*)&dummy;
  }else{
    return &p->aOp[addr];
  }
}

#if !defined(SQLITE4_OMIT_EXPLAIN) || !defined(NDEBUG) \
     || defined(VDBE_PROFILE) || defined(SQLITE4_DEBUG)
/*
** Compute a string that describes the P4 parameter for an opcode.
** Use zTemp for any required temporary buffer space.
*/
static char *displayP4(Op *pOp, char *zTemp, int nTemp){
  char *zP4 = zTemp;
  assert( nTemp>=30 );
  switch( pOp->p4type ){
    case P4_KEYINFO_STATIC:
    case P4_KEYINFO: {
      int i, j;
      KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
      i = sqlite4_snprintf(zTemp, nTemp,
                 "keyinfo(%d,%d,%d", pKeyInfo->nField, pKeyInfo->nPK,
                 pKeyInfo->nData);
      for(j=0; j<pKeyInfo->nField; j++){
        CollSeq *pColl = pKeyInfo->aColl[j];
        if( pColl ){
          int n = sqlite4Strlen30(pColl->zName);
          if( i+n>nTemp-6 ){
            memcpy(&zTemp[i],",...",4);
            break;
          }
          zTemp[i++] = ',';
          if( pKeyInfo->aSortOrder && pKeyInfo->aSortOrder[j] ){
            zTemp[i++] = '-';
          }
          memcpy(&zTemp[i], pColl->zName,n+1);
          i += n;
        }else if( i+4<nTemp-6 ){
          memcpy(&zTemp[i],",nil",4);
          i += 4;
        }
      }
      zTemp[i++] = ')';
      zTemp[i] = 0;
      assert( i<nTemp );
      break;
    }
    case P4_COLLSEQ: {
      CollSeq *pColl = pOp->p4.pColl;
      sqlite4_snprintf(zTemp, nTemp, "collseq(%.20s)", pColl->zName);
      break;
    }
    case P4_FUNCDEF: {
      FuncDef *pDef = pOp->p4.pFunc;
      sqlite4_snprintf(zTemp, nTemp, "%s(%d)", pDef->zName, pDef->nArg);
      break;
    }
    case P4_INT32: {
      sqlite4_snprintf(zTemp, nTemp, "%d", pOp->p4.i);
      break;
    }
    case P4_NUM: {
      sqlite4_num_to_text(*pOp->p4.pNum, zTemp, 0); 
      break;
    }
    case P4_MEM: {
      Mem *pMem = pOp->p4.pMem;
      if( pMem->flags & MEM_Str ){
        zP4 = pMem->z;
      }else if( pMem->flags & (MEM_Int|MEM_Real) ){
        char aOut[30];
        sqlite4_num_to_text(pMem->u.num, aOut, (pMem->flags & MEM_Real));
        sqlite4_snprintf(zTemp, nTemp, "%s", aOut);
      }else if( pMem->flags & MEM_Null ){
        sqlite4_snprintf(zTemp, nTemp, "NULL");
      }else{
        assert( pMem->flags & MEM_Blob );
        zP4 = "(blob)";
      }
      break;
    }
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    case P4_VTAB: {
      sqlite4_vtab *pVtab = pOp->p4.pVtab->pVtab;
      sqlite4_snprintf(zTemp, nTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
      break;
    }
#endif
    case P4_INTARRAY: {
      int i, j, n, cSep = '(';
      i = sqlite4_snprintf(zTemp, nTemp, "intarray");
      n = pOp->opcode==OP_Permutation ? pOp->p1 : 0;
      for(j=0; j<n; j++){
        i += sqlite4_snprintf(zTemp+i, nTemp-i,"%c%d",cSep, pOp->p4.ai[j]);
        cSep = ',';
      }
      sqlite4_snprintf(zTemp+i, nTemp-i, ")");
      break;
    }
    case P4_SUBPROGRAM: {
      sqlite4_snprintf(zTemp, nTemp, "program");
      break;
    }
    case P4_ADVANCE: {
      zTemp[0] = 0;
      break;
    }
    default: {
      if( pOp->opcode==OP_Blob ){
        int n = pOp->p1*2+2;
        if( n>nTemp-2 ) n = nTemp-2;
        zTemp[0] = 'x';
        zTemp[1] = '\'';
        sqlite4BlobToHex((n-2)/2,pOp->p4.z,zTemp+2);
        zTemp[n] = '\'';
        zTemp[n+1] = 0;
      }else{
        zP4 = pOp->p4.z;
        if( zP4==0 ){
          zP4 = zTemp;
          zTemp[0] = 0;
        }
      }
    }
  }
  assert( zP4!=0 );
  return zP4;
}
#endif

/*
** Declare to the Vdbe that the database at db->aDb[i] is used.
*/
SQLITE4_PRIVATE void sqlite4VdbeUsesStorage(Vdbe *p, int i){
  assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
}


#if defined(VDBE_PROFILE) || defined(SQLITE4_DEBUG)
/*
** Print a single opcode.  This routine is used for debugging only.
*/
SQLITE4_PRIVATE void sqlite4VdbePrintOp(FILE *pOut, int pc, Op *pOp){
  char *zP4;
  char zPtr[150];
  static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
  if( pOut==0 ) pOut = stdout;
  zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
  fprintf(pOut, zFormat1, pc, 
      sqlite4OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
#ifdef SQLITE4_DEBUG
      pOp->zComment ? pOp->zComment : ""
#else
      ""
#endif
  );
  fflush(pOut);
}
#endif

/*
** Release an array of N Mem elements
*/
static void releaseMemArray(Mem *p, int N){
  if( p && N ){
    Mem *pEnd;
    sqlite4 *db = p->db;
    u8 malloc_failed = db->mallocFailed;
    if( db->pnBytesFreed ){
      for(pEnd=&p[N]; p<pEnd; p++){
        sqlite4DbFree(db, p->zMalloc);
      }
      return;
    }
    for(pEnd=&p[N]; p<pEnd; p++){
      assert( (&p[1])==pEnd || p[0].db==p[1].db );

      /* This block is really an inlined version of sqlite4VdbeMemRelease()
      ** that takes advantage of the fact that the memory cell value is 
      ** being set to NULL after releasing any dynamic resources.
      **
      ** The justification for duplicating code is that according to 
      ** callgrind, this causes a certain test case to hit the CPU 4.7 
      ** percent less (x86 linux, gcc version 4.1.2, -O6) than if 
      ** sqlite4MemRelease() were called from here. With -O2, this jumps
      ** to 6.6 percent. The test case is inserting 1000 rows into a table 
      ** with no indexes using a single prepared INSERT statement, bind() 
      ** and reset(). Inserts are grouped into a transaction.
      */
      if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
        sqlite4VdbeMemRelease(p);
      }else if( p->zMalloc ){
        sqlite4DbFree(db, p->zMalloc);
        p->zMalloc = 0;
      }

      p->flags = MEM_Invalid;
    }
    db->mallocFailed = malloc_failed;
  }
}

/*
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
** allocated by the OP_Program opcode in sqlite4VdbeExec().
*/
SQLITE4_PRIVATE void sqlite4VdbeFrameDelete(VdbeFrame *p){
  int i;
  Mem *aMem = VdbeFrameMem(p);
  VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
  for(i=0; i<p->nChildCsr; i++){
    sqlite4VdbeFreeCursor(apCsr[i]);
  }
  releaseMemArray(aMem, p->nChildMem);
  sqlite4DbFree(p->v->db, p);
}

#ifndef SQLITE4_OMIT_EXPLAIN
/*
** Give a listing of the program in the virtual machine.
**
** The interface is the same as sqlite4VdbeExec().  But instead of
** running the code, it invokes the callback once for each instruction.
** This feature is used to implement "EXPLAIN".
**
** When p->explain==1, each instruction is listed.  When
** p->explain==2, only OP_Explain instructions are listed and these
** are shown in a different format.  p->explain==2 is used to implement
** EXPLAIN QUERY PLAN.
**
** When p->explain==1, first the main program is listed, then each of
** the trigger subprograms are listed one by one.
*/
SQLITE4_PRIVATE int sqlite4VdbeList(
  Vdbe *p                   /* The VDBE */
){
  int nRow;                            /* Stop when row count reaches this */
  int nSub = 0;                        /* Number of sub-vdbes seen so far */
  SubProgram **apSub = 0;              /* Array of sub-vdbes */
  Mem *pSub = 0;                       /* Memory cell hold array of subprogs */
  sqlite4 *db = p->db;                 /* The database connection */
  int i;                               /* Loop counter */
  int rc = SQLITE4_OK;                  /* Return code */
  Mem *pMem = &p->aMem[1];             /* First Mem of result set */

  assert( p->explain );
  assert( p->magic==VDBE_MAGIC_RUN );
  assert( p->rc==SQLITE4_OK || p->rc==SQLITE4_BUSY || p->rc==SQLITE4_NOMEM );

  /* Even though this opcode does not use dynamic strings for
  ** the result, result columns may become dynamic if the user calls
  ** sqlite4_column_text16(), causing a translation to UTF-16 encoding.
  */
  releaseMemArray(pMem, 8);
  p->pResultSet = 0;

  if( p->rc==SQLITE4_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite4_column_text() or
    ** sqlite4_column_text16() failed.  */
    db->mallocFailed = 1;
    return SQLITE4_ERROR;
  }

  /* When the number of output rows reaches nRow, that means the
  ** listing has finished and sqlite4_step() should return SQLITE4_DONE.
  ** nRow is the sum of the number of rows in the main program, plus
  ** the sum of the number of rows in all trigger subprograms encountered
  ** so far.  The nRow value will increase as new trigger subprograms are
  ** encountered, but p->pc will eventually catch up to nRow.
  */
  nRow = p->nOp;
  if( p->explain==1 ){
    /* The first 8 memory cells are used for the result set.  So we will
    ** commandeer the 9th cell to use as storage for an array of pointers
    ** to trigger subprograms.  The VDBE is guaranteed to have at least 9
    ** cells.  */
    assert( p->nMem>9 );
    pSub = &p->aMem[9];
    if( pSub->flags&MEM_Blob ){
      /* On the first call to sqlite4_step(), pSub will hold a NULL.  It is
      ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
      nSub = pSub->n/sizeof(Vdbe*);
      apSub = (SubProgram **)pSub->z;
    }
    for(i=0; i<nSub; i++){
      nRow += apSub[i]->nOp;
    }
  }

  do{
    i = p->pc++;
  }while( i<nRow && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
  if( i>=nRow ){
    p->rc = SQLITE4_OK;
    rc = SQLITE4_DONE;
  }else if( db->u1.isInterrupted ){
    p->rc = SQLITE4_INTERRUPT;
    rc = SQLITE4_ERROR;
    sqlite4SetString(&p->zErrMsg, db, "%s", sqlite4ErrStr(p->rc));
  }else{
    char *z;
    Op *pOp;
    if( i<p->nOp ){
      /* The output line number is small enough that we are still in the
      ** main program. */
      pOp = &p->aOp[i];
    }else{
      /* We are currently listing subprograms.  Figure out which one and
      ** pick up the appropriate opcode. */
      int j;
      i -= p->nOp;
      for(j=0; i>=apSub[j]->nOp; j++){
        i -= apSub[j]->nOp;
      }
      pOp = &apSub[j]->aOp[i];
    }
    if( p->explain==1 ){
      pMem->flags = MEM_Int;
      pMem->type = SQLITE4_INTEGER;
      pMem->u.num = sqlite4_num_from_int64(i);             /* Program counter */
      pMem++;
  
      pMem->flags = MEM_Static|MEM_Str|MEM_Term;
      pMem->z = (char*)sqlite4OpcodeName(pOp->opcode);     /* Opcode */
      assert( pMem->z!=0 );
      pMem->n = sqlite4Strlen30(pMem->z);
      pMem->type = SQLITE4_TEXT;
      pMem->enc = SQLITE4_UTF8;
      pMem++;

      /* When an OP_Program opcode is encounter (the only opcode that has
      ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
      ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
      ** has not already been seen.
      */
      if( pOp->p4type==P4_SUBPROGRAM ){
        int nByte = (nSub+1)*sizeof(SubProgram*);
        int j;
        for(j=0; j<nSub; j++){
          if( apSub[j]==pOp->p4.pProgram ) break;
        }
        if( j==nSub && SQLITE4_OK==sqlite4VdbeMemGrow(pSub, nByte, 1) ){
          apSub = (SubProgram **)pSub->z;
          apSub[nSub++] = pOp->p4.pProgram;
          pSub->flags |= MEM_Blob;
          pSub->n = nSub*sizeof(SubProgram*);
        }
      }
    }

    pMem->flags = MEM_Int;
    pMem->u.num = sqlite4_num_from_int64(pOp->p1);         /* P1 */
    pMem->type = SQLITE4_INTEGER;
    pMem++;

    pMem->flags = MEM_Int;
    pMem->u.num = sqlite4_num_from_int64(pOp->p2);         /* P2 */
    pMem->type = SQLITE4_INTEGER;
    pMem++;

    pMem->flags = MEM_Int;
    pMem->u.num = sqlite4_num_from_int64(pOp->p3);         /* P3 */
    pMem->type = SQLITE4_INTEGER;
    pMem++;

    if( sqlite4VdbeMemGrow(pMem, 150, 0) ){                /* P4 */
      assert( p->db->mallocFailed );
      return SQLITE4_ERROR;
    }
    pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
    z = displayP4(pOp, pMem->z, 150);
    if( z!=pMem->z ){
      sqlite4VdbeMemSetStr(pMem, z, -1, SQLITE4_UTF8, 0, 0);
    }else{
      assert( pMem->z!=0 );
      pMem->n = sqlite4Strlen30(pMem->z);
      pMem->enc = SQLITE4_UTF8;
    }
    pMem->type = SQLITE4_TEXT;
    pMem++;

    if( p->explain==1 ){
      if( sqlite4VdbeMemGrow(pMem, 4, 0) ){
        assert( p->db->mallocFailed );
        return SQLITE4_ERROR;
      }
      pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
      pMem->n = 2;
      sqlite4_snprintf(pMem->z, 3, "%.2x", pOp->p5);   /* P5 */
      pMem->type = SQLITE4_TEXT;
      pMem->enc = SQLITE4_UTF8;
      pMem++;
  
#ifdef SQLITE4_DEBUG
      if( pOp->zComment ){
        pMem->flags = MEM_Str|MEM_Term;
        pMem->z = pOp->zComment;
        pMem->n = sqlite4Strlen30(pMem->z);
        pMem->enc = SQLITE4_UTF8;
        pMem->type = SQLITE4_TEXT;
      }else
#endif
      {
        pMem->flags = MEM_Null;                       /* Comment */
        pMem->type = SQLITE4_NULL;
      }
    }

    p->nResColumn = 8 - 4*(p->explain-1);
    p->pResultSet = &p->aMem[1];
    p->rc = SQLITE4_OK;
    rc = SQLITE4_ROW;
  }
  return rc;
}
#endif /* SQLITE4_OMIT_EXPLAIN */

#ifdef SQLITE4_DEBUG
/*
** Print the SQL that was used to generate a VDBE program.
*/
SQLITE4_PRIVATE void sqlite4VdbePrintSql(Vdbe *p){
  int nOp = p->nOp;
  VdbeOp *pOp;
  if( nOp<1 ) return;
  pOp = &p->aOp[0];
  if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
    const char *z = pOp->p4.z;
    while( sqlite4Isspace(*z) ) z++;
    printf("SQL: [%s]\n", z);
  }
}
#endif

#if !defined(SQLITE4_OMIT_TRACE) && defined(SQLITE4_ENABLE_IOTRACE)
/*
** Print an IOTRACE message showing SQL content.
*/
SQLITE4_PRIVATE void sqlite4VdbeIOTraceSql(Vdbe *p){
  int nOp = p->nOp;
  VdbeOp *pOp;
  if( sqlite4IoTrace==0 ) return;
  if( nOp<1 ) return;
  pOp = &p->aOp[0];
  if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
    int i, j;
    char z[1000];
    sqlite4_snprintf(z, sizeof(z), "%s", pOp->p4.z);
    for(i=0; sqlite4Isspace(z[i]); i++){}
    for(j=0; z[i]; i++){
      if( sqlite4Isspace(z[i]) ){
        if( z[i-1]!=' ' ){
          z[j++] = ' ';
        }
      }else{
        z[j++] = z[i];
      }
    }
    z[j] = 0;
    sqlite4IoTrace("SQL %s\n", z);
  }
}
#endif /* !SQLITE4_OMIT_TRACE && SQLITE4_ENABLE_IOTRACE */

/*
** Allocate space from a fixed size buffer and return a pointer to
** that space.  If insufficient space is available, return NULL.
**
** The pBuf parameter is the initial value of a pointer which will
** receive the new memory.  pBuf is normally NULL.  If pBuf is not
** NULL, it means that memory space has already been allocated and that
** this routine should not allocate any new memory.  When pBuf is not
** NULL simply return pBuf.  Only allocate new memory space when pBuf
** is NULL.
**
** nByte is the number of bytes of space needed.
**
** *ppFrom points to available space and pEnd points to the end of the
** available space.  When space is allocated, *ppFrom is advanced past
** the end of the allocated space.
**
** *pnByte is a counter of the number of bytes of space that have failed
** to allocate.  If there is insufficient space in *ppFrom to satisfy the
** request, then increment *pnByte by the amount of the request.
*/
static void *allocSpace(
  void *pBuf,          /* Where return pointer will be stored */
  int nByte,           /* Number of bytes to allocate */
  u8 **ppFrom,         /* IN/OUT: Allocate from *ppFrom */
  u8 *pEnd,            /* Pointer to 1 byte past the end of *ppFrom buffer */
  int *pnByte          /* If allocation cannot be made, increment *pnByte */
){
  assert( EIGHT_BYTE_ALIGNMENT(*ppFrom) );
  if( pBuf ) return pBuf;
  nByte = ROUND8(nByte);
  if( &(*ppFrom)[nByte] <= pEnd ){
    pBuf = (void*)*ppFrom;
    *ppFrom += nByte;
  }else{
    *pnByte += nByte;
  }
  return pBuf;
}

/*
** Rewind the VDBE back to the beginning in preparation for
** running it.
*/
SQLITE4_PRIVATE void sqlite4VdbeRewind(Vdbe *p){
#if defined(SQLITE4_DEBUG) || defined(VDBE_PROFILE)
  int i;
#endif
  assert( p!=0 );
  assert( p->magic==VDBE_MAGIC_INIT );

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

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

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

/*
** Prepare a virtual machine for execution for the first time after
** creating the virtual machine.  This involves things such
** as allocating stack space and initializing the program counter.
** After the VDBE has be prepped, it can be executed by one or more
** calls to sqlite4VdbeExec().  
**
** This function may be called exact once on a each virtual machine.
** After this routine is called the VM has been "packaged" and is ready
** to run.  After this routine is called, futher calls to 
** sqlite4VdbeAddOp() functions are prohibited.  This routine disconnects
** the Vdbe from the Parse object that helped generate it so that the
** the Vdbe becomes an independent entity and the Parse object can be
** destroyed.
**
** Use the sqlite4VdbeRewind() procedure to restore a virtual machine back
** to its initial state after it has been run.
*/
SQLITE4_PRIVATE void sqlite4VdbeMakeReady(
  Vdbe *p,                       /* The VDBE */
  Parse *pParse                  /* Parsing context */
){
  sqlite4 *db;                   /* The database connection */
  int nVar;                      /* Number of parameters */
  int nMem;                      /* Number of VM memory registers */
  int nCursor;                   /* Number of cursors required */
  int nArg;                      /* Number of arguments in subprograms */
  int nOnce;                     /* Number of OP_Once instructions */
  int n;                         /* Loop counter */
  u8 *zCsr;                      /* Memory available for allocation */
  u8 *zEnd;                      /* First byte past allocated memory */
  int nByte;                     /* How much extra memory is needed */

  assert( p!=0 );
  assert( p->nOp>0 );
  assert( pParse!=0 );
  assert( p->magic==VDBE_MAGIC_INIT );
  db = p->db;
  assert( db->mallocFailed==0 );
  nVar = pParse->nVar;
  nMem = pParse->nMem;
  nCursor = pParse->nTab;
  nArg = pParse->nMaxArg;
  nOnce = pParse->nOnce;
  if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */
  
  /* For each cursor required, also allocate a memory cell. Memory
  ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by
  ** the vdbe program. Instead they are used to allocate space for
  ** VdbeCursor/BtCursor structures. The blob of memory associated with 
  ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1)
  ** stores the blob of memory associated with cursor 1, etc.
  **
  ** See also: allocateCursor().
  */
  nMem += nCursor;

  /* Allocate space for memory registers, SQL variables, VDBE cursors and 
  ** an array to marshal SQL function arguments in.
  */
  zCsr = (u8*)&p->aOp[p->nOp];       /* Memory avaliable for allocation */
  zEnd = (u8*)&p->aOp[p->nOpAlloc];  /* First byte past end of zCsr[] */

  resolveP2Values(p, &nArg);
  p->needSavepoint = (u8)(pParse->isMultiWrite && pParse->mayAbort);
  if( pParse->explain && nMem<10 ){
    nMem = 10;
  }
  memset(zCsr, 0, zEnd-zCsr);
  zCsr += (zCsr - (u8*)0)&7;
  assert( EIGHT_BYTE_ALIGNMENT(zCsr) );
  p->expired = 0;

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

  p->nCursor = (u16)nCursor;
  p->nOnceFlag = nOnce;
  if( p->aVar ){
    p->nVar = (ynVar)nVar;
    for(n=0; n<nVar; n++){
      p->aVar[n].flags = MEM_Null;
      p->aVar[n].db = db;
    }
  }
  if( p->azVar ){
    p->nzVar = pParse->nzVar;
    memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
    memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
  }
  if( p->aMem ){
    p->aMem--;                      /* aMem[] goes from 1..nMem */
    p->nMem = nMem;                 /*       not from 0..nMem-1 */
    for(n=1; n<=nMem; n++){
      p->aMem[n].flags = MEM_Invalid;
      p->aMem[n].db = db;
    }
  }
  p->explain = pParse->explain;
  sqlite4VdbeRewind(p);
}

/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
** control to the main program.
*/
SQLITE4_PRIVATE int sqlite4VdbeFrameRestore(VdbeFrame *pFrame){
  Vdbe *v = pFrame->v;
  v->aOnceFlag = pFrame->aOnceFlag;
  v->nOnceFlag = pFrame->nOnceFlag;
  v->aOp = pFrame->aOp;
  v->nOp = pFrame->nOp;
  v->aMem = pFrame->aMem;
  v->nMem = pFrame->nMem;
  v->apCsr = pFrame->apCsr;
  v->nCursor = pFrame->nCursor;
  v->nChange = pFrame->nChange;
  return pFrame->pc;
}

/*
** Close all cursors.
**
** Also release any dynamic memory held by the VM in the Vdbe.aMem memory 
** cell array. This is necessary as the memory cell array may contain
** pointers to VdbeFrame objects, which may in turn contain pointers to
** open cursors.
*/
static void closeAllCursors(Vdbe *p){
  if( p->pFrame ){
    VdbeFrame *pFrame;
    for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
    sqlite4VdbeFrameRestore(pFrame);
  }
  p->pFrame = 0;
  p->nFrame = 0;

  if( p->apCsr ){
    int i;
    for(i=0; i<p->nCursor; i++){
      VdbeCursor *pC = p->apCsr[i];
      if( pC ){
        sqlite4VdbeFreeCursor(pC);
        p->apCsr[i] = 0;
      }
    }
  }
  if( p->aMem ){
    releaseMemArray(&p->aMem[1], p->nMem);
  }
  while( p->pDelFrame ){
    VdbeFrame *pDel = p->pDelFrame;
    p->pDelFrame = pDel->pParent;
    sqlite4VdbeFrameDelete(pDel);
  }
}

/*
** Clean up the VM after execution.
**
** This routine will automatically close any cursors, lists, and/or
** sorters that were left open.
*/
static void Cleanup(Vdbe *p){
  sqlite4 *db = p->db;

#ifdef SQLITE4_DEBUG
  /* Execute assert() statements to ensure that the Vdbe.apCsr[] and 
  ** Vdbe.aMem[] arrays have already been cleaned up.  */
  int i;
  if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
  if( p->aMem ){
    for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
  }
#endif

  sqlite4DbFree(db, p->zErrMsg);
  p->zErrMsg = 0;
  p->pResultSet = 0;
}

/*
** Set the number of result columns that will be returned by this SQL
** statement. This is now set at compile time, rather than during
** execution of the vdbe program so that sqlite4_column_count() can
** be called on an SQL statement before sqlite4_step().
*/
SQLITE4_PRIVATE void sqlite4VdbeSetNumCols(Vdbe *p, int nResColumn){
  Mem *pColName;
  int n;
  sqlite4 *db = p->db;

  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
  sqlite4DbFree(db, p->aColName);
  n = nResColumn*COLNAME_N;
  p->nResColumn = (u16)nResColumn;
  p->aColName = pColName = (Mem*)sqlite4DbMallocZero(db, sizeof(Mem)*n );
  if( p->aColName==0 ) return;
  while( n-- > 0 ){
    pColName->flags = MEM_Null;
    pColName->db = p->db;
    pColName++;
  }
}

/*
** Set the name of the idx'th column to be returned by the SQL statement.
** zName must be a pointer to a nul terminated string.
**
** This call must be made after a call to sqlite4VdbeSetNumCols().
**
** The final parameter, xDel, must be one of SQLITE4_DYNAMIC, SQLITE4_STATIC
** or SQLITE4_TRANSIENT. If it is SQLITE4_DYNAMIC, then the buffer pointed
** to by zName will be freed by sqlite4DbFree() when the vdbe is destroyed.
*/
SQLITE4_PRIVATE int sqlite4VdbeSetColName(
  Vdbe *p,                         /* Vdbe being configured */
  int idx,                         /* Index of column zName applies to */
  int var,                         /* One of the COLNAME_* constants */
  const char *zName,               /* Pointer to buffer containing name */
  void (*xDel)(void*,void*)        /* Memory management strategy for zName */
){
  int rc;
  Mem *pColName;
  assert( idx<p->nResColumn );
  assert( var<COLNAME_N );
  assert( xDel==SQLITE4_STATIC || xDel==SQLITE4_TRANSIENT
             || xDel==SQLITE4_DYNAMIC );
  if( p->db->mallocFailed ){
    assert( !zName || xDel!=SQLITE4_DYNAMIC );
    return SQLITE4_NOMEM;
  }
  assert( p->aColName!=0 );
  pColName = &(p->aColName[idx+var*p->nResColumn]);
  rc = sqlite4VdbeMemSetStr(pColName, zName, -1, SQLITE4_UTF8, xDel, 0);
  assert( rc!=0 || !zName || (pColName->flags&MEM_Term)!=0 );
  return rc;
}

/*
** Free all Savepoint structures that correspond to transaction levels
** larger than iLevel. Passing iLevel==1 deletes all Savepoint structures.
** iLevel==2 deletes all except for the outermost. And so on.
*/
static void freeSavepoints(sqlite4 *db, int iLevel){
  if( iLevel<1 ) iLevel = 1;
  while( (iLevel-1)<db->nSavepoint ){
    Savepoint *pDel = db->pSavepoint;
    db->pSavepoint = pDel->pNext;
    db->nSavepoint--;
    sqlite4DbFree(db, pDel);
  }
}

#ifdef SQLITE4_DEBUG
static int countSavepoints(sqlite4 *db){
  int nRet = 0;
  Savepoint *p;
  for(p=db->pSavepoint; p; p=p->pNext) nRet++;
  return nRet;
}
#endif

/*
** Rollback to transaction level iLevel. iLevel is as defined by the kv-store
** layer. For example, if the user has done:
**
**   BEGIN;
**     write 1;
**       SAVEPOINT one;
**         write 2;
**           SAVEPOINT two;
**             write 3;
**
** then:
**
**   iLevel==1     Roll back and close top-level transaction.
**   iLevel==2     Roll back top-level transaction. Transaction remains open.
**   iLevel==3     Roll back to just after "write 1". Savepoint "one" remains
**                 open. Savepoint "two" is closed.
**   iLevel==4     Roll back to just after "write 2". Both savepoints remain
**                 open (but "write 3" has been backed out).
*/
SQLITE4_PRIVATE int sqlite4VdbeRollback(sqlite4 *db, int iLevel){
  int i;
  assert( sqlite4_mutex_held(db->mutex) );
  assert( db->nSavepoint==countSavepoints(db) );

  /* Invoke the xRollback() hook on all backends. */
  sqlite4BeginBenignMalloc(db->pEnv);
  for(i=0; i<db->nDb; i++){
    KVStore *pKV = db->aDb[i].pKV;
    if( pKV && pKV->iTransLevel>=iLevel ){
      sqlite4KVStoreRollback(pKV, iLevel);
    }
  }
  sqlite4EndBenignMalloc(db->pEnv);

  /* If the InternChanges flag is set, expire prepared statements and
  ** reload the schema. If this is not a rollback of the top-level 
  ** transaction, do not clear the SQLITE4_InternChanges flag.  */ 
  if( db->flags&SQLITE4_InternChanges ){
    sqlite4ExpirePreparedStatements(db);
    sqlite4ResetInternalSchema(db, -1);
    if( iLevel>2 ) db->flags |= SQLITE4_InternChanges;
  }

  /* Free elements from the db->pSavepoint list. Restore the deferred FK
  ** constraint counter to the value consistent with the restored database
  ** state.  */
  freeSavepoints(db, iLevel);
  db->nDeferredCons = (db->pSavepoint ? db->pSavepoint->nDeferredCons : 0);
  assert( db->nSavepoint==countSavepoints(db) );

  return SQLITE4_OK;
}

/*
** Commit to transaction level iLevel.
*/
SQLITE4_PRIVATE int sqlite4VdbeCommit(sqlite4 *db, int iLevel){
  int rc = SQLITE4_OK;
  int i;
  assert( sqlite4_mutex_held(db->mutex) );
  assert( db->nSavepoint==countSavepoints(db) );
  assert( iLevel>1 || db->nDeferredCons==0 );

  /* Invoke the xCommit() hook on all backends. */
  for(i=0; rc==SQLITE4_OK && i<db->nDb; i++){
    KVStore *pKV = db->aDb[i].pKV;
    if( pKV && pKV->iTransLevel>iLevel ){
      rc = sqlite4KVStoreCommit(pKV, iLevel);
    }
  }

  if( rc!=SQLITE4_OK ){
    sqlite4VdbeRollback(db, 1);
  }else{
    freeSavepoints(db, iLevel);
  }
  assert( db->nSavepoint==countSavepoints(db) );
  return rc;
}

static int vdbeCloseStatement(Vdbe *p, int bRollback){
  int i;
  int rc = SQLITE4_OK;
  sqlite4 *db = p->db;

  for(i=0; rc==SQLITE4_OK && i<db->nDb; i++){
    if( p->stmtTransMask & ((yDbMask)1)<<i ){
      KVStore *pKV = db->aDb[i].pKV;
      assert( pKV->iTransLevel>2 );
      if( bRollback ){
        rc = sqlite4KVStoreRollback(pKV, pKV->iTransLevel);
      }
      if( rc==SQLITE4_OK ){
        rc = sqlite4KVStoreCommit(pKV, pKV->iTransLevel-1);
      }
    }
  }

  if( bRollback ){
    p->db->nDeferredCons = p->nStmtDefCons;
  }

  if( rc ){
    sqlite4VdbeRollback(db, 1);
  }
  return rc;
}

/* 
** This routine checks that the sqlite4.activeVdbeCnt count variable
** matches the number of vdbe's in the list sqlite4.pVdbe that are
** currently active. An assertion fails if the two counts do not match.
** This is an internal self-check only - it is not an essential processing
** step.
**
** This is a no-op if NDEBUG is defined.
*/
#ifndef NDEBUG
static void checkActiveVdbeCnt(sqlite4 *db){
  Vdbe *p;
  int cnt = 0;
  int nWrite = 0;
  p = db->pVdbe;
  while( p ){
    if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){
      cnt++;
      if( p->readOnly==0 ) nWrite++;
    }
    p = p->pNext;
  }
  assert( cnt==db->activeVdbeCnt );
  assert( nWrite==db->writeVdbeCnt );
}
#else
#define checkActiveVdbeCnt(x)
#endif

/*
** If the Vdbe passed as the first argument opened a statement-transaction,
** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
** SAVEPOINT_RELEASE. If it is SAVEPOINT_ROLLBACK, then the statement
** transaction is rolled back. If eOp is SAVEPOINT_RELEASE, then the 
** statement transaction is commtted.
**
** If an IO error occurs, an SQLITE4_IOERR_XXX error code is returned. 
** Otherwise SQLITE4_OK.
*/
SQLITE4_PRIVATE int sqlite4VdbeCloseStatement(Vdbe *p, int eOp){
  return SQLITE4_OK;
}



/*
** This function is called when a transaction opened by the database 
** handle associated with the VM passed as an argument is about to be 
** committed. If there are outstanding deferred foreign key constraint
** violations, return SQLITE4_ERROR. Otherwise, SQLITE4_OK.
**
** If there are outstanding FK violations and this function returns 
** SQLITE4_ERROR, set the result of the VM to SQLITE4_CONSTRAINT and write
** an error message to it. Then return SQLITE4_ERROR.
*/
#ifndef SQLITE4_OMIT_FOREIGN_KEY
SQLITE4_PRIVATE int sqlite4VdbeCheckFk(Vdbe *p, int deferred){
  sqlite4 *db = p->db;
  if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
    p->rc = SQLITE4_CONSTRAINT;
    p->errorAction = OE_Abort;
    sqlite4SetString(&p->zErrMsg, db, "foreign key constraint failed");
    return SQLITE4_ERROR;
  }
  return SQLITE4_OK;
}
#endif

/*
** This routine is called the when a VDBE tries to halt.  If the VDBE
** has made changes and is in autocommit mode, then commit those
** changes.  If a rollback is needed, then do the rollback.
**
** This routine is the only way to move the state of a VM from
** SQLITE4_MAGIC_RUN to SQLITE4_MAGIC_HALT.  It is harmless to
** call this on a VM that is in the SQLITE4_MAGIC_HALT state.
**
** Return an error code.  If the commit could not complete because of
** lock contention, return SQLITE4_BUSY.  If SQLITE4_BUSY is returned, it
** means the close did not happen and needs to be repeated.
*/
SQLITE4_PRIVATE int sqlite4VdbeHalt(Vdbe *p){
  sqlite4 *db = p->db;

  if( db->mallocFailed ) p->rc = SQLITE4_NOMEM;
  if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag);
  closeAllCursors(p);
  if( p->magic!=VDBE_MAGIC_RUN ){
    return SQLITE4_OK;
  }
  checkActiveVdbeCnt(db);

  if( p->pc>=0 ){
    /* Figure out if a transaction or statement transaction needs to be
    ** committed or rolled back.
    **
    **    0 - Do commit, either statement or transaction.
    **    1 - Do rollback, either statement or transaction.
    **    2 - Do transaction rollback.
    */
    int eAction = (p->rc!=SQLITE4_OK);

    if( p->rc==SQLITE4_CONSTRAINT ){
      if( p->errorAction==OE_Rollback ){
        eAction = 2;
      }else if( p->errorAction==OE_Fail ){
        eAction = 0;
      }
    }
    if( eAction==0 && sqlite4VdbeCheckFk(p, 0) ) eAction = 1;

    if( eAction==2 || (
       db->writeVdbeCnt==(p->readOnly==0) && db->pSavepoint==0
    )){

      if( eAction==0 && sqlite4VdbeCheckFk(p, 1) ) eAction = 1;
      if( eAction==0 ){
        int rc = sqlite4VdbeCommit(db, 1);
        if( rc!=SQLITE4_OK ){
          p->rc = rc;
          eAction = 1;
        }else{
          assert( db->nDeferredCons<=0 );
          sqlite4CommitInternalChanges(db);
        }
      }

      if( eAction ){
        sqlite4VdbeRollback(db, 1);
      }

      db->nDeferredCons = 0;
    }else if( p->stmtTransMask ){
      /* Auto-commit mode is turned off and no "OR ROLLBACK" constraint was
      ** encountered. So either commit (if eAction==0) or rollback (if 
      ** eAction==1) any statement transactions opened by this VM.  */
      assert( eAction==0 || eAction==1 );
      vdbeCloseStatement(p, eAction);
    }

    if( p->changeCntOn ){
      sqlite4VdbeSetChanges(db, (eAction ? 0 : p->nChange));
    }
    p->nChange = 0;

    /* We have successfully halted and closed the VM.  Record this fact. */
    db->activeVdbeCnt--;
    if( !p->readOnly ){
      db->writeVdbeCnt--;
    }
    assert( db->activeVdbeCnt>=db->writeVdbeCnt );

    if( db->pSavepoint==0 && db->activeVdbeCnt==0 ){
      sqlite4VdbeRollback(db, 0);
    }
  }

  p->magic = VDBE_MAGIC_HALT;
  checkActiveVdbeCnt(db);
  if( p->db->mallocFailed ){
    p->rc = SQLITE4_NOMEM;
  }
  return (p->rc==SQLITE4_BUSY ? SQLITE4_BUSY : SQLITE4_OK);
}


/*
** Each VDBE holds the result of the most recent sqlite4_step() call
** in p->rc.  This routine sets that result back to SQLITE4_OK.
*/
SQLITE4_PRIVATE void sqlite4VdbeResetStepResult(Vdbe *p){
  p->rc = SQLITE4_OK;
}

/*
** Copy the error code and error message belonging to the VDBE passed
** as the first argument to its database handle (so that they will be 
** returned by calls to sqlite4_errcode() and sqlite4_errmsg()).
**
** This function does not clear the VDBE error code or message, just
** copies them to the database handle.
*/
SQLITE4_PRIVATE int sqlite4VdbeTransferError(Vdbe *p){
  sqlite4 *db = p->db;
  int rc = p->rc;
  if( p->zErrMsg ){
    u8 mallocFailed = db->mallocFailed;
    sqlite4BeginBenignMalloc(db->pEnv);
    sqlite4ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE4_UTF8,
                       SQLITE4_TRANSIENT, 0);
    sqlite4EndBenignMalloc(db->pEnv);
    db->mallocFailed = mallocFailed;
    db->errCode = rc;
  }else{
    sqlite4Error(db, rc, 0);
  }
  return rc;
}

/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg.  Return the result code.
**
** After this routine is run, the VDBE should be ready to be executed
** again.
**
** To look at it another way, this routine resets the state of the
** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
** VDBE_MAGIC_INIT.
*/
SQLITE4_PRIVATE int sqlite4VdbeReset(Vdbe *p){
  sqlite4 *db;
  db = p->db;

  /* If the VM did not run to completion or if it encountered an
  ** error, then it might not have been halted properly.  So halt
  ** it now.
  */
  sqlite4VdbeHalt(p);

  /* If the VDBE has be run even partially, then transfer the error code
  ** and error message from the VDBE into the main database structure.  But
  ** if the VDBE has just been set to run but has not actually executed any
  ** instructions yet, leave the main database error information unchanged.
  */
  if( p->pc>=0 ){
    sqlite4VdbeTransferError(p);
    sqlite4DbFree(db, p->zErrMsg);
    p->zErrMsg = 0;
    if( p->runOnlyOnce ) p->expired = 1;
  }else if( p->rc && p->expired ){
    /* The expired flag was set on the VDBE before the first call
    ** to sqlite4_step(). For consistency (since sqlite4_step() was
    ** called), set the database error in this case as well.
    */
    sqlite4Error(db, p->rc, 0);
    sqlite4ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE4_UTF8,
                       SQLITE4_TRANSIENT, 0);
    sqlite4DbFree(db, p->zErrMsg);
    p->zErrMsg = 0;
  }

  /* Reclaim all memory used by the VDBE
  */
  Cleanup(p);

  /* Save profiling information from this VDBE run.
  */
#ifdef VDBE_PROFILE
  {
    FILE *out = fopen("vdbe_profile.out", "a");
    if( out ){
      int i;
      fprintf(out, "---- ");
      for(i=0; i<p->nOp; i++){
        fprintf(out, "%02x", p->aOp[i].opcode);
      }
      fprintf(out, "\n");
      for(i=0; i<p->nOp; i++){
        fprintf(out, "%6d %10lld %8lld ",
           p->aOp[i].cnt,
           p->aOp[i].cycles,
           p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
        );
        sqlite4VdbePrintOp(out, i, &p->aOp[i]);
      }
      fclose(out);
    }
  }
#endif
  p->magic = VDBE_MAGIC_INIT;
  return p->rc;
}
 
/*
** Clean up and delete a VDBE after execution.  Return an integer which is
** the result code.  Write any error message text into *pzErrMsg.
*/
SQLITE4_PRIVATE int sqlite4VdbeFinalize(Vdbe *p){
  int rc = SQLITE4_OK;
  if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
    rc = sqlite4VdbeReset(p);
  }
  sqlite4VdbeDelete(p);
  return rc;
}

/*
** Call the destructor for each auxdata entry in pVdbeFunc for which
** the corresponding bit in mask is clear.  Auxdata entries beyond 31
** are always destroyed.  To destroy all auxdata entries, call this
** routine with mask==0.
*/
SQLITE4_PRIVATE void sqlite4VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
  int i;
  for(i=0; i<pVdbeFunc->nAux; i++){
    struct AuxData *pAux = &pVdbeFunc->apAux[i];
    if( (i>31 || !(mask&(((u32)1)<<i))) && pAux->pAux ){
      if( pAux->xDelete ){
        pAux->xDelete(pAux->pDeleteArg, pAux->pAux);
      }
      pAux->pAux = 0;
    }
  }
}

/*
** Free all memory associated with the Vdbe passed as the second argument.
** The difference between this function and sqlite4VdbeDelete() is that
** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
** the database connection.
*/
SQLITE4_PRIVATE void sqlite4VdbeDeleteObject(sqlite4 *db, Vdbe *p){
  SubProgram *pSub, *pNext;
  int i;
  assert( p->db==0 || p->db==db );
  releaseMemArray(p->aVar, p->nVar);
  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
  for(pSub=p->pProgram; pSub; pSub=pNext){
    pNext = pSub->pNext;
    vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
    sqlite4DbFree(db, pSub);
  }
  for(i=p->nzVar-1; i>=0; i--) sqlite4DbFree(db, p->azVar[i]);
  vdbeFreeOpArray(db, p->aOp, p->nOp);
  sqlite4DbFree(db, p->aLabel);
  sqlite4DbFree(db, p->aColName);
  sqlite4DbFree(db, p->zSql);
  sqlite4DbFree(db, p->pFree);
#if defined(SQLITE4_ENABLE_TREE_EXPLAIN)
  sqlite4DbFree(db, p->zExplain);
  sqlite4DbFree(db, p->pExplain);
#endif
  sqlite4DbFree(db, p);
}

/*
** Delete an entire VDBE.
*/
SQLITE4_PRIVATE void sqlite4VdbeDelete(Vdbe *p){
  sqlite4 *db;

  if( NEVER(p==0) ) return;
  db = p->db;
  if( p->pPrev ){
    p->pPrev->pNext = p->pNext;
  }else{
    assert( db->pVdbe==p );
    db->pVdbe = p->pNext;
  }
  if( p->pNext ){
    p->pNext->pPrev = p->pPrev;
  }
  p->magic = VDBE_MAGIC_DEAD;
  p->db = 0;
  sqlite4VdbeDeleteObject(db, p);
}

/*
** If we are on an architecture with mixed-endian floating 
** points (ex: ARM7) then swap the lower 4 bytes with the 
** upper 4 bytes.  Return the result.
**
** For most architectures, this is a no-op.
**
** (later):  It is reported to me that the mixed-endian problem
** on ARM7 is an issue with GCC, not with the ARM7 chip.  It seems
** that early versions of GCC stored the two words of a 64-bit
** float in the wrong order.  And that error has been propagated
** ever since.  The blame is not necessarily with GCC, though.
** GCC might have just copying the problem from a prior compiler.
** I am also told that newer versions of GCC that follow a different
** ABI get the byte order right.
**
** Developers using SQLite on an ARM7 should compile and run their
** application using -DSQLITE4_DEBUG=1 at least once.  With DEBUG
** enabled, some asserts below will ensure that the byte order of
** floating point values is correct.
**
** (2007-08-30)  Frank van Vugt has studied this problem closely
** and has send his findings to the SQLite developers.  Frank
** writes that some Linux kernels offer floating point hardware
** emulation that uses only 32-bit mantissas instead of a full 
** 48-bits as required by the IEEE standard.  (This is the
** CONFIG_FPE_FASTFPE option.)  On such systems, floating point
** byte swapping becomes very complicated.  To avoid problems,
** the necessary byte swapping is carried out using a 64-bit integer
** rather than a 64-bit float.  Frank assures us that the code here
** works for him.  We, the developers, have no way to independently
** verify this, but Frank seems to know what he is talking about
** so we trust him.
*/
#ifdef SQLITE4_MIXED_ENDIAN_64BIT_FLOAT
static u64 floatSwap(u64 in){
  union {
    u64 r;
    u32 i[2];
  } u;
  u32 t;

  u.r = in;
  t = u.i[0];
  u.i[0] = u.i[1];
  u.i[1] = t;
  return u.r;
}
# define swapMixedEndianFloat(X)  X = floatSwap(X)
#else
# define swapMixedEndianFloat(X)
#endif


/*
** This routine sets the value to be returned by subsequent calls to
** sqlite4_changes() on the database handle 'db'. 
*/
SQLITE4_PRIVATE void sqlite4VdbeSetChanges(sqlite4 *db, int nChange){
  assert( sqlite4_mutex_held(db->mutex) );
  db->nChange = nChange;
  db->nTotalChange += nChange;
}

/*
** Set a flag in the vdbe to update the change counter when it is finalised
** or reset.
*/
SQLITE4_PRIVATE void sqlite4VdbeCountChanges(Vdbe *v){
  v->changeCntOn = 1;
}

/*
** Mark every prepared statement associated with a database connection
** as expired.
**
** An expired statement means that recompilation of the statement is
** recommend.  Statements expire when things happen that make their
** programs obsolete.  Removing user-defined functions or collating
** sequences, or changing an authorization function are the types of
** things that make prepared statements obsolete.
*/
SQLITE4_PRIVATE void sqlite4ExpirePreparedStatements(sqlite4 *db){
  Vdbe *p;
  for(p = db->pVdbe; p; p=p->pNext){
    p->expired = 1;
  }
}

/*
** Return the database associated with the Vdbe.
*/
SQLITE4_PRIVATE sqlite4 *sqlite4VdbeDb(Vdbe *v){
  return v->db;
}

/*
** Return a pointer to an sqlite4_value structure containing the value bound
** parameter iVar of VM v. Except, if the value is an SQL NULL, return 
** 0 instead. Unless it is NULL, apply affinity aff (one of the SQLITE4_AFF_*
** constants) to the value before returning it.
**
** The returned value must be freed by the caller using sqlite4ValueFree().
*/
SQLITE4_PRIVATE sqlite4_value *sqlite4VdbeGetValue(Vdbe *v, int iVar, u8 aff){
  assert( iVar>0 );
  if( v ){
    Mem *pMem = &v->aVar[iVar-1];
    if( 0==(pMem->flags & MEM_Null) ){
      sqlite4_value *pRet = sqlite4ValueNew(v->db);
      if( pRet ){
        sqlite4VdbeMemCopy((Mem *)pRet, pMem);
        sqlite4ValueApplyAffinity(pRet, aff, SQLITE4_UTF8);
        sqlite4VdbeMemStoreType((Mem *)pRet);
      }
      return pRet;
    }
  }
  return 0;
}

/*
** Configure SQL variable iVar so that binding a new value to it signals
** to sqlite4_reoptimize() that re-preparing the statement may result
** in a better query plan.
*/
SQLITE4_PRIVATE void sqlite4VdbeSetVarmask(Vdbe *v, int iVar){
  assert( iVar>0 );
  if( iVar>32 ){
    v->expmask = 0xffffffff;
  }else{
    v->expmask |= ((u32)1 << (iVar-1));
  }
}

/************** End of vdbeaux.c *********************************************/
/************** Begin file vdbeapi.c *****************************************/
/*
** 2004 May 26
**
** 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 use to implement APIs that are part of the
** VDBE.
*/

/*
** Check on a Vdbe to make sure it has not been finalized.  Log
** an error and return true if it has been finalized (or is otherwise
** invalid).  Return false if it is ok.
*/
static int vdbeSafety(Vdbe *p){
  if( p->db==0 ){
    sqlite4_log(0,SQLITE4_MISUSE,"API called with finalized prepared statement");
    return 1;
  }else{
    return 0;
  }
}
static int vdbeSafetyNotNull(Vdbe *p){
  if( p==0 ){
    sqlite4_log(0,SQLITE4_MISUSE, "API called with NULL prepared statement");
    return 1;
  }else{
    return vdbeSafety(p);
  }
}

/*
** The following routine destroys a virtual machine that is created by
** the sqlite4_compile() routine. The integer returned is an SQLITE4_
** success/failure code that describes the result of executing the virtual
** machine.
**
** This routine sets the error code and string returned by
** sqlite4_errcode(), sqlite4_errmsg() and sqlite4_errmsg16().
*/
SQLITE4_API int sqlite4_finalize(sqlite4_stmt *pStmt){
  int rc;
  if( pStmt==0 ){
    /* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite4_finalize() on a NULL
    ** pointer is a harmless no-op. */
    rc = SQLITE4_OK;
  }else{
    Vdbe *v = (Vdbe*)pStmt;
    sqlite4 *db = v->db;
#if SQLITE4_THREADSAFE
    sqlite4_mutex *mutex;
#endif
    if( vdbeSafety(v) ) return SQLITE4_MISUSE_BKPT;
#if SQLITE4_THREADSAFE
    mutex = v->db->mutex;
#endif
    sqlite4_mutex_enter(mutex);
    rc = sqlite4VdbeFinalize(v);
    rc = sqlite4ApiExit(db, rc);
    sqlite4_mutex_leave(mutex);
  }
  return rc;
}

/*
** Terminate the current execution of an SQL statement and reset it
** back to its starting state so that it can be reused. A success code from
** the prior execution is returned.
**
** This routine sets the error code and string returned by
** sqlite4_errcode(), sqlite4_errmsg() and sqlite4_errmsg16().
*/
SQLITE4_API int sqlite4_reset(sqlite4_stmt *pStmt){
  int rc;
  if( pStmt==0 ){
    rc = SQLITE4_OK;
  }else{
    Vdbe *v = (Vdbe*)pStmt;
    sqlite4_mutex_enter(v->db->mutex);
    rc = sqlite4VdbeReset(v);
    sqlite4VdbeRewind(v);
    rc = sqlite4ApiExit(v->db, rc);
    sqlite4_mutex_leave(v->db->mutex);
  }
  return rc;
}

/*
** Set all the parameters in the compiled SQL statement to NULL.
*/
SQLITE4_API int sqlite4_clear_bindings(sqlite4_stmt *pStmt){
  int i;
  int rc = SQLITE4_OK;
  Vdbe *p = (Vdbe*)pStmt;
#if SQLITE4_THREADSAFE
  sqlite4_mutex *mutex = ((Vdbe*)pStmt)->db->mutex;
#endif
  sqlite4_mutex_enter(mutex);
  for(i=0; i<p->nVar; i++){
    sqlite4VdbeMemRelease(&p->aVar[i]);
    p->aVar[i].flags = MEM_Null;
  }
  if( p->expmask ){
    p->expired = 1;
  }
  sqlite4_mutex_leave(mutex);
  return rc;
}


/**************************** sqlite4_value_  *******************************
** The following routines extract information from a Mem or sqlite4_value
** structure.
*/
SQLITE4_API const void *sqlite4_value_blob(sqlite4_value *pVal, int *pnByte){
  Mem *p = (Mem*)pVal;
  if( p->flags & (MEM_Blob|MEM_Str) ){
    p->flags &= ~MEM_Str;
    p->flags |= MEM_Blob;
    if( pnByte ) *pnByte = p->n;
    return p->n ? p->z : 0;
  }else{
    return sqlite4_value_text(pVal, pnByte);
  }
}
SQLITE4_API int sqlite4_value_bytes(sqlite4_value *pVal){
  return sqlite4ValueBytes(pVal, SQLITE4_UTF8);
}
SQLITE4_API int sqlite4_value_bytes16(sqlite4_value *pVal){
  return sqlite4ValueBytes(pVal, SQLITE4_UTF16NATIVE);
}
SQLITE4_API double sqlite4_value_double(sqlite4_value *pVal){
  return sqlite4VdbeRealValue((Mem*)pVal);
}
SQLITE4_API int sqlite4_value_int(sqlite4_value *pVal){
  return (int)sqlite4VdbeIntValue((Mem*)pVal);
}
SQLITE4_API sqlite4_int64 sqlite4_value_int64(sqlite4_value *pVal){
  return sqlite4VdbeIntValue((Mem*)pVal);
}
SQLITE4_API const char *sqlite4_value_text(sqlite4_value *pVal, int *pnByte){
  const char *zRet = (const char *)sqlite4ValueText(pVal, SQLITE4_UTF8);
  if( pnByte ) *pnByte = (zRet ? ((Mem *)pVal)->n : 0);
  return zRet;
}
#ifndef SQLITE4_OMIT_UTF16
SQLITE4_API const void *sqlite4_value_text16(sqlite4_value* pVal, int *pnByte){
  const void *pRet = sqlite4ValueText(pVal, SQLITE4_UTF16NATIVE);
  if( pnByte ) *pnByte = (pRet ? ((Mem *)pVal)->n : 0);
  return pRet;
}
SQLITE4_API const void *sqlite4_value_text16be(sqlite4_value *pVal, int *pnByte){
  const void *pRet = sqlite4ValueText(pVal, SQLITE4_UTF16BE);
  if( pnByte ) *pnByte = (pRet ? ((Mem *)pVal)->n : 0);
  return pRet;
}
SQLITE4_API const void *sqlite4_value_text16le(sqlite4_value *pVal, int *pnByte){
  const void *pRet = sqlite4ValueText(pVal, SQLITE4_UTF16LE);
  if( pnByte ) *pnByte = (pRet ? ((Mem *)pVal)->n : 0);
  return pRet;
}
#endif /* SQLITE4_OMIT_UTF16 */
SQLITE4_API int sqlite4_value_type(sqlite4_value* pVal){
  return pVal->type;
}

/**************************** sqlite4_result_  *******************************
** The following routines are used by user-defined functions to specify
** the function result.
**
** The setStrOrError() funtion calls sqlite4VdbeMemSetStr() to store the
** result as a string or blob but if the string or blob is too large, it
** then sets the error code to SQLITE4_TOOBIG
*/
static void setResultStrOrError(
  sqlite4_context *pCtx,     /* Function context */
  const char *z,             /* String pointer */
  int n,                     /* Bytes in string, or negative */
  u8 enc,                    /* Encoding of z.  0 for BLOBs */
  void (*xDel)(void*,void*), /* Destructor function */
  void *pDelArg              /* First argument to xDel() */
){
  if( xDel==SQLITE4_DYNAMIC ){
    assert( sqlite4MemdebugHasType(z, MEMTYPE_HEAP) );
    assert( sqlite4MemdebugNoType(z, ~MEMTYPE_HEAP) );
    sqlite4MemdebugSetType((char*)z, MEMTYPE_DB | MEMTYPE_HEAP);
  }
  if( sqlite4VdbeMemSetStr(&pCtx->s, z, n, enc, xDel,pDelArg)==SQLITE4_TOOBIG ){
    sqlite4_result_error_toobig(pCtx);
  }
}
SQLITE4_API void sqlite4_result_blob(
  sqlite4_context *pCtx, 
  const void *z, 
  int n, 
  void (*xDel)(void*,void*),
  void *pDelArg
){
  assert( n>=0 );
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  setResultStrOrError(pCtx, z, n, 0, xDel, pDelArg);
}
SQLITE4_API void sqlite4_result_double(sqlite4_context *pCtx, double rVal){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  sqlite4VdbeMemSetDouble(&pCtx->s, rVal);
}
SQLITE4_API void sqlite4_result_error(sqlite4_context *pCtx, const char *z, int n){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  pCtx->isError = SQLITE4_ERROR;
  sqlite4VdbeMemSetStr(&pCtx->s, z, n, SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
}
#ifndef SQLITE4_OMIT_UTF16
SQLITE4_API void sqlite4_result_error16(sqlite4_context *pCtx, const void *z, int n){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  pCtx->isError = SQLITE4_ERROR;
  sqlite4VdbeMemSetStr(&pCtx->s, z, n, SQLITE4_UTF16NATIVE,SQLITE4_TRANSIENT,0);
}
#endif
SQLITE4_API void sqlite4_result_int(sqlite4_context *pCtx, int iVal){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  sqlite4VdbeMemSetInt64(&pCtx->s, (i64)iVal);
}
SQLITE4_API void sqlite4_result_int64(sqlite4_context *pCtx, i64 iVal){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  sqlite4VdbeMemSetInt64(&pCtx->s, iVal);
}
SQLITE4_API void sqlite4_result_num(sqlite4_context *pCtx, sqlite4_num val){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  sqlite4VdbeMemSetNum(&pCtx->s, val, MEM_Real);
}
SQLITE4_API void sqlite4_result_null(sqlite4_context *pCtx){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  sqlite4VdbeMemSetNull(&pCtx->s);
}
SQLITE4_API void sqlite4_result_text(
  sqlite4_context *pCtx, 
  const char *z, 
  int n,
  void (*xDel)(void*,void*),
  void *pDelArg
){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  setResultStrOrError(pCtx, z, n, SQLITE4_UTF8, xDel, pDelArg);
}
#ifndef SQLITE4_OMIT_UTF16
SQLITE4_API void sqlite4_result_text16(
  sqlite4_context *pCtx, 
  const void *z, 
  int n, 
  void (*xDel)(void*,void*),
  void *pDelArg
){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  setResultStrOrError(pCtx, z, n, SQLITE4_UTF16NATIVE, xDel, pDelArg);
}
SQLITE4_API void sqlite4_result_text16be(
  sqlite4_context *pCtx, 
  const void *z, 
  int n, 
  void (*xDel)(void*,void*),
  void *pDelArg
){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  setResultStrOrError(pCtx, z, n, SQLITE4_UTF16BE, xDel, pDelArg);
}
SQLITE4_API void sqlite4_result_text16le(
  sqlite4_context *pCtx, 
  const void *z, 
  int n, 
  void (*xDel)(void*,void*),
  void *pDelArg
){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  setResultStrOrError(pCtx, z, n, SQLITE4_UTF16LE, xDel, pDelArg);
}
#endif /* SQLITE4_OMIT_UTF16 */
SQLITE4_API void sqlite4_result_value(sqlite4_context *pCtx, sqlite4_value *pValue){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  sqlite4VdbeMemCopy(&pCtx->s, pValue);
}
SQLITE4_API void sqlite4_result_error_code(sqlite4_context *pCtx, int errCode){
  pCtx->isError = errCode;
  if( pCtx->s.flags & MEM_Null ){
    sqlite4VdbeMemSetStr(&pCtx->s, sqlite4ErrStr(errCode), -1, 
                         SQLITE4_UTF8, SQLITE4_STATIC, 0);
  }
}

/* Force an SQLITE4_TOOBIG error. */
SQLITE4_API void sqlite4_result_error_toobig(sqlite4_context *pCtx){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  pCtx->isError = SQLITE4_TOOBIG;
  sqlite4VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, 
                       SQLITE4_UTF8, SQLITE4_STATIC, 0);
}

/* An SQLITE4_NOMEM error. */
SQLITE4_API void sqlite4_result_error_nomem(sqlite4_context *pCtx){
  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  sqlite4VdbeMemSetNull(&pCtx->s);
  pCtx->isError = SQLITE4_NOMEM;
  pCtx->s.db->mallocFailed = 1;
}

/*
** Execute the statement pStmt, either until a row of data is ready, the
** statement is completely executed or an error occurs.
**
** This routine implements the bulk of the logic behind the sqlite_step()
** API.  The only thing omitted is the automatic recompile if a 
** schema change has occurred.  That detail is handled by the
** outer sqlite4_step() wrapper procedure.
*/
static int sqlite4Step(Vdbe *p){
  sqlite4 *db;
  int rc;

  assert(p);
  if( p->magic!=VDBE_MAGIC_RUN ){
    /* We used to require that sqlite4_reset() be called before retrying
    ** sqlite4_step() after any error or after SQLITE4_DONE.  But beginning
    ** with version 3.7.0, we changed this so that sqlite4_reset() would
    ** be called automatically instead of throwing the SQLITE4_MISUSE error.
    ** This "automatic-reset" change is not technically an incompatibility, 
    ** since any application that receives an SQLITE4_MISUSE is broken by
    ** definition.
    **
    ** Nevertheless, some published applications that were originally written
    ** for version 3.6.23 or earlier do in fact depend on SQLITE4_MISUSE 
    ** returns, and those were broken by the automatic-reset change.  As a
    ** a work-around, the SQLITE4_OMIT_AUTORESET compile-time restores the
    ** legacy behavior of returning SQLITE4_MISUSE for cases where the 
    ** previous sqlite4_step() returned something other than a SQLITE4_LOCKED
    ** or SQLITE4_BUSY error.
    */
#ifdef SQLITE4_OMIT_AUTORESET
    if( p->rc==SQLITE4_BUSY || p->rc==SQLITE4_LOCKED ){
      sqlite4_reset((sqlite4_stmt*)p);
    }else{
      return SQLITE4_MISUSE_BKPT;
    }
#else
    sqlite4_reset((sqlite4_stmt*)p);
#endif
  }

  /* Check that malloc() has not failed. If it has, return early. */
  db = p->db;
  if( db->mallocFailed ){
    p->rc = SQLITE4_NOMEM;
    return SQLITE4_NOMEM;
  }

  if( p->pc<=0 && p->expired ){
    p->rc = SQLITE4_SCHEMA;
    rc = SQLITE4_ERROR;
    goto end_of_step;
  }
  if( p->pc<0 ){
    /* If there are no other statements currently running, then
    ** reset the interrupt flag.  This prevents a call to sqlite4_interrupt
    ** from interrupting a statement that has not yet started.
    */
    if( db->activeVdbeCnt==0 ){
      db->u1.isInterrupted = 0;
    }

    assert( db->writeVdbeCnt>0 || db->pSavepoint || db->nDeferredCons==0 );

#ifndef SQLITE4_OMIT_TRACE
    if( db->xProfile && !db->init.busy ){
      sqlite4OsCurrentTime(0, &p->startTime);
    }
#endif

    db->activeVdbeCnt++;
    if( p->readOnly==0 ) db->writeVdbeCnt++;
    p->pc = 0;
  }
#ifndef SQLITE4_OMIT_EXPLAIN
  if( p->explain ){
    rc = sqlite4VdbeList(p);
  }else
#endif /* SQLITE4_OMIT_EXPLAIN */
  {
    db->vdbeExecCnt++;
    rc = sqlite4VdbeExec(p);
    db->vdbeExecCnt--;
  }

#ifndef SQLITE4_OMIT_TRACE
  /* Invoke the profile callback if there is one
  */
  if( rc!=SQLITE4_ROW && db->xProfile && !db->init.busy && p->zSql ){
    sqlite4_uint64 iNow = 0;
    sqlite4OsCurrentTime(0, &iNow);
    db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000);
  }
#endif

  db->errCode = rc;
  if( SQLITE4_NOMEM==sqlite4ApiExit(p->db, p->rc) ){
    p->rc = SQLITE4_NOMEM;
  }
end_of_step:
  /* At this point local variable rc holds the value that should be 
  ** returned if this statement was compiled using the legacy 
  ** sqlite4_prepare() interface. According to the docs, this can only
  ** be one of the values in the first assert() below. Variable p->rc 
  ** contains the value that would be returned if sqlite4_finalize() 
  ** were called on statement p.
  */
  assert( rc==SQLITE4_ROW  || rc==SQLITE4_DONE   || rc==SQLITE4_ERROR 
       || rc==SQLITE4_BUSY || rc==SQLITE4_MISUSE
  );
  assert( p->rc!=SQLITE4_ROW && p->rc!=SQLITE4_DONE );
  if( rc!=SQLITE4_ROW && rc!=SQLITE4_DONE ){
    rc = sqlite4VdbeTransferError(p);
  }
  return rc;
}

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

/*
** This is the top-level implementation of sqlite4_step().  Call
** sqlite4Step() to do most of the work.  If a schema error occurs,
** call sqlite4Reprepare() and try again.
*/
SQLITE4_API int sqlite4_step(sqlite4_stmt *pStmt){
  int rc = SQLITE4_OK;      /* Result from sqlite4Step() */
  int rc2 = SQLITE4_OK;     /* Result from sqlite4Reprepare() */
  Vdbe *v = (Vdbe*)pStmt;  /* the prepared statement */
  int cnt = 0;             /* Counter to prevent infinite loop of reprepares */
  sqlite4 *db;             /* The database connection */

  if( vdbeSafetyNotNull(v) ){
    return SQLITE4_MISUSE_BKPT;
  }
  db = v->db;
  sqlite4_mutex_enter(db->mutex);
  while( (rc = sqlite4Step(v))==SQLITE4_SCHEMA
         && cnt++ < SQLITE4_MAX_SCHEMA_RETRY
         && (rc2 = rc = sqlite4Reprepare(v))==SQLITE4_OK ){
    sqlite4_reset(pStmt);
    assert( v->expired==0 );
  }
  if( rc2!=SQLITE4_OK && ALWAYS(db->pErr) ){
    /* This case occurs after failing to recompile an sql statement. 
    ** The error message from the SQL compiler has already been loaded 
    ** into the database handle. This block copies the error message 
    ** from the database handle into the statement and sets the statement
    ** program counter to 0 to ensure that when the statement is 
    ** finalized or reset the parser error message is available via
    ** sqlite4_errmsg() and sqlite4_errcode().
    */
    const char *zErr = sqlite4_value_text(db->pErr, 0); 
    sqlite4DbFree(db, v->zErrMsg);
    if( !db->mallocFailed ){
      v->zErrMsg = sqlite4DbStrDup(db, zErr);
      v->rc = rc2;
    } else {
      v->zErrMsg = 0;
      v->rc = rc = SQLITE4_NOMEM;
    }
  }
  rc = sqlite4ApiExit(db, rc);
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Extract the user data from a sqlite4_context structure and return a
** pointer to it.
*/
SQLITE4_API void *sqlite4_context_appdata(sqlite4_context *p){
  assert( p && p->pFunc );
  return p->pFunc->pUserData;
}

/*
** Return the sqlite4 object that owns the sqlite4_context.
**
** IMPLEMENTATION-OF: R-46798-50301 The sqlite4_context_db_handle() interface
** returns a copy of the pointer to the database connection (the 1st
** parameter) of the sqlite4_create_function() and
** sqlite4_create_function16() routines that originally registered the
** application defined function.
*/
SQLITE4_API sqlite4 *sqlite4_context_db_handle(sqlite4_context *p){
  assert( p && p->pFunc );
  return p->s.db;
}

/*
** Return the sqlite4_env object associated with the sqlite4_context.
*/
SQLITE4_API sqlite4_env *sqlite4_context_env(sqlite4_context *p){
  assert( p && p->pFunc );
  return p->s.db->pEnv;
}

/*
** The following is the implementation of an SQL function that always
** fails with an error message stating that the function is used in the
** wrong context.  The sqlite4_overload_function() API might construct
** SQL function that use this routine so that the functions will exist
** for name resolution but are actually overloaded by the xFindFunction
** method of virtual tables.
*/
SQLITE4_PRIVATE void sqlite4InvalidFunction(
  sqlite4_context *context,  /* The function calling context */
  int NotUsed,               /* Number of arguments to the function */
  sqlite4_value **NotUsed2   /* Value of each argument */
){
  const char *zName = context->pFunc->zName;
  char *zErr;
  sqlite4_env *pEnv = sqlite4_context_env(context);
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  zErr = sqlite4_mprintf(pEnv,
      "unable to use function %s in the requested context", zName);
  sqlite4_result_error(context, zErr, -1);
  sqlite4_free(pEnv, zErr);
}

/*
** Allocate or return the aggregate context for a user function.  A new
** context is allocated on the first call.  Subsequent calls return the
** same context that was returned on prior calls.
*/
SQLITE4_API void *sqlite4_aggregate_context(sqlite4_context *p, int nByte){
  Mem *pMem;
  assert( p && p->pFunc && p->pFunc->xStep );
  assert( sqlite4_mutex_held(p->s.db->mutex) );
  pMem = p->pMem;
  testcase( nByte<0 );
  if( (pMem->flags & MEM_Agg)==0 ){
    if( nByte<=0 ){
      sqlite4VdbeMemReleaseExternal(pMem);
      pMem->flags = MEM_Null;
      pMem->z = 0;
    }else{
      sqlite4VdbeMemGrow(pMem, nByte, 0);
      pMem->flags = MEM_Agg;
      pMem->u.pDef = p->pFunc;
      if( pMem->z ){
        memset(pMem->z, 0, nByte);
      }
    }
  }
  return (void*)pMem->z;
}

/*
** Return the auxilary data pointer, if any, for the iArg'th argument to
** the user-function defined by pCtx.
*/
SQLITE4_API void *sqlite4_auxdata_fetch(sqlite4_context *pCtx, int iArg){
  VdbeFunc *pVdbeFunc;

  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  pVdbeFunc = pCtx->pVdbeFunc;
  if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
    return 0;
  }
  return pVdbeFunc->apAux[iArg].pAux;
}

/*
** Set the auxilary data pointer and delete function, for the iArg'th
** argument to the user-function defined by pCtx. Any previous value is
** deleted by calling the delete function specified when it was set.
*/
SQLITE4_API void sqlite4_auxdata_store(
  sqlite4_context *pCtx, 
  int iArg, 
  void *pAux, 
  void (*xDelete)(void*,void*),
  void *pDeleteArg
){
  struct AuxData *pAuxData;
  VdbeFunc *pVdbeFunc;
  if( iArg<0 ) goto failed;

  assert( sqlite4_mutex_held(pCtx->s.db->mutex) );
  pVdbeFunc = pCtx->pVdbeFunc;
  if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
    int nAux = (pVdbeFunc ? pVdbeFunc->nAux : 0);
    int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
    pVdbeFunc = sqlite4DbRealloc(pCtx->s.db, pVdbeFunc, nMalloc);
    if( !pVdbeFunc ){
      goto failed;
    }
    pCtx->pVdbeFunc = pVdbeFunc;
    memset(&pVdbeFunc->apAux[nAux], 0, sizeof(struct AuxData)*(iArg+1-nAux));
    pVdbeFunc->nAux = iArg+1;
    pVdbeFunc->pFunc = pCtx->pFunc;
  }

  pAuxData = &pVdbeFunc->apAux[iArg];
  if( pAuxData->pAux && pAuxData->xDelete ){
    pAuxData->xDelete(pAuxData->pDeleteArg, pAuxData->pAux);
  }
  pAuxData->pAux = pAux;
  pAuxData->xDelete = xDelete;
  pAuxData->pDeleteArg = pDeleteArg;
  return;

failed:
  if( xDelete ){
    xDelete(pDeleteArg, pAux);
  }
}

/*
** Return the number of columns in the result set for the statement pStmt.
*/
SQLITE4_API int sqlite4_column_count(sqlite4_stmt *pStmt){
  Vdbe *pVm = (Vdbe *)pStmt;
  return pVm ? pVm->nResColumn : 0;
}

/*
** Return the number of values available from the current row of the
** currently executing statement pStmt.
*/
SQLITE4_API int sqlite4_data_count(sqlite4_stmt *pStmt){
  Vdbe *pVm = (Vdbe *)pStmt;
  if( pVm==0 || pVm->pResultSet==0 ) return 0;
  return pVm->nResColumn;
}


/*
** Check to see if column iCol of the given statement is valid.  If
** it is, return a pointer to the Mem for the value of that column.
** If iCol is not valid, return a pointer to a Mem which has a value
** of NULL.
*/
static Mem *columnMem(sqlite4_stmt *pStmt, int i){
  Vdbe *pVm;
  Mem *pOut;

  pVm = (Vdbe *)pStmt;
  if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
    sqlite4_mutex_enter(pVm->db->mutex);
    pOut = &pVm->pResultSet[i];
  }else{
    /* If the value passed as the second argument is out of range, return
    ** a pointer to the following static Mem object which contains the
    ** value SQL NULL. Even though the Mem structure contains an element
    ** of type i64, on certain architectures (x86) with certain compiler
    ** switches (-Os), gcc may align this Mem object on a 4-byte boundary
    ** instead of an 8-byte one. This all works fine, except that when
    ** running with SQLITE4_DEBUG defined the SQLite code sometimes assert()s
    ** that a Mem structure is located on an 8-byte boundary. To prevent
    ** these assert()s from failing, when building with SQLITE4_DEBUG defined
    ** using gcc, we force nullMem to be 8-byte aligned using the magical
    ** __attribute__((aligned(8))) macro.  */
    static const Mem nullMem 
#if defined(SQLITE4_DEBUG) && defined(__GNUC__)
      __attribute__((aligned(8))) 
#endif
      = {0, "", {{0,0,0,0}}, 0, MEM_Null, SQLITE4_NULL, 0,
#ifdef SQLITE4_DEBUG
         0, 0,  /* pScopyFrom, pFiller */
#endif
         0, 0 };

    if( pVm && ALWAYS(pVm->db) ){
      sqlite4_mutex_enter(pVm->db->mutex);
      sqlite4Error(pVm->db, SQLITE4_RANGE, 0);
    }
    pOut = (Mem*)&nullMem;
  }
  return pOut;
}

/*
** Return a pointer to an sqlite4_value object that contains the value
** of column iCol of the current row of statement pStmt.
**
** Unlike columnMem(), it is the responsibility of the caller to ensure 
** that the database handle mutex is held and that the value iCol is
** within the valid range.
*/
SQLITE4_PRIVATE sqlite4_value *sqlite4ColumnValue(sqlite4_stmt *pStmt, int iCol){
  Vdbe *p = (Vdbe*)pStmt;
  assert( sqlite4_mutex_held(p->db->mutex) );
  assert( iCol<p->nResColumn && iCol>=0 );
  return (sqlite4_value *)&p->pResultSet[iCol];
}

/*
** This function is called after invoking an sqlite4_value_XXX function on a 
** column value (i.e. a value returned by evaluating an SQL expression in the
** select list of a SELECT statement) that may cause a malloc() failure. If 
** malloc() has failed, the threads mallocFailed flag is cleared and the result
** code of statement pStmt set to SQLITE4_NOMEM.
**
** Specifically, this is called from within:
**
**     sqlite4_column_int()
**     sqlite4_column_int64()
**     sqlite4_column_text()
**     sqlite4_column_text16()
**     sqlite4_column_real()
**     sqlite4_column_bytes()
**     sqlite4_column_bytes16()
**     sqiite3_column_blob()
*/
static void columnMallocFailure(sqlite4_stmt *pStmt)
{
  /* If malloc() failed during an encoding conversion within an
  ** sqlite4_column_XXX API, then set the return code of the statement to
  ** SQLITE4_NOMEM. The next call to _step() (if any) will return SQLITE4_ERROR
  ** and _finalize() will return NOMEM.
  */
  Vdbe *p = (Vdbe *)pStmt;
  if( p ){
    p->rc = sqlite4ApiExit(p->db, p->rc);
    sqlite4_mutex_leave(p->db->mutex);
  }
}

/**************************** sqlite4_column_  *******************************
** The following routines are used to access elements of the current row
** in the result set.
*/
SQLITE4_API const void *sqlite4_column_blob(sqlite4_stmt *pStmt, int i, int *pnByte){
  const void *val;
  val = sqlite4_value_blob( columnMem(pStmt,i), pnByte );
  columnMallocFailure(pStmt);
  return val;
}
SQLITE4_API double sqlite4_column_double(sqlite4_stmt *pStmt, int i){
  double val = sqlite4_value_double( columnMem(pStmt,i) );
  columnMallocFailure(pStmt);
  return val;
}
SQLITE4_API int sqlite4_column_int(sqlite4_stmt *pStmt, int i){
  int val = sqlite4_value_int( columnMem(pStmt,i) );
  columnMallocFailure(pStmt);
  return val;
}
SQLITE4_API sqlite4_int64 sqlite4_column_int64(sqlite4_stmt *pStmt, int i){
  sqlite4_int64 val = sqlite4_value_int64( columnMem(pStmt,i) );
  columnMallocFailure(pStmt);
  return val;
}
SQLITE4_API const char *sqlite4_column_text(sqlite4_stmt *pStmt, int i, int *pnByte){
  const char *val = sqlite4_value_text( columnMem(pStmt,i), pnByte );
  columnMallocFailure(pStmt);
  return val;
}
SQLITE4_API sqlite4_value *sqlite4_column_value(sqlite4_stmt *pStmt, int i){
  Mem *pOut = columnMem(pStmt, i);
  if( pOut->flags&MEM_Static ){
    pOut->flags &= ~MEM_Static;
    pOut->flags |= MEM_Ephem;
  }
  columnMallocFailure(pStmt);
  return (sqlite4_value *)pOut;
}
#ifndef SQLITE4_OMIT_UTF16
SQLITE4_API const void *sqlite4_column_text16(sqlite4_stmt *pStmt, int i, int *pnByte){
  const void *val = sqlite4_value_text16( columnMem(pStmt,i), pnByte );
  columnMallocFailure(pStmt);
  return val;
}
#endif /* SQLITE4_OMIT_UTF16 */
SQLITE4_API int sqlite4_column_type(sqlite4_stmt *pStmt, int i){
  int iType = sqlite4_value_type( columnMem(pStmt,i) );
  columnMallocFailure(pStmt);
  return iType;
}

/* The following function is experimental and subject to change or
** removal */
/*int sqlite4_column_numeric_type(sqlite4_stmt *pStmt, int i){
**  return sqlite4_value_numeric_type( columnMem(pStmt,i) );
**}
*/

/*
** Convert the N-th element of pStmt->pColName[] into a string using
** xFunc() then return that string.  If N is out of range, return 0.
**
** There are up to 5 names for each column.  useType determines which
** name is returned.  Here are the names:
**
**    0      The column name as it should be displayed for output
**    1      The datatype name for the column
**    2      The name of the database that the column derives from
**    3      The name of the table that the column derives from
**    4      The name of the table column that the result column derives from
**
** If the result is not a simple column reference (if it is an expression
** or a constant) then useTypes 2, 3, and 4 return NULL.
*/
static const void *columnName(
  sqlite4_stmt *pStmt,
  int N,
  const void *(*xFunc)(Mem*, int *),
  int useType
){
  const void *ret = 0;
  Vdbe *p = (Vdbe *)pStmt;
  int n;
  sqlite4 *db = p->db;
  
  assert( db!=0 );
  n = sqlite4_column_count(pStmt);
  if( N<n && N>=0 ){
    N += useType*n;
    sqlite4_mutex_enter(db->mutex);
    assert( db->mallocFailed==0 );
    ret = xFunc(&p->aColName[N], 0);
     /* A malloc may have failed inside of the xFunc() call. If this
    ** is the case, clear the mallocFailed flag and return NULL.
    */
    if( db->mallocFailed ){
      db->mallocFailed = 0;
      ret = 0;
    }
    sqlite4_mutex_leave(db->mutex);
  }
  return ret;
}

/*
** Return the name of the Nth column of the result set returned by SQL
** statement pStmt.
*/
SQLITE4_API const char *sqlite4_column_name(sqlite4_stmt *pStmt, int N){
  return columnName(
      pStmt, N, (const void*(*)(Mem*, int*))sqlite4_value_text, COLNAME_NAME);
}

/*
** Constraint:  If you have ENABLE_COLUMN_METADATA then you must
** not define OMIT_DECLTYPE.
*/
#if defined(SQLITE4_OMIT_DECLTYPE) && defined(SQLITE4_ENABLE_COLUMN_METADATA)
# error "Must not define both SQLITE4_OMIT_DECLTYPE \
         and SQLITE4_ENABLE_COLUMN_METADATA"
#endif

#ifndef SQLITE4_OMIT_DECLTYPE
/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt.
*/
SQLITE4_API const char *sqlite4_column_decltype(sqlite4_stmt *pStmt, int N){
  return columnName(pStmt, 
      N, (const void*(*)(Mem*, int*))sqlite4_value_text, COLNAME_DECLTYPE);
}
#endif /* SQLITE4_OMIT_DECLTYPE */

#ifdef SQLITE4_ENABLE_COLUMN_METADATA
/*
** Return the name of the database from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
SQLITE4_API const char *sqlite4_column_database_name(sqlite4_stmt *pStmt, int N){
  return columnName(pStmt, 
      N, (const void*(*)(Mem*, int*))sqlite4_value_text, COLNAME_DATABASE);
}

/*
** Return the name of the table from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
SQLITE4_API const char *sqlite4_column_table_name(sqlite4_stmt *pStmt, int N){
  return columnName(pStmt, 
      N, (const void*(*)(Mem*, int*))sqlite4_value_text, COLNAME_TABLE);
}

/*
** Return the name of the table column from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
SQLITE4_API const char *sqlite4_column_origin_name(sqlite4_stmt *pStmt, int N){
  return columnName(pStmt, 
      N, (const void*(*)(Mem*, int*))sqlite4_value_text, COLNAME_COLUMN);
}
#endif /* SQLITE4_ENABLE_COLUMN_METADATA */


/******************************* sqlite4_bind_  ***************************
** 
** Routines used to attach values to wildcards in a compiled SQL statement.
*/
/*
** Unbind the value bound to variable i in virtual machine p. This is the 
** the same as binding a NULL value to the column. If the "i" parameter is
** out of range, then SQLITE4_RANGE is returned. Othewise SQLITE4_OK.
**
** A successful evaluation of this routine acquires the mutex on p.
** the mutex is released if any kind of error occurs.
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
*/
static int vdbeUnbind(Vdbe *p, int i){
  Mem *pVar;
  if( vdbeSafetyNotNull(p) ){
    return SQLITE4_MISUSE_BKPT;
  }
  sqlite4_mutex_enter(p->db->mutex);
  if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
    sqlite4Error(p->db, SQLITE4_MISUSE, 0);
    sqlite4_mutex_leave(p->db->mutex);
    sqlite4_log(p->db->pEnv,SQLITE4_MISUSE, 
        "bind on a busy prepared statement: [%s]", p->zSql);
    return SQLITE4_MISUSE_BKPT;
  }
  if( i<1 || i>p->nVar ){
    sqlite4Error(p->db, SQLITE4_RANGE, 0);
    sqlite4_mutex_leave(p->db->mutex);
    return SQLITE4_RANGE;
  }
  i--;
  pVar = &p->aVar[i];
  sqlite4VdbeMemRelease(pVar);
  pVar->flags = MEM_Null;
  sqlite4Error(p->db, SQLITE4_OK, 0);

  /* If the bit corresponding to this variable in Vdbe.expmask is set, then 
  ** binding a new value to this variable invalidates the current query plan.
  **
  ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
  ** parameter in the WHERE clause might influence the choice of query plan
  ** for a statement, then the statement will be automatically recompiled,
  ** as if there had been a schema change, on the first sqlite4_step() call
  ** following any change to the bindings of that parameter.
  */
  if( ((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff)
  ){
    p->expired = 1;
  }
  return SQLITE4_OK;
}

/*
** Bind a text or BLOB value.
*/
static int bindText(
  sqlite4_stmt *pStmt,       /* The statement to bind against */
  int i,                     /* Index of the parameter to bind */
  const void *zData,         /* Pointer to the data to be bound */
  int nData,                 /* Number of bytes of data to be bound */
  void (*xDel)(void*,void*), /* Destructor for the data */
  void *pDelArg,             /* First argument to xDel() */
  u8 encoding                /* Encoding for the data */
){
  Vdbe *p = (Vdbe *)pStmt;
  Mem *pVar;
  int rc;

  rc = vdbeUnbind(p, i);
  if( rc==SQLITE4_OK ){
    if( zData!=0 ){
      pVar = &p->aVar[i-1];
      rc = sqlite4VdbeMemSetStr(pVar, zData, nData, encoding, xDel, pDelArg);
      if( rc==SQLITE4_OK && encoding!=0 ){
        rc = sqlite4VdbeChangeEncoding(pVar, ENC(p->db));
      }
      sqlite4Error(p->db, rc, 0);
      rc = sqlite4ApiExit(p->db, rc);
    }
    sqlite4_mutex_leave(p->db->mutex);
  }else if( xDel!=SQLITE4_STATIC && xDel!=SQLITE4_TRANSIENT ){
    xDel(pDelArg, (void*)zData);
  }
  return rc;
}


/*
** Bind a blob value to an SQL statement variable.
*/
SQLITE4_API int sqlite4_bind_blob(
  sqlite4_stmt *pStmt, 
  int i, 
  const void *zData, 
  int nData, 
  void (*xDel)(void*,void*),
  void *pDelArg
){
  return bindText(pStmt, i, zData, nData, xDel, pDelArg, 0);
}
SQLITE4_API int sqlite4_bind_double(sqlite4_stmt *pStmt, int i, double rValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, i);
  if( rc==SQLITE4_OK ){
    sqlite4VdbeMemSetDouble(&p->aVar[i-1], rValue);
    sqlite4_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE4_API int sqlite4_bind_int(sqlite4_stmt *p, int i, int iValue){
  return sqlite4_bind_int64(p, i, (i64)iValue);
}
SQLITE4_API int sqlite4_bind_int64(sqlite4_stmt *pStmt, int i, sqlite4_int64 iValue){
  int rc;
  Vdbe *p = (Vdbe *)pStmt;
  rc = vdbeUnbind(p, i);
  if( rc==SQLITE4_OK ){
    sqlite4VdbeMemSetInt64(&p->aVar[i-1], iValue);
    sqlite4_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE4_API int sqlite4_bind_null(sqlite4_stmt *pStmt, int i){
  int rc;
  Vdbe *p = (Vdbe*)pStmt;
  rc = vdbeUnbind(p, i);
  if( rc==SQLITE4_OK ){
    sqlite4_mutex_leave(p->db->mutex);
  }
  return rc;
}
SQLITE4_API int sqlite4_bind_text( 
  sqlite4_stmt *pStmt, 
  int i, 
  const char *zData, 
  int nData, 
  void (*xDel)(void*,void*),
  void *pDelArg
){
  return bindText(pStmt, i, zData, nData, xDel, pDelArg, SQLITE4_UTF8);
}
#ifndef SQLITE4_OMIT_UTF16
SQLITE4_API int sqlite4_bind_text16(
  sqlite4_stmt *pStmt, 
  int i, 
  const void *zData, 
  int nData, 
  void (*xDel)(void*,void*),
  void *pDelArg
){
  return bindText(pStmt, i, zData, nData, xDel, pDelArg, SQLITE4_UTF16NATIVE);
}
#endif /* SQLITE4_OMIT_UTF16 */
SQLITE4_API int sqlite4_bind_value(sqlite4_stmt *pStmt, int i, const sqlite4_value *pValue){
  int rc;
  switch( pValue->type ){
    case SQLITE4_INTEGER:
    case SQLITE4_FLOAT: {
      Mem *p = (Mem *)pValue;
      Vdbe *v = (Vdbe *)pStmt;
      vdbeUnbind(v, i);
      v->aVar[i-1].u.num = p->u.num;
      MemSetTypeFlag(&v->aVar[i-1], 
          (pValue->type==SQLITE4_FLOAT ? MEM_Real : MEM_Int)
      );
      break;
    }
    case SQLITE4_BLOB: {
      rc = sqlite4_bind_blob(pStmt, i, pValue->z, pValue->n,
                             SQLITE4_TRANSIENT, 0);
      break;
    }
    case SQLITE4_TEXT: {
      rc = bindText(pStmt,i,  pValue->z, pValue->n, SQLITE4_TRANSIENT, 0,
                              pValue->enc);
      break;
    }
    default: {
      rc = sqlite4_bind_null(pStmt, i);
      break;
    }
  }
  return rc;
}

/*
** Return the number of wildcards that can be potentially bound to.
** This routine is added to support DBD::SQLite.  
*/
SQLITE4_API int sqlite4_bind_parameter_count(sqlite4_stmt *pStmt){
  Vdbe *p = (Vdbe*)pStmt;
  return p ? p->nVar : 0;
}

/*
** Return the name of a wildcard parameter.  Return NULL if the index
** is out of range or if the wildcard is unnamed.
**
** The result is always UTF-8.
*/
SQLITE4_API const char *sqlite4_bind_parameter_name(sqlite4_stmt *pStmt, int i){
  Vdbe *p = (Vdbe*)pStmt;
  if( p==0 || i<1 || i>p->nzVar ){
    return 0;
  }
  return p->azVar[i-1];
}

/*
** Given a wildcard parameter name, return the index of the variable
** with that name.  If there is no variable with the given name,
** return 0.
*/
SQLITE4_PRIVATE int sqlite4VdbeParameterIndex(Vdbe *p, const char *zName, int nName){
  int i;
  if( p==0 ){
    return 0;
  }
  if( zName ){
    for(i=0; i<p->nzVar; i++){
      const char *z = p->azVar[i];
      if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
        return i+1;
      }
    }
  }
  return 0;
}
SQLITE4_API int sqlite4_bind_parameter_index(sqlite4_stmt *pStmt, const char *zName){
  return sqlite4VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite4Strlen30(zName));
}

/*
** Transfer all bindings from the first statement over to the second.
*/
SQLITE4_PRIVATE int sqlite4TransferBindings(sqlite4_stmt *pFromStmt, sqlite4_stmt *pToStmt){
  Vdbe *pFrom = (Vdbe*)pFromStmt;
  Vdbe *pTo = (Vdbe*)pToStmt;
  int i;
  assert( pTo->db==pFrom->db );
  assert( pTo->nVar==pFrom->nVar );
  sqlite4_mutex_enter(pTo->db->mutex);
  for(i=0; i<pFrom->nVar; i++){
    sqlite4VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
  }
  sqlite4_mutex_leave(pTo->db->mutex);
  return SQLITE4_OK;
}

/*
** Return the sqlite4* database handle to which the prepared statement given
** in the argument belongs.  This is the same database handle that was
** the first argument to the sqlite4_prepare() that was used to create
** the statement in the first place.
*/
SQLITE4_API sqlite4 *sqlite4_db_handle(sqlite4_stmt *pStmt){
  return pStmt ? ((Vdbe*)pStmt)->db : 0;
}

/*
** Return true if the prepared statement is guaranteed to not modify the
** database.
*/
SQLITE4_API int sqlite4_stmt_readonly(sqlite4_stmt *pStmt){
  return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
}

/*
** Return true if the prepared statement is in need of being reset.
*/
SQLITE4_API int sqlite4_stmt_busy(sqlite4_stmt *pStmt){
  Vdbe *v = (Vdbe*)pStmt;
  return v!=0 && v->pc>0 && v->magic==VDBE_MAGIC_RUN;
}

/*
** Return a pointer to the next prepared statement after pStmt associated
** with database connection pDb.  If pStmt is NULL, return the first
** prepared statement for the database connection.  Return NULL if there
** are no more.
*/
SQLITE4_API sqlite4_stmt *sqlite4_next_stmt(sqlite4 *pDb, sqlite4_stmt *pStmt){
  sqlite4_stmt *pNext;
  sqlite4_mutex_enter(pDb->mutex);
  if( pStmt==0 ){
    pNext = (sqlite4_stmt*)pDb->pVdbe;
  }else{
    pNext = (sqlite4_stmt*)((Vdbe*)pStmt)->pNext;
  }
  sqlite4_mutex_leave(pDb->mutex);
  return pNext;
}

/*
** Return the value of a status counter for a prepared statement
*/
SQLITE4_API int sqlite4_stmt_status(sqlite4_stmt *pStmt, int op, int resetFlag){
  Vdbe *pVdbe = (Vdbe*)pStmt;
  int v = pVdbe->aCounter[op-1];
  if( resetFlag ) pVdbe->aCounter[op-1] = 0;
  return v;
}

/************** End of vdbeapi.c *********************************************/
/************** Begin file vdbecodec.c ***************************************/
/*
** 2012 January 24
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code for encoding and decoding values and keys for
** insertion and reading from the key/value storage engine.
*/

/*
** The decoder object.
**
** An instance of this object is used to extract individual columns (numbers,
** strings, blobs, or NULLs) from a row of a table or index.  Usually the
** content is extract from the value side of the key/value pair, though
** sometimes information might be taken from the key as well.
**
** When the VDBE needs to extract multiple columns from the same row, it will
** try to reuse a single decoder object.  The decoder, therefore, should attempt
** to cache any intermediate results that might be useful on later invocations.
*/
struct RowDecoder {
  sqlite4 *db;                /* The database connection */
  VdbeCursor *pCur;           /* The cursor for being decoded */
  KVCursor *pKVCur;           /* Alternative KVCursor if pCur is NULL */
  const KVByteArray *a;       /* Content to be decoded */
  const KVByteArray *aKey;    /* Key content */
  KVSize n;                   /* Bytes of content in a[] */
  KVSize nKey;                /* Bytes of key content */
  int mxCol;                  /* Maximum number of columns */
};

/*
** Create an object that can be used to decode fields of the data encoding.
**
** The aIn[] value must remain stable for the life of the decoder.
*/
SQLITE4_PRIVATE int sqlite4VdbeDecoderCreate(
  sqlite4 *db,                /* The database connection */
  VdbeCursor *pCur,           /* The cursor associated with this decoder */
  KVCursor *pKVCur,           /* Alternative KVCursor */
  int mxCol,                  /* Maximum number of columns to ever decode */
  RowDecoder **ppOut          /* Return the answer here */
){
  RowDecoder *p;

  assert( pCur==0 || pKVCur==0 );
  assert( pCur!=0 || pKVCur!=0 );
  p = sqlite4DbMallocZero(db, sizeof(*p));
  *ppOut = p;
  if( p==0 ) return SQLITE4_NOMEM;
  p->db = db;
  p->pCur = pCur;
  p->pKVCur = pKVCur;
  p->mxCol = mxCol;
  return SQLITE4_OK;
}

/*
** Destroy a decoder object previously created
** using sqlite4VdbeCreateDecoder().
*/
SQLITE4_PRIVATE int sqlite4VdbeDecoderDestroy(RowDecoder *p){
  if( p ){
    sqlite4DbFree(p->db, p);
  }
  return SQLITE4_OK;
}

/*
** Make sure the p->a and p->n fields are valid and current.
*/
static int decoderFetchData(RowDecoder *p){
  VdbeCursor *pCur = p->pCur;
  int rc;
  if( pCur==0 ){
    rc = sqlite4KVCursorData(p->pKVCur, 0, -1, &p->a, &p->n);
    return rc;
  }
  if( pCur->rowChnged ){
    p->a = 0;
    p->aKey = 0;
    pCur->rowChnged = 0;
  }
  if( p->a ) return SQLITE4_OK;
  rc = sqlite4VdbeCursorMoveto(pCur);
  if( rc ) return rc;
  if( pCur->nullRow ){
    p->a = 0;
    p->n = 0;
    return SQLITE4_OK;
  }
  assert( pCur->pKVCur!=0 );
  return sqlite4KVCursorData(pCur->pKVCur, 0, -1, &p->a, &p->n);
}

/*
** Make sure the p->aKey and p->nKey fields are valid and current.
*/
static int decoderFetchKey(RowDecoder *p){
  VdbeCursor *pCur = p->pCur;
  int rc;
  if( pCur==0 ){
    rc = sqlite4KVCursorKey(p->pKVCur, &p->aKey, &p->nKey);
    return rc;
  }
  assert( p->a!=0 );
  if( p->aKey ) return SQLITE4_OK;
  assert( pCur->pKVCur!=0 );
  return sqlite4KVCursorKey(pCur->pKVCur, &p->aKey, &p->nKey);
}

/*
** Decode a blob from a key.  The blob-key is in a[0] through a[n-1].
** xorMask is either 0x00 for ascending order or 0xff for descending.
** Store the blob in pOut.
*/
static int decoderMemSetFromBlob(
  const KVByteArray *a, KVSize n, /* The blob as a key */
  unsigned int xorMask,           /* 0x00 (ascending) or 0xff (descending) */
  Mem *pOut                       /* Write the blob here */
){
  int rc;
  unsigned int m = 0;
  int i, j, k;

  sqlite4VdbeMemSetStr(pOut, "", 0, 0, 0, 0);
  rc = sqlite4VdbeMemGrow(pOut, n, 0);
  if( rc==SQLITE4_OK ){
    i = 0;
    j = 0;
    k = 0;
    while( i<n ){
      m = (m<<7) | ((a[i++] ^ xorMask)&0x7f);
      j += 7;
      if( j>=8 ){
        pOut->z[k++] = (m>>(j-8))&0xff;
        j -= 8;
      }
    }
    if( j>0 ){
      pOut->z[k] = m<<(7-j);
    }
    pOut->n = k;
  }
  return rc;
}

/*
** Decode a numeric key encoding.  Return the number of bytes in the
** encoding on success.  On an error, return 0.
*/
SQLITE4_PRIVATE int sqlite4VdbeDecodeNumericKey(
  const KVByteArray *aKey,       /* Input encoding */
  KVSize nKey,                   /* Number of bytes in aKey[] */
  sqlite4_num *pVal              /* Write the result here */
){
  unsigned int i, y;
  unsigned int xorMask = 0;
  short e;
  sqlite4_uint64 m;
  sqlite4_int64 eBig;
  KVByteArray aInvertedKey[4];

  pVal->approx = 0;
  pVal->sign = 0;
  if( nKey<1 ) return 0;
  switch( aKey[0] ){
    case 0x06:   /* NaN ascending */
    case 0xf9:   /* NaN descending */
      pVal->m = 0;
      pVal->e = 1000;
      return 1;

    case 0x07:   /* -inf ascending */
    case 0xf8:   /* -inf descending */
      pVal->m = 1;
      pVal->sign = 1;
      pVal->e = 1000;
      return 1;

    case 0x15:   /* zero ascending */
    case 0xea:   /* zero descending */
      pVal->m = 0;
      pVal->e = 0;
      return 1;

    case 0x23:   /* +inf ascending */
    case 0xdc:   /* +inf descending */
      pVal->m = 1;
      pVal->e = 1000;
      return 1;

    case 0x09:
    case 0x0a:
    case 0x0b:
    case 0x0c:
    case 0x0d:
    case 0x0e:
    case 0x0f:
    case 0x10:
    case 0x11:
    case 0x12:
    case 0x13:   /* -medium ascending */
      pVal->sign = 1;
      xorMask = 0xff;
      e = 0x13 - aKey[0];
      i = 1;
      break;

    case 0xf6:
    case 0xf5:
    case 0xf4:
    case 0xf3:
    case 0xf2:
    case 0xf1:
    case 0xf0:
    case 0xef:
    case 0xee:
    case 0xed:
    case 0xec:   /* -medium descending */
      pVal->sign = 1;
      e = aKey[0] - 0xec;
      i = 1;
      break;

    case 0x17:
    case 0x18:
    case 0x19:
    case 0x1a:
    case 0x1b:
    case 0x1c:
    case 0x1d:
    case 0x1e:
    case 0x1f:
    case 0x20:
    case 0x21:   /* +medium ascending */
      e = aKey[0] - 0x17;
      i = 1;
      break;

    case 0xe8:
    case 0xe7:
    case 0xe6:
    case 0xe5:
    case 0xe4:
    case 0xe3:
    case 0xe2:
    case 0xe1:
    case 0xe0:
    case 0xdf:
    case 0xde:   /* +medium descending */
      e = 0xe8 - aKey[0];
      xorMask = 0xff;
      i = 1;
      break;

    case 0x14:   /* -small ascending */
    case 0xe9:   /* +small descending */
      i = 1 + sqlite4GetVarint64(aKey+1, 2, &eBig);
      e = (short)-eBig;
      xorMask = 0xff;
      break;

    case 0x16:   /* +small ascending */
    case 0xeb:   /* -small descending */
      aInvertedKey[0] = aKey[1] ^ 0xff;
      aInvertedKey[1] = aKey[2] ^ 0xff;
      i = 1 + sqlite4GetVarint64(aInvertedKey, 2, &eBig);
      e = (short)-eBig;
      break;

    case 0x08:   /* -large ascending */
    case 0xdd:   /* +large descending */
      aInvertedKey[0] = aKey[1] ^ 0xff;
      aInvertedKey[1] = aKey[2] ^ 0xff;
      i = 1 + sqlite4GetVarint64(aInvertedKey, 2, &eBig);
      e = (short)eBig;
      xorMask = 0xff;
      break;

    case 0x22:   /* +large ascending */
    case 0xf7:   /* -large descending */
      i = 1 + sqlite4GetVarint64(aKey+1, 2, &eBig);
      e = (short)eBig;
      break;

    default:
      return 0;
  }
  m = 0;
  do{
    y = aKey[i++] ^ xorMask;
    m = m*100 + y/2;
    e--;
  }while( y & 1 );
  if( m==0 ) return 0;

  pVal->m = m;
  pVal->e = 2*e;
  return i;
}

/*
** This is a private method for the RowDecoder object.
**
** Attempt to extract a single column value from the key of the current
** key/value pair.  If beginning of the value is iOfst bytes from the beginning
** of the key.  If affReal is true, then force numeric values to be floating
** point.  Write the result in pOut.  Or return non-zero if there is an
** error.
*/
static int decoderFromKey(
  RowDecoder *p,           /* The current key/value pair */
  int affReal,             /* True to coerce numbers to floating point */
  sqlite4_int64 iOfst,     /* Offset of value in the key */
  Mem *pOut                /* Write the results here */
){
  int rc;
  KVSize i;
  KVSize n;
  const KVByteArray *a;
  char *z;

  if( iOfst<0 ){
    return SQLITE4_CORRUPT_BKPT;
  }
  rc = decoderFetchKey(p);
  if( rc ) return rc;
  if( iOfst>=p->nKey ){
    return SQLITE4_CORRUPT_BKPT;
  }
  a = p->aKey;
  n = p->nKey;
  switch( a[iOfst++] ){
    case 0x05: case 0xFA:       /* NULL */
    case 0x06: case 0xF9: {     /* NaN */
      sqlite4VdbeMemSetNull(pOut);
      break;
    }

    case 0x24: {                /* Text (ascending index) */
      for(i=iOfst; i<n && a[i]!=0; i++){}
      rc = sqlite4VdbeMemSetStr(pOut, &a[iOfst], i-iOfst,
                                SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      break;
    }
    case 0xDB: {                /* Text (descending index) */
      for(i=iOfst; i<n && a[i]!=0xFF; i++){}
      rc = sqlite4VdbeMemSetStr(pOut, &a[iOfst+1], n = i - iOfst,
                                SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      if( rc==SQLITE4_OK ){
        z = pOut->z;
        for(i=n-1; i>=0; i--) *(z++) ^= 0xFF;
      }
      break;
    }

    case 0x25: {                /* Blob (ascending index) */
      for(i=iOfst; i<n && a[i]!=0; i++){}
      rc = decoderMemSetFromBlob(&a[iOfst], i-iOfst, 0x00, pOut);
      break;
    }
    case 0xDA: {                /* Blob (descending index) */
      for(i=iOfst; i<n && a[i]!=0xFF; i++){}
      rc = decoderMemSetFromBlob(&a[iOfst], i-iOfst, 0xFF, pOut);
      break;
    }

    case 0x26: {                /* Blob-final (ascending) */
      rc = sqlite4VdbeMemSetStr(pOut, &a[iOfst], n-iOfst, 0,
                                SQLITE4_TRANSIENT, 0);
      break;
    }
    case 0xD9: {                /* Blob-final (descending) */
      rc = sqlite4VdbeMemSetStr(pOut, &a[iOfst], n-iOfst,
                                SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      if( rc==SQLITE4_OK ){
        z = pOut->z;
        for(i=n-iOfst; i>0; i--) *(z++) ^= 0xFF;
      }
      break;
    }
    default: {
      sqlite4_num v;
      i = sqlite4VdbeDecodeNumericKey(a+iOfst-1, n-iOfst+1, &v);
      if( i==0 ){
        rc = SQLITE4_CORRUPT_BKPT;
      }else{
        sqlite4VdbeMemSetNum(pOut, v, affReal ? MEM_Real : MEM_Int);
        rc = SQLITE4_OK;
      }
      break;
    }
  };
  return rc;
}

/*
** Decode a single column from a key/value pair taken from the storage
** engine.  The key/value pair to be decoded is the one that the VdbeCursor
** or KVCursor is currently pointing to.
**
** iVal is the column index of the value.  0 is the first column of the
** value.  If N is the number of columns in the value and iVal>=N then
** the result is pDefault.  Write the result into pOut.  Return SQLITE4_OK
** on success or an appropriate error code on failure.
**
** The key is referenced only if the iVal-th column in the value is either
** the 22 or 23 header code which indicates that the value is stored in the
** key instead.
*/
SQLITE4_PRIVATE int sqlite4VdbeDecoderGetColumn(
  RowDecoder *p,             /* The decoder for the whole string */
  int iVal,                    /* Index of the value to decode.  First is 0 */
  Mem *pDefault,               /* The default value.  Often NULL */
  Mem *pOut                    /* Write the result here */
){
  u32 size;                    /* Size of a field */
  sqlite4_uint64 ofst;         /* Offset to the payload */
  sqlite4_uint64 type;         /* Datatype */
  sqlite4_uint64 subtype;      /* Subtype for a typed blob */
  int cclass;                  /* class of content */
  int n;                       /* Offset into the header */
  int i;                       /* Loop counter */
  int sz;                      /* Size of a varint */
  int endHdr;                  /* First byte past header */
  int rc;                      /* Return code */

  sqlite4VdbeMemSetNull(pOut);
  assert( iVal<=p->mxCol );
  rc = decoderFetchData(p);
  if( rc ) return rc;
  if( p->a==0 ) return SQLITE4_OK;
  n = sqlite4GetVarint64(p->a, p->n, &ofst);
  if( n==0 ) return SQLITE4_CORRUPT;
  ofst += n;
  endHdr = ofst;
  if( endHdr>p->n ) return SQLITE4_CORRUPT;
  for(i=0; i<=iVal && n<endHdr; i++){
    sz = sqlite4GetVarint64(p->a+n, p->n-n, &type);
    if( sz==0 ) return SQLITE4_CORRUPT;
    n += sz;
    if( type>=22 ){  /* STRING, BLOB, KEY, and TYPED */
      cclass = (type-22)%4;
      if( cclass==2 ){
        size = 0;  /* KEY */
      }else{
        size = (type-22)/4;
        if( cclass==3 ){  /* The TYPED header code */
          sz = sqlite4GetVarint64(p->a+n, p->n-n, &subtype);
          if( sz==0 ) return SQLITE4_CORRUPT;
          n += sz;
        }
      }
    }else if( type<=2 ){  /* NULL, ZERO, and ONE */
      size = 0;
    }else if( type<=10 ){ /* INT */
      size = type - 2;
    }else{
      assert( type>=11 && type<=21 );  /* NUM */
      size = type - 9;
    }
    if( i<iVal ){
      ofst += size;
    }else if( type==0 ){
      /* no-op */
    }else if( type<=2 ){
      sqlite4VdbeMemSetInt64(pOut, type-1);
    }else if( type<=10 ){
      int iByte;
      sqlite4_int64 v = ((char*)p->a)[ofst];
      for(iByte=1; iByte<size; iByte++){
        v = v*256 + p->a[ofst+iByte];
      }
      sqlite4VdbeMemSetInt64(pOut, v);
    }else if( type<=21 ){
      sqlite4_num num = {0, 0, 0, 0};
      sqlite4_uint64 x;
      int e;

      n = sqlite4GetVarint64(p->a+ofst, p->n-ofst, &x);
      e = (int)x;
      n += sqlite4GetVarint64(p->a+ofst+n, p->n-(ofst+n), &x);
      if( n!=size ) return SQLITE4_CORRUPT;

      num.m = x;
      num.e = (e >> 2);
      if( e & 0x02 ) num.e = -1 * num.e;
      if( e & 0x01 ) num.sign = 1;
      pOut->u.num = num;
      MemSetTypeFlag(pOut, MEM_Real);
    }else if( cclass==0 ){
      if( size==0 ){
        sqlite4VdbeMemSetStr(pOut, "", 0, SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else if( p->a[ofst]>0x02 ){
        sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst), size, 
                             SQLITE4_UTF8, SQLITE4_TRANSIENT, 0);
      }else{
        static const u8 enc[] = {SQLITE4_UTF8,SQLITE4_UTF16LE,SQLITE4_UTF16BE };
        sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst+1), size-1, 
                             enc[p->a[ofst]], SQLITE4_TRANSIENT, 0);
      }
    }else if( cclass==2 ){
      unsigned int k = (type - 24)/4;
      return decoderFromKey(p, (k&1)!=0, k/2, pOut);
    }else{
      sqlite4VdbeMemSetStr(pOut, (char*)(p->a+ofst), size, 0,
                           SQLITE4_TRANSIENT, 0);
      pOut->enc = ENC(p->db);
    }
  }
  testcase( i==iVal );
  testcase( i==iVal+1 );
  if( i<=iVal ){
    if( pDefault ){
      sqlite4VdbeMemShallowCopy(pOut, pDefault, MEM_Static);
    }else{
      sqlite4VdbeMemSetNull(pOut);
    }
  }
  return SQLITE4_OK; 
}

/*
** Return the number of bytes needed to represent a 64-bit signed integer.
*/
static int significantBytes(sqlite4_int64 v){
  sqlite4_int64 x;
  int n = 1;
  if( v<0 ){
    x = -128;
    while( v<x && n<8 ){ n++; x *= 256; }
  }else{
    x = 127;
    while( v>x && n<8 ){ n++; x *= 256; }
  }
  return n;
}

/*
** Encode nIn values from array aIn[] using the data encoding. If argument
** aPermute[] is NULL, then the nIn elements are elements 0, 1 ... (nIn-1)
** of the array. Otherwise, aPermute[0], aPermute[1] ... aPermute[nIn-1].
**
** Assume that affinity has already been applied to all elements of the
** input array aIn[].
**
** Space to hold the record is obtained from sqlite4DbMalloc() and should
** be freed by the caller using sqlite4DbFree() to avoid a memory leak.
*/
SQLITE4_PRIVATE int sqlite4VdbeEncodeData(
  sqlite4 *db,                /* The database connection */
  Mem *aIn,                   /* Array of values to encode */
  int *aPermute,              /* Permutation or NULL (see above) */
  int nIn,                    /* Number of entries in aIn[] */
  u8 **pzOut,                 /* The output data record */
  int *pnOut                  /* Bytes of content in pzOut */
){
  int i, j;
  int rc = SQLITE4_OK;
  int nHdr;
  int n;
  u8 *aOut = 0;               /* The result */
  int nOut;                   /* Bytes of aOut used */
  int nPayload = 0;           /* Payload space required */
  int encoding = ENC(db);     /* Text encoding */
  struct dencAux {            /* For each input value of aIn[] */
    int n;                       /* Size of encoding at this position */
    u8 z[12];                    /* Encoding for number at this position */
  } *aAux;

  aAux = sqlite4StackAllocZero(db, sizeof(*aAux)*nIn);
  if( aAux==0 ) return SQLITE4_NOMEM;
  aOut = sqlite4DbMallocZero(db, (nIn+1)*9);
  if( aOut==0 ){
    rc = SQLITE4_NOMEM;
    goto vdbeEncodeData_error;
  }
  nOut = 9;
  for(i=0; i<nIn; i++){
    Mem *pIn = &aIn[ aPermute ? aPermute[i] : i ];
    int flags = pIn->flags;
    if( flags & MEM_Null ){
      aOut[nOut++] = 0;
    }else if( flags & MEM_Int ){
      i64 i1;
      i1 = sqlite4_num_to_int64(pIn->u.num, 0);
      n = significantBytes(i1);
      aOut[nOut++] = n+2;
      nPayload += n;
      aAux[i].n = n;
    }else if( flags & MEM_Real ){
      sqlite4_num *p = &pIn->u.num;
      int e;
      assert( p->sign==0 || p->sign==1 );
      if( p->e<0 ){
        e = (p->e*-4) + 2 + p->sign;
      }else{
        e = (p->e*4) + p->sign;
      }
      n = sqlite4PutVarint64(aAux[i].z, (sqlite4_uint64)e);
      n += sqlite4PutVarint64(aAux[i].z+n, p->m);
      aAux[i].n = n;
      aOut[nOut++] = n+9;
      nPayload += n;
    }else if( flags & MEM_Str ){
      n = pIn->n;
      if( n && (encoding!=SQLITE4_UTF8 || pIn->z[0]<3) ) n++;
      nPayload += n;
      nOut += sqlite4PutVarint64(aOut+nOut, 22+4*(sqlite4_int64)n);
    }else{
      n = pIn->n;
      assert( flags & MEM_Blob );
      nPayload += n;
      nOut += sqlite4PutVarint64(aOut+nOut, 23+4*(sqlite4_int64)n);
    }
  }
  nHdr = nOut - 9;
  n = sqlite4PutVarint64(aOut, nHdr);
  for(i=n, j=9; j<nOut; j++) aOut[i++] = aOut[j];
  nOut = i;
  aOut = sqlite4DbReallocOrFree(db, aOut, nOut + nPayload);
  if( aOut==0 ){ rc = SQLITE4_NOMEM; goto vdbeEncodeData_error; }
  for(i=0; i<nIn; i++){
    Mem *pIn = &aIn[ aPermute ? aPermute[i] : i ];
    int flags = pIn->flags;
    if( flags & MEM_Null ){
      /* No content */
    }else if( flags & MEM_Int ){
      sqlite4_int64 v;
      v = sqlite4_num_to_int64(pIn->u.num, 0);
      n = aAux[i].n;
      aOut[nOut+(--n)] = v & 0xff;
      while( n ){
        v >>= 8;
        aOut[nOut+(--n)] = v & 0xff;
      }
      nOut += aAux[i].n;
    }else if( flags & MEM_Real ){
      memcpy(aOut+nOut, aAux[i].z, aAux[i].n);
      nOut += aAux[i].n;
    }else if( flags & MEM_Str ){
      n = pIn->n;
      if( n ){
        if( encoding==SQLITE4_UTF16LE ) aOut[nOut++] = 1;
        else if( encoding==SQLITE4_UTF16BE ) aOut[nOut++] = 2;
        else if( pIn->z[0]<3 ) aOut[nOut++] = 0;
        memcpy(aOut+nOut, pIn->z, n);
        nOut += n;
      }
    }else{
      assert( flags & MEM_Blob );
      memcpy(aOut+nOut, pIn->z, pIn->n);
      nOut += pIn->n;
    }
  }

  *pzOut = aOut;
  *pnOut = nOut;
  sqlite4StackFree(db, aAux);
  return SQLITE4_OK;

vdbeEncodeData_error:
  sqlite4StackFree(db, aAux);
  sqlite4DbFree(db, aOut);
  return rc;
}

/*
** An output buffer for sqlite4VdbeEncodeKey
*/
typedef struct KeyEncoder KeyEncoder;
struct KeyEncoder {
  sqlite4 *db;   /* Database connection */
  u8 *aOut;      /* Output buffer */
  int nOut;      /* Slots of aOut[] used */
  int nAlloc;    /* Slots of aOut[] allocated */
};

/*
** Enlarge a memory allocation, if necessary
*/
static int enlargeEncoderAllocation(KeyEncoder *p, int needed){
  assert( p->nOut<=p->nAlloc );
  if( p->nOut+needed>p->nAlloc ){
    u8 *aNew;
    p->nAlloc = p->nAlloc + needed + 10;
    aNew = sqlite4DbRealloc(p->db, p->aOut, p->nAlloc);
    if( aNew==0 ){
      sqlite4DbFree(p->db, p->aOut);
      memset(p, 0, sizeof(*p));
      return SQLITE4_NOMEM;
    }
    p->aOut = aNew;
    p->nAlloc = sqlite4DbMallocSize(p->db, p->aOut);
  }
  return SQLITE4_OK;
}

/*
** Write value v as a varint into buffer p. If parameter bInvert
** is non-zero, write the ones-complement of each byte instead of
** the usual value.
*/
static void putVarint64(KeyEncoder *p, sqlite4_uint64 v, int bInvert){
  unsigned char *z = &p->aOut[p->nOut];
  int n = sqlite4PutVarint64(z, v);
  if( bInvert ){
    int i;
    for(i=0; i<n; i++) z[i] = ~z[i];
  }
  p->nOut += n;
}

/*
** Write value num into buffer p using the key encoding.
*/
static void encodeNumericKey(KeyEncoder *p, sqlite4_num num){
  if( num.m==0 ){
    if( sqlite4_num_isnan(num) ){
      p->aOut[p->nOut++] = 0x06;  /* NaN */
    }else{
      p->aOut[p->nOut++] = 0x15;  /* Numeric zero */
    }
  }else if( sqlite4_num_isinf(num) ){
    p->aOut[p->nOut++] = num.sign ? 0x07 : 0x23;  /* Neg and Pos infinity */
  }else{
    int e;
    u64 m;
    int iDigit = 0;
    u8 aDigit[12];

    while( (num.m % 10)==0 ){
      num.e++;
      num.m = num.m / 10;
    }
    m = num.m;
    e = num.e;

    if( num.e % 2 ){
      aDigit[0] = 10 * (m % 10);
      m = m / 10;
      e--;
      iDigit = 1;
    }else{
      iDigit = 0;
    }

    while( m ){
      aDigit[iDigit++] = (m % 100);
      m = m / 100;
    }
    e = (iDigit + (e/2));

    if( e>=11 ){                /* Large value */
      if( num.sign==0 ){
        p->aOut[p->nOut++] = 0x22;
        putVarint64(p, e, 0);
      }else{
        p->aOut[p->nOut++] = 0x08;
        putVarint64(p, e, 1);
      }
    }
    else if( e>=0 ){            /* Medium value */
      if( num.sign==0 ){
        p->aOut[p->nOut++] = 0x17+e;
      }else{
        p->aOut[p->nOut++] = 0x13-e;
      }
    }
    else{                       /* Small value */
      if( num.sign==0 ){
        p->aOut[p->nOut++] = 0x16;
        putVarint64(p, -1*e, 1);
      }else{
        p->aOut[p->nOut++] = 0x14;
        putVarint64(p, -1*e, 0);
      }
    }

    /* Write M to the output. */
    while( (iDigit--)>0 ){
      u8 d = aDigit[iDigit]*2;
      if( iDigit!=0 ) d |= 0x01;
      if( num.sign ) d = ~d;
      p->aOut[p->nOut++] = d;
    }
  }
}

/*
** Encode a single integer using the key encoding.  The caller must 
** ensure that sufficient space exits in a[] (at least 12 bytes).  
** The return value is the number of bytes of a[] used.  
*/
SQLITE4_PRIVATE int sqlite4VdbeEncodeIntKey(u8 *a, sqlite4_int64 v){
  KeyEncoder s;
  sqlite4_num num;

  num = sqlite4_num_from_int64(v);
  memset(&s, 0, sizeof(s));
  s.aOut = a;
  encodeNumericKey(&s, num);
  return s.nOut;
}

/*
** Encode a single column of the key
*/
static int encodeOneKeyValue(
  KeyEncoder *p,    /* Key encoder context */
  Mem *pMem,        /* Value to be encoded */
  u8 sortOrder,     /* Sort order for this value */
  u8 isLastValue,   /* True if this is the last value in the key */
  CollSeq *pColl    /* Collating sequence for the value */
){
  int flags = pMem->flags;
  int i;
  int n;
  int iStart = p->nOut;
  if( flags & MEM_Null ){
    if( enlargeEncoderAllocation(p, 1) ) return SQLITE4_NOMEM;
    p->aOut[p->nOut++] = 0x05;   /* NULL */
  }else
  if( flags & (MEM_Real|MEM_Int) ){
    if( enlargeEncoderAllocation(p, 16) ) return SQLITE4_NOMEM;
    encodeNumericKey(p, pMem->u.num);
  }else if( flags & MEM_Str ){
    int enc;                      /* Initial encoding of pMem */

    assert( pMem->enc==SQLITE4_UTF8 
         || pMem->enc==SQLITE4_UTF16LE
         || pMem->enc==SQLITE4_UTF16BE
    );
    assert( pMem->db );
    enc = pMem->enc;

    /* Write the encoded key to the output buffer. */
    if( enlargeEncoderAllocation(p, pMem->n*4 + 2) ) return SQLITE4_NOMEM;
    p->aOut[p->nOut++] = 0x24;   /* Text */
    if( pColl==0 || pColl->xMkKey==0 ){
      const char *z = (const char *)sqlite4ValueText(pMem, SQLITE4_UTF8);
      if( z ){
        const char *zCsr = z;
        const char *zEnd = &z[pMem->n];
        while( *zCsr && zCsr<zEnd ) zCsr++;
        memcpy(p->aOut+p->nOut, z, (zCsr-z));
        p->nOut += (zCsr-z);
      }
    }else{
      int rc;                     /* xMkKey() return code */
      int nReq;                   /* Space required by xMkKey() */
      int nSpc;                   /* Space available */

      nSpc = p->nAlloc-p->nOut;
      rc = pColl->xMkKey(pColl->pUser, pMem, nSpc, p->aOut+p->nOut, &nReq);
      if( rc!=SQLITE4_OK ) return rc;
      if( nReq+1>nSpc ){
        if( enlargeEncoderAllocation(p, nReq+1) ) return SQLITE4_NOMEM;
        rc = pColl->xMkKey(pColl->pUser, pMem, nReq, p->aOut+p->nOut, &nReq);
      }
      p->nOut += nReq;
    }
    p->aOut[p->nOut++] = 0x00;

    /* If the operations above changed the encoding of pMem, change it back.
    ** This call is a no-op if pMem was not modified by the code above.  */
    sqlite4VdbeChangeEncoding(pMem, enc);

  }else if( isLastValue ){
    /* A BLOB value that is the right-most value of a key */
    assert( flags & MEM_Blob );
    if( enlargeEncoderAllocation(p, pMem->n+1) ) return SQLITE4_NOMEM;
    p->aOut[p->nOut++] = 0x26;
    memcpy(p->aOut+p->nOut, pMem->z, pMem->n);
    p->nOut += pMem->n;
  }else{
    /* A BLOB value that is followed by other values */
    const unsigned char *a;
    unsigned char s, t;
    assert( flags & MEM_Blob );
    n = pMem->n;
    a = (u8*)pMem->z;
    s = 1;
    t = 0;
    if( enlargeEncoderAllocation(p, (n*8+6)/7 + 2) ) return SQLITE4_NOMEM;
    p->aOut[p->nOut++] = 0x25;   /* Blob */
    for(i=0; i<n; i++){
      unsigned char x = a[i];
      p->aOut[p->nOut++] = 0x80 | t | (x>>s);
      if( s<7 ){
        t = x<<(7-s);
        s++;
      }else{
        p->aOut[p->nOut++] = 0x80 | x;
        s = 1;
        t = 0;
      }
    }
    if( s>1 ) p->aOut[p->nOut++] = 0x80 | t;
    p->aOut[p->nOut++] = 0x00;
  }
  if( sortOrder==SQLITE4_SO_DESC ){
    for(i=iStart; i<p->nOut; i++) p->aOut[i] ^= 0xff;
  }
  assert( p->nOut<=p->nAlloc );
  return SQLITE4_OK;
}

/*
** Variables aKey/nKey contain an encoded index key. This function returns
** the length (in bytes) of the key with all but the first nField fields
** removed.
*/
SQLITE4_PRIVATE int sqlite4VdbeShortKey(
  const u8 *aKey,                 /* Buffer containing encoded key */
  int nKey,                       /* Size of buffer aKey[] in bytes */
  int nField,                     /* Number of fields */
  int *pnOut                      /* Number of complete fields read (or NULL) */
){
  u8 *p = (u8*)aKey;
  u8 *pEnd = (u8*)&aKey[nKey];
  u64 dummy;
  int i;

  /* Skip over the "root page" number at the start of the key */
  p += sqlite4GetVarint64(p, pEnd-p, &dummy);

  for(i=0; i<nField && p<pEnd; i++){
    u8 c = *(p++);
    switch( c ){

      case 0x05: case 0xFA:       /* NULL */
      case 0x06: case 0xF9:       /* NaN */
      case 0x07: case 0xF8:       /* -ve infinity */
      case 0x15: case 0xEA:       /* zero */
      case 0x23: case 0xDC:       /* +ve infinity */
        break;

      case 0x24:                  /* Text (ascending index) */
      case 0x25:                  /* Blob (ascending index) */
        while( *(p++) );
        break;

      case 0xDB:                  /* Text (descending index) */
      case 0xDA:                  /* Blob (descending index) */
        while( (0xFF!=*(p++)) );
        break;

      case 0x26:                  /* Blob-final (ascending) */
      case 0xD9:                  /* Blob-final (descending) */
        p = pEnd;
        break;

      case 0x22: case 0xDD:       /* Large positive number */
      case 0x14: case 0xEB:       /* Small negative number */
      case 0x16: case 0xE9:       /* Small positive number */
      case 0x08: case 0xF7: {     /* Large negative number */
        u8 d;                     /* Value of byte following "c" */

        /* For large positive and small negative integer keys skip over
        ** a varint here. For small positive integers and larger negative 
        ** integers, skip over the ones-complement varint.  */
        if( c==0x16 || c==0x08 || c==0xDD || c==0xEB ){
          d = ~(*(p++));
        }else{
          d = *(p++);
        }
        if( d>240 ){
          p++;
          if( d>248 ) p += (d - 248);
        }

        /* Fall through */
      }

      default:                    /* Medium sized number */
        if( c<0x15 || (c>0xDC && c<0xEA) ){
          while( !((*p++) & 0x01) );
        }else{
          while( ((*p++) & 0x01) );
        }
        break;
    }

    if( p>pEnd ) break;
  }
  if( pnOut ) *pnOut = i;

  return (p - aKey);
}

/*
** Generate a database key from one or more data values.
**
** Space to hold the key is obtained from sqlite4DbMalloc() and should
** be freed by the caller using sqlite4DbFree() to avoid a memory leak.
*/
SQLITE4_PRIVATE int sqlite4VdbeEncodeKey(
  sqlite4 *db,                 /* The database connection */
  Mem *aIn,                    /* Values to be encoded */
  int nIn,                     /* Number of entries in aIn[] */
  int iTabno,                  /* The table this key applies to, or negative */
  KeyInfo *pKeyInfo,           /* Collating sequence and sort-order info */
  u8 **paOut,                  /* Write the resulting key here */
  int *pnOut,                  /* Number of bytes in the key */
  int nExtra                   /* extra bytes of space appended to the key */
){
  int i;
  int rc = SQLITE4_OK;
  KeyEncoder x;
  u8 *so;
  CollSeq **aColl;

  assert( pKeyInfo );
  assert( nIn<=pKeyInfo->nField );

  x.db = db;
  x.aOut = 0;
  x.nOut = 0;
  x.nAlloc = 0;
  *paOut = 0;
  *pnOut = 0;

  if( enlargeEncoderAllocation(&x, (nIn+1)*10) ) return SQLITE4_NOMEM;
  if( iTabno>=0 ){
    x.nOut = sqlite4PutVarint64(x.aOut, iTabno);
  }
  aColl = pKeyInfo->aColl;
  so = pKeyInfo->aSortOrder;
  for(i=0; i<nIn && rc==SQLITE4_OK; i++){
    rc = encodeOneKeyValue(&x, aIn+i, so ? so[i] : SQLITE4_SO_ASC,
                           i==pKeyInfo->nField-1, aColl[i]);
  }

  if( rc==SQLITE4_OK && nExtra ){ rc = enlargeEncoderAllocation(&x, nExtra); }
  if( rc ){
    sqlite4DbFree(db, x.aOut);
  }else{
    *paOut = x.aOut;
    *pnOut = x.nOut;
  }
  return rc;
}

/************** End of vdbecodec.c *******************************************/
/************** Begin file vdbecursor.c **************************************/
/*
** 2012-02-16
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains methods for the VdbeCursor object.
**
** A VdbeCursor is an abstraction of the KVCursor that includes knowledge
** about different "tables" in the key space.  A VdbeCursor is only active
** over a particular table.  Thus, for example, sqlite4VdbeNext() will
** return SQLITE4_NOTFOUND when advancing off the end of a table into the
** next table whereas the lower-level sqlite4KVCursorNext() routine will
** not return SQLITE4_NOTFOUND until it is advanced off the end of the very
** last table in the database.
*/


/*
** Move a VDBE cursor to the first or to the last element of its table.  The
** first element is sought if iEnd==+1 and the last element if iEnd==-1.
**
** Return SQLITE4_OK on success. Return SQLITE4_NOTFOUND if the table is empty.
** Other error codes are also possible for various kinds of errors.
*/
SQLITE4_PRIVATE int sqlite4VdbeSeekEnd(VdbeCursor *pC, int iEnd){
  KVCursor *pCur = pC->pKVCur;
  int rc;
  KVSize nProbe;
  KVByteArray aProbe[16];

  assert( iEnd==(+1) || iEnd==(-1) || iEnd==(-2) );  
  if( pC->iRoot==KVSTORE_ROOT ){
    if( iEnd>0 ){
      rc = sqlite4KVCursorSeek(pCur, (const KVByteArray *)"\00", 1, iEnd);
    }else{
      nProbe = sqlite4PutVarint64(aProbe, LARGEST_INT64);
      rc = sqlite4KVCursorSeek(pCur, aProbe, nProbe, iEnd);
    }
    if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
  }else{
    const KVByteArray *aKey;
    KVSize nKey;

    nProbe = sqlite4PutVarint64(aProbe, pC->iRoot);
    aProbe[nProbe] = 0xFF;

    rc = sqlite4KVCursorSeek(pCur, aProbe, nProbe+(iEnd<0), iEnd);
    if( rc==SQLITE4_OK ){
      rc = SQLITE4_CORRUPT_BKPT;
    }else if( rc==SQLITE4_INEXACT ){
      rc = sqlite4KVCursorKey(pCur, &aKey, &nKey);
      if( rc==SQLITE4_OK && (nKey<nProbe || memcmp(aKey, aProbe, nProbe)!=0) ){
        rc = SQLITE4_NOTFOUND;
      }
    }
    pC->rowChnged = 1;
  }

  return rc;
}

/*
** Move a VDBE cursor to the next element in its table.
** Return SQLITE4_NOTFOUND if the seek falls of the end of the table.
*/
SQLITE4_PRIVATE int sqlite4VdbeNext(VdbeCursor *pC){
  KVCursor *pCur = pC->pKVCur;
  const KVByteArray *aKey;
  KVSize nKey;
  int rc;
  sqlite4_uint64 iTabno;

  rc = sqlite4KVCursorNext(pCur);
  if( rc==SQLITE4_OK && pC->iRoot!=KVSTORE_ROOT ){
    rc = sqlite4KVCursorKey(pCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      iTabno = 0;
      sqlite4GetVarint64(aKey, nKey, &iTabno);
      if( iTabno!=pC->iRoot ) rc = SQLITE4_NOTFOUND;
    }
  }
  pC->rowChnged = 1;
  return rc;
}

/*
** Move a VDBE cursor to the previous element in its table.
** Return SQLITE4_NOTFOUND if the seek falls of the end of the table.
*/
SQLITE4_PRIVATE int sqlite4VdbePrevious(VdbeCursor *pC){
  KVCursor *pCur = pC->pKVCur;
  const KVByteArray *aKey;
  KVSize nKey;
  int rc;
  sqlite4_uint64 iTabno;

  rc = sqlite4KVCursorPrev(pCur);
  if( rc==SQLITE4_OK && pC->iRoot!=KVSTORE_ROOT ){
    rc = sqlite4KVCursorKey(pCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      iTabno = 0;
      sqlite4GetVarint64(aKey, nKey, &iTabno);
      if( iTabno!=pC->iRoot ) rc = SQLITE4_NOTFOUND;
    }
  }
  pC->rowChnged = 1;
  return rc;
}


/*
** Close a VDBE cursor and release all the resources that cursor 
** happens to hold.
*/
SQLITE4_PRIVATE void sqlite4VdbeFreeCursor(VdbeCursor *pCx){
  if( pCx==0 ){
    return;
  }
  sqlite4Fts5Close(pCx->pFts);
  if( pCx->pKVCur ){
    sqlite4KVCursorClose(pCx->pKVCur);
  }
  if( pCx->pTmpKV ){
    sqlite4KVStoreClose(pCx->pTmpKV);
  }
  if( pCx->pDecoder ){
    sqlite4VdbeDecoderDestroy(pCx->pDecoder);
    pCx->pDecoder = 0;
  }
  sqlite4_buffer_clear(&pCx->sSeekKey);
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( pCx->pVtabCursor ){
    sqlite4_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
    const sqlite4_module *pModule = pCx->pModule;
    p->inVtabMethod = 1;
    pModule->xClose(pVtabCursor);
    p->inVtabMethod = 0;
  }
#endif
}


/*
** Cursor pPk is open on a primary key index. If there is currently a
** deferred seek pending on the cursor, do the actual seek now.
**
** If the operation is a success, SQLITE4_OK is returned. Or, if the
** required entry is not found in the PK index, SQLITE4_CORRUPT. Or if 
** some other error occurs, an error code is returned.
*/
SQLITE4_PRIVATE int sqlite4VdbeCursorMoveto(VdbeCursor *pPk){
  int rc = SQLITE4_OK;            /* Return code */
  if( pPk->sSeekKey.n!=0 ){
    assert( pPk->pKeyInfo->nPK==0 );
    rc = sqlite4KVCursorSeek(pPk->pKVCur, pPk->sSeekKey.p, pPk->sSeekKey.n, 0);
    if( rc==SQLITE4_NOTFOUND ){
      rc = SQLITE4_CORRUPT_BKPT;
    }
    pPk->nullRow = 0;
    pPk->sSeekKey.n = 0;
    pPk->rowChnged = 1;
  }
  return rc;
}

/************** End of vdbecursor.c ******************************************/
/************** Begin file vdbetrace.c ***************************************/
/*
** 2009 November 25
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code used to insert the values of host parameters
** (aka "wildcards") into the SQL text output by sqlite4_trace().
**
** The Vdbe parse-tree explainer is also found here.
*/

#ifndef SQLITE4_OMIT_TRACE

/*
** zSql is a zero-terminated string of UTF-8 SQL text.  Return the number of
** bytes in this text up to but excluding the first character in
** a host parameter.  If the text contains no host parameters, return
** the total number of bytes in the text.
*/
static int findNextHostParameter(const char *zSql, int *pnToken){
  int tokenType;
  int nTotal = 0;
  int n;

  *pnToken = 0;
  while( zSql[0] ){
    n = sqlite4GetToken((u8*)zSql, &tokenType);
    assert( n>0 && tokenType!=TK_ILLEGAL );
    if( tokenType==TK_VARIABLE ){
      *pnToken = n;
      break;
    }
    nTotal += n;
    zSql += n;
  }
  return nTotal;
}

/*
** This function returns a pointer to a nul-terminated string in memory
** obtained from sqlite4DbMalloc(). If sqlite4.vdbeExecCnt is 1, then the
** string contains a copy of zRawSql but with host parameters expanded to 
** their current bindings. Or, if sqlite4.vdbeExecCnt is greater than 1, 
** then the returned string holds a copy of zRawSql with "-- " prepended
** to each line of text.
**
** The calling function is responsible for making sure the memory returned
** is eventually freed.
**
** ALGORITHM:  Scan the input string looking for host parameters in any of
** these forms:  ?, ?N, $A, @A, :A.  Take care to avoid text within
** string literals, quoted identifier names, and comments.  For text forms,
** the host parameter index is found by scanning the perpared
** statement for the corresponding OP_Variable opcode.  Once the host
** parameter index is known, locate the value in p->aVar[].  Then render
** the value as a literal in place of the host parameter name.
*/
SQLITE4_PRIVATE char *sqlite4VdbeExpandSql(
  Vdbe *p,                 /* The prepared statement being evaluated */
  const char *zRawSql      /* Raw text of the SQL statement */
){
  sqlite4 *db;             /* The database connection */
  int idx = 0;             /* Index of a host parameter */
  int nextIndex = 1;       /* Index of next ? host parameter */
  int n;                   /* Length of a token prefix */
  int nToken;              /* Length of the parameter token */
  int i;                   /* Loop counter */
  Mem *pVar;               /* Value of a host parameter */
  StrAccum out;            /* Accumulate the output here */
  char zBase[100];         /* Initial working space */

  db = p->db;
  sqlite4StrAccumInit(&out, zBase, sizeof(zBase), 
                      db->aLimit[SQLITE4_LIMIT_LENGTH]);
  out.db = db;
  out.pEnv = db->pEnv;
  if( db->vdbeExecCnt>1 ){
    while( *zRawSql ){
      const char *zStart = zRawSql;
      while( *(zRawSql++)!='\n' && *zRawSql );
      sqlite4StrAccumAppend(&out, "-- ", 3);
      sqlite4StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
    }
  }else{
    while( zRawSql[0] ){
      n = findNextHostParameter(zRawSql, &nToken);
      assert( n>0 );
      sqlite4StrAccumAppend(&out, zRawSql, n);
      zRawSql += n;
      assert( zRawSql[0] || nToken==0 );
      if( nToken==0 ) break;
      if( zRawSql[0]=='?' ){
        if( nToken>1 ){
          assert( sqlite4Isdigit(zRawSql[1]) );
          sqlite4GetInt32(&zRawSql[1], &idx);
        }else{
          idx = nextIndex;
        }
      }else{
        assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
        testcase( zRawSql[0]==':' );
        testcase( zRawSql[0]=='$' );
        testcase( zRawSql[0]=='@' );
        idx = sqlite4VdbeParameterIndex(p, zRawSql, nToken);
        assert( idx>0 );
      }
      zRawSql += nToken;
      nextIndex = idx + 1;
      assert( idx>0 && idx<=p->nVar );
      pVar = &p->aVar[idx-1];
      if( pVar->flags & MEM_Null ){
        sqlite4StrAccumAppend(&out, "NULL", 4);
      }else if( pVar->flags & (MEM_Int|MEM_Real) ){
        char aOut[30];
        sqlite4_num_to_text(pVar->u.num, aOut, (pVar->flags & MEM_Real));
        sqlite4XPrintf(&out, "%s", aOut);
      }else if( pVar->flags & MEM_Str ){
#ifndef SQLITE4_OMIT_UTF16
        u8 enc = ENC(db);
        if( enc!=SQLITE4_UTF8 ){
          Mem utf8;
          memset(&utf8, 0, sizeof(utf8));
          utf8.db = db;
          sqlite4VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE4_STATIC, 0);
          sqlite4VdbeChangeEncoding(&utf8, SQLITE4_UTF8);
          sqlite4XPrintf(&out, "'%.*q'", utf8.n, utf8.z);
          sqlite4VdbeMemRelease(&utf8);
        }else
#endif
        {
          sqlite4XPrintf(&out, "'%.*q'", pVar->n, pVar->z);
        }
      }else{
        assert( pVar->flags & MEM_Blob );
        sqlite4StrAccumAppend(&out, "x'", 2);
        for(i=0; i<pVar->n; i++){
          sqlite4XPrintf(&out, "%02x", pVar->z[i]&0xff);
        }
        sqlite4StrAccumAppend(&out, "'", 1);
      }
    }
  }
  return sqlite4StrAccumFinish(&out);
}

#endif /* #ifndef SQLITE4_OMIT_TRACE */

/*****************************************************************************
** The following code implements the data-structure explaining logic
** for the Vdbe.
*/

#if defined(SQLITE4_ENABLE_TREE_EXPLAIN)

/*
** Allocate a new Explain object
*/
SQLITE4_PRIVATE void sqlite4ExplainBegin(Vdbe *pVdbe){
  if( pVdbe ){
    Explain *p;
    sqlite4 *db = pVdbe->db;
    sqlite4_env *pEnv = db->pEnv;
    sqlite4BeginBenignMalloc(pEnv);
    p = sqlite4_malloc(pEnv, sizeof(Explain) );
    if( p ){
      memset(p, 0, sizeof(*p));
      p->pVdbe = pVdbe;
      sqlite4_free(pEnv, pVdbe->pExplain);
      pVdbe->pExplain = p;
      sqlite4StrAccumInit(&p->str, p->zBase, sizeof(p->zBase),
                          SQLITE4_MAX_LENGTH);
      p->str.useMalloc = 2;
      p->str.pEnv = pEnv;
    }else{
      sqlite4EndBenignMalloc(pEnv);
    }
  }
}

/*
** Return true if the Explain ends with a new-line.
*/
static int endsWithNL(Explain *p){
  return p && p->str.zText && p->str.nChar
           && p->str.zText[p->str.nChar-1]=='\n';
}
    
/*
** Append text to the indentation
*/
SQLITE4_PRIVATE void sqlite4ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
  Explain *p;
  if( pVdbe && (p = pVdbe->pExplain)!=0 ){
    va_list ap;
    if( p->nIndent && endsWithNL(p) ){
      int n = p->nIndent;
      if( n>ArraySize(p->aIndent) ) n = ArraySize(p->aIndent);
      sqlite4AppendSpace(&p->str, p->aIndent[n-1]);
    }   
    va_start(ap, zFormat);
    sqlite4VXPrintf(&p->str, 1, zFormat, ap);
    va_end(ap);
  }
}

/*
** Append a '\n' if there is not already one.
*/
SQLITE4_PRIVATE void sqlite4ExplainNL(Vdbe *pVdbe){
  Explain *p;
  if( pVdbe && (p = pVdbe->pExplain)!=0 && !endsWithNL(p) ){
    sqlite4StrAccumAppend(&p->str, "\n", 1);
  }
}

/*
** Push a new indentation level.  Subsequent lines will be indented
** so that they begin at the current cursor position.
*/
SQLITE4_PRIVATE void sqlite4ExplainPush(Vdbe *pVdbe){
  Explain *p;
  if( pVdbe && (p = pVdbe->pExplain)!=0 ){
    if( p->str.zText && p->nIndent<ArraySize(p->aIndent) ){
      const char *z = p->str.zText;
      int i = p->str.nChar-1;
      int x;
      while( i>=0 && z[i]!='\n' ){ i--; }
      x = (p->str.nChar - 1) - i;
      if( p->nIndent && x<p->aIndent[p->nIndent-1] ){
        x = p->aIndent[p->nIndent-1];
      }
      p->aIndent[p->nIndent] = x;
    }
    p->nIndent++;
  }
}

/*
** Pop the indentation stack by one level.
*/
SQLITE4_PRIVATE void sqlite4ExplainPop(Vdbe *p){
  if( p && p->pExplain ) p->pExplain->nIndent--;
}

/*
** Free the indentation structure
*/
SQLITE4_PRIVATE void sqlite4ExplainFinish(Vdbe *pVdbe){
  if( pVdbe && pVdbe->pExplain ){
    sqlite4_env *pEnv = pVdbe->db->pEnv;
    sqlite4_free(pEnv, pVdbe->zExplain);
    sqlite4ExplainNL(pVdbe);
    pVdbe->zExplain = sqlite4StrAccumFinish(&pVdbe->pExplain->str);
    sqlite4_free(pEnv, pVdbe->pExplain);
    pVdbe->pExplain = 0;
    sqlite4EndBenignMalloc(pEnv);
  }
}

/*
** Return the explanation of a virtual machine.
*/
SQLITE4_PRIVATE const char *sqlite4VdbeExplanation(Vdbe *pVdbe){
  return (pVdbe && pVdbe->zExplain) ? pVdbe->zExplain : 0;
}
#endif /* defined(SQLITE4_DEBUG) */

/************** End of vdbetrace.c *******************************************/
/************** Begin file vdbe.c ********************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** The code in this file implements execution method of the 
** Virtual Database Engine (VDBE).  A separate file ("vdbeaux.c")
** handles housekeeping details such as creating and deleting
** VDBE instances.  This file is solely interested in executing
** the VDBE program.
**
** In the external interface, an "sqlite4_stmt*" is an opaque pointer
** to a VDBE.
**
** The SQL parser generates a program which is then executed by
** the VDBE to do the work of the SQL statement.  VDBE programs are 
** similar in form to assembly language.  The program consists of
** a linear sequence of operations.  Each operation has an opcode 
** and 5 operands.  Operands P1, P2, and P3 are integers.  Operand P4 
** is a null-terminated string.  Operand P5 is an unsigned character.
** Few opcodes use all 5 operands.
**
** Computation results are stored on a set of registers numbered beginning
** with 1 and going up to Vdbe.nMem.  Each register can store
** either an integer, a null-terminated string, a floating point
** number, or the SQL "NULL" value.  An implicit conversion from one
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqlite4VdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
*/

/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell.  This macro verifies that shallow copies are
** not misused.
*/
#ifdef SQLITE4_DEBUG
# define memAboutToChange(P,M) sqlite4VdbeMemAboutToChange(P,M)
#else
# define memAboutToChange(P,M)
#endif

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes.  The test
** procedures use this information to make sure that indices are
** working correctly.  This variable has no function other than to
** help verify the correct operation of the library.
*/
#ifdef SQLITE4_TEST
SQLITE4_API int sqlite4_search_count = 0;
#endif

/*
** When this global variable is positive, it gets decremented once before
** each instruction in the VDBE.  When it reaches zero, the u1.isInterrupted
** field of the sqlite4 structure is set in order to simulate an interrupt.
**
** This facility is used for testing purposes only.  It does not function
** in an ordinary build.
*/
#ifdef SQLITE4_TEST
SQLITE4_API int sqlite4_interrupt_count = 0;
#endif

/*
** The next global variable is incremented each type the OP_Sort opcode
** is executed.  The test procedures use this information to make sure that
** sorting is occurring or not occurring at appropriate times.   This variable
** has no function other than to help verify the correct operation of the
** library.
*/
#ifdef SQLITE4_TEST
SQLITE4_API int sqlite4_sort_count = 0;
#endif

/*
** The next global variable records the size of the largest MEM_Blob
** or MEM_Str that has been used by a VDBE opcode.  The test procedures
** use this information to make sure that the zero-blob functionality
** is working correctly.   This variable has no function other than to
** help verify the correct operation of the library.
*/
#ifdef SQLITE4_TEST
SQLITE4_API int sqlite4_max_blobsize = 0;
static void updateMaxBlobsize(Mem *p){
  if( (p->flags & (MEM_Str|MEM_Blob))!=0 && p->n>sqlite4_max_blobsize ){
    sqlite4_max_blobsize = p->n;
  }
}
#endif

/*
** The next global variable is incremented each type the OP_Found opcode
** is executed. This is used to test whether or not the foreign key
** operation implemented using OP_FkIsZero is working. This variable
** has no function other than to help verify the correct operation of the
** library.
*/
#ifdef SQLITE4_TEST
SQLITE4_API int sqlite4_found_count = 0;
#endif

/*
** Test a register to see if it exceeds the current maximum blob size.
** If it does, record the new maximum blob size.
*/
#if defined(SQLITE4_TEST) && !defined(SQLITE4_OMIT_BUILTIN_TEST)
# define UPDATE_MAX_BLOBSIZE(P)  updateMaxBlobsize(P)
#else
# define UPDATE_MAX_BLOBSIZE(P)
#endif

/*
** Convert the given register into a string if it isn't one
** already. Return non-zero if a malloc() fails.
*/
#define Stringify(P, enc) \
   if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite4VdbeMemStringify(P,enc)) \
     { goto no_mem; }

/*
** An ephemeral string value (signified by the MEM_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
** is responsible for deallocating that string.  Because the register
** does not control the string, it might be deleted without the register
** knowing it.
**
** This routine converts an ephemeral string into a dynamically allocated
** string that the register itself controls.  In other words, it
** converts an MEM_Ephem string into an MEM_Dyn string.
*/
#define Deephemeralize(P) \
   if( ((P)->flags&MEM_Ephem)!=0 \
       && sqlite4VdbeMemMakeWriteable(P) ){ goto no_mem;}

/*
** 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.
** This routine sets the pMem->type variable used by the sqlite4_value_*() 
** routines.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemStoreType(Mem *pMem){
  int flags = pMem->flags;
  if( flags & MEM_Null ){
    pMem->type = SQLITE4_NULL;
  }
  else if( flags & MEM_Int ){
    pMem->type = SQLITE4_INTEGER;
  }
  else if( flags & MEM_Real ){
    pMem->type = SQLITE4_FLOAT;
  }
  else if( flags & MEM_Str ){
    pMem->type = SQLITE4_TEXT;
  }else{
    pMem->type = SQLITE4_BLOB;
  }
}

/*
** Allocate VdbeCursor number iCur.  Return a pointer to it.  Return NULL
** if we run out of memory.
*/
static VdbeCursor *allocateCursor(
  Vdbe *p,              /* The virtual machine */
  int iCur,             /* Index of the new VdbeCursor */
  int nField,           /* Number of fields in the table or index */
  int iDb,              /* Database the cursor belongs to, or -1 */
  int isTrueCursor      /* True real cursor.  False for pseudo-table or vtab */
){
  /* Find the memory cell that will be used to store the blob of memory
  ** required for this VdbeCursor structure. It is convenient to use a 
  ** vdbe memory cell to manage the memory allocation required for a
  ** VdbeCursor structure for the following reasons:
  **
  **   * Sometimes cursor numbers are used for a couple of different
  **     purposes in a vdbe program. The different uses might require
  **     different sized allocations. Memory cells provide growable
  **     allocations.
  **
  ** Memory cells for cursors are allocated at the top of the address
  ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for
  ** cursor 1 is managed by memory cell (p->nMem-1), etc.
  */
  Mem *pMem = &p->aMem[p->nMem-iCur];

  int nByte;
  VdbeCursor *pCx = 0;
  nByte = 
      ROUND8(sizeof(VdbeCursor)) + 
      2*nField*sizeof(u32);

  assert( iCur<p->nCursor );
  if( p->apCsr[iCur] ){
    sqlite4VdbeFreeCursor(p->apCsr[iCur]);
    p->apCsr[iCur] = 0;
  }
  if( SQLITE4_OK==sqlite4VdbeMemGrow(pMem, nByte, 0) ){
    p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
    memset(pCx, 0, sizeof(VdbeCursor));
    pCx->db = p->db;
    pCx->iDb = iDb;
    pCx->nField = nField;
    pCx->rowChnged = 1;
    sqlite4_buffer_init(&pCx->sSeekKey, p->db->pEnv->pMM);
  }
  return pCx;
}

/*
** Try to convert a value into a numeric representation if we can
** do so without loss of information.  In other words, if the string
** looks like a number, convert it into a number.  If it does not
** look like a number, leave it alone.
*/
static void applyNumericAffinity(Mem *pRec){
  if( (pRec->flags & (MEM_Real|MEM_Int))==0 && (pRec->flags & MEM_Str) ){
    int flags = pRec->enc | SQLITE4_IGNORE_WHITESPACE;
    int bReal = 0;
    sqlite4_num num;
    
    num = sqlite4_num_from_text(pRec->z, pRec->n, flags, &bReal);
    if( sqlite4_num_isnan(num)==0 ){
      pRec->u.num = num;
      MemSetTypeFlag(pRec, (bReal ? MEM_Real : MEM_Int));
    }
  }
}

/*
** Processing is determine by the affinity parameter:
**
** SQLITE4_AFF_INTEGER:
** SQLITE4_AFF_REAL:
** SQLITE4_AFF_NUMERIC:
**    Try to convert pRec to an integer representation or a 
**    floating-point representation if an integer representation
**    is not possible.  Note that the integer representation is
**    always preferred, even if the affinity is REAL, because
**    an integer representation is more space efficient on disk.
**
** SQLITE4_AFF_TEXT:
**    Convert pRec to a text representation.
**
** SQLITE4_AFF_NONE:
**    No-op.  pRec is unchanged.
*/
static void applyAffinity(
  Mem *pRec,          /* The value to apply affinity to */
  char affinity,      /* The affinity to be applied */
  u8 enc              /* Use this text encoding */
){
  if( affinity==SQLITE4_AFF_TEXT ){
    /* Only attempt the conversion to TEXT if there is an integer or real
    ** representation (blob and NULL do not get converted) but no string
    ** representation.
    */
    if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
      sqlite4VdbeMemStringify(pRec, enc);
    }
    pRec->flags &= ~(MEM_Real|MEM_Int);
  }else if( affinity!=SQLITE4_AFF_NONE ){
    assert( affinity==SQLITE4_AFF_INTEGER || affinity==SQLITE4_AFF_REAL
             || affinity==SQLITE4_AFF_NUMERIC );
    applyNumericAffinity(pRec);
    if( pRec->flags & MEM_Real ){
      sqlite4VdbeIntegerAffinity(pRec);
    }
  }
}

/*
** Try to convert the type of a function argument or a result column
** into a numeric representation.  Use either INTEGER or REAL whichever
** is appropriate.  But only do the conversion if it is possible without
** loss of information and return the revised type of the argument.
*/
SQLITE4_API int sqlite4_value_numeric_type(sqlite4_value *pVal){
  Mem *pMem = (Mem*)pVal;
  if( pMem->type==SQLITE4_TEXT ){
    applyNumericAffinity(pMem);
    sqlite4VdbeMemStoreType(pMem);
  }
  return pMem->type;
}

SQLITE4_API sqlite4_num sqlite4_value_num(sqlite4_value *pVal){
  return sqlite4VdbeNumValue((Mem*)pVal);
}

/*
** Exported version of applyAffinity(). This one works on sqlite4_value*, 
** not the internal Mem* type.
*/
SQLITE4_PRIVATE void sqlite4ValueApplyAffinity(
  sqlite4_value *pVal, 
  u8 affinity, 
  u8 enc
){
  applyAffinity((Mem *)pVal, affinity, enc);
}

#ifdef SQLITE4_DEBUG
/*
** Write a nice string representation of the contents of cell pMem
** into buffer zBuf, length nBuf.
*/
SQLITE4_PRIVATE void sqlite4VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
  char *zCsr = zBuf;
  int f = pMem->flags;

  static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"};

  if( f&MEM_Blob ){
    int i;
    char c;
    if( f & MEM_Dyn ){
      c = 'z';
      assert( (f & (MEM_Static|MEM_Ephem))==0 );
    }else if( f & MEM_Static ){
      c = 't';
      assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
    }else if( f & MEM_Ephem ){
      c = 'e';
      assert( (f & (MEM_Static|MEM_Dyn))==0 );
    }else{
      c = 's';
    }

    zCsr += sqlite4_snprintf(zCsr, 100, "%c", c);
    zCsr += sqlite4_snprintf(zCsr, 100, "%d[", pMem->n);
    for(i=0; i<16 && i<pMem->n; i++){
      zCsr += sqlite4_snprintf(zCsr, 100, "%02X", ((int)pMem->z[i] & 0xFF));
    }
    for(i=0; i<16 && i<pMem->n; i++){
      char z = pMem->z[i];
      if( z<32 || z>126 ) *zCsr++ = '.';
      else *zCsr++ = z;
    }

    zCsr += sqlite4_snprintf(zCsr, 100, "]%s", encnames[pMem->enc]);
    *zCsr = '\0';
  }else if( f & MEM_Str ){
    int j, k;
    zBuf[0] = ' ';
    if( f & MEM_Dyn ){
      zBuf[1] = 'z';
      assert( (f & (MEM_Static|MEM_Ephem))==0 );
    }else if( f & MEM_Static ){
      zBuf[1] = 't';
      assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
    }else if( f & MEM_Ephem ){
      zBuf[1] = 'e';
      assert( (f & (MEM_Static|MEM_Dyn))==0 );
    }else{
      zBuf[1] = 's';
    }
    k = 2;
    k += sqlite4_snprintf(&zBuf[k], 100, "%d", pMem->n);
    zBuf[k++] = '[';
    for(j=0; j<15 && j<pMem->n; j++){
      u8 c = pMem->z[j];
      if( c>=0x20 && c<0x7f ){
        zBuf[k++] = c;
      }else{
        zBuf[k++] = '.';
      }
    }
    zBuf[k++] = ']';
    k += sqlite4_snprintf(&zBuf[k], 100, encnames[pMem->enc]);
    zBuf[k++] = 0;
  }
}
#endif

#ifdef SQLITE4_DEBUG
/*
** Print the value of a register for tracing purposes:
*/
static void memTracePrint(FILE *out, Mem *p){
  if( p->flags & MEM_Null ){
    fprintf(out, " NULL");
  }else if( p->flags & (MEM_Int|MEM_Real) ){
    char aNum[31];
    char *zFlags = "r";
    sqlite4_num_to_text(p->u.num, aNum, (p->flags & MEM_Real));
    if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){
      zFlags = "si";
    }else if( p->flags & MEM_Int ){
      zFlags = "i";
    }
    fprintf(out, " %s:%s", zFlags, aNum);
  }else if( p->flags & MEM_RowSet ){
    fprintf(out, " (keyset)");
  }else{
    char zBuf[200];
    sqlite4VdbeMemPrettyPrint(p, zBuf);
    fprintf(out, " ");
    fprintf(out, "%s", zBuf);
  }
}
static void registerTrace(FILE *out, int iReg, Mem *p){
  fprintf(out, "REG[%d] = ", iReg);
  memTracePrint(out, p);
  fprintf(out, "\n");
}
#endif

#ifdef SQLITE4_DEBUG
static int assertFlagsOk(Mem *p){
  u16 flags = p->flags;
  assert( (flags&MEM_Int)==0 || (flags&MEM_Real)==0 );
  return 1;
}
#endif

#ifdef SQLITE4_DEBUG
# define REGISTER_TRACE(R,M) \
    if(assertFlagsOk(M) && p->trace)registerTrace(p->trace,R,M)
#else
# define REGISTER_TRACE(R,M)
#endif


#ifdef VDBE_PROFILE

/* 
** hwtime.h contains inline assembler code for implementing 
** high-performance timing routines.
*/
/************** Include hwtime.h in the middle of vdbe.c *********************/
/************** Begin file hwtime.h ******************************************/
/*
** 2008 May 27
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains inline asm code for retrieving "high-performance"
** counters for x86 class CPUs.
*/
#ifndef _HWTIME_H_
#define _HWTIME_H_

/*
** The following routine only works on pentium-class (or newer) processors.
** It uses the RDTSC opcode to read the cycle count value out of the
** processor and returns that value.  This can be used for high-res
** profiling.
*/
#if (defined(__GNUC__) || defined(_MSC_VER)) && \
      (defined(i386) || defined(__i386__) || defined(_M_IX86))

  #if defined(__GNUC__)

  __inline__ sqlite_uint64 sqlite4Hwtime(void){
     unsigned int lo, hi;
     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
     return (sqlite_uint64)hi << 32 | lo;
  }

  #elif defined(_MSC_VER)

  __declspec(naked) __inline sqlite_uint64 __cdecl sqlite4Hwtime(void){
     __asm {
        rdtsc
        ret       ; return value at EDX:EAX
     }
  }

  #endif

#elif (defined(__GNUC__) && defined(__x86_64__))

  __inline__ sqlite_uint64 sqlite4Hwtime(void){
      unsigned long val;
      __asm__ __volatile__ ("rdtsc" : "=A" (val));
      return val;
  }
 
#elif (defined(__GNUC__) && defined(__ppc__))

  __inline__ sqlite_uint64 sqlite4Hwtime(void){
      unsigned long long retval;
      unsigned long junk;
      __asm__ __volatile__ ("\n\
          1:      mftbu   %1\n\
                  mftb    %L0\n\
                  mftbu   %0\n\
                  cmpw    %0,%1\n\
                  bne     1b"
                  : "=r" (retval), "=r" (junk));
      return retval;
  }

#else

  #error Need implementation of sqlite4Hwtime() for your platform.

  /*
  ** To compile without implementing sqlite4Hwtime() for your platform,
  ** you can remove the above #error and use the following
  ** stub function.  You will lose timing support for many
  ** of the debugging and testing utilities, but it should at
  ** least compile and run.
  */
SQLITE4_PRIVATE   sqlite_uint64 sqlite4Hwtime(void){ return ((sqlite_uint64)0); }

#endif

#endif /* !defined(_HWTIME_H_) */

/************** End of hwtime.h **********************************************/
/************** Continuing where we left off in vdbe.c ***********************/

#endif

/*
** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
** sqlite4_interrupt() routine has been called.  If it has been, then
** processing of the VDBE program is interrupted.
**
** This macro added to every instruction that does a jump in order to
** implement a loop.  This test used to be on every single instruction,
** but that meant we more testing than we needed.  By only testing the
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
   if( db->u1.isInterrupted ) goto abort_due_to_interrupt;

/*
** Transfer error message text from an sqlite4_vtab.zErrMsg (text stored
** in memory obtained from sqlite4_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite4DbMalloc).
*/
/*UNUSED static*/ void importVtabErrMsg(Vdbe *p, sqlite4_vtab *pVtab){
  sqlite4 *db = p->db;
  sqlite4DbFree(db, p->zErrMsg);
  p->zErrMsg = sqlite4DbStrDup(db, pVtab->zErrMsg);
  sqlite4_free(db->pEnv, pVtab->zErrMsg);
  pVtab->zErrMsg = 0;
}

/*
** Return a pointer to a register in the root frame.
*/
static Mem *sqlite4RegisterInRootFrame(Vdbe *p, int i){
  if( p->pFrame ){
    VdbeFrame *pFrame;
    for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
    return &pFrame->aMem[i];
  }else{
    return &p->aMem[i];
  }
}

/*
** Execute as much of a VDBE program as we can then return.
**
** sqlite4VdbeMakeReady() must be called before this routine in order to
** close the program with a final OP_Halt and to set up the callbacks
** and the error message pointer.
**
** Whenever a row or result data is available, this routine will either
** invoke the result callback (if there is one) or return with
** SQLITE4_ROW.
**
** If an attempt is made to open a locked database, then this routine
** will either invoke the busy callback (if there is one) or it will
** return SQLITE4_BUSY.
**
** If an error occurs, an error message is written to memory obtained
** from sqlite4_malloc() and p->zErrMsg is made to point to that memory.
** The error code is stored in p->rc and this routine returns SQLITE4_ERROR.
**
** If the callback ever returns non-zero, then the program exits
** immediately.  There will be no error message but the p->rc field is
** set to SQLITE4_ABORT and this routine will return SQLITE4_ERROR.
**
** A memory allocation error causes p->rc to be set to SQLITE4_NOMEM and this
** routine to return SQLITE4_ERROR.
**
** Other fatal errors return SQLITE4_ERROR.
**
** After this routine has finished, sqlite4VdbeFinalize() should be
** used to clean up the mess that was left behind.
*/
SQLITE4_PRIVATE int sqlite4VdbeExec(
  Vdbe *p                    /* The VDBE */
){
  int pc=0;                  /* The program counter */
  Op *aOp = p->aOp;          /* Copy of p->aOp */
  Op *pOp;                   /* Current operation */
  int rc = SQLITE4_OK;        /* Value to return */
  sqlite4 *db = p->db;       /* The database */
  u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
  u8 encoding = ENC(db);     /* The database encoding */
#ifndef SQLITE4_OMIT_PROGRESS_CALLBACK
  int checkProgress;         /* True if progress callbacks are enabled */
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
#endif
  Mem *aMem = p->aMem;       /* Copy of p->aMem */
  Mem *pIn1 = 0;             /* 1st input operand */
  Mem *pIn2 = 0;             /* 2nd input operand */
  Mem *pIn3 = 0;             /* 3rd input operand */
  Mem *pOut = 0;             /* Output operand */
  int iCompare = 0;          /* Result of last OP_Compare operation */
  int *aPermute = 0;         /* Permutation of columns for OP_Compare */
#ifdef VDBE_PROFILE
  u64 start;                 /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
#endif
  /********************************************************************
  ** Automatically generated code
  **
  ** The following union is automatically generated by the
  ** vdbe-compress.tcl script.  The purpose of this union is to
  ** reduce the amount of stack space required by this function.
  ** See comments in the vdbe-compress.tcl script for details.
  */
  union vdbeExecUnion {
    struct OP_Yield_stack_vars {
      int pcDest;
    } aa;
    struct OP_Null_stack_vars {
      int cnt;
    } ab;
    struct OP_Variable_stack_vars {
      Mem *pVar;       /* Value being transferred */
    } ac;
    struct OP_Move_stack_vars {
      char *zMalloc;   /* Holding variable for allocated memory */
      int n;           /* Number of registers left to copy */
      int p1;          /* Register to copy from */
      int p2;          /* Register to copy to */
    } ad;
    struct OP_ResultRow_stack_vars {
      Mem *pMem;
      int i;
    } ae;
    struct OP_Concat_stack_vars {
      i64 nByte;
    } af;
    struct OP_Remainder_stack_vars {
      int flags;      /* Combined MEM_* flags from both inputs */
      i64 iA;         /* Integer value of left operand */
      i64 iB;         /* Integer value of right operand */
      sqlite4_num num1;
      sqlite4_num num2;
    } ag;
    struct OP_Function_stack_vars {
      int i;
      Mem *pArg;
      sqlite4_context ctx;
      sqlite4_value **apVal;
      int n;
    } ah;
    struct OP_ShiftRight_stack_vars {
      i64 iA;
      u64 uA;
      i64 iB;
      u8 op;
    } ai;
    struct OP_Ge_stack_vars {
      int res;            /* Result of the comparison of pIn1 against pIn3 */
      char affinity;      /* Affinity to use for comparison */
      u16 flags1;         /* Copy of initial value of pIn1->flags */
      u16 flags3;         /* Copy of initial value of pIn3->flags */
    } aj;
    struct OP_Compare_stack_vars {
      int n;
      int i;
      int p1;
      int p2;
      const KeyInfo *pKeyInfo;
      int idx;
      CollSeq *pColl;    /* Collating sequence to use on this term */
      int bRev;          /* True for DESCENDING sort order */
    } ak;
    struct OP_Or_stack_vars {
      int v1;    /* Left operand:  0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
      int v2;    /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
    } al;
    struct OP_IfNot_stack_vars {
      int c;
    } am;
    struct OP_IsNull_stack_vars {
      Mem *pEnd;
    } an;
    struct OP_Column_stack_vars {
      int p1;                   /* Index of VdbeCursor to decode */
      int mxField;              /* Maximum column number */
      VdbeCursor *pC;           /* The VDBE cursor */
      Mem *pDest;               /* Where to write the results */
      Mem *pDefault;            /* Default value from P4 */
    } ao;
    struct OP_MakeRecord_stack_vars {
      VdbeCursor *pC;        /* The cursor for OP_MakeKey */
      Mem *pData0;           /* First field to be combined into the record */
      Mem *pLast;            /* Last field of the record */
      Mem *pMem;             /* For looping over inputs */
      Mem *pOut;             /* Where to store results */
      int nIn;               /* Number of input values to be encoded */
      char *zAffinity;       /* The affinity string */
      u8 *aRec;              /* The constructed key or value */
      int nRec;              /* Size of aRec[] in bytes */
      int bRepeat;           /* True to loop to the next opcode */
      u8 aSeq[10];           /* Encoded sequence number */
      int nSeq;              /* Size of sequence number in bytes */
      u64 iSeq;              /* Sequence number, if any */
    } ap;
    struct OP_Affinity_stack_vars {
      const char *zAffinity;   /* The affinity to be applied */
      Mem *pEnd;
    } aq;
    struct OP_Count_stack_vars {
      i64 nEntry;
      VdbeCursor *pC;
    } ar;
    struct OP_Savepoint_stack_vars {
      int iSave;
      Savepoint *pSave;               /* Savepoint object operated upon */
      const char *zSave;              /* Name of savepoint (or NULL for trans.) */
      int nSave;                      /* Size of zSave in bytes */
      int iOp;                        /* SAVEPOINT_XXX operation */
      const char *zErr;               /* Static error message */
    } as;
    struct OP_Transaction_stack_vars {
      Db *pDb;
      KVStore *pKV;
      int bStmt;                      /* True to open statement transaction */
      int iLevel;                     /* Savepoint level to open */
    } at;
    struct OP_SetCookie_stack_vars {
      Db *pDb;
      i64 v;
    } au;
    struct OP_OpenWrite_stack_vars {
      int nField;
      KeyInfo *pKeyInfo;
      int p2;
      int iDb;
      KVStore *pX;
      VdbeCursor *pCur;
      Db *pDb;
    } av;
    struct OP_OpenEphemeral_stack_vars {
      VdbeCursor *pCx;
    } aw;
    struct OP_SeekPk_stack_vars {
      KVByteArray *aKey;              /* Key data from cursor pIdx */
      KVSize nKey;                    /* Size of aKey[] in bytes */
      VdbeCursor *pPk;                /* Cursor P1 */
      VdbeCursor *pIdx;               /* Cursor P3 */
      int nShort;                     /* Size of aKey[] without PK fields */
      int nVarint;                    /* Size of varint pPk->iRoot */
    } ax;
    struct OP_SeekGt_stack_vars {
      int op;                         /* Copy of pOp->opcode (the op-code) */
      VdbeCursor *pC;                 /* Cursor P1 */
      int nField;                     /* Number of values to encode into key */
      KVByteArray *aProbe;            /* Buffer containing encoded key */
      KVSize nProbe;                  /* Size of aProbe[] in bytes */
      int dir;                        /* KV search dir (+ve or -ve) */
      const KVByteArray *aKey;        /* Pointer to final cursor key */
      KVSize nKey;                    /* Size of aKey[] in bytes */
    } ay;
    struct OP_Found_stack_vars {
      int alreadyExists;
      VdbeCursor *pC;
      KVByteArray *pFree;
      KVByteArray *pProbe;
      KVSize nProbe;
      const KVByteArray *pKey;
      KVSize nKey;
    } az;
    struct OP_IsUnique_stack_vars {
      VdbeCursor *pC;
      Mem *pProbe;
      Mem *pOut;
      int iOut;
      int nShort;
      int dir;
      int bPk;
      u64 dummy;
    } ba;
    struct OP_NewRowid_stack_vars {
      i64 v;                   /* The new rowid */
      VdbeCursor *pC;          /* Cursor of table to get the new rowid */
      const KVByteArray *aKey; /* Key of an existing row */
      KVSize nKey;             /* Size of the existing row key */
      int n;                   /* Number of bytes decoded */
      i64 i3;                  /* Integer value from pIn3 */
      sqlite4_num vNum;        /* Intermediate result */
    } bb;
    struct OP_NewIdxid_stack_vars {
      u64 iMax;
      i64 i1;
      KVStore *pKV;
      KVCursor *pCsr;
    } bc;
    struct OP_Delete_stack_vars {
      VdbeCursor *pC;
    } bd;
    struct OP_GrpCompare_stack_vars {
      VdbeCursor *pC;                 /* Cursor P1 */
    } be;
    struct OP_RowData_stack_vars {
      VdbeCursor *pC;
      KVCursor *pCrsr;
      const KVByteArray *pData;
      KVSize nData;
      int nVarint;
      u64 dummy;
    } bf;
    struct OP_AnalyzeKey_stack_vars {
      VdbeCursor *pC;
      const KVByteArray *pNew;
      KVSize nNew;
      Mem *pKey;
      Mem *aIncr;
      int nEq;
      int nTotal;
      int i;
    } bg;
    struct OP_Rowid_stack_vars {
      VdbeCursor *pC;
      i64 v;
      const KVByteArray *aKey;
      KVSize nKey;
      int n;
      sqlite4_num vNum;
    } bh;
    struct OP_NullRow_stack_vars {
      VdbeCursor *pC;
    } bi;
    struct OP_Last_stack_vars {
      VdbeCursor *pC;
    } bj;
    struct OP_Rewind_stack_vars {
      VdbeCursor *pC;
      int doJump;
    } bk;
    struct OP_Next_stack_vars {
      VdbeCursor *pC;
    } bl;
    struct OP_Insert_stack_vars {
      VdbeCursor *pC;
      Mem *pKey;
      Mem *pData;
      int nKVKey;
      KVByteArray *pKVKey;
      KVByteArray aKey[24];
    } bm;
    struct OP_IdxDelete_stack_vars {
      VdbeCursor *pC;
      Mem *pKey;
    } bn;
    struct OP_IdxGT_stack_vars {
      VdbeCursor *pC;                 /* Cursor P1 */
    } bo;
    struct OP_Clear_stack_vars {
      KVCursor *pCur;
    } bp;
    struct OP_ParseSchema_stack_vars {
      int iDb;
      const char *zMaster;
      char *zSql;
      InitData initData;
    } bq;
    struct OP_RowSetTest_stack_vars {
      int iSet;
    } br;
    struct OP_RowSetRead_stack_vars {
      const u8 *aKey;
      int nKey;
    } bs;
    struct OP_Program_stack_vars {
      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 */
      Mem *pMem;              /* Used to iterate through memory cells */
      Mem *pEnd;              /* Last memory cell in new array */
      VdbeFrame *pFrame;      /* New vdbe frame to execute in */
      SubProgram *pProgram;   /* Sub-program to execute */
    } bt;
    struct OP_Param_stack_vars {
      VdbeFrame *pFrame;
      Mem *pIn;
    } bu;
    struct OP_MemMax_stack_vars {
      i64 i1;
      i64 i2;
      Mem *pIn1;
    } bv;
    struct OP_IfPos_stack_vars {
      i64 i1;
    } bw;
    struct OP_IfNeg_stack_vars {
      i64 i1;
    } bx;
    struct OP_IfZero_stack_vars {
      i64 i1;
    } by;
    struct OP_AggStep_stack_vars {
      int n;
      int i;
      Mem *pMem;
      Mem *pRec;
      sqlite4_context ctx;
      sqlite4_value **apVal;
    } bz;
    struct OP_AggFinal_stack_vars {
      Mem *pMem;
    } ca;
    struct OP_VBegin_stack_vars {
      VTable *pVTab;
    } cb;
    struct OP_VOpen_stack_vars {
      VdbeCursor *pCur;
      sqlite4_vtab_cursor *pVtabCursor;
      sqlite4_vtab *pVtab;
      sqlite4_module *pModule;
    } cc;
    struct OP_VFilter_stack_vars {
      int nArg;
      int iQuery;
      const sqlite4_module *pModule;
      Mem *pQuery;
      Mem *pArgc;
      sqlite4_vtab_cursor *pVtabCursor;
      sqlite4_vtab *pVtab;
      VdbeCursor *pCur;
      int res;
      int i;
      Mem **apArg;
    } cd;
    struct OP_VColumn_stack_vars {
      sqlite4_vtab *pVtab;
      const sqlite4_module *pModule;
      Mem *pDest;
      sqlite4_context sContext;
    } ce;
    struct OP_VNext_stack_vars {
      sqlite4_vtab *pVtab;
      const sqlite4_module *pModule;
      int res;
      VdbeCursor *pCur;
    } cf;
    struct OP_VRename_stack_vars {
      sqlite4_vtab *pVtab;
      Mem *pName;
    } cg;
    struct OP_VUpdate_stack_vars {
      sqlite4_vtab *pVtab;
      sqlite4_module *pModule;
      int nArg;
      int i;
      sqlite4_int64 rowid;
      Mem **apArg;
      Mem *pX;
    } ch;
    struct OP_Trace_stack_vars {
      char *zTrace;
      char *z;
    } ci;
    struct OP_FtsUpdate_stack_vars {
      Fts5Info *pInfo;                /* Description of fts5 index to update */
      Mem *pKey;                      /* Primary key of indexed row */
      Mem *aArg;                      /* Pointer to array of N arguments */
      int iRoot;                      /* Root page number (or 0) */
    } cj;
    struct OP_FtsCksum_stack_vars {
      Fts5Info *pInfo;                /* Description of fts5 index to update */
      Mem *pKey;                      /* Primary key of row */
      Mem *aArg;                      /* Pointer to array of N values */
      i64 cksum;                      /* Checksum for this row or index entry */
      i64 i1;
    } ck;
    struct OP_FtsOpen_stack_vars {
      Fts5Info *pInfo;                /* Description of fts5 index to update */
      VdbeCursor *pCur;
      char *zMatch;
      Mem *pMatch;
    } cl;
    struct OP_FtsNext_stack_vars {
      VdbeCursor *pCsr;
    } cm;
  } u;
  /* End automatically generated code
  ********************************************************************/

  assert( p->magic==VDBE_MAGIC_RUN );  /* sqlite4_step() verifies this */
  if( p->rc==SQLITE4_NOMEM ){
    /* This happens if a malloc() inside a call to sqlite4_column_text() or
    ** sqlite4_column_text16() failed.  */
    goto no_mem;
  }
  assert( p->rc==SQLITE4_OK || p->rc==SQLITE4_BUSY );
  p->rc = SQLITE4_OK;
  assert( p->explain==0 );
  p->pResultSet = 0;
  CHECK_FOR_INTERRUPT;
  sqlite4VdbeIOTraceSql(p);
#ifndef SQLITE4_OMIT_PROGRESS_CALLBACK
  checkProgress = db->xProgress!=0;
#endif
#ifdef SQLITE4_DEBUG
  sqlite4BeginBenignMalloc(db->pEnv);
  if( p->pc==0  && (db->flags & SQLITE4_VdbeListing)!=0 ){
    int i;
    printf("VDBE Program Listing:\n");
    sqlite4VdbePrintSql(p);
    for(i=0; i<p->nOp; i++){
      sqlite4VdbePrintOp(stdout, i, &aOp[i]);
    }
  }
  sqlite4EndBenignMalloc(db->pEnv);
#endif
  for(pc=p->pc; rc==SQLITE4_OK; pc++){
    assert( pc>=0 && pc<p->nOp );
    if( db->mallocFailed ) goto no_mem;
#ifdef VDBE_PROFILE
    origPc = pc;
    start = sqlite4Hwtime();
#endif
    pOp = &aOp[pc];

    /* Only allow tracing if SQLITE4_DEBUG is defined.
    */
#ifdef SQLITE4_DEBUG
    if( p->trace ){
      if( pc==0 ){
        printf("VDBE Execution Trace:\n");
        sqlite4VdbePrintSql(p);
      }
      sqlite4VdbePrintOp(p->trace, pc, pOp);
    }
#endif
      

    /* Check to see if we need to simulate an interrupt.  This only happens
    ** if we have a special test build.
    */
#ifdef SQLITE4_TEST
    if( sqlite4_interrupt_count>0 ){
      sqlite4_interrupt_count--;
      if( sqlite4_interrupt_count==0 ){
        sqlite4_interrupt(db);
      }
    }
#endif

#ifndef SQLITE4_OMIT_PROGRESS_CALLBACK
    /* Call the progress callback if it is configured and the required number
    ** of VDBE ops have been executed (either since this invocation of
    ** sqlite4VdbeExec() or since last time the progress callback was called).
    ** If the progress callback returns non-zero, exit the virtual machine with
    ** a return code SQLITE4_ABORT.
    */
    if( checkProgress ){
      if( db->nProgressOps==nProgressOps ){
        int prc;
        prc = db->xProgress(db->pProgressArg);
        if( prc!=0 ){
          rc = SQLITE4_INTERRUPT;
          goto vdbe_error_halt;
        }
        nProgressOps = 0;
      }
      nProgressOps++;
    }
#endif

    /* On any opcode with the "out2-prerelase" tag, free any
    ** external allocations out of mem[p2] and set mem[p2] to be
    ** an undefined integer.  Opcodes will either fill in the integer
    ** value or convert mem[p2] to a different type.
    */
    assert( pOp->opflags==sqlite4OpcodeProperty[pOp->opcode] );
    if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      pOut = &aMem[pOp->p2];
      memAboutToChange(p, pOut);
      VdbeMemRelease(pOut);
      pOut->flags = MEM_Int;
    }

    /* Sanity checking on other operands */
#ifdef SQLITE4_DEBUG
    if( (pOp->opflags & OPFLG_IN1)!=0 ){
      assert( pOp->p1>0 );
      assert( pOp->p1<=p->nMem );
      assert( memIsValid(&aMem[pOp->p1]) );
      REGISTER_TRACE(pOp->p1, &aMem[pOp->p1]);
    }
    if( (pOp->opflags & OPFLG_IN2)!=0 ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      assert( memIsValid(&aMem[pOp->p2]) );
      REGISTER_TRACE(pOp->p2, &aMem[pOp->p2]);
    }
    if( (pOp->opflags & OPFLG_IN3)!=0 ){
      assert( pOp->p3>0 );
      assert( pOp->p3<=p->nMem );
      assert( memIsValid(&aMem[pOp->p3]) );
      REGISTER_TRACE(pOp->p3, &aMem[pOp->p3]);
    }
    if( (pOp->opflags & OPFLG_OUT2)!=0 ){
      assert( pOp->p2>0 );
      assert( pOp->p2<=p->nMem );
      memAboutToChange(p, &aMem[pOp->p2]);
    }
    if( (pOp->opflags & OPFLG_OUT3)!=0 ){
      assert( pOp->p3>0 );
      assert( pOp->p3<=p->nMem );
      memAboutToChange(p, &aMem[pOp->p3]);
    }
#endif
  
    switch( pOp->opcode ){

/*****************************************************************************
** What follows is a massive switch statement where each case implements a
** separate instruction in the virtual machine.  If we follow the usual
** indentation conventions, each case should be indented by 6 spaces.  But
** that is a lot of wasted space on the left margin.  So the code within
** the switch statement will break with convention and be flush-left. Another
** big comment (similar to this one) will mark the point in the code where
** we transition back to normal indentation.
**
** The formatting of each case is important.  The makefile for SQLite
** generates two C files "opcodes.h" and "opcodes.c" by scanning this
** file looking for lines that begin with "case OP_".  The opcodes.h files
** will be filled with #defines that give unique integer values to each
** opcode and the opcodes.c file is filled with an array of strings where
** each string is the symbolic name for the corresponding opcode.  If the
** case statement is followed by a comment of the form "/# same as ... #/"
** that comment is used to determine the particular value of the opcode.
**
** Other keywords in the comment that follows each case are used to
** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[].
** Keywords include: in1, in2, in3, out2_prerelease, out2, out3.  See
** the mkopcodeh.awk script for additional information.
**
** Documentation about VDBE opcodes is generated by scanning this file
** for lines of that contain "Opcode:".  That line and all subsequent
** comment lines are used in the generation of the opcode.html documentation
** file.
**
** SUMMARY:
**
**     Formatting is important to scripts that scan this file.
**     Do not deviate from the formatting style currently in use.
**
*****************************************************************************/

/* Opcode:  Goto * P2 * * *
**
** An unconditional jump to address P2.
** The next instruction executed will be 
** the one at index P2 from the beginning of
** the program.
*/
case OP_Goto: {             /* jump */
  CHECK_FOR_INTERRUPT;
  pc = pOp->p2 - 1;
  break;
}

/* Opcode:  Gosub P1 P2 * * *
**
** Write the current address onto register P1
** and then jump to address P2.
*/
case OP_Gosub: {            /* jump */
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  pIn1 = &aMem[pOp->p1];
  assert( (pIn1->flags & MEM_Dyn)==0 );
  memAboutToChange(p, pIn1);
  pIn1->flags = MEM_Int;
  pIn1->u.num = sqlite4_num_from_int64((i64)pc);
  REGISTER_TRACE(pOp->p1, pIn1);
  pc = pOp->p2 - 1;
  break;
}

/* Opcode:  Return P1 * * * *
**
** Jump to the next instruction after the address in register P1.
*/
case OP_Return: {           /* in1 */
  pIn1 = &aMem[pOp->p1];
  assert( pIn1->flags & MEM_Int );
  pc = sqlite4_num_to_int32(pIn1->u.num, 0);
  break;
}

/* Opcode:  Yield P1 * * * *
**
** Swap the program counter with the value in register P1.
*/
case OP_Yield: {            /* in1 */
#if 0  /* local variables moved into u.aa */
  int pcDest;
#endif /* local variables moved into u.aa */
  pIn1 = &aMem[pOp->p1];
  assert( (pIn1->flags & MEM_Dyn)==0 );
  pIn1->flags = MEM_Int;
  u.aa.pcDest = sqlite4_num_to_int32(pIn1->u.num, 0);
  pIn1->u.num = sqlite4_num_from_int64(pc);
  REGISTER_TRACE(pOp->p1, pIn1);
  pc = u.aa.pcDest;
  break;
}

/* Opcode:  HaltIfNull  P1 P2 P3 P4 *
**
** Check the value in register P3.  If it is NULL then Halt using
** parameter P1, P2, and P4 as if this were a Halt instruction.  If the
** value in register P3 is not NULL, then this routine is a no-op.
*/
case OP_HaltIfNull: {      /* in3 */
  pIn3 = &aMem[pOp->p3];
  if( (pIn3->flags & MEM_Null)==0 ) break;
  /* Fall through into OP_Halt */
}

/* Opcode:  Halt P1 P2 * P4 *
**
** Exit immediately.  All open cursors, etc are closed
** automatically.
**
** P1 is the result code returned by sqlite4_exec(), sqlite4_reset(),
** or sqlite4_finalize().  For a normal halt, this should be SQLITE4_OK (0).
** For errors, it can be some other value.  If P1!=0 then P2 will determine
** whether or not to rollback the current transaction.  Do not rollback
** if P2==OE_Fail. Do the rollback if P2==OE_Rollback.  If P2==OE_Abort,
** then back out all changes that have occurred during this execution of the
** VDBE, but do not rollback the transaction. 
**
** If P4 is not null then it is an error message string.
**
** There is an implied "Halt 0 0 0" instruction inserted at the very end of
** every program.  So a jump past the last instruction of the program
** is the same as executing Halt.
*/
case OP_Halt: {
  if( pOp->p1==SQLITE4_OK && p->pFrame ){
    /* Halt the sub-program. Return control to the parent frame. */
    VdbeFrame *pFrame = p->pFrame;
    p->pFrame = pFrame->pParent;
    p->nFrame--;
    sqlite4VdbeSetChanges(db, p->nChange);
    pc = sqlite4VdbeFrameRestore(pFrame);
    if( pOp->p2==OE_Ignore ){
      /* Instruction pc is the OP_Program that invoked the sub-program 
      ** currently being halted. If the p2 instruction of this OP_Halt
      ** instruction is set to OE_Ignore, then the sub-program is throwing
      ** an IGNORE exception. In this case jump to the address specified
      ** as the p2 of the calling OP_Program.  */
      pc = p->aOp[pc].p2-1;
    }
    aOp = p->aOp;
    aMem = p->aMem;
    break;
  }

  p->rc = pOp->p1;
  p->errorAction = (u8)pOp->p2;
  p->pc = pc;
  if( pOp->p4.z ){
    assert( p->rc!=SQLITE4_OK );
    sqlite4SetString(&p->zErrMsg, db, "%s", pOp->p4.z);
    testcase( sqlite4DefaultEnv.xLog!=0 );
    sqlite4_log(db->pEnv, pOp->p1,
                "abort at %d in [%s]: %s", pc, p->zSql, pOp->p4.z);
  }else if( p->rc ){
    testcase( sqlite4DefaultEnv.xLog!=0 );
    sqlite4_log(db->pEnv, pOp->p1,
                "constraint failed at %d in [%s]", pc, p->zSql);
  }
  rc = sqlite4VdbeHalt(p);
  assert( rc==SQLITE4_BUSY || rc==SQLITE4_OK || rc==SQLITE4_ERROR );
  if( rc==SQLITE4_BUSY ){
    p->rc = rc = SQLITE4_BUSY;
  }else{
    assert( rc==SQLITE4_OK || p->rc==SQLITE4_CONSTRAINT );
    assert( rc==SQLITE4_OK || db->nDeferredCons>0 );
    rc = p->rc ? SQLITE4_ERROR : SQLITE4_DONE;
  }
  goto vdbe_return;
}

/* Opcode: Integer P1 P2 * * *
**
** The 32-bit integer value P1 is written into register P2.
*/
case OP_Integer: {         /* out2-prerelease */
  pOut->u.num = sqlite4_num_from_int64((i64)pOp->p1);
  MemSetTypeFlag(pOut, MEM_Int);
  break;
}

/* Opcode: Num P1 P2 * P4 *
**
** P4 is a pointer to an sqlite4_num value. Write that value into 
** register P2. Set the register flags to MEM_Int if P1 is non-zero,
** or MEM_Real otherwise.
*/
case OP_Num: {            /* out2-prerelease */
  pOut->flags = (pOp->p1 ? MEM_Int : MEM_Real);
  pOut->u.num = *(pOp->p4.pNum);
  break;
}

/* Opcode: String8 * P2 * P4 *
**
** P4 points to a nul terminated UTF-8 string. This opcode is transformed 
** into an OP_String before it is executed for the first time.
*/
case OP_String8: {         /* same as TK_STRING, out2-prerelease */
  assert( pOp->p4.z!=0 );
  pOp->opcode = OP_String;
  pOp->p1 = sqlite4Strlen30(pOp->p4.z);

#ifndef SQLITE4_OMIT_UTF16
  if( encoding!=SQLITE4_UTF8 ){
    rc = sqlite4VdbeMemSetStr(pOut, pOp->p4.z, -1, SQLITE4_UTF8,
                              SQLITE4_STATIC, 0);
    if( rc==SQLITE4_TOOBIG ) goto too_big;
    if( SQLITE4_OK!=sqlite4VdbeChangeEncoding(pOut, encoding) ) goto no_mem;
    assert( pOut->zMalloc==pOut->z );
    assert( pOut->flags & MEM_Dyn );
    pOut->zMalloc = 0;
    pOut->flags |= MEM_Static;
    pOut->flags &= ~MEM_Dyn;
    if( pOp->p4type==P4_DYNAMIC ){
      sqlite4DbFree(db, pOp->p4.z);
    }
    pOp->p4type = P4_DYNAMIC;
    pOp->p4.z = pOut->z;
    pOp->p1 = pOut->n;
  }
#endif
  if( pOp->p1>db->aLimit[SQLITE4_LIMIT_LENGTH] ){
    goto too_big;
  }
  /* Fall through to the next case, OP_String */
}
  
/* Opcode: String P1 P2 * P4 *
**
** The string value P4 of length P1 (bytes) is stored in register P2.
*/
case OP_String: {          /* out2-prerelease */
  assert( pOp->p4.z!=0 );
  pOut->flags = MEM_Str|MEM_Static|MEM_Term;
  pOut->z = pOp->p4.z;
  pOut->n = pOp->p1;
  pOut->enc = encoding;
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Null * P2 P3 * *
**
** Write a NULL into registers P2.  If P3 greater than P2, then also write
** NULL into register P3 and ever register in between P2 and P3.  If P3
** is less than P2 (typically P3 is zero) then only register P2 is
** set to NULL
*/
case OP_Null: {           /* out2-prerelease */
#if 0  /* local variables moved into u.ab */
  int cnt;
#endif /* local variables moved into u.ab */
  u.ab.cnt = pOp->p3-pOp->p2;
  assert( pOp->p3<=p->nMem );
  pOut->flags = MEM_Null;
  while( u.ab.cnt>0 ){
    pOut++;
    memAboutToChange(p, pOut);
    VdbeMemRelease(pOut);
    pOut->flags = MEM_Null;
    u.ab.cnt--;
  }
  break;
}


/* Opcode: Blob P1 P2 * P4
**
** P4 points to a blob of data P1 bytes long.  Store this
** blob in register P2.
*/
case OP_Blob: {                /* out2-prerelease */
  assert( pOp->p1 <= SQLITE4_MAX_LENGTH );
  sqlite4VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0, 0);
  pOut->enc = encoding;
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Variable P1 P2 * P4 *
**
** Transfer the values of bound parameter P1 into register P2
**
** If the parameter is named, then its name appears in P4 and P3==1.
** The P4 value is used by sqlite4_bind_parameter_name().
*/
case OP_Variable: {            /* out2-prerelease */
#if 0  /* local variables moved into u.ac */
  Mem *pVar;       /* Value being transferred */
#endif /* local variables moved into u.ac */

  assert( pOp->p1>0 && pOp->p1<=p->nVar );
  assert( pOp->p4.z==0 || pOp->p4.z==p->azVar[pOp->p1-1] );
  u.ac.pVar = &p->aVar[pOp->p1 - 1];
  if( sqlite4VdbeMemTooBig(u.ac.pVar) ){
    goto too_big;
  }
  sqlite4VdbeMemShallowCopy(pOut, u.ac.pVar, MEM_Static);
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Move P1 P2 P3 * *
**
** Move the values in register P1..P1+P3-1 over into
** registers P2..P2+P3-1.  Registers P1..P1+P1-1 are
** left holding a NULL.  It is an error for register ranges
** P1..P1+P3-1 and P2..P2+P3-1 to overlap.
*/
case OP_Move: {
#if 0  /* local variables moved into u.ad */
  char *zMalloc;   /* Holding variable for allocated memory */
  int n;           /* Number of registers left to copy */
  int p1;          /* Register to copy from */
  int p2;          /* Register to copy to */
#endif /* local variables moved into u.ad */

  u.ad.n = pOp->p3;
  u.ad.p1 = pOp->p1;
  u.ad.p2 = pOp->p2;
  assert( u.ad.n>0 && u.ad.p1>0 && u.ad.p2>0 );
  assert( u.ad.p1+u.ad.n<=u.ad.p2 || u.ad.p2+u.ad.n<=u.ad.p1 );

  pIn1 = &aMem[u.ad.p1];
  pOut = &aMem[u.ad.p2];
  while( u.ad.n-- ){
    assert( pOut<=&aMem[p->nMem] );
    assert( pIn1<=&aMem[p->nMem] );
    assert( memIsValid(pIn1) );
    memAboutToChange(p, pOut);
    u.ad.zMalloc = pOut->zMalloc;
    pOut->zMalloc = 0;
    sqlite4VdbeMemMove(pOut, pIn1);
#ifdef SQLITE4_DEBUG
    if( pOut->pScopyFrom>=&aMem[u.ad.p1] && pOut->pScopyFrom<&aMem[u.ad.p1+pOp->p3] ){
      pOut->pScopyFrom += u.ad.p1 - pOp->p2;
    }
#endif
    pIn1->zMalloc = u.ad.zMalloc;
    REGISTER_TRACE(u.ad.p2++, pOut);
    pIn1++;
    pOut++;
  }
  break;
}

/* Opcode: Copy P1 P2 * * *
**
** Make a copy of register P1 into register P2.
**
** This instruction makes a deep copy of the value.  A duplicate
** is made of any string or blob constant.  See also OP_SCopy.
*/
case OP_Copy: {             /* in1, out2 */
  pIn1 = &aMem[pOp->p1];
  pOut = &aMem[pOp->p2];
  assert( pOut!=pIn1 );
  sqlite4VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
  Deephemeralize(pOut);
  REGISTER_TRACE(pOp->p2, pOut);
  break;
}

/* Opcode: SCopy P1 P2 * * *
**
** Make a shallow copy of register P1 into register P2.
**
** This instruction makes a shallow copy of the value.  If the value
** is a string or blob, then the copy is only a pointer to the
** original and hence if the original changes so will the copy.
** Worse, if the original is deallocated, the copy becomes invalid.
** Thus the program must guarantee that the original will not change
** during the lifetime of the copy.  Use OP_Copy to make a complete
** copy.
*/
case OP_SCopy: {            /* in1, out2 */
  pIn1 = &aMem[pOp->p1];
  pOut = &aMem[pOp->p2];
  assert( pOut!=pIn1 );
  sqlite4VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
#ifdef SQLITE4_DEBUG
  if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
#endif
  REGISTER_TRACE(pOp->p2, pOut);
  break;
}

/* Opcode: ResultRow P1 P2 * * *
**
** The registers P1 through P1+P2-1 contain a single row of
** results. This opcode causes the sqlite4_step() call to terminate
** with an SQLITE4_ROW return code and it sets up the sqlite4_stmt
** structure to provide access to the top P1 values as the result
** row.
*/
case OP_ResultRow: {
#if 0  /* local variables moved into u.ae */
  Mem *pMem;
  int i;
#endif /* local variables moved into u.ae */
  assert( p->nResColumn==pOp->p2 );
  assert( pOp->p1>0 );
  assert( pOp->p1+pOp->p2<=p->nMem+1 );
  assert( p->nFkConstraint==0 );

  /* If the SQLITE4_CountRows flag is set in sqlite4.flags mask, then
  ** DML statements invoke this opcode to return the number of rows
  ** modified to the user. This is the only way that a VM that
  ** opens a statement transaction may invoke this opcode.
  **
  ** In case this is such a statement, close any statement transaction
  ** opened by this VM before returning control to the user. This is to
  ** ensure that statement-transactions are always nested, not overlapping.
  ** If the open statement-transaction is not closed here, then the user
  ** may step another VM that opens its own statement transaction. This
  ** may lead to overlapping statement transactions.
  **
  ** The statement transaction is never a top-level transaction.  Hence
  ** the RELEASE call below can never fail.
  */
  rc = sqlite4VdbeCloseStatement(p, SAVEPOINT_RELEASE);
  if( NEVER(rc!=SQLITE4_OK) ){
    break;
  }

  /* Invalidate all ephemeral cursor row caches */
  p->cacheCtr = (p->cacheCtr + 2)|1;

  /* Make sure the results of the current row are \000 terminated
  ** and have an assigned type.  The results are de-ephemeralized as
  ** a side effect.
  */
  u.ae.pMem = p->pResultSet = &aMem[pOp->p1];
  for(u.ae.i=0; u.ae.i<pOp->p2; u.ae.i++){
    assert( memIsValid(&u.ae.pMem[u.ae.i]) );
    Deephemeralize(&u.ae.pMem[u.ae.i]);
    assert( (u.ae.pMem[u.ae.i].flags & MEM_Ephem)==0
            || (u.ae.pMem[u.ae.i].flags & (MEM_Str|MEM_Blob))==0 );
    sqlite4VdbeMemNulTerminate(&u.ae.pMem[u.ae.i]);
    sqlite4VdbeMemStoreType(&u.ae.pMem[u.ae.i]);
    REGISTER_TRACE(pOp->p1+u.ae.i, &u.ae.pMem[u.ae.i]);
  }
  if( db->mallocFailed ) goto no_mem;

  /* Return SQLITE4_ROW
  */
  p->pc = pc + 1;
  rc = SQLITE4_ROW;
  goto vdbe_return;
}

/* Opcode: Concat P1 P2 P3 * *
**
** Add the text in register P1 onto the end of the text in
** register P2 and store the result in register P3.
** If either the P1 or P2 text are NULL then store NULL in P3.
**
**   P3 = P2 || P1
**
** It is illegal for P1 and P3 to be the same register. Sometimes,
** if P3 is the same register as P2, the implementation is able
** to avoid a memcpy().
*/
case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
#if 0  /* local variables moved into u.af */
  i64 nByte;
#endif /* local variables moved into u.af */

  pIn1 = &aMem[pOp->p1];
  pIn2 = &aMem[pOp->p2];
  pOut = &aMem[pOp->p3];
  assert( pIn1!=pOut );
  if( (pIn1->flags | pIn2->flags) & MEM_Null ){
    sqlite4VdbeMemSetNull(pOut);
    break;
  }
  Stringify(pIn1, encoding);
  Stringify(pIn2, encoding);
  u.af.nByte = pIn1->n + pIn2->n;
  if( u.af.nByte>db->aLimit[SQLITE4_LIMIT_LENGTH] ){
    goto too_big;
  }
  MemSetTypeFlag(pOut, MEM_Str);
  if( sqlite4VdbeMemGrow(pOut, (int)u.af.nByte+2, pOut==pIn2) ){
    goto no_mem;
  }
  if( pOut!=pIn2 ){
    memcpy(pOut->z, pIn2->z, pIn2->n);
  }
  memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
  pOut->z[u.af.nByte] = 0;
  pOut->z[u.af.nByte+1] = 0;
  pOut->flags |= MEM_Term;
  pOut->n = (int)u.af.nByte;
  pOut->enc = encoding;
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: Add P1 P2 P3 * *
**
** Add the value in register P1 to the value in register P2
** and store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: Multiply P1 P2 P3 * *
**
**
** Multiply the value in register P1 by the value in register P2
** and store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: Subtract P1 P2 P3 * *
**
** Subtract the value in register P1 from the value in register P2
** and store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: Divide P1 P2 P3 * *
**
** Divide the value in register P1 by the value in register P2
** and store the result in register P3 (P3=P2/P1). If the value in 
** register P1 is zero, then the result is NULL. If either input is 
** NULL, the result is NULL.
*/
/* Opcode: Remainder P1 P2 P3 * *
**
** Compute the remainder after integer division of the value in
** register P1 by the value in register P2 and store the result in P3. 
** If the value in register P2 is zero the result is NULL.
** If either operand is NULL, the result is NULL.
*/
case OP_Add:                   /* same as TK_PLUS, in1, in2, out3 */
case OP_Subtract:              /* same as TK_MINUS, in1, in2, out3 */
case OP_Multiply:              /* same as TK_STAR, in1, in2, out3 */
case OP_Divide:                /* same as TK_SLASH, in1, in2, out3 */
case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
#if 0  /* local variables moved into u.ag */
  int flags;      /* Combined MEM_* flags from both inputs */
  i64 iA;         /* Integer value of left operand */
  i64 iB;         /* Integer value of right operand */
  sqlite4_num num1;
  sqlite4_num num2;
#endif /* local variables moved into u.ag */

  pIn1 = &aMem[pOp->p1];
  applyNumericAffinity(pIn1);
  pIn2 = &aMem[pOp->p2];
  applyNumericAffinity(pIn2);
  pOut = &aMem[pOp->p3];
  u.ag.flags = pIn1->flags | pIn2->flags;
  if( (u.ag.flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;

  if( (pIn1->flags&MEM_Int) && (pIn2->flags&MEM_Int) ){
    u.ag.iA = sqlite4_num_to_int64(pIn1->u.num, 0);
    u.ag.iB = sqlite4_num_to_int64(pIn2->u.num, 0);

    switch( pOp->opcode ){
      case OP_Add:       if( sqlite4AddInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
      case OP_Subtract:  if( sqlite4SubInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
      case OP_Multiply:  if( sqlite4MulInt64(&u.ag.iB,u.ag.iA) ) goto fp_math;  break;
      case OP_Divide: {
        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
        if( u.ag.iA==-1 && u.ag.iB==SMALLEST_INT64 ) goto fp_math;
        u.ag.iB /= u.ag.iA;
        break;
      }
      default: {
        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
        if( u.ag.iA==-1 ) u.ag.iA = 1;
        u.ag.iB %= u.ag.iA;
        break;
      }
    }
    pOut->u.num = sqlite4_num_from_int64(u.ag.iB);
    MemSetTypeFlag(pOut, MEM_Int);

    break;
  }else{

 fp_math:
    u.ag.num1 = sqlite4VdbeNumValue(pIn1);
    u.ag.num2 = sqlite4VdbeNumValue(pIn2);
    switch( pOp->opcode ){
      case OP_Add:
        pOut->u.num = sqlite4_num_add(u.ag.num1, u.ag.num2); break;
      case OP_Subtract:
        pOut->u.num = sqlite4_num_sub(u.ag.num2, u.ag.num1); break;
      case OP_Multiply:
        pOut->u.num = sqlite4_num_mul(u.ag.num1, u.ag.num2); break;
      case OP_Divide:
        pOut->u.num = sqlite4_num_div(u.ag.num2, u.ag.num1); break;
      default: {
        u.ag.iA = sqlite4_num_to_int64(u.ag.num1, 0);
        u.ag.iB = sqlite4_num_to_int64(u.ag.num2, 0);
        if( u.ag.iA==0 ) goto arithmetic_result_is_null;
        if( u.ag.iA==-1 ) u.ag.iA = 1;
        pOut->u.num = sqlite4_num_from_int64(u.ag.iB % u.ag.iA);
        break;
      }
    }

    if( sqlite4_num_isnan(pOut->u.num) ){
      goto arithmetic_result_is_null;
    }else{
      MemSetTypeFlag(pOut, MEM_Real);
      if( (u.ag.flags & MEM_Real)==0 ){
        sqlite4VdbeIntegerAffinity(pOut);
      }
    }
  }

  break;

arithmetic_result_is_null:
  sqlite4VdbeMemSetNull(pOut);
  break;
}

/* Opcode: CollSeq * * P4
**
** P4 is a pointer to a CollSeq struct. If the next call to a user function
** or aggregate calls sqlite4GetFuncCollSeq(), this collation sequence will
** be returned. This is used by the built-in min(), max() and nullif()
** functions.
**
** The interface used by the implementation of the aforementioned functions
** to retrieve the collation sequence set by this opcode is not available
** publicly, only to user functions defined in func.c.
*/
case OP_CollSeq: {
  assert( pOp->p4type==P4_COLLSEQ );
  break;
}

/* Opcode: Mifunction P1
*/
case OP_KVMethod: {
  assert( pOp[1].opcode==OP_Function );
  break;
};

/* Opcode: Mifunction P1
*/
case OP_Mifunction: {
  pc++;
  pOp++;
  /* fall through to OP_Function */
};

/* Opcode: Function P1 P2 P3 P4 P5
**
** Invoke a user function (P4 is a pointer to a Function structure that
** defines the function) with P5 arguments taken from register P2 and
** successors.  The result of the function is stored in register P3.
** Register P3 must not be one of the function inputs.
**
** P1 is a 32-bit bitmask indicating whether or not each argument to the 
** function was determined to be constant at compile time. If the first
** argument was constant then bit 0 of P1 is set. This is used to determine
** whether meta data associated with a user function argument using the
** sqlite4_auxdata_store() API may be safely retained until the next
** invocation of this opcode.
**
** See also: AggStep and AggFinal
*/
case OP_Function: {
#if 0  /* local variables moved into u.ah */
  int i;
  Mem *pArg;
  sqlite4_context ctx;
  sqlite4_value **apVal;
  int n;
#endif /* local variables moved into u.ah */

  u.ah.n = pOp->p5;
  u.ah.apVal = p->apArg;
  assert( u.ah.apVal || u.ah.n==0 );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  pOut = &aMem[pOp->p3];
  memAboutToChange(p, pOut);

  assert( u.ah.n==0 || (pOp->p2>0 && pOp->p2+u.ah.n<=p->nMem+1) );
  assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+u.ah.n );
  u.ah.pArg = &aMem[pOp->p2];
  for(u.ah.i=0; u.ah.i<u.ah.n; u.ah.i++, u.ah.pArg++){
    assert( memIsValid(u.ah.pArg) );
    u.ah.apVal[u.ah.i] = u.ah.pArg;
    Deephemeralize(u.ah.pArg);
    sqlite4VdbeMemStoreType(u.ah.pArg);
    REGISTER_TRACE(pOp->p2+u.ah.i, u.ah.pArg);
  }

  assert( pOp->p4type==P4_FUNCDEF || pOp->p4type==P4_VDBEFUNC );
  if( pOp->p4type==P4_FUNCDEF ){
    u.ah.ctx.pFunc = pOp->p4.pFunc;
    u.ah.ctx.pVdbeFunc = 0;
  }else{
    u.ah.ctx.pVdbeFunc = (VdbeFunc*)pOp->p4.pVdbeFunc;
    u.ah.ctx.pFunc = u.ah.ctx.pVdbeFunc->pFunc;
  }

  u.ah.ctx.s.flags = MEM_Null;
  u.ah.ctx.s.db = db;
  u.ah.ctx.s.xDel = 0;
  u.ah.ctx.s.zMalloc = 0;
  u.ah.ctx.pFts = 0;
  if( pOp[-1].opcode==OP_Mifunction ){
    u.ah.ctx.pFts = p->apCsr[pOp[-1].p1]->pFts;
    u.ah.apVal++;
    u.ah.n--;
  }

  /* The output cell may already have a buffer allocated. Move
  ** the pointer to u.ah.ctx.s so in case the user-function can use
  ** the already allocated buffer instead of allocating a new one.
  */
  sqlite4VdbeMemMove(&u.ah.ctx.s, pOut);
  MemSetTypeFlag(&u.ah.ctx.s, MEM_Null);

  u.ah.ctx.isError = 0;
  if( u.ah.ctx.pFunc->flags & SQLITE4_FUNC_NEEDCOLL ){
    assert( pOp>aOp );
    assert( pOp[-1].p4type==P4_COLLSEQ );
    assert( pOp[-1].opcode==OP_CollSeq );
    u.ah.ctx.pColl = pOp[-1].p4.pColl;
  }
  (*u.ah.ctx.pFunc->xFunc)(&u.ah.ctx, u.ah.n, u.ah.apVal); /* IMP: R-24505-23230 */

  /* If any auxiliary data functions have been called by this user function,
  ** immediately call the destructor for any non-static values.
  */
  if( u.ah.ctx.pVdbeFunc ){
    sqlite4VdbeDeleteAuxData(u.ah.ctx.pVdbeFunc, pOp->p1);
    pOp->p4.pVdbeFunc = u.ah.ctx.pVdbeFunc;
    pOp->p4type = P4_VDBEFUNC;
  }

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

  /* If the function returned an error, throw an exception */
  if( u.ah.ctx.isError ){
    sqlite4SetString(&p->zErrMsg, db, "%s",
        (const char *)sqlite4ValueText(&u.ah.ctx.s, SQLITE4_UTF8)
    );
    rc = u.ah.ctx.isError;
  }

  /* Copy the result of the function into register P3 */
  sqlite4VdbeChangeEncoding(&u.ah.ctx.s, encoding);
  sqlite4VdbeMemMove(pOut, &u.ah.ctx.s);
  if( sqlite4VdbeMemTooBig(pOut) ){
    goto too_big;
  }

#if 0
  /* The app-defined function has done something that as caused this
  ** statement to expire.  (Perhaps the function called sqlite4_exec()
  ** with a CREATE TABLE statement.)
  */
  if( p->expired ) rc = SQLITE4_ABORT;
#endif

  REGISTER_TRACE(pOp->p3, pOut);
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: BitAnd P1 P2 P3 * *
**
** Take the bit-wise AND of the values in register P1 and P2 and
** store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: BitOr P1 P2 P3 * *
**
** Take the bit-wise OR of the values in register P1 and P2 and
** store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: ShiftLeft P1 P2 P3 * *
**
** Shift the integer value in register P2 to the left by the
** number of bits specified by the integer in register P1.
** Store the result in register P3.
** If either input is NULL, the result is NULL.
*/
/* Opcode: ShiftRight P1 P2 P3 * *
**
** Shift the integer value in register P2 to the right by the
** number of bits specified by the integer in register P1.
** Store the result in register P3.
** If either input is NULL, the result is NULL.
*/
case OP_BitAnd:                 /* same as TK_BITAND, in1, in2, out3 */
case OP_BitOr:                  /* same as TK_BITOR, in1, in2, out3 */
case OP_ShiftLeft:              /* same as TK_LSHIFT, in1, in2, out3 */
case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
#if 0  /* local variables moved into u.ai */
  i64 iA;
  u64 uA;
  i64 iB;
  u8 op;
#endif /* local variables moved into u.ai */

  pIn1 = &aMem[pOp->p1];
  pIn2 = &aMem[pOp->p2];
  pOut = &aMem[pOp->p3];
  if( (pIn1->flags | pIn2->flags) & MEM_Null ){
    sqlite4VdbeMemSetNull(pOut);
    break;
  }
  u.ai.iA = sqlite4VdbeIntValue(pIn2);
  u.ai.iB = sqlite4VdbeIntValue(pIn1);
  u.ai.op = pOp->opcode;
  if( u.ai.op==OP_BitAnd ){
    u.ai.iA &= u.ai.iB;
  }else if( u.ai.op==OP_BitOr ){
    u.ai.iA |= u.ai.iB;
  }else if( u.ai.iB!=0 ){
    assert( u.ai.op==OP_ShiftRight || u.ai.op==OP_ShiftLeft );

    /* If shifting by a negative amount, shift in the other direction */
    if( u.ai.iB<0 ){
      assert( OP_ShiftRight==OP_ShiftLeft+1 );
      u.ai.op = 2*OP_ShiftLeft + 1 - u.ai.op;
      u.ai.iB = u.ai.iB>(-64) ? -u.ai.iB : 64;
    }

    if( u.ai.iB>=64 ){
      u.ai.iA = (u.ai.iA>=0 || u.ai.op==OP_ShiftLeft) ? 0 : -1;
    }else{
      memcpy(&u.ai.uA, &u.ai.iA, sizeof(u.ai.uA));
      if( u.ai.op==OP_ShiftLeft ){
        u.ai.uA <<= u.ai.iB;
      }else{
        u.ai.uA >>= u.ai.iB;
        /* Sign-extend on a right shift of a negative number */
        if( u.ai.iA<0 ) u.ai.uA |= ((((u64)0xffffffff)<<32)|0xffffffff) << (64-u.ai.iB);
      }
      memcpy(&u.ai.iA, &u.ai.uA, sizeof(u.ai.iA));
    }
  }

  pOut->u.num = sqlite4_num_from_int64(u.ai.iA);
  MemSetTypeFlag(pOut, MEM_Int);
  break;
}

/* Opcode: AddImm  P1 P2 * * *
** 
** Add the constant P2 to the value in register P1.
** The result is always an integer.
**
** To force any register to be an integer, just add 0.
*/
case OP_AddImm: {            /* in1 */
  pIn1 = &aMem[pOp->p1];
  memAboutToChange(p, pIn1);
  sqlite4VdbeMemIntegerify(pIn1);
  pIn1->u.num = sqlite4_num_add(pIn1->u.num, sqlite4_num_from_int64(pOp->p2));
  break;
}

/* Opcode: MustBeInt P1 P2 * * *
** 
** Force the value in register P1 to be an integer.  If the value
** in P1 is not an integer and cannot be converted into an integer
** without data loss, then jump immediately to P2, or if P2==0
** raise an SQLITE4_MISMATCH exception.
*/
case OP_MustBeInt: {            /* jump, in1 */
  pIn1 = &aMem[pOp->p1];
  applyAffinity(pIn1, SQLITE4_AFF_NUMERIC, encoding);
  if( (pIn1->flags & MEM_Int)==0 ){
    if( pOp->p2==0 ){
      rc = SQLITE4_MISMATCH;
      goto abort_due_to_error;
    }else{
      pc = pOp->p2 - 1;
    }
  }else{
    MemSetTypeFlag(pIn1, MEM_Int);
  }
  break;
}

#ifndef SQLITE4_OMIT_FLOATING_POINT
/* Opcode: RealAffinity P1 * * * *
**
** If register P1 holds an integer convert it to a real value.
**
** This opcode is used when extracting information from a column that
** has REAL affinity.  Such column values may still be stored as
** integers, for space efficiency, but after extraction we want them
** to have only a real value.
*/
case OP_RealAffinity: {                  /* in1 */
  pIn1 = &aMem[pOp->p1];
  if( pIn1->flags & MEM_Int ){
    MemSetTypeFlag(pIn1, MEM_Real);
  }
  break;
}
#endif

#ifndef SQLITE4_OMIT_CAST
/* Opcode: ToText P1 * * * *
**
** Force the value in register P1 to be text.
** If the value is numeric, convert it to a string using the
** equivalent of printf().  Blob values are unchanged and
** are afterwards simply interpreted as text.
**
** A NULL value is not changed by this routine.  It remains NULL.
*/
case OP_ToText: {                  /* same as TK_TO_TEXT, in1 */
  pIn1 = &aMem[pOp->p1];
  memAboutToChange(p, pIn1);
  if( pIn1->flags & MEM_Null ) break;
  assert( MEM_Str==(MEM_Blob>>3) );
  pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
  applyAffinity(pIn1, SQLITE4_AFF_TEXT, encoding);
  assert( pIn1->flags & MEM_Str || db->mallocFailed );
  pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
  UPDATE_MAX_BLOBSIZE(pIn1);
  break;
}

/* Opcode: ToBlob P1 * * * *
**
** Force the value in register P1 to be a BLOB.
** If the value is numeric, convert it to a string first.
** Strings are simply reinterpreted as blobs with no change
** to the underlying data.
**
** A NULL value is not changed by this routine.  It remains NULL.
*/
case OP_ToBlob: {                  /* same as TK_TO_BLOB, in1 */
  pIn1 = &aMem[pOp->p1];
  if( pIn1->flags & MEM_Null ) break;
  if( (pIn1->flags & MEM_Blob)==0 ){
    applyAffinity(pIn1, SQLITE4_AFF_TEXT, encoding);
    assert( pIn1->flags & MEM_Str || db->mallocFailed );
    MemSetTypeFlag(pIn1, MEM_Blob);
  }else{
    pIn1->flags &= ~(MEM_TypeMask&~MEM_Blob);
  }
  UPDATE_MAX_BLOBSIZE(pIn1);
  break;
}

/* Opcode: ToNumeric P1 * * * *
**
** Force the value in register P1 to be numeric (either an
** integer or a floating-point number.)
** If the value is text or blob, try to convert it to an using the
** equivalent of atoi() or atof() and store 0 if no such conversion 
** is possible.
**
** A NULL value is not changed by this routine.  It remains NULL.
*/
case OP_ToNumeric: {                  /* same as TK_TO_NUMERIC, in1 */
  pIn1 = &aMem[pOp->p1];
  sqlite4VdbeMemNumerify(pIn1);
  break;
}
#endif /* SQLITE4_OMIT_CAST */

/* Opcode: ToInt P1 * * * *
**
** Force the value in register P1 to be an integer.  If
** The value is currently a real number, drop its fractional part.
** If the value is text or blob, try to convert it to an integer using the
** equivalent of atoi() and store 0 if no such conversion is possible.
**
** A NULL value is not changed by this routine.  It remains NULL.
*/
case OP_ToInt: {                  /* same as TK_TO_INT, in1 */
  pIn1 = &aMem[pOp->p1];
  if( (pIn1->flags & MEM_Null)==0 ){
    sqlite4VdbeMemIntegerify(pIn1);
  }
  break;
}

#if !defined(SQLITE4_OMIT_CAST) && !defined(SQLITE4_OMIT_FLOATING_POINT)
/* Opcode: ToReal P1 * * * *
**
** Force the value in register P1 to be a floating point number.
** If The value is currently an integer, convert it.
** If the value is text or blob, try to convert it to an integer using the
** equivalent of atoi() and store 0.0 if no such conversion is possible.
**
** A NULL value is not changed by this routine.  It remains NULL.
*/
case OP_ToReal: {                  /* same as TK_TO_REAL, in1 */
  pIn1 = &aMem[pOp->p1];
  memAboutToChange(p, pIn1);
  sqlite4VdbeMemNumerify(pIn1);
  pIn1->flags |= MEM_Real;
  pIn1->flags &= ~MEM_Int;
  break;
}
#endif /* !defined(SQLITE4_OMIT_CAST) && !defined(SQLITE4_OMIT_FLOATING_POINT) */

/* Opcode: Lt P1 P2 P3 P4 P5
**
** Compare the values in register P1 and P3.  If reg(P3)<reg(P1) then
** jump to address P2.  
**
** If the SQLITE4_JUMPIFNULL bit of P5 is set and either reg(P1) or
** reg(P3) is NULL then take the jump.  If the SQLITE4_JUMPIFNULL 
** bit is clear then fall through if either operand is NULL.
**
** The SQLITE4_AFF_MASK portion of P5 must be an affinity character -
** SQLITE4_AFF_TEXT, SQLITE4_AFF_INTEGER, and so forth. An attempt is made 
** to coerce both inputs according to this affinity before the
** comparison is made. If the SQLITE4_AFF_MASK is 0x00, then numeric
** affinity is used. Note that the affinity conversions are stored
** back into the input registers P1 and P3.  So this opcode can cause
** persistent changes to registers P1 and P3.
**
** Once any conversions have taken place, and neither value is NULL, 
** the values are compared. If both values are blobs then memcmp() is
** used to determine the results of the comparison.  If both values
** are text, then the appropriate collating function specified in
** P4 is  used to do the comparison.  If P4 is not specified then
** memcmp() is used to compare text string.  If both values are
** numeric, then a numeric comparison is used. If the two values
** are of different types, then numbers are considered less than
** strings and strings are considered less than blobs.
**
** If the SQLITE4_STOREP2 bit of P5 is set, then do not jump.  Instead,
** store a boolean result (either 0, or 1, or NULL) in register P2.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
**
** This works just like the Lt opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal.  See the Lt opcode for
** additional information.
**
** If SQLITE4_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is false.  If either operand is NULL then the result is true.
** If neither operand is NULL the result is the same as it would be if
** the SQLITE4_NULLEQ flag were omitted from P5.
*/
/* Opcode: Eq P1 P2 P3 P4 P5
**
** This works just like the Lt opcode except that the jump is taken if
** the operands in registers P1 and P3 are equal.
** See the Lt opcode for additional information.
**
** If SQLITE4_NULLEQ is set in P5 then the result of comparison is always either
** true or false and is never NULL.  If both operands are NULL then the result
** of comparison is true.  If either operand is NULL then the result is false.
** If neither operand is NULL the result is the same as it would be if
** the SQLITE4_NULLEQ flag were omitted from P5.
*/
/* Opcode: Le P1 P2 P3 P4 P5
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is less than or equal to the content of
** register P1.  See the Lt opcode for additional information.
*/
/* Opcode: Gt P1 P2 P3 P4 P5
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is greater than the content of
** register P1.  See the Lt opcode for additional information.
*/
/* Opcode: Ge P1 P2 P3 P4 P5
**
** This works just like the Lt opcode except that the jump is taken if
** the content of register P3 is greater than or equal to the content of
** register P1.  See the Lt opcode for additional information.
*/
case OP_Eq:               /* same as TK_EQ, jump, in1, in3 */
case OP_Ne:               /* same as TK_NE, jump, in1, in3 */
case OP_Lt:               /* same as TK_LT, jump, in1, in3 */
case OP_Le:               /* same as TK_LE, jump, in1, in3 */
case OP_Gt:               /* same as TK_GT, jump, in1, in3 */
case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
#if 0  /* local variables moved into u.aj */
  int res;            /* Result of the comparison of pIn1 against pIn3 */
  char affinity;      /* Affinity to use for comparison */
  u16 flags1;         /* Copy of initial value of pIn1->flags */
  u16 flags3;         /* Copy of initial value of pIn3->flags */
#endif /* local variables moved into u.aj */

  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  u.aj.flags1 = pIn1->flags;
  u.aj.flags3 = pIn3->flags;
  if( (u.aj.flags1 | u.aj.flags3)&MEM_Null ){
    /* One or both operands are NULL */
    if( pOp->p5 & SQLITE4_NULLEQ ){
      /* If SQLITE4_NULLEQ is set (which will only happen if the operator is
      ** OP_Eq or OP_Ne) then take the jump or not depending on whether
      ** or not both operands are null.
      */
      assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
      u.aj.res = (u.aj.flags1 & u.aj.flags3 & MEM_Null)==0;
    }else{
      /* SQLITE4_NULLEQ is clear and at least one operand is NULL,
      ** then the result is always NULL.
      ** The jump is taken if the SQLITE4_JUMPIFNULL bit is set.
      */
      if( pOp->p5 & SQLITE4_STOREP2 ){
        pOut = &aMem[pOp->p2];
        MemSetTypeFlag(pOut, MEM_Null);
        REGISTER_TRACE(pOp->p2, pOut);
      }else if( pOp->p5 & SQLITE4_JUMPIFNULL ){
        pc = pOp->p2-1;
      }
      break;
    }
  }else{
    /* Neither operand is NULL.  Do a comparison. */
    u.aj.affinity = pOp->p5 & SQLITE4_AFF_MASK;
    if( u.aj.affinity ){
      applyAffinity(pIn1, u.aj.affinity, encoding);
      applyAffinity(pIn3, u.aj.affinity, encoding);
      if( db->mallocFailed ) goto no_mem;
    }

    assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
    rc = sqlite4MemCompare(pIn3, pIn1, pOp->p4.pColl, &u.aj.res);
  }
  switch( pOp->opcode ){
    case OP_Eq:    u.aj.res = u.aj.res==0;     break;
    case OP_Ne:    u.aj.res = u.aj.res!=0;     break;
    case OP_Lt:    u.aj.res = u.aj.res<0;      break;
    case OP_Le:    u.aj.res = u.aj.res<=0;     break;
    case OP_Gt:    u.aj.res = u.aj.res>0;      break;
    default:       u.aj.res = u.aj.res>=0;     break;
  }

  if( pOp->p5 & SQLITE4_STOREP2 ){
    pOut = &aMem[pOp->p2];
    memAboutToChange(p, pOut);
    MemSetTypeFlag(pOut, MEM_Int);
    pOut->u.num = sqlite4_num_from_int64(u.aj.res);
    REGISTER_TRACE(pOp->p2, pOut);
  }else if( u.aj.res ){
    pc = pOp->p2-1;
  }

  /* Undo any changes made by applyAffinity() to the input registers. */
  pIn1->flags = (pIn1->flags&~MEM_TypeMask) | (u.aj.flags1&MEM_TypeMask);
  pIn3->flags = (pIn3->flags&~MEM_TypeMask) | (u.aj.flags3&MEM_TypeMask);
  break;
}

/* Opcode: Permutation P1 * * P4 *
**
** Set the permutation used by the OP_Compare operator to be the array
** of integers in P4.  P4 will contain exactly P1 elements.  The P1
** parameter is used only for printing the P4 array when debugging.
**
** The permutation is only valid until the next OP_Permutation, OP_Compare,
** OP_Halt, or OP_ResultRow.  Typically the OP_Permutation should occur
** immediately prior to the OP_Compare.
*/
case OP_Permutation: {
  assert( pOp->p4type==P4_INTARRAY );
  assert( pOp->p4.ai );
  aPermute = pOp->p4.ai;
  break;
}

/* Opcode: Compare P1 P2 P3 P4 *
**
** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this
** vector "A") and in reg(P2)..reg(P2+P3-1) ("B").  Save the result of
** the comparison for use by the next OP_Jump instruct.
**
** P4 is a KeyInfo structure that defines collating sequences and sort
** orders for the comparison.  The permutation applies to registers
** only.  The KeyInfo elements are used sequentially.
**
** The comparison is a sort comparison, so NULLs compare equal,
** NULLs are less than numbers, numbers are less than strings,
** and strings are less than blobs.
*/
case OP_Compare: {
#if 0  /* local variables moved into u.ak */
  int n;
  int i;
  int p1;
  int p2;
  const KeyInfo *pKeyInfo;
  int idx;
  CollSeq *pColl;    /* Collating sequence to use on this term */
  int bRev;          /* True for DESCENDING sort order */
#endif /* local variables moved into u.ak */

  u.ak.n = pOp->p3;
  u.ak.pKeyInfo = pOp->p4.pKeyInfo;
  assert( u.ak.n>0 );
  assert( u.ak.pKeyInfo!=0 );
  u.ak.p1 = pOp->p1;
  u.ak.p2 = pOp->p2;
#if SQLITE4_DEBUG
  if( aPermute ){
    int k, mx = 0;
    for(k=0; k<u.ak.n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
    assert( u.ak.p1>0 && u.ak.p1+mx<=p->nMem+1 );
    assert( u.ak.p2>0 && u.ak.p2+mx<=p->nMem+1 );
  }else{
    assert( u.ak.p1>0 && u.ak.p1+u.ak.n<=p->nMem+1 );
    assert( u.ak.p2>0 && u.ak.p2+u.ak.n<=p->nMem+1 );
  }
#endif /* SQLITE4_DEBUG */
  for(u.ak.i=0; u.ak.i<u.ak.n; u.ak.i++){
    u.ak.idx = aPermute ? aPermute[u.ak.i] : u.ak.i;
    assert( memIsValid(&aMem[u.ak.p1+u.ak.idx]) );
    assert( memIsValid(&aMem[u.ak.p2+u.ak.idx]) );
    REGISTER_TRACE(u.ak.p1+u.ak.idx, &aMem[u.ak.p1+u.ak.idx]);
    REGISTER_TRACE(u.ak.p2+u.ak.idx, &aMem[u.ak.p2+u.ak.idx]);
    assert( u.ak.i<u.ak.pKeyInfo->nField );
    u.ak.pColl = u.ak.pKeyInfo->aColl[u.ak.i];
    u.ak.bRev = u.ak.pKeyInfo->aSortOrder[u.ak.i];
    rc = sqlite4MemCompare(&aMem[u.ak.p1+u.ak.idx], &aMem[u.ak.p2+u.ak.idx], u.ak.pColl, &iCompare);
    if( iCompare ){
      if( u.ak.bRev ) iCompare = -iCompare;
      break;
    }
  }
  aPermute = 0;
  break;
}

/* Opcode: Jump P1 P2 P3 * *
**
** Jump to the instruction at address P1, P2, or P3 depending on whether
** in the most recent OP_Compare instruction the P1 vector was less than
** equal to, or greater than the P2 vector, respectively.
*/
case OP_Jump: {             /* jump */
  if( iCompare<0 ){
    pc = pOp->p1 - 1;
  }else if( iCompare==0 ){
    pc = pOp->p2 - 1;
  }else{
    pc = pOp->p3 - 1;
  }
  break;
}

/* Opcode: And P1 P2 P3 * *
**
** Take the logical AND of the values in registers P1 and P2 and
** write the result into register P3.
**
** If either P1 or P2 is 0 (false) then the result is 0 even if
** the other input is NULL.  A NULL and true or two NULLs give
** a NULL output.
*/
/* Opcode: Or P1 P2 P3 * *
**
** Take the logical OR of the values in register P1 and P2 and
** store the answer in register P3.
**
** If either P1 or P2 is nonzero (true) then the result is 1 (true)
** even if the other input is NULL.  A NULL and false or two NULLs
** give a NULL output.
*/
case OP_And:              /* same as TK_AND, in1, in2, out3 */
case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
#if 0  /* local variables moved into u.al */
  int v1;    /* Left operand:  0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
  int v2;    /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
#endif /* local variables moved into u.al */

  pIn1 = &aMem[pOp->p1];
  if( pIn1->flags & MEM_Null ){
    u.al.v1 = 2;
  }else{
    u.al.v1 = sqlite4VdbeIntValue(pIn1)!=0;
  }
  pIn2 = &aMem[pOp->p2];
  if( pIn2->flags & MEM_Null ){
    u.al.v2 = 2;
  }else{
    u.al.v2 = sqlite4VdbeIntValue(pIn2)!=0;
  }
  if( pOp->opcode==OP_And ){
    static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
    u.al.v1 = and_logic[u.al.v1*3+u.al.v2];
  }else{
    static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 };
    u.al.v1 = or_logic[u.al.v1*3+u.al.v2];
  }
  pOut = &aMem[pOp->p3];
  if( u.al.v1==2 ){
    MemSetTypeFlag(pOut, MEM_Null);
  }else{
    pOut->u.num = sqlite4_num_from_int64(u.al.v1);
    MemSetTypeFlag(pOut, MEM_Int);
  }
  break;
}

/* Opcode: Not P1 P2 * * *
**
** Interpret the value in register P1 as a boolean value.  Store the
** boolean complement in register P2.  If the value in register P1 is 
** NULL, then a NULL is stored in P2.
*/
case OP_Not: {                /* same as TK_NOT, in1, out2 */
  pIn1 = &aMem[pOp->p1];
  pOut = &aMem[pOp->p2];
  if( pIn1->flags & MEM_Null ){
    sqlite4VdbeMemSetNull(pOut);
  }else{
    sqlite4VdbeMemSetInt64(pOut, !sqlite4VdbeIntValue(pIn1));
  }
  break;
}

/* Opcode: BitNot P1 P2 * * *
**
** Interpret the content of register P1 as an integer.  Store the
** ones-complement of the P1 value into register P2.  If P1 holds
** a NULL then store a NULL in P2.
*/
case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
  pIn1 = &aMem[pOp->p1];
  pOut = &aMem[pOp->p2];
  if( pIn1->flags & MEM_Null ){
    sqlite4VdbeMemSetNull(pOut);
  }else{
    sqlite4VdbeMemSetInt64(pOut, ~sqlite4VdbeIntValue(pIn1));
  }
  break;
}

/* Opcode: Once P1 P2 * * *
**
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
** set the flag and fall through to the next instruction.
**
** See also: JumpOnce
*/
case OP_Once: {             /* jump */
  assert( pOp->p1<p->nOnceFlag );
  if( p->aOnceFlag[pOp->p1] ){
    pc = pOp->p2-1;
  }else{
    p->aOnceFlag[pOp->p1] = 1;
  }
  break;
}

/* Opcode: If P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is true.  The value
** is considered true if it is numeric and non-zero.  If the value
** in P1 is NULL then take the jump if P3 is non-zero.
*/
/* Opcode: IfNot P1 P2 P3 * *
**
** Jump to P2 if the value in register P1 is False.  The value
** is considered false if it has a numeric value of zero.  If the value
** in P1 is NULL then take the jump if P3 is zero.
*/
case OP_If:                 /* jump, in1 */
case OP_IfNot: {            /* jump, in1 */
#if 0  /* local variables moved into u.am */
  int c;
#endif /* local variables moved into u.am */
  pIn1 = &aMem[pOp->p1];
  if( pIn1->flags & MEM_Null ){
    u.am.c = pOp->p3;
  }else{
    u.am.c = sqlite4VdbeNumValue(pIn1).m!=0;
    if( pOp->opcode==OP_IfNot ) u.am.c = !u.am.c;
  }
  if( u.am.c ){
    pc = pOp->p2-1;
  }
  break;
}

/* Opcode: IsNull P1 P2 P3 * *
**
** P1 is the first in an array of P3 registers. Or, if P3 is 0, the first
** in an array of a single register. If any registers in the array are
** NULL, jump to instruction P2.
*/
case OP_IsNull: {            /* same as TK_ISNULL, jump, in1 */
#if 0  /* local variables moved into u.an */
  Mem *pEnd;
#endif /* local variables moved into u.an */
  pIn1 = &aMem[pOp->p1];
  u.an.pEnd = &aMem[pOp->p1+pOp->p3];

  do {
    if( (pIn1->flags & MEM_Null)!=0 ){
      pc = pOp->p2 - 1;
      break;
    }
  }while( (++pIn1)<u.an.pEnd );

  break;
}

/* Opcode: NotNull P1 P2 * * *
**
** Jump to P2 if the value in register P1 is not NULL.  
*/
case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
  pIn1 = &aMem[pOp->p1];
  if( (pIn1->flags & MEM_Null)==0 ){
    pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: Column P1 P2 P3 P4 P5
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction.  (See the MakeRecord opcode for additional
** information about the format of the data.)  Extract the P2-th column
** from this record.  If there are less that (P2+1) 
** values in the record, extract a NULL.
**
** The value extracted is stored in register P3.
**
** If the column contains fewer than P2 fields, then extract a NULL.  Or,
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
**
** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
** then the cache of the cursor is reset prior to extracting the column.
** The first OP_Column against a pseudo-table after the value of the content
** register has changed should have this bit set.
*/
case OP_Column: {
#if 0  /* local variables moved into u.ao */
  int p1;                   /* Index of VdbeCursor to decode */
  int mxField;              /* Maximum column number */
  VdbeCursor *pC;           /* The VDBE cursor */
  Mem *pDest;               /* Where to write the results */
  Mem *pDefault;            /* Default value from P4 */
#endif /* local variables moved into u.ao */

  u.ao.p1 = pOp->p1;
  assert( u.ao.p1<p->nCursor );
  assert( pOp->p3>0 && pOp->p3<=p->nMem );
  u.ao.pDest = &aMem[pOp->p3];
  memAboutToChange(p, u.ao.pDest);
  u.ao.pC = p->apCsr[u.ao.p1];
  assert( u.ao.pC!=0 );
  assert( u.ao.pC->iRoot!=KVSTORE_ROOT );
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  assert( u.ao.pC->pVtabCursor==0 );
#endif
  if( u.ao.pC->pDecoder==0 ){
    u.ao.mxField = u.ao.pC->nField;
    if( u.ao.pC->pKeyInfo && u.ao.pC->pKeyInfo->nData ) u.ao.mxField = u.ao.pC->pKeyInfo->nData;
    rc = sqlite4VdbeDecoderCreate(db, u.ao.pC, 0, u.ao.mxField, &u.ao.pC->pDecoder);
    u.ao.pC->rowChnged = 1;
  }
  if( rc==SQLITE4_OK ){
    u.ao.pDefault = (pOp->p4type==P4_MEM) ? pOp->p4.pMem : 0;
    rc = sqlite4VdbeDecoderGetColumn(u.ao.pC->pDecoder, pOp->p2, u.ao.pDefault, u.ao.pDest);
  }else{
    sqlite4VdbeMemSetNull(u.ao.pDest);
  }
  UPDATE_MAX_BLOBSIZE(u.ao.pDest);
  REGISTER_TRACE(pOp->p3, u.ao.pDest);
  break;
}

/* Opcode:  MakeKey  P1 P2 P3 P4 P5
**
** Encode the values in registers P1..P1+P2-1 using the key encoding
** and write the result into register P3.  The cursor used for the encoding
** is given by the P4 value which must be an integer (P4_INT32).
**
** If the OPFLAG_SEQCOUNT bit of P5 is set, then a sequence number 
** (unique within the cursor) is appended to the record. The sole purpose
** of this is to ensure that the key blob is unique within the cursor table.
*/
/* Opcode:  MakeRecord  P1 P2 P3 P4 P5
**
** Encode the values in registers P1..P1+P2-1 using the data encoding
** and write the result into register P3.  Apply affinities in P4 prior
** to performing the encoding.
**
** If the OPFLAG_USEKEY bit of P5 is set and this opcode immediately follows
** an MakeKey opcode, then the data encoding generated may try to refer
** to content in the previously generated key in order to make the encoding
** smaller.
*/
case OP_MakeKey:
case OP_MakeRecord: {
#if 0  /* local variables moved into u.ap */
  VdbeCursor *pC;        /* The cursor for OP_MakeKey */
  Mem *pData0;           /* First field to be combined into the record */
  Mem *pLast;            /* Last field of the record */
  Mem *pMem;             /* For looping over inputs */
  Mem *pOut;             /* Where to store results */
  int nIn;               /* Number of input values to be encoded */
  char *zAffinity;       /* The affinity string */
  u8 *aRec;              /* The constructed key or value */
  int nRec;              /* Size of aRec[] in bytes */
  int bRepeat;           /* True to loop to the next opcode */
  u8 aSeq[10];           /* Encoded sequence number */
  int nSeq;              /* Size of sequence number in bytes */
  u64 iSeq;              /* Sequence number, if any */
#endif /* local variables moved into u.ap */

  do{
    u.ap.bRepeat = 0;
    u.ap.zAffinity = pOp->p4type==P4_INT32 ? 0 : pOp->p4.z;
    assert( pOp->p1>0 && pOp->p2>0 && pOp->p2+pOp->p1<=p->nMem+1 );
    u.ap.pData0 = &aMem[pOp->p1];
    u.ap.nIn = pOp->p2;
    u.ap.pLast = &u.ap.pData0[u.ap.nIn-1];
    assert( pOp->p3>0 && pOp->p3<=p->nMem );
    u.ap.pOut = &aMem[pOp->p3];
    memAboutToChange(p, u.ap.pOut);
    u.ap.aRec = 0;
    u.ap.nSeq = 0;

    /* Apply affinities */
    if( u.ap.zAffinity ){
      for(u.ap.pMem=u.ap.pData0; u.ap.pMem<=u.ap.pLast; u.ap.pMem++){
        assert( memIsValid(u.ap.pMem) );
        applyAffinity(u.ap.pMem, *(u.ap.zAffinity++), encoding);
      }
    }

    if( pOp->opcode==OP_MakeKey ){
      assert( pOp->p4type==P4_INT32 );
      assert( pOp->p4.i>=0 && pOp->p4.i<p->nCursor );
      u.ap.pC = p->apCsr[pOp->p4.i];

      /* If P4 contains OPFLAG_SEQCOUNT, encode the sequence number blob to be
      ** appended to the end of the key.  Variable u.ap.nSeq is set to the number
      ** of bytes in the encoded key.  A non-standard encoding is used (not
      ** the usual varint encoding) so that the OP_GrpCompare opcode can easily
      ** back up over the sequence count to find the true end of the key.
      */
      if( pOp->p5 & OPFLAG_SEQCOUNT ){
        u.ap.iSeq = u.ap.pC->seqCount++;
        do {
          u.ap.nSeq++;
          u.ap.aSeq[sizeof(u.ap.aSeq)-u.ap.nSeq] = (u8)(u.ap.iSeq & 0x007F);
          u.ap.iSeq = u.ap.iSeq >> 7;
        }while( u.ap.iSeq );
        u.ap.aSeq[sizeof(u.ap.aSeq)-u.ap.nSeq] |= 0x80;
      }

      /* Generate the key encoding */
      rc = sqlite4VdbeEncodeKey(
        db, u.ap.pData0, u.ap.nIn, u.ap.pC->iRoot, u.ap.pC->pKeyInfo, &u.ap.aRec, &u.ap.nRec, u.ap.nSeq
      );

      if( pOp[1].opcode==OP_MakeRecord ){
        pc++;
        pOp++;
        u.ap.bRepeat = 1;
      }
    }else{
      assert( pOp->opcode==OP_MakeRecord );
      rc = sqlite4VdbeEncodeData(db, u.ap.pData0, aPermute, u.ap.nIn, &u.ap.aRec, &u.ap.nRec);
      aPermute = 0;
    }

    /* Store the result */
    if( rc!=SQLITE4_OK ){
      sqlite4DbFree(db, u.ap.aRec);
    }else{
      if( u.ap.nSeq ) memcpy(&u.ap.aRec[u.ap.nRec], &u.ap.aSeq[sizeof(u.ap.aSeq)-u.ap.nSeq], u.ap.nSeq);
      rc = sqlite4VdbeMemSetStr(u.ap.pOut, (char *)u.ap.aRec, u.ap.nRec+u.ap.nSeq, 0,
                                SQLITE4_DYNAMIC, 0);
      REGISTER_TRACE(pOp->p3, u.ap.pOut);
      UPDATE_MAX_BLOBSIZE(u.ap.pOut);
    }
  }while( rc==SQLITE4_OK && u.ap.bRepeat );
  break;
}

/* Opcode: Affinity P1 P2 * P4 *
**
** Apply affinities to a range of P2 registers starting with P1.
**
** P4 is a string that is P2 characters long. The nth character of the
** string indicates the column affinity that should be used for the nth
** memory cell in the range.
*/
case OP_Affinity: {
#if 0  /* local variables moved into u.aq */
  const char *zAffinity;   /* The affinity to be applied */
  Mem *pEnd;
#endif /* local variables moved into u.aq */

  u.aq.zAffinity = pOp->p4.z;
  assert( u.aq.zAffinity!=0 );
  assert( sqlite4Strlen30(u.aq.zAffinity)>=pOp->p2 );

  u.aq.pEnd = &aMem[pOp->p2+pOp->p1];
  for(pIn1=&aMem[pOp->p1]; pIn1<u.aq.pEnd; pIn1++){
    assert( memIsValid(pIn1) );
    memAboutToChange(p, pIn1);
    applyAffinity(pIn1, *(u.aq.zAffinity++), encoding);
    REGISTER_TRACE(pIn1-aMem, pIn1);
  }

  break;
}

/* Opcode: Count P1 P2 * * *
**
** Store the number of entries (an integer value) in the table or index 
** opened by cursor P1 in register P2
*/
case OP_Count: {         /* out2-prerelease */
#if 0  /* local variables moved into u.ar */
  i64 nEntry;
  VdbeCursor *pC;
#endif /* local variables moved into u.ar */

  u.ar.pC = p->apCsr[pOp->p1];
  rc = sqlite4VdbeSeekEnd(u.ar.pC, +1);
  u.ar.nEntry = 0;
  while( rc!=SQLITE4_NOTFOUND ){
    u.ar.nEntry++;
    rc = sqlite4VdbeNext(u.ar.pC);
  }
  sqlite4VdbeMemSetInt64(pOut, u.ar.nEntry);
  if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;
  break;
}

/* Opcode: Savepoint P1 * * P4 *
**
** This opcode is used to implement the SQL BEGIN, COMMIT, ROLLBACK,
** SAVEPOINT, RELEASE and ROLLBACK TO commands. As follows:
**
**     sql command      p1     p4
**     -------------------------------------
**     BEGIN            0      0
**     COMMIT           1      0
**     ROLLBACK         2      0
**     SAVEPOINT        0      <name of savepoint to open>
**     RELEASE          1      <name of savepoint to release>
**     ROLLBACK TO      2      <name of savepoint to rollback>
*/
case OP_Savepoint: {
#if 0  /* local variables moved into u.as */
  int iSave;
  Savepoint *pSave;               /* Savepoint object operated upon */
  const char *zSave;              /* Name of savepoint (or NULL for trans.) */
  int nSave;                      /* Size of zSave in bytes */
  int iOp;                        /* SAVEPOINT_XXX operation */
  const char *zErr;               /* Static error message */
#endif /* local variables moved into u.as */

  u.as.zErr = 0;
  u.as.zSave = pOp->p4.z;
  u.as.nSave = u.as.zSave ? sqlite4Strlen30(u.as.zSave) : 0;
  u.as.iOp = pOp->p1;
  assert( pOp->p1==SAVEPOINT_BEGIN
       || pOp->p1==SAVEPOINT_RELEASE
       || pOp->p1==SAVEPOINT_ROLLBACK
  );

  if( u.as.iOp==SAVEPOINT_BEGIN ){
    if( u.as.zSave==0 && db->pSavepoint ){
      /* If u.as.zSave==0 this is a "BEGIN" command. Return an error if there is
      ** already an open transaction in this case.  */
      u.as.zErr = "cannot start a transaction within a transaction";
    }else{
      u.as.pSave = (Savepoint *)sqlite4DbMallocZero(db, u.as.nSave+1+sizeof(Savepoint));
      if( u.as.pSave==0 ) break;
      if( u.as.zSave ){
        u.as.pSave->zName = (char *)&u.as.pSave[1];
        memcpy(u.as.pSave->zName, u.as.zSave, u.as.nSave);
      }
      u.as.pSave->pNext = db->pSavepoint;
      u.as.pSave->nDeferredCons = db->nDeferredCons;
      db->pSavepoint = u.as.pSave;
      db->nSavepoint++;
    }
  }

  else{
    /* Determine which of the zero or more nested savepoints (if any) to
    ** commit or rollback to. This block sets variable u.as.pSave to point
    ** to the Savepoint object and u.as.iSave to the kvstore layer transaction
    ** number. For example, to commit or rollback the top level transaction
    ** u.as.iSave==2.  */
    u.as.iSave = db->nSavepoint+1;
    for(u.as.pSave=db->pSavepoint; u.as.pSave; u.as.pSave=u.as.pSave->pNext){
      if( u.as.zSave ){
        if( u.as.pSave->zName && 0==sqlite4_stricmp(u.as.zSave, u.as.pSave->zName) ) break;
      }else{
        if( u.as.pSave->pNext==0 ) break;
      }
      u.as.iSave--;
    }

    if( u.as.pSave==0 ){
      if( u.as.zSave ){
        sqlite4SetString(&p->zErrMsg, db, "no such savepoint: %s", u.as.zSave);
        rc = SQLITE4_ERROR;
      }else if( u.as.iOp==SAVEPOINT_RELEASE ){
        u.as.zErr = "cannot commit - no transaction is active";
      }else{
        u.as.zErr = "cannot rollback - no transaction is active";
      }
    }else{

      /* If this is an attempt to commit the top level transaction, check
      ** that there are no outstanding deferred foreign key violations. If
      ** there are, return an SQLITE4_CONSTRAINT error. Do not release any
      ** savepoints in this case.  */
      if( u.as.iOp==SAVEPOINT_RELEASE && u.as.iSave==2 ){
        rc = sqlite4VdbeCheckFk(p, 1);
        if( rc!=SQLITE4_OK ) break;
      }

      if( u.as.iOp==SAVEPOINT_RELEASE ){
        rc = sqlite4VdbeCommit(db, u.as.iSave-1);
      }else{
        rc = sqlite4VdbeRollback(db, u.as.iSave-(u.as.zSave==0));
      }
    }
  }

  if( u.as.zErr ){
    sqlite4SetString(&p->zErrMsg, db, "%s", u.as.zErr);
    rc = SQLITE4_ERROR;
  }
  break;
}

/* Opcode: Transaction P1 P2 * * *
**
** Begin a transaction.
**
** P1 is the index of the database file on which the transaction is
** started.  Index 0 is the main database file and index 1 is the
** file used for temporary tables.  Indices of 2 or more are used for
** attached databases.
**
** If P2 is non-zero, then a write-transaction is started.  If P2 is zero
** then a read-transaction is started.
**
** If a write-transaction is started and the Vdbe.needSavepoint flag is
** true (this flag is set if the Vdbe may modify more than one row and may
** throw an ABORT exception), a statement transaction may also be opened.
** More specifically, a statement transaction is opened iff the database
** connection is currently not in autocommit mode, or if there are other
** active statements. A statement transaction allows the affects of this
** VDBE to be rolled back after an error without having to roll back the
** entire transaction. If no error is encountered, the statement transaction
** will automatically commit when the VDBE halts.
*/
case OP_Transaction: {
#if 0  /* local variables moved into u.at */
  Db *pDb;
  KVStore *pKV;
  int bStmt;                      /* True to open statement transaction */
  int iLevel;                     /* Savepoint level to open */
#endif /* local variables moved into u.at */

  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  u.at.pDb = &db->aDb[pOp->p1];
  u.at.pKV = u.at.pDb->pKV;
  if( u.at.pKV ){
    if( pOp->p2==0 ){
      /* Read transaction needed.  Start if we are not already in one. */
      if( u.at.pKV->iTransLevel==0 ){
        rc = sqlite4KVStoreBegin(u.at.pKV, 1);
      }
    }else{
      /* A write transaction is needed */
      u.at.iLevel = db->nSavepoint + 1;
      if( u.at.iLevel<2 ) u.at.iLevel = 2;
      u.at.bStmt = db->pSavepoint && (p->needSavepoint || db->activeVdbeCnt>1);
      if( u.at.pKV->iTransLevel<u.at.iLevel ){
        rc = sqlite4KVStoreBegin(u.at.pKV, u.at.iLevel);
      }
      if( rc==SQLITE4_OK && u.at.bStmt ){
        rc = sqlite4KVStoreBegin(u.at.pKV, u.at.pKV->iTransLevel+1);
        if( rc==SQLITE4_OK ){
          p->stmtTransMask |= ((yDbMask)1)<<pOp->p1;
        }
        p->nStmtDefCons = db->nDeferredCons;
      }
    }
  }
  break;
}

/* Opcode: ReadCookie P1 P2 * * *
**
** Read the schema cookie from database P1 and write it into register P2.
**
** There must be a read-lock on the database (either a transaction
** must be started or there must be an open cursor) before
** executing this instruction.
*/
case OP_ReadCookie: {               /* out2-prerelease */
  unsigned int iMeta;
  KVStore *pKV;

  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  pKV = db->aDb[pOp->p1].pKV;
  rc = sqlite4KVStoreGetSchema(pKV, &iMeta);
  pOut->u.num = sqlite4_num_from_int64(iMeta);
  MemSetTypeFlag(pOut, MEM_Int);
  break;
}

/* Opcode: SetCookie P1 P2 P3 * *
**
** Write the content of register P3 (interpreted as an integer)
** into cookie number P2 of database P1.  P2==1 is the schema version.  
** P2==2 is the database format. P2==3 is the recommended pager cache 
** size, and so forth.  P1==0 is the main database file and P1==1 is the 
** database file used to store temporary tables.
**
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: {       /* in3 */
#if 0  /* local variables moved into u.au */
  Db *pDb;
  i64 v;
#endif /* local variables moved into u.au */

  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  u.au.pDb = &db->aDb[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  sqlite4VdbeMemIntegerify(pIn3);
  u.au.v = sqlite4_num_to_int64(pIn3->u.num, 0);
  rc = sqlite4KVStorePutSchema(u.au.pDb->pKV, (u32)u.au.v);
  u.au.pDb->pSchema->schema_cookie = (int)u.au.v;
  db->flags |= SQLITE4_InternChanges;
  if( pOp->p1==1 ){
    /* Invalidate all prepared statements whenever the TEMP database
    ** schema is changed.  Ticket #1644 */
    sqlite4ExpirePreparedStatements(db);
    p->expired = 0;
  }
  break;
}

/* Opcode: VerifyCookie P1 P2 P3 * *
**
** Check the value of global database parameter number 0 (the
** schema version) and make sure it is equal to P2 and that the
** generation counter on the local schema parse equals P3.
**
** P1 is the database number which is 0 for the main database file
** and 1 for the file holding temporary tables and some higher number
** for auxiliary databases.
**
** The cookie changes its value whenever the database schema changes.
** This operation is used to detect when that the cookie has changed
** and that the current process needs to reread the schema.
**
** Either a transaction needs to have been started or an OP_Open needs
** to be executed (to establish a read lock) before this opcode is
** invoked.
*/
case OP_VerifyCookie: {
  unsigned int iMeta;
  int iGen;
  KVStore *pKV;

  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  pKV = db->aDb[pOp->p1].pKV;
  if( pKV ){
    rc = sqlite4KVStoreGetSchema(pKV, &iMeta);
    if( rc ) break;
    iGen = db->aDb[pOp->p1].pSchema->iGeneration;
  }else{
    iGen = iMeta = 0;
  }
  if( iMeta!=pOp->p2 || iGen!=pOp->p3 ){
    sqlite4DbFree(db, p->zErrMsg);
    p->zErrMsg = sqlite4DbStrDup(db, "database schema has changed");
    /* If the schema-cookie from the database file matches the cookie 
    ** stored with the in-memory representation of the schema, do
    ** not reload the schema from the database file.
    **
    ** If virtual-tables are in use, this is not just an optimization.
    ** Often, v-tables store their data in other SQLite tables, which
    ** are queried from within xNext() and other v-table methods using
    ** prepared queries. If such a query is out-of-date, we do not want to
    ** discard the database schema, as the user code implementing the
    ** v-table would have to be ready for the sqlite4_vtab structure itself
    ** to be invalidated whenever sqlite4_step() is called from within 
    ** a v-table method.
    */
    if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
      sqlite4ResetInternalSchema(db, pOp->p1);
    }

    p->expired = 1;
    rc = SQLITE4_SCHEMA;
  }
  break;
}

/* Opcode: OpenRead P1 P2 P3 P4 P5
**
** Open a read-only cursor for the database table whose root page is
** P2 in a database file.  The database file is determined by P3. 
** P3==0 means the main database, P3==1 means the database used for 
** temporary tables, and P3>1 means used the corresponding attached
** database.  Give the new cursor an identifier of P1.  The P1
** values need not be contiguous but all P1 values should be small integers.
** It is an error for P1 to be negative.
**
** If P5!=0 then use the content of register P2 as the root page, not
** the value of P2 itself.
**
** There will be a read lock on the database whenever there is an
** open cursor.  If the database was unlocked prior to this instruction
** then a read lock is acquired as part of this instruction.  A read
** lock allows other processes to read the database but prohibits
** any other process from modifying the database.  The read lock is
** released when all cursors are closed.  If this instruction attempts
** to get a read lock but fails, the script terminates with an
** SQLITE4_BUSY error code.
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo 
** structure, then said structure defines the content and collating 
** sequence of the index being opened. Otherwise, if P4 is an integer 
** value, it is set to the number of columns in the table.
**
** See also OpenWrite.
*/
/* Opcode: OpenWrite P1 P2 P3 P4 P5
**
** Open a read/write cursor named P1 on the table or index whose root
** page is P2.  Or if P5!=0 use the content of register P2 to find the
** root page.
**
** The P4 value may be either an integer (P4_INT32) or a pointer to
** a KeyInfo structure (P4_KEYINFO). If it is a pointer to a KeyInfo 
** structure, then said structure defines the content and collating 
** sequence of the index being opened. Otherwise, if P4 is an integer 
** value, it is set to the number of columns in the table, or to the
** largest index of any column of the table that is actually used.
**
** This instruction works just like OpenRead except that it opens the cursor
** in read/write mode.  For a given table, there can be one or more read-only
** cursors or a single read/write cursor but not both.
**
** See also OpenRead.
*/
case OP_OpenRead:
case OP_OpenWrite: {
#if 0  /* local variables moved into u.av */
  int nField;
  KeyInfo *pKeyInfo;
  int p2;
  int iDb;
  KVStore *pX;
  VdbeCursor *pCur;
  Db *pDb;
#endif /* local variables moved into u.av */

  if( p->expired ){
    rc = SQLITE4_ABORT;
    break;
  }

  u.av.nField = 0;
  u.av.pKeyInfo = 0;
  u.av.p2 = pOp->p2;
  u.av.iDb = pOp->p3;
  assert( u.av.iDb>=0 && u.av.iDb<db->nDb );
  u.av.pDb = &db->aDb[u.av.iDb];
  u.av.pX = u.av.pDb->pKV;
  assert( u.av.pX!=0 );
  if( pOp->p5 ){
    assert( u.av.p2>0 );
    assert( u.av.p2<=p->nMem );
    pIn2 = &aMem[u.av.p2];
    assert( memIsValid(pIn2) );
    assert( (pIn2->flags & MEM_Int)!=0 );
    sqlite4VdbeMemIntegerify(pIn2);
    u.av.p2 = sqlite4_num_to_int32(pIn2->u.num, 0);
    /* The u.av.p2 value always comes from a prior OP_NewIdxid opcode and
    ** that opcode will always set the u.av.p2 value to 2 or more or else fail.
    ** If there were a failure, the prepared statement would have halted
    ** before reaching this instruction. */
    if( NEVER(u.av.p2<2) ) {
      rc = SQLITE4_CORRUPT_BKPT;
      goto abort_due_to_error;
    }
  }
  if( pOp->p4type==P4_KEYINFO ){
    u.av.pKeyInfo = pOp->p4.pKeyInfo;
    u.av.nField = u.av.pKeyInfo->nField+1;
  }else if( pOp->p4type==P4_INT32 ){
    u.av.nField = pOp->p4.i;
  }
  assert( pOp->p1>=0 );
  u.av.pCur = allocateCursor(p, pOp->p1, u.av.nField, u.av.iDb, 1);
  if( u.av.pCur==0 ) goto no_mem;
  u.av.pCur->nullRow = 1;
  u.av.pCur->iRoot = u.av.p2;
  rc = sqlite4KVStoreOpenCursor(u.av.pX, &u.av.pCur->pKVCur);
  u.av.pCur->pKeyInfo = u.av.pKeyInfo;
  break;
}

/* Opcode: OpenEphemeral P1 P2 * P4 P5
**
** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if 
** the main database is read-only.  The ephemeral
** table is deleted automatically when the cursor is closed.
**
** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0.  If P4 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
**
** This opcode was once called OpenTemp.  But that created
** confusion because the term "temp table", might refer either
** 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 *
**
** This opcode works the same as OP_OpenEphemeral.  It has a
** different name to distinguish its use.  Tables created using
** by this opcode will be used for automatically created transient
** indices in joins.
*/
case OP_OpenAutoindex: 
case OP_OpenEphemeral: {
#if 0  /* local variables moved into u.aw */
  VdbeCursor *pCx;
#endif /* local variables moved into u.aw */

  assert( pOp->p1>=0 );
  u.aw.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
  if( u.aw.pCx==0 ) goto no_mem;
  u.aw.pCx->nullRow = 1;

  rc = sqlite4KVStoreOpen(db, "ephm", 0, &u.aw.pCx->pTmpKV,
          SQLITE4_KVOPEN_TEMPORARY | SQLITE4_KVOPEN_NO_TRANSACTIONS
  );
  if( rc==SQLITE4_OK ) rc = sqlite4KVStoreOpenCursor(u.aw.pCx->pTmpKV, &u.aw.pCx->pKVCur);
  if( rc==SQLITE4_OK ) rc = sqlite4KVStoreBegin(u.aw.pCx->pTmpKV, 2);

  u.aw.pCx->pKeyInfo = pOp->p4.pKeyInfo;

  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: {
  /* VdbeCursor *pCx; */
  pOp->opcode = OP_OpenEphemeral;
  pc--;
  break;
}

/* Opcode: Close P1 * * * *
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  sqlite4VdbeFreeCursor(p->apCsr[pOp->p1]);
  p->apCsr[pOp->p1] = 0;
  break;
}

/* Opcode: SeekPk P1 * P3 * *
**
** P1 must be a cursor open on a PRIMARY KEY index. P3 is a cursor open
** on an auxiliary index on the same table. P3 must be pointing to a valid
** index entry.
**
** This opcode seeks cursor P1 so that it points to the PK index entry
** that corresponds to the same table row as the current entry that 
** cursor P3 points to. The entry must exist.
**
** Actually, the seek is deferred until it is actually needed and if the
** PRIMARY KEY index is never referenced, the seek never takes place.  The
** sqlite3VdbeCursorMoveto() does the seek, if necessary.  If the target
** row does not exist in the PRIMARY KEY table, then the
** sqlite3VdbeCursorMoveto() routine will throw an SQLITE4_CORRUPT error.
*/
case OP_SeekPk: {
#if 0  /* local variables moved into u.ax */
  KVByteArray *aKey;              /* Key data from cursor pIdx */
  KVSize nKey;                    /* Size of aKey[] in bytes */
  VdbeCursor *pPk;                /* Cursor P1 */
  VdbeCursor *pIdx;               /* Cursor P3 */
  int nShort;                     /* Size of aKey[] without PK fields */
  int nVarint;                    /* Size of varint pPk->iRoot */
#endif /* local variables moved into u.ax */

  u.ax.pPk = p->apCsr[pOp->p1];
  u.ax.pIdx = p->apCsr[pOp->p3];

  if( u.ax.pIdx->pFts ){
    rc = sqlite4Fts5Pk(u.ax.pIdx->pFts, u.ax.pPk->iRoot, &u.ax.aKey, &u.ax.nKey);
    if( rc==SQLITE4_OK ){
      rc = sqlite4KVCursorSeek(u.ax.pPk->pKVCur, u.ax.aKey, u.ax.nKey, 0);
      if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_CORRUPT_BKPT;
      u.ax.pPk->nullRow = 0;
    }
  }else{
    rc = sqlite4KVCursorKey(u.ax.pIdx->pKVCur, (const KVByteArray **)&u.ax.aKey, &u.ax.nKey);
    if( rc!=SQLITE4_OK ) break;
    u.ax.nShort = sqlite4VdbeShortKey(u.ax.aKey, u.ax.nKey,
        u.ax.pIdx->pKeyInfo->nField - u.ax.pIdx->pKeyInfo->nPK, 0
    );
    u.ax.nVarint = sqlite4VarintLen(u.ax.pPk->iRoot);
    rc = sqlite4_buffer_resize(&u.ax.pPk->sSeekKey, u.ax.nVarint + u.ax.nKey - u.ax.nShort);
    if( rc!=SQLITE4_OK ) break;
    putVarint32((u8 *)(u.ax.pPk->sSeekKey.p), u.ax.pPk->iRoot);
    memcpy(((u8*)u.ax.pPk->sSeekKey.p) + u.ax.nVarint, &u.ax.aKey[u.ax.nShort], u.ax.nKey-u.ax.nShort);
    assert( u.ax.pPk->sSeekKey.n>0 );
  }
  u.ax.pPk->rowChnged = 1;

  break;
}

/* Opcode: SeekGe P1 P2 P3 P4 *
**
** P1 identifies an open database cursor. The cursor is repositioned so
** that it points to the smallest entry in its index that is greater than
** or equal to the key formed by the array of P4 registers starting at
** register P3.
**
** If there are no records greater than or equal to the key and P2 is 
** not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
*/
/* Opcode: SeekGt P1 P2 P3 P4 *
**
** P1 identifies an open database cursor. The cursor is repositioned so
** that it points to the smallest entry in its index that is greater than
** the key formed by the array of P4 registers starting at
** register P3.
**
** If there are no records greater than the key and P2 is 
** not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
*/
/* Opcode: SeekLt P1 P2 P3 P4 * 
**
** P1 identifies an open database cursor. The cursor is repositioned so
** that it points to the largest entry in its index that is less than
** the key formed by the array of P4 registers starting at
** register P3.
**
** If there are no records less than the key and P2 is 
** not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
*/
/* Opcode: SeekLe P1 P2 P3 P4 *
**
** P1 identifies an open database cursor. The cursor is repositioned so
** that it points to the largest entry in its index that is less than or
** equal to the key formed by the array of P4 registers starting at
** register P3.
**
** If there are no records less than or equal to the key and P2 is 
** not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
*/
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.ay */
  int op;                         /* Copy of pOp->opcode (the op-code) */
  VdbeCursor *pC;                 /* Cursor P1 */
  int nField;                     /* Number of values to encode into key */
  KVByteArray *aProbe;            /* Buffer containing encoded key */
  KVSize nProbe;                  /* Size of aProbe[] in bytes */
  int dir;                        /* KV search dir (+ve or -ve) */
  const KVByteArray *aKey;        /* Pointer to final cursor key */
  KVSize nKey;                    /* Size of aKey[] in bytes */
#endif /* local variables moved into u.ay */

  u.ay.pC = p->apCsr[pOp->p1];
  u.ay.pC->nullRow = 0;
  u.ay.pC->sSeekKey.n = 0;
  u.ay.pC->rowChnged = 1;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p2!=0 );
  assert( u.ay.pC!=0 );
  assert( OP_SeekLe == OP_SeekLt+1 );
  assert( OP_SeekGe == OP_SeekLt+2 );
  assert( OP_SeekGt == OP_SeekLt+3 );

  u.ay.dir = +1;
  u.ay.op = pOp->opcode;
  if( u.ay.op==OP_SeekLe || u.ay.op==OP_SeekLt ) u.ay.dir = -1;

  /* Encode a database key consisting of the contents of the P4 registers
  ** starting at register P3. Have the vdbecodec module allocate an extra
  ** free byte at the end of the database key (see below).  */
  u.ay.nField = pOp->p4.i;
  pIn3 = &aMem[pOp->p3];
  if( u.ay.pC->iRoot!=KVSTORE_ROOT ){
    rc = sqlite4VdbeEncodeKey(
        db, pIn3, u.ay.nField, u.ay.pC->iRoot, u.ay.pC->pKeyInfo, &u.ay.aProbe, &u.ay.nProbe, 1
    );

    /*   Opcode    search-u.ay.dir    increment-key
    **  --------------------------------------
    **   SeekLt    -1            no
    **   SeekLe    -1            yes
    **   SeekGe    +1            no
    **   SeekGt    +1            yes
    */
    if( u.ay.op==OP_SeekLe || u.ay.op==OP_SeekGt ) u.ay.aProbe[u.ay.nProbe++] = 0xFF;
    if( rc==SQLITE4_OK ){
      rc = sqlite4KVCursorSeek(u.ay.pC->pKVCur, u.ay.aProbe, u.ay.nProbe, u.ay.dir);
    }
  }else{
    Stringify(pIn3, encoding);
    rc = sqlite4KVCursorSeek(
        u.ay.pC->pKVCur, (const KVByteArray *)pIn3->z, pIn3->n, u.ay.dir
    );
  }

  if( rc==SQLITE4_OK ){
    if( u.ay.op==OP_SeekLt ){
      rc = sqlite4KVCursorPrev(u.ay.pC->pKVCur);
    }else if( u.ay.op==OP_SeekGt ){
      rc = sqlite4KVCursorNext(u.ay.pC->pKVCur);
    }
  }

  if( u.ay.pC->iRoot!=KVSTORE_ROOT ){
    /* Check that the KV cursor currently points to an entry belonging
    ** to index u.ay.pC->iRoot (and not an entry that is part of some other
    ** index).  */
    if( rc==SQLITE4_OK || rc==SQLITE4_INEXACT ){
      rc = sqlite4KVCursorKey(u.ay.pC->pKVCur, &u.ay.aKey, &u.ay.nKey);
      if( rc==SQLITE4_OK && memcmp(u.ay.aKey, u.ay.aProbe, sqlite4VarintLen(u.ay.pC->iRoot)) ){
        rc = SQLITE4_NOTFOUND;
      }
    }

    /* Free the key allocated above. If no error has occurred but the cursor
    ** does not currently point to a valid entry, jump to instruction P2.  */
    sqlite4DbFree(db, u.ay.aProbe);
  }else if( rc==SQLITE4_INEXACT ){
    rc = SQLITE4_OK;
  }

#ifdef SQLITE4_TEST
  if( rc==SQLITE4_OK ){ sqlite4_search_count++; }
#endif
  if( rc==SQLITE4_NOTFOUND ){
    rc = SQLITE4_OK;
    pc = pOp->p2 - 1;
  }
  break;
}
 

/* Opcode: Found P1 P2 P3 P4 *
**
** If P4==0 then register P3 holds a blob constructed by MakeKey.  If
** P4>0 then register P3 is the first of P4 registers that should be
** combined to generate a key.
**
** Cursor P1 is open on an index.  If the record identified by P3 and P4
** is a prefix of any entry in P1 then a jump is made to P2 and
** P1 is left pointing at the matching entry.
*/
/* Opcode: NotFound P1 P2 P3 P4 *
**
** If P4==0 then register P3 holds a blob constructed by MakeKey.  If
** P4>0 then register P3 is the first of P4 registers that should be
** combined to generate key.
** 
** Cursor P1 is on an index.  If the record identified by P3 and P4
** is not the prefix of any entry in P1 then a jump is made to P2.  If P1 
** does contain an entry whose prefix matches the P3/P4 record then control
** falls through to the next instruction and P1 is left pointing at the
** matching entry.
**
** See also: Found, NotExists, IsUnique
*/
/* Opcode: NotExists P1 P2 P3 * *
**
** Use the content of register P3 as an integer key.  If a record 
** with that key does not exist in table of P1, then jump to P2. 
** If the record does exist, then fall through.  The cursor is left 
** pointing to the record if it exists.
**
** The difference between this operation and NotFound is that this
** operation assumes the key is an integer and that P1 is a table whereas
** NotFound assumes key is a blob constructed from MakeKey and
** P1 is an index.
**
** See also: Found, NotFound, IsUnique
*/
case OP_NotExists: {    /* jump, in3 */
  pOp->p4.i = 1;
  pOp->p4type = P4_INT32;
  /* Fall through into OP_NotFound */
}
case OP_NotFound:       /* jump, in3 */
case OP_Found: {        /* jump, in3 */
#if 0  /* local variables moved into u.az */
  int alreadyExists;
  VdbeCursor *pC;
  KVByteArray *pFree;
  KVByteArray *pProbe;
  KVSize nProbe;
  const KVByteArray *pKey;
  KVSize nKey;
#endif /* local variables moved into u.az */

#ifdef SQLITE4_TEST
  sqlite4_found_count++;
#endif

  u.az.alreadyExists = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p4type==P4_INT32 );
  u.az.pC = p->apCsr[pOp->p1];
  u.az.pC->sSeekKey.n = 0;
  u.az.pC->rowChnged = 1;
  assert( u.az.pC!=0 );
  pIn3 = &aMem[pOp->p3];
  assert( u.az.pC->pKVCur!=0 );
  if( pOp->p4.i>0 ){
    rc = sqlite4VdbeEncodeKey(
        db, pIn3, pOp->p4.i, u.az.pC->iRoot, u.az.pC->pKeyInfo, &u.az.pProbe, &u.az.nProbe, 0
    );
    u.az.pFree = u.az.pProbe;
  }else{
    u.az.pProbe = (KVByteArray*)pIn3->z;
    u.az.nProbe = pIn3->n;
    u.az.pFree = 0;
  }
  if( rc==SQLITE4_OK ){
    rc = sqlite4KVCursorSeek(u.az.pC->pKVCur, u.az.pProbe, u.az.nProbe, +1);
    if( rc==SQLITE4_INEXACT || rc==SQLITE4_OK ){
      rc = sqlite4KVCursorKey(u.az.pC->pKVCur, &u.az.pKey, &u.az.nKey);
      if( rc==SQLITE4_OK && u.az.nKey>=u.az.nProbe && memcmp(u.az.pKey, u.az.pProbe, u.az.nProbe)==0 ){
        u.az.alreadyExists = 1;
        u.az.pC->nullRow = 0;
      }
    }else if( rc==SQLITE4_NOTFOUND ){
      rc = SQLITE4_OK;
    }
  }
  sqlite4DbFree(db, u.az.pFree);
  if( pOp->opcode==OP_Found ){
    if( u.az.alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !u.az.alreadyExists ) pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: IsUnique P1 P2 P3 P4 *
**
** Cursor P1 is open on an index that enforces a UNIQUE constraint. 
** Register P3 contains an encoded key suitable to be inserted into the 
** index. If the key can be inserted into the index without violating
** a UNIQUE constraint, jump to instruction P2. Otherwise, fall through
** to the next instruction.
**
** If P4 is a non-zero integer and the jump is not taken, then it is
** a register that currently contains a blob. At the start of the blob
** is a varint that contains the index number for the PRIMARY KEY index
** of the table. The contents of P4 are overwritten with an index key
** composed of the varint from the start of the initial blob content
** and the PRIMARY KEY values from the index entry causing the UNIQUE
** constraint to fail.
*/
case OP_IsUnique: {        /* jump, in3 */
#if 0  /* local variables moved into u.ba */
  VdbeCursor *pC;
  Mem *pProbe;
  Mem *pOut;
  int iOut;
  int nShort;
  int dir;
  int bPk;
  u64 dummy;
#endif /* local variables moved into u.ba */

  KVByteArray const *aKey;        /* Key read from cursor */
  KVSize nKey;                    /* Size of aKey in bytes */

  assert( pOp->p4type==P4_INT32 );

  u.ba.pProbe = &aMem[pOp->p3];
  u.ba.pC = p->apCsr[pOp->p1];
  u.ba.pC->rowChnged = 1;
  u.ba.pOut = (pOp->p4.i==0 ? 0 : &aMem[pOp->p4.i]);
  u.ba.bPk = (u.ba.pC->pKeyInfo->nPK==0);
  assert( u.ba.pOut==0 || (u.ba.pOut->flags & MEM_Blob) || u.ba.bPk );

  if( u.ba.bPk==0 ){
    u.ba.nShort = sqlite4VdbeShortKey((u8 *)u.ba.pProbe->z, u.ba.pProbe->n,
        u.ba.pC->pKeyInfo->nField - u.ba.pC->pKeyInfo->nPK, 0
        );
    assert( u.ba.nShort<=u.ba.pProbe->n );
    assert( (u.ba.nShort==u.ba.pProbe->n)==(u.ba.pC->pKeyInfo->nPK==0) );
  }else{
    u.ba.nShort = u.ba.pProbe->n;
  }

  u.ba.dir = !u.ba.bPk;      /* "u.ba.dir = (u.ba.bPk ? 0 : 1);" */
  rc = sqlite4KVCursorSeek(u.ba.pC->pKVCur, (u8 *)u.ba.pProbe->z, u.ba.nShort, u.ba.dir);

  if( rc==SQLITE4_OK && u.ba.pOut ){
    sqlite4VdbeMemCopy(u.ba.pOut, u.ba.pProbe);
  }else if( rc==SQLITE4_NOTFOUND ){
    rc = SQLITE4_OK;
    pc = pOp->p2-1;
  }else if( rc==SQLITE4_INEXACT ){
    assert( u.ba.nShort<u.ba.pProbe->n );
    assert( u.ba.bPk==0 );
    rc = sqlite4KVCursorKey(u.ba.pC->pKVCur, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      if( nKey<u.ba.nShort || memcmp(u.ba.pProbe->z, aKey, u.ba.nShort) ){
        pc = pOp->p2-1;
      }else if( u.ba.pOut ){
        u.ba.iOut = sqlite4GetVarint64((u8 *)u.ba.pOut->z, u.ba.pOut->n, &u.ba.dummy);
        rc = sqlite4VdbeMemGrow(u.ba.pOut, u.ba.iOut+(nKey - u.ba.nShort), 1);
        if( rc==SQLITE4_OK ){
          memcpy(&u.ba.pOut->z[u.ba.iOut], &aKey[u.ba.nShort], (nKey - u.ba.nShort));
          u.ba.pOut->n = u.ba.iOut + (nKey - u.ba.nShort);
        }
      }
    }
  }

  break;
}

/* Opcode: Sequence P1 P2 * * *
**
** Find the next available sequence number for cursor P1.
** Write the sequence number into register P2.
** The sequence number on the cursor is incremented after this
** instruction.  
*/
case OP_Sequence: {           /* out2-prerelease */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( p->apCsr[pOp->p1]!=0 );
  pOut->u.num = sqlite4_num_from_int64(p->apCsr[pOp->p1]->seqCount++);
  break;
}


/* Opcode: NewRowid P1 P2 P3 * *
**
** Get a new integer primary key (a.k.a "rowid") for table P1.  The integer
** should not be currently in use as a primary key on that table.
**
** If P3 is not zero, then it is the number of a register in the top-level
** frame that holds a lower bound for the new rowid.  In other words, the
** new rowid must be no less than reg[P3]+1.
*/
case OP_NewRowid: {           /* out2-prerelease */
#if 0  /* local variables moved into u.bb */
  i64 v;                   /* The new rowid */
  VdbeCursor *pC;          /* Cursor of table to get the new rowid */
  const KVByteArray *aKey; /* Key of an existing row */
  KVSize nKey;             /* Size of the existing row key */
  int n;                   /* Number of bytes decoded */
  i64 i3;                  /* Integer value from pIn3 */
  sqlite4_num vNum;        /* Intermediate result */
#endif /* local variables moved into u.bb */

  u.bb.v = 0;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bb.pC = p->apCsr[pOp->p1];
  assert( u.bb.pC!=0 );

  /* Some compilers complain about constants of the form 0x7fffffffffffffff.
  ** Others complain about 0x7ffffffffffffffffLL.  The following macro seems
  ** to provide the constant while making all compilers happy.
  */
# define MAX_ROWID  (i64)( (((u64)0x7fffffff)<<32) | (u64)0xffffffff )

  /* The next rowid or record number (different terms for the same
  ** thing) is obtained in a two-step algorithm.
  **
  ** First we attempt to find the largest existing rowid and add one
  ** to that.  But if the largest existing rowid is already the maximum
  ** positive integer, we have to fall through to the second
  ** probabilistic algorithm
  **
  ** The second algorithm is to select a rowid at random and see if
  ** it already exists in the table.  If it does not exist, we have
  ** succeeded.  If the random rowid does exist, we select a new one
  ** and try again, up to 100 times.
  */

  rc = sqlite4VdbeSeekEnd(u.bb.pC, -2);
  if( rc==SQLITE4_NOTFOUND ){
    u.bb.v = 0;
    rc = SQLITE4_OK;
  }else if( rc==SQLITE4_OK ){
    rc = sqlite4KVCursorKey(u.bb.pC->pKVCur, &u.bb.aKey, &u.bb.nKey);
    if( rc==SQLITE4_OK ){
      u.bb.n = sqlite4GetVarint64((u8 *)u.bb.aKey, u.bb.nKey, (u64 *)&u.bb.v);
      if( u.bb.n==0 ) rc = SQLITE4_CORRUPT_BKPT;
      if( u.bb.v!=u.bb.pC->iRoot ) rc = SQLITE4_CORRUPT_BKPT;
    }
    if( rc==SQLITE4_OK ){
      u.bb.n = sqlite4VdbeDecodeNumericKey(&u.bb.aKey[u.bb.n], u.bb.nKey-u.bb.n, &u.bb.vNum);
      if( u.bb.n==0 || (u.bb.v = sqlite4_num_to_int64(u.bb.vNum,0))==LARGEST_INT64 ){
        assert( 0 );
        rc = SQLITE4_FULL;
      }
    }
  }else{
    break;
  }
#ifndef SQLITE_OMIT_AUTOINCREMENT
  if( pOp->p3 && rc==SQLITE4_OK ){
    pIn3 = sqlite4RegisterInRootFrame(p, pOp->p3);
    assert( memIsValid(pIn3) );
    REGISTER_TRACE(pOp->p3, pIn3);
    sqlite4VdbeMemIntegerify(pIn3);
    assert( (pIn3->flags & MEM_Int)!=0 );  /* mem(P3) holds an integer */
    u.bb.i3 = sqlite4_num_to_int64(pIn3->u.num, 0);
    if( u.bb.i3==MAX_ROWID ){
      rc = SQLITE4_FULL;
      assert( 0 );
    }
    if( u.bb.v<u.bb.i3 ) u.bb.v = u.bb.i3;
  }
#endif
  pOut->flags = MEM_Int;
  pOut->u.num = sqlite4_num_from_int64(u.bb.v+1);
  break;
}

/* Opcode: NewIdxid P1 P2 * * *
**
** This opcode is used to allocated new integer index numbers. P1 must
** be an integer value when this opcode is invoked. Before the opcode
** concludes, P1 is set to a value 1 greater than the larger of:
**
**   * its current value, or 
**   * the largest index number still visible in the database using the 
**     LEFAST query mode used by OP_NewRowid in database P2.
*/
case OP_NewIdxid: {          /* in1 */
#if 0  /* local variables moved into u.bc */
  u64 iMax;
  i64 i1;
  KVStore *pKV;
  KVCursor *pCsr;
#endif /* local variables moved into u.bc */

  u.bc.pKV = db->aDb[pOp->p2].pKV;
  pIn1 = &aMem[pOp->p1];
  u.bc.iMax = 0;
  assert( pIn1->flags & MEM_Int );

  rc = sqlite4KVStoreOpenCursor(u.bc.pKV, &u.bc.pCsr);
  if( rc==SQLITE4_OK ){
    const u8 aKey[] = { 0xFF, 0xFF };
    rc = sqlite4KVCursorSeek(u.bc.pCsr, aKey, sizeof(aKey), -2);
    if( rc==SQLITE4_OK || rc==SQLITE4_INEXACT ){
      const KVByteArray *pKey;
      KVSize nKey;
      rc = sqlite4KVCursorKey(u.bc.pCsr, &pKey, &nKey);
      if( rc==SQLITE4_OK ){
        sqlite4GetVarint64((const unsigned char *)pKey, nKey, &u.bc.iMax);
      }
    }else if( rc==SQLITE4_NOTFOUND ){
      rc = SQLITE4_OK;
    }
    sqlite4KVCursorClose(u.bc.pCsr);
  }

  u.bc.i1 = sqlite4_num_to_int64(pIn1->u.num, 0);
  if( u.bc.i1>=(i64)u.bc.iMax ){
    u.bc.i1++;
  }else{
    u.bc.i1 = u.bc.iMax+1;
  }
  pIn1->u.num = sqlite4_num_from_int64(u.bc.i1);

  break;
}

/* Opcode: Delete P1 P2 * * *
**
** Delete the record at which the P1 cursor is currently pointing.
**
** The cursor will be left pointing at either the next or the previous
** record in the table. If it is left pointing at the next record, then
** the next Next instruction will be a no-op.  Hence it is OK to delete
** a record from within an Next loop.
**
** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
** incremented (otherwise not).
**
** P1 must not be pseudo-table. It has to be a real table.
*/
case OP_Delete: {
#if 0  /* local variables moved into u.bd */
  VdbeCursor *pC;
#endif /* local variables moved into u.bd */
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bd.pC = p->apCsr[pOp->p1];
  assert( u.bd.pC!=0 );
  assert( u.bd.pC->sSeekKey.n==0 );
  u.bd.pC->rowChnged = 1;
  rc = sqlite4KVCursorDelete(u.bd.pC->pKVCur);
  if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  break;
}

/* Opcode: ResetCount * * * * *
**
** The value of the change counter is copied to the database handle
** change counter (returned by subsequent calls to sqlite4_changes()).
** Then the VMs internal change counter resets to 0.
** This is used by trigger programs.
*/
case OP_ResetCount: {
  sqlite4VdbeSetChanges(db, p->nChange);
  p->nChange = 0;
  break;
}

/* Opcode: GrpCompare P1 P2 P3
**
** P1 is a cursor used to sort records. Its keys consist of the fields being
** sorted on encoded as an ordinary database key, followed by a sequence 
** number encoded as defined by the comments surrounding OP_MakeIdxKey. 
** Register P3 either contains NULL, or such a key truncated so as to 
** remove the sequence number.
**
** This opcode compares the current key of P1, less the sequence number, 
** with the contents of register P3. If they are identical, jump to 
** instruction P2. Otherwise, replace the contents of P3 with the current
** key of P1 (minus the sequence number) and fall through to the next
** instruction.
*/
case OP_GrpCompare: {
#if 0  /* local variables moved into u.be */
  VdbeCursor *pC;                 /* Cursor P1 */
#endif /* local variables moved into u.be */
  KVByteArray const *aKey;        /* Key from cursor P1 */
  KVSize nKey;                    /* Size of aKey[] in bytes */

  u.be.pC = p->apCsr[pOp->p1];
  rc = sqlite4KVCursorKey(u.be.pC->pKVCur, &aKey, &nKey);
  if( rc==SQLITE4_OK ){
    for(nKey--; (aKey[nKey] & 0x80)==0; nKey--);
  }

  pIn3 = &aMem[pOp->p3];
  if( (pIn3->flags & MEM_Blob)
   && pIn3->n==nKey && 0==memcmp(pIn3->z, aKey, nKey)
  ){
    pc = pOp->p2-1;
  }else{
    sqlite4VdbeMemSetStr(pIn3, (const char*)aKey, nKey, 0, SQLITE4_TRANSIENT,0);
  }

  break;
};

/* Opcode: SorterData P1 P2 * * *
**
** Write into register P2 the current sorter data for sorter cursor P1.
*/
/* Opcode: RowData P1 P2 * * *
**
** Write into register P2 the complete row data for cursor P1.
** There is no interpretation of the data.  
** It is just copied onto the P2 register exactly as 
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
*/
/* Opcode: RowKey P1 P2 * * P5
**
** Write into register P2 the complete row key for cursor P1. There is 
** no interpretation of the data. The key is copied onto the P3 register 
** exactly as it is found in the database file.
**
** The P1 cursor must be pointing to a valid row (not a NULL row)
** of a real table, not a pseudo-table.
**
** If P5 is non-zero, it is a flag indicating that this value will be
** stored as a sample in the sqlite_stat3 table. At present, this means
** that the table number is stripped from the start of the record, and
** then all but the initial field removed from the end. In other words,
** the blob copied into register P2 is the first field of the index-key
** only.
*/
case OP_SorterData:
case OP_RowKey:
case OP_RowData: {
#if 0  /* local variables moved into u.bf */
  VdbeCursor *pC;
  KVCursor *pCrsr;
  const KVByteArray *pData;
  KVSize nData;
  int nVarint;
  u64 dummy;
#endif /* local variables moved into u.bf */

  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.bf.pC = p->apCsr[pOp->p1];
  rc = sqlite4VdbeCursorMoveto(u.bf.pC);
  if( rc!=SQLITE4_OK ) break;
  assert( u.bf.pC->nullRow==0 );
  assert( u.bf.pC->pKVCur!=0 );
  u.bf.pCrsr = u.bf.pC->pKVCur;

  if( pOp->opcode==OP_RowKey ){
    rc = sqlite4KVCursorKey(u.bf.pCrsr, &u.bf.pData, &u.bf.nData);
    if( pOp->p5 ){
      u.bf.nData = sqlite4VdbeShortKey(u.bf.pData, u.bf.nData, 1, 0);
      u.bf.nVarint = sqlite4GetVarint64(u.bf.pData, u.bf.nData, &u.bf.dummy);
      u.bf.pData += u.bf.nVarint;
      u.bf.nData -= u.bf.nVarint;
    }
  }else{
    rc = sqlite4KVCursorData(u.bf.pCrsr, 0, -1, &u.bf.pData, &u.bf.nData);
  }
  if( rc==SQLITE4_OK && u.bf.nData>db->aLimit[SQLITE4_LIMIT_LENGTH] ){
    goto too_big;
  }
  sqlite4VdbeMemSetStr(pOut, (const char*)u.bf.pData, u.bf.nData, 0, SQLITE4_TRANSIENT,0);
  pOut->enc = SQLITE4_UTF8;  /* In case the blob is ever cast to text */
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: AnalyzeKey P1 P2 P3 P4
**
** P1 is an open cursor that currently points to a valid row. P2 is a 
** register that contains either a NULL value, or an index key. If it is 
** not NULL, this opcode compares the key in register P2 with the key of 
** the row P1 currently points to and determines the number of fields in
** the prefix that the two keys share in common (which may be zero).
** Call this value N. If P2 is NULL, set N to P4.
**
** P3 is the first in an array of P4 registers containing integer values.
** The first N of these are left as is by this instruction. The remaining
** (P4-N) are incremented.
**
** Finally, the key belonging to the current row of cursor P1 is copied
** into register P2.
*/
case OP_AnalyzeKey: {
#if 0  /* local variables moved into u.bg */
  VdbeCursor *pC;
  const KVByteArray *pNew;
  KVSize nNew;
  Mem *pKey;
  Mem *aIncr;
  int nEq;
  int nTotal;
  int i;
#endif /* local variables moved into u.bg */

  u.bg.pKey = &aMem[pOp->p2];
  u.bg.aIncr = &aMem[pOp->p3];
  u.bg.nTotal = pOp->p4.i;
  u.bg.pC = p->apCsr[pOp->p1];
  assert( u.bg.pC!=0 );
  assert( u.bg.pC->nullRow==0 );
  assert( u.bg.pC->pKVCur!=0 );
  assert( pOp->p4type==P4_INT32 );

  rc = sqlite4KVCursorKey(u.bg.pC->pKVCur, &u.bg.pNew, &u.bg.nNew);
  if( rc==SQLITE4_OK ){
    assert( u.bg.pKey->flags & (MEM_Blob|MEM_Null) );
    if( u.bg.pKey->flags & MEM_Blob ){
      for(u.bg.i=0; u.bg.i<u.bg.nNew && u.bg.i<u.bg.pKey->n && u.bg.pNew[u.bg.i]==(KVByteArray)u.bg.pKey->z[u.bg.i]; u.bg.i++);

      /* The two keys share u.bg.i bytes in common. Figure out how many fields
      ** this corresponds to. Store said value in variable u.bg.nEq. */
      sqlite4VdbeShortKey(u.bg.pNew, u.bg.i, LARGEST_INT32, &u.bg.nEq);
    }else{
      u.bg.nEq = u.bg.nTotal;
    }

    /* Increment u.bg.nTotal-u.bg.nEq registers */
    for(u.bg.i=u.bg.nEq; u.bg.i<u.bg.nTotal; u.bg.i++){
      memAboutToChange(p, &u.bg.aIncr[u.bg.i]);
      sqlite4VdbeMemIntegerify(&u.bg.aIncr[u.bg.i]);
      u.bg.aIncr[u.bg.i].u.num = sqlite4_num_add(
          u.bg.aIncr[u.bg.i].u.num, sqlite4_num_from_int64(1)
      );
      REGISTER_TRACE(pOp->p1, &u.bg.aIncr[u.bg.i]);
    }

    /* Copy the new key into register P2 */
    memAboutToChange(p, u.bg.pKey);
    sqlite4VdbeMemSetStr(u.bg.pKey, (const char*)u.bg.pNew, u.bg.nNew, 0, SQLITE4_TRANSIENT,0);
    u.bg.pKey->enc = SQLITE4_UTF8;
    UPDATE_MAX_BLOBSIZE(u.bg.pKey);
  }

  break;
}

/* Opcode: Rowid P1 P2 * * *
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
**
** P1 can be either an ordinary table or a virtual table.  There used to
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
case OP_Rowid: {                 /* out2-prerelease */
#if 0  /* local variables moved into u.bh */
  VdbeCursor *pC;
  i64 v;
  const KVByteArray *aKey;
  KVSize nKey;
  int n;
  sqlite4_num vNum;
#endif /* local variables moved into u.bh */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bh.pC = p->apCsr[pOp->p1];
  rc = sqlite4VdbeCursorMoveto(u.bh.pC);
  if( rc!=SQLITE4_OK ) break;
  assert( u.bh.pC->sSeekKey.n==0 );
  if( u.bh.pC->nullRow ){
    pOut->flags = MEM_Null;
    break;
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  }else if( u.bh.pC->pVtabCursor ){
    pVtab = u.bh.pC->pVtabCursor->pVtab;
    pModule = pVtab->pModule;
    assert( pModule->xRowid );
    rc = pModule->xRowid(u.bh.pC->pVtabCursor, &u.bh.v);
    importVtabErrMsg(p, pVtab);
#endif /* SQLITE4_OMIT_VIRTUALTABLE */
  }else{
    rc = sqlite4KVCursorKey(u.bh.pC->pKVCur, &u.bh.aKey, &u.bh.nKey);
    if( rc==SQLITE4_OK ){
      u.bh.n = sqlite4GetVarint64(u.bh.aKey, u.bh.nKey, (sqlite4_uint64*)&u.bh.v);
      u.bh.n = sqlite4VdbeDecodeNumericKey(&u.bh.aKey[u.bh.n], u.bh.nKey-u.bh.n, &u.bh.vNum);
      if( u.bh.n==0 ) rc = SQLITE4_CORRUPT;
      u.bh.v = sqlite4_num_to_int64(u.bh.vNum,0);
    }
  }
  pOut->u.num = sqlite4_num_from_int64(u.bh.v);
  break;
}

/* Opcode: NullRow P1 * * * *
**
** Move the cursor P1 to a null row.  Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
*/
case OP_NullRow: {
#if 0  /* local variables moved into u.bi */
  VdbeCursor *pC;
#endif /* local variables moved into u.bi */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bi.pC = p->apCsr[pOp->p1];
  assert( u.bi.pC!=0 );
  u.bi.pC->nullRow = 1;
  u.bi.pC->rowChnged = 1;
  break;
}

/* Opcode: Last P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: {        /* jump */
#if 0  /* local variables moved into u.bj */
  VdbeCursor *pC;
#endif /* local variables moved into u.bj */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bj.pC = p->apCsr[pOp->p1];
  assert( u.bj.pC!=0 );
  rc = sqlite4VdbeSeekEnd(u.bj.pC, -1);
  if( rc==SQLITE4_NOTFOUND ){
    rc = SQLITE4_OK;
    if( pOp->p2 ) pc = pOp->p2 - 1;
  }else{
    u.bj.pC->nullRow = 0;
  }
  break;
}


/* Opcode: Sort P1 P2 * * *
**
** This opcode does exactly the same thing as OP_Rewind except that
** it increments an undocumented global variable used for testing.
**
** Sorting is accomplished by writing records into a sorting index,
** then rewinding that index and playing it back from beginning to
** end.  We use the OP_Sort opcode instead of OP_Rewind to do the
** rewinding so that the global variable will be incremented and
** regression tests can determine whether or not the optimizer is
** correctly optimizing out sorts.
*/
case OP_SorterSort:    /* jump */
  pOp->opcode = OP_Sort;
case OP_Sort: {        /* jump */
#ifdef SQLITE4_TEST
  sqlite4_sort_count++;
  sqlite4_search_count--;
#endif
  p->aCounter[SQLITE4_STMTSTATUS_SORT-1]++;
  /* Fall through into OP_Rewind */
}
/* Opcode: Rewind P1 P2 * * *
**
** The next use of the Rowid or Column or Next instruction for P1 
** will refer to the first entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Rewind: {        /* jump */
#if 0  /* local variables moved into u.bk */
  VdbeCursor *pC;
  int doJump;
#endif /* local variables moved into u.bk */

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  u.bk.pC = p->apCsr[pOp->p1];
  assert( u.bk.pC!=0 );
  u.bk.doJump = 1;
  rc = sqlite4VdbeSeekEnd(u.bk.pC, +1);
  if( rc==SQLITE4_NOTFOUND ){
    rc = SQLITE4_OK;
    u.bk.doJump = 1;
  }else{
    u.bk.doJump = 0;
  }
  u.bk.pC->nullRow = (u8)u.bk.doJump;
  assert( pOp->p2>0 && pOp->p2<p->nOp );
  if( u.bk.doJump ){
    pc = pOp->p2 - 1;
  }
  break;
}

/* 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
** to the following instruction.  But if the cursor advance was successful,
** jump immediately to P2.
**
** 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
** sqlite4VdbeNext().
**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
** See also: Prev
*/
/* Opcode: Prev P1 P2 * * P5
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index.  If there is no previous key/value pairs then fall through
** to the following instruction.  But if the cursor backup was successful,
** jump immediately to P2.
**
** 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
** sqlite4VdbePrevious().
**
** 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 */
  pOp->opcode = OP_Next;
case OP_Prev:          /* jump */
case OP_Next: {        /* jump */
#if 0  /* local variables moved into u.bl */
  VdbeCursor *pC;
#endif /* local variables moved into u.bl */

  CHECK_FOR_INTERRUPT;
  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( pOp->p5<=ArraySize(p->aCounter) );
  u.bl.pC = p->apCsr[pOp->p1];
  if( u.bl.pC==0 ){
    break;  /* See ticket #2273 */
  }
  assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite4VdbeNext );
  assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite4VdbePrevious );
  rc = pOp->p4.xAdvance(u.bl.pC);
  if( rc==SQLITE4_OK ){
    pc = pOp->p2 - 1;
    if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
    u.bl.pC->nullRow = 0;
#ifdef SQLITE4_TEST
    sqlite4_search_count++;
#endif
  }else if( rc==SQLITE4_NOTFOUND ){
    u.bl.pC->nullRow = 1;
    rc = SQLITE4_OK;
  }
  break;
}


/* Opcode: Insert P1 P2 P3 * P5
**
** Register P3 holds the key and register P2 holds the data for an
** index entry.  Write this record into the index specified by the
** cursor P1.
**
** P3 can be either an integer or a blob.  If it is a blob then its value
** is used as-is as the KVStore key.  If P3 is an integer, then the KVStore
** key is constructed using P3 as the INTEGER PRIMARY KEY value.
**
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
** incremented (otherwise not).
*/
case OP_Insert: {
#if 0  /* local variables moved into u.bm */
  VdbeCursor *pC;
  Mem *pKey;
  Mem *pData;
  int nKVKey;
  KVByteArray *pKVKey;
  KVByteArray aKey[24];
#endif /* local variables moved into u.bm */


  u.bm.pC = p->apCsr[pOp->p1];
  u.bm.pKey = &aMem[pOp->p3];
  u.bm.pData = pOp->p2 ? &aMem[pOp->p2] : 0;

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( u.bm.pC && u.bm.pC->pKVCur && u.bm.pC->pKVCur->pStore );
  assert( u.bm.pData==0 || (u.bm.pData->flags & MEM_Blob) );

  if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;

  if( u.bm.pKey->flags & MEM_Int ){
    u.bm.nKVKey = sqlite4PutVarint64(u.bm.aKey, u.bm.pC->iRoot);
    u.bm.nKVKey += sqlite4VdbeEncodeIntKey(u.bm.aKey+u.bm.nKVKey, sqlite4VdbeIntValue(u.bm.pKey));
    u.bm.pKVKey = u.bm.aKey;
  }else{
    u.bm.nKVKey = u.bm.pKey->n;
    u.bm.pKVKey = u.bm.pKey->z;
  }


  rc = sqlite4KVStoreReplace(
     u.bm.pC->pKVCur->pStore,
     (u8 *)u.bm.pKVKey, u.bm.nKVKey,
     (u8 *)(u.bm.pData ? u.bm.pData->z : 0), (u.bm.pData ? u.bm.pData->n : 0)
  );
  u.bm.pC->rowChnged = 1;

  break;
}

/* Opcode: IdxDelete P1 * P3 * *
**
** P1 is a cursor open on a database index. P3 contains a key suitable for
** the index. Delete P3 from P1 if it is present.
*/
case OP_IdxDelete: {
#if 0  /* local variables moved into u.bn */
  VdbeCursor *pC;
  Mem *pKey;
#endif /* local variables moved into u.bn */

  u.bn.pC = p->apCsr[pOp->p1];
  u.bn.pKey = &aMem[pOp->p3];

  assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  assert( u.bn.pC && u.bn.pC->pKVCur && u.bn.pC->pKVCur->pStore );
  assert( u.bn.pKey->flags & MEM_Blob );

  rc = sqlite4KVCursorSeek(u.bn.pC->pKVCur, (u8 *)u.bn.pKey->z, u.bn.pKey->n, 0);
  if( rc==SQLITE4_OK ){
    rc = sqlite4KVCursorDelete(u.bn.pC->pKVCur);
  }else if( rc==SQLITE4_NOTFOUND ){
    rc = SQLITE4_OK;
  }
  u.bn.pC->rowChnged = 1;

  break;
}

/* Opcode: IdxRowkey P1 P2 P3 * *
**
** Cursor P1 points to an index entry. Extract the encoded primary key 
** fields from the entry. Then set output register P2 to a blob value
** containing the value P3 as a varint followed by the encoded PK
** fields.
**
** See also: Rowkey
*/
case OP_IdxRowkey: {              /* out2-prerelease */
  KVByteArray const *aKey;        /* Key data from cursor pIdx */
  KVSize nKey;                    /* Size of aKey[] in bytes */
  int nShort;                     /* Size of aKey[] without PK fields */
  KVByteArray *aPkKey;            /* Pointer to PK buffer */
  KVSize nPkKey;                  /* Size of aPkKey in bytes */
  int iRoot;
  VdbeCursor *pC;

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

  pC = p->apCsr[pOp->p1];

  rc = sqlite4KVCursorKey(pC->pKVCur, &aKey, &nKey);
  if( rc!=SQLITE4_OK ) break;

  nShort = sqlite4VdbeShortKey(aKey, nKey, 
      pC->pKeyInfo->nField - pC->pKeyInfo->nPK, 0
  );

  nPkKey = sqlite4VarintLen(iRoot) + nKey - nShort;
  if( nPkKey>db->aLimit[SQLITE4_LIMIT_LENGTH] ){
    goto too_big;
  }

  rc = sqlite4VdbeMemGrow(pOut, nPkKey, 0);
  if( rc!=SQLITE4_OK ) break;
  aPkKey = pOut->z;
  putVarint32(aPkKey, iRoot);
  memcpy(&aPkKey[nPkKey - (nKey-nShort)], &aKey[nShort], nKey-nShort);
  pOut->type = SQLITE4_BLOB;
  pOut->n = nPkKey;
  MemSetTypeFlag(pOut, MEM_Blob);

  pOut->enc = SQLITE4_UTF8;  /* In case the blob is ever cast to text */
  UPDATE_MAX_BLOBSIZE(pOut);
  break;
}

/* Opcode: IdxGE P1 P2 P3
**
** P1 is an open cursor. P3 contains a database key formatted by MakeKey.
** This opcode compares the current key that index P1 points to with
** the key in register P3.
**
** If the index key is greater than or equal to the key in register P3, 
** then jump to instruction P2. Otherwise, fall through to the next VM
** instruction. The comparison is done using memcmp(), except that if P3
** is a prefix of the P1 key they are considered equal.
*/
case OP_IdxLT:          /* jump */
case OP_IdxLE:          /* jump */
case OP_IdxGE:          /* jump */
case OP_IdxGT: {        /* jump */
#if 0  /* local variables moved into u.bo */
  VdbeCursor *pC;                 /* Cursor P1 */
#endif /* local variables moved into u.bo */
  KVByteArray const *aKey;        /* Key from cursor P1 */
  KVSize nKey;                    /* Size of aKey[] in bytes */
  Mem *pCmp;                      /* Memory cell to compare index key with */
  int nCmp;                       /* Bytes of data to compare using memcmp() */
  int res;                        /* Result of memcmp() call */
  int bJump;                      /* True to take the jump */

  pCmp = &aMem[pOp->p3];
  assert( pCmp->flags & MEM_Blob );
  u.bo.pC = p->apCsr[pOp->p1];
  rc = sqlite4KVCursorKey(u.bo.pC->pKVCur, &aKey, &nKey);

  if( rc==SQLITE4_OK ){
    nCmp = pCmp->n;
    if( nCmp>nKey ) nCmp = nKey;

    res = memcmp(aKey, pCmp->z, nCmp);
    switch( pOp->opcode ){
      case OP_IdxLT: bJump = (res <  0); break;
      case OP_IdxLE: bJump = (res <= 0); break;
      case OP_IdxGE: bJump = (res >= 0); break;
      case OP_IdxGT: bJump = (res >  0); break;
    }

    if( bJump ) pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: Clear P1 P2 * * P5
**
** Delete all contents of the database table or index whose table number
** in the database file is given by P1.  
**
** The table being clear is in the main database file if P2==0.  If
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** If the OPFLAG_NCHANGE flag of P5 is set, then the row change count is
** incremented (otherwise not).
**
** See also: Destroy
*/
case OP_Clear: {
#if 0  /* local variables moved into u.bp */
  KVCursor *pCur;
#endif /* local variables moved into u.bp */
  KVByteArray const *aKey;
  KVSize nKey;
  KVSize nProbe;
  KVByteArray aProbe[12];

  nProbe = sqlite4PutVarint64(aProbe, pOp->p1);
  rc = sqlite4KVStoreOpenCursor(db->aDb[pOp->p2].pKV, &u.bp.pCur);
  if( rc ) break;
  rc = sqlite4KVCursorSeek(u.bp.pCur, aProbe, nProbe, +1);
  while( rc!=SQLITE4_NOTFOUND ){
    if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
    rc = sqlite4KVCursorKey(u.bp.pCur, &aKey, &nKey);
    if( rc!=SQLITE4_OK ) break;
    if( nKey<nProbe ){ rc = SQLITE4_CORRUPT; break; }
    if( memcmp(aKey, aProbe, nProbe)!=0 ) break;
    rc = sqlite4KVCursorDelete(u.bp.pCur);
    if( rc ) break;
    rc = sqlite4KVCursorNext(u.bp.pCur);
  }
  sqlite4KVCursorClose(u.bp.pCur);
  if( rc==SQLITE4_NOTFOUND) rc = SQLITE4_OK;
  break;
}


/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE4_MASTER table of database P1
** that match the WHERE clause P4. 
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
#if 0  /* local variables moved into u.bq */
  int iDb;
  const char *zMaster;
  char *zSql;
  InitData initData;
#endif /* local variables moved into u.bq */

  u.bq.iDb = pOp->p1;
  assert( u.bq.iDb>=0 && u.bq.iDb<db->nDb );
  assert( DbHasProperty(db, u.bq.iDb, DB_SchemaLoaded) );
  /* Used to be a conditional */ {
    u.bq.zMaster = SCHEMA_TABLE(u.bq.iDb);
    u.bq.initData.db = db;
    u.bq.initData.iDb = pOp->p1;
    u.bq.initData.pzErrMsg = &p->zErrMsg;
    u.bq.zSql = sqlite4MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[u.bq.iDb].zName, u.bq.zMaster, pOp->p4.z);
    if( u.bq.zSql==0 ){
      rc = SQLITE4_NOMEM;
    }else{
      assert( db->init.busy==0 );
      db->init.busy = 1;
      u.bq.initData.rc = SQLITE4_OK;
      assert( !db->mallocFailed );
      rc = sqlite4_exec(db, u.bq.zSql, sqlite4InitCallback, &u.bq.initData);
      if( rc==SQLITE4_OK ) rc = u.bq.initData.rc;
      sqlite4DbFree(db, u.bq.zSql);
      db->init.busy = 0;
    }
  }
  if( rc==SQLITE4_NOMEM ){
    goto no_mem;
  }
  break;
}

#if !defined(SQLITE4_OMIT_ANALYZE)
/* Opcode: LoadAnalysis P1 * * * *
**
** Read the sqlite_stat1 table for database P1 and load the content
** of that table into the internal index hash table.  This will cause
** the analysis to be used when preparing all subsequent queries.
*/
case OP_LoadAnalysis: {
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
  rc = sqlite4AnalysisLoad(db, pOp->p1);
  break;  
}
#endif /* !defined(SQLITE4_OMIT_ANALYZE) */

/* Opcode: DropTable P1 * * P4 *
**
** Remove the internal (in-memory) data structures that describe
** the table named P4 in database P1.  This is called after a table
** is dropped in order to keep the internal representation of the
** schema consistent with what is on disk.
*/
case OP_DropTable: {
  sqlite4UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
  break;
}

/* Opcode: DropIndex P1 * * P4 *
**
** Remove the internal (in-memory) data structures that describe
** the index named P4 in database P1.  This is called after an index
** is dropped in order to keep the internal representation of the
** schema consistent with what is on disk.
*/
case OP_DropIndex: {
  sqlite4UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
  break;
}

/* Opcode: DropTrigger P1 * * P4 *
**
** Remove the internal (in-memory) data structures that describe
** the trigger named P4 in database P1.  This is called after a trigger
** is dropped in order to keep the internal representation of the
** schema consistent with what is on disk.
*/
case OP_DropTrigger: {
  sqlite4UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
  break;
}

/* Opcode: RowSetTest P1 P2 P3 * *
**
** Register P1 contains a RowSet object. Register P3 contains a database 
** key. This function checks if the RowSet already contains an equal key.
** If so, control jumps to instruction P2. Otherwise, fall through to the
** next instruction.
**
** TODO: Optimization similar to SQLite 3 using P4.
*/
case OP_RowSetTest: {        /* in1, in3, jump */
#if 0  /* local variables moved into u.br */
  int iSet;
#endif /* local variables moved into u.br */
  pIn1 = &aMem[pOp->p1];
  pIn3 = &aMem[pOp->p3];
  u.br.iSet = pOp->p4.i;

  if( 0!=(pIn1->flags & MEM_RowSet)
   && 0!=sqlite4RowSetTest(pIn1->u.pRowSet, u.br.iSet, (u8 *)pIn3->z, pIn3->n)
  ){
    pc = pOp->p2-1;
    break;
  }

  /* Fall through to RowSetAdd */
}

/* Opcode: RowSetAdd P1 P2 * * *
**
** Read the blob value from register P2 and store it in RowSet object P1.
*/
case OP_RowSetAdd: {         /* in1, in3 */
  pIn1 = &aMem[pOp->p1];
  if( (pIn1->flags & MEM_RowSet)==0 ){
    sqlite4VdbeMemSetRowSet(pIn1);
    if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
  }
  pIn3 = &aMem[pOp->p3];
  assert( pIn3->flags & MEM_Blob );
  sqlite4RowSetInsert(pIn1->u.pRowSet, (u8 *)pIn3->z, pIn3->n);
  break;
}

/* Opcode: RowSetRead P1 P2 P3 * *
**
** Remove a value from MemSet object P1 and store it in register P3.
** Or, if MemSet P1 is already empty, leave P3 unchanged and jump to 
** instruction P2.
*/
case OP_RowSetRead: {       /* in1 */
#if 0  /* local variables moved into u.bs */
  const u8 *aKey;
  int nKey;
#endif /* local variables moved into u.bs */

  CHECK_FOR_INTERRUPT;
  pIn1 = &aMem[pOp->p1];
  pOut = &aMem[pOp->p3];
  if( (pIn1->flags & MEM_RowSet)
   && (u.bs.aKey = sqlite4RowSetRead(pIn1->u.pRowSet, &u.bs.nKey))
  ){
    rc = sqlite4VdbeMemSetStr(pOut, (char const *)u.bs.aKey, u.bs.nKey, 0,
                              SQLITE4_TRANSIENT, 0);
    sqlite4RowSetNext(pIn1->u.pRowSet);
  }else{
    /* The RowSet is empty */
    sqlite4VdbeMemSetNull(pIn1);
    pc = pOp->p2 - 1;
  }

  break;
}

#ifndef SQLITE4_OMIT_TRIGGER

/* Opcode: Program P1 P2 P3 P4 *
**
** Execute the trigger program passed as P4 (type P4_SUBPROGRAM). 
**
** P1 contains the address of the memory cell that contains the first memory 
** cell in an array of values used as arguments to the sub-program. P2 
** contains the address to jump to if the sub-program throws an IGNORE 
** exception using the RAISE() function. Register P3 contains the address 
** of a memory cell in this (the parent) VM that is used to allocate the 
** memory required by the sub-vdbe at runtime.
**
** P4 is a pointer to the VM containing the trigger program.
*/
case OP_Program: {        /* jump */
#if 0  /* local variables moved into u.bt */
  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 */
  Mem *pMem;              /* Used to iterate through memory cells */
  Mem *pEnd;              /* Last memory cell in new array */
  VdbeFrame *pFrame;      /* New vdbe frame to execute in */
  SubProgram *pProgram;   /* Sub-program to execute */
#endif /* local variables moved into u.bt */

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

  if( p->nFrame>=db->aLimit[SQLITE4_LIMIT_TRIGGER_DEPTH] ){
    rc = SQLITE4_ERROR;
    sqlite4SetString(&p->zErrMsg, db, "too many levels of trigger recursion");
    break;
  }

  /* Register u.bt.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.bt.pRt
  ** is already allocated. Otherwise, it must be initialized.  */
  if( (u.bt.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.bt.nMem (and later, VdbeFrame.nChildMem) to this value.
    */
    u.bt.nMem = u.bt.pProgram->nMem + u.bt.pProgram->nCsr;
    u.bt.nByte = ROUND8(sizeof(VdbeFrame))
              + u.bt.nMem * sizeof(Mem)
              + u.bt.pProgram->nCsr * sizeof(VdbeCursor *)
              + u.bt.pProgram->nOnce * sizeof(u8);
    u.bt.pFrame = sqlite4DbMallocZero(db, u.bt.nByte);
    if( !u.bt.pFrame ){
      goto no_mem;
    }
    sqlite4VdbeMemRelease(u.bt.pRt);
    u.bt.pRt->flags = MEM_Frame;
    u.bt.pRt->u.pFrame = u.bt.pFrame;

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

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

  p->nFrame++;
  u.bt.pFrame->pParent = p->pFrame;
  u.bt.pFrame->nChange = p->nChange;
  p->nChange = 0;
  p->pFrame = u.bt.pFrame;
  p->aMem = aMem = &VdbeFrameMem(u.bt.pFrame)[-1];
  p->nMem = u.bt.pFrame->nChildMem;
  p->nCursor = (u16)u.bt.pFrame->nChildCsr;
  p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
  p->aOp = aOp = u.bt.pProgram->aOp;
  p->nOp = u.bt.pProgram->nOp;
  p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
  p->nOnceFlag = u.bt.pProgram->nOnce;
  pc = -1;
  memset(p->aOnceFlag, 0, p->nOnceFlag);

  break;
}

/* Opcode: Param P1 P2 * * *
**
** This opcode is only ever present in sub-programs called via the 
** OP_Program instruction. Copy a value currently stored in a memory 
** cell of the calling (parent) frame to cell P2 in the current frames 
** address space. This is used by trigger programs to access the new.* 
** and old.* values.
**
** The address of the cell in the parent frame is determined by adding
** the value of the P1 argument to the value of the P1 argument to the
** calling OP_Program instruction.
*/
case OP_Param: {           /* out2-prerelease */
#if 0  /* local variables moved into u.bu */
  VdbeFrame *pFrame;
  Mem *pIn;
#endif /* local variables moved into u.bu */
  u.bu.pFrame = p->pFrame;
  u.bu.pIn = &u.bu.pFrame->aMem[pOp->p1 + u.bu.pFrame->aOp[u.bu.pFrame->pc].p1];
  assert( memIsValid(u.bu.pIn) );
  sqlite4VdbeMemShallowCopy(pOut, u.bu.pIn, MEM_Ephem);
  break;
}

#endif /* #ifndef SQLITE4_OMIT_TRIGGER */

#ifndef SQLITE4_OMIT_FOREIGN_KEY
/* Opcode: FkCounter P1 P2 * * *
**
** Increment a "constraint counter" by P2 (P2 may be negative or positive).
** If P1 is non-zero, the database constraint counter is incremented 
** (deferred foreign key constraints). Otherwise, if P1 is zero, the 
** statement counter is incremented (immediate foreign key constraints).
*/
case OP_FkCounter: {
  if( pOp->p1 ){
    db->nDeferredCons += pOp->p2;
  }else{
    p->nFkConstraint += pOp->p2;
  }
  break;
}

/* Opcode: FkIfZero P1 P2 * * *
**
** This opcode tests if a foreign key constraint-counter is currently zero.
** If so, jump to instruction P2. Otherwise, fall through to the next 
** instruction.
**
** If P1 is non-zero, then the jump is taken if the database constraint-counter
** is zero (the one that counts deferred constraint violations). If P1 is
** zero, the jump is taken if the statement constraint-counter is zero
** (immediate foreign key constraint violations).
*/
case OP_FkIfZero: {         /* jump */
  if( pOp->p1 ){
    if( db->nDeferredCons==0 ) pc = pOp->p2-1;
  }else{
    if( p->nFkConstraint==0 ) pc = pOp->p2-1;
  }
  break;
}
#endif /* #ifndef SQLITE4_OMIT_FOREIGN_KEY */

#ifndef SQLITE4_OMIT_AUTOINCREMENT
/* Opcode: MemMax P1 P2 * * *
**
** P1 is a register in the root frame of this VM (the root frame is
** different from the current frame if this instruction is being executed
** within a sub-program). Set the value of register P1 to the maximum of 
** its current value and the value in register P2.
**
** This instruction throws an error if the memory cell is not initially
** an integer.
*/
case OP_MemMax: {        /* in2 */
#if 0  /* local variables moved into u.bv */
  i64 i1;
  i64 i2;
  Mem *pIn1;
#endif /* local variables moved into u.bv */
  u.bv.pIn1 = sqlite4RegisterInRootFrame(p, pOp->p1);
  assert( memIsValid(u.bv.pIn1) );
  sqlite4VdbeMemIntegerify(u.bv.pIn1);
  pIn2 = &aMem[pOp->p2];
  REGISTER_TRACE(pOp->p1, u.bv.pIn1);
  sqlite4VdbeMemIntegerify(pIn2);
  u.bv.i1 = sqlite4_num_to_int64(u.bv.pIn1->u.num, 0);
  u.bv.i2 = sqlite4_num_to_int64(pIn2->u.num, 0);
  if( u.bv.i1<u.bv.i2 ){
    u.bv.pIn1->u.num = sqlite4_num_from_int64(u.bv.i2);
  }
  REGISTER_TRACE(pOp->p1, u.bv.pIn1);
  break;
}
#endif /* SQLITE4_OMIT_AUTOINCREMENT */

/* Opcode: IfPos P1 P2 * * *
**
** If the value of register P1 is 1 or greater, jump to P2.
**
** It is illegal to use this instruction on a register that does
** not contain an integer.  An assertion fault will result if you try.
*/
case OP_IfPos: {        /* jump, in1 */
#if 0  /* local variables moved into u.bw */
  i64 i1;
#endif /* local variables moved into u.bw */
  pIn1 = &aMem[pOp->p1];
  assert( pIn1->flags&MEM_Int );
  u.bw.i1 = sqlite4_num_to_int64(pIn1->u.num, 0);
  if( u.bw.i1>0 ){
     pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: IfNeg P1 P2 * * *
**
** If the value of register P1 is less than zero, jump to P2. 
**
** It is illegal to use this instruction on a register that does
** not contain an integer.  An assertion fault will result if you try.
*/
case OP_IfNeg: {        /* jump, in1 */
#if 0  /* local variables moved into u.bx */
  i64 i1;
#endif /* local variables moved into u.bx */
  pIn1 = &aMem[pOp->p1];
  assert( pIn1->flags&MEM_Int );
  u.bx.i1 = sqlite4_num_to_int64(pIn1->u.num, 0);
  if( u.bx.i1<0 ){
     pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: IfZero P1 P2 P3 * *
**
** The register P1 must contain an integer.  Add literal P3 to the
** value in register P1.  If the result is exactly 0, jump to P2. 
**
** It is illegal to use this instruction on a register that does
** not contain an integer.  An assertion fault will result if you try.
*/
case OP_IfZero: {        /* jump, in1 */
#if 0  /* local variables moved into u.by */
  i64 i1;
#endif /* local variables moved into u.by */
  pIn1 = &aMem[pOp->p1];
  assert( pIn1->flags&MEM_Int );
  u.by.i1 = sqlite4_num_to_int64(pIn1->u.num, 0);
  u.by.i1 += pOp->p3;
  pIn1->u.num = sqlite4_num_from_int64(u.by.i1);
  if( u.by.i1==0 ){
     pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: AggStep * P2 P3 P4 P5
**
** Execute the step function for an aggregate.  The
** function has P5 arguments.   P4 is a pointer to the FuncDef
** structure that specifies the function.  Use register
** P3 as the accumulator.
**
** The P5 arguments are taken from register P2 and its
** successors.
*/
case OP_AggStep: {
#if 0  /* local variables moved into u.bz */
  int n;
  int i;
  Mem *pMem;
  Mem *pRec;
  sqlite4_context ctx;
  sqlite4_value **apVal;
#endif /* local variables moved into u.bz */

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

  sqlite4VdbeMemRelease(&u.bz.ctx.s);

  break;
}

/* Opcode: AggFinal P1 P2 * P4 *
**
** Execute the finalizer function for an aggregate.  P1 is
** the memory location that is the accumulator for the aggregate.
**
** P2 is the number of arguments that the step function takes and
** P4 is a pointer to the FuncDef for this function.  The P2
** argument is not used by this opcode.  It is only there to disambiguate
** functions that can take varying numbers of arguments.  The
** P4 argument is only needed for the degenerate case where
** the step function was not previously called.
*/
case OP_AggFinal: {
#if 0  /* local variables moved into u.ca */
  Mem *pMem;
#endif /* local variables moved into u.ca */
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  u.ca.pMem = &aMem[pOp->p1];
  assert( (u.ca.pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
  rc = sqlite4VdbeMemFinalize(u.ca.pMem, pOp->p4.pFunc);
  if( rc ){
    sqlite4SetString(&p->zErrMsg, db, "%s",
        (const char *)sqlite4ValueText(u.ca.pMem, SQLITE4_UTF8)
    );
  }
  sqlite4VdbeChangeEncoding(u.ca.pMem, encoding);
  UPDATE_MAX_BLOBSIZE(u.ca.pMem);
  if( sqlite4VdbeMemTooBig(u.ca.pMem) ){
    goto too_big;
  }
  break;
}

#ifndef SQLITE4_OMIT_PRAGMA
/* Opcode: JournalMode P1 P2 P3 * P5
**
** Change the journal mode of database P1 to P3. P3 must be one of the
** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
** modes (delete, truncate, persist, off and memory), this is a simple
** operation. No IO is required.
**
** If changing into or out of WAL mode the procedure is more complicated.
**
** Write a string containing the final journal-mode to register P2.
*/
case OP_JournalMode: {    /* out2-prerelease */
  break;
};
#endif /* SQLITE4_OMIT_PRAGMA */


/* Opcode: Expire P1 * * * *
**
** Cause precompiled statements to become expired. An expired statement
** fails with an error code of SQLITE4_SCHEMA if it is ever executed 
** (via sqlite4_step()).
** 
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
** then only the currently executing statement is affected. 
*/
case OP_Expire: {
  if( !pOp->p1 ){
    sqlite4ExpirePreparedStatements(db);
  }else{
    p->expired = 1;
  }
  break;
}


#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VBegin * * * P4 *
**
** P4 may be a pointer to an sqlite4_vtab structure. If so, call the 
** xBegin method for that table.
**
** Also, whether or not P4 is set, check that this is not being called from
** within a callback to a virtual table xSync() method. If it is, the error
** code will be set to SQLITE4_LOCKED.
*/
case OP_VBegin: {
#if 0  /* local variables moved into u.cb */
  VTable *pVTab;
#endif /* local variables moved into u.cb */
  u.cb.pVTab = pOp->p4.pVtab;
  rc = sqlite4VtabBegin(db, u.cb.pVTab);
  if( u.cb.pVTab ) importVtabErrMsg(p, u.cb.pVTab->pVtab);
  break;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VCreate P1 * * P4 *
**
** P4 is the name of a virtual table in database P1. Call the xCreate method
** for that table.
*/
case OP_VCreate: {
  rc = sqlite4VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg);
  break;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VDestroy P1 * * P4 *
**
** P4 is the name of a virtual table in database P1.  Call the xDestroy method
** of that table.
*/
case OP_VDestroy: {
  p->inVtabMethod = 2;
  rc = sqlite4VtabCallDestroy(db, pOp->p1, pOp->p4.z);
  p->inVtabMethod = 0;
  break;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VOpen P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite4_vtab structure.
** P1 is a cursor number.  This opcode opens a cursor to the virtual
** table and stores that cursor in P1.
*/
case OP_VOpen: {
#if 0  /* local variables moved into u.cc */
  VdbeCursor *pCur;
  sqlite4_vtab_cursor *pVtabCursor;
  sqlite4_vtab *pVtab;
  sqlite4_module *pModule;
#endif /* local variables moved into u.cc */

  u.cc.pCur = 0;
  u.cc.pVtabCursor = 0;
  u.cc.pVtab = pOp->p4.pVtab->pVtab;
  u.cc.pModule = (sqlite4_module *)u.cc.pVtab->pModule;
  assert(u.cc.pVtab && u.cc.pModule);
  rc = u.cc.pModule->xOpen(u.cc.pVtab, &u.cc.pVtabCursor);
  importVtabErrMsg(p, u.cc.pVtab);
  if( SQLITE4_OK==rc ){
    /* Initialize sqlite4_vtab_cursor base class */
    u.cc.pVtabCursor->pVtab = u.cc.pVtab;

    /* Initialise vdbe cursor object */
    u.cc.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
    if( u.cc.pCur ){
      u.cc.pCur->pVtabCursor = u.cc.pVtabCursor;
      u.cc.pCur->pModule = u.cc.pVtabCursor->pVtab->pModule;
    }else{
      db->mallocFailed = 1;
      u.cc.pModule->xClose(u.cc.pVtabCursor);
    }
  }
  break;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
**
** P1 is a cursor opened using VOpen.  P2 is an address to jump to if
** the filtered result set is empty.
**
** P4 is either NULL or a string that was generated by the xBestIndex
** method of the module.  The interpretation of the P4 string is left
** to the module implementation.
**
** This opcode invokes the xFilter method on the virtual table specified
** by P1.  The integer query plan parameter to xFilter is stored in register
** P3. Register P3+1 stores the argc parameter to be passed to the
** xFilter method. Registers P3+2..P3+1+argc are the argc
** additional parameters which are passed to
** xFilter as argv. Register P3+2 becomes argv[0] when passed to xFilter.
**
** 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.cd */
  int nArg;
  int iQuery;
  const sqlite4_module *pModule;
  Mem *pQuery;
  Mem *pArgc;
  sqlite4_vtab_cursor *pVtabCursor;
  sqlite4_vtab *pVtab;
  VdbeCursor *pCur;
  int res;
  int i;
  Mem **apArg;
#endif /* local variables moved into u.cd */

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

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

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

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

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

  break;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VColumn P1 P2 P3 * *
**
** Store the value of the P2-th column of
** the row of the virtual-table that the 
** P1 cursor is pointing to into register P3.
*/
case OP_VColumn: {
#if 0  /* local variables moved into u.ce */
  sqlite4_vtab *pVtab;
  const sqlite4_module *pModule;
  Mem *pDest;
  sqlite4_context sContext;
#endif /* local variables moved into u.ce */

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

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

  rc = u.ce.pModule->xColumn(pCur->pVtabCursor, &u.ce.sContext, pOp->p2);
  importVtabErrMsg(p, u.ce.pVtab);
  if( u.ce.sContext.isError ){
    rc = u.ce.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.ce.sContext.s (a Mem struct) is  released.
  */
  sqlite4VdbeChangeEncoding(&u.ce.sContext.s, encoding);
  sqlite4VdbeMemMove(u.ce.pDest, &u.ce.sContext.s);
  REGISTER_TRACE(pOp->p3, u.ce.pDest);
  UPDATE_MAX_BLOBSIZE(u.ce.pDest);

  if( sqlite4VdbeMemTooBig(u.ce.pDest) ){
    goto too_big;
  }
  break;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VNext P1 P2 * * *
**
** Advance virtual table P1 to the next row in its result set and
** jump to instruction P2.  Or, if the virtual table has reached
** the end of its result set, then fall through to the next instruction.
*/
case OP_VNext: {   /* jump */
#if 0  /* local variables moved into u.cf */
  sqlite4_vtab *pVtab;
  const sqlite4_module *pModule;
  int res;
  VdbeCursor *pCur;
#endif /* local variables moved into u.cf */

  u.cf.res = 0;
  u.cf.pCur = p->apCsr[pOp->p1];
  assert( u.cf.pCur->pVtabCursor );
  if( u.cf.pCur->nullRow ){
    break;
  }
  u.cf.pVtab = u.cf.pCur->pVtabCursor->pVtab;
  u.cf.pModule = u.cf.pVtab->pModule;
  assert( u.cf.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
  ** xNext(). Instead, if an error occurs, true is returned (indicating that
  ** data is available) and the error code returned when xColumn or
  ** some other method is next invoked on the save virtual table cursor.
  */
  p->inVtabMethod = 1;
  rc = u.cf.pModule->xNext(u.cf.pCur->pVtabCursor);
  p->inVtabMethod = 0;
  importVtabErrMsg(p, u.cf.pVtab);
  if( rc==SQLITE4_OK ){
    u.cf.res = u.cf.pModule->xEof(u.cf.pCur->pVtabCursor);
  }

  if( !u.cf.res ){
    /* If there is data, jump to P2 */
    pc = pOp->p2 - 1;
  }
  break;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VRename P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite4_vtab structure.
** This opcode invokes the corresponding xRename method. The value
** in register P1 is passed as the zName argument to the xRename method.
*/
case OP_VRename: {
#if 0  /* local variables moved into u.cg */
  sqlite4_vtab *pVtab;
  Mem *pName;
#endif /* local variables moved into u.cg */

  u.cg.pVtab = pOp->p4.pVtab->pVtab;
  u.cg.pName = &aMem[pOp->p1];
  assert( u.cg.pVtab->pModule->xRename );
  assert( memIsValid(u.cg.pName) );
  REGISTER_TRACE(pOp->p1, u.cg.pName);
  assert( u.cg.pName->flags & MEM_Str );
  testcase( u.cg.pName->enc==SQLITE4_UTF8 );
  testcase( u.cg.pName->enc==SQLITE4_UTF16BE );
  testcase( u.cg.pName->enc==SQLITE4_UTF16LE );
  rc = sqlite4VdbeChangeEncoding(u.cg.pName, SQLITE4_UTF8);
  if( rc==SQLITE4_OK ){
    rc = u.cg.pVtab->pModule->xRename(u.cg.pVtab, u.cg.pName->z);
    importVtabErrMsg(p, u.cg.pVtab);
    p->expired = 0;
  }
  break;
}
#endif

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Opcode: VUpdate P1 P2 P3 P4 *
**
** P4 is a pointer to a virtual table object, an sqlite4_vtab structure.
** This opcode invokes the corresponding xUpdate method. P2 values
** are contiguous memory cells starting at P3 to pass to the xUpdate 
** invocation. The value in register (P3+P2-1) corresponds to the 
** p2th element of the argv array passed to xUpdate.
**
** The xUpdate method will do a DELETE or an INSERT or both.
** The argv[0] element (which corresponds to memory cell P3)
** is the rowid of a row to delete.  If argv[0] is NULL then no 
** deletion occurs.  The argv[1] element is the rowid of the new 
** row.  This can be NULL to have the virtual table select the new 
** rowid for itself.  The subsequent elements in the array are 
** the values of columns in the new row.
**
** If P2==1 then no insert is performed.  argv[0] is the rowid of
** a row to delete.
**
** P1 is a boolean flag. If it is set to true and the xUpdate call
** is successful, then the value returned by sqlite4_last_insert_rowid() 
** is set to the value of the rowid for the row just inserted.
*/
case OP_VUpdate: {
#if 0  /* local variables moved into u.ch */
  sqlite4_vtab *pVtab;
  sqlite4_module *pModule;
  int nArg;
  int i;
  sqlite4_int64 rowid;
  Mem **apArg;
  Mem *pX;
#endif /* local variables moved into u.ch */

  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.ch.pVtab = pOp->p4.pVtab->pVtab;
  u.ch.pModule = (sqlite4_module *)u.ch.pVtab->pModule;
  u.ch.nArg = pOp->p2;
  assert( pOp->p4type==P4_VTAB );
  if( ALWAYS(u.ch.pModule->xUpdate) ){
    u8 vtabOnConflict = db->vtabOnConflict;
    u.ch.apArg = p->apArg;
    u.ch.pX = &aMem[pOp->p3];
    for(u.ch.i=0; u.ch.i<u.ch.nArg; u.ch.i++){
      assert( memIsValid(u.ch.pX) );
      memAboutToChange(p, u.ch.pX);
      sqlite4VdbeMemStoreType(u.ch.pX);
      u.ch.apArg[u.ch.i] = u.ch.pX;
      u.ch.pX++;
    }
    db->vtabOnConflict = pOp->p5;
    rc = u.ch.pModule->xUpdate(u.ch.pVtab, u.ch.nArg, u.ch.apArg, &u.ch.rowid);
    db->vtabOnConflict = vtabOnConflict;
    importVtabErrMsg(p, u.ch.pVtab);
    if( rc==SQLITE4_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
      if( pOp->p5==OE_Ignore ){
        rc = SQLITE4_OK;
      }else{
        p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5);
      }
    }else{
      p->nChange++;
    }
  }
  break;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifndef SQLITE4_OMIT_TRACE
/* Opcode: Trace * * * P4 *
**
** If tracing is enabled (by the sqlite4_trace()) interface, then
** the UTF-8 string contained in P4 is emitted on the trace callback.
*/
case OP_Trace: {
#if 0  /* local variables moved into u.ci */
  char *zTrace;
  char *z;
#endif /* local variables moved into u.ci */

  if( db->xTrace && (u.ci.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0 ){
    u.ci.z = sqlite4VdbeExpandSql(p, u.ci.zTrace);
    db->xTrace(db->pTraceArg, u.ci.z);
    sqlite4DbFree(db, u.ci.z);
  }
#ifdef SQLITE4_DEBUG
  if( (db->flags & SQLITE4_SqlTrace)!=0
   && (u.ci.zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
  ){
    sqlite4DebugPrintf("SQL-trace: %s\n", u.ci.zTrace);
  }
#endif /* SQLITE4_DEBUG */
  break;
}
#endif

/* Opcode: FtsUpdate P1 P2 P3 P4 P5
**
** This opcode is used to write to an FTS index. P4 points to an Fts5Info 
** object describing the index.
**
** If argument P5 is non-zero, then entries are removed from the FTS index.
** If it is zero, then entries are inserted. In other words, when a row
** is deleted from a table with an FTS index, this opcode is invoked with
** P5==1. When a row is inserted, it is invoked with P5==0. If an existing
** row is updated, this opcode is invoked twice - once with P5==1 and then
** again with P5==0.
**
** Register P1 contains the PK (a blob in key format) of the affected row.
** P3 is the first in an array of N registers, where N is the number of
** columns in the indexed table. Each register contains the value for the
** corresponding table column.
**
** If P2 is non-zero, then it is a register containing the root page number
** of the fts index to update. If it is zero, then the root page of the 
** index is available as part of the Fts5Info structure.
*/
case OP_FtsUpdate: {
#if 0  /* local variables moved into u.cj */
  Fts5Info *pInfo;                /* Description of fts5 index to update */
  Mem *pKey;                      /* Primary key of indexed row */
  Mem *aArg;                      /* Pointer to array of N arguments */
  int iRoot;                      /* Root page number (or 0) */
#endif /* local variables moved into u.cj */

  assert( pOp->p4type==P4_FTS5INFO );
  u.cj.pInfo = pOp->p4.pFtsInfo;
  u.cj.aArg = &aMem[pOp->p3];
  u.cj.pKey = &aMem[pOp->p1];

  if( pOp->p2 ){
    u.cj.iRoot = sqlite4_num_to_int32(aMem[pOp->p2].u.num, 0);
  }else{
    u.cj.iRoot = 0;
  }

  rc = sqlite4Fts5Update(db, u.cj.pInfo, u.cj.iRoot, u.cj.pKey, u.cj.aArg, pOp->p5, &p->zErrMsg);
  break;
}

/*
** Opcode: FtsCksum P1 * P3 P4 P5
**
** This opcode is used by the integrity-check procedure that verifies that
** the contents of an fts5 index and its corresponding table match.
*/
case OP_FtsCksum: {
#if 0  /* local variables moved into u.ck */
  Fts5Info *pInfo;                /* Description of fts5 index to update */
  Mem *pKey;                      /* Primary key of row */
  Mem *aArg;                      /* Pointer to array of N values */
  i64 cksum;                      /* Checksum for this row or index entry */
  i64 i1;
#endif /* local variables moved into u.ck */

  assert( pOp->p4type==P4_FTS5INFO );
  u.ck.pInfo = pOp->p4.pFtsInfo;

  pOut = &aMem[pOp->p1];
  u.ck.pKey = &aMem[pOp->p3];
  u.ck.aArg = &aMem[pOp->p3+1];
  u.ck.cksum = 0;

  if( pOp->p5 ){
    sqlite4Fts5EntryCksum(db, u.ck.pInfo, u.ck.pKey, u.ck.aArg, &u.ck.cksum);
  }else{
    sqlite4Fts5RowCksum(db, u.ck.pInfo, u.ck.pKey, u.ck.aArg, &u.ck.cksum);
  }
  u.ck.i1 = sqlite4_num_to_int64(pOut->u.num, 0);
  pOut->u.num = sqlite4_num_from_int64(u.ck.i1 ^ u.ck.cksum);

  break;
}

/* Opcode: FtsOpen P1 P2 P3 P4 P5
**
** Open an FTS cursor named P1. P4 points to an Fts5Info object.
**
** Register P3 contains the MATCH expression that this cursor will iterate
** through the matches for. P5 is set to 0 to iterate through the results
** in ascending PK order, or 1 for descending PK order.
**
** If the expression matches zero rows, jump to instruction P2. Otherwise,
** leave the cursor pointing at the first match and fall through to the
** next instruction.
*/
case OP_FtsOpen: {          /* jump */
#if 0  /* local variables moved into u.cl */
  Fts5Info *pInfo;                /* Description of fts5 index to update */
  VdbeCursor *pCur;
  char *zMatch;
  Mem *pMatch;
#endif /* local variables moved into u.cl */

  u.cl.pMatch = &aMem[pOp->p3];
  Stringify(u.cl.pMatch, encoding);
  u.cl.zMatch = u.cl.pMatch->z;

  assert( pOp->p4type==P4_FTS5INFO );
  u.cl.pInfo = pOp->p4.pFtsInfo;
  u.cl.pCur = allocateCursor(p, pOp->p1, 0, u.cl.pInfo->iDb, 0);
  if( u.cl.pCur ){
    rc = sqlite4Fts5Open(db, u.cl.pInfo, u.cl.zMatch, pOp->p5, &u.cl.pCur->pFts, &p->zErrMsg);
  }
  if( rc==SQLITE4_OK && 0==sqlite4Fts5Valid(u.cl.pCur->pFts) ){
    pc = pOp->p2-1;
  }
  break;
}

/* Opcode: FtsNext P1 P2 * * *
**
** Advance FTS cursor P1 to the next entry and jump to instruction P2. Or,
** if there is no next entry, set the cursor to point to EOF and fall through
** to the next instruction.
*/
case OP_FtsNext: {
#if 0  /* local variables moved into u.cm */
  VdbeCursor *pCsr;
#endif /* local variables moved into u.cm */

  u.cm.pCsr = p->apCsr[pOp->p1];
  rc = sqlite4Fts5Next(u.cm.pCsr->pFts);
  if( rc==SQLITE4_OK && sqlite4Fts5Valid(u.cm.pCsr->pFts) ) pc = pOp->p2-1;

  break;
}

/* Opcode: FtsPk P1 P2 * * * 
**
** P1 is an FTS cursor that points to a valid entry (not EOF). Copy the PK 
** blob for the current entry to register P2.
*/
case OP_FtsPk: {
  assert( 0 );
  break;
}

/* Opcode: Noop * * * * *
**
** Do nothing.  This instruction is often useful as a jump
** destination.
*/
/*
** The magic Explain opcode are only inserted when explain==2 (which
** is to say when the EXPLAIN QUERY PLAN syntax is used.)
** This opcode records information from the optimizer.  It is the
** the same as a no-op.  This opcode never appears in a real VM program.
*/
default: {          /* This is really OP_Noop and OP_Explain */
  assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
  break;
}

/*****************************************************************************
** The cases of the switch statement above this line should all be indented
** by 6 spaces.  But the left-most 6 spaces have been removed to improve the
** readability.  From this point on down, the normal indentation rules are
** restored.
*****************************************************************************/
    }

#ifdef VDBE_PROFILE
    {
      u64 elapsed = sqlite4Hwtime() - start;
      pOp->cycles += elapsed;
      pOp->cnt++;
#if 0
        fprintf(stdout, "%10llu ", elapsed);
        sqlite4VdbePrintOp(stdout, origPc, &aOp[origPc]);
#endif
    }
#endif

    /* The following code adds nothing to the actual functionality
    ** of the program.  It is only here for testing and debugging.
    ** On the other hand, it does burn CPU cycles every time through
    ** the evaluator loop.  So we can leave it out when NDEBUG is defined.
    */
#ifndef NDEBUG
    assert( pc>=-1 && pc<p->nOp );

#ifdef SQLITE4_DEBUG
    if( p->trace ){
      if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
      if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){
        registerTrace(p->trace, pOp->p2, &aMem[pOp->p2]);
      }
      if( pOp->opflags & OPFLG_OUT3 ){
        registerTrace(p->trace, pOp->p3, &aMem[pOp->p3]);
      }
    }
#endif  /* SQLITE4_DEBUG */
#endif  /* NDEBUG */
  }  /* The end of the for(;;) loop the loops through opcodes */

  /* If we reach this point, it means that execution is finished with
  ** an error of some kind.
  */
vdbe_error_halt:
  assert( rc );
  p->rc = rc;
  testcase( sqlite4DefaultEnv.xLog!=0 );
  sqlite4_log(db->pEnv, rc, "statement aborts at %d: [%s] %s", 
                   pc, p->zSql, p->zErrMsg);
  sqlite4VdbeHalt(p);
  if( rc==SQLITE4_IOERR_NOMEM ) db->mallocFailed = 1;
  rc = SQLITE4_ERROR;
  if( resetSchemaOnFault>0 ){
    sqlite4ResetInternalSchema(db, resetSchemaOnFault-1);
  }

  /* This is the only way out of this procedure.  We have to
  ** release the mutexes on btrees that were acquired at the
  ** top. */
vdbe_return:
  return rc;

  /* Jump to here if a string or blob larger than SQLITE4_MAX_LENGTH
  ** is encountered.
  */
too_big:
  sqlite4SetString(&p->zErrMsg, db, "string or blob too big");
  rc = SQLITE4_TOOBIG;
  goto vdbe_error_halt;

  /* Jump to here if a malloc() fails.
  */
no_mem:
  db->mallocFailed = 1;
  sqlite4SetString(&p->zErrMsg, db, "out of memory");
  rc = SQLITE4_NOMEM;
  goto vdbe_error_halt;

  /* Jump to here for any other kind of fatal error.  The "rc" variable
  ** should hold the error number.
  */
abort_due_to_error:
  assert( p->zErrMsg==0 );
  if( db->mallocFailed ) rc = SQLITE4_NOMEM;
  if( rc!=SQLITE4_IOERR_NOMEM ){
    sqlite4SetString(&p->zErrMsg, db, "%s", sqlite4ErrStr(rc));
  }
  goto vdbe_error_halt;

  /* Jump to here if the sqlite4_interrupt() API sets the interrupt
  ** flag.
  */
abort_due_to_interrupt:
  assert( db->u1.isInterrupted );
  rc = SQLITE4_INTERRUPT;
  p->rc = rc;
  sqlite4SetString(&p->zErrMsg, db, "%s", sqlite4ErrStr(rc));
  goto vdbe_error_halt;
}

/************** End of vdbe.c ************************************************/
/************** Begin file walker.c ******************************************/
/*
** 2008 August 16
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for walking the parser tree for
** an SQL statement.
*/
/* #include <stdlib.h> */
/* #include <string.h> */


/*
** Walk an expression tree.  Invoke the callback once for each node
** of the expression, while decending.  (In other words, the callback
** is invoked before visiting children.)
**
** The return value from the callback should be one of the WRC_*
** constants to specify how to proceed with the walk.
**
**    WRC_Continue      Continue descending down the tree.
**
**    WRC_Prune         Do not descend into child nodes.  But allow
**                      the walk to continue with sibling nodes.
**
**    WRC_Abort         Do no more callbacks.  Unwind the stack and
**                      return the top-level walk call.
**
** The return value from this routine is WRC_Abort to abandon the tree walk
** and WRC_Continue to continue.
*/
SQLITE4_PRIVATE int sqlite4WalkExpr(Walker *pWalker, Expr *pExpr){
  int rc;
  if( pExpr==0 ) return WRC_Continue;
  testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
  testcase( ExprHasProperty(pExpr, EP_Reduced) );
  rc = pWalker->xExprCallback(pWalker, pExpr);
  if( rc==WRC_Continue
              && !ExprHasAnyProperty(pExpr,EP_TokenOnly) ){
    if( sqlite4WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
    if( sqlite4WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      if( sqlite4WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
    }else{
      if( sqlite4WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
    }
  }
  return rc & WRC_Abort;
}

/*
** Call sqlite4WalkExpr() for every expression in list p or until
** an abort request is seen.
*/
SQLITE4_PRIVATE int sqlite4WalkExprList(Walker *pWalker, ExprList *p){
  int i;
  ExprListItem *pItem;
  if( p ){
    for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
      if( sqlite4WalkExpr(pWalker, pItem->pExpr) ) return WRC_Abort;
    }
  }
  return WRC_Continue;
}

/*
** Walk all expressions associated with SELECT statement p.  Do
** not invoke the SELECT callback on p, but do (of course) invoke
** any expr callbacks and SELECT callbacks that come from subqueries.
** Return WRC_Abort or WRC_Continue.
*/
SQLITE4_PRIVATE int sqlite4WalkSelectExpr(Walker *pWalker, Select *p){
  if( sqlite4WalkExprList(pWalker, p->pEList) ) return WRC_Abort;
  if( sqlite4WalkExpr(pWalker, p->pWhere) ) return WRC_Abort;
  if( sqlite4WalkExprList(pWalker, p->pGroupBy) ) return WRC_Abort;
  if( sqlite4WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
  if( sqlite4WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
  if( sqlite4WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
  if( sqlite4WalkExpr(pWalker, p->pOffset) ) return WRC_Abort;
  return WRC_Continue;
}

/*
** Walk the parse trees associated with all subqueries in the
** FROM clause of SELECT statement p.  Do not invoke the select
** callback on p, but do invoke it on each FROM clause subquery
** and on any subqueries further down in the tree.  Return 
** WRC_Abort or WRC_Continue;
*/
SQLITE4_PRIVATE int sqlite4WalkSelectFrom(Walker *pWalker, Select *p){
  SrcList *pSrc;
  int i;
  SrcListItem *pItem;

  pSrc = p->pSrc;
  if( ALWAYS(pSrc) ){
    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
      if( sqlite4WalkSelect(pWalker, pItem->pSelect) ){
        return WRC_Abort;
      }
    }
  }
  return WRC_Continue;
} 

/*
** Call sqlite4WalkExpr() for every expression in Select statement p.
** Invoke sqlite4WalkSelect() for subqueries in the FROM clause and
** on the compound select chain, p->pPrior.
**
** Return WRC_Continue under normal conditions.  Return WRC_Abort if
** there is an abort request.
**
** If the Walker does not have an xSelectCallback() then this routine
** is a no-op returning WRC_Continue.
*/
SQLITE4_PRIVATE int sqlite4WalkSelect(Walker *pWalker, Select *p){
  int rc;
  if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
  rc = WRC_Continue;
  while( p  ){
    rc = pWalker->xSelectCallback(pWalker, p);
    if( rc ) break;
    if( sqlite4WalkSelectExpr(pWalker, p) ) return WRC_Abort;
    if( sqlite4WalkSelectFrom(pWalker, p) ) return WRC_Abort;
    p = p->pPrior;
  }
  return rc & WRC_Abort;
}

/************** End of walker.c **********************************************/
/************** Begin file resolve.c *****************************************/
/*
** 2008 August 18
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains routines used for walking the parser tree and
** 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
** result set in pEList.
**
** If the result set column is a simple column reference, then this routine
** makes an exact copy.  But for any other kind of expression, this
** routine make a copy of the result set column as the argument to the
** TK_AS operator.  The TK_AS operator causes the expression to be
** evaluated just once and then reused for each alias.
**
** The reason for suppressing the TK_AS term when the expression is a simple
** column reference is so that the column reference will be recognized as
** usable by indices within the WHERE clause processing logic. 
**
** Hack:  The TK_AS operator is inhibited if zType[0]=='G'.  This means
** that in a GROUP BY clause, the expression is evaluated twice.  Hence:
**
**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
**
** Is equivalent to:
**
**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
**
** The result of random()%5 in the GROUP BY clause is probably different
** from the result in the result-set.  We might fix this someday.  Or
** then again, we might not...
*/
static void resolveAlias(
  Parse *pParse,         /* Parsing context */
  ExprList *pEList,      /* A result set */
  int iCol,              /* A column in the result set.  0..pEList->nExpr-1 */
  Expr *pExpr,           /* Transform this into an alias to the result set */
  const char *zType      /* "GROUP" or "ORDER" or "" */
){
  Expr *pOrig;           /* The iCol-th column of the result set */
  Expr *pDup;            /* Copy of pOrig */
  sqlite4 *db;           /* The database connection */

  assert( iCol>=0 && iCol<pEList->nExpr );
  pOrig = pEList->a[iCol].pExpr;
  assert( pOrig!=0 );
  assert( pOrig->flags & EP_Resolved );
  db = pParse->db;
  if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
    pDup = sqlite4ExprDup(db, pOrig, 0);
    pDup = sqlite4PExpr(pParse, TK_AS, pDup, 0, 0);
    if( pDup==0 ) return;
    if( pEList->a[iCol].iAlias==0 ){
      pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
    }
    pDup->iTable = pEList->a[iCol].iAlias;
  }else if( ExprHasProperty(pOrig, EP_IntValue) || pOrig->u.zToken==0 ){
    pDup = sqlite4ExprDup(db, pOrig, 0);
    if( pDup==0 ) return;
  }else{
    char *zToken = pOrig->u.zToken;
    assert( zToken!=0 );
    pOrig->u.zToken = 0;
    pDup = sqlite4ExprDup(db, pOrig, 0);
    pOrig->u.zToken = zToken;
    if( pDup==0 ) return;
    assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
    pDup->flags2 |= EP2_MallocedToken;
    pDup->u.zToken = sqlite4DbStrDup(db, zToken);
  }
  if( pExpr->flags & EP_ExpCollate ){
    pDup->pColl = pExpr->pColl;
    pDup->flags |= EP_ExpCollate;
  }

  /* Before calling sqlite4ExprDelete(), set the EP_Static flag. This 
  ** prevents ExprDelete() from deleting the Expr structure itself,
  ** allowing it to be repopulated by the memcpy() on the following line.
  */
  ExprSetProperty(pExpr, EP_Static);
  sqlite4ExprDelete(db, pExpr);
  memcpy(pExpr, pDup, sizeof(*pExpr));
  sqlite4DbFree(db, pDup);
}


/*
** Return TRUE if the name zCol occurs anywhere in the USING clause.
**
** Return FALSE if the USING clause is NULL or if it does not contain
** zCol.
*/
static int nameInUsingClause(IdList *pUsing, const char *zCol){
  if( pUsing ){
    int k;
    for(k=0; k<pUsing->nId; k++){
      if( sqlite4_stricmp(pUsing->a[k].zName, zCol)==0 ) return 1;
    }
  }
  return 0;
}

/*
** Return true if table pTab has an implicit primary key, and zCol points
** to a column name that resolves to the implicit primary key (i.e. "rowid").
*/
int isRowidReference(Table *pTab, const char *zCol){
  int ret = 0;
  if( 0==sqlite4_stricmp(zCol, "ROWID") ){
    /* If the call to FindPrimaryKey() returns NULL, then pTab must be a
    ** sub-select or a view. Neither of these have an IPK.  */
    Index *pPk = sqlite4FindPrimaryKey(pTab, 0);
    if( pPk && pPk->aiColumn[0]==-1 ) ret = 1;
  }
  return ret;
}

/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr 
** expression node refer back to that source column.  The following changes
** are made to pExpr:
**
**    pExpr->iDb           Set the index in db->aDb[] of the database X
**                         (even if X is implied).
**    pExpr->iTable        Set to the cursor number for the table obtained
**                         from pSrcList.
**    pExpr->pTab          Points to the Table structure of X.Y (even if
**                         X and/or Y are implied.)
**    pExpr->iColumn       Set to the column number within the table.
**    pExpr->op            Set to TK_COLUMN.
**    pExpr->pLeft         Any expression this points to is deleted
**    pExpr->pRight        Any expression this points to is deleted.
**
** The zDb variable is the name of the database (the "X").  This value may be
** NULL meaning that name is of the form Y.Z or Z.  Any available database
** can be used.  The zTable variable is the name of the table (the "Y").  This
** value can be NULL if zDb is also NULL.  If zTable is NULL it
** means that the form of the name is Z and that columns from any table
** can be used.
**
** If the name cannot be resolved unambiguously, leave an error message
** in pParse and return WRC_Abort.  Return WRC_Prune on success.
*/
static int lookupName(
  Parse *pParse,       /* The parsing context */
  const char *zDb,     /* Name of the database containing table, or NULL */
  const char *zTab,    /* Name of table containing column, or NULL */
  const char *zCol,    /* Name of the column. */
  NameContext *pNC,    /* The name context used to resolve the name */
  Expr *pExpr          /* Make this EXPR node point to the selected column */
){
  int i, j;            /* Loop counters */
  int cnt = 0;                      /* Number of matching column names */
  int cntTab = 0;                   /* Number of matching table names */
  sqlite4 *db = pParse->db;         /* The database connection */
  SrcListItem *pItem;       /* Use for looping over pSrcList items */
  SrcListItem *pMatch = 0;  /* The matching pSrcList item */
  NameContext *pTopNC = pNC;        /* First namecontext in the list */
  Schema *pSchema = 0;              /* Schema of the expression */
  int isTrigger = 0;

  assert( pNC );     /* the name context cannot be NULL. */
  assert( zCol );    /* The Z in X.Y.Z cannot be NULL */
  assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );

  /* Initialize the node to no-match */
  pExpr->iTable = -1;
  pExpr->pTab = 0;
  ExprSetIrreducible(pExpr);

  /* Start at the inner-most context and move outward until a match is found */
  while( pNC && cnt==0 ){
    ExprList *pEList;
    SrcList *pSrcList = pNC->pSrcList;

    if( pSrcList ){
      for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
        Table *pTab;
        int iDb;
        Column *pCol;
  
        pTab = pItem->pTab;
        assert( pTab!=0 && pTab->zName!=0 );
        iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
        assert( pTab->nCol>0 );
        if( zTab ){
          if( pItem->zAlias ){
            char *zTabName = pItem->zAlias;
            if( sqlite4_stricmp(zTabName, zTab)!=0 ) continue;
          }else{
            char *zTabName = pTab->zName;
            if( NEVER(zTabName==0) || sqlite4_stricmp(zTabName, zTab)!=0 ){
              continue;
            }
            if( zDb!=0 && sqlite4_stricmp(db->aDb[iDb].zName, zDb)!=0 ){
              continue;
            }
          }
        }
        if( 0==(cntTab++) ){
          pExpr->iTable = pItem->iCursor;
          pExpr->pTab = pTab;
          pSchema = pTab->pSchema;
          pMatch = pItem;
        }
        for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
          if( sqlite4_stricmp(pCol->zName, zCol)==0 ){
            /* If there has been exactly one prior match and this match
            ** is for the right-hand table of a NATURAL JOIN or is in a 
            ** USING clause, then skip this match.
            */
            if( cnt==1 ){
              if( pItem->jointype & JT_NATURAL ) continue;
              if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
            }
            cnt++;
            pExpr->iTable = pItem->iCursor;
            pExpr->pTab = pTab;
            pMatch = pItem;
            pSchema = pTab->pSchema;
            pExpr->iColumn = (i16)j;
            break;
          }
        }
      }
    }

#ifndef SQLITE4_OMIT_TRIGGER
    /* If we have not already resolved the name, then maybe 
    ** it is a new.* or old.* trigger argument reference
    */
    if( zDb==0 && zTab!=0 && cnt==0 && pParse->pTriggerTab!=0 ){
      int op = pParse->eTriggerOp;
      Table *pTab = 0;
      assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
      if( op!=TK_DELETE && sqlite4_stricmp("new",zTab) == 0 ){
        pExpr->iTable = 1;
        pTab = pParse->pTriggerTab;
      }else if( op!=TK_INSERT && sqlite4_stricmp("old",zTab)==0 ){
        pExpr->iTable = 0;
        pTab = pParse->pTriggerTab;
      }

      if( pTab ){ 
        int iCol;
        pSchema = pTab->pSchema;
        cntTab++;
        for(iCol=0; iCol<pTab->nCol; iCol++){
          Column *pCol = &pTab->aCol[iCol];
          if( sqlite4_stricmp(pCol->zName, zCol)==0 ){
            break;
          }
        }
        if( iCol>=pTab->nCol && isRowidReference(pTab, zCol) ){
          iCol = -1;        /* IMP: R-44911-55124 */
        }
        if( iCol<pTab->nCol ){
          cnt++;
          if( iCol<0 ){
            pExpr->affinity = SQLITE4_AFF_INTEGER;
          }else if( pExpr->iTable==0 ){
            testcase( iCol==31 );
            testcase( iCol==32 );
            pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
          }else{
            testcase( iCol==31 );
            testcase( iCol==32 );
            pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
          }
          pExpr->iColumn = (i16)iCol;
          isTrigger = 1;
        }
        pExpr->pTab = pTab;
      }
    }
#endif /* !defined(SQLITE4_OMIT_TRIGGER) */

    /*
    ** Perhaps the name is a reference to the ROWID
    */
    if( cnt==0 && cntTab==1 && isRowidReference(pExpr->pTab, zCol) ){
      cnt = 1;
      pExpr->iColumn = -1;     /* IMP: R-44911-55124 */
      pExpr->affinity = SQLITE4_AFF_INTEGER;
    }

    /*
    ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
    ** might refer to an result-set alias.  This happens, for example, when
    ** we are resolving names in the WHERE clause of the following command:
    **
    **     SELECT a+b AS x FROM table WHERE x<10;
    **
    ** In cases like this, replace pExpr with a copy of the expression that
    ** forms the result set entry ("a+b" in the example) and return immediately.
    ** Note that the expression in the result set should have already been
    ** resolved by the time the WHERE clause is resolved.
    */
    if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
      for(j=0; j<pEList->nExpr; j++){
        char *zAs = pEList->a[j].zName;
        if( zAs!=0 && sqlite4_stricmp(zAs, zCol)==0 ){
          Expr *pOrig;
          assert( pExpr->pLeft==0 && pExpr->pRight==0 );
          assert( pExpr->x.pList==0 );
          assert( pExpr->x.pSelect==0 );
          pOrig = pEList->a[j].pExpr;
          if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
            sqlite4ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
            return WRC_Abort;
          }
          resolveAlias(pParse, pEList, j, pExpr, "");
          cnt = 1;
          pMatch = 0;
          assert( zTab==0 && zDb==0 );
          goto lookupname_end;
        }
      } 
    }

    /* Advance to the next name context.  The loop will exit when either
    ** we have a match (cnt>0) or when we run out of name contexts.
    */
    if( cnt==0 ){
      pNC = pNC->pNext;
    }
  }

  /*
  ** cnt==0 means there was not match.  cnt>1 means there were two or
  ** more matches.  Either way, we have an error.
  */
  if( cnt!=1 ){
    const char *zErr;
    zErr = cnt==0 ? "no such column" : "ambiguous column name";
    if( zDb ){
      sqlite4ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
    }else if( zTab ){
      sqlite4ErrorMsg(pParse, "%s: %s.%s", zErr, zTab, zCol);
    }else{
      sqlite4ErrorMsg(pParse, "%s: %s", zErr, zCol);
    }
    pParse->checkSchema = 1;
    pTopNC->nErr++;
  }

  /* If a column from a table in pSrcList is referenced, then record
  ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
  ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  If the
  ** column number is greater than the number of bits in the bitmask
  ** then set the high-order bit of the bitmask.
  */
  if( pMatch!=0 ){
    int n = pExpr->iColumn;
    testcase( n==BMS-1 );
    if( n>=BMS || n<0 ){
      n = BMS-1;
    }
    assert( pMatch->iCursor==pExpr->iTable );
    pMatch->colUsed |= ((Bitmask)1)<<n;
  }

  /* Clean up and return
  */
  sqlite4ExprDelete(db, pExpr->pLeft);
  pExpr->pLeft = 0;
  sqlite4ExprDelete(db, pExpr->pRight);
  pExpr->pRight = 0;
  pExpr->op = (isTrigger ? TK_TRIGGER : TK_COLUMN);
lookupname_end:
  if( cnt==1 ){
    assert( pNC!=0 );
    sqlite4AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
    /* Increment the nRef value on all name contexts from TopNC up to
    ** the point where the name matched. */
    for(;;){
      assert( pTopNC!=0 );
      pTopNC->nRef++;
      if( pTopNC==pNC ) break;
      pTopNC = pTopNC->pNext;
    }
    return WRC_Prune;
  } else {
    return WRC_Abort;
  }
}

/*
** Allocate and return a pointer to an expression to load the column iCol
** from datasource iSrc in SrcList pSrc.
*/
SQLITE4_PRIVATE Expr *sqlite4CreateColumnExpr(sqlite4 *db, SrcList *pSrc, int iSrc, int iCol){
  Expr *p = sqlite4ExprAlloc(db, TK_COLUMN, 0, 0);
  if( p ){
    SrcListItem *pItem = &pSrc->a[iSrc];
    p->pTab = pItem->pTab;
    p->iTable = pItem->iCursor;
    p->iColumn = (ynVar)iCol;
    testcase( iCol==BMS );
    testcase( iCol==BMS-1 );
    pItem->colUsed |= ((Bitmask)1)<<((iCol>=BMS || iCol<0) ? BMS-1 : iCol);
    ExprSetProperty(p, EP_Resolved);
  }
  return p;
}

static void resolveMatchArg(Parse *pParse, NameContext *pNC, Expr *pExpr){
  SrcList *pSrc = pNC->pSrcList;
  SrcListItem *pItem;
  char *zLhs;
  int i;

  if( pExpr->op!=TK_ID || pSrc==0 || pExpr==0 ){
    sqlite4ErrorMsg(pParse, "first argument xxx must be a table name");
    return;
  }
  zLhs = pExpr->u.zToken;

  for(i=0; i<pSrc->nSrc; i++){
    pItem = &pSrc->a[i];
    if( pItem->zAlias && sqlite4_stricmp(zLhs, pItem->zAlias)==0 ) break;
    if( pItem->zAlias==0 && sqlite4_stricmp(zLhs, pItem->zName)==0 ) break;
  }
  if( i==pSrc->nSrc ){
    sqlite4ErrorMsg(pParse, "no such table: %s", zLhs);
    return;
  }

  pExpr->op = TK_NULL;
  pExpr->iTable = pItem->iCursor;
  ExprSetProperty(pExpr, EP_Resolved);
}

static void resolveMatch(Parse *pParse, NameContext *pNC, Expr *pExpr){
  Expr *pLeft = pExpr->pLeft;
  SrcList *pSrc = pNC->pSrcList;
  SrcListItem *pItem;
  char *zLhs;
  int i;
  Index *pIdx;

  if( pLeft->op!=TK_ID || pSrc==0 ){
    sqlite4ErrorMsg(pParse, "lhs of MATCH operator must be a table name");
    return;
  }
  zLhs = pLeft->u.zToken;

  for(i=0; i<pSrc->nSrc; i++){
    pItem = &pSrc->a[i];
    if( pItem->zAlias && sqlite4_stricmp(zLhs, pItem->zAlias)==0 ) break;
    if( pItem->zAlias==0 && sqlite4_stricmp(zLhs, pItem->zName)==0 ) break;
  }

  if( i==pSrc->nSrc ){
    sqlite4ErrorMsg(pParse, "no such table: %s", zLhs);
    return;
  }

  for(pIdx=pItem->pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->eIndexType==SQLITE4_INDEX_FTS5 ) break;
  }
  if( !pIdx ){
    sqlite4ErrorMsg(pParse, "no index to process MATCH operator");
    return;
  }

  pExpr->pLeft = 0;
  pExpr->pIdx = pIdx;
  sqlite4ExprDelete(pParse->db, pLeft);
}

/*
** This routine is callback for sqlite4WalkExpr().
**
** Resolve symbolic names into TK_COLUMN operators for the current
** node in the expression tree.  Return 0 to continue the search down
** the tree or 2 to abort the tree walk.
**
** This routine also does error checking and name resolution for
** function names.  The operator for aggregate functions is changed
** to TK_AGG_FUNCTION.
*/
static int resolveExprStep(Walker *pWalker, Expr *pExpr){
  NameContext *pNC;
  Parse *pParse;

  pNC = pWalker->u.pNC;
  assert( pNC!=0 );
  pParse = pNC->pParse;
  assert( pParse==pWalker->pParse );

  if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return WRC_Prune;
  ExprSetProperty(pExpr, EP_Resolved);
#ifndef NDEBUG
  if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){
    SrcList *pSrcList = pNC->pSrcList;
    int i;
    for(i=0; i<pNC->pSrcList->nSrc; i++){
      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
    }
  }
#endif
  switch( pExpr->op ){

#if defined(SQLITE4_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE4_OMIT_SUBQUERY)
    /* The special operator TK_ROW means use the rowid for the first
    ** column in the FROM clause.  This is used by the LIMIT and ORDER BY
    ** clause processing on UPDATE and DELETE statements.
    */
    case TK_ROW: {
      SrcList *pSrcList = pNC->pSrcList;
      SrcListItem *pItem;
      assert( pSrcList && pSrcList->nSrc==1 );
      pItem = pSrcList->a; 
      pExpr->op = TK_COLUMN;
      pExpr->pTab = pItem->pTab;
      pExpr->iTable = pItem->iCursor;
      pExpr->iColumn = -1;
      pExpr->affinity = SQLITE4_AFF_INTEGER;
      break;
    }
#endif /* defined(SQLITE4_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE4_OMIT_SUBQUERY) */

    /* A lone identifier is the name of a column.
    */
    case TK_ID: {
      return lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
    }
  
    /* A table name and column name:     ID.ID
    ** Or a database, table and column:  ID.ID.ID
    */
    case TK_DOT: {
      const char *zColumn;
      const char *zTable;
      const char *zDb;
      Expr *pRight;

      /* if( pSrcList==0 ) break; */
      pRight = pExpr->pRight;
      if( pRight->op==TK_ID ){
        zDb = 0;
        zTable = pExpr->pLeft->u.zToken;
        zColumn = pRight->u.zToken;
      }else{
        assert( pRight->op==TK_DOT );
        zDb = pExpr->pLeft->u.zToken;
        zTable = pRight->pLeft->u.zToken;
        zColumn = pRight->pRight->u.zToken;
      }
      return lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
    }

    /* Resolve function names
    */
    case TK_CONST_FUNC:
    case TK_FUNCTION: {
      ExprList *pList = pExpr->x.pList;    /* The argument list */
      int n = pList ? pList->nExpr : 0;    /* Number of arguments */
      int no_such_func = 0;       /* True if no such function exists */
      int wrong_num_args = 0;     /* True if wrong number of arguments */
      int is_agg = 0;             /* True if is an aggregate function */
      int auth;                   /* Authorization to use the function */
      int nId;                    /* Number of characters in function name */
      const char *zId;            /* The function name. */
      FuncDef *pDef;              /* Information about the function */

      testcase( pExpr->op==TK_CONST_FUNC );
      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
      zId = pExpr->u.zToken;
      nId = sqlite4Strlen30(zId);
      pDef = sqlite4FindFunction(pParse->db, zId, nId, n, 0);
      if( pDef==0 ){
        pDef = sqlite4FindFunction(pParse->db, zId, nId, -1, 0);
        if( pDef==0 ){
          no_such_func = 1;
        }else{
          wrong_num_args = 1;
        }
      }else{
        is_agg = pDef->xFunc==0;
      }
#ifndef SQLITE4_OMIT_AUTHORIZATION
      if( pDef ){
        auth = sqlite4AuthCheck(pParse, SQLITE4_FUNCTION, 0, pDef->zName, 0);
        if( auth!=SQLITE4_OK ){
          if( auth==SQLITE4_DENY ){
            sqlite4ErrorMsg(pParse, "not authorized to use function: %s",
                                    pDef->zName);
            pNC->nErr++;
          }
          pExpr->op = TK_NULL;
          return WRC_Prune;
        }
      }
#endif
      if( is_agg && !pNC->allowAgg ){
        sqlite4ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
        pNC->nErr++;
        is_agg = 0;
      }else if( no_such_func ){
        sqlite4ErrorMsg(pParse, "no such function: %.*s", nId, zId);
        pNC->nErr++;
      }else if( wrong_num_args ){
        sqlite4ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
             nId, zId);
        pNC->nErr++;
      }
      if( is_agg ){
        pExpr->op = TK_AGG_FUNCTION;
        pNC->hasAgg = 1;
      }

      if( pParse->nErr==0 ){
        if( pDef->bMatchinfo ){
          resolveMatchArg(pParse, pNC, n>0 ? pList->a[0].pExpr : 0);
        }
        if( is_agg ) pNC->allowAgg = 0;
        sqlite4WalkExprList(pWalker, pList);
        if( is_agg ) pNC->allowAgg = 1;
      }

      /* FIX ME:  Compute pExpr->affinity based on the expected return
      ** type of the function 
      */
      return WRC_Prune;
    }
#ifndef SQLITE4_OMIT_SUBQUERY
    case TK_SELECT:
    case TK_EXISTS:  testcase( pExpr->op==TK_EXISTS );
#endif
    case TK_IN: {
      testcase( pExpr->op==TK_IN );
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        int nRef = pNC->nRef;
#ifndef SQLITE4_OMIT_CHECK
        if( pNC->isCheck ){
          sqlite4ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
        }
#endif
        sqlite4WalkSelect(pWalker, pExpr->x.pSelect);
        assert( pNC->nRef>=nRef );
        if( nRef!=pNC->nRef ){
          ExprSetProperty(pExpr, EP_VarSelect);
        }
      }
      break;
    }
#ifndef SQLITE4_OMIT_CHECK
    case TK_VARIABLE: {
      if( pNC->isCheck ){
        sqlite4ErrorMsg(pParse,"parameters prohibited in CHECK constraints");
      }
      break;
    }
#endif
    case TK_MATCH: {
      resolveMatch(pParse, pNC, pExpr);
      break;
    }
  }
  return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
}

/*
** pEList is a list of expressions which are really the result set of the
** a SELECT statement.  pE is a term in an ORDER BY or GROUP BY clause.
** This routine checks to see if pE is a simple identifier which corresponds
** to the AS-name of one of the terms of the expression list.  If it is,
** this routine return an integer between 1 and N where N is the number of
** elements in pEList, corresponding to the matching entry.  If there is
** no match, or if pE is not a simple identifier, then this routine
** return 0.
**
** pEList has been resolved.  pE has not.
*/
static int resolveAsName(
  Parse *pParse,     /* Parsing context for error messages */
  ExprList *pEList,  /* List of expressions to scan */
  Expr *pE           /* Expression we are trying to match */
){
  int i;             /* Loop counter */

  UNUSED_PARAMETER(pParse);

  if( pE->op==TK_ID ){
    char *zCol = pE->u.zToken;
    for(i=0; i<pEList->nExpr; i++){
      char *zAs = pEList->a[i].zName;
      if( zAs!=0 && sqlite4_stricmp(zAs, zCol)==0 ){
        return i+1;
      }
    }
  }
  return 0;
}

/*
** pE is a pointer to an expression which is a single term in the
** ORDER BY of a compound SELECT.  The expression has not been
** name resolved.
**
** At the point this routine is called, we already know that the
** ORDER BY term is not an integer index into the result set.  That
** case is handled by the calling routine.
**
** Attempt to match pE against result set columns in the left-most
** SELECT statement.  Return the index i of the matching column,
** as an indication to the caller that it should sort by the i-th column.
** The left-most column is 1.  In other words, the value returned is the
** same integer value that would be used in the SQL statement to indicate
** the column.
**
** If there is no match, return 0.  Return -1 if an error occurs.
*/
static int resolveOrderByTermToExprList(
  Parse *pParse,     /* Parsing context for error messages */
  Select *pSelect,   /* The SELECT statement with the ORDER BY clause */
  Expr *pE           /* The specific ORDER BY term */
){
  int i;             /* Loop counter */
  ExprList *pEList;  /* The columns of the result set */
  NameContext nc;    /* Name context for resolving pE */
  sqlite4 *db;       /* Database connection */
  int rc;            /* Return code from subprocedures */
  u8 savedSuppErr;   /* Saved value of db->suppressErr */

  assert( sqlite4ExprIsInteger(pE, &i)==0 );
  pEList = pSelect->pEList;

  /* Resolve all names in the ORDER BY term expression
  */
  memset(&nc, 0, sizeof(nc));
  nc.pParse = pParse;
  nc.pSrcList = pSelect->pSrc;
  nc.pEList = pEList;
  nc.allowAgg = 1;
  nc.nErr = 0;
  db = pParse->db;
  savedSuppErr = db->suppressErr;
  db->suppressErr = 1;
  rc = sqlite4ResolveExprNames(&nc, pE);
  db->suppressErr = savedSuppErr;
  if( rc ) return 0;

  /* Try to match the ORDER BY expression against an expression
  ** in the result set.  Return an 1-based index of the matching
  ** result-set entry.
  */
  for(i=0; i<pEList->nExpr; i++){
    if( sqlite4ExprCompare(pEList->a[i].pExpr, pE)<2 ){
      return i+1;
    }
  }

  /* If no match, return 0. */
  return 0;
}

/*
** Generate an ORDER BY or GROUP BY term out-of-range error.
*/
static void resolveOutOfRangeError(
  Parse *pParse,         /* The error context into which to write the error */
  const char *zType,     /* "ORDER" or "GROUP" */
  int i,                 /* The index (1-based) of the term out of range */
  int mx                 /* Largest permissible value of i */
){
  sqlite4ErrorMsg(pParse, 
    "%r %s BY term out of range - should be "
    "between 1 and %d", i, zType, mx);
}

/*
** Analyze the ORDER BY clause in a compound SELECT statement.   Modify
** each term of the ORDER BY clause is a constant integer between 1
** and N where N is the number of columns in the compound SELECT.
**
** ORDER BY terms that are already an integer between 1 and N are
** unmodified.  ORDER BY terms that are integers outside the range of
** 1 through N generate an error.  ORDER BY terms that are expressions
** are matched against result set expressions of compound SELECT
** beginning with the left-most SELECT and working toward the right.
** At the first match, the ORDER BY expression is transformed into
** the integer column number.
**
** Return the number of errors seen.
*/
static int resolveCompoundOrderBy(
  Parse *pParse,        /* Parsing context.  Leave error messages here */
  Select *pSelect       /* The SELECT statement containing the ORDER BY */
){
  int i;
  ExprList *pOrderBy;
  ExprList *pEList;
  sqlite4 *db;
  int moreToDo = 1;

  pOrderBy = pSelect->pOrderBy;
  if( pOrderBy==0 ) return 0;
  db = pParse->db;
#if SQLITE4_MAX_COLUMN
  if( pOrderBy->nExpr>db->aLimit[SQLITE4_LIMIT_COLUMN] ){
    sqlite4ErrorMsg(pParse, "too many terms in ORDER BY clause");
    return 1;
  }
#endif
  for(i=0; i<pOrderBy->nExpr; i++){
    pOrderBy->a[i].done = 0;
  }
  pSelect->pNext = 0;
  while( pSelect->pPrior ){
    pSelect->pPrior->pNext = pSelect;
    pSelect = pSelect->pPrior;
  }
  while( pSelect && moreToDo ){
    ExprListItem *pItem;
    moreToDo = 0;
    pEList = pSelect->pEList;
    assert( pEList!=0 );
    for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
      int iCol = -1;
      Expr *pE, *pDup;
      if( pItem->done ) continue;
      pE = pItem->pExpr;
      if( sqlite4ExprIsInteger(pE, &iCol) ){
        if( iCol<=0 || iCol>pEList->nExpr ){
          resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
          return 1;
        }
      }else{
        iCol = resolveAsName(pParse, pEList, pE);
        if( iCol==0 ){
          pDup = sqlite4ExprDup(db, pE, 0);
          if( !db->mallocFailed ){
            assert(pDup);
            iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
          }
          sqlite4ExprDelete(db, pDup);
        }
      }
      if( iCol>0 ){
        CollSeq *pColl = pE->pColl;
        int flags = pE->flags & EP_ExpCollate;
        sqlite4ExprDelete(db, pE);
        pItem->pExpr = pE = sqlite4Expr(db, TK_INTEGER, 0);
        if( pE==0 ) return 1;
        pE->pColl = pColl;
        pE->flags |= EP_IntValue | flags;
        pE->u.iValue = iCol;
        pItem->iOrderByCol = (u16)iCol;
        pItem->done = 1;
      }else{
        moreToDo = 1;
      }
    }
    pSelect = pSelect->pNext;
  }
  for(i=0; i<pOrderBy->nExpr; i++){
    if( pOrderBy->a[i].done==0 ){
      sqlite4ErrorMsg(pParse, "%r ORDER BY term does not match any "
            "column in the result set", i+1);
      return 1;
    }
  }
  return 0;
}

/*
** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
** the SELECT statement pSelect.  If any term is reference to a
** result set expression (as determined by the ExprList.a.iCol field)
** then convert that term into a copy of the corresponding result set
** column.
**
** If any errors are detected, add an error message to pParse and
** return non-zero.  Return zero if no errors are seen.
*/
SQLITE4_PRIVATE int sqlite4ResolveOrderGroupBy(
  Parse *pParse,        /* Parsing context.  Leave error messages here */
  Select *pSelect,      /* The SELECT statement containing the clause */
  ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */
  const char *zType     /* "ORDER" or "GROUP" */
){
  int i;
  sqlite4 *db = pParse->db;
  ExprList *pEList;
  ExprListItem *pItem;

  if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
#if SQLITE4_MAX_COLUMN
  if( pOrderBy->nExpr>db->aLimit[SQLITE4_LIMIT_COLUMN] ){
    sqlite4ErrorMsg(pParse, "too many terms in %s BY clause", zType);
    return 1;
  }
#endif
  pEList = pSelect->pEList;
  assert( pEList!=0 );  /* sqlite4SelectNew() guarantees this */
  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
    if( pItem->iOrderByCol ){
      if( pItem->iOrderByCol>pEList->nExpr ){
        resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
        return 1;
      }
      resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType);
    }
  }
  return 0;
}

/*
** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
** The Name context of the SELECT statement is pNC.  zType is either
** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
**
** This routine resolves each term of the clause into an expression.
** If the order-by term is an integer I between 1 and N (where N is the
** number of columns in the result set of the SELECT) then the expression
** in the resolution is a copy of the I-th result-set expression.  If
** the order-by term is an identify that corresponds to the AS-name of
** a result-set expression, then the term resolves to a copy of the
** result-set expression.  Otherwise, the expression is resolved in
** the usual way - using sqlite4ResolveExprNames().
**
** This routine returns the number of errors.  If errors occur, then
** an appropriate error message might be left in pParse.  (OOM errors
** excepted.)
*/
static int resolveOrderGroupBy(
  NameContext *pNC,     /* The name context of the SELECT statement */
  Select *pSelect,      /* The SELECT statement holding pOrderBy */
  ExprList *pOrderBy,   /* An ORDER BY or GROUP BY clause to resolve */
  const char *zType     /* Either "ORDER" or "GROUP", as appropriate */
){
  int i;                         /* Loop counter */
  int iCol;                      /* Column number */
  ExprListItem *pItem;   /* A term of the ORDER BY clause */
  Parse *pParse;                 /* Parsing context */
  int nResult;                   /* Number of terms in the result set */

  if( pOrderBy==0 ) return 0;
  nResult = pSelect->pEList->nExpr;
  pParse = pNC->pParse;
  for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
    Expr *pE = pItem->pExpr;
    iCol = resolveAsName(pParse, pSelect->pEList, pE);
    if( iCol>0 ){
      /* If an AS-name match is found, mark this ORDER BY column as being
      ** a copy of the iCol-th result-set column.  The subsequent call to
      ** sqlite4ResolveOrderGroupBy() will convert the expression to a
      ** copy of the iCol-th result-set expression. */
      pItem->iOrderByCol = (u16)iCol;
      continue;
    }
    if( sqlite4ExprIsInteger(pE, &iCol) ){
      /* The ORDER BY term is an integer constant.  Again, set the column
      ** number so that sqlite4ResolveOrderGroupBy() will convert the
      ** order-by term to a copy of the result-set expression */
      if( iCol<1 ){
        resolveOutOfRangeError(pParse, zType, i+1, nResult);
        return 1;
      }
      pItem->iOrderByCol = (u16)iCol;
      continue;
    }

    /* Otherwise, treat the ORDER BY term as an ordinary expression */
    pItem->iOrderByCol = 0;
    if( sqlite4ResolveExprNames(pNC, pE) ){
      return 1;
    }
  }
  return sqlite4ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType);
}

/*
** Resolve names in the SELECT statement p and all of its descendents.
*/
static int resolveSelectStep(Walker *pWalker, Select *p){
  NameContext *pOuterNC;  /* Context that contains this SELECT */
  NameContext sNC;        /* Name context of this SELECT */
  int isCompound;         /* True if p is a compound select */
  int nCompound;          /* Number of compound terms processed so far */
  Parse *pParse;          /* Parsing context */
  ExprList *pEList;       /* Result set expression list */
  int i;                  /* Loop counter */
  ExprList *pGroupBy;     /* The GROUP BY clause */
  Select *pLeftmost;      /* Left-most of SELECT of a compound */
  sqlite4 *db;            /* Database connection */
  

  assert( p!=0 );
  if( p->selFlags & SF_Resolved ){
    return WRC_Prune;
  }
  pOuterNC = pWalker->u.pNC;
  pParse = pWalker->pParse;
  db = pParse->db;

  /* Normally sqlite4SelectExpand() will be called first and will have
  ** already expanded this SELECT.  However, if this is a subquery within
  ** an expression, sqlite4ResolveExprNames() will be called without a
  ** prior call to sqlite4SelectExpand().  When that happens, let
  ** sqlite4SelectPrep() do all of the processing for this SELECT.
  ** sqlite4SelectPrep() will invoke both sqlite4SelectExpand() and
  ** this routine in the correct order.
  */
  if( (p->selFlags & SF_Expanded)==0 ){
    sqlite4SelectPrep(pParse, p, pOuterNC);
    return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
  }

  isCompound = p->pPrior!=0;
  nCompound = 0;
  pLeftmost = p;
  while( p ){
    assert( (p->selFlags & SF_Expanded)!=0 );
    assert( (p->selFlags & SF_Resolved)==0 );
    p->selFlags |= SF_Resolved;

    /* Resolve the expressions in the LIMIT and OFFSET clauses. These
    ** are not allowed to refer to any names, so pass an empty NameContext.
    */
    memset(&sNC, 0, sizeof(sNC));
    sNC.pParse = pParse;
    if( sqlite4ResolveExprNames(&sNC, p->pLimit) ||
        sqlite4ResolveExprNames(&sNC, p->pOffset) ){
      return WRC_Abort;
    }
  
    /* Set up the local name-context to pass to sqlite4ResolveExprNames() to
    ** resolve the result-set expression list.
    */
    sNC.allowAgg = 1;
    sNC.pSrcList = p->pSrc;
    sNC.pNext = pOuterNC;
  
    /* Resolve names in the result set. */
    pEList = p->pEList;
    assert( pEList!=0 );
    for(i=0; i<pEList->nExpr; i++){
      Expr *pX = pEList->a[i].pExpr;
      if( sqlite4ResolveExprNames(&sNC, pX) ){
        return WRC_Abort;
      }
    }
  
    /* Recursively resolve names in all subqueries
    */
    for(i=0; i<p->pSrc->nSrc; i++){
      SrcListItem *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;
        sqlite4ResolveSelectNames(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);
      }
    }
  
    /* If there are no aggregate functions in the result-set, and no GROUP BY 
    ** expression, do not allow aggregates in any of the other expressions.
    */
    assert( (p->selFlags & SF_Aggregate)==0 );
    pGroupBy = p->pGroupBy;
    if( pGroupBy || sNC.hasAgg ){
      p->selFlags |= SF_Aggregate;
    }else{
      sNC.allowAgg = 0;
    }
  
    /* If a HAVING clause is present, then there must be a GROUP BY clause.
    */
    if( p->pHaving && !pGroupBy ){
      sqlite4ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
      return WRC_Abort;
    }
  
    /* Add the expression list to the name-context before parsing the
    ** other expressions in the SELECT statement. This is so that
    ** expressions in the WHERE clause (etc.) can refer to expressions by
    ** aliases in the result set.
    **
    ** Minor point: If this is the case, then the expression will be
    ** re-evaluated for each reference to it.
    */
    sNC.pEList = p->pEList;
    if( sqlite4ResolveExprNames(&sNC, p->pWhere) ||
       sqlite4ResolveExprNames(&sNC, p->pHaving)
    ){
      return WRC_Abort;
    }

    /* The ORDER BY and GROUP BY clauses may not refer to terms in
    ** outer queries 
    */
    sNC.pNext = 0;
    sNC.allowAgg = 1;

    /* Process the ORDER BY clause for singleton SELECT statements.
    ** The ORDER BY clause for compounds SELECT statements is handled
    ** below, after all of the result-sets for all of the elements of
    ** the compound have been resolved.
    */
    if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
      return WRC_Abort;
    }
    if( db->mallocFailed ){
      return WRC_Abort;
    }
  
    /* Resolve the GROUP BY clause.  At the same time, make sure 
    ** the GROUP BY clause does not contain aggregate functions.
    */
    if( pGroupBy ){
      ExprListItem *pItem;
    
      if( resolveOrderGroupBy(&sNC, p, pGroupBy, "GROUP") || db->mallocFailed ){
        return WRC_Abort;
      }
      for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){
        if( ExprHasProperty(pItem->pExpr, EP_Agg) ){
          sqlite4ErrorMsg(pParse, "aggregate functions are not allowed in "
              "the GROUP BY clause");
          return WRC_Abort;
        }
      }
    }

    /* Advance to the next term of the compound
    */
    p = p->pPrior;
    nCompound++;
  }

  /* Resolve the ORDER BY on a compound SELECT after all terms of
  ** the compound have been resolved.
  */
  if( isCompound && resolveCompoundOrderBy(pParse, pLeftmost) ){
    return WRC_Abort;
  }

  return WRC_Prune;
}

/*
** This routine walks an expression tree and resolves references to
** table columns and result-set columns.  At the same time, do error
** checking on function usage and set a flag if any aggregate functions
** are seen.
**
** To resolve table columns references we look for nodes (or subtrees) of the 
** form X.Y.Z or Y.Z or just Z where
**
**      X:   The name of a database.  Ex:  "main" or "temp" or
**           the symbolic name assigned to an ATTACH-ed database.
**
**      Y:   The name of a table in a FROM clause.  Or in a trigger
**           one of the special names "old" or "new".
**
**      Z:   The name of a column in table Y.
**
** The node at the root of the subtree is modified as follows:
**
**    Expr.op        Changed to TK_COLUMN
**    Expr.pTab      Points to the Table object for X.Y
**    Expr.iColumn   The column index in X.Y.  -1 for the rowid.
**    Expr.iTable    The VDBE cursor number for X.Y
**
**
** To resolve result-set references, look for expression nodes of the
** form Z (with no X and Y prefix) where the Z matches the right-hand
** size of an AS clause in the result-set of a SELECT.  The Z expression
** is replaced by a copy of the left-hand side of the result-set expression.
** Table-name and function resolution occurs on the substituted expression
** tree.  For example, in:
**
**      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
**
** The "x" term of the order by is replaced by "a+b" to render:
**
**      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
**
** Function calls are checked to make sure that the function is 
** defined and that the correct number of arguments are specified.
** If the function is an aggregate function, then the pNC->hasAgg is
** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
** If an expression contains aggregate functions then the EP_Agg
** property on the expression is set.
**
** An error message is left in pParse if anything is amiss.  The number
** if errors is returned.
*/
SQLITE4_PRIVATE int sqlite4ResolveExprNames( 
  NameContext *pNC,       /* Namespace to resolve expressions in. */
  Expr *pExpr             /* The expression to be analyzed. */
){
  int savedHasAgg;
  Walker w;

  if( pExpr==0 ) return 0;
#if SQLITE4_MAX_EXPR_DEPTH>0
  {
    Parse *pParse = pNC->pParse;
    if( sqlite4ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
      return 1;
    }
    pParse->nHeight += pExpr->nHeight;
  }
#endif
  savedHasAgg = pNC->hasAgg;
  pNC->hasAgg = 0;
  w.xExprCallback = resolveExprStep;
  w.xSelectCallback = resolveSelectStep;
  w.pParse = pNC->pParse;
  w.u.pNC = pNC;
  sqlite4WalkExpr(&w, pExpr);
#if SQLITE4_MAX_EXPR_DEPTH>0
  pNC->pParse->nHeight -= pExpr->nHeight;
#endif
  if( pNC->nErr>0 || w.pParse->nErr>0 ){
    ExprSetProperty(pExpr, EP_Error);
  }
  if( pNC->hasAgg ){
    ExprSetProperty(pExpr, EP_Agg);
  }else if( savedHasAgg ){
    pNC->hasAgg = 1;
  }
  return ExprHasProperty(pExpr, EP_Error);
}


/*
** Resolve all names in all expressions of a SELECT and in all
** decendents of the SELECT, including compounds off of p->pPrior,
** subqueries in expressions, and subqueries used as FROM clause
** terms.
**
** See sqlite4ResolveExprNames() for a description of the kinds of
** transformations that occur.
**
** All SELECT statements should have been expanded using
** sqlite4SelectExpand() prior to invoking this routine.
*/
SQLITE4_PRIVATE void sqlite4ResolveSelectNames(
  Parse *pParse,         /* The parser context */
  Select *p,             /* The SELECT statement being coded. */
  NameContext *pOuterNC  /* Name context for parent SELECT statement */
){
  Walker w;

  assert( p!=0 );
  w.xExprCallback = resolveExprStep;
  w.xSelectCallback = resolveSelectStep;
  w.pParse = pParse;
  w.u.pNC = pOuterNC;
  sqlite4WalkSelect(&w, p);
}

/************** End of resolve.c *********************************************/
/************** Begin file expr.c ********************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
*/

/*
** Return the 'affinity' of the expression pExpr if any.
**
** If pExpr is a column, a reference to a column via an 'AS' alias,
** or a sub-select with a column as the return value, then the 
** affinity of that column is returned. Otherwise, 0x00 is returned,
** indicating no affinity for the expression.
**
** i.e. the WHERE clause expresssions in the following statements all
** have an affinity:
**
** CREATE TABLE t1(a);
** SELECT * FROM t1 WHERE a;
** SELECT a AS b FROM t1 WHERE b;
** SELECT * FROM t1 WHERE (select a from t1);
*/
SQLITE4_PRIVATE char sqlite4ExprAffinity(Expr *pExpr){
  int op = pExpr->op;
  if( op==TK_SELECT ){
    assert( pExpr->flags&EP_xIsSelect );
    return sqlite4ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
  }
#ifndef SQLITE4_OMIT_CAST
  if( op==TK_CAST ){
    assert( !ExprHasProperty(pExpr, EP_IntValue) );
    return sqlite4AffinityType(pExpr->u.zToken);
  }
#endif
  if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) 
   && pExpr->pTab!=0
  ){
    /* op==TK_REGISTER && pExpr->pTab!=0 happens when pExpr was originally
    ** a TK_COLUMN but was previously evaluated and cached in a register */
    int j = pExpr->iColumn;
    if( j<0 ) return SQLITE4_AFF_INTEGER;
    assert( pExpr->pTab && j<pExpr->pTab->nCol );
    return pExpr->pTab->aCol[j].affinity;
  }
  return pExpr->affinity;
}

/*
** Set the explicit collating sequence for an expression to the
** collating sequence supplied in the second argument.
*/
SQLITE4_PRIVATE Expr *sqlite4ExprSetColl(Expr *pExpr, CollSeq *pColl){
  if( pExpr && pColl ){
    pExpr->pColl = pColl;
    pExpr->flags |= EP_ExpCollate;
  }
  return pExpr;
}

/*
** Set the collating sequence for expression pExpr to be the collating
** sequence named by pToken.   Return a pointer to the revised expression.
** The collating sequence is marked as "explicit" using the EP_ExpCollate
** flag.  An explicit collating sequence will override implicit
** collating sequences.
*/
SQLITE4_PRIVATE Expr *sqlite4ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
  char *zColl = 0;            /* Dequoted name of collation sequence */
  CollSeq *pColl;
  sqlite4 *db = pParse->db;
  zColl = sqlite4NameFromToken(db, pCollName);
  pColl = sqlite4LocateCollSeq(pParse, zColl);
  sqlite4ExprSetColl(pExpr, pColl);
  sqlite4DbFree(db, zColl);
  return pExpr;
}

/*
** Return the default collation sequence for the expression pExpr. If
** there is no default collation type, return 0.
*/
SQLITE4_PRIVATE CollSeq *sqlite4ExprCollSeq(Parse *pParse, Expr *pExpr){
  CollSeq *pColl = 0;
  Expr *p = pExpr;
  while( p ){
    int op;
    pColl = p->pColl;
    if( pColl ) break;
    op = p->op;
    if( p->pTab!=0 && (
        op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER
    )){
      /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
      ** a TK_COLUMN but was previously evaluated and cached in a register */
      const char *zColl;
      int j = p->iColumn;
      if( j>=0 ){
        sqlite4 *db = pParse->db;
        zColl = p->pTab->aCol[j].zColl;
        pColl = sqlite4FindCollSeq(db, zColl, 0);
        pExpr->pColl = pColl;
      }
      break;
    }
    if( op!=TK_CAST && op!=TK_UPLUS ){
      break;
    }
    p = p->pLeft;
  }
  if( sqlite4CheckCollSeq(pParse, pColl) ){ 
    pColl = 0;
  }
  return pColl;
}

/*
** pExpr is an operand of a comparison operator.  aff2 is the
** type affinity of the other operand.  This routine returns the
** type affinity that should be used for the comparison operator.
*/
SQLITE4_PRIVATE char sqlite4CompareAffinity(Expr *pExpr, char aff2){
  char aff1 = sqlite4ExprAffinity(pExpr);
  if( aff1 && aff2 ){
    /* Both sides of the comparison are columns. If one has numeric
    ** affinity, use that. Otherwise use no affinity.
    */
    if( sqlite4IsNumericAffinity(aff1) || sqlite4IsNumericAffinity(aff2) ){
      return SQLITE4_AFF_NUMERIC;
    }else{
      return SQLITE4_AFF_NONE;
    }
  }else if( !aff1 && !aff2 ){
    /* Neither side of the comparison is a column.  Compare the
    ** results directly.
    */
    return SQLITE4_AFF_NONE;
  }else{
    /* One side is a column, the other is not. Use the columns affinity. */
    assert( aff1==0 || aff2==0 );
    return (aff1 + aff2);
  }
}

/*
** pExpr is a comparison operator.  Return the type affinity that should
** be applied to both operands prior to doing the comparison.
*/
static char comparisonAffinity(Expr *pExpr){
  char aff;
  assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
          pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
          pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
  assert( pExpr->pLeft );
  aff = sqlite4ExprAffinity(pExpr->pLeft);
  if( pExpr->pRight ){
    aff = sqlite4CompareAffinity(pExpr->pRight, aff);
  }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
    aff = sqlite4CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
  }else if( !aff ){
    aff = SQLITE4_AFF_NONE;
  }
  return aff;
}

/*
** pExpr is a comparison expression, eg. '=', '<', IN(...) etc.
** idx_affinity is the affinity of an indexed column. Return true
** if the index with affinity idx_affinity may be used to implement
** the comparison in pExpr.
*/
SQLITE4_PRIVATE int sqlite4IndexAffinityOk(Expr *pExpr, char idx_affinity){
  char aff = comparisonAffinity(pExpr);
  switch( aff ){
    case SQLITE4_AFF_NONE:
      return 1;
    case SQLITE4_AFF_TEXT:
      return idx_affinity==SQLITE4_AFF_TEXT;
    default:
      return sqlite4IsNumericAffinity(idx_affinity);
  }
}

/*
** Return the P5 value that should be used for a binary comparison
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
*/
static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
  u8 aff = (char)sqlite4ExprAffinity(pExpr2);
  aff = (u8)sqlite4CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
  return aff;
}

/*
** Return a pointer to the collation sequence that should be used by
** a binary comparison operator comparing pLeft and pRight.
**
** If the left hand expression has a collating sequence type, then it is
** used. Otherwise the collation sequence for the right hand expression
** is used, or the default (BINARY) if neither expression has a collating
** type.
**
** Argument pRight (but not pLeft) may be a null pointer. In this case,
** it is not considered.
*/
SQLITE4_PRIVATE CollSeq *sqlite4BinaryCompareCollSeq(
  Parse *pParse, 
  Expr *pLeft, 
  Expr *pRight
){
  CollSeq *pColl;
  assert( pLeft );
  if( pLeft->flags & EP_ExpCollate ){
    assert( pLeft->pColl );
    pColl = pLeft->pColl;
  }else if( pRight && pRight->flags & EP_ExpCollate ){
    assert( pRight->pColl );
    pColl = pRight->pColl;
  }else{
    pColl = sqlite4ExprCollSeq(pParse, pLeft);
    if( !pColl ){
      pColl = sqlite4ExprCollSeq(pParse, pRight);
    }
  }
  return pColl;
}

/*
** Generate code for a comparison operator.
*/
static int codeCompare(
  Parse *pParse,    /* The parsing (and code generating) context */
  Expr *pLeft,      /* The left operand */
  Expr *pRight,     /* The right operand */
  int opcode,       /* The comparison opcode */
  int in1, int in2, /* Register holding operands */
  int dest,         /* Jump here if true.  */
  int jumpIfNull    /* If true, jump if either operand is NULL */
){
  int p5;
  int addr;
  CollSeq *p4;

  p4 = sqlite4BinaryCompareCollSeq(pParse, pLeft, pRight);
  p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
  addr = sqlite4VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
                           (void*)p4, P4_COLLSEQ);
  sqlite4VdbeChangeP5(pParse->pVdbe, (u8)p5);
  return addr;
}

#if SQLITE4_MAX_EXPR_DEPTH>0
/*
** Check that argument nHeight is less than or equal to the maximum
** expression depth allowed. If it is not, leave an error message in
** pParse.
*/
SQLITE4_PRIVATE int sqlite4ExprCheckHeight(Parse *pParse, int nHeight){
  int rc = SQLITE4_OK;
  int mxHeight = pParse->db->aLimit[SQLITE4_LIMIT_EXPR_DEPTH];
  if( nHeight>mxHeight ){
    sqlite4ErrorMsg(pParse, 
       "Expression tree is too large (maximum depth %d)", mxHeight
    );
    rc = SQLITE4_ERROR;
  }
  return rc;
}

/* The following three functions, heightOfExpr(), heightOfExprList()
** and heightOfSelect(), are used to determine the maximum height
** of any expression tree referenced by the structure passed as the
** first argument.
**
** If this maximum height is greater than the current value pointed
** to by pnHeight, the second parameter, then set *pnHeight to that
** value.
*/
static void heightOfExpr(Expr *p, int *pnHeight){
  if( p ){
    if( p->nHeight>*pnHeight ){
      *pnHeight = p->nHeight;
    }
  }
}
static void heightOfExprList(ExprList *p, int *pnHeight){
  if( p ){
    int i;
    for(i=0; i<p->nExpr; i++){
      heightOfExpr(p->a[i].pExpr, pnHeight);
    }
  }
}
static void heightOfSelect(Select *p, int *pnHeight){
  if( p ){
    heightOfExpr(p->pWhere, pnHeight);
    heightOfExpr(p->pHaving, pnHeight);
    heightOfExpr(p->pLimit, pnHeight);
    heightOfExpr(p->pOffset, pnHeight);
    heightOfExprList(p->pEList, pnHeight);
    heightOfExprList(p->pGroupBy, pnHeight);
    heightOfExprList(p->pOrderBy, pnHeight);
    heightOfSelect(p->pPrior, pnHeight);
  }
}

/*
** Set the Expr.nHeight variable in the structure passed as an 
** argument. An expression with no children, Expr.pList or 
** Expr.pSelect member has a height of 1. Any other expression
** has a height equal to the maximum height of any other 
** referenced Expr plus one.
*/
static void exprSetHeight(Expr *p){
  int nHeight = 0;
  heightOfExpr(p->pLeft, &nHeight);
  heightOfExpr(p->pRight, &nHeight);
  if( ExprHasProperty(p, EP_xIsSelect) ){
    heightOfSelect(p->x.pSelect, &nHeight);
  }else{
    heightOfExprList(p->x.pList, &nHeight);
  }
  p->nHeight = nHeight + 1;
}

/*
** Set the Expr.nHeight variable using the exprSetHeight() function. If
** the height is greater than the maximum allowed expression depth,
** leave an error in pParse.
*/
SQLITE4_PRIVATE void sqlite4ExprSetHeight(Parse *pParse, Expr *p){
  exprSetHeight(p);
  sqlite4ExprCheckHeight(pParse, p->nHeight);
}

/*
** Return the maximum height of any expression tree referenced
** by the select statement passed as an argument.
*/
SQLITE4_PRIVATE int sqlite4SelectExprHeight(Select *p){
  int nHeight = 0;
  heightOfSelect(p, &nHeight);
  return nHeight;
}
#else
  #define exprSetHeight(y)
#endif /* SQLITE4_MAX_EXPR_DEPTH>0 */

/*
** This routine is the core allocator for Expr nodes.
**
** Construct a new expression node and return a pointer to it.  Memory
** for this node and for the pToken argument is a single allocation
** obtained from sqlite4DbMalloc().  The calling function
** is responsible for making sure the node eventually gets freed.
**
** If dequote is true, then the token (if it exists) is dequoted.
** If dequote is false, no dequoting is performance.  The deQuote
** parameter is ignored if pToken is NULL or if the token does not
** appear to be quoted.
**
** Special case:  If op==TK_INTEGER and pToken points to a string that
** can be translated into a 32-bit integer, then the token is not
** stored in u.zToken.  Instead, the integer values is written
** into u.iValue and the EP_IntValue flag is set.  No extra storage
** is allocated to hold the integer text and the dequote flag is ignored.
*/
SQLITE4_PRIVATE Expr *sqlite4ExprAlloc(
  sqlite4 *db,            /* Handle for sqlite4DbMallocZero() (may be null) */
  int op,                 /* Expression opcode */
  const Token *pToken,    /* Token argument.  Might be NULL */
  int dequote             /* True to dequote */
){
  Expr *pNew;
  int nExtra = 0;
  int iValue = 0;

  if( pToken ){
    if( op!=TK_INTEGER || pToken->z==0
          || sqlite4GetInt32(pToken->z, &iValue)==0 ){
      nExtra = pToken->n+1;
      assert( iValue>=0 );
    }
  }
  pNew = sqlite4DbMallocZero(db, sizeof(Expr)+nExtra);
  if( pNew ){
    pNew->op = (u8)op;
    pNew->iAgg = -1;
    if( pToken ){
      if( nExtra==0 ){
        pNew->flags |= EP_IntValue;
        pNew->u.iValue = iValue;
      }else{
        int c;
        pNew->u.zToken = (char*)&pNew[1];
        assert( pToken->z!=0 || pToken->n==0 );
        if( pToken->n ) memcpy(pNew->u.zToken, pToken->z, pToken->n);
        pNew->u.zToken[pToken->n] = 0;
        if( dequote && nExtra>=3 
             && ((c = pToken->z[0])=='\'' || c=='"' || c=='[') ){
          sqlite4Dequote(pNew->u.zToken);
        }
      }
    }
#if SQLITE4_MAX_EXPR_DEPTH>0
    pNew->nHeight = 1;
#endif  
  }
  return pNew;
}

/*
** Allocate a new expression node from a zero-terminated token that has
** already been dequoted.
*/
SQLITE4_PRIVATE Expr *sqlite4Expr(
  sqlite4 *db,            /* Handle for sqlite4DbMallocZero() (may be null) */
  int op,                 /* Expression opcode */
  const char *zToken      /* Token argument.  Might be NULL */
){
  Token x;
  x.z = zToken;
  x.n = zToken ? sqlite4Strlen30(zToken) : 0;
  return sqlite4ExprAlloc(db, op, &x, 0);
}

/*
** Attach subtrees pLeft and pRight to the Expr node pRoot.
**
** If pRoot==NULL that means that a memory allocation error has occurred.
** In that case, delete the subtrees pLeft and pRight.
*/
SQLITE4_PRIVATE void sqlite4ExprAttachSubtrees(
  sqlite4 *db,
  Expr *pRoot,
  Expr *pLeft,
  Expr *pRight
){
  if( pRoot==0 ){
    assert( db->mallocFailed );
    sqlite4ExprDelete(db, pLeft);
    sqlite4ExprDelete(db, pRight);
  }else{
    if( pRight ){
      pRoot->pRight = pRight;
      if( pRight->flags & EP_ExpCollate ){
        pRoot->flags |= EP_ExpCollate;
        pRoot->pColl = pRight->pColl;
      }
    }
    if( pLeft ){
      pRoot->pLeft = pLeft;
      if( pLeft->flags & EP_ExpCollate ){
        pRoot->flags |= EP_ExpCollate;
        pRoot->pColl = pLeft->pColl;
      }
    }
    exprSetHeight(pRoot);
  }
}

/*
** Allocate a Expr node which joins as many as two subtrees.
**
** One or both of the subtrees can be NULL.  Return a pointer to the new
** Expr node.  Or, if an OOM error occurs, set pParse->db->mallocFailed,
** free the subtrees and return NULL.
*/
SQLITE4_PRIVATE Expr *sqlite4PExpr(
  Parse *pParse,          /* Parsing context */
  int op,                 /* Expression opcode */
  Expr *pLeft,            /* Left operand */
  Expr *pRight,           /* Right operand */
  const Token *pToken     /* Argument token */
){
  Expr *p = sqlite4ExprAlloc(pParse->db, op, pToken, 1);
  sqlite4ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
  if( p ) {
    sqlite4ExprCheckHeight(pParse, p->nHeight);
  }
  return p;
}

/*
** Join two expressions using an AND operator.  If either expression is
** NULL, then just return the other expression.
*/
SQLITE4_PRIVATE Expr *sqlite4ExprAnd(sqlite4 *db, Expr *pLeft, Expr *pRight){
  if( pLeft==0 ){
    return pRight;
  }else if( pRight==0 ){
    return pLeft;
  }else{
    Expr *pNew = sqlite4ExprAlloc(db, TK_AND, 0, 0);
    sqlite4ExprAttachSubtrees(db, pNew, pLeft, pRight);
    return pNew;
  }
}

/*
** Construct a new expression node for a function with multiple
** arguments.
*/
SQLITE4_PRIVATE Expr *sqlite4ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
  Expr *pNew;
  sqlite4 *db = pParse->db;
  assert( pToken );
  pNew = sqlite4ExprAlloc(db, TK_FUNCTION, pToken, 1);
  if( pNew==0 ){
    sqlite4ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
    return 0;
  }
  pNew->x.pList = pList;
  assert( !ExprHasProperty(pNew, EP_xIsSelect) );
  sqlite4ExprSetHeight(pParse, pNew);
  return pNew;
}

/*
** Assign a variable number to an expression that encodes a wildcard
** in the original SQL statement.  
**
** Wildcards consisting of a single "?" are assigned the next sequential
** variable number.
**
** Wildcards of the form "?nnn" are assigned the number "nnn".  We make
** sure "nnn" is not too be to avoid a denial of service attack when
** the SQL statement comes from an external source.
**
** Wildcards of the form ":aaa", "@aaa", or "$aaa" are assigned the same number
** as the previous instance of the same wildcard.  Or if this is the first
** instance of the wildcard, the next sequenial variable number is
** assigned.
*/
SQLITE4_PRIVATE void sqlite4ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
  sqlite4 *db = pParse->db;
  const char *z;

  if( pExpr==0 ) return;
  assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
  z = pExpr->u.zToken;
  assert( z!=0 );
  assert( z[0]!=0 );
  if( z[1]==0 ){
    /* Wildcard of the form "?".  Assign the next variable number */
    assert( z[0]=='?' );
    pExpr->iColumn = (ynVar)(++pParse->nVar);
  }else{
    ynVar x = 0;
    u32 n = sqlite4Strlen30(z);
    if( z[0]=='?' ){
      /* Wildcard of the form "?nnn".  Convert "nnn" to an integer and
      ** use it as the variable number */
      i64 i;
      int bOk = 0==sqlite4Atoi64(&z[1], &i, n-1, SQLITE4_UTF8);
      pExpr->iColumn = x = (ynVar)i;
      testcase( i==0 );
      testcase( i==1 );
      testcase( i==db->aLimit[SQLITE4_LIMIT_VARIABLE_NUMBER]-1 );
      testcase( i==db->aLimit[SQLITE4_LIMIT_VARIABLE_NUMBER] );
      if( bOk==0 || i<1 || i>db->aLimit[SQLITE4_LIMIT_VARIABLE_NUMBER] ){
        sqlite4ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
            db->aLimit[SQLITE4_LIMIT_VARIABLE_NUMBER]);
        x = 0;
      }
      if( i>pParse->nVar ){
        pParse->nVar = (int)i;
      }
    }else{
      /* Wildcards like ":aaa", "$aaa" or "@aaa".  Reuse the same variable
      ** number as the prior appearance of the same name, or if the name
      ** has never appeared before, reuse the same variable number
      */
      ynVar i;
      for(i=0; i<pParse->nzVar; i++){
        if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){
          pExpr->iColumn = x = (ynVar)i+1;
          break;
        }
      }
      if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
    }
    if( x>0 ){
      if( x>pParse->nzVar ){
        char **a;
        a = sqlite4DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
        if( a==0 ) return;  /* Error reported through db->mallocFailed */
        pParse->azVar = a;
        memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
        pParse->nzVar = x;
      }
      if( z[0]!='?' || pParse->azVar[x-1]==0 ){
        sqlite4DbFree(db, pParse->azVar[x-1]);
        pParse->azVar[x-1] = sqlite4DbStrNDup(db, z, n);
      }
    }
  } 
  if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE4_LIMIT_VARIABLE_NUMBER] ){
    sqlite4ErrorMsg(pParse, "too many SQL variables");
  }
}

/*
** Recursively delete an expression tree.
*/
SQLITE4_PRIVATE void sqlite4ExprDelete(sqlite4 *db, Expr *p){
  if( p==0 ) return;
  /* Sanity check: Assert that the IntValue is non-negative if it exists */
  assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
  if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
    sqlite4ExprDelete(db, p->pLeft);
    sqlite4ExprDelete(db, p->pRight);
    if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){
      sqlite4DbFree(db, p->u.zToken);
    }
    if( ExprHasProperty(p, EP_xIsSelect) ){
      sqlite4SelectDelete(db, p->x.pSelect);
    }else{
      sqlite4ExprListDelete(db, p->x.pList);
    }
  }
  if( !ExprHasProperty(p, EP_Static) ){
    sqlite4DbFree(db, p);
  }
}

/*
** Return the number of bytes allocated for the expression structure 
** passed as the first argument. This is always one of EXPR_FULLSIZE,
** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
*/
static int exprStructSize(Expr *p){
  if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
  if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
  return EXPR_FULLSIZE;
}

/*
** The dupedExpr*Size() routines each return the number of bytes required
** to store a copy of an expression or expression tree.  They differ in
** how much of the tree is measured.
**
**     dupedExprStructSize()     Size of only the Expr structure 
**     dupedExprNodeSize()       Size of Expr + space for token
**     dupedExprSize()           Expr + token + subtree components
**
***************************************************************************
**
** The dupedExprStructSize() function returns two values OR-ed together:  
** (1) the space required for a copy of the Expr structure only and 
** (2) the EP_xxx flags that indicate what the structure size should be.
** The return values is always one of:
**
**      EXPR_FULLSIZE
**      EXPR_REDUCEDSIZE   | EP_Reduced
**      EXPR_TOKENONLYSIZE | EP_TokenOnly
**
** The size of the structure can be found by masking the return value
** of this routine with 0xfff.  The flags can be found by masking the
** return value with EP_Reduced|EP_TokenOnly.
**
** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size
** (unreduced) Expr objects as they or originally constructed by the parser.
** During expression analysis, extra information is computed and moved into
** later parts of teh Expr object and that extra information might get chopped
** off if the expression is reduced.  Note also that it does not work to
** make a EXPRDUP_REDUCE copy of a reduced expression.  It is only legal
** to reduce a pristine expression tree from the parser.  The implementation
** of dupedExprStructSize() contain multiple assert() statements that attempt
** to enforce this constraint.
*/
static int dupedExprStructSize(Expr *p, int flags){
  int nSize;
  assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
  if( 0==(flags&EXPRDUP_REDUCE) ){
    nSize = EXPR_FULLSIZE;
  }else{
    assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
    assert( !ExprHasProperty(p, EP_FromJoin) ); 
    assert( (p->flags2 & EP2_MallocedToken)==0 );
    assert( (p->flags2 & EP2_Irreducible)==0 );
    if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
      nSize = EXPR_REDUCEDSIZE | EP_Reduced;
    }else{
      nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
    }
  }
  return nSize;
}

/*
** This function returns the space in bytes required to store the copy 
** of the Expr structure and a copy of the Expr.u.zToken string (if that
** string is defined.)
*/
static int dupedExprNodeSize(Expr *p, int flags){
  int nByte = dupedExprStructSize(p, flags) & 0xfff;
  if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
    nByte += sqlite4Strlen30(p->u.zToken)+1;
  }
  return ROUND8(nByte);
}

/*
** Return the number of bytes required to create a duplicate of the 
** expression passed as the first argument. The second argument is a
** mask containing EXPRDUP_XXX flags.
**
** The value returned includes space to create a copy of the Expr struct
** itself and the buffer referred to by Expr.u.zToken, if any.
**
** If the EXPRDUP_REDUCE flag is set, then the return value includes 
** space to duplicate all Expr nodes in the tree formed by Expr.pLeft 
** and Expr.pRight variables (but not for any structures pointed to or 
** descended from the Expr.x.pList or Expr.x.pSelect variables).
*/
static int dupedExprSize(Expr *p, int flags){
  int nByte = 0;
  if( p ){
    nByte = dupedExprNodeSize(p, flags);
    if( flags&EXPRDUP_REDUCE ){
      nByte += dupedExprSize(p->pLeft, flags) + dupedExprSize(p->pRight, flags);
    }
  }
  return nByte;
}

/*
** This function is similar to sqlite4ExprDup(), except that if pzBuffer 
** is not NULL then *pzBuffer is assumed to point to a buffer large enough 
** to store the copy of expression p, the copies of p->u.zToken
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
** if any. Before returning, *pzBuffer is set to the first byte passed the
** portion of the buffer copied into by this function.
*/
static Expr *exprDup(sqlite4 *db, Expr *p, int flags, u8 **pzBuffer){
  Expr *pNew = 0;                      /* Value to return */
  if( p ){
    const int isReduced = (flags&EXPRDUP_REDUCE);
    u8 *zAlloc;
    u32 staticFlag = 0;

    assert( pzBuffer==0 || isReduced );

    /* Figure out where to write the new Expr structure. */
    if( pzBuffer ){
      zAlloc = *pzBuffer;
      staticFlag = EP_Static;
    }else{
      zAlloc = sqlite4DbMallocRaw(db, dupedExprSize(p, flags));
    }
    pNew = (Expr *)zAlloc;

    if( pNew ){
      /* Set nNewSize to the size allocated for the structure pointed to
      ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
      ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
      ** by the copy of the p->u.zToken string (if any).
      */
      const unsigned nStructSize = dupedExprStructSize(p, flags);
      const int nNewSize = nStructSize & 0xfff;
      int nToken;
      if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
        nToken = sqlite4Strlen30(p->u.zToken) + 1;
      }else{
        nToken = 0;
      }
      if( isReduced ){
        assert( ExprHasProperty(p, EP_Reduced)==0 );
        memcpy(zAlloc, p, nNewSize);
      }else{
        int nSize = exprStructSize(p);
        memcpy(zAlloc, p, nSize);
        memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
      }

      /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
      pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
      pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
      pNew->flags |= staticFlag;

      /* Copy the p->u.zToken string, if any. */
      if( nToken ){
        char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
        memcpy(zToken, p->u.zToken, nToken);
      }

      if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
        /* Fill in the pNew->x.pSelect or pNew->x.pList member. */
        if( ExprHasProperty(p, EP_xIsSelect) ){
          pNew->x.pSelect = sqlite4SelectDup(db, p->x.pSelect, isReduced);
        }else{
          pNew->x.pList = sqlite4ExprListDup(db, p->x.pList, isReduced);
        }
      }

      /* Fill in pNew->pLeft and pNew->pRight. */
      if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly) ){
        zAlloc += dupedExprNodeSize(p, flags);
        if( ExprHasProperty(pNew, EP_Reduced) ){
          pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
          pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc);
        }
        if( pzBuffer ){
          *pzBuffer = zAlloc;
        }
      }else{
        pNew->flags2 = 0;
        if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
          pNew->pLeft = sqlite4ExprDup(db, p->pLeft, 0);
          pNew->pRight = sqlite4ExprDup(db, p->pRight, 0);
        }
      }

    }
  }
  return pNew;
}

/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements.  The copies can
** be deleted (by being passed to their respective ...Delete() routines)
** without effecting the originals.
**
** The expression list, ID, and source lists return by sqlite4ExprListDup(),
** sqlite4IdListDup(), and sqlite4SrcListDup() can not be further expanded 
** by subsequent calls to sqlite*ListAppend() routines.
**
** Any tables that the SrcList might point to are not duplicated.
**
** The flags parameter contains a combination of the EXPRDUP_XXX flags.
** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
** truncated version of the usual Expr structure that will be stored as
** part of the in-memory representation of the database schema.
*/
SQLITE4_PRIVATE Expr *sqlite4ExprDup(sqlite4 *db, Expr *p, int flags){
  return exprDup(db, p, flags, 0);
}
SQLITE4_PRIVATE ExprList *sqlite4ExprListDup(sqlite4 *db, ExprList *p, int flags){
  ExprList *pNew;
  ExprListItem *pItem, *pOldItem;
  int i;
  if( p==0 ) return 0;
  pNew = sqlite4DbMallocRaw(db, sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->iECursor = 0;
  pNew->nExpr = pNew->nAlloc = p->nExpr;
  pNew->a = pItem = sqlite4DbMallocRaw(db,  p->nExpr*sizeof(p->a[0]) );
  if( pItem==0 ){
    sqlite4DbFree(db, pNew);
    return 0;
  } 
  pOldItem = p->a;
  for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
    Expr *pOldExpr = pOldItem->pExpr;
    pItem->pExpr = sqlite4ExprDup(db, pOldExpr, flags);
    pItem->zName = sqlite4DbStrDup(db, pOldItem->zName);
    pItem->zSpan = sqlite4DbStrDup(db, pOldItem->zSpan);
    pItem->sortOrder = pOldItem->sortOrder;
    pItem->done = 0;
    pItem->iOrderByCol = pOldItem->iOrderByCol;
    pItem->iAlias = pOldItem->iAlias;
  }
  return pNew;
}

/*
** If cursors, triggers, views and subqueries are all omitted from
** the build, then none of the following routines, except for 
** sqlite4SelectDup(), can be called. sqlite4SelectDup() is sometimes
** called with a NULL argument.
*/
#if !defined(SQLITE4_OMIT_VIEW) || !defined(SQLITE4_OMIT_TRIGGER) \
 || !defined(SQLITE4_OMIT_SUBQUERY)
SQLITE4_PRIVATE SrcList *sqlite4SrcListDup(sqlite4 *db, SrcList *p, int flags){
  SrcList *pNew;
  int i;
  int nByte;
  if( p==0 ) return 0;
  nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
  pNew = sqlite4DbMallocRaw(db, nByte );
  if( pNew==0 ) return 0;
  pNew->nSrc = pNew->nAlloc = p->nSrc;
  for(i=0; i<p->nSrc; i++){
    SrcListItem *pNewItem = &pNew->a[i];
    SrcListItem *pOldItem = &p->a[i];
    Table *pTab;
    pNewItem->zDatabase = sqlite4DbStrDup(db, pOldItem->zDatabase);
    pNewItem->zName = sqlite4DbStrDup(db, pOldItem->zName);
    pNewItem->zAlias = sqlite4DbStrDup(db, pOldItem->zAlias);
    pNewItem->jointype = pOldItem->jointype;
    pNewItem->iCursor = pOldItem->iCursor;
    pNewItem->addrFillSub = pOldItem->addrFillSub;
    pNewItem->regReturn = pOldItem->regReturn;
    pNewItem->isCorrelated = pOldItem->isCorrelated;
    pNewItem->zIndex = sqlite4DbStrDup(db, pOldItem->zIndex);
    pNewItem->notIndexed = pOldItem->notIndexed;
    pNewItem->pIndex = pOldItem->pIndex;
    pTab = pNewItem->pTab = pOldItem->pTab;
    if( pTab ){
      pTab->nRef++;
    }
    pNewItem->pSelect = sqlite4SelectDup(db, pOldItem->pSelect, flags);
    pNewItem->pOn = sqlite4ExprDup(db, pOldItem->pOn, flags);
    pNewItem->pUsing = sqlite4IdListDup(db, pOldItem->pUsing);
    pNewItem->colUsed = pOldItem->colUsed;
  }
  return pNew;
}
SQLITE4_PRIVATE IdList *sqlite4IdListDup(sqlite4 *db, IdList *p){
  IdList *pNew;
  int i;
  if( p==0 ) return 0;
  pNew = sqlite4DbMallocRaw(db, sizeof(*pNew) );
  if( pNew==0 ) return 0;
  pNew->nId = pNew->nAlloc = p->nId;
  pNew->a = sqlite4DbMallocRaw(db, p->nId*sizeof(p->a[0]) );
  if( pNew->a==0 ){
    sqlite4DbFree(db, pNew);
    return 0;
  }
  for(i=0; i<p->nId; i++){
    IdListItem *pNewItem = &pNew->a[i];
    IdListItem *pOldItem = &p->a[i];
    pNewItem->zName = sqlite4DbStrDup(db, pOldItem->zName);
    pNewItem->idx = pOldItem->idx;
  }
  return pNew;
}
SQLITE4_PRIVATE Select *sqlite4SelectDup(sqlite4 *db, Select *p, int flags){
  Select *pNew, *pPrior;
  if( p==0 ) return 0;
  pNew = sqlite4DbMallocRaw(db, sizeof(*p) );
  if( pNew==0 ) return 0;
  pNew->pEList = sqlite4ExprListDup(db, p->pEList, flags);
  pNew->pSrc = sqlite4SrcListDup(db, p->pSrc, flags);
  pNew->pWhere = sqlite4ExprDup(db, p->pWhere, flags);
  pNew->pGroupBy = sqlite4ExprListDup(db, p->pGroupBy, flags);
  pNew->pHaving = sqlite4ExprDup(db, p->pHaving, flags);
  pNew->pOrderBy = sqlite4ExprListDup(db, p->pOrderBy, flags);
  pNew->op = p->op;
  pNew->pPrior = pPrior = sqlite4SelectDup(db, p->pPrior, flags);
  if( pPrior ) pPrior->pNext = pNew;
  pNew->pNext = 0;
  pNew->pLimit = sqlite4ExprDup(db, p->pLimit, flags);
  pNew->pOffset = sqlite4ExprDup(db, p->pOffset, flags);
  pNew->iLimit = 0;
  pNew->iOffset = 0;
  pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
  pNew->pRightmost = 0;
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;
  pNew->addrOpenEphm[2] = -1;
  return pNew;
}
#else
SQLITE4_PRIVATE Select *sqlite4SelectDup(sqlite4 *db, Select *p, int flags){
  assert( p==0 );
  return 0;
}
#endif


/*
** Add a new element to the end of an expression list.  If pList is
** initially NULL, then create a new expression list.
**
** If a memory allocation error occurs, the entire list is freed and
** NULL is returned.  If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
*/
SQLITE4_PRIVATE ExprList *sqlite4ExprListAppend(
  Parse *pParse,          /* Parsing context */
  ExprList *pList,        /* List to which to append. Might be NULL */
  Expr *pExpr             /* Expression to be appended. Might be NULL */
){
  sqlite4 *db = pParse->db;
  if( pList==0 ){
    pList = sqlite4DbMallocZero(db, sizeof(ExprList) );
    if( pList==0 ){
      goto no_mem;
    }
    assert( pList->nAlloc==0 );
  }
  if( pList->nAlloc<=pList->nExpr ){
    ExprListItem *a;
    int n = pList->nAlloc*2 + 4;
    a = sqlite4DbRealloc(db, pList->a, n*sizeof(pList->a[0]));
    if( a==0 ){
      goto no_mem;
    }
    pList->a = a;
    pList->nAlloc = sqlite4DbMallocSize(db, a)/sizeof(a[0]);
  }
  assert( pList->a!=0 );
  if( 1 ){
    ExprListItem *pItem = &pList->a[pList->nExpr++];
    memset(pItem, 0, sizeof(*pItem));
    pItem->pExpr = pExpr;
  }
  return pList;

no_mem:     
  /* Avoid leaking memory if malloc has failed. */
  sqlite4ExprDelete(db, pExpr);
  sqlite4ExprListDelete(db, pList);
  return 0;
}

/*
** Set the ExprList.a[].zName element of the most recently added item
** on the expression list.
**
** pList might be NULL following an OOM error.  But pName should never be
** NULL.  If a memory allocation fails, the pParse->db->mallocFailed flag
** is set.
*/
SQLITE4_PRIVATE void sqlite4ExprListSetName(
  Parse *pParse,          /* Parsing context */
  ExprList *pList,        /* List to which to add the span. */
  Token *pName,           /* Name to be added */
  int dequote             /* True to cause the name to be dequoted */
){
  assert( pList!=0 || pParse->db->mallocFailed!=0 );
  if( pList ){
    ExprListItem *pItem;
    assert( pList->nExpr>0 );
    pItem = &pList->a[pList->nExpr-1];
    assert( pItem->zName==0 );
    pItem->zName = sqlite4DbStrNDup(pParse->db, pName->z, pName->n);
    if( dequote && pItem->zName ) sqlite4Dequote(pItem->zName);
  }
}

/*
** Set the ExprList.a[].zSpan element of the most recently added item
** on the expression list.
**
** pList might be NULL following an OOM error.  But pSpan should never be
** NULL.  If a memory allocation fails, the pParse->db->mallocFailed flag
** is set.
*/
SQLITE4_PRIVATE void sqlite4ExprListSetSpan(
  Parse *pParse,          /* Parsing context */
  ExprList *pList,        /* List to which to add the span. */
  ExprSpan *pSpan         /* The span to be added */
){
  sqlite4 *db = pParse->db;
  assert( pList!=0 || db->mallocFailed!=0 );
  if( pList ){
    ExprListItem *pItem = &pList->a[pList->nExpr-1];
    assert( pList->nExpr>0 );
    assert( db->mallocFailed || pItem->pExpr==pSpan->pExpr );
    sqlite4DbFree(db, pItem->zSpan);
    pItem->zSpan = sqlite4DbStrNDup(db, (char*)pSpan->zStart,
                                    (int)(pSpan->zEnd - pSpan->zStart));
  }
}

/*
** If the expression list pEList contains more than iLimit elements,
** leave an error message in pParse.
*/
SQLITE4_PRIVATE void sqlite4ExprListCheckLength(
  Parse *pParse,
  ExprList *pEList,
  const char *zObject
){
  int mx = pParse->db->aLimit[SQLITE4_LIMIT_COLUMN];
  testcase( pEList && pEList->nExpr==mx );
  testcase( pEList && pEList->nExpr==mx+1 );
  if( pEList && pEList->nExpr>mx ){
    sqlite4ErrorMsg(pParse, "too many columns in %s", zObject);
  }
}

/*
** Delete an entire expression list.
*/
SQLITE4_PRIVATE void sqlite4ExprListDelete(sqlite4 *db, ExprList *pList){
  int i;
  ExprListItem *pItem;
  if( pList==0 ) return;
  assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
  assert( pList->nExpr<=pList->nAlloc );
  for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
    sqlite4ExprDelete(db, pItem->pExpr);
    sqlite4DbFree(db, pItem->zName);
    sqlite4DbFree(db, pItem->zSpan);
  }
  sqlite4DbFree(db, pList->a);
  sqlite4DbFree(db, pList);
}

/*
** These routines are Walker callbacks.  Walker.u.pi is a pointer
** to an integer.  These routines are checking an expression to see
** if it is a constant.  Set *Walker.u.pi to 0 if the expression is
** not constant.
**
** These callback routines are used to implement the following:
**
**     sqlite4ExprIsConstant()
**     sqlite4ExprIsConstantNotJoin()
**     sqlite4ExprIsConstantOrFunction()
**
*/
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){

  /* If pWalker->u.i is 3 then any term of the expression that comes from
  ** the ON or USING clauses of a join disqualifies the expression
  ** from being considered constant. */
  if( pWalker->u.i==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){
    pWalker->u.i = 0;
    return WRC_Abort;
  }

  switch( pExpr->op ){
    /* Consider functions to be constant if all their arguments are constant
    ** and pWalker->u.i==2 */
    case TK_FUNCTION:
      if( pWalker->u.i==2 ) return 0;
      /* Fall through */
    case TK_ID:
    case TK_MATCH:
    case TK_COLUMN:
    case TK_AGG_FUNCTION:
    case TK_AGG_COLUMN:
      testcase( pExpr->op==TK_ID );
      testcase( pExpr->op==TK_COLUMN );
      testcase( pExpr->op==TK_AGG_FUNCTION );
      testcase( pExpr->op==TK_AGG_COLUMN );
      pWalker->u.i = 0;
      return WRC_Abort;
    default:
      testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
      testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
      return WRC_Continue;
  }
}
static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
  UNUSED_PARAMETER(NotUsed);
  pWalker->u.i = 0;
  return WRC_Abort;
}
static int exprIsConst(Expr *p, int initFlag){
  Walker w;
  w.u.i = initFlag;
  w.xExprCallback = exprNodeIsConstant;
  w.xSelectCallback = selectNodeIsConstant;
  sqlite4WalkExpr(&w, p);
  return w.u.i;
}

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables or function calls.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
SQLITE4_PRIVATE int sqlite4ExprIsConstant(Expr *p){
  return exprIsConst(p, 1);
}

/*
** Walk an expression tree.  Return 1 if the expression is constant
** that does no originate from the ON or USING clauses of a join.
** Return 0 if it involves variables or function calls or terms from
** an ON or USING clause.
*/
SQLITE4_PRIVATE int sqlite4ExprIsConstantNotJoin(Expr *p){
  return exprIsConst(p, 3);
}

/*
** Walk an expression tree.  Return 1 if the expression is constant
** or a function call with constant arguments.  Return and 0 if there
** are any variables.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
SQLITE4_PRIVATE int sqlite4ExprIsConstantOrFunction(Expr *p){
  return exprIsConst(p, 2);
}

/*
** If the expression p codes a constant integer that is small enough
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue.  If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
*/
SQLITE4_PRIVATE int sqlite4ExprIsInteger(Expr *p, int *pValue){
  int rc = 0;

  /* If an expression is an integer literal that fits in a signed 32-bit
  ** integer, then the EP_IntValue flag will have already been set */
  assert( p->op!=TK_INTEGER || (p->flags & EP_IntValue)!=0
           || sqlite4GetInt32(p->u.zToken, &rc)==0 );

  if( p->flags & EP_IntValue ){
    *pValue = p->u.iValue;
    return 1;
  }
  switch( p->op ){
    case TK_UPLUS: {
      rc = sqlite4ExprIsInteger(p->pLeft, pValue);
      break;
    }
    case TK_UMINUS: {
      int v;
      if( sqlite4ExprIsInteger(p->pLeft, &v) ){
        *pValue = -v;
        rc = 1;
      }
      break;
    }
    default: break;
  }
  return rc;
}

/*
** Return FALSE if there is no chance that the expression can be NULL.
**
** If the expression might be NULL or if the expression is too complex
** to tell return TRUE.  
**
** This routine is used as an optimization, to skip OP_IsNull opcodes
** when we know that a value cannot be NULL.  Hence, a false positive
** (returning TRUE when in fact the expression can never be NULL) might
** be a small performance hit but is otherwise harmless.  On the other
** hand, a false negative (returning FALSE when the result could be NULL)
** will likely result in an incorrect answer.  So when in doubt, return
** TRUE.
*/
SQLITE4_PRIVATE int sqlite4ExprCanBeNull(const Expr *p){
  u8 op;
  while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
  op = p->op;
  if( op==TK_REGISTER ) op = p->op2;
  switch( op ){
    case TK_INTEGER:
    case TK_STRING:
    case TK_FLOAT:
    case TK_BLOB:
      return 0;
    default:
      return 1;
  }
}

/*
** Generate an OP_IsNull instruction that tests register iReg and jumps
** to location iDest if the value in iReg is NULL.  The value in iReg 
** was computed by pExpr.  If we can look at pExpr at compile-time and
** determine that it can never generate a NULL, then the OP_IsNull operation
** can be omitted.
*/
SQLITE4_PRIVATE void sqlite4ExprCodeIsNullJump(
  Vdbe *v,            /* The VDBE under construction */
  const Expr *pExpr,  /* Only generate OP_IsNull if this expr can be NULL */
  int iReg,           /* Test the value in this register for NULL */
  int iDest           /* Jump here if the value is null */
){
  if( sqlite4ExprCanBeNull(pExpr) ){
    sqlite4VdbeAddOp2(v, OP_IsNull, iReg, iDest);
  }
}

/*
** Return TRUE if the given expression is a constant which would be
** unchanged by OP_Affinity with the affinity given in the second
** argument.
**
** This routine is used to determine if the OP_Affinity operation
** can be omitted.  When in doubt return FALSE.  A false negative
** is harmless.  A false positive, however, can result in the wrong
** answer.
*/
SQLITE4_PRIVATE int sqlite4ExprNeedsNoAffinityChange(const Expr *p, char aff){
  u8 op;
  if( aff==SQLITE4_AFF_NONE ) return 1;
  while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
  op = p->op;
  if( op==TK_REGISTER ) op = p->op2;
  switch( op ){
    case TK_INTEGER: {
      return aff==SQLITE4_AFF_INTEGER || aff==SQLITE4_AFF_NUMERIC;
    }
    case TK_FLOAT: {
      return aff==SQLITE4_AFF_REAL || aff==SQLITE4_AFF_NUMERIC;
    }
    case TK_STRING: {
      return aff==SQLITE4_AFF_TEXT;
    }
    case TK_BLOB: {
      return 1;
    }
    case TK_COLUMN: {
      assert( p->iTable>=0 );  /* p cannot be part of a CHECK constraint */
      return p->iColumn<0
          && (aff==SQLITE4_AFF_INTEGER || aff==SQLITE4_AFF_NUMERIC);
    }
    default: {
      return 0;
    }
  }
}

/*
** Code an OP_Once instruction and allocate space for its flag. Return the 
** address of the new instruction.
*/
SQLITE4_PRIVATE int sqlite4CodeOnce(Parse *pParse){
  Vdbe *v = sqlite4GetVdbe(pParse);      /* Virtual machine being coded */
  return sqlite4VdbeAddOp1(v, OP_Once, pParse->nOnce++);
}

/*
** Return true if we are able to the IN operator optimization on a
** query of the form
**
**       x IN (SELECT ...)
**
** Where the SELECT... clause is as specified by the parameter to this
** routine.
**
** The Select object passed in has already been preprocessed and no
** errors have been found.
*/
#ifndef SQLITE4_OMIT_SUBQUERY
static int isCandidateForInOpt(Select *p){
  SrcList *pSrc;
  ExprList *pEList;
  Table *pTab;
  if( p==0 ) return 0;                   /* right-hand side of IN is SELECT */
  if( p->pPrior ) return 0;              /* Not a compound SELECT */
  if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
    testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
    testcase( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
    return 0; /* No DISTINCT keyword and no aggregate functions */
  }
  assert( p->pGroupBy==0 );              /* Has no GROUP BY clause */
  if( p->pLimit ) return 0;              /* Has no LIMIT clause */
  assert( p->pOffset==0 );               /* No LIMIT means no OFFSET */
  if( p->pWhere ) return 0;              /* Has no WHERE clause */
  pSrc = p->pSrc;
  assert( pSrc!=0 );
  if( pSrc->nSrc!=1 ) return 0;          /* Single term in FROM clause */
  if( pSrc->a[0].pSelect ) return 0;     /* FROM is not a subquery or view */
  pTab = pSrc->a[0].pTab;
  if( NEVER(pTab==0) ) return 0;
  assert( pTab->pSelect==0 );            /* FROM clause is not a view */
  if( IsVirtual(pTab) ) return 0;        /* FROM clause not a virtual table */
  pEList = p->pEList;
  if( pEList->nExpr!=1 ) return 0;       /* One column in the result set */
  if( pEList->a[0].pExpr->op!=TK_COLUMN ) return 0; /* Result is a column */
  return 1;
}

SQLITE4_PRIVATE Index *sqlite4FindExistingInIndex(Parse *pParse, Expr *pX, int bReqUnique){
  Index *pIdx = 0;
  Select *p;

  p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
  if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
    sqlite4 *db = pParse->db;
    Table *pTab = p->pSrc->a[0].pTab;
    Expr *pRhs = p->pEList->a[0].pExpr;
    int iCol = pRhs->iColumn;
    CollSeq *pReq;
    char colaff;

    /* The collation sequence used by the comparison. If an index is to
    ** be used in place of a temp-table, it must be ordered according
    ** to this collation sequence.  */
    pReq = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pRhs);
    if( !pReq ) pReq = db->pDfltColl;

    /* Check that the affinity that will be used to perform the 
    ** comparison is the same as the affinity of the column. If
    ** it is not, it is not possible to use any index.  */
    colaff = (iCol<0) ? SQLITE4_AFF_NUMERIC : pTab->aCol[iCol].affinity;
    if( 0==sqlite4IndexAffinityOk(pX, colaff) ) return 0;

    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      if( (pIdx->aiColumn[0]==iCol)
       && sqlite4FindCollSeq(db, pIdx->azColl[0], 0)==pReq
       && (!bReqUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
      ){
        break;
      }
    }
  }

  return pIdx;
}
#endif /* SQLITE4_OMIT_SUBQUERY */

#ifndef SQLITE4_OMIT_SUBQUERY
/*
** This function is used by the implementation of the IN (...) operator.
** The pX parameter is the expression on the RHS of the IN operator, which
** might be either a list of expressions or a subquery.
**
** The job of this routine is to find or create a b-tree object that can
** be used either to test for membership in the RHS set or to iterate through
** all members of the RHS set, skipping duplicates.
**
** A cursor is opened on the b-tree object that the RHS of the IN operator
** and pX->iTable is set to the index of that cursor.
**
** The returned value of this function indicates the b-tree type, as follows:
**
**   IN_INDEX_ROWID      - The cursor was opened on the PK index of a
**                         table with an implicit integer primary key.
**   IN_INDEX_INDEX_ASC  - The cursor was opened on an ascending index.
**   IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
**   IN_INDEX_EPH        - The cursor was opened on a specially created and
**                         populated epheremal table.
**
** An existing b-tree might be used if the RHS expression pX is a simple
** subquery such as:
**
**     SELECT <column> FROM <table>
**
** If the RHS of the IN operator is a list or a more complex subquery, then
** an ephemeral table might need to be generated from the RHS and then
** pX->iTable made to point to the ephermeral table instead of an
** existing table.  
**
**
** ITERATING THROUGH SET MEMBERS
** 
**   If the prNotFound parameter is 0, then the b-tree will be used to 
**   iterate through the set members, skipping any duplicates. In this
**   case the piCov parameter is always non-zero. An index on column 
**   <column> of <table> is used in this case if:
**
**     1. The index guarantees the column is unique (i.e. it is a UNIQUE
**        or PRIMARY KEY Index), and
**
**     2. The index uses the same collation sequence as the comparison
**        performed by expression pX.
**
**     3. The index is a covering index for <column> (either because it
**        is a PRIMARY KEY or was created with a COVERING clause).
**
**   Restriction (3) could be removed by the calling code in where.c.
**
**   Before returning, *piCov is set to the column number of <column> in
**   the value associated with the selected covering or primary key index.
**
** SET MEMBERSHIP TESTS
**
** If the prNotFound parameter is not 0, then the b-tree will be used 
** for fast set membership tests. In this case an epheremal table must 
** be used unless <column> is an INTEGER PRIMARY KEY or an index can 
** be found with <column> as its left-most column.
**
** When the b-tree is being used for membership tests, the calling function
** needs to know whether or not the structure contains an SQL NULL 
** value in order to correctly evaluate expressions like "X IN (Y, Z)".
** If there is any chance that the (...) might contain a NULL value at
** runtime, then a register is allocated and the register number written
** to *prNotFound. If there is no chance that the (...) contains a
** NULL value, then *prNotFound is left unchanged.
**
** If a register is allocated and its location stored in *prNotFound, then
** its initial value is NULL.  If the (...) does not remain constant
** for the duration of the query (i.e. the SELECT within the (...)
** is a correlated subquery) then the value of the allocated register is
** reset to NULL each time the subquery is rerun. This allows the
** caller to use vdbe code equivalent to the following:
**
**   if( register==NULL ){
**     has_null = <test if data structure contains null>
**     register = 1
**   }
**
** in order to avoid running the <test if data structure contains null>
** test more often than is necessary.
*/
SQLITE4_PRIVATE int sqlite4FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int *piCov){
  Select *p;                            /* SELECT to the right of IN operator */
  int eType = 0;                        /* Type of RHS table. IN_INDEX_* */
  int iTab = pParse->nTab++;            /* Cursor of the RHS table */
  int mustBeUnique = (prNotFound==0);   /* True if RHS must be unique */
  Vdbe *v = sqlite4GetVdbe(pParse);     /* Virtual machine being coded */

  assert( pX->op==TK_IN );
  assert( mustBeUnique==(piCov!=0) );

  /* This function is only called from two places. In both cases the vdbe
  ** has already been allocated. So assume sqlite4GetVdbe() is always
  ** successful here.  */
  assert(v);

  /* Check to see if an existing table or index can be used to
  ** satisfy the query.  This is preferable to generating a new 
  ** ephemeral table.
  */
  p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
  if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
    sqlite4 *db = pParse->db;     /* Database connection */
    Table *pTab;                  /* Table <table>. */
    Expr *pExpr;                  /* Expression <column> */
    int iCol;                     /* Index of column <column> */
    int iDb;                      /* Database idx for pTab */
    Index *pIdx;                  /* Used to iterate through indexes on pTab */
    CollSeq *pReq;                /* Collation sequence for comparison */
    char affinity;                /* Affinity of selected column */
    int affinity_ok;              /* True if the affinity matches */

    assert( p );                        /* Because of isCandidateForInOpt(p) */
    assert( p->pEList!=0 );             /* Because of isCandidateForInOpt(p) */
    assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */
    assert( p->pSrc!=0 );               /* Because of isCandidateForInOpt(p) */
    pTab = p->pSrc->a[0].pTab;
    pExpr = p->pEList->a[0].pExpr;
    iCol = pExpr->iColumn;
   
    /* Code an OP_VerifyCookie for <table>. */
    iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
    sqlite4CodeVerifySchema(pParse, iDb);

    /* The collation sequence used by the comparison. If an index is to
    ** be used in place of a temp-table, it must be ordered according
    ** to this collation sequence.  */
    pReq = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pExpr);

    /* Check that the affinity that will be used to perform the 
    ** comparison is the same as the affinity of the column. If
    ** it is not, it is not possible to use any index.  */
    affinity = (iCol<0?SQLITE4_AFF_NUMERIC:pTab->aCol[iCol].affinity);
    affinity_ok = sqlite4IndexAffinityOk(pX, affinity);

    for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
      if( (pIdx->aiColumn[0]==iCol)
       && (iCol<0 || sqlite4FindCollSeq(db, pIdx->azColl[0], 0)==pReq)
       && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None))
      ){
        int iAddr;

        if( mustBeUnique ){
          if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){
            int i;
            for(i=0; i<pIdx->nCover; i++){
              if( pIdx->aiCover[i]==iCol ) break;
            }
            if( i==pIdx->nCover ) continue;
            *piCov = i;
          }else{
            *piCov = iCol;
          }
        }

        iAddr = sqlite4CodeOnce(pParse);
        sqlite4OpenIndex(pParse, iTab, iDb, pIdx, OP_OpenRead);
        assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
        if( iCol<0 ){
          eType = IN_INDEX_ROWID;
        }else{
          eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
        }

        sqlite4VdbeJumpHere(v, iAddr);
        if( prNotFound && !pTab->aCol[iCol].notNull ){
          *prNotFound = ++pParse->nMem;
          sqlite4VdbeAddOp2(v, OP_Null, 0, *prNotFound);
        }
      }
    }
  }

  if( eType==0 ){
    /* Could not found an existing table or index to use as the RHS b-tree.
    ** We will have to generate an ephemeral table to do the job.
    */
    u32 savedNQueryLoop = pParse->nQueryLoop;
    int rMayHaveNull = 0;
    eType = IN_INDEX_EPH;
    if( prNotFound ){
      *prNotFound = rMayHaveNull = ++pParse->nMem;
      sqlite4VdbeAddOp2(v, OP_Null, 0, *prNotFound);
    }else{
      testcase( pParse->nQueryLoop>0 );
      pParse->nQueryLoop = 0;
      *piCov = 0;
    }
    sqlite4CodeSubselect(pParse, pX, rMayHaveNull);
    pParse->nQueryLoop = savedNQueryLoop;
  }else{
    pX->iTable = iTab;
  }
  return eType;
}
#endif

/*
** Generate code for scalar subqueries used as a subquery expression, EXISTS,
** or IN operators.  Examples:
**
**     (SELECT a FROM b)          -- subquery
**     EXISTS (SELECT a FROM b)   -- EXISTS subquery
**     x IN (4,5,11)              -- IN operator with list on right-hand side
**     x IN (SELECT a FROM b)     -- IN operator with subquery on the right
**
** The pExpr parameter describes the expression that contains the IN
** operator or subquery.
**
** If parameter isRowid is non-zero, then expression pExpr is guaranteed
** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
** to some integer key column of a table B-Tree. In this case, use an
** intkey B-Tree to store the set of IN(...) values instead of the usual
** (slower) variable length keys B-Tree.
**
** If rMayHaveNull is non-zero, that means that the operation is an IN
** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
** Furthermore, the IN is in a WHERE clause and that we really want
** to iterate over the RHS of the IN operator in order to quickly locate
** all corresponding LHS elements.  All this routine does is initialize
** the register given by rMayHaveNull to NULL.  Calling routines will take
** care of changing this register value to non-NULL if the RHS is NULL-free.
**
** If rMayHaveNull is zero, that means that the subquery is being used
** for membership testing only.  There is no need to initialize any
** registers to indicate the presense or absence of NULLs on the RHS.
**
** For a SELECT or EXISTS operator, return the register that holds the
** result.  For IN operators or if an error occurs, the return value is 0.
*/
#ifndef SQLITE4_OMIT_SUBQUERY
SQLITE4_PRIVATE int sqlite4CodeSubselect(
  Parse *pParse,          /* Parsing context */
  Expr *pExpr,            /* The IN, SELECT, or EXISTS operator */
  int rMayHaveNull        /* Register that records whether NULLs exist in RHS */
){
  int testAddr = -1;                      /* One-time test address */
  int rReg = 0;                           /* Register storing resulting */
  Vdbe *v = sqlite4GetVdbe(pParse);
  if( NEVER(v==0) ) return 0;
  sqlite4ExprCachePush(pParse);

  /* This code must be run in its entirety every time it is encountered
  ** if any of the following is true:
  **
  **    *  The right-hand side is a correlated subquery
  **    *  The right-hand side is an expression list containing variables
  **    *  We are inside a trigger
  **
  ** If all of the above are false, then we can run this code just once
  ** save the results, and reuse the same result on subsequent invocations.
  */
  if( !ExprHasAnyProperty(pExpr, EP_VarSelect) ){
    testAddr = sqlite4CodeOnce(pParse);
  }

#ifndef SQLITE4_OMIT_EXPLAIN
  if( pParse->explain==2 ){
    char *zMsg = sqlite4MPrintf(
        pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
        pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
    );
    sqlite4VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
#endif

  switch( pExpr->op ){
    case TK_IN: {
      char affinity;              /* Affinity of the LHS of the IN */
      KeyInfo keyInfo;            /* Keyinfo for the generated table */
      int addr;                   /* Address of OP_OpenEphemeral instruction */
      Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */

      if( rMayHaveNull ){
        sqlite4VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
      }

      affinity = sqlite4ExprAffinity(pLeft);

      /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
      ** expression it is handled the same way.  An ephemeral table is 
      ** filled with single-field index keys representing the results
      ** from the SELECT or the <exprlist>.
      **
      ** If the 'x' expression is a column value, or the SELECT...
      ** statement returns a column value, then the affinity of that
      ** column is used to build the index keys. If both 'x' and the
      ** SELECT... statement are columns, then numeric affinity is used
      ** if either column has NUMERIC or INTEGER affinity. If neither
      ** 'x' nor the SELECT... statement are columns, then numeric affinity
      ** is used.
      */
      pExpr->iTable = pParse->nTab++;
      addr = sqlite4VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1);
      memset(&keyInfo, 0, sizeof(keyInfo));
      keyInfo.nField = 1;

      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        /* Case 1:     expr IN (SELECT ...)
        **
        ** Generate code to write the results of the select into the temporary
        ** table allocated and opened above.
        */
        SelectDest dest;
        ExprList *pEList;

        sqlite4SelectDestInit(&dest, SRT_Set, pExpr->iTable);
        dest.affinity = (u8)affinity;
        assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
        pExpr->x.pSelect->iLimit = 0;
        if( sqlite4Select(pParse, pExpr->x.pSelect, &dest) ){
          return 0;
        }
        pEList = pExpr->x.pSelect->pEList;
        if( ALWAYS(pEList!=0 && pEList->nExpr>0) ){ 
          keyInfo.aColl[0] = sqlite4BinaryCompareCollSeq(pParse, pExpr->pLeft,
              pEList->a[0].pExpr);
        }
      }else if( ALWAYS(pExpr->x.pList!=0) ){
        /* Case 2:     expr IN (exprlist)
        **
        ** For each expression, build an index key from the evaluation and
        ** store it in the temporary table. If <expr> is a column, then use
        ** that columns affinity when building index keys. If <expr> is not
        ** a column, use numeric affinity.
        */
        int i;
        ExprList *pList = pExpr->x.pList;
        ExprListItem *pItem;
        int r1, r2, r3, r4;

        if( !affinity ){
          affinity = SQLITE4_AFF_NONE;
        }
        keyInfo.aColl[0] = sqlite4ExprCollSeq(pParse, pExpr->pLeft);

        /* Loop through each expression in <exprlist>. */
        r1 = sqlite4GetTempReg(pParse);
        r2 = sqlite4GetTempReg(pParse);
        sqlite4VdbeAddOp2(v, OP_Null, 0, r2);
        for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
          Expr *pE2 = pItem->pExpr;
          int iValToIns;

          /* If the expression is not constant then we will need to
          ** disable the test that was generated above that makes sure
          ** this code only executes once.  Because for a non-constant
          ** expression we need to rerun this code each time.
          */
          if( testAddr>=0 && !sqlite4ExprIsConstant(pE2) ){
            sqlite4VdbeChangeToNoop(v, testAddr);
            testAddr = -1;
          }

          /* Evaluate the expression and insert it into the temp table */
          r3 = sqlite4ExprCodeTarget(pParse, pE2, r1);
          r4 = sqlite4GetTempReg(pParse);
          sqlite4VdbeAddOp4(v, OP_Affinity, r3, 1, 0, &affinity, 1);
          sqlite4VdbeAddOp4Int(v, OP_MakeKey, r3, 1, r4, pExpr->iTable);
          sqlite4VdbeAddOp3(v, OP_MakeRecord, r3, 1, r2);
          sqlite4ExprCacheAffinityChange(pParse, r3, 1);
          sqlite4VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r4);
          sqlite4ReleaseTempReg(pParse, r4);
        }
        sqlite4ReleaseTempReg(pParse, r1);
        sqlite4ReleaseTempReg(pParse, r2);
      }
      sqlite4VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
      break;
    }

    case TK_EXISTS:
    case TK_SELECT:
    default: {
      /* If this has to be a scalar SELECT.  Generate code to put the
      ** value of this select in a memory cell and record the number
      ** of the memory cell in iColumn.  If this is an EXISTS, write
      ** an integer 0 (not exists) or 1 (exists) into a memory cell
      ** and record that memory cell in iColumn.
      */
      Select *pSel;                         /* SELECT statement to encode */
      SelectDest dest;                      /* How to deal with SELECt result */

      testcase( pExpr->op==TK_EXISTS );
      testcase( pExpr->op==TK_SELECT );
      assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );

      assert( ExprHasProperty(pExpr, EP_xIsSelect) );
      pSel = pExpr->x.pSelect;
      sqlite4SelectDestInit(&dest, 0, ++pParse->nMem);
      if( pExpr->op==TK_SELECT ){
        dest.eDest = SRT_Mem;
        sqlite4VdbeAddOp2(v, OP_Null, 0, dest.iParm);
        VdbeComment((v, "Init subquery result"));
      }else{
        dest.eDest = SRT_Exists;
        sqlite4VdbeAddOp2(v, OP_Integer, 0, dest.iParm);
        VdbeComment((v, "Init EXISTS result"));
      }
      sqlite4ExprDelete(pParse->db, pSel->pLimit);
      pSel->pLimit = sqlite4PExpr(pParse, TK_INTEGER, 0, 0,
                                  &sqlite4IntTokens[1]);
      pSel->iLimit = 0;
      if( sqlite4Select(pParse, pSel, &dest) ){
        return 0;
      }
      rReg = dest.iParm;
      ExprSetIrreducible(pExpr);
      break;
    }
  }

  if( testAddr>=0 ){
    sqlite4VdbeJumpHere(v, testAddr);
  }
  sqlite4ExprCachePop(pParse, 1);

  return rReg;
}
#endif /* SQLITE4_OMIT_SUBQUERY */

#ifndef SQLITE4_OMIT_SUBQUERY
/*
** Generate code for an IN expression.
**
**      x IN (SELECT ...)
**      x IN (value, value, ...)
**
** The left-hand side (LHS) is a scalar expression.  The right-hand side (RHS)
** is an array of zero or more values.  The expression is true if the LHS is
** contained within the RHS.  The value of the expression is unknown (NULL)
** if the LHS is NULL or if the LHS is not contained within the RHS and the
** RHS contains one or more NULL values.
**
** This routine generates code will jump to destIfFalse if the LHS is not 
** contained within the RHS.  If due to NULLs we cannot determine if the LHS
** is contained in the RHS then jump to destIfNull.  If the LHS is contained
** within the RHS then fall through.
*/
static void sqlite4ExprCodeIN(
  Parse *pParse,        /* Parsing and code generating context */
  Expr *pExpr,          /* The IN expression */
  int destIfFalse,      /* Jump here if LHS is not contained in the RHS */
  int destIfNull        /* Jump here if the results are unknown due to NULLs */
){
  int rRhsHasNull = 0;  /* Register that is true if RHS contains NULL values */
  char affinity;        /* Comparison affinity to use */
  int eType;            /* Type of the RHS */
  int r1;               /* Temporary use register */
  Vdbe *v;              /* Statement under construction */

  /* Compute the RHS.   After this step, the table with cursor
  ** pExpr->iTable will contains the values that make up the RHS.
  */
  v = pParse->pVdbe;
  assert( v!=0 );       /* OOM detected prior to this routine */
  VdbeNoopComment((v, "begin IN expr"));
  eType = sqlite4FindInIndex(pParse, pExpr, &rRhsHasNull, 0);

  /* Figure out the affinity to use to create a key from the results
  ** of the expression. affinityStr stores a static string suitable for
  ** P4 of OP_MakeRecord.
  */
  affinity = comparisonAffinity(pExpr);

  /* Code the LHS, the <expr> from "<expr> IN (...)".
  */
  sqlite4ExprCachePush(pParse);
  r1 = sqlite4GetTempReg(pParse);
  sqlite4ExprCode(pParse, pExpr->pLeft, r1);

  /* If the LHS is NULL, then the result is either false or NULL depending
  ** on whether the RHS is empty or not, respectively.
  */
  if( destIfNull==destIfFalse ){
    /* Shortcut for the common case where the false and NULL outcomes are
    ** the same. */
    sqlite4VdbeAddOp2(v, OP_IsNull, r1, destIfNull);
  }else{
    int addr1 = sqlite4VdbeAddOp1(v, OP_NotNull, r1);
    sqlite4VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse);
    sqlite4VdbeAddOp2(v, OP_Goto, 0, destIfNull);
    sqlite4VdbeJumpHere(v, addr1);
  }

  if( eType==IN_INDEX_ROWID ){
    /* In this case, the RHS is the ROWID of table b-tree
    */
    sqlite4VdbeAddOp2(v, OP_MustBeInt, r1, destIfFalse);
    sqlite4VdbeAddOp3(v, OP_NotExists, pExpr->iTable, destIfFalse, r1);
  }else{
    /* In this case, the RHS is an index b-tree.
    */
    sqlite4VdbeAddOp4(v, OP_Affinity, r1, 1, 0, &affinity, 1);

    /* If the set membership test fails, then the result of the 
    ** "x IN (...)" expression must be either 0 or NULL. If the set
    ** contains no NULL values, then the result is 0. If the set 
    ** contains one or more NULL values, then the result of the
    ** expression is also NULL.
    */
    if( rRhsHasNull==0 || destIfFalse==destIfNull ){
      /* This branch runs if it is known at compile time that the RHS
      ** cannot contain NULL values. This happens as the result
      ** of a "NOT NULL" constraint in the database schema.
      **
      ** Also run this branch if NULL is equivalent to FALSE
      ** for this particular IN operator.
      */
      sqlite4VdbeAddOp4Int(v, OP_NotFound, pExpr->iTable, destIfFalse, r1, 1);

    }else{
      /* In this branch, the RHS of the IN might contain a NULL and
      ** the presence of a NULL on the RHS makes a difference in the
      ** outcome.
      */
      int j1, j2, j3;

      /* First check to see if the LHS is contained in the RHS.  If so,
      ** then the presence of NULLs in the RHS does not matter, so jump
      ** over all of the code that follows.
      */
      j1 = sqlite4VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, r1, 1);

      /* Here we begin generating code that runs if the LHS is not
      ** contained within the RHS.  Generate additional code that
      ** tests the RHS for NULLs.  If the RHS contains a NULL then
      ** jump to destIfNull.  If there are no NULLs in the RHS then
      ** jump to destIfFalse.
      */
      j2 = sqlite4VdbeAddOp1(v, OP_NotNull, rRhsHasNull);
      j3 = sqlite4VdbeAddOp4Int(v, OP_Found, pExpr->iTable, 0, rRhsHasNull, 1);
      sqlite4VdbeAddOp2(v, OP_Integer, -1, rRhsHasNull);
      sqlite4VdbeJumpHere(v, j3);
      sqlite4VdbeAddOp2(v, OP_AddImm, rRhsHasNull, 1);
      sqlite4VdbeJumpHere(v, j2);

      /* Jump to the appropriate target depending on whether or not
      ** the RHS contains a NULL
      */
      sqlite4VdbeAddOp2(v, OP_If, rRhsHasNull, destIfNull);
      sqlite4VdbeAddOp2(v, OP_Goto, 0, destIfFalse);

      /* The OP_Found at the top of this branch jumps here when true, 
      ** causing the overall IN expression evaluation to fall through.
      */
      sqlite4VdbeJumpHere(v, j1);
    }
  }
  sqlite4ReleaseTempReg(pParse, r1);
  sqlite4ExprCachePop(pParse, 1);
  VdbeComment((v, "end IN expr"));
}
#endif /* SQLITE4_OMIT_SUBQUERY */

#ifndef SQLITE4_OMIT_FLOATING_POINT
/*
** Generate an instruction that will put the floating point
** value described by z[0..n-1] into register iMem.
**
** The z[] string will probably not be zero-terminated.  But the 
** z[n] character is guaranteed to be something that does not look
** like the continuation of the number.
*/
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
  if( ALWAYS(z!=0) ){
    int s = sizeof(sqlite4_num);
    sqlite4_num *p = (sqlite4_num *)sqlite4DbMallocZero(sqlite4VdbeDb(v), s);
    if( p ){
      *p = sqlite4_num_from_text(z, -1, 0, 0);
      assert( p->sign==0 );
      assert( negateFlag==0 || negateFlag==1 );
      p->sign = negateFlag;
      sqlite4VdbeAddOp4(v, OP_Num, 0, iMem, 0, (const char *)p, P4_NUM);
    }
  }
}
#endif


/*
** Generate an instruction that will put the integer describe by
** text z[0..n-1] into register iMem.
**
** Expr.u.zToken is always UTF8 and zero-terminated.
*/
static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
  Vdbe *v = pParse->pVdbe;
  if( pExpr->flags & EP_IntValue ){
    int i = pExpr->u.iValue;
    assert( i>=0 );
    if( negFlag ) i = -i;
    sqlite4VdbeAddOp2(v, OP_Integer, i, iMem);
  }else{
    sqlite4_num *p;
    const char *z = pExpr->u.zToken;
    assert( z!=0 );

    p = (sqlite4_num *)sqlite4DbMallocRaw(pParse->db, sizeof(sqlite4_num));
    if( p ){
      *p = sqlite4_num_from_text(z, -1, (negFlag ? SQLITE4_NEGATIVE : 0), 0);
      sqlite4VdbeAddOp4(v, OP_Num, p->e==0, iMem, 0, (const char *)p, P4_NUM);
    }
  }
}

/*
** Clear a cache entry.
*/
static void cacheEntryClear(Parse *pParse, ParseYColCache *p){
  if( p->tempReg ){
    if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
      pParse->aTempReg[pParse->nTempReg++] = p->iReg;
    }
    p->tempReg = 0;
  }
}


/*
** Record in the column cache that a particular column from a
** particular table is stored in a particular register.
*/
SQLITE4_PRIVATE void sqlite4ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
  int i;
  int minLru;
  int idxLru;
  ParseYColCache *p;

  assert( iReg>0 );  /* Register numbers are always positive */
  assert( iCol>=-1 && iCol<32768 );  /* Finite column numbers */

  /* The SQLITE4_ColumnCache flag disables the column cache.  This is used
  ** for testing only - to verify that SQLite always gets the same answer
  ** with and without the column cache.
  */
  if( pParse->db->flags & SQLITE4_ColumnCache ) return;

  /* First replace any existing entry.
  **
  ** Actually, the way the column cache is currently used, we are guaranteed
  ** that the object will never already be in cache.  Verify this guarantee.
  */
#ifndef NDEBUG
  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
#if 0 /* This code wold remove the entry from the cache if it existed */
    if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
      cacheEntryClear(pParse, p);
      p->iLevel = pParse->iCacheLevel;
      p->iReg = iReg;
      p->lru = pParse->iCacheCnt++;
      return;
    }
#endif
    assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
  }
#endif

  /* Find an empty slot and replace it */
  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    if( p->iReg==0 ){
      p->iLevel = pParse->iCacheLevel;
      p->iTable = iTab;
      p->iColumn = iCol;
      p->iReg = iReg;
      p->tempReg = 0;
      p->lru = pParse->iCacheCnt++;
      return;
    }
  }

  /* Replace the last recently used */
  minLru = 0x7fffffff;
  idxLru = -1;
  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    if( p->lru<minLru ){
      idxLru = i;
      minLru = p->lru;
    }
  }
  if( ALWAYS(idxLru>=0) ){
    p = &pParse->aColCache[idxLru];
    p->iLevel = pParse->iCacheLevel;
    p->iTable = iTab;
    p->iColumn = iCol;
    p->iReg = iReg;
    p->tempReg = 0;
    p->lru = pParse->iCacheCnt++;
    return;
  }
}

/*
** Indicate that registers between iReg..iReg+nReg-1 are being overwritten.
** Purge the range of registers from the column cache.
*/
SQLITE4_PRIVATE void sqlite4ExprCacheRemove(Parse *pParse, int iReg, int nReg){
  int i;
  int iLast = iReg + nReg - 1;
  ParseYColCache *p;
  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    int r = p->iReg;
    if( r>=iReg && r<=iLast ){
      cacheEntryClear(pParse, p);
      p->iReg = 0;
    }
  }
}

/*
** Remember the current column cache context.  Any new entries added
** added to the column cache after this call are removed when the
** corresponding pop occurs.
*/
SQLITE4_PRIVATE void sqlite4ExprCachePush(Parse *pParse){
  pParse->iCacheLevel++;
}

/*
** Remove from the column cache any entries that were added since the
** the previous N Push operations.  In other words, restore the cache
** to the state it was in N Pushes ago.
*/
SQLITE4_PRIVATE void sqlite4ExprCachePop(Parse *pParse, int N){
  int i;
  ParseYColCache *p;
  assert( N>0 );
  assert( pParse->iCacheLevel>=N );
  pParse->iCacheLevel -= N;
  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    if( p->iReg && p->iLevel>pParse->iCacheLevel ){
      cacheEntryClear(pParse, p);
      p->iReg = 0;
    }
  }
}

/*
** When a cached column is reused, make sure that its register is
** no longer available as a temp register.  ticket #3879:  that same
** register might be in the cache in multiple places, so be sure to
** get them all.
*/
static void sqlite4ExprCachePinRegister(Parse *pParse, int iReg){
  int i;
  ParseYColCache *p;
  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    if( p->iReg==iReg ){
      p->tempReg = 0;
    }
  }
}

/*
** Generate code to extract the value of the iCol-th column of a table.
*/
SQLITE4_PRIVATE void sqlite4ExprCodeGetColumnOfTable(
  Vdbe *v,        /* The VDBE under construction */
  Table *pTab,    /* The table containing the value */
  int iTabCur,    /* The cursor for this table */
  int iCol,       /* Index of the column to extract */
  int regOut      /* Extract the valud into this register */
){
  if( iCol<0 ){
    sqlite4VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
  }else if( IsKvstore(pTab) ){
    int aOp[2] = { OP_RowKey, OP_RowData };
    assert( iCol==0 || iCol==1 );
    sqlite4VdbeAddOp2(v, aOp[iCol], iTabCur, regOut);
  }else{
    int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
    sqlite4VdbeAddOp3(v, op, iTabCur, iCol, regOut);
  }
  if( iCol>=0 ){
    sqlite4ColumnDefault(v, pTab, iCol, regOut);
  }
}

/*
** Generate code that will extract the iColumn-th column from
** table pTab and store the column value in a register.  An effort
** is made to store the column value in register iReg, but this is
** not guaranteed.  The location of the column value is returned.
**
** There must be an open cursor to pTab in iTable when this routine
** is called.  If iColumn<0 then code is generated that extracts the rowid.
*/
SQLITE4_PRIVATE int sqlite4ExprCodeGetColumn(
  Parse *pParse,   /* Parsing and code generating context */
  Table *pTab,     /* Description of the table we are reading from */
  int iColumn,     /* Index of the table column */
  int iTable,      /* The cursor pointing to the table */
  int iReg         /* Store results here */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  ParseYColCache *p;

  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
      p->lru = pParse->iCacheCnt++;
      sqlite4ExprCachePinRegister(pParse, p->iReg);
      return p->iReg;
    }
  }  
  assert( v!=0 );
  sqlite4ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
  sqlite4ExprCacheStore(pParse, iTable, iColumn, iReg);
  return iReg;
}

/*
** Clear all column cache entries.
*/
SQLITE4_PRIVATE void sqlite4ExprCacheClear(Parse *pParse){
  int i;
  ParseYColCache *p;

  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    if( p->iReg ){
      cacheEntryClear(pParse, p);
      p->iReg = 0;
    }
  }
}

/*
** Record the fact that an affinity change has occurred on iCount
** registers starting with iStart.
*/
SQLITE4_PRIVATE void sqlite4ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
  sqlite4ExprCacheRemove(pParse, iStart, iCount);
}

/*
** Generate code to move content from registers iFrom...iFrom+nReg-1
** over to iTo..iTo+nReg-1. Keep the column cache up-to-date.
*/
SQLITE4_PRIVATE void sqlite4ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
  int i;
  ParseYColCache *p;
  if( NEVER(iFrom==iTo) ) return;
  sqlite4VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    int x = p->iReg;
    if( x>=iFrom && x<iFrom+nReg ){
      p->iReg += iTo-iFrom;
    }
  }
}

/*
** Generate code to copy content from registers iFrom...iFrom+nReg-1
** over to iTo..iTo+nReg-1.
*/
SQLITE4_PRIVATE void sqlite4ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){
  int i;
  if( NEVER(iFrom==iTo) ) return;
  for(i=0; i<nReg; i++){
    sqlite4VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i);
  }
}

#if defined(SQLITE4_DEBUG) || defined(SQLITE4_COVERAGE_TEST)
/*
** Return true if any register in the range iFrom..iTo (inclusive)
** is used as part of the column cache.
**
** This routine is used within assert() and testcase() macros only
** and does not appear in a normal build.
*/
static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
  int i;
  ParseYColCache *p;
  for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
    int r = p->iReg;
    if( r>=iFrom && r<=iTo ) return 1;    /*NO_TEST*/
  }
  return 0;
}
#endif /* SQLITE4_DEBUG || SQLITE4_COVERAGE_TEST */

/*
** Generate code into the current Vdbe to evaluate the given
** expression.  Attempt to store the results in register "target".
** Return the register where results are stored.
**
** With this routine, there is no guarantee that results will
** be stored in target.  The result might be stored in some other
** register if it is convenient to do so.  The calling function
** must check the return code and move the results to the desired
** register.
*/
SQLITE4_PRIVATE int sqlite4ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
  Vdbe *v = pParse->pVdbe;  /* The VM under construction */
  int op;                   /* The opcode being coded */
  int inReg = target;       /* Results stored in register inReg */
  int regFree1 = 0;         /* If non-zero free this temporary register */
  int regFree2 = 0;         /* If non-zero free this temporary register */
  int r1, r2, r3, r4;       /* Various register numbers */
  sqlite4 *db = pParse->db; /* The database connection */

  assert( target>0 && target<=pParse->nMem );
  if( v==0 ){
    assert( pParse->db->mallocFailed );
    return 0;
  }

  if( pExpr==0 ){
    op = TK_NULL;
  }else{
    op = pExpr->op;
  }
  switch( op ){
    case TK_AGG_COLUMN: {
      AggInfo *pAggInfo = pExpr->pAggInfo;
      AggInfoCol *pCol = &pAggInfo->aCol[pExpr->iAgg];
      if( !pAggInfo->directMode ){
        assert( pCol->iMem>0 );
        inReg = pCol->iMem;
        break;
      }else if( pAggInfo->useSortingIdx ){
        sqlite4VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,
                              pExpr->iAgg, target);
        break;
      }
      /* Otherwise, fall thru into the TK_COLUMN case */
    }
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){
        /* This only happens when coding check constraints */
        assert( pParse->ckBase>0 );
        inReg = pExpr->iColumn + pParse->ckBase;
      }else{
        inReg = sqlite4ExprCodeGetColumn(pParse, pExpr->pTab,
                                 pExpr->iColumn, pExpr->iTable, target);
      }
      break;
    }
    case TK_INTEGER: {
      codeInteger(pParse, pExpr, 0, target);
      break;
    }
#ifndef SQLITE4_OMIT_FLOATING_POINT
    case TK_FLOAT: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      codeReal(v, pExpr->u.zToken, 0, target);
      break;
    }
#endif
    case TK_STRING: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      sqlite4VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0);
      break;
    }
    case TK_NULL: {
      sqlite4VdbeAddOp2(v, OP_Null, 0, target);
      break;
    }
#ifndef SQLITE4_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      int n;
      const char *z;
      char *zBlob;
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
      assert( pExpr->u.zToken[1]=='\'' );
      z = &pExpr->u.zToken[2];
      n = sqlite4Strlen30(z) - 1;
      assert( z[n]=='\'' );
      zBlob = sqlite4HexToBlob(sqlite4VdbeDb(v), z, n);
      sqlite4VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
      break;
    }
#endif
    case TK_VARIABLE: {
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      assert( pExpr->u.zToken!=0 );
      assert( pExpr->u.zToken[0]!=0 );
      sqlite4VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
      if( pExpr->u.zToken[1]!=0 ){
        assert( pExpr->u.zToken[0]=='?' 
             || strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
        sqlite4VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
      }
      break;
    }
    case TK_REGISTER: {
      inReg = pExpr->iTable;
      break;
    }
    case TK_AS: {
      inReg = sqlite4ExprCodeTarget(pParse, pExpr->pLeft, target);
      break;
    }
#ifndef SQLITE4_OMIT_CAST
    case TK_CAST: {
      /* Expressions of the form:   CAST(pLeft AS token) */
      int aff, to_op;
      inReg = sqlite4ExprCodeTarget(pParse, pExpr->pLeft, target);
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      aff = sqlite4AffinityType(pExpr->u.zToken);
      to_op = aff - SQLITE4_AFF_TEXT + OP_ToText;
      assert( to_op==OP_ToText    || aff!=SQLITE4_AFF_TEXT    );
      assert( to_op==OP_ToBlob    || aff!=SQLITE4_AFF_NONE    );
      assert( to_op==OP_ToNumeric || aff!=SQLITE4_AFF_NUMERIC );
      assert( to_op==OP_ToInt     || aff!=SQLITE4_AFF_INTEGER );
      assert( to_op==OP_ToReal    || aff!=SQLITE4_AFF_REAL    );
      testcase( to_op==OP_ToText );
      testcase( to_op==OP_ToBlob );
      testcase( to_op==OP_ToNumeric );
      testcase( to_op==OP_ToInt );
      testcase( to_op==OP_ToReal );
      if( inReg!=target ){
        sqlite4VdbeAddOp2(v, OP_SCopy, inReg, target);
        inReg = target;
      }
      sqlite4VdbeAddOp1(v, to_op, inReg);
      testcase( usedAsColumnCache(pParse, inReg, inReg) );
      sqlite4ExprCacheAffinityChange(pParse, inReg, 1);
      break;
    }
#endif /* SQLITE4_OMIT_CAST */
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      assert( TK_LT==OP_Lt );
      assert( TK_LE==OP_Le );
      assert( TK_GT==OP_Gt );
      assert( TK_GE==OP_Ge );
      assert( TK_EQ==OP_Eq );
      assert( TK_NE==OP_Ne );
      testcase( op==TK_LT );
      testcase( op==TK_LE );
      testcase( op==TK_GT );
      testcase( op==TK_GE );
      testcase( op==TK_EQ );
      testcase( op==TK_NE );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite4ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, inReg, SQLITE4_STOREP2);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_IS:
    case TK_ISNOT: {
      testcase( op==TK_IS );
      testcase( op==TK_ISNOT );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite4ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      op = (op==TK_IS) ? TK_EQ : TK_NE;
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, inReg, SQLITE4_STOREP2 | SQLITE4_NULLEQ);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_AND:
    case TK_OR:
    case TK_PLUS:
    case TK_STAR:
    case TK_MINUS:
    case TK_REM:
    case TK_BITAND:
    case TK_BITOR:
    case TK_SLASH:
    case TK_LSHIFT:
    case TK_RSHIFT: 
    case TK_CONCAT: {
      assert( TK_AND==OP_And );
      assert( TK_OR==OP_Or );
      assert( TK_PLUS==OP_Add );
      assert( TK_MINUS==OP_Subtract );
      assert( TK_REM==OP_Remainder );
      assert( TK_BITAND==OP_BitAnd );
      assert( TK_BITOR==OP_BitOr );
      assert( TK_SLASH==OP_Divide );
      assert( TK_LSHIFT==OP_ShiftLeft );
      assert( TK_RSHIFT==OP_ShiftRight );
      assert( TK_CONCAT==OP_Concat );
      testcase( op==TK_AND );
      testcase( op==TK_OR );
      testcase( op==TK_PLUS );
      testcase( op==TK_MINUS );
      testcase( op==TK_REM );
      testcase( op==TK_BITAND );
      testcase( op==TK_BITOR );
      testcase( op==TK_SLASH );
      testcase( op==TK_LSHIFT );
      testcase( op==TK_RSHIFT );
      testcase( op==TK_CONCAT );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite4ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      sqlite4VdbeAddOp3(v, op, r2, r1, target);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_UMINUS: {
      Expr *pLeft = pExpr->pLeft;
      assert( pLeft );
      if( pLeft->op==TK_INTEGER ){
        codeInteger(pParse, pLeft, 1, target);
#ifndef SQLITE4_OMIT_FLOATING_POINT
      }else if( pLeft->op==TK_FLOAT ){
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
        codeReal(v, pLeft->u.zToken, 1, target);
#endif
      }else{
        regFree1 = r1 = sqlite4GetTempReg(pParse);
        sqlite4VdbeAddOp2(v, OP_Integer, 0, r1);
        r2 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
        sqlite4VdbeAddOp3(v, OP_Subtract, r2, r1, target);
        testcase( regFree2==0 );
      }
      inReg = target;
      break;
    }
    case TK_BITNOT:
    case TK_NOT: {
      assert( TK_BITNOT==OP_BitNot );
      assert( TK_NOT==OP_Not );
      testcase( op==TK_BITNOT );
      testcase( op==TK_NOT );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      testcase( regFree1==0 );
      inReg = target;
      sqlite4VdbeAddOp2(v, op, r1, inReg);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      int addr;
      assert( TK_ISNULL==OP_IsNull );
      assert( TK_NOTNULL==OP_NotNull );
      testcase( op==TK_ISNULL );
      testcase( op==TK_NOTNULL );
      sqlite4VdbeAddOp2(v, OP_Integer, 1, target);
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      testcase( regFree1==0 );
      addr = sqlite4VdbeAddOp1(v, op, r1);
      sqlite4VdbeAddOp2(v, OP_AddImm, target, -1);
      sqlite4VdbeJumpHere(v, addr);
      break;
    }
    case TK_AGG_FUNCTION: {
      AggInfo *pInfo = pExpr->pAggInfo;
      if( pInfo==0 ){
        assert( !ExprHasProperty(pExpr, EP_IntValue) );
        sqlite4ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
      }else{
        inReg = pInfo->aFunc[pExpr->iAgg].iMem;
      }
      break;
    }
    case TK_CONST_FUNC:
    case TK_FUNCTION: {
      ExprList *pFarg;       /* List of function arguments */
      int nFarg;             /* Number of function arguments */
      FuncDef *pDef;         /* The function definition object */
      int nId;               /* Length of the function name in bytes */
      const char *zId;       /* The function name */
      int constMask = 0;     /* Mask of function arguments that are constant */
      int i;                 /* Loop counter */
      CollSeq *pColl = 0;    /* A collating sequence */

      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
      testcase( op==TK_CONST_FUNC );
      testcase( op==TK_FUNCTION );
      if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
        pFarg = 0;
      }else{
        pFarg = pExpr->x.pList;
      }
      nFarg = pFarg ? pFarg->nExpr : 0;
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      zId = pExpr->u.zToken;
      nId = sqlite4Strlen30(zId);
      pDef = sqlite4FindFunction(db, zId, nId, nFarg, 0);
      if( pDef==0 ){
        sqlite4ErrorMsg(pParse, "unknown function: %.*s()", nId, zId);
        break;
      }

      /* Attempt a direct implementation of the built-in COALESCE() and
      ** IFNULL() functions.  This avoids unnecessary evalation of
      ** arguments past the first non-NULL argument.
      */
      if( pDef->flags & SQLITE4_FUNC_COALESCE ){
        int endCoalesce = sqlite4VdbeMakeLabel(v);
        assert( nFarg>=2 );
        sqlite4ExprCode(pParse, pFarg->a[0].pExpr, target);
        for(i=1; i<nFarg; i++){
          sqlite4VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
          sqlite4ExprCacheRemove(pParse, target, 1);
          sqlite4ExprCachePush(pParse);
          sqlite4ExprCode(pParse, pFarg->a[i].pExpr, target);
          sqlite4ExprCachePop(pParse, 1);
        }
        sqlite4VdbeResolveLabel(v, endCoalesce);
        break;
      }


      if( pFarg ){
        r1 = sqlite4GetTempRange(pParse, nFarg);
        sqlite4ExprCachePush(pParse);     /* Ticket 2ea2425d34be */
        sqlite4ExprCodeExprList(pParse, pFarg, r1, 1);
        sqlite4ExprCachePop(pParse, 1);   /* Ticket 2ea2425d34be */
      }else{
        r1 = 0;
      }
#ifndef SQLITE4_OMIT_VIRTUALTABLE
      /* Possibly overload the function if the first argument is
      ** a virtual table column.
      **
      ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the
      ** second argument, not the first, as the argument to test to
      ** see if it is a column in a virtual table.  This is done because
      ** the left operand of infix functions (the operand we want to
      ** control overloading) ends up as the second argument to the
      ** function.  The expression "A glob B" is equivalent to 
      ** "glob(B,A).  We want to use the A in "A glob B" to test
      ** for function overloading.  But we use the B term in "glob(B,A)".
      */
      if( nFarg>=2 && (pExpr->flags & EP_InfixFunc) ){
        pDef = sqlite4VtabOverloadFunction(db, pDef, nFarg, pFarg->a[1].pExpr);
      }else if( nFarg>0 ){
        pDef = sqlite4VtabOverloadFunction(db, pDef, nFarg, pFarg->a[0].pExpr);
      }
#endif
      for(i=0; i<nFarg; i++){
        if( i<32 && sqlite4ExprIsConstant(pFarg->a[i].pExpr) ){
          constMask |= (1<<i);
        }
        if( (pDef->flags & SQLITE4_FUNC_NEEDCOLL)!=0 && !pColl ){
          pColl = sqlite4ExprCollSeq(pParse, pFarg->a[i].pExpr);
        }
      }
      if( pDef->flags & SQLITE4_FUNC_NEEDCOLL ){
        if( !pColl ) pColl = db->pDfltColl; 
        sqlite4VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
      }
      if( pDef->bMatchinfo ){
        sqlite4VdbeAddOp1(v, OP_Mifunction, pFarg->a[0].pExpr->iTable);
      }
      sqlite4VdbeAddOp4(v, OP_Function, constMask, r1, target,
                        (char*)pDef, P4_FUNCDEF);
      sqlite4VdbeChangeP5(v, (u8)nFarg);
      if( nFarg ){
        sqlite4ReleaseTempRange(pParse, r1, nFarg);
      }
      break;
    }
#ifndef SQLITE4_OMIT_SUBQUERY
    case TK_EXISTS:
    case TK_SELECT: {
      testcase( op==TK_EXISTS );
      testcase( op==TK_SELECT );
      inReg = sqlite4CodeSubselect(pParse, pExpr, 0);
      break;
    }
    case TK_IN: {
      int destIfFalse = sqlite4VdbeMakeLabel(v);
      int destIfNull = sqlite4VdbeMakeLabel(v);
      sqlite4VdbeAddOp2(v, OP_Null, 0, target);
      sqlite4ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
      sqlite4VdbeAddOp2(v, OP_Integer, 1, target);
      sqlite4VdbeResolveLabel(v, destIfFalse);
      sqlite4VdbeAddOp2(v, OP_AddImm, target, 0);
      sqlite4VdbeResolveLabel(v, destIfNull);
      break;
    }
#endif /* SQLITE4_OMIT_SUBQUERY */


    /*
    **    x BETWEEN y AND z
    **
    ** This is equivalent to
    **
    **    x>=y AND x<=z
    **
    ** X is stored in pExpr->pLeft.
    ** Y is stored in pExpr->pList->a[0].pExpr.
    ** Z is stored in pExpr->pList->a[1].pExpr.
    */
    case TK_BETWEEN: {
      Expr *pLeft = pExpr->pLeft;
      ExprListItem *pLItem = pExpr->x.pList->a;
      Expr *pRight = pLItem->pExpr;

      r1 = sqlite4ExprCodeTemp(pParse, pLeft, &regFree1);
      r2 = sqlite4ExprCodeTemp(pParse, pRight, &regFree2);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      r3 = sqlite4GetTempReg(pParse);
      r4 = sqlite4GetTempReg(pParse);
      codeCompare(pParse, pLeft, pRight, OP_Ge,
                  r1, r2, r3, SQLITE4_STOREP2);
      pLItem++;
      pRight = pLItem->pExpr;
      sqlite4ReleaseTempReg(pParse, regFree2);
      r2 = sqlite4ExprCodeTemp(pParse, pRight, &regFree2);
      testcase( regFree2==0 );
      codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE4_STOREP2);
      sqlite4VdbeAddOp3(v, OP_And, r3, r4, target);
      sqlite4ReleaseTempReg(pParse, r3);
      sqlite4ReleaseTempReg(pParse, r4);
      break;
    }
    case TK_UPLUS: {
      inReg = sqlite4ExprCodeTarget(pParse, pExpr->pLeft, target);
      break;
    }

    case TK_TRIGGER: {
      /* If the opcode is TK_TRIGGER, then the expression is a reference
      ** to a column in the new.* or old.* pseudo-tables available to
      ** trigger programs. In this case Expr.iTable is set to 1 for the
      ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
      ** is set to the column of the pseudo-table to read, or to -1 to
      ** read the rowid field (if applicable - see below).
      **
      ** The expression is implemented using an OP_Param opcode. The p1
      ** parameter is set to 0 for an old.rowid reference, or to (i+1)
      ** to reference another column of the old.* pseudo-table, where 
      ** i is the index of the column. For a new.rowid reference, p1 is
      ** set to (n+1), where n is the number of columns in each pseudo-table.
      ** For a reference to any other column in the new.* pseudo-table, p1
      ** is set to (n+2+i), where n and i are as defined previously. For
      ** example, if the table on which triggers are being fired is
      ** declared as:
      **
      **   CREATE TABLE t1(a, b);
      **
      ** Then p1 is interpreted as follows:
      **
      **   p1==0   ->    old.rowid     p1==3   ->    new.rowid
      **   p1==1   ->    old.a         p1==4   ->    new.a
      **   p1==2   ->    old.b         p1==5   ->    new.b       
      **
      ** As of SQLite 4, the rowid references are only valid if the table is
      ** declared without an explicit PRIMARY KEY (as it is in the example
      ** above). If the table does have an explicit PRIMARY KEY, the contents
      ** of the old.rowid and new.rowid registers are not defined.
      */
      Table *pTab = pExpr->pTab;
      int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;

      assert( pExpr->iTable==0 || pExpr->iTable==1 );
      assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
      assert( p1>=0 && p1<(pTab->nCol*2+2) );

      sqlite4VdbeAddOp2(v, OP_Param, p1, target);
      VdbeComment((v, "%s.%s -> $%d",
        (pExpr->iTable ? "new" : "old"),
        (pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
        target
      ));

#ifndef SQLITE4_OMIT_FLOATING_POINT
      /* If the column has REAL affinity, it may currently be stored as an
      ** integer. Use OP_RealAffinity to make sure it is really real.  */
      if( pExpr->iColumn>=0 
       && pTab->aCol[pExpr->iColumn].affinity==SQLITE4_AFF_REAL
      ){
        sqlite4VdbeAddOp1(v, OP_RealAffinity, target);
      }
#endif
      break;
    }

    case TK_MATCH: {
      sqlite4ErrorMsg(pParse, "no index to process MATCH operator");
      return 0;
    }


    /*
    ** Form A:
    **   CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
    **
    ** Form B:
    **   CASE WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
    **
    ** Form A is can be transformed into the equivalent form B as follows:
    **   CASE WHEN x=e1 THEN r1 WHEN x=e2 THEN r2 ...
    **        WHEN x=eN THEN rN ELSE y END
    **
    ** X (if it exists) is in pExpr->pLeft.
    ** Y is in pExpr->pRight.  The Y is also optional.  If there is no
    ** ELSE clause and no other term matches, then the result of the
    ** exprssion is NULL.
    ** Ei is in pExpr->pList->a[i*2] and Ri is pExpr->pList->a[i*2+1].
    **
    ** The result of the expression is the Ri for the first matching Ei,
    ** or if there is no matching Ei, the ELSE term Y, or if there is
    ** no ELSE term, NULL.
    */
    default: assert( op==TK_CASE ); {
      int endLabel;                     /* GOTO label for end of CASE stmt */
      int nextCase;                     /* GOTO label for next WHEN clause */
      int nExpr;                        /* 2x number of WHEN terms */
      int i;                            /* Loop counter */
      ExprList *pEList;                 /* List of WHEN terms */
      ExprListItem *aListelem;  /* Array of WHEN terms */
      Expr opCompare;                   /* The X==Ei expression */
      Expr cacheX;                      /* Cached expression X */
      Expr *pX;                         /* The X expression */
      Expr *pTest = 0;                  /* X==Ei (form A) or just Ei (form B) */
      VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )

      assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
      assert((pExpr->x.pList->nExpr % 2) == 0);
      assert(pExpr->x.pList->nExpr > 0);
      pEList = pExpr->x.pList;
      aListelem = pEList->a;
      nExpr = pEList->nExpr;
      endLabel = sqlite4VdbeMakeLabel(v);
      if( (pX = pExpr->pLeft)!=0 ){
        cacheX = *pX;
        testcase( pX->op==TK_COLUMN );
        testcase( pX->op==TK_REGISTER );
        cacheX.iTable = sqlite4ExprCodeTemp(pParse, pX, &regFree1);
        testcase( regFree1==0 );
        cacheX.op = TK_REGISTER;
        opCompare.op = TK_EQ;
        opCompare.pLeft = &cacheX;
        pTest = &opCompare;
        /* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
        ** The value in regFree1 might get SCopy-ed into the file result.
        ** So make sure that the regFree1 register is not reused for other
        ** purposes and possibly overwritten.  */
        regFree1 = 0;
      }
      for(i=0; i<nExpr; i=i+2){
        sqlite4ExprCachePush(pParse);
        if( pX ){
          assert( pTest!=0 );
          opCompare.pRight = aListelem[i].pExpr;
        }else{
          pTest = aListelem[i].pExpr;
        }
        nextCase = sqlite4VdbeMakeLabel(v);
        testcase( pTest->op==TK_COLUMN );
        sqlite4ExprIfFalse(pParse, pTest, nextCase, SQLITE4_JUMPIFNULL);
        testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
        testcase( aListelem[i+1].pExpr->op==TK_REGISTER );
        sqlite4ExprCode(pParse, aListelem[i+1].pExpr, target);
        sqlite4VdbeAddOp2(v, OP_Goto, 0, endLabel);
        sqlite4ExprCachePop(pParse, 1);
        sqlite4VdbeResolveLabel(v, nextCase);
      }
      if( pExpr->pRight ){
        sqlite4ExprCachePush(pParse);
        sqlite4ExprCode(pParse, pExpr->pRight, target);
        sqlite4ExprCachePop(pParse, 1);
      }else{
        sqlite4VdbeAddOp2(v, OP_Null, 0, target);
      }
      assert( db->mallocFailed || pParse->nErr>0 
           || pParse->iCacheLevel==iCacheLevel );
      sqlite4VdbeResolveLabel(v, endLabel);
      break;
    }
#ifndef SQLITE4_OMIT_TRIGGER
    case TK_RAISE: {
      assert( pExpr->affinity==OE_Rollback 
           || pExpr->affinity==OE_Abort
           || pExpr->affinity==OE_Fail
           || pExpr->affinity==OE_Ignore
      );
      if( !pParse->pTriggerTab ){
        sqlite4ErrorMsg(pParse,
                       "RAISE() may only be used within a trigger-program");
        return 0;
      }
      if( pExpr->affinity==OE_Abort ){
        sqlite4MayAbort(pParse);
      }
      assert( !ExprHasProperty(pExpr, EP_IntValue) );
      if( pExpr->affinity==OE_Ignore ){
        sqlite4VdbeAddOp4(
            v, OP_Halt, SQLITE4_OK, OE_Ignore, 0, pExpr->u.zToken,0);
      }else{
        sqlite4HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0);
      }

      break;
    }
#endif
  }
  sqlite4ReleaseTempReg(pParse, regFree1);
  sqlite4ReleaseTempReg(pParse, regFree2);
  return inReg;
}

/*
** Generate code to evaluate an expression and store the results
** into a register.  Return the register number where the results
** are stored.
**
** If the register is a temporary register that can be deallocated,
** then write its number into *pReg.  If the result register is not
** a temporary, then set *pReg to zero.
*/
SQLITE4_PRIVATE int sqlite4ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
  int r1 = sqlite4GetTempReg(pParse);
  int r2 = sqlite4ExprCodeTarget(pParse, pExpr, r1);
  if( r2==r1 ){
    *pReg = r1;
  }else{
    sqlite4ReleaseTempReg(pParse, r1);
    *pReg = 0;
  }
  return r2;
}

/*
** Generate code that will evaluate expression pExpr and store the
** results in register target.  The results are guaranteed to appear
** in register target.
*/
SQLITE4_PRIVATE int sqlite4ExprCode(Parse *pParse, Expr *pExpr, int target){
  int inReg;

  assert( target>0 && target<=pParse->nMem );
  if( pExpr && pExpr->op==TK_REGISTER ){
    sqlite4VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
  }else{
    inReg = sqlite4ExprCodeTarget(pParse, pExpr, target);
    assert( pParse->pVdbe || pParse->db->mallocFailed );
    if( inReg!=target && pParse->pVdbe ){
      sqlite4VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
    }
  }
  return target;
}

/*
** Generate code that evalutes the given expression and puts the result
** in register target.
**
** Also make a copy of the expression results into another "cache" register
** and modify the expression so that the next time it is evaluated,
** the result is a copy of the cache register.
**
** This routine is used for expressions that are used multiple 
** times.  They are evaluated once and the results of the expression
** are reused.
*/
SQLITE4_PRIVATE int sqlite4ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
  Vdbe *v = pParse->pVdbe;
  int inReg;
  inReg = sqlite4ExprCode(pParse, pExpr, target);
  assert( target>0 );
  if( pExpr->op!=TK_REGISTER ){  
    int iMem;
    iMem = ++pParse->nMem;
    sqlite4VdbeAddOp2(v, OP_Copy, inReg, iMem);
    pExpr->iTable = iMem;
    pExpr->op2 = pExpr->op;
    pExpr->op = TK_REGISTER;
  }
  return inReg;
}

#if defined(SQLITE4_ENABLE_TREE_EXPLAIN)
/*
** Generate a human-readable explanation of an expression tree.
*/
SQLITE4_PRIVATE void sqlite4ExplainExpr(Vdbe *pOut, Expr *pExpr){
  int op;                   /* The opcode being coded */
  const char *zBinOp = 0;   /* Binary operator */
  const char *zUniOp = 0;   /* Unary operator */
  if( pExpr==0 ){
    op = TK_NULL;
  }else{
    op = pExpr->op;
  }
  switch( op ){
    case TK_AGG_COLUMN: {
      sqlite4ExplainPrintf(pOut, "AGG{%d:%d}",
            pExpr->iTable, pExpr->iColumn);
      break;
    }
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){
        /* This only happens when coding check constraints */
        sqlite4ExplainPrintf(pOut, "COLUMN(%d)", pExpr->iColumn);
      }else{
        sqlite4ExplainPrintf(pOut, "{%d:%d}",
                             pExpr->iTable, pExpr->iColumn);
      }
      break;
    }
    case TK_INTEGER: {
      if( pExpr->flags & EP_IntValue ){
        sqlite4ExplainPrintf(pOut, "%d", pExpr->u.iValue);
      }else{
        sqlite4ExplainPrintf(pOut, "%s", pExpr->u.zToken);
      }
      break;
    }
#ifndef SQLITE4_OMIT_FLOATING_POINT
    case TK_FLOAT: {
      sqlite4ExplainPrintf(pOut,"%s", pExpr->u.zToken);
      break;
    }
#endif
    case TK_STRING: {
      sqlite4ExplainPrintf(pOut,"%Q", pExpr->u.zToken);
      break;
    }
    case TK_NULL: {
      sqlite4ExplainPrintf(pOut,"NULL");
      break;
    }
#ifndef SQLITE4_OMIT_BLOB_LITERAL
    case TK_BLOB: {
      sqlite4ExplainPrintf(pOut,"%s", pExpr->u.zToken);
      break;
    }
#endif
    case TK_VARIABLE: {
      sqlite4ExplainPrintf(pOut,"VARIABLE(%s,%d)",
                           pExpr->u.zToken, pExpr->iColumn);
      break;
    }
    case TK_REGISTER: {
      sqlite4ExplainPrintf(pOut,"REGISTER(%d)", pExpr->iTable);
      break;
    }
    case TK_AS: {
      sqlite4ExplainExpr(pOut, pExpr->pLeft);
      break;
    }
#ifndef SQLITE4_OMIT_CAST
    case TK_CAST: {
      /* Expressions of the form:   CAST(pLeft AS token) */
      const char *zAff = "unk";
      switch( sqlite4AffinityType(pExpr->u.zToken) ){
        case SQLITE4_AFF_TEXT:    zAff = "TEXT";     break;
        case SQLITE4_AFF_NONE:    zAff = "NONE";     break;
        case SQLITE4_AFF_NUMERIC: zAff = "NUMERIC";  break;
        case SQLITE4_AFF_INTEGER: zAff = "INTEGER";  break;
        case SQLITE4_AFF_REAL:    zAff = "REAL";     break;
      }
      sqlite4ExplainPrintf(pOut, "CAST-%s(", zAff);
      sqlite4ExplainExpr(pOut, pExpr->pLeft);
      sqlite4ExplainPrintf(pOut, ")");
      break;
    }
#endif /* SQLITE4_OMIT_CAST */
    case TK_LT:      zBinOp = "LT";     break;
    case TK_LE:      zBinOp = "LE";     break;
    case TK_GT:      zBinOp = "GT";     break;
    case TK_GE:      zBinOp = "GE";     break;
    case TK_NE:      zBinOp = "NE";     break;
    case TK_EQ:      zBinOp = "EQ";     break;
    case TK_IS:      zBinOp = "IS";     break;
    case TK_ISNOT:   zBinOp = "ISNOT";  break;
    case TK_AND:     zBinOp = "AND";    break;
    case TK_OR:      zBinOp = "OR";     break;
    case TK_PLUS:    zBinOp = "ADD";    break;
    case TK_STAR:    zBinOp = "MUL";    break;
    case TK_MINUS:   zBinOp = "SUB";    break;
    case TK_REM:     zBinOp = "REM";    break;
    case TK_BITAND:  zBinOp = "BITAND"; break;
    case TK_BITOR:   zBinOp = "BITOR";  break;
    case TK_SLASH:   zBinOp = "DIV";    break;
    case TK_LSHIFT:  zBinOp = "LSHIFT"; break;
    case TK_RSHIFT:  zBinOp = "RSHIFT"; break;
    case TK_CONCAT:  zBinOp = "CONCAT"; break;

    case TK_UMINUS:  zUniOp = "UMINUS"; break;
    case TK_UPLUS:   zUniOp = "UPLUS";  break;
    case TK_BITNOT:  zUniOp = "BITNOT"; break;
    case TK_NOT:     zUniOp = "NOT";    break;
    case TK_ISNULL:  zUniOp = "ISNULL"; break;
    case TK_NOTNULL: zUniOp = "NOTNULL"; break;

    case TK_AGG_FUNCTION:
    case TK_CONST_FUNC:
    case TK_FUNCTION: {
      ExprList *pFarg;       /* List of function arguments */
      if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){
        pFarg = 0;
      }else{
        pFarg = pExpr->x.pList;
      }
      sqlite4ExplainPrintf(pOut, "%sFUNCTION:%s(",
                           op==TK_AGG_FUNCTION ? "AGG_" : "",
                           pExpr->u.zToken);
      if( pFarg ){
        sqlite4ExplainExprList(pOut, pFarg);
      }
      sqlite4ExplainPrintf(pOut, ")");
      break;
    }
#ifndef SQLITE4_OMIT_SUBQUERY
    case TK_EXISTS: {
      sqlite4ExplainPrintf(pOut, "EXISTS(");
      sqlite4ExplainSelect(pOut, pExpr->x.pSelect);
      sqlite4ExplainPrintf(pOut,")");
      break;
    }
    case TK_SELECT: {
      sqlite4ExplainPrintf(pOut, "(");
      sqlite4ExplainSelect(pOut, pExpr->x.pSelect);
      sqlite4ExplainPrintf(pOut, ")");
      break;
    }
    case TK_IN: {
      sqlite4ExplainPrintf(pOut, "IN(");
      sqlite4ExplainExpr(pOut, pExpr->pLeft);
      sqlite4ExplainPrintf(pOut, ",");
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        sqlite4ExplainSelect(pOut, pExpr->x.pSelect);
      }else{
        sqlite4ExplainExprList(pOut, pExpr->x.pList);
      }
      sqlite4ExplainPrintf(pOut, ")");
      break;
    }
#endif /* SQLITE4_OMIT_SUBQUERY */

    /*
    **    x BETWEEN y AND z
    **
    ** This is equivalent to
    **
    **    x>=y AND x<=z
    **
    ** X is stored in pExpr->pLeft.
    ** Y is stored in pExpr->pList->a[0].pExpr.
    ** Z is stored in pExpr->pList->a[1].pExpr.
    */
    case TK_BETWEEN: {
      Expr *pX = pExpr->pLeft;
      Expr *pY = pExpr->x.pList->a[0].pExpr;
      Expr *pZ = pExpr->x.pList->a[1].pExpr;
      sqlite4ExplainPrintf(pOut, "BETWEEN(");
      sqlite4ExplainExpr(pOut, pX);
      sqlite4ExplainPrintf(pOut, ",");
      sqlite4ExplainExpr(pOut, pY);
      sqlite4ExplainPrintf(pOut, ",");
      sqlite4ExplainExpr(pOut, pZ);
      sqlite4ExplainPrintf(pOut, ")");
      break;
    }
    case TK_TRIGGER: {
      /* If the opcode is TK_TRIGGER, then the expression is a reference
      ** to a column in the new.* or old.* pseudo-tables available to
      ** trigger programs. In this case Expr.iTable is set to 1 for the
      ** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
      ** is set to the column of the pseudo-table to read, or to -1 to
      ** read the rowid field.
      */
      sqlite4ExplainPrintf(pOut, "%s(%d)", 
          pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
      break;
    }
    case TK_CASE: {
      sqlite4ExplainPrintf(pOut, "CASE(");
      sqlite4ExplainExpr(pOut, pExpr->pLeft);
      sqlite4ExplainPrintf(pOut, ",");
      sqlite4ExplainExprList(pOut, pExpr->x.pList);
      break;
    }
#ifndef SQLITE4_OMIT_TRIGGER
    case TK_RAISE: {
      const char *zType = "unk";
      switch( pExpr->affinity ){
        case OE_Rollback:   zType = "rollback";  break;
        case OE_Abort:      zType = "abort";     break;
        case OE_Fail:       zType = "fail";      break;
        case OE_Ignore:     zType = "ignore";    break;
      }
      sqlite4ExplainPrintf(pOut, "RAISE-%s(%s)", zType, pExpr->u.zToken);
      break;
    }
#endif
  }
  if( zBinOp ){
    sqlite4ExplainPrintf(pOut,"%s(", zBinOp);
    sqlite4ExplainExpr(pOut, pExpr->pLeft);
    sqlite4ExplainPrintf(pOut,",");
    sqlite4ExplainExpr(pOut, pExpr->pRight);
    sqlite4ExplainPrintf(pOut,")");
  }else if( zUniOp ){
    sqlite4ExplainPrintf(pOut,"%s(", zUniOp);
    sqlite4ExplainExpr(pOut, pExpr->pLeft);
    sqlite4ExplainPrintf(pOut,")");
  }
}
#endif /* defined(SQLITE4_ENABLE_TREE_EXPLAIN) */

#if defined(SQLITE4_ENABLE_TREE_EXPLAIN)
/*
** Generate a human-readable explanation of an expression list.
*/
SQLITE4_PRIVATE void sqlite4ExplainExprList(Vdbe *pOut, ExprList *pList){
  int i;
  if( pList==0 || pList->nExpr==0 ){
    sqlite4ExplainPrintf(pOut, "(empty-list)");
    return;
  }else if( pList->nExpr==1 ){
    sqlite4ExplainExpr(pOut, pList->a[0].pExpr);
  }else{
    sqlite4ExplainPush(pOut);
    for(i=0; i<pList->nExpr; i++){
      sqlite4ExplainPrintf(pOut, "item[%d] = ", i);
      sqlite4ExplainPush(pOut);
      sqlite4ExplainExpr(pOut, pList->a[i].pExpr);
      sqlite4ExplainPop(pOut);
      if( i<pList->nExpr-1 ){
        sqlite4ExplainNL(pOut);
      }
    }
    sqlite4ExplainPop(pOut);
  }
}
#endif /* SQLITE4_DEBUG */

/*
** Return TRUE if pExpr is an constant expression that is appropriate
** for factoring out of a loop.  Appropriate expressions are:
**
**    *  Any expression that evaluates to two or more opcodes.
**
**    *  Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null, 
**       or OP_Variable that does not need to be placed in a 
**       specific register.
**
** There is no point in factoring out single-instruction constant
** expressions that need to be placed in a particular register.  
** We could factor them out, but then we would end up adding an
** OP_SCopy instruction to move the value into the correct register
** later.  We might as well just use the original instruction and
** avoid the OP_SCopy.
*/
static int isAppropriateForFactoring(Expr *p){
  if( !sqlite4ExprIsConstantNotJoin(p) ){
    return 0;  /* Only constant expressions are appropriate for factoring */
  }
  if( p->op==TK_MATCH || p->op==TK_TABLE ) return 0;
  if( (p->flags & EP_FixedDest)==0 ){
    return 1;  /* Any constant without a fixed destination is appropriate */
  }
  while( p->op==TK_UPLUS ) p = p->pLeft;
  switch( p->op ){
#ifndef SQLITE4_OMIT_BLOB_LITERAL
    case TK_BLOB:
#endif
    case TK_VARIABLE:
    case TK_INTEGER:
    case TK_FLOAT:
    case TK_NULL:
    case TK_STRING: {
      testcase( p->op==TK_BLOB );
      testcase( p->op==TK_VARIABLE );
      testcase( p->op==TK_INTEGER );
      testcase( p->op==TK_FLOAT );
      testcase( p->op==TK_NULL );
      testcase( p->op==TK_STRING );
      /* Single-instruction constants with a fixed destination are
      ** better done in-line.  If we factor them, they will just end
      ** up generating an OP_SCopy to move the value to the destination
      ** register. */
      return 0;
    }
    case TK_UMINUS: {
      if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){
        return 0;
      }
      break;
    }
    default: {
      break;
    }
  }
  return 1;
}

/*
** If pExpr is a constant expression that is appropriate for
** factoring out of a loop, then evaluate the expression
** into a register and convert the expression into a TK_REGISTER
** expression.
*/
static int evalConstExpr(Walker *pWalker, Expr *pExpr){
  Parse *pParse = pWalker->pParse;
  switch( pExpr->op ){
    case TK_IN:
    case TK_REGISTER: {
      return WRC_Prune;
    }
    case TK_FUNCTION:
    case TK_AGG_FUNCTION:
    case TK_CONST_FUNC: {
      /* The arguments to a function have a fixed destination.
      ** Mark them this way to avoid generated unneeded OP_SCopy
      ** instructions. 
      */
      ExprList *pList = pExpr->x.pList;
      assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
      if( pList ){
        int i = pList->nExpr;
        ExprListItem *pItem = pList->a;
        for(; i>0; i--, pItem++){
          if( ALWAYS(pItem->pExpr) ) pItem->pExpr->flags |= EP_FixedDest;
        }
      }
      break;
    }
  }
  if( isAppropriateForFactoring(pExpr) ){
    int r1 = ++pParse->nMem;
    int r2;
    r2 = sqlite4ExprCodeTarget(pParse, pExpr, r1);
    if( NEVER(r1!=r2) ) sqlite4ReleaseTempReg(pParse, r1);
    pExpr->op2 = pExpr->op;
    pExpr->op = TK_REGISTER;
    pExpr->iTable = r2;
    return WRC_Prune;
  }
  return WRC_Continue;
}

/*
** Preevaluate constant subexpressions within pExpr and store the
** results in registers.  Modify pExpr so that the constant subexpresions
** are TK_REGISTER opcodes that refer to the precomputed values.
**
** This routine is a no-op if the jump to the cookie-check code has
** already occur.  Since the cookie-check jump is generated prior to
** any other serious processing, this check ensures that there is no
** way to accidently bypass the constant initializations.
**
** This routine is also a no-op if the SQLITE4_FactorOutConst optimization
** is disabled via the sqlite4_test_control(SQLITE4_TESTCTRL_OPTIMIZATIONS)
** interface.  This allows test logic to verify that the same answer is
** obtained for queries regardless of whether or not constants are
** precomputed into registers or if they are inserted in-line.
*/
SQLITE4_PRIVATE void sqlite4ExprCodeConstants(Parse *pParse, Expr *pExpr){
  Walker w;
  if( pParse->cookieGoto ) return;
  if( (pParse->db->flags & SQLITE4_FactorOutConst)!=0 ) return;
  w.xExprCallback = evalConstExpr;
  w.xSelectCallback = 0;
  w.pParse = pParse;
  sqlite4WalkExpr(&w, pExpr);
}


/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
**
** Return the number of elements evaluated.
*/
SQLITE4_PRIVATE int sqlite4ExprCodeExprList(
  Parse *pParse,     /* Parsing context */
  ExprList *pList,   /* The expression list to be coded */
  int target,        /* Where to write results */
  int doHardCopy     /* Make a hard copy of every element */
){
  ExprListItem *pItem;
  int i, n;
  assert( pList!=0 );
  assert( target>0 );
  assert( pParse->pVdbe!=0 );  /* Never gets this far otherwise */
  n = pList->nExpr;
  for(pItem=pList->a, i=0; i<n; i++, pItem++){
    Expr *pExpr = pItem->pExpr;
    int inReg = sqlite4ExprCodeTarget(pParse, pExpr, target+i);
    if( inReg!=target+i ){
      sqlite4VdbeAddOp2(pParse->pVdbe, doHardCopy ? OP_Copy : OP_SCopy,
                        inReg, target+i);
    }
  }
  return n;
}

/*
** Generate code for a BETWEEN operator.
**
**    x BETWEEN y AND z
**
** The above is equivalent to 
**
**    x>=y AND x<=z
**
** Code it as such, taking care to do the common subexpression
** elementation of x.
*/
static void exprCodeBetween(
  Parse *pParse,    /* Parsing and code generating context */
  Expr *pExpr,      /* The BETWEEN expression */
  int dest,         /* Jump here if the jump is taken */
  int jumpIfTrue,   /* Take the jump if the BETWEEN is true */
  int jumpIfNull    /* Take the jump if the BETWEEN is NULL */
){
  Expr exprAnd;     /* The AND operator in  x>=y AND x<=z  */
  Expr compLeft;    /* The  x>=y  term */
  Expr compRight;   /* The  x<=z  term */
  Expr exprX;       /* The  x  subexpression */
  int regFree1 = 0; /* Temporary use register */

  assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
  exprX = *pExpr->pLeft;
  exprAnd.op = TK_AND;
  exprAnd.pLeft = &compLeft;
  exprAnd.pRight = &compRight;
  compLeft.op = TK_GE;
  compLeft.pLeft = &exprX;
  compLeft.pRight = pExpr->x.pList->a[0].pExpr;
  compRight.op = TK_LE;
  compRight.pLeft = &exprX;
  compRight.pRight = pExpr->x.pList->a[1].pExpr;
  exprX.iTable = sqlite4ExprCodeTemp(pParse, &exprX, &regFree1);
  exprX.op = TK_REGISTER;
  if( jumpIfTrue ){
    sqlite4ExprIfTrue(pParse, &exprAnd, dest, jumpIfNull);
  }else{
    sqlite4ExprIfFalse(pParse, &exprAnd, dest, jumpIfNull);
  }
  sqlite4ReleaseTempReg(pParse, regFree1);

  /* Ensure adequate test coverage */
  testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1==0 );
  testcase( jumpIfTrue==0 && jumpIfNull==0 && regFree1!=0 );
  testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1==0 );
  testcase( jumpIfTrue==0 && jumpIfNull!=0 && regFree1!=0 );
  testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1==0 );
  testcase( jumpIfTrue!=0 && jumpIfNull==0 && regFree1!=0 );
  testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1==0 );
  testcase( jumpIfTrue!=0 && jumpIfNull!=0 && regFree1!=0 );
}

/*
** Generate code for a boolean expression such that a jump is made
** to the label "dest" if the expression is true but execution
** continues straight thru if the expression is false.
**
** If the expression evaluates to NULL (neither true nor false), then
** take the jump if the jumpIfNull flag is SQLITE4_JUMPIFNULL.
**
** This code depends on the fact that certain token values (ex: TK_EQ)
** are the same as opcode values (ex: OP_Eq) that implement the corresponding
** operation.  Special comments in vdbe.c and the mkopcodeh.awk script in
** the make process cause these values to align.  Assert()s in the code
** below verify that the numbers are aligned correctly.
*/
SQLITE4_PRIVATE void sqlite4ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
  Vdbe *v = pParse->pVdbe;
  int op = 0;
  int regFree1 = 0;
  int regFree2 = 0;
  int r1, r2;

  assert( jumpIfNull==SQLITE4_JUMPIFNULL || jumpIfNull==0 );
  if( NEVER(v==0) )     return;  /* Existance of VDBE checked by caller */
  if( NEVER(pExpr==0) ) return;  /* No way this can happen */
  op = pExpr->op;
  switch( op ){
    case TK_AND: {
      int d2 = sqlite4VdbeMakeLabel(v);
      testcase( jumpIfNull==0 );
      sqlite4ExprCachePush(pParse);
      sqlite4ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE4_JUMPIFNULL);
      sqlite4ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite4VdbeResolveLabel(v, d2);
      sqlite4ExprCachePop(pParse, 1);
      break;
    }
    case TK_OR: {
      testcase( jumpIfNull==0 );
      sqlite4ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
      sqlite4ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
      break;
    }
    case TK_NOT: {
      testcase( jumpIfNull==0 );
      sqlite4ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
      break;
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      assert( TK_LT==OP_Lt );
      assert( TK_LE==OP_Le );
      assert( TK_GT==OP_Gt );
      assert( TK_GE==OP_Ge );
      assert( TK_EQ==OP_Eq );
      assert( TK_NE==OP_Ne );
      testcase( op==TK_LT );
      testcase( op==TK_LE );
      testcase( op==TK_GT );
      testcase( op==TK_GE );
      testcase( op==TK_EQ );
      testcase( op==TK_NE );
      testcase( jumpIfNull==0 );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite4ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, jumpIfNull);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_IS:
    case TK_ISNOT: {
      testcase( op==TK_IS );
      testcase( op==TK_ISNOT );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite4ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      op = (op==TK_IS) ? TK_EQ : TK_NE;
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, SQLITE4_NULLEQ);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      assert( TK_ISNULL==OP_IsNull );
      assert( TK_NOTNULL==OP_NotNull );
      testcase( op==TK_ISNULL );
      testcase( op==TK_NOTNULL );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      sqlite4VdbeAddOp2(v, op, r1, dest);
      testcase( regFree1==0 );
      break;
    }
    case TK_BETWEEN: {
      testcase( jumpIfNull==0 );
      exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull);
      break;
    }
#ifndef SQLITE4_OMIT_SUBQUERY
    case TK_IN: {
      int destIfFalse = sqlite4VdbeMakeLabel(v);
      int destIfNull = jumpIfNull ? dest : destIfFalse;
      sqlite4ExprCodeIN(pParse, pExpr, destIfFalse, destIfNull);
      sqlite4VdbeAddOp2(v, OP_Goto, 0, dest);
      sqlite4VdbeResolveLabel(v, destIfFalse);
      break;
    }
#endif
    default: {
      r1 = sqlite4ExprCodeTemp(pParse, pExpr, &regFree1);
      sqlite4VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
      testcase( regFree1==0 );
      testcase( jumpIfNull==0 );
      break;
    }
  }
  sqlite4ReleaseTempReg(pParse, regFree1);
  sqlite4ReleaseTempReg(pParse, regFree2);  
}

/*
** Generate code for a boolean expression such that a jump is made
** to the label "dest" if the expression is false but execution
** continues straight thru if the expression is true.
**
** If the expression evaluates to NULL (neither true nor false) then
** jump if jumpIfNull is SQLITE4_JUMPIFNULL or fall through if jumpIfNull
** is 0.
*/
SQLITE4_PRIVATE void sqlite4ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
  Vdbe *v = pParse->pVdbe;
  int op = 0;
  int regFree1 = 0;
  int regFree2 = 0;
  int r1, r2;

  assert( jumpIfNull==SQLITE4_JUMPIFNULL || jumpIfNull==0 );
  if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */
  if( pExpr==0 )    return;

  /* The value of pExpr->op and op are related as follows:
  **
  **       pExpr->op            op
  **       ---------          ----------
  **       TK_ISNULL          OP_NotNull
  **       TK_NOTNULL         OP_IsNull
  **       TK_NE              OP_Eq
  **       TK_EQ              OP_Ne
  **       TK_GT              OP_Le
  **       TK_LE              OP_Gt
  **       TK_GE              OP_Lt
  **       TK_LT              OP_Ge
  **
  ** For other values of pExpr->op, op is undefined and unused.
  ** The value of TK_ and OP_ constants are arranged such that we
  ** can compute the mapping above using the following expression.
  ** Assert()s verify that the computation is correct.
  */
  op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1);

  /* Verify correct alignment of TK_ and OP_ constants
  */
  assert( pExpr->op!=TK_ISNULL || op==OP_NotNull );
  assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull );
  assert( pExpr->op!=TK_NE || op==OP_Eq );
  assert( pExpr->op!=TK_EQ || op==OP_Ne );
  assert( pExpr->op!=TK_LT || op==OP_Ge );
  assert( pExpr->op!=TK_LE || op==OP_Gt );
  assert( pExpr->op!=TK_GT || op==OP_Le );
  assert( pExpr->op!=TK_GE || op==OP_Lt );

  switch( pExpr->op ){
    case TK_AND: {
      testcase( jumpIfNull==0 );
      sqlite4ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
      sqlite4ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
      break;
    }
    case TK_OR: {
      int d2 = sqlite4VdbeMakeLabel(v);
      testcase( jumpIfNull==0 );
      sqlite4ExprCachePush(pParse);
      sqlite4ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE4_JUMPIFNULL);
      sqlite4ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
      sqlite4VdbeResolveLabel(v, d2);
      sqlite4ExprCachePop(pParse, 1);
      break;
    }
    case TK_NOT: {
      testcase( jumpIfNull==0 );
      sqlite4ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
      break;
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      testcase( op==TK_LT );
      testcase( op==TK_LE );
      testcase( op==TK_GT );
      testcase( op==TK_GE );
      testcase( op==TK_EQ );
      testcase( op==TK_NE );
      testcase( jumpIfNull==0 );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite4ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, jumpIfNull);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_IS:
    case TK_ISNOT: {
      testcase( pExpr->op==TK_IS );
      testcase( pExpr->op==TK_ISNOT );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite4ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, SQLITE4_NULLEQ);
      testcase( regFree1==0 );
      testcase( regFree2==0 );
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      testcase( op==TK_ISNULL );
      testcase( op==TK_NOTNULL );
      r1 = sqlite4ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      sqlite4VdbeAddOp2(v, op, r1, dest);
      testcase( regFree1==0 );
      break;
    }
    case TK_BETWEEN: {
      testcase( jumpIfNull==0 );
      exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull);
      break;
    }
#ifndef SQLITE4_OMIT_SUBQUERY
    case TK_IN: {
      if( jumpIfNull ){
        sqlite4ExprCodeIN(pParse, pExpr, dest, dest);
      }else{
        int destIfNull = sqlite4VdbeMakeLabel(v);
        sqlite4ExprCodeIN(pParse, pExpr, dest, destIfNull);
        sqlite4VdbeResolveLabel(v, destIfNull);
      }
      break;
    }
#endif
    default: {
      r1 = sqlite4ExprCodeTemp(pParse, pExpr, &regFree1);
      sqlite4VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
      testcase( regFree1==0 );
      testcase( jumpIfNull==0 );
      break;
    }
  }
  sqlite4ReleaseTempReg(pParse, regFree1);
  sqlite4ReleaseTempReg(pParse, regFree2);
}

/*
** Do a deep comparison of two expression trees.  Return 0 if the two
** expressions are completely identical.  Return 1 if they differ only
** by a COLLATE operator at the top level.  Return 2 if there are differences
** other than the top-level COLLATE operator.
**
** Sometimes this routine will return 2 even if the two expressions
** really are equivalent.  If we cannot prove that the expressions are
** identical, we return 2 just to be safe.  So if this routine
** returns 2, then you do not really know for certain if the two
** expressions are the same.  But if you get a 0 or 1 return, then you
** can be sure the expressions are the same.  In the places where
** this routine is used, it does not hurt to get an extra 2 - that
** just might result in some slightly slower code.  But returning
** an incorrect 0 or 1 could lead to a malfunction.
*/
SQLITE4_PRIVATE int sqlite4ExprCompare(Expr *pA, Expr *pB){
  if( pA==0||pB==0 ){
    return pB==pA ? 0 : 2;
  }
  assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
  assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
  if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
    return 2;
  }
  if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
  if( pA->op!=pB->op ) return 2;
  if( sqlite4ExprCompare(pA->pLeft, pB->pLeft) ) return 2;
  if( sqlite4ExprCompare(pA->pRight, pB->pRight) ) return 2;
  if( sqlite4ExprListCompare(pA->x.pList, pB->x.pList) ) return 2;
  if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2;
  if( ExprHasProperty(pA, EP_IntValue) ){
    if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
      return 2;
    }
  }else if( pA->op!=TK_COLUMN && pA->u.zToken ){
    if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
    if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
      return 2;
    }
  }
  if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1;
  if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2;
  return 0;
}

/*
** Compare two ExprList objects.  Return 0 if they are identical and 
** non-zero if they differ in any way.
**
** This routine might return non-zero for equivalent ExprLists.  The
** only consequence will be disabled optimizations.  But this routine
** must never return 0 if the two ExprList objects are different, or
** a malfunction will result.
**
** Two NULL pointers are considered to be the same.  But a NULL pointer
** always differs from a non-NULL pointer.
*/
SQLITE4_PRIVATE int sqlite4ExprListCompare(ExprList *pA, ExprList *pB){
  int i;
  if( pA==0 && pB==0 ) return 0;
  if( pA==0 || pB==0 ) return 1;
  if( pA->nExpr!=pB->nExpr ) return 1;
  for(i=0; i<pA->nExpr; i++){
    Expr *pExprA = pA->a[i].pExpr;
    Expr *pExprB = pB->a[i].pExpr;
    if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
    if( sqlite4ExprCompare(pExprA, pExprB) ) return 1;
  }
  return 0;
}

/*
** Add a new element to the pAggInfo->aCol[] array.  Return the index of
** the new element.  Return a negative number if malloc fails.
*/
static int addAggInfoColumn(sqlite4 *db, AggInfo *pInfo){
  int i;
  pInfo->aCol = sqlite4ArrayAllocate(
       db,
       pInfo->aCol,
       sizeof(pInfo->aCol[0]),
       3,
       &pInfo->nColumn,
       &pInfo->nColumnAlloc,
       &i
  );
  return i;
}    

/*
** Add a new element to the pAggInfo->aFunc[] array.  Return the index of
** the new element.  Return a negative number if malloc fails.
*/
static int addAggInfoFunc(sqlite4 *db, AggInfo *pInfo){
  int i;
  pInfo->aFunc = sqlite4ArrayAllocate(
       db, 
       pInfo->aFunc,
       sizeof(pInfo->aFunc[0]),
       3,
       &pInfo->nFunc,
       &pInfo->nFuncAlloc,
       &i
  );
  return i;
}    

/*
** This is the xExprCallback for a tree walker.  It is used to
** implement sqlite4ExprAnalyzeAggregates().  See sqlite4ExprAnalyzeAggregates
** for additional information.
*/
static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
  int i;
  NameContext *pNC = pWalker->u.pNC;
  Parse *pParse = pNC->pParse;
  SrcList *pSrcList = pNC->pSrcList;
  AggInfo *pAggInfo = pNC->pAggInfo;

  switch( pExpr->op ){
    case TK_AGG_COLUMN:
    case TK_COLUMN: {
      testcase( pExpr->op==TK_AGG_COLUMN );
      testcase( pExpr->op==TK_COLUMN );
      /* Check to see if the column is in one of the tables in the FROM
      ** clause of the aggregate query */
      if( ALWAYS(pSrcList!=0) ){
        SrcListItem *pItem = pSrcList->a;
        for(i=0; i<pSrcList->nSrc; i++, pItem++){
          AggInfoCol *pCol;
          assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
          if( pExpr->iTable==pItem->iCursor ){
            /* If we reach this point, it means that pExpr refers to a table
            ** that is in the FROM clause of the aggregate query.  
            **
            ** Make an entry for the column in pAggInfo->aCol[] if there
            ** is not an entry there already.
            */
            int k;
            pCol = pAggInfo->aCol;
            for(k=0; k<pAggInfo->nColumn; k++, pCol++){
              if( pCol->iTable==pExpr->iTable &&
                  pCol->iColumn==pExpr->iColumn ){
                break;
              }
            }
            if( (k>=pAggInfo->nColumn)
             && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 
            ){
              pCol = &pAggInfo->aCol[k];
              pCol->pTab = pExpr->pTab;
              pCol->iTable = pExpr->iTable;
              pCol->iColumn = pExpr->iColumn;
              pCol->iMem = ++pParse->nMem;
              pCol->iSorterColumn = -1;
              pCol->pExpr = pExpr;
              if( pAggInfo->pGroupBy ){
                int j, n;
                ExprList *pGB = pAggInfo->pGroupBy;
                ExprListItem *pTerm = pGB->a;
                n = pGB->nExpr;
                for(j=0; j<n; j++, pTerm++){
                  Expr *pE = pTerm->pExpr;
                  if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable &&
                      pE->iColumn==pExpr->iColumn ){
                    pCol->iSorterColumn = j;
                    break;
                  }
                }
              }
              if( pCol->iSorterColumn<0 ){
                pCol->iSorterColumn = pAggInfo->nSortingColumn++;
              }
            }
            /* There is now an entry for pExpr in pAggInfo->aCol[] (either
            ** because it was there before or because we just created it).
            ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
            ** pAggInfo->aCol[] entry.
            */
            ExprSetIrreducible(pExpr);
            pExpr->pAggInfo = pAggInfo;
            pExpr->op = TK_AGG_COLUMN;
            pExpr->iAgg = (i16)k;
            break;
          } /* endif pExpr->iTable==pItem->iCursor */
        } /* end loop over pSrcList */
      }
      return WRC_Prune;
    }
    case TK_AGG_FUNCTION: {
      /* The pNC->nDepth==0 test causes aggregate functions in subqueries
      ** to be ignored */
      if( pNC->nDepth==0 ){
        /* Check to see if pExpr is a duplicate of another aggregate 
        ** function that is already in the pAggInfo structure
        */
        AggInfoFunc *pItem = pAggInfo->aFunc;
        for(i=0; i<pAggInfo->nFunc; i++, pItem++){
          if( sqlite4ExprCompare(pItem->pExpr, pExpr)==0 ){
            break;
          }
        }
        if( i>=pAggInfo->nFunc ){
          /* pExpr is original.  Make a new entry in pAggInfo->aFunc[]
          */
          i = addAggInfoFunc(pParse->db, pAggInfo);
          if( i>=0 ){
            assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
            pItem = &pAggInfo->aFunc[i];
            pItem->pExpr = pExpr;
            pItem->iMem = ++pParse->nMem;
            assert( !ExprHasProperty(pExpr, EP_IntValue) );
            pItem->pFunc = sqlite4FindFunction(pParse->db,
                   pExpr->u.zToken, sqlite4Strlen30(pExpr->u.zToken),
                   pExpr->x.pList ? pExpr->x.pList->nExpr : 0, 0);
            if( pExpr->flags & EP_Distinct ){
              pItem->iDistinct = pParse->nTab++;
            }else{
              pItem->iDistinct = -1;
            }
          }
        }
        /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
        */
        assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
        ExprSetIrreducible(pExpr);
        pExpr->iAgg = (i16)i;
        pExpr->pAggInfo = pAggInfo;
        return WRC_Prune;
      }
    }
  }
  return WRC_Continue;
}
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
  NameContext *pNC = pWalker->u.pNC;
  if( pNC->nDepth==0 ){
    pNC->nDepth++;
    sqlite4WalkSelect(pWalker, pSelect);
    pNC->nDepth--;
    return WRC_Prune;
  }else{
    return WRC_Continue;
  }
}

/*
** Analyze the given expression looking for aggregate functions and
** for variables that need to be added to the pParse->aAgg[] array.
** Make additional entries to the pParse->aAgg[] array as necessary.
**
** This routine should only be called after the expression has been
** analyzed by sqlite4ResolveExprNames().
*/
SQLITE4_PRIVATE void sqlite4ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
  Walker w;
  w.xExprCallback = analyzeAggregate;
  w.xSelectCallback = analyzeAggregatesInSelect;
  w.u.pNC = pNC;
  assert( pNC->pSrcList!=0 );
  sqlite4WalkExpr(&w, pExpr);
}

/*
** Call sqlite4ExprAnalyzeAggregates() for every expression in an
** expression list.  Return the number of errors.
**
** If an error is found, the analysis is cut short.
*/
SQLITE4_PRIVATE void sqlite4ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
  ExprListItem *pItem;
  int i;
  if( pList ){
    for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
      sqlite4ExprAnalyzeAggregates(pNC, pItem->pExpr);
    }
  }
}

/*
** Allocate a single new register for use to hold some intermediate result.
*/
SQLITE4_PRIVATE int sqlite4GetTempReg(Parse *pParse){
  if( pParse->nTempReg==0 ){
    return ++pParse->nMem;
  }
  return pParse->aTempReg[--pParse->nTempReg];
}

/*
** Deallocate a register, making available for reuse for some other
** purpose.
**
** If a register is currently being used by the column cache, then
** the dallocation is deferred until the column cache line that uses
** the register becomes stale.
*/
SQLITE4_PRIVATE void sqlite4ReleaseTempReg(Parse *pParse, int iReg){
  if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
    int i;
    ParseYColCache *p;
    for(i=0, p=pParse->aColCache; i<SQLITE4_N_COLCACHE; i++, p++){
      if( p->iReg==iReg ){
        p->tempReg = 1;
        return;
      }
    }
    pParse->aTempReg[pParse->nTempReg++] = iReg;
  }
}

/*
** Allocate or deallocate a block of nReg consecutive registers
*/
SQLITE4_PRIVATE int sqlite4GetTempRange(Parse *pParse, int nReg){
  int i, n;
  i = pParse->iRangeReg;
  n = pParse->nRangeReg;
  if( nReg<=n ){
    assert( !usedAsColumnCache(pParse, i, i+n-1) );
    pParse->iRangeReg += nReg;
    pParse->nRangeReg -= nReg;
  }else{
    i = pParse->nMem+1;
    pParse->nMem += nReg;
  }
  return i;
}
SQLITE4_PRIVATE void sqlite4ReleaseTempRange(Parse *pParse, int iReg, int nReg){
  sqlite4ExprCacheRemove(pParse, iReg, nReg);
  if( nReg>pParse->nRangeReg ){
    pParse->nRangeReg = nReg;
    pParse->iRangeReg = iReg;
  }
}

/*
** Mark all temporary registers as being unavailable for reuse.
*/
SQLITE4_PRIVATE void sqlite4ClearTempRegCache(Parse *pParse){
  pParse->nTempReg = 0;
  pParse->nRangeReg = 0;
}

/************** End of expr.c ************************************************/
/************** Begin file alter.c *******************************************/
/*
** 2005 February 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
*/

/*
** The code in this file only exists if we are not omitting the
** ALTER TABLE logic from the build.
*/
#ifndef SQLITE4_OMIT_ALTERTABLE


/*
** This function is used by SQL generated to implement the 
** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
** CREATE INDEX command. The second is a table name. The table name in 
** the CREATE TABLE or CREATE INDEX statement is replaced with the third
** argument and the result returned. Examples:
**
** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
**     -> 'CREATE TABLE def(a, b, c)'
**
** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
**     -> 'CREATE INDEX i ON def(a, b, c)'
*/
static void renameTableFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **argv
){
  char const *zSql = sqlite4_value_text(argv[0], 0);
  char const *zTableName = sqlite4_value_text(argv[1], 0);

  int token;
  Token tname;
  char const *zCsr = zSql;
  int len = 0;
  char *zRet;

  sqlite4 *db = sqlite4_context_db_handle(context);

  UNUSED_PARAMETER(NotUsed);

  /* The principle used to locate the table name in the CREATE TABLE 
  ** statement is that the table name is the first non-space token that
  ** is immediately followed by a TK_LP or TK_USING token.
  */
  if( zSql ){
    do {
      if( !*zCsr ){
        /* Ran out of input before finding an opening bracket. Return NULL. */
        return;
      }

      /* Store the token that zCsr points to in tname. */
      tname.z = (char*)zCsr;
      tname.n = len;

      /* Advance zCsr to the next token. Store that token type in 'token',
      ** and its length in 'len' (to be used next iteration of this loop).
      */
      do {
        zCsr += len;
        len = sqlite4GetToken((u8*)zCsr, &token);
      } while( token==TK_SPACE );
      assert( len>0 );
    } while( token!=TK_LP && token!=TK_USING );

    zRet = sqlite4MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, 
       zTableName, tname.z+tname.n);
    sqlite4_result_text(context, zRet, -1, SQLITE4_TRANSIENT, 0);
    sqlite4DbFree(db, zRet);
  }
}

/*
** This C function implements an SQL user function that is used by SQL code
** generated by the ALTER TABLE ... RENAME command to modify the definition
** of any foreign key constraints that use the table being renamed as the 
** parent table. It is passed three arguments:
**
**   1) The complete text of the CREATE TABLE statement being modified,
**   2) The old name of the table being renamed, and
**   3) The new name of the table being renamed.
**
** It returns the new CREATE TABLE statement. For example:
**
**   sqlite_rename_parent('CREATE TABLE t1(a REFERENCES t2)', 't2', 't3')
**       -> 'CREATE TABLE t1(a REFERENCES t3)'
*/
#ifndef SQLITE4_OMIT_FOREIGN_KEY
static void renameParentFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **argv
){
  sqlite4 *db = sqlite4_context_db_handle(context);
  char *zOutput = 0;
  char *zResult;
  char const *zInput = sqlite4_value_text(argv[0], 0);
  char const *zOld = sqlite4_value_text(argv[1], 0);
  char const *zNew = sqlite4_value_text(argv[2], 0);

  const char *z;                  /* Pointer to token */
  int n;                          /* Length of token z */
  int token;                      /* Type of token */

  UNUSED_PARAMETER(NotUsed);
  for(z=zInput; *z; z=z+n){
    n = sqlite4GetToken((u8*)z, &token);
    if( token==TK_REFERENCES ){
      char *zParent;
      do {
        z += n;
        n = sqlite4GetToken((u8*)z, &token);
      }while( token==TK_SPACE );

      zParent = sqlite4DbStrNDup(db, (const char *)z, n);
      if( zParent==0 ) break;
      sqlite4Dequote(zParent);
      if( 0==sqlite4_stricmp(zOld, zParent) ){
        char *zOut = sqlite4MPrintf(db, "%s%.*s\"%w\"", 
            (zOutput?zOutput:""), z-zInput, zInput, zNew
        );
        sqlite4DbFree(db, zOutput);
        zOutput = zOut;
        zInput = &z[n];
      }
      sqlite4DbFree(db, zParent);
    }
  }

  zResult = sqlite4MPrintf(db, "%s%s", (zOutput?zOutput:""), zInput), 
  sqlite4_result_text(context, zResult, -1, SQLITE4_TRANSIENT, 0);
  sqlite4DbFree(db, zOutput);
  sqlite4DbFree(db, zResult);
}
#endif

#ifndef SQLITE4_OMIT_TRIGGER
/* This function is used by SQL generated to implement the
** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER 
** statement. The second is a table name. The table name in the CREATE 
** TRIGGER statement is replaced with the third argument and the result 
** returned. This is analagous to renameTableFunc() above, except for CREATE
** TRIGGER, not CREATE INDEX and CREATE TABLE.
*/
static void renameTriggerFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **argv
){
  char const *zSql = sqlite4_value_text(argv[0], 0);
  char const *zTableName = sqlite4_value_text(argv[1], 0);

  int token;
  Token tname;
  int dist = 3;
  char const *zCsr = zSql;
  int len = 0;
  char *zRet;
  sqlite4 *db = sqlite4_context_db_handle(context);

  UNUSED_PARAMETER(NotUsed);

  /* The principle used to locate the table name in the CREATE TRIGGER 
  ** statement is that the table name is the first token that is immediatedly
  ** preceded by either TK_ON or TK_DOT and immediatedly followed by one
  ** of TK_WHEN, TK_BEGIN or TK_FOR.
  */
  if( zSql ){
    do {

      if( !*zCsr ){
        /* Ran out of input before finding the table name. Return NULL. */
        return;
      }

      /* Store the token that zCsr points to in tname. */
      tname.z = (char*)zCsr;
      tname.n = len;

      /* Advance zCsr to the next token. Store that token type in 'token',
      ** and its length in 'len' (to be used next iteration of this loop).
      */
      do {
        zCsr += len;
        len = sqlite4GetToken((u8*)zCsr, &token);
      }while( token==TK_SPACE );
      assert( len>0 );

      /* Variable 'dist' stores the number of tokens read since the most
      ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN 
      ** token is read and 'dist' equals 2, the condition stated above
      ** to be met.
      **
      ** Note that ON cannot be a database, table or column name, so
      ** there is no need to worry about syntax like 
      ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
      */
      dist++;
      if( token==TK_DOT || token==TK_ON ){
        dist = 0;
      }
    } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );

    /* Variable tname now contains the token that is the old table-name
    ** in the CREATE TRIGGER statement.
    */
    zRet = sqlite4MPrintf(db, "%.*s\"%w\"%s", tname.z - zSql, zSql, 
       zTableName, tname.z+tname.n);
    sqlite4_result_text(context, zRet, -1, SQLITE4_TRANSIENT, 0);
    sqlite4DbFree(db, zRet);
  }
}
#endif   /* !SQLITE4_OMIT_TRIGGER */

/*
** Register built-in functions used to help implement ALTER TABLE
*/
SQLITE4_PRIVATE void sqlite4AlterFunctions(sqlite4_env *pEnv){
  static FuncDef aAlterTableFuncs[] = {
    FUNCTION(sqlite_rename_table,   2, 0, 0, renameTableFunc),
#ifndef SQLITE4_OMIT_TRIGGER
    FUNCTION(sqlite_rename_trigger, 2, 0, 0, renameTriggerFunc),
#endif
#ifndef SQLITE4_OMIT_FOREIGN_KEY
    FUNCTION(sqlite_rename_parent,  3, 0, 0, renameParentFunc),
#endif
  };
  int i;
  FuncDefTable *pFuncTab = &pEnv->aGlobalFuncs;
  FuncDef *aFunc = (FuncDef*)aAlterTableFuncs;

  for(i=0; i<ArraySize(aAlterTableFuncs); i++){
    sqlite4FuncDefInsert(pFuncTab, &aFunc[i], 1);
  }
}

/*
** This function is used to create the text of expressions of the form:
**
**   name=<constant1> OR name=<constant2> OR ...
**
** If argument zWhere is NULL, then a pointer string containing the text 
** "name=<constant>" is returned, where <constant> is the quoted version
** of the string passed as argument zConstant. The returned buffer is
** allocated using sqlite4DbMalloc(). It is the responsibility of the
** caller to ensure that it is eventually freed.
**
** If argument zWhere is not NULL, then the string returned is 
** "<where> OR name=<constant>", where <where> is the contents of zWhere.
** In this case zWhere is passed to sqlite4DbFree() before returning.
** 
*/
static char *whereOrName(sqlite4 *db, char *zWhere, char *zConstant){
  char *zNew;
  if( !zWhere ){
    zNew = sqlite4MPrintf(db, "name=%Q", zConstant);
  }else{
    zNew = sqlite4MPrintf(db, "%s OR name=%Q", zWhere, zConstant);
    sqlite4DbFree(db, zWhere);
  }
  return zNew;
}

#if !defined(SQLITE4_OMIT_FOREIGN_KEY) && !defined(SQLITE4_OMIT_TRIGGER)
/*
** Generate the text of a WHERE expression which can be used to select all
** tables that have foreign key constraints that refer to table pTab (i.e.
** constraints for which pTab is the parent table) from the sqlite_master
** table.
*/
static char *whereForeignKeys(Parse *pParse, Table *pTab){
  FKey *p;
  char *zWhere = 0;
  for(p=sqlite4FkReferences(pTab); p; p=p->pNextTo){
    zWhere = whereOrName(pParse->db, zWhere, p->pFrom->zName);
  }
  return zWhere;
}
#endif

/*
** Generate the text of a WHERE expression which can be used to select all
** temporary triggers on table pTab from the sqlite_temp_master table. If
** table pTab has no temporary triggers, or is itself stored in the 
** temporary database, NULL is returned.
*/
static char *whereTempTriggers(Parse *pParse, Table *pTab){
  Trigger *pTrig;
  char *zWhere = 0;
  const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */

  /* If the table is not located in the temp-db (in which case NULL is 
  ** returned, loop through the tables list of triggers. For each trigger
  ** that is not part of the temp-db schema, add a clause to the WHERE 
  ** expression being built up in zWhere.
  */
  if( pTab->pSchema!=pTempSchema ){
    sqlite4 *db = pParse->db;
    for(pTrig=sqlite4TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
      if( pTrig->pSchema==pTempSchema ){
        zWhere = whereOrName(db, zWhere, pTrig->zName);
      }
    }
  }
  if( zWhere ){
    char *zNew = sqlite4MPrintf(pParse->db, "type='trigger' AND (%s)", zWhere);
    sqlite4DbFree(pParse->db, zWhere);
    zWhere = zNew;
  }
  return zWhere;
}

/*
** Generate code to drop and reload the internal representation of table
** pTab from the database, including triggers and temporary triggers.
** Argument zName is the name of the table in the database schema at
** the time the generated code is executed. This can be different from
** pTab->zName if this function is being called to code part of an 
** "ALTER TABLE RENAME TO" statement.
*/
static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
  Vdbe *v;
  char *zWhere;
  int iDb;                   /* Index of database containing pTab */
#ifndef SQLITE4_OMIT_TRIGGER
  Trigger *pTrig;
#endif

  v = sqlite4GetVdbe(pParse);
  if( NEVER(v==0) ) return;
  iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
  assert( iDb>=0 );

#ifndef SQLITE4_OMIT_TRIGGER
  /* Drop any table triggers from the internal schema. */
  for(pTrig=sqlite4TriggerList(pParse, pTab); pTrig; pTrig=pTrig->pNext){
    int iTrigDb = sqlite4SchemaToIndex(pParse->db, pTrig->pSchema);
    assert( iTrigDb==iDb || iTrigDb==1 );
    sqlite4VdbeAddOp4(v, OP_DropTrigger, iTrigDb, 0, 0, pTrig->zName, 0);
  }
#endif

  /* Drop the table and index from the internal schema.  */
  sqlite4VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);

  /* Reload the table, index and permanent trigger schemas. */
  zWhere = sqlite4MPrintf(pParse->db, "tbl_name=%Q", zName);
  if( !zWhere ) return;
  sqlite4VdbeAddParseSchemaOp(v, iDb, zWhere);

#ifndef SQLITE4_OMIT_TRIGGER
  /* Now, if the table is not stored in the temp database, reload any temp 
  ** triggers. Don't use IN(...) in case SQLITE4_OMIT_SUBQUERY is defined. 
  */
  if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
    sqlite4VdbeAddParseSchemaOp(v, 1, zWhere);
  }
#endif
}

/*
** Parameter zName is the name of a table that is about to be altered
** (either with ALTER TABLE ... RENAME TO or ALTER TABLE ... ADD COLUMN).
** If the table is a system table, this function leaves an error message
** in pParse->zErr (system tables may not be altered) and returns non-zero.
**
** Or, if zName is not a system table, zero is returned.
*/
static int isSystemTable(Parse *pParse, const char *zName){
  if( sqlite4Strlen30(zName)>6 && 0==sqlite4_strnicmp(zName, "sqlite_", 7) ){
    sqlite4ErrorMsg(pParse, "table %s may not be altered", zName);
    return 1;
  }
  return 0;
}

/*
** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" 
** command. 
*/
SQLITE4_PRIVATE void sqlite4AlterRenameTable(
  Parse *pParse,            /* Parser context. */
  SrcList *pSrc,            /* The table to rename. */
  Token *pName              /* The new table name. */
){
  int iDb;                  /* Database that contains the table */
  char *zDb;                /* Name of database iDb */
  Table *pTab;              /* Table being renamed */
  char *zName = 0;          /* NULL-terminated version of pName */ 
  sqlite4 *db = pParse->db; /* Database connection */
  int nTabName;             /* Number of UTF-8 characters in zTabName */
  const char *zTabName;     /* Original name of the table */
  Vdbe *v;
#ifndef SQLITE4_OMIT_TRIGGER
  char *zWhere = 0;         /* Where clause to locate temp triggers */
#endif
  VTable *pVTab = 0;        /* Non-zero if this is a v-tab with an xRename() */
  int savedDbFlags;         /* Saved value of db->flags */

  savedDbFlags = db->flags;  
  if( NEVER(db->mallocFailed) ) goto exit_rename_table;
  assert( pSrc->nSrc==1 );

  pTab = sqlite4LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
  if( !pTab ) goto exit_rename_table;
  iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
  zDb = db->aDb[iDb].zName;
  db->flags |= SQLITE4_PreferBuiltin;

  /* Get a NULL terminated version of the new table name. */
  zName = sqlite4NameFromToken(db, pName);
  if( !zName ) goto exit_rename_table;

  /* Check that a table or index named 'zName' does not already exist
  ** in database iDb. If so, this is an error.
  */
  if( sqlite4FindTable(db, zName, zDb) || sqlite4FindIndex(db, zName, zDb) ){
    sqlite4ErrorMsg(pParse, 
        "there is already another table or index with this name: %s", zName);
    goto exit_rename_table;
  }

  /* Make sure it is not a system table being altered, or a reserved name
  ** that the table is being renamed to.
  */
  if( SQLITE4_OK!=isSystemTable(pParse, pTab->zName) ){
    goto exit_rename_table;
  }
  if( SQLITE4_OK!=sqlite4CheckObjectName(pParse, zName) ){ goto
    exit_rename_table;
  }

#ifndef SQLITE4_OMIT_VIEW
  if( pTab->pSelect ){
    sqlite4ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
    goto exit_rename_table;
  }
#endif

#ifndef SQLITE4_OMIT_AUTHORIZATION
  /* Invoke the authorization callback. */
  if( sqlite4AuthCheck(pParse, SQLITE4_ALTER_TABLE, zDb, pTab->zName, 0) ){
    goto exit_rename_table;
  }
#endif

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( sqlite4ViewGetColumnNames(pParse, pTab) ){
    goto exit_rename_table;
  }
  if( IsVirtual(pTab) ){
    pVTab = sqlite4GetVTable(db, pTab);
    if( pVTab->pVtab->pModule->xRename==0 ){
      pVTab = 0;
    }
  }
#endif

  /* Begin a transaction and code the VerifyCookie for database iDb. 
  ** Then modify the schema cookie (since the ALTER TABLE modifies the
  ** schema). Open a statement transaction if the table is a virtual
  ** table.
  */
  v = sqlite4GetVdbe(pParse);
  if( v==0 ){
    goto exit_rename_table;
  }
  sqlite4BeginWriteOperation(pParse, pVTab!=0, iDb);
  sqlite4ChangeCookie(pParse, iDb);

  /* If this is a virtual table, invoke the xRename() function if
  ** one is defined. The xRename() callback will modify the names
  ** of any resources used by the v-table implementation (including other
  ** SQLite tables) that are identified by the name of the virtual table.
  */
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( pVTab ){
    int i = ++pParse->nMem;
    sqlite4VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0);
    sqlite4VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
    sqlite4MayAbort(pParse);
  }
#endif

  /* figure out how many UTF-8 characters are in zName */
  zTabName = pTab->zName;
  nTabName = sqlite4Utf8CharLen(zTabName, -1);

#if !defined(SQLITE4_OMIT_FOREIGN_KEY) && !defined(SQLITE4_OMIT_TRIGGER)
  if( db->flags&SQLITE4_ForeignKeys ){
    /* If foreign-key support is enabled, rewrite the CREATE TABLE 
    ** statements corresponding to all child tables of foreign key constraints
    ** for which the renamed table is the parent table.  */
    if( (zWhere=whereForeignKeys(pParse, pTab))!=0 ){
      sqlite4NestedParse(pParse, 
          "UPDATE \"%w\".%s SET "
              "sql = sqlite_rename_parent(sql, %Q, %Q) "
              "WHERE %s;", zDb, SCHEMA_TABLE(iDb), zTabName, zName, zWhere);
      sqlite4DbFree(db, zWhere);
    }
  }
#endif

  /* Modify the sqlite_master table to use the new table name. */
  sqlite4NestedParse(pParse,
      "UPDATE %Q.%s SET "
#ifdef SQLITE4_OMIT_TRIGGER
          "sql = sqlite_rename_table(sql, %Q), "
#else
          "sql = CASE "
            "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
            "ELSE sqlite_rename_table(sql, %Q) END, "
#endif
          "tbl_name = %Q, "
          "name = CASE "
            "WHEN type='table' THEN %Q "
            "WHEN name LIKE 'sqlite_%%_unique%%' AND type='index' THEN "
             "'sqlite_' || %Q || substr(name,%d+8) "
            "ELSE name END "
      "WHERE tbl_name=%Q AND "
          "(type='table' OR type='index' OR type='trigger');", 
      zDb, SCHEMA_TABLE(iDb), zName, zName, zName, 
#ifndef SQLITE4_OMIT_TRIGGER
      zName,
#endif
      zName, nTabName, zTabName
  );

#ifndef SQLITE4_OMIT_AUTOINCREMENT
  /* If the sqlite_sequence table exists in this database, then update 
  ** it with the new table name.
  */
  if( sqlite4FindTable(db, "sqlite_sequence", zDb) ){
    sqlite4NestedParse(pParse,
        "UPDATE \"%w\".sqlite_sequence set name = %Q WHERE name = %Q",
        zDb, zName, pTab->zName);
  }
#endif

#ifndef SQLITE4_OMIT_TRIGGER
  /* If there are TEMP triggers on this table, modify the sqlite_temp_master
  ** table. Don't do this if the table being ALTERed is itself located in
  ** the temp database.
  */
  if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
    sqlite4NestedParse(pParse, 
        "UPDATE sqlite_temp_master SET "
            "sql = sqlite_rename_trigger(sql, %Q), "
            "tbl_name = %Q "
            "WHERE %s;", zName, zName, zWhere);
    sqlite4DbFree(db, zWhere);
  }
#endif

#if !defined(SQLITE4_OMIT_FOREIGN_KEY) && !defined(SQLITE4_OMIT_TRIGGER)
  if( db->flags&SQLITE4_ForeignKeys ){
    FKey *p;
    for(p=sqlite4FkReferences(pTab); p; p=p->pNextTo){
      Table *pFrom = p->pFrom;
      if( pFrom!=pTab ){
        reloadTableSchema(pParse, p->pFrom, pFrom->zName);
      }
    }
  }
#endif

  /* Drop and reload the internal table schema. */
  reloadTableSchema(pParse, pTab, zName);

exit_rename_table:
  sqlite4SrcListDelete(db, pSrc);
  sqlite4DbFree(db, zName);
  db->flags = savedDbFlags;
}


/*
** This function is called after an "ALTER TABLE ... ADD" statement
** has been parsed. Argument pColDef contains the text of the new
** column definition.
**
** The Table structure pParse->pNewTable was extended to include
** the new column during parsing.
*/
SQLITE4_PRIVATE void sqlite4AlterFinishAddColumn(Parse *pParse, Token *pColDef){
  Table *pNew;              /* Copy of pParse->pNewTable */
  Table *pTab;              /* Table being altered */
  int iDb;                  /* Database number */
  const char *zDb;          /* Database name */
  const char *zTab;         /* Table name */
  char *zCol;               /* Null-terminated column definition */
  Column *pCol;             /* The new column */
  Expr *pDflt;              /* Default value for the new column */
  sqlite4 *db;              /* The database connection; */

  db = pParse->db;
  if( pParse->nErr || db->mallocFailed ) return;
  pNew = pParse->pNewTable;
  assert( pNew );

  iDb = sqlite4SchemaToIndex(db, pNew->pSchema);
  zDb = db->aDb[iDb].zName;
  zTab = &pNew->zName[16];  /* Skip the "sqlite_altertab_" prefix on the name */
  pCol = &pNew->aCol[pNew->nCol-1];
  pDflt = pCol->pDflt;
  pTab = sqlite4FindTable(db, zTab, zDb);
  assert( pTab );

#ifndef SQLITE4_OMIT_AUTHORIZATION
  /* Invoke the authorization callback. */
  if( sqlite4AuthCheck(pParse, SQLITE4_ALTER_TABLE, zDb, pTab->zName, 0) ){
    return;
  }
#endif

  /* If the default value for the new column was specified with a 
  ** literal NULL, then set pDflt to 0. This simplifies checking
  ** for an SQL NULL default below.
  */
  if( pDflt && pDflt->op==TK_NULL ){
    pDflt = 0;
  }

  /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
  ** If there is a NOT NULL constraint, then the default value for the
  ** column must not be NULL.
  */
  if( pCol->iPrimKey>0 ){
    sqlite4ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
    return;
  }
  if( pNew->pIndex ){
    sqlite4ErrorMsg(pParse, "Cannot add a UNIQUE column");
    return;
  }
  if( (db->flags&SQLITE4_ForeignKeys) && pNew->pFKey && pDflt ){
    sqlite4ErrorMsg(pParse, 
        "Cannot add a REFERENCES column with non-NULL default value");
    return;
  }
  if( pCol->notNull && !pDflt ){
    sqlite4ErrorMsg(pParse, 
        "Cannot add a NOT NULL column with default value NULL");
    return;
  }

  /* Ensure the default expression is something that sqlite4ValueFromExpr()
  ** can handle (i.e. not CURRENT_TIME etc.)
  */
  if( pDflt ){
    sqlite4_value *pVal;
    if( sqlite4ValueFromExpr(db, pDflt, SQLITE4_UTF8, SQLITE4_AFF_NONE, &pVal) ){
      db->mallocFailed = 1;
      return;
    }
    if( !pVal ){
      sqlite4ErrorMsg(pParse, "Cannot add a column with non-constant default");
      return;
    }
    sqlite4ValueFree(pVal);
  }

  /* Modify the CREATE TABLE statement. */
  zCol = sqlite4DbStrNDup(db, (char*)pColDef->z, pColDef->n);
  if( zCol ){
    char *zEnd = &zCol[pColDef->n-1];
    int savedDbFlags = db->flags;
    while( zEnd>zCol && (*zEnd==';' || sqlite4Isspace(*zEnd)) ){
      *zEnd-- = '\0';
    }
    db->flags |= SQLITE4_PreferBuiltin;
    sqlite4NestedParse(pParse, 
        "UPDATE \"%w\".%s SET "
          "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
        "WHERE type = 'table' AND name = %Q", 
      zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
      zTab
    );
    sqlite4DbFree(db, zCol);
    db->flags = savedDbFlags;
  }

  /* Reload the schema of the modified table. */
  reloadTableSchema(pParse, pTab, pTab->zName);
}

/*
** This function is called by the parser after the table-name in
** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument 
** pSrc is the full-name of the table being altered.
**
** This routine makes a (partial) copy of the Table structure
** for the table being altered and sets Parse.pNewTable to point
** to it. Routines called by the parser as the column definition
** is parsed (i.e. sqlite4AddColumn()) add the new Column data to 
** the copy. The copy of the Table structure is deleted by tokenize.c 
** after parsing is finished.
**
** Routine sqlite4AlterFinishAddColumn() will be called to complete
** coding the "ALTER TABLE ... ADD" statement.
*/
SQLITE4_PRIVATE void sqlite4AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
  Table *pNew;
  Table *pTab;
  Vdbe *v;
  int iDb;
  int i;
  int nAlloc;
  sqlite4 *db = pParse->db;

  /* Look up the table being altered. */
  assert( pParse->pNewTable==0 );
  if( db->mallocFailed ) goto exit_begin_add_column;
  pTab = sqlite4LocateTable(pParse, 0, pSrc->a[0].zName, pSrc->a[0].zDatabase);
  if( !pTab ) goto exit_begin_add_column;

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( IsVirtual(pTab) ){
    sqlite4ErrorMsg(pParse, "virtual tables may not be altered");
    goto exit_begin_add_column;
  }
#endif

  /* Make sure this is not an attempt to ALTER a view. */
  if( pTab->pSelect ){
    sqlite4ErrorMsg(pParse, "Cannot add a column to a view");
    goto exit_begin_add_column;
  }
  if( SQLITE4_OK!=isSystemTable(pParse, pTab->zName) ){
    goto exit_begin_add_column;
  }

  assert( pTab->addColOffset>0 );
  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);

  /* Put a copy of the Table struct in Parse.pNewTable for the
  ** sqlite4AddColumn() function and friends to modify.  But modify
  ** the name by adding an "sqlite_altertab_" prefix.  By adding this
  ** prefix, we insure that the name will not collide with an existing
  ** table because user table are not allowed to have the "sqlite_"
  ** prefix on their name.
  */
  pNew = (Table*)sqlite4DbMallocZero(db, sizeof(Table));
  if( !pNew ) goto exit_begin_add_column;
  pParse->pNewTable = pNew;
  pNew->nRef = 1;
  pNew->nCol = pTab->nCol;
  assert( pNew->nCol>0 );
  nAlloc = (((pNew->nCol-1)/8)*8)+8;
  assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
  pNew->aCol = (Column*)sqlite4DbMallocZero(db, sizeof(Column)*nAlloc);
  pNew->zName = sqlite4MPrintf(db, "sqlite_altertab_%s", pTab->zName);
  if( !pNew->aCol || !pNew->zName ){
    db->mallocFailed = 1;
    goto exit_begin_add_column;
  }
  memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
  for(i=0; i<pNew->nCol; i++){
    Column *pCol = &pNew->aCol[i];
    pCol->zName = sqlite4DbStrDup(db, pCol->zName);
    pCol->zColl = 0;
    pCol->zType = 0;
    pCol->pDflt = 0;
    pCol->zDflt = 0;
  }
  pNew->pSchema = db->aDb[iDb].pSchema;
  pNew->addColOffset = pTab->addColOffset;
  pNew->nRef = 1;

  /* Begin a transaction and increment the schema cookie.  */
  sqlite4BeginWriteOperation(pParse, 0, iDb);
  v = sqlite4GetVdbe(pParse);
  if( !v ) goto exit_begin_add_column;
  sqlite4ChangeCookie(pParse, iDb);

exit_begin_add_column:
  sqlite4SrcListDelete(db, pSrc);
  return;
}
#endif  /* SQLITE4_ALTER_TABLE */

/************** End of alter.c ***********************************************/
/************** Begin file analyze.c *****************************************/
/*
** 2005 July 8
**
** 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 associated with the ANALYZE command.
**
** The ANALYZE command gather statistics about the content of tables
** and indices.  These statistics are made available to the query planner
** to help it make better decisions about how to perform queries.
**
** The following system tables are or have been supported:
**
**    CREATE TABLE sqlite_stat1(tbl, idx, stat);
**    CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);
**
** The sqlite_stat3 table is only created if SQLITE4_ENABLE_STAT3 is
** defined.
**
** Format of sqlite_stat1:
**
** There is normally one row per index, with the index identified by the
** name in the idx column.  The tbl column is the name of the table to
** which the index belongs.  In each such row, the stat column will be
** a string consisting of a list of integers.  The first integer in this
** list is the number of rows in the index and in the table.  The second
** integer is the average number of rows in the index that have the same
** value in the first column of the index.  The third integer is the average
** number of rows in the index that have the same value for the first two
** columns.  The N-th integer (for N>1) is the average number of rows in 
** the index which have the same value for the first N-1 columns.  For
** a K-column index, there will be K+1 integers in the stat column.  If
** the index is unique, then the last integer will be 1.
**
** The list of integers in the stat column can optionally be followed
** by the keyword "unordered".  The "unordered" keyword, if it is present,
** must be separated from the last integer by a single space.  If the
** "unordered" keyword is present, then the query planner assumes that
** the index is unordered and will not use the index for a range query.
** 
** If the sqlite_stat1.idx column is NULL, then the sqlite_stat1.stat
** column contains a single integer which is the (estimated) number of
** rows in the table identified by sqlite_stat1.tbl.
**
** Format for sqlite_stat3:
**
** The sqlite_stat3 table may contain multiple entries for each index.
** The idx column names the index and the tbl column contains the name
** of the indexed table. If the idx and tbl columns are the same, then the 
** sample is of the PRIMARY KEY index. The sample column is a value taken 
** from the left-most column of the index encoded using the key-encoding. 
** The nEq column is the approximate number of entires in the index whose 
** left-most column exactly matches the sample. nLt is the approximate 
** number of entires whose left-most column is less than the sample. The 
** nDLt column is the approximate number of distinct left-most entries in 
** the index that are less than the sample.
**
** Future versions of SQLite might change to store a string containing
** multiple integers values in the nDLt column of sqlite_stat3.  The first
** integer will be the number of prior index entries that are distinct in
** the left-most column.  The second integer will be the number of prior index
** entries that are distinct in the first two columns.  The third integer
** will be the number of prior index entries that are distinct in the first
** three columns.  And so forth.  With that extension, the nDLt field is
** similar in function to the sqlite_stat1.stat field.
**
** There can be an arbitrary number of sqlite_stat3 entries per index.
** The ANALYZE command will typically generate sqlite_stat3 tables
** that contain between 10 and 40 samples which are distributed across
** the key space, though not uniformly, and which include samples with
** largest possible nEq values.
*/
#ifndef SQLITE4_OMIT_ANALYZE

/*
** This routine generates code that opens the sqlite_stat1 table for
** writing with cursor iStatCur. If the library was built with the
** SQLITE4_ENABLE_STAT3 macro defined, then the sqlite_stat3 table is
** opened for writing using cursor (iStatCur+1)
**
** If the sqlite_stat1 tables does not previously exist, it is created.
** Similarly, if the sqlite_stat3 table does not exist and the library
** is compiled with SQLITE4_ENABLE_STAT3 defined, it is created. 
**
** Argument zWhere may be a pointer to a buffer containing a table name,
** or it may be a NULL pointer. If it is not NULL, then all entries in
** the sqlite_stat1 and (if applicable) sqlite_stat3 tables associated
** with the named table are deleted. If zWhere==0, then code is generated
** to delete all stat table entries.
*/
static void openStatTable(
  Parse *pParse,          /* Parsing context */
  int iDb,                /* The database we are looking in */
  int iStatCur,           /* Open the sqlite_stat1 table on this cursor */
  const char *zWhere,     /* Delete entries for this table or index */
  const char *zWhereType  /* Either "tbl" or "idx" */
){
  static const struct {
    const char *zName;
    const char *zCols;
  } aTable[] = {
    { "sqlite_stat1", "tbl,idx,stat" },
#ifdef SQLITE4_ENABLE_STAT3
    { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
#endif
  };

  int aRoot[] = {0, 0};
  u8 aCreateTbl[] = {0, 0};

  int i;
  sqlite4 *db = pParse->db;
  Db *pDb;
  Vdbe *v = sqlite4GetVdbe(pParse);
  if( v==0 ) return;
  assert( sqlite4VdbeDb(v)==db );
  pDb = &db->aDb[iDb];

  /* Create new statistic tables if they do not exist, or clear them
  ** if they do already exist.
  */
  for(i=0; i<ArraySize(aTable); i++){
    const char *zTab = aTable[i].zName;
    Table *pStat;
    if( (pStat = sqlite4FindTable(db, zTab, pDb->zName))==0 ){
      /* The sqlite_stat[12] table does not exist. Create it. Note that a 
      ** side-effect of the CREATE TABLE statement is to leave the rootpage 
      ** of the new table in register pParse->regRoot. This is important 
      ** because the OpenWrite opcode below will be needing it. */
      pParse->pPKRoot = &aRoot[i];
      sqlite4NestedParse(pParse,
          "CREATE TABLE %Q.%s(%s)", pDb->zName, zTab, aTable[i].zCols
      );
      assert( pParse->nErr>0 || aRoot[i]>0 );
      pParse->pPKRoot = 0;
      aCreateTbl[i] = 1;
    }else{
      /* The table already exists. If zWhere is not NULL, delete all entries 
      ** associated with the table zWhere. If zWhere is NULL, delete the
      ** entire contents of the table. */
      Index *pPK = sqlite4FindPrimaryKey(pStat, 0);
      aRoot[i] = pPK->tnum;
      assert( aRoot[i]>0 );
      if( zWhere ){
        sqlite4NestedParse(pParse,
           "DELETE FROM %Q.%s WHERE %s=%Q", pDb->zName, zTab, zWhereType, zWhere
        );
      }else{
        /* The sqlite_stat[13] table already exists.  Delete all rows. */
        sqlite4VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
      }
    }
  }

  /* Open the sqlite_stat[13] tables for writing. */
  for(i=0; i<ArraySize(aTable); i++){
    sqlite4VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb);
    sqlite4VdbeChangeP4(v, -1, (char *)3, P4_INT32);
    sqlite4VdbeChangeP5(v, aCreateTbl[i]);
  }
}

/*
** Recommended number of samples for sqlite_stat3
*/
#ifndef SQLITE4_STAT3_SAMPLES
# define SQLITE4_STAT3_SAMPLES 24
#endif

/*
** Three SQL functions - stat3_init(), stat3_push(), and stat3_get() -
** share an instance of the following structure to hold their state
** information.
*/
typedef struct Stat3Accum Stat3Accum;
struct Stat3Accum {
  tRowcnt nRow;             /* Number of rows in the entire table */
  tRowcnt nPSample;         /* How often to do a periodic sample */
  int iMin;                 /* Index of entry with minimum nEq and hash */
  int mxSample;             /* Maximum number of samples to accumulate */
  int nSample;              /* Current number of samples */
  u32 iPrn;                 /* Pseudo-random number used for sampling */
  struct Stat3Sample {
    void *pKey;                /* Index key for this sample */
    int nKey;                  /* Bytes of pKey in use */
    int nAlloc;                /* Bytes of space allocated at pKey */
    tRowcnt nEq;               /* sqlite_stat3.nEq */
    tRowcnt nLt;               /* sqlite_stat3.nLt */
    tRowcnt nDLt;              /* sqlite_stat3.nDLt */
    u8 isPSample;              /* True if a periodic sample */
    u32 iHash;                 /* Tiebreaker value (pseudo-random) */
  } *a;                     /* An array of samples */
};

#ifdef SQLITE4_ENABLE_STAT3

/*
** Delete a Stat3Accum object.
*/
static void delStat3Accum(void *pCtx, void *pDel){
  sqlite4 *db = (sqlite4*)pCtx;
  Stat3Accum *p = (Stat3Accum*)pDel;
  int i;

  for(i=0; i<p->nSample; i++){
    sqlite4DbFree(db, p->a[i].pKey);
  }
  sqlite4DbFree(db, p);
}

/*
** Implementation of the stat3_init(C,S) SQL function.  The two parameters
** are the number of rows in the table or index (C) and the number of samples
** to accumulate (S).
**
** This routine allocates the Stat3Accum object.
**
** The return value is the Stat3Accum object (P).
*/
static void stat3Init(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  sqlite4 *db = sqlite4_context_db_handle(context);
  Stat3Accum *p;
  tRowcnt nRow;
  int mxSample;
  int n;

  UNUSED_PARAMETER(argc);
  nRow = (tRowcnt)sqlite4_value_int64(argv[0]);
  mxSample = sqlite4_value_int(argv[1]);
  n = sizeof(*p) + sizeof(p->a[0])*mxSample;
  p = (Stat3Accum *)sqlite4DbMallocZero(db, n);
  if( p==0 ){
    sqlite4_result_error_nomem(context);
    return;
  }
  p->a = (struct Stat3Sample*)&p[1];
  p->nRow = nRow;
  p->mxSample = mxSample;
  p->nPSample = p->nRow/(mxSample/3+1) + 1;
  sqlite4_randomness(sqlite4_db_env(db), sizeof(p->iPrn), &p->iPrn);
  sqlite4_result_blob(context, p, sizeof(p), delStat3Accum, (void*)db);
}
static const FuncDef stat3InitFuncdef = {
  2,                /* nArg */
  0,                /* flags */
  0,                /* pUserData */
  0,                /* pNext */
  stat3Init,        /* xFunc */
  0,                /* xStep */
  0,                /* xFinalize */
  "stat3_init",     /* zName */
  0,                /* pHash */
  0                 /* pDestructor */
};


/*
** Implementation of the stat3_push(nEq,nLt,nDLt,idxkey,P) SQL function.  The
** arguments describe a single key instance.  This routine makes the 
** decision about whether or not to retain this key for the sqlite_stat3
** table.
**
** The return value is NULL.
*/
static void stat3Push(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  Stat3Accum *p = (Stat3Accum*)sqlite4_value_blob(argv[4], 0);
  tRowcnt nEq = sqlite4_value_int64(argv[0]);
  tRowcnt nLt = sqlite4_value_int64(argv[1]);
  tRowcnt nDLt = sqlite4_value_int64(argv[2]);
  const void *pKey;
  int nKey;
  u8 isPSample = 0;
  u8 doInsert = 0;
  int iMin = p->iMin;
  struct Stat3Sample *pSample;
  int i;
  u32 h;

  UNUSED_PARAMETER(context);
  UNUSED_PARAMETER(argc);
  if( nEq==0 ) return;
  h = p->iPrn = p->iPrn*1103515245 + 12345;
  if( (nLt/p->nPSample)!=((nEq+nLt)/p->nPSample) ){
    doInsert = isPSample = 1;
  }else if( p->nSample<p->mxSample ){
    doInsert = 1;
  }else{
    if( nEq>p->a[iMin].nEq || (nEq==p->a[iMin].nEq && h>p->a[iMin].iHash) ){
      doInsert = 1;
    }
  }
  if( !doInsert ) return;
  if( p->nSample==p->mxSample ){
    void *pKey = p->a[iMin].pKey;
    int nAlloc = p->a[iMin].nAlloc;
    assert( p->nSample - iMin - 1 >= 0 );
    memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1));
    pSample = &p->a[p->nSample-1];
    memset(pSample, 0, sizeof(struct Stat3Sample));
    pSample->pKey = pKey;
    pSample->nAlloc = nAlloc;
  }else{
    pSample = &p->a[p->nSample++];
  }

  pKey = sqlite4_value_blob(argv[3], &nKey);
  if( nKey>pSample->nAlloc ){
    sqlite4 *db = sqlite4_context_db_handle(context);
    int nReq = nKey*4;
    pSample->pKey = sqlite4DbReallocOrFree(db, pSample->pKey, nReq);
    if( pSample->pKey==0 ) return;
    pSample->nAlloc = nReq;
  }
  memcpy(pSample->pKey, pKey, nKey);
  pSample->nKey = nKey;
  pSample->nEq = nEq;
  pSample->nLt = nLt;
  pSample->nDLt = nDLt;
  pSample->iHash = h;
  pSample->isPSample = isPSample;

  /* Find the new minimum */
  if( p->nSample==p->mxSample ){
    pSample = p->a;
    i = 0;
    while( pSample->isPSample ){
      i++;
      pSample++;
      assert( i<p->nSample );
    }
    nEq = pSample->nEq;
    h = pSample->iHash;
    iMin = i;
    for(i++, pSample++; i<p->nSample; i++, pSample++){
      if( pSample->isPSample ) continue;
      if( pSample->nEq<nEq
       || (pSample->nEq==nEq && pSample->iHash<h)
      ){
        iMin = i;
        nEq = pSample->nEq;
        h = pSample->iHash;
      }
    }
    p->iMin = iMin;
  }
}
static const FuncDef stat3PushFuncdef = {
  5,                /* nArg */
  0,                /* flags */
  0,                /* pUserData */
  0,                /* pNext */
  stat3Push,        /* xFunc */
  0,                /* xStep */
  0,                /* xFinalize */
  "stat3_push",     /* zName */
  0,                /* pHash */
  0                 /* pDestructor */
};

/*
** Implementation of the stat3_get(P,N,...) SQL function.  This routine is
** used to query the results.  Content is returned for the Nth sqlite_stat3
** row where N is between 0 and S-1 and S is the number of samples.  The
** value returned depends on the number of arguments.
**
**    CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample);

**   argc==2    result:  nEq
**   argc==3    result:  nLt
**   argc==4    result:  nDLt
**   argc==5    result:  sample
*/
static void stat3Get(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int n = sqlite4_value_int(argv[1]);
  Stat3Accum *p = (Stat3Accum*)sqlite4_value_blob(argv[0], 0);

  assert( p!=0 );
  if( p->nSample<=n ) return;
  switch( argc ){
    case 2: sqlite4_result_int64(context, p->a[n].nEq);    break;
    case 3: sqlite4_result_int64(context, p->a[n].nLt);    break;
    case 4: sqlite4_result_int64(context, p->a[n].nDLt);   break;
    default: {
      assert( argc==5 );
      sqlite4_result_blob(
          context, p->a[n].pKey, p->a[n].nKey, SQLITE4_TRANSIENT, 0
      );
      break;
    }
  }
}
static const FuncDef stat3GetFuncdef = {
  -1,               /* nArg */
  0,                /* flags */
  0,                /* pUserData */
  0,                /* pNext */
  stat3Get,         /* xFunc */
  0,                /* xStep */
  0,                /* xFinalize */
  "stat3_get",      /* zName */
  0,                /* pHash */
  0                 /* pDestructor */
};
#endif /* SQLITE4_ENABLE_STAT3 */

/*
** Generate code to do an analysis of all indices associated with
** a single table.
*/
static void analyzeOneTable(
  Parse *pParse,   /* Parser context */
  Table *pTab,     /* Table whose indices are to be analyzed */
  Index *pOnlyIdx, /* If not NULL, only analyze this one index */
  int iStatCur,    /* Index of VdbeCursor that writes the sqlite_stat1 table */
  int iMem         /* Available memory locations begin here */
){
  sqlite4 *db = pParse->db;    /* Database handle */
  Index *pIdx;                 /* An index to being analyzed */
  int iIdxCur;                 /* Cursor open on index being analyzed */
  Vdbe *v;                     /* The virtual machine being built up */
  int i;                       /* Loop counter */
  int topOfLoop;               /* The top of the loop */
  int endOfLoop;               /* The end of the loop */
  int jZeroRows = -1;          /* Jump from here if number of rows is zero */
  int iDb;                     /* Index of database containing pTab */
  int regTabname = iMem++;     /* Register containing table name */
  int regIdxname = iMem++;     /* Register containing index name */
  int regStat1 = iMem++;       /* The stat column of sqlite_stat1 */
#ifdef SQLITE4_ENABLE_STAT3
  int regNumEq = regStat1;     /* Number of instances.  Same as regStat1 */
  int regNumLt = iMem++;       /* Number of keys less than regSample */
  int regNumDLt = iMem++;      /* Number of distinct keys less than regSample */
  int regSample = iMem++;      /* The next sample value */
  int regAccum = iMem++;       /* Register to hold Stat3Accum object */
  int regLoop = iMem++;        /* Loop counter */
  int regCount = iMem++;       /* Number of rows in the table or index */
  int regTemp1 = iMem++;       /* Intermediate register */
  int regTemp2 = iMem++;       /* Intermediate register */
  int regNewSample = iMem++;
  int once = 1;                /* One-time initialization */
  int iTabCur = pParse->nTab++; /* Table cursor */
  int addrEq;
#endif
  int regRec = iMem++;         /* Register holding completed record */
  int regTemp = iMem++;        /* Temporary use register */
  int regNewRowid = iMem++;    /* Rowid for the inserted record */

  v = sqlite4GetVdbe(pParse);
  if( v==0 || NEVER(pTab==0) ){
    return;
  }
  if( pTab->pIndex==0 ){
    /* Do not gather statistics on views or virtual tables */
    return;
  }
  if( sqlite4_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
    /* Do not gather statistics on system tables */
    return;
  }
  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 );
#ifndef SQLITE4_OMIT_AUTHORIZATION
  if( sqlite4AuthCheck(pParse, SQLITE4_ANALYZE, pTab->zName, 0,
      db->aDb[iDb].zName ) ){
    return;
  }
#endif

  iIdxCur = pParse->nTab++;
  sqlite4VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0);
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    int nCol;
    KeyInfo *pKey;
    int regCnt;                  /* Total number of rows in table. */
    int regPrev;                 /* Previous index key read from database */
    int aregCard;                /* Cardinality array registers */
#ifdef SQLITE4_ENABLE_STAT3
    int addrAddimm;              /* Address at top of stat3 output loop */
    int addrIsnull;              /* Another address within the stat3 loop */
#endif

    if( pOnlyIdx && pOnlyIdx!=pIdx ) continue;
    VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName));
    nCol = pIdx->nColumn;
    pKey = sqlite4IndexKeyinfo(pParse, pIdx);
    if( iMem+1+(nCol*2)>pParse->nMem ){
      pParse->nMem = iMem+1+(nCol*2);
    }

    /* Open a cursor to the index to be analyzed. */
    assert( iDb==sqlite4SchemaToIndex(db, pIdx->pSchema) );
    sqlite4VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb,
        (char *)pKey, P4_KEYINFO_HANDOFF);
    VdbeComment((v, "%s", pIdx->zName));

    /* Populate the register containing the index name. */
    sqlite4VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0);

#ifdef SQLITE4_ENABLE_STAT3
    if( once ){
      once = 0;
      sqlite4OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);
    }

    sqlite4VdbeAddOp2(v, OP_Integer, 0, regNumEq);
    sqlite4VdbeAddOp2(v, OP_Integer, 0, regNumLt);
    sqlite4VdbeAddOp2(v, OP_Integer, 0, regNumDLt);

    assert( regAccum==regSample+1 );
    sqlite4VdbeAddOp3(v, OP_Null, 0, regSample, regAccum);
    assert( regTemp1==regCount+1 );
    sqlite4VdbeAddOp2(v, OP_Count, iIdxCur, regCount);
    sqlite4VdbeAddOp2(v, OP_Integer, SQLITE4_STAT3_SAMPLES, regTemp1);
    sqlite4VdbeAddOp4(v, OP_Function, 1, regCount, regAccum,
                      (char*)&stat3InitFuncdef, P4_FUNCDEF);
    sqlite4VdbeChangeP5(v, 2);
#endif /* SQLITE4_ENABLE_STAT3 */

    /* The block of memory cells initialized here is used as follows.
    **
    **    iMem:                
    **        The total number of rows in the table.
    **
    **    iMem+1:
    **        Previous record read from index.
    **
    **    iMem+1+1 .. iMem+1+nCol: 
    **        Number of distinct entries in index considering the 
    **        left-most N columns only, where N is between 1 and nCol, 
    **        inclusive.
    */
    regCnt = iMem;
    regPrev = iMem+1;
    aregCard = iMem+2;

    sqlite4VdbeAddOp2(v, OP_Integer, 0, regCnt);
    sqlite4VdbeAddOp2(v, OP_Null, 0, regPrev);
#ifdef SQLITE4_ENABLE_STAT3
    sqlite4VdbeAddOp2(v, OP_Null, 0, regSample);
#endif
    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp2(v, OP_Integer, 1, aregCard+i);
    }

    /* Start the analysis loop. This loop runs through all the entries in
    ** the index b-tree.  */
    endOfLoop = sqlite4VdbeMakeLabel(v);
    sqlite4VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
    topOfLoop = sqlite4VdbeCurrentAddr(v);
    sqlite4VdbeAddOp2(v, OP_AddImm, regCnt, 1);  /* Increment row counter */
    sqlite4VdbeAddOp4Int(v, OP_AnalyzeKey, iIdxCur, regPrev, aregCard, nCol);

#ifdef SQLITE4_ENABLE_STAT3
    sqlite4VdbeAddOp2(v, OP_RowKey, iIdxCur, regNewSample);
    sqlite4VdbeChangeP5(v, 1);
    addrEq = sqlite4VdbeAddOp3(v, OP_Eq, regNewSample, 0, regSample);
    addrIsnull = sqlite4VdbeAddOp2(v, OP_IsNull, regSample, 0);

    assert( regNumEq==regNumLt-1  && regNumEq==regNumDLt-2
         && regNumEq==regSample-3 && regNumEq==regAccum-4
    );
    sqlite4VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2, 
        (char*)&stat3PushFuncdef, P4_FUNCDEF
    );
    sqlite4VdbeChangeP5(v, 5);
    sqlite4VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt);
    sqlite4VdbeAddOp2(v, OP_AddImm, regNumDLt, 1);

    sqlite4VdbeJumpHere(v, addrIsnull);
    sqlite4VdbeAddOp2(v, OP_Integer, 0, regNumEq);
    sqlite4VdbeAddOp2(v, OP_Copy, regNewSample, regSample);
    sqlite4VdbeJumpHere(v, addrEq);
    sqlite4VdbeAddOp2(v, OP_AddImm, regNumEq, 1);
#endif

    /* Always jump here after updating the iMem+1...iMem+1+nCol counters */
    sqlite4VdbeResolveLabel(v, endOfLoop);

    sqlite4VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
    sqlite4VdbeAddOp1(v, OP_Close, iIdxCur);

#ifdef SQLITE4_ENABLE_STAT3
    /* Push the last record (if any) to the accumulator. */
    sqlite4VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2,
                      (char*)&stat3PushFuncdef, P4_FUNCDEF);
    sqlite4VdbeChangeP5(v, 5);

    /* This block codes a loop that iterates through all entries stored
    ** by the accumulator (the Stat3Accum object). 
    */
    sqlite4VdbeAddOp2(v, OP_Integer, -1, regLoop);
    addrAddimm = sqlite4VdbeAddOp2(v, OP_AddImm, regLoop, 1);
    for(i=0; i<4; i++){
      sqlite4VdbeAddOp3(v, OP_Function, 1, regAccum, regNumEq+i);
      sqlite4VdbeChangeP4(v, -1, (char*)&stat3GetFuncdef, P4_FUNCDEF);
      sqlite4VdbeChangeP5(v, i+2);
    }
    addrIsnull = sqlite4VdbeAddOp1(v, OP_IsNull, regNumEq);
    sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regRec, "bbbbbb", 0);
    sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
    sqlite4VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid);
    sqlite4VdbeAddOp2(v, OP_Goto, 0, addrAddimm);
    sqlite4VdbeJumpHere(v, addrIsnull);
#endif

    /* Store the results in sqlite_stat1.
    **
    ** The result is a single row of the sqlite_stat1 table.  The first
    ** two columns are the names of the table and index.  The third column
    ** is a string composed of a list of integer statistics about the
    ** index.  The first integer in the list is the total number of entries
    ** in the index.  There is one additional integer in the list for each
    ** column of the table.  This additional integer is a guess of how many
    ** rows of the table the index will select.  If D is the count of distinct
    ** values and K is the total number of rows, then the integer is computed
    ** as:
    **
    **        I = (K+D-1)/D
    **
    ** If K==0 then no entry is made into the sqlite_stat1 table.  
    ** If K>0 then it is always the case the D>0 so division by zero
    ** is never possible.
    */
    sqlite4VdbeAddOp2(v, OP_SCopy, iMem, regStat1);
    if( jZeroRows<0 ){
      jZeroRows = sqlite4VdbeAddOp1(v, OP_IfNot, iMem);
    }
    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp4(v, OP_String8, 0, regTemp, 0, " ", 0);
      sqlite4VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
      sqlite4VdbeAddOp3(v, OP_Add, iMem, aregCard+i, regTemp);
      sqlite4VdbeAddOp2(v, OP_AddImm, regTemp, -1);
      sqlite4VdbeAddOp3(v, OP_Divide, aregCard+i, regTemp, regTemp);
      sqlite4VdbeAddOp1(v, OP_ToInt, regTemp);
      sqlite4VdbeAddOp3(v, OP_Concat, regTemp, regStat1, regStat1);
    }
    sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
    sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
    sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
  }

  sqlite4VdbeJumpHere(v, jZeroRows);
  jZeroRows = sqlite4VdbeAddOp0(v, OP_Goto);
  sqlite4VdbeAddOp2(v, OP_Null, 0, regIdxname);
  sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regRec, "aaa", 0);
  sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
  sqlite4VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regNewRowid);
  if( pParse->nMem<regRec ) pParse->nMem = regRec;
  sqlite4VdbeJumpHere(v, jZeroRows);
}

/*
** Generate code that will cause the most recent index analysis to
** be loaded into internal hash tables where is can be used.
*/
static void loadAnalysis(Parse *pParse, int iDb){
  Vdbe *v = sqlite4GetVdbe(pParse);
  if( v ){
    sqlite4VdbeAddOp1(v, OP_LoadAnalysis, iDb);
  }
}

/*
** Generate code that will do an analysis of an entire database
*/
static void analyzeDatabase(Parse *pParse, int iDb){
  sqlite4 *db = pParse->db;
  Schema *pSchema = db->aDb[iDb].pSchema;    /* Schema of database iDb */
  HashElem *k;
  int iStatCur;
  int iMem;

  sqlite4BeginWriteOperation(pParse, 0, iDb);
  iStatCur = pParse->nTab;
  pParse->nTab += 3;
  openStatTable(pParse, iDb, iStatCur, 0, 0);
  iMem = pParse->nMem+1;
  for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
    Table *pTab = (Table*)sqliteHashData(k);
    analyzeOneTable(pParse, pTab, 0, iStatCur, iMem);
  }
  loadAnalysis(pParse, iDb);
}

/*
** Generate code that will do an analysis of a single table in
** a database.  If pOnlyIdx is not NULL then it is a single index
** in pTab that should be analyzed.
*/
static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){
  int iDb;
  int iStatCur;

  assert( pTab!=0 );
  iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
  sqlite4BeginWriteOperation(pParse, 0, iDb);
  iStatCur = pParse->nTab;
  pParse->nTab += 3;
  if( pOnlyIdx ){
    openStatTable(pParse, iDb, iStatCur, pOnlyIdx->zName, "idx");
  }else{
    openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl");
  }
  analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem+1);
  loadAnalysis(pParse, iDb);
}

/*
** Generate code for the ANALYZE command.  The parser calls this routine
** when it recognizes an ANALYZE command.
**
**        ANALYZE                            -- 1
**        ANALYZE  <database>                -- 2
**        ANALYZE  ?<database>.?<tablename>  -- 3
**
** Form 1 causes all indices in all attached databases to be analyzed.
** Form 2 analyzes all indices the single database named.
** Form 3 analyzes all indices associated with the named table.
*/
SQLITE4_PRIVATE void sqlite4Analyze(Parse *pParse, Token *pName1, Token *pName2){
  sqlite4 *db = pParse->db;
  int iDb;
  int i;
  char *z, *zDb;
  Table *pTab;
  Index *pIdx;
  Token *pTableName;

  /* Read the database schema. If an error occurs, leave an error message
  ** and code in pParse and return NULL. */
  if( SQLITE4_OK!=sqlite4ReadSchema(pParse) ){
    return;
  }

  assert( pName2!=0 || pName1==0 );
  if( pName1==0 ){
    /* Form 1:  Analyze everything */
    for(i=0; i<db->nDb; i++){
      if( i==1 ) continue;  /* Do not analyze the TEMP database */
      analyzeDatabase(pParse, i);
    }
  }else if( pName2->n==0 ){
    /* Form 2:  Analyze the database or table named */
    iDb = sqlite4FindDb(db, pName1);
    if( iDb>=0 ){
      analyzeDatabase(pParse, iDb);
    }else{
      z = sqlite4NameFromToken(db, pName1);
      if( z ){
        if( (pTab = sqlite4LocateTable(pParse, 0, z, 0))!=0 ){
          analyzeTable(pParse, pTab, 0);
        }else if( (pIdx = sqlite4FindIndex(db, z, 0))!=0 ){
          analyzeTable(pParse, pIdx->pTable, pIdx);
        }
        sqlite4DbFree(db, z);
      }
    }
  }else{
    /* Form 3: Analyze the fully qualified table name */
    iDb = sqlite4TwoPartName(pParse, pName1, pName2, &pTableName);
    if( iDb>=0 ){
      zDb = db->aDb[iDb].zName;
      z = sqlite4NameFromToken(db, pTableName);
      if( z ){
        if( (pTab = sqlite4LocateTable(pParse, 0, z, zDb))!=0 ){
          analyzeTable(pParse, pTab, 0);
        }else if( (pIdx = sqlite4FindIndex(db, z, zDb))!=0 ){
          analyzeTable(pParse, pIdx->pTable, pIdx);
        }
        sqlite4DbFree(db, z);
      }
    }   
  }
}

/*
** Used to pass information from the analyzer reader through to the
** callback routine.
*/
typedef struct analysisInfo analysisInfo;
struct analysisInfo {
  sqlite4 *db;
  const char *zDatabase;
};

/*
** This callback is invoked once for each index when reading the
** sqlite_stat1 table.  
**
**     argv[0] = name of the table
**     argv[1] = name of the index (might be NULL)
**     argv[2] = results of analysis - one integer for each column
**
** Entries for which argv[1]==NULL simply record the number of rows in
** the table.
*/
static int analysisLoader(
  void *pData,                    /* Pointer to analysisInfo structure */
  int nVal,                       /* Size of apVal[] array */
  sqlite4_value **apVal,          /* Values for current row */
  const char **NotUsed            /* Column names (not used by this function) */
){
  analysisInfo *pInfo = (analysisInfo*)pData;
  Index *pIndex;
  Table *pTable;
  int i, c, n;
  tRowcnt v;

  const char *zTab = sqlite4_value_text(apVal[0], 0);
  const char *zIdx = sqlite4_value_text(apVal[1], 0);
  const char *z = sqlite4_value_text(apVal[2], 0);

  assert( nVal==3 );
  UNUSED_PARAMETER2(NotUsed, nVal);

  if( zTab==0 || zIdx==0 || z==0 ) return 0;

  pTable = sqlite4FindTable(pInfo->db, zTab, pInfo->zDatabase);
  if( pTable==0 ){
    return 0;
  }
  pIndex = sqlite4FindIndex(pInfo->db, zIdx, pInfo->zDatabase);

  n = pIndex ? pIndex->nColumn : 0;
  for(i=0; *z && i<=n; i++){
    v = 0;
    while( (c=z[0])>='0' && c<='9' ){
      v = v*10 + c - '0';
      z++;
    }
    if( i==0 ) pTable->nRowEst = v;
    if( pIndex==0 ) break;
    pIndex->aiRowEst[i] = v;
    if( *z==' ' ) z++;
#if 0
    if( strcmp(z, "unordered")==0 ){
      pIndex->bUnordered = 1;
      break;
    }
#endif
  }
  return 0;
}

/*
** If the Index.aSample variable is not NULL, delete the aSample[] array
** and its contents.
*/
SQLITE4_PRIVATE void sqlite4DeleteIndexSamples(sqlite4 *db, Index *pIdx){
#ifdef SQLITE4_ENABLE_STAT3
  sqlite4DbFree(db, pIdx->aSample);
  if( db && db->pnBytesFreed==0 ){
    pIdx->nSample = 0;
    pIdx->aSample = 0;
  }
#else
  UNUSED_PARAMETER(db);
  UNUSED_PARAMETER(pIdx);
#endif
}

#ifdef SQLITE4_ENABLE_STAT3
/*
** Load content from the sqlite_stat3 table into the Index.aSample[]
** arrays of all indices.
*/
static int loadStat3(sqlite4 *db, const char *zDb){
  int rc;                       /* Result codes from subroutines */
  sqlite4_stmt *pStmt = 0;      /* An SQL statement being run */
  char *zSql;                   /* Text of the SQL statement */
  Index *pPrevIdx = 0;          /* Previous index in the loop */
  int idx = 0;                  /* slot in pIdx->aSample[] for next sample */
  IndexSample *pSample;         /* A slot in pIdx->aSample[] */
  u8 *pSpace;                   /* Space for copy of all samples */

  assert( db->lookaside.bEnabled==0 );
  if( !sqlite4FindTable(db, "sqlite_stat3", zDb) ){
    return SQLITE4_OK;
  }

  zSql = sqlite4MPrintf(db, 
      "SELECT idx, count(*), sum(length(sample)) FROM %Q.sqlite_stat3"
      " GROUP BY idx", zDb);
  if( !zSql ){
    return SQLITE4_NOMEM;
  }
  rc = sqlite4_prepare(db, zSql, -1, &pStmt, 0);
  sqlite4DbFree(db, zSql);
  if( rc ) return rc;

  while( sqlite4_step(pStmt)==SQLITE4_ROW ){
    char *zIndex;   /* Index name */
    Index *pIdx;    /* Pointer to the index object */
    int nSample;    /* Number of samples */
    int nSpace;     /* Bytes of space required for all samples */
    int nAlloc;     /* Bytes of space to allocate */

    zIndex = (char *)sqlite4_column_text(pStmt, 0, 0);
    if( zIndex==0 ) continue;
    nSample = sqlite4_column_int(pStmt, 1);
    nSpace = sqlite4_column_int(pStmt, 2);
    pIdx = sqlite4FindIndex(db, zIndex, zDb);
    if( pIdx==0 ) continue;
    assert( pIdx->nSample==0 );
    nAlloc = nSample*sizeof(IndexSample) + nSpace;
    pIdx->nSample = nSample;
    pIdx->aSample = (IndexSample*)sqlite4DbMallocZero(db, nAlloc);
    pIdx->avgEq = pIdx->aiRowEst[1];
    if( pIdx->aSample==0 ){
      db->mallocFailed = 1;
      sqlite4_finalize(pStmt);
      return SQLITE4_NOMEM;
    }
  }
  rc = sqlite4_finalize(pStmt);
  if( rc ) return rc;

  zSql = sqlite4MPrintf(db, 
      "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
  if( !zSql ){
    return SQLITE4_NOMEM;
  }
  rc = sqlite4_prepare(db, zSql, -1, &pStmt, 0);
  sqlite4DbFree(db, zSql);
  if( rc ) return rc;

  while( sqlite4_step(pStmt)==SQLITE4_ROW ){
    char *zIndex;   /* Index name */
    Index *pIdx;    /* Pointer to the index object */
    int i;          /* Loop counter */
    tRowcnt sumEq;  /* Sum of the nEq values */
    const u8 *aVal;
    int nVal;

    zIndex = (char *)sqlite4_column_text(pStmt, 0, 0);
    if( zIndex==0 ) continue;
    pIdx = sqlite4FindIndex(db, zIndex, zDb);
    if( pIdx==0 ) continue;
    if( pIdx==pPrevIdx ){
      idx++;
    }else{
      pPrevIdx = pIdx;
      idx = 0;
      pSpace = (u8*)&pIdx->aSample[pIdx->nSample];
    }
    assert( idx<pIdx->nSample );
    pSample = &pIdx->aSample[idx];
    pSample->nEq = (tRowcnt)sqlite4_column_int64(pStmt, 1);
    pSample->nLt = (tRowcnt)sqlite4_column_int64(pStmt, 2);
    pSample->nDLt = (tRowcnt)sqlite4_column_int64(pStmt, 3);
    if( idx==pIdx->nSample-1 ){
      if( pSample->nDLt>0 ){
        for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq;
        pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt;
      }
      if( pIdx->avgEq<=0 ) pIdx->avgEq = 1;
    }

    aVal = sqlite4_column_blob(pStmt, 4, &nVal);
    pSample->aVal = pSpace;
    pSample->nVal = nVal;
    memcpy(pSample->aVal, aVal, nVal);
    pSpace += nVal;
  }
  return sqlite4_finalize(pStmt);
}
#endif /* SQLITE4_ENABLE_STAT3 */

/*
** Load the content of the sqlite_stat1 and sqlite_stat3 tables. The
** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
** arrays. The contents of sqlite_stat3 are used to populate the
** Index.aSample[] arrays.
**
** If the sqlite_stat1 table is not present in the database, SQLITE4_ERROR
** is returned. In this case, even if SQLITE4_ENABLE_STAT3 was defined 
** during compilation and the sqlite_stat3 table is present, no data is 
** read from it.
**
** If SQLITE4_ENABLE_STAT3 was defined during compilation and the 
** sqlite_stat3 table is not present in the database, SQLITE4_ERROR is
** returned. However, in this case, data is read from the sqlite_stat1
** table (if it is present) before returning.
**
** If an OOM error occurs, this function always sets db->mallocFailed.
** This means if the caller does not care about other errors, the return
** code may be ignored.
*/
SQLITE4_PRIVATE int sqlite4AnalysisLoad(sqlite4 *db, int iDb){
  analysisInfo sInfo;
  HashElem *i;
  char *zSql;
  int rc;

  assert( iDb>=0 && iDb<db->nDb );
  assert( db->aDb[iDb].pKV!=0 );

  /* Clear any prior statistics */
  for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
    Index *pIdx = sqliteHashData(i);
    sqlite4DefaultRowEst(pIdx);
#ifdef SQLITE4_ENABLE_STAT3
    sqlite4DeleteIndexSamples(db, pIdx);
    pIdx->aSample = 0;
#endif
  }

  /* Check to make sure the sqlite_stat1 table exists */
  sInfo.db = db;
  sInfo.zDatabase = db->aDb[iDb].zName;
  if( sqlite4FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
    return SQLITE4_ERROR;
  }

  /* Load new statistics out of the sqlite_stat1 table */
  zSql = sqlite4MPrintf(db, 
      "SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
  if( zSql==0 ){
    rc = SQLITE4_NOMEM;
  }else{
    rc = sqlite4_exec(db, zSql, analysisLoader, &sInfo);
    sqlite4DbFree(db, zSql);
  }


  /* Load the statistics from the sqlite_stat3 table. */
#ifdef SQLITE4_ENABLE_STAT3
  if( rc==SQLITE4_OK ){
    int lookasideEnabled = db->lookaside.bEnabled;
    db->lookaside.bEnabled = 0;
    rc = loadStat3(db, sInfo.zDatabase);
    db->lookaside.bEnabled = lookasideEnabled;
  }
#endif

  if( rc==SQLITE4_NOMEM ){
    db->mallocFailed = 1;
  }
  return rc;
}


#endif /* SQLITE4_OMIT_ANALYZE */

/************** End of analyze.c *********************************************/
/************** Begin file attach.c ******************************************/
/*
** 2003 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
*/

#ifndef SQLITE4_OMIT_ATTACH
/*
** Resolve an expression that was part of an ATTACH or DETACH statement. This
** is slightly different from resolving a normal SQL expression, because simple
** identifiers are treated as strings, not possible column names or aliases.
**
** i.e. if the parser sees:
**
**     ATTACH DATABASE abc AS def
**
** it treats the two expressions as literal strings 'abc' and 'def' instead of
** looking for columns of the same name.
**
** This only applies to the root node of pExpr, so the statement:
**
**     ATTACH DATABASE abc||def AS 'db2'
**
** will fail because neither abc or def can be resolved.
*/
static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
{
  int rc = SQLITE4_OK;
  if( pExpr ){
    if( pExpr->op!=TK_ID ){
      rc = sqlite4ResolveExprNames(pName, pExpr);
      if( rc==SQLITE4_OK && !sqlite4ExprIsConstant(pExpr) ){
        sqlite4ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken);
        return SQLITE4_ERROR;
      }
    }else{
      pExpr->op = TK_STRING;
    }
  }
  return rc;
}

/*
** An SQL user-function registered to do the work of an ATTACH statement. The
** three arguments to the function come directly from an attach statement:
**
**     ATTACH DATABASE x AS y KEY z
**
**     SELECT sqlite_attach(x, y, z)
**
** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
** third argument.
*/
static void attachFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **argv
){
  int i;
  int rc = 0;
  sqlite4 *db = sqlite4_context_db_handle(context);
  const char *zName;
  const char *zFile;
  char *zPath = 0;
  char *zErr = 0;
  unsigned int flags;
  Db *aNew;
  char *zErrDyn = 0;

  UNUSED_PARAMETER(NotUsed);

  zFile = (const char *)sqlite4_value_text(argv[0], 0);
  zName = (const char *)sqlite4_value_text(argv[1], 0);
  if( zFile==0 ) zFile = "";
  if( zName==0 ) zName = "";

  /* Check for the following errors:
  **
  **     * Too many attached databases,
  **     * Transaction currently open
  **     * Specified database name already being used.
  */
  if( db->nDb>=db->aLimit[SQLITE4_LIMIT_ATTACHED]+2 ){
    zErrDyn = sqlite4MPrintf(db, "too many attached databases - max %d", 
      db->aLimit[SQLITE4_LIMIT_ATTACHED]
    );
    goto attach_error;
  }
  if( db->pSavepoint ){
    zErrDyn = sqlite4MPrintf(db, "cannot ATTACH database within transaction");
    goto attach_error;
  }
  for(i=0; i<db->nDb; i++){
    char *z = db->aDb[i].zName;
    assert( z && zName );
    if( sqlite4_stricmp(z, zName)==0 ){
      zErrDyn = sqlite4MPrintf(db, "database %s is already in use", zName);
      goto attach_error;
    }
  }

  /* Allocate the new entry in the db->aDb[] array and initialise the schema
  ** hash tables.
  */
  if( db->aDb==db->aDbStatic ){
    aNew = sqlite4DbMallocRaw(db, sizeof(db->aDb[0])*3 );
    if( aNew==0 ) return;
    memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
  }else{
    aNew = sqlite4DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
    if( aNew==0 ) return;
  }
  db->aDb = aNew;
  aNew = &db->aDb[db->nDb];
  memset(aNew, 0, sizeof(*aNew));

  /* Open the database file. If the btree is successfully opened, use
  ** it to obtain the database schema. At this point the schema may
  ** or may not be initialised.
  */
  flags = db->openFlags;
  rc = sqlite4ParseUri(db->pEnv, zFile, &flags, &zPath, &zErr);
  if( rc!=SQLITE4_OK ){
    if( rc==SQLITE4_NOMEM ) db->mallocFailed = 1;
    sqlite4_result_error(context, zErr, -1);
    sqlite4_free(db->pEnv, zErr);
    return;
  }
  rc = sqlite4KVStoreOpen(db, zName, zPath, &aNew->pKV, flags);
  sqlite4_free(db->pEnv, zPath);
  db->nDb++;
  if( rc==SQLITE4_CONSTRAINT ){
    rc = SQLITE4_ERROR;
    zErrDyn = sqlite4MPrintf(db, "database is already attached");
  }else if( rc==SQLITE4_OK ){
    aNew->pSchema = sqlite4SchemaGet(db);
    if( !aNew->pSchema ){
      rc = SQLITE4_NOMEM;
    }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
      zErrDyn = sqlite4MPrintf(db, 
        "attached databases must use the same text encoding as main database");
      rc = SQLITE4_ERROR;
    }
  }
  aNew->zName = sqlite4DbStrDup(db, zName);
  if( rc==SQLITE4_OK && aNew->zName==0 ){
    rc = SQLITE4_NOMEM;
  }

  /* If the file was opened successfully, read the schema for the new database.
  ** If this fails, or if opening the file failed, then close the file and 
  ** remove the entry from the db->aDb[] array. i.e. put everything back the way
  ** we found it.
  */
  if( rc==SQLITE4_OK ){
    rc = sqlite4Init(db, &zErrDyn);
  }
  if( rc ){
    int iDb = db->nDb - 1;
    assert( iDb>=2 );
    if( db->aDb[iDb].pKV ){
      sqlite4KVStoreClose(db->aDb[iDb].pKV);
      db->aDb[iDb].pKV = 0;
      db->aDb[iDb].pSchema = 0;
    }
    sqlite4ResetInternalSchema(db, -1);
    db->nDb = iDb;
    if( rc==SQLITE4_NOMEM || rc==SQLITE4_IOERR_NOMEM ){
      db->mallocFailed = 1;
      sqlite4DbFree(db, zErrDyn);
      zErrDyn = sqlite4MPrintf(db, "out of memory");
    }else if( zErrDyn==0 ){
      zErrDyn = sqlite4MPrintf(db, "unable to open database: %s", zFile);
    }
    goto attach_error;
  }
  
  return;

attach_error:
  /* Return an error if we get here */
  if( zErrDyn ){
    sqlite4_result_error(context, zErrDyn, -1);
    sqlite4DbFree(db, zErrDyn);
  }
  if( rc ) sqlite4_result_error_code(context, rc);
}

/*
** An SQL user-function registered to do the work of an DETACH statement. The
** three arguments to the function come directly from a detach statement:
**
**     DETACH DATABASE x
**
**     SELECT sqlite_detach(x)
*/
static void detachFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **argv
){
  const char *zName = (const char *)sqlite4_value_text(argv[0], 0);
  sqlite4 *db = sqlite4_context_db_handle(context);
  int i;
  Db *pDb = 0;
  char zErr[128];

  UNUSED_PARAMETER(NotUsed);

  if( zName==0 ) zName = "";
  for(i=0; i<db->nDb; i++){
    pDb = &db->aDb[i];
    if( pDb->pKV==0 ) continue;
    if( sqlite4_stricmp(pDb->zName, zName)==0 ) break;
  }

  if( i>=db->nDb ){
    sqlite4_snprintf(zErr,sizeof(zErr), "no such database: %s", zName);
    goto detach_error;
  }
  if( i<2 ){
    sqlite4_snprintf(zErr,sizeof(zErr), "cannot detach database %s", zName);
    goto detach_error;
  }
  if( db->pSavepoint ){
    sqlite4_snprintf(zErr,sizeof(zErr),
                     "cannot DETACH database within transaction");
    goto detach_error;
  }
  if( pDb->pKV->iTransLevel ){
    sqlite4_snprintf(zErr,sizeof(zErr), "database %s is locked", zName);
    goto detach_error;
  }

  sqlite4KVStoreClose(pDb->pKV);
  pDb->pKV = 0;
  sqlite4SchemaClear(db->pEnv, pDb->pSchema);
  sqlite4DbFree(db, pDb->pSchema);
  pDb->pSchema = 0;
  sqlite4ResetInternalSchema(db, -1);
  return;

detach_error:
  sqlite4_result_error(context, zErr, -1);
}

/*
** This procedure generates VDBE code for a single invocation of either the
** sqlite_detach() or sqlite_attach() SQL user functions.
*/
static void codeAttach(
  Parse *pParse,       /* The parser context */
  int type,            /* Either SQLITE4_ATTACH or SQLITE4_DETACH */
  FuncDef const *pFunc,/* FuncDef wrapper for detachFunc() or attachFunc() */
  Expr *pAuthArg,      /* Expression to pass to authorization callback */
  Expr *pFilename,     /* Name of database file */
  Expr *pDbname,       /* Name of the database to use internally */
  Expr *pKey           /* Database key for encryption extension */
){
  int rc;
  NameContext sName;
  Vdbe *v;
  sqlite4* db = pParse->db;
  int regArgs;

  memset(&sName, 0, sizeof(NameContext));
  sName.pParse = pParse;

  if( 
      SQLITE4_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
      SQLITE4_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
      SQLITE4_OK!=(rc = resolveAttachExpr(&sName, pKey))
  ){
    pParse->nErr++;
    goto attach_end;
  }

#ifndef SQLITE4_OMIT_AUTHORIZATION
  if( pAuthArg ){
    char *zAuthArg;
    if( pAuthArg->op==TK_STRING ){
      zAuthArg = pAuthArg->u.zToken;
    }else{
      zAuthArg = 0;
    }
    rc = sqlite4AuthCheck(pParse, type, zAuthArg, 0, 0);
    if(rc!=SQLITE4_OK ){
      goto attach_end;
    }
  }
#endif /* SQLITE4_OMIT_AUTHORIZATION */


  v = sqlite4GetVdbe(pParse);
  regArgs = sqlite4GetTempRange(pParse, 4);
  sqlite4ExprCode(pParse, pFilename, regArgs);
  sqlite4ExprCode(pParse, pDbname, regArgs+1);
  sqlite4ExprCode(pParse, pKey, regArgs+2);

  assert( v || db->mallocFailed );
  if( v ){
    sqlite4VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3);
    assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
    sqlite4VdbeChangeP5(v, (u8)(pFunc->nArg));
    sqlite4VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);

    /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
    ** statement only). For DETACH, set it to false (expire all existing
    ** statements).
    */
    sqlite4VdbeAddOp1(v, OP_Expire, (type==SQLITE4_ATTACH));
  }
  
attach_end:
  sqlite4ExprDelete(db, pFilename);
  sqlite4ExprDelete(db, pDbname);
  sqlite4ExprDelete(db, pKey);
}

/*
** Called by the parser to compile a DETACH statement.
**
**     DETACH pDbname
*/
SQLITE4_PRIVATE void sqlite4Detach(Parse *pParse, Expr *pDbname){
  static const FuncDef detach_func = {
    1,                /* nArg */
    0,                /* flags */
    0,                /* pUserData */
    0,                /* pNext */
    detachFunc,       /* xFunc */
    0,                /* xStep */
    0,                /* xFinalize */
    "sqlite_detach",  /* zName */
    0,                /* pHash */
    0                 /* pDestructor */
  };
  codeAttach(pParse, SQLITE4_DETACH, &detach_func, pDbname, 0, 0, pDbname);
}

/*
** Called by the parser to compile an ATTACH statement.
**
**     ATTACH p AS pDbname KEY pKey
*/
SQLITE4_PRIVATE void sqlite4Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
  static const FuncDef attach_func = {
    3,                /* nArg */
    0,                /* flags */
    0,                /* pUserData */
    0,                /* pNext */
    attachFunc,       /* xFunc */
    0,                /* xStep */
    0,                /* xFinalize */
    "sqlite_attach",  /* zName */
    0,                /* pHash */
    0                 /* pDestructor */
  };
  codeAttach(pParse, SQLITE4_ATTACH, &attach_func, p, p, pDbname, pKey);
}
#endif /* SQLITE4_OMIT_ATTACH */

/*
** Initialize a DbFixer structure.  This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
**
** The return value indicates whether or not fixation is required.  TRUE
** means we do need to fix the database references, FALSE means we do not.
*/
SQLITE4_PRIVATE int sqlite4FixInit(
  DbFixer *pFix,      /* The fixer to be initialized */
  Parse *pParse,      /* Error messages will be written here */
  int iDb,            /* This is the database that must be used */
  const char *zType,  /* "view", "trigger", or "index" */
  const Token *pName  /* Name of the view, trigger, or index */
){
  sqlite4 *db;

  if( NEVER(iDb<0) || iDb==1 ) return 0;
  db = pParse->db;
  assert( db->nDb>iDb );
  pFix->pParse = pParse;
  pFix->zDb = db->aDb[iDb].zName;
  pFix->zType = zType;
  pFix->pName = pName;
  return 1;
}

/*
** The following set of routines walk through the parse tree and assign
** a specific database to all table references where the database name
** was left unspecified in the original SQL statement.  The pFix structure
** must have been initialized by a prior call to sqlite4FixInit().
**
** These routines are used to make sure that an index, trigger, or
** view in one database does not refer to objects in a different database.
** (Exception: indices, triggers, and views in the TEMP database are
** allowed to refer to anything.)  If a reference is explicitly made
** to an object in a different database, an error message is added to
** pParse->zErrMsg and these routines return non-zero.  If everything
** checks out, these routines return 0.
*/
SQLITE4_PRIVATE int sqlite4FixSrcList(
  DbFixer *pFix,       /* Context of the fixation */
  SrcList *pList       /* The Source list to check and modify */
){
  int i;
  const char *zDb;
  SrcListItem *pItem;

  if( NEVER(pList==0) ) return 0;
  zDb = pFix->zDb;
  for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
    if( pItem->zDatabase==0 ){
      pItem->zDatabase = sqlite4DbStrDup(pFix->pParse->db, zDb);
    }else if( sqlite4_stricmp(pItem->zDatabase,zDb)!=0 ){
      sqlite4ErrorMsg(pFix->pParse,
         "%s %T cannot reference objects in database %s",
         pFix->zType, pFix->pName, pItem->zDatabase);
      return 1;
    }
#if !defined(SQLITE4_OMIT_VIEW) || !defined(SQLITE4_OMIT_TRIGGER)
    if( sqlite4FixSelect(pFix, pItem->pSelect) ) return 1;
    if( sqlite4FixExpr(pFix, pItem->pOn) ) return 1;
#endif
  }
  return 0;
}
#if !defined(SQLITE4_OMIT_VIEW) || !defined(SQLITE4_OMIT_TRIGGER)
SQLITE4_PRIVATE int sqlite4FixSelect(
  DbFixer *pFix,       /* Context of the fixation */
  Select *pSelect      /* The SELECT statement to be fixed to one database */
){
  while( pSelect ){
    if( sqlite4FixExprList(pFix, pSelect->pEList) ){
      return 1;
    }
    if( sqlite4FixSrcList(pFix, pSelect->pSrc) ){
      return 1;
    }
    if( sqlite4FixExpr(pFix, pSelect->pWhere) ){
      return 1;
    }
    if( sqlite4FixExpr(pFix, pSelect->pHaving) ){
      return 1;
    }
    pSelect = pSelect->pPrior;
  }
  return 0;
}
SQLITE4_PRIVATE int sqlite4FixExpr(
  DbFixer *pFix,     /* Context of the fixation */
  Expr *pExpr        /* The expression to be fixed to one database */
){
  while( pExpr ){
    if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break;
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      if( sqlite4FixSelect(pFix, pExpr->x.pSelect) ) return 1;
    }else{
      if( sqlite4FixExprList(pFix, pExpr->x.pList) ) return 1;
    }
    if( sqlite4FixExpr(pFix, pExpr->pRight) ){
      return 1;
    }
    pExpr = pExpr->pLeft;
  }
  return 0;
}
SQLITE4_PRIVATE int sqlite4FixExprList(
  DbFixer *pFix,     /* Context of the fixation */
  ExprList *pList    /* The expression to be fixed to one database */
){
  int i;
  ExprListItem *pItem;
  if( pList==0 ) return 0;
  for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
    if( sqlite4FixExpr(pFix, pItem->pExpr) ){
      return 1;
    }
  }
  return 0;
}
#endif

#ifndef SQLITE4_OMIT_TRIGGER
SQLITE4_PRIVATE int sqlite4FixTriggerStep(
  DbFixer *pFix,     /* Context of the fixation */
  TriggerStep *pStep /* The trigger step be fixed to one database */
){
  while( pStep ){
    if( sqlite4FixSelect(pFix, pStep->pSelect) ){
      return 1;
    }
    if( sqlite4FixExpr(pFix, pStep->pWhere) ){
      return 1;
    }
    if( sqlite4FixExprList(pFix, pStep->pExprList) ){
      return 1;
    }
    pStep = pStep->pNext;
  }
  return 0;
}
#endif

/************** End of attach.c **********************************************/
/************** Begin file auth.c ********************************************/
/*
** 2003 January 11
**
** 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 used to implement the sqlite4_authorizer_push()
** and sqlite4_authorizer_pop() APIs. This facility is an optional feature 
** of the library. Embedded systems that do not need this facility may omit 
** it by recompiling the library with -DSQLITE4_OMIT_AUTHORIZATION=1
*/

/*
** All of the code in this file may be omitted by defining a single
** macro.
*/
#ifndef SQLITE4_OMIT_AUTHORIZATION

/*
** Each authorizer callback is stored in an instance of this structure.
** The structures themselves are stored in a linked list headed at
** sqlite4.pAuth.
*/
struct Authorizer {
  void *pCtx;
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
  void (*xDestroy)(void*);
  Authorizer *pNext;
};

/*
** Push an authorizer callback onto the stack.
*/
SQLITE4_API int sqlite4_authorizer_push(
  sqlite4 *db,
  void *pCtx,
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
  void (*xDestroy)(void*)
){
  int rc = SQLITE4_OK;
  Authorizer *pNew;

  sqlite4_mutex_enter(db->mutex);

  pNew = (Authorizer *)sqlite4DbMallocZero(db, sizeof(Authorizer));
  if( pNew==0 ){
    rc = SQLITE4_NOMEM;
    if( xDestroy ) xDestroy(pCtx);
  }else{
    pNew->pCtx = pCtx;
    pNew->xAuth = xAuth;
    pNew->xDestroy = xDestroy;
    pNew->pNext = db->pAuth;
    db->pAuth = pNew;
    sqlite4ExpirePreparedStatements(db);
  }

  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Pop an authorizer callback from the stack. This version assumes that
** the stack is not empty and that the database handle mutex is held.
*/
static void authPopStack(sqlite4 *db){
  Authorizer *pAuth = db->pAuth;
  db->pAuth = pAuth->pNext;
  if( pAuth->xDestroy ){
    pAuth->xDestroy(pAuth->pCtx);
  }
  sqlite4DbFree(db, pAuth);
}

/*
** Pop an authorizer callback from the stack.
*/
SQLITE4_API int sqlite4_authorizer_pop(sqlite4 *db){
  int rc = SQLITE4_OK;
  sqlite4_mutex_enter(db->mutex);

  if( db->pAuth==0 ){
    rc = SQLITE4_ERROR;
  }else{
    authPopStack(db);
  }
  sqlite4ExpirePreparedStatements(db);
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Free the entire authorization callback stack. This function is called
** as part of closing the database handle.
*/
SQLITE4_PRIVATE void sqlite4AuthFreeAll(sqlite4 *db){
  while( db->pAuth ){
    authPopStack(db);
  }
}

/*
** Write an error message into pParse->zErrMsg that explains that the
** user-supplied authorization function returned an illegal value.
*/
static void authBadReturnCode(Parse *pParse){
  sqlite4ErrorMsg(pParse, "authorizer malfunction");
  pParse->rc = SQLITE4_ERROR;
}

/*
** Invoke the authorization callback stack with the supplied parameters.
** If no error occurs, return SQLITE4_OK, SQLITE4_IGNORE or SQLITE4_DENY.
**
** If an authorizer function returns an invalid value, return SQLITE4_DENY
** and leave an error message in pParse.
*/
static int authInvokeStack(
  Parse *pParse,
  int eAuth,                      /* Action code */
  const char *z1,                 /* Third argument for auth callbacks */
  const char *z2,                 /* Fourth argument for auth callbacks */
  const char *z3,                 /* Fifth argument for auth callbacks */
  const char *z4                  /* Sixth argument for auth callbacks */
){
  int rc = SQLITE4_OK;
  Authorizer *p;
  
  for(p=pParse->db->pAuth; p; p=p->pNext){
    int rcauth = p->xAuth(p->pCtx, eAuth, z1, z2, z3, z4);
    if( rcauth!=SQLITE4_OK ){
      switch( rcauth ){
        case SQLITE4_IGNORE:
        case SQLITE4_DENY:
          rc = rcauth;
          /* fall through */

        case SQLITE4_ALLOW:
          break;

        default:
          authBadReturnCode(pParse);
          rc = SQLITE4_DENY;
      }
      break;
    }
  }

  assert( rc==SQLITE4_OK || rc==SQLITE4_DENY || rc==SQLITE4_IGNORE );
  return rc;
}

/*
** Invoke the authorization callback for permission to read column zCol from
** table zTab in database zDb. This function assumes that an authorization
** callback has been registered (i.e. that sqlite4.xAuth is not NULL).
**
** If SQLITE4_IGNORE is returned and pExpr is not NULL, then pExpr is changed
** to an SQL NULL expression. Otherwise, if pExpr is NULL, then SQLITE4_IGNORE
** is treated as SQLITE4_DENY. In this case an error is left in pParse.
*/
SQLITE4_PRIVATE int sqlite4AuthReadCol(
  Parse *pParse,                  /* The parser context */
  const char *zTab,               /* Table name */
  const char *zCol,               /* Column name */
  int iDb                         /* Index of containing database. */
){
  const char *zAuthContext = pParse->zAuthContext;
  sqlite4 *db = pParse->db;       /* Database handle */
  char *zDb = db->aDb[iDb].zName; /* Name of attached database */
  int rc;                         /* Auth callback return code */

  rc = authInvokeStack(pParse, SQLITE4_READ, zTab, zCol, zDb, zAuthContext);
  if( rc==SQLITE4_DENY && pParse->rc==SQLITE4_OK ){
    if( db->nDb>2 || iDb!=0 ){
      sqlite4ErrorMsg(pParse, "access to %s.%s.%s is prohibited",zDb,zTab,zCol);
    }else{
      sqlite4ErrorMsg(pParse, "access to %s.%s is prohibited", zTab, zCol);
    }
    pParse->rc = SQLITE4_AUTH;
  }

  return rc;
}

/*
** The pExpr should be a TK_COLUMN expression.  The table referred to
** is in pTabList or else it is the NEW or OLD table of a trigger.  
** Check to see if it is OK to read this particular column.
**
** If the auth function returns SQLITE4_IGNORE, change the TK_COLUMN 
** instruction into a TK_NULL.  If the auth function returns SQLITE4_DENY,
** then generate an error.
*/
SQLITE4_PRIVATE void sqlite4AuthRead(
  Parse *pParse,        /* The parser context */
  Expr *pExpr,          /* The expression to check authorization on */
  Schema *pSchema,      /* The schema of the expression */
  SrcList *pTabList     /* All table that pExpr might refer to */
){
  sqlite4 *db = pParse->db;
  Table *pTab = 0;      /* The table being read */
  const char *zCol;     /* Name of the column of the table */
  int iSrc;             /* Index in pTabList->a[] of table being read */
  int iDb;              /* The index of the database the expression refers to */
  int iCol;             /* Index of column in table */

  if( db->pAuth==0 ) return;
  iDb = sqlite4SchemaToIndex(pParse->db, pSchema);
  if( iDb<0 ){
    /* An attempt to read a column out of a subquery or other
    ** temporary table. */
    return;
  }

  assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
  if( pExpr->op==TK_TRIGGER ){
    pTab = pParse->pTriggerTab;
  }else{
    assert( pTabList );
    for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){
      if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
        pTab = pTabList->a[iSrc].pTab;
        break;
      }
    }
  }
  iCol = pExpr->iColumn;
  if( NEVER(pTab==0) ) return;

  if( iCol>=0 ){
    assert( iCol<pTab->nCol );
    zCol = pTab->aCol[iCol].zName;
  }else{
    zCol = "ROWID";
  }
  assert( iDb>=0 && iDb<db->nDb );
  if( SQLITE4_IGNORE==sqlite4AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
    pExpr->op = TK_NULL;
  }
}

/*
** Do an authorization check using the code and arguments given.  Return
** either SQLITE4_OK (zero) or SQLITE4_IGNORE or SQLITE4_DENY.  If SQLITE4_DENY
** is returned, then the error count and error message in pParse are
** modified appropriately.
*/
SQLITE4_PRIVATE int sqlite4AuthCheck(
  Parse *pParse,
  int code,
  const char *zArg1,
  const char *zArg2,
  const char *zArg3
){
  sqlite4 *db = pParse->db;
  int rc;

  /* Don't do any authorization checks if the database is initialising
  ** or if the parser is being invoked from within sqlite4_declare_vtab.
  */
  if( db->init.busy || IN_DECLARE_VTAB ){
    return SQLITE4_OK;
  }

  rc = authInvokeStack(pParse, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
  if( rc==SQLITE4_DENY && pParse->rc==SQLITE4_OK ){
    sqlite4ErrorMsg(pParse, "not authorized");
    pParse->rc = SQLITE4_AUTH;
  }

  return rc;
}

/*
** Push an authorization context.  After this routine is called, the
** zArg3 argument to authorization callbacks will be zContext until
** popped.  Or if pParse==0, this routine is a no-op.
*/
SQLITE4_PRIVATE void sqlite4AuthContextPush(
  Parse *pParse,
  AuthContext *pContext, 
  const char *zContext
){
  assert( pParse );
  pContext->pParse = pParse;
  pContext->zAuthContext = pParse->zAuthContext;
  pParse->zAuthContext = zContext;
}

/*
** Pop an authorization context that was previously pushed
** by sqlite4AuthContextPush
*/
SQLITE4_PRIVATE void sqlite4AuthContextPop(AuthContext *pContext){
  if( pContext->pParse ){
    pContext->pParse->zAuthContext = pContext->zAuthContext;
    pContext->pParse = 0;
  }
}

#endif /* SQLITE4_OMIT_AUTHORIZATION */

/************** End of auth.c ************************************************/
/************** Begin file build.c *******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the SQLite parser
** when syntax rules are reduced.  The routines in this file handle the
** following kinds of SQL syntax:
**
**     CREATE TABLE
**     DROP TABLE
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
*/

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
*/
SQLITE4_PRIVATE void sqlite4BeginParse(Parse *pParse, int explainFlag){
  pParse->explain = (u8)explainFlag;
  pParse->nVar = 0;
}


/*
** This routine is called after a single SQL statement has been
** parsed and a VDBE program to execute that statement has been
** prepared.  This routine puts the finishing touches on the
** VDBE program and resets the pParse structure for the next
** parse.
**
** Note that if an error occurred, it might be the case that
** no VDBE code was generated.
*/
SQLITE4_PRIVATE void sqlite4FinishCoding(Parse *pParse){
  sqlite4 *db;
  Vdbe *v;

  db = pParse->db;
  if( db->mallocFailed ) return;
  if( pParse->nested ) return;
  if( pParse->nErr ) return;

  /* Begin by generating some termination code at the end of the
  ** vdbe program
  */
  v = sqlite4GetVdbe(pParse);
  assert( !pParse->isMultiWrite 
       || sqlite4VdbeAssertMayAbort(v, pParse->mayAbort));
  if( v ){
    sqlite4VdbeAddOp0(v, OP_Halt);

    /* The cookie mask contains one bit for each database file open.
    ** (Bit 0 is for main, bit 1 is for temp, and so forth.)  Bits are
    ** set for each database that is used.  Generate code to start a
    ** transaction on each used database and to verify the schema cookie
    ** on each used database.
    */
    if( pParse->cookieGoto>0 ){
      yDbMask mask;
      int iDb;
      sqlite4VdbeJumpHere(v, pParse->cookieGoto-1);
      for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
        if( (mask & pParse->cookieMask)==0 ) continue;
        sqlite4VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
        if( db->init.busy==0 ){
          sqlite4VdbeAddOp3(v, OP_VerifyCookie,
                            iDb, pParse->cookieValue[iDb],
                            db->aDb[iDb].pSchema->iGeneration);
        }
      }
#ifndef SQLITE4_OMIT_VIRTUALTABLE
      {
        int i;
        for(i=0; i<pParse->nVtabLock; i++){
          char *vtab = (char *)sqlite4GetVTable(db, pParse->apVtabLock[i]);
          sqlite4VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
        }
        pParse->nVtabLock = 0;
      }
#endif

      /* Initialize any AUTOINCREMENT data structures required.
      */
      sqlite4AutoincrementBegin(pParse);

      /* Finally, jump back to the beginning of the executable code. */
      sqlite4VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto);
    }
  }


  /* Get the VDBE program ready for execution
  */
  if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
#ifdef SQLITE4_DEBUG
    FILE *trace = (db->flags & SQLITE4_VdbeTrace)!=0 ? stdout : 0;
    sqlite4VdbeTrace(v, trace);
#endif
    assert( pParse->iCacheLevel==0 );  /* Disables and re-enables match */
    /* A minimum of one cursor is required if autoincrement is used
    *  See ticket [a696379c1f08866] */
    if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
    sqlite4VdbeMakeReady(v, pParse);
    pParse->rc = SQLITE4_DONE;
    pParse->colNamesSet = 0;
  }else{
    pParse->rc = SQLITE4_ERROR;
  }
  pParse->nTab = 0;
  pParse->nMem = 0;
  pParse->nSet = 0;
  pParse->nVar = 0;
  pParse->cookieMask = 0;
  pParse->cookieGoto = 0;
}

/*
** Generate VM code to allocate a new table number. Store the new value
** in register iReg.
*/
static void allocateTableNumber(
  Parse *pParse,                  /* Parse context */
  int iDb,                        /* Database number to allocate for */
  int iReg                        /* Register to store new tnum in */
){
  Vdbe *v;

  v = sqlite4GetVdbe(pParse);
  if( pParse->iNewidxReg==0 ){
    Schema *pSchema;
    HashElem *p;
    int maxTab = 1;

    pSchema = pParse->db->aDb[iDb].pSchema;
    for(p=sqliteHashFirst(&pSchema->idxHash); p;p=sqliteHashNext(p)){
      Index *pIdx = (Index*)sqliteHashData(p);
      if( pIdx->tnum!=KVSTORE_ROOT && pIdx->tnum > maxTab ) maxTab = pIdx->tnum;
    }

    pParse->iNewidxReg = ++pParse->nMem;
    sqlite4VdbeAddOp2(v, OP_Integer, maxTab, pParse->iNewidxReg);
  }

  sqlite4VdbeAddOp2(v, OP_NewIdxid, pParse->iNewidxReg, iDb);
  sqlite4VdbeAddOp2(v, OP_Copy, pParse->iNewidxReg, iReg);
}

/*
** Run the parser and code generator recursively in order to generate
** code for the SQL statement given onto the end of the pParse context
** currently under construction.  When the parser is run recursively
** this way, the final OP_Halt is not appended and other initialization
** and finalization steps are omitted because those are handling by the
** outermost parser.
**
** Not everything is nestable.  This facility is designed to permit
** INSERT, UPDATE, and DELETE operations against SQLITE4_MASTER.  Use
** care if you decide to try to use this routine for some other purposes.
*/
SQLITE4_PRIVATE void sqlite4NestedParse(Parse *pParse, const char *zFormat, ...){
  va_list ap;
  char *zSql;
  char *zErrMsg = 0;
  sqlite4 *db = pParse->db;
# define SAVE_SZ  (sizeof(Parse) - offsetof(Parse,nVar))
  char saveBuf[SAVE_SZ];

  if( pParse->nErr ) return;
  assert( pParse->nested<10 );  /* Nesting should only be of limited depth */
  va_start(ap, zFormat);
  zSql = sqlite4VMPrintf(db, zFormat, ap);
  va_end(ap);
  if( zSql==0 ){
    return;   /* A malloc must have failed */
  }
  pParse->nested++;
  memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
  memset(&pParse->nVar, 0, SAVE_SZ);
  sqlite4RunParser(pParse, zSql, &zErrMsg);
  sqlite4DbFree(db, zErrMsg);
  sqlite4DbFree(db, zSql);
  memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
  pParse->nested--;
}

/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table.  Return NULL if not found.
**
** If zDatabase is 0, all databases are searched for the table and the
** first matching table is returned.  (No checking for duplicate table
** names is done.)  The search order is TEMP first, then MAIN, then any
** auxiliary databases added using the ATTACH command.
**
** See also sqlite4LocateTable().
*/
SQLITE4_PRIVATE Table *sqlite4FindTable(sqlite4 *db, const char *zName, const char *zDatabase){
  Table *p = 0;
  int i;
  int nName;
  assert( zName!=0 );
  nName = sqlite4Strlen30(zName);
  /* All mutexes are required for schema access.  Make sure we hold them. */
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */
    if( zDatabase!=0 && sqlite4_stricmp(zDatabase, db->aDb[j].zName) ) continue;
    p = sqlite4HashFind(&db->aDb[j].pSchema->tblHash, zName, nName);
    if( p ) break;
  }
  return p;
}

/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table.  Return NULL if not found.  Also leave an
** error message in pParse->zErrMsg.
**
** The difference between this routine and sqlite4FindTable() is that this
** routine leaves an error message in pParse->zErrMsg where
** sqlite4FindTable() does not.
*/
SQLITE4_PRIVATE Table *sqlite4LocateTable(
  Parse *pParse,         /* context in which to report errors */
  int isView,            /* True if looking for a VIEW rather than a TABLE */
  const char *zName,     /* Name of the table we are looking for */
  const char *zDbase     /* Name of the database.  Might be NULL */
){
  Table *p;

  /* Read the database schema. If an error occurs, leave an error message
  ** and code in pParse and return NULL. */
  if( SQLITE4_OK!=sqlite4ReadSchema(pParse) ){
    return 0;
  }

  p = sqlite4FindTable(pParse->db, zName, zDbase);
  if( p==0 ){
    const char *zMsg = isView ? "no such view" : "no such table";
    if( zDbase ){
      sqlite4ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
    }else{
      sqlite4ErrorMsg(pParse, "%s: %s", zMsg, zName);
    }
    pParse->checkSchema = 1;
  }
  return p;
}

/*
** Locate the in-memory structure that describes 
** a particular index given the name of that index
** and the name of the database that contains the index.
** Return NULL if not found.
**
** If zDatabase is 0, all databases are searched for the
** table and the first matching index is returned.  (No checking
** for duplicate index names is done.)  The search order is
** TEMP first, then MAIN, then any auxiliary databases added
** using the ATTACH command.
*/
SQLITE4_PRIVATE Index *sqlite4FindIndex(sqlite4 *db, const char *zName, const char *zDb){
  Index *p = 0;
  int i;
  int nName = sqlite4Strlen30(zName);
  /* All mutexes are required for schema access.  Make sure we hold them. */
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
    Schema *pSchema = db->aDb[j].pSchema;
    assert( pSchema );
    if( zDb && sqlite4_stricmp(zDb, db->aDb[j].zName) ) continue;
    p = sqlite4HashFind(&pSchema->idxHash, zName, nName);
    if( p ) break;
  }
  return p;
}

/*
** Reclaim the memory used by an index
*/
static void freeIndex(sqlite4 *db, Index *p){
#ifndef SQLITE4_OMIT_ANALYZE
  sqlite4DeleteIndexSamples(db, p);
#endif
  sqlite4Fts5IndexFree(db, p);
  sqlite4DbFree(db, p->zColAff);
  sqlite4DbFree(db, p);
}

/*
** For the index called zIdxName which is found in the database iDb,
** unlike that index from its Table then remove the index from
** the index hash table and free all memory structures associated
** with the index.
*/
SQLITE4_PRIVATE void sqlite4UnlinkAndDeleteIndex(sqlite4 *db, int iDb, const char *zIdxName){
  Index *pIndex;
  int len;
  Hash *pHash;

  pHash = &db->aDb[iDb].pSchema->idxHash;
  len = sqlite4Strlen30(zIdxName);
  pIndex = sqlite4HashInsert(pHash, zIdxName, len, 0);
  if( ALWAYS(pIndex) ){
    if( pIndex->pTable->pIndex==pIndex ){
      pIndex->pTable->pIndex = pIndex->pNext;
    }else{
      Index *p;
      /* Justification of ALWAYS();  The index must be on the list of
      ** indices. */
      p = pIndex->pTable->pIndex;
      while( ALWAYS(p) && p->pNext!=pIndex ){ p = p->pNext; }
      if( ALWAYS(p && p->pNext==pIndex) ){
        p->pNext = pIndex->pNext;
      }
    }
    freeIndex(db, pIndex);
  }
  db->flags |= SQLITE4_InternChanges;
}

/*
** Erase all schema information from the in-memory hash tables of
** a single database.  This routine is called to reclaim memory
** before the database closes.  It is also called during a rollback
** if there were schema changes during the transaction or if a
** schema-cookie mismatch occurs.
**
** If iDb<0 then reset the internal schema tables for all database
** files.  If iDb>=0 then reset the internal schema for only the
** single file indicated.
*/
SQLITE4_PRIVATE void sqlite4ResetInternalSchema(sqlite4 *db, int iDb){
  int i, j;
  assert( iDb<db->nDb );

  if( iDb>=0 ){
    /* Case 1:  Reset the single schema identified by iDb */
    Db *pDb = &db->aDb[iDb];
    assert( pDb->pSchema!=0 );
    sqlite4SchemaClear(db->pEnv, pDb->pSchema);

    /* If any database other than TEMP is reset, then also reset TEMP
    ** since TEMP might be holding triggers that reference tables in the
    ** other database.
    */
    if( iDb!=1 ){
      pDb = &db->aDb[1];
      assert( pDb->pSchema!=0 );
      sqlite4SchemaClear(db->pEnv, pDb->pSchema);
    }
    return;
  }
  /* Case 2 (from here to the end): Reset all schemas for all attached
  ** databases. */
  assert( iDb<0 );
  for(i=0; i<db->nDb; i++){
    Db *pDb = &db->aDb[i];
    if( pDb->pSchema ){
      sqlite4SchemaClear(db->pEnv, pDb->pSchema);
    }
  }
  db->flags &= ~SQLITE4_InternChanges;
  sqlite4VtabUnlockList(db);

  /* If one or more of the auxiliary database files has been closed,
  ** then remove them from the auxiliary database list.  We take the
  ** opportunity to do this here since we have just deleted all of the
  ** schema hash tables and therefore do not have to make any changes
  ** to any of those tables.
  */
  for(i=j=2; i<db->nDb; i++){
    struct Db *pDb = &db->aDb[i];
    if( pDb->pKV==0 ){
      sqlite4DbFree(db, pDb->zName);
      pDb->zName = 0;
      continue;
    }
    if( j<i ){
      db->aDb[j] = db->aDb[i];
    }
    j++;
  }
  memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
  db->nDb = j;
  if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
    memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
    sqlite4DbFree(db, db->aDb);
    db->aDb = db->aDbStatic;
  }
}

/*
** This routine is called when a commit occurs.
*/
SQLITE4_PRIVATE void sqlite4CommitInternalChanges(sqlite4 *db){
  db->flags &= ~SQLITE4_InternChanges;
}

/*
** Delete memory allocated for the column names of a table or view (the
** Table.aCol[] array).
*/
static void sqliteDeleteColumnNames(sqlite4 *db, Table *pTable){
  int i;
  Column *pCol;
  assert( pTable!=0 );
  if( (pCol = pTable->aCol)!=0 ){
    for(i=0; i<pTable->nCol; i++, pCol++){
      sqlite4DbFree(db, pCol->zName);
      sqlite4ExprDelete(db, pCol->pDflt);
      sqlite4DbFree(db, pCol->zDflt);
      sqlite4DbFree(db, pCol->zType);
      sqlite4DbFree(db, pCol->zColl);
    }
    sqlite4DbFree(db, pTable->aCol);
  }
}

/*
** Remove the memory data structures associated with the given
** Table.  No changes are made to disk by this routine.
**
** This routine just deletes the data structure.  It does not unlink
** the table data structure from the hash table.  But it does destroy
** memory structures of the indices and foreign keys associated with 
** the table.
*/
SQLITE4_PRIVATE void sqlite4DeleteTable(sqlite4 *db, Table *pTable){
  Index *pIndex, *pNext;

  assert( !pTable || pTable->nRef>0 );

  /* Do not delete the table until the reference count reaches zero. */
  if( !pTable ) return;
  if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;

  /* Delete all indices associated with this table. */
  for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
    pNext = pIndex->pNext;
    assert( pIndex->pSchema==pTable->pSchema );
    if( !db || db->pnBytesFreed==0 ){
      char *zName = pIndex->zName; 
      TESTONLY ( Index *pOld = ) sqlite4HashInsert(
	  &pIndex->pSchema->idxHash, zName, sqlite4Strlen30(zName), 0
      );
      assert( pOld==pIndex || pOld==0 );
    }
    freeIndex(db, pIndex);
  }

  /* Delete any foreign keys attached to this table. */
  sqlite4FkDelete(db, pTable);

  /* Delete the Table structure itself.
  */
  sqliteDeleteColumnNames(db, pTable);
  sqlite4DbFree(db, pTable->zName);
  sqlite4DbFree(db, pTable->zColAff);
  sqlite4SelectDelete(db, pTable->pSelect);
#ifndef SQLITE4_OMIT_CHECK
  sqlite4ExprDelete(db, pTable->pCheck);
#endif
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  sqlite4VtabClear(db, pTable);
#endif
  sqlite4DbFree(db, pTable);
}

/*
** Unlink the given table from the hash tables and the delete the
** table structure with all its indices and foreign keys.
*/
SQLITE4_PRIVATE void sqlite4UnlinkAndDeleteTable(sqlite4 *db, int iDb, const char *zTabName){
  Table *p;
  Db *pDb;

  assert( db!=0 );
  assert( iDb>=0 && iDb<db->nDb );
  assert( zTabName );
  testcase( zTabName[0]==0 );  /* Zero-length table names are allowed */
  pDb = &db->aDb[iDb];
  p = sqlite4HashInsert(&pDb->pSchema->tblHash, zTabName,
                        sqlite4Strlen30(zTabName),0);
  sqlite4DeleteTable(db, p);
  db->flags |= SQLITE4_InternChanges;
}

/*
** Given a token, return a string that consists of the text of that
** token.  Space to hold the returned string
** is obtained from sqliteMalloc() and must be freed by the calling
** function.
**
** Any quotation marks (ex:  "name", 'name', [name], or `name`) that
** surround the body of the token are removed.
**
** Tokens are often just pointers into the original SQL text and so
** are not \000 terminated and are not persistent.  The returned string
** is \000 terminated and is persistent.
*/
SQLITE4_PRIVATE char *sqlite4NameFromToken(sqlite4 *db, Token *pName){
  char *zName;
  if( pName ){
    zName = sqlite4DbStrNDup(db, (char*)pName->z, pName->n);
    sqlite4Dequote(zName);
  }else{
    zName = 0;
  }
  return zName;
}

/*
** Open the sqlite_master table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
SQLITE4_PRIVATE void sqlite4OpenMasterTable(Parse *p, int iDb){
  Vdbe *v = sqlite4GetVdbe(p);
  sqlite4VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
  sqlite4VdbeChangeP4(v, -1, (char *)5, P4_INT32);  /* 5 column table */
  if( p->nTab==0 ){
    p->nTab = 1;
  }
}

/*
** Parameter zName points to a nul-terminated buffer containing the name
** of a database ("main", "temp" or the name of an attached db). This
** function returns the index of the named database in db->aDb[], or
** -1 if the named db cannot be found.
*/
SQLITE4_PRIVATE int sqlite4FindDbName(sqlite4 *db, const char *zName){
  int i = -1;         /* Database number */
  if( zName ){
    Db *pDb;
    int n = sqlite4Strlen30(zName);
    for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){
      if( (!OMIT_TEMPDB || i!=1 ) && n==sqlite4Strlen30(pDb->zName) && 
          0==sqlite4_stricmp(pDb->zName, zName) ){
        break;
      }
    }
  }
  return i;
}

/*
** The token *pName contains the name of a database (either "main" or
** "temp" or the name of an attached db). This routine returns the
** index of the named database in db->aDb[], or -1 if the named db 
** does not exist.
*/
SQLITE4_PRIVATE int sqlite4FindDb(sqlite4 *db, Token *pName){
  int i;                               /* Database number */
  char *zName;                         /* Name we are searching for */
  zName = sqlite4NameFromToken(db, pName);
  i = sqlite4FindDbName(db, zName);
  sqlite4DbFree(db, zName);
  return i;
}

/* The table or view or trigger name is passed to this routine via tokens
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
** 
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
** CREATE TABLE yyy(...);
**
** Then pName1 is set to "yyy" and pName2 is "".
**
** This routine sets the *ppUnqual pointer to point at the token (pName1 or
** pName2) that stores the unqualified table name.  The index of the
** database "xxx" is returned.
*/
SQLITE4_PRIVATE int sqlite4TwoPartName(
  Parse *pParse,      /* Parsing and code generating context */
  Token *pName1,      /* The "xxx" in the name "xxx.yyy" or "xxx" */
  Token *pName2,      /* The "yyy" in the name "xxx.yyy" */
  Token **pUnqual     /* Write the unqualified object name here */
){
  int iDb;                    /* Database holding the object */
  sqlite4 *db = pParse->db;

  if( ALWAYS(pName2!=0) && pName2->n>0 ){
    if( db->init.busy ) {
      sqlite4ErrorMsg(pParse, "corrupt database");
      pParse->nErr++;
      return -1;
    }
    *pUnqual = pName2;
    iDb = sqlite4FindDb(db, pName1);
    if( iDb<0 ){
      sqlite4ErrorMsg(pParse, "unknown database %T", pName1);
      pParse->nErr++;
      return -1;
    }
  }else{
    assert( db->init.iDb==0 || db->init.busy );
    iDb = db->init.iDb;
    *pUnqual = pName1;
  }
  return iDb;
}

/*
** This routine is used to check if the UTF-8 string zName is a legal
** unqualified name for a new schema object (table, index, view or
** trigger). All names are legal except those that begin with the string
** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
** is reserved for internal use.
*/
SQLITE4_PRIVATE int sqlite4CheckObjectName(Parse *pParse, const char *zName){
  if( !pParse->db->init.busy && pParse->nested==0 
          && (pParse->db->flags & SQLITE4_WriteSchema)==0
          && 0==sqlite4_strnicmp(zName, "sqlite_", 7) ){
    sqlite4ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
    return SQLITE4_ERROR;
  }
  return SQLITE4_OK;
}

/*
** Begin constructing a new table representation in memory.  This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement.  In particular, this routine is called
** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp
** flag is true if the table should be stored in the auxiliary database
** file instead of in the main database file.  This is normally the case
** when the "TEMP" or "TEMPORARY" keyword occurs in between
** CREATE and TABLE.
**
** The new table record is initialized and put in pParse->pNewTable.
** As more of the CREATE TABLE statement is parsed, additional action
** routines will be called to add more information to this record.
** At the end of the CREATE TABLE statement, the sqlite4EndTable() routine
** is called to complete the construction of the new table record.
*/
SQLITE4_PRIVATE void sqlite4StartTable(
  Parse *pParse,   /* Parser context */
  Token *pName1,   /* First part of the name of the table or view */
  Token *pName2,   /* Second part of the name of the table or view */
  int isTemp,      /* True if this is a TEMP table */
  int isView,      /* True if this is a VIEW */
  int isVirtual,   /* True if this is a VIRTUAL table */
  int noErr        /* Do nothing if table already exists */
){
  Table *pTable;
  char *zName = 0; /* The name of the new table */
  sqlite4 *db = pParse->db;
  Vdbe *v;
  int iDb;         /* Database number to create the table in */
  Token *pName;    /* Unqualified name of the table to create */

  /* The table or view name to create is passed to this routine via tokens
  ** pName1 and pName2. If the table name was fully qualified, for example:
  **
  ** CREATE TABLE xxx.yyy (...);
  ** 
  ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
  ** the table name is not fully qualified, i.e.:
  **
  ** CREATE TABLE yyy(...);
  **
  ** Then pName1 is set to "yyy" and pName2 is "".
  **
  ** The call below sets the pName pointer to point at the token (pName1 or
  ** pName2) that stores the unqualified table name. The variable iDb is
  ** set to the index of the database that the table or view is to be
  ** created in.
  */
  iDb = sqlite4TwoPartName(pParse, pName1, pName2, &pName);
  if( iDb<0 ) return;
  if( !OMIT_TEMPDB && isTemp && pName2->n>0 && iDb!=1 ){
    /* If creating a temp table, the name may not be qualified. Unless 
    ** the database name is "temp" anyway.  */
    sqlite4ErrorMsg(pParse, "temporary table name must be unqualified");
    return;
  }
  if( !OMIT_TEMPDB && isTemp ) iDb = 1;

  pParse->sNameToken = *pName;
  zName = sqlite4NameFromToken(db, pName);
  if( zName==0 ) return;
  if( SQLITE4_OK!=sqlite4CheckObjectName(pParse, zName) ){
    goto begin_table_error;
  }
  if( db->init.iDb==1 ) isTemp = 1;
#ifndef SQLITE4_OMIT_AUTHORIZATION
  assert( (isTemp & 1)==isTemp );
  {
    int code;
    char *zDb = db->aDb[iDb].zName;
    if( sqlite4AuthCheck(pParse, SQLITE4_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){
      goto begin_table_error;
    }
    if( isView ){
      if( !OMIT_TEMPDB && isTemp ){
        code = SQLITE4_CREATE_TEMP_VIEW;
      }else{
        code = SQLITE4_CREATE_VIEW;
      }
    }else{
      if( !OMIT_TEMPDB && isTemp ){
        code = SQLITE4_CREATE_TEMP_TABLE;
      }else{
        code = SQLITE4_CREATE_TABLE;
      }
    }
    if( !isVirtual && sqlite4AuthCheck(pParse, code, zName, 0, zDb) ){
      goto begin_table_error;
    }
  }
#endif

  /* Make sure the new table name does not collide with an existing
  ** index or table name in the same database.  Issue an error message if
  ** it does. The exception is if the statement being parsed was passed
  ** to an sqlite4_declare_vtab() call. In that case only the column names
  ** and types will be used, so there is no need to test for namespace
  ** collisions.
  */
  if( !IN_DECLARE_VTAB ){
    char *zDb = db->aDb[iDb].zName;
    if( SQLITE4_OK!=sqlite4ReadSchema(pParse) ){
      goto begin_table_error;
    }
    pTable = sqlite4FindTable(db, zName, zDb);
    if( pTable ){
      if( !noErr ){
        sqlite4ErrorMsg(pParse, "table %T already exists", pName);
      }else{
        assert( !db->init.busy );
        sqlite4CodeVerifySchema(pParse, iDb);
      }
      goto begin_table_error;
    }
    if( sqlite4FindIndex(db, zName, zDb)!=0 ){
      sqlite4ErrorMsg(pParse, "there is already an index named %s", zName);
      goto begin_table_error;
    }
  }

  pTable = sqlite4DbMallocZero(db, sizeof(Table));
  if( pTable==0 ){
    db->mallocFailed = 1;
    pParse->rc = SQLITE4_NOMEM;
    pParse->nErr++;
    goto begin_table_error;
  }
  pTable->zName = zName;
  pTable->pSchema = db->aDb[iDb].pSchema;
  pTable->nRef = 1;
  pTable->nRowEst = 1000000;
  assert( pParse->pNewTable==0 );
  pParse->pNewTable = pTable;

  /* If this is the magic sqlite_sequence table used by autoincrement,
  ** then record a pointer to this table in the main database structure
  ** so that INSERT can find the table easily.
  */
#ifndef SQLITE4_OMIT_AUTOINCREMENT
  if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
    pTable->pSchema->pSeqTab = pTable;
  }
#endif

  /* Begin generating the code that will insert the table record into
  ** the SQLITE4_MASTER table.  Note in particular that we must go ahead
  ** and allocate the record number for the table entry now.  Before any
  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
  ** indices to be created and the table record must come before the 
  ** indices.  Hence, the record number for the table must be allocated
  ** now.
  */
  if( !db->init.busy && (v = sqlite4GetVdbe(pParse))!=0 ){
    int reg1, reg3;
    sqlite4BeginWriteOperation(pParse, 0, iDb);

#ifndef SQLITE4_OMIT_VIRTUALTABLE
    if( isVirtual ){
      sqlite4VdbeAddOp0(v, OP_VBegin);
    }
#endif

    /* This just creates a place-holder record in the sqlite_master table.
    ** The record created does not contain anything yet.  It will be replaced
    ** by the real entry in code generated at sqlite4EndTable().
    **
    ** The rowid for the new entry is left in register pParse->regRowid.
    ** The root page number of the new table is left in reg pParse->regRoot.
    ** The rowid and root page number values are needed by the code that
    ** sqlite4EndTable will generate.
    */
    reg1 = pParse->regRowid = ++pParse->nMem;
    reg3 = ++pParse->nMem;
#if 0
#if !defined(SQLITE4_OMIT_VIEW) || !defined(SQLITE4_OMIT_VIRTUALTABLE)
    if( isView || isVirtual ){
      sqlite4VdbeAddOp2(v, OP_Integer, 0, reg2);
    }else
#endif
    {
      int tnum = firstAvailableTableNumber(db, iDb);
      sqlite4VdbeAddOp2(v, OP_Integer, tnum, reg2);
    }
#endif
    sqlite4OpenMasterTable(pParse, iDb);
    sqlite4VdbeAddOp2(v, OP_NewRowid, 0, reg1);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, 0, reg1);
    sqlite4VdbeAddOp0(v, OP_Close);
  }

  /* Normal (non-error) return. */
  return;

  /* If an error occurs, we jump here */
begin_table_error:
  sqlite4DbFree(db, zName);
  return;
}

/*
** This macro is used to compare two strings in a case-insensitive manner.
** It is slightly faster than calling sqlite4_stricmp() directly, but
** produces larger code.
**
** WARNING: This macro is not compatible with the strcmp() family. It
** returns true if the two strings are equal, otherwise false.
*/
#define STRICMP(x, y) (\
sqlite4UpperToLower[*(unsigned char *)(x)]==   \
sqlite4UpperToLower[*(unsigned char *)(y)]     \
&& sqlite4_stricmp((x)+1,(y)+1)==0 )

/*
** Add a new column to the table currently being constructed.
**
** The parser calls this routine once for each column declaration
** in a CREATE TABLE statement.  sqlite4StartTable() gets called
** first to get things going.  Then this routine is called for each
** column.
*/
SQLITE4_PRIVATE void sqlite4AddColumn(Parse *pParse, Token *pName){
  Table *p;
  int i;
  char *z;
  Column *pCol;
  sqlite4 *db = pParse->db;
  if( (p = pParse->pNewTable)==0 ) return;
#if SQLITE4_MAX_COLUMN
  if( p->nCol+1>db->aLimit[SQLITE4_LIMIT_COLUMN] ){
    sqlite4ErrorMsg(pParse, "too many columns on %s", p->zName);
    return;
  }
#endif
  z = sqlite4NameFromToken(db, pName);
  if( z==0 ) return;
  for(i=0; i<p->nCol; i++){
    if( STRICMP(z, p->aCol[i].zName) ){
      sqlite4ErrorMsg(pParse, "duplicate column name: %s", z);
      sqlite4DbFree(db, z);
      return;
    }
  }
  if( (p->nCol & 0x7)==0 ){
    Column *aNew;
    aNew = sqlite4DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
    if( aNew==0 ){
      sqlite4DbFree(db, z);
      return;
    }
    p->aCol = aNew;
  }
  pCol = &p->aCol[p->nCol];
  memset(pCol, 0, sizeof(p->aCol[0]));
  pCol->zName = z;
 
  /* If there is no type specified, columns have the default affinity
  ** 'NONE'. If there is a type specified, then sqlite4AddColumnType() will
  ** be called next to set pCol->affinity correctly.
  */
  pCol->affinity = SQLITE4_AFF_NONE;
  p->nCol++;
}

/*
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.  A "NOT NULL" constraint has
** been seen on a column.  This routine sets the notNull flag on
** the column currently under construction.
*/
SQLITE4_PRIVATE void sqlite4AddNotNull(Parse *pParse, int onError){
  Table *p;
  p = pParse->pNewTable;
  if( p==0 || NEVER(p->nCol<1) ) return;
  p->aCol[p->nCol-1].notNull = (u8)onError;
}

/*
** Scan the column type name zType (length nType) and return the
** associated affinity type.
**
** This routine does a case-independent search of zType for the 
** substrings in the following table. If one of the substrings is
** found, the corresponding affinity is returned. If zType contains
** more than one of the substrings, entries toward the top of 
** the table take priority. For example, if zType is 'BLOBINT', 
** SQLITE4_AFF_INTEGER is returned.
**
** Substring     | Affinity
** --------------------------------
** 'INT'         | SQLITE4_AFF_INTEGER
** 'CHAR'        | SQLITE4_AFF_TEXT
** 'CLOB'        | SQLITE4_AFF_TEXT
** 'TEXT'        | SQLITE4_AFF_TEXT
** 'BLOB'        | SQLITE4_AFF_NONE
** 'REAL'        | SQLITE4_AFF_REAL
** 'FLOA'        | SQLITE4_AFF_REAL
** 'DOUB'        | SQLITE4_AFF_REAL
**
** If none of the substrings in the above table are found,
** SQLITE4_AFF_NUMERIC is returned.
*/
SQLITE4_PRIVATE char sqlite4AffinityType(const char *zIn){
  u32 h = 0;
  char aff = SQLITE4_AFF_NUMERIC;

  if( zIn ) while( zIn[0] ){
    h = (h<<8) + sqlite4UpperToLower[(*zIn)&0xff];
    zIn++;
    if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){             /* CHAR */
      aff = SQLITE4_AFF_TEXT; 
    }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){       /* CLOB */
      aff = SQLITE4_AFF_TEXT;
    }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){       /* TEXT */
      aff = SQLITE4_AFF_TEXT;
    }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b')          /* BLOB */
        && (aff==SQLITE4_AFF_NUMERIC || aff==SQLITE4_AFF_REAL) ){
      aff = SQLITE4_AFF_NONE;
#ifndef SQLITE4_OMIT_FLOATING_POINT
    }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l')          /* REAL */
        && aff==SQLITE4_AFF_NUMERIC ){
      aff = SQLITE4_AFF_REAL;
    }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a')          /* FLOA */
        && aff==SQLITE4_AFF_NUMERIC ){
      aff = SQLITE4_AFF_REAL;
    }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b')          /* DOUB */
        && aff==SQLITE4_AFF_NUMERIC ){
      aff = SQLITE4_AFF_REAL;
#endif
    }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){    /* INT */
      aff = SQLITE4_AFF_INTEGER;
      break;
    }
  }

  return aff;
}

/*
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.  The pFirst token is the first
** token in the sequence of tokens that describe the type of the
** column currently under construction.   pLast is the last token
** in the sequence.  Use this information to construct a string
** that contains the typename of the column and store that string
** in zType.
*/ 
SQLITE4_PRIVATE void sqlite4AddColumnType(Parse *pParse, Token *pType){
  Table *p;
  Column *pCol;

  p = pParse->pNewTable;
  if( p==0 || NEVER(p->nCol<1) ) return;
  pCol = &p->aCol[p->nCol-1];
  assert( pCol->zType==0 );
  pCol->zType = sqlite4NameFromToken(pParse->db, pType);
  pCol->affinity = sqlite4AffinityType(pCol->zType);
}

/*
** The expression is the default value for the most recently added column
** of the table currently under construction.
**
** Default value expressions must be constant.  Raise an exception if this
** is not the case.
**
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.
*/
SQLITE4_PRIVATE void sqlite4AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
  Table *p;
  Column *pCol;
  sqlite4 *db = pParse->db;
  p = pParse->pNewTable;
  if( p!=0 ){
    pCol = &(p->aCol[p->nCol-1]);
    if( !sqlite4ExprIsConstantOrFunction(pSpan->pExpr) ){
      sqlite4ErrorMsg(pParse, "default value of column [%s] is not constant",
          pCol->zName);
    }else{
      /* A copy of pExpr is used instead of the original, as pExpr contains
      ** tokens that point to volatile memory. The 'span' of the expression
      ** is required by pragma table_info.
      */
      sqlite4ExprDelete(db, pCol->pDflt);
      pCol->pDflt = sqlite4ExprDup(db, pSpan->pExpr, EXPRDUP_REDUCE);
      sqlite4DbFree(db, pCol->zDflt);
      pCol->zDflt = sqlite4DbStrNDup(db, (char*)pSpan->zStart,
                                     (int)(pSpan->zEnd - pSpan->zStart));
    }
  }
  sqlite4ExprDelete(db, pSpan->pExpr);
}

/*
** Designate the PRIMARY KEY for the table.  pList is a list of names 
** of columns that form the primary key.  If pList is NULL, then the
** most recently added column of the table is the primary key.
**
** A table can have at most one primary key.  If the table already has
** a primary key (and this is the second primary key) then create an
** error.
*/
SQLITE4_PRIVATE void sqlite4AddPrimaryKey(
  Parse *pParse,    /* Parsing context */
  ExprList *pList,  /* List of field names to be indexed */
  int onError,      /* What to do with a uniqueness conflict */
  int autoInc,      /* True if the AUTOINCREMENT keyword is present */
  int sortOrder     /* SQLITE4_SO_ASC or SQLITE4_SO_DESC */
){
  Table *pTab = pParse->pNewTable;
  Index *pPk;                        /* Primary key index */
  char *zType = 0;                   /* Primary key column type */
  int iCol = -1, i;
  if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit;
  if( pTab->tabFlags & TF_HasPrimaryKey ){
    sqlite4ErrorMsg(pParse, 
      "table \"%s\" has more than one primary key", pTab->zName);
    goto primary_key_exit;
  }
  pTab->tabFlags |= TF_HasPrimaryKey;
  if( pList==0 ){
    iCol = pTab->nCol - 1;
    pTab->aCol[iCol].iPrimKey = 1;
    pTab->aCol[iCol].notNull = 1;
  }else{
    for(i=0; i<pList->nExpr; i++){
      for(iCol=0; iCol<pTab->nCol; iCol++){
        if( sqlite4_stricmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){
          break;
        }
      }
      if( iCol<pTab->nCol ){
        pTab->aCol[iCol].iPrimKey = i+1;
        pTab->aCol[iCol].notNull = 1;
      }
    }
    if( pList->nExpr>1 ) iCol = -1;
  }
  pPk = sqlite4CreateIndex(pParse, 0, pList, 0, onError, 0, sortOrder, 1);

  if( iCol>=0 && iCol<pTab->nCol
   && (zType = pTab->aCol[iCol].zType)!=0
   && sqlite4_stricmp(zType, "INTEGER")==0
   && sortOrder==SQLITE4_SO_ASC
   && pPk
  ){
    pPk->fIndex |= IDX_IntPK;
    assert( autoInc==0 || autoInc==1 );
    pTab->tabFlags |= (-autoInc)&TF_Autoincrement;
  }else if( autoInc ){
    sqlite4ErrorMsg(pParse, 
        "AUTOINCREMENT permitted on INTEGER PRIMARY KEY ASC only");
  }
  pList = 0;

primary_key_exit:
  sqlite4ExprListDelete(pParse->db, pList);
  return;
}

/*
** Add a new CHECK constraint to the table currently under construction.
*/
SQLITE4_PRIVATE void sqlite4AddCheckConstraint(
  Parse *pParse,    /* Parsing context */
  Expr *pCheckExpr  /* The check expression */
){
  sqlite4 *db = pParse->db;
#ifndef SQLITE4_OMIT_CHECK
  Table *pTab = pParse->pNewTable;
  if( pTab && !IN_DECLARE_VTAB ){
    pTab->pCheck = sqlite4ExprAnd(db, pTab->pCheck, pCheckExpr);
  }else
#endif
  {
    sqlite4ExprDelete(db, pCheckExpr);
  }
}

/*
** Set the collation function of the most recently parsed table column
** to the CollSeq given.
*/
SQLITE4_PRIVATE void sqlite4AddCollateType(Parse *pParse, Token *pToken){
  Table *p;
  int i;
  char *zColl;              /* Dequoted name of collation sequence */
  sqlite4 *db;

  if( (p = pParse->pNewTable)==0 ) return;
  i = p->nCol-1;
  db = pParse->db;
  zColl = sqlite4NameFromToken(db, pToken);
  if( !zColl ) return;

  if( sqlite4LocateCollSeq(pParse, zColl) ){
    Index *pIdx;
    p->aCol[i].zColl = zColl;
  
    /* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
    ** then an index may have been created on this column before the
    ** collation type was added. Correct this if it is the case.
    */
    for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->nColumn==1 );
      if( pIdx->aiColumn[0]==i ){
        pIdx->azColl[0] = p->aCol[i].zColl;
      }
    }
  }else{
    sqlite4DbFree(db, zColl);
  }
}

/*
** This function returns the collation sequence for database native text
** encoding identified by the string zName, length nName.
**
** If the requested collation sequence is not available, or not available
** in the database native encoding, the collation factory is invoked to
** request it. If the collation factory does not supply such a sequence,
** and the sequence is available in another text encoding, then that is
** returned instead.
**
** If no versions of the requested collations sequence are available, or
** another error occurs, NULL is returned and an error message written into
** pParse.
**
** This routine is a wrapper around sqlite4FindCollSeq().  This routine
** invokes the collation factory if the named collation cannot be found
** and generates an error message.
**
** See also: sqlite4FindCollSeq(), sqlite4GetCollSeq()
*/
SQLITE4_PRIVATE CollSeq *sqlite4LocateCollSeq(Parse *pParse, const char *zName){
  sqlite4 *db = pParse->db;
  u8 initbusy = db->init.busy;
  CollSeq *pColl;

  pColl = sqlite4FindCollSeq(db, zName, initbusy);
  if( !initbusy && (!pColl || !pColl->xCmp) ){
    pColl = sqlite4GetCollSeq(db, pColl, zName);
    if( !pColl ){
      sqlite4ErrorMsg(pParse, "no such collation sequence: %s", zName);
    }
  }

  return pColl;
}


/*
** Generate code that will increment the schema cookie.
**
** The schema cookie is used to determine when the schema for the
** database changes.  After each schema change, the cookie value
** changes.  When a process first reads the schema it records the
** cookie.  Thereafter, whenever it goes to access the database,
** it checks the cookie to make sure the schema has not changed
** since it was last read.
**
** This plan is not completely bullet-proof.  It is possible for
** the schema to change multiple times and for the cookie to be
** set back to prior value.  But schema changes are infrequent
** and the probability of hitting the same cookie value is only
** 1 chance in 2^32.  So we're safe enough.
*/
SQLITE4_PRIVATE void sqlite4ChangeCookie(Parse *pParse, int iDb){
  int r1 = sqlite4GetTempReg(pParse);
  sqlite4 *db = pParse->db;
  Vdbe *v = pParse->pVdbe;
  sqlite4VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1);
  sqlite4VdbeAddOp3(v, OP_SetCookie, iDb, 0, r1);
  sqlite4ReleaseTempReg(pParse, r1);
}

/*
** Measure the number of characters needed to output the given
** identifier.  The number returned includes any quotes used
** but does not include the null terminator.
**
** The estimate is conservative.  It might be larger that what is
** really needed.
*/
static int identLength(const char *z){
  int n;
  for(n=0; *z; n++, z++){
    if( *z=='"' ){ n++; }
  }
  return n + 2;
}

/*
** The first parameter is a pointer to an output buffer. The second 
** parameter is a pointer to an integer that contains the offset at
** which to write into the output buffer. This function copies the
** nul-terminated string pointed to by the third parameter, zSignedIdent,
** to the specified offset in the buffer and updates *pIdx to refer
** to the first byte after the last byte written before returning.
** 
** If the string zSignedIdent consists entirely of alpha-numeric
** characters, does not begin with a digit and is not an SQL keyword,
** then it is copied to the output buffer exactly as it is. Otherwise,
** it is quoted using double-quotes.
*/
static void identPut(char *z, int *pIdx, char *zSignedIdent){
  unsigned char *zIdent = (unsigned char*)zSignedIdent;
  int i, j, needQuote;
  i = *pIdx;

  for(j=0; zIdent[j]; j++){
    if( !sqlite4Isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
  }
  needQuote = sqlite4Isdigit(zIdent[0]) || sqlite4KeywordCode(zIdent, j)!=TK_ID;
  if( !needQuote ){
    needQuote = zIdent[j];
  }

  if( needQuote ) z[i++] = '"';
  for(j=0; zIdent[j]; j++){
    z[i++] = zIdent[j];
    if( zIdent[j]=='"' ) z[i++] = '"';
  }
  if( needQuote ) z[i++] = '"';
  z[i] = 0;
  *pIdx = i;
}

/*
** Generate a CREATE TABLE statement appropriate for the given
** table.  Memory to hold the text of the statement is obtained
** from sqliteMalloc() and must be freed by the calling function.
*/
static char *createTableStmt(sqlite4 *db, Table *p){
  int i, k, n;
  char *zStmt;
  char *zSep, *zSep2, *zEnd;
  Column *pCol;
  n = 0;
  for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
    n += identLength(pCol->zName) + 5;
  }
  n += identLength(p->zName);
  if( n<50 ){ 
    zSep = "";
    zSep2 = ",";
    zEnd = ")";
  }else{
    zSep = "\n  ";
    zSep2 = ",\n  ";
    zEnd = "\n)";
  }
  n += 35 + 6*p->nCol;
  zStmt = sqlite4DbMallocRaw(0, n);
  if( zStmt==0 ){
    db->mallocFailed = 1;
    return 0;
  }
  k = sqlite4_snprintf(zStmt, n, "CREATE TABLE ");
  identPut(zStmt, &k, p->zName);
  zStmt[k++] = '(';
  for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){
    static const char * const azType[] = {
        /* SQLITE4_AFF_TEXT    */ " TEXT",
        /* SQLITE4_AFF_NONE    */ "",
        /* SQLITE4_AFF_NUMERIC */ " NUM",
        /* SQLITE4_AFF_INTEGER */ " INT",
        /* SQLITE4_AFF_REAL    */ " REAL"
    };
    int len;
    const char *zType;

    k += sqlite4_snprintf(&zStmt[k], n-k, zSep);
    zSep = zSep2;
    identPut(zStmt, &k, pCol->zName);
    assert( pCol->affinity-SQLITE4_AFF_TEXT >= 0 );
    assert( pCol->affinity-SQLITE4_AFF_TEXT < ArraySize(azType) );
    testcase( pCol->affinity==SQLITE4_AFF_TEXT );
    testcase( pCol->affinity==SQLITE4_AFF_NONE );
    testcase( pCol->affinity==SQLITE4_AFF_NUMERIC );
    testcase( pCol->affinity==SQLITE4_AFF_INTEGER );
    testcase( pCol->affinity==SQLITE4_AFF_REAL );
    
    zType = azType[pCol->affinity - SQLITE4_AFF_TEXT];
    len = sqlite4Strlen30(zType);
    assert( pCol->affinity==SQLITE4_AFF_NONE 
            || pCol->affinity==sqlite4AffinityType(zType) );
    memcpy(&zStmt[k], zType, len);
    k += len;
    assert( k<=n );
  }
  sqlite4_snprintf(&zStmt[k], n-k, "%s", zEnd);
  return zStmt;
}

static Index *newIndex(
  Parse *pParse,                  /* Parse context for current statement */
  Table *pTab,                    /* Table index is created on */
  const char *zName,              /* Name of index object to create */
  int nCol,                       /* Number of columns in index */
  int nCover,                     /* Number of covered columns in index */
  int onError,                    /* One of OE_Abort, OE_Replace etc. */
  int nExtra,                     /* Bytes of extra space to allocate */
  char **pzExtra                  /* OUT: Pointer to extra space */
){
  sqlite4 *db = pParse->db;       /* Database handle */
  Index *pIndex;                  /* Return value */
  char *zExtra = 0;               /* nExtra bytes of extra space allocated */
  int nName;                      /* Length of zName in bytes */

  /* Allocate the index structure. */
  nName = sqlite4Strlen30(zName);
  pIndex = sqlite4DbMallocZero(db, 
      ROUND8(sizeof(Index)) +              /* Index structure  */
      ROUND8(sizeof(tRowcnt)*(nCol+1)) +   /* Index.aiRowEst   */
      sizeof(char *)*nCol +                /* Index.azColl     */
      sizeof(int)*nCol +                   /* Index.aiColumn   */
      sizeof(int)*nCover +                 /* Index.aiCover    */
      sizeof(u8)*nCol +                    /* Index.aSortOrder */
      nName + 1 +                          /* Index.zName      */
      nExtra                               /* Collation sequence names */
  );
  assert( pIndex || db->mallocFailed );

  if( pIndex ){
    zExtra = (char*)pIndex;
    pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))];
    pIndex->azColl = (char**)
      ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1));
    assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
    assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
    pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
    pIndex->aiCover = (int *)(&pIndex->aiColumn[nCol]);
    pIndex->aSortOrder = (u8 *)(&pIndex->aiCover[nCover]);
    pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
    zExtra = (char *)(&pIndex->zName[nName+1]);
    memcpy(pIndex->zName, zName, nName+1);
    pIndex->pTable = pTab;
    pIndex->nColumn = nCol;
    pIndex->nCover = nCover;
    pIndex->onError = (u8)onError;
    pIndex->pSchema = pTab->pSchema;
  }

  *pzExtra = zExtra;
  return pIndex;
}

static int addIndexToHash(sqlite4 *db, Index *pIdx){
  if( db->init.busy ){
    Hash *pIdxHash = &pIdx->pSchema->idxHash;
    int nName = sqlite4Strlen30(pIdx->zName);
    Index *p;
    p = sqlite4HashInsert(pIdxHash, pIdx->zName, nName, pIdx);
    if( p ){
      assert( p==pIdx );
      db->mallocFailed = 1;
      return SQLITE4_NOMEM;
    }
  }
  return SQLITE4_OK;
}


/*
** Allocate and populate an Index structure representing an implicit 
** primary key. In implicit primary key behaves similarly to the built-in
** INTEGER PRIMARY KEY columns in SQLite 3.
*/
static void addImplicitPrimaryKey(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table to add implicit PRIMARY KEY to */
  int iDb
){
  sqlite4 *db = pParse->db;
  Index *pIndex;                  /* New index */
  char *zExtra;

  assert( !pTab->pIndex || pTab->pIndex->eIndexType!=SQLITE4_INDEX_PRIMARYKEY );
  assert( sqlite4Strlen30("binary")==6 );
  pIndex = newIndex(pParse, pTab, pTab->zName, 1, 0, OE_Abort, 1+6, &zExtra);
  if( pIndex && addIndexToHash(db, pIndex) ){
    sqlite4DbFree(db, pIndex);
    pIndex = 0;
  }
  if( pIndex ){
    pIndex->aiColumn[0] = -1;
    pIndex->azColl[0] = zExtra;
    memcpy(zExtra, "binary", 7);
    pIndex->eIndexType = SQLITE4_INDEX_PRIMARYKEY;
    pIndex->pNext = pTab->pIndex;
    pTab->pIndex = pIndex;
    sqlite4DefaultRowEst(pIndex);
    pTab->tabFlags |= TF_HasPrimaryKey;

    if( db->init.busy ){
      pIndex->tnum = db->init.newTnum;
    }else{
      pIndex->tnum = ++pParse->nMem;
      allocateTableNumber(pParse, iDb, pIndex->tnum);
    }
  }
}

/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
**
** The table structure that other action routines have been building
** is added to the internal hash tables, assuming no errors have
** occurred.
**
** An entry for the table is made in the master table on disk, unless
** this is a temporary table or db->init.busy==1.  When db->init.busy==1
** it means we are reading the sqlite_master table because we just
** connected to the database or because the sqlite_master table has
** recently changed, so the entry for this table already exists in
** the sqlite_master table.  We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
** was called to create a table generated from a 
** "CREATE TABLE ... AS SELECT ..." statement.  The column names of
** the new table will match the result set of the SELECT.
*/
SQLITE4_PRIVATE void sqlite4EndTable(
  Parse *pParse,          /* Parse context */
  Token *pCons,           /* The ',' token after the last column defn. */
  Token *pEnd,            /* The final ')' token in the CREATE TABLE */
  Select *pSelect         /* Select from a "CREATE ... AS SELECT" */
){
  Table *p;
  sqlite4 *db = pParse->db;
  int iDb;
  int iPkRoot = 0;                /* Root page of primary key index */

  if( (pEnd==0 && pSelect==0) || db->mallocFailed ){
    return;
  }
  p = pParse->pNewTable;
  if( p==0 ) return;

  assert( !db->init.busy || !pSelect );
  iDb = sqlite4SchemaToIndex(db, p->pSchema);

  if( !IsView(p) ){
    Index *pPk;                   /* PRIMARY KEY index of table p */
    if( 0==(p->tabFlags & TF_HasPrimaryKey) ){
      /* If no explicit PRIMARY KEY has been created, add an implicit 
      ** primary key here.  An implicit primary key works the way "rowid" 
      ** did in SQLite 3.  */
      addImplicitPrimaryKey(pParse, p, iDb);
    }
    pPk = sqlite4FindPrimaryKey(p, 0);
    assert( pPk || pParse->nErr || db->mallocFailed );
    if( pPk ){
      iPkRoot = pPk->tnum;
      if( pParse->pPKRoot ){
        /* If pParse->pPKRoto is non-zero, it is a pointer to a location in
        ** which to store the root page number of the table just created. 
        ** This is used by the ANALYZE command when creating the sqlite_stat*
        ** tables.  */
        *pParse->pPKRoot = iPkRoot;
      }
    }
  }

#ifndef SQLITE4_OMIT_CHECK
  /* Resolve names in all CHECK constraint expressions.
  */
  if( p->pCheck ){
    SrcList sSrc;                   /* Fake SrcList for pParse->pNewTable */
    NameContext sNC;                /* Name context for pParse->pNewTable */

    memset(&sNC, 0, sizeof(sNC));
    memset(&sSrc, 0, sizeof(sSrc));
    sSrc.nSrc = 1;
    sSrc.a[0].zName = p->zName;
    sSrc.a[0].pTab = p;
    sSrc.a[0].iCursor = -1;
    sNC.pParse = pParse;
    sNC.pSrcList = &sSrc;
    sNC.isCheck = 1;
    if( sqlite4ResolveExprNames(&sNC, p->pCheck) ){
      return;
    }
  }
#endif /* !defined(SQLITE4_OMIT_CHECK) */

  /* If not initializing, then create a record for the new table
  ** in the SQLITE4_MASTER table of the database.
  **
  ** If this is a TEMPORARY table, write the entry into the auxiliary
  ** file instead of into the main database file.
  */
  if( !db->init.busy ){
    int n;
    Vdbe *v;
    char *zType;    /* "view" or "table" */
    char *zType2;   /* "VIEW" or "TABLE" */
    char *zStmt;    /* Text of the CREATE TABLE or CREATE VIEW statement */

    v = sqlite4GetVdbe(pParse);
    if( NEVER(v==0) ) return;

    sqlite4VdbeAddOp1(v, OP_Close, 0);

    /* 
    ** Initialize zType for the new view or table.
    */
    if( p->pSelect==0 ){
      /* A regular table */
      zType = "table";
      zType2 = "TABLE";
#ifndef SQLITE4_OMIT_VIEW
    }else{
      /* A view */
      zType = "view";
      zType2 = "VIEW";
#endif
    }

    /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
    ** statement to populate the new table. The root-page number for the
    ** new table is in register pParse->regRoot.
    **
    ** Once the SELECT has been coded by sqlite4Select(), it is in a
    ** suitable state to query for the column names and types to be used
    ** by the new table.
    */
    if( pSelect ){
      SelectDest dest;
      Table *pSelTab;

      assert(pParse->nTab==1);
      sqlite4VdbeAddOp3(v, OP_OpenWrite, 1, iPkRoot, iDb);
      sqlite4VdbeChangeP5(v, 1);
      pParse->nTab = 2;
      sqlite4SelectDestInit(&dest, SRT_Table, 1);
      sqlite4Select(pParse, pSelect, &dest);
      sqlite4VdbeAddOp1(v, OP_Close, 1);
      if( pParse->nErr==0 ){
        pSelTab = sqlite4ResultSetOfSelect(pParse, pSelect);
        if( pSelTab==0 ) return;
        assert( p->aCol==0 );
        p->nCol = pSelTab->nCol;
        p->aCol = pSelTab->aCol;
        pSelTab->nCol = 0;
        pSelTab->aCol = 0;
        sqlite4DeleteTable(db, pSelTab);
      }
    }

    /* Compute the complete text of the CREATE statement */
    if( pSelect ){
      zStmt = createTableStmt(db, p);
    }else{
      n = (int)(pEnd->z - pParse->sNameToken.z) + 1;
      zStmt = sqlite4MPrintf(db, 
          "CREATE %s %.*s", zType2, n, pParse->sNameToken.z
      );
    }

    /* A slot for the record has already been allocated in the 
    ** SQLITE4_MASTER table.  We just need to update that slot with all
    ** the information we've collected.
    */
    sqlite4NestedParse(pParse,
      "UPDATE %Q.%s "
         "SET type='%s', name=%Q, tbl_name=%Q, rootpage=%s%d, sql=%Q "
       "WHERE rowid=#%d",
      db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
      zType,
      p->zName,
      p->zName,
      (iPkRoot ? "#" : ""), iPkRoot,
      zStmt,
      pParse->regRowid
    );
    sqlite4DbFree(db, zStmt);
    sqlite4ChangeCookie(pParse, iDb);

#ifndef SQLITE4_OMIT_AUTOINCREMENT
    /* Check to see if we need to create an sqlite_sequence table for
    ** keeping track of autoincrement keys.
    */
    if( p->tabFlags & TF_Autoincrement ){
      Db *pDb = &db->aDb[iDb];
      if( pDb->pSchema->pSeqTab==0 ){
        sqlite4NestedParse(pParse,
          "CREATE TABLE %Q.sqlite_sequence(name,seq)",
          pDb->zName
        );
      }
    }
#endif

    /* Reparse everything to update our internal data structures */
    sqlite4VdbeAddParseSchemaOp(v, iDb,
               sqlite4MPrintf(db, "tbl_name='%q'", p->zName));
  }


  /* Add the table to the in-memory representation of the database.
  */
  if( db->init.busy ){
    Table *pOld;
    Schema *pSchema = p->pSchema;
    pOld = sqlite4HashInsert(&pSchema->tblHash, p->zName,
                             sqlite4Strlen30(p->zName),p);
    if( pOld ){
      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
      db->mallocFailed = 1;
      return;
    }
    pParse->pNewTable = 0;
    db->nTable++;
    db->flags |= SQLITE4_InternChanges;

#ifndef SQLITE4_OMIT_ALTERTABLE
    if( !p->pSelect ){
      const char *zName = (const char *)pParse->sNameToken.z;
      int nName;
      assert( !pSelect && pCons && pEnd );
      if( pCons->z==0 ){
        pCons = pEnd;
      }
      nName = (int)((const char *)pCons->z - zName);
      p->addColOffset = 13 + sqlite4Utf8CharLen(zName, nName);
    }
#endif
  }
}

#ifndef SQLITE4_OMIT_VIEW
/*
** The parser calls this routine in order to create a new VIEW
*/
SQLITE4_PRIVATE void sqlite4CreateView(
  Parse *pParse,     /* The parsing context */
  Token *pBegin,     /* The CREATE token that begins the statement */
  Token *pName1,     /* The token that holds the name of the view */
  Token *pName2,     /* The token that holds the name of the view */
  Select *pSelect,   /* A SELECT statement that will become the new view */
  int isTemp,        /* TRUE for a TEMPORARY view */
  int noErr          /* Suppress error messages if VIEW already exists */
){
  Table *p;
  int n;
  const char *z;
  Token sEnd;
  DbFixer sFix;
  Token *pName = 0;
  int iDb;
  sqlite4 *db = pParse->db;

  if( pParse->nVar>0 ){
    sqlite4ErrorMsg(pParse, "parameters are not allowed in views");
    sqlite4SelectDelete(db, pSelect);
    return;
  }
  sqlite4StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
  p = pParse->pNewTable;
  if( p==0 || pParse->nErr ){
    sqlite4SelectDelete(db, pSelect);
    return;
  }
  sqlite4TwoPartName(pParse, pName1, pName2, &pName);
  iDb = sqlite4SchemaToIndex(db, p->pSchema);
  if( sqlite4FixInit(&sFix, pParse, iDb, "view", pName)
    && sqlite4FixSelect(&sFix, pSelect)
  ){
    sqlite4SelectDelete(db, pSelect);
    return;
  }

  /* Make a copy of the entire SELECT statement that defines the view.
  ** This will force all the Expr.token.z values to be dynamically
  ** allocated rather than point to the input string - which means that
  ** they will persist after the current sqlite4_exec() call returns.
  */
  p->pSelect = sqlite4SelectDup(db, pSelect, EXPRDUP_REDUCE);
  sqlite4SelectDelete(db, pSelect);
  if( db->mallocFailed ){
    return;
  }
  if( !db->init.busy ){
    sqlite4ViewGetColumnNames(pParse, p);
  }

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;
  if( ALWAYS(sEnd.z[0]!=0) && sEnd.z[0]!=';' ){
    sEnd.z += sEnd.n;
  }
  sEnd.n = 0;
  n = (int)(sEnd.z - pBegin->z);
  z = pBegin->z;
  while( ALWAYS(n>0) && sqlite4Isspace(z[n-1]) ){ n--; }
  sEnd.z = &z[n-1];
  sEnd.n = 1;

  /* Use sqlite4EndTable() to add the view to the SQLITE4_MASTER table */
  sqlite4EndTable(pParse, 0, &sEnd, 0);
  return;
}
#endif /* SQLITE4_OMIT_VIEW */

#if !defined(SQLITE4_OMIT_VIEW) || !defined(SQLITE4_OMIT_VIRTUALTABLE)
/*
** The Table structure pTable is really a VIEW.  Fill in the names of
** the columns of the view in the pTable structure.  Return the number
** of errors.  If an error is seen leave an error message in pParse->zErrMsg.
*/
SQLITE4_PRIVATE int sqlite4ViewGetColumnNames(Parse *pParse, Table *pTable){
  Table *pSelTab;   /* A fake table from which we get the result set */
  Select *pSel;     /* Copy of the SELECT that implements the view */
  int nErr = 0;     /* Number of errors encountered */
  int n;            /* Temporarily holds the number of cursors assigned */
  sqlite4 *db = pParse->db;  /* Database connection for malloc errors */
  Authorizer *pAuth;

  assert( pTable );

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( sqlite4VtabCallConnect(pParse, pTable) ){
    return SQLITE4_ERROR;
  }
  if( IsVirtual(pTable) ) return 0;
#endif

#ifndef SQLITE4_OMIT_VIEW
  /* A positive nCol means the columns names for this view are
  ** already known.
  */
  if( pTable->nCol>0 ) return 0;

  /* A negative nCol is a special marker meaning that we are currently
  ** trying to compute the column names.  If we enter this routine with
  ** a negative nCol, it means two or more views form a loop, like this:
  **
  **     CREATE VIEW one AS SELECT * FROM two;
  **     CREATE VIEW two AS SELECT * FROM one;
  **
  ** Actually, the error above is now caught prior to reaching this point.
  ** But the following test is still important as it does come up
  ** in the following:
  ** 
  **     CREATE TABLE main.ex1(a);
  **     CREATE TEMP VIEW ex1 AS SELECT a FROM ex1;
  **     SELECT * FROM temp.ex1;
  */
  if( pTable->nCol<0 ){
    sqlite4ErrorMsg(pParse, "view %s is circularly defined", pTable->zName);
    return 1;
  }
  assert( pTable->nCol>=0 );

  /* If we get this far, it means we need to compute the table names.
  ** Note that the call to sqlite4ResultSetOfSelect() will expand any
  ** "*" elements in the results set of the view and will assign cursors
  ** to the elements of the FROM clause.  But we do not want these changes
  ** to be permanent.  So the computation is done on a copy of the SELECT
  ** statement that defines the view.
  */
  assert( pTable->pSelect );
  pSel = sqlite4SelectDup(db, pTable->pSelect, 0);
  if( pSel ){
    u8 enableLookaside = db->lookaside.bEnabled;
    n = pParse->nTab;
    sqlite4SrcListAssignCursors(pParse, pSel->pSrc);
    pTable->nCol = -1;
    db->lookaside.bEnabled = 0;
#ifndef SQLITE4_OMIT_AUTHORIZATION
    pAuth = db->pAuth;
    db->pAuth = 0;
    pSelTab = sqlite4ResultSetOfSelect(pParse, pSel);
    db->pAuth = pAuth;
#else
    pSelTab = sqlite4ResultSetOfSelect(pParse, pSel);
#endif
    db->lookaside.bEnabled = enableLookaside;
    pParse->nTab = n;
    if( pSelTab ){
      assert( pTable->aCol==0 );
      pTable->nCol = pSelTab->nCol;
      pTable->aCol = pSelTab->aCol;
      pSelTab->nCol = 0;
      pSelTab->aCol = 0;
      sqlite4DeleteTable(db, pSelTab);
      pTable->pSchema->flags |= DB_UnresetViews;
    }else{
      pTable->nCol = 0;
      nErr++;
    }
    sqlite4SelectDelete(db, pSel);
  } else {
    nErr++;
  }
#endif /* SQLITE4_OMIT_VIEW */
  return nErr;  
}
#endif /* !defined(SQLITE4_OMIT_VIEW) || !defined(SQLITE4_OMIT_VIRTUALTABLE) */

#ifndef SQLITE4_OMIT_VIEW
/*
** Clear the column names from every VIEW in database idx.
*/
static void sqliteViewResetAll(sqlite4 *db, int idx){
  HashElem *i;
  if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
  for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
    Table *pTab = sqliteHashData(i);
    if( pTab->pSelect ){
      sqliteDeleteColumnNames(db, pTab);
      pTab->aCol = 0;
      pTab->nCol = 0;
    }
  }
  DbClearProperty(db, idx, DB_UnresetViews);
}
#else
# define sqliteViewResetAll(A,B)
#endif /* SQLITE4_OMIT_VIEW */


/*
** Write code to erase the table with root-page iTable from database iDb.
** Also write code to modify the sqlite_master table and internal schema
** if a root-page of another table is moved by the btree-layer whilst
** erasing iTable (this can happen with an auto-vacuum database).
*/ 
static void destroyRootPage(Parse *pParse, int iTable, int iDb){
  Vdbe *v = sqlite4GetVdbe(pParse);
  sqlite4VdbeAddOp2(v, OP_Clear, iTable, iDb);
#if 0
  sqlite4MayAbort(pParse);
#endif
}

/*
** Write VDBE code to erase table pTab and all associated indices on disk.
** Code to update the sqlite_master tables and internal schema definitions
** in case a root-page belonging to another table is moved by the btree layer
** is also added (this can happen with an auto-vacuum database).
*/
static void destroyTable(Parse *pParse, Table *pTab){
  Index *pIdx;
  int iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    destroyRootPage(pParse, pIdx->tnum, iDb);
  }
}

/*
** Remove entries from the sqlite_statN tables (for N in (1,2,3))
** after a DROP INDEX or DROP TABLE command.
*/
static void sqlite4ClearStatTables(
  Parse *pParse,         /* The parsing context */
  int iDb,               /* The database number */
  const char *zType,     /* "idx" or "tbl" */
  const char *zName      /* Name of index or table */
){
  int i;
  const char *zDbName = pParse->db->aDb[iDb].zName;
  for(i=1; i<=3; i++){
    char zTab[24];
    sqlite4_snprintf(zTab,sizeof(zTab),"sqlite_stat%d",i);
    if( sqlite4FindTable(pParse->db, zTab, zDbName) ){
      sqlite4NestedParse(pParse,
        "DELETE FROM %Q.%s WHERE %s=%Q",
        zDbName, zTab, zType, zName
      );
    }
  }
}

/*
** Generate code to drop a table.
*/
SQLITE4_PRIVATE void sqlite4CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
  Vdbe *v;
  sqlite4 *db = pParse->db;
  Trigger *pTrigger;
  Db *pDb = &db->aDb[iDb];

  v = sqlite4GetVdbe(pParse);
  assert( v!=0 );
  sqlite4BeginWriteOperation(pParse, 1, iDb);

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if( IsVirtual(pTab) ){
    sqlite4VdbeAddOp0(v, OP_VBegin);
  }
#endif

  /* Drop all triggers associated with the table being dropped. Code
  ** is generated to remove entries from sqlite_master and/or
  ** sqlite_temp_master if required.
  */
  pTrigger = sqlite4TriggerList(pParse, pTab);
  while( pTrigger ){
    assert( pTrigger->pSchema==pTab->pSchema || 
        pTrigger->pSchema==db->aDb[1].pSchema );
    sqlite4DropTriggerPtr(pParse, pTrigger);
    pTrigger = pTrigger->pNext;
  }

#ifndef SQLITE4_OMIT_AUTOINCREMENT
  /* Remove any entries of the sqlite_sequence table associated with
  ** the table being dropped. This is done before the table is dropped
  ** at the btree level, in case the sqlite_sequence table needs to
  ** move as a result of the drop (can happen in auto-vacuum mode).
  */
  if( pTab->tabFlags & TF_Autoincrement ){
    sqlite4NestedParse(pParse,
      "DELETE FROM %Q.sqlite_sequence WHERE name=%Q",
      pDb->zName, pTab->zName
    );
  }
#endif

  /* Drop all SQLITE4_MASTER table and index entries that refer to the
  ** table. The program name loops through the master table and deletes
  ** every row that refers to a table of the same name as the one being
  ** dropped. Triggers are handled seperately because a trigger can be
  ** created in the temp database that refers to a table in another
  ** database.
  */
  sqlite4NestedParse(pParse, 
      "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
      pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
  if( !isView && !IsVirtual(pTab) ){
    destroyTable(pParse, pTab);
  }

  /* Remove the table entry from SQLite's internal schema and modify
  ** the schema cookie.
  */
  if( IsVirtual(pTab) ){
    sqlite4VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
  }
  sqlite4VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
  sqlite4ChangeCookie(pParse, iDb);
  sqliteViewResetAll(db, iDb);
}

/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
SQLITE4_PRIVATE void sqlite4DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
  Table *pTab;
  Vdbe *v;
  sqlite4 *db = pParse->db;
  int iDb;

  if( db->mallocFailed ){
    goto exit_drop_table;
  }
  assert( pParse->nErr==0 );
  assert( pName->nSrc==1 );
  if( noErr ) db->suppressErr++;
  pTab = sqlite4LocateTable(pParse, isView, 
                            pName->a[0].zName, pName->a[0].zDatabase);
  if( noErr ) db->suppressErr--;

  if( pTab==0 ){
    if( noErr ) sqlite4CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
    goto exit_drop_table;
  }
  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  assert( iDb>=0 && iDb<db->nDb );

  /* If pTab is a virtual table, call ViewGetColumnNames() to ensure
  ** it is initialized.
  */
  if( IsVirtual(pTab) && sqlite4ViewGetColumnNames(pParse, pTab) ){
    goto exit_drop_table;
  }
#ifndef SQLITE4_OMIT_AUTHORIZATION
  {
    int code;
    const char *zTab = SCHEMA_TABLE(iDb);
    const char *zDb = db->aDb[iDb].zName;
    const char *zArg2 = 0;
    if( sqlite4AuthCheck(pParse, SQLITE4_DELETE, zTab, 0, zDb)){
      goto exit_drop_table;
    }
    if( isView ){
      if( !OMIT_TEMPDB && iDb==1 ){
        code = SQLITE4_DROP_TEMP_VIEW;
      }else{
        code = SQLITE4_DROP_VIEW;
      }
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    }else if( IsVirtual(pTab) ){
      code = SQLITE4_DROP_VTABLE;
      zArg2 = sqlite4GetVTable(db, pTab)->pMod->zName;
#endif
    }else{
      if( !OMIT_TEMPDB && iDb==1 ){
        code = SQLITE4_DROP_TEMP_TABLE;
      }else{
        code = SQLITE4_DROP_TABLE;
      }
    }
    if( sqlite4AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){
      goto exit_drop_table;
    }
    if( sqlite4AuthCheck(pParse, SQLITE4_DELETE, pTab->zName, 0, zDb) ){
      goto exit_drop_table;
    }
  }
#endif
  if( sqlite4_strnicmp(pTab->zName, "sqlite_", 7)==0 
    && sqlite4_strnicmp(pTab->zName, "sqlite_stat", 11)!=0 ){
    sqlite4ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
    goto exit_drop_table;
  }

#ifndef SQLITE4_OMIT_VIEW
  /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
  ** on a table.
  */
  if( isView && pTab->pSelect==0 ){
    sqlite4ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
    goto exit_drop_table;
  }
  if( !isView && pTab->pSelect ){
    sqlite4ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
    goto exit_drop_table;
  }
#endif

  /* Generate code to remove the table from the master table
  ** on disk.
  */
  v = sqlite4GetVdbe(pParse);
  if( v ){
    sqlite4BeginWriteOperation(pParse, 1, iDb);
    sqlite4ClearStatTables(pParse, iDb, "tbl", pTab->zName);
    sqlite4FkDropTable(pParse, pName, pTab);
    sqlite4CodeDropTable(pParse, pTab, iDb, isView);
  }

exit_drop_table:
  sqlite4SrcListDelete(db, pName);
}

/*
** This routine is called to create a new foreign key on the table
** currently under construction.  pFromCol determines which columns
** in the current table point to the foreign key.  If pFromCol==0 then
** connect the key to the last column inserted.  pTo is the name of
** the table referred to.  pToCol is a list of tables in the other
** pTo table that the foreign key points to.  flags contains all
** information about the conflict resolution algorithms specified
** in the ON DELETE, ON UPDATE and ON INSERT clauses.
**
** An FKey structure is created and added to the table currently
** under construction in the pParse->pNewTable field.
**
** The foreign key is set for IMMEDIATE processing.  A subsequent call
** to sqlite4DeferForeignKey() might change this to DEFERRED.
*/
SQLITE4_PRIVATE void sqlite4CreateForeignKey(
  Parse *pParse,       /* Parsing context */
  ExprList *pFromCol,  /* Columns in this table that point to other table */
  Token *pTo,          /* Name of the other table */
  ExprList *pToCol,    /* Columns in the other table */
  int flags            /* Conflict resolution algorithms. */
){
  sqlite4 *db = pParse->db;
#ifndef SQLITE4_OMIT_FOREIGN_KEY
  FKey *pFKey = 0;
  FKey *pNextTo;
  Table *p = pParse->pNewTable;
  int nByte;
  int i;
  int nCol;
  char *z;

  assert( pTo!=0 );
  if( p==0 || IN_DECLARE_VTAB ) goto fk_end;
  if( pFromCol==0 ){
    int iCol = p->nCol-1;
    if( NEVER(iCol<0) ) goto fk_end;
    if( pToCol && pToCol->nExpr!=1 ){
      sqlite4ErrorMsg(pParse, "foreign key on %s"
         " should reference only one column of table %T",
         p->aCol[iCol].zName, pTo);
      goto fk_end;
    }
    nCol = 1;
  }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){
    sqlite4ErrorMsg(pParse,
        "number of columns in foreign key does not match the number of "
        "columns in the referenced table");
    goto fk_end;
  }else{
    nCol = pFromCol->nExpr;
  }
  nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
  if( pToCol ){
    for(i=0; i<pToCol->nExpr; i++){
      nByte += sqlite4Strlen30(pToCol->a[i].zName) + 1;
    }
  }
  pFKey = sqlite4DbMallocZero(db, nByte );
  if( pFKey==0 ){
    goto fk_end;
  }
  pFKey->pFrom = p;
  pFKey->pNextFrom = p->pFKey;
  z = (char*)&pFKey->aCol[nCol];
  pFKey->zTo = z;
  memcpy(z, pTo->z, pTo->n);
  z[pTo->n] = 0;
  sqlite4Dequote(z);
  z += pTo->n+1;
  pFKey->nCol = nCol;
  if( pFromCol==0 ){
    pFKey->aCol[0].iFrom = p->nCol-1;
  }else{
    for(i=0; i<nCol; i++){
      int j;
      for(j=0; j<p->nCol; j++){
        if( sqlite4_stricmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
          pFKey->aCol[i].iFrom = j;
          break;
        }
      }
      if( j>=p->nCol ){
        sqlite4ErrorMsg(pParse, 
          "unknown column \"%s\" in foreign key definition", 
          pFromCol->a[i].zName);
        goto fk_end;
      }
    }
  }
  if( pToCol ){
    for(i=0; i<nCol; i++){
      int n = sqlite4Strlen30(pToCol->a[i].zName);
      pFKey->aCol[i].zCol = z;
      memcpy(z, pToCol->a[i].zName, n);
      z[n] = 0;
      z += n+1;
    }
  }
  pFKey->isDeferred = 0;
  pFKey->aAction[0] = (u8)(flags & 0xff);            /* ON DELETE action */
  pFKey->aAction[1] = (u8)((flags >> 8 ) & 0xff);    /* ON UPDATE action */

  pNextTo = (FKey *)sqlite4HashInsert(&p->pSchema->fkeyHash, 
      pFKey->zTo, sqlite4Strlen30(pFKey->zTo), (void *)pFKey
  );
  if( pNextTo==pFKey ){
    db->mallocFailed = 1;
    goto fk_end;
  }
  if( pNextTo ){
    assert( pNextTo->pPrevTo==0 );
    pFKey->pNextTo = pNextTo;
    pNextTo->pPrevTo = pFKey;
  }

  /* Link the foreign key to the table as the last step.
  */
  p->pFKey = pFKey;
  pFKey = 0;

fk_end:
  sqlite4DbFree(db, pFKey);
#endif /* !defined(SQLITE4_OMIT_FOREIGN_KEY) */
  sqlite4ExprListDelete(db, pFromCol);
  sqlite4ExprListDelete(db, pToCol);
}

/*
** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED
** clause is seen as part of a foreign key definition.  The isDeferred
** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.
** The behavior of the most recently created foreign key is adjusted
** accordingly.
*/
SQLITE4_PRIVATE void sqlite4DeferForeignKey(Parse *pParse, int isDeferred){
#ifndef SQLITE4_OMIT_FOREIGN_KEY
  Table *pTab;
  FKey *pFKey;
  if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
  assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
  pFKey->isDeferred = (u8)isDeferred;
#endif
}

/*
** Cursor iPkCsr is open on a primary key index. This function generates
** code that creates the corresponding covering index record required
** by pIdx by reading values from this cursor. The record is stored in
** register regOut.
*/
SQLITE4_PRIVATE void sqlite4EncodeIndexValue(
  Parse *pParse,                  /* Parse context */
  int iPkCsr,                     /* Cursor open on primary key */
  Index *pIdx,                    /* Index to create record for */
  int regOut                      /* Register to write record to */
){
  Vdbe *v = pParse->pVdbe;        /* Generate code into this virtual machine */
  Table *pTab = pIdx->pTable;     /* The table that is indexed */
  int i;                          /* Used to iterate through columns */
  int reg;                        /* Array of pIdx->nCover temp registers */

  reg = sqlite4GetTempRange(pParse, pIdx->nCover);
  for(i=0; i<pIdx->nCover; i++){
    sqlite4ExprCodeGetColumnOfTable(v, pTab, iPkCsr, pIdx->aiCover[i], reg+i);
  }
  sqlite4VdbeAddOp3(v, OP_MakeRecord, reg, pIdx->nCover, regOut);
  sqlite4ReleaseTempRange(pParse, reg, pIdx->nCover);
}

/*
** Generate code that will erase and refill index *pIdx.  This is
** used to initialize a newly created index or to recompute the
** content of an index in response to a REINDEX command.
*/
static void sqlite4RefillIndex(Parse *pParse, Index *pIdx, int bCreate){
  Table *pTab = pIdx->pTable;    /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Cursor used for PK of pTab */
  int iIdx = pParse->nTab++;     /* Cursor used for pIdx */
  int addr1;                     /* Address of top of loop */
  Vdbe *v;                       /* Generate code into this virtual machine */
  int regKey;                    /* Registers containing the index key */
  sqlite4 *db = pParse->db;      /* The database connection */
  int iDb = sqlite4SchemaToIndex(db, pIdx->pSchema);
  Index *pPk;

#ifndef SQLITE4_OMIT_AUTHORIZATION
  if( sqlite4AuthCheck(pParse, SQLITE4_REINDEX, pIdx->zName, 0,
      db->aDb[iDb].zName ) ){
    return;
  }
#endif

  pPk = sqlite4FindPrimaryKey(pTab, 0);
  v = sqlite4GetVdbe(pParse);
  if( v==0 ) return;

  /* A write-lock on the table is required to perform this operation. Easiest
  ** way to do this is to open a write-cursor on the PK - even though this
  ** operation only requires read access.  */
  sqlite4OpenPrimaryKey(pParse, iTab, iDb, pTab, OP_OpenWrite);

  /* Delete the current contents (if any) of the index. Then open a write
  ** cursor on it.  */
  if( bCreate==0 ){
    sqlite4VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
  }
  sqlite4OpenIndex(pParse, iIdx, iDb, pIdx, OP_OpenWrite);
  if( bCreate ) sqlite4VdbeChangeP5(v, 1);

  /* Loop through the contents of the PK index. At each row, insert the
  ** corresponding entry into the auxiliary index.  */
  addr1 = sqlite4VdbeAddOp2(v, OP_Rewind, iTab, 0);

  if( pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){
    int regData;
    int i;

    regKey = sqlite4GetTempRange(pParse, pTab->nCol+1);
    regData = regKey+1;

    sqlite4VdbeAddOp2(v, OP_RowKey, iTab, regKey);
    for(i=0; i<pTab->nCol; i++){
      sqlite4VdbeAddOp3(v, OP_Column, iTab, i, regData+i);
    }
    sqlite4Fts5CodeUpdate(pParse, pIdx, pParse->iNewidxReg, regKey, regData, 0);
  }else{
    int regData = 0;
    regKey = sqlite4GetTempRange(pParse, 2);
    sqlite4EncodeIndexKey(pParse, pPk, iTab, pIdx, iIdx, 0, regKey);
    if( pIdx->onError!=OE_None ){
      const char *zErr = "indexed columns are not unique";
      int addrTest;

      addrTest = sqlite4VdbeAddOp4Int(v, OP_IsUnique, iIdx, 0, regKey, 0);
      sqlite4HaltConstraint(pParse, OE_Abort, (char *)zErr, P4_STATIC);
      sqlite4VdbeJumpHere(v, addrTest);
    }
    if( pIdx->nCover>0 ){
      regData = regKey+1;
      sqlite4EncodeIndexValue(pParse, iTab, pIdx, regData);
    }
    sqlite4VdbeAddOp3(v, OP_Insert, iIdx, regData, regKey);  
    sqlite4ReleaseTempRange(pParse, regKey, 2);
  }

  sqlite4VdbeAddOp2(v, OP_Next, iTab, addr1+1);
  sqlite4VdbeJumpHere(v, addr1);

  sqlite4VdbeAddOp1(v, OP_Close, iTab);
  sqlite4VdbeAddOp1(v, OP_Close, iIdx);
}

/*
** The CreateIndex structure indicated by the first argument contains the
** results of parsing the first part of a CREATE INDEX statement. 
** Specifically, everything up to and including the "ON tblname" clause.
** The index may be an ordinary index, or it may be a "USING fts5" index.
** This function performs processing common to both.
*/
static Table *createIndexFindTable(
  Parse *pParse,                  /* Parsing context */
  CreateIndex *p,                 /* First part of CREATE INDEX statement */
  Token **ppIdxName,              /* OUT: Pointer to index name token */
  char **pzIdxName,               /* OUT: DbMalloc'd copy of index name */
  int *piDb                       /* OUT: Database to create index in */
){
  DbFixer sFix;                   /* For assigning database names to pTblName */
  sqlite4 *db = pParse->db;       /* Database handle */
  Token *pName = 0;               /* Token containing unqualified index name */
  char *zName;                    /* Name of index being created */
  int iDb;                        /* Index of database in db->aDb[] */
  Table *pTab;                    /* Table object to return */

  /* Use the two-part index name to determine the database 
  ** to search for the table. 'Fix' the table name to this db
  ** before looking up the table.  */
  iDb = sqlite4TwoPartName(pParse, &p->tName1, &p->tName2, &pName);
  if( iDb<0 ) return 0;
  assert( pName && pName->z );

#ifndef SQLITE4_OMIT_TEMPDB
  /* If the index name was unqualified, check if the the table
  ** is a temp table. If so, set the database to 1. Do not do this
  ** if initialising a database schema.  */
  if( !db->init.busy ){
    pTab = sqlite4SrcListLookup(pParse, p->pTblName);
    if( p->tName2.n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
      iDb = 1;
    }
  }
#endif

  if( sqlite4FixInit(&sFix, pParse, iDb, "index", pName) &&
      sqlite4FixSrcList(&sFix, p->pTblName)
  ){
    /* Because the parser constructs pTblName from a single identifier,
    ** sqlite4FixSrcList can never fail. */
    assert(0);
  }

  pTab = sqlite4SrcListLookup(pParse, p->pTblName);
  if( !pTab || db->mallocFailed ) return 0;
  assert( db->aDb[iDb].pSchema==pTab->pSchema );
  assert( pParse->nErr==0 );

  /* TODO: We will need to reinstate this block when sqlite_master is 
  ** modified to use an implicit primary key.  */
  if( sqlite4_strnicmp(pTab->zName, "sqlite_", 7)==0 
   && memcmp(&pTab->zName[7],"altertab_",9)!=0 
  ){
    sqlite4ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
    return 0;
  }

  /* Verify that this is not an attempt to create an index on a view or
  ** virtual table. */
  if( IsView(pTab) ){
    sqlite4ErrorMsg(pParse, "views may not be indexed");
    return 0;
  }
  if( IsVirtual(pTab) ){
    sqlite4ErrorMsg(pParse, "virtual tables may not be indexed");
    return 0;
  }

  /* Ensure that the proposed index name is not reserved. */
  assert( pName->z!=0 );
  zName = sqlite4NameFromToken(db, pName);
  if( zName==0 || sqlite4CheckObjectName(pParse, zName) ){
    pTab = 0;
  }

  /* Unless SQLite is currently parsing an existing database schema, check
  ** that there is not already an index or table using the proposed name.  */
  else if( !db->init.busy ){
    char *zDb = db->aDb[iDb].zName;
    if( sqlite4FindTable(db, zName, zDb)!=0 ){
      sqlite4ErrorMsg(pParse, "there is already a table named %s", zName);
    }
    else if( sqlite4FindIndex(db, zName, zDb)!=0 ){
      if( p->bIfnotexist ){
        assert( !db->init.busy );
        sqlite4CodeVerifySchema(pParse, iDb);
        pTab = 0;
      }else{
        sqlite4ErrorMsg(pParse, "index %s already exists", zName);
      }
    }
  }

  if( pParse->nErr || pTab==0 ){
    sqlite4DbFree(db, zName);
    pTab = 0;
    zName = 0;
  }
  *ppIdxName = pName;
  *pzIdxName = zName;
  *piDb = iDb;
  return pTab;
}

#ifndef SQLITE4_OMIT_AUTHORIZATION
/*
** Check for authorization to create index zIdx on table pTab. If 
** authorization is granted, return zero. Otherwise, return non-zero
** and leave an error in pParse.
*/
static int createIndexAuth(
  Parse *pParse,                  /* Parser context */
  Table *pTab,                    /* Table index is being created on */
  const char *zIdx                /* Name of index being created */
){
  sqlite4 *db;
  int iDb;
  int iOp;
  const char *zDb;

  db = pParse->db;
  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  zDb = db->aDb[iDb].zName;

  if( sqlite4AuthCheck(pParse, SQLITE4_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){
    return 1;
  }

  iOp = (!OMIT_TEMPDB && iDb==1)?SQLITE4_CREATE_TEMP_INDEX:SQLITE4_CREATE_INDEX;
  if( sqlite4AuthCheck(pParse, iOp, zIdx, pTab->zName, zDb) ){
    return 1;
  }

  return 0;
}
#else
# define createIndexAuth(a, b, c) 0
#endif // SQLITE4_OMIT_AUTHORIZATION

/*
** This function is called when parsing a CREATE statement executed by the
** user (not when parsing the schema of an existing database). It generates
** the VDBE code to assign a root page number to the new index and, if 
** required, to write a new entry into the sqlite_master table.
*/
static void createIndexWriteSchema(
  Parse *pParse,                  /* Parser context */
  Index *pIdx,                    /* New index object */
  Token *pName,                   /* Token containing name of new index */
  Token *pEnd                     /* Token for final closing paren of CREATE */
){
  sqlite4 *db = pParse->db;
  int iDb;

  assert( db->init.busy==0 );
  iDb = sqlite4SchemaToIndex(db, pIdx->pSchema);
  pIdx->tnum = ++pParse->nMem;
  allocateTableNumber(pParse, iDb, pIdx->tnum);

  if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){
    Vdbe *v;
    char *zStmt;

    v = sqlite4GetVdbe(pParse);
    if( v==0 ) return;

    sqlite4BeginWriteOperation(pParse, 1, iDb);

    /* Unless this index is an automatic index created by a UNIQUE 
    ** constraint, assemble a CREATE INDEX statement to write into the 
    ** sqlite_master table.  */
    if( pIdx->eIndexType!=SQLITE4_INDEX_UNIQUE ){
      int n = (int)(pEnd->z - pName->z) + pEnd->n;
      const char *zUnique = (pIdx->onError==OE_None ? "" : " UNIQUE");
      zStmt = sqlite4MPrintf(db, "CREATE%s INDEX %.*s", zUnique, n, pName->z);
    }else{
      /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
      zStmt = 0;
    }

    /* Add an entry in sqlite_master for this index */
    sqlite4NestedParse(pParse, 
        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
        db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
        pIdx->zName,
        pIdx->pTable->zName,
        pIdx->tnum,
        zStmt
    );
    sqlite4DbFree(db, zStmt);

    /* Fill the index with data and reparse the schema. Code an OP_Expire
    ** to invalidate all pre-compiled statements.
    */
    if( pIdx->eIndexType!=SQLITE4_INDEX_UNIQUE ){
      sqlite4RefillIndex(pParse, pIdx, 1);
      sqlite4ChangeCookie(pParse, iDb);
      sqlite4VdbeAddParseSchemaOp(v, iDb,
          sqlite4MPrintf(db, "name='%q' AND type='index'", pIdx->zName));
      sqlite4VdbeAddOp1(v, OP_Expire, 0);
    }
  }
}

SQLITE4_PRIVATE void sqlite4CreateUsingIndex(
  Parse *pParse,                  /* Parsing context */
  CreateIndex *p,                 /* First part of CREATE INDEX statement */
  ExprList *pList,
  Token *pUsing,                  /* Token following USING keyword */
  Token *pEnd                     /* Final '(' in CREATE INDEX */
){
  sqlite4 *db = pParse->db;
  if( p->bUnique ){
    sqlite4ErrorMsg(pParse, "USING %.*s index may not be UNIQUE", 
        pUsing->n, pUsing->z
    );
  }else{
    Index *pIdx = 0;              /* New index object */
    Table *pTab;
    Token *pIdxName = 0;
    char *zIdx = 0;
    int iDb = 0;

    pTab = createIndexFindTable(pParse, p, &pIdxName, &zIdx, &iDb);
    if( pTab && 0==createIndexAuth(pParse, pTab, zIdx) ){
      int nExtra = sqlite4Fts5IndexSz();
      char *zExtra = 0;
      pIdx = newIndex(pParse, pTab, zIdx, 0, 0, 0, nExtra, &zExtra);
      if( pIdx ){
        pIdx->pFts = (Fts5Index *)zExtra;
        sqlite4Fts5IndexInit(pParse, pIdx, pList);
        pIdx->eIndexType = SQLITE4_INDEX_FTS5;
      }
    }

    if( pIdx ){
      if( db->init.busy ){
        db->flags |= SQLITE4_InternChanges;
        pIdx->tnum = db->init.newTnum;
        pIdx->pNext = pTab->pIndex;
        pTab->pIndex = pIdx;
        addIndexToHash(db, pIdx);
        pIdx = 0;
      }else{
        createIndexWriteSchema(pParse, pIdx, pIdxName, pEnd);
      }
    }

    if( pIdx ) freeIndex(db, pIdx);
    sqlite4DbFree(db, zIdx);
  }

  sqlite4ExprListDelete(db, pList);
  sqlite4SrcListDelete(db, p->pTblName);
}

/*
** Parameter zName points to a nul-terminated buffer containing a column
** name. If table pTab has a column of the specified name, return its
** index (the first table column being 0, the next 1 etc.). Or, if there
** is no such column, leave an error in pParse and return -1.
*/
static int findTableColumn(Parse *pParse, Table *pTab, const char *zName){
  int j;
  Column *pTabCol;

  for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
    if( sqlite4_stricmp(zName, pTabCol->zName)==0 ) break;
  }
  if( j>=pTab->nCol ){
    sqlite4ErrorMsg(pParse, "table %s has no column named %s",
        pTab->zName, zName);
    pParse->checkSchema = 1;
    return -1;
  }

  return j;
}

/*
** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
** and pTblList is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
** as the table to be indexed.  pParse->pNewTable is a table that is
** currently being constructed by a CREATE TABLE statement.
**
** pList is a list of columns to be indexed.  pList will be NULL if this
** is a primary key or unique-constraint on the most recent column added
** to the table currently under construction.  
**
** If the index is created successfully, return a pointer to the new Index
** structure. This is used by sqlite4AddPrimaryKey() to mark the index
** as the tables primary key (Index.autoIndex==2).
*/
SQLITE4_PRIVATE Index *sqlite4CreateIndex(
  Parse *pParse,     /* All information about this parse */
  CreateIndex *pCI,  /* Name of index to create etc. */
  ExprList *pList,   /* A list of columns to be indexed */
  IdList *pCovering, /* Covering list (or NULL) */
  int onError,       /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  Token *pEnd,       /* The ")" that closes the CREATE INDEX statement */
  int sortOrder,     /* Sort order of primary key when pList==NULL */
  int bPrimaryKey    /* True to create the tables primary key */
){
  Index *pRet = 0;     /* Pointer to return */
  Table *pTab = 0;     /* Table to be indexed */
  Index *pIndex = 0;   /* The index to be created */
  char *zName = 0;     /* Name of the index */
  int i, j;
  Token nullId;        /* Fake token for an empty ID list */
  sqlite4 *db = pParse->db;
  int iDb;             /* Index of the database that is being written */
  Token *pName = 0;    /* Unqualified name of the index to create */
  ExprListItem *pListItem; /* For looping over pList */
  int nExtra = 0;
  char *zExtra;

  int nCover = 0;
  Token *pStart = 0;
  SrcList *pTblName = 0;

  if( pCI ){
    pStart = &pCI->tCreate;
    pTblName = pCI->pTblName;
  }
  if( pCovering ){
    nCover = pCovering->nId;
    if( nCover==0 ) nCover = pList->nExpr;
  }

  assert( pStart==0 || pEnd!=0 ); /* pEnd must be non-NULL if pStart is */
  assert( pParse->nErr==0 );      /* Never called with prior errors */
  if( db->mallocFailed || IN_DECLARE_VTAB ){
    goto exit_create_index;
  }
  if( SQLITE4_OK!=sqlite4ReadSchema(pParse) ){
    goto exit_create_index;
  }

  /* Find the table that is to be indexed.  Return early if not found. */
  if( pCI ){
    pTab = createIndexFindTable(pParse, pCI, &pName, &zName, &iDb);
    if( !pTab ) goto exit_create_index;
  }else{
    assert( pName==0 );
    assert( pStart==0 );
    pTab = pParse->pNewTable;
    if( !pTab ) goto exit_create_index;
    iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  }

  if( db->init.busy==0 ){
    sqlite4CodeVerifySchema(pParse, iDb);
  }

  assert( pTab!=0 );
  assert( pParse->nErr==0 );
  assert( IsVirtual(pTab)==0 && IsView(pTab)==0 );

  /* If pCI==0 it means that we are dealing with a PRIMARY KEY or 
  ** UNIQUE constraint.  We have to invent our own name.  */
  if( pCI==0 ){
    if( !bPrimaryKey ){
      int n;
      Index *pLoop;
      for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
      zName = sqlite4MPrintf(db, "sqlite_%s_unique%d", pTab->zName, n);
    }else{
      zName = sqlite4MPrintf(db, "%s", pTab->zName);
    }
    if( zName==0 ){
      goto exit_create_index;
    }
  }

  /* Check for authorization to create the index.  */
  if( bPrimaryKey==0 && createIndexAuth(pParse, pTab, zName) ){
    goto exit_create_index;
  }

  /* If pList==0, it means this routine was called as a result of a PRIMARY
  ** KEY or UNIQUE constraint attached to the last column added to the table 
  ** under construction. So create a fake list to simulate this.
  **
  ** TODO: This 'fake list' could be created by the caller to reduce the
  ** number of parameters passed to this function.
  */
  if( pList==0 ){
    nullId.z = pTab->aCol[pTab->nCol-1].zName;
    nullId.n = sqlite4Strlen30((char*)nullId.z);
    pList = sqlite4ExprListAppend(pParse, 0, 0);
    if( pList==0 ) goto exit_create_index;
    sqlite4ExprListSetName(pParse, pList, &nullId, 0);
    pList->a[0].sortOrder = (u8)sortOrder;
  }

  /* Figure out how many bytes of space are required to store explicitly
  ** specified collation sequence names.
  */
  for(i=0; i<pList->nExpr; i++){
    Expr *pExpr = pList->a[i].pExpr;
    if( pExpr ){
      CollSeq *pColl = pExpr->pColl;
      /* Either pColl!=0 or there was an OOM failure.  But if an OOM
      ** failure we have quit before reaching this point. */
      if( ALWAYS(pColl) ){
        nExtra += (1 + sqlite4Strlen30(pColl->zName));
      }
    }
  }

  /* Allocate the new Index structure. */
  pIndex = newIndex(
      pParse, pTab, zName, pList->nExpr, nCover, onError, nExtra, &zExtra
  );
  if( !pIndex ) goto exit_create_index;

  assert( pIndex->eIndexType==SQLITE4_INDEX_USER );
  if( pName==0 ){
    if( bPrimaryKey ){
      pIndex->eIndexType = SQLITE4_INDEX_PRIMARYKEY;
    }else{
      pIndex->eIndexType = SQLITE4_INDEX_UNIQUE;
    }
  }

  /* Scan the names of the columns of the table to be indexed and
  ** load the column indices into the Index structure.  Report an error
  ** if any column is not found.
  **
  ** TODO:  Add a test to make sure that the same column is not named
  ** more than once within the same index.  Only the first instance of
  ** the column will ever be used by the optimizer.
  */
  for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
    char *zColl;                   /* Collation sequence name */

    j = findTableColumn(pParse, pTab, pListItem->zName);
    if( j<0 ) goto exit_create_index;

    pIndex->aiColumn[i] = j;
    if( pListItem->pExpr && pListItem->pExpr->pColl ){
      int nColl;
      zColl = pListItem->pExpr->pColl->zName;
      nColl = sqlite4Strlen30(zColl) + 1;
      assert( nExtra>=nColl );
      memcpy(zExtra, zColl, nColl);
      zColl = zExtra;
      zExtra += nColl;
      nExtra -= nColl;
    }else{
      zColl = pTab->aCol[j].zColl;
      if( !zColl ){
        zColl = db->pDfltColl->zName;
      }
    }
    if( !db->init.busy && !sqlite4LocateCollSeq(pParse, zColl) ){
      goto exit_create_index;
    }
    pIndex->azColl[i] = zColl;
    pIndex->aSortOrder[i] = (u8)pListItem->sortOrder;
  }
  sqlite4DefaultRowEst(pIndex);

  /* Scan the names of any covered columns. */
  for(i=0; i<nCover; i++){
    if( pCovering->nId ){
      j = findTableColumn(pParse, pTab, pCovering->a[i].zName);
      if( j<0 ) goto exit_create_index;
      pIndex->aiCover[i] = j;
    }else{
      pIndex->aiCover[i] = i;
    }
  }

  if( pTab==pParse->pNewTable ){
    /* This routine has been called to create an automatic index as a
    ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or
    ** a PRIMARY KEY or UNIQUE clause following the column definitions.
    ** i.e. one of:
    **
    ** CREATE TABLE t(x PRIMARY KEY, y);
    ** CREATE TABLE t(x, y, UNIQUE(x, y));
    **
    ** Either way, check to see if the table already has such an index. If
    ** so, don't bother creating this one. This only applies to
    ** automatically created indices. Users can do as they wish with
    ** explicit indices.
    **
    ** Two UNIQUE or PRIMARY KEY constraints are considered equivalent
    ** (and thus suppressing the second one) even if they have different
    ** sort orders.
    **
    ** If there are different collating sequences or if the columns of
    ** the constraint occur in different orders, then the constraints are
    ** considered distinct and both result in separate indices.
    */
    Index *pIdx;
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      int k;
      assert( pIdx->onError!=OE_None );
      assert( pIdx->eIndexType!=SQLITE4_INDEX_USER );
      assert( pIndex->onError!=OE_None );

      if( pIdx->nColumn!=pIndex->nColumn ) continue;
      for(k=0; k<pIdx->nColumn; k++){
        const char *z1;
        const char *z2;
        if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
        z1 = pIdx->azColl[k];
        z2 = pIndex->azColl[k];
        if( z1!=z2 && sqlite4_stricmp(z1, z2) ) break;
      }
      if( k==pIdx->nColumn ){
        if( pIdx->onError!=pIndex->onError ){
          /* This constraint creates the same index as a previous
          ** constraint specified somewhere in the CREATE TABLE statement.
          ** However the ON CONFLICT clauses are different. If both this 
          ** constraint and the previous equivalent constraint have explicit
          ** ON CONFLICT clauses this is an error. Otherwise, use the
          ** explicitly specified behaviour for the index.
          */
          if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
            sqlite4ErrorMsg(pParse, 
                "conflicting ON CONFLICT clauses specified", 0);
          }
          if( pIdx->onError==OE_Default ){
            pIdx->onError = pIndex->onError;
          }
        }

        /* If this index was to be the PRIMARY KEY, mark the UNIQUE index
        ** that makes it redundant as the PRIMARY KEY instead.  */
        if( bPrimaryKey ){
          assert( pIdx->eIndexType==SQLITE4_INDEX_UNIQUE );
          pIdx->eIndexType = SQLITE4_INDEX_PRIMARYKEY;
        }
        goto exit_create_index;
      }
    }
  }

  /* Link the new Index structure to its table and to the other
  ** in-memory database structures. 
  */
  if( db->init.busy ){
    db->flags |= SQLITE4_InternChanges;
    if( pTblName!=0 || bPrimaryKey ){
      pIndex->tnum = db->init.newTnum;
    }
    if( addIndexToHash(db, pIndex) ) goto exit_create_index;
  }

  /* If the db->init.busy is 0 then create the index on disk.  This
  ** involves writing the index into the master table and filling in the
  ** index with the current table contents.
  **
  ** The db->init.busy is 0 when the user first enters a CREATE INDEX 
  ** command.  db->init.busy is 1 when a database is opened and 
  ** CREATE INDEX statements are read out of the master table.  In
  ** the latter case the index already exists on disk, which is why
  ** we don't want to recreate it.
  **
  ** If pTblName==0 it means this index is generated as a primary key
  ** or UNIQUE constraint of a CREATE TABLE statement.  Since the table
  ** has just been created, it contains no data and the index initialization
  ** step can be skipped.
  */
  else{
    createIndexWriteSchema(pParse, pIndex, pName, pEnd);
  }

  /* When adding an index to the list of indices for a table, make
  ** sure all indices labeled OE_Replace come after all those labeled
  ** OE_Ignore.  This is necessary for the correct constraint check
  ** processing (in sqlite4GenerateConstraintChecks()) as part of
  ** UPDATE and INSERT statements.  
  */
  if( db->init.busy || pTblName==0 ){
    if( onError!=OE_Replace || pTab->pIndex==0
         || pTab->pIndex->onError==OE_Replace){
      pIndex->pNext = pTab->pIndex;
      pTab->pIndex = pIndex;
    }else{
      Index *pOther = pTab->pIndex;
      while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
        pOther = pOther->pNext;
      }
      pIndex->pNext = pOther->pNext;
      pOther->pNext = pIndex;
    }
    pRet = pIndex;
    pIndex = 0;
  }

  /* Clean up before exiting */
exit_create_index:
  if( pIndex ){
    sqlite4DbFree(db, pIndex->zColAff);
    sqlite4DbFree(db, pIndex);
  }
  sqlite4ExprListDelete(db, pList);
  sqlite4SrcListDelete(db, pTblName);
  sqlite4IdListDelete(db, pCovering);
  sqlite4DbFree(db, zName);
  return pRet;
}

/*
** Fill the Index.aiRowEst[] array with default information - information
** to be used when we have not run the ANALYZE command.
**
** aiRowEst[0] is suppose to contain the number of elements in the index.
** Since we do not know, guess 1 million.  aiRowEst[1] is an estimate of the
** number of rows in the table that match any particular value of the
** first column of the index.  aiRowEst[2] is an estimate of the number
** of rows that match any particular combiniation of the first 2 columns
** of the index.  And so forth.  It must always be the case that
**
**           aiRowEst[N]<=aiRowEst[N-1]
**           aiRowEst[N]>=1
**
** Apart from that, we have little to go on besides intuition as to
** how aiRowEst[] should be initialized.  The numbers generated here
** are based on typical values found in actual indices.
*/
SQLITE4_PRIVATE void sqlite4DefaultRowEst(Index *pIdx){
  tRowcnt *a = pIdx->aiRowEst;
  int i;
  tRowcnt n;
  assert( a!=0 );
  a[0] = pIdx->pTable->nRowEst;
  if( a[0]<10 ) a[0] = 10;
  n = 10;
  for(i=1; i<=pIdx->nColumn; i++){
    a[i] = n;
    if( n>5 ) n--;
  }
  if( pIdx->onError!=OE_None ){
    a[pIdx->nColumn] = 1;
  }
}

/*
** This routine will drop an existing named index.  This routine
** implements the DROP INDEX statement.
*/
SQLITE4_PRIVATE void sqlite4DropIndex(Parse *pParse, SrcList *pName, int ifExists){
  Index *pIndex;
  Vdbe *v;
  sqlite4 *db = pParse->db;
  int iDb;

  assert( pParse->nErr==0 );   /* Never called with prior errors */
  if( db->mallocFailed ){
    goto exit_drop_index;
  }
  assert( pName->nSrc==1 );
  if( SQLITE4_OK!=sqlite4ReadSchema(pParse) ){
    goto exit_drop_index;
  }
  pIndex = sqlite4FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
  if( pIndex==0 ){
    if( !ifExists ){
      sqlite4ErrorMsg(pParse, "no such index: %S", pName, 0);
    }else{
      sqlite4CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
    }
    pParse->checkSchema = 1;
    goto exit_drop_index;
  }
  if( pIndex->eIndexType!=SQLITE4_INDEX_USER 
   && pIndex->eIndexType!=SQLITE4_INDEX_FTS5 
  ){
    sqlite4ErrorMsg(pParse, "index associated with UNIQUE "
      "or PRIMARY KEY constraint cannot be dropped", 0);
    goto exit_drop_index;
  }
  iDb = sqlite4SchemaToIndex(db, pIndex->pSchema);
#ifndef SQLITE4_OMIT_AUTHORIZATION
  {
    int code = SQLITE4_DROP_INDEX;
    Table *pTab = pIndex->pTable;
    const char *zDb = db->aDb[iDb].zName;
    const char *zTab = SCHEMA_TABLE(iDb);
    if( sqlite4AuthCheck(pParse, SQLITE4_DELETE, zTab, 0, zDb) ){
      goto exit_drop_index;
    }
    if( !OMIT_TEMPDB && iDb ) code = SQLITE4_DROP_TEMP_INDEX;
    if( sqlite4AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
      goto exit_drop_index;
    }
  }
#endif

  /* Generate code to remove the index and from the master table */
  v = sqlite4GetVdbe(pParse);
  if( v ){
    sqlite4BeginWriteOperation(pParse, 1, iDb);
    sqlite4NestedParse(pParse,
       "DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pIndex->zName
    );
    sqlite4ClearStatTables(pParse, iDb, "idx", pIndex->zName);
    sqlite4ChangeCookie(pParse, iDb);
    destroyRootPage(pParse, pIndex->tnum, iDb);
    sqlite4VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
  }

exit_drop_index:
  sqlite4SrcListDelete(db, pName);
}

/*
** pArray is a pointer to an array of objects.  Each object in the
** array is szEntry bytes in size.  This routine allocates a new
** object on the end of the array.
**
** *pnEntry is the number of entries already in use.  *pnAlloc is
** the previously allocated size of the array.  initSize is the
** suggested initial array size allocation.
**
** The index of the new entry is returned in *pIdx.
**
** This routine returns a pointer to the array of objects.  This
** might be the same as the pArray parameter or it might be a different
** pointer if the array was resized.
*/
SQLITE4_PRIVATE void *sqlite4ArrayAllocate(
  sqlite4 *db,      /* Connection to notify of malloc failures */
  void *pArray,     /* Array of objects.  Might be reallocated */
  int szEntry,      /* Size of each object in the array */
  int initSize,     /* Suggested initial allocation, in elements */
  int *pnEntry,     /* Number of objects currently in use */
  int *pnAlloc,     /* Current size of the allocation, in elements */
  int *pIdx         /* Write the index of a new slot here */
){
  char *z;
  if( *pnEntry >= *pnAlloc ){
    void *pNew;
    int newSize;
    newSize = (*pnAlloc)*2 + initSize;
    pNew = sqlite4DbRealloc(db, pArray, newSize*szEntry);
    if( pNew==0 ){
      *pIdx = -1;
      return pArray;
    }
    *pnAlloc = sqlite4DbMallocSize(db, pNew)/szEntry;
    pArray = pNew;
  }
  z = (char*)pArray;
  memset(&z[*pnEntry * szEntry], 0, szEntry);
  *pIdx = *pnEntry;
  ++*pnEntry;
  return pArray;
}

/*
** Append a new element to the given IdList.  Create a new IdList if
** need be.
**
** A new IdList is returned, or NULL if malloc() fails.
*/
SQLITE4_PRIVATE IdList *sqlite4IdListAppend(sqlite4 *db, IdList *pList, Token *pToken){
  int i;
  if( pList==0 ){
    pList = sqlite4DbMallocZero(db, sizeof(IdList) );
    if( pList==0 ) return 0;
    pList->nAlloc = 0;
  }
  pList->a = sqlite4ArrayAllocate(
      db,
      pList->a,
      sizeof(pList->a[0]),
      5,
      &pList->nId,
      &pList->nAlloc,
      &i
  );
  if( i<0 ){
    sqlite4IdListDelete(db, pList);
    return 0;
  }
  pList->a[i].zName = sqlite4NameFromToken(db, pToken);
  return pList;
}

/*
** Delete an IdList.
*/
SQLITE4_PRIVATE void sqlite4IdListDelete(sqlite4 *db, IdList *pList){
  int i;
  if( pList==0 ) return;
  for(i=0; i<pList->nId; i++){
    sqlite4DbFree(db, pList->a[i].zName);
  }
  sqlite4DbFree(db, pList->a);
  sqlite4DbFree(db, pList);
}

/*
** Return the index in pList of the identifier named zId.  Return -1
** if not found.
*/
SQLITE4_PRIVATE int sqlite4IdListIndex(IdList *pList, const char *zName){
  int i;
  if( pList==0 ) return -1;
  for(i=0; i<pList->nId; i++){
    if( sqlite4_stricmp(pList->a[i].zName, zName)==0 ) return i;
  }
  return -1;
}

/*
** Expand the space allocated for the given SrcList object by
** creating nExtra new slots beginning at iStart.  iStart is zero based.
** New slots are zeroed.
**
** For example, suppose a SrcList initially contains two entries: A,B.
** To append 3 new entries onto the end, do this:
**
**    sqlite4SrcListEnlarge(db, pSrclist, 3, 2);
**
** After the call above it would contain:  A, B, nil, nil, nil.
** If the iStart argument had been 1 instead of 2, then the result
** would have been:  A, nil, nil, nil, B.  To prepend the new slots,
** the iStart value would be 0.  The result then would
** be: nil, nil, nil, A, B.
**
** If a memory allocation fails the SrcList is unchanged.  The
** db->mallocFailed flag will be set to true.
*/
SQLITE4_PRIVATE SrcList *sqlite4SrcListEnlarge(
  sqlite4 *db,       /* Database connection to notify of OOM errors */
  SrcList *pSrc,     /* The SrcList to be enlarged */
  int nExtra,        /* Number of new slots to add to pSrc->a[] */
  int iStart         /* Index in pSrc->a[] of first new slot */
){
  int i;

  /* Sanity checking on calling parameters */
  assert( iStart>=0 );
  assert( nExtra>=1 );
  assert( pSrc!=0 );
  assert( iStart<=pSrc->nSrc );

  /* Allocate additional space if needed */
  if( pSrc->nSrc+nExtra>pSrc->nAlloc ){
    SrcList *pNew;
    int nAlloc = pSrc->nSrc+nExtra;
    int nGot;
    pNew = sqlite4DbRealloc(db, pSrc,
               sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
    if( pNew==0 ){
      assert( db->mallocFailed );
      return pSrc;
    }
    pSrc = pNew;
    nGot = (sqlite4DbMallocSize(db, pNew) - sizeof(*pSrc))/sizeof(pSrc->a[0])+1;
    pSrc->nAlloc = (u16)nGot;
  }

  /* Move existing slots that come after the newly inserted slots
  ** out of the way */
  for(i=pSrc->nSrc-1; i>=iStart; i--){
    pSrc->a[i+nExtra] = pSrc->a[i];
  }
  pSrc->nSrc += (i16)nExtra;

  /* Zero the newly allocated slots */
  memset(&pSrc->a[iStart], 0, sizeof(pSrc->a[0])*nExtra);
  for(i=iStart; i<iStart+nExtra; i++){
    pSrc->a[i].iCursor = -1;
  }

  /* Return a pointer to the enlarged SrcList */
  return pSrc;
}


/*
** Append a new table name to the given SrcList.  Create a new SrcList if
** need be.  A new entry is created in the SrcList even if pTable is NULL.
**
** A SrcList is returned, or NULL if there is an OOM error.  The returned
** SrcList might be the same as the SrcList that was input or it might be
** a new one.  If an OOM error does occurs, then the prior value of pList
** that is input to this routine is automatically freed.
**
** If pDatabase is not null, it means that the table has an optional
** database name prefix.  Like this:  "database.table".  The pDatabase
** points to the table name and the pTable points to the database name.
** The SrcList.a[].zName field is filled with the table name which might
** come from pTable (if pDatabase is NULL) or from pDatabase.  
** SrcList.a[].zDatabase is filled with the database name from pTable,
** or with NULL if no database is specified.
**
** In other words, if call like this:
**
**         sqlite4SrcListAppend(D,A,B,0);
**
** Then B is a table name and the database name is unspecified.  If called
** like this:
**
**         sqlite4SrcListAppend(D,A,B,C);
**
** Then C is the table name and B is the database name.  If C is defined
** then so is B.  In other words, we never have a case where:
**
**         sqlite4SrcListAppend(D,A,0,C);
**
** Both pTable and pDatabase are assumed to be quoted.  They are dequoted
** before being added to the SrcList.
*/
SQLITE4_PRIVATE SrcList *sqlite4SrcListAppend(
  sqlite4 *db,        /* Connection to notify of malloc failures */
  SrcList *pList,     /* Append to this SrcList. NULL creates a new SrcList */
  Token *pTable,      /* Table to append */
  Token *pDatabase    /* Database of the table */
){
  SrcListItem *pItem;
  assert( pDatabase==0 || pTable!=0 );  /* Cannot have C without B */
  if( pList==0 ){
    pList = sqlite4DbMallocZero(db, sizeof(SrcList) );
    if( pList==0 ) return 0;
    pList->nAlloc = 1;
  }
  pList = sqlite4SrcListEnlarge(db, pList, 1, pList->nSrc);
  if( db->mallocFailed ){
    sqlite4SrcListDelete(db, pList);
    return 0;
  }
  pItem = &pList->a[pList->nSrc-1];
  if( pDatabase && pDatabase->z==0 ){
    pDatabase = 0;
  }
  if( pDatabase ){
    Token *pTemp = pDatabase;
    pDatabase = pTable;
    pTable = pTemp;
  }
  pItem->zName = sqlite4NameFromToken(db, pTable);
  pItem->zDatabase = sqlite4NameFromToken(db, pDatabase);
  return pList;
}

/*
** Assign VdbeCursor index numbers to all tables in a SrcList
*/
SQLITE4_PRIVATE void sqlite4SrcListAssignCursors(Parse *pParse, SrcList *pList){
  int i;
  SrcListItem *pItem;
  assert(pList || pParse->db->mallocFailed );
  if( pList ){
    for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
      if( pItem->iCursor>=0 ) break;
      pItem->iCursor = pParse->nTab++;
      if( pItem->pSelect ){
        sqlite4SrcListAssignCursors(pParse, pItem->pSelect->pSrc);
      }
    }
  }
}

/*
** Delete an entire SrcList including all its substructure.
*/
SQLITE4_PRIVATE void sqlite4SrcListDelete(sqlite4 *db, SrcList *pList){
  int i;
  SrcListItem *pItem;
  if( pList==0 ) return;
  for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
    sqlite4DbFree(db, pItem->zDatabase);
    sqlite4DbFree(db, pItem->zName);
    sqlite4DbFree(db, pItem->zAlias);
    sqlite4DbFree(db, pItem->zIndex);
    sqlite4DeleteTable(db, pItem->pTab);
    sqlite4SelectDelete(db, pItem->pSelect);
    sqlite4ExprDelete(db, pItem->pOn);
    sqlite4IdListDelete(db, pItem->pUsing);
  }
  sqlite4DbFree(db, pList);
}

/*
** This routine is called by the parser to add a new term to the
** end of a growing FROM clause.  The "p" parameter is the part of
** the FROM clause that has already been constructed.  "p" is NULL
** if this is the first term of the FROM clause.  pTable and pDatabase
** are the name of the table and database named in the FROM clause term.
** pDatabase is NULL if the database name qualifier is missing - the
** usual case.  If the term has a alias, then pAlias points to the
** alias token.  If the term is a subquery, then pSubquery is the
** SELECT statement that the subquery encodes.  The pTable and
** pDatabase parameters are NULL for subqueries.  The pOn and pUsing
** parameters are the content of the ON and USING clauses.
**
** Return a new SrcList which encodes is the FROM with the new
** term added.
*/
SQLITE4_PRIVATE SrcList *sqlite4SrcListAppendFromTerm(
  Parse *pParse,          /* Parsing context */
  SrcList *p,             /* The left part of the FROM clause already seen */
  Token *pTable,          /* Name of the table to add to the FROM clause */
  Token *pDatabase,       /* Name of the database containing pTable */
  Token *pAlias,          /* The right-hand side of the AS subexpression */
  Select *pSubquery,      /* A subquery used in place of a table name */
  Expr *pOn,              /* The ON clause of a join */
  IdList *pUsing          /* The USING clause of a join */
){
  SrcListItem *pItem;
  sqlite4 *db = pParse->db;
  if( !p && (pOn || pUsing) ){
    sqlite4ErrorMsg(pParse, "a JOIN clause is required before %s", 
      (pOn ? "ON" : "USING")
    );
    goto append_from_error;
  }
  p = sqlite4SrcListAppend(db, p, pTable, pDatabase);
  if( p==0 || NEVER(p->nSrc==0) ){
    goto append_from_error;
  }
  pItem = &p->a[p->nSrc-1];
  assert( pAlias!=0 );
  if( pAlias->n ){
    pItem->zAlias = sqlite4NameFromToken(db, pAlias);
  }
  pItem->pSelect = pSubquery;
  pItem->pOn = pOn;
  pItem->pUsing = pUsing;
  return p;

 append_from_error:
  assert( p==0 );
  sqlite4ExprDelete(db, pOn);
  sqlite4IdListDelete(db, pUsing);
  sqlite4SelectDelete(db, pSubquery);
  return 0;
}

/*
** Add an INDEXED BY or NOT INDEXED clause to the most recently added 
** element of the source-list passed as the second argument.
*/
SQLITE4_PRIVATE void sqlite4SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
  assert( pIndexedBy!=0 );
  if( p && ALWAYS(p->nSrc>0) ){
    SrcListItem *pItem = &p->a[p->nSrc-1];
    assert( pItem->notIndexed==0 && pItem->zIndex==0 );
    if( pIndexedBy->n==1 && !pIndexedBy->z ){
      /* A "NOT INDEXED" clause was supplied. See parse.y 
      ** construct "indexed_opt" for details. */
      pItem->notIndexed = 1;
    }else{
      pItem->zIndex = sqlite4NameFromToken(pParse->db, pIndexedBy);
    }
  }
}

/*
** When building up a FROM clause in the parser, the join operator
** is initially attached to the left operand.  But the code generator
** expects the join operator to be on the right operand.  This routine
** Shifts all join operators from left to right for an entire FROM
** clause.
**
** Example: Suppose the join is like this:
**
**           A natural cross join B
**
** The operator is "natural cross join".  The A and B operands are stored
** in p->a[0] and p->a[1], respectively.  The parser initially stores the
** operator with A.  This routine shifts that operator over to B.
*/
SQLITE4_PRIVATE void sqlite4SrcListShiftJoinType(SrcList *p){
  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;
    }
    p->a[0].jointype = 0;
  }
}

/*
** Begin a transaction
*/
SQLITE4_PRIVATE void sqlite4BeginTransaction(Parse *pParse, int type){
  sqlite4 *db;
  Vdbe *v;
  int i;

  assert( pParse!=0 );
  db = pParse->db;
  assert( db!=0 );
  if( sqlite4AuthCheck(pParse, SQLITE4_TRANSACTION, "BEGIN", 0, 0) ){
    return;
  }
  v = sqlite4GetVdbe(pParse);
  if( !v ) return;
  if( type!=TK_DEFERRED ){
    for(i=0; i<db->nDb; i++){
      sqlite4VdbeAddOp2(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
      sqlite4VdbeUsesStorage(v, i);
    }
  }
  sqlite4VdbeAddOp1(v, OP_Savepoint, SAVEPOINT_BEGIN);
}

/*
** Write VDBE code for either a "COMMIT" or "ROLLBACK" statement.
**
** For COMMIT, the second argument should be SAVEPOINT_RELEASE. For a
** ROLLBACK, the second argument to this function should be 
** SAVEPOINT_ROLLBACK.
*/
SQLITE4_PRIVATE void sqlite4EndTransaction(Parse *pParse, int op){
  Vdbe *v;

  /* Invoke the authorization callback */
#ifndef SQLITE4_OMIT_AUTHORIZATION
  const char *azCmd[] = { "COMMIT", "ROLLBACK" };
  assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
  assert( SAVEPOINT_RELEASE==1 && SAVEPOINT_ROLLBACK==2 );
  if( sqlite4AuthCheck(pParse, SQLITE4_TRANSACTION, azCmd[op-1], 0, 0) ) return;
#endif

  /* Code the OP_Savepoint instruction. */
  v = sqlite4GetVdbe(pParse);
  if( v ) sqlite4VdbeAddOp1(v, OP_Savepoint, op);
}

/*
** This function is called by the parser when it parses a command to create,
** release or rollback an SQL savepoint. 
*/
SQLITE4_PRIVATE void sqlite4Savepoint(Parse *pParse, int op, Token *pName){
  char *zName = sqlite4NameFromToken(pParse->db, pName);
  if( zName ){
    Vdbe *v = sqlite4GetVdbe(pParse);
#ifndef SQLITE4_OMIT_AUTHORIZATION
    static const char * const az[] = { "BEGIN", "RELEASE", "ROLLBACK" };
    assert( !SAVEPOINT_BEGIN && SAVEPOINT_RELEASE==1 && SAVEPOINT_ROLLBACK==2 );
#endif
    if( !v || sqlite4AuthCheck(pParse, SQLITE4_SAVEPOINT, az[op], zName, 0) ){
      sqlite4DbFree(pParse->db, zName);
      return;
    }
    sqlite4VdbeAddOp4(v, OP_Savepoint, op, 0, 0, zName, P4_DYNAMIC);
  }
}

/*
** Make sure the TEMP database is open and available for use.  Return
** the number of errors.  Leave any error messages in the pParse structure.
*/
SQLITE4_PRIVATE int sqlite4OpenTempDatabase(Parse *pParse){
  sqlite4 *db = pParse->db;
  if( db->aDb[1].pKV==0 && !pParse->explain ){
    int rc;
    rc = sqlite4KVStoreOpen(db, "temp", ":memory:", &db->aDb[1].pKV,
                            SQLITE4_KVOPEN_TEMPORARY);
    if( rc!=SQLITE4_OK ){
      sqlite4ErrorMsg(pParse, "unable to open a temporary database "
        "file for storing temporary tables");
      pParse->rc = rc;
      return 1;
    }
    assert( db->aDb[1].pSchema );
  }
  return 0;
}

/*
** Generate VDBE code that will verify the schema cookie and start
** a read-transaction for all named database files.
**
** It is important that all schema cookies be verified and all
** read transactions be started before anything else happens in
** the VDBE program.  But this routine can be called after much other
** code has been generated.  So here is what we do:
**
** The first time this routine is called, we code an OP_Goto that
** will jump to a subroutine at the end of the program.  Then we
** record every database that needs its schema verified in the
** pParse->cookieMask field.  Later, after all other code has been
** generated, the subroutine that does the cookie verifications and
** starts the transactions will be coded and the OP_Goto P2 value
** will be made to point to that subroutine.  The generation of the
** cookie verification subroutine code happens in sqlite4FinishCoding().
**
** If iDb<0 then code the OP_Goto only - don't set flag to verify the
** schema on any databases.  This can be used to position the OP_Goto
** early in the code, before we know if any database tables will be used.
*/
SQLITE4_PRIVATE void sqlite4CodeVerifySchema(Parse *pParse, int iDb){
  Parse *pToplevel = sqlite4ParseToplevel(pParse);

  if( pToplevel->cookieGoto==0 ){
    Vdbe *v = sqlite4GetVdbe(pToplevel);
    if( v==0 ) return;  /* This only happens if there was a prior error */
    pToplevel->cookieGoto = sqlite4VdbeAddOp2(v, OP_Goto, 0, 0)+1;
  }
  if( iDb>=0 ){
    sqlite4 *db = pToplevel->db;
    yDbMask mask;

    assert( iDb<db->nDb );
    assert( db->aDb[iDb].pKV!=0 || iDb==1 );
    assert( iDb<SQLITE4_MAX_ATTACHED+2 );
    mask = ((yDbMask)1)<<iDb;
    if( (pToplevel->cookieMask & mask)==0 ){
      pToplevel->cookieMask |= mask;
      pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
      if( !OMIT_TEMPDB && iDb==1 ){
        sqlite4OpenTempDatabase(pToplevel);
      }
    }
  }
}

/*
** If argument zDb is NULL, then call sqlite4CodeVerifySchema() for each 
** attached database. Otherwise, invoke it for the database named zDb only.
*/
SQLITE4_PRIVATE void sqlite4CodeVerifyNamedSchema(Parse *pParse, const char *zDb){
  sqlite4 *db = pParse->db;
  int i;
  for(i=0; i<db->nDb; i++){
    Db *pDb = &db->aDb[i];
    if( pDb->pKV && (!zDb || 0==sqlite4_stricmp(zDb, pDb->zName)) ){
      sqlite4CodeVerifySchema(pParse, i);
    }
  }
}

/*
** Generate VDBE code that prepares for doing an operation that
** might change the database.
**
** This routine starts a new transaction if we are not already within
** a transaction.  If we are already within a transaction, then a checkpoint
** is set if the setStatement parameter is true.  A checkpoint should
** be set for operations that might fail (due to a constraint) part of
** the way through and which will need to undo some writes without having to
** rollback the whole transaction.  For operations where all constraints
** can be checked before any changes are made to the database, it is never
** necessary to undo a write and the checkpoint should not be set.
*/
SQLITE4_PRIVATE void sqlite4BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
  Parse *pToplevel = sqlite4ParseToplevel(pParse);
  sqlite4CodeVerifySchema(pParse, iDb);
  pToplevel->writeMask |= ((yDbMask)1)<<iDb;
  pToplevel->isMultiWrite |= setStatement;
}

/*
** Indicate that the statement currently under construction might write
** more than one entry (example: deleting one row then inserting another,
** inserting multiple rows in a table, or inserting a row and index entries.)
** If an abort occurs after some of these writes have completed, then it will
** be necessary to undo the completed writes.
*/
SQLITE4_PRIVATE void sqlite4MultiWrite(Parse *pParse){
  Parse *pToplevel = sqlite4ParseToplevel(pParse);
  pToplevel->isMultiWrite = 1;
}

/* 
** The code generator calls this routine if is discovers that it is
** possible to abort a statement prior to completion.  In order to 
** perform this abort without corrupting the database, we need to make
** sure that the statement is protected by a statement transaction.
**
** Technically, we only need to set the mayAbort flag if the
** isMultiWrite flag was previously set.  There is a time dependency
** such that the abort must occur after the multiwrite.  This makes
** some statements involving the REPLACE conflict resolution algorithm
** go a little faster.  But taking advantage of this time dependency
** makes it more difficult to prove that the code is correct (in 
** particular, it prevents us from writing an effective
** implementation of sqlite4AssertMayAbort()) and so we have chosen
** to take the safe route and skip the optimization.
*/
SQLITE4_PRIVATE void sqlite4MayAbort(Parse *pParse){
  Parse *pToplevel = sqlite4ParseToplevel(pParse);
  pToplevel->mayAbort = 1;
}

/*
** Code an OP_Halt that causes the vdbe to return an SQLITE4_CONSTRAINT
** error. The onError parameter determines which (if any) of the statement
** and/or current transaction is rolled back.
*/
SQLITE4_PRIVATE void sqlite4HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){
  Vdbe *v = sqlite4GetVdbe(pParse);
  if( onError==OE_Abort ){
    sqlite4MayAbort(pParse);
  }
  sqlite4VdbeAddOp4(v, OP_Halt, SQLITE4_CONSTRAINT, onError, 0, p4, p4type);
}

/*
** Check to see if pIndex uses the collating sequence pColl.  Return
** true if it does and false if it does not.
*/
#ifndef SQLITE4_OMIT_REINDEX
static int collationMatch(const char *zColl, Index *pIndex){
  int i;
  assert( zColl!=0 );
  for(i=0; i<pIndex->nColumn; i++){
    const char *z = pIndex->azColl[i];
    assert( z!=0 );
    if( 0==sqlite4_stricmp(z, zColl) ){
      return 1;
    }
  }
  return 0;
}
#endif

/*
** Recompute all indices of pTab that use the collating sequence pColl.
** If pColl==0 then recompute all indices of pTab.
*/
#ifndef SQLITE4_OMIT_REINDEX
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
  Index *pIndex;              /* An index associated with pTab */

  for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
    if( pIndex->eIndexType==SQLITE4_INDEX_PRIMARYKEY ) continue;
    if( zColl==0 || collationMatch(zColl, pIndex) ){
      int iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
      sqlite4BeginWriteOperation(pParse, 0, iDb);
      sqlite4RefillIndex(pParse, pIndex, 0);
    }
  }
}
#endif

/*
** Recompute all indices of all tables in all databases where the
** indices use the collating sequence pColl.  If pColl==0 then recompute
** all indices everywhere.
*/
#ifndef SQLITE4_OMIT_REINDEX
static void reindexDatabases(Parse *pParse, char const *zColl){
  Db *pDb;                    /* A single database */
  int iDb;                    /* The database index number */
  sqlite4 *db = pParse->db;   /* The database connection */
  HashElem *k;                /* For looping over tables in pDb */
  Table *pTab;                /* A table in the database */

  for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
    assert( pDb!=0 );
    for(k=sqliteHashFirst(&pDb->pSchema->tblHash);  k; k=sqliteHashNext(k)){
      pTab = (Table*)sqliteHashData(k);
      reindexTable(pParse, pTab, zColl);
    }
  }
}
#endif

/*
** Generate code for the REINDEX command.
**
**        REINDEX                            -- 1
**        REINDEX  <collation>               -- 2
**        REINDEX  ?<database>.?<tablename>  -- 3
**        REINDEX  ?<database>.?<indexname>  -- 4
**
** Form 1 causes all indices in all attached databases to be rebuilt.
** Form 2 rebuilds all indices in all databases that use the named
** collating function.  Forms 3 and 4 rebuild the named index or all
** indices associated with the named table.
*/
#ifndef SQLITE4_OMIT_REINDEX
SQLITE4_PRIVATE void sqlite4Reindex(Parse *pParse, Token *pName1, Token *pName2){
  CollSeq *pColl;             /* Collating sequence to be reindexed, or NULL */
  char *z;                    /* Name of a table or index */
  const char *zDb;            /* Name of the database */
  Table *pTab;                /* A table in the database */
  Index *pIndex;              /* An index associated with pTab */
  int iDb;                    /* The database index number */
  sqlite4 *db = pParse->db;   /* The database connection */
  Token *pObjName;            /* Name of the table or index to be reindexed */

  /* Read the database schema. If an error occurs, leave an error message
  ** and code in pParse and return NULL. */
  if( SQLITE4_OK!=sqlite4ReadSchema(pParse) ){
    return;
  }

  if( pName1==0 ){
    reindexDatabases(pParse, 0);
    return;
  }else if( NEVER(pName2==0) || pName2->z==0 ){
    char *zColl;
    assert( pName1->z );
    zColl = sqlite4NameFromToken(pParse->db, pName1);
    if( !zColl ) return;
    pColl = sqlite4FindCollSeq(db, zColl, 0);
    if( pColl ){
      reindexDatabases(pParse, zColl);
      sqlite4DbFree(db, zColl);
      return;
    }
    sqlite4DbFree(db, zColl);
  }
  iDb = sqlite4TwoPartName(pParse, pName1, pName2, &pObjName);
  if( iDb<0 ) return;
  z = sqlite4NameFromToken(db, pObjName);
  if( z==0 ) return;
  zDb = db->aDb[iDb].zName;
  pTab = sqlite4FindTable(db, z, zDb);
  if( pTab ){
    reindexTable(pParse, pTab, 0);
    sqlite4DbFree(db, z);
    return;
  }
  pIndex = sqlite4FindIndex(db, z, zDb);
  sqlite4DbFree(db, z);
  if( pIndex && pIndex->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){
    sqlite4BeginWriteOperation(pParse, 0, iDb);
    sqlite4RefillIndex(pParse, pIndex, 0);
    return;
  }
  sqlite4ErrorMsg(pParse, "unable to identify the object to be reindexed");
}
#endif

/*
** Return a dynamicly allocated KeyInfo structure that can be used
** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
**
** If successful, a pointer to the new structure is returned. In this case
** the caller is responsible for calling sqlite4DbFree(db, ) on the returned 
** pointer. If an error occurs (out of memory or missing collation 
** sequence), NULL is returned and the state of pParse updated to reflect
** the error.
*/
SQLITE4_PRIVATE KeyInfo *sqlite4IndexKeyinfo(Parse *pParse, Index *pIdx){
  Index *pPk;                     /* Primary key index on same table */
  int i;
  int nCol;
  int nBytes;
  sqlite4 *db = pParse->db;
  KeyInfo *pKey;

  if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY
   || pIdx->eIndexType==SQLITE4_INDEX_TEMP
  ){
    pPk = 0;
  }else{
    pPk = sqlite4FindPrimaryKey(pIdx->pTable, 0);
  }
  nCol = pIdx->nColumn + (pPk ? pPk->nColumn : 0);

  nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
  pKey = (KeyInfo *)sqlite4DbMallocZero(db, nBytes);
  if( pKey ){
    pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
    assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) );

    for(i=0; i<pIdx->nColumn; i++){
      char *zColl = pIdx->azColl[i];
      assert( zColl );
      pKey->aColl[i] = sqlite4LocateCollSeq(pParse, zColl);
      pKey->aSortOrder[i] = pIdx->aSortOrder[i];
    }
    if( pPk ){
      for(i=0; i<pPk->nColumn; i++){
        char *zColl = pPk->azColl[i];
        assert( zColl );
        pKey->aColl[i+pIdx->nColumn] = sqlite4LocateCollSeq(pParse, zColl);
        pKey->aSortOrder[i+pIdx->nColumn] = pPk->aSortOrder[i];
      }
    }

    pKey->nField = (u16)nCol;
    if( pPk ){
      pKey->nPK = pPk->nColumn;
    }else{
      pKey->nData = pIdx->pTable->nCol;
    }
  }

  if( pParse->nErr ){
    sqlite4DbFree(db, pKey);
    pKey = 0;
  }
  return pKey;
}

/************** End of build.c ***********************************************/
/************** Begin file callback.c ****************************************/
/*
** 2005 May 23 
**
** 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 functions used to access the internal hash tables
** of user defined functions and collation sequences.
*/


/*
** Invoke the 'collation needed' callback to request a collation sequence
** in the encoding enc of name zName, length nName.
*/
static void callCollNeeded(sqlite4 *db, const char *zName){
  if( db->xCollNeeded ){
    char *zExternal = sqlite4DbStrDup(db, zName);
    if( !zExternal ) return;
    db->xCollNeeded(db->pCollNeededArg, db, zExternal);
    sqlite4DbFree(db, zExternal);
  }
}

/*
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the desired encoding.
** 
** If it is not NULL, then pColl must point to the database native encoding 
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
** sequence can be found.
**
** See also: sqlite4LocateCollSeq(), sqlite4FindCollSeq()
*/
SQLITE4_PRIVATE CollSeq *sqlite4GetCollSeq(
  sqlite4* db,          /* The database connection */
  CollSeq *pColl,       /* Collating sequence object, or NULL */
  const char *zName     /* Collating sequence name */
){
  CollSeq *p;

  p = pColl;
  if( !p ){
    p = sqlite4FindCollSeq(db, zName, 0);
  }
  if( !p || !p->xCmp ){
    /* No collation sequence of this type for this encoding is registered.
    ** Call the collation factory to see if it can supply us with one. */
    callCollNeeded(db, zName);
    p = sqlite4FindCollSeq(db, zName, 0);
  }
  if( p && !p->xCmp ) p = 0;

  assert( !p || p->xCmp );
  return p;
}

/*
** This routine is called on a collation sequence before it is used to
** check that it is defined. An undefined collation sequence exists when
** a database is loaded that contains references to collation sequences
** that have not been defined by sqlite4_create_collation() etc.
**
** If required, this routine calls the 'collation needed' callback to
** request a definition of the collating sequence. If this doesn't work, 
** an equivalent collating sequence that uses a text encoding different
** from the main database is substituted, if one is available.
*/
SQLITE4_PRIVATE int sqlite4CheckCollSeq(Parse *pParse, CollSeq *pColl){
  if( pColl ){
    const char *zName = pColl->zName;
    sqlite4 *db = pParse->db;
    CollSeq *p = sqlite4GetCollSeq(db, pColl, zName);
    if( !p ){
      sqlite4ErrorMsg(pParse, "no such collation sequence: %s", zName);
      pParse->nErr++;
      return SQLITE4_ERROR;
    }
    assert( p==pColl );
  }
  return SQLITE4_OK;
}



/*
** Locate and return an entry from the db.aCollSeq hash table. If the entry
** specified by zName and nName is not found and parameter 'create' is
** true, then create a new entry. Otherwise return NULL.
**
** Stored immediately after the CollSeq object in memory is a copy of
** the collation sequence name. A pointer to this string is stored in
** CollSeq.zName.
*/
static CollSeq *findCollSeqEntry(
  sqlite4 *db,          /* Database connection */
  const char *zName,    /* Name of the collating sequence */
  int create            /* Create a new entry if true */
){
  CollSeq *pColl;
  int nName = sqlite4Strlen30(zName);
  pColl = sqlite4HashFind(&db->aCollSeq, zName, nName);

  if( 0==pColl && create ){
    CollSeq *pDel;

    pColl = (CollSeq*)sqlite4DbMallocZero(db, sizeof(CollSeq)+nName+1);
    if( pColl ){
      pColl->zName = (char *)&pColl[1];
      memcpy(pColl->zName, zName, nName);
    }
      
    /* If a malloc() failure occurs in sqlite4HashInsert(), a copy of 
    ** pColl is returned. Free it if this happens. */
    pDel = sqlite4HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
    assert( pDel==0 || pDel==pColl );
    if( pDel!=0 ){
      db->mallocFailed = 1;
      sqlite4DbFree(db, pDel);
      pColl = 0;
    }
  }

  return pColl;
}

/*
** Parameter zName points to a UTF-8 encoded string nName bytes long.
** Return the CollSeq* pointer for the collation sequence named zName.
**
** If the entry specified is not found and 'create' is true, then create a
** new entry.  Otherwise return NULL.
**
** A separate function sqlite4LocateCollSeq() is a wrapper around
** this routine.  sqlite4LocateCollSeq() invokes the collation factory
** if necessary and generates an error message if the collating sequence
** cannot be found.
**
** See also: sqlite4LocateCollSeq(), sqlite4GetCollSeq()
*/
SQLITE4_PRIVATE CollSeq *sqlite4FindCollSeq(
  sqlite4 *db,
  const char *zName,
  int create
){
  CollSeq *pColl;
  if( zName ){
    pColl = findCollSeqEntry(db, zName, create);
  }else{
    pColl = db->pDfltColl;
  }
  return pColl;
}

/* During the search for the best function definition, this procedure
** is called to test how well the function passed as the first argument
** matches the request for a function with nArg arguments in a system
** that uses encoding enc. The value returned indicates how well the
** request is matched. A higher value indicates a better match.
**
** The returned value is as follows:
**
** 0: Not a match, or nArg<0 and the function has no implementation.
** 1: A variable arguments function.
** 2: An exact match.
*/
static int matchQuality(FuncDef *p, int nArg){
  if( nArg<0 && (p->xFunc || p->xStep) ) return 2;
  if( p->nArg==nArg ) return 2;
  if( p->nArg<0 ) return 1;
  return 0;
}

/*
** Search a FuncDefTable for a function with the given name.  Return
** a pointer to the matching FuncDef if found, or 0 if there is no match.
*/
static FuncDef *functionSearch(
  FuncDefTable *pFuncTab,  /* Lookup table to search */
  const char *zFunc,       /* Name of function */
  int nFunc                /* Number of bytes in zFunc */
){
  FuncDef *p;
  if( nFunc<0 ) nFunc = sqlite4Strlen30(zFunc);
  for(p=pFuncTab->pFirst; p; p=p->pNextName){
    if( sqlite4_strnicmp(p->zName, zFunc, nFunc)==0 && p->zName[nFunc]==0 ){
      return p;
    }
  }
  return 0;
}

/*
** Insert a new FuncDef into a FuncDefTable.
**
** The pDef is private to a single database connection if isBuiltIn==0 but
** is a global public function if isBuiltIn==1.  In the case of isBuiltIn==1,
** any changes to pDef are made in a way that is threadsafe, so that if two
** threads attempt to build the global function table at the same time, the
** trailing thread will perform harmless no-op assignments.
*/
SQLITE4_PRIVATE void sqlite4FuncDefInsert(
  FuncDefTable *pFuncTab,  /* The lookup table into which to insert */
  FuncDef *pDef,           /* The function definition to insert */
  int isBuiltIn            /* True if pDef is one of the built-in functions */
){
  FuncDef *pOther;
  assert( pDef->pSameName==0 || isBuiltIn );
  assert( pDef->pNextName==0 || isBuiltIn );
  if( pFuncTab->pFirst==0 ){
    pFuncTab->pFirst = pDef;
    pFuncTab->pLast = pDef;
    pFuncTab->pSame = pDef;
  }else if( isBuiltIn
            && sqlite4_stricmp(pDef->zName, pFuncTab->pLast->zName)==0 ){
    assert( pFuncTab->pSame->pSameName==0 || pFuncTab->pSame->pSameName==pDef );
    pFuncTab->pSame->pSameName = pDef;
    pFuncTab->pSame = pDef;
  }else if( !isBuiltIn && (pOther=functionSearch(pFuncTab,pDef->zName,-1))!=0 ){
    pDef->pSameName = pOther->pSameName;
    pOther->pSameName = pDef;
  }else{
    assert( pFuncTab->pLast->pNextName==0 || pFuncTab->pLast->pNextName==pDef );
    pFuncTab->pLast->pNextName = pDef;
    pFuncTab->pLast = pDef;
    pFuncTab->pSame = pDef;
  }
}
  
  

/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8.  Return a
** pointer to the FuncDef structure that defines that function, or return
** NULL if the function does not exist.
**
** If the createFlag argument is true, then a new (zeroed) FuncDef
** structure is created and linked into the "db" structure if a
** no matching function previously existed.  When createFlag is true
** and the nArg parameter is -1, then only a function that accepts
** any number of arguments will be returned.
**
** If createFlag is false and nArg is -1, then the first valid
** function found is returned.  A function is valid if either xFunc
** or xStep is non-zero.
**
** If createFlag is false, then a function with the required name and
** number of arguments may be returned even if the eTextRep flag does not
** match that requested.
*/
SQLITE4_PRIVATE FuncDef *sqlite4FindFunction(
  sqlite4 *db,       /* An open database */
  const char *zName, /* Name of the function.  Not null-terminated */
  int nName,         /* Number of characters in the name */
  int nArg,          /* Number of arguments.  -1 means any number */
  int createFlag     /* Create new entry if true and does not otherwise exist */
){
  FuncDef *p;         /* Iterator variable */
  FuncDef *pBest = 0; /* Best match found so far */
  int bestScore = 0;  /* Score of best match */

  /* First search for a match amongst the application-defined functions.
  */
  p = functionSearch(&db->aFunc, zName, nName);
  while( p ){
    int score = matchQuality(p, nArg);
    if( score>bestScore ){
      pBest = p;
      bestScore = score;
    }
    p = p->pSameName;
  }

  /* If no match is found, search the built-in functions.
  **
  ** If the SQLITE4_PreferBuiltin flag is set, then search the built-in
  ** functions even if a prior app-defined function was found.  And give
  ** priority to built-in functions.
  **
  ** Except, if createFlag is true, that means that we are trying to
  ** install a new function.  Whatever FuncDef structure is returned it will
  ** have fields overwritten with new information appropriate for the
  ** new function.  But the FuncDefs for built-in functions are read-only.
  ** So we must not search for built-ins when creating a new function.
  */ 
  if( !createFlag && (pBest==0 || (db->flags & SQLITE4_PreferBuiltin)!=0) ){
    FuncDefTable *pFuncTab = &db->pEnv->aGlobalFuncs;
    bestScore = 0;
    p = functionSearch(pFuncTab, zName, nName);
    while( p ){
      int score = matchQuality(p, nArg);
      if( score>bestScore ){
        pBest = p;
        bestScore = score;
      }
      p = p->pSameName;
    }
  }

  /* If the createFlag parameter is true and the search did not reveal an
  ** exact match for the name, number of arguments and encoding, then add a
  ** new entry to the hash table and return it.
  */
  if( createFlag && (bestScore<2 || pBest->nArg!=nArg) && 
      (pBest = sqlite4DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
    pBest->zName = (char *)&pBest[1];
    pBest->nArg = (u16)nArg;
    memcpy(pBest->zName, zName, nName);
    pBest->zName[nName] = 0;
    sqlite4FuncDefInsert(&db->aFunc, pBest, 0);
  }

  if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
    return pBest;
  }
  return 0;
}

/*
** Free all resources held by the schema structure. The void* argument points
** at a Schema struct. This function does not call sqlite4DbFree(db, ) on the 
** pointer itself, it just cleans up subsidiary resources (i.e. the contents
** of the schema hash tables).
**
** The Schema.cache_size variable is not cleared.
*/
SQLITE4_PRIVATE void sqlite4SchemaClear(sqlite4_env *pEnv, Schema *pSchema){
  Hash temp1;
  Hash temp2;
  HashElem *pElem;

  temp1 = pSchema->tblHash;
  temp2 = pSchema->trigHash;
  sqlite4HashInit(pEnv, &pSchema->trigHash, 0);
  sqlite4HashClear(&pSchema->idxHash);
  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    sqlite4DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
  }
  sqlite4HashClear(&temp2);
  sqlite4HashInit(pEnv, &pSchema->tblHash, 0);
  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    sqlite4DeleteTable(0, pTab);
  }
  sqlite4HashClear(&temp1);
  sqlite4HashClear(&pSchema->fkeyHash);
  pSchema->pSeqTab = 0;
  if( pSchema->flags & DB_SchemaLoaded ){
    pSchema->iGeneration++;
    pSchema->flags &= ~DB_SchemaLoaded;
  }
}

/*
** Find and return the schema associated with a BTree.  Create
** a new one if necessary.
*/
SQLITE4_PRIVATE Schema *sqlite4SchemaGet(sqlite4 *db){
  Schema * p;
  p = (Schema *)sqlite4DbMallocZero(0, sizeof(Schema));
  if( !p ){
    db->mallocFailed = 1;
  }else if ( 0==p->file_format ){
    sqlite4HashInit(db->pEnv, &p->tblHash, 0);
    sqlite4HashInit(db->pEnv, &p->idxHash, 0);
    sqlite4HashInit(db->pEnv, &p->trigHash, 0);
    sqlite4HashInit(db->pEnv, &p->fkeyHash, 0);
    p->enc = SQLITE4_UTF8;
  }
  return p;
}

/************** End of callback.c ********************************************/
/************** Begin file delete.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
*/

/*
** While a SrcList can in general represent multiple tables and subqueries
** (as in the FROM clause of a SELECT statement) in this case it contains
** the name of a single table, as one might find in an INSERT, DELETE,
** or UPDATE statement.  Look up that table in the symbol table and
** return a pointer.  Set an error message and return NULL if the table 
** name is not found or if any other error occurs.
**
** The following fields are initialized appropriate in pSrc:
**
**    pSrc->a[0].pTab       Pointer to the Table object
**    pSrc->a[0].pIndex     Pointer to the INDEXED BY index, if there is one
*/
SQLITE4_PRIVATE Table *sqlite4SrcListLookup(Parse *pParse, SrcList *pSrc){
  SrcListItem *pItem = pSrc->a;
  Table *pTab;
  assert( pItem && pSrc->nSrc==1 );
  pTab = sqlite4LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
  sqlite4DeleteTable(pParse->db, pItem->pTab);
  pItem->pTab = pTab;
  if( pTab ){
    pTab->nRef++;
  }
  if( sqlite4IndexedByLookup(pParse, pItem) ){
    pTab = 0;
  }
  return pTab;
}

/*
** Check to make sure the given table is writable.  If it is not
** writable, generate an error message and return 1.  If it is
** writable return 0;
*/
SQLITE4_PRIVATE int sqlite4IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
  /* A table is not writable under the following circumstances:
  **
  **   1) It is a virtual table and no implementation of the xUpdate method
  **      has been provided, or
  **   2) It is a system table (i.e. sqlite_master), this call is not
  **      part of a nested parse and writable_schema pragma has not 
  **      been specified.
  **
  ** In either case leave an error message in pParse and return non-zero.
  */
  if( ( IsVirtual(pTab) 
     && sqlite4GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
   || ( (pTab->tabFlags & TF_Readonly)!=0
     && (pParse->db->flags & SQLITE4_WriteSchema)==0
     && pParse->nested==0 )
  ){
    sqlite4ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
    return 1;
  }

#ifndef SQLITE4_OMIT_VIEW
  if( !viewOk && pTab->pSelect ){
    sqlite4ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
    return 1;
  }
#endif
  return 0;
}


#if !defined(SQLITE4_OMIT_VIEW) && !defined(SQLITE4_OMIT_TRIGGER)
/*
** Evaluate a view and store its result in an ephemeral table.  The
** pWhere argument is an optional WHERE clause that restricts the
** set of rows in the view that are to be added to the ephemeral table.
*/
SQLITE4_PRIVATE void sqlite4MaterializeView(
  Parse *pParse,       /* Parsing context */
  Table *pView,        /* View definition */
  Expr *pWhere,        /* Optional WHERE clause to be added */
  int iCur             /* Cursor number for ephemerial table */
){
  SelectDest dest;
  Select *pDup;
  sqlite4 *db = pParse->db;

  pDup = sqlite4SelectDup(db, pView->pSelect, 0);
  if( pWhere ){
    SrcList *pFrom;
    
    pWhere = sqlite4ExprDup(db, pWhere, 0);
    pFrom = sqlite4SrcListAppend(db, 0, 0, 0);
    if( pFrom ){
      assert( pFrom->nSrc==1 );
      pFrom->a[0].zAlias = sqlite4DbStrDup(db, pView->zName);
      pFrom->a[0].pSelect = pDup;
      assert( pFrom->a[0].pOn==0 );
      assert( pFrom->a[0].pUsing==0 );
    }else{
      sqlite4SelectDelete(db, pDup);
    }
    pDup = sqlite4SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
  }
  sqlite4SelectDestInit(&dest, SRT_EphemTab, iCur);
  sqlite4Select(pParse, pDup, &dest);
  sqlite4SelectDelete(db, pDup);
}
#endif /* !defined(SQLITE4_OMIT_VIEW) && !defined(SQLITE4_OMIT_TRIGGER) */

#if defined(SQLITE4_ENABLE_UPDATE_DELETE_LIMIT) \
 && !defined(SQLITE4_OMIT_SUBQUERY)
/*
** Generate an expression tree to implement the WHERE, ORDER BY,
** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
**
**     DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
**                            \__________________________/
**                               pLimitWhere (pInClause)
*/
SQLITE4_PRIVATE Expr *sqlite4LimitWhere(
  Parse *pParse,            /* The parser context */
  SrcList *pSrc,            /* the FROM clause -- which tables to scan */
  Expr *pWhere,             /* The WHERE clause.  May be null */
  ExprList *pOrderBy,       /* The ORDER BY clause.  May be null */
  Expr *pLimit,             /* The LIMIT clause.  May be null */
  Expr *pOffset,            /* The OFFSET clause.  May be null */
  char *zStmtType           /* Either DELETE or UPDATE. For error messages. */
){
  Expr *pWhereRowid = NULL; /* WHERE rowid .. */
  Expr *pInClause = NULL;   /* WHERE rowid IN ( select ) */
  Expr *pSelectRowid = NULL;/* SELECT rowid ... */
  ExprList *pEList = NULL;  /* Expression list contaning only pSelectRowid */
  SrcList *pSelectSrc = NULL;/* SELECT rowid FROM x ... (dup of pSrc) */
  Select *pSelect = NULL;   /* Complete SELECT tree */

  /* Check that there isn't an ORDER BY without a LIMIT clause.
  */
  if( pOrderBy && (pLimit == 0) ) {
    sqlite4ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
    goto limit_where_cleanup_2;
  }

  /* We only need to generate a select expression if there
  ** is a limit/offset term to enforce.
  */
  if( pLimit == 0 ) {
    /* if pLimit is null, pOffset will always be null as well. */
    assert( pOffset == 0 );
    return pWhere;
  }

  /* Generate a select expression tree to enforce the limit/offset 
  ** term for the DELETE or UPDATE statement.  For example:
  **   DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
  ** becomes:
  **   DELETE FROM table_a WHERE rowid IN ( 
  **     SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
  **   );
  */

  pSelectRowid = sqlite4PExpr(pParse, TK_ROW, 0, 0, 0);
  if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
  pEList = sqlite4ExprListAppend(pParse, 0, pSelectRowid);
  if( pEList == 0 ) goto limit_where_cleanup_2;

  /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
  ** and the SELECT subtree. */
  pSelectSrc = sqlite4SrcListDup(pParse->db, pSrc, 0);
  if( pSelectSrc == 0 ) {
    sqlite4ExprListDelete(pParse->db, pEList);
    goto limit_where_cleanup_2;
  }

  /* generate the SELECT expression tree. */
  pSelect = sqlite4SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,
                             pOrderBy,0,pLimit,pOffset);
  if( pSelect == 0 ) return 0;

  /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
  pWhereRowid = sqlite4PExpr(pParse, TK_ROW, 0, 0, 0);
  if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
  pInClause = sqlite4PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
  if( pInClause == 0 ) goto limit_where_cleanup_1;

  pInClause->x.pSelect = pSelect;
  pInClause->flags |= EP_xIsSelect;
  sqlite4ExprSetHeight(pParse, pInClause);
  return pInClause;

  /* something went wrong. clean up anything allocated. */
limit_where_cleanup_1:
  sqlite4SelectDelete(pParse->db, pSelect);
  return 0;

limit_where_cleanup_2:
  sqlite4ExprDelete(pParse->db, pWhere);
  sqlite4ExprListDelete(pParse->db, pOrderBy);
  sqlite4ExprDelete(pParse->db, pLimit);
  sqlite4ExprDelete(pParse->db, pOffset);
  return 0;
}
#endif /* defined(SQLITE4_ENABLE_UPDATE_DELETE_LIMIT) */
       /* && !defined(SQLITE4_OMIT_SUBQUERY) */

/*
** Generate code for a DELETE FROM statement.
**
**     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
**                 \________/       \________________/
**                  pTabList              pWhere
*/
SQLITE4_PRIVATE void sqlite4DeleteFrom(
  Parse *pParse,         /* The parser context */
  SrcList *pTabList,     /* The table from which we should delete things */
  Expr *pWhere           /* The WHERE clause.  May be null */
){
  sqlite4 *db = pParse->db;       /* Main database structure */
  Vdbe *v;                        /* The virtual database engine */
  Table *pTab;                    /* Table to delete from */
  const char *zDb;                /* Name of database holding pTab */
  AuthContext sContext;           /* Authorization context */
  NameContext sNC;                /* Name context to resolve WHERE expression */
  int iDb;                        /* Database number */
  int rcauth;                     /* Value returned by authorization callback */
  int iCur;                       /* Cursor number used by where.c */
  Trigger *pTrigger;              /* List of triggers, or NULL */

  memset(&sContext, 0, sizeof(sContext));
  memset(&sNC, 0, sizeof(sNC));

  db = pParse->db;
  if( pParse->nErr || db->mallocFailed ){
    goto delete_from_cleanup;
  }
  assert( pTabList->nSrc==1 );

  /* Locate the table to delete records from. If it is a view, make sure
  ** that the column names are initialized.  */
  pTab = sqlite4SrcListLookup(pParse, pTabList);
  if( pTab==0 || sqlite4ViewGetColumnNames(pParse, pTab) ){
    goto delete_from_cleanup;
  }
  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  zDb = db->aDb[iDb].zName;

  /* Figure out if there are any triggers */
  pTrigger = sqlite4TriggersExist(pParse, pTab, TK_DELETE, 0, 0);

  /* Check the table is not read-only. A table is read-only if it is one
  ** of the built-in system tables (e.g. sqlite_master, sqlite_stat) or
  ** if it is a view and there are no INSTEAD OF triggers to handle the 
  ** delete.  */
  if( sqlite4IsReadOnly(pParse, pTab, pTrigger!=0) ) goto delete_from_cleanup;
  assert( !IsView(pTab) || pTrigger );
  assert( !IsView(pTab) || pTab->pIndex==0 );

  /* Invoke the authorization callback */
  rcauth = sqlite4AuthCheck(pParse, SQLITE4_DELETE, pTab->zName, 0, zDb);
  assert( rcauth==SQLITE4_OK || rcauth==SQLITE4_DENY
         || rcauth==SQLITE4_IGNORE );
  if( rcauth==SQLITE4_DENY ){
    goto delete_from_cleanup;
  }

  /* Assign a cursor number to the table or view this statement is 
  ** deleting from. If pTab is actually a view, this will be used as the
  ** ephemeral table cursor. 
  **
  ** Or, if this is a real table, it is the number of a read-only cursor 
  ** used by where.c to iterate through those records that match the WHERE 
  ** clause supplied by the user. This is a separate cursor from the array
  ** of read-write cursors used to delete entries from each of the tables
  ** indexes.  */
  pTabList->a[0].iCursor = iCur = pParse->nTab++;

  /* Begin generating code */
  v = sqlite4GetVdbe(pParse);
  if( v==0 ) goto delete_from_cleanup;
  if( pParse->nested==0 ) sqlite4VdbeCountChanges(v);
  sqlite4BeginWriteOperation(pParse, 1, iDb);

  /* If we are trying to delete from a view, realize that view into
  ** a ephemeral table.  */
  if( IsView(pTab) ){
    sqlite4AuthContextPush(pParse, &sContext, pTab->zName);
    sqlite4MaterializeView(pParse, pTab, pWhere, iCur);
  }

  /* Resolve the column names in the WHERE clause. This has to come after
  ** the call to sqlite4MaterializeView() above.  */
  sNC.pParse = pParse;
  sNC.pSrcList = pTabList;
  if( sqlite4ResolveExprNames(&sNC, pWhere) ){
    goto delete_from_cleanup;
  }

#ifndef SQLITE4_OMIT_TRUNCATE_OPTIMIZATION
  /* Special case: A DELETE without a WHERE clause deletes everything.
  ** It is easier just to erase the whole table. Prior to version 3.6.5,
  ** this optimization caused the row change count (the value returned by 
  ** API function sqlite4_count_changes) to be set incorrectly.  */
  if( rcauth==SQLITE4_OK && pWhere==0 && !pTrigger && !IsVirtual(pTab) 
   && 0==sqlite4FkRequired(pParse, pTab, 0)
   && !IsKvstore(pTab)
  ){
    Index *pIdx;                  /* For looping over indices of the table */
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->pSchema==pTab->pSchema );
      sqlite4VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
      if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){
        sqlite4VdbeChangeP5(v, OPFLAG_NCHANGE);
      }
    }
  }else
#endif /* SQLITE4_OMIT_TRUNCATE_OPTIMIZATION */
  /* The usual case: There is a WHERE clause so we have to scan through
  ** the table and pick which records to delete.
  */
  {
    WhereInfo *pWInfo;            /* Information about the WHERE clause */
    int baseCur = 0;
    int regSet = ++pParse->nMem;  /* Register for rowset of rows to delete */
    int regKey = ++pParse->nMem;  /* Used for storing row keys */
    int addrTop;                  /* Instruction (RowSetRead) at top of loop */

    /* Query the table for all rows that match the WHERE clause. Store the
    ** PRIMARY KEY for each matching row in the RowSet object in register
    ** regSet. After the scan is complete, the VM will loop through the set 
    ** of keys in the RowSet and delete each row. Rows must be deleted after 
    ** the scan is complete because deleting an item can change the scan 
    ** order.  */
    sqlite4VdbeAddOp2(v, OP_Null, 0, regSet);
    VdbeComment((v, "initialize RowSet"));
    pWInfo = sqlite4WhereBegin(
        pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
    );
    if( pWInfo==0 ) goto delete_from_cleanup;
    sqlite4VdbeAddOp2(v, OP_RowKey, iCur, regKey);
    sqlite4VdbeAddOp3(v, OP_RowSetAdd, regSet, 0, regKey);
    sqlite4WhereEnd(pWInfo);

    /* Unless this is a view, open cursors for all indexes on the table
    ** from which we are deleting.  */
    if( !IsView(pTab) ){
      baseCur = pParse->nTab;
      sqlite4OpenAllIndexes(pParse, pTab, baseCur, OP_OpenWrite);
    }

    addrTop = sqlite4VdbeAddOp3(v, OP_RowSetRead, regSet, 0, regKey);

    /* Delete the row */
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      const char *pVTab = (const char *)sqlite4GetVTable(db, pTab);
      sqlite4VtabMakeWritable(pParse, pTab);
      sqlite4VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
      sqlite4VdbeChangeP5(v, OE_Abort);
      sqlite4MayAbort(pParse);
    }else
#endif
    {
      sqlite4GenerateRowDelete(
          pParse, pTab, baseCur, regKey, pParse->nested==0, pTrigger, OE_Default
      );
    }

    /* End of the delete loop */
    sqlite4VdbeAddOp2(v, OP_Goto, 0, addrTop);
    sqlite4VdbeJumpHere(v, addrTop);

    /* Close all open cursors */
    sqlite4CloseAllIndexes(pParse, pTab, baseCur);
  }

delete_from_cleanup:
  sqlite4AuthContextPop(&sContext);
  sqlite4SrcListDelete(db, pTabList);
  sqlite4ExprDelete(db, pWhere);
  return;
}

/*
** This routine generates VDBE code that causes a single row of a
** single table to be deleted.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
**
**   1.  A read/write cursor pointing to pTab, the table containing the row
**       to be deleted, must be opened as cursor number $iCur.
**
**   2.  Read/write cursors for all indices of pTab must be open as
**       cursor number base+i for the i-th index.
**
**   3.  The record number of the row to be deleted must be stored in
**       memory cell iRowid.
**
** This routine generates code to remove both the table record and all 
** index entries that point to that record.
*/
SQLITE4_PRIVATE void sqlite4GenerateRowDelete(
  Parse *pParse,                  /* Parsing context */
  Table *pTab,                    /* Table containing the row to be deleted */
  int baseCur,                    /* Base cursor number */
  int regKey,                     /* Register containing PK of row to delete */
  int bCount,                     /* True to increment the row change counter */
  Trigger *pTrigger,              /* List of triggers to (potentially) fire */
  int onconf                      /* Default ON CONFLICT policy for triggers */
){
  Vdbe *v = pParse->pVdbe;        /* Vdbe */
  int regOld = 0;                 /* First register in OLD.* array */
  int iLabel;                     /* Label resolved to end of generated code */
  int iPk;                        /* Offset of PK cursor in cursor array */
  int iPkCsr;                     /* Primary key cursor number */
  Index *pPk;                     /* Primary key index */

  /* Vdbe is guaranteed to have been allocated by this stage. */
  assert( v );

  pPk = sqlite4FindPrimaryKey(pTab, &iPk);
  iPkCsr = baseCur + iPk;

  /* Seek the PK cursor to the row to delete. If this row no longer exists 
  ** (this can happen if a trigger program has already deleted it), do
  ** not attempt to delete it or fire any DELETE triggers.  */
  iLabel = sqlite4VdbeMakeLabel(v);
  sqlite4VdbeAddOp4Int(v, OP_NotFound, iPkCsr, iLabel, regKey, 0);
 
  /* If there are any triggers to fire, allocate a range of registers to
  ** use for the old.* references in the triggers.  */
  if( sqlite4FkRequired(pParse, pTab, 0) || pTrigger ){
    u32 mask;                     /* Mask of OLD.* columns in use */
    int iCol;                     /* Iterator used while populating OLD.* */

    /* Determine which table columns may be required by either foreign key
    ** logic or triggers. This block sets stack variable mask to a 32-bit mask
    ** where bit 0 corresponds to the left-most table column, bit 1 to the
    ** second left-most, and so on. If an OLD.* column may be required, then
    ** the corresponding bit is set.
    **
    ** Or, if the table contains more than 32 columns and at least one of
    ** the columns following the 32nd is required, set mask to 0xffffffff.  */
    mask = sqlite4TriggerColmask(
        pParse, pTrigger, 0, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onconf
    );
    mask |= sqlite4FkOldmask(pParse, pTab);

    /* Allocate an array of (nCol+1) registers, where nCol is the number
    ** of columns in the table. 
    **
    ** If the table has an implicit PK, the first register in the array 
    ** contains the rowid. Otherwise, its contents are undefined. The 
    ** remaining registers contain the OLD.* column values, in order. */
    regOld = pParse->nMem+1;
    pParse->nMem += (pTab->nCol+1);
    for(iCol=0; iCol<pTab->nCol; iCol++){
      if( mask==0xffffffff || mask&(1<<iCol) ){
        sqlite4ExprCodeGetColumnOfTable(v, pTab, iPkCsr, iCol, regOld+iCol+1);
      }
    }
    assert( (pPk==0)==IsView(pTab) );
    if( pPk && pPk->aiColumn[0]<0 ){
      sqlite4VdbeAddOp2(v, OP_Rowid, iPkCsr, regOld);
    }

    /* Invoke BEFORE DELETE trigger programs. */
    sqlite4CodeRowTrigger(pParse, pTrigger, 
        TK_DELETE, 0, TRIGGER_BEFORE, pTab, regOld, onconf, iLabel
    );

    /* Seek the cursor to the row to be deleted again. It may be that
    ** the BEFORE triggers coded above have already removed the row
    ** being deleted. Do not attempt to delete the row a second time, and 
    ** do not fire AFTER triggers.  */
    sqlite4VdbeAddOp4Int(v, OP_NotFound, iPkCsr, iLabel, regKey, 0);

    /* Do FK processing. This call checks that any FK constraints that
    ** refer to this table (i.e. constraints attached to other tables) 
    ** are not violated by deleting this row.  */
    sqlite4FkCheck(pParse, pTab, regOld+1, 0);
  }

  /* Delete the index and table entries. Skip this step if pTab is really
  ** a view (in which case the only effect of the DELETE statement is to
  ** fire the INSTEAD OF triggers).  */ 
  if( !IsView(pTab) ){
    sqlite4GenerateRowIndexDelete(pParse, pTab, bCount, baseCur, 0);
  }

  /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
  ** handle rows (possibly in other tables) that refer via a foreign key
  ** to the row just deleted. This is a no-op if there are no configured
  ** foreign keys that use this table as a parent table.  */ 
  sqlite4FkActions(pParse, pTab, 0, regOld);

  /* Invoke AFTER DELETE trigger programs. */
  sqlite4CodeRowTrigger(pParse, pTrigger, 
      TK_DELETE, 0, TRIGGER_AFTER, pTab, regOld, onconf, iLabel
  );

  /* Jump here if the row had already been deleted before any BEFORE
  ** trigger programs were invoked. Or if a trigger program throws a 
  ** RAISE(IGNORE) exception.  */
  sqlite4VdbeResolveLabel(v, iLabel);
}

/*
** Generate code that will assemble an index key and put it in register
** regOut. The key is for use with index pIdx. 
*/
SQLITE4_PRIVATE void sqlite4EncodeIndexKey(
  Parse *pParse,                  /* Parse context */
  Index *pPk,                     /* Primary key index (or NULL) */ 
  int iPkCsr,                     /* Cursor open on primary key */
  Index *pIdx, int iIdxCsr,       /* Index and cursor to create a key for */
  int bAddSeq,                    /* True to append a sequence number */
  int regOut                      /* Output register */
){
  Vdbe *v = pParse->pVdbe;        /* VM to write code to */
  int nTmpReg;                    /* Number of temp registers required */
  int regTmp;                     /* First register in temp array */
  int i;                          /* Iterator variable */
  int nPkCol;                     /* Number of columns to copy from PK */
 
  /* Allocate temp registers */
  assert( pIdx!=pPk );
  nPkCol = (pPk ? pPk->nColumn : 0);
  nTmpReg = pIdx->nColumn + nPkCol;
  regTmp = sqlite4GetTempRange(pParse, nTmpReg);

  /* Assemble the values for the key in the array of temp registers */
  for(i=0; i<pIdx->nColumn; i++){
    int regVal = regTmp + i;
    sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, pIdx->aiColumn[i], regVal);
  }
  for(i=0; i<nPkCol; i++){
    int iCol = pPk->aiColumn[i];
    int regVal = pIdx->nColumn + regTmp + i;
    if( iCol<0 ){
      sqlite4VdbeAddOp2(v, OP_Rowid, iPkCsr, regVal);
    }else{
      sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, pPk->aiColumn[i], regVal);
    }
  }

  /* Build the index key. If bAddSeq is true, append a sequence number to 
  ** the end of the key to ensure it is unique.  */
  sqlite4VdbeAddOp4Int(v, OP_MakeKey, regTmp, nTmpReg, regOut, iIdxCsr);
  if( bAddSeq ) sqlite4VdbeChangeP5(v, OPFLAG_SEQCOUNT);

  /* Release temp registers */
  sqlite4ReleaseTempRange(pParse, regTmp, nTmpReg);
}

/*
** This routine generates VDBE code that causes the deletion of all
** index entries associated with a single row of a single table.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
**
**   1.  A read/write cursor pointing to pTab, the table containing the row
**       to be deleted, must be opened as cursor number "iCur".
**
**   2.  Read/write cursors for all indices of pTab must be open as
**       cursor number iCur+i for the i-th index.
**
**   3.  The "iCur" cursor must be pointing to the row that is to be
**       deleted.
*/
SQLITE4_PRIVATE void sqlite4GenerateRowIndexDelete(
  Parse *pParse,                  /* Parsing and code generating context */
  Table *pTab,                    /* Table containing the row to be deleted */
  int bCount,                     /* Non-zero to increment change counter */
  int baseCur,                    /* Cursor number for the table */
  int *aRegIdx                    /* Only delete if (aRegIdx && aRegIdx[i]>0) */
){
  Vdbe *v = pParse->pVdbe;
  Index *pPk;
  int iPk;
  int iPkCsr;
  int i;
  int regKey;
  Index *pIdx;

  regKey = sqlite4GetTempReg(pParse);
  pPk = sqlite4FindPrimaryKey(pTab, &iPk);
  iPkCsr = baseCur+iPk;

  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    if( pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){
      int iCol;
      int iReg = pParse->nMem+1;
      pParse->nMem += (1 + pTab->nCol);
      for(iCol=0; iCol<pTab->nCol; iCol++){
        sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, iCol, iReg+iCol);
      }
      sqlite4VdbeAddOp2(v, OP_RowKey, iPkCsr, iReg+pTab->nCol);
      sqlite4Fts5CodeUpdate(pParse, pIdx, 0, iReg+pTab->nCol, iReg, 1);
    }else if( pIdx!=pPk && (aRegIdx==0 || aRegIdx[i]>0) ){
      int addrNotFound;
      sqlite4EncodeIndexKey(pParse, pPk, baseCur+iPk,pIdx,baseCur+i,0,regKey);
      addrNotFound = sqlite4VdbeAddOp4(v,
          OP_NotFound, baseCur+i, 0, regKey, 0, P4_INT32
      );
      sqlite4VdbeAddOp1(v, OP_Delete, baseCur+i);
      sqlite4VdbeJumpHere(v, addrNotFound);
    }
  }

  sqlite4VdbeAddOp2(v, OP_Delete, baseCur+iPk, (bCount ? OPFLAG_NCHANGE: 0));
  sqlite4ReleaseTempReg(pParse, regKey);
}

/************** End of delete.c **********************************************/
/************** Begin file func.c ********************************************/
/*
** 2002 February 23
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** 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.
*/
static CollSeq *sqlite4GetFuncCollSeq(sqlite4_context *context){
  return context->pColl;
}

/*
** Implementation of the non-aggregate min() and max() functions
*/
static void minmaxFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int i;
  int mask;    /* 0 for min() or 0xffffffff for max() */
  int iBest;
  CollSeq *pColl;

  assert( argc>1 );
  mask = sqlite4_context_appdata(context)==0 ? 0 : -1;
  pColl = sqlite4GetFuncCollSeq(context);
  assert( pColl );
  assert( mask==-1 || mask==0 );
  iBest = 0;
  if( sqlite4_value_type(argv[0])==SQLITE4_NULL ) return;
  for(i=1; i<argc; i++){
    int res, rc;
    if( sqlite4_value_type(argv[i])==SQLITE4_NULL ) return;
    rc = sqlite4MemCompare(argv[iBest], argv[i], pColl, &res);
    if( rc!=SQLITE4_OK ){
      sqlite4_result_error_code(context, rc);
      return;
    }
    if( (res^mask)>=0 ){
      testcase( mask==0 );
      iBest = i;
    }
  }
  sqlite4_result_value(context, argv[iBest]);
}

/*
** Return the type of the argument.
*/
static void typeofFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **argv
){
  const char *z = 0;
  UNUSED_PARAMETER(NotUsed);
  switch( sqlite4_value_type(argv[0]) ){
    case SQLITE4_INTEGER: z = "integer"; break;
    case SQLITE4_TEXT:    z = "text";    break;
    case SQLITE4_FLOAT:   z = "real";    break;
    case SQLITE4_BLOB:    z = "blob";    break;
    default:             z = "null";    break;
  }
  sqlite4_result_text(context, z, -1, SQLITE4_STATIC, 0);
}


/*
** Implementation of the length() function
*/
static void lengthFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  switch( sqlite4_value_type(argv[0]) ){
    case SQLITE4_BLOB: {
      int nBlob;
      sqlite4_value_blob(argv[0], &nBlob);
      sqlite4_result_int(context, nBlob);
      break;
    };

    case SQLITE4_INTEGER:
    case SQLITE4_FLOAT:
    case SQLITE4_TEXT: {
      const char *z = sqlite4_value_text(argv[0], 0);
      if( z ){ 
        int nChar;
        for(nChar=0; *z; nChar++){
          SQLITE4_SKIP_UTF8(z);
        }
        sqlite4_result_int(context, nChar);
      }
      break;
    }

    default: {
      sqlite4_result_null(context);
      break;
    }
  }
}

/*
** Implementation of the abs() function.
**
** IMP: R-23979-26855 The abs(X) function returns the absolute value of
** the numeric argument X. 
*/
static void absFunc(sqlite4_context *context, int argc, sqlite4_value **argv){
  assert( argc==1 );
  UNUSED_PARAMETER(argc);

  switch( sqlite4_value_type(argv[0]) ){
    case SQLITE4_INTEGER: {
      i64 iVal = sqlite4_value_int64(argv[0]);
      if( iVal<0 ){
        if( (iVal<<1)==0 ){
          /* IMP: R-35460-15084 If X is the integer -9223372036854775807 then
          ** abs(X) throws an integer overflow error since there is no
          ** equivalent positive 64-bit two complement value. */
          sqlite4_result_error(context, "integer overflow", -1);
          return;
        }
        iVal = -iVal;
      } 
      sqlite4_result_int64(context, iVal);
      break;
    }
    case SQLITE4_NULL: {
      /* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */
      sqlite4_result_null(context);
      break;
    }
    default: {
      /* Because sqlite4_value_num() returns 0.0 if the argument is not
      ** something that can be converted into a number, we have:
      ** IMP: R-57326-31541 Abs(X) return 0.0 if X is a string or blob that
      ** cannot be converted to a numeric value.  */
      sqlite4_num num = sqlite4_value_num(argv[0]);
      num.sign = 0;
      sqlite4_result_num(context, num);
      break;
    }
  }
}

/*
** Implementation of the substr() function.
**
** substr(x,p1,p2)  returns p2 characters of x[] beginning with p1.
** p1 is 1-indexed.  So substr(x,1,1) returns the first character
** of x.  If x is text, then we actually count UTF-8 characters.
** If x is a blob, then we count bytes.
**
** If p1 is negative, then we begin abs(p1) from the end of x[].
**
** If p2 is negative, return the p2 characters preceeding p1.
*/
static void substrFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  const char *z;
  const char *z2;
  int len;
  int p0type;
  i64 p1, p2;
  int negP2 = 0;

  assert( argc==3 || argc==2 );
  if( sqlite4_value_type(argv[1])==SQLITE4_NULL
   || (argc==3 && sqlite4_value_type(argv[2])==SQLITE4_NULL)
  ){
    return;
  }
  p0type = sqlite4_value_type(argv[0]);
  p1 = sqlite4_value_int(argv[1]);
  if( p0type==SQLITE4_BLOB ){
    z = sqlite4_value_blob(argv[0], &len);
    if( z==0 ) return;
  }else{
    z = sqlite4_value_text(argv[0], 0);
    if( z==0 ) return;
    len = 0;
    if( p1<0 ){
      for(z2=z; *z2; len++){
        SQLITE4_SKIP_UTF8(z2);
      }
    }
  }
  if( argc==3 ){
    p2 = sqlite4_value_int(argv[2]);
    if( p2<0 ){
      p2 = -p2;
      negP2 = 1;
    }
  }else{
    p2 = sqlite4_context_db_handle(context)->aLimit[SQLITE4_LIMIT_LENGTH];
  }
  if( p1<0 ){
    p1 += len;
    if( p1<0 ){
      p2 += p1;
      if( p2<0 ) p2 = 0;
      p1 = 0;
    }
  }else if( p1>0 ){
    p1--;
  }else if( p2>0 ){
    p2--;
  }
  if( negP2 ){
    p1 -= p2;
    if( p1<0 ){
      p2 += p1;
      p1 = 0;
    }
  }
  assert( p1>=0 && p2>=0 );
  if( p0type!=SQLITE4_BLOB ){
    while( *z && p1 ){
      SQLITE4_SKIP_UTF8(z);
      p1--;
    }
    for(z2=z; *z2 && p2; p2--){
      SQLITE4_SKIP_UTF8(z2);
    }
    sqlite4_result_text(context, (char*)z, (int)(z2-z), SQLITE4_TRANSIENT, 0);
  }else{
    if( p1+p2>len ){
      p2 = len-p1;
      if( p2<0 ) p2 = 0;
    }
    sqlite4_result_blob(context, (char*)&z[p1], (int)p2, SQLITE4_TRANSIENT, 0);
  }
}

/*
** Implementation of the round() function
*/
static void roundFunc(sqlite4_context *context, int argc, sqlite4_value **argv){
  int n = 0;                      /* Second argument to this function */
  assert( argc==1 || argc==2 );
  if( argc==2 ){
    if( SQLITE4_NULL==sqlite4_value_type(argv[1]) ) return;
    n = sqlite4_value_int(argv[1]);
    if( n>30 ) n = 30;
    if( n<0 ) n = 0;
  }
  if( sqlite4_value_type(argv[0])==SQLITE4_NULL ) return;

  sqlite4_result_num(context, sqlite4_num_round(sqlite4_value_num(argv[0]), n));
}

/*
** Allocate nByte bytes of space using sqlite4_malloc(). If the
** allocation fails, call sqlite4_result_error_nomem() to notify
** the database handle that malloc() has failed and return NULL.
** If nByte is larger than the maximum string or blob length, then
** raise an SQLITE4_TOOBIG exception and return NULL.
*/
static void *contextMalloc(sqlite4_context *context, i64 nByte){
  char *z;
  sqlite4 *db = sqlite4_context_db_handle(context);
  assert( nByte>0 );
  testcase( nByte==db->aLimit[SQLITE4_LIMIT_LENGTH] );
  testcase( nByte==db->aLimit[SQLITE4_LIMIT_LENGTH]+1 );
  if( nByte>db->aLimit[SQLITE4_LIMIT_LENGTH] ){
    sqlite4_result_error_toobig(context);
    z = 0;
  }else{
    z = sqlite4Malloc(db->pEnv, (int)nByte);
    if( !z ){
      sqlite4_result_error_nomem(context);
    }
  }
  return z;
}

/*
** Implementation of the upper() and lower() SQL functions.
*/
static void upperFunc(sqlite4_context *context, int argc, sqlite4_value **argv){
  char *z1;
  const char *z2;
  int i, n;
  UNUSED_PARAMETER(argc);
  z2 = sqlite4_value_text(argv[0], &n);
  if( z2 ){
    z1 = contextMalloc(context, ((i64)n)+1);
    if( z1 ){
      for(i=0; i<n; i++){
        z1[i] = (char)sqlite4Toupper(z2[i]);
      }
      sqlite4_result_text(context, z1, n, SQLITE4_DYNAMIC, 0);
    }
  }
}
static void lowerFunc(sqlite4_context *context, int argc, sqlite4_value **argv){
  char *z1;
  const char *z2;
  int i, n;
  UNUSED_PARAMETER(argc);
  z2 = sqlite4_value_text(argv[0], &n);
  if( z2 ){
    z1 = contextMalloc(context, ((i64)n)+1);
    if( z1 ){
      for(i=0; i<n; i++){
        z1[i] = sqlite4Tolower(z2[i]);
      }
      sqlite4_result_text(context, z1, n, SQLITE4_DYNAMIC, 0);
    }
  }
}


#if 0  /* This function is never used. */
/*
** The COALESCE() and IFNULL() functions used to be implemented as shown
** here.  But now they are implemented as VDBE code so that unused arguments
** do not have to be computed.  This legacy implementation is retained as
** comment.
*/
/*
** Implementation of the IFNULL(), NVL(), and COALESCE() functions.  
** All three do the same thing.  They return the first non-NULL
** argument.
*/
static void ifnullFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int i;
  for(i=0; i<argc; i++){
    if( SQLITE4_NULL!=sqlite4_value_type(argv[i]) ){
      sqlite4_result_value(context, argv[i]);
      break;
    }
  }
}
#endif /* NOT USED */
#define ifnullFunc versionFunc   /* Substitute function - never called */

/*
** Implementation of random().  Return a random integer.  
*/
static void randomFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **NotUsed2
){
  sqlite4_int64 r;
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  sqlite4_randomness(sqlite4_context_env(context), sizeof(r), &r);
  if( r<0 ){
    /* We need to prevent a random number of 0x8000000000000000 
    ** (or -9223372036854775808) since when you do abs() of that
    ** number of you get the same value back again.  To do this
    ** in a way that is testable, mask the sign bit off of negative
    ** values, resulting in a positive value.  Then take the 
    ** 2s complement of that positive value.  The end result can
    ** therefore be no less than -9223372036854775807.
    */
    r = -(r ^ (((sqlite4_int64)1)<<63));
  }
  sqlite4_result_int64(context, r);
}

/*
** Implementation of randomblob(N).  Return a random blob
** that is N bytes long.
*/
static void randomBlob(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int n;
  unsigned char *p;
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  n = sqlite4_value_int(argv[0]);
  if( n<1 ){
    n = 1;
  }
  p = contextMalloc(context, n);
  if( p ){
    sqlite4_randomness(sqlite4_context_env(context), n, p);
    sqlite4_result_blob(context, (char*)p, n, SQLITE4_DYNAMIC, 0);
  }
}

/*
** Implementation of the changes() SQL function.
**
** IMP: R-62073-11209 The changes() SQL function is a wrapper
** around the sqlite4_changes() C/C++ function and hence follows the same
** rules for counting changes.
*/
static void changes(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **NotUsed2
){
  sqlite4 *db = sqlite4_context_db_handle(context);
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  sqlite4_result_int(context, sqlite4_changes(db));
}

/*
** Implementation of the total_changes() SQL function.  The return value is
** the same as the sqlite4_total_changes() API function.
*/
static void total_changes(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **NotUsed2
){
  sqlite4 *db = sqlite4_context_db_handle(context);
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  /* IMP: R-52756-41993 This function is a wrapper around the
  ** sqlite4_total_changes() C/C++ interface. */
  sqlite4_result_int(context, sqlite4_total_changes(db));
}

/*
** A structure defining how to do GLOB-style comparisons.
*/
struct compareInfo {
  u8 matchAll;
  u8 matchOne;
  u8 matchSet;
  u8 noCase;
};

/*
** For LIKE and GLOB matching on EBCDIC machines, assume that every
** character is exactly one byte in size.  Also, all characters are
** able to participate in upper-case-to-lower-case mappings in EBCDIC
** whereas only characters less than 0x80 do in ASCII.
*/
#if defined(SQLITE4_EBCDIC)
# define sqlite4Utf8Read(A,C)  (*(A++))
# define GlogUpperToLower(A)   A = sqlite4UpperToLower[A]
#else
# define GlogUpperToLower(A)   if( !((A)&~0x7f) ){ A = sqlite4UpperToLower[A]; }
#endif

static const struct compareInfo globInfo = { '*', '?', '[', 0 };
/* The correct SQL-92 behavior is for the LIKE operator to ignore
** case.  Thus  'a' LIKE 'A' would be true. */
static const struct compareInfo likeInfoNorm = { '%', '_',   0, 1 };
/* If SQLITE4_CASE_SENSITIVE_LIKE is defined, then the LIKE operator
** is case sensitive causing 'a' LIKE 'A' to be false */
static const struct compareInfo likeInfoAlt = { '%', '_',   0, 0 };

/*
** Compare two UTF-8 strings for equality where the first string can
** potentially be a "glob" expression.  Return true (1) if they
** are the same and false (0) if they are different.
**
** Globbing rules:
**
**      '*'       Matches any sequence of zero or more characters.
**
**      '?'       Matches exactly one character.
**
**     [...]      Matches one character from the enclosed list of
**                characters.
**
**     [^...]     Matches one character not in the enclosed list.
**
** With the [...] and [^...] matching, a ']' character can be included
** in the list by making it the first character after '[' or '^'.  A
** range of characters can be specified using '-'.  Example:
** "[a-z]" matches any single lower-case letter.  To match a '-', make
** it the last character in the list.
**
** This routine is usually quick, but can be N**2 in the worst case.
**
** Hints: to match '*' or '?', put them in "[]".  Like this:
**
**         abc[*]xyz        Matches "abc*xyz" only
*/
static int patternCompare(
  const char *zPattern,            /* The glob pattern */
  const char *zString,             /* The string to compare against the glob */
  const struct compareInfo *pInfo, /* Information about how to do the compare */
  u32 esc                          /* The escape character */
){
  u32 c, c2;
  int invert;
  int seen;
  u8 matchOne = pInfo->matchOne;
  u8 matchAll = pInfo->matchAll;
  u8 matchSet = pInfo->matchSet;
  u8 noCase = pInfo->noCase; 
  int prevEscape = 0;     /* True if the previous character was 'escape' */

  while( (c = sqlite4Utf8Read(zPattern,&zPattern))!=0 ){
    if( !prevEscape && c==matchAll ){
      while( (c=sqlite4Utf8Read(zPattern,&zPattern)) == matchAll
               || c == matchOne ){
        if( c==matchOne && sqlite4Utf8Read(zString, &zString)==0 ){
          return 0;
        }
      }
      if( c==0 ){
        return 1;
      }else if( c==esc ){
        c = sqlite4Utf8Read(zPattern, &zPattern);
        if( c==0 ){
          return 0;
        }
      }else if( c==matchSet ){
        assert( esc==0 );         /* This is GLOB, not LIKE */
        assert( matchSet<0x80 );  /* '[' is a single-byte character */
        while( *zString && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
          SQLITE4_SKIP_UTF8(zString);
        }
        return *zString!=0;
      }
      while( (c2 = sqlite4Utf8Read(zString,&zString))!=0 ){
        if( noCase ){
          GlogUpperToLower(c2);
          GlogUpperToLower(c);
          while( c2 != 0 && c2 != c ){
            c2 = sqlite4Utf8Read(zString, &zString);
            GlogUpperToLower(c2);
          }
        }else{
          while( c2 != 0 && c2 != c ){
            c2 = sqlite4Utf8Read(zString, &zString);
          }
        }
        if( c2==0 ) return 0;
        if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
      }
      return 0;
    }else if( !prevEscape && c==matchOne ){
      if( sqlite4Utf8Read(zString, &zString)==0 ){
        return 0;
      }
    }else if( c==matchSet ){
      u32 prior_c = 0;
      assert( esc==0 );    /* This only occurs for GLOB, not LIKE */
      seen = 0;
      invert = 0;
      c = sqlite4Utf8Read(zString, &zString);
      if( c==0 ) return 0;
      c2 = sqlite4Utf8Read(zPattern, &zPattern);
      if( c2=='^' ){
        invert = 1;
        c2 = sqlite4Utf8Read(zPattern, &zPattern);
      }
      if( c2==']' ){
        if( c==']' ) seen = 1;
        c2 = sqlite4Utf8Read(zPattern, &zPattern);
      }
      while( c2 && c2!=']' ){
        if( c2=='-' && zPattern[0]!=']' && zPattern[0]!=0 && prior_c>0 ){
          c2 = sqlite4Utf8Read(zPattern, &zPattern);
          if( c>=prior_c && c<=c2 ) seen = 1;
          prior_c = 0;
        }else{
          if( c==c2 ){
            seen = 1;
          }
          prior_c = c2;
        }
        c2 = sqlite4Utf8Read(zPattern, &zPattern);
      }
      if( c2==0 || (seen ^ invert)==0 ){
        return 0;
      }
    }else if( esc==c && !prevEscape ){
      prevEscape = 1;
    }else{
      c2 = sqlite4Utf8Read(zString, &zString);
      if( noCase ){
        GlogUpperToLower(c);
        GlogUpperToLower(c2);
      }
      if( c!=c2 ){
        return 0;
      }
      prevEscape = 0;
    }
  }
  return *zString==0;
}

/*
** Count the number of times that the LIKE operator (or GLOB which is
** just a variation of LIKE) gets called.  This is used for testing
** only.
*/
#ifdef SQLITE4_TEST
SQLITE4_API int sqlite4_like_count = 0;
#endif


/*
** Implementation of the like() SQL function.  This function implements
** the build-in LIKE operator.  The first argument to the function is the
** pattern and the second argument is the string.  So, the SQL statements:
**
**       A LIKE B
**
** is implemented as like(B,A).
**
** This same function (with a different compareInfo structure) computes
** the GLOB operator.
*/
static void likeFunc(
  sqlite4_context *context, 
  int argc, 
  sqlite4_value **argv
){
  const char *zA, *zB;
  u32 escape = 0;
  int nPat;
  sqlite4 *db = sqlite4_context_db_handle(context);

  zB = sqlite4_value_text(argv[0], &nPat);
  zA = sqlite4_value_text(argv[1], 0);

  /* Limit the length of the LIKE or GLOB pattern to avoid problems
  ** of deep recursion and N*N behavior in patternCompare().
  */
  testcase( nPat==db->aLimit[SQLITE4_LIMIT_LIKE_PATTERN_LENGTH] );
  testcase( nPat==db->aLimit[SQLITE4_LIMIT_LIKE_PATTERN_LENGTH]+1 );
  if( nPat > db->aLimit[SQLITE4_LIMIT_LIKE_PATTERN_LENGTH] ){
    sqlite4_result_error(context, "LIKE or GLOB pattern too complex", -1);
    return;
  }

  if( argc==3 ){
    /* The escape character string must consist of a single UTF-8 character.
    ** Otherwise, return an error.
    */
    const char *zEsc = sqlite4_value_text(argv[2], 0);
    if( zEsc==0 ) return;
    if( sqlite4Utf8CharLen(zEsc, -1)!=1 ){
      static const char *zErr = "ESCAPE expression must be a single character";
      sqlite4_result_error(context, zErr, -1);
      return;
    }
    escape = sqlite4Utf8Read(zEsc, &zEsc);
  }
  if( zA && zB ){
    struct compareInfo *pInfo = sqlite4_context_appdata(context);
#ifdef SQLITE4_TEST
    sqlite4_like_count++;
#endif
    
    sqlite4_result_int(context, patternCompare(zB, zA, pInfo, escape));
  }
}

/*
** Implementation of the NULLIF(x,y) function.  The result is the first
** argument if the arguments are different.  The result is NULL if the
** arguments are equal to each other.
*/
static void nullifFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **argv
){
  int rc, res;
  CollSeq *pColl = sqlite4GetFuncCollSeq(context);
  UNUSED_PARAMETER(NotUsed);
  rc = sqlite4MemCompare(argv[0], argv[1], pColl, &res);
  if( rc!=SQLITE4_OK ){
    sqlite4_result_error_code(context, rc);
  }else if( res ){
    sqlite4_result_value(context, argv[0]);
  }
}

/*
** Implementation of the sqlite_version() function.  The result is the version
** of the SQLite library that is running.
*/
static void versionFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **NotUsed2
){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  /* IMP: R-48699-48617 This function is an SQL wrapper around the
  ** sqlite4_libversion() C-interface. */
  sqlite4_result_text(context, sqlite4_libversion(), -1, SQLITE4_STATIC, 0);
}

/*
** Implementation of the sqlite_source_id() function. The result is a string
** that identifies the particular version of the source code used to build
** SQLite.
*/
static void sourceidFunc(
  sqlite4_context *context,
  int NotUsed,
  sqlite4_value **NotUsed2
){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  /* IMP: R-24470-31136 This function is an SQL wrapper around the
  ** sqlite4_sourceid() C interface. */
  sqlite4_result_text(context, sqlite4_sourceid(), -1, SQLITE4_STATIC, 0);
}

/*
** Implementation of the sqlite_log() function.  This is a wrapper around
** sqlite4_log().  The return value is NULL.  The function exists purely for
** its side-effects.
*/
static void errlogFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int rclog = sqlite4_value_int(argv[0]);
  sqlite4_env *pEnv = sqlite4_context_env(context);
  sqlite4_log(pEnv, rclog, "%s", sqlite4_value_text(argv[1], 0));
  UNUSED_PARAMETER(argc);
}

/*
** Implementation of the sqlite_compileoption_used() function.
** The result is an integer that identifies if the compiler option
** was used to build SQLite.
*/
#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS
static void compileoptionusedFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  const char *zOptName;
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  /* IMP: R-39564-36305 The sqlite_compileoption_used() SQL
  ** function is a wrapper around the sqlite4_compileoption_used() C/C++
  ** function.
  */
  if( (zOptName = sqlite4_value_text(argv[0], 0))!=0 ){
    sqlite4_result_int(context, sqlite4_compileoption_used(zOptName));
  }
}
#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */

/*
** Implementation of the sqlite_compileoption_get() function. 
** The result is a string that identifies the compiler options 
** used to build SQLite.
*/
#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS
static void compileoptiongetFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int n;
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  /* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function
  ** is a wrapper around the sqlite4_compileoption_get() C/C++ function.
  */
  n = sqlite4_value_int(argv[0]);
  sqlite4_result_text(context, sqlite4_compileoption_get(n), -1,
                      SQLITE4_STATIC, 0);
}
#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */

/*
** EXPERIMENTAL - This is not an official function.  The interface may
** change.  This function may disappear.  Do not write code that depends
** on this function.
**
** Implementation of the QUOTE() function.  This function takes a single
** argument.  If the argument is numeric, the return value is the same as
** the argument.  If the argument is NULL, the return value is the string
** "NULL".  Otherwise, the argument is enclosed in single quotes with
** single-quote escapes.
*/
static void quoteFunc(sqlite4_context *context, int argc, sqlite4_value **argv){
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  switch( sqlite4_value_type(argv[0]) ){
    case SQLITE4_INTEGER:
    case SQLITE4_FLOAT: {
      sqlite4_result_value(context, argv[0]);
      break;
    }
    case SQLITE4_BLOB: {
      int nBlob;
      char *zText = 0;
      const char *zBlob = sqlite4_value_blob(argv[0], &nBlob);
      zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); 
      if( zText ){
        zText[0] = 'x';
        zText[1] = '\'';
        sqlite4BlobToHex(nBlob, (const u8*)zBlob, zText+2);
        zText[(nBlob*2)+2] = '\'';
        zText[(nBlob*2)+3] = 0;
        sqlite4_result_text(context, zText, -1, SQLITE4_TRANSIENT, 0);
        sqlite4_free(sqlite4_context_env(context), zText);
      }
      break;
    }
    case SQLITE4_TEXT: {
      int i,j;
      u64 n;
      const char *zArg = sqlite4_value_text(argv[0], 0);
      char *z;

      if( zArg==0 ) return;
      for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
      z = contextMalloc(context, ((i64)i)+((i64)n)+3);
      if( z ){
        z[0] = '\'';
        for(i=0, j=1; zArg[i]; i++){
          z[j++] = zArg[i];
          if( zArg[i]=='\'' ){
            z[j++] = '\'';
          }
        }
        z[j++] = '\'';
        z[j] = 0;
        sqlite4_result_text(context, z, j, SQLITE4_DYNAMIC, 0);
      }
      break;
    }
    default: {
      assert( sqlite4_value_type(argv[0])==SQLITE4_NULL );
      sqlite4_result_text(context, "NULL", 4, SQLITE4_STATIC, 0);
      break;
    }
  }
}

/*
** The hex() function.  Interpret the argument as a blob.  Return
** a hexadecimal rendering as text.
*/
static void hexFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  int i, n;
  const unsigned char *pBlob;
  char *zHex;
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  pBlob = sqlite4_value_blob(argv[0], &n);
  zHex = contextMalloc(context, ((i64)n)*2 + 1);
  if( zHex ){
    sqlite4BlobToHex(n, (const u8*)pBlob, zHex);
    sqlite4_result_text(context, zHex, n*2, SQLITE4_DYNAMIC, 0);
  }
}

/*
** The replace() function.  Three arguments are all strings: call
** them A, B, and C. The result is also a string which is derived
** from A by replacing every occurance of B with C.  The match
** must be exact.  Collating sequences are not used.
*/
static void replaceFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  const char *zStr;        /* The input string A */
  const char *zPattern;    /* The pattern string B */
  const char *zRep;        /* The replacement string C */
  char *zOut;              /* The output */
  int nStr;                /* Size of zStr */
  int nPattern;            /* Size of zPattern */
  int nRep;                /* Size of zRep */
  i64 nOut;                /* Maximum size of zOut */
  int loopLimit;           /* Last zStr[] that might match zPattern[] */
  int i, j;                /* Loop counters */

  assert( argc==3 );
  UNUSED_PARAMETER(argc);
  zStr = sqlite4_value_text(argv[0], &nStr);
  if( zStr==0 ) return;
  zPattern = sqlite4_value_text(argv[1], &nPattern);
  if( zPattern==0 ){
    assert( sqlite4_value_type(argv[1])==SQLITE4_NULL
            || sqlite4_context_db_handle(context)->mallocFailed );
    return;
  }
  if( zPattern[0]==0 ){
    assert( sqlite4_value_type(argv[1])!=SQLITE4_NULL );
    sqlite4_result_value(context, argv[0]);
    return;
  }
  zRep = sqlite4_value_text(argv[2], &nRep);
  if( zRep==0 ) return;
  nOut = nStr + 1;
  assert( nOut<SQLITE4_MAX_LENGTH );
  zOut = contextMalloc(context, (i64)nOut);
  if( zOut==0 ){
    return;
  }
  loopLimit = nStr - nPattern;  
  for(i=j=0; i<=loopLimit; i++){
    if( zStr[i]!=zPattern[0] || memcmp(&zStr[i], zPattern, nPattern) ){
      zOut[j++] = zStr[i];
    }else{
      char *zOld;
      sqlite4 *db = sqlite4_context_db_handle(context);
      nOut += nRep - nPattern;
      testcase( nOut-1==db->aLimit[SQLITE4_LIMIT_LENGTH] );
      testcase( nOut-2==db->aLimit[SQLITE4_LIMIT_LENGTH] );
      if( nOut-1>db->aLimit[SQLITE4_LIMIT_LENGTH] ){
        sqlite4_result_error_toobig(context);
        sqlite4_free(db->pEnv, zOut);
        return;
      }
      zOld = zOut;
      zOut = sqlite4_realloc(db->pEnv, zOut, (int)nOut);
      if( zOut==0 ){
        sqlite4_result_error_nomem(context);
        sqlite4_free(db->pEnv, zOld);
        return;
      }
      memcpy(&zOut[j], zRep, nRep);
      j += nRep;
      i += nPattern-1;
    }
  }
  assert( j+nStr-i+1==nOut );
  memcpy(&zOut[j], &zStr[i], nStr-i);
  j += nStr - i;
  assert( j<=nOut );
  zOut[j] = 0;
  sqlite4_result_text(context, zOut, j, SQLITE4_DYNAMIC, 0);
}

/*
** Implementation of the TRIM(), LTRIM(), and RTRIM() functions.
** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both.
*/
static void trimFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  const char *zIn;                /* Input string */
  const char *zCharSet;           /* Set of characters to trim */
  int nIn;                        /* Number of bytes in input */
  int flags;                      /* 1: trimleft  2: trimright  3: trim */
  int i;                          /* Loop counter */
  u8 *aLen = 0;                   /* Length of each character in zCharSet */
  char **azChar = 0;              /* Individual characters in zCharSet */
  int nChar;                      /* Number of characters in zCharSet */

  if( sqlite4_value_type(argv[0])==SQLITE4_NULL ){
    return;
  }
  zIn = sqlite4_value_text(argv[0], &nIn);
  if( zIn==0 ) return;
  if( argc==1 ){
    static const unsigned char lenOne[] = { 1 };
    static char * const azOne[] = { " " };
    nChar = 1;
    aLen = (u8*)lenOne;
    azChar = (char**)azOne;
    zCharSet = 0;
  }else if( (zCharSet = sqlite4_value_text(argv[1], 0))==0 ){
    return;
  }else{
    const char *z;
    for(z=zCharSet, nChar=0; *z; nChar++){
      SQLITE4_SKIP_UTF8(z);
    }
    if( nChar>0 ){
      azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
      if( azChar==0 ){
        return;
      }
      aLen = (unsigned char*)&azChar[nChar];
      for(z=zCharSet, nChar=0; *z; nChar++){
        azChar[nChar] = (char*)z;
        SQLITE4_SKIP_UTF8(z);
        aLen[nChar] = (u8)(z - azChar[nChar]);
      }
    }
  }
  if( nChar>0 ){
    flags = SQLITE4_PTR_TO_INT(sqlite4_context_appdata(context));
    if( flags & 1 ){
      while( nIn>0 ){
        int len = 0;
        for(i=0; i<nChar; i++){
          len = aLen[i];
          if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
        }
        if( i>=nChar ) break;
        zIn += len;
        nIn -= len;
      }
    }
    if( flags & 2 ){
      while( nIn>0 ){
        int len = 0;
        for(i=0; i<nChar; i++){
          len = aLen[i];
          if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
        }
        if( i>=nChar ) break;
        nIn -= len;
      }
    }
    if( zCharSet ){
      sqlite4_free(sqlite4_context_env(context), azChar);
    }
  }
  sqlite4_result_text(context, zIn, nIn, SQLITE4_TRANSIENT, 0);
}


/* IMP: R-25361-16150 This function is omitted from SQLite by default. It
** is only available if the SQLITE4_SOUNDEX compile-time option is used
** when SQLite is built.
*/
#ifdef SQLITE4_SOUNDEX
/*
** Compute the soundex encoding of a word.
**
** IMP: R-59782-00072 The soundex(X) function returns a string that is the
** soundex encoding of the string X. 
*/
static void soundexFunc(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  char zResult[8];
  const u8 *zIn;
  int i, j;
  static const unsigned char iCode[] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
    1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
    0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
    1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
  };
  assert( argc==1 );
  zIn = (u8*)sqlite4_value_text(argv[0]);
  if( zIn==0 ) zIn = (u8*)"";
  for(i=0; zIn[i] && !sqlite4Isalpha(zIn[i]); i++){}
  if( zIn[i] ){
    u8 prevcode = iCode[zIn[i]&0x7f];
    zResult[0] = sqlite4Toupper(zIn[i]);
    for(j=1; j<4 && zIn[i]; i++){
      int code = iCode[zIn[i]&0x7f];
      if( code>0 ){
        if( code!=prevcode ){
          prevcode = code;
          zResult[j++] = code + '0';
        }
      }else{
        prevcode = 0;
      }
    }
    while( j<4 ){
      zResult[j++] = '0';
    }
    zResult[j] = 0;
    sqlite4_result_text(context, zResult, 4, SQLITE4_TRANSIENT, 0);
  }else{
    /* IMP: R-64894-50321 The string "?000" is returned if the argument
    ** is NULL or contains no ASCII alphabetic characters. */
    sqlite4_result_text(context, "?000", 4, SQLITE4_STATIC, 0);
  }
}
#endif /* SQLITE4_SOUNDEX */

#if 0 /*ndef SQLITE4_OMIT_LOAD_EXTENSION*/
/*
** A function that loads a shared-library extension then returns NULL.
*/
static void loadExt(sqlite4_context *context, int argc, sqlite4_value **argv){
  const char *zFile = (const char *)sqlite4_value_text(argv[0]);
  const char *zProc;
  sqlite4 *db = sqlite4_context_db_handle(context);
  char *zErrMsg = 0;

  if( argc==2 ){
    zProc = (const char *)sqlite4_value_text(argv[1]);
  }else{
    zProc = 0;
  }
  if( zFile && sqlite4_load_extension(db, zFile, zProc, &zErrMsg) ){
    sqlite4_result_error(context, zErrMsg, -1);
    sqlite4_free(zErrMsg);
  }
}
#endif


/*
** An instance of the following structure holds the context of a
** sum() or avg() aggregate computation.
*/
typedef struct SumCtx SumCtx;
struct SumCtx {
  sqlite4_num sum;  /* Sum so far */
  i64 cnt;          /* Number of elements summed */
  u8 approx;        /* True if non-integer value was input to the sum */
};

/*
** Routines used to compute the sum, average, and total.
**
** The SUM() function follows the (broken) SQL standard which means
** that it returns NULL if it sums over no inputs.  TOTAL returns
** 0.0 in that case.  In addition, TOTAL always returns a float where
** SUM might return an integer if it never encounters a floating point
** value.  TOTAL never fails, but SUM might through an exception if
** it overflows an integer.
*/
static void sumStep(sqlite4_context *context, int argc, sqlite4_value **argv){
  SumCtx *p;
  int type;
  assert( argc==1 );
  UNUSED_PARAMETER(argc);
  p = sqlite4_aggregate_context(context, sizeof(*p));
  type = sqlite4_value_numeric_type(argv[0]);
  if( p && type!=SQLITE4_NULL ){
    p->cnt++;
    p->sum = sqlite4_num_add(p->sum, sqlite4_value_num(argv[0]));
    if( type!=SQLITE4_INTEGER ){
      p->approx = 1;
    }
  }
}
static void sumFinalize(sqlite4_context *context){
  SumCtx *p;
  p = sqlite4_aggregate_context(context, 0);
  if( p && p->cnt>0 ){
    if( p->approx==0 ){
      int bLossy;
      i64 iVal = sqlite4_num_to_int64(p->sum, &bLossy);
      if( bLossy ){
        sqlite4_result_error(context, "integer overflow", -1);
      }else{
        sqlite4_result_int64(context, iVal);
      }
    }else{
      sqlite4_result_num(context, p->sum);
    }
  }
}
static void avgFinalize(sqlite4_context *context){
  SumCtx *p;
  p = sqlite4_aggregate_context(context, 0);
  if( p && p->cnt>0 ){
    sqlite4_result_num(context, 
        sqlite4_num_div(p->sum, sqlite4_num_from_int64(p->cnt))
    );
  }
}
static void totalFinalize(sqlite4_context *context){
  SumCtx *p;
  p = sqlite4_aggregate_context(context, 0);
  sqlite4_result_num(context, (p ? p->sum : sqlite4_num_from_int64(0)));
}

/*
** The following structure keeps track of state information for the
** count() aggregate function.
*/
typedef struct CountCtx CountCtx;
struct CountCtx {
  i64 n;
};

/*
** Routines to implement the count() aggregate function.
*/
static void countStep(sqlite4_context *context, int argc, sqlite4_value **argv){
  CountCtx *p;
  p = sqlite4_aggregate_context(context, sizeof(*p));
  if( (argc==0 || SQLITE4_NULL!=sqlite4_value_type(argv[0])) && p ){
    p->n++;
  }
}   
static void countFinalize(sqlite4_context *context){
  CountCtx *p;
  p = sqlite4_aggregate_context(context, 0);
  sqlite4_result_int64(context, p ? p->n : 0);
}

/*
** Routines to implement min() and max() aggregate functions.
*/
static void minmaxStep(
  sqlite4_context *context, 
  int NotUsed, 
  sqlite4_value **argv
){
  Mem *pArg  = (Mem *)argv[0];
  Mem *pBest;
  UNUSED_PARAMETER(NotUsed);

  if( sqlite4_value_type(argv[0])==SQLITE4_NULL ) return;
  pBest = (Mem *)sqlite4_aggregate_context(context, sizeof(*pBest));
  if( !pBest ) return;

  if( pBest->flags ){
    int max;
    int cmp;
    int rc;
    CollSeq *pColl = sqlite4GetFuncCollSeq(context);
    /* This step function is used for both the min() and max() aggregates,
    ** the only difference between the two being that the sense of the
    ** comparison is inverted. For the max() aggregate, the
    ** sqlite4_context_appdata() function returns (void *)-1. For min() it
    ** returns (void *)db, where db is the sqlite4* database pointer.
    ** Therefore the next statement sets variable 'max' to 1 for the max()
    ** aggregate, or 0 for min().
    */
    max = sqlite4_context_appdata(context)!=0;
    rc = sqlite4MemCompare(pBest, pArg, pColl, &cmp);
    if( rc!=SQLITE4_OK ){
      sqlite4_result_error_code(context, rc);
      return;
    }
    if( (max && cmp<0) || (!max && cmp>0) ){
      sqlite4VdbeMemCopy(pBest, pArg);
    }
  }else{
    sqlite4VdbeMemCopy(pBest, pArg);
  }
}
static void minMaxFinalize(sqlite4_context *context){
  sqlite4_value *pRes;
  pRes = (sqlite4_value *)sqlite4_aggregate_context(context, 0);
  if( pRes ){
    if( ALWAYS(pRes->flags) ){
      sqlite4_result_value(context, pRes);
    }
    sqlite4VdbeMemRelease(pRes);
  }
}

/*
** group_concat(EXPR, ?SEPARATOR?)
*/
static void groupConcatStep(
  sqlite4_context *context,
  int argc,
  sqlite4_value **argv
){
  const char *zVal;
  StrAccum *pAccum;
  const char *zSep;
  int nVal, nSep;
  assert( argc==1 || argc==2 );
  if( sqlite4_value_type(argv[0])==SQLITE4_NULL ) return;
  pAccum = (StrAccum*)sqlite4_aggregate_context(context, sizeof(*pAccum));

  if( pAccum ){
    sqlite4 *db = sqlite4_context_db_handle(context);
    int firstTerm = pAccum->useMalloc==0;
    pAccum->useMalloc = 2;
    pAccum->pEnv = db->pEnv;
    pAccum->mxAlloc = db->aLimit[SQLITE4_LIMIT_LENGTH];
    if( !firstTerm ){
      if( argc==2 ){
        zSep = (char*)sqlite4_value_text(argv[1], &nSep);
      }else{
        zSep = ",";
        nSep = 1;
      }
      sqlite4StrAccumAppend(pAccum, zSep, nSep);
    }
    zVal = (char*)sqlite4_value_text(argv[0], &nVal);
    sqlite4StrAccumAppend(pAccum, zVal, nVal);
  }
}
static void groupConcatFinalize(sqlite4_context *context){
  StrAccum *pAccum;
  pAccum = sqlite4_aggregate_context(context, 0);
  if( pAccum ){
    if( pAccum->tooBig ){
      sqlite4_result_error_toobig(context);
    }else if( pAccum->mallocFailed ){
      sqlite4_result_error_nomem(context);
    }else{    
      sqlite4_result_text(context, sqlite4StrAccumFinish(pAccum), -1, 
                          SQLITE4_DYNAMIC, 0);
    }
  }
}

/*
** This routine does per-connection function registration.  Most
** of the built-in functions above are part of the global function set.
** This routine only deals with those that are not global.
*/
SQLITE4_PRIVATE void sqlite4RegisterBuiltinFunctions(sqlite4 *db){
  int rc = sqlite4_overload_function(db, "MATCH", 2);
  assert( rc==SQLITE4_NOMEM || rc==SQLITE4_OK );
  if( rc==SQLITE4_NOMEM ){
    db->mallocFailed = 1;
  }
}

/*
** Set the LIKEOPT flag on the 2-argument function with the given name.
*/
static void setLikeOptFlag(sqlite4 *db, const char *zName, u8 flagVal){
  FuncDef *pDef;
  pDef = sqlite4FindFunction(db, zName, sqlite4Strlen30(zName), 2, 0);
  if( ALWAYS(pDef) ){
    pDef->flags = flagVal;
  }
}

/*
** Register the built-in LIKE and GLOB functions.  The caseSensitive
** parameter determines whether or not the LIKE operator is case
** sensitive.  GLOB is always case sensitive.
*/
SQLITE4_PRIVATE void sqlite4RegisterLikeFunctions(sqlite4 *db, int caseSensitive){
  struct compareInfo *pInfo;
  if( caseSensitive ){
    pInfo = (struct compareInfo*)&likeInfoAlt;
  }else{
    pInfo = (struct compareInfo*)&likeInfoNorm;
  }
  sqlite4CreateFunc(db, "like", 2, pInfo, likeFunc, 0, 0, 0);
  sqlite4CreateFunc(db, "like", 3, pInfo, likeFunc, 0, 0, 0);
  sqlite4CreateFunc(db, "glob", 2, 
      (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0);
  setLikeOptFlag(db, "glob", SQLITE4_FUNC_LIKE | SQLITE4_FUNC_CASE);
  setLikeOptFlag(db, "like", 
      caseSensitive ? (SQLITE4_FUNC_LIKE | SQLITE4_FUNC_CASE) : SQLITE4_FUNC_LIKE);
}

/*
** pExpr points to an expression which implements a function.  If
** it is appropriate to apply the LIKE optimization to that function
** then set aWc[0] through aWc[2] to the wildcard characters and
** return TRUE.  If the function is not a LIKE-style function then
** return FALSE.
*/
SQLITE4_PRIVATE int sqlite4IsLikeFunction(sqlite4 *db, Expr *pExpr, int *pIsNocase, char *aWc){
  FuncDef *pDef;
  if( pExpr->op!=TK_FUNCTION 
   || !pExpr->x.pList 
   || pExpr->x.pList->nExpr!=2
  ){
    return 0;
  }
  assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
  pDef = sqlite4FindFunction(db, pExpr->u.zToken, 
                             sqlite4Strlen30(pExpr->u.zToken), 2, 0);
  if( NEVER(pDef==0) || (pDef->flags & SQLITE4_FUNC_LIKE)==0 ){
    return 0;
  }

  /* The memcpy() statement assumes that the wildcard characters are
  ** the first three statements in the compareInfo structure.  The
  ** asserts() that follow verify that assumption
  */
  memcpy(aWc, pDef->pUserData, 3);
  assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
  assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
  assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
  *pIsNocase = (pDef->flags & SQLITE4_FUNC_CASE)==0;
  return 1;
}

/*
** Add all of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table.  This occurs at start-time (as
** a consequence of calling sqlite4_initialize()).
**
** After this routine runs
*/
SQLITE4_PRIVATE void sqlite4RegisterGlobalFunctions(sqlite4_env *pEnv){
  /*
  ** The following array holds FuncDef structures for all of the functions
  ** defined in this file.
  **
  ** The array cannot be constant since changes are made to the
  ** FuncDef.pNextName and FuncDef.pSameName elements at start-time.
  */
  static FuncDef aBuiltinFunc[] = {
    FUNCTION(ltrim,              1, 1, 0, trimFunc         ),
    FUNCTION(ltrim,              2, 1, 0, trimFunc         ),
    FUNCTION(rtrim,              1, 2, 0, trimFunc         ),
    FUNCTION(rtrim,              2, 2, 0, trimFunc         ),
    FUNCTION(trim,               1, 3, 0, trimFunc         ),
    FUNCTION(trim,               2, 3, 0, trimFunc         ),
    FUNCTION(min,               -1, 0, 1, minmaxFunc       ),
    FUNCTION(min,                0, 0, 1, 0                ),
    AGGREGATE(min,               1, 0, 1, minmaxStep,      minMaxFinalize ),
    FUNCTION(max,               -1, 1, 1, minmaxFunc       ),
    FUNCTION(max,                0, 1, 1, 0                ),
    AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
    FUNCTION(typeof,             1, 0, 0, typeofFunc       ),
    FUNCTION(length,             1, 0, 0, lengthFunc       ),
    FUNCTION(substr,             2, 0, 0, substrFunc       ),
    FUNCTION(substr,             3, 0, 0, substrFunc       ),
    FUNCTION(abs,                1, 0, 0, absFunc          ),
    FUNCTION(round,              1, 0, 0, roundFunc        ),
    FUNCTION(round,              2, 0, 0, roundFunc        ),
    FUNCTION(upper,              1, 0, 0, upperFunc        ),
    FUNCTION(lower,              1, 0, 0, lowerFunc        ),
    FUNCTION(coalesce,           1, 0, 0, 0                ),
    FUNCTION(coalesce,           0, 0, 0, 0                ),
/*  FUNCTION(coalesce,          -1, 0, 0, ifnullFunc       ), */
    {-1,SQLITE4_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0},
    FUNCTION(hex,                1, 0, 0, hexFunc          ),
/*  FUNCTION(ifnull,             2, 0, 0, ifnullFunc       ), */
    {2,SQLITE4_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0},
    FUNCTION(random,             0, 0, 0, randomFunc       ),
    FUNCTION(randomblob,         1, 0, 0, randomBlob       ),
    FUNCTION(nullif,             2, 0, 1, nullifFunc       ),
    FUNCTION(sqlite_version,     0, 0, 0, versionFunc      ),
    FUNCTION(sqlite_source_id,   0, 0, 0, sourceidFunc     ),
    FUNCTION(sqlite_log,         2, 0, 0, errlogFunc       ),
#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS
    FUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc  ),
    FUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc  ),
#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */
    FUNCTION(quote,              1, 0, 0, quoteFunc        ),
    FUNCTION(changes,            0, 0, 0, changes          ),
    FUNCTION(total_changes,      0, 0, 0, total_changes    ),
    FUNCTION(replace,            3, 0, 0, replaceFunc      ),
  #ifdef SQLITE4_SOUNDEX
    FUNCTION(soundex,            1, 0, 0, soundexFunc      ),
  #endif
  #if 0 /*ndef SQLITE4_OMIT_LOAD_EXTENSION*/
    FUNCTION(load_extension,     1, 0, 0, loadExt          ),
    FUNCTION(load_extension,     2, 0, 0, loadExt          ),
  #endif
    AGGREGATE(sum,               1, 0, 0, sumStep,         sumFinalize    ),
    AGGREGATE(total,             1, 0, 0, sumStep,         totalFinalize    ),
    AGGREGATE(avg,               1, 0, 0, sumStep,         avgFinalize    ),
 /* AGGREGATE(count,             0, 0, 0, countStep,       countFinalize  ), */
    {0,SQLITE4_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0},
    AGGREGATE(count,             1, 0, 0, countStep,       countFinalize  ),
    AGGREGATE(group_concat,      1, 0, 0, groupConcatStep, groupConcatFinalize),
    AGGREGATE(group_concat,      2, 0, 0, groupConcatStep, groupConcatFinalize),
  
    LIKEFUNC(glob, 2, &globInfo, SQLITE4_FUNC_LIKE|SQLITE4_FUNC_CASE),
  #ifdef SQLITE4_CASE_SENSITIVE_LIKE
    LIKEFUNC(like, 2, &likeInfoAlt, SQLITE4_FUNC_LIKE|SQLITE4_FUNC_CASE),
    LIKEFUNC(like, 3, &likeInfoAlt, SQLITE4_FUNC_LIKE|SQLITE4_FUNC_CASE),
  #else
    LIKEFUNC(like, 2, &likeInfoNorm, SQLITE4_FUNC_LIKE),
    LIKEFUNC(like, 3, &likeInfoNorm, SQLITE4_FUNC_LIKE),
  #endif
  };

  int i;
  FuncDefTable *pFuncTab = &pEnv->aGlobalFuncs;
  FuncDef *aFunc = (FuncDef*)aBuiltinFunc;

  for(i=0; i<ArraySize(aBuiltinFunc); i++){
    sqlite4FuncDefInsert(pFuncTab, &aFunc[i], 1);
  }
  sqlite4RegisterDateTimeFunctions(pEnv);
#ifndef SQLITE4_OMIT_ALTERTABLE
  sqlite4AlterFunctions(pEnv);
#endif
}

/************** End of func.c ************************************************/
/************** Begin file fkey.c ********************************************/
/*
**
** 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 used by the compiler to add foreign key
** support to compiled SQL statements.
*/

#ifndef SQLITE4_OMIT_FOREIGN_KEY
#ifndef SQLITE4_OMIT_TRIGGER

/*
** Deferred and Immediate FKs
** --------------------------
**
** Foreign keys in SQLite come in two flavours: deferred and immediate.
** If an immediate foreign key constraint is violated, SQLITE4_CONSTRAINT
** is returned and the current statement transaction rolled back. If a 
** deferred foreign key constraint is violated, no action is taken 
** immediately. However if the application attempts to commit the 
** transaction before fixing the constraint violation, the attempt fails.
**
** Deferred constraints are implemented using a simple counter associated
** with the database handle. The counter is set to zero each time a 
** database transaction is opened. Each time a statement is executed 
** that causes a foreign key violation, the counter is incremented. Each
** time a statement is executed that removes an existing violation from
** the database, the counter is decremented. When the transaction is
** committed, the commit fails if the current value of the counter is
** greater than zero. This scheme has two big drawbacks:
**
**   * When a commit fails due to a deferred foreign key constraint, 
**     there is no way to tell which foreign constraint is not satisfied,
**     or which row it is not satisfied for.
**
**   * If the database contains foreign key violations when the 
**     transaction is opened, this may cause the mechanism to malfunction.
**
** Despite these problems, this approach is adopted as it seems simpler
** than the alternatives.
**
** INSERT operations:
**
**   I.1) For each FK for which the table is the child table, search
**        the parent table for a match. If none is found increment the
**        constraint counter.
**
**   I.2) For each FK for which the table is the parent table, 
**        search the child table for rows that correspond to the new
**        row in the parent table. Decrement the counter for each row
**        found (as the constraint is now satisfied).
**
** DELETE operations:
**
**   D.1) For each FK for which the table is the child table, 
**        search the parent table for a row that corresponds to the 
**        deleted row in the child table. If such a row is not found, 
**        decrement the counter.
**
**   D.2) For each FK for which the table is the parent table, search 
**        the child table for rows that correspond to the deleted row 
**        in the parent table. For each found increment the counter.
**
** UPDATE operations:
**
**   An UPDATE command requires that all 4 steps above are taken, but only
**   for FK constraints for which the affected columns are actually 
**   modified (values must be compared at runtime).
**
** Note that I.1 and D.1 are very similar operations, as are I.2 and D.2.
** This simplifies the implementation a bit.
**
** For the purposes of immediate FK constraints, the OR REPLACE conflict
** resolution is considered to delete rows before the new row is inserted.
** If a delete caused by OR REPLACE violates an FK constraint, an exception
** is thrown, even if the FK constraint would be satisfied after the new 
** row is inserted.
**
** Immediate constraints are usually handled similarly. The only difference 
** is that the counter used is stored as part of each individual statement
** object (struct Vdbe). If, after the statement has run, its immediate
** constraint counter is greater than zero, it returns SQLITE4_CONSTRAINT
** and the statement transaction is rolled back. An exception is an INSERT
** statement that inserts a single row only (no triggers). In this case,
** instead of using a counter, an exception is thrown immediately if the
** INSERT violates a foreign key constraint. This is necessary as such
** an INSERT does not open a statement transaction.
**
** TODO: How should dropping a table be handled? How should renaming a 
** table be handled?
**
**
** Query API Notes
** ---------------
**
** Before coding an UPDATE or DELETE row operation, the code-generator
** for those two operations needs to know whether or not the operation
** requires any FK processing and, if so, which columns of the original
** row are required by the FK processing VDBE code (i.e. if FKs were
** implemented using triggers, which of the old.* columns would be 
** accessed). No information is required by the code-generator before
** coding an INSERT operation. The functions used by the UPDATE/DELETE
** generation code to query for this information are:
**
**   sqlite4FkRequired() - Test to see if FK processing is required.
**   sqlite4FkOldmask()  - Query for the set of required old.* columns.
**
**
** Externally accessible module functions
** --------------------------------------
**
**   sqlite4FkCheck()    - Check for foreign key violations.
**   sqlite4FkActions()  - Code triggers for ON UPDATE/ON DELETE actions.
**   sqlite4FkDelete()   - Delete an FKey structure.
*/

/*
** VDBE Calling Convention
** -----------------------
**
** Example:
**
**   For the following INSERT statement:
**
**     CREATE TABLE t1(a, b INTEGER PRIMARY KEY, c);
**     INSERT INTO t1 VALUES(1, 2, 3.1);
**
**   Register (x):        2    (type integer)
**   Register (x+1):      1    (type integer)
**   Register (x+2):      NULL (type NULL)
**   Register (x+3):      3.1  (type real)
*/

/*
** A foreign key constraint requires that the key columns in the parent
** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
** Given that pParent is the parent table for foreign key constraint pFKey, 
** search the schema for a unique index on the parent key columns. 
**
** If successful, zero is returned and *ppIdx is set to point to the 
** unique index.
** 
** If the parent key consists of a single column (the foreign key constraint
** is not a composite foreign key), output variable *paiCol is set to NULL.
** Otherwise, it is set to point to an allocated array of size N, where
** N is the number of columns in the parent key. The first element of the
** array is the index of the child table column that is mapped by the FK
** constraint to the parent table column stored in the left-most column
** of index *ppIdx. The second element of the array is the index of the
** child table column that corresponds to the second left-most column of
** *ppIdx, and so on.
**
** If the required index cannot be found, either because:
**
**   1) The named parent key columns do not exist, or
**
**   2) The named parent key columns do exist, but are not subject to a
**      UNIQUE or PRIMARY KEY constraint, or
**
**   3) No parent key columns were provided explicitly as part of the
**      foreign key definition, and the parent table does not have a
**      PRIMARY KEY, or
**
**   4) No parent key columns were provided explicitly as part of the
**      foreign key definition, and the PRIMARY KEY of the parent table 
**      consists of a a different number of columns to the child key in 
**      the child table.
**
** then non-zero is returned, and a "foreign key mismatch" error loaded
** into pParse. If an OOM error occurs, non-zero is returned and the
** pParse->db->mallocFailed flag is set.
*/
static int locateFkeyIndex(
  Parse *pParse,                  /* Parse context to store any error in */
  Table *pParent,                 /* Parent table of FK constraint pFKey */
  FKey *pFKey,                    /* Foreign key to find index for */
  Index **ppIdx,                  /* OUT: Unique index on parent table */
  int **paiCol                    /* OUT: Map of index columns in pFKey */
){
  Index *pIdx = 0;                /* Value to return via *ppIdx */
  int *aiCol = 0;                 /* Value to return via *paiCol */
  int nCol = pFKey->nCol;         /* Number of columns in parent key */
  int bImplicit;                  /* True if no explicit parent columns */

  /* The caller is responsible for zeroing output parameters. */
  assert( ppIdx && *ppIdx==0 );
  assert( !paiCol || *paiCol==0 );
  assert( pParse );

  bImplicit = (pFKey->aCol[0].zCol==0);

  /* If this is a composite foreign key (more than one column), allocate
  ** space for the aiCol array (returned via output parameter *paiCol).
  ** Non-composite foreign keys do not require the aiCol array.  */
  if( paiCol && nCol>1 ){
    assert( nCol>1 );
    aiCol = (int *)sqlite4DbMallocRaw(pParse->db, nCol*sizeof(int));
    if( !aiCol ) return 1;
    *paiCol = aiCol;
  }

  for(pIdx=pParent->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->nColumn==nCol 
     && pIdx->onError!=OE_None
     && pIdx->aiColumn[0]!=-1
    ){ 
      /* pIdx is a UNIQUE index (or a PRIMARY KEY) and has the right number
      ** of columns. If each indexed column corresponds to a foreign key
      ** column of pFKey, then this index is a winner.  */

      if( bImplicit ){
        if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){
          if( aiCol ){
            int i;
            for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom;
          }
          break;
        }
      }else{
        /* If this foreign key was declared to map to an explicit list of 
        ** columns in table pParent. Check if this index matches those 
        ** columns. Also, check that the index uses the default collation 
        ** sequences for each column. */
        int i, j;
        for(i=0; i<nCol; i++){
          int iCol = pIdx->aiColumn[i];     /* Index of column in parent tbl */
          char *zDfltColl;                  /* Def. collation for column */
          char *zIdxCol;                    /* Name of indexed column */

          /* If the index uses a collation sequence that is different from
          ** the default collation sequence for the column, this index is
          ** unusable. Bail out early in this case.  */
          zDfltColl = pParent->aCol[iCol].zColl;
          if( !zDfltColl ){
            zDfltColl = "BINARY";
          }
          if( sqlite4_stricmp(pIdx->azColl[i], zDfltColl) ) break;

          zIdxCol = pParent->aCol[iCol].zName;
          for(j=0; j<nCol; j++){
            if( sqlite4_stricmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
              if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
              break;
            }
          }
          if( j==nCol ) break;
        }
        if( i==nCol ) break;      /* pIdx is usable */
      }
    }
  }

  if( !pIdx ){
    if( !pParse->disableTriggers ){
      sqlite4ErrorMsg(pParse, "foreign key mismatch");
    }
    sqlite4DbFree(pParse->db, aiCol);
    return 1;
  }

  *ppIdx = pIdx;
  return 0;
}

/*
** This function is called when a row is inserted into or deleted from the 
** child table of foreign key constraint pFKey. If an SQL UPDATE is executed 
** on the child table of pFKey, this function is invoked twice for each row
** affected - once to "delete" the old row, and then again to "insert" the
** new row.
**
** Each time it is called, this function generates VDBE code to locate the
** row in the parent table that corresponds to the row being inserted into 
** or deleted from the child table. If the parent row can be found, no 
** special action is taken. Otherwise, if the parent row can *not* be
** found in the parent table:
**
**   Operation | FK type   | Action taken
**   --------------------------------------------------------------------------
**   INSERT      immediate   Increment the "immediate constraint counter".
**
**   DELETE      immediate   Decrement the "immediate constraint counter".
**
**   INSERT      deferred    Increment the "deferred constraint counter".
**
**   DELETE      deferred    Decrement the "deferred constraint counter".
**
** These operations are identified in the comment at the top of this file 
** (fkey.c) as "I.1" and "D.1".
*/
static void fkLookupParent(
  Parse *pParse,        /* Parse context */
  int iDb,              /* Index of database housing pTab */
  Table *pTab,          /* Parent table of FK pFKey */
  Index *pIdx,          /* Unique index on parent key columns in pTab */
  FKey *pFKey,          /* Foreign key constraint */
  int *aiCol,           /* Map from parent key columns to child table columns */
  int regContent,       /* Address of array containing child table row */
  int nIncr,            /* Increment constraint counter by this */
  int isIgnore          /* If true, pretend pTab contains all NULL values */
){
  int i;                                    /* Iterator variable */
  Vdbe *v = sqlite4GetVdbe(pParse);         /* Vdbe to add code to */
  int iCur = pParse->nTab - 1;              /* Cursor number to use */
  int iOk = sqlite4VdbeMakeLabel(v);        /* jump here if parent key found */

  assert( pIdx );

  /* If nIncr is less than zero (this is a DELETE), then check at runtime if
  ** there are any outstanding constraints to resolve. If there are not, 
  ** there is no need to check if deleting this row resolves any outstanding 
  ** violations.  */
  if( nIncr<0 ){
    sqlite4VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, iOk);
  }

  /* Check if any of the key columns in the child table row are NULL. If 
  ** any are, then the constraint is considered satisfied. No need to 
  ** search for a matching row in the parent table.  */
  for(i=0; i<pFKey->nCol; i++){
    int iReg = aiCol[i] + regContent;
    sqlite4VdbeAddOp2(v, OP_IsNull, iReg, iOk);
  }

  if( isIgnore==0 ){
    int nCol = pFKey->nCol;
    int regTemp = sqlite4GetTempRange(pParse, nCol);
    int regRec = sqlite4GetTempReg(pParse);

    sqlite4OpenIndex(pParse, iCur, iDb, pIdx, OP_OpenRead);

    /* Assemble the child key values in a contiguous array of registers.
    ** Then apply the affinity transformation for the parent index.  */
    for(i=0; i<nCol; i++){
      sqlite4VdbeAddOp2(v, OP_Copy, aiCol[i]+regContent, regTemp+i);
    }
    sqlite4VdbeAddOp2(v, OP_Affinity, regTemp, nCol);
    sqlite4VdbeChangeP4(v, -1, sqlite4IndexAffinityStr(v, pIdx), P4_TRANSIENT);

    /* If the parent table is the same as the child table, and we are about
    ** to increment the constraint-counter (i.e. this is an INSERT operation),
    ** then check if the row being inserted matches itself. If so, do not
    ** increment the constraint-counter. 
    **
    ** If any of the parent-key values are NULL, then the row cannot match 
    ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any
    ** of the parent-key values are NULL (at this point it is known that
    ** none of the child key values are).  */
    if( pTab==pFKey->pFrom && nIncr==1 ){
      int iJump = sqlite4VdbeCurrentAddr(v) + nCol + 1;
      for(i=0; i<nCol; i++){
        int iChild = regTemp+i;
        int iParent = pIdx->aiColumn[i]+regContent;
        sqlite4VdbeAddOp3(v, OP_Ne, iChild, iJump, iParent);
        sqlite4VdbeChangeP5(v, SQLITE4_JUMPIFNULL);
        assert( iChild<=pParse->nMem && iParent<=pParse->nMem );
      }
      sqlite4VdbeAddOp2(v, OP_Goto, 0, iOk);
    }

    sqlite4VdbeAddOp4Int(v, OP_MakeKey, regTemp, nCol, regRec, iCur);
    sqlite4VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0);

    sqlite4ReleaseTempReg(pParse, regRec);
    sqlite4ReleaseTempRange(pParse, regTemp, nCol);
  }

  if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
    /* Special case: If this is an INSERT statement that will insert exactly
    ** one row into the table, raise a constraint immediately instead of
    ** incrementing a counter. This is necessary as the VM code is being
    ** generated for will not open a statement transaction.  */
    assert( nIncr==1 );
    sqlite4HaltConstraint(
        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
    );
  }else{
    if( nIncr>0 && pFKey->isDeferred==0 ){
      sqlite4ParseToplevel(pParse)->mayAbort = 1;
    }
    sqlite4VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  }

  sqlite4VdbeResolveLabel(v, iOk);
  sqlite4VdbeAddOp1(v, OP_Close, iCur);
}

/*
** This function is called to generate code executed when a row is inserted
** into or deleted from the parent table of foreign key constraint pFKey.
** When generating code for an SQL UPDATE operation, this function may be 
** called twice - once to "delete" the old row and once to "insert" the 
** new row.
**
** The code generated by this function scans through the rows in the child
** table that correspond to the parent table row being deleted or inserted.
** For each child row found, one of the following actions is taken:
**
**   Operation | FK type   | Action taken
**   --------------------------------------------------------------------------
**   DELETE      immediate   Increment the "immediate constraint counter".
**                           Or, if the ON (UPDATE|DELETE) action is RESTRICT,
**                           throw a "foreign key constraint failed" exception.
**
**   INSERT      immediate   Decrement the "immediate constraint counter".
**
**   DELETE      deferred    Increment the "deferred constraint counter".
**                           Or, if the ON (UPDATE|DELETE) action is RESTRICT,
**                           throw a "foreign key constraint failed" exception.
**
**   INSERT      deferred    Decrement the "deferred constraint counter".
**
** These operations are identified in the comment at the top of this file 
** (fkey.c) as "I.2" and "D.2".
*/
static void fkScanChildren(
  Parse *pParse,                  /* Parse context */
  SrcList *pSrc,                  /* SrcList containing the table to scan */
  Table *pTab,
  Index *pIdx,                    /* Foreign key index */
  FKey *pFKey,                    /* Foreign key relationship */
  int *aiCol,                     /* Map from pIdx cols to child table cols */
  int regData,                    /* Referenced table data starts here */
  int nIncr                       /* Amount to increment deferred counter by */
){
  sqlite4 *db = pParse->db;       /* Database handle */
  int i;                          /* Iterator variable */
  Expr *pWhere = 0;               /* WHERE clause to scan with */
  NameContext sNameContext;       /* Context used to resolve WHERE clause */
  WhereInfo *pWInfo;              /* Context used by sqlite4WhereXXX() */
  int iFkIfZero = 0;              /* Address of OP_FkIfZero */
  Vdbe *v = sqlite4GetVdbe(pParse);

  assert( pIdx && pIdx->pTable==pTab );

  if( nIncr<0 ){
    iFkIfZero = sqlite4VdbeAddOp2(v, OP_FkIfZero, pFKey->isDeferred, 0);
  }

  /* Create an Expr object representing an SQL expression like:
  **
  **   <parent-key1> = <child-key1> AND <parent-key2> = <child-key2> ...
  **
  ** The collation sequence used for the comparison should be that of
  ** the parent key columns. The affinity of the parent key column should
  ** be applied to each child key value before the comparison takes place.
  */
  for(i=0; i<pFKey->nCol; i++){
    Expr *pLeft;                  /* Value from parent table row */
    Expr *pRight;                 /* Column ref to child table */
    Expr *pEq;                    /* Expression (pLeft = pRight) */
    int iCol;                     /* Index of column in child table */ 
    const char *zCol;             /* Name of column in child table */

    pLeft = sqlite4Expr(db, TK_REGISTER, 0);
    if( pLeft ){
      /* Set the collation sequence and affinity of the LHS of each TK_EQ
      ** expression to the parent key column defaults.  */
      Column *pCol;
      iCol = pIdx->aiColumn[i];
      pCol = &pTab->aCol[iCol];
      pLeft->iTable = regData+iCol;
      pLeft->affinity = pCol->affinity;
      pLeft->pColl = sqlite4LocateCollSeq(pParse, pCol->zColl);
    }
    iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
    assert( iCol>=0 );
    zCol = pFKey->pFrom->aCol[iCol].zName;
    pRight = sqlite4Expr(db, TK_ID, zCol);
    pEq = sqlite4PExpr(pParse, TK_EQ, pLeft, pRight, 0);
    pWhere = sqlite4ExprAnd(db, pWhere, pEq);
  }

  /* If the child table is the same as the parent table, and this scan
  ** is taking place as part of a DELETE operation (operation D.2), omit the
  ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE 
  ** clause, where $rowid is the rowid of the row being deleted.  */
  if( pTab==pFKey->pFrom && nIncr>0 ){
    Expr *pEq;                    /* Expression (pLeft = pRight) */
    Expr *pLeft;                  /* Value from parent table row */
    Expr *pRight;                 /* Column ref to child table */
    pLeft = sqlite4Expr(db, TK_REGISTER, 0);
    pRight = sqlite4Expr(db, TK_COLUMN, 0);
    if( pLeft && pRight ){
      pLeft->iTable = regData;
      pLeft->affinity = SQLITE4_AFF_INTEGER;
      pRight->iTable = pSrc->a[0].iCursor;
      pRight->iColumn = -1;
    }
    pEq = sqlite4PExpr(pParse, TK_NE, pLeft, pRight, 0);
    pWhere = sqlite4ExprAnd(db, pWhere, pEq);
  }

  /* Resolve the references in the WHERE clause. */
  memset(&sNameContext, 0, sizeof(NameContext));
  sNameContext.pSrcList = pSrc;
  sNameContext.pParse = pParse;
  sqlite4ResolveExprNames(&sNameContext, pWhere);

  /* Create VDBE to loop through the entries in pSrc that match the WHERE
  ** clause. For each row found, increment the relevant constraint counter
  ** by nIncr.  */
  pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
  if( nIncr>0 && pFKey->isDeferred==0 ){
    sqlite4ParseToplevel(pParse)->mayAbort = 1;
  }
  sqlite4VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
  if( pWInfo ){
    sqlite4WhereEnd(pWInfo);
  }

  /* Clean up the WHERE clause constructed above. */
  sqlite4ExprDelete(db, pWhere);
  if( iFkIfZero ){
    sqlite4VdbeJumpHere(v, iFkIfZero);
  }
}

/*
** This function returns a pointer to the head of a linked list of FK
** constraints for which table pTab is the parent table. For example,
** given the following schema:
**
**   CREATE TABLE t1(a PRIMARY KEY);
**   CREATE TABLE t2(b REFERENCES t1(a);
**
** Calling this function with table "t1" as an argument returns a pointer
** to the FKey structure representing the foreign key constraint on table
** "t2". Calling this function with "t2" as the argument would return a
** NULL pointer (as there are no FK constraints for which t2 is the parent
** table).
*/
SQLITE4_PRIVATE FKey *sqlite4FkReferences(Table *pTab){
  int nName = sqlite4Strlen30(pTab->zName);
  return (FKey *)sqlite4HashFind(&pTab->pSchema->fkeyHash, pTab->zName, nName);
}

/*
** The second argument is a Trigger structure allocated by the 
** fkActionTrigger() routine. This function deletes the Trigger structure
** and all of its sub-components.
**
** The Trigger structure or any of its sub-components may be allocated from
** the lookaside buffer belonging to database handle dbMem.
*/
static void fkTriggerDelete(sqlite4 *dbMem, Trigger *p){
  if( p ){
    TriggerStep *pStep = p->step_list;
    sqlite4ExprDelete(dbMem, pStep->pWhere);
    sqlite4ExprListDelete(dbMem, pStep->pExprList);
    sqlite4SelectDelete(dbMem, pStep->pSelect);
    sqlite4ExprDelete(dbMem, p->pWhen);
    sqlite4DbFree(dbMem, p);
  }
}

/*
** This function is called to generate code that runs when table pTab is
** being dropped from the database. The SrcList passed as the second argument
** to this function contains a single entry guaranteed to resolve to
** table pTab.
**
** Normally, no code is required. However, if either
**
**   (a) The table is the parent table of a FK constraint, or
**   (b) The table is the child table of a deferred FK constraint and it is
**       determined at runtime that there are outstanding deferred FK 
**       constraint violations in the database,
**
** then the equivalent of "DELETE FROM <tbl>" is executed before dropping
** the table from the database. Triggers are disabled while running this
** DELETE, but foreign key actions are not.
*/
SQLITE4_PRIVATE void sqlite4FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
  sqlite4 *db = pParse->db;
  if( (db->flags&SQLITE4_ForeignKeys) && !IsVirtual(pTab) && !pTab->pSelect ){
    int iSkip = 0;
    Vdbe *v = sqlite4GetVdbe(pParse);

    assert( v );                  /* VDBE has already been allocated */
    if( sqlite4FkReferences(pTab)==0 ){
      /* Search for a deferred foreign key constraint for which this table
      ** is the child table. If one cannot be found, return without 
      ** generating any VDBE code. If one can be found, then jump over
      ** the entire DELETE if there are no outstanding deferred constraints
      ** when this statement is run.  */
      FKey *p;
      for(p=pTab->pFKey; p; p=p->pNextFrom){
        if( p->isDeferred ) break;
      }
      if( !p ) return;
      iSkip = sqlite4VdbeMakeLabel(v);
      sqlite4VdbeAddOp2(v, OP_FkIfZero, 1, iSkip);
    }

    pParse->disableTriggers = 1;
    sqlite4DeleteFrom(pParse, sqlite4SrcListDup(db, pName, 0), 0);
    pParse->disableTriggers = 0;

    /* If the DELETE has generated immediate foreign key constraint 
    ** violations, halt the VDBE and return an error at this point, before
    ** any modifications to the schema are made. This is because statement
    ** transactions are not able to rollback schema changes.  */
    sqlite4VdbeAddOp2(v, OP_FkIfZero, 0, sqlite4VdbeCurrentAddr(v)+2);
    sqlite4HaltConstraint(
        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
    );

    if( iSkip ){
      sqlite4VdbeResolveLabel(v, iSkip);
    }
  }
}

/*
** This function is called when inserting, deleting or updating a row of
** table pTab to generate VDBE code to perform foreign key constraint 
** processing for the operation.
**
** For a DELETE operation, parameter regOld is passed the index of the
** first register in an array of (pTab->nCol+1) registers containing the
** rowid of the row being deleted, followed by each of the column values
** of the row being deleted, from left to right. Parameter regNew is passed
** zero in this case.
**
** For an INSERT operation, regOld is passed zero and regNew is passed the
** first register of an array of (pTab->nCol+1) registers containing the new
** row data.
**
** For an UPDATE operation, this function is called twice. Once before
** the original record is deleted from the table using the calling convention
** described for DELETE. Then again after the original record is deleted
** but before the new record is inserted using the INSERT convention. 
*/
SQLITE4_PRIVATE void sqlite4FkCheck(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Row is being deleted from this table */ 
  int regOld,                     /* Previous row data is stored here */
  int regNew                      /* New row data is stored here */
){
  sqlite4 *db = pParse->db;       /* Database handle */
  FKey *pFKey;                    /* Used to iterate through FKs */
  int iDb;                        /* Index of database containing pTab */
  const char *zDb;                /* Name of database containing pTab */
  int isIgnoreErrors = pParse->disableTriggers;

  /* Exactly one of regOld and regNew should be non-zero. */
  assert( (regOld==0)!=(regNew==0) );

  /* If foreign-keys are disabled, this function is a no-op. */
  if( (db->flags&SQLITE4_ForeignKeys)==0 ) return;

  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  zDb = db->aDb[iDb].zName;

  /* Loop through all the foreign key constraints for which pTab is the
  ** child table (the table that the foreign key definition is part of).  */
  for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
    Table *pTo;                   /* Parent table of foreign key pFKey */
    Index *pIdx = 0;              /* Index on key columns in pTo */
    int *aiFree = 0;
    int *aiCol;
    int iCol;
    int i;
    int isIgnore = 0;

    /* Find the parent table of this foreign key. Also find a unique index 
    ** on the parent key columns in the parent table. If either of these 
    ** schema items cannot be located, set an error in pParse and return 
    ** early.  */
    if( pParse->disableTriggers ){
      pTo = sqlite4FindTable(db, pFKey->zTo, zDb);
    }else{
      pTo = sqlite4LocateTable(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 = sqlite4GetVdbe(pParse);
        int iJump = sqlite4VdbeCurrentAddr(v) + pFKey->nCol + 1;
        for(i=0; i<pFKey->nCol; i++){
          int iReg = pFKey->aCol[i].iFrom + regOld;
          sqlite4VdbeAddOp2(v, OP_IsNull, iReg, iJump);
        }
        sqlite4VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
      }
      continue;
    }
    assert( pFKey->nCol==1 || (aiFree && pIdx) );

    if( aiFree ){
      aiCol = aiFree;
    }else{
      iCol = pFKey->aCol[0].iFrom;
      aiCol = &iCol;
    }
#ifndef SQLITE4_OMIT_AUTHORIZATION
    for(i=0; i<pFKey->nCol; i++){
      /* Request permission to read the parent key columns. If the 
      ** authorization callback returns SQLITE4_IGNORE, behave as if any
      ** values read from the parent table are NULL. */
      int rcauth;
      char *zCol = pTo->aCol[pIdx->aiColumn[i]].zName;
      rcauth = sqlite4AuthReadCol(pParse, pTo->zName, zCol, iDb);
      isIgnore = (rcauth==SQLITE4_IGNORE);
    }
#endif

    pParse->nTab++;
    if( regOld!=0 ){
      /* A row is being removed from the child table. Search for the parent.
      ** If the parent does not exist, removing the child row resolves an 
      ** outstanding foreign key constraint violation. */
      fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regOld, -1,isIgnore);
    }
    if( regNew!=0 ){
      /* A row is being added to the child table. If a parent row cannot
      ** be found, adding the child row has violated the FK constraint. */ 
      fkLookupParent(pParse, iDb, pTo, pIdx, pFKey, aiCol, regNew, +1,isIgnore);
    }

    sqlite4DbFree(db, aiFree);
  }

  /* Loop through all the foreign key constraints that refer to this table */
  for(pFKey = sqlite4FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
    Index *pIdx = 0;              /* Foreign key index for pFKey */
    SrcList *pSrc;
    int *aiCol = 0;

    if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){
      assert( regOld==0 && regNew!=0 );
      /* Inserting a single row into a parent table cannot cause an immediate
      ** foreign key violation. So do nothing in this case.  */
      continue;
    }

    if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
      if( !isIgnoreErrors || db->mallocFailed ) return;
      continue;
    }
    assert( aiCol || pFKey->nCol==1 );

    /* Create a SrcList structure containing a single table (the table 
    ** the foreign key that refers to this table is attached to). This
    ** is required for the sqlite4WhereXXX() interface.  */
    pSrc = sqlite4SrcListAppend(db, 0, 0, 0);
    if( pSrc ){
      SrcListItem *pItem = pSrc->a;
      pItem->pTab = pFKey->pFrom;
      pItem->zName = pFKey->pFrom->zName;
      pItem->pTab->nRef++;
      pItem->iCursor = pParse->nTab++;
  
      if( regNew!=0 ){
        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regNew, -1);
      }
      if( regOld!=0 ){
        /* If there is a RESTRICT action configured for the current operation
        ** on the parent table of this FK, then throw an exception 
        ** immediately if the FK constraint is violated, even if this is a
        ** deferred trigger. That's what RESTRICT means. To defer checking
        ** the constraint, the FK should specify NO ACTION (represented
        ** using OE_None). NO ACTION is the default.  */
        fkScanChildren(pParse, pSrc, pTab, pIdx, pFKey, aiCol, regOld, 1);
      }
      pItem->zName = 0;
      sqlite4SrcListDelete(db, pSrc);
    }
    sqlite4DbFree(db, aiCol);
  }
}

#define COLUMN_MASK(x) (((x)>31) ? 0xffffffff : ((u32)1<<(x)))

/*
** This function is called before generating code to update or delete a 
** row contained in table pTab. 
*/
SQLITE4_PRIVATE u32 sqlite4FkOldmask(
  Parse *pParse,                  /* Parse context */
  Table *pTab                     /* Table being modified */
){
  u32 mask = 0;
  if( pParse->db->flags&SQLITE4_ForeignKeys ){
    FKey *p;
    int i;
    for(p=pTab->pFKey; p; p=p->pNextFrom){
      for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
    }
    for(p=sqlite4FkReferences(pTab); p; p=p->pNextTo){
      Index *pIdx = 0;
      locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
      if( pIdx ){
        for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
      }
    }
  }
  return mask;
}

/*
** This function is called before generating code to update or delete a 
** row contained in table pTab. If the operation is a DELETE, then
** parameter aChange is passed a NULL value. For an UPDATE, aChange points
** to an array of size N, where N is the number of columns in table pTab.
** If the i'th column is not modified by the UPDATE, then the corresponding 
** entry in the aChange[] array is set to -1. If the column is modified,
** the value is 0 or greater. Parameter chngRowid is set to true if the
** UPDATE statement modifies the rowid fields of the table.
**
** If any foreign key processing will be required, this function returns
** true. If there is no foreign key related processing, this function 
** returns false.
*/
SQLITE4_PRIVATE int sqlite4FkRequired(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being modified */
  int *aChange                    /* Non-NULL for UPDATE operations */
){
  if( pParse->db->flags&SQLITE4_ForeignKeys ){
    if( !aChange ){
      /* A DELETE operation. Foreign key processing is required if the 
      ** table in question is either the child or parent table for any 
      ** foreign key constraint.  */
      return (sqlite4FkReferences(pTab) || pTab->pFKey);
    }else{
      /* This is an UPDATE. Foreign key processing is only required if the
      ** operation modifies one or more child or parent key columns. */
      int i;
      FKey *p;

      /* Check if any child key columns are being modified. */
      for(p=pTab->pFKey; p; p=p->pNextFrom){
        for(i=0; i<p->nCol; i++){
          int iChildKey = p->aCol[i].iFrom;
          if( aChange[iChildKey]>=0 ) return 1;
        }
      }

      /* Check if any parent key columns are being modified. */
      for(p=sqlite4FkReferences(pTab); p; p=p->pNextTo){
        for(i=0; i<p->nCol; i++){
          char *zKey = p->aCol[i].zCol;
          int iKey;
          for(iKey=0; iKey<pTab->nCol; iKey++){
            Column *pCol = &pTab->aCol[iKey];
            if( (zKey ? !sqlite4_stricmp(pCol->zName,zKey) : pCol->iPrimKey>0) ){
              if( aChange[iKey]>=0 ) return 1;
            }
          }
        }
      }
    }
  }
  return 0;
}

/*
** This function is called when an UPDATE or DELETE operation is being 
** compiled on table pTab, which is the parent table of foreign-key pFKey.
** If the current operation is an UPDATE, then the pChanges parameter is
** passed a pointer to the list of columns being modified. If it is a
** DELETE, pChanges is passed a NULL pointer.
**
** It returns a pointer to a Trigger structure containing a trigger
** equivalent to the ON UPDATE or ON DELETE action specified by pFKey.
** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is
** returned (these actions require no special handling by the triggers
** sub-system, code for them is created by fkScanChildren()).
**
** For example, if pFKey is the foreign key and pTab is table "p" in 
** the following schema:
**
**   CREATE TABLE p(pk PRIMARY KEY);
**   CREATE TABLE c(ck REFERENCES p ON DELETE CASCADE);
**
** then the returned trigger structure is equivalent to:
**
**   CREATE TRIGGER ... DELETE ON p BEGIN
**     DELETE FROM c WHERE ck = old.pk;
**   END;
**
** The returned pointer is cached as part of the foreign key object. It
** is eventually freed along with the rest of the foreign key object by 
** sqlite4FkDelete().
*/
static Trigger *fkActionTrigger(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being updated or deleted from */
  FKey *pFKey,                    /* Foreign key to get action for */
  ExprList *pChanges              /* Change-list for UPDATE, NULL for DELETE */
){
  sqlite4 *db = pParse->db;       /* Database handle */
  int action;                     /* One of OE_None, OE_Cascade etc. */
  Trigger *pTrigger;              /* Trigger definition to return */
  int iAction = (pChanges!=0);    /* 1 for UPDATE, 0 for DELETE */

  action = pFKey->aAction[iAction];
  pTrigger = pFKey->apTrigger[iAction];

  if( action!=OE_None && !pTrigger ){
    u8 enableLookaside;           /* Copy of db->lookaside.bEnabled */
    char const *zFrom;            /* Name of child table */
    int nFrom;                    /* Length in bytes of zFrom */
    Index *pIdx = 0;              /* Parent key index for this FK */
    int *aiCol = 0;               /* child table cols -> parent key cols */
    TriggerStep *pStep = 0;        /* First (only) step of trigger program */
    Expr *pWhere = 0;             /* WHERE clause of trigger step */
    ExprList *pList = 0;          /* Changes list if ON UPDATE CASCADE */
    Select *pSelect = 0;          /* If RESTRICT, "SELECT RAISE(...)" */
    int i;                        /* Iterator variable */
    Expr *pWhen = 0;              /* WHEN clause for the trigger */

    if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
    assert( aiCol || pFKey->nCol==1 );

    for(i=0; i<pFKey->nCol; i++){
      Token tOld = { "old", 3 };  /* Literal "old" token */
      Token tNew = { "new", 3 };  /* Literal "new" token */
      Token tFromCol;             /* Name of column in child table */
      Token tToCol;               /* Name of column in parent table */
      int iFromCol;               /* Idx of column in child table */
      Expr *pEq;                  /* tFromCol = OLD.tToCol */

      iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
      assert( iFromCol>=0 );
      tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid";
      tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName;

      tToCol.n = sqlite4Strlen30(tToCol.z);
      tFromCol.n = sqlite4Strlen30(tFromCol.z);

      /* Create the expression "OLD.zToCol = zFromCol". It is important
      ** that the "OLD.zToCol" term is on the LHS of the = operator, so
      ** that the affinity and collation sequence associated with the
      ** parent table are used for the comparison. */
      pEq = sqlite4PExpr(pParse, TK_EQ,
          sqlite4PExpr(pParse, TK_DOT, 
            sqlite4PExpr(pParse, TK_ID, 0, 0, &tOld),
            sqlite4PExpr(pParse, TK_ID, 0, 0, &tToCol)
          , 0),
          sqlite4PExpr(pParse, TK_ID, 0, 0, &tFromCol)
      , 0);
      pWhere = sqlite4ExprAnd(db, pWhere, pEq);

      /* For ON UPDATE, construct the next term of the WHEN clause.
      ** The final WHEN clause will be like this:
      **
      **    WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN)
      */
      if( pChanges ){
        pEq = sqlite4PExpr(pParse, TK_IS,
            sqlite4PExpr(pParse, TK_DOT, 
              sqlite4PExpr(pParse, TK_ID, 0, 0, &tOld),
              sqlite4PExpr(pParse, TK_ID, 0, 0, &tToCol),
              0),
            sqlite4PExpr(pParse, TK_DOT, 
              sqlite4PExpr(pParse, TK_ID, 0, 0, &tNew),
              sqlite4PExpr(pParse, TK_ID, 0, 0, &tToCol),
              0),
            0);
        pWhen = sqlite4ExprAnd(db, pWhen, pEq);
      }
  
      if( action!=OE_Restrict && (action!=OE_Cascade || pChanges) ){
        Expr *pNew;
        if( action==OE_Cascade ){
          pNew = sqlite4PExpr(pParse, TK_DOT, 
            sqlite4PExpr(pParse, TK_ID, 0, 0, &tNew),
            sqlite4PExpr(pParse, TK_ID, 0, 0, &tToCol)
          , 0);
        }else if( action==OE_SetDflt ){
          Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
          if( pDflt ){
            pNew = sqlite4ExprDup(db, pDflt, 0);
          }else{
            pNew = sqlite4PExpr(pParse, TK_NULL, 0, 0, 0);
          }
        }else{
          pNew = sqlite4PExpr(pParse, TK_NULL, 0, 0, 0);
        }
        pList = sqlite4ExprListAppend(pParse, pList, pNew);
        sqlite4ExprListSetName(pParse, pList, &tFromCol, 0);
      }
    }
    sqlite4DbFree(db, aiCol);

    zFrom = pFKey->pFrom->zName;
    nFrom = sqlite4Strlen30(zFrom);

    if( action==OE_Restrict ){
      Token tFrom;
      Expr *pRaise; 

      tFrom.z = zFrom;
      tFrom.n = nFrom;
      pRaise = sqlite4Expr(db, TK_RAISE, "foreign key constraint failed");
      if( pRaise ){
        pRaise->affinity = OE_Abort;
      }
      pSelect = sqlite4SelectNew(pParse, 
          sqlite4ExprListAppend(pParse, 0, pRaise),
          sqlite4SrcListAppend(db, 0, &tFrom, 0),
          pWhere,
          0, 0, 0, 0, 0, 0
      );
      pWhere = 0;
    }

    /* Disable lookaside memory allocation */
    enableLookaside = db->lookaside.bEnabled;
    db->lookaside.bEnabled = 0;

    pTrigger = (Trigger *)sqlite4DbMallocZero(db, 
        sizeof(Trigger) +         /* struct Trigger */
        sizeof(TriggerStep) +     /* Single step in trigger program */
        nFrom + 1                 /* Space for pStep->target.z */
    );
    if( pTrigger ){
      pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
      pStep->target.z = (char *)&pStep[1];
      pStep->target.n = nFrom;
      memcpy((char *)pStep->target.z, zFrom, nFrom);
  
      pStep->pWhere = sqlite4ExprDup(db, pWhere, EXPRDUP_REDUCE);
      pStep->pExprList = sqlite4ExprListDup(db, pList, EXPRDUP_REDUCE);
      pStep->pSelect = sqlite4SelectDup(db, pSelect, EXPRDUP_REDUCE);
      if( pWhen ){
        pWhen = sqlite4PExpr(pParse, TK_NOT, pWhen, 0, 0);
        pTrigger->pWhen = sqlite4ExprDup(db, pWhen, EXPRDUP_REDUCE);
      }
    }

    /* Re-enable the lookaside buffer, if it was disabled earlier. */
    db->lookaside.bEnabled = enableLookaside;

    sqlite4ExprDelete(db, pWhere);
    sqlite4ExprDelete(db, pWhen);
    sqlite4ExprListDelete(db, pList);
    sqlite4SelectDelete(db, pSelect);
    if( db->mallocFailed==1 ){
      fkTriggerDelete(db, pTrigger);
      return 0;
    }
    assert( pStep!=0 );

    switch( action ){
      case OE_Restrict:
        pStep->op = TK_SELECT; 
        break;
      case OE_Cascade: 
        if( !pChanges ){ 
          pStep->op = TK_DELETE; 
          break; 
        }
      default:
        pStep->op = TK_UPDATE;
    }
    pStep->pTrig = pTrigger;
    pTrigger->pSchema = pTab->pSchema;
    pTrigger->pTabSchema = pTab->pSchema;
    pFKey->apTrigger[iAction] = pTrigger;
    pTrigger->op = (pChanges ? TK_UPDATE : TK_DELETE);
  }

  return pTrigger;
}

/*
** This function is called when deleting or updating a row to implement
** any required CASCADE, SET NULL or SET DEFAULT actions.
*/
SQLITE4_PRIVATE void sqlite4FkActions(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table being updated or deleted from */
  ExprList *pChanges,             /* Change-list for UPDATE, NULL for DELETE */
  int regOld                      /* Address of array containing old row */
){
  /* If foreign-key support is enabled, iterate through all FKs that 
  ** refer to table pTab. If there is an action associated with the FK 
  ** for this operation (either update or delete), invoke the associated 
  ** trigger sub-program.  */
  if( pParse->db->flags&SQLITE4_ForeignKeys ){
    FKey *pFKey;                  /* Iterator variable */
    for(pFKey = sqlite4FkReferences(pTab); pFKey; pFKey=pFKey->pNextTo){
      Trigger *pAction = fkActionTrigger(pParse, pTab, pFKey, pChanges);
      if( pAction ){
        sqlite4CodeRowTriggerDirect(pParse, pAction, pTab, regOld, OE_Abort, 0);
      }
    }
  }
}

#endif /* ifndef SQLITE4_OMIT_TRIGGER */

/*
** Free all memory associated with foreign key definitions attached to
** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash
** hash table.
*/
SQLITE4_PRIVATE void sqlite4FkDelete(sqlite4 *db, Table *pTab){
  FKey *pFKey;                    /* Iterator variable */
  FKey *pNext;                    /* Copy of pFKey->pNextFrom */

  for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){

    /* Remove the FK from the fkeyHash hash table. */
    if( !db || db->pnBytesFreed==0 ){
      if( pFKey->pPrevTo ){
        pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
      }else{
        void *p = (void *)pFKey->pNextTo;
        const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo);
        sqlite4HashInsert(&pTab->pSchema->fkeyHash, z, sqlite4Strlen30(z), p);
      }
      if( pFKey->pNextTo ){
        pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
      }
    }

    /* EV: R-30323-21917 Each foreign key constraint in SQLite is
    ** classified as either immediate or deferred.
    */
    assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 );

    /* Delete any triggers created to implement actions for this FK. */
#ifndef SQLITE4_OMIT_TRIGGER
    fkTriggerDelete(db, pFKey->apTrigger[0]);
    fkTriggerDelete(db, pFKey->apTrigger[1]);
#endif

    pNext = pFKey->pNextFrom;
    sqlite4DbFree(db, pFKey);
  }
}
#endif /* ifndef SQLITE4_OMIT_FOREIGN_KEY */

/************** End of fkey.c ************************************************/
/************** Begin file insert.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
*/

/*
** Generate code that will open a table for reading.
*/
SQLITE4_PRIVATE void sqlite4OpenTable(
  Parse *p,       /* Generate code into this VDBE */
  int iCur,       /* The cursor number of the table */
  int iDb,        /* The database index in sqlite4.aDb[] */
  Table *pTab,    /* The table to be opened */
  int opcode      /* OP_OpenRead or OP_OpenWrite */
){
  Index *pPk = sqlite4FindPrimaryKey(pTab, 0);
  sqlite4OpenIndex(p, iCur, iDb, pPk, opcode);
}

/*
** Open VDBE cursor iCur to access index pIdx. pIdx is guaranteed to be
** a part of database iDb.
*/
SQLITE4_PRIVATE void sqlite4OpenIndex(
  Parse *p,                       /* Current parser context */
  int iCur,                       /* The cursor number of the cursor to open */
  int iDb,                        /* The database index in sqlite4.aDb[] */
  Index *pIdx,                    /* The index to be opened */
  int opcode                      /* OP_OpenRead or OP_OpenWrite */
){
  KeyInfo *pKey;                /* KeyInfo structure describing PK index */
  Vdbe *v;                      /* VM to write code into */

  assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
  assert( pIdx->tnum>0 );

  v = sqlite4GetVdbe(p);
  pKey = sqlite4IndexKeyinfo(p, pIdx);
  testcase( pKey==0 );

  sqlite4VdbeAddOp3(v, opcode, iCur, pIdx->tnum, iDb);
  sqlite4VdbeChangeP4(v, -1, (const char *)pKey, P4_KEYINFO_HANDOFF);
  VdbeComment((v, "%s", pIdx->zName));
}

/*
** Generate code that will open the primary key of a table for either 
** reading (if opcode==OP_OpenRead) or writing (if opcode==OP_OpenWrite).
*/
SQLITE4_PRIVATE void sqlite4OpenPrimaryKey(
  Parse *p,                       /* Current parser context */
  int iCur,                       /* The cursor number of the cursor to open */
  int iDb,                        /* The database index in sqlite4.aDb[] */
  Table *pTab,                    /* The table to be opened */
  int opcode                      /* OP_OpenRead or OP_OpenWrite */
){
  assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
  if( IsVirtual(pTab)==0 ){
    Index *pIdx;                  /* PRIMARY KEY index for table pTab */

    pIdx = sqlite4FindPrimaryKey(pTab, 0);
    sqlite4OpenIndex(p, iCur, iDb, pIdx, opcode);
    assert( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY );
  }
}

/*
** Return a pointer to the column affinity string associated with index
** pIdx. A column affinity string has one character for each column in 
** the index key. If the index is the PRIMARY KEY of its table, the key
** consists of the index columns only. Otherwise, it consists of the
** indexed columns, followed by the columns that make up the tables PRIMARY
** KEY. For each column in the index key, the corresponding character of
** the affinity string is set according to the column affinity, as follows:
**
**  Character      Column affinity
**  ------------------------------
**  'a'            TEXT
**  'b'            NONE
**  'c'            NUMERIC
**  'd'            INTEGER
**  'e'            REAL
**
** Memory for the buffer containing the column index affinity string
** is managed along with the rest of the Index structure. It will be
** released when sqlite4DeleteIndex() is called.
*/
SQLITE4_PRIVATE const char *sqlite4IndexAffinityStr(Vdbe *v, Index *pIdx){
  /* The first time a column affinity string for a particular index is
  ** required, it is allocated and populated here. It is then stored as
  ** a member of the Index structure for subsequent use. The column 
  ** affinity string will eventually be deleted by sqliteDeleteIndex() 
  ** when the Index structure itself is cleaned up.  */
  if( !pIdx->zColAff ){
    sqlite4 *db = sqlite4VdbeDb(v);
    Table *pTab = pIdx->pTable;   /* Table pIdx is attached to */
    int n;                        /* Iterator variable for zAff */
    Index *pPk;                   /* Primary key on same table as pIdx */
    Index *p;                     /* Iterator variable */
    char *zAff;                   /* Affinity string to populate and return */
    int nAff;                     /* Characters in zAff */

    /* Determine how many characters are in the affinity string. There is
    ** one character for each indexed column, and, if the index is not itself
    ** the primary key, one character for each column in the primary key
    ** of the table pIdx indexes.  */ 
    nAff = pIdx->nColumn;
    pPk = sqlite4FindPrimaryKey(pTab, 0);
    if( pPk && pIdx!=pPk ){
      nAff += pPk->nColumn;
    }

    /* Allocate space for the affinity string */
    zAff = pIdx->zColAff = (char *)sqlite4DbMallocRaw(0, nAff+1);
    if( !zAff ){
      db->mallocFailed = 1;
      return 0;
    }

    /* Populate the affinity string. This loop runs either once or twice.
    ** The first iteration populates zAff with affinities according to the
    ** columns indexed by pIdx.  If pIdx is not itself the table's primary 
    ** key, then the second iteration of the loop adds the primary key 
    ** columns to zAff.  */
    for(n=0, p=pIdx; p; p=(p==pPk ? (Index*)0 : pPk)){
      int i;
      for(i=0; i<p->nColumn; i++){
        int iCol = p->aiColumn[i];
        zAff[n++] = (iCol<0) ? SQLITE4_AFF_INTEGER : pTab->aCol[iCol].affinity;
      }
    }
    zAff[n] = 0;
  }
 
  return pIdx->zColAff;
}

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for table pTab. A column affinity string has one character
** for each column indexed by the index, according to the affinity of the
** column:
**
**  Character      Column affinity
**  ------------------------------
**  'a'            TEXT
**  'b'            NONE
**  'c'            NUMERIC
**  'd'            INTEGER
**  'e'            REAL
*/
SQLITE4_PRIVATE void sqlite4TableAffinityStr(Vdbe *v, Table *pTab){
  /* The first time a column affinity string for a particular table
  ** is required, it is allocated and populated here. It is then 
  ** stored as a member of the Table structure for subsequent use.
  **
  ** The column affinity string will eventually be deleted by
  ** sqlite4DeleteTable() when the Table structure itself is cleaned up.
  */
  if( !pTab->zColAff ){
    char *zColAff;
    int i;
    sqlite4 *db = sqlite4VdbeDb(v);

    zColAff = (char *)sqlite4DbMallocRaw(0, pTab->nCol+1);
    if( !zColAff ){
      db->mallocFailed = 1;
      return;
    }

    for(i=0; i<pTab->nCol; i++){
      zColAff[i] = pTab->aCol[i].affinity;
    }
    zColAff[pTab->nCol] = '\0';

    pTab->zColAff = zColAff;
  }

  sqlite4VdbeChangeP4(v, -1, pTab->zColAff, P4_TRANSIENT);
}

/*
** Return non-zero if the table pTab in database iDb or any of its indices
** have been opened at any point in the VDBE program beginning at location
** iStartAddr throught the end of the program.  This is used to see if 
** a statement of the form  "INSERT INTO <iDb, pTab> SELECT ..." can 
** run without using temporary table for the results of the SELECT. 
**
** Also return true if the statement accesses the sqlite_kvstore table.
*/
static int readsTable(Parse *p, int iStartAddr, int iDb, Table *pTab){
  Vdbe *v = sqlite4GetVdbe(p);
  int i;
  int iEnd = sqlite4VdbeCurrentAddr(v);
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  VTable *pVTab = IsVirtual(pTab) ? sqlite4GetVTable(p->db, pTab) : 0;
#endif

  for(i=iStartAddr; i<iEnd; i++){
    VdbeOp *pOp = sqlite4VdbeGetOp(v, i);
    assert( pOp!=0 );
    if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){
      Index *pIndex;
      int tnum = pOp->p2;
      if( tnum==KVSTORE_ROOT ) return 1;
      for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
        if( tnum==pIndex->tnum ){
          return 1;
        }
      }
    }
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    if( pOp->opcode==OP_VOpen && pOp->p4.pVtab==pVTab ){
      assert( pOp->p4.pVtab!=0 );
      assert( pOp->p4type==P4_VTAB );
      return 1;
    }
#endif
  }
  return 0;
}

#ifndef SQLITE4_OMIT_AUTOINCREMENT
/*
** Locate or create an AutoincInfo structure associated with table pTab
** which is in database iDb.  Return the register number for the register
** that holds the maximum rowid.
**
** There is at most one AutoincInfo structure per table even if the
** same table is autoincremented multiple times due to inserts within
** triggers.  A new AutoincInfo structure is created if this is the
** first use of table pTab.  On 2nd and subsequent uses, the original
** AutoincInfo structure is used.
**
** Three memory locations are allocated:
**
**   (1)  Register to hold the name of the pTab table.
**   (2)  Register to hold the maximum ROWID of pTab.
**   (3)  Register to hold the rowid in sqlite_sequence of pTab
**
** The 2nd register is the one that is returned.  That is all the
** insert routine needs to know about.
*/
static int autoIncBegin(
  Parse *pParse,      /* Parsing context */
  int iDb,            /* Index of the database holding pTab */
  Table *pTab         /* The table we are writing to */
){
  int memId = 0;      /* Register holding maximum rowid */
  if( pTab->tabFlags & TF_Autoincrement ){
    Parse *pToplevel = sqlite4ParseToplevel(pParse);
    AutoincInfo *pInfo;

    pInfo = pToplevel->pAinc;
    while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
    if( pInfo==0 ){
      pInfo = sqlite4DbMallocRaw(pParse->db, sizeof(*pInfo));
      if( pInfo==0 ) return 0;
      pInfo->pNext = pToplevel->pAinc;
      pToplevel->pAinc = pInfo;
      pInfo->pTab = pTab;
      pInfo->iDb = iDb;
      pToplevel->nMem++;                  /* Register to hold name of table */
      pInfo->regCtr = ++pToplevel->nMem;  /* Max rowid register */
      pToplevel->nMem++;                  /* Rowid in sqlite_sequence */
    }
    memId = pInfo->regCtr;
  }
  return memId;
}

/*
** This routine generates code that will initialize all of the
** register used by the autoincrement tracker.  
*/
SQLITE4_PRIVATE void sqlite4AutoincrementBegin(Parse *pParse){
  AutoincInfo *p;            /* Information about an AUTOINCREMENT */
  sqlite4 *db = pParse->db;  /* The database connection */
  Db *pDb;                   /* Database only autoinc table */
  int memId;                 /* Register holding max rowid */
  int addr;                  /* A VDBE address */
  Vdbe *v = pParse->pVdbe;   /* VDBE under construction */

  /* This routine is never called during trigger-generation.  It is
  ** only called from the top-level */
  assert( pParse->pTriggerTab==0 );
  assert( pParse==sqlite4ParseToplevel(pParse) );

  assert( v );   /* We failed long ago if this is not so */
  for(p = pParse->pAinc; p; p = p->pNext){
    pDb = &db->aDb[p->iDb];
    memId = p->regCtr;
    sqlite4OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
    sqlite4VdbeAddOp3(v, OP_Null, 0, memId, memId+1);
    addr = sqlite4VdbeCurrentAddr(v);
    sqlite4VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0);
    sqlite4VdbeAddOp2(v, OP_Rewind, 0, addr+9);
    sqlite4VdbeAddOp3(v, OP_Column, 0, 0, memId);
    sqlite4VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId);
    sqlite4VdbeChangeP5(v, SQLITE4_JUMPIFNULL);
    sqlite4VdbeAddOp2(v, OP_Rowid, 0, memId+1);
    sqlite4VdbeAddOp3(v, OP_Column, 0, 1, memId);
    sqlite4VdbeAddOp2(v, OP_Goto, 0, addr+9);
    sqlite4VdbeAddOp2(v, OP_Next, 0, addr+2);
    sqlite4VdbeAddOp2(v, OP_Integer, 0, memId);
    sqlite4VdbeAddOp0(v, OP_Close);
  }
}

/*
** Update the maximum rowid for an autoincrement calculation.
**
** This routine should be called when the top of the stack holds a
** new rowid that is about to be inserted.  If that new rowid is
** larger than the maximum rowid in the memId memory cell, then the
** memory cell is updated.  The stack is unchanged.
*/
static void autoIncStep(Parse *pParse, int memId, int regRowid){
  if( memId>0 ){
    sqlite4VdbeAddOp2(pParse->pVdbe, OP_MemMax, memId, regRowid);
  }
}

/*
** This routine generates the code needed to write autoincrement
** maximum rowid values back into the sqlite_sequence register.
** Every statement that might do an INSERT into an autoincrement
** table (either directly or through triggers) needs to call this
** routine just before the "exit" code.
*/
SQLITE4_PRIVATE void sqlite4AutoincrementEnd(Parse *pParse){
  AutoincInfo *p;
  Vdbe *v = pParse->pVdbe;
  sqlite4 *db = pParse->db;

  assert( v );
  for(p = pParse->pAinc; p; p = p->pNext){
    Db *pDb = &db->aDb[p->iDb];
    int j1, j2, j3, j4, j5;
    int iRec;
    int memId = p->regCtr;

    iRec = sqlite4GetTempReg(pParse);
    sqlite4OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
    j1 = sqlite4VdbeAddOp1(v, OP_NotNull, memId+1);
    j2 = sqlite4VdbeAddOp0(v, OP_Rewind);
    j3 = sqlite4VdbeAddOp3(v, OP_Column, 0, 0, iRec);
    j4 = sqlite4VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec);
    sqlite4VdbeAddOp2(v, OP_Next, 0, j3);
    sqlite4VdbeJumpHere(v, j2);
    sqlite4VdbeAddOp2(v, OP_NewRowid, 0, memId+1);
    j5 = sqlite4VdbeAddOp0(v, OP_Goto);
    sqlite4VdbeJumpHere(v, j4);
    sqlite4VdbeAddOp2(v, OP_Rowid, 0, memId+1);
    sqlite4VdbeJumpHere(v, j1);
    sqlite4VdbeJumpHere(v, j5);
    sqlite4VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1);
    sqlite4VdbeAddOp0(v, OP_Close);
    sqlite4ReleaseTempReg(pParse, iRec);
  }
}
#else
/*
** If SQLITE4_OMIT_AUTOINCREMENT is defined, then the three routines
** above are all no-ops
*/
# define autoIncBegin(A,B,C) (0)
# define autoIncStep(A,B,C)
#endif /* SQLITE4_OMIT_AUTOINCREMENT */


/* Forward declaration */
/*static FIXME: make static when this function gets used. */ int xferOptimization(
  Parse *pParse,        /* Parser context */
  Table *pDest,         /* The table we are inserting into */
  Select *pSelect,      /* A SELECT statement to use as the data source */
  int onError,          /* How to handle constraint errors */
  int iDbDest           /* The database of pDest */
);

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
**    insert into TABLE (IDLIST) select
**
** The IDLIST following the table name is always optional.  If omitted,
** then a list of all columns for the table is substituted.  The IDLIST
** appears in the pColumn parameter.  pColumn is NULL if IDLIST is omitted.
**
** The pList parameter holds EXPRLIST in the first form of the INSERT
** statement above, and pSelect is NULL.  For the second form, pList is
** NULL and pSelect is a pointer to the select statement used to generate
** data for the insert.
**
** The code generated follows one of four templates.  For a simple
** select with data coming from a VALUES clause, the code executes
** once straight down through.  Pseudo-code follows (we call this
** the "1st template"):
**
**         open write cursor to <table> and its indices
**         puts VALUES clause expressions onto the stack
**         write the resulting record into <table>
**         cleanup
**
** The three remaining templates assume the statement is of the form
**
**   INSERT INTO <table> SELECT ...
**
** If the SELECT clause is of the restricted form "SELECT * FROM <table2>" -
** in other words if the SELECT pulls all columns from a single table
** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and
** if <table2> and <table1> are distinct tables but have identical
** schemas, including all the same indices, then a special optimization
** is invoked that copies raw records from <table2> over to <table1>.
** See the xferOptimization() function for the implementation of this
** template.  This is the 2nd template.
**
**         open a write cursor to <table>
**         open read cursor on <table2>
**         transfer all records in <table2> over to <table>
**         close cursors
**         foreach index on <table>
**           open a write cursor on the <table> index
**           open a read cursor on the corresponding <table2> index
**           transfer all records from the read to the write cursors
**           close cursors
**         end foreach
**
** The 3rd template is for when the second template does not apply
** and the SELECT clause does not read from <table> at any time.
** The generated code follows this template:
**
**         EOF <- 0
**         X <- A
**         goto B
**      A: setup for the SELECT
**         loop over the rows in the SELECT
**           load values into registers R..R+n
**           yield X
**         end loop
**         cleanup after the SELECT
**         EOF <- 1
**         yield X
**         goto A
**      B: open write cursor to <table> and its indices
**      C: yield X
**         if EOF goto D
**         insert the select result into <table> from R..R+n
**         goto C
**      D: cleanup
**
** The 4th template is used if the insert statement takes its
** values from a SELECT but the data is being inserted into a table
** that is also read as part of the SELECT.  In the third form,
** we have to use a intermediate table to store the results of
** the select.  The template is like this:
**
**         EOF <- 0
**         X <- A
**         goto B
**      A: setup for the SELECT
**         loop over the tables in the SELECT
**           load value into register R..R+n
**           yield X
**         end loop
**         cleanup after the SELECT
**         EOF <- 1
**         yield X
**         halt-error
**      B: open temp table
**      L: yield X
**         if EOF goto M
**         insert row from R..R+n into temp table
**         goto L
**      M: open write cursor to <table> and its indices
**         rewind temp table
**      C: loop over rows of intermediate table
**           transfer values form intermediate table into <table>
**         end loop
**      D: cleanup
*/
SQLITE4_PRIVATE void sqlite4Insert(
  Parse *pParse,        /* Parser context */
  SrcList *pTabList,    /* Name of table into which we are inserting */
  ExprList *pList,      /* List of values to be inserted */
  Select *pSelect,      /* A SELECT statement to use as the data source */
  IdList *pColumn,      /* Column names corresponding to IDLIST. */
  int onError           /* How to handle constraint errors */
){
  sqlite4 *db;          /* The main database structure */
  Table *pTab;          /* The table to insert into.  aka TABLE */
  char *zTab;           /* Name of the table into which we are inserting */
  const char *zDb;      /* Name of the database holding this table */
  int i, j, idx;        /* Loop counters */
  Vdbe *v;              /* Generate code into this virtual machine */
  Index *pIdx;          /* For looping over indices of the table */
  int nColumn;          /* Number of columns in the data */
  int nHidden = 0;      /* Number of hidden columns if TABLE is virtual */
  int baseCur = 0;      /* VDBE Cursor number for pTab */
  int endOfLoop;        /* Label for the end of the insertion loop */
  int useTempTable = 0; /* Store SELECT results in intermediate table */
  int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */
  int addrInsTop = 0;   /* Jump to label "D" */
  int addrCont = 0;     /* Top of insert loop. Label "C" in templates 3 and 4 */
  int addrSelect = 0;   /* Address of coroutine that implements the SELECT */
  SelectDest dest;      /* Destination for SELECT on rhs of INSERT */
  int iDb;              /* Index of database holding TABLE */
  Db *pDb;              /* The database containing table being inserted into */
  int appendFlag = 0;   /* True if the insert is likely to be an append */
  int iPk;              /* Cursor offset of PK index cursor */
  Index *pPk;           /* Primary key for table pTab */
  int iIntPKCol = -1;   /* Column of INTEGER PRIMARY KEY or -1 */
  int bImplicitPK;      /* True if table pTab has an implicit PK */

  /* Register allocations */
  int regFromSelect = 0;/* Base register for data coming from SELECT */
  int regEof = 0;       /* Register recording end of SELECT data */
  int *aRegIdx = 0;     /* One register allocated to each index */
  int regContent;       /* First register in column value array */
  int regRowid;         /* If bImplicitPK, register holding IPK */
  int regAutoinc;       /* Register holding the AUTOINCREMENT counter */

#ifndef SQLITE4_OMIT_TRIGGER
  int isView;                 /* True if attempting to insert into a view */
  Trigger *pTrigger;          /* List of triggers on pTab, if required */
  int tmask;                  /* Mask of trigger times */
#endif

  db = pParse->db;
  memset(&dest, 0, sizeof(dest));
  if( pParse->nErr || db->mallocFailed ){
    goto insert_cleanup;
  }

  /* Locate the table into which we will be inserting new information. */
  assert( pTabList->nSrc==1 );
  zTab = pTabList->a[0].zName;
  if( NEVER(zTab==0) ) goto insert_cleanup;
  pTab = sqlite4SrcListLookup(pParse, pTabList);
  if( pTab==0 ){
    goto insert_cleanup;
  }
  iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  assert( iDb<db->nDb );
  pDb = &db->aDb[iDb];
  zDb = pDb->zName;
  if( sqlite4AuthCheck(pParse, SQLITE4_INSERT, pTab->zName, 0, zDb) ){
    goto insert_cleanup;
  }

  /* Set bImplicitPK to true for an implicit PRIMARY KEY, or false otherwise.
  ** Also set pPk to point to the primary key, and iPk to the cursor offset
  ** of the primary key cursor (i.e. so that the cursor opened on the primary
  ** key index is VDBE cursor (baseCur+iPk).  */
  pPk = sqlite4FindPrimaryKey(pTab, &iPk);
  assert( (pPk==0)==IsView(pTab) );
  if( pPk ){
    bImplicitPK = pPk->aiColumn[0]==(-1);
    if( pPk->fIndex & IDX_IntPK ){
      assert( pPk->nColumn==1 );
      iIntPKCol = pPk->aiColumn[0];
    }
  }else{
    bImplicitPK = 0;
  }
      

  /* Figure out if we have any triggers and if the table being
  ** inserted into is a view. */
#ifndef SQLITE4_OMIT_TRIGGER
  pTrigger = sqlite4TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
  isView = pTab->pSelect!=0;
#else
# define pTrigger 0
# define tmask 0
# define isView 0
#endif
#ifdef SQLITE4_OMIT_VIEW
# undef isView
# define isView 0
#endif
  assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );

  /* If pTab is really a view, make sure it has been initialized.
  ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual 
  ** module table).  */
  if( sqlite4ViewGetColumnNames(pParse, pTab) ){
    goto insert_cleanup;
  }

  /* Ensure that:
  **   (a) the table is not read-only (e.g. sqlite_master, sqlite_stat), and
  **   (b) that if it is a view then ON INSERT triggers exist
  */
  if( sqlite4IsReadOnly(pParse, pTab, tmask) ){
    goto insert_cleanup;
  }

  /* Allocate a VDBE and begin a write transaction */
  v = sqlite4GetVdbe(pParse);
  if( v==0 ) goto insert_cleanup;
  if( pParse->nested==0 ) sqlite4VdbeCountChanges(v);
  sqlite4BeginWriteOperation(pParse, pSelect || pTrigger, iDb);

  /* If this is an AUTOINCREMENT table, look up the sequence number in the
  ** sqlite_sequence table and store it in memory cell regAutoinc.
  */
  regAutoinc = autoIncBegin(pParse, iDb, pTab);

  /* Figure out how many columns of data are supplied.  If the data
  ** is coming from a SELECT statement, then generate a co-routine that
  ** produces a single row of the SELECT on each invocation.  The
  ** co-routine is the common header to the 3rd and 4th templates.
  */
  if( pSelect ){
    /* Data is coming from a SELECT.  Generate code to implement that SELECT
    ** as a co-routine.  The code is common to both the 3rd and 4th
    ** templates:
    **
    **         EOF <- 0
    **         X <- A
    **         goto B
    **      A: setup for the SELECT
    **         loop over the tables in the SELECT
    **           load value into register R..R+n
    **           yield X
    **         end loop
    **         cleanup after the SELECT
    **         EOF <- 1
    **         yield X
    **         halt-error
    **
    ** On each invocation of the co-routine, it puts a single row of the
    ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1.
    ** (These output registers are allocated by sqlite4Select().)  When
    ** the SELECT completes, it sets the EOF flag stored in regEof.
    */
    int rc, j1;

    regEof = ++pParse->nMem;
    sqlite4VdbeAddOp2(v, OP_Integer, 0, regEof);      /* EOF <- 0 */
    VdbeComment((v, "SELECT eof flag"));
    sqlite4SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem);
    addrSelect = sqlite4VdbeCurrentAddr(v)+2;
    sqlite4VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iParm);
    j1 = sqlite4VdbeAddOp2(v, OP_Goto, 0, 0);
    VdbeComment((v, "Jump over SELECT coroutine"));

    /* Resolve the expressions in the SELECT statement and execute it. */
    rc = sqlite4Select(pParse, pSelect, &dest);
    assert( pParse->nErr==0 || rc );
    if( rc || NEVER(pParse->nErr) || db->mallocFailed ){
      goto insert_cleanup;
    }
    sqlite4VdbeAddOp2(v, OP_Integer, 1, regEof);         /* EOF <- 1 */
    sqlite4VdbeAddOp1(v, OP_Yield, dest.iParm);   /* yield X */
    sqlite4VdbeAddOp2(v, OP_Halt, SQLITE4_INTERNAL, OE_Abort);
    VdbeComment((v, "End of SELECT coroutine"));
    sqlite4VdbeJumpHere(v, j1);                          /* label B: */

    regFromSelect = dest.iMem;
    assert( pSelect->pEList );
    nColumn = pSelect->pEList->nExpr;
    assert( dest.nMem==nColumn );

    /* Set useTempTable to TRUE if the result of the SELECT statement
    ** should be written into a temporary table (template 4).  Set to
    ** FALSE if each* row of the SELECT can be written directly into
    ** the destination table (template 3).
    **
    ** A temp table must be used if the table being updated is also one
    ** of the tables being read by the SELECT statement.  Also use a 
    ** temp table in the case of row triggers.
    */
    if( pTrigger 
     || IsKvstore(pTab) 
     || readsTable(pParse, addrSelect, iDb, pTab) 
    ){
      useTempTable = 1;
    }

    if( useTempTable ){
      /* Invoke the coroutine to extract information from the SELECT
      ** and add it to a transient table srcTab.  The code generated
      ** here is from the 4th template:
      **
      **      B: open temp table
      **      L: yield X
      **         if EOF goto M
      **         insert row from R..R+n into temp table
      **         goto L
      **      M: ...
      */
      int regRec;          /* Register to hold packed record */
      int regTempRowid;    /* Register to hold temp table ROWID */
      int addrTop;         /* Label "L" */
      int addrIf;          /* Address of jump to M */

      srcTab = pParse->nTab++;
      regRec = sqlite4GetTempReg(pParse);
      regTempRowid = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
      addrTop = sqlite4VdbeAddOp1(v, OP_Yield, dest.iParm);
      addrIf = sqlite4VdbeAddOp1(v, OP_If, regEof);
      sqlite4VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
      sqlite4VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
      sqlite4VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
      sqlite4VdbeAddOp2(v, OP_Goto, 0, addrTop);
      sqlite4VdbeJumpHere(v, addrIf);
      sqlite4ReleaseTempReg(pParse, regRec);
      sqlite4ReleaseTempReg(pParse, regTempRowid);
    }
  }else{
    /* This is the case if the data for the INSERT is coming from a VALUES
    ** (or DEFAULT VALUES) clause. Resolve all references in the VALUES(...)
    ** expressions.  */ 
    NameContext sNC;
    memset(&sNC, 0, sizeof(sNC));
    sNC.pParse = pParse;
    srcTab = -1;
    assert( useTempTable==0 );
    nColumn = pList ? pList->nExpr : 0;
    for(i=0; i<nColumn; i++){
      if( sqlite4ResolveExprNames(&sNC, pList->a[i].pExpr) ){
        goto insert_cleanup;
      }
    }
  }

  /* Make sure the number of columns in the source data matches the number
  ** of columns to be inserted into the table.
  */
  if( IsVirtual(pTab) ){
    for(i=0; i<pTab->nCol; i++){
      nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
    }
  }
  if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
    sqlite4ErrorMsg(pParse,
       "table %S has %d columns but %d values were supplied",
       pTabList, 0, pTab->nCol-nHidden, nColumn);
    goto insert_cleanup;
  }
  if( pColumn!=0 && nColumn!=pColumn->nId ){
    sqlite4ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
    goto insert_cleanup;
  }

  /* If the INSERT statement included an IDLIST term, then make sure
  ** all elements of the IDLIST really are columns of the table. Set
  ** the pColumn->a[iCol].idx variables to indicate which column of the
  ** table each IDLIST element corresponds to.
  */
  if( pColumn ){
    for(i=0; i<pColumn->nId; i++){
      pColumn->a[i].idx = -1;
    }
    for(i=0; i<pColumn->nId; i++){
      char *zTest = pColumn->a[i].zName;
      for(j=0; j<pTab->nCol; j++){
        if( sqlite4_stricmp(zTest, pTab->aCol[j].zName)==0 ){
          pColumn->a[i].idx = j;
          break;
        }
      }
      if( j==pTab->nCol ){
        sqlite4ErrorMsg(pParse, "table %S has no column named %s",
              pTabList, 0, pColumn->a[i].zName);
        pParse->checkSchema = 1;
        goto insert_cleanup;
      }
    }
  }

  /* If this is not a view, open a write cursor on each index. Allocate
  ** a contiguous array of (nIdx+1) registers, where nIdx is the total
  ** number of indexes (including the PRIMARY KEY index). 
  **
  **   Register aRegIdx[0]:         The PRIMARY KEY index key
  **   Register aRegIdx[1..nIdx-1]: Keys for other table indexes 
  **   Register aRegIdx[nIdx]:      Data record for table row.
  */
  if( !isView ){
    int nIdx;

    baseCur = pParse->nTab;
    nIdx = sqlite4OpenAllIndexes(pParse, pTab, baseCur, OP_OpenWrite);
    aRegIdx = sqlite4DbMallocRaw(db, sizeof(int)*(nIdx+1));
    if( aRegIdx==0 ){
      goto insert_cleanup;
    }
    for(i=0; i<nIdx; i++){
      aRegIdx[i] = ++pParse->nMem;  /* Register in which to store key */
      pParse->nMem++;               /* Extra register for data */
    }
  }

  /* This is the top of the main insertion loop */
  if( useTempTable ){
    /* This block codes the top of loop only.  The complete loop is the
    ** following pseudocode (template 4):
    **
    **         rewind temp table
    **      C: loop over rows of intermediate table
    **           transfer values form intermediate table into <table>
    **         end loop
    **      D: ...
    */
    addrInsTop = sqlite4VdbeAddOp1(v, OP_Rewind, srcTab);
    addrCont = sqlite4VdbeCurrentAddr(v);
  }else if( pSelect ){
    /* This block codes the top of loop only.  The complete loop is the
    ** following pseudocode (template 3):
    **
    **      C: yield X
    **         if EOF goto D
    **         insert the select result into <table> from R..R+n
    **         goto C
    **      D: ...
    */
    addrCont = sqlite4VdbeAddOp1(v, OP_Yield, dest.iParm);
    addrInsTop = sqlite4VdbeAddOp1(v, OP_If, regEof);
  }

  /* Allocate an array of registers in which to assemble the values for the
  ** new row. If the table has an explicit primary key, we need one register
  ** for each table column. If the table uses an implicit primary key, then
  ** nCol+1 registers are required.  */
  regRowid = ++pParse->nMem;
  regContent = pParse->nMem+1;
  pParse->nMem += pTab->nCol;

  if( IsVirtual(pTab) ){
    /* TODO: Fix this */
    regContent++;
    regRowid++;
    pParse->nMem++;
  }

  endOfLoop = sqlite4VdbeMakeLabel(v);

  for(i=0; i<pTab->nCol; i++){
    int regDest = regContent+i;
    j = i;
    if( pColumn ){
      for(j=0; j<pColumn->nId; j++){
        if( pColumn->a[j].idx==i ) break;
      }
    }

    if( nColumn==0 || (pColumn && j>=pColumn->nId) ){
      sqlite4ExprCode(pParse, pTab->aCol[i].pDflt, regDest);
    }else if( useTempTable ){
      sqlite4VdbeAddOp3(v, OP_Column, srcTab, j, regDest);
    }else if( pSelect ){
      sqlite4VdbeAddOp2(v, OP_SCopy, regFromSelect+j, regDest);
    }else{
      assert( pSelect==0 ); /* Otherwise useTempTable is true */
      sqlite4ExprCodeAndCache(pParse, pList->a[j].pExpr, regDest);
    }
  }

  if( !isView ){
    sqlite4VdbeAddOp2(v, OP_Affinity, regContent, pTab->nCol);
    sqlite4TableAffinityStr(v, pTab);
  }

  /* Fire BEFORE or INSTEAD OF triggers */
  if( pTrigger ){
    sqlite4VdbeAddOp2(v, OP_Integer, -1, regRowid);
    VdbeComment((v, "new.rowid value for BEFORE triggers"));
    sqlite4CodeRowTrigger(
        pParse, pTrigger, TK_INSERT, 0, TRIGGER_BEFORE, 
        pTab, (regRowid - pTab->nCol - 1), onError, endOfLoop
    );
  }

  if( iIntPKCol>=0 ){
    int regDest = regContent+iIntPKCol;
    int a1;
    a1 = sqlite4VdbeAddOp1(v, OP_NotNull, regDest);
    sqlite4VdbeAddOp3(v, OP_NewRowid, baseCur, regDest, regAutoinc);
    sqlite4VdbeJumpHere(v, a1);
    autoIncStep(pParse, regAutoinc, regDest);
  }

  if( bImplicitPK ){
    assert( !isView );
    sqlite4VdbeAddOp2(v, OP_NewRowid, baseCur+iPk, regRowid);
  }

  if( !isView ){
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    if( IsVirtual(pTab) ){
      const char *pVTab = (const char *)sqlite4GetVTable(db, pTab);
      sqlite4VtabMakeWritable(pParse, pTab);
      sqlite4VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
      sqlite4VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
      sqlite4MayAbort(pParse);
    }else
#endif
    {
      /* Generate code to check constraints and generate index keys and
      ** do the insertion.  */
      int isReplace;    /* Set to true if constraints may cause a replace */
      sqlite4GenerateConstraintChecks(pParse, pTab, baseCur, 
          regContent, aRegIdx, 0, 0, onError, endOfLoop, &isReplace
      );
      sqlite4FkCheck(pParse, pTab, 0, regContent);
      sqlite4CompleteInsertion(pParse, pTab, baseCur, 
          regContent, aRegIdx, 0, appendFlag, isReplace==0
      );
    }
  }

  /* Code AFTER triggers */
  sqlite4CodeRowTrigger(
      pParse, pTrigger, TK_INSERT, 0, TRIGGER_AFTER, 
      pTab, regRowid - pTab->nCol - 1, onError, endOfLoop
  );

  /* The bottom of the main insertion loop, if the data source
  ** is a SELECT statement.
  */
  sqlite4VdbeResolveLabel(v, endOfLoop);
  if( useTempTable ){
    sqlite4VdbeAddOp2(v, OP_Next, srcTab, addrCont);
    sqlite4VdbeJumpHere(v, addrInsTop);
    sqlite4VdbeAddOp1(v, OP_Close, srcTab);
  }else if( pSelect ){
    sqlite4VdbeAddOp2(v, OP_Goto, 0, addrCont);
    sqlite4VdbeJumpHere(v, addrInsTop);
  }

  if( !IsVirtual(pTab) && !isView ){
    /* Close all tables opened */
    for(idx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
      sqlite4VdbeAddOp1(v, OP_Close, idx+baseCur);
    }
  }

  /* Update the sqlite_sequence table by storing the content of the
  ** maximum rowid counter values recorded while inserting into
  ** autoincrement tables.
  */
  if( pParse->nested==0 && pParse->pTriggerTab==0 ){
    sqlite4AutoincrementEnd(pParse);
  }

insert_cleanup:
  sqlite4SrcListDelete(db, pTabList);
  sqlite4ExprListDelete(db, pList);
  sqlite4SelectDelete(db, pSelect);
  sqlite4IdListDelete(db, pColumn);
  sqlite4DbFree(db, aRegIdx);
}

/* Make sure "isView" and other macros defined above are undefined. Otherwise
** thely may interfere with compilation of other functions in this file
** (or in another file, if this file becomes part of the amalgamation).  */
#ifdef isView
 #undef isView
#endif
#ifdef pTrigger
 #undef pTrigger
#endif
#ifdef tmask
 #undef tmask
#endif

/*
** Return the name of the iCol'th column in index pIdx.
*/
const char *indexColumnName(Index *pIdx, int iCol){
  int iTbl = pIdx->aiColumn[iCol];
  assert( iTbl>=-1 && iTbl<pIdx->pTable->nCol );
  if( iTbl<0 ){
    assert( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY && pIdx->nColumn==1 );
    return "rowid";
  }
  return pIdx->pTable->aCol[iTbl].zName;
}

static void generateNotNullChecks(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table to generate checks for */
  int regContent,                 /* Index of the range of input registers */
  int overrideError,              /* Override default OE_* with this */
  int ignoreDest                  /* Jump to this lable if OE_Ignore */
){
  Vdbe *v = pParse->pVdbe;
  int i;

  for(i=0; i<pTab->nCol; i++){
    int onError = pTab->aCol[i].notNull;
    if( onError ){
      if( overrideError!=OE_Default ){
        onError = overrideError;
      }else if( onError==OE_Default ){
        onError = OE_Abort;
      }
      if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
        onError = OE_Abort;
      }

      switch( onError ){
        case OE_Abort:
          sqlite4MayAbort(pParse);
        case OE_Rollback:
        case OE_Fail: {
          char *zMsg = sqlite4MPrintf(pParse->db, "%s.%s may not be NULL",
              pTab->zName, pTab->aCol[i].zName
          );
          sqlite4VdbeAddOp4(v, OP_HaltIfNull, 
              SQLITE4_CONSTRAINT, onError, regContent+i, zMsg, P4_DYNAMIC
          );
          break;
        }

        case OE_Ignore:
          sqlite4VdbeAddOp2(v, OP_IsNull, regContent+i, ignoreDest);
          break;

        default: {
          int j1 = sqlite4VdbeAddOp1(v, OP_NotNull, regContent+i);
          sqlite4ExprCode(pParse, pTab->aCol[i].pDflt, regContent+i);
          sqlite4VdbeJumpHere(v, j1);
          assert( onError==OE_Replace );
          break;
        }
      }
    }
  }
}

#ifndef SQLITE4_OMIT_CHECK
static void generateCheckChecks(
  Parse *pParse,                  /* Parse context */
  Table *pTab,                    /* Table to generate checks for */
  int regContent,                 /* Index of the range of input registers */
  int overrideError,              /* Override default OE_* with this */
  int ignoreDest                  /* Jump to this lable if OE_Ignore */
){
  Vdbe *v = pParse->pVdbe;

  if( pTab->pCheck && (pParse->db->flags & SQLITE4_IgnoreChecks)==0 ){
    int onError;
    int allOk = sqlite4VdbeMakeLabel(v);
    pParse->ckBase = regContent;
    sqlite4ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE4_JUMPIFNULL);
    onError = overrideError!=OE_Default ? overrideError : OE_Abort;
    if( onError==OE_Ignore ){
      sqlite4VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
    }else{
      if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
      sqlite4HaltConstraint(pParse, onError, 0, 0);
    }
    sqlite4VdbeResolveLabel(v, allOk);
  }
}
#else /* !defined(SQLITE4_OMIT_CHECK) */
# define generateCheckChecks(a,b,c,d,e)
#endif

/*
** Locate the primary key index for a table.
*/
SQLITE4_PRIVATE Index *sqlite4FindPrimaryKey(
  Table *pTab,                    /* Table to locate primary key for */
  int *piPk                       /* OUT: Index of PRIMARY KEY */
){
  Index *p;
  int iPk = 0;
  for(p=pTab->pIndex; p && p->eIndexType!=SQLITE4_INDEX_PRIMARYKEY; p=p->pNext){
    iPk++;
  }
  if( piPk ) *piPk = iPk;
  return p;
}

/*
** Index pIdx is a UNIQUE index. This function returns a pointer to a buffer
** containing an error message to tell the user that the UNIQUE constraint
** has failed.
**
** The returned buffer should be freed by the caller using sqlite4DbFree().
*/
static char *notUniqueMessage(
  Parse *pParse,                  /* Parse context */
  Index *pIdx                     /* Index to generate error message for */
){
  const int nCol = pIdx->nColumn; /* Number of columns indexed by pIdx */
  StrAccum errMsg;                /* Buffer to build error message within */
  int iCol;                       /* Used to iterate through indexed columns */

  sqlite4StrAccumInit(&errMsg, 0, 0, 200);
  errMsg.db = pParse->db;
  errMsg.pEnv = errMsg.db->pEnv;
  if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){
    sqlite4StrAccumAppend(&errMsg, "PRIMARY KEY must be unique", -1);
  }else{
    sqlite4StrAccumAppend(&errMsg, (nCol>1 ? "columns " : "column "), -1);
    for(iCol=0; iCol<pIdx->nColumn; iCol++){
      const char *zCol = indexColumnName(pIdx, iCol);
      sqlite4StrAccumAppend(&errMsg, (iCol==0 ? "" : ", "), -1);
      sqlite4StrAccumAppend(&errMsg, zCol, -1);
    }
    sqlite4StrAccumAppend(&errMsg, (nCol>1 ? " are" : " is"), -1);
    sqlite4StrAccumAppend(&errMsg, " not unique", -1);
  }
  return sqlite4StrAccumFinish(&errMsg);
}

/*
** This function generates code used as part of both INSERT and UPDATE
** statements. The generated code performs two tasks:
**
**   1. Checks all NOT NULL, CHECK and UNIQUE database constraints, 
**      including the implicit NOT NULL and UNIQUE constraints imposed
**      by the PRIMARY KEY definition.
**
**   2. Generates serialized index keys (using OP_MakeKey) for the caller
**      to store in database indexes. This function does not encode the
**      actual data record, just the index keys.
**
** Both INSERT and UPDATE use this function in concert with the
** sqlite4CompleteInsertion(). This function does as described above, and
** then CompleteInsertion() generates code to serialize the data record 
** and do the actual inserts into the database.
**
** regContent:
**   The first in an array of registers that contain the column values
**   for the new row. Register regContent contains the value for the 
**   left-most table column, (regContent+1) contains the value for the next 
**   column, and so on. All entries in this array have had any required
**   affinity transformations applied already. All zero-blobs have been 
**   expanded.
**
**   If the table has an implicit primary key and aRegIdx[0] is not 0 (see
**   below), register (regContent-1) is also valid. It contains the new 
**   implicit integer PRIMARY KEY value.
**
** aRegIdx:
**   Array sized so that there is one entry for each index (including the
**   PK index) attached to the database table. Entries are in the same order
**   as the linked list of Index structures attached to the table. 
**
**   If an array entry is non-zero, it contains the register that the 
**   corresponding index key should be written to. If an entry is zero, then
**   the corresponding index key is not required by the caller. In this case
**   any UNIQUE constraint enforced by the index does not need to be checked.
**
** 
**
** Generate code to do constraint checks prior to an INSERT or an UPDATE.
**
** The input is a range of consecutive registers as follows:
**
**    1.  The rowid of the row after the update.
**
**    2.  The data in the first column of the entry after the update.
**
**    i.  Data from middle columns...
**
**    N.  The data in the last column of the entry after the update.
**
** The regRowid parameter is the index of the register containing (1).
**
** If isUpdate is true and rowidChng is non-zero, then rowidChng contains
** the address of a register containing the rowid before the update takes
** place. isUpdate is true for UPDATEs and false for INSERTs. If isUpdate
** is false, indicating an INSERT statement, then a non-zero rowidChng 
** indicates that the rowid was explicitly specified as part of the
** INSERT statement. If rowidChng is false, it means that  the rowid is
** computed automatically in an insert or that the rowid value is not 
** modified by an update.
**
** The code generated by this routine store new index entries into
** registers identified by aRegIdx[].  No index entry is created for
** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is
** the same as the order of indices on the linked list of indices
** attached to the table.
**
** This routine also generates code to check constraints.  NOT NULL,
** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
** then the appropriate action is performed.  There are five possible
** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
**
**  Constraint type  Action       What Happens
**  ---------------  ----------   ----------------------------------------
**  any              ROLLBACK     The current transaction is rolled back and
**                                sqlite4_exec() returns immediately with a
**                                return code of SQLITE4_CONSTRAINT.
**
**  any              ABORT        Back out changes from the current command
**                                only (do not do a complete rollback) then
**                                cause sqlite4_exec() to return immediately
**                                with SQLITE4_CONSTRAINT.
**
**  any              FAIL         Sqlite3_exec() returns immediately with a
**                                return code of SQLITE4_CONSTRAINT.  The
**                                transaction is not rolled back and any
**                                prior changes are retained.
**
**  any              IGNORE       The record number and data is popped from
**                                the stack and there is an immediate jump
**                                to label ignoreDest.
**
**  NOT NULL         REPLACE      The NULL value is replace by the default
**                                value for that column.  If the default value
**                                is NULL, the action is the same as ABORT.
**
**  UNIQUE           REPLACE      The other row that conflicts with the row
**                                being inserted is removed.
**
**  CHECK            REPLACE      Illegal.  The results in an exception.
**
** Which action to take is determined by the overrideError parameter.
** Or if overrideError==OE_Default, then the pParse->onError parameter
** is used.  Or if pParse->onError==OE_Default then the onError value
** for the constraint is used.
**
** The calling routine must open a read/write cursor for pTab with
** cursor number "baseCur".  All indices of pTab must also have open
** read/write cursors with cursor number baseCur+i for the i-th cursor.
** Except, if there is no possibility of a REPLACE action then
** cursors do not need to be open for indices where aRegIdx[i]==0.
*/
SQLITE4_PRIVATE void sqlite4GenerateConstraintChecks(
  Parse *pParse,      /* The parser context */
  Table *pTab,        /* the table into which we are inserting */
  int baseCur,        /* First in array of cursors for pTab indexes */
  int regContent,     /* Index of the range of input registers */
  int *aRegIdx,       /* Register used by each index.  0 for unused indices */
  int regOldKey,      /* For an update, the original encoded PK */
  int isUpdate,       /* True for UPDATE, False for INSERT */
  int overrideError,  /* Override onError to this if not OE_Default */
  int ignoreDest,     /* Jump to this label on an OE_Ignore resolution */
  int *pbMayReplace   /* OUT: Set to true if constraint may cause a replace */
){
  u8 aPkRoot[10];                 /* Root page number for pPk as a varint */ 
  int nPkRoot;                    /* Size of aPkRoot in bytes */
  Index *pPk;                     /* Primary key index for table pTab */
  int i;              /* loop counter */
  Vdbe *v;            /* VDBE under constrution */
  int onError;        /* Conflict resolution strategy */
  int iCur;           /* Table cursor number */
  Index *pIdx;         /* Pointer to one of the indices */
  int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */

  v = sqlite4GetVdbe(pParse);
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  pPk = sqlite4FindPrimaryKey(pTab, 0);
  nPkRoot = sqlite4PutVarint64(aPkRoot, pPk->tnum);

  assert( pPk->eIndexType==SQLITE4_INDEX_PRIMARYKEY );

  /* Test all NOT NULL constraints. */
  generateNotNullChecks(pParse, pTab, regContent, overrideError, ignoreDest);

  /* Test all CHECK constraints */
  generateCheckChecks(pParse, pTab, regContent, overrideError, ignoreDest);

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Add the new records to the indices as we go.
  */
  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
    int nTmpReg;                  /* Number of temp registers required */
    int regTmp;                   /* First temp register allocated */
    int regPk;                    /* PK of conflicting row (for REPLACE) */
    int regKey = aRegIdx[iCur];   /* Write encoded index key for pIdx here */
    int iIdx = baseCur+iCur;      /* Cursor for index pIdx */

    /* If regKey is 0, pIdx will not be updated. */
    if( regKey==0 ) continue;

    /* Create an index key. Primary key indexes consists of just the primary
    ** key values. Other indexes consists of the indexed columns followed by
    ** the primary key values.  */
    if( pIdx->tnum==KVSTORE_ROOT ){
      /* If this is the sqlite_kvstore PK index, interpret the value
      ** specified for column "key" as a blob and use it as the index key. */
      sqlite4VdbeAddOp2(v, OP_SCopy, regContent, regKey);
      sqlite4VdbeAddOp1(v, OP_ToBlob, regKey);
      regPk = regKey;
    }else{
      nTmpReg = 1 + pIdx->nColumn + (pIdx==pPk ? 0 : pPk->nColumn);
      regTmp = sqlite4GetTempRange(pParse, nTmpReg);
      regPk = regTmp + nTmpReg - 1;

      for(i=0; i<pIdx->nColumn; i++){
        int idx = pIdx->aiColumn[i];
        sqlite4VdbeAddOp2(v, OP_SCopy, regContent+idx, regTmp+i);
      }
      if( pIdx!=pPk ){
        for(i=0; i<pPk->nColumn; i++){
          int idx = pPk->aiColumn[i];
          sqlite4VdbeAddOp2(v, OP_SCopy, regContent+idx,regTmp+i+pIdx->nColumn);
        }
      }
      sqlite4VdbeAddOp4Int(v, OP_MakeKey, regTmp, nTmpReg-1, regKey, iIdx);
    }
    VdbeComment((v, "key for %s", pIdx->zName));

    /* If Index.onError==OE_None, then pIdx is not a UNIQUE or PRIMARY KEY 
    ** index. In this case there is no need to test the index for uniqueness
    ** - all that is required is to populate the regKey register. Jump 
    ** to the next iteration of the loop if this is the case.  */
    onError = pIdx->onError;
    if( onError!=OE_None ){
      int iLabel;
     
      /* Figure out what to do if a UNIQUE constraint is encountered. 
      **
      ** TODO: If a previous constraint is a REPLACE, why change IGNORE to
      ** REPLACE and FAIL to ABORT here?  */
      if( overrideError!=OE_Default ){
        onError = overrideError;
      }else if( onError==OE_Default ){
        onError = OE_Abort;
      }
      if( seenReplace ){
        if( onError==OE_Ignore ) onError = OE_Replace;
        else if( onError==OE_Fail ) onError = OE_Abort;
      }

      iLabel = sqlite4VdbeMakeLabel(v);
      if( pIdx!=pPk ){
        sqlite4VdbeAddOp3(v, OP_IsNull, regTmp, iLabel, pIdx->nColumn);
        sqlite4VdbeAddOp4(v, OP_Blob, nPkRoot, regPk, 0,(char*)aPkRoot,nPkRoot);
      }
      if( regOldKey && pIdx==pPk ){
        sqlite4VdbeAddOp3(v, OP_Eq, regOldKey, iLabel, regKey);
      }
      sqlite4VdbeAddOp4Int(v, OP_IsUnique, iIdx, iLabel, regKey, regPk);
      if( regOldKey && pIdx!=pPk ){
        sqlite4VdbeAddOp3(v, OP_Eq, regOldKey, iLabel, regPk);
      }
      
      switch( onError ){
        case OE_Rollback:
        case OE_Abort:
        case OE_Fail: {
          char *zErr = notUniqueMessage(pParse, pIdx);
          sqlite4HaltConstraint(pParse, onError, zErr, 0);
          sqlite4DbFree(pParse->db, zErr);
          break;
        }

        case OE_Ignore: {
          assert( seenReplace==0 );
          sqlite4VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
          break;
        }
        default: {
          Trigger *pTrigger;
          assert( onError==OE_Replace );
          sqlite4MultiWrite(pParse);
          pTrigger = sqlite4TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
          sqlite4GenerateRowDelete(
              pParse, pTab, baseCur, regPk, 0, pTrigger, OE_Replace
          );
          seenReplace = 1;
          break;
        }
      }

      sqlite4VdbeResolveLabel(v, iLabel);
    }

    sqlite4ReleaseTempRange(pParse, regTmp, nTmpReg);
  }
  
  if( pbMayReplace ){
    *pbMayReplace = seenReplace;
  }
}

/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlite4GenerateConstraintChecks.
** The arguments to this routine should be the same as the first six
** arguments to sqlite4GenerateConstraintChecks.
**
** Argument regContent points to the first in a contiguous array of 
** registers that contain the row content. This function uses OP_MakeRecord
** to encode them into a record before inserting them into the database.
**
** The array aRegIdx[] contains one entry for each index attached to
** the table, in the same order as the Table.pIndex linked list. If an
** aRegIdx[] entry is 0, this indicates that the entry in the corresponding
** index does not need to be modified. Otherwise, it is the number of
** a register containing the serialized key to insert into the index.
** aRegIdx[0] (the PRIMARY KEY index key) is never 0.
*/
SQLITE4_PRIVATE void sqlite4CompleteInsertion(
  Parse *pParse,      /* The parser context */
  Table *pTab,        /* the table into which we are inserting */
  int baseCur,        /* Index of a read/write cursor pointing at pTab */
  int regContent,     /* First register of content */
  int *aRegIdx,       /* Register used by each index.  0 for unused indices */
  int isUpdate,       /* True for UPDATE, False for INSERT */
  int appendBias,     /* True if this is likely to be an append */
  int useSeekResult   /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */
){
  int i;
  Vdbe *v;
  Index *pIdx;
  u8 pik_flags;
  int regRec;
  int regCover;

  v = sqlite4GetVdbe(pParse);
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */

  if( pParse->nested ){
    pik_flags = 0;
  }else{
    pik_flags = OPFLAG_NCHANGE | (isUpdate?OPFLAG_ISUPDATE:0);
  }

  /* Generate code to serialize array of registers into a database record. 
  ** This OP_MakeRecord also serves to apply affinities to the array of
  ** input registers at regContent. For this reason it must be executed 
  ** before any MakeRecord instructions used to create covering index
  ** records.  */
  regRec = sqlite4GetTempReg(pParse);
  if( IsKvstore(pTab) ){
    sqlite4VdbeAddOp2(v, OP_SCopy, regContent+1, regRec);
    sqlite4VdbeAddOp1(v, OP_ToBlob, regRec);
  }else{
    sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pTab->nCol, regRec);
    sqlite4TableAffinityStr(v, pTab);
    sqlite4ExprCacheAffinityChange(pParse, regContent, pTab->nCol);
  }
  regCover = sqlite4GetTempReg(pParse);

  /* Write the entry to each index. */
  for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
    assert( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY || aRegIdx[i] );
    if( pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){
      int iPK;
      sqlite4FindPrimaryKey(pTab, &iPK);
      sqlite4Fts5CodeUpdate(pParse, pIdx, 0, aRegIdx[iPK], regContent, 0);
    }
    else if( aRegIdx[i] ){
      int regData = 0;
      int flags = 0;
      if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){
        regData = regRec;
        flags = pik_flags;
      }else if( pIdx->nCover>0 ){
        int nByte = sizeof(int)*pIdx->nCover;
        int *aiPermute = (int *)sqlite4DbMallocRaw(pParse->db, nByte);

        if( aiPermute ){
          memcpy(aiPermute, pIdx->aiCover, nByte);
          sqlite4VdbeAddOp4(
              v, OP_Permutation, pIdx->nCover, 0, 0,
              (char*)aiPermute, P4_INTARRAY
          );
        }
        regData = regCover;
        sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pIdx->nCover, regData);
      }
      sqlite4VdbeAddOp3(v, OP_Insert, baseCur+i, regData, aRegIdx[i]);
      sqlite4VdbeChangeP5(v, flags);
    }
  }
}

/*
** Generate code that will open cursors for a table and for all
** indices of that table.  The "baseCur" parameter is the cursor number used
** for the table.  Indices are opened on subsequent cursors.
**
** Return the number of indices on the table.
*/
SQLITE4_PRIVATE int sqlite4OpenAllIndexes(
  Parse *pParse,   /* Parsing context */
  Table *pTab,     /* Table to be opened */
  int baseCur,     /* Cursor number assigned to the table */
  int op           /* OP_OpenRead or OP_OpenWrite */
){
  int i = 0;
  if( IsVirtual(pTab)==0 ){
    int iDb;
    Index *pIdx;

    iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      sqlite4OpenIndex(pParse, baseCur+i, iDb, pIdx, op);
      i++;
    }
    if( pParse->nTab<baseCur+i ){
      pParse->nTab = baseCur+i;
    }
  }
  return i;
}

SQLITE4_PRIVATE void sqlite4CloseAllIndexes(
  Parse *pParse,
  Table *pTab,
  int baseCur
){
  int i;
  Index *pIdx;
  Vdbe *v;

  assert( pTab->pIndex==0 || IsVirtual(pTab)==0 );
  assert( pTab->pIndex==0 || IsView(pTab)==0 );

  v = sqlite4GetVdbe(pParse);
  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    sqlite4VdbeAddOp1(v, OP_Close, baseCur+i);
  }
}


#ifdef SQLITE4_TEST
/*
** The following global variable is incremented whenever the
** transfer optimization is used.  This is used for testing
** purposes only - to make sure the transfer optimization really
** is happening when it is suppose to.
*/
SQLITE4_API int sqlite4_xferopt_count;
#endif /* SQLITE4_TEST */

/************** End of insert.c **********************************************/
/************** Begin file legacy.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
*/


/*
** Execute SQL code.  Return one of the SQLITE4_ success/failure
** codes.  Also write an error message into memory obtained from
** malloc() and make *pzErrMsg point to that message.
**
** If the SQL is a query, then for each row in the query result
** the xCall() function is called.  pArg becomes the first
** argument to xCall().  If xCall=NULL then no callback
** is invoked, even for queries.
*/
SQLITE4_API int sqlite4_exec(
  sqlite4 *db,                /* The database on which the SQL executes */
  const char *zSql,           /* The SQL to be executed */
  int (*xCall)(void*,int,sqlite4_value**,const char**),  /* Callback function */
  void *pArg                  /* First argument to xCall() */
){
  int rc = SQLITE4_OK;        /* Return code */
  int nRetry = 0;             /* Number of retry attempts */
  int bAbort = 0;             /* Set to true if callback returns non-zero */

  if( !sqlite4SafetyCheckOk(db) ) return SQLITE4_MISUSE_BKPT;
  if( zSql==0 ) zSql = "";

  sqlite4_mutex_enter(db->mutex);
  sqlite4Error(db, SQLITE4_OK, 0);

  /* Loop until we run out of SQL to execute, or the callback function
  ** returns non-zero, or an error occurs.  */
  while( zSql[0] && bAbort==0
     && (rc==SQLITE4_OK || (rc==SQLITE4_SCHEMA && (++nRetry)<2))
  ){
    int nUsed;                    /* Length of first SQL statement in zSql */
    int nCol;                     /* Number of returned columns */
    sqlite4_stmt *pStmt = 0;      /* The current SQL statement */
    const char **azCol = 0;       /* Names of result columns */
    sqlite4_value **apVal = 0;    /* Row of value objects */

    pStmt = 0;
    rc = sqlite4_prepare(db, zSql, -1, &pStmt, &nUsed);
    assert( rc==SQLITE4_OK || pStmt==0 );
    if( rc!=SQLITE4_OK ){
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql += nUsed;
      continue;
    }

    nCol = sqlite4_column_count(pStmt);
    do {

      /* Step the statement. Then invoke the callback function if required */
      rc = sqlite4_step(pStmt);
      if( xCall && SQLITE4_ROW==rc ){
        if( azCol==0 ){
          int nAlloc;             /* Bytes of space to allocate */

          nAlloc = (sizeof(char *) + sizeof(sqlite4_value *)) * nCol;
          azCol = (const char **)sqlite4DbMallocZero(db, nAlloc);
          if( azCol ){
            int i;                /* Used to iterate through result columns */
            apVal = (sqlite4_value **)&azCol[nCol];
            for(i=0; i<nCol; i++){
              azCol[i] = sqlite4_column_name(pStmt, i);
              /* sqlite4VdbeSetColName() installs column names as UTF8
              ** strings so there is no way for column_name() to fail. */
              assert( azCol[i]!=0 );
            }
          }
        }

        if( azCol ){
          int i;                  /* Used to iterate through result columns */
          for(i=0; i<nCol; i++){
            apVal[i] = sqlite4ColumnValue(pStmt, i);
            assert( apVal[i]!=0 );
          }
          bAbort = xCall(pArg, nCol, apVal, azCol);
        }
      }

      if( bAbort || rc!=SQLITE4_ROW ){
        rc = sqlite4VdbeFinalize((Vdbe *)pStmt);
        pStmt = 0;
        if( rc!=SQLITE4_SCHEMA ){
          nRetry = 0;
          zSql += nUsed;
          while( sqlite4Isspace(zSql[0]) ) zSql++;
        }
        assert( rc!=SQLITE4_ROW );
      }
    }while( rc==SQLITE4_ROW );

    sqlite4DbFree(db, azCol);
  }

  if( bAbort ) rc = SQLITE4_ABORT;
  rc = sqlite4ApiExit(db, rc);

  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/************** End of legacy.c **********************************************/
/************** Begin file pragma.c ******************************************/
/*
** 2003 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
*/

/*
** Interpret the given string as a boolean value.
*/
SQLITE4_PRIVATE u8 sqlite4GetBoolean(const char *z){
                             /* 123456789 12345 */
  static const char zText[] = "onoffalseyestrue";
  static const u8 iOffset[] = {0, 1, 2, 4, 9, 12};
  static const u8 iLength[] = {2, 2, 3, 5, 3, 4};
  static const u8 iValue[] =  {1, 0, 0, 0, 1, 1};
  int i, n;
  if( sqlite4Isdigit(*z) ){
    return (u8)sqlite4Atoi(z);
  }
  n = sqlite4Strlen30(z);
  for(i=0; i<ArraySize(iLength); i++){
    if( iLength[i]==n && sqlite4_strnicmp(&zText[iOffset[i]],z,n)==0 ){
      return iValue[i];
    }
  }
  return 1;
}

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

/*
** Generate code to return a single integer value.
*/
static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
  Vdbe *v = sqlite4GetVdbe(pParse);
  int mem = ++pParse->nMem;
  sqlite4_num *pNum;

  pNum = sqlite4DbMallocRaw(pParse->db, sizeof(value));
  if( pNum ){
    *pNum = sqlite4_num_from_int64(value);
  }
  sqlite4VdbeAddOp4(v, OP_Num, 1, mem, 0, (char *)pNum, P4_NUM);
  sqlite4VdbeSetNumCols(v, 1);
  sqlite4VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE4_STATIC);
  sqlite4VdbeAddOp2(v, OP_ResultRow, mem, 1);
}

#ifndef SQLITE4_OMIT_FLAG_PRAGMAS
/*
** Check to see if zRight and zLeft refer to a pragma that queries
** or changes one of the flags in db->flags.  Return 1 if so and 0 if not.
** Also, implement the pragma.
*/
static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
  static const struct sPragmaType {
    const char *zName;  /* Name of the pragma */
    int mask;           /* Mask for the db->flags value */
  } aPragma[] = {
    { "reverse_unordered_selects", SQLITE4_ReverseOrder  },
    { "automatic_index",           SQLITE4_AutoIndex  },
#ifdef SQLITE4_DEBUG
    { "sql_trace",                SQLITE4_SqlTrace      },
    { "vdbe_listing",             SQLITE4_VdbeListing   },
    { "vdbe_trace",               SQLITE4_VdbeTrace     },
    { "kv_trace",                 SQLITE4_KvTrace       },
    { "trace",                    SQLITE4_SqlTrace | SQLITE4_VdbeListing |
                                  SQLITE4_VdbeTrace | SQLITE4_KvTrace },
    { "vdbe_addoptrace",          SQLITE4_VdbeAddopTrace },
#endif
#ifndef SQLITE4_OMIT_CHECK
    { "ignore_check_constraints", SQLITE4_IgnoreChecks  },
#endif
    /* The following is VERY experimental */
    { "writable_schema",          SQLITE4_WriteSchema|SQLITE4_RecoveryMode },

    /* This flag may only be set if both foreign-key and trigger support
    ** are present in the build.  */
#if !defined(SQLITE4_OMIT_FOREIGN_KEY) && !defined(SQLITE4_OMIT_TRIGGER)
    { "foreign_keys",             SQLITE4_ForeignKeys },
#endif
  };
  int i, j;
  const struct sPragmaType *p;
  for(i=0, p=aPragma; i<ArraySize(aPragma); i++, p++){
    if( sqlite4_stricmp(zLeft, p->zName)==0 ){
      sqlite4 *db = pParse->db;
      Vdbe *v;
      v = sqlite4GetVdbe(pParse);
      assert( v!=0 );  /* Already allocated by sqlite4Pragma() */
      if( ALWAYS(v) ){
        if( zRight==0 ){
          returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 );
        }else{
          int mask = p->mask;          /* Mask of bits to set or clear. */
          if( db->pSavepoint ){
            /* Foreign key support may not be enabled or disabled while not
            ** in auto-commit mode.  */
            mask &= ~(SQLITE4_ForeignKeys);
          }

          if( sqlite4GetBoolean(zRight) ){
            db->flags |= mask;
          }else{
            db->flags &= ~mask;
          }

          /* Many of the flag-pragmas modify the code generated by the SQL 
          ** compiler (eg. count_changes). So add an opcode to expire all
          ** compiled SQL statements after modifying a pragma value.
          */
          sqlite4VdbeAddOp2(v, OP_Expire, 0, 0);
        }
        for(j=0; j<db->nDb; j++){
          if( db->aDb[j].pKV ){
            db->aDb[j].pKV->fTrace = (db->flags & SQLITE4_KvTrace)!=0;
          }
        }
      }

      return 1;
    }
  }
  return 0;
}
#endif /* SQLITE4_OMIT_FLAG_PRAGMAS */

/*
** Return a human-readable name for a constraint resolution action.
*/
#ifndef SQLITE4_OMIT_FOREIGN_KEY
static const char *actionName(u8 action){
  const char *zName;
  switch( action ){
    case OE_SetNull:  zName = "SET NULL";        break;
    case OE_SetDflt:  zName = "SET DEFAULT";     break;
    case OE_Cascade:  zName = "CASCADE";         break;
    case OE_Restrict: zName = "RESTRICT";        break;
    default:          zName = "NO ACTION";  
                      assert( action==OE_None ); break;
  }
  return zName;
}
#endif

/*
** Prepare an SQL PRAGMA statement.
*/
SQLITE4_PRIVATE void sqlite4Pragma(
  Parse *pParse,      /* Parse context */
  Token *pId1,        /* First part of [database.]id field */
  Token *pId2,        /* Second part of [database.]id field, or {0, 0} */
  ExprList *pList     /* List of pragma arguments */
){
  sqlite4 *db = pParse->db;
  Vdbe *v = pParse->pVdbe = sqlite4VdbeCreate(db);
  Token *pPragma;                 /* Token containing name of PRAGMA */
  char *zPragma = 0;              /* Name of requested PRAGMA */
  char *zRight = 0;               /* Argument to built-in pragmas */
  int iDb;                        /* Index of affected database */
  const char *zDb;                /* Named database (or NULL) */
  int rc = SQLITE4_OK;            /* Error code */
  KVStore *pKV;                   /* KV store corresponding to db iDb */

  /* Interpret the [database.] part of the pragma statement. iDb is the
  ** index of the database this pragma is being applied to in db.aDb[]. */
  iDb = sqlite4TwoPartName(pParse, pId1, pId2, &pPragma);
  if( iDb<0 ) goto pragma_out;
  zPragma = sqlite4NameFromToken(db, pPragma);
  if( !zPragma ) goto pragma_out;

  assert( pId2 );
  zDb = pId2->n>0 ? db->aDb[iDb].zName : 0;

  /* If this pragma is to operate on the temp database, make sure it is open. */
  if( iDb==1 && sqlite4OpenTempDatabase(pParse) ){
    goto pragma_out;
  }

  /* If a database was named as part of the pragma command, check to see if
  ** this is a custom key-value store pragma. */
  pKV = db->aDb[iDb].pKV;
  if( pKV->pStoreVfunc->xGetMethod ){
    void (*xFunc)(sqlite4_context *, int, sqlite4_value **);
    void (*xDestroy)(void *);
    void *pArg;

    rc = pKV->pStoreVfunc->xGetMethod(pKV, zPragma, &pArg, &xFunc, &xDestroy);
    if( rc==SQLITE4_OK ){
      FuncDef *pDef;
      int r1 = 0;
      int regOut;               /* Result register */

      if( sqlite4AuthCheck(pParse, SQLITE4_PRAGMA, zPragma, 0, zDb) ){
        goto pragma_out;
      }

      pDef = (FuncDef *)sqlite4DbMallocZero(db, sizeof(FuncDef));
      if( !pDef ) goto pragma_out;
      pDef->flags = SQLITE4_FUNC_EPHEM;
      pDef->pUserData = pArg;
      pDef->xFunc = xFunc;
      pDef->xDestroy = xDestroy;

      sqlite4VdbeSetNumCols(v, 1);
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, zPragma, SQLITE4_TRANSIENT);

      if( pList ){
        r1 = pParse->nMem+1;
        pParse->nMem += pList->nExpr;
        sqlite4ExprCodeExprList(pParse, pList, r1, 0);
        pDef->nArg = pList->nExpr;
      }

      regOut = ++pParse->nMem;
      sqlite4VdbeAddOp1(v, OP_KVMethod, iDb);
      sqlite4VdbeAddOp3(v, OP_Function, 0, r1, regOut);
      sqlite4VdbeChangeP4(v, -1, (char*)pDef, P4_FUNCDEF);
      if( pList ) sqlite4VdbeChangeP5(v, pList->nExpr);
      sqlite4VdbeAddOp2(v, OP_ResultRow, regOut, 1);
      goto pragma_out;

    }else if( rc==SQLITE4_NOTFOUND ){
      rc = SQLITE4_OK;
    }else{
      goto pragma_out;
    }
  }

  pParse->nMem = 2;
  sqlite4VdbeRunOnlyOnce(v);
  zRight = 0;
  if( pList ){
    zRight = pList->a[0].zSpan;
    if( zRight==0 ){ 
      assert( pList->a[0].pExpr->op==TK_ID );
      zRight = pList->a[0].pExpr->u.zToken; 
    }
    sqlite4Dequote(zRight);
  }

  if( sqlite4AuthCheck(pParse, SQLITE4_PRAGMA, zPragma, zRight, zDb) ){
    goto pragma_out;
  }

#ifndef SQLITE4_OMIT_FLAG_PRAGMAS
  if( flagPragma(pParse, zPragma, zRight) ){
    /* The flagPragma() subroutine also generates any necessary code
    ** there is nothing more to do here */
  }else
#endif /* SQLITE4_OMIT_FLAG_PRAGMAS */

  /*
  **   PRAGMA fts_check(<index>)
  */
  if( sqlite4_stricmp(zPragma, "fts_check")==0 && zRight ){
    int iCksum1;
    int iCksum2;
    Index *pIdx;
    Table *pTab;
    Vdbe *v = sqlite4GetVdbe(pParse);
    if( v==0 || sqlite4ReadSchema(pParse) ) goto pragma_out;

    iCksum1 = ++pParse->nMem;
    iCksum2 = ++pParse->nMem;
    sqlite4VdbeAddOp2(v, OP_Integer, 0, iCksum1);
    sqlite4VdbeAddOp2(v, OP_Integer, 0, iCksum2);

    pIdx = sqlite4FindIndex(db, zRight, zDb);
    if( pIdx && pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){
      int iTab = pParse->nTab++;
      int iAddr;
      int iReg;
      int i;

      pTab = pIdx->pTable;
      sqlite4OpenPrimaryKey(pParse, iTab, iDb, pTab, OP_OpenRead);
      iAddr = sqlite4VdbeAddOp2(v, OP_Rewind, iTab, 0);

      iReg = pParse->nMem+1;
      pParse->nMem += (1 + pTab->nCol);

      sqlite4VdbeAddOp2(v, OP_RowKey, iTab, iReg);
      for(i=0; i<pTab->nCol; i++){
        sqlite4VdbeAddOp3(v, OP_Column, iTab, i, iReg+1+i);
      }
      sqlite4Fts5CodeCksum(pParse, pIdx, iCksum1, iReg, 0);

      sqlite4VdbeAddOp2(v, OP_Next, iTab, iAddr+1);
      sqlite4VdbeJumpHere(v, iAddr);
      sqlite4VdbeAddOp1(v, OP_Close, iTab);

      sqlite4VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
      iAddr = sqlite4VdbeAddOp2(v, OP_Rewind, iTab, 0);

      iReg = pParse->nMem+1;
      pParse->nMem += 2;
      sqlite4VdbeAddOp2(v, OP_RowKey, iTab, iReg);
      sqlite4VdbeAddOp2(v, OP_RowData, iTab, iReg+1);
      sqlite4Fts5CodeCksum(pParse, pIdx, iCksum2, iReg, 1);

      sqlite4VdbeAddOp2(v, OP_Next, iTab, iAddr+1);
      sqlite4VdbeJumpHere(v, iAddr);
      sqlite4VdbeAddOp1(v, OP_Close, iTab);

      iReg = ++pParse->nMem;
      sqlite4VdbeAddOp4(v, OP_String8, 0, iReg, 0, "ok", 0);
      iAddr = sqlite4VdbeAddOp3(v, OP_Eq, iCksum1, 0, iCksum2);
      sqlite4VdbeAddOp4(v, OP_String8, 0, iReg, 0, "error - cksum mismatch", 0);
      sqlite4VdbeJumpHere(v, iAddr);
      sqlite4VdbeAddOp2(v, OP_ResultRow, iReg, 1);

      sqlite4VdbeSetNumCols(v, 1);
    }
  }

#ifndef SQLITE4_OMIT_SCHEMA_PRAGMAS
  /*
  **   PRAGMA table_info(<table>)
  **
  ** Return a single row for each column of the named table. The columns of
  ** the returned data set are:
  **
  ** cid:        Column id (numbered from left to right, starting at 0)
  ** name:       Column name
  ** type:       Column declaration type.
  ** notnull:    True if 'NOT NULL' is part of column declaration
  ** dflt_value: The default value for the column, if any.
  */
  if( sqlite4_stricmp(zPragma, "table_info")==0 && zRight ){
    Table *pTab;
    if( sqlite4ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite4FindTable(db, zRight, zDb);
    if( pTab ){
      int i;
      int nHidden = 0;
      Column *pCol;
      sqlite4VdbeSetNumCols(v, 6);
      pParse->nMem = 6;
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE4_STATIC);
      sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC);
      sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE4_STATIC);
      sqlite4VdbeSetColName(v, 3, COLNAME_NAME, "notnull", SQLITE4_STATIC);
      sqlite4VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", SQLITE4_STATIC);
      sqlite4VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE4_STATIC);
      sqlite4ViewGetColumnNames(pParse, pTab);
      for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
        if( IsHiddenColumn(pCol) ){
          nHidden++;
          continue;
        }
        sqlite4VdbeAddOp2(v, OP_Integer, i-nHidden, 1);
        sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, pCol->zName, 0);
        sqlite4VdbeAddOp4(v, OP_String8, 0, 3, 0,
           pCol->zType ? pCol->zType : "", 0);
        sqlite4VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4);
        if( pCol->zDflt ){
          sqlite4VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pCol->zDflt, 0);
        }else{
          sqlite4VdbeAddOp2(v, OP_Null, 0, 5);
        }
        sqlite4VdbeAddOp2(v, OP_Integer, pCol->iPrimKey, 6);
        sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 6);
      }
    }
  }else

  if( sqlite4_stricmp(zPragma, "index_info")==0 && zRight ){
    Index *pIdx;
    Table *pTab;
    if( sqlite4ReadSchema(pParse) ) goto pragma_out;
    pIdx = sqlite4FindIndex(db, zRight, zDb);
    if( pIdx ){
      int i;
      pTab = pIdx->pTable;
      sqlite4VdbeSetNumCols(v, 3);
      pParse->nMem = 3;
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE4_STATIC);
      sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE4_STATIC);
      sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE4_STATIC);
      for(i=0; i<pIdx->nColumn; i++){
        int cnum = pIdx->aiColumn[i];
        sqlite4VdbeAddOp2(v, OP_Integer, i, 1);
        sqlite4VdbeAddOp2(v, OP_Integer, cnum, 2);
        assert( pTab->nCol>cnum );
        sqlite4VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
        sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 3);
      }
    }
  }else

  if( sqlite4_stricmp(zPragma, "index_list")==0 && zRight ){
    Index *pIdx;
    Table *pTab;
    if( sqlite4ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite4FindTable(db, zRight, zDb);
    if( pTab ){
      v = sqlite4GetVdbe(pParse);
      pIdx = pTab->pIndex;
      if( pIdx ){
        int i = 0; 
        sqlite4VdbeSetNumCols(v, 3);
        pParse->nMem = 3;
        sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE4_STATIC);
        while(pIdx){
          sqlite4VdbeAddOp2(v, OP_Integer, i, 1);
          sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
          sqlite4VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
          sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 3);
          ++i;
          pIdx = pIdx->pNext;
        }
      }
    }
  }else

  if( sqlite4_stricmp(zPragma, "database_list")==0 ){
    int i;
    if( sqlite4ReadSchema(pParse) ) goto pragma_out;
    sqlite4VdbeSetNumCols(v, 2);
    pParse->nMem = 3;
    sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE4_STATIC);
    sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC);
    for(i=0; i<db->nDb; i++){
      if( db->aDb[i].pKV==0 ) continue;
      assert( db->aDb[i].zName!=0 );
      sqlite4VdbeAddOp2(v, OP_Integer, i, 1);
      sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, db->aDb[i].zName, 0);
      sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 2);
    }
  }else

  if( sqlite4_stricmp(zPragma, "collation_list")==0 ){
    int i = 0;
    HashElem *p;
    sqlite4VdbeSetNumCols(v, 2);
    pParse->nMem = 2;
    sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE4_STATIC);
    sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE4_STATIC);
    for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){
      CollSeq *pColl = (CollSeq *)sqliteHashData(p);
      sqlite4VdbeAddOp2(v, OP_Integer, i++, 1);
      sqlite4VdbeAddOp4(v, OP_String8, 0, 2, 0, pColl->zName, 0);
      sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 2);
    }
  }else
#endif /* SQLITE4_OMIT_SCHEMA_PRAGMAS */

#ifndef SQLITE4_OMIT_FOREIGN_KEY
  if( sqlite4_stricmp(zPragma, "foreign_key_list")==0 && zRight ){
    FKey *pFK;
    Table *pTab;
    if( sqlite4ReadSchema(pParse) ) goto pragma_out;
    pTab = sqlite4FindTable(db, zRight, zDb);
    if( pTab ){
      v = sqlite4GetVdbe(pParse);
      pFK = pTab->pFKey;
      if( pFK ){
        int i = 0; 
        sqlite4VdbeSetNumCols(v, 8);
        pParse->nMem = 8;
        sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 3, COLNAME_NAME, "from", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 4, COLNAME_NAME, "to", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 5, COLNAME_NAME, "on_update", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 6, COLNAME_NAME, "on_delete", SQLITE4_STATIC);
        sqlite4VdbeSetColName(v, 7, COLNAME_NAME, "match", SQLITE4_STATIC);
        while(pFK){
          int j;
          for(j=0; j<pFK->nCol; j++){
            char *zCol = pFK->aCol[j].zCol;
            char *zOnDelete = (char *)actionName(pFK->aAction[0]);
            char *zOnUpdate = (char *)actionName(pFK->aAction[1]);
            sqlite4VdbeAddOp2(v, OP_Integer, i, 1);
            sqlite4VdbeAddOp2(v, OP_Integer, j, 2);
            sqlite4VdbeAddOp4(v, OP_String8, 0, 3, 0, pFK->zTo, 0);
            sqlite4VdbeAddOp4(v, OP_String8, 0, 4, 0,
                              pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
            sqlite4VdbeAddOp4(v, zCol ? OP_String8 : OP_Null, 0, 5, 0, zCol, 0);
            sqlite4VdbeAddOp4(v, OP_String8, 0, 6, 0, zOnUpdate, 0);
            sqlite4VdbeAddOp4(v, OP_String8, 0, 7, 0, zOnDelete, 0);
            sqlite4VdbeAddOp4(v, OP_String8, 0, 8, 0, "NONE", 0);
            sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 8);
          }
          ++i;
          pFK = pFK->pNextFrom;
        }
      }
    }
  }else
#endif /* !defined(SQLITE4_OMIT_FOREIGN_KEY) */

#ifndef NDEBUG
  if( sqlite4_stricmp(zPragma, "parser_trace")==0 ){
    if( zRight ){
      if( sqlite4GetBoolean(zRight) ){
        sqlite4ParserTrace(stderr, "parser: ");
      }else{
        sqlite4ParserTrace(0, 0);
      }
    }
  }else
#endif

  /* Reinstall the LIKE and GLOB functions.  The variant of LIKE
  ** used will be case sensitive or not depending on the RHS.
  */
  if( sqlite4_stricmp(zPragma, "case_sensitive_like")==0 ){
    if( zRight ){
      sqlite4RegisterLikeFunctions(db, sqlite4GetBoolean(zRight));
    }
  }else

#ifndef SQLITE4_INTEGRITY_CHECK_ERROR_MAX
# define SQLITE4_INTEGRITY_CHECK_ERROR_MAX 100
#endif


#ifndef SQLITE4_OMIT_UTF16
  /*
  **   PRAGMA encoding
  **   PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be"
  **
  ** In its first form, this pragma returns the encoding of the main
  ** database. If the database is not initialized, it is initialized now.
  **
  ** The second form of this pragma is a no-op if the main database file
  ** has not already been initialized. In this case it sets the default
  ** encoding that will be used for the main database file if a new file
  ** is created. If an existing main database file is opened, then the
  ** default text encoding for the existing database is used.
  ** 
  ** In all cases new databases created using the ATTACH command are
  ** created to use the same default text encoding as the main database. If
  ** the main database has not been initialized and/or created when ATTACH
  ** is executed, this is done before the ATTACH operation.
  **
  ** In the second form this pragma sets the text encoding to be used in
  ** new database files created using this database handle. It is only
  ** useful if invoked immediately after the main database i
  */
  if( sqlite4_stricmp(zPragma, "encoding")==0 ){
    static const struct EncName {
      char *zName;
      u8 enc;
    } encnames[] = {
      { "UTF8",     SQLITE4_UTF8        },
      { "UTF-8",    SQLITE4_UTF8        },  /* Must be element [1] */
      { "UTF-16le", SQLITE4_UTF16LE     },  /* Must be element [2] */
      { "UTF-16be", SQLITE4_UTF16BE     },  /* Must be element [3] */
      { "UTF16le",  SQLITE4_UTF16LE     },
      { "UTF16be",  SQLITE4_UTF16BE     },
      { "UTF-16",   0                  }, /* SQLITE4_UTF16NATIVE */
      { "UTF16",    0                  }, /* SQLITE4_UTF16NATIVE */
      { 0, 0 }
    };
    const struct EncName *pEnc;
    if( !zRight ){    /* "PRAGMA encoding" */
      if( sqlite4ReadSchema(pParse) ) goto pragma_out;
      sqlite4VdbeSetNumCols(v, 1);
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "encoding", SQLITE4_STATIC);
      sqlite4VdbeAddOp2(v, OP_String8, 0, 1);
      assert( encnames[SQLITE4_UTF8].enc==SQLITE4_UTF8 );
      assert( encnames[SQLITE4_UTF16LE].enc==SQLITE4_UTF16LE );
      assert( encnames[SQLITE4_UTF16BE].enc==SQLITE4_UTF16BE );
      sqlite4VdbeChangeP4(v, -1, encnames[ENC(pParse->db)].zName, P4_STATIC);
      sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 1);
    }else{                        /* "PRAGMA encoding = XXX" */
      /* Only change the value of sqlite.enc if the database handle is not
      ** initialized. If the main database exists, the new sqlite.enc value
      ** will be overwritten when the schema is next loaded. If it does not
      ** already exists, it will be created to use the new encoding value.
      */
      if( 
        !(DbHasProperty(db, 0, DB_SchemaLoaded)) || 
        DbHasProperty(db, 0, DB_Empty) 
      ){
        for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
          if( 0==sqlite4_stricmp(zRight, pEnc->zName) ){
            ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE4_UTF16NATIVE;
            break;
          }
        }
        if( !pEnc->zName ){
          sqlite4ErrorMsg(pParse, "unsupported encoding: %s", zRight);
        }
      }
    }
  }else
#endif /* SQLITE4_OMIT_UTF16 */


#ifndef SQLITE4_OMIT_COMPILEOPTION_DIAGS
  /*
  **   PRAGMA compile_options
  **
  ** Return the names of all compile-time options used in this build,
  ** one option per row.
  */
  if( sqlite4_stricmp(zPragma, "compile_options")==0 ){
    int i = 0;
    const char *zOpt;
    sqlite4VdbeSetNumCols(v, 1);
    pParse->nMem = 1;
    sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "compile_option", SQLITE4_STATIC);
    while( (zOpt = sqlite4_compileoption_get(i++))!=0 ){
      sqlite4VdbeAddOp4(v, OP_String8, 0, 1, 0, zOpt, 0);
      sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 1);
    }
  }else
#endif /* SQLITE4_OMIT_COMPILEOPTION_DIAGS */

#ifdef SQLITE4_DEBUG
  /*
  **   PRAGMA kvdump
  **
  ** Print an ascii rendering of the complete content of the database file.
  */
  if( sqlite4_stricmp(zPragma, "kvdump")==0 ){
    sqlite4KVStoreDump(db->aDb[0].pKV);
  }else

  /*
  **   PRAGMA kvreplace(BLOB,BLOB)
  **
  ** Insert or replace a single raw record into the KV store.  This pragma
  ** is exceedingly dangerous and should not be used by general-purpose
  ** applications.  It is intended for internal testing only - to provide
  ** a convenient way to insert arbitrary content into the key/value store.
  */
  if( sqlite4_stricmp(zPragma, "kvreplace")==0
   && pList->nExpr==2
  ){
    int r1, r2;
    Vdbe *v = sqlite4GetVdbe(pParse);
    pParse->nTab = 1;
    pParse->nMem = 3;
    sqlite4BeginWriteOperation(pParse, 0, iDb);
    r1 = sqlite4ExprCodeTarget(pParse, pList->a[0].pExpr, 1);
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r1, "key may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r1);
    r2 = sqlite4ExprCodeTarget(pParse, pList->a[1].pExpr, 2);
    sqlite4VdbeAddOp4(v, OP_HaltIfNull, SQLITE4_CONSTRAINT, OE_Abort,
                         r2, "value may not be null", P4_STATIC);
    sqlite4VdbeAddOp1(v, OP_ToBlob, r2);
    sqlite4VdbeAddOp0(v, OP_OpenWrite);
    sqlite4VdbeAddOp3(v, OP_Insert, 0, r2, r1);
    sqlite4VdbeAddOp0(v, OP_Halt);
  }else
#endif /* SQLITE4_DEBUG */

  /*
  **   PRAGMA integrity_check
  **
  ** Check that for each table, the content of any auxilliary indexes are 
  ** consistent with the primary key index.
  */
  if( sqlite4_stricmp(zPragma, "integrity_check")==0 ){
    const int baseCsr = 1;        /* Base cursor for OpenAllIndexes() call */

    const int regErrcnt = 1;      /* Register containing error count */
    const int regErrstr = 2;      /* Register containing error string */
    const int regTmp = 3;         /* Register for tmp use */
    const int regRowcnt1 = 4;     /* Register containing row count (from PK) */
    const int regRowcnt2 = 5;     /* Register containing error count */
    const int regResult = 6;      /* Register containing result string */
    const int regKey = 7;         /* Register containing encoded key */
    const int regArray = 8;       /* First in array of registers */

    int i;
    int nMaxArray = 1;
    int addrNot = 0;
    Vdbe *v;

    if( sqlite4ReadSchema(pParse) ) goto pragma_out;

    for(i=0; i<db->nDb; i++){
      if( OMIT_TEMPDB && i==1 ) continue;
      sqlite4CodeVerifySchema(pParse, i);
    }

    v = sqlite4GetVdbe(pParse);
    sqlite4VdbeAddOp2(v, OP_Integer, 0, regErrcnt);
    sqlite4VdbeAddOp4(v, OP_String8, 0, regErrstr, 0, "", 0);

    for(i=0; i<db->nDb; i++){
      Hash *pTbls;
      HashElem *x;

      if( OMIT_TEMPDB && i==1 ) continue;

      pTbls = &db->aDb[i].pSchema->tblHash;
      for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
        Index *pIdx;
        Table *pTab = (Table *)sqliteHashData(x);
        int addrRewind;
        int nIdx = 0;
        int iPkCsr;
        Index *pPk;
        int iCsr;

        /* Do nothing for views or sqlite_kvstore */
        if( IsView(pTab) || IsKvstore(pTab) ) continue;

        /* Open all indexes for table pTab. */
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
          if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){
            pPk = pIdx;
            iPkCsr = nIdx+baseCsr;
          }
          nIdx++;
        }
        sqlite4OpenAllIndexes(pParse, pTab, baseCsr, OP_OpenRead);

        sqlite4VdbeAddOp2(v, OP_Integer, 0, regRowcnt1);
        addrRewind = sqlite4VdbeAddOp1(v, OP_Rewind, iPkCsr);

        /* Increment the row-count register */
        sqlite4VdbeAddOp2(v, OP_AddImm, regRowcnt1, 1);

        for(iCsr=baseCsr, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCsr++){
          assert( (pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY)==(iCsr==iPkCsr) );
          if( iCsr!=iPkCsr ){
            char *zErr;
            int iCol;
            int jmp;
            for(iCol=0; iCol<pIdx->nColumn; iCol++){
              int r = regArray + iCol;
              sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, pIdx->aiColumn[iCol], r);
              assert( pIdx->aiColumn[iCol]>=0 );
            }
            for(iCol=0; iCol<pPk->nColumn; iCol++){
              int reg = regArray + pIdx->nColumn + iCol;
              int iTblCol = pPk->aiColumn[iCol];
              if( iTblCol<0 ){
                sqlite4VdbeAddOp2(v, OP_Rowid, iPkCsr, reg);
              }else{
                sqlite4VdbeAddOp3(v, OP_Column, iPkCsr, iTblCol, reg);
              }
            }

            if( (pPk->nColumn+pIdx->nColumn)>nMaxArray ){
              nMaxArray = pPk->nColumn + pIdx->nColumn;
            }

            sqlite4VdbeAddOp4Int(v, OP_MakeKey, regArray,
                                 pIdx->nColumn+pPk->nColumn, regKey, iCsr);
            jmp = sqlite4VdbeAddOp4(v, OP_Found, iCsr, 0, regKey, 0, P4_INT32);
            sqlite4VdbeAddOp2(v, OP_AddImm, regErrcnt, 1);
            zErr = sqlite4MPrintf(
                db, "entry missing from index %s: ", pIdx->zName
            );
            sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, zErr, 0);
            sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr);
            sqlite4VdbeAddOp3(v, OP_Function, 0, regKey, regTmp);
            sqlite4VdbeChangeP4(v, -1,
                (char *)sqlite4FindFunction(db, "hex", 3, 1, 0), 
                P4_FUNCDEF
            );
            sqlite4VdbeChangeP5(v, 1);
            sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr);
            sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, "\n", 0);
            sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr);
            sqlite4VdbeJumpHere(v, jmp);
            sqlite4DbFree(db, zErr);
          }
        }
        sqlite4VdbeAddOp2(v, OP_Next, iPkCsr, addrRewind+1);
        sqlite4VdbeJumpHere(v, addrRewind);

        for(iCsr=baseCsr, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCsr++){
          if( iCsr!=iPkCsr ){
            char *zErr;
            int addrEq;
            int addrRewind2;
            sqlite4VdbeAddOp2(v, OP_Integer, 0, regRowcnt2);
            addrRewind2 = sqlite4VdbeAddOp1(v, OP_Rewind, iCsr);
            sqlite4VdbeAddOp2(v, OP_AddImm, regRowcnt2, 1);
            sqlite4VdbeAddOp2(v, OP_Next, iCsr, addrRewind2+1);
            sqlite4VdbeJumpHere(v, addrRewind2);
            zErr = sqlite4MPrintf(
                db, "wrong # number of entries in index %s\n", pIdx->zName
            );
            addrEq = sqlite4VdbeAddOp3(v, OP_Eq, regRowcnt1, 0, regRowcnt2);
            sqlite4VdbeAddOp2(v, OP_AddImm, regErrcnt, 1);
            sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, zErr, 0);
            sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr);

            sqlite4VdbeJumpHere(v, addrEq);
            sqlite4DbFree(db, zErr);
          }
        }

        for(iCsr=baseCsr; iCsr<(baseCsr+nIdx); iCsr++){
          sqlite4VdbeAddOp1(v, OP_Close, iCsr);
        }
      }
    }

    sqlite4VdbeAddOp4(v, OP_String8, 0, regResult, 0, "ok", 0);
    addrNot = sqlite4VdbeAddOp1(v, OP_IfNot, regErrcnt);
    sqlite4VdbeAddOp4(v, OP_String8, 0, regArray, 0, " errors:\n", 0);
    sqlite4VdbeAddOp3(v, OP_Concat, regArray, regErrcnt, regResult);
    sqlite4VdbeAddOp3(v, OP_Concat, regErrstr, regResult, regResult);
    sqlite4VdbeJumpHere(v, addrNot);

    pParse->nMem = (regArray + nMaxArray);
    sqlite4VdbeSetNumCols(v, 1);
    sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", SQLITE4_STATIC);
    sqlite4VdbeAddOp2(v, OP_ResultRow, regResult, 1);

  }else


  /*
  **  PRAGMA shrink_memory
  **
  ** This pragma attempts to free as much memory as possible from the
  ** current database connection.
  */
  if( sqlite4_stricmp(zPragma, "shrink_memory")==0 ){
    sqlite4_db_release_memory(db);
  }else

  /*
  **  PRAGMA schema_version
  */
  if( sqlite4_stricmp(zPragma, "schema_version")==0 ){
    if( zRight ){
      /* Write the specified cookie value */
      static const VdbeOpList setCookie[] = {
        { OP_Transaction,    0,  1,  0},    /* 0 */
        { OP_Integer,        0,  1,  0},    /* 1 */
        { OP_SetCookie,      0,  0,  1},    /* 2 */
      };
      int addr = sqlite4VdbeAddOpList(v, ArraySize(setCookie), setCookie);
      sqlite4VdbeChangeP1(v, addr, iDb);
      sqlite4VdbeChangeP1(v, addr+1, sqlite4Atoi(zRight));
      sqlite4VdbeChangeP1(v, addr+2, iDb);
    }else{
      /* Read the specified cookie value */
      static const VdbeOpList readCookie[] = {
        { OP_Transaction,     0,  0,  0},    /* 0 */
        { OP_ReadCookie,      0,  1,  0},    /* 1 */
        { OP_ResultRow,       1,  1,  0}
      };
      int addr = sqlite4VdbeAddOpList(v, ArraySize(readCookie), readCookie);
      sqlite4VdbeChangeP1(v, addr, iDb);
      sqlite4VdbeChangeP1(v, addr+1, iDb);
      sqlite4VdbeSetNumCols(v, 1);
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, zPragma, SQLITE4_TRANSIENT);
    }
  }else

  /*
  ** TODO: This is temporary. There should be some generic way to
  ** pass PRAGMA commands through to KV stores.
  */
  if( sqlite4_stricmp(zPragma, "bt_page_dump")==0 && zRight ){
    bt_info info;
    memset(&info, 0, sizeof(info));
    info.pgno = sqlite4Atoi(zRight);
    sqlite4_buffer_init(&info.output, sqlite4_db_env(db)->pMM);

    rc = sqlite4_kvstore_control(db, zDb, BT_CONTROL_INFO, (void*)&info);
    if( rc==SQLITE4_OK ){
      sqlite4VdbeSetNumCols(v, 1);
      sqlite4VdbeSetColName(v, 0, COLNAME_NAME, "info", SQLITE4_STATIC);
      sqlite4VdbeAddOp2(v, OP_String8, 0, 1);
      sqlite4VdbeChangeP4(v, -1, (char*)info.output.p, P4_TRANSIENT);
      sqlite4VdbeAddOp2(v, OP_ResultRow, 1, 1);
    }
    sqlite4_buffer_clear(&info.output);
  }else

 
  {/* Empty ELSE clause */}



 pragma_out:
  sqlite4DbFree(db, zPragma);
  /* sqlite4DbFree(db, zRight); */
  sqlite4ExprListDelete(db, pList);
}

#endif /* SQLITE4_OMIT_PRAGMA */

/************** End of pragma.c **********************************************/
/************** Begin file prepare.c *****************************************/
/*
** 2005 May 25
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite4_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
*/

/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
static void corruptSchema(
  InitData *pData,     /* Initialization context */
  const char *zObj,    /* Object being parsed at the point of error */
  const char *zExtra   /* Error information */
){
  sqlite4 *db = pData->db;
  if( !db->mallocFailed && (db->flags & SQLITE4_RecoveryMode)==0 ){
    if( zObj==0 ) zObj = "?";
    sqlite4SetString(pData->pzErrMsg, db,
      "malformed database schema (%s)", zObj);
    if( zExtra ){
      *pData->pzErrMsg = sqlite4MAppendf(db, *pData->pzErrMsg, 
                                 "%s - %s", *pData->pzErrMsg, zExtra);
    }
  }
  pData->rc = db->mallocFailed ? SQLITE4_NOMEM : SQLITE4_CORRUPT_BKPT;
}

/*
** Create an in-memory schema object.
*/
static int initCallback(
  InitData *pData,                /* Schema initialization context */
  const char *zObj,               /* Name of object being created */
  int iRoot,                      /* Root page number. Zero for trigger/view */
  const char *zSql                /* Text of SQL CREATE statement */
){
  sqlite4 *db = pData->db;
  int iDb = pData->iDb;

  assert( sqlite4_mutex_held(db->mutex) );
  assert( iDb>=0 && iDb<db->nDb );

  DbClearProperty(db, iDb, DB_Empty);
  if( db->mallocFailed ){
    corruptSchema(pData, zObj, 0);
    return 1;
  }

  if( zSql && zSql[0] ){
    /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
    ** But because db->init.busy is set to 1, no VDBE code is generated
    ** or executed.  All the parser does is build the internal data
    ** structures that describe the table, index, or view.  */
    int rc;
    sqlite4_stmt *pStmt;
    TESTONLY(int rcp);            /* Return code from sqlite4_prepare() */

    assert( db->init.busy );
    db->init.iDb = iDb;
    db->init.newTnum = iRoot;
    db->init.orphanTrigger = 0;
    TESTONLY(rcp = ) sqlite4_prepare(db, zSql, -1, &pStmt, 0);
    rc = db->errCode;
    assert( (rc&0xFF)==(rcp&0xFF) );
    db->init.iDb = 0;
    if( SQLITE4_OK!=rc ){
      if( db->init.orphanTrigger ){
        assert( iDb==1 );
      }else{
        pData->rc = rc;
        if( rc==SQLITE4_NOMEM ){
          db->mallocFailed = 1;
        }else if( rc!=SQLITE4_INTERRUPT && (rc&0xFF)!=SQLITE4_LOCKED ){
          corruptSchema(pData, zObj, sqlite4_errmsg(db));
        }
      }
    }
    sqlite4_finalize(pStmt);
  }else if( zObj==0 ){
    corruptSchema(pData, 0, 0);
  }else{
    /* If the SQL column is blank it means this is an index that
    ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
    ** constraint for a CREATE TABLE.  The index should have already
    ** been created when we processed the CREATE TABLE.  All we have
    ** to do here is record the root page number for that index.
    */
    Index *pIndex;
    pIndex = sqlite4FindIndex(db, zObj, db->aDb[iDb].zName);
    if( pIndex==0 ){
      /* This can occur if there exists an index on a TEMP table which
      ** has the same name as another index on a permanent index.  Since
      ** the permanent table is hidden by the TEMP table, we can also
      ** safely ignore the index on the permanent table.
      */
      /* Do Nothing */;
    }else if( iRoot==0 ){
      corruptSchema(pData, zObj, "invalid rootpage");
    }else{
      pIndex->tnum = iRoot;
    }
  }
  return 0;
}

/*
** This is the callback routine for the code that initializes the
** database.  See sqlite4Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
**
** Each callback contains the following information:
**
**     argv[0] = name of thing being created
**     argv[1] = root page number for table or index. 0 for trigger or view.
**     argv[2] = SQL text for the CREATE statement.
**
*/
SQLITE4_PRIVATE int sqlite4InitCallback(
  void *pInit, 
  int nVal, 
  sqlite4_value **apVal, 
  const char **azCol
){
  InitData *pData = (InitData*)pInit;
  sqlite4 *db = pData->db;
  int iDb = pData->iDb;

  UNUSED_PARAMETER2(azCol, nVal);
  assert( nVal==3 );
  assert( iDb>=0 && iDb<db->nDb );
  assert( sqlite4_mutex_held(db->mutex) );

  DbClearProperty(db, iDb, DB_Empty);
  if( db->mallocFailed ){
    corruptSchema(pData, sqlite4_value_text(apVal[0], 0), 0);
  }else if( apVal ){
    if( sqlite4_value_type(apVal[1])==SQLITE4_NULL ){
      corruptSchema(pData, sqlite4_value_text(apVal[0], 0), 0);
    }else{
      initCallback(pData, 
          sqlite4_value_text(apVal[0], 0),    /* Object name */
          sqlite4_value_int(apVal[1]),        /* Root page number */
          sqlite4_value_text(apVal[2], 0)     /* Text of CREATE statement */
      );
    }
  }

  return 0;
}

static int createSchemaTable(
  InitData *pInit,
  const char *zName,
  i64 iRoot,
  const char *zSchema
){
  Table *pTab;
  initCallback(pInit, zName, iRoot, zSchema);
  if( pInit->rc ) return 1;
  pTab = sqlite4FindTable(pInit->db, zName, pInit->db->aDb[pInit->iDb].zName);
  if( ALWAYS(pTab) ) pTab->tabFlags |= TF_Readonly;
  return 0;
}


/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE4_ error codes to
** indicate success or failure.
*/
static int sqlite4InitOne(sqlite4 *db, int iDb, char **pzErrMsg){
  int rc;
  Table *pTab;
  Db *pDb;
  InitData initData;
  char const *zMasterSchema;
  char const *zMasterName;
  char const *zKvstoreName;
  int openedTransaction = 0;

  static const char *aMaster[] = {
     "CREATE TABLE sqlite_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")", 
#ifndef SQLITE4_OMIT_TEMPDB
     "CREATE TEMP TABLE sqlite_temp_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
#endif
  };
  static const char *aKvstore[] = {
     "CREATE TABLE sqlite_kvstore(key BLOB PRIMARY KEY, value BLOB)",
#ifndef SQLITE4_OMIT_TEMPDB
     "CREATE TABLE sqlite_temp_kvstore(key BLOB PRIMARY KEY, value BLOB)"
#endif
  };
  static const char *aKvstoreName[] = {
     "sqlite_kvstore",
#ifndef SQLITE4_OMIT_TEMPDB
     "sqlite_temp_kvstore"
#endif
  };


  assert( iDb>=0 && iDb<db->nDb );
  assert( db->aDb[iDb].pSchema );
  assert( sqlite4_mutex_held(db->mutex) );

  /* zMasterName is the name of the master table.  */
  zMasterName = SCHEMA_TABLE(iDb);
  zKvstoreName = aKvstoreName[iDb==1];

  /* Construct the schema tables.  */
  initData.db = db;
  initData.iDb = iDb;
  initData.rc = SQLITE4_OK;
  initData.pzErrMsg = pzErrMsg;
  if( createSchemaTable(&initData, zMasterName, 1, aMaster[iDb==1])
   || createSchemaTable(&initData, zKvstoreName, KVSTORE_ROOT, aKvstore[iDb==1])
  ){
    rc = initData.rc;
    goto error_out;
  }

  /* Create a cursor to hold the database open
  */
  pDb = &db->aDb[iDb];
  if( pDb->pKV==0 ){
    if( !OMIT_TEMPDB && ALWAYS(iDb==1) ){
      DbSetProperty(db, 1, DB_SchemaLoaded);
    }
    return SQLITE4_OK;
  }

  /* If there is not already a read-only (or read-write) transaction opened
  ** on the database, open one now. If a transaction is opened, it 
  ** will be closed before this function returns.  */
  if( pDb->pKV->iTransLevel==0 ){
    rc = sqlite4KVStoreBegin(pDb->pKV, 1);
    if( rc!=SQLITE4_OK ){
      sqlite4SetString(pzErrMsg, db, "%s", sqlite4ErrStr(rc));
      goto initone_error_out;
    }
    openedTransaction = 1;
  }

  /* Get the database schema version.
  */
  sqlite4KVStoreGetSchema(pDb->pKV, (u32 *)&pDb->pSchema->schema_cookie);

  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  {
    char *zSql;
    zSql = sqlite4MPrintf(db, 
        "SELECT name, rootpage, sql FROM '%q'.%s ORDER BY rowid",
        db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE4_OMIT_AUTHORIZATION
    {
      Authorizer *pAuth;
      pAuth = db->pAuth;
      db->pAuth = 0;
#endif
      rc = sqlite4_exec(db, zSql, sqlite4InitCallback, &initData);
#ifndef SQLITE4_OMIT_AUTHORIZATION
      db->pAuth = pAuth;
    }
#endif
    if( rc==SQLITE4_OK ) rc = initData.rc;
    sqlite4DbFree(db, zSql);
#ifndef SQLITE4_OMIT_ANALYZE
    if( rc==SQLITE4_OK ){
      sqlite4AnalysisLoad(db, iDb);
    }
#endif
  }
  if( db->mallocFailed ){
    rc = SQLITE4_NOMEM;
    sqlite4ResetInternalSchema(db, -1);
  }
  if( rc==SQLITE4_OK || (db->flags&SQLITE4_RecoveryMode)){
    /* Black magic: If the SQLITE4_RecoveryMode flag is set, then consider
    ** the schema loaded, even if errors occurred. In this situation the 
    ** current sqlite4_prepare() operation will fail, but the following one
    ** will attempt to compile the supplied statement against whatever subset
    ** of the schema was loaded before the error occurred. The primary
    ** purpose of this is to allow access to the sqlite_master table
    ** even when its contents have been corrupted.
    */
    DbSetProperty(db, iDb, DB_SchemaLoaded);
    rc = SQLITE4_OK;
  }

  /* Jump here for an error that occurs after successfully allocating
  ** curMain. For an error that occurs before that point, jump to error_out.
  */
initone_error_out:
  if( openedTransaction ){
    sqlite4KVStoreCommit(pDb->pKV, 0);
  }

error_out:
  if( rc==SQLITE4_NOMEM || rc==SQLITE4_IOERR_NOMEM ){
    db->mallocFailed = 1;
  }
  return rc;
}

/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
** created using ATTACH statements.  Return a success code.  If an
** error occurs, write an error message into *pzErrMsg.
**
** After a database is initialized, the DB_SchemaLoaded bit is set
** bit is set in the flags field of the Db structure. If the database
** file was of zero-length, then the DB_Empty flag is also set.
*/
SQLITE4_PRIVATE int sqlite4Init(sqlite4 *db, char **pzErrMsg){
  int i, rc;
  int commit_internal = !(db->flags&SQLITE4_InternChanges);
  
  assert( sqlite4_mutex_held(db->mutex) );
  rc = SQLITE4_OK;
  db->init.busy = 1;
  for(i=0; rc==SQLITE4_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue;
    rc = sqlite4InitOne(db, i, pzErrMsg);
    if( rc ){
      sqlite4ResetInternalSchema(db, i);
    }
  }

  /* Once all the other databases have been initialised, load the schema
  ** for the TEMP database. This is loaded last, as the TEMP database
  ** schema may contain references to objects in other databases.
  */
#ifndef SQLITE4_OMIT_TEMPDB
  if( rc==SQLITE4_OK && ALWAYS(db->nDb>1)
                    && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
    rc = sqlite4InitOne(db, 1, pzErrMsg);
    if( rc ){
      sqlite4ResetInternalSchema(db, 1);
    }
  }
#endif

  db->init.busy = 0;
  if( rc==SQLITE4_OK && commit_internal ){
    sqlite4CommitInternalChanges(db);
  }

  return rc; 
}

/*
** This routine is a no-op if the database schema is already initialised.
** Otherwise, the schema is loaded. An error code is returned.
*/
SQLITE4_PRIVATE int sqlite4ReadSchema(Parse *pParse){
  int rc = SQLITE4_OK;
  sqlite4 *db = pParse->db;
  assert( sqlite4_mutex_held(db->mutex) );
  if( !db->init.busy ){
    rc = sqlite4Init(db, &pParse->zErrMsg);
  }
  if( rc!=SQLITE4_OK ){
    pParse->rc = rc;
    pParse->nErr++;
  }
  return rc;
}


/*
** Check schema cookies in all databases.  If any cookie is out
** of date set pParse->rc to SQLITE4_SCHEMA.  If all schema cookies
** make no changes to pParse->rc.
*/
static void schemaIsValid(Parse *pParse){
  sqlite4 *db = pParse->db;
  int iDb;
  int rc;
  int cookie;

  assert( pParse->checkSchema );
  assert( sqlite4_mutex_held(db->mutex) );
  for(iDb=0; iDb<db->nDb; iDb++){
    int openedTransaction = 0;         /* True if a transaction is opened */
    KVStore *pKV = db->aDb[iDb].pKV;   /* Database to read cookie from */
    if( pKV==0 ) continue;

    /* If there is not already a read-only (or read-write) transaction opened
    ** on the b-tree database, open one now. If a transaction is opened, it 
    ** will be closed immediately after reading the meta-value. */
    if( pKV->iTransLevel==0 ){
      rc = sqlite4KVStoreBegin(pKV, 1);
      if( rc==SQLITE4_NOMEM || rc==SQLITE4_IOERR_NOMEM ){
        db->mallocFailed = 1;
      }
      if( rc!=SQLITE4_OK ) return;
      openedTransaction = 1;
    }

    /* Read the schema cookie from the database. If it does not match the 
    ** value stored as part of the in-memory schema representation,
    ** set Parse.rc to SQLITE4_SCHEMA. */
    sqlite4KVStoreGetSchema(pKV, (u32 *)&cookie);
    if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){
      sqlite4ResetInternalSchema(db, iDb);
      pParse->rc = SQLITE4_SCHEMA;
    }

    /* Close the transaction, if one was opened. */
    if( openedTransaction ){
      sqlite4KVStoreCommit(pKV, 0);
    }
  }
}

/*
** Convert a schema pointer into the iDb index that indicates
** which database file in db->aDb[] the schema refers to.
**
** If the same database is attached more than once, the first
** attached database is returned.
*/
SQLITE4_PRIVATE int sqlite4SchemaToIndex(sqlite4 *db, Schema *pSchema){
  int i = -1000000;

  /* If pSchema is NULL, then return -1000000. This happens when code in 
  ** expr.c is trying to resolve a reference to a transient table (i.e. one
  ** created by a sub-select). In this case the return value of this 
  ** function should never be used.
  **
  ** We return -1000000 instead of the more usual -1 simply because using
  ** -1000000 as the incorrect index into db->aDb[] is much 
  ** more likely to cause a segfault than -1 (of course there are assert()
  ** statements too, but it never hurts to play the odds).
  */
  assert( sqlite4_mutex_held(db->mutex) );
  if( pSchema ){
    for(i=0; ALWAYS(i<db->nDb); i++){
      if( db->aDb[i].pSchema==pSchema ){
        break;
      }
    }
    assert( i>=0 && i<db->nDb );
  }
  return i;
}

/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
static int sqlite4Prepare(
  sqlite4 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  Vdbe *pReprepare,         /* VM being reprepared */
  sqlite4_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  int *pnUsed               /* OUT: Bytes read from zSql */
){
  Parse *pParse;            /* Parsing context */
  char *zErrMsg = 0;        /* Error message */
  int rc = SQLITE4_OK;       /* Result code */
  int i;                    /* Loop counter */

  /* Allocate the parsing context */
  pParse = sqlite4StackAllocZero(db, sizeof(*pParse));
  if( pParse==0 ){
    rc = SQLITE4_NOMEM;
    goto end_prepare;
  }
  pParse->pReprepare = pReprepare;
  assert( ppStmt && *ppStmt==0 );
  assert( !db->mallocFailed );
  assert( sqlite4_mutex_held(db->mutex) );

  sqlite4VtabUnlockList(db);

  pParse->db = db;
  pParse->nQueryLoop = (double)1;
  if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
    char *zSqlCopy;
    int mxLen = db->aLimit[SQLITE4_LIMIT_SQL_LENGTH];
    testcase( nBytes==mxLen );
    testcase( nBytes==mxLen+1 );
    if( nBytes>mxLen ){
      sqlite4Error(db, SQLITE4_TOOBIG, "statement too long");
      rc = sqlite4ApiExit(db, SQLITE4_TOOBIG);
      goto end_prepare;
    }
    zSqlCopy = sqlite4DbStrNDup(db, zSql, nBytes);
    if( zSqlCopy ){
      sqlite4RunParser(pParse, zSqlCopy, &zErrMsg);
      sqlite4DbFree(db, zSqlCopy);
      pParse->zTail = &zSql[pParse->zTail-zSqlCopy];
    }else{
      pParse->zTail = &zSql[nBytes];
    }
  }else{
    sqlite4RunParser(pParse, zSql, &zErrMsg);
  }
  assert( 1==(int)pParse->nQueryLoop );

  if( db->mallocFailed ){
    pParse->rc = SQLITE4_NOMEM;
  }
  if( pParse->rc==SQLITE4_DONE ) pParse->rc = SQLITE4_OK;
  if( pParse->checkSchema ){
    schemaIsValid(pParse);
  }
  if( db->mallocFailed ){
    pParse->rc = SQLITE4_NOMEM;
  }
  if( pnUsed ){
    *pnUsed = (pParse->zTail-zSql);
  }
  rc = pParse->rc;

#ifndef SQLITE4_OMIT_EXPLAIN
  if( rc==SQLITE4_OK && pParse->pVdbe && pParse->explain ){
    static const char * const azColName[] = {
       "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
       "selectid", "order", "from", "detail"
    };
    int iFirst, mx;
    if( pParse->explain==2 ){
      sqlite4VdbeSetNumCols(pParse->pVdbe, 4);
      iFirst = 8;
      mx = 12;
    }else{
      sqlite4VdbeSetNumCols(pParse->pVdbe, 8);
      iFirst = 0;
      mx = 8;
    }
    for(i=iFirst; i<mx; i++){
      sqlite4VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
                            azColName[i], SQLITE4_STATIC);
    }
  }
#endif

  if( /*db->init.busy==0*/ 1 ){
    Vdbe *pVdbe = pParse->pVdbe;
    sqlite4VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql));
  }
  if( pParse->pVdbe && (rc!=SQLITE4_OK || db->mallocFailed) ){
    sqlite4VdbeFinalize(pParse->pVdbe);
    assert(!(*ppStmt));
  }else{
    *ppStmt = (sqlite4_stmt*)pParse->pVdbe;
  }

  if( zErrMsg ){
    sqlite4Error(db, rc, "%s", zErrMsg);
    sqlite4DbFree(db, zErrMsg);
  }else{
    sqlite4Error(db, rc, 0);
  }

  /* Delete any TriggerPrg structures allocated while parsing this statement. */
  while( pParse->pTriggerPrg ){
    TriggerPrg *pT = pParse->pTriggerPrg;
    pParse->pTriggerPrg = pT->pNext;
    sqlite4DbFree(db, pT);
  }

end_prepare:

  sqlite4StackFree(db, pParse);
  rc = sqlite4ApiExit(db, rc);
  return rc;
}
static int sqlite4LockAndPrepare(
  sqlite4 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  Vdbe *pOld,               /* VM being reprepared */
  sqlite4_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  int *pnUsed               /* OUT: Bytes read from zSql */
){
  int rc;
  assert( ppStmt!=0 );
  *ppStmt = 0;
  if( pnUsed ){
    *pnUsed = 0;
  }
  if( !sqlite4SafetyCheckOk(db) ){
    return SQLITE4_MISUSE_BKPT;
  }
  sqlite4_mutex_enter(db->mutex);
  rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pnUsed);
  if( rc==SQLITE4_SCHEMA ){
    sqlite4_finalize(*ppStmt);
    rc = sqlite4Prepare(db, zSql, nBytes, pOld, ppStmt, pnUsed);
  }
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Rerun the compilation of a statement after a schema change.
**
** If the statement is successfully recompiled, return SQLITE4_OK. Otherwise,
** if the statement cannot be recompiled because another connection has
** locked the sqlite4_master table, return SQLITE4_LOCKED. If any other error
** occurs, return SQLITE4_SCHEMA.
*/
SQLITE4_PRIVATE int sqlite4Reprepare(Vdbe *p){
  int rc;
  sqlite4_stmt *pNew;
  const char *zSql;
  sqlite4 *db;

  assert( sqlite4_mutex_held(sqlite4VdbeDb(p)->mutex) );
  zSql = sqlite4_stmt_sql((sqlite4_stmt *)p);
  db = sqlite4VdbeDb(p);
  assert( sqlite4_mutex_held(db->mutex) );
  rc = sqlite4LockAndPrepare(db, zSql, -1, p, &pNew, 0);
  if( rc ){
    if( rc==SQLITE4_NOMEM ){
      db->mallocFailed = 1;
    }
    assert( pNew==0 );
    return rc;
  }else{
    assert( pNew!=0 );
  }
  sqlite4VdbeSwap((Vdbe*)pNew, p);
  sqlite4TransferBindings(pNew, (sqlite4_stmt*)p);
  sqlite4VdbeResetStepResult((Vdbe*)pNew);
  sqlite4VdbeFinalize((Vdbe*)pNew);
  return SQLITE4_OK;
}


/*
** Two versions of the official API.  Legacy and new use.  In the legacy
** version, the original SQL text is not saved in the prepared statement
** and so if a schema change occurs, SQLITE4_SCHEMA is returned by
** sqlite4_step().  In the new version, the original SQL text is retained
** and the statement is automatically recompiled if an schema change
** occurs.
*/
SQLITE4_API int sqlite4_prepare(
  sqlite4 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  sqlite4_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  int *pnUsed               /* OUT: Bytes read from zSql */
){
  int rc;
  rc = sqlite4LockAndPrepare(db, zSql, nBytes, 0, ppStmt, pnUsed);
  assert( rc==SQLITE4_OK || ppStmt==0 || *ppStmt==0 );  /* VERIFY: F13021 */
  return rc;
}

/************** End of prepare.c *********************************************/
/************** Begin file select.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
*/


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
*/
static void clearSelect(sqlite4 *db, Select *p){
  sqlite4ExprListDelete(db, p->pEList);
  sqlite4SrcListDelete(db, p->pSrc);
  sqlite4ExprDelete(db, p->pWhere);
  sqlite4ExprListDelete(db, p->pGroupBy);
  sqlite4ExprDelete(db, p->pHaving);
  sqlite4ExprListDelete(db, p->pOrderBy);
  sqlite4SelectDelete(db, p->pPrior);
  sqlite4ExprDelete(db, p->pLimit);
  sqlite4ExprDelete(db, p->pOffset);
}

/*
** Initialize a SelectDest structure.
*/
SQLITE4_PRIVATE void sqlite4SelectDestInit(SelectDest *pDest, int eDest, int iParm){
  pDest->eDest = (u8)eDest;
  pDest->iParm = iParm;
  pDest->affinity = 0;
  pDest->iMem = 0;
  pDest->nMem = 0;
}


/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
SQLITE4_PRIVATE Select *sqlite4SelectNew(
  Parse *pParse,        /* Parsing context */
  ExprList *pEList,     /* which columns to include in the result */
  SrcList *pSrc,        /* the FROM clause -- which tables to scan */
  Expr *pWhere,         /* the WHERE clause */
  ExprList *pGroupBy,   /* the GROUP BY clause */
  Expr *pHaving,        /* the HAVING clause */
  ExprList *pOrderBy,   /* the ORDER BY clause */
  int isDistinct,       /* true if the DISTINCT keyword is present */
  Expr *pLimit,         /* LIMIT value.  NULL means not used */
  Expr *pOffset         /* OFFSET value.  NULL means no offset */
){
  Select *pNew;
  Select standin;
  sqlite4 *db = pParse->db;
  pNew = sqlite4DbMallocZero(db, sizeof(*pNew) );
  assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */
  if( pNew==0 ){
    assert( db->mallocFailed );
    pNew = &standin;
    memset(pNew, 0, sizeof(*pNew));
  }
  if( pEList==0 ){
    pEList = sqlite4ExprListAppend(pParse, 0, sqlite4Expr(db,TK_ALL,0));
  }
  pNew->pEList = pEList;
  if( pSrc==0 ) pSrc = sqlite4DbMallocZero(db, sizeof(*pSrc));
  pNew->pSrc = pSrc;
  pNew->pWhere = pWhere;
  pNew->pGroupBy = pGroupBy;
  pNew->pHaving = pHaving;
  pNew->pOrderBy = pOrderBy;
  pNew->selFlags = isDistinct ? SF_Distinct : 0;
  pNew->op = TK_SELECT;
  pNew->pLimit = pLimit;
  pNew->pOffset = pOffset;
  assert( pOffset==0 || pLimit!=0 );
  pNew->addrOpenEphm[0] = -1;
  pNew->addrOpenEphm[1] = -1;
  pNew->addrOpenEphm[2] = -1;
  if( db->mallocFailed ) {
    clearSelect(db, pNew);
    if( pNew!=&standin ) sqlite4DbFree(db, pNew);
    pNew = 0;
  }else{
    assert( pNew->pSrc!=0 || pParse->nErr>0 );
  }
  assert( pNew!=&standin );
  return pNew;
}

/*
** Delete the given Select structure and all of its substructures.
*/
SQLITE4_PRIVATE void sqlite4SelectDelete(sqlite4 *db, Select *p){
  if( p ){
    clearSelect(db, p);
    sqlite4DbFree(db, p);
  }
}

/*
** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the
** type of join.  Return an integer constant that expresses that type
** in terms of the following bit values:
**
**     JT_INNER
**     JT_CROSS
**     JT_OUTER
**     JT_NATURAL
**     JT_LEFT
**     JT_RIGHT
**
** A full outer join is the combination of JT_LEFT and JT_RIGHT.
**
** If an illegal or unsupported join type is seen, then still return
** a join type, but put an error in the pParse structure.
*/
SQLITE4_PRIVATE int sqlite4JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
  int jointype = 0;
  Token *apAll[3];
  Token *p;
                             /*   0123456789 123456789 123456789 123 */
  static const char zKeyText[] = "naturaleftouterightfullinnercross";
  static const struct {
    u8 i;        /* Beginning of keyword text in zKeyText[] */
    u8 nChar;    /* Length of the keyword in characters */
    u8 code;     /* Join type mask */
  } aKeyword[] = {
    /* natural */ { 0,  7, JT_NATURAL                },
    /* left    */ { 6,  4, JT_LEFT|JT_OUTER          },
    /* outer   */ { 10, 5, JT_OUTER                  },
    /* right   */ { 14, 5, JT_RIGHT|JT_OUTER         },
    /* full    */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },
    /* inner   */ { 23, 5, JT_INNER                  },
    /* cross   */ { 28, 5, JT_INNER|JT_CROSS         },
  };
  int i, j;
  apAll[0] = pA;
  apAll[1] = pB;
  apAll[2] = pC;
  for(i=0; i<3 && apAll[i]; i++){
    p = apAll[i];
    for(j=0; j<ArraySize(aKeyword); j++){
      if( p->n==aKeyword[j].nChar 
          && sqlite4_strnicmp((char*)p->z, &zKeyText[aKeyword[j].i], p->n)==0 ){
        jointype |= aKeyword[j].code;
        break;
      }
    }
    testcase( j==0 || j==1 || j==2 || j==3 || j==4 || j==5 || j==6 );
    if( j>=ArraySize(aKeyword) ){
      jointype |= JT_ERROR;
      break;
    }
  }
  if(
     (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
     (jointype & JT_ERROR)!=0
  ){
    const char *zSp = " ";
    assert( pB!=0 );
    if( pC==0 ){ zSp++; }
    sqlite4ErrorMsg(pParse, "unknown or unsupported join type: "
       "%T %T%s%T", pA, pB, zSp, pC);
    jointype = JT_INNER;
  }else if( (jointype & JT_OUTER)!=0 
         && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){
    sqlite4ErrorMsg(pParse, 
      "RIGHT and FULL OUTER JOINs are not currently supported");
    jointype = JT_INNER;
  }
  return jointype;
}

/*
** Return the index of a column in a table.  Return -1 if the column
** is not contained in the table.
*/
static int columnIndex(Table *pTab, const char *zCol){
  int i;
  for(i=0; i<pTab->nCol; i++){
    if( sqlite4_stricmp(pTab->aCol[i].zName, zCol)==0 ) return i;
  }
  return -1;
}

/*
** Search the first N tables in pSrc, from left to right, looking for a
** table that has a column named zCol.  
**
** When found, set *piTab and *piCol to the table index and column index
** of the matching column and return TRUE.
**
** If not found, return FALSE.
*/
static int tableAndColumnIndex(
  SrcList *pSrc,       /* Array of tables to search */
  int N,               /* Number of tables in pSrc->a[] to search */
  const char *zCol,    /* Name of the column we are looking for */
  int *piTab,          /* Write index of pSrc->a[] here */
  int *piCol           /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
){
  int i;               /* For looping over tables in pSrc */
  int iCol;            /* Index of column matching zCol */

  assert( (piTab==0)==(piCol==0) );  /* Both or neither are NULL */
  for(i=0; i<N; i++){
    iCol = columnIndex(pSrc->a[i].pTab, zCol);
    if( iCol>=0 ){
      if( piTab ){
        *piTab = i;
        *piCol = iCol;
      }
      return 1;
    }
  }
  return 0;
}

/*
** This function is used to add terms implied by JOIN syntax to the
** WHERE clause expression of a SELECT statement. The new term, which
** is ANDed with the existing WHERE clause, is of the form:
**
**    (tab1.col1 = tab2.col2)
**
** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the 
** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
** column iColRight of tab2.
*/
static void addWhereTerm(
  Parse *pParse,                  /* Parsing context */
  SrcList *pSrc,                  /* List of tables in FROM clause */
  int iLeft,                      /* Index of first table to join in pSrc */
  int iColLeft,                   /* Index of column in first table */
  int iRight,                     /* Index of second table in pSrc */
  int iColRight,                  /* Index of column in second table */
  int isOuterJoin,                /* True if this is an OUTER join */
  Expr **ppWhere                  /* IN/OUT: The WHERE clause to add to */
){
  sqlite4 *db = pParse->db;
  Expr *pE1;
  Expr *pE2;
  Expr *pEq;

  assert( iLeft<iRight );
  assert( pSrc->nSrc>iRight );
  assert( pSrc->a[iLeft].pTab );
  assert( pSrc->a[iRight].pTab );

  pE1 = sqlite4CreateColumnExpr(db, pSrc, iLeft, iColLeft);
  pE2 = sqlite4CreateColumnExpr(db, pSrc, iRight, iColRight);

  pEq = sqlite4PExpr(pParse, TK_EQ, pE1, pE2, 0);
  if( pEq && isOuterJoin ){
    ExprSetProperty(pEq, EP_FromJoin);
    assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) );
    ExprSetIrreducible(pEq);
    pEq->iRightJoinTable = (i16)pE2->iTable;
  }
  *ppWhere = sqlite4ExprAnd(db, *ppWhere, pEq);
}

/*
** Set the EP_FromJoin property on all terms of the given expression.
** And set the Expr.iRightJoinTable to iTable for every term in the
** expression.
**
** The EP_FromJoin property is used on terms of an expression to tell
** the LEFT OUTER JOIN processing logic that this term is part of the
** join restriction specified in the ON or USING clause and not a part
** of the more general WHERE clause.  These terms are moved over to the
** WHERE clause during join processing but we need to remember that they
** originated in the ON or USING clause.
**
** The Expr.iRightJoinTable tells the WHERE clause processing that the
** expression depends on table iRightJoinTable even if that table is not
** explicitly mentioned in the expression.  That information is needed
** for cases like this:
**
**    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
**
** The where clause needs to defer the handling of the t1.x=5
** term until after the t2 loop of the join.  In that way, a
** NULL t2 row will be inserted whenever t1.x!=5.  If we do not
** defer the handling of t1.x=5, it will be processed immediately
** after the t1 loop and rows with t1.x!=5 will never appear in
** the output, which is incorrect.
*/
static void setJoinExpr(Expr *p, int iTable){
  while( p ){
    ExprSetProperty(p, EP_FromJoin);
    assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
    ExprSetIrreducible(p);
    p->iRightJoinTable = (i16)iTable;
    setJoinExpr(p->pLeft, iTable);
    p = p->pRight;
  } 
}

/*
** This routine processes the join information for a SELECT statement.
** ON and USING clauses are converted into extra terms of the WHERE clause.
** NATURAL joins also create extra WHERE clause terms.
**
** The terms of a FROM clause are contained in the Select.pSrc structure.
** The left most table is the first entry in Select.pSrc.  The right-most
** table is the last entry.  The join operator is held in the entry to
** the left.  Thus entry 0 contains the join operator for the join between
** entries 0 and 1.  Any ON or USING clauses associated with the join are
** also attached to the left entry.
**
** This routine returns the number of errors encountered.
*/
static int sqliteProcessJoin(Parse *pParse, Select *p){
  SrcList *pSrc;                  /* All tables in the FROM clause */
  int i, j;                       /* Loop counters */
  SrcListItem *pLeft;     /* Left table being joined */
  SrcListItem *pRight;    /* Right table being joined */

  pSrc = p->pSrc;
  pLeft = &pSrc->a[0];
  pRight = &pLeft[1];
  for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
    Table *pLeftTab = pLeft->pTab;
    Table *pRightTab = pRight->pTab;
    int isOuter;

    if( NEVER(pLeftTab==0 || pRightTab==0) ) continue;
    isOuter = (pRight->jointype & JT_OUTER)!=0;

    /* When the NATURAL keyword is present, add WHERE clause terms for
    ** every column that the two tables have in common.
    */
    if( pRight->jointype & JT_NATURAL ){
      if( pRight->pOn || pRight->pUsing ){
        sqlite4ErrorMsg(pParse, "a NATURAL join may not have "
           "an ON or USING clause", 0);
        return 1;
      }
      for(j=0; j<pRightTab->nCol; j++){
        char *zName;   /* Name of column in the right table */
        int iLeft;     /* Matching left table */
        int iLeftCol;  /* Matching column in the left table */

        zName = pRightTab->aCol[j].zName;
        if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
          addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
                       isOuter, &p->pWhere);
        }
      }
    }

    /* Disallow both ON and USING clauses in the same join
    */
    if( pRight->pOn && pRight->pUsing ){
      sqlite4ErrorMsg(pParse, "cannot have both ON and USING "
        "clauses in the same join");
      return 1;
    }

    /* Add the ON clause to the end of the WHERE clause, connected by
    ** an AND operator.
    */
    if( pRight->pOn ){
      if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
      p->pWhere = sqlite4ExprAnd(pParse->db, p->pWhere, pRight->pOn);
      pRight->pOn = 0;
    }

    /* Create extra terms on the WHERE clause for each column named
    ** in the USING clause.  Example: If the two tables to be joined are 
    ** A and B and the USING clause names X, Y, and Z, then add this
    ** to the WHERE clause:    A.X=B.X AND A.Y=B.Y AND A.Z=B.Z
    ** Report an error if any column mentioned in the USING clause is
    ** not contained in both tables to be joined.
    */
    if( pRight->pUsing ){
      IdList *pList = pRight->pUsing;
      for(j=0; j<pList->nId; j++){
        char *zName;     /* Name of the term in the USING clause */
        int iLeft;       /* Table on the left with matching column name */
        int iLeftCol;    /* Column number of matching column on the left */
        int iRightCol;   /* Column number of matching column on the right */

        zName = pList->a[j].zName;
        iRightCol = columnIndex(pRightTab, zName);
        if( iRightCol<0
         || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
        ){
          sqlite4ErrorMsg(pParse, "cannot join using column %s - column "
            "not present in both tables", zName);
          return 1;
        }
        addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
                     isOuter, &p->pWhere);
      }
    }
  }
  return 0;
}

/*
** Insert code into "v" that will push the record on the top of the
** stack into the sorter.
*/
static void pushOntoSorter(
  Parse *pParse,                  /* Parser context */
  ExprList *pOrderBy,             /* The ORDER BY clause */
  Select *pSelect,                /* The whole SELECT statement */
  int regData                     /* Register holding data to be sorted */
){
  Vdbe *v = pParse->pVdbe;
  int nExpr = pOrderBy->nExpr;
  int regBase = sqlite4GetTempRange(pParse, nExpr+1);
  int regKey = sqlite4GetTempReg(pParse);

  /* Assemble the sort-key values in a contiguous array of registers
  ** starting at regBase. The sort-key consists of the result of each 
  ** expression in the ORDER BY clause followed by a unique sequence 
  ** number. The sequence number allows more than one row with the same
  ** sort-key.  */
  sqlite4ExprCacheClear(pParse);
  sqlite4ExprCodeExprList(pParse, pOrderBy, regBase, 0);
  sqlite4VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);

  /* Encode the sort-key. */
  sqlite4VdbeAddOp4Int(v, OP_MakeKey, regBase, nExpr+1, regKey,
                       pOrderBy->iECursor);

  /* Insert an entry into the sorter. The key inserted is the encoded key
  ** created by the OP_MakeKey coded above. The value is the record
  ** currently stored in register regData.  */
  sqlite4VdbeAddOp3(v, OP_Insert, pOrderBy->iECursor, regData, regKey);

  /* Release the temporary registers */
  sqlite4ReleaseTempReg(pParse, regKey);
  sqlite4ReleaseTempRange(pParse, regBase, nExpr+1);

  if( pSelect->iLimit ){
    int addr1, addr2;
    int iLimit;
    if( pSelect->iOffset ){
      iLimit = pSelect->iOffset+1;
    }else{
      iLimit = pSelect->iLimit;
    }
    addr1 = sqlite4VdbeAddOp1(v, OP_IfZero, iLimit);
    sqlite4VdbeAddOp2(v, OP_AddImm, iLimit, -1);
    addr2 = sqlite4VdbeAddOp0(v, OP_Goto);
    sqlite4VdbeJumpHere(v, addr1);
    sqlite4VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);
    sqlite4VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor);
    sqlite4VdbeJumpHere(v, addr2);
  }
}

/*
** Add code to implement the OFFSET
*/
static void codeOffset(
  Vdbe *v,          /* Generate code into this VM */
  Select *p,        /* The SELECT statement being coded */
  int iContinue     /* Jump here to skip the current record */
){
  if( p->iOffset && iContinue!=0 ){
    int addr;
    sqlite4VdbeAddOp2(v, OP_AddImm, p->iOffset, -1);
    addr = sqlite4VdbeAddOp1(v, OP_IfNeg, p->iOffset);
    sqlite4VdbeAddOp2(v, OP_Goto, 0, iContinue);
    VdbeComment((v, "skip OFFSET records"));
    sqlite4VdbeJumpHere(v, addr);
  }
}

/*
** Add code that will check to make sure the N registers starting at iMem
** form a distinct entry.  iTab is a sorting index that holds previously
** seen combinations of the N values.  A new entry is made in iTab
** if the current N values are new.
**
** A jump to addrRepeat is made and the N+1 values are popped from the
** stack if the top N elements are not distinct.
*/
static void codeDistinct(
  Parse *pParse,     /* Parsing and code generating context */
  int iTab,          /* A sorting index used to test for distinctness */
  int addrRepeat,    /* Jump to here if not distinct */
  int N,             /* Number of elements */
  int iMem           /* First element */
){
  Vdbe *v;
  int r1, r2;

  v = pParse->pVdbe;
  r1 = sqlite4GetTempReg(pParse);
  r2 = sqlite4GetTempReg(pParse);
  sqlite4VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N);
  sqlite4VdbeAddOp4Int(v, OP_MakeKey, iMem, N, r2, iTab);
  sqlite4VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
  sqlite4VdbeChangeP5(v, OPFLAG_USEKEY);
  sqlite4VdbeAddOp3(v, OP_Insert, iTab, r1, r2);
  sqlite4ReleaseTempReg(pParse, r1);
  sqlite4ReleaseTempReg(pParse, r2);
}

#ifndef SQLITE4_OMIT_SUBQUERY
/*
** Generate an error message when a SELECT is used within a subexpression
** (example:  "a IN (SELECT * FROM table)") but it has more than 1 result
** column.  We do this in a subroutine because the error used to occur
** in multiple places.  (The error only occurs in one place now, but we
** retain the subroutine to minimize code disruption.)
*/
static int checkForMultiColumnSelectError(
  Parse *pParse,       /* Parse context. */
  SelectDest *pDest,   /* Destination of SELECT results */
  int nExpr            /* Number of result columns returned by SELECT */
){
  int eDest = pDest->eDest;
  if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){
    sqlite4ErrorMsg(pParse, "only a single result allowed for "
       "a SELECT that is part of an expression");
    return 1;
  }else{
    return 0;
  }
}
#endif

/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
** If srcTab and nColumn are both zero, then the pEList expressions
** are evaluated in order to get the data for this row.  If nColumn>0
** then data is pulled from srcTab and pEList is used only to get the
** datatypes for each column.
*/
static void selectInnerLoop(
  Parse *pParse,          /* The parser context */
  Select *p,              /* The complete select statement being coded */
  ExprList *pEList,       /* List of values being extracted */
  int srcTab,             /* Pull data from this table */
  int nColumn,            /* Number of columns in the source table */
  ExprList *pOrderBy,     /* If not NULL, sort results using this key */
  int distinct,           /* If >=0, make sure results are distinct */
  SelectDest *pDest,      /* How to dispose of the results */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  int hasDistinct;        /* True if the DISTINCT keyword is present */
  int regResult;              /* Start of memory holding result set */
  int eDest = pDest->eDest;   /* How to dispose of results */
  int iParm = pDest->iParm;   /* First argument to disposal method */
  int nResultCol;             /* Number of result columns */

  assert( v );
  if( NEVER(v==0) ) return;
  assert( pEList!=0 );
  hasDistinct = distinct>=0;
  if( pOrderBy==0 && !hasDistinct ){
    codeOffset(v, p, iContinue);
  }

  /* Pull the requested columns.
  */
  if( nColumn>0 ){
    nResultCol = nColumn;
  }else{
    nResultCol = pEList->nExpr;
  }
  if( pDest->iMem==0 ){
    pDest->iMem = pParse->nMem+1;
    pDest->nMem = nResultCol;
    pParse->nMem += nResultCol;
  }else{ 
    assert( pDest->nMem==nResultCol );
  }
  regResult = pDest->iMem;
  if( nColumn>0 ){
    for(i=0; i<nColumn; i++){
      sqlite4VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
    }
  }else if( eDest!=SRT_Exists ){
    /* If the destination is an EXISTS(...) expression, the actual
    ** values returned by the SELECT are not required.
    */
    sqlite4ExprCacheClear(pParse);
    sqlite4ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);
  }
  nColumn = nResultCol;

  /* If the DISTINCT keyword was present on the SELECT statement
  ** and this row has been seen before, then do not make this row
  ** part of the result.
  */
  if( hasDistinct ){
    assert( pEList!=0 );
    assert( pEList->nExpr==nColumn );
    codeDistinct(pParse, distinct, iContinue, nColumn, regResult);
    if( pOrderBy==0 ){
      codeOffset(v, p, iContinue);
    }
  }

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary
    ** table iParm.
    */
#ifndef SQLITE4_OMIT_COMPOUND_SELECT
    case SRT_Union: {
      int r1, r2;
      r1 = sqlite4GetTempReg(pParse);
      r2 = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp4Int(v, OP_MakeKey, regResult, nColumn, r2, iParm);
      sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
      sqlite4VdbeChangeP5(v, OPFLAG_USEKEY);
      sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
      sqlite4ReleaseTempReg(pParse, r1);
      sqlite4ReleaseTempReg(pParse, r2);
      break;
    }

    /* This is used for processing queries of the form:
    **
    **     <select-1> EXCEPT <select-2>
    **
    ** Temporary index iParm contains the results of <select-1>. This
    ** code is processing the results of <select-2>. For each row of
    ** <select-2>, remove any identical row from iParm.  */
    case SRT_Except: {
      int regKey = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp4Int(v, OP_MakeKey, regResult, nColumn, regKey, iParm);
      sqlite4VdbeAddOp3(v, OP_IdxDelete, iParm, 0, regKey);
      sqlite4ReleaseTempReg(pParse, regKey);
      break;
    }
#endif

    /* Store the result as data using a unique key.
    */
    case SRT_Table:
    case SRT_EphemTab: {
      int r1 = sqlite4GetTempReg(pParse);
      testcase( eDest==SRT_Table );
      testcase( eDest==SRT_EphemTab );
      sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p, r1);
      }else{
        int r2 = sqlite4GetTempReg(pParse);
        sqlite4VdbeAddOp2(v, OP_NewRowid, iParm, r2);
        sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
        sqlite4ReleaseTempReg(pParse, r2);
      }
      sqlite4ReleaseTempReg(pParse, r1);
      break;
    }

#ifndef SQLITE4_OMIT_SUBQUERY
    /* If we are creating a set for an "expr IN (SELECT ...)" construct,
    ** then there should be a single item on the stack.  Write this
    ** item into the set table with bogus data.
    */
    case SRT_Set: {
      int r1 = sqlite4GetTempReg(pParse);
      assert( nColumn==1 );
      p->affinity = sqlite4CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
      if( pOrderBy ){
        /* At first glance you would think we could optimize out the
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        sqlite4VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
        pushOntoSorter(pParse, pOrderBy, p, r1);
      }else{
        int r2 = sqlite4GetTempReg(pParse);
        sqlite4VdbeAddOp4(v, OP_Affinity, regResult, 1, 0, &p->affinity, 1);
        sqlite4VdbeAddOp4Int(v, OP_MakeKey, regResult, 1, r2, iParm);
        sqlite4ExprCacheAffinityChange(pParse, regResult, 1);
        sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, 1, r1);
        sqlite4VdbeChangeP5(v, OPFLAG_USEKEY);
        sqlite4VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
        sqlite4ReleaseTempReg(pParse, r2);
      }
      sqlite4ReleaseTempReg(pParse, r1);
      break;
    }

    /* If any row exist in the result set, record that fact and abort.
    */
    case SRT_Exists: {
      sqlite4VdbeAddOp2(v, OP_Integer, 1, iParm);
      /* The LIMIT clause will terminate the loop for us */
      break;
    }

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    */
    case SRT_Mem: {
      assert( nColumn==1 );
      if( pOrderBy ){
        int regRecord = sqlite4GetTempReg(pParse);
        sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, 1, regRecord);
        pushOntoSorter(pParse, pOrderBy, p, regRecord);
        sqlite4ReleaseTempReg(pParse, regRecord);
      }else{
        sqlite4ExprCodeMove(pParse, regResult, iParm, 1);
        /* The LIMIT clause will jump out of the loop for us */
      }
      break;
    }
#endif /* #ifndef SQLITE4_OMIT_SUBQUERY */

    /* Send the data to the callback function or to a subroutine.  In the
    ** case of a subroutine, the subroutine itself is responsible for
    ** popping the data from the stack.
    */
    case SRT_Coroutine:
    case SRT_Output: {
      testcase( eDest==SRT_Coroutine );
      testcase( eDest==SRT_Output );
      if( pOrderBy ){
        int r1 = sqlite4GetTempReg(pParse);
        sqlite4VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
        pushOntoSorter(pParse, pOrderBy, p, r1);
        sqlite4ReleaseTempReg(pParse, r1);
      }else if( eDest==SRT_Coroutine ){
        sqlite4VdbeAddOp1(v, OP_Yield, pDest->iParm);
      }else{
        sqlite4VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
        sqlite4ExprCacheAffinityChange(pParse, regResult, nColumn);
      }
      break;
    }

#if !defined(SQLITE4_OMIT_TRIGGER)
    /* Discard the results.  This is used for SELECT statements inside
    ** the body of a TRIGGER.  The purpose of such selects is to call
    ** user-defined functions that have side effects.  We do not care
    ** about the actual results of the select.
    */
    default: {
      assert( eDest==SRT_Discard );
      break;
    }
#endif
  }

  /* Jump to the end of the loop if the LIMIT is reached.  Except, if
  ** there is a sorter, in which case the sorter has already limited
  ** the output for us.
  */
  if( pOrderBy==0 && p->iLimit ){
    sqlite4VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1);
  }
}

/*
** Given an expression list, generate a KeyInfo structure that can be
** used to encode the results of the expressions into an index key.
**
** If the ExprList is an ORDER BY or GROUP BY clause then the resulting
** KeyInfo structure is appropriate for initializing a virtual index to
** implement that clause. If the ExprList is the result set of a SELECT
** then the KeyInfo structure is appropriate for initializing a virtual
** index to implement a DISTINCT test.
**
** Space to hold the KeyInfo structure is obtain from malloc.  The calling
** function is responsible for seeing that this structure is eventually
** freed.  Add the KeyInfo structure to the P4 field of an opcode using
** P4_KEYINFO_HANDOFF is the usual way of dealing with this.
*/
static KeyInfo *keyInfoFromExprList(
  Parse *pParse, 
  ExprList *pList,
  int bOrderBy                    /* True for ORDER BY */
){
  sqlite4 *db = pParse->db;       /* Database handle */
  int nField;                     /* Number of fields in keys */
  KeyInfo *pInfo;                 /* Object to return */
  int nByte;                      /* Bytes of space to allocate */

  assert( bOrderBy==0 || bOrderBy==1 );

  nField = pList->nExpr + bOrderBy;
  nByte = sizeof(KeyInfo) + nField * sizeof(CollSeq *) + nField;
  pInfo = (KeyInfo *)sqlite4DbMallocZero(db, nByte);

  if( pInfo ){
    int i;                        /* Used to iterate through pList */

    pInfo->aSortOrder = (u8*)&pInfo->aColl[nField];
    pInfo->nField = (u16)nField;

    for(i=0; i<pList->nExpr; i++){
      CollSeq *pColl;
      pColl = sqlite4ExprCollSeq(pParse, pList->a[i].pExpr);
      if( !pColl ) pColl = db->pDfltColl;
      pInfo->aColl[i] = pColl;
      pInfo->aSortOrder[i] = pList->a[i].sortOrder;
    }
  }
  return pInfo;
}

#ifndef SQLITE4_OMIT_COMPOUND_SELECT
/*
** Name of the connection operator, used for error messages.
*/
static const char *selectOpName(int id){
  char *z;
  switch( id ){
    case TK_ALL:       z = "UNION ALL";   break;
    case TK_INTERSECT: z = "INTERSECT";   break;
    case TK_EXCEPT:    z = "EXCEPT";      break;
    default:           z = "UNION";       break;
  }
  return z;
}
#endif /* SQLITE4_OMIT_COMPOUND_SELECT */

#ifndef SQLITE4_OMIT_EXPLAIN
/*
** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
** is a no-op. Otherwise, it adds a single row of output to the EQP result,
** where the caption is of the form:
**
**   "USE TEMP B-TREE FOR xxx"
**
** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which
** is determined by the zUsage argument.
*/
static void explainTempTable(Parse *pParse, const char *zUsage){
  if( pParse->explain==2 ){
    Vdbe *v = pParse->pVdbe;
    char *zMsg = sqlite4MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage);
    sqlite4VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
}

/*
** Assign expression b to lvalue a. A second, no-op, version of this macro
** is provided when SQLITE4_OMIT_EXPLAIN is defined. This allows the code
** in sqlite4Select() to assign values to structure member variables that
** only exist if SQLITE4_OMIT_EXPLAIN is not defined without polluting the
** code with #ifndef directives.
*/
# define explainSetInteger(a, b) a = b

#else
/* No-op versions of the explainXXX() functions and macros. */
# define explainTempTable(y,z)
# define explainSetInteger(y,z)
#endif

#if !defined(SQLITE4_OMIT_EXPLAIN) && !defined(SQLITE4_OMIT_COMPOUND_SELECT)
/*
** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
** is a no-op. Otherwise, it adds a single row of output to the EQP result,
** where the caption is of one of the two forms:
**
**   "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)"
**   "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)"
**
** where iSub1 and iSub2 are the integers passed as the corresponding
** function parameters, and op is the text representation of the parameter
** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT,
** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is 
** false, or the second form if it is true.
*/
static void explainComposite(
  Parse *pParse,                  /* Parse context */
  int op,                         /* One of TK_UNION, TK_EXCEPT etc. */
  int iSub1,                      /* Subquery id 1 */
  int iSub2,                      /* Subquery id 2 */
  int bUseTmp                     /* True if a temp table was used */
){
  assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL );
  if( pParse->explain==2 ){
    Vdbe *v = pParse->pVdbe;
    char *zMsg = sqlite4MPrintf(
        pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2,
        bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op)
    );
    sqlite4VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
}
#else
/* No-op versions of the explainXXX() functions and macros. */
# define explainComposite(v,w,x,y,z)
#endif

/*
** If the inner loop was generated using a non-null pOrderBy argument,
** then the results were placed in a sorter. After the loop is terminated
** we need to loop through the contents of the sorter and output the 
** results. The following routine generates the code needed to do that.
*/
static void generateSortTail(
  Parse *pParse,                  /* Parsing context */
  Select *p,                      /* The SELECT statement */
  Vdbe *v,                        /* Generate code into this VDBE */
  int nColumn,                    /* Number of columns of data */
  SelectDest *pDest               /* Write the sorted results here */
){
  int addrBreak = sqlite4VdbeMakeLabel(v);     /* Jump here to exit loop */
  int addrContinue = sqlite4VdbeMakeLabel(v);  /* Jump here for next cycle */
  int addr;
  int iTab;                       /* Sorter object cursor */
  ExprList *pOrderBy = p->pOrderBy;
  int eDest = pDest->eDest;
  int iParm = pDest->iParm;
  int op;                         /* Opcode use to sort results */

  iTab = pOrderBy->iECursor;
  op = (p->selFlags & SF_UseSorter) ? OP_SorterSort : OP_Sort;
  addr = 1 + sqlite4VdbeAddOp2(v, op, iTab, addrBreak);
  codeOffset(v, p, addrContinue);
  switch( eDest ){
    case SRT_Table:
    case SRT_EphemTab: {
      int regRowid = sqlite4GetTempReg(pParse);
      int regRow = sqlite4GetTempReg(pParse);
      testcase( eDest==SRT_Table );
      testcase( eDest==SRT_EphemTab );
      sqlite4VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
      sqlite4VdbeAddOp2(v, OP_RowData, iTab, regRow);
      sqlite4VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
      sqlite4ReleaseTempReg(pParse, regRow);
      sqlite4ReleaseTempReg(pParse, regRowid);
      break;
    }
#ifndef SQLITE4_OMIT_SUBQUERY
    case SRT_Set: {
      int regRes = sqlite4GetTempReg(pParse);
      int regKey = sqlite4GetTempReg(pParse);
      int regValue = sqlite4GetTempReg(pParse);
      assert( nColumn==1 );
      sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, regRes);
      sqlite4VdbeAddOp4(v, OP_Affinity, regRes, 1, 0, &p->affinity, 1);
      sqlite4VdbeAddOp4Int(v, OP_MakeKey, regRes, 1, regKey, iParm);
      sqlite4ExprCacheAffinityChange(pParse, regRes, 1);
      sqlite4VdbeAddOp3(v, OP_MakeRecord, regRes, 1, regValue);
      sqlite4VdbeChangeP5(v, OPFLAG_USEKEY);
      sqlite4VdbeAddOp3(v, OP_Insert, iParm, regValue, regKey);
      sqlite4ReleaseTempReg(pParse, regKey);
      sqlite4ReleaseTempReg(pParse, regRes);
      sqlite4ReleaseTempReg(pParse, regValue);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, iParm);
      /* The LIMIT clause will terminate the loop for us */
      break;
    }
#endif
    default: {
      int i;
      assert( eDest==SRT_Output || eDest==SRT_Coroutine ); 
      testcase( eDest==SRT_Output );
      testcase( eDest==SRT_Coroutine );

      /* Read the data out of the sorter and into the array of nColumn
      ** contiguous registers starting at pDest->iMem.  */
      for(i=0; i<nColumn; i++){
        sqlite4VdbeAddOp3(v, OP_Column, iTab, i, pDest->iMem+i);
      }

      if( eDest==SRT_Output ){
        sqlite4VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
        sqlite4ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);
      }else{
        sqlite4VdbeAddOp1(v, OP_Yield, pDest->iParm);
      }
      break;
    }
  }

  /* The bottom of the loop
  */
  sqlite4VdbeResolveLabel(v, addrContinue);
  if( p->selFlags & SF_UseSorter ){
    sqlite4VdbeAddOp2(v, OP_SorterNext, iTab, addr);
  }else{
    sqlite4VdbeAddOp2(v, OP_Next, iTab, addr);
  }
  sqlite4VdbeResolveLabel(v, addrBreak);
}

/*
** Return a pointer to a string containing the 'declaration type' of the
** expression pExpr. The string may be treated as static by the caller.
**
** The declaration type is the exact datatype definition extracted from the
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
** is considered a column can be complex in the presence of subqueries. The
** result-set expression in all of the following SELECT statements is 
** considered a column by this function.
**
**   SELECT col FROM tbl;
**   SELECT (SELECT col FROM tbl;
**   SELECT (SELECT col FROM tbl);
**   SELECT abc FROM (SELECT col AS abc FROM tbl);
** 
** The declaration type for any expression other than a column is NULL.
*/
static const char *columnType(
  NameContext *pNC, 
  Expr *pExpr,
  const char **pzOriginDb,
  const char **pzOriginTab,
  const char **pzOriginCol
){
  char const *zType = 0;
  char const *zOriginDb = 0;
  char const *zOriginTab = 0;
  char const *zOriginCol = 0;
  int j;
  if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;

  switch( pExpr->op ){
    case TK_AGG_COLUMN:
    case TK_COLUMN: {
      /* The expression is a column. Locate the table the column is being
      ** extracted from in NameContext.pSrcList. This table may be real
      ** database table or a subquery.
      */
      Table *pTab = 0;            /* Table structure column is extracted from */
      Select *pS = 0;             /* Select the column is extracted from */
      int iCol = pExpr->iColumn;  /* Index of column in pTab */
      testcase( pExpr->op==TK_AGG_COLUMN );
      testcase( pExpr->op==TK_COLUMN );
      while( pNC && !pTab ){
        SrcList *pTabList = pNC->pSrcList;
        for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
        if( j<pTabList->nSrc ){
          pTab = pTabList->a[j].pTab;
          pS = pTabList->a[j].pSelect;
        }else{
          pNC = pNC->pNext;
        }
      }

      if( pTab==0 ){
        /* At one time, code such as "SELECT new.x" within a trigger would
        ** cause this condition to run.  Since then, we have restructured how
        ** trigger code is generated and so this condition is no longer 
        ** possible. However, it can still be true for statements like
        ** the following:
        **
        **   CREATE TABLE t1(col INTEGER);
        **   SELECT (SELECT t1.col) FROM FROM t1;
        **
        ** when columnType() is called on the expression "t1.col" in the 
        ** sub-select. In this case, set the column type to NULL, even
        ** though it should really be "INTEGER".
        **
        ** This is not a problem, as the column type of "t1.col" is never
        ** used. When columnType() is called on the expression 
        ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
        ** branch below.  */
        break;
      }

      assert( pTab && pExpr->pTab==pTab );
      if( pS ){
        /* The "table" is actually a sub-select or a view in the FROM clause
        ** of the SELECT statement. Return the declaration type and origin
        ** data for the result-set column of the sub-select.
        */
        if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
          /* If iCol is less than zero, then the expression requests the
          ** rowid of the sub-select or view. This expression is legal (see 
          ** test case misc2.2.2) - it always evaluates to NULL.
          */
          NameContext sNC;
          Expr *p = pS->pEList->a[iCol].pExpr;
          sNC.pSrcList = pS->pSrc;
          sNC.pNext = pNC;
          sNC.pParse = pNC->pParse;
          zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); 
        }
      }else if( ALWAYS(pTab->pSchema) ){
        /* A real table */
        assert( !pS );
        assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
        if( iCol<0 ){
          zType = "INTEGER";
          zOriginCol = "rowid";
        }else{
          zType = pTab->aCol[iCol].zType;
          zOriginCol = pTab->aCol[iCol].zName;
        }
        zOriginTab = pTab->zName;
        if( pNC->pParse ){
          int iDb = sqlite4SchemaToIndex(pNC->pParse->db, pTab->pSchema);
          zOriginDb = pNC->pParse->db->aDb[iDb].zName;
        }
      }
      break;
    }
#ifndef SQLITE4_OMIT_SUBQUERY
    case TK_SELECT: {
      /* The expression is a sub-select. Return the declaration type and
      ** origin info for the single column in the result set of the SELECT
      ** statement.
      */
      NameContext sNC;
      Select *pS = pExpr->x.pSelect;
      Expr *p = pS->pEList->a[0].pExpr;
      assert( ExprHasProperty(pExpr, EP_xIsSelect) );
      sNC.pSrcList = pS->pSrc;
      sNC.pNext = pNC;
      sNC.pParse = pNC->pParse;
      zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); 
      break;
    }
#endif
  }
  
  if( pzOriginDb ){
    assert( pzOriginTab && pzOriginCol );
    *pzOriginDb = zOriginDb;
    *pzOriginTab = zOriginTab;
    *pzOriginCol = zOriginCol;
  }
  return zType;
}

/*
** Generate code that will tell the VDBE the declaration types of columns
** in the result set.
*/
static void generateColumnTypes(
  Parse *pParse,      /* Parser context */
  SrcList *pTabList,  /* List of tables */
  ExprList *pEList    /* Expressions defining the result set */
){
#ifndef SQLITE4_OMIT_DECLTYPE
  Vdbe *v = pParse->pVdbe;
  int i;
  NameContext sNC;
  sNC.pSrcList = pTabList;
  sNC.pParse = pParse;
  for(i=0; i<pEList->nExpr; i++){
    Expr *p = pEList->a[i].pExpr;
    const char *zType;
#ifdef SQLITE4_ENABLE_COLUMN_METADATA
    const char *zOrigDb = 0;
    const char *zOrigTab = 0;
    const char *zOrigCol = 0;
    zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);

    /* The vdbe must make its own copy of the column-type and other 
    ** column specific strings, in case the schema is reset before this
    ** virtual machine is deleted.
    */
    sqlite4VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, SQLITE4_TRANSIENT);
    sqlite4VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE4_TRANSIENT);
    sqlite4VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE4_TRANSIENT);
#else
    zType = columnType(&sNC, p, 0, 0, 0);
#endif
    sqlite4VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE4_TRANSIENT);
  }
#endif /* SQLITE4_OMIT_DECLTYPE */
}

/*
** Generate code that will tell the VDBE the names of columns
** in the result set.  This information is used to provide the
** azCol[] values in the callback.
*/
static void generateColumnNames(
  Parse *pParse,      /* Parser context */
  SrcList *pTabList,  /* List of tables */
  ExprList *pEList    /* Expressions defining the result set */
){
  Vdbe *v = pParse->pVdbe;
  int i, j;
  sqlite4 *db = pParse->db;

#ifndef SQLITE4_OMIT_EXPLAIN
  /* If this is an EXPLAIN, skip this step */
  if( pParse->explain ){
    return;
  }
#endif

  if( pParse->colNamesSet || NEVER(v==0) || db->mallocFailed ) return;
  pParse->colNamesSet = 1;
  sqlite4VdbeSetNumCols(v, pEList->nExpr);
  for(i=0; i<pEList->nExpr; i++){
    Expr *p;
    p = pEList->a[i].pExpr;
    if( NEVER(p==0) ) continue;
    if( pEList->a[i].zName ){
      char *zName = pEList->a[i].zName;
      sqlite4VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE4_TRANSIENT);
    }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){
      Table *pTab;
      char *zCol;
      int iCol = p->iColumn;
      for(j=0; ALWAYS(j<pTabList->nSrc); j++){
        if( pTabList->a[j].iCursor==p->iTable ) break;
      }
      assert( j<pTabList->nSrc );
      pTab = pTabList->a[j].pTab;
      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
      if( iCol<0 ){
        zCol = "rowid";
      }else{
        zCol = pTab->aCol[iCol].zName;
      }
      sqlite4VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE4_TRANSIENT);
    }else{
      sqlite4VdbeSetColName(v, i, COLNAME_NAME, 
          sqlite4DbStrDup(db, pEList->a[i].zSpan), SQLITE4_DYNAMIC);
    }
  }
  generateColumnTypes(pParse, pTabList, pEList);
}

/*
** Given a an expression list (which is really the list of expressions
** that form the result set of a SELECT statement) compute appropriate
** column names for a table that would hold the expression list.
**
** All column names will be unique.
**
** Only the column names are computed.  Column.zType, Column.zColl,
** and other fields of Column are zeroed.
**
** Return SQLITE4_OK on success.  If a memory allocation error occurs,
** store NULL in *paCol and 0 in *pnCol and return SQLITE4_NOMEM.
*/
static int selectColumnsFromExprList(
  Parse *pParse,          /* Parsing context */
  ExprList *pEList,       /* Expr list from which to derive column names */
  int *pnCol,             /* Write the number of columns here */
  Column **paCol          /* Write the new column list here */
){
  sqlite4 *db = pParse->db;   /* Database connection */
  int i, j;                   /* Loop counters */
  int cnt;                    /* Index added to make the name unique */
  Column *aCol, *pCol;        /* For looping over result columns */
  int nCol;                   /* Number of columns in the result set */
  Expr *p;                    /* Expression for a single result column */
  char *zName;                /* Column name */
  int nName;                  /* Size of name in zName[] */

  *pnCol = nCol = pEList ? pEList->nExpr : 0;
  aCol = *paCol = sqlite4DbMallocZero(db, sizeof(aCol[0])*nCol);
  if( aCol==0 ) return SQLITE4_NOMEM;
  for(i=0, pCol=aCol; i<nCol; i++, pCol++){
    /* Get an appropriate name for the column
    */
    p = pEList->a[i].pExpr;
    assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
               || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
    if( (zName = pEList->a[i].zName)!=0 ){
      /* If the column contains an "AS <name>" phrase, use <name> as the name */
      zName = sqlite4DbStrDup(db, zName);
    }else{
      Expr *pColExpr = p;  /* The expression that is the result column name */
      Table *pTab;         /* Table associated with this expression */
      while( pColExpr->op==TK_DOT ){
        pColExpr = pColExpr->pRight;
        assert( pColExpr!=0 );
      }
      if( pColExpr->op==TK_COLUMN && ALWAYS(pColExpr->pTab!=0) ){
        /* For columns use the column name name */
        int iCol = pColExpr->iColumn;
        pTab = pColExpr->pTab;
        zName = sqlite4MPrintf(db, "%s",
                 iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
      }else if( pColExpr->op==TK_ID ){
        assert( !ExprHasProperty(pColExpr, EP_IntValue) );
        zName = sqlite4MPrintf(db, "%s", pColExpr->u.zToken);
      }else{
        /* Use the original text of the column expression as its name */
        zName = sqlite4MPrintf(db, "%s", pEList->a[i].zSpan);
      }
    }
    if( db->mallocFailed ){
      sqlite4DbFree(db, zName);
      break;
    }

    /* Make sure the column name is unique.  If the name is not unique,
    ** append a integer to the name so that it becomes unique.
    */
    nName = sqlite4Strlen30(zName);
    for(j=cnt=0; j<i; j++){
      if( sqlite4_stricmp(aCol[j].zName, zName)==0 ){
        char *zNewName;
        zName[nName] = 0;
        zNewName = sqlite4MPrintf(db, "%s:%d", zName, ++cnt);
        sqlite4DbFree(db, zName);
        zName = zNewName;
        j = -1;
        if( zName==0 ) break;
      }
    }
    pCol->zName = zName;
  }
  if( db->mallocFailed ){
    for(j=0; j<i; j++){
      sqlite4DbFree(db, aCol[j].zName);
    }
    sqlite4DbFree(db, aCol);
    *paCol = 0;
    *pnCol = 0;
    return SQLITE4_NOMEM;
  }
  return SQLITE4_OK;
}

/*
** Add type and collation information to a column list based on
** a SELECT statement.
** 
** The column list presumably came from selectColumnNamesFromExprList().
** The column list has only names, not types or collations.  This
** routine goes through and adds the types and collations.
**
** This routine requires that all identifiers in the SELECT
** statement be resolved.
*/
static void selectAddColumnTypeAndCollation(
  Parse *pParse,        /* Parsing contexts */
  int nCol,             /* Number of columns */
  Column *aCol,         /* List of columns */
  Select *pSelect       /* SELECT used to determine types and collations */
){
  sqlite4 *db = pParse->db;
  NameContext sNC;
  Column *pCol;
  CollSeq *pColl;
  int i;
  Expr *p;
  ExprListItem *a;

  assert( pSelect!=0 );
  assert( (pSelect->selFlags & SF_Resolved)!=0 );
  assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
  if( db->mallocFailed ) return;
  memset(&sNC, 0, sizeof(sNC));
  sNC.pSrcList = pSelect->pSrc;
  a = pSelect->pEList->a;
  for(i=0, pCol=aCol; i<nCol; i++, pCol++){
    p = a[i].pExpr;
    pCol->zType = sqlite4DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
    pCol->affinity = sqlite4ExprAffinity(p);
    if( pCol->affinity==0 ) pCol->affinity = SQLITE4_AFF_NONE;
    pColl = sqlite4ExprCollSeq(pParse, p);
    if( pColl ){
      pCol->zColl = sqlite4DbStrDup(db, pColl->zName);
    }
  }
}

/*
** Given a SELECT statement, generate a Table structure that describes
** the result set of that SELECT.
*/
SQLITE4_PRIVATE Table *sqlite4ResultSetOfSelect(Parse *pParse, Select *pSelect){
  Table *pTab;
  sqlite4 *db = pParse->db;

  sqlite4SelectPrep(pParse, pSelect, 0);
  if( pParse->nErr ) return 0;
  while( pSelect->pPrior ) pSelect = pSelect->pPrior;
  pTab = sqlite4DbMallocZero(db, sizeof(Table) );
  if( pTab==0 ){
    return 0;
  }
  /* The sqlite4ResultSetOfSelect() is only used n contexts where lookaside
  ** is disabled */
  assert( db->lookaside.bEnabled==0 );
  pTab->nRef = 1;
  pTab->zName = 0;
  pTab->nRowEst = 1000000;
  selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
  selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
  if( db->mallocFailed ){
    sqlite4DeleteTable(db, pTab);
    return 0;
  }
  return pTab;
}

/*
** Get a VDBE for the given parser context.  Create a new one if necessary.
** If an error occurs, return NULL and leave a message in pParse.
*/
SQLITE4_PRIVATE Vdbe *sqlite4GetVdbe(Parse *pParse){
  Vdbe *v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqlite4VdbeCreate(pParse->db);
#ifndef SQLITE4_OMIT_TRACE
    if( v ){
      sqlite4VdbeAddOp0(v, OP_Trace);
    }
#endif
  }
  return v;
}


/*
** Compute the iLimit and iOffset fields of the SELECT based on the
** pLimit and pOffset expressions.  pLimit and pOffset hold the expressions
** that appear in the original SQL statement after the LIMIT and OFFSET
** keywords.  Or NULL if those keywords are omitted. iLimit and iOffset 
** are the integer memory register numbers for counters used to compute 
** the limit and offset.  If there is no limit and/or offset, then 
** iLimit and iOffset are negative.
**
** This routine changes the values of iLimit and iOffset only if
** a limit or offset is defined by pLimit and pOffset.  iLimit and
** iOffset should have been preset to appropriate default values
** (usually but not always -1) prior to calling this routine.
** Only if pLimit!=0 or pOffset!=0 do the limit registers get
** redefined.  The UNION ALL operator uses this property to force
** the reuse of the same limit and offset registers across multiple
** SELECT statements.
*/
static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
  Vdbe *v = 0;
  int iLimit = 0;
  int iOffset;
  int addr1, n;
  if( p->iLimit ) return;

  /* 
  ** "LIMIT -1" always shows all rows.  There is some
  ** contraversy about what the correct behavior should be.
  ** The current implementation interprets "LIMIT 0" to mean
  ** no rows.
  */
  sqlite4ExprCacheClear(pParse);
  assert( p->pOffset==0 || p->pLimit!=0 );
  if( p->pLimit ){
    p->iLimit = iLimit = ++pParse->nMem;
    v = sqlite4GetVdbe(pParse);
    if( NEVER(v==0) ) return;  /* VDBE should have already been allocated */
    if( sqlite4ExprIsInteger(p->pLimit, &n) ){
      sqlite4VdbeAddOp2(v, OP_Integer, n, iLimit);
      VdbeComment((v, "LIMIT counter"));
      if( n==0 ){
        sqlite4VdbeAddOp2(v, OP_Goto, 0, iBreak);
      }else{
        if( p->nSelectRow > (double)n ) p->nSelectRow = (double)n;
      }
    }else{
      sqlite4ExprCode(pParse, p->pLimit, iLimit);
      sqlite4VdbeAddOp1(v, OP_MustBeInt, iLimit);
      VdbeComment((v, "LIMIT counter"));
      sqlite4VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
    }
    if( p->pOffset ){
      p->iOffset = iOffset = ++pParse->nMem;
      pParse->nMem++;   /* Allocate an extra register for limit+offset */
      sqlite4ExprCode(pParse, p->pOffset, iOffset);
      sqlite4VdbeAddOp1(v, OP_MustBeInt, iOffset);
      VdbeComment((v, "OFFSET counter"));
      addr1 = sqlite4VdbeAddOp1(v, OP_IfPos, iOffset);
      sqlite4VdbeAddOp2(v, OP_Integer, 0, iOffset);
      sqlite4VdbeJumpHere(v, addr1);
      sqlite4VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
      VdbeComment((v, "LIMIT+OFFSET"));
      addr1 = sqlite4VdbeAddOp1(v, OP_IfPos, iLimit);
      sqlite4VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
      sqlite4VdbeJumpHere(v, addr1);
    }
  }
}

#ifndef SQLITE4_OMIT_COMPOUND_SELECT
/*
** Return the appropriate collating sequence for the iCol-th column of
** the result set for the compound-select statement "p".  Return NULL if
** the column has no default collating sequence.
**
** The collating sequence for the compound select is taken from the
** left-most term of the select that has a collating sequence.
*/
static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
  CollSeq *pRet;
  if( p->pPrior ){
    pRet = multiSelectCollSeq(pParse, p->pPrior, iCol);
  }else{
    pRet = 0;
  }
  assert( iCol>=0 );
  if( pRet==0 && iCol<p->pEList->nExpr ){
    pRet = sqlite4ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);
  }
  return pRet;
}
#endif /* SQLITE4_OMIT_COMPOUND_SELECT */

/* Forward reference */
static int multiSelectOrderBy(
  Parse *pParse,        /* Parsing context */
  Select *p,            /* The right-most of SELECTs to be coded */
  SelectDest *pDest     /* What to do with query results */
);


#ifndef SQLITE4_OMIT_COMPOUND_SELECT
/*
** This routine is called to process a compound query form from
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
** INTERSECT
**
** "p" points to the right-most of the two queries.  the query on the
** left is p->pPrior.  The left query could also be a compound query
** in which case this routine will be called recursively. 
**
** The results of the total query are to be written into a destination
** of type eDest with parameter iParm.
**
** Example 1:  Consider a three-way compound SQL statement.
**
**     SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3
**
** This statement is parsed up as follows:
**
**     SELECT c FROM t3
**      |
**      `----->  SELECT b FROM t2
**                |
**                `------>  SELECT a FROM t1
**
** The arrows in the diagram above represent the Select.pPrior pointer.
** So if this routine is called with p equal to the t3 query, then
** pPrior will be the t2 query.  p->op will be TK_UNION in this case.
**
** Notice that because of the way SQLite parses compound SELECTs, the
** individual selects always group from left to right.
*/
static int multiSelect(
  Parse *pParse,        /* Parsing context */
  Select *p,            /* The right-most of SELECTs to be coded */
  SelectDest *pDest     /* What to do with query results */
){
  int rc = SQLITE4_OK;   /* Success code from a subroutine */
  Select *pPrior;       /* Another SELECT immediately to our left */
  Vdbe *v;              /* Generate code to this VDBE */
  SelectDest dest;      /* Alternative data destination */
  Select *pDelete = 0;  /* Chain of simple selects to delete */
  sqlite4 *db;          /* Database connection */
#ifndef SQLITE4_OMIT_EXPLAIN
  int iSub1;            /* EQP id of left-hand query */
  int iSub2;            /* EQP id of right-hand query */
#endif

  /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
  */
  assert( p && p->pPrior );  /* Calling function guarantees this much */
  db = pParse->db;
  pPrior = p->pPrior;
  assert( pPrior->pRightmost!=pPrior );
  assert( pPrior->pRightmost==p->pRightmost );
  dest = *pDest;
  if( pPrior->pOrderBy ){
    sqlite4ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
      selectOpName(p->op));
    rc = 1;
    goto multi_select_end;
  }
  if( pPrior->pLimit ){
    sqlite4ErrorMsg(pParse,"LIMIT clause should come after %s not before",
      selectOpName(p->op));
    rc = 1;
    goto multi_select_end;
  }

  v = sqlite4GetVdbe(pParse);
  assert( v!=0 );  /* The VDBE already created by calling function */

  /* Create the destination temporary table if necessary
  */
  if( dest.eDest==SRT_EphemTab ){
    assert( p->pEList );
    sqlite4VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr);
    dest.eDest = SRT_Table;
  }

  /* Make sure all SELECTs in the statement have the same number of elements
  ** in their result sets.
  */
  assert( p->pEList && pPrior->pEList );
  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
    if( p->selFlags & SF_Values ){
      sqlite4ErrorMsg(pParse, "all VALUES must have the same number of terms");
    }else{
      sqlite4ErrorMsg(pParse, "SELECTs to the left and right of %s"
        " do not have the same number of result columns", selectOpName(p->op));
    }
    rc = 1;
    goto multi_select_end;
  }

  /* Compound SELECTs that have an ORDER BY clause are handled separately.
  */
  if( p->pOrderBy ){
    return multiSelectOrderBy(pParse, p, pDest);
  }

  /* Generate code for the left and right SELECT statements.
  */
  switch( p->op ){
    case TK_ALL: {
      int addr = 0;
      int nLimit;
      assert( !pPrior->pLimit );
      pPrior->pLimit = p->pLimit;
      pPrior->pOffset = p->pOffset;
      explainSetInteger(iSub1, pParse->iNextSelectId);
      rc = sqlite4Select(pParse, pPrior, &dest);
      p->pLimit = 0;
      p->pOffset = 0;
      if( rc ){
        goto multi_select_end;
      }
      p->pPrior = 0;
      p->iLimit = pPrior->iLimit;
      p->iOffset = pPrior->iOffset;
      if( p->iLimit ){
        addr = sqlite4VdbeAddOp1(v, OP_IfZero, p->iLimit);
        VdbeComment((v, "Jump ahead if LIMIT reached"));
      }
      explainSetInteger(iSub2, pParse->iNextSelectId);
      rc = sqlite4Select(pParse, p, &dest);
      testcase( rc!=SQLITE4_OK );
      pDelete = p->pPrior;
      p->pPrior = pPrior;
      p->nSelectRow += pPrior->nSelectRow;
      if( pPrior->pLimit
       && sqlite4ExprIsInteger(pPrior->pLimit, &nLimit)
       && p->nSelectRow > (double)nLimit 
      ){
        p->nSelectRow = (double)nLimit;
      }
      if( addr ){
        sqlite4VdbeJumpHere(v, addr);
      }
      break;
    }
    case TK_EXCEPT:
    case TK_UNION: {
      int unionTab;    /* Cursor number of the temporary table holding result */
      u8 op = 0;       /* One of the SRT_ operations to apply to self */
      int priorOp;     /* The SRT_ operation to apply to prior selects */
      Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */
      int addr;
      SelectDest uniondest;

      testcase( p->op==TK_EXCEPT );
      testcase( p->op==TK_UNION );
      priorOp = SRT_Union;
      if( dest.eDest==priorOp && ALWAYS(!p->pLimit &&!p->pOffset) ){
        /* We can reuse a temporary table generated by a SELECT to our
        ** right.
        */
        assert( p->pRightmost!=p );  /* Can only happen for leftward elements
                                     ** of a 3-way or more compound */
        assert( p->pLimit==0 );      /* Not allowed on leftward elements */
        assert( p->pOffset==0 );     /* Not allowed on leftward elements */
        unionTab = dest.iParm;
      }else{
        /* We will need to create our own temporary table to hold the
        ** intermediate results.
        */
        unionTab = pParse->nTab++;
        assert( p->pOrderBy==0 );
        addr = sqlite4VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
        assert( p->addrOpenEphm[0] == -1 );
        p->addrOpenEphm[0] = addr;
        p->pRightmost->selFlags |= SF_UsesEphemeral;
        assert( p->pEList );
      }

      /* Code the SELECT statements to our left
      */
      assert( !pPrior->pOrderBy );
      sqlite4SelectDestInit(&uniondest, priorOp, unionTab);
      explainSetInteger(iSub1, pParse->iNextSelectId);
      rc = sqlite4Select(pParse, pPrior, &uniondest);
      if( rc ){
        goto multi_select_end;
      }

      /* Code the current SELECT statement
      */
      if( p->op==TK_EXCEPT ){
        op = SRT_Except;
      }else{
        assert( p->op==TK_UNION );
        op = SRT_Union;
      }
      p->pPrior = 0;
      pLimit = p->pLimit;
      p->pLimit = 0;
      pOffset = p->pOffset;
      p->pOffset = 0;
      uniondest.eDest = op;
      explainSetInteger(iSub2, pParse->iNextSelectId);
      rc = sqlite4Select(pParse, p, &uniondest);
      testcase( rc!=SQLITE4_OK );
      /* Query flattening in sqlite4Select() might refill p->pOrderBy.
      ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
      sqlite4ExprListDelete(db, p->pOrderBy);
      pDelete = p->pPrior;
      p->pPrior = pPrior;
      p->pOrderBy = 0;
      if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
      sqlite4ExprDelete(db, p->pLimit);
      p->pLimit = pLimit;
      p->pOffset = pOffset;
      p->iLimit = 0;
      p->iOffset = 0;

      /* Convert the data in the temporary table into whatever form
      ** it is that we currently need.
      */
      assert( unionTab==dest.iParm || dest.eDest!=priorOp );
      if( dest.eDest!=priorOp ){
        int iCont, iBreak, iStart;
        assert( p->pEList );
        if( dest.eDest==SRT_Output ){
          Select *pFirst = p;
          while( pFirst->pPrior ) pFirst = pFirst->pPrior;
          generateColumnNames(pParse, 0, pFirst->pEList);
        }
        iBreak = sqlite4VdbeMakeLabel(v);
        iCont = sqlite4VdbeMakeLabel(v);
        computeLimitRegisters(pParse, p, iBreak);
        sqlite4VdbeAddOp2(v, OP_Rewind, unionTab, iBreak);
        iStart = sqlite4VdbeCurrentAddr(v);
        selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
                        0, -1, &dest, iCont, iBreak);
        sqlite4VdbeResolveLabel(v, iCont);
        sqlite4VdbeAddOp2(v, OP_Next, unionTab, iStart);
        sqlite4VdbeResolveLabel(v, iBreak);
        sqlite4VdbeAddOp2(v, OP_Close, unionTab, 0);
      }
      break;
    }
    default: assert( p->op==TK_INTERSECT ); {
      int tab1, tab2;
      int iCont, iBreak, iStart;
      Expr *pLimit, *pOffset;
      int addr;
      SelectDest intersectdest;
      int r1;

      /* INTERSECT is different from the others since it requires
      ** two temporary tables.  Hence it has its own case.  Begin
      ** by allocating the tables we will need.
      */
      tab1 = pParse->nTab++;
      tab2 = pParse->nTab++;
      assert( p->pOrderBy==0 );

      addr = sqlite4VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
      assert( p->addrOpenEphm[0] == -1 );
      p->addrOpenEphm[0] = addr;
      p->pRightmost->selFlags |= SF_UsesEphemeral;
      assert( p->pEList );

      /* Code the SELECTs to our left into temporary table "tab1".
      */
      sqlite4SelectDestInit(&intersectdest, SRT_Union, tab1);
      explainSetInteger(iSub1, pParse->iNextSelectId);
      rc = sqlite4Select(pParse, pPrior, &intersectdest);
      if( rc ){
        goto multi_select_end;
      }

      /* Code the current SELECT into temporary table "tab2"
      */
      addr = sqlite4VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
      assert( p->addrOpenEphm[1] == -1 );
      p->addrOpenEphm[1] = addr;
      p->pPrior = 0;
      pLimit = p->pLimit;
      p->pLimit = 0;
      pOffset = p->pOffset;
      p->pOffset = 0;
      intersectdest.iParm = tab2;
      explainSetInteger(iSub2, pParse->iNextSelectId);
      rc = sqlite4Select(pParse, p, &intersectdest);
      testcase( rc!=SQLITE4_OK );
      pDelete = p->pPrior;
      p->pPrior = pPrior;
      if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
      sqlite4ExprDelete(db, p->pLimit);
      p->pLimit = pLimit;
      p->pOffset = pOffset;

      /* Generate code to take the intersection of the two temporary
      ** tables.
      */
      assert( p->pEList );
      if( dest.eDest==SRT_Output ){
        Select *pFirst = p;
        while( pFirst->pPrior ) pFirst = pFirst->pPrior;
        generateColumnNames(pParse, 0, pFirst->pEList);
      }
      iBreak = sqlite4VdbeMakeLabel(v);
      iCont = sqlite4VdbeMakeLabel(v);
      computeLimitRegisters(pParse, p, iBreak);
      sqlite4VdbeAddOp2(v, OP_Rewind, tab1, iBreak);
      r1 = sqlite4GetTempReg(pParse);
      iStart = sqlite4VdbeAddOp2(v, OP_RowKey, tab1, r1);
      sqlite4VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0);
      sqlite4ReleaseTempReg(pParse, r1);
      selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
                      0, -1, &dest, iCont, iBreak);
      sqlite4VdbeResolveLabel(v, iCont);
      sqlite4VdbeAddOp2(v, OP_Next, tab1, iStart);
      sqlite4VdbeResolveLabel(v, iBreak);
      sqlite4VdbeAddOp2(v, OP_Close, tab2, 0);
      sqlite4VdbeAddOp2(v, OP_Close, tab1, 0);
      break;
    }
  }

  explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL);

  /* Compute collating sequences used by 
  ** temporary tables needed to implement the compound select.
  ** Attach the KeyInfo structure to all temporary tables.
  **
  ** This section is run by the right-most SELECT statement only.
  ** SELECT statements to the left always skip this part.  The right-most
  ** SELECT might also skip this part if it has no ORDER BY clause and
  ** no temp tables are required.
  */
  if( p->selFlags & SF_UsesEphemeral ){
    int i;                        /* Loop counter */
    KeyInfo *pKeyInfo;            /* Collating sequence for the result set */
    Select *pLoop;                /* For looping through SELECT statements */
    CollSeq **apColl;             /* For looping through pKeyInfo->aColl[] */
    int nCol;                     /* Number of columns in result set */

    assert( p->pRightmost==p );
    nCol = p->pEList->nExpr;
    pKeyInfo = sqlite4DbMallocZero(db,
                       sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));
    if( !pKeyInfo ){
      rc = SQLITE4_NOMEM;
      goto multi_select_end;
    }

    pKeyInfo->nField = (u16)nCol;

    for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
      *apColl = multiSelectCollSeq(pParse, p, i);
      if( 0==*apColl ){
        *apColl = db->pDfltColl;
      }
    }

    for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
      for(i=0; i<2; i++){
        int addr = pLoop->addrOpenEphm[i];
        if( addr<0 ){
          /* If [0] is unused then [1] is also unused.  So we can
          ** always safely abort as soon as the first unused slot is found */
          assert( pLoop->addrOpenEphm[1]<0 );
          break;
        }
        sqlite4VdbeChangeP2(v, addr, nCol);
        sqlite4VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO);
        pLoop->addrOpenEphm[i] = -1;
      }
    }
    sqlite4DbFree(db, pKeyInfo);
  }

multi_select_end:
  pDest->iMem = dest.iMem;
  pDest->nMem = dest.nMem;
  sqlite4SelectDelete(db, pDelete);
  return rc;
}
#endif /* SQLITE4_OMIT_COMPOUND_SELECT */

/*
** Code an output subroutine for a coroutine implementation of a
** SELECT statment.
**
** The data to be output is contained in pIn->iMem.  There are
** pIn->nMem columns to be output.  pDest is where the output should
** be sent.
**
** regReturn is the number of the register holding the subroutine
** return address.
**
** If regPrev>0 then it is the first register in a vector that
** records the previous output.  mem[regPrev] is a flag that is false
** if there has been no previous output.  If regPrev>0 then code is
** generated to suppress duplicates.  pKeyInfo is used for comparing
** keys.
**
** If the LIMIT found in p->iLimit is reached, jump immediately to
** iBreak.
*/
static int generateOutputSubroutine(
  Parse *pParse,          /* Parsing context */
  Select *p,              /* The SELECT statement */
  SelectDest *pIn,        /* Coroutine supplying data */
  SelectDest *pDest,      /* Where to send the data */
  int regReturn,          /* The return address register */
  int regPrev,            /* Previous result register.  No uniqueness if 0 */
  KeyInfo *pKeyInfo,      /* For comparing with previous entry */
  int p4type,             /* The p4 type for pKeyInfo */
  int iBreak              /* Jump here if we hit the LIMIT */
){
  Vdbe *v = pParse->pVdbe;
  int iContinue;
  int addr;

  addr = sqlite4VdbeCurrentAddr(v);
  iContinue = sqlite4VdbeMakeLabel(v);

  /* Suppress duplicates for UNION, EXCEPT, and INTERSECT 
  */
  if( regPrev ){
    int j1, j2;
    j1 = sqlite4VdbeAddOp1(v, OP_IfNot, regPrev);
    j2 = sqlite4VdbeAddOp4(v, OP_Compare, pIn->iMem, regPrev+1, pIn->nMem,
                              (char*)pKeyInfo, p4type);
    sqlite4VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
    sqlite4VdbeJumpHere(v, j1);
    sqlite4ExprCodeCopy(pParse, pIn->iMem, regPrev+1, pIn->nMem);
    sqlite4VdbeAddOp2(v, OP_Integer, 1, regPrev);
  }
  if( pParse->db->mallocFailed ) return 0;

  /* Suppress the the first OFFSET entries if there is an OFFSET clause
  */
  codeOffset(v, p, iContinue);

  switch( pDest->eDest ){
    /* Store the result as data using a unique key.
    */
    case SRT_Table:
    case SRT_EphemTab: {
      int r1 = sqlite4GetTempReg(pParse);
      int r2 = sqlite4GetTempReg(pParse);
      testcase( pDest->eDest==SRT_Table );
      testcase( pDest->eDest==SRT_EphemTab );
      sqlite4VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1);
      sqlite4VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2);
      sqlite4VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2);
      sqlite4ReleaseTempReg(pParse, r2);
      sqlite4ReleaseTempReg(pParse, r1);
      break;
    }

#ifndef SQLITE4_OMIT_SUBQUERY
    /* If we are creating a set for an "expr IN (SELECT ...)" construct,
    ** then there should be a single item on the stack.  Write this
    ** item into the set table with bogus data.
    */
    case SRT_Set: {
      int r1, r2;
      assert( pIn->nMem==1 );
      p->affinity = 
         sqlite4CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity);
      r1 = sqlite4GetTempReg(pParse);
      r2 = sqlite4GetTempReg(pParse);
      sqlite4VdbeAddOp4(v, OP_Affinity, pIn->iMem, 1, 0, &p->affinity, 1);
      sqlite4ExprCacheAffinityChange(pParse, pIn->iMem, 1);
      sqlite4VdbeAddOp4Int(v, OP_MakeKey, pIn->iMem, 1, r2, pDest->iParm);
      sqlite4VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, 1, r1);
      sqlite4VdbeChangeP5(v, OPFLAG_USEKEY);
      sqlite4VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2);
      sqlite4ReleaseTempReg(pParse, r1);
      sqlite4ReleaseTempReg(pParse, r2);
      break;
    }

#if 0  /* Never occurs on an ORDER BY query */
    /* If any row exist in the result set, record that fact and abort.
    */
    case SRT_Exists: {
      sqlite4VdbeAddOp2(v, OP_Integer, 1, pDest->iParm);
      /* The LIMIT clause will terminate the loop for us */
      break;
    }
#endif

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    */
    case SRT_Mem: {
      assert( pIn->nMem==1 );
      sqlite4ExprCodeMove(pParse, pIn->iMem, pDest->iParm, 1);
      /* The LIMIT clause will jump out of the loop for us */
      break;
    }
#endif /* #ifndef SQLITE4_OMIT_SUBQUERY */

    /* The results are stored in a sequence of registers
    ** starting at pDest->iMem.  Then the co-routine yields.
    */
    case SRT_Coroutine: {
      if( pDest->iMem==0 ){
        pDest->iMem = sqlite4GetTempRange(pParse, pIn->nMem);
        pDest->nMem = pIn->nMem;
      }
      sqlite4ExprCodeMove(pParse, pIn->iMem, pDest->iMem, pDest->nMem);
      sqlite4VdbeAddOp1(v, OP_Yield, pDest->iParm);
      break;
    }

    /* If none of the above, then the result destination must be
    ** SRT_Output.  This routine is never called with any other
    ** destination other than the ones handled above or SRT_Output.
    **
    ** For SRT_Output, results are stored in a sequence of registers.  
    ** Then the OP_ResultRow opcode is used to cause sqlite4_step() to
    ** return the next row of result.
    */
    default: {
      assert( pDest->eDest==SRT_Output );
      sqlite4VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem);
      sqlite4ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem);
      break;
    }
  }

  /* Jump to the end of the loop if the LIMIT is reached.
  */
  if( p->iLimit ){
    sqlite4VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1);
  }

  /* Generate the subroutine return
  */
  sqlite4VdbeResolveLabel(v, iContinue);
  sqlite4VdbeAddOp1(v, OP_Return, regReturn);

  return addr;
}

/*
** Alternative compound select code generator for cases when there
** is an ORDER BY clause.
**
** We assume a query of the following form:
**
**      <selectA>  <operator>  <selectB>  ORDER BY <orderbylist>
**
** <operator> is one of UNION ALL, UNION, EXCEPT, or INTERSECT.  The idea
** is to code both <selectA> and <selectB> with the ORDER BY clause as
** co-routines.  Then run the co-routines in parallel and merge the results
** into the output.  In addition to the two coroutines (called selectA and
** selectB) there are 7 subroutines:
**
**    outA:    Move the output of the selectA coroutine into the output
**             of the compound query.
**
**    outB:    Move the output of the selectB coroutine into the output
**             of the compound query.  (Only generated for UNION and
**             UNION ALL.  EXCEPT and INSERTSECT never output a row that
**             appears only in B.)
**
**    AltB:    Called when there is data from both coroutines and A<B.
**
**    AeqB:    Called when there is data from both coroutines and A==B.
**
**    AgtB:    Called when there is data from both coroutines and A>B.
**
**    EofA:    Called when data is exhausted from selectA.
**
**    EofB:    Called when data is exhausted from selectB.
**
** The implementation of the latter five subroutines depend on which 
** <operator> is used:
**
**
**             UNION ALL         UNION            EXCEPT          INTERSECT
**          -------------  -----------------  --------------  -----------------
**   AltB:   outA, nextA      outA, nextA       outA, nextA         nextA
**
**   AeqB:   outA, nextA         nextA             nextA         outA, nextA
**
**   AgtB:   outB, nextB      outB, nextB          nextB            nextB
**
**   EofA:   outB, nextB      outB, nextB          halt             halt
**
**   EofB:   outA, nextA      outA, nextA       outA, nextA         halt
**
** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA
** causes an immediate jump to EofA and an EOF on B following nextB causes
** an immediate jump to EofB.  Within EofA and EofB, and EOF on entry or
** following nextX causes a jump to the end of the select processing.
**
** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled
** within the output subroutine.  The regPrev register set holds the previously
** output value.  A comparison is made against this value and the output
** is skipped if the next results would be the same as the previous.
**
** The implementation plan is to implement the two coroutines and seven
** subroutines first, then put the control logic at the bottom.  Like this:
**
**          goto Init
**     coA: coroutine for left query (A)
**     coB: coroutine for right query (B)
**    outA: output one row of A
**    outB: output one row of B (UNION and UNION ALL only)
**    EofA: ...
**    EofB: ...
**    AltB: ...
**    AeqB: ...
**    AgtB: ...
**    Init: initialize coroutine registers
**          yield coA
**          if eof(A) goto EofA
**          yield coB
**          if eof(B) goto EofB
**    Cmpr: Compare A, B
**          Jump AltB, AeqB, AgtB
**     End: ...
**
** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not
** actually called using Gosub and they do not Return.  EofA and EofB loop
** until all data is exhausted then jump to the "end" labe.  AltB, AeqB,
** and AgtB jump to either L2 or to one of EofA or EofB.
*/
#ifndef SQLITE4_OMIT_COMPOUND_SELECT
static int multiSelectOrderBy(
  Parse *pParse,        /* Parsing context */
  Select *p,            /* The right-most of SELECTs to be coded */
  SelectDest *pDest     /* What to do with query results */
){
  int i, j;             /* Loop counters */
  Select *pPrior;       /* Another SELECT immediately to our left */
  Vdbe *v;              /* Generate code to this VDBE */
  SelectDest destA;     /* Destination for coroutine A */
  SelectDest destB;     /* Destination for coroutine B */
  int regAddrA;         /* Address register for select-A coroutine */
  int regEofA;          /* Flag to indicate when select-A is complete */
  int regAddrB;         /* Address register for select-B coroutine */
  int regEofB;          /* Flag to indicate when select-B is complete */
  int addrSelectA;      /* Address of the select-A coroutine */
  int addrSelectB;      /* Address of the select-B coroutine */
  int regOutA;          /* Address register for the output-A subroutine */
  int regOutB;          /* Address register for the output-B subroutine */
  int addrOutA;         /* Address of the output-A subroutine */
  int addrOutB = 0;     /* Address of the output-B subroutine */
  int addrEofA;         /* Address of the select-A-exhausted subroutine */
  int addrEofB;         /* Address of the select-B-exhausted subroutine */
  int addrAltB;         /* Address of the A<B subroutine */
  int addrAeqB;         /* Address of the A==B subroutine */
  int addrAgtB;         /* Address of the A>B subroutine */
  int regLimitA;        /* Limit register for select-A */
  int regLimitB;        /* Limit register for select-A */
  int regPrev;          /* A range of registers to hold previous output */
  int savedLimit;       /* Saved value of p->iLimit */
  int savedOffset;      /* Saved value of p->iOffset */
  int labelCmpr;        /* Label for the start of the merge algorithm */
  int labelEnd;         /* Label for the end of the overall SELECT stmt */
  int j1;               /* Jump instructions that get retargetted */
  int op;               /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
  KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
  KeyInfo *pKeyMerge;   /* Comparison information for merging rows */
  sqlite4 *db;          /* Database connection */
  ExprList *pOrderBy;   /* The ORDER BY clause */
  int nOrderBy;         /* Number of terms in the ORDER BY clause */
  int *aPermute;        /* Mapping from ORDER BY terms to result set columns */
#ifndef SQLITE4_OMIT_EXPLAIN
  int iSub1;            /* EQP id of left-hand query */
  int iSub2;            /* EQP id of right-hand query */
#endif

  assert( p->pOrderBy!=0 );
  assert( pKeyDup==0 ); /* "Managed" code needs this.  Ticket #3382. */
  db = pParse->db;
  v = pParse->pVdbe;
  assert( v!=0 );       /* Already thrown the error if VDBE alloc failed */
  labelEnd = sqlite4VdbeMakeLabel(v);
  labelCmpr = sqlite4VdbeMakeLabel(v);


  /* Patch up the ORDER BY clause
  */
  op = p->op;  
  pPrior = p->pPrior;
  assert( pPrior->pOrderBy==0 );
  pOrderBy = p->pOrderBy;
  assert( pOrderBy );
  nOrderBy = pOrderBy->nExpr;

  /* For operators other than UNION ALL we have to make sure that
  ** the ORDER BY clause covers every term of the result set.  Add
  ** terms to the ORDER BY clause as necessary.
  */
  if( op!=TK_ALL ){
    for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
      ExprListItem *pItem;
      for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
        assert( pItem->iOrderByCol>0 );
        if( pItem->iOrderByCol==i ) break;
      }
      if( j==nOrderBy ){
        Expr *pNew = sqlite4Expr(db, TK_INTEGER, 0);
        if( pNew==0 ) return SQLITE4_NOMEM;
        pNew->flags |= EP_IntValue;
        pNew->u.iValue = i;
        pOrderBy = sqlite4ExprListAppend(pParse, pOrderBy, pNew);
        pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i;
      }
    }
  }

  /* Compute the comparison permutation and keyinfo that is used with
  ** the permutation used to determine if the next
  ** row of results comes from selectA or selectB.  Also add explicit
  ** collations to the ORDER BY clause terms so that when the subqueries
  ** to the right and the left are evaluated, they use the correct
  ** collation.
  */
  aPermute = sqlite4DbMallocRaw(db, sizeof(int)*nOrderBy);
  if( aPermute ){
    ExprListItem *pItem;
    for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
      assert( pItem->iOrderByCol>0  && pItem->iOrderByCol<=p->pEList->nExpr );
      aPermute[i] = pItem->iOrderByCol - 1;
    }
    pKeyMerge =
      sqlite4DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
    if( pKeyMerge ){
      pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy];
      pKeyMerge->nField = (u16)nOrderBy;
      for(i=0; i<nOrderBy; i++){
        CollSeq *pColl;
        Expr *pTerm = pOrderBy->a[i].pExpr;
        if( pTerm->flags & EP_ExpCollate ){
          pColl = pTerm->pColl;
        }else{
          pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
          pTerm->flags |= EP_ExpCollate;
          pTerm->pColl = pColl;
        }
        pKeyMerge->aColl[i] = pColl;
        pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
      }
    }
  }else{
    pKeyMerge = 0;
  }

  /* Reattach the ORDER BY clause to the query.
  */
  p->pOrderBy = pOrderBy;
  pPrior->pOrderBy = sqlite4ExprListDup(pParse->db, pOrderBy, 0);

  /* Allocate a range of temporary registers and the KeyInfo needed
  ** for the logic that removes duplicate result rows when the
  ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
  */
  if( op==TK_ALL ){
    regPrev = 0;
  }else{
    int nExpr = p->pEList->nExpr;
    assert( nOrderBy>=nExpr || db->mallocFailed );
    regPrev = pParse->nMem + 1;
    pParse->nMem += nExpr + 1;
    sqlite4VdbeAddOp2(v, OP_Integer, 0, regPrev);
    pKeyDup = sqlite4DbMallocZero(db,
                  sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
    if( pKeyDup ){
      pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr];
      pKeyDup->nField = (u16)nExpr;
      for(i=0; i<nExpr; i++){
        pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
        pKeyDup->aSortOrder[i] = 0;
      }
    }
  }
 
  /* Separate the left and the right query from one another
  */
  p->pPrior = 0;
  sqlite4ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
  if( pPrior->pPrior==0 ){
    sqlite4ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
  }

  /* Compute the limit registers */
  computeLimitRegisters(pParse, p, labelEnd);
  if( p->iLimit && op==TK_ALL ){
    regLimitA = ++pParse->nMem;
    regLimitB = ++pParse->nMem;
    sqlite4VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit,
                                  regLimitA);
    sqlite4VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB);
  }else{
    regLimitA = regLimitB = 0;
  }
  sqlite4ExprDelete(db, p->pLimit);
  p->pLimit = 0;
  sqlite4ExprDelete(db, p->pOffset);
  p->pOffset = 0;

  regAddrA = ++pParse->nMem;
  regEofA = ++pParse->nMem;
  regAddrB = ++pParse->nMem;
  regEofB = ++pParse->nMem;
  regOutA = ++pParse->nMem;
  regOutB = ++pParse->nMem;
  sqlite4SelectDestInit(&destA, SRT_Coroutine, regAddrA);
  sqlite4SelectDestInit(&destB, SRT_Coroutine, regAddrB);

  /* Jump past the various subroutines and coroutines to the main
  ** merge loop
  */
  j1 = sqlite4VdbeAddOp0(v, OP_Goto);
  addrSelectA = sqlite4VdbeCurrentAddr(v);


  /* Generate a coroutine to evaluate the SELECT statement to the
  ** left of the compound operator - the "A" select.
  */
  VdbeNoopComment((v, "Begin coroutine for left SELECT"));
  pPrior->iLimit = regLimitA;
  explainSetInteger(iSub1, pParse->iNextSelectId);
  sqlite4Select(pParse, pPrior, &destA);
  sqlite4VdbeAddOp2(v, OP_Integer, 1, regEofA);
  sqlite4VdbeAddOp1(v, OP_Yield, regAddrA);
  VdbeNoopComment((v, "End coroutine for left SELECT"));

  /* Generate a coroutine to evaluate the SELECT statement on 
  ** the right - the "B" select
  */
  addrSelectB = sqlite4VdbeCurrentAddr(v);
  VdbeNoopComment((v, "Begin coroutine for right SELECT"));
  savedLimit = p->iLimit;
  savedOffset = p->iOffset;
  p->iLimit = regLimitB;
  p->iOffset = 0;  
  explainSetInteger(iSub2, pParse->iNextSelectId);
  sqlite4Select(pParse, p, &destB);
  p->iLimit = savedLimit;
  p->iOffset = savedOffset;
  sqlite4VdbeAddOp2(v, OP_Integer, 1, regEofB);
  sqlite4VdbeAddOp1(v, OP_Yield, regAddrB);
  VdbeNoopComment((v, "End coroutine for right SELECT"));

  /* Generate a subroutine that outputs the current row of the A
  ** select as the next output row of the compound select.
  */
  VdbeNoopComment((v, "Output routine for A"));
  addrOutA = generateOutputSubroutine(pParse,
                 p, &destA, pDest, regOutA,
                 regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd);
  
  /* Generate a subroutine that outputs the current row of the B
  ** select as the next output row of the compound select.
  */
  if( op==TK_ALL || op==TK_UNION ){
    VdbeNoopComment((v, "Output routine for B"));
    addrOutB = generateOutputSubroutine(pParse,
                 p, &destB, pDest, regOutB,
                 regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd);
  }

  /* Generate a subroutine to run when the results from select A
  ** are exhausted and only data in select B remains.
  */
  VdbeNoopComment((v, "eof-A subroutine"));
  if( op==TK_EXCEPT || op==TK_INTERSECT ){
    addrEofA = sqlite4VdbeAddOp2(v, OP_Goto, 0, labelEnd);
  }else{  
    addrEofA = sqlite4VdbeAddOp2(v, OP_If, regEofB, labelEnd);
    sqlite4VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
    sqlite4VdbeAddOp1(v, OP_Yield, regAddrB);
    sqlite4VdbeAddOp2(v, OP_Goto, 0, addrEofA);
    p->nSelectRow += pPrior->nSelectRow;
  }

  /* Generate a subroutine to run when the results from select B
  ** are exhausted and only data in select A remains.
  */
  if( op==TK_INTERSECT ){
    addrEofB = addrEofA;
    if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
  }else{  
    VdbeNoopComment((v, "eof-B subroutine"));
    addrEofB = sqlite4VdbeAddOp2(v, OP_If, regEofA, labelEnd);
    sqlite4VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
    sqlite4VdbeAddOp1(v, OP_Yield, regAddrA);
    sqlite4VdbeAddOp2(v, OP_Goto, 0, addrEofB);
  }

  /* Generate code to handle the case of A<B
  */
  VdbeNoopComment((v, "A-lt-B subroutine"));
  addrAltB = sqlite4VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
  sqlite4VdbeAddOp1(v, OP_Yield, regAddrA);
  sqlite4VdbeAddOp2(v, OP_If, regEofA, addrEofA);
  sqlite4VdbeAddOp2(v, OP_Goto, 0, labelCmpr);

  /* Generate code to handle the case of A==B
  */
  if( op==TK_ALL ){
    addrAeqB = addrAltB;
  }else if( op==TK_INTERSECT ){
    addrAeqB = addrAltB;
    addrAltB++;
  }else{
    VdbeNoopComment((v, "A-eq-B subroutine"));
    addrAeqB =
    sqlite4VdbeAddOp1(v, OP_Yield, regAddrA);
    sqlite4VdbeAddOp2(v, OP_If, regEofA, addrEofA);
    sqlite4VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
  }

  /* Generate code to handle the case of A>B
  */
  VdbeNoopComment((v, "A-gt-B subroutine"));
  addrAgtB = sqlite4VdbeCurrentAddr(v);
  if( op==TK_ALL || op==TK_UNION ){
    sqlite4VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
  }
  sqlite4VdbeAddOp1(v, OP_Yield, regAddrB);
  sqlite4VdbeAddOp2(v, OP_If, regEofB, addrEofB);
  sqlite4VdbeAddOp2(v, OP_Goto, 0, labelCmpr);

  /* This code runs once to initialize everything.
  */
  sqlite4VdbeJumpHere(v, j1);
  sqlite4VdbeAddOp2(v, OP_Integer, 0, regEofA);
  sqlite4VdbeAddOp2(v, OP_Integer, 0, regEofB);
  sqlite4VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA);
  sqlite4VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB);
  sqlite4VdbeAddOp2(v, OP_If, regEofA, addrEofA);
  sqlite4VdbeAddOp2(v, OP_If, regEofB, addrEofB);

  /* Implement the main merge loop
  */
  sqlite4VdbeResolveLabel(v, labelCmpr);
  sqlite4VdbeAddOp4(v, OP_Permutation, nOrderBy, 0, 0,
                    (char*)aPermute, P4_INTARRAY);
  sqlite4VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy,
                         (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
  sqlite4VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);

  /* Jump to the this point in order to terminate the query.
  */
  sqlite4VdbeResolveLabel(v, labelEnd);

  /* Set the number of output columns
  */
  if( pDest->eDest==SRT_Output ){
    Select *pFirst = pPrior;
    while( pFirst->pPrior ) pFirst = pFirst->pPrior;
    generateColumnNames(pParse, 0, pFirst->pEList);
  }

  /* Reassembly the compound query so that it will be freed correctly
  ** by the calling function */
  if( p->pPrior ){
    sqlite4SelectDelete(db, p->pPrior);
  }
  p->pPrior = pPrior;

  /*** TBD:  Insert subroutine calls to close cursors on incomplete
  **** subqueries ****/
  explainComposite(pParse, p->op, iSub1, iSub2, 0);
  return SQLITE4_OK;
}
#endif

#if !defined(SQLITE4_OMIT_SUBQUERY) || !defined(SQLITE4_OMIT_VIEW)
/* Forward Declarations */
static void substExprList(sqlite4*, ExprList*, int, ExprList*);
static void substSelect(sqlite4*, Select *, int, ExprList *);

/*
** Scan through the expression pExpr.  Replace every reference to
** a column in table number iTable with a copy of the iColumn-th
** entry in pEList.  (But leave references to the ROWID column 
** unchanged.)
**
** This routine is part of the flattening procedure.  A subquery
** whose result set is defined by pEList appears as entry in the
** FROM clause of a SELECT such that the VDBE cursor assigned to that
** FORM clause entry is iTable.  This routine make the necessary 
** changes to pExpr so that it refers directly to the source table
** of the subquery rather the result set of the subquery.
*/
static Expr *substExpr(
  sqlite4 *db,        /* Report malloc errors to this connection */
  Expr *pExpr,        /* Expr in which substitution occurs */
  int iTable,         /* Table to be substituted */
  ExprList *pEList    /* Substitute expressions */
){
  if( pExpr==0 ) return 0;
  if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
    if( pExpr->iColumn<0 ){
      pExpr->op = TK_NULL;
    }else{
      Expr *pNew;
      assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
      assert( pExpr->pLeft==0 && pExpr->pRight==0 );
      pNew = sqlite4ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
      if( pNew && pExpr->pColl ){
        pNew->pColl = pExpr->pColl;
      }
      sqlite4ExprDelete(db, pExpr);
      pExpr = pNew;
    }
  }else{
    pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
    pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList);
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      substSelect(db, pExpr->x.pSelect, iTable, pEList);
    }else{
      substExprList(db, pExpr->x.pList, iTable, pEList);
    }
  }
  return pExpr;
}
static void substExprList(
  sqlite4 *db,         /* Report malloc errors here */
  ExprList *pList,     /* List to scan and in which to make substitutes */
  int iTable,          /* Table to be substituted */
  ExprList *pEList     /* Substitute values */
){
  int i;
  if( pList==0 ) return;
  for(i=0; i<pList->nExpr; i++){
    pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList);
  }
}
static void substSelect(
  sqlite4 *db,         /* Report malloc errors here */
  Select *p,           /* SELECT statement in which to make substitutions */
  int iTable,          /* Table to be replaced */
  ExprList *pEList     /* Substitute values */
){
  SrcList *pSrc;
  SrcListItem *pItem;
  int i;
  if( !p ) return;
  substExprList(db, p->pEList, iTable, pEList);
  substExprList(db, p->pGroupBy, iTable, pEList);
  substExprList(db, p->pOrderBy, iTable, pEList);
  p->pHaving = substExpr(db, p->pHaving, iTable, pEList);
  p->pWhere = substExpr(db, p->pWhere, iTable, pEList);
  substSelect(db, p->pPrior, iTable, pEList);
  pSrc = p->pSrc;
  assert( pSrc );  /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */
  if( ALWAYS(pSrc) ){
    for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
      substSelect(db, pItem->pSelect, iTable, pEList);
    }
  }
}
#endif /* !defined(SQLITE4_OMIT_SUBQUERY) || !defined(SQLITE4_OMIT_VIEW) */

#if !defined(SQLITE4_OMIT_SUBQUERY) || !defined(SQLITE4_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries as a performance optimization.
** This routine returns 1 if it makes changes and 0 if no flattening occurs.
**
** To understand the concept of flattening, consider the following
** query:
**
**     SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5
**
** The default way of implementing this query is to execute the
** subquery first and store the results in a temporary table, then
** run the outer query on that temporary table.  This requires two
** passes over the data.  Furthermore, because the temporary table
** has no indices, the WHERE clause on the outer query cannot be
** optimized.
**
** This routine attempts to rewrite queries such as the above into
** a single flat select, like this:
**
**     SELECT x+y AS a FROM t1 WHERE z<100 AND a>5
**
** The code generated for this simpification gives the same result
** but only has to scan the data once.  And because indices might 
** exist on the table t1, a complete scan of the data might be
** avoided.
**
** Flattening is only attempted if all of the following are true:
**
**   (1)  The subquery and the outer query do not both use aggregates.
**
**   (2)  The subquery is not an aggregate or the outer query is not a join.
**
**   (3)  The subquery is not the right operand of a left outer join
**        (Originally ticket #306.  Strengthened by ticket #3300)
**
**   (4)  The subquery is not DISTINCT.
**
**  (**)  At one point restrictions (4) and (5) defined a subset of DISTINCT
**        sub-queries that were excluded from this optimization. Restriction 
**        (4) has since been expanded to exclude all DISTINCT subqueries.
**
**   (6)  The subquery does not use aggregates or the outer query is not
**        DISTINCT.
**
**   (7)  The subquery has a FROM clause.  TODO:  For subqueries without
**        A FROM clause, consider adding a FROM close with the special
**        table sqlite_once that consists of a single row containing a
**        single NULL.
**
**   (8)  The subquery does not use LIMIT or the outer query is not a join.
**
**   (9)  The subquery does not use LIMIT or the outer query does not use
**        aggregates.
**
**  (10)  The subquery does not use aggregates or the outer query does not
**        use LIMIT.
**
**  (11)  The subquery and the outer query do not both have ORDER BY clauses.
**
**  (**)  Not implemented.  Subsumed into restriction (3).  Was previously
**        a separate restriction deriving from ticket #350.
**
**  (13)  The subquery and outer query do not both use LIMIT.
**
**  (14)  The subquery does not use OFFSET.
**
**  (15)  The outer query is not part of a compound select or the
**        subquery does not have a LIMIT clause.
**        (See ticket #2339 and ticket [02a8e81d44]).
**
**  (16)  The outer query is not an aggregate or the subquery does
**        not contain ORDER BY.  (Ticket #2942)  This used to not matter
**        until we introduced the group_concat() function.  
**
**  (17)  The sub-query is not a compound select, or it is a UNION ALL 
**        compound clause made up entirely of non-aggregate queries, and 
**        the parent query:
**
**          * is not itself part of a compound select,
**          * is not an aggregate or DISTINCT query, and
**          * is not a join
**
**        The parent and sub-query may contain WHERE clauses. Subject to
**        rules (11), (13) and (14), they may also contain ORDER BY,
**        LIMIT and OFFSET clauses.  The subquery cannot use any compound
**        operator other than UNION ALL because all the other compound
**        operators have an implied DISTINCT which is disallowed by
**        restriction (4).
**
**  (18)  If the sub-query is a compound select, then all terms of the
**        ORDER by clause of the parent must be simple references to 
**        columns of the sub-query.
**
**        Also, each component of the sub-query must return the same number
**        of result columns. This is actually a requirement for any compound
**        SELECT statement, but all the code here does is make sure that no
**        such (illegal) sub-query is flattened. The caller will detect the
**        syntax error and return a detailed message.
**
**  (19)  The subquery does not use LIMIT or the outer query does not
**        have a WHERE clause.
**
**  (20)  If the sub-query is a compound select, then it must not use
**        an ORDER BY clause.  Ticket #3773.  We could relax this constraint
**        somewhat by saying that the terms of the ORDER BY clause must
**        appear as unmodified result columns in the outer query.  But we
**        have other optimizations in mind to deal with that case.
**
**  (21)  The subquery does not use LIMIT or the outer query is not
**        DISTINCT.  (See ticket [752e1646fc]).
**
** In this routine, the "p" parameter is a pointer to the outer query.
** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query
** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.
**
** If flattening is not attempted, this routine is a no-op and returns 0.
** If flattening is attempted this routine returns 1.
**
** All of the expression analysis must occur on both the outer query and
** the subquery before this routine runs.
*/
static int flattenSubquery(
  Parse *pParse,       /* Parsing context */
  Select *p,           /* The parent or outer SELECT statement */
  int iFrom,           /* Index in p->pSrc->a[] of the inner subquery */
  int isAgg,           /* True if outer SELECT uses aggregate functions */
  int subqueryIsAgg    /* True if the subquery uses aggregate functions */
){
  const char *zSavedAuthContext = pParse->zAuthContext;
  Select *pParent;
  Select *pSub;       /* The inner query or "subquery" */
  Select *pSub1;      /* Pointer to the rightmost select in sub-query */
  SrcList *pSrc;      /* The FROM clause of the outer query */
  SrcList *pSubSrc;   /* The FROM clause of the subquery */
  ExprList *pList;    /* The result set of the outer query */
  int iParent;        /* VDBE cursor number of the pSub result set temp table */
  int i;              /* Loop counter */
  Expr *pWhere;                    /* The WHERE clause */
  SrcListItem *pSubitem;   /* The subquery */
  sqlite4 *db = pParse->db;

  /* Check to see if flattening is permitted.  Return 0 if not.
  */
  assert( p!=0 );
  assert( p->pPrior==0 );  /* Unable to flatten compound queries */
  if( db->flags & SQLITE4_QueryFlattener ) return 0;
  pSrc = p->pSrc;
  assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
  pSubitem = &pSrc->a[iFrom];
  iParent = pSubitem->iCursor;
  pSub = pSubitem->pSelect;
  assert( pSub!=0 );
  if( isAgg && subqueryIsAgg ) return 0;                 /* Restriction (1)  */
  if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;          /* Restriction (2)  */
  pSubSrc = pSub->pSrc;
  assert( pSubSrc );
  /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
  ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET
  ** because they could be computed at compile-time.  But when LIMIT and OFFSET
  ** became arbitrary expressions, we were forced to add restrictions (13)
  ** and (14). */
  if( pSub->pLimit && p->pLimit ) return 0;              /* Restriction (13) */
  if( pSub->pOffset ) return 0;                          /* Restriction (14) */
  if( p->pRightmost && pSub->pLimit ){
    return 0;                                            /* Restriction (15) */
  }
  if( pSubSrc->nSrc==0 ) return 0;                       /* Restriction (7)  */
  if( pSub->selFlags & SF_Distinct ) return 0;           /* Restriction (5)  */
  if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
     return 0;         /* Restrictions (8)(9) */
  }
  if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
     return 0;         /* Restriction (6)  */
  }
  if( p->pOrderBy && pSub->pOrderBy ){
     return 0;                                           /* Restriction (11) */
  }
  if( isAgg && pSub->pOrderBy ) return 0;                /* Restriction (16) */
  if( pSub->pLimit && p->pWhere ) return 0;              /* Restriction (19) */
  if( pSub->pLimit && (p->selFlags & SF_Distinct)!=0 ){
     return 0;         /* Restriction (21) */
  }

  /* OBSOLETE COMMENT 1:
  ** Restriction 3:  If the subquery is a join, make sure the subquery is 
  ** not used as the right operand of an outer join.  Examples of why this
  ** is not allowed:
  **
  **         t1 LEFT OUTER JOIN (t2 JOIN t3)
  **
  ** If we flatten the above, we would get
  **
  **         (t1 LEFT OUTER JOIN t2) JOIN t3
  **
  ** which is not at all the same thing.
  **
  ** OBSOLETE COMMENT 2:
  ** Restriction 12:  If the subquery is the right operand of a left outer
  ** join, make sure the subquery has no WHERE clause.
  ** An examples of why this is not allowed:
  **
  **         t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
  **
  ** If we flatten the above, we would get
  **
  **         (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
  **
  ** But the t2.x>0 test will always fail on a NULL row of t2, which
  ** effectively converts the OUTER JOIN into an INNER JOIN.
  **
  ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
  ** Ticket #3300 shows that flattening the right term of a LEFT JOIN
  ** is fraught with danger.  Best to avoid the whole thing.  If the
  ** subquery is the right term of a LEFT JOIN, then do not flatten.
  */
  if( (pSubitem->jointype & JT_OUTER)!=0 ){
    return 0;
  }

  /* Restriction 17: If the sub-query is a compound SELECT, then it must
  ** use only the UNION ALL operator. And none of the simple select queries
  ** that make up the compound SELECT are allowed to be aggregate or distinct
  ** queries.
  */
  if( pSub->pPrior ){
    if( pSub->pOrderBy ){
      return 0;  /* Restriction 20 */
    }
    if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
      return 0;
    }
    for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
      testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
      testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
      assert( pSub->pSrc!=0 );
      if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
       || (pSub1->pPrior && pSub1->op!=TK_ALL) 
       || pSub1->pSrc->nSrc<1
       || pSub->pEList->nExpr!=pSub1->pEList->nExpr
      ){
        return 0;
      }
      testcase( pSub1->pSrc->nSrc>1 );
    }

    /* Restriction 18. */
    if( p->pOrderBy ){
      int ii;
      for(ii=0; ii<p->pOrderBy->nExpr; ii++){
        if( p->pOrderBy->a[ii].iOrderByCol==0 ) return 0;
      }
    }
  }

  /***** If we reach this point, flattening is permitted. *****/

  /* Authorize the subquery */
  pParse->zAuthContext = pSubitem->zName;
  sqlite4AuthCheck(pParse, SQLITE4_SELECT, 0, 0, 0);
  pParse->zAuthContext = zSavedAuthContext;

  /* If the sub-query is a compound SELECT statement, then (by restrictions
  ** 17 and 18 above) it must be a UNION ALL and the parent query must 
  ** be of the form:
  **
  **     SELECT <expr-list> FROM (<sub-query>) <where-clause> 
  **
  ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block
  ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or 
  ** OFFSET clauses and joins them to the left-hand-side of the original
  ** using UNION ALL operators. In this case N is the number of simple
  ** select statements in the compound sub-query.
  **
  ** Example:
  **
  **     SELECT a+1 FROM (
  **        SELECT x FROM tab
  **        UNION ALL
  **        SELECT y FROM tab
  **        UNION ALL
  **        SELECT abs(z*2) FROM tab2
  **     ) WHERE a!=5 ORDER BY 1
  **
  ** Transformed into:
  **
  **     SELECT x+1 FROM tab WHERE x+1!=5
  **     UNION ALL
  **     SELECT y+1 FROM tab WHERE y+1!=5
  **     UNION ALL
  **     SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5
  **     ORDER BY 1
  **
  ** We call this the "compound-subquery flattening".
  */
  for(pSub=pSub->pPrior; pSub; pSub=pSub->pPrior){
    Select *pNew;
    ExprList *pOrderBy = p->pOrderBy;
    Expr *pLimit = p->pLimit;
    Select *pPrior = p->pPrior;
    p->pOrderBy = 0;
    p->pSrc = 0;
    p->pPrior = 0;
    p->pLimit = 0;
    pNew = sqlite4SelectDup(db, p, 0);
    p->pLimit = pLimit;
    p->pOrderBy = pOrderBy;
    p->pSrc = pSrc;
    p->op = TK_ALL;
    p->pRightmost = 0;
    if( pNew==0 ){
      pNew = pPrior;
    }else{
      pNew->pPrior = pPrior;
      pNew->pRightmost = 0;
    }
    p->pPrior = pNew;
    if( db->mallocFailed ) return 1;
  }

  /* Begin flattening the iFrom-th entry of the FROM clause 
  ** in the outer query.
  */
  pSub = pSub1 = pSubitem->pSelect;

  /* Delete the transient table structure associated with the
  ** subquery
  */
  sqlite4DbFree(db, pSubitem->zDatabase);
  sqlite4DbFree(db, pSubitem->zName);
  sqlite4DbFree(db, pSubitem->zAlias);
  pSubitem->zDatabase = 0;
  pSubitem->zName = 0;
  pSubitem->zAlias = 0;
  pSubitem->pSelect = 0;

  /* Defer deleting the Table object associated with the
  ** subquery until code generation is
  ** complete, since there may still exist Expr.pTab entries that
  ** refer to the subquery even after flattening.  Ticket #3346.
  **
  ** pSubitem->pTab is always non-NULL by test restrictions and tests above.
  */
  if( ALWAYS(pSubitem->pTab!=0) ){
    Table *pTabToDel = pSubitem->pTab;
    if( pTabToDel->nRef==1 ){
      Parse *pToplevel = sqlite4ParseToplevel(pParse);
      pTabToDel->pNextZombie = pToplevel->pZombieTab;
      pToplevel->pZombieTab = pTabToDel;
    }else{
      pTabToDel->nRef--;
    }
    pSubitem->pTab = 0;
  }

  /* The following loop runs once for each term in a compound-subquery
  ** flattening (as described above).  If we are doing a different kind
  ** of flattening - a flattening other than a compound-subquery flattening -
  ** then this loop only runs once.
  **
  ** This loop moves all of the FROM elements of the subquery into the
  ** the FROM clause of the outer query.  Before doing this, remember
  ** the cursor number for the original outer query FROM element in
  ** iParent.  The iParent cursor will never be used.  Subsequent code
  ** will scan expressions looking for iParent references and replace
  ** those references with expressions that resolve to the subquery FROM
  ** elements we are now copying in.
  */
  for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
    int nSubSrc;
    u8 jointype = 0;
    pSubSrc = pSub->pSrc;     /* FROM clause of subquery */
    nSubSrc = pSubSrc->nSrc;  /* Number of terms in subquery FROM clause */
    pSrc = pParent->pSrc;     /* FROM clause of the outer query */

    if( pSrc ){
      assert( pParent==p );  /* First time through the loop */
      jointype = pSubitem->jointype;
    }else{
      assert( pParent!=p );  /* 2nd and subsequent times through the loop */
      pSrc = pParent->pSrc = sqlite4SrcListAppend(db, 0, 0, 0);
      if( pSrc==0 ){
        assert( db->mallocFailed );
        break;
      }
    }

    /* The subquery uses a single slot of the FROM clause of the outer
    ** query.  If the subquery has more than one element in its FROM clause,
    ** then expand the outer query to make space for it to hold all elements
    ** of the subquery.
    **
    ** Example:
    **
    **    SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB;
    **
    ** The outer query has 3 slots in its FROM clause.  One slot of the
    ** outer query (the middle slot) is used by the subquery.  The next
    ** block of code will expand the out query to 4 slots.  The middle
    ** slot is expanded to two slots in order to make space for the
    ** two elements in the FROM clause of the subquery.
    */
    if( nSubSrc>1 ){
      pParent->pSrc = pSrc = sqlite4SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1);
      if( db->mallocFailed ){
        break;
      }
    }

    /* Transfer the FROM clause terms from the subquery into the
    ** outer query.
    */
    for(i=0; i<nSubSrc; i++){
      sqlite4IdListDelete(db, pSrc->a[i+iFrom].pUsing);
      pSrc->a[i+iFrom] = pSubSrc->a[i];
      memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
    }
    pSrc->a[iFrom].jointype = jointype;
  
    /* Now begin substituting subquery result set expressions for 
    ** references to the iParent in the outer query.
    ** 
    ** Example:
    **
    **   SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b;
    **   \                     \_____________ subquery __________/          /
    **    \_____________________ outer query ______________________________/
    **
    ** We look at every expression in the outer query and every place we see
    ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10".
    */
    pList = pParent->pEList;
    for(i=0; i<pList->nExpr; i++){
      if( pList->a[i].zName==0 ){
        const char *zSpan = pList->a[i].zSpan;
        if( ALWAYS(zSpan) ){
          pList->a[i].zName = sqlite4DbStrDup(db, zSpan);
        }
      }
    }
    substExprList(db, pParent->pEList, iParent, pSub->pEList);
    if( isAgg ){
      substExprList(db, pParent->pGroupBy, iParent, pSub->pEList);
      pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
    }
    if( pSub->pOrderBy ){
      assert( pParent->pOrderBy==0 );
      pParent->pOrderBy = pSub->pOrderBy;
      pSub->pOrderBy = 0;
    }else if( pParent->pOrderBy ){
      substExprList(db, pParent->pOrderBy, iParent, pSub->pEList);
    }
    if( pSub->pWhere ){
      pWhere = sqlite4ExprDup(db, pSub->pWhere, 0);
    }else{
      pWhere = 0;
    }
    if( subqueryIsAgg ){
      assert( pParent->pHaving==0 );
      pParent->pHaving = pParent->pWhere;
      pParent->pWhere = pWhere;
      pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList);
      pParent->pHaving = sqlite4ExprAnd(db, pParent->pHaving, 
                                  sqlite4ExprDup(db, pSub->pHaving, 0));
      assert( pParent->pGroupBy==0 );
      pParent->pGroupBy = sqlite4ExprListDup(db, pSub->pGroupBy, 0);
    }else{
      pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList);
      pParent->pWhere = sqlite4ExprAnd(db, pParent->pWhere, pWhere);
    }
  
    /* The flattened query is distinct if either the inner or the
    ** outer query is distinct. 
    */
    pParent->selFlags |= pSub->selFlags & SF_Distinct;
  
    /*
    ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y;
    **
    ** One is tempted to try to add a and b to combine the limits.  But this
    ** does not work if either limit is negative.
    */
    if( pSub->pLimit ){
      pParent->pLimit = pSub->pLimit;
      pSub->pLimit = 0;
    }
  }

  /* Finially, delete what is left of the subquery and return
  ** success.
  */
  sqlite4SelectDelete(db, pSub1);

  return 1;
}
#endif /* !defined(SQLITE4_OMIT_SUBQUERY) || !defined(SQLITE4_OMIT_VIEW) */

/*
** Analyze the SELECT statement passed as an argument to see if it
** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if 
** it is, or 0 otherwise. At present, a query is considered to be
** a min()/max() query if:
**
**   1. There is a single object in the FROM clause.
**
**   2. There is a single expression in the result set, and it is
**      either min(x) or max(x), where x is a column reference.
*/
static u8 minMaxQuery(Select *p){
  Expr *pExpr;
  ExprList *pEList = p->pEList;

  if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
  pExpr = pEList->a[0].pExpr;
  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
  if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0;
  pEList = pExpr->x.pList;
  if( pEList==0 || pEList->nExpr!=1 ) return 0;
  if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
  assert( !ExprHasProperty(pExpr, EP_IntValue) );
  if( sqlite4_stricmp(pExpr->u.zToken,"min")==0 ){
    return WHERE_ORDERBY_MIN;
  }else if( sqlite4_stricmp(pExpr->u.zToken,"max")==0 ){
    return WHERE_ORDERBY_MAX;
  }
  return WHERE_ORDERBY_NORMAL;
}

/*
** If the source-list item passed as an argument was augmented with an
** INDEXED BY clause, then try to locate the specified index. If there
** was such a clause and the named index cannot be found, return 
** SQLITE4_ERROR and leave an error in pParse. Otherwise, populate 
** pFrom->pIndex and return SQLITE4_OK.
*/
SQLITE4_PRIVATE int sqlite4IndexedByLookup(Parse *pParse, SrcListItem *pFrom){
  if( pFrom->pTab && pFrom->zIndex ){
    Table *pTab = pFrom->pTab;
    char *zIndex = pFrom->zIndex;
    Index *pIdx;
    for(pIdx=pTab->pIndex; 
        pIdx && sqlite4_stricmp(pIdx->zName, zIndex); 
        pIdx=pIdx->pNext
    );
    if( !pIdx ){
      sqlite4ErrorMsg(pParse, "no such index: %s", zIndex, 0);
      pParse->checkSchema = 1;
      return SQLITE4_ERROR;
    }
    pFrom->pIndex = pIdx;
  }
  return SQLITE4_OK;
}

/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
**
**    (1)  Make sure VDBE cursor numbers have been assigned to every
**         element of the FROM clause.
**
**    (2)  Fill in the pTabList->a[].pTab fields in the SrcList that 
**         defines FROM clause.  When views appear in the FROM clause,
**         fill pTabList->a[].pSelect with a copy of the SELECT statement
**         that implements the view.  A copy is made of the view's SELECT
**         statement so that we can freely modify or delete that statement
**         without worrying about messing up the presistent representation
**         of the view.
**
**    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword
**         on joins and the ON and USING clause of joins.
**
**    (4)  Scan the list of columns in the result set (pEList) looking
**         for instances of the "*" operator or the TABLE.* operator.
**         If found, expand each "*" to be every column in every table
**         and TABLE.* to be every column in TABLE.
**
*/
static int selectExpander(Walker *pWalker, Select *p){
  Parse *pParse = pWalker->pParse;
  int i, j, k;
  SrcList *pTabList;
  ExprList *pEList;
  SrcListItem *pFrom;
  sqlite4 *db = pParse->db;

  if( db->mallocFailed  ){
    return WRC_Abort;
  }
  if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
    return WRC_Prune;
  }
  p->selFlags |= SF_Expanded;
  pTabList = p->pSrc;
  pEList = p->pEList;

  /* Make sure cursor numbers have been assigned to all entries in
  ** the FROM clause of the SELECT statement.
  */
  sqlite4SrcListAssignCursors(pParse, pTabList);

  /* Look up every table named in the FROM clause of the select.  If
  ** an entry of the FROM clause is a subquery instead of a table or view,
  ** then create a transient table structure to describe the subquery.
  */
  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
    Table *pTab;
    if( pFrom->pTab!=0 ){
      /* This statement has already been prepared.  There is no need
      ** to go further. */
      assert( i==0 );
      return WRC_Prune;
    }
    if( pFrom->zName==0 ){
#ifndef SQLITE4_OMIT_SUBQUERY
      Select *pSel = pFrom->pSelect;
      /* A sub-query in the FROM clause of a SELECT */
      assert( pSel!=0 );
      assert( pFrom->pTab==0 );
      sqlite4WalkSelect(pWalker, pSel);
      pFrom->pTab = pTab = sqlite4DbMallocZero(db, sizeof(Table));
      if( pTab==0 ) return WRC_Abort;
      pTab->nRef = 1;
      pTab->zName = sqlite4MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
      while( pSel->pPrior ){ pSel = pSel->pPrior; }
      selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
      pTab->nRowEst = 1000000;
      pTab->tabFlags |= TF_Ephemeral;
#endif
    }else{
      /* An ordinary table or view name in the FROM clause */
      assert( pFrom->pTab==0 );
      pFrom->pTab = pTab = 
        sqlite4LocateTable(pParse,0,pFrom->zName,pFrom->zDatabase);
      if( pTab==0 ) return WRC_Abort;
      pTab->nRef++;
#if !defined(SQLITE4_OMIT_VIEW) || !defined (SQLITE4_OMIT_VIRTUALTABLE)
      if( pTab->pSelect || IsVirtual(pTab) ){
        /* We reach here if the named table is a really a view */
        if( sqlite4ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
        assert( pFrom->pSelect==0 );
        pFrom->pSelect = sqlite4SelectDup(db, pTab->pSelect, 0);
        sqlite4WalkSelect(pWalker, pFrom->pSelect);
      }
#endif
    }

    /* Locate the index named by the INDEXED BY clause, if any. */
    if( sqlite4IndexedByLookup(pParse, pFrom) ){
      return WRC_Abort;
    }
  }

  /* Process NATURAL keywords, and ON and USING clauses of joins.
  */
  if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
    return WRC_Abort;
  }

  /* For every "*" that occurs in the column list, insert the names of
  ** all columns in all tables.  And for every TABLE.* insert the names
  ** of all columns in TABLE.  The parser inserted a special expression
  ** with the TK_ALL operator for each "*" that it found in the column list.
  ** The following code just has to locate the TK_ALL expressions and expand
  ** each one to the list of all columns in all tables.
  **
  ** The first loop just checks to see if there are any "*" operators
  ** that need expanding.
  */
  for(k=0; k<pEList->nExpr; k++){
    Expr *pE = pEList->a[k].pExpr;
    if( pE->op==TK_ALL ) break;
    assert( pE->op!=TK_DOT || pE->pRight!=0 );
    assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
    if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break;
  }
  if( k<pEList->nExpr ){
    /*
    ** If we get here it means the result set contains one or more "*"
    ** operators that need to be expanded.  Loop through each expression
    ** in the result set and expand them one by one.
    */
    ExprListItem *a = pEList->a;
    ExprList *pNew = 0;

    for(k=0; k<pEList->nExpr; k++){
      Expr *pE = a[k].pExpr;
      assert( pE->op!=TK_DOT || pE->pRight!=0 );
      if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
        /* This particular expression does not need to be expanded.
        */
        pNew = sqlite4ExprListAppend(pParse, pNew, a[k].pExpr);
        if( pNew ){
          pNew->a[pNew->nExpr-1].zName = a[k].zName;
          pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
          a[k].zName = 0;
          a[k].zSpan = 0;
        }
        a[k].pExpr = 0;
      }else{
        /* This expression is a "*" or a "TABLE.*" and needs to be
        ** expanded. */
        int tableSeen = 0;      /* Set to 1 when TABLE matches */
        char *zTName;            /* text of name of TABLE */
        if( pE->op==TK_DOT ){
          assert( pE->pLeft!=0 );
          assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
          zTName = pE->pLeft->u.zToken;
        }else{
          zTName = 0;
        }
        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
          Table *pTab = pFrom->pTab;
          char *zTabName = pFrom->zAlias;
          if( zTabName==0 ){
            zTabName = pTab->zName;
          }
          if( db->mallocFailed ) break;
          if( zTName && sqlite4_stricmp(zTName, zTabName)!=0 ){
            continue;
          }
          tableSeen = 1;
          for(j=0; j<pTab->nCol; j++){
            Expr *pExpr, *pRight;
            char *zName = pTab->aCol[j].zName;
            char *zColname;  /* The computed column name */
            char *zToFree;   /* Malloced string that needs to be freed */
            Token sColname;  /* Computed column name as a token */

            /* If a column is marked as 'hidden' (currently only possible
            ** for virtual tables), do not include it in the expanded
            ** result-set list.
            */
            if( IsHiddenColumn(&pTab->aCol[j]) ){
              assert(IsVirtual(pTab));
              continue;
            }

            if( i>0 && zTName==0 ){
              if( (pFrom->jointype & JT_NATURAL)!=0
                && tableAndColumnIndex(pTabList, i, zName, 0, 0)
              ){
                /* In a NATURAL join, omit the join columns from the 
                ** table to the right of the join */
                continue;
              }
              if( sqlite4IdListIndex(pFrom->pUsing, zName)>=0 ){
                /* In a join with a USING clause, omit columns in the
                ** using clause from the table on the right. */
                continue;
              }
            }
            pRight = sqlite4Expr(db, TK_ID, zName);
            zColname = zName;
            zToFree = 0;
            if( pTabList->nSrc>1 ){
              Expr *pLeft;
              pLeft = sqlite4Expr(db, TK_ID, zTabName);
              pExpr = sqlite4PExpr(pParse, TK_DOT, pLeft, pRight, 0);
            }else{
              pExpr = pRight;
            }
            pNew = sqlite4ExprListAppend(pParse, pNew, pExpr);
            sColname.z = zColname;
            sColname.n = sqlite4Strlen30(zColname);
            sqlite4ExprListSetName(pParse, pNew, &sColname, 0);
            sqlite4DbFree(db, zToFree);
          }
        }
        if( !tableSeen ){
          if( zTName ){
            sqlite4ErrorMsg(pParse, "no such table: %s", zTName);
          }else{
            sqlite4ErrorMsg(pParse, "no tables specified");
          }
        }
      }
    }
    sqlite4ExprListDelete(db, pEList);
    p->pEList = pNew;
  }
#if SQLITE4_MAX_COLUMN
  if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE4_LIMIT_COLUMN] ){
    sqlite4ErrorMsg(pParse, "too many columns in result set");
  }
#endif
  return WRC_Continue;
}

/*
** No-op routine for the parse-tree walker.
**
** When this routine is the Walker.xExprCallback then expression trees
** are walked without any actions being taken at each node.  Presumably,
** when this routine is used for Walker.xExprCallback then 
** Walker.xSelectCallback is set to do something useful for every 
** subquery in the parser tree.
*/
static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
  UNUSED_PARAMETER2(NotUsed, NotUsed2);
  return WRC_Continue;
}

/*
** This routine "expands" a SELECT statement and all of its subqueries.
** For additional information on what it means to "expand" a SELECT
** statement, see the comment on the selectExpand worker callback above.
**
** Expanding a SELECT statement is the first step in processing a
** SELECT statement.  The SELECT statement must be expanded before
** name resolution is performed.
**
** If anything goes wrong, an error message is written into pParse.
** The calling function can detect the problem by looking at pParse->nErr
** and/or pParse->db->mallocFailed.
*/
static void sqlite4SelectExpand(Parse *pParse, Select *pSelect){
  Walker w;
  w.xSelectCallback = selectExpander;
  w.xExprCallback = exprWalkNoop;
  w.pParse = pParse;
  sqlite4WalkSelect(&w, pSelect);
}


#ifndef SQLITE4_OMIT_SUBQUERY
/*
** This is a Walker.xSelectCallback callback for the sqlite4SelectTypeInfo()
** interface.
**
** For each FROM-clause subquery, add Column.zType and Column.zColl
** information to the Table structure that represents the result set
** of that subquery.
**
** The Table structure that represents the result set was constructed
** by selectExpander() but the type and collation information was omitted
** at that point because identifiers had not yet been resolved.  This
** routine is called after identifier resolution.
*/
static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
  Parse *pParse;
  int i;
  SrcList *pTabList;
  SrcListItem *pFrom;

  assert( p->selFlags & SF_Resolved );
  if( (p->selFlags & SF_HasTypeInfo)==0 ){
    p->selFlags |= SF_HasTypeInfo;
    pParse = pWalker->pParse;
    pTabList = p->pSrc;
    for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
      Table *pTab = pFrom->pTab;
      if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){
        /* A sub-query in the FROM clause of a SELECT */
        Select *pSel = pFrom->pSelect;
        assert( pSel );
        while( pSel->pPrior ) pSel = pSel->pPrior;
        selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
      }
    }
  }
  return WRC_Continue;
}
#endif


/*
** This routine adds datatype and collating sequence information to
** the Table structures of all FROM-clause subqueries in a
** SELECT statement.
**
** Use this routine after name resolution.
*/
static void sqlite4SelectAddTypeInfo(Parse *pParse, Select *pSelect){
#ifndef SQLITE4_OMIT_SUBQUERY
  Walker w;
  w.xSelectCallback = selectAddSubqueryTypeInfo;
  w.xExprCallback = exprWalkNoop;
  w.pParse = pParse;
  sqlite4WalkSelect(&w, pSelect);
#endif
}


/*
** This routine sets of a SELECT statement for processing.  The
** following is accomplished:
**
**     *  VDBE Cursor numbers are assigned to all FROM-clause terms.
**     *  Ephemeral Table objects are created for all FROM-clause subqueries.
**     *  ON and USING clauses are shifted into WHERE statements
**     *  Wildcards "*" and "TABLE.*" in result sets are expanded.
**     *  Identifiers in expression are matched to tables.
**
** This routine acts recursively on all subqueries within the SELECT.
*/
SQLITE4_PRIVATE void sqlite4SelectPrep(
  Parse *pParse,         /* The parser context */
  Select *p,             /* The SELECT statement being coded. */
  NameContext *pOuterNC  /* Name context for container */
){
  sqlite4 *db;
  if( NEVER(p==0) ) return;
  db = pParse->db;
  if( p->selFlags & SF_HasTypeInfo ) return;
  sqlite4SelectExpand(pParse, p);
  if( pParse->nErr || db->mallocFailed ) return;
  sqlite4ResolveSelectNames(pParse, p, pOuterNC);
  if( pParse->nErr || db->mallocFailed ) return;
  sqlite4SelectAddTypeInfo(pParse, p);
}

/*
** Reset the aggregate accumulator.
**
** The aggregate accumulator is a set of memory cells that hold
** intermediate results while calculating an aggregate.  This
** routine simply stores NULLs in all of those memory cells.
*/
static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  AggInfoFunc *pFunc;
  if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){
    return;
  }
  for(i=0; i<pAggInfo->nColumn; i++){
    sqlite4VdbeAddOp2(v, OP_Null, 0, pAggInfo->aCol[i].iMem);
  }
  for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
    sqlite4VdbeAddOp2(v, OP_Null, 0, pFunc->iMem);
    if( pFunc->iDistinct>=0 ){
      Expr *pE = pFunc->pExpr;
      assert( !ExprHasProperty(pE, EP_xIsSelect) );
      if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
        sqlite4ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
           "argument");
        pFunc->iDistinct = -1;
      }else{
        KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0);
        sqlite4VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
                          (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
      }
    }
  }
}

/*
** Invoke the OP_AggFinalize opcode for every aggregate function
** in the AggInfo structure.
*/
static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  AggInfoFunc *pF;
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
    ExprList *pList = pF->pExpr->x.pList;
    assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
    sqlite4VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0,
                      (void*)pF->pFunc, P4_FUNCDEF);
  }
}

/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
*/
static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  AggInfoFunc *pF;
  AggInfoCol *pC;

  pAggInfo->directMode = 1;
  sqlite4ExprCacheClear(pParse);
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
    int nArg;
    int addrNext = 0;
    int regAgg;
    ExprList *pList = pF->pExpr->x.pList;
    assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
    if( pList ){
      nArg = pList->nExpr;
      regAgg = sqlite4GetTempRange(pParse, nArg);
      sqlite4ExprCodeExprList(pParse, pList, regAgg, 1);
    }else{
      nArg = 0;
      regAgg = 0;
    }
    if( pF->iDistinct>=0 ){
      addrNext = sqlite4VdbeMakeLabel(v);
      assert( nArg==1 );
      codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
    }
    if( pF->pFunc->flags & SQLITE4_FUNC_NEEDCOLL ){
      CollSeq *pColl = 0;
      ExprListItem *pItem;
      int j;
      assert( pList!=0 );  /* pList!=0 if pF->pFunc has NEEDCOLL */
      for(j=0, pItem=pList->a; !pColl && j<nArg; j++, pItem++){
        pColl = sqlite4ExprCollSeq(pParse, pItem->pExpr);
      }
      if( !pColl ){
        pColl = pParse->db->pDfltColl;
      }
      sqlite4VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
    }
    sqlite4VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
                      (void*)pF->pFunc, P4_FUNCDEF);
    sqlite4VdbeChangeP5(v, (u8)nArg);
    sqlite4ExprCacheAffinityChange(pParse, regAgg, nArg);
    sqlite4ReleaseTempRange(pParse, regAgg, nArg);
    if( addrNext ){
      sqlite4VdbeResolveLabel(v, addrNext);
      sqlite4ExprCacheClear(pParse);
    }
  }

  /* Before populating the accumulator registers, clear the column cache.
  ** Otherwise, if any of the required column values are already present 
  ** in registers, sqlite4ExprCode() may use OP_SCopy to copy the value
  ** to pC->iMem. But by the time the value is used, the original register
  ** may have been used, invalidating the underlying buffer holding the
  ** text or blob value. See ticket [883034dcb5].
  **
  ** Another solution would be to change the OP_SCopy used to copy cached
  ** values to an OP_Copy.
  */
  sqlite4ExprCacheClear(pParse);
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite4ExprCode(pParse, pC->pExpr, pC->iMem);
  }
  pAggInfo->directMode = 0;
  sqlite4ExprCacheClear(pParse);
}

/*
** Generate code for the SELECT statement given in the p argument.  
**
** The results are distributed in various ways depending on the
** contents of the SelectDest structure pointed to by argument pDest
** as follows:
**
**     pDest->eDest    Result
**     ------------    -------------------------------------------
**     SRT_Output      Generate a row of output (using the OP_ResultRow
**                     opcode) for each row in the result set.
**
**     SRT_Mem         Only valid if the result is a single column.
**                     Store the first column of the first result row
**                     in register pDest->iParm then abandon the rest
**                     of the query.  This destination implies "LIMIT 1".
**
**     SRT_Set         The result must be a single column.  Store each
**                     row of result as the key in table pDest->iParm. 
**                     Apply the affinity pDest->affinity before storing
**                     results.  Used to implement "IN (SELECT ...)".
**
**     SRT_Union       Store results as a key in a temporary table pDest->iParm.
**
**     SRT_Except      Remove results from the temporary table pDest->iParm.
**
**     SRT_Table       Store results in temporary table pDest->iParm.
**                     This is like SRT_EphemTab except that the table
**                     is assumed to already be open.
**
**     SRT_EphemTab    Create an temporary table pDest->iParm and store
**                     the result there. The cursor is left open after
**                     returning.  This is like SRT_Table except that
**                     this destination uses OP_OpenEphemeral to create
**                     the table first.
**
**     SRT_Coroutine   Generate a co-routine that returns a new row of
**                     results each time it is invoked.  The entry point
**                     of the co-routine is stored in register pDest->iParm.
**
**     SRT_Exists      Store a 1 in memory cell pDest->iParm if the result
**                     set is not empty.
**
**     SRT_Discard     Throw the results away.  This is used by SELECT
**                     statements within triggers whose only purpose is
**                     the side-effects of functions.
**
** This routine returns the number of errors.  If any errors are
** encountered, then an appropriate error message is left in
** pParse->zErrMsg.
**
** This routine does NOT free the Select structure passed in.  The
** calling function needs to do that.
*/
SQLITE4_PRIVATE int sqlite4Select(
  Parse *pParse,         /* The parser context */
  Select *p,             /* The SELECT statement being coded. */
  SelectDest *pDest      /* What to do with the query results */
){
  int i, j;              /* Loop counters */
  WhereInfo *pWInfo;     /* Return from sqlite4WhereBegin() */
  Vdbe *v;               /* The virtual machine under construction */
  int isAgg;             /* True for select lists like "count(*)" */
  ExprList *pEList;      /* List of columns to extract. */
  SrcList *pTabList;     /* List of tables to select from */
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */
  int rc = 1;            /* Value to return from this function */
  int addrSortIndex;     /* Address of an OP_OpenEphemeral instruction */
  int addrDistinctIndex; /* Address of an OP_OpenEphemeral instruction */
  AggInfo sAggInfo;      /* Information used by aggregate queries */
  int iEnd;              /* Address of the end of the query */
  sqlite4 *db;           /* The database connection */

#ifndef SQLITE4_OMIT_EXPLAIN
  int iRestoreSelectId = pParse->iSelectId;
  pParse->iSelectId = pParse->iNextSelectId++;
#endif

  memset(&sAggInfo, 0, sizeof(sAggInfo));

  db = pParse->db;
  if( p==0 || db->mallocFailed || pParse->nErr ){
    return 1;
  }
  if( sqlite4AuthCheck(pParse, SQLITE4_SELECT, 0, 0, 0) ) return 1;

  if( IgnorableOrderby(pDest) ){
    assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union || 
           pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
    /* If ORDER BY makes no difference in the output then neither does
    ** DISTINCT so it can be removed too. */
    sqlite4ExprListDelete(db, p->pOrderBy);
    p->pOrderBy = 0;
    p->selFlags &= ~SF_Distinct;
  }
  sqlite4SelectPrep(pParse, p, 0);
  pOrderBy = p->pOrderBy;
  pTabList = p->pSrc;
  pEList = p->pEList;
  if( pParse->nErr || db->mallocFailed ){
    goto select_end;
  }
  isAgg = (p->selFlags & SF_Aggregate)!=0;
  assert( pEList!=0 );

  /* Begin generating code.
  */
  v = sqlite4GetVdbe(pParse);
  if( v==0 ) goto select_end;

  /* If writing to memory or generating a set
  ** only a single column may be output.
  */
#ifndef SQLITE4_OMIT_SUBQUERY
  if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
    goto select_end;
  }
#endif

  /* Generate code for all sub-queries in the FROM clause
  */
#if !defined(SQLITE4_OMIT_SUBQUERY) || !defined(SQLITE4_OMIT_VIEW)
  for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
    SrcListItem *pItem = &pTabList->a[i];
    SelectDest dest;
    Select *pSub = pItem->pSelect;
    int isAggSub;

    if( pSub==0 ) continue;
    if( pItem->addrFillSub ){
      sqlite4VdbeAddOp2(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
    ** may contain expression trees of at most
    ** (SQLITE4_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
    ** more conservative than necessary, but much easier than enforcing
    ** an exact limit.
    */
    pParse->nHeight += sqlite4SelectExprHeight(p);

    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 = sqlite4VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
      pItem->addrFillSub = topAddr+1;
      VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
      if( pItem->isCorrelated==0 ){
        /* If the subquery is no correlated and if we are not inside of
        ** a trigger, then we only need to compute the value of the subquery
        ** once. */
        onceAddr = sqlite4CodeOnce(pParse);
      }
      sqlite4SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
      sqlite4Select(pParse, pSub, &dest);
      pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
      if( onceAddr ) sqlite4VdbeJumpHere(v, onceAddr);
      retAddr = sqlite4VdbeAddOp1(v, OP_Return, pItem->regReturn);
      VdbeComment((v, "end %s", pItem->pTab->zName));
      sqlite4VdbeChangeP1(v, topAddr, retAddr);
      sqlite4ClearTempRegCache(pParse);
    }
    if( /*pParse->nErr ||*/ db->mallocFailed ){
      goto select_end;
    }
    pParse->nHeight -= sqlite4SelectExprHeight(p);
    pTabList = p->pSrc;
    if( !IgnorableOrderby(pDest) ){
      pOrderBy = p->pOrderBy;
    }
  }
  pEList = p->pEList;
#endif
  pWhere = p->pWhere;
  pGroupBy = p->pGroupBy;
  pHaving = p->pHaving;
  isDistinct = (p->selFlags & SF_Distinct)!=0;

#ifndef SQLITE4_OMIT_COMPOUND_SELECT
  /* If there is are a sequence of queries, do the earlier ones first.
  */
  if( p->pPrior ){
    if( p->pRightmost==0 ){
      Select *pLoop, *pRight = 0;
      int cnt = 0;
      int mxSelect;
      for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){
        pLoop->pRightmost = p;
        pLoop->pNext = pRight;
        pRight = pLoop;
      }
      mxSelect = db->aLimit[SQLITE4_LIMIT_COMPOUND_SELECT];
      if( mxSelect && cnt>mxSelect ){
        sqlite4ErrorMsg(pParse, "too many terms in compound SELECT");
        goto select_end;
      }
    }
    rc = multiSelect(pParse, p, pDest);
    explainSetInteger(pParse->iSelectId, iRestoreSelectId);
    return rc;
  }
#endif

  /* 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
  ** an optimization - the correct answer should result regardless.
  ** Use the SQLITE4_GroupByOrder flag with SQLITE4_TESTCTRL_OPTIMIZER
  ** to disable this optimization for testing purposes.
  */
  if( sqlite4ExprListCompare(p->pGroupBy, pOrderBy)==0
         && (db->flags & SQLITE4_GroupByOrder)==0 ){
    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 
   && sqlite4ExprListCompare(pOrderBy, p->pEList)==0
  ){
    p->selFlags &= ~SF_Distinct;
    p->pGroupBy = sqlite4ExprListDup(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
  ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
  ** we figure out that the sorting index is not needed.  The addrSortIndex
  ** variable is used to facilitate that change.
  */
  if( pOrderBy ){
    KeyInfo *pKeyInfo;
    pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 1);
    if( pKeyInfo ) pKeyInfo->nData = pEList->nExpr;

    pOrderBy->iECursor = pParse->nTab++;
    p->addrOpenEphm[2] = addrSortIndex =
      sqlite4VdbeAddOp4(v, OP_OpenEphemeral,
                           pOrderBy->iECursor, pOrderBy->nExpr+2, 0,
                           (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
  }else{
    addrSortIndex = -1;
  }

  /* If the output is destined for a temporary table, open that table.
  */
  if( pDest->eDest==SRT_EphemTab ){
    sqlite4VdbeAddOp2(v, OP_OpenEphemeral, pDest->iParm, pEList->nExpr);
  }

  /* Set the limiter.
  */
  iEnd = sqlite4VdbeMakeLabel(v);
  p->nSelectRow = (double)LARGEST_INT64;
  computeLimitRegisters(pParse, p, iEnd);
  if( p->iLimit==0 && addrSortIndex>=0 ){
    sqlite4VdbeGetOp(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;
    distinct = pParse->nTab++;
    pKeyInfo = keyInfoFromExprList(pParse, p->pEList, 0);
    addrDistinctIndex = sqlite4VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0,
        (char*)pKeyInfo, P4_KEYINFO_HANDOFF);
  }else{
    distinct = addrDistinctIndex = -1;
  }

  /* Aggregate and non-aggregate queries are handled differently */
  if( !isAgg && pGroupBy==0 ){
    ExprList *pDist = (isDistinct ? p->pEList : 0);

    /* Begin the database scan. */
    pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0, 0);
    if( pWInfo==0 ) goto select_end;
    if( sqlite4WhereOutputRowCount(pWInfo)<p->nSelectRow ){
      p->nSelectRow = sqlite4WhereOutputRowCount(pWInfo);
    }
    if( pOrderBy && sqlite4WhereIsOrdered(pWInfo) ) pOrderBy = 0;

    /* If sorting index that was created by a prior OP_OpenEphemeral 
    ** instruction ended up not being needed, then change the OP_OpenEphemeral
    ** into an OP_Noop.
    */
    if( addrSortIndex>=0 && pOrderBy==0 ){
      sqlite4VdbeChangeToNoop(v, addrSortIndex);
      p->addrOpenEphm[2] = -1;
    }

    if( sqlite4WhereIsDistinct(pWInfo) ){
      VdbeOp *pOp;                /* No longer required OpenEphemeral instr. */
     
      assert( addrDistinctIndex>=0 );
      pOp = sqlite4VdbeGetOp(v, addrDistinctIndex);

      assert( isDistinct );
      assert( sqlite4WhereIsDistinct(pWInfo)==WHERE_DISTINCT_ORDERED 
           || sqlite4WhereIsDistinct(pWInfo)==WHERE_DISTINCT_UNIQUE 
      );
      distinct = -1;
      if( sqlite4WhereIsDistinct(pWInfo)==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;

        sqlite4ExprCodeExprList(pParse, pEList, iBase, 1);
        iJump = sqlite4VdbeCurrentAddr(v) + 1 + pEList->nExpr + 1 + 1;
        sqlite4VdbeAddOp2(v, OP_If, iFlag, iJump-1);
        for(iExpr=0; iExpr<pEList->nExpr; iExpr++){
          CollSeq *pColl = sqlite4ExprCollSeq(pParse, pEList->a[iExpr].pExpr);
          sqlite4VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr);
          sqlite4VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
          sqlite4VdbeChangeP5(v, SQLITE4_NULLEQ);
        }
        sqlite4VdbeAddOp2(v, OP_Goto, 0, sqlite4WhereContinueLabel(pWInfo));

        sqlite4VdbeAddOp2(v, OP_Integer, 0, iFlag);
        assert( sqlite4VdbeCurrentAddr(v)==iJump );
        sqlite4VdbeAddOp3(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,
        sqlite4WhereContinueLabel(pWInfo), sqlite4WhereBreakLabel(pWInfo)
    );

    /* End the database scan loop.
    */
    sqlite4WhereEnd(pWInfo);
  }else{
    /* This is the processing for aggregate queries */
    NameContext sNC;    /* Name context for processing aggregate information */
    int iAMem;          /* First Mem address for storing current GROUP BY */
    int iBMem;          /* First Mem address for previous GROUP BY */
    int iUseFlag;       /* Mem address holding flag indicating that at least
                        ** one row of the input to the aggregator has been
                        ** processed */
    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 */

    /* Remove any and all aliases between the result set and the
    ** GROUP BY clause.
    */
    if( pGroupBy ){
      int k;                        /* Loop counter */
      ExprListItem *pItem;  /* For looping over expression in a list */

      for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
        pItem->iAlias = 0;
      }
      for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
        pItem->iAlias = 0;
      }
      if( p->nSelectRow>(double)100 ) p->nSelectRow = (double)100;
    }else{
      p->nSelectRow = (double)1;
    }

 
    /* Create a label to jump to when we want to abort the query */
    addrEnd = sqlite4VdbeMakeLabel(v);

    /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
    ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
    ** SELECT statement.
    */
    memset(&sNC, 0, sizeof(sNC));
    sNC.pParse = pParse;
    sNC.pSrcList = pTabList;
    sNC.pAggInfo = &sAggInfo;
    sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
    sAggInfo.pGroupBy = pGroupBy;
    sqlite4ExprAnalyzeAggList(&sNC, pEList);
    sqlite4ExprAnalyzeAggList(&sNC, pOrderBy);
    if( pHaving ){
      sqlite4ExprAnalyzeAggregates(&sNC, pHaving);
    }
    sAggInfo.nAccumulator = sAggInfo.nColumn;
    for(i=0; i<sAggInfo.nFunc; i++){
      assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
      sqlite4ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
    }
    if( db->mallocFailed ) goto select_end;

    /* Processing for aggregates with GROUP BY is very different and
    ** much more complex than aggregates without a GROUP BY.
    */
    if( pGroupBy ){
      KeyInfo *pKeyInfo;  /* Keying information for the group by clause */
      int j1;             /* A-vs-B comparision jump */
      int addrOutputRow;  /* Start of subroutine that outputs a result row */
      int regOutputRow;   /* Return address register for output subroutine */
      int addrSetAbort;   /* Set the abort flag and return */
      int addrTopOfLoop;  /* Top of the input loop */
      int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
      int addrReset;      /* Subroutine for resetting the accumulator */
      int regReset;       /* Return address register for reset subroutine */

      /* 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 OP_SorterOpen instruction
      ** will be converted into a Noop.  
      */
      sAggInfo.sortingIdx = pParse->nTab++;
      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0);
      addrSortingIdx = sqlite4VdbeAddOp4(v, OP_SorterOpen, 
          sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 
          0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF);

      /* Initialize memory locations used by GROUP BY aggregate processing
      */
      iUseFlag = ++pParse->nMem;
      iAbortFlag = ++pParse->nMem;
      regOutputRow = ++pParse->nMem;
      addrOutputRow = sqlite4VdbeMakeLabel(v);
      regReset = ++pParse->nMem;
      addrReset = sqlite4VdbeMakeLabel(v);
      iAMem = pParse->nMem + 1;
      pParse->nMem += pGroupBy->nExpr;
      iBMem = pParse->nMem + 1;
      pParse->nMem += pGroupBy->nExpr;
      sqlite4VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
      VdbeComment((v, "clear abort flag"));
      sqlite4VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
      VdbeComment((v, "indicate accumulator empty"));
      sqlite4VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);

      /* Begin a loop that will extract all source rows in GROUP BY order.
      ** This might involve two separate loops with an OP_Sort in between, or
      ** it might be a single loop that uses an index to extract information
      ** in the right order to begin with.
      */
      sqlite4VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0);
      if( pWInfo==0 ) goto select_end;
      if( sqlite4WhereIsOrdered(pWInfo) ){
        /* The optimizer is able to deliver rows in group by order so
        ** we do not have to sort.  The OP_OpenEphemeral table will be
        ** cancelled later because we still need to use the pKeyInfo.
        */
        groupBySort = 0;

        /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
        ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
        ** Then compare the current GROUP BY terms against the GROUP BY terms
        ** from the previous row currently stored in a0, a1, a2...
        */
        sAggInfo.directMode = 1;
        addrTopOfLoop = sqlite4VdbeCurrentAddr(v);
        sqlite4ExprCacheClear(pParse);
        for(j=0; j<pGroupBy->nExpr; j++){
          sqlite4ExprCode(pParse, pGroupBy->a[j].pExpr, iBMem+j);
        }
        sqlite4VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr,
            (char*)pKeyInfo, P4_KEYINFO);
        j1 = sqlite4VdbeCurrentAddr(v);
        sqlite4VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1);
      }else{
        /* Rows are coming out in undetermined order.  We have to push
        ** each row into a sorting index, terminate the first loop,
        ** then loop over the sorting index in order to get the output
        ** in sorted order */
        int regBase;
        int nCol = sAggInfo.nColumn;
        int nGroup = pGroupBy->nExpr;
        int regKey = ++pParse->nMem;
        int regRecord = 0;

        groupBySort = 1;

        explainTempTable(pParse, 
            isDistinct && !(p->selFlags&SF_Distinct)?"DISTINCT":"GROUP BY");

        /* Encode the key for the sorting index. The key consists of each
        ** of the expressions in the GROUP BY list followed by a sequence
        ** number (to ensure each key is unique - the point of this is just
        ** to sort the rows, not to eliminate duplicates).  */
        sqlite4ExprCacheClear(pParse);
        regBase = sqlite4GetTempRange(pParse, nGroup);
        sqlite4ExprCodeExprList(pParse, pGroupBy, regBase, 0);
        sqlite4VdbeAddOp4Int(v, OP_MakeKey, regBase, nGroup, regKey, 
                                sAggInfo.sortingIdx);
        sqlite4VdbeChangeP5(v, OPFLAG_SEQCOUNT);
        sqlite4ReleaseTempRange(pParse, regBase, nGroup);

        /* Encode the record for the sorting index. The record contains all
        ** required column values from the elements of the FROM clause.  
        ** If no column values are required, insert a NULL into the sorting
        ** index instead of a record. No column values are required for 
        ** queries such as "SELECT count(*) FROM ..."  */
        if( nCol>0 ){
          regRecord = ++pParse->nMem;
          regBase = sqlite4GetTempRange(pParse, nCol);
          for(i=0; i<nCol; i++){
            AggInfoCol *pCol = &sAggInfo.aCol[i];
            int regDest = i + regBase;
            int regValue = sqlite4ExprCodeGetColumn(
                pParse, pCol->pTab, pCol->iColumn, pCol->iTable, regDest
                );
            if( regDest!=regValue ){
              sqlite4VdbeAddOp2(v, OP_SCopy, regValue, regDest);
            }
          }
          sqlite4VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord);
          sqlite4ReleaseTempRange(pParse, regBase, nCol);
        }

        /* Insert the key/value into the sorting index and end the loop
        ** generated by where.c code.  */
        sqlite4VdbeAddOp3(
            v, OP_Insert, sAggInfo.sortingIdx, regRecord, regKey
        );
        sqlite4WhereEnd(pWInfo);

        sqlite4VdbeAddOp2(v, OP_Null, 0, regKey);
        sqlite4VdbeAddOp2(v, OP_SorterSort, sAggInfo.sortingIdx, addrEnd);
        VdbeComment((v, "GROUP BY sort"));
        sAggInfo.useSortingIdx = 1;
        sqlite4ExprCacheClear(pParse);

        j1 = sqlite4VdbeAddOp3(v, OP_GrpCompare, sAggInfo.sortingIdx, 0,regKey);
        addrTopOfLoop = j1;
      }

      /* Generate code that runs whenever the GROUP BY changes.
      ** Changes in the GROUP BY are detected by the previous code
      ** block.  If there were no changes, this block is skipped.
      **
      ** This code copies current group by terms in b0,b1,b2,...
      ** over to a0,a1,a2.  It then calls the output subroutine
      ** and resets the aggregate accumulator registers in preparation
      ** for the next GROUP BY batch.
      */
      if( groupBySort==0 ){
        sqlite4ExprCodeMove(pParse, iBMem, iAMem, pGroupBy->nExpr);
      }
      sqlite4VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
      VdbeComment((v, "output one row"));
      sqlite4VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd);
      VdbeComment((v, "check abort flag"));
      sqlite4VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
      VdbeComment((v, "reset accumulator"));

      /* Update the aggregate accumulators based on the content of
      ** the current row
      */
      sqlite4VdbeJumpHere(v, j1);
      updateAccumulator(pParse, &sAggInfo);
      sqlite4VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
      VdbeComment((v, "indicate data in accumulator"));

      /* End of the loop
      */
      if( groupBySort ){
        sqlite4VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop);
      }else{
        sqlite4WhereEnd(pWInfo);
        sqlite4VdbeChangeToNoop(v, addrSortingIdx);
      }

      /* Output the final row of result
      */
      sqlite4VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow);
      VdbeComment((v, "output final row"));

      /* Jump over the subroutines
      */
      sqlite4VdbeAddOp2(v, OP_Goto, 0, addrEnd);

      /* Generate a subroutine that outputs a single row of the result
      ** set.  This subroutine first looks at the iUseFlag.  If iUseFlag
      ** is less than or equal to zero, the subroutine is a no-op.  If
      ** the processing calls for the query to abort, this subroutine
      ** increments the iAbortFlag memory location before returning in
      ** order to signal the caller to abort.
      */
      addrSetAbort = sqlite4VdbeCurrentAddr(v);
      sqlite4VdbeAddOp2(v, OP_Integer, 1, iAbortFlag);
      VdbeComment((v, "set abort flag"));
      sqlite4VdbeAddOp1(v, OP_Return, regOutputRow);
      sqlite4VdbeResolveLabel(v, addrOutputRow);
      addrOutputRow = sqlite4VdbeCurrentAddr(v);
      sqlite4VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
      VdbeComment((v, "Groupby result generator entry point"));
      sqlite4VdbeAddOp1(v, OP_Return, regOutputRow);
      finalizeAggFunctions(pParse, &sAggInfo);
      sqlite4ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE4_JUMPIFNULL);
      selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
                      distinct, pDest,
                      addrOutputRow+1, addrSetAbort);
      sqlite4VdbeAddOp1(v, OP_Return, regOutputRow);
      VdbeComment((v, "end groupby result generator"));

      /* Generate a subroutine that will reset the group-by accumulator
      */
      sqlite4VdbeResolveLabel(v, addrReset);
      resetAccumulator(pParse, &sAggInfo);
      sqlite4VdbeAddOp1(v, OP_Return, regReset);
     
    } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
    else {
      ExprList *pDel = 0;
      {
        /* Check if the query is of one of the following forms:
        **
        **   SELECT min(x) FROM ...
        **   SELECT max(x) FROM ...
        **
        ** If it is, then ask the code in where.c to attempt to sort results
        ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause. 
        ** If where.c is able to produce results sorted in this order, then
        ** add vdbe code to break out of the processing loop after the 
        ** first iteration (since the first iteration of the loop is 
        ** guaranteed to operate on the row with the minimum or maximum 
        ** value of x, the only row required).
        **
        ** A special flag must be passed to sqlite4WhereBegin() to slightly
        ** modify behaviour as follows:
        **
        **   + If the query is a "SELECT min(x)", then the loop coded by
        **     where.c should not iterate over any values with a NULL value
        **     for x.
        **
        **   + The optimizer code in where.c (the thing that decides which
        **     index or indices to use) should place a different priority on 
        **     satisfying the 'ORDER BY' clause than it does in other cases.
        **     Refer to code and comments in where.c for details.
        */
        ExprList *pMinMax = 0;
        u8 flag = minMaxQuery(p);
        if( flag ){
          assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
          pMinMax = sqlite4ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
          pDel = pMinMax;
          if( pMinMax && !db->mallocFailed ){
            pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
            pMinMax->a[0].pExpr->op = TK_COLUMN;
          }
        }
  
        /* This case runs if the aggregate has no GROUP BY clause.  The
        ** processing is much simpler since there is only a single row
        ** of output.
        */
        resetAccumulator(pParse, &sAggInfo);
        pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0);
        if( pWInfo==0 ){
          sqlite4ExprListDelete(db, pDel);
          goto select_end;
        }
        updateAccumulator(pParse, &sAggInfo);
        if( sqlite4WhereIsOrdered(pWInfo) && flag ){
          sqlite4VdbeAddOp2(v, OP_Goto, 0, sqlite4WhereBreakLabel(pWInfo));
          VdbeComment((v, "%s() by index",
                (flag==WHERE_ORDERBY_MIN?"min":"max")));
        }
        sqlite4WhereEnd(pWInfo);
        finalizeAggFunctions(pParse, &sAggInfo);
      }

      pOrderBy = 0;
      sqlite4ExprIfFalse(pParse, pHaving, addrEnd, SQLITE4_JUMPIFNULL);
      selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, 
                      pDest, addrEnd, addrEnd);
      sqlite4ExprListDelete(db, pDel);
    }
    sqlite4VdbeResolveLabel(v, addrEnd);
    
  } /* endif aggregate query */

  if( distinct>=0 ){
    explainTempTable(pParse, "DISTINCT");
  }

  /* If there is an ORDER BY clause, then we need to sort the results
  ** and send them to the callback one by one.
  */
  if( pOrderBy ){
    explainTempTable(pParse, "ORDER BY");
    generateSortTail(pParse, p, v, pEList->nExpr, pDest);
  }

  /* Jump here to skip this query
  */
  sqlite4VdbeResolveLabel(v, iEnd);

  /* The SELECT was successfully coded.   Set the return code to 0
  ** to indicate no errors.
  */
  rc = 0;

  /* Control jumps to here if an error is encountered above, or upon
  ** successful coding of the SELECT.
  */
select_end:
  explainSetInteger(pParse->iSelectId, iRestoreSelectId);

  /* Identify column names if results of the SELECT are to be output.
  */
  if( rc==SQLITE4_OK && pDest->eDest==SRT_Output ){
    generateColumnNames(pParse, pTabList, pEList);
  }

  sqlite4DbFree(db, sAggInfo.aCol);
  sqlite4DbFree(db, sAggInfo.aFunc);
  return rc;
}

#if defined(SQLITE4_ENABLE_TREE_EXPLAIN)
/*
** Generate a human-readable description of a the Select object.
*/
static void explainOneSelect(Vdbe *pVdbe, Select *p){
  sqlite4ExplainPrintf(pVdbe, "SELECT ");
  if( p->selFlags & (SF_Distinct|SF_Aggregate) ){
    if( p->selFlags & SF_Distinct ){
      sqlite4ExplainPrintf(pVdbe, "DISTINCT ");
    }
    if( p->selFlags & SF_Aggregate ){
      sqlite4ExplainPrintf(pVdbe, "agg_flag ");
    }
    sqlite4ExplainNL(pVdbe);
    sqlite4ExplainPrintf(pVdbe, "   ");
  }
  sqlite4ExplainExprList(pVdbe, p->pEList);
  sqlite4ExplainNL(pVdbe);
  if( p->pSrc && p->pSrc->nSrc ){
    int i;
    sqlite4ExplainPrintf(pVdbe, "FROM ");
    sqlite4ExplainPush(pVdbe);
    for(i=0; i<p->pSrc->nSrc; i++){
      SrcListItem *pItem = &p->pSrc->a[i];
      sqlite4ExplainPrintf(pVdbe, "{%d,*} = ", pItem->iCursor);
      if( pItem->pSelect ){
        sqlite4ExplainSelect(pVdbe, pItem->pSelect);
        if( pItem->pTab ){
          sqlite4ExplainPrintf(pVdbe, " (tabname=%s)", pItem->pTab->zName);
        }
      }else if( pItem->zName ){
        sqlite4ExplainPrintf(pVdbe, "%s", pItem->zName);
      }
      if( pItem->zAlias ){
        sqlite4ExplainPrintf(pVdbe, " (AS %s)", pItem->zAlias);
      }
      if( pItem->jointype & JT_LEFT ){
        sqlite4ExplainPrintf(pVdbe, " LEFT-JOIN");
      }
      sqlite4ExplainNL(pVdbe);
    }
    sqlite4ExplainPop(pVdbe);
  }
  if( p->pWhere ){
    sqlite4ExplainPrintf(pVdbe, "WHERE ");
    sqlite4ExplainExpr(pVdbe, p->pWhere);
    sqlite4ExplainNL(pVdbe);
  }
  if( p->pGroupBy ){
    sqlite4ExplainPrintf(pVdbe, "GROUPBY ");
    sqlite4ExplainExprList(pVdbe, p->pGroupBy);
    sqlite4ExplainNL(pVdbe);
  }
  if( p->pHaving ){
    sqlite4ExplainPrintf(pVdbe, "HAVING ");
    sqlite4ExplainExpr(pVdbe, p->pHaving);
    sqlite4ExplainNL(pVdbe);
  }
  if( p->pOrderBy ){
    sqlite4ExplainPrintf(pVdbe, "ORDERBY ");
    sqlite4ExplainExprList(pVdbe, p->pOrderBy);
    sqlite4ExplainNL(pVdbe);
  }
  if( p->pLimit ){
    sqlite4ExplainPrintf(pVdbe, "LIMIT ");
    sqlite4ExplainExpr(pVdbe, p->pLimit);
    sqlite4ExplainNL(pVdbe);
  }
  if( p->pOffset ){
    sqlite4ExplainPrintf(pVdbe, "OFFSET ");
    sqlite4ExplainExpr(pVdbe, p->pOffset);
    sqlite4ExplainNL(pVdbe);
  }
}
SQLITE4_PRIVATE void sqlite4ExplainSelect(Vdbe *pVdbe, Select *p){
  if( p==0 ){
    sqlite4ExplainPrintf(pVdbe, "(null-select)");
    return;
  }
  while( p->pPrior ) p = p->pPrior;
  sqlite4ExplainPush(pVdbe);
  while( p ){
    explainOneSelect(pVdbe, p);
    p = p->pNext;
    if( p==0 ) break;
    sqlite4ExplainNL(pVdbe);
    sqlite4ExplainPrintf(pVdbe, "%s\n", selectOpName(p->op));
  }
  sqlite4ExplainPrintf(pVdbe, "END");
  sqlite4ExplainPop(pVdbe);
}

/* End of the structure debug printing code
*****************************************************************************/
#endif /* defined(SQLITE4_ENABLE_TREE_EXPLAIN) */

/************** End of select.c **********************************************/
/************** Begin file trigger.c *****************************************/
/*
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation for TRIGGERs
*/

#ifndef SQLITE4_OMIT_TRIGGER
/*
** Delete a linked list of TriggerStep structures.
*/
SQLITE4_PRIVATE void sqlite4DeleteTriggerStep(sqlite4 *db, TriggerStep *pTriggerStep){
  while( pTriggerStep ){
    TriggerStep * pTmp = pTriggerStep;
    pTriggerStep = pTriggerStep->pNext;

    sqlite4ExprDelete(db, pTmp->pWhere);
    sqlite4ExprListDelete(db, pTmp->pExprList);
    sqlite4SelectDelete(db, pTmp->pSelect);
    sqlite4IdListDelete(db, pTmp->pIdList);

    sqlite4DbFree(db, pTmp);
  }
}

/*
** Given table pTab, return a list of all the triggers attached to 
** the table. The list is connected by Trigger.pNext pointers.
**
** All of the triggers on pTab that are in the same database as pTab
** are already attached to pTab->pTrigger.  But there might be additional
** triggers on pTab in the TEMP schema.  This routine prepends all
** TEMP triggers on pTab to the beginning of the pTab->pTrigger list
** and returns the combined list.
**
** To state it another way:  This routine returns a list of all triggers
** that fire off of pTab.  The list will include any TEMP triggers on
** pTab as well as the triggers lised in pTab->pTrigger.
*/
SQLITE4_PRIVATE Trigger *sqlite4TriggerList(Parse *pParse, Table *pTab){
  Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
  Trigger *pList = 0;                  /* List of triggers to return */

  if( pParse->disableTriggers ){
    return 0;
  }

  if( pTmpSchema!=pTab->pSchema ){
    HashElem *p;
    for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
      Trigger *pTrig = (Trigger *)sqliteHashData(p);
      if( pTrig->pTabSchema==pTab->pSchema
       && 0==sqlite4_stricmp(pTrig->table, pTab->zName) 
      ){
        pTrig->pNext = (pList ? pList : pTab->pTrigger);
        pList = pTrig;
      }
    }
  }

  return (pList ? pList : pTab->pTrigger);
}

/*
** This is called by the parser when it sees a CREATE TRIGGER statement
** up to the point of the BEGIN before the trigger actions.  A Trigger
** structure is generated based on the information available and stored
** in pParse->pNewTrigger.  After the trigger actions have been parsed, the
** sqlite4FinishTrigger() function is called to complete the trigger
** construction process.
*/
SQLITE4_PRIVATE void sqlite4BeginTrigger(
  Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */
  Token *pName1,      /* The name of the trigger */
  Token *pName2,      /* The name of the trigger */
  int tr_tm,          /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
  int op,             /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
  IdList *pColumns,   /* column list if this is an UPDATE OF trigger */
  SrcList *pTableName,/* The name of the table/view the trigger applies to */
  Expr *pWhen,        /* WHEN clause */
  int isTemp,         /* True if the TEMPORARY keyword is present */
  int noErr           /* Suppress errors if the trigger already exists */
){
  Trigger *pTrigger = 0;  /* The new trigger */
  Table *pTab;            /* Table that the trigger fires off of */
  char *zName = 0;        /* Name of the trigger */
  sqlite4 *db = pParse->db;  /* The database connection */
  int iDb;                /* The database to store the trigger in */
  Token *pName;           /* The unqualified db name */
  DbFixer sFix;           /* State vector for the DB fixer */
  int iTabDb;             /* Index of the database holding pTab */

  assert( pName1!=0 );   /* pName1->z might be NULL, but not pName1 itself */
  assert( pName2!=0 );
  assert( op==TK_INSERT || op==TK_UPDATE || op==TK_DELETE );
  assert( op>0 && op<0xff );
  if( isTemp ){
    /* If TEMP was specified, then the trigger name may not be qualified. */
    if( pName2->n>0 ){
      sqlite4ErrorMsg(pParse, "temporary trigger may not have qualified name");
      goto trigger_cleanup;
    }
    iDb = 1;
    pName = pName1;
  }else{
    /* Figure out the db that the the trigger will be created in */
    iDb = sqlite4TwoPartName(pParse, pName1, pName2, &pName);
    if( iDb<0 ){
      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 SQLITE4_MASTER.
  */
  if( db->init.busy && iDb!=1 ){
    sqlite4DbFree(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 sqlite4SrcListLookup() returns 0, indicating the table does not
  ** exist, the error is caught by the block below.
  */
  pTab = sqlite4SrcListLookup(pParse, pTableName);
  if( db->init.busy==0 && pName2->n==0 && pTab
        && pTab->pSchema==db->aDb[1].pSchema ){
    iDb = 1;
  }

  /* Ensure the table name matches database name and that the table exists */
  if( db->mallocFailed ) goto trigger_cleanup;
  assert( pTableName->nSrc==1 );
  if( sqlite4FixInit(&sFix, pParse, iDb, "trigger", pName) && 
      sqlite4FixSrcList(&sFix, pTableName) ){
    goto trigger_cleanup;
  }
  pTab = sqlite4SrcListLookup(pParse, pTableName);
  if( !pTab ){
    /* The table does not exist. */
    if( db->init.iDb==1 ){
      /* Ticket #3810.
      ** Normally, whenever a table is dropped, all associated triggers are
      ** dropped too.  But if a TEMP trigger is created on a non-TEMP table
      ** and the table is dropped by a different database connection, the
      ** trigger is not visible to the database connection that does the
      ** drop so the trigger cannot be dropped.  This results in an
      ** "orphaned trigger" - a trigger whose associated table is missing.
      */
      db->init.orphanTrigger = 1;
    }
    goto trigger_cleanup;
  }
  if( IsVirtual(pTab) ){
    sqlite4ErrorMsg(pParse, "cannot create triggers on virtual tables");
    goto trigger_cleanup;
  }

  /* Check that the trigger name is not reserved and that no trigger of the
  ** specified name exists */
  zName = sqlite4NameFromToken(db, pName);
  if( !zName || SQLITE4_OK!=sqlite4CheckObjectName(pParse, zName) ){
    goto trigger_cleanup;
  }
  if( sqlite4HashFind(&(db->aDb[iDb].pSchema->trigHash),
                      zName, sqlite4Strlen30(zName)) ){
    if( !noErr ){
      sqlite4ErrorMsg(pParse, "trigger %T already exists", pName);
    }else{
      assert( !db->init.busy );
      sqlite4CodeVerifySchema(pParse, iDb);
    }
    goto trigger_cleanup;
  }

  /* Do not create a trigger on a system table */
  if( sqlite4_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
    sqlite4ErrorMsg(pParse, "cannot create trigger on system table");
    pParse->nErr++;
    goto trigger_cleanup;
  }

  /* INSTEAD of triggers are only for views and views only support INSTEAD
  ** of triggers.
  */
  if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
    sqlite4ErrorMsg(pParse, "cannot create %s trigger on view: %S", 
        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
    goto trigger_cleanup;
  }
  if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
    sqlite4ErrorMsg(pParse, "cannot create INSTEAD OF"
        " trigger on table: %S", pTableName, 0);
    goto trigger_cleanup;
  }
  iTabDb = sqlite4SchemaToIndex(db, pTab->pSchema);

#ifndef SQLITE4_OMIT_AUTHORIZATION
  {
    int code = SQLITE4_CREATE_TRIGGER;
    const char *zDb = db->aDb[iTabDb].zName;
    const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
    if( iTabDb==1 || isTemp ) code = SQLITE4_CREATE_TEMP_TRIGGER;
    if( sqlite4AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
      goto trigger_cleanup;
    }
    if( sqlite4AuthCheck(pParse, SQLITE4_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
      goto trigger_cleanup;
    }
  }
#endif

  /* INSTEAD OF triggers can only appear on views and BEFORE triggers
  ** cannot appear on views.  So we might as well translate every
  ** INSTEAD OF trigger into a BEFORE trigger.  It simplifies code
  ** elsewhere.
  */
  if (tr_tm == TK_INSTEAD){
    tr_tm = TK_BEFORE;
  }

  /* Build the Trigger object */
  pTrigger = (Trigger*)sqlite4DbMallocZero(db, sizeof(Trigger));
  if( pTrigger==0 ) goto trigger_cleanup;
  pTrigger->zName = zName;
  zName = 0;
  pTrigger->table = sqlite4DbStrDup(db, pTableName->a[0].zName);
  pTrigger->pSchema = db->aDb[iDb].pSchema;
  pTrigger->pTabSchema = pTab->pSchema;
  pTrigger->op = (u8)op;
  pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
  pTrigger->pWhen = sqlite4ExprDup(db, pWhen, EXPRDUP_REDUCE);
  pTrigger->pColumns = sqlite4IdListDup(db, pColumns);
  assert( pParse->pNewTrigger==0 );
  pParse->pNewTrigger = pTrigger;

trigger_cleanup:
  sqlite4DbFree(db, zName);
  sqlite4SrcListDelete(db, pTableName);
  sqlite4IdListDelete(db, pColumns);
  sqlite4ExprDelete(db, pWhen);
  if( !pParse->pNewTrigger ){
    sqlite4DeleteTrigger(db, pTrigger);
  }else{
    assert( pParse->pNewTrigger==pTrigger );
  }
}

/*
** This routine is called after all of the trigger actions have been parsed
** in order to complete the process of building the trigger.
*/
SQLITE4_PRIVATE void sqlite4FinishTrigger(
  Parse *pParse,          /* Parser context */
  TriggerStep *pStepList, /* The triggered program */
  Token *pAll             /* Token that describes the complete CREATE TRIGGER */
){
  Trigger *pTrig = pParse->pNewTrigger;   /* Trigger being finished */
  char *zName;                            /* Name of trigger */
  sqlite4 *db = pParse->db;               /* The database */
  DbFixer sFix;                           /* Fixer object */
  int iDb;                                /* Database containing the trigger */
  Token nameToken;                        /* Trigger name for error reporting */

  pParse->pNewTrigger = 0;
  if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup;
  zName = pTrig->zName;
  iDb = sqlite4SchemaToIndex(pParse->db, pTrig->pSchema);
  pTrig->step_list = pStepList;
  while( pStepList ){
    pStepList->pTrig = pTrig;
    pStepList = pStepList->pNext;
  }
  nameToken.z = pTrig->zName;
  nameToken.n = sqlite4Strlen30(nameToken.z);
  if( sqlite4FixInit(&sFix, pParse, iDb, "trigger", &nameToken) 
          && sqlite4FixTriggerStep(&sFix, pTrig->step_list) ){
    goto triggerfinish_cleanup;
  }

  /* if we are not initializing,
  ** build the sqlite_master entry
  */
  if( !db->init.busy ){
    Vdbe *v;
    char *z;

    /* Make an entry in the sqlite_master table */
    v = sqlite4GetVdbe(pParse);
    if( v==0 ) goto triggerfinish_cleanup;
    sqlite4BeginWriteOperation(pParse, 0, iDb);
    z = sqlite4DbStrNDup(db, (char*)pAll->z, pAll->n);
    sqlite4NestedParse(pParse,
       "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName,
       pTrig->table, z);
    sqlite4DbFree(db, z);
    sqlite4ChangeCookie(pParse, iDb);
    sqlite4VdbeAddParseSchemaOp(v, iDb,
        sqlite4MPrintf(db, "type='trigger' AND name='%q'", zName));
  }

  if( db->init.busy ){
    Trigger *pLink = pTrig;
    Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
    pTrig = sqlite4HashInsert(pHash, zName, sqlite4Strlen30(zName), pTrig);
    if( pTrig ){
      db->mallocFailed = 1;
    }else if( pLink->pSchema==pLink->pTabSchema ){
      Table *pTab;
      int n = sqlite4Strlen30(pLink->table);
      pTab = sqlite4HashFind(&pLink->pTabSchema->tblHash, pLink->table, n);
      assert( pTab!=0 );
      pLink->pNext = pTab->pTrigger;
      pTab->pTrigger = pLink;
    }
  }

triggerfinish_cleanup:
  sqlite4DeleteTrigger(db, pTrig);
  assert( !pParse->pNewTrigger );
  sqlite4DeleteTriggerStep(db, pStepList);
}

/*
** Turn a SELECT statement (that the pSelect parameter points to) into
** a trigger step.  Return a pointer to a TriggerStep structure.
**
** The parser calls this routine when it finds a SELECT statement in
** body of a TRIGGER.  
*/
SQLITE4_PRIVATE TriggerStep *sqlite4TriggerSelectStep(sqlite4 *db, Select *pSelect){
  TriggerStep *pTriggerStep = sqlite4DbMallocZero(db, sizeof(TriggerStep));
  if( pTriggerStep==0 ) {
    sqlite4SelectDelete(db, pSelect);
    return 0;
  }
  pTriggerStep->op = TK_SELECT;
  pTriggerStep->pSelect = pSelect;
  pTriggerStep->orconf = OE_Default;
  return pTriggerStep;
}

/*
** Allocate space to hold a new trigger step.  The allocated space
** holds both the TriggerStep object and the TriggerStep.target.z string.
**
** If an OOM error occurs, NULL is returned and db->mallocFailed is set.
*/
static TriggerStep *triggerStepAllocate(
  sqlite4 *db,                /* Database connection */
  u8 op,                      /* Trigger opcode */
  Token *pName                /* The target name */
){
  TriggerStep *pTriggerStep;

  pTriggerStep = sqlite4DbMallocZero(db, sizeof(TriggerStep) + pName->n);
  if( pTriggerStep ){
    char *z = (char*)&pTriggerStep[1];
    memcpy(z, pName->z, pName->n);
    pTriggerStep->target.z = z;
    pTriggerStep->target.n = pName->n;
    pTriggerStep->op = op;
  }
  return pTriggerStep;
}

/*
** Build a trigger step out of an INSERT statement.  Return a pointer
** to the new trigger step.
**
** The parser calls this routine when it sees an INSERT inside the
** body of a trigger.
*/
SQLITE4_PRIVATE TriggerStep *sqlite4TriggerInsertStep(
  sqlite4 *db,        /* The database connection */
  Token *pTableName,  /* Name of the table into which we insert */
  IdList *pColumn,    /* List of columns in pTableName to insert into */
  ExprList *pEList,   /* The VALUE clause: a list of values to be inserted */
  Select *pSelect,    /* A SELECT statement that supplies values */
  u8 orconf           /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
  TriggerStep *pTriggerStep;

  assert(pEList == 0 || pSelect == 0);
  assert(pEList != 0 || pSelect != 0 || db->mallocFailed);

  pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
  if( pTriggerStep ){
    pTriggerStep->pSelect = sqlite4SelectDup(db, pSelect, EXPRDUP_REDUCE);
    pTriggerStep->pIdList = pColumn;
    pTriggerStep->pExprList = sqlite4ExprListDup(db, pEList, EXPRDUP_REDUCE);
    pTriggerStep->orconf = orconf;
  }else{
    sqlite4IdListDelete(db, pColumn);
  }
  sqlite4ExprListDelete(db, pEList);
  sqlite4SelectDelete(db, pSelect);

  return pTriggerStep;
}

/*
** Construct a trigger step that implements an UPDATE statement and return
** a pointer to that trigger step.  The parser calls this routine when it
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
*/
SQLITE4_PRIVATE TriggerStep *sqlite4TriggerUpdateStep(
  sqlite4 *db,         /* The database connection */
  Token *pTableName,   /* Name of the table to be updated */
  ExprList *pEList,    /* The SET clause: list of column and new values */
  Expr *pWhere,        /* The WHERE clause */
  u8 orconf            /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
){
  TriggerStep *pTriggerStep;

  pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName);
  if( pTriggerStep ){
    pTriggerStep->pExprList = sqlite4ExprListDup(db, pEList, EXPRDUP_REDUCE);
    pTriggerStep->pWhere = sqlite4ExprDup(db, pWhere, EXPRDUP_REDUCE);
    pTriggerStep->orconf = orconf;
  }
  sqlite4ExprListDelete(db, pEList);
  sqlite4ExprDelete(db, pWhere);
  return pTriggerStep;
}

/*
** Construct a trigger step that implements a DELETE statement and return
** a pointer to that trigger step.  The parser calls this routine when it
** sees a DELETE statement inside the body of a CREATE TRIGGER.
*/
SQLITE4_PRIVATE TriggerStep *sqlite4TriggerDeleteStep(
  sqlite4 *db,            /* Database connection */
  Token *pTableName,      /* The table from which rows are deleted */
  Expr *pWhere            /* The WHERE clause */
){
  TriggerStep *pTriggerStep;

  pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName);
  if( pTriggerStep ){
    pTriggerStep->pWhere = sqlite4ExprDup(db, pWhere, EXPRDUP_REDUCE);
    pTriggerStep->orconf = OE_Default;
  }
  sqlite4ExprDelete(db, pWhere);
  return pTriggerStep;
}

/* 
** Recursively delete a Trigger structure
*/
SQLITE4_PRIVATE void sqlite4DeleteTrigger(sqlite4 *db, Trigger *pTrigger){
  if( pTrigger==0 ) return;
  sqlite4DeleteTriggerStep(db, pTrigger->step_list);
  sqlite4DbFree(db, pTrigger->zName);
  sqlite4DbFree(db, pTrigger->table);
  sqlite4ExprDelete(db, pTrigger->pWhen);
  sqlite4IdListDelete(db, pTrigger->pColumns);
  sqlite4DbFree(db, pTrigger);
}

/*
** This function is called to drop a trigger from the database schema. 
**
** This may be called directly from the parser and therefore identifies
** the trigger by name.  The sqlite4DropTriggerPtr() routine does the
** same job as this routine except it takes a pointer to the trigger
** instead of the trigger name.
**/
SQLITE4_PRIVATE void sqlite4DropTrigger(Parse *pParse, SrcList *pName, int noErr){
  Trigger *pTrigger = 0;
  int i;
  const char *zDb;
  const char *zName;
  int nName;
  sqlite4 *db = pParse->db;

  if( db->mallocFailed ) goto drop_trigger_cleanup;
  if( SQLITE4_OK!=sqlite4ReadSchema(pParse) ){
    goto drop_trigger_cleanup;
  }

  assert( pName->nSrc==1 );
  zDb = pName->a[0].zDatabase;
  zName = pName->a[0].zName;
  nName = sqlite4Strlen30(zName);
  for(i=OMIT_TEMPDB; i<db->nDb; i++){
    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
    if( zDb && sqlite4_stricmp(db->aDb[j].zName, zDb) ) continue;
    pTrigger = sqlite4HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
    if( pTrigger ) break;
  }
  if( !pTrigger ){
    if( !noErr ){
      sqlite4ErrorMsg(pParse, "no such trigger: %S", pName, 0);
    }else{
      sqlite4CodeVerifyNamedSchema(pParse, zDb);
    }
    pParse->checkSchema = 1;
    goto drop_trigger_cleanup;
  }
  sqlite4DropTriggerPtr(pParse, pTrigger);

drop_trigger_cleanup:
  sqlite4SrcListDelete(db, pName);
}

/*
** Return a pointer to the Table structure for the table that a trigger
** is set on.
*/
static Table *tableOfTrigger(Trigger *pTrigger){
  int n = sqlite4Strlen30(pTrigger->table);
  return sqlite4HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
}


/*
** Drop a trigger given a pointer to that trigger. 
*/
SQLITE4_PRIVATE void sqlite4DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
  Table   *pTable;
  Vdbe *v;
  sqlite4 *db = pParse->db;
  int iDb;

  iDb = sqlite4SchemaToIndex(pParse->db, pTrigger->pSchema);
  assert( iDb>=0 && iDb<db->nDb );
  pTable = tableOfTrigger(pTrigger);
  assert( pTable );
  assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
#ifndef SQLITE4_OMIT_AUTHORIZATION
  {
    int code = SQLITE4_DROP_TRIGGER;
    const char *zDb = db->aDb[iDb].zName;
    const char *zTab = SCHEMA_TABLE(iDb);
    if( iDb==1 ) code = SQLITE4_DROP_TEMP_TRIGGER;
    if( sqlite4AuthCheck(pParse, code, pTrigger->zName, pTable->zName, zDb) ||
      sqlite4AuthCheck(pParse, SQLITE4_DELETE, zTab, 0, zDb) ){
      return;
    }
  }
#endif

  /* Generate code to destroy the database record of the trigger.
  */
  assert( pTable!=0 );
  if( (v = sqlite4GetVdbe(pParse))!=0 ){
    int base;
    static const VdbeOpList dropTrigger[] = {
      { OP_Rewind,     0, ADDR(9),  0},
      { OP_String8,    0, 1,        0}, /* 1 */
      { OP_Column,     0, 1,        2},
      { OP_Ne,         2, ADDR(8),  1},
      { OP_String8,    0, 1,        0}, /* 4: "trigger" */
      { OP_Column,     0, 0,        2},
      { OP_Ne,         2, ADDR(8),  1},
      { OP_Delete,     0, 0,        0},
      { OP_Next,       0, ADDR(1),  0}, /* 8 */
    };

    sqlite4BeginWriteOperation(pParse, 0, iDb);
    sqlite4OpenMasterTable(pParse, iDb);
    base = sqlite4VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
    sqlite4VdbeChangeP4(v, base+1, pTrigger->zName, P4_TRANSIENT);
    sqlite4VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
    sqlite4ChangeCookie(pParse, iDb);
    sqlite4VdbeAddOp2(v, OP_Close, 0, 0);
    sqlite4VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->zName, 0);
    if( pParse->nMem<3 ){
      pParse->nMem = 3;
    }
  }
}

/*
** Remove a trigger from the hash tables of the sqlite* pointer.
*/
SQLITE4_PRIVATE void sqlite4UnlinkAndDeleteTrigger(sqlite4 *db, int iDb, const char *zName){
  Trigger *pTrigger;
  Hash *pHash;

  pHash = &(db->aDb[iDb].pSchema->trigHash);
  pTrigger = sqlite4HashInsert(pHash, zName, sqlite4Strlen30(zName), 0);
  if( ALWAYS(pTrigger) ){
    if( pTrigger->pSchema==pTrigger->pTabSchema ){
      Table *pTab = tableOfTrigger(pTrigger);
      Trigger **pp;
      for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
      *pp = (*pp)->pNext;
    }
    sqlite4DeleteTrigger(db, pTrigger);
    db->flags |= SQLITE4_InternChanges;
  }
}

/*
** pEList is the SET clause of an UPDATE statement.  Each entry
** in pEList is of the format <id>=<expr>.  If any of the entries
** in pEList have an <id> which matches an identifier in pIdList,
** then return TRUE.  If pIdList==NULL, then it is considered a
** wildcard that matches anything.  Likewise if pEList==NULL then
** it matches anything so always return true.  Return false only
** if there is no match.
*/
static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
  int e;
  if( pIdList==0 || NEVER(pEList==0) ) return 1;
  for(e=0; e<pEList->nExpr; e++){
    if( sqlite4IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
  }
  return 0; 
}

/*
** Return a list of all triggers on table pTab if there exists at least
** one trigger that must be fired when an operation of type 'op' is 
** performed on the table, and, if that operation is an UPDATE, if at
** least one of the columns in pChanges is being modified.
*/
SQLITE4_PRIVATE Trigger *sqlite4TriggersExist(
  Parse *pParse,          /* Parse context */
  Table *pTab,            /* The table the contains the triggers */
  int op,                 /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
  ExprList *pChanges,     /* Columns that change in an UPDATE statement */
  int *pMask              /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
){
  int mask = 0;
  Trigger *pList = 0;
  Trigger *p;

  if( (pParse->db->flags & SQLITE4_EnableTrigger)!=0 ){
    pList = sqlite4TriggerList(pParse, pTab);
  }
  assert( pList==0 || IsVirtual(pTab)==0 );
  for(p=pList; p; p=p->pNext){
    if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
      mask |= p->tr_tm;
    }
  }
  if( pMask ){
    *pMask = mask;
  }
  return (mask ? pList : 0);
}

/*
** Convert the pStep->target token into a SrcList and return a pointer
** to that SrcList.
**
** This routine adds a specific database name, if needed, to the target when
** forming the SrcList.  This prevents a trigger in one database from
** referring to a target in another database.  An exception is when the
** trigger is in TEMP in which case it can refer to any other database it
** wants.
*/
static SrcList *targetSrcList(
  Parse *pParse,       /* The parsing context */
  TriggerStep *pStep   /* The trigger containing the target token */
){
  int iDb;             /* Index of the database to use */
  SrcList *pSrc;       /* SrcList to be returned */

  pSrc = sqlite4SrcListAppend(pParse->db, 0, &pStep->target, 0);
  if( pSrc ){
    assert( pSrc->nSrc>0 );
    assert( pSrc->a!=0 );
    iDb = sqlite4SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
    if( iDb==0 || iDb>=2 ){
      sqlite4 *db = pParse->db;
      assert( iDb<pParse->db->nDb );
      pSrc->a[pSrc->nSrc-1].zDatabase = sqlite4DbStrDup(db, db->aDb[iDb].zName);
    }
  }
  return pSrc;
}

/*
** Generate VDBE code for the statements inside the body of a single 
** trigger.
*/
static int codeTriggerProgram(
  Parse *pParse,            /* The parser context */
  TriggerStep *pStepList,   /* List of statements inside the trigger body */
  int orconf                /* Conflict algorithm. (OE_Abort, etc) */  
){
  TriggerStep *pStep;
  Vdbe *v = pParse->pVdbe;
  sqlite4 *db = pParse->db;

  assert( pParse->pTriggerTab && pParse->pToplevel );
  assert( pStepList );
  assert( v!=0 );
  for(pStep=pStepList; pStep; pStep=pStep->pNext){
    /* Figure out the ON CONFLICT policy that will be used for this step
    ** of the trigger program. If the statement that caused this trigger
    ** to fire had an explicit ON CONFLICT, then use it. Otherwise, use
    ** the ON CONFLICT policy that was specified as part of the trigger
    ** step statement. Example:
    **
    **   CREATE TRIGGER AFTER INSERT ON t1 BEGIN;
    **     INSERT OR REPLACE INTO t2 VALUES(new.a, new.b);
    **   END;
    **
    **   INSERT INTO t1 ... ;            -- insert into t2 uses REPLACE policy
    **   INSERT OR IGNORE INTO t1 ... ;  -- insert into t2 uses IGNORE policy
    */
    pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;

    switch( pStep->op ){
      case TK_UPDATE: {
        sqlite4Update(pParse, 
          targetSrcList(pParse, pStep),
          sqlite4ExprListDup(db, pStep->pExprList, 0), 
          sqlite4ExprDup(db, pStep->pWhere, 0), 
          pParse->eOrconf
        );
        break;
      }
      case TK_INSERT: {
        sqlite4Insert(pParse, 
          targetSrcList(pParse, pStep),
          sqlite4ExprListDup(db, pStep->pExprList, 0), 
          sqlite4SelectDup(db, pStep->pSelect, 0), 
          sqlite4IdListDup(db, pStep->pIdList), 
          pParse->eOrconf
        );
        break;
      }
      case TK_DELETE: {
        sqlite4DeleteFrom(pParse, 
          targetSrcList(pParse, pStep),
          sqlite4ExprDup(db, pStep->pWhere, 0)
        );
        break;
      }
      default: assert( pStep->op==TK_SELECT ); {
        SelectDest sDest;
        Select *pSelect = sqlite4SelectDup(db, pStep->pSelect, 0);
        sqlite4SelectDestInit(&sDest, SRT_Discard, 0);
        sqlite4Select(pParse, pSelect, &sDest);
        sqlite4SelectDelete(db, pSelect);
        break;
      }
    } 
    if( pStep->op!=TK_SELECT ){
      sqlite4VdbeAddOp0(v, OP_ResetCount);
    }
  }

  return 0;
}

#ifdef SQLITE4_DEBUG
/*
** This function is used to add VdbeComment() annotations to a VDBE
** program. It is not used in production code, only for debugging.
*/
static const char *onErrorText(int onError){
  switch( onError ){
    case OE_Abort:    return "abort";
    case OE_Rollback: return "rollback";
    case OE_Fail:     return "fail";
    case OE_Replace:  return "replace";
    case OE_Ignore:   return "ignore";
    case OE_Default:  return "default";
  }
  return "n/a";
}
#endif

/*
** Parse context structure pFrom has just been used to create a sub-vdbe
** (trigger program). If an error has occurred, transfer error information
** from pFrom to pTo.
*/
static void transferParseError(Parse *pTo, Parse *pFrom){
  assert( pFrom->zErrMsg==0 || pFrom->nErr );
  assert( pTo->zErrMsg==0 || pTo->nErr );
  if( pTo->nErr==0 ){
    pTo->zErrMsg = pFrom->zErrMsg;
    pTo->nErr = pFrom->nErr;
  }else{
    sqlite4DbFree(pFrom->db, pFrom->zErrMsg);
  }
}

/*
** Create and populate a new TriggerPrg object with a sub-program 
** implementing trigger pTrigger with ON CONFLICT policy orconf.
*/
static TriggerPrg *codeRowTrigger(
  Parse *pParse,       /* Current parse context */
  Trigger *pTrigger,   /* Trigger to code */
  Table *pTab,         /* The table pTrigger is attached to */
  int orconf           /* ON CONFLICT policy to code trigger program with */
){
  Parse *pTop = sqlite4ParseToplevel(pParse);
  sqlite4 *db = pParse->db;   /* Database handle */
  TriggerPrg *pPrg;           /* Value to return */
  Expr *pWhen = 0;            /* Duplicate of trigger WHEN expression */
  Vdbe *v;                    /* Temporary VM */
  NameContext sNC;            /* Name context for sub-vdbe */
  SubProgram *pProgram = 0;   /* Sub-vdbe for trigger program */
  Parse *pSubParse;           /* Parse context for sub-vdbe */
  int iEndTrigger = 0;        /* Label to jump to if WHEN is false */

  assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
  assert( pTop->pVdbe );

  /* Allocate the TriggerPrg and SubProgram objects. To ensure that they
  ** are freed if an error occurs, link them into the Parse.pTriggerPrg 
  ** list of the top-level Parse object sooner rather than later.  */
  pPrg = sqlite4DbMallocZero(db, sizeof(TriggerPrg));
  if( !pPrg ) return 0;
  pPrg->pNext = pTop->pTriggerPrg;
  pTop->pTriggerPrg = pPrg;
  pPrg->pProgram = pProgram = sqlite4DbMallocZero(db, sizeof(SubProgram));
  if( !pProgram ) return 0;
  sqlite4VdbeLinkSubProgram(pTop->pVdbe, pProgram);
  pPrg->pTrigger = pTrigger;
  pPrg->orconf = orconf;
  pPrg->aColmask[0] = 0xffffffff;
  pPrg->aColmask[1] = 0xffffffff;

  /* Allocate and populate a new Parse context to use for coding the 
  ** trigger sub-program.  */
  pSubParse = sqlite4StackAllocZero(db, sizeof(Parse));
  if( !pSubParse ) return 0;
  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pSubParse;
  pSubParse->db = db;
  pSubParse->pTriggerTab = pTab;
  pSubParse->pToplevel = pTop;
  pSubParse->zAuthContext = pTrigger->zName;
  pSubParse->eTriggerOp = pTrigger->op;
  pSubParse->nQueryLoop = pParse->nQueryLoop;

  v = sqlite4GetVdbe(pSubParse);
  if( v ){
    VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)", 
      pTrigger->zName, onErrorText(orconf),
      (pTrigger->tr_tm==TRIGGER_BEFORE ? "BEFORE" : "AFTER"),
        (pTrigger->op==TK_UPDATE ? "UPDATE" : ""),
        (pTrigger->op==TK_INSERT ? "INSERT" : ""),
        (pTrigger->op==TK_DELETE ? "DELETE" : ""),
      pTab->zName
    ));
#ifndef SQLITE4_OMIT_TRACE
    sqlite4VdbeChangeP4(v, -1, 
      sqlite4MPrintf(db, "-- TRIGGER %s", pTrigger->zName), P4_DYNAMIC
    );
#endif

    /* If one was specified, code the WHEN clause. If it evaluates to false
    ** (or NULL) the sub-vdbe is immediately halted by jumping to the 
    ** OP_Halt inserted at the end of the program.  */
    if( pTrigger->pWhen ){
      pWhen = sqlite4ExprDup(db, pTrigger->pWhen, 0);
      if( SQLITE4_OK==sqlite4ResolveExprNames(&sNC, pWhen) 
       && db->mallocFailed==0 
      ){
        iEndTrigger = sqlite4VdbeMakeLabel(v);
        sqlite4ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE4_JUMPIFNULL);
      }
      sqlite4ExprDelete(db, pWhen);
    }

    /* Code the trigger program into the sub-vdbe. */
    codeTriggerProgram(pSubParse, pTrigger->step_list, orconf);

    /* Insert an OP_Halt at the end of the sub-program. */
    if( iEndTrigger ){
      sqlite4VdbeResolveLabel(v, iEndTrigger);
    }
    sqlite4VdbeAddOp0(v, OP_Halt);
    VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));

    transferParseError(pParse, pSubParse);
    if( db->mallocFailed==0 ){
      pProgram->aOp = sqlite4VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg);
    }
    pProgram->nMem = pSubParse->nMem;
    pProgram->nCsr = pSubParse->nTab;
    pProgram->nOnce = pSubParse->nOnce;
    pProgram->token = (void *)pTrigger;
    pPrg->aColmask[0] = pSubParse->oldmask;
    pPrg->aColmask[1] = pSubParse->newmask;
    sqlite4VdbeDelete(v);
  }

  assert( !pSubParse->pAinc       && !pSubParse->pZombieTab );
  assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
  sqlite4StackFree(db, pSubParse);

  return pPrg;
}
    
/*
** Return a pointer to a TriggerPrg object containing the sub-program for
** trigger pTrigger with default ON CONFLICT algorithm orconf. If no such
** TriggerPrg object exists, a new object is allocated and populated before
** being returned.
*/
static TriggerPrg *getRowTrigger(
  Parse *pParse,       /* Current parse context */
  Trigger *pTrigger,   /* Trigger to code */
  Table *pTab,         /* The table trigger pTrigger is attached to */
  int orconf           /* ON CONFLICT algorithm. */
){
  Parse *pRoot = sqlite4ParseToplevel(pParse);
  TriggerPrg *pPrg;

  assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );

  /* It may be that this trigger has already been coded (or is in the
  ** process of being coded). If this is the case, then an entry with
  ** a matching TriggerPrg.pTrigger field will be present somewhere
  ** in the Parse.pTriggerPrg list. Search for such an entry.  */
  for(pPrg=pRoot->pTriggerPrg; 
      pPrg && (pPrg->pTrigger!=pTrigger || pPrg->orconf!=orconf); 
      pPrg=pPrg->pNext
  );

  /* If an existing TriggerPrg could not be located, create a new one. */
  if( !pPrg ){
    pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf);
  }

  return pPrg;
}

/*
** Generate code for the trigger program associated with trigger p on 
** table pTab. The reg, orconf and ignoreJump parameters passed to this
** function are the same as those described in the header function for
** sqlite4CodeRowTrigger()
*/
SQLITE4_PRIVATE void sqlite4CodeRowTriggerDirect(
  Parse *pParse,       /* Parse context */
  Trigger *p,          /* Trigger to code */
  Table *pTab,         /* The table to code triggers from */
  int reg,             /* Reg array containing OLD.* and NEW.* values */
  int orconf,          /* ON CONFLICT policy */
  int ignoreJump       /* Instruction to jump to for RAISE(IGNORE) */
){
  Vdbe *v = sqlite4GetVdbe(pParse); /* Main VM */
  TriggerPrg *pPrg;
  pPrg = getRowTrigger(pParse, p, pTab, orconf);
  assert( pPrg || pParse->nErr || pParse->db->mallocFailed );

  /* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program 
  ** is a pointer to the sub-vdbe containing the trigger program.  */
  if( pPrg ){
    sqlite4VdbeAddOp3(v, OP_Program, reg, ignoreJump, ++pParse->nMem);
    sqlite4VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM);
    VdbeComment(
        (v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf)));
  }
}

/*
** This is called to code the required FOR EACH ROW triggers for an operation
** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE)
** is given by the op paramater. The tr_tm parameter determines whether the
** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then
** parameter pChanges is passed the list of columns being modified.
**
** If there are no triggers that fire at the specified time for the specified
** operation on pTab, this function is a no-op.
**
** The reg argument is the address of the first in an array of registers 
** that contain the values substituted for the new.* and old.* references
** in the trigger program. If N is the number of columns in table pTab
** (a copy of pTab->nCol), then registers are populated as follows:
**
**   Register       Contains
**   ------------------------------------------------------
**   reg+0          OLD.rowid
**   reg+1          OLD.* value of left-most column of pTab
**   ...            ...
**   reg+N          OLD.* value of right-most column of pTab
**   reg+N+1        NEW.rowid
**   reg+N+2        OLD.* value of left-most column of pTab
**   ...            ...
**   reg+N+N+1      NEW.* value of right-most column of pTab
**
** For ON DELETE triggers, the registers containing the NEW.* values will
** never be accessed by the trigger program, so they are not allocated or 
** populated by the caller (there is no data to populate them with anyway). 
** Similarly, for ON INSERT triggers the values stored in the OLD.* registers
** are never accessed, and so are not allocated by the caller. So, for an
** ON INSERT trigger, the value passed to this function as parameter reg
** is not a readable register, although registers (reg+N) through 
** (reg+N+N+1) are.
**
** Parameter orconf is the default conflict resolution algorithm for the
** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump
** is the instruction that control should jump to if a trigger program
** raises an IGNORE exception.
*/
SQLITE4_PRIVATE void sqlite4CodeRowTrigger(
  Parse *pParse,       /* Parse context */
  Trigger *pTrigger,   /* List of triggers on table pTab */
  int op,              /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
  ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
  int tr_tm,           /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
  Table *pTab,         /* The table to code triggers from */
  int reg,             /* The first in an array of registers (see above) */
  int orconf,          /* ON CONFLICT policy */
  int ignoreJump       /* Instruction to jump to for RAISE(IGNORE) */
){
  Trigger *p;          /* Used to iterate through pTrigger list */

  assert( op==TK_UPDATE || op==TK_INSERT || op==TK_DELETE );
  assert( tr_tm==TRIGGER_BEFORE || tr_tm==TRIGGER_AFTER );
  assert( (op==TK_UPDATE)==(pChanges!=0) );

  for(p=pTrigger; p; p=p->pNext){

    /* Sanity checking:  The schema for the trigger and for the table are
    ** always defined.  The trigger must be in the same schema as the table
    ** or else it must be a TEMP trigger. */
    assert( p->pSchema!=0 );
    assert( p->pTabSchema!=0 );
    assert( p->pSchema==p->pTabSchema 
         || p->pSchema==pParse->db->aDb[1].pSchema );

    /* Determine whether we should code this trigger */
    if( p->op==op 
     && p->tr_tm==tr_tm 
     && checkColumnOverlap(p->pColumns, pChanges)
    ){
      sqlite4CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
    }
  }
}

/*
** Triggers may access values stored in the old.* or new.* pseudo-table. 
** This function returns a 32-bit bitmask indicating which columns of the 
** old.* or new.* tables actually are used by triggers. This information 
** may be used by the caller, for example, to avoid having to load the entire
** old.* record into memory when executing an UPDATE or DELETE command.
**
** Bit 0 of the returned mask is set if the left-most column of the
** table may be accessed using an [old|new].<col> reference. Bit 1 is set if
** the second leftmost column value is required, and so on. If there
** are more than 32 columns in the table, and at least one of the columns
** with an index greater than 32 may be accessed, 0xffffffff is returned.
**
** It is not possible to determine if the old.rowid or new.rowid column is 
** accessed by triggers. The caller must always assume that it is.
**
** Parameter isNew must be either 1 or 0. If it is 0, then the mask returned
** applies to the old.* table. If 1, the new.* table.
**
** Parameter tr_tm must be a mask with one or both of the TRIGGER_BEFORE
** and TRIGGER_AFTER bits set. Values accessed by BEFORE triggers are only
** included in the returned mask if the TRIGGER_BEFORE bit is set in the
** tr_tm parameter. Similarly, values accessed by AFTER triggers are only
** included in the returned mask if the TRIGGER_AFTER bit is set in tr_tm.
*/
SQLITE4_PRIVATE u32 sqlite4TriggerColmask(
  Parse *pParse,       /* Parse context */
  Trigger *pTrigger,   /* List of triggers on table pTab */
  ExprList *pChanges,  /* Changes list for any UPDATE OF triggers */
  int isNew,           /* 1 for new.* ref mask, 0 for old.* ref mask */
  int tr_tm,           /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
  Table *pTab,         /* The table to code triggers from */
  int orconf           /* Default ON CONFLICT policy for trigger steps */
){
  const int op = pChanges ? TK_UPDATE : TK_DELETE;
  u32 mask = 0;
  Trigger *p;

  assert( isNew==1 || isNew==0 );
  for(p=pTrigger; p; p=p->pNext){
    if( p->op==op && (tr_tm&p->tr_tm)
     && checkColumnOverlap(p->pColumns,pChanges)
    ){
      TriggerPrg *pPrg;
      pPrg = getRowTrigger(pParse, p, pTab, orconf);
      if( pPrg ){
        mask |= pPrg->aColmask[isNew];
      }
    }
  }

  return mask;
}

#endif /* !defined(SQLITE4_OMIT_TRIGGER) */

/************** End of trigger.c *********************************************/
/************** Begin file update.c ******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
*/

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
  SrcList *pSrc,       /* The virtual table to be modified */
  Table *pTab,         /* The virtual table */
  ExprList *pChanges,  /* The columns to change in the UPDATE statement */
  Expr *pRowidExpr,    /* Expression used to recompute the rowid */
  int *aXRef,          /* Mapping from columns of pTab to entries in pChanges */
  Expr *pWhere,        /* WHERE clause of the UPDATE statement */
  int onError          /* ON CONFLICT strategy */
);
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

/*
** The most recently coded instruction was an OP_Column to retrieve the
** i-th column of table pTab. This routine sets the P4 parameter of the 
** OP_Column to the default value, if any.
**
** The default value of a column is specified by a DEFAULT clause in the 
** column definition. This was either supplied by the user when the table
** was created, or added later to the table definition by an ALTER TABLE
** command. If the latter, then the row-records in the table btree on disk
** may not contain a value for the column and the default value, taken
** from the P4 parameter of the OP_Column instruction, is returned instead.
** If the former, then all row-records are guaranteed to include a value
** for the column and the P4 value is not required.
**
** Column definitions created by an ALTER TABLE command may only have 
** literal default values specified: a number, null or a string. (If a more
** complicated default expression value was provided, it is evaluated 
** when the ALTER TABLE is executed and one of the literal values written
** into the sqlite_master table.)
**
** Therefore, the P4 parameter is only required if the default value for
** the column is a literal number, string or null. The sqlite4ValueFromExpr()
** function is capable of transforming these types of expressions into
** sqlite4_value objects.
**
** If parameter iReg is not negative, code an OP_RealAffinity instruction
** on register iReg. This is used when an equivalent integer value is 
** stored in place of an 8-byte floating point value in order to save 
** space.
*/
SQLITE4_PRIVATE void sqlite4ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
  assert( pTab!=0 );
  if( !pTab->pSelect ){
    sqlite4_value *pValue;
    u8 enc = ENC(sqlite4VdbeDb(v));
    Column *pCol = &pTab->aCol[i];
    VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
    assert( i<pTab->nCol );
    sqlite4ValueFromExpr(sqlite4VdbeDb(v), pCol->pDflt, enc, 
                         pCol->affinity, &pValue);
    if( pValue ){
      sqlite4VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM);
    }
#ifndef SQLITE4_OMIT_FLOATING_POINT
    if( iReg>=0 && pTab->aCol[i].affinity==SQLITE4_AFF_REAL ){
      sqlite4VdbeAddOp1(v, OP_RealAffinity, iReg);
    }
#endif
  }
}

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
**          \_______/ \________/     \______/       \________________/
*            onError   pSrc          pChanges             pWhere
*/
SQLITE4_PRIVATE void sqlite4Update(
  Parse *pParse,         /* The parser context */
  SrcList *pSrc,         /* The table in which we should change things */
  ExprList *pChanges,    /* Things to be changed */
  Expr *pWhere,          /* The WHERE clause.  May be null */
  int onError            /* How to handle constraint errors */
){
  int i, j;              /* Loop counters */
  Table *pTab;           /* The table to be updated */
  int addr = 0;          /* VDBE instruction address of the start of the loop */
  WhereInfo *pWInfo;     /* Information about the WHERE clause */
  Vdbe *v;               /* The virtual database engine */
  Index *pIdx;           /* Iterator variable */
  int nIdx;              /* Total number of indexes on table (incl. PK) */
  int iCur;              /* VDBE Cursor number of pTab */
  sqlite4 *db;           /* The database structure */
  int *aRegIdx = 0;      /* One register assigned to each index to be updated */
  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                         ** an expression for the i-th column of the table.
                         ** aXRef[i]==-1 if the i-th column is not changed. */
  AuthContext sContext;  /* The authorization context */
  NameContext sNC;       /* The name-context to resolve expressions in */
  int iDb;               /* Database containing the table being updated */
  int okOnePass;         /* True for one-pass algorithm without the FIFO */
  int hasFK;             /* True if foreign key processing is required */

#ifndef SQLITE4_OMIT_TRIGGER
  int isView;            /* True when updating a view (INSTEAD OF trigger) */
  Trigger *pTrigger;     /* List of triggers on pTab, if required */
  int tmask;             /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
#endif
  int newmask;           /* Mask of NEW.* columns accessed by BEFORE triggers */

  int regOldKey;                  /* Register containing the original PK */
  int regNew;                     /* Content of the NEW.* table in triggers */
  int regOld = 0;                 /* Content of OLD.* table in triggers */
  int regRowSet = 0;              /* Register containing RowSet object */
  Index *pPk = 0;                 /* The primary key index of this table */
  int iPk = 0;                    /* Offset of primary key in aRegIdx[] */
  int bChngPk = 0;                /* True if any PK columns are updated */
  int bOpenAll = 0;               /* True if all indexes were opened */
  int bImplicitPk = 0;            /* True if pTab has an implicit PK */
  int regOldTr = 0;               /* Content of OLD.* table including IPK */
  int regNewTr = 0;               /* Content of NEW.* table including IPK */

  memset(&sContext, 0, sizeof(sContext));
  db = pParse->db;
  if( pParse->nErr || db->mallocFailed ){
    goto update_cleanup;
  }
  assert( pSrc->nSrc==1 );

  /* Locate and analyze the table to be updated. This block sets:
  **
  **   pTab
  **   iDb
  **   pPk
  **   bImplicitPk
  */
  pTab = sqlite4SrcListLookup(pParse, pSrc);
  if( pTab==0 ) goto update_cleanup;
  iDb = sqlite4SchemaToIndex(pParse->db, pTab->pSchema);
  if( IsView(pTab)==0 ){
    pPk = sqlite4FindPrimaryKey(pTab, &iPk);
    bImplicitPk = (pPk->aiColumn[0]<0);
  }

  /* Figure out if we have any triggers and if the table being
  ** updated is a view.
  */
#ifndef SQLITE4_OMIT_TRIGGER
  pTrigger = sqlite4TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
  isView = pTab->pSelect!=0;
  assert( pTrigger || tmask==0 );
#else
# define pTrigger 0
# define isView 0
# define tmask 0
#endif
#ifdef SQLITE4_OMIT_VIEW
# undef isView
# define isView 0
#endif

  if( sqlite4ViewGetColumnNames(pParse, pTab) ) goto update_cleanup;
  if( sqlite4IsReadOnly(pParse, pTab, tmask) ) goto update_cleanup;

  aXRef = sqlite4DbMallocRaw(db, sizeof(int) * pTab->nCol );
  if( aXRef==0 ) goto update_cleanup;
  for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;

  /* Allocate a cursors for the main database table and for all indices.
  ** The index cursors might not be used, but if they are used they
  ** need to occur right after the database cursor.  So go ahead and
  ** allocate enough space, just in case.  */
  iCur = pParse->nTab;
  pSrc->a[0].iCursor = iCur+iPk;
  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    pParse->nTab++;
  }
  if( IsView(pTab) ) pParse->nTab++;

  /* Initialize the name-context */
  memset(&sNC, 0, sizeof(sNC));
  sNC.pParse = pParse;
  sNC.pSrcList = pSrc;

  /* Resolve the column names in all the expressions of the of the UPDATE 
  ** statement. Also find the column index for each column to be updated in 
  ** the pChanges array.  For each column to be updated, make sure we have
  ** authorization to change that column.  
  **
  ** Also, if any columns that are part of the tables primary key are
  ** to be modified, set the bChngPk variable to true. This is significant
  ** because if the primary key changes, *all* index entries need to be
  ** replaced (not just those that index modified columns).  */
  for(i=0; i<pChanges->nExpr; i++){
    int iPkCol;                      /* To iterate through PK columns */

    /* Resolve any names in the expression for this assignment */
    if( sqlite4ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
      goto update_cleanup;
    }

    /* Resolve the column name on the left of the assignment */
    for(j=0; j<pTab->nCol; j++){
      if( sqlite4_stricmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ) break;
    }
    if( j==pTab->nCol ){
      sqlite4ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
      pParse->checkSchema = 1;
      goto update_cleanup;
    }
    aXRef[j] = i;

    /* Check if this column is part of the primary key. If so, set bChngPk. */
    if( !IsView(pTab) ){
      for(iPkCol=0; iPkCol<pPk->nColumn; iPkCol++){
        if( pPk->aiColumn[iPkCol]==j ) bChngPk = 1;
      }
    }

#ifndef SQLITE4_OMIT_AUTHORIZATION
    {
      int rc;
      rc = sqlite4AuthCheck(pParse, SQLITE4_UPDATE, pTab->zName,
                           pTab->aCol[j].zName, db->aDb[iDb].zName);
      if( rc==SQLITE4_DENY ){
        goto update_cleanup;
      }else if( rc==SQLITE4_IGNORE ){
        aXRef[j] = -1;
      }
    }
#endif
  }

  /* Begin generating code. */
  v = sqlite4GetVdbe(pParse);
  if( v==0 ) goto update_cleanup;
  if( pParse->nested==0 ) sqlite4VdbeCountChanges(v);
  sqlite4BeginWriteOperation(pParse, 1, iDb);

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  /* TODO: This is currently broken */
  /* Virtual tables must be handled separately */
  if( IsVirtual(pTab) ){
    updateVirtualTable(pParse, pSrc, pTab, pChanges, 0, aXRef, pWhere, onError);
    pWhere = 0;
    pSrc = 0;
    goto update_cleanup;
  }
#endif

  hasFK = sqlite4FkRequired(pParse, pTab, aXRef);

  /* Allocate memory for the array aRegIdx[].  There is one entry in the
  ** array for each index associated with table being updated.  Fill in
  ** the value with a register number for indices that are to be used
  ** and with zero for unused indices.  */
  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
  assert( nIdx>0 || isView );
  if( nIdx ){
    aRegIdx = sqlite4DbMallocZero(db, sizeof(Index*) * nIdx );
    if( aRegIdx==0 ) goto update_cleanup;
  }

  /* Allocate registers for and populate the aRegIdx array. */
  for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
    if( pIdx==pPk || hasFK || bChngPk ){
      aRegIdx[j] = ++pParse->nMem;
    }else{
      for(i=0; i<pIdx->nColumn; i++){
        if( aXRef[pIdx->aiColumn[i]]>=0 ){
          aRegIdx[j] = ++pParse->nMem;
          break;
        }
      }
    }
  }

  /* Allocate other required registers. Specifically:
  **
  **     regRowSet:     1 register
  **     regOldKey:     1 register
  **     regOldTr:      nCol+1 registers
  **     regNewTr:      nCol+1 registers
  **
  ** The regOldTr allocation is only required if there are either triggers 
  ** or foreign keys to be processed.
  **
  ** The regOldTr and regNewTr register arrays include space for the 
  ** implicit primary key value if the table in question does not have an
  ** explicit PRIMARY KEY.
  */
  regRowSet = ++pParse->nMem;
  regOldKey = ++pParse->nMem;
  if( pTrigger || hasFK ){
    regOldTr = pParse->nMem + 1;
    regOld = regOldTr+1;
    pParse->nMem += (pTab->nCol + 1);
  }
  regNewTr = pParse->nMem + 1;
  regNew = regNewTr+1;
  pParse->nMem += (pTab->nCol+1);

  /* Start the view context. */
  if( isView ){
    sqlite4AuthContextPush(pParse, &sContext, pTab->zName);
  }

  /* If we are trying to update a view, realize that view into
  ** a ephemeral table.
  */
#if !defined(SQLITE4_OMIT_VIEW) && !defined(SQLITE4_OMIT_TRIGGER)
  if( isView ){
    sqlite4MaterializeView(pParse, pTab, pWhere, iCur);
  }
#endif

  /* Resolve the column names in all the expressions in the
  ** WHERE clause.
  */
  if( sqlite4ResolveExprNames(&sNC, pWhere) ){
    goto update_cleanup;
  }

  /* This block codes a loop that iterates through all rows of the table
  ** identified by the UPDATE statements WHERE clause. The primary key
  ** of each row visited by the loop is added to the RowSet object stored
  ** in register regRowSet.
  **
  ** There is one exception to the above: If static analysis of the WHERE 
  ** clause indicates that the loop will visit at most one row, then the
  ** RowSet object is bypassed and the primary key of the single row (if
  ** any) left in register regOldKey. This is called the "one-pass"
  ** approach. Set okOnePass to true if it can be used in this case.  */
  sqlite4VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldKey);
  pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0);
  if( pWInfo==0 ) goto update_cleanup;
  okOnePass = sqlite4WhereOkOnePass(pWInfo);
  sqlite4VdbeAddOp2(v, OP_RowKey, iCur+iPk, regOldKey);
  if( !okOnePass ){
    sqlite4VdbeAddOp3(v, OP_RowSetAdd, regRowSet, 0, regOldKey);
  }
  sqlite4WhereEnd(pWInfo);

  /* Open every index that needs updating. If any index could potentially 
  ** invoke a REPLACE conflict resolution action, then we need to open all 
  ** indices because we might need to be deleting some records.  */
  if( !isView ){
    /* Set bOpenAll to true if this UPDATE might strike a REPLACE */
    bOpenAll = (onError==OE_Replace);
    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( aRegIdx[i] && pIdx->onError==OE_Replace ) bOpenAll = 1;
    }

    /* If bOpenAll is true, open all indexes. Otherwise, just open those
    ** indexes for which the corresponding aRegIdx[] entry is non-zero
    ** (those that index columns that will be modified by this UPDATE
    ** statement). Also, if the one-pass approach is being used, do not
    ** open the primary key index here - it is already open.  */
    for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      if( (bOpenAll || aRegIdx[i]) && (okOnePass==0 || pIdx!=pPk) ){
        sqlite4OpenIndex(pParse, iCur+i, iDb, pIdx, OP_OpenWrite);
      }
    }
  }

  /* The next instruction coded is the top of the update loop (executed once
  ** for each row to be updated). 
  **
  ** If okOnePass is true, then regOldKey either contains the encoded PK of 
  ** the row to update, or it is NULL (indicating that this statement will 
  ** update zero rows). If this is the case, jump to the end of the loop 
  ** without doing anything. Otherwise - if okOnePass is true and regOldKey 
  ** contains something other than NULL - proceed.
  **
  ** Or, if okOnePass is false, then the RowSet object stored in register
  ** regRowSet contains the set of encoded PKs for the rows that will
  ** be updated by this statement. Read the next one into register regOldKey.
  ** Or, if the RowSet is already empty, jump to the end of the loop.
  */
  if( okOnePass ){
    int a1 = sqlite4VdbeAddOp1(v, OP_NotNull, regOldKey);
    addr = sqlite4VdbeAddOp0(v, OP_Goto);
    sqlite4VdbeJumpHere(v, a1);
  }else{
    addr = sqlite4VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldKey);
  }

  /* Make cursor iCur point to the record that is being updated. If
  ** this record does not exist for some reason (deleted by a trigger,
  ** for example, then jump to the next iteration of the RowSet loop. 
  ** TODO: If okOnePass is true, does iCur already point to this record? */
  sqlite4VdbeAddOp4(v, OP_NotFound, iCur+iPk, addr, regOldKey, 0, P4_INT32);

  /* If there are triggers on this table, populate an array of registers 
  ** with the required old.* column data.  */
  if( hasFK || pTrigger ){
    u32 oldmask = (hasFK ? sqlite4FkOldmask(pParse, pTab) : 0);
    oldmask |= sqlite4TriggerColmask(pParse, 
        pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
    );

    if( bImplicitPk ){
      sqlite4VdbeAddOp2(v, OP_Rowid, iCur+iPk, regOldTr);
    }
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 || oldmask==0xffffffff || (i<32 && (oldmask & (1<<i))) ){
        sqlite4ExprCodeGetColumnOfTable(v, pTab, iCur+iPk, i, regOld+i);
      }else{
        sqlite4VdbeAddOp2(v, OP_Null, 0, regOld+i);
      }
    }
  }

  /* Populate the array of registers beginning at regNew with the new
  ** row data. This array is used to check constaints, create the new
  ** table and index records, and as the values for any new.* references
  ** made by triggers.
  **
  ** If there are one or more BEFORE triggers, then do not populate the
  ** registers associated with columns that are (a) not modified by
  ** this UPDATE statement and (b) not accessed by new.* references. The
  ** values for registers not modified by the UPDATE must be reloaded from 
  ** the database after the BEFORE triggers are fired anyway (as the trigger 
  ** may have modified them). So not loading those that are not going to
  ** be used eliminates some redundant opcodes.
  */
  newmask = sqlite4TriggerColmask(
      pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
  );
  sqlite4VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);
  for(i=0; i<pTab->nCol; i++){
    j = aXRef[i];
    if( j>=0 ){
      sqlite4ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
    }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
      /* This branch loads the value of a column that will not be changed 
      ** into a register. This is done if there are no BEFORE triggers, or
      ** if there are one or more BEFORE triggers that use this value via
      ** a new.* reference in a trigger program.
      */
      testcase( i==31 );
      testcase( i==32 );
      sqlite4ExprCodeGetColumnOfTable(v, pTab, iCur+iPk, i, regNew+i);
    }
  }
  if( bImplicitPk ){
    sqlite4VdbeAddOp2(v, OP_Rowid, iCur+iPk, regNew-1);
  }

  /* Fire any BEFORE UPDATE triggers. This happens before constraints are
  ** verified. One could argue that this is wrong.
  */
  if( tmask&TRIGGER_BEFORE ){
    sqlite4VdbeAddOp2(v, OP_Affinity, regNew, pTab->nCol);
    sqlite4TableAffinityStr(v, pTab);
    sqlite4CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
        TRIGGER_BEFORE, pTab, regOldTr, onError, addr);

    /* The row-trigger may have deleted the row being updated. In this
    ** case, jump to the next row. No updates or AFTER triggers are 
    ** required. This behaviour - what happens when the row being updated
    ** is deleted or renamed by a BEFORE trigger - is left undefined in the
    ** documentation.
    */
    sqlite4VdbeAddOp4Int(v, OP_NotFound, iCur+iPk, addr, regOldKey, 0);

    /* If it did not delete it, the row-trigger may still have modified 
    ** some of the columns of the row being updated. Load the values for 
    ** all columns not modified by the update statement into their 
    ** registers in case this has happened.
    */
    for(i=0; i<pTab->nCol; i++){
      if( aXRef[i]<0 ){
        sqlite4ExprCodeGetColumnOfTable(v, pTab, iCur+iPk, i, regNew+i);
      }
    }
  }

  if( !isView ){
    int j1;                       /* Address of jump instruction */

    /* Do constraint checks. */
    assert( bChngPk==0 || bImplicitPk==0 );
    if( bChngPk==0 ) aRegIdx[iPk] = 0;
    sqlite4GenerateConstraintChecks(
        pParse, pTab, iCur, regNew, aRegIdx, regOldKey, 1, onError, addr, 0
    );
    if( bChngPk==0 ) aRegIdx[iPk] = regOldKey;

    /* Do FK constraint checks. */
    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, regOld, 0);
    }

    /* Delete the index entries associated with the current record.  */
    j1 = sqlite4VdbeAddOp4(v, OP_NotFound, iCur+iPk, 0, regOldKey, 0, P4_INT32);
    sqlite4GenerateRowIndexDelete(pParse, pTab, 0, iCur, aRegIdx);
    sqlite4VdbeJumpHere(v, j1);

    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, 0, regNew);
    }
  
    /* Insert the new index entries and the new record. */
    sqlite4CompleteInsertion(pParse, pTab, iCur, regNew, aRegIdx, 1, 0, 0);

    /* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
    ** handle rows (possibly in other tables) that refer via a foreign key
    ** to the row just updated. */ 
    if( hasFK ){
      sqlite4FkActions(pParse, pTab, pChanges, regOldTr);
    }
  }

  sqlite4CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges, 
      TRIGGER_AFTER, pTab, regOldTr, onError, addr);

  /* Repeat the above with the next record to be updated, until
  ** all record selected by the WHERE clause have been updated.
  */
  sqlite4VdbeAddOp2(v, OP_Goto, 0, addr);
  sqlite4VdbeJumpHere(v, addr);

  /* Close all cursors */
  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    assert( aRegIdx );
    if( bOpenAll || aRegIdx[i] ){
      sqlite4VdbeAddOp2(v, OP_Close, iCur+i, 0);
    }
  }

  /* Update the sqlite_sequence table by storing the content of the
  ** maximum rowid counter values recorded while inserting into
  ** autoincrement tables.
  */
  if( pParse->nested==0 && pParse->pTriggerTab==0 ){
    sqlite4AutoincrementEnd(pParse);
  }

update_cleanup:
  sqlite4AuthContextPop(&sContext);
  sqlite4DbFree(db, aRegIdx);
  sqlite4DbFree(db, aXRef);
  sqlite4SrcListDelete(db, pSrc);
  sqlite4ExprListDelete(db, pChanges);
  sqlite4ExprDelete(db, pWhere);
  return;
}
/* Make sure "isView" and other macros defined above are undefined. Otherwise
** thely may interfere with compilation of other functions in this file
** (or in another file, if this file becomes part of the amalgamation).  */
#ifdef isView
 #undef isView
#endif
#ifdef pTrigger
 #undef pTrigger
#endif

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/*
** Generate code for an UPDATE of a virtual table.
**
** The strategy is that we create an ephemerial table that contains
** for each row to be changed:
**
**   (A)  The original rowid of that row.
**   (B)  The revised rowid for the row. (note1)
**   (C)  The content of every column in the row.
**
** Then we loop over this ephemeral table and for each row in
** the ephermeral table call VUpdate.
**
** When finished, drop the ephemeral table.
**
** (note1) Actually, if we know in advance that (A) is always the same
** as (B) we only store (A), then duplicate (A) when pulling
** it out of the ephemeral table before calling VUpdate.
*/
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
  SrcList *pSrc,       /* The virtual table to be modified */
  Table *pTab,         /* The virtual table */
  ExprList *pChanges,  /* The columns to change in the UPDATE statement */
  Expr *pRowid,        /* Expression used to recompute the rowid */
  int *aXRef,          /* Mapping from columns of pTab to entries in pChanges */
  Expr *pWhere,        /* WHERE clause of the UPDATE statement */
  int onError          /* ON CONFLICT strategy */
){
  Vdbe *v = pParse->pVdbe;  /* Virtual machine under construction */
  ExprList *pEList = 0;     /* The result set of the SELECT statement */
  Select *pSelect = 0;      /* The SELECT statement */
  Expr *pExpr;              /* Temporary expression */
  int ephemTab;             /* Table holding the result of the SELECT */
  int i;                    /* Loop counter */
  int addr;                 /* Address of top of loop */
  int iReg;                 /* First register in set passed to OP_VUpdate */
  sqlite4 *db = pParse->db; /* Database connection */
  const char *pVTab = (const char*)sqlite4GetVTable(db, pTab);
  SelectDest dest;

  /* Construct the SELECT statement that will find the new values for
  ** all updated rows. 
  */
  pEList = sqlite4ExprListAppend(pParse, 0, sqlite4Expr(db, TK_ID, "_rowid_"));
  if( pRowid ){
    pEList = sqlite4ExprListAppend(pParse, pEList,
                                   sqlite4ExprDup(db, pRowid, 0));
  }
  assert( pTab->iPKey<0 );
  for(i=0; i<pTab->nCol; i++){
    if( aXRef[i]>=0 ){
      pExpr = sqlite4ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0);
    }else{
      pExpr = sqlite4Expr(db, TK_ID, pTab->aCol[i].zName);
    }
    pEList = sqlite4ExprListAppend(pParse, pEList, pExpr);
  }
  pSelect = sqlite4SelectNew(pParse, pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
  
  /* Create the ephemeral table into which the update results will
  ** be stored.
  */
  assert( v );
  ephemTab = pParse->nTab++;
  sqlite4VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));

  /* fill the ephemeral table 
  */
  sqlite4SelectDestInit(&dest, SRT_Table, ephemTab);
  sqlite4Select(pParse, pSelect, &dest);

  /* Generate code to scan the ephemeral table and call VUpdate. */
  iReg = ++pParse->nMem;
  pParse->nMem += pTab->nCol+1;
  addr = sqlite4VdbeAddOp2(v, OP_Rewind, ephemTab, 0);
  sqlite4VdbeAddOp3(v, OP_Column,  ephemTab, 0, iReg);
  sqlite4VdbeAddOp3(v, OP_Column, ephemTab, (pRowid?1:0), iReg+1);
  for(i=0; i<pTab->nCol; i++){
    sqlite4VdbeAddOp3(v, OP_Column, ephemTab, i+1+(pRowid!=0), iReg+2+i);
  }
  sqlite4VtabMakeWritable(pParse, pTab);
  sqlite4VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
  sqlite4VdbeChangeP5(v, onError==OE_Default ? OE_Abort : onError);
  sqlite4MayAbort(pParse);
  sqlite4VdbeAddOp2(v, OP_Next, ephemTab, addr+1);
  sqlite4VdbeJumpHere(v, addr);
  sqlite4VdbeAddOp2(v, OP_Close, ephemTab, 0);

  /* Cleanup */
  sqlite4SelectDelete(db, pSelect);  
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

/************** End of update.c **********************************************/
/************** Begin file where.c *******************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is responsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
*/

/*
** Trace output macros
*/
#if defined(SQLITE4_TEST) || defined(SQLITE4_DEBUG)
/***/ int sqlite4WhereTrace = 0;
#endif
#if defined(SQLITE4_DEBUG) \
    && (defined(SQLITE4_TEST) || defined(SQLITE4_ENABLE_WHERETRACE))
# define WHERETRACE(K,X)  if(sqlite4WhereTrace&(K)) sqlite4DebugPrintf X
# define WHERETRACE_ENABLED 1
#else
# define WHERETRACE(K,X)
#endif

/* Forward reference
*/
typedef struct WhereClause WhereClause;
typedef struct WhereMaskSet WhereMaskSet;
typedef struct WhereOrInfo WhereOrInfo;
typedef struct WhereAndInfo WhereAndInfo;
typedef struct WhereLevel WhereLevel;
typedef struct WhereLoop WhereLoop;
typedef struct WherePath WherePath;
typedef struct WhereTerm WhereTerm;
typedef struct WhereLoopBuilder WhereLoopBuilder;
typedef struct WhereScan WhereScan;
typedef struct WhereOrCost WhereOrCost;
typedef struct WhereOrSet WhereOrSet;

/*
** Cost X is tracked as 10*log2(X) stored in a 16-bit integer.  The
** maximum cost for ordinary tables is 64*(2**63) which becomes 6900.
** (Virtual tables can return a larger cost, but let's assume they do not.)
** So all costs can be stored in a 16-bit unsigned integer without risk
** of overflow.
**
** Costs are estimates, so don't go to the computational trouble to compute
** 10*log2(X) exactly.  Instead, a close estimate is used.  Any value of
** X<=1 is stored as 0.  X=2 is 10.  X=3 is 16.  X=1000 is 99. etc.
**
** The tool/wherecosttest.c source file implements a command-line program
** that will convert between WhereCost to integers and do addition and
** multiplication on WhereCost values.  That command-line program is a
** useful utility to have around when working with this module.
*/
typedef unsigned short int WhereCost;

/*
** This object contains information needed to implement a single nested
** loop in WHERE clause.
**
** Contrast this object with WhereLoop.  This object describes the
** implementation of the loop.  WhereLoop describes the algorithm.
** This object contains a pointer to the WhereLoop algorithm as one of
** its elements.
**
** The WhereInfo object contains a single instance of this object for
** each term in the FROM clause (which is to say, for each of the
** nested loops as implemented).  The order of WhereLevel objects determines
** the loop nested order, with WhereInfo.a[0] being the outer loop and
** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop.
*/
struct WhereLevel {
  int iLeftJoin;        /* Memory cell used to implement LEFT OUTER JOIN */
  int iTabCur;          /* The VDBE cursor used to access the table */
  int iIdxCur;          /* The VDBE cursor used to access pIdx */
  int addrBrk;          /* Jump here to break out of the loop */
  int addrNxt;          /* Jump here to start the next IN combination */
  int addrCont;         /* Jump here to continue with the next loop cycle */
  int addrFirst;        /* First instruction of interior of the loop */
  u8 iFrom;             /* Which entry in the FROM clause */
  u8 op, p5;            /* Opcode and P5 of the opcode that ends the loop */
  int p1, p2;           /* Operands of the opcode used to ends the loop */
  union {               /* Information that depends on pWLoop->wsFlags */
    struct {
      int nIn;              /* Number of entries in aInLoop[] */
      struct InLoop {
        int iCur;              /* The VDBE cursor used by this IN operator */
        int addrInTop;         /* Top of the IN loop */
        u8 eEndLoopOp;         /* IN Loop terminator. OP_Next or OP_Prev */
      } *aInLoop;           /* Information about each nested IN operator */
    } in;                 /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */
    Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
  } u;
  struct WhereLoop *pWLoop;  /* The selected WhereLoop object */
};

/*
** Each instance of this object represents an algorithm for evaluating one
** term of a join.  Every term of the FROM clause will have at least
** one corresponding WhereLoop object (unless INDEXED BY constraints
** prevent a query solution - which is an error) and many terms of the
** FROM clause will have multiple WhereLoop objects, each describing a
** potential way of implementing that FROM-clause term, together with
** dependencies and cost estimates for using the chosen algorithm.
**
** Query planning consists of building up a collection of these WhereLoop
** objects, then computing a particular sequence of WhereLoop objects, with
** one WhereLoop object per FROM clause term, that satisfy all dependencies
** and that minimize the overall cost.
*/
struct WhereLoop {
  Bitmask prereq;       /* Bitmask of other loops that must run first */
  Bitmask maskSelf;     /* Bitmask identifying table iTab */
#ifdef SQLITE4_DEBUG
  char cId;             /* Symbolic ID of this loop for debugging use */
#endif
  u8 iTab;              /* Position in FROM clause of table for this loop */
  u8 iSortIdx;          /* Sorting index number.  0==None */
  WhereCost rSetup;     /* One-time setup cost (ex: create transient index) */
  WhereCost rRun;       /* Cost of running each loop */
  WhereCost nOut;       /* Estimated number of output rows */
  union {
    struct {               /* Information for internal btree tables */
      int nEq;               /* Number of equality constraints */
      Index *pIndex;         /* Index used, or NULL */
    } btree;
    struct {               /* Information for virtual tables */
      int idxNum;            /* Index number */
      u8 needFree;           /* True if sqlite4_free(idxStr) is needed */
      u8 isOrdered;          /* True if satisfies ORDER BY */
      u16 omitMask;          /* Terms that may be omitted */
      char *idxStr;          /* Index identifier string */
    } vtab;
  } u;
  u32 wsFlags;          /* WHERE_* flags describing the plan */
  u16 nLTerm;           /* Number of entries in aLTerm[] */
  /**** whereLoopXfer() copies fields above ***********************/
# define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot)
  u16 nLSlot;           /* Number of slots allocated for aLTerm[] */
  WhereTerm **aLTerm;   /* WhereTerms used */
  WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
  WhereTerm *aLTermSpace[4];  /* Initial aLTerm[] space */
};

/* This object holds the prerequisites and the cost of running a
** subquery on one operand of an OR operator in the WHERE clause.
** See WhereOrSet for additional information 
*/
struct WhereOrCost {
  Bitmask prereq;     /* Prerequisites */
  WhereCost rRun;     /* Cost of running this subquery */
  WhereCost nOut;     /* Number of outputs for this subquery */
};

/* The WhereOrSet object holds a set of possible WhereOrCosts that
** correspond to the subquery(s) of OR-clause processing.  At most
** favorable N_OR_COST elements are retained.
*/
#define N_OR_COST 3
struct WhereOrSet {
  u16 n;                      /* Number of valid a[] entries */
  WhereOrCost a[N_OR_COST];   /* Set of best costs */
};


/* Forward declaration of methods */
static int whereLoopResize(sqlite4*, WhereLoop*, int);

/*
** Each instance of this object holds a sequence of WhereLoop objects
** that implement some or all of a query plan.
**
** Think of each WhereLoop object as a node in a graph with arcs
** showing dependences and costs for travelling between nodes.  (That is
** not a completely accurate description because WhereLoop costs are a
** vector, not a scalar, and because dependences are many-to-one, not
** one-to-one as are graph nodes.  But it is a useful visualization aid.)
** Then a WherePath object is a path through the graph that visits some
** or all of the WhereLoop objects once.
**
** The "solver" works by creating the N best WherePath objects of length
** 1.  Then using those as a basis to compute the N best WherePath objects
** of length 2.  And so forth until the length of WherePaths equals the
** number of nodes in the FROM clause.  The best (lowest cost) WherePath
** at the end is the choosen query plan.
*/
struct WherePath {
  Bitmask maskLoop;     /* Bitmask of all WhereLoop objects in this path */
  Bitmask revLoop;      /* aLoop[]s that should be reversed for ORDER BY */
  WhereCost nRow;       /* Estimated number of rows generated by this path */
  WhereCost rCost;      /* Total cost of this path */
  u8 isOrdered;         /* True if this path satisfies ORDER BY */
  u8 isOrderedValid;    /* True if the isOrdered field is valid */
  WhereLoop **aLoop;    /* Array of WhereLoop objects implementing this path */
};

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by AND operators,
** usually, or sometimes subexpressions separated by OR.
**
** All WhereTerms are collected into a single WhereClause structure.  
** The following identity holds:
**
**        WhereTerm.pWC->a[WhereTerm.idx] == WhereTerm
**
** When a term is of the form:
**
**              X <op> <expr>
**
** where X is a column name and <op> is one of certain operators,
** then WhereTerm.leftCursor and WhereTerm.u.leftColumn record the
** cursor number and column number for X.  WhereTerm.eOperator records
** the <op> using a bitmask encoding defined by WO_xxx below.  The
** use of a bitmask encoding for the operator allows us to search
** quickly for terms that match any of several different operators.
**
** A WhereTerm might also be two or more subterms connected by OR:
**
**         (t1.X <op> <expr>) OR (t1.Y <op> <expr>) OR ....
**
** In this second case, wtFlag as the TERM_ORINFO set and eOperator==WO_OR
** and the WhereTerm.u.pOrInfo field points to auxiliary information that
** is collected about the
**
** If a term in the WHERE clause does not match either of the two previous
** categories, then eOperator==0.  The WhereTerm.pExpr field is still set
** to the original subexpression content and wtFlags is set up appropriately
** but no other fields in the WhereTerm object are meaningful.
**
** When eOperator!=0, prereqRight and prereqAll record sets of cursor numbers,
** but they do so indirectly.  A single WhereMaskSet structure translates
** cursor number into bits and the translated bit is stored in the prereq
** fields.  The translation is used in order to maximize the number of
** bits that will fit in a Bitmask.  The VDBE cursor numbers might be
** spread out over the non-negative integers.  For example, the cursor
** numbers might be 3, 8, 9, 10, 20, 23, 41, and 45.  The WhereMaskSet
** translates these sparse cursor numbers into consecutive integers
** beginning with 0 in order to make the best possible use of the available
** bits in the Bitmask.  So, in the example above, the cursor numbers
** would be mapped into integers 0 through 7.
**
** The number of terms in a join is limited by the number of bits
** in prereqRight and prereqAll.  The default is 64 bits, hence SQLite
** is only able to process joins with 64 or fewer tables.
*/
struct WhereTerm {
  Expr *pExpr;            /* Pointer to the subexpression that is this term */
  int iParent;            /* Disable pWC->a[iParent] when this term disabled */
  int leftCursor;         /* Cursor number of X in "X <op> <expr>" */
  union {
    int leftColumn;         /* Column number of X in "X <op> <expr>" */
    WhereOrInfo *pOrInfo;   /* Extra information if (eOperator & WO_OR)!=0 */
    WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
  } u;
  u16 eOperator;          /* A WO_xx value describing <op> */
  u8 wtFlags;             /* TERM_xxx bit flags.  See below */
  u8 nChild;              /* Number of children that must disable us */
  WhereClause *pWC;       /* The clause this term is part of */
  Bitmask prereqRight;    /* Bitmask of tables used by pExpr->pRight */
  Bitmask prereqAll;      /* Bitmask of tables referenced by pExpr */
};

/*
** Allowed values of WhereTerm.wtFlags
*/
#define TERM_DYNAMIC    0x01   /* Need to call sqlite4ExprDelete(db, pExpr) */
#define TERM_VIRTUAL    0x02   /* Added by the optimizer.  Do not code */
#define TERM_CODED      0x04   /* This term is already coded */
#define TERM_COPIED     0x08   /* Has a child */
#define TERM_ORINFO     0x10   /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO    0x20   /* Need to free the WhereTerm.u.pAndInfo obj */
#define TERM_OR_OK      0x40   /* Used during OR-clause processing */
#ifdef SQLITE4_ENABLE_STAT3
#  define TERM_VNULL    0x80   /* Manufactured x>NULL or x<=NULL term */
#else
#  define TERM_VNULL    0x00   /* Disabled if not using stat3 */
#endif

/*
** An instance of the WhereScan object is used as an iterator for locating
** terms in the WHERE clause that are useful to the query planner.
*/
struct WhereScan {
  WhereClause *pOrigWC;      /* Original, innermost WhereClause */
  WhereClause *pWC;          /* WhereClause currently being scanned */
  char *zCollName;           /* Required collating sequence, if not NULL */
  char idxaff;               /* Must match this affinity, if zCollName!=NULL */
  unsigned char nEquiv;      /* Number of entries in aEquiv[] */
  unsigned char iEquiv;      /* Next unused slot in aEquiv[] */
  u32 opMask;                /* Acceptable operators */
  int k;                     /* Resume scanning at this->pWC->a[this->k] */
  int aEquiv[22];            /* Cursor,Column pairs for equivalence classes */
};

/*
** An instance of the following structure holds all information about a
** WHERE clause.  Mostly this is a container for one or more WhereTerms.
**
** Explanation of pOuter:  For a WHERE clause of the form
**
**           a AND ((b AND c) OR (d AND e)) AND f
**
** There are separate WhereClause objects for the whole clause and for
** the subclauses "(b AND c)" and "(d AND e)".  The pOuter field of the
** subclauses points to the WhereClause object for the whole clause.
*/
struct WhereClause {
  WhereInfo *pWInfo;       /* WHERE clause processing context */
  WhereClause *pOuter;     /* Outer conjunction */
  u8 op;                   /* Split operator.  TK_AND or TK_OR */
  int nTerm;               /* Number of terms */
  int nSlot;               /* Number of entries in a[] */
  WhereTerm *a;            /* Each a[] describes a term of the WHERE cluase */
#if defined(SQLITE4_SMALL_STACK)
  WhereTerm aStatic[1];    /* Initial static space for a[] */
#else
  WhereTerm aStatic[8];    /* Initial static space for a[] */
#endif
};

/*
** A WhereTerm with eOperator==WO_OR has its u.pOrInfo pointer set to
** a dynamically allocated instance of the following structure.
*/
struct WhereOrInfo {
  WhereClause wc;          /* Decomposition into subterms */
  Bitmask indexable;       /* Bitmask of all indexable tables in the clause */
};

/*
** A WhereTerm with eOperator==WO_AND has its u.pAndInfo pointer set to
** a dynamically allocated instance of the following structure.
*/
struct WhereAndInfo {
  WhereClause wc;          /* The subexpression broken out */
};

/*
** An instance of the following structure keeps track of a mapping
** between VDBE cursor numbers and bits of the bitmasks in WhereTerm.
**
** The VDBE cursor numbers are small integers contained in 
** SrcListItem.iCursor and Expr.iTable fields.  For any given WHERE 
** clause, the cursor numbers might not begin with 0 and they might
** contain gaps in the numbering sequence.  But we want to make maximum
** use of the bits in our bitmasks.  This structure provides a mapping
** from the sparse cursor numbers into consecutive integers beginning
** with 0.
**
** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask
** corresponds VDBE cursor number B.  The A-th bit of a bitmask is 1<<A.
**
** For example, if the WHERE clause expression used these VDBE
** cursors:  4, 5, 8, 29, 57, 73.  Then the  WhereMaskSet structure
** would map those cursor numbers into bits 0 through 5.
**
** Note that the mapping is not necessarily ordered.  In the example
** above, the mapping might go like this:  4->3, 5->1, 8->2, 29->0,
** 57->5, 73->4.  Or one of 719 other combinations might be used. It
** does not really matter.  What is important is that sparse cursor
** numbers all get mapped into bit numbers that begin with 0 and contain
** no gaps.
*/
struct WhereMaskSet {
  int n;                        /* Number of assigned cursor values */
  int ix[BMS];                  /* Cursor assigned to each bit */
};

/*
** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query.
*/
struct WhereLoopBuilder {
  WhereInfo *pWInfo;        /* Information about this WHERE */
  WhereClause *pWC;         /* WHERE clause terms */
  ExprList *pOrderBy;       /* ORDER BY clause */
  WhereLoop *pNew;          /* Template WhereLoop */
  WhereOrSet *pOrSet;       /* Record best loops here, if not NULL */
};

/*
** The WHERE clause processing routine has two halves.  The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop.  An instance of
** this structure is returned by the first half and passed
** into the second half to give some continuity.
**
** An instance of this object holds the complete state of the query
** planner.
*/
struct WhereInfo {
  Parse *pParse;            /* Parsing and code generating context */
  SrcList *pTabList;        /* List of tables in the join */
  ExprList *pOrderBy;       /* The ORDER BY clause or NULL */
  ExprList *pResultSet;     /* Result set. DISTINCT operates on these */
  WhereLoop *pLoops;        /* List of all WhereLoop objects */
  Bitmask revMask;          /* Mask of ORDER BY terms that need reversing */
  WhereCost nRowOut;        /* Estimated number of output rows */
  u16 wctrlFlags;           /* Flags originally passed to sqlite4WhereBegin() */
  u8 bOBSat;                /* ORDER BY satisfied by indices */
  u8 okOnePass;             /* Ok to use one-pass algorithm for UPDATE/DELETE */
  u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
  u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
  u8 nLevel;                /* Number of nested loop */
  int iTop;                 /* The very beginning of the WHERE loop */
  int iContinue;            /* Jump here to continue with next record */
  int iBreak;               /* Jump here to break out of the loop */
  int savedNQueryLoop;      /* pParse->nQueryLoop outside the WHERE loop */
  WhereMaskSet sMaskSet;    /* Map cursor numbers to bitmasks */
  WhereClause sWC;          /* Decomposition of the WHERE clause */
  WhereLevel a[1];          /* Information about each nest loop in WHERE */
};

/*
** Bitmasks for the operators on WhereTerm objects.  These are all
** operators that are of interest to the query planner.  An
** OR-ed combination of these values can be used when searching for
** particular WhereTerms within a WhereClause.
*/
#define WO_IN     0x001
#define WO_EQ     0x002
#define WO_LT     (WO_EQ<<(TK_LT-TK_EQ))
#define WO_LE     (WO_EQ<<(TK_LE-TK_EQ))
#define WO_GT     (WO_EQ<<(TK_GT-TK_EQ))
#define WO_GE     (WO_EQ<<(TK_GE-TK_EQ))
#define WO_MATCH  0x040
#define WO_ISNULL 0x080
#define WO_OR     0x100       /* Two or more OR-connected terms */
#define WO_AND    0x200       /* Two or more AND-connected terms */
#define WO_EQUIV  0x400       /* Of the form A==B, both columns */
#define WO_NOOP   0x800       /* This term does not restrict search space */

#define WO_ALL    0xfff       /* Mask of all possible WO_* values */
#define WO_SINGLE 0x0ff       /* Mask of all non-compound WO_* values */

/*
** These are definitions of bits in the WhereLoop.wsFlags field.
** The particular combination of bits in each WhereLoop help to
** determine the algorithm that WhereLoop represents.
*/
#define WHERE_COLUMN_EQ    0x00000001  /* x=EXPR */
#define WHERE_COLUMN_RANGE 0x00000002  /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN    0x00000004  /* x IN (...) */
#define WHERE_COLUMN_NULL  0x00000008  /* x IS NULL */
#define WHERE_CONSTRAINT   0x0000000f  /* Any of the WHERE_COLUMN_xxx values */
#define WHERE_TOP_LIMIT    0x00000010  /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT    0x00000020  /* x>EXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT   0x00000030  /* Both x>EXPR and x<EXPR */
#define WHERE_IDX_ONLY     0x00000040  /* Use index only - omit table */
#define WHERE_PRIMARY_KEY  0x00000100  /* Index is the PK index */
#define WHERE_INDEXED      0x00000200  /* WhereLoop.u.btree.pIndex is valid */
#define WHERE_VIRTUALTABLE 0x00000400  /* WhereLoop.u.vtab is valid */
#define WHERE_IN_ABLE      0x00000800  /* Able to support an IN operator */
#define WHERE_ONEROW       0x00001000  /* Selects no more than one row */
#define WHERE_MULTI_OR     0x00002000  /* OR using multiple indices */
#define WHERE_AUTO_INDEX   0x00004000  /* Uses an ephemeral index */


/* Convert a WhereCost value (10 times log2(X)) into its integer value X.
** A rough approximation is used.  The value returned is not exact.
*/
static u64 whereCostToInt(WhereCost x){
  u64 n;
  if( x<10 ) return 1;
  n = x%10;
  x /= 10;
  if( n>=5 ) n -= 2;
  else if( n>=1 ) n -= 1;
  if( x>=3 ) return (n+8)<<(x-3);
  return (n+8)>>(3-x);
}

/*
** Return the estimated number of output rows from a WHERE clause
*/
SQLITE4_PRIVATE u64 sqlite4WhereOutputRowCount(WhereInfo *pWInfo){
  return whereCostToInt(pWInfo->nRowOut);
}

/*
** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this
** WHERE clause returns outputs for DISTINCT processing.
*/
SQLITE4_PRIVATE int sqlite4WhereIsDistinct(WhereInfo *pWInfo){
  return pWInfo->eDistinct;
}

/*
** Return TRUE if the WHERE clause returns rows in ORDER BY order.
** Return FALSE if the output needs to be sorted.
*/
SQLITE4_PRIVATE int sqlite4WhereIsOrdered(WhereInfo *pWInfo){
  return pWInfo->bOBSat!=0;
}

/*
** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause.
*/
SQLITE4_PRIVATE int sqlite4WhereContinueLabel(WhereInfo *pWInfo){
  return pWInfo->iContinue;
}

/*
** Return the VDBE address or label to jump to in order to break
** out of a WHERE loop.
*/
SQLITE4_PRIVATE int sqlite4WhereBreakLabel(WhereInfo *pWInfo){
  return pWInfo->iBreak;
}

/*
** Return TRUE if an UPDATE or DELETE statement can operate directly on
** the rowids returned by a WHERE clause.  Return FALSE if doing an
** UPDATE or DELETE might change subsequent WHERE clause results.
*/
SQLITE4_PRIVATE int sqlite4WhereOkOnePass(WhereInfo *pWInfo){
  return pWInfo->okOnePass;
}

/*
** Move the content of pSrc into pDest
*/
static void whereOrMove(WhereOrSet *pDest, WhereOrSet *pSrc){
  pDest->n = pSrc->n;
  memcpy(pDest->a, pSrc->a, pDest->n*sizeof(pDest->a[0]));
}

/*
** Try to insert a new prerequisite/cost entry into the WhereOrSet pSet.
**
** The new entry might overwrite an existing entry, or it might be
** appended, or it might be discarded.  Do whatever is the right thing
** so that pSet keeps the N_OR_COST best entries seen so far.
*/
static int whereOrInsert(
  WhereOrSet *pSet,      /* The WhereOrSet to be updated */
  Bitmask prereq,        /* Prerequisites of the new entry */
  WhereCost rRun,        /* Run-cost of the new entry */
  WhereCost nOut         /* Number of outputs for the new entry */
){
  u16 i;
  WhereOrCost *p;
  for(i=pSet->n, p=pSet->a; i>0; i--, p++){
    if( rRun<=p->rRun && (prereq & p->prereq)==prereq ){
      goto whereOrInsert_done;
    }
    if( p->rRun<=rRun && (p->prereq & prereq)==p->prereq ){
      return 0;
    }
  }
  if( pSet->n<N_OR_COST ){
    p = &pSet->a[pSet->n++];
    p->nOut = nOut;
  }else{
    p = pSet->a;
    for(i=1; i<pSet->n; i++){
      if( p->rRun>pSet->a[i].rRun ) p = pSet->a + i;
    }
    if( p->rRun<=rRun ) return 0;
  }
whereOrInsert_done:
  p->prereq = prereq;
  p->rRun = rRun;
  if( p->nOut>nOut ) p->nOut = nOut;
  return 1;
}

/*
** Initialize a preallocated WhereClause structure.
*/
static void whereClauseInit(
  WhereClause *pWC,        /* The WhereClause to be initialized */
  WhereInfo *pWInfo        /* The WHERE processing context */
){
  pWC->pWInfo = pWInfo;
  pWC->pOuter = 0;
  pWC->nTerm = 0;
  pWC->nSlot = ArraySize(pWC->aStatic);
  pWC->a = pWC->aStatic;
}

/* Forward reference */
static void whereClauseClear(WhereClause*);

/*
** Deallocate all memory associated with a WhereOrInfo object.
*/
static void whereOrInfoDelete(sqlite4 *db, WhereOrInfo *p){
  whereClauseClear(&p->wc);
  sqlite4DbFree(db, p);
}

/*
** Deallocate all memory associated with a WhereAndInfo object.
*/
static void whereAndInfoDelete(sqlite4 *db, WhereAndInfo *p){
  whereClauseClear(&p->wc);
  sqlite4DbFree(db, p);
}

/*
** Deallocate a WhereClause structure.  The WhereClause structure
** itself is not freed.  This routine is the inverse of whereClauseInit().
*/
static void whereClauseClear(WhereClause *pWC){
  int i;
  WhereTerm *a;
  sqlite4 *db = pWC->pWInfo->pParse->db;
  for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
    if( a->wtFlags & TERM_DYNAMIC ){
      sqlite4ExprDelete(db, a->pExpr);
    }
    if( a->wtFlags & TERM_ORINFO ){
      whereOrInfoDelete(db, a->u.pOrInfo);
    }else if( a->wtFlags & TERM_ANDINFO ){
      whereAndInfoDelete(db, a->u.pAndInfo);
    }
  }
  if( pWC->a!=pWC->aStatic ){
    sqlite4DbFree(db, pWC->a);
  }
}


/*
** Skip over any TK_COLLATE and/or TK_AS operators at the root of
** an expression.
**
** NOTE: This function was added when the NGQP was imported from SQLite3.
** At present it is not actually possible for Expr.op to be set to 
** TK_COLLATE. But will be if the way Expr objects represent collation
** sequences is changed to match SQLite3.
*/
static Expr *sqlite4ExprSkipCollate(Expr *pExpr){
  assert( pExpr==0 || pExpr->op!=TK_COLLATE );

  while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){
    pExpr = pExpr->pLeft;
  }
  return pExpr;
}

/*
** A bit in a Bitmask
*/
#define MASKBIT(n)   (((Bitmask)1)<<(n))



/*
** Add a single new WhereTerm entry to the WhereClause object pWC.
** The new WhereTerm object is constructed from Expr p and with wtFlags.
** The index in pWC->a[] of the new WhereTerm is returned on success.
** 0 is returned if the new WhereTerm could not be added due to a memory
** allocation error.  The memory allocation failure will be recorded in
** the db->mallocFailed flag so that higher-level functions can detect it.
**
** This routine will increase the size of the pWC->a[] array as necessary.
**
** If the wtFlags argument includes TERM_DYNAMIC, then responsibility
** for freeing the expression p is assumed by the WhereClause object pWC.
** This is true even if this routine fails to allocate a new WhereTerm.
**
** WARNING:  This routine might reallocate the space used to store
** WhereTerms.  All pointers to WhereTerms should be invalidated after
** calling this routine.  Such pointers may be reinitialized by referencing
** the pWC->a[] array.
*/
static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
  WhereTerm *pTerm;
  int idx;
  testcase( wtFlags & TERM_VIRTUAL );  /* EV: R-00211-15100 */
  if( pWC->nTerm>=pWC->nSlot ){
    WhereTerm *pOld = pWC->a;
    sqlite4 *db = pWC->pWInfo->pParse->db;
    pWC->a = sqlite4DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
    if( pWC->a==0 ){
      if( wtFlags & TERM_DYNAMIC ){
        sqlite4ExprDelete(db, p);
      }
      pWC->a = pOld;
      return 0;
    }
    memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
    if( pOld!=pWC->aStatic ){
      sqlite4DbFree(db, pOld);
    }
    pWC->nSlot = sqlite4DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
  }
  pTerm = &pWC->a[idx = pWC->nTerm++];
  pTerm->pExpr = sqlite4ExprSkipCollate(p);
  pTerm->wtFlags = wtFlags;
  pTerm->pWC = pWC;
  pTerm->iParent = -1;
  return idx;
}

/*
** This routine identifies subexpressions in the WHERE clause where
** each subexpression is separated by the AND operator or some other
** operator specified in the op parameter.  The WhereClause structure
** is filled with pointers to subexpressions.  For example:
**
**    WHERE  a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22)
**           \________/     \_______________/     \________________/
**            slot[0]            slot[1]               slot[2]
**
** The original WHERE clause in pExpr is unaltered.  All this routine
** does is make slot[] entries point to substructure within pExpr.
**
** In the previous sentence and in the diagram, "slot[]" refers to
** the WhereClause.a[] array.  The slot[] array grows as needed to contain
** all terms of the WHERE clause.
*/
static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
  pWC->op = op;
  if( pExpr==0 ) return;
  if( pExpr->op!=op ){
    whereClauseInsert(pWC, pExpr, 0);
  }else{
    whereSplit(pWC, pExpr->pLeft, op);
    whereSplit(pWC, pExpr->pRight, op);
  }
}

/*
** Initialize a WhereMaskSet object
*/
#define initMaskSet(P)  (P)->n=0

/*
** Return the bitmask for the given cursor number.  Return 0 if
** iCursor is not in the set.
*/
static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){
  int i;
  assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
  for(i=0; i<pMaskSet->n; i++){
    if( pMaskSet->ix[i]==iCursor ){
      return MASKBIT(i);
    }
  }
  return 0;
}

/*
** Create a new mask for cursor iCursor.
**
** There is one cursor per table in the FROM clause.  The number of
** tables in the FROM clause is limited by a test early in the
** sqlite4WhereBegin() routine.  So we know that the pMaskSet->ix[]
** array will never overflow.
*/
static void createMask(WhereMaskSet *pMaskSet, int iCursor){
  assert( pMaskSet->n < ArraySize(pMaskSet->ix) );
  pMaskSet->ix[pMaskSet->n++] = iCursor;
}

/*
** These routine walk (recursively) an expression tree and generates
** a bitmask indicating which tables are used in that expression
** tree.
*/
static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*);
static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*);
static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){
  Bitmask mask = 0;
  if( p==0 ) return 0;
  if( p->op==TK_COLUMN ){
    mask = getMask(pMaskSet, p->iTable);
    return mask;
  }
  mask = exprTableUsage(pMaskSet, p->pRight);
  mask |= exprTableUsage(pMaskSet, p->pLeft);
  if( ExprHasProperty(p, EP_xIsSelect) ){
    mask |= exprSelectTableUsage(pMaskSet, p->x.pSelect);
  }else{
    mask |= exprListTableUsage(pMaskSet, p->x.pList);
  }
  return mask;
}
static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){
  int i;
  Bitmask mask = 0;
  if( pList ){
    for(i=0; i<pList->nExpr; i++){
      mask |= exprTableUsage(pMaskSet, pList->a[i].pExpr);
    }
  }
  return mask;
}
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;
}

/*
** Return TRUE if the given operator is one of the operators that is
** allowed for an indexable WHERE clause term.  The allowed operators are
** "=", "<", ">", "<=", ">=", "IN", and "IS NULL"
**
** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be
** of one of the following forms: column = expression column > expression
** column >= expression column < expression column <= expression
** expression = column expression > column expression >= column
** expression < column expression <= column column IN
** (expression-list) column IN (subquery) column IS NULL
*/
static int allowedOp(int op){
  assert( TK_GT>TK_EQ && TK_GT<TK_GE );
  assert( TK_LT>TK_EQ && TK_LT<TK_GE );
  assert( TK_LE>TK_EQ && TK_LE<TK_GE );
  assert( TK_GE==TK_EQ+4 );
  return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL;
}

/*
** Swap two objects of type TYPE.
*/
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}

/*
** Commute a comparison operator.  Expressions of the form "X op Y"
** are converted into "Y op X".
**
** If left/right precedence rules come into play when determining the
** collating sequence, then COLLATE operators are adjusted to ensure
** that the collating sequence does not change.  For example:
** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
** the left hand side of a comparison overrides any collation sequence 
** attached to the right. For the same reason the EP_ExpCollate flag
** is not commuted.
*/
static void exprCommute(Parse *pParse, Expr *pExpr){
  u16 expRight = (pExpr->pRight->flags & EP_ExpCollate);
  u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate);
  assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
  if( expRight==expLeft ){
    /* Either X and Y both have COLLATE operator or neither do */
    if( expRight ){
      /* Both X and Y have COLLATE operators.  Make sure X is always
      ** used by clearing the EP_ExpCollate flag from Y. */
      pExpr->pRight->flags &= ~EP_ExpCollate;
    }else if( sqlite4ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
      /* Neither X nor Y have COLLATE operators, but X has a non-default
      ** collating sequence.  So add the EP_ExpCollate marker on X to cause
      ** it to be searched first. */
      pExpr->pLeft->flags |= EP_ExpCollate;
    }
  }
  SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
  if( pExpr->op>=TK_GT ){
    assert( TK_LT==TK_GT+2 );
    assert( TK_GE==TK_LE+2 );
    assert( TK_GT>TK_EQ );
    assert( TK_GT<TK_LE );
    assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
    pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
  }
}

/*
** Translate from TK_xx operator to WO_xx bitmask.
*/
static u16 operatorMask(int op){
  u16 c;
  assert( allowedOp(op) );
  if( op==TK_IN ){
    c = WO_IN;
  }else if( op==TK_ISNULL ){
    c = WO_ISNULL;
  }else{
    assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
    c = (u16)(WO_EQ<<(op-TK_EQ));
  }
  assert( op!=TK_ISNULL || c==WO_ISNULL );
  assert( op!=TK_IN || c==WO_IN );
  assert( op!=TK_EQ || c==WO_EQ );
  assert( op!=TK_LT || c==WO_LT );
  assert( op!=TK_LE || c==WO_LE );
  assert( op!=TK_GT || c==WO_GT );
  assert( op!=TK_GE || c==WO_GE );
  return c;
}

/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
*/
static WhereTerm *whereScanNext(WhereScan *pScan){
  int iCur;            /* The cursor on the LHS of the term */
  int iColumn;         /* The column on the LHS of the term.  -1 for IPK */
  Expr *pX;            /* An expression being tested */
  WhereClause *pWC;    /* Shorthand for pScan->pWC */
  WhereTerm *pTerm;    /* The term being tested */
  int k = pScan->k;    /* Where to start scanning */

  while( pScan->iEquiv<=pScan->nEquiv ){
    iCur = pScan->aEquiv[pScan->iEquiv-2];
    iColumn = pScan->aEquiv[pScan->iEquiv-1];
    while( (pWC = pScan->pWC)!=0 ){
      for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
        if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn ){
          if( (pTerm->eOperator & WO_EQUIV)!=0
           && pScan->nEquiv<ArraySize(pScan->aEquiv)
          ){
            int j;
            pX = sqlite4ExprSkipCollate(pTerm->pExpr->pRight);
            assert( pX->op==TK_COLUMN );
            for(j=0; j<pScan->nEquiv; j+=2){
              if( pScan->aEquiv[j]==pX->iTable
               && pScan->aEquiv[j+1]==pX->iColumn ){
                  break;
              }
            }
            if( j==pScan->nEquiv ){
              pScan->aEquiv[j] = pX->iTable;
              pScan->aEquiv[j+1] = pX->iColumn;
              pScan->nEquiv += 2;
            }
          }
          if( (pTerm->eOperator & pScan->opMask)!=0 ){
            /* Verify the affinity and collating sequence match */
            if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
              CollSeq *pColl;
              Parse *pParse = pWC->pWInfo->pParse;
              pX = pTerm->pExpr;
              if( !sqlite4IndexAffinityOk(pX, pScan->idxaff) ){
                continue;
              }
              assert(pX->pLeft);
              pColl = sqlite4BinaryCompareCollSeq(pParse,
                                                  pX->pLeft, pX->pRight);
              if( pColl==0 ) pColl = pParse->db->pDfltColl;
              if( sqlite4_stricmp(pColl->zName, pScan->zCollName) ){
                continue;
              }
            }
            if( (pTerm->eOperator & WO_EQ)!=0
             && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
             && pX->iTable==pScan->aEquiv[0]
             && pX->iColumn==pScan->aEquiv[1]
            ){
              continue;
            }
            pScan->k = k+1;
            return pTerm;
          }
        }
      }
      pScan->pWC = pScan->pWC->pOuter;
      k = 0;
    }
    pScan->pWC = pScan->pOrigWC;
    k = 0;
    pScan->iEquiv += 2;
  }
  return 0;
}

/*
** Return the table column number of the iIdxCol'th field in the index
** keys used by index pIdx, including any appended PRIMARY KEY fields.
** If there is no iIdxCol'th field in index pIdx, return -2.
**
** Example:
**
**   CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b));
**   CREATE INDEX i1 ON t1(c);
**
** Index i1 in the example above consists of three fields - the indexed
** field "c" followed by the two primary key fields. The automatic PRIMARY
** KEY index consists of two fields only.
*/
static int idxColumnNumber(Index *pIdx, Index *pPk, int iIdxCol){
  int iRet = -2;
  if( iIdxCol<pIdx->nColumn ){
    iRet = pIdx->aiColumn[iIdxCol];
  }else if( pPk && iIdxCol<(pIdx->nColumn + pPk->nColumn) ){
    iRet = pPk->aiColumn[iIdxCol - pIdx->nColumn];
  }
  return iRet;
}

/*
** Return a pointer to a buffer containing the name of the collation 
** sequence used with the iIdxCol'th field in index pIdx, including any
** appended PRIMARY KEY fields.
*/
static char *idxColumnCollation(Index *pIdx, Index *pPk, int iIdxCol){
  char *zColl;
  assert( iIdxCol<(pIdx->nColumn + pPk->nColumn) );
  if( iIdxCol<pIdx->nColumn ){
    zColl = pIdx->azColl[iIdxCol];
  }else if( pPk && iIdxCol<(pIdx->nColumn + pPk->nColumn) ){
    zColl = pPk->azColl[iIdxCol - pIdx->nColumn];
  }
  return zColl;
}

/*
** Return the sort order (SQLITE4_SO_ASC or DESC) used by the iIdxCol'th 
** field in index pIdx, including any appended PRIMARY KEY fields.
*/
static int idxColumnSortOrder(Index *pIdx, Index *pPk, int iIdxCol){
  int iRet = SQLITE4_SO_ASC;
  if( iIdxCol<pIdx->nColumn ){
    iRet = pIdx->aSortOrder[iIdxCol];
  }
  return iRet;
}

/*
** Return the total number of fields in the index pIdx, including any
** trailing primary key fields.
*/
static int idxColumnCount(Index *pIdx, Index *pPk){
  return (pIdx->nColumn + ((pPk==0 || pIdx==pPk) ? 0 : pPk->nColumn));
}

/*
** Initialize a WHERE clause scanner object.  Return a pointer to the
** first match.  Return NULL if there are no matches.
**
** The scanner will be searching the WHERE clause pWC.  It will look
** for terms of the form "X <op> <expr>" where X is column iColumn of table
** iCur.  The <op> must be one of the operators described by opMask.
**
** If the search is for X and the WHERE clause contains terms of the
** form X=Y then this routine might also return terms of the form
** "Y <op> <expr>".  The number of levels of transitivity is limited,
** but is enough to handle most commonly occurring SQL statements.
**
** If X is not the INTEGER PRIMARY KEY then X must be compatible with
** index pIdx.
*/
static WhereTerm *whereScanInit(
  WhereScan *pScan,       /* The WhereScan object being initialized */
  WhereClause *pWC,       /* The WHERE clause to be scanned */
  int iCur,               /* Cursor to scan for */
  int iColumn,            /* Column to scan for */
  u32 opMask,             /* Operator(s) to scan for */
  Index *pIdx             /* Must be compatible with this index */
){
  int j;

  /* memset(pScan, 0, sizeof(*pScan)); */
  pScan->pOrigWC = pWC;
  pScan->pWC = pWC;
  if( pIdx && iColumn>=0 ){
    Index *pPk = sqlite4FindPrimaryKey(pIdx->pTable, 0);
    pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
    for(j=0; idxColumnNumber(pIdx, pPk, j)!=iColumn; j++){
      if( NEVER(j>=idxColumnCount(pIdx, pPk)) ) return 0;
    }
    pScan->zCollName = idxColumnCollation(pIdx, pPk, j);
  }else{
    pScan->idxaff = 0;
    pScan->zCollName = 0;
  }
  pScan->opMask = opMask;
  pScan->k = 0;
  pScan->aEquiv[0] = iCur;
  pScan->aEquiv[1] = iColumn;
  pScan->nEquiv = 2;
  pScan->iEquiv = 2;
  return whereScanNext(pScan);
}

/*
** Search for a term in the WHERE clause that is of the form "X <op> <expr>"
** where X is a reference to the iColumn of table iCur and <op> is one of
** the WO_xx operator codes specified by the op parameter.
** Return a pointer to the term.  Return 0 if not found.
**
** The term returned might by Y=<expr> if there is another constraint in
** the WHERE clause that specifies that X=Y.  Any such constraints will be
** identified by the WO_EQUIV bit in the pTerm->eOperator field.  The
** aEquiv[] array holds X and all its equivalents, with each SQL variable
** taking up two slots in aEquiv[].  The first slot is for the cursor number
** and the second is for the column number.  There are 22 slots in aEquiv[]
** so that means we can look for X plus up to 10 other equivalent values.
** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
** and ... and A9=A10 and A10=<expr>.
**
** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
** then try for the one with no dependencies on <expr> - in other words where
** <expr> is a constant expression of some kind.  Only return entries of
** the form "X <op> Y" where Y is a column in another table if no terms of
** the form "X <op> <const-expr>" exist.   If no terms with a constant RHS
** exist, try to return a term that does not use WO_EQUIV.
*/
static WhereTerm *findTerm(
  WhereClause *pWC,     /* The WHERE clause to be searched */
  int iCur,             /* Cursor number of LHS */
  int iColumn,          /* Column number of LHS */
  Bitmask notReady,     /* RHS must not overlap with this mask */
  u32 op,               /* Mask of WO_xx values describing operator */
  Index *pIdx           /* Must be compatible with this index, if not NULL */
){
  WhereTerm *pResult = 0;
  WhereTerm *p;
  WhereScan scan;

  p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx);
  while( p ){
    if( (p->prereqRight & notReady)==0 ){
      if( p->prereqRight==0 && (p->eOperator&WO_EQ)!=0 ){
        return p;
      }
      if( pResult==0 ) pResult = p;
    }
    p = whereScanNext(&scan);
  }
  return pResult;
}

/* Forward reference */
static void exprAnalyze(SrcList*, WhereClause*, int);

/*
** Call exprAnalyze on all terms in a WHERE clause.  
*/
static void exprAnalyzeAll(
  SrcList *pTabList,       /* the FROM clause */
  WhereClause *pWC         /* the WHERE clause to be analyzed */
){
  int i;
  for(i=pWC->nTerm-1; i>=0; i--){
    exprAnalyze(pTabList, pWC, i);
  }
}

#ifndef SQLITE4_OMIT_LIKE_OPTIMIZATION
/*
** Check to see if the given expression is a LIKE or GLOB operator that
** can be optimized using inequality constraints.  Return TRUE if it is
** so and false if not.
**
** In order for the operator to be optimizible, the RHS must be a string
** literal that does not begin with a wildcard.  
*/
static int isLikeOrGlob(
  Parse *pParse,    /* Parsing and code generating context */
  Expr *pExpr,      /* Test this expression */
  Expr **ppPrefix,  /* Pointer to TK_STRING expression with pattern prefix */
  int *pisComplete, /* True if the only wildcard is % in the last character */
  int *pnoCase      /* True if uppercase is equivalent to lowercase */
){
  const char *z = 0;         /* String on RHS of LIKE operator */
  Expr *pRight, *pLeft;      /* Right and left size of LIKE operator */
  ExprList *pList;           /* List of operands to the LIKE operator */
  int c;                     /* One character in z[] */
  int cnt;                   /* Number of non-wildcard prefix characters */
  char wc[3];                /* Wildcard characters */
  sqlite4 *db = pParse->db;  /* Database connection */
  sqlite4_value *pVal = 0;
  int op;                    /* Opcode of pRight */

  if( !sqlite4IsLikeFunction(db, pExpr, pnoCase, wc) ){
    return 0;
  }
#ifdef SQLITE4_EBCDIC
  if( *pnoCase ) return 0;
#endif
  pList = pExpr->x.pList;
  pLeft = pList->a[1].pExpr;
  if( pLeft->op!=TK_COLUMN 
   || sqlite4ExprAffinity(pLeft)!=SQLITE4_AFF_TEXT 
   || IsVirtual(pLeft->pTab)
  ){
    /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
    ** be the name of an indexed column with TEXT affinity. */
    return 0;
  }
  assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */

  pRight = pList->a[0].pExpr;
  op = pRight->op;
  if( op==TK_REGISTER ){
    op = pRight->op2;
  }
  if( op==TK_VARIABLE ){
    Vdbe *pReprepare = pParse->pReprepare;
    int iCol = pRight->iColumn;
    pVal = sqlite4VdbeGetValue(pReprepare, iCol, SQLITE4_AFF_NONE);
    if( pVal && sqlite4_value_type(pVal)==SQLITE4_TEXT ){
      z = (char *)sqlite4_value_text(pVal, 0);
    }
    sqlite4VdbeSetVarmask(pParse->pVdbe, iCol);
    assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
  }else if( op==TK_STRING ){
    z = pRight->u.zToken;
  }
  if( z ){
    cnt = 0;
    while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
      cnt++;
    }
    if( cnt!=0 && 255!=(u8)z[cnt-1] ){
      Expr *pPrefix;
      *pisComplete = c==wc[0] && z[cnt+1]==0;
      pPrefix = sqlite4Expr(db, TK_STRING, z);
      if( pPrefix ) pPrefix->u.zToken[cnt] = 0;
      *ppPrefix = pPrefix;
      if( op==TK_VARIABLE ){
        Vdbe *v = pParse->pVdbe;
        sqlite4VdbeSetVarmask(v, pRight->iColumn);
        if( *pisComplete && pRight->u.zToken[1] ){
          /* If the rhs of the LIKE expression is a variable, and the current
          ** value of the variable means there is no need to invoke the LIKE
          ** function, then no OP_Variable will be added to the program.
          ** This causes problems for the sqlite4_bind_parameter_name()
          ** API. To workaround them, add a dummy OP_Variable here.
          */ 
          int r1 = sqlite4GetTempReg(pParse);
          sqlite4ExprCodeTarget(pParse, pRight, r1);
          sqlite4VdbeChangeP3(v, sqlite4VdbeCurrentAddr(v)-1, 0);
          sqlite4ReleaseTempReg(pParse, r1);
        }
      }
    }else{
      z = 0;
    }
  }

  sqlite4ValueFree(pVal);
  return (z!=0);
}
#endif /* SQLITE4_OMIT_LIKE_OPTIMIZATION */


#ifndef SQLITE4_OMIT_VIRTUALTABLE
/*
** Check to see if the given expression is of the form
**
**         column MATCH expr
**
** If it is then return TRUE.  If not, return FALSE.
*/
static int isMatchOfColumn(
  Expr *pExpr      /* Test this expression */
){
  ExprList *pList;

  if( pExpr->op!=TK_FUNCTION ){
    return 0;
  }
  if( sqlite4_stricmp(pExpr->u.zToken,"match")!=0 ){
    return 0;
  }
  pList = pExpr->x.pList;
  if( pList->nExpr!=2 ){
    return 0;
  }
  if( pList->a[1].pExpr->op != TK_COLUMN ){
    return 0;
  }
  return 1;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

/*
** If the pBase expression originated in the ON or USING clause of
** a join, then transfer the appropriate markings over to derived.
*/
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
  pDerived->flags |= pBase->flags & EP_FromJoin;
  pDerived->iRightJoinTable = pBase->iRightJoinTable;
}

#if !defined(SQLITE4_OMIT_OR_OPTIMIZATION) && !defined(SQLITE4_OMIT_SUBQUERY)
/*
** Analyze a term that consists of two or more OR-connected
** subterms.  So in:
**
**     ... WHERE  (a=5) AND (b=7 OR c=9 OR d=13) AND (d=13)
**                          ^^^^^^^^^^^^^^^^^^^^
**
** This routine analyzes terms such as the middle term in the above example.
** A WhereOrTerm object is computed and attached to the term under
** analysis, regardless of the outcome of the analysis.  Hence:
**
**     WhereTerm.wtFlags   |=  TERM_ORINFO
**     WhereTerm.u.pOrInfo  =  a dynamically allocated WhereOrTerm object
**
** The term being analyzed must have two or more of OR-connected subterms.
** A single subterm might be a set of AND-connected sub-subterms.
** Examples of terms under analysis:
**
**     (A)     t1.x=t2.y OR t1.x=t2.z OR t1.y=15 OR t1.z=t3.a+5
**     (B)     x=expr1 OR expr2=x OR x=expr3
**     (C)     t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
**     (D)     x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
**     (E)     (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
**
** CASE 1:
**
** If all subterms are of the form T.C=expr for some single column of C and
** a single table T (as shown in example B above) then create a new virtual
** term that is an equivalent IN expression.  In other words, if the term
** being analyzed is:
**
**      x = expr1  OR  expr2 = x  OR  x = expr3
**
** then create a new virtual term like this:
**
**      x IN (expr1,expr2,expr3)
**
** CASE 2:
**
** If all subterms are indexable by a single table T, then set
**
**     WhereTerm.eOperator              =  WO_OR
**     WhereTerm.u.pOrInfo->indexable  |=  the cursor number for table T
**
** A subterm is "indexable" if it is of the form
** "T.C <op> <expr>" where C is any column of table T and 
** <op> is one of "=", "<", "<=", ">", ">=", "IS NULL", or "IN".
** A subterm is also indexable if it is an AND of two or more
** subsubterms at least one of which is indexable.  Indexable AND 
** subterms have their eOperator set to WO_AND and they have
** u.pAndInfo set to a dynamically allocated WhereAndTerm object.
**
** From another point of view, "indexable" means that the subterm could
** potentially be used with an index if an appropriate index exists.
** This analysis does not consider whether or not the index exists; that
** is something the bestIndex() routine will determine.  This analysis
** only looks at whether subterms appropriate for indexing exist.
**
** All examples A through E above all satisfy case 2.  But if a term
** also statisfies case 1 (such as B) we know that the optimizer will
** always prefer case 1, so in that case we pretend that case 2 is not
** satisfied.
**
** It might be the case that multiple tables are indexable.  For example,
** (E) above is indexable on tables P, Q, and R.
**
** Terms that satisfy case 2 are candidates for lookup by using
** separate indices to find rowids for each subterm and composing
** the union of all rowids using a RowSet object.  This is similar
** to "bitmap indices" in other database engines.
**
** OTHERWISE:
**
** If neither case 1 nor case 2 apply, then leave the eOperator set to
** zero.  This term is not useful for search.
*/
static void exprAnalyzeOrTerm(
  SrcList *pSrc,            /* the FROM clause */
  WhereClause *pWC,         /* the complete WHERE clause */
  int idxTerm               /* Index of the OR-term to be analyzed */
){
  WhereInfo *pWInfo = pWC->pWInfo;        /* WHERE clause processing context */
  Parse *pParse = pWInfo->pParse;         /* Parser context */
  sqlite4 *db = pParse->db;               /* Database connection */
  WhereTerm *pTerm = &pWC->a[idxTerm];    /* The term to be analyzed */
  Expr *pExpr = pTerm->pExpr;             /* The expression of the term */
  int i;                                  /* Loop counters */
  WhereClause *pOrWc;       /* Breakup of pTerm into subterms */
  WhereTerm *pOrTerm;       /* A Sub-term within the pOrWc */
  WhereOrInfo *pOrInfo;     /* Additional information associated with pTerm */
  Bitmask chngToIN;         /* Tables that might satisfy case 1 */
  Bitmask indexable;        /* Tables that are indexable, satisfying case 2 */

  /*
  ** Break the OR clause into its separate subterms.  The subterms are
  ** stored in a WhereClause structure containing within the WhereOrInfo
  ** object that is attached to the original OR clause term.
  */
  assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 );
  assert( pExpr->op==TK_OR );
  pTerm->u.pOrInfo = pOrInfo = sqlite4DbMallocZero(db, sizeof(*pOrInfo));
  if( pOrInfo==0 ) return;
  pTerm->wtFlags |= TERM_ORINFO;
  pOrWc = &pOrInfo->wc;
  whereClauseInit(pOrWc, pWInfo);
  whereSplit(pOrWc, pExpr, TK_OR);
  exprAnalyzeAll(pSrc, pOrWc);
  if( db->mallocFailed ) return;
  assert( pOrWc->nTerm>=2 );

  /*
  ** Compute the set of tables that might satisfy cases 1 or 2.
  */
  indexable = ~(Bitmask)0;
  chngToIN = ~(Bitmask)0;
  for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
    if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
      WhereAndInfo *pAndInfo;
      assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
      chngToIN = 0;
      pAndInfo = sqlite4DbMallocRaw(db, sizeof(*pAndInfo));
      if( pAndInfo ){
        WhereClause *pAndWC;
        WhereTerm *pAndTerm;
        int j;
        Bitmask b = 0;
        pOrTerm->u.pAndInfo = pAndInfo;
        pOrTerm->wtFlags |= TERM_ANDINFO;
        pOrTerm->eOperator = WO_AND;
        pAndWC = &pAndInfo->wc;
        whereClauseInit(pAndWC, pWC->pWInfo);
        whereSplit(pAndWC, pOrTerm->pExpr, TK_AND);
        exprAnalyzeAll(pSrc, pAndWC);
        pAndWC->pOuter = pWC;
        testcase( db->mallocFailed );
        if( !db->mallocFailed ){
          for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){
            assert( pAndTerm->pExpr );
            if( allowedOp(pAndTerm->pExpr->op) ){
              b |= getMask(&pWInfo->sMaskSet, pAndTerm->leftCursor);
            }
          }
        }
        indexable &= b;
      }
    }else if( pOrTerm->wtFlags & TERM_COPIED ){
      /* Skip this term for now.  We revisit it when we process the
      ** corresponding TERM_VIRTUAL term */
    }else{
      Bitmask b;
      b = getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor);
      if( pOrTerm->wtFlags & TERM_VIRTUAL ){
        WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent];
        b |= getMask(&pWInfo->sMaskSet, pOther->leftCursor);
      }
      indexable &= b;
      if( (pOrTerm->eOperator & WO_EQ)==0 ){
        chngToIN = 0;
      }else{
        chngToIN &= b;
      }
    }
  }

  /*
  ** Record the set of tables that satisfy case 2.  The set might be
  ** empty.
  */
  pOrInfo->indexable = indexable;
  pTerm->eOperator = indexable==0 ? 0 : WO_OR;

  /*
  ** chngToIN holds a set of tables that *might* satisfy case 1.  But
  ** we have to do some additional checking to see if case 1 really
  ** is satisfied.
  **
  ** chngToIN will hold either 0, 1, or 2 bits.  The 0-bit case means
  ** that there is no possibility of transforming the OR clause into an
  ** IN operator because one or more terms in the OR clause contain
  ** something other than == on a column in the single table.  The 1-bit
  ** case means that every term of the OR clause is of the form
  ** "table.column=expr" for some single table.  The one bit that is set
  ** will correspond to the common table.  We still need to check to make
  ** sure the same column is used on all terms.  The 2-bit case is when
  ** the all terms are of the form "table1.column=table2.column".  It
  ** might be possible to form an IN operator with either table1.column
  ** or table2.column as the LHS if either is common to every term of
  ** the OR clause.
  **
  ** Note that terms of the form "table.column1=table.column2" (the
  ** same table on both sizes of the ==) cannot be optimized.
  */
  if( chngToIN ){
    int okToChngToIN = 0;     /* True if the conversion to IN is valid */
    int iColumn = -1;         /* Column index on lhs of IN operator */
    int iCursor = -1;         /* Table cursor common to all terms */
    int j = 0;                /* Loop counter */

    /* Search for a table and column that appears on one side or the
    ** other of the == operator in every subterm.  That table and column
    ** will be recorded in iCursor and iColumn.  There might not be any
    ** such table and column.  Set okToChngToIN if an appropriate table
    ** and column is found but leave okToChngToIN false if not found.
    */
    for(j=0; j<2 && !okToChngToIN; j++){
      pOrTerm = pOrWc->a;
      for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
        assert( pOrTerm->eOperator & WO_EQ );
        pOrTerm->wtFlags &= ~TERM_OR_OK;
        if( pOrTerm->leftCursor==iCursor ){
          /* This is the 2-bit case and we are on the second iteration and
          ** current term is from the first iteration.  So skip this term. */
          assert( j==1 );
          continue;
        }
        if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){
          /* This term must be of the form t1.a==t2.b where t2 is in the
          ** chngToIN set but t1 is not.  This term will be either preceeded
          ** or follwed by an inverted copy (t2.b==t1.a).  Skip this term 
          ** and use its inversion. */
          testcase( pOrTerm->wtFlags & TERM_COPIED );
          testcase( pOrTerm->wtFlags & TERM_VIRTUAL );
          assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
          continue;
        }
        iColumn = pOrTerm->u.leftColumn;
        iCursor = pOrTerm->leftCursor;
        break;
      }
      if( i<0 ){
        /* No candidate table+column was found.  This can only occur
        ** on the second iteration */
        assert( j==1 );
        assert( IsPowerOfTwo(chngToIN) );
        assert( chngToIN==getMask(&pWInfo->sMaskSet, iCursor) );
        break;
      }
      testcase( j==1 );

      /* We have found a candidate table and column.  Check to see if that
      ** table and column is common to every term in the OR clause */
      okToChngToIN = 1;
      for(; i>=0 && okToChngToIN; i--, pOrTerm++){
        assert( pOrTerm->eOperator & WO_EQ );
        if( pOrTerm->leftCursor!=iCursor ){
          pOrTerm->wtFlags &= ~TERM_OR_OK;
        }else if( pOrTerm->u.leftColumn!=iColumn ){
          okToChngToIN = 0;
        }else{
          int affLeft, affRight;
          /* If the right-hand side is also a column, then the affinities
          ** of both right and left sides must be such that no type
          ** conversions are required on the right.  (Ticket #2249)
          */
          affRight = sqlite4ExprAffinity(pOrTerm->pExpr->pRight);
          affLeft = sqlite4ExprAffinity(pOrTerm->pExpr->pLeft);
          if( affRight!=0 && affRight!=affLeft ){
            okToChngToIN = 0;
          }else{
            pOrTerm->wtFlags |= TERM_OR_OK;
          }
        }
      }
    }

    /* At this point, okToChngToIN is true if original pTerm satisfies
    ** case 1.  In that case, construct a new virtual term that is 
    ** pTerm converted into an IN operator.
    **
    ** EV: R-00211-15100
    */
    if( okToChngToIN ){
      Expr *pDup;            /* A transient duplicate expression */
      ExprList *pList = 0;   /* The RHS of the IN operator */
      Expr *pLeft = 0;       /* The LHS of the IN operator */
      Expr *pNew;            /* The complete IN operator */

      for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
        if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
        assert( pOrTerm->eOperator & WO_EQ );
        assert( pOrTerm->leftCursor==iCursor );
        assert( pOrTerm->u.leftColumn==iColumn );
        pDup = sqlite4ExprDup(db, pOrTerm->pExpr->pRight, 0);
        pList = sqlite4ExprListAppend(pWInfo->pParse, pList, pDup);
        pLeft = pOrTerm->pExpr->pLeft;
      }
      assert( pLeft!=0 );
      pDup = sqlite4ExprDup(db, pLeft, 0);
      pNew = sqlite4PExpr(pParse, TK_IN, pDup, 0, 0);
      if( pNew ){
        int idxNew;
        transferJoinMarkings(pNew, pExpr);
        assert( !ExprHasProperty(pNew, EP_xIsSelect) );
        pNew->x.pList = pList;
        idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
        testcase( idxNew==0 );
        exprAnalyze(pSrc, pWC, idxNew);
        pTerm = &pWC->a[idxTerm];
        pWC->a[idxNew].iParent = idxTerm;
        pTerm->nChild = 1;
      }else{
        sqlite4ExprListDelete(db, pList);
      }
      pTerm->eOperator = WO_NOOP;  /* case 1 trumps case 2 */
    }
  }
}
#endif /* !SQLITE4_OMIT_OR_OPTIMIZATION && !SQLITE4_OMIT_SUBQUERY */

/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in.  The job of this routine is to analyze the
** subexpression and populate all the other fields of the WhereTerm
** structure.
**
** If the expression is of the form "<expr> <op> X" it gets commuted
** to the standard form of "X <op> <expr>".
**
** If the expression is of the form "X <op> Y" where both X and Y are
** columns, then the original expression is unchanged and a new virtual
** term of the form "Y <op> X" is added to the WHERE clause and
** analyzed separately.  The original term is marked with TERM_COPIED
** and the new term is marked with TERM_DYNAMIC (because it's pExpr
** needs to be freed with the WhereClause) and TERM_VIRTUAL (because it
** is a commuted copy of a prior term.)  The original term has nChild=1
** and the copy has idxParent set to the index of the original term.
*/
static void exprAnalyze(
  SrcList *pSrc,            /* the FROM clause */
  WhereClause *pWC,         /* the WHERE clause */
  int idxTerm               /* Index of the term to be analyzed */
){
  WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */
  WhereTerm *pTerm;                /* The term to be analyzed */
  WhereMaskSet *pMaskSet;          /* Set of table index masks */
  Expr *pExpr;                     /* The expression to be analyzed */
  Bitmask prereqLeft;              /* Prerequesites of the pExpr->pLeft */
  Bitmask prereqAll;               /* Prerequesites of pExpr */
  Bitmask extraRight = 0;          /* Extra dependencies on LEFT JOIN */
  Expr *pStr1 = 0;                 /* RHS of LIKE/GLOB operator */
  int isComplete = 0;              /* RHS of LIKE/GLOB ends with wildcard */
  int noCase = 0;                  /* LIKE/GLOB distinguishes case */
  int op;                          /* Top-level operator.  pExpr->op */
  Parse *pParse = pWInfo->pParse;  /* Parsing context */
  sqlite4 *db = pParse->db;        /* Database connection */

  if( db->mallocFailed ){
    return;
  }
  pTerm = &pWC->a[idxTerm];
  pMaskSet = &pWInfo->sMaskSet;
  pExpr = pTerm->pExpr;
  assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
  prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft);
  op = pExpr->op;
  if( op==TK_IN ){
    assert( pExpr->pRight==0 );
    if( ExprHasProperty(pExpr, EP_xIsSelect) ){
      pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect);
    }else{
      pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->x.pList);
    }
  }else if( op==TK_ISNULL ){
    pTerm->prereqRight = 0;
  }else{
    pTerm->prereqRight = exprTableUsage(pMaskSet, pExpr->pRight);
  }
  prereqAll = exprTableUsage(pMaskSet, pExpr);
  if( ExprHasProperty(pExpr, EP_FromJoin) ){
    Bitmask x = getMask(pMaskSet, pExpr->iRightJoinTable);
    prereqAll |= x;
    extraRight = x-1;  /* ON clause terms may not be used with an index
                       ** on left table of a LEFT JOIN.  Ticket #3015 */
  }
  pTerm->prereqAll = prereqAll;
  pTerm->leftCursor = -1;
  pTerm->iParent = -1;
  pTerm->eOperator = 0;
  if( allowedOp(op) ){
    Expr *pLeft = sqlite4ExprSkipCollate(pExpr->pLeft);
    Expr *pRight = sqlite4ExprSkipCollate(pExpr->pRight);
    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
    if( pLeft->op==TK_COLUMN ){
      pTerm->leftCursor = pLeft->iTable;
      pTerm->u.leftColumn = pLeft->iColumn;
      pTerm->eOperator = operatorMask(op) & opMask;
    }
    if( pRight && pRight->op==TK_COLUMN ){
      WhereTerm *pNew;
      Expr *pDup;
      u16 eExtraOp = 0;        /* Extra bits for pNew->eOperator */
      if( pTerm->leftCursor>=0 ){
        int idxNew;
        pDup = sqlite4ExprDup(db, pExpr, 0);
        if( db->mallocFailed ){
          sqlite4ExprDelete(db, pDup);
          return;
        }
        idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC);
        if( idxNew==0 ) return;
        pNew = &pWC->a[idxNew];
        pNew->iParent = idxTerm;
        pTerm = &pWC->a[idxTerm];
        pTerm->nChild = 1;
        pTerm->wtFlags |= TERM_COPIED;
        if( pExpr->op==TK_EQ
         && !ExprHasProperty(pExpr, EP_FromJoin)
         && OptimizationEnabled(db, SQLITE4_Transitive)
        ){
          pTerm->eOperator |= WO_EQUIV;
          eExtraOp = WO_EQUIV;
        }
      }else{
        pDup = pExpr;
        pNew = pTerm;
      }
      exprCommute(pParse, pDup);
      pLeft = sqlite4ExprSkipCollate(pDup->pLeft);
      pNew->leftCursor = pLeft->iTable;
      pNew->u.leftColumn = pLeft->iColumn;
      testcase( (prereqLeft | extraRight) != prereqLeft );
      pNew->prereqRight = prereqLeft | extraRight;
      pNew->prereqAll = prereqAll;
      pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
    }
  }

#ifndef SQLITE4_OMIT_BETWEEN_OPTIMIZATION
  /* If a term is the BETWEEN operator, create two new virtual terms
  ** that define the range that the BETWEEN implements.  For example:
  **
  **      a BETWEEN b AND c
  **
  ** is converted into:
  **
  **      (a BETWEEN b AND c) AND (a>=b) AND (a<=c)
  **
  ** The two new terms are added onto the end of the WhereClause object.
  ** The new terms are "dynamic" and are children of the original BETWEEN
  ** term.  That means that if the BETWEEN term is coded, the children are
  ** skipped.  Or, if the children are satisfied by an index, the original
  ** BETWEEN term is skipped.
  */
  else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
    ExprList *pList = pExpr->x.pList;
    int i;
    static const u8 ops[] = {TK_GE, TK_LE};
    assert( pList!=0 );
    assert( pList->nExpr==2 );
    for(i=0; i<2; i++){
      Expr *pNewExpr;
      int idxNew;
      pNewExpr = sqlite4PExpr(pParse, ops[i], 
                             sqlite4ExprDup(db, pExpr->pLeft, 0),
                             sqlite4ExprDup(db, pList->a[i].pExpr, 0), 0);
      idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
      testcase( idxNew==0 );
      exprAnalyze(pSrc, pWC, idxNew);
      pTerm = &pWC->a[idxTerm];
      pWC->a[idxNew].iParent = idxTerm;
    }
    pTerm->nChild = 2;
  }
#endif /* SQLITE4_OMIT_BETWEEN_OPTIMIZATION */

#if !defined(SQLITE4_OMIT_OR_OPTIMIZATION) && !defined(SQLITE4_OMIT_SUBQUERY)
  /* Analyze a term that is composed of two or more subterms connected by
  ** an OR operator.
  */
  else if( pExpr->op==TK_OR ){
    assert( pWC->op==TK_AND );
    exprAnalyzeOrTerm(pSrc, pWC, idxTerm);
    pTerm = &pWC->a[idxTerm];
  }
#endif /* SQLITE4_OMIT_OR_OPTIMIZATION */

#ifndef SQLITE4_OMIT_LIKE_OPTIMIZATION
  /* Add constraints to reduce the search space on a LIKE or GLOB
  ** operator.
  **
  ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
  **
  **          x>='abc' AND x<'abd' AND x LIKE 'abc%'
  **
  ** The last character of the prefix "abc" is incremented to form the
  ** termination condition "abd".
  */
  if( pWC->op==TK_AND 
   && isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
  ){
    Expr *pLeft;       /* LHS of LIKE/GLOB operator */
    Expr *pStr2;       /* Copy of pStr1 - RHS of LIKE/GLOB operator */
    Expr *pNewExpr1;
    Expr *pNewExpr2;
    int idxNew1;
    int idxNew2;
    Token sCollSeqName;  /* Name of collating sequence */

    pLeft = pExpr->x.pList->a[1].pExpr;
    pStr2 = sqlite4ExprDup(db, pStr1, 0);
    if( !db->mallocFailed ){
      u8 c, *pC;       /* Last character before the first wildcard */
      pC = (u8*)&pStr2->u.zToken[sqlite4Strlen30(pStr2->u.zToken)-1];
      c = *pC;
      if( noCase ){
        /* The point is to increment the last character before the first
        ** wildcard.  But if we increment '@', that will push it into the
        ** alphabetic range where case conversions will mess up the 
        ** inequality.  To avoid this, make sure to also run the full
        ** LIKE on all candidate expressions by clearing the isComplete flag
        */
        if( c=='A'-1 ) isComplete = 0;   /* EV: R-64339-08207 */


        c = sqlite4UpperToLower[c];
      }
      *pC = c + 1;
    }
    sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
    sCollSeqName.n = 6;
    pNewExpr1 = sqlite4ExprDup(db, pLeft, 0);
    sqlite4ExprSetCollByToken(pParse, pNewExpr1, &sCollSeqName);
    pNewExpr1 = sqlite4PExpr(pParse, TK_GE, pNewExpr1, pStr1, 0);
    idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
    testcase( idxNew1==0 );
    exprAnalyze(pSrc, pWC, idxNew1);
    pNewExpr2 = sqlite4ExprDup(db, pLeft, 0);
    sqlite4ExprSetCollByToken(pParse, pNewExpr2, &sCollSeqName);
    pNewExpr2 = sqlite4PExpr(pParse, TK_LT, pNewExpr2, pStr2, 0);
    idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
    testcase( idxNew2==0 );
    exprAnalyze(pSrc, pWC, idxNew2);
    pTerm = &pWC->a[idxTerm];
    if( isComplete ){
      pWC->a[idxNew1].iParent = idxTerm;
      pWC->a[idxNew2].iParent = idxTerm;
      pTerm->nChild = 2;
    }
  }
#endif /* SQLITE4_OMIT_LIKE_OPTIMIZATION */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  /* Add a WO_MATCH auxiliary term to the constraint set if the
  ** current expression is of the form:  column MATCH expr.
  ** This information is used by the xBestIndex methods of
  ** virtual tables.  The native query optimizer does not attempt
  ** to do anything with MATCH functions.
  */
  if( isMatchOfColumn(pExpr) ){
    int idxNew;
    Expr *pRight, *pLeft;
    WhereTerm *pNewTerm;
    Bitmask prereqColumn, prereqExpr;

    pRight = pExpr->x.pList->a[0].pExpr;
    pLeft = pExpr->x.pList->a[1].pExpr;
    prereqExpr = exprTableUsage(pMaskSet, pRight);
    prereqColumn = exprTableUsage(pMaskSet, pLeft);
    if( (prereqExpr & prereqColumn)==0 ){
      Expr *pNewExpr;
      pNewExpr = sqlite4PExpr(pParse, TK_MATCH, 
                              0, sqlite4ExprDup(db, pRight, 0), 0);
      idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
      testcase( idxNew==0 );
      pNewTerm = &pWC->a[idxNew];
      pNewTerm->prereqRight = prereqExpr;
      pNewTerm->leftCursor = pLeft->iTable;
      pNewTerm->u.leftColumn = pLeft->iColumn;
      pNewTerm->eOperator = WO_MATCH;
      pNewTerm->iParent = idxTerm;
      pTerm = &pWC->a[idxTerm];
      pTerm->nChild = 1;
      pTerm->wtFlags |= TERM_COPIED;
      pNewTerm->prereqAll = pTerm->prereqAll;
    }
  }
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

#ifdef SQLITE4_ENABLE_STAT3
  /* When sqlite_stat3 histogram data is available an operator of the
  ** form "x IS NOT NULL" can sometimes be evaluated more efficiently
  ** as "x>NULL" if x is not an INTEGER PRIMARY KEY.  So construct a
  ** virtual term of that form.
  **
  ** Note that the virtual term must be tagged with TERM_VNULL.  This
  ** TERM_VNULL tag will suppress the not-null check at the beginning
  ** of the loop.  Without the TERM_VNULL flag, the not-null check at
  ** the start of the loop will prevent any results from being returned.
  */
  if( pExpr->op==TK_NOTNULL
   && pExpr->pLeft->op==TK_COLUMN
   && pExpr->pLeft->iColumn>=0
   && OptimizationEnabled(db, SQLITE4_Stat3)
  ){
    Expr *pNewExpr;
    Expr *pLeft = pExpr->pLeft;
    int idxNew;
    WhereTerm *pNewTerm;

    pNewExpr = sqlite4PExpr(pParse, TK_GT,
                            sqlite4ExprDup(db, pLeft, 0),
                            sqlite4PExpr(pParse, TK_NULL, 0, 0, 0), 0);

    idxNew = whereClauseInsert(pWC, pNewExpr,
                              TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
    if( idxNew ){
      pNewTerm = &pWC->a[idxNew];
      pNewTerm->prereqRight = 0;
      pNewTerm->leftCursor = pLeft->iTable;
      pNewTerm->u.leftColumn = pLeft->iColumn;
      pNewTerm->eOperator = WO_GT;
      pNewTerm->iParent = idxTerm;
      pTerm = &pWC->a[idxTerm];
      pTerm->nChild = 1;
      pTerm->wtFlags |= TERM_COPIED;
      pNewTerm->prereqAll = pTerm->prereqAll;
    }
  }
#endif /* SQLITE4_ENABLE_STAT */

  /* Prevent ON clause terms of a LEFT JOIN from being used to drive
  ** an index for tables to the left of the join.
  */
  pTerm->prereqRight |= extraRight;
}

/*
** This function searches pList for a entry that matches the iCol-th column
** of index pIdx.
**
** 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 = sqlite4ExprSkipCollate(pList->a[i].pExpr);
    if( p->op==TK_COLUMN
     && p->iColumn==pIdx->aiColumn[iCol]
     && p->iTable==iBase
    ){
      CollSeq *pColl = sqlite4ExprCollSeq(pParse, pList->a[i].pExpr);
      if( ALWAYS(pColl) && 0==sqlite4_stricmp(pColl->zName, zColl) ){
        return i;
      }
    }
  }

  return -1;
}

/*
** Return true if the DISTINCT expression-list passed as the third argument
** is redundant.
**
** A DISTINCT list is redundant if the database contains some subset of
** columns that are unique and non-null.
*/
static int isDistinctRedundant(
  Parse *pParse,            /* Parsing context */
  SrcList *pTabList,        /* The FROM clause */
  WhereClause *pWC,         /* The WHERE clause */
  ExprList *pDistinct       /* The result set that needs to be DISTINCT */
){
  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 = sqlite4ExprSkipCollate(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.
  **
  **   3. All of those index columns for which the WHERE clause does not
  **      contain a "col=X" term are subject to a NOT NULL constraint.
  */
  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) ){
        int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i);
        if( iIdxCol<0 || pTab->aCol[pIdx->aiColumn[i]].notNull==0 ){
          break;
        }
      }
    }
    if( i==pIdx->nColumn ){
      /* This index implies that the DISTINCT qualifier is redundant. */
      return 1;
    }
  }

  return 0;
}

/* 
** The (an approximate) sum of two WhereCosts.  This computation is
** not a simple "+" operator because WhereCost is stored as a logarithmic
** value.
** 
*/
static WhereCost whereCostAdd(WhereCost a, WhereCost b){
  static const unsigned char x[] = {
     10, 10,                         /* 0,1 */
      9, 9,                          /* 2,3 */
      8, 8,                          /* 4,5 */
      7, 7, 7,                       /* 6,7,8 */
      6, 6, 6,                       /* 9,10,11 */
      5, 5, 5,                       /* 12-14 */
      4, 4, 4, 4,                    /* 15-18 */
      3, 3, 3, 3, 3, 3,              /* 19-24 */
      2, 2, 2, 2, 2, 2, 2,           /* 25-31 */
  };
  if( a>=b ){
    if( a>b+49 ) return a;
    if( a>b+31 ) return a+1;
    return a+x[a-b];
  }else{
    if( b>a+49 ) return b;
    if( b>a+31 ) return b+1;
    return b+x[b-a];
  }
}

/*
** Convert an integer into a WhereCost.  In other words, compute a
** good approximatation for 10*log2(x).
*/
static WhereCost whereCost(tRowcnt x){
  static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
  WhereCost y = 40;
  if( x<8 ){
    if( x<2 ) return 0;
    while( x<8 ){  y -= 10; x <<= 1; }
  }else{
    while( x>255 ){ y += 40; x >>= 4; }
    while( x>15 ){  y += 10; x >>= 1; }
  }
  return a[x&7] + y - 10;
}

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/*
** Convert a double (as received from xBestIndex of a virtual table)
** into a WhereCost.  In other words, compute an approximation for
** 10*log2(x).
*/
static WhereCost whereCostFromDouble(double x){
  u64 a;
  WhereCost e;
  assert( sizeof(x)==8 && sizeof(a)==8 );
  if( x<=1 ) return 0;
  if( x<=2000000000 ) return whereCost((tRowcnt)x);
  memcpy(&a, &x, 8);
  e = (a>>52) - 1022;
  return e*10;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

/*
** Estimate the logarithm of the input value to base 2.
*/
static WhereCost estLog(WhereCost N){
  WhereCost x = whereCost(N);
  return x>33 ? x - 33 : 0;
}

/*
** Two routines for printing the content of an sqlite4_index_info
** structure.  Used for testing and debugging only.  If neither
** SQLITE4_TEST or SQLITE4_DEBUG are defined, then these routines
** are no-ops.
*/
#if !defined(SQLITE4_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
static void TRACE_IDX_INPUTS(sqlite4_index_info *p){
  int i;
  if( !sqlite4WhereTrace ) return;
  for(i=0; i<p->nConstraint; i++){
    sqlite4DebugPrintf("  constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
       i,
       p->aConstraint[i].iColumn,
       p->aConstraint[i].iTermOffset,
       p->aConstraint[i].op,
       p->aConstraint[i].usable);
  }
  for(i=0; i<p->nOrderBy; i++){
    sqlite4DebugPrintf("  orderby[%d]: col=%d desc=%d\n",
       i,
       p->aOrderBy[i].iColumn,
       p->aOrderBy[i].desc);
  }
}
static void TRACE_IDX_OUTPUTS(sqlite4_index_info *p){
  int i;
  if( !sqlite4WhereTrace ) return;
  for(i=0; i<p->nConstraint; i++){
    sqlite4DebugPrintf("  usage[%d]: argvIdx=%d omit=%d\n",
       i,
       p->aConstraintUsage[i].argvIndex,
       p->aConstraintUsage[i].omit);
  }
  sqlite4DebugPrintf("  idxNum=%d\n", p->idxNum);
  sqlite4DebugPrintf("  idxStr=%s\n", p->idxStr);
  sqlite4DebugPrintf("  orderByConsumed=%d\n", p->orderByConsumed);
  sqlite4DebugPrintf("  estimatedCost=%g\n", p->estimatedCost);
}
#else
#define TRACE_IDX_INPUTS(A)
#define TRACE_IDX_OUTPUTS(A)
#endif

#ifndef SQLITE4_OMIT_AUTOMATIC_INDEX
/*
** Return TRUE if the WHERE clause term pTerm is of a form where it
** could be used with an index to access pSrc, assuming an appropriate
** index existed.
*/
static int termCanDriveIndex(
  WhereTerm *pTerm,              /* WHERE clause term to check */
  struct SrcListItem *pSrc,     /* Table we are trying to access */
  Bitmask notReady               /* Tables in outer loops of the join */
){
  char aff;
  if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
  if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
  if( (pTerm->prereqRight & notReady)!=0 ) return 0;
  if( pTerm->u.leftColumn<0 ) return 0;
  aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
  if( !sqlite4IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
  return 1;
}
#endif


#ifndef SQLITE4_OMIT_AUTOMATIC_INDEX
/*
** Generate code to construct the Index object for an automatic index
** and to set up the WhereLevel object pLevel so that the code generator
** makes use of the automatic index.
*/
static void constructAutomaticIndex(
  Parse *pParse,              /* The parsing context */
  WhereClause *pWC,           /* The WHERE clause */
  struct SrcListItem *pSrc,  /* The FROM clause term to get the next index */
  Bitmask notReady,           /* Mask of cursors that are not available */
  WhereLevel *pLevel          /* Write new index here */
){
  int nColumn;                /* Number of columns in the constructed index */
  WhereTerm *pTerm;           /* A single term of the WHERE clause */
  WhereTerm *pWCEnd;          /* End of pWC->a[] */
  int nByte;                  /* Byte of memory needed for pIdx */
  Index *pIdx;                /* Object describing the transient index */
  Vdbe *v;                    /* Prepared statement under construction */
  int addrInit;               /* Address of the initialization bypass jump */
  Table *pTable;              /* The table being indexed */
  KeyInfo *pKeyinfo;          /* Key information for the index */   
  int addrTop;                /* Top of the index fill loop */
  int regRecord;              /* Register holding an index value */
  int regKey;                 /* Register holding an index key */
  int n;                      /* Column counter */
  int i;                      /* Loop counter */
  int mxBitCol;               /* Maximum column in pSrc->colUsed */
  int iPkCsr;                 /* PK cursor number */
  CollSeq *pColl;             /* Collating sequence to on a column */
  WhereLoop *pLoop;           /* The Loop object */
  Bitmask idxCols;            /* Bitmap of columns used for indexing */
  Bitmask extraCols;          /* Bitmap of additional columns */
  u8 sentWarning = 0;         /* True if a warnning has been issued */

  /* Generate code to skip over the creation and initialization of the
  ** transient index on 2nd and subsequent iterations of the loop. */
  v = pParse->pVdbe;
  assert( v!=0 );
  addrInit = sqlite4CodeOnce(pParse);

  /* Count the number of columns that will be added to the index
  ** and used to match WHERE clause constraints */
  nColumn = 0;
  pTable = pSrc->pTab;
  pWCEnd = &pWC->a[pWC->nTerm];
  pLoop = pLevel->pWLoop;
  idxCols = 0;
  for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
    if( termCanDriveIndex(pTerm, pSrc, notReady) ){
      int iCol = pTerm->u.leftColumn;
      Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
      testcase( iCol==BMS );
      testcase( iCol==BMS-1 );
      if( !sentWarning ){
        sqlite4_log(pParse->db->pEnv, SQLITE4_WARNING_AUTOINDEX,
            "automatic index on %s(%s)", pTable->zName,
            pTable->aCol[iCol].zName);
        sentWarning = 1;
      }
      if( (idxCols & cMask)==0 ){
        if( whereLoopResize(pParse->db, pLoop, nColumn+1) ) return;
        pLoop->aLTerm[nColumn++] = pTerm;
        idxCols |= cMask;
      }
    }
  }
  assert( nColumn>0 );
  pLoop->u.btree.nEq = pLoop->nLTerm = nColumn;
  pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
                     | WHERE_AUTO_INDEX;

  /* Count the number of additional columns needed to create a
  ** covering index.  A "covering index" is an index that contains all
  ** columns that are needed by the query.  With a covering index, the
  ** original table never needs to be accessed.  Automatic indices must
  ** be a covering index because the index will not be updated if the
  ** original table changes and the index and table cannot both be used
  ** if they go out of sync.
  */
  extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1));
  mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol;
  testcase( pTable->nCol==BMS-1 );
  testcase( pTable->nCol==BMS-2 );
  for(i=0; i<mxBitCol; i++){
    if( extraCols & MASKBIT(i) ) nColumn++;
  }
  if( pSrc->colUsed & MASKBIT(BMS-1) ){
    nColumn += pTable->nCol - BMS + 1;
  }
  pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY;

  /* Construct the Index object to describe this index */
  nByte = sizeof(Index);
  nByte += nColumn*sizeof(int);     /* Index.aiColumn */
  nByte += nColumn*sizeof(char*);   /* Index.azColl */
  nByte += nColumn;                 /* Index.aSortOrder */
  pIdx = sqlite4DbMallocZero(pParse->db, nByte);
  if( pIdx==0 ) return;
  pLoop->u.btree.pIndex = pIdx;
  pIdx->azColl = (char**)&pIdx[1];
  pIdx->aiColumn = (int*)&pIdx->azColl[nColumn];
  pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn];
  pIdx->zName = "auto-index";
  pIdx->nColumn = nColumn;
  pIdx->pTable = pTable;
  pIdx->aiCover = pIdx->aiColumn;
  pIdx->nCover = pIdx->nColumn;
  pIdx->eIndexType = SQLITE4_INDEX_TEMP;
  n = 0;
  idxCols = 0;
  for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
    if( termCanDriveIndex(pTerm, pSrc, notReady) ){
      int iCol = pTerm->u.leftColumn;
      Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
      testcase( iCol==BMS-1 );
      testcase( iCol==BMS );
      if( (idxCols & cMask)==0 ){
        Expr *pX = pTerm->pExpr;
        idxCols |= cMask;
        pIdx->aiColumn[n] = pTerm->u.leftColumn;
        pColl = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
        pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY";
        n++;
      }
    }
  }
  assert( (u32)n==pLoop->u.btree.nEq );

  /* Add additional columns needed to make the automatic index into
  ** a covering index */
  for(i=0; i<mxBitCol; i++){
    if( extraCols & MASKBIT(i) ){
      pIdx->aiColumn[n] = i;
      pIdx->azColl[n] = "BINARY";
      n++;
    }
  }
  if( pSrc->colUsed & MASKBIT(BMS-1) ){
    for(i=BMS-1; i<pTable->nCol; i++){
      pIdx->aiColumn[n] = i;
      pIdx->azColl[n] = "BINARY";
      n++;
    }
  }
  assert( n==nColumn );

  /* Create the automatic index */
  pKeyinfo = sqlite4IndexKeyinfo(pParse, pIdx);
  assert( pLevel->iIdxCur>=0 );
  pLevel->iIdxCur = pParse->nTab++;
  sqlite4VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0,
                    (char*)pKeyinfo, P4_KEYINFO_HANDOFF);
  VdbeComment((v, "for %s", pTable->zName));

  /* Fill the automatic index with content */
  iPkCsr = pLevel->iTabCur;
  addrTop = sqlite4VdbeAddOp1(v, OP_Rewind, iPkCsr);
  regRecord = sqlite4GetTempRange(pParse, 2);
  regKey = regRecord + 1;
  sqlite4EncodeIndexKey(pParse, 0, iPkCsr, pIdx, pLevel->iIdxCur, 1, regKey);
  sqlite4EncodeIndexValue(pParse, iPkCsr, pIdx, regRecord);
  sqlite4VdbeAddOp3(v, OP_Insert, pLevel->iIdxCur, regRecord, regKey);
  /* sqlite4VdbeChangeP5(v, OPFLAG_USESEEKRESULT); */
  sqlite4VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
  sqlite4VdbeChangeP5(v, SQLITE4_STMTSTATUS_AUTOINDEX);
  sqlite4VdbeJumpHere(v, addrTop);
  sqlite4ReleaseTempRange(pParse, regRecord, 2);
  
  /* Jump here when skipping the initialization */
  sqlite4VdbeJumpHere(v, addrInit);
}
#endif /* SQLITE4_OMIT_AUTOMATIC_INDEX */

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/*
** Allocate and populate an sqlite4_index_info structure. It is the 
** responsibility of the caller to eventually release the structure
** by passing the pointer returned by this function to sqlite4_free().
*/
static sqlite4_index_info *allocateIndexInfo(
  Parse *pParse,
  WhereClause *pWC,
  struct SrcListItem *pSrc,
  ExprList *pOrderBy
){
  int i, j;
  int nTerm;
  struct sqlite4_index_constraint *pIdxCons;
  struct sqlite4_index_orderby *pIdxOrderBy;
  struct sqlite4_index_constraint_usage *pUsage;
  WhereTerm *pTerm;
  int nOrderBy;
  sqlite4_index_info *pIdxInfo;

  /* Count the number of possible WHERE clause constraints referring
  ** to this virtual table */
  for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    if( pTerm->leftCursor != pSrc->iCursor ) continue;
    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
    testcase( pTerm->eOperator & WO_IN );
    testcase( pTerm->eOperator & WO_ISNULL );
    if( pTerm->eOperator & (WO_ISNULL) ) continue;
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    nTerm++;
  }

  /* If the ORDER BY clause contains only columns in the current 
  ** virtual table then allocate space for the aOrderBy part of
  ** the sqlite4_index_info structure.
  */
  nOrderBy = 0;
  if( pOrderBy ){
    int n = pOrderBy->nExpr;
    for(i=0; i<n; i++){
      Expr *pExpr = pOrderBy->a[i].pExpr;
      if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
    }
    if( i==n){
      nOrderBy = n;
    }
  }

  /* Allocate the sqlite4_index_info structure
  */
  pIdxInfo = sqlite4DbMallocZero(pParse->db, sizeof(*pIdxInfo)
                           + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
                           + sizeof(*pIdxOrderBy)*nOrderBy );
  if( pIdxInfo==0 ){
    sqlite4ErrorMsg(pParse, "out of memory");
    return 0;
  }

  /* Initialize the structure.  The sqlite4_index_info structure contains
  ** many fields that are declared "const" to prevent xBestIndex from
  ** changing them.  We have to do some funky casting in order to
  ** initialize those fields.
  */
  pIdxCons = (struct sqlite4_index_constraint*)&pIdxInfo[1];
  pIdxOrderBy = (struct sqlite4_index_orderby*)&pIdxCons[nTerm];
  pUsage = (struct sqlite4_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
  *(int*)&pIdxInfo->nConstraint = nTerm;
  *(int*)&pIdxInfo->nOrderBy = nOrderBy;
  *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
  *(struct sqlite4_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
  *(struct sqlite4_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
                                                                   pUsage;

  for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
    u8 op;
    if( pTerm->leftCursor != pSrc->iCursor ) continue;
    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
    testcase( pTerm->eOperator & WO_IN );
    testcase( pTerm->eOperator & WO_ISNULL );
    if( pTerm->eOperator & (WO_ISNULL) ) continue;
    if( pTerm->wtFlags & TERM_VNULL ) continue;
    pIdxCons[j].iColumn = pTerm->u.leftColumn;
    pIdxCons[j].iTermOffset = i;
    op = (u8)pTerm->eOperator & WO_ALL;
    if( op==WO_IN ) op = WO_EQ;
    pIdxCons[j].op = op;
    /* The direct assignment in the previous line is possible only because
    ** the WO_ and SQLITE4_INDEX_CONSTRAINT_ codes are identical.  The
    ** following asserts verify this fact. */
    assert( WO_EQ==SQLITE4_INDEX_CONSTRAINT_EQ );
    assert( WO_LT==SQLITE4_INDEX_CONSTRAINT_LT );
    assert( WO_LE==SQLITE4_INDEX_CONSTRAINT_LE );
    assert( WO_GT==SQLITE4_INDEX_CONSTRAINT_GT );
    assert( WO_GE==SQLITE4_INDEX_CONSTRAINT_GE );
    assert( WO_MATCH==SQLITE4_INDEX_CONSTRAINT_MATCH );
    assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
    j++;
  }
  for(i=0; i<nOrderBy; i++){
    Expr *pExpr = pOrderBy->a[i].pExpr;
    pIdxOrderBy[i].iColumn = pExpr->iColumn;
    pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
  }

  return pIdxInfo;
}

/*
** The table object reference passed as the second argument to this function
** must represent a virtual table. This function invokes the xBestIndex()
** method of the virtual table with the sqlite4_index_info object that
** comes in as the 3rd argument to this function.
**
** If an error occurs, pParse is populated with an error message and a
** non-zero value is returned. Otherwise, 0 is returned and the output
** part of the sqlite4_index_info structure is left populated.
**
** Whether or not an error is returned, it is the responsibility of the
** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates
** that this is required.
*/
static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite4_index_info *p){
  sqlite4_vtab *pVtab = sqlite4GetVTable(pParse->db, pTab)->pVtab;
  int i;
  int rc;

  TRACE_IDX_INPUTS(p);
  rc = pVtab->pModule->xBestIndex(pVtab, p);
  TRACE_IDX_OUTPUTS(p);

  if( rc!=SQLITE4_OK ){
    if( rc==SQLITE4_NOMEM ){
      pParse->db->mallocFailed = 1;
    }else if( !pVtab->zErrMsg ){
      sqlite4ErrorMsg(pParse, "%s", sqlite4ErrStr(rc));
    }else{
      sqlite4ErrorMsg(pParse, "%s", pVtab->zErrMsg);
    }
  }
  sqlite4_free(pVtab->zErrMsg);
  pVtab->zErrMsg = 0;

  for(i=0; i<p->nConstraint; i++){
    if( !p->aConstraint[i].usable && p->aConstraintUsage[i].argvIndex>0 ){
      sqlite4ErrorMsg(pParse, 
          "table %s: xBestIndex returned an invalid plan", pTab->zName);
    }
  }

  return pParse->nErr;
}
#endif /* !defined(SQLITE4_OMIT_VIRTUALTABLE) */


#ifdef SQLITE4_ENABLE_STAT3
/*
** Estimate the location of a particular key among all keys in an
** index.  Store the results in aStat as follows:
**
**    aStat[0]      Est. number of rows less than pVal
**    aStat[1]      Est. number of rows equal to pVal
**
** Return SQLITE4_OK on success.
*/
static int whereKeyStats(
  Parse *pParse,              /* Database connection */
  Index *pIdx,                /* Index to consider domain of */
  sqlite4_buffer *pBuf,       /* Buffer containing encoded value to consider */
  int roundUp,                /* Round up if true.  Round down if false */
  tRowcnt *aStat              /* OUT: stats written here */
){
  tRowcnt n;
  IndexSample *aSample;
  int i;
  int isEq = 0;

  assert( roundUp==0 || roundUp==1 );
  assert( pIdx->nSample>0 );
  assert( pBuf->n>0 );

  n = pIdx->aiRowEst[0];
  aSample = pIdx->aSample;


  /* Set variable i to the index of the first sample equal to or larger 
  ** than the value in pBuf. Set isEq to true if the value is equal, or
  ** false otherwise.  */
  for(i=0; i<pIdx->nSample; i++){
    int res;
    int n = pBuf->n;
    if( n>aSample[i].nVal ) n = aSample[i].nVal;

    res = memcmp(pBuf->p, aSample[i].aVal, n);
    if( res==0 ) res = pBuf->n - aSample[i].nVal;
    if( res<=0 ){
      isEq = (res==0);
      break;
    }
  }

  /* At this point, aSample[i] is the first sample that is greater than
  ** or equal to pVal.  Or if i==pIdx->nSample, then all samples are less
  ** than pVal.  If aSample[i]==pVal, then isEq==1.
  */
  if( isEq ){
    assert( i<pIdx->nSample );
    aStat[0] = aSample[i].nLt;
    aStat[1] = aSample[i].nEq;
  }else{
    tRowcnt iLower, iUpper, iGap;
    if( i==0 ){
      iLower = 0;
      iUpper = aSample[0].nLt;
    }else{
      iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
      iLower = aSample[i-1].nEq + aSample[i-1].nLt;
    }
    aStat[1] = pIdx->avgEq;
    if( iLower>=iUpper ){
      iGap = 0;
    }else{
      iGap = iUpper - iLower;
    }
    if( roundUp ){
      iGap = (iGap*2)/3;
    }else{
      iGap = iGap/3;
    }
    aStat[0] = iLower + iGap;
  }
  return SQLITE4_OK;
}
#endif /* SQLITE4_ENABLE_STAT3 */

/*
** If expression pExpr represents a literal value, extract it and apply
** the affinity aff to it. Then encode the value using the database index
** key encoding and write the result into buffer pBuf.
**
** If the current parse is a recompile (sqlite4Reprepare()) and pExpr
** is an SQL variable that currently has a non-NULL value bound to it,
** do the same with the bound value.
**
** If neither of the above apply, leave the buffer empty.
**
** If an error occurs, return an error code. Otherwise, SQLITE4_OK.
*/
#ifdef SQLITE4_ENABLE_STAT3
static int valueFromExpr(
  Parse *pParse,                  /* Parse context */
  KeyInfo *pKeyinfo,              /* Collation sequence and sort order */
  Expr *pExpr,                    /* Expression to extract value from */
  u8 aff,                         /* Affinity to apply to value */
  sqlite4_buffer *pBuf            /* Buffer to populate */
){
  int rc = SQLITE4_OK;
  sqlite4 *db = pParse->db;
  sqlite4_value *pVal = 0;

  assert( pBuf->n==0 );

  if( pExpr->op==TK_VARIABLE
   || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
  ){
    int iVar = pExpr->iColumn;
    sqlite4VdbeSetVarmask(pParse->pVdbe, iVar);
    pVal = sqlite4VdbeGetValue(pParse->pReprepare, iVar, aff);
  }else{
    rc = sqlite4ValueFromExpr(db, pExpr, SQLITE4_UTF8, aff, &pVal);
  }

  if( pVal && rc==SQLITE4_OK ){
    u8 *aOut;
    int nOut;
    rc = sqlite4VdbeEncodeKey(db, pVal, 1, -1, pKeyinfo, &aOut, &nOut, 0);
    if( rc==SQLITE4_OK ){
      rc = sqlite4_buffer_set(pBuf, aOut, nOut);
    }
    sqlite4DbFree(db, aOut);
  }

  sqlite4ValueFree(pVal);
  return SQLITE4_OK;
}
#endif

/*
** TODO: Should this be ENABLE_STAT3 only.
** TODO: Comment this.
*/
static int whereSampleKeyinfo(Parse *pParse, Index *p, KeyInfo *pKeyInfo){
  CollSeq *pColl;
  memset(pKeyInfo, 0, sizeof(KeyInfo));
  pKeyInfo->nField = p->nColumn;
  pKeyInfo->nPK = 1;
  pKeyInfo->nData = 0;
  pKeyInfo->aSortOrder = p->aSortOrder;
  pKeyInfo->aColl[0] = pColl = sqlite4LocateCollSeq(pParse, p->azColl[0]);
  pKeyInfo->aColl[0] = pColl;
  return pColl ? SQLITE4_OK : SQLITE4_ERROR;
}


/*
** This function is used to estimate the number of rows that will be visited
** by scanning an index for a range of values. The range may have an upper
** bound, a lower bound, or both. The WHERE clause terms that set the upper
** and lower bounds are represented by pLower and pUpper respectively. For
** example, assuming that index p is on t1(a):
**
**   ... FROM t1 WHERE a > ? AND a < ? ...
**                    |_____|   |_____|
**                       |         |
**                     pLower    pUpper
**
** If either of the upper or lower bound is not present, then NULL is passed in
** place of the corresponding WhereTerm.
**
** The nEq parameter is passed the index of the index column subject to the
** range constraint. Or, equivalently, the number of equality constraints
** optimized by the proposed index scan. For example, assuming index p is
** on t1(a, b), and the SQL query is:
**
**   ... FROM t1 WHERE a = ? AND b > ? AND b < ? ...
**
** then nEq should be passed the value 1 (as the range restricted column,
** b, is the second left-most column of the index). Or, if the query is:
**
**   ... FROM t1 WHERE a > ? AND a < ? ...
**
** then nEq should be passed 0.
**
** The returned value is an integer divisor to reduce the estimated
** search space.  A return value of 1 means that range constraints are
** no help at all.  A return value of 2 means range constraints are
** expected to reduce the search space by half.  And so forth...
**
** In the absence of sqlite_stat3 ANALYZE data, each range inequality
** reduces the search space by a factor of 4.  Hence a single constraint (x>?)
** results in a return of 4 and a range constraint (x>? AND x<?) results
** in a return of 16.
*/
static int whereRangeScanEst(
  Parse *pParse,       /* Parsing & code generating context */
  Index *p,            /* The index containing the range-compared column; "x" */
  int nEq,             /* index into p->aCol[] of the range-compared column */
  WhereTerm *pLower,   /* Lower bound on the range. ex: "x>123" Might be NULL */
  WhereTerm *pUpper,   /* Upper bound on the range. ex: "x<455" Might be NULL */
  WhereCost *pRangeDiv /* OUT: Reduce search space by this divisor */
){
  int rc = SQLITE4_OK;

#ifdef SQLITE4_ENABLE_STAT3

  if( nEq==0 && p->nSample && OptimizationEnabled(pParse->db, SQLITE4_Stat3) ){
    sqlite4 *db = pParse->db;
    KeyInfo keyinfo;
    sqlite4_buffer buf;
    tRowcnt iLower = 0;
    tRowcnt iUpper = p->aiRowEst[0];
    tRowcnt a[2];
    u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;

    sqlite4_buffer_init(&buf, db->pEnv->pMM);
    rc = whereSampleKeyinfo(pParse, p, &keyinfo);

    if( rc==SQLITE4_OK && pLower ){
      Expr *pExpr = pLower->pExpr->pRight;
      rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf);
      assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
      if( rc==SQLITE4_OK && buf.n
       && whereKeyStats(pParse, p, &buf, 0, a)==SQLITE4_OK
      ){
        iLower = a[0];
        if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
      }
      sqlite4_buffer_set(&buf, 0, 0);
    }
    if( rc==SQLITE4_OK && pUpper ){
      Expr *pExpr = pUpper->pExpr->pRight;
      rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf);
      assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
      if( rc==SQLITE4_OK && buf.n
       && whereKeyStats(pParse, p, &buf, 1, a)==SQLITE4_OK
      ){
        iUpper = a[0];
        if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
      }
    }
    sqlite4_buffer_clear(&buf);
    if( rc==SQLITE4_OK ){
      WhereCost iBase = whereCost(p->aiRowEst[0]);
      if( iUpper>iLower ){
        iBase -= whereCost(iUpper - iLower);
      }
      *pRangeDiv = iBase;
      WHERETRACE(0x100, ("range scan regions: %u..%u  div=%d\n",
                         (u32)iLower, (u32)iUpper, *pRangeDiv));
      return SQLITE4_OK;
    }
  }
#else
  UNUSED_PARAMETER(pParse);
  UNUSED_PARAMETER(p);
  UNUSED_PARAMETER(nEq);
#endif
  assert( pLower || pUpper );
  *pRangeDiv = 0;
  /* TUNING:  Each inequality constraint reduces the search space 4-fold.
  ** A BETWEEN operator, therefore, reduces the search space 16-fold */
  if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
    *pRangeDiv += 20;  assert( 20==whereCost(4) );
  }
  if( pUpper ){
    *pRangeDiv += 20;  assert( 20==whereCost(4) );
  }
  return rc;
}

#ifdef SQLITE4_ENABLE_STAT3
/*
** Estimate the number of rows that will be returned based on
** an equality constraint x=VALUE and where that VALUE occurs in
** the histogram data.  This only works when x is the left-most
** column of an index and sqlite_stat3 histogram data is available
** for that index.  When pExpr==NULL that means the constraint is
** "x IS NULL" instead of "x=VALUE".
**
** Write the estimated row count into *pnRow and return SQLITE4_OK. 
** If unable to make an estimate, leave *pnRow unchanged and return
** non-zero.
**
** This routine can fail if it is unable to load a collating sequence
** required for string comparison, or if unable to allocate memory
** for a UTF conversion required for comparison.  The error is stored
** in the pParse structure.
*/
static int whereEqualScanEst(
  Parse *pParse,       /* Parsing & code generating context */
  Index *p,            /* The index whose left-most column is pTerm */
  Expr *pExpr,         /* Expression for VALUE in the x=VALUE constraint */
  tRowcnt *pnRow       /* Write the revised row estimate here */
){
  sqlite4_buffer buf;       /* Encoded on right-hand side of pTerm */
  u8 aff;                   /* Column affinity */
  int rc;                   /* Subfunction return code */
  tRowcnt a[2];             /* Statistics */

  assert( p->aSample!=0 );
  assert( p->nSample>0 );
  sqlite4_buffer_init(&buf, pParse->db->pEnv->pMM);
  aff = p->pTable->aCol[p->aiColumn[0]].affinity;
  if( pExpr ){
    KeyInfo keyinfo;
    rc = whereSampleKeyinfo(pParse, p, &keyinfo);
    if( rc==SQLITE4_OK ){
      rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf);
      if( rc==SQLITE4_OK && buf.n==0 ) rc = SQLITE4_NOTFOUND;
    }
  }else{
    /* Populate the buffer with a NULL. */
    u8 aNull[2] = {0x05, 0xfa};        /* ASC, DESC */
    rc = sqlite4_buffer_set(&buf, &aNull[p->aSortOrder[0]], 1);
  }

  if( rc==SQLITE4_OK ){
    rc = whereKeyStats(pParse, p, &buf, 0, a);
    if( rc==SQLITE4_OK ){
      WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1]));
      *pnRow = a[1];
    }
  }
whereEqualScanEst_cancel:
  sqlite4_buffer_clear(&buf);
  return rc;
}
#endif /* defined(SQLITE4_ENABLE_STAT3) */

#ifdef SQLITE4_ENABLE_STAT3
/*
** Estimate the number of rows that will be returned based on
** an IN constraint where the right-hand side of the IN operator
** is a list of values.  Example:
**
**        WHERE x IN (1,2,3,4)
**
** Write the estimated row count into *pnRow and return SQLITE4_OK. 
** If unable to make an estimate, leave *pnRow unchanged and return
** non-zero.
**
** This routine can fail if it is unable to load a collating sequence
** required for string comparison, or if unable to allocate memory
** for a UTF conversion required for comparison.  The error is stored
** in the pParse structure.
*/
static int whereInScanEst(
  Parse *pParse,       /* Parsing & code generating context */
  Index *p,            /* The index whose left-most column is pTerm */
  ExprList *pList,     /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
  tRowcnt *pnRow       /* Write the revised row estimate here */
){
  int rc = SQLITE4_OK;     /* Subfunction return code */
  tRowcnt nEst;           /* Number of rows for a single term */
  tRowcnt nRowEst = 0;    /* New estimate of the number of rows */
  int i;                  /* Loop counter */

  assert( p->aSample!=0 );
  for(i=0; rc==SQLITE4_OK && i<pList->nExpr; i++){
    nEst = p->aiRowEst[0];
    rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst);
    nRowEst += nEst;
  }
  if( rc==SQLITE4_OK ){
    if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
    *pnRow = nRowEst;
    WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst));
  }
  return rc;
}
#endif /* defined(SQLITE4_ENABLE_STAT3) */

/*
** Disable a term in the WHERE clause.  Except, do not disable the term
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
** or USING clause of that join.
**
** Consider the term t2.z='ok' in the following queries:
**
**   (1)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
**   (2)  SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
**   (3)  SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
**
** The t2.z='ok' is disabled in the in (2) because it originates
** in the ON clause.  The term is disabled in (3) because it is not part
** of a LEFT OUTER JOIN.  In (1), the term is not disabled.
**
** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are
** completely satisfied by indices.
**
** Disabling a term causes that term to not be tested in the inner loop
** of the join.  Disabling is an optimization.  When terms are satisfied
** by indices, we disable them to prevent redundant tests in the inner
** loop.  We would get the correct results if nothing were ever disabled,
** but joins might run a little slower.  The trick is to disable as much
** as we can without disabling too much.  If we disabled in (1), we'd get
** the wrong answer.  See ticket #813.
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
  if( pTerm
      && (pTerm->wtFlags & TERM_CODED)==0
      && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
  ){
    pTerm->wtFlags |= TERM_CODED;
    if( pTerm->iParent>=0 ){
      WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
      if( (--pOther->nChild)==0 ){
        disableTerm(pLevel, pOther);
      }
    }
  }
}

/*
** Code an OP_Affinity opcode to apply the column affinity string zAff
** to the n registers starting at base. 
**
** As an optimization, SQLITE4_AFF_NONE entries (which are no-ops) at the
** beginning and end of zAff are ignored.  If all entries in zAff are
** SQLITE4_AFF_NONE, then no code gets generated.
**
** This routine makes its own copy of zAff so that the caller is free
** to modify zAff after this routine returns.
*/
static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
  Vdbe *v = pParse->pVdbe;
  if( zAff==0 ){
    assert( pParse->db->mallocFailed );
    return;
  }
  assert( v!=0 );

  /* Adjust base and n to skip over SQLITE4_AFF_NONE entries at the beginning
  ** and end of the affinity string.
  */
  while( n>0 && zAff[0]==SQLITE4_AFF_NONE ){
    n--;
    base++;
    zAff++;
  }
  while( n>1 && zAff[n-1]==SQLITE4_AFF_NONE ){
    n--;
  }

  /* Code the OP_Affinity opcode if there is anything left to do. */
  if( n>0 ){
    sqlite4VdbeAddOp2(v, OP_Affinity, base, n);
    sqlite4VdbeChangeP4(v, -1, zAff, n);
    sqlite4ExprCacheAffinityChange(pParse, base, n);
  }
}


/*
** Generate code for a single equality term of the WHERE clause.  An equality
** term can be either X=expr or X IN (...).   pTerm is the term to be 
** coded.
**
** The current value for the constraint is left in register iReg.
**
** For a constraint of the form X=expr, the expression is evaluated and its
** result is left on the stack.  For constraints of the form X IN (...)
** this routine sets up a loop that will iterate over all values of X.
*/
static int codeEqualityTerm(
  Parse *pParse,      /* The parsing context */
  WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
  WhereLevel *pLevel, /* The level of the FROM clause we are working on */
  int iEq,            /* Index of the equality term within this level */
  int bRev,           /* True for reverse-order IN operations */
  int iTarget         /* Attempt to leave results in this register */
){
  Expr *pX = pTerm->pExpr;
  Vdbe *v = pParse->pVdbe;
  int iReg;                  /* Register holding results */

  assert( iTarget>0 );
  if( pX->op==TK_EQ ){
    iReg = sqlite4ExprCodeTarget(pParse, pX->pRight, iTarget);
  }else if( pX->op==TK_ISNULL ){
    iReg = iTarget;
    sqlite4VdbeAddOp2(v, OP_Null, 0, iReg);
#ifndef SQLITE4_OMIT_SUBQUERY
  }else{
    int eType;
    int iTab;
    int iCov;
    struct InLoop *pIn;
    WhereLoop *pLoop = pLevel->pWLoop;

    if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
      && pLoop->u.btree.pIndex!=0
      && pLoop->u.btree.pIndex->aSortOrder[iEq]
    ){
      testcase( iEq==0 );
      testcase( bRev );
      bRev = !bRev;
    }
    assert( pX->op==TK_IN );
    iReg = iTarget;
    eType = sqlite4FindInIndex(pParse, pX, 0, &iCov);
    if( eType==IN_INDEX_INDEX_DESC ){
      testcase( bRev );
      bRev = !bRev;
    }
    iTab = pX->iTable;
    sqlite4VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
    assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
    pLoop->wsFlags |= WHERE_IN_ABLE;
    if( pLevel->u.in.nIn==0 ){
      pLevel->addrNxt = sqlite4VdbeMakeLabel(v);
    }
    pLevel->u.in.nIn++;
    pLevel->u.in.aInLoop =
       sqlite4DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
                              sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
    pIn = pLevel->u.in.aInLoop;
    if( pIn ){
      pIn += pLevel->u.in.nIn - 1;
      pIn->iCur = iTab;
      if( eType==IN_INDEX_ROWID ){
        pIn->addrInTop = sqlite4VdbeAddOp2(v, OP_Rowid, iTab, iReg);
      }else{
        pIn->addrInTop = sqlite4VdbeAddOp3(v, OP_Column, iTab, iCov, iReg);
      }
      pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
      sqlite4VdbeAddOp1(v, OP_IsNull, iReg);
    }else{
      pLevel->u.in.nIn = 0;
    }
#endif
  }
  disableTerm(pLevel, pTerm);
  return iReg;
}

/*
** Generate code that will evaluate all == and IN constraints for an
** index.
**
** For example, consider table t1(a,b,c,d,e,f) with index i1(a,b,c).
** Suppose the WHERE clause is this:  a==5 AND b IN (1,2,3) AND c>5 AND c<10
** The index has as many as three equality constraints, but in this
** example, the third "c" value is an inequality.  So only two 
** constraints are coded.  This routine will generate code to evaluate
** a==5 and b IN (1,2,3).  The current values for a and b will be stored
** in consecutive registers and the index of the first register is returned.
**
** In the example above nEq==2.  But this subroutine works for any value
** of nEq including 0.  If nEq==0, this routine is nearly a no-op.
** The only thing it does is allocate the pLevel->iMem memory cell and
** compute the affinity string.
**
** This routine always allocates at least one memory cell and returns
** the index of that memory cell. The code that
** calls this routine will use that memory cell to store the termination
** key value of the loop.  If one or more IN operators appear, then
** this routine allocates an additional nEq memory cells for internal
** use.
**
** Before returning, *pzAff is set to point to a buffer containing a
** copy of the column affinity string of the index allocated using
** sqlite4DbMalloc(). Except, entries in the copy of the string associated
** with equality constraints that use NONE affinity are set to
** SQLITE4_AFF_NONE. This is to deal with SQL such as the following:
**
**   CREATE TABLE t1(a TEXT PRIMARY KEY, b);
**   SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b;
**
** In the example above, the index on t1(a) has TEXT affinity. But since
** the right hand side of the equality constraint (t2.b) has NONE affinity,
** no conversion should be attempted before using a t2.b value as part of
** a key to search the index. Hence the first byte in the returned affinity
** string in this example would be set to SQLITE4_AFF_NONE.
*/
static int codeAllEqualityTerms(
  Parse *pParse,        /* Parsing context */
  WhereLevel *pLevel,   /* Which nested loop of the FROM we are coding */
  int bRev,             /* Reverse the order of IN operators */
  int nExtraReg,        /* Number of extra registers to allocate */
  char **pzAff          /* OUT: Set to point to affinity string */
){
  int nEq;                      /* The number of == or IN constraints to code */
  Vdbe *v = pParse->pVdbe;      /* The vm under construction */
  Index *pIdx;                  /* The index being used for this loop */
  WhereTerm *pTerm;             /* A single constraint term */
  WhereLoop *pLoop;             /* The WhereLoop object */
  int j;                        /* Loop counter */
  int regBase;                  /* Base register */
  int nReg;                     /* Number of registers to allocate */
  char *zAff;                   /* Affinity string to return */

  /* This module is only called on query plans that use an index. */
  pLoop = pLevel->pWLoop;
  assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
  nEq = pLoop->u.btree.nEq;
  pIdx = pLoop->u.btree.pIndex;
  assert( pIdx!=0 );

  /* Figure out how many memory cells we will need then allocate them.
  */
  regBase = pParse->nMem + 1;
  nReg = pLoop->u.btree.nEq + nExtraReg;
  pParse->nMem += nReg;

  zAff = sqlite4DbStrDup(pParse->db, sqlite4IndexAffinityStr(v, pIdx));
  if( !zAff ){
    pParse->db->mallocFailed = 1;
  }

  /* Evaluate the equality constraints
  */
  assert( idxColumnCount(pIdx, sqlite4FindPrimaryKey(pIdx->pTable, 0))>=nEq );
  for(j=0; j<nEq; j++){
    int r1;
    pTerm = pLoop->aLTerm[j];
    assert( pTerm!=0 );
    /* The following true for indices with redundant columns. 
    ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
    testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
    r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
    if( r1!=regBase+j ){
      if( nReg==1 ){
        sqlite4ReleaseTempReg(pParse, regBase);
        regBase = r1;
      }else{
        sqlite4VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
      }
    }
    testcase( pTerm->eOperator & WO_ISNULL );
    testcase( pTerm->eOperator & WO_IN );
    if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
      Expr *pRight = pTerm->pExpr->pRight;
      sqlite4ExprCodeIsNullJump(v, pRight, regBase+j, pLevel->addrBrk);
      if( zAff ){
        if( sqlite4CompareAffinity(pRight, zAff[j])==SQLITE4_AFF_NONE ){
          zAff[j] = SQLITE4_AFF_NONE;
        }
        if( sqlite4ExprNeedsNoAffinityChange(pRight, zAff[j]) ){
          zAff[j] = SQLITE4_AFF_NONE;
        }
      }
    }
  }
  *pzAff = zAff;
  return regBase;
}

#ifndef SQLITE4_OMIT_EXPLAIN
/*
** This routine is a helper for explainIndexRange() below
**
** pStr holds the text of an expression that we are building up one term
** at a time.  This routine adds a new term to the end of the expression.
** Terms are separated by AND so add the "AND" text for second and subsequent
** terms only.
*/
static void explainAppendTerm(
  StrAccum *pStr,             /* The text expression being built */
  int iTerm,                  /* Index of this term.  First is zero */
  const char *zColumn,        /* Name of the column */
  const char *zOp             /* Name of the operator */
){
  if( iTerm ) sqlite4StrAccumAppend(pStr, " AND ", 5);
  sqlite4StrAccumAppend(pStr, zColumn, -1);
  sqlite4StrAccumAppend(pStr, zOp, 1);
  sqlite4StrAccumAppend(pStr, "?", 1);
}

/*
** Argument pLevel describes a strategy for scanning table pTab. This 
** function returns a pointer to a string buffer containing a description
** of the subset of table rows scanned by the strategy in the form of an
** SQL expression. Or, if all rows are scanned, NULL is returned.
**
** For example, if the query:
**
**   SELECT * FROM t1 WHERE a=1 AND b>2;
**
** is run and there is an index on (a, b), then this function returns a
** string similar to:
**
**   "a=? AND b>?"
**
** The returned pointer points to memory obtained from sqlite4DbMalloc().
** It is the responsibility of the caller to free the buffer when it is
** no longer required.
*/
static char *explainIndexRange(sqlite4 *db, WhereLoop *pLoop, Table *pTab){
  Index *pIndex = pLoop->u.btree.pIndex;
  int nEq = pLoop->u.btree.nEq;
  int i, j;
  Column *aCol = pTab->aCol;
  int *aiColumn = pIndex->aiColumn;
  StrAccum txt;

  if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
    return 0;
  }
  sqlite4StrAccumInit(&txt, 0, 0, SQLITE4_MAX_LENGTH);
  txt.db = db;
  sqlite4StrAccumAppend(&txt, " (", 2);
  for(i=0; i<nEq; i++){
    explainAppendTerm(&txt, i, aCol[aiColumn[i]].zName, "=");
  }

  j = i;
  if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
    char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
    explainAppendTerm(&txt, i++, z, ">");
  }
  if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
    char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
    explainAppendTerm(&txt, i, z, "<");
  }
  sqlite4StrAccumAppend(&txt, ")", 1);
  return sqlite4StrAccumFinish(&txt);
}

/*
** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single
** record is added to the output to describe the table scan strategy in 
** pLevel.
*/
static void explainOneScan(
  Parse *pParse,                  /* Parse context */
  SrcList *pTabList,              /* Table list this loop refers to */
  WhereLevel *pLevel,             /* Scan to write OP_Explain opcode for */
  int iLevel,                     /* Value for "level" column of output */
  int iFrom,                      /* Value for "from" column of output */
  u16 wctrlFlags                  /* Flags passed to sqlite4WhereBegin() */
){
  if( pParse->explain==2 ){
    struct SrcListItem *pItem = &pTabList->a[pLevel->iFrom];
    Vdbe *v = pParse->pVdbe;      /* VM being constructed */
    sqlite4 *db = pParse->db;     /* Database handle */
    char *zMsg;                   /* Text to add to EQP output */
    int iId = pParse->iSelectId;  /* Select id (left-most output column) */
    int isSearch;                 /* True for a SEARCH. False for SCAN. */
    WhereLoop *pLoop;             /* The controlling WhereLoop object */
    u32 flags;                    /* Flags that describe this loop */

    pLoop = pLevel->pWLoop;
    flags = pLoop->wsFlags;
    if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;

    isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
            || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
            || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));

    zMsg = sqlite4MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
    if( pItem->pSelect ){
      zMsg = sqlite4MAppendf(db, zMsg, "%s SUBQUERY %d", zMsg,pItem->iSelectId);
    }else{
      zMsg = sqlite4MAppendf(db, zMsg, "%s TABLE %s", zMsg, pItem->zName);
    }

    if( pItem->zAlias ){
      zMsg = sqlite4MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
    }
    if( (flags & WHERE_VIRTUALTABLE)==0
     && ALWAYS(pLoop->u.btree.pIndex!=0)
    ){
      char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
      Index *pIdx = pLoop->u.btree.pIndex;
      if( flags & WHERE_AUTO_INDEX ){
        zMsg = sqlite4MAppendf(db, zMsg, "%s USING AUTOMATIC COVERING INDEX%s",
            zMsg, zWhere
        );
      }else if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){
        if( isSearch ){
          zMsg = sqlite4MAppendf(db, zMsg, "%s USING PRIMARY KEY%s",
              zMsg, zWhere
          );
        }
      }else{
        const char *zCover = (flags & WHERE_IDX_ONLY) ? " COVERING" : "";
        zMsg = sqlite4MAppendf(db, zMsg, "%s USING%s INDEX %s%s",
            zMsg, zCover, pIdx->zName, zWhere
        );
      }
      sqlite4DbFree(db, zWhere);
    }
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
      zMsg = sqlite4MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
                  pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
    }
#endif
    zMsg = sqlite4MAppendf(db, zMsg, "%s", zMsg);
    sqlite4VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
  }
}
#else
# define explainOneScan(u,v,w,x,y,z)
#endif /* SQLITE4_OMIT_EXPLAIN */


/*
** Try to find a MATCH expression that constrains the pTabItem table in the
** WHERE clause. If one exists, set *piTerm to the index in the pWC->a[] array
** and return non-zero. If no such expression exists, return 0.
*/
static int findMatchExpr(
  WhereClause *pWC, 
  SrcListItem *pTabItem, 
  int *piTerm
){
  int i;
  int iCsr = pTabItem->iCursor;

  for(i=0; i<pWC->nTerm; i++){
    Expr *pMatch = pWC->a[i].pExpr;
    if( pMatch->iTable==iCsr && pMatch->op==TK_MATCH ) break;
  }
  if( i==pWC->nTerm ) return 0;

  *piTerm = i;
  return 1;
}


/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
static Bitmask codeOneLoopStart(
  WhereInfo *pWInfo,   /* Complete information about the WHERE clause */
  int iLevel,          /* Which level of pWInfo->a[] should be coded */
  Bitmask notReady     /* Which tables are currently available */
){
  int j, k;            /* Loop counters */
  int iCur;            /* The VDBE cursor for the table */
  int addrNxt;         /* Where to jump to continue with the next IN case */
  int omitTable;       /* True if we use the index only */
  int bRev;            /* True if we need to scan in reverse order */
  WhereLevel *pLevel;  /* The where level to be coded */
  WhereLoop *pLoop;    /* The WhereLoop object being coded */
  WhereClause *pWC;    /* Decomposition of the entire WHERE clause */
  WhereTerm *pTerm;               /* A WHERE clause term */
  Parse *pParse;                  /* Parsing context */
  Vdbe *v;                        /* The prepared stmt under constructions */
  struct SrcListItem *pTabItem;  /* FROM clause term being coded */
  int addrBrk;                    /* Jump here to break out of the loop */
  int addrCont;                   /* Jump here to continue with next cycle */
  int iRowidReg = 0;        /* Rowid is stored in this register, if not zero */
  int iReleaseReg = 0;      /* Temp register to free before returning */
  Bitmask newNotReady;      /* Return value */

  pParse = pWInfo->pParse;
  v = pParse->pVdbe;
  pWC = &pWInfo->sWC;
  pLevel = &pWInfo->a[iLevel];
  pLoop = pLevel->pWLoop;
  pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
  iCur = pTabItem->iCursor;
  bRev = (pWInfo->revMask>>iLevel)&1;
  omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 
           && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0;
  VdbeNoopComment((v, "Begin Join Loop %d", iLevel));

  /* Create labels for the "break" and "continue" instructions
  ** for the current loop.  Jump to addrBrk to break out of a loop.
  ** Jump to cont to go immediately to the next iteration of the
  ** loop.
  **
  ** When there is an IN operator, we also have a "addrNxt" label that
  ** means to continue with the next IN value combination.  When
  ** there are no IN operators in the constraints, the "addrNxt" label
  ** is the same as "addrBrk".
  */
  addrBrk = pLevel->addrBrk = pLevel->addrNxt = sqlite4VdbeMakeLabel(v);
  addrCont = pLevel->addrCont = sqlite4VdbeMakeLabel(v);

  /* If this is the right table of a LEFT OUTER JOIN, allocate and
  ** initialize a memory cell that records if this table matches any
  ** row of the left table of the join.
  */
  if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){
    pLevel->iLeftJoin = ++pParse->nMem;
    sqlite4VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
    VdbeComment((v, "init LEFT JOIN no-match flag"));
  }

#if 0
  /* Special case of a FROM clause subquery implemented as a co-routine */
  if( pTabItem->viaCoroutine ){
    int regYield = pTabItem->regReturn;
    sqlite4VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield);
    pLevel->p2 =  sqlite4VdbeAddOp1(v, OP_Yield, regYield);
    VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName));
    sqlite4VdbeAddOp2(v, OP_If, regYield+1, addrBrk);
    pLevel->op = OP_Goto;
  }else
#endif

  if( (pLoop->wsFlags & WHERE_INDEXED)
   && (pLoop->u.btree.pIndex->eIndexType==SQLITE4_INDEX_FTS5)
  ){
    /* Case -1:  An FTS query */
    int iTerm;
    int rMatch;
    int rFree;
    findMatchExpr(pWC, pTabItem, &iTerm);

    rMatch = sqlite4ExprCodeTemp(pParse, pWC->a[iTerm].pExpr->pRight, &rFree);
    pWC->a[iTerm].wtFlags |= TERM_CODED;
    sqlite4Fts5CodeQuery(pParse, 
        pLoop->u.btree.pIndex, pLevel->iIdxCur, addrBrk, rMatch
    );
    sqlite4VdbeChangeP5(v, bRev);
    sqlite4ReleaseTempReg(pParse, rFree);

    pLevel->p2 = sqlite4VdbeCurrentAddr(v);
    sqlite4VdbeAddOp3(v, OP_SeekPk, iCur, 0, pLevel->iIdxCur);
    pLevel->op = OP_FtsNext;
    pLevel->p1 = pLevel->iIdxCur;
  }else

#ifndef SQLITE4_OMIT_VIRTUALTABLE
  if(  (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
    /* Case 1:  The table is a virtual-table.  Use the VFilter and VNext
    **          to access the data.
    */
    int iReg;   /* P3 Value for OP_VFilter */
    int addrNotFound;
    int nConstraint = pLoop->nLTerm;

    sqlite4ExprCachePush(pParse);
    iReg = sqlite4GetTempRange(pParse, nConstraint+2);
    addrNotFound = pLevel->addrBrk;
    for(j=0; j<nConstraint; j++){
      int iTarget = iReg+j+2;
      pTerm = pLoop->aLTerm[j];
      if( pTerm==0 ) continue;
      if( pTerm->eOperator & WO_IN ){
        codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
        addrNotFound = pLevel->addrNxt;
      }else{
        sqlite4ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
      }
    }
    sqlite4VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
    sqlite4VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1);
    sqlite4VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg,
                      pLoop->u.vtab.idxStr,
                      pLoop->u.vtab.needFree ? P4_DYNAMIC : P4_STATIC);
    pLoop->u.vtab.needFree = 0;
    for(j=0; j<nConstraint && j<16; j++){
      if( (pLoop->u.vtab.omitMask>>j)&1 ){
        disableTerm(pLevel, pLoop->aLTerm[j]);
      }
    }
    pLevel->op = OP_VNext;
    pLevel->p1 = iCur;
    pLevel->p2 = sqlite4VdbeCurrentAddr(v);
    sqlite4ReleaseTempRange(pParse, iReg, nConstraint+2);
    sqlite4ExprCachePop(pParse, 1);
  }else
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

  if( pLoop->wsFlags & WHERE_INDEXED ){
    /* Case 4: A scan using an index.
    **
    **         The WHERE clause may contain zero or more equality 
    **         terms ("==" or "IN" operators) that refer to the N
    **         left-most columns of the index. It may also contain
    **         inequality constraints (>, <, >= or <=) on the indexed
    **         column that immediately follows the N equalities. Only 
    **         the right-most column can be an inequality - the rest must
    **         use the "==" and "IN" operators. For example, if the 
    **         index is on (x,y,z), then the following clauses are all 
    **         optimized:
    **
    **            x=5
    **            x=5 AND y=10
    **            x=5 AND y<10
    **            x=5 AND y>5 AND y<10
    **            x=5 AND y=5 AND z<=10
    **
    **         The z<10 term of the following cannot be used, only
    **         the x=5 term:
    **
    **            x=5 AND z<10
    **
    **         N may be zero if there are inequality constraints.
    **         If there are no inequality constraints, then N is at
    **         least one.
    **
    **         This case is also used when there are no WHERE clause
    **         constraints but an index is selected anyway, in order
    **         to force the output order to conform to an ORDER BY.
    */  
    static const u8 aStartOp[] = {
      0,
      0,
      OP_Rewind,           /* 2: (!start_constraints && startEq &&  !bRev) */
      OP_Last,             /* 3: (!start_constraints && startEq &&   bRev) */
      OP_SeekGt,           /* 4: (start_constraints  && !startEq && !bRev) */
      OP_SeekLt,           /* 5: (start_constraints  && !startEq &&  bRev) */
      OP_SeekGe,           /* 6: (start_constraints  &&  startEq && !bRev) */
      OP_SeekLe            /* 7: (start_constraints  &&  startEq &&  bRev) */
    };
    static const u8 aEndOp[] = {
      OP_Noop,             /* 0: (!end_constraints) */
      OP_IdxGE,            /* 1: (end_constraints && !endEq && !bRev) */
      OP_IdxLE,            /* 2: (end_constraints && !endEq &&  bRev) */
      OP_IdxGT,            /* 3: (end_constraints &&  endEq && !bRev) */
      OP_IdxLT             /* 4: (end_constraints &&  endEq &&  bRev) */
    };

    int nEq = pLoop->u.btree.nEq;  /* Number of == or IN terms */
    int isMinQuery = 0;            /* If this is an optimized SELECT min(x).. */
    int regBase;                 /* Base register holding constraint values */
    int r1;                      /* Temp register */
    WhereTerm *pRangeStart = 0;  /* Inequality constraint at range start */
    WhereTerm *pRangeEnd = 0;    /* Inequality constraint at range end */
    int startEq;                 /* True if range start uses ==, >= or <= */
    int endEq;                   /* True if range end uses ==, >= or <= */
    int start_constraints;       /* Start of range is constrained */
    int nConstraint;             /* Number of constraint terms */
    Index *pIdx;                 /* The index we will be using */
    int iIdxCur;                 /* The VDBE cursor for the index */
    int nExtraReg = 0;           /* Number of extra registers needed */
    int op;                      /* Instruction opcode */
    char *zStartAff;             /* Affinity for start of range constraint */
    char *zEndAff;               /* Affinity for end of range constraint */
    int regEndKey;               /* Register for end-key */
    int iIneq;                   /* The table column subject to inequality */
    Index *pPk;                  /* Primary key index on same table as pIdx */

    pIdx = pLoop->u.btree.pIndex;
    pPk = sqlite4FindPrimaryKey(pIdx->pTable, 0);
    iIneq = idxColumnNumber(pIdx, pPk, nEq);
    iIdxCur = pLevel->iIdxCur;
    assert( iCur==pLevel->iTabCur );

    /* If this loop satisfies a sort order (pOrderBy) request that 
    ** was passed to this function to implement a "SELECT min(x) ..." 
    ** query, then the caller will only allow the loop to run for
    ** a single iteration. This means that the first row returned
    ** should not have a NULL value stored in 'x'. If column 'x' is
    ** the first one after the nEq equality constraints in the index,
    ** this requires some special handling.
    */
    if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
     && (pWInfo->bOBSat!=0)
     && (pIdx->nColumn>nEq)
    ){
      /* assert( pOrderBy->nExpr==1 ); */
      /* assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); */
      isMinQuery = 1;
      nExtraReg = 1;
    }

    /* Find any inequality constraint terms for the start and end 
    ** of the range. 
    */
    j = nEq;
    if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
      pRangeStart = pLoop->aLTerm[j++];
      nExtraReg = 1;
    }
    if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
      pRangeEnd = pLoop->aLTerm[j++];
      nExtraReg = 1;
    }

    /* Generate code to evaluate all constraint terms using == or IN
    ** and store the values of those terms in an array of registers
    ** starting at regBase.
    */
    regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
    assert( (regBase+nEq+nExtraReg-1)<=pParse->nMem );
    zEndAff = sqlite4DbStrDup(pParse->db, zStartAff);
    addrNxt = pLevel->addrNxt;

    /* If we are doing a reverse order scan on an ascending index, or
    ** a forward order scan on a descending index, interchange the 
    ** start and end terms (pRangeStart and pRangeEnd).
    */
    if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE4_SO_ASC))
     || (bRev && pIdx->nColumn==nEq)
    ){
      SWAP(WhereTerm *, pRangeEnd, pRangeStart);
    }

    testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
    testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
    testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 );
    testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 );
    startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE);
    endEq =   !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE);
    start_constraints = pRangeStart || nEq>0;

    /* Seek the index cursor to the start of the range. */
    nConstraint = nEq;
    if( pRangeStart ){
      Expr *pRight = pRangeStart->pExpr->pRight;
      sqlite4ExprCode(pParse, pRight, regBase+nEq);
      if( (pRangeStart->wtFlags & TERM_VNULL)==0 ){
        sqlite4ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
      }
      if( zStartAff ){
        if( sqlite4CompareAffinity(pRight, zStartAff[nEq])==SQLITE4_AFF_NONE){
          /* Since the comparison is to be performed with no conversions
          ** applied to the operands, set the affinity to apply to pRight to 
          ** SQLITE4_AFF_NONE.  */
          zStartAff[nEq] = SQLITE4_AFF_NONE;
        }
        if( sqlite4ExprNeedsNoAffinityChange(pRight, zStartAff[nEq]) ){
          zStartAff[nEq] = SQLITE4_AFF_NONE;
        }
      }  
      nConstraint++;
      testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
    }else if( isMinQuery ){
      sqlite4VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
      nConstraint++;
      startEq = 0;
      start_constraints = 1;
    }
    codeApplyAffinity(pParse, regBase, nConstraint, zStartAff);
    op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
    assert( op!=0 );
    testcase( op==OP_Rewind );
    testcase( op==OP_Last );
    testcase( op==OP_SeekGt );
    testcase( op==OP_SeekGe );
    testcase( op==OP_SeekLe );
    testcase( op==OP_SeekLt );
    sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);

    /* Set variable op to the instruction required to determine if the
    ** cursor is passed the end of the range. If the range is unbounded,
    ** then set op to OP_Noop. Nothing to do in this case.  */
    assert( (endEq==0 || endEq==1) );
    op = aEndOp[(pRangeEnd || nEq) * (1 + (endEq+endEq) + bRev)];
    testcase( op==OP_Noop );
    testcase( op==OP_IdxGE );
    testcase( op==OP_IdxLT );
    testcase( op==OP_IdxLE );
    testcase( op==OP_IdxGT );

    if( op!=OP_Noop ){
      /* Load the value for the inequality constraint at the end of the
      ** range (if any).
      */
      nConstraint = nEq;
      if( pRangeEnd ){
        Expr *pRight = pRangeEnd->pExpr->pRight;
        sqlite4ExprCacheRemove(pParse, regBase+nEq, 1);
        sqlite4ExprCode(pParse, pRight, regBase+nEq);
        if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){
          sqlite4ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
        }
        if( zEndAff ){
          if( sqlite4CompareAffinity(pRight, zEndAff[nEq])==SQLITE4_AFF_NONE){
            /* Since the comparison is to be performed with no conversions
            ** applied to the operands, set the affinity to apply to pRight to 
            ** SQLITE4_AFF_NONE.  */
            zEndAff[nEq] = SQLITE4_AFF_NONE;
          }
          if( sqlite4ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){
            zEndAff[nEq] = SQLITE4_AFF_NONE;
          }
        }  
        codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
        nConstraint++;
        testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
      }

      /* Now compute an end-key using OP_MakeKey */
      regEndKey = ++pParse->nMem;
      if( pIdx->tnum==KVSTORE_ROOT ){
        sqlite4VdbeAddOp2(v, OP_Copy, regBase, regEndKey);
        sqlite4VdbeAddOp1(v, OP_ToBlob, regEndKey);
      }else{
        sqlite4VdbeAddOp4Int(v, OP_MakeKey, regBase, nConstraint, regEndKey,
                                iIdxCur);
      }
    }

    sqlite4DbFree(pParse->db, zStartAff);
    sqlite4DbFree(pParse->db, zEndAff);

    /* Top of the loop body */
    pLevel->p2 = sqlite4VdbeCurrentAddr(v);

    if( op!=OP_Noop ){
      sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regEndKey, nConstraint);
    }

    /* Seek the PK cursor, if required */
    disableTerm(pLevel, pRangeStart);
    disableTerm(pLevel, pRangeEnd);
    if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY
     && pIdx->eIndexType!=SQLITE4_INDEX_TEMP
     && 0==(pLoop->wsFlags & WHERE_IDX_ONLY)
    ){
      sqlite4VdbeAddOp3(v, OP_SeekPk, iCur, 0, iIdxCur);
    }

    /* If there are inequality constraints, check that the value
    ** of the table column that the inequality contrains is not NULL.
    ** If it is, jump to the next iteration of the loop.
    */
    r1 = sqlite4GetTempReg(pParse);
    testcase( pLoop->wsFlags & WHERE_BTM_LIMIT );
    testcase( pLoop->wsFlags & WHERE_TOP_LIMIT );
    if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){
      sqlite4ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iIneq, r1);
      sqlite4VdbeAddOp2(v, OP_IsNull, r1, addrCont);
    }
    sqlite4ReleaseTempReg(pParse, r1);

    /* Record the instruction used to terminate the loop. Disable 
    ** WHERE clause terms made redundant by the index range scan.
    */
    if( pLoop->wsFlags & WHERE_ONEROW ){
      pLevel->op = OP_Noop;
    }else if( bRev ){
      pLevel->op = OP_Prev;
    }else{
      pLevel->op = OP_Next;
    }
    pLevel->p1 = iIdxCur;
    if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
      pLevel->p5 = SQLITE4_STMTSTATUS_FULLSCAN_STEP;
    }else{
      assert( pLevel->p5==0 );
    }
  }else

#ifndef SQLITE4_OMIT_OR_OPTIMIZATION
  if( pLoop->wsFlags & WHERE_MULTI_OR ){
    /* Case 5:  Two or more separately indexed terms connected by OR
    **
    ** Example:
    **
    **   CREATE TABLE t1(a,b,c,d);
    **   CREATE INDEX i1 ON t1(a);
    **   CREATE INDEX i2 ON t1(b);
    **   CREATE INDEX i3 ON t1(c);
    **
    **   SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13)
    **
    ** In the example, there are three indexed terms connected by OR.
    ** The top of the loop looks like this:
    **
    **          Null       1                # Zero the rowset in reg 1
    **
    ** Then, for each indexed term, the following. The arguments to
    ** RowSetTest are such that the rowid of the current row is inserted
    ** into the RowSet. If it is already present, control skips the
    ** Gosub opcode and jumps straight to the code generated by WhereEnd().
    **
    **        sqlite4WhereBegin(<term>)
    **          RowSetTest                  # Insert rowid into rowset
    **          Gosub      2 A
    **        sqlite4WhereEnd()
    **
    ** Following the above, code to terminate the loop. Label A, the target
    ** of the Gosub above, jumps to the instruction right after the Goto.
    **
    **          Null       1                # Zero the rowset in reg 1
    **          Goto       B                # The loop is finished.
    **
    **       A: <loop body>                 # Return data, whatever.
    **
    **          Return     2                # Jump back to the Gosub
    **
    **       B: <after the loop>
    **
    */
    WhereClause *pOrWc;    /* The OR-clause broken out into subterms */
    SrcList *pOrTab;       /* Shortened table list or OR-clause generation */
    Index *pCov = 0;             /* Potential covering index (or NULL) */
    int iCovCur = pParse->nTab++;  /* Cursor used for index scans (if any) */

    int regReturn = ++pParse->nMem;           /* Register used with OP_Gosub */
    int regKeyset = 0;                        /* Register for RowSet object */
    int regKey = 0;                           /* Register holding key */
    int iLoopBody = sqlite4VdbeMakeLabel(v);  /* Start of loop body */
    int iRetInit;                             /* Address of regReturn init */
    int untestedTerms = 0;             /* Some terms not completely tested */
    int ii;                            /* Loop counter */
    Expr *pAndExpr = 0;                /* An ".. AND (...)" expression */
   
    pTerm = pLoop->aLTerm[0];
    assert( pTerm!=0 );
    assert( pTerm->eOperator & WO_OR );
    assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
    pOrWc = &pTerm->u.pOrInfo->wc;
    pLevel->op = OP_Return;
    pLevel->p1 = regReturn;

    /* Set up a new SrcList in pOrTab containing the table being scanned
    ** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
    ** This becomes the SrcList in the recursive call to sqlite4WhereBegin().
    */
    if( pWInfo->nLevel>1 ){
      int nNotReady;                 /* The number of notReady tables */
      struct SrcListItem *origSrc;     /* Original list of tables */
      nNotReady = pWInfo->nLevel - iLevel - 1;
      pOrTab = sqlite4StackAllocRaw(pParse->db,
                            sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
      if( pOrTab==0 ) return notReady;
      pOrTab->nAlloc = (u8)(nNotReady + 1);
      pOrTab->nSrc = pOrTab->nAlloc;
      memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem));
      origSrc = pWInfo->pTabList->a;
      for(k=1; k<=nNotReady; k++){
        memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k]));
      }
    }else{
      pOrTab = pWInfo->pTabList;
    }

    /* Initialize the keyset register to contain NULL. An SQL NULL is 
    ** equivalent to an empty keyset.
    **
    ** Also initialize regReturn to contain the address of the instruction 
    ** immediately following the OP_Return at the bottom of the loop. This
    ** is required in a few obscure LEFT JOIN cases where control jumps
    ** over the top of the loop into the body of it. In this case the 
    ** correct response for the end-of-loop code (the OP_Return) is to 
    ** fall through to the next instruction, just as an OP_Next does if
    ** called on an uninitialized cursor.
    */
    if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
      regKeyset = ++pParse->nMem;
      regKey = ++pParse->nMem;
      sqlite4VdbeAddOp2(v, OP_Null, 0, regKeyset);
    }
    iRetInit = sqlite4VdbeAddOp2(v, OP_Integer, 0, regReturn);

    /* If the original WHERE clause is z of the form:  (x1 OR x2 OR ...) AND y
    ** Then for every term xN, evaluate as the subexpression: xN AND z
    ** That way, terms in y that are factored into the disjunction will
    ** be picked up by the recursive calls to sqlite4WhereBegin() below.
    **
    ** Actually, each subexpression is converted to "xN AND w" where w is
    ** the "interesting" terms of z - terms that did not originate in the
    ** ON or USING clause of a LEFT JOIN, and terms that are usable as 
    ** indices.
    **
    ** This optimization also only applies if the (x1 OR x2 OR ...) term
    ** is not contained in the ON clause of a LEFT JOIN.
    ** See ticket http://www.sqlite.org/src/info/f2369304e4
    */
    if( pWC->nTerm>1 ){
      int iTerm;
      for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
        Expr *pExpr = pWC->a[iTerm].pExpr;
        if( &pWC->a[iTerm] == pTerm ) continue;
        if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
        if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
        if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
        pExpr = sqlite4ExprDup(pParse->db, pExpr, 0);
        pAndExpr = sqlite4ExprAnd(pParse->db, pAndExpr, pExpr);
      }
      if( pAndExpr ){
        pAndExpr = sqlite4PExpr(pParse, TK_AND, 0, pAndExpr, 0);
      }
    }

    for(ii=0; ii<pOrWc->nTerm; ii++){
      WhereTerm *pOrTerm = &pOrWc->a[ii];
      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
        WhereInfo *pSubWInfo;          /* Info for single OR-term scan */
        Expr *pOrExpr = pOrTerm->pExpr;
        if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
          pAndExpr->pLeft = pOrExpr;
          pOrExpr = pAndExpr;
        }
        /* Loop through table entries that match term pOrTerm. */
        pSubWInfo = sqlite4WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
                        WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
                        WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
        assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
        if( pSubWInfo ){
          WhereLoop *pSubLoop;
          explainOneScan(
              pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
          );
          if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
            int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
            sqlite4VdbeAddOp2(v, OP_RowKey, iCur, regKey);
            sqlite4VdbeAddOp4Int(v, OP_RowSetTest, regKeyset,
                                 sqlite4VdbeCurrentAddr(v)+2, regKey, iSet);
          }
          sqlite4VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);

          /* The pSubWInfo->untestedTerms flag means that this OR term
          ** contained one or more AND term from a notReady table.  The
          ** terms from the notReady table could not be tested and will
          ** need to be tested later.
          */
          if( pSubWInfo->untestedTerms ) untestedTerms = 1;

          /* If all of the OR-connected terms are optimized using the same
          ** index, and the index is opened using the same cursor number
          ** by each call to sqlite4WhereBegin() made by this loop, it may
          ** be possible to use that index as a covering index.
          **
          ** If the call to sqlite4WhereBegin() above resulted in a scan that
          ** uses an index, and this is either the first OR-connected term
          ** processed or the index is the same as that used by all previous
          ** terms, set pCov to the candidate covering index. Otherwise, set 
          ** pCov to NULL to indicate that no candidate covering index will 
          ** be available.
          */
          pSubLoop = pSubWInfo->a[0].pWLoop;
          assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
          if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
           && (ii==0 || pSubLoop->u.btree.pIndex==pCov)
          ){
            pCov = pSubLoop->u.btree.pIndex;
            assert( pCov->eIndexType==SQLITE4_INDEX_PRIMARYKEY 
                 || pSubWInfo->a[0].iIdxCur==iCovCur 
            );
          }else{
            pCov = 0;
          }

          /* Finish the loop through table entries that match term pOrTerm. */
          sqlite4WhereEnd(pSubWInfo);
        }
      }
    }
    assert( pLevel->u.pCovidx==0 );
    if( pCov && pCov->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){
      pLevel->iIdxCur = iCovCur;
      pLevel->u.pCovidx = pCov;
    }
    if( pAndExpr ){
      pAndExpr->pLeft = 0;
      sqlite4ExprDelete(pParse->db, pAndExpr);
    }
    sqlite4VdbeChangeP1(v, iRetInit, sqlite4VdbeCurrentAddr(v));
    sqlite4VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
    sqlite4VdbeResolveLabel(v, iLoopBody);

    if( pWInfo->nLevel>1 ) sqlite4StackFree(pParse->db, pOrTab);
    if( !untestedTerms ) disableTerm(pLevel, pTerm);
  }else
#endif /* SQLITE4_OMIT_OR_OPTIMIZATION */

  {
    /* Case 6:  There is no usable index.  We must do a complete
    **          scan of the entire table. This comes up when scanning
    **          through b-trees containing materialized sub-queries or 
    **          views.
    */
    static const u8 aStep[] = { OP_Next, OP_Prev };
    static const u8 aStart[] = { OP_Rewind, OP_Last };
    assert( bRev==0 || bRev==1 );
    pLevel->op = aStep[bRev];
    pLevel->p1 = iCur;
    pLevel->p2 = 1 + sqlite4VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
    pLevel->p5 = SQLITE4_STMTSTATUS_FULLSCAN_STEP;
  }
  newNotReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur);

  /* Insert code to test every subexpression that can be completely
  ** computed using the current set of tables.
  **
  ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
  ** the use of indices become tests that are evaluated against each row of
  ** the relevant input tables.
  */
  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
    Expr *pE;
    testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
    testcase( pTerm->wtFlags & TERM_CODED );
    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
    if( (pTerm->prereqAll & newNotReady)!=0 ){
      testcase( pWInfo->untestedTerms==0
               && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 );
      pWInfo->untestedTerms = 1;
      continue;
    }
    pE = pTerm->pExpr;
    assert( pE!=0 );
    if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
      continue;
    }
    sqlite4ExprIfFalse(pParse, pE, addrCont, SQLITE4_JUMPIFNULL);
    pTerm->wtFlags |= TERM_CODED;
  }

  /* Insert code to test for implied constraints based on transitivity
  ** of the "==" operator.
  **
  ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123"
  ** and we are coding the t1 loop and the t2 loop has not yet coded,
  ** then we cannot use the "t1.a=t2.b" constraint, but we can code
  ** the implied "t1.a=123" constraint.
  */
  for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
    Expr *pE;
    WhereTerm *pAlt;
    Expr sEq;
    if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
    if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue;
    if( pTerm->leftCursor!=iCur ) continue;
    if( pLevel->iLeftJoin ) continue;
    pE = pTerm->pExpr;
    assert( !ExprHasProperty(pE, EP_FromJoin) );
    assert( (pTerm->prereqRight & newNotReady)!=0 );
    pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0);
    if( pAlt==0 ) continue;
    if( pAlt->wtFlags & (TERM_CODED) ) continue;
    testcase( pAlt->eOperator & WO_EQ );
    testcase( pAlt->eOperator & WO_IN );
    VdbeNoopComment((v, "begin transitive constraint"));
    sEq = *pAlt->pExpr;
    sEq.pLeft = pE->pLeft;
    sqlite4ExprIfFalse(pParse, &sEq, addrCont, SQLITE4_JUMPIFNULL);
  }

  /* For a LEFT OUTER JOIN, generate code that will record the fact that
  ** at least one row of the right table has matched the left table.  
  */
  if( pLevel->iLeftJoin ){
    pLevel->addrFirst = sqlite4VdbeCurrentAddr(v);
    sqlite4VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
    VdbeComment((v, "record LEFT JOIN hit"));
    sqlite4ExprCacheClear(pParse);
    for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
      testcase( pTerm->wtFlags & TERM_VIRTUAL );  /* IMP: R-30575-11662 */
      testcase( pTerm->wtFlags & TERM_CODED );
      if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
      if( (pTerm->prereqAll & newNotReady)!=0 ){
        assert( pWInfo->untestedTerms );
        continue;
      }
      assert( pTerm->pExpr );
      sqlite4ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE4_JUMPIFNULL);
      pTerm->wtFlags |= TERM_CODED;
    }
  }
  sqlite4ReleaseTempReg(pParse, iReleaseReg);

  return newNotReady;
}

#ifdef WHERETRACE_ENABLED
/*
** Print a WhereLoop object for debugging purposes
*/
static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
  int nb = 1+(pTabList->nSrc+7)/8;
  struct SrcListItem *pItem = pTabList->a + p->iTab;
  Table *pTab = pItem->pTab;
  sqlite4DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
                     p->iTab, nb, p->maskSelf, nb, p->prereq);
  sqlite4DebugPrintf(" %12s",
                     pItem->zAlias ? pItem->zAlias : pTab->zName);
  if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
    if( p->u.btree.pIndex ){
      const char *zName = p->u.btree.pIndex->zName;
      if( zName==0 ) zName = "ipk";
      if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){
        int i = sqlite4Strlen30(zName) - 1;
        while( zName[i]!='_' ) i--;
        zName += i;
      }
      sqlite4DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq);
    }else{
      sqlite4DebugPrintf("%20s","");
    }
  }else{
    char *z;
    if( p->u.vtab.idxStr ){
      z = sqlite4_mprintf(0, "(%d,\"%s\",%x)",
                p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
    }else{
      z = sqlite4_mprintf(0, "(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
    }
    sqlite4DebugPrintf(" %-19s", z);
    sqlite4_free(0, z);
  }
  sqlite4DebugPrintf(" f %04x N %d", p->wsFlags, p->nLTerm);
  sqlite4DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
}
#endif

/*
** Convert bulk memory into a valid WhereLoop that can be passed
** to whereLoopClear harmlessly.
*/
static void whereLoopInit(WhereLoop *p){
  p->aLTerm = p->aLTermSpace;
  p->nLTerm = 0;
  p->nLSlot = ArraySize(p->aLTermSpace);
  p->wsFlags = 0;
}

/*
** Clear the WhereLoop.u union.  Leave WhereLoop.pLTerm intact.
*/
static void whereLoopClearUnion(sqlite4 *db, WhereLoop *p){
  if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){
    if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){
#if 0
      sqlite4_free(p->u.vtab.idxStr);
#endif
      p->u.vtab.needFree = 0;
      p->u.vtab.idxStr = 0;
    }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
      sqlite4DbFree(db, p->u.btree.pIndex->zColAff);
      sqlite4DbFree(db, p->u.btree.pIndex);
      p->u.btree.pIndex = 0;
    }
  }
}

/*
** Deallocate internal memory used by a WhereLoop object
*/
static void whereLoopClear(sqlite4 *db, WhereLoop *p){
  if( p->aLTerm!=p->aLTermSpace ) sqlite4DbFree(db, p->aLTerm);
  whereLoopClearUnion(db, p);
  whereLoopInit(p);
}

/*
** Increase the memory allocation for pLoop->aLTerm[] to be at least n.
*/
static int whereLoopResize(sqlite4 *db, WhereLoop *p, int n){
  WhereTerm **paNew;
  if( p->nLSlot>=n ) return SQLITE4_OK;
  n = (n+7)&~7;
  paNew = sqlite4DbMallocRaw(db, sizeof(p->aLTerm[0])*n);
  if( paNew==0 ) return SQLITE4_NOMEM;
  memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot);
  if( p->aLTerm!=p->aLTermSpace ) sqlite4DbFree(db, p->aLTerm);
  p->aLTerm = paNew;
  p->nLSlot = n;
  return SQLITE4_OK;
}

/*
** Transfer content from the second pLoop into the first.
*/
static int whereLoopXfer(sqlite4 *db, WhereLoop *pTo, WhereLoop *pFrom){
  if( whereLoopResize(db, pTo, pFrom->nLTerm) ) return SQLITE4_NOMEM;
  whereLoopClearUnion(db, pTo);
  memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
  memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0]));
  if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){
    pFrom->u.vtab.needFree = 0;
  }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){
    pFrom->u.btree.pIndex = 0;
  }
  return SQLITE4_OK;
}

/*
** Delete a WhereLoop object
*/
static void whereLoopDelete(sqlite4 *db, WhereLoop *p){
  whereLoopClear(db, p);
  sqlite4DbFree(db, p);
}

/*
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite4 *db, WhereInfo *pWInfo){
  if( ALWAYS(pWInfo) ){
    whereClauseClear(&pWInfo->sWC);
    while( pWInfo->pLoops ){
      WhereLoop *p = pWInfo->pLoops;
      pWInfo->pLoops = p->pNextLoop;
      whereLoopDelete(db, p);
    }
    sqlite4DbFree(db, pWInfo);
  }
}

/*
** Insert or replace a WhereLoop entry using the template supplied.
**
** An existing WhereLoop entry might be overwritten if the new template
** is better and has fewer dependencies.  Or the template will be ignored
** and no insert will occur if an existing WhereLoop is faster and has
** fewer dependencies than the template.  Otherwise a new WhereLoop is
** added based on the template.
**
** If pBuilder->pOrSet is not NULL then we only care about only the
** prerequisites and rRun and nOut costs of the N best loops.  That
** information is gathered in the pBuilder->pOrSet object.  This special
** processing mode is used only for OR clause processing.
**
** When accumulating multiple loops (when pBuilder->pOrSet is NULL) we
** still might overwrite similar loops with the new template if the
** template is better.  Loops may be overwritten if the following 
** conditions are met:
**
**    (1)  They have the same iTab.
**    (2)  They have the same iSortIdx.
**    (3)  The template has same or fewer dependencies than the current loop
**    (4)  The template has the same or lower cost than the current loop
**    (5)  The template uses more terms of the same index but has no additional
**         dependencies          
*/
static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
  WhereLoop **ppPrev, *p, *pNext = 0;
  WhereInfo *pWInfo = pBuilder->pWInfo;
  sqlite4 *db = pWInfo->pParse->db;

  assert( pTemplate->u.btree.pIndex || !(pTemplate->wsFlags & WHERE_INDEXED) );

  /* If pBuilder->pOrSet is defined, then only keep track of the costs
  ** and prereqs.
  */
  if( pBuilder->pOrSet!=0 ){
#if WHERETRACE_ENABLED
    u16 n = pBuilder->pOrSet->n;
    int x =
#endif
    whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
                                    pTemplate->nOut);
#if WHERETRACE_ENABLED
    if( sqlite4WhereTrace & 0x8 ){

      sqlite4DebugPrintf(x?"   or-%d:  ":"   or-X:  ", n);
      whereLoopPrint(pTemplate, pWInfo->pTabList);
    }
#endif
    return SQLITE4_OK;
  }

  /* Search for an existing WhereLoop to overwrite, or which takes
  ** priority over pTemplate.
  */
  for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){
    if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){
      /* If either the iTab or iSortIdx values for two WhereLoop are different
      ** then those WhereLoops need to be considered separately.  Neither is
      ** a candidate to replace the other. */
      continue;
    }
    /* In the current implementation, the rSetup value is either zero
    ** or the cost of building an automatic index (NlogN) and the NlogN
    ** is the same for compatible WhereLoops. */
    assert( p->rSetup==0 || pTemplate->rSetup==0 
                 || p->rSetup==pTemplate->rSetup );

    /* whereLoopAddBtree() always generates and inserts the automatic index
    ** case first.  Hence compatible candidate WhereLoops never have a larger
    ** rSetup. Call this SETUP-INVARIANT */
    assert( p->rSetup>=pTemplate->rSetup );

    if( (p->prereq & pTemplate->prereq)==p->prereq
     && p->rSetup<=pTemplate->rSetup
     && p->rRun<=pTemplate->rRun
    ){
      /* This branch taken when p is equal or better than pTemplate in 
      ** all of (1) dependences (2) setup-cost, and (3) run-cost. */
      assert( p->rSetup==pTemplate->rSetup );
      if( p->nLTerm<pTemplate->nLTerm
       && (p->wsFlags & WHERE_INDEXED)!=0
       && (pTemplate->wsFlags & WHERE_INDEXED)!=0
       && p->u.btree.pIndex==pTemplate->u.btree.pIndex
       && p->prereq==pTemplate->prereq
      ){
        /* Overwrite an existing WhereLoop with an similar one that uses
        ** more terms of the index */
        pNext = p->pNextLoop;
        break;
      }else{
        /* pTemplate is not helpful.
        ** Return without changing or adding anything */
        goto whereLoopInsert_noop;
      }
    }
    if( (p->prereq & pTemplate->prereq)==pTemplate->prereq
     && p->rRun>=pTemplate->rRun
     && ALWAYS(p->rSetup>=pTemplate->rSetup) /* See SETUP-INVARIANT above */
    ){
      /* Overwrite an existing WhereLoop with a better one: one that is
      ** better at one of (1) dependences, (2) setup-cost, or (3) run-cost
      ** and is no worse in any of those categories. */
      pNext = p->pNextLoop;
      break;
    }
  }

  /* If we reach this point it means that either p[] should be overwritten
  ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
  ** WhereLoop and insert it.
  */
#if WHERETRACE_ENABLED
  if( sqlite4WhereTrace & 0x8 ){
    if( p!=0 ){
      sqlite4DebugPrintf("ins-del:  ");
      whereLoopPrint(p, pWInfo->pTabList);
    }
    sqlite4DebugPrintf("ins-new:  ");
    whereLoopPrint(pTemplate, pWInfo->pTabList);
  }
#endif
  if( p==0 ){
    p = sqlite4DbMallocRaw(db, sizeof(WhereLoop));
    if( p==0 ) return SQLITE4_NOMEM;
    whereLoopInit(p);
  }
  whereLoopXfer(db, p, pTemplate);
  p->pNextLoop = pNext;
  *ppPrev = p;
  if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
    Index *pIndex = p->u.btree.pIndex;
    if( pIndex && pIndex->tnum==0 ){
      p->u.btree.pIndex = 0;
    }
  }
  return SQLITE4_OK;

  /* Jump here if the insert is a no-op */
whereLoopInsert_noop:
#if WHERETRACE_ENABLED
  if( sqlite4WhereTrace & 0x8 ){
    sqlite4DebugPrintf("ins-noop: ");
    whereLoopPrint(pTemplate, pWInfo->pTabList);
  }
#endif
  return SQLITE4_OK;  
}


/*
** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex.
** Try to match one more.
*/
static int whereLoopAddBtreeIndex(
  WhereLoopBuilder *pBuilder,     /* The WhereLoop factory */
  struct SrcListItem *pSrc,      /* FROM clause term being analyzed */
  Index *pProbe,                  /* An index on pSrc */
  WhereCost nInMul                /* log(Number of iterations due to IN) */
){
  WhereInfo *pWInfo = pBuilder->pWInfo;  /* WHERE analyse context */
  Parse *pParse = pWInfo->pParse;        /* Parsing context */
  sqlite4 *db = pParse->db;       /* Database connection malloc context */
  WhereLoop *pNew;                /* Template WhereLoop under construction */
  WhereTerm *pTerm;               /* A WhereTerm under consideration */
  int opMask;                     /* Valid operators for constraints */
  WhereScan scan;                 /* Iterator for WHERE terms */
  Bitmask saved_prereq;           /* Original value of pNew->prereq */
  u16 saved_nLTerm;               /* Original value of pNew->nLTerm */
  int saved_nEq;                  /* Original value of pNew->u.btree.nEq */
  u32 saved_wsFlags;              /* Original value of pNew->wsFlags */
  WhereCost saved_nOut;           /* Original value of pNew->nOut */
  int iCol;                       /* Index of the column in the table */
  int rc = SQLITE4_OK;             /* Return code */
  WhereCost nRowEst;              /* Estimated index selectivity */
  WhereCost rLogSize;             /* Logarithm of table size */
  WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */

  assert( pProbe->eIndexType==SQLITE4_INDEX_USER
       || pProbe->eIndexType==SQLITE4_INDEX_UNIQUE
       || pProbe->eIndexType==SQLITE4_INDEX_PRIMARYKEY
  );

  pNew = pBuilder->pNew;
  if( db->mallocFailed ) return SQLITE4_NOMEM;

  assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
  assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
  if( pNew->wsFlags & WHERE_BTM_LIMIT ){
    opMask = WO_LT|WO_LE;
  }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){
    opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE;
  }else{
    opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE;
  }
  if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);

  if( pNew->u.btree.nEq < pProbe->nColumn ){
    iCol = pProbe->aiColumn[pNew->u.btree.nEq];
    nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
    if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
  }else if( pProbe->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){
    Index *pPk;
    pPk = sqlite4FindPrimaryKey(pProbe->pTable, 0);
    iCol = idxColumnNumber(pProbe, pPk, pNew->u.btree.nEq);
    nRowEst = 0;
  }else{
    return SQLITE4_OK;
  }
  assert( iCol>=-1 );
  pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol,
                        opMask, pProbe);
  saved_nEq = pNew->u.btree.nEq;
  saved_nLTerm = pNew->nLTerm;
  saved_wsFlags = pNew->wsFlags;
  saved_prereq = pNew->prereq;
  saved_nOut = pNew->nOut;
  pNew->rSetup = 0;
  rLogSize = estLog(whereCost(pProbe->aiRowEst[0]));
  for(; rc==SQLITE4_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
    int nIn = 0;
    if( pTerm->prereqRight & pNew->maskSelf ) continue;
#ifdef SQLITE4_ENABLE_STAT3
    if( (pTerm->wtFlags & TERM_VNULL)!=0 && pSrc->pTab->aCol[iCol].notNull ){
      continue; /* skip IS NOT NULL constraints on a NOT NULL column */
    }
#endif
    pNew->wsFlags = saved_wsFlags;
    pNew->u.btree.nEq = saved_nEq;
    pNew->nLTerm = saved_nLTerm;
    if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
    pNew->aLTerm[pNew->nLTerm++] = pTerm;
    pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;
    pNew->rRun = rLogSize; /* Baseline cost is log2(N).  Adjustments below */
    if( pTerm->eOperator & WO_IN ){
      Expr *pExpr = pTerm->pExpr;
      pNew->wsFlags |= WHERE_COLUMN_IN;
      if( ExprHasProperty(pExpr, EP_xIsSelect) ){
        /* "x IN (SELECT ...)":  TUNING: the SELECT returns 25 rows */
        nIn = 46;  assert( 46==whereCost(25) );
      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
        /* "x IN (value, value, ...)" */
        nIn = whereCost(pExpr->x.pList->nExpr);
      }
      pNew->rRun += nIn;
      pNew->u.btree.nEq++;
      pNew->nOut = nRowEst + nInMul + nIn;
    }else if( pTerm->eOperator & (WO_EQ) ){
      assert( (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0
                  || nInMul==0 );
      pNew->wsFlags |= WHERE_COLUMN_EQ;
      if( iCol<0  
       || (pProbe->onError!=OE_None && nInMul==0
           && pNew->u.btree.nEq==pProbe->nColumn-1)
      ){
        assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 );
        pNew->wsFlags |= WHERE_ONEROW;
      }
      pNew->u.btree.nEq++;
      pNew->nOut = nRowEst + nInMul;
    }else if( pTerm->eOperator & (WO_ISNULL) ){
      pNew->wsFlags |= WHERE_COLUMN_NULL;
      pNew->u.btree.nEq++;
      /* TUNING: IS NULL selects 2 rows */
      nIn = 10;  assert( 10==whereCost(2) );
      pNew->nOut = nRowEst + nInMul + nIn;
    }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
      testcase( pTerm->eOperator & WO_GT );
      testcase( pTerm->eOperator & WO_GE );
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
      pBtm = pTerm;
      pTop = 0;
    }else{
      assert( pTerm->eOperator & (WO_LT|WO_LE) );
      testcase( pTerm->eOperator & WO_LT );
      testcase( pTerm->eOperator & WO_LE );
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
      pTop = pTerm;
      pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ?
                     pNew->aLTerm[pNew->nLTerm-2] : 0;
    }
    if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
      /* Adjust nOut and rRun for STAT3 range values */
      WhereCost rDiv;
      whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq,
                        pBtm, pTop, &rDiv);
      pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10;
    }
#ifdef SQLITE4_ENABLE_STAT3
    if( pNew->u.btree.nEq==1 && pProbe->nSample
     &&  OptimizationEnabled(db, SQLITE4_Stat3) ){
      tRowcnt nOut = 0;
      if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){
        testcase( pTerm->eOperator & WO_EQ );
        testcase( pTerm->eOperator & WO_ISNULL );
        rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight, &nOut);
      }else if( (pTerm->eOperator & WO_IN)
             &&  !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)  ){
        rc = whereInScanEst(pParse, pProbe, pTerm->pExpr->x.pList, &nOut);
      }
      if( rc==SQLITE4_OK ) pNew->nOut = whereCost(nOut);
    }
#endif
    if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_PRIMARY_KEY))==0 ){
      /* Each row involves a step of the index, then a binary search of
      ** the main table */
      pNew->rRun =  whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10);
    }
    /* Step cost for each output row */
    pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
    /* TBD: Adjust nOut for additional constraints */
    rc = whereLoopInsert(pBuilder, pNew);
    if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
     && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
    ){
      whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
    }
  }
  pNew->prereq = saved_prereq;
  pNew->u.btree.nEq = saved_nEq;
  pNew->wsFlags = saved_wsFlags;
  pNew->nOut = saved_nOut;
  pNew->nLTerm = saved_nLTerm;
  return rc;
}

/*
** Return True if it is possible that pIndex might be useful in
** implementing the ORDER BY clause in pBuilder.
**
** Return False if pBuilder does not contain an ORDER BY clause or
** if there is no way for pIndex to be useful in implementing that
** ORDER BY clause.
*/
static int indexMightHelpWithOrderBy(
  WhereLoopBuilder *pBuilder,
  Index *pIndex,
  int iCursor
){
  ExprList *pOB;
  int ii, jj;

  if( pIndex->bUnordered ) return 0;
  if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
  for(ii=0; ii<pOB->nExpr; ii++){
    Expr *pExpr = sqlite4ExprSkipCollate(pOB->a[ii].pExpr);
    if( pExpr->op!=TK_COLUMN ) return 0;
    if( pExpr->iTable==iCursor ){
      for(jj=0; jj<pIndex->nColumn; jj++){
        if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1;
      }
    }
  }
  return 0;
}

/*
** Return a bitmask where 1s indicate that the corresponding column of
** the table is used by an index.  Only the first 63 columns are considered.
*/
static Bitmask columnsInIndex(Index *pIdx){
  Bitmask m = 0;
  if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){
    int j;
    for(j=pIdx->nCover-1; j>=0; j--){
      int x = pIdx->aiCover[j];
      testcase( x==BMS-1 );
      testcase( x==BMS-2 );
      if( x<BMS-1 ) m |= MASKBIT(x);
    }
  }
  return m;
}

static int whereLoopAddMatch(
  WhereLoopBuilder *pBuilder, 
  struct SrcListItem *pSrc,
  Bitmask mExtra, 
  int *pbDone
){
  WhereClause *pWC = pBuilder->pWC;
  int iTerm;
  int rc = SQLITE4_OK;
  if( findMatchExpr(pWC, pSrc, &iTerm) ){
    WhereLoop *pNew = pBuilder->pNew;

    pNew->prereq = pWC->a[iTerm].prereqRight; 
    pNew->wsFlags = WHERE_INDEXED;
    pNew->rSetup = 0;
    pNew->rRun = 1;
    pNew->nOut = 1;
    pNew->u.btree.nEq = 0;
    pNew->u.btree.pIndex = pWC->a[iTerm].pExpr->pIdx;
    
    rc = whereLoopInsert(pBuilder, pNew);
    *pbDone = 1;
  }else{
    *pbDone = 0;
  }
  return rc;
}

/*
** Add all WhereLoop objects for a single table of the join where the table
** is idenfied by pBuilder->pNew->iTab.  That table is guaranteed to be
** a b-tree table, not a virtual table.
*/
static int whereLoopAddBtree(
  WhereLoopBuilder *pBuilder, /* WHERE clause information */
  Bitmask mExtra              /* Extra prerequesites for using this table */
){
  WhereInfo *pWInfo;          /* WHERE analysis context */
  Index *pProbe;              /* An index we are evaluating */
  Index *pPk;                 /* Primary key index for table pSrc */
  SrcList *pTabList;          /* The FROM clause */
  struct SrcListItem *pSrc;   /* The FROM clause btree term to add */
  WhereLoop *pNew;            /* Template WhereLoop object */
  int rc = SQLITE4_OK;        /* Return code */
  int iSortIdx = 1;           /* Index number */
  int b;                      /* A boolean value */
  WhereCost rSize;            /* number of rows in the table */
  WhereCost rLogSize;         /* Logarithm of the number of rows in the table */
  
  pNew = pBuilder->pNew;
  pWInfo = pBuilder->pWInfo;
  pTabList = pWInfo->pTabList;
  pSrc = pTabList->a + pNew->iTab;
  assert( !IsVirtual(pSrc->pTab) );
  pPk = sqlite4FindPrimaryKey(pSrc->pTab, 0);

  if( pSrc->pIndex ){
    /* An INDEXED BY clause specifies a particular index to use */
    pProbe = pSrc->pIndex;
  }else if( pSrc->notIndexed ){
    /* A NOT INDEXED clause means use the PK index */
    pProbe = pPk;
  }else{
    /* Otherwise, consider all indexes */
    pProbe = pSrc->pTab->pIndex;
  }

  rc = whereLoopAddMatch(pBuilder, pSrc, mExtra, &b);
  if( b ) return rc;
  assert( rc==SQLITE4_OK );

  rSize = whereCost(pSrc->pTab->nRowEst);
  rLogSize = estLog(rSize);

#ifndef SQLITE4_OMIT_AUTOMATIC_INDEX
  /* Automatic indexes */
  if( !pBuilder->pOrSet
   && (pWInfo->pParse->db->flags & SQLITE4_AutoIndex)!=0
   && pSrc->pIndex==0
#if 0
   && !pSrc->viaCoroutine
#endif
   && !pSrc->notIndexed
   && !pSrc->isCorrelated
  ){
    /* Generate auto-index WhereLoops */
    WhereClause *pWC = pBuilder->pWC;
    WhereTerm *pTerm;
    WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
    for(pTerm=pWC->a; rc==SQLITE4_OK && pTerm<pWCEnd; pTerm++){
      if( pTerm->prereqRight & pNew->maskSelf ) continue;
      if( termCanDriveIndex(pTerm, pSrc, 0) ){
        pNew->u.btree.nEq = 1;
        pNew->u.btree.pIndex = 0;
        pNew->nLTerm = 1;
        pNew->aLTerm[0] = pTerm;
        /* TUNING: One-time cost for computing the automatic index is
        ** approximately 7*N*log2(N) where N is the number of rows in
        ** the table being indexed. */
        pNew->rSetup = rLogSize + rSize + 28;  assert( 28==whereCost(7) );
        /* TUNING: Each index lookup yields 20 rows in the table.  This
        ** is more than the usual guess of 10 rows, since we have no way
        ** of knowning how selective the index will ultimately be.  It would
        ** not be unreasonable to make this value much larger. */
        pNew->nOut = 43;  assert( 43==whereCost(20) );
        pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
        pNew->wsFlags = WHERE_AUTO_INDEX;
        pNew->prereq = mExtra | pTerm->prereqRight;
        rc = whereLoopInsert(pBuilder, pNew);
      }
    }
  }
#endif /* ifndef SQLITE4_OMIT_AUTOMATIC_INDEX */

  /* If this table has no primary key, then it is either a materialized
  ** view or ephemeral table. Either way, add a WhereLoop for a full-scan 
  ** of it.  */
  if( pPk==0 ){
    assert( pSrc->pTab->pSelect || (pSrc->pTab->tabFlags & TF_Ephemeral) );
    pNew->u.btree.nEq = 0;
    pNew->nLTerm = 0;
    pNew->iSortIdx = 0;
    pNew->rSetup = 0;
    pNew->prereq = mExtra;
    pNew->nOut = rSize;
    pNew->u.btree.pIndex = 0;
    pNew->wsFlags = 0;
    pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
    rc = whereLoopInsert(pBuilder, pNew);
  }

  /* Loop through the set of indices being considered. */
  for(; rc==SQLITE4_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
    int bCover = (pProbe!=pPk && 0==(pSrc->colUsed & ~columnsInIndex(pProbe)));
    if( pProbe->eIndexType==SQLITE4_INDEX_FTS5 ) continue;
    assert( pProbe->tnum>0 );

    pNew->u.btree.nEq = 0;
    pNew->nLTerm = 0;
    pNew->rSetup = 0;
    pNew->prereq = mExtra;
    pNew->nOut = rSize;
    pNew->u.btree.pIndex = pProbe;
    pNew->wsFlags = WHERE_INDEXED;
    pNew->wsFlags |= (bCover ? WHERE_IDX_ONLY : 0); 
    pNew->wsFlags |= (pProbe==pPk ? WHERE_PRIMARY_KEY : 0);

    b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
    /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */
    assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 );
    pNew->iSortIdx = b ? iSortIdx : 0;

    if( pProbe==pPk || b || (bCover
     && pProbe->bUnordered==0
     && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
#if 0
     && sqlite4GlobalConfig.bUseCis
     && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
#endif
    )){
      if( pProbe==pPk ){
        /* TUNING: Cost of full table scan is 3*(N + log2(N)).
        **  +  The extra 3 factor is to encourage the use of indexed lookups
        **     over full scans.  A smaller constant 2 is used for covering
        **     index scans so that a covering index scan will be favored over
        **     a table scan. */
        pNew->rRun = whereCostAdd(rSize,rLogSize) + 16;
      }else if( bCover ){
        /* TUNING: Cost of a covering index scan is 2*(N + log2(N)).
        **  +  The extra 2 factor is to encourage the use of indexed lookups
        **     over index scans.  A table scan uses a factor of 3 so that
        **     index scans are favored over table scans.
        **  +  If this covering index might also help satisfy the ORDER BY
        **     clause, then the cost is fudged down slightly so that this
        **     index is favored above other indices that have no hope of
        **     helping with the ORDER BY. */
        pNew->rRun = 10 + whereCostAdd(rSize,rLogSize) - b;
      }else{
        assert( b!=0 ); 
        /* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
         ** which we will simplify to just N*log2(N) */
        pNew->rRun = rSize + rLogSize;
      }
      rc = whereLoopInsert(pBuilder, pNew);
      if( rc ) break;
    }

    rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);

    /* If there was an INDEXED BY or NOT INDEXED clause, then only one
    ** index is considered. */
    if( pSrc->pIndex || pSrc->notIndexed ) break;
  }
  return rc;
}

#ifndef SQLITE4_OMIT_VIRTUALTABLE
/*
** Add all WhereLoop objects for a table of the join identified by
** pBuilder->pNew->iTab.  That table is guaranteed to be a virtual table.
*/
static int whereLoopAddVirtual(
  WhereLoopBuilder *pBuilder   /* WHERE clause information */
){
  WhereInfo *pWInfo;           /* WHERE analysis context */
  Parse *pParse;               /* The parsing context */
  WhereClause *pWC;            /* The WHERE clause */
  struct SrcListItem *pSrc;   /* The FROM clause term to search */
  Table *pTab;
  sqlite4 *db;
  sqlite4_index_info *pIdxInfo;
  struct sqlite4_index_constraint *pIdxCons;
  struct sqlite4_index_constraint_usage *pUsage;
  WhereTerm *pTerm;
  int i, j;
  int iTerm, mxTerm;
  int nConstraint;
  int seenIn = 0;              /* True if an IN operator is seen */
  int seenVar = 0;             /* True if a non-constant constraint is seen */
  int iPhase;                  /* 0: const w/o IN, 1: const, 2: no IN,  2: IN */
  WhereLoop *pNew;
  int rc = SQLITE4_OK;

  pWInfo = pBuilder->pWInfo;
  pParse = pWInfo->pParse;
  db = pParse->db;
  pWC = pBuilder->pWC;
  pNew = pBuilder->pNew;
  pSrc = &pWInfo->pTabList->a[pNew->iTab];
  pTab = pSrc->pTab;
  assert( IsVirtual(pTab) );
  pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pBuilder->pOrderBy);
  if( pIdxInfo==0 ) return SQLITE4_NOMEM;
  pNew->prereq = 0;
  pNew->rSetup = 0;
  pNew->wsFlags = WHERE_VIRTUALTABLE;
  pNew->nLTerm = 0;
  pNew->u.vtab.needFree = 0;
  pUsage = pIdxInfo->aConstraintUsage;
  nConstraint = pIdxInfo->nConstraint;
  if( whereLoopResize(db, pNew, nConstraint) ){
    sqlite4DbFree(db, pIdxInfo);
    return SQLITE4_NOMEM;
  }

  for(iPhase=0; iPhase<=3; iPhase++){
    if( !seenIn && (iPhase&1)!=0 ){
      iPhase++;
      if( iPhase>3 ) break;
    }
    if( !seenVar && iPhase>1 ) break;
    pIdxCons = *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint;
    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
      j = pIdxCons->iTermOffset;
      pTerm = &pWC->a[j];
      switch( iPhase ){
        case 0:    /* Constants without IN operator */
          pIdxCons->usable = 0;
          if( (pTerm->eOperator & WO_IN)!=0 ){
            seenIn = 1;
          }
          if( pTerm->prereqRight!=0 ){
            seenVar = 1;
          }else if( (pTerm->eOperator & WO_IN)==0 ){
            pIdxCons->usable = 1;
          }
          break;
        case 1:    /* Constants with IN operators */
          assert( seenIn );
          pIdxCons->usable = (pTerm->prereqRight==0);
          break;
        case 2:    /* Variables without IN */
          assert( seenVar );
          pIdxCons->usable = (pTerm->eOperator & WO_IN)==0;
          break;
        default:   /* Variables with IN */
          assert( seenVar && seenIn );
          pIdxCons->usable = 1;
          break;
      }
    }
    memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
    if( pIdxInfo->needToFreeIdxStr ) sqlite4_free(pIdxInfo->idxStr);
    pIdxInfo->idxStr = 0;
    pIdxInfo->idxNum = 0;
    pIdxInfo->needToFreeIdxStr = 0;
    pIdxInfo->orderByConsumed = 0;
    pIdxInfo->estimatedCost = SQLITE4_BIG_DBL / (double)2;
    rc = vtabBestIndex(pParse, pTab, pIdxInfo);
    if( rc ) goto whereLoopAddVtab_exit;
    pIdxCons = *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint;
    pNew->prereq = 0;
    mxTerm = -1;
    assert( pNew->nLSlot>=nConstraint );
    for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
    pNew->u.vtab.omitMask = 0;
    for(i=0; i<nConstraint; i++, pIdxCons++){
      if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){
        j = pIdxCons->iTermOffset;
        if( iTerm>=nConstraint
         || j<0
         || j>=pWC->nTerm
         || pNew->aLTerm[iTerm]!=0
        ){
          rc = SQLITE4_ERROR;
          sqlite4ErrorMsg(pParse, "%s.xBestIndex() malfunction", pTab->zName);
          goto whereLoopAddVtab_exit;
        }
        testcase( iTerm==nConstraint-1 );
        testcase( j==0 );
        testcase( j==pWC->nTerm-1 );
        pTerm = &pWC->a[j];
        pNew->prereq |= pTerm->prereqRight;
        assert( iTerm<pNew->nLSlot );
        pNew->aLTerm[iTerm] = pTerm;
        if( iTerm>mxTerm ) mxTerm = iTerm;
        testcase( iTerm==15 );
        testcase( iTerm==16 );
        if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
        if( (pTerm->eOperator & WO_IN)!=0 ){
          if( pUsage[i].omit==0 ){
            /* Do not attempt to use an IN constraint if the virtual table
            ** says that the equivalent EQ constraint cannot be safely omitted.
            ** If we do attempt to use such a constraint, some rows might be
            ** repeated in the output. */
            break;
          }
          /* A virtual table that is constrained by an IN clause may not
          ** consume the ORDER BY clause because (1) the order of IN terms
          ** is not necessarily related to the order of output terms and
          ** (2) Multiple outputs from a single IN value will not merge
          ** together.  */
          pIdxInfo->orderByConsumed = 0;
        }
      }
    }
    if( i>=nConstraint ){
      pNew->nLTerm = mxTerm+1;
      assert( pNew->nLTerm<=pNew->nLSlot );
      pNew->u.vtab.idxNum = pIdxInfo->idxNum;
      pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
      pIdxInfo->needToFreeIdxStr = 0;
      pNew->u.vtab.idxStr = pIdxInfo->idxStr;
      pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
                                     && pIdxInfo->orderByConsumed);
      pNew->rSetup = 0;
      pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost);
      /* TUNING: Every virtual table query returns 25 rows */
      pNew->nOut = 46;  assert( 46==whereCost(25) );
      whereLoopInsert(pBuilder, pNew);
      if( pNew->u.vtab.needFree ){
        sqlite4_free(pNew->u.vtab.idxStr);
        pNew->u.vtab.needFree = 0;
      }
    }
  }  

whereLoopAddVtab_exit:
  if( pIdxInfo->needToFreeIdxStr ) sqlite4_free(pIdxInfo->idxStr);
  sqlite4DbFree(db, pIdxInfo);
  return rc;
}
#endif /* SQLITE4_OMIT_VIRTUALTABLE */

/*
** Add WhereLoop entries to handle OR terms.  This works for either
** btrees or virtual tables.
*/
static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
  WhereInfo *pWInfo = pBuilder->pWInfo;
  WhereClause *pWC;
  WhereLoop *pNew;
  WhereTerm *pTerm, *pWCEnd;
  int rc = SQLITE4_OK;
  int iCur;
  WhereClause tempWC;
  WhereLoopBuilder sSubBuild;
  WhereOrSet sSum, sCur, sPrev;
  struct SrcListItem *pItem;
  
  pWC = pBuilder->pWC;
  if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE4_OK;
  pWCEnd = pWC->a + pWC->nTerm;
  pNew = pBuilder->pNew;

  for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE4_OK; pTerm++){
    if( (pTerm->eOperator & WO_OR)!=0
     && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 
    ){
      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
      WhereTerm *pOrTerm;
      int once = 1;
      int i, j;
    
      pItem = pWInfo->pTabList->a + pNew->iTab;
      iCur = pItem->iCursor;
      sSubBuild = *pBuilder;
      sSubBuild.pOrderBy = 0;
      sSubBuild.pOrSet = &sCur;

      for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
        if( (pOrTerm->eOperator & WO_AND)!=0 ){
          sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
        }else if( pOrTerm->leftCursor==iCur ){
          tempWC.pWInfo = pWC->pWInfo;
          tempWC.pOuter = pWC;
          tempWC.op = TK_AND;
          tempWC.nTerm = 1;
          tempWC.a = pOrTerm;
          sSubBuild.pWC = &tempWC;
        }else{
          continue;
        }
        sCur.n = 0;
#ifndef SQLITE4_OMIT_VIRTUALTABLE
        if( IsVirtual(pItem->pTab) ){
          rc = whereLoopAddVirtual(&sSubBuild);
          for(i=0; i<sCur.n; i++) sCur.a[i].prereq |= mExtra;
        }else
#endif
        {
          rc = whereLoopAddBtree(&sSubBuild, mExtra);
        }
        assert( rc==SQLITE4_OK || sCur.n==0 );
        if( sCur.n==0 ){
          sSum.n = 0;
          break;
        }else if( once ){
          whereOrMove(&sSum, &sCur);
          once = 0;
        }else{
          whereOrMove(&sPrev, &sSum);
          sSum.n = 0;
          for(i=0; i<sPrev.n; i++){
            for(j=0; j<sCur.n; j++){
              whereOrInsert(&sSum, sPrev.a[i].prereq | sCur.a[j].prereq,
                            whereCostAdd(sPrev.a[i].rRun, sCur.a[j].rRun),
                            whereCostAdd(sPrev.a[i].nOut, sCur.a[j].nOut));
            }
          }
        }
      }
      pNew->nLTerm = 1;
      pNew->aLTerm[0] = pTerm;
      pNew->wsFlags = WHERE_MULTI_OR;
      pNew->rSetup = 0;
      pNew->iSortIdx = 0;
      memset(&pNew->u, 0, sizeof(pNew->u));
      for(i=0; rc==SQLITE4_OK && i<sSum.n; i++){
        /* TUNING: Multiple by 3.5 for the secondary table lookup */
        pNew->rRun = sSum.a[i].rRun + 18;
        pNew->nOut = sSum.a[i].nOut;
        pNew->prereq = sSum.a[i].prereq;
        rc = whereLoopInsert(pBuilder, pNew);
      }
    }
  }
  return rc;
}

/*
** Add all WhereLoop objects for all tables 
*/
static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
  WhereInfo *pWInfo = pBuilder->pWInfo;
  Bitmask mExtra = 0;
  Bitmask mPrior = 0;
  int iTab;
  SrcList *pTabList = pWInfo->pTabList;
  struct SrcListItem *pItem;
  sqlite4 *db = pWInfo->pParse->db;
  int nTabList = pWInfo->nLevel;
  int rc = SQLITE4_OK;
  u8 priorJoinType = 0;
  WhereLoop *pNew;

  /* Loop over the tables in the join, from left to right */
  pNew = pBuilder->pNew;
  whereLoopInit(pNew);
  for(iTab=0, pItem=pTabList->a; iTab<nTabList; iTab++, pItem++){
    pNew->iTab = iTab;
    pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor);
    if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){
      mExtra = mPrior;
    }
    priorJoinType = pItem->jointype;
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    if( IsVirtual(pItem->pTab) ){
      rc = whereLoopAddVirtual(pBuilder);
    }else
#endif
    {
      rc = whereLoopAddBtree(pBuilder, mExtra);
    }
    if( rc==SQLITE4_OK ){
      rc = whereLoopAddOr(pBuilder, mExtra);
    }
    mPrior |= pNew->maskSelf;
    if( rc || db->mallocFailed ) break;
  }
  whereLoopClear(db, pNew);
  return rc;
}

/*
** Examine a WherePath (with the addition of the extra WhereLoop of the 5th
** parameters) to see if it outputs rows in the requested ORDER BY
** (or GROUP BY) without requiring a separate sort operation.  Return:
** 
**    0:  ORDER BY is not satisfied.  Sorting required
**    1:  ORDER BY is satisfied.      Omit sorting
**   -1:  Unknown at this time
**
** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as
** strict.  With GROUP BY and DISTINCT the only requirement is that
** equivalent rows appear immediately adjacent to one another.  GROUP BY
** and DISTINT do not require rows to appear in any particular order as long
** as equivelent rows are grouped together.  Thus for GROUP BY and DISTINCT
** the pOrderBy terms can be matched in any order.  With ORDER BY, the 
** pOrderBy terms must be matched in strict left-to-right order.
*/
static int wherePathSatisfiesOrderBy(
  WhereInfo *pWInfo,    /* The WHERE clause */
  ExprList *pOrderBy,   /* ORDER BY or GROUP BY or DISTINCT clause to check */
  WherePath *pPath,     /* The WherePath to check */
  u16 wctrlFlags,       /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */
  u16 nLoop,            /* Number of entries in pPath->aLoop[] */
  WhereLoop *pLast,     /* Add this WhereLoop to the end of pPath->aLoop[] */
  Bitmask *pRevMask     /* OUT: Mask of WhereLoops to run in reverse order */
){
  u8 revSet;            /* True if rev is known */
  u8 rev;               /* Composite sort order */
  u8 revIdx;            /* Index sort order */
  u8 isOrderDistinct;   /* All prior WhereLoops are order-distinct */
  u8 isMatch;           /* iColumn matches a term of the ORDER BY clause */
  u16 nColumn;          /* Number of columns in pIndex */
  u16 nOrderBy;         /* Number terms in the ORDER BY clause */
  int iLoop;            /* Index of WhereLoop in pPath being processed */
  int i, j;             /* Loop counters */
  int iCur;             /* Cursor number for current WhereLoop */
  int iColumn;          /* A column number within table iCur */
  WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */
  WhereTerm *pTerm;     /* A single term of the WHERE clause */
  Expr *pOBExpr;        /* An expression from the ORDER BY clause */
  CollSeq *pColl;       /* COLLATE function from an ORDER BY clause term */
  Index *pIndex;        /* The index associated with pLoop */
  sqlite4 *db = pWInfo->pParse->db;  /* Database connection */
  Bitmask obSat = 0;    /* Mask of ORDER BY terms satisfied so far */
  Bitmask obDone;       /* Mask of all ORDER BY terms */
  Bitmask orderDistinctMask;  /* Mask of all well-ordered loops */
  Bitmask ready;              /* Mask of inner loops */

  /*
  ** We say the WhereLoop is "one-row" if it generates no more than one
  ** row of output.  A WhereLoop is one-row if all of the following are true:
  **  (a) All index columns match with WHERE_COLUMN_EQ.
  **  (b) The index is unique
  ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row.
  ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags.
  **
  ** We say the WhereLoop is "order-distinct" if the set of columns from
  ** that WhereLoop that are in the ORDER BY clause are different for every
  ** row of the WhereLoop.  Every one-row WhereLoop is automatically
  ** order-distinct.   A WhereLoop that has no columns in the ORDER BY clause
  ** is not order-distinct. To be order-distinct is not quite the same as being
  ** UNIQUE since a UNIQUE column or index can have multiple rows that 
  ** are NULL and NULL values are equivalent for the purpose of order-distinct.
  ** To be order-distinct, the columns must be UNIQUE and NOT NULL.
  **
  ** The rowid for a table is always UNIQUE and NOT NULL so whenever the
  ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is
  ** automatically order-distinct.
  */

  assert( pOrderBy!=0 );

  /* Sortability of virtual tables is determined by the xBestIndex method
  ** of the virtual table itself */
  if( pLast->wsFlags & WHERE_VIRTUALTABLE ){
    testcase( nLoop>0 );  /* True when outer loops are one-row and match 
                          ** no ORDER BY terms */
    return pLast->u.vtab.isOrdered;
  }
  if( nLoop && OptimizationDisabled(db, SQLITE4_OrderByIdxJoin) ) return 0;

  nOrderBy = pOrderBy->nExpr;
  testcase( nOrderBy==BMS-1 );
  if( nOrderBy>BMS-1 ) return 0;  /* Cannot optimize overly large ORDER BYs */
  isOrderDistinct = 1;
  obDone = MASKBIT(nOrderBy)-1;
  orderDistinctMask = 0;
  ready = 0;
  for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){
    if( iLoop>0 ) ready |= pLoop->maskSelf;
    pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast;
    assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 );
    iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;

    /* Mark off any ORDER BY term X that is a column in the table of
    ** the current loop for which there is term in the WHERE
    ** clause of the form X IS NULL or X=? that reference only outer
    ** loops.
    */
    for(i=0; i<nOrderBy; i++){
      if( MASKBIT(i) & obSat ) continue;
      pOBExpr = sqlite4ExprSkipCollate(pOrderBy->a[i].pExpr);
      if( pOBExpr->op!=TK_COLUMN ) continue;
      if( pOBExpr->iTable!=iCur ) continue;
      pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
                       ~ready, WO_EQ|WO_ISNULL, 0);
      if( pTerm==0 ) continue;
      if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){
        const char *z1, *z2;
        pColl = sqlite4ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
        if( !pColl ) pColl = db->pDfltColl;
        z1 = pColl->zName;
        pColl = sqlite4ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
        if( !pColl ) pColl = db->pDfltColl;
        z2 = pColl->zName;
        if( sqlite4_stricmp(z1, z2)!=0 ) continue;
      }
      obSat |= MASKBIT(i);
    }

    if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){
      Index *pPk = 0;
      if( (pIndex = pLoop->u.btree.pIndex)==0 
        || pIndex->bUnordered 
        || pIndex->eIndexType==SQLITE4_INDEX_FTS5 
      ){
        return 0;
      }else{
        isOrderDistinct = pIndex->onError!=OE_None;
        pPk = sqlite4FindPrimaryKey(pIndex->pTable, 0);
        nColumn = idxColumnCount(pIndex, pPk);
      }

      /* Loop through all columns of the index and deal with the ones
      ** that are not constrained by == or IN.
      */
      rev = revSet = 0;
      for(j=0; j<nColumn; j++){
        u8 bOnce;   /* True to run the ORDER BY search loop */

        /* Skip over == and IS NULL terms */
        if( j<pLoop->u.btree.nEq
         && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0
        ){
          if( i & WO_ISNULL ){
            testcase( isOrderDistinct );
            isOrderDistinct = 0;
          }
          continue;  
        }

        /* Get the column number in the table (iColumn) and sort order
        ** (revIdx) for the j-th column of the index.
        */
        if( j<nColumn ){
          /* Normal index columns */
          iColumn = idxColumnNumber(pIndex, pPk, j);
          revIdx = idxColumnSortOrder(pIndex, pPk, j);
        }else{
          /* The ROWID column at the end */
          assert( j==nColumn );
          iColumn = -1;
          revIdx = 0;
        }

        /* An unconstrained column that might be NULL means that this
        ** WhereLoop is not well-ordered 
        */
        if( isOrderDistinct
         && iColumn>=0
         && j>=pLoop->u.btree.nEq
         && pIndex->pTable->aCol[iColumn].notNull==0
        ){
          isOrderDistinct = 0;
        }

        /* Find the ORDER BY term that corresponds to the j-th column
        ** of the index and and mark that ORDER BY term off 
        */
        bOnce = 1;
        isMatch = 0;
        for(i=0; bOnce && i<nOrderBy; i++){
          if( MASKBIT(i) & obSat ) continue;
          pOBExpr = sqlite4ExprSkipCollate(pOrderBy->a[i].pExpr);
          testcase( wctrlFlags & WHERE_GROUPBY );
          testcase( wctrlFlags & WHERE_DISTINCTBY );
          if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
          if( pOBExpr->op!=TK_COLUMN ) continue;
          if( pOBExpr->iTable!=iCur ) continue;
          if( pOBExpr->iColumn!=iColumn ) continue;
          if( iColumn>=0 ){
            const char *zIdxColl;
            pColl = sqlite4ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
            if( !pColl ) pColl = db->pDfltColl;
            zIdxColl = idxColumnCollation(pIndex, pPk, j);
            if( sqlite4_stricmp(pColl->zName, zIdxColl)!=0 ) continue;
          }
          isMatch = 1;
          break;
        }
        if( isMatch ){
          obSat |= MASKBIT(i);
          if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){
            /* Make sure the sort order is compatible in an ORDER BY clause.
            ** Sort order is irrelevant for a GROUP BY clause. */
            if( revSet ){
              if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) return 0;
            }else{
              rev = revIdx ^ pOrderBy->a[i].sortOrder;
              if( rev ) *pRevMask |= MASKBIT(iLoop);
              revSet = 1;
            }
          }
        }else{
          /* No match found */
          if( j==0 || j<nColumn ){
            testcase( isOrderDistinct!=0 );
            isOrderDistinct = 0;
          }
          break;
        }
      } /* end Loop over all index columns */

      /* If (j==nColumn), then each column of the index, including any 
      ** appended PK columns, corresponds to either an ORDER BY term or 
      ** equality constraint. Since the PK columns are collectively UNIQUE
      ** and NOT NULL, consider the loop order-distinct.  */
      if( j==nColumn ){
        testcase( isOrderDistinct==0 );
        isOrderDistinct = 1;
      }
    } /* end-if not one-row */

    /* Mark off any other ORDER BY terms that reference pLoop */
    if( isOrderDistinct ){
      orderDistinctMask |= pLoop->maskSelf;
      for(i=0; i<nOrderBy; i++){
        Expr *p;
        if( MASKBIT(i) & obSat ) continue;
        p = pOrderBy->a[i].pExpr;
        if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){
          obSat |= MASKBIT(i);
        }
      }
    }
  } /* End the loop over all WhereLoops from outer-most down to inner-most */
  if( obSat==obDone ) return 1;
  if( !isOrderDistinct ) return 0;
  return -1;
}

#ifdef WHERETRACE_ENABLED
/* For debugging use only: */
static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){
  static char zName[65];
  int i;
  for(i=0; i<nLoop; i++){ zName[i] = pPath->aLoop[i]->cId; }
  if( pLast ) zName[i++] = pLast->cId;
  zName[i] = 0;
  return zName;
}
#endif


/*
** Given the list of WhereLoop objects at pWInfo->pLoops, this routine
** attempts to find the lowest cost path that visits each WhereLoop
** once.  This path is then loaded into the pWInfo->a[].pWLoop fields.
**
** Assume that the total number of output rows that will need to be sorted
** will be nRowEst (in the 10*log2 representation).  Or, ignore sorting
** costs if nRowEst==0.
**
** Return SQLITE4_OK on success or SQLITE4_NOMEM of a memory allocation
** error occurs.
*/
static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
  int mxChoice;             /* Maximum number of simultaneous paths tracked */
  int nLoop;                /* Number of terms in the join */
  Parse *pParse;            /* Parsing context */
  sqlite4 *db;              /* The database connection */
  int iLoop;                /* Loop counter over the terms of the join */
  int ii, jj;               /* Loop counters */
  WhereCost rCost;             /* Cost of a path */
  WhereCost mxCost = 0;        /* Maximum cost of a set of paths */
  WhereCost rSortCost;         /* Cost to do a sort */
  int nTo, nFrom;           /* Number of valid entries in aTo[] and aFrom[] */
  WherePath *aFrom;         /* All nFrom paths at the previous level */
  WherePath *aTo;           /* The nTo best paths at the current level */
  WherePath *pFrom;         /* An element of aFrom[] that we are working on */
  WherePath *pTo;           /* An element of aTo[] that we are working on */
  WhereLoop *pWLoop;        /* One of the WhereLoop objects */
  WhereLoop **pX;           /* Used to divy up the pSpace memory */
  char *pSpace;             /* Temporary memory used by this routine */

  pParse = pWInfo->pParse;
  db = pParse->db;
  nLoop = pWInfo->nLevel;
  /* TUNING: For simple queries, only the best path is tracked.
  ** For 2-way joins, the 5 best paths are followed.
  ** For joins of 3 or more tables, track the 10 best paths */
  mxChoice = (nLoop==1) ? 1 : (nLoop==2 ? 5 : 10);
  assert( nLoop<=pWInfo->pTabList->nSrc );
  WHERETRACE(0x002, ("---- begin solver\n"));

  /* Allocate and initialize space for aTo and aFrom */
  ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
  pSpace = sqlite4DbMallocRaw(db, ii);
  if( pSpace==0 ) return SQLITE4_NOMEM;
  aTo = (WherePath*)pSpace;
  aFrom = aTo+mxChoice;
  memset(aFrom, 0, sizeof(aFrom[0]));
  pX = (WhereLoop**)(aFrom+mxChoice);
  for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
    pFrom->aLoop = pX;
  }

  /* Seed the search with a single WherePath containing zero WhereLoops.
  **
  ** TUNING: Do not let the number of iterations go above 25.  If the cost
  ** of computing an automatic index is not paid back within the first 25
  ** rows, then do not use the automatic index. */
  aFrom[0].nRow = MIN(pParse->nQueryLoop, 46);  assert( 46==whereCost(25) );
  nFrom = 1;

  /* Precompute the cost of sorting the final result set, if the caller
  ** to sqlite4WhereBegin() was concerned about sorting */
  rSortCost = 0;
  if( pWInfo->pOrderBy==0 || nRowEst==0 ){
    aFrom[0].isOrderedValid = 1;
  }else{
    /* TUNING: Estimated cost of sorting is N*log2(N) where N is the
    ** number of output rows. */
    rSortCost = nRowEst + estLog(nRowEst);
    WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
  }

  /* Compute successively longer WherePaths using the previous generation
  ** of WherePaths as the basis for the next.  Keep track of the mxChoice
  ** best paths at each generation */
  for(iLoop=0; iLoop<nLoop; iLoop++){
    nTo = 0;
    for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){
      for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){
        Bitmask maskNew;
        Bitmask revMask = 0;
        u8 isOrderedValid = pFrom->isOrderedValid;
        u8 isOrdered = pFrom->isOrdered;
        if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
        if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
        /* At this point, pWLoop is a candidate to be the next loop. 
        ** Compute its cost */
        rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
        rCost = whereCostAdd(rCost, pFrom->rCost);
        maskNew = pFrom->maskLoop | pWLoop->maskSelf;
        if( !isOrderedValid ){
          switch( wherePathSatisfiesOrderBy(pWInfo,
                       pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
                       iLoop, pWLoop, &revMask) ){
            case 1:  /* Yes.  pFrom+pWLoop does satisfy the ORDER BY clause */
              isOrdered = 1;
              isOrderedValid = 1;
              break;
            case 0:  /* No.  pFrom+pWLoop will require a separate sort */
              isOrdered = 0;
              isOrderedValid = 1;
              rCost = whereCostAdd(rCost, rSortCost);
              break;
            default: /* Cannot tell yet.  Try again on the next iteration */
              break;
          }
        }else{
          revMask = pFrom->revLoop;
        }
        /* Check to see if pWLoop should be added to the mxChoice best so far */
        for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){
          if( pTo->maskLoop==maskNew && pTo->isOrderedValid==isOrderedValid ){
            testcase( jj==nTo-1 );
            break;
          }
        }
        if( jj>=nTo ){
          if( nTo>=mxChoice && rCost>=mxCost ){
#ifdef WHERETRACE_ENABLED
            if( sqlite4WhereTrace&0x4 ){
              sqlite4DebugPrintf("Skip   %s cost=%3d order=%c\n",
                  wherePathName(pFrom, iLoop, pWLoop), rCost,
                  isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
            }
#endif
            continue;
          }
          /* Add a new Path to the aTo[] set */
          if( nTo<mxChoice ){
            /* Increase the size of the aTo set by one */
            jj = nTo++;
          }else{
            /* New path replaces the prior worst to keep count below mxChoice */
            for(jj=nTo-1; aTo[jj].rCost<mxCost; jj--){ assert(jj>0); }
          }
          pTo = &aTo[jj];
#ifdef WHERETRACE_ENABLED
          if( sqlite4WhereTrace&0x4 ){
            sqlite4DebugPrintf("New    %s cost=%-3d order=%c\n",
                wherePathName(pFrom, iLoop, pWLoop), rCost,
                isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
          }
#endif
        }else{
          if( pTo->rCost<=rCost ){
#ifdef WHERETRACE_ENABLED
            if( sqlite4WhereTrace&0x4 ){
              sqlite4DebugPrintf(
                  "Skip   %s cost=%-3d order=%c",
                  wherePathName(pFrom, iLoop, pWLoop), rCost,
                  isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
              sqlite4DebugPrintf("   vs %s cost=%-3d order=%c\n",
                  wherePathName(pTo, iLoop+1, 0), pTo->rCost,
                  pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
            }
#endif
            testcase( pTo->rCost==rCost );
            continue;
          }
          testcase( pTo->rCost==rCost+1 );
          /* A new and better score for a previously created equivalent path */
#ifdef WHERETRACE_ENABLED
          if( sqlite4WhereTrace&0x4 ){
            sqlite4DebugPrintf(
                "Update %s cost=%-3d order=%c",
                wherePathName(pFrom, iLoop, pWLoop), rCost,
                isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
            sqlite4DebugPrintf("  was %s cost=%-3d order=%c\n",
                wherePathName(pTo, iLoop+1, 0), pTo->rCost,
                pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
          }
#endif
        }
        /* pWLoop is a winner.  Add it to the set of best so far */
        pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
        pTo->revLoop = revMask;
        pTo->nRow = pFrom->nRow + pWLoop->nOut;
        pTo->rCost = rCost;
        pTo->isOrderedValid = isOrderedValid;
        pTo->isOrdered = isOrdered;
        memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
        pTo->aLoop[iLoop] = pWLoop;
        if( nTo>=mxChoice ){
          mxCost = aTo[0].rCost;
          for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){
            if( pTo->rCost>mxCost ) mxCost = pTo->rCost;
          }
        }
      }
    }

#ifdef WHERETRACE_ENABLED
    if( sqlite4WhereTrace>=2 ){
      sqlite4DebugPrintf("---- after round %d ----\n", iLoop);
      for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
        sqlite4DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
           wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
           pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
        if( pTo->isOrderedValid && pTo->isOrdered ){
          sqlite4DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
        }else{
          sqlite4DebugPrintf("\n");
        }
      }
    }
#endif

    /* Swap the roles of aFrom and aTo for the next generation */
    pFrom = aTo;
    aTo = aFrom;
    aFrom = pFrom;
    nFrom = nTo;
  }

  if( nFrom==0 ){
    sqlite4ErrorMsg(pParse, "no query solution");
    sqlite4DbFree(db, pSpace);
    return SQLITE4_ERROR;
  }
  
  /* Find the lowest cost path.  pFrom will be left pointing to that path */
  pFrom = aFrom;
  assert( nFrom==1 );
#if 0 /* The following is needed if nFrom is ever more than 1 */
  for(ii=1; ii<nFrom; ii++){
    if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii];
  }
#endif
  assert( pWInfo->nLevel==nLoop );
  /* Load the lowest cost path into pWInfo */
  for(iLoop=0; iLoop<nLoop; iLoop++){
    WhereLevel *pLevel = pWInfo->a + iLoop;
    pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop];
    pLevel->iFrom = pWLoop->iTab;
    pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
  }
  if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0
   && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
   && pWInfo->eDistinct==WHERE_DISTINCT_NOOP
   && nRowEst
  ){
    Bitmask notUsed;
    int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom,
                 WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], &notUsed);
    if( rc==1 ) pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
  }
  if( pFrom->isOrdered ){
    if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
      pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
    }else{
      pWInfo->bOBSat = 1;
      pWInfo->revMask = pFrom->revLoop;
    }
  }
  pWInfo->nRowOut = pFrom->nRow;

  /* Free temporary memory and return success */
  sqlite4DbFree(db, pSpace);
  return SQLITE4_OK;
}

/*
** Most queries use only a single table (they are not joins) and have
** simple == constraints against indexed fields.  This routine attempts
** to plan those simple cases using much less ceremony than the
** general-purpose query planner, and thereby yield faster sqlite4_prepare()
** times for the common case.
**
** Return non-zero on success, if this query can be handled by this
** no-frills query planner.  Return zero if this query needs the 
** general-purpose query planner.
*/
static int whereShortCut(WhereLoopBuilder *pBuilder){
  WhereInfo *pWInfo;
  struct SrcListItem *pItem;
  WhereClause *pWC;
  WhereTerm *pTerm;
  WhereLoop *pLoop;
  int iCur;
  int j;
  Table *pTab;
  Index *pIdx;
  
  pWInfo = pBuilder->pWInfo;
  if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0;
  assert( pWInfo->pTabList->nSrc>=1 );
  pItem = pWInfo->pTabList->a;
  pTab = pItem->pTab;
  if( IsVirtual(pTab) ) return 0;
  if( pItem->zIndex ) return 0;
  iCur = pItem->iCursor;
  pWC = &pWInfo->sWC;
  pLoop = pBuilder->pNew;
  pLoop->wsFlags = 0;

  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
    if( pIdx->onError==OE_None ) continue;
    for(j=0; j<pIdx->nColumn; j++){
      pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
      if( pTerm==0 ) break;
      whereLoopResize(pWInfo->pParse->db, pLoop, j);
      pLoop->aLTerm[j] = pTerm;
    }
    if( j!=pIdx->nColumn ) continue;
    pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
    if( (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){
      pLoop->wsFlags |= WHERE_IDX_ONLY;
    }
    pLoop->nLTerm = j;
    pLoop->u.btree.nEq = j;
    pLoop->u.btree.pIndex = pIdx;
    /* TUNING: Cost of a unique index lookup is 15 */
    pLoop->rRun = 39;  /* 39==whereCost(15) */
    break;
  }

  if( pLoop->wsFlags ){
    pLoop->nOut = (WhereCost)1;
    pWInfo->a[0].pWLoop = pLoop;
    pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
    pWInfo->a[0].iTabCur = iCur;
    pWInfo->nRowOut = 1;
    if( pWInfo->pOrderBy ) pWInfo->bOBSat =  1;
    if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }
#ifdef SQLITE4_DEBUG
    pLoop->cId = '0';
#endif
    return 1;
  }
  return 0;
}

/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an opaque structure that contains
** information needed to terminate the loop.  Later, the calling routine
** should invoke sqlite4WhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.
**
** If an error occurs, this routine returns NULL.
**
** The basic idea is to do a nested loop, one loop for each table in
** the FROM clause of a select.  (INSERT and UPDATE statements are the
** same as a SELECT with only a single table in the FROM clause.)  For
** example, if the SQL is this:
**
**       SELECT * FROM t1, t2, t3 WHERE ...;
**
** Then the code generated is conceptually like the following:
**
**      foreach row1 in t1 do       \    Code generated
**        foreach row2 in t2 do      |-- by sqlite4WhereBegin()
**          foreach row3 in t3 do   /
**            ...
**          end                     \    Code generated
**        end                        |-- by sqlite4WhereEnd()
**      end                         /
**
** Note that the loops might not be nested in the order in which they
** appear in the FROM clause if a different order is better able to make
** use of indices.  Note also that when the IN operator appears in
** the WHERE clause, it might result in additional nested loops for
** scanning through all values on the right-hand side of the IN.
**
** There are Btree cursors associated with each table.  t1 uses cursor
** number pTabList->a[0].iCursor.  t2 uses the cursor pTabList->a[1].iCursor.
** And so forth.  This routine generates code to open those VDBE cursors
** and sqlite4WhereEnd() generates the code to close them.
**
** The code that sqlite4WhereBegin() generates leaves the cursors named
** in pTabList pointing at their appropriate entries.  The [...] code
** can use OP_Column and OP_Rowid opcodes on these cursors to extract
** data from the various tables of the loop.
**
** If the WHERE clause is empty, the foreach loops must each scan their
** entire tables.  Thus a three-way join is an O(N^3) operation.  But if
** the tables have indices and there are terms in the WHERE clause that
** refer to those indices, a complete table scan can be avoided and the
** code will run much faster.  Most of the work of this routine is checking
** to see if there are indices that can be used to speed up the loop.
**
** Terms of the WHERE clause are also used to limit which rows actually
** make it to the "..." in the middle of the loop.  After each "foreach",
** terms of the WHERE clause that use only terms in that loop and outer
** loops are evaluated and if false a jump is made around all subsequent
** inner loops (or around the "..." if the test occurs within the inner-
** most loop)
**
** OUTER JOINS
**
** An outer join of tables t1 and t2 is conceptally coded as follows:
**
**    foreach row1 in t1 do
**      flag = 0
**      foreach row2 in t2 do
**        start:
**          ...
**          flag = 1
**      end
**      if flag==0 then
**        move the row2 cursor to a null row
**        goto start
**      fi
**    end
**
** ORDER BY CLAUSE PROCESSING
**
** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause
** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement
** if there is one.  If there is no ORDER BY clause or if this routine
** is called from an UPDATE or DELETE statement, then pOrderBy is NULL.
*/
SQLITE4_PRIVATE WhereInfo *sqlite4WhereBegin(
  Parse *pParse,        /* The parser context */
  SrcList *pTabList,    /* FROM clause: A list of all tables to be scanned */
  Expr *pWhere,         /* The WHERE clause */
  ExprList *pOrderBy,   /* An ORDER BY clause, or NULL */
  ExprList *pResultSet, /* Result set of the query */
  u16 wctrlFlags,       /* One of the WHERE_* flags defined in sqliteInt.h */
  int iIdxCur           /* If WHERE_ONETABLE_ONLY is set, index cursor number */
){
  int nByteWInfo;            /* Num. bytes allocated for WhereInfo struct */
  int nTabList;              /* Number of elements in pTabList */
  WhereInfo *pWInfo;         /* Will become the return value of this function */
  Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
  Bitmask notReady;          /* Cursors that are not yet positioned */
  WhereLoopBuilder sWLB;     /* The WhereLoop builder */
  WhereMaskSet *pMaskSet;    /* The expression mask set */
  WhereLevel *pLevel;        /* A single level in pWInfo->a[] */
  WhereLoop *pLoop;          /* Pointer to a single WhereLoop object */
  int ii;                    /* Loop counter */
  sqlite4 *db;               /* Database connection */
  int rc;                    /* Return code */

  /* src4: In SQLite3, the caller would set this flag. */
  if( pResultSet ) wctrlFlags |= WHERE_WANT_DISTINCT;

  /* Variable initialization */
  db = pParse->db;
  memset(&sWLB, 0, sizeof(sWLB));
  sWLB.pOrderBy = pOrderBy;

  /* Disable the DISTINCT optimization if SQLITE4_DistinctOpt is set via
  ** sqlite4_test_ctrl(SQLITE4_TESTCTRL_OPTIMIZATIONS,...) */
  if( OptimizationDisabled(db, SQLITE4_DistinctOpt) ){
    wctrlFlags &= ~WHERE_WANT_DISTINCT;
  }

  /* The number of tables in the FROM clause is limited by the number of
  ** bits in a Bitmask 
  */
  testcase( pTabList->nSrc==BMS );
  if( pTabList->nSrc>BMS ){
    sqlite4ErrorMsg(pParse, "at most %d tables in a join", BMS);
    return 0;
  }

  /* This function normally generates a nested loop for all tables in 
  ** pTabList.  But if the WHERE_ONETABLE_ONLY flag is set, then we should
  ** only generate code for the first table in pTabList and assume that
  ** any cursors associated with subsequent tables are uninitialized.
  */
  nTabList = (wctrlFlags & WHERE_ONETABLE_ONLY) ? 1 : pTabList->nSrc;

  /* Allocate and initialize the WhereInfo structure that will become the
  ** return value. A single allocation is used to store the WhereInfo
  ** struct, the contents of WhereInfo.a[], the WhereClause structure
  ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte
  ** field (type Bitmask) it must be aligned on an 8-byte boundary on
  ** some architectures. Hence the ROUND8() below.
  */
  nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
  pWInfo = sqlite4DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
  if( db->mallocFailed ){
    sqlite4DbFree(db, pWInfo);
    pWInfo = 0;
    goto whereBeginError;
  }
  pWInfo->nLevel = nTabList;
  pWInfo->pParse = pParse;
  pWInfo->pTabList = pTabList;
  pWInfo->pOrderBy = pOrderBy;
  pWInfo->pResultSet = pResultSet;
  pWInfo->iBreak = sqlite4VdbeMakeLabel(v);
  pWInfo->wctrlFlags = wctrlFlags;
  pWInfo->savedNQueryLoop = pParse->nQueryLoop;
  pMaskSet = &pWInfo->sMaskSet;
  sWLB.pWInfo = pWInfo;
  sWLB.pWC = &pWInfo->sWC;
  sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
  assert( EIGHT_BYTE_ALIGNMENT(sWLB.pNew) );
  whereLoopInit(sWLB.pNew);
#ifdef SQLITE4_DEBUG
  sWLB.pNew->cId = '*';
#endif

  /* Split the WHERE clause into separate subexpressions where each
  ** subexpression is separated by an AND operator.
  */
  initMaskSet(pMaskSet);
  whereClauseInit(&pWInfo->sWC, pWInfo);
  sqlite4ExprCodeConstants(pParse, pWhere);
  whereSplit(&pWInfo->sWC, pWhere, TK_AND);   /* IMP: R-15842-53296 */
  sqlite4CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
    
  /* Special case: a WHERE clause that is constant.  Evaluate the
  ** expression and either jump over all of the code or fall thru.
  */
  if( pWhere && (nTabList==0 || sqlite4ExprIsConstantNotJoin(pWhere)) ){
    sqlite4ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE4_JUMPIFNULL);
    pWhere = 0;
  }

  /* Special case: No FROM clause
  */
  if( nTabList==0 ){
    if( pOrderBy ) pWInfo->bOBSat = 1;
    if( wctrlFlags & WHERE_WANT_DISTINCT ){
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }
  }

  /* Assign a bit from the bitmask to every term in the FROM clause.
  **
  ** When assigning bitmask values to FROM clause cursors, it must be
  ** the case that if X is the bitmask for the N-th FROM clause term then
  ** the bitmask for all FROM clause terms to the left of the N-th term
  ** is (X-1).   An expression from the ON clause of a LEFT JOIN can use
  ** its Expr.iRightJoinTable value to find the bitmask of the right table
  ** of the join.  Subtracting one from the right table bitmask gives a
  ** bitmask for all tables to the left of the join.  Knowing the bitmask
  ** for all tables to the left of a left join is important.  Ticket #3015.
  **
  ** Note that bitmasks are created for all pTabList->nSrc tables in
  ** pTabList, not just the first nTabList tables.  nTabList is normally
  ** equal to pTabList->nSrc but might be shortened to 1 if the
  ** WHERE_ONETABLE_ONLY flag is set.
  */
  for(ii=0; ii<pTabList->nSrc; ii++){
    createMask(pMaskSet, pTabList->a[ii].iCursor);
  }
#ifndef NDEBUG
  {
    Bitmask toTheLeft = 0;
    for(ii=0; ii<pTabList->nSrc; ii++){
      Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor);
      assert( (m-1)==toTheLeft );
      toTheLeft |= m;
    }
  }
#endif

  /* Analyze all of the subexpressions.  Note that exprAnalyze() might
  ** add new virtual terms onto the end of the WHERE clause.  We do not
  ** want to analyze these virtual terms, so start analyzing at the end
  ** and work forward so that the added virtual terms are never processed.
  */
  exprAnalyzeAll(pTabList, &pWInfo->sWC);
  if( db->mallocFailed ){
    goto whereBeginError;
  }

  /* If the ORDER BY (or GROUP BY) clause contains references to general
  ** expressions, then we won't be able to satisfy it using indices, so
  ** go ahead and disable it now.
  */
  if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){
    for(ii=0; ii<pOrderBy->nExpr; ii++){
      Expr *pExpr = sqlite4ExprSkipCollate(pOrderBy->a[ii].pExpr);
      if( pExpr->op!=TK_COLUMN ){
        pWInfo->pOrderBy = pOrderBy = 0;
        break;
      }else if( pExpr->iColumn<0 ){
        break;
      }
    }
  }

  if( wctrlFlags & WHERE_WANT_DISTINCT ){
    if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
      /* The DISTINCT marking is pointless.  Ignore it. */
      pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
    }else if( pOrderBy==0 ){
      /* Try to ORDER BY the result set to make distinct processing easier */
      pWInfo->wctrlFlags |= WHERE_DISTINCTBY;
      pWInfo->pOrderBy = pResultSet;
    }
  }

  /* Construct the WhereLoop objects */
  WHERETRACE(0xffff,("*** Optimizer Start ***\n"));
  if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
    rc = whereLoopAddAll(&sWLB);
    if( rc ) goto whereBeginError;
  
    /* Display all of the WhereLoop objects if wheretrace is enabled */
#ifdef WHERETRACE_ENABLED
    if( sqlite4WhereTrace ){
      WhereLoop *p;
      int i;
      static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
                                       "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
      for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
        p->cId = zLabel[i%sizeof(zLabel)];
        whereLoopPrint(p, pTabList);
      }
    }
#endif
  
    wherePathSolver(pWInfo, 0);
    if( db->mallocFailed ) goto whereBeginError;
    if( pWInfo->pOrderBy ){
       wherePathSolver(pWInfo, pWInfo->nRowOut+1);
       if( db->mallocFailed ) goto whereBeginError;
    }
  }
  if( pWInfo->pOrderBy==0 && (db->flags & SQLITE4_ReverseOrder)!=0 ){
     pWInfo->revMask = (Bitmask)(-1);
  }
  if( pParse->nErr || NEVER(db->mallocFailed) ){
    goto whereBeginError;
  }
#ifdef WHERETRACE_ENABLED
  if( sqlite4WhereTrace ){
    int ii;
    sqlite4DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
    if( pWInfo->bOBSat ){
      sqlite4DebugPrintf(" ORDERBY=0x%llx", pWInfo->revMask);
    }
    switch( pWInfo->eDistinct ){
      case WHERE_DISTINCT_UNIQUE: {
        sqlite4DebugPrintf("  DISTINCT=unique");
        break;
      }
      case WHERE_DISTINCT_ORDERED: {
        sqlite4DebugPrintf("  DISTINCT=ordered");
        break;
      }
      case WHERE_DISTINCT_UNORDERED: {
        sqlite4DebugPrintf("  DISTINCT=unordered");
        break;
      }
    }
    sqlite4DebugPrintf("\n");
    for(ii=0; ii<pWInfo->nLevel; ii++){
      whereLoopPrint(pWInfo->a[ii].pWLoop, pTabList);
    }
  }
#endif
  /* Attempt to omit tables from the join that do not effect the result */
  if( pWInfo->nLevel>=2
   && pResultSet!=0
   && OptimizationEnabled(db, SQLITE4_OmitNoopJoin)
  ){
    Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet);
    if( pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, pOrderBy);
    while( pWInfo->nLevel>=2 ){
      WhereTerm *pTerm, *pEnd;
      pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop;
      if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break;
      if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
       && (pLoop->wsFlags & WHERE_ONEROW)==0
      ){
        break;
      }
      if( (tabUsed & pLoop->maskSelf)!=0 ) break;
      pEnd = sWLB.pWC->a + sWLB.pWC->nTerm;
      for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
        if( (pTerm->prereqAll & pLoop->maskSelf)!=0
         && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
        ){
          break;
        }
      }
      if( pTerm<pEnd ) break;
      WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
      pWInfo->nLevel--;
      nTabList--;
    }
  }
  WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
  pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;

  /* If the caller is an UPDATE or DELETE statement that is requesting
  ** to use a one-pass algorithm, determine if this is appropriate.
  ** The one-pass algorithm only works if the WHERE clause constraints
  ** the statement to update a single row.
  */
  assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 );
  if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 
   && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){
    pWInfo->okOnePass = 1;
    pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY;
  }

  /* Open all tables in the pTabList and any indices selected for
  ** searching those tables.
  */
  notReady = ~(Bitmask)0;
  for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
    Table *pTab;     /* Table to open */
    int iDb;         /* Index of database containing table/index */
    struct SrcListItem *pTabItem;

    pTabItem = &pTabList->a[pLevel->iFrom];
    pTab = pTabItem->pTab;
    iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
    pLoop = pLevel->pWLoop;
    if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
      /* Do nothing */
    }else
#ifndef SQLITE4_OMIT_VIRTUALTABLE
    if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
      const char *pVTab = (const char *)sqlite4GetVTable(db, pTab);
      int iCur = pTabItem->iCursor;
      sqlite4VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB);
    }else if( IsVirtual(pTab) ){
      /* noop */
    }else
#endif
    if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
         && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){
      int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead;
      sqlite4OpenPrimaryKey(pParse, pTabItem->iCursor, iDb, pTab, op);
      testcase( !pWInfo->okOnePass && pTab->nCol==BMS-1 );
      testcase( !pWInfo->okOnePass && pTab->nCol==BMS );
    }
#ifndef SQLITE4_OMIT_AUTOMATIC_INDEX
    if( (pLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
      constructAutomaticIndex(pParse, &pWInfo->sWC, pTabItem, notReady, pLevel);
    }else
#endif
    if( pLoop->wsFlags & WHERE_INDEXED ){
      Index *pIx = pLoop->u.btree.pIndex;
      if( pIx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){
        pLevel->iIdxCur = pTabItem->iCursor;
      }else{
        /* FIXME:  As an optimization use pTabItem->iCursor if WHERE_IDX_ONLY */
        pLevel->iIdxCur = iIdxCur ? iIdxCur : pParse->nTab++;
        if( pIx->eIndexType!=SQLITE4_INDEX_FTS5 ){
          KeyInfo *pKey = sqlite4IndexKeyinfo(pParse, pIx);
          assert( pIx->pSchema==pTab->pSchema );
          assert( pLevel->iIdxCur>=0 );
          sqlite4VdbeAddOp4(v, OP_OpenRead, pLevel->iIdxCur, pIx->tnum, iDb,
              (char*)pKey, P4_KEYINFO_HANDOFF);
          VdbeComment((v, "%s", pIx->zName));
        }
      }
    }
    sqlite4CodeVerifySchema(pParse, iDb);
    notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
  }
  pWInfo->iTop = sqlite4VdbeCurrentAddr(v);
  if( db->mallocFailed ) goto whereBeginError;

  /* Generate the code to do the search.  Each iteration of the for
  ** loop below generates code for a single nested loop of the VM
  ** program.
  */
  notReady = ~(Bitmask)0;
  for(ii=0; ii<nTabList; ii++){
    pLevel = &pWInfo->a[ii];
    explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
    notReady = codeOneLoopStart(pWInfo, ii, notReady);
    pWInfo->iContinue = pLevel->addrCont;
  }

  /* Done. */
  return pWInfo;

  /* Jump here if malloc fails */
whereBeginError:
  if( pWInfo ){
    pParse->nQueryLoop = pWInfo->savedNQueryLoop;
    whereInfoFree(db, pWInfo);
  }
  return 0;
}

/*
** Generate the end of the WHERE loop.  See comments on 
** sqlite4WhereBegin() for additional information.
*/
SQLITE4_PRIVATE void sqlite4WhereEnd(WhereInfo *pWInfo){
  Parse *pParse = pWInfo->pParse;
  Vdbe *v = pParse->pVdbe;
  int i;
  WhereLevel *pLevel;
  WhereLoop *pLoop;
  SrcList *pTabList = pWInfo->pTabList;
  sqlite4 *db = pParse->db;

  /* Generate loop termination code.
  */
  sqlite4ExprCacheClear(pParse);
  for(i=pWInfo->nLevel-1; i>=0; i--){
    pLevel = &pWInfo->a[i];
    pLoop = pLevel->pWLoop;
    sqlite4VdbeResolveLabel(v, pLevel->addrCont);
    if( pLevel->op!=OP_Noop ){
      sqlite4VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
      sqlite4VdbeChangeP5(v, pLevel->p5);
    }
    if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
      struct InLoop *pIn;
      int j;
      sqlite4VdbeResolveLabel(v, pLevel->addrNxt);
      for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
        sqlite4VdbeJumpHere(v, pIn->addrInTop+1);
        sqlite4VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
        sqlite4VdbeJumpHere(v, pIn->addrInTop-1);
      }
      sqlite4DbFree(db, pLevel->u.in.aInLoop);
    }
    sqlite4VdbeResolveLabel(v, pLevel->addrBrk);
    if( pLevel->iLeftJoin ){
      int addr;
      addr = sqlite4VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin);
      assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
           || (pLoop->wsFlags & WHERE_INDEXED)!=0 );
      if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
        sqlite4VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
      }
      if( pLoop->wsFlags & WHERE_INDEXED ){
        sqlite4VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
      }
      if( pLevel->op==OP_Return ){
        sqlite4VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst);
      }else{
        sqlite4VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst);
      }
      sqlite4VdbeJumpHere(v, addr);
    }
  }

  /* The "break" point is here, just past the end of the outer loop.
  ** Set it.
  */
  sqlite4VdbeResolveLabel(v, pWInfo->iBreak);

  /* Close all of the cursors that were opened by sqlite4WhereBegin.
  */
  assert( pWInfo->nLevel<=pTabList->nSrc );
  for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
    Index *pIdx = 0;
    struct SrcListItem *pTabItem = &pTabList->a[pLevel->iFrom];
    Table *pTab = pTabItem->pTab;
    assert( pTab!=0 );
    pLoop = pLevel->pWLoop;
    if( (pTab->tabFlags & TF_Ephemeral)==0
     && pTab->pSelect==0
     && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0
    ){
      int ws = pLoop->wsFlags;
      if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){
        sqlite4VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
      }
      if( (ws & WHERE_INDEXED)!=0 && (ws & WHERE_AUTO_INDEX)==0 ){
        if( pLevel->iIdxCur!=pTabItem->iCursor ){
          sqlite4VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
        }
      }
    }

    /* If this scan uses an index, make VDBE code substitutions to read data
    ** from the index instead of from the table where possible.  In some cases
    ** this optimization prevents the table from ever being read, which can
    ** yield a significant performance boost.
    ** 
    ** Calls to the code generator in between sqlite4WhereBegin and
    ** sqlite4WhereEnd will have created code that references the table
    ** directly.  This loop scans all that code looking for opcodes
    ** that reference the table and converts them into opcodes that
    ** reference the index.
    */
    if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
      pIdx = pLoop->u.btree.pIndex;
    }else if( pLoop->wsFlags & WHERE_MULTI_OR ){
      pIdx = pLevel->u.pCovidx;
    }
    if( pIdx && pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY 
     && !db->mallocFailed 
    ){
      int *aiCover = pIdx->aiCover;
      int nCover = pIdx->nCover;
      int k, j, last;
      VdbeOp *pOp;

      pOp = sqlite4VdbeGetOp(v, pWInfo->iTop);
      last = sqlite4VdbeCurrentAddr(v);
      for(k=pWInfo->iTop; k<last; k++, pOp++){
        if( pOp->p1!=pLevel->iTabCur ) continue;
        if( pOp->opcode==OP_Column ){
          for(j=0; j<nCover; j++){
            if( pOp->p2==aiCover[j] ){
              pOp->p2 = j;
              pOp->p1 = pLevel->iIdxCur;
              break;
            }
          }
          assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || j<nCover );
        }else if( pOp->opcode==OP_RowKey ){
          Index *pPk = sqlite4FindPrimaryKey(pTab, 0);
          pOp->p3 = pPk->tnum;
          pOp->p1 = pLevel->iIdxCur;
          pOp->opcode = OP_IdxRowkey;
        }
      }
    }

    if( (pLoop->wsFlags & WHERE_INDEXED)
     && (pLoop->u.btree.pIndex->eIndexType==SQLITE4_INDEX_FTS5)
    ){
      VdbeOp *pOp;
      VdbeOp *pEnd;

      assert( pLevel->iTabCur!=pLevel->iIdxCur );
      pOp = sqlite4VdbeGetOp(v, pWInfo->iTop);
      pEnd = &pOp[sqlite4VdbeCurrentAddr(v) - pWInfo->iTop];

      while( pOp<pEnd ){
        if( pOp->p1==pLevel->iTabCur && pOp->opcode==OP_Mifunction ){
          pOp->p1 = pLevel->iIdxCur;
        }
        pOp++;
      }
    }
  }

  /* Final cleanup
  */
  pParse->nQueryLoop = pWInfo->savedNQueryLoop;
  whereInfoFree(db, pWInfo);
  return;
}

/************** End of where.c ***********************************************/
/************** Begin file fts5.c ********************************************/
/*
** 2012 December 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
*/


/* 
** Stream numbers must be lower than this.
**
** For optimization purposes, it is assumed that a given tokenizer uses
** a set of contiguous stream numbers starting with 0. And that most
** tokens belong to stream 0.
**
** The hard limit is 63 (due to the format of "row size" records).
*/
#define SQLITE4_FTS5_NSTREAM 32

/*
** Records stored within the index:
**
** Row size record:
**   There is one "row size" record in the index for each row in the
**   indexed table. The "row size" record contains the number of tokens
**   in the associated row for each combination of a stream and column
**   number (i.e. contains the data required to find the number of
**   tokens associated with stream S present in column C of the row for
**   all S and C).
**
**   The key for the row size record is a single 0x00 byte followed by
**   a copy of the PK blob for the table row. 
**
**   The value is a series of varints. Each column of the table is
**   represented by one or more varints packed into the array.
**
**   If a column contains only stream 0 tokens, then it is represented
**   by a single varint - (nToken << 1), where nToken is the number of
**   stream 0 tokens stored in the column.
**
**   Or, if the column contains tokens from multiple streams, the first
**   varint contains a bitmask indicating which of the streams are present
**   (stored as ((bitmask << 1) | 0x01)). Following the bitmask is a
**   varint containing the number of tokens for each stream present, in
**   ascending order of stream number.
**
**   TODO: The format above is not currently implemented! Instead, there
**   is a simpler place-holder format (which consumes more space).
**
** Global size record:
**   There is a single "global size" record stored in the database. The
**   database key for this record is a single byte - 0x00.
**
**   The data for this record is a series of varint values. The first 
**   varint is the total number of rows in the table. The subsequent
**   varints make up a "row size" record containing the total number of
**   tokens for each S/C combination in all rows of the table.
**
** FTS index records:
**   The FTS index records implement the following mapping:
**
**       (token, document-pk) -> (list of instances)
**
**   The key for each index record is in the same format as the keys for
**   regular text indexes. An 0x24 byte, followed by the utf-8 representation
**   of the token, followed by 0x00, followed by the PK blob for the table
**   row.
**
**   TODO: Describe value format.
*/

/*
** Default distance value for NEAR operators.
*/
#define FTS5_DEFAULT_NEAR 10

/*
** Token types used by expression parser.
*/
#define TOKEN_EOF       0         /* end of expression - no more tokens */
#define TOKEN_PRIMITIVE 1         /* quoted string or non-keyword */
#define TOKEN_STAR      2         /* * */
#define TOKEN_PLUS      3         /* + */
#define TOKEN_NEAR      4         /* NEAR/nnn */
#define TOKEN_COLON     5         /* : */
#define TOKEN_NOT       6         /* NOT */
#define TOKEN_AND       7         /* AND */
#define TOKEN_OR        8         /* OR */
#define TOKEN_LP        9         /* ( */
#define TOKEN_RP       10         /* ) */

/*
** Each tokenizer registered with a database handle is stored as an object
** of the following type. All objects associated with a single database
** connection are stored in the singly-linked list starting at 
** sqlite4.pTokenizer and connected by Fts5Tokenizer.pNext.
*/
struct Fts5Tokenizer {
  char *zName;                   /* Name of tokenizer (nul-terminated) */
  void *pCtx;
  int (*xCreate)(void*, const char**, int, sqlite4_tokenizer**);
  int (*xTokenize)(void*, sqlite4_tokenizer*,
      const char*, int, int(*x)(void*, int, int, const char*, int, int, int)
  );
  int (*xDestroy)(sqlite4_tokenizer *);
  Fts5Tokenizer *pNext;
};

/*
** FTS5 specific index data.
**
** This object is part of a database schema, so it may be shared between
** multiple connections.
*/
struct Fts5Index {
  int nTokenizer;                 /* Elements in azTokenizer[] array */
  char **azTokenizer;             /* Name and arguments for tokenizer */
};

/*
** Expression grammar:
**
**   phrase := PRIMITIVE
**   phrase := PRIMITIVE *
**   phrase := phrase + phrase
**   phrase := phrase NEAR phrase
**
**   expr := phrase
**   expr := PRIMITIVE COLON phrase
**
**   expr := expr NOT expr
**   expr := expr AND expr
**   expr := expr OR  expr
**   expr := LP expr RP
*/

/*
** Structure types used by this module.
*/
typedef struct Fts5Expr Fts5Expr;
typedef struct Fts5ExprNode Fts5ExprNode;
typedef struct Fts5List Fts5List;
typedef struct Fts5MatchIter Fts5MatchIter;
typedef struct Fts5Parser Fts5Parser;
typedef struct Fts5ParserToken Fts5ParserToken;
typedef struct Fts5Phrase Fts5Phrase;
typedef struct Fts5Prefix Fts5Prefix;
typedef struct Fts5Size Fts5Size;
typedef struct Fts5Str Fts5Str;
typedef struct Fts5Token Fts5Token;


struct Fts5ParserToken {
  int eType;                      /* Token type */
  int n;                          /* Size of z[] in bytes */
  const char *z;                  /* Token value */
};

struct Fts5Parser {
  Fts5Tokenizer *pTokenizer;
  sqlite4_tokenizer *p;
  sqlite4 *db;                    /* Database handle */

  char *zErr;                     /* Error message (or NULL) */

  const char *zExpr;              /* Pointer to expression text (nul-term) */
  int iExpr;                      /* Current offset in zExpr */
  Fts5ParserToken next;           /* Next token */

  char **azCol;                   /* Column names of indexed table */
  int nCol;                       /* Size of azCol[] in bytes */
  int iRoot;                      /* Root page number of FTS index */

  /* Space for dequoted copies of strings */
  char *aSpace;
  int iSpace;
  int nSpace;                     /* Total size of aSpace in bytes */
};

struct Fts5List {
  u8 *aData;
  int nData;
};

struct Fts5Prefix {
  u8 *aPk;                        /* Buffer containing PK */
  int nPk;                        /* Size of PK in bytes */
  Fts5Prefix *pNext;              /* Next entry in query-time list */
  u8 *aList;
  int nList;
  int nAlloc;
};

struct Fts5Token {
  /* TODO: The first three members are redundant in some senses, since the
  ** same information is encoded in the aPrefix[]/nPrefix key. */
  int bPrefix;                    /* True for a prefix search */
  int n;                          /* Size of z[] in bytes */
  char *z;                        /* Token value */

  KVByteArray *aPrefix;           /* KV prefix to iterate through */
  KVSize nPrefix;                 /* Size of aPrefix in bytes */
  KVCursor *pCsr;                 /* Cursor to iterate thru entries for token */
  Fts5Prefix *pPrefix;            /* Head of prefix list */
};

struct Fts5Str {
  Fts5Token *aToken;
  int nToken;
  u8 *aList;
  int nList;
  int nListAlloc;
};

struct Fts5Phrase {
  int iCol;                       /* Column of table to search (-1 -> all) */
  int nStr;
  Fts5Str *aStr;
  int *aiNear;
};

struct Fts5ExprNode {
  int eType;
  Fts5Phrase *pPhrase;
  Fts5ExprNode *pLeft;
  Fts5ExprNode *pRight;
  const u8 *aPk;                  /* Primary key of current entry (or null) */
  int nPk;                        /* Size of aPk[] in bytes */
};

struct Fts5Expr {
  Fts5ExprNode *pRoot;            /* Root node of expression */
  int nPhrase;                    /* Number of Fts5Str objects in query */
  Fts5Str **apPhrase;             /* All Fts5Str objects */
};

/*
** FTS5 specific cursor data.
*/
struct Fts5Cursor {
  sqlite4 *db;
  Fts5Info *pInfo;
  Fts5Expr *pExpr;                /* MATCH expression for this cursor */
  char *zExpr;                    /* Full text of MATCH expression */
  KVByteArray *aKey;              /* Buffer for primary key */
  int nKeyAlloc;                  /* Bytes allocated at aKey[] */

  KVCursor *pCsr;                 /* Cursor used to retrive values */
  Mem *aMem;                      /* Array of column values */
  int bMemValid;                  /* True if contents of aMem[] are valid */

  Fts5Size *pSz;                  /* Local size data */
  Fts5Size *pGlobal;              /* Global size data */
  i64 nGlobal;                    /* Total number of rows in table */

  /* Arrays used by sqlite4_mi_row_count(). */
  int *anRowCS;
  int *anRowC;
  int *anRowS;
  int *anRow;

  Fts5MatchIter *pIter;           /* Used by mi_match_detail() */
};

/*
** A deserialized 'size record' (see above).
*/
struct Fts5Size {
  int nCol;                       /* Number of columns in indexed table */
  int nStream;                    /* Number of streams */
  i64 *aSz;                       /* Token count for each C/S */
};

/*
** This type is used when reading (decoding) an instance-list.
*/
typedef struct InstanceList InstanceList;
struct InstanceList {
  u8 *aList;
  int nList;
  int iList;

  /* The current entry */
  int iCol;
  int iStream;
  int iOff;
};

/*
** An instance of this structure is used by the sqlite4_mi_match_detail()
** API to iterate through matches. 
*/
struct Fts5MatchIter {
  int bValid;                     /* True if aList[] is current row */
  int iCurrent;                   /* Current index in aList[] (or -1) */
  int iMatch;                     /* Current iMatch value */
  InstanceList *aList;            /* One iterator for each phrase in expr */
};

/*
** Return true for EOF, or false if the next entry is valid.
*/
static int fts5InstanceListNext(InstanceList *p){
  int i = p->iList;
  int bRet = 1;
  
  while( bRet && i<p->nList ){
    u32 iVal;
    i += getVarint32(&p->aList[i], iVal);
    if( (iVal & 0x03)==0x01 ){
      p->iCol = (iVal>>2);
      p->iOff = 0;
    }
    else if( (iVal & 0x03)==0x03 ){
      p->iStream = (iVal>>2);
    }
    else{
      p->iOff += (iVal>>1);
      bRet = 0;
    }
  }
  if( bRet ){
    p->aList = 0;
  }

  p->iList = i;
  return bRet;
}

static int fts5InstanceListEof(InstanceList *p){
  return (p->aList==0);
}

static void fts5InstanceListAppend(
  InstanceList *p,                /* Instance list to append to */
  int iCol,                       /* Column of new entry */
  int iStream,                    /* Weight of new entry */
  int iOff                        /* Offset of new entry */
){
  assert( iCol>=p->iCol );
  assert( iCol>p->iCol || iOff>=p->iOff );

  if( iCol!=p->iCol ){
    p->iList += putVarint32(&p->aList[p->iList], (iCol<<2)|0x01);
    p->iCol = iCol;
    p->iOff = 0;
  }

  if( iStream!=p->iStream ){
    p->iList += putVarint32(&p->aList[p->iList], (iStream<<2)|0x03);
    p->iStream = iStream;
  }

  p->iList += putVarint32(&p->aList[p->iList], (iOff-p->iOff)<<1);
  p->iOff = iOff;

  assert( p->iList<=p->nList );
}

static void fts5InstanceListInit(u8 *aList, int nList, InstanceList *p){
  memset(p, 0, sizeof(InstanceList));
  p->aList = aList;
  p->nList = nList;
}

/*
** Return true if argument c is one of the special non-whitespace 
** characters that ends an unquoted expression token. 
*/
static int fts5IsSpecial(char c){
  return (c==':' || c=='(' || c==')' || c=='+' || c=='"' || c=='*');
}

static int fts5NextToken(
  Fts5Parser *pParse,             /* Parser context */
  Fts5ParserToken *p              /* OUT: Populate this object */
){
  const char *z = pParse->zExpr;
  char c;

  memset(p, 0, sizeof(Fts5ParserToken));

  /* Skip past any whitespace */
  while( sqlite4Isspace(z[pParse->iExpr]) ) pParse->iExpr++;

  c = z[pParse->iExpr];
  if( c=='\0' ){
    p->eType = TOKEN_EOF;
  }

  else if( c=='(' ){
    pParse->iExpr++;
    p->eType = TOKEN_LP;
  }

  else if( c==')' ){
    pParse->iExpr++;
    p->eType = TOKEN_RP;
  }

  else if( c==':' ){
    pParse->iExpr++;
    p->eType = TOKEN_COLON;
  }

  else if( c=='+' ){
    pParse->iExpr++;
    p->eType = TOKEN_PLUS;
  }

  else if( c=='*' ){
    pParse->iExpr++;
    p->eType = TOKEN_STAR;
  }

  else if( c=='"' ){
    char *zOut = &pParse->aSpace[pParse->iSpace];
    const char *zPrimitive = zOut;
    int i = pParse->iExpr+1;

    while( z[i] ){
      if( z[i]=='"' ){
        if( z[i+1]=='"' ){
          i++;
        }else{
          break;
        }
      }
      *zOut++ = z[i];
      i++;
    }
    if( z[i]!='"' ){
      /* Mismatched quotation mark */
      return SQLITE4_ERROR;
    }

    pParse->iExpr = i+1;
    p->eType = TOKEN_PRIMITIVE;
    p->z = zPrimitive;
    p->n = (zOut - zPrimitive);
    pParse->iSpace += (zOut - zPrimitive);
  }

  else{
    const char *zPrimitive = &z[pParse->iExpr];
    int n = 0;
    while( zPrimitive[n] 
        && fts5IsSpecial(zPrimitive[n])==0
        && sqlite4Isspace(zPrimitive[n])==0 
    ){
      n++;
    }
    pParse->iExpr += n;

    if( n>=4 && memcmp(zPrimitive, "NEAR", 4)==0 ){
      int nNear = FTS5_DEFAULT_NEAR;
      if( n>4 ){
        int i;
        nNear = 0;
        for(i=5; i<n; i++){
          if( !sqlite4Isdigit(zPrimitive[i]) ) break;
          nNear = nNear*10 + zPrimitive[i]-'0';
        }
        if( n<6 || zPrimitive[4]!='/' || i<n ){
          return SQLITE4_ERROR;
        }
      }
      p->eType = TOKEN_NEAR;
      p->n = nNear;
      p->z = 0;
    }else if( n==3 && memcmp(zPrimitive, "NOT", 3)==0 ){
      p->eType = TOKEN_NOT;
    }
    else if( n==2 && memcmp(zPrimitive, "OR", 2)==0 ){
      p->eType = TOKEN_OR;
    }
    else if( n==3 && memcmp(zPrimitive, "AND", 3)==0 ){
      p->eType = TOKEN_AND;
    }else{
      p->eType = TOKEN_PRIMITIVE;
      p->z = zPrimitive;
      p->n = n;
    }
  }

  return SQLITE4_OK;
}

static int fts5NextToken2(
  Fts5Parser *pParse,
  Fts5ParserToken *p
){
  int rc = SQLITE4_OK;
  if( pParse->iExpr==0 ){
    rc = fts5NextToken(pParse, p);
  }else{
    *p = pParse->next;
  }

  if( rc==SQLITE4_OK && p->eType!=TOKEN_EOF ){
    rc = fts5NextToken(pParse, &pParse->next);
  }

  return rc;
}

static int fts5PhraseNewStr(
  Fts5Parser *pParse,             /* Expression parsing context */
  Fts5Phrase *pPhrase,            /* Phrase to add a new Fts5Str to */
  int nNear                       /* Value of nnn in NEAR/nnn operator */
){
  const int nIncr = 4;

  if( (pPhrase->nStr % nIncr)==0 ){
    Fts5Str *aNew;
    aNew = (Fts5Str *)sqlite4DbRealloc(pParse->db, 
        pPhrase->aStr, (pPhrase->nStr+nIncr)*sizeof(Fts5Str)
    );
    if( !aNew ) return SQLITE4_NOMEM;
    memset(&aNew[pPhrase->nStr], 0, nIncr*sizeof(Fts5Str));
    pPhrase->aStr = aNew;
  }
  if( pPhrase->nStr>0 ){
    if( ((pPhrase->nStr-1) % nIncr)==0 ){
      int *aNew;
      aNew = (int *)sqlite4DbRealloc(pParse->db, 
        pPhrase->aiNear, (pPhrase->nStr+nIncr-1)*sizeof(int)
      );
      if( !aNew ) return SQLITE4_NOMEM;
      pPhrase->aiNear = aNew;
    }
    pPhrase->aiNear[pPhrase->nStr-1] = nNear;
  }

  pPhrase->nStr++;
  return SQLITE4_OK;
}

/*
** Callback for fts5CountTokens().
*/
static int fts5CountTokensCb(
  void *pCtx, 
  int iStream, 
  int iOff, 
  const char *z, int n,
  int iSrc, int nSrc
){
  (*((int *)pCtx))++;
  return 0;
}

/*
** Count the number of tokens in document zDoc/nDoc using the tokenizer and
** tokenizer instance supplied as the first two arguments. Set *pnToken to
** the result before returning.
*/
static int fts5CountTokens(
  Fts5Tokenizer *pTokenizer,
  sqlite4_tokenizer *p,
  const char *zDoc,
  int nDoc,
  int *pnToken
){
  int nToken = 0;
  int rc;
  rc = pTokenizer->xTokenize((void *)&nToken, p, zDoc, nDoc, fts5CountTokensCb);
  *pnToken = nToken;
  return rc;
}

struct AppendTokensCtx {
  Fts5Parser *pParse;
  Fts5Str *pStr;
};

static int fts5AppendTokensCb(
  void *pCtx, 
  int iStream, 
  int iOff, 
  const char *z, int n, 
  int iSrc, int nSrc
){
  struct AppendTokensCtx *p = (struct AppendTokensCtx *)pCtx;
  Fts5Parser *pParse = p->pParse;
  Fts5Token *pToken;
  char *zSpace;
  int nUsed;

  pToken = &p->pStr->aToken[p->pStr->nToken];

  zSpace = &pParse->aSpace[pParse->iSpace];
  nUsed = putVarint32((u8 *)zSpace, pParse->iRoot);
  zSpace[nUsed++] = 0x24;
  pToken->bPrefix = 0;
  pToken->pPrefix = 0;
  pToken->z = &zSpace[nUsed];
  pToken->n = n;
  memcpy(pToken->z, z, n);
  pToken->z[n] = '\0';

  nUsed += (n+1);
  pToken->aPrefix = (u8 *)zSpace;
  pToken->nPrefix = nUsed;
  pToken->pCsr = 0;
  pParse->iSpace += nUsed;
  p->pStr->nToken++;

  assert( pParse->iSpace<=pParse->nSpace );
  return 0;
}

static int fts5AppendTokens( 
  Fts5Parser *pParse,
  Fts5Str *pStr, const char *zPrim,
  int nPrim
){
  struct AppendTokensCtx ctx;
  ctx.pParse = pParse;
  ctx.pStr = pStr;

  return pParse->pTokenizer->xTokenize(
      (void *)&ctx, pParse->p , zPrim, nPrim, fts5AppendTokensCb
  );
}

/*
** Append a new token to the current phrase.
*/
static int fts5PhraseAppend(
  Fts5Parser *pParse,
  Fts5Phrase *pPhrase,
  const char *zPrim,
  int nPrim
){
  Fts5Tokenizer *pTok = pParse->pTokenizer;
  int nToken;
  int rc;

  rc = fts5CountTokens(pTok, pParse->p, zPrim, nPrim, &nToken);
  if( rc==SQLITE4_OK && nToken>0 ){
    /* Extend the size of the token array by nToken entries */
    Fts5Str *pStr = &pPhrase->aStr[pPhrase->nStr-1];

    pStr->aToken = sqlite4DbReallocOrFree(pParse->db, pStr->aToken,
        (pStr->nToken + nToken) * sizeof(Fts5Token)
    );
    if( !pStr->aToken ){
      rc = SQLITE4_NOMEM;
    }else{
      rc = fts5AppendTokens(pParse, pStr, zPrim, nPrim);
    }
  }

  return rc;
}

static int fts5PhraseAppendStar(
  Fts5Parser *pParse,
  Fts5Phrase *pPhrase
){
  Fts5Str *pStr = &pPhrase->aStr[pPhrase->nStr-1];
  Fts5Token *p = &pStr->aToken[pStr->nToken-1];

  if( p->bPrefix ){
    return SQLITE4_ERROR;
  }
  p->bPrefix = 1;
  p->nPrefix--;
  return SQLITE4_OK;
}

static void fts5PhraseFree(sqlite4 *db, Fts5Phrase *p){
  if( p ){
    int i;
    for(i=0; i<p->nStr; i++){
      int iTok;
      for(iTok=0; iTok<p->aStr[i].nToken; iTok++){
        sqlite4KVCursorClose(p->aStr[i].aToken[iTok].pCsr);
      }
      sqlite4DbFree(db, p->aStr[i].aToken);
      sqlite4DbFree(db, p->aStr[i].aList);
    }
    sqlite4DbFree(db, p->aiNear);
    sqlite4DbFree(db, p->aStr);
    sqlite4DbFree(db, p);
  }
}

static int fts5NextTokenOrPhrase(
  Fts5Parser *pParse,             /* Parser context */
  int *peType,                    /* OUT: Token type */
  Fts5Phrase **ppPhrase           /* OUT: New phrase object */
){
  int rc;
  Fts5Phrase *pPhrase = 0;
  Fts5ParserToken t;

  rc = fts5NextToken2(pParse, &t);
  *peType = t.eType;
  if( rc==SQLITE4_OK && t.eType==TOKEN_PRIMITIVE ){

    /* Allocate the Fts5Phrase object */
    pPhrase = sqlite4DbMallocZero(pParse->db, sizeof(Fts5Phrase));
    if( pPhrase==0 ){
      rc = SQLITE4_NOMEM;
      goto token_or_phrase_out;
    }
    pPhrase->iCol = -1;

    /* Check if this first primitive is a column name or not. */
    if( pParse->next.eType==TOKEN_COLON ){
      int iCol;
      for(iCol=0; iCol<pParse->nCol; iCol++){
        if( sqlite4_strnicmp(pParse->azCol[iCol], t.z, t.n)==0 ) break;
      }
      if( iCol==pParse->nCol ){
        pParse->zErr = sqlite4MPrintf(pParse->db, 
            "fts5: no such column: %.*s", t.n, t.z
        );
        rc = SQLITE4_ERROR;
        goto token_or_phrase_out;
      }
      pPhrase->iCol = iCol;

      rc = fts5NextToken2(pParse, &t);
      if( rc==SQLITE4_OK ) rc = fts5NextToken2(pParse, &t);
      if( rc==SQLITE4_OK && t.eType!=TOKEN_PRIMITIVE ){
        rc = SQLITE4_ERROR;
      }
      if( rc!=SQLITE4_OK ) goto token_or_phrase_out;
    }

    /* Add the first Fts5Str to the new phrase object. Populate it with the
    ** results of tokenizing t.z/t.n. */
    rc = fts5PhraseNewStr(pParse, pPhrase, 0);
    if( rc==SQLITE4_OK ){
      rc = fts5PhraseAppend(pParse, pPhrase, t.z, t.n);
    }
    if( rc==SQLITE4_OK && pParse->next.eType==TOKEN_STAR ){
      fts5NextToken2(pParse, &t);
      rc = fts5PhraseAppendStar(pParse, pPhrase);
    }

    /* Add any further primitives connected by "+" or NEAR operators. */
    while( rc==SQLITE4_OK && 
        (pParse->next.eType==TOKEN_PLUS || pParse->next.eType==TOKEN_NEAR)
    ){
      rc = fts5NextToken2(pParse, &t);
      if( rc==SQLITE4_OK ){
        if( t.eType==TOKEN_NEAR ){
          rc = fts5PhraseNewStr(pParse, pPhrase, t.n);
          if( rc!=SQLITE4_OK ) goto token_or_phrase_out;
        }
        rc = fts5NextToken2(pParse, &t);
        if( rc!=SQLITE4_OK ) goto token_or_phrase_out;
        if( t.eType!=TOKEN_PRIMITIVE ){
          rc = SQLITE4_ERROR;
        }else{
          rc = fts5PhraseAppend(pParse, pPhrase, t.z, t.n);
          if( rc==SQLITE4_OK && pParse->next.eType==TOKEN_STAR ){
            fts5NextToken2(pParse, &t);
            rc = fts5PhraseAppendStar(pParse, pPhrase);
          }
        }
      }
    }
  }

 token_or_phrase_out:
  if( rc!=SQLITE4_OK ){
    fts5PhraseFree(pParse->db, pPhrase);
  }else{
    *ppPhrase = pPhrase;
  }
  return rc;
}

static void fts5FreeExprNode(sqlite4 *db, Fts5ExprNode *pNode){
  if( pNode ){
    fts5PhraseFree(db, pNode->pPhrase);
    fts5FreeExprNode(db, pNode->pLeft);
    fts5FreeExprNode(db, pNode->pRight);
    sqlite4DbFree(db, pNode);
  }
}

static void fts5ExpressionFree(sqlite4 *db, Fts5Expr *pExpr){
  if( pExpr ){
    fts5FreeExprNode(db, pExpr->pRoot);
    sqlite4DbFree(db, pExpr->apPhrase);
    sqlite4DbFree(db, pExpr);
  }
}

typedef struct ExprHier ExprHier;
struct ExprHier {
  Fts5ExprNode **ppNode;
  int nOpen;
};

static int fts5GrowExprHier(
  sqlite4 *db, 
  int *pnAlloc, 
  ExprHier **paHier, 
  int nReq
){
  int rc = SQLITE4_OK;
  int nAlloc = *pnAlloc;
  if( nAlloc<nReq ){
    ExprHier *aNew;
    nAlloc += 8;
    aNew = (ExprHier *)sqlite4DbReallocOrFree(
        db, *paHier, nAlloc*sizeof(ExprHier)
    );
    if( aNew==0 ) rc = SQLITE4_NOMEM;
    *paHier = aNew;
  }
  return rc;
}

static int fts5AddBinary(
  sqlite4 *db, 
  int eType,
  int *pnHier, 
  int *pnHierAlloc, 
  ExprHier **paHier
){
  Fts5ExprNode *pNode;
  Fts5ExprNode **pp;
  int rc;

  rc = fts5GrowExprHier(db, pnHierAlloc, paHier, *pnHier+1);
  if( rc!=SQLITE4_OK ) return rc;
  pNode = sqlite4DbMallocZero(db, sizeof(Fts5ExprNode));
  if( !pNode ) return SQLITE4_NOMEM;
  pNode->eType = eType;

  pp = (*paHier)[*pnHier-1].ppNode;
  pNode->pLeft = *pp;
  *pp = pNode;
  (*paHier)[*pnHier].ppNode = &pNode->pRight;
  (*paHier)[*pnHier].nOpen = 0;
  (*pnHier)++;

  return SQLITE4_OK;
}

static void fts5FindStrings(Fts5ExprNode *p, Fts5Str ***papStr){
  if( p ){
    if( p->eType==TOKEN_PRIMITIVE ){
      int i;
      Fts5Str *aStr = p->pPhrase->aStr;
      for(i=0; i<p->pPhrase->nStr; i++){
        **papStr = &aStr[i];
        (*papStr)++;
      }
    }
    fts5FindStrings(p->pLeft, papStr);
    fts5FindStrings(p->pRight, papStr);
  }
}

static int fts5ParseExpression(
  sqlite4 *db,                    /* Database handle */
  Fts5Tokenizer *pTokenizer,      /* Tokenizer module */
  sqlite4_tokenizer *p,           /* Tokenizer instance */
  int iRoot,                      /* Root page number of FTS index */
  char **azCol,                   /* Array of column names (nul-term'd) */
  int nCol,                       /* Size of array azCol[] */
  const char *zExpr,              /* FTS expression text */
  Fts5Expr **ppExpr,              /* OUT: Expression object */
  char **pzErr                    /* OUT: Error message */
){
  int rc = SQLITE4_OK;
  Fts5Parser sParse;
  int nStr = 0;
  int nExpr;
  int i;
  Fts5Expr *pExpr;

  int nHier = 0;
  int nHierAlloc = 0;
  ExprHier *aHier = 0;

  nExpr = sqlite4Strlen30(zExpr);
  memset(&sParse, 0, sizeof(Fts5Parser));
  sParse.zExpr = zExpr;
  sParse.azCol = azCol;
  sParse.nCol = nCol;
  sParse.pTokenizer = pTokenizer;
  sParse.p = p;
  sParse.db = db;
  sParse.iRoot = iRoot;

  pExpr = sqlite4DbMallocZero(db, sizeof(Fts5Expr) + nExpr*4);
  if( !pExpr ) return SQLITE4_NOMEM;
  sParse.aSpace = (char *)&pExpr[1];
  sParse.nSpace = nExpr*4;

  rc = fts5GrowExprHier(db, &nHierAlloc, &aHier, 1);
  if( rc==SQLITE4_OK ){
    aHier[0].ppNode = &pExpr->pRoot;
    aHier[0].nOpen = 0;
    nHier = 1;
  }

  while( rc==SQLITE4_OK ){
    int eType = 0;
    Fts5Phrase *pPhrase = 0;
    Fts5ExprNode *pNode = 0;

    rc = fts5NextTokenOrPhrase(&sParse, &eType, &pPhrase);
    if( rc!=SQLITE4_OK || eType==TOKEN_EOF ) break;

    switch( eType ){
      case TOKEN_PRIMITIVE: {
        Fts5ExprNode **pp = aHier[nHier-1].ppNode;
        if( *pp ){
          rc = fts5AddBinary(db, TOKEN_AND, &nHier, &nHierAlloc, &aHier);
          pp = aHier[nHier-1].ppNode;
        }
        if( rc==SQLITE4_OK ){
          pNode = sqlite4DbMallocZero(db, sizeof(Fts5ExprNode));
          if( pNode==0 ){
            rc = SQLITE4_NOMEM;
          }else{
            pNode->eType = TOKEN_PRIMITIVE;
            pNode->pPhrase = pPhrase;
            *pp = pNode;
          }
        }
        nStr += pPhrase->nStr;
        break;
      }

      case TOKEN_AND:
      case TOKEN_OR:
      case TOKEN_NOT: {
        Fts5ExprNode **pp = aHier[nHier-1].ppNode;

        if( *pp==0 ){
          rc = SQLITE4_ERROR;
        }else{
          while( nHier>1 
             && aHier[nHier-1].nOpen==0 
             && (*aHier[nHier-2].ppNode)->eType  < eType 
          ){
            nHier--;
          }

          rc = fts5AddBinary(db, eType, &nHier, &nHierAlloc, &aHier);
        }
        break;
      }

      case TOKEN_LP: {
        Fts5ExprNode **pp = aHier[nHier-1].ppNode;
        if( *pp ){
          rc = SQLITE4_ERROR;
        }else{
          aHier[nHier-1].nOpen++;
        }
        break;
      }

      case TOKEN_RP: {
        Fts5ExprNode **pp = aHier[nHier-1].ppNode;
        if( *pp==0 ){
          rc = SQLITE4_ERROR;
        }else{
          for(i=nHier-1; i>=0; i--){
            if( aHier[i].nOpen>0 ) break;
          }
          if( i<0 ){
            rc = SQLITE4_ERROR;
          }else{
            aHier[i].nOpen--;
            nHier = i+1;
          }
        }
        break;
      }

      default:
        rc = SQLITE4_ERROR;
        break;
    }

    if( rc!=SQLITE4_OK ){
      sqlite4DbFree(db, pNode);
      break;
    }
  }

  if( rc==SQLITE4_OK && *aHier[nHier-1].ppNode==0 ){
    rc = SQLITE4_ERROR;
  }
  for(i=0; rc==SQLITE4_OK && i<nHier; i++){
    if( aHier[i].nOpen>0 ) rc = SQLITE4_ERROR;
  }

  if( rc==SQLITE4_OK ){
    pExpr->nPhrase = nStr;
    pExpr->apPhrase = (Fts5Str**)sqlite4DbMallocZero(db, sizeof(Fts5Str*)*nStr);
    if( pExpr->apPhrase==0 ){
      rc = SQLITE4_NOMEM;
    }else{
      Fts5Str **a = pExpr->apPhrase;
      fts5FindStrings(pExpr->pRoot, &a);
    }
  }

  if( rc!=SQLITE4_OK ){
    fts5ExpressionFree(db, pExpr);
    *pzErr = sParse.zErr;
    pExpr = 0;
  }
  *ppExpr = pExpr;
  sqlite4DbFree(db, aHier);
  return rc;
}

/*
** Search for the Fts5Tokenizer object named zName. Return a pointer to it
** if it exists, or NULL otherwise.
*/
static Fts5Tokenizer *fts5FindTokenizer(sqlite4 *db, const char *zName){
  Fts5Tokenizer *p;
  for(p=db->pTokenizer; p; p=p->pNext){
    if( 0==sqlite4_stricmp(zName, p->zName) ) break;
  }
  return p;
}

static void fts5TokenizerCreate(
  Parse *pParse, 
  Fts5Index *pFts, 
  Fts5Tokenizer **ppTokenizer,
  sqlite4_tokenizer **pp
){
  Fts5Tokenizer *pTok;
  char *zTok;                     /* Tokenizer name */
  const char **azArg;             /* Tokenizer arguments */
  int nArg;                       /* Number of elements in azArg */

  if( pFts->nTokenizer ){
    zTok = pFts->azTokenizer[0];
    azArg = (const char **)&pFts->azTokenizer[1];
    nArg = pFts->nTokenizer-1;
  }else{
    zTok = "simple";
    azArg = 0;
    nArg = 0;
  }
 
  *ppTokenizer = pTok = fts5FindTokenizer(pParse->db, zTok);
  if( !pTok ){
    sqlite4ErrorMsg(pParse, "no such tokenizer: \"%s\"", zTok);
  }else{
    int rc = pTok->xCreate(pTok->pCtx, azArg, nArg, pp);
    if( rc!=SQLITE4_OK ){
      assert( *pp==0 );
      sqlite4ErrorMsg(pParse, "error creating tokenizer");
    }
  }
}

static void fts5TokenizerDestroy(Fts5Tokenizer *pTok, sqlite4_tokenizer *p){
  if( p ) pTok->xDestroy(p);
}

SQLITE4_PRIVATE void sqlite4ShutdownFts5(sqlite4 *db){
  Fts5Tokenizer *p;
  Fts5Tokenizer *pNext;
  for(p=db->pTokenizer; p; p=pNext){
    pNext = p->pNext;
    sqlite4DbFree(db, p);
  }
}

/*
** This function is used to install custom FTS tokenizers.
*/
SQLITE4_API int sqlite4_create_tokenizer(
  sqlite4 *db,
  const char *zName,
  void *pCtx,
  int (*xCreate)(void*, const char**, int, sqlite4_tokenizer**),
  int (*xTokenize)(void*, sqlite4_tokenizer*,
      const char*, int, int(*x)(void*, int, int, const char*, int, int, int)
  ),
  int (*xDestroy)(sqlite4_tokenizer *)
){
  int rc = SQLITE4_OK;
  sqlite4_mutex_enter(db->mutex);

  /* It is not possible to override an existing tokenizer */
  if( fts5FindTokenizer(db, zName) ){
    rc = SQLITE4_ERROR;
  }else{
    int nName = sqlite4Strlen30(zName);
    Fts5Tokenizer *pTokenizer = (Fts5Tokenizer *)sqlite4DbMallocZero(db, 
        sizeof(Fts5Tokenizer) + nName+1
    );
    if( !pTokenizer ){
      rc = SQLITE4_NOMEM;
    }else{
      pTokenizer->pCtx = pCtx;
      pTokenizer->xCreate = xCreate;
      pTokenizer->xTokenize = xTokenize;
      pTokenizer->xDestroy = xDestroy;
      pTokenizer->zName = (char *)&pTokenizer[1];
      memcpy(pTokenizer->zName, zName, nName+1);

      pTokenizer->pNext = db->pTokenizer;
      db->pTokenizer = pTokenizer;
    }
  }

  rc = sqlite4ApiExit(db, rc);
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Return the size of an Fts5Index structure, in bytes.
*/
SQLITE4_PRIVATE int sqlite4Fts5IndexSz(void){ 
  return sizeof(Fts5Index); 
}

/*
** Initialize the fts5 specific part of the index object passed as the
** second argument.
*/
SQLITE4_PRIVATE void sqlite4Fts5IndexInit(Parse *pParse, Index *pIdx, ExprList *pArgs){
  Fts5Index *pFts = pIdx->pFts;

  if( pArgs ){
    int i;
    for(i=0; pParse->nErr==0 && i<pArgs->nExpr; i++){
      char *zArg = pArgs->a[i].zName;
      char *zVal = pArgs->a[i].pExpr->u.zToken;

      if( zArg && sqlite4_stricmp(zArg, "tokenizer")==0 ){
        /* zVal is the name of the tokenizer to use. Any subsequent arguments
         ** that do not contain assignment operators (=) are also passed to
         ** the tokenizer. Figure out how many bytes of space are required for
         ** all.  */
        int j;
        char *pSpace;
        int nByte = sqlite4Strlen30(zVal) + 1;
        for(j=i+1; j<pArgs->nExpr; j++){
          ExprListItem *pItem = &pArgs->a[j];
          if( pItem->zName ) break;
          nByte += sqlite4Strlen30(pItem->pExpr->u.zToken) + 1;
        }
        nByte += sizeof(char *) * (j-i);
        pFts->azTokenizer = (char **)sqlite4DbMallocZero(pParse->db, nByte);
        if( pFts->azTokenizer==0 ) return;
        pFts->nTokenizer = (j-i);

        pSpace = (char *)&pFts->azTokenizer[j-i];
        for(j=i; j<pArgs->nExpr; j++){
          ExprListItem *pItem = &pArgs->a[j];
          if( pItem->zName && j>i ){
            break;
          }else{
            int nToken = sqlite4Strlen30(pItem->pExpr->u.zToken);
            memcpy(pSpace, pItem->pExpr->u.zToken, nToken+1);
            pFts->azTokenizer[j-i] = pSpace;
            pSpace += nToken+1;
          }
        }

        /* If this function is being called as part of a CREATE INDEX statement
        ** issued by the user (to create a new index) check if the tokenizer
        ** is valid. If not, return an error. Do not do this if this function
        ** is being called as part of parsing an existing database schema.
        */
        if( pParse->db->init.busy==0 ){
          Fts5Tokenizer *pTok = 0;
          sqlite4_tokenizer *t = 0;

          fts5TokenizerCreate(pParse, pFts, &pTok, &t);
          fts5TokenizerDestroy(pTok, t);
        }
      }
      else{
        sqlite4ErrorMsg(pParse,"unrecognized argument: \"%s\"", zArg?zArg:zVal);
      }
    }
  }
}

SQLITE4_PRIVATE void sqlite4Fts5IndexFree(sqlite4 *db, Index *pIdx){
  if( pIdx->pFts ){
    sqlite4DbFree(db, pIdx->pFts->azTokenizer);
  }
}


/*
** Context structure passed to tokenizer callback when tokenizing a document.
**
** The hash table maps between tokens and TokenizeTerm structures.
**
** TokenizeTerm structures are allocated using sqlite4DbMalloc(). Immediately
** following the structure in memory is the token itself (TokenizeTerm.nToken
** bytes of data). Following this is the list of token instances in the same
** format as it is stored in the database. 
**
** All of the above is a single allocation, size TokenizeTerm.nAlloc bytes.
** If the initial allocation is too small, it is extended using
** sqlite4DbRealloc().
*/
typedef struct TokenizeCtx TokenizeCtx;
typedef struct TokenizeTerm TokenizeTerm;
struct TokenizeCtx {
  int rc;
  int iCol;
  int nCol;                       /* Number of columns in table */
  sqlite4 *db;
  int nMax;
  i64 *aSz;                       /* Number of tokens in each column/stream */
  int nStream;                    /* Number of streams in document */
  Hash hash;
};
struct TokenizeTerm {
  int iStream;                    /* Weight of previous entry */
  int iCol;                       /* Column containing previous entry */
  int iOff;                       /* Token offset of previous entry */
  int nToken;                     /* Size of token in bytes */
  int nData;                      /* Bytes of data in value */
  int nAlloc;                     /* Bytes of data allocated */
};

TokenizeTerm *fts5TokenizeAppendInt(
  TokenizeCtx *p, 
  TokenizeTerm *pTerm, 
  int iVal
){
  unsigned char *a;
  int nSpace = pTerm->nAlloc-pTerm->nData-pTerm->nToken-sizeof(TokenizeTerm);

  if( nSpace < 5 ){
    int nAlloc = (pTerm->nAlloc<256) ? 256 : pTerm->nAlloc * 2;
    pTerm = sqlite4DbReallocOrFree(p->db, pTerm, nAlloc);
    if( !pTerm ) return 0;
    pTerm->nAlloc = sqlite4DbMallocSize(p->db, pTerm);
  }

  a = &(((unsigned char *)&pTerm[1])[pTerm->nToken+pTerm->nData]);
  pTerm->nData += putVarint32(a, iVal);
  return pTerm;
}

static int fts5TokenizeCb(
  void *pCtx, 
  int iStream, 
  int iOff,
  const char *zToken, 
  int nToken, 
  int iSrc, 
  int nSrc
){
  TokenizeCtx *p = (TokenizeCtx *)pCtx;
  sqlite4 *db = p->db;
  TokenizeTerm *pTerm = 0;

  /* TODO: Error here if iStream is out of range */

  if( nToken>p->nMax ) p->nMax = nToken;

  if( iStream>=p->nStream ){
    int iCol;
    int nOld = p->nStream;
    int nNew = 4;
    i64 *aNew;
    
    while( nNew<=iStream ) nNew = nNew*2;
    aNew = sqlite4DbMallocZero(db, nNew*p->nCol*sizeof(i64));
    if( aNew==0 ) goto tokenize_cb_out;

    for(iCol=0; iCol<p->nCol; iCol++){
      int iStr;
      for(iStr=0; iStr<nOld; iStr++){
        aNew[nNew*iCol + iStr] = p->aSz[nOld*iCol + iStr];
      }
    }

    sqlite4DbFree(db, p->aSz);
    p->aSz = aNew;
    p->nStream = nNew;
  }
  p->aSz[p->iCol * p->nStream + iStream]++;

  pTerm = (TokenizeTerm *)sqlite4HashFind(&p->hash, zToken, nToken);
  if( pTerm==0 ){
    /* Size the initial allocation so that it fits in the lookaside buffer */
    int nAlloc = sizeof(TokenizeTerm) + nToken + 32;

    pTerm = sqlite4DbMallocZero(p->db, nAlloc);
    if( pTerm ){
      pTerm->nAlloc = sqlite4DbMallocSize(p->db, pTerm);
      pTerm->nToken = nToken;
      memcpy(&pTerm[1], zToken, nToken);
    }
    if( pTerm==0 ) goto tokenize_cb_out;
  }else{
    sqlite4HashInsert(&p->hash, zToken, nToken, 0);
  }

  if( iStream!=pTerm->iStream ){
    pTerm = fts5TokenizeAppendInt(p, pTerm, (iStream << 2) | 0x00000003);
    if( !pTerm ) goto tokenize_cb_out;
    pTerm->iStream = iStream;
  }

  if( pTerm && p->iCol!=pTerm->iCol ){
    pTerm = fts5TokenizeAppendInt(p, pTerm, (p->iCol << 2) | 0x00000001);
    if( !pTerm ) goto tokenize_cb_out;
    pTerm->iCol = p->iCol;
    pTerm->iOff = 0;
  }

  pTerm = fts5TokenizeAppendInt(p, pTerm, (iOff-pTerm->iOff) << 1);
  if( !pTerm ) goto tokenize_cb_out;
  pTerm->iOff = iOff;

tokenize_cb_out:
  sqlite4HashInsert(&p->hash, (char *)&pTerm[1], nToken, pTerm);
  if( !pTerm ){
    p->rc = SQLITE4_NOMEM;
    return 1;
  }

  return 0;
}

static int fts5LoadSizeRecord(
  sqlite4 *db,                    /* Database handle */
  u8 *aKey, int nKey,             /* KVStore key */
  int nMinStream,                 /* Space for at least this many streams */
  Fts5Info *pInfo,                /* Info record */
  i64 *pnRow,                     /* non-NULL when reading global record */
  Fts5Size **ppSz                 /* OUT: Loaded size record */
){
  Fts5Size *pSz = 0;              /* Size object */
  KVCursor *pCsr = 0;             /* Cursor used to read global record */
  int rc;

  rc = sqlite4KVStoreOpenCursor(db->aDb[pInfo->iDb].pKV, &pCsr);
  if( rc==SQLITE4_OK ){
    rc = sqlite4KVCursorSeek(pCsr, aKey, nKey, 0);
    if( rc==SQLITE4_NOTFOUND ){
      if( pnRow ){
        int nByte = sizeof(Fts5Size) + sizeof(i64) * pInfo->nCol * nMinStream;
        pSz = sqlite4DbMallocZero(db, nByte);
        if( pSz==0 ){
          rc = SQLITE4_NOMEM;
        }else{
          pSz->aSz = (i64 *)&pSz[1];
          pSz->nStream = nMinStream;
          pSz->nCol = pInfo->nCol;
          *pnRow = 0;
          rc = SQLITE4_OK;
        }
      }else{
        rc = SQLITE4_CORRUPT_BKPT;
      }
    }else if( rc==SQLITE4_OK ){
      const u8 *aData = 0;
      int nData = 0;
      rc = sqlite4KVCursorData(pCsr, 0, -1, &aData, &nData);
      if( rc==SQLITE4_OK ){
        int iOff = 0;
        int nStream = 0;
        int nAlloc;

        /* If pnRow is not NULL, then this is the global record. Read the
        ** number of documents in the table from the start of the record. */
        if( pnRow ){
          iOff += sqlite4GetVarint64(&aData[iOff], nData-iOff, (u64 *)pnRow);
        }
        iOff += getVarint32(&aData[iOff], nStream);
        nAlloc = (nStream < nMinStream ? nMinStream : nStream);

        pSz = sqlite4DbMallocZero(db, 
            sizeof(Fts5Size) + sizeof(i64) * pInfo->nCol * nAlloc
        );
        if( pSz==0 ){
          rc = SQLITE4_NOMEM;
        }else{
          int iCol = 0;
          pSz->aSz = (i64 *)&pSz[1];
          pSz->nCol = pInfo->nCol;
          pSz->nStream = nAlloc;
          while( iOff<nData ){
            int i;
            i64 *aSz = &pSz->aSz[iCol*nAlloc];
            for(i=0; i<nStream; i++){
              iOff += sqlite4GetVarint64(&aData[iOff],nData-iOff,(u64*)&aSz[i]);
            }
            iCol++;
          }
        }
      }
    }
    sqlite4KVCursorClose(pCsr);
  }

  *ppSz = pSz;
  return rc;
}

static int fts5StoreSizeRecord(
  KVStore *p,
  u8 *aKey, int nKey,
  Fts5Size *pSz, 
  i64 nRow, 
  u8 *a                           /* Space to serialize record in */
){
  int iOff = 0;
  int iCol;

  if( nRow>=0 ){
    iOff += sqlite4PutVarint64(&a[iOff], nRow);
  }
  iOff += sqlite4PutVarint64(&a[iOff], pSz->nStream);

  for(iCol=0; iCol<pSz->nCol; iCol++){
    int i;
    for(i=0; i<pSz->nStream; i++){
      iOff += sqlite4PutVarint64(&a[iOff], pSz->aSz[iCol*pSz->nStream+i]);
    }
  }

  return sqlite4KVStoreReplace(p, aKey, nKey, a, iOff);
}

static int fts5CsrLoadGlobal(Fts5Cursor *pCsr){
  int rc = SQLITE4_OK;
  if( pCsr->pGlobal==0 ){
    int nKey;
    u8 aKey[10];
    nKey = putVarint32(aKey, pCsr->pInfo->iRoot);
    aKey[nKey++] = 0x00;
    rc = fts5LoadSizeRecord(
        pCsr->db, aKey, nKey, 0, pCsr->pInfo, &pCsr->nGlobal, &pCsr->pGlobal
    );
  }
  return rc;
}

static int fts5CsrLoadSz(Fts5Cursor *pCsr){
  int rc = SQLITE4_OK;
  if( pCsr->pSz==0 ){
    sqlite4 *db = pCsr->db;
    Fts5Info *pInfo = pCsr->pInfo;
    u8 *aKey;
    int nKey = 0;
    int nPk = pCsr->pExpr->pRoot->nPk;

    aKey = (u8 *)sqlite4DbMallocZero(db, 10 + nPk);
    if( !aKey ) return SQLITE4_NOMEM;

    nKey = putVarint32(aKey, pInfo->iRoot);
    aKey[nKey++] = 0x00;
    memcpy(&aKey[nKey], pCsr->pExpr->pRoot->aPk, nPk);
    nKey += nPk;

    rc = fts5LoadSizeRecord(pCsr->db, aKey, nKey, 0, pInfo, 0, &pCsr->pSz);
    sqlite4DbFree(db, aKey);
  }

  return rc;
}


/*
** Update an fts index.
*/
SQLITE4_PRIVATE int sqlite4Fts5Update(
  sqlite4 *db,                    /* Database handle */
  Fts5Info *pInfo,                /* Description of fts index to update */
  int iRoot,
  Mem *pKey,                      /* Primary key blob */
  Mem *aArg,                      /* Array of arguments (see above) */
  int bDel,                       /* True for a delete, false for insert */
  char **pzErr                    /* OUT: Error message */
){
  int i;
  int rc = SQLITE4_OK;
  KVStore *pStore;
  TokenizeCtx sCtx;
  int nTnum = 0;
  u32 dummy = 0;

  u8 *aSpace = 0;
  int nSpace = 0;

  const u8 *pPK;
  int nPK;
  HashElem *pElem;

  if( iRoot==0 ) iRoot = pInfo->iRoot;
  pStore = db->aDb[pInfo->iDb].pKV;

  memset(&sCtx, 0, sizeof(sCtx));
  sCtx.db = db;
  sCtx.nCol = pInfo->nCol;
  sqlite4HashInit(db->pEnv, &sCtx.hash, 1);

  pPK = (const u8 *)sqlite4_value_blob(pKey, &nPK);
  
  nTnum = getVarint32(pPK, dummy);
  nPK -= nTnum;
  pPK += nTnum;

  for(i=0; rc==SQLITE4_OK && i<pInfo->nCol; i++){
    sqlite4_value *pArg = (sqlite4_value *)(&aArg[i]);
    if( pArg->flags & MEM_Str ){
      const char *zText;
      int nText;

      zText = (const char *)sqlite4_value_text(pArg, &nText);
      sCtx.iCol = i;
      rc = pInfo->pTokenizer->xTokenize(
          &sCtx, pInfo->p, zText, nText, fts5TokenizeCb
      );
    }
  }

  /* Allocate enough space to serialize all the stuff that needs to
  ** be inserted into the database. Specifically:
  **
  **   * Space for index record keys,
  **   * space for the size record and key for this document, and
  **   * space for the updated global size record for the document set.
  **
  ** To make it easier, the below allocates enough space to simultaneously
  ** store the largest index record key and the largest possible global
  ** size record.
  */
  nSpace = (sqlite4VarintLen(iRoot) + 2 + sCtx.nMax + nPK) + 
           (9 * (2 + pInfo->nCol * sCtx.nStream));
  aSpace = sqlite4DbMallocRaw(db, nSpace);
  if( aSpace==0 ) rc = SQLITE4_NOMEM;

  for(pElem=sqliteHashFirst(&sCtx.hash); pElem; pElem=sqliteHashNext(pElem)){
    TokenizeTerm *pTerm = (TokenizeTerm *)sqliteHashData(pElem);
    if( rc==SQLITE4_OK ){
      int nToken = sqliteHashKeysize(pElem);
      char *zToken = (char *)sqliteHashKey(pElem);
      u8 *aKey = aSpace;
      int nKey;

      nKey = putVarint32(aKey, iRoot);
      aKey[nKey++] = 0x24;
      memcpy(&aKey[nKey], zToken, nToken);
      nKey += nToken;
      aKey[nKey++] = 0x00;
      memcpy(&aKey[nKey], pPK, nPK);
      nKey += nPK;

      if( bDel ){
        /* delete key aKey/nKey from the index */
        rc = sqlite4KVStoreReplace(pStore, aKey, nKey, 0, -1);
      }else{
        /* Insert a new entry for aKey/nKey into the fts index */
        const KVByteArray *aData = (const KVByteArray *)&pTerm[1];
        aData += pTerm->nToken;
        rc = sqlite4KVStoreReplace(pStore, aKey, nKey, aData, pTerm->nData);
      }
    }
    sqlite4DbFree(db, pTerm);
  }

  /* Write the size record into the db */
  if( rc==SQLITE4_OK ){
    u8 *aKey = aSpace;
    int nKey;

    nKey = putVarint32(aKey, iRoot);
    aKey[nKey++] = 0x00;
    memcpy(&aKey[nKey], pPK, nPK);
    nKey += nPK;

    if( bDel==0 ){
      Fts5Size sSz;
      sSz.nCol = pInfo->nCol;
      sSz.nStream = sCtx.nStream;
      sSz.aSz = sCtx.aSz;
      rc = fts5StoreSizeRecord(pStore, aKey, nKey, &sSz, -1, &aKey[nKey]);
    }else{
      rc = sqlite4KVStoreReplace(pStore, aKey, nKey, 0, -1);
    }
  }

  /* Update the global record */
  if( rc==SQLITE4_OK ){
    Fts5Size *pSz;                /* Deserialized global size record */
    i64 nRow;                     /* Number of rows in indexed table */
    u8 *aKey = aSpace;            /* Space to format the global record key */
    int nKey;                     /* Size of global record key in bytes */

    nKey = putVarint32(aKey, iRoot);
    aKey[nKey++] = 0x00;
    rc = fts5LoadSizeRecord(db, aKey, nKey, sCtx.nStream, pInfo, &nRow, &pSz);
    assert( rc!=SQLITE4_OK || pSz->nStream>=sCtx.nStream );

    if( rc==SQLITE4_OK ){
      int iCol;
      for(iCol=0; iCol<pSz->nCol; iCol++){
        int iStr;
        i64 *aIn = &sCtx.aSz[iCol * sCtx.nStream];
        i64 *aOut = &pSz->aSz[iCol * pSz->nStream];
        for(iStr=0; iStr<sCtx.nStream; iStr++){
          aOut[iStr] += (aIn[iStr] * (bDel?-1:1));
          assert( iStr==0 || aOut[iStr]==0 );
        }
      }
      nRow += (bDel?-1:1);
      rc = fts5StoreSizeRecord(pStore, aKey, nKey, pSz, nRow, &aKey[nKey]);
    }

    sqlite4DbFree(db, pSz);
  }
  
  sqlite4DbFree(db, aSpace);
  sqlite4DbFree(db, sCtx.aSz);
  sqlite4HashClear(&sCtx.hash);
  return rc;
}

static Fts5Info *fts5InfoCreate(Parse *pParse, Index *pIdx, int bCol){
  sqlite4 *db = pParse->db;
  Fts5Info *pInfo;                /* p4 argument for FtsUpdate opcode */
  int nByte;

  nByte = sizeof(Fts5Info);
  if( bCol ){
    int i;
    int nCol = pIdx->pTable->nCol;
    for(i=0; i<nCol; i++){
      const char *zCol = pIdx->pTable->aCol[i].zName;
      nByte += sqlite4Strlen30(zCol) + 1;
    }
    nByte += nCol * sizeof(char *);
  }

  pInfo = sqlite4DbMallocZero(db, nByte);
  if( pInfo ){
    pInfo->iDb = sqlite4SchemaToIndex(db, pIdx->pSchema);
    pInfo->iRoot = pIdx->tnum;
    pInfo->iTbl = sqlite4FindPrimaryKey(pIdx->pTable, 0)->tnum;
    pInfo->nCol = pIdx->pTable->nCol;
    fts5TokenizerCreate(pParse, pIdx->pFts, &pInfo->pTokenizer, &pInfo->p);

    if( pInfo->p==0 ){
      assert( pParse->nErr );
      sqlite4DbFree(db, pInfo);
      pInfo = 0;
    }
    else if( bCol ){
      int i;
      char *p;
      int nCol = pIdx->pTable->nCol;

      pInfo->azCol = (char **)(&pInfo[1]);
      p = (char *)(&pInfo->azCol[nCol]);
      for(i=0; i<nCol; i++){
        const char *zCol = pIdx->pTable->aCol[i].zName;
        int n = sqlite4Strlen30(zCol) + 1;
        pInfo->azCol[i] = p;
        memcpy(p, zCol, n);
        p += n;
      }
    }
  }

  return pInfo;
}

SQLITE4_PRIVATE void sqlite4Fts5CodeUpdate(
  Parse *pParse, 
  Index *pIdx, 
  int iRegRoot,
  int iRegPk, 
  int iRegData,
  int bDel
){
  Vdbe *v;
  Fts5Info *pInfo;                /* p4 argument for FtsUpdate opcode */

  if( 0==(pInfo = fts5InfoCreate(pParse, pIdx, 0)) ) return;

  v = sqlite4GetVdbe(pParse);
  sqlite4VdbeAddOp3(v, OP_FtsUpdate, iRegPk, iRegRoot, iRegData);
  sqlite4VdbeChangeP4(v, -1, (const char *)pInfo, P4_FTS5INFO);
  sqlite4VdbeChangeP5(v, (u8)bDel);
}

SQLITE4_PRIVATE void sqlite4Fts5CodeQuery(
  Parse *pParse,
  Index *pIdx,
  int iCsr,
  int iJump,
  int iRegMatch
){
  Vdbe *v;
  Fts5Info *pInfo;                /* p4 argument for FtsOpen opcode */

  if( 0==(pInfo = fts5InfoCreate(pParse, pIdx, 1)) ) return;

  v = sqlite4GetVdbe(pParse);
  sqlite4VdbeAddOp3(v, OP_FtsOpen, iCsr, iJump, iRegMatch);
  sqlite4VdbeChangeP4(v, -1, (const char *)pInfo, P4_FTS5INFO);
}

SQLITE4_PRIVATE void sqlite4Fts5FreeInfo(sqlite4 *db, Fts5Info *p){
  if( db->pnBytesFreed==0 ){
    if( p->p ) p->pTokenizer->xDestroy(p->p);
    sqlite4DbFree(db, p);
  }
}

SQLITE4_PRIVATE void sqlite4Fts5CodeCksum(
  Parse *pParse, 
  Index *pIdx, 
  int iCksum, 
  int iReg,
  int bIdx                        /* True for fts index, false for table */
){
  Vdbe *v;
  Fts5Info *pInfo;                /* p4 argument for FtsCksum opcode */

  if( 0==(pInfo = fts5InfoCreate(pParse, pIdx, 0)) ) return;

  v = sqlite4GetVdbe(pParse);
  sqlite4VdbeAddOp3(v, OP_FtsCksum, iCksum, 0, iReg);
  sqlite4VdbeChangeP4(v, -1, (const char *)pInfo, P4_FTS5INFO);
  sqlite4VdbeChangeP5(v, bIdx);
}

/*
** Calculate a 64-bit checksum for a term instance. The index checksum is
** the XOR of the checksum for each term instance in the table. A term
** instance checksum is calculated based on:
**
**   * the term itself,
**   * the pk of the row the instance appears in,
**   * the weight assigned to the instance,
**   * the column number, and
**   * the term offset.
*/
static i64 fts5TermInstanceCksum(
  const u8 *aTerm, int nTerm,
  const u8 *aPk, int nPk,
  int iStream,
  int iCol,
  int iOff
){
  int i;
  i64 cksum = 0;

  /* Add the term to the checksum */
  for(i=0; i<nTerm; i++){
    cksum += (cksum << 3) + aTerm[i];
  }

  /* Add the primary key blob to the checksum */
  for(i=0; i<nPk; i++){
    cksum += (cksum << 3) + aPk[i];
  }

  /* Add the weight, column number and offset (in that order) to the checksum */
  cksum += (cksum << 3) + iStream;
  cksum += (cksum << 3) + iCol;
  cksum += (cksum << 3) + iOff;

  return cksum;
}


SQLITE4_PRIVATE int sqlite4Fts5EntryCksum(
  sqlite4 *db,                    /* Database handle */
  Fts5Info *p,                    /* Index description */
  Mem *pKey,                      /* Database key */
  Mem *pVal,                      /* Database value */
  i64 *piCksum                    /* OUT: Checksum value */
){
  i64 cksum = 0;
  u8 const *aKey; int nKey;       /* Key blob */
  u8 const *aVal; int nVal;       /* List of token instances */
  u8 const *aToken; int nToken;   /* Token for this entry */
  u8 const *aPk; int nPk;         /* Entry primary key blob */
  InstanceList sList;             /* Used to iterate through pVal */
  int nTnum;
  u32 tnum;

  aKey = (const u8 *)sqlite4_value_blob(pKey, &nKey);
  aVal = (const u8 *)sqlite4_value_blob(pVal, &nVal);

  /* Find the token and primary key blobs for this entry. */
  nTnum = getVarint32(aKey, tnum);
  if( aKey[nTnum]!=0 ){
    aToken = &aKey[nTnum+1];
    nToken = sqlite4Strlen30((const char *)aToken);
    aPk = &aToken[nToken+1];
    nPk = (&aKey[nKey] - aPk);

    fts5InstanceListInit((u8 *)aVal, nVal, &sList);
    while( 0==fts5InstanceListNext(&sList) ){
      i64 v = fts5TermInstanceCksum(
          aPk, nPk, aToken, nToken, sList.iStream, sList.iCol, sList.iOff
          );
      cksum = cksum ^ v;
    }
  }

  *piCksum = cksum;
  return SQLITE4_OK;
}

typedef struct CksumCtx CksumCtx;
struct CksumCtx {
  const u8 *pPK;
  int nPK;
  int iCol;
  i64 cksum;
};

static int fts5CksumCb(
  void *pCtx, 
  int iStream, 
  int iOff,
  const char *zToken, 
  int nToken, 
  int iSrc, 
  int nSrc
){
  CksumCtx *p = (CksumCtx *)pCtx;
  i64 cksum;

  cksum = fts5TermInstanceCksum(p->pPK, p->nPK, 
      (const u8 *)zToken, nToken, iStream, p->iCol, iOff
  );

  p->cksum = (p->cksum ^ cksum);
  return 0;
}

SQLITE4_PRIVATE int sqlite4Fts5RowCksum(
  sqlite4 *db,                    /* Database handle */
  Fts5Info *pInfo,                /* Index description */
  Mem *pKey,                      /* Primary key blob */
  Mem *aArg,                      /* Array of column values */
  i64 *piCksum                    /* OUT: Checksum value */
){
  int i;
  int rc = SQLITE4_OK;
  CksumCtx sCtx;
  int nTnum = 0;
  u32 dummy = 0;

  sCtx.cksum = 0;

  sCtx.pPK = (const u8 *)sqlite4_value_blob(pKey, &sCtx.nPK);
  nTnum = getVarint32(sCtx.pPK, dummy);
  sCtx.nPK -= nTnum;
  sCtx.pPK += nTnum;

  for(i=0; rc==SQLITE4_OK && i<pInfo->nCol; i++){
    sqlite4_value *pArg = (sqlite4_value *)(&aArg[i]);
    if( pArg->flags & MEM_Str ){
      const char *zText;
      int nText;

      zText = (const char *)sqlite4_value_text(pArg, &nText);
      sCtx.iCol = i;
      rc = pInfo->pTokenizer->xTokenize(
          &sCtx, pInfo->p, zText, nText, fts5CksumCb
      );
    }
  }

  *piCksum = sCtx.cksum;
  return rc;
}

/*
** Obtain the primary key value from the entry cursor pToken->pCsr currently
** points to. Set *paPk to point to a buffer containing the PK, and *pnPk
** to the size of the buffer in bytes before returning.
**
** Return SQLITE4_OK if everything goes according to plan, or an error code
** if an error occurs. If an error occurs the final values of *paPk and *pnPk
** are undefined.
*/
static int fts5TokenPk(Fts5Token *p, const u8 **paPk, int *pnPk){
  int rc;

  if( p->pCsr ){
    const u8 *aKey;
    int nKey;

    rc = sqlite4KVCursorKey(p->pCsr, &aKey, &nKey);
    if( rc==SQLITE4_OK ){
      if( nKey<p->nPrefix || memcmp(p->aPrefix, aKey, p->nPrefix) ){
        rc = SQLITE4_NOTFOUND;
      }else if( p->bPrefix==0 ){
        *paPk = &aKey[p->nPrefix];
        *pnPk = nKey - p->nPrefix;
      }else{
        const u8 *z = &aKey[p->nPrefix];
        while( *(z++)!='\0' );
        *paPk = z;
        *pnPk = nKey - (z-aKey);
      }
    }
  }else{
    if( p->pPrefix ){
      *paPk = p->pPrefix->aPk;
      *pnPk = p->pPrefix->nPk;
      rc = SQLITE4_OK;
    }else{
      rc = SQLITE4_NOTFOUND;
    }
  }

  return rc;
}

static int fts5TokenAdvance(sqlite4 *db, Fts5Token *pToken){
  int rc;
  if( pToken->pCsr ){
    rc = sqlite4KVCursorNext(pToken->pCsr);
  }else if( pToken->pPrefix ){
    Fts5Prefix *pDel = pToken->pPrefix;
    pToken->pPrefix = pDel->pNext;
    sqlite4DbFree(db, pDel->aList);
    sqlite4DbFree(db, pDel);
    rc = SQLITE4_OK;
  }else{
    rc = SQLITE4_NOTFOUND;
  }
  return rc;
}

static int fts5TokenData(Fts5Token *pToken, const u8 **paData, int *pnData){
  int rc;
  if( pToken->pCsr ){
    rc = sqlite4KVCursorData(pToken->pCsr, 0, -1, paData, pnData);
  }else if( pToken->pPrefix ){
    *paData = pToken->pPrefix->aList;
    *pnData = pToken->pPrefix->nList;
    rc = SQLITE4_OK;
  }else{
    rc = SQLITE4_NOTFOUND;
  }

  return rc;
}

/*
** Compare keys (aLeft/nLeft) and (aRight/nRight) using the ordinary memcmp()
** method. Except, if either aLeft or aRight are NULL, consider them larger
** than all other values.
*/
static int fts5KeyCompare(
  const u8 *aLeft, int nLeft, 
  const u8 *aRight, int nRight
){
  int res;
  int nMin;

  res = (aLeft==0) - (aRight==0);
  if( res==0 ){
    nMin = (nLeft > nRight) ? nRight : nLeft;
    res = memcmp(aLeft, aRight, nMin);
  }
  return (res ? res : (nLeft-nRight));
}

static int fts5ListMerge(sqlite4 *db, Fts5List *p1, Fts5List *p2, int bFree){
  InstanceList in1;
  InstanceList in2;
  InstanceList out;

  memset(&out, 0, sizeof(InstanceList));
  if( p1->nData==0 && p2->nData==0 ) return SQLITE4_OK;
  out.nList = p1->nData+p2->nData;
  out.aList = sqlite4DbMallocRaw(db, out.nList);
  if( !out.aList ) return SQLITE4_NOMEM;
  fts5InstanceListInit(p1->aData, p1->nData, &in1);
  fts5InstanceListInit(p2->aData, p2->nData, &in2);

  fts5InstanceListNext(&in1);
  fts5InstanceListNext(&in2);

  while( fts5InstanceListEof(&in1)==0 || fts5InstanceListEof(&in2)==0 ){
    InstanceList *pAdv;

    if( fts5InstanceListEof(&in1) ){
      pAdv = &in2;
    }else if( fts5InstanceListEof(&in2) ){
      pAdv = &in1;
    }else if( in1.iCol==in2.iCol && in1.iOff==in2.iOff ){
      pAdv = &in1;
      fts5InstanceListNext(&in2);
    }else if( in1.iCol<in2.iCol || (in1.iCol==in2.iCol && in1.iOff<in2.iOff) ){
      pAdv = &in1;
    }else{
      pAdv = &in2;
    }

    fts5InstanceListAppend(&out, pAdv->iCol, pAdv->iStream, pAdv->iOff);
    fts5InstanceListNext(pAdv);
  }

  if( bFree ){
    sqlite4DbFree(db, p1->aData);
    sqlite4DbFree(db, p2->aData);
  }
  memset(p2, 0, sizeof(Fts5List));
  p1->aData = out.aList;
  p1->nData = out.iList;
  return SQLITE4_OK;
}

static void fts5PrefixMerge(Fts5Prefix **pp, Fts5Prefix *p2){
  Fts5Prefix *p1 = *pp;
  Fts5Prefix *pRet = 0;
  Fts5Prefix **ppWrite = &pRet;

  while( p1 || p2 ){
    Fts5Prefix **ppAdv = 0;
    if( p1==0 ){
      ppAdv = &p2;
    }else if( p2==0 ){
      ppAdv = &p1;
    }else{
      int res = fts5KeyCompare(p1->aPk, p1->nPk, p2->aPk, p2->nPk);
      assert( res!=0 );
      if( res<0 ){
        ppAdv = &p1;
      }else{
        ppAdv = &p2;
      }
    }

    *ppWrite = *ppAdv;
    ppWrite = &((*ppWrite)->pNext);
    *ppAdv = (*ppAdv)->pNext;
    *ppWrite = 0;
  }

  *pp = pRet;
}

static int fts5FindPrefixes(sqlite4 *db, Fts5Info *pInfo, Fts5Token *pToken){
  int rc = SQLITE4_OK;
  HashElem *pElem;
  Hash hash;

  assert( pToken->bPrefix );
  assert( pToken->aPrefix[pToken->nPrefix-1]!='\0' );
  sqlite4HashInit(db->pEnv, &hash, 1);

  do {
    const u8 *aData;
    int nData;
    const u8 *aPk;
    int nPk;

    rc = fts5TokenPk(pToken, &aPk, &nPk);
    if( rc==SQLITE4_OK ){
      rc = fts5TokenData(pToken, &aData, &nData);
    }
    if( rc==SQLITE4_OK ){
      Fts5Prefix *p;

      p = (Fts5Prefix *)sqlite4HashFind(&hash, (const char *)aPk, nPk);
      if( !p ){
        p = (Fts5Prefix *)sqlite4DbMallocZero(db, sizeof(Fts5Prefix) + nPk);
        if( !p ){
          rc = SQLITE4_NOMEM;
        }else{
          void *pFree;
          p->aPk = (u8 *)&p[1];
          p->nPk = nPk;
          memcpy(p->aPk, aPk, nPk);
          pFree = sqlite4HashInsert(&hash, (const char *)p->aPk, p->nPk, p);
          if( pFree ){
            assert( pFree==(void *)p );
            rc = SQLITE4_NOMEM;
            sqlite4DbFree(db, pFree);
          }
        }
      }

      if( rc==SQLITE4_OK ){
        int nReq = nData + sqlite4VarintLen(nData);
        while( (p->nList + nReq) > p->nAlloc ){
          int nAlloc = (p->nAlloc ? p->nAlloc*2 : 64);
          p->aList = sqlite4DbReallocOrFree(db, p->aList, nAlloc);
          if( !p->aList ){
            rc = SQLITE4_NOMEM;
            break;
          }
          p->nAlloc = nAlloc;
        }
      }

      if( rc==SQLITE4_OK ){
        p->nList += putVarint32(&p->aList[p->nList], nData);
        memcpy(&p->aList[p->nList], aData, nData);
        p->nList += nData;
      }
      
      if( rc==SQLITE4_OK ){
        rc = fts5TokenAdvance(db, pToken);
      }
    }
  }while( rc==SQLITE4_OK );
  if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;

  if( rc==SQLITE4_OK ){
    Fts5List *aMerge;
    aMerge = (Fts5List *)sqlite4DbMallocZero(db, sizeof(Fts5List) * 32);
    if( !aMerge ) rc = SQLITE4_NOMEM;

    for(pElem=sqliteHashFirst(&hash); pElem; pElem=sqliteHashNext(pElem)){
      Fts5Prefix *p = (Fts5Prefix *)sqliteHashData(pElem);
      Fts5List list = {0, 0};
      int i = 0;
      int iLevel;

      memset(aMerge, 0, sizeof(Fts5List)*32);
      while( i<p->nList && rc==SQLITE4_OK ){
        u32 n;
        i += getVarint32(&p->aList[i], n);
        list.aData = &p->aList[i];
        list.nData = n;
        i += n;

        for(iLevel=0; rc==SQLITE4_OK && iLevel<32; iLevel++){
          if( aMerge[iLevel].aData==0 ){
            aMerge[iLevel] = list;
            break;
          }else{
            rc = fts5ListMerge(db, &list, &aMerge[iLevel], (iLevel>0));
          }
        }
        assert( iLevel<32 );
      }

      list.aData = 0;
      list.nData = 0;
      for(iLevel=0; rc==SQLITE4_OK && iLevel<32; iLevel++){
        rc = fts5ListMerge(db, &list, &aMerge[iLevel], (iLevel>0));
      }

      if( rc==SQLITE4_OK ){
        sqlite4DbFree(db, p->aList);
        p->aList = list.aData;
        p->nAlloc = p->nList = list.nData;
      }else{
        sqlite4DbFree(db, list.aData);
      }
    }

    sqlite4DbFree(db, aMerge);
  }

  if( rc==SQLITE4_OK ){
    Fts5Prefix **aMerge;
    Fts5Prefix *pPrefix = 0;

    aMerge = (Fts5Prefix **)sqlite4DbMallocZero(db, sizeof(Fts5List) * 32);
    if( !aMerge ){
      rc = SQLITE4_NOMEM;
    }else{
      int iLevel;
      for(pElem=sqliteHashFirst(&hash); pElem; pElem=sqliteHashNext(pElem)){
        pPrefix = (Fts5Prefix *)sqliteHashData(pElem);
        for(iLevel=0; iLevel<32; iLevel++){
          if( aMerge[iLevel] ){
            fts5PrefixMerge(&pPrefix, aMerge[iLevel]);
            aMerge[iLevel] = 0;
          }else{
            aMerge[iLevel] = pPrefix;
            break;
          }
        }
        assert( iLevel<32 );
      }
      pPrefix = 0;
      for(iLevel=0; iLevel<32; iLevel++){
        fts5PrefixMerge(&pPrefix, aMerge[iLevel]);
      }
      sqlite4HashClear(&hash);
      sqlite4DbFree(db, aMerge);
    }
    pToken->pPrefix = pPrefix;
  }

  for(pElem=sqliteHashFirst(&hash); pElem; pElem=sqliteHashNext(pElem)){
    Fts5Prefix *pPrefix = (Fts5Prefix *)sqliteHashData(pElem);
    sqlite4DbFree(db, pPrefix->aList);
    sqlite4DbFree(db, pPrefix);
  }
  sqlite4KVCursorClose(pToken->pCsr);
  pToken->pCsr = 0;

  return rc;
}

static int fts5OpenExprCursors(sqlite4 *db, Fts5Info *pInfo, Fts5ExprNode *p){
  int rc = SQLITE4_OK;
  if( p ){
    if( p->eType==TOKEN_PRIMITIVE ){
      KVStore *pStore = db->aDb[pInfo->iDb].pKV;
      Fts5Phrase *pPhrase = p->pPhrase;
      int iStr;

      for(iStr=0; rc==SQLITE4_OK && iStr<pPhrase->nStr; iStr++){
        Fts5Str *pStr = &pPhrase->aStr[iStr];
        int i;
        for(i=0; rc==SQLITE4_OK && i<pStr->nToken; i++){
          Fts5Token *pToken = &pStr->aToken[i];
          rc = sqlite4KVStoreOpenCursor(pStore, &pToken->pCsr);
          rc = sqlite4KVCursorSeek(
              pToken->pCsr, pToken->aPrefix, pToken->nPrefix, 1
          );
          if( rc==SQLITE4_INEXACT ) rc = SQLITE4_OK;
          if( rc==SQLITE4_OK && pToken->bPrefix ){
            rc = fts5FindPrefixes(db, pInfo, pToken);
          }
        }
      }
    }
    if( rc==SQLITE4_OK ) rc = fts5OpenExprCursors(db, pInfo, p->pLeft);
    if( rc==SQLITE4_OK ) rc = fts5OpenExprCursors(db, pInfo, p->pRight);
  }

  return rc;
}

/*
** Open a cursor for each token in the expression.
*/
static int fts5OpenCursors(sqlite4 *db, Fts5Info *pInfo, Fts5Cursor *pCsr){
  return fts5OpenExprCursors(db, pInfo, pCsr->pExpr->pRoot);
}

SQLITE4_PRIVATE void sqlite4Fts5Close(Fts5Cursor *pCsr){
  if( pCsr ){
    sqlite4 *db = pCsr->db;
    if( pCsr->aMem ){
      int i;
      for(i=0; i<pCsr->pInfo->nCol; i++){
        sqlite4DbFree(db, pCsr->aMem[i].zMalloc);
      }
      sqlite4DbFree(db, pCsr->aMem);
    }

    sqlite4KVCursorClose(pCsr->pCsr);
    fts5ExpressionFree(db, pCsr->pExpr);
    sqlite4DbFree(db, pCsr->pIter);
    sqlite4DbFree(db, pCsr->aKey);
    sqlite4DbFree(db, pCsr->anRow);
    sqlite4DbFree(db, pCsr);
  }
}

static int fts5TokenAdvanceToMatch(
  InstanceList *p,
  InstanceList *pFirst,
  int iOff,
  int *pbEof
){
  int iReq = pFirst->iOff + iOff;

  while( p->iCol<pFirst->iCol || (p->iCol==pFirst->iCol && p->iOff < iReq) ){
    int bEof = fts5InstanceListNext(p);
    if( bEof ){
      *pbEof = 1;
      return 0;
    }
  }

  return (p->iCol==pFirst->iCol && p->iOff==iReq);
}

static int fts5StringFindInstances(sqlite4 *db, int iCol, Fts5Str *pStr){
  int i;
  int rc = SQLITE4_OK;
  int bEof = 0;
  int nByte = sizeof(InstanceList) * pStr->nToken;
  InstanceList *aIn;
  InstanceList out;

  pStr->nList = 0;
  memset(&out, 0, sizeof(InstanceList));

  aIn = (InstanceList *)sqlite4DbMallocZero(db, nByte);
  if( !aIn ) rc = SQLITE4_NOMEM;
  for(i=0; rc==SQLITE4_OK && i<pStr->nToken; i++){
    const u8 *aData;
    int nData;
    rc = fts5TokenData(&pStr->aToken[i], &aData, &nData);
    if( rc==SQLITE4_OK ){
      fts5InstanceListInit((u8 *)aData, nData, &aIn[i]);
      fts5InstanceListNext(&aIn[i]);
    }
  }

  /* Allocate the output list */
  if( rc==SQLITE4_OK ){
    int nReq = aIn[0].nList;
    if( nReq<=pStr->nListAlloc ){
      out.aList = pStr->aList;
      out.nList = pStr->nListAlloc;
    }else{
      pStr->aList = out.aList = sqlite4DbReallocOrFree(db, pStr->aList, nReq*2);
      pStr->nListAlloc = out.nList = nReq*2;
      if( out.aList==0 ) rc = SQLITE4_NOMEM;
    }
  }

  while( rc==SQLITE4_OK && bEof==0 ){
    for(i=1; i<pStr->nToken; i++){
      int bMatch = fts5TokenAdvanceToMatch(&aIn[i], &aIn[0], i, &bEof);
      if( bMatch==0 || bEof ) break;
    }
    if( i==pStr->nToken && (iCol<0 || aIn[0].iCol==iCol) ){
      /* Record a match here */
      fts5InstanceListAppend(&out, aIn[0].iCol, aIn[0].iStream, aIn[0].iOff);
    }
    bEof = fts5InstanceListNext(&aIn[0]);
  }

  pStr->nList = out.iList;
  sqlite4DbFree(db, aIn);

  return rc;
}

static int fts5IsNear(InstanceList *p1, InstanceList *p2, int nNear){
  if( p1->iCol==p2->iCol && p1->iOff<p2->iOff && (p1->iOff+nNear)>=p2->iOff ){
    return 1;
  }
  return 0;
}

static int fts5StringNearTrim(
  Fts5Str *pTrim,                 /* Trim this instance list */
  Fts5Str *pNext,                 /* According to this one */
  int nNear
){
  if( pNext->nList==0 ){
    pTrim->nList = 0;
  }else{
    int bEof = 0;
    int nTrail = nNear + (pNext->nToken-1) + 1;
    int nLead = nNear + (pTrim->nToken-1) + 1;

    InstanceList lNear;
    InstanceList in;
    InstanceList out;

    fts5InstanceListInit(pNext->aList, pNext->nList, &lNear);
    fts5InstanceListInit(pTrim->aList, pTrim->nList, &in);
    fts5InstanceListInit(pTrim->aList, pTrim->nList, &out);
    fts5InstanceListNext(&lNear);
    fts5InstanceListNext(&in);

    while( bEof==0 ){
      if( fts5IsNear(&lNear, &in, nTrail) 
       || fts5IsNear(&in, &lNear, nLead)
      ){
        /* The current position is a match. Append an entry to the output
        ** and advance the input cursor. */
        fts5InstanceListAppend(&out, in.iCol, in.iStream, in.iOff);
        bEof = fts5InstanceListNext(&in);
      }else{
        if( lNear.iCol<in.iCol || (lNear.iCol==in.iCol && lNear.iOff<in.iOff) ){
          bEof = fts5InstanceListNext(&lNear);
        }else if( lNear.iCol==in.iCol && lNear.iOff==in.iOff ){
          bEof = fts5InstanceListNext(&in);
          if( fts5IsNear(&lNear, &in, nTrail) ){
            fts5InstanceListAppend(&out, lNear.iCol, lNear.iStream, lNear.iOff);
          }
        }else{
          bEof = fts5InstanceListNext(&in);
        }
      }
    }

    pTrim->nList = out.iList;
  }
  return SQLITE4_OK;
}

/*
** This function tests if the cursors embedded in the Fts5Phrase object
** currently point to a match for the entire phrase. If so, *pbMatch
** is set to true before returning.
**
** If the cursors do not point to a match, then *ppAdvance is set to
** the token of the individual cursor that should be advanced before
** retrying this function.
*/
static int fts5PhraseIsMatch(
  sqlite4 *db,                    /* Database handle */
  Fts5Phrase *pPhrase,            /* Phrase to test */
  int *pbMatch,                   /* OUT: True for a match, false otherwise */
  Fts5Token **ppAdvance           /* OUT: Token to advance before retrying */
){
  const u8 *aPk1 = 0;
  int nPk1 = 0;
  int rc = SQLITE4_OK;
  int i;

  *pbMatch = 0;
  *ppAdvance = &pPhrase->aStr[0].aToken[0];

  rc = fts5TokenPk(*ppAdvance, &aPk1, &nPk1);
  for(i=0; rc==SQLITE4_OK && i<pPhrase->nStr; i++){
    int j;
    for(j=(i==0); j<pPhrase->aStr[i].nToken; j++){
      const u8 *aPk = 0;
      int nPk = 0;
      Fts5Token *pToken = &pPhrase->aStr[i].aToken[j];
      rc = fts5TokenPk(pToken, &aPk, &nPk);
      if( rc==SQLITE4_OK ){
        int res = fts5KeyCompare(aPk1, nPk1, aPk, nPk);
        if( res<0 ){
          return SQLITE4_OK;
        }
        if( res>0 ){
          *ppAdvance = pToken;
          return SQLITE4_OK;
        }
      }
    }
  }

  /* At this point, it is established that all of the token cursors in the
  ** phrase point to an entry with the same primary key. Now figure out if
  ** the various string constraints are met. Along the way, synthesize a 
  ** position list for each Fts5Str object.  */
  for(i=0; rc==SQLITE4_OK && i<pPhrase->nStr; i++){
    Fts5Str *pStr = &pPhrase->aStr[i];
    rc = fts5StringFindInstances(db, pPhrase->iCol, pStr);
  }

  /* Trim the instance lists according to any NEAR constraints.  */
  for(i=1; rc==SQLITE4_OK && i<pPhrase->nStr; i++){
    int n = pPhrase->aiNear[i-1];
    rc = fts5StringNearTrim(&pPhrase->aStr[i], &pPhrase->aStr[i-1], n);
  }
  for(i=pPhrase->nStr-1; rc==SQLITE4_OK && i>0; i--){
    int n = pPhrase->aiNear[i-1];
    rc = fts5StringNearTrim(&pPhrase->aStr[i-1], &pPhrase->aStr[i], n);
  }

  *pbMatch = (pPhrase->aStr[0].nList>0);
  return rc;
}

static int fts5PhraseAdvanceToMatch(sqlite4 *db, Fts5Phrase *pPhrase){
  int rc;
  do {
    int bMatch;
    Fts5Token *pAdvance = 0;
    rc = fts5PhraseIsMatch(db, pPhrase, &bMatch, &pAdvance);
    if( rc!=SQLITE4_OK || bMatch ) break;
    rc = fts5TokenAdvance(db, pAdvance);
  }while( rc==SQLITE4_OK );
  return rc;
}

static int fts5ExprAdvance(sqlite4 *db, Fts5ExprNode *p, int bFirst){
  int rc = SQLITE4_OK;

  switch( p->eType ){
    case TOKEN_PRIMITIVE: {
      Fts5Phrase *pPhrase = p->pPhrase;
      if( bFirst==0 ){
        rc = fts5TokenAdvance(db, &pPhrase->aStr[0].aToken[0]);
      }
      if( rc==SQLITE4_OK ) rc = fts5PhraseAdvanceToMatch(db, pPhrase);
      if( rc==SQLITE4_OK ){
        rc = fts5TokenPk(&pPhrase->aStr[0].aToken[0], &p->aPk, &p->nPk);
      }else{
        p->aPk = 0;
        p->nPk = 0;
        if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;
      }
      break;
    }

    case TOKEN_AND:
      p->aPk = 0;
      p->nPk = 0;
      rc = fts5ExprAdvance(db, p->pLeft, bFirst);
      if( rc==SQLITE4_OK ) rc = fts5ExprAdvance(db, p->pRight, bFirst);
      while( rc==SQLITE4_OK && p->pLeft->aPk && p->pRight->aPk ){
        int res = fts5KeyCompare(
            p->pLeft->aPk, p->pLeft->nPk, p->pRight->aPk, p->pRight->nPk
        );
        if( res<0 ){
          rc = fts5ExprAdvance(db, p->pLeft, 0);
        }else if( res>0 ){
          rc = fts5ExprAdvance(db, p->pRight, 0);
        }else{
          p->aPk = p->pLeft->aPk;
          p->nPk = p->pLeft->nPk;
          break;
        }
      }
      break;

    case TOKEN_OR: {
      int res = 0;
      if( bFirst==0 ){
        res = fts5KeyCompare(
            p->pLeft->aPk, p->pLeft->nPk, p->pRight->aPk, p->pRight->nPk
        );
      }
        
      if( res<=0 ) rc = fts5ExprAdvance(db, p->pLeft, bFirst);
      if( rc==SQLITE4_OK && res>=0 ){
        rc = fts5ExprAdvance(db, p->pRight, bFirst);
      }

      res = fts5KeyCompare(
          p->pLeft->aPk, p->pLeft->nPk, p->pRight->aPk, p->pRight->nPk
      );
      if( res>0 ){
        p->aPk = p->pRight->aPk;
        p->nPk = p->pRight->nPk;
      }else{
        p->aPk = p->pLeft->aPk;
        p->nPk = p->pLeft->nPk;
      }
      assert( p->aPk!=0 || (p->pLeft->aPk==0 && p->pRight->aPk==0) );
      break;
    }


    default: assert( p->eType==TOKEN_NOT );

      p->aPk = 0;
      p->nPk = 0;

      rc = fts5ExprAdvance(db, p->pLeft, bFirst);
      if( bFirst && rc==SQLITE4_OK ){
        rc = fts5ExprAdvance(db, p->pRight, bFirst);
      }

      while( rc==SQLITE4_OK && p->pLeft->aPk && p->pRight->aPk ){
        int res = fts5KeyCompare(
            p->pLeft->aPk, p->pLeft->nPk, p->pRight->aPk, p->pRight->nPk
        );
        if( res<0 ){
          break;
        }else if( res>0 ){
          rc = fts5ExprAdvance(db, p->pRight, 0);
        }else{
          rc = fts5ExprAdvance(db, p->pLeft, 0);
        }
      }

      p->aPk = p->pLeft->aPk;
      p->nPk = p->pLeft->nPk;
      break;
  }

  assert( rc!=SQLITE4_NOTFOUND );
  return rc;
}

SQLITE4_PRIVATE int sqlite4Fts5Next(Fts5Cursor *pCsr){
  sqlite4DbFree(pCsr->db, pCsr->pSz);
  pCsr->pSz = 0;
  pCsr->bMemValid = 0;
  return fts5ExprAdvance(pCsr->db, pCsr->pExpr->pRoot, 0);
}

SQLITE4_PRIVATE int sqlite4Fts5Open(
  sqlite4 *db,                    /* Database handle */
  Fts5Info *pInfo,                /* Index description */
  const char *zMatch,             /* Match expression */
  int bDesc,                      /* True to iterate in desc. order of PK */
  Fts5Cursor **ppCsr,             /* OUT: New FTS cursor object */
  char **pzErr                    /* OUT: Error message */
){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr;
  int nMatch = sqlite4Strlen30(zMatch);

  pCsr = sqlite4DbMallocZero(db, sizeof(Fts5Cursor) + nMatch + 1);

  if( !pCsr ){
    rc = SQLITE4_NOMEM;
  }else{
    pCsr->zExpr = (char *)&pCsr[1];
    memcpy(pCsr->zExpr, zMatch, nMatch);
    pCsr->pInfo = pInfo;
    pCsr->db = db;
    rc = fts5ParseExpression(db, pInfo->pTokenizer, pInfo->p, 
        pInfo->iRoot, pInfo->azCol, pInfo->nCol, zMatch, &pCsr->pExpr, pzErr
    );
  }

  if( rc==SQLITE4_OK ){
    /* Open a KV cursor for each term in the expression. Set each cursor
    ** to point to the first entry in the range it will scan.  */
    rc = fts5OpenCursors(db, pInfo, pCsr);
  }
  if( rc!=SQLITE4_OK ){
    sqlite4Fts5Close(pCsr);
    pCsr = 0;
  }else{
    rc = fts5ExprAdvance(db, pCsr->pExpr->pRoot, 1);
  }
  *ppCsr = pCsr;
  return rc;
}

/*
** Return true if the cursor passed as the second argument currently points
** to a valid entry, or false otherwise.
*/
SQLITE4_PRIVATE int sqlite4Fts5Valid(Fts5Cursor *pCsr){
  return( pCsr->pExpr->pRoot->aPk!=0 );
}

SQLITE4_PRIVATE int sqlite4Fts5Pk(
  Fts5Cursor *pCsr, 
  int iTbl,
  KVByteArray **paKey,
  KVSize *pnKey
){
  int i;
  int nReq;
  const u8 *aPk;
  int nPk;

  aPk = pCsr->pExpr->pRoot->aPk;
  nPk = pCsr->pExpr->pRoot->nPk;

  nReq = sqlite4VarintLen(iTbl) + nPk;
  if( nReq>pCsr->nKeyAlloc ){
    pCsr->aKey = sqlite4DbReallocOrFree(pCsr->db, pCsr->aKey, nReq*2);
    if( !pCsr->aKey ) return SQLITE4_NOMEM;
    pCsr->nKeyAlloc = nReq*2;
  }

  i = putVarint32(pCsr->aKey, iTbl);
  memcpy(&pCsr->aKey[i], aPk, nPk);

  *paKey = pCsr->aKey;
  *pnKey = nReq;
  return SQLITE4_OK;
}

SQLITE4_API int sqlite4_mi_column_count(sqlite4_context *pCtx, int *pn){
  int rc = SQLITE4_OK;
  if( pCtx->pFts ){
    *pn = pCtx->pFts->pInfo->nCol;
  }else{
    rc = SQLITE4_MISUSE;
  }
  return rc;
}

SQLITE4_API int sqlite4_mi_phrase_count(sqlite4_context *pCtx, int *pn){
  int rc = SQLITE4_OK;
  if( pCtx->pFts ){
    *pn = pCtx->pFts->pExpr->nPhrase;
  }else{
    rc = SQLITE4_MISUSE;
  }
  return rc;
}

SQLITE4_API int sqlite4_mi_phrase_token_count(sqlite4_context *pCtx, int iP, int *pn){
  int rc = SQLITE4_OK;
  if( pCtx->pFts ){
    Fts5Expr *pExpr = pCtx->pFts->pExpr;
    if( iP>pExpr->nPhrase || iP<0 ){
      *pn = 0;
    }else{
      *pn = pExpr->apPhrase[iP]->nToken;
    }
  }else{
    rc = SQLITE4_MISUSE;
  }
  return rc;
}

SQLITE4_API int sqlite4_mi_stream_count(sqlite4_context *pCtx, int *pn){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;
  if( pCsr ){
    rc = fts5CsrLoadGlobal(pCtx->pFts);
    if( rc==SQLITE4_OK ) *pn = pCsr->pGlobal->nStream;
  }else{
    rc = SQLITE4_MISUSE;
  }
  return rc;
}

static int fts5GetSize(Fts5Size *pSz, int iC, int iS){
  int nToken = 0;
  int i;

  if( iC<0 && iS<0 ){
    int nFin = pSz->nCol * pSz->nStream;
    for(i=0; i<nFin; i++) nToken += pSz->aSz[i];
  }else if( iC<0 ){
    for(i=0; i<pSz->nCol; i++) nToken += pSz->aSz[i*pSz->nStream + iS];
  }else if( iS<0 ){
    for(i=0; i<pSz->nStream; i++) nToken += pSz->aSz[pSz->nStream*iC + i];
  }else if( iC<pSz->nCol && iS<pSz->nStream ){
    nToken = pSz->aSz[iC * pSz->nStream + iS];
  }

  return nToken;
}

SQLITE4_API int sqlite4_mi_size(sqlite4_context *pCtx, int iC, int iS, int *pn){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;

  if( pCsr==0 ){
    rc = SQLITE4_MISUSE;
  }else{
    rc = fts5CsrLoadSz(pCsr);
    if( rc==SQLITE4_OK ){
      *pn = fts5GetSize(pCsr->pSz, iC, iS);
    }
  }
  return rc;
}

SQLITE4_API int sqlite4_mi_total_size(sqlite4_context *pCtx, int iC, int iS, int *pn){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;

  if( pCsr==0 ){
    rc = SQLITE4_MISUSE;
  }else{
    rc = fts5CsrLoadGlobal(pCsr);
    if( rc==SQLITE4_OK ){
      *pn = fts5GetSize(pCsr->pGlobal, iC, iS);
    }
  }
  return rc;
}

SQLITE4_API int sqlite4_mi_total_rows(sqlite4_context *pCtx, int *pn){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;
  if( pCsr==0 ){
    rc = SQLITE4_MISUSE;
  }else{
    rc = fts5CsrLoadGlobal(pCsr);
    if( rc==SQLITE4_OK ) *pn = pCsr->nGlobal;
  }
  return rc;
}

SQLITE4_API int sqlite4_mi_column_value(
  sqlite4_context *pCtx, 
  int iCol, 
  sqlite4_value **ppVal
){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;
  if( pCsr==0 ){
    rc = SQLITE4_MISUSE;
  }else{
    if( pCsr->bMemValid==0 ){
      sqlite4 *db = pCsr->db;

      Fts5Info *pInfo = pCsr->pInfo;
      if( pCsr->aMem==0 ){
        int nByte = sizeof(Mem) * pInfo->nCol;
        pCsr->aMem = (Mem *)sqlite4DbMallocZero(db, nByte);
        if( pCsr->aMem==0 ){
          rc = SQLITE4_NOMEM;
        }else{
          int i;
          for(i=0; i<pInfo->nCol; i++){
            pCsr->aMem[i].db = db;
          }
        }
      }

      if( pCsr->pCsr==0 && rc==SQLITE4_OK ){
        KVStore *pStore = db->aDb[pInfo->iDb].pKV;
        rc = sqlite4KVStoreOpenCursor(pStore, &pCsr->pCsr);
      }

      if( rc==SQLITE4_OK ){
        u8 *aKey = 0; int nKey;     /* Primary key for current row */
        const u8 *aData; int nData; /* Data record for current row */

        rc = sqlite4Fts5Pk(pCsr, pInfo->iTbl, &aKey, &nKey);
        if( rc==SQLITE4_OK ){
          rc = sqlite4KVCursorSeek(pCsr->pCsr, aKey, nKey, 0);
          if( rc==SQLITE4_NOTFOUND ){
            rc = SQLITE4_CORRUPT_BKPT;
          }
        }

        if( rc==SQLITE4_OK ){
          int i;
          RowDecoder *pCodec;   /* The decoder object */

          rc = sqlite4VdbeDecoderCreate(db,0, pCsr->pCsr, pInfo->nCol, &pCodec);
          for(i=0; rc==SQLITE4_OK && i<pInfo->nCol; i++){
            rc = sqlite4VdbeDecoderGetColumn(pCodec, i, 0, &pCsr->aMem[i]);
          }
          sqlite4VdbeDecoderDestroy(pCodec);
        }

        if( rc==SQLITE4_OK ) pCsr->bMemValid = 1;
      }
    }

    if( rc==SQLITE4_OK ){
      assert( pCsr->bMemValid );
      *ppVal = &pCsr->aMem[iCol];
    }
  }

  return rc;
}

SQLITE4_API int sqlite4_mi_tokenize(
  sqlite4_context *pCtx,
  const char *zText,
  int nText,
  void *p,
  int(*x)(void *, int, int, const char *, int, int, int)
){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;

  if( pCsr==0 ){
    rc = SQLITE4_MISUSE;
  }else{
    Fts5Info *pInfo = pCsr->pInfo;
    rc = pInfo->pTokenizer->xTokenize(p, pInfo->p, zText, nText, x);
  }
  return rc;
}

static Fts5Str *fts5FindStr(
  const u8 *aPk, int nPk,
  Fts5ExprNode *p,
  int *piStr
){
  Fts5Str *pRet = 0;
  if( p->eType==TOKEN_PRIMITIVE ){
    int iStr = *piStr;
    if( iStr<p->pPhrase->nStr && iStr>=0 
     && p->nPk==nPk && 0==memcmp(p->aPk, aPk, nPk) 
    ){
      pRet = &p->pPhrase->aStr[iStr];
    }else{
      *piStr = iStr - p->pPhrase->nStr;
    }
  }else{
    pRet = fts5FindStr(aPk, nPk, p->pLeft, piStr);
    if( pRet==0 ) pRet = fts5FindStr(aPk, nPk, p->pRight, piStr);
  }
  return pRet;
}

SQLITE4_API int sqlite4_mi_match_count(
  sqlite4_context *pCtx, 
  int iC,
  int iS,
  int iPhrase,
  int *pnMatch
){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;
  if( pCsr ){
    Fts5ExprNode *pRoot = pCsr->pExpr->pRoot;
    int nMatch = 0;
    Fts5Str *pStr;
    int iCopy = iPhrase;
    InstanceList sList;

    pStr = fts5FindStr(pRoot->aPk, pRoot->nPk, pRoot, &iCopy);
    if( pStr ){
      fts5InstanceListInit(pStr->aList, pStr->nList, &sList);
      while( 0==fts5InstanceListNext(&sList) ){
        if( (iC<0 || sList.iCol==iC) && (iS<0 || sList.iStream==iS) ) nMatch++;
      }
    }
    *pnMatch = nMatch;
  }else{
    rc = SQLITE4_MISUSE;
  }
  return rc;
}

SQLITE4_API int sqlite4_mi_match_offset(
  sqlite4_context *pCtx, 
  int iCol, 
  int iPhrase, 
  int iMatch, 
  int *piOff
){
  return SQLITE4_OK;
}

SQLITE4_API int sqlite4_mi_total_match_count(
  sqlite4_context *pCtx,
  int iCol,
  int iPhrase,
  int *pnMatch,
  int *pnDoc,
  int *pnRelevant
){
  return SQLITE4_OK;
}

static void fts5StrLoadRowcounts(
  Fts5Str *pStr, 
  int nStream, 
  int *anRow,
  int *anRowC,
  int *anRowS,
  int *pnRowCS
){
  u32 mask = 0;
  int iPrevCol = -1;
  InstanceList sList;

  fts5InstanceListInit(pStr->aList, pStr->nList, &sList);
  while( 0==fts5InstanceListNext(&sList) ){
    if( iPrevCol<0 ) (*pnRowCS)++;
    if( sList.iCol!=iPrevCol ){
      mask = 0;
      anRowC[sList.iCol]++;
    }
    if( (mask & (1<<sList.iStream))==0 ){
      anRow[sList.iCol * nStream + sList.iStream]++;
      mask |= (1<<sList.iStream);
      iPrevCol = sList.iCol;
    }
  }
}

static int fts5ExprLoadRowcounts(
  sqlite4 *db, 
  Fts5Cursor *pCsr,
  int nStream,
  Fts5ExprNode *pNode, 
  int *piStr
){
  int rc = SQLITE4_OK;

  if( pNode ){
    Fts5Info *pInfo = pCsr->pInfo;

    if( pNode->eType==TOKEN_PRIMITIVE ){
      Fts5Phrase *pPhrase = pNode->pPhrase;
      int iStr = *piStr;

      rc = fts5ExprAdvance(db, pNode, 1);
      while( rc==SQLITE4_OK && pNode->aPk ){
        int i;
        for(i=0; i<pPhrase->nStr; i++){
          int *anRow = &pCsr->anRow[(iStr+i) * pInfo->nCol * nStream];
          int *anRowC = &pCsr->anRowC[(iStr+i) * pInfo->nCol];
          int *anRowS = &pCsr->anRowS[(iStr+i) * nStream];
          int *pnRowCS = &pCsr->anRowCS[iStr+i];
          fts5StrLoadRowcounts(
              &pPhrase->aStr[i], nStream, anRow, anRowC, anRowS, pnRowCS
          );
        }
        rc = fts5ExprAdvance(db, pNode, 0);
      }

      *piStr = iStr + pPhrase->nStr;
    }

    if( rc==SQLITE4_OK ){
      rc = fts5ExprLoadRowcounts(db, pCsr, nStream, pNode->pLeft, piStr);
    }
    if( rc==SQLITE4_OK ){
      rc = fts5ExprLoadRowcounts(db, pCsr, nStream, pNode->pRight, piStr);
    }
  }

  return rc;
}

static int fts5CsrLoadRowcounts(Fts5Cursor *pCsr){
  int rc = SQLITE4_OK;

  if( pCsr->anRow==0 ){
    int nStream = pCsr->pGlobal->nStream;
    sqlite4 *db = pCsr->db;
    Fts5Expr *pCopy;
    Fts5Expr *pExpr = pCsr->pExpr;
    Fts5Info *pInfo = pCsr->pInfo;
    int *anRow;
    int iPhrase = 0;

    pCsr->anRow = anRow = (int *)sqlite4DbMallocZero(db, sizeof(int) * (
        pExpr->nPhrase * pInfo->nCol * pCsr->pGlobal->nStream
      + pExpr->nPhrase * pInfo->nCol
      + pExpr->nPhrase * pCsr->pGlobal->nStream
      + pExpr->nPhrase 
    ));
    if( !anRow ) return SQLITE4_NOMEM;
    pCsr->anRowC = &anRow[pExpr->nPhrase*pInfo->nCol*pCsr->pGlobal->nStream];
    pCsr->anRowS = &pCsr->anRowC[pExpr->nPhrase * pInfo->nCol];
    pCsr->anRowCS = &pCsr->anRowS[pExpr->nPhrase * pCsr->pGlobal->nStream];

    rc = fts5ParseExpression(db, pInfo->pTokenizer, pInfo->p, 
        pInfo->iRoot, pInfo->azCol, pInfo->nCol, pCsr->zExpr, &pCopy, 0
    );
    if( rc==SQLITE4_OK ){
      rc = fts5OpenExprCursors(db, pInfo, pCopy->pRoot);
    }
    if( rc==SQLITE4_OK ){
      rc = fts5ExprLoadRowcounts(db, pCsr, nStream, pCopy->pRoot, &iPhrase);
    }

    fts5ExpressionFree(db, pCopy);
  }

  return rc;
}

SQLITE4_API int sqlite4_mi_row_count(
  sqlite4_context *pCtx,          /* Context object passed to mi function */
  int iC,                         /* Specific column (or -ve for all columns) */
  int iS,                         /* Specific stream (or -ve for all streams) */
  int iP,                         /* Specific phrase */
  int *pn                         /* Total number of rows containing C/S/P */
){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;
  if( pCsr==0 ){
    rc = SQLITE4_MISUSE;
  }else{
    rc = fts5CsrLoadGlobal(pCsr);
    if( rc==SQLITE4_OK ) rc = fts5CsrLoadRowcounts(pCsr);

    if( rc==SQLITE4_OK ){
      int i;
      int nRow = 0;
      int nStream = pCsr->pGlobal->nStream;
      int nCol = pCsr->pInfo->nCol;
      int *aRow = &pCsr->anRow[iP * nStream * nCol];

      if( iC<0 && iS<0 ){
        nRow = pCsr->anRowCS[iP];
      }else if( iC<0 ){
        for(i=0; i<nCol; i++) nRow += aRow[i*nStream + iS];
      }else if( iS<0 ){
        nRow = pCsr->anRowC[iP*nCol + iC];
      }else if( iC<nCol && iS<nStream ){
        nRow = aRow[iC * nStream + iS];
      }

      *pn = nRow;
    }
  }
  return rc;
}

static void fts5IterSetCurrent(Fts5MatchIter *pIter, int nList){
  InstanceList *pBest = 0;
  int i;

  for(i=0; i<nList; i++){
    InstanceList *p = &pIter->aList[i];
    if( fts5InstanceListEof(p)==0 ){
      if( (pBest==0)
       || (p->iCol<pBest->iCol)
       || (p->iCol==pBest->iCol && p->iOff<pBest->iOff)
      ){
        pBest = p;
      }
    }
  }

  if( pBest==0 ){
    pIter->iCurrent = -1;
  }else{
    pIter->iCurrent = pBest - pIter->aList;
  }
}

static void fts5InitExprIterator(
  const u8 *aPk, 
  int nPk, 
  Fts5ExprNode *p,
  Fts5MatchIter *pIter
){
  if( p ){
    if( p->eType==TOKEN_PRIMITIVE ){
      if( p->nPk==nPk && 0==memcmp(aPk, p->aPk, nPk) ){
        int i;
        for(i=0; i<p->pPhrase->nStr; i++){
          Fts5Str *pStr = &p->pPhrase->aStr[i];
          InstanceList *pList = &pIter->aList[pIter->iCurrent++];
          fts5InstanceListInit(pStr->aList, pStr->nList, pList);
          fts5InstanceListNext(pList);
        }
      }else{
        memset(&pIter->aList[pIter->iCurrent], 0, sizeof(InstanceList));
        pIter->iCurrent += p->pPhrase->nStr;
      }
    }
    fts5InitExprIterator(aPk, nPk, p->pLeft, pIter);
    fts5InitExprIterator(aPk, nPk, p->pRight, pIter);
  }
}

static void fts5InitIterator(Fts5Cursor *pCsr){
  Fts5MatchIter *pIter = pCsr->pIter;
  Fts5ExprNode *pRoot = pCsr->pExpr->pRoot;

  pIter->iCurrent = 0;
  fts5InitExprIterator(pRoot->aPk, pRoot->nPk, pRoot, pIter);
  pIter->iMatch = 0;
  pIter->bValid = 1;
  fts5IterSetCurrent(pIter, pCsr->pExpr->nPhrase);
}

SQLITE4_API int sqlite4_mi_match_detail(
  sqlite4_context *pCtx,          /* Context object passed to mi function */
  int iMatch,                     /* Index of match */
  int *piOff,                     /* OUT: Token offset of match */
  int *piC,                       /* OUT: Column number of match iMatch */
  int *piS,                       /* OUT: Stream number of match iMatch */
  int *piP                        /* OUT: Phrase number of match iMatch */
){
  int rc = SQLITE4_OK;
  Fts5Cursor *pCsr = pCtx->pFts;
  if( pCsr==0 ){
    rc = SQLITE4_MISUSE;
  }else{
    int nPhrase = pCsr->pExpr->nPhrase;
    Fts5MatchIter *pIter = pCsr->pIter;
    if( pIter==0 ){
      pCsr->pIter = pIter = (Fts5MatchIter *)sqlite4DbMallocZero(
          pCsr->db, sizeof(Fts5MatchIter) + sizeof(InstanceList)*nPhrase
      );
      if( pIter ){
        pIter->aList = (InstanceList *)&pIter[1];
      }else{
        rc = SQLITE4_NOMEM;
      }
    }

    if( rc==SQLITE4_OK && (pIter->bValid==0 || iMatch<pIter->iMatch) ){
      fts5InitIterator(pCsr);
#if 0
      int i;
      for(i=0; i<pCsr->pExpr->nPhrase; i++){
        Fts5Str *pStr = pCsr->pExpr->apPhrase[i];
        fts5InstanceListInit(pStr->aList, pStr->nList, &pIter->aList[i]);
        fts5InstanceListNext(&pIter->aList[i]);
      }
      pIter->iMatch = 0;
      fts5IterSetCurrent(pIter, pCsr->pExpr->nPhrase);
#endif
    }

    if( rc==SQLITE4_OK ){
      assert( pIter->iMatch<=iMatch );
      while( pIter->iCurrent>=0 && pIter->iMatch<iMatch ){
        fts5InstanceListNext(&pIter->aList[pIter->iCurrent]);
        fts5IterSetCurrent(pIter, pCsr->pExpr->nPhrase);
        pIter->iMatch++;
      }
      if( pIter->iCurrent<0 ){
        rc = SQLITE4_NOTFOUND;
      }else{
        InstanceList *p = &pIter->aList[pIter->iCurrent];
        *piOff = p->iOff;
        *piC = p->iCol;
        *piS = p->iStream;
        *piP = pIter->iCurrent;
      }
    }
  }
  return rc;
}

/**************************************************************************
***************************************************************************
** Below this point is test code.
*/
#ifdef SQLITE4_TEST
static int fts5PrintExprNode(sqlite4 *, const char **, Fts5ExprNode *, char **);
static int fts5PrintExprNodeParen(
  sqlite4 *db, const char **azCol,
  Fts5ExprNode *pNode, 
  char **pzRet
){
  int bParen = (pNode->eType!=TOKEN_PRIMITIVE || pNode->pPhrase->nStr>1);
  sqlite4_env *pEnv = sqlite4_db_env(db);
  char *zRet = *pzRet;

  if( bParen ) zRet = sqlite4_mprintf(pEnv, "%z(", zRet);
  fts5PrintExprNode(db, azCol, pNode, &zRet);
  if( bParen ) zRet = sqlite4_mprintf(pEnv, "%z)", zRet);

  *pzRet = zRet;
  return SQLITE4_OK;
}
static int fts5PrintExprNode(
  sqlite4 *db, 
  const char **azCol,
  Fts5ExprNode *pNode, 
  char **pzRet
){
  sqlite4_env *pEnv = sqlite4_db_env(db);
  char *zRet = *pzRet;

  assert(
      pNode->eType==TOKEN_AND || pNode->eType==TOKEN_OR
   || pNode->eType==TOKEN_NOT || pNode->eType==TOKEN_PRIMITIVE
  );
  assert( (pNode->eType==TOKEN_PRIMITIVE)==(pNode->pPhrase!=0) );

  if( pNode->eType==TOKEN_PRIMITIVE ){
    int iStr;
    Fts5Phrase *pPhrase = pNode->pPhrase;
    if( pPhrase->iCol>=0 ){
        zRet = sqlite4_mprintf(pEnv, "%z\"%s\":", zRet, azCol[pPhrase->iCol]);
    }
    for(iStr=0; iStr<pPhrase->nStr; iStr++){
      int iToken;
      Fts5Str *pStr = &pPhrase->aStr[iStr];
      if( iStr>0 ){
        zRet = sqlite4_mprintf(
            pEnv, "%z NEAR/%d ", zRet, pPhrase->aiNear[iStr-1]
        );
      }
      for(iToken=0; iToken<pStr->nToken; iToken++){
        int nRet = sqlite4Strlen30(zRet);
        const char *z = pStr->aToken[iToken].z;
        int n = pStr->aToken[iToken].n;
        int i;

        zRet = (char *)sqlite4_realloc(pEnv, zRet, nRet + n*2+4);
        if( iToken>0 ) zRet[nRet++] = '+';
        zRet[nRet++] = '"';

        for(i=0; i<n; i++){
          if( z[i]=='"' ) zRet[nRet++] = '"';
          zRet[nRet++] = z[i];
        }
        zRet[nRet++] = '"';
        if( pStr->aToken[iToken].bPrefix ){
          zRet[nRet++] = '*';
        }
        zRet[nRet++] = '\0';
      }
    }
  }else{
    fts5PrintExprNodeParen(db, azCol, pNode->pLeft, &zRet);
    switch( pNode->eType ){
      case TOKEN_AND:
        zRet = sqlite4_mprintf(pEnv, "%z AND ", zRet);
        break;
      case TOKEN_OR:
        zRet = sqlite4_mprintf(pEnv, "%z OR ", zRet);
        break;
      case TOKEN_NOT:
        zRet = sqlite4_mprintf(pEnv, "%z NOT ", zRet);
        break;
    }
    fts5PrintExprNodeParen(db, azCol, pNode->pRight, &zRet);
  }

  *pzRet = zRet;
  return SQLITE4_OK;
}
static int fts5PrintExpr(
  sqlite4 *db, 
  const char **azCol, 
  Fts5Expr *pExpr, 
  char **pzRet
){
  return fts5PrintExprNode(db, azCol, pExpr->pRoot, pzRet);
}

/*
** A user defined function used to test the fts5 expression parser. As follows:
**
**   fts5_parse_expr(<tokenizer>, <expr>);
*/
static void fts5_parse_expr(
  sqlite4_context *pCtx, 
  int nVal, 
  sqlite4_value **aVal
){
  int rc;
  Fts5Expr *pExpr = 0;
  Fts5Tokenizer *pTok;
  sqlite4_tokenizer *p = 0;
  sqlite4 *db;

  const char *zTokenizer;
  const char *zExpr;
  const char *zTbl;
  char *zErr = 0;
  char *zRet = 0;
  const char **azCol = 0;
  int nCol = 0;
  sqlite4_stmt *pStmt = 0;

  db = sqlite4_context_db_handle(pCtx);
  assert( nVal==3 );
  zTokenizer = sqlite4_value_text(aVal[0], 0);
  zExpr = sqlite4_value_text(aVal[1], 0);
  zTbl = sqlite4_value_text(aVal[2], 0);

  if( sqlite4Strlen30(zTbl)>0 ){
    int i;
    char *zSql = sqlite4MPrintf(db, "SELECT * FROM '%q'", zTbl);
    rc = sqlite4_prepare(db, zSql, -1, &pStmt, 0);
    sqlite4DbFree(db, zSql);
    if( rc!=SQLITE4_OK ){
      sqlite4_result_error(pCtx, sqlite4_errmsg(db), -1);
      sqlite4_result_error_code(pCtx, rc);
      return;
    }
    nCol = sqlite4_column_count(pStmt);
    azCol = sqlite4DbMallocZero(db, sizeof(char *)*nCol);
    for(i=0; i<nCol; i++){
      azCol[i] = sqlite4_column_name(pStmt, i);
    }
  }

  pTok = fts5FindTokenizer(db, zTokenizer);
  if( pTok==0 ){
    zErr = sqlite4MPrintf(db, "no such tokenizer: %s", zTokenizer);
    goto fts5_parse_expr_out;
  }else{
    rc = pTok->xCreate(pTok->pCtx, 0, 0, &p);
    if( rc!=SQLITE4_OK ){
      zErr = sqlite4MPrintf(db, "error creating tokenizer: %d", rc);
      goto fts5_parse_expr_out;
    }
  }

  rc = fts5ParseExpression(
      db, pTok, p, 0, (char **)azCol, nCol, zExpr, &pExpr, &zErr);
  if( rc!=SQLITE4_OK ){
    if( zErr==0 ){
      zErr = sqlite4MPrintf(db, "error parsing expression: %d", rc);
    }
    goto fts5_parse_expr_out;
  }

  fts5PrintExpr(db, azCol, pExpr, &zRet);
  sqlite4_result_text(pCtx, zRet, -1, SQLITE4_TRANSIENT, 0);
  fts5ExpressionFree(db, pExpr);
  sqlite4_free(sqlite4_db_env(db), zRet);

 fts5_parse_expr_out:
  if( p ) pTok->xDestroy(p);
  sqlite4DbFree(db, azCol);
  sqlite4_finalize(pStmt);
  if( zErr ){
    sqlite4_result_error(pCtx, zErr, -1);
    sqlite4DbFree(db, zErr);
  }
}
#endif

/*
** Register the default FTS5 tokenizer and functions with handle db.
*/
SQLITE4_PRIVATE int sqlite4InitFts5(sqlite4 *db){
#ifdef SQLITE4_TEST
  int rc = sqlite4_create_function(
      db, "fts5_parse_expr", 3, 0, fts5_parse_expr, 0, 0, 0
  );
  if( rc!=SQLITE4_OK ) return rc;
#endif
  return sqlite4InitFts5Func(db);
}

/************** End of fts5.c ************************************************/
/************** Begin file fts5func.c ****************************************/
/*
** 2012 December 17
**
** 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.
**
*************************************************************************
*/

/*
** The BM25 and BM25F implementations in this file are based on information
** found in:
**
**   Stephen Robertson and Hugo Zaragoza: "The Probablistic Relevance
**   Framework: BM25 and Beyond", 2009.
*/

/* #include <math.h>                 // temporary: For log()  */

static char fts5Tolower(char c){
  if( c>='A' && c<='Z' ) c = c + ('a' - 'A');
  return c;
}

static int fts5SimpleCreate(
  void *pCtx, 
  const char **azArg, 
  int nArg, 
  sqlite4_tokenizer **pp
){
  *pp = (sqlite4_tokenizer *)pCtx;
  return SQLITE4_OK;
}

static int fts5SimpleDestroy(sqlite4_tokenizer *p){
  return SQLITE4_OK;
}

typedef struct Fts5RankCtx Fts5RankCtx;
struct Fts5RankCtx {
  sqlite4 *db;
  double *aAvgdl;                 /* Average document size of each field */
  int nPhrase;                    /* Number of phrases in query */
  double *aIdf;                   /* IDF weights for each phrase in query */
};

static void fts5RankFreeCtx(void *pNotUsed, void *pCtx){
  if( pCtx ){
    Fts5RankCtx *p = (Fts5RankCtx *)pCtx;
    sqlite4DbFree(p->db, p);
  }
}

#define BM25_EXPLAIN  0x01
#define BM25_FCOLUMNS 0x02
#define BM25_FSTREAMS 0x04

static int fts5GetSizeFreqScale(
  sqlite4_context *pCtx,
  int nArg, sqlite4_value **apArg,/* Function arguments */
  int bm25mask,                   /* bm25 configuration mask */
  int iPhrase,                    /* Phrase number */
  int iField,                     /* Field number */
  int *pnSize,                    /* OUT: Size of field in tokens */
  int *pnFreq,                    /* OUT: Occurences of phrase in field */
  double *pdScale                 /* OUT: Scale to use with this field */
){
  int rc;
  double scale = 1.0;
  int nSize = 0;
  int nFreq = 0;

  if( bm25mask & BM25_FCOLUMNS ){
    rc = sqlite4_mi_match_count(pCtx, iField, -1, iPhrase, &nFreq); 
    if( rc==SQLITE4_OK ) rc = sqlite4_mi_size(pCtx, iField, -1, &nSize); 
    if( nArg>iField ) scale = sqlite4_value_double(apArg[iField]);
  }else if( bm25mask & BM25_FSTREAMS ){
    rc = sqlite4_mi_match_count(pCtx, -1, iField, iPhrase, &nFreq); 
    if( rc==SQLITE4_OK ) rc = sqlite4_mi_size(pCtx, -1, iField, &nSize); 
    if( nArg>iField ) scale = sqlite4_value_double(apArg[iField]);
  }else{
    rc = sqlite4_mi_match_count(pCtx, -1, -1, iPhrase, &nFreq); 
    if( rc==SQLITE4_OK ) rc = sqlite4_mi_size(pCtx, -1, -1, &nSize); 
  }

  *pnSize = nSize;
  *pnFreq = nFreq;
  *pdScale = scale;
  return rc;
}

/*
** A BM25(F) based ranking function for fts5.
**
** This is based on the information in the Robertson/Zaragoza paper 
** referenced above. As there is no way to provide relevance feedback 
** IDF weights (equation 3.3 in R/Z) are used instead of RSJ for each phrase.
** The rest of the implementation is as presented in equations 3.19-21.
**
** R and Z observe that the experimental evidence suggests that reasonable
** values for free parameters "b" and "k1" are often in the ranges 
** (0.5 < b < 0.8) and (1.2 < k1 < 2), although the optimal values depend
** on the nature of both the documents and queries. The implementation
** below sets each parameter to the midpoint of the suggested range.
*/
static void fts5Rank(sqlite4_context *pCtx, int nArg, sqlite4_value **apArg){
  const double b = 0.65;
  const double k1 = 1.6;

  sqlite4 *db = sqlite4_context_db_handle(pCtx);
  int rc = SQLITE4_OK;            /* Error code */
  Fts5RankCtx *p;                 /* Structure to store reusable values */
  int i;                          /* Used to iterate through phrases */
  double rank = 0.0;              /* UDF return value */

  int bExplain;                   /* True to run in explain mode */
  char *zExplain = 0;             /* String to return in explain mode */
  int nField = 1;                 /* Number of fields in collection */

  int bm25mask = SQLITE4_PTR_TO_INT(sqlite4_context_appdata(pCtx));
  bExplain = (bm25mask & BM25_EXPLAIN);

  if( bm25mask & BM25_FCOLUMNS ) sqlite4_mi_column_count(pCtx, &nField);
  if( bm25mask & BM25_FSTREAMS ) sqlite4_mi_stream_count(pCtx, &nField);

  p = sqlite4_auxdata_fetch(pCtx, 0);
  if( p==0 ){
    int nPhrase;                  /* Number of phrases in query expression */
    int nByte;                    /* Number of bytes of data to allocate */

    sqlite4_mi_phrase_count(pCtx, &nPhrase);
    nByte = sizeof(Fts5RankCtx) + (nPhrase+nField) * sizeof(double);
    p = (Fts5RankCtx *)sqlite4DbMallocZero(db, nByte);
    sqlite4_auxdata_store(pCtx, 0, (void *)p, fts5RankFreeCtx, 0);
    p = sqlite4_auxdata_fetch(pCtx, 0);

    if( !p ){
      rc = SQLITE4_NOMEM;
    }else{
      int N;                      /* Total number of docs in collection */
      int ni;                     /* Number of docs with phrase i */

      p->db = db;
      p->nPhrase = nPhrase;
      p->aIdf = (double *)&p[1];
      p->aAvgdl = &p->aIdf[nPhrase];

      /* Determine the IDF weight for each phrase in the query. */
      rc = sqlite4_mi_total_rows(pCtx, &N);
      for(i=0; rc==SQLITE4_OK && i<nPhrase; i++){
        rc = sqlite4_mi_row_count(pCtx, -1, -1, i, &ni);
        if( rc==SQLITE4_OK ){
          assert( ni<=N );
          p->aIdf[i] = log((0.5 + N - ni) / (0.5 + ni));
        }
      }

      /* Determine the average document length. For bm25f, determine the
      ** average length of each field.  */
      if( rc==SQLITE4_OK ){
        int iField;
        for(iField=0; iField<nField; iField++){
          int nTotal;
          if( bm25mask & BM25_FCOLUMNS ){
            rc = sqlite4_mi_total_size(pCtx, iField, -1, &nTotal);
          }else if( bm25mask & BM25_FSTREAMS ){
            rc = sqlite4_mi_total_size(pCtx, -1, iField, &nTotal);
          }else{
            rc = sqlite4_mi_total_size(pCtx, -1, -1, &nTotal);
          }
          if( rc==SQLITE4_OK ){
            p->aAvgdl[iField] = (double)nTotal / (double)N;
          }
        }
      }
    }
  }

  if( bExplain ){
    int iField;
    zExplain = sqlite4MAppendf(
        db, zExplain, "%s<table><tr><th>Stream<th>Scale<th>avgsl<th>sl", 
        zExplain
    );
    for(i=0; i<p->nPhrase; i++){
      zExplain = sqlite4MAppendf(
        db, zExplain, "%s<th>tf</span><sub>%d</sub>", zExplain, i
      );
    }
    for(iField=0; rc==SQLITE4_OK && iField<nField; iField++){
      int dl, tf;
      double scale;
      rc = fts5GetSizeFreqScale(
          pCtx, nArg, apArg, bm25mask, 0, iField, &dl, &tf, &scale
      );
      zExplain = sqlite4MAppendf(
          db, zExplain, "%s<tr><td>%d<td>%.2f<td>%.2f<td>%d", 
          zExplain, iField, scale, p->aAvgdl[iField], dl
      );
      for(i=0; rc==SQLITE4_OK && i<p->nPhrase; i++){
        rc = fts5GetSizeFreqScale(
            pCtx, nArg, apArg, bm25mask, i, iField, &dl, &tf, &scale
        );
        zExplain = sqlite4MAppendf(db, zExplain, "%s<td>%d", zExplain, tf);
      }
    }
    zExplain = sqlite4MAppendf(
        db, zExplain, "%s</table><table><tr><th>Phrase<th>IDF", zExplain
    );
    for(i=0; i<nField; i++){
      zExplain = sqlite4MAppendf(
        db, zExplain, "%s<th><span style=text-decoration:overline>"
        "tf</span><sub>s%d</sub>", zExplain, i
      );
    }
    zExplain = sqlite4MAppendf(db, zExplain, "%s<th>rank", zExplain);
  }

  for(i=0; rc==SQLITE4_OK && i<p->nPhrase; i++){
    int iField;
    double tfns = 0.0;            /* Sum of tfn for all fields */
    double prank;                 /* Contribution to rank of this phrase */

    if( bExplain ){
      zExplain = sqlite4MAppendf(
        db, zExplain, "%s<tr><td>%d<td>%.2f", zExplain, i, p->aIdf[i]
      );
    }

    for(iField = 0; iField<nField; iField++){
      double scale = 1.0;
      int tf;                       /* Count of phrase i in row (term freq.) */
      double tfn;                   /* Normalized term frequency */
      int dl;                       /* Tokens in this row (document length) */
      double B;                     /* B from formula 3.20 */

      /* Set variable tf to the total number of occurrences of phrase iPhrase
      ** in this row/field. And dl to the number of tokens in the current 
      ** row/field. */
      rc = fts5GetSizeFreqScale(
          pCtx, nArg, apArg, bm25mask, i, iField, &dl, &tf, &scale
      );

      B = (1.0 - b) + b * (double)dl / p->aAvgdl[iField];    /* 3.20 */
      tfn = scale * (double)tf / B;
      tfns += tfn;                                           /* 3.19 */


      if( bExplain ){
        zExplain = sqlite4MAppendf(db, zExplain, "%s<td>%.2f", zExplain, tfn);
      }
    }

    prank = p->aIdf[i] * tfns / (k1 + tfns);                 /* 3.21 */
    if( bExplain ){
      zExplain = sqlite4MAppendf(db, zExplain, "%s<td>%.2f", zExplain, prank);
    }

    /* Add it to the overall rank */
    rank += prank;
  }

  if( rc==SQLITE4_OK ){
    if( bExplain ){
      zExplain = sqlite4MAppendf(
          db, zExplain, "%s</table><b>overall rank=%.2f</b>", zExplain, rank
      );
      sqlite4_result_text(pCtx, zExplain, -1, SQLITE4_TRANSIENT, 0);
    }else{
      sqlite4_result_double(pCtx, rank);
    }
  }else{
    sqlite4_result_error_code(pCtx, rc);
  }
  sqlite4DbFree(db, zExplain);
}

typedef struct Snippet Snippet;
typedef struct SnippetText SnippetText;

struct Snippet {
  int iCol;
  int iOff;
  u64 hlmask;
};

struct SnippetText {
  char *zOut;                     /* Pointer to snippet text */
  int nOut;                       /* Size of zOut in bytes */
  int nAlloc;                     /* Bytes of space allocated at zOut */
};

typedef struct SnippetCtx SnippetCtx;
struct SnippetCtx {
  sqlite4 *db;                    /* Database handle */
  int nToken;                     /* Number of tokens in snippet */
  int iOff;                       /* First token in snippet */
  u64 mask;                       /* Snippet mask. Highlight these terms */
  const char *zStart;
  const char *zEnd;
  const char *zEllipses;

  SnippetText *pOut;

  int iFrom;
  int iTo;
  const char *zText;              /* Document to extract snippet from */
  int rc;                         /* Set to NOMEM if OOM is encountered */
};

static void fts5SnippetAppend(SnippetCtx *p, const char *z, int n){
  if( p->rc==SQLITE4_OK ){
    SnippetText *pOut = p->pOut;
    if( n<0 ) n = strlen(z);
    if( (pOut->nOut + n) > pOut->nAlloc ){
      int nNew = (pOut->nOut+n) * 2;

      pOut->zOut = sqlite4DbReallocOrFree(p->db, pOut->zOut, nNew);
      if( pOut->zOut==0 ){
        p->rc = SQLITE4_NOMEM;
        return;
      }
      pOut->nAlloc = sqlite4DbMallocSize(p->db, pOut->zOut);
    }

    memcpy(&pOut->zOut[pOut->nOut], z, n);
    pOut->nOut += n;
  }
}

static int fts5SnippetCb(
  void *pCtx, 
  int iStream, 
  int iOff, 
  const char *z, int n,
  int iSrc, int nSrc
){
  SnippetCtx *p = (SnippetCtx *)pCtx;

  if( iOff<p->iOff ){
    return 0;
  }else if( iOff>=(p->iOff + p->nToken) ){
    fts5SnippetAppend(p, &p->zText[p->iFrom], p->iTo - p->iFrom);
    fts5SnippetAppend(p, p->zEllipses, -1);
    p->iFrom = -1;
    return 1;
  }else{
    int bHighlight;               /* True to highlight term */

    bHighlight = (p->mask & ((u64)1 << (iOff-p->iOff))) ? 1 : 0;

    if( p->iFrom==0 && p->iOff!=0 ){
      p->iFrom = iSrc;
      if( p->pOut->nOut==0 ) fts5SnippetAppend(p, p->zEllipses, -1);
    }

    if( bHighlight ){
      fts5SnippetAppend(p, &p->zText[p->iFrom], iSrc - p->iFrom);
      fts5SnippetAppend(p, p->zStart, -1);
      fts5SnippetAppend(p, &p->zText[iSrc], nSrc);
      fts5SnippetAppend(p, p->zEnd, -1);
      p->iTo = p->iFrom = iSrc+nSrc;
    }else{
      p->iTo = iSrc + nSrc;
    }
  }

  return 0;
}

static int fts5SnippetText(
  sqlite4_context *pCtx, 
  Snippet *pSnip,
  SnippetText *pText,
  int nToken,
  const char *zStart,
  const char *zEnd,
  const char *zEllipses
){
  int rc;
  sqlite4_value *pVal = 0;

  u64 mask = pSnip->hlmask;
  int iOff = pSnip->iOff;
  int iCol = pSnip->iCol;

  rc = sqlite4_mi_column_value(pCtx, iCol, &pVal);
  if( rc==SQLITE4_OK ){
    SnippetCtx sCtx;
    int nText;

    memset(&sCtx, 0, sizeof(sCtx));
    sCtx.zText = sqlite4_value_text(pVal, &nText);
    sCtx.db = sqlite4_context_db_handle(pCtx);
    sCtx.nToken = nToken;
    sCtx.iOff = iOff;
    sCtx.mask = mask;
    sCtx.zStart = zStart;
    sCtx.zEnd = zEnd;
    sCtx.zEllipses = zEllipses;
    sCtx.pOut = pText;

    sqlite4_mi_tokenize(pCtx, sCtx.zText, nText, &sCtx, fts5SnippetCb);
    if( sCtx.rc==SQLITE4_OK && sCtx.iFrom>0 ){
      fts5SnippetAppend(&sCtx, &sCtx.zText[sCtx.iFrom], nText - sCtx.iFrom);
    }
    rc = sCtx.rc;
  }

  return rc;
}

static int fts5BestSnippet(
  sqlite4_context *pCtx,          /* Context snippet() was called in */
  int iColumn,                    /* In this column (-1 means any column) */
  u64 *pMask,                     /* IN/OUT: Mask of high-priority phrases */
  int nToken,                     /* Number of tokens in requested snippet */
  Snippet *pSnip                  /* Populate this object */
){
  sqlite4 *db = sqlite4_context_db_handle(pCtx);
  int nPhrase;
  int rc = SQLITE4_OK;
  int i;
  int iPrev = 0;
  int iPrevCol = 0;
  u64 *aMask;
  u64 mask = *pMask;
  u64 allmask = 0;

  int iBestOff = nToken-1;
  int iBestCol = (iColumn >= 0 ? iColumn : 0);
  int nBest = 0;
  u64 hlmask = 0;                 /* Highlight mask associated with iBestOff */
  u64 missmask = 0;               /* Mask of missing terms in iBestOff snip. */

  sqlite4_mi_phrase_count(pCtx, &nPhrase);
  aMask = sqlite4DbMallocZero(db, sizeof(u64) * nPhrase);
  if( !aMask ) return SQLITE4_NOMEM;

  /* Iterate through all matches for all phrases */
  for(i=0; rc==SQLITE4_OK; i++){
    int iOff;
    int iCol;
    int iStream;
    int iPhrase;

    rc = sqlite4_mi_match_detail(pCtx, i, &iOff, &iCol, &iStream, &iPhrase);
    if( rc==SQLITE4_OK ){
      u64 tmask = 0;
      u64 miss = 0;
      int iMask;
      int nShift; 
      int nScore = 0;

      int nPTok;
      int iPTok;

      if( iColumn>=0 && iColumn!=iCol ) continue;

      allmask |= ((u64)1 << iPhrase);

      nShift = ((iPrevCol==iCol) ? (iOff-iPrev) : 100);

      for(iMask=0; iMask<nPhrase; iMask++){
        if( nShift<64){
          aMask[iMask] = aMask[iMask] >> nShift;
        }else{
          aMask[iMask] = 0;
        }
      }
      sqlite4_mi_phrase_token_count(pCtx, iPhrase, &nPTok);
      for(iPTok=0; iPTok<nPTok; iPTok++){
        aMask[iPhrase] = aMask[iPhrase] | ((u64)1 << (nToken-1+iPTok));
      }

      for(iMask=0; iMask<nPhrase; iMask++){
        int iBit;
        if( aMask[iMask] ){
          nScore += ((((u64)1 << iMask) & mask) ? 100 : 1);
        }else{
          miss |= ((u64)1 << iMask);
        }
        tmask = tmask | aMask[iMask];
        /* TODO: This is the Hamming Weight. There are much more efficient
        ** ways to calculate it. */
        for(iBit=0; iBit<nToken; iBit++){
          if( tmask & ((u64)1 << iBit) ) nScore++;
        }
      }

      if( nScore>nBest ){
        hlmask = tmask;
        missmask = miss;
        nBest = nScore;
        iBestOff = iOff;
        iBestCol = iCol;
      }

      iPrev = iOff;
      iPrevCol = iCol;
    }
  }
  if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK;

  pSnip->iOff = iBestOff-nToken+1;
  pSnip->iCol = iBestCol;
  pSnip->hlmask = hlmask;
  *pMask = mask & missmask & allmask;

  sqlite4DbFree(db, aMask);
  return rc;
}

static void fts5SnippetImprove(
  sqlite4_context *pCtx, 
  int nToken,                     /* Size of required snippet */
  int nSz,                        /* Total size of column in tokens */
  Snippet *pSnip
){
  int i;
  int nLead = 0;
  int nShift = 0;

  u64 mask = pSnip->hlmask;
  int iOff = pSnip->iOff;

  if( mask==0 ) return;
  assert( mask & ((u64)1 << (nToken-1)) );

  for(i=0; (mask & ((u64)1 << i))==0; i++);
  nLead = i;

  nShift = (nLead/2);
  if( iOff+nShift > nSz-nToken ) nShift = (nSz-nToken) - iOff;
  if( iOff+nShift < 0 ) nShift = -1 * iOff;

  iOff += nShift;
  mask = mask >> nShift;

  pSnip->iOff = iOff;
  pSnip->hlmask = mask;
}

/*
** Parameter aSnip points to an array of nSnip Snippet objects, where nSnip
** is less than or equal to 4. This function sorts the array in place in
** ascending order of Snippet.iCol and Snippet.iOff. 
*/
static void fts5SnippetSort(Snippet *aSnip, int nSnip){
  Snippet aTmp[4];
  int i;

  assert( nSnip<=4 && nSnip>=1 );

  for(i=0; i<nSnip; i++){
    int iBest = -1;
    int iTry;
    for(iTry=0; iTry<nSnip; iTry++){
      Snippet *pTry = &aSnip[iTry];
      if( pTry->iCol>=0 && (iBest<0 
         || pTry->iCol<aSnip[iBest].iCol
         || (pTry->iCol==aSnip[iBest].iCol && pTry->iOff<aSnip[iBest].iOff)
      )){
        iBest = iTry;
      }
    }

    assert( iBest>=0 );
    memcpy(&aTmp[i], &aSnip[iBest], sizeof(Snippet));
    aSnip[iBest].iCol = -1;
  }

  memcpy(aSnip, aTmp, sizeof(Snippet)*nSnip);
}


static void fts5Snippet(sqlite4_context *pCtx, int nArg, sqlite4_value **apArg){
  Snippet aSnip[4];
  int nSnip;
  int iCol = -1;
  int nToken = -15;
  int rc;
  int nPhrase;

  const char *zStart = "<b>";
  const char *zEnd = "</b>";
  const char *zEllipses = "...";

  if( nArg>0 ) zStart = (const char *)sqlite4_value_text(apArg[0], 0);
  if( nArg>1 ) zEnd = (const char *)sqlite4_value_text(apArg[1], 0);
  if( nArg>2 ) zEllipses = (const char *)sqlite4_value_text(apArg[2], 0);
  if( nArg>3 ) iCol = sqlite4_value_int(apArg[3]);
  if( nArg>4 ) nToken = sqlite4_value_int(apArg[4]);

  rc = sqlite4_mi_phrase_count(pCtx, &nPhrase);
  for(nSnip=1; rc==SQLITE4_OK && nSnip<5; nSnip = ((nSnip==2) ? 3 : (nSnip+1))){
    int nTok;
    int i;
    u64 mask = ((u64)1 << nPhrase) - 1;

    if( nToken<0 ){
      nTok = nToken * -1;
    }else{
      nTok = (nToken + (nSnip-1)) / nSnip;
    }

    memset(aSnip, 0, sizeof(aSnip));
    for(i=0; rc==SQLITE4_OK && i<nSnip; i++){
      rc = fts5BestSnippet(pCtx, iCol, &mask, nTok, &aSnip[i]);
    }
    if( mask==0 || nSnip==4 ){
      SnippetText text = {0, 0, 0};
      fts5SnippetSort(aSnip, nSnip);
      for(i=0; rc==SQLITE4_OK && i<nSnip; i++){
        int nSz;
        rc = sqlite4_mi_size(pCtx, aSnip[i].iCol, -1, &nSz);
        if( rc==SQLITE4_OK ){
          fts5SnippetImprove(pCtx, nTok, nSz, &aSnip[i]);
          rc = fts5SnippetText(
              pCtx, &aSnip[i], &text, nTok, zStart, zEnd, zEllipses
          );
        }
      }
      sqlite4_result_text(pCtx, text.zOut, text.nOut, SQLITE4_TRANSIENT, 0);
      sqlite4DbFree(sqlite4_context_db_handle(pCtx), text.zOut);
      break;
    }
  }

  if( rc!=SQLITE4_OK ){
    sqlite4_result_error_code(pCtx, rc);
  }
}

static int fts5SimpleTokenize(
  void *pCtx, sqlite4_tokenizer *p,
  const char *zDoc,
  int nDoc,
  int(*x)(void*, int, int, const char*, int, int, int)
){
  sqlite4_env *pEnv = (sqlite4_env *)p;
  char *aBuf;
  int nBuf;
  int iBuf;
  int i;
  int brk = 0;
  int iOff = 0;

  nBuf = 128;
  aBuf = (char *)sqlite4_malloc(pEnv, nBuf);
  if( !aBuf ) return SQLITE4_NOMEM;

  iBuf = 0;
  for(i=0; brk==0 && i<nDoc; i++){
    if( sqlite4Isalnum(zDoc[i]) ){
      aBuf[iBuf++] = fts5Tolower(zDoc[i]);
    }else if( iBuf>0 ){
      brk = x(pCtx, 0, iOff++, aBuf, iBuf, i-iBuf, iBuf);
      iBuf = 0;
    }
  }
  if( iBuf>0 ) x(pCtx, 0, iOff++, aBuf, iBuf, i-iBuf, iBuf);

  sqlite4_free(pEnv, aBuf);
  return SQLITE4_OK;
}

SQLITE4_PRIVATE int sqlite4InitFts5Func(sqlite4 *db){
  int rc;
  int i;
  sqlite4_env *pEnv = sqlite4_db_env(db);

  struct RankFunction {
    const char *zName;
    int mask;
  } aRank[] = {
    { "rank",  0 },
    { "erank",  BM25_EXPLAIN },
    { "rankc",  BM25_FCOLUMNS },
    { "erankc", BM25_FCOLUMNS|BM25_EXPLAIN },
    { "ranks",  BM25_FSTREAMS },
    { "eranks", BM25_FSTREAMS|BM25_EXPLAIN }
  };

  rc = sqlite4_create_tokenizer(db, "simple", (void *)pEnv, 
      fts5SimpleCreate, fts5SimpleTokenize, fts5SimpleDestroy
  );
  if( rc==SQLITE4_OK ){
    rc = sqlite4_create_mi_function(
        db, "snippet", -1, SQLITE4_UTF8, 0, fts5Snippet, 0);
  }

  for(i=0; rc==SQLITE4_OK && i<ArraySize(aRank); i++){
    void *p = SQLITE4_INT_TO_PTR(aRank[i].mask);
    const char *z = aRank[i].zName;
    rc = sqlite4_create_mi_function(db, z, -1, SQLITE4_UTF8, p, fts5Rank, 0);
  }

  return rc;
}

/************** End of fts5func.c ********************************************/
/************** Begin file parse.c *******************************************/
/* Driver template for the LEMON parser generator.
** The author disclaims copyright to this source code.
**
** This version of "lempar.c" is modified, slightly, for use by SQLite.
** The only modifications are the addition of a couple of NEVER()
** macros to disable tests that are needed in the case of a general
** LALR(1) grammar but which are always false in the
** specific grammar used by SQLite.
*/
/* First off, code is included that follows the "include" declaration
** in the input grammar file. */
/* #include <stdio.h> */


/*
** Disable all error recovery processing in the parser push-down
** automaton.
*/
#define YYNOERRORRECOVERY 1

/*
** Make yytestcase() the same as testcase()
*/
#define yytestcase(X) testcase(X)

/*
** An instance of this structure holds information about the
** LIMIT clause of a SELECT statement.
*/
struct LimitVal {
  Expr *pLimit;    /* The LIMIT expression.  NULL if there is no limit */
  Expr *pOffset;   /* The OFFSET expression.  NULL if there is none */
};

/*
** An instance of this structure is used to store the LIKE,
** GLOB, NOT LIKE, and NOT GLOB operators.
*/
struct LikeOp {
  Token eOperator;  /* "like" or "glob" or "regexp" */
  int not;         /* True if the NOT keyword is present */
};

/*
** An instance of the following structure describes the event of a
** TRIGGER.  "a" is the event type, one of TK_UPDATE, TK_INSERT,
** TK_DELETE, or TK_INSTEAD.  If the event is of the form
**
**      UPDATE ON (a,b,c)
**
** Then the "b" IdList records the list "a,b,c".
*/
struct TrigEvent { int a; IdList * b; };

/*
** An instance of this structure holds the ATTACH key and the key type.
*/
struct AttachKey { int type;  Token key; };

/*
** One or more VALUES claues
*/
struct ValueList {
  ExprList *pList;
  Select *pSelect;
};

/*
** A COVERING clause.
*/
struct CoveringOpt { IdList *pList; Token sEnd; };


  /* This is a utility routine used to set the ExprSpan.zStart and
  ** ExprSpan.zEnd values of pOut so that the span covers the complete
  ** range of text beginning with pStart and going to the end of pEnd.
  */
  static void spanSet(ExprSpan *pOut, Token *pStart, Token *pEnd){
    pOut->zStart = pStart->z;
    pOut->zEnd = &pEnd->z[pEnd->n];
  }

  /* Construct a new Expr object from a single identifier.  Use the
  ** new Expr to populate pOut.  Set the span of pOut to be the identifier
  ** that created the expression.
  */
  static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token *pValue){
    pOut->pExpr = sqlite4PExpr(pParse, op, 0, 0, pValue);
    pOut->zStart = pValue->z;
    pOut->zEnd = &pValue->z[pValue->n];
  }

  /* This routine constructs a binary expression node out of two ExprSpan
  ** objects and uses the result to populate a new ExprSpan object.
  */
  static void spanBinaryExpr(
    ExprSpan *pOut,     /* Write the result here */
    Parse *pParse,      /* The parsing context.  Errors accumulate here */
    int op,             /* The binary operation */
    ExprSpan *pLeft,    /* The left operand */
    ExprSpan *pRight    /* The right operand */
  ){
    pOut->pExpr = sqlite4PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0);
    pOut->zStart = pLeft->zStart;
    pOut->zEnd = pRight->zEnd;
  }

  /* Construct an expression node for a unary postfix operator
  */
  static void spanUnaryPostfix(
    ExprSpan *pOut,        /* Write the new expression node here */
    Parse *pParse,         /* Parsing context to record errors */
    int op,                /* The operator */
    ExprSpan *pOperand,    /* The operand */
    Token *pPostOp         /* The operand token for setting the span */
  ){
    pOut->pExpr = sqlite4PExpr(pParse, op, pOperand->pExpr, 0, 0);
    pOut->zStart = pOperand->zStart;
    pOut->zEnd = &pPostOp->z[pPostOp->n];
  }                           

  /* A routine to convert a binary TK_IS or TK_ISNOT expression into a
  ** unary TK_ISNULL or TK_NOTNULL expression. */
  static void binaryToUnaryIfNull(Parse *pParse, Expr *pY, Expr *pA, int op){
    sqlite4 *db = pParse->db;
    if( db->mallocFailed==0 && pY->op==TK_NULL ){
      pA->op = (u8)op;
      sqlite4ExprDelete(db, pA->pRight);
      pA->pRight = 0;
    }
  }

  /* Construct an expression node for a unary prefix operator
  */
  static void spanUnaryPrefix(
    ExprSpan *pOut,        /* Write the new expression node here */
    Parse *pParse,         /* Parsing context to record errors */
    int op,                /* The operator */
    ExprSpan *pOperand,    /* The operand */
    Token *pPreOp         /* The operand token for setting the span */
  ){
    pOut->pExpr = sqlite4PExpr(pParse, op, pOperand->pExpr, 0, 0);
    pOut->zStart = pPreOp->z;
    pOut->zEnd = pOperand->zEnd;
  }
/* Next is all token values, in a form suitable for use by makeheaders.
** This section will be null unless lemon is run with the -m switch.
*/
/* 
** These constants (all generated automatically by the parser generator)
** specify the various kinds of tokens (terminals) that the parser
** understands. 
**
** Each symbol here is a terminal symbol in the grammar.
*/
/* Make sure the INTERFACE macro is defined.
*/
#ifndef INTERFACE
# define INTERFACE 1
#endif
/* The next thing included is series of defines which control
** various aspects of the generated parser.
**    YYCODETYPE         is the data type used for storing terminal
**                       and nonterminal numbers.  "unsigned char" is
**                       used if there are fewer than 250 terminals
**                       and nonterminals.  "int" is used otherwise.
**    YYNOCODE           is a number of type YYCODETYPE which corresponds
**                       to no legal terminal or nonterminal number.  This
**                       number is used to fill in empty slots of the hash 
**                       table.
**    YYFALLBACK         If defined, this indicates that one or more tokens
**                       have fall-back values which should be used if the
**                       original value of the token will not parse.
**    YYACTIONTYPE       is the data type used for storing terminal
**                       and nonterminal numbers.  "unsigned char" is
**                       used if there are fewer than 250 rules and
**                       states combined.  "int" is used otherwise.
**    sqlite4ParserTOKENTYPE     is the data type used for minor tokens given 
**                       directly to the parser from the tokenizer.
**    YYMINORTYPE        is the data type used for all minor tokens.
**                       This is typically a union of many types, one of
**                       which is sqlite4ParserTOKENTYPE.  The entry in the union
**                       for base tokens is called "yy0".
**    YYSTACKDEPTH       is the maximum depth of the parser's stack.  If
**                       zero the stack is dynamically sized using realloc()
**    sqlite4ParserARG_SDECL     A static variable declaration for the %extra_argument
**    sqlite4ParserARG_PDECL     A parameter declaration for the %extra_argument
**    sqlite4ParserARG_STORE     Code to store %extra_argument into yypParser
**    sqlite4ParserARG_FETCH     Code to extract %extra_argument from yypParser
**    YYNSTATE           the combined number of states.
**    YYNRULE            the number of rules in the grammar
**    YYERRORSYMBOL      is the code number of the error symbol.  If not
**                       defined, then do no error processing.
*/
#define YYCODETYPE unsigned char
#define YYNOCODE 252
#define YYACTIONTYPE unsigned short int
#define YYWILDCARD 66
#define sqlite4ParserTOKENTYPE Token
typedef union {
  int yyinit;
  sqlite4ParserTOKENTYPE yy0;
  Expr* yy72;
  TriggerStep* yy145;
  ExprList* yy148;
  struct ValueList yy167;
  SrcList* yy185;
  ExprSpan yy190;
  int yy194;
  CreateIndex yy195;
  u8 yy234;
  Select* yy243;
  IdList* yy254;
  struct TrigEvent yy332;
  struct LimitVal yy354;
  struct CoveringOpt yy376;
  struct LikeOp yy392;
  struct {int value; int mask;} yy497;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
#endif
#define sqlite4ParserARG_SDECL Parse *pParse;
#define sqlite4ParserARG_PDECL ,Parse *pParse
#define sqlite4ParserARG_FETCH Parse *pParse = yypParser->pParse
#define sqlite4ParserARG_STORE yypParser->pParse = pParse
#define YYNSTATE 625
#define YYNRULE 325
#define YYFALLBACK 1
#define YY_NO_ACTION      (YYNSTATE+YYNRULE+2)
#define YY_ACCEPT_ACTION  (YYNSTATE+YYNRULE+1)
#define YY_ERROR_ACTION   (YYNSTATE+YYNRULE)

/* The yyzerominor constant is used to initialize instances of
** YYMINORTYPE objects to zero. */
static const YYMINORTYPE yyzerominor = { 0 };

/* Define the yytestcase() macro to be a no-op if is not already defined
** otherwise.
**
** Applications can choose to define yytestcase() in the %include section
** to a macro that can assist in verifying code coverage.  For production
** code the yytestcase() macro should be turned off.  But it is useful
** for testing.
*/
#ifndef yytestcase
# define yytestcase(X)
#endif


/* Next are the tables used to determine what action to take based on the
** current state and lookahead token.  These tables are used to implement
** functions that take a state number and lookahead value and return an
** action integer.  
**
** Suppose the action integer is N.  Then the action is determined as
** follows
**
**   0 <= N < YYNSTATE                  Shift N.  That is, push the lookahead
**                                      token onto the stack and goto state N.
**
**   YYNSTATE <= N < YYNSTATE+YYNRULE   Reduce by rule N-YYNSTATE.
**
**   N == YYNSTATE+YYNRULE              A syntax error has occurred.
**
**   N == YYNSTATE+YYNRULE+1            The parser accepts its input.
**
**   N == YYNSTATE+YYNRULE+2            No such action.  Denotes unused
**                                      slots in the yy_action[] table.
**
** The action table is constructed as a single large table named yy_action[].
** Given state S and lookahead X, the action is computed as
**
**      yy_action[ yy_shift_ofst[S] + X ]
**
** If the index value yy_shift_ofst[S]+X is out of range or if the value
** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
** and that yy_default[S] should be used instead.  
**
** The formula above is for computing the action when the lookahead is
** a terminal symbol.  If the lookahead is a non-terminal (as occurs after
** a reduce action) then the yy_reduce_ofst[] array is used in place of
** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
** YY_SHIFT_USE_DFLT.
**
** The following are the tables generated in this section:
**
**  yy_action[]        A single table containing all actions.
**  yy_lookahead[]     A table containing the lookahead for each entry in
**                     yy_action.  Used to detect hash collisions.
**  yy_shift_ofst[]    For each state, the offset into yy_action for
**                     shifting terminals.
**  yy_reduce_ofst[]   For each state, the offset into yy_action for
**                     shifting non-terminals after a reduce.
**  yy_default[]       Default action for each state.
*/
#define YY_ACTTAB_COUNT (1595)
static const YYACTIONTYPE yy_action[] = {
 /*     0 */   312,  169,   50,   46,  153,  174,  622,  592,   56,   56,
 /*    10 */    56,   56,   49,   54,   54,   54,   54,   53,   53,   52,
 /*    20 */    52,   52,   51,  240,  242,   66,  618,  617,  428,  592,
 /*    30 */   585,   48,   56,   56,   56,   56,  354,   54,   54,   54,
 /*    40 */    54,   53,   53,   52,   52,   52,   51,  240,   57,   58,
 /*    50 */    47,  578,  577,  579,  579,   55,   55,   56,   56,   56,
 /*    60 */    56,  304,   54,   54,   54,   54,   53,   53,   52,   52,
 /*    70 */    52,   51,  240,  312,  592,  272,  329,  412,  509,   32,
 /*    80 */    54,   54,   54,   54,   53,   53,   52,   52,   52,   51,
 /*    90 */   240,  329,  415,  615,  614,  168,  592,  603,  383,  380,
 /*   100 */   379,  596,   81,  585,   48,  199,  198,  197,   59,  378,
 /*   110 */   512,  511,   53,   53,   52,   52,   52,   51,  240,  268,
 /*   120 */   270,   57,   58,   47,  578,  577,  579,  579,   55,   55,
 /*   130 */    56,   56,   56,   56,  216,   54,   54,   54,   54,   53,
 /*   140 */    53,   52,   52,   52,   51,  240,  312,  410,  228,  575,
 /*   150 */   575,  139,  179,  145,  286,  386,  281,  385,  171,  562,
 /*   160 */   412,  196,  429,  228,  412,  277,  502,  503,  145,  286,
 /*   170 */   386,  281,  385,  171,  576,  415,  585,   48,  168,  415,
 /*   180 */   277,  383,  380,  379,  596,   88,  241,  522,  596,   88,
 /*   190 */     3,  590,  378,   18,   57,   58,   47,  578,  577,  579,
 /*   200 */   579,   55,   55,   56,   56,   56,   56,  461,   54,   54,
 /*   210 */    54,   54,   53,   53,   52,   52,   52,   51,  240,  312,
 /*   220 */   113,  666,  588,  588,  588,  236,  285,  412,  397,  235,
 /*   230 */   338,  168,  419,  621,  383,  380,  379,  284,  243,  412,
 /*   240 */   136,  412,  415,   10,  597,  378,  207,  667,  598,  585,
 /*   250 */    48,  596,   95,  462,  415,  311,  415,    1,  564,  488,
 /*   260 */   215,  618,  617,  596,   95,  596,   81,   57,   58,   47,
 /*   270 */   578,  577,  579,  579,   55,   55,   56,   56,   56,   56,
 /*   280 */   595,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*   290 */    51,  240,  312,  399,  668,  487,  341,  340,  389,  469,
 /*   300 */   261,  350,  260,  470,  345,  395,  602,   67,  178,  412,
 /*   310 */   616,  242,  412,  545,  321,  314,   68,  366,  158,  204,
 /*   320 */   618,  617,  585,   48,  415,  316,  433,  415,  615,  614,
 /*   330 */   193,  478,  177,  596,   95,   38,  596,   95,  618,  617,
 /*   340 */    57,   58,   47,  578,  577,  579,  579,   55,   55,   56,
 /*   350 */    56,   56,   56,  595,   54,   54,   54,   54,   53,   53,
 /*   360 */    52,   52,   52,   51,  240,  312,  412,  568,  568,  527,
 /*   370 */   613,  612,  611,  618,  617,  399,  205,  557,  399,   44,
 /*   380 */   400,  415,  152,  351,  618,  617,  592,  615,  614,  365,
 /*   390 */   596,   74,  209,  556,  170,  585,   48,  619,  363,  529,
 /*   400 */    52,   52,   52,   51,  240,  615,  614,  545,   35,  555,
 /*   410 */   595,  403,  616,   57,   58,   47,  578,  577,  579,  579,
 /*   420 */    55,   55,   56,   56,   56,   56,  595,   54,   54,   54,
 /*   430 */    54,   53,   53,   52,   52,   52,   51,  240,  312,  572,
 /*   440 */   615,  614,  524,  573,  528,   65,  487,  315,  574,  412,
 /*   450 */   355,  615,  614,  592,  302,  412,  190,  477,   67,  563,
 /*   460 */   412,  616,  561,  560,  415,  538,  544,  173,  585,   48,
 /*   470 */   415,   62,  462,  596,   94,  415,  349,  543,  257,  596,
 /*   480 */    73,  618,  617,  208,  596,   95,   57,   58,   47,  578,
 /*   490 */   577,  579,  579,   55,   55,   56,   56,   56,   56,  202,
 /*   500 */    54,   54,   54,   54,   53,   53,   52,   52,   52,   51,
 /*   510 */   240,  312,  185,  557,  184,  507,  545,  595,  550,  261,
 /*   520 */   350,  260,  254,  256,  295,  356,  322,  549,  559,  556,
 /*   530 */   242,  159,  410,  540,  575,  575,  410,  176,  575,  575,
 /*   540 */   616,  585,   48,  353,  174,  555,  592,  516,  615,  614,
 /*   550 */   410,  558,  575,  575,  331,  571,  570,  554,  515,   57,
 /*   560 */    58,   47,  578,  577,  579,  579,   55,   55,   56,   56,
 /*   570 */    56,   56,  531,   54,   54,   54,   54,   53,   53,   52,
 /*   580 */    52,   52,   51,  240,  312,  152,  375,   34,  274,   50,
 /*   590 */    46,  153,  225,  408,  571,  570,  501,  487,  520,  255,
 /*   600 */   410,    6,  575,  575,  625,  623,  333,  599,  423,   67,
 /*   610 */   545,  384,  616,  592,  585,   48,  467,  170,  500,  480,
 /*   620 */   506,  239,   50,   46,  153,  201,  481,  951,  187,  420,
 /*   630 */     2,   30,   57,   58,   47,  578,  577,  579,  579,   55,
 /*   640 */    55,   56,   56,   56,   56,   13,   54,   54,   54,   54,
 /*   650 */    53,   53,   52,   52,   52,   51,  240,  312,  266,  595,
 /*   660 */   239,  412,   21,  624,    2,  412,  388,  327,   12,  203,
 /*   670 */   315,  200,  150,  616,  542,  277,  415,  471,  471,  368,
 /*   680 */   415,  496,  134,  169,  209,  596,   69,  585,   48,  596,
 /*   690 */    97,  597,  518,  517,  465,  598,  564,  407,  215,  172,
 /*   700 */   275,  336,  169,  595,  206,   57,   58,   47,  578,  577,
 /*   710 */   579,  579,   55,   55,   56,   56,   56,   56,  595,   54,
 /*   720 */    54,   54,   54,   53,   53,   52,   52,   52,   51,  240,
 /*   730 */   312,  412,  871,  278,  412,  343,  278,  600,  595,  376,
 /*   740 */   112,  169,  355,  601,  489,  492,  415,  412,  616,  415,
 /*   750 */   412,  616,  492,  547,  242,  596,  100,  334,  596,   98,
 /*   760 */   585,   48,  415,   20,  344,  415,  354,  455,  362,  173,
 /*   770 */   326,  596,  108,  227,  596,  107,  214,  150,   57,   58,
 /*   780 */    47,  578,  577,  579,  579,   55,   55,   56,   56,   56,
 /*   790 */    56,  412,   54,   54,   54,   54,   53,   53,   52,   52,
 /*   800 */    52,   51,  240,  312,  412,  278,  415,  412,  454,  391,
 /*   810 */    34,  412,  278,  359,  149,  596,  110,  392,  534,  415,
 /*   820 */   616,  360,  415,  412,  536,  526,  415,  616,  596,  111,
 /*   830 */   440,  596,  140,  585,   48,  596,  141,  525,  415,  616,
 /*   840 */   148,   39,  325,   37,  213,  233,  191,  596,  101,  324,
 /*   850 */    28,   57,   58,   47,  578,  577,  579,  579,   55,   55,
 /*   860 */    56,   56,   56,   56,  412,   54,   54,   54,   54,   53,
 /*   870 */    53,   52,   52,   52,   51,  240,  312,  412,  595,  415,
 /*   880 */   412,  212,  499,  278,  356,  412,  382,  330,  596,  106,
 /*   890 */   566,  238,  415,  412,  250,  415,  169,  412,  616,  616,
 /*   900 */   415,  596,  105,  132,  596,  104,  585,   48,  415,  596,
 /*   910 */    96,  439,  415,  173,  276,  595,  540,  596,  103,  131,
 /*   920 */   320,  596,   77,   27,   57,   45,   47,  578,  577,  579,
 /*   930 */   579,   55,   55,   56,   56,   56,   56,  412,   54,   54,
 /*   940 */    54,   54,   53,   53,   52,   52,   52,   51,  240,  312,
 /*   950 */   266,  221,  415,  412,  434,  234,   23,  412,   16,  377,
 /*   960 */   189,  596,   99,  464,  517,  616,  623,  333,  415,  130,
 /*   970 */   412,  361,  415,  536,  361,  584,  583,  596,  144,  585,
 /*   980 */    48,  596,  143,  284,  167,  415,  616,  373,  616,  616,
 /*   990 */    51,  240,  475,  265,  596,  142,  581,  580,   58,   47,
 /*  1000 */   578,  577,  579,  579,   55,   55,   56,   56,   56,   56,
 /*  1010 */   412,   54,   54,   54,   54,   53,   53,   52,   52,   52,
 /*  1020 */    51,  240,  312,  582,  412,  415,  412,  361,  188,  369,
 /*  1030 */   412,  128,  607,  472,  596,   76,  367,  127,  468,  415,
 /*  1040 */   263,  415,  616,  412,  536,  415,  412,  616,  596,   93,
 /*  1050 */   596,   92,  585,   48,  596,   75,  173,   15,  415,  616,
 /*  1060 */   162,  415,  460,  161,  160,  457,  226,  596,   91,  259,
 /*  1070 */   596,   90,   47,  578,  577,  579,  579,   55,   55,   56,
 /*  1080 */    56,   56,   56,  125,   54,   54,   54,   54,   53,   53,
 /*  1090 */    52,   52,   52,   51,  240,   43,  406,   25,    4,  435,
 /*  1100 */   412,  540,  416,  617,  412,  540,  124,  323,   24,   43,
 /*  1110 */   406,  606,    4,  409,   11,  415,  416,  617,    5,  415,
 /*  1120 */   352,  266,  224,  412,  596,  102,  616,  409,  596,   89,
 /*  1130 */   453,  448,  404,  115,  122,  117,  616,  605,  415,  146,
 /*  1140 */   290,  562,  451,  137,  288,  266,  404,  596,   87,  114,
 /*  1150 */   438,  266,  616,  220,  616,  562,  266,  442,  219,  411,
 /*  1160 */   616,   40,   41,  536,  449,  412,  616,   64,   42,  414,
 /*  1170 */   413,  616,  430,  590,  616,   40,   41,  412,  616,  432,
 /*  1180 */   415,  431,   42,  414,  413,  266,  430,  590,  447,  596,
 /*  1190 */    86,  218,  415,  432,  446,  431,  266,  266,  589,  445,
 /*  1200 */   616,  596,   85,  335,  588,  588,  588,  587,  586,   14,
 /*  1210 */    61,  616,  616,  616,  618,  617,  154,  244,  588,  588,
 /*  1220 */   588,  587,  586,   14,   43,  406,  318,    4,  223,  401,
 /*  1230 */   553,  416,  617,  332,  109,  421,  232,  541,  129,  222,
 /*  1240 */   251,  537,  409,  412,  616,  616,  620,   43,  406,  535,
 /*  1250 */     4,  412,  616,  562,  416,  617,  616,  610,  415,  183,
 /*  1260 */   182,  404,  280,  412,  616,  409,  415,  596,   72,  609,
 /*  1270 */   562,  418,    8,  195,  194,  596,   71,  616,  415,  412,
 /*  1280 */   505,  522,  608,  180,  404,  590,  242,  596,   84,   30,
 /*  1290 */    40,   41,  530,  562,  415,  616,  279,   42,  414,  413,
 /*  1300 */   594,  417,  590,  596,   83,  298,  396,  398,   31,  299,
 /*  1310 */   237,  616,  485,   40,   41,  273,  588,  588,  588,  297,
 /*  1320 */    42,  414,  413,   60,  271,  590,  412,  616,  296,  269,
 /*  1330 */   616,   36,  267,  588,  588,  588,  587,  586,   14,  616,
 /*  1340 */   412,  415,  175,  242,  616,   43,  406,  616,    4,  552,
 /*  1350 */   596,   82,  416,  617,  291,  415,  588,  588,  588,  587,
 /*  1360 */   586,   14,  262,  409,  596,   80,  466,  186,   33,  406,
 /*  1370 */   412,    4,  412,  459,  412,  416,  617,  616,  593,   29,
 /*  1380 */   539,  616,  404,  289,  393,  415,  409,  415,  616,  415,
 /*  1390 */   287,  562,  458,  357,  596,   70,  596,   17,  596,   79,
 /*  1400 */   342,  412,  249,  519,  533,  404,  390,  616,  616,  246,
 /*  1410 */   387,   40,   41,  245,  562,  616,  415,  616,   42,  414,
 /*  1420 */   413,  415,  532,  590,  616,  596,   78,  328,  616,  424,
 /*  1430 */   596,    9,  294,  514,   40,   41,  151,  282,  394,  513,
 /*  1440 */   510,   42,  414,  413,  616,  509,  590,  616,  293,  508,
 /*  1450 */   310,  616,  133,  616,  588,  588,  588,  587,  586,   14,
 /*  1460 */   217,  230,  490,  616,  231,  307,  306,  305,  181,  303,
 /*  1470 */   229,  484,  450,  483,  166,  482,  374,  588,  588,  588,
 /*  1480 */   587,  586,   14,  309,  476,  165,  155,  372,  248,  164,
 /*  1490 */   264,  211,  474,  370,   26,  163,  147,  247,  364,  463,
 /*  1500 */   126,  473,  138,  123,  452,  121,  348,  120,  119,  118,
 /*  1510 */   157,  444,  462,  116,  441,  135,  319,   22,  156,  317,
 /*  1520 */   427,   19,  426,  425,  422,   63,  604,  192,  569,  591,
 /*  1530 */   300,  567,  551,  405,  548,  283,  506,  292,  495,  358,
 /*  1540 */   494,  493,  491,  456,  443,  381,  258,  253,  339,  346,
 /*  1550 */   437,  436,  308,  565,  546,    7,  240,  486,  479,  261,
 /*  1560 */   347,  252,  210,  301,  371,  313,  402,  523,  521,  504,
 /*  1570 */   242,  498,  497,  952,  952,  952,  952,  952,  952,  952,
 /*  1580 */   952,  952,  952,  952,  952,  952,  952,  952,  952,  952,
 /*  1590 */   952,  952,  952,  952,  337,
};
static const YYCODETYPE yy_lookahead[] = {
 /*     0 */    19,   25,  222,  223,  224,   24,    1,   26,   76,   77,
 /*    10 */    78,   79,   80,   81,   82,   83,   84,   85,   86,   87,
 /*    20 */    88,   89,   90,   91,  115,   22,   26,   27,  248,   26,
 /*    30 */    49,   50,   76,   77,   78,   79,  127,   81,   82,   83,
 /*    40 */    84,   85,   86,   87,   88,   89,   90,   91,   67,   68,
 /*    50 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*    60 */    79,   15,   81,   82,   83,   84,   85,   86,   87,   88,
 /*    70 */    89,   90,   91,   19,   93,   16,   19,  150,  102,   25,
 /*    80 */    81,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*    90 */    91,   19,  165,   93,   94,   95,   93,   23,   98,   99,
 /*   100 */   100,  174,  175,   49,   50,  104,  105,  106,   54,  109,
 /*   110 */     7,    8,   85,   86,   87,   88,   89,   90,   91,   60,
 /*   120 */    61,   67,   68,   69,   70,   71,   72,   73,   74,   75,
 /*   130 */    76,   77,   78,   79,   22,   81,   82,   83,   84,   85,
 /*   140 */    86,   87,   88,   89,   90,   91,   19,  111,   91,  113,
 /*   150 */   114,   24,   95,   96,   97,   98,   99,  100,  101,   65,
 /*   160 */   150,   25,  235,   91,  150,  108,   96,   97,   96,   97,
 /*   170 */    98,   99,  100,  101,  112,  165,   49,   50,   95,  165,
 /*   180 */   108,   98,   99,  100,  174,  175,  197,   93,  174,  175,
 /*   190 */    22,   97,  109,  204,   67,   68,   69,   70,   71,   72,
 /*   200 */    73,   74,   75,   76,   77,   78,   79,   11,   81,   82,
 /*   210 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   19,
 /*   220 */    22,  117,  128,  129,  130,  215,   97,  150,  214,  215,
 /*   230 */   166,   95,  146,  147,   98,   99,  100,  108,  152,  150,
 /*   240 */   154,  150,  165,   75,  112,  109,  160,  117,  116,   49,
 /*   250 */    50,  174,  175,   57,  165,  163,  165,   22,  166,  167,
 /*   260 */   168,   26,   27,  174,  175,  174,  175,   67,   68,   69,
 /*   270 */    70,   71,   72,   73,   74,   75,   76,   77,   78,   79,
 /*   280 */   194,   81,   82,   83,   84,   85,   86,   87,   88,   89,
 /*   290 */    90,   91,   19,  216,  117,  150,  232,  233,  221,   30,
 /*   300 */   104,  105,  106,   34,  218,  216,  161,  162,  117,  150,
 /*   310 */   165,  115,  150,   25,  228,  155,   22,   48,  120,  160,
 /*   320 */    26,   27,   49,   50,  165,  234,  235,  165,   93,   94,
 /*   330 */   185,  186,  117,  174,  175,  135,  174,  175,   26,   27,
 /*   340 */    67,   68,   69,   70,   71,   72,   73,   74,   75,   76,
 /*   350 */    77,   78,   79,  194,   81,   82,   83,   84,   85,   86,
 /*   360 */    87,   88,   89,   90,   91,   19,  150,  128,  129,   23,
 /*   370 */     7,    8,    9,   26,   27,  216,  160,   12,  216,   22,
 /*   380 */   221,  165,   94,  221,   26,   27,   26,   93,   94,  229,
 /*   390 */   174,  175,  160,   28,   50,   49,   50,  150,  238,   87,
 /*   400 */    87,   88,   89,   90,   91,   93,   94,  119,  135,   44,
 /*   410 */   194,   46,  165,   67,   68,   69,   70,   71,   72,   73,
 /*   420 */    74,   75,   76,   77,   78,   79,  194,   81,   82,   83,
 /*   430 */    84,   85,   86,   87,   88,   89,   90,   91,   19,   23,
 /*   440 */    93,   94,   23,   23,   23,   25,  150,  103,   23,  150,
 /*   450 */   218,   93,   94,   93,  158,  150,   22,  161,  162,   23,
 /*   460 */   150,  165,   23,   11,  165,   23,  119,   25,   49,   50,
 /*   470 */   165,  239,   57,  174,  175,  165,  244,  119,   16,  174,
 /*   480 */   175,   26,   27,  160,  174,  175,   67,   68,   69,   70,
 /*   490 */    71,   72,   73,   74,   75,   76,   77,   78,   79,   22,
 /*   500 */    81,   82,   83,   84,   85,   86,   87,   88,   89,   90,
 /*   510 */    91,   19,   23,   12,   23,   23,   25,  194,   32,  104,
 /*   520 */   105,  106,   60,   61,  225,  150,  216,   41,   23,   28,
 /*   530 */   115,   25,  111,  166,  113,  114,  111,   25,  113,  114,
 /*   540 */   165,   49,   50,  220,   24,   44,   26,   46,   93,   94,
 /*   550 */   111,   23,  113,  114,  169,  170,  171,   23,   57,   67,
 /*   560 */    68,   69,   70,   71,   72,   73,   74,   75,   76,   77,
 /*   570 */    78,   79,  205,   81,   82,   83,   84,   85,   86,   87,
 /*   580 */    88,   89,   90,   91,   19,   94,   19,   25,   23,  222,
 /*   590 */   223,  224,  217,  169,  170,  171,   36,  150,  165,  137,
 /*   600 */   111,   35,  113,  114,    0,    1,    2,  174,  161,  162,
 /*   610 */   119,   51,  165,   93,   49,   50,   21,   50,   58,  181,
 /*   620 */   182,  236,  222,  223,  224,  160,  188,  142,  143,  144,
 /*   630 */   145,  125,   67,   68,   69,   70,   71,   72,   73,   74,
 /*   640 */    75,   76,   77,   78,   79,   25,   81,   82,   83,   84,
 /*   650 */    85,   86,   87,   88,   89,   90,   91,   19,  150,  194,
 /*   660 */   236,  150,   24,  144,  145,  150,   87,  107,   35,  160,
 /*   670 */   103,  206,  207,  165,  119,  108,  165,  104,  105,  106,
 /*   680 */   165,   23,   22,   25,  160,  174,  175,   49,   50,  174,
 /*   690 */   175,  112,  190,  191,   99,  116,  166,  167,  168,   35,
 /*   700 */    23,  193,   25,  194,  160,   67,   68,   69,   70,   71,
 /*   710 */    72,   73,   74,   75,   76,   77,   78,   79,  194,   81,
 /*   720 */    82,   83,   84,   85,   86,   87,   88,   89,   90,   91,
 /*   730 */    19,  150,  137,  150,  150,   96,  150,  173,  194,   23,
 /*   740 */    22,   25,  218,  172,  173,  181,  165,  150,  165,  165,
 /*   750 */   150,  165,  181,   25,  115,  174,  175,  249,  174,  175,
 /*   760 */    49,   50,  165,   52,  220,  165,  127,   23,  244,   25,
 /*   770 */   187,  174,  175,  187,  174,  175,  206,  207,   67,   68,
 /*   780 */    69,   70,   71,   72,   73,   74,   75,   76,   77,   78,
 /*   790 */    79,  150,   81,   82,   83,   84,   85,   86,   87,   88,
 /*   800 */    89,   90,   91,   19,  150,  150,  165,  150,   23,   19,
 /*   810 */    25,  150,  150,   19,  117,  174,  175,   27,   27,  165,
 /*   820 */   165,   27,  165,  150,  150,   23,  165,  165,  174,  175,
 /*   830 */   112,  174,  175,   49,   50,  174,  175,   23,  165,  165,
 /*   840 */    39,  134,  187,  136,  160,   52,  118,  174,  175,  187,
 /*   850 */    22,   67,   68,   69,   70,   71,   72,   73,   74,   75,
 /*   860 */    76,   77,   78,   79,  150,   81,   82,   83,   84,   85,
 /*   870 */    86,   87,   88,   89,   90,   91,   19,  150,  194,  165,
 /*   880 */   150,  160,   29,  150,  150,  150,   52,  213,  174,  175,
 /*   890 */    85,   86,  165,  150,   23,  165,   25,  150,  165,  165,
 /*   900 */   165,  174,  175,   22,  174,  175,   49,   50,  165,  174,
 /*   910 */   175,   23,  165,   25,   23,  194,  166,  174,  175,   22,
 /*   920 */   187,  174,  175,   22,   67,   68,   69,   70,   71,   72,
 /*   930 */    73,   74,   75,   76,   77,   78,   79,  150,   81,   82,
 /*   940 */    83,   84,   85,   86,   87,   88,   89,   90,   91,   19,
 /*   950 */   150,  217,  165,  150,   23,  205,   25,  150,   22,   52,
 /*   960 */    24,  174,  175,  190,  191,  165,    1,    2,  165,   22,
 /*   970 */   150,  150,  165,  150,  150,   49,   50,  174,  175,   49,
 /*   980 */    50,  174,  175,  108,  101,  165,  165,   19,  165,  165,
 /*   990 */    90,   91,   20,  193,  174,  175,   70,   71,   68,   69,
 /*  1000 */    70,   71,   72,   73,   74,   75,   76,   77,   78,   79,
 /*  1010 */   150,   81,   82,   83,   84,   85,   86,   87,   88,   89,
 /*  1020 */    90,   91,   19,   97,  150,  165,  150,  150,   24,   43,
 /*  1030 */   150,  103,  150,   59,  174,  175,  213,   53,   53,  165,
 /*  1040 */   137,  165,  165,  150,  150,  165,  150,  165,  174,  175,
 /*  1050 */   174,  175,   49,   50,  174,  175,   25,    5,  165,  165,
 /*  1060 */   103,  165,    1,  117,   35,   27,  245,  174,  175,  245,
 /*  1070 */   174,  175,   69,   70,   71,   72,   73,   74,   75,   76,
 /*  1080 */    77,   78,   79,  107,   81,   82,   83,   84,   85,   86,
 /*  1090 */    87,   88,   89,   90,   91,   19,   20,   75,   22,   23,
 /*  1100 */   150,  166,   26,   27,  150,  166,  126,  213,   75,   19,
 /*  1110 */    20,  150,   22,   37,   22,  165,   26,   27,   22,  165,
 /*  1120 */    25,  150,  245,  150,  174,  175,  165,   37,  174,  175,
 /*  1130 */    23,   20,   56,  107,  118,  118,  165,  150,  165,  150,
 /*  1140 */   205,   65,    1,   22,  205,  150,   56,  174,  175,  126,
 /*  1150 */    23,  150,  165,   25,  165,   65,  150,  127,   75,  150,
 /*  1160 */   165,   85,   86,  150,  193,  150,  165,   16,   92,   93,
 /*  1170 */    94,  165,   96,   97,  165,   85,   86,  150,  165,  103,
 /*  1180 */   165,  105,   92,   93,   94,  150,   96,   97,  193,  174,
 /*  1190 */   175,   75,  165,  103,  193,  105,  150,  150,  150,  193,
 /*  1200 */   165,  174,  175,   64,  128,  129,  130,  131,  132,  133,
 /*  1210 */    22,  165,  165,  165,   26,   27,   15,  140,  128,  129,
 /*  1220 */   130,  131,  132,  133,   19,   20,  213,   22,  193,  150,
 /*  1230 */   150,   26,   27,    3,  164,    4,  180,  150,  180,  193,
 /*  1240 */   193,  150,   37,  150,  165,  165,  149,   19,   20,  150,
 /*  1250 */    22,  150,  165,   65,   26,   27,  165,  149,  165,    6,
 /*  1260 */   151,   56,  150,  150,  165,   37,  165,  174,  175,  149,
 /*  1270 */    65,  149,   25,   85,   86,  174,  175,  165,  165,  150,
 /*  1280 */   150,   93,   13,  151,   56,   97,  115,  174,  175,  125,
 /*  1290 */    85,   86,   87,   65,  165,  165,  150,   92,   93,   94,
 /*  1300 */   194,  159,   97,  174,  175,  200,  122,  121,  123,  199,
 /*  1310 */   226,  165,  150,   85,   86,  150,  128,  129,  130,  201,
 /*  1320 */    92,   93,   94,  124,  150,   97,  150,  165,  202,  150,
 /*  1330 */   165,  134,  150,  128,  129,  130,  131,  132,  133,  165,
 /*  1340 */   150,  165,  117,  115,  165,   19,   20,  165,   22,  157,
 /*  1350 */   174,  175,   26,   27,  210,  165,  128,  129,  130,  131,
 /*  1360 */   132,  133,  150,   37,  174,  175,  150,  157,   19,   20,
 /*  1370 */   150,   22,  150,  150,  150,   26,   27,  165,  203,  103,
 /*  1380 */   211,  165,   56,  210,  120,  165,   37,  165,  165,  165,
 /*  1390 */   210,   65,  150,  150,  174,  175,  174,  175,  174,  175,
 /*  1400 */   150,  150,  150,  176,  211,   56,  150,  165,  165,  150,
 /*  1410 */   103,   85,   86,  150,   65,  165,  165,  165,   92,   93,
 /*  1420 */    94,  165,  211,   97,  165,  174,  175,   47,  165,  150,
 /*  1430 */   174,  175,  150,  176,   85,   86,  150,  176,  150,  184,
 /*  1440 */   178,   92,   93,   94,  165,  102,   97,  165,  150,  176,
 /*  1450 */   179,  165,   22,  165,  128,  129,  130,  131,  132,  133,
 /*  1460 */     5,   91,  184,  165,  231,   10,   11,   12,   13,   14,
 /*  1470 */   231,  176,   17,  176,  156,  176,   18,  128,  129,  130,
 /*  1480 */   131,  132,  133,  179,  157,  156,   31,  157,   33,  156,
 /*  1490 */   242,  157,  157,   45,  134,  156,   67,   42,  157,  189,
 /*  1500 */   189,  243,  219,   22,  199,  192,   18,  192,  192,  192,
 /*  1510 */    55,  199,   57,  189,  230,  219,  138,  247,   63,  157,
 /*  1520 */    40,  247,  157,  157,   38,  250,  153,  196,  237,  166,
 /*  1530 */   198,  237,  177,  227,  177,  177,  182,  209,  177,  246,
 /*  1540 */   166,  177,  166,  199,  199,  178,  246,  209,  166,  209,
 /*  1550 */   166,  166,  148,  166,  208,  196,   91,  186,  186,  104,
 /*  1560 */   105,  106,  240,  195,  241,  110,  191,  174,  174,  183,
 /*  1570 */   115,  183,  183,  251,  251,  251,  251,  251,  251,  251,
 /*  1580 */   251,  251,  251,  251,  251,  251,  251,  251,  251,  251,
 /*  1590 */   251,  251,  251,  251,  139,
};
#define YY_SHIFT_USE_DFLT (-92)
#define YY_SHIFT_COUNT (419)
#define YY_SHIFT_MIN   (-91)
#define YY_SHIFT_MAX   (1488)
static const short yy_shift_ofst[] = {
 /*     0 */   965, 1228, 1455, 1076, 1228, 1326, 1326, 1326,    0,  -19,
 /*    10 */  1090, 1326, 1326, 1326, 1326,  415,  455,  711, 1205, 1326,
 /*    20 */  1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326,
 /*    30 */  1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326,
 /*    40 */  1326, 1326, 1326, 1326, 1326, 1326, 1326, 1349, 1326, 1326,
 /*    50 */  1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326, 1326,
 /*    60 */  1326, 1326,  196,  455,  455,  805,  805,  360, 1171,   54,
 /*    70 */   638,  565,  492,  419,  346,  273,  200,  127,  784,  784,
 /*    80 */   784,  784,  784,  784,  784,  784,  784,  784,  784,  784,
 /*    90 */   784,  784,  784,  784,  784,  784,  857,  784,  930, 1003,
 /*   100 */  1003,  -68,  -44,  -44,  -44,  -44,  -44,  -44,   -1,   57,
 /*   110 */    27,  313,  455,  455,  455,  455,  455,  455,  455,  455,
 /*   120 */   455,  455,  455,  455,  455,  455,  455,  455,  455,  567,
 /*   130 */   455,  455,  455,  455,  455,  639,  595,  360,  -91,  360,
 /*   140 */   900, 1465,  -92,  -92,  -92, 1188,   72,  501,  501,  312,
 /*   150 */   294,  358,  347,  235,  455,  455,  455,  455,  455,  455,
 /*   160 */   455,  455,  455,  455,  455,  455,  455,  455,  455,  455,
 /*   170 */   455,  455,  455,  455,  455,  455,  455,  455,  455,  455,
 /*   180 */   455,  455,  455,  455,  520,  520,  520,  604, 1171, 1171,
 /*   190 */  1171,  -92,  -92,  136,   94,   94,   83,  560,  560,  560,
 /*   200 */   491,  489,  365,  439,  425,  421,   36,   36,   36,   36,
 /*   210 */   573,  269,   36,   36,  288,    3,  579,  363,  360,  360,
 /*   220 */   360,  506,  790,  790,  794,  506,  794,  -24,  360,  486,
 /*   230 */   360,  486,  344,  486,  790,  486,  486,  707,  239,  239,
 /*   240 */   360,  728,  132,  936, 1486, 1225, 1225, 1480, 1480, 1225,
 /*   250 */  1378, 1481, 1429, 1164, 1488, 1488, 1488, 1488, 1164, 1481,
 /*   260 */  1429, 1429, 1225, 1458, 1360, 1448, 1225, 1225, 1458, 1225,
 /*   270 */  1458, 1225, 1458, 1430, 1307, 1307, 1307, 1380, 1370, 1370,
 /*   280 */  1430, 1307, 1343, 1307, 1380, 1307, 1307, 1264, 1276, 1264,
 /*   290 */  1276, 1264, 1276, 1225, 1225, 1197, 1199, 1186, 1185, 1184,
 /*   300 */  1164, 1171, 1247, 1269, 1269, 1253, 1253, 1253, 1253,  -92,
 /*   310 */   -92,  -92,  926,  462,   59,    1,  931,  168,  888,  718,
 /*   320 */   871,  198,  785,  744,  716,  677,  658,   70,  103,  129,
 /*   330 */   442,  420, 1231, 1230, 1077, 1201, 1139, 1151, 1116, 1083,
 /*   340 */  1128, 1127, 1121, 1030, 1095, 1023, 1026, 1017, 1111, 1141,
 /*   350 */  1016, 1107, 1096, 1095, 1092,  980, 1033, 1022,  976, 1038,
 /*   360 */  1029,  946, 1061, 1052,  957,  903,  985, 1031,  984,  974,
 /*   370 */   986,  928, 1004,  972,  968,  875,  883,  947,  907,  901,
 /*   380 */   897,  891,  881,  834,  853,  828,  793,  801,  814,  802,
 /*   390 */   697,  791,  664,  660,  555,  562,  633,  620,  566,  562,
 /*   400 */   534,  528,  512,  505,  477,  452,  434,  436,  416,  357,
 /*   410 */    62,  215,  191,  177,  130,  104,  112,   74,   46,    5,
};
#define YY_REDUCE_USE_DFLT (-221)
#define YY_REDUCE_COUNT (311)
#define YY_REDUCE_MIN   (-220)
#define YY_REDUCE_MAX   (1404)
static const short yy_reduce_ofst[] = {
 /*     0 */   485,  159,   86,   91,  216,  162,   14,   77,  145,  367,
 /*    10 */   -73,  310,   89,   10,  299,  232,  296, -220, 1256, 1251,
 /*    20 */  1224, 1222, 1220, 1190, 1176, 1129, 1113, 1101, 1093, 1027,
 /*    30 */  1015,  973,  954,  950,  896,  893,  880,  876,  874,  860,
 /*    40 */   820,  807,  803,  787,  747,  743,  735,  730,  727,  714,
 /*    50 */   673,  661,  657,  654,  641,  600,  597,  584,  581,  515,
 /*    60 */   511,  305,  524,  447,  508,  424,  385,   92,  465,  400,
 /*    70 */   400,  400,  400,  400,  400,  400,  400,  400,  400,  400,
 /*    80 */   400,  400,  400,  400,  400,  400,  400,  400,  400,  400,
 /*    90 */   400,  400,  400,  400,  400,  400,  400,  400,  400,  400,
 /*   100 */   400,  400,  400,  400,  400,  400,  400,  400,  400,  571,
 /*   110 */   400,  400, 1013,  733, 1047,  734, 1046, 1035, 1006, 1001,
 /*   120 */   995,  971,  877,  894,  824,  375,  821,  823,  800,  438,
 /*   130 */   662,  655,  586,  583,  674,  544,  160,   64,  323,  530,
 /*   140 */   400,  400,  400,  400,  400,  433,  564,  773,  502, 1009,
 /*   150 */  1298, 1288, 1286, 1282, 1279, 1263, 1259, 1252, 1250, 1243,
 /*   160 */  1242, 1223, 1216, 1212, 1182, 1179, 1174, 1165, 1162, 1146,
 /*   170 */  1130, 1112, 1099, 1091, 1087, 1080, 1079, 1048, 1009,  989,
 /*   180 */   987,  961,  882,  247,  939,  935,  750,  519,  721,  684,
 /*   190 */   509,  570,  -11, 1372, 1394, 1393, 1371, 1389, 1388, 1386,
 /*   200 */  1346, 1368, 1375, 1368, 1368, 1368, 1368, 1368, 1368, 1368,
 /*   210 */  1323, 1322, 1368, 1368, 1346, 1387, 1359, 1404, 1385, 1384,
 /*   220 */  1382, 1345, 1340, 1338, 1300, 1344, 1293, 1367, 1376, 1364,
 /*   230 */  1374, 1361, 1354, 1358, 1328, 1357, 1355, 1306, 1294, 1291,
 /*   240 */  1363, 1332, 1331, 1373, 1275, 1366, 1365, 1274, 1270, 1362,
 /*   250 */  1284, 1296, 1324, 1312, 1317, 1316, 1315, 1313, 1305, 1283,
 /*   260 */  1311, 1310, 1341, 1339, 1258, 1248, 1335, 1334, 1333, 1330,
 /*   270 */  1329, 1327, 1318, 1304, 1299, 1297, 1295, 1278, 1239, 1233,
 /*   280 */  1271, 1273, 1262, 1261, 1255, 1257, 1227, 1211, 1180, 1193,
 /*   290 */  1173, 1169, 1144, 1210, 1192, 1084, 1175, 1126, 1118, 1105,
 /*   300 */  1110, 1106, 1142, 1132, 1109, 1122, 1120, 1108, 1097, 1058,
 /*   310 */  1056, 1070,
};
static const YYACTIONTYPE yy_default[] = {
 /*     0 */   630,  865,  950,  950,  950,  865,  950,  865,  950,  754,
 /*    10 */   950,  950,  950,  950,  863,  950,  950,  937,  950,  950,
 /*    20 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*    30 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*    40 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*    50 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*    60 */   950,  950,  950,  950,  950,  903,  903,  669,  758,  789,
 /*    70 */   950,  950,  950,  950,  950,  950,  950,  950,  936,  938,
 /*    80 */   894,  895,  797,  796,  916,  769,  794,  787,  780,  791,
 /*    90 */   866,  859,  860,  858,  862,  867,  950,  790,  826,  843,
 /*   100 */   825,  836,  842,  849,  841,  838,  837,  828,  827,  661,
 /*   110 */   829,  830,  950,  950,  950,  950,  950,  950,  950,  950,
 /*   120 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  723,
 /*   130 */   950,  950,  950,  950,  950,  950,  656,  880,  950,  950,
 /*   140 */   831,  832,  846,  845,  844,  950,  950,  950,  950,  950,
 /*   150 */   950,  950,  950,  950,  950,  943,  941,  950,  950,  950,
 /*   160 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*   170 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*   180 */   950,  950,  950,  636,  754,  754,  754,  630,  950,  950,
 /*   190 */   950,  758,  748,  714,  950,  950,  950,  950,  950,  950,
 /*   200 */   950,  950,  950,  950,  950,  950,  799,  737,  926,  928,
 /*   210 */   950,  909,  735,  658,  756,  671,  746,  638,  950,  950,
 /*   220 */   950,  793,  771,  771,  921,  793,  921,  695,  950,  783,
 /*   230 */   950,  783,  692,  783,  771,  783,  783,  861,  950,  950,
 /*   240 */   950,  755,  746,  950,  948,  762,  762,  940,  940,  762,
 /*   250 */   885,  805,  727,  793,  734,  734,  734,  734,  793,  805,
 /*   260 */   727,  727,  762,  653,  915,  913,  762,  762,  653,  762,
 /*   270 */   653,  762,  653,  872,  725,  725,  725,  710,  876,  876,
 /*   280 */   872,  725,  695,  725,  710,  725,  725,  775,  770,  775,
 /*   290 */   770,  775,  770,  762,  762,  950,  788,  776,  786,  784,
 /*   300 */   793,  950,  713,  646,  646,  635,  635,  635,  635,  697,
 /*   310 */   697,  679,  950,  950,  950,  950,  950,  889,  950,  950,
 /*   320 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*   330 */   950,  950,  950,  631,  950,  950,  947,  950,  884,  882,
 /*   340 */   879,  950,  950,  950,  798,  950,  950,  950,  950,  950,
 /*   350 */   950,  950,  950,  925,  950,  950,  950,  950,  950,  950,
 /*   360 */   950,  919,  950,  950,  950,  950,  950,  912,  911,  950,
 /*   370 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*   380 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*   390 */   950,  950,  950,  950,  950,  785,  950,  777,  950,  864,
 /*   400 */   950,  950,  950,  950,  950,  950,  950,  950,  950,  950,
 /*   410 */   740,  814,  950,  813,  817,  812,  663,  950,  644,  950,
 /*   420 */   627,  632,  949,  946,  945,  944,  942,  939,  935,  892,
 /*   430 */   898,  897,  896,  893,  891,  890,  883,  881,  878,  887,
 /*   440 */   886,  869,  800,  795,  792,  934,  888,  736,  733,  732,
 /*   450 */   652,  918,  927,  804,  803,  806,  924,  923,  922,  920,
 /*   460 */   917,  904,  802,  801,  728,  870,  868,  655,  908,  907,
 /*   470 */   906,  910,  914,  905,  764,  654,  651,  660,  717,  716,
 /*   480 */   724,  722,  721,  720,  719,  718,  715,  662,  670,  681,
 /*   490 */   709,  694,  693,  875,  877,  874,  873,  702,  701,  707,
 /*   500 */   706,  705,  704,  703,  700,  699,  698,  691,  690,  696,
 /*   510 */   689,  712,  711,  708,  688,  731,  730,  729,  726,  687,
 /*   520 */   686,  685,  817,  684,  683,  823,  822,  810,  853,  751,
 /*   530 */   750,  749,  761,  760,  773,  772,  808,  807,  774,  759,
 /*   540 */   753,  752,  768,  767,  766,  765,  757,  747,  779,  782,
 /*   550 */   781,  778,  855,  763,  852,  933,  932,  931,  930,  929,
 /*   560 */   857,  856,  824,  821,  674,  675,  902,  900,  901,  899,
 /*   570 */   677,  676,  673,  672,  854,  742,  741,  850,  847,  839,
 /*   580 */   851,  848,  840,  835,  834,  833,  819,  818,  816,  815,
 /*   590 */   811,  820,  665,  743,  739,  738,  809,  745,  744,  682,
 /*   600 */   680,  678,  659,  657,  650,  648,  647,  649,  645,  643,
 /*   610 */   642,  641,  640,  639,  668,  667,  666,  664,  663,  637,
 /*   620 */   634,  633,  629,  628,  626,
};

/* The next table maps tokens into fallback tokens.  If a construct
** like the following:
** 
**      %fallback ID X Y Z.
**
** appears in the grammar, then ID becomes a fallback token for X, Y,
** and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
** but it does not parse, the type of the token is changed to ID and
** the parse is retried before an error is thrown.
*/
#ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = {
    0,  /*          $ => nothing */
    0,  /*       SEMI => nothing */
   26,  /*    EXPLAIN => ID */
   26,  /*      QUERY => ID */
   26,  /*       PLAN => ID */
   26,  /*      BEGIN => ID */
    0,  /* TRANSACTION => nothing */
   26,  /*   DEFERRED => ID */
   26,  /*  IMMEDIATE => ID */
   26,  /*  EXCLUSIVE => ID */
    0,  /*     COMMIT => nothing */
   26,  /*        END => ID */
   26,  /*   ROLLBACK => ID */
   26,  /*  SAVEPOINT => ID */
   26,  /*    RELEASE => ID */
    0,  /*         TO => nothing */
    0,  /*      TABLE => nothing */
    0,  /*     CREATE => nothing */
   26,  /*         IF => ID */
    0,  /*        NOT => nothing */
    0,  /*     EXISTS => nothing */
   26,  /*       TEMP => ID */
    0,  /*         LP => nothing */
    0,  /*         RP => nothing */
    0,  /*         AS => nothing */
    0,  /*      COMMA => nothing */
    0,  /*         ID => nothing */
    0,  /*    INDEXED => nothing */
   26,  /*      ABORT => ID */
   26,  /*     ACTION => ID */
   26,  /*      AFTER => ID */
   26,  /*    ANALYZE => ID */
   26,  /*        ASC => ID */
   26,  /*     ATTACH => ID */
   26,  /*     BEFORE => ID */
   26,  /*         BY => ID */
   26,  /*    CASCADE => ID */
   26,  /*       CAST => ID */
   26,  /*   COLUMNKW => ID */
   26,  /*   CONFLICT => ID */
   26,  /*   DATABASE => ID */
   26,  /*       DESC => ID */
   26,  /*     DETACH => ID */
   26,  /*       EACH => ID */
   26,  /*       FAIL => ID */
   26,  /*        FOR => ID */
   26,  /*     IGNORE => ID */
   26,  /*  INITIALLY => ID */
   26,  /*    INSTEAD => ID */
   26,  /*    LIKE_KW => ID */
   26,  /*      MATCH => ID */
   26,  /*         NO => ID */
   26,  /*        KEY => ID */
   26,  /*         OF => ID */
   26,  /*     OFFSET => ID */
   26,  /*     PRAGMA => ID */
   26,  /*      RAISE => ID */
   26,  /*    REPLACE => ID */
   26,  /*   RESTRICT => ID */
   26,  /*        ROW => ID */
   26,  /*    TRIGGER => ID */
   26,  /*       VIEW => ID */
   26,  /*    VIRTUAL => ID */
   26,  /*    REINDEX => ID */
   26,  /*     RENAME => ID */
   26,  /*   CTIME_KW => ID */
};
#endif /* YYFALLBACK */

/* The following structure represents a single element of the
** parser's stack.  Information stored includes:
**
**   +  The state number for the parser at this level of the stack.
**
**   +  The value of the token stored at this level of the stack.
**      (In other words, the "major" token.)
**
**   +  The semantic value stored at this level of the stack.  This is
**      the information used by the action routines in the grammar.
**      It is sometimes called the "minor" token.
*/
struct yyStackEntry {
  YYACTIONTYPE stateno;  /* The state-number */
  YYCODETYPE major;      /* The major token value.  This is the code
                         ** number for the token at this stack level */
  YYMINORTYPE minor;     /* The user-supplied minor token value.  This
                         ** is the value of the token  */
};
typedef struct yyStackEntry yyStackEntry;

/* The state of the parser is completely contained in an instance of
** the following structure */
struct yyParser {
  int yyidx;                    /* Index of top element in stack */
#ifdef YYTRACKMAXSTACKDEPTH
  int yyidxMax;                 /* Maximum value of yyidx */
#endif
  int yyerrcnt;                 /* Shifts left before out of the error */
  sqlite4ParserARG_SDECL                /* A place to hold %extra_argument */
#if YYSTACKDEPTH<=0
  int yystksz;                  /* Current side of the stack */
  yyStackEntry *yystack;        /* The parser's stack */
#else
  yyStackEntry yystack[YYSTACKDEPTH];  /* The parser's stack */
#endif
  void *pEnv;                   /* Malloc context */
};
typedef struct yyParser yyParser;

#ifndef NDEBUG
/* #include <stdio.h> */
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */

#ifndef NDEBUG
/* 
** Turn parser tracing on by giving a stream to which to write the trace
** and a prompt to preface each trace message.  Tracing is turned off
** by making either argument NULL 
**
** Inputs:
** <ul>
** <li> A FILE* to which trace output should be written.
**      If NULL, then tracing is turned off.
** <li> A prefix string written at the beginning of every
**      line of trace output.  If NULL, then tracing is
**      turned off.
** </ul>
**
** Outputs:
** None.
*/
SQLITE4_PRIVATE void sqlite4ParserTrace(FILE *TraceFILE, char *zTracePrompt){
  yyTraceFILE = TraceFILE;
  yyTracePrompt = zTracePrompt;
  if( yyTraceFILE==0 ) yyTracePrompt = 0;
  else if( yyTracePrompt==0 ) yyTraceFILE = 0;
}
#endif /* NDEBUG */

#ifndef NDEBUG
/* For tracing shifts, the names of all terminals and nonterminals
** are required.  The following table supplies these names */
static const char *const yyTokenName[] = { 
  "$",             "SEMI",          "EXPLAIN",       "QUERY",       
  "PLAN",          "BEGIN",         "TRANSACTION",   "DEFERRED",    
  "IMMEDIATE",     "EXCLUSIVE",     "COMMIT",        "END",         
  "ROLLBACK",      "SAVEPOINT",     "RELEASE",       "TO",          
  "TABLE",         "CREATE",        "IF",            "NOT",         
  "EXISTS",        "TEMP",          "LP",            "RP",          
  "AS",            "COMMA",         "ID",            "INDEXED",     
  "ABORT",         "ACTION",        "AFTER",         "ANALYZE",     
  "ASC",           "ATTACH",        "BEFORE",        "BY",          
  "CASCADE",       "CAST",          "COLUMNKW",      "CONFLICT",    
  "DATABASE",      "DESC",          "DETACH",        "EACH",        
  "FAIL",          "FOR",           "IGNORE",        "INITIALLY",   
  "INSTEAD",       "LIKE_KW",       "MATCH",         "NO",          
  "KEY",           "OF",            "OFFSET",        "PRAGMA",      
  "RAISE",         "REPLACE",       "RESTRICT",      "ROW",         
  "TRIGGER",       "VIEW",          "VIRTUAL",       "REINDEX",     
  "RENAME",        "CTIME_KW",      "ANY",           "OR",          
  "AND",           "IS",            "BETWEEN",       "IN",          
  "ISNULL",        "NOTNULL",       "NE",            "EQ",          
  "GT",            "LE",            "LT",            "GE",          
  "ESCAPE",        "BITAND",        "BITOR",         "LSHIFT",      
  "RSHIFT",        "PLUS",          "MINUS",         "STAR",        
  "SLASH",         "REM",           "CONCAT",        "COLLATE",     
  "BITNOT",        "STRING",        "JOIN_KW",       "CONSTRAINT",  
  "DEFAULT",       "NULL",          "PRIMARY",       "UNIQUE",      
  "CHECK",         "REFERENCES",    "AUTOINCR",      "ON",          
  "INSERT",        "DELETE",        "UPDATE",        "SET",         
  "DEFERRABLE",    "FOREIGN",       "DROP",          "UNION",       
  "ALL",           "EXCEPT",        "INTERSECT",     "SELECT",      
  "DISTINCT",      "DOT",           "FROM",          "JOIN",        
  "USING",         "ORDER",         "GROUP",         "HAVING",      
  "LIMIT",         "WHERE",         "INTO",          "VALUES",      
  "INTEGER",       "FLOAT",         "BLOB",          "REGISTER",    
  "VARIABLE",      "CASE",          "WHEN",          "THEN",        
  "ELSE",          "INDEX",         "COVERING",      "ALTER",       
  "ADD",           "error",         "input",         "cmdlist",     
  "ecmd",          "explain",       "cmdx",          "cmd",         
  "transtype",     "trans_opt",     "nm",            "savepoint_opt",
  "create_table",  "create_table_args",  "createkw",      "temp",        
  "ifnotexists",   "dbnm",          "columnlist",    "conslist_opt",
  "select",        "column",        "columnid",      "type",        
  "carglist",      "id",            "ids",           "typetoken",   
  "typename",      "signed",        "plus_num",      "minus_num",   
  "carg",          "ccons",         "term",          "expr",        
  "onconf",        "sortorder",     "autoinc",       "idxlist_opt", 
  "refargs",       "defer_subclause",  "refarg",        "refact",      
  "init_deferred_pred_opt",  "conslist",      "tcons",         "idxlist",     
  "defer_subclause_opt",  "orconf",        "resolvetype",   "raisetype",   
  "ifexists",      "fullname",      "oneselect",     "multiselect_op",
  "distinct",      "selcollist",    "from",          "where_opt",   
  "groupby_opt",   "having_opt",    "orderby_opt",   "limit_opt",   
  "sclp",          "as",            "seltablist",    "stl_prefix",  
  "joinop",        "indexed_opt",   "on_opt",        "using_opt",   
  "joinop2",       "inscollist",    "sortlist",      "sortitem",    
  "nexprlist",     "setlist",       "insert_cmd",    "inscollist_opt",
  "valuelist",     "exprlist",      "likeop",        "between_op",  
  "in_op",         "case_operand",  "case_exprlist",  "case_else",   
  "createindex",   "uniqueflag",    "covering_opt",  "collate",     
  "uidxlist_opt",  "uidxlist",      "pragmaargs",    "pragmaarg",   
  "plus_opt",      "number",        "trigger_decl",  "trigger_cmd_list",
  "trigger_time",  "trigger_event",  "foreach_clause",  "when_clause", 
  "trigger_cmd",   "trnm",          "tridxby",       "database_kw_opt",
  "key_opt",       "add_column_fullname",  "kwcolumn_opt",
};
#endif /* NDEBUG */

#ifndef NDEBUG
/* For tracing reduce actions, the names of all rules are required.
*/
static const char *const yyRuleName[] = {
 /*   0 */ "input ::= cmdlist",
 /*   1 */ "cmdlist ::= cmdlist ecmd",
 /*   2 */ "cmdlist ::= ecmd",
 /*   3 */ "ecmd ::= SEMI",
 /*   4 */ "ecmd ::= explain cmdx SEMI",
 /*   5 */ "explain ::=",
 /*   6 */ "explain ::= EXPLAIN",
 /*   7 */ "explain ::= EXPLAIN QUERY PLAN",
 /*   8 */ "cmdx ::= cmd",
 /*   9 */ "cmd ::= BEGIN transtype trans_opt",
 /*  10 */ "trans_opt ::=",
 /*  11 */ "trans_opt ::= TRANSACTION",
 /*  12 */ "trans_opt ::= TRANSACTION nm",
 /*  13 */ "transtype ::=",
 /*  14 */ "transtype ::= DEFERRED",
 /*  15 */ "transtype ::= IMMEDIATE",
 /*  16 */ "transtype ::= EXCLUSIVE",
 /*  17 */ "cmd ::= COMMIT trans_opt",
 /*  18 */ "cmd ::= END trans_opt",
 /*  19 */ "cmd ::= ROLLBACK trans_opt",
 /*  20 */ "savepoint_opt ::= SAVEPOINT",
 /*  21 */ "savepoint_opt ::=",
 /*  22 */ "cmd ::= SAVEPOINT nm",
 /*  23 */ "cmd ::= RELEASE savepoint_opt nm",
 /*  24 */ "cmd ::= ROLLBACK trans_opt TO savepoint_opt nm",
 /*  25 */ "cmd ::= create_table create_table_args",
 /*  26 */ "create_table ::= createkw temp TABLE ifnotexists nm dbnm",
 /*  27 */ "createkw ::= CREATE",
 /*  28 */ "ifnotexists ::=",
 /*  29 */ "ifnotexists ::= IF NOT EXISTS",
 /*  30 */ "temp ::= TEMP",
 /*  31 */ "temp ::=",
 /*  32 */ "create_table_args ::= LP columnlist conslist_opt RP",
 /*  33 */ "create_table_args ::= AS select",
 /*  34 */ "columnlist ::= columnlist COMMA column",
 /*  35 */ "columnlist ::= column",
 /*  36 */ "column ::= columnid type carglist",
 /*  37 */ "columnid ::= nm",
 /*  38 */ "id ::= ID",
 /*  39 */ "id ::= INDEXED",
 /*  40 */ "ids ::= ID|STRING",
 /*  41 */ "nm ::= id",
 /*  42 */ "nm ::= STRING",
 /*  43 */ "nm ::= JOIN_KW",
 /*  44 */ "type ::=",
 /*  45 */ "type ::= typetoken",
 /*  46 */ "typetoken ::= typename",
 /*  47 */ "typetoken ::= typename LP signed RP",
 /*  48 */ "typetoken ::= typename LP signed COMMA signed RP",
 /*  49 */ "typename ::= ids",
 /*  50 */ "typename ::= typename ids",
 /*  51 */ "signed ::= plus_num",
 /*  52 */ "signed ::= minus_num",
 /*  53 */ "carglist ::= carglist carg",
 /*  54 */ "carglist ::=",
 /*  55 */ "carg ::= CONSTRAINT nm ccons",
 /*  56 */ "carg ::= ccons",
 /*  57 */ "ccons ::= DEFAULT term",
 /*  58 */ "ccons ::= DEFAULT LP expr RP",
 /*  59 */ "ccons ::= DEFAULT PLUS term",
 /*  60 */ "ccons ::= DEFAULT MINUS term",
 /*  61 */ "ccons ::= DEFAULT id",
 /*  62 */ "ccons ::= NULL onconf",
 /*  63 */ "ccons ::= NOT NULL onconf",
 /*  64 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
 /*  65 */ "ccons ::= UNIQUE onconf",
 /*  66 */ "ccons ::= CHECK LP expr RP",
 /*  67 */ "ccons ::= REFERENCES nm idxlist_opt refargs",
 /*  68 */ "ccons ::= defer_subclause",
 /*  69 */ "ccons ::= COLLATE ids",
 /*  70 */ "autoinc ::=",
 /*  71 */ "autoinc ::= AUTOINCR",
 /*  72 */ "refargs ::=",
 /*  73 */ "refargs ::= refargs refarg",
 /*  74 */ "refarg ::= MATCH nm",
 /*  75 */ "refarg ::= ON INSERT refact",
 /*  76 */ "refarg ::= ON DELETE refact",
 /*  77 */ "refarg ::= ON UPDATE refact",
 /*  78 */ "refact ::= SET NULL",
 /*  79 */ "refact ::= SET DEFAULT",
 /*  80 */ "refact ::= CASCADE",
 /*  81 */ "refact ::= RESTRICT",
 /*  82 */ "refact ::= NO ACTION",
 /*  83 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
 /*  84 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
 /*  85 */ "init_deferred_pred_opt ::=",
 /*  86 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
 /*  87 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
 /*  88 */ "conslist_opt ::=",
 /*  89 */ "conslist_opt ::= COMMA conslist",
 /*  90 */ "conslist ::= conslist COMMA tcons",
 /*  91 */ "conslist ::= conslist tcons",
 /*  92 */ "conslist ::= tcons",
 /*  93 */ "tcons ::= CONSTRAINT nm",
 /*  94 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf",
 /*  95 */ "tcons ::= UNIQUE LP idxlist RP onconf",
 /*  96 */ "tcons ::= CHECK LP expr RP onconf",
 /*  97 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt",
 /*  98 */ "defer_subclause_opt ::=",
 /*  99 */ "defer_subclause_opt ::= defer_subclause",
 /* 100 */ "onconf ::=",
 /* 101 */ "onconf ::= ON CONFLICT resolvetype",
 /* 102 */ "orconf ::=",
 /* 103 */ "orconf ::= OR resolvetype",
 /* 104 */ "resolvetype ::= raisetype",
 /* 105 */ "resolvetype ::= IGNORE",
 /* 106 */ "resolvetype ::= REPLACE",
 /* 107 */ "cmd ::= DROP TABLE ifexists fullname",
 /* 108 */ "ifexists ::= IF EXISTS",
 /* 109 */ "ifexists ::=",
 /* 110 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select",
 /* 111 */ "cmd ::= DROP VIEW ifexists fullname",
 /* 112 */ "cmd ::= select",
 /* 113 */ "select ::= oneselect",
 /* 114 */ "select ::= select multiselect_op oneselect",
 /* 115 */ "multiselect_op ::= UNION",
 /* 116 */ "multiselect_op ::= UNION ALL",
 /* 117 */ "multiselect_op ::= EXCEPT|INTERSECT",
 /* 118 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
 /* 119 */ "distinct ::= DISTINCT",
 /* 120 */ "distinct ::= ALL",
 /* 121 */ "distinct ::=",
 /* 122 */ "sclp ::= selcollist COMMA",
 /* 123 */ "sclp ::=",
 /* 124 */ "selcollist ::= sclp expr as",
 /* 125 */ "selcollist ::= sclp STAR",
 /* 126 */ "selcollist ::= sclp nm DOT STAR",
 /* 127 */ "as ::= AS nm",
 /* 128 */ "as ::= ids",
 /* 129 */ "as ::=",
 /* 130 */ "from ::=",
 /* 131 */ "from ::= FROM seltablist",
 /* 132 */ "stl_prefix ::= seltablist joinop",
 /* 133 */ "stl_prefix ::=",
 /* 134 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
 /* 135 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
 /* 136 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
 /* 137 */ "dbnm ::=",
 /* 138 */ "dbnm ::= DOT nm",
 /* 139 */ "fullname ::= nm dbnm",
 /* 140 */ "joinop ::= COMMA|JOIN",
 /* 141 */ "joinop ::= JOIN_KW JOIN",
 /* 142 */ "joinop ::= JOIN_KW nm JOIN",
 /* 143 */ "joinop ::= JOIN_KW nm nm JOIN",
 /* 144 */ "on_opt ::= ON expr",
 /* 145 */ "on_opt ::=",
 /* 146 */ "indexed_opt ::=",
 /* 147 */ "indexed_opt ::= INDEXED BY nm",
 /* 148 */ "indexed_opt ::= NOT INDEXED",
 /* 149 */ "using_opt ::= USING LP inscollist RP",
 /* 150 */ "using_opt ::=",
 /* 151 */ "orderby_opt ::=",
 /* 152 */ "orderby_opt ::= ORDER BY sortlist",
 /* 153 */ "sortlist ::= sortlist COMMA sortitem sortorder",
 /* 154 */ "sortlist ::= sortitem sortorder",
 /* 155 */ "sortitem ::= expr",
 /* 156 */ "sortorder ::= ASC",
 /* 157 */ "sortorder ::= DESC",
 /* 158 */ "sortorder ::=",
 /* 159 */ "groupby_opt ::=",
 /* 160 */ "groupby_opt ::= GROUP BY nexprlist",
 /* 161 */ "having_opt ::=",
 /* 162 */ "having_opt ::= HAVING expr",
 /* 163 */ "limit_opt ::=",
 /* 164 */ "limit_opt ::= LIMIT expr",
 /* 165 */ "limit_opt ::= LIMIT expr OFFSET expr",
 /* 166 */ "limit_opt ::= LIMIT expr COMMA expr",
 /* 167 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt",
 /* 168 */ "where_opt ::=",
 /* 169 */ "where_opt ::= WHERE expr",
 /* 170 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt",
 /* 171 */ "setlist ::= setlist COMMA nm EQ expr",
 /* 172 */ "setlist ::= nm EQ expr",
 /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist",
 /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select",
 /* 175 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES",
 /* 176 */ "insert_cmd ::= INSERT orconf",
 /* 177 */ "insert_cmd ::= REPLACE",
 /* 178 */ "valuelist ::= VALUES LP nexprlist RP",
 /* 179 */ "valuelist ::= valuelist COMMA LP exprlist RP",
 /* 180 */ "inscollist_opt ::=",
 /* 181 */ "inscollist_opt ::= LP inscollist RP",
 /* 182 */ "inscollist ::= inscollist COMMA nm",
 /* 183 */ "inscollist ::= nm",
 /* 184 */ "expr ::= term",
 /* 185 */ "expr ::= LP expr RP",
 /* 186 */ "term ::= NULL",
 /* 187 */ "expr ::= id",
 /* 188 */ "expr ::= JOIN_KW",
 /* 189 */ "expr ::= nm DOT nm",
 /* 190 */ "expr ::= nm DOT nm DOT nm",
 /* 191 */ "term ::= INTEGER|FLOAT|BLOB",
 /* 192 */ "term ::= STRING",
 /* 193 */ "expr ::= REGISTER",
 /* 194 */ "expr ::= VARIABLE",
 /* 195 */ "expr ::= expr COLLATE ids",
 /* 196 */ "expr ::= CAST LP expr AS typetoken RP",
 /* 197 */ "expr ::= ID LP distinct exprlist RP",
 /* 198 */ "expr ::= ID LP STAR RP",
 /* 199 */ "term ::= CTIME_KW",
 /* 200 */ "expr ::= expr AND expr",
 /* 201 */ "expr ::= expr OR expr",
 /* 202 */ "expr ::= expr LT|GT|GE|LE expr",
 /* 203 */ "expr ::= expr EQ|NE expr",
 /* 204 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
 /* 205 */ "expr ::= expr PLUS|MINUS expr",
 /* 206 */ "expr ::= expr STAR|SLASH|REM expr",
 /* 207 */ "expr ::= expr CONCAT expr",
 /* 208 */ "likeop ::= LIKE_KW",
 /* 209 */ "likeop ::= NOT LIKE_KW",
 /* 210 */ "likeop ::= NOT MATCH",
 /* 211 */ "expr ::= expr likeop expr",
 /* 212 */ "expr ::= expr likeop expr ESCAPE expr",
 /* 213 */ "expr ::= expr MATCH expr",
 /* 214 */ "expr ::= expr ISNULL|NOTNULL",
 /* 215 */ "expr ::= expr NOT NULL",
 /* 216 */ "expr ::= expr IS expr",
 /* 217 */ "expr ::= expr IS NOT expr",
 /* 218 */ "expr ::= NOT expr",
 /* 219 */ "expr ::= BITNOT expr",
 /* 220 */ "expr ::= MINUS expr",
 /* 221 */ "expr ::= PLUS expr",
 /* 222 */ "between_op ::= BETWEEN",
 /* 223 */ "between_op ::= NOT BETWEEN",
 /* 224 */ "expr ::= expr between_op expr AND expr",
 /* 225 */ "in_op ::= IN",
 /* 226 */ "in_op ::= NOT IN",
 /* 227 */ "expr ::= expr in_op LP exprlist RP",
 /* 228 */ "expr ::= LP select RP",
 /* 229 */ "expr ::= expr in_op LP select RP",
 /* 230 */ "expr ::= expr in_op nm dbnm",
 /* 231 */ "expr ::= EXISTS LP select RP",
 /* 232 */ "expr ::= CASE case_operand case_exprlist case_else END",
 /* 233 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
 /* 234 */ "case_exprlist ::= WHEN expr THEN expr",
 /* 235 */ "case_else ::= ELSE expr",
 /* 236 */ "case_else ::=",
 /* 237 */ "case_operand ::= expr",
 /* 238 */ "case_operand ::=",
 /* 239 */ "exprlist ::= nexprlist",
 /* 240 */ "exprlist ::=",
 /* 241 */ "nexprlist ::= nexprlist COMMA expr",
 /* 242 */ "nexprlist ::= expr",
 /* 243 */ "createindex ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm",
 /* 244 */ "cmd ::= createindex LP idxlist RP covering_opt",
 /* 245 */ "uniqueflag ::= UNIQUE",
 /* 246 */ "uniqueflag ::=",
 /* 247 */ "idxlist_opt ::=",
 /* 248 */ "idxlist_opt ::= LP idxlist RP",
 /* 249 */ "idxlist ::= idxlist COMMA nm collate sortorder",
 /* 250 */ "idxlist ::= nm collate sortorder",
 /* 251 */ "collate ::=",
 /* 252 */ "collate ::= COLLATE ids",
 /* 253 */ "cmd ::= createindex USING nm LP uidxlist_opt RP",
 /* 254 */ "uidxlist_opt ::= uidxlist",
 /* 255 */ "uidxlist_opt ::=",
 /* 256 */ "uidxlist ::= uidxlist COMMA ids EQ ids",
 /* 257 */ "uidxlist ::= uidxlist COMMA ids",
 /* 258 */ "uidxlist ::= ids EQ ids",
 /* 259 */ "uidxlist ::= ids",
 /* 260 */ "covering_opt ::=",
 /* 261 */ "covering_opt ::= COVERING ALL",
 /* 262 */ "covering_opt ::= COVERING LP inscollist RP",
 /* 263 */ "cmd ::= DROP INDEX ifexists fullname",
 /* 264 */ "cmd ::= PRAGMA nm dbnm",
 /* 265 */ "cmd ::= PRAGMA nm dbnm LP RP",
 /* 266 */ "cmd ::= PRAGMA nm dbnm LP pragmaargs RP",
 /* 267 */ "cmd ::= PRAGMA nm dbnm EQ pragmaarg",
 /* 268 */ "pragmaargs ::= pragmaarg",
 /* 269 */ "pragmaargs ::= pragmaargs COMMA expr",
 /* 270 */ "pragmaarg ::= expr",
 /* 271 */ "pragmaarg ::= ON",
 /* 272 */ "pragmaarg ::= DELETE",
 /* 273 */ "pragmaarg ::= DEFAULT",
 /* 274 */ "plus_num ::= plus_opt number",
 /* 275 */ "minus_num ::= MINUS number",
 /* 276 */ "number ::= INTEGER|FLOAT",
 /* 277 */ "plus_opt ::= PLUS",
 /* 278 */ "plus_opt ::=",
 /* 279 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
 /* 280 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
 /* 281 */ "trigger_time ::= BEFORE",
 /* 282 */ "trigger_time ::= AFTER",
 /* 283 */ "trigger_time ::= INSTEAD OF",
 /* 284 */ "trigger_time ::=",
 /* 285 */ "trigger_event ::= DELETE|INSERT",
 /* 286 */ "trigger_event ::= UPDATE",
 /* 287 */ "trigger_event ::= UPDATE OF inscollist",
 /* 288 */ "foreach_clause ::=",
 /* 289 */ "foreach_clause ::= FOR EACH ROW",
 /* 290 */ "when_clause ::=",
 /* 291 */ "when_clause ::= WHEN expr",
 /* 292 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
 /* 293 */ "trigger_cmd_list ::= trigger_cmd SEMI",
 /* 294 */ "trnm ::= nm",
 /* 295 */ "trnm ::= nm DOT nm",
 /* 296 */ "tridxby ::=",
 /* 297 */ "tridxby ::= INDEXED BY nm",
 /* 298 */ "tridxby ::= NOT INDEXED",
 /* 299 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt",
 /* 300 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist",
 /* 301 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select",
 /* 302 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt",
 /* 303 */ "trigger_cmd ::= select",
 /* 304 */ "expr ::= RAISE LP IGNORE RP",
 /* 305 */ "expr ::= RAISE LP raisetype COMMA nm RP",
 /* 306 */ "raisetype ::= ROLLBACK",
 /* 307 */ "raisetype ::= ABORT",
 /* 308 */ "raisetype ::= FAIL",
 /* 309 */ "cmd ::= DROP TRIGGER ifexists fullname",
 /* 310 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
 /* 311 */ "cmd ::= DETACH database_kw_opt expr",
 /* 312 */ "key_opt ::=",
 /* 313 */ "key_opt ::= KEY expr",
 /* 314 */ "database_kw_opt ::= DATABASE",
 /* 315 */ "database_kw_opt ::=",
 /* 316 */ "cmd ::= REINDEX",
 /* 317 */ "cmd ::= REINDEX nm dbnm",
 /* 318 */ "cmd ::= ANALYZE",
 /* 319 */ "cmd ::= ANALYZE nm dbnm",
 /* 320 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
 /* 321 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column",
 /* 322 */ "add_column_fullname ::= fullname",
 /* 323 */ "kwcolumn_opt ::=",
 /* 324 */ "kwcolumn_opt ::= COLUMNKW",
};
#endif /* NDEBUG */


#if YYSTACKDEPTH<=0
/*
** Try to increase the size of the parser stack.
*/
static void yyGrowStack(yyParser *p){
  int newSize;
  yyStackEntry *pNew;

  newSize = p->yystksz*2 + 100;
  pNew = realloc(p->yystack, newSize*sizeof(pNew[0]));
  if( pNew ){
    p->yystack = pNew;
    p->yystksz = newSize;
#ifndef NDEBUG
    if( yyTraceFILE ){
      fprintf(yyTraceFILE,"%sStack grows to %d entries!\n",
              yyTracePrompt, p->yystksz);
    }
#endif
  }
}
#endif

/* 
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
** malloc.
**
** Inputs:
** A pointer to the function used to allocate memory.
**
** Outputs:
** A pointer to a parser.  This pointer is used in subsequent calls
** to sqlite4Parser and sqlite4ParserFree.
*/
SQLITE4_PRIVATE void *sqlite4ParserAlloc(void *(*mallocProc)(void*,size_t), void *pEnv){
  yyParser *pParser;
  pParser = (yyParser*)(*mallocProc)(pEnv, (size_t)sizeof(yyParser) );
  if( pParser ){
    pParser->yyidx = -1;
#ifdef YYTRACKMAXSTACKDEPTH
    pParser->yyidxMax = 0;
#endif
#if YYSTACKDEPTH<=0
    pParser->yystack = NULL;
    pParser->yystksz = 0;
    yyGrowStack(pParser);
#endif
    pParser->pEnv = pEnv;
  }
  return pParser;
}

/* The following function deletes the value associated with a
** symbol.  The symbol can be either a terminal or nonterminal.
** "yymajor" is the symbol code, and "yypminor" is a pointer to
** the value.
*/
static void yy_destructor(
  yyParser *yypParser,    /* The parser */
  YYCODETYPE yymajor,     /* Type code for object to destroy */
  YYMINORTYPE *yypminor   /* The object to be destroyed */
){
  sqlite4ParserARG_FETCH;
  switch( yymajor ){
    /* Here is inserted the actions which take place when a
    ** terminal or non-terminal is destroyed.  This can happen
    ** when the symbol is popped from the stack during a
    ** reduce or during error processing or when a parser is 
    ** being destroyed before it is finished parsing.
    **
    ** Note: during a reduce, the only symbols destroyed are those
    ** which appear on the RHS of the rule, but which are not used
    ** inside the C code.
    */
    case 160: /* select */
    case 194: /* oneselect */
{
sqlite4SelectDelete(pParse->db, (yypminor->yy243));
}
      break;
    case 174: /* term */
    case 175: /* expr */
{
sqlite4ExprDelete(pParse->db, (yypminor->yy190).pExpr);
}
      break;
    case 179: /* idxlist_opt */
    case 187: /* idxlist */
    case 197: /* selcollist */
    case 200: /* groupby_opt */
    case 202: /* orderby_opt */
    case 204: /* sclp */
    case 214: /* sortlist */
    case 216: /* nexprlist */
    case 217: /* setlist */
    case 221: /* exprlist */
    case 226: /* case_exprlist */
    case 232: /* uidxlist_opt */
    case 233: /* uidxlist */
    case 234: /* pragmaargs */
    case 235: /* pragmaarg */
{
sqlite4ExprListDelete(pParse->db, (yypminor->yy148));
}
      break;
    case 193: /* fullname */
    case 198: /* from */
    case 206: /* seltablist */
    case 207: /* stl_prefix */
{
sqlite4SrcListDelete(pParse->db, (yypminor->yy185));
}
      break;
    case 199: /* where_opt */
    case 201: /* having_opt */
    case 210: /* on_opt */
    case 215: /* sortitem */
    case 225: /* case_operand */
    case 227: /* case_else */
    case 243: /* when_clause */
    case 248: /* key_opt */
{
sqlite4ExprDelete(pParse->db, (yypminor->yy72));
}
      break;
    case 211: /* using_opt */
    case 213: /* inscollist */
    case 219: /* inscollist_opt */
{
sqlite4IdListDelete(pParse->db, (yypminor->yy254));
}
      break;
    case 220: /* valuelist */
{

  sqlite4ExprListDelete(pParse->db, (yypminor->yy167).pList);
  sqlite4SelectDelete(pParse->db, (yypminor->yy167).pSelect);

}
      break;
    case 228: /* createindex */
{
sqlite4SrcListDelete(pParse->db, (yypminor->yy195).pTblName);
}
      break;
    case 230: /* covering_opt */
{
sqlite4IdListDelete(pParse->db, (yypminor->yy376).pList);
}
      break;
    case 239: /* trigger_cmd_list */
    case 244: /* trigger_cmd */
{
sqlite4DeleteTriggerStep(pParse->db, (yypminor->yy145));
}
      break;
    case 241: /* trigger_event */
{
sqlite4IdListDelete(pParse->db, (yypminor->yy332).b);
}
      break;
    default:  break;   /* If no destructor action specified: do nothing */
  }
}

/*
** Pop the parser's stack once.
**
** If there is a destructor routine associated with the token which
** is popped from the stack, then call it.
**
** Return the major token number for the symbol popped.
*/
static int yy_pop_parser_stack(yyParser *pParser){
  YYCODETYPE yymajor;
  yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];

  /* There is no mechanism by which the parser stack can be popped below
  ** empty in SQLite.  */
  if( NEVER(pParser->yyidx<0) ) return 0;
#ifndef NDEBUG
  if( yyTraceFILE && pParser->yyidx>=0 ){
    fprintf(yyTraceFILE,"%sPopping %s\n",
      yyTracePrompt,
      yyTokenName[yytos->major]);
  }
#endif
  yymajor = yytos->major;
  yy_destructor(pParser, yymajor, &yytos->minor);
  pParser->yyidx--;
  return yymajor;
}

/* 
** Deallocate and destroy a parser.  Destructors are all called for
** all stack elements before shutting the parser down.
**
** Inputs:
** <ul>
** <li>  A pointer to the parser.  This should be a pointer
**       obtained from sqlite4ParserAlloc.
** <li>  A pointer to a function used to reclaim memory obtained
**       from malloc.
** </ul>
*/
SQLITE4_PRIVATE void sqlite4ParserFree(
  void *p,                      /* The parser to be deleted */
  void (*freeProc)(void*,void*) /* Function used to reclaim memory */
){
  yyParser *pParser = (yyParser*)p;
  /* In SQLite, we never try to destroy a parser that was not successfully
  ** created in the first place. */
  if( NEVER(pParser==0) ) return;
  while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
#if YYSTACKDEPTH<=0
  free(pParser->yystack);
#endif
  (*freeProc)(pParser->pEnv, (void*)pParser);
}

/*
** Return the peak depth of the stack for a parser.
*/
#ifdef YYTRACKMAXSTACKDEPTH
SQLITE4_PRIVATE int sqlite4ParserStackPeak(void *p){
  yyParser *pParser = (yyParser*)p;
  return pParser->yyidxMax;
}
#endif

/*
** Find the appropriate action for a parser given the terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead.  If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_shift_action(
  yyParser *pParser,        /* The parser */
  YYCODETYPE iLookAhead     /* The look-ahead token */
){
  int i;
  int stateno = pParser->yystack[pParser->yyidx].stateno;
 
  if( stateno>YY_SHIFT_COUNT
   || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){
    return yy_default[stateno];
  }
  assert( iLookAhead!=YYNOCODE );
  i += iLookAhead;
  if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
    if( iLookAhead>0 ){
#ifdef YYFALLBACK
      YYCODETYPE iFallback;            /* Fallback token */
      if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
             && (iFallback = yyFallback[iLookAhead])!=0 ){
#ifndef NDEBUG
        if( yyTraceFILE ){
          fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
             yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
        }
#endif
        return yy_find_shift_action(pParser, iFallback);
      }
#endif
#ifdef YYWILDCARD
      {
        int j = i - iLookAhead + YYWILDCARD;
        if( 
#if YY_SHIFT_MIN+YYWILDCARD<0
          j>=0 &&
#endif
#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
          j<YY_ACTTAB_COUNT &&
#endif
          yy_lookahead[j]==YYWILDCARD
        ){
#ifndef NDEBUG
          if( yyTraceFILE ){
            fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
               yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]);
          }
#endif /* NDEBUG */
          return yy_action[j];
        }
      }
#endif /* YYWILDCARD */
    }
    return yy_default[stateno];
  }else{
    return yy_action[i];
  }
}

/*
** Find the appropriate action for a parser given the non-terminal
** look-ahead token iLookAhead.
**
** If the look-ahead token is YYNOCODE, then check to see if the action is
** independent of the look-ahead.  If it is, return the action, otherwise
** return YY_NO_ACTION.
*/
static int yy_find_reduce_action(
  int stateno,              /* Current state number */
  YYCODETYPE iLookAhead     /* The look-ahead token */
){
  int i;
#ifdef YYERRORSYMBOL
  if( stateno>YY_REDUCE_COUNT ){
    return yy_default[stateno];
  }
#else
  assert( stateno<=YY_REDUCE_COUNT );
#endif
  i = yy_reduce_ofst[stateno];
  assert( i!=YY_REDUCE_USE_DFLT );
  assert( iLookAhead!=YYNOCODE );
  i += iLookAhead;
#ifdef YYERRORSYMBOL
  if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
    return yy_default[stateno];
  }
#else
  assert( i>=0 && i<YY_ACTTAB_COUNT );
  assert( yy_lookahead[i]==iLookAhead );
#endif
  return yy_action[i];
}

/*
** The following routine is called if the stack overflows.
*/
static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){
   sqlite4ParserARG_FETCH;
   yypParser->yyidx--;
#ifndef NDEBUG
   if( yyTraceFILE ){
     fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
   }
#endif
   while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
   /* Here code is inserted which will execute if the parser
   ** stack every overflows */

  UNUSED_PARAMETER(yypMinor); /* Silence some compiler warnings */
  sqlite4ErrorMsg(pParse, "parser stack overflow");
   sqlite4ParserARG_STORE; /* Suppress warning about unused %extra_argument var */
}

/*
** Perform a shift action.
*/
static void yy_shift(
  yyParser *yypParser,          /* The parser to be shifted */
  int yyNewState,               /* The new state to shift in */
  int yyMajor,                  /* The major token to shift in */
  YYMINORTYPE *yypMinor         /* Pointer to the minor token to shift in */
){
  yyStackEntry *yytos;
  yypParser->yyidx++;
#ifdef YYTRACKMAXSTACKDEPTH
  if( yypParser->yyidx>yypParser->yyidxMax ){
    yypParser->yyidxMax = yypParser->yyidx;
  }
#endif
#if YYSTACKDEPTH>0 
  if( yypParser->yyidx>=YYSTACKDEPTH ){
    yyStackOverflow(yypParser, yypMinor);
    return;
  }
#else
  if( yypParser->yyidx>=yypParser->yystksz ){
    yyGrowStack(yypParser);
    if( yypParser->yyidx>=yypParser->yystksz ){
      yyStackOverflow(yypParser, yypMinor);
      return;
    }
  }
#endif
  yytos = &yypParser->yystack[yypParser->yyidx];
  yytos->stateno = (YYACTIONTYPE)yyNewState;
  yytos->major = (YYCODETYPE)yyMajor;
  yytos->minor = *yypMinor;
#ifndef NDEBUG
  if( yyTraceFILE && yypParser->yyidx>0 ){
    int i;
    fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
    fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
    for(i=1; i<=yypParser->yyidx; i++)
      fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
    fprintf(yyTraceFILE,"\n");
  }
#endif
}

/* The following table contains information about every rule that
** is used during the reduce.
*/
static const struct {
  YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
  unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
} yyRuleInfo[] = {
  { 142, 1 },
  { 143, 2 },
  { 143, 1 },
  { 144, 1 },
  { 144, 3 },
  { 145, 0 },
  { 145, 1 },
  { 145, 3 },
  { 146, 1 },
  { 147, 3 },
  { 149, 0 },
  { 149, 1 },
  { 149, 2 },
  { 148, 0 },
  { 148, 1 },
  { 148, 1 },
  { 148, 1 },
  { 147, 2 },
  { 147, 2 },
  { 147, 2 },
  { 151, 1 },
  { 151, 0 },
  { 147, 2 },
  { 147, 3 },
  { 147, 5 },
  { 147, 2 },
  { 152, 6 },
  { 154, 1 },
  { 156, 0 },
  { 156, 3 },
  { 155, 1 },
  { 155, 0 },
  { 153, 4 },
  { 153, 2 },
  { 158, 3 },
  { 158, 1 },
  { 161, 3 },
  { 162, 1 },
  { 165, 1 },
  { 165, 1 },
  { 166, 1 },
  { 150, 1 },
  { 150, 1 },
  { 150, 1 },
  { 163, 0 },
  { 163, 1 },
  { 167, 1 },
  { 167, 4 },
  { 167, 6 },
  { 168, 1 },
  { 168, 2 },
  { 169, 1 },
  { 169, 1 },
  { 164, 2 },
  { 164, 0 },
  { 172, 3 },
  { 172, 1 },
  { 173, 2 },
  { 173, 4 },
  { 173, 3 },
  { 173, 3 },
  { 173, 2 },
  { 173, 2 },
  { 173, 3 },
  { 173, 5 },
  { 173, 2 },
  { 173, 4 },
  { 173, 4 },
  { 173, 1 },
  { 173, 2 },
  { 178, 0 },
  { 178, 1 },
  { 180, 0 },
  { 180, 2 },
  { 182, 2 },
  { 182, 3 },
  { 182, 3 },
  { 182, 3 },
  { 183, 2 },
  { 183, 2 },
  { 183, 1 },
  { 183, 1 },
  { 183, 2 },
  { 181, 3 },
  { 181, 2 },
  { 184, 0 },
  { 184, 2 },
  { 184, 2 },
  { 159, 0 },
  { 159, 2 },
  { 185, 3 },
  { 185, 2 },
  { 185, 1 },
  { 186, 2 },
  { 186, 7 },
  { 186, 5 },
  { 186, 5 },
  { 186, 10 },
  { 188, 0 },
  { 188, 1 },
  { 176, 0 },
  { 176, 3 },
  { 189, 0 },
  { 189, 2 },
  { 190, 1 },
  { 190, 1 },
  { 190, 1 },
  { 147, 4 },
  { 192, 2 },
  { 192, 0 },
  { 147, 8 },
  { 147, 4 },
  { 147, 1 },
  { 160, 1 },
  { 160, 3 },
  { 195, 1 },
  { 195, 2 },
  { 195, 1 },
  { 194, 9 },
  { 196, 1 },
  { 196, 1 },
  { 196, 0 },
  { 204, 2 },
  { 204, 0 },
  { 197, 3 },
  { 197, 2 },
  { 197, 4 },
  { 205, 2 },
  { 205, 1 },
  { 205, 0 },
  { 198, 0 },
  { 198, 2 },
  { 207, 2 },
  { 207, 0 },
  { 206, 7 },
  { 206, 7 },
  { 206, 7 },
  { 157, 0 },
  { 157, 2 },
  { 193, 2 },
  { 208, 1 },
  { 208, 2 },
  { 208, 3 },
  { 208, 4 },
  { 210, 2 },
  { 210, 0 },
  { 209, 0 },
  { 209, 3 },
  { 209, 2 },
  { 211, 4 },
  { 211, 0 },
  { 202, 0 },
  { 202, 3 },
  { 214, 4 },
  { 214, 2 },
  { 215, 1 },
  { 177, 1 },
  { 177, 1 },
  { 177, 0 },
  { 200, 0 },
  { 200, 3 },
  { 201, 0 },
  { 201, 2 },
  { 203, 0 },
  { 203, 2 },
  { 203, 4 },
  { 203, 4 },
  { 147, 5 },
  { 199, 0 },
  { 199, 2 },
  { 147, 7 },
  { 217, 5 },
  { 217, 3 },
  { 147, 5 },
  { 147, 5 },
  { 147, 6 },
  { 218, 2 },
  { 218, 1 },
  { 220, 4 },
  { 220, 5 },
  { 219, 0 },
  { 219, 3 },
  { 213, 3 },
  { 213, 1 },
  { 175, 1 },
  { 175, 3 },
  { 174, 1 },
  { 175, 1 },
  { 175, 1 },
  { 175, 3 },
  { 175, 5 },
  { 174, 1 },
  { 174, 1 },
  { 175, 1 },
  { 175, 1 },
  { 175, 3 },
  { 175, 6 },
  { 175, 5 },
  { 175, 4 },
  { 174, 1 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 175, 3 },
  { 222, 1 },
  { 222, 2 },
  { 222, 2 },
  { 175, 3 },
  { 175, 5 },
  { 175, 3 },
  { 175, 2 },
  { 175, 3 },
  { 175, 3 },
  { 175, 4 },
  { 175, 2 },
  { 175, 2 },
  { 175, 2 },
  { 175, 2 },
  { 223, 1 },
  { 223, 2 },
  { 175, 5 },
  { 224, 1 },
  { 224, 2 },
  { 175, 5 },
  { 175, 3 },
  { 175, 5 },
  { 175, 4 },
  { 175, 4 },
  { 175, 5 },
  { 226, 5 },
  { 226, 4 },
  { 227, 2 },
  { 227, 0 },
  { 225, 1 },
  { 225, 0 },
  { 221, 1 },
  { 221, 0 },
  { 216, 3 },
  { 216, 1 },
  { 228, 8 },
  { 147, 5 },
  { 229, 1 },
  { 229, 0 },
  { 179, 0 },
  { 179, 3 },
  { 187, 5 },
  { 187, 3 },
  { 231, 0 },
  { 231, 2 },
  { 147, 6 },
  { 232, 1 },
  { 232, 0 },
  { 233, 5 },
  { 233, 3 },
  { 233, 3 },
  { 233, 1 },
  { 230, 0 },
  { 230, 2 },
  { 230, 4 },
  { 147, 4 },
  { 147, 3 },
  { 147, 5 },
  { 147, 6 },
  { 147, 5 },
  { 234, 1 },
  { 234, 3 },
  { 235, 1 },
  { 235, 1 },
  { 235, 1 },
  { 235, 1 },
  { 170, 2 },
  { 171, 2 },
  { 237, 1 },
  { 236, 1 },
  { 236, 0 },
  { 147, 5 },
  { 238, 11 },
  { 240, 1 },
  { 240, 1 },
  { 240, 2 },
  { 240, 0 },
  { 241, 1 },
  { 241, 1 },
  { 241, 3 },
  { 242, 0 },
  { 242, 3 },
  { 243, 0 },
  { 243, 2 },
  { 239, 3 },
  { 239, 2 },
  { 245, 1 },
  { 245, 3 },
  { 246, 0 },
  { 246, 3 },
  { 246, 2 },
  { 244, 7 },
  { 244, 5 },
  { 244, 5 },
  { 244, 5 },
  { 244, 1 },
  { 175, 4 },
  { 175, 6 },
  { 191, 1 },
  { 191, 1 },
  { 191, 1 },
  { 147, 4 },
  { 147, 6 },
  { 147, 3 },
  { 248, 0 },
  { 248, 2 },
  { 247, 1 },
  { 247, 0 },
  { 147, 1 },
  { 147, 3 },
  { 147, 1 },
  { 147, 3 },
  { 147, 6 },
  { 147, 6 },
  { 249, 1 },
  { 250, 0 },
  { 250, 1 },
};

static void yy_accept(yyParser*);  /* Forward Declaration */

/*
** Perform a reduce action and the shift that must immediately
** follow the reduce.
*/
static void yy_reduce(
  yyParser *yypParser,         /* The parser */
  int yyruleno                 /* Number of the rule by which to reduce */
){
  int yygoto;                     /* The next state */
  int yyact;                      /* The next action */
  YYMINORTYPE yygotominor;        /* The LHS of the rule reduced */
  yyStackEntry *yymsp;            /* The top of the parser's stack */
  int yysize;                     /* Amount to pop the stack */
  sqlite4ParserARG_FETCH;
  yymsp = &yypParser->yystack[yypParser->yyidx];
#ifndef NDEBUG
  if( yyTraceFILE && yyruleno>=0 
        && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
    fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
      yyRuleName[yyruleno]);
  }
#endif /* NDEBUG */

  /* Silence complaints from purify about yygotominor being uninitialized
  ** in some cases when it is copied into the stack after the following
  ** switch.  yygotominor is uninitialized when a rule reduces that does
  ** not set the value of its left-hand side nonterminal.  Leaving the
  ** value of the nonterminal uninitialized is utterly harmless as long
  ** as the value is never used.  So really the only thing this code
  ** accomplishes is to quieten purify.  
  **
  ** 2007-01-16:  The wireshark project (www.wireshark.org) reports that
  ** without this code, their parser segfaults.  I'm not sure what there
  ** parser is doing to make this happen.  This is the second bug report
  ** from wireshark this week.  Clearly they are stressing Lemon in ways
  ** that it has not been previously stressed...  (SQLite ticket #2172)
  */
  /*memset(&yygotominor, 0, sizeof(yygotominor));*/
  yygotominor = yyzerominor;


  switch( yyruleno ){
  /* Beginning here are the reduction cases.  A typical example
  ** follows:
  **   case 0:
  **  #line <lineno> <grammarfile>
  **     { ... }           // User supplied code
  **  #line <lineno> <thisfile>
  **     break;
  */
      case 5: /* explain ::= */
{ sqlite4BeginParse(pParse, 0); }
        break;
      case 6: /* explain ::= EXPLAIN */
{ sqlite4BeginParse(pParse, 1); }
        break;
      case 7: /* explain ::= EXPLAIN QUERY PLAN */
{ sqlite4BeginParse(pParse, 2); }
        break;
      case 8: /* cmdx ::= cmd */
{ sqlite4FinishCoding(pParse); }
        break;
      case 9: /* cmd ::= BEGIN transtype trans_opt */
{sqlite4BeginTransaction(pParse, yymsp[-1].minor.yy194);}
        break;
      case 13: /* transtype ::= */
{yygotominor.yy194 = TK_DEFERRED;}
        break;
      case 14: /* transtype ::= DEFERRED */
      case 15: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==15);
      case 16: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==16);
      case 115: /* multiselect_op ::= UNION */ yytestcase(yyruleno==115);
      case 117: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==117);
{yygotominor.yy194 = yymsp[0].major;}
        break;
      case 17: /* cmd ::= COMMIT trans_opt */
      case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18);
{sqlite4EndTransaction(pParse, SAVEPOINT_RELEASE);}
        break;
      case 19: /* cmd ::= ROLLBACK trans_opt */
{sqlite4EndTransaction(pParse, SAVEPOINT_ROLLBACK);}
        break;
      case 22: /* cmd ::= SAVEPOINT nm */
{
  sqlite4Savepoint(pParse, SAVEPOINT_BEGIN, &yymsp[0].minor.yy0);
}
        break;
      case 23: /* cmd ::= RELEASE savepoint_opt nm */
{
  sqlite4Savepoint(pParse, SAVEPOINT_RELEASE, &yymsp[0].minor.yy0);
}
        break;
      case 24: /* cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
{
  sqlite4Savepoint(pParse, SAVEPOINT_ROLLBACK, &yymsp[0].minor.yy0);
}
        break;
      case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
   sqlite4StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy194,0,0,yymsp[-2].minor.yy194);
}
        break;
      case 27: /* createkw ::= CREATE */
{
  pParse->db->lookaside.bEnabled = 0;
  yygotominor.yy0 = yymsp[0].minor.yy0;
}
        break;
      case 28: /* ifnotexists ::= */
      case 31: /* temp ::= */ yytestcase(yyruleno==31);
      case 70: /* autoinc ::= */ yytestcase(yyruleno==70);
      case 83: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==83);
      case 85: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==85);
      case 87: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==87);
      case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
      case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
      case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
      case 222: /* between_op ::= BETWEEN */ yytestcase(yyruleno==222);
      case 225: /* in_op ::= IN */ yytestcase(yyruleno==225);
{yygotominor.yy194 = 0;}
        break;
      case 29: /* ifnotexists ::= IF NOT EXISTS */
      case 30: /* temp ::= TEMP */ yytestcase(yyruleno==30);
      case 71: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==71);
      case 86: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==86);
      case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
      case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
      case 223: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==223);
      case 226: /* in_op ::= NOT IN */ yytestcase(yyruleno==226);
{yygotominor.yy194 = 1;}
        break;
      case 32: /* create_table_args ::= LP columnlist conslist_opt RP */
{
  sqlite4EndTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0);
}
        break;
      case 33: /* create_table_args ::= AS select */
{
  sqlite4EndTable(pParse,0,0,yymsp[0].minor.yy243);
  sqlite4SelectDelete(pParse->db, yymsp[0].minor.yy243);
}
        break;
      case 36: /* column ::= columnid type carglist */
{
  yygotominor.yy0.z = yymsp[-2].minor.yy0.z;
  yygotominor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-2].minor.yy0.z) + pParse->sLastToken.n;
}
        break;
      case 37: /* columnid ::= nm */
{
  sqlite4AddColumn(pParse,&yymsp[0].minor.yy0);
  yygotominor.yy0 = yymsp[0].minor.yy0;
}
        break;
      case 38: /* id ::= ID */
      case 39: /* id ::= INDEXED */ yytestcase(yyruleno==39);
      case 40: /* ids ::= ID|STRING */ yytestcase(yyruleno==40);
      case 41: /* nm ::= id */ yytestcase(yyruleno==41);
      case 42: /* nm ::= STRING */ yytestcase(yyruleno==42);
      case 43: /* nm ::= JOIN_KW */ yytestcase(yyruleno==43);
      case 46: /* typetoken ::= typename */ yytestcase(yyruleno==46);
      case 49: /* typename ::= ids */ yytestcase(yyruleno==49);
      case 127: /* as ::= AS nm */ yytestcase(yyruleno==127);
      case 128: /* as ::= ids */ yytestcase(yyruleno==128);
      case 138: /* dbnm ::= DOT nm */ yytestcase(yyruleno==138);
      case 147: /* indexed_opt ::= INDEXED BY nm */ yytestcase(yyruleno==147);
      case 252: /* collate ::= COLLATE ids */ yytestcase(yyruleno==252);
      case 274: /* plus_num ::= plus_opt number */ yytestcase(yyruleno==274);
      case 275: /* minus_num ::= MINUS number */ yytestcase(yyruleno==275);
      case 276: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==276);
      case 294: /* trnm ::= nm */ yytestcase(yyruleno==294);
{yygotominor.yy0 = yymsp[0].minor.yy0;}
        break;
      case 45: /* type ::= typetoken */
{sqlite4AddColumnType(pParse,&yymsp[0].minor.yy0);}
        break;
      case 47: /* typetoken ::= typename LP signed RP */
{
  yygotominor.yy0.z = yymsp[-3].minor.yy0.z;
  yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
}
        break;
      case 48: /* typetoken ::= typename LP signed COMMA signed RP */
{
  yygotominor.yy0.z = yymsp[-5].minor.yy0.z;
  yygotominor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
}
        break;
      case 50: /* typename ::= typename ids */
{yygotominor.yy0.z=yymsp[-1].minor.yy0.z; yygotominor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
        break;
      case 57: /* ccons ::= DEFAULT term */
      case 59: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==59);
{sqlite4AddDefaultValue(pParse,&yymsp[0].minor.yy190);}
        break;
      case 58: /* ccons ::= DEFAULT LP expr RP */
{sqlite4AddDefaultValue(pParse,&yymsp[-1].minor.yy190);}
        break;
      case 60: /* ccons ::= DEFAULT MINUS term */
{
  ExprSpan v;
  v.pExpr = sqlite4PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy190.pExpr, 0, 0);
  v.zStart = yymsp[-1].minor.yy0.z;
  v.zEnd = yymsp[0].minor.yy190.zEnd;
  sqlite4AddDefaultValue(pParse,&v);
}
        break;
      case 61: /* ccons ::= DEFAULT id */
{
  ExprSpan v;
  spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0);
  sqlite4AddDefaultValue(pParse,&v);
}
        break;
      case 63: /* ccons ::= NOT NULL onconf */
{sqlite4AddNotNull(pParse, yymsp[0].minor.yy194);}
        break;
      case 64: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
{sqlite4AddPrimaryKey(pParse,0,yymsp[-1].minor.yy194,yymsp[0].minor.yy194,yymsp[-2].minor.yy194);}
        break;
      case 65: /* ccons ::= UNIQUE onconf */
{sqlite4CreateIndex(pParse,0,0,0,yymsp[0].minor.yy194,0,0,0);}
        break;
      case 66: /* ccons ::= CHECK LP expr RP */
{sqlite4AddCheckConstraint(pParse,yymsp[-1].minor.yy190.pExpr);}
        break;
      case 67: /* ccons ::= REFERENCES nm idxlist_opt refargs */
{sqlite4CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy148,yymsp[0].minor.yy194);}
        break;
      case 68: /* ccons ::= defer_subclause */
{sqlite4DeferForeignKey(pParse,yymsp[0].minor.yy194);}
        break;
      case 69: /* ccons ::= COLLATE ids */
{sqlite4AddCollateType(pParse, &yymsp[0].minor.yy0);}
        break;
      case 72: /* refargs ::= */
{ yygotominor.yy194 = OE_None*0x0101; /* EV: R-19803-45884 */}
        break;
      case 73: /* refargs ::= refargs refarg */
{ yygotominor.yy194 = (yymsp[-1].minor.yy194 & ~yymsp[0].minor.yy497.mask) | yymsp[0].minor.yy497.value; }
        break;
      case 74: /* refarg ::= MATCH nm */
      case 75: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==75);
{ yygotominor.yy497.value = 0;     yygotominor.yy497.mask = 0x000000; }
        break;
      case 76: /* refarg ::= ON DELETE refact */
{ yygotominor.yy497.value = yymsp[0].minor.yy194;     yygotominor.yy497.mask = 0x0000ff; }
        break;
      case 77: /* refarg ::= ON UPDATE refact */
{ yygotominor.yy497.value = yymsp[0].minor.yy194<<8;  yygotominor.yy497.mask = 0x00ff00; }
        break;
      case 78: /* refact ::= SET NULL */
{ yygotominor.yy194 = OE_SetNull;  /* EV: R-33326-45252 */}
        break;
      case 79: /* refact ::= SET DEFAULT */
{ yygotominor.yy194 = OE_SetDflt;  /* EV: R-33326-45252 */}
        break;
      case 80: /* refact ::= CASCADE */
{ yygotominor.yy194 = OE_Cascade;  /* EV: R-33326-45252 */}
        break;
      case 81: /* refact ::= RESTRICT */
{ yygotominor.yy194 = OE_Restrict; /* EV: R-33326-45252 */}
        break;
      case 82: /* refact ::= NO ACTION */
{ yygotominor.yy194 = OE_None;     /* EV: R-33326-45252 */}
        break;
      case 84: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
      case 99: /* defer_subclause_opt ::= defer_subclause */ yytestcase(yyruleno==99);
      case 101: /* onconf ::= ON CONFLICT resolvetype */ yytestcase(yyruleno==101);
      case 104: /* resolvetype ::= raisetype */ yytestcase(yyruleno==104);
{yygotominor.yy194 = yymsp[0].minor.yy194;}
        break;
      case 88: /* conslist_opt ::= */
{yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;}
        break;
      case 89: /* conslist_opt ::= COMMA conslist */
{yygotominor.yy0 = yymsp[-1].minor.yy0;}
        break;
      case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */
{sqlite4AddPrimaryKey(pParse,yymsp[-3].minor.yy148,yymsp[0].minor.yy194,yymsp[-2].minor.yy194,0);}
        break;
      case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */
{sqlite4CreateIndex(pParse,0,yymsp[-2].minor.yy148,0,yymsp[0].minor.yy194,0,0,0);}
        break;
      case 96: /* tcons ::= CHECK LP expr RP onconf */
{sqlite4AddCheckConstraint(pParse,yymsp[-2].minor.yy190.pExpr);}
        break;
      case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */
{
    sqlite4CreateForeignKey(pParse, yymsp[-6].minor.yy148, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy148, yymsp[-1].minor.yy194);
    sqlite4DeferForeignKey(pParse, yymsp[0].minor.yy194);
}
        break;
      case 100: /* onconf ::= */
{yygotominor.yy194 = OE_Default;}
        break;
      case 102: /* orconf ::= */
{yygotominor.yy234 = OE_Default;}
        break;
      case 103: /* orconf ::= OR resolvetype */
{yygotominor.yy234 = (u8)yymsp[0].minor.yy194;}
        break;
      case 105: /* resolvetype ::= IGNORE */
{yygotominor.yy194 = OE_Ignore;}
        break;
      case 106: /* resolvetype ::= REPLACE */
{yygotominor.yy194 = OE_Replace;}
        break;
      case 107: /* cmd ::= DROP TABLE ifexists fullname */
{
  sqlite4DropTable(pParse, yymsp[0].minor.yy185, 0, yymsp[-1].minor.yy194);
}
        break;
      case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */
{
  sqlite4CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy243, yymsp[-6].minor.yy194, yymsp[-4].minor.yy194);
}
        break;
      case 111: /* cmd ::= DROP VIEW ifexists fullname */
{
  sqlite4DropTable(pParse, yymsp[0].minor.yy185, 1, yymsp[-1].minor.yy194);
}
        break;
      case 112: /* cmd ::= select */
{
  SelectDest dest = {SRT_Output, 0, 0, 0, 0};
  sqlite4Select(pParse, yymsp[0].minor.yy243, &dest);
  sqlite4ExplainBegin(pParse->pVdbe);
  sqlite4ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy243);
  sqlite4ExplainFinish(pParse->pVdbe);
  sqlite4SelectDelete(pParse->db, yymsp[0].minor.yy243);
}
        break;
      case 113: /* select ::= oneselect */
{yygotominor.yy243 = yymsp[0].minor.yy243;}
        break;
      case 114: /* select ::= select multiselect_op oneselect */
{
  if( yymsp[0].minor.yy243 ){
    yymsp[0].minor.yy243->op = (u8)yymsp[-1].minor.yy194;
    yymsp[0].minor.yy243->pPrior = yymsp[-2].minor.yy243;
  }else{
    sqlite4SelectDelete(pParse->db, yymsp[-2].minor.yy243);
  }
  yygotominor.yy243 = yymsp[0].minor.yy243;
}
        break;
      case 116: /* multiselect_op ::= UNION ALL */
{yygotominor.yy194 = TK_ALL;}
        break;
      case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
  yygotominor.yy243 = sqlite4SelectNew(pParse,yymsp[-6].minor.yy148,yymsp[-5].minor.yy185,yymsp[-4].minor.yy72,yymsp[-3].minor.yy148,yymsp[-2].minor.yy72,yymsp[-1].minor.yy148,yymsp[-7].minor.yy194,yymsp[0].minor.yy354.pLimit,yymsp[0].minor.yy354.pOffset);
}
        break;
      case 122: /* sclp ::= selcollist COMMA */
      case 248: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==248);
{yygotominor.yy148 = yymsp[-1].minor.yy148;}
        break;
      case 123: /* sclp ::= */
      case 151: /* orderby_opt ::= */ yytestcase(yyruleno==151);
      case 159: /* groupby_opt ::= */ yytestcase(yyruleno==159);
      case 240: /* exprlist ::= */ yytestcase(yyruleno==240);
      case 247: /* idxlist_opt ::= */ yytestcase(yyruleno==247);
{yygotominor.yy148 = 0;}
        break;
      case 124: /* selcollist ::= sclp expr as */
{
   yygotominor.yy148 = sqlite4ExprListAppend(pParse, yymsp[-2].minor.yy148, yymsp[-1].minor.yy190.pExpr);
   if( yymsp[0].minor.yy0.n>0 ) sqlite4ExprListSetName(pParse, yygotominor.yy148, &yymsp[0].minor.yy0, 1);
   sqlite4ExprListSetSpan(pParse,yygotominor.yy148,&yymsp[-1].minor.yy190);
}
        break;
      case 125: /* selcollist ::= sclp STAR */
{
  Expr *p = sqlite4Expr(pParse->db, TK_ALL, 0);
  yygotominor.yy148 = sqlite4ExprListAppend(pParse, yymsp[-1].minor.yy148, p);
}
        break;
      case 126: /* selcollist ::= sclp nm DOT STAR */
{
  Expr *pRight = sqlite4PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0);
  Expr *pLeft = sqlite4PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *pDot = sqlite4PExpr(pParse, TK_DOT, pLeft, pRight, 0);
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,yymsp[-3].minor.yy148, pDot);
}
        break;
      case 129: /* as ::= */
{yygotominor.yy0.n = 0;}
        break;
      case 130: /* from ::= */
{yygotominor.yy185 = sqlite4DbMallocZero(pParse->db, sizeof(*yygotominor.yy185));}
        break;
      case 131: /* from ::= FROM seltablist */
{
  yygotominor.yy185 = yymsp[0].minor.yy185;
  sqlite4SrcListShiftJoinType(yygotominor.yy185);
}
        break;
      case 132: /* stl_prefix ::= seltablist joinop */
{
   yygotominor.yy185 = yymsp[-1].minor.yy185;
   if( ALWAYS(yygotominor.yy185 && yygotominor.yy185->nSrc>0) ) yygotominor.yy185->a[yygotominor.yy185->nSrc-1].jointype = (u8)yymsp[0].minor.yy194;
}
        break;
      case 133: /* stl_prefix ::= */
{yygotominor.yy185 = 0;}
        break;
      case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
{
  yygotominor.yy185 = sqlite4SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy72,yymsp[0].minor.yy254);
  sqlite4SrcListIndexedBy(pParse, yygotominor.yy185, &yymsp[-2].minor.yy0);
}
        break;
      case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
{
    yygotominor.yy185 = sqlite4SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy243,yymsp[-1].minor.yy72,yymsp[0].minor.yy254);
  }
        break;
      case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
{
    if( yymsp[-6].minor.yy185==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy72==0 && yymsp[0].minor.yy254==0 ){
      yygotominor.yy185 = yymsp[-4].minor.yy185;
    }else{
      Select *pSubquery;
      sqlite4SrcListShiftJoinType(yymsp[-4].minor.yy185);
      pSubquery = sqlite4SelectNew(pParse,0,yymsp[-4].minor.yy185,0,0,0,0,0,0,0);
      yygotominor.yy185 = sqlite4SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy185,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy72,yymsp[0].minor.yy254);
    }
  }
        break;
      case 137: /* dbnm ::= */
      case 146: /* indexed_opt ::= */ yytestcase(yyruleno==146);
{yygotominor.yy0.z=0; yygotominor.yy0.n=0;}
        break;
      case 139: /* fullname ::= nm dbnm */
{yygotominor.yy185 = sqlite4SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
        break;
      case 140: /* joinop ::= COMMA|JOIN */
{ yygotominor.yy194 = JT_INNER; }
        break;
      case 141: /* joinop ::= JOIN_KW JOIN */
{ yygotominor.yy194 = sqlite4JoinType(pParse,&yymsp[-1].minor.yy0,0,0); }
        break;
      case 142: /* joinop ::= JOIN_KW nm JOIN */
{ yygotominor.yy194 = sqlite4JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); }
        break;
      case 143: /* joinop ::= JOIN_KW nm nm JOIN */
{ yygotominor.yy194 = sqlite4JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); }
        break;
      case 144: /* on_opt ::= ON expr */
      case 155: /* sortitem ::= expr */ yytestcase(yyruleno==155);
      case 162: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==162);
      case 169: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==169);
      case 235: /* case_else ::= ELSE expr */ yytestcase(yyruleno==235);
      case 237: /* case_operand ::= expr */ yytestcase(yyruleno==237);
{yygotominor.yy72 = yymsp[0].minor.yy190.pExpr;}
        break;
      case 145: /* on_opt ::= */
      case 161: /* having_opt ::= */ yytestcase(yyruleno==161);
      case 168: /* where_opt ::= */ yytestcase(yyruleno==168);
      case 236: /* case_else ::= */ yytestcase(yyruleno==236);
      case 238: /* case_operand ::= */ yytestcase(yyruleno==238);
{yygotominor.yy72 = 0;}
        break;
      case 148: /* indexed_opt ::= NOT INDEXED */
{yygotominor.yy0.z=0; yygotominor.yy0.n=1;}
        break;
      case 149: /* using_opt ::= USING LP inscollist RP */
      case 181: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==181);
{yygotominor.yy254 = yymsp[-1].minor.yy254;}
        break;
      case 150: /* using_opt ::= */
      case 180: /* inscollist_opt ::= */ yytestcase(yyruleno==180);
{yygotominor.yy254 = 0;}
        break;
      case 152: /* orderby_opt ::= ORDER BY sortlist */
      case 160: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==160);
      case 239: /* exprlist ::= nexprlist */ yytestcase(yyruleno==239);
      case 268: /* pragmaargs ::= pragmaarg */ yytestcase(yyruleno==268);
{yygotominor.yy148 = yymsp[0].minor.yy148;}
        break;
      case 153: /* sortlist ::= sortlist COMMA sortitem sortorder */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,yymsp[-3].minor.yy148,yymsp[-1].minor.yy72);
  if( yygotominor.yy148 ) yygotominor.yy148->a[yygotominor.yy148->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy194;
}
        break;
      case 154: /* sortlist ::= sortitem sortorder */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,0,yymsp[-1].minor.yy72);
  if( yygotominor.yy148 && ALWAYS(yygotominor.yy148->a) ) yygotominor.yy148->a[0].sortOrder = (u8)yymsp[0].minor.yy194;
}
        break;
      case 156: /* sortorder ::= ASC */
      case 158: /* sortorder ::= */ yytestcase(yyruleno==158);
{yygotominor.yy194 = SQLITE4_SO_ASC;}
        break;
      case 157: /* sortorder ::= DESC */
{yygotominor.yy194 = SQLITE4_SO_DESC;}
        break;
      case 163: /* limit_opt ::= */
{yygotominor.yy354.pLimit = 0; yygotominor.yy354.pOffset = 0;}
        break;
      case 164: /* limit_opt ::= LIMIT expr */
{yygotominor.yy354.pLimit = yymsp[0].minor.yy190.pExpr; yygotominor.yy354.pOffset = 0;}
        break;
      case 165: /* limit_opt ::= LIMIT expr OFFSET expr */
{yygotominor.yy354.pLimit = yymsp[-2].minor.yy190.pExpr; yygotominor.yy354.pOffset = yymsp[0].minor.yy190.pExpr;}
        break;
      case 166: /* limit_opt ::= LIMIT expr COMMA expr */
{yygotominor.yy354.pOffset = yymsp[-2].minor.yy190.pExpr; yygotominor.yy354.pLimit = yymsp[0].minor.yy190.pExpr;}
        break;
      case 167: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */
{
  sqlite4SrcListIndexedBy(pParse, yymsp[-2].minor.yy185, &yymsp[-1].minor.yy0);
  sqlite4DeleteFrom(pParse,yymsp[-2].minor.yy185,yymsp[0].minor.yy72);
}
        break;
      case 170: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */
{
  sqlite4SrcListIndexedBy(pParse, yymsp[-4].minor.yy185, &yymsp[-3].minor.yy0);
  sqlite4ExprListCheckLength(pParse,yymsp[-1].minor.yy148,"set list"); 
  sqlite4Update(pParse,yymsp[-4].minor.yy185,yymsp[-1].minor.yy148,yymsp[0].minor.yy72,yymsp[-5].minor.yy234);
}
        break;
      case 171: /* setlist ::= setlist COMMA nm EQ expr */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse, yymsp[-4].minor.yy148, yymsp[0].minor.yy190.pExpr);
  sqlite4ExprListSetName(pParse, yygotominor.yy148, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 172: /* setlist ::= nm EQ expr */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse, 0, yymsp[0].minor.yy190.pExpr);
  sqlite4ExprListSetName(pParse, yygotominor.yy148, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */
{sqlite4Insert(pParse, yymsp[-2].minor.yy185, yymsp[0].minor.yy167.pList, yymsp[0].minor.yy167.pSelect, yymsp[-1].minor.yy254, yymsp[-4].minor.yy234);}
        break;
      case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */
{sqlite4Insert(pParse, yymsp[-2].minor.yy185, 0, yymsp[0].minor.yy243, yymsp[-1].minor.yy254, yymsp[-4].minor.yy234);}
        break;
      case 175: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */
{sqlite4Insert(pParse, yymsp[-3].minor.yy185, 0, 0, yymsp[-2].minor.yy254, yymsp[-5].minor.yy234);}
        break;
      case 176: /* insert_cmd ::= INSERT orconf */
{yygotominor.yy234 = yymsp[0].minor.yy234;}
        break;
      case 177: /* insert_cmd ::= REPLACE */
{yygotominor.yy234 = OE_Replace;}
        break;
      case 178: /* valuelist ::= VALUES LP nexprlist RP */
{
  yygotominor.yy167.pList = yymsp[-1].minor.yy148;
  yygotominor.yy167.pSelect = 0;
}
        break;
      case 179: /* valuelist ::= valuelist COMMA LP exprlist RP */
{
  Select *pRight = sqlite4SelectNew(pParse, yymsp[-1].minor.yy148, 0, 0, 0, 0, 0, 0, 0, 0);
  if( yymsp[-4].minor.yy167.pList ){
    yymsp[-4].minor.yy167.pSelect = sqlite4SelectNew(pParse, yymsp[-4].minor.yy167.pList, 0, 0, 0, 0, 0, 0, 0, 0);
    yymsp[-4].minor.yy167.pList = 0;
  }
  yygotominor.yy167.pList = 0;
  if( yymsp[-4].minor.yy167.pSelect==0 || pRight==0 ){
    sqlite4SelectDelete(pParse->db, pRight);
    sqlite4SelectDelete(pParse->db, yymsp[-4].minor.yy167.pSelect);
    yygotominor.yy167.pSelect = 0;
  }else{
    pRight->op = TK_ALL;
    pRight->pPrior = yymsp[-4].minor.yy167.pSelect;
    pRight->selFlags |= SF_Values;
    pRight->pPrior->selFlags |= SF_Values;
    yygotominor.yy167.pSelect = pRight;
  }
}
        break;
      case 182: /* inscollist ::= inscollist COMMA nm */
{yygotominor.yy254 = sqlite4IdListAppend(pParse->db,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);}
        break;
      case 183: /* inscollist ::= nm */
{yygotominor.yy254 = sqlite4IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);}
        break;
      case 184: /* expr ::= term */
{yygotominor.yy190 = yymsp[0].minor.yy190;}
        break;
      case 185: /* expr ::= LP expr RP */
{yygotominor.yy190.pExpr = yymsp[-1].minor.yy190.pExpr; spanSet(&yygotominor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);}
        break;
      case 186: /* term ::= NULL */
      case 191: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==191);
      case 192: /* term ::= STRING */ yytestcase(yyruleno==192);
{spanExpr(&yygotominor.yy190, pParse, yymsp[0].major, &yymsp[0].minor.yy0);}
        break;
      case 187: /* expr ::= id */
      case 188: /* expr ::= JOIN_KW */ yytestcase(yyruleno==188);
{spanExpr(&yygotominor.yy190, pParse, TK_ID, &yymsp[0].minor.yy0);}
        break;
      case 189: /* expr ::= nm DOT nm */
{
  Expr *temp1 = sqlite4PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *temp2 = sqlite4PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
  yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_DOT, temp1, temp2, 0);
  spanSet(&yygotominor.yy190,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 190: /* expr ::= nm DOT nm DOT nm */
{
  Expr *temp1 = sqlite4PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0);
  Expr *temp2 = sqlite4PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0);
  Expr *temp3 = sqlite4PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0);
  Expr *temp4 = sqlite4PExpr(pParse, TK_DOT, temp2, temp3, 0);
  yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_DOT, temp1, temp4, 0);
  spanSet(&yygotominor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 193: /* expr ::= REGISTER */
{
  /* When doing a nested parse, one can include terms in an expression
  ** that look like this:   #1 #2 ...  These terms refer to registers
  ** in the virtual machine.  #N is the N-th register. */
  if( pParse->nested==0 ){
    sqlite4ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0);
    yygotominor.yy190.pExpr = 0;
  }else{
    yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0);
    if( yygotominor.yy190.pExpr ) sqlite4GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy190.pExpr->iTable);
  }
  spanSet(&yygotominor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 194: /* expr ::= VARIABLE */
{
  spanExpr(&yygotominor.yy190, pParse, TK_VARIABLE, &yymsp[0].minor.yy0);
  sqlite4ExprAssignVarNumber(pParse, yygotominor.yy190.pExpr);
  spanSet(&yygotominor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 195: /* expr ::= expr COLLATE ids */
{
  yygotominor.yy190.pExpr = sqlite4ExprSetCollByToken(pParse, yymsp[-2].minor.yy190.pExpr, &yymsp[0].minor.yy0);
  yygotominor.yy190.zStart = yymsp[-2].minor.yy190.zStart;
  yygotominor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 196: /* expr ::= CAST LP expr AS typetoken RP */
{
  yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_CAST, yymsp[-3].minor.yy190.pExpr, 0, &yymsp[-1].minor.yy0);
  spanSet(&yygotominor.yy190,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 197: /* expr ::= ID LP distinct exprlist RP */
{
  if( yymsp[-1].minor.yy148 && yymsp[-1].minor.yy148->nExpr>pParse->db->aLimit[SQLITE4_LIMIT_FUNCTION_ARG] ){
    sqlite4ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0);
  }
  yygotominor.yy190.pExpr = sqlite4ExprFunction(pParse, yymsp[-1].minor.yy148, &yymsp[-4].minor.yy0);
  spanSet(&yygotominor.yy190,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
  if( yymsp[-2].minor.yy194 && yygotominor.yy190.pExpr ){
    yygotominor.yy190.pExpr->flags |= EP_Distinct;
  }
}
        break;
      case 198: /* expr ::= ID LP STAR RP */
{
  yygotominor.yy190.pExpr = sqlite4ExprFunction(pParse, 0, &yymsp[-3].minor.yy0);
  spanSet(&yygotominor.yy190,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0);
}
        break;
      case 199: /* term ::= CTIME_KW */
{
  /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are
  ** treated as functions that return constants */
  yygotominor.yy190.pExpr = sqlite4ExprFunction(pParse, 0,&yymsp[0].minor.yy0);
  if( yygotominor.yy190.pExpr ){
    yygotominor.yy190.pExpr->op = TK_CONST_FUNC;  
  }
  spanSet(&yygotominor.yy190, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 200: /* expr ::= expr AND expr */
      case 201: /* expr ::= expr OR expr */ yytestcase(yyruleno==201);
      case 202: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==202);
      case 203: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==203);
      case 204: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==204);
      case 205: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==205);
      case 206: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==206);
      case 207: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==207);
{spanBinaryExpr(&yygotominor.yy190,pParse,yymsp[-1].major,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);}
        break;
      case 208: /* likeop ::= LIKE_KW */
{yygotominor.yy392.eOperator = yymsp[0].minor.yy0; yygotominor.yy392.not = 0;}
        break;
      case 209: /* likeop ::= NOT LIKE_KW */
      case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210);
{yygotominor.yy392.eOperator = yymsp[0].minor.yy0; yygotominor.yy392.not = 1;}
        break;
      case 211: /* expr ::= expr likeop expr */
{
  ExprList *pList;
  pList = sqlite4ExprListAppend(pParse,0, yymsp[0].minor.yy190.pExpr);
  pList = sqlite4ExprListAppend(pParse,pList, yymsp[-2].minor.yy190.pExpr);
  yygotominor.yy190.pExpr = sqlite4ExprFunction(pParse, pList, &yymsp[-1].minor.yy392.eOperator);
  if( yymsp[-1].minor.yy392.not ) yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_NOT, yygotominor.yy190.pExpr, 0, 0);
  yygotominor.yy190.zStart = yymsp[-2].minor.yy190.zStart;
  yygotominor.yy190.zEnd = yymsp[0].minor.yy190.zEnd;
  if( yygotominor.yy190.pExpr ) yygotominor.yy190.pExpr->flags |= EP_InfixFunc;
}
        break;
      case 212: /* expr ::= expr likeop expr ESCAPE expr */
{
  ExprList *pList;
  pList = sqlite4ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr);
  pList = sqlite4ExprListAppend(pParse,pList, yymsp[-4].minor.yy190.pExpr);
  pList = sqlite4ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr);
  yygotominor.yy190.pExpr = sqlite4ExprFunction(pParse, pList, &yymsp[-3].minor.yy392.eOperator);
  if( yymsp[-3].minor.yy392.not ) yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_NOT, yygotominor.yy190.pExpr, 0, 0);
  yygotominor.yy190.zStart = yymsp[-4].minor.yy190.zStart;
  yygotominor.yy190.zEnd = yymsp[0].minor.yy190.zEnd;
  if( yygotominor.yy190.pExpr ) yygotominor.yy190.pExpr->flags |= EP_InfixFunc;
}
        break;
      case 213: /* expr ::= expr MATCH expr */
{
  spanBinaryExpr(&yygotominor.yy190, pParse, TK_MATCH, &yymsp[-2].minor.yy190, &yymsp[0].minor.yy190);
}
        break;
      case 214: /* expr ::= expr ISNULL|NOTNULL */
{spanUnaryPostfix(&yygotominor.yy190,pParse,yymsp[0].major,&yymsp[-1].minor.yy190,&yymsp[0].minor.yy0);}
        break;
      case 215: /* expr ::= expr NOT NULL */
{spanUnaryPostfix(&yygotominor.yy190,pParse,TK_NOTNULL,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy0);}
        break;
      case 216: /* expr ::= expr IS expr */
{
  spanBinaryExpr(&yygotominor.yy190,pParse,TK_IS,&yymsp[-2].minor.yy190,&yymsp[0].minor.yy190);
  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yygotominor.yy190.pExpr, TK_ISNULL);
}
        break;
      case 217: /* expr ::= expr IS NOT expr */
{
  spanBinaryExpr(&yygotominor.yy190,pParse,TK_ISNOT,&yymsp[-3].minor.yy190,&yymsp[0].minor.yy190);
  binaryToUnaryIfNull(pParse, yymsp[0].minor.yy190.pExpr, yygotominor.yy190.pExpr, TK_NOTNULL);
}
        break;
      case 218: /* expr ::= NOT expr */
      case 219: /* expr ::= BITNOT expr */ yytestcase(yyruleno==219);
{spanUnaryPrefix(&yygotominor.yy190,pParse,yymsp[-1].major,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);}
        break;
      case 220: /* expr ::= MINUS expr */
{spanUnaryPrefix(&yygotominor.yy190,pParse,TK_UMINUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);}
        break;
      case 221: /* expr ::= PLUS expr */
{spanUnaryPrefix(&yygotominor.yy190,pParse,TK_UPLUS,&yymsp[0].minor.yy190,&yymsp[-1].minor.yy0);}
        break;
      case 224: /* expr ::= expr between_op expr AND expr */
{
  ExprList *pList = sqlite4ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr);
  pList = sqlite4ExprListAppend(pParse,pList, yymsp[0].minor.yy190.pExpr);
  yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy190.pExpr, 0, 0);
  if( yygotominor.yy190.pExpr ){
    yygotominor.yy190.pExpr->x.pList = pList;
  }else{
    sqlite4ExprListDelete(pParse->db, pList);
  } 
  if( yymsp[-3].minor.yy194 ) yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_NOT, yygotominor.yy190.pExpr, 0, 0);
  yygotominor.yy190.zStart = yymsp[-4].minor.yy190.zStart;
  yygotominor.yy190.zEnd = yymsp[0].minor.yy190.zEnd;
}
        break;
      case 227: /* expr ::= expr in_op LP exprlist RP */
{
    if( yymsp[-1].minor.yy148==0 ){
      /* Expressions of the form
      **
      **      expr1 IN ()
      **      expr1 NOT IN ()
      **
      ** simplify to constants 0 (false) and 1 (true), respectively,
      ** regardless of the value of expr1.
      */
      yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_INTEGER, 0, 0, &sqlite4IntTokens[yymsp[-3].minor.yy194]);
      sqlite4ExprDelete(pParse->db, yymsp[-4].minor.yy190.pExpr);
    }else{
      yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0);
      if( yygotominor.yy190.pExpr ){
        yygotominor.yy190.pExpr->x.pList = yymsp[-1].minor.yy148;
        sqlite4ExprSetHeight(pParse, yygotominor.yy190.pExpr);
      }else{
        sqlite4ExprListDelete(pParse->db, yymsp[-1].minor.yy148);
      }
      if( yymsp[-3].minor.yy194 ) yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_NOT, yygotominor.yy190.pExpr, 0, 0);
    }
    yygotominor.yy190.zStart = yymsp[-4].minor.yy190.zStart;
    yygotominor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 228: /* expr ::= LP select RP */
{
    yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_SELECT, 0, 0, 0);
    if( yygotominor.yy190.pExpr ){
      yygotominor.yy190.pExpr->x.pSelect = yymsp[-1].minor.yy243;
      ExprSetProperty(yygotominor.yy190.pExpr, EP_xIsSelect);
      sqlite4ExprSetHeight(pParse, yygotominor.yy190.pExpr);
    }else{
      sqlite4SelectDelete(pParse->db, yymsp[-1].minor.yy243);
    }
    yygotominor.yy190.zStart = yymsp[-2].minor.yy0.z;
    yygotominor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 229: /* expr ::= expr in_op LP select RP */
{
    yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_IN, yymsp[-4].minor.yy190.pExpr, 0, 0);
    if( yygotominor.yy190.pExpr ){
      yygotominor.yy190.pExpr->x.pSelect = yymsp[-1].minor.yy243;
      ExprSetProperty(yygotominor.yy190.pExpr, EP_xIsSelect);
      sqlite4ExprSetHeight(pParse, yygotominor.yy190.pExpr);
    }else{
      sqlite4SelectDelete(pParse->db, yymsp[-1].minor.yy243);
    }
    if( yymsp[-3].minor.yy194 ) yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_NOT, yygotominor.yy190.pExpr, 0, 0);
    yygotominor.yy190.zStart = yymsp[-4].minor.yy190.zStart;
    yygotominor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 230: /* expr ::= expr in_op nm dbnm */
{
    SrcList *pSrc = sqlite4SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);
    yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_IN, yymsp[-3].minor.yy190.pExpr, 0, 0);
    if( yygotominor.yy190.pExpr ){
      yygotominor.yy190.pExpr->x.pSelect = sqlite4SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
      ExprSetProperty(yygotominor.yy190.pExpr, EP_xIsSelect);
      sqlite4ExprSetHeight(pParse, yygotominor.yy190.pExpr);
    }else{
      sqlite4SrcListDelete(pParse->db, pSrc);
    }
    if( yymsp[-2].minor.yy194 ) yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_NOT, yygotominor.yy190.pExpr, 0, 0);
    yygotominor.yy190.zStart = yymsp[-3].minor.yy190.zStart;
    yygotominor.yy190.zEnd = yymsp[0].minor.yy0.z ? &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] : &yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n];
  }
        break;
      case 231: /* expr ::= EXISTS LP select RP */
{
    Expr *p = yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_EXISTS, 0, 0, 0);
    if( p ){
      p->x.pSelect = yymsp[-1].minor.yy243;
      ExprSetProperty(p, EP_xIsSelect);
      sqlite4ExprSetHeight(pParse, p);
    }else{
      sqlite4SelectDelete(pParse->db, yymsp[-1].minor.yy243);
    }
    yygotominor.yy190.zStart = yymsp[-3].minor.yy0.z;
    yygotominor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
  }
        break;
      case 232: /* expr ::= CASE case_operand case_exprlist case_else END */
{
  yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_CASE, yymsp[-3].minor.yy72, yymsp[-1].minor.yy72, 0);
  if( yygotominor.yy190.pExpr ){
    yygotominor.yy190.pExpr->x.pList = yymsp[-2].minor.yy148;
    sqlite4ExprSetHeight(pParse, yygotominor.yy190.pExpr);
  }else{
    sqlite4ExprListDelete(pParse->db, yymsp[-2].minor.yy148);
  }
  yygotominor.yy190.zStart = yymsp[-4].minor.yy0.z;
  yygotominor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 233: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,yymsp[-4].minor.yy148, yymsp[-2].minor.yy190.pExpr);
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,yygotominor.yy148, yymsp[0].minor.yy190.pExpr);
}
        break;
      case 234: /* case_exprlist ::= WHEN expr THEN expr */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,0, yymsp[-2].minor.yy190.pExpr);
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,yygotominor.yy148, yymsp[0].minor.yy190.pExpr);
}
        break;
      case 241: /* nexprlist ::= nexprlist COMMA expr */
{yygotominor.yy148 = sqlite4ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);}
        break;
      case 242: /* nexprlist ::= expr */
{yygotominor.yy148 = sqlite4ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr);}
        break;
      case 243: /* createindex ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm */
{
  yygotominor.yy195.bUnique = yymsp[-6].minor.yy194;
  yygotominor.yy195.bIfnotexist = yymsp[-4].minor.yy194;
  yygotominor.yy195.tCreate = yymsp[-7].minor.yy0;
  yygotominor.yy195.tName1 = yymsp[-3].minor.yy0;
  yygotominor.yy195.tName2 = yymsp[-2].minor.yy0;
  yygotominor.yy195.pTblName = sqlite4SrcListAppend(pParse->db, 0, &yymsp[0].minor.yy0, 0);
}
        break;
      case 244: /* cmd ::= createindex LP idxlist RP covering_opt */
{
  Token *pEnd = (yymsp[0].minor.yy376.pList ? &yymsp[0].minor.yy376.sEnd : &yymsp[-1].minor.yy0);
  sqlite4CreateIndex(pParse, &yymsp[-4].minor.yy195, yymsp[-2].minor.yy148, yymsp[0].minor.yy376.pList, yymsp[-4].minor.yy195.bUnique, pEnd, SQLITE4_SO_ASC,0);
}
        break;
      case 245: /* uniqueflag ::= UNIQUE */
      case 307: /* raisetype ::= ABORT */ yytestcase(yyruleno==307);
{yygotominor.yy194 = OE_Abort;}
        break;
      case 246: /* uniqueflag ::= */
{yygotominor.yy194 = OE_None;}
        break;
      case 249: /* idxlist ::= idxlist COMMA nm collate sortorder */
{
  Expr *p = 0;
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite4Expr(pParse->db, TK_COLUMN, 0);
    sqlite4ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,yymsp[-4].minor.yy148, p);
  sqlite4ExprListSetName(pParse,yygotominor.yy148,&yymsp[-2].minor.yy0,1);
  sqlite4ExprListCheckLength(pParse, yygotominor.yy148, "index");
  if( yygotominor.yy148 ) yygotominor.yy148->a[yygotominor.yy148->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy194;
}
        break;
      case 250: /* idxlist ::= nm collate sortorder */
{
  Expr *p = 0;
  if( yymsp[-1].minor.yy0.n>0 ){
    p = sqlite4PExpr(pParse, TK_COLUMN, 0, 0, 0);
    sqlite4ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0);
  }
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,0, p);
  sqlite4ExprListSetName(pParse, yygotominor.yy148, &yymsp[-2].minor.yy0, 1);
  sqlite4ExprListCheckLength(pParse, yygotominor.yy148, "index");
  if( yygotominor.yy148 ) yygotominor.yy148->a[yygotominor.yy148->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy194;
}
        break;
      case 251: /* collate ::= */
{yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;}
        break;
      case 253: /* cmd ::= createindex USING nm LP uidxlist_opt RP */
{
  sqlite4CreateUsingIndex(pParse, &yymsp[-5].minor.yy195, yymsp[-1].minor.yy148, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0);
}
        break;
      case 254: /* uidxlist_opt ::= uidxlist */
{ yygotominor.yy148 = yymsp[0].minor.yy148; }
        break;
      case 255: /* uidxlist_opt ::= */
{ yygotominor.yy148 = 0; }
        break;
      case 256: /* uidxlist ::= uidxlist COMMA ids EQ ids */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse, yymsp[-4].minor.yy148, sqlite4PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0));
  sqlite4ExprListSetName(pParse, yygotominor.yy148, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 257: /* uidxlist ::= uidxlist COMMA ids */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse, yymsp[-2].minor.yy148, sqlite4PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0));
}
        break;
      case 258: /* uidxlist ::= ids EQ ids */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse, 0, sqlite4PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0));
  sqlite4ExprListSetName(pParse, yygotominor.yy148, &yymsp[-2].minor.yy0, 1);
}
        break;
      case 259: /* uidxlist ::= ids */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse, 0, sqlite4PExpr(pParse, yymsp[0].major, 0, 0, &yymsp[0].minor.yy0));
}
        break;
      case 260: /* covering_opt ::= */
{ yygotominor.yy376.pList = 0; }
        break;
      case 261: /* covering_opt ::= COVERING ALL */
{ 
  yygotominor.yy376.pList = sqlite4DbMallocZero(pParse->db, sizeof(IdList)); 
  yygotominor.yy376.sEnd = yymsp[0].minor.yy0;
}
        break;
      case 262: /* covering_opt ::= COVERING LP inscollist RP */
{ 
  yygotominor.yy376.pList = yymsp[-1].minor.yy254; 
  yygotominor.yy376.sEnd = yymsp[0].minor.yy0;
}
        break;
      case 263: /* cmd ::= DROP INDEX ifexists fullname */
{sqlite4DropIndex(pParse, yymsp[0].minor.yy185, yymsp[-1].minor.yy194);}
        break;
      case 264: /* cmd ::= PRAGMA nm dbnm */
{ sqlite4Pragma(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0, 0); }
        break;
      case 265: /* cmd ::= PRAGMA nm dbnm LP RP */
{ sqlite4Pragma(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, 0); }
        break;
      case 266: /* cmd ::= PRAGMA nm dbnm LP pragmaargs RP */
{
  sqlite4Pragma(pParse, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy148);
}
        break;
      case 267: /* cmd ::= PRAGMA nm dbnm EQ pragmaarg */
{
  sqlite4Pragma(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy148);
}
        break;
      case 269: /* pragmaargs ::= pragmaargs COMMA expr */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,yymsp[-2].minor.yy148,yymsp[0].minor.yy190.pExpr);
  sqlite4ExprListSetSpan(pParse,yygotominor.yy148,&yymsp[0].minor.yy190);
}
        break;
      case 270: /* pragmaarg ::= expr */
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse,0,yymsp[0].minor.yy190.pExpr);
  sqlite4ExprListSetSpan(pParse,yygotominor.yy148,&yymsp[0].minor.yy190);
}
        break;
      case 271: /* pragmaarg ::= ON */
      case 272: /* pragmaarg ::= DELETE */ yytestcase(yyruleno==272);
      case 273: /* pragmaarg ::= DEFAULT */ yytestcase(yyruleno==273);
{
  yygotominor.yy148 = sqlite4ExprListAppend(pParse, 0, sqlite4PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0)); 
}
        break;
      case 279: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
{
  Token all;
  all.z = yymsp[-3].minor.yy0.z;
  all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
  sqlite4FinishTrigger(pParse, yymsp[-1].minor.yy145, &all);
}
        break;
      case 280: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
  sqlite4BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy194, yymsp[-4].minor.yy332.a, yymsp[-4].minor.yy332.b, yymsp[-2].minor.yy185, yymsp[0].minor.yy72, yymsp[-10].minor.yy194, yymsp[-8].minor.yy194);
  yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0);
}
        break;
      case 281: /* trigger_time ::= BEFORE */
      case 284: /* trigger_time ::= */ yytestcase(yyruleno==284);
{ yygotominor.yy194 = TK_BEFORE; }
        break;
      case 282: /* trigger_time ::= AFTER */
{ yygotominor.yy194 = TK_AFTER;  }
        break;
      case 283: /* trigger_time ::= INSTEAD OF */
{ yygotominor.yy194 = TK_INSTEAD;}
        break;
      case 285: /* trigger_event ::= DELETE|INSERT */
      case 286: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==286);
{yygotominor.yy332.a = yymsp[0].major; yygotominor.yy332.b = 0;}
        break;
      case 287: /* trigger_event ::= UPDATE OF inscollist */
{yygotominor.yy332.a = TK_UPDATE; yygotominor.yy332.b = yymsp[0].minor.yy254;}
        break;
      case 290: /* when_clause ::= */
      case 312: /* key_opt ::= */ yytestcase(yyruleno==312);
{ yygotominor.yy72 = 0; }
        break;
      case 291: /* when_clause ::= WHEN expr */
      case 313: /* key_opt ::= KEY expr */ yytestcase(yyruleno==313);
{ yygotominor.yy72 = yymsp[0].minor.yy190.pExpr; }
        break;
      case 292: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
  assert( yymsp[-2].minor.yy145!=0 );
  yymsp[-2].minor.yy145->pLast->pNext = yymsp[-1].minor.yy145;
  yymsp[-2].minor.yy145->pLast = yymsp[-1].minor.yy145;
  yygotominor.yy145 = yymsp[-2].minor.yy145;
}
        break;
      case 293: /* trigger_cmd_list ::= trigger_cmd SEMI */
{ 
  assert( yymsp[-1].minor.yy145!=0 );
  yymsp[-1].minor.yy145->pLast = yymsp[-1].minor.yy145;
  yygotominor.yy145 = yymsp[-1].minor.yy145;
}
        break;
      case 295: /* trnm ::= nm DOT nm */
{
  yygotominor.yy0 = yymsp[0].minor.yy0;
  sqlite4ErrorMsg(pParse, 
        "qualified table names are not allowed on INSERT, UPDATE, and DELETE "
        "statements within triggers");
}
        break;
      case 297: /* tridxby ::= INDEXED BY nm */
{
  sqlite4ErrorMsg(pParse,
        "the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
        break;
      case 298: /* tridxby ::= NOT INDEXED */
{
  sqlite4ErrorMsg(pParse,
        "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
        "within triggers");
}
        break;
      case 299: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */
{ yygotominor.yy145 = sqlite4TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy148, yymsp[0].minor.yy72, yymsp[-5].minor.yy234); }
        break;
      case 300: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */
{yygotominor.yy145 = sqlite4TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, yymsp[0].minor.yy167.pList, yymsp[0].minor.yy167.pSelect, yymsp[-4].minor.yy234);}
        break;
      case 301: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */
{yygotominor.yy145 = sqlite4TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy254, 0, yymsp[0].minor.yy243, yymsp[-4].minor.yy234);}
        break;
      case 302: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */
{yygotominor.yy145 = sqlite4TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy72);}
        break;
      case 303: /* trigger_cmd ::= select */
{yygotominor.yy145 = sqlite4TriggerSelectStep(pParse->db, yymsp[0].minor.yy243); }
        break;
      case 304: /* expr ::= RAISE LP IGNORE RP */
{
  yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_RAISE, 0, 0, 0); 
  if( yygotominor.yy190.pExpr ){
    yygotominor.yy190.pExpr->affinity = OE_Ignore;
  }
  yygotominor.yy190.zStart = yymsp[-3].minor.yy0.z;
  yygotominor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 305: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
  yygotominor.yy190.pExpr = sqlite4PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); 
  if( yygotominor.yy190.pExpr ) {
    yygotominor.yy190.pExpr->affinity = (char)yymsp[-3].minor.yy194;
  }
  yygotominor.yy190.zStart = yymsp[-5].minor.yy0.z;
  yygotominor.yy190.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
        break;
      case 306: /* raisetype ::= ROLLBACK */
{yygotominor.yy194 = OE_Rollback;}
        break;
      case 308: /* raisetype ::= FAIL */
{yygotominor.yy194 = OE_Fail;}
        break;
      case 309: /* cmd ::= DROP TRIGGER ifexists fullname */
{
  sqlite4DropTrigger(pParse,yymsp[0].minor.yy185,yymsp[-1].minor.yy194);
}
        break;
      case 310: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
  sqlite4Attach(pParse, yymsp[-3].minor.yy190.pExpr, yymsp[-1].minor.yy190.pExpr, yymsp[0].minor.yy72);
}
        break;
      case 311: /* cmd ::= DETACH database_kw_opt expr */
{
  sqlite4Detach(pParse, yymsp[0].minor.yy190.pExpr);
}
        break;
      case 316: /* cmd ::= REINDEX */
{sqlite4Reindex(pParse, 0, 0);}
        break;
      case 317: /* cmd ::= REINDEX nm dbnm */
{sqlite4Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
        break;
      case 318: /* cmd ::= ANALYZE */
{sqlite4Analyze(pParse, 0, 0);}
        break;
      case 319: /* cmd ::= ANALYZE nm dbnm */
{sqlite4Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
        break;
      case 320: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
  sqlite4AlterRenameTable(pParse,yymsp[-3].minor.yy185,&yymsp[0].minor.yy0);
}
        break;
      case 321: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */
{
  sqlite4AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0);
}
        break;
      case 322: /* add_column_fullname ::= fullname */
{
  pParse->db->lookaside.bEnabled = 0;
  sqlite4AlterBeginAddColumn(pParse, yymsp[0].minor.yy185);
}
        break;
      default:
      /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
      /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
      /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
      /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);
      /* (4) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==4);
      /* (10) trans_opt ::= */ yytestcase(yyruleno==10);
      /* (11) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==11);
      /* (12) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==12);
      /* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20);
      /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
      /* (25) cmd ::= create_table create_table_args */ yytestcase(yyruleno==25);
      /* (34) columnlist ::= columnlist COMMA column */ yytestcase(yyruleno==34);
      /* (35) columnlist ::= column */ yytestcase(yyruleno==35);
      /* (44) type ::= */ yytestcase(yyruleno==44);
      /* (51) signed ::= plus_num */ yytestcase(yyruleno==51);
      /* (52) signed ::= minus_num */ yytestcase(yyruleno==52);
      /* (53) carglist ::= carglist carg */ yytestcase(yyruleno==53);
      /* (54) carglist ::= */ yytestcase(yyruleno==54);
      /* (55) carg ::= CONSTRAINT nm ccons */ yytestcase(yyruleno==55);
      /* (56) carg ::= ccons */ yytestcase(yyruleno==56);
      /* (62) ccons ::= NULL onconf */ yytestcase(yyruleno==62);
      /* (90) conslist ::= conslist COMMA tcons */ yytestcase(yyruleno==90);
      /* (91) conslist ::= conslist tcons */ yytestcase(yyruleno==91);
      /* (92) conslist ::= tcons */ yytestcase(yyruleno==92);
      /* (93) tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93);
      /* (277) plus_opt ::= PLUS */ yytestcase(yyruleno==277);
      /* (278) plus_opt ::= */ yytestcase(yyruleno==278);
      /* (288) foreach_clause ::= */ yytestcase(yyruleno==288);
      /* (289) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==289);
      /* (296) tridxby ::= */ yytestcase(yyruleno==296);
      /* (314) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==314);
      /* (315) database_kw_opt ::= */ yytestcase(yyruleno==315);
      /* (323) kwcolumn_opt ::= */ yytestcase(yyruleno==323);
      /* (324) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==324);
        break;
  };
  yygoto = yyRuleInfo[yyruleno].lhs;
  yysize = yyRuleInfo[yyruleno].nrhs;
  yypParser->yyidx -= yysize;
  yyact = yy_find_reduce_action(yymsp[-yysize].stateno,(YYCODETYPE)yygoto);
  if( yyact < YYNSTATE ){
#ifdef NDEBUG
    /* If we are not debugging and the reduce action popped at least
    ** one element off the stack, then we can push the new element back
    ** onto the stack here, and skip the stack overflow test in yy_shift().
    ** That gives a significant speed improvement. */
    if( yysize ){
      yypParser->yyidx++;
      yymsp -= yysize-1;
      yymsp->stateno = (YYACTIONTYPE)yyact;
      yymsp->major = (YYCODETYPE)yygoto;
      yymsp->minor = yygotominor;
    }else
#endif
    {
      yy_shift(yypParser,yyact,yygoto,&yygotominor);
    }
  }else{
    assert( yyact == YYNSTATE + YYNRULE + 1 );
    yy_accept(yypParser);
  }
}

/*
** The following code executes when the parse fails
*/
#ifndef YYNOERRORRECOVERY
static void yy_parse_failed(
  yyParser *yypParser           /* The parser */
){
  sqlite4ParserARG_FETCH;
#ifndef NDEBUG
  if( yyTraceFILE ){
    fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
  }
#endif
  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
  /* Here code is inserted which will be executed whenever the
  ** parser fails */
  sqlite4ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}
#endif /* YYNOERRORRECOVERY */

/*
** The following code executes when a syntax error first occurs.
*/
static void yy_syntax_error(
  yyParser *yypParser,           /* The parser */
  int yymajor,                   /* The major type of the error token */
  YYMINORTYPE yyminor            /* The minor type of the error token */
){
  sqlite4ParserARG_FETCH;
#define TOKEN (yyminor.yy0)

  UNUSED_PARAMETER(yymajor);  /* Silence some compiler warnings */
  assert( TOKEN.z[0] );  /* The tokenizer always gives us a token */
  sqlite4ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
  sqlite4ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}

/*
** The following is executed when the parser accepts
*/
static void yy_accept(
  yyParser *yypParser           /* The parser */
){
  sqlite4ParserARG_FETCH;
#ifndef NDEBUG
  if( yyTraceFILE ){
    fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
  }
#endif
  while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
  /* Here code is inserted which will be executed whenever the
  ** parser accepts */
  sqlite4ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */
}

/* The main parser program.
** The first argument is a pointer to a structure obtained from
** "sqlite4ParserAlloc" which describes the current state of the parser.
** The second argument is the major token number.  The third is
** the minor token.  The fourth optional argument is whatever the
** user wants (and specified in the grammar) and is available for
** use by the action routines.
**
** Inputs:
** <ul>
** <li> A pointer to the parser (an opaque structure.)
** <li> The major token number.
** <li> The minor token number.
** <li> An option argument of a grammar-specified type.
** </ul>
**
** Outputs:
** None.
*/
SQLITE4_PRIVATE void sqlite4Parser(
  void *yyp,                   /* The parser */
  int yymajor,                 /* The major token code number */
  sqlite4ParserTOKENTYPE yyminor       /* The value for the token */
  sqlite4ParserARG_PDECL               /* Optional %extra_argument parameter */
){
  YYMINORTYPE yyminorunion;
  int yyact;            /* The parser action. */
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
  int yyendofinput;     /* True if we are at the end of input */
#endif
#ifdef YYERRORSYMBOL
  int yyerrorhit = 0;   /* True if yymajor has invoked an error */
#endif
  yyParser *yypParser;  /* The parser */

  /* (re)initialize the parser, if necessary */
  yypParser = (yyParser*)yyp;
  if( yypParser->yyidx<0 ){
#if YYSTACKDEPTH<=0
    if( yypParser->yystksz <=0 ){
      /*memset(&yyminorunion, 0, sizeof(yyminorunion));*/
      yyminorunion = yyzerominor;
      yyStackOverflow(yypParser, &yyminorunion);
      return;
    }
#endif
    yypParser->yyidx = 0;
    yypParser->yyerrcnt = -1;
    yypParser->yystack[0].stateno = 0;
    yypParser->yystack[0].major = 0;
  }
  yyminorunion.yy0 = yyminor;
#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
  yyendofinput = (yymajor==0);
#endif
  sqlite4ParserARG_STORE;

#ifndef NDEBUG
  if( yyTraceFILE ){
    fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
  }
#endif

  do{
    yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor);
    if( yyact<YYNSTATE ){
      yy_shift(yypParser,yyact,yymajor,&yyminorunion);
      yypParser->yyerrcnt--;
      yymajor = YYNOCODE;
    }else if( yyact < YYNSTATE + YYNRULE ){
      yy_reduce(yypParser,yyact-YYNSTATE);
    }else{
      assert( yyact == YY_ERROR_ACTION );
#ifdef YYERRORSYMBOL
      int yymx;
#endif
#ifndef NDEBUG
      if( yyTraceFILE ){
        fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
      }
#endif
#ifdef YYERRORSYMBOL
      /* A syntax error has occurred.
      ** The response to an error depends upon whether or not the
      ** grammar defines an error token "ERROR".  
      **
      ** This is what we do if the grammar does define ERROR:
      **
      **  * Call the %syntax_error function.
      **
      **  * Begin popping the stack until we enter a state where
      **    it is legal to shift the error symbol, then shift
      **    the error symbol.
      **
      **  * Set the error count to three.
      **
      **  * Begin accepting and shifting new tokens.  No new error
      **    processing will occur until three tokens have been
      **    shifted successfully.
      **
      */
      if( yypParser->yyerrcnt<0 ){
        yy_syntax_error(yypParser,yymajor,yyminorunion);
      }
      yymx = yypParser->yystack[yypParser->yyidx].major;
      if( yymx==YYERRORSYMBOL || yyerrorhit ){
#ifndef NDEBUG
        if( yyTraceFILE ){
          fprintf(yyTraceFILE,"%sDiscard input token %s\n",
             yyTracePrompt,yyTokenName[yymajor]);
        }
#endif
        yy_destructor(yypParser, (YYCODETYPE)yymajor,&yyminorunion);
        yymajor = YYNOCODE;
      }else{
         while(
          yypParser->yyidx >= 0 &&
          yymx != YYERRORSYMBOL &&
          (yyact = yy_find_reduce_action(
                        yypParser->yystack[yypParser->yyidx].stateno,
                        YYERRORSYMBOL)) >= YYNSTATE
        ){
          yy_pop_parser_stack(yypParser);
        }
        if( yypParser->yyidx < 0 || yymajor==0 ){
          yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
          yy_parse_failed(yypParser);
          yymajor = YYNOCODE;
        }else if( yymx!=YYERRORSYMBOL ){
          YYMINORTYPE u2;
          u2.YYERRSYMDT = 0;
          yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
        }
      }
      yypParser->yyerrcnt = 3;
      yyerrorhit = 1;
#elif defined(YYNOERRORRECOVERY)
      /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
      ** do any kind of error recovery.  Instead, simply invoke the syntax
      ** error routine and continue going as if nothing had happened.
      **
      ** Applications can set this macro (for example inside %include) if
      ** they intend to abandon the parse upon the first syntax error seen.
      */
      yy_syntax_error(yypParser,yymajor,yyminorunion);
      yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
      yymajor = YYNOCODE;
      
#else  /* YYERRORSYMBOL is not defined */
      /* This is what we do if the grammar does not define ERROR:
      **
      **  * Report an error message, and throw away the input token.
      **
      **  * If the input token is $, then fail the parse.
      **
      ** As before, subsequent error messages are suppressed until
      ** three input tokens have been successfully shifted.
      */
      if( yypParser->yyerrcnt<=0 ){
        yy_syntax_error(yypParser,yymajor,yyminorunion);
      }
      yypParser->yyerrcnt = 3;
      yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
      if( yyendofinput ){
        yy_parse_failed(yypParser);
      }
      yymajor = YYNOCODE;
#endif
    }
  }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
  return;
}

/************** End of parse.c ***********************************************/
/************** Begin file tokenize.c ****************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** 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
** lower-case ASCII equivalent.  On ASCII machines, this is just
** an upper-to-lower case map.  On EBCDIC machines we also need
** to adjust the encoding.  Only alphabetic characters and underscores
** need to be translated.
*/
#ifdef SQLITE4_ASCII
# define charMap(X) sqlite4UpperToLower[(unsigned char)X]
#endif
#ifdef SQLITE4_EBCDIC
# define charMap(X) ebcdicToAscii[(unsigned char)X]
const unsigned char ebcdicToAscii[] = {
/* 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 0x */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 1x */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 2x */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 3x */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 4x */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 5x */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 95,  0,  0,  /* 6x */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 7x */
   0, 97, 98, 99,100,101,102,103,104,105,  0,  0,  0,  0,  0,  0,  /* 8x */
   0,106,107,108,109,110,111,112,113,114,  0,  0,  0,  0,  0,  0,  /* 9x */
   0,  0,115,116,117,118,119,120,121,122,  0,  0,  0,  0,  0,  0,  /* Ax */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* Bx */
   0, 97, 98, 99,100,101,102,103,104,105,  0,  0,  0,  0,  0,  0,  /* Cx */
   0,106,107,108,109,110,111,112,113,114,  0,  0,  0,  0,  0,  0,  /* Dx */
   0,  0,115,116,117,118,119,120,121,122,  0,  0,  0,  0,  0,  0,  /* Ex */
   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* Fx */
};
#endif

/*
** The sqlite4KeywordCode function looks up an identifier to determine if
** it is a keyword.  If it is a keyword, the token code of that keyword is 
** returned.  If the input is not a keyword, TK_ID is returned.
**
** The implementation of this routine was generated by a program,
** mkkeywordhash.h, located in the tool subdirectory of the distribution.
** The output of the mkkeywordhash.c program is written into a file
** named keywordhash.h and then included into this source file by
** the #include below.
*/
/************** Include keywordhash.h in the middle of tokenize.c ************/
/************** Begin file keywordhash.h *************************************/
/***** This file contains automatically generated code ******
**
** The code in this file has been automatically generated by
**
**   sqlite/tool/mkkeywordhash.c
**
** The code in this file implements a function that determines whether
** or not a given identifier is really an SQL keyword.  The same thing
** might be implemented more directly using a hand-written hash table.
** But by using this automatically generated code, the size of the code
** is substantially reduced.  This is important for embedded applications
** on platforms with limited memory.
*/
/* Hash score: 166 */
static int keywordCode(const char *z, int n){
  /* zText[] encodes 805 bytes of keywords in 535 bytes */
  /*   REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT       */
  /*   ABLEFTHENDEFERRABLELSEXCEPTRANSACTIONATURALTERAISEXCLUSIVE         */
  /*   XISTSAVEPOINTERSECTRIGGEREFERENCESCONSTRAINTOFFSETEMPORARY         */
  /*   UNIQUERYATTACHAVINGROUPDATEBEGINNERELEASEBETWEENOTNULLIKE          */
  /*   CASCADELETECASECOLLATECREATECURRENT_DATEDETACHIMMEDIATEJOIN        */
  /*   SERTMATCHPLANALYZEPRAGMABORTVALUESWHENWHERENAMEAFTEREPLACEAND      */
  /*   EFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCOVERINGLOBYCROSS       */
  /*   CURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILIMITFROMFULLIF       */
  /*   ISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVIEWINITIALLY      */
  static const char zText[534] = {
    'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
    'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
    'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
    'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F',
    'E','R','R','A','B','L','E','L','S','E','X','C','E','P','T','R','A','N',
    'S','A','C','T','I','O','N','A','T','U','R','A','L','T','E','R','A','I',
    'S','E','X','C','L','U','S','I','V','E','X','I','S','T','S','A','V','E',
    'P','O','I','N','T','E','R','S','E','C','T','R','I','G','G','E','R','E',
    'F','E','R','E','N','C','E','S','C','O','N','S','T','R','A','I','N','T',
    'O','F','F','S','E','T','E','M','P','O','R','A','R','Y','U','N','I','Q',
    'U','E','R','Y','A','T','T','A','C','H','A','V','I','N','G','R','O','U',
    'P','D','A','T','E','B','E','G','I','N','N','E','R','E','L','E','A','S',
    'E','B','E','T','W','E','E','N','O','T','N','U','L','L','I','K','E','C',
    'A','S','C','A','D','E','L','E','T','E','C','A','S','E','C','O','L','L',
    'A','T','E','C','R','E','A','T','E','C','U','R','R','E','N','T','_','D',
    'A','T','E','D','E','T','A','C','H','I','M','M','E','D','I','A','T','E',
    'J','O','I','N','S','E','R','T','M','A','T','C','H','P','L','A','N','A',
    'L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','V','A','L','U',
    'E','S','W','H','E','N','W','H','E','R','E','N','A','M','E','A','F','T',
    'E','R','E','P','L','A','C','E','A','N','D','E','F','A','U','L','T','A',
    'U','T','O','I','N','C','R','E','M','E','N','T','C','A','S','T','C','O',
    'L','U','M','N','C','O','M','M','I','T','C','O','N','F','L','I','C','T',
    'C','O','V','E','R','I','N','G','L','O','B','Y','C','R','O','S','S','C',
    'U','R','R','E','N','T','_','T','I','M','E','S','T','A','M','P','R','I',
    'M','A','R','Y','D','E','F','E','R','R','E','D','I','S','T','I','N','C',
    'T','D','R','O','P','F','A','I','L','I','M','I','T','F','R','O','M','F',
    'U','L','L','I','F','I','S','N','U','L','L','O','R','D','E','R','E','S',
    'T','R','I','C','T','O','U','T','E','R','I','G','H','T','R','O','L','L',
    'B','A','C','K','R','O','W','U','N','I','O','N','U','S','I','N','G','V',
    'I','E','W','I','N','I','T','I','A','L','L','Y',
  };
  static const unsigned char aHash[127] = {
      72, 102, 114,  70,   0,  45,   0,   0,  78,   0,  73,   0,   0,
      42,  12,  74,  15,   0, 113,  79,  50, 108,   0,  19,   0,   0,
      35,   0, 116, 111,   0,  22,  87,   0,   9,   0,   0,  66,  67,
       0,  65,   6,   0,  48,  84,  99,   0, 115,  98,   0,  93,  44,
       0, 100,  24,   0,  17,   0, 118,  49,  23,   0,   5,  94,  25,
      90,   0,   0, 120, 103,  56, 119,  53,  28,  51,   0,  85,   0,
      97,  26,   0,  96,   0,   0,   0,  89,  86,  91,  82, 107,  14,
      39, 106,   0,  77,   0,  18,  83,  95,  32,   0, 117,  76, 109,
      58,  46, 105,   0,   0,  88,  40,   0, 112,   0,  36,   0,   0,
      29,   0,  80,  59,  60,   0,  20,  57,   0,  52,
  };
  static const unsigned char aNext[120] = {
       0,   0,   0,   0,   4,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   2,   0,   0,   0,   0,   0,   0,  13,   0,   0,   0,   0,
       0,   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,   0,  33,   0,  21,   0,   0,   0,  43,   3,  47,
       0,   0,   0,   0,  30,   0,  54,   0,  38,   0,   0,   0,   1,
      62,   0,   0,  63,   0,  41,   0,   0,   0,   0,   0,   0,   0,
       0,   0,   0,  31,  55,  16,  34,  10,   0,   0,   0,   0,   0,
       0,   0,   0,  81,   0,  11,  68,  75,   0,   8,   0, 101,  92,
       0,   0, 104,   0,  71,   0,   0, 110,  27,  37,  69,  61,   0,
      64,   0,   0,
  };
  static const unsigned char aLen[120] = {
       7,   7,   5,   4,   6,   4,   5,   3,   6,   7,   3,   6,   6,
       7,   7,   3,   8,   2,   6,   5,   4,   4,   3,  10,   4,   6,
      11,   6,   2,   7,   5,   5,   9,   6,   9,   9,   7,  10,  10,
       4,   6,   2,   3,   9,   4,   2,   6,   5,   6,   6,   5,   6,
       5,   5,   7,   7,   7,   3,   2,   4,   4,   7,   3,   6,   4,
       7,   6,  12,   6,   9,   4,   6,   5,   4,   7,   6,   5,   6,
       4,   5,   6,   5,   7,   3,   7,  13,   2,   2,   4,   6,   6,
       8,   8,   4,   2,   5,  17,  12,   7,   8,   8,   2,   4,   4,
       5,   4,   4,   2,   6,   5,   8,   5,   5,   8,   3,   5,   5,
       4,   9,   3,
  };
  static const unsigned short int aOffset[120] = {
       0,   2,   2,   8,   9,  14,  16,  20,  23,  25,  25,  29,  33,
      36,  41,  46,  48,  53,  54,  59,  62,  65,  67,  69,  78,  81,
      86,  91,  95,  96, 101, 105, 109, 117, 122, 128, 136, 142, 152,
     159, 162, 162, 165, 167, 167, 171, 176, 179, 184, 189, 194, 197,
     203, 206, 210, 217, 223, 223, 223, 226, 229, 233, 234, 238, 244,
     248, 255, 261, 273, 279, 288, 290, 296, 301, 303, 310, 315, 320,
     326, 330, 333, 339, 343, 350, 352, 359, 361, 363, 372, 376, 382,
     388, 396, 403, 406, 408, 413, 413, 429, 436, 443, 444, 451, 455,
     458, 463, 467, 471, 473, 479, 483, 491, 495, 500, 508, 511, 516,
     521, 525, 530,
  };
  static const unsigned char aCode[120] = {
    TK_REINDEX,    TK_INDEXED,    TK_INDEX,      TK_DESC,       TK_ESCAPE,     
    TK_EACH,       TK_CHECK,      TK_KEY,        TK_BEFORE,     TK_FOREIGN,    
    TK_FOR,        TK_IGNORE,     TK_LIKE_KW,    TK_EXPLAIN,    TK_INSTEAD,    
    TK_ADD,        TK_DATABASE,   TK_AS,         TK_SELECT,     TK_TABLE,      
    TK_JOIN_KW,    TK_THEN,       TK_END,        TK_DEFERRABLE, TK_ELSE,       
    TK_EXCEPT,     TK_TRANSACTION,TK_ACTION,     TK_ON,         TK_JOIN_KW,    
    TK_ALTER,      TK_RAISE,      TK_EXCLUSIVE,  TK_EXISTS,     TK_SAVEPOINT,  
    TK_INTERSECT,  TK_TRIGGER,    TK_REFERENCES, TK_CONSTRAINT, TK_INTO,       
    TK_OFFSET,     TK_OF,         TK_SET,        TK_TEMP,       TK_TEMP,       
    TK_OR,         TK_UNIQUE,     TK_QUERY,      TK_ATTACH,     TK_HAVING,     
    TK_GROUP,      TK_UPDATE,     TK_BEGIN,      TK_JOIN_KW,    TK_RELEASE,    
    TK_BETWEEN,    TK_NOTNULL,    TK_NOT,        TK_NO,         TK_NULL,       
    TK_LIKE_KW,    TK_CASCADE,    TK_ASC,        TK_DELETE,     TK_CASE,       
    TK_COLLATE,    TK_CREATE,     TK_CTIME_KW,   TK_DETACH,     TK_IMMEDIATE,  
    TK_JOIN,       TK_INSERT,     TK_MATCH,      TK_PLAN,       TK_ANALYZE,    
    TK_PRAGMA,     TK_ABORT,      TK_VALUES,     TK_WHEN,       TK_WHERE,      
    TK_RENAME,     TK_AFTER,      TK_REPLACE,    TK_AND,        TK_DEFAULT,    
    TK_AUTOINCR,   TK_TO,         TK_IN,         TK_CAST,       TK_COLUMNKW,   
    TK_COMMIT,     TK_CONFLICT,   TK_COVERING,   TK_LIKE_KW,    TK_BY,         
    TK_JOIN_KW,    TK_CTIME_KW,   TK_CTIME_KW,   TK_PRIMARY,    TK_DEFERRED,   
    TK_DISTINCT,   TK_IS,         TK_DROP,       TK_FAIL,       TK_LIMIT,      
    TK_FROM,       TK_JOIN_KW,    TK_IF,         TK_ISNULL,     TK_ORDER,      
    TK_RESTRICT,   TK_JOIN_KW,    TK_JOIN_KW,    TK_ROLLBACK,   TK_ROW,        
    TK_UNION,      TK_USING,      TK_VIEW,       TK_INITIALLY,  TK_ALL,        
  };
  int h, i;
  if( n<2 ) return TK_ID;
  h = ((charMap(z[0])*4) ^
      (charMap(z[n-1])*3) ^
      n) % 127;
  for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){
    if( aLen[i]==n && sqlite4_strnicmp(&zText[aOffset[i]],z,n)==0 ){
      testcase( i==0 ); /* REINDEX */
      testcase( i==1 ); /* INDEXED */
      testcase( i==2 ); /* INDEX */
      testcase( i==3 ); /* DESC */
      testcase( i==4 ); /* ESCAPE */
      testcase( i==5 ); /* EACH */
      testcase( i==6 ); /* CHECK */
      testcase( i==7 ); /* KEY */
      testcase( i==8 ); /* BEFORE */
      testcase( i==9 ); /* FOREIGN */
      testcase( i==10 ); /* FOR */
      testcase( i==11 ); /* IGNORE */
      testcase( i==12 ); /* REGEXP */
      testcase( i==13 ); /* EXPLAIN */
      testcase( i==14 ); /* INSTEAD */
      testcase( i==15 ); /* ADD */
      testcase( i==16 ); /* DATABASE */
      testcase( i==17 ); /* AS */
      testcase( i==18 ); /* SELECT */
      testcase( i==19 ); /* TABLE */
      testcase( i==20 ); /* LEFT */
      testcase( i==21 ); /* THEN */
      testcase( i==22 ); /* END */
      testcase( i==23 ); /* DEFERRABLE */
      testcase( i==24 ); /* ELSE */
      testcase( i==25 ); /* EXCEPT */
      testcase( i==26 ); /* TRANSACTION */
      testcase( i==27 ); /* ACTION */
      testcase( i==28 ); /* ON */
      testcase( i==29 ); /* NATURAL */
      testcase( i==30 ); /* ALTER */
      testcase( i==31 ); /* RAISE */
      testcase( i==32 ); /* EXCLUSIVE */
      testcase( i==33 ); /* EXISTS */
      testcase( i==34 ); /* SAVEPOINT */
      testcase( i==35 ); /* INTERSECT */
      testcase( i==36 ); /* TRIGGER */
      testcase( i==37 ); /* REFERENCES */
      testcase( i==38 ); /* CONSTRAINT */
      testcase( i==39 ); /* INTO */
      testcase( i==40 ); /* OFFSET */
      testcase( i==41 ); /* OF */
      testcase( i==42 ); /* SET */
      testcase( i==43 ); /* TEMPORARY */
      testcase( i==44 ); /* TEMP */
      testcase( i==45 ); /* OR */
      testcase( i==46 ); /* UNIQUE */
      testcase( i==47 ); /* QUERY */
      testcase( i==48 ); /* ATTACH */
      testcase( i==49 ); /* HAVING */
      testcase( i==50 ); /* GROUP */
      testcase( i==51 ); /* UPDATE */
      testcase( i==52 ); /* BEGIN */
      testcase( i==53 ); /* INNER */
      testcase( i==54 ); /* RELEASE */
      testcase( i==55 ); /* BETWEEN */
      testcase( i==56 ); /* NOTNULL */
      testcase( i==57 ); /* NOT */
      testcase( i==58 ); /* NO */
      testcase( i==59 ); /* NULL */
      testcase( i==60 ); /* LIKE */
      testcase( i==61 ); /* CASCADE */
      testcase( i==62 ); /* ASC */
      testcase( i==63 ); /* DELETE */
      testcase( i==64 ); /* CASE */
      testcase( i==65 ); /* COLLATE */
      testcase( i==66 ); /* CREATE */
      testcase( i==67 ); /* CURRENT_DATE */
      testcase( i==68 ); /* DETACH */
      testcase( i==69 ); /* IMMEDIATE */
      testcase( i==70 ); /* JOIN */
      testcase( i==71 ); /* INSERT */
      testcase( i==72 ); /* MATCH */
      testcase( i==73 ); /* PLAN */
      testcase( i==74 ); /* ANALYZE */
      testcase( i==75 ); /* PRAGMA */
      testcase( i==76 ); /* ABORT */
      testcase( i==77 ); /* VALUES */
      testcase( i==78 ); /* WHEN */
      testcase( i==79 ); /* WHERE */
      testcase( i==80 ); /* RENAME */
      testcase( i==81 ); /* AFTER */
      testcase( i==82 ); /* REPLACE */
      testcase( i==83 ); /* AND */
      testcase( i==84 ); /* DEFAULT */
      testcase( i==85 ); /* AUTOINCREMENT */
      testcase( i==86 ); /* TO */
      testcase( i==87 ); /* IN */
      testcase( i==88 ); /* CAST */
      testcase( i==89 ); /* COLUMN */
      testcase( i==90 ); /* COMMIT */
      testcase( i==91 ); /* CONFLICT */
      testcase( i==92 ); /* COVERING */
      testcase( i==93 ); /* GLOB */
      testcase( i==94 ); /* BY */
      testcase( i==95 ); /* CROSS */
      testcase( i==96 ); /* CURRENT_TIMESTAMP */
      testcase( i==97 ); /* CURRENT_TIME */
      testcase( i==98 ); /* PRIMARY */
      testcase( i==99 ); /* DEFERRED */
      testcase( i==100 ); /* DISTINCT */
      testcase( i==101 ); /* IS */
      testcase( i==102 ); /* DROP */
      testcase( i==103 ); /* FAIL */
      testcase( i==104 ); /* LIMIT */
      testcase( i==105 ); /* FROM */
      testcase( i==106 ); /* FULL */
      testcase( i==107 ); /* IF */
      testcase( i==108 ); /* ISNULL */
      testcase( i==109 ); /* ORDER */
      testcase( i==110 ); /* RESTRICT */
      testcase( i==111 ); /* OUTER */
      testcase( i==112 ); /* RIGHT */
      testcase( i==113 ); /* ROLLBACK */
      testcase( i==114 ); /* ROW */
      testcase( i==115 ); /* UNION */
      testcase( i==116 ); /* USING */
      testcase( i==117 ); /* VIEW */
      testcase( i==118 ); /* INITIALLY */
      testcase( i==119 ); /* ALL */
      return aCode[i];
    }
  }
  return TK_ID;
}
SQLITE4_PRIVATE int sqlite4KeywordCode(const unsigned char *z, int n){
  return keywordCode((char*)z, n);
}
#define SQLITE4_N_KEYWORD 120

/************** End of keywordhash.h *****************************************/
/************** Continuing where we left off in tokenize.c *******************/


/*
** If X is a character that can be used in an identifier then
** IdChar(X) will be true.  Otherwise it is false.
**
** For ASCII, any character with the high-order bit set is
** allowed in an identifier.  For 7-bit characters, 
** sqlite4IsIdChar[X] must be 1.
**
** For EBCDIC, the rules are more complex but have the same
** end result.
**
** Ticket #1066.  the SQL standard does not allow '$' in the
** middle of identfiers.  But many SQL implementations do. 
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
#ifdef SQLITE4_ASCII
#define IdChar(C)  ((sqlite4CtypeMap[(unsigned char)C]&0x46)!=0)
#endif
#ifdef SQLITE4_EBCDIC
SQLITE4_PRIVATE const char sqlite4IsEbcdicIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 4x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0,  /* 5x */
    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,  /* 6x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,  /* 7x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0,  /* 8x */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0,  /* 9x */
    1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0,  /* Ax */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* Bx */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,  /* Cx */
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,  /* Dx */
    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,  /* Ex */
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0,  /* Fx */
};
#define IdChar(C)  (((c=C)>=0x42 && sqlite4IsEbcdicIdChar[c-0x40]))
#endif


/*
** Return the length of the token that begins at z[0]. 
** Store the token type in *tokenType before returning.
*/
SQLITE4_PRIVATE int sqlite4GetToken(const unsigned char *z, int *tokenType){
  int i, c;
  switch( *z ){
    case ' ': case '\t': case '\n': case '\f': case '\r': {
      testcase( z[0]==' ' );
      testcase( z[0]=='\t' );
      testcase( z[0]=='\n' );
      testcase( z[0]=='\f' );
      testcase( z[0]=='\r' );
      for(i=1; sqlite4Isspace(z[i]); i++){}
      *tokenType = TK_SPACE;
      return i;
    }
    case '-': {
      if( z[1]=='-' ){
        /* IMP: R-50417-27976 -- syntax diagram for comments */
        for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
        *tokenType = TK_SPACE;   /* IMP: R-22934-25134 */
        return i;
      }
      *tokenType = TK_MINUS;
      return 1;
    }
    case '(': {
      *tokenType = TK_LP;
      return 1;
    }
    case ')': {
      *tokenType = TK_RP;
      return 1;
    }
    case ';': {
      *tokenType = TK_SEMI;
      return 1;
    }
    case '+': {
      *tokenType = TK_PLUS;
      return 1;
    }
    case '*': {
      *tokenType = TK_STAR;
      return 1;
    }
    case '/': {
      if( z[1]!='*' || z[2]==0 ){
        *tokenType = TK_SLASH;
        return 1;
      }
      /* IMP: R-50417-27976 -- syntax diagram for comments */
      for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
      if( c ) i++;
      *tokenType = TK_SPACE;   /* IMP: R-22934-25134 */
      return i;
    }
    case '%': {
      *tokenType = TK_REM;
      return 1;
    }
    case '=': {
      *tokenType = TK_EQ;
      return 1 + (z[1]=='=');
    }
    case '<': {
      if( (c=z[1])=='=' ){
        *tokenType = TK_LE;
        return 2;
      }else if( c=='>' ){
        *tokenType = TK_NE;
        return 2;
      }else if( c=='<' ){
        *tokenType = TK_LSHIFT;
        return 2;
      }else{
        *tokenType = TK_LT;
        return 1;
      }
    }
    case '>': {
      if( (c=z[1])=='=' ){
        *tokenType = TK_GE;
        return 2;
      }else if( c=='>' ){
        *tokenType = TK_RSHIFT;
        return 2;
      }else{
        *tokenType = TK_GT;
        return 1;
      }
    }
    case '!': {
      if( z[1]!='=' ){
        *tokenType = TK_ILLEGAL;
        return 2;
      }else{
        *tokenType = TK_NE;
        return 2;
      }
    }
    case '|': {
      if( z[1]!='|' ){
        *tokenType = TK_BITOR;
        return 1;
      }else{
        *tokenType = TK_CONCAT;
        return 2;
      }
    }
    case ',': {
      *tokenType = TK_COMMA;
      return 1;
    }
    case '&': {
      *tokenType = TK_BITAND;
      return 1;
    }
    case '~': {
      *tokenType = TK_BITNOT;
      return 1;
    }
    case '\'':
    case '"': {
      int delim = z[0];
      testcase( delim=='`' );
      testcase( delim=='\'' );
      testcase( delim=='"' );
      for(i=1; (c=z[i])!=0; i++){
        if( c==delim ){
          if( z[i+1]==delim ){
            i++;
          }else{
            break;
          }
        }
      }
      if( c=='\'' ){
        *tokenType = TK_STRING;
        return i+1;
      }else if( c!=0 ){
        *tokenType = TK_ID;
        return i+1;
      }else{
        *tokenType = TK_ILLEGAL;
        return i;
      }
    }
    case '.': {
#ifndef SQLITE4_OMIT_FLOATING_POINT
      if( !sqlite4Isdigit(z[1]) )
#endif
      {
        *tokenType = TK_DOT;
        return 1;
      }
      /* If the next character is a digit, this is a floating point
      ** number that begins with ".".  Fall thru into the next case */
    }
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9': {
      testcase( z[0]=='0' );  testcase( z[0]=='1' );  testcase( z[0]=='2' );
      testcase( z[0]=='3' );  testcase( z[0]=='4' );  testcase( z[0]=='5' );
      testcase( z[0]=='6' );  testcase( z[0]=='7' );  testcase( z[0]=='8' );
      testcase( z[0]=='9' );
      *tokenType = TK_INTEGER;
      for(i=0; sqlite4Isdigit(z[i]); i++){}
#ifndef SQLITE4_OMIT_FLOATING_POINT
      if( z[i]=='.' ){
        i++;
        while( sqlite4Isdigit(z[i]) ){ i++; }
        *tokenType = TK_FLOAT;
      }
      if( (z[i]=='e' || z[i]=='E') &&
           ( sqlite4Isdigit(z[i+1]) 
            || ((z[i+1]=='+' || z[i+1]=='-') && sqlite4Isdigit(z[i+2]))
           )
      ){
        i += 2;
        while( sqlite4Isdigit(z[i]) ){ i++; }
        *tokenType = TK_FLOAT;
      }
#endif
      while( IdChar(z[i]) ){
        *tokenType = TK_ILLEGAL;
        i++;
      }
      return i;
    }
    case '[': {
      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
      *tokenType = c==']' ? TK_ID : TK_ILLEGAL;
      return i;
    }
    case '?': {
      *tokenType = TK_VARIABLE;
      for(i=1; sqlite4Isdigit(z[i]); i++){}
      return i;
    }
    case '#': {
      for(i=1; sqlite4Isdigit(z[i]); i++){}
      if( i>1 ){
        /* Parameters of the form #NNN (where NNN is a number) are used
        ** internally by sqlite4NestedParse.  */
        *tokenType = TK_REGISTER;
        return i;
      }
      /* Fall through into the next case if the '#' is not followed by
      ** a digit. Try to match #AAAA where AAAA is a parameter name. */
    }
#ifndef SQLITE4_OMIT_TCL_VARIABLE
    case '$':
#endif
    case '@':  /* For compatibility with MS SQL Server */
    case ':': {
      int n = 0;
      testcase( z[0]=='$' );  testcase( z[0]=='@' );  testcase( z[0]==':' );
      *tokenType = TK_VARIABLE;
      for(i=1; (c=z[i])!=0; i++){
        if( IdChar(c) ){
          n++;
#ifndef SQLITE4_OMIT_TCL_VARIABLE
        }else if( c=='(' && n>0 ){
          do{
            i++;
          }while( (c=z[i])!=0 && !sqlite4Isspace(c) && c!=')' );
          if( c==')' ){
            i++;
          }else{
            *tokenType = TK_ILLEGAL;
          }
          break;
        }else if( c==':' && z[i+1]==':' ){
          i++;
#endif
        }else{
          break;
        }
      }
      if( n==0 ) *tokenType = TK_ILLEGAL;
      return i;
    }
#ifndef SQLITE4_OMIT_BLOB_LITERAL
    case 'x': case 'X': {
      testcase( z[0]=='x' ); testcase( z[0]=='X' );
      if( z[1]=='\'' ){
        *tokenType = TK_BLOB;
        for(i=2; sqlite4Isxdigit(z[i]); i++){}
        if( z[i]!='\'' || i%2 ){
          *tokenType = TK_ILLEGAL;
          while( z[i] && z[i]!='\'' ){ i++; }
        }
        if( z[i] ) i++;
        return i;
      }
      /* Otherwise fall through to the next case */
    }
#endif
    default: {
      if( !IdChar(*z) ){
        break;
      }
      for(i=1; IdChar(z[i]); i++){}
      *tokenType = keywordCode((char*)z, i);
      return i;
    }
  }
  *tokenType = TK_ILLEGAL;
  return 1;
}

/*
** Run the parser on the given SQL string.  The parser structure is
** passed in.  An SQLITE4_ status code is returned.  If an error occurs
** then an and attempt is made to write an error message into 
** memory obtained from sqlite4_malloc() and to make *pzErrMsg point to that
** error message.
*/
SQLITE4_PRIVATE int sqlite4RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
  int nErr = 0;                   /* Number of errors encountered */
  int i;                          /* Loop counter */
  void *pEngine;                  /* The LEMON-generated LALR(1) parser */
  int tokenType;                  /* type of the next token */
  int lastTokenParsed = -1;       /* type of the previous token */
  u8 enableLookaside;             /* Saved value of db->lookaside.bEnabled */
  sqlite4 *db = pParse->db;       /* The database connection */
  int mxSqlLen;                   /* Max length of an SQL string */


  mxSqlLen = db->aLimit[SQLITE4_LIMIT_SQL_LENGTH];
  if( db->activeVdbeCnt==0 ){
    db->u1.isInterrupted = 0;
  }
  pParse->rc = SQLITE4_OK;
  pParse->zTail = zSql;
  i = 0;
  assert( pzErrMsg!=0 );
  pEngine = sqlite4ParserAlloc((void*(*)(void*,size_t))sqlite4_malloc,db->pEnv);
  if( pEngine==0 ){
    db->mallocFailed = 1;
    return SQLITE4_NOMEM;
  }
  assert( pParse->pNewTable==0 );
  assert( pParse->pNewTrigger==0 );
  assert( pParse->nVar==0 );
  assert( pParse->nzVar==0 );
  assert( pParse->azVar==0 );
  enableLookaside = db->lookaside.bEnabled;
  if( db->lookaside.pStart ) db->lookaside.bEnabled = 1;
  while( !db->mallocFailed && zSql[i]!=0 ){
    assert( i>=0 );
    pParse->sLastToken.z = &zSql[i];
    pParse->sLastToken.n = sqlite4GetToken((unsigned char*)&zSql[i],&tokenType);
    i += pParse->sLastToken.n;
    if( i>mxSqlLen ){
      pParse->rc = SQLITE4_TOOBIG;
      break;
    }
    switch( tokenType ){
      case TK_SPACE: {
        if( db->u1.isInterrupted ){
          sqlite4ErrorMsg(pParse, "interrupt");
          pParse->rc = SQLITE4_INTERRUPT;
          goto abort_parse;
        }
        break;
      }
      case TK_ILLEGAL: {
        sqlite4DbFree(db, *pzErrMsg);
        *pzErrMsg = sqlite4MPrintf(db, "unrecognized token: \"%T\"",
                        &pParse->sLastToken);
        nErr++;
        goto abort_parse;
      }
      case TK_SEMI: {
        pParse->zTail = &zSql[i];
        /* Fall thru into the default case */
      }
      default: {
        sqlite4Parser(pEngine, tokenType, pParse->sLastToken, pParse);
        lastTokenParsed = tokenType;
        if( pParse->rc!=SQLITE4_OK ){
          goto abort_parse;
        }
        break;
      }
    }
  }
abort_parse:
  if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE4_OK ){
    if( lastTokenParsed!=TK_SEMI ){
      sqlite4Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
      pParse->zTail = &zSql[i];
    }
    sqlite4Parser(pEngine, 0, pParse->sLastToken, pParse);
  }
#if YYTRACKMAXSTACKDEPTH
  sqlite4StatusSet(SQLITE4_STATUS_PARSER_STACK,
      sqlite4ParserStackPeak(pEngine)
  );
#endif
  sqlite4ParserFree(pEngine, (void(*)(void*,void*))sqlite4_free);
  db->lookaside.bEnabled = enableLookaside;
  if( db->mallocFailed ){
    pParse->rc = SQLITE4_NOMEM;
  }
  if( pParse->rc!=SQLITE4_OK && pParse->rc!=SQLITE4_DONE && pParse->zErrMsg==0 ){
    sqlite4SetString(&pParse->zErrMsg, db, "%s", sqlite4ErrStr(pParse->rc));
  }
  assert( pzErrMsg!=0 );
  if( pParse->zErrMsg ){
    *pzErrMsg = pParse->zErrMsg;
    sqlite4_log(db->pEnv, pParse->rc, "%s", *pzErrMsg);
    pParse->zErrMsg = 0;
    nErr++;
  }
  if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
    sqlite4VdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
  }
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  sqlite4_free(0, pParse->apVtabLock);
#endif

  if( !IN_DECLARE_VTAB ){
    /* If the pParse->declareVtab flag is set, do not delete any table 
    ** structure built up in pParse->pNewTable. The calling code (see vtab.c)
    ** will take responsibility for freeing the Table structure.
    */
    sqlite4DeleteTable(db, pParse->pNewTable);
  }

  sqlite4DeleteTrigger(db, pParse->pNewTrigger);
  for(i=pParse->nzVar-1; i>=0; i--) sqlite4DbFree(db, pParse->azVar[i]);
  sqlite4DbFree(db, pParse->azVar);
  sqlite4DbFree(db, pParse->aAlias);
  while( pParse->pAinc ){
    AutoincInfo *p = pParse->pAinc;
    pParse->pAinc = p->pNext;
    sqlite4DbFree(db, p);
  }
  while( pParse->pZombieTab ){
    Table *p = pParse->pZombieTab;
    pParse->pZombieTab = p->pNextZombie;
    sqlite4DeleteTable(db, p);
  }
  if( nErr>0 && pParse->rc==SQLITE4_OK ){
    pParse->rc = SQLITE4_ERROR;
  }
  return nErr;
}

/************** End of tokenize.c ********************************************/
/************** Begin file complete.c ****************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that implements the sqlite4_complete() API.
** This code used to be part of the tokenizer.c source file.  But by
** separating it out, the code will be automatically omitted from
** static links that do not use it.
*/
#ifndef SQLITE4_OMIT_COMPLETE

/*
** This is defined in tokenize.c.  We just have to import the definition.
*/
#ifndef SQLITE4_AMALGAMATION
#ifdef SQLITE4_ASCII
#define IdChar(C)  ((sqlite4CtypeMap[(unsigned char)C]&0x46)!=0)
#endif
#ifdef SQLITE4_EBCDIC
SQLITE4_PRIVATE const char sqlite4IsEbcdicIdChar[];
#define IdChar(C)  (((c=C)>=0x42 && sqlite4IsEbcdicIdChar[c-0x40]))
#endif
#endif /* SQLITE4_AMALGAMATION */


/*
** Token types used by the sqlite4_complete() routine.  See the header
** comments on that procedure for additional information.
*/
#define tkSEMI    0
#define tkWS      1
#define tkOTHER   2
#ifndef SQLITE4_OMIT_TRIGGER
#define tkEXPLAIN 3
#define tkCREATE  4
#define tkTEMP    5
#define tkTRIGGER 6
#define tkEND     7
#endif

/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
** This implementation uses a state machine with 8 states:
**
**   (0) INVALID   We have not yet seen a non-whitespace character.
**
**   (1) START     At the beginning or end of an SQL statement.  This routine
**                 returns 1 if it ends in the START state and 0 if it ends
**                 in any other state.
**
**   (2) NORMAL    We are in the middle of statement which ends with a single
**                 semicolon.
**
**   (3) EXPLAIN   The keyword EXPLAIN has been seen at the beginning of 
**                 a statement.
**
**   (4) CREATE    The keyword CREATE has been seen at the beginning of a
**                 statement, possibly preceeded by EXPLAIN and/or followed by
**                 TEMP or TEMPORARY
**
**   (5) TRIGGER   We are in the middle of a trigger definition that must be
**                 ended by a semicolon, the keyword END, and another semicolon.
**
**   (6) SEMI      We've seen the first semicolon in the ";END;" that occurs at
**                 the end of a trigger definition.
**
**   (7) END       We've seen the ";END" of the ";END;" that occurs at the end
**                 of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input.  The following tokens are significant:
**
**   (0) tkSEMI      A semicolon.
**   (1) tkWS        Whitespace.
**   (2) tkOTHER     Any other SQL token.
**   (3) tkEXPLAIN   The "explain" keyword.
**   (4) tkCREATE    The "create" keyword.
**   (5) tkTEMP      The "temp" or "temporary" keyword.
**   (6) tkTRIGGER   The "trigger" keyword.
**   (7) tkEND       The "end" keyword.
**
** Whitespace never causes a state transition and is always ignored.
** This means that a SQL string of all whitespace is invalid.
**
** If we compile with SQLITE4_OMIT_TRIGGER, all of the computation needed
** to recognize the end of a trigger can be omitted.  All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
SQLITE4_API int sqlite4_complete(const char *zSql){
  u8 state = 0;   /* Current state, using numbers defined in header comment */
  u8 token;       /* Value of the next token */

#ifndef SQLITE4_OMIT_TRIGGER
  /* A complex statement machine used to detect the end of a CREATE TRIGGER
  ** statement.  This is the normal case.
  */
  static const u8 trans[8][8] = {
                     /* Token:                                                */
     /* State:       **  SEMI  WS  OTHER  EXPLAIN  CREATE  TEMP  TRIGGER  END */
     /* 0 INVALID: */ {    1,  0,     2,       3,      4,    2,       2,   2, },
     /* 1   START: */ {    1,  1,     2,       3,      4,    2,       2,   2, },
     /* 2  NORMAL: */ {    1,  2,     2,       2,      2,    2,       2,   2, },
     /* 3 EXPLAIN: */ {    1,  3,     3,       2,      4,    2,       2,   2, },
     /* 4  CREATE: */ {    1,  4,     2,       2,      2,    4,       5,   2, },
     /* 5 TRIGGER: */ {    6,  5,     5,       5,      5,    5,       5,   5, },
     /* 6    SEMI: */ {    6,  6,     5,       5,      5,    5,       5,   7, },
     /* 7     END: */ {    1,  7,     5,       5,      5,    5,       5,   5, },
  };
#else
  /* If triggers are not supported by this compile then the statement machine
  ** used to detect the end of a statement is much simplier
  */
  static const u8 trans[3][3] = {
                     /* Token:           */
     /* State:       **  SEMI  WS  OTHER */
     /* 0 INVALID: */ {    1,  0,     2, },
     /* 1   START: */ {    1,  1,     2, },
     /* 2  NORMAL: */ {    1,  2,     2, },
  };
#endif /* SQLITE4_OMIT_TRIGGER */

  while( *zSql ){
    switch( *zSql ){
      case ';': {  /* A semicolon */
        token = tkSEMI;
        break;
      }
      case ' ':
      case '\r':
      case '\t':
      case '\n':
      case '\f': {  /* White space is ignored */
        token = tkWS;
        break;
      }
      case '/': {   /* C-style comments */
        if( zSql[1]!='*' ){
          token = tkOTHER;
          break;
        }
        zSql += 2;
        while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
        if( zSql[0]==0 ) return 0;
        zSql++;
        token = tkWS;
        break;
      }
      case '-': {   /* SQL-style comments from "--" to end of line */
        if( zSql[1]!='-' ){
          token = tkOTHER;
          break;
        }
        while( *zSql && *zSql!='\n' ){ zSql++; }
        if( *zSql==0 ) return state==1;
        token = tkWS;
        break;
      }
      case '[': {   /* Microsoft-style identifiers in [...] */
        zSql++;
        while( *zSql && *zSql!=']' ){ zSql++; }
        if( *zSql==0 ) return 0;
        token = tkOTHER;
        break;
      }
      case '`':     /* Grave-accent quoted symbols used by MySQL */
      case '"':     /* single- and double-quoted strings */
      case '\'': {
        int c = *zSql;
        zSql++;
        while( *zSql && *zSql!=c ){ zSql++; }
        if( *zSql==0 ) return 0;
        token = tkOTHER;
        break;
      }
      default: {
#ifdef SQLITE4_EBCDIC
        unsigned char c;
#endif
        if( IdChar((u8)*zSql) ){
          /* Keywords and unquoted identifiers */
          int nId;
          for(nId=1; IdChar(zSql[nId]); nId++){}
#ifdef SQLITE4_OMIT_TRIGGER
          token = tkOTHER;
#else
          switch( *zSql ){
            case 'c': case 'C': {
              if( nId==6 && sqlite4_strnicmp(zSql, "create", 6)==0 ){
                token = tkCREATE;
              }else{
                token = tkOTHER;
              }
              break;
            }
            case 't': case 'T': {
              if( nId==7 && sqlite4_strnicmp(zSql, "trigger", 7)==0 ){
                token = tkTRIGGER;
              }else if( nId==4 && sqlite4_strnicmp(zSql, "temp", 4)==0 ){
                token = tkTEMP;
              }else if( nId==9 && sqlite4_strnicmp(zSql, "temporary", 9)==0 ){
                token = tkTEMP;
              }else{
                token = tkOTHER;
              }
              break;
            }
            case 'e':  case 'E': {
              if( nId==3 && sqlite4_strnicmp(zSql, "end", 3)==0 ){
                token = tkEND;
              }else
#ifndef SQLITE4_OMIT_EXPLAIN
              if( nId==7 && sqlite4_strnicmp(zSql, "explain", 7)==0 ){
                token = tkEXPLAIN;
              }else
#endif
              {
                token = tkOTHER;
              }
              break;
            }
            default: {
              token = tkOTHER;
              break;
            }
          }
#endif /* SQLITE4_OMIT_TRIGGER */
          zSql += nId-1;
        }else{
          /* Operators and special symbols */
          token = tkOTHER;
        }
        break;
      }
    }
    state = trans[state][token];
    zSql++;
  }
  return state==1;
}

#ifndef SQLITE4_OMIT_UTF16
/*
** This routine is the same as the sqlite4_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
SQLITE4_API int sqlite4_complete16(const void *zSql){
  sqlite4_value *pVal;
  char const *zSql8;
  int rc = SQLITE4_NOMEM;

#ifndef SQLITE4_OMIT_AUTOINIT
  rc = sqlite4_initialize(0);
  if( rc ) return rc;
#endif
  pVal = sqlite4ValueNew(0);
  sqlite4ValueSetStr(pVal, -1, zSql, SQLITE4_UTF16NATIVE, SQLITE4_STATIC, 0);
  zSql8 = sqlite4ValueText(pVal, SQLITE4_UTF8);
  if( zSql8 ){
    rc = sqlite4_complete(zSql8);
  }else{
    rc = SQLITE4_NOMEM;
  }
  sqlite4ValueFree(pVal);
  return sqlite4ApiExit(0, rc);
}
#endif /* SQLITE4_OMIT_UTF16 */
#endif /* SQLITE4_OMIT_COMPLETE */

/************** End of complete.c ********************************************/
/************** Begin file main.c ********************************************/
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
*/

#ifdef SQLITE4_ENABLE_FTS3
# include "fts3.h"
#endif
#ifdef SQLITE4_ENABLE_RTREE
# include "rtree.h"
#endif
#ifdef SQLITE4_ENABLE_ICU
# include "sqliteicu.h"
#endif

/*
** Dummy function used as a unique symbol for SQLITE4_DYNAMIC
*/
SQLITE4_API void sqlite4_dynamic(void *pArg,void *p){ (void)pArg; (void)p; }

/* IMPLEMENTATION-OF: R-53536-42575 The sqlite4_libversion() function returns
** a pointer to the to the sqlite4_version[] string constant. 
*/
SQLITE4_API const char *sqlite4_libversion(void){ return SQLITE4_VERSION; }

/* IMPLEMENTATION-OF: R-63124-39300 The sqlite4_sourceid() function returns a
** pointer to a string constant whose value is the same as the
** SQLITE4_SOURCE_ID C preprocessor macro. 
*/
SQLITE4_API const char *sqlite4_sourceid(void){ return SQLITE4_SOURCE_ID; }

/* IMPLEMENTATION-OF: R-35210-63508 The sqlite4_libversion_number() function
** returns an integer equal to SQLITE4_VERSION_NUMBER.
*/
SQLITE4_API int sqlite4_libversion_number(void){ return SQLITE4_VERSION_NUMBER; }

/* Return the thread-safety setting.
*/
SQLITE4_API int sqlite4_threadsafe(sqlite4_env *pEnv){
  if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
  return pEnv->bCoreMutex + pEnv->bFullMutex;
}

#if !defined(SQLITE4_OMIT_TRACE) && defined(SQLITE4_ENABLE_IOTRACE)
/*
** If the following function pointer is not NULL and if
** SQLITE4_ENABLE_IOTRACE is enabled, then messages describing
** I/O active are written using this function.  These messages
** are intended for debugging activity only.
*/
SQLITE4_PRIVATE void (*sqlite4IoTrace)(const char*, ...) = 0;
#endif

/*
** Set up the lookaside buffers for a database connection.
** Return SQLITE4_OK on success.  
** If lookaside is already active, return SQLITE4_BUSY.
**
** The sz parameter is the number of bytes in each lookaside slot.
** The cnt parameter is the number of slots.  If pStart is NULL the
** space for the lookaside memory is obtained from sqlite4_malloc().
** If pStart is not NULL then it is sz*cnt bytes of memory to use for
** the lookaside memory.
*/
static int setupLookaside(sqlite4 *db, void *pBuf, int sz, int cnt){
  void *pStart;
  if( db->lookaside.nOut ){
    return SQLITE4_BUSY;
  }
  /* Free any existing lookaside buffer for this handle before
  ** allocating a new one so we don't have to have space for 
  ** both at the same time.
  */
  if( db->lookaside.bMalloced ){
    sqlite4_free(db->pEnv, db->lookaside.pStart);
  }
  /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger
  ** than a pointer to be useful.
  */
  sz = ROUNDDOWN8(sz);  /* IMP: R-33038-09382 */
  if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
  if( cnt<0 ) cnt = 0;
  if( sz==0 || cnt==0 ){
    sz = 0;
    pStart = 0;
  }else if( pBuf==0 ){
    sqlite4BeginBenignMalloc(db->pEnv);
    pStart = sqlite4Malloc(db->pEnv, sz*cnt );  /* IMP: R-61949-35727 */
    sqlite4EndBenignMalloc(db->pEnv);
    if( pStart ) cnt = sqlite4MallocSize(db->pEnv, pStart)/sz;
  }else{
    pStart = pBuf;
  }
  db->lookaside.pStart = pStart;
  db->lookaside.pFree = 0;
  db->lookaside.sz = (u16)sz;
  if( pStart ){
    int i;
    LookasideSlot *p;
    assert( sz > (int)sizeof(LookasideSlot*) );
    p = (LookasideSlot*)pStart;
    for(i=cnt-1; i>=0; i--){
      p->pNext = db->lookaside.pFree;
      db->lookaside.pFree = p;
      p = (LookasideSlot*)&((u8*)p)[sz];
    }
    db->lookaside.pEnd = p;
    db->lookaside.bEnabled = 1;
    db->lookaside.bMalloced = pBuf==0 ?1:0;
  }else{
    db->lookaside.pEnd = 0;
    db->lookaside.bEnabled = 0;
    db->lookaside.bMalloced = 0;
  }
  return SQLITE4_OK;
}

/*
** Return the mutex associated with a database connection.
*/
SQLITE4_API sqlite4_mutex *sqlite4_db_mutex(sqlite4 *db){
  return db->mutex;
}

/*
** Free up as much memory as we can from the given database
** connection.
*/
SQLITE4_API int sqlite4_db_release_memory(sqlite4 *db){
  sqlite4_mutex_enter(db->mutex);
  sqlite4_mutex_leave(db->mutex);
  return SQLITE4_OK;
}

/*
** Configuration settings for an individual database connection
*/
SQLITE4_API int sqlite4_db_config(sqlite4 *db, int op, ...){
  va_list ap;
  int rc;
  va_start(ap, op);
  switch( op ){
    case SQLITE4_DBCONFIG_LOOKASIDE: {
      void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */
      int sz = va_arg(ap, int);       /* IMP: R-47871-25994 */
      int cnt = va_arg(ap, int);      /* IMP: R-04460-53386 */
      rc = setupLookaside(db, pBuf, sz, cnt);
      break;
    }
    default: {
      static const struct {
        int op;      /* The opcode */
        u32 mask;    /* Mask of the bit in sqlite4.flags to set/clear */
      } aFlagOp[] = {
        { SQLITE4_DBCONFIG_ENABLE_FKEY,    SQLITE4_ForeignKeys    },
        { SQLITE4_DBCONFIG_ENABLE_TRIGGER, SQLITE4_EnableTrigger  },
      };
      unsigned int i;
      rc = SQLITE4_ERROR; /* IMP: R-42790-23372 */
      for(i=0; i<ArraySize(aFlagOp); i++){
        if( aFlagOp[i].op==op ){
          int onoff = va_arg(ap, int);
          int *pRes = va_arg(ap, int*);
          int oldFlags = db->flags;
          if( onoff>0 ){
            db->flags |= aFlagOp[i].mask;
          }else if( onoff==0 ){
            db->flags &= ~aFlagOp[i].mask;
          }
          if( oldFlags!=db->flags ){
            sqlite4ExpirePreparedStatements(db);
          }
          if( pRes ){
            *pRes = (db->flags & aFlagOp[i].mask)!=0;
          }
          rc = SQLITE4_OK;
          break;
        }
      }
      break;
    }
  }
  va_end(ap);
  return rc;
}


/*
** Return true if the buffer z[0..n-1] contains all spaces.
*/
static int allSpaces(const char *z, int n){
  while( n>0 && z[n-1]==' ' ){ n--; }
  return n==0;
}

/*
** This is the default collating function named "BINARY" which is always
** available.
**
** If the padFlag argument is not NULL then space padding at the end
** of strings is ignored. This implements the RTRIM collation.
*/
static int binCollFunc(
  void *padFlag,
  sqlite4_value *p1,
  sqlite4_value *p2,
  int *pRes
){
  int n;
  int n1;
  int n2;
  int res;
  const char *z1 = sqlite4_value_text(p1, &n1);
  const char *z2 = sqlite4_value_text(p2, &n2);

  n = (n1<n2 ? n1 : n2);
  res = memcmp(z1, z2, n);
  if( res==0 ){
    if( padFlag && allSpaces(z1+n, n1-n) && allSpaces(z2+n, n2-n) ){
      /* Leave res unchanged at 0 */
    }else{
      res = n1 - n2;
    }
  }
  *pRes = res;
  return SQLITE4_OK;
}

/*
** The xMakeKey callback for the built-in RTRIM collation. The output
** is the same as the input, with any trailing ' ' characters removed.
** (e.g.  " abc   "  ->   " abc").
*/
static int collRtrimMkKey(
  void *NotUsed,                  /* Not used */
  sqlite4_value *pVal,            /* Text value to make a key of */
  int nOut, void *pOut,           /* Output buffer */
  int *pnOut
){
  int nIn;
  const char *zIn = sqlite4_value_text(pVal, &nIn);

  int nCopy = nIn;
  while( nCopy>0 && zIn[nCopy-1]==' ' ) nCopy--;
  if( nCopy<=nOut ){
    memcpy(pOut, zIn, nCopy);
  }
  *pnOut = nCopy;
  return SQLITE4_OK;
}

/*
** Another built-in collating sequence: NOCASE. 
**
** This collating sequence is intended to be used for "case independant
** comparison". SQLite's knowledge of upper and lower case equivalents
** extends only to the 26 characters used in the English language.
**
** At the moment there is only a UTF-8 implementation.
*/
static int collNocaseCmp(
  void *NotUsed,
  sqlite4_value *p1,
  sqlite4_value *p2,
  int *pRes
){
  int n1;
  int n2;
  int res;
  const char *z1 = sqlite4_value_text(p1, &n1);
  const char *z2 = sqlite4_value_text(p2, &n2);

  UNUSED_PARAMETER(NotUsed);

  res = sqlite4_strnicmp(z1, z2, (n1 < n2 ? n1 : n2));
  if( res==0 ) res = n1 - n2;
  *pRes = res;
  return SQLITE4_OK;
}

static int collNocaseMkKey(
  void *NotUsed,
  sqlite4_value *pVal,
  int nOut, void *pOut,
  int *pnOut
){
  int nIn;
  const char *zIn = sqlite4_value_text(pVal, &nIn);
  if( nOut>=nIn ){
    int i;
    u8 *aIn = (u8 *)zIn;
    u8 *aOut = (u8 *)pOut;
    for(i=0; i<nIn; i++){
      aOut[i] = sqlite4_tolower(aIn[i]);
    }
  }

  *pnOut = nIn;
  return SQLITE4_OK;
}

/*
** Return the number of changes in the most recent call to sqlite4_exec().
*/
SQLITE4_API int sqlite4_changes(sqlite4 *db){
  return db->nChange;
}

/*
** Return the number of changes since the database handle was opened.
*/
SQLITE4_API int sqlite4_total_changes(sqlite4 *db){
  return db->nTotalChange;
}

/*
** Close all open savepoints. This function only manipulates fields of the
** database handle object, it does not close any savepoints that may be open
** at the b-tree/pager level.
*/
SQLITE4_PRIVATE void sqlite4CloseSavepoints(sqlite4 *db){
  while( db->pSavepoint ){
    Savepoint *pTmp = db->pSavepoint;
    db->pSavepoint = pTmp->pNext;
    sqlite4DbFree(db, pTmp);
  }
  db->nSavepoint = 0;
  db->nStatement = 0;
}

/*
** Invoke the destructor function associated with FuncDef p, if any. Except,
** if this is not the last copy of the function, do not invoke it.
*/
static void functionDestroy(sqlite4 *db, FuncDef *p){
  if( p->xDestroy ){
    p->xDestroy(p->pUserData);
  }
}

/*
** Close an existing SQLite database
*/
SQLITE4_API int sqlite4_close(sqlite4 *db, unsigned int flags){
  HashElem *i;                    /* Hash table iterator */
  int j;

  UNUSED_PARAMETER(flags);
  if( !db ){
    return SQLITE4_OK;
  }
  if( !sqlite4SafetyCheckSickOrOk(db) ){
    return SQLITE4_MISUSE_BKPT;
  }
  sqlite4_mutex_enter(db->mutex);

  /* Force xDestroy calls on all virtual tables */
  sqlite4ResetInternalSchema(db, -1);

  /* If a transaction is open, the ResetInternalSchema() call above
  ** will not have called the xDisconnect() method on any virtual
  ** tables in the db->aVTrans[] array. The following sqlite4VtabRollback()
  ** call will do so. We need to do this before the check for active
  ** SQL statements below, as the v-table implementation may be storing
  ** some prepared statements internally.
  */
  sqlite4VtabRollback(db);

  /* If there are any outstanding VMs, return SQLITE4_BUSY. */
  if( db->pVdbe ){
    sqlite4Error(db, SQLITE4_BUSY, 
        "unable to close due to unfinalised statements");
    sqlite4_mutex_leave(db->mutex);
    return SQLITE4_BUSY;
  }
  assert( sqlite4SafetyCheckSickOrOk(db) );

  /* Free any outstanding Savepoint structures. */
  sqlite4CloseSavepoints(db);

  for(j=0; j<db->nDb; j++){
    struct Db *pDb = &db->aDb[j];
    if( pDb->pKV ){
      sqlite4KVStoreClose(pDb->pKV);
      pDb->pKV = 0;
    }
    sqlite4DbFree(db, pDb->pSchema);
    pDb->pSchema = 0;
  }
  sqlite4ResetInternalSchema(db, -1);

  /* Free any authorizer callbacks */
  sqlite4AuthFreeAll(db);

  /* Tell the code in notify.c that the connection no longer holds any
  ** locks and does not require any further unlock-notify callbacks.
  */
  sqlite4ConnectionClosed(db);

  /* Delete any collation needed, profile and trace callbacks */
  sqlite4_collation_needed(db, 0, 0, 0);
  sqlite4_profile(db, 0, 0, 0);
  sqlite4_trace(db, 0, 0, 0);
  
  /* Delete tokenizers */
  sqlite4ShutdownFts5(db);

  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  {
    FuncDef *pNext, *pSame, *p;
    for(p=db->aFunc.pFirst; p; p=pNext){
      pNext = p->pNextName;
      while( p ){
        functionDestroy(db, p);
        pSame = p->pSameName;
        sqlite4DbFree(db, p);
        p = pSame;
      }
    }
  }
  for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){
    CollSeq *pColl = (CollSeq *)sqliteHashData(i);
    if( pColl->xDel ) pColl->xDel(pColl->pUser);
    sqlite4DbFree(db, pColl);
  }
  sqlite4HashClear(&db->aCollSeq);
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
    Module *pMod = (Module *)sqliteHashData(i);
    if( pMod->xDestroy ){
      pMod->xDestroy(pMod->pAux);
    }
    sqlite4DbFree(db, pMod);
  }
  sqlite4HashClear(&db->aModule);
#endif

  sqlite4Error(db, SQLITE4_OK, 0); /* Deallocates any cached error strings. */
  if( db->pErr ){
    sqlite4ValueFree(db->pErr);
  }

  db->magic = SQLITE4_MAGIC_ERROR;
  sqlite4_mutex_leave(db->mutex);
  db->magic = SQLITE4_MAGIC_CLOSED;
  sqlite4_mutex_free(db->mutex);
  assert( db->lookaside.nOut==0 );  /* Fails on a lookaside memory leak */
  if( db->lookaside.bMalloced ){
    sqlite4_free(db->pEnv, db->lookaside.pStart);
  }
  sqlite4_free(db->pEnv, db);
  return SQLITE4_OK;
}

/*
** Return a static string that describes the kind of error specified in the
** argument.
*/
SQLITE4_PRIVATE const char *sqlite4ErrStr(int rc){
  static const char* const aMsg[] = {
    /* SQLITE4_OK          */ "not an error",
    /* SQLITE4_ERROR       */ "SQL logic error or missing database",
    /* SQLITE4_INTERNAL    */ 0,
    /* SQLITE4_PERM        */ "access permission denied",
    /* SQLITE4_ABORT       */ "callback requested query abort",
    /* SQLITE4_BUSY        */ "database is locked",
    /* SQLITE4_LOCKED      */ "database table is locked",
    /* SQLITE4_NOMEM       */ "out of memory",
    /* SQLITE4_READONLY    */ "attempt to write a readonly database",
    /* SQLITE4_INTERRUPT   */ "interrupted",
    /* SQLITE4_IOERR       */ "disk I/O error",
    /* SQLITE4_CORRUPT     */ "database disk image is malformed",
    /* SQLITE4_NOTFOUND    */ "unknown operation",
    /* SQLITE4_FULL        */ "database or disk is full",
    /* SQLITE4_CANTOPEN    */ "unable to open database file",
    /* SQLITE4_PROTOCOL    */ "locking protocol",
    /* SQLITE4_EMPTY       */ "table contains no data",
    /* SQLITE4_SCHEMA      */ "database schema has changed",
    /* SQLITE4_TOOBIG      */ "string or blob too big",
    /* SQLITE4_CONSTRAINT  */ "constraint failed",
    /* SQLITE4_MISMATCH    */ "datatype mismatch",
    /* SQLITE4_MISUSE      */ "library routine called out of sequence",
    /* SQLITE4_NOLFS       */ "large file support is disabled",
    /* SQLITE4_AUTH        */ "authorization denied",
    /* SQLITE4_FORMAT      */ "auxiliary database format error",
    /* SQLITE4_RANGE       */ "bind or column index out of range",
    /* SQLITE4_NOTADB      */ "file is encrypted or is not a database",
  };
  rc &= 0xff;
  if( ALWAYS(rc>=0) && rc<(int)(sizeof(aMsg)/sizeof(aMsg[0])) && aMsg[rc]!=0 ){
    return aMsg[rc];
  }else{
    return "unknown error";
  }
}

/*
** Cause any pending operation to stop at its earliest opportunity.
*/
SQLITE4_API void sqlite4_interrupt(sqlite4 *db){
  db->u1.isInterrupted = 1;
}


/*
** This function is exactly the same as sqlite4_create_function(), except
** that it is designed to be called by internal code. The difference is
** that if a malloc() fails in sqlite4_create_function(), an error code
** is returned and the mallocFailed flag cleared. 
*/
SQLITE4_PRIVATE int sqlite4CreateFunc(
  sqlite4 *db,
  const char *zFunctionName,
  int nArg,
  void *pUserData,
  void (*xFunc)(sqlite4_context*,int,sqlite4_value **),
  void (*xStep)(sqlite4_context*,int,sqlite4_value **),
  void (*xFinal)(sqlite4_context*),
  void (*xDestroy)(void *)
){
  FuncDef *p;
  int nName;

  assert( sqlite4_mutex_held(db->mutex) );
  if( zFunctionName==0 ||
      (xFunc && (xFinal || xStep)) || 
      (!xFunc && (xFinal && !xStep)) ||
      (!xFunc && (!xFinal && xStep)) ||
      (nArg<-1 || nArg>SQLITE4_MAX_FUNCTION_ARG) ||
      (255<(nName = sqlite4Strlen30( zFunctionName))) ){
    return SQLITE4_MISUSE_BKPT;
  }
  
  /* Check if an existing function is being overridden or deleted. If so,
  ** and there are active VMs, then return SQLITE4_BUSY. If a function
  ** is being overridden/deleted but there are no active VMs, allow the
  ** operation to continue but invalidate all precompiled statements.
  */
  p = sqlite4FindFunction(db, zFunctionName, nName, nArg, 0);
  if( p && p->nArg==nArg ){
    if( db->activeVdbeCnt ){
      sqlite4Error(db, SQLITE4_BUSY, 
        "unable to delete/modify user-function due to active statements");
      assert( !db->mallocFailed );
      return SQLITE4_BUSY;
    }else{
      sqlite4ExpirePreparedStatements(db);
    }
  }

  p = sqlite4FindFunction(db, zFunctionName, nName, nArg, 1);
  assert(p || db->mallocFailed);
  if( !p ){
    return SQLITE4_NOMEM;
  }

  /* If an older version of the function with a configured destructor is
  ** being replaced invoke the destructor function here. */
  functionDestroy(db, p);

  p->xDestroy = xDestroy;
  p->flags = 0;
  p->xFunc = xFunc;
  p->xStep = xStep;
  p->xFinalize = xFinal;
  p->pUserData = pUserData;
  p->nArg = (u16)nArg;
  return SQLITE4_OK;
}

/*
** Create new user functions.
*/
SQLITE4_API int sqlite4_create_function(
  sqlite4 *db,
  const char *zFunc,
  int nArg,
  void *p,
  void (*xFunc)(sqlite4_context*,int,sqlite4_value **),
  void (*xStep)(sqlite4_context*,int,sqlite4_value **),
  void (*xFinal)(sqlite4_context*),
  void (*xDestroy)(void *)
){
  int rc;
  sqlite4_mutex_enter(db->mutex);
  rc = sqlite4CreateFunc(
      db, zFunc, nArg, p, xFunc, xStep, xFinal, xDestroy
  );
  rc = sqlite4ApiExit(db, rc);
  if( rc!=SQLITE4_OK && xDestroy ) xDestroy(p);
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

SQLITE4_API int sqlite4_create_mi_function(
  sqlite4 *db,
  const char *zFunc,
  int nArg,
  int enc,
  void *p,
  void (*xFunc)(sqlite4_context*,int,sqlite4_value **),
  void (*xDestroy)(void *)
){
  int rc;
  int n;

  n = nArg + (nArg>=0);
  sqlite4_mutex_enter(db->mutex);
  rc = sqlite4_create_function(db, zFunc, n, p, xFunc, 0, 0, xDestroy);
  if( rc==SQLITE4_OK ){
    FuncDef *p = sqlite4FindFunction(db, zFunc, -1, n, 0);
    p->bMatchinfo = 1;
  }
  rc = sqlite4ApiExit(db, rc);
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Declare that a function has been overloaded by a virtual table.
**
** If the function already exists as a regular global function, then
** this routine is a no-op.  If the function does not exist, then create
** a new one that always throws a run-time error.  
**
** When virtual tables intend to provide an overloaded function, they
** should call this routine to make sure the global function exists.
** A global function must exist in order for name resolution to work
** properly.
*/
SQLITE4_API int sqlite4_overload_function(
  sqlite4 *db,
  const char *zName,
  int nArg
){
  int nName = sqlite4Strlen30(zName);
  int rc = SQLITE4_OK;
  sqlite4_mutex_enter(db->mutex);
  if( sqlite4FindFunction(db, zName, nName, nArg, 0)==0 ){
    rc = sqlite4CreateFunc(db, zName, nArg,
                           0, sqlite4InvalidFunction, 0, 0, 0);
  }
  rc = sqlite4ApiExit(db, rc);
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

#ifndef SQLITE4_OMIT_TRACE
/*
** Register a trace function.  The pArg from the previously registered trace
** is returned.  
**
** A NULL trace function means that no tracing is executes.  A non-NULL
** trace is a pointer to a function that is invoked at the start of each
** SQL statement.
*/
SQLITE4_API void sqlite4_trace(
  sqlite4 *db, 
  void *pArg,
  void (*xTrace)(void*,const char*), 
  void (*xDestroy)(void*)
){
  sqlite4_mutex_enter(db->mutex);
  if( db->xTraceDestroy ){
    db->xTraceDestroy(db->pTraceArg);
  }
  db->xTrace = xTrace;
  db->xTraceDestroy = xDestroy;
  db->pTraceArg = pArg;
  sqlite4_mutex_leave(db->mutex);
}
/*
** Register a profile function.  The pArg from the previously registered 
** profile function is returned.  
**
** A NULL profile function means that no profiling is executes.  A non-NULL
** profile is a pointer to a function that is invoked at the conclusion of
** each SQL statement that is run.
*/
SQLITE4_API void sqlite4_profile(
  sqlite4 *db,
  void *pArg,
  void (*xProfile)(void*,const char*,sqlite4_uint64),
  void (*xDestroy)(void*)
){
  sqlite4_mutex_enter(db->mutex);
  if( db->xProfileDestroy ){
    db->xProfileDestroy(db->pProfileArg);
  }
  db->xProfile = xProfile;
  db->xProfileDestroy = xDestroy;
  db->pProfileArg = pArg;
  sqlite4_mutex_leave(db->mutex);
}
#endif /* SQLITE4_OMIT_TRACE */

/*
** Return UTF-8 encoded English language explanation of the most recent
** error.
*/
SQLITE4_API const char *sqlite4_errmsg(sqlite4 *db){
  const char *z;
  if( !db ){
    return sqlite4ErrStr(SQLITE4_NOMEM);
  }
  if( !sqlite4SafetyCheckSickOrOk(db) ){
    return sqlite4ErrStr(SQLITE4_MISUSE_BKPT);
  }
  sqlite4_mutex_enter(db->mutex);
  if( db->mallocFailed ){
    z = sqlite4ErrStr(SQLITE4_NOMEM);
  }else{
    z = (char*)sqlite4_value_text(db->pErr, 0);
    assert( !db->mallocFailed );
    if( z==0 ){
      z = sqlite4ErrStr(db->errCode);
    }
  }
  sqlite4_mutex_leave(db->mutex);
  return z;
}

/*
** Return the most recent error code generated by an SQLite routine. If NULL is
** passed to this function, we assume a malloc() failed during sqlite4_open().
*/
SQLITE4_API int sqlite4_errcode(sqlite4 *db){
  if( db && !sqlite4SafetyCheckSickOrOk(db) ){
    return SQLITE4_MISUSE_BKPT;
  }
  if( !db || db->mallocFailed ){
    return SQLITE4_NOMEM;
  }
  return db->errCode;
}

/*
** Create a new collating function named zName for database db.
*/
static int createCollation(
  sqlite4* db,
  const char *zName, 
  void *pCtx,
  int(*xCompare)(void*, sqlite4_value*, sqlite4_value*, int*),
  int(*xMakeKey)(void*, sqlite4_value*, int, void*, int*),
  void(*xDel)(void*)
){
  CollSeq *pColl;
  
  assert( sqlite4_mutex_held(db->mutex) );

  /* Check if this call is removing or replacing an existing collation 
  ** sequence. If so, and there are active VMs, return busy. If there
  ** are no active VMs, invalidate any pre-compiled statements.
  */
  pColl = sqlite4FindCollSeq(db, zName, 0);
  if( pColl && pColl->xCmp ){
    if( db->activeVdbeCnt ){
      sqlite4Error(db, SQLITE4_BUSY, 
        "unable to delete/modify collation sequence due to active statements");
      return SQLITE4_BUSY;
    }
    sqlite4ExpirePreparedStatements(db);

    if( pColl->xDel ){
      pColl->xDel(pColl->pUser);
    }
    pColl->xDel = 0;
    pColl->xCmp = 0;
    pColl->xMkKey = 0;
    pColl->pUser = 0;
  }

  pColl = sqlite4FindCollSeq(db, zName, 1);
  if( pColl==0 ) return SQLITE4_NOMEM;
  pColl->xCmp = xCompare;
  pColl->xMkKey = xMakeKey;
  pColl->pUser = pCtx;
  pColl->xDel = xDel;
  return SQLITE4_OK;
}


/*
** This array defines hard upper bounds on limit values.  The
** initializer must be kept in sync with the SQLITE4_LIMIT_*
** #defines in sqlite4.h.
*/
static const int aHardLimit[] = {
  SQLITE4_MAX_LENGTH,
  SQLITE4_MAX_SQL_LENGTH,
  SQLITE4_MAX_COLUMN,
  SQLITE4_MAX_EXPR_DEPTH,
  SQLITE4_MAX_COMPOUND_SELECT,
  SQLITE4_MAX_VDBE_OP,
  SQLITE4_MAX_FUNCTION_ARG,
  SQLITE4_MAX_ATTACHED,
  SQLITE4_MAX_LIKE_PATTERN_LENGTH,
  SQLITE4_MAX_VARIABLE_NUMBER,
  SQLITE4_MAX_TRIGGER_DEPTH,
};

/*
** Make sure the hard limits are set to reasonable values
*/
#if SQLITE4_MAX_LENGTH<100
# error SQLITE4_MAX_LENGTH must be at least 100
#endif
#if SQLITE4_MAX_SQL_LENGTH<100
# error SQLITE4_MAX_SQL_LENGTH must be at least 100
#endif
#if SQLITE4_MAX_SQL_LENGTH>SQLITE4_MAX_LENGTH
# error SQLITE4_MAX_SQL_LENGTH must not be greater than SQLITE4_MAX_LENGTH
#endif
#if SQLITE4_MAX_COMPOUND_SELECT<2
# error SQLITE4_MAX_COMPOUND_SELECT must be at least 2
#endif
#if SQLITE4_MAX_VDBE_OP<40
# error SQLITE4_MAX_VDBE_OP must be at least 40
#endif
#if SQLITE4_MAX_FUNCTION_ARG<0 || SQLITE4_MAX_FUNCTION_ARG>1000
# error SQLITE4_MAX_FUNCTION_ARG must be between 0 and 1000
#endif
#if SQLITE4_MAX_ATTACHED<0 || SQLITE4_MAX_ATTACHED>62
# error SQLITE4_MAX_ATTACHED must be between 0 and 62
#endif
#if SQLITE4_MAX_LIKE_PATTERN_LENGTH<1
# error SQLITE4_MAX_LIKE_PATTERN_LENGTH must be at least 1
#endif
#if SQLITE4_MAX_COLUMN>32767
# error SQLITE4_MAX_COLUMN must not exceed 32767
#endif
#if SQLITE4_MAX_TRIGGER_DEPTH<1
# error SQLITE4_MAX_TRIGGER_DEPTH must be at least 1
#endif


/*
** Change the value of a limit.  Report the old value.
** If an invalid limit index is supplied, report -1.
** Make no changes but still report the old value if the
** new limit is negative.
**
** A new lower limit does not shrink existing constructs.
** It merely prevents new constructs that exceed the limit
** from forming.
*/
SQLITE4_API int sqlite4_limit(sqlite4 *db, int limitId, int newLimit){
  int oldLimit;


  /* EVIDENCE-OF: R-30189-54097 For each limit category SQLITE4_LIMIT_NAME
  ** there is a hard upper bound set at compile-time by a C preprocessor
  ** macro called SQLITE4_MAX_NAME. (The "_LIMIT_" in the name is changed to
  ** "_MAX_".)
  */
  assert( aHardLimit[SQLITE4_LIMIT_LENGTH]==SQLITE4_MAX_LENGTH );
  assert( aHardLimit[SQLITE4_LIMIT_SQL_LENGTH]==SQLITE4_MAX_SQL_LENGTH );
  assert( aHardLimit[SQLITE4_LIMIT_COLUMN]==SQLITE4_MAX_COLUMN );
  assert( aHardLimit[SQLITE4_LIMIT_EXPR_DEPTH]==SQLITE4_MAX_EXPR_DEPTH );
  assert( aHardLimit[SQLITE4_LIMIT_COMPOUND_SELECT]==SQLITE4_MAX_COMPOUND_SELECT);
  assert( aHardLimit[SQLITE4_LIMIT_VDBE_OP]==SQLITE4_MAX_VDBE_OP );
  assert( aHardLimit[SQLITE4_LIMIT_FUNCTION_ARG]==SQLITE4_MAX_FUNCTION_ARG );
  assert( aHardLimit[SQLITE4_LIMIT_ATTACHED]==SQLITE4_MAX_ATTACHED );
  assert( aHardLimit[SQLITE4_LIMIT_LIKE_PATTERN_LENGTH]==
                                               SQLITE4_MAX_LIKE_PATTERN_LENGTH );
  assert( aHardLimit[SQLITE4_LIMIT_VARIABLE_NUMBER]==SQLITE4_MAX_VARIABLE_NUMBER);
  assert( aHardLimit[SQLITE4_LIMIT_TRIGGER_DEPTH]==SQLITE4_MAX_TRIGGER_DEPTH );
  assert( SQLITE4_LIMIT_TRIGGER_DEPTH==(SQLITE4_N_LIMIT-1) );


  if( limitId<0 || limitId>=SQLITE4_N_LIMIT ){
    return -1;
  }
  oldLimit = db->aLimit[limitId];
  if( newLimit>=0 ){                   /* IMP: R-52476-28732 */
    if( newLimit>aHardLimit[limitId] ){
      newLimit = aHardLimit[limitId];  /* IMP: R-51463-25634 */
    }
    db->aLimit[limitId] = newLimit;
  }
  return oldLimit;                     /* IMP: R-53341-35419 */
}

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

  assert( *pzErrMsg==0 );

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

    for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
    zFile = sqlite4_malloc(pEnv, nByte);
    if( !zFile ) return SQLITE4_NOMEM;

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

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

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

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

    /* Check if there were any options specified that should be interpreted 
    ** here. Options that are interpreted here include "vfs" and those that
    ** correspond to flags that may be passed to the sqlite4_open()
    ** method. */
    zOpt = &zFile[sqlite4Strlen30(zFile)+1];
    while( zOpt[0] ){
      int nOpt = sqlite4Strlen30(zOpt);
      char *zVal = &zOpt[nOpt+1];
      int nVal = sqlite4Strlen30(zVal);
      struct OpenMode {
        const char *z;
        int mode;
      } *aMode = 0;
      char *zModeType = 0;
      int mask = 0;
      int limit = 0;

      if( nOpt==4 && memcmp("mode", zOpt, 4)==0 ){
        static struct OpenMode aOpenMode[] = {
          { "ro",  SQLITE4_OPEN_READONLY },
          { "rw",  SQLITE4_OPEN_READWRITE }, 
          { "rwc", SQLITE4_OPEN_READWRITE | SQLITE4_OPEN_CREATE },
          { 0, 0 }
        };

        mask = SQLITE4_OPEN_READONLY|SQLITE4_OPEN_READWRITE|SQLITE4_OPEN_CREATE;
        aMode = aOpenMode;
        limit = mask & flags;
        zModeType = "access";
      }

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

      zOpt = &zVal[nVal+1];
    }

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

 parse_uri_out:
  if( rc!=SQLITE4_OK ){
    sqlite4_free(pEnv, zFile);
    zFile = 0;
  }
  *pFlags = flags;
  *pzFile = zFile;
  return rc;
}


/*
** This routine does the work of opening a database on behalf of
** sqlite4_open(). The database filename "zFilename" is UTF-8 encoded.
*/
static int openDatabase(
  sqlite4_env *pEnv,     /* The run-time environment */
  const char *zFilename, /* Database filename UTF-8 encoded */
  unsigned int flags,    /* Flags influencing the open */
  sqlite4 **ppDb,        /* OUT: Returned database handle */
  va_list ap             /* Zero-terminated list of options */
){
  sqlite4 *db;                    /* Store allocated handle here */
  int rc;                         /* Return code */
  int isThreadsafe;               /* True for threadsafe connections */
  char *zOpen = 0;                /* Filename passed to StorageOpen() */
  char *zErrMsg = 0;              /* Error message from sqlite4ParseUri() */

  *ppDb = 0;
#ifndef SQLITE4_OMIT_AUTOINIT
  rc = sqlite4_initialize(pEnv);
  if( rc ) return rc;
#endif

  if( pEnv->bCoreMutex==0 ){
    isThreadsafe = 0;
  }else{
    isThreadsafe = pEnv->bFullMutex;
  }

  /* Allocate the sqlite data structure */
  db = sqlite4MallocZero(pEnv, sizeof(sqlite4) );
  if( db==0 ) goto opendb_out;
  db->pEnv = pEnv;
  if( isThreadsafe ){
    db->mutex = sqlite4MutexAlloc(pEnv, SQLITE4_MUTEX_RECURSIVE);
    if( db->mutex==0 ){
      sqlite4_free(pEnv, db);
      db = 0;
      goto opendb_out;
    }
  }
  sqlite4_mutex_enter(db->mutex);
  db->nDb = 2;
  db->magic = SQLITE4_MAGIC_BUSY;
  db->aDb = db->aDbStatic;

  assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
  memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
  db->nextAutovac = -1;
  db->nextPagesize = 0;
  db->flags |=  SQLITE4_AutoIndex
                 | SQLITE4_EnableTrigger
                 | SQLITE4_ForeignKeys
            ;

  sqlite4HashInit(pEnv, &db->aCollSeq, 0);
#ifndef SQLITE4_OMIT_VIRTUALTABLE
  sqlite4HashInit(pEnv, &db->aModule, 0);
#endif

  /* Add the built-in collation sequences BINARY, RTRIM and NOCASE. */
  createCollation(db, "BINARY", 0, binCollFunc, 0, 0);
  createCollation(db, "RTRIM", (void*)1, binCollFunc, collRtrimMkKey, 0);
  createCollation(db, "NOCASE", 0, collNocaseCmp, collNocaseMkKey, 0);
  if( db->mallocFailed ){
    goto opendb_out;
  }
  db->pDfltColl = sqlite4FindCollSeq(db, "BINARY", 0);
  assert( db->pDfltColl!=0 );

  /* Parse the filename/URI argument. */
  rc = sqlite4ParseUri(pEnv, zFilename, &flags, &zOpen, &zErrMsg);
  if( rc!=SQLITE4_OK ){
    if( rc==SQLITE4_NOMEM ) db->mallocFailed = 1;
    sqlite4Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
    sqlite4_free(pEnv, zErrMsg);
    goto opendb_out;
  }
  db->openFlags = flags;

  /* Open the backend database driver */
  rc = sqlite4KVStoreOpen(db, "main", zOpen, &db->aDb[0].pKV, flags);
  if( rc!=SQLITE4_OK ){
    if( rc==SQLITE4_IOERR_NOMEM ){
      rc = SQLITE4_NOMEM;
    }
    sqlite4Error(db, rc, 0);
    goto opendb_out;
  }
  db->aDb[0].pSchema = sqlite4SchemaGet(db);
  db->aDb[1].pSchema = sqlite4SchemaGet(db);

  /* The default safety_level for the main database is 'full'; for the temp
  ** database it is 'NONE'. This matches the pager layer defaults.  
  */
  db->aDb[0].zName = "main";
  db->aDb[1].zName = "temp";

  db->magic = SQLITE4_MAGIC_OPEN;
  if( db->mallocFailed ){
    goto opendb_out;
  }

  /* Register all built-in functions, but do not attempt to read the
  ** database schema yet. This is delayed until the first time the database
  ** is accessed.
  */
  sqlite4Error(db, SQLITE4_OK, 0);
  sqlite4RegisterBuiltinFunctions(db);

  /* Load automatic extensions - extensions that have been registered
  ** using the sqlite4_automatic_extension() API.
  */
  rc = sqlite4_errcode(db);
  if( rc==SQLITE4_OK ){
    /* sqlite4AutoLoadExtensions(db); */
    rc = sqlite4_errcode(db);
    if( rc!=SQLITE4_OK ){
      goto opendb_out;
    }
  }

  if( !db->mallocFailed && rc==SQLITE4_OK ){
    rc = sqlite4InitFts5(db);
  }

#ifdef SQLITE4_ENABLE_ICU
  if( !db->mallocFailed && rc==SQLITE4_OK ){
    rc = sqlite4IcuInit(db);
  }
#endif

#ifdef SQLITE4_ENABLE_RTREE
  if( !db->mallocFailed && rc==SQLITE4_OK){
    rc = sqlite4RtreeInit(db);
  }
#endif

  sqlite4Error(db, rc, 0);

  /* Enable the lookaside-malloc subsystem */
  setupLookaside(db, 0, pEnv->szLookaside,
                        pEnv->nLookaside);

opendb_out:
  sqlite4_free(pEnv, zOpen);
  if( db ){
    assert( db->mutex!=0 || isThreadsafe==0 || pEnv->bFullMutex==0 );
    sqlite4_mutex_leave(db->mutex);
  }
  rc = sqlite4_errcode(db);
  assert( db!=0 || rc==SQLITE4_NOMEM );
  if( rc==SQLITE4_NOMEM ){
    sqlite4_close(db, 0);
    db = 0;
  }else if( rc!=SQLITE4_OK ){
    db->magic = SQLITE4_MAGIC_SICK;
  }
  *ppDb = db;
  return sqlite4ApiExit(0, rc);
}

/*
** Open a new database handle.
*/
SQLITE4_API int sqlite4_open(
  sqlite4_env *pEnv,
  const char *zFilename, 
  sqlite4 **ppDb,
  ...
){
  va_list ap;
  int rc;
  if( pEnv==0 ) pEnv = sqlite4_env_default();
  va_start(ap, ppDb);
  rc = openDatabase(pEnv, zFilename,
                      SQLITE4_OPEN_READWRITE | SQLITE4_OPEN_CREATE, ppDb, ap);
  va_end(ap);
  return rc;
}

/*
** Return the environment of a database connection
*/
SQLITE4_API sqlite4_env *sqlite4_db_env(sqlite4 *db){
  return db ? db->pEnv : sqlite4_env_default();
}

/*
** Register a new collation sequence with the database handle db.
*/
SQLITE4_API int sqlite4_create_collation(
  sqlite4* db, 
  const char *zName, 
  void *pCtx,
  int(*xCompare)(void*, sqlite4_value*, sqlite4_value*, int*),
  int(*xMakeKey)(void*, sqlite4_value*, int, void*, int*),
  void(*xDel)(void*)
){
  int rc;
  sqlite4_mutex_enter(db->mutex);
  assert( !db->mallocFailed );
  rc = createCollation(db, zName, pCtx, xCompare, xMakeKey, xDel);
  rc = sqlite4ApiExit(db, rc);
  if( rc!=SQLITE4_OK && xDel ) xDel(pCtx);
  sqlite4_mutex_leave(db->mutex);
  return rc;
}

/*
** Register a collation sequence factory callback with the database handle
** db. Replace any previously installed collation sequence factory.
*/
SQLITE4_API int sqlite4_collation_needed(
  sqlite4 *db, 
  void *pCollNeededArg,
  void(*xCollNeeded)(void*,sqlite4*,const char*),
  void(*xDestroy)(void*)
){
  sqlite4_mutex_enter(db->mutex);
  if( db->xCollNeededDestroy ){
    db->xCollNeededDestroy(db->pCollNeededArg);
  }
  db->xCollNeeded = xCollNeeded;
  db->xCollNeededDestroy = xDestroy;
  db->pCollNeededArg = pCollNeededArg;
  sqlite4_mutex_leave(db->mutex);
  return SQLITE4_OK;
}

/*
** Test to see whether or not the database connection is currently within
** an explicitly started transaction (BEGIN/COMMIT block). Return non-zero 
** if it is and FALSE otherwise. Explicit transactions are opened by a 
** BEGIN statement and concluded by the next COMMIT or ROLLBACK.
*/
SQLITE4_API int sqlite4_db_transaction_status(sqlite4 *db){
  return (db->pSavepoint!=0);
}

/*
** The following routines are subtitutes for constants SQLITE4_CORRUPT,
** SQLITE4_MISUSE, SQLITE4_CANTOPEN, SQLITE4_IOERR and possibly other error
** constants.  They server two purposes:
**
**   1.  Serve as a convenient place to set a breakpoint in a debugger
**       to detect when version error conditions occurs.
**
**   2.  Invoke sqlite4_log() to provide the source code location where
**       a low-level error is first detected.
*/
SQLITE4_PRIVATE int sqlite4CorruptError(int lineno){
  testcase( sqlite4DefaultEnv.xLog!=0 );
  sqlite4_log(0, SQLITE4_CORRUPT,
              "database corruption at line %d of [%.10s]",
              lineno, 20+sqlite4_sourceid());
  return SQLITE4_CORRUPT;
}
SQLITE4_PRIVATE int sqlite4MisuseError(int lineno){
  testcase( sqlite4DefaultEnv.xLog!=0 );
  sqlite4_log(0, SQLITE4_MISUSE, 
              "misuse at line %d of [%.10s]",
              lineno, 20+sqlite4_sourceid());
  return SQLITE4_MISUSE;
}
SQLITE4_PRIVATE int sqlite4CantopenError(int lineno){
  testcase( sqlite4DefaultEnv.xLog!=0 );
  sqlite4_log(0, SQLITE4_CANTOPEN, 
              "cannot open file at line %d of [%.10s]",
              lineno, 20+sqlite4_sourceid());
  return SQLITE4_CANTOPEN;
}


/*
** Sleep for a little while.  Return the amount of time slept.
*/
SQLITE4_API int sqlite4_sleep(int ms){
  return SQLITE4_MISUSE;
}

/*
** Invoke the xFileControl method on a particular database.
*/
SQLITE4_API int sqlite4_kvstore_control(
  sqlite4 *db,                    /* Database handle */
  const char *zDbName,            /* Name of database backend ("main" etc.) */
  int op,                         /* First argument to pass to xControl() */
  void *pArg                      /* Second argument to pass to xControl() */
){
  int rc = SQLITE4_ERROR;
  KVStore *pKV = 0;
  int i;

  sqlite4_mutex_enter(db->mutex);

  /* Find the named key-value store */
  for(i=0; i<db->nDb; i++){
    Db *pDb = &db->aDb[i];
    if( pDb->pKV && (0==zDbName || 0==sqlite4_stricmp(zDbName, pDb->zName)) ){
      pKV = pDb->pKV;
      break;
    }
  }

  /* If the named key-value store was located, invoke its xControl() method. */
  if( pKV ){
    rc = pKV->pStoreVfunc->xControl(pKV, op, pArg);
  }

  sqlite4_mutex_leave(db->mutex);
  return rc;   
}


/*
** Interface to the testing logic.
*/
SQLITE4_API int sqlite4_test_control(int op, ...){
  int rc = 0;
#ifndef SQLITE4_OMIT_BUILTIN_TEST
  va_list ap;
  va_start(ap, op);
  switch( op ){
    /*
    **  sqlite4_test_control(SQLITE4_TESTCTRL_ASSERT, int X)
    **
    ** This action provides a run-time test to see whether or not
    ** assert() was enabled at compile-time.  If X is true and assert()
    ** is enabled, then the return value is true.  If X is true and
    ** assert() is disabled, then the return value is zero.  If X is
    ** false and assert() is enabled, then the assertion fires and the
    ** process aborts.  If X is false and assert() is disabled, then the
    ** return value is zero.
    */
    case SQLITE4_TESTCTRL_ASSERT: {
      volatile int x = 0;
      assert( (x = va_arg(ap,int))!=0 );
      rc = x;
      break;
    }


    /*
    **  sqlite4_test_control(SQLITE4_TESTCTRL_ALWAYS, int X)
    **
    ** This action provides a run-time test to see how the ALWAYS and
    ** NEVER macros were defined at compile-time.
    **
    ** The return value is ALWAYS(X).  
    **
    ** The recommended test is X==2.  If the return value is 2, that means
    ** ALWAYS() and NEVER() are both no-op pass-through macros, which is the
    ** default setting.  If the return value is 1, then ALWAYS() is either
    ** hard-coded to true or else it asserts if its argument is false.
    ** The first behavior (hard-coded to true) is the case if
    ** SQLITE4_TESTCTRL_ASSERT shows that assert() is disabled and the second
    ** behavior (assert if the argument to ALWAYS() is false) is the case if
    ** SQLITE4_TESTCTRL_ASSERT shows that assert() is enabled.
    **
    ** The run-time test procedure might look something like this:
    **
    **    if( sqlite4_test_control(SQLITE4_TESTCTRL_ALWAYS, 2)==2 ){
    **      // ALWAYS() and NEVER() are no-op pass-through macros
    **    }else if( sqlite4_test_control(SQLITE4_TESTCTRL_ASSERT, 1) ){
    **      // ALWAYS(x) asserts that x is true. NEVER(x) asserts x is false.
    **    }else{
    **      // ALWAYS(x) is a constant 1.  NEVER(x) is a constant 0.
    **    }
    */
    case SQLITE4_TESTCTRL_ALWAYS: {
      int x = va_arg(ap,int);
      rc = ALWAYS(x);
      break;
    }

    /*  sqlite4_test_control(SQLITE4_TESTCTRL_OPTIMIZATIONS, sqlite4 *db, int N)
    **
    ** Enable or disable various optimizations for testing purposes.  The 
    ** argument N is a bitmask of optimizations to be disabled.  For normal
    ** operation N should be 0.  The idea is that a test program (like the
    ** SQL Logic Test or SLT test module) can run the same SQL multiple times
    ** with various optimizations disabled to verify that the same answer
    ** is obtained in every case.
    */
    case SQLITE4_TESTCTRL_OPTIMIZATIONS: {
      sqlite4 *db = va_arg(ap, sqlite4*);
      int x = va_arg(ap,int);
      db->flags = (x & SQLITE4_OptMask) | (db->flags & ~SQLITE4_OptMask);
      break;
    }

#ifdef SQLITE4_N_KEYWORD
    /* sqlite4_test_control(SQLITE4_TESTCTRL_ISKEYWORD, const char *zWord)
    **
    ** If zWord is a keyword recognized by the parser, then return the
    ** number of keywords.  Or if zWord is not a keyword, return 0.
    ** 
    ** This test feature is only available in the amalgamation since
    ** the SQLITE4_N_KEYWORD macro is not defined in this file if SQLite
    ** is built using separate source files.
    */
    case SQLITE4_TESTCTRL_ISKEYWORD: {
      const char *zWord = va_arg(ap, const char*);
      int n = sqlite4Strlen30(zWord);
      rc = (sqlite4KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE4_N_KEYWORD : 0;
      break;
    }
#endif 

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

#if defined(SQLITE4_ENABLE_TREE_EXPLAIN)
    /*   sqlite4_test_control(SQLITE4_TESTCTRL_EXPLAIN_STMT,
    **                        sqlite4_stmt*,const char**);
    **
    ** If compiled with SQLITE4_ENABLE_TREE_EXPLAIN, each sqlite4_stmt holds
    ** a string that describes the optimized parse tree.  This test-control
    ** returns a pointer to that string.
    */
    case SQLITE4_TESTCTRL_EXPLAIN_STMT: {
      sqlite4_stmt *pStmt = va_arg(ap, sqlite4_stmt*);
      const char **pzRet = va_arg(ap, const char**);
      *pzRet = sqlite4VdbeExplanation((Vdbe*)pStmt);
      break;
    }
#endif

    case SQLITE4_TESTCTRL_PRNG_GET: {
      sqlite4_env *pEnv = va_arg(ap, sqlite4_env *);
      sqlite4_int64 *piOut = va_arg(ap, sqlite4_int64 *);
      if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
      *piOut = (sqlite4_int64)(((u64)pEnv->prngX << 32) + pEnv->prngY);
      break;
    }
    case SQLITE4_TESTCTRL_PRNG_SET: {
      sqlite4_env *pEnv = va_arg(ap, sqlite4_env *);
      u64 iVal = (u64)va_arg(ap, sqlite4_int64);
      if( pEnv==0 ) pEnv = &sqlite4DefaultEnv;
      pEnv->prngX = (iVal>>32);
      pEnv->prngY = (iVal & 0xFFFFFFFF);
      break;
    }
  }
  va_end(ap);
#endif /* SQLITE4_OMIT_BUILTIN_TEST */
  return rc;
}

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

/*
** Return a boolean value for a query parameter.
*/
SQLITE4_API int sqlite4_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
  const char *z = sqlite4_uri_parameter(zFilename, zParam);
  return z ? sqlite4GetBoolean(z) : (bDflt!=0);
}

/*
** Return a 64-bit integer value for a query parameter.
*/
SQLITE4_API sqlite4_int64 sqlite4_uri_int64(
  const char *zFilename,    /* Filename as passed to xOpen */
  const char *zParam,       /* URI parameter sought */
  sqlite4_int64 bDflt       /* return if parameter is missing */
){
  const char *z = sqlite4_uri_parameter(zFilename, zParam);
  sqlite4_int64 v;
  if( z && sqlite4Atoi64(z, &v, sqlite4Strlen30(z), SQLITE4_UTF8)==SQLITE4_OK ){
    bDflt = v;
  }
  return bDflt;
}

/************** End of main.c ************************************************/
