diff --git a/Data/SQLite/src/sqlite3.c b/Data/SQLite/src/sqlite3.c index f501d0b31..f69816e2a 100644 --- a/Data/SQLite/src/sqlite3.c +++ b/Data/SQLite/src/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.7.10. By combining all the individual C code files into this +** version 3.7.13. 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 @@ -443,15 +443,22 @@ #endif /* -** Many people are failing to set -DNDEBUG=1 when compiling SQLite. -** Setting NDEBUG makes the code smaller and run faster. So the following -** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1 -** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that +** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true, +** make it true by defining or undefining NDEBUG. +** +** Setting NDEBUG makes the code smaller and run faster by disabling the +** number assert() statements in the code. So we want the default action +** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG +** is set. Thus NDEBUG becomes an opt-in rather than an opt-out ** feature. */ #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) # define NDEBUG 1 #endif +#if defined(NDEBUG) && defined(SQLITE_DEBUG) +# undef NDEBUG +#endif /* ** The testcase() macro is used to aid in coverage testing. When @@ -657,9 +664,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.7.10" -#define SQLITE_VERSION_NUMBER 3007010 -#define SQLITE_SOURCE_ID "2012-01-16 13:28:40 ebd01a8deffb5024a5d7494eef800d2366d97204" +#define SQLITE_VERSION "3.7.13" +#define SQLITE_VERSION_NUMBER 3007013 +#define SQLITE_SOURCE_ID "2012-06-11 02:05:22 f5b5a13f7394dc143aa136f1d4faba6839eaa6dc" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -1008,9 +1015,11 @@ SQLITE_API int sqlite3_exec( #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) +#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations @@ -1026,6 +1035,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ #define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ @@ -1266,7 +1276,8 @@ struct sqlite3_io_methods { ** into an integer that the pArg argument points to. This capability ** is used during testing and only needs to be supported when SQLITE_TEST ** is defined. -** +** */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 @@ -1365,6 +1408,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_OVERWRITE 11 #define SQLITE_FCNTL_VFSNAME 12 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 +#define SQLITE_FCNTL_PRAGMA 14 /* ** CAPI3REF: Mutex Handle @@ -2062,7 +2106,7 @@ struct sqlite3_mem_methods { ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] -**
SQLITE_CONFIG_PCACHE and SQLITE_CONFNIG_GETPCACHE +**
SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE **
These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** @@ -2683,12 +2727,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); ** implementation of these routines to be omitted. That capability ** is no longer provided. Only built-in memory allocators can be used. ** -** The Windows OS interface layer calls +** Prior to SQLite version 3.7.10, the Windows OS interface layer called ** the system malloc() and free() directly when converting ** filenames between the UTF-8 encoding used by SQLite ** and whatever filename encoding is used by the particular Windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or +** installation. Memory allocation errors were detected, but +** they were reported back as [SQLITE_CANTOPEN] or ** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. ** ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] @@ -3089,18 +3133,20 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** present, then the VFS specified by the option takes precedence over ** the value passed as the fourth parameter to sqlite3_open_v2(). ** -**
  • mode: ^(The mode parameter may be set to either "ro", "rw" or -** "rwc". Attempting to set it to any other value is an error)^. +**
  • mode: ^(The mode parameter may be set to either "ro", "rw", +** "rwc", or "memory". Attempting to set it to any other value is +** an error)^. ** ^If "ro" is specified, then the database is opened for read-only ** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the ** third argument to sqlite3_prepare_v2(). ^If the mode option is set to ** "rw", then the database is opened for read-write (but not create) ** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had ** been set. ^Value "rwc" is equivalent to setting both -** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is -** used, it is an error to specify a value for the mode parameter that is -** less restrictive than that specified by the flags passed as the third -** parameter. +** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is +** set to "memory" then a pure [in-memory database] that never reads +** or writes from disk is used. ^It is an error to specify a value for +** the mode parameter that is less restrictive than that specified by +** the flags passed in the third parameter to sqlite3_open_v2(). ** **
  • cache: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the @@ -3194,9 +3240,14 @@ SQLITE_API int sqlite3_open_v2( ** ** The sqlite3_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 sqlite3_uri_boolean(F,P,B) returns (B!=0). +** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the +** value of query parameter P is one of "yes", "true", or "on" in any +** case or if the value begins with a non-zero number. The +** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of +** query parameter P is one of "no", "false", or "off" in any case or +** if the value begins with a numeric zero. If P is not a query +** parameter on F or if the value of P is does not match any of the +** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). ** ** The sqlite3_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 @@ -4958,6 +5009,43 @@ SQLITE_API int sqlite3_sleep(int); */ SQLITE_API char *sqlite3_temp_directory; +/* +** CAPI3REF: Name Of The Folder Holding Database Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all database files +** specified with a relative pathname and created or accessed by +** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed +** to be relative to that directory.)^ ^If this variable is a NULL +** pointer, then SQLite assumes that all database files specified +** with a relative pathname are relative to the current directory +** for the process. Only the windows VFS makes use of this global +** variable; it is ignored by the unix VFS. +** +** Changing the value of this variable while a database connection is +** open can result in a corrupt database. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [data_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [data_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [data_store_directory pragma] should be avoided. +*/ +SQLITE_API char *sqlite3_data_directory; + /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} @@ -5009,6 +5097,15 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); */ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); +/* +** CAPI3REF: Determine if a database is read-only +** +** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N +** of connection D is read-only, 0 if it is read/write, or -1 if N is not +** the name of a database on connection D. +*/ +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); + /* ** CAPI3REF: Find the next prepared statement ** @@ -5127,7 +5224,6 @@ SQLITE_API void *sqlite3_update_hook( /* ** CAPI3REF: Enable Or Disable Shared Pager Cache -** KEYWORDS: {shared cache} ** ** ^(This routine enables or disables the sharing of the database cache ** and schema data structures between [database connection | connections] @@ -6507,6 +6603,17 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS ** is always 0. **
  • +** +** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
    SQLITE_DBSTATUS_CACHE_WRITE
    +**
    This parameter returns the number of dirty cache entries that have +** been written to disk. Specifically, the number of pages written to the +** wal file in wal mode databases, or the number of pages written to the +** database file in rollback mode databases. Any pages written as part of +** transaction rollback or database recovery operations are not included. +** If an IO or other error occurs while writing a page to disk, the effect +** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The +** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. +**
    ** */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 @@ -6518,7 +6625,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 -#define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_WRITE 9 +#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ /* @@ -7134,11 +7242,12 @@ SQLITE_API int sqlite3_unlock_notify( /* ** CAPI3REF: String Comparison ** -** ^The [sqlite3_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. +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow 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. */ +SQLITE_API int sqlite3_stricmp(const char *, const char *); SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* @@ -7473,7 +7582,11 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), +#ifdef SQLITE_RTREE_INT_ONLY + int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), +#else + int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), +#endif void *pContext ); @@ -8015,9 +8128,13 @@ struct BusyHandler { /* ** The following value as a destructor means to use sqlite3DbFree(). -** This is an internal extension to SQLITE_STATIC and SQLITE_TRANSIENT. +** The sqlite3DbFree() routine requires two parameters instead of the +** one parameter that destructors normally want. So we have to introduce +** this magic value that the code knows to handle differently. Any +** pointer will work here as long as it is distinct from SQLITE_STATIC +** and SQLITE_TRANSIENT. */ -#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3DbFree) +#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3MallocSize) /* ** When SQLITE_OMIT_WSD is defined, it means that the target platform does @@ -8177,10 +8294,9 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( ** pager.h. */ #define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */ -#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */ -#define BTREE_MEMORY 4 /* This is an in-memory DB */ -#define BTREE_SINGLE 8 /* The file contains at most 1 b-tree */ -#define BTREE_UNORDERED 16 /* Use of a hash implementation is OK */ +#define BTREE_MEMORY 2 /* This is an in-memory DB */ +#define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */ +#define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */ SQLITE_PRIVATE int sqlite3BtreeClose(Btree*); SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int); @@ -8198,7 +8314,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int); SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*); -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*); +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int); SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, int*, int flags); SQLITE_PRIVATE int sqlite3BtreeIsInTrans(Btree*); @@ -8853,8 +8969,7 @@ typedef struct PgHdr DbPage; ** NOTE: These values must match the corresponding BTREE_ values in btree.h. */ #define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */ -#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */ -#define PAGER_MEMORY 0x0004 /* In-memory database */ +#define PAGER_MEMORY 0x0002 /* In-memory database */ /* ** Valid values for the second argument to sqlite3PagerLockingMode(). @@ -8939,12 +9054,15 @@ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager); SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager); +#ifdef SQLITE_ENABLE_ZIPVFS +SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager); +#endif /* Functions used to query pager state and configuration. */ SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*); SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*); SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*); -SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*); +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int); SQLITE_PRIVATE const sqlite3_vfs *sqlite3PagerVfs(Pager*); SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*); SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*); @@ -9011,8 +9129,8 @@ struct PgHdr { void *pData; /* Page data */ void *pExtra; /* Extra content */ PgHdr *pDirty; /* Transient list of dirty pages */ - Pgno pgno; /* Page number for this page */ Pager *pPager; /* The pager this page is part of */ + Pgno pgno; /* Page number for this page */ #ifdef SQLITE_CHECK_PAGES u32 pageHash; /* Hash of page content */ #endif @@ -9214,13 +9332,11 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); # endif #endif -/* -** Define the maximum size of a temporary filename -*/ #if SQLITE_OS_WIN # include -# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) -#elif SQLITE_OS_OS2 +#endif + +#if SQLITE_OS_OS2 # if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY) # include /* has to be included before os2.h for linking to work */ # endif @@ -9233,18 +9349,27 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); # define INCL_DOSSEMAPHORES # include # include -# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP) -#else -# define SQLITE_TEMPNAME_SIZE 200 #endif /* ** Determine if we are dealing with Windows NT. +** +** We ought to be able to determine if we are compiling for win98 or winNT +** using the _WIN32_WINNT macro as follows: +** +** #if defined(_WIN32_WINNT) +** # define SQLITE_OS_WINNT 1 +** #else +** # define SQLITE_OS_WINNT 0 +** #endif +** +** However, vs2005 does not set _WIN32_WINNT by default, as it ought to, +** so the above test does not work. We'll just assume that everything is +** winNT unless the programmer explicitly says otherwise by setting +** SQLITE_OS_WINNT to 0. */ -#if defined(_WIN32_WINNT) +#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT) # define SQLITE_OS_WINNT 1 -#else -# define SQLITE_OS_WINNT 0 #endif /* @@ -9257,6 +9382,22 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void); # define SQLITE_OS_WINCE 0 #endif +/* +** Determine if we are dealing with WindowsRT (Metro) as this has a different and +** incompatible API from win32. +*/ +#if !defined(SQLITE_OS_WINRT) +# define SQLITE_OS_WINRT 0 +#endif + +/* +** When compiled for WinCE or WinRT, there is no concept of the current +** directory. + */ +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT +# define SQLITE_CURDIR 1 +#endif + /* If the SET_FULLSYNC macro is not defined above, then make it ** a no-op */ @@ -9642,35 +9783,16 @@ struct FuncDefHash { /* ** Each database connection is an instance of the following structure. -** -** The sqlite.lastRowid records the last insert rowid generated by an -** insert statement. Inserts on views do not affect its value. Each -** trigger has its own context, so that lastRowid can be updated inside -** triggers as usual. The previous value will be restored once the trigger -** exits. Upon entering a before or instead of trigger, lastRowid is no -** longer (since after version 2.8.12) reset to -1. -** -** The sqlite.nChange does not count changes within triggers and keeps no -** context. It is reset at start of sqlite3_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 just like lastRowid 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 sqlite3Error() is used to set these variables -** consistently. */ struct sqlite3 { sqlite3_vfs *pVfs; /* OS Interface */ - int nDb; /* Number of backends currently in use */ + struct Vdbe *pVdbe; /* List of active virtual machines */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + sqlite3_mutex *mutex; /* Connection mutex */ Db *aDb; /* All backends */ + int nDb; /* Number of backends currently in use */ int flags; /* Miscellaneous flags. See below */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ @@ -9681,27 +9803,23 @@ struct sqlite3 { 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() */ + u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ int nextPagesize; /* Pagesize after VACUUM if >0 */ - int nTable; /* Number of tables in the database */ - CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ - i64 lastRowid; /* ROWID of most recent insert (see above) */ u32 magic; /* Magic number for detect library misuse */ int nChange; /* Value returned by sqlite3_changes() */ int nTotalChange; /* Value returned by sqlite3_total_changes() */ - sqlite3_mutex *mutex; /* Connection mutex */ int aLimit[SQLITE_N_LIMIT]; /* Limits */ struct sqlite3InitInfo { /* Information used during initialization */ - int iDb; /* When back is being initialized */ int newTnum; /* Rootpage of table being initialized */ + u8 iDb; /* Which db file is being initialized */ u8 busy; /* TRUE if currently initializing */ u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */ } init; - 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() */ + int nExtension; /* Number of loaded extensions */ + void **aExtension; /* Array of shared library handles */ void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ @@ -9738,21 +9856,20 @@ struct sqlite3 { int nProgressOps; /* Number of opcodes for progress callback */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE + int nVTrans; /* Allocated size of aVTrans */ Hash aModule; /* populated by sqlite3_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 sqlite3_prepare() */ #endif FuncDefHash aFunc; /* Hash table of connection functions */ Hash aCollSeq; /* All collating sequences */ BusyHandler busyHandler; /* Busy callback */ - int busyTimeout; /* Busy handler timeout, in msec */ Db aDbStatic[2]; /* Static space for the 2 default backends */ Savepoint *pSavepoint; /* List of active savepoints */ + int busyTimeout; /* Busy handler timeout, in msec */ int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ - u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ @@ -9795,8 +9912,7 @@ struct sqlite3 { #define SQLITE_SqlTrace 0x00004000 /* Debug print SQL as it executes */ #define SQLITE_VdbeListing 0x00008000 /* Debug listings of VDBE programs */ #define SQLITE_WriteSchema 0x00010000 /* OK to update SQLITE_MASTER */ -#define SQLITE_NoReadlock 0x00020000 /* Readlocks are omitted when - ** accessing read-only databases */ + /* 0x00020000 Unused */ #define SQLITE_IgnoreChecks 0x00040000 /* Do not enforce check constraints */ #define SQLITE_ReadUncommitted 0x0080000 /* For shared-cache mode */ #define SQLITE_LegacyFileFmt 0x00100000 /* Create new databases in format 1 */ @@ -9879,15 +9995,18 @@ struct FuncDestructor { }; /* -** Possible values for FuncDef.flags +** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF +** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There +** are assert() statements in the code to verify this. */ #define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ #define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ #define SQLITE_FUNC_EPHEM 0x04 /* Ephemeral. Delete with VDBE */ #define SQLITE_FUNC_NEEDCOLL 0x08 /* sqlite3GetFuncCollSeq() might be called */ -#define SQLITE_FUNC_PRIVATE 0x10 /* Allowed for internal use only */ -#define SQLITE_FUNC_COUNT 0x20 /* Built-in count(*) aggregate */ -#define SQLITE_FUNC_COALESCE 0x40 /* Built-in coalesce() or ifnull() function */ +#define SQLITE_FUNC_COUNT 0x10 /* Built-in count(*) aggregate */ +#define SQLITE_FUNC_COALESCE 0x20 /* Built-in coalesce() or ifnull() function */ +#define SQLITE_FUNC_LENGTH 0x40 /* Built-in length() function */ +#define SQLITE_FUNC_TYPEOF 0x80 /* Built-in typeof() function */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -9915,7 +10034,10 @@ struct FuncDestructor { ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ + {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL), \ + SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} +#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \ + {nArg, SQLITE_UTF8, (bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ {nArg, SQLITE_UTF8, bNC*SQLITE_FUNC_NEEDCOLL, \ @@ -10145,7 +10267,7 @@ struct Table { FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ #ifndef SQLITE_OMIT_CHECK - Expr *pCheck; /* The AND of all CHECK constraints */ + ExprList *pCheck; /* All CHECK constraints */ #endif #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ @@ -10168,8 +10290,6 @@ struct 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 */ - /* @@ -10331,19 +10451,19 @@ struct UnpackedRecord { */ 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 */ 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 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ - u8 bUnordered; /* Use this index for == or IN queries only */ 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 */ + int nColumn; /* Number of columns in the table used by this index */ + int tnum; /* Page containing root of this index in database file */ + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ + u8 bUnordered; /* Use this index for == or IN queries only */ #ifdef SQLITE_ENABLE_STAT3 int nSample; /* Number of elements in aSample[] */ tRowcnt avgEq; /* Average nEq value for key values not in aSample */ @@ -10402,8 +10522,8 @@ struct AggInfo { ** than the source table */ int sortingIdx; /* Cursor number of the sorting index */ int sortingIdxPTab; /* Cursor number of pseudo-table */ - ExprList *pGroupBy; /* The group by clause */ int nSortingColumn; /* Number of columns in the sorting index */ + ExprList *pGroupBy; /* The group by clause */ struct AggInfo_col { /* For each column used in source tables */ Table *pTab; /* Source table */ int iTable; /* Cursor number of the source table */ @@ -10413,7 +10533,6 @@ struct AggInfo { Expr *pExpr; /* The original expression */ } *aCol; 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 */ @@ -10424,7 +10543,6 @@ struct AggInfo { int iDistinct; /* Ephemeral table used to enforce DISTINCT */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ - int nFuncAlloc; /* Number of slots allocated for aFunc[] */ }; /* @@ -10542,6 +10660,7 @@ struct Expr { i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ u8 flags2; /* Second set of flags. EP2_... */ u8 op2; /* If a TK_REGISTER, the original value of Expr.op */ + /* If TK_COLUMN, the value of p5 for OP_Column */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ Table *pTab; /* Table for TK_COLUMN expressions. */ #if SQLITE_MAX_EXPR_DEPTH>0 @@ -10564,7 +10683,7 @@ struct Expr { #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_Hint 0x1000 /* Not used */ #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() */ @@ -10621,9 +10740,8 @@ struct Expr { */ 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 */ - struct ExprList_item { + struct ExprList_item { /* For each expression in the list */ Expr *pExpr; /* The list of expressions */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ @@ -10631,7 +10749,7 @@ struct ExprList { 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; /* One entry for each expression */ + } *a; /* Alloc a power of two greater or equal to nExpr */ }; /* @@ -10666,7 +10784,6 @@ struct IdList { int idx; /* Index in some Table.aCol[] of a column named zName */ } *a; int nId; /* Number of identifiers on the list */ - int nAlloc; /* Number of entries allocated for a[] below */ }; /* @@ -10875,16 +10992,21 @@ 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 */ + int nRef; /* Number of names resolved by this context */ + int nErr; /* Number of errors encountered while resolving names */ + u8 ncFlags; /* Zero or more NC_* flags defined below */ }; +/* +** Allowed values for the NameContext, ncFlags field. +*/ +#define NC_AllowAgg 0x01 /* Aggregate functions are allowed here */ +#define NC_HasAgg 0x02 /* One or more aggregate functions seen */ +#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */ +#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */ + /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. @@ -10910,6 +11032,9 @@ struct Select { u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */ char affinity; /* MakeRecord with this affinity for SRT_Set */ u16 selFlags; /* Various SF_* values */ + 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 */ SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ @@ -10920,9 +11045,6 @@ struct Select { 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 */ }; /* @@ -10936,6 +11058,7 @@ struct Select { #define SF_Expanded 0x10 /* sqlite3SelectExpand() 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 */ /* @@ -11013,10 +11136,10 @@ struct AutoincInfo { */ 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 */ + SubProgram *pProgram; /* Program implementing pTrigger/orconf */ + int orconf; /* Default ON CONFLICT policy */ + u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */ }; /* @@ -11046,14 +11169,18 @@ struct TriggerPrg { */ struct Parse { sqlite3 *db; /* The main database structure */ - int rc; /* Return code from execution */ char *zErrMsg; /* An error message */ Vdbe *pVdbe; /* An engine for executing database bytecode */ + int rc; /* Return code from execution */ 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 */ + u8 nColCache; /* Number of entries in aColCache[] */ + u8 iColCache; /* Next entry in aColCache[] to replace */ + u8 isMultiWrite; /* True if statement may modify/insert multiple rows */ + u8 mayAbort; /* True if statement may throw an ABORT exception */ int aTempReg[8]; /* Holding area for temporary registers */ int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ @@ -11065,8 +11192,6 @@ struct Parse { 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 */ - u8 nColCache; /* Number of entries in aColCache[] */ - u8 iColCache; /* Next entry in aColCache[] to replace */ struct yColCache { int iTable; /* Table cursor number */ int iColumn; /* Table column number */ @@ -11077,61 +11202,64 @@ struct Parse { } aColCache[SQLITE_N_COLCACHE]; /* One for each column cache 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[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */ + int regRowid; /* Register holding rowid of CREATE TABLE entry */ + int regRoot; /* Register holding root page number for new objects */ + int nMaxArg; /* Max args passed to user function by sub-program */ + Token constraintName;/* Name of the constraint currently being parsed */ #ifndef SQLITE_OMIT_SHARED_CACHE int nTableLock; /* Number of locks in aTableLock */ TableLock *aTableLock; /* Required table locks for shared-cache mode */ #endif - int regRowid; /* Register holding rowid of CREATE TABLE entry */ - int regRoot; /* Register holding root page number for new objects */ 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 */ + double nQueryLoop; /* Estimated number of iterations of a query */ 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 (sqlite3Reprepare()) */ - 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 */ + int nVar; /* Number of '?' variables seen in the SQL so far */ + int nzVar; /* Number of available slots in azVar[] */ + u8 explain; /* True if the EXPLAIN flag is found on the query */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 declareVtab; /* True if inside sqlite3_declare_vtab() */ + int nVtabLock; /* Number of virtual tables to lock */ +#endif + int nAlias; /* Number of aliased result set columns */ + int nHeight; /* Expression tree height of current sub-select */ +#ifndef SQLITE_OMIT_EXPLAIN + int iSelectId; /* ID of current select for EXPLAIN output */ + int iNextSelectId; /* Next available select ID for EXPLAIN output */ +#endif + char **azVar; /* Pointers to names of parameters */ + Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */ + int *aAlias; /* Register used to hold aliased result */ + 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 */ + Token sNameToken; /* Token with unqualified schema object name */ + Token sLastToken; /* The last token parsed */ #ifndef SQLITE_OMIT_VIRTUALTABLE - Token sArg; /* Complete text of a module argument */ - u8 declareVtab; /* True if inside sqlite3_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 SQLITE_OMIT_EXPLAIN - int iSelectId; - int iNextSelectId; + Token sArg; /* Complete text of a module argument */ + Table **apVtabLock; /* Pointer to virtual tables needing locking */ #endif + Table *pZombieTab; /* List of Table objects to delete after code gen */ + TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */ }; +/* +** Return true if currently inside an sqlite3_declare_vtab() call. +*/ #ifdef SQLITE_OMIT_VIRTUALTABLE #define IN_DECLARE_VTAB 0 #else @@ -11148,7 +11276,7 @@ struct AuthContext { }; /* -** Bitfield flags for P5 value in OP_Insert and OP_Delete +** Bitfield flags for P5 value in various opcodes. */ #define OPFLAG_NCHANGE 0x01 /* Set to update db->nChange */ #define OPFLAG_LASTROWID 0x02 /* Set to update db->lastRowid */ @@ -11156,6 +11284,8 @@ struct AuthContext { #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ +#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ +#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ /* * Each trigger present in the database schema is stored as an instance of @@ -11282,8 +11412,8 @@ struct StrAccum { */ typedef struct { sqlite3 *db; /* The database being initialized */ - int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ char **pzErrMsg; /* Error message stored here */ + int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */ int rc; /* Result code stored here */ } InitData; @@ -11338,6 +11468,7 @@ struct Walker { union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int i; /* Integer value */ + SrcList *pSrcList; /* FROM clause */ } u; }; @@ -11425,7 +11556,7 @@ SQLITE_PRIVATE int sqlite3CantopenError(int); /* ** Internal function prototypes */ -SQLITE_PRIVATE int sqlite3StrICmp(const char *, const char *); +#define sqlite3StrICmp sqlite3_stricmp SQLITE_PRIVATE int sqlite3Strlen30(const char*); #define sqlite3StrNICmp sqlite3_strnicmp @@ -11557,7 +11688,9 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*); SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**); SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**); SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); -SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3*, int); +SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*); +SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int); +SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*); SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int); SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*); SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*); @@ -11573,6 +11706,7 @@ SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*); SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,Select*); SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*, sqlite3_vfs**,char**,char **); +SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*); SQLITE_PRIVATE int sqlite3CodeOnce(Parse *); SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32); @@ -11608,7 +11742,7 @@ SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse); # define sqlite3AutoincrementEnd(X) #endif SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); -SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int,int*,int*,int*); +SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*); SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); @@ -11638,7 +11772,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16); SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*); -SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int); +SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8); SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int); SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, int, int, int); @@ -11672,7 +11806,7 @@ SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*); SQLITE_PRIVATE void sqlite3PrngSaveState(void); SQLITE_PRIVATE void sqlite3PrngRestoreState(void); SQLITE_PRIVATE void sqlite3PrngResetState(void); -SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*); +SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int); SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int); SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb); SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int); @@ -11705,7 +11839,7 @@ SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int); SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,IdList*); SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,Select*,int); SQLITE_PRIVATE void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*); -SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int); +SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,u8); SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(sqlite3*); SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void); SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void); @@ -11846,7 +11980,7 @@ SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*); #else # define sqlite3FileSuffix3(X,Y) #endif -SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z); +SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,int); SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8); SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8); @@ -11961,6 +12095,7 @@ SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*); # define sqlite3GetVTable(X,Y) ((VTable*)0) #else SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*); +SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p); SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, char **); SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db); SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db); @@ -11972,7 +12107,7 @@ SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*); # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) #endif SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*); -SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*); +SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int); SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*); SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*); SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*); @@ -12415,6 +12550,9 @@ static const char * const azCompileOpt[] = { #ifdef SQLITE_COVERAGE_TEST "COVERAGE_TEST", #endif +#ifdef SQLITE_CURDIR + "CURDIR", +#endif #ifdef SQLITE_DEBUG "DEBUG", #endif @@ -12901,21 +13039,21 @@ typedef struct VdbeCursor VdbeCursor; typedef struct VdbeFrame VdbeFrame; struct VdbeFrame { Vdbe *v; /* VM this frame belongs to */ - int pc; /* Program Counter in parent (calling) frame */ + VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */ 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 */ + i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ + u16 nCursor; /* Number of entries in apCsr */ + int pc; /* Program Counter in parent (calling) frame */ + int nOp; /* Size of aOp array */ + int nMem; /* Number of entries in aMem */ + int nOnceFlag; /* Number of entries in aOnceFlag */ int nChildMem; /* Number of memory cells for child frame */ int nChildCsr; /* Number of cursors for child frame */ - i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ 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))]) @@ -13042,8 +13180,9 @@ struct sqlite3_context { 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 */ + int isError; /* Error code returned by the function. */ + int skipFlag; /* Skip skip accumulator loading if true */ }; /* @@ -13084,7 +13223,6 @@ struct Vdbe { 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[] */ @@ -13470,10 +13608,12 @@ SQLITE_API int sqlite3_db_status( ** to zero. */ case SQLITE_DBSTATUS_CACHE_HIT: - case SQLITE_DBSTATUS_CACHE_MISS: { + case SQLITE_DBSTATUS_CACHE_MISS: + case SQLITE_DBSTATUS_CACHE_WRITE:{ int i; int nRet = 0; assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); + assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); for(i=0; inDb; i++){ if( db->aDb[i].pBt ){ @@ -15151,7 +15291,31 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){ ** to obtain the memory it needs. ** ** This file contains implementations of the low-level memory allocation -** routines specified in the sqlite3_mem_methods object. +** routines specified in the sqlite3_mem_methods object. The content of +** this file is only used if SQLITE_SYSTEM_MALLOC is defined. The +** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the +** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined. The +** default configuration is to use memory allocation routines in this +** file. +** +** 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. +** +** SQLITE_WITHOUT_ZONEMALLOC Some older macs lack support for the zone +** memory allocator. Set this symbol to enable +** building on older macs. +** +** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of +** _msize() on windows systems. This might +** be necessary when compiling for Delphi, +** for example. */ /* @@ -15162,17 +15326,19 @@ SQLITE_PRIVATE void sqlite3MemSetDefault(void){ #ifdef SQLITE_SYSTEM_MALLOC /* -** Windows systems have malloc_usable_size() but it is called _msize() +** The MSVCRT has malloc_usable_size() but it is called _msize(). +** The use of _msize() is automatic, but can be disabled by compiling +** with -DSQLITE_WITHOUT_MSIZE */ -#if !defined(HAVE_MALLOC_USABLE_SIZE) && SQLITE_OS_WIN -# define HAVE_MALLOC_USABLE_SIZE 1 -# define malloc_usable_size _msize +#if defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE) +# define SQLITE_MALLOCSIZE _msize #endif -#if defined(__APPLE__) +#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) /* -** Use the zone allocator available on apple products +** Use the zone allocator available on apple products unless the +** SQLITE_WITHOUT_ZONEMALLOC symbol is defined. */ #include #include @@ -15187,17 +15353,23 @@ static malloc_zone_t* _sqliteZone_; #else /* if not __APPLE__ */ /* -** Use standard C library malloc and free on non-Apple systems. +** Use standard C library malloc and free on non-Apple systems. +** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined. */ #define SQLITE_MALLOC(x) malloc(x) #define SQLITE_FREE(x) free(x) #define SQLITE_REALLOC(x,y) realloc((x),(y)) +#if (defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)) \ + || (defined(HAVE_MALLOC_H) && defined(HAVE_MALLOC_USABLE_SIZE)) +# include /* Needed for malloc_usable_size on linux */ +#endif #ifdef HAVE_MALLOC_USABLE_SIZE -#include -#define SQLITE_MALLOCSIZE(x) malloc_usable_size(x) +# ifndef SQLITE_MALLOCSIZE +# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x) +# endif #else -#undef SQLITE_MALLOCSIZE +# undef SQLITE_MALLOCSIZE #endif #endif /* __APPLE__ or not __APPLE__ */ @@ -15319,7 +15491,7 @@ static int sqlite3MemRoundup(int n){ ** Initialize this module. */ static int sqlite3MemInit(void *NotUsed){ -#if defined(__APPLE__) +#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) int cpuCount; size_t len; if( _sqliteZone_ ){ @@ -18234,7 +18406,7 @@ struct sqlite3_mutex { ** this out as well. */ #if 0 -#if SQLITE_OS_WINCE +#if SQLITE_OS_WINCE || SQLITE_OS_WINRT # define mutexIsNT() (1) #else static int mutexIsNT(void){ @@ -18287,18 +18459,24 @@ static int winMutex_isInit = 0; */ static long winMutex_lock = 0; +SQLITE_API extern void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */ + static int winMutexInit(void){ /* The first to increment to 1 does actual initialization */ if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){ int i; for(i=0; iid = iType; #endif +#if SQLITE_OS_WINRT + InitializeCriticalSectionEx(&p->mutex, 0, 0); +#else InitializeCriticalSection(&p->mutex); +#endif } break; } @@ -19003,6 +19185,10 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){ } if( isLookaside(db, p) ){ LookasideSlot *pBuf = (LookasideSlot*)p; +#if SQLITE_DEBUG + /* Trash all content in the buffer being freed */ + memset(p, 0xaa, db->lookaside.sz); +#endif pBuf->pNext = db->lookaside.pFree; db->lookaside.pFree = pBuf; db->lookaside.nOut--; @@ -21188,13 +21374,13 @@ SQLITE_PRIVATE int sqlite3Dequote(char *z){ ** Some systems have stricmp(). Others have strcasecmp(). Because ** there is no consistency, we will define our own. ** -** IMPLEMENTATION-OF: R-20522-24639 The sqlite3_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. +** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and +** sqlite3_strnicmp() APIs allow 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. */ -SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){ +SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){ register unsigned char *a, *b; a = (unsigned char *)zLeft; b = (unsigned char *)zRight; @@ -24899,8 +25085,8 @@ SQLITE_API int sqlite3_os_end(void){ #endif /* - ** Default permissions when creating auto proxy dir - */ +** Default permissions when creating auto proxy dir +*/ #ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS # define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755 #endif @@ -24945,7 +25131,7 @@ struct unixFile { unixInodeInfo *pInode; /* Info about locks on this inode */ int h; /* The file descriptor */ unsigned char eFileLock; /* The type of lock held on this fd */ - unsigned char ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ + unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ @@ -24961,7 +25147,7 @@ struct unixFile { #if OS_VXWORKS struct vxworksFileId *pId; /* Unique file ID */ #endif -#ifndef NDEBUG +#ifdef SQLITE_DEBUG /* The next group of variables are used to track whether or not the ** transaction counter in bytes 24-27 of database files are updated ** whenever any part of the database changes. An assertion fault will @@ -25249,6 +25435,15 @@ static int posixOpen(const char *zFile, int flags, int mode){ return open(zFile, flags, mode); } +/* +** On some systems, calls to fchown() will trigger a message in a security +** log if they come from non-root processes. So avoid calling fchown() if +** we are not running as root. +*/ +static int posixFchown(int fd, uid_t uid, gid_t gid){ + return geteuid() ? 0 : fchown(fd,uid,gid); +} + /* Forward reference */ static int openDirectory(const char*, int*); @@ -25360,6 +25555,12 @@ static struct unix_syscall { { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 }, #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent) + { "fchown", (sqlite3_syscall_ptr)posixFchown, 0 }, +#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent) + + { "umask", (sqlite3_syscall_ptr)umask, 0 }, +#define osUmask ((mode_t(*)(mode_t))aSyscall[21].pCurrent) + }; /* End of the overrideable system calls */ /* @@ -25446,12 +25647,46 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){ } /* -** Retry open() calls that fail due to EINTR +** Invoke open(). Do so multiple times, until it either succeeds or +** fails for some reason other than EINTR. +** +** If the file creation mode "m" is 0 then set it to the default for +** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally +** 0644) as modified by the system umask. If m is not 0, then +** make the file creation mode be exactly m ignoring the umask. +** +** The m parameter will be non-zero only when creating -wal, -journal, +** and -shm files. We want those files to have *exactly* the same +** permissions as their original database, unadulterated by the umask. +** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a +** transaction crashes and leaves behind hot journals, then any +** process that is able to write to the database will also be able to +** recover the hot journals. */ -static int robust_open(const char *z, int f, int m){ - int rc; - do{ rc = osOpen(z,f,m); }while( rc<0 && errno==EINTR ); - return rc; +static int robust_open(const char *z, int f, mode_t m){ + int fd; + mode_t m2; + mode_t origM = 0; + if( m==0 ){ + m2 = SQLITE_DEFAULT_FILE_PERMISSIONS; + }else{ + m2 = m; + origM = osUmask(0); + } + do{ +#if defined(O_CLOEXEC) + fd = osOpen(z,f|O_CLOEXEC,m2); +#else + fd = osOpen(z,f,m2); +#endif + }while( fd<0 && errno==EINTR ); + if( m ){ + osUmask(origM); + } +#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0) + if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); +#endif + return fd; } /* @@ -26464,7 +26699,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){ } -#ifndef NDEBUG +#ifdef SQLITE_DEBUG /* Set up the transaction-counter change checking flags when ** transitioning from a SHARED to a RESERVED lock. The change ** from SHARED to RESERVED marks the beginning of a normal @@ -26543,7 +26778,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){ if( pFile->eFileLock>SHARED_LOCK ){ assert( pInode->eFileLock==pFile->eFileLock ); -#ifndef NDEBUG +#ifdef SQLITE_DEBUG /* When reducing a lock such that other processes can start ** reading the database file again, make sure that the ** transaction counter was updated if any part of the database @@ -27742,7 +27977,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) { SimulateIOError( h=(-1) ) SimulateIOErrorBenign(0); -#ifndef NDEBUG +#ifdef SQLITE_DEBUG /* When reducing a lock such that other processes can start ** reading the database file again, make sure that the ** transaction counter was updated if any part of the database @@ -28046,7 +28281,7 @@ static int unixWrite( ); #endif -#ifndef NDEBUG +#ifdef SQLITE_DEBUG /* If we are doing a normal write to a database file (as opposed to ** doing a hot-journal rollback or a write to some file other than a ** normal database file) then record the fact that the database @@ -28246,9 +28481,6 @@ static int openDirectory(const char *zFilename, int *pFd){ zDirname[ii] = '\0'; fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0); if( fd>=0 ){ -#ifdef FD_CLOEXEC - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); -#endif OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname)); } } @@ -28331,7 +28563,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){ ** actual file size after the operation may be larger than the requested ** size). */ - if( pFile->szChunk ){ + if( pFile->szChunk>0 ){ nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; } @@ -28340,7 +28572,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){ pFile->lastErrno = errno; return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath); }else{ -#ifndef NDEBUG +#ifdef SQLITE_DEBUG /* If we are doing a normal write to a database file (as opposed to ** doing a hot-journal rollback or a write to some file other than a ** normal database file) and we truncate the file to zero length, @@ -28497,7 +28729,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); return SQLITE_OK; } -#ifndef NDEBUG +#ifdef SQLITE_DEBUG /* The pager calls this method to signal that it has done ** a rollback and that the database is therefore unchanged and ** it hence it is OK for the transaction change counter to be @@ -28798,8 +29030,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ /* Call fstat() to figure out the permissions on the database file. If ** a new *-shm file is created, an attempt will be made to create it - ** with the same permissions. The actual permissions the file is created - ** with are subject to the current umask setting. + ** with the same permissions. */ if( osFstat(pDbFd->h, &sStat) && pInode->bProcessLock==0 ){ rc = SQLITE_IOERR_FSTAT; @@ -28843,11 +29074,15 @@ static int unixOpenSharedMemory(unixFile *pDbFd){ } pShmNode->h = robust_open(zShmFilename, openFlags, (sStat.st_mode&0777)); if( pShmNode->h<0 ){ - if( pShmNode->h<0 ){ - rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename); - goto shm_open_err; - } + rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShmFilename); + goto shm_open_err; } + + /* If this process is running as root, make sure that the SHM file + ** is owned by the same user that owns the original database. Otherwise, + ** the original owner will not be able to connect. + */ + osFchown(pShmNode->h, sStat.st_uid, sStat.st_gid); /* Check to see if another process is holding the dead-man switch. ** If not, truncate the file to zero length. @@ -29821,12 +30056,10 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ ** written to *pMode. If an IO error occurs, an SQLite error code is ** returned and the value of *pMode is not modified. ** -** If the file being opened is a temporary file, it is always created with -** the octal permissions 0600 (read/writable by owner only). If the file -** is a database or master journal file, it is created with the permissions -** mask SQLITE_DEFAULT_FILE_PERMISSIONS. -** -** Finally, if the file being opened is a WAL or regular journal file, then +** In most cases cases, this routine sets *pMode to 0, which will become +** an indication to robust_open() to create the file using +** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask. +** But if the file being opened is a WAL or regular journal file, then ** this function queries the file-system for the permissions on the ** corresponding database file and sets *pMode to this value. Whenever ** possible, WAL and journal files are created using the same permissions @@ -29840,10 +30073,14 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){ static int findCreateFileMode( const char *zPath, /* Path of file (possibly) being created */ int flags, /* Flags passed as 4th argument to xOpen() */ - mode_t *pMode /* OUT: Permissions to open file with */ + mode_t *pMode, /* OUT: Permissions to open file with */ + uid_t *pUid, /* OUT: uid to set on the file */ + gid_t *pGid /* OUT: gid to set on the file */ ){ int rc = SQLITE_OK; /* Return Code */ - *pMode = SQLITE_DEFAULT_FILE_PERMISSIONS; + *pMode = 0; + *pUid = 0; + *pGid = 0; if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ char zDb[MAX_PATHNAME+1]; /* Database file path */ int nDb; /* Number of valid bytes in zDb */ @@ -29877,6 +30114,8 @@ static int findCreateFileMode( if( 0==osStat(zDb, &sStat) ){ *pMode = sStat.st_mode & 0777; + *pUid = sStat.st_uid; + *pGid = sStat.st_gid; }else{ rc = SQLITE_IOERR_FSTAT; } @@ -30023,7 +30262,9 @@ static int unixOpen( if( fd<0 ){ mode_t openMode; /* Permissions to create file with */ - rc = findCreateFileMode(zName, flags, &openMode); + uid_t uid; /* Userid for the file */ + gid_t gid; /* Groupid for the file */ + rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); if( rc!=SQLITE_OK ){ assert( !p->pUnused ); assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); @@ -30044,6 +30285,14 @@ static int unixOpen( rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName); goto open_finished; } + + /* If this process is running as root and if creating a new rollback + ** journal or WAL file, set the ownership of the journal or WAL to be + ** the same as the original database. + */ + if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){ + osFchown(fd, uid, gid); + } } assert( fd>=0 ); if( pOutFlags ){ @@ -30068,10 +30317,6 @@ static int unixOpen( } #endif -#ifdef FD_CLOEXEC - osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC); -#endif - noLock = eType!=SQLITE_OPEN_MAIN_DB; @@ -30355,7 +30600,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ memset(zBuf, 0, nBuf); #if !defined(SQLITE_TEST) { - int pid, fd; + int pid, fd, got; fd = robust_open("/dev/urandom", O_RDONLY, 0); if( fd<0 ){ time_t t; @@ -30366,7 +30611,7 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){ assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf ); nBuf = sizeof(t) + sizeof(pid); }else{ - do{ nBuf = osRead(fd, zBuf, nBuf); }while( nBuf<0 && errno==EINTR ); + do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR ); robust_close(0, fd, __LINE__); } } @@ -30770,17 +31015,17 @@ static int proxyCreateUnixFile( } } if( fd<0 ){ - fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); + fd = robust_open(path, openFlags, 0); terrno = errno; if( fd<0 && errno==ENOENT && islockfile ){ if( proxyCreateLockPath(path) == SQLITE_OK ){ - fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); + fd = robust_open(path, openFlags, 0); } } } if( fd<0 ){ openFlags = O_RDONLY; - fd = robust_open(path, openFlags, SQLITE_DEFAULT_FILE_PERMISSIONS); + fd = robust_open(path, openFlags, 0); terrno = errno; } if( fd<0 ){ @@ -30904,8 +31149,7 @@ static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){ goto end_breaklock; } /* write it out to the temporary break file */ - fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), - SQLITE_DEFAULT_FILE_PERMISSIONS); + fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0); if( fd<0 ){ sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno); goto end_breaklock; @@ -31182,8 +31426,7 @@ static int proxyTakeConch(unixFile *pFile){ robust_close(pFile, pFile->h, __LINE__); } pFile->h = -1; - fd = robust_open(pCtx->dbPath, pFile->openFlags, - SQLITE_DEFAULT_FILE_PERMISSIONS); + fd = robust_open(pCtx->dbPath, pFile->openFlags, 0); OSTRACE(("TRANSPROXY: OPEN %d\n", fd)); if( fd>=0 ){ pFile->h = fd; @@ -31752,7 +31995,7 @@ SQLITE_API int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==20 ); + assert( ArraySize(aSyscall)==22 ); /* Register all VFSes defined in the aVfs[] array */ for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){ @@ -32009,6 +32252,13 @@ SQLITE_API int sqlite3_open_file_count = 0; /************** End of os_common.h *******************************************/ /************** Continuing where we left off in os_win.c *********************/ +/* +** Macro to find the minimum of two numeric values. +*/ +#ifndef MIN +# define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + /* ** Some Microsoft compilers lack this definition. */ @@ -32016,6 +32266,14 @@ SQLITE_API int sqlite3_open_file_count = 0; # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #endif +#ifndef FILE_FLAG_MASK +# define FILE_FLAG_MASK (0xFF3C0000) +#endif + +#ifndef FILE_ATTRIBUTE_MASK +# define FILE_ATTRIBUTE_MASK (0x0003FFF7) +#endif + /* Forward references */ typedef struct winShm winShm; /* A connection to shared-memory */ typedef struct winShmNode winShmNode; /* A region of shared-memory */ @@ -32064,11 +32322,37 @@ struct winFile { #define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ #define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ +/* + * The size of the buffer used by sqlite3_win32_write_debug(). + */ +#ifndef SQLITE_WIN32_DBG_BUF_SIZE +# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD))) +#endif + /* * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the * various Win32 API heap functions instead of our own. */ #ifdef SQLITE_WIN32_MALLOC + +/* + * If this is non-zero, an isolated heap will be created by the native Win32 + * allocator subsystem; otherwise, the default process heap will be used. This + * setting has no effect when compiling for WinRT. By default, this is enabled + * and an isolated heap will be created to store all allocated data. + * + ****************************************************************************** + * WARNING: It is important to note that when this setting is non-zero and the + * winMemShutdown function is called (e.g. by the sqlite3_shutdown + * function), all data that was allocated using the isolated heap will + * be freed immediately and any attempt to access any of that freed + * data will almost certainly result in an immediate access violation. + ****************************************************************************** + */ +#ifndef SQLITE_WIN32_HEAP_CREATE +# define SQLITE_WIN32_HEAP_CREATE (TRUE) +#endif + /* * The initial size of the Win32-specific heap. This value may be zero. */ @@ -32153,17 +32437,11 @@ SQLITE_API int sqlite3_os_type = 0; static int sqlite3_os_type = 0; #endif -/* -** Many system calls are accessed through pointer-to-functions so that -** they may be overridden at runtime to facilitate fault injection during -** testing and sandboxing. The following array holds the names and pointers -** to all overrideable system calls. -*/ -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT # define SQLITE_WIN32_HAS_ANSI #endif -#if SQLITE_OS_WINCE || SQLITE_OS_WINNT +#if SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT # define SQLITE_WIN32_HAS_WIDE #endif @@ -32171,40 +32449,35 @@ static int sqlite3_os_type = 0; # define SYSCALL sqlite3_syscall_ptr #endif -#if SQLITE_OS_WINCE /* -** These macros are necessary because Windows CE does not natively support the -** Win32 APIs LockFile, UnlockFile, and LockFileEx. - */ - -# define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) -# define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) -# define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) - -/* -** These are the special syscall hacks for Windows CE. The locking related -** defines here refer to the macros defined just above. +** This function is not available on Windows CE or WinRT. */ +#if SQLITE_OS_WINCE || SQLITE_OS_WINRT # define osAreFileApisANSI() 1 -# define osLockFile LockFile -# define osUnlockFile UnlockFile -# define osLockFileEx LockFileEx #endif +/* +** Many system calls are accessed through pointer-to-functions so that +** they may be overridden at runtime to facilitate fault injection during +** testing and sandboxing. The following array holds the names and pointers +** to all overrideable system calls. +*/ static struct win_syscall { const char *zName; /* Name of the sytem call */ sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ sqlite3_syscall_ptr pDefault; /* Default value */ } aSyscall[] = { -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 }, - -#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent) #else { "AreFileApisANSI", (SYSCALL)0, 0 }, #endif +#ifndef osAreFileApisANSI +#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent) +#endif + #if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) { "CharLowerW", (SYSCALL)CharLowerW, 0 }, #else @@ -32234,7 +32507,7 @@ static struct win_syscall { #define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "CreateFileW", (SYSCALL)CreateFileW, 0 }, #else { "CreateFileW", (SYSCALL)0, 0 }, @@ -32243,28 +32516,23 @@ static struct win_syscall { #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) - { "CreateFileMapping", (SYSCALL)CreateFileMapping, 0 }, - -#define osCreateFileMapping ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ - DWORD,DWORD,DWORD,LPCTSTR))aSyscall[6].pCurrent) - -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, #else { "CreateFileMappingW", (SYSCALL)0, 0 }, #endif #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ - DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent) + DWORD,DWORD,DWORD,LPCWSTR))aSyscall[6].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "CreateMutexW", (SYSCALL)CreateMutexW, 0 }, #else { "CreateMutexW", (SYSCALL)0, 0 }, #endif #define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \ - LPCWSTR))aSyscall[8].pCurrent) + LPCWSTR))aSyscall[7].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "DeleteFileA", (SYSCALL)DeleteFileA, 0 }, @@ -32272,7 +32540,7 @@ static struct win_syscall { { "DeleteFileA", (SYSCALL)0, 0 }, #endif -#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent) +#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[8].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "DeleteFileW", (SYSCALL)DeleteFileW, 0 }, @@ -32280,7 +32548,7 @@ static struct win_syscall { { "DeleteFileW", (SYSCALL)0, 0 }, #endif -#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent) +#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[9].pCurrent) #if SQLITE_OS_WINCE { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 }, @@ -32289,7 +32557,7 @@ static struct win_syscall { #endif #define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \ - LPFILETIME))aSyscall[11].pCurrent) + LPFILETIME))aSyscall[10].pCurrent) #if SQLITE_OS_WINCE { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 }, @@ -32298,11 +32566,11 @@ static struct win_syscall { #endif #define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \ - LPSYSTEMTIME))aSyscall[12].pCurrent) + LPSYSTEMTIME))aSyscall[11].pCurrent) { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 }, -#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent) +#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[12].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "FormatMessageA", (SYSCALL)FormatMessageA, 0 }, @@ -32311,7 +32579,7 @@ static struct win_syscall { #endif #define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \ - DWORD,va_list*))aSyscall[14].pCurrent) + DWORD,va_list*))aSyscall[13].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "FormatMessageW", (SYSCALL)FormatMessageW, 0 }, @@ -32320,15 +32588,15 @@ static struct win_syscall { #endif #define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \ - DWORD,va_list*))aSyscall[15].pCurrent) + DWORD,va_list*))aSyscall[14].pCurrent) { "FreeLibrary", (SYSCALL)FreeLibrary, 0 }, -#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent) +#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[15].pCurrent) { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 }, -#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent) +#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[16].pCurrent) #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 }, @@ -32337,16 +32605,16 @@ static struct win_syscall { #endif #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \ - LPDWORD))aSyscall[18].pCurrent) + LPDWORD))aSyscall[17].pCurrent) -#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 }, #else { "GetDiskFreeSpaceW", (SYSCALL)0, 0 }, #endif #define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \ - LPDWORD))aSyscall[19].pCurrent) + LPDWORD))aSyscall[18].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 }, @@ -32354,15 +32622,15 @@ static struct win_syscall { { "GetFileAttributesA", (SYSCALL)0, 0 }, #endif -#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent) +#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[19].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 }, #else { "GetFileAttributesW", (SYSCALL)0, 0 }, #endif -#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent) +#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[20].pCurrent) #if defined(SQLITE_WIN32_HAS_WIDE) { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 }, @@ -32371,11 +32639,15 @@ static struct win_syscall { #endif #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \ - LPVOID))aSyscall[22].pCurrent) + LPVOID))aSyscall[21].pCurrent) +#if !SQLITE_OS_WINRT { "GetFileSize", (SYSCALL)GetFileSize, 0 }, +#else + { "GetFileSize", (SYSCALL)0, 0 }, +#endif -#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent) +#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[22].pCurrent) #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 }, @@ -32384,20 +32656,20 @@ static struct win_syscall { #endif #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \ - LPSTR*))aSyscall[24].pCurrent) + LPSTR*))aSyscall[23].pCurrent) -#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 }, #else { "GetFullPathNameW", (SYSCALL)0, 0 }, #endif #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \ - LPWSTR*))aSyscall[25].pCurrent) + LPWSTR*))aSyscall[24].pCurrent) { "GetLastError", (SYSCALL)GetLastError, 0 }, -#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent) +#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[25].pCurrent) #if SQLITE_OS_WINCE /* The GetProcAddressA() routine is only available on Windows CE. */ @@ -32409,15 +32681,19 @@ static struct win_syscall { #endif #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \ - LPCSTR))aSyscall[27].pCurrent) + LPCSTR))aSyscall[26].pCurrent) +#if !SQLITE_OS_WINRT { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 }, +#else + { "GetSystemInfo", (SYSCALL)0, 0 }, +#endif -#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent) +#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[27].pCurrent) { "GetSystemTime", (SYSCALL)GetSystemTime, 0 }, -#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent) +#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[28].pCurrent) #if !SQLITE_OS_WINCE { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 }, @@ -32426,7 +32702,7 @@ static struct win_syscall { #endif #define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \ - LPFILETIME))aSyscall[30].pCurrent) + LPFILETIME))aSyscall[29].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "GetTempPathA", (SYSCALL)GetTempPathA, 0 }, @@ -32434,19 +32710,23 @@ static struct win_syscall { { "GetTempPathA", (SYSCALL)0, 0 }, #endif -#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent) +#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[30].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "GetTempPathW", (SYSCALL)GetTempPathW, 0 }, #else { "GetTempPathW", (SYSCALL)0, 0 }, #endif -#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent) +#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[31].pCurrent) +#if !SQLITE_OS_WINRT { "GetTickCount", (SYSCALL)GetTickCount, 0 }, +#else + { "GetTickCount", (SYSCALL)0, 0 }, +#endif -#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) +#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[32].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, @@ -32455,40 +32735,52 @@ static struct win_syscall { #endif #define osGetVersionExA ((BOOL(WINAPI*)( \ - LPOSVERSIONINFOA))aSyscall[34].pCurrent) + LPOSVERSIONINFOA))aSyscall[33].pCurrent) { "HeapAlloc", (SYSCALL)HeapAlloc, 0 }, #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \ - SIZE_T))aSyscall[35].pCurrent) + SIZE_T))aSyscall[34].pCurrent) +#if !SQLITE_OS_WINRT { "HeapCreate", (SYSCALL)HeapCreate, 0 }, +#else + { "HeapCreate", (SYSCALL)0, 0 }, +#endif #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \ - SIZE_T))aSyscall[36].pCurrent) + SIZE_T))aSyscall[35].pCurrent) +#if !SQLITE_OS_WINRT { "HeapDestroy", (SYSCALL)HeapDestroy, 0 }, +#else + { "HeapDestroy", (SYSCALL)0, 0 }, +#endif -#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent) +#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[36].pCurrent) { "HeapFree", (SYSCALL)HeapFree, 0 }, -#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent) +#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[37].pCurrent) { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 }, #define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \ - SIZE_T))aSyscall[39].pCurrent) + SIZE_T))aSyscall[38].pCurrent) { "HeapSize", (SYSCALL)HeapSize, 0 }, #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \ - LPCVOID))aSyscall[40].pCurrent) + LPCVOID))aSyscall[39].pCurrent) +#if !SQLITE_OS_WINRT { "HeapValidate", (SYSCALL)HeapValidate, 0 }, +#else + { "HeapValidate", (SYSCALL)0, 0 }, +#endif #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \ - LPCVOID))aSyscall[41].pCurrent) + LPCVOID))aSyscall[40].pCurrent) #if defined(SQLITE_WIN32_HAS_ANSI) { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 }, @@ -32496,107 +32788,247 @@ static struct win_syscall { { "LoadLibraryA", (SYSCALL)0, 0 }, #endif -#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent) +#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[41].pCurrent) -#if defined(SQLITE_WIN32_HAS_WIDE) +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 }, #else { "LoadLibraryW", (SYSCALL)0, 0 }, #endif -#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent) +#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[42].pCurrent) +#if !SQLITE_OS_WINRT { "LocalFree", (SYSCALL)LocalFree, 0 }, +#else + { "LocalFree", (SYSCALL)0, 0 }, +#endif -#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent) +#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[43].pCurrent) -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "LockFile", (SYSCALL)LockFile, 0 }, - -#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ - DWORD))aSyscall[45].pCurrent) #else { "LockFile", (SYSCALL)0, 0 }, #endif +#ifndef osLockFile +#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ + DWORD))aSyscall[44].pCurrent) +#endif + #if !SQLITE_OS_WINCE { "LockFileEx", (SYSCALL)LockFileEx, 0 }, - -#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ - LPOVERLAPPED))aSyscall[46].pCurrent) #else { "LockFileEx", (SYSCALL)0, 0 }, #endif +#ifndef osLockFileEx +#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ + LPOVERLAPPED))aSyscall[45].pCurrent) +#endif + +#if !SQLITE_OS_WINRT { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, +#else + { "MapViewOfFile", (SYSCALL)0, 0 }, +#endif #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ - SIZE_T))aSyscall[47].pCurrent) + SIZE_T))aSyscall[46].pCurrent) { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 }, #define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \ - int))aSyscall[48].pCurrent) + int))aSyscall[47].pCurrent) { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 }, #define osQueryPerformanceCounter ((BOOL(WINAPI*)( \ - LARGE_INTEGER*))aSyscall[49].pCurrent) + LARGE_INTEGER*))aSyscall[48].pCurrent) { "ReadFile", (SYSCALL)ReadFile, 0 }, #define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \ - LPOVERLAPPED))aSyscall[50].pCurrent) + LPOVERLAPPED))aSyscall[49].pCurrent) { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 }, -#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent) +#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[50].pCurrent) +#if !SQLITE_OS_WINRT { "SetFilePointer", (SYSCALL)SetFilePointer, 0 }, +#else + { "SetFilePointer", (SYSCALL)0, 0 }, +#endif #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \ - DWORD))aSyscall[52].pCurrent) + DWORD))aSyscall[51].pCurrent) +#if !SQLITE_OS_WINRT { "Sleep", (SYSCALL)Sleep, 0 }, +#else + { "Sleep", (SYSCALL)0, 0 }, +#endif -#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent) +#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[52].pCurrent) { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 }, #define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \ - LPFILETIME))aSyscall[54].pCurrent) + LPFILETIME))aSyscall[53].pCurrent) -#if !SQLITE_OS_WINCE +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT { "UnlockFile", (SYSCALL)UnlockFile, 0 }, - -#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ - DWORD))aSyscall[55].pCurrent) #else { "UnlockFile", (SYSCALL)0, 0 }, #endif +#ifndef osUnlockFile +#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ + DWORD))aSyscall[54].pCurrent) +#endif + #if !SQLITE_OS_WINCE { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 }, - -#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ - LPOVERLAPPED))aSyscall[56].pCurrent) #else { "UnlockFileEx", (SYSCALL)0, 0 }, #endif +#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ + LPOVERLAPPED))aSyscall[55].pCurrent) + { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, -#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent) +#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[56].pCurrent) { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 }, #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \ - LPCSTR,LPBOOL))aSyscall[58].pCurrent) + LPCSTR,LPBOOL))aSyscall[57].pCurrent) { "WriteFile", (SYSCALL)WriteFile, 0 }, #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \ - LPOVERLAPPED))aSyscall[59].pCurrent) + LPOVERLAPPED))aSyscall[58].pCurrent) + +#if SQLITE_OS_WINRT + { "CreateEventExW", (SYSCALL)CreateEventExW, 0 }, +#else + { "CreateEventExW", (SYSCALL)0, 0 }, +#endif + +#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ + DWORD,DWORD))aSyscall[59].pCurrent) + +#if !SQLITE_OS_WINRT + { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, +#else + { "WaitForSingleObject", (SYSCALL)0, 0 }, +#endif + +#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ + DWORD))aSyscall[60].pCurrent) + +#if !SQLITE_OS_WINCE + { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, +#else + { "WaitForSingleObjectEx", (SYSCALL)0, 0 }, +#endif + +#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ + BOOL))aSyscall[61].pCurrent) + +#if !SQLITE_OS_WINCE + { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 }, +#else + { "SetFilePointerEx", (SYSCALL)0, 0 }, +#endif + +#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \ + PLARGE_INTEGER,DWORD))aSyscall[62].pCurrent) + +#if SQLITE_OS_WINRT + { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 }, +#else + { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, +#endif + +#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ + FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[63].pCurrent) + +#if SQLITE_OS_WINRT + { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, +#else + { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, +#endif + +#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \ + SIZE_T))aSyscall[64].pCurrent) + +#if SQLITE_OS_WINRT + { "CreateFile2", (SYSCALL)CreateFile2, 0 }, +#else + { "CreateFile2", (SYSCALL)0, 0 }, +#endif + +#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \ + LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[65].pCurrent) + +#if SQLITE_OS_WINRT + { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 }, +#else + { "LoadPackagedLibrary", (SYSCALL)0, 0 }, +#endif + +#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \ + DWORD))aSyscall[66].pCurrent) + +#if SQLITE_OS_WINRT + { "GetTickCount64", (SYSCALL)GetTickCount64, 0 }, +#else + { "GetTickCount64", (SYSCALL)0, 0 }, +#endif + +#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[67].pCurrent) + +#if SQLITE_OS_WINRT + { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, +#else + { "GetNativeSystemInfo", (SYSCALL)0, 0 }, +#endif + +#define osGetNativeSystemInfo ((VOID(WINAPI*)( \ + LPSYSTEM_INFO))aSyscall[68].pCurrent) + +#if defined(SQLITE_WIN32_HAS_ANSI) + { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, +#else + { "OutputDebugStringA", (SYSCALL)0, 0 }, +#endif + +#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[69].pCurrent) + +#if defined(SQLITE_WIN32_HAS_WIDE) + { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 }, +#else + { "OutputDebugStringW", (SYSCALL)0, 0 }, +#endif + +#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[70].pCurrent) + + { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, + +#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[71].pCurrent) + +#if SQLITE_OS_WINRT + { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, +#else + { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, +#endif + +#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ + LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[72].pCurrent) }; /* End of the overrideable system calls */ @@ -32683,6 +33115,64 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){ return 0; } +/* +** This function outputs the specified (ANSI) string to the Win32 debugger +** (if available). +*/ + +SQLITE_API void sqlite3_win32_write_debug(char *zBuf, int nBuf){ + char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; + int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ + if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ + assert( nMin==-1 || nMin==0 || nMin0 ){ + memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); + memcpy(zDbgBuf, zBuf, nMin); + osOutputDebugStringA(zDbgBuf); + }else{ + osOutputDebugStringA(zBuf); + } +#elif defined(SQLITE_WIN32_HAS_WIDE) + memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); + if ( osMultiByteToWideChar( + osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf, + nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){ + return; + } + osOutputDebugStringW((LPCWSTR)zDbgBuf); +#else + if( nMin>0 ){ + memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); + memcpy(zDbgBuf, zBuf, nMin); + fprintf(stderr, "%s", zDbgBuf); + }else{ + fprintf(stderr, "%s", zBuf); + } +#endif +} + +/* +** The following routine suspends the current thread for at least ms +** milliseconds. This is equivalent to the Win32 Sleep() interface. +*/ +#if SQLITE_OS_WINRT +static HANDLE sleepObj = NULL; +#endif + +SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){ +#if SQLITE_OS_WINRT + if ( sleepObj==NULL ){ + sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, + SYNCHRONIZE); + } + assert( sleepObj!=NULL ); + osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE); +#else + osSleep(milliseconds); +#endif +} + /* ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, ** or WinCE. Return false (zero) for Win95, Win98, or WinME. @@ -32694,7 +33184,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){ ** WinNT/2K/XP so that we will know whether or not we can safely call ** the LockFileEx() API. */ -#if SQLITE_OS_WINCE +#if SQLITE_OS_WINCE || SQLITE_OS_WINRT # define isNT() (1) #else static int isNT(void){ @@ -32720,7 +33210,7 @@ static void *winMemMalloc(int nBytes){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#ifdef SQLITE_WIN32_MALLOC_VALIDATE +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif assert( nBytes>=0 ); @@ -32742,7 +33232,7 @@ static void winMemFree(void *pPrior){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#ifdef SQLITE_WIN32_MALLOC_VALIDATE +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); #endif if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ @@ -32763,7 +33253,7 @@ static void *winMemRealloc(void *pPrior, int nBytes){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#ifdef SQLITE_WIN32_MALLOC_VALIDATE +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); #endif assert( nBytes>=0 ); @@ -32791,7 +33281,7 @@ static int winMemSize(void *p){ hHeap = winMemGetHeap(); assert( hHeap!=0 ); assert( hHeap!=INVALID_HANDLE_VALUE ); -#ifdef SQLITE_WIN32_MALLOC_VALIDATE +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif if( !p ) return 0; @@ -32819,6 +33309,8 @@ static int winMemInit(void *pAppData){ if( !pWinMemData ) return SQLITE_ERROR; assert( pWinMemData->magic==WINMEM_MAGIC ); + +#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE if( !pWinMemData->hHeap ){ pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS, SQLITE_WIN32_HEAP_INIT_SIZE, @@ -32831,10 +33323,21 @@ static int winMemInit(void *pAppData){ return SQLITE_NOMEM; } pWinMemData->bOwned = TRUE; + assert( pWinMemData->bOwned ); } +#else + pWinMemData->hHeap = osGetProcessHeap(); + if( !pWinMemData->hHeap ){ + sqlite3_log(SQLITE_NOMEM, + "failed to GetProcessHeap (%d)", osGetLastError()); + return SQLITE_NOMEM; + } + pWinMemData->bOwned = FALSE; + assert( !pWinMemData->bOwned ); +#endif assert( pWinMemData->hHeap!=0 ); assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); -#ifdef SQLITE_WIN32_MALLOC_VALIDATE +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif return SQLITE_OK; @@ -32849,7 +33352,7 @@ static void winMemShutdown(void *pAppData){ if( !pWinMemData ) return; if( pWinMemData->hHeap ){ assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); -#ifdef SQLITE_WIN32_MALLOC_VALIDATE +#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); #endif if( pWinMemData->bOwned ){ @@ -33049,6 +33552,17 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ char *zOut = 0; if( isNT() ){ +#if SQLITE_OS_WINRT + WCHAR zTempWide[MAX_PATH+1]; /* NOTE: Somewhat arbitrary. */ + dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + lastErrno, + 0, + zTempWide, + MAX_PATH, + 0); +#else LPWSTR zTempWide = NULL; dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -33059,20 +33573,20 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ (LPWSTR) &zTempWide, 0, 0); +#endif if( dwLen > 0 ){ /* allocate a buffer and convert to UTF8 */ sqlite3BeginBenignMalloc(); zOut = unicodeToUtf8(zTempWide); sqlite3EndBenignMalloc(); +#if !SQLITE_OS_WINRT /* free the system buffer allocated by FormatMessage */ osLocalFree(zTempWide); +#endif } -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -** Since the ANSI version of these Windows API do not exist for WINCE, -** it's important to not reference them for WINCE builds. -*/ -#if SQLITE_OS_WINCE==0 - }else{ + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ char *zTemp = NULL; dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | @@ -33091,8 +33605,8 @@ static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ /* free the system buffer allocated by FormatMessage */ osLocalFree(zTemp); } -#endif } +#endif if( 0 == dwLen ){ sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno); }else{ @@ -33175,7 +33689,7 @@ static int retryIoerr(int *pnRetry, DWORD *pError){ if( e==ERROR_ACCESS_DENIED || e==ERROR_LOCK_VIOLATION || e==ERROR_SHARING_VIOLATION ){ - osSleep(win32IoerrRetryDelay*(1+*pnRetry)); + sqlite3_win32_sleep(win32IoerrRetryDelay*(1+*pnRetry)); ++*pnRetry; return 1; } @@ -33236,7 +33750,7 @@ struct tm *__cdecl localtime(const time_t *t) static void winceMutexAcquire(HANDLE h){ DWORD dwErr; do { - dwErr = WaitForSingleObject(h, INFINITE); + dwErr = osWaitForSingleObject(h, INFINITE); } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); } /* @@ -33367,7 +33881,7 @@ static void winceDestroyLock(winFile *pFile){ ** An implementation of the LockFile() API of Windows for CE */ static BOOL winceLockFile( - HANDLE *phFile, + LPHANDLE phFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToLockLow, @@ -33431,7 +33945,7 @@ static BOOL winceLockFile( ** An implementation of the UnlockFile API of Windows for CE */ static BOOL winceUnlockFile( - HANDLE *phFile, + LPHANDLE phFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh, DWORD nNumberOfBytesToUnlockLow, @@ -33488,35 +34002,74 @@ static BOOL winceUnlockFile( winceMutexRelease(pFile->hMutex); return bReturn; } - -/* -** An implementation of the LockFileEx() API of Windows for CE -*/ -static BOOL winceLockFileEx( - HANDLE *phFile, - DWORD dwFlags, - DWORD dwReserved, - DWORD nNumberOfBytesToLockLow, - DWORD nNumberOfBytesToLockHigh, - LPOVERLAPPED lpOverlapped -){ - UNUSED_PARAMETER(dwReserved); - UNUSED_PARAMETER(nNumberOfBytesToLockHigh); - - /* If the caller wants a shared read lock, forward this call - ** to winceLockFile */ - if (lpOverlapped->Offset == (DWORD)SHARED_FIRST && - dwFlags == 1 && - nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ - return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); - } - return FALSE; -} /* ** End of the special code for wince *****************************************************************************/ #endif /* SQLITE_OS_WINCE */ +/* +** Lock a file region. +*/ +static BOOL winLockFile( + LPHANDLE phFile, + DWORD flags, + DWORD offsetLow, + DWORD offsetHigh, + DWORD numBytesLow, + DWORD numBytesHigh +){ +#if SQLITE_OS_WINCE + /* + ** NOTE: Windows CE is handled differently here due its lack of the Win32 + ** API LockFile. + */ + return winceLockFile(phFile, offsetLow, offsetHigh, + numBytesLow, numBytesHigh); +#else + if( isNT() ){ + OVERLAPPED ovlp; + memset(&ovlp, 0, sizeof(OVERLAPPED)); + ovlp.Offset = offsetLow; + ovlp.OffsetHigh = offsetHigh; + return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp); + }else{ + return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow, + numBytesHigh); + } +#endif +} + +/* +** Unlock a file region. + */ +static BOOL winUnlockFile( + LPHANDLE phFile, + DWORD offsetLow, + DWORD offsetHigh, + DWORD numBytesLow, + DWORD numBytesHigh +){ +#if SQLITE_OS_WINCE + /* + ** NOTE: Windows CE is handled differently here due its lack of the Win32 + ** API UnlockFile. + */ + return winceUnlockFile(phFile, offsetLow, offsetHigh, + numBytesLow, numBytesHigh); +#else + if( isNT() ){ + OVERLAPPED ovlp; + memset(&ovlp, 0, sizeof(OVERLAPPED)); + ovlp.Offset = offsetLow; + ovlp.OffsetHigh = offsetHigh; + return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp); + }else{ + return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow, + numBytesHigh); + } +#endif +} + /***************************************************************************** ** The next group of routines implement the I/O methods specified ** by the sqlite3_io_methods object. @@ -33535,6 +34088,7 @@ static BOOL winceLockFileEx( ** Otherwise, set pFile->lastErrno and return non-zero. */ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){ +#if !SQLITE_OS_WINRT LONG upperBits; /* Most sig. 32 bits of new offset */ LONG lowerBits; /* Least sig. 32 bits of new offset */ DWORD dwRet; /* Value returned by SetFilePointer() */ @@ -33561,6 +34115,26 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){ } return 0; +#else + /* + ** Same as above, except that this implementation works for WinRT. + */ + + LARGE_INTEGER x; /* The new offset */ + BOOL bRet; /* Value returned by SetFilePointerEx() */ + + x.QuadPart = iOffset; + bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN); + + if(!bRet){ + pFile->lastErrno = osGetLastError(); + winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, + "seekWinFile", pFile->zPath); + return 1; + } + + return 0; +#endif } /* @@ -33584,7 +34158,7 @@ static int winClose(sqlite3_file *id){ do{ rc = osCloseHandle(pFile->h); /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ - }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (osSleep(100), 1) ); + }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); #if SQLITE_OS_WINCE #define WINCE_DELETION_ATTEMPTS 3 winceDestroyLock(pFile); @@ -33595,12 +34169,15 @@ static int winClose(sqlite3_file *id){ && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff && cnt++ < WINCE_DELETION_ATTEMPTS ){ - osSleep(100); /* Wait a little before trying again */ + sqlite3_win32_sleep(100); /* Wait a little before trying again */ } sqlite3_free(pFile->zDeleteOnClose); } #endif OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed")); + if( rc ){ + pFile->h = NULL; + } OpenCounter(-1); return rc ? SQLITE_OK : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), @@ -33618,6 +34195,9 @@ static int winRead( int amt, /* Number of bytes to read */ sqlite3_int64 offset /* Begin reading at this offset */ ){ +#if !SQLITE_OS_WINCE + OVERLAPPED overlapped; /* The offset for ReadFile. */ +#endif winFile *pFile = (winFile*)id; /* file handle */ DWORD nRead; /* Number of bytes actually read from file */ int nRetry = 0; /* Number of retrys */ @@ -33626,10 +34206,18 @@ static int winRead( SimulateIOError(return SQLITE_IOERR_READ); OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype)); +#if SQLITE_OS_WINCE if( seekWinFile(pFile, offset) ){ return SQLITE_FULL; } while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ +#else + memset(&overlapped, 0, sizeof(OVERLAPPED)); + overlapped.Offset = (LONG)(offset & 0xffffffff); + overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); + while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) && + osGetLastError()!=ERROR_HANDLE_EOF ){ +#endif DWORD lastErrno; if( retryIoerr(&nRetry, &lastErrno) ) continue; pFile->lastErrno = lastErrno; @@ -33656,7 +34244,7 @@ static int winWrite( int amt, /* Number of bytes to write */ sqlite3_int64 offset /* Offset into the file to begin writing at */ ){ - int rc; /* True if error has occured, else false */ + int rc = 0; /* True if error has occured, else false */ winFile *pFile = (winFile*)id; /* File handle */ int nRetry = 0; /* Number of retries */ @@ -33667,19 +34255,44 @@ static int winWrite( OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype)); +#if SQLITE_OS_WINCE rc = seekWinFile(pFile, offset); if( rc==0 ){ +#else + { +#endif +#if !SQLITE_OS_WINCE + OVERLAPPED overlapped; /* The offset for WriteFile. */ +#endif u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ int nRem = amt; /* Number of bytes yet to be written */ DWORD nWrite; /* Bytes written by each WriteFile() call */ DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ +#if !SQLITE_OS_WINCE + memset(&overlapped, 0, sizeof(OVERLAPPED)); + overlapped.Offset = (LONG)(offset & 0xffffffff); + overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); +#endif + while( nRem>0 ){ +#if SQLITE_OS_WINCE if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ +#else + if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ +#endif if( retryIoerr(&nRetry, &lastErrno) ) continue; break; } - if( nWrite<=0 ) break; + if( nWrite<=0 ){ + lastErrno = osGetLastError(); + break; + } +#if !SQLITE_OS_WINCE + offset += nWrite; + overlapped.Offset = (LONG)(offset & 0xffffffff); + overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); +#endif aRem += nWrite; nRem -= nWrite; } @@ -33811,23 +34424,40 @@ static int winSync(sqlite3_file *id, int flags){ ** Determine the current size of a file in bytes */ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ - DWORD upperBits; - DWORD lowerBits; winFile *pFile = (winFile*)id; - DWORD lastErrno; + int rc = SQLITE_OK; assert( id!=0 ); SimulateIOError(return SQLITE_IOERR_FSTAT); - lowerBits = osGetFileSize(pFile->h, &upperBits); - if( (lowerBits == INVALID_FILE_SIZE) - && ((lastErrno = osGetLastError())!=NO_ERROR) ) +#if SQLITE_OS_WINRT { - pFile->lastErrno = lastErrno; - return winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, - "winFileSize", pFile->zPath); + FILE_STANDARD_INFO info; + if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo, + &info, sizeof(info)) ){ + *pSize = info.EndOfFile.QuadPart; + }else{ + pFile->lastErrno = osGetLastError(); + rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, + "winFileSize", pFile->zPath); + } } - *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; - return SQLITE_OK; +#else + { + DWORD upperBits; + DWORD lowerBits; + DWORD lastErrno; + + lowerBits = osGetFileSize(pFile->h, &upperBits); + *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; + if( (lowerBits == INVALID_FILE_SIZE) + && ((lastErrno = osGetLastError())!=NO_ERROR) ){ + pFile->lastErrno = lastErrno; + rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, + "winFileSize", pFile->zPath); + } + } +#endif + return rc; } /* @@ -33837,6 +34467,30 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ # define LOCKFILE_FAIL_IMMEDIATELY 1 #endif +#ifndef LOCKFILE_EXCLUSIVE_LOCK +# define LOCKFILE_EXCLUSIVE_LOCK 2 +#endif + +/* +** Historically, SQLite has used both the LockFile and LockFileEx functions. +** When the LockFile function was used, it was always expected to fail +** immediately if the lock could not be obtained. Also, it always expected to +** obtain an exclusive lock. These flags are used with the LockFileEx function +** and reflect those expectations; therefore, they should not be changed. +*/ +#ifndef SQLITE_LOCKFILE_FLAGS +# define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \ + LOCKFILE_EXCLUSIVE_LOCK) +#endif + +/* +** Currently, SQLite never calls the LockFileEx function without wanting the +** call to fail immediately if the lock cannot be obtained. +*/ +#ifndef SQLITE_LOCKFILEEX_FLAGS +# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY) +#endif + /* ** Acquire a reader lock. ** Different API routines are called depending on whether or not this @@ -33845,22 +34499,26 @@ static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ static int getReadLock(winFile *pFile){ int res; if( isNT() ){ - OVERLAPPED ovlp; - ovlp.Offset = SHARED_FIRST; - ovlp.OffsetHigh = 0; - ovlp.hEvent = 0; - res = osLockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY, - 0, SHARED_SIZE, 0, &ovlp); -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -*/ -#if SQLITE_OS_WINCE==0 - }else{ +#if SQLITE_OS_WINCE + /* + ** NOTE: Windows CE is handled differently here due its lack of the Win32 + ** API LockFileEx. + */ + res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0); +#else + res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0, + SHARED_SIZE, 0); +#endif + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ int lk; sqlite3_randomness(sizeof(lk), &lk); pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); - res = osLockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); -#endif + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, + SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); } +#endif if( res == 0 ){ pFile->lastErrno = osGetLastError(); /* No need to log a failure to lock */ @@ -33875,14 +34533,13 @@ static int unlockReadLock(winFile *pFile){ int res; DWORD lastErrno; if( isNT() ){ - res = osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -*/ -#if SQLITE_OS_WINCE==0 - }else{ - res = osUnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); -#endif + res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); + } +#endif if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){ pFile->lastErrno = lastErrno; winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno, @@ -33953,7 +34610,8 @@ static int winLock(sqlite3_file *id, int locktype){ && (pFile->locktype==RESERVED_LOCK)) ){ int cnt = 3; - while( cnt-->0 && (res = osLockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ + while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, + PENDING_BYTE, 0, 1, 0))==0 ){ /* Try 3 times to get the pending lock. This is needed to work ** around problems caused by indexing and/or anti-virus software on ** Windows systems. @@ -33961,7 +34619,7 @@ static int winLock(sqlite3_file *id, int locktype){ ** copy this retry logic. It is a hack intended for Windows only. */ OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt)); - if( cnt ) osSleep(1); + if( cnt ) sqlite3_win32_sleep(1); } gotPendingLock = res; if( !res ){ @@ -33985,7 +34643,7 @@ static int winLock(sqlite3_file *id, int locktype){ */ if( locktype==RESERVED_LOCK && res ){ assert( pFile->locktype==SHARED_LOCK ); - res = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0); if( res ){ newLocktype = RESERVED_LOCK; }else{ @@ -34006,7 +34664,8 @@ static int winLock(sqlite3_file *id, int locktype){ assert( pFile->locktype>=SHARED_LOCK ); res = unlockReadLock(pFile); OSTRACE(("unreadlock = %d\n", res)); - res = osLockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, + SHARED_SIZE, 0); if( res ){ newLocktype = EXCLUSIVE_LOCK; }else{ @@ -34020,7 +34679,7 @@ static int winLock(sqlite3_file *id, int locktype){ ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ - osUnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); + winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); } /* Update the state of the lock has held in the file descriptor then @@ -34054,9 +34713,9 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ rc = 1; OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc)); }else{ - rc = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + rc = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0); if( rc ){ - osUnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); } rc = !rc; OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc)); @@ -34086,7 +34745,7 @@ static int winUnlock(sqlite3_file *id, int locktype){ pFile->locktype, pFile->sharedLockByte)); type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ - osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ /* This should never happen. We should always be able to ** reacquire the read lock */ @@ -34095,13 +34754,13 @@ static int winUnlock(sqlite3_file *id, int locktype){ } } if( type>=RESERVED_LOCK ){ - osUnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ unlockReadLock(pFile); } if( type>=PENDING_LOCK ){ - osUnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); + winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); } pFile->locktype = (u8)locktype; return rc; @@ -34339,25 +34998,19 @@ static int winShmSystemLock( int ofst, /* Offset to first byte to be locked/unlocked */ int nByte /* Number of bytes to lock or unlock */ ){ - OVERLAPPED ovlp; - DWORD dwFlags; int rc = 0; /* Result code form Lock/UnlockFileEx() */ /* Access to the winShmNode object is serialized by the caller */ assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); - /* Initialize the locking parameters */ - dwFlags = LOCKFILE_FAIL_IMMEDIATELY; - if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; - - memset(&ovlp, 0, sizeof(OVERLAPPED)); - ovlp.Offset = ofst; - /* Release/Acquire the system-level lock */ if( lockType==_SHM_UNLCK ){ - rc = osUnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp); + rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0); }else{ - rc = osLockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp); + /* Initialize the locking parameters */ + DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; + if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; + rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); } if( rc!= 0 ){ @@ -34795,18 +35448,30 @@ static int winShmMap( HANDLE hMap; /* file-mapping handle */ void *pMap = 0; /* Mapped memory region */ - hMap = osCreateFileMapping(pShmNode->hFile.h, +#if SQLITE_OS_WINRT + hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, + NULL, PAGE_READWRITE, nByte, NULL + ); +#else + hMap = osCreateFileMappingW(pShmNode->hFile.h, NULL, PAGE_READWRITE, 0, nByte, NULL ); +#endif OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n", (int)osGetCurrentProcessId(), pShmNode->nRegion, nByte, hMap ? "ok" : "failed")); if( hMap ){ int iOffset = pShmNode->nRegion*szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; +#if SQLITE_OS_WINRT + pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ, + iOffset - iOffsetShift, szRegion + iOffsetShift + ); +#else pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, iOffset - iOffsetShift, szRegion + iOffsetShift ); +#endif OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n", (int)osGetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion, pMap ? "ok" : "failed")); @@ -34892,13 +35557,12 @@ static void *convertUtf8Filename(const char *zFilename){ void *zConverted = 0; if( isNT() ){ zConverted = utf8ToUnicode(zFilename); -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -*/ -#if SQLITE_OS_WINCE==0 - }else{ - zConverted = sqlite3_win32_utf8_to_mbcs(zFilename); -#endif } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + zConverted = sqlite3_win32_utf8_to_mbcs(zFilename); + } +#endif /* caller will handle out of memory */ return zConverted; } @@ -34913,6 +35577,7 @@ static int getTempname(int nBuf, char *zBuf){ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789"; size_t i, j; + int nTempPath; char zTempPath[MAX_PATH+2]; /* It's odd to simulate an io-error here, but really this is just @@ -34921,9 +35586,13 @@ static int getTempname(int nBuf, char *zBuf){ */ SimulateIOError( return SQLITE_IOERR ); + memset(zTempPath, 0, MAX_PATH+2); + if( sqlite3_temp_directory ){ sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); - }else if( isNT() ){ + } +#if !SQLITE_OS_WINRT + else if( isNT() ){ char *zMulti; WCHAR zWidePath[MAX_PATH]; osGetTempPathW(MAX_PATH-30, zWidePath); @@ -34934,12 +35603,9 @@ static int getTempname(int nBuf, char *zBuf){ }else{ return SQLITE_IOERR_NOMEM; } -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -** Since the ANSI version of these Windows API do not exist for WINCE, -** it's important to not reference them for WINCE builds. -*/ -#if SQLITE_OS_WINCE==0 - }else{ + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ char *zUtf8; char zMbcsPath[MAX_PATH]; osGetTempPathA(MAX_PATH-30, zMbcsPath); @@ -34950,21 +35616,25 @@ static int getTempname(int nBuf, char *zBuf){ }else{ return SQLITE_IOERR_NOMEM; } -#endif } +#endif +#endif /* Check that the output buffer is large enough for the temporary file ** name. If it is not, return SQLITE_ERROR. */ - if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){ + nTempPath = sqlite3Strlen30(zTempPath); + + if( (nTempPath + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){ return SQLITE_ERROR; } - for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} + for(i=nTempPath; i>0 && zTempPath[i-1]=='\\'; i--){} zTempPath[i] = 0; - sqlite3_snprintf(nBuf-18, zBuf, - "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); + sqlite3_snprintf(nBuf-18, zBuf, (nTempPath > 0) ? + "%s\\"SQLITE_TEMP_FILE_PREFIX : SQLITE_TEMP_FILE_PREFIX, + zTempPath); j = sqlite3Strlen30(zBuf); sqlite3_randomness(15, &zBuf[j]); for(i=0; i<15; i++, j++){ @@ -34977,6 +35647,35 @@ static int getTempname(int nBuf, char *zBuf){ return SQLITE_OK; } +/* +** Return TRUE if the named file is really a directory. Return false if +** it is something other than a directory, or if there is any kind of memory +** allocation failure. +*/ +static int winIsDir(const void *zConverted){ + DWORD attr; + int rc = 0; + DWORD lastErrno; + + if( isNT() ){ + int cnt = 0; + WIN32_FILE_ATTRIBUTE_DATA sAttrData; + memset(&sAttrData, 0, sizeof(sAttrData)); + while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, + GetFileExInfoStandard, + &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){} + if( !rc ){ + return 0; /* Invalid name? */ + } + attr = sAttrData.dwFileAttributes; +#if SQLITE_OS_WINCE==0 + }else{ + attr = osGetFileAttributesA((char*)zConverted); +#endif + } + return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY); +} + /* ** Open a file. */ @@ -35083,6 +35782,11 @@ static int winOpen( return SQLITE_IOERR_NOMEM; } + if( winIsDir(zConverted) ){ + sqlite3_free(zConverted); + return SQLITE_CANTOPEN_ISDIR; + } + if( isReadWrite ){ dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; }else{ @@ -35126,29 +35830,48 @@ static int winOpen( #endif if( isNT() ){ +#if SQLITE_OS_WINRT + CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; + extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); + extendedParameters.dwFileAttributes = + dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK; + extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK; + extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; + extendedParameters.lpSecurityAttributes = NULL; + extendedParameters.hTemplateFile = NULL; + while( (h = osCreateFile2((LPCWSTR)zConverted, + dwDesiredAccess, + dwShareMode, + dwCreationDisposition, + &extendedParameters))==INVALID_HANDLE_VALUE && + retryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } +#else while( (h = osCreateFileW((LPCWSTR)zConverted, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL))==INVALID_HANDLE_VALUE && - retryIoerr(&cnt, &lastErrno) ){} -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -** Since the ANSI version of these Windows API do not exist for WINCE, -** it's important to not reference them for WINCE builds. -*/ -#if SQLITE_OS_WINCE==0 - }else{ + retryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } +#endif + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ while( (h = osCreateFileA((LPCSTR)zConverted, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL))==INVALID_HANDLE_VALUE && - retryIoerr(&cnt, &lastErrno) ){} -#endif + retryIoerr(&cnt, &lastErrno) ){ + /* Noop */ + } } - +#endif logIoerr(cnt); OSTRACE(("OPEN %d %s 0x%lx %s\n", @@ -35225,6 +35948,7 @@ static int winDelete( ){ int cnt = 0; int rc; + DWORD attr; DWORD lastErrno; void *zConverted; UNUSED_PARAMETER(pVfs); @@ -35236,22 +35960,61 @@ static int winDelete( return SQLITE_IOERR_NOMEM; } if( isNT() ){ - rc = 1; - while( osGetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES && - (rc = osDeleteFileW(zConverted))==0 && retryIoerr(&cnt, &lastErrno) ){} - rc = rc ? SQLITE_OK : SQLITE_ERROR; -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -** Since the ANSI version of these Windows API do not exist for WINCE, -** it's important to not reference them for WINCE builds. -*/ -#if SQLITE_OS_WINCE==0 - }else{ - rc = 1; - while( osGetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES && - (rc = osDeleteFileA(zConverted))==0 && retryIoerr(&cnt, &lastErrno) ){} - rc = rc ? SQLITE_OK : SQLITE_ERROR; + do { +#if SQLITE_OS_WINRT + WIN32_FILE_ATTRIBUTE_DATA sAttrData; + memset(&sAttrData, 0, sizeof(sAttrData)); + if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, + &sAttrData) ){ + attr = sAttrData.dwFileAttributes; + }else{ + rc = SQLITE_OK; /* Already gone? */ + break; + } +#else + attr = osGetFileAttributesW(zConverted); #endif + if ( attr==INVALID_FILE_ATTRIBUTES ){ + rc = SQLITE_OK; /* Already gone? */ + break; + } + if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ + rc = SQLITE_ERROR; /* Files only. */ + break; + } + if ( osDeleteFileW(zConverted) ){ + rc = SQLITE_OK; /* Deleted OK. */ + break; + } + if ( !retryIoerr(&cnt, &lastErrno) ){ + rc = SQLITE_ERROR; /* No more retries. */ + break; + } + } while(1); } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + do { + attr = osGetFileAttributesA(zConverted); + if ( attr==INVALID_FILE_ATTRIBUTES ){ + rc = SQLITE_OK; /* Already gone? */ + break; + } + if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ + rc = SQLITE_ERROR; /* Files only. */ + break; + } + if ( osDeleteFileA(zConverted) ){ + rc = SQLITE_OK; /* Deleted OK. */ + break; + } + if ( !retryIoerr(&cnt, &lastErrno) ){ + rc = SQLITE_ERROR; /* No more retries. */ + break; + } + } while(1); + } +#endif if( rc ){ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); @@ -35311,15 +36074,12 @@ static int winAccess( attr = INVALID_FILE_ATTRIBUTES; } } -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -** Since the ANSI version of these Windows API do not exist for WINCE, -** it's important to not reference them for WINCE builds. -*/ -#if SQLITE_OS_WINCE==0 - }else{ - attr = osGetFileAttributesA((char*)zConverted); -#endif } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + attr = osGetFileAttributesA((char*)zConverted); + } +#endif sqlite3_free(zConverted); switch( flags ){ case SQLITE_ACCESS_READ: @@ -35338,6 +36098,43 @@ static int winAccess( } +/* +** Returns non-zero if the specified path name should be used verbatim. If +** non-zero is returned from this function, the calling function must simply +** use the provided path name verbatim -OR- resolve it into a full path name +** using the GetFullPathName Win32 API function (if available). +*/ +static BOOL winIsVerbatimPathname( + const char *zPathname +){ + /* + ** If the path name starts with a forward slash or a backslash, it is either + ** a legal UNC name, a volume relative path, or an absolute path name in the + ** "Unix" format on Windows. There is no easy way to differentiate between + ** the final two cases; therefore, we return the safer return value of TRUE + ** so that callers of this function will simply use it verbatim. + */ + if ( zPathname[0]=='/' || zPathname[0]=='\\' ){ + return TRUE; + } + + /* + ** If the path name starts with a letter and a colon it is either a volume + ** relative path or an absolute path. Callers of this function must not + ** attempt to treat it as a relative path name (i.e. they should simply use + ** it verbatim). + */ + if ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ){ + return TRUE; + } + + /* + ** If we get to this point, the path name should almost certainly be a purely + ** relative one (i.e. not a UNC name, not absolute, and not volume relative). + */ + return FALSE; +} + /* ** Turn a relative pathname into a full pathname. Write the full ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname @@ -35353,19 +36150,51 @@ static int winFullPathname( #if defined(__CYGWIN__) SimulateIOError( return SQLITE_ERROR ); UNUSED_PARAMETER(nFull); - cygwin_conv_to_full_win32_path(zRelative, zFull); + assert( pVfs->mxPathname>=MAX_PATH ); + assert( nFull>=pVfs->mxPathname ); + if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ + /* + ** NOTE: We are dealing with a relative path name and the data + ** directory has been set. Therefore, use it as the basis + ** for converting the relative path name to an absolute + ** one by prepending the data directory and a slash. + */ + char zOut[MAX_PATH+1]; + memset(zOut, 0, MAX_PATH+1); + cygwin_conv_to_win32_path(zRelative, zOut); /* POSIX to Win32 */ + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s", + sqlite3_data_directory, zOut); + }else{ + /* + ** NOTE: The Cygwin docs state that the maximum length needed + ** for the buffer passed to cygwin_conv_to_full_win32_path + ** is MAX_PATH. + */ + cygwin_conv_to_full_win32_path(zRelative, zFull); + } return SQLITE_OK; #endif -#if SQLITE_OS_WINCE +#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__) SimulateIOError( return SQLITE_ERROR ); - UNUSED_PARAMETER(nFull); /* WinCE has no concept of a relative pathname, or so I am told. */ - sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); + /* WinRT has no way to convert a relative path to an absolute one. */ + if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ + /* + ** NOTE: We are dealing with a relative path name and the data + ** directory has been set. Therefore, use it as the basis + ** for converting the relative path name to an absolute + ** one by prepending the data directory and a backslash. + */ + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s", + sqlite3_data_directory, zRelative); + }else{ + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative); + } return SQLITE_OK; #endif -#if !SQLITE_OS_WINCE && !defined(__CYGWIN__) +#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) int nByte; void *zConverted; char *zOut; @@ -35383,7 +36212,17 @@ static int winFullPathname( ** current working directory has been unlinked. */ SimulateIOError( return SQLITE_ERROR ); - UNUSED_PARAMETER(nFull); + if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ + /* + ** NOTE: We are dealing with a relative path name and the data + ** directory has been set. Therefore, use it as the basis + ** for converting the relative path name to an absolute + ** one by prepending the data directory and a backslash. + */ + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s", + sqlite3_data_directory, zRelative); + return SQLITE_OK; + } zConverted = convertUtf8Filename(zRelative); if( zConverted==0 ){ return SQLITE_IOERR_NOMEM; @@ -35400,12 +36239,9 @@ static int winFullPathname( sqlite3_free(zConverted); zOut = unicodeToUtf8(zTemp); sqlite3_free(zTemp); -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -** Since the ANSI version of these Windows API do not exist for WINCE, -** it's important to not reference them for WINCE builds. -*/ -#if SQLITE_OS_WINCE==0 - }else{ + } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ char *zTemp; nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) ); @@ -35417,10 +36253,10 @@ static int winFullPathname( sqlite3_free(zConverted); zOut = sqlite3_win32_mbcs_to_utf8(zTemp); sqlite3_free(zTemp); -#endif } +#endif if( zOut ){ - sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); + sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); sqlite3_free(zOut); return SQLITE_OK; }else{ @@ -35446,16 +36282,17 @@ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ return 0; } if( isNT() ){ +#if SQLITE_OS_WINRT + h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0); +#else h = osLoadLibraryW((LPCWSTR)zConverted); -/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed. -** Since the ANSI version of these Windows API do not exist for WINCE, -** it's important to not reference them for WINCE builds. -*/ -#if SQLITE_OS_WINCE==0 - }else{ - h = osLoadLibraryA((char*)zConverted); #endif } +#ifdef SQLITE_WIN32_HAS_ANSI + else{ + h = osLoadLibraryA((char*)zConverted); + } +#endif sqlite3_free(zConverted); return (void*)h; } @@ -35500,11 +36337,19 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ memcpy(&zBuf[n], &pid, sizeof(pid)); n += sizeof(pid); } +#if SQLITE_OS_WINRT + if( sizeof(ULONGLONG)<=nBuf-n ){ + ULONGLONG cnt = osGetTickCount64(); + memcpy(&zBuf[n], &cnt, sizeof(cnt)); + n += sizeof(cnt); + } +#else if( sizeof(DWORD)<=nBuf-n ){ DWORD cnt = osGetTickCount(); memcpy(&zBuf[n], &cnt, sizeof(cnt)); n += sizeof(cnt); } +#endif if( sizeof(LARGE_INTEGER)<=nBuf-n ){ LARGE_INTEGER i; osQueryPerformanceCounter(&i); @@ -35520,7 +36365,7 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ ** Sleep for a little while. Return the amount of time slept. */ static int winSleep(sqlite3_vfs *pVfs, int microsec){ - osSleep((microsec+999)/1000); + sqlite3_win32_sleep((microsec+999)/1000); UNUSED_PARAMETER(pVfs); return ((microsec+999)/1000)*1000; } @@ -35662,12 +36507,16 @@ SQLITE_API int sqlite3_os_init(void){ /* Double-check that the aSyscall[] array has been constructed ** correctly. See ticket [bb3a86e890c8e96ab] */ - assert( ArraySize(aSyscall)==60 ); + assert( ArraySize(aSyscall)==73 ); #ifndef SQLITE_OMIT_WAL /* get memory map allocation granularity */ memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); +#if SQLITE_OS_WINRT + osGetNativeSystemInfo(&winSysInfo); +#else osGetSystemInfo(&winSysInfo); +#endif assert(winSysInfo.dwAllocationGranularity > 0); #endif @@ -35676,6 +36525,12 @@ SQLITE_API int sqlite3_os_init(void){ } SQLITE_API int sqlite3_os_end(void){ +#if SQLITE_OS_WINRT + if( sleepObj != NULL ){ + osCloseHandle(sleepObj); + sleepObj = NULL; + } +#endif return SQLITE_OK; } @@ -36791,6 +37646,7 @@ struct PCache1 { unsigned int nMin; /* Minimum number of pages reserved */ unsigned int nMax; /* Configured "cache_size" value */ unsigned int n90pct; /* nMax*9/10 */ + unsigned int iMaxKey; /* Largest key seen since xTruncate() */ /* Hash table of all pages. The following variables may only be accessed ** when the accessor is holding the PGroup mutex. @@ -36799,8 +37655,6 @@ struct PCache1 { unsigned int nPage; /* Total number of pages in apHash */ unsigned int nHash; /* Number of slots in apHash[] */ PgHdr1 **apHash; /* Hash table for fast lookup by key */ - - unsigned int iMaxKey; /* Largest key seen since xTruncate() */ }; /* @@ -36844,8 +37698,8 @@ static SQLITE_WSD struct PCacheGlobal { void *pStart, *pEnd; /* Bounds of pagecache malloc range */ /* Above requires no mutex. Use mutex below for variable that follow. */ sqlite3_mutex *mutex; /* Mutex for accessing the following: */ - int nFreeSlot; /* Number of unused pcache slots */ PgFreeslot *pFree; /* Free page blocks */ + int nFreeSlot; /* Number of unused pcache slots */ /* The following value requires a mutex to change. We skip the mutex on ** reading because (1) most platforms read a 32-bit integer atomically and ** (2) even if an incorrect value is read, no great harm is done since this @@ -36928,12 +37782,14 @@ static void *pcache1Alloc(int nByte){ ** it from sqlite3Malloc instead. */ p = sqlite3Malloc(nByte); +#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS if( p ){ int sz = sqlite3MallocSize(p); sqlite3_mutex_enter(pcache1.mutex); sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz); sqlite3_mutex_leave(pcache1.mutex); } +#endif sqlite3MemdebugSetType(p, MEMTYPE_PCACHE); } return p; @@ -36960,9 +37816,11 @@ static int pcache1Free(void *p){ assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) ); sqlite3MemdebugSetType(p, MEMTYPE_HEAP); nFreed = sqlite3MallocSize(p); +#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS sqlite3_mutex_enter(pcache1.mutex); sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed); sqlite3_mutex_leave(pcache1.mutex); +#endif sqlite3_free(p); } return nFreed; @@ -37812,6 +38670,11 @@ SQLITE_PRIVATE void sqlite3PcacheStats( /* ** Each entry in a RowSet is an instance of the following object. +** +** This same object is reused to store a linked list of trees of RowSetEntry +** objects. In that alternative use, pRight points to the next entry +** in the list, pLeft points to the tree, and v is unused. The +** RowSet.pForest value points to the head of this forest list. */ struct RowSetEntry { i64 v; /* ROWID value for this entry */ @@ -37841,12 +38704,18 @@ struct RowSet { struct RowSetEntry *pEntry; /* List of entries using pRight */ struct RowSetEntry *pLast; /* Last entry on the pEntry list */ struct RowSetEntry *pFresh; /* Source of new entry objects */ - struct RowSetEntry *pTree; /* Binary tree of entries */ + struct RowSetEntry *pForest; /* List of binary trees of entries */ u16 nFresh; /* Number of objects on pFresh */ - u8 isSorted; /* True if pEntry is sorted */ + u8 rsFlags; /* Various flags */ u8 iBatch; /* Current insert batch */ }; +/* +** Allowed values for RowSet.rsFlags +*/ +#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */ +#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */ + /* ** Turn bulk memory into a RowSet object. N bytes of memory ** are available at pSpace. The db pointer is used as a memory context @@ -37867,10 +38736,10 @@ SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db, void *pSpace, unsigned int p->db = db; p->pEntry = 0; p->pLast = 0; - p->pTree = 0; + p->pForest = 0; p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p); p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry)); - p->isSorted = 1; + p->rsFlags = ROWSET_SORTED; p->iBatch = 0; return p; } @@ -37890,8 +38759,33 @@ SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ p->nFresh = 0; p->pEntry = 0; p->pLast = 0; - p->pTree = 0; - p->isSorted = 1; + p->pForest = 0; + p->rsFlags = ROWSET_SORTED; +} + +/* +** Allocate a new RowSetEntry object that is associated with the +** given RowSet. Return a pointer to the new and completely uninitialized +** objected. +** +** In an OOM situation, the RowSet.db->mallocFailed flag is set and this +** routine returns NULL. +*/ +static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){ + assert( p!=0 ); + if( p->nFresh==0 ){ + struct RowSetChunk *pNew; + pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); + if( pNew==0 ){ + return 0; + } + pNew->pNextChunk = p->pChunk; + p->pChunk = pNew; + p->pFresh = pNew->aEntry; + p->nFresh = ROWSET_ENTRY_PER_CHUNK; + } + p->nFresh--; + return p->pFresh++; } /* @@ -37903,30 +38797,21 @@ SQLITE_PRIVATE void sqlite3RowSetClear(RowSet *p){ SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){ struct RowSetEntry *pEntry; /* The new entry */ struct RowSetEntry *pLast; /* The last prior entry */ - assert( p!=0 ); - if( p->nFresh==0 ){ - struct RowSetChunk *pNew; - pNew = sqlite3DbMallocRaw(p->db, sizeof(*pNew)); - if( pNew==0 ){ - return; - } - pNew->pNextChunk = p->pChunk; - p->pChunk = pNew; - p->pFresh = pNew->aEntry; - p->nFresh = ROWSET_ENTRY_PER_CHUNK; - } - pEntry = p->pFresh++; - p->nFresh--; + + /* This routine is never called after sqlite3RowSetNext() */ + assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); + + pEntry = rowSetEntryAlloc(p); + if( pEntry==0 ) return; pEntry->v = rowid; pEntry->pRight = 0; pLast = p->pLast; if( pLast ){ - if( p->isSorted && rowid<=pLast->v ){ - p->isSorted = 0; + if( (p->rsFlags & ROWSET_SORTED)!=0 && rowid<=pLast->v ){ + p->rsFlags &= ~ROWSET_SORTED; } pLast->pRight = pEntry; }else{ - assert( p->pEntry==0 ); /* Fires if INSERT after SMALLEST */ p->pEntry = pEntry; } p->pLast = pEntry; @@ -37938,7 +38823,7 @@ SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){ ** The input lists are connected via pRight pointers and are ** assumed to each already be in sorted order. */ -static struct RowSetEntry *rowSetMerge( +static struct RowSetEntry *rowSetEntryMerge( struct RowSetEntry *pA, /* First sorted list to be merged */ struct RowSetEntry *pB /* Second sorted list to be merged */ ){ @@ -37972,32 +38857,29 @@ static struct RowSetEntry *rowSetMerge( } /* -** Sort all elements on the pEntry list of the RowSet into ascending order. +** Sort all elements on the list of RowSetEntry objects into order of +** increasing v. */ -static void rowSetSort(RowSet *p){ +static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){ unsigned int i; - struct RowSetEntry *pEntry; - struct RowSetEntry *aBucket[40]; + struct RowSetEntry *pNext, *aBucket[40]; - assert( p->isSorted==0 ); memset(aBucket, 0, sizeof(aBucket)); - while( p->pEntry ){ - pEntry = p->pEntry; - p->pEntry = pEntry->pRight; - pEntry->pRight = 0; + while( pIn ){ + pNext = pIn->pRight; + pIn->pRight = 0; for(i=0; aBucket[i]; i++){ - pEntry = rowSetMerge(aBucket[i], pEntry); + pIn = rowSetEntryMerge(aBucket[i], pIn); aBucket[i] = 0; } - aBucket[i] = pEntry; + aBucket[i] = pIn; + pIn = pNext; } - pEntry = 0; + pIn = 0; for(i=0; ipEntry = pEntry; - p->pLast = 0; - p->isSorted = 1; + return pIn; } @@ -38091,20 +38973,37 @@ static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){ } /* -** 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. +** Take all the entries on p->pEntry and on the trees in p->pForest and +** sort them all together into one big ordered list on p->pEntry. +** +** This routine should only be called once in the life of a RowSet. */ static void rowSetToList(RowSet *p){ - if( !p->isSorted ){ - rowSetSort(p); + + /* This routine is called only once */ + assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 ); + + if( (p->rsFlags & ROWSET_SORTED)==0 ){ + p->pEntry = rowSetEntrySort(p->pEntry); } - if( p->pTree ){ - struct RowSetEntry *pHead, *pTail; - rowSetTreeToList(p->pTree, &pHead, &pTail); - p->pTree = 0; - p->pEntry = rowSetMerge(p->pEntry, pHead); + + /* While this module could theoretically support it, sqlite3RowSetNext() + ** is never called after sqlite3RowSetText() for the same RowSet. So + ** there is never a forest to deal with. Should this change, simply + ** remove the assert() and the #if 0. */ + assert( p->pForest==0 ); +#if 0 + while( p->pForest ){ + struct RowSetEntry *pTree = p->pForest->pLeft; + if( pTree ){ + struct RowSetEntry *pHead, *pTail; + rowSetTreeToList(pTree, &pHead, &pTail); + p->pEntry = rowSetEntryMerge(p->pEntry, pHead); + } + p->pForest = p->pForest->pRight; } +#endif + p->rsFlags |= ROWSET_NEXT; /* Verify this routine is never called again */ } /* @@ -38116,7 +39015,12 @@ static void rowSetToList(RowSet *p){ ** routine may not be called again. */ SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ - rowSetToList(p); + assert( p!=0 ); + + /* Merge the forest into a single sorted list on first call */ + if( (p->rsFlags & ROWSET_NEXT)==0 ) rowSetToList(p); + + /* Return the next entry on the list */ if( p->pEntry ){ *pRowid = p->pEntry->v; p->pEntry = p->pEntry->pRight; @@ -38132,26 +39036,66 @@ SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){ /* ** Check to see if element iRowid was inserted into the the rowset as ** part of any insert batch prior to iBatch. Return 1 or 0. +** +** If this is the first test of a new batch and if there exist entires +** on pRowSet->pEntry, then sort those entires into the forest at +** pRowSet->pForest so that they can be tested. */ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){ - struct RowSetEntry *p; + struct RowSetEntry *p, *pTree; + + /* This routine is never called after sqlite3RowSetNext() */ + assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 ); + + /* Sort entries into the forest on the first test of a new batch + */ if( iBatch!=pRowSet->iBatch ){ - if( pRowSet->pEntry ){ - rowSetToList(pRowSet); - pRowSet->pTree = rowSetListToTree(pRowSet->pEntry); + p = pRowSet->pEntry; + if( p ){ + struct RowSetEntry **ppPrevTree = &pRowSet->pForest; + if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ + p = rowSetEntrySort(p); + } + for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ + ppPrevTree = &pTree->pRight; + if( pTree->pLeft==0 ){ + pTree->pLeft = rowSetListToTree(p); + break; + }else{ + struct RowSetEntry *pAux, *pTail; + rowSetTreeToList(pTree->pLeft, &pAux, &pTail); + pTree->pLeft = 0; + p = rowSetEntryMerge(pAux, p); + } + } + if( pTree==0 ){ + *ppPrevTree = pTree = rowSetEntryAlloc(pRowSet); + if( pTree ){ + pTree->v = 0; + pTree->pRight = 0; + pTree->pLeft = rowSetListToTree(p); + } + } pRowSet->pEntry = 0; pRowSet->pLast = 0; + pRowSet->rsFlags |= ROWSET_SORTED; } pRowSet->iBatch = iBatch; } - p = pRowSet->pTree; - while( p ){ - if( p->vpRight; - }else if( p->v>iRowid ){ - p = p->pLeft; - }else{ - return 1; + + /* Test to see if the iRowid value appears anywhere in the forest. + ** Return 1 if it does and 0 if not. + */ + for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){ + p = pTree->pLeft; + while( p ){ + if( p->vpRight; + }else if( p->v>iRowid ){ + p = p->pLeft; + }else{ + return 1; + } } } return 0; @@ -38226,6 +39170,7 @@ SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 i # define sqlite3WalCallback(z) 0 # define sqlite3WalExclusiveMode(y,z) 0 # define sqlite3WalHeapMemory(z) 0 +# define sqlite3WalFramesize(z) 0 #else #define WAL_SAVEPOINT_NDATA 4 @@ -38307,6 +39252,13 @@ SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op); */ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal); +#ifdef SQLITE_ENABLE_ZIPVFS +/* If the WAL file is not empty, return the number of bytes of content +** stored in each frame (i.e. the db page-size when the WAL was created). +*/ +SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal); +#endif + #endif /* ifndef SQLITE_OMIT_WAL */ #endif /* _WAL_H_ */ @@ -38903,7 +39855,6 @@ struct Pager { u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */ u8 useJournal; /* Use a rollback journal on this file */ - u8 noReadlock; /* Do not bother to obtain readlocks */ u8 noSync; /* Do not sync the journal if true */ u8 fullSync; /* Do extra syncs of the journal for robustness */ u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */ @@ -38962,9 +39913,9 @@ struct Pager { char *zJournal; /* Name of the journal file */ int (*xBusyHandler)(void*); /* Function to call when busy */ void *pBusyHandlerArg; /* Context argument for xBusyHandler */ - int nHit, nMiss; /* Total cache hits and misses */ + int aStat[3]; /* Total cache hits, misses and writes */ #ifdef SQLITE_TEST - int nRead, nWrite; /* Database pages read/written */ + int nRead; /* Database pages read */ #endif void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */ #ifdef SQLITE_HAS_CODEC @@ -38981,6 +39932,15 @@ struct Pager { #endif }; +/* +** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains +** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS +** or CACHE_WRITE to sqlite3_db_status(). +*/ +#define PAGER_STAT_HIT 0 +#define PAGER_STAT_MISS 1 +#define PAGER_STAT_WRITE 2 + /* ** The following global variables hold counters used for ** testing purposes only. These variables do not exist in @@ -39151,7 +40111,7 @@ static int assert_pager_state(Pager *p){ case PAGER_READER: assert( pPager->errCode==SQLITE_OK ); assert( p->eLock!=UNKNOWN_LOCK ); - assert( p->eLock>=SHARED_LOCK || p->noReadlock ); + assert( p->eLock>=SHARED_LOCK ); break; case PAGER_WRITER_LOCKED: @@ -41263,6 +42223,7 @@ static int pagerWalFrames( int isCommit /* True if this is a commit */ ){ int rc; /* Return code */ + int nList; /* Number of pages in pList */ #if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES) PgHdr *p; /* For looping over pages */ #endif @@ -41276,6 +42237,7 @@ static int pagerWalFrames( } #endif + assert( pList->pDirty==0 || isCommit ); if( isCommit ){ /* If a WAL transaction is being committed, there is no point in writing ** any pages with page numbers greater than nTruncate into the WAL file. @@ -41283,11 +42245,18 @@ static int pagerWalFrames( ** list here. */ PgHdr *p; PgHdr **ppNext = &pList; - for(p=pList; (*ppNext = p); p=p->pDirty){ - if( p->pgno<=nTruncate ) ppNext = &p->pDirty; + nList = 0; + for(p=pList; (*ppNext = p)!=0; p=p->pDirty){ + if( p->pgno<=nTruncate ){ + ppNext = &p->pDirty; + nList++; + } } assert( pList ); + }else{ + nList = 1; } + pPager->aStat[PAGER_STAT_WRITE] += nList; if( pList->pgno==1 ) pager_write_changecounter(pList); rc = sqlite3WalFrames(pPager->pWal, @@ -41360,7 +42329,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ ** contains no valid committed transactions. */ assert( pPager->eState==PAGER_OPEN ); - assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock ); + assert( pPager->eLock>=SHARED_LOCK ); nPage = sqlite3WalDbsize(pPager->pWal); /* If the database size was not available from the WAL sub-system, @@ -41415,7 +42384,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){ static int pagerOpenWalIfPresent(Pager *pPager){ int rc = SQLITE_OK; assert( pPager->eState==PAGER_OPEN ); - assert( pPager->eLock>=SHARED_LOCK || pPager->noReadlock ); + assert( pPager->eLock>=SHARED_LOCK ); if( !pPager->tempFile ){ int isWal; /* True if WAL file exists */ @@ -42355,6 +43324,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ if( pgno>pPager->dbFileSize ){ pPager->dbFileSize = pgno; } + pPager->aStat[PAGER_STAT_WRITE]++; /* Update any backup objects copying the contents of this pager. */ sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)pList->pData); @@ -42363,7 +43333,6 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){ PAGERID(pPager), pgno, pager_pagehash(pList))); IOTRACE(("PGOUT %p %d\n", pPager, pgno)); PAGER_INCR(sqlite3_pager_writedb_count); - PAGER_INCR(pPager->nWrite); }else{ PAGERTRACE(("NOSTORE %d page %d\n", PAGERID(pPager), pgno)); } @@ -42578,7 +43547,7 @@ static int pagerStress(void *p, PgHdr *pPg){ ** ** The flags argument is used to specify properties that affect the ** operation of the pager. It should be passed some bitwise combination -** of the PAGER_OMIT_JOURNAL and PAGER_NO_READLOCK flags. +** of the PAGER_* flags. ** ** The vfsFlags parameter is a bitmask to pass to the flags parameter ** of the xOpen() method of the supplied VFS when opening files. @@ -42609,7 +43578,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen( char *zPathname = 0; /* Full path to database file */ int nPathname = 0; /* Number of bytes in zPathname */ int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; /* False to omit journal */ - int noReadlock = (flags & PAGER_NO_READLOCK)!=0; /* True to omit read-lock */ int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */ u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */ const char *zUri = 0; /* URI args to copy */ @@ -42635,7 +43603,12 @@ SQLITE_PRIVATE int sqlite3PagerOpen( #ifndef SQLITE_OMIT_MEMORYDB if( flags & PAGER_MEMORY ){ memDb = 1; - zFilename = 0; + if( zFilename && zFilename[0] ){ + zPathname = sqlite3DbStrDup(0, zFilename); + if( zPathname==0 ) return SQLITE_NOMEM; + nPathname = sqlite3Strlen30(zPathname); + zFilename = 0; + } } #endif @@ -42646,7 +43619,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( if( zFilename && zFilename[0] ){ const char *z; nPathname = pVfs->mxPathname+1; - zPathname = sqlite3Malloc(nPathname*2); + zPathname = sqlite3DbMallocRaw(0, nPathname*2); if( zPathname==0 ){ return SQLITE_NOMEM; } @@ -42670,7 +43643,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( rc = SQLITE_CANTOPEN_BKPT; } if( rc!=SQLITE_OK ){ - sqlite3_free(zPathname); + sqlite3DbFree(0, zPathname); return rc; } } @@ -42700,7 +43673,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( ); assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) ); if( !pPtr ){ - sqlite3_free(zPathname); + sqlite3DbFree(0, zPathname); return SQLITE_NOMEM; } pPager = (Pager*)(pPtr); @@ -42716,7 +43689,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( assert( nPathname>0 ); pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri); memcpy(pPager->zFilename, zPathname, nPathname); - memcpy(&pPager->zFilename[nPathname+1], zUri, nUri); + if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri); memcpy(pPager->zJournal, zPathname, nPathname); memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+1); sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal); @@ -42726,7 +43699,7 @@ SQLITE_PRIVATE int sqlite3PagerOpen( memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1); sqlite3FileSuffix3(pPager->zFilename, pPager->zWal); #endif - sqlite3_free(zPathname); + sqlite3DbFree(0, zPathname); } pPager->pVfs = pVfs; pPager->vfsFlags = vfsFlags; @@ -42816,7 +43789,6 @@ SQLITE_PRIVATE int sqlite3PagerOpen( IOTRACE(("OPEN %p %s\n", pPager, pPager->zFilename)) pPager->useJournal = (u8)useJournal; - pPager->noReadlock = (noReadlock && readOnly) ?1:0; /* pPager->stmtOpen = 0; */ /* pPager->stmtInUse = 0; */ /* pPager->nRef = 0; */ @@ -43038,14 +44010,11 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){ int bHotJournal = 1; /* True if there exists a hot journal-file */ assert( !MEMDB ); - assert( pPager->noReadlock==0 || pPager->readOnly ); - if( pPager->noReadlock==0 ){ - rc = pager_wait_on_lock(pPager, SHARED_LOCK); - if( rc!=SQLITE_OK ){ - assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK ); - goto failed; - } + rc = pager_wait_on_lock(pPager, SHARED_LOCK); + if( rc!=SQLITE_OK ){ + assert( pPager->eLock==NO_LOCK || pPager->eLock==UNKNOWN_LOCK ); + goto failed; } /* If a journal file exists, and there is no RESERVED lock on the @@ -43326,7 +44295,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire( /* In this case the pcache already contains an initialized copy of ** the page. Return without further ado. */ assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) ); - pPager->nHit++; + pPager->aStat[PAGER_STAT_HIT]++; return SQLITE_OK; }else{ @@ -43368,7 +44337,7 @@ SQLITE_PRIVATE int sqlite3PagerAcquire( IOTRACE(("ZERO %p %d\n", pPager, pgno)); }else{ assert( pPg->pPager==pPager ); - pPager->nMiss++; + pPager->aStat[PAGER_STAT_MISS]++; rc = readDbPage(pPg); if( rc!=SQLITE_OK ){ goto pager_acquire_err; @@ -43953,6 +44922,7 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){ CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM, zBuf); if( rc==SQLITE_OK ){ rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0); + pPager->aStat[PAGER_STAT_WRITE]++; } if( rc==SQLITE_OK ){ pPager->changeCountDone = 1; @@ -44396,11 +45366,11 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ a[3] = pPager->eState==PAGER_OPEN ? -1 : (int) pPager->dbSize; a[4] = pPager->eState; a[5] = pPager->errCode; - a[6] = pPager->nHit; - a[7] = pPager->nMiss; + a[6] = pPager->aStat[PAGER_STAT_HIT]; + a[7] = pPager->aStat[PAGER_STAT_MISS]; a[8] = 0; /* Used to be pPager->nOvfl */ a[9] = pPager->nRead; - a[10] = pPager->nWrite; + a[10] = pPager->aStat[PAGER_STAT_WRITE]; return a; } #endif @@ -44413,20 +45383,19 @@ SQLITE_PRIVATE int *sqlite3PagerStats(Pager *pPager){ ** returning. */ SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *pPager, int eStat, int reset, int *pnVal){ - int *piStat; assert( eStat==SQLITE_DBSTATUS_CACHE_HIT || eStat==SQLITE_DBSTATUS_CACHE_MISS + || eStat==SQLITE_DBSTATUS_CACHE_WRITE ); - if( eStat==SQLITE_DBSTATUS_CACHE_HIT ){ - piStat = &pPager->nHit; - }else{ - piStat = &pPager->nMiss; - } - *pnVal += *piStat; + assert( SQLITE_DBSTATUS_CACHE_HIT+1==SQLITE_DBSTATUS_CACHE_MISS ); + assert( SQLITE_DBSTATUS_CACHE_HIT+2==SQLITE_DBSTATUS_CACHE_WRITE ); + assert( PAGER_STAT_HIT==0 && PAGER_STAT_MISS==1 && PAGER_STAT_WRITE==2 ); + + *pnVal += pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT]; if( reset ){ - *piStat = 0; + pPager->aStat[eStat - SQLITE_DBSTATUS_CACHE_HIT] = 0; } } @@ -44575,9 +45544,16 @@ SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ /* ** Return the full pathname of the database file. +** +** Except, if the pager is in-memory only, then return an empty string if +** nullIfMemDb is true. This routine is called with nullIfMemDb==1 when +** used to report the filename to the user, for compatibility with legacy +** behavior. But when the Btree needs to know the filename for matching to +** shared cache, it uses nullIfMemDb==0 so that in-memory databases can +** participate in shared-cache. */ -SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager){ - return pPager->zFilename; +SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){ + return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename; } /* @@ -45053,7 +46029,7 @@ static int pagerOpenWal(Pager *pPager){ int rc = SQLITE_OK; assert( pPager->pWal==0 && pPager->tempFile==0 ); - assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK || pPager->noReadlock); + assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK ); /* If the pager is already in exclusive-mode, the WAL module will use ** heap-memory for the wal-index instead of the VFS shared-memory @@ -45168,6 +46144,20 @@ SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager){ return rc; } +#ifdef SQLITE_ENABLE_ZIPVFS +/* +** A read-lock must be held on the pager when this function is called. If +** the pager is in WAL mode and the WAL file currently contains one or more +** frames, return the size in bytes of the page images stored within the +** WAL frames. Otherwise, if this is not a WAL database or the WAL file +** is empty, return 0. +*/ +SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager){ + assert( pPager->eState==PAGER_READER ); + return sqlite3WalFramesize(pPager->pWal); +} +#endif + #ifdef SQLITE_HAS_CODEC /* ** This function is called by the wal module when writing page content @@ -47587,7 +48577,7 @@ SQLITE_PRIVATE int sqlite3WalRead( iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE; *pInWal = 1; /* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */ - return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset); + return sqlite3OsRead(pWal->pWalFd, pOut, (nOut>sz ? sz : nOut), iOffset); } *pInWal = 0; @@ -48258,6 +49248,18 @@ SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal){ return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ); } +#ifdef SQLITE_ENABLE_ZIPVFS +/* +** If the argument is not NULL, it points to a Wal object that holds a +** read-lock. This function returns the database page-size if it is known, +** or zero if it is not (or if pWal is NULL). +*/ +SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){ + assert( pWal==0 || pWal->readLock>=0 ); + return (pWal ? pWal->szPage : 0); +} +#endif + #endif /* #ifndef SQLITE_OMIT_WAL */ /************** End of wal.c *************************************************/ @@ -48566,10 +49568,9 @@ struct MemPage { u16 nFree; /* Number of free bytes on the page */ u16 nCell; /* Number of cells on this page, local and ovfl */ u16 maskPage; /* Mask for page offset */ - struct _OvflCell { /* Cells that will not fit on aData[] */ - u8 *pCell; /* Pointers to the body of the overflow cell */ - u16 idx; /* Insert this cell before idx-th non-overflow cell */ - } aOvfl[5]; + u16 aiOvfl[5]; /* Insert the i-th overflow cell before the aiOvfl-th + ** non-overflow cell */ + u8 *apOvfl[5]; /* Pointers to the body of overflow cells */ BtShared *pBt; /* Pointer to BtShared that this page is part of */ u8 *aData; /* Pointer to disk image of the page data */ u8 *aDataEnd; /* One byte past the end of usable data */ @@ -48777,6 +49778,9 @@ struct BtCursor { BtShared *pBt; /* The BtShared this cursor points to */ BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ +#ifndef SQLITE_OMIT_INCRBLOB + Pgno *aOverflow; /* Cache of overflow page locations */ +#endif Pgno pgnoRoot; /* The root page of this tree */ sqlite3_int64 cachedRowid; /* Next rowid cache. 0 means not valid */ CellInfo info; /* A parse of the cell we are pointing at */ @@ -48788,7 +49792,6 @@ struct BtCursor { u8 validNKey; /* True if info.nKey is valid */ u8 eState; /* One of the CURSOR_XXX constants (see below) */ #ifndef SQLITE_OMIT_INCRBLOB - Pgno *aOverflow; /* Cache of overflow page locations */ u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ #endif i16 iPage; /* Index of current page in apPage */ @@ -48912,13 +49915,19 @@ struct BtCursor { /* ** This structure is passed around through all the sanity checking routines ** in order to keep track of some global state information. +** +** The aRef[] array is allocated so that there is 1 bit for each page in +** the database. As the integrity-check proceeds, for each page used in +** the database the corresponding bit is set. This allows integrity-check to +** detect pages that are used twice and orphaned pages (both of which +** indicate corruption). */ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ + u8 *aPgRef; /* 1 bit per page in the db (see above) */ Pgno nPage; /* Number of pages in the database */ - int *anRef; /* Number of times each page is referenced */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int mallocFailed; /* A memory allocation error has occurred */ @@ -50078,12 +51087,10 @@ static u8 *findOverflowCell(MemPage *pPage, int iCell){ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); for(i=pPage->nOverflow-1; i>=0; i--){ int k; - struct _OvflCell *pOvfl; - pOvfl = &pPage->aOvfl[i]; - k = pOvfl->idx; + k = pPage->aiOvfl[i]; if( k<=iCell ){ if( k==iCell ){ - return pOvfl->pCell; + return pPage->apOvfl[i]; } iCell--; } @@ -50897,11 +51904,8 @@ static int btreeInvokeBusyHandler(void *pArg){ ** If zFilename is ":memory:" then an in-memory database is created ** that is automatically destroyed when it is closed. ** -** The "flags" parameter is a bitmask that might contain bits -** BTREE_OMIT_JOURNAL and/or BTREE_NO_READLOCK. The BTREE_NO_READLOCK -** bit is also set if the SQLITE_NoReadlock flags is set in db->flags. -** These flags are passed through into sqlite3PagerOpen() and must -** be the same values as PAGER_OMIT_JOURNAL and PAGER_NO_READLOCK. +** The "flags" parameter is a bitmask that might contain bits like +** BTREE_OMIT_JOURNAL and/or BTREE_MEMORY. ** ** If the database is already opened in the same database connection ** and we are in shared cache mode, then the open will fail with an @@ -50934,7 +51938,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( const int isMemdb = 0; #else const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0) - || (isTempDb && sqlite3TempInMemory(db)); + || (isTempDb && sqlite3TempInMemory(db)) + || (vfsFlags & SQLITE_OPEN_MEMORY)!=0; #endif assert( db!=0 ); @@ -50948,9 +51953,6 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( /* A BTREE_SINGLE database is always a temporary and/or ephemeral */ assert( (flags & BTREE_SINGLE)==0 || isTempDb ); - if( db->flags & SQLITE_NoReadlock ){ - flags |= BTREE_NO_READLOCK; - } if( isMemdb ){ flags |= BTREE_MEMORY; } @@ -50973,7 +51975,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( ** If this Btree is a candidate for shared cache, try to find an ** existing BtShared object that we can share with */ - if( isMemdb==0 && isTempDb==0 ){ + if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){ if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){ int nFullPathname = pVfs->mxPathname+1; char *zFullPathname = sqlite3Malloc(nFullPathname); @@ -50983,11 +51985,16 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( sqlite3_free(p); return SQLITE_NOMEM; } - rc = sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname); - if( rc ){ - sqlite3_free(zFullPathname); - sqlite3_free(p); - return rc; + if( isMemdb ){ + memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1); + }else{ + rc = sqlite3OsFullPathname(pVfs, zFilename, + nFullPathname, zFullPathname); + if( rc ){ + sqlite3_free(zFullPathname); + sqlite3_free(p); + return rc; + } } #if SQLITE_THREADSAFE mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN); @@ -50997,7 +52004,7 @@ SQLITE_PRIVATE int sqlite3BtreeOpen( #endif for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){ assert( pBt->nRef>0 ); - if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) + if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0)) && sqlite3PagerVfs(pBt->pPager)==pVfs ){ int iDb; for(iDb=db->nDb-1; iDb>=0; iDb--){ @@ -51257,7 +52264,7 @@ SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){ ** The call to sqlite3BtreeRollback() drops any table-locks held by ** this handle. */ - sqlite3BtreeRollback(p); + sqlite3BtreeRollback(p, SQLITE_OK); sqlite3BtreeLeave(p); /* If there are still other outstanding references to the shared-btree @@ -52495,6 +53502,7 @@ static int countWriteCursors(BtShared *pBt){ */ SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ BtCursor *p; + if( pBtree==0 ) return; sqlite3BtreeEnter(pBtree); for(p=pBtree->pBt->pCursor; p; p=p->pNext){ int i; @@ -52518,25 +53526,20 @@ SQLITE_PRIVATE void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){ ** This will release the write lock on the database file. If there ** are no active cursors, it also releases the read lock. */ -SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p){ +SQLITE_PRIVATE int sqlite3BtreeRollback(Btree *p, int tripCode){ int rc; BtShared *pBt = p->pBt; MemPage *pPage1; sqlite3BtreeEnter(p); - rc = saveAllCursors(pBt, 0, 0); -#ifndef SQLITE_OMIT_SHARED_CACHE - if( rc!=SQLITE_OK ){ - /* This is a horrible situation. An IO or malloc() error occurred whilst - ** trying to save cursor positions. If this is an automatic rollback (as - ** the result of a constraint, malloc() failure or IO error) then - ** the cache may be internally inconsistent (not contain valid trees) so - ** we cannot simply return the error to the caller. Instead, abort - ** all queries that may be using any of the cursors that failed to save. - */ - sqlite3BtreeTripAllCursors(p, rc); + if( tripCode==SQLITE_OK ){ + rc = tripCode = saveAllCursors(pBt, 0, 0); + }else{ + rc = SQLITE_OK; + } + if( tripCode ){ + sqlite3BtreeTripAllCursors(p, tripCode); } -#endif btreeIntegrity(p); if( p->inTrans==TRANS_WRITE ){ @@ -54735,7 +55738,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){ ** If the cell content will fit on the page, then put it there. If it ** will not fit, then make a copy of the cell content into pTemp if ** pTemp is not null. Regardless of pTemp, allocate a new entry -** in pPage->aOvfl[] and make it point to the cell content (either +** in pPage->apOvfl[] and make it point to the cell content (either ** in pTemp or the original pCell) and also record its index. ** Allocating a new entry in pPage->aCell[] implies that ** pPage->nOverflow is incremented. @@ -54769,7 +55772,8 @@ static void insertCell( assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 ); - assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) ); + assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); + assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); /* The cell should normally be sized correctly. However, when moving a ** malformed cell from a leaf page to an interior page, if the cell size @@ -54786,9 +55790,9 @@ static void insertCell( put4byte(pCell, iChild); } j = pPage->nOverflow++; - assert( j<(int)(sizeof(pPage->aOvfl)/sizeof(pPage->aOvfl[0])) ); - pPage->aOvfl[j].pCell = pCell; - pPage->aOvfl[j].idx = (u16)i; + assert( j<(int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])) ); + pPage->apOvfl[j] = pCell; + pPage->aiOvfl[j] = (u16)i; }else{ int rc = sqlite3PagerWrite(pPage->pDbPage); if( rc!=SQLITE_OK ){ @@ -54936,7 +55940,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){ if( rc==SQLITE_OK ){ u8 *pOut = &pSpace[4]; - u8 *pCell = pPage->aOvfl[0].pCell; + u8 *pCell = pPage->apOvfl[0]; u16 szCell = cellSizePtr(pPage, pCell); u8 *pStop; @@ -55046,7 +56050,7 @@ static int ptrmapCheckPages(MemPage **apPage, int nPage){ ** map entries are also updated so that the parent page is page pTo. ** ** If pFrom is currently carrying any overflow cells (entries in the -** MemPage.aOvfl[] array), they are not copied to pTo. +** MemPage.apOvfl[] array), they are not copied to pTo. ** ** Before returning, page pTo is reinitialized using btreeInitPage(). ** @@ -55183,7 +56187,7 @@ static int balance_nonroot( ** is called (indirectly) from sqlite3BtreeDelete(). */ assert( pParent->nOverflow==0 || pParent->nOverflow==1 ); - assert( pParent->nOverflow==0 || pParent->aOvfl[0].idx==iParentIdx ); + assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx ); if( !aOvflSpace ){ return SQLITE_NOMEM; @@ -55230,8 +56234,8 @@ static int balance_nonroot( nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; if( (i--)==0 ) break; - if( i+nxDiv==pParent->aOvfl[0].idx && pParent->nOverflow ){ - apDiv[i] = pParent->aOvfl[0].pCell; + if( i+nxDiv==pParent->aiOvfl[0] && pParent->nOverflow ){ + apDiv[i] = pParent->apOvfl[0]; pgno = get4byte(apDiv[i]); szNew[i] = cellSizePtr(pParent, apDiv[i]); pParent->nOverflow = 0; @@ -55672,7 +56676,7 @@ static int balance_nonroot( MemPage *pOld = apCopy[0]; int nOverflow = pOld->nOverflow; int iNextOld = pOld->nCell + nOverflow; - int iOverflow = (nOverflow ? pOld->aOvfl[0].idx : -1); + int iOverflow = (nOverflow ? pOld->aiOvfl[0] : -1); j = 0; /* Current 'old' sibling page */ k = 0; /* Current 'new' sibling page */ for(i=0; inCell + pOld->nOverflow; if( pOld->nOverflow ){ nOverflow = pOld->nOverflow; - iOverflow = i + !leafData + pOld->aOvfl[0].idx; + iOverflow = i + !leafData + pOld->aiOvfl[0]; } isDivider = !leafData; } assert(nOverflow>0 || iOverflowaOvfl[0].idx==pOld->aOvfl[1].idx-1); - assert(nOverflow<3 || pOld->aOvfl[1].idx==pOld->aOvfl[2].idx-1); + assert(nOverflow<2 || pOld->aiOvfl[0]==pOld->aiOvfl[1]-1); + assert(nOverflow<3 || pOld->aiOvfl[1]==pOld->aiOvfl[2]-1); if( i==iOverflow ){ isDivider = 1; if( (--nOverflow)>0 ){ @@ -55814,7 +56818,10 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){ TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); /* Copy the overflow cells from pRoot to pChild */ - memcpy(pChild->aOvfl, pRoot->aOvfl, pRoot->nOverflow*sizeof(pRoot->aOvfl[0])); + memcpy(pChild->aiOvfl, pRoot->aiOvfl, + pRoot->nOverflow*sizeof(pRoot->aiOvfl[0])); + memcpy(pChild->apOvfl, pRoot->apOvfl, + pRoot->nOverflow*sizeof(pRoot->apOvfl[0])); pChild->nOverflow = pRoot->nOverflow; /* Zero the contents of pRoot. Then install pChild as the right-child. */ @@ -55877,7 +56884,7 @@ static int balance(BtCursor *pCur){ #ifndef SQLITE_OMIT_QUICKBALANCE if( pPage->hasData && pPage->nOverflow==1 - && pPage->aOvfl[0].idx==pPage->nCell + && pPage->aiOvfl[0]==pPage->nCell && pParent->pgno!=1 && pParent->nCell==iIdx ){ @@ -56005,13 +57012,6 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( ** blob of associated data. */ assert( (pKey==0)==(pCur->pKeyInfo==0) ); - /* If this is an insert into a table b-tree, invalidate any incrblob - ** cursors open on the row being replaced (assuming this is a replace - ** operation - if it is not, the following is a no-op). */ - if( pCur->pKeyInfo==0 ){ - invalidateIncrblobCursors(p, nKey, 0); - } - /* Save the positions of any other cursors open on this table. ** ** In some cases, the call to btreeMoveto() below is a no-op. For @@ -56025,6 +57025,14 @@ SQLITE_PRIVATE int sqlite3BtreeInsert( */ rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); if( rc ) return rc; + + /* If this is an insert into a table b-tree, invalidate any incrblob + ** cursors open on the row being replaced (assuming this is a replace + ** operation - if it is not, the following is a no-op). */ + if( pCur->pKeyInfo==0 ){ + invalidateIncrblobCursors(p, nKey, 0); + } + if( !loc ){ rc = btreeMoveto(pCur, pKey, nKey, appendBias, &loc); if( rc ) return rc; @@ -56135,12 +57143,6 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ return SQLITE_ERROR; /* Something has gone awry. */ } - /* If this is a delete operation to remove a row from a table b-tree, - ** invalidate any incrblob cursors open on the row being deleted. */ - if( pCur->pKeyInfo==0 ){ - invalidateIncrblobCursors(p, pCur->info.nKey, 0); - } - iCellDepth = pCur->iPage; iCellIdx = pCur->aiIdx[iCellDepth]; pPage = pCur->apPage[iCellDepth]; @@ -56166,6 +57168,13 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor *pCur){ */ rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); if( rc ) return rc; + + /* If this is a delete operation to remove a row from a table b-tree, + ** invalidate any incrblob cursors open on the row being deleted. */ + if( pCur->pKeyInfo==0 ){ + invalidateIncrblobCursors(p, pCur->info.nKey, 0); + } + rc = sqlite3PagerWrite(pPage->pDbPage); if( rc ) return rc; rc = clearCell(pPage, pCell); @@ -56447,13 +57456,13 @@ SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){ sqlite3BtreeEnter(p); assert( p->inTrans==TRANS_WRITE ); - /* Invalidate all incrblob cursors open on table iTable (assuming iTable - ** is the root of a table b-tree - if it is not, the following call is - ** a no-op). */ - invalidateIncrblobCursors(p, 0, 1); - rc = saveAllCursors(pBt, (Pgno)iTable, 0); + if( SQLITE_OK==rc ){ + /* Invalidate all incrblob cursors open on table iTable (assuming iTable + ** is the root of a table b-tree - if it is not, the following call is + ** a no-op). */ + invalidateIncrblobCursors(p, 0, 1); rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange); } sqlite3BtreeLeave(p); @@ -56768,6 +57777,25 @@ static void checkAppendMsg( #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ #ifndef SQLITE_OMIT_INTEGRITY_CHECK + +/* +** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that +** corresponds to page iPg is already set. +*/ +static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){ + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07))); +} + +/* +** Set the bit in the IntegrityCk.aPgRef[] array that corresponds to page iPg. +*/ +static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){ + assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 ); + pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07)); +} + + /* ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. @@ -56782,11 +57810,12 @@ static int checkRef(IntegrityCk *pCheck, Pgno iPage, char *zContext){ checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); return 1; } - if( pCheck->anRef[iPage]==1 ){ + if( getPageReferenced(pCheck, iPage) ){ checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); return 1; } - return (pCheck->anRef[iPage]++)>1; + setPageReferenced(pCheck, iPage); + return 0; } #ifndef SQLITE_OMIT_AUTOVACUUM @@ -57162,17 +58191,15 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( sqlite3BtreeLeave(p); return 0; } - sCheck.anRef = sqlite3Malloc( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); - if( !sCheck.anRef ){ + + sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1); + if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } - for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } i = PENDING_BYTE_PAGE(pBt); - if( i<=sCheck.nPage ){ - sCheck.anRef[i] = 1; - } + if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000); sCheck.errMsg.useMalloc = 2; @@ -57197,18 +58224,18 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( */ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM - if( sCheck.anRef[i]==0 ){ + if( getPageReferenced(&sCheck, i)==0 ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } #else /* If the database supports auto-vacuum, make sure no tables contain ** references to pointer-map pages. */ - if( sCheck.anRef[i]==0 && + if( getPageReferenced(&sCheck, i)==0 && (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Page %d is never used", i); } - if( sCheck.anRef[i]!=0 && + if( getPageReferenced(&sCheck, i)!=0 && (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); } @@ -57229,7 +58256,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( /* Clean up and report errors. */ sqlite3BtreeLeave(p); - sqlite3_free(sCheck.anRef); + sqlite3_free(sCheck.aPgRef); if( sCheck.mallocFailed ){ sqlite3StrAccumReset(&sCheck.errMsg); *pnErr = sCheck.nErr+1; @@ -57242,14 +58269,15 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck( #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* -** Return the full pathname of the underlying database file. +** Return the full pathname of the underlying database file. Return +** an empty string if the database is in-memory or a TEMP database. ** ** The pager filename is invariant as long as the pager is ** open so it is safe to access without the BtShared mutex. */ SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); - return sqlite3PagerFilename(p->pBt->pPager); + return sqlite3PagerFilename(p->pBt->pPager, 1); } /* @@ -57900,7 +58928,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); if( rc==SQLITE_OK ){ if( p->pDestDb ){ - sqlite3ResetInternalSchema(p->pDestDb, -1); + sqlite3ResetAllSchemasOfConnection(p->pDestDb); } if( destMode==PAGER_JOURNALMODE_WAL ){ rc = sqlite3BtreeSetVersion(p->pDest, 2); @@ -58054,7 +59082,7 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){ } /* If a transaction is still open on the Btree, roll it back. */ - sqlite3BtreeRollback(p->pDest); + sqlite3BtreeRollback(p->pDest, SQLITE_OK); /* Set the error code of the destination database handle. */ rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc; @@ -58265,10 +59293,10 @@ SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){ ** 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. +** If the third argument passed to this function is true, then memory +** cell pMem must contain a string or blob. In this case the content is +** preserved. Otherwise, if the third parameter to this function is false, +** any current string or blob value 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 @@ -58283,6 +59311,10 @@ SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ ); assert( (pMem->flags&MEM_RowSet)==0 ); + /* If the preserve flag is set to true, then the memory cell must already + ** contain a valid string or blob value. */ + assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) ); + if( n<32 ) n = 32; if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)z==pMem->zMalloc ){ @@ -58298,6 +59330,7 @@ SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){ memcpy(pMem->zMalloc, pMem->z, pMem->n); } if( pMem->flags&MEM_Dyn && pMem->xDel ){ + assert( pMem->xDel!=SQLITE_DYNAMIC ); pMem->xDel((void *)(pMem->z)); } @@ -58477,6 +59510,7 @@ SQLITE_PRIVATE void sqlite3VdbeMemReleaseExternal(Mem *p){ sqlite3VdbeMemRelease(p); }else if( p->flags&MEM_Dyn && p->xDel ){ assert( (p->flags&MEM_RowSet)==0 ); + assert( p->xDel!=SQLITE_DYNAMIC ); p->xDel((void *)p->z); p->xDel = 0; }else if( p->flags&MEM_RowSet ){ @@ -58619,8 +59653,14 @@ SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem *pMem){ ** true and could be omitted. But we leave it in because other ** architectures might behave differently. */ - if( pMem->r==(double)pMem->u.i && pMem->u.i>SMALLEST_INT64 - && ALWAYS(pMem->u.ir==(double)pMem->u.i + && pMem->u.i>SMALLEST_INT64 +#if defined(__i486__) || defined(__x86_64__) + && ALWAYS(pMem->u.iu.iflags |= MEM_Int; } } @@ -59594,14 +60634,11 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp4Int( ** Zero is returned if a malloc() fails. */ SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Vdbe *p){ - int i; - i = p->nLabel++; + int i = p->nLabel++; assert( p->magic==VDBE_MAGIC_INIT ); - if( i>=p->nLabelAlloc ){ - int n = p->nLabelAlloc*2 + 5; - p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, - n*sizeof(p->aLabel[0])); - p->nLabelAlloc = sqlite3DbMallocSize(p->db, p->aLabel)/sizeof(p->aLabel[0]); + if( (i & (i-1))==0 ){ + p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel, + (i*2+1)*sizeof(p->aLabel[0])); } if( p->aLabel ){ p->aLabel[i] = -1; @@ -60596,7 +61633,7 @@ SQLITE_PRIVATE int sqlite3VdbeList( for(j=0; jp4.pProgram ) break; } - if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, 1) ){ + if( j==nSub && SQLITE_OK==sqlite3VdbeMemGrow(pSub, nByte, nSub!=0) ){ apSub = (SubProgram **)pSub->z; apSub[nSub++] = pOp->p4.pProgram; pSub->flags |= MEM_Blob; @@ -61359,32 +62396,6 @@ static void checkActiveVdbeCnt(sqlite3 *db){ #define checkActiveVdbeCnt(x) #endif -/* -** For every Btree that in database connection db which -** has been modified, "trip" or invalidate each cursor in -** that Btree might have been modified so that the cursor -** can never be used again. This happens when a rollback -*** occurs. We have to trip all the other cursors, even -** cursor from other VMs in different database connections, -** so that none of them try to use the data at which they -** were pointing and which now may have been changed due -** to the rollback. -** -** Remember that a rollback can delete tables complete and -** reorder rootpages. So it is not sufficient just to save -** the state of the cursor. We have to invalidate the cursor -** so that it is never used again. -*/ -static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){ - int i; - for(i=0; inDb; i++){ - Btree *p = db->aDb[i].pBt; - if( p && sqlite3BtreeIsInTrans(p) ){ - sqlite3BtreeTripAllCursors(p, SQLITE_ABORT); - } - } -} - /* ** If the Vdbe passed as the first argument opened a statement-transaction, ** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or @@ -61549,8 +62560,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ /* We are forced to roll back the active transaction. Before doing ** so, abort any other statements this handle currently has active. */ - invalidateCursorsOnModifiedBtrees(db); - sqlite3RollbackAll(db); + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; } @@ -61592,13 +62602,13 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; - sqlite3RollbackAll(db); + sqlite3RollbackAll(db, SQLITE_OK); }else{ db->nDeferredCons = 0; sqlite3CommitInternalChanges(db); } }else{ - sqlite3RollbackAll(db); + sqlite3RollbackAll(db, SQLITE_OK); } db->nStatement = 0; }else if( eStatementOp==0 ){ @@ -61607,8 +62617,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ }else if( p->errorAction==OE_Abort ){ eStatementOp = SAVEPOINT_ROLLBACK; }else{ - invalidateCursorsOnModifiedBtrees(db); - sqlite3RollbackAll(db); + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; } @@ -61628,8 +62637,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; } - invalidateCursorsOnModifiedBtrees(db); - sqlite3RollbackAll(db); + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); sqlite3CloseSavepoints(db); db->autoCommit = 1; } @@ -61646,12 +62654,6 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){ } p->nChange = 0; } - - /* Rollback or commit any schema changes that occurred. */ - if( p->rc!=SQLITE_OK && db->flags&SQLITE_InternChanges ){ - sqlite3ResetInternalSchema(db, -1); - db->flags = (db->flags | SQLITE_InternChanges); - } /* Release the locks */ sqlite3VdbeLeave(p); @@ -64111,8 +65113,9 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql( */ SQLITE_PRIVATE void sqlite3ExplainBegin(Vdbe *pVdbe){ if( pVdbe ){ + Explain *p; sqlite3BeginBenignMalloc(); - Explain *p = sqlite3_malloc( sizeof(Explain) ); + p = sqlite3_malloc( sizeof(Explain) ); if( p ){ memset(p, 0, sizeof(*p)); p->pVdbe = pVdbe; @@ -66072,19 +67075,26 @@ arithmetic_result_is_null: break; } -/* Opcode: CollSeq * * P4 +/* Opcode: CollSeq P1 * * P4 ** ** P4 is a pointer to a CollSeq struct. If the next call to a user function ** or aggregate calls sqlite3GetFuncCollSeq(), this collation sequence will ** be returned. This is used by the built-in min(), max() and nullif() ** functions. ** +** If P1 is not zero, then it is a register that a subsequent min() or +** max() aggregate will set to 1 if the current row is not the minimum or +** maximum. The P1 register is initialized to 0 by this instruction. +** ** 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 ); + if( pOp->p1 ){ + sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0); + } break; } @@ -66873,6 +67883,11 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ ** 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. +** +** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 when +** the result is guaranteed to only be used as the argument of a length() +** or typeof() function, respectively. The loading of large blobs can be +** skipped for length() and all content loading can be skipped for typeof(). */ case OP_Column: { #if 0 /* local variables moved into u.an */ @@ -67015,7 +68030,7 @@ case OP_Column: { u.an.pC->aRow = 0; } } - /* The following assert is true in all cases accept when + /* The following assert is true in all cases except when ** the database file has been corrupted externally. ** assert( u.an.zRec!=0 || u.an.avail>=u.an.payloadSize || u.an.avail>=9 ); */ u.an.szHdr = getVarint32((u8*)u.an.zData, u.an.offset); @@ -67090,11 +68105,11 @@ case OP_Column: { break; } }else{ - /* If u.an.i is less that u.an.nField, then there are less fields in this + /* If u.an.i is less that u.an.nField, then there are fewer fields in this ** record than SetNumColumns indicated there are columns in the ** table. Set the u.an.offset for any extra columns not present in - ** the record to 0. This tells code below to store a NULL - ** instead of deserializing a value from the record. + ** the record to 0. This tells code below to store the default value + ** for the column instead of deserializing a value from the record. */ u.an.aOffset[u.an.i] = 0; } @@ -67124,17 +68139,32 @@ case OP_Column: { if( u.an.aOffset[u.an.p2] ){ assert( rc==SQLITE_OK ); if( u.an.zRec ){ + /* This is the common case where the whole row fits on a single page */ VdbeMemRelease(u.an.pDest); sqlite3VdbeSerialGet((u8 *)&u.an.zRec[u.an.aOffset[u.an.p2]], u.an.aType[u.an.p2], u.an.pDest); }else{ - u.an.len = sqlite3VdbeSerialTypeLen(u.an.aType[u.an.p2]); - sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest); - rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len, u.an.pC->isIndex, &u.an.sMem); - if( rc!=SQLITE_OK ){ - goto op_column_out; + /* This branch happens only when the row overflows onto multiple pages */ + u.an.t = u.an.aType[u.an.p2]; + if( (pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0 + && ((u.an.t>=12 && (u.an.t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0) + ){ + /* Content is irrelevant for the typeof() function and for + ** the length(X) function if X is a blob. So we might as well use + ** bogus content rather than reading content from disk. NULL works + ** for text and blob and whatever is in the u.an.payloadSize64 variable + ** will work for everything else. */ + u.an.zData = u.an.t<12 ? (char*)&u.an.payloadSize64 : 0; + }else{ + u.an.len = sqlite3VdbeSerialTypeLen(u.an.t); + sqlite3VdbeMemMove(&u.an.sMem, u.an.pDest); + rc = sqlite3VdbeMemFromBtree(u.an.pCrsr, u.an.aOffset[u.an.p2], u.an.len, u.an.pC->isIndex, + &u.an.sMem); + if( rc!=SQLITE_OK ){ + goto op_column_out; + } + u.an.zData = u.an.sMem.z; } - u.an.zData = u.an.sMem.z; - sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.aType[u.an.p2], u.an.pDest); + sqlite3VdbeSerialGet((u8*)u.an.zData, u.an.t, u.an.pDest); } u.an.pDest->enc = encoding; }else{ @@ -67440,16 +68470,12 @@ case OP_Savepoint: { if( !u.ar.pSavepoint ){ sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", u.ar.zName); rc = SQLITE_ERROR; - }else if( - db->writeVdbeCnt>0 || (u.ar.p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1) - ){ + }else if( db->writeVdbeCnt>0 && u.ar.p1==SAVEPOINT_RELEASE ){ /* It is not possible to release (commit) a savepoint if there are - ** active write statements. It is not possible to rollback a savepoint - ** if there are any active statements at all. + ** active write statements. */ sqlite3SetString(&p->zErrMsg, db, - "cannot %s savepoint - SQL statements in progress", - (u.ar.p1==SAVEPOINT_ROLLBACK ? "rollback": "release") + "cannot release savepoint - SQL statements in progress" ); rc = SQLITE_BUSY; }else{ @@ -67474,6 +68500,11 @@ case OP_Savepoint: { rc = p->rc; }else{ u.ar.iSavepoint = db->nSavepoint - u.ar.iSavepoint - 1; + if( u.ar.p1==SAVEPOINT_ROLLBACK ){ + for(u.ar.ii=0; u.ar.iinDb; u.ar.ii++){ + sqlite3BtreeTripAllCursors(db->aDb[u.ar.ii].pBt, SQLITE_ABORT); + } + } for(u.ar.ii=0; u.ar.iinDb; u.ar.ii++){ rc = sqlite3BtreeSavepoint(db->aDb[u.ar.ii].pBt, u.ar.p1, u.ar.iSavepoint); if( rc!=SQLITE_OK ){ @@ -67482,7 +68513,7 @@ case OP_Savepoint: { } if( u.ar.p1==SAVEPOINT_ROLLBACK && (db->flags&SQLITE_InternChanges)!=0 ){ sqlite3ExpirePreparedStatements(db); - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); db->flags = (db->flags | SQLITE_InternChanges); } } @@ -67544,6 +68575,7 @@ case OP_AutoCommit: { assert( u.as.desiredAutoCommit==1 || u.as.iRollback==0 ); assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ +#if 0 if( u.as.turnOnAC && u.as.iRollback && db->activeVdbeCnt>1 ){ /* If this instruction implements a ROLLBACK and other VMs are ** still running, and a transaction is active, return an error indicating @@ -67552,7 +68584,9 @@ case OP_AutoCommit: { sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - " "SQL statements in progress"); rc = SQLITE_BUSY; - }else if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){ + }else +#endif + if( u.as.turnOnAC && !u.as.iRollback && db->writeVdbeCnt>0 ){ /* If this instruction implements a COMMIT and other VMs are writing ** return an error indicating that the other VMs must complete first. */ @@ -67562,7 +68596,7 @@ case OP_AutoCommit: { }else if( u.as.desiredAutoCommit!=db->autoCommit ){ if( u.as.iRollback ){ assert( u.as.desiredAutoCommit==1 ); - sqlite3RollbackAll(db); + sqlite3RollbackAll(db, SQLITE_ABORT_ROLLBACK); db->autoCommit = 1; }else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){ goto vdbe_return; @@ -67618,7 +68652,7 @@ case OP_AutoCommit: { ** 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 +** active statements. A statement transaction allows the changes made by 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. @@ -67793,7 +68827,7 @@ case OP_VerifyCookie: { ** a v-table method. */ if( db->aDb[pOp->p1].pSchema->schema_cookie!=u.aw.iMeta ){ - sqlite3ResetInternalSchema(db, pOp->p1); + sqlite3ResetOneSchema(db, pOp->p1); } p->expired = 1; @@ -68628,7 +69662,7 @@ case OP_NewRowid: { /* out2-prerelease */ assert( sqlite3BtreeCursorIsValid(u.bg.pC->pCursor) ); rc = sqlite3BtreeKeySize(u.bg.pC->pCursor, &u.bg.v); assert( rc==SQLITE_OK ); /* Cannot fail following BtreeLast() */ - if( u.bg.v==MAX_ROWID ){ + if( u.bg.v>=MAX_ROWID ){ u.bg.pC->useRandomRowid = 1; }else{ u.bg.v++; /* IMP: R-29538-34987 */ @@ -68986,7 +70020,6 @@ case OP_RowData: { assert( u.bl.pC!=0 ); assert( u.bl.pC->nullRow==0 ); assert( u.bl.pC->pseudoTableReg==0 ); - assert( !u.bl.pC->isSorter ); assert( u.bl.pC->pCursor!=0 ); u.bl.pCrsr = u.bl.pC->pCursor; assert( sqlite3BtreeCursorIsValid(u.bl.pCrsr) ); @@ -69662,6 +70695,7 @@ case OP_ParseSchema: { db->init.busy = 0; } } + if( rc ) sqlite3ResetAllSchemasOfConnection(db); if( rc==SQLITE_NOMEM ){ goto no_mem; } @@ -70004,7 +71038,6 @@ case OP_Program: { /* jump */ p->nOp = u.cc.pProgram->nOp; p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor]; p->nOnceFlag = u.cc.pProgram->nOnce; - p->nOp = u.cc.pProgram->nOp; pc = -1; memset(p->aOnceFlag, 0, p->nOnceFlag); @@ -70199,6 +71232,7 @@ case OP_AggStep: { u.cf.ctx.s.db = db; u.cf.ctx.isError = 0; u.cf.ctx.pColl = 0; + u.cf.ctx.skipFlag = 0; if( u.cf.ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){ assert( pOp>p->aOp ); assert( pOp[-1].p4type==P4_COLLSEQ ); @@ -70210,6 +71244,11 @@ case OP_AggStep: { sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&u.cf.ctx.s)); rc = u.cf.ctx.isError; } + if( u.cf.ctx.skipFlag ){ + assert( pOp[-1].opcode==OP_CollSeq ); + u.cf.i = pOp[-1].p1; + if( u.cf.i ) sqlite3VdbeMemSetInt64(&aMem[u.cf.i], 1); + } sqlite3VdbeMemRelease(&u.cf.ctx.s); @@ -70323,7 +71362,7 @@ case OP_JournalMode: { /* out2-prerelease */ if( !sqlite3PagerOkToChangeJournalMode(u.ci.pPager) ) u.ci.eNew = u.ci.eOld; #ifndef SQLITE_OMIT_WAL - u.ci.zFilename = sqlite3PagerFilename(u.ci.pPager); + u.ci.zFilename = sqlite3PagerFilename(u.ci.pPager, 1); /* Do not allow a transition to journal_mode=WAL for a database ** in temporary storage or if the VFS does not support shared memory @@ -70989,7 +72028,7 @@ vdbe_error_halt: if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1; rc = SQLITE_ERROR; if( resetSchemaOnFault>0 ){ - sqlite3ResetInternalSchema(db, resetSchemaOnFault-1); + sqlite3ResetOneSchema(db, resetSchemaOnFault-1); } /* This is the only way out of this procedure. We have to @@ -71603,17 +72642,17 @@ typedef struct SorterRecord SorterRecord; ** being merged (rounded up to the next power of 2). */ struct VdbeSorter { - int nInMemory; /* Current size of pRecord list as PMA */ - int nTree; /* Used size of aTree/aIter (power of 2) */ - VdbeSorterIter *aIter; /* Array of iterators to merge */ - int *aTree; /* Current state of incremental merge */ i64 iWriteOff; /* Current write offset within file pTemp1 */ i64 iReadOff; /* Current read offset within file pTemp1 */ - sqlite3_file *pTemp1; /* PMA file 1 */ + int nInMemory; /* Current size of pRecord list as PMA */ + int nTree; /* Used size of aTree/aIter (power of 2) */ int nPMA; /* Number of PMAs stored in pTemp1 */ - SorterRecord *pRecord; /* Head of in-memory record list */ int mnPmaSize; /* Minimum PMA size, in bytes */ int mxPmaSize; /* Maximum PMA size, in bytes. 0==no limit */ + VdbeSorterIter *aIter; /* Array of iterators to merge */ + int *aTree; /* Current state of incremental merge */ + sqlite3_file *pTemp1; /* PMA file 1 */ + SorterRecord *pRecord; /* Head of in-memory record list */ UnpackedRecord *pUnpacked; /* Used to unpack keys */ }; @@ -71624,10 +72663,10 @@ struct VdbeSorter { struct VdbeSorterIter { i64 iReadOff; /* Current read offset */ i64 iEof; /* 1 byte past EOF for this iterator */ - sqlite3_file *pFile; /* File iterator is reading from */ int nAlloc; /* Bytes of space at aAlloc */ - u8 *aAlloc; /* Allocated space */ int nKey; /* Number of bytes in key */ + sqlite3_file *pFile; /* File iterator is reading from */ + u8 *aAlloc; /* Allocated space */ u8 *aKey; /* Pointer to current key */ }; @@ -73344,7 +74383,7 @@ static int lookupName( assert( pExpr->x.pList==0 ); assert( pExpr->x.pSelect==0 ); pOrig = pEList->a[j].pExpr; - if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){ + if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){ sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs); return WRC_Abort; } @@ -73566,7 +74605,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ - pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); + pDef = sqlite3FindFunction(pParse->db, zId, nId, -2, enc, 0); if( pDef==0 ){ no_such_func = 1; }else{ @@ -73589,7 +74628,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } } #endif - if( is_agg && !pNC->allowAgg ){ + if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); pNC->nErr++; is_agg = 0; @@ -73603,11 +74642,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } if( is_agg ){ pExpr->op = TK_AGG_FUNCTION; - pNC->hasAgg = 1; + pNC->ncFlags |= NC_HasAgg; } - if( is_agg ) pNC->allowAgg = 0; + if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg; sqlite3WalkExprList(pWalker, pList); - if( is_agg ) pNC->allowAgg = 1; + if( is_agg ) pNC->ncFlags |= NC_AllowAgg; /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ @@ -73622,7 +74661,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ if( ExprHasProperty(pExpr, EP_xIsSelect) ){ int nRef = pNC->nRef; #ifndef SQLITE_OMIT_CHECK - if( pNC->isCheck ){ + if( (pNC->ncFlags & NC_IsCheck)!=0 ){ sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); } #endif @@ -73636,7 +74675,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } #ifndef SQLITE_OMIT_CHECK case TK_VARIABLE: { - if( pNC->isCheck ){ + if( (pNC->ncFlags & NC_IsCheck)!=0 ){ sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints"); } break; @@ -73718,7 +74757,7 @@ static int resolveOrderByTermToExprList( nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; nc.pEList = pEList; - nc.allowAgg = 1; + nc.ncFlags = NC_AllowAgg; nc.nErr = 0; db = pParse->db; savedSuppErr = db->suppressErr; @@ -73916,7 +74955,7 @@ static int resolveOrderGroupBy( 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 i, j; /* Loop counters */ int iCol; /* Column number */ struct ExprList_item *pItem; /* A term of the ORDER BY clause */ Parse *pParse; /* Parsing context */ @@ -73953,6 +74992,11 @@ static int resolveOrderGroupBy( if( sqlite3ResolveExprNames(pNC, pE) ){ return 1; } + for(j=0; jpEList->nExpr; j++){ + if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr)==0 ){ + pItem->iOrderByCol = j+1; + } + } } return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType); } @@ -74015,7 +75059,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. */ - sNC.allowAgg = 1; + sNC.ncFlags = NC_AllowAgg; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; @@ -74061,10 +75105,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ */ assert( (p->selFlags & SF_Aggregate)==0 ); pGroupBy = p->pGroupBy; - if( pGroupBy || sNC.hasAgg ){ + if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){ p->selFlags |= SF_Aggregate; }else{ - sNC.allowAgg = 0; + sNC.ncFlags &= ~NC_AllowAgg; } /* If a HAVING clause is present, then there must be a GROUP BY clause. @@ -74093,7 +75137,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ ** outer queries */ sNC.pNext = 0; - sNC.allowAgg = 1; + sNC.ncFlags |= NC_AllowAgg; /* Process the ORDER BY clause for singleton SELECT statements. ** The ORDER BY clause for compounds SELECT statements is handled @@ -74181,7 +75225,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){ ** ** 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 +** If the function is an aggregate function, then the NC_HasAgg flag 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. @@ -74193,7 +75237,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ - int savedHasAgg; + u8 savedHasAgg; Walker w; if( pExpr==0 ) return 0; @@ -74206,8 +75250,8 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( pParse->nHeight += pExpr->nHeight; } #endif - savedHasAgg = pNC->hasAgg; - pNC->hasAgg = 0; + savedHasAgg = pNC->ncFlags & NC_HasAgg; + pNC->ncFlags &= ~NC_HasAgg; w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.pParse = pNC->pParse; @@ -74219,10 +75263,10 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames( if( pNC->nErr>0 || w.pParse->nErr>0 ){ ExprSetProperty(pExpr, EP_Error); } - if( pNC->hasAgg ){ + if( pNC->ncFlags & NC_HasAgg ){ ExprSetProperty(pExpr, EP_Agg); }else if( savedHasAgg ){ - pNC->hasAgg = 1; + pNC->ncFlags |= NC_HasAgg; } return ExprHasProperty(pExpr, EP_Error); } @@ -74742,23 +75786,55 @@ SQLITE_PRIVATE Expr *sqlite3PExpr( Expr *pRight, /* Right operand */ const Token *pToken /* Argument token */ ){ - Expr *p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); - sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); + Expr *p; + if( op==TK_AND && pLeft && pRight ){ + /* Take advantage of short-circuit false optimization for AND */ + p = sqlite3ExprAnd(pParse->db, pLeft, pRight); + }else{ + p = sqlite3ExprAlloc(pParse->db, op, pToken, 1); + sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); + } if( p ) { sqlite3ExprCheckHeight(pParse, p->nHeight); } return p; } +/* +** Return 1 if an expression must be FALSE in all cases and 0 if the +** expression might be true. This is an optimization. If is OK to +** return 0 here even if the expression really is always false (a +** false negative). But it is a bug to return 1 if the expression +** might be true in some rare circumstances (a false positive.) +** +** Note that if the expression is part of conditional for a +** LEFT JOIN, then we cannot determine at compile-time whether or not +** is it true or false, so always return 0. +*/ +static int exprAlwaysFalse(Expr *p){ + int v = 0; + if( ExprHasProperty(p, EP_FromJoin) ) return 0; + if( !sqlite3ExprIsInteger(p, &v) ) return 0; + return v==0; +} + /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. +** +** If one side or the other of the AND is known to be false, then instead +** of returning an AND expression, just return a constant expression with +** a value of false. */ SQLITE_PRIVATE Expr *sqlite3ExprAnd(sqlite3 *db, Expr *pLeft, Expr *pRight){ if( pLeft==0 ){ return pRight; }else if( pRight==0 ){ return pLeft; + }else if( exprAlwaysFalse(pLeft) || exprAlwaysFalse(pRight) ){ + sqlite3ExprDelete(db, pLeft); + sqlite3ExprDelete(db, pRight); + return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0); }else{ Expr *pNew = sqlite3ExprAlloc(db, TK_AND, 0, 0); sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight); @@ -75114,8 +76190,9 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags) pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); if( pNew==0 ) return 0; pNew->iECursor = 0; - pNew->nExpr = pNew->nAlloc = p->nExpr; - pNew->a = pItem = sqlite3DbMallocRaw(db, p->nExpr*sizeof(p->a[0]) ); + pNew->nExpr = i = p->nExpr; + if( (flags & EXPRDUP_REDUCE)==0 ) for(i=1; inExpr; i+=i){} + pNew->a = pItem = sqlite3DbMallocRaw(db, i*sizeof(p->a[0]) ); if( pItem==0 ){ sqlite3DbFree(db, pNew); return 0; @@ -75183,12 +76260,15 @@ SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){ if( p==0 ) return 0; pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) ); if( pNew==0 ) return 0; - pNew->nId = pNew->nAlloc = p->nId; + pNew->nId = p->nId; pNew->a = sqlite3DbMallocRaw(db, p->nId*sizeof(p->a[0]) ); if( pNew->a==0 ){ sqlite3DbFree(db, pNew); return 0; } + /* Note that because the size of the allocation for p->a[] is not + ** necessarily a power of two, sqlite3IdListAppend() may not be called + ** on the duplicate created by this function. */ for(i=0; inId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; struct IdList_item *pOldItem = &p->a[i]; @@ -75250,17 +76330,16 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend( if( pList==0 ){ goto no_mem; } - assert( pList->nAlloc==0 ); - } - if( pList->nAlloc<=pList->nExpr ){ + pList->a = sqlite3DbMallocRaw(db, sizeof(pList->a[0])); + if( pList->a==0 ) goto no_mem; + }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ struct ExprList_item *a; - int n = pList->nAlloc*2 + 4; - a = sqlite3DbRealloc(db, pList->a, n*sizeof(pList->a[0])); + assert( pList->nExpr>0 ); + a = sqlite3DbRealloc(db, pList->a, pList->nExpr*2*sizeof(pList->a[0])); if( a==0 ){ goto no_mem; } pList->a = a; - pList->nAlloc = sqlite3DbMallocSize(db, a)/sizeof(a[0]); } assert( pList->a!=0 ); if( 1 ){ @@ -75351,8 +76430,7 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){ int i; struct ExprList_item *pItem; if( pList==0 ) return; - assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); - assert( pList->nExpr<=pList->nAlloc ); + assert( pList->a!=0 || pList->nExpr==0 ); for(pItem=pList->a, i=0; inExpr; i++, pItem++){ sqlite3ExprDelete(db, pItem->pExpr); sqlite3DbFree(db, pItem->zName); @@ -76288,15 +77366,6 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int */ #ifndef NDEBUG for(i=0, p=pParse->aColCache; iiReg && 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 @@ -76431,7 +77500,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( 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 */ + int iReg, /* Store results here */ + u8 p5 /* P5 value for OP_Column */ ){ Vdbe *v = pParse->pVdbe; int i; @@ -76446,7 +77516,11 @@ SQLITE_PRIVATE int sqlite3ExprCodeGetColumn( } assert( v!=0 ); sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg); - sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg); + if( p5 ){ + sqlite3VdbeChangeP5(v, p5); + }else{ + sqlite3ExprCacheStore(pParse, iTable, iColumn, iReg); + } return iReg; } @@ -76574,7 +77648,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) inReg = pExpr->iColumn + pParse->ckBase; }else{ inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, - pExpr->iColumn, pExpr->iTable, target); + pExpr->iColumn, pExpr->iTable, target, + pExpr->op2); } break; } @@ -76851,6 +77926,25 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target) if( pFarg ){ r1 = sqlite3GetTempRange(pParse, nFarg); + + /* For length() and typeof() functions with a column argument, + ** set the P5 parameter to the OP_Column opcode to OPFLAG_LENGTHARG + ** or OPFLAG_TYPEOFARG respectively, to avoid unnecessary data + ** loading. + */ + if( (pDef->flags & (SQLITE_FUNC_LENGTH|SQLITE_FUNC_TYPEOF))!=0 ){ + u8 exprOp; + assert( nFarg==1 ); + assert( pFarg->a[0].pExpr!=0 ); + exprOp = pFarg->a[0].pExpr->op; + if( exprOp==TK_COLUMN || exprOp==TK_AGG_COLUMN ){ + assert( SQLITE_FUNC_LENGTH==OPFLAG_LENGTHARG ); + assert( SQLITE_FUNC_TYPEOF==OPFLAG_TYPEOFARG ); + testcase( pDef->flags==SQLITE_FUNC_LENGTH ); + pFarg->a[0].pExpr->op2 = pDef->flags; + } + } + sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */ sqlite3ExprCodeExprList(pParse, pFarg, r1, 1); sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */ @@ -77986,7 +79080,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB){ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ return 2; } - }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ + }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_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; @@ -78023,6 +79117,41 @@ SQLITE_PRIVATE int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){ return 0; } +/* +** This is the expression callback for sqlite3FunctionUsesOtherSrc(). +** +** Determine if an expression references any table other than one of the +** tables in pWalker->u.pSrcList and abort if it does. +*/ +static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){ + int i; + SrcList *pSrc = pWalker->u.pSrcList; + for(i=0; inSrc; i++){ + if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue; + } + return WRC_Abort; + }else{ + return WRC_Continue; + } +} + +/* +** Determine if any of the arguments to the pExpr Function references +** any SrcList other than pSrcList. Return true if they do. Return +** false if pExpr has no argument or has only constant arguments or +** only references tables named in pSrcList. +*/ +static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){ + Walker w; + assert( pExpr->op==TK_AGG_FUNCTION ); + memset(&w, 0, sizeof(w)); + w.xExprCallback = exprUsesOtherSrc; + w.u.pSrcList = pSrcList; + if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1; + return 0; +} + /* ** Add a new element to the pAggInfo->aCol[] array. Return the index of ** the new element. Return a negative number if malloc fails. @@ -78033,9 +79162,7 @@ static int addAggInfoColumn(sqlite3 *db, AggInfo *pInfo){ db, pInfo->aCol, sizeof(pInfo->aCol[0]), - 3, &pInfo->nColumn, - &pInfo->nColumnAlloc, &i ); return i; @@ -78051,9 +79178,7 @@ static int addAggInfoFunc(sqlite3 *db, AggInfo *pInfo){ db, pInfo->aFunc, sizeof(pInfo->aFunc[0]), - 3, &pInfo->nFunc, - &pInfo->nFuncAlloc, &i ); return i; @@ -78142,9 +79267,9 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ return WRC_Prune; } case TK_AGG_FUNCTION: { - /* The pNC->nDepth==0 test causes aggregate functions in subqueries - ** to be ignored */ - if( pNC->nDepth==0 ){ + if( (pNC->ncFlags & NC_InAggFunc)==0 + && !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList) + ){ /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure */ @@ -78181,22 +79306,16 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ ExprSetIrreducible(pExpr); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; - return WRC_Prune; } + return WRC_Prune; } } return WRC_Continue; } static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ - NameContext *pNC = pWalker->u.pNC; - if( pNC->nDepth==0 ){ - pNC->nDepth++; - sqlite3WalkSelect(pWalker, pSelect); - pNC->nDepth--; - return WRC_Prune; - }else{ - return WRC_Continue; - } + UNUSED_PARAMETER(pWalker); + UNUSED_PARAMETER(pSelect); + return WRC_Continue; } /* @@ -78209,6 +79328,7 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ */ SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ Walker w; + memset(&w, 0, sizeof(w)); w.xExprCallback = analyzeAggregate; w.xSelectCallback = analyzeAggregatesInSelect; w.u.pNC = pNC; @@ -78830,7 +79950,7 @@ SQLITE_PRIVATE void sqlite3AlterRenameTable( "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN " "'sqlite_autoindex_' || %Q || substr(name,%d+18) " "ELSE name END " - "WHERE tbl_name=%Q AND " + "WHERE tbl_name=%Q COLLATE nocase AND " "(type='table' OR type='index' OR type='trigger');", zDb, SCHEMA_TABLE(iDb), zName, zName, zName, #ifndef SQLITE_OMIT_TRIGGER @@ -80060,6 +81180,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){ int eType; /* Datatype of a sample */ IndexSample *pSample; /* A slot in pIdx->aSample[] */ + assert( db->lookaside.bEnabled==0 ); if( !sqlite3FindTable(db, "sqlite_stat3", zDb) ){ return SQLITE_OK; } @@ -80086,7 +81207,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){ if( pIdx==0 ) continue; assert( pIdx->nSample==0 ); pIdx->nSample = nSample; - pIdx->aSample = sqlite3MallocZero( nSample*sizeof(IndexSample) ); + pIdx->aSample = sqlite3DbMallocZero(db, nSample*sizeof(IndexSample)); pIdx->avgEq = pIdx->aiRowEst[1]; if( pIdx->aSample==0 ){ db->mallocFailed = 1; @@ -80159,7 +81280,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){ if( n < 1){ pSample->u.z = 0; }else{ - pSample->u.z = sqlite3Malloc(n); + pSample->u.z = sqlite3DbMallocRaw(db, n); if( pSample->u.z==0 ){ db->mallocFailed = 1; sqlite3_finalize(pStmt); @@ -80235,7 +81356,10 @@ SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ /* Load the statistics from the sqlite_stat3 table. */ #ifdef SQLITE_ENABLE_STAT3 if( rc==SQLITE_OK ){ + int lookasideEnabled = db->lookaside.bEnabled; + db->lookaside.bEnabled = 0; rc = loadStat3(db, sInfo.zDatabase); + db->lookaside.bEnabled = lookasideEnabled; } #endif @@ -80467,7 +81591,7 @@ static void attachFunc( db->aDb[iDb].pBt = 0; db->aDb[iDb].pSchema = 0; } - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); db->nDb = iDb; if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ db->mallocFailed = 1; @@ -80539,7 +81663,7 @@ static void detachFunc( sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; pDb->pSchema = 0; - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); return; detach_error: @@ -81455,58 +82579,15 @@ SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char } /* -** Erase all schema information from the in-memory hash tables of -** a single database. This routine is called to reclaim memory -** before the database closes. It is also called during a rollback -** if there were schema changes during the transaction or if a -** schema-cookie mismatch occurs. +** Look through the list of open database files in db->aDb[] and if +** any have been closed, remove them from the list. Reallocate the +** db->aDb[] structure to a smaller size, if possible. ** -** If iDb<0 then reset the internal schema tables for all database -** files. If iDb>=0 then reset the internal schema for only the -** single file indicated. +** Entry 0 (the "main" database) and entry 1 (the "temp" database) +** are never candidates for being collapsed. */ -SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ +SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3 *db){ int i, j; - assert( iDbnDb ); - - if( iDb>=0 ){ - /* Case 1: Reset the single schema identified by iDb */ - Db *pDb = &db->aDb[iDb]; - assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - assert( pDb->pSchema!=0 ); - sqlite3SchemaClear(pDb->pSchema); - - /* If any database other than TEMP is reset, then also reset TEMP - ** since TEMP might be holding triggers that reference tables in the - ** other database. - */ - if( iDb!=1 ){ - pDb = &db->aDb[1]; - assert( pDb->pSchema!=0 ); - sqlite3SchemaClear(pDb->pSchema); - } - return; - } - /* Case 2 (from here to the end): Reset all schemas for all attached - ** databases. */ - assert( iDb<0 ); - sqlite3BtreeEnterAll(db); - for(i=0; inDb; i++){ - Db *pDb = &db->aDb[i]; - if( pDb->pSchema ){ - sqlite3SchemaClear(pDb->pSchema); - } - } - db->flags &= ~SQLITE_InternChanges; - sqlite3VtabUnlockList(db); - sqlite3BtreeLeaveAll(db); - - /* If one or more of the auxiliary database files has been closed, - ** then remove them from the auxiliary database list. We take the - ** opportunity to do this here since we have just deleted all of the - ** schema hash tables and therefore do not have to make any changes - ** to any of those tables. - */ for(i=j=2; inDb; i++){ struct Db *pDb = &db->aDb[i]; if( pDb->pBt==0 ){ @@ -81528,6 +82609,51 @@ SQLITE_PRIVATE void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ } } +/* +** Reset the schema for the database at index iDb. Also reset the +** TEMP schema. +*/ +SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3 *db, int iDb){ + Db *pDb; + assert( iDbnDb ); + + /* Case 1: Reset the single schema identified by iDb */ + pDb = &db->aDb[iDb]; + assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); + assert( pDb->pSchema!=0 ); + sqlite3SchemaClear(pDb->pSchema); + + /* If any database other than TEMP is reset, then also reset TEMP + ** since TEMP might be holding triggers that reference tables in the + ** other database. + */ + if( iDb!=1 ){ + pDb = &db->aDb[1]; + assert( pDb->pSchema!=0 ); + sqlite3SchemaClear(pDb->pSchema); + } + return; +} + +/* +** Erase all schema information from all attached databases (including +** "main" and "temp") for a single database connection. +*/ +SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ + int i; + sqlite3BtreeEnterAll(db); + for(i=0; inDb; i++){ + Db *pDb = &db->aDb[i]; + if( pDb->pSchema ){ + sqlite3SchemaClear(pDb->pSchema); + } + } + db->flags &= ~SQLITE_InternChanges; + sqlite3VtabUnlockList(db); + sqlite3BtreeLeaveAll(db); + sqlite3CollapseDatabaseArray(db); +} + /* ** This routine is called when a commit occurs. */ @@ -81563,9 +82689,16 @@ static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){ ** the table data structure from the hash table. But it does destroy ** memory structures of the indices and foreign keys associated with ** the table. +** +** The db parameter is optional. It is needed if the Table object +** contains lookaside memory. (Table objects in the schema do not use +** lookaside memory, but some ephemeral Table objects do.) Or the +** db parameter can be used with db->pnBytesFreed to measure the memory +** used by the Table object. */ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ Index *pIndex, *pNext; + TESTONLY( int nLookaside; ) /* Used to verify lookaside not used for schema */ assert( !pTable || pTable->nRef>0 ); @@ -81573,6 +82706,12 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ if( !pTable ) return; if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return; + /* Record the number of outstanding lookaside allocations in schema Tables + ** prior to doing any free() operations. Since schema Tables do not use + ** lookaside, this number should not change. */ + TESTONLY( nLookaside = (db && (pTable->tabFlags & TF_Ephemeral)==0) ? + db->lookaside.nOut : 0 ); + /* Delete all indices associated with this table. */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; @@ -81598,12 +82737,15 @@ SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3 *db, Table *pTable){ sqlite3DbFree(db, pTable->zColAff); sqlite3SelectDelete(db, pTable->pSelect); #ifndef SQLITE_OMIT_CHECK - sqlite3ExprDelete(db, pTable->pCheck); + sqlite3ExprListDelete(db, pTable->pCheck); #endif #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3VtabClear(db, pTable); #endif sqlite3DbFree(db, pTable); + + /* Verify that no lookaside memory was used by schema tables */ + assert( nLookaside==0 || nLookaside==db->lookaside.nOut ); } /* @@ -82261,15 +83403,17 @@ SQLITE_PRIVATE void sqlite3AddCheckConstraint( Parse *pParse, /* Parsing context */ Expr *pCheckExpr /* The check expression */ ){ - sqlite3 *db = pParse->db; #ifndef SQLITE_OMIT_CHECK Table *pTab = pParse->pNewTable; if( pTab && !IN_DECLARE_VTAB ){ - pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, pCheckExpr); + pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr); + if( pParse->constraintName.n ){ + sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1); + } }else #endif { - sqlite3ExprDelete(db, pCheckExpr); + sqlite3ExprDelete(pParse->db, pCheckExpr); } } @@ -82539,6 +83683,8 @@ SQLITE_PRIVATE void sqlite3EndTable( if( p->pCheck ){ SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ NameContext sNC; /* Name context for pParse->pNewTable */ + ExprList *pList; /* List of all CHECK constraints */ + int i; /* Loop counter */ memset(&sNC, 0, sizeof(sNC)); memset(&sSrc, 0, sizeof(sSrc)); @@ -82548,9 +83694,12 @@ SQLITE_PRIVATE void sqlite3EndTable( sSrc.a[0].iCursor = -1; sNC.pParse = pParse; sNC.pSrcList = &sSrc; - sNC.isCheck = 1; - if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){ - return; + sNC.ncFlags = NC_IsCheck; + pList = p->pCheck; + for(i=0; inExpr; i++){ + if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){ + return; + } } } #endif /* !defined(SQLITE_OMIT_CHECK) */ @@ -82699,7 +83848,6 @@ SQLITE_PRIVATE void sqlite3EndTable( return; } pParse->pNewTable = 0; - db->nTable++; db->flags |= SQLITE_InternChanges; #ifndef SQLITE_OMIT_ALTERTABLE @@ -83802,7 +84950,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex( }else{ zColl = pTab->aCol[j].zColl; if( !zColl ){ - zColl = db->pDfltColl->zName; + zColl = "BINARY"; } } if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){ @@ -84102,45 +85250,43 @@ exit_drop_index: } /* -** 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. +** pArray is a pointer to an array of objects. Each object in the +** array is szEntry bytes in size. This routine uses sqlite3DbRealloc() +** to extend the array so that there is space for a new object at the end. ** -** *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. +** When this function is called, *pnEntry contains the current size of +** the array (in entries - so the allocation is ((*pnEntry) * szEntry) bytes +** in total). ** -** The index of the new entry is returned in *pIdx. +** If the realloc() is successful (i.e. if no OOM condition occurs), the +** space allocated for the new object is zeroed, *pnEntry updated to +** reflect the new size of the array and a pointer to the new allocation +** returned. *pIdx is set to the index of the new array entry in this case. ** -** 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. +** Otherwise, if the realloc() fails, *pIdx is set to -1, *pnEntry remains +** unchanged and a copy of pArray returned. */ SQLITE_PRIVATE void *sqlite3ArrayAllocate( sqlite3 *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 = sqlite3DbRealloc(db, pArray, newSize*szEntry); + int n = *pnEntry; + if( (n & (n-1))==0 ){ + int sz = (n==0) ? 1 : 2*n; + void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry); if( pNew==0 ){ *pIdx = -1; return pArray; } - *pnAlloc = sqlite3DbMallocSize(db, pNew)/szEntry; pArray = pNew; } z = (char*)pArray; - memset(&z[*pnEntry * szEntry], 0, szEntry); - *pIdx = *pnEntry; + memset(&z[n * szEntry], 0, szEntry); + *pIdx = n; ++*pnEntry; return pArray; } @@ -84156,15 +85302,12 @@ SQLITE_PRIVATE IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pT if( pList==0 ){ pList = sqlite3DbMallocZero(db, sizeof(IdList) ); if( pList==0 ) return 0; - pList->nAlloc = 0; } pList->a = sqlite3ArrayAllocate( db, pList->a, sizeof(pList->a[0]), - 5, &pList->nId, - &pList->nAlloc, &i ); if( i<0 ){ @@ -85108,38 +86251,57 @@ SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq( ** that uses encoding enc. The value returned indicates how well the ** request is matched. A higher value indicates a better match. ** +** If nArg is -1 that means to only return a match (non-zero) if p->nArg +** is also -1. In other words, we are searching for a function that +** takes a variable number of arguments. +** +** If nArg is -2 that means that we are searching for any function +** regardless of the number of arguments it uses, so return a positive +** match score for any +** ** The returned value is always between 0 and 6, as follows: ** -** 0: Not a match, or if nArg<0 and the function is has no implementation. -** 1: A variable arguments function that prefers UTF-8 when a UTF-16 -** encoding is requested, or vice versa. -** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is -** requested, or vice versa. -** 3: A variable arguments function using the same text encoding. -** 4: A function with the exact number of arguments requested that -** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. -** 5: A function with the exact number of arguments requested that -** prefers UTF-16LE when UTF-16BE is requested, or vice versa. -** 6: An exact match. +** 0: Not a match. +** 1: UTF8/16 conversion required and function takes any number of arguments. +** 2: UTF16 byte order change required and function takes any number of args. +** 3: encoding matches and function takes any number of arguments +** 4: UTF8/16 conversion required - argument count matches exactly +** 5: UTF16 byte order conversion required - argument count matches exactly +** 6: Perfect match: encoding and argument count match exactly. ** +** If nArg==(-2) then any function with a non-null xStep or xFunc is +** a perfect match and any function with both xStep and xFunc NULL is +** a non-match. */ -static int matchQuality(FuncDef *p, int nArg, u8 enc){ - int match = 0; - if( p->nArg==-1 || p->nArg==nArg - || (nArg==-1 && (p->xFunc!=0 || p->xStep!=0)) - ){ +#define FUNC_PERFECT_MATCH 6 /* The score for a perfect match */ +static int matchQuality( + FuncDef *p, /* The function we are evaluating for match quality */ + int nArg, /* Desired number of arguments. (-1)==any */ + u8 enc /* Desired text encoding */ +){ + int match; + + /* nArg of -2 is a special case */ + if( nArg==(-2) ) return (p->xFunc==0 && p->xStep==0) ? 0 : FUNC_PERFECT_MATCH; + + /* Wrong number of arguments means "no match" */ + if( p->nArg!=nArg && p->nArg>=0 ) return 0; + + /* Give a better score to a function with a specific number of arguments + ** than to function that accepts any number of arguments. */ + if( p->nArg==nArg ){ + match = 4; + }else{ match = 1; - if( p->nArg==nArg || nArg==-1 ){ - match = 4; - } - if( enc==p->iPrefEnc ){ - match += 2; - } - else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || - (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ - match += 1; - } } + + /* Bonus points if the text encoding matches */ + if( enc==p->iPrefEnc ){ + match += 2; /* Exact encoding match */ + }else if( (enc & p->iPrefEnc & 2)!=0 ){ + match += 1; /* Both are UTF16, but with different byte orders */ + } + return match; } @@ -85195,13 +86357,12 @@ SQLITE_PRIVATE void sqlite3FuncDefInsert( ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked 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. +** no matching function previously existed. ** -** 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 nArg is -2, then the first valid function found is returned. A +** function is valid if either xFunc or xStep is non-zero. The nArg==(-2) +** case is used to see if zName is a valid function name for some number +** of arguments. If nArg is -2, then createFlag must be 0. ** ** 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 @@ -85213,14 +86374,15 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction( int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ u8 enc, /* Preferred text encoding */ - int createFlag /* Create new entry if true and does not otherwise exist */ + u8 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 */ int h; /* Hash value */ - + assert( nArg>=(-2) ); + assert( nArg>=(-1) || createFlag==0 ); assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a); @@ -85266,7 +86428,7 @@ SQLITE_PRIVATE FuncDef *sqlite3FindFunction( ** 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<6 || pBest->nArg!=nArg) && + if( createFlag && bestScorezName = (char *)&pBest[1]; pBest->nArg = (u16)nArg; @@ -85718,7 +86880,7 @@ SQLITE_PRIVATE void sqlite3DeleteFrom( pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK ); if( pWInfo==0 ) goto delete_from_cleanup; - regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid); + regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0); sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid); if( db->flags & SQLITE_CountRows ){ sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1); @@ -86024,6 +87186,14 @@ static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ return context->pColl; } +/* +** Indicate that the accumulator load should be skipped on this +** iteration of the aggregate loop. +*/ +static void sqlite3SkipAccumulatorLoad(sqlite3_context *context){ + context->skipFlag = 1; +} + /* ** Implementation of the non-aggregate min() and max() functions */ @@ -86404,7 +87574,7 @@ static void randomFunc( ** 2s complement of that positive value. The end result can ** therefore be no less than -9223372036854775807. */ - r = -(r ^ (((sqlite3_int64)1)<<63)); + r = -(r & LARGEST_INT64); } sqlite3_result_int64(context, r); } @@ -87330,11 +88500,12 @@ static void minmaxStep( Mem *pBest; UNUSED_PARAMETER(NotUsed); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); if( !pBest ) return; - if( pBest->flags ){ + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ + if( pBest->flags ) sqlite3SkipAccumulatorLoad(context); + }else if( pBest->flags ){ int max; int cmp; CollSeq *pColl = sqlite3GetFuncCollSeq(context); @@ -87350,6 +88521,8 @@ static void minmaxStep( cmp = sqlite3MemCompare(pBest, pArg, pColl); if( (max && cmp<0) || (!max && cmp>0) ){ sqlite3VdbeMemCopy(pBest, pArg); + }else{ + sqlite3SkipAccumulatorLoad(context); } }else{ sqlite3VdbeMemCopy(pBest, pArg); @@ -87359,7 +88532,7 @@ static void minMaxFinalize(sqlite3_context *context){ sqlite3_value *pRes; pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); if( pRes ){ - if( ALWAYS(pRes->flags) ){ + if( pRes->flags ){ sqlite3_result_value(context, pRes); } sqlite3VdbeMemRelease(pRes); @@ -87527,8 +88700,8 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ 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 ), + FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), + FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), @@ -87540,11 +88713,9 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){ 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,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0}, + FUNCTION2(coalesce, -1, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE), FUNCTION(hex, 1, 0, 0, hexFunc ), -/* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */ - {2,SQLITE_UTF8,SQLITE_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0}, + FUNCTION2(ifnull, 2, 0, 0, ifnullFunc, SQLITE_FUNC_COALESCE), FUNCTION(random, 0, 0, 0, randomFunc ), FUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), @@ -89981,9 +91152,11 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( int regData; /* Register containing first data column */ int iCur; /* Table cursor number */ Index *pIdx; /* Pointer to one of the indices */ + sqlite3 *db; /* Database connection */ int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */ int regOldRowid = (rowidChng && isUpdate) ? rowidChng : regRowid; + db = pParse->db; v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ @@ -90016,7 +91189,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( char *zMsg; sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT, onError, regData+i); - zMsg = sqlite3MPrintf(pParse->db, "%s.%s may not be NULL", + zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL", pTab->zName, pTab->aCol[i].zName); sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC); break; @@ -90038,18 +91211,27 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( /* Test all CHECK constraints */ #ifndef SQLITE_OMIT_CHECK - if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){ - int allOk = sqlite3VdbeMakeLabel(v); + if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ + ExprList *pCheck = pTab->pCheck; pParse->ckBase = regData; - sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL); onError = overrideError!=OE_Default ? overrideError : OE_Abort; - if( onError==OE_Ignore ){ - sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); - }else{ - if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ - sqlite3HaltConstraint(pParse, onError, 0, 0); + for(i=0; inExpr; i++){ + int allOk = sqlite3VdbeMakeLabel(v); + sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); + if( onError==OE_Ignore ){ + sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); + }else{ + char *zConsName = pCheck->a[i].zName; + if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ + if( zConsName ){ + zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); + }else{ + zConsName = 0; + } + sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); + } + sqlite3VdbeResolveLabel(v, allOk); } - sqlite3VdbeResolveLabel(v, allOk); } #endif /* !defined(SQLITE_OMIT_CHECK) */ @@ -90105,7 +91287,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( ** table. */ Trigger *pTrigger = 0; - if( pParse->db->flags&SQLITE_RecTriggers ){ + if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){ @@ -90194,7 +91376,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( char *zErr; sqlite3StrAccumInit(&errMsg, 0, 0, 200); - errMsg.db = pParse->db; + errMsg.db = db; zSep = pIdx->nColumn>1 ? "columns " : "column "; for(j=0; jnColumn; j++){ char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; @@ -90218,7 +91400,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks( Trigger *pTrigger = 0; assert( onError==OE_Replace ); sqlite3MultiWrite(pParse); - if( pParse->db->flags&SQLITE_RecTriggers ){ + if( db->flags&SQLITE_RecTriggers ){ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0); } sqlite3GenerateRowDelete( @@ -90548,7 +91730,7 @@ static int xferOptimization( } } #ifndef SQLITE_OMIT_CHECK - if( pDest->pCheck && sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ + if( pDest->pCheck && sqlite3ExprListCompare(pSrc->pCheck, pDest->pCheck) ){ return 0; /* Tables have different CHECK constraints. Ticket #2252 */ } #endif @@ -91941,14 +93123,15 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){ /* ** Interpret the given string as a safety level. Return 0 for OFF, ** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or -** unrecognized string argument. +** unrecognized string argument. The FULL option is disallowed +** if the omitFull parameter it 1. ** ** Note that the values returned are one less that the values that ** should be passed into sqlite3BtreeSetSafetyLevel(). The is done ** to support legacy SQL code. The safety level used to be boolean ** and older scripts may have used numbers 0 for OFF and 1 for ON. */ -static u8 getSafetyLevel(const char *z){ +static u8 getSafetyLevel(const char *z, int omitFull, int dflt){ /* 123456789 123456789 */ static const char zText[] = "onoffalseyestruefull"; static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; @@ -91959,19 +93142,19 @@ static u8 getSafetyLevel(const char *z){ return (u8)sqlite3Atoi(z); } n = sqlite3Strlen30(z); - for(i=0; iaDb[1].pBt); db->aDb[1].pBt = 0; - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); } return SQLITE_OK; } @@ -92114,7 +93297,6 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ #endif /* The following is VERY experimental */ { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, - { "omit_readlock", SQLITE_NoReadlock }, /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted ** flag if there are any active statements. */ @@ -92146,7 +93328,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ mask &= ~(SQLITE_ForeignKeys); } - if( sqlite3GetBoolean(zRight) ){ + if( sqlite3GetBoolean(zRight, 0) ){ db->flags |= mask; }else{ db->flags &= ~mask; @@ -92237,9 +93419,12 @@ SQLITE_PRIVATE void sqlite3Pragma( const char *zDb = 0; /* The database name */ Token *pId; /* Pointer to token */ int iDb; /* Database index for */ - sqlite3 *db = pParse->db; - Db *pDb; - Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); + char *aFcntl[4]; /* Argument to SQLITE_FCNTL_PRAGMA */ + int rc; /* return value form SQLITE_FCNTL_PRAGMA */ + sqlite3 *db = pParse->db; /* The database connection */ + Db *pDb; /* The specific database being pragmaed */ + Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db); /* Prepared statement */ + if( v==0 ) return; sqlite3VdbeRunOnlyOnce(v); pParse->nMem = 2; @@ -92270,6 +93455,34 @@ SQLITE_PRIVATE void sqlite3Pragma( if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ goto pragma_out; } + + /* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS + ** connection. If it returns SQLITE_OK, then assume that the VFS + ** handled the pragma and generate a no-op prepared statement. + */ + aFcntl[0] = 0; + aFcntl[1] = zLeft; + aFcntl[2] = zRight; + aFcntl[3] = 0; + rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl); + if( rc==SQLITE_OK ){ + if( aFcntl[0] ){ + int mem = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC); + sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1); + sqlite3_free(aFcntl[0]); + } + }else if( rc!=SQLITE_NOTFOUND ){ + if( aFcntl[0] ){ + sqlite3ErrorMsg(pParse, "%s", aFcntl[0]); + sqlite3_free(aFcntl[0]); + } + pParse->nErr++; + pParse->rc = rc; + }else + #if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED) /* @@ -92362,7 +93575,7 @@ SQLITE_PRIVATE void sqlite3Pragma( int b = -1; assert( pBt!=0 ); if( zRight ){ - b = sqlite3GetBoolean(zRight); + b = sqlite3GetBoolean(zRight, 0); } if( pId2->n==0 && b>=0 ){ int ii; @@ -92557,7 +93770,7 @@ SQLITE_PRIVATE void sqlite3Pragma( ** creates the database file. It is important that it is created ** as an auto-vacuum capable db. */ - int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); + rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ /* When setting the auto_vacuum mode to either "full" or ** "incremental", write the value of meta[6] in the database @@ -92675,7 +93888,6 @@ SQLITE_PRIVATE void sqlite3Pragma( }else{ #ifndef SQLITE_OMIT_WSD if( zRight[0] ){ - int rc; int res; rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ @@ -92699,6 +93911,50 @@ SQLITE_PRIVATE void sqlite3Pragma( } }else +#if SQLITE_OS_WIN + /* + ** PRAGMA data_store_directory + ** PRAGMA data_store_directory = ""|"directory_name" + ** + ** Return or set the local value of the data_store_directory flag. Changing + ** the value sets a specific directory to be used for database files that + ** were specified with a relative pathname. Setting to a null string reverts + ** to the default database directory, which for database files specified with + ** a relative path will probably be based on the current directory for the + ** process. Database file specified with an absolute path are not impacted + ** by this setting, regardless of its value. + ** + */ + if( sqlite3StrICmp(zLeft, "data_store_directory")==0 ){ + if( !zRight ){ + if( sqlite3_data_directory ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "data_store_directory", SQLITE_STATIC); + sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, sqlite3_data_directory, 0); + sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); + } + }else{ +#ifndef SQLITE_OMIT_WSD + if( zRight[0] ){ + int res; + rc = sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); + if( rc!=SQLITE_OK || res==0 ){ + sqlite3ErrorMsg(pParse, "not a writable directory"); + goto pragma_out; + } + } + sqlite3_free(sqlite3_data_directory); + if( zRight[0] ){ + sqlite3_data_directory = sqlite3_mprintf("%s", zRight); + }else{ + sqlite3_data_directory = 0; + } +#endif /* SQLITE_OMIT_WSD */ + } + }else +#endif + #if !defined(SQLITE_ENABLE_LOCKING_STYLE) # if defined(__APPLE__) # define SQLITE_ENABLE_LOCKING_STYLE 1 @@ -92767,7 +94023,7 @@ SQLITE_PRIVATE void sqlite3Pragma( sqlite3ErrorMsg(pParse, "Safety level may not be changed inside a transaction"); }else{ - pDb->safety_level = getSafetyLevel(zRight)+1; + pDb->safety_level = getSafetyLevel(zRight,0,1)+1; } } }else @@ -92966,7 +94222,7 @@ SQLITE_PRIVATE void sqlite3Pragma( #ifndef NDEBUG if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ if( zRight ){ - if( sqlite3GetBoolean(zRight) ){ + if( sqlite3GetBoolean(zRight, 0) ){ sqlite3ParserTrace(stderr, "parser: "); }else{ sqlite3ParserTrace(0, 0); @@ -92980,7 +94236,7 @@ SQLITE_PRIVATE void sqlite3Pragma( */ if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){ if( zRight ){ - sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight)); + sqlite3RegisterLikeFunctions(db, sqlite3GetBoolean(zRight, 0)); } }else @@ -93731,7 +94987,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; if( encoding==0 ) encoding = SQLITE_UTF8; ENC(db) = encoding; - db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0); }else{ /* If opening an attached database, the encoding much match ENC(db) */ if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){ @@ -93811,7 +95066,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ } if( db->mallocFailed ){ rc = SQLITE_NOMEM; - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); } if( rc==SQLITE_OK || (db->flags&SQLITE_RecoveryMode)){ /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider @@ -93864,7 +95119,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ if( DbHasProperty(db, i, DB_SchemaLoaded) || i==1 ) continue; rc = sqlite3InitOne(db, i, pzErrMsg); if( rc ){ - sqlite3ResetInternalSchema(db, i); + sqlite3ResetOneSchema(db, i); } } @@ -93877,7 +95132,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){ && !DbHasProperty(db, 1, DB_SchemaLoaded) ){ rc = sqlite3InitOne(db, 1, pzErrMsg); if( rc ){ - sqlite3ResetInternalSchema(db, 1); + sqlite3ResetOneSchema(db, 1); } } #endif @@ -93945,7 +95200,7 @@ static void schemaIsValid(Parse *pParse){ sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&cookie); assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ - sqlite3ResetInternalSchema(db, iDb); + sqlite3ResetOneSchema(db, iDb); pParse->rc = SQLITE_SCHEMA; } @@ -94175,6 +95430,7 @@ static int sqlite3LockAndPrepare( } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); + assert( rc==SQLITE_OK || *ppStmt==0 ); return rc; } @@ -94406,6 +95662,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew( pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0)); } pNew->pEList = pEList; + if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); pNew->pSrc = pSrc; pNew->pWhere = pWhere; pNew->pGroupBy = pGroupBy; @@ -95590,9 +96847,17 @@ static int selectColumnsFromExprList( char *zName; /* Column name */ int nName; /* Size of name in zName[] */ - *pnCol = nCol = pEList->nExpr; - aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); - if( aCol==0 ) return SQLITE_NOMEM; + if( pEList ){ + nCol = pEList->nExpr; + aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); + testcase( aCol==0 ); + }else{ + nCol = 0; + aCol = 0; + } + *pnCol = nCol; + *paCol = aCol; + for(i=0, pCol=aCol; ipEList && pPrior->pEList ); if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ - sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" - " do not have the same number of result columns", selectOpName(p->op)); + if( p->selFlags & SF_Values ){ + sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); + }else{ + sqlite3ErrorMsg(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; } @@ -96561,7 +97830,7 @@ static int multiSelectOrderBy( pNew->flags |= EP_IntValue; pNew->u.iValue = i; pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); - pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i; + if( pOrderBy ) pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i; } } } @@ -97171,7 +98440,8 @@ static int flattenSubquery( /* Authorize the subquery */ pParse->zAuthContext = pSubitem->zName; - sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); + TESTONLY(i =) sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0); + testcase( i==SQLITE_DENY ); pParse->zAuthContext = zSavedAuthContext; /* If the sub-query is a compound SELECT statement, then (by restrictions @@ -97468,6 +98738,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ if( IsVirtual(pTab) ) return 0; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; + if( pAggInfo->nFunc==0 ) return 0; if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0; if( pExpr->flags&EP_Distinct ) return 0; @@ -97924,6 +99195,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; + int regHit = 0; + int addrHitTest = 0; struct AggInfo_func *pF; struct AggInfo_col *pC; @@ -97959,7 +99232,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ if( !pColl ){ pColl = pParse->db->pDfltColl; } - sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ); + if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem; + sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ); } sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem, (void*)pF->pFunc, P4_FUNCDEF); @@ -97982,12 +99256,18 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ ** Another solution would be to change the OP_SCopy used to copy cached ** values to an OP_Copy. */ + if( regHit ){ + addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); + } sqlite3ExprCacheClear(pParse); for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ sqlite3ExprCode(pParse, pC->pExpr, pC->iMem); } pAggInfo->directMode = 0; sqlite3ExprCacheClear(pParse); + if( addrHitTest ){ + sqlite3VdbeJumpHere(v, addrHitTest); + } } /* @@ -98449,7 +99729,9 @@ SQLITE_PRIVATE int sqlite3Select( sAggInfo.nAccumulator = sAggInfo.nColumn; for(i=0; ix.pList); + sNC.ncFlags &= ~NC_InAggFunc; } if( db->mallocFailed ) goto select_end; @@ -98547,7 +99829,7 @@ SQLITE_PRIVATE int sqlite3Select( int r2; r2 = sqlite3ExprCodeGetColumn(pParse, - pCol->pTab, pCol->iColumn, pCol->iTable, r1); + pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0); if( r1!=r2 ){ sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); } @@ -98928,7 +100210,7 @@ SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){ /* End of the structure debug printing code *****************************************************************************/ -#endif /* defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */ +#endif /* defined(SQLITE_ENABLE_TREE_EXPLAIN) */ /************** End of select.c **********************************************/ /************** Begin file table.c *******************************************/ @@ -101108,6 +102390,18 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ } #endif + rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + + /* Begin a transaction and take an exclusive lock on the main database + ** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below, + ** to ensure that we do not try to change the page-size on a WAL database. + */ + rc = execSql(db, pzErrMsg, "BEGIN;"); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + rc = sqlite3BtreeBeginTrans(pMain, 2); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + /* Do not attempt to change the page size for a WAL database */ if( sqlite3PagerGetJournalMode(sqlite3BtreePager(pMain)) ==PAGER_JOURNALMODE_WAL ){ @@ -101121,20 +102415,12 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){ rc = SQLITE_NOMEM; goto end_of_vacuum; } - rc = execSql(db, pzErrMsg, "PRAGMA vacuum_db.synchronous=OFF"); - if( rc!=SQLITE_OK ){ - goto end_of_vacuum; - } #ifndef SQLITE_OMIT_AUTOVACUUM sqlite3BtreeSetAutoVacuum(pTemp, db->nextAutovac>=0 ? db->nextAutovac : sqlite3BtreeGetAutoVacuum(pMain)); #endif - /* Begin a transaction */ - rc = execSql(db, pzErrMsg, "BEGIN EXCLUSIVE;"); - if( rc!=SQLITE_OK ) goto end_of_vacuum; - /* Query the schema of the main database. Create a mirror schema ** in the temporary database. */ @@ -101267,7 +102553,7 @@ end_of_vacuum: /* This both clears the schemas and reduces the size of the db->aDb[] ** array. */ - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); return rc; } @@ -101299,8 +102585,8 @@ end_of_vacuum: ** are invoked only from within xCreate and xConnect methods. */ struct VtabCtx { - Table *pTab; - VTable *pVTable; + VTable *pVTable; /* The virtual table being constructed */ + Table *pTab; /* The Table object to which the virtual table belongs */ }; /* @@ -101315,33 +102601,35 @@ static int createModule( void *pAux, /* Context pointer for xCreate/xConnect */ void (*xDestroy)(void *) /* Module destructor function */ ){ - int rc, nName; - Module *pMod; + int rc = SQLITE_OK; + int nName; sqlite3_mutex_enter(db->mutex); nName = sqlite3Strlen30(zName); - pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); - if( pMod ){ - Module *pDel; - char *zCopy = (char *)(&pMod[1]); - memcpy(zCopy, zName, nName+1); - pMod->zName = zCopy; - pMod->pModule = pModule; - pMod->pAux = pAux; - pMod->xDestroy = xDestroy; - pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod); - if( pDel && pDel->xDestroy ){ - sqlite3ResetInternalSchema(db, -1); - pDel->xDestroy(pDel->pAux); + if( sqlite3HashFind(&db->aModule, zName, nName) ){ + rc = SQLITE_MISUSE_BKPT; + }else{ + Module *pMod; + pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); + if( pMod ){ + Module *pDel; + char *zCopy = (char *)(&pMod[1]); + memcpy(zCopy, zName, nName+1); + pMod->zName = zCopy; + pMod->pModule = pModule; + pMod->pAux = pAux; + pMod->xDestroy = xDestroy; + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,nName,(void*)pMod); + assert( pDel==0 || pDel==pMod ); + if( pDel ){ + db->mallocFailed = 1; + sqlite3DbFree(db, pDel); + } } - sqlite3DbFree(db, pDel); - if( pDel==pMod ){ - db->mallocFailed = 1; - } - }else if( xDestroy ){ - xDestroy(pAux); } - rc = sqlite3ApiExit(db, SQLITE_OK); + rc = sqlite3ApiExit(db, rc); + if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); + sqlite3_mutex_leave(db->mutex); return rc; } @@ -101457,6 +102745,31 @@ static VTable *vtabDisconnectAll(sqlite3 *db, Table *p){ return pRet; } +/* +** Table *p is a virtual table. This function removes the VTable object +** for table *p associated with database connection db from the linked +** list in p->pVTab. It also decrements the VTable ref count. This is +** used when closing database connection db to free all of its VTable +** objects without disturbing the rest of the Schema object (which may +** be being used by other shared-cache connections). +*/ +SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p){ + VTable **ppVTab; + + assert( IsVirtual(p) ); + assert( sqlite3BtreeHoldsAllMutexes(db) ); + assert( sqlite3_mutex_held(db->mutex) ); + + for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){ + if( (*ppVTab)->db==db ){ + VTable *pVTab = *ppVTab; + *ppVTab = pVTab->pNext; + sqlite3VtabUnlock(pVTab); + break; + } + } +} + /* ** Disconnect all the virtual table objects in the sqlite3.pDisconnect list. @@ -101555,13 +102868,14 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse( Parse *pParse, /* Parsing context */ Token *pName1, /* Name of new table, or database name */ Token *pName2, /* Name of new table or NULL */ - Token *pModuleName /* Name of the module for the virtual table */ + Token *pModuleName, /* Name of the module for the virtual table */ + int ifNotExists /* No error if the table already exists */ ){ int iDb; /* The database the table is being created in */ Table *pTable; /* The new virtual table */ sqlite3 *db; /* Database connection */ - sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0); + sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, ifNotExists); pTable = pParse->pNewTable; if( pTable==0 ) return; assert( 0==pTable->pIndex ); @@ -101596,7 +102910,7 @@ SQLITE_PRIVATE void sqlite3VtabBeginParse( ** virtual table currently under construction in pParse->pTable. */ static void addArgumentToVtab(Parse *pParse){ - if( pParse->sArg.z && ALWAYS(pParse->pNewTable) ){ + if( pParse->sArg.z && pParse->pNewTable ){ const char *z = (const char*)pParse->sArg.z; int n = pParse->sArg.n; sqlite3 *db = pParse->db; @@ -101723,7 +103037,7 @@ static int vtabCallConstructor( int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), char **pzErr ){ - VtabCtx sCtx; + VtabCtx sCtx, *pPriorCtx; VTable *pVTable; int rc; const char *const*azArg = (const char *const*)pTab->azModuleArg; @@ -101748,9 +103062,10 @@ static int vtabCallConstructor( assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; + pPriorCtx = db->pVtabCtx; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); - db->pVtabCtx = 0; + db->pVtabCtx = pPriorCtx; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; if( SQLITE_OK!=rc ){ @@ -103031,7 +104346,10 @@ static int isLikeOrGlob( #endif pList = pExpr->x.pList; pLeft = pList->a[1].pExpr; - if( pLeft->op!=TK_COLUMN || sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT ){ + if( pLeft->op!=TK_COLUMN + || sqlite3ExprAffinity(pLeft)!=SQLITE_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; @@ -103904,15 +105222,19 @@ static int isDistinctRedundant( ** 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; inColumn; i++){ int iCol = pIdx->aiColumn[i]; - if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) - && 0>findIndexCol(pParse, pDistinct, iBase, pIdx, i) - ){ - break; + if( 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 ){ @@ -104060,14 +105382,25 @@ static int isSortingIndex( } if( pIdx->onError!=OE_None && i==pIdx->nColumn && (wsFlags & WHERE_COLUMN_NULL)==0 - && !referencesOtherTables(pOrderBy, pMaskSet, j, base) ){ - /* All terms of this index match some prefix of the ORDER BY clause - ** and the index is UNIQUE and no terms on the tail of the ORDER BY - ** clause reference other tables in a join. If this is all true then - ** the order by clause is superfluous. Not that if the matching - ** condition is IS NULL then the result is not necessarily unique - ** even on a UNIQUE index, so disallow those cases. */ - return 1; + && !referencesOtherTables(pOrderBy, pMaskSet, j, base) + ){ + Column *aCol = pIdx->pTable->aCol; + + /* All terms of this index match some prefix of the ORDER BY clause, + ** the index is UNIQUE, and no terms on the tail of the ORDER BY + ** refer to other tables in a join. So, assuming that the index entries + ** visited contain no NULL values, then this index delivers rows in + ** the required order. + ** + ** It is not possible for any of the first nEqCol index fields to be + ** NULL (since the corresponding "=" operator in the WHERE clause would + ** not be true). So if all remaining index columns have NOT NULL + ** constaints attached to them, we can be confident that the visited + ** index entries are free of NULLs. */ + for(i=nEqCol; inColumn; i++){ + if( aCol[pIdx->aiColumn[i]].notNull==0 ) break; + } + return (i==pIdx->nColumn); } return 0; } @@ -105448,7 +106781,9 @@ static void bestBtreeIndex( /* If there is a DISTINCT qualifier and this index will scan rows in ** order of the DISTINCT expressions, clear bDist and set the appropriate ** flags in wsFlags. */ - if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) ){ + if( isDistinctIndex(pParse, pWC, pProbe, iCur, pDistinct, nEq) + && (wsFlags & WHERE_COLUMN_IN)==0 + ){ bDist = 0; wsFlags |= WHERE_ROWID_RANGE|WHERE_COLUMN_RANGE|WHERE_DISTINCT; } @@ -106145,8 +107480,7 @@ static Bitmask codeOneLoopStart( WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ - Bitmask notReady, /* Which tables are currently available */ - Expr *pWhere /* Complete WHERE clause */ + Bitmask notReady /* Which tables are currently available */ ){ int j, k; /* Loop counters */ int iCur; /* The VDBE cursor for the table */ @@ -106685,10 +108019,25 @@ static Bitmask codeOneLoopStart( ** 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 sqlite3WhereBegin() 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. */ if( pWC->nTerm>1 ){ - pAndExpr = sqlite3ExprAlloc(pParse->db, TK_AND, 0, 0); - pAndExpr->pRight = pWhere; + int iTerm; + for(iTerm=0; iTermnTerm; iTerm++){ + Expr *pExpr = pWC->a[iTerm].pExpr; + if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; + if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue; + if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; + pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); + pAndExpr = sqlite3ExprAnd(pParse->db, pAndExpr, pExpr); + } + if( pAndExpr ){ + pAndExpr = sqlite3PExpr(pParse, TK_AND, 0, pAndExpr, 0); + } } for(ii=0; iinTerm; ii++){ @@ -106712,7 +108061,7 @@ static Bitmask codeOneLoopStart( int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); int r; r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur, - regRowid); + regRowid, 0); sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, sqlite3VdbeCurrentAddr(v)+2, r, iSet); } @@ -106730,7 +108079,10 @@ static Bitmask codeOneLoopStart( } } } - sqlite3DbFree(pParse->db, pAndExpr); + if( pAndExpr ){ + pAndExpr->pLeft = 0; + sqlite3ExprDelete(pParse->db, pAndExpr); + } sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v)); sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); sqlite3VdbeResolveLabel(v, iLoopBody); @@ -107386,7 +108738,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin( for(i=0; ia[i]; explainOneScan(pParse, pTabList, pLevel, i, pLevel->iFrom, wctrlFlags); - notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady, pWhere); + notReady = codeOneLoopStart(pWInfo, i, wctrlFlags, notReady); pWInfo->iContinue = pLevel->addrCont; } @@ -107622,7 +108974,7 @@ struct LimitVal { */ struct LikeOp { Token eOperator; /* "like" or "glob" or "regexp" */ - int not; /* True if the NOT keyword is present */ + int bNot; /* True if the NOT keyword is present */ }; /* @@ -107641,6 +108993,14 @@ struct TrigEvent { int a; IdList * b; }; */ struct AttachKey { int type; Token key; }; +/* +** One or more VALUES claues +*/ +struct ValueList { + ExprList *pList; + Select *pSelect; +}; + /* This is a utility routine used to set the ExprSpan.zStart and ** ExprSpan.zEnd values of pOut so that the span covers the complete @@ -107764,26 +109124,27 @@ struct AttachKey { int type; Token key; }; ** defined, then do no error processing. */ #define YYCODETYPE unsigned char -#define YYNOCODE 253 +#define YYNOCODE 251 #define YYACTIONTYPE unsigned short int #define YYWILDCARD 67 #define sqlite3ParserTOKENTYPE Token typedef union { int yyinit; sqlite3ParserTOKENTYPE yy0; - int yy4; - struct TrigEvent yy90; - ExprSpan yy118; - TriggerStep* yy203; - u8 yy210; - struct {int value; int mask;} yy215; - SrcList* yy259; - struct LimitVal yy292; - Expr* yy314; - ExprList* yy322; - struct LikeOp yy342; - IdList* yy384; - Select* yy387; + struct LimitVal yy64; + Expr* yy122; + Select* yy159; + IdList* yy180; + struct {int value; int mask;} yy207; + u8 yy258; + struct LikeOp yy318; + TriggerStep* yy327; + ExprSpan yy342; + SrcList* yy347; + int yy392; + struct TrigEvent yy410; + ExprList* yy442; + struct ValueList yy487; } YYMINORTYPE; #ifndef YYSTACKDEPTH #define YYSTACKDEPTH 100 @@ -107792,8 +109153,8 @@ typedef union { #define sqlite3ParserARG_PDECL ,Parse *pParse #define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse #define sqlite3ParserARG_STORE yypParser->pParse = pParse -#define YYNSTATE 630 -#define YYNRULE 329 +#define YYNSTATE 627 +#define YYNRULE 327 #define YYFALLBACK 1 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2) #define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) @@ -107863,473 +109224,474 @@ static const YYMINORTYPE yyzerominor = { 0 }; ** shifting non-terminals after a reduce. ** yy_default[] Default action for each state. */ -#define YY_ACTTAB_COUNT (1557) +#define YY_ACTTAB_COUNT (1564) static const YYACTIONTYPE yy_action[] = { - /* 0 */ 313, 960, 186, 419, 2, 172, 627, 597, 55, 55, - /* 10 */ 55, 55, 48, 53, 53, 53, 53, 52, 52, 51, - /* 20 */ 51, 51, 50, 238, 302, 283, 623, 622, 516, 515, - /* 30 */ 590, 584, 55, 55, 55, 55, 282, 53, 53, 53, - /* 40 */ 53, 52, 52, 51, 51, 51, 50, 238, 6, 56, - /* 50 */ 57, 47, 582, 581, 583, 583, 54, 54, 55, 55, - /* 60 */ 55, 55, 608, 53, 53, 53, 53, 52, 52, 51, - /* 70 */ 51, 51, 50, 238, 313, 597, 409, 330, 579, 579, - /* 80 */ 32, 53, 53, 53, 53, 52, 52, 51, 51, 51, - /* 90 */ 50, 238, 330, 217, 620, 619, 166, 411, 624, 382, - /* 100 */ 379, 378, 7, 491, 590, 584, 200, 199, 198, 58, - /* 110 */ 377, 300, 414, 621, 481, 66, 623, 622, 621, 580, - /* 120 */ 254, 601, 94, 56, 57, 47, 582, 581, 583, 583, - /* 130 */ 54, 54, 55, 55, 55, 55, 671, 53, 53, 53, - /* 140 */ 53, 52, 52, 51, 51, 51, 50, 238, 313, 532, - /* 150 */ 226, 506, 507, 133, 177, 139, 284, 385, 279, 384, - /* 160 */ 169, 197, 342, 398, 251, 226, 253, 275, 388, 167, - /* 170 */ 139, 284, 385, 279, 384, 169, 570, 236, 590, 584, - /* 180 */ 672, 240, 275, 157, 620, 619, 554, 437, 51, 51, - /* 190 */ 51, 50, 238, 343, 439, 553, 438, 56, 57, 47, - /* 200 */ 582, 581, 583, 583, 54, 54, 55, 55, 55, 55, - /* 210 */ 465, 53, 53, 53, 53, 52, 52, 51, 51, 51, - /* 220 */ 50, 238, 313, 390, 52, 52, 51, 51, 51, 50, - /* 230 */ 238, 391, 166, 491, 566, 382, 379, 378, 409, 440, - /* 240 */ 579, 579, 252, 440, 607, 66, 377, 513, 621, 49, - /* 250 */ 46, 147, 590, 584, 621, 16, 466, 189, 621, 441, - /* 260 */ 442, 673, 526, 441, 340, 577, 595, 64, 194, 482, - /* 270 */ 434, 56, 57, 47, 582, 581, 583, 583, 54, 54, - /* 280 */ 55, 55, 55, 55, 30, 53, 53, 53, 53, 52, - /* 290 */ 52, 51, 51, 51, 50, 238, 313, 593, 593, 593, - /* 300 */ 387, 578, 606, 493, 259, 351, 258, 411, 1, 623, - /* 310 */ 622, 496, 623, 622, 65, 240, 623, 622, 597, 443, - /* 320 */ 237, 239, 414, 341, 237, 602, 590, 584, 18, 603, - /* 330 */ 166, 601, 87, 382, 379, 378, 67, 623, 622, 38, - /* 340 */ 623, 622, 176, 270, 377, 56, 57, 47, 582, 581, - /* 350 */ 583, 583, 54, 54, 55, 55, 55, 55, 175, 53, - /* 360 */ 53, 53, 53, 52, 52, 51, 51, 51, 50, 238, - /* 370 */ 313, 396, 233, 411, 531, 565, 317, 620, 619, 44, - /* 380 */ 620, 619, 240, 206, 620, 619, 597, 266, 414, 268, - /* 390 */ 409, 597, 579, 579, 352, 184, 505, 601, 73, 533, - /* 400 */ 590, 584, 466, 548, 190, 620, 619, 576, 620, 619, - /* 410 */ 547, 383, 551, 35, 332, 575, 574, 600, 504, 56, - /* 420 */ 57, 47, 582, 581, 583, 583, 54, 54, 55, 55, - /* 430 */ 55, 55, 567, 53, 53, 53, 53, 52, 52, 51, - /* 440 */ 51, 51, 50, 238, 313, 411, 561, 561, 528, 364, - /* 450 */ 259, 351, 258, 183, 361, 549, 524, 374, 411, 597, - /* 460 */ 414, 240, 560, 560, 409, 604, 579, 579, 328, 601, - /* 470 */ 93, 623, 622, 414, 590, 584, 237, 564, 559, 559, - /* 480 */ 520, 402, 601, 87, 409, 210, 579, 579, 168, 421, - /* 490 */ 950, 519, 950, 56, 57, 47, 582, 581, 583, 583, - /* 500 */ 54, 54, 55, 55, 55, 55, 192, 53, 53, 53, - /* 510 */ 53, 52, 52, 51, 51, 51, 50, 238, 313, 600, - /* 520 */ 293, 563, 511, 234, 357, 146, 475, 475, 367, 411, - /* 530 */ 562, 411, 358, 542, 425, 171, 411, 215, 144, 620, - /* 540 */ 619, 544, 318, 353, 414, 203, 414, 275, 590, 584, - /* 550 */ 549, 414, 174, 601, 94, 601, 79, 558, 471, 61, - /* 560 */ 601, 79, 421, 949, 350, 949, 34, 56, 57, 47, - /* 570 */ 582, 581, 583, 583, 54, 54, 55, 55, 55, 55, - /* 580 */ 535, 53, 53, 53, 53, 52, 52, 51, 51, 51, - /* 590 */ 50, 238, 313, 307, 424, 394, 272, 49, 46, 147, - /* 600 */ 349, 322, 4, 411, 491, 312, 321, 425, 568, 492, - /* 610 */ 216, 264, 407, 575, 574, 429, 66, 549, 414, 621, - /* 620 */ 540, 602, 590, 584, 13, 603, 621, 601, 72, 12, - /* 630 */ 618, 617, 616, 202, 210, 621, 546, 469, 422, 319, - /* 640 */ 148, 56, 57, 47, 582, 581, 583, 583, 54, 54, - /* 650 */ 55, 55, 55, 55, 338, 53, 53, 53, 53, 52, - /* 660 */ 52, 51, 51, 51, 50, 238, 313, 600, 600, 411, - /* 670 */ 39, 21, 37, 170, 237, 875, 411, 572, 572, 201, - /* 680 */ 144, 473, 538, 331, 414, 474, 143, 146, 630, 628, - /* 690 */ 334, 414, 353, 601, 68, 168, 590, 584, 132, 365, - /* 700 */ 601, 96, 307, 423, 530, 336, 49, 46, 147, 568, - /* 710 */ 406, 216, 549, 360, 529, 56, 57, 47, 582, 581, - /* 720 */ 583, 583, 54, 54, 55, 55, 55, 55, 411, 53, - /* 730 */ 53, 53, 53, 52, 52, 51, 51, 51, 50, 238, - /* 740 */ 313, 411, 605, 414, 484, 510, 172, 422, 597, 318, - /* 750 */ 496, 485, 601, 99, 411, 142, 414, 411, 231, 411, - /* 760 */ 540, 411, 359, 629, 2, 601, 97, 426, 308, 414, - /* 770 */ 590, 584, 414, 20, 414, 621, 414, 621, 601, 106, - /* 780 */ 503, 601, 105, 601, 108, 601, 109, 204, 28, 56, - /* 790 */ 57, 47, 582, 581, 583, 583, 54, 54, 55, 55, - /* 800 */ 55, 55, 411, 53, 53, 53, 53, 52, 52, 51, - /* 810 */ 51, 51, 50, 238, 313, 411, 597, 414, 411, 276, - /* 820 */ 214, 600, 411, 366, 213, 381, 601, 134, 274, 500, - /* 830 */ 414, 167, 130, 414, 621, 411, 354, 414, 376, 601, - /* 840 */ 135, 129, 601, 100, 590, 584, 601, 104, 522, 521, - /* 850 */ 414, 621, 224, 273, 600, 167, 327, 282, 600, 601, - /* 860 */ 103, 468, 521, 56, 57, 47, 582, 581, 583, 583, - /* 870 */ 54, 54, 55, 55, 55, 55, 411, 53, 53, 53, - /* 880 */ 53, 52, 52, 51, 51, 51, 50, 238, 313, 411, - /* 890 */ 27, 414, 411, 375, 276, 167, 359, 544, 50, 238, - /* 900 */ 601, 95, 128, 223, 414, 411, 165, 414, 411, 621, - /* 910 */ 411, 621, 612, 601, 102, 372, 601, 76, 590, 584, - /* 920 */ 414, 570, 236, 414, 470, 414, 167, 621, 188, 601, - /* 930 */ 98, 225, 601, 138, 601, 137, 232, 56, 45, 47, - /* 940 */ 582, 581, 583, 583, 54, 54, 55, 55, 55, 55, - /* 950 */ 411, 53, 53, 53, 53, 52, 52, 51, 51, 51, - /* 960 */ 50, 238, 313, 276, 276, 414, 411, 276, 544, 459, - /* 970 */ 359, 171, 209, 479, 601, 136, 628, 334, 621, 621, - /* 980 */ 125, 414, 621, 368, 411, 621, 257, 540, 589, 588, - /* 990 */ 601, 75, 590, 584, 458, 446, 23, 23, 124, 414, - /* 1000 */ 326, 325, 621, 427, 324, 309, 600, 288, 601, 92, - /* 1010 */ 586, 585, 57, 47, 582, 581, 583, 583, 54, 54, - /* 1020 */ 55, 55, 55, 55, 411, 53, 53, 53, 53, 52, - /* 1030 */ 52, 51, 51, 51, 50, 238, 313, 587, 411, 414, - /* 1040 */ 411, 207, 611, 476, 171, 472, 160, 123, 601, 91, - /* 1050 */ 323, 261, 15, 414, 464, 414, 411, 621, 411, 354, - /* 1060 */ 222, 411, 601, 74, 601, 90, 590, 584, 159, 264, - /* 1070 */ 158, 414, 461, 414, 621, 600, 414, 121, 120, 25, - /* 1080 */ 601, 89, 601, 101, 621, 601, 88, 47, 582, 581, - /* 1090 */ 583, 583, 54, 54, 55, 55, 55, 55, 544, 53, - /* 1100 */ 53, 53, 53, 52, 52, 51, 51, 51, 50, 238, - /* 1110 */ 43, 405, 263, 3, 610, 264, 140, 415, 622, 24, - /* 1120 */ 410, 11, 456, 594, 118, 155, 219, 452, 408, 621, - /* 1130 */ 621, 621, 156, 43, 405, 621, 3, 286, 621, 113, - /* 1140 */ 415, 622, 111, 445, 411, 400, 557, 403, 545, 10, - /* 1150 */ 411, 408, 264, 110, 205, 436, 541, 566, 453, 414, - /* 1160 */ 621, 621, 63, 621, 435, 414, 411, 621, 601, 94, - /* 1170 */ 403, 621, 411, 337, 601, 86, 150, 40, 41, 534, - /* 1180 */ 566, 414, 242, 264, 42, 413, 412, 414, 600, 595, - /* 1190 */ 601, 85, 191, 333, 107, 451, 601, 84, 621, 539, - /* 1200 */ 40, 41, 420, 230, 411, 149, 316, 42, 413, 412, - /* 1210 */ 398, 127, 595, 315, 621, 399, 278, 625, 181, 414, - /* 1220 */ 593, 593, 593, 592, 591, 14, 450, 411, 601, 71, - /* 1230 */ 240, 621, 43, 405, 264, 3, 615, 180, 264, 415, - /* 1240 */ 622, 614, 414, 593, 593, 593, 592, 591, 14, 621, - /* 1250 */ 408, 601, 70, 621, 417, 33, 405, 613, 3, 411, - /* 1260 */ 264, 411, 415, 622, 418, 626, 178, 509, 8, 403, - /* 1270 */ 241, 416, 126, 408, 414, 621, 414, 449, 208, 566, - /* 1280 */ 240, 221, 621, 601, 83, 601, 82, 599, 297, 277, - /* 1290 */ 296, 30, 403, 31, 395, 264, 295, 397, 489, 40, - /* 1300 */ 41, 411, 566, 220, 621, 294, 42, 413, 412, 271, - /* 1310 */ 621, 595, 600, 621, 59, 60, 414, 269, 267, 623, - /* 1320 */ 622, 36, 40, 41, 621, 601, 81, 598, 235, 42, - /* 1330 */ 413, 412, 621, 621, 595, 265, 344, 411, 248, 556, - /* 1340 */ 173, 185, 593, 593, 593, 592, 591, 14, 218, 29, - /* 1350 */ 621, 543, 414, 305, 304, 303, 179, 301, 411, 566, - /* 1360 */ 454, 601, 80, 289, 335, 593, 593, 593, 592, 591, - /* 1370 */ 14, 411, 287, 414, 151, 392, 246, 260, 411, 196, - /* 1380 */ 195, 523, 601, 69, 411, 245, 414, 526, 537, 285, - /* 1390 */ 389, 595, 621, 414, 536, 601, 17, 362, 153, 414, - /* 1400 */ 466, 463, 601, 78, 154, 414, 462, 152, 601, 77, - /* 1410 */ 355, 255, 621, 455, 601, 9, 621, 386, 444, 517, - /* 1420 */ 247, 621, 593, 593, 593, 621, 621, 244, 621, 243, - /* 1430 */ 430, 518, 292, 621, 329, 621, 145, 393, 280, 513, - /* 1440 */ 291, 131, 621, 514, 621, 621, 311, 621, 259, 346, - /* 1450 */ 249, 621, 621, 229, 314, 621, 228, 512, 227, 240, - /* 1460 */ 494, 488, 310, 164, 487, 486, 373, 480, 163, 262, - /* 1470 */ 369, 371, 162, 26, 212, 478, 477, 161, 141, 363, - /* 1480 */ 467, 122, 339, 187, 119, 348, 347, 117, 116, 115, - /* 1490 */ 114, 112, 182, 457, 320, 22, 433, 432, 448, 19, - /* 1500 */ 609, 431, 428, 62, 193, 596, 573, 298, 555, 552, - /* 1510 */ 571, 404, 290, 380, 498, 510, 495, 306, 281, 499, - /* 1520 */ 250, 5, 497, 460, 345, 447, 569, 550, 238, 299, - /* 1530 */ 527, 525, 508, 961, 502, 501, 961, 401, 961, 211, - /* 1540 */ 490, 356, 256, 961, 483, 961, 961, 961, 961, 961, - /* 1550 */ 961, 961, 961, 961, 961, 961, 370, + /* 0 */ 309, 955, 184, 417, 2, 171, 624, 594, 56, 56, + /* 10 */ 56, 56, 49, 54, 54, 54, 54, 53, 53, 52, + /* 20 */ 52, 52, 51, 233, 620, 619, 298, 620, 619, 234, + /* 30 */ 587, 581, 56, 56, 56, 56, 19, 54, 54, 54, + /* 40 */ 54, 53, 53, 52, 52, 52, 51, 233, 605, 57, + /* 50 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56, + /* 60 */ 56, 56, 541, 54, 54, 54, 54, 53, 53, 52, + /* 70 */ 52, 52, 51, 233, 309, 594, 325, 196, 195, 194, + /* 80 */ 33, 54, 54, 54, 54, 53, 53, 52, 52, 52, + /* 90 */ 51, 233, 617, 616, 165, 617, 616, 380, 377, 376, + /* 100 */ 407, 532, 576, 576, 587, 581, 303, 422, 375, 59, + /* 110 */ 53, 53, 52, 52, 52, 51, 233, 50, 47, 146, + /* 120 */ 574, 545, 65, 57, 58, 48, 579, 578, 580, 580, + /* 130 */ 55, 55, 56, 56, 56, 56, 213, 54, 54, 54, + /* 140 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 223, + /* 150 */ 539, 420, 170, 176, 138, 280, 383, 275, 382, 168, + /* 160 */ 489, 551, 409, 668, 620, 619, 271, 438, 409, 438, + /* 170 */ 550, 604, 67, 482, 507, 618, 599, 412, 587, 581, + /* 180 */ 600, 483, 618, 412, 618, 598, 91, 439, 440, 439, + /* 190 */ 335, 598, 73, 669, 222, 266, 480, 57, 58, 48, + /* 200 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56, + /* 210 */ 670, 54, 54, 54, 54, 53, 53, 52, 52, 52, + /* 220 */ 51, 233, 309, 279, 232, 231, 1, 132, 200, 385, + /* 230 */ 620, 619, 617, 616, 278, 435, 289, 563, 175, 262, + /* 240 */ 409, 264, 437, 497, 436, 166, 441, 568, 336, 568, + /* 250 */ 201, 537, 587, 581, 599, 412, 165, 594, 600, 380, + /* 260 */ 377, 376, 597, 598, 92, 523, 618, 569, 569, 592, + /* 270 */ 375, 57, 58, 48, 579, 578, 580, 580, 55, 55, + /* 280 */ 56, 56, 56, 56, 597, 54, 54, 54, 54, 53, + /* 290 */ 53, 52, 52, 52, 51, 233, 309, 463, 617, 616, + /* 300 */ 590, 590, 590, 174, 272, 396, 409, 272, 409, 548, + /* 310 */ 397, 620, 619, 68, 326, 620, 619, 620, 619, 618, + /* 320 */ 546, 412, 618, 412, 471, 594, 587, 581, 472, 598, + /* 330 */ 92, 598, 92, 52, 52, 52, 51, 233, 513, 512, + /* 340 */ 206, 322, 363, 464, 221, 57, 58, 48, 579, 578, + /* 350 */ 580, 580, 55, 55, 56, 56, 56, 56, 529, 54, + /* 360 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233, + /* 370 */ 309, 396, 409, 396, 597, 372, 386, 530, 347, 617, + /* 380 */ 616, 575, 202, 617, 616, 617, 616, 412, 620, 619, + /* 390 */ 145, 255, 346, 254, 577, 598, 74, 351, 45, 489, + /* 400 */ 587, 581, 235, 189, 464, 544, 167, 296, 187, 469, + /* 410 */ 479, 67, 62, 39, 618, 546, 597, 345, 573, 57, + /* 420 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56, + /* 430 */ 56, 56, 6, 54, 54, 54, 54, 53, 53, 52, + /* 440 */ 52, 52, 51, 233, 309, 562, 558, 407, 528, 576, + /* 450 */ 576, 344, 255, 346, 254, 182, 617, 616, 503, 504, + /* 460 */ 314, 409, 557, 235, 166, 271, 409, 352, 564, 181, + /* 470 */ 407, 546, 576, 576, 587, 581, 412, 537, 556, 561, + /* 480 */ 517, 412, 618, 249, 598, 16, 7, 36, 467, 598, + /* 490 */ 92, 516, 618, 57, 58, 48, 579, 578, 580, 580, + /* 500 */ 55, 55, 56, 56, 56, 56, 541, 54, 54, 54, + /* 510 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 327, + /* 520 */ 572, 571, 525, 558, 560, 394, 871, 246, 409, 248, + /* 530 */ 171, 392, 594, 219, 407, 409, 576, 576, 502, 557, + /* 540 */ 364, 145, 510, 412, 407, 229, 576, 576, 587, 581, + /* 550 */ 412, 598, 92, 381, 269, 556, 166, 400, 598, 69, + /* 560 */ 501, 419, 945, 199, 945, 198, 546, 57, 58, 48, + /* 570 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56, + /* 580 */ 568, 54, 54, 54, 54, 53, 53, 52, 52, 52, + /* 590 */ 51, 233, 309, 317, 419, 944, 508, 944, 308, 597, + /* 600 */ 594, 565, 490, 212, 173, 247, 423, 615, 614, 613, + /* 610 */ 323, 197, 143, 405, 572, 571, 489, 66, 50, 47, + /* 620 */ 146, 594, 587, 581, 232, 231, 559, 427, 67, 555, + /* 630 */ 15, 618, 186, 543, 303, 421, 35, 206, 432, 423, + /* 640 */ 552, 57, 58, 48, 579, 578, 580, 580, 55, 55, + /* 650 */ 56, 56, 56, 56, 205, 54, 54, 54, 54, 53, + /* 660 */ 53, 52, 52, 52, 51, 233, 309, 569, 569, 260, + /* 670 */ 268, 597, 12, 373, 568, 166, 409, 313, 409, 420, + /* 680 */ 409, 473, 473, 365, 618, 50, 47, 146, 597, 594, + /* 690 */ 468, 412, 166, 412, 351, 412, 587, 581, 32, 598, + /* 700 */ 94, 598, 97, 598, 95, 627, 625, 329, 142, 50, + /* 710 */ 47, 146, 333, 349, 358, 57, 58, 48, 579, 578, + /* 720 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54, + /* 730 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233, + /* 740 */ 309, 409, 388, 412, 409, 22, 565, 404, 212, 362, + /* 750 */ 389, 598, 104, 359, 409, 156, 412, 409, 603, 412, + /* 760 */ 537, 331, 569, 569, 598, 103, 493, 598, 105, 412, + /* 770 */ 587, 581, 412, 260, 549, 618, 11, 598, 106, 521, + /* 780 */ 598, 133, 169, 457, 456, 170, 35, 601, 618, 57, + /* 790 */ 58, 48, 579, 578, 580, 580, 55, 55, 56, 56, + /* 800 */ 56, 56, 409, 54, 54, 54, 54, 53, 53, 52, + /* 810 */ 52, 52, 51, 233, 309, 409, 259, 412, 409, 50, + /* 820 */ 47, 146, 357, 318, 355, 598, 134, 527, 352, 337, + /* 830 */ 412, 409, 356, 412, 357, 409, 357, 618, 598, 98, + /* 840 */ 129, 598, 102, 618, 587, 581, 412, 21, 235, 618, + /* 850 */ 412, 618, 211, 143, 598, 101, 30, 167, 598, 93, + /* 860 */ 350, 535, 203, 57, 58, 48, 579, 578, 580, 580, + /* 870 */ 55, 55, 56, 56, 56, 56, 409, 54, 54, 54, + /* 880 */ 54, 53, 53, 52, 52, 52, 51, 233, 309, 409, + /* 890 */ 526, 412, 409, 425, 215, 305, 597, 551, 141, 598, + /* 900 */ 100, 40, 409, 38, 412, 409, 550, 412, 409, 228, + /* 910 */ 220, 314, 598, 77, 500, 598, 96, 412, 587, 581, + /* 920 */ 412, 338, 253, 412, 218, 598, 137, 379, 598, 136, + /* 930 */ 28, 598, 135, 270, 715, 210, 481, 57, 58, 48, + /* 940 */ 579, 578, 580, 580, 55, 55, 56, 56, 56, 56, + /* 950 */ 409, 54, 54, 54, 54, 53, 53, 52, 52, 52, + /* 960 */ 51, 233, 309, 409, 272, 412, 409, 315, 147, 597, + /* 970 */ 272, 626, 2, 598, 76, 209, 409, 127, 412, 618, + /* 980 */ 126, 412, 409, 621, 235, 618, 598, 90, 374, 598, + /* 990 */ 89, 412, 587, 581, 27, 260, 350, 412, 618, 598, + /* 1000 */ 75, 321, 541, 541, 125, 598, 88, 320, 278, 597, + /* 1010 */ 618, 57, 46, 48, 579, 578, 580, 580, 55, 55, + /* 1020 */ 56, 56, 56, 56, 409, 54, 54, 54, 54, 53, + /* 1030 */ 53, 52, 52, 52, 51, 233, 309, 409, 450, 412, + /* 1040 */ 164, 284, 282, 272, 609, 424, 304, 598, 87, 370, + /* 1050 */ 409, 477, 412, 409, 608, 409, 607, 602, 618, 618, + /* 1060 */ 598, 99, 586, 585, 122, 412, 587, 581, 412, 618, + /* 1070 */ 412, 618, 618, 598, 86, 366, 598, 17, 598, 85, + /* 1080 */ 319, 185, 519, 518, 583, 582, 58, 48, 579, 578, + /* 1090 */ 580, 580, 55, 55, 56, 56, 56, 56, 409, 54, + /* 1100 */ 54, 54, 54, 53, 53, 52, 52, 52, 51, 233, + /* 1110 */ 309, 584, 409, 412, 409, 260, 260, 260, 408, 591, + /* 1120 */ 474, 598, 84, 170, 409, 466, 518, 412, 121, 412, + /* 1130 */ 618, 618, 618, 618, 618, 598, 83, 598, 72, 412, + /* 1140 */ 587, 581, 51, 233, 625, 329, 470, 598, 71, 257, + /* 1150 */ 159, 120, 14, 462, 157, 158, 117, 260, 448, 447, + /* 1160 */ 446, 48, 579, 578, 580, 580, 55, 55, 56, 56, + /* 1170 */ 56, 56, 618, 54, 54, 54, 54, 53, 53, 52, + /* 1180 */ 52, 52, 51, 233, 44, 403, 260, 3, 409, 459, + /* 1190 */ 260, 413, 619, 118, 398, 10, 25, 24, 554, 348, + /* 1200 */ 217, 618, 406, 412, 409, 618, 4, 44, 403, 618, + /* 1210 */ 3, 598, 82, 618, 413, 619, 455, 542, 115, 412, + /* 1220 */ 538, 401, 536, 274, 506, 406, 251, 598, 81, 216, + /* 1230 */ 273, 563, 618, 243, 453, 618, 154, 618, 618, 618, + /* 1240 */ 449, 416, 623, 110, 401, 618, 409, 236, 64, 123, + /* 1250 */ 487, 41, 42, 531, 563, 204, 409, 267, 43, 411, + /* 1260 */ 410, 412, 265, 592, 108, 618, 107, 434, 332, 598, + /* 1270 */ 80, 412, 618, 263, 41, 42, 443, 618, 409, 598, + /* 1280 */ 70, 43, 411, 410, 433, 261, 592, 149, 618, 597, + /* 1290 */ 256, 237, 188, 412, 590, 590, 590, 589, 588, 13, + /* 1300 */ 618, 598, 18, 328, 235, 618, 44, 403, 360, 3, + /* 1310 */ 418, 461, 339, 413, 619, 227, 124, 590, 590, 590, + /* 1320 */ 589, 588, 13, 618, 406, 409, 618, 409, 139, 34, + /* 1330 */ 403, 387, 3, 148, 622, 312, 413, 619, 311, 330, + /* 1340 */ 412, 460, 412, 401, 180, 353, 412, 406, 598, 79, + /* 1350 */ 598, 78, 250, 563, 598, 9, 618, 612, 611, 610, + /* 1360 */ 618, 8, 452, 442, 242, 415, 401, 618, 239, 235, + /* 1370 */ 179, 238, 428, 41, 42, 288, 563, 618, 618, 618, + /* 1380 */ 43, 411, 410, 618, 144, 592, 618, 618, 177, 61, + /* 1390 */ 618, 596, 391, 620, 619, 287, 41, 42, 414, 618, + /* 1400 */ 293, 30, 393, 43, 411, 410, 292, 618, 592, 31, + /* 1410 */ 618, 395, 291, 60, 230, 37, 590, 590, 590, 589, + /* 1420 */ 588, 13, 214, 553, 183, 290, 172, 301, 300, 299, + /* 1430 */ 178, 297, 595, 563, 451, 29, 285, 390, 540, 590, + /* 1440 */ 590, 590, 589, 588, 13, 283, 520, 534, 150, 533, + /* 1450 */ 241, 281, 384, 192, 191, 324, 515, 514, 276, 240, + /* 1460 */ 510, 523, 307, 511, 128, 592, 509, 225, 226, 486, + /* 1470 */ 485, 224, 152, 491, 464, 306, 484, 163, 153, 371, + /* 1480 */ 478, 151, 162, 258, 369, 161, 367, 208, 475, 476, + /* 1490 */ 26, 160, 465, 140, 361, 131, 590, 590, 590, 116, + /* 1500 */ 119, 454, 343, 155, 114, 342, 113, 112, 445, 111, + /* 1510 */ 130, 109, 431, 316, 426, 430, 23, 429, 20, 606, + /* 1520 */ 190, 507, 255, 341, 244, 63, 294, 593, 310, 570, + /* 1530 */ 277, 402, 354, 235, 567, 496, 495, 492, 494, 302, + /* 1540 */ 458, 378, 286, 245, 566, 5, 252, 547, 193, 444, + /* 1550 */ 233, 340, 207, 524, 368, 505, 334, 522, 499, 399, + /* 1560 */ 295, 498, 956, 488, }; static const YYCODETYPE yy_lookahead[] = { /* 0 */ 19, 142, 143, 144, 145, 24, 1, 26, 77, 78, /* 10 */ 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - /* 20 */ 89, 90, 91, 92, 15, 98, 26, 27, 7, 8, - /* 30 */ 49, 50, 77, 78, 79, 80, 109, 82, 83, 84, - /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 22, 68, + /* 20 */ 89, 90, 91, 92, 26, 27, 15, 26, 27, 197, + /* 30 */ 49, 50, 77, 78, 79, 80, 204, 82, 83, 84, + /* 40 */ 85, 86, 87, 88, 89, 90, 91, 92, 23, 68, /* 50 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 60 */ 79, 80, 23, 82, 83, 84, 85, 86, 87, 88, - /* 70 */ 89, 90, 91, 92, 19, 94, 112, 19, 114, 115, + /* 60 */ 79, 80, 166, 82, 83, 84, 85, 86, 87, 88, + /* 70 */ 89, 90, 91, 92, 19, 94, 19, 105, 106, 107, /* 80 */ 25, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 90 */ 91, 92, 19, 22, 94, 95, 96, 150, 150, 99, - /* 100 */ 100, 101, 76, 150, 49, 50, 105, 106, 107, 54, - /* 110 */ 110, 158, 165, 165, 161, 162, 26, 27, 165, 113, - /* 120 */ 16, 174, 175, 68, 69, 70, 71, 72, 73, 74, - /* 130 */ 75, 76, 77, 78, 79, 80, 118, 82, 83, 84, - /* 140 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 23, - /* 150 */ 92, 97, 98, 24, 96, 97, 98, 99, 100, 101, - /* 160 */ 102, 25, 97, 216, 60, 92, 62, 109, 221, 25, - /* 170 */ 97, 98, 99, 100, 101, 102, 86, 87, 49, 50, - /* 180 */ 118, 116, 109, 25, 94, 95, 32, 97, 88, 89, - /* 190 */ 90, 91, 92, 128, 104, 41, 106, 68, 69, 70, + /* 90 */ 91, 92, 94, 95, 96, 94, 95, 99, 100, 101, + /* 100 */ 112, 205, 114, 115, 49, 50, 22, 23, 110, 54, + /* 110 */ 86, 87, 88, 89, 90, 91, 92, 221, 222, 223, + /* 120 */ 23, 120, 25, 68, 69, 70, 71, 72, 73, 74, + /* 130 */ 75, 76, 77, 78, 79, 80, 22, 82, 83, 84, + /* 140 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 92, + /* 150 */ 23, 67, 25, 96, 97, 98, 99, 100, 101, 102, + /* 160 */ 150, 32, 150, 118, 26, 27, 109, 150, 150, 150, + /* 170 */ 41, 161, 162, 180, 181, 165, 113, 165, 49, 50, + /* 180 */ 117, 188, 165, 165, 165, 173, 174, 170, 171, 170, + /* 190 */ 171, 173, 174, 118, 184, 16, 186, 68, 69, 70, /* 200 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 210 */ 11, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 220 */ 91, 92, 19, 19, 86, 87, 88, 89, 90, 91, - /* 230 */ 92, 27, 96, 150, 66, 99, 100, 101, 112, 150, - /* 240 */ 114, 115, 138, 150, 161, 162, 110, 103, 165, 222, - /* 250 */ 223, 224, 49, 50, 165, 22, 57, 24, 165, 170, - /* 260 */ 171, 118, 94, 170, 171, 23, 98, 25, 185, 186, - /* 270 */ 243, 68, 69, 70, 71, 72, 73, 74, 75, 76, - /* 280 */ 77, 78, 79, 80, 126, 82, 83, 84, 85, 86, - /* 290 */ 87, 88, 89, 90, 91, 92, 19, 129, 130, 131, - /* 300 */ 88, 23, 172, 173, 105, 106, 107, 150, 22, 26, - /* 310 */ 27, 181, 26, 27, 22, 116, 26, 27, 26, 230, - /* 320 */ 231, 197, 165, 230, 231, 113, 49, 50, 204, 117, - /* 330 */ 96, 174, 175, 99, 100, 101, 22, 26, 27, 136, - /* 340 */ 26, 27, 118, 16, 110, 68, 69, 70, 71, 72, - /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 118, 82, + /* 210 */ 118, 82, 83, 84, 85, 86, 87, 88, 89, 90, + /* 220 */ 91, 92, 19, 98, 86, 87, 22, 24, 160, 88, + /* 230 */ 26, 27, 94, 95, 109, 97, 224, 66, 118, 60, + /* 240 */ 150, 62, 104, 23, 106, 25, 229, 230, 229, 230, + /* 250 */ 160, 150, 49, 50, 113, 165, 96, 26, 117, 99, + /* 260 */ 100, 101, 194, 173, 174, 94, 165, 129, 130, 98, + /* 270 */ 110, 68, 69, 70, 71, 72, 73, 74, 75, 76, + /* 280 */ 77, 78, 79, 80, 194, 82, 83, 84, 85, 86, + /* 290 */ 87, 88, 89, 90, 91, 92, 19, 11, 94, 95, + /* 300 */ 129, 130, 131, 118, 150, 215, 150, 150, 150, 25, + /* 310 */ 220, 26, 27, 22, 213, 26, 27, 26, 27, 165, + /* 320 */ 25, 165, 165, 165, 30, 94, 49, 50, 34, 173, + /* 330 */ 174, 173, 174, 88, 89, 90, 91, 92, 7, 8, + /* 340 */ 160, 187, 48, 57, 187, 68, 69, 70, 71, 72, + /* 350 */ 73, 74, 75, 76, 77, 78, 79, 80, 23, 82, /* 360 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 370 */ 19, 214, 215, 150, 23, 23, 155, 94, 95, 22, - /* 380 */ 94, 95, 116, 160, 94, 95, 94, 60, 165, 62, - /* 390 */ 112, 26, 114, 115, 128, 23, 36, 174, 175, 88, - /* 400 */ 49, 50, 57, 120, 22, 94, 95, 23, 94, 95, - /* 410 */ 120, 51, 25, 136, 169, 170, 171, 194, 58, 68, + /* 370 */ 19, 215, 150, 215, 194, 19, 220, 88, 220, 94, + /* 380 */ 95, 23, 160, 94, 95, 94, 95, 165, 26, 27, + /* 390 */ 95, 105, 106, 107, 113, 173, 174, 217, 22, 150, + /* 400 */ 49, 50, 116, 119, 57, 120, 50, 158, 22, 21, + /* 410 */ 161, 162, 232, 136, 165, 120, 194, 237, 23, 68, /* 420 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, - /* 430 */ 79, 80, 23, 82, 83, 84, 85, 86, 87, 88, - /* 440 */ 89, 90, 91, 92, 19, 150, 12, 12, 23, 228, - /* 450 */ 105, 106, 107, 23, 233, 25, 165, 19, 150, 94, - /* 460 */ 165, 116, 28, 28, 112, 174, 114, 115, 108, 174, - /* 470 */ 175, 26, 27, 165, 49, 50, 231, 11, 44, 44, - /* 480 */ 46, 46, 174, 175, 112, 160, 114, 115, 50, 22, - /* 490 */ 23, 57, 25, 68, 69, 70, 71, 72, 73, 74, - /* 500 */ 75, 76, 77, 78, 79, 80, 119, 82, 83, 84, - /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 194, - /* 520 */ 225, 23, 23, 215, 19, 95, 105, 106, 107, 150, - /* 530 */ 23, 150, 27, 23, 67, 25, 150, 206, 207, 94, - /* 540 */ 95, 166, 104, 218, 165, 22, 165, 109, 49, 50, - /* 550 */ 120, 165, 25, 174, 175, 174, 175, 23, 21, 234, - /* 560 */ 174, 175, 22, 23, 239, 25, 25, 68, 69, 70, + /* 430 */ 79, 80, 22, 82, 83, 84, 85, 86, 87, 88, + /* 440 */ 89, 90, 91, 92, 19, 23, 12, 112, 23, 114, + /* 450 */ 115, 63, 105, 106, 107, 23, 94, 95, 97, 98, + /* 460 */ 104, 150, 28, 116, 25, 109, 150, 150, 23, 23, + /* 470 */ 112, 25, 114, 115, 49, 50, 165, 150, 44, 11, + /* 480 */ 46, 165, 165, 16, 173, 174, 76, 136, 100, 173, + /* 490 */ 174, 57, 165, 68, 69, 70, 71, 72, 73, 74, + /* 500 */ 75, 76, 77, 78, 79, 80, 166, 82, 83, 84, + /* 510 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 169, + /* 520 */ 170, 171, 23, 12, 23, 214, 138, 60, 150, 62, + /* 530 */ 24, 215, 26, 216, 112, 150, 114, 115, 36, 28, + /* 540 */ 213, 95, 103, 165, 112, 205, 114, 115, 49, 50, + /* 550 */ 165, 173, 174, 51, 23, 44, 25, 46, 173, 174, + /* 560 */ 58, 22, 23, 22, 25, 160, 120, 68, 69, 70, /* 570 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, - /* 580 */ 205, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 590 */ 91, 92, 19, 22, 23, 216, 23, 222, 223, 224, - /* 600 */ 63, 220, 35, 150, 150, 163, 220, 67, 166, 167, - /* 610 */ 168, 150, 169, 170, 171, 161, 162, 25, 165, 165, - /* 620 */ 150, 113, 49, 50, 25, 117, 165, 174, 175, 35, - /* 630 */ 7, 8, 9, 160, 160, 165, 120, 100, 67, 247, - /* 640 */ 248, 68, 69, 70, 71, 72, 73, 74, 75, 76, - /* 650 */ 77, 78, 79, 80, 193, 82, 83, 84, 85, 86, - /* 660 */ 87, 88, 89, 90, 91, 92, 19, 194, 194, 150, - /* 670 */ 135, 24, 137, 35, 231, 138, 150, 129, 130, 206, - /* 680 */ 207, 30, 27, 213, 165, 34, 118, 95, 0, 1, - /* 690 */ 2, 165, 218, 174, 175, 50, 49, 50, 22, 48, - /* 700 */ 174, 175, 22, 23, 23, 244, 222, 223, 224, 166, - /* 710 */ 167, 168, 120, 239, 23, 68, 69, 70, 71, 72, + /* 580 */ 230, 82, 83, 84, 85, 86, 87, 88, 89, 90, + /* 590 */ 91, 92, 19, 215, 22, 23, 23, 25, 163, 194, + /* 600 */ 94, 166, 167, 168, 25, 138, 67, 7, 8, 9, + /* 610 */ 108, 206, 207, 169, 170, 171, 150, 22, 221, 222, + /* 620 */ 223, 26, 49, 50, 86, 87, 23, 161, 162, 23, + /* 630 */ 22, 165, 24, 120, 22, 23, 25, 160, 241, 67, + /* 640 */ 176, 68, 69, 70, 71, 72, 73, 74, 75, 76, + /* 650 */ 77, 78, 79, 80, 160, 82, 83, 84, 85, 86, + /* 660 */ 87, 88, 89, 90, 91, 92, 19, 129, 130, 150, + /* 670 */ 23, 194, 35, 23, 230, 25, 150, 155, 150, 67, + /* 680 */ 150, 105, 106, 107, 165, 221, 222, 223, 194, 94, + /* 690 */ 23, 165, 25, 165, 217, 165, 49, 50, 25, 173, + /* 700 */ 174, 173, 174, 173, 174, 0, 1, 2, 118, 221, + /* 710 */ 222, 223, 193, 219, 237, 68, 69, 70, 71, 72, /* 720 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82, /* 730 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 740 */ 19, 150, 173, 165, 181, 182, 24, 67, 26, 104, - /* 750 */ 181, 188, 174, 175, 150, 39, 165, 150, 52, 150, - /* 760 */ 150, 150, 150, 144, 145, 174, 175, 249, 250, 165, - /* 770 */ 49, 50, 165, 52, 165, 165, 165, 165, 174, 175, - /* 780 */ 29, 174, 175, 174, 175, 174, 175, 160, 22, 68, + /* 740 */ 19, 150, 19, 165, 150, 24, 166, 167, 168, 227, + /* 750 */ 27, 173, 174, 231, 150, 25, 165, 150, 172, 165, + /* 760 */ 150, 242, 129, 130, 173, 174, 180, 173, 174, 165, + /* 770 */ 49, 50, 165, 150, 176, 165, 35, 173, 174, 165, + /* 780 */ 173, 174, 35, 23, 23, 25, 25, 173, 165, 68, /* 790 */ 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, /* 800 */ 79, 80, 150, 82, 83, 84, 85, 86, 87, 88, - /* 810 */ 89, 90, 91, 92, 19, 150, 94, 165, 150, 150, - /* 820 */ 160, 194, 150, 213, 160, 52, 174, 175, 23, 23, - /* 830 */ 165, 25, 22, 165, 165, 150, 150, 165, 52, 174, - /* 840 */ 175, 22, 174, 175, 49, 50, 174, 175, 190, 191, - /* 850 */ 165, 165, 240, 23, 194, 25, 187, 109, 194, 174, - /* 860 */ 175, 190, 191, 68, 69, 70, 71, 72, 73, 74, + /* 810 */ 89, 90, 91, 92, 19, 150, 193, 165, 150, 221, + /* 820 */ 222, 223, 150, 213, 19, 173, 174, 23, 150, 97, + /* 830 */ 165, 150, 27, 165, 150, 150, 150, 165, 173, 174, + /* 840 */ 22, 173, 174, 165, 49, 50, 165, 52, 116, 165, + /* 850 */ 165, 165, 206, 207, 173, 174, 126, 50, 173, 174, + /* 860 */ 128, 27, 160, 68, 69, 70, 71, 72, 73, 74, /* 870 */ 75, 76, 77, 78, 79, 80, 150, 82, 83, 84, /* 880 */ 85, 86, 87, 88, 89, 90, 91, 92, 19, 150, - /* 890 */ 22, 165, 150, 23, 150, 25, 150, 166, 91, 92, - /* 900 */ 174, 175, 22, 217, 165, 150, 102, 165, 150, 165, - /* 910 */ 150, 165, 150, 174, 175, 19, 174, 175, 49, 50, - /* 920 */ 165, 86, 87, 165, 23, 165, 25, 165, 24, 174, - /* 930 */ 175, 187, 174, 175, 174, 175, 205, 68, 69, 70, + /* 890 */ 23, 165, 150, 23, 216, 25, 194, 32, 39, 173, + /* 900 */ 174, 135, 150, 137, 165, 150, 41, 165, 150, 52, + /* 910 */ 238, 104, 173, 174, 29, 173, 174, 165, 49, 50, + /* 920 */ 165, 219, 238, 165, 238, 173, 174, 52, 173, 174, + /* 930 */ 22, 173, 174, 23, 23, 160, 25, 68, 69, 70, /* 940 */ 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, /* 950 */ 150, 82, 83, 84, 85, 86, 87, 88, 89, 90, - /* 960 */ 91, 92, 19, 150, 150, 165, 150, 150, 166, 23, - /* 970 */ 150, 25, 160, 20, 174, 175, 1, 2, 165, 165, - /* 980 */ 104, 165, 165, 43, 150, 165, 240, 150, 49, 50, - /* 990 */ 174, 175, 49, 50, 23, 23, 25, 25, 53, 165, - /* 1000 */ 187, 187, 165, 23, 187, 25, 194, 205, 174, 175, - /* 1010 */ 71, 72, 69, 70, 71, 72, 73, 74, 75, 76, + /* 960 */ 91, 92, 19, 150, 150, 165, 150, 245, 246, 194, + /* 970 */ 150, 144, 145, 173, 174, 160, 150, 22, 165, 165, + /* 980 */ 22, 165, 150, 150, 116, 165, 173, 174, 52, 173, + /* 990 */ 174, 165, 49, 50, 22, 150, 128, 165, 165, 173, + /* 1000 */ 174, 187, 166, 166, 22, 173, 174, 187, 109, 194, + /* 1010 */ 165, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* 1020 */ 77, 78, 79, 80, 150, 82, 83, 84, 85, 86, - /* 1030 */ 87, 88, 89, 90, 91, 92, 19, 98, 150, 165, - /* 1040 */ 150, 160, 150, 59, 25, 53, 104, 22, 174, 175, - /* 1050 */ 213, 138, 5, 165, 1, 165, 150, 165, 150, 150, - /* 1060 */ 240, 150, 174, 175, 174, 175, 49, 50, 118, 150, - /* 1070 */ 35, 165, 27, 165, 165, 194, 165, 108, 127, 76, - /* 1080 */ 174, 175, 174, 175, 165, 174, 175, 70, 71, 72, - /* 1090 */ 73, 74, 75, 76, 77, 78, 79, 80, 166, 82, + /* 1030 */ 87, 88, 89, 90, 91, 92, 19, 150, 193, 165, + /* 1040 */ 102, 205, 205, 150, 150, 247, 248, 173, 174, 19, + /* 1050 */ 150, 20, 165, 150, 150, 150, 150, 150, 165, 165, + /* 1060 */ 173, 174, 49, 50, 104, 165, 49, 50, 165, 165, + /* 1070 */ 165, 165, 165, 173, 174, 43, 173, 174, 173, 174, + /* 1080 */ 187, 24, 190, 191, 71, 72, 69, 70, 71, 72, + /* 1090 */ 73, 74, 75, 76, 77, 78, 79, 80, 150, 82, /* 1100 */ 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, - /* 1110 */ 19, 20, 193, 22, 150, 150, 150, 26, 27, 76, - /* 1120 */ 150, 22, 1, 150, 119, 121, 217, 20, 37, 165, - /* 1130 */ 165, 165, 16, 19, 20, 165, 22, 205, 165, 119, - /* 1140 */ 26, 27, 108, 128, 150, 150, 150, 56, 150, 22, - /* 1150 */ 150, 37, 150, 127, 160, 23, 150, 66, 193, 165, - /* 1160 */ 165, 165, 16, 165, 23, 165, 150, 165, 174, 175, - /* 1170 */ 56, 165, 150, 65, 174, 175, 15, 86, 87, 88, - /* 1180 */ 66, 165, 140, 150, 93, 94, 95, 165, 194, 98, - /* 1190 */ 174, 175, 22, 3, 164, 193, 174, 175, 165, 150, - /* 1200 */ 86, 87, 4, 180, 150, 248, 251, 93, 94, 95, - /* 1210 */ 216, 180, 98, 251, 165, 221, 150, 149, 6, 165, - /* 1220 */ 129, 130, 131, 132, 133, 134, 193, 150, 174, 175, - /* 1230 */ 116, 165, 19, 20, 150, 22, 149, 151, 150, 26, - /* 1240 */ 27, 149, 165, 129, 130, 131, 132, 133, 134, 165, - /* 1250 */ 37, 174, 175, 165, 149, 19, 20, 13, 22, 150, - /* 1260 */ 150, 150, 26, 27, 146, 147, 151, 150, 25, 56, - /* 1270 */ 152, 159, 154, 37, 165, 165, 165, 193, 160, 66, - /* 1280 */ 116, 193, 165, 174, 175, 174, 175, 194, 199, 150, - /* 1290 */ 200, 126, 56, 124, 123, 150, 201, 122, 150, 86, - /* 1300 */ 87, 150, 66, 193, 165, 202, 93, 94, 95, 150, - /* 1310 */ 165, 98, 194, 165, 125, 22, 165, 150, 150, 26, - /* 1320 */ 27, 135, 86, 87, 165, 174, 175, 203, 226, 93, - /* 1330 */ 94, 95, 165, 165, 98, 150, 218, 150, 193, 157, - /* 1340 */ 118, 157, 129, 130, 131, 132, 133, 134, 5, 104, - /* 1350 */ 165, 211, 165, 10, 11, 12, 13, 14, 150, 66, - /* 1360 */ 17, 174, 175, 210, 246, 129, 130, 131, 132, 133, - /* 1370 */ 134, 150, 210, 165, 31, 121, 33, 150, 150, 86, - /* 1380 */ 87, 176, 174, 175, 150, 42, 165, 94, 211, 210, - /* 1390 */ 150, 98, 165, 165, 211, 174, 175, 150, 55, 165, - /* 1400 */ 57, 150, 174, 175, 61, 165, 150, 64, 174, 175, - /* 1410 */ 150, 150, 165, 150, 174, 175, 165, 104, 150, 184, - /* 1420 */ 150, 165, 129, 130, 131, 165, 165, 150, 165, 150, - /* 1430 */ 150, 176, 150, 165, 47, 165, 150, 150, 176, 103, - /* 1440 */ 150, 22, 165, 178, 165, 165, 179, 165, 105, 106, - /* 1450 */ 107, 165, 165, 229, 111, 165, 92, 176, 229, 116, - /* 1460 */ 184, 176, 179, 156, 176, 176, 18, 157, 156, 237, - /* 1470 */ 45, 157, 156, 135, 157, 157, 238, 156, 68, 157, - /* 1480 */ 189, 189, 139, 219, 22, 157, 18, 192, 192, 192, - /* 1490 */ 192, 189, 219, 199, 157, 242, 40, 157, 199, 242, - /* 1500 */ 153, 157, 38, 245, 196, 166, 232, 198, 177, 177, - /* 1510 */ 232, 227, 209, 178, 166, 182, 166, 148, 177, 177, - /* 1520 */ 209, 196, 177, 199, 209, 199, 166, 208, 92, 195, - /* 1530 */ 174, 174, 183, 252, 183, 183, 252, 191, 252, 235, - /* 1540 */ 186, 241, 241, 252, 186, 252, 252, 252, 252, 252, - /* 1550 */ 252, 252, 252, 252, 252, 252, 236, + /* 1110 */ 19, 98, 150, 165, 150, 150, 150, 150, 150, 150, + /* 1120 */ 59, 173, 174, 25, 150, 190, 191, 165, 53, 165, + /* 1130 */ 165, 165, 165, 165, 165, 173, 174, 173, 174, 165, + /* 1140 */ 49, 50, 91, 92, 1, 2, 53, 173, 174, 138, + /* 1150 */ 104, 22, 5, 1, 35, 118, 127, 150, 193, 193, + /* 1160 */ 193, 70, 71, 72, 73, 74, 75, 76, 77, 78, + /* 1170 */ 79, 80, 165, 82, 83, 84, 85, 86, 87, 88, + /* 1180 */ 89, 90, 91, 92, 19, 20, 150, 22, 150, 27, + /* 1190 */ 150, 26, 27, 108, 150, 22, 76, 76, 150, 25, + /* 1200 */ 193, 165, 37, 165, 150, 165, 22, 19, 20, 165, + /* 1210 */ 22, 173, 174, 165, 26, 27, 23, 150, 119, 165, + /* 1220 */ 150, 56, 150, 150, 150, 37, 16, 173, 174, 193, + /* 1230 */ 150, 66, 165, 193, 1, 165, 121, 165, 165, 165, + /* 1240 */ 20, 146, 147, 119, 56, 165, 150, 152, 16, 154, + /* 1250 */ 150, 86, 87, 88, 66, 160, 150, 150, 93, 94, + /* 1260 */ 95, 165, 150, 98, 108, 165, 127, 23, 65, 173, + /* 1270 */ 174, 165, 165, 150, 86, 87, 128, 165, 150, 173, + /* 1280 */ 174, 93, 94, 95, 23, 150, 98, 15, 165, 194, + /* 1290 */ 150, 140, 22, 165, 129, 130, 131, 132, 133, 134, + /* 1300 */ 165, 173, 174, 3, 116, 165, 19, 20, 150, 22, + /* 1310 */ 4, 150, 217, 26, 27, 179, 179, 129, 130, 131, + /* 1320 */ 132, 133, 134, 165, 37, 150, 165, 150, 164, 19, + /* 1330 */ 20, 150, 22, 246, 149, 249, 26, 27, 249, 244, + /* 1340 */ 165, 150, 165, 56, 6, 150, 165, 37, 173, 174, + /* 1350 */ 173, 174, 150, 66, 173, 174, 165, 149, 149, 13, + /* 1360 */ 165, 25, 150, 150, 150, 149, 56, 165, 150, 116, + /* 1370 */ 151, 150, 150, 86, 87, 150, 66, 165, 165, 165, + /* 1380 */ 93, 94, 95, 165, 150, 98, 165, 165, 151, 22, + /* 1390 */ 165, 194, 150, 26, 27, 150, 86, 87, 159, 165, + /* 1400 */ 199, 126, 123, 93, 94, 95, 200, 165, 98, 124, + /* 1410 */ 165, 122, 201, 125, 225, 135, 129, 130, 131, 132, + /* 1420 */ 133, 134, 5, 157, 157, 202, 118, 10, 11, 12, + /* 1430 */ 13, 14, 203, 66, 17, 104, 210, 121, 211, 129, + /* 1440 */ 130, 131, 132, 133, 134, 210, 175, 211, 31, 211, + /* 1450 */ 33, 210, 104, 86, 87, 47, 175, 183, 175, 42, + /* 1460 */ 103, 94, 178, 177, 22, 98, 175, 92, 228, 175, + /* 1470 */ 175, 228, 55, 183, 57, 178, 175, 156, 61, 18, + /* 1480 */ 157, 64, 156, 235, 157, 156, 45, 157, 236, 157, + /* 1490 */ 135, 156, 189, 68, 157, 218, 129, 130, 131, 22, + /* 1500 */ 189, 199, 157, 156, 192, 18, 192, 192, 199, 192, + /* 1510 */ 218, 189, 40, 157, 38, 157, 240, 157, 240, 153, + /* 1520 */ 196, 181, 105, 106, 107, 243, 198, 166, 111, 230, + /* 1530 */ 176, 226, 239, 116, 230, 176, 166, 166, 176, 148, + /* 1540 */ 199, 177, 209, 209, 166, 196, 239, 208, 185, 199, + /* 1550 */ 92, 209, 233, 173, 234, 182, 139, 173, 182, 191, + /* 1560 */ 195, 182, 250, 186, }; -#define YY_SHIFT_USE_DFLT (-74) -#define YY_SHIFT_COUNT (418) -#define YY_SHIFT_MIN (-73) -#define YY_SHIFT_MAX (1468) +#define YY_SHIFT_USE_DFLT (-70) +#define YY_SHIFT_COUNT (416) +#define YY_SHIFT_MIN (-69) +#define YY_SHIFT_MAX (1487) static const short yy_shift_ofst[] = { - /* 0 */ 975, 1114, 1343, 1114, 1213, 1213, 90, 90, 0, -19, - /* 10 */ 1213, 1213, 1213, 1213, 1213, 345, 445, 721, 1091, 1213, - /* 20 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, - /* 30 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, - /* 40 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1236, 1213, 1213, - /* 50 */ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213, - /* 60 */ 1213, 199, 445, 445, 835, 835, 365, 1164, 55, 647, - /* 70 */ 573, 499, 425, 351, 277, 203, 129, 795, 795, 795, - /* 80 */ 795, 795, 795, 795, 795, 795, 795, 795, 795, 795, - /* 90 */ 795, 795, 795, 795, 795, 869, 795, 943, 1017, 1017, - /* 100 */ -69, -45, -45, -45, -45, -45, -1, 58, 138, 100, - /* 110 */ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, - /* 120 */ 445, 445, 445, 445, 445, 445, 537, 438, 445, 445, - /* 130 */ 445, 445, 445, 365, 807, 1436, -74, -74, -74, 1293, - /* 140 */ 73, 434, 434, 311, 314, 290, 283, 286, 540, 467, - /* 150 */ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, - /* 160 */ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, - /* 170 */ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445, - /* 180 */ 445, 445, 65, 722, 722, 722, 688, 266, 1164, 1164, - /* 190 */ 1164, -74, -74, -74, 136, 168, 168, 234, 360, 360, - /* 200 */ 360, 430, 372, 435, 352, 278, 126, -36, -36, -36, - /* 210 */ -36, 421, 651, -36, -36, 592, 292, 212, 623, 158, - /* 220 */ 204, 204, 505, 158, 505, 144, 365, 154, 365, 154, - /* 230 */ 645, 154, 204, 154, 154, 535, 548, 548, 365, 387, - /* 240 */ 508, 233, 1464, 1222, 1222, 1456, 1456, 1222, 1462, 1410, - /* 250 */ 1165, 1468, 1468, 1468, 1468, 1222, 1165, 1462, 1410, 1410, - /* 260 */ 1222, 1448, 1338, 1425, 1222, 1222, 1448, 1222, 1448, 1222, - /* 270 */ 1448, 1419, 1313, 1313, 1313, 1387, 1364, 1364, 1419, 1313, - /* 280 */ 1336, 1313, 1387, 1313, 1313, 1254, 1245, 1254, 1245, 1254, - /* 290 */ 1245, 1222, 1222, 1186, 1189, 1175, 1169, 1171, 1165, 1164, - /* 300 */ 1243, 1244, 1244, 1212, 1212, 1212, 1212, -74, -74, -74, - /* 310 */ -74, -74, -74, 939, 104, 680, 571, 327, 1, 980, - /* 320 */ 26, 972, 971, 946, 901, 870, 830, 806, 54, 21, - /* 330 */ -73, 510, 242, 1198, 1190, 1170, 1042, 1161, 1108, 1146, - /* 340 */ 1141, 1132, 1015, 1127, 1026, 1034, 1020, 1107, 1004, 1116, - /* 350 */ 1121, 1005, 1099, 951, 1043, 1003, 969, 1045, 1035, 950, - /* 360 */ 1053, 1047, 1025, 942, 913, 992, 1019, 945, 984, 940, - /* 370 */ 876, 904, 953, 896, 748, 804, 880, 786, 868, 819, - /* 380 */ 805, 810, 773, 751, 766, 706, 716, 691, 681, 568, - /* 390 */ 655, 638, 676, 516, 541, 594, 599, 567, 541, 534, - /* 400 */ 507, 527, 498, 523, 466, 382, 409, 384, 357, 6, - /* 410 */ 240, 224, 143, 62, 18, 71, 39, 9, 5, + /* 0 */ 1143, 1188, 1417, 1188, 1287, 1287, 138, 138, -2, -19, + /* 10 */ 1287, 1287, 1287, 1287, 347, 362, 129, 129, 795, 1165, + /* 20 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, + /* 30 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, + /* 40 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1310, 1287, + /* 50 */ 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, 1287, + /* 60 */ 1287, 1287, 286, 362, 362, 538, 538, 231, 1253, 55, + /* 70 */ 721, 647, 573, 499, 425, 351, 277, 203, 869, 869, + /* 80 */ 869, 869, 869, 869, 869, 869, 869, 869, 869, 869, + /* 90 */ 869, 869, 869, 943, 869, 1017, 1091, 1091, -69, -45, + /* 100 */ -45, -45, -45, -45, -1, 24, 245, 362, 362, 362, + /* 110 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, + /* 120 */ 362, 362, 362, 388, 356, 362, 362, 362, 362, 362, + /* 130 */ 732, 868, 231, 1051, 1458, -70, -70, -70, 1367, 57, + /* 140 */ 434, 434, 289, 291, 285, 1, 204, 572, 539, 362, + /* 150 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, + /* 160 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, + /* 170 */ 362, 362, 362, 362, 362, 362, 362, 362, 362, 362, + /* 180 */ 362, 506, 506, 506, 705, 1253, 1253, 1253, -70, -70, + /* 190 */ -70, 171, 171, 160, 502, 502, 502, 446, 432, 511, + /* 200 */ 422, 358, 335, -12, -12, -12, -12, 576, 294, -12, + /* 210 */ -12, 295, 595, 141, 600, 730, 723, 723, 805, 730, + /* 220 */ 805, 439, 911, 231, 865, 231, 865, 807, 865, 723, + /* 230 */ 766, 633, 633, 231, 284, 63, 608, 1476, 1308, 1308, + /* 240 */ 1472, 1472, 1308, 1477, 1425, 1275, 1487, 1487, 1487, 1487, + /* 250 */ 1308, 1461, 1275, 1477, 1425, 1425, 1308, 1461, 1355, 1441, + /* 260 */ 1308, 1308, 1461, 1308, 1461, 1308, 1461, 1442, 1348, 1348, + /* 270 */ 1348, 1408, 1375, 1375, 1442, 1348, 1357, 1348, 1408, 1348, + /* 280 */ 1348, 1316, 1331, 1316, 1331, 1316, 1331, 1308, 1308, 1280, + /* 290 */ 1288, 1289, 1285, 1279, 1275, 1253, 1336, 1346, 1346, 1338, + /* 300 */ 1338, 1338, 1338, -70, -70, -70, -70, -70, -70, 1013, + /* 310 */ 467, 612, 84, 179, -28, 870, 410, 761, 760, 667, + /* 320 */ 650, 531, 220, 361, 331, 125, 127, 97, 1306, 1300, + /* 330 */ 1270, 1151, 1272, 1203, 1232, 1261, 1244, 1148, 1174, 1139, + /* 340 */ 1156, 1124, 1220, 1115, 1210, 1233, 1099, 1193, 1184, 1174, + /* 350 */ 1173, 1029, 1121, 1120, 1085, 1162, 1119, 1037, 1152, 1147, + /* 360 */ 1129, 1046, 1011, 1093, 1098, 1075, 1061, 1032, 960, 1057, + /* 370 */ 1031, 1030, 899, 938, 982, 936, 972, 958, 910, 955, + /* 380 */ 875, 885, 908, 857, 859, 867, 804, 590, 834, 747, + /* 390 */ 818, 513, 611, 741, 673, 637, 611, 606, 603, 579, + /* 400 */ 501, 541, 468, 386, 445, 395, 376, 281, 185, 120, + /* 410 */ 92, 75, 45, 114, 25, 11, 5, }; -#define YY_REDUCE_USE_DFLT (-142) -#define YY_REDUCE_COUNT (312) -#define YY_REDUCE_MIN (-141) -#define YY_REDUCE_MAX (1369) +#define YY_REDUCE_USE_DFLT (-169) +#define YY_REDUCE_COUNT (308) +#define YY_REDUCE_MIN (-168) +#define YY_REDUCE_MAX (1391) static const short yy_reduce_ofst[] = { - /* 0 */ -141, 994, 1118, 223, 157, -53, 93, 89, 83, 375, - /* 10 */ 386, 381, 379, 308, 295, 325, -47, 27, 1240, 1234, - /* 20 */ 1228, 1221, 1208, 1187, 1151, 1111, 1109, 1077, 1054, 1022, - /* 30 */ 1016, 1000, 911, 908, 906, 890, 888, 874, 834, 816, - /* 40 */ 800, 760, 758, 755, 742, 739, 726, 685, 672, 668, - /* 50 */ 665, 652, 611, 609, 607, 604, 591, 578, 526, 519, - /* 60 */ 453, 474, 454, 461, 443, 245, 442, 473, 484, 484, - /* 70 */ 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, - /* 80 */ 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, - /* 90 */ 484, 484, 484, 484, 484, 484, 484, 484, 484, 484, - /* 100 */ 484, 484, 484, 484, 484, 484, 484, 130, 484, 484, - /* 110 */ 1145, 909, 1110, 1088, 1084, 1033, 1002, 965, 820, 837, - /* 120 */ 746, 686, 612, 817, 610, 919, 221, 563, 814, 813, - /* 130 */ 744, 669, 470, 543, 484, 484, 484, 484, 484, 291, - /* 140 */ 569, 671, 658, 970, 1290, 1287, 1286, 1282, 518, 518, - /* 150 */ 1280, 1279, 1277, 1270, 1268, 1263, 1261, 1260, 1256, 1251, - /* 160 */ 1247, 1227, 1185, 1168, 1167, 1159, 1148, 1139, 1117, 1066, - /* 170 */ 1049, 1006, 998, 996, 995, 973, 970, 966, 964, 892, - /* 180 */ 762, -52, 881, 932, 802, 731, 619, 812, 664, 660, - /* 190 */ 627, 392, 331, 124, 1358, 1357, 1356, 1354, 1352, 1351, - /* 200 */ 1349, 1319, 1334, 1346, 1334, 1334, 1334, 1334, 1334, 1334, - /* 210 */ 1334, 1320, 1304, 1334, 1334, 1319, 1360, 1325, 1369, 1326, - /* 220 */ 1315, 1311, 1301, 1324, 1300, 1335, 1350, 1345, 1348, 1342, - /* 230 */ 1333, 1341, 1303, 1332, 1331, 1284, 1278, 1274, 1339, 1309, - /* 240 */ 1308, 1347, 1258, 1344, 1340, 1257, 1253, 1337, 1273, 1302, - /* 250 */ 1299, 1298, 1297, 1296, 1295, 1328, 1294, 1264, 1292, 1291, - /* 260 */ 1322, 1321, 1238, 1232, 1318, 1317, 1316, 1314, 1312, 1310, - /* 270 */ 1307, 1283, 1289, 1288, 1285, 1276, 1229, 1224, 1267, 1281, - /* 280 */ 1265, 1262, 1235, 1255, 1205, 1183, 1179, 1177, 1162, 1140, - /* 290 */ 1153, 1184, 1182, 1102, 1124, 1103, 1095, 1090, 1089, 1093, - /* 300 */ 1112, 1115, 1086, 1105, 1092, 1087, 1068, 962, 955, 957, - /* 310 */ 1031, 1023, 1030, + /* 0 */ -141, 90, 1095, 222, 158, 156, 19, 17, 10, -104, + /* 10 */ 378, 316, 311, 12, 180, 249, 598, 464, 397, 1181, + /* 20 */ 1177, 1175, 1128, 1106, 1096, 1054, 1038, 974, 964, 962, + /* 30 */ 948, 905, 903, 900, 887, 874, 832, 826, 816, 813, + /* 40 */ 800, 758, 755, 752, 742, 739, 726, 685, 681, 668, + /* 50 */ 665, 652, 607, 604, 594, 591, 578, 530, 528, 526, + /* 60 */ 385, 18, 477, 466, 519, 444, 350, 435, 405, 488, + /* 70 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, + /* 80 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, + /* 90 */ 488, 488, 488, 488, 488, 488, 488, 488, 488, 488, + /* 100 */ 488, 488, 488, 488, 488, 488, 488, 1040, 678, 1036, + /* 110 */ 1007, 967, 966, 965, 845, 686, 610, 684, 317, 672, + /* 120 */ 893, 327, 623, 522, -7, 820, 814, 157, 154, 101, + /* 130 */ 702, 494, 580, 488, 488, 488, 488, 488, 614, 586, + /* 140 */ 935, 892, 968, 1245, 1242, 1234, 1225, 798, 798, 1222, + /* 150 */ 1221, 1218, 1214, 1213, 1212, 1202, 1195, 1191, 1161, 1158, + /* 160 */ 1140, 1135, 1123, 1112, 1107, 1100, 1080, 1074, 1073, 1072, + /* 170 */ 1070, 1067, 1048, 1044, 969, 968, 907, 906, 904, 894, + /* 180 */ 833, 837, 836, 340, 827, 815, 775, 68, 722, 646, + /* 190 */ -168, 1384, 1380, 1377, 1379, 1376, 1373, 1339, 1365, 1368, + /* 200 */ 1365, 1365, 1365, 1365, 1365, 1365, 1365, 1320, 1319, 1365, + /* 210 */ 1365, 1339, 1378, 1349, 1391, 1350, 1342, 1334, 1307, 1341, + /* 220 */ 1293, 1364, 1363, 1371, 1362, 1370, 1359, 1340, 1354, 1333, + /* 230 */ 1305, 1304, 1299, 1361, 1328, 1324, 1366, 1282, 1360, 1358, + /* 240 */ 1278, 1276, 1356, 1292, 1322, 1309, 1317, 1315, 1314, 1312, + /* 250 */ 1345, 1347, 1302, 1277, 1311, 1303, 1337, 1335, 1252, 1248, + /* 260 */ 1332, 1330, 1329, 1327, 1326, 1323, 1321, 1297, 1301, 1295, + /* 270 */ 1294, 1290, 1243, 1240, 1284, 1291, 1286, 1283, 1274, 1281, + /* 280 */ 1271, 1238, 1241, 1236, 1235, 1227, 1226, 1267, 1266, 1189, + /* 290 */ 1229, 1223, 1211, 1206, 1201, 1197, 1239, 1237, 1219, 1216, + /* 300 */ 1209, 1208, 1185, 1089, 1086, 1087, 1137, 1136, 1164, }; static const YYACTIONTYPE yy_default[] = { - /* 0 */ 635, 870, 959, 959, 959, 870, 899, 899, 959, 759, - /* 10 */ 959, 959, 959, 959, 868, 959, 959, 933, 959, 959, - /* 20 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 30 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 40 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 50 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 60 */ 959, 959, 959, 959, 899, 899, 674, 763, 794, 959, - /* 70 */ 959, 959, 959, 959, 959, 959, 959, 932, 934, 809, - /* 80 */ 808, 802, 801, 912, 774, 799, 792, 785, 796, 871, - /* 90 */ 864, 865, 863, 867, 872, 959, 795, 831, 848, 830, - /* 100 */ 842, 847, 854, 846, 843, 833, 832, 666, 834, 835, - /* 110 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 120 */ 959, 959, 959, 959, 959, 959, 661, 728, 959, 959, - /* 130 */ 959, 959, 959, 959, 836, 837, 851, 850, 849, 959, - /* 140 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 150 */ 959, 939, 937, 959, 883, 959, 959, 959, 959, 959, - /* 160 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 170 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 180 */ 959, 641, 959, 759, 759, 759, 635, 959, 959, 959, - /* 190 */ 959, 951, 763, 753, 719, 959, 959, 959, 959, 959, - /* 200 */ 959, 959, 959, 959, 959, 959, 959, 804, 742, 922, - /* 210 */ 924, 959, 905, 740, 663, 761, 676, 751, 643, 798, - /* 220 */ 776, 776, 917, 798, 917, 700, 959, 788, 959, 788, - /* 230 */ 697, 788, 776, 788, 788, 866, 959, 959, 959, 760, - /* 240 */ 751, 959, 944, 767, 767, 936, 936, 767, 810, 732, - /* 250 */ 798, 739, 739, 739, 739, 767, 798, 810, 732, 732, - /* 260 */ 767, 658, 911, 909, 767, 767, 658, 767, 658, 767, - /* 270 */ 658, 876, 730, 730, 730, 715, 880, 880, 876, 730, - /* 280 */ 700, 730, 715, 730, 730, 780, 775, 780, 775, 780, - /* 290 */ 775, 767, 767, 959, 793, 781, 791, 789, 798, 959, - /* 300 */ 718, 651, 651, 640, 640, 640, 640, 956, 956, 951, - /* 310 */ 702, 702, 684, 959, 959, 959, 959, 959, 959, 959, - /* 320 */ 885, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 330 */ 959, 959, 959, 959, 636, 946, 959, 959, 943, 959, - /* 340 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 350 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 915, - /* 360 */ 959, 959, 959, 959, 959, 959, 908, 907, 959, 959, - /* 370 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 380 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 959, - /* 390 */ 959, 959, 959, 959, 790, 959, 782, 959, 869, 959, - /* 400 */ 959, 959, 959, 959, 959, 959, 959, 959, 959, 745, - /* 410 */ 819, 959, 818, 822, 817, 668, 959, 649, 959, 632, - /* 420 */ 637, 955, 958, 957, 954, 953, 952, 947, 945, 942, - /* 430 */ 941, 940, 938, 935, 931, 889, 887, 894, 893, 892, - /* 440 */ 891, 890, 888, 886, 884, 805, 803, 800, 797, 930, - /* 450 */ 882, 741, 738, 737, 657, 948, 914, 923, 921, 811, - /* 460 */ 920, 919, 918, 916, 913, 900, 807, 806, 733, 874, - /* 470 */ 873, 660, 904, 903, 902, 906, 910, 901, 769, 659, - /* 480 */ 656, 665, 722, 721, 729, 727, 726, 725, 724, 723, - /* 490 */ 720, 667, 675, 686, 714, 699, 698, 879, 881, 878, - /* 500 */ 877, 707, 706, 712, 711, 710, 709, 708, 705, 704, - /* 510 */ 703, 696, 695, 701, 694, 717, 716, 713, 693, 736, - /* 520 */ 735, 734, 731, 692, 691, 690, 822, 689, 688, 828, - /* 530 */ 827, 815, 858, 756, 755, 754, 766, 765, 778, 777, - /* 540 */ 813, 812, 779, 764, 758, 757, 773, 772, 771, 770, - /* 550 */ 762, 752, 784, 787, 786, 783, 860, 768, 857, 929, - /* 560 */ 928, 927, 926, 925, 862, 861, 829, 826, 679, 680, - /* 570 */ 898, 896, 897, 895, 682, 681, 678, 677, 859, 747, - /* 580 */ 746, 855, 852, 844, 840, 856, 853, 845, 841, 839, - /* 590 */ 838, 824, 823, 821, 820, 816, 825, 670, 748, 744, - /* 600 */ 743, 814, 750, 749, 687, 685, 683, 664, 662, 655, - /* 610 */ 653, 652, 654, 650, 648, 647, 646, 645, 644, 673, - /* 620 */ 672, 671, 669, 668, 642, 639, 638, 634, 633, 631, + /* 0 */ 632, 866, 954, 954, 866, 866, 954, 954, 954, 756, + /* 10 */ 954, 954, 954, 864, 954, 954, 784, 784, 928, 954, + /* 20 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 30 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 40 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 50 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 60 */ 954, 954, 954, 954, 954, 954, 954, 671, 760, 790, + /* 70 */ 954, 954, 954, 954, 954, 954, 954, 954, 927, 929, + /* 80 */ 798, 797, 907, 771, 795, 788, 792, 867, 860, 861, + /* 90 */ 859, 863, 868, 954, 791, 827, 844, 826, 838, 843, + /* 100 */ 850, 842, 839, 829, 828, 830, 831, 954, 954, 954, + /* 110 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 120 */ 954, 954, 954, 658, 725, 954, 954, 954, 954, 954, + /* 130 */ 954, 954, 954, 832, 833, 847, 846, 845, 954, 663, + /* 140 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 150 */ 934, 932, 954, 879, 954, 954, 954, 954, 954, 954, + /* 160 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 170 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 180 */ 638, 756, 756, 756, 632, 954, 954, 954, 946, 760, + /* 190 */ 750, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 200 */ 954, 954, 954, 800, 739, 917, 919, 954, 900, 737, + /* 210 */ 660, 758, 673, 748, 640, 794, 773, 773, 912, 794, + /* 220 */ 912, 696, 719, 954, 784, 954, 784, 693, 784, 773, + /* 230 */ 862, 954, 954, 954, 757, 748, 954, 939, 764, 764, + /* 240 */ 931, 931, 764, 806, 729, 794, 736, 736, 736, 736, + /* 250 */ 764, 655, 794, 806, 729, 729, 764, 655, 906, 904, + /* 260 */ 764, 764, 655, 764, 655, 764, 655, 872, 727, 727, + /* 270 */ 727, 711, 876, 876, 872, 727, 696, 727, 711, 727, + /* 280 */ 727, 777, 772, 777, 772, 777, 772, 764, 764, 954, + /* 290 */ 789, 778, 787, 785, 794, 954, 714, 648, 648, 637, + /* 300 */ 637, 637, 637, 951, 951, 946, 698, 698, 681, 954, + /* 310 */ 954, 954, 954, 954, 954, 954, 881, 954, 954, 954, + /* 320 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 633, + /* 330 */ 941, 954, 954, 938, 954, 954, 954, 954, 799, 954, + /* 340 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 916, + /* 350 */ 954, 954, 954, 954, 954, 954, 954, 910, 954, 954, + /* 360 */ 954, 954, 954, 954, 903, 902, 954, 954, 954, 954, + /* 370 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 380 */ 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + /* 390 */ 954, 954, 786, 954, 779, 954, 865, 954, 954, 954, + /* 400 */ 954, 954, 954, 954, 954, 954, 954, 742, 815, 954, + /* 410 */ 814, 818, 813, 665, 954, 646, 954, 629, 634, 950, + /* 420 */ 953, 952, 949, 948, 947, 942, 940, 937, 936, 935, + /* 430 */ 933, 930, 926, 885, 883, 890, 889, 888, 887, 886, + /* 440 */ 884, 882, 880, 801, 796, 793, 925, 878, 738, 735, + /* 450 */ 734, 654, 943, 909, 918, 805, 804, 807, 915, 914, + /* 460 */ 913, 911, 908, 895, 803, 802, 730, 870, 869, 657, + /* 470 */ 899, 898, 897, 901, 905, 896, 766, 656, 653, 662, + /* 480 */ 717, 718, 726, 724, 723, 722, 721, 720, 716, 664, + /* 490 */ 672, 710, 695, 694, 875, 877, 874, 873, 703, 702, + /* 500 */ 708, 707, 706, 705, 704, 701, 700, 699, 692, 691, + /* 510 */ 697, 690, 713, 712, 709, 689, 733, 732, 731, 728, + /* 520 */ 688, 687, 686, 818, 685, 684, 824, 823, 811, 854, + /* 530 */ 753, 752, 751, 763, 762, 775, 774, 809, 808, 776, + /* 540 */ 761, 755, 754, 770, 769, 768, 767, 759, 749, 781, + /* 550 */ 783, 782, 780, 856, 765, 853, 924, 923, 922, 921, + /* 560 */ 920, 858, 857, 825, 822, 676, 677, 893, 892, 894, + /* 570 */ 891, 679, 678, 675, 674, 855, 744, 743, 851, 848, + /* 580 */ 840, 836, 852, 849, 841, 837, 835, 834, 820, 819, + /* 590 */ 817, 816, 812, 821, 667, 745, 741, 740, 810, 747, + /* 600 */ 746, 683, 682, 680, 661, 659, 652, 650, 649, 651, + /* 610 */ 647, 645, 644, 643, 642, 641, 670, 669, 668, 666, + /* 620 */ 665, 639, 636, 635, 631, 630, 628, }; /* The next table maps tokens into fallback tokens. If a construct @@ -108532,26 +109894,26 @@ static const char *const yyTokenName[] = { "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", + "ccons", "term", "expr", "onconf", + "sortorder", "autoinc", "idxlist_opt", "refargs", + "defer_subclause", "refarg", "refact", "init_deferred_pred_opt", + "conslist", "tconscomma", "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", - "itemlist", "exprlist", "likeop", "between_op", - "in_op", "case_operand", "case_exprlist", "case_else", - "uniqueflag", "collate", "nmnum", "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", "create_vtab", "vtabarglist", - "vtabarg", "vtabargtoken", "lp", "anylist", + "joinop2", "inscollist", "sortlist", "nexprlist", + "setlist", "insert_cmd", "inscollist_opt", "valuelist", + "exprlist", "likeop", "between_op", "in_op", + "case_operand", "case_exprlist", "case_else", "uniqueflag", + "collate", "nmnum", "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", + "create_vtab", "vtabarglist", "vtabarg", "vtabargtoken", + "lp", "anylist", }; #endif /* NDEBUG */ @@ -108612,46 +109974,46 @@ static const char *const yyRuleName[] = { /* 50 */ "typename ::= typename ids", /* 51 */ "signed ::= plus_num", /* 52 */ "signed ::= minus_num", - /* 53 */ "carglist ::= carglist carg", + /* 53 */ "carglist ::= carglist ccons", /* 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", + /* 55 */ "ccons ::= CONSTRAINT nm", + /* 56 */ "ccons ::= DEFAULT term", + /* 57 */ "ccons ::= DEFAULT LP expr RP", + /* 58 */ "ccons ::= DEFAULT PLUS term", + /* 59 */ "ccons ::= DEFAULT MINUS term", + /* 60 */ "ccons ::= DEFAULT id", + /* 61 */ "ccons ::= NULL onconf", + /* 62 */ "ccons ::= NOT NULL onconf", + /* 63 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 64 */ "ccons ::= UNIQUE onconf", + /* 65 */ "ccons ::= CHECK LP expr RP", + /* 66 */ "ccons ::= REFERENCES nm idxlist_opt refargs", + /* 67 */ "ccons ::= defer_subclause", + /* 68 */ "ccons ::= COLLATE ids", + /* 69 */ "autoinc ::=", + /* 70 */ "autoinc ::= AUTOINCR", + /* 71 */ "refargs ::=", + /* 72 */ "refargs ::= refargs refarg", + /* 73 */ "refarg ::= MATCH nm", + /* 74 */ "refarg ::= ON INSERT refact", + /* 75 */ "refarg ::= ON DELETE refact", + /* 76 */ "refarg ::= ON UPDATE refact", + /* 77 */ "refact ::= SET NULL", + /* 78 */ "refact ::= SET DEFAULT", + /* 79 */ "refact ::= CASCADE", + /* 80 */ "refact ::= RESTRICT", + /* 81 */ "refact ::= NO ACTION", + /* 82 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 83 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 84 */ "init_deferred_pred_opt ::=", + /* 85 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 86 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 87 */ "conslist_opt ::=", + /* 88 */ "conslist_opt ::= COMMA conslist", + /* 89 */ "conslist ::= conslist tconscomma tcons", + /* 90 */ "conslist ::= tcons", + /* 91 */ "tconscomma ::= COMMA", + /* 92 */ "tconscomma ::=", /* 93 */ "tcons ::= CONSTRAINT nm", /* 94 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", /* 95 */ "tcons ::= UNIQUE LP idxlist RP onconf", @@ -108712,182 +110074,180 @@ static const char *const yyRuleName[] = { /* 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 VALUES LP itemlist RP", - /* 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 */ "itemlist ::= itemlist COMMA expr", - /* 179 */ "itemlist ::= expr", - /* 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 ::= MATCH", - /* 211 */ "likeop ::= NOT MATCH", - /* 212 */ "expr ::= expr likeop expr", - /* 213 */ "expr ::= expr likeop expr ESCAPE 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 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP", - /* 244 */ "uniqueflag ::= UNIQUE", - /* 245 */ "uniqueflag ::=", - /* 246 */ "idxlist_opt ::=", - /* 247 */ "idxlist_opt ::= LP idxlist RP", - /* 248 */ "idxlist ::= idxlist COMMA nm collate sortorder", - /* 249 */ "idxlist ::= nm collate sortorder", - /* 250 */ "collate ::=", - /* 251 */ "collate ::= COLLATE ids", - /* 252 */ "cmd ::= DROP INDEX ifexists fullname", - /* 253 */ "cmd ::= VACUUM", - /* 254 */ "cmd ::= VACUUM nm", - /* 255 */ "cmd ::= PRAGMA nm dbnm", - /* 256 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", - /* 257 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", - /* 258 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", - /* 259 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", - /* 260 */ "nmnum ::= plus_num", - /* 261 */ "nmnum ::= nm", - /* 262 */ "nmnum ::= ON", - /* 263 */ "nmnum ::= DELETE", - /* 264 */ "nmnum ::= DEFAULT", - /* 265 */ "plus_num ::= plus_opt number", + /* 153 */ "sortlist ::= sortlist COMMA expr sortorder", + /* 154 */ "sortlist ::= expr sortorder", + /* 155 */ "sortorder ::= ASC", + /* 156 */ "sortorder ::= DESC", + /* 157 */ "sortorder ::=", + /* 158 */ "groupby_opt ::=", + /* 159 */ "groupby_opt ::= GROUP BY nexprlist", + /* 160 */ "having_opt ::=", + /* 161 */ "having_opt ::= HAVING expr", + /* 162 */ "limit_opt ::=", + /* 163 */ "limit_opt ::= LIMIT expr", + /* 164 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 165 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 166 */ "cmd ::= DELETE FROM fullname indexed_opt where_opt", + /* 167 */ "where_opt ::=", + /* 168 */ "where_opt ::= WHERE expr", + /* 169 */ "cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt", + /* 170 */ "setlist ::= setlist COMMA nm EQ expr", + /* 171 */ "setlist ::= nm EQ expr", + /* 172 */ "cmd ::= insert_cmd INTO fullname inscollist_opt valuelist", + /* 173 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", + /* 174 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES", + /* 175 */ "insert_cmd ::= INSERT orconf", + /* 176 */ "insert_cmd ::= REPLACE", + /* 177 */ "valuelist ::= VALUES LP nexprlist RP", + /* 178 */ "valuelist ::= valuelist COMMA LP exprlist RP", + /* 179 */ "inscollist_opt ::=", + /* 180 */ "inscollist_opt ::= LP inscollist RP", + /* 181 */ "inscollist ::= inscollist COMMA nm", + /* 182 */ "inscollist ::= nm", + /* 183 */ "expr ::= term", + /* 184 */ "expr ::= LP expr RP", + /* 185 */ "term ::= NULL", + /* 186 */ "expr ::= id", + /* 187 */ "expr ::= JOIN_KW", + /* 188 */ "expr ::= nm DOT nm", + /* 189 */ "expr ::= nm DOT nm DOT nm", + /* 190 */ "term ::= INTEGER|FLOAT|BLOB", + /* 191 */ "term ::= STRING", + /* 192 */ "expr ::= REGISTER", + /* 193 */ "expr ::= VARIABLE", + /* 194 */ "expr ::= expr COLLATE ids", + /* 195 */ "expr ::= CAST LP expr AS typetoken RP", + /* 196 */ "expr ::= ID LP distinct exprlist RP", + /* 197 */ "expr ::= ID LP STAR RP", + /* 198 */ "term ::= CTIME_KW", + /* 199 */ "expr ::= expr AND expr", + /* 200 */ "expr ::= expr OR expr", + /* 201 */ "expr ::= expr LT|GT|GE|LE expr", + /* 202 */ "expr ::= expr EQ|NE expr", + /* 203 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 204 */ "expr ::= expr PLUS|MINUS expr", + /* 205 */ "expr ::= expr STAR|SLASH|REM expr", + /* 206 */ "expr ::= expr CONCAT expr", + /* 207 */ "likeop ::= LIKE_KW", + /* 208 */ "likeop ::= NOT LIKE_KW", + /* 209 */ "likeop ::= MATCH", + /* 210 */ "likeop ::= NOT MATCH", + /* 211 */ "expr ::= expr likeop expr", + /* 212 */ "expr ::= expr likeop expr ESCAPE expr", + /* 213 */ "expr ::= expr ISNULL|NOTNULL", + /* 214 */ "expr ::= expr NOT NULL", + /* 215 */ "expr ::= expr IS expr", + /* 216 */ "expr ::= expr IS NOT expr", + /* 217 */ "expr ::= NOT expr", + /* 218 */ "expr ::= BITNOT expr", + /* 219 */ "expr ::= MINUS expr", + /* 220 */ "expr ::= PLUS expr", + /* 221 */ "between_op ::= BETWEEN", + /* 222 */ "between_op ::= NOT BETWEEN", + /* 223 */ "expr ::= expr between_op expr AND expr", + /* 224 */ "in_op ::= IN", + /* 225 */ "in_op ::= NOT IN", + /* 226 */ "expr ::= expr in_op LP exprlist RP", + /* 227 */ "expr ::= LP select RP", + /* 228 */ "expr ::= expr in_op LP select RP", + /* 229 */ "expr ::= expr in_op nm dbnm", + /* 230 */ "expr ::= EXISTS LP select RP", + /* 231 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 232 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 233 */ "case_exprlist ::= WHEN expr THEN expr", + /* 234 */ "case_else ::= ELSE expr", + /* 235 */ "case_else ::=", + /* 236 */ "case_operand ::= expr", + /* 237 */ "case_operand ::=", + /* 238 */ "exprlist ::= nexprlist", + /* 239 */ "exprlist ::=", + /* 240 */ "nexprlist ::= nexprlist COMMA expr", + /* 241 */ "nexprlist ::= expr", + /* 242 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP", + /* 243 */ "uniqueflag ::= UNIQUE", + /* 244 */ "uniqueflag ::=", + /* 245 */ "idxlist_opt ::=", + /* 246 */ "idxlist_opt ::= LP idxlist RP", + /* 247 */ "idxlist ::= idxlist COMMA nm collate sortorder", + /* 248 */ "idxlist ::= nm collate sortorder", + /* 249 */ "collate ::=", + /* 250 */ "collate ::= COLLATE ids", + /* 251 */ "cmd ::= DROP INDEX ifexists fullname", + /* 252 */ "cmd ::= VACUUM", + /* 253 */ "cmd ::= VACUUM nm", + /* 254 */ "cmd ::= PRAGMA nm dbnm", + /* 255 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 256 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 257 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 258 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP", + /* 259 */ "nmnum ::= plus_num", + /* 260 */ "nmnum ::= nm", + /* 261 */ "nmnum ::= ON", + /* 262 */ "nmnum ::= DELETE", + /* 263 */ "nmnum ::= DEFAULT", + /* 264 */ "plus_num ::= PLUS number", + /* 265 */ "plus_num ::= number", /* 266 */ "minus_num ::= MINUS number", /* 267 */ "number ::= INTEGER|FLOAT", - /* 268 */ "plus_opt ::= PLUS", - /* 269 */ "plus_opt ::=", - /* 270 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", - /* 271 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", - /* 272 */ "trigger_time ::= BEFORE", - /* 273 */ "trigger_time ::= AFTER", - /* 274 */ "trigger_time ::= INSTEAD OF", - /* 275 */ "trigger_time ::=", - /* 276 */ "trigger_event ::= DELETE|INSERT", - /* 277 */ "trigger_event ::= UPDATE", - /* 278 */ "trigger_event ::= UPDATE OF inscollist", - /* 279 */ "foreach_clause ::=", - /* 280 */ "foreach_clause ::= FOR EACH ROW", - /* 281 */ "when_clause ::=", - /* 282 */ "when_clause ::= WHEN expr", - /* 283 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", - /* 284 */ "trigger_cmd_list ::= trigger_cmd SEMI", - /* 285 */ "trnm ::= nm", - /* 286 */ "trnm ::= nm DOT nm", - /* 287 */ "tridxby ::=", - /* 288 */ "tridxby ::= INDEXED BY nm", - /* 289 */ "tridxby ::= NOT INDEXED", - /* 290 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", - /* 291 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt VALUES LP itemlist RP", - /* 292 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select", - /* 293 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", - /* 294 */ "trigger_cmd ::= select", - /* 295 */ "expr ::= RAISE LP IGNORE RP", - /* 296 */ "expr ::= RAISE LP raisetype COMMA nm RP", - /* 297 */ "raisetype ::= ROLLBACK", - /* 298 */ "raisetype ::= ABORT", - /* 299 */ "raisetype ::= FAIL", - /* 300 */ "cmd ::= DROP TRIGGER ifexists fullname", - /* 301 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", - /* 302 */ "cmd ::= DETACH database_kw_opt expr", - /* 303 */ "key_opt ::=", - /* 304 */ "key_opt ::= KEY expr", - /* 305 */ "database_kw_opt ::= DATABASE", - /* 306 */ "database_kw_opt ::=", - /* 307 */ "cmd ::= REINDEX", - /* 308 */ "cmd ::= REINDEX nm dbnm", - /* 309 */ "cmd ::= ANALYZE", - /* 310 */ "cmd ::= ANALYZE nm dbnm", - /* 311 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", - /* 312 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", - /* 313 */ "add_column_fullname ::= fullname", - /* 314 */ "kwcolumn_opt ::=", - /* 315 */ "kwcolumn_opt ::= COLUMNKW", - /* 316 */ "cmd ::= create_vtab", - /* 317 */ "cmd ::= create_vtab LP vtabarglist RP", - /* 318 */ "create_vtab ::= createkw VIRTUAL TABLE nm dbnm USING nm", - /* 319 */ "vtabarglist ::= vtabarg", - /* 320 */ "vtabarglist ::= vtabarglist COMMA vtabarg", - /* 321 */ "vtabarg ::=", - /* 322 */ "vtabarg ::= vtabarg vtabargtoken", - /* 323 */ "vtabargtoken ::= ANY", - /* 324 */ "vtabargtoken ::= lp anylist RP", - /* 325 */ "lp ::= LP", - /* 326 */ "anylist ::=", - /* 327 */ "anylist ::= anylist LP anylist RP", - /* 328 */ "anylist ::= anylist ANY", + /* 268 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END", + /* 269 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 270 */ "trigger_time ::= BEFORE", + /* 271 */ "trigger_time ::= AFTER", + /* 272 */ "trigger_time ::= INSTEAD OF", + /* 273 */ "trigger_time ::=", + /* 274 */ "trigger_event ::= DELETE|INSERT", + /* 275 */ "trigger_event ::= UPDATE", + /* 276 */ "trigger_event ::= UPDATE OF inscollist", + /* 277 */ "foreach_clause ::=", + /* 278 */ "foreach_clause ::= FOR EACH ROW", + /* 279 */ "when_clause ::=", + /* 280 */ "when_clause ::= WHEN expr", + /* 281 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 282 */ "trigger_cmd_list ::= trigger_cmd SEMI", + /* 283 */ "trnm ::= nm", + /* 284 */ "trnm ::= nm DOT nm", + /* 285 */ "tridxby ::=", + /* 286 */ "tridxby ::= INDEXED BY nm", + /* 287 */ "tridxby ::= NOT INDEXED", + /* 288 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt", + /* 289 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist", + /* 290 */ "trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select", + /* 291 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt", + /* 292 */ "trigger_cmd ::= select", + /* 293 */ "expr ::= RAISE LP IGNORE RP", + /* 294 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 295 */ "raisetype ::= ROLLBACK", + /* 296 */ "raisetype ::= ABORT", + /* 297 */ "raisetype ::= FAIL", + /* 298 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 299 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 300 */ "cmd ::= DETACH database_kw_opt expr", + /* 301 */ "key_opt ::=", + /* 302 */ "key_opt ::= KEY expr", + /* 303 */ "database_kw_opt ::= DATABASE", + /* 304 */ "database_kw_opt ::=", + /* 305 */ "cmd ::= REINDEX", + /* 306 */ "cmd ::= REINDEX nm dbnm", + /* 307 */ "cmd ::= ANALYZE", + /* 308 */ "cmd ::= ANALYZE nm dbnm", + /* 309 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 310 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 311 */ "add_column_fullname ::= fullname", + /* 312 */ "kwcolumn_opt ::=", + /* 313 */ "kwcolumn_opt ::= COLUMNKW", + /* 314 */ "cmd ::= create_vtab", + /* 315 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 316 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm", + /* 317 */ "vtabarglist ::= vtabarg", + /* 318 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 319 */ "vtabarg ::=", + /* 320 */ "vtabarg ::= vtabarg vtabargtoken", + /* 321 */ "vtabargtoken ::= ANY", + /* 322 */ "vtabargtoken ::= lp anylist RP", + /* 323 */ "lp ::= LP", + /* 324 */ "anylist ::=", + /* 325 */ "anylist ::= anylist LP anylist RP", + /* 326 */ "anylist ::= anylist ANY", }; #endif /* NDEBUG */ @@ -108969,29 +110329,28 @@ static void yy_destructor( case 160: /* select */ case 194: /* oneselect */ { -sqlite3SelectDelete(pParse->db, (yypminor->yy387)); +sqlite3SelectDelete(pParse->db, (yypminor->yy159)); } break; - case 174: /* term */ - case 175: /* expr */ + case 173: /* term */ + case 174: /* expr */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy118).pExpr); +sqlite3ExprDelete(pParse->db, (yypminor->yy342).pExpr); } break; - case 179: /* idxlist_opt */ + case 178: /* 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 220: /* itemlist */ - case 221: /* exprlist */ - case 226: /* case_exprlist */ + case 215: /* nexprlist */ + case 216: /* setlist */ + case 220: /* exprlist */ + case 225: /* case_exprlist */ { -sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); +sqlite3ExprListDelete(pParse->db, (yypminor->yy442)); } break; case 193: /* fullname */ @@ -108999,37 +110358,44 @@ sqlite3ExprListDelete(pParse->db, (yypminor->yy322)); case 206: /* seltablist */ case 207: /* stl_prefix */ { -sqlite3SrcListDelete(pParse->db, (yypminor->yy259)); +sqlite3SrcListDelete(pParse->db, (yypminor->yy347)); } 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 238: /* when_clause */ - case 243: /* key_opt */ + case 224: /* case_operand */ + case 226: /* case_else */ + case 236: /* when_clause */ + case 241: /* key_opt */ { -sqlite3ExprDelete(pParse->db, (yypminor->yy314)); +sqlite3ExprDelete(pParse->db, (yypminor->yy122)); } break; case 211: /* using_opt */ case 213: /* inscollist */ - case 219: /* inscollist_opt */ + case 218: /* inscollist_opt */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy384)); +sqlite3IdListDelete(pParse->db, (yypminor->yy180)); } break; - case 234: /* trigger_cmd_list */ - case 239: /* trigger_cmd */ + case 219: /* valuelist */ { -sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy203)); + + sqlite3ExprListDelete(pParse->db, (yypminor->yy487).pList); + sqlite3SelectDelete(pParse->db, (yypminor->yy487).pSelect); + } break; - case 236: /* trigger_event */ + case 232: /* trigger_cmd_list */ + case 237: /* trigger_cmd */ { -sqlite3IdListDelete(pParse->db, (yypminor->yy90).b); +sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy327)); +} + break; + case 234: /* trigger_event */ +{ +sqlite3IdListDelete(pParse->db, (yypminor->yy410).b); } break; default: break; /* If no destructor action specified: do nothing */ @@ -109329,44 +110695,44 @@ static const struct { { 169, 1 }, { 164, 2 }, { 164, 0 }, + { 172, 2 }, + { 172, 2 }, + { 172, 4 }, { 172, 3 }, + { 172, 3 }, + { 172, 2 }, + { 172, 2 }, + { 172, 3 }, + { 172, 5 }, + { 172, 2 }, + { 172, 4 }, + { 172, 4 }, { 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 }, + { 172, 2 }, + { 177, 0 }, + { 177, 1 }, + { 179, 0 }, + { 179, 2 }, { 181, 2 }, - { 184, 0 }, - { 184, 2 }, - { 184, 2 }, + { 181, 3 }, + { 181, 3 }, + { 181, 3 }, + { 182, 2 }, + { 182, 2 }, + { 182, 1 }, + { 182, 1 }, + { 182, 2 }, + { 180, 3 }, + { 180, 2 }, + { 183, 0 }, + { 183, 2 }, + { 183, 2 }, { 159, 0 }, { 159, 2 }, - { 185, 3 }, - { 185, 2 }, + { 184, 3 }, + { 184, 1 }, { 185, 1 }, + { 185, 0 }, { 186, 2 }, { 186, 7 }, { 186, 5 }, @@ -109374,8 +110740,8 @@ static const struct { { 186, 10 }, { 188, 0 }, { 188, 1 }, - { 176, 0 }, - { 176, 3 }, + { 175, 0 }, + { 175, 3 }, { 189, 0 }, { 189, 2 }, { 190, 1 }, @@ -109429,10 +110795,9 @@ static const struct { { 202, 3 }, { 214, 4 }, { 214, 2 }, - { 215, 1 }, - { 177, 1 }, - { 177, 1 }, - { 177, 0 }, + { 176, 1 }, + { 176, 1 }, + { 176, 0 }, { 200, 0 }, { 200, 3 }, { 201, 0 }, @@ -109445,87 +110810,87 @@ static const struct { { 199, 0 }, { 199, 2 }, { 147, 7 }, - { 217, 5 }, - { 217, 3 }, - { 147, 8 }, + { 216, 5 }, + { 216, 3 }, + { 147, 5 }, { 147, 5 }, { 147, 6 }, - { 218, 2 }, - { 218, 1 }, - { 220, 3 }, - { 220, 1 }, - { 219, 0 }, - { 219, 3 }, + { 217, 2 }, + { 217, 1 }, + { 219, 4 }, + { 219, 5 }, + { 218, 0 }, + { 218, 3 }, { 213, 3 }, { 213, 1 }, - { 175, 1 }, - { 175, 3 }, { 174, 1 }, - { 175, 1 }, - { 175, 1 }, - { 175, 3 }, - { 175, 5 }, + { 174, 3 }, + { 173, 1 }, { 174, 1 }, { 174, 1 }, - { 175, 1 }, - { 175, 1 }, - { 175, 3 }, - { 175, 6 }, - { 175, 5 }, - { 175, 4 }, + { 174, 3 }, + { 174, 5 }, + { 173, 1 }, + { 173, 1 }, { 174, 1 }, - { 175, 3 }, - { 175, 3 }, - { 175, 3 }, - { 175, 3 }, - { 175, 3 }, - { 175, 3 }, - { 175, 3 }, - { 175, 3 }, + { 174, 1 }, + { 174, 3 }, + { 174, 6 }, + { 174, 5 }, + { 174, 4 }, + { 173, 1 }, + { 174, 3 }, + { 174, 3 }, + { 174, 3 }, + { 174, 3 }, + { 174, 3 }, + { 174, 3 }, + { 174, 3 }, + { 174, 3 }, + { 221, 1 }, + { 221, 2 }, + { 221, 1 }, + { 221, 2 }, + { 174, 3 }, + { 174, 5 }, + { 174, 2 }, + { 174, 3 }, + { 174, 3 }, + { 174, 4 }, + { 174, 2 }, + { 174, 2 }, + { 174, 2 }, + { 174, 2 }, { 222, 1 }, { 222, 2 }, - { 222, 1 }, - { 222, 2 }, - { 175, 3 }, - { 175, 5 }, - { 175, 2 }, - { 175, 3 }, - { 175, 3 }, - { 175, 4 }, - { 175, 2 }, - { 175, 2 }, - { 175, 2 }, - { 175, 2 }, + { 174, 5 }, { 223, 1 }, { 223, 2 }, - { 175, 5 }, + { 174, 5 }, + { 174, 3 }, + { 174, 5 }, + { 174, 4 }, + { 174, 4 }, + { 174, 5 }, + { 225, 5 }, + { 225, 4 }, + { 226, 2 }, + { 226, 0 }, { 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 }, + { 224, 0 }, + { 220, 1 }, + { 220, 0 }, + { 215, 3 }, + { 215, 1 }, { 147, 11 }, - { 228, 1 }, - { 228, 0 }, - { 179, 0 }, - { 179, 3 }, + { 227, 1 }, + { 227, 0 }, + { 178, 0 }, + { 178, 3 }, { 187, 5 }, { 187, 3 }, - { 229, 0 }, - { 229, 2 }, + { 228, 0 }, + { 228, 2 }, { 147, 4 }, { 147, 1 }, { 147, 2 }, @@ -109534,75 +110899,74 @@ static const struct { { 147, 6 }, { 147, 5 }, { 147, 6 }, - { 230, 1 }, - { 230, 1 }, - { 230, 1 }, - { 230, 1 }, - { 230, 1 }, + { 229, 1 }, + { 229, 1 }, + { 229, 1 }, + { 229, 1 }, + { 229, 1 }, { 170, 2 }, + { 170, 1 }, { 171, 2 }, - { 232, 1 }, - { 231, 1 }, - { 231, 0 }, + { 230, 1 }, { 147, 5 }, - { 233, 11 }, - { 235, 1 }, - { 235, 1 }, - { 235, 2 }, - { 235, 0 }, - { 236, 1 }, - { 236, 1 }, - { 236, 3 }, - { 237, 0 }, - { 237, 3 }, - { 238, 0 }, - { 238, 2 }, + { 231, 11 }, + { 233, 1 }, + { 233, 1 }, + { 233, 2 }, + { 233, 0 }, + { 234, 1 }, + { 234, 1 }, { 234, 3 }, - { 234, 2 }, - { 240, 1 }, - { 240, 3 }, + { 235, 0 }, + { 235, 3 }, + { 236, 0 }, + { 236, 2 }, + { 232, 3 }, + { 232, 2 }, + { 238, 1 }, + { 238, 3 }, + { 239, 0 }, + { 239, 3 }, + { 239, 2 }, + { 237, 7 }, + { 237, 5 }, + { 237, 5 }, + { 237, 5 }, + { 237, 1 }, + { 174, 4 }, + { 174, 6 }, + { 191, 1 }, + { 191, 1 }, + { 191, 1 }, + { 147, 4 }, + { 147, 6 }, + { 147, 3 }, { 241, 0 }, - { 241, 3 }, { 241, 2 }, - { 239, 7 }, - { 239, 8 }, - { 239, 5 }, - { 239, 5 }, - { 239, 1 }, - { 175, 4 }, - { 175, 6 }, - { 191, 1 }, - { 191, 1 }, - { 191, 1 }, - { 147, 4 }, - { 147, 6 }, + { 240, 1 }, + { 240, 0 }, + { 147, 1 }, { 147, 3 }, - { 243, 0 }, - { 243, 2 }, + { 147, 1 }, + { 147, 3 }, + { 147, 6 }, + { 147, 6 }, { 242, 1 }, - { 242, 0 }, - { 147, 1 }, - { 147, 3 }, - { 147, 1 }, - { 147, 3 }, - { 147, 6 }, - { 147, 6 }, - { 244, 1 }, - { 245, 0 }, - { 245, 1 }, + { 243, 0 }, + { 243, 1 }, { 147, 1 }, { 147, 4 }, - { 246, 7 }, + { 244, 8 }, + { 245, 1 }, + { 245, 3 }, + { 246, 0 }, + { 246, 2 }, { 247, 1 }, { 247, 3 }, - { 248, 0 }, - { 248, 2 }, - { 249, 1 }, - { 249, 3 }, - { 250, 1 }, - { 251, 0 }, - { 251, 4 }, - { 251, 2 }, + { 248, 1 }, + { 249, 0 }, + { 249, 4 }, + { 249, 2 }, }; static void yy_accept(yyParser*); /* Forward Declaration */ @@ -109670,17 +111034,17 @@ static void yy_reduce( { sqlite3FinishCoding(pParse); } break; case 9: /* cmd ::= BEGIN transtype trans_opt */ -{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy4);} +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy392);} break; case 13: /* transtype ::= */ -{yygotominor.yy4 = TK_DEFERRED;} +{yygotominor.yy392 = 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.yy4 = yymsp[0].major;} +{yygotominor.yy392 = yymsp[0].major;} break; case 17: /* cmd ::= COMMIT trans_opt */ case 18: /* cmd ::= END trans_opt */ yytestcase(yyruleno==18); @@ -109706,7 +111070,7 @@ static void yy_reduce( break; case 26: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */ { - sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy4,0,0,yymsp[-2].minor.yy4); + sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy392,0,0,yymsp[-2].minor.yy392); } break; case 27: /* createkw ::= CREATE */ @@ -109717,27 +111081,27 @@ static void yy_reduce( 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 69: /* autoinc ::= */ yytestcase(yyruleno==69); + case 82: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */ yytestcase(yyruleno==82); + case 84: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==84); + case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86); 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.yy4 = 0;} + case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221); + case 224: /* in_op ::= IN */ yytestcase(yyruleno==224); +{yygotominor.yy392 = 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 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70); + case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85); 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.yy4 = 1;} + case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222); + case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225); +{yygotominor.yy392 = 1;} break; case 32: /* create_table_args ::= LP columnlist conslist_opt RP */ { @@ -109746,8 +111110,8 @@ static void yy_reduce( break; case 33: /* create_table_args ::= AS select */ { - sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy387); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); + sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy159); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159); } break; case 36: /* column ::= columnid type carglist */ @@ -109760,6 +111124,7 @@ static void yy_reduce( { sqlite3AddColumn(pParse,&yymsp[0].minor.yy0); yygotominor.yy0 = yymsp[0].minor.yy0; + pParse->constraintName.n = 0; } break; case 38: /* id ::= ID */ @@ -109774,16 +111139,17 @@ static void yy_reduce( 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 251: /* collate ::= COLLATE ids */ yytestcase(yyruleno==251); - case 260: /* nmnum ::= plus_num */ yytestcase(yyruleno==260); - case 261: /* nmnum ::= nm */ yytestcase(yyruleno==261); - case 262: /* nmnum ::= ON */ yytestcase(yyruleno==262); - case 263: /* nmnum ::= DELETE */ yytestcase(yyruleno==263); - case 264: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==264); - case 265: /* plus_num ::= plus_opt number */ yytestcase(yyruleno==265); + case 250: /* collate ::= COLLATE ids */ yytestcase(yyruleno==250); + case 259: /* nmnum ::= plus_num */ yytestcase(yyruleno==259); + case 260: /* nmnum ::= nm */ yytestcase(yyruleno==260); + case 261: /* nmnum ::= ON */ yytestcase(yyruleno==261); + case 262: /* nmnum ::= DELETE */ yytestcase(yyruleno==262); + case 263: /* nmnum ::= DEFAULT */ yytestcase(yyruleno==263); + case 264: /* plus_num ::= PLUS number */ yytestcase(yyruleno==264); + case 265: /* plus_num ::= number */ yytestcase(yyruleno==265); case 266: /* minus_num ::= MINUS number */ yytestcase(yyruleno==266); case 267: /* number ::= INTEGER|FLOAT */ yytestcase(yyruleno==267); - case 285: /* trnm ::= nm */ yytestcase(yyruleno==285); + case 283: /* trnm ::= nm */ yytestcase(yyruleno==283); {yygotominor.yy0 = yymsp[0].minor.yy0;} break; case 45: /* type ::= typetoken */ @@ -109804,192 +111170,199 @@ static void yy_reduce( 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); -{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy118);} + case 55: /* ccons ::= CONSTRAINT nm */ + case 93: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==93); +{pParse->constraintName = yymsp[0].minor.yy0;} break; - case 58: /* ccons ::= DEFAULT LP expr RP */ -{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy118);} + case 56: /* ccons ::= DEFAULT term */ + case 58: /* ccons ::= DEFAULT PLUS term */ yytestcase(yyruleno==58); +{sqlite3AddDefaultValue(pParse,&yymsp[0].minor.yy342);} break; - case 60: /* ccons ::= DEFAULT MINUS term */ + case 57: /* ccons ::= DEFAULT LP expr RP */ +{sqlite3AddDefaultValue(pParse,&yymsp[-1].minor.yy342);} + break; + case 59: /* ccons ::= DEFAULT MINUS term */ { ExprSpan v; - v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy118.pExpr, 0, 0); + v.pExpr = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy342.pExpr, 0, 0); v.zStart = yymsp[-1].minor.yy0.z; - v.zEnd = yymsp[0].minor.yy118.zEnd; + v.zEnd = yymsp[0].minor.yy342.zEnd; sqlite3AddDefaultValue(pParse,&v); } break; - case 61: /* ccons ::= DEFAULT id */ + case 60: /* ccons ::= DEFAULT id */ { ExprSpan v; spanExpr(&v, pParse, TK_STRING, &yymsp[0].minor.yy0); sqlite3AddDefaultValue(pParse,&v); } break; - case 63: /* ccons ::= NOT NULL onconf */ -{sqlite3AddNotNull(pParse, yymsp[0].minor.yy4);} + case 62: /* ccons ::= NOT NULL onconf */ +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy392);} break; - case 64: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ -{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy4,yymsp[0].minor.yy4,yymsp[-2].minor.yy4);} + case 63: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */ +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy392,yymsp[0].minor.yy392,yymsp[-2].minor.yy392);} break; - case 65: /* ccons ::= UNIQUE onconf */ -{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy4,0,0,0,0);} + case 64: /* ccons ::= UNIQUE onconf */ +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy392,0,0,0,0);} break; - case 66: /* ccons ::= CHECK LP expr RP */ -{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy118.pExpr);} + case 65: /* ccons ::= CHECK LP expr RP */ +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy342.pExpr);} break; - case 67: /* ccons ::= REFERENCES nm idxlist_opt refargs */ -{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy4);} + case 66: /* ccons ::= REFERENCES nm idxlist_opt refargs */ +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy442,yymsp[0].minor.yy392);} break; - case 68: /* ccons ::= defer_subclause */ -{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy4);} + case 67: /* ccons ::= defer_subclause */ +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy392);} break; - case 69: /* ccons ::= COLLATE ids */ + case 68: /* ccons ::= COLLATE ids */ {sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);} break; - case 72: /* refargs ::= */ -{ yygotominor.yy4 = OE_None*0x0101; /* EV: R-19803-45884 */} + case 71: /* refargs ::= */ +{ yygotominor.yy392 = OE_None*0x0101; /* EV: R-19803-45884 */} break; - case 73: /* refargs ::= refargs refarg */ -{ yygotominor.yy4 = (yymsp[-1].minor.yy4 & ~yymsp[0].minor.yy215.mask) | yymsp[0].minor.yy215.value; } + case 72: /* refargs ::= refargs refarg */ +{ yygotominor.yy392 = (yymsp[-1].minor.yy392 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; } break; - case 74: /* refarg ::= MATCH nm */ - case 75: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==75); -{ yygotominor.yy215.value = 0; yygotominor.yy215.mask = 0x000000; } + case 73: /* refarg ::= MATCH nm */ + case 74: /* refarg ::= ON INSERT refact */ yytestcase(yyruleno==74); +{ yygotominor.yy207.value = 0; yygotominor.yy207.mask = 0x000000; } break; - case 76: /* refarg ::= ON DELETE refact */ -{ yygotominor.yy215.value = yymsp[0].minor.yy4; yygotominor.yy215.mask = 0x0000ff; } + case 75: /* refarg ::= ON DELETE refact */ +{ yygotominor.yy207.value = yymsp[0].minor.yy392; yygotominor.yy207.mask = 0x0000ff; } break; - case 77: /* refarg ::= ON UPDATE refact */ -{ yygotominor.yy215.value = yymsp[0].minor.yy4<<8; yygotominor.yy215.mask = 0x00ff00; } + case 76: /* refarg ::= ON UPDATE refact */ +{ yygotominor.yy207.value = yymsp[0].minor.yy392<<8; yygotominor.yy207.mask = 0x00ff00; } break; - case 78: /* refact ::= SET NULL */ -{ yygotominor.yy4 = OE_SetNull; /* EV: R-33326-45252 */} + case 77: /* refact ::= SET NULL */ +{ yygotominor.yy392 = OE_SetNull; /* EV: R-33326-45252 */} break; - case 79: /* refact ::= SET DEFAULT */ -{ yygotominor.yy4 = OE_SetDflt; /* EV: R-33326-45252 */} + case 78: /* refact ::= SET DEFAULT */ +{ yygotominor.yy392 = OE_SetDflt; /* EV: R-33326-45252 */} break; - case 80: /* refact ::= CASCADE */ -{ yygotominor.yy4 = OE_Cascade; /* EV: R-33326-45252 */} + case 79: /* refact ::= CASCADE */ +{ yygotominor.yy392 = OE_Cascade; /* EV: R-33326-45252 */} break; - case 81: /* refact ::= RESTRICT */ -{ yygotominor.yy4 = OE_Restrict; /* EV: R-33326-45252 */} + case 80: /* refact ::= RESTRICT */ +{ yygotominor.yy392 = OE_Restrict; /* EV: R-33326-45252 */} break; - case 82: /* refact ::= NO ACTION */ -{ yygotominor.yy4 = OE_None; /* EV: R-33326-45252 */} + case 81: /* refact ::= NO ACTION */ +{ yygotominor.yy392 = OE_None; /* EV: R-33326-45252 */} break; - case 84: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */ + case 83: /* 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.yy4 = yymsp[0].minor.yy4;} +{yygotominor.yy392 = yymsp[0].minor.yy392;} break; - case 88: /* conslist_opt ::= */ + case 87: /* conslist_opt ::= */ {yygotominor.yy0.n = 0; yygotominor.yy0.z = 0;} break; - case 89: /* conslist_opt ::= COMMA conslist */ + case 88: /* conslist_opt ::= COMMA conslist */ {yygotominor.yy0 = yymsp[-1].minor.yy0;} break; + case 91: /* tconscomma ::= COMMA */ +{pParse->constraintName.n = 0;} + break; case 94: /* tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf */ -{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy4,yymsp[-2].minor.yy4,0);} +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy442,yymsp[0].minor.yy392,yymsp[-2].minor.yy392,0);} break; case 95: /* tcons ::= UNIQUE LP idxlist RP onconf */ -{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy4,0,0,0,0);} +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy442,yymsp[0].minor.yy392,0,0,0,0);} break; case 96: /* tcons ::= CHECK LP expr RP onconf */ -{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy118.pExpr);} +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy342.pExpr);} break; case 97: /* tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt */ { - sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy4); - sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy4); + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy442, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy442, yymsp[-1].minor.yy392); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy392); } break; case 100: /* onconf ::= */ -{yygotominor.yy4 = OE_Default;} +{yygotominor.yy392 = OE_Default;} break; case 102: /* orconf ::= */ -{yygotominor.yy210 = OE_Default;} +{yygotominor.yy258 = OE_Default;} break; case 103: /* orconf ::= OR resolvetype */ -{yygotominor.yy210 = (u8)yymsp[0].minor.yy4;} +{yygotominor.yy258 = (u8)yymsp[0].minor.yy392;} break; case 105: /* resolvetype ::= IGNORE */ -{yygotominor.yy4 = OE_Ignore;} +{yygotominor.yy392 = OE_Ignore;} break; case 106: /* resolvetype ::= REPLACE */ -{yygotominor.yy4 = OE_Replace;} +{yygotominor.yy392 = OE_Replace;} break; case 107: /* cmd ::= DROP TABLE ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy259, 0, yymsp[-1].minor.yy4); + sqlite3DropTable(pParse, yymsp[0].minor.yy347, 0, yymsp[-1].minor.yy392); } break; case 110: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm AS select */ { - sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy387, yymsp[-6].minor.yy4, yymsp[-4].minor.yy4); + sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, yymsp[0].minor.yy159, yymsp[-6].minor.yy392, yymsp[-4].minor.yy392); } break; case 111: /* cmd ::= DROP VIEW ifexists fullname */ { - sqlite3DropTable(pParse, yymsp[0].minor.yy259, 1, yymsp[-1].minor.yy4); + sqlite3DropTable(pParse, yymsp[0].minor.yy347, 1, yymsp[-1].minor.yy392); } break; case 112: /* cmd ::= select */ { SelectDest dest = {SRT_Output, 0, 0, 0, 0}; - sqlite3Select(pParse, yymsp[0].minor.yy387, &dest); + sqlite3Select(pParse, yymsp[0].minor.yy159, &dest); sqlite3ExplainBegin(pParse->pVdbe); - sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy387); + sqlite3ExplainSelect(pParse->pVdbe, yymsp[0].minor.yy159); sqlite3ExplainFinish(pParse->pVdbe); - sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy159); } break; case 113: /* select ::= oneselect */ -{yygotominor.yy387 = yymsp[0].minor.yy387;} +{yygotominor.yy159 = yymsp[0].minor.yy159;} break; case 114: /* select ::= select multiselect_op oneselect */ { - if( yymsp[0].minor.yy387 ){ - yymsp[0].minor.yy387->op = (u8)yymsp[-1].minor.yy4; - yymsp[0].minor.yy387->pPrior = yymsp[-2].minor.yy387; + if( yymsp[0].minor.yy159 ){ + yymsp[0].minor.yy159->op = (u8)yymsp[-1].minor.yy392; + yymsp[0].minor.yy159->pPrior = yymsp[-2].minor.yy159; }else{ - sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy159); } - yygotominor.yy387 = yymsp[0].minor.yy387; + yygotominor.yy159 = yymsp[0].minor.yy159; } break; case 116: /* multiselect_op ::= UNION ALL */ -{yygotominor.yy4 = TK_ALL;} +{yygotominor.yy392 = TK_ALL;} break; case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */ { - yygotominor.yy387 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy259,yymsp[-4].minor.yy314,yymsp[-3].minor.yy322,yymsp[-2].minor.yy314,yymsp[-1].minor.yy322,yymsp[-7].minor.yy4,yymsp[0].minor.yy292.pLimit,yymsp[0].minor.yy292.pOffset); + yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset); } break; case 122: /* sclp ::= selcollist COMMA */ - case 247: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==247); -{yygotominor.yy322 = yymsp[-1].minor.yy322;} + case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246); +{yygotominor.yy442 = yymsp[-1].minor.yy442;} 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 246: /* idxlist_opt ::= */ yytestcase(yyruleno==246); -{yygotominor.yy322 = 0;} + case 158: /* groupby_opt ::= */ yytestcase(yyruleno==158); + case 239: /* exprlist ::= */ yytestcase(yyruleno==239); + case 245: /* idxlist_opt ::= */ yytestcase(yyruleno==245); +{yygotominor.yy442 = 0;} break; case 124: /* selcollist ::= sclp expr as */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, yymsp[-1].minor.yy118.pExpr); - if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[0].minor.yy0, 1); - sqlite3ExprListSetSpan(pParse,yygotominor.yy322,&yymsp[-1].minor.yy118); + yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy442, yymsp[-1].minor.yy342.pExpr); + if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[0].minor.yy0, 1); + sqlite3ExprListSetSpan(pParse,yygotominor.yy442,&yymsp[-1].minor.yy342); } break; case 125: /* selcollist ::= sclp STAR */ { Expr *p = sqlite3Expr(pParse->db, TK_ALL, 0); - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy322, p); + yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-1].minor.yy442, p); } break; case 126: /* selcollist ::= sclp nm DOT STAR */ @@ -109997,50 +111370,50 @@ static void yy_reduce( Expr *pRight = sqlite3PExpr(pParse, TK_ALL, 0, 0, &yymsp[0].minor.yy0); Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, pDot); + yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442, pDot); } break; case 129: /* as ::= */ {yygotominor.yy0.n = 0;} break; case 130: /* from ::= */ -{yygotominor.yy259 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy259));} +{yygotominor.yy347 = sqlite3DbMallocZero(pParse->db, sizeof(*yygotominor.yy347));} break; case 131: /* from ::= FROM seltablist */ { - yygotominor.yy259 = yymsp[0].minor.yy259; - sqlite3SrcListShiftJoinType(yygotominor.yy259); + yygotominor.yy347 = yymsp[0].minor.yy347; + sqlite3SrcListShiftJoinType(yygotominor.yy347); } break; case 132: /* stl_prefix ::= seltablist joinop */ { - yygotominor.yy259 = yymsp[-1].minor.yy259; - if( ALWAYS(yygotominor.yy259 && yygotominor.yy259->nSrc>0) ) yygotominor.yy259->a[yygotominor.yy259->nSrc-1].jointype = (u8)yymsp[0].minor.yy4; + yygotominor.yy347 = yymsp[-1].minor.yy347; + if( ALWAYS(yygotominor.yy347 && yygotominor.yy347->nSrc>0) ) yygotominor.yy347->a[yygotominor.yy347->nSrc-1].jointype = (u8)yymsp[0].minor.yy392; } break; case 133: /* stl_prefix ::= */ -{yygotominor.yy259 = 0;} +{yygotominor.yy347 = 0;} break; case 134: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */ { - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); - sqlite3SrcListIndexedBy(pParse, yygotominor.yy259, &yymsp[-2].minor.yy0); + yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); + sqlite3SrcListIndexedBy(pParse, yygotominor.yy347, &yymsp[-2].minor.yy0); } break; case 135: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */ { - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy387,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); + yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy159,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); } break; case 136: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */ { - if( yymsp[-6].minor.yy259==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy314==0 && yymsp[0].minor.yy384==0 ){ - yygotominor.yy259 = yymsp[-4].minor.yy259; + if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){ + yygotominor.yy347 = yymsp[-4].minor.yy347; }else{ Select *pSubquery; - sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy259); - pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy259,0,0,0,0,0,0,0); - yygotominor.yy259 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy259,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy314,yymsp[0].minor.yy384); + sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347); + pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0); + yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180); } } break; @@ -110049,322 +111422,340 @@ static void yy_reduce( {yygotominor.yy0.z=0; yygotominor.yy0.n=0;} break; case 139: /* fullname ::= nm dbnm */ -{yygotominor.yy259 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} +{yygotominor.yy347 = sqlite3SrcListAppend(pParse->db,0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);} break; case 140: /* joinop ::= COMMA|JOIN */ -{ yygotominor.yy4 = JT_INNER; } +{ yygotominor.yy392 = JT_INNER; } break; case 141: /* joinop ::= JOIN_KW JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } +{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } break; case 142: /* joinop ::= JOIN_KW nm JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } +{ yygotominor.yy392 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); } break; case 143: /* joinop ::= JOIN_KW nm nm JOIN */ -{ yygotominor.yy4 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0); } +{ yygotominor.yy392 = sqlite3JoinType(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.yy314 = yymsp[0].minor.yy118.pExpr;} + case 161: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==161); + case 168: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==168); + case 234: /* case_else ::= ELSE expr */ yytestcase(yyruleno==234); + case 236: /* case_operand ::= expr */ yytestcase(yyruleno==236); +{yygotominor.yy122 = yymsp[0].minor.yy342.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.yy314 = 0;} + case 160: /* having_opt ::= */ yytestcase(yyruleno==160); + case 167: /* where_opt ::= */ yytestcase(yyruleno==167); + case 235: /* case_else ::= */ yytestcase(yyruleno==235); + case 237: /* case_operand ::= */ yytestcase(yyruleno==237); +{yygotominor.yy122 = 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.yy384 = yymsp[-1].minor.yy384;} + case 180: /* inscollist_opt ::= LP inscollist RP */ yytestcase(yyruleno==180); +{yygotominor.yy180 = yymsp[-1].minor.yy180;} break; case 150: /* using_opt ::= */ - case 180: /* inscollist_opt ::= */ yytestcase(yyruleno==180); -{yygotominor.yy384 = 0;} + case 179: /* inscollist_opt ::= */ yytestcase(yyruleno==179); +{yygotominor.yy180 = 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); -{yygotominor.yy322 = yymsp[0].minor.yy322;} + case 159: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==159); + case 238: /* exprlist ::= nexprlist */ yytestcase(yyruleno==238); +{yygotominor.yy442 = yymsp[0].minor.yy442;} break; - case 153: /* sortlist ::= sortlist COMMA sortitem sortorder */ + case 153: /* sortlist ::= sortlist COMMA expr sortorder */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322,yymsp[-1].minor.yy314); - if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4; + yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy442,yymsp[-1].minor.yy342.pExpr); + if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; } break; - case 154: /* sortlist ::= sortitem sortorder */ + case 154: /* sortlist ::= expr sortorder */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy314); - if( yygotominor.yy322 && ALWAYS(yygotominor.yy322->a) ) yygotominor.yy322->a[0].sortOrder = (u8)yymsp[0].minor.yy4; + yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy342.pExpr); + if( yygotominor.yy442 && ALWAYS(yygotominor.yy442->a) ) yygotominor.yy442->a[0].sortOrder = (u8)yymsp[0].minor.yy392; } break; - case 156: /* sortorder ::= ASC */ - case 158: /* sortorder ::= */ yytestcase(yyruleno==158); -{yygotominor.yy4 = SQLITE_SO_ASC;} + case 155: /* sortorder ::= ASC */ + case 157: /* sortorder ::= */ yytestcase(yyruleno==157); +{yygotominor.yy392 = SQLITE_SO_ASC;} break; - case 157: /* sortorder ::= DESC */ -{yygotominor.yy4 = SQLITE_SO_DESC;} + case 156: /* sortorder ::= DESC */ +{yygotominor.yy392 = SQLITE_SO_DESC;} break; - case 163: /* limit_opt ::= */ -{yygotominor.yy292.pLimit = 0; yygotominor.yy292.pOffset = 0;} + case 162: /* limit_opt ::= */ +{yygotominor.yy64.pLimit = 0; yygotominor.yy64.pOffset = 0;} break; - case 164: /* limit_opt ::= LIMIT expr */ -{yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr; yygotominor.yy292.pOffset = 0;} + case 163: /* limit_opt ::= LIMIT expr */ +{yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr; yygotominor.yy64.pOffset = 0;} break; - case 165: /* limit_opt ::= LIMIT expr OFFSET expr */ -{yygotominor.yy292.pLimit = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pOffset = yymsp[0].minor.yy118.pExpr;} + case 164: /* limit_opt ::= LIMIT expr OFFSET expr */ +{yygotominor.yy64.pLimit = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pOffset = yymsp[0].minor.yy342.pExpr;} break; - case 166: /* limit_opt ::= LIMIT expr COMMA expr */ -{yygotominor.yy292.pOffset = yymsp[-2].minor.yy118.pExpr; yygotominor.yy292.pLimit = yymsp[0].minor.yy118.pExpr;} + case 165: /* limit_opt ::= LIMIT expr COMMA expr */ +{yygotominor.yy64.pOffset = yymsp[-2].minor.yy342.pExpr; yygotominor.yy64.pLimit = yymsp[0].minor.yy342.pExpr;} break; - case 167: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */ + case 166: /* cmd ::= DELETE FROM fullname indexed_opt where_opt */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy259, &yymsp[-1].minor.yy0); - sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy259,yymsp[0].minor.yy314); + sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy347, &yymsp[-1].minor.yy0); + sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy347,yymsp[0].minor.yy122); } break; - case 170: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */ + case 169: /* cmd ::= UPDATE orconf fullname indexed_opt SET setlist where_opt */ { - sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy259, &yymsp[-3].minor.yy0); - sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy322,"set list"); - sqlite3Update(pParse,yymsp[-4].minor.yy259,yymsp[-1].minor.yy322,yymsp[0].minor.yy314,yymsp[-5].minor.yy210); + sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy347, &yymsp[-3].minor.yy0); + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy442,"set list"); + sqlite3Update(pParse,yymsp[-4].minor.yy347,yymsp[-1].minor.yy442,yymsp[0].minor.yy122,yymsp[-5].minor.yy258); } break; - case 171: /* setlist ::= setlist COMMA nm EQ expr */ + case 170: /* setlist ::= setlist COMMA nm EQ expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy118.pExpr); - sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1); + yygotominor.yy442 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy442, yymsp[0].minor.yy342.pExpr); + sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); } break; - case 172: /* setlist ::= nm EQ expr */ + case 171: /* setlist ::= nm EQ expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy118.pExpr); - sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1); + yygotominor.yy442 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy342.pExpr); + sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); } break; - case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP */ -{sqlite3Insert(pParse, yymsp[-5].minor.yy259, yymsp[-1].minor.yy322, 0, yymsp[-4].minor.yy384, yymsp[-7].minor.yy210);} + case 172: /* cmd ::= insert_cmd INTO fullname inscollist_opt valuelist */ +{sqlite3Insert(pParse, yymsp[-2].minor.yy347, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);} break; - case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */ -{sqlite3Insert(pParse, yymsp[-2].minor.yy259, 0, yymsp[0].minor.yy387, yymsp[-1].minor.yy384, yymsp[-4].minor.yy210);} + case 173: /* cmd ::= insert_cmd INTO fullname inscollist_opt select */ +{sqlite3Insert(pParse, yymsp[-2].minor.yy347, 0, yymsp[0].minor.yy159, yymsp[-1].minor.yy180, yymsp[-4].minor.yy258);} break; - case 175: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */ -{sqlite3Insert(pParse, yymsp[-3].minor.yy259, 0, 0, yymsp[-2].minor.yy384, yymsp[-5].minor.yy210);} + case 174: /* cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES */ +{sqlite3Insert(pParse, yymsp[-3].minor.yy347, 0, 0, yymsp[-2].minor.yy180, yymsp[-5].minor.yy258);} break; - case 176: /* insert_cmd ::= INSERT orconf */ -{yygotominor.yy210 = yymsp[0].minor.yy210;} + case 175: /* insert_cmd ::= INSERT orconf */ +{yygotominor.yy258 = yymsp[0].minor.yy258;} break; - case 177: /* insert_cmd ::= REPLACE */ -{yygotominor.yy210 = OE_Replace;} + case 176: /* insert_cmd ::= REPLACE */ +{yygotominor.yy258 = OE_Replace;} break; - case 178: /* itemlist ::= itemlist COMMA expr */ - case 241: /* nexprlist ::= nexprlist COMMA expr */ yytestcase(yyruleno==241); -{yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy118.pExpr);} + case 177: /* valuelist ::= VALUES LP nexprlist RP */ +{ + yygotominor.yy487.pList = yymsp[-1].minor.yy442; + yygotominor.yy487.pSelect = 0; +} break; - case 179: /* itemlist ::= expr */ - case 242: /* nexprlist ::= expr */ yytestcase(yyruleno==242); -{yygotominor.yy322 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy118.pExpr);} + case 178: /* valuelist ::= valuelist COMMA LP exprlist RP */ +{ + Select *pRight = sqlite3SelectNew(pParse, yymsp[-1].minor.yy442, 0, 0, 0, 0, 0, 0, 0, 0); + if( yymsp[-4].minor.yy487.pList ){ + yymsp[-4].minor.yy487.pSelect = sqlite3SelectNew(pParse, yymsp[-4].minor.yy487.pList, 0, 0, 0, 0, 0, 0, 0, 0); + yymsp[-4].minor.yy487.pList = 0; + } + yygotominor.yy487.pList = 0; + if( yymsp[-4].minor.yy487.pSelect==0 || pRight==0 ){ + sqlite3SelectDelete(pParse->db, pRight); + sqlite3SelectDelete(pParse->db, yymsp[-4].minor.yy487.pSelect); + yygotominor.yy487.pSelect = 0; + }else{ + pRight->op = TK_ALL; + pRight->pPrior = yymsp[-4].minor.yy487.pSelect; + pRight->selFlags |= SF_Values; + pRight->pPrior->selFlags |= SF_Values; + yygotominor.yy487.pSelect = pRight; + } +} break; - case 182: /* inscollist ::= inscollist COMMA nm */ -{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy384,&yymsp[0].minor.yy0);} + case 181: /* inscollist ::= inscollist COMMA nm */ +{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,yymsp[-2].minor.yy180,&yymsp[0].minor.yy0);} break; - case 183: /* inscollist ::= nm */ -{yygotominor.yy384 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} + case 182: /* inscollist ::= nm */ +{yygotominor.yy180 = sqlite3IdListAppend(pParse->db,0,&yymsp[0].minor.yy0);} break; - case 184: /* expr ::= term */ -{yygotominor.yy118 = yymsp[0].minor.yy118;} + case 183: /* expr ::= term */ +{yygotominor.yy342 = yymsp[0].minor.yy342;} break; - case 185: /* expr ::= LP expr RP */ -{yygotominor.yy118.pExpr = yymsp[-1].minor.yy118.pExpr; spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);} + case 184: /* expr ::= LP expr RP */ +{yygotominor.yy342.pExpr = yymsp[-1].minor.yy342.pExpr; spanSet(&yygotominor.yy342,&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.yy118, pParse, yymsp[0].major, &yymsp[0].minor.yy0);} + case 185: /* term ::= NULL */ + case 190: /* term ::= INTEGER|FLOAT|BLOB */ yytestcase(yyruleno==190); + case 191: /* term ::= STRING */ yytestcase(yyruleno==191); +{spanExpr(&yygotominor.yy342, pParse, yymsp[0].major, &yymsp[0].minor.yy0);} break; - case 187: /* expr ::= id */ - case 188: /* expr ::= JOIN_KW */ yytestcase(yyruleno==188); -{spanExpr(&yygotominor.yy118, pParse, TK_ID, &yymsp[0].minor.yy0);} + case 186: /* expr ::= id */ + case 187: /* expr ::= JOIN_KW */ yytestcase(yyruleno==187); +{spanExpr(&yygotominor.yy342, pParse, TK_ID, &yymsp[0].minor.yy0);} break; - case 189: /* expr ::= nm DOT nm */ + case 188: /* expr ::= nm DOT nm */ { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); - spanSet(&yygotominor.yy118,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0); + spanSet(&yygotominor.yy342,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } break; - case 190: /* expr ::= nm DOT nm DOT nm */ + case 189: /* expr ::= nm DOT nm DOT nm */ { Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-4].minor.yy0); Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[-2].minor.yy0); Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &yymsp[0].minor.yy0); Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); - spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0); + spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); } break; - case 193: /* expr ::= REGISTER */ + case 192: /* 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 ){ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = 0; + yygotominor.yy342.pExpr = 0; }else{ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0); - if( yygotominor.yy118.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy118.pExpr->iTable); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &yymsp[0].minor.yy0); + if( yygotominor.yy342.pExpr ) sqlite3GetInt32(&yymsp[0].minor.yy0.z[1], &yygotominor.yy342.pExpr->iTable); } - spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; - case 194: /* expr ::= VARIABLE */ + case 193: /* expr ::= VARIABLE */ { - spanExpr(&yygotominor.yy118, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); - sqlite3ExprAssignVarNumber(pParse, yygotominor.yy118.pExpr); - spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + spanExpr(&yygotominor.yy342, pParse, TK_VARIABLE, &yymsp[0].minor.yy0); + sqlite3ExprAssignVarNumber(pParse, yygotominor.yy342.pExpr); + spanSet(&yygotominor.yy342, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); } break; - case 195: /* expr ::= expr COLLATE ids */ + case 194: /* expr ::= expr COLLATE ids */ { - yygotominor.yy118.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy118.pExpr, &yymsp[0].minor.yy0); - yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy342.pExpr = sqlite3ExprSetCollByToken(pParse, yymsp[-2].minor.yy342.pExpr, &yymsp[0].minor.yy0); + yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; + yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 196: /* expr ::= CAST LP expr AS typetoken RP */ + case 195: /* expr ::= CAST LP expr AS typetoken RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy118.pExpr, 0, &yymsp[-1].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CAST, yymsp[-3].minor.yy342.pExpr, 0, &yymsp[-1].minor.yy0); + spanSet(&yygotominor.yy342,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); } break; - case 197: /* expr ::= ID LP distinct exprlist RP */ + case 196: /* expr ::= ID LP distinct exprlist RP */ { - if( yymsp[-1].minor.yy322 && yymsp[-1].minor.yy322->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ + if( yymsp[-1].minor.yy442 && yymsp[-1].minor.yy442->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){ sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); } - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); - if( yymsp[-2].minor.yy4 && yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->flags |= EP_Distinct; + yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0); + spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->flags |= EP_Distinct; } } break; - case 198: /* expr ::= ID LP STAR RP */ + case 197: /* expr ::= ID LP STAR RP */ { - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); - spanSet(&yygotominor.yy118,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0); + spanSet(&yygotominor.yy342,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); } break; - case 199: /* term ::= CTIME_KW */ + case 198: /* term ::= CTIME_KW */ { /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are ** treated as functions that return constants */ - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->op = TK_CONST_FUNC; + yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, 0,&yymsp[0].minor.yy0); + if( yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->op = TK_CONST_FUNC; } - spanSet(&yygotominor.yy118, &yymsp[0].minor.yy0, &yymsp[0].minor.yy0); + spanSet(&yygotominor.yy342, &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.yy118,pParse,yymsp[-1].major,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118);} + case 199: /* expr ::= expr AND expr */ + case 200: /* expr ::= expr OR expr */ yytestcase(yyruleno==200); + case 201: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==201); + case 202: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==202); + case 203: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==203); + case 204: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==204); + case 205: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==205); + case 206: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==206); +{spanBinaryExpr(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342);} break; - case 208: /* likeop ::= LIKE_KW */ - case 210: /* likeop ::= MATCH */ yytestcase(yyruleno==210); -{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.not = 0;} + case 207: /* likeop ::= LIKE_KW */ + case 209: /* likeop ::= MATCH */ yytestcase(yyruleno==209); +{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 0;} break; - case 209: /* likeop ::= NOT LIKE_KW */ - case 211: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==211); -{yygotominor.yy342.eOperator = yymsp[0].minor.yy0; yygotominor.yy342.not = 1;} + case 208: /* likeop ::= NOT LIKE_KW */ + case 210: /* likeop ::= NOT MATCH */ yytestcase(yyruleno==210); +{yygotominor.yy318.eOperator = yymsp[0].minor.yy0; yygotominor.yy318.bNot = 1;} break; - case 212: /* expr ::= expr likeop expr */ + case 211: /* expr ::= expr likeop expr */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy342.eOperator); - if( yymsp[-1].minor.yy342.not ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-2].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; - if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy342.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy342.pExpr); + yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy318.eOperator); + if( yymsp[-1].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); + yygotominor.yy342.zStart = yymsp[-2].minor.yy342.zStart; + yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; + if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc; } break; - case 213: /* expr ::= expr likeop expr ESCAPE expr */ + case 212: /* expr ::= expr likeop expr ESCAPE expr */ { ExprList *pList; - pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy342.eOperator); - if( yymsp[-3].minor.yy342.not ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; - if( yygotominor.yy118.pExpr ) yygotominor.yy118.pExpr->flags |= EP_InfixFunc; + pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy342.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr); + yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy318.eOperator); + if( yymsp[-3].minor.yy318.bNot ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); + yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart; + yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; + if( yygotominor.yy342.pExpr ) yygotominor.yy342.pExpr->flags |= EP_InfixFunc; } break; - case 214: /* expr ::= expr ISNULL|NOTNULL */ -{spanUnaryPostfix(&yygotominor.yy118,pParse,yymsp[0].major,&yymsp[-1].minor.yy118,&yymsp[0].minor.yy0);} + case 213: /* expr ::= expr ISNULL|NOTNULL */ +{spanUnaryPostfix(&yygotominor.yy342,pParse,yymsp[0].major,&yymsp[-1].minor.yy342,&yymsp[0].minor.yy0);} break; - case 215: /* expr ::= expr NOT NULL */ -{spanUnaryPostfix(&yygotominor.yy118,pParse,TK_NOTNULL,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy0);} + case 214: /* expr ::= expr NOT NULL */ +{spanUnaryPostfix(&yygotominor.yy342,pParse,TK_NOTNULL,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy0);} break; - case 216: /* expr ::= expr IS expr */ + case 215: /* expr ::= expr IS expr */ { - spanBinaryExpr(&yygotominor.yy118,pParse,TK_IS,&yymsp[-2].minor.yy118,&yymsp[0].minor.yy118); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_ISNULL); + spanBinaryExpr(&yygotominor.yy342,pParse,TK_IS,&yymsp[-2].minor.yy342,&yymsp[0].minor.yy342); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_ISNULL); } break; - case 217: /* expr ::= expr IS NOT expr */ + case 216: /* expr ::= expr IS NOT expr */ { - spanBinaryExpr(&yygotominor.yy118,pParse,TK_ISNOT,&yymsp[-3].minor.yy118,&yymsp[0].minor.yy118); - binaryToUnaryIfNull(pParse, yymsp[0].minor.yy118.pExpr, yygotominor.yy118.pExpr, TK_NOTNULL); + spanBinaryExpr(&yygotominor.yy342,pParse,TK_ISNOT,&yymsp[-3].minor.yy342,&yymsp[0].minor.yy342); + binaryToUnaryIfNull(pParse, yymsp[0].minor.yy342.pExpr, yygotominor.yy342.pExpr, TK_NOTNULL); } break; - case 218: /* expr ::= NOT expr */ - case 219: /* expr ::= BITNOT expr */ yytestcase(yyruleno==219); -{spanUnaryPrefix(&yygotominor.yy118,pParse,yymsp[-1].major,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 217: /* expr ::= NOT expr */ + case 218: /* expr ::= BITNOT expr */ yytestcase(yyruleno==218); +{spanUnaryPrefix(&yygotominor.yy342,pParse,yymsp[-1].major,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);} break; - case 220: /* expr ::= MINUS expr */ -{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UMINUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 219: /* expr ::= MINUS expr */ +{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UMINUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);} break; - case 221: /* expr ::= PLUS expr */ -{spanUnaryPrefix(&yygotominor.yy118,pParse,TK_UPLUS,&yymsp[0].minor.yy118,&yymsp[-1].minor.yy0);} + case 220: /* expr ::= PLUS expr */ +{spanUnaryPrefix(&yygotominor.yy342,pParse,TK_UPLUS,&yymsp[0].minor.yy342,&yymsp[-1].minor.yy0);} break; - case 224: /* expr ::= expr between_op expr AND expr */ + case 223: /* expr ::= expr between_op expr AND expr */ { - ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy118.pExpr); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = pList; + ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); + pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy342.pExpr); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy342.pExpr, 0, 0); + if( yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } - if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = yymsp[0].minor.yy118.zEnd; + if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); + yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart; + yygotominor.yy342.zEnd = yymsp[0].minor.yy342.zEnd; } break; - case 227: /* expr ::= expr in_op LP exprlist RP */ + case 226: /* expr ::= expr in_op LP exprlist RP */ { - if( yymsp[-1].minor.yy322==0 ){ + if( yymsp[-1].minor.yy442==0 ){ /* Expressions of the form ** ** expr1 IN () @@ -110373,226 +111764,232 @@ static void yy_reduce( ** simplify to constants 0 (false) and 1 (true), respectively, ** regardless of the value of expr1. */ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy4]); - sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy118.pExpr); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[yymsp[-3].minor.yy392]); + sqlite3ExprDelete(pParse->db, yymsp[-4].minor.yy342.pExpr); }else{ - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = yymsp[-1].minor.yy322; - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0); + if( yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->x.pList = yymsp[-1].minor.yy442; + sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322); + sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy442); } - if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); + if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); } - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart; + yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 228: /* expr ::= LP select RP */ + case 227: /* expr ::= LP select RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387; - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); + if( yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159; + ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); } - yygotominor.yy118.zStart = yymsp[-2].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy342.zStart = yymsp[-2].minor.yy0.z; + yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 229: /* expr ::= expr in_op LP select RP */ + case 228: /* expr ::= expr in_op LP select RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = yymsp[-1].minor.yy387; - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy342.pExpr, 0, 0); + if( yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->x.pSelect = yymsp[-1].minor.yy159; + ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); } - if( yymsp[-3].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-4].minor.yy118.zStart; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + if( yymsp[-3].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); + yygotominor.yy342.zStart = yymsp[-4].minor.yy342.zStart; + yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 230: /* expr ::= expr in_op nm dbnm */ + case 229: /* expr ::= expr in_op nm dbnm */ { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0); - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy118.pExpr, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); - ExprSetProperty(yygotominor.yy118.pExpr, EP_xIsSelect); - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy342.pExpr, 0, 0); + if( yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); + ExprSetProperty(yygotominor.yy342.pExpr, EP_xIsSelect); + sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } - if( yymsp[-2].minor.yy4 ) yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy118.pExpr, 0, 0); - yygotominor.yy118.zStart = yymsp[-3].minor.yy118.zStart; - yygotominor.yy118.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]; + if( yymsp[-2].minor.yy392 ) yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_NOT, yygotominor.yy342.pExpr, 0, 0); + yygotominor.yy342.zStart = yymsp[-3].minor.yy342.zStart; + yygotominor.yy342.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 */ + case 230: /* expr ::= EXISTS LP select RP */ { - Expr *p = yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); + Expr *p = yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ - p->x.pSelect = yymsp[-1].minor.yy387; + p->x.pSelect = yymsp[-1].minor.yy159; ExprSetProperty(p, EP_xIsSelect); sqlite3ExprSetHeight(pParse, p); }else{ - sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy387); + sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy159); } - yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z; + yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 232: /* expr ::= CASE case_operand case_exprlist case_else END */ + case 231: /* expr ::= CASE case_operand case_exprlist case_else END */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy314, yymsp[-1].minor.yy314, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->x.pList = yymsp[-2].minor.yy322; - sqlite3ExprSetHeight(pParse, yygotominor.yy118.pExpr); + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy122, yymsp[-1].minor.yy122, 0); + if( yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->x.pList = yymsp[-2].minor.yy442; + sqlite3ExprSetHeight(pParse, yygotominor.yy342.pExpr); }else{ - sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322); + sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy442); } - yygotominor.yy118.zStart = yymsp[-4].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy342.zStart = yymsp[-4].minor.yy0.z; + yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 233: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ + case 232: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr); + yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, yymsp[-2].minor.yy342.pExpr); + yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr); } break; - case 234: /* case_exprlist ::= WHEN expr THEN expr */ + case 233: /* case_exprlist ::= WHEN expr THEN expr */ { - yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy118.pExpr); - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yygotominor.yy322, yymsp[0].minor.yy118.pExpr); + yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy342.pExpr); + yygotominor.yy442 = sqlite3ExprListAppend(pParse,yygotominor.yy442, yymsp[0].minor.yy342.pExpr); } break; - case 243: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */ + case 240: /* nexprlist ::= nexprlist COMMA expr */ +{yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy442,yymsp[0].minor.yy342.pExpr);} + break; + case 241: /* nexprlist ::= expr */ +{yygotominor.yy442 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy342.pExpr);} + break; + case 242: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP */ { sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy0, &yymsp[-5].minor.yy0, - sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy322, yymsp[-9].minor.yy4, - &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy4); + sqlite3SrcListAppend(pParse->db,0,&yymsp[-3].minor.yy0,0), yymsp[-1].minor.yy442, yymsp[-9].minor.yy392, + &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy392); } break; - case 244: /* uniqueflag ::= UNIQUE */ - case 298: /* raisetype ::= ABORT */ yytestcase(yyruleno==298); -{yygotominor.yy4 = OE_Abort;} + case 243: /* uniqueflag ::= UNIQUE */ + case 296: /* raisetype ::= ABORT */ yytestcase(yyruleno==296); +{yygotominor.yy392 = OE_Abort;} break; - case 245: /* uniqueflag ::= */ -{yygotominor.yy4 = OE_None;} + case 244: /* uniqueflag ::= */ +{yygotominor.yy392 = OE_None;} break; - case 248: /* idxlist ::= idxlist COMMA nm collate sortorder */ + case 247: /* idxlist ::= idxlist COMMA nm collate sortorder */ { Expr *p = 0; if( yymsp[-1].minor.yy0.n>0 ){ p = sqlite3Expr(pParse->db, TK_COLUMN, 0); sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); } - yygotominor.yy322 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, p); - sqlite3ExprListSetName(pParse,yygotominor.yy322,&yymsp[-2].minor.yy0,1); - sqlite3ExprListCheckLength(pParse, yygotominor.yy322, "index"); - if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4; + yygotominor.yy442 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy442, p); + sqlite3ExprListSetName(pParse,yygotominor.yy442,&yymsp[-2].minor.yy0,1); + sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); + if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; } break; - case 249: /* idxlist ::= nm collate sortorder */ + case 248: /* idxlist ::= nm collate sortorder */ { Expr *p = 0; if( yymsp[-1].minor.yy0.n>0 ){ p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0); sqlite3ExprSetCollByToken(pParse, p, &yymsp[-1].minor.yy0); } - yygotominor.yy322 = sqlite3ExprListAppend(pParse,0, p); - sqlite3ExprListSetName(pParse, yygotominor.yy322, &yymsp[-2].minor.yy0, 1); - sqlite3ExprListCheckLength(pParse, yygotominor.yy322, "index"); - if( yygotominor.yy322 ) yygotominor.yy322->a[yygotominor.yy322->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy4; + yygotominor.yy442 = sqlite3ExprListAppend(pParse,0, p); + sqlite3ExprListSetName(pParse, yygotominor.yy442, &yymsp[-2].minor.yy0, 1); + sqlite3ExprListCheckLength(pParse, yygotominor.yy442, "index"); + if( yygotominor.yy442 ) yygotominor.yy442->a[yygotominor.yy442->nExpr-1].sortOrder = (u8)yymsp[0].minor.yy392; } break; - case 250: /* collate ::= */ + case 249: /* collate ::= */ {yygotominor.yy0.z = 0; yygotominor.yy0.n = 0;} break; - case 252: /* cmd ::= DROP INDEX ifexists fullname */ -{sqlite3DropIndex(pParse, yymsp[0].minor.yy259, yymsp[-1].minor.yy4);} + case 251: /* cmd ::= DROP INDEX ifexists fullname */ +{sqlite3DropIndex(pParse, yymsp[0].minor.yy347, yymsp[-1].minor.yy392);} break; - case 253: /* cmd ::= VACUUM */ - case 254: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==254); + case 252: /* cmd ::= VACUUM */ + case 253: /* cmd ::= VACUUM nm */ yytestcase(yyruleno==253); {sqlite3Vacuum(pParse);} break; - case 255: /* cmd ::= PRAGMA nm dbnm */ + case 254: /* cmd ::= PRAGMA nm dbnm */ {sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);} break; - case 256: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ + case 255: /* cmd ::= PRAGMA nm dbnm EQ nmnum */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);} break; - case 257: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ + case 256: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);} break; - case 258: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ + case 257: /* cmd ::= PRAGMA nm dbnm EQ minus_num */ {sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);} break; - case 259: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ + case 258: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */ {sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);} break; - case 270: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */ + case 268: /* 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; - sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy203, &all); + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy327, &all); } break; - case 271: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ + case 269: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */ { - sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy4, yymsp[-4].minor.yy90.a, yymsp[-4].minor.yy90.b, yymsp[-2].minor.yy259, yymsp[0].minor.yy314, yymsp[-10].minor.yy4, yymsp[-8].minor.yy4); + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy392, yymsp[-4].minor.yy410.a, yymsp[-4].minor.yy410.b, yymsp[-2].minor.yy347, yymsp[0].minor.yy122, yymsp[-10].minor.yy392, yymsp[-8].minor.yy392); yygotominor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); } break; - case 272: /* trigger_time ::= BEFORE */ - case 275: /* trigger_time ::= */ yytestcase(yyruleno==275); -{ yygotominor.yy4 = TK_BEFORE; } + case 270: /* trigger_time ::= BEFORE */ + case 273: /* trigger_time ::= */ yytestcase(yyruleno==273); +{ yygotominor.yy392 = TK_BEFORE; } break; - case 273: /* trigger_time ::= AFTER */ -{ yygotominor.yy4 = TK_AFTER; } + case 271: /* trigger_time ::= AFTER */ +{ yygotominor.yy392 = TK_AFTER; } break; - case 274: /* trigger_time ::= INSTEAD OF */ -{ yygotominor.yy4 = TK_INSTEAD;} + case 272: /* trigger_time ::= INSTEAD OF */ +{ yygotominor.yy392 = TK_INSTEAD;} break; - case 276: /* trigger_event ::= DELETE|INSERT */ - case 277: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==277); -{yygotominor.yy90.a = yymsp[0].major; yygotominor.yy90.b = 0;} + case 274: /* trigger_event ::= DELETE|INSERT */ + case 275: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==275); +{yygotominor.yy410.a = yymsp[0].major; yygotominor.yy410.b = 0;} break; - case 278: /* trigger_event ::= UPDATE OF inscollist */ -{yygotominor.yy90.a = TK_UPDATE; yygotominor.yy90.b = yymsp[0].minor.yy384;} + case 276: /* trigger_event ::= UPDATE OF inscollist */ +{yygotominor.yy410.a = TK_UPDATE; yygotominor.yy410.b = yymsp[0].minor.yy180;} break; - case 281: /* when_clause ::= */ - case 303: /* key_opt ::= */ yytestcase(yyruleno==303); -{ yygotominor.yy314 = 0; } + case 279: /* when_clause ::= */ + case 301: /* key_opt ::= */ yytestcase(yyruleno==301); +{ yygotominor.yy122 = 0; } break; - case 282: /* when_clause ::= WHEN expr */ - case 304: /* key_opt ::= KEY expr */ yytestcase(yyruleno==304); -{ yygotominor.yy314 = yymsp[0].minor.yy118.pExpr; } + case 280: /* when_clause ::= WHEN expr */ + case 302: /* key_opt ::= KEY expr */ yytestcase(yyruleno==302); +{ yygotominor.yy122 = yymsp[0].minor.yy342.pExpr; } break; - case 283: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ + case 281: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */ { - assert( yymsp[-2].minor.yy203!=0 ); - yymsp[-2].minor.yy203->pLast->pNext = yymsp[-1].minor.yy203; - yymsp[-2].minor.yy203->pLast = yymsp[-1].minor.yy203; - yygotominor.yy203 = yymsp[-2].minor.yy203; + assert( yymsp[-2].minor.yy327!=0 ); + yymsp[-2].minor.yy327->pLast->pNext = yymsp[-1].minor.yy327; + yymsp[-2].minor.yy327->pLast = yymsp[-1].minor.yy327; + yygotominor.yy327 = yymsp[-2].minor.yy327; } break; - case 284: /* trigger_cmd_list ::= trigger_cmd SEMI */ + case 282: /* trigger_cmd_list ::= trigger_cmd SEMI */ { - assert( yymsp[-1].minor.yy203!=0 ); - yymsp[-1].minor.yy203->pLast = yymsp[-1].minor.yy203; - yygotominor.yy203 = yymsp[-1].minor.yy203; + assert( yymsp[-1].minor.yy327!=0 ); + yymsp[-1].minor.yy327->pLast = yymsp[-1].minor.yy327; + yygotominor.yy327 = yymsp[-1].minor.yy327; } break; - case 286: /* trnm ::= nm DOT nm */ + case 284: /* trnm ::= nm DOT nm */ { yygotominor.yy0 = yymsp[0].minor.yy0; sqlite3ErrorMsg(pParse, @@ -110600,121 +111997,121 @@ static void yy_reduce( "statements within triggers"); } break; - case 288: /* tridxby ::= INDEXED BY nm */ + case 286: /* tridxby ::= INDEXED BY nm */ { sqlite3ErrorMsg(pParse, "the INDEXED BY clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 289: /* tridxby ::= NOT INDEXED */ + case 287: /* tridxby ::= NOT INDEXED */ { sqlite3ErrorMsg(pParse, "the NOT INDEXED clause is not allowed on UPDATE or DELETE statements " "within triggers"); } break; - case 290: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ -{ yygotominor.yy203 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy322, yymsp[0].minor.yy314, yymsp[-5].minor.yy210); } + case 288: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt */ +{ yygotominor.yy327 = sqlite3TriggerUpdateStep(pParse->db, &yymsp[-4].minor.yy0, yymsp[-1].minor.yy442, yymsp[0].minor.yy122, yymsp[-5].minor.yy258); } break; - case 291: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt VALUES LP itemlist RP */ -{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy384, yymsp[-1].minor.yy322, 0, yymsp[-7].minor.yy210);} + case 289: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt valuelist */ +{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, yymsp[0].minor.yy487.pList, yymsp[0].minor.yy487.pSelect, yymsp[-4].minor.yy258);} break; - case 292: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */ -{yygotominor.yy203 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy384, 0, yymsp[0].minor.yy387, yymsp[-4].minor.yy210);} + case 290: /* trigger_cmd ::= insert_cmd INTO trnm inscollist_opt select */ +{yygotominor.yy327 = sqlite3TriggerInsertStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy180, 0, yymsp[0].minor.yy159, yymsp[-4].minor.yy258);} break; - case 293: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ -{yygotominor.yy203 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy314);} + case 291: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt */ +{yygotominor.yy327 = sqlite3TriggerDeleteStep(pParse->db, &yymsp[-2].minor.yy0, yymsp[0].minor.yy122);} break; - case 294: /* trigger_cmd ::= select */ -{yygotominor.yy203 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy387); } + case 292: /* trigger_cmd ::= select */ +{yygotominor.yy327 = sqlite3TriggerSelectStep(pParse->db, yymsp[0].minor.yy159); } break; - case 295: /* expr ::= RAISE LP IGNORE RP */ + case 293: /* expr ::= RAISE LP IGNORE RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); - if( yygotominor.yy118.pExpr ){ - yygotominor.yy118.pExpr->affinity = OE_Ignore; + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0); + if( yygotominor.yy342.pExpr ){ + yygotominor.yy342.pExpr->affinity = OE_Ignore; } - yygotominor.yy118.zStart = yymsp[-3].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy342.zStart = yymsp[-3].minor.yy0.z; + yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 296: /* expr ::= RAISE LP raisetype COMMA nm RP */ + case 294: /* expr ::= RAISE LP raisetype COMMA nm RP */ { - yygotominor.yy118.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); - if( yygotominor.yy118.pExpr ) { - yygotominor.yy118.pExpr->affinity = (char)yymsp[-3].minor.yy4; + yygotominor.yy342.pExpr = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &yymsp[-1].minor.yy0); + if( yygotominor.yy342.pExpr ) { + yygotominor.yy342.pExpr->affinity = (char)yymsp[-3].minor.yy392; } - yygotominor.yy118.zStart = yymsp[-5].minor.yy0.z; - yygotominor.yy118.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; + yygotominor.yy342.zStart = yymsp[-5].minor.yy0.z; + yygotominor.yy342.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n]; } break; - case 297: /* raisetype ::= ROLLBACK */ -{yygotominor.yy4 = OE_Rollback;} + case 295: /* raisetype ::= ROLLBACK */ +{yygotominor.yy392 = OE_Rollback;} break; - case 299: /* raisetype ::= FAIL */ -{yygotominor.yy4 = OE_Fail;} + case 297: /* raisetype ::= FAIL */ +{yygotominor.yy392 = OE_Fail;} break; - case 300: /* cmd ::= DROP TRIGGER ifexists fullname */ + case 298: /* cmd ::= DROP TRIGGER ifexists fullname */ { - sqlite3DropTrigger(pParse,yymsp[0].minor.yy259,yymsp[-1].minor.yy4); + sqlite3DropTrigger(pParse,yymsp[0].minor.yy347,yymsp[-1].minor.yy392); } break; - case 301: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ + case 299: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */ { - sqlite3Attach(pParse, yymsp[-3].minor.yy118.pExpr, yymsp[-1].minor.yy118.pExpr, yymsp[0].minor.yy314); + sqlite3Attach(pParse, yymsp[-3].minor.yy342.pExpr, yymsp[-1].minor.yy342.pExpr, yymsp[0].minor.yy122); } break; - case 302: /* cmd ::= DETACH database_kw_opt expr */ + case 300: /* cmd ::= DETACH database_kw_opt expr */ { - sqlite3Detach(pParse, yymsp[0].minor.yy118.pExpr); + sqlite3Detach(pParse, yymsp[0].minor.yy342.pExpr); } break; - case 307: /* cmd ::= REINDEX */ + case 305: /* cmd ::= REINDEX */ {sqlite3Reindex(pParse, 0, 0);} break; - case 308: /* cmd ::= REINDEX nm dbnm */ + case 306: /* cmd ::= REINDEX nm dbnm */ {sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 309: /* cmd ::= ANALYZE */ + case 307: /* cmd ::= ANALYZE */ {sqlite3Analyze(pParse, 0, 0);} break; - case 310: /* cmd ::= ANALYZE nm dbnm */ + case 308: /* cmd ::= ANALYZE nm dbnm */ {sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);} break; - case 311: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ + case 309: /* cmd ::= ALTER TABLE fullname RENAME TO nm */ { - sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy259,&yymsp[0].minor.yy0); + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy347,&yymsp[0].minor.yy0); } break; - case 312: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ + case 310: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column */ { sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy0); } break; - case 313: /* add_column_fullname ::= fullname */ + case 311: /* add_column_fullname ::= fullname */ { pParse->db->lookaside.bEnabled = 0; - sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy259); + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy347); } break; - case 316: /* cmd ::= create_vtab */ + case 314: /* cmd ::= create_vtab */ {sqlite3VtabFinishParse(pParse,0);} break; - case 317: /* cmd ::= create_vtab LP vtabarglist RP */ + case 315: /* cmd ::= create_vtab LP vtabarglist RP */ {sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} break; - case 318: /* create_vtab ::= createkw VIRTUAL TABLE nm dbnm USING nm */ + case 316: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */ { - sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0); + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy392); } break; - case 321: /* vtabarg ::= */ + case 319: /* vtabarg ::= */ {sqlite3VtabArgInit(pParse);} break; - case 323: /* vtabargtoken ::= ANY */ - case 324: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==324); - case 325: /* lp ::= LP */ yytestcase(yyruleno==325); + case 321: /* vtabargtoken ::= ANY */ + case 322: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==322); + case 323: /* lp ::= LP */ yytestcase(yyruleno==323); {sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} break; default: @@ -110734,30 +112131,25 @@ static void yy_reduce( /* (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); + /* (53) carglist ::= carglist ccons */ 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); - /* (268) plus_opt ::= PLUS */ yytestcase(yyruleno==268); - /* (269) plus_opt ::= */ yytestcase(yyruleno==269); - /* (279) foreach_clause ::= */ yytestcase(yyruleno==279); - /* (280) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==280); - /* (287) tridxby ::= */ yytestcase(yyruleno==287); - /* (305) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==305); - /* (306) database_kw_opt ::= */ yytestcase(yyruleno==306); - /* (314) kwcolumn_opt ::= */ yytestcase(yyruleno==314); - /* (315) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==315); - /* (319) vtabarglist ::= vtabarg */ yytestcase(yyruleno==319); - /* (320) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==320); - /* (322) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==322); - /* (326) anylist ::= */ yytestcase(yyruleno==326); - /* (327) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==327); - /* (328) anylist ::= anylist ANY */ yytestcase(yyruleno==328); + /* (61) ccons ::= NULL onconf */ yytestcase(yyruleno==61); + /* (89) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==89); + /* (90) conslist ::= tcons */ yytestcase(yyruleno==90); + /* (92) tconscomma ::= */ yytestcase(yyruleno==92); + /* (277) foreach_clause ::= */ yytestcase(yyruleno==277); + /* (278) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==278); + /* (285) tridxby ::= */ yytestcase(yyruleno==285); + /* (303) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==303); + /* (304) database_kw_opt ::= */ yytestcase(yyruleno==304); + /* (312) kwcolumn_opt ::= */ yytestcase(yyruleno==312); + /* (313) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==313); + /* (317) vtabarglist ::= vtabarg */ yytestcase(yyruleno==317); + /* (318) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==318); + /* (320) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==320); + /* (324) anylist ::= */ yytestcase(yyruleno==324); + /* (325) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==325); + /* (326) anylist ::= anylist ANY */ yytestcase(yyruleno==326); break; }; yygoto = yyRuleInfo[yyruleno].lhs; @@ -112267,6 +113659,15 @@ SQLITE_PRIVATE void (*sqlite3IoTrace)(const char*, ...) = 0; */ SQLITE_API char *sqlite3_temp_directory = 0; +/* +** If the following global variable points to a string which is the +** name of a directory, then that directory will be used to store +** all database files specified with a relative pathname. +** +** See also the "PRAGMA data_store_directory" SQL command. +*/ +SQLITE_API char *sqlite3_data_directory = 0; + /* ** Initialize SQLite. ** @@ -112465,6 +113866,18 @@ SQLITE_API int sqlite3_shutdown(void){ if( sqlite3GlobalConfig.isMallocInit ){ sqlite3MallocEnd(); sqlite3GlobalConfig.isMallocInit = 0; + +#ifndef SQLITE_OMIT_SHUTDOWN_DIRECTORIES + /* The heap subsystem has now been shutdown and these values are supposed + ** to be NULL or point to memory that was obtained from sqlite3_malloc(), + ** which would rely on that heap subsystem; therefore, make sure these + ** values cannot refer to heap memory that was just invalidated when the + ** heap subsystem was shutdown. This is only done if the current call to + ** this function resulted in the heap subsystem actually being shutdown. + */ + sqlite3_data_directory = 0; + sqlite3_temp_directory = 0; +#endif } if( sqlite3GlobalConfig.isMutexInit ){ sqlite3MutexEnd(); @@ -112913,6 +114326,30 @@ static void functionDestroy(sqlite3 *db, FuncDef *p){ } } +/* +** Disconnect all sqlite3_vtab objects that belong to database connection +** db. This is called when db is being closed. +*/ +static void disconnectAllVtab(sqlite3 *db){ +#ifndef SQLITE_OMIT_VIRTUALTABLE + int i; + sqlite3BtreeEnterAll(db); + for(i=0; inDb; i++){ + Schema *pSchema = db->aDb[i].pSchema; + if( db->aDb[i].pSchema ){ + HashElem *p; + for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ + Table *pTab = (Table *)sqliteHashData(p); + if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab); + } + } + } + sqlite3BtreeLeaveAll(db); +#else + UNUSED_PARAMETER(db); +#endif +} + /* ** Close an existing SQLite database */ @@ -112928,10 +114365,10 @@ SQLITE_API int sqlite3_close(sqlite3 *db){ } sqlite3_mutex_enter(db->mutex); - /* Force xDestroy calls on all virtual tables */ - sqlite3ResetInternalSchema(db, -1); + /* Force xDisconnect calls on all virtual tables */ + disconnectAllVtab(db); - /* If a transaction is open, the ResetInternalSchema() call above + /* If a transaction is open, the disconnectAllVtab() call above ** will not have called the xDisconnect() method on any virtual ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() ** call will do so. We need to do this before the check for active @@ -112962,6 +114399,7 @@ SQLITE_API int sqlite3_close(sqlite3 *db){ /* Free any outstanding Savepoint structures. */ sqlite3CloseSavepoints(db); + /* Close all database connections */ for(j=0; jnDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ @@ -112972,15 +114410,22 @@ SQLITE_API int sqlite3_close(sqlite3 *db){ } } } - sqlite3ResetInternalSchema(db, -1); + /* Clear the TEMP schema separately and last */ + if( db->aDb[1].pSchema ){ + sqlite3SchemaClear(db->aDb[1].pSchema); + } + sqlite3VtabUnlockList(db); + + /* Free up the array of auxiliary databases */ + sqlite3CollapseDatabaseArray(db); + assert( db->nDb<=2 ); + assert( db->aDb==db->aDbStatic ); /* Tell the code in notify.c that the connection no longer holds any ** locks and does not require any further unlock-notify callbacks. */ sqlite3ConnectionClosed(db); - assert( db->nDb<=2 ); - assert( db->aDb==db->aDbStatic ); for(j=0; jaFunc.a); j++){ FuncDef *pNext, *pHash, *p; for(p=db->aFunc.a[j]; p; p=pHash){ @@ -113042,19 +114487,23 @@ SQLITE_API int sqlite3_close(sqlite3 *db){ } /* -** Rollback all database files. +** Rollback all database files. If tripCode is not SQLITE_OK, then +** any open cursors are invalidated ("tripped" - as in "tripping a circuit +** breaker") and made to return tripCode if there are any further +** attempts to use that cursor. */ -SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){ +SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){ int i; int inTrans = 0; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); for(i=0; inDb; i++){ - if( db->aDb[i].pBt ){ - if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ + Btree *p = db->aDb[i].pBt; + if( p ){ + if( sqlite3BtreeIsInTrans(p) ){ inTrans = 1; } - sqlite3BtreeRollback(db->aDb[i].pBt); + sqlite3BtreeRollback(p, tripCode); db->aDb[i].inTrans = 0; } } @@ -113063,7 +114512,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){ if( db->flags&SQLITE_InternChanges ){ sqlite3ExpirePreparedStatements(db); - sqlite3ResetInternalSchema(db, -1); + sqlite3ResetAllSchemasOfConnection(db); } /* Any deferred constraint violations have now been resolved. */ @@ -113109,12 +114558,21 @@ SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){ /* SQLITE_RANGE */ "bind or column index out of range", /* SQLITE_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"; + const char *zErr = "unknown error"; + switch( rc ){ + case SQLITE_ABORT_ROLLBACK: { + zErr = "abort due to ROLLBACK"; + break; + } + default: { + rc &= 0xff; + if( ALWAYS(rc>=0) && rclimit ){ + if( (mode & ~SQLITE_OPEN_MEMORY)>limit ){ *pzErrMsg = sqlite3_mprintf("%s mode not allowed: %s", zModeType, zVal); rc = SQLITE_PERM; @@ -114236,6 +115695,7 @@ SQLITE_PRIVATE int sqlite3ParseUri( memcpy(zFile, zUri, nUri); zFile[nUri] = '\0'; zFile[nUri+1] = '\0'; + flags &= ~SQLITE_OPEN_URI; } *ppVfs = sqlite3_vfs_find(zVfs); @@ -114885,35 +116345,27 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ */ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){ int rc = SQLITE_ERROR; - int iDb; + Btree *pBtree; + sqlite3_mutex_enter(db->mutex); - if( zDbName==0 ){ - iDb = 0; - }else{ - for(iDb=0; iDbnDb; iDb++){ - if( strcmp(db->aDb[iDb].zName, zDbName)==0 ) break; - } - } - if( iDbnDb ){ - Btree *pBtree = db->aDb[iDb].pBt; - if( pBtree ){ - Pager *pPager; - sqlite3_file *fd; - sqlite3BtreeEnter(pBtree); - pPager = sqlite3BtreePager(pBtree); - assert( pPager!=0 ); - fd = sqlite3PagerFile(pPager); - assert( fd!=0 ); - if( op==SQLITE_FCNTL_FILE_POINTER ){ - *(sqlite3_file**)pArg = fd; - rc = SQLITE_OK; - }else if( fd->pMethods ){ - rc = sqlite3OsFileControl(fd, op, pArg); - }else{ - rc = SQLITE_NOTFOUND; - } - sqlite3BtreeLeave(pBtree); + pBtree = sqlite3DbNameToBtree(db, zDbName); + if( pBtree ){ + Pager *pPager; + sqlite3_file *fd; + sqlite3BtreeEnter(pBtree); + pPager = sqlite3BtreePager(pBtree); + assert( pPager!=0 ); + fd = sqlite3PagerFile(pPager); + assert( fd!=0 ); + if( op==SQLITE_FCNTL_FILE_POINTER ){ + *(sqlite3_file**)pArg = fd; + rc = SQLITE_OK; + }else if( fd->pMethods ){ + rc = sqlite3OsFileControl(fd, op, pArg); + }else{ + rc = SQLITE_NOTFOUND; } + sqlite3BtreeLeave(pBtree); } sqlite3_mutex_leave(db->mutex); return rc; @@ -115188,7 +116640,8 @@ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char * */ SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){ const char *z = sqlite3_uri_parameter(zFilename, zParam); - return z ? sqlite3GetBoolean(z) : (bDflt!=0); + bDflt = bDflt!=0; + return z ? sqlite3GetBoolean(z, bDflt) : bDflt; } /* @@ -115207,18 +116660,37 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64( return bDflt; } +/* +** Return the Btree pointer identified by zDbName. Return NULL if not found. +*/ +SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){ + int i; + for(i=0; inDb; i++){ + if( db->aDb[i].pBt + && (zDbName==0 || sqlite3StrICmp(zDbName, db->aDb[i].zName)==0) + ){ + return db->aDb[i].pBt; + } + } + return 0; +} + /* ** Return the filename of the database associated with a database ** connection. */ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){ - int i; - for(i=0; inDb; i++){ - if( db->aDb[i].pBt && sqlite3StrICmp(zDbName, db->aDb[i].zName)==0 ){ - return sqlite3BtreeGetFilename(db->aDb[i].pBt); - } - } - return 0; + Btree *pBt = sqlite3DbNameToBtree(db, zDbName); + return pBt ? sqlite3BtreeGetFilename(pBt) : 0; +} + +/* +** Return 1 if database is read-only or 0 if read/write. Return -1 if +** no such database exists. +*/ +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ + Btree *pBt = sqlite3DbNameToBtree(db, zDbName); + return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1; } /************** End of main.c ************************************************/ @@ -115628,7 +117100,7 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ ** A doclist is stored like this: ** ** array { -** varint docid; +** varint docid; (delta from previous doclist) ** array { (position list for column 0) ** varint position; (2 more than the delta from previous position) ** } @@ -115659,8 +117131,8 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ ** at D signals the start of a new column; the 1 at E indicates that the ** new column is column number 1. There are two positions at 12 and 45 ** (14-2 and 35-2+12). The 0 at H indicate the end-of-document. The -** 234 at I is the next docid. It has one position 72 (72-2) and then -** terminates with the 0 at K. +** 234 at I is the delta to next docid (357). It has one position 70 +** (72-2) and then terminates with the 0 at K. ** ** A "position-list" is the list of positions for multiple columns for ** a single docid. A "column-list" is the set of positions for a single @@ -115844,10 +117316,6 @@ SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db){ ** will eventually overtake the earlier data and knock it out. The ** query logic likewise merges doclists so that newer data knocks out ** older data. -** -** TODO(shess) Provide a VACUUM type operation to clear out all -** deletions and duplications. This would basically be a forced merge -** into a single segment. */ /************** Include fts3Int.h in the middle of fts3.c ********************/ @@ -115943,7 +117411,7 @@ typedef struct sqlite3_tokenizer_cursor sqlite3_tokenizer_cursor; struct sqlite3_tokenizer_module { /* - ** Structure version. Should always be set to 0. + ** Structure version. Should always be set to 0 or 1. */ int iVersion; @@ -116024,6 +117492,15 @@ struct sqlite3_tokenizer_module { int *piEndOffset, /* OUT: Byte offset of end of token in input buffer */ int *piPosition /* OUT: Number of tokens returned before this one */ ); + + /*********************************************************************** + ** Methods below this point are only available if iVersion>=1. + */ + + /* + ** Configure the language id of a tokenizer cursor. + */ + int (*xLanguageid)(sqlite3_tokenizer_cursor *pCsr, int iLangid); }; struct sqlite3_tokenizer { @@ -116190,6 +117667,9 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi #ifndef MIN # define MIN(x,y) ((x)<(y)?(x):(y)) #endif +#ifndef MAX +# define MAX(x,y) ((x)>(y)?(x):(y)) +#endif /* ** Maximum length of a varint encoded integer. The varint format is different @@ -116244,7 +117724,7 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi # define NEVER(X) (0) #else # define ALWAYS(x) (x) -# define NEVER(X) (x) +# define NEVER(x) (x) #endif /* @@ -116254,6 +117734,7 @@ typedef unsigned char u8; /* 1-byte (or larger) unsigned integer */ typedef short int i16; /* 2-byte (or larger) signed integer */ typedef unsigned int u32; /* 4-byte unsigned integer */ typedef sqlite3_uint64 u64; /* 8-byte unsigned integer */ +typedef sqlite3_int64 i64; /* 8-byte signed integer */ /* ** Macro used to suppress compiler warnings for unused parameters. @@ -116315,36 +117796,44 @@ struct Fts3Table { char **azColumn; /* column names. malloced */ sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */ char *zContentTbl; /* content=xxx option, or NULL */ + char *zLanguageid; /* languageid=xxx option, or NULL */ + u8 bAutoincrmerge; /* True if automerge=1 */ + u32 nLeafAdd; /* Number of leaf blocks added this trans */ /* Precompiled statements used by the implementation. Each of these ** statements is run and reset within a single virtual table API call. */ - sqlite3_stmt *aStmt[27]; + sqlite3_stmt *aStmt[37]; char *zReadExprlist; char *zWriteExprlist; int nNodeSize; /* Soft limit for node size */ + u8 bFts4; /* True for FTS4, false for FTS3 */ u8 bHasStat; /* True if %_stat table exists */ u8 bHasDocsize; /* True if %_docsize table exists */ u8 bDescIdx; /* True if doclists are in reverse order */ + u8 bIgnoreSavepoint; /* True to ignore xSavepoint invocations */ int nPgsz; /* Page size for host database */ char *zSegmentsTbl; /* Name of %_segments table */ sqlite3_blob *pSegments; /* Blob handle open on %_segments table */ - /* TODO: Fix the first paragraph of this comment. - ** - ** The following hash table is used to buffer pending index updates during - ** transactions. Variable nPendingData estimates the memory size of the - ** pending data, including hash table overhead, but not malloc overhead. - ** When nPendingData exceeds nMaxPendingData, the buffer is flushed - ** automatically. Variable iPrevDocid is the docid of the most recently - ** inserted record. + /* + ** The following array of hash tables is used to buffer pending index + ** updates during transactions. All pending updates buffered at any one + ** time must share a common language-id (see the FTS4 langid= feature). + ** The current language id is stored in variable iPrevLangid. ** ** A single FTS4 table may have multiple full-text indexes. For each index ** there is an entry in the aIndex[] array. Index 0 is an index of all the ** terms that appear in the document set. Each subsequent index in aIndex[] ** is an index of prefixes of a specific length. + ** + ** Variable nPendingData contains an estimate the memory consumed by the + ** pending data structures, including hash table overhead, but not including + ** malloc overhead. When nPendingData exceeds nMaxPendingData, all hash + ** tables are flushed to disk. Variable iPrevDocid is the docid of the most + ** recently inserted record. */ int nIndex; /* Size of aIndex[] */ struct Fts3Index { @@ -116354,12 +117843,13 @@ struct Fts3Table { int nMaxPendingData; /* Max pending data before flush to disk */ int nPendingData; /* Current bytes of pending data */ sqlite_int64 iPrevDocid; /* Docid of most recently inserted document */ + int iPrevLangid; /* Langid of recently inserted document */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) /* State variables used for validating that the transaction control ** methods of the virtual table are called at appropriate times. These - ** values do not contribution to the FTS computation; they are used for - ** verifying the SQLite core. + ** values do not contribute to FTS functionality; they are used for + ** verifying the operation of the SQLite core. */ int inTransaction; /* True after xBegin but before xCommit/xRollback */ int mxSavepoint; /* Largest valid xSavepoint integer */ @@ -116378,6 +117868,7 @@ struct Fts3Cursor { u8 isRequireSeek; /* True if must seek pStmt to %_content row */ sqlite3_stmt *pStmt; /* Prepared statement in use by the cursor */ Fts3Expr *pExpr; /* Parsed MATCH query string */ + int iLangid; /* Language being queried for */ int nPhrase; /* Number of matchable phrases in query */ Fts3DeferredToken *pDeferred; /* Deferred search tokens, if any */ sqlite3_int64 iPrevId; /* Previous id read from aDoclist */ @@ -116524,12 +118015,12 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod(sqlite3_vtab*,int,sqlite3_value**,sql SQLITE_PRIVATE int sqlite3Fts3PendingTermsFlush(Fts3Table *); SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *); SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *); -SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, sqlite3_int64, +SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(int, int, sqlite3_int64, sqlite3_int64, sqlite3_int64, const char *, int, Fts3SegReader**); SQLITE_PRIVATE int sqlite3Fts3SegReaderPending( Fts3Table*,int,const char*,int,int,Fts3SegReader**); SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *); -SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, sqlite3_stmt **); +SQLITE_PRIVATE int sqlite3Fts3AllSegdirs(Fts3Table*, int, int, int, sqlite3_stmt **); SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *); SQLITE_PRIVATE int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*); @@ -116541,6 +118032,7 @@ SQLITE_PRIVATE int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); SQLITE_PRIVATE void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); SQLITE_PRIVATE void sqlite3Fts3SegmentsClose(Fts3Table *); +SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *, int *); /* Special values interpreted by sqlite3SegReaderCursor() */ #define FTS3_SEGCURSOR_PENDING -1 @@ -116550,8 +118042,8 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStart(Fts3Table*, Fts3MultiSegReader*, Ft SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(Fts3Table *, Fts3MultiSegReader *); SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish(Fts3MultiSegReader *); -SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( - Fts3Table *, int, int, const char *, int, int, int, Fts3MultiSegReader *); +SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor(Fts3Table *, + int, int, int, const char *, int, int, int, Fts3MultiSegReader *); /* Flags allowed as part of the 4th argument to SegmentReaderIterate() */ #define FTS3_SEGMENT_REQUIRE_POS 0x00000001 @@ -116592,6 +118084,8 @@ struct Fts3MultiSegReader { int nDoclist; /* Size of aDoclist[] in bytes */ }; +SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int); + /* fts3.c */ SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64); SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *); @@ -116601,6 +118095,7 @@ SQLITE_PRIVATE void sqlite3Fts3Dequote(char *); SQLITE_PRIVATE void sqlite3Fts3DoclistPrev(int,char*,int,char**,sqlite3_int64*,int*,u8*); SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(Fts3Cursor *, Fts3Expr *, u32 *); SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *); +SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*); /* fts3_tokenizer.c */ SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *); @@ -116618,7 +118113,7 @@ SQLITE_PRIVATE void sqlite3Fts3Snippet(sqlite3_context *, Fts3Cursor *, const ch SQLITE_PRIVATE void sqlite3Fts3Matchinfo(sqlite3_context *, Fts3Cursor *, const char *); /* fts3_expr.c */ -SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, +SQLITE_PRIVATE int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int, char **, int, int, int, const char *, int, Fts3Expr ** ); SQLITE_PRIVATE void sqlite3Fts3ExprFree(Fts3Expr *); @@ -116627,6 +118122,10 @@ SQLITE_PRIVATE int sqlite3Fts3ExprInitTestInterface(sqlite3 *db); SQLITE_PRIVATE int sqlite3Fts3InitTerm(sqlite3 *db); #endif +SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer(sqlite3_tokenizer *, int, const char *, int, + sqlite3_tokenizer_cursor ** +); + /* fts3_aux.c */ SQLITE_PRIVATE int sqlite3Fts3InitAux(sqlite3 *db); @@ -116636,12 +118135,19 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrStart( Fts3Table*, Fts3MultiSegReader*, int, const char*, int); SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext( Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *); -SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol); +SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); SQLITE_PRIVATE int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); SQLITE_PRIVATE int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); SQLITE_PRIVATE int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *); +/* fts3_unicode2.c (functions generated by parsing unicode text files) */ +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 +SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int, int); +SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int); +SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int); +#endif + #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ #endif /* _FTSINT_H */ @@ -116821,6 +118327,7 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){ sqlite3_free(p->zReadExprlist); sqlite3_free(p->zWriteExprlist); sqlite3_free(p->zContentTbl); + sqlite3_free(p->zLanguageid); /* Invoke the tokenizer destructor to free the tokenizer. */ p->pTokenizer->pModule->xDestroy(p->pTokenizer); @@ -116897,7 +118404,9 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){ int rc; /* Return code */ char *zSql; /* SQL statement passed to declare_vtab() */ char *zCols; /* List of user defined columns */ + const char *zLanguageid; + zLanguageid = (p->zLanguageid ? p->zLanguageid : "__langid"); sqlite3_vtab_config(p->db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); /* Create a list of user columns for the virtual table */ @@ -116908,7 +118417,8 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){ /* Create the whole "CREATE TABLE" statement to pass to SQLite */ zSql = sqlite3_mprintf( - "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN)", zCols, p->zName + "CREATE TABLE x(%s %Q HIDDEN, docid HIDDEN, %Q HIDDEN)", + zCols, p->zName, zLanguageid ); if( !zCols || !zSql ){ rc = SQLITE_NOMEM; @@ -116922,6 +118432,18 @@ static void fts3DeclareVtab(int *pRc, Fts3Table *p){ } } +/* +** Create the %_stat table if it does not already exist. +*/ +SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int *pRc, Fts3Table *p){ + fts3DbExec(pRc, p->db, + "CREATE TABLE IF NOT EXISTS %Q.'%q_stat'" + "(id INTEGER PRIMARY KEY, value BLOB);", + p->zDb, p->zName + ); + if( (*pRc)==SQLITE_OK ) p->bHasStat = 1; +} + /* ** Create the backing store tables (%_content, %_segments and %_segdir) ** required by the FTS3 table passed as the only argument. This is done @@ -116937,6 +118459,7 @@ static int fts3CreateTables(Fts3Table *p){ sqlite3 *db = p->db; /* The database connection */ if( p->zContentTbl==0 ){ + const char *zLanguageid = p->zLanguageid; char *zContentCols; /* Columns of %_content table */ /* Create a list of user columns for the content table */ @@ -116945,6 +118468,9 @@ static int fts3CreateTables(Fts3Table *p){ char *z = p->azColumn[i]; zContentCols = sqlite3_mprintf("%z, 'c%d%q'", zContentCols, i, z); } + if( zLanguageid && zContentCols ){ + zContentCols = sqlite3_mprintf("%z, langid", zContentCols, zLanguageid); + } if( zContentCols==0 ) rc = SQLITE_NOMEM; /* Create the content table */ @@ -116978,11 +118504,9 @@ static int fts3CreateTables(Fts3Table *p){ p->zDb, p->zName ); } + assert( p->bHasStat==p->bFts4 ); if( p->bHasStat ){ - fts3DbExec(&rc, db, - "CREATE TABLE %Q.'%q_stat'(id INTEGER PRIMARY KEY, value BLOB);", - p->zDb, p->zName - ); + sqlite3Fts3CreateStatTable(&rc, p); } return rc; } @@ -117089,7 +118613,7 @@ static void fts3Appendf( static char *fts3QuoteId(char const *zInput){ int nRet; char *zRet; - nRet = 2 + strlen(zInput)*2 + 1; + nRet = 2 + (int)strlen(zInput)*2 + 1; zRet = sqlite3_malloc(nRet); if( zRet ){ int i; @@ -117144,14 +118668,20 @@ static char *fts3ReadExprList(Fts3Table *p, const char *zFunc, int *pRc){ for(i=0; inColumn; i++){ fts3Appendf(pRc, &zRet, ",%s(x.'c%d%q')", zFunction, i, p->azColumn[i]); } + if( p->zLanguageid ){ + fts3Appendf(pRc, &zRet, ", x.%Q", "langid"); + } sqlite3_free(zFree); }else{ fts3Appendf(pRc, &zRet, "rowid"); for(i=0; inColumn; i++){ fts3Appendf(pRc, &zRet, ", x.'%q'", p->azColumn[i]); } + if( p->zLanguageid ){ + fts3Appendf(pRc, &zRet, ", x.%Q", p->zLanguageid); + } } - fts3Appendf(pRc, &zRet, "FROM '%q'.'%q%s' AS x", + fts3Appendf(pRc, &zRet, " FROM '%q'.'%q%s' AS x", p->zDb, (p->zContentTbl ? p->zContentTbl : p->zName), (p->zContentTbl ? "" : "_content") @@ -117194,6 +118724,9 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){ for(i=0; inColumn; i++){ fts3Appendf(pRc, &zRet, ",%s(?)", zFunction); } + if( p->zLanguageid ){ + fts3Appendf(pRc, &zRet, ", ?"); + } sqlite3_free(zFree); return zRet; } @@ -117336,7 +118869,7 @@ static int fts3ContentColumns( nCol = sqlite3_column_count(pStmt); for(i=0; i COMPRESS */ { "uncompress", 10 }, /* 3 -> UNCOMPRESS */ { "order", 5 }, /* 4 -> ORDER */ - { "content", 7 } /* 5 -> CONTENT */ + { "content", 7 }, /* 5 -> CONTENT */ + { "languageid", 10 } /* 6 -> LANGUAGEID */ }; int iOpt; @@ -117512,12 +119047,18 @@ static int fts3InitVtab( bDescIdx = (zVal[0]=='d' || zVal[0]=='D'); break; - default: /* CONTENT */ - assert( iOpt==5 ); - sqlite3_free(zUncompress); + case 5: /* CONTENT */ + sqlite3_free(zContent); zContent = zVal; zVal = 0; break; + + case 6: /* LANGUAGEID */ + assert( iOpt==6 ); + sqlite3_free(zLanguageid); + zLanguageid = zVal; + zVal = 0; + break; } } sqlite3_free(zVal); @@ -117547,8 +119088,21 @@ static int fts3InitVtab( sqlite3_free((void*)aCol); aCol = 0; rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString); + + /* If a languageid= option was specified, remove the language id + ** column from the aCol[] array. */ + if( rc==SQLITE_OK && zLanguageid ){ + int j; + for(j=0; j0 ); } if( rc!=SQLITE_OK ) goto fts3_init_out; @@ -117593,9 +119147,13 @@ static int fts3InitVtab( p->nMaxPendingData = FTS3_MAX_PENDING_DATA; p->bHasDocsize = (isFts4 && bNoDocsize==0); p->bHasStat = isFts4; + p->bFts4 = isFts4; p->bDescIdx = bDescIdx; + p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */ p->zContentTbl = zContent; + p->zLanguageid = zLanguageid; zContent = 0; + zLanguageid = 0; TESTONLY( p->inTransaction = -1 ); TESTONLY( p->mxSavepoint = -1 ); @@ -117644,6 +119202,16 @@ static int fts3InitVtab( rc = fts3CreateTables(p); } + /* Check to see if a legacy fts3 table has been "upgraded" by the + ** addition of a %_stat table so that it can use incremental merge. + */ + if( !isFts4 && !isCreate ){ + int rc2 = SQLITE_OK; + fts3DbExec(&rc2, db, "SELECT 1 FROM %Q.'%q_stat' WHERE id=2", + p->zDb, p->zName); + if( rc2==SQLITE_OK ) p->bHasStat = 1; + } + /* Figure out the page-size for the database. This is required in order to ** estimate the cost of loading large doclists from the database. */ fts3DatabasePageSize(&rc, p); @@ -117658,6 +119226,7 @@ fts3_init_out: sqlite3_free(zCompress); sqlite3_free(zUncompress); sqlite3_free(zContent); + sqlite3_free(zLanguageid); sqlite3_free((void *)aCol); if( rc!=SQLITE_OK ){ if( p ){ @@ -117709,6 +119278,7 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ Fts3Table *p = (Fts3Table *)pVTab; int i; /* Iterator variable */ int iCons = -1; /* Index of constraint to use */ + int iLangidCons = -1; /* Index of langid=x constraint, if present */ /* By default use a full table scan. This is an expensive option, ** so search through the constraints to see if a more efficient @@ -117721,7 +119291,8 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ if( pCons->usable==0 ) continue; /* A direct lookup on the rowid or docid column. Assign a cost of 1.0. */ - if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ + if( iCons<0 + && pCons->op==SQLITE_INDEX_CONSTRAINT_EQ && (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1 ) ){ pInfo->idxNum = FTS3_DOCID_SEARCH; @@ -117744,7 +119315,13 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ pInfo->idxNum = FTS3_FULLTEXT_SEARCH + pCons->iColumn; pInfo->estimatedCost = 2.0; iCons = i; - break; + } + + /* Equality constraint on the langid column */ + if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ + && pCons->iColumn==p->nColumn + 2 + ){ + iLangidCons = i; } } @@ -117752,6 +119329,9 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ pInfo->aConstraintUsage[iCons].argvIndex = 1; pInfo->aConstraintUsage[iCons].omit = 1; } + if( iLangidCons>=0 ){ + pInfo->aConstraintUsage[iLangidCons].argvIndex = 2; + } /* Regardless of the strategy selected, FTS can deliver rows in rowid (or ** docid) order. Both ascending and descending are possible. @@ -118635,7 +120215,7 @@ static int fts3DoclistOrMerge( } *paOut = aOut; - *pnOut = (p-aOut); + *pnOut = (int)(p-aOut); assert( *pnOut<=n1+n2+FTS3_VARINT_MAX-1 ); return SQLITE_OK; } @@ -118699,7 +120279,7 @@ static void fts3DoclistPhraseMerge( } } - *pnRight = p - aOut; + *pnRight = (int)(p - aOut); } /* @@ -118901,6 +120481,7 @@ static int fts3SegReaderCursorAppend( */ static int fts3SegReaderCursor( Fts3Table *p, /* FTS3 table handle */ + int iLangid, /* Language id */ int iIndex, /* Index to search (from 0 to p->nIndex-1) */ int iLevel, /* Level of segments to scan */ const char *zTerm, /* Term to query for */ @@ -118929,7 +120510,7 @@ static int fts3SegReaderCursor( if( iLevel!=FTS3_SEGCURSOR_PENDING ){ if( rc==SQLITE_OK ){ - rc = sqlite3Fts3AllSegdirs(p, iIndex, iLevel, &pStmt); + rc = sqlite3Fts3AllSegdirs(p, iLangid, iIndex, iLevel, &pStmt); } while( rc==SQLITE_OK && SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){ @@ -118952,7 +120533,9 @@ static int fts3SegReaderCursor( } rc = sqlite3Fts3SegReaderNew(pCsr->nSegment+1, - iStartBlock, iLeavesEndBlock, iEndBlock, zRoot, nRoot, &pSeg + (isPrefix==0 && isScan==0), + iStartBlock, iLeavesEndBlock, + iEndBlock, zRoot, nRoot, &pSeg ); if( rc!=SQLITE_OK ) goto finished; rc = fts3SegReaderCursorAppend(pCsr, pSeg); @@ -118972,6 +120555,7 @@ static int fts3SegReaderCursor( */ SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( Fts3Table *p, /* FTS3 table handle */ + int iLangid, /* Language-id to search */ int iIndex, /* Index to search (from 0 to p->nIndex-1) */ int iLevel, /* Level of segments to scan */ const char *zTerm, /* Term to query for */ @@ -118989,14 +120573,9 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( assert( FTS3_SEGCURSOR_ALL<0 && FTS3_SEGCURSOR_PENDING<0 ); assert( isPrefix==0 || isScan==0 ); - /* "isScan" is only set to true by the ft4aux module, an ordinary - ** full-text tables. */ - assert( isScan==0 || p->aIndex==0 ); - memset(pCsr, 0, sizeof(Fts3MultiSegReader)); - return fts3SegReaderCursor( - p, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr + p, iLangid, iIndex, iLevel, zTerm, nTerm, isPrefix, isScan, pCsr ); } @@ -119008,11 +120587,14 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderCursor( */ static int fts3SegReaderCursorAddZero( Fts3Table *p, /* FTS virtual table handle */ + int iLangid, const char *zTerm, /* Term to scan doclist of */ int nTerm, /* Number of bytes in zTerm */ Fts3MultiSegReader *pCsr /* Fts3MultiSegReader to modify */ ){ - return fts3SegReaderCursor(p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr); + return fts3SegReaderCursor(p, + iLangid, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0,pCsr + ); } /* @@ -119048,8 +120630,9 @@ static int fts3TermSegReaderCursor( for(i=1; bFound==0 && inIndex; i++){ if( p->aIndex[i].nPrefix==nTerm ){ bFound = 1; - rc = sqlite3Fts3SegReaderCursor( - p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr); + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, + i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 0, 0, pSegcsr + ); pSegcsr->bLookup = 1; } } @@ -119057,19 +120640,21 @@ static int fts3TermSegReaderCursor( for(i=1; bFound==0 && inIndex; i++){ if( p->aIndex[i].nPrefix==nTerm+1 ){ bFound = 1; - rc = sqlite3Fts3SegReaderCursor( - p, i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, + i, FTS3_SEGCURSOR_ALL, zTerm, nTerm, 1, 0, pSegcsr ); if( rc==SQLITE_OK ){ - rc = fts3SegReaderCursorAddZero(p, zTerm, nTerm, pSegcsr); + rc = fts3SegReaderCursorAddZero( + p, pCsr->iLangid, zTerm, nTerm, pSegcsr + ); } } } } if( bFound==0 ){ - rc = sqlite3Fts3SegReaderCursor( - p, 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr + rc = sqlite3Fts3SegReaderCursor(p, pCsr->iLangid, + 0, FTS3_SEGCURSOR_ALL, zTerm, nTerm, isPrefix, 0, pSegcsr ); pSegcsr->bLookup = !isPrefix; } @@ -119224,7 +120809,7 @@ static int fts3FilterMethod( UNUSED_PARAMETER(nVal); assert( idxNum>=0 && idxNum<=(FTS3_FULLTEXT_SEARCH+p->nColumn) ); - assert( nVal==0 || nVal==1 ); + assert( nVal==0 || nVal==1 || nVal==2 ); assert( (nVal==0)==(idxNum==FTS3_FULLSCAN_SEARCH) ); assert( p->pSegments==0 ); @@ -119249,8 +120834,11 @@ static int fts3FilterMethod( return SQLITE_NOMEM; } - rc = sqlite3Fts3ExprParse(p->pTokenizer, p->azColumn, p->bHasStat, - p->nColumn, iCol, zQuery, -1, &pCsr->pExpr + pCsr->iLangid = 0; + if( nVal==2 ) pCsr->iLangid = sqlite3_value_int(apVal[1]); + + rc = sqlite3Fts3ExprParse(p->pTokenizer, pCsr->iLangid, + p->azColumn, p->bFts4, p->nColumn, iCol, zQuery, -1, &pCsr->pExpr ); if( rc!=SQLITE_OK ){ if( rc==SQLITE_ERROR ){ @@ -119321,10 +120909,17 @@ static int fts3RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ /* ** This is the xColumn method, called by SQLite to request a value from ** the row that the supplied cursor currently points to. +** +** If: +** +** (iCol < p->nColumn) -> The value of the iCol'th user column. +** (iCol == p->nColumn) -> Magic column with the same name as the table. +** (iCol == p->nColumn+1) -> Docid column +** (iCol == p->nColumn+2) -> Langid column */ static int fts3ColumnMethod( sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */ - sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */ + sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */ int iCol /* Index of column to read value from */ ){ int rc = SQLITE_OK; /* Return Code */ @@ -119332,22 +120927,34 @@ static int fts3ColumnMethod( Fts3Table *p = (Fts3Table *)pCursor->pVtab; /* The column value supplied by SQLite must be in range. */ - assert( iCol>=0 && iCol<=p->nColumn+1 ); + assert( iCol>=0 && iCol<=p->nColumn+2 ); if( iCol==p->nColumn+1 ){ /* This call is a request for the "docid" column. Since "docid" is an ** alias for "rowid", use the xRowid() method to obtain the value. */ - sqlite3_result_int64(pContext, pCsr->iPrevId); + sqlite3_result_int64(pCtx, pCsr->iPrevId); }else if( iCol==p->nColumn ){ /* The extra column whose name is the same as the table. - ** Return a blob which is a pointer to the cursor. - */ - sqlite3_result_blob(pContext, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); + ** Return a blob which is a pointer to the cursor. */ + sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); + }else if( iCol==p->nColumn+2 && pCsr->pExpr ){ + sqlite3_result_int64(pCtx, pCsr->iLangid); }else{ + /* The requested column is either a user column (one that contains + ** indexed data), or the language-id column. */ rc = fts3CursorSeek(0, pCsr); - if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){ - sqlite3_result_value(pContext, sqlite3_column_value(pCsr->pStmt, iCol+1)); + + if( rc==SQLITE_OK ){ + if( iCol==p->nColumn+2 ){ + int iLangid = 0; + if( p->zLanguageid ){ + iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1); + } + sqlite3_result_int(pCtx, iLangid); + }else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){ + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1)); + } } } @@ -119374,8 +120981,42 @@ static int fts3UpdateMethod( ** hash-table to the database. */ static int fts3SyncMethod(sqlite3_vtab *pVtab){ - int rc = sqlite3Fts3PendingTermsFlush((Fts3Table *)pVtab); - sqlite3Fts3SegmentsClose((Fts3Table *)pVtab); + + /* Following an incremental-merge operation, assuming that the input + ** segments are not completely consumed (the usual case), they are updated + ** in place to remove the entries that have already been merged. This + ** involves updating the leaf block that contains the smallest unmerged + ** entry and each block (if any) between the leaf and the root node. So + ** if the height of the input segment b-trees is N, and input segments + ** are merged eight at a time, updating the input segments at the end + ** of an incremental-merge requires writing (8*(1+N)) blocks. N is usually + ** small - often between 0 and 2. So the overhead of the incremental + ** merge is somewhere between 8 and 24 blocks. To avoid this overhead + ** dwarfing the actual productive work accomplished, the incremental merge + ** is only attempted if it will write at least 64 leaf blocks. Hence + ** nMinMerge. + ** + ** Of course, updating the input segments also involves deleting a bunch + ** of blocks from the segments table. But this is not considered overhead + ** as it would also be required by a crisis-merge that used the same input + ** segments. + */ + const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ + + Fts3Table *p = (Fts3Table*)pVtab; + int rc = sqlite3Fts3PendingTermsFlush(p); + + if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){ + int mxLevel = 0; /* Maximum relative level value in db */ + int A; /* Incr-merge parameter A */ + + rc = sqlite3Fts3MaxLevel(p, &mxLevel); + assert( rc==SQLITE_OK || mxLevel==0 ); + A = p->nLeafAdd * mxLevel; + A += (A/2); + if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8); + } + sqlite3Fts3SegmentsClose(p); return rc; } @@ -119383,13 +121024,14 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){ ** Implementation of xBegin() method. This is a no-op. */ static int fts3BeginMethod(sqlite3_vtab *pVtab){ - TESTONLY( Fts3Table *p = (Fts3Table*)pVtab ); + Fts3Table *p = (Fts3Table*)pVtab; UNUSED_PARAMETER(pVtab); assert( p->pSegments==0 ); assert( p->nPendingData==0 ); assert( p->inTransaction!=1 ); TESTONLY( p->inTransaction = 1 ); TESTONLY( p->mxSavepoint = -1; ); + p->nLeafAdd = 0; return SQLITE_OK; } @@ -119684,11 +121326,15 @@ static int fts3RenameMethod( ** Flush the contents of the pending-terms table to disk. */ static int fts3SavepointMethod(sqlite3_vtab *pVtab, int iSavepoint){ + int rc = SQLITE_OK; UNUSED_PARAMETER(iSavepoint); assert( ((Fts3Table *)pVtab)->inTransaction ); assert( ((Fts3Table *)pVtab)->mxSavepoint < iSavepoint ); TESTONLY( ((Fts3Table *)pVtab)->mxSavepoint = iSavepoint ); - return fts3SyncMethod(pVtab); + if( ((Fts3Table *)pVtab)->bIgnoreSavepoint==0 ){ + rc = fts3SyncMethod(pVtab); + } + return rc; } /* @@ -119770,6 +121416,9 @@ static void hashDestroy(void *p){ */ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule(sqlite3_tokenizer_module const**ppModule); SQLITE_PRIVATE void sqlite3Fts3PorterTokenizerModule(sqlite3_tokenizer_module const**ppModule); +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 +SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const**ppModule); +#endif #ifdef SQLITE_ENABLE_ICU SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const**ppModule); #endif @@ -119785,12 +121434,19 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ Fts3Hash *pHash = 0; const sqlite3_tokenizer_module *pSimple = 0; const sqlite3_tokenizer_module *pPorter = 0; +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 + const sqlite3_tokenizer_module *pUnicode = 0; +#endif #ifdef SQLITE_ENABLE_ICU const sqlite3_tokenizer_module *pIcu = 0; sqlite3Fts3IcuTokenizerModule(&pIcu); #endif +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 + sqlite3Fts3UnicodeTokenizer(&pUnicode); +#endif + #ifdef SQLITE_TEST rc = sqlite3Fts3InitTerm(db); if( rc!=SQLITE_OK ) return rc; @@ -119814,6 +121470,10 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){ if( rc==SQLITE_OK ){ if( sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple) || sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter) + +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 + || sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode) +#endif #ifdef SQLITE_ENABLE_ICU || (pIcu && sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu)) #endif @@ -120048,7 +121708,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ fts3PoslistPhraseMerge(&aOut, iToken-iPrev, 0, 1, &p1, &p2); sqlite3_free(aPoslist); aPoslist = pList; - nPoslist = aOut - aPoslist; + nPoslist = (int)(aOut - aPoslist); if( nPoslist==0 ){ sqlite3_free(aPoslist); pPhrase->doclist.pList = 0; @@ -120092,7 +121752,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ pPhrase->doclist.pList = aOut; if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){ pPhrase->doclist.bFreeList = 1; - pPhrase->doclist.nList = (aOut - pPhrase->doclist.pList); + pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList); }else{ sqlite3_free(aOut); pPhrase->doclist.pList = 0; @@ -120161,7 +121821,7 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistPrev( int nDoclist, /* Length of aDoclist in bytes */ char **ppIter, /* IN/OUT: Iterator pointer */ sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */ - int *pnList, /* IN/OUT: List length pointer */ + int *pnList, /* OUT: List length pointer */ u8 *pbEof /* OUT: End-of-file flag */ ){ char *p = *ppIter; @@ -120188,7 +121848,7 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistPrev( iMul = (bDescIdx ? -1 : 1); } - *pnList = pEnd - pNext; + *pnList = (int)(pEnd - pNext); *ppIter = pNext; *piDocid = iDocid; }else{ @@ -120202,12 +121862,47 @@ SQLITE_PRIVATE void sqlite3Fts3DoclistPrev( }else{ char *pSave = p; fts3ReversePoslist(aDoclist, &p); - *pnList = (pSave - p); + *pnList = (int)(pSave - p); } *ppIter = p; } } +/* +** Iterate forwards through a doclist. +*/ +SQLITE_PRIVATE void sqlite3Fts3DoclistNext( + int bDescIdx, /* True if the doclist is desc */ + char *aDoclist, /* Pointer to entire doclist */ + int nDoclist, /* Length of aDoclist in bytes */ + char **ppIter, /* IN/OUT: Iterator pointer */ + sqlite3_int64 *piDocid, /* IN/OUT: Docid pointer */ + u8 *pbEof /* OUT: End-of-file flag */ +){ + char *p = *ppIter; + + assert( nDoclist>0 ); + assert( *pbEof==0 ); + assert( p || *piDocid==0 ); + assert( !p || (p>=aDoclist && p<=&aDoclist[nDoclist]) ); + + if( p==0 ){ + p = aDoclist; + p += sqlite3Fts3GetVarint(p, piDocid); + }else{ + fts3PoslistCopy(0, &p); + if( p>=&aDoclist[nDoclist] ){ + *pbEof = 1; + }else{ + sqlite3_int64 iVar; + p += sqlite3Fts3GetVarint(p, &iVar); + *piDocid += ((bDescIdx ? -1 : 1) * iVar); + } + } + + *ppIter = p; +} + /* ** Attempt to move the phrase iterator to point to the next matching docid. ** If an error occurs, return an SQLite error code. Otherwise, return @@ -120262,7 +121957,7 @@ static int fts3EvalPhraseNext( } pDL->pList = pIter; fts3PoslistCopy(0, &pIter); - pDL->nList = (pIter - pDL->pList); + pDL->nList = (int)(pIter - pDL->pList); /* pIter now points just past the 0x00 that terminates the position- ** list for document pDL->iDocid. However, if this position-list was @@ -120603,7 +122298,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){ fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc); /* Determine which, if any, tokens in the expression should be deferred. */ - if( rc==SQLITE_OK && nToken>1 && pTab->bHasStat ){ + if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){ Fts3TokenAndCost *aTC; Fts3Expr **apOr; aTC = (Fts3TokenAndCost *)sqlite3_malloc( @@ -120620,8 +122315,8 @@ static int fts3EvalStart(Fts3Cursor *pCsr){ Fts3Expr **ppOr = apOr; fts3EvalTokenCosts(pCsr, 0, pCsr->pExpr, &pTC, &ppOr, &rc); - nToken = pTC-aTC; - nOr = ppOr-apOr; + nToken = (int)(pTC-aTC); + nOr = (int)(ppOr-apOr); if( rc==SQLITE_OK ){ rc = fts3EvalSelectDeferred(pCsr, 0, aTC, nToken); @@ -120693,7 +122388,7 @@ static int fts3EvalNearTrim( &pOut, aTmp, nParam1, nParam2, paPoslist, &p2 ); if( res ){ - nNew = (pOut - pPhrase->doclist.pList) - 1; + nNew = (int)(pOut - pPhrase->doclist.pList) - 1; assert( pPhrase->doclist.pList[nNew]=='\0' ); assert( nNew<=pPhrase->doclist.nList && nNew>0 ); memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew); @@ -121363,26 +123058,87 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats( ** This function works regardless of whether or not the phrase is deferred, ** incremental, or neither. */ -SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist( +SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist( Fts3Cursor *pCsr, /* FTS3 cursor object */ Fts3Expr *pExpr, /* Phrase to return doclist for */ - int iCol /* Column to return position list for */ + int iCol, /* Column to return position list for */ + char **ppOut /* OUT: Pointer to position list */ ){ Fts3Phrase *pPhrase = pExpr->pPhrase; Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; - char *pIter = pPhrase->doclist.pList; + char *pIter; int iThis; + sqlite3_int64 iDocid; + /* If this phrase is applies specifically to some column other than + ** column iCol, return a NULL pointer. */ + *ppOut = 0; assert( iCol>=0 && iColnColumn ); - if( !pIter - || pExpr->bEof - || pExpr->iDocid!=pCsr->iPrevId - || (pPhrase->iColumnnColumn && pPhrase->iColumn!=iCol) - ){ - return 0; + if( (pPhrase->iColumnnColumn && pPhrase->iColumn!=iCol) ){ + return SQLITE_OK; } - assert( pPhrase->doclist.nList>0 ); + iDocid = pExpr->iDocid; + pIter = pPhrase->doclist.pList; + if( iDocid!=pCsr->iPrevId || pExpr->bEof ){ + int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */ + int bOr = 0; + u8 bEof = 0; + Fts3Expr *p; + + /* Check if this phrase descends from an OR expression node. If not, + ** return NULL. Otherwise, the entry that corresponds to docid + ** pCsr->iPrevId may lie earlier in the doclist buffer. */ + for(p=pExpr->pParent; p; p=p->pParent){ + if( p->eType==FTSQUERY_OR ) bOr = 1; + } + if( bOr==0 ) return SQLITE_OK; + + /* This is the descendent of an OR node. In this case we cannot use + ** an incremental phrase. Load the entire doclist for the phrase + ** into memory in this case. */ + if( pPhrase->bIncr ){ + int rc = SQLITE_OK; + int bEofSave = pExpr->bEof; + fts3EvalRestart(pCsr, pExpr, &rc); + while( rc==SQLITE_OK && !pExpr->bEof ){ + fts3EvalNextRow(pCsr, pExpr, &rc); + if( bEofSave==0 && pExpr->iDocid==iDocid ) break; + } + pIter = pPhrase->doclist.pList; + assert( rc!=SQLITE_OK || pPhrase->bIncr==0 ); + if( rc!=SQLITE_OK ) return rc; + } + + if( pExpr->bEof ){ + pIter = 0; + iDocid = 0; + } + bEof = (pPhrase->doclist.nAll==0); + assert( bDescDoclist==0 || bDescDoclist==1 ); + assert( pCsr->bDesc==0 || pCsr->bDesc==1 ); + + if( pCsr->bDesc==bDescDoclist ){ + int dummy; + while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)>0 ) && bEof==0 ){ + sqlite3Fts3DoclistPrev( + bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, + &pIter, &iDocid, &dummy, &bEof + ); + } + }else{ + while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){ + sqlite3Fts3DoclistNext( + bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll, + &pIter, &iDocid, &bEof + ); + } + } + + if( bEof || iDocid!=pCsr->iPrevId ) pIter = 0; + } + if( pIter==0 ) return SQLITE_OK; + if( *pIter==0x01 ){ pIter++; pIter += sqlite3Fts3GetVarint32(pIter, &iThis); @@ -121396,7 +123152,8 @@ SQLITE_PRIVATE char *sqlite3Fts3EvalPhrasePoslist( pIter += sqlite3Fts3GetVarint32(pIter, &iThis); } - return ((iCol==iThis)?pIter:0); + *ppOut = ((iCol==iThis)?pIter:0); + return SQLITE_OK; } /* @@ -121419,6 +123176,7 @@ SQLITE_PRIVATE void sqlite3Fts3EvalPhraseCleanup(Fts3Phrase *pPhrase){ } } + /* ** Return SQLITE_CORRUPT_VTAB. */ @@ -121526,9 +123284,9 @@ static int fts3auxConnectMethod( } zDb = argv[1]; - nDb = strlen(zDb); + nDb = (int)strlen(zDb); zFts3 = argv[3]; - nFts3 = strlen(zFts3); + nFts3 = (int)strlen(zFts3); rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA); if( rc!=SQLITE_OK ) return rc; @@ -121823,7 +123581,7 @@ static int fts3auxFilterMethod( if( pCsr->zStop==0 ) return SQLITE_NOMEM; } - rc = sqlite3Fts3SegReaderCursor(pFts3, 0, FTS3_SEGCURSOR_ALL, + rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL, pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr ); if( rc==SQLITE_OK ){ @@ -122015,6 +123773,7 @@ SQLITE_API int sqlite3_fts3_enable_parentheses = 0; typedef struct ParseContext ParseContext; struct ParseContext { sqlite3_tokenizer *pTokenizer; /* Tokenizer module */ + int iLangid; /* Language id used with tokenizer */ const char **azCol; /* Array of column names for fts3 table */ int bFts4; /* True to allow FTS4-only syntax */ int nCol; /* Number of entries in azCol[] */ @@ -122050,6 +123809,33 @@ static void *fts3MallocZero(int nByte){ return pRet; } +SQLITE_PRIVATE int sqlite3Fts3OpenTokenizer( + sqlite3_tokenizer *pTokenizer, + int iLangid, + const char *z, + int n, + sqlite3_tokenizer_cursor **ppCsr +){ + sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; + sqlite3_tokenizer_cursor *pCsr = 0; + int rc; + + rc = pModule->xOpen(pTokenizer, z, n, &pCsr); + assert( rc==SQLITE_OK || pCsr==0 ); + if( rc==SQLITE_OK ){ + pCsr->pTokenizer = pTokenizer; + if( pModule->iVersion>=1 ){ + rc = pModule->xLanguageid(pCsr, iLangid); + if( rc!=SQLITE_OK ){ + pModule->xClose(pCsr); + pCsr = 0; + } + } + } + *ppCsr = pCsr; + return rc; +} + /* ** Extract the next token from buffer z (length n) using the tokenizer @@ -122077,15 +123863,13 @@ static int getNextToken( Fts3Expr *pRet = 0; int nConsumed = 0; - rc = pModule->xOpen(pTokenizer, z, n, &pCursor); + rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); if( rc==SQLITE_OK ){ const char *zToken; int nToken, iStart, iEnd, iPosition; int nByte; /* total space to allocate */ - pCursor->pTokenizer = pTokenizer; rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); - if( rc==SQLITE_OK ){ nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; pRet = (Fts3Expr *)fts3MallocZero(nByte); @@ -122191,10 +123975,10 @@ static int getNextString( ** appends buffer zTemp to buffer p, and fills in the Fts3Expr and Fts3Phrase ** structures. */ - rc = pModule->xOpen(pTokenizer, zInput, nInput, &pCursor); + rc = sqlite3Fts3OpenTokenizer( + pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); if( rc==SQLITE_OK ){ int ii; - pCursor->pTokenizer = pTokenizer; for(ii=0; rc==SQLITE_OK; ii++){ const char *zByte; int nByte, iBegin, iEnd, iPos; @@ -122668,6 +124452,7 @@ exprparse_out: */ SQLITE_PRIVATE int sqlite3Fts3ExprParse( sqlite3_tokenizer *pTokenizer, /* Tokenizer module */ + int iLangid, /* Language id for tokenizer */ char **azCol, /* Array of column names for fts3 table */ int bFts4, /* True to allow FTS4-only syntax */ int nCol, /* Number of entries in azCol[] */ @@ -122678,11 +124463,13 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse( int nParsed; int rc; ParseContext sParse; + + memset(&sParse, 0, sizeof(ParseContext)); sParse.pTokenizer = pTokenizer; + sParse.iLangid = iLangid; sParse.azCol = (const char **)azCol; sParse.nCol = nCol; sParse.iDefaultCol = iDefaultCol; - sParse.nNest = 0; sParse.bFts4 = bFts4; if( z==0 ){ *ppExpr = 0; @@ -122873,7 +124660,7 @@ static void fts3ExprTest( } rc = sqlite3Fts3ExprParse( - pTokenizer, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr + pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr ); if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ sqlite3_result_error(context, "Error parsing expression", -1); @@ -123922,6 +125709,7 @@ static const sqlite3_tokenizer_module porterTokenizerModule = { porterOpen, porterClose, porterNext, + 0 }; /* @@ -124148,10 +125936,9 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer( /* ** Implementation of a special SQL scalar function for testing tokenizers ** designed to be used in concert with the Tcl testing framework. This -** function must be called with two arguments: +** function must be called with two or more arguments: ** -** SELECT (, ); -** SELECT (, ); +** SELECT (, ..., ); ** ** where is the name passed as the second argument ** to the sqlite3Fts3InitHashTable() function (e.g. 'fts3_tokenizer') @@ -124188,27 +125975,27 @@ static void testFunc( const char *zInput; int nInput; - const char *zArg = 0; + const char *azArg[64]; const char *zToken; int nToken; int iStart; int iEnd; int iPos; + int i; Tcl_Obj *pRet; - assert( argc==2 || argc==3 ); + if( argc<2 ){ + sqlite3_result_error(context, "insufficient arguments", -1); + return; + } nName = sqlite3_value_bytes(argv[0]); zName = (const char *)sqlite3_value_text(argv[0]); nInput = sqlite3_value_bytes(argv[argc-1]); zInput = (const char *)sqlite3_value_text(argv[argc-1]); - if( argc==3 ){ - zArg = (const char *)sqlite3_value_text(argv[1]); - } - pHash = (Fts3Hash *)sqlite3_user_data(context); p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1); @@ -124222,16 +126009,19 @@ static void testFunc( pRet = Tcl_NewObj(); Tcl_IncrRefCount(pRet); - if( SQLITE_OK!=p->xCreate(zArg ? 1 : 0, &zArg, &pTokenizer) ){ + for(i=1; ixCreate(argc-2, azArg, &pTokenizer) ){ zErr = "error in xCreate()"; goto finish; } pTokenizer->pModule = p; - if( SQLITE_OK!=p->xOpen(pTokenizer, zInput, nInput, &pCsr) ){ + if( sqlite3Fts3OpenTokenizer(pTokenizer, 0, zInput, nInput, &pCsr) ){ zErr = "error in xOpen()"; goto finish; } - pCsr->pTokenizer = pTokenizer; while( SQLITE_OK==p->xNext(pCsr, &zToken, &nToken, &iStart, &iEnd, &iPos) ){ Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(iPos)); @@ -124407,10 +126197,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitHashTable( } #ifdef SQLITE_TEST if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zTest, 2, any, p, testFunc, 0, 0); - } - if( SQLITE_OK==rc ){ - rc = sqlite3_create_function(db, zTest, 3, any, p, testFunc, 0, 0); + rc = sqlite3_create_function(db, zTest, -1, any, p, testFunc, 0, 0); } if( SQLITE_OK==rc ){ rc = sqlite3_create_function(db, zTest2, 0, any, pdb, intTestFunc, 0, 0); @@ -124647,6 +126434,7 @@ static const sqlite3_tokenizer_module simpleTokenizerModule = { simpleOpen, simpleClose, simpleNext, + 0, }; /* @@ -124688,6 +126476,9 @@ SQLITE_PRIVATE void sqlite3Fts3SimpleTokenizerModule( /* #include */ /* #include */ + +#define FTS_MAX_APPENDABLE_HEIGHT 16 + /* ** When full-text index nodes are loaded from disk, the buffer that they ** are loaded into has the following number of bytes of padding at the end @@ -124727,6 +126518,29 @@ int test_fts3_node_chunk_threshold = (4*1024)*4; # define FTS3_NODE_CHUNK_THRESHOLD (FTS3_NODE_CHUNKSIZE*4) #endif +/* +** The two values that may be meaningfully bound to the :1 parameter in +** statements SQL_REPLACE_STAT and SQL_SELECT_STAT. +*/ +#define FTS_STAT_DOCTOTAL 0 +#define FTS_STAT_INCRMERGEHINT 1 +#define FTS_STAT_AUTOINCRMERGE 2 + +/* +** If FTS_LOG_MERGES is defined, call sqlite3_log() to report each automatic +** and incremental merge operation that takes place. This is used for +** debugging FTS only, it should not usually be turned on in production +** systems. +*/ +#ifdef FTS3_LOG_MERGES +static void fts3LogMerge(int nMerge, sqlite3_int64 iAbsLevel){ + sqlite3_log(SQLITE_OK, "%d-way merge from level %d", nMerge, (int)iAbsLevel); +} +#else +#define fts3LogMerge(x, y) +#endif + + typedef struct PendingList PendingList; typedef struct SegmentNode SegmentNode; typedef struct SegmentWriter SegmentWriter; @@ -124774,6 +126588,8 @@ struct Fts3DeferredToken { */ struct Fts3SegReader { int iIdx; /* Index within level, or 0x7FFFFFFF for PT */ + u8 bLookup; /* True for a lookup only */ + u8 rootOnly; /* True for a root-only reader */ sqlite3_int64 iStartBlock; /* Rowid of first leaf block to traverse */ sqlite3_int64 iLeafEndBlock; /* Rowid of final leaf block to traverse */ @@ -124807,7 +126623,7 @@ struct Fts3SegReader { }; #define fts3SegReaderIsPending(p) ((p)->ppNextElem!=0) -#define fts3SegReaderIsRootOnly(p) ((p)->aNode==(char *)&(p)[1]) +#define fts3SegReaderIsRootOnly(p) ((p)->rootOnly!=0) /* ** An instance of this structure is used to create a segment b-tree in the @@ -124887,13 +126703,22 @@ struct SegmentNode { #define SQL_DELETE_DOCSIZE 19 #define SQL_REPLACE_DOCSIZE 20 #define SQL_SELECT_DOCSIZE 21 -#define SQL_SELECT_DOCTOTAL 22 -#define SQL_REPLACE_DOCTOTAL 23 +#define SQL_SELECT_STAT 22 +#define SQL_REPLACE_STAT 23 #define SQL_SELECT_ALL_PREFIX_LEVEL 24 #define SQL_DELETE_ALL_TERMS_SEGDIR 25 - #define SQL_DELETE_SEGDIR_RANGE 26 +#define SQL_SELECT_ALL_LANGID 27 +#define SQL_FIND_MERGE_LEVEL 28 +#define SQL_MAX_LEAF_NODE_ESTIMATE 29 +#define SQL_DELETE_SEGDIR_ENTRY 30 +#define SQL_SHIFT_SEGDIR_ENTRY 31 +#define SQL_SELECT_SEGDIR 32 +#define SQL_CHOMP_SEGDIR 33 +#define SQL_SEGMENT_IS_APPENDABLE 34 +#define SQL_SELECT_INDEXES 35 +#define SQL_SELECT_MXLEVEL 36 /* ** This function is used to obtain an SQLite prepared statement handle @@ -124922,9 +126747,9 @@ static int fts3SqlStmt( /* 6 */ "DELETE FROM %Q.'%q_stat'", /* 7 */ "SELECT %s WHERE rowid=?", /* 8 */ "SELECT (SELECT max(idx) FROM %Q.'%q_segdir' WHERE level = ?) + 1", -/* 9 */ "INSERT INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", +/* 9 */ "REPLACE INTO %Q.'%q_segments'(blockid, block) VALUES(?, ?)", /* 10 */ "SELECT coalesce((SELECT max(blockid) FROM %Q.'%q_segments') + 1, 1)", -/* 11 */ "INSERT INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", +/* 11 */ "REPLACE INTO %Q.'%q_segdir' VALUES(?,?,?,?,?,?)", /* Return segments in order from oldest to newest.*/ /* 12 */ "SELECT idx, start_block, leaves_end_block, end_block, root " @@ -124942,13 +126767,61 @@ static int fts3SqlStmt( /* 19 */ "DELETE FROM %Q.'%q_docsize' WHERE docid = ?", /* 20 */ "REPLACE INTO %Q.'%q_docsize' VALUES(?,?)", /* 21 */ "SELECT size FROM %Q.'%q_docsize' WHERE docid=?", -/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=0", -/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(0,?)", +/* 22 */ "SELECT value FROM %Q.'%q_stat' WHERE id=?", +/* 23 */ "REPLACE INTO %Q.'%q_stat' VALUES(?,?)", /* 24 */ "", /* 25 */ "", /* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?", +/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'", +/* This statement is used to determine which level to read the input from +** when performing an incremental merge. It returns the absolute level number +** of the oldest level in the db that contains at least ? segments. Or, +** if no level in the FTS index contains more than ? segments, the statement +** returns zero rows. */ +/* 28 */ "SELECT level FROM %Q.'%q_segdir' GROUP BY level HAVING count(*)>=?" + " ORDER BY (level %% 1024) ASC LIMIT 1", + +/* Estimate the upper limit on the number of leaf nodes in a new segment +** created by merging the oldest :2 segments from absolute level :1. See +** function sqlite3Fts3Incrmerge() for details. */ +/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) " + " FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?", + +/* SQL_DELETE_SEGDIR_ENTRY +** Delete the %_segdir entry on absolute level :1 with index :2. */ +/* 30 */ "DELETE FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", + +/* SQL_SHIFT_SEGDIR_ENTRY +** Modify the idx value for the segment with idx=:3 on absolute level :2 +** to :1. */ +/* 31 */ "UPDATE %Q.'%q_segdir' SET idx = ? WHERE level=? AND idx=?", + +/* SQL_SELECT_SEGDIR +** Read a single entry from the %_segdir table. The entry from absolute +** level :1 with index value :2. */ +/* 32 */ "SELECT idx, start_block, leaves_end_block, end_block, root " + "FROM %Q.'%q_segdir' WHERE level = ? AND idx = ?", + +/* SQL_CHOMP_SEGDIR +** Update the start_block (:1) and root (:2) fields of the %_segdir +** entry located on absolute level :3 with index :4. */ +/* 33 */ "UPDATE %Q.'%q_segdir' SET start_block = ?, root = ?" + "WHERE level = ? AND idx = ?", + +/* SQL_SEGMENT_IS_APPENDABLE +** Return a single row if the segment with end_block=? is appendable. Or +** no rows otherwise. */ +/* 34 */ "SELECT 1 FROM %Q.'%q_segments' WHERE blockid=? AND block IS NULL", + +/* SQL_SELECT_INDEXES +** Return the list of valid segment indexes for absolute level ? */ +/* 35 */ "SELECT idx FROM %Q.'%q_segdir' WHERE level=? ORDER BY 1 ASC", + +/* SQL_SELECT_MXLEVEL +** Return the largest relative level in the FTS index or indexes. */ +/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'" }; int rc = SQLITE_OK; sqlite3_stmt *pStmt; @@ -124986,22 +126859,18 @@ static int fts3SqlStmt( return rc; } + static int fts3SelectDocsize( Fts3Table *pTab, /* FTS3 table handle */ - int eStmt, /* Either SQL_SELECT_DOCSIZE or DOCTOTAL */ sqlite3_int64 iDocid, /* Docid to bind for SQL_SELECT_DOCSIZE */ sqlite3_stmt **ppStmt /* OUT: Statement handle */ ){ sqlite3_stmt *pStmt = 0; /* Statement requested from fts3SqlStmt() */ int rc; /* Return code */ - assert( eStmt==SQL_SELECT_DOCSIZE || eStmt==SQL_SELECT_DOCTOTAL ); - - rc = fts3SqlStmt(pTab, eStmt, &pStmt, 0); + rc = fts3SqlStmt(pTab, SQL_SELECT_DOCSIZE, &pStmt, 0); if( rc==SQLITE_OK ){ - if( eStmt==SQL_SELECT_DOCSIZE ){ - sqlite3_bind_int64(pStmt, 1, iDocid); - } + sqlite3_bind_int64(pStmt, 1, iDocid); rc = sqlite3_step(pStmt); if( rc!=SQLITE_ROW || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB ){ rc = sqlite3_reset(pStmt); @@ -125020,7 +126889,21 @@ SQLITE_PRIVATE int sqlite3Fts3SelectDoctotal( Fts3Table *pTab, /* Fts3 table handle */ sqlite3_stmt **ppStmt /* OUT: Statement handle */ ){ - return fts3SelectDocsize(pTab, SQL_SELECT_DOCTOTAL, 0, ppStmt); + sqlite3_stmt *pStmt = 0; + int rc; + rc = fts3SqlStmt(pTab, SQL_SELECT_STAT, &pStmt, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); + if( sqlite3_step(pStmt)!=SQLITE_ROW + || sqlite3_column_type(pStmt, 0)!=SQLITE_BLOB + ){ + rc = sqlite3_reset(pStmt); + if( rc==SQLITE_OK ) rc = FTS_CORRUPT_VTAB; + pStmt = 0; + } + } + *ppStmt = pStmt; + return rc; } SQLITE_PRIVATE int sqlite3Fts3SelectDocsize( @@ -125028,7 +126911,7 @@ SQLITE_PRIVATE int sqlite3Fts3SelectDocsize( sqlite3_int64 iDocid, /* Docid to read size data for */ sqlite3_stmt **ppStmt /* OUT: Statement handle */ ){ - return fts3SelectDocsize(pTab, SQL_SELECT_DOCSIZE, iDocid, ppStmt); + return fts3SelectDocsize(pTab, iDocid, ppStmt); } /* @@ -125094,6 +126977,44 @@ SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *p){ return rc; } +/* +** FTS maintains a separate indexes for each language-id (a 32-bit integer). +** Within each language id, a separate index is maintained to store the +** document terms, and each configured prefix size (configured the FTS +** "prefix=" option). And each index consists of multiple levels ("relative +** levels"). +** +** All three of these values (the language id, the specific index and the +** level within the index) are encoded in 64-bit integer values stored +** in the %_segdir table on disk. This function is used to convert three +** separate component values into the single 64-bit integer value that +** can be used to query the %_segdir table. +** +** Specifically, each language-id/index combination is allocated 1024 +** 64-bit integer level values ("absolute levels"). The main terms index +** for language-id 0 is allocate values 0-1023. The first prefix index +** (if any) for language-id 0 is allocated values 1024-2047. And so on. +** Language 1 indexes are allocated immediately following language 0. +** +** So, for a system with nPrefix prefix indexes configured, the block of +** absolute levels that corresponds to language-id iLangid and index +** iIndex starts at absolute level ((iLangid * (nPrefix+1) + iIndex) * 1024). +*/ +static sqlite3_int64 getAbsoluteLevel( + Fts3Table *p, /* FTS3 table handle */ + int iLangid, /* Language id */ + int iIndex, /* Index in p->aIndex[] */ + int iLevel /* Level of segments */ +){ + sqlite3_int64 iBase; /* First absolute level for iLangid/iIndex */ + assert( iLangid>=0 ); + assert( p->nIndex>0 ); + assert( iIndex>=0 && iIndexnIndex ); + + iBase = ((sqlite3_int64)iLangid * p->nIndex + iIndex) * FTS3_SEGDIR_MAXLEVEL; + return iBase + iLevel; +} + /* ** Set *ppStmt to a statement handle that may be used to iterate through ** all rows in the %_segdir table, from oldest to newest. If successful, @@ -125113,8 +127034,9 @@ SQLITE_PRIVATE int sqlite3Fts3ReadLock(Fts3Table *p){ */ SQLITE_PRIVATE int sqlite3Fts3AllSegdirs( Fts3Table *p, /* FTS3 table */ + int iLangid, /* Language being queried */ int iIndex, /* Index for p->aIndex[] */ - int iLevel, /* Level to select */ + int iLevel, /* Level to select (relative level) */ sqlite3_stmt **ppStmt /* OUT: Compiled statement */ ){ int rc; @@ -125128,14 +127050,16 @@ SQLITE_PRIVATE int sqlite3Fts3AllSegdirs( /* "SELECT * FROM %_segdir WHERE level BETWEEN ? AND ? ORDER BY ..." */ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE, &pStmt, 0); if( rc==SQLITE_OK ){ - sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); - sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL-1); + sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); + sqlite3_bind_int64(pStmt, 2, + getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) + ); } }else{ /* "SELECT * FROM %_segdir WHERE level = ? ORDER BY ..." */ rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); if( rc==SQLITE_OK ){ - sqlite3_bind_int(pStmt, 1, iLevel+iIndex*FTS3_SEGDIR_MAXLEVEL); + sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex,iLevel)); } } *ppStmt = pStmt; @@ -125301,6 +127225,7 @@ static int fts3PendingTermsAddOne( */ static int fts3PendingTermsAdd( Fts3Table *p, /* Table into which text will be inserted */ + int iLangid, /* Language id to use */ const char *zText, /* Text of document to be inserted */ int iCol, /* Column into which text is being inserted */ u32 *pnWord /* OUT: Number of tokens inserted */ @@ -125330,11 +127255,10 @@ static int fts3PendingTermsAdd( return SQLITE_OK; } - rc = pModule->xOpen(pTokenizer, zText, -1, &pCsr); + rc = sqlite3Fts3OpenTokenizer(pTokenizer, iLangid, zText, -1, &pCsr); if( rc!=SQLITE_OK ){ return rc; } - pCsr->pTokenizer = pTokenizer; xNext = pModule->xNext; while( SQLITE_OK==rc @@ -125377,18 +127301,28 @@ static int fts3PendingTermsAdd( ** fts3PendingTermsAdd() are to add term/position-list pairs for the ** contents of the document with docid iDocid. */ -static int fts3PendingTermsDocid(Fts3Table *p, sqlite_int64 iDocid){ +static int fts3PendingTermsDocid( + Fts3Table *p, /* Full-text table handle */ + int iLangid, /* Language id of row being written */ + sqlite_int64 iDocid /* Docid of row being written */ +){ + assert( iLangid>=0 ); + /* TODO(shess) Explore whether partially flushing the buffer on ** forced-flush would provide better performance. I suspect that if ** we ordered the doclists by size and flushed the largest until the ** buffer was half empty, that would let the less frequent terms ** generate longer doclists. */ - if( iDocid<=p->iPrevDocid || p->nPendingData>p->nMaxPendingData ){ + if( iDocid<=p->iPrevDocid + || p->iPrevLangid!=iLangid + || p->nPendingData>p->nMaxPendingData + ){ int rc = sqlite3Fts3PendingTermsFlush(p); if( rc!=SQLITE_OK ) return rc; } p->iPrevDocid = iDocid; + p->iPrevLangid = iLangid; return SQLITE_OK; } @@ -125417,11 +127351,16 @@ SQLITE_PRIVATE void sqlite3Fts3PendingTermsClear(Fts3Table *p){ ** Argument apVal is the same as the similarly named argument passed to ** fts3InsertData(). Parameter iDocid is the docid of the new row. */ -static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){ +static int fts3InsertTerms( + Fts3Table *p, + int iLangid, + sqlite3_value **apVal, + u32 *aSz +){ int i; /* Iterator variable */ for(i=2; inColumn+2; i++){ const char *zText = (const char *)sqlite3_value_text(apVal[i]); - int rc = fts3PendingTermsAdd(p, zText, i-2, &aSz[i-2]); + int rc = fts3PendingTermsAdd(p, iLangid, zText, i-2, &aSz[i-2]); if( rc!=SQLITE_OK ){ return rc; } @@ -125442,6 +127381,7 @@ static int fts3InsertTerms(Fts3Table *p, sqlite3_value **apVal, u32 *aSz){ ** apVal[p->nColumn+1] Right-most user-defined column ** apVal[p->nColumn+2] Hidden column with same name as table ** apVal[p->nColumn+3] Hidden "docid" column (alias for rowid) +** apVal[p->nColumn+4] Hidden languageid column */ static int fts3InsertData( Fts3Table *p, /* Full-text table */ @@ -125472,9 +127412,13 @@ static int fts3InsertData( ** defined columns in the FTS3 table, plus one for the docid field. */ rc = fts3SqlStmt(p, SQL_CONTENT_INSERT, &pContentInsert, &apVal[1]); - if( rc!=SQLITE_OK ){ - return rc; + if( rc==SQLITE_OK && p->zLanguageid ){ + rc = sqlite3_bind_int( + pContentInsert, p->nColumn+2, + sqlite3_value_int(apVal[p->nColumn+4]) + ); } + if( rc!=SQLITE_OK ) return rc; /* There is a quirk here. The users INSERT statement may have specified ** a value for the "rowid" field, for the "docid" field, or for both. @@ -125534,6 +127478,15 @@ static int fts3DeleteAll(Fts3Table *p, int bContent){ return rc; } +/* +** +*/ +static int langidFromSelect(Fts3Table *p, sqlite3_stmt *pSelect){ + int iLangid = 0; + if( p->zLanguageid ) iLangid = sqlite3_column_int(pSelect, p->nColumn+1); + return iLangid; +} + /* ** The first element in the apVal[] array is assumed to contain the docid ** (an integer) of a row about to be deleted. Remove all terms from the @@ -125553,16 +127506,18 @@ static void fts3DeleteTerms( if( rc==SQLITE_OK ){ if( SQLITE_ROW==sqlite3_step(pSelect) ){ int i; - for(i=1; i<=p->nColumn; i++){ + int iLangid = langidFromSelect(p, pSelect); + rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); + for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ const char *zText = (const char *)sqlite3_column_text(pSelect, i); - rc = fts3PendingTermsAdd(p, zText, -1, &aSz[i-1]); - if( rc!=SQLITE_OK ){ - sqlite3_reset(pSelect); - *pRC = rc; - return; - } + rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]); aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); } + if( rc!=SQLITE_OK ){ + sqlite3_reset(pSelect); + *pRC = rc; + return; + } } rc = sqlite3_reset(pSelect); }else{ @@ -125575,7 +127530,7 @@ static void fts3DeleteTerms( ** Forward declaration to account for the circular dependency between ** functions fts3SegmentMerge() and fts3AllocateSegdirIdx(). */ -static int fts3SegmentMerge(Fts3Table *, int, int); +static int fts3SegmentMerge(Fts3Table *, int, int, int); /* ** This function allocates a new level iLevel index in the segdir table. @@ -125594,6 +127549,7 @@ static int fts3SegmentMerge(Fts3Table *, int, int); */ static int fts3AllocateSegdirIdx( Fts3Table *p, + int iLangid, /* Language id */ int iIndex, /* Index for p->aIndex */ int iLevel, int *piIdx @@ -125602,10 +127558,15 @@ static int fts3AllocateSegdirIdx( sqlite3_stmt *pNextIdx; /* Query for next idx at level iLevel */ int iNext = 0; /* Result of query pNextIdx */ + assert( iLangid>=0 ); + assert( p->nIndex>=1 ); + /* Set variable iNext to the next available segdir index at level iLevel. */ rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pNextIdx, 0); if( rc==SQLITE_OK ){ - sqlite3_bind_int(pNextIdx, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel); + sqlite3_bind_int64( + pNextIdx, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) + ); if( SQLITE_ROW==sqlite3_step(pNextIdx) ){ iNext = sqlite3_column_int(pNextIdx, 0); } @@ -125619,7 +127580,8 @@ static int fts3AllocateSegdirIdx( ** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext. */ if( iNext>=FTS3_MERGE_COUNT ){ - rc = fts3SegmentMerge(p, iIndex, iLevel); + fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel)); + rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel); *piIdx = 0; }else{ *piIdx = iNext; @@ -125666,7 +127628,7 @@ SQLITE_PRIVATE int sqlite3Fts3ReadBlock( int rc; /* Return code */ /* pnBlob must be non-NULL. paBlob may be NULL or non-NULL. */ - assert( pnBlob); + assert( pnBlob ); if( p->pSegments ){ rc = sqlite3_blob_reopen(p->pSegments, iBlockid); @@ -125752,6 +127714,18 @@ static int fts3SegReaderRequire(Fts3SegReader *pReader, char *pFrom, int nByte){ return rc; } +/* +** Set an Fts3SegReader cursor to point at EOF. +*/ +static void fts3SegReaderSetEof(Fts3SegReader *pSeg){ + if( !fts3SegReaderIsRootOnly(pSeg) ){ + sqlite3_free(pSeg->aNode); + sqlite3_blob_close(pSeg->pBlob); + pSeg->pBlob = 0; + } + pSeg->aNode = 0; +} + /* ** Move the iterator passed as the first argument to the next term in the ** segment. If successful, SQLITE_OK is returned. If there is no next term, @@ -125791,12 +127765,7 @@ static int fts3SegReaderNext( return SQLITE_OK; } - if( !fts3SegReaderIsRootOnly(pReader) ){ - sqlite3_free(pReader->aNode); - sqlite3_blob_close(pReader->pBlob); - pReader->pBlob = 0; - } - pReader->aNode = 0; + fts3SegReaderSetEof(pReader); /* If iCurrentBlock>=iLeafEndBlock, this is an EOF condition. All leaf ** blocks have already been traversed. */ @@ -126000,7 +127969,7 @@ SQLITE_PRIVATE int sqlite3Fts3MsrOvfl( int rc = SQLITE_OK; int pgsz = p->nPgsz; - assert( p->bHasStat ); + assert( p->bFts4 ); assert( pgsz>0 ); for(ii=0; rc==SQLITE_OK && iinSegment; ii++){ @@ -126043,6 +128012,7 @@ SQLITE_PRIVATE void sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){ */ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( int iAge, /* Segment "age". */ + int bLookup, /* True for a lookup only */ sqlite3_int64 iStartLeaf, /* First leaf to traverse */ sqlite3_int64 iEndLeaf, /* Final leaf to traverse */ sqlite3_int64 iEndBlock, /* Final block of segment */ @@ -126064,6 +128034,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( } memset(pReader, 0, sizeof(Fts3SegReader)); pReader->iIdx = iAge; + pReader->bLookup = bLookup!=0; pReader->iStartBlock = iStartLeaf; pReader->iLeafEndBlock = iEndLeaf; pReader->iEndBlock = iEndBlock; @@ -126071,6 +128042,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew( if( nExtra ){ /* The entire segment is stored in the root node. */ pReader->aNode = (char *)&pReader[1]; + pReader->rootOnly = 1; pReader->nNode = nRoot; memcpy(pReader->aNode, zRoot, nRoot); memset(&pReader->aNode[nRoot], 0, FTS3_NODE_PADDING); @@ -126356,12 +128328,33 @@ static int fts3WriteSegment( return rc; } +/* +** Find the largest relative level number in the table. If successful, set +** *pnMax to this value and return SQLITE_OK. Otherwise, if an error occurs, +** set *pnMax to zero and return an SQLite error code. +*/ +SQLITE_PRIVATE int sqlite3Fts3MaxLevel(Fts3Table *p, int *pnMax){ + int rc; + int mxLevel = 0; + sqlite3_stmt *pStmt = 0; + + rc = fts3SqlStmt(p, SQL_SELECT_MXLEVEL, &pStmt, 0); + if( rc==SQLITE_OK ){ + if( SQLITE_ROW==sqlite3_step(pStmt) ){ + mxLevel = sqlite3_column_int(pStmt, 0); + } + rc = sqlite3_reset(pStmt); + } + *pnMax = mxLevel; + return rc; +} + /* ** Insert a record into the %_segdir table. */ static int fts3WriteSegdir( Fts3Table *p, /* Virtual table handle */ - int iLevel, /* Value for "level" field */ + sqlite3_int64 iLevel, /* Value for "level" field (absolute level) */ int iIdx, /* Value for "idx" field */ sqlite3_int64 iStartBlock, /* Value for "start_block" field */ sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */ @@ -126372,7 +128365,7 @@ static int fts3WriteSegdir( sqlite3_stmt *pStmt; int rc = fts3SqlStmt(p, SQL_INSERT_SEGDIR, &pStmt, 0); if( rc==SQLITE_OK ){ - sqlite3_bind_int(pStmt, 1, iLevel); + sqlite3_bind_int64(pStmt, 1, iLevel); sqlite3_bind_int(pStmt, 2, iIdx); sqlite3_bind_int64(pStmt, 3, iStartBlock); sqlite3_bind_int64(pStmt, 4, iLeafEndBlock); @@ -126672,6 +128665,7 @@ static int fts3SegWriterAdd( /* The current leaf node is full. Write it out to the database. */ rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData); if( rc!=SQLITE_OK ) return rc; + p->nLeafAdd++; /* Add the current term to the interior node tree. The term added to ** the interior tree must: @@ -126755,7 +128749,7 @@ static int fts3SegWriterAdd( static int fts3SegWriterFlush( Fts3Table *p, /* Virtual table handle */ SegmentWriter *pWriter, /* SegmentWriter to flush to the db */ - int iLevel, /* Value for 'level' column of %_segdir */ + sqlite3_int64 iLevel, /* Value for 'level' column of %_segdir */ int iIdx /* Value for 'idx' column of %_segdir */ ){ int rc; /* Return code */ @@ -126780,6 +128774,7 @@ static int fts3SegWriterFlush( rc = fts3WriteSegdir( p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData); } + p->nLeafAdd++; return rc; } @@ -126833,7 +128828,12 @@ static int fts3IsEmpty(Fts3Table *p, sqlite3_value *pRowid, int *pisEmpty){ ** ** Return SQLITE_OK if successful, or an SQLite error code if not. */ -static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){ +static int fts3SegmentMaxLevel( + Fts3Table *p, + int iLangid, + int iIndex, + sqlite3_int64 *pnMax +){ sqlite3_stmt *pStmt; int rc; assert( iIndex>=0 && iIndexnIndex ); @@ -126846,14 +128846,39 @@ static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){ */ rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; - sqlite3_bind_int(pStmt, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); - sqlite3_bind_int(pStmt, 2, (iIndex+1)*FTS3_SEGDIR_MAXLEVEL - 1); + sqlite3_bind_int64(pStmt, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); + sqlite3_bind_int64(pStmt, 2, + getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) + ); if( SQLITE_ROW==sqlite3_step(pStmt) ){ - *pnMax = sqlite3_column_int(pStmt, 0); + *pnMax = sqlite3_column_int64(pStmt, 0); } return sqlite3_reset(pStmt); } +/* +** Delete all entries in the %_segments table associated with the segment +** opened with seg-reader pSeg. This function does not affect the contents +** of the %_segdir table. +*/ +static int fts3DeleteSegment( + Fts3Table *p, /* FTS table handle */ + Fts3SegReader *pSeg /* Segment to delete */ +){ + int rc = SQLITE_OK; /* Return code */ + if( pSeg->iStartBlock ){ + sqlite3_stmt *pDelete; /* SQL statement to delete rows */ + rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pDelete, 1, pSeg->iStartBlock); + sqlite3_bind_int64(pDelete, 2, pSeg->iEndBlock); + sqlite3_step(pDelete); + rc = sqlite3_reset(pDelete); + } + } + return rc; +} + /* ** This function is used after merging multiple segments into a single large ** segment to delete the old, now redundant, segment b-trees. Specifically, @@ -126870,24 +128895,18 @@ static int fts3SegmentMaxLevel(Fts3Table *p, int iIndex, int *pnMax){ */ static int fts3DeleteSegdir( Fts3Table *p, /* Virtual table handle */ + int iLangid, /* Language id */ int iIndex, /* Index for p->aIndex */ int iLevel, /* Level of %_segdir entries to delete */ Fts3SegReader **apSegment, /* Array of SegReader objects */ int nReader /* Size of array apSegment */ ){ - int rc; /* Return Code */ + int rc = SQLITE_OK; /* Return Code */ int i; /* Iterator variable */ - sqlite3_stmt *pDelete; /* SQL statement to delete rows */ + sqlite3_stmt *pDelete = 0; /* SQL statement to delete rows */ - rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDelete, 0); for(i=0; rc==SQLITE_OK && iiStartBlock ){ - sqlite3_bind_int64(pDelete, 1, pSegment->iStartBlock); - sqlite3_bind_int64(pDelete, 2, pSegment->iEndBlock); - sqlite3_step(pDelete); - rc = sqlite3_reset(pDelete); - } + rc = fts3DeleteSegment(p, apSegment[i]); } if( rc!=SQLITE_OK ){ return rc; @@ -126897,13 +128916,17 @@ static int fts3DeleteSegdir( if( iLevel==FTS3_SEGCURSOR_ALL ){ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_RANGE, &pDelete, 0); if( rc==SQLITE_OK ){ - sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL); - sqlite3_bind_int(pDelete, 2, (iIndex+1) * FTS3_SEGDIR_MAXLEVEL - 1); + sqlite3_bind_int64(pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, 0)); + sqlite3_bind_int64(pDelete, 2, + getAbsoluteLevel(p, iLangid, iIndex, FTS3_SEGDIR_MAXLEVEL-1) + ); } }else{ rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_LEVEL, &pDelete, 0); if( rc==SQLITE_OK ){ - sqlite3_bind_int(pDelete, 1, iIndex*FTS3_SEGDIR_MAXLEVEL + iLevel); + sqlite3_bind_int64( + pDelete, 1, getAbsoluteLevel(p, iLangid, iIndex, iLevel) + ); } } @@ -127066,11 +129089,16 @@ static int fts3SegReaderStart( ** b-tree leaf nodes contain more than one term. */ for(i=0; pCsr->bRestart==0 && inSegment; i++){ + int res = 0; Fts3SegReader *pSeg = pCsr->apSegment[i]; do { int rc = fts3SegReaderNext(p, pSeg, 0); if( rc!=SQLITE_OK ) return rc; - }while( zTerm && fts3SegReaderTermCmp(pSeg, zTerm, nTerm)<0 ); + }while( zTerm && (res = fts3SegReaderTermCmp(pSeg, zTerm, nTerm))<0 ); + + if( pSeg->bLookup && res!=0 ){ + fts3SegReaderSetEof(pSeg); + } } fts3SegReaderSort(pCsr->apSegment, nSeg, nSeg, fts3SegReaderCmp); @@ -127191,7 +129219,12 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep( ** forward. Then sort the list in order of current term again. */ for(i=0; inAdvance; i++){ - rc = fts3SegReaderNext(p, apSegment[i], 0); + Fts3SegReader *pSeg = apSegment[i]; + if( pSeg->bLookup ){ + fts3SegReaderSetEof(pSeg); + }else{ + rc = fts3SegReaderNext(p, pSeg, 0); + } if( rc!=SQLITE_OK ) return rc; } fts3SegReaderSort(apSegment, nSegment, pCsr->nAdvance, fts3SegReaderCmp); @@ -127362,13 +129395,18 @@ SQLITE_PRIVATE void sqlite3Fts3SegReaderFinish( ** Otherwise, if successful, SQLITE_OK is returned. If an error occurs, ** an SQLite error code is returned. */ -static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){ +static int fts3SegmentMerge( + Fts3Table *p, + int iLangid, /* Language id to merge */ + int iIndex, /* Index in p->aIndex[] to merge */ + int iLevel /* Level to merge */ +){ int rc; /* Return code */ int iIdx = 0; /* Index of new segment */ - int iNewLevel = 0; /* Level/index to create new segment at */ + sqlite3_int64 iNewLevel = 0; /* Level/index to create new segment at */ SegmentWriter *pWriter = 0; /* Used to write the new, merged, segment */ Fts3SegFilter filter; /* Segment term filter condition */ - Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ + Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */ int bIgnoreEmpty = 0; /* True to ignore empty segments */ assert( iLevel==FTS3_SEGCURSOR_ALL @@ -127378,7 +129416,7 @@ static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){ assert( iLevel=0 && iIndexnIndex ); - rc = sqlite3Fts3SegReaderCursor(p, iIndex, iLevel, 0, 0, 1, 0, &csr); + rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr); if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished; if( iLevel==FTS3_SEGCURSOR_ALL ){ @@ -127390,24 +129428,24 @@ static int fts3SegmentMerge(Fts3Table *p, int iIndex, int iLevel){ rc = SQLITE_DONE; goto finished; } - rc = fts3SegmentMaxLevel(p, iIndex, &iNewLevel); + rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel); bIgnoreEmpty = 1; }else if( iLevel==FTS3_SEGCURSOR_PENDING ){ - iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL; - rc = fts3AllocateSegdirIdx(p, iIndex, 0, &iIdx); + iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0); + rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx); }else{ /* This call is to merge all segments at level iLevel. find the next ** available segment index at level iLevel+1. The call to ** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to ** a single iLevel+2 segment if necessary. */ - rc = fts3AllocateSegdirIdx(p, iIndex, iLevel+1, &iIdx); - iNewLevel = iIndex * FTS3_SEGDIR_MAXLEVEL + iLevel+1; + rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx); + iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1); } if( rc!=SQLITE_OK ) goto finished; assert( csr.nSegment>0 ); - assert( iNewLevel>=(iIndex*FTS3_SEGDIR_MAXLEVEL) ); - assert( iNewLevel<((iIndex+1)*FTS3_SEGDIR_MAXLEVEL) ); + assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) ); + assert( iNewLevelnIndex; i++){ - rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_PENDING); + rc = fts3SegmentMerge(p, p->iPrevLangid, i, FTS3_SEGCURSOR_PENDING); if( rc==SQLITE_DONE ) rc = SQLITE_OK; } sqlite3Fts3PendingTermsClear(p); + + /* Determine the auto-incr-merge setting if unknown. If enabled, + ** estimate the number of leaf blocks of content to be written + */ + if( rc==SQLITE_OK && p->bHasStat + && p->bAutoincrmerge==0xff && p->nLeafAdd>0 + ){ + sqlite3_stmt *pStmt = 0; + rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); + rc = sqlite3_step(pStmt); + p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0)); + rc = sqlite3_reset(pStmt); + } + } return rc; } @@ -127557,12 +129614,13 @@ static void fts3UpdateDocTotals( return; } pBlob = (char*)&a[nStat]; - rc = fts3SqlStmt(p, SQL_SELECT_DOCTOTAL, &pStmt, 0); + rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0); if( rc ){ sqlite3_free(a); *pRC = rc; return; } + sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); if( sqlite3_step(pStmt)==SQLITE_ROW ){ fts3DecodeIntArray(nStat, a, sqlite3_column_blob(pStmt, 0), @@ -127570,7 +129628,12 @@ static void fts3UpdateDocTotals( }else{ memset(a, 0, sizeof(u32)*(nStat) ); } - sqlite3_reset(pStmt); + rc = sqlite3_reset(pStmt); + if( rc!=SQLITE_OK ){ + sqlite3_free(a); + *pRC = rc; + return; + } if( nChng<0 && a[0]<(u32)(-nChng) ){ a[0] = 0; }else{ @@ -127586,29 +129649,47 @@ static void fts3UpdateDocTotals( a[i+1] = x; } fts3EncodeIntArray(nStat, a, pBlob, &nBlob); - rc = fts3SqlStmt(p, SQL_REPLACE_DOCTOTAL, &pStmt, 0); + rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); if( rc ){ sqlite3_free(a); *pRC = rc; return; } - sqlite3_bind_blob(pStmt, 1, pBlob, nBlob, SQLITE_STATIC); + sqlite3_bind_int(pStmt, 1, FTS_STAT_DOCTOTAL); + sqlite3_bind_blob(pStmt, 2, pBlob, nBlob, SQLITE_STATIC); sqlite3_step(pStmt); *pRC = sqlite3_reset(pStmt); sqlite3_free(a); } +/* +** Merge the entire database so that there is one segment for each +** iIndex/iLangid combination. +*/ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){ - int i; int bSeenDone = 0; - int rc = SQLITE_OK; - for(i=0; rc==SQLITE_OK && inIndex; i++){ - rc = fts3SegmentMerge(p, i, FTS3_SEGCURSOR_ALL); - if( rc==SQLITE_DONE ){ - bSeenDone = 1; - rc = SQLITE_OK; + int rc; + sqlite3_stmt *pAllLangid = 0; + + rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); + if( rc==SQLITE_OK ){ + int rc2; + sqlite3_bind_int(pAllLangid, 1, p->nIndex); + while( sqlite3_step(pAllLangid)==SQLITE_ROW ){ + int i; + int iLangid = sqlite3_column_int(pAllLangid, 0); + for(i=0; rc==SQLITE_OK && inIndex; i++){ + rc = fts3SegmentMerge(p, iLangid, i, FTS3_SEGCURSOR_ALL); + if( rc==SQLITE_DONE ){ + bSeenDone = 1; + rc = SQLITE_OK; + } + } } + rc2 = sqlite3_reset(pAllLangid); + if( rc==SQLITE_OK ) rc = rc2; } + sqlite3Fts3SegmentsClose(p); sqlite3Fts3PendingTermsClear(p); @@ -127659,11 +129740,12 @@ static int fts3DoRebuild(Fts3Table *p){ while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ int iCol; - rc = fts3PendingTermsDocid(p, sqlite3_column_int64(pStmt, 0)); + int iLangid = langidFromSelect(p, pStmt); + rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); aSz[p->nColumn] = 0; for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); - rc = fts3PendingTermsAdd(p, z, iCol, &aSz[iCol]); + rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); } if( p->bHasDocsize ){ @@ -127679,7 +129761,7 @@ static int fts3DoRebuild(Fts3Table *p){ } } } - if( p->bHasStat ){ + if( p->bFts4 ){ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nEntry); } sqlite3_free(aSz); @@ -127695,6 +129777,1687 @@ static int fts3DoRebuild(Fts3Table *p){ return rc; } + +/* +** This function opens a cursor used to read the input data for an +** incremental merge operation. Specifically, it opens a cursor to scan +** the oldest nSeg segments (idx=0 through idx=(nSeg-1)) in absolute +** level iAbsLevel. +*/ +static int fts3IncrmergeCsr( + Fts3Table *p, /* FTS3 table handle */ + sqlite3_int64 iAbsLevel, /* Absolute level to open */ + int nSeg, /* Number of segments to merge */ + Fts3MultiSegReader *pCsr /* Cursor object to populate */ +){ + int rc; /* Return Code */ + sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */ + int nByte; /* Bytes allocated at pCsr->apSegment[] */ + + /* Allocate space for the Fts3MultiSegReader.aCsr[] array */ + memset(pCsr, 0, sizeof(*pCsr)); + nByte = sizeof(Fts3SegReader *) * nSeg; + pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte); + + if( pCsr->apSegment==0 ){ + rc = SQLITE_NOMEM; + }else{ + memset(pCsr->apSegment, 0, nByte); + rc = fts3SqlStmt(p, SQL_SELECT_LEVEL, &pStmt, 0); + } + if( rc==SQLITE_OK ){ + int i; + int rc2; + sqlite3_bind_int64(pStmt, 1, iAbsLevel); + assert( pCsr->nSegment==0 ); + for(i=0; rc==SQLITE_OK && sqlite3_step(pStmt)==SQLITE_ROW && iapSegment[i] + ); + pCsr->nSegment++; + } + rc2 = sqlite3_reset(pStmt); + if( rc==SQLITE_OK ) rc = rc2; + } + + return rc; +} + +typedef struct IncrmergeWriter IncrmergeWriter; +typedef struct NodeWriter NodeWriter; +typedef struct Blob Blob; +typedef struct NodeReader NodeReader; + +/* +** An instance of the following structure is used as a dynamic buffer +** to build up nodes or other blobs of data in. +** +** The function blobGrowBuffer() is used to extend the allocation. +*/ +struct Blob { + char *a; /* Pointer to allocation */ + int n; /* Number of valid bytes of data in a[] */ + int nAlloc; /* Allocated size of a[] (nAlloc>=n) */ +}; + +/* +** This structure is used to build up buffers containing segment b-tree +** nodes (blocks). +*/ +struct NodeWriter { + sqlite3_int64 iBlock; /* Current block id */ + Blob key; /* Last key written to the current block */ + Blob block; /* Current block image */ +}; + +/* +** An object of this type contains the state required to create or append +** to an appendable b-tree segment. +*/ +struct IncrmergeWriter { + int nLeafEst; /* Space allocated for leaf blocks */ + int nWork; /* Number of leaf pages flushed */ + sqlite3_int64 iAbsLevel; /* Absolute level of input segments */ + int iIdx; /* Index of *output* segment in iAbsLevel+1 */ + sqlite3_int64 iStart; /* Block number of first allocated block */ + sqlite3_int64 iEnd; /* Block number of last allocated block */ + NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT]; +}; + +/* +** An object of the following type is used to read data from a single +** FTS segment node. See the following functions: +** +** nodeReaderInit() +** nodeReaderNext() +** nodeReaderRelease() +*/ +struct NodeReader { + const char *aNode; + int nNode; + int iOff; /* Current offset within aNode[] */ + + /* Output variables. Containing the current node entry. */ + sqlite3_int64 iChild; /* Pointer to child node */ + Blob term; /* Current term */ + const char *aDoclist; /* Pointer to doclist */ + int nDoclist; /* Size of doclist in bytes */ +}; + +/* +** If *pRc is not SQLITE_OK when this function is called, it is a no-op. +** Otherwise, if the allocation at pBlob->a is not already at least nMin +** bytes in size, extend (realloc) it to be so. +** +** If an OOM error occurs, set *pRc to SQLITE_NOMEM and leave pBlob->a +** unmodified. Otherwise, if the allocation succeeds, update pBlob->nAlloc +** to reflect the new size of the pBlob->a[] buffer. +*/ +static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){ + if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){ + int nAlloc = nMin; + char *a = (char *)sqlite3_realloc(pBlob->a, nAlloc); + if( a ){ + pBlob->nAlloc = nAlloc; + pBlob->a = a; + }else{ + *pRc = SQLITE_NOMEM; + } + } +} + +/* +** Attempt to advance the node-reader object passed as the first argument to +** the next entry on the node. +** +** Return an error code if an error occurs (SQLITE_NOMEM is possible). +** Otherwise return SQLITE_OK. If there is no next entry on the node +** (e.g. because the current entry is the last) set NodeReader->aNode to +** NULL to indicate EOF. Otherwise, populate the NodeReader structure output +** variables for the new entry. +*/ +static int nodeReaderNext(NodeReader *p){ + int bFirst = (p->term.n==0); /* True for first term on the node */ + int nPrefix = 0; /* Bytes to copy from previous term */ + int nSuffix = 0; /* Bytes to append to the prefix */ + int rc = SQLITE_OK; /* Return code */ + + assert( p->aNode ); + if( p->iChild && bFirst==0 ) p->iChild++; + if( p->iOff>=p->nNode ){ + /* EOF */ + p->aNode = 0; + }else{ + if( bFirst==0 ){ + p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nPrefix); + } + p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &nSuffix); + + blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc); + if( rc==SQLITE_OK ){ + memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix); + p->term.n = nPrefix+nSuffix; + p->iOff += nSuffix; + if( p->iChild==0 ){ + p->iOff += sqlite3Fts3GetVarint32(&p->aNode[p->iOff], &p->nDoclist); + p->aDoclist = &p->aNode[p->iOff]; + p->iOff += p->nDoclist; + } + } + } + + assert( p->iOff<=p->nNode ); + + return rc; +} + +/* +** Release all dynamic resources held by node-reader object *p. +*/ +static void nodeReaderRelease(NodeReader *p){ + sqlite3_free(p->term.a); +} + +/* +** Initialize a node-reader object to read the node in buffer aNode/nNode. +** +** If successful, SQLITE_OK is returned and the NodeReader object set to +** point to the first entry on the node (if any). Otherwise, an SQLite +** error code is returned. +*/ +static int nodeReaderInit(NodeReader *p, const char *aNode, int nNode){ + memset(p, 0, sizeof(NodeReader)); + p->aNode = aNode; + p->nNode = nNode; + + /* Figure out if this is a leaf or an internal node. */ + if( p->aNode[0] ){ + /* An internal node. */ + p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild); + }else{ + p->iOff = 1; + } + + return nodeReaderNext(p); +} + +/* +** This function is called while writing an FTS segment each time a leaf o +** node is finished and written to disk. The key (zTerm/nTerm) is guaranteed +** to be greater than the largest key on the node just written, but smaller +** than or equal to the first key that will be written to the next leaf +** node. +** +** The block id of the leaf node just written to disk may be found in +** (pWriter->aNodeWriter[0].iBlock) when this function is called. +*/ +static int fts3IncrmergePush( + Fts3Table *p, /* Fts3 table handle */ + IncrmergeWriter *pWriter, /* Writer object */ + const char *zTerm, /* Term to write to internal node */ + int nTerm /* Bytes at zTerm */ +){ + sqlite3_int64 iPtr = pWriter->aNodeWriter[0].iBlock; + int iLayer; + + assert( nTerm>0 ); + for(iLayer=1; ALWAYS(iLayeraNodeWriter[iLayer]; + int rc = SQLITE_OK; + int nPrefix; + int nSuffix; + int nSpace; + + /* Figure out how much space the key will consume if it is written to + ** the current node of layer iLayer. Due to the prefix compression, + ** the space required changes depending on which node the key is to + ** be added to. */ + nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm); + nSuffix = nTerm - nPrefix; + nSpace = sqlite3Fts3VarintLen(nPrefix); + nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; + + if( pNode->key.n==0 || (pNode->block.n + nSpace)<=p->nNodeSize ){ + /* If the current node of layer iLayer contains zero keys, or if adding + ** the key to it will not cause it to grow to larger than nNodeSize + ** bytes in size, write the key here. */ + + Blob *pBlk = &pNode->block; + if( pBlk->n==0 ){ + blobGrowBuffer(pBlk, p->nNodeSize, &rc); + if( rc==SQLITE_OK ){ + pBlk->a[0] = (char)iLayer; + pBlk->n = 1 + sqlite3Fts3PutVarint(&pBlk->a[1], iPtr); + } + } + blobGrowBuffer(pBlk, pBlk->n + nSpace, &rc); + blobGrowBuffer(&pNode->key, nTerm, &rc); + + if( rc==SQLITE_OK ){ + if( pNode->key.n ){ + pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix); + } + pBlk->n += sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix); + memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix); + pBlk->n += nSuffix; + + memcpy(pNode->key.a, zTerm, nTerm); + pNode->key.n = nTerm; + } + }else{ + /* Otherwise, flush the the current node of layer iLayer to disk. + ** Then allocate a new, empty sibling node. The key will be written + ** into the parent of this node. */ + rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n); + + assert( pNode->block.nAlloc>=p->nNodeSize ); + pNode->block.a[0] = (char)iLayer; + pNode->block.n = 1 + sqlite3Fts3PutVarint(&pNode->block.a[1], iPtr+1); + + iNextPtr = pNode->iBlock; + pNode->iBlock++; + pNode->key.n = 0; + } + + if( rc!=SQLITE_OK || iNextPtr==0 ) return rc; + iPtr = iNextPtr; + } + + assert( 0 ); + return 0; +} + +/* +** Append a term and (optionally) doclist to the FTS segment node currently +** stored in blob *pNode. The node need not contain any terms, but the +** header must be written before this function is called. +** +** A node header is a single 0x00 byte for a leaf node, or a height varint +** followed by the left-hand-child varint for an internal node. +** +** The term to be appended is passed via arguments zTerm/nTerm. For a +** leaf node, the doclist is passed as aDoclist/nDoclist. For an internal +** node, both aDoclist and nDoclist must be passed 0. +** +** If the size of the value in blob pPrev is zero, then this is the first +** term written to the node. Otherwise, pPrev contains a copy of the +** previous term. Before this function returns, it is updated to contain a +** copy of zTerm/nTerm. +** +** It is assumed that the buffer associated with pNode is already large +** enough to accommodate the new entry. The buffer associated with pPrev +** is extended by this function if requrired. +** +** If an error (i.e. OOM condition) occurs, an SQLite error code is +** returned. Otherwise, SQLITE_OK. +*/ +static int fts3AppendToNode( + Blob *pNode, /* Current node image to append to */ + Blob *pPrev, /* Buffer containing previous term written */ + const char *zTerm, /* New term to write */ + int nTerm, /* Size of zTerm in bytes */ + const char *aDoclist, /* Doclist (or NULL) to write */ + int nDoclist /* Size of aDoclist in bytes */ +){ + int rc = SQLITE_OK; /* Return code */ + int bFirst = (pPrev->n==0); /* True if this is the first term written */ + int nPrefix; /* Size of term prefix in bytes */ + int nSuffix; /* Size of term suffix in bytes */ + + /* Node must have already been started. There must be a doclist for a + ** leaf node, and there must not be a doclist for an internal node. */ + assert( pNode->n>0 ); + assert( (pNode->a[0]=='\0')==(aDoclist!=0) ); + + blobGrowBuffer(pPrev, nTerm, &rc); + if( rc!=SQLITE_OK ) return rc; + + nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm); + nSuffix = nTerm - nPrefix; + memcpy(pPrev->a, zTerm, nTerm); + pPrev->n = nTerm; + + if( bFirst==0 ){ + pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nPrefix); + } + pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nSuffix); + memcpy(&pNode->a[pNode->n], &zTerm[nPrefix], nSuffix); + pNode->n += nSuffix; + + if( aDoclist ){ + pNode->n += sqlite3Fts3PutVarint(&pNode->a[pNode->n], nDoclist); + memcpy(&pNode->a[pNode->n], aDoclist, nDoclist); + pNode->n += nDoclist; + } + + assert( pNode->n<=pNode->nAlloc ); + + return SQLITE_OK; +} + +/* +** Append the current term and doclist pointed to by cursor pCsr to the +** appendable b-tree segment opened for writing by pWriter. +** +** Return SQLITE_OK if successful, or an SQLite error code otherwise. +*/ +static int fts3IncrmergeAppend( + Fts3Table *p, /* Fts3 table handle */ + IncrmergeWriter *pWriter, /* Writer object */ + Fts3MultiSegReader *pCsr /* Cursor containing term and doclist */ +){ + const char *zTerm = pCsr->zTerm; + int nTerm = pCsr->nTerm; + const char *aDoclist = pCsr->aDoclist; + int nDoclist = pCsr->nDoclist; + int rc = SQLITE_OK; /* Return code */ + int nSpace; /* Total space in bytes required on leaf */ + int nPrefix; /* Size of prefix shared with previous term */ + int nSuffix; /* Size of suffix (nTerm - nPrefix) */ + NodeWriter *pLeaf; /* Object used to write leaf nodes */ + + pLeaf = &pWriter->aNodeWriter[0]; + nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm); + nSuffix = nTerm - nPrefix; + + nSpace = sqlite3Fts3VarintLen(nPrefix); + nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; + nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; + + /* If the current block is not empty, and if adding this term/doclist + ** to the current block would make it larger than Fts3Table.nNodeSize + ** bytes, write this block out to the database. */ + if( pLeaf->block.n>0 && (pLeaf->block.n + nSpace)>p->nNodeSize ){ + rc = fts3WriteSegment(p, pLeaf->iBlock, pLeaf->block.a, pLeaf->block.n); + pWriter->nWork++; + + /* Add the current term to the parent node. The term added to the + ** parent must: + ** + ** a) be greater than the largest term on the leaf node just written + ** to the database (still available in pLeaf->key), and + ** + ** b) be less than or equal to the term about to be added to the new + ** leaf node (zTerm/nTerm). + ** + ** In other words, it must be the prefix of zTerm 1 byte longer than + ** the common prefix (if any) of zTerm and pWriter->zTerm. + */ + if( rc==SQLITE_OK ){ + rc = fts3IncrmergePush(p, pWriter, zTerm, nPrefix+1); + } + + /* Advance to the next output block */ + pLeaf->iBlock++; + pLeaf->key.n = 0; + pLeaf->block.n = 0; + + nSuffix = nTerm; + nSpace = 1; + nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix; + nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist; + } + + blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc); + + if( rc==SQLITE_OK ){ + if( pLeaf->block.n==0 ){ + pLeaf->block.n = 1; + pLeaf->block.a[0] = '\0'; + } + rc = fts3AppendToNode( + &pLeaf->block, &pLeaf->key, zTerm, nTerm, aDoclist, nDoclist + ); + } + + return rc; +} + +/* +** This function is called to release all dynamic resources held by the +** merge-writer object pWriter, and if no error has occurred, to flush +** all outstanding node buffers held by pWriter to disk. +** +** If *pRc is not SQLITE_OK when this function is called, then no attempt +** is made to write any data to disk. Instead, this function serves only +** to release outstanding resources. +** +** Otherwise, if *pRc is initially SQLITE_OK and an error occurs while +** flushing buffers to disk, *pRc is set to an SQLite error code before +** returning. +*/ +static void fts3IncrmergeRelease( + Fts3Table *p, /* FTS3 table handle */ + IncrmergeWriter *pWriter, /* Merge-writer object */ + int *pRc /* IN/OUT: Error code */ +){ + int i; /* Used to iterate through non-root layers */ + int iRoot; /* Index of root in pWriter->aNodeWriter */ + NodeWriter *pRoot; /* NodeWriter for root node */ + int rc = *pRc; /* Error code */ + + /* Set iRoot to the index in pWriter->aNodeWriter[] of the output segment + ** root node. If the segment fits entirely on a single leaf node, iRoot + ** will be set to 0. If the root node is the parent of the leaves, iRoot + ** will be 1. And so on. */ + for(iRoot=FTS_MAX_APPENDABLE_HEIGHT-1; iRoot>=0; iRoot--){ + NodeWriter *pNode = &pWriter->aNodeWriter[iRoot]; + if( pNode->block.n>0 ) break; + assert( *pRc || pNode->block.nAlloc==0 ); + assert( *pRc || pNode->key.nAlloc==0 ); + sqlite3_free(pNode->block.a); + sqlite3_free(pNode->key.a); + } + + /* Empty output segment. This is a no-op. */ + if( iRoot<0 ) return; + + /* The entire output segment fits on a single node. Normally, this means + ** the node would be stored as a blob in the "root" column of the %_segdir + ** table. However, this is not permitted in this case. The problem is that + ** space has already been reserved in the %_segments table, and so the + ** start_block and end_block fields of the %_segdir table must be populated. + ** And, by design or by accident, released versions of FTS cannot handle + ** segments that fit entirely on the root node with start_block!=0. + ** + ** Instead, create a synthetic root node that contains nothing but a + ** pointer to the single content node. So that the segment consists of a + ** single leaf and a single interior (root) node. + ** + ** Todo: Better might be to defer allocating space in the %_segments + ** table until we are sure it is needed. + */ + if( iRoot==0 ){ + Blob *pBlock = &pWriter->aNodeWriter[1].block; + blobGrowBuffer(pBlock, 1 + FTS3_VARINT_MAX, &rc); + if( rc==SQLITE_OK ){ + pBlock->a[0] = 0x01; + pBlock->n = 1 + sqlite3Fts3PutVarint( + &pBlock->a[1], pWriter->aNodeWriter[0].iBlock + ); + } + iRoot = 1; + } + pRoot = &pWriter->aNodeWriter[iRoot]; + + /* Flush all currently outstanding nodes to disk. */ + for(i=0; iaNodeWriter[i]; + if( pNode->block.n>0 && rc==SQLITE_OK ){ + rc = fts3WriteSegment(p, pNode->iBlock, pNode->block.a, pNode->block.n); + } + sqlite3_free(pNode->block.a); + sqlite3_free(pNode->key.a); + } + + /* Write the %_segdir record. */ + if( rc==SQLITE_OK ){ + rc = fts3WriteSegdir(p, + pWriter->iAbsLevel+1, /* level */ + pWriter->iIdx, /* idx */ + pWriter->iStart, /* start_block */ + pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */ + pWriter->iEnd, /* end_block */ + pRoot->block.a, pRoot->block.n /* root */ + ); + } + sqlite3_free(pRoot->block.a); + sqlite3_free(pRoot->key.a); + + *pRc = rc; +} + +/* +** Compare the term in buffer zLhs (size in bytes nLhs) with that in +** zRhs (size in bytes nRhs) using memcmp. If one term is a prefix of +** the other, it is considered to be smaller than the other. +** +** Return -ve if zLhs is smaller than zRhs, 0 if it is equal, or +ve +** if it is greater. +*/ +static int fts3TermCmp( + const char *zLhs, int nLhs, /* LHS of comparison */ + const char *zRhs, int nRhs /* RHS of comparison */ +){ + int nCmp = MIN(nLhs, nRhs); + int res; + + res = memcmp(zLhs, zRhs, nCmp); + if( res==0 ) res = nLhs - nRhs; + + return res; +} + + +/* +** Query to see if the entry in the %_segments table with blockid iEnd is +** NULL. If no error occurs and the entry is NULL, set *pbRes 1 before +** returning. Otherwise, set *pbRes to 0. +** +** Or, if an error occurs while querying the database, return an SQLite +** error code. The final value of *pbRes is undefined in this case. +** +** This is used to test if a segment is an "appendable" segment. If it +** is, then a NULL entry has been inserted into the %_segments table +** with blockid %_segdir.end_block. +*/ +static int fts3IsAppendable(Fts3Table *p, sqlite3_int64 iEnd, int *pbRes){ + int bRes = 0; /* Result to set *pbRes to */ + sqlite3_stmt *pCheck = 0; /* Statement to query database with */ + int rc; /* Return code */ + + rc = fts3SqlStmt(p, SQL_SEGMENT_IS_APPENDABLE, &pCheck, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pCheck, 1, iEnd); + if( SQLITE_ROW==sqlite3_step(pCheck) ) bRes = 1; + rc = sqlite3_reset(pCheck); + } + + *pbRes = bRes; + return rc; +} + +/* +** This function is called when initializing an incremental-merge operation. +** It checks if the existing segment with index value iIdx at absolute level +** (iAbsLevel+1) can be appended to by the incremental merge. If it can, the +** merge-writer object *pWriter is initialized to write to it. +** +** An existing segment can be appended to by an incremental merge if: +** +** * It was initially created as an appendable segment (with all required +** space pre-allocated), and +** +** * The first key read from the input (arguments zKey and nKey) is +** greater than the largest key currently stored in the potential +** output segment. +*/ +static int fts3IncrmergeLoad( + Fts3Table *p, /* Fts3 table handle */ + sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ + int iIdx, /* Index of candidate output segment */ + const char *zKey, /* First key to write */ + int nKey, /* Number of bytes in nKey */ + IncrmergeWriter *pWriter /* Populate this object */ +){ + int rc; /* Return code */ + sqlite3_stmt *pSelect = 0; /* SELECT to read %_segdir entry */ + + rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pSelect, 0); + if( rc==SQLITE_OK ){ + sqlite3_int64 iStart = 0; /* Value of %_segdir.start_block */ + sqlite3_int64 iLeafEnd = 0; /* Value of %_segdir.leaves_end_block */ + sqlite3_int64 iEnd = 0; /* Value of %_segdir.end_block */ + const char *aRoot = 0; /* Pointer to %_segdir.root buffer */ + int nRoot = 0; /* Size of aRoot[] in bytes */ + int rc2; /* Return code from sqlite3_reset() */ + int bAppendable = 0; /* Set to true if segment is appendable */ + + /* Read the %_segdir entry for index iIdx absolute level (iAbsLevel+1) */ + sqlite3_bind_int64(pSelect, 1, iAbsLevel+1); + sqlite3_bind_int(pSelect, 2, iIdx); + if( sqlite3_step(pSelect)==SQLITE_ROW ){ + iStart = sqlite3_column_int64(pSelect, 1); + iLeafEnd = sqlite3_column_int64(pSelect, 2); + iEnd = sqlite3_column_int64(pSelect, 3); + nRoot = sqlite3_column_bytes(pSelect, 4); + aRoot = sqlite3_column_blob(pSelect, 4); + }else{ + return sqlite3_reset(pSelect); + } + + /* Check for the zero-length marker in the %_segments table */ + rc = fts3IsAppendable(p, iEnd, &bAppendable); + + /* Check that zKey/nKey is larger than the largest key the candidate */ + if( rc==SQLITE_OK && bAppendable ){ + char *aLeaf = 0; + int nLeaf = 0; + + rc = sqlite3Fts3ReadBlock(p, iLeafEnd, &aLeaf, &nLeaf, 0); + if( rc==SQLITE_OK ){ + NodeReader reader; + for(rc = nodeReaderInit(&reader, aLeaf, nLeaf); + rc==SQLITE_OK && reader.aNode; + rc = nodeReaderNext(&reader) + ){ + assert( reader.aNode ); + } + if( fts3TermCmp(zKey, nKey, reader.term.a, reader.term.n)<=0 ){ + bAppendable = 0; + } + nodeReaderRelease(&reader); + } + sqlite3_free(aLeaf); + } + + if( rc==SQLITE_OK && bAppendable ){ + /* It is possible to append to this segment. Set up the IncrmergeWriter + ** object to do so. */ + int i; + int nHeight = (int)aRoot[0]; + NodeWriter *pNode; + + pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT; + pWriter->iStart = iStart; + pWriter->iEnd = iEnd; + pWriter->iAbsLevel = iAbsLevel; + pWriter->iIdx = iIdx; + + for(i=nHeight+1; iaNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; + } + + pNode = &pWriter->aNodeWriter[nHeight]; + pNode->iBlock = pWriter->iStart + pWriter->nLeafEst*nHeight; + blobGrowBuffer(&pNode->block, MAX(nRoot, p->nNodeSize), &rc); + if( rc==SQLITE_OK ){ + memcpy(pNode->block.a, aRoot, nRoot); + pNode->block.n = nRoot; + } + + for(i=nHeight; i>=0 && rc==SQLITE_OK; i--){ + NodeReader reader; + pNode = &pWriter->aNodeWriter[i]; + + rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n); + while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader); + blobGrowBuffer(&pNode->key, reader.term.n, &rc); + if( rc==SQLITE_OK ){ + memcpy(pNode->key.a, reader.term.a, reader.term.n); + pNode->key.n = reader.term.n; + if( i>0 ){ + char *aBlock = 0; + int nBlock = 0; + pNode = &pWriter->aNodeWriter[i-1]; + pNode->iBlock = reader.iChild; + rc = sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0); + blobGrowBuffer(&pNode->block, MAX(nBlock, p->nNodeSize), &rc); + if( rc==SQLITE_OK ){ + memcpy(pNode->block.a, aBlock, nBlock); + pNode->block.n = nBlock; + } + sqlite3_free(aBlock); + } + } + nodeReaderRelease(&reader); + } + } + + rc2 = sqlite3_reset(pSelect); + if( rc==SQLITE_OK ) rc = rc2; + } + + return rc; +} + +/* +** Determine the largest segment index value that exists within absolute +** level iAbsLevel+1. If no error occurs, set *piIdx to this value plus +** one before returning SQLITE_OK. Or, if there are no segments at all +** within level iAbsLevel, set *piIdx to zero. +** +** If an error occurs, return an SQLite error code. The final value of +** *piIdx is undefined in this case. +*/ +static int fts3IncrmergeOutputIdx( + Fts3Table *p, /* FTS Table handle */ + sqlite3_int64 iAbsLevel, /* Absolute index of input segments */ + int *piIdx /* OUT: Next free index at iAbsLevel+1 */ +){ + int rc; + sqlite3_stmt *pOutputIdx = 0; /* SQL used to find output index */ + + rc = fts3SqlStmt(p, SQL_NEXT_SEGMENT_INDEX, &pOutputIdx, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pOutputIdx, 1, iAbsLevel+1); + sqlite3_step(pOutputIdx); + *piIdx = sqlite3_column_int(pOutputIdx, 0); + rc = sqlite3_reset(pOutputIdx); + } + + return rc; +} + +/* +** Allocate an appendable output segment on absolute level iAbsLevel+1 +** with idx value iIdx. +** +** In the %_segdir table, a segment is defined by the values in three +** columns: +** +** start_block +** leaves_end_block +** end_block +** +** When an appendable segment is allocated, it is estimated that the +** maximum number of leaf blocks that may be required is the sum of the +** number of leaf blocks consumed by the input segments, plus the number +** of input segments, multiplied by two. This value is stored in stack +** variable nLeafEst. +** +** A total of 16*nLeafEst blocks are allocated when an appendable segment +** is created ((1 + end_block - start_block)==16*nLeafEst). The contiguous +** array of leaf nodes starts at the first block allocated. The array +** of interior nodes that are parents of the leaf nodes start at block +** (start_block + (1 + end_block - start_block) / 16). And so on. +** +** In the actual code below, the value "16" is replaced with the +** pre-processor macro FTS_MAX_APPENDABLE_HEIGHT. +*/ +static int fts3IncrmergeWriter( + Fts3Table *p, /* Fts3 table handle */ + sqlite3_int64 iAbsLevel, /* Absolute level of input segments */ + int iIdx, /* Index of new output segment */ + Fts3MultiSegReader *pCsr, /* Cursor that data will be read from */ + IncrmergeWriter *pWriter /* Populate this object */ +){ + int rc; /* Return Code */ + int i; /* Iterator variable */ + int nLeafEst = 0; /* Blocks allocated for leaf nodes */ + sqlite3_stmt *pLeafEst = 0; /* SQL used to determine nLeafEst */ + sqlite3_stmt *pFirstBlock = 0; /* SQL used to determine first block */ + + /* Calculate nLeafEst. */ + rc = fts3SqlStmt(p, SQL_MAX_LEAF_NODE_ESTIMATE, &pLeafEst, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pLeafEst, 1, iAbsLevel); + sqlite3_bind_int64(pLeafEst, 2, pCsr->nSegment); + if( SQLITE_ROW==sqlite3_step(pLeafEst) ){ + nLeafEst = sqlite3_column_int(pLeafEst, 0); + } + rc = sqlite3_reset(pLeafEst); + } + if( rc!=SQLITE_OK ) return rc; + + /* Calculate the first block to use in the output segment */ + rc = fts3SqlStmt(p, SQL_NEXT_SEGMENTS_ID, &pFirstBlock, 0); + if( rc==SQLITE_OK ){ + if( SQLITE_ROW==sqlite3_step(pFirstBlock) ){ + pWriter->iStart = sqlite3_column_int64(pFirstBlock, 0); + pWriter->iEnd = pWriter->iStart - 1; + pWriter->iEnd += nLeafEst * FTS_MAX_APPENDABLE_HEIGHT; + } + rc = sqlite3_reset(pFirstBlock); + } + if( rc!=SQLITE_OK ) return rc; + + /* Insert the marker in the %_segments table to make sure nobody tries + ** to steal the space just allocated. This is also used to identify + ** appendable segments. */ + rc = fts3WriteSegment(p, pWriter->iEnd, 0, 0); + if( rc!=SQLITE_OK ) return rc; + + pWriter->iAbsLevel = iAbsLevel; + pWriter->nLeafEst = nLeafEst; + pWriter->iIdx = iIdx; + + /* Set up the array of NodeWriter objects */ + for(i=0; iaNodeWriter[i].iBlock = pWriter->iStart + i*pWriter->nLeafEst; + } + return SQLITE_OK; +} + +/* +** Remove an entry from the %_segdir table. This involves running the +** following two statements: +** +** DELETE FROM %_segdir WHERE level = :iAbsLevel AND idx = :iIdx +** UPDATE %_segdir SET idx = idx - 1 WHERE level = :iAbsLevel AND idx > :iIdx +** +** The DELETE statement removes the specific %_segdir level. The UPDATE +** statement ensures that the remaining segments have contiguously allocated +** idx values. +*/ +static int fts3RemoveSegdirEntry( + Fts3Table *p, /* FTS3 table handle */ + sqlite3_int64 iAbsLevel, /* Absolute level to delete from */ + int iIdx /* Index of %_segdir entry to delete */ +){ + int rc; /* Return code */ + sqlite3_stmt *pDelete = 0; /* DELETE statement */ + + rc = fts3SqlStmt(p, SQL_DELETE_SEGDIR_ENTRY, &pDelete, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pDelete, 1, iAbsLevel); + sqlite3_bind_int(pDelete, 2, iIdx); + sqlite3_step(pDelete); + rc = sqlite3_reset(pDelete); + } + + return rc; +} + +/* +** One or more segments have just been removed from absolute level iAbsLevel. +** Update the 'idx' values of the remaining segments in the level so that +** the idx values are a contiguous sequence starting from 0. +*/ +static int fts3RepackSegdirLevel( + Fts3Table *p, /* FTS3 table handle */ + sqlite3_int64 iAbsLevel /* Absolute level to repack */ +){ + int rc; /* Return code */ + int *aIdx = 0; /* Array of remaining idx values */ + int nIdx = 0; /* Valid entries in aIdx[] */ + int nAlloc = 0; /* Allocated size of aIdx[] */ + int i; /* Iterator variable */ + sqlite3_stmt *pSelect = 0; /* Select statement to read idx values */ + sqlite3_stmt *pUpdate = 0; /* Update statement to modify idx values */ + + rc = fts3SqlStmt(p, SQL_SELECT_INDEXES, &pSelect, 0); + if( rc==SQLITE_OK ){ + int rc2; + sqlite3_bind_int64(pSelect, 1, iAbsLevel); + while( SQLITE_ROW==sqlite3_step(pSelect) ){ + if( nIdx>=nAlloc ){ + int *aNew; + nAlloc += 16; + aNew = sqlite3_realloc(aIdx, nAlloc*sizeof(int)); + if( !aNew ){ + rc = SQLITE_NOMEM; + break; + } + aIdx = aNew; + } + aIdx[nIdx++] = sqlite3_column_int(pSelect, 0); + } + rc2 = sqlite3_reset(pSelect); + if( rc==SQLITE_OK ) rc = rc2; + } + + if( rc==SQLITE_OK ){ + rc = fts3SqlStmt(p, SQL_SHIFT_SEGDIR_ENTRY, &pUpdate, 0); + } + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pUpdate, 2, iAbsLevel); + } + + assert( p->bIgnoreSavepoint==0 ); + p->bIgnoreSavepoint = 1; + for(i=0; rc==SQLITE_OK && ibIgnoreSavepoint = 0; + + sqlite3_free(aIdx); + return rc; +} + +static void fts3StartNode(Blob *pNode, int iHeight, sqlite3_int64 iChild){ + pNode->a[0] = (char)iHeight; + if( iChild ){ + assert( pNode->nAlloc>=1+sqlite3Fts3VarintLen(iChild) ); + pNode->n = 1 + sqlite3Fts3PutVarint(&pNode->a[1], iChild); + }else{ + assert( pNode->nAlloc>=1 ); + pNode->n = 1; + } +} + +/* +** The first two arguments are a pointer to and the size of a segment b-tree +** node. The node may be a leaf or an internal node. +** +** This function creates a new node image in blob object *pNew by copying +** all terms that are greater than or equal to zTerm/nTerm (for leaf nodes) +** or greater than zTerm/nTerm (for internal nodes) from aNode/nNode. +*/ +static int fts3TruncateNode( + const char *aNode, /* Current node image */ + int nNode, /* Size of aNode in bytes */ + Blob *pNew, /* OUT: Write new node image here */ + const char *zTerm, /* Omit all terms smaller than this */ + int nTerm, /* Size of zTerm in bytes */ + sqlite3_int64 *piBlock /* OUT: Block number in next layer down */ +){ + NodeReader reader; /* Reader object */ + Blob prev = {0, 0, 0}; /* Previous term written to new node */ + int rc = SQLITE_OK; /* Return code */ + int bLeaf = aNode[0]=='\0'; /* True for a leaf node */ + + /* Allocate required output space */ + blobGrowBuffer(pNew, nNode, &rc); + if( rc!=SQLITE_OK ) return rc; + pNew->n = 0; + + /* Populate new node buffer */ + for(rc = nodeReaderInit(&reader, aNode, nNode); + rc==SQLITE_OK && reader.aNode; + rc = nodeReaderNext(&reader) + ){ + if( pNew->n==0 ){ + int res = fts3TermCmp(reader.term.a, reader.term.n, zTerm, nTerm); + if( res<0 || (bLeaf==0 && res==0) ) continue; + fts3StartNode(pNew, (int)aNode[0], reader.iChild); + *piBlock = reader.iChild; + } + rc = fts3AppendToNode( + pNew, &prev, reader.term.a, reader.term.n, + reader.aDoclist, reader.nDoclist + ); + if( rc!=SQLITE_OK ) break; + } + if( pNew->n==0 ){ + fts3StartNode(pNew, (int)aNode[0], reader.iChild); + *piBlock = reader.iChild; + } + assert( pNew->n<=pNew->nAlloc ); + + nodeReaderRelease(&reader); + sqlite3_free(prev.a); + return rc; +} + +/* +** Remove all terms smaller than zTerm/nTerm from segment iIdx in absolute +** level iAbsLevel. This may involve deleting entries from the %_segments +** table, and modifying existing entries in both the %_segments and %_segdir +** tables. +** +** SQLITE_OK is returned if the segment is updated successfully. Or an +** SQLite error code otherwise. +*/ +static int fts3TruncateSegment( + Fts3Table *p, /* FTS3 table handle */ + sqlite3_int64 iAbsLevel, /* Absolute level of segment to modify */ + int iIdx, /* Index within level of segment to modify */ + const char *zTerm, /* Remove terms smaller than this */ + int nTerm /* Number of bytes in buffer zTerm */ +){ + int rc = SQLITE_OK; /* Return code */ + Blob root = {0,0,0}; /* New root page image */ + Blob block = {0,0,0}; /* Buffer used for any other block */ + sqlite3_int64 iBlock = 0; /* Block id */ + sqlite3_int64 iNewStart = 0; /* New value for iStartBlock */ + sqlite3_int64 iOldStart = 0; /* Old value for iStartBlock */ + sqlite3_stmt *pFetch = 0; /* Statement used to fetch segdir */ + + rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR, &pFetch, 0); + if( rc==SQLITE_OK ){ + int rc2; /* sqlite3_reset() return code */ + sqlite3_bind_int64(pFetch, 1, iAbsLevel); + sqlite3_bind_int(pFetch, 2, iIdx); + if( SQLITE_ROW==sqlite3_step(pFetch) ){ + const char *aRoot = sqlite3_column_blob(pFetch, 4); + int nRoot = sqlite3_column_bytes(pFetch, 4); + iOldStart = sqlite3_column_int64(pFetch, 1); + rc = fts3TruncateNode(aRoot, nRoot, &root, zTerm, nTerm, &iBlock); + } + rc2 = sqlite3_reset(pFetch); + if( rc==SQLITE_OK ) rc = rc2; + } + + while( rc==SQLITE_OK && iBlock ){ + char *aBlock = 0; + int nBlock = 0; + iNewStart = iBlock; + + rc = sqlite3Fts3ReadBlock(p, iBlock, &aBlock, &nBlock, 0); + if( rc==SQLITE_OK ){ + rc = fts3TruncateNode(aBlock, nBlock, &block, zTerm, nTerm, &iBlock); + } + if( rc==SQLITE_OK ){ + rc = fts3WriteSegment(p, iNewStart, block.a, block.n); + } + sqlite3_free(aBlock); + } + + /* Variable iNewStart now contains the first valid leaf node. */ + if( rc==SQLITE_OK && iNewStart ){ + sqlite3_stmt *pDel = 0; + rc = fts3SqlStmt(p, SQL_DELETE_SEGMENTS_RANGE, &pDel, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pDel, 1, iOldStart); + sqlite3_bind_int64(pDel, 2, iNewStart-1); + sqlite3_step(pDel); + rc = sqlite3_reset(pDel); + } + } + + if( rc==SQLITE_OK ){ + sqlite3_stmt *pChomp = 0; + rc = fts3SqlStmt(p, SQL_CHOMP_SEGDIR, &pChomp, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int64(pChomp, 1, iNewStart); + sqlite3_bind_blob(pChomp, 2, root.a, root.n, SQLITE_STATIC); + sqlite3_bind_int64(pChomp, 3, iAbsLevel); + sqlite3_bind_int(pChomp, 4, iIdx); + sqlite3_step(pChomp); + rc = sqlite3_reset(pChomp); + } + } + + sqlite3_free(root.a); + sqlite3_free(block.a); + return rc; +} + +/* +** This function is called after an incrmental-merge operation has run to +** merge (or partially merge) two or more segments from absolute level +** iAbsLevel. +** +** Each input segment is either removed from the db completely (if all of +** its data was copied to the output segment by the incrmerge operation) +** or modified in place so that it no longer contains those entries that +** have been duplicated in the output segment. +*/ +static int fts3IncrmergeChomp( + Fts3Table *p, /* FTS table handle */ + sqlite3_int64 iAbsLevel, /* Absolute level containing segments */ + Fts3MultiSegReader *pCsr, /* Chomp all segments opened by this cursor */ + int *pnRem /* Number of segments not deleted */ +){ + int i; + int nRem = 0; + int rc = SQLITE_OK; + + for(i=pCsr->nSegment-1; i>=0 && rc==SQLITE_OK; i--){ + Fts3SegReader *pSeg = 0; + int j; + + /* Find the Fts3SegReader object with Fts3SegReader.iIdx==i. It is hiding + ** somewhere in the pCsr->apSegment[] array. */ + for(j=0; ALWAYS(jnSegment); j++){ + pSeg = pCsr->apSegment[j]; + if( pSeg->iIdx==i ) break; + } + assert( jnSegment && pSeg->iIdx==i ); + + if( pSeg->aNode==0 ){ + /* Seg-reader is at EOF. Remove the entire input segment. */ + rc = fts3DeleteSegment(p, pSeg); + if( rc==SQLITE_OK ){ + rc = fts3RemoveSegdirEntry(p, iAbsLevel, pSeg->iIdx); + } + *pnRem = 0; + }else{ + /* The incremental merge did not copy all the data from this + ** segment to the upper level. The segment is modified in place + ** so that it contains no keys smaller than zTerm/nTerm. */ + const char *zTerm = pSeg->zTerm; + int nTerm = pSeg->nTerm; + rc = fts3TruncateSegment(p, iAbsLevel, pSeg->iIdx, zTerm, nTerm); + nRem++; + } + } + + if( rc==SQLITE_OK && nRem!=pCsr->nSegment ){ + rc = fts3RepackSegdirLevel(p, iAbsLevel); + } + + *pnRem = nRem; + return rc; +} + +/* +** Store an incr-merge hint in the database. +*/ +static int fts3IncrmergeHintStore(Fts3Table *p, Blob *pHint){ + sqlite3_stmt *pReplace = 0; + int rc; /* Return code */ + + rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pReplace, 0); + if( rc==SQLITE_OK ){ + sqlite3_bind_int(pReplace, 1, FTS_STAT_INCRMERGEHINT); + sqlite3_bind_blob(pReplace, 2, pHint->a, pHint->n, SQLITE_STATIC); + sqlite3_step(pReplace); + rc = sqlite3_reset(pReplace); + } + + return rc; +} + +/* +** Load an incr-merge hint from the database. The incr-merge hint, if one +** exists, is stored in the rowid==1 row of the %_stat table. +** +** If successful, populate blob *pHint with the value read from the %_stat +** table and return SQLITE_OK. Otherwise, if an error occurs, return an +** SQLite error code. +*/ +static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){ + sqlite3_stmt *pSelect = 0; + int rc; + + pHint->n = 0; + rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pSelect, 0); + if( rc==SQLITE_OK ){ + int rc2; + sqlite3_bind_int(pSelect, 1, FTS_STAT_INCRMERGEHINT); + if( SQLITE_ROW==sqlite3_step(pSelect) ){ + const char *aHint = sqlite3_column_blob(pSelect, 0); + int nHint = sqlite3_column_bytes(pSelect, 0); + if( aHint ){ + blobGrowBuffer(pHint, nHint, &rc); + if( rc==SQLITE_OK ){ + memcpy(pHint->a, aHint, nHint); + pHint->n = nHint; + } + } + } + rc2 = sqlite3_reset(pSelect); + if( rc==SQLITE_OK ) rc = rc2; + } + + return rc; +} + +/* +** If *pRc is not SQLITE_OK when this function is called, it is a no-op. +** Otherwise, append an entry to the hint stored in blob *pHint. Each entry +** consists of two varints, the absolute level number of the input segments +** and the number of input segments. +** +** If successful, leave *pRc set to SQLITE_OK and return. If an error occurs, +** set *pRc to an SQLite error code before returning. +*/ +static void fts3IncrmergeHintPush( + Blob *pHint, /* Hint blob to append to */ + i64 iAbsLevel, /* First varint to store in hint */ + int nInput, /* Second varint to store in hint */ + int *pRc /* IN/OUT: Error code */ +){ + blobGrowBuffer(pHint, pHint->n + 2*FTS3_VARINT_MAX, pRc); + if( *pRc==SQLITE_OK ){ + pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], iAbsLevel); + pHint->n += sqlite3Fts3PutVarint(&pHint->a[pHint->n], (i64)nInput); + } +} + +/* +** Read the last entry (most recently pushed) from the hint blob *pHint +** and then remove the entry. Write the two values read to *piAbsLevel and +** *pnInput before returning. +** +** If no error occurs, return SQLITE_OK. If the hint blob in *pHint does +** not contain at least two valid varints, return SQLITE_CORRUPT_VTAB. +*/ +static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){ + const int nHint = pHint->n; + int i; + + i = pHint->n-2; + while( i>0 && (pHint->a[i-1] & 0x80) ) i--; + while( i>0 && (pHint->a[i-1] & 0x80) ) i--; + + pHint->n = i; + i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel); + i += sqlite3Fts3GetVarint32(&pHint->a[i], pnInput); + if( i!=nHint ) return SQLITE_CORRUPT_VTAB; + + return SQLITE_OK; +} + + +/* +** Attempt an incremental merge that writes nMerge leaf blocks. +** +** Incremental merges happen nMin segments at a time. The two +** segments to be merged are the nMin oldest segments (the ones with +** the smallest indexes) in the highest level that contains at least +** nMin segments. Multiple merges might occur in an attempt to write the +** quota of nMerge leaf blocks. +*/ +SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ + int rc; /* Return code */ + int nRem = nMerge; /* Number of leaf pages yet to be written */ + Fts3MultiSegReader *pCsr; /* Cursor used to read input data */ + Fts3SegFilter *pFilter; /* Filter used with cursor pCsr */ + IncrmergeWriter *pWriter; /* Writer object */ + int nSeg = 0; /* Number of input segments */ + sqlite3_int64 iAbsLevel = 0; /* Absolute level number to work on */ + Blob hint = {0, 0, 0}; /* Hint read from %_stat table */ + int bDirtyHint = 0; /* True if blob 'hint' has been modified */ + + /* Allocate space for the cursor, filter and writer objects */ + const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter); + pWriter = (IncrmergeWriter *)sqlite3_malloc(nAlloc); + if( !pWriter ) return SQLITE_NOMEM; + pFilter = (Fts3SegFilter *)&pWriter[1]; + pCsr = (Fts3MultiSegReader *)&pFilter[1]; + + rc = fts3IncrmergeHintLoad(p, &hint); + while( rc==SQLITE_OK && nRem>0 ){ + const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex; + sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */ + int bUseHint = 0; /* True if attempting to append */ + + /* Search the %_segdir table for the absolute level with the smallest + ** relative level number that contains at least nMin segments, if any. + ** If one is found, set iAbsLevel to the absolute level number and + ** nSeg to nMin. If no level with at least nMin segments can be found, + ** set nSeg to -1. + */ + rc = fts3SqlStmt(p, SQL_FIND_MERGE_LEVEL, &pFindLevel, 0); + sqlite3_bind_int(pFindLevel, 1, nMin); + if( sqlite3_step(pFindLevel)==SQLITE_ROW ){ + iAbsLevel = sqlite3_column_int64(pFindLevel, 0); + nSeg = nMin; + }else{ + nSeg = -1; + } + rc = sqlite3_reset(pFindLevel); + + /* If the hint read from the %_stat table is not empty, check if the + ** last entry in it specifies a relative level smaller than or equal + ** to the level identified by the block above (if any). If so, this + ** iteration of the loop will work on merging at the hinted level. + */ + if( rc==SQLITE_OK && hint.n ){ + int nHint = hint.n; + sqlite3_int64 iHintAbsLevel = 0; /* Hint level */ + int nHintSeg = 0; /* Hint number of segments */ + + rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg); + if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){ + iAbsLevel = iHintAbsLevel; + nSeg = nHintSeg; + bUseHint = 1; + bDirtyHint = 1; + }else{ + /* This undoes the effect of the HintPop() above - so that no entry + ** is removed from the hint blob. */ + hint.n = nHint; + } + } + + /* If nSeg is less that zero, then there is no level with at least + ** nMin segments and no hint in the %_stat table. No work to do. + ** Exit early in this case. */ + if( nSeg<0 ) break; + + /* Open a cursor to iterate through the contents of the oldest nSeg + ** indexes of absolute level iAbsLevel. If this cursor is opened using + ** the 'hint' parameters, it is possible that there are less than nSeg + ** segments available in level iAbsLevel. In this case, no work is + ** done on iAbsLevel - fall through to the next iteration of the loop + ** to start work on some other level. */ + memset(pWriter, 0, nAlloc); + pFilter->flags = FTS3_SEGMENT_REQUIRE_POS; + if( rc==SQLITE_OK ){ + rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr); + } + if( SQLITE_OK==rc && pCsr->nSegment==nSeg + && SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter)) + && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr)) + ){ + int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */ + rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx); + if( rc==SQLITE_OK ){ + if( bUseHint && iIdx>0 ){ + const char *zKey = pCsr->zTerm; + int nKey = pCsr->nTerm; + rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter); + }else{ + rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter); + } + } + + if( rc==SQLITE_OK && pWriter->nLeafEst ){ + fts3LogMerge(nSeg, iAbsLevel); + do { + rc = fts3IncrmergeAppend(p, pWriter, pCsr); + if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr); + if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK; + }while( rc==SQLITE_ROW ); + + /* Update or delete the input segments */ + if( rc==SQLITE_OK ){ + nRem -= (1 + pWriter->nWork); + rc = fts3IncrmergeChomp(p, iAbsLevel, pCsr, &nSeg); + if( nSeg!=0 ){ + bDirtyHint = 1; + fts3IncrmergeHintPush(&hint, iAbsLevel, nSeg, &rc); + } + } + } + + fts3IncrmergeRelease(p, pWriter, &rc); + } + + sqlite3Fts3SegReaderFinish(pCsr); + } + + /* Write the hint values into the %_stat table for the next incr-merger */ + if( bDirtyHint && rc==SQLITE_OK ){ + rc = fts3IncrmergeHintStore(p, &hint); + } + + sqlite3_free(pWriter); + sqlite3_free(hint.a); + return rc; +} + +/* +** Convert the text beginning at *pz into an integer and return +** its value. Advance *pz to point to the first character past +** the integer. +*/ +static int fts3Getint(const char **pz){ + const char *z = *pz; + int i = 0; + while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0'; + *pz = z; + return i; +} + +/* +** Process statements of the form: +** +** INSERT INTO table(table) VALUES('merge=A,B'); +** +** A and B are integers that decode to be the number of leaf pages +** written for the merge, and the minimum number of segments on a level +** before it will be selected for a merge, respectively. +*/ +static int fts3DoIncrmerge( + Fts3Table *p, /* FTS3 table handle */ + const char *zParam /* Nul-terminated string containing "A,B" */ +){ + int rc; + int nMin = (FTS3_MERGE_COUNT / 2); + int nMerge = 0; + const char *z = zParam; + + /* Read the first integer value */ + nMerge = fts3Getint(&z); + + /* If the first integer value is followed by a ',', read the second + ** integer value. */ + if( z[0]==',' && z[1]!='\0' ){ + z++; + nMin = fts3Getint(&z); + } + + if( z[0]!='\0' || nMin<2 ){ + rc = SQLITE_ERROR; + }else{ + rc = SQLITE_OK; + if( !p->bHasStat ){ + assert( p->bFts4==0 ); + sqlite3Fts3CreateStatTable(&rc, p); + } + if( rc==SQLITE_OK ){ + rc = sqlite3Fts3Incrmerge(p, nMerge, nMin); + } + sqlite3Fts3SegmentsClose(p); + } + return rc; +} + +/* +** Process statements of the form: +** +** INSERT INTO table(table) VALUES('automerge=X'); +** +** where X is an integer. X==0 means to turn automerge off. X!=0 means +** turn it on. The setting is persistent. +*/ +static int fts3DoAutoincrmerge( + Fts3Table *p, /* FTS3 table handle */ + const char *zParam /* Nul-terminated string containing boolean */ +){ + int rc = SQLITE_OK; + sqlite3_stmt *pStmt = 0; + p->bAutoincrmerge = fts3Getint(&zParam)!=0; + if( !p->bHasStat ){ + assert( p->bFts4==0 ); + sqlite3Fts3CreateStatTable(&rc, p); + if( rc ) return rc; + } + rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0); + if( rc ) return rc;; + sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE); + sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge); + sqlite3_step(pStmt); + rc = sqlite3_reset(pStmt); + return rc; +} + +/* +** Return a 64-bit checksum for the FTS index entry specified by the +** arguments to this function. +*/ +static u64 fts3ChecksumEntry( + const char *zTerm, /* Pointer to buffer containing term */ + int nTerm, /* Size of zTerm in bytes */ + int iLangid, /* Language id for current row */ + int iIndex, /* Index (0..Fts3Table.nIndex-1) */ + i64 iDocid, /* Docid for current row. */ + int iCol, /* Column number */ + int iPos /* Position */ +){ + int i; + u64 ret = (u64)iDocid; + + ret += (ret<<3) + iLangid; + ret += (ret<<3) + iIndex; + ret += (ret<<3) + iCol; + ret += (ret<<3) + iPos; + for(i=0; inIndex-1) */ + int *pRc /* OUT: Return code */ +){ + Fts3SegFilter filter; + Fts3MultiSegReader csr; + int rc; + u64 cksum = 0; + + assert( *pRc==SQLITE_OK ); + + memset(&filter, 0, sizeof(filter)); + memset(&csr, 0, sizeof(csr)); + filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY; + filter.flags |= FTS3_SEGMENT_SCAN; + + rc = sqlite3Fts3SegReaderCursor( + p, iLangid, iIndex, FTS3_SEGCURSOR_ALL, 0, 0, 0, 1,&csr + ); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts3SegReaderStart(p, &csr, &filter); + } + + if( rc==SQLITE_OK ){ + while( SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, &csr)) ){ + char *pCsr = csr.aDoclist; + char *pEnd = &pCsr[csr.nDoclist]; + + i64 iDocid = 0; + i64 iCol = 0; + i64 iPos = 0; + + pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid); + while( pCsrnIndex); + while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){ + int iLangid = sqlite3_column_int(pAllLangid, 0); + int i; + for(i=0; inIndex; i++){ + cksum1 = cksum1 ^ fts3ChecksumIndex(p, iLangid, i, &rc); + } + } + rc2 = sqlite3_reset(pAllLangid); + if( rc==SQLITE_OK ) rc = rc2; + } + + /* This block calculates the checksum according to the %_content table */ + rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0); + if( rc==SQLITE_OK ){ + sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule; + sqlite3_stmt *pStmt = 0; + char *zSql; + + zSql = sqlite3_mprintf("SELECT %s" , p->zReadExprlist); + if( !zSql ){ + rc = SQLITE_NOMEM; + }else{ + rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0); + sqlite3_free(zSql); + } + + while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ + i64 iDocid = sqlite3_column_int64(pStmt, 0); + int iLang = langidFromSelect(p, pStmt); + int iCol; + + for(iCol=0; rc==SQLITE_OK && iColnColumn; iCol++){ + const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); + int nText = sqlite3_column_bytes(pStmt, iCol+1); + sqlite3_tokenizer_cursor *pT = 0; + + rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT); + while( rc==SQLITE_OK ){ + char const *zToken; /* Buffer containing token */ + int nToken; /* Number of bytes in token */ + int iDum1, iDum2; /* Dummy variables */ + int iPos; /* Position of token in zText */ + + rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos); + if( rc==SQLITE_OK ){ + int i; + cksum2 = cksum2 ^ fts3ChecksumEntry( + zToken, nToken, iLang, 0, iDocid, iCol, iPos + ); + for(i=1; inIndex; i++){ + if( p->aIndex[i].nPrefix<=nToken ){ + cksum2 = cksum2 ^ fts3ChecksumEntry( + zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos + ); + } + } + } + } + if( pT ) pModule->xClose(pT); + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + } + } + + sqlite3_finalize(pStmt); + } + + *pbOk = (cksum1==cksum2); + return rc; +} + +/* +** Run the integrity-check. If no error occurs and the current contents of +** the FTS index are correct, return SQLITE_OK. Or, if the contents of the +** FTS index are incorrect, return SQLITE_CORRUPT_VTAB. +** +** Or, if an error (e.g. an OOM or IO error) occurs, return an SQLite +** error code. +** +** The integrity-check works as follows. For each token and indexed token +** prefix in the document set, a 64-bit checksum is calculated (by code +** in fts3ChecksumEntry()) based on the following: +** +** + The index number (0 for the main index, 1 for the first prefix +** index etc.), +** + The token (or token prefix) text itself, +** + The language-id of the row it appears in, +** + The docid of the row it appears in, +** + The column it appears in, and +** + The tokens position within that column. +** +** The checksums for all entries in the index are XORed together to create +** a single checksum for the entire index. +** +** The integrity-check code calculates the same checksum in two ways: +** +** 1. By scanning the contents of the FTS index, and +** 2. By scanning and tokenizing the content table. +** +** If the two checksums are identical, the integrity-check is deemed to have +** passed. +*/ +static int fts3DoIntegrityCheck( + Fts3Table *p /* FTS3 table handle */ +){ + int rc; + int bOk = 0; + rc = fts3IntegrityCheck(p, &bOk); + if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB; + return rc; +} + /* ** Handle a 'special' INSERT of the form: ** @@ -127714,6 +131477,12 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){ rc = fts3DoOptimize(p, 0); }else if( nVal==7 && 0==sqlite3_strnicmp(zVal, "rebuild", 7) ){ rc = fts3DoRebuild(p); + }else if( nVal==15 && 0==sqlite3_strnicmp(zVal, "integrity-check", 15) ){ + rc = fts3DoIntegrityCheck(p); + }else if( nVal>6 && 0==sqlite3_strnicmp(zVal, "merge=", 6) ){ + rc = fts3DoIncrmerge(p, &zVal[6]); + }else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){ + rc = fts3DoAutoincrmerge(p, &zVal[10]); #ifdef SQLITE_TEST }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){ p->nNodeSize = atoi(&zVal[9]); @@ -127782,14 +131551,13 @@ SQLITE_PRIVATE int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *pCsr){ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); sqlite3_tokenizer_cursor *pTC = 0; - rc = pModule->xOpen(pT, zText, -1, &pTC); + rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ int nToken; /* Number of bytes in token */ int iDum1, iDum2; /* Dummy variables */ int iPos; /* Position of token in zText */ - pTC->pTokenizer = pT; rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ Fts3PhraseToken *pPT = pDef->pToken; @@ -127889,8 +131657,6 @@ static int fts3DeleteByRowid( rc = fts3DeleteAll(p, 1); *pnDoc = *pnDoc - 1; }else{ - sqlite3_int64 iRemove = sqlite3_value_int64(pRowid); - rc = fts3PendingTermsDocid(p, iRemove); fts3DeleteTerms(&rc, p, pRowid, aSzDel); if( p->zContentTbl==0 ){ fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); @@ -127909,7 +131675,16 @@ static int fts3DeleteByRowid( /* ** This function does the work for the xUpdate method of FTS3 virtual -** tables. +** tables. The schema of the virtual table being: +** +** CREATE TABLE ( +** , +**
    HIDDEN, +** docid HIDDEN, +** HIDDEN +** ); +** +** */ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( sqlite3_vtab *pVtab, /* FTS3 vtab object */ @@ -127926,6 +131701,10 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( int bInsertDone = 0; assert( p->pSegments==0 ); + assert( + nArg==1 /* DELETE operations */ + || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ + ); /* Check for a "special" INSERT operation. One of the form: ** @@ -127939,6 +131718,11 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( goto update_out; } + if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ + rc = SQLITE_CONSTRAINT; + goto update_out; + } + /* Allocate space to hold the change in document sizes */ aSzIns = sqlite3_malloc( sizeof(aSzIns[0])*(p->nColumn+1)*2 ); if( aSzIns==0 ){ @@ -128006,6 +131790,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( /* If this is an INSERT or UPDATE operation, insert the new record. */ if( nArg>1 && rc==SQLITE_OK ){ + int iLangid = sqlite3_value_int(apVal[2 + p->nColumn + 2]); if( bInsertDone==0 ){ rc = fts3InsertData(p, apVal, pRowid); if( rc==SQLITE_CONSTRAINT && p->zContentTbl==0 ){ @@ -128013,11 +131798,11 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( } } if( rc==SQLITE_OK && (!isRemove || *pRowid!=p->iPrevDocid ) ){ - rc = fts3PendingTermsDocid(p, *pRowid); + rc = fts3PendingTermsDocid(p, iLangid, *pRowid); } if( rc==SQLITE_OK ){ assert( p->iPrevDocid==*pRowid ); - rc = fts3InsertTerms(p, apVal, aSzIns); + rc = fts3InsertTerms(p, iLangid, apVal, aSzIns); } if( p->bHasDocsize ){ fts3InsertDocsize(&rc, p, aSzIns); @@ -128025,7 +131810,7 @@ SQLITE_PRIVATE int sqlite3Fts3UpdateMethod( nChng++; } - if( p->bHasStat ){ + if( p->bFts4 ){ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); } @@ -128422,10 +132207,11 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ SnippetIter *p = (SnippetIter *)ctx; SnippetPhrase *pPhrase = &p->aPhrase[iPhrase]; char *pCsr; + int rc; pPhrase->nToken = pExpr->pPhrase->nToken; - - pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol); + rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr); + assert( rc==SQLITE_OK || pCsr==0 ); if( pCsr ){ int iFirst = 0; pPhrase->pList = pCsr; @@ -128436,10 +132222,12 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){ pPhrase->iHead = iFirst; pPhrase->iTail = iFirst; }else{ - assert( pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 ); + assert( rc!=SQLITE_OK || ( + pPhrase->pList==0 && pPhrase->pHead==0 && pPhrase->pTail==0 + )); } - return SQLITE_OK; + return rc; } /* @@ -128594,6 +132382,7 @@ static int fts3StringAppend( */ static int fts3SnippetShift( Fts3Table *pTab, /* FTS3 table snippet comes from */ + int iLangid, /* Language id to use in tokenizing */ int nSnippet, /* Number of tokens desired for snippet */ const char *zDoc, /* Document text to extract snippet from */ int nDoc, /* Size of buffer zDoc in bytes */ @@ -128629,11 +132418,10 @@ static int fts3SnippetShift( /* Open a cursor on zDoc/nDoc. Check if there are (nSnippet+nDesired) ** or more tokens in zDoc/nDoc. */ - rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); + rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); if( rc!=SQLITE_OK ){ return rc; } - pC->pTokenizer = pTab->pTokenizer; while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ const char *ZDUMMY; int DUMMY1, DUMMY2, DUMMY3; rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); @@ -128693,11 +132481,10 @@ static int fts3SnippetText( /* Open a token cursor on the document. */ pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; - rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); + rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); if( rc!=SQLITE_OK ){ return rc; } - pC->pTokenizer = pTab->pTokenizer; while( rc==SQLITE_OK ){ int iBegin; /* Offset in zDoc of start of token */ @@ -128719,7 +132506,9 @@ static int fts3SnippetText( if( !isShiftDone ){ int n = nDoc - iBegin; - rc = fts3SnippetShift(pTab, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask); + rc = fts3SnippetShift( + pTab, pCsr->iLangid, nSnippet, &zDoc[iBegin], n, &iPos, &hlmask + ); isShiftDone = 1; /* Now that the shift has been done, check if the initial "..." are @@ -128831,13 +132620,14 @@ static int fts3ExprLocalHitsCb( int iPhrase, /* Phrase number */ void *pCtx /* Pointer to MatchInfo structure */ ){ + int rc = SQLITE_OK; MatchInfo *p = (MatchInfo *)pCtx; int iStart = iPhrase * p->nCol * 3; int i; - for(i=0; inCol; i++){ + for(i=0; inCol && rc==SQLITE_OK; i++){ char *pCsr; - pCsr = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i); + rc = sqlite3Fts3EvalPhrasePoslist(p->pCursor, pExpr, i, &pCsr); if( pCsr ){ p->aMatchinfo[iStart+i*3] = fts3ColumnlistCount(&pCsr); }else{ @@ -128845,7 +132635,7 @@ static int fts3ExprLocalHitsCb( } } - return SQLITE_OK; + return rc; } static int fts3MatchinfoCheck( @@ -128855,8 +132645,8 @@ static int fts3MatchinfoCheck( ){ if( (cArg==FTS3_MATCHINFO_NPHRASE) || (cArg==FTS3_MATCHINFO_NCOL) - || (cArg==FTS3_MATCHINFO_NDOC && pTab->bHasStat) - || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bHasStat) + || (cArg==FTS3_MATCHINFO_NDOC && pTab->bFts4) + || (cArg==FTS3_MATCHINFO_AVGLENGTH && pTab->bFts4) || (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize) || (cArg==FTS3_MATCHINFO_LCS) || (cArg==FTS3_MATCHINFO_HITS) @@ -129006,8 +132796,10 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){ int nLive = 0; /* Number of iterators in aIter not at EOF */ for(i=0; inPhrase; i++){ + int rc; LcsIterator *pIt = &aIter[i]; - pIt->pRead = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol); + rc = sqlite3Fts3EvalPhrasePoslist(pCsr, pIt->pExpr, iCol, &pIt->pRead); + if( rc!=SQLITE_OK ) return rc; if( pIt->pRead ){ pIt->iPos = pIt->iPosOffset; fts3LcsIteratorAdvance(&aIter[i]); @@ -129359,9 +133151,10 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ int iTerm; /* For looping through nTerm phrase terms */ char *pList; /* Pointer to position list for phrase */ int iPos = 0; /* First position in position-list */ + int rc; UNUSED_PARAMETER(iPhrase); - pList = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol); + rc = sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pList); nTerm = pExpr->pPhrase->nToken; if( pList ){ fts3GetDeltaPosition(&pList, &iPos); @@ -129375,7 +133168,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){ pT->iPos = iPos; } - return SQLITE_OK; + return rc; } /* @@ -129452,9 +133245,10 @@ SQLITE_PRIVATE void sqlite3Fts3Offsets( } /* Initialize a tokenizer iterator to iterate through column iCol. */ - rc = pMod->xOpen(pTab->pTokenizer, zDoc, nDoc, &pC); + rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, + zDoc, nDoc, &pC + ); if( rc!=SQLITE_OK ) goto offsets_out; - pC->pTokenizer = pTab->pTokenizer; rc = pMod->xNext(pC, &ZDUMMY, &NDUMMY, &iStart, &iEnd, &iCurrent); while( rc==SQLITE_OK ){ @@ -129562,6 +133356,769 @@ SQLITE_PRIVATE void sqlite3Fts3Matchinfo( #endif /************** End of fts3_snippet.c ****************************************/ +/************** Begin file fts3_unicode.c ************************************/ +/* +** 2012 May 24 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +** +** Implementation of the "unicode" full-text-search tokenizer. +*/ + +#ifdef SQLITE_ENABLE_FTS4_UNICODE61 + +#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) + +/* #include */ +/* #include */ +/* #include */ +/* #include */ + + +/* +** The following two macros - READ_UTF8 and WRITE_UTF8 - have been copied +** from the sqlite3 source file utf.c. If this file is compiled as part +** of the amalgamation, they are not required. +*/ +#ifndef SQLITE_AMALGAMATION + +static const unsigned char sqlite3Utf8Trans1[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, +}; + +#define READ_UTF8(zIn, zTerm, c) \ + c = *(zIn++); \ + if( c>=0xc0 ){ \ + c = sqlite3Utf8Trans1[c-0xc0]; \ + while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \ + c = (c<<6) + (0x3f & *(zIn++)); \ + } \ + if( c<0x80 \ + || (c&0xFFFFF800)==0xD800 \ + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ + } + +#define WRITE_UTF8(zOut, c) { \ + if( c<0x00080 ){ \ + *zOut++ = (u8)(c&0xFF); \ + } \ + else if( c<0x00800 ){ \ + *zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \ + *zOut++ = 0x80 + (u8)(c & 0x3F); \ + } \ + else if( c<0x10000 ){ \ + *zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \ + *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ + *zOut++ = 0x80 + (u8)(c & 0x3F); \ + }else{ \ + *zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \ + *zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \ + *zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \ + *zOut++ = 0x80 + (u8)(c & 0x3F); \ + } \ +} + +#endif /* ifndef SQLITE_AMALGAMATION */ + +typedef struct unicode_tokenizer unicode_tokenizer; +typedef struct unicode_cursor unicode_cursor; + +struct unicode_tokenizer { + sqlite3_tokenizer base; + int bRemoveDiacritic; + int nException; + int *aiException; +}; + +struct unicode_cursor { + sqlite3_tokenizer_cursor base; + const unsigned char *aInput; /* Input text being tokenized */ + int nInput; /* Size of aInput[] in bytes */ + int iOff; /* Current offset within aInput[] */ + int iToken; /* Index of next token to be returned */ + char *zToken; /* storage for current token */ + int nAlloc; /* space allocated at zToken */ +}; + + +/* +** Destroy a tokenizer allocated by unicodeCreate(). +*/ +static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){ + if( pTokenizer ){ + unicode_tokenizer *p = (unicode_tokenizer *)pTokenizer; + sqlite3_free(p->aiException); + sqlite3_free(p); + } + return SQLITE_OK; +} + +/* +** As part of a tokenchars= or separators= option, the CREATE VIRTUAL TABLE +** statement has specified that the tokenizer for this table shall consider +** all characters in string zIn/nIn to be separators (if bAlnum==0) or +** token characters (if bAlnum==1). +** +** For each codepoint in the zIn/nIn string, this function checks if the +** sqlite3FtsUnicodeIsalnum() function already returns the desired result. +** If so, no action is taken. Otherwise, the codepoint is added to the +** unicode_tokenizer.aiException[] array. For the purposes of tokenization, +** the return value of sqlite3FtsUnicodeIsalnum() is inverted for all +** codepoints in the aiException[] array. +** +** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic() +** identifies as a diacritic) occurs in the zIn/nIn string it is ignored. +** It is not possible to change the behaviour of the tokenizer with respect +** to these codepoints. +*/ +static int unicodeAddExceptions( + unicode_tokenizer *p, /* Tokenizer to add exceptions to */ + int bAlnum, /* Replace Isalnum() return value with this */ + const char *zIn, /* Array of characters to make exceptions */ + int nIn /* Length of z in bytes */ +){ + const unsigned char *z = (const unsigned char *)zIn; + const unsigned char *zTerm = &z[nIn]; + int iCode; + int nEntry = 0; + + assert( bAlnum==0 || bAlnum==1 ); + + while( zaiException, (p->nException+nEntry)*sizeof(int)); + if( aNew==0 ) return SQLITE_NOMEM; + nNew = p->nException; + + z = (const unsigned char *)zIn; + while( zi; j--) aNew[j] = aNew[j-1]; + aNew[i] = iCode; + nNew++; + } + } + p->aiException = aNew; + p->nException = nNew; + } + + return SQLITE_OK; +} + +/* +** Return true if the p->aiException[] array contains the value iCode. +*/ +static int unicodeIsException(unicode_tokenizer *p, int iCode){ + if( p->nException>0 ){ + int *a = p->aiException; + int iLo = 0; + int iHi = p->nException-1; + + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + if( iCode==a[iTest] ){ + return 1; + }else if( iCode>a[iTest] ){ + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + } + + return 0; +} + +/* +** Return true if, for the purposes of tokenization, codepoint iCode is +** considered a token character (not a separator). +*/ +static int unicodeIsAlnum(unicode_tokenizer *p, int iCode){ + assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 ); + return sqlite3FtsUnicodeIsalnum(iCode) ^ unicodeIsException(p, iCode); +} + +/* +** Create a new tokenizer instance. +*/ +static int unicodeCreate( + int nArg, /* Size of array argv[] */ + const char * const *azArg, /* Tokenizer creation arguments */ + sqlite3_tokenizer **pp /* OUT: New tokenizer handle */ +){ + unicode_tokenizer *pNew; /* New tokenizer object */ + int i; + int rc = SQLITE_OK; + + pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer)); + if( pNew==NULL ) return SQLITE_NOMEM; + memset(pNew, 0, sizeof(unicode_tokenizer)); + pNew->bRemoveDiacritic = 1; + + for(i=0; rc==SQLITE_OK && ibRemoveDiacritic = 1; + } + else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){ + pNew->bRemoveDiacritic = 0; + } + else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){ + rc = unicodeAddExceptions(pNew, 1, &z[11], n-11); + } + else if( n>=11 && memcmp("separators=", z, 11)==0 ){ + rc = unicodeAddExceptions(pNew, 0, &z[11], n-11); + } + else{ + /* Unrecognized argument */ + rc = SQLITE_ERROR; + } + } + + if( rc!=SQLITE_OK ){ + unicodeDestroy((sqlite3_tokenizer *)pNew); + pNew = 0; + } + *pp = (sqlite3_tokenizer *)pNew; + return rc; +} + +/* +** Prepare to begin tokenizing a particular string. The input +** string to be tokenized is pInput[0..nBytes-1]. A cursor +** used to incrementally tokenize this string is returned in +** *ppCursor. +*/ +static int unicodeOpen( + sqlite3_tokenizer *p, /* The tokenizer */ + const char *aInput, /* Input string */ + int nInput, /* Size of string aInput in bytes */ + sqlite3_tokenizer_cursor **pp /* OUT: New cursor object */ +){ + unicode_cursor *pCsr; + + pCsr = (unicode_cursor *)sqlite3_malloc(sizeof(unicode_cursor)); + if( pCsr==0 ){ + return SQLITE_NOMEM; + } + memset(pCsr, 0, sizeof(unicode_cursor)); + + pCsr->aInput = (const unsigned char *)aInput; + if( aInput==0 ){ + pCsr->nInput = 0; + }else if( nInput<0 ){ + pCsr->nInput = (int)strlen(aInput); + }else{ + pCsr->nInput = nInput; + } + + *pp = &pCsr->base; + UNUSED_PARAMETER(p); + return SQLITE_OK; +} + +/* +** Close a tokenization cursor previously opened by a call to +** simpleOpen() above. +*/ +static int unicodeClose(sqlite3_tokenizer_cursor *pCursor){ + unicode_cursor *pCsr = (unicode_cursor *) pCursor; + sqlite3_free(pCsr->zToken); + sqlite3_free(pCsr); + return SQLITE_OK; +} + +/* +** Extract the next token from a tokenization cursor. The cursor must +** have been opened by a prior call to simpleOpen(). +*/ +static int unicodeNext( + sqlite3_tokenizer_cursor *pC, /* Cursor returned by simpleOpen */ + const char **paToken, /* OUT: Token text */ + int *pnToken, /* OUT: Number of bytes at *paToken */ + int *piStart, /* OUT: Starting offset of token */ + int *piEnd, /* OUT: Ending offset of token */ + int *piPos /* OUT: Position integer of token */ +){ + unicode_cursor *pCsr = (unicode_cursor *)pC; + unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer); + int iCode; + char *zOut; + const unsigned char *z = &pCsr->aInput[pCsr->iOff]; + const unsigned char *zStart = z; + const unsigned char *zEnd; + const unsigned char *zTerm = &pCsr->aInput[pCsr->nInput]; + + /* Scan past any delimiter characters before the start of the next token. + ** Return SQLITE_DONE early if this takes us all the way to the end of + ** the input. */ + while( z=zTerm ) return SQLITE_DONE; + + zOut = pCsr->zToken; + do { + int iOut; + + /* Grow the output buffer if required. */ + if( (zOut-pCsr->zToken)>=(pCsr->nAlloc-4) ){ + char *zNew = sqlite3_realloc(pCsr->zToken, pCsr->nAlloc+64); + if( !zNew ) return SQLITE_NOMEM; + zOut = &zNew[zOut - pCsr->zToken]; + pCsr->zToken = zNew; + pCsr->nAlloc += 64; + } + + /* Write the folded case of the last character read to the output */ + zEnd = z; + iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic); + if( iOut ){ + WRITE_UTF8(zOut, iOut); + } + + /* If the cursor is not at EOF, read the next character */ + if( z>=zTerm ) break; + READ_UTF8(z, zTerm, iCode); + }while( unicodeIsAlnum(p, iCode) + || sqlite3FtsUnicodeIsdiacritic(iCode) + ); + + /* Set the output variables and return. */ + pCsr->iOff = (z - pCsr->aInput); + *paToken = pCsr->zToken; + *pnToken = zOut - pCsr->zToken; + *piStart = (zStart - pCsr->aInput); + *piEnd = (zEnd - pCsr->aInput); + *piPos = pCsr->iToken++; + return SQLITE_OK; +} + +/* +** Set *ppModule to a pointer to the sqlite3_tokenizer_module +** structure for the unicode tokenizer. +*/ +SQLITE_PRIVATE void sqlite3Fts3UnicodeTokenizer(sqlite3_tokenizer_module const **ppModule){ + static const sqlite3_tokenizer_module module = { + 0, + unicodeCreate, + unicodeDestroy, + unicodeOpen, + unicodeClose, + unicodeNext, + 0, + }; + *ppModule = &module; +} + +#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */ +#endif /* ifndef SQLITE_ENABLE_FTS4_UNICODE61 */ + +/************** End of fts3_unicode.c ****************************************/ +/************** Begin file fts3_unicode2.c ***********************************/ +/* +** 2012 May 25 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +****************************************************************************** +*/ + +/* +** DO NOT EDIT THIS MACHINE GENERATED FILE. +*/ + +#if defined(SQLITE_ENABLE_FTS4_UNICODE61) +#if defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) + +/* #include */ + +/* +** Return true if the argument corresponds to a unicode codepoint +** classified as either a letter or a number. Otherwise false. +** +** The results are undefined if the value passed to this function +** is less than zero. +*/ +SQLITE_PRIVATE int sqlite3FtsUnicodeIsalnum(int c){ + /* Each unsigned integer in the following array corresponds to a contiguous + ** range of unicode codepoints that are not either letters or numbers (i.e. + ** codepoints for which this function should return 0). + ** + ** The most significant 22 bits in each 32-bit value contain the first + ** codepoint in the range. The least significant 10 bits are used to store + ** the size of the range (always at least 1). In other words, the value + ** ((C<<22) + N) represents a range of N codepoints starting with codepoint + ** C. It is not possible to represent a range larger than 1023 codepoints + ** using this format. + */ + const static unsigned int aEntry[] = { + 0x00000030, 0x0000E807, 0x00016C06, 0x0001EC2F, 0x0002AC07, + 0x0002D001, 0x0002D803, 0x0002EC01, 0x0002FC01, 0x00035C01, + 0x0003DC01, 0x000B0804, 0x000B480E, 0x000B9407, 0x000BB401, + 0x000BBC81, 0x000DD401, 0x000DF801, 0x000E1002, 0x000E1C01, + 0x000FD801, 0x00120808, 0x00156806, 0x00162402, 0x00163C01, + 0x00164437, 0x0017CC02, 0x00180005, 0x00181816, 0x00187802, + 0x00192C15, 0x0019A804, 0x0019C001, 0x001B5001, 0x001B580F, + 0x001B9C07, 0x001BF402, 0x001C000E, 0x001C3C01, 0x001C4401, + 0x001CC01B, 0x001E980B, 0x001FAC09, 0x001FD804, 0x00205804, + 0x00206C09, 0x00209403, 0x0020A405, 0x0020C00F, 0x00216403, + 0x00217801, 0x0023901B, 0x00240004, 0x0024E803, 0x0024F812, + 0x00254407, 0x00258804, 0x0025C001, 0x00260403, 0x0026F001, + 0x0026F807, 0x00271C02, 0x00272C03, 0x00275C01, 0x00278802, + 0x0027C802, 0x0027E802, 0x00280403, 0x0028F001, 0x0028F805, + 0x00291C02, 0x00292C03, 0x00294401, 0x0029C002, 0x0029D401, + 0x002A0403, 0x002AF001, 0x002AF808, 0x002B1C03, 0x002B2C03, + 0x002B8802, 0x002BC002, 0x002C0403, 0x002CF001, 0x002CF807, + 0x002D1C02, 0x002D2C03, 0x002D5802, 0x002D8802, 0x002DC001, + 0x002E0801, 0x002EF805, 0x002F1803, 0x002F2804, 0x002F5C01, + 0x002FCC08, 0x00300403, 0x0030F807, 0x00311803, 0x00312804, + 0x00315402, 0x00318802, 0x0031FC01, 0x00320802, 0x0032F001, + 0x0032F807, 0x00331803, 0x00332804, 0x00335402, 0x00338802, + 0x00340802, 0x0034F807, 0x00351803, 0x00352804, 0x00355C01, + 0x00358802, 0x0035E401, 0x00360802, 0x00372801, 0x00373C06, + 0x00375801, 0x00376008, 0x0037C803, 0x0038C401, 0x0038D007, + 0x0038FC01, 0x00391C09, 0x00396802, 0x003AC401, 0x003AD006, + 0x003AEC02, 0x003B2006, 0x003C041F, 0x003CD00C, 0x003DC417, + 0x003E340B, 0x003E6424, 0x003EF80F, 0x003F380D, 0x0040AC14, + 0x00412806, 0x00415804, 0x00417803, 0x00418803, 0x00419C07, + 0x0041C404, 0x0042080C, 0x00423C01, 0x00426806, 0x0043EC01, + 0x004D740C, 0x004E400A, 0x00500001, 0x0059B402, 0x005A0001, + 0x005A6C02, 0x005BAC03, 0x005C4803, 0x005CC805, 0x005D4802, + 0x005DC802, 0x005ED023, 0x005F6004, 0x005F7401, 0x0060000F, + 0x0062A401, 0x0064800C, 0x0064C00C, 0x00650001, 0x00651002, + 0x0066C011, 0x00672002, 0x00677822, 0x00685C05, 0x00687802, + 0x0069540A, 0x0069801D, 0x0069FC01, 0x006A8007, 0x006AA006, + 0x006C0005, 0x006CD011, 0x006D6823, 0x006E0003, 0x006E840D, + 0x006F980E, 0x006FF004, 0x00709014, 0x0070EC05, 0x0071F802, + 0x00730008, 0x00734019, 0x0073B401, 0x0073C803, 0x00770027, + 0x0077F004, 0x007EF401, 0x007EFC03, 0x007F3403, 0x007F7403, + 0x007FB403, 0x007FF402, 0x00800065, 0x0081A806, 0x0081E805, + 0x00822805, 0x0082801A, 0x00834021, 0x00840002, 0x00840C04, + 0x00842002, 0x00845001, 0x00845803, 0x00847806, 0x00849401, + 0x00849C01, 0x0084A401, 0x0084B801, 0x0084E802, 0x00850005, + 0x00852804, 0x00853C01, 0x00864264, 0x00900027, 0x0091000B, + 0x0092704E, 0x00940200, 0x009C0475, 0x009E53B9, 0x00AD400A, + 0x00B39406, 0x00B3BC03, 0x00B3E404, 0x00B3F802, 0x00B5C001, + 0x00B5FC01, 0x00B7804F, 0x00B8C00C, 0x00BA001A, 0x00BA6C59, + 0x00BC00D6, 0x00BFC00C, 0x00C00005, 0x00C02019, 0x00C0A807, + 0x00C0D802, 0x00C0F403, 0x00C26404, 0x00C28001, 0x00C3EC01, + 0x00C64002, 0x00C6580A, 0x00C70024, 0x00C8001F, 0x00C8A81E, + 0x00C94001, 0x00C98020, 0x00CA2827, 0x00CB003F, 0x00CC0100, + 0x01370040, 0x02924037, 0x0293F802, 0x02983403, 0x0299BC10, + 0x029A7C01, 0x029BC008, 0x029C0017, 0x029C8002, 0x029E2402, + 0x02A00801, 0x02A01801, 0x02A02C01, 0x02A08C09, 0x02A0D804, + 0x02A1D004, 0x02A20002, 0x02A2D011, 0x02A33802, 0x02A38012, + 0x02A3E003, 0x02A4980A, 0x02A51C0D, 0x02A57C01, 0x02A60004, + 0x02A6CC1B, 0x02A77802, 0x02A8A40E, 0x02A90C01, 0x02A93002, + 0x02A97004, 0x02A9DC03, 0x02A9EC01, 0x02AAC001, 0x02AAC803, + 0x02AADC02, 0x02AAF802, 0x02AB0401, 0x02AB7802, 0x02ABAC07, + 0x02ABD402, 0x02AF8C0B, 0x03600001, 0x036DFC02, 0x036FFC02, + 0x037FFC02, 0x03E3FC01, 0x03EC7801, 0x03ECA401, 0x03EEC810, + 0x03F4F802, 0x03F7F002, 0x03F8001A, 0x03F88007, 0x03F8C023, + 0x03F95013, 0x03F9A004, 0x03FBFC01, 0x03FC040F, 0x03FC6807, + 0x03FCEC06, 0x03FD6C0B, 0x03FF8007, 0x03FFA007, 0x03FFE405, + 0x04040003, 0x0404DC09, 0x0405E411, 0x0406400C, 0x0407402E, + 0x040E7C01, 0x040F4001, 0x04215C01, 0x04247C01, 0x0424FC01, + 0x04280403, 0x04281402, 0x04283004, 0x0428E003, 0x0428FC01, + 0x04294009, 0x0429FC01, 0x042CE407, 0x04400003, 0x0440E016, + 0x04420003, 0x0442C012, 0x04440003, 0x04449C0E, 0x04450004, + 0x04460003, 0x0446CC0E, 0x04471404, 0x045AAC0D, 0x0491C004, + 0x05BD442E, 0x05BE3C04, 0x074000F6, 0x07440027, 0x0744A4B5, + 0x07480046, 0x074C0057, 0x075B0401, 0x075B6C01, 0x075BEC01, + 0x075C5401, 0x075CD401, 0x075D3C01, 0x075DBC01, 0x075E2401, + 0x075EA401, 0x075F0C01, 0x07BBC002, 0x07C0002C, 0x07C0C064, + 0x07C2800F, 0x07C2C40E, 0x07C3040F, 0x07C3440F, 0x07C4401F, + 0x07C4C03C, 0x07C5C02B, 0x07C7981D, 0x07C8402B, 0x07C90009, + 0x07C94002, 0x07CC0021, 0x07CCC006, 0x07CCDC46, 0x07CE0014, + 0x07CE8025, 0x07CF1805, 0x07CF8011, 0x07D0003F, 0x07D10001, + 0x07D108B6, 0x07D3E404, 0x07D4003E, 0x07D50004, 0x07D54018, + 0x07D7EC46, 0x07D9140B, 0x07DA0046, 0x07DC0074, 0x38000401, + 0x38008060, 0x380400F0, 0x3C000001, 0x3FFFF401, 0x40000001, + 0x43FFF401, + }; + static const unsigned int aAscii[4] = { + 0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001, + }; + + if( c<128 ){ + return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 ); + }else if( c<(1<<22) ){ + unsigned int key = (((unsigned int)c)<<10) | 0x000003FF; + int iRes; + int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; + int iLo = 0; + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + if( key >= aEntry[iTest] ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + assert( aEntry[0]=aEntry[iRes] ); + return (c >= ((aEntry[iRes]>>10) + (aEntry[iRes]&0x3FF))); + } + return 1; +} + + +/* +** If the argument is a codepoint corresponding to a lowercase letter +** in the ASCII range with a diacritic added, return the codepoint +** of the ASCII letter only. For example, if passed 235 - "LATIN +** SMALL LETTER E WITH DIAERESIS" - return 65 ("LATIN SMALL LETTER +** E"). The resuls of passing a codepoint that corresponds to an +** uppercase letter are undefined. +*/ +static int remove_diacritic(int c){ + unsigned short aDia[] = { + 0, 1797, 1848, 1859, 1891, 1928, 1940, 1995, + 2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286, + 2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732, + 2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336, + 3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928, + 3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234, + 4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504, + 6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529, + 61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726, + 61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122, + 62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536, + 62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730, + 62924, 63050, 63082, 63274, 63390, + }; + char aChar[] = { + '\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c', + 'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r', + 's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o', + 'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r', + 'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h', + 'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't', + 'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a', + 'e', 'i', 'o', 'u', 'y', + }; + + unsigned int key = (((unsigned int)c)<<3) | 0x00000007; + int iRes = 0; + int iHi = sizeof(aDia)/sizeof(aDia[0]) - 1; + int iLo = 0; + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + if( key >= aDia[iTest] ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + assert( key>=aDia[iRes] ); + return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]); +}; + + +/* +** Return true if the argument interpreted as a unicode codepoint +** is a diacritical modifier character. +*/ +SQLITE_PRIVATE int sqlite3FtsUnicodeIsdiacritic(int c){ + unsigned int mask0 = 0x08029FDF; + unsigned int mask1 = 0x000361F8; + if( c<768 || c>817 ) return 0; + return (c < 768+32) ? + (mask0 & (1 << (c-768))) : + (mask1 & (1 << (c-768-32))); +} + + +/* +** Interpret the argument as a unicode codepoint. If the codepoint +** is an upper case character that has a lower case equivalent, +** return the codepoint corresponding to the lower case version. +** Otherwise, return a copy of the argument. +** +** The results are undefined if the value passed to this function +** is less than zero. +*/ +SQLITE_PRIVATE int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){ + /* Each entry in the following array defines a rule for folding a range + ** of codepoints to lower case. The rule applies to a range of nRange + ** codepoints starting at codepoint iCode. + ** + ** If the least significant bit in flags is clear, then the rule applies + ** to all nRange codepoints (i.e. all nRange codepoints are upper case and + ** need to be folded). Or, if it is set, then the rule only applies to + ** every second codepoint in the range, starting with codepoint C. + ** + ** The 7 most significant bits in flags are an index into the aiOff[] + ** array. If a specific codepoint C does require folding, then its lower + ** case equivalent is ((C + aiOff[flags>>1]) & 0xFFFF). + ** + ** The contents of this array are generated by parsing the CaseFolding.txt + ** file distributed as part of the "Unicode Character Database". See + ** http://www.unicode.org for details. + */ + static const struct TableEntry { + unsigned short iCode; + unsigned char flags; + unsigned char nRange; + } aEntry[] = { + {65, 14, 26}, {181, 64, 1}, {192, 14, 23}, + {216, 14, 7}, {256, 1, 48}, {306, 1, 6}, + {313, 1, 16}, {330, 1, 46}, {376, 116, 1}, + {377, 1, 6}, {383, 104, 1}, {385, 50, 1}, + {386, 1, 4}, {390, 44, 1}, {391, 0, 1}, + {393, 42, 2}, {395, 0, 1}, {398, 32, 1}, + {399, 38, 1}, {400, 40, 1}, {401, 0, 1}, + {403, 42, 1}, {404, 46, 1}, {406, 52, 1}, + {407, 48, 1}, {408, 0, 1}, {412, 52, 1}, + {413, 54, 1}, {415, 56, 1}, {416, 1, 6}, + {422, 60, 1}, {423, 0, 1}, {425, 60, 1}, + {428, 0, 1}, {430, 60, 1}, {431, 0, 1}, + {433, 58, 2}, {435, 1, 4}, {439, 62, 1}, + {440, 0, 1}, {444, 0, 1}, {452, 2, 1}, + {453, 0, 1}, {455, 2, 1}, {456, 0, 1}, + {458, 2, 1}, {459, 1, 18}, {478, 1, 18}, + {497, 2, 1}, {498, 1, 4}, {502, 122, 1}, + {503, 134, 1}, {504, 1, 40}, {544, 110, 1}, + {546, 1, 18}, {570, 70, 1}, {571, 0, 1}, + {573, 108, 1}, {574, 68, 1}, {577, 0, 1}, + {579, 106, 1}, {580, 28, 1}, {581, 30, 1}, + {582, 1, 10}, {837, 36, 1}, {880, 1, 4}, + {886, 0, 1}, {902, 18, 1}, {904, 16, 3}, + {908, 26, 1}, {910, 24, 2}, {913, 14, 17}, + {931, 14, 9}, {962, 0, 1}, {975, 4, 1}, + {976, 140, 1}, {977, 142, 1}, {981, 146, 1}, + {982, 144, 1}, {984, 1, 24}, {1008, 136, 1}, + {1009, 138, 1}, {1012, 130, 1}, {1013, 128, 1}, + {1015, 0, 1}, {1017, 152, 1}, {1018, 0, 1}, + {1021, 110, 3}, {1024, 34, 16}, {1040, 14, 32}, + {1120, 1, 34}, {1162, 1, 54}, {1216, 6, 1}, + {1217, 1, 14}, {1232, 1, 88}, {1329, 22, 38}, + {4256, 66, 38}, {4295, 66, 1}, {4301, 66, 1}, + {7680, 1, 150}, {7835, 132, 1}, {7838, 96, 1}, + {7840, 1, 96}, {7944, 150, 8}, {7960, 150, 6}, + {7976, 150, 8}, {7992, 150, 8}, {8008, 150, 6}, + {8025, 151, 8}, {8040, 150, 8}, {8072, 150, 8}, + {8088, 150, 8}, {8104, 150, 8}, {8120, 150, 2}, + {8122, 126, 2}, {8124, 148, 1}, {8126, 100, 1}, + {8136, 124, 4}, {8140, 148, 1}, {8152, 150, 2}, + {8154, 120, 2}, {8168, 150, 2}, {8170, 118, 2}, + {8172, 152, 1}, {8184, 112, 2}, {8186, 114, 2}, + {8188, 148, 1}, {8486, 98, 1}, {8490, 92, 1}, + {8491, 94, 1}, {8498, 12, 1}, {8544, 8, 16}, + {8579, 0, 1}, {9398, 10, 26}, {11264, 22, 47}, + {11360, 0, 1}, {11362, 88, 1}, {11363, 102, 1}, + {11364, 90, 1}, {11367, 1, 6}, {11373, 84, 1}, + {11374, 86, 1}, {11375, 80, 1}, {11376, 82, 1}, + {11378, 0, 1}, {11381, 0, 1}, {11390, 78, 2}, + {11392, 1, 100}, {11499, 1, 4}, {11506, 0, 1}, + {42560, 1, 46}, {42624, 1, 24}, {42786, 1, 14}, + {42802, 1, 62}, {42873, 1, 4}, {42877, 76, 1}, + {42878, 1, 10}, {42891, 0, 1}, {42893, 74, 1}, + {42896, 1, 4}, {42912, 1, 10}, {42922, 72, 1}, + {65313, 14, 26}, + }; + static const unsigned short aiOff[] = { + 1, 2, 8, 15, 16, 26, 28, 32, + 37, 38, 40, 48, 63, 64, 69, 71, + 79, 80, 116, 202, 203, 205, 206, 207, + 209, 210, 211, 213, 214, 217, 218, 219, + 775, 7264, 10792, 10795, 23228, 23256, 30204, 54721, + 54753, 54754, 54756, 54787, 54793, 54809, 57153, 57274, + 57921, 58019, 58363, 61722, 65268, 65341, 65373, 65406, + 65408, 65410, 65415, 65424, 65436, 65439, 65450, 65462, + 65472, 65476, 65478, 65480, 65482, 65488, 65506, 65511, + 65514, 65521, 65527, 65528, 65529, + }; + + int ret = c; + + assert( c>=0 ); + assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 ); + + if( c<128 ){ + if( c>='A' && c<='Z' ) ret = c + ('a' - 'A'); + }else if( c<65536 ){ + int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1; + int iLo = 0; + int iRes = -1; + + while( iHi>=iLo ){ + int iTest = (iHi + iLo) / 2; + int cmp = (c - aEntry[iTest].iCode); + if( cmp>=0 ){ + iRes = iTest; + iLo = iTest+1; + }else{ + iHi = iTest-1; + } + } + assert( iRes<0 || c>=aEntry[iRes].iCode ); + + if( iRes>=0 ){ + const struct TableEntry *p = &aEntry[iRes]; + if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){ + ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF; + assert( ret>0 ); + } + } + + if( bRemoveDiacritic ) ret = remove_diacritic(ret); + } + + else if( c>=66560 && c<66600 ){ + ret = c + 40; + } + + return ret; +} +#endif /* defined(SQLITE_ENABLE_FTS3) || defined(SQLITE_ENABLE_FTS4) */ +#endif /* !defined(SQLITE_ENABLE_FTS4_UNICODE61) */ + +/************** End of fts3_unicode2.c ***************************************/ /************** Begin file rtree.c *******************************************/ /* ** 2001 September 15 @@ -129745,6 +134302,19 @@ struct Rtree { #define RTREE_COORD_REAL32 0 #define RTREE_COORD_INT32 1 +/* +** If SQLITE_RTREE_INT_ONLY is defined, then this virtual table will +** only deal with integer coordinates. No floating point operations +** will be done. +*/ +#ifdef SQLITE_RTREE_INT_ONLY + typedef sqlite3_int64 RtreeDValue; /* High accuracy coordinate */ + typedef int RtreeValue; /* Low accuracy coordinate */ +#else + typedef double RtreeDValue; /* High accuracy coordinate */ + typedef float RtreeValue; /* Low accuracy coordinate */ +#endif + /* ** The minimum number of cells allowed for a node is a third of the ** maximum. In Gutman's notation: @@ -129780,20 +134350,25 @@ struct RtreeCursor { }; union RtreeCoord { - float f; + RtreeValue f; int i; }; /* ** The argument is an RtreeCoord. Return the value stored within the RtreeCoord -** formatted as a double. This macro assumes that local variable pRtree points -** to the Rtree structure associated with the RtreeCoord. +** formatted as a RtreeDValue (double or int64). This macro assumes that local +** variable pRtree points to the Rtree structure associated with the +** RtreeCoord. */ -#define DCOORD(coord) ( \ - (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ - ((double)coord.f) : \ - ((double)coord.i) \ -) +#ifdef SQLITE_RTREE_INT_ONLY +# define DCOORD(coord) ((RtreeDValue)coord.i) +#else +# define DCOORD(coord) ( \ + (pRtree->eCoordType==RTREE_COORD_REAL32) ? \ + ((double)coord.f) : \ + ((double)coord.i) \ + ) +#endif /* ** A search constraint. @@ -129801,8 +134376,8 @@ union RtreeCoord { struct RtreeConstraint { int iCoord; /* Index of constrained coordinate */ int op; /* Constraining operation */ - double rValue; /* Constraint value. */ - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + RtreeDValue rValue; /* Constraint value. */ + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); sqlite3_rtree_geometry *pGeom; /* Constraint callback argument for a MATCH */ }; @@ -129850,10 +134425,10 @@ struct RtreeCell { */ struct RtreeMatchArg { u32 magic; /* Always RTREE_GEOMETRY_MAGIC */ - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue*, int *); void *pContext; int nParam; - double aParam[1]; + RtreeDValue aParam[1]; }; /* @@ -129865,7 +134440,7 @@ struct RtreeMatchArg { ** the geometry callback function). */ struct RtreeGeomCallback { - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *); + int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*); void *pContext; }; @@ -130431,7 +135006,7 @@ static int testRtreeGeom( int *pbRes /* OUT: Test result */ ){ int i; - double aCoord[RTREE_MAX_DIMENSIONS*2]; + RtreeDValue aCoord[RTREE_MAX_DIMENSIONS*2]; int nCoord = pRtree->nDim*2; assert( pConstraint->op==RTREE_MATCH ); @@ -130461,8 +135036,8 @@ static int testRtreeCell(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; bRes==0 && iinConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; - double cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); - double cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); + RtreeDValue cell_min = DCOORD(cell.aCoord[(p->iCoord>>1)*2]); + RtreeDValue cell_max = DCOORD(cell.aCoord[(p->iCoord>>1)*2+1]); assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH @@ -130514,7 +135089,7 @@ static int testRtreeEntry(Rtree *pRtree, RtreeCursor *pCursor, int *pbEof){ nodeGetCell(pRtree, pCursor->pNode, pCursor->iCell, &cell); for(ii=0; iinConstraint; ii++){ RtreeConstraint *p = &pCursor->aConstraint[ii]; - double coord = DCOORD(cell.aCoord[p->iCoord]); + RtreeDValue coord = DCOORD(cell.aCoord[p->iCoord]); int res; assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_MATCH @@ -130712,9 +135287,12 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ }else{ RtreeCoord c; nodeGetCoord(pRtree, pCsr->pNode, pCsr->iCell, i-1, &c); +#ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ sqlite3_result_double(ctx, c.f); - }else{ + }else +#endif + { assert( pRtree->eCoordType==RTREE_COORD_INT32 ); sqlite3_result_int(ctx, c.i); } @@ -130761,7 +135339,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ /* Check that the blob is roughly the right size. */ nBlob = sqlite3_value_bytes(pValue); if( nBlob<(int)sizeof(RtreeMatchArg) - || ((nBlob-sizeof(RtreeMatchArg))%sizeof(double))!=0 + || ((nBlob-sizeof(RtreeMatchArg))%sizeof(RtreeDValue))!=0 ){ return SQLITE_ERROR; } @@ -130775,7 +135353,7 @@ static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){ memcpy(p, sqlite3_value_blob(pValue), nBlob); if( p->magic!=RTREE_GEOMETRY_MAGIC - || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(double)) + || nBlob!=(int)(sizeof(RtreeMatchArg) + (p->nParam-1)*sizeof(RtreeDValue)) ){ sqlite3_free(pGeom); return SQLITE_ERROR; @@ -130847,7 +135425,11 @@ static int rtreeFilter( break; } }else{ +#ifdef SQLITE_RTREE_INT_ONLY + p->rValue = sqlite3_value_int64(argv[ii]); +#else p->rValue = sqlite3_value_double(argv[ii]); +#endif } } } @@ -130981,11 +135563,11 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ /* ** Return the N-dimensional volumn of the cell stored in *p. */ -static float cellArea(Rtree *pRtree, RtreeCell *p){ - float area = 1.0; +static RtreeDValue cellArea(Rtree *pRtree, RtreeCell *p){ + RtreeDValue area = (RtreeDValue)1; int ii; for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - area = (float)(area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); + area = (area * (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii]))); } return area; } @@ -130994,11 +135576,11 @@ static float cellArea(Rtree *pRtree, RtreeCell *p){ ** Return the margin length of cell p. The margin length is the sum ** of the objects size in each dimension. */ -static float cellMargin(Rtree *pRtree, RtreeCell *p){ - float margin = 0.0; +static RtreeDValue cellMargin(Rtree *pRtree, RtreeCell *p){ + RtreeDValue margin = (RtreeDValue)0; int ii; for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - margin += (float)(DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); + margin += (DCOORD(p->aCoord[ii+1]) - DCOORD(p->aCoord[ii])); } return margin; } @@ -131043,8 +135625,8 @@ static int cellContains(Rtree *pRtree, RtreeCell *p1, RtreeCell *p2){ /* ** Return the amount cell p would grow by if it were unioned with pCell. */ -static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ - float area; +static RtreeDValue cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ + RtreeDValue area; RtreeCell cell; memcpy(&cell, p, sizeof(RtreeCell)); area = cellArea(pRtree, &cell); @@ -131053,7 +135635,7 @@ static float cellGrowth(Rtree *pRtree, RtreeCell *p, RtreeCell *pCell){ } #if VARIANT_RSTARTREE_CHOOSESUBTREE || VARIANT_RSTARTREE_SPLIT -static float cellOverlap( +static RtreeDValue cellOverlap( Rtree *pRtree, RtreeCell *p, RtreeCell *aCell, @@ -131061,7 +135643,7 @@ static float cellOverlap( int iExclude ){ int ii; - float overlap = 0.0; + RtreeDValue overlap = 0.0; for(ii=0; iinDim*2); jj+=2){ - double x1; - double x2; + RtreeDValue x1, x2; x1 = MAX(DCOORD(p->aCoord[jj]), DCOORD(aCell[ii].aCoord[jj])); x2 = MIN(DCOORD(p->aCoord[jj+1]), DCOORD(aCell[ii].aCoord[jj+1])); @@ -131083,7 +135664,7 @@ static float cellOverlap( o = 0.0; break; }else{ - o = o * (float)(x2-x1); + o = o * (x2-x1); } } overlap += o; @@ -131094,7 +135675,7 @@ static float cellOverlap( #endif #if VARIANT_RSTARTREE_CHOOSESUBTREE -static float cellOverlapEnlargement( +static RtreeDValue cellOverlapEnlargement( Rtree *pRtree, RtreeCell *p, RtreeCell *pInsert, @@ -131102,12 +135683,11 @@ static float cellOverlapEnlargement( int nCell, int iExclude ){ - double before; - double after; + RtreeDValue before, after; before = cellOverlap(pRtree, p, aCell, nCell, iExclude); cellUnion(pRtree, p, pInsert); after = cellOverlap(pRtree, p, aCell, nCell, iExclude); - return (float)(after-before); + return (after-before); } #endif @@ -131131,11 +135711,11 @@ static int ChooseLeaf( int iCell; sqlite3_int64 iBest = 0; - float fMinGrowth = 0.0; - float fMinArea = 0.0; + RtreeDValue fMinGrowth = 0.0; + RtreeDValue fMinArea = 0.0; #if VARIANT_RSTARTREE_CHOOSESUBTREE - float fMinOverlap = 0.0; - float overlap; + RtreeDValue fMinOverlap = 0.0; + RtreeDValue overlap; #endif int nCell = NCELL(pNode); @@ -131166,8 +135746,8 @@ static int ChooseLeaf( */ for(iCell=0; iCellnDim; i++){ - float x1 = DCOORD(aCell[0].aCoord[i*2]); - float x2 = DCOORD(aCell[0].aCoord[i*2+1]); - float x3 = x1; - float x4 = x2; + RtreeDValue x1 = DCOORD(aCell[0].aCoord[i*2]); + RtreeDValue x2 = DCOORD(aCell[0].aCoord[i*2+1]); + RtreeDValue x3 = x1; + RtreeDValue x4 = x2; int jj; int iCellLeft = 0; int iCellRight = 0; for(jj=1; jjx4 ) x4 = right; @@ -131328,7 +135908,7 @@ static void LinearPickSeeds( } if( x4!=x1 ){ - float normalwidth = (x3 - x2) / (x4 - x1); + RtreeDValue normalwidth = (x3 - x2) / (x4 - x1); if( normalwidth>maxNormalInnerWidth ){ iLeftSeed = iCellLeft; iRightSeed = iCellRight; @@ -131357,13 +135937,13 @@ static RtreeCell *QuadraticPickNext( #define FABS(a) ((a)<0.0?-1.0*(a):(a)) int iSelect = -1; - float fDiff; + RtreeDValue fDiff; int ii; for(ii=0; iifDiff ){ fDiff = diff; iSelect = ii; @@ -131390,13 +135970,13 @@ static void QuadraticPickSeeds( int iLeftSeed = 0; int iRightSeed = 1; - float fWaste = 0.0; + RtreeDValue fWaste = 0.0; for(ii=0; iifWaste ){ iLeftSeed = ii; @@ -131431,7 +136011,7 @@ static void QuadraticPickSeeds( static void SortByDistance( int *aIdx, int nIdx, - float *aDistance, + RtreeDValue *aDistance, int *aSpare ){ if( nIdx>1 ){ @@ -131457,8 +136037,8 @@ static void SortByDistance( aIdx[iLeft+iRight] = aLeft[iLeft]; iLeft++; }else{ - float fLeft = aDistance[aLeft[iLeft]]; - float fRight = aDistance[aRight[iRight]]; + RtreeDValue fLeft = aDistance[aLeft[iLeft]]; + RtreeDValue fRight = aDistance[aRight[iRight]]; if( fLeftnDim+1)*(sizeof(int*)+nCell*sizeof(int)); @@ -131590,9 +136170,9 @@ static int splitNodeStartree( } for(ii=0; iinDim; ii++){ - float margin = 0.0; - float fBestOverlap = 0.0; - float fBestArea = 0.0; + RtreeDValue margin = 0.0; + RtreeDValue fBestOverlap = 0.0; + RtreeDValue fBestArea = 0.0; int iBestLeft = 0; int nLeft; @@ -131604,8 +136184,8 @@ static int splitNodeStartree( RtreeCell left; RtreeCell right; int kk; - float overlap; - float area; + RtreeDValue overlap; + RtreeDValue area; memcpy(&left, &aCell[aaSorted[ii][0]], sizeof(RtreeCell)); memcpy(&right, &aCell[aaSorted[ii][nCell-1]], sizeof(RtreeCell)); @@ -131688,7 +136268,7 @@ static int splitNodeGuttman( for(i=nCell-2; i>0; i--){ RtreeCell *pNext; pNext = PickNext(pRtree, aCell, nCell, pBboxLeft, pBboxRight, aiUsed); - float diff = + RtreeDValue diff = cellGrowth(pRtree, pBboxLeft, pNext) - cellGrowth(pRtree, pBboxRight, pNext) ; @@ -132021,32 +136601,34 @@ static int Reinsert( int *aOrder; int *aSpare; RtreeCell *aCell; - float *aDistance; + RtreeDValue *aDistance; int nCell; - float aCenterCoord[RTREE_MAX_DIMENSIONS]; + RtreeDValue aCenterCoord[RTREE_MAX_DIMENSIONS]; int iDim; int ii; int rc = SQLITE_OK; + int n; - memset(aCenterCoord, 0, sizeof(float)*RTREE_MAX_DIMENSIONS); + memset(aCenterCoord, 0, sizeof(RtreeDValue)*RTREE_MAX_DIMENSIONS); nCell = NCELL(pNode)+1; + n = (nCell+1)&(~1); /* Allocate the buffers used by this operation. The allocation is ** relinquished before this function returns. */ - aCell = (RtreeCell *)sqlite3_malloc(nCell * ( - sizeof(RtreeCell) + /* aCell array */ - sizeof(int) + /* aOrder array */ - sizeof(int) + /* aSpare array */ - sizeof(float) /* aDistance array */ + aCell = (RtreeCell *)sqlite3_malloc(n * ( + sizeof(RtreeCell) + /* aCell array */ + sizeof(int) + /* aOrder array */ + sizeof(int) + /* aSpare array */ + sizeof(RtreeDValue) /* aDistance array */ )); if( !aCell ){ return SQLITE_NOMEM; } - aOrder = (int *)&aCell[nCell]; - aSpare = (int *)&aOrder[nCell]; - aDistance = (float *)&aSpare[nCell]; + aOrder = (int *)&aCell[n]; + aSpare = (int *)&aOrder[n]; + aDistance = (RtreeDValue *)&aSpare[n]; for(ii=0; iinDim; iDim++){ - aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2]); - aCenterCoord[iDim] += (float)DCOORD(aCell[ii].aCoord[iDim*2+1]); + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]); + aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]); } } for(iDim=0; iDimnDim; iDim++){ - aCenterCoord[iDim] = (float)(aCenterCoord[iDim]/((float)nCell*2.0)); + aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2)); } for(ii=0; iinDim; iDim++){ - float coord = (float)(DCOORD(aCell[ii].aCoord[iDim*2+1]) - - DCOORD(aCell[ii].aCoord[iDim*2])); + RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) - + DCOORD(aCell[ii].aCoord[iDim*2])); aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]); } } @@ -132277,6 +136859,36 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ return rc; } +/* +** Rounding constants for float->double conversion. +*/ +#define RNDTOWARDS (1.0 - 1.0/8388608.0) /* Round towards zero */ +#define RNDAWAY (1.0 + 1.0/8388608.0) /* Round away from zero */ + +#if !defined(SQLITE_RTREE_INT_ONLY) +/* +** Convert an sqlite3_value into an RtreeValue (presumably a float) +** while taking care to round toward negative or positive, respectively. +*/ +static RtreeValue rtreeValueDown(sqlite3_value *v){ + double d = sqlite3_value_double(v); + float f = (float)d; + if( f>d ){ + f = (float)(d*(d<0 ? RNDAWAY : RNDTOWARDS)); + } + return f; +} +static RtreeValue rtreeValueUp(sqlite3_value *v){ + double d = sqlite3_value_double(v); + float f = (float)d; + if( fnDim*2 + 3) ); +#ifndef SQLITE_RTREE_INT_ONLY if( pRtree->eCoordType==RTREE_COORD_REAL32 ){ for(ii=0; ii<(pRtree->nDim*2); ii+=2){ - cell.aCoord[ii].f = (float)sqlite3_value_double(azData[ii+3]); - cell.aCoord[ii+1].f = (float)sqlite3_value_double(azData[ii+4]); + cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]); + cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]); if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){ rc = SQLITE_CONSTRAINT; goto constraint; } } - }else{ + }else +#endif + { for(ii=0; ii<(pRtree->nDim*2); ii+=2){ cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]); cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]); @@ -132619,8 +137234,8 @@ static int rtreeInit( sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); /* Allocate the sqlite3_vtab structure */ - nDb = strlen(argv[1]); - nName = strlen(argv[2]); + nDb = (int)strlen(argv[1]); + nName = (int)strlen(argv[2]); pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); if( !pRtree ){ return SQLITE_NOMEM; @@ -132715,10 +137330,16 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){ nodeGetCell(&tree, &node, ii, &cell); sqlite3_snprintf(512-nCell,&zCell[nCell],"%lld", cell.iRowid); - nCell = strlen(zCell); + nCell = (int)strlen(zCell); for(jj=0; jjpContext = pGeomCtx->pContext; pBlob->nParam = nArg; for(i=0; iaParam[i] = sqlite3_value_int64(aArg[i]); +#else pBlob->aParam[i] = sqlite3_value_double(aArg[i]); +#endif } sqlite3_result_blob(ctx, pBlob, nBlob, doSqlite3Free); } @@ -132816,7 +137445,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry *, int, double *, int *), + int (*xGeom)(sqlite3_rtree_geometry *, int, RtreeDValue *, int *), void *pContext ){ RtreeGeomCallback *pGeomCtx; /* Context object for new user-function */ @@ -133461,7 +138090,10 @@ static int icuOpen( *ppCursor = 0; - if( nInput<0 ){ + if( zInput==0 ){ + nInput = 0; + zInput = ""; + }else if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; diff --git a/Data/SQLite/src/sqlite3.h b/Data/SQLite/src/sqlite3.h index fc9cd076a..0a1cf9db7 100644 --- a/Data/SQLite/src/sqlite3.h +++ b/Data/SQLite/src/sqlite3.h @@ -107,9 +107,9 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.7.10" -#define SQLITE_VERSION_NUMBER 3007010 -#define SQLITE_SOURCE_ID "2012-01-16 13:28:40 ebd01a8deffb5024a5d7494eef800d2366d97204" +#define SQLITE_VERSION "3.7.13" +#define SQLITE_VERSION_NUMBER 3007013 +#define SQLITE_SOURCE_ID "2012-06-11 02:05:22 f5b5a13f7394dc143aa136f1d4faba6839eaa6dc" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -458,9 +458,11 @@ SQLITE_API int sqlite3_exec( #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) +#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) +#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8)) /* ** CAPI3REF: Flags For File Open Operations @@ -476,6 +478,7 @@ SQLITE_API int sqlite3_exec( #define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */ #define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */ #define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */ +#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */ #define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */ #define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */ #define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */ @@ -716,7 +719,8 @@ struct sqlite3_io_methods { ** into an integer that the pArg argument points to. This capability ** is used during testing and only needs to be supported when SQLITE_TEST ** is defined. -** +**
      +**
    • [[SQLITE_FCNTL_SIZE_HINT]] ** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS ** layer a hint of how large the database file will grow to be during the ** current transaction. This hint is not guaranteed to be accurate but it @@ -724,6 +728,7 @@ struct sqlite3_io_methods { ** file space based on this hint in order to help writes to the database ** file run faster. ** +**
    • [[SQLITE_FCNTL_CHUNK_SIZE]] ** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS ** extends and truncates the database file in chunks of a size specified ** by the user. The fourth argument to [sqlite3_file_control()] should @@ -732,11 +737,13 @@ struct sqlite3_io_methods { ** chunks (say 1MB at a time), may reduce file-system fragmentation and ** improve performance on some systems. ** +**
    • [[SQLITE_FCNTL_FILE_POINTER]] ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer ** to the [sqlite3_file] object associated with a particular database ** connection. See the [sqlite3_file_control()] documentation for ** additional information. ** +**
    • [[SQLITE_FCNTL_SYNC_OMITTED]] ** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by ** SQLite and sent to all VFSes in place of a call to the xSync method ** when the database connection has [PRAGMA synchronous] set to OFF.)^ @@ -747,6 +754,7 @@ struct sqlite3_io_methods { ** opcode as doing so may disrupt the operation of the specialized VFSes ** that do require it. ** +**
    • [[SQLITE_FCNTL_WIN32_AV_RETRY]] ** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic ** retry counts and intervals for certain disk I/O operations for the ** windows [VFS] in order to provide robustness in the presence of @@ -763,8 +771,9 @@ struct sqlite3_io_methods { ** into the array entry, allowing the current retry settings to be ** interrogated. The zDbName parameter is ignored. ** +**
    • [[SQLITE_FCNTL_PERSIST_WAL]] ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the -** persistent [WAL | Write AHead Log] setting. By default, the auxiliary +** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary ** write ahead log and shared memory files used for transaction control ** are automatically deleted when the latest connection to the database ** closes. Setting persistent WAL mode causes those files to persist after @@ -777,6 +786,7 @@ struct sqlite3_io_methods { ** WAL mode. If the integer is -1, then it is overwritten with the current ** WAL persistence setting. ** +**
    • [[SQLITE_FCNTL_POWERSAFE_OVERWRITE]] ** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the ** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting ** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the @@ -786,11 +796,13 @@ struct sqlite3_io_methods { ** mode. If the integer is -1, then it is overwritten with the current ** zero-damage mode setting. ** +**
    • [[SQLITE_FCNTL_OVERWRITE]] ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening ** a write transaction to indicate that, unless it is rolled back for some ** reason, the entire database file will be overwritten by the current ** transaction. This is used by VACUUM operations. ** +**
    • [[SQLITE_FCNTL_VFSNAME]] ** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of ** all [VFSes] in the VFS stack. The names are of all VFS shims and the ** final bottom-level VFS are written into memory obtained from @@ -801,6 +813,30 @@ struct sqlite3_io_methods { ** do anything. Callers should initialize the char* variable to a NULL ** pointer in case this file-control is not implemented. This file-control ** is intended for diagnostic use only. +** +**
    • [[SQLITE_FCNTL_PRAGMA]] +** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA] +** file control is sent to the open [sqlite3_file] object corresponding +** to the database file to which the pragma statement refers. ^The argument +** to the [SQLITE_FCNTL_PRAGMA] file control is an array of +** pointers to strings (char**) in which the second element of the array +** is the name of the pragma and the third element is the argument to the +** pragma or NULL if the pragma has no argument. ^The handler for an +** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element +** of the char** argument point to a string obtained from [sqlite3_mprintf()] +** or the equivalent and that string will become the result of the pragma or +** the error message if the pragma fails. ^If the +** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal +** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA] +** file control returns [SQLITE_OK], then the parser assumes that the +** VFS has handled the PRAGMA itself and the parser generates a no-op +** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns +** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means +** that the VFS encountered an error while handling the [PRAGMA] and the +** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] +** file control occurs at the beginning of pragma statement analysis and so +** it is able to override built-in [PRAGMA] statements. +**
    */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 @@ -815,6 +851,7 @@ struct sqlite3_io_methods { #define SQLITE_FCNTL_OVERWRITE 11 #define SQLITE_FCNTL_VFSNAME 12 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 +#define SQLITE_FCNTL_PRAGMA 14 /* ** CAPI3REF: Mutex Handle @@ -1512,7 +1549,7 @@ struct sqlite3_mem_methods { ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] -**
    SQLITE_CONFIG_PCACHE and SQLITE_CONFNIG_GETPCACHE +**
    SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE **
    These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** @@ -2133,12 +2170,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list); ** implementation of these routines to be omitted. That capability ** is no longer provided. Only built-in memory allocators can be used. ** -** The Windows OS interface layer calls +** Prior to SQLite version 3.7.10, the Windows OS interface layer called ** the system malloc() and free() directly when converting ** filenames between the UTF-8 encoding used by SQLite ** and whatever filename encoding is used by the particular Windows -** installation. Memory allocation errors are detected, but -** they are reported back as [SQLITE_CANTOPEN] or +** installation. Memory allocation errors were detected, but +** they were reported back as [SQLITE_CANTOPEN] or ** [SQLITE_IOERR] rather than [SQLITE_NOMEM]. ** ** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()] @@ -2539,18 +2576,20 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); ** present, then the VFS specified by the option takes precedence over ** the value passed as the fourth parameter to sqlite3_open_v2(). ** -**
  • mode: ^(The mode parameter may be set to either "ro", "rw" or -** "rwc". Attempting to set it to any other value is an error)^. +**
  • mode: ^(The mode parameter may be set to either "ro", "rw", +** "rwc", or "memory". Attempting to set it to any other value is +** an error)^. ** ^If "ro" is specified, then the database is opened for read-only ** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the ** third argument to sqlite3_prepare_v2(). ^If the mode option is set to ** "rw", then the database is opened for read-write (but not create) ** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had ** been set. ^Value "rwc" is equivalent to setting both -** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If sqlite3_open_v2() is -** used, it is an error to specify a value for the mode parameter that is -** less restrictive than that specified by the flags passed as the third -** parameter. +** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is +** set to "memory" then a pure [in-memory database] that never reads +** or writes from disk is used. ^It is an error to specify a value for +** the mode parameter that is less restrictive than that specified by +** the flags passed in the third parameter to sqlite3_open_v2(). ** **
  • cache: ^The cache parameter may be set to either "shared" or ** "private". ^Setting it to "shared" is equivalent to setting the @@ -2644,9 +2683,14 @@ SQLITE_API int sqlite3_open_v2( ** ** The sqlite3_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 sqlite3_uri_boolean(F,P,B) returns (B!=0). +** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the +** value of query parameter P is one of "yes", "true", or "on" in any +** case or if the value begins with a non-zero number. The +** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of +** query parameter P is one of "no", "false", or "off" in any case or +** if the value begins with a numeric zero. If P is not a query +** parameter on F or if the value of P is does not match any of the +** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0). ** ** The sqlite3_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 @@ -4408,6 +4452,43 @@ SQLITE_API int sqlite3_sleep(int); */ SQLITE_API SQLITE_EXTERN char *sqlite3_temp_directory; +/* +** CAPI3REF: Name Of The Folder Holding Database Files +** +** ^(If this global variable is made to point to a string which is +** the name of a folder (a.k.a. directory), then all database files +** specified with a relative pathname and created or accessed by +** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed +** to be relative to that directory.)^ ^If this variable is a NULL +** pointer, then SQLite assumes that all database files specified +** with a relative pathname are relative to the current directory +** for the process. Only the windows VFS makes use of this global +** variable; it is ignored by the unix VFS. +** +** Changing the value of this variable while a database connection is +** open can result in a corrupt database. +** +** It is not safe to read or modify this variable in more than one +** thread at a time. It is not safe to read or modify this variable +** if a [database connection] is being used at the same time in a separate +** thread. +** It is intended that this variable be set once +** as part of process initialization and before any SQLite interface +** routines have been called and that this variable remain unchanged +** thereafter. +** +** ^The [data_store_directory pragma] may modify this variable and cause +** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore, +** the [data_store_directory pragma] always assumes that any string +** that this variable points to is held in memory obtained from +** [sqlite3_malloc] and the pragma may attempt to free that memory +** using [sqlite3_free]. +** Hence, if this variable is modified directly, either it should be +** made NULL or made to point to memory obtained from [sqlite3_malloc] +** or else the use of the [data_store_directory pragma] should be avoided. +*/ +SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory; + /* ** CAPI3REF: Test For Auto-Commit Mode ** KEYWORDS: {autocommit mode} @@ -4459,6 +4540,15 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*); */ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName); +/* +** CAPI3REF: Determine if a database is read-only +** +** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N +** of connection D is read-only, 0 if it is read/write, or -1 if N is not +** the name of a database on connection D. +*/ +SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName); + /* ** CAPI3REF: Find the next prepared statement ** @@ -4577,7 +4667,6 @@ SQLITE_API void *sqlite3_update_hook( /* ** CAPI3REF: Enable Or Disable Shared Pager Cache -** KEYWORDS: {shared cache} ** ** ^(This routine enables or disables the sharing of the database cache ** and schema data structures between [database connection | connections] @@ -5957,6 +6046,17 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r ** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS ** is always 0. **
  • +** +** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(
    SQLITE_DBSTATUS_CACHE_WRITE
    +**
    This parameter returns the number of dirty cache entries that have +** been written to disk. Specifically, the number of pages written to the +** wal file in wal mode databases, or the number of pages written to the +** database file in rollback mode databases. Any pages written as part of +** transaction rollback or database recovery operations are not included. +** If an IO or other error occurs while writing a page to disk, the effect +** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The +** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. +**
    ** */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 @@ -5968,7 +6068,8 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r #define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6 #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 -#define SQLITE_DBSTATUS_MAX 8 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_CACHE_WRITE 9 +#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ /* @@ -6584,11 +6685,12 @@ SQLITE_API int sqlite3_unlock_notify( /* ** CAPI3REF: String Comparison ** -** ^The [sqlite3_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. +** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow 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. */ +SQLITE_API int sqlite3_stricmp(const char *, const char *); SQLITE_API int sqlite3_strnicmp(const char *, const char *, int); /* @@ -6923,7 +7025,11 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry; SQLITE_API int sqlite3_rtree_geometry_callback( sqlite3 *db, const char *zGeom, - int (*xGeom)(sqlite3_rtree_geometry *, int nCoord, double *aCoord, int *pRes), +#ifdef SQLITE_RTREE_INT_ONLY + int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes), +#else + int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes), +#endif void *pContext );