DELETED COPYRIGHT.md
Index: COPYRIGHT.md
==================================================================
--- COPYRIGHT.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright © 2008 D. Richard Hipp
-
-This program is free software. As far as the author is
-concerned, you can redistribute it and/or modify the code
-as you see fit. No attribution is required. Use whichever
-of the following license terms best applies to your situation.
-
- 1. GNU General Public License
- 2. BSD License
- 3. MIT License
- 4. CC0 License
-
-This program is distributed in the hope that it will be useful,
-but without any warranty; without even the implied warranty of
-merchantability or fitness for a particular purpose.
Index: src/sqlite3.c
==================================================================
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.48.0. By combining all the individual C code files into this
+** version 3.47.0. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
** of 5% or more are commonly seen when SQLite is compiled as a single
** translation unit.
@@ -16,15 +16,12 @@
** if you want a wrapper to interface SQLite with your choice of programming
** language. The code for the "sqlite3" command-line shell is also in a
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
-** 2b17bc49655c577029919c2d409de994b0d2 with changes in files:
-**
-**
+** a31a94644113c226a06316a3f95fb38b6058.
*/
-#ifndef SQLITE_AMALGAMATION
#define SQLITE_CORE 1
#define SQLITE_AMALGAMATION 1
#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif
@@ -463,13 +460,13 @@
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.48.0"
-#define SQLITE_VERSION_NUMBER 3048000
-#define SQLITE_SOURCE_ID "2024-12-30 21:23:53 2b17bc49655c577029919c2d409de994b0d252f8efb5da1ba0913f2c96bee552"
+#define SQLITE_VERSION "3.47.0"
+#define SQLITE_VERSION_NUMBER 3047000
+#define SQLITE_SOURCE_ID "2024-10-18 12:31:21 a31a94644113c226a06316a3f95fb38b605821f1c123e2cda06ba90bfcacf59f"
/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
@@ -969,17 +966,10 @@
**
** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying
** filesystem supports doing multiple write operations atomically when those
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
-**
-** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read
-** from the database file in amounts that are not a multiple of the
-** page size and that do not begin at a page boundary. Without this
-** property, SQLite is careful to only do full-page reads and write
-** on aligned pages, with the one exception that it will do a sub-page
-** read of the first page to access the database header.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
#define SQLITE_IOCAP_ATOMIC1K 0x00000004
#define SQLITE_IOCAP_ATOMIC2K 0x00000008
@@ -992,11 +982,10 @@
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
-#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000
/*
** CAPI3REF: File Locking Levels
**
** SQLite uses one of these integer values as the second
@@ -1139,11 +1128,10 @@
**
[SQLITE_IOCAP_SEQUENTIAL]
** [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
** [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** [SQLITE_IOCAP_IMMUTABLE]
** [SQLITE_IOCAP_BATCH_ATOMIC]
-** [SQLITE_IOCAP_SUBPAGE_READ]
**
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
** mean that writes of blocks that are nnn bytes in size and
@@ -1417,15 +1405,10 @@
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
-** [[SQLITE_FCNTL_NULL_IO]]
-** The [SQLITE_FCNTL_NULL_IO] opcode sets the low-level file descriptor
-** or file handle for the [sqlite3_file] object such that it will no longer
-** read or write to the database file.
-**
** [[SQLITE_FCNTL_WAL_BLOCK]]
** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
** be advantageous to block on the next WAL lock if the lock is not immediately
** available. The WAL subsystem issues this signal during rare
** circumstances in order to fix a problem with priority inversion.
@@ -1575,11 +1558,10 @@
#define SQLITE_FCNTL_RESERVE_BYTES 38
#define SQLITE_FCNTL_CKPT_START 39
#define SQLITE_FCNTL_EXTERNAL_READER 40
#define SQLITE_FCNTL_CKSM_FILE 41
#define SQLITE_FCNTL_RESET_CACHE 42
-#define SQLITE_FCNTL_NULL_IO 43
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -2954,18 +2936,14 @@
**
** ^These functions return the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter.
** The two functions are identical except for the type of the return value
-** and that if the number of rows modified by the most recent INSERT, UPDATE,
+** and that if the number of rows modified by the most recent INSERT, UPDATE
** or DELETE is greater than the maximum value supported by type "int", then
** the return value of sqlite3_changes() is undefined. ^Executing any other
** type of SQL statement does not modify the value returned by these functions.
-** For the purposes of this interface, a CREATE TABLE AS SELECT statement
-** does not count as an INSERT, UPDATE or DELETE statement and hence the rows
-** added to the new table by the CREATE TABLE AS SELECT statement are not
-** counted.
**
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
** [foreign key actions] or [REPLACE] constraint resolution are not counted.
**
@@ -4521,26 +4499,15 @@
**
** [[SQLITE_PREPARE_NO_VTAB]] SQLITE_PREPARE_NO_VTAB
** The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
** to return an error (error code SQLITE_ERROR) if the statement uses
** any virtual tables.
-**
-** [[SQLITE_PREPARE_DONT_LOG]] SQLITE_PREPARE_DONT_LOG
-** The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
-** errors from being sent to the error log defined by
-** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
-** compiles to see if some SQL syntax is well-formed, without generating
-** messages on the global error log when it is not. If the test compile
-** fails, the sqlite3_prepare_v3() call returns the same error indications
-** with or without this flag; it just omits the call to [sqlite3_log()] that
-** logs the error.
**
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
#define SQLITE_PREPARE_NORMALIZE 0x02
#define SQLITE_PREPARE_NO_VTAB 0x04
-#define SQLITE_PREPARE_DONT_LOG 0x10
/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
** METHOD: sqlite3
@@ -11227,11 +11194,11 @@
#endif
#if 0
} /* End of the 'extern "C"' block */
#endif
-/* #endif for SQLITE3_H will be added by mksqlite3.tcl */
+#endif /* SQLITE3_H */
/******** Begin file sqlite3rtree.h *********/
/*
** 2010 August 30
**
@@ -13478,33 +13445,18 @@
** This is used to access token iToken of phrase hit iIdx within the
** current row. If iIdx is less than zero or greater than or equal to the
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
** output variable (*ppToken) is set to point to a buffer containing the
** matching document token, and (*pnToken) to the size of that buffer in
-** bytes.
+** bytes. This API is not available if the specified token matches a
+** prefix query term. In that case both output variables are always set
+** to 0.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
-** This API may be slow in some cases if the token identified by parameters
-** iIdx and iToken matched a prefix token in the query. In most cases, the
-** first call to this API for each prefix token in the query is forced
-** to scan the portion of the full-text index that matches the prefix
-** token to collect the extra data required by this API. If the prefix
-** token matches a large number of token instances in the document set,
-** this may be a performance problem.
-**
-** If the user knows in advance that a query may use this API for a
-** prefix token, FTS5 may be configured to collect all required data as part
-** of the initial querying of the full-text index, avoiding the second scan
-** entirely. This also causes prefix queries that do not use this API to
-** run more slowly and use more memory. FTS5 may be configured in this way
-** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
-** option, or on a per-query basis using the
-** [fts5_insttoken | fts5_insttoken()] user function.
-**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
**
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
** If parameter iCol is less than zero, or greater than or equal to the
@@ -13934,11 +13886,10 @@
#endif
#endif /* _FTS5_H */
/******** End of fts5.h *********/
-#endif /* SQLITE3_H */
/************** End of sqlite3.h *********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
/*
@@ -13980,11 +13931,10 @@
** to count the size: 2^31-1 or 2147483647.
*/
#ifndef SQLITE_MAX_LENGTH
# define SQLITE_MAX_LENGTH 1000000000
#endif
-#define SQLITE_MIN_LENGTH 30 /* Minimum value for the length limit */
/*
** This is the maximum number of
**
** * Columns in a table
@@ -14046,17 +13996,13 @@
# define SQLITE_MAX_VDBE_OP 250000000
#endif
/*
** The maximum number of arguments to an SQL function.
-**
-** This value has a hard upper limit of 32767 due to storage
-** constraints (it needs to fit inside a i16). We keep it
-** lower than that to prevent abuse.
*/
#ifndef SQLITE_MAX_FUNCTION_ARG
-# define SQLITE_MAX_FUNCTION_ARG 1000
+# define SQLITE_MAX_FUNCTION_ARG 127
#endif
/*
** The suggested maximum number of in-memory pages to use for
** the main database table and for temporary tables.
@@ -16054,26 +16000,10 @@
#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
-#define isWalMode(x) ((x)==PAGER_JOURNALMODE_WAL)
-
-/*
-** The argument to this macro is a file descriptor (type sqlite3_file*).
-** Return 0 if it is not open, or non-zero (but not 1) if it is.
-**
-** This is so that expressions can be written as:
-**
-** if( isOpen(pPager->jfd) ){ ...
-**
-** instead of
-**
-** if( pPager->jfd->pMethods ){ ...
-*/
-#define isOpen(pFd) ((pFd)->pMethods!=0)
-
/*
** Flags that make up the mask passed to sqlite3PagerGet().
*/
#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */
#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */
@@ -17095,11 +17025,11 @@
/*
** Additional non-public SQLITE_PREPARE_* flags
*/
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
-#define SQLITE_PREPARE_MASK 0x1f /* Mask of public flags */
+#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
/*
** Prototypes for the VDBE interface. See comments on the implementation
** for a description of what each of these routines does.
*/
@@ -17810,15 +17740,51 @@
struct FuncDefHash {
FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */
};
#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
+#if defined(SQLITE_USER_AUTHENTICATION)
+# warning "The SQLITE_USER_AUTHENTICATION extension is deprecated. \
+ See ext/userauth/user-auth.txt for details."
+#endif
+#ifdef SQLITE_USER_AUTHENTICATION
+/*
+** Information held in the "sqlite3" database connection object and used
+** to manage user authentication.
+*/
+typedef struct sqlite3_userauth sqlite3_userauth;
+struct sqlite3_userauth {
+ u8 authLevel; /* Current authentication level */
+ int nAuthPW; /* Size of the zAuthPW in bytes */
+ char *zAuthPW; /* Password used to authenticate */
+ char *zAuthUser; /* User name used to authenticate */
+};
+
+/* Allowed values for sqlite3_userauth.authLevel */
+#define UAUTH_Unknown 0 /* Authentication not yet checked */
+#define UAUTH_Fail 1 /* User authentication failed */
+#define UAUTH_User 2 /* Authenticated as a normal user */
+#define UAUTH_Admin 3 /* Authenticated as an administrator */
+
+/* Functions used only by user authorization logic */
+SQLITE_PRIVATE int sqlite3UserAuthTable(const char*);
+SQLITE_PRIVATE int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
+SQLITE_PRIVATE void sqlite3UserAuthInit(sqlite3*);
+SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
+
+#endif /* SQLITE_USER_AUTHENTICATION */
+
/*
** typedef for the authorization callback function.
*/
-typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
- const char*);
+#ifdef SQLITE_USER_AUTHENTICATION
+ typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
+ const char*, const char*);
+#else
+ typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
+ const char*);
+#endif
#ifndef SQLITE_OMIT_DEPRECATED
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
** in the style of sqlite3_trace()
*/
@@ -17975,10 +17941,13 @@
sqlite3 *pUnlockConnection; /* Connection to watch for unlock */
void *pUnlockArg; /* Argument to xUnlockNotify */
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
#endif
+#ifdef SQLITE_USER_AUTHENTICATION
+ sqlite3_userauth auth; /* User authentication information */
+#endif
};
/*
** A macro to discover the encoding of a database.
*/
@@ -18133,11 +18102,11 @@
**
** The u.pHash field is used by the global built-ins. The u.pDestructor
** field is used by per-connection app-def functions.
*/
struct FuncDef {
- i16 nArg; /* Number of arguments. -1 means unlimited */
+ i8 nArg; /* Number of arguments. -1 means unlimited */
u32 funcFlags; /* Some combination of SQLITE_FUNC_* */
void *pUserData; /* User data parameter */
FuncDef *pNext; /* Next function with same name */
void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */
void (*xFinalize)(sqlite3_context*); /* Agg finalizer */
@@ -19829,11 +19798,11 @@
**
** SRT_Set The result must be a single column. Store each
** row of result as the key in table pDest->iSDParm.
** Apply the affinity pDest->affSdst before storing
** results. if pDest->iSDParm2 is positive, then it is
-** a register holding a Bloom filter for the IN operator
+** a regsiter holding a Bloom filter for the IN operator
** that should be populated in addition to the
** pDest->iSDParm table. This SRT is used to
** implement "IN (SELECT ...)".
**
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
@@ -22881,10 +22850,13 @@
"UNLINK_AFTER_CLOSE",
#endif
#ifdef SQLITE_UNTESTABLE
"UNTESTABLE",
#endif
+#ifdef SQLITE_USER_AUTHENTICATION
+ "USER_AUTHENTICATION",
+#endif
#ifdef SQLITE_USE_ALLOCA
"USE_ALLOCA",
#endif
#ifdef SQLITE_USE_FCNTL_TRACE
"USE_FCNTL_TRACE",
@@ -23728,11 +23700,11 @@
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
u8 enc; /* Encoding to use for results */
u8 skipFlag; /* Skip accumulator loading if true */
- u16 argc; /* Number of arguments */
+ u8 argc; /* Number of arguments */
sqlite3_value *argv[1]; /* Argument set */
};
/* A bitfield type for use inside of structures. Always follow with :N where
** N is the number of bits.
@@ -23875,11 +23847,10 @@
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
int iNewReg; /* Register for new.* values */
int iBlobWrite; /* Value returned by preupdate_blobwrite() */
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
- Mem oldipk; /* Memory cell holding "old" IPK value */
Mem *aNew; /* Array of new.* values */
Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
sqlite3_value **apDflt; /* Array of default values, if required */
};
@@ -32325,11 +32296,10 @@
&& (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
){
pExpr = pExpr->pLeft;
}
if( pExpr==0 ) return;
- if( ExprHasProperty(pExpr, EP_FromDDL) ) return;
db->errByteOffset = pExpr->w.iOfst;
}
/*
** Enlarge the memory allocation on a StrAccum object so that it is
@@ -33055,11 +33025,11 @@
}
if( pItem->fg.isCte ){
sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
}
if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
- sqlite3_str_appendf(&x, " isOn");
+ sqlite3_str_appendf(&x, " ON");
}
if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
@@ -34139,14 +34109,10 @@
**
** This routines are given external linkage so that they will always be
** accessible to the debugging, and to avoid warnings about unused
** functions. But these routines only exist in debugging builds, so they
** do not contaminate the interface.
-**
-** See Also:
-**
-** sqlite3ShowWhereTerm() in where.c
*/
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
@@ -35719,12 +35685,12 @@
int esign = 1; /* sign of exponent */
int e = 0; /* exponent */
int eValid = 1; /* True exponent is either not used or is well-formed */
int nDigit = 0; /* Number of digits processed */
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
- u64 s2; /* round-tripped significand */
double rr[2];
+ u64 s2;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
*pResult = 0.0; /* Default return value, in case of an error */
if( length==0 ) return 0;
@@ -35823,36 +35789,25 @@
/* adjust exponent by d, and update sign */
e = (e*esign) + d;
/* Try to adjust the exponent to make it smaller */
- while( e>0 && s<((LARGEST_UINT64-0x7ff)/10) ){
+ while( e>0 && s<(LARGEST_UINT64/10) ){
s *= 10;
e--;
}
while( e<0 && (s%10)==0 ){
s /= 10;
e++;
}
rr[0] = (double)s;
- assert( sizeof(s2)==sizeof(rr[0]) );
-#ifdef SQLITE_DEBUG
- rr[1] = 18446744073709549568.0;
- memcpy(&s2, &rr[1], sizeof(s2));
- assert( s2==0x43efffffffffffffLL );
+ s2 = (u64)rr[0];
+#if defined(_MSC_VER) && _MSC_VER<1700
+ if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
#endif
- /* Largest double that can be safely converted to u64
- ** vvvvvvvvvvvvvvvvvvvvvv */
- if( rr[0]<=18446744073709549568.0 ){
- s2 = (u64)rr[0];
- rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
- }else{
- rr[1] = 0.0;
- }
- assert( rr[1]<=1.0e-10*rr[0] ); /* Equal only when rr[0]==0.0 */
-
+ rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
if( e>0 ){
while( e>=100 ){
e -= 100;
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
}
@@ -37038,10 +36993,108 @@
i += pIn[i+1];
}while( ih, F2FS_IOC_ABORT_VOLATILE_WRITE);
return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK;
}
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
- case SQLITE_FCNTL_NULL_IO: {
- osClose(pFile->h);
- pFile->h = -1;
- return SQLITE_OK;
- }
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
}
case SQLITE_FCNTL_LAST_ERRNO: {
@@ -42639,11 +42687,10 @@
/* Set the POWERSAFE_OVERWRITE flag if requested. */
if( pFd->ctrlFlags & UNIXFILE_PSOW ){
pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
}
- pFd->deviceCharacteristics |= SQLITE_IOCAP_SUBPAGE_READ;
pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
}
}
#else
@@ -50379,15 +50426,10 @@
OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
hOldFile, pFile->h));
return SQLITE_OK;
}
#endif
- case SQLITE_FCNTL_NULL_IO: {
- (void)osCloseHandle(pFile->h);
- pFile->h = NULL;
- return SQLITE_OK;
- }
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = 0;
int rc = winGetTempname(pFile->pVfs, &zTFile);
if( rc==SQLITE_OK ){
*(char**)pArg = zTFile;
@@ -50445,11 +50487,11 @@
/*
** Return a vector of device characteristics.
*/
static int winDeviceCharacteristics(sqlite3_file *id){
winFile *p = (winFile*)id;
- return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | SQLITE_IOCAP_SUBPAGE_READ |
+ return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
}
/*
** Windows will only let you create file view mappings
@@ -51833,11 +51875,11 @@
*/
char *zTmpname = 0; /* For temporary filename, if necessary. */
int rc = SQLITE_OK; /* Function Return Code */
#if !defined(NDEBUG) || SQLITE_OS_WINCE
- int eType = flags&0x0FFF00; /* Type of file to open */
+ int eType = flags&0xFFFFFF00; /* Type of file to open */
#endif
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
int isCreate = (flags & SQLITE_OPEN_CREATE);
@@ -58034,37 +58076,43 @@
# define USEFETCH(x) ((x)->bUseFetch)
#else
# define USEFETCH(x) 0
#endif
+/*
+** The argument to this macro is a file descriptor (type sqlite3_file*).
+** Return 0 if it is not open, or non-zero (but not 1) if it is.
+**
+** This is so that expressions can be written as:
+**
+** if( isOpen(pPager->jfd) ){ ...
+**
+** instead of
+**
+** if( pPager->jfd->pMethods ){ ...
+*/
+#define isOpen(pFd) ((pFd)->pMethods!=0)
+
#ifdef SQLITE_DIRECT_OVERFLOW_READ
/*
** Return true if page pgno can be read directly from the database file
** by the b-tree layer. This is the case if:
**
-** (1) the database file is open
-** (2) the VFS for the database is able to do unaligned sub-page reads
-** (3) there are no dirty pages in the cache, and
-** (4) the desired page is not currently in the wal file.
+** * the database file is open,
+** * there are no dirty pages in the cache, and
+** * the desired page is not currently in the wal file.
*/
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
- assert( pPager!=0 );
- assert( pPager->fd!=0 );
- if( pPager->fd->pMethods==0 ) return 0; /* Case (1) */
- if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0; /* Failed (3) */
+ if( pPager->fd->pMethods==0 ) return 0;
+ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
#ifndef SQLITE_OMIT_WAL
if( pPager->pWal ){
u32 iRead = 0;
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
- return iRead==0; /* Condition (4) */
+ return iRead==0;
}
#endif
- assert( pPager->fd->pMethods->xDeviceCharacteristics!=0 );
- if( (pPager->fd->pMethods->xDeviceCharacteristics(pPager->fd)
- & SQLITE_IOCAP_SUBPAGE_READ)==0 ){
- return 0; /* Case (2) */
- }
return 1;
}
#endif
#ifndef SQLITE_OMIT_WAL
@@ -59319,11 +59367,11 @@
rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
}
}
pPager->journalOff = 0;
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
- || (pPager->exclusiveMode && pPager->journalModeexclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
){
rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
pPager->journalOff = 0;
}else{
/* This branch may be executed with Pager.journalMode==MEMORY if
@@ -67477,11 +67525,11 @@
return SQLITE_IOERR_IN_PAGE;
}
/*
** Assert that the Wal.lockMask mask, which indicates the locks held
-** by the connection, is consistent with the Wal.readLock, Wal.writeLock
+** by the connenction, is consistent with the Wal.readLock, Wal.writeLock
** and Wal.ckptLock variables. To be used as:
**
** assert( walAssertLockmask(pWal) );
*/
static int walAssertLockmask(Wal *pWal){
@@ -68029,11 +68077,15 @@
** so it takes care to hold an exclusive lock on the corresponding
** WAL_READ_LOCK() while changing values.
*/
static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
volatile WalCkptInfo *pInfo; /* Checkpoint information in wal-index */
+ u32 mxReadMark; /* Largest aReadMark[] value */
+ int mxI; /* Index of largest aReadMark[] value */
+ int i; /* Loop counter */
int rc = SQLITE_OK; /* Return code */
+ u32 mxFrame; /* Wal frame to lock to */
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
int nBlockTmout = 0;
#endif
assert( pWal->readLock<0 ); /* Not currently locked */
@@ -68135,151 +68187,145 @@
assert( pWal->nWiData>0 );
assert( pWal->apWiData[0]!=0 );
pInfo = walCkptInfo(pWal);
SEH_INJECT_FAULT;
- {
- u32 mxReadMark; /* Largest aReadMark[] value */
- int mxI; /* Index of largest aReadMark[] value */
- int i; /* Loop counter */
- u32 mxFrame; /* Wal frame to lock to */
- if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
-#ifdef SQLITE_ENABLE_SNAPSHOT
- && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0)
-#endif
- ){
- /* The WAL has been completely backfilled (or it is empty).
- ** and can be safely ignored.
- */
- rc = walLockShared(pWal, WAL_READ_LOCK(0));
- walShmBarrier(pWal);
- if( rc==SQLITE_OK ){
- if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr,sizeof(WalIndexHdr)) ){
- /* It is not safe to allow the reader to continue here if frames
- ** may have been appended to the log before READ_LOCK(0) was obtained.
- ** When holding READ_LOCK(0), the reader ignores the entire log file,
- ** which implies that the database file contains a trustworthy
- ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
- ** happening, this is usually correct.
- **
- ** However, if frames have been appended to the log (or if the log
- ** is wrapped and written for that matter) before the READ_LOCK(0)
- ** is obtained, that is not necessarily true. A checkpointer may
- ** have started to backfill the appended frames but crashed before
- ** it finished. Leaving a corrupt image in the database file.
- */
- walUnlockShared(pWal, WAL_READ_LOCK(0));
- return WAL_RETRY;
- }
- pWal->readLock = 0;
- return SQLITE_OK;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
- }
- }
-
- /* If we get this far, it means that the reader will want to use
- ** the WAL to get at content from recent commits. The job now is
- ** to select one of the aReadMark[] entries that is closest to
- ** but not exceeding pWal->hdr.mxFrame and lock that entry.
- */
- mxReadMark = 0;
- mxI = 0;
- mxFrame = pWal->hdr.mxFrame;
-#ifdef SQLITE_ENABLE_SNAPSHOT
- if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame;
- }
-#endif
- for(i=1; iaReadMark+i); SEH_INJECT_FAULT;
- if( mxReadMark<=thisMark && thisMark<=mxFrame ){
- assert( thisMark!=READMARK_NOT_USED );
- mxReadMark = thisMark;
- mxI = i;
- }
- }
- if( (pWal->readOnly & WAL_SHM_RDONLY)==0
- && (mxReadMarkaReadMark+i,mxFrame);
- mxReadMark = mxFrame;
- mxI = i;
- walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
- break;
- }else if( rc!=SQLITE_BUSY ){
- return rc;
- }
- }
- }
- if( mxI==0 ){
- assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
- return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
- }
-
- (void)walEnableBlockingMs(pWal, nBlockTmout);
- rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
- walDisableBlocking(pWal);
- if( rc ){
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
- if( rc==SQLITE_BUSY_TIMEOUT ){
- *pCnt |= WAL_RETRY_BLOCKED_MASK;
- }
-#else
- assert( rc!=SQLITE_BUSY_TIMEOUT );
-#endif
- assert((rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT);
- return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
- }
- /* Now that the read-lock has been obtained, check that neither the
- ** value in the aReadMark[] array or the contents of the wal-index
- ** header have changed.
- **
- ** It is necessary to check that the wal-index header did not change
- ** between the time it was read and when the shared-lock was obtained
- ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
- ** that the log file may have been wrapped by a writer, or that frames
- ** that occur later in the log than pWal->hdr.mxFrame may have been
- ** copied into the database by a checkpointer. If either of these things
- ** happened, then reading the database with the current value of
- ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
- ** instead.
- **
- ** Before checking that the live wal-index header has not changed
- ** since it was read, set Wal.minFrame to the first frame in the wal
- ** file that has not yet been checkpointed. This client will not need
- ** to read any frames earlier than minFrame from the wal file - they
- ** can be safely read directly from the database file.
- **
- ** Because a ShmBarrier() call is made between taking the copy of
- ** nBackfill and checking that the wal-header in shared-memory still
- ** matches the one cached in pWal->hdr, it is guaranteed that the
- ** checkpointer that set nBackfill was not working with a wal-index
- ** header newer than that cached in pWal->hdr. If it were, that could
- ** cause a problem. The checkpointer could omit to checkpoint
- ** a version of page X that lies before pWal->minFrame (call that version
- ** A) on the basis that there is a newer version (version B) of the same
- ** page later in the wal file. But if version B happens to like past
- ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
- ** that it can read version A from the database file. However, since
- ** we can guarantee that the checkpointer that set nBackfill could not
- ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
- */
- pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT;
- walShmBarrier(pWal);
- if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
- || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
- ){
- walUnlockShared(pWal, WAL_READ_LOCK(mxI));
- return WAL_RETRY;
- }else{
- assert( mxReadMark<=pWal->hdr.mxFrame );
- pWal->readLock = (i16)mxI;
- }
+ if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
+#ifdef SQLITE_ENABLE_SNAPSHOT
+ && ((pWal->bGetSnapshot==0 && pWal->pSnapshot==0) || pWal->hdr.mxFrame==0)
+#endif
+ ){
+ /* The WAL has been completely backfilled (or it is empty).
+ ** and can be safely ignored.
+ */
+ rc = walLockShared(pWal, WAL_READ_LOCK(0));
+ walShmBarrier(pWal);
+ if( rc==SQLITE_OK ){
+ if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
+ /* It is not safe to allow the reader to continue here if frames
+ ** may have been appended to the log before READ_LOCK(0) was obtained.
+ ** When holding READ_LOCK(0), the reader ignores the entire log file,
+ ** which implies that the database file contains a trustworthy
+ ** snapshot. Since holding READ_LOCK(0) prevents a checkpoint from
+ ** happening, this is usually correct.
+ **
+ ** However, if frames have been appended to the log (or if the log
+ ** is wrapped and written for that matter) before the READ_LOCK(0)
+ ** is obtained, that is not necessarily true. A checkpointer may
+ ** have started to backfill the appended frames but crashed before
+ ** it finished. Leaving a corrupt image in the database file.
+ */
+ walUnlockShared(pWal, WAL_READ_LOCK(0));
+ return WAL_RETRY;
+ }
+ pWal->readLock = 0;
+ return SQLITE_OK;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+
+ /* If we get this far, it means that the reader will want to use
+ ** the WAL to get at content from recent commits. The job now is
+ ** to select one of the aReadMark[] entries that is closest to
+ ** but not exceeding pWal->hdr.mxFrame and lock that entry.
+ */
+ mxReadMark = 0;
+ mxI = 0;
+ mxFrame = pWal->hdr.mxFrame;
+#ifdef SQLITE_ENABLE_SNAPSHOT
+ if( pWal->pSnapshot && pWal->pSnapshot->mxFramepSnapshot->mxFrame;
+ }
+#endif
+ for(i=1; iaReadMark+i); SEH_INJECT_FAULT;
+ if( mxReadMark<=thisMark && thisMark<=mxFrame ){
+ assert( thisMark!=READMARK_NOT_USED );
+ mxReadMark = thisMark;
+ mxI = i;
+ }
+ }
+ if( (pWal->readOnly & WAL_SHM_RDONLY)==0
+ && (mxReadMarkaReadMark+i,mxFrame);
+ mxReadMark = mxFrame;
+ mxI = i;
+ walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ break;
+ }else if( rc!=SQLITE_BUSY ){
+ return rc;
+ }
+ }
+ }
+ if( mxI==0 ){
+ assert( rc==SQLITE_BUSY || (pWal->readOnly & WAL_SHM_RDONLY)!=0 );
+ return rc==SQLITE_BUSY ? WAL_RETRY : SQLITE_READONLY_CANTINIT;
+ }
+
+ (void)walEnableBlockingMs(pWal, nBlockTmout);
+ rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
+ walDisableBlocking(pWal);
+ if( rc ){
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
+ if( rc==SQLITE_BUSY_TIMEOUT ){
+ *pCnt |= WAL_RETRY_BLOCKED_MASK;
+ }
+#else
+ assert( rc!=SQLITE_BUSY_TIMEOUT );
+#endif
+ assert( (rc&0xFF)!=SQLITE_BUSY||rc==SQLITE_BUSY||rc==SQLITE_BUSY_TIMEOUT );
+ return (rc&0xFF)==SQLITE_BUSY ? WAL_RETRY : rc;
+ }
+ /* Now that the read-lock has been obtained, check that neither the
+ ** value in the aReadMark[] array or the contents of the wal-index
+ ** header have changed.
+ **
+ ** It is necessary to check that the wal-index header did not change
+ ** between the time it was read and when the shared-lock was obtained
+ ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
+ ** that the log file may have been wrapped by a writer, or that frames
+ ** that occur later in the log than pWal->hdr.mxFrame may have been
+ ** copied into the database by a checkpointer. If either of these things
+ ** happened, then reading the database with the current value of
+ ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
+ ** instead.
+ **
+ ** Before checking that the live wal-index header has not changed
+ ** since it was read, set Wal.minFrame to the first frame in the wal
+ ** file that has not yet been checkpointed. This client will not need
+ ** to read any frames earlier than minFrame from the wal file - they
+ ** can be safely read directly from the database file.
+ **
+ ** Because a ShmBarrier() call is made between taking the copy of
+ ** nBackfill and checking that the wal-header in shared-memory still
+ ** matches the one cached in pWal->hdr, it is guaranteed that the
+ ** checkpointer that set nBackfill was not working with a wal-index
+ ** header newer than that cached in pWal->hdr. If it were, that could
+ ** cause a problem. The checkpointer could omit to checkpoint
+ ** a version of page X that lies before pWal->minFrame (call that version
+ ** A) on the basis that there is a newer version (version B) of the same
+ ** page later in the wal file. But if version B happens to like past
+ ** frame pWal->hdr.mxFrame - then the client would incorrectly assume
+ ** that it can read version A from the database file. However, since
+ ** we can guarantee that the checkpointer that set nBackfill could not
+ ** see any pages past pWal->hdr.mxFrame, this problem does not come up.
+ */
+ pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT;
+ walShmBarrier(pWal);
+ if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark
+ || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
+ ){
+ walUnlockShared(pWal, WAL_READ_LOCK(mxI));
+ return WAL_RETRY;
+ }else{
+ assert( mxReadMark<=pWal->hdr.mxFrame );
+ pWal->readLock = (i16)mxI;
}
return rc;
}
#ifdef SQLITE_ENABLE_SNAPSHOT
@@ -87155,11 +87201,10 @@
**
** All other fields of Mem can safely remain uninitialized for now. They
** will be initialized before use.
*/
static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
- assert( db!=0 );
if( N>0 ){
do{
p->flags = flags;
p->db = db;
p->szMalloc = 0;
@@ -87181,11 +87226,10 @@
*/
static void releaseMemArray(Mem *p, int N){
if( p && N ){
Mem *pEnd = &p[N];
sqlite3 *db = p->db;
- assert( db!=0 );
if( db->pnBytesFreed ){
do{
if( p->szMalloc ) sqlite3DbFree(db, p->zMalloc);
}while( (++p)nOp>0 );
assert( pParse!=0 );
assert( p->eVdbeState==VDBE_INIT_STATE );
assert( pParse==p->pParse );
- assert( pParse->db==p->db );
p->pVList = pParse->pVList;
pParse->pVList = 0;
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
@@ -90543,11 +90586,10 @@
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
- sqlite3VdbeMemRelease(&preupdate.oldipk);
if( preupdate.aNew ){
int i;
for(i=0; inField; i++){
sqlite3VdbeMemRelease(&preupdate.aNew[i]);
}
@@ -91900,11 +91942,11 @@
**
** sqlite3_column_int()
** sqlite3_column_int64()
** sqlite3_column_text()
** sqlite3_column_text16()
-** sqlite3_column_double()
+** sqlite3_column_real()
** sqlite3_column_bytes()
** sqlite3_column_bytes16()
** sqlite3_column_blob()
*/
static void columnMallocFailure(sqlite3_stmt *pStmt)
@@ -92762,68 +92804,64 @@
if( iIdx>=p->pCsr->nField || iIdx<0 ){
rc = SQLITE_RANGE;
goto preupdate_old_out;
}
+ /* If the old.* record has not yet been loaded into memory, do so now. */
+ if( p->pUnpacked==0 ){
+ u32 nRec;
+ u8 *aRec;
+
+ assert( p->pCsr->eCurType==CURTYPE_BTREE );
+ nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
+ aRec = sqlite3DbMallocRaw(db, nRec);
+ if( !aRec ) goto preupdate_old_out;
+ rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
+ if( rc==SQLITE_OK ){
+ p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
+ if( !p->pUnpacked ) rc = SQLITE_NOMEM;
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3DbFree(db, aRec);
+ goto preupdate_old_out;
+ }
+ p->aRecord = aRec;
+ }
+
+ pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
if( iIdx==p->pTab->iPKey ){
- *ppValue = pMem = &p->oldipk;
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
- }else{
-
- /* If the old.* record has not yet been loaded into memory, do so now. */
- if( p->pUnpacked==0 ){
- u32 nRec;
- u8 *aRec;
-
- assert( p->pCsr->eCurType==CURTYPE_BTREE );
- nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
- aRec = sqlite3DbMallocRaw(db, nRec);
- if( !aRec ) goto preupdate_old_out;
- rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
- if( rc==SQLITE_OK ){
- p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
- if( !p->pUnpacked ) rc = SQLITE_NOMEM;
- }
- if( rc!=SQLITE_OK ){
- sqlite3DbFree(db, aRec);
- goto preupdate_old_out;
- }
- p->aRecord = aRec;
- }
-
- pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
- if( iIdx>=p->pUnpacked->nField ){
- /* This occurs when the table has been extended using ALTER TABLE
- ** ADD COLUMN. The value to return is the default value of the column. */
- Column *pCol = &p->pTab->aCol[iIdx];
- if( pCol->iDflt>0 ){
- if( p->apDflt==0 ){
- int nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
- p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
- if( p->apDflt==0 ) goto preupdate_old_out;
- }
- if( p->apDflt[iIdx]==0 ){
- sqlite3_value *pVal = 0;
- Expr *pDflt;
- assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
- pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
- rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
- if( rc==SQLITE_OK && pVal==0 ){
- rc = SQLITE_CORRUPT_BKPT;
- }
- p->apDflt[iIdx] = pVal;
- }
- *ppValue = p->apDflt[iIdx];
- }else{
- *ppValue = (sqlite3_value *)columnNullValue();
- }
- }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
- if( pMem->flags & (MEM_Int|MEM_IntReal) ){
- testcase( pMem->flags & MEM_Int );
- testcase( pMem->flags & MEM_IntReal );
- sqlite3VdbeMemRealify(pMem);
- }
+ }else if( iIdx>=p->pUnpacked->nField ){
+ /* This occurs when the table has been extended using ALTER TABLE
+ ** ADD COLUMN. The value to return is the default value of the column. */
+ Column *pCol = &p->pTab->aCol[iIdx];
+ if( pCol->iDflt>0 ){
+ if( p->apDflt==0 ){
+ int nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
+ p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
+ if( p->apDflt==0 ) goto preupdate_old_out;
+ }
+ if( p->apDflt[iIdx]==0 ){
+ sqlite3_value *pVal = 0;
+ Expr *pDflt;
+ assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
+ pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
+ rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
+ if( rc==SQLITE_OK && pVal==0 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
+ p->apDflt[iIdx] = pVal;
+ }
+ *ppValue = p->apDflt[iIdx];
+ }else{
+ *ppValue = (sqlite3_value *)columnNullValue();
+ }
+ }else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
+ if( pMem->flags & (MEM_Int|MEM_IntReal) ){
+ testcase( pMem->flags & MEM_Int );
+ testcase( pMem->flags & MEM_IntReal );
+ sqlite3VdbeMemRealify(pMem);
}
}
preupdate_old_out:
sqlite3Error(db, rc);
@@ -93367,108 +93405,10 @@
** commenting and indentation practices when changing or adding code.
*/
/* #include "sqliteInt.h" */
/* #include "vdbeInt.h" */
-/*
-** High-resolution hardware timer used for debugging and testing only.
-*/
-#if defined(VDBE_PROFILE) \
- || defined(SQLITE_PERFORMANCE_TRACE) \
- || defined(SQLITE_ENABLE_STMT_SCANSTATUS)
-/************** Include hwtime.h in the middle of vdbe.c *********************/
-/************** Begin file hwtime.h ******************************************/
-/*
-** 2008 May 27
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-******************************************************************************
-**
-** This file contains inline asm code for retrieving "high-performance"
-** counters for x86 and x86_64 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_HWTIME_H
-
-/*
-** The following routine only works on Pentium-class (or newer) processors.
-** It uses the RDTSC opcode to read the cycle count value out of the
-** processor and returns that value. This can be used for high-res
-** profiling.
-*/
-#if !defined(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
- #elif defined(_MSC_VER)
-
- __declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned int lo, hi;
- __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
- return (sqlite_uint64)hi << 32 | lo;
- }
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlite3Hwtime(void){
- unsigned long long retval;
- unsigned long junk;
- __asm__ __volatile__ ("\n\
- 1: mftbu %1\n\
- mftb %L0\n\
- mftbu %0\n\
- cmpw %0,%1\n\
- bne 1b"
- : "=r" (retval), "=r" (junk));
- return retval;
- }
-
-#else
-
- /*
- ** asm() is needed for hardware timing support. Without asm(),
- ** disable the sqlite3Hwtime() routine.
- **
- ** sqlite3Hwtime() is only used for some obscure debugging
- ** and analysis configurations, not in any deliverable, so this
- ** should not be a great loss.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
-
-/************** End of hwtime.h **********************************************/
-/************** Continuing where we left off in vdbe.c ***********************/
-#endif
-
/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell. This macro verifies that shallow copies are
** not misused. A shallow copy of a string or blob just copies a
** pointer to the string or blob, not the content. If the original
@@ -97973,15 +97913,13 @@
0, pCx->uc.pCursor);
pCx->isTable = 1;
}
}
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
- assert( p->apCsr[pOp->p1]==pCx );
if( rc ){
assert( !sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
sqlite3BtreeClose(pCx->ub.pBtx);
- p->apCsr[pOp->p1] = 0; /* Not required; helps with static analysis */
}else{
assert( sqlite3BtreeClosesWithCursor(pCx->ub.pBtx, pCx->uc.pCursor) );
}
}
}
@@ -102497,11 +102435,11 @@
** element.
**
** As with all opcodes, the meanings of the parameters for OP_Explain
** are subject to change from one release to the next. Applications
** should not attempt to interpret or use any of the information
-** contained in the OP_Explain opcode. The information provided by this
+** contined in the OP_Explain opcode. The information provided by this
** opcode is intended for testing and debugging use only.
*/
default: { /* This is really OP_Noop, OP_Explain */
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
@@ -109907,11 +109845,11 @@
p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
}
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
(void*)p4, P4_COLLSEQ);
- sqlite3VdbeChangeP5(pParse->pVdbe, (u16)p5);
+ sqlite3VdbeChangeP5(pParse->pVdbe, (u8)p5);
return addr;
}
/*
** Return true if expression pExpr is a vector, or false otherwise.
@@ -112074,11 +112012,11 @@
**
** (4) If pSrc is the right operand of a LEFT JOIN, then...
** (4a) pExpr must come from an ON clause..
** (4b) and specifically the ON clause associated with the LEFT JOIN.
**
-** (5) If pSrc is the right operand of a LEFT JOIN or the left
+** (5) If pSrc is not the right operand of a LEFT JOIN or the left
** operand of a RIGHT JOIN, then pExpr must be from the WHERE
** clause, not an ON clause.
**
** (6) Either:
**
@@ -115608,41 +115546,35 @@
**
** Additionally, if pExpr is a simple SQL value and the value is the
** same as that currently bound to variable pVar, non-zero is returned.
** Otherwise, if the values are not the same or if pExpr is not a simple
** SQL value, zero is returned.
-**
-** If the SQLITE_EnableQPSG flag is set on the database connection, then
-** this routine always returns false.
*/
-static SQLITE_NOINLINE int exprCompareVariable(
+static int exprCompareVariable(
const Parse *pParse,
const Expr *pVar,
const Expr *pExpr
){
- int res = 2;
+ int res = 0;
int iVar;
sqlite3_value *pL, *pR = 0;
- if( pExpr->op==TK_VARIABLE && pVar->iColumn==pExpr->iColumn ){
- return 0;
- }
- if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) return 2;
sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB, &pR);
if( pR ){
iVar = pVar->iColumn;
sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB);
if( pL ){
if( sqlite3_value_type(pL)==SQLITE_TEXT ){
sqlite3_value_text(pL); /* Make sure the encoding is UTF-8 */
}
- res = sqlite3MemCompare(pL, pR, 0) ? 2 : 0;
+ res = 0==sqlite3MemCompare(pL, pR, 0);
}
sqlite3ValueFree(pR);
sqlite3ValueFree(pL);
}
+
return res;
}
/*
** Do a deep comparison of two expression trees. Return 0 if the two
@@ -115664,14 +115596,16 @@
** can be sure the expressions are the same. In the places where
** this routine is used, it does not hurt to get an extra 2 - that
** just might result in some slightly slower code. But returning
** an incorrect 0 or 1 could lead to a malfunction.
**
-** If pParse is not NULL and SQLITE_EnableQPSG is off then TK_VARIABLE
-** terms in pA with bindings in pParse->pReprepare can be matched against
-** literals in pB. The pParse->pVdbe->expmask bitmask is updated for
-** each variable referenced.
+** If pParse is not NULL then TK_VARIABLE terms in pA with bindings in
+** pParse->pReprepare can be matched against literals in pB. The
+** pParse->pVdbe->expmask bitmask is updated for each variable referenced.
+** If pParse is NULL (the normal case) then any TK_VARIABLE term in
+** Argument pParse should normally be NULL. If it is not NULL and pA or
+** pB causes a return value of 2.
*/
SQLITE_PRIVATE int sqlite3ExprCompare(
const Parse *pParse,
const Expr *pA,
const Expr *pB,
@@ -115679,12 +115613,12 @@
){
u32 combinedFlags;
if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
}
- if( pParse && pA->op==TK_VARIABLE ){
- return exprCompareVariable(pParse, pA, pB);
+ if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){
+ return 0;
}
combinedFlags = pA->flags | pB->flags;
if( combinedFlags & EP_IntValue ){
if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
return 0;
@@ -115875,74 +115809,22 @@
}
}
return 0;
}
-/*
-** Return true if the boolean value of the expression is always either
-** FALSE or NULL.
-*/
-static int sqlite3ExprIsNotTrue(Expr *pExpr){
- int v;
- if( pExpr->op==TK_NULL ) return 1;
- if( pExpr->op==TK_TRUEFALSE && sqlite3ExprTruthValue(pExpr)==0 ) return 1;
- v = 1;
- if( sqlite3ExprIsInteger(pExpr, &v, 0) && v==0 ) return 1;
- return 0;
-}
-
-/*
-** Return true if the expression is one of the following:
-**
-** CASE WHEN x THEN y END
-** CASE WHEN x THEN y ELSE NULL END
-** CASE WHEN x THEN y ELSE false END
-** iif(x,y)
-** iif(x,y,NULL)
-** iif(x,y,false)
-*/
-static int sqlite3ExprIsIIF(sqlite3 *db, const Expr *pExpr){
- ExprList *pList;
- if( pExpr->op==TK_FUNCTION ){
- const char *z = pExpr->u.zToken;
- FuncDef *pDef;
- if( (z[0]!='i' && z[0]!='I') ) return 0;
- if( pExpr->x.pList==0 ) return 0;
- pDef = sqlite3FindFunction(db, z, pExpr->x.pList->nExpr, ENC(db), 0);
-#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- if( pDef==0 ) return 0;
-#else
- if( NEVER(pDef==0) ) return 0;
-#endif
- if( (pDef->funcFlags & SQLITE_FUNC_INLINE)==0 ) return 0;
- if( SQLITE_PTR_TO_INT(pDef->pUserData)!=INLINEFUNC_iif ) return 0;
- }else if( pExpr->op==TK_CASE ){
- if( pExpr->pLeft!=0 ) return 0;
- }else{
- return 0;
- }
- pList = pExpr->x.pList;
- assert( pList!=0 );
- if( pList->nExpr==2 ) return 1;
- if( pList->nExpr==3 && sqlite3ExprIsNotTrue(pList->a[2].pExpr) ) return 1;
- return 0;
-}
-
/*
** Return true if we can prove the pE2 will always be true if pE1 is
** true. Return false if we cannot complete the proof or if pE2 might
** be false. Examples:
**
-** pE1: x==5 pE2: x==5 Result: true
-** pE1: x>0 pE2: x==5 Result: false
-** pE1: x=21 pE2: x=21 OR y=43 Result: true
-** pE1: x!=123 pE2: x IS NOT NULL Result: true
-** pE1: x!=?1 pE2: x IS NOT NULL Result: true
-** pE1: x IS NULL pE2: x IS NOT NULL Result: false
-** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
-** pE1: iif(x,y) pE2: x Result: true
-** PE1: iif(x,y,0) pE2: x Result: true
+** pE1: x==5 pE2: x==5 Result: true
+** pE1: x>0 pE2: x==5 Result: false
+** pE1: x=21 pE2: x=21 OR y=43 Result: true
+** pE1: x!=123 pE2: x IS NOT NULL Result: true
+** pE1: x!=?1 pE2: x IS NOT NULL Result: true
+** pE1: x IS NULL pE2: x IS NOT NULL Result: false
+** pE1: x IS ?2 pE2: x IS NOT NULL Result: false
**
** When comparing TK_COLUMN nodes between pE1 and pE2, if pE2 has
** Expr.iTable<0 then assume a table number given by iTab.
**
** If pParse is not NULL, then the values of bound variables in pE1 are
@@ -115972,13 +115854,10 @@
if( pE2->op==TK_NOTNULL
&& exprImpliesNotNull(pParse, pE1, pE2->pLeft, iTab, 0)
){
return 1;
}
- if( sqlite3ExprIsIIF(pParse->db, pE1) ){
- return sqlite3ExprImpliesExpr(pParse,pE1->x.pList->a[0].pExpr,pE2,iTab);
- }
return 0;
}
/* This is a helper function to impliesNotNullRow(). In this routine,
** set pWalker->eCode to one only if *both* of the input expressions
@@ -121386,10 +121265,19 @@
rc = sqlite3Init(db, &zErrDyn);
}
sqlite3BtreeLeaveAll(db);
assert( zErrDyn==0 || rc!=SQLITE_OK );
}
+#ifdef SQLITE_USER_AUTHENTICATION
+ if( rc==SQLITE_OK && !REOPEN_AS_MEMDB(db) ){
+ u8 newAuth = 0;
+ rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth);
+ if( newAuthauth.authLevel ){
+ rc = SQLITE_AUTH_USER;
+ }
+ }
+#endif
if( rc ){
if( ALWAYS(!REOPEN_AS_MEMDB(db)) ){
int iDb = db->nDb - 1;
assert( iDb>=2 );
if( db->aDb[iDb].pBt ){
@@ -121883,11 +121771,15 @@
sqlite3 *db = pParse->db; /* Database handle */
char *zDb = db->aDb[iDb].zDbSName; /* Schema name of attached database */
int rc; /* Auth callback return code */
if( db->init.busy ) return SQLITE_OK;
- rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext);
+ rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
+#ifdef SQLITE_USER_AUTHENTICATION
+ ,db->auth.zAuthUser
+#endif
+ );
if( rc==SQLITE_DENY ){
char *z = sqlite3_mprintf("%s.%s", zTab, zCol);
if( db->nDb>2 || iDb!=0 ) z = sqlite3_mprintf("%s.%z", zDb, z);
sqlite3ErrorMsg(pParse, "access to %z is prohibited", z);
pParse->rc = SQLITE_AUTH;
@@ -121990,11 +121882,15 @@
testcase( zArg1==0 );
testcase( zArg2==0 );
testcase( zArg3==0 );
testcase( pParse->zAuthContext==0 );
- rc = db->xAuth(db->pAuthArg,code,zArg1,zArg2,zArg3,pParse->zAuthContext);
+ rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext
+#ifdef SQLITE_USER_AUTHENTICATION
+ ,db->auth.zAuthUser
+#endif
+ );
if( rc==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
rc = SQLITE_DENY;
@@ -122222,10 +122118,21 @@
VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addrRewind);
}
}
sqlite3VdbeAddOp0(v, OP_Halt);
+
+#if SQLITE_USER_AUTHENTICATION && !defined(SQLITE_OMIT_SHARED_CACHE)
+ if( pParse->nTableLock>0 && db->init.busy==0 ){
+ sqlite3UserAuthInit(db);
+ if( db->auth.authLevelrc = SQLITE_AUTH_USER;
+ return;
+ }
+ }
+#endif
/* The cookie mask contains one bit for each database file open.
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
** set for each database that is used. Generate code to start a
** transaction on each used database and to verify the schema cookie
@@ -122351,10 +122258,20 @@
sqlite3DbFree(db, zSql);
memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
pParse->nested--;
}
+#if SQLITE_USER_AUTHENTICATION
+/*
+** Return TRUE if zTable is the name of the system table that stores the
+** list of users and their access credentials.
+*/
+SQLITE_PRIVATE int sqlite3UserAuthTable(const char *zTable){
+ return sqlite3_stricmp(zTable, "sqlite_user")==0;
+}
+#endif
+
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table. Return NULL if not found.
**
@@ -122369,10 +122286,17 @@
Table *p = 0;
int i;
/* All mutexes are required for schema access. Make sure we hold them. */
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
+#if SQLITE_USER_AUTHENTICATION
+ /* Only the admin user is allowed to know that the sqlite_user table
+ ** exists */
+ if( db->auth.authLevelnDb; i++){
if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
}
if( i>=db->nDb ){
@@ -126027,10 +125951,13 @@
assert( pTab!=0 );
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
&& pTblName!=0
+#if SQLITE_USER_AUTHENTICATION
+ && sqlite3UserAuthTable(pTab->zName)==0
+#endif
){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
}
#ifndef SQLITE_OMIT_VIEW
@@ -129734,19 +129661,20 @@
const unsigned char *z;
const unsigned char *z2;
int len;
int p0type;
i64 p1, p2;
+ int negP2 = 0;
assert( argc==3 || argc==2 );
if( sqlite3_value_type(argv[1])==SQLITE_NULL
|| (argc==3 && sqlite3_value_type(argv[2])==SQLITE_NULL)
){
return;
}
p0type = sqlite3_value_type(argv[0]);
- p1 = sqlite3_value_int64(argv[1]);
+ p1 = sqlite3_value_int(argv[1]);
if( p0type==SQLITE_BLOB ){
len = sqlite3_value_bytes(argv[0]);
z = sqlite3_value_blob(argv[0]);
if( z==0 ) return;
assert( len==sqlite3_value_bytes(argv[0]) );
@@ -129767,36 +129695,36 @@
** from 2009-02-02 for compatibility of applications that exploited the
** old buggy behavior. */
if( p1==0 ) p1 = 1; /* */
#endif
if( argc==3 ){
- p2 = sqlite3_value_int64(argv[2]);
+ p2 = sqlite3_value_int(argv[2]);
+ if( p2<0 ){
+ p2 = -p2;
+ negP2 = 1;
+ }
}else{
p2 = sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH];
}
if( p1<0 ){
p1 += len;
if( p1<0 ){
- if( p2<0 ){
- p2 = 0;
- }else{
- p2 += p1;
- }
+ p2 += p1;
+ if( p2<0 ) p2 = 0;
p1 = 0;
}
}else if( p1>0 ){
p1--;
}else if( p2>0 ){
p2--;
}
- if( p2<0 ){
- if( p2<-p1 ){
- p2 = p1;
- }else{
- p2 = -p2;
- }
+ if( negP2 ){
p1 -= p2;
+ if( p1<0 ){
+ p2 += p1;
+ p1 = 0;
+ }
}
assert( p1>=0 && p2>=0 );
if( p0type!=SQLITE_BLOB ){
while( *z && p1 ){
SQLITE_SKIP_UTF8(z);
@@ -129806,15 +129734,13 @@
SQLITE_SKIP_UTF8(z2);
}
sqlite3_result_text64(context, (char*)z, z2-z, SQLITE_TRANSIENT,
SQLITE_UTF8);
}else{
- if( p1>=len ){
- p1 = p2 = 0;
- }else if( p2>len-p1 ){
+ if( p1+p2>len ){
p2 = len-p1;
- assert( p2>0 );
+ if( p2<0 ) p2 = 0;
}
sqlite3_result_blob64(context, (char*)&z[p1], (u64)p2, SQLITE_TRANSIENT);
}
}
@@ -129821,17 +129747,17 @@
/*
** Implementation of the round() function
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
- i64 n = 0;
+ int n = 0;
double r;
char *zBuf;
assert( argc==1 || argc==2 );
if( argc==2 ){
if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return;
- n = sqlite3_value_int64(argv[1]);
+ n = sqlite3_value_int(argv[1]);
if( n>30 ) n = 30;
if( n<0 ) n = 0;
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
r = sqlite3_value_double(argv[0]);
@@ -129842,11 +129768,11 @@
if( r<-4503599627370496.0 || r>+4503599627370496.0 ){
/* The value has no fractional part so there is nothing to round */
}else if( n==0 ){
r = (double)((sqlite_int64)(r+(r<0?-0.5:+0.5)));
}else{
- zBuf = sqlite3_mprintf("%!.*f",(int)n,r);
+ zBuf = sqlite3_mprintf("%!.*f",n,r);
if( zBuf==0 ){
sqlite3_result_error_nomem(context);
return;
}
sqlite3AtoF(zBuf, &r, sqlite3Strlen30(zBuf), SQLITE_UTF8);
@@ -132059,10 +131985,13 @@
#endif
#ifndef SQLITE_OMIT_LOAD_EXTENSION
SFUNCTION(load_extension, 1, 0, 0, loadExt ),
SFUNCTION(load_extension, 2, 0, 0, loadExt ),
#endif
+#if SQLITE_USER_AUTHENTICATION
+ FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
+#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
INLINE_FUNC(unlikely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
@@ -132195,14 +132124,11 @@
MFUNCTION(degrees, 1, radToDeg, math1Func ),
MFUNCTION(pi, 0, 0, piFunc ),
#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
FUNCTION(sign, 1, 0, 0, signFunc ),
INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
- INLINE_FUNC(iif, 2, INLINEFUNC_iif, 0 ),
INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
- INLINE_FUNC(if, 2, INLINEFUNC_iif, 0 ),
- INLINE_FUNC(if, 3, INLINEFUNC_iif, 0 ),
};
#ifndef SQLITE_OMIT_ALTERTABLE
sqlite3AlterFunctions();
#endif
sqlite3WindowFunctions();
@@ -140711,10 +140637,16 @@
if( db->autoCommit==0 ){
/* Foreign key support may not be enabled or disabled while not
** in auto-commit mode. */
mask &= ~(SQLITE_ForeignKeys);
}
+#if SQLITE_USER_AUTHENTICATION
+ if( db->auth.authLevel==UAUTH_User ){
+ /* Do not allow non-admin users to modify the schema arbitrarily */
+ mask &= ~(SQLITE_WriteSchema);
+ }
+#endif
if( sqlite3GetBoolean(zRight, 0) ){
if( (mask & SQLITE_WriteSchema)==0
|| (db->flags & SQLITE_Defensive)==0
){
@@ -140846,12 +140778,11 @@
pTab = sqliteHashData(k);
if( pTab->nCol==0 ){
char *zSql = sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
if( zSql ){
sqlite3_stmt *pDummy = 0;
- (void)sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_DONT_LOG,
- &pDummy, 0);
+ (void)sqlite3_prepare(db, zSql, -1, &pDummy, 0);
(void)sqlite3_finalize(pDummy);
sqlite3DbFree(db, zSql);
}
if( db->mallocFailed ){
sqlite3ErrorMsg(db->pParse, "out of memory");
@@ -141328,11 +141259,11 @@
sqlite3VdbeAddOp3(v, OP_Null, 0, 8, 8+cnt);
sqlite3ClearTempRegCache(pParse);
/* Do the b-tree integrity checks */
sqlite3VdbeAddOp4(v, OP_IntegrityCk, 1, cnt, 8, (char*)aRoot,P4_INTARRAY);
- sqlite3VdbeChangeP5(v, (u16)i);
+ sqlite3VdbeChangeP5(v, (u8)i);
addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
P4_DYNAMIC);
sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3);
@@ -142948,11 +142879,18 @@
encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
if( encoding==0 ) encoding = SQLITE_UTF8;
#else
encoding = SQLITE_UTF8;
#endif
- sqlite3SetTextEncoding(db, encoding);
+ if( db->nVdbeActive>0 && encoding!=ENC(db)
+ && (db->mDbFlags & DBFLAG_Vacuum)==0
+ ){
+ rc = SQLITE_LOCKED;
+ goto initone_error_out;
+ }else{
+ sqlite3SetTextEncoding(db, encoding);
+ }
}else{
/* If opening an attached database, the encoding much match ENC(db) */
if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){
sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
" text encoding as main database");
@@ -147646,36 +147584,36 @@
return pExpr;
}
if( pSubst->isOuterJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
- if( pNew->op==TK_TRUEFALSE ){
- pNew->u.iValue = sqlite3ExprTruthValue(pNew);
- pNew->op = TK_INTEGER;
- ExprSetProperty(pNew, EP_IntValue);
- }
-
- /* Ensure that the expression now has an implicit collation sequence,
- ** just as it did when it was a column of a view or sub-query. */
- {
- CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pNew);
- CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
- pSubst->pCList->a[iColumn].pExpr
- );
- if( pNat!=pColl || (pNew->op!=TK_COLUMN && pNew->op!=TK_COLLATE) ){
- pNew = sqlite3ExprAddCollateString(pSubst->pParse, pNew,
- (pColl ? pColl->zName : "BINARY")
- );
- }
- }
- ExprClearProperty(pNew, EP_Collate);
if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
pExpr->flags & (EP_OuterON|EP_InnerON));
}
sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
+ if( pExpr->op==TK_TRUEFALSE ){
+ pExpr->u.iValue = sqlite3ExprTruthValue(pExpr);
+ pExpr->op = TK_INTEGER;
+ ExprSetProperty(pExpr, EP_IntValue);
+ }
+
+ /* Ensure that the expression now has an implicit collation sequence,
+ ** just as it did when it was a column of a view or sub-query. */
+ {
+ CollSeq *pNat = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
+ CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse,
+ pSubst->pCList->a[iColumn].pExpr
+ );
+ if( pNat!=pColl || (pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE) ){
+ pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
+ (pColl ? pColl->zName : "BINARY")
+ );
+ }
+ }
+ ExprClearProperty(pExpr, EP_Collate);
}
}
}else{
if( pExpr->op==TK_IF_NULL_ROW && pExpr->iTable==pSubst->iTable ){
pExpr->iTable = pSubst->iNewTable;
@@ -148408,20 +148346,20 @@
}
/* Transfer the FROM clause terms from the subquery into the
** outer query.
*/
- iNewParent = pSubSrc->a[0].iCursor;
for(i=0; ia[i+iFrom];
assert( pItem->fg.isTabFunc==0 );
assert( pItem->fg.isSubquery
|| pItem->fg.fixedSchema
|| pItem->u4.zDatabase==0 );
if( pItem->fg.isUsing ) sqlite3IdListDelete(db, pItem->u3.pUsing);
*pItem = pSubSrc->a[i];
pItem->fg.jointype |= ltorj;
+ iNewParent = pSubSrc->a[i].iCursor;
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
pSrc->a[iFrom].fg.jointype |= jointype | ltorj;
@@ -148457,11 +148395,10 @@
pSub->pOrderBy = 0;
}
pWhere = pSub->pWhere;
pSub->pWhere = 0;
if( isOuterJoin>0 ){
- assert( pSubSrc->nSrc==1 );
sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
}
if( pWhere ){
if( pParent->pWhere ){
pParent->pWhere = sqlite3PExpr(pParse, TK_AND, pWhere, pParent->pWhere);
@@ -150561,11 +150498,11 @@
}
sqlite3ReleaseTempReg(pParse, regSubtype);
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u16)nArg);
+ sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3VdbeAddOp2(v, OP_Next, pF->iOBTab, iTop+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, iTop);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
}
sqlite3VdbeAddOp2(v, OP_AggFinal, AggInfoFuncReg(pAggInfo,i),
@@ -150724,11 +150661,11 @@
sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0,
(char *)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp3(v, OP_AggStep, 0, regAgg, AggInfoFuncReg(pAggInfo,i));
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u16)nArg);
+ sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
}
if( addrNext ){
sqlite3VdbeResolveLabel(v, addrNext);
}
@@ -151557,11 +151494,11 @@
sqlite3TreeViewSelect(0, p, 0);
}
#endif
assert( pSubq->pSelect && (pSub->selFlags & SF_PushDown)!=0 );
}else{
- TREETRACE(0x4000,pParse,p,("WHERE-clause push-down not possible\n"));
+ TREETRACE(0x4000,pParse,p,("WHERE-lcause push-down not possible\n"));
}
/* Convert unused result columns of the subquery into simple NULL
** expressions, to avoid unneeded searching and computation.
** tag-select-0440
@@ -154118,11 +154055,11 @@
/* Set the P5 operand of the OP_Program instruction to non-zero if
** recursive invocation of this trigger program is disallowed. Recursive
** invocation is disallowed if (a) the sub-program is really a trigger,
** not a foreign key action, and (b) the flag to enable recursive triggers
** is clear. */
- sqlite3VdbeChangeP5(v, (u16)bRecursive);
+ sqlite3VdbeChangeP5(v, (u8)bRecursive);
}
}
/*
** This is called to code the required FOR EACH ROW triggers for an operation
@@ -158331,21 +158268,13 @@
SQLITE_PRIVATE int sqlite3WhereExplainBloomFilter(
const Parse *pParse, /* Parse context */
const WhereInfo *pWInfo, /* WHERE clause */
const WhereLevel *pLevel /* Bloom filter on this level */
);
-SQLITE_PRIVATE void sqlite3WhereAddExplainText(
- Parse *pParse, /* Parse context */
- int addr,
- SrcList *pTabList, /* Table list this loop refers to */
- WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
- u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
-);
#else
# define sqlite3WhereExplainOneScan(u,v,w,x) 0
# define sqlite3WhereExplainBloomFilter(u,v,w) 0
-# define sqlite3WhereAddExplainText(u,v,w,x,y)
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
SQLITE_PRIVATE void sqlite3WhereAddScanStatus(
Vdbe *v, /* Vdbe to add scanstatus entry to */
SrcList *pSrclist, /* FROM clause pLvl reads data from */
@@ -158543,42 +158472,42 @@
}
sqlite3_str_append(pStr, ")", 1);
}
/*
-** This function sets the P4 value of an existing OP_Explain opcode to
-** text describing the loop in pLevel. If the OP_Explain opcode already has
-** a P4 value, it is freed before it is overwritten.
+** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
+** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
+** was defined at compile-time. If it is not a no-op, a single OP_Explain
+** opcode is added to the output to describe the table scan strategy in pLevel.
+**
+** If an OP_Explain opcode is added to the VM, its address is returned.
+** Otherwise, if no OP_Explain is coded, zero is returned.
*/
-SQLITE_PRIVATE void sqlite3WhereAddExplainText(
+SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
Parse *pParse, /* Parse context */
- int addr, /* Address of OP_Explain opcode */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
+ int ret = 0;
#if !defined(SQLITE_DEBUG)
if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
#endif
{
- VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe, addr);
-
SrcItem *pItem = &pTabList->a[pLevel->iFrom];
+ Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
u32 flags; /* Flags that describe this loop */
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
char *zMsg; /* Text to add to EQP output */
-#endif
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
- if( db->mallocFailed ) return;
-
pLoop = pLevel->pWLoop;
flags = pLoop->wsFlags;
+ if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
@@ -158598,11 +158527,11 @@
}
}else if( flags & WHERE_PARTIALIDX ){
zFmt = "AUTOMATIC PARTIAL COVERING INDEX";
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "AUTOMATIC COVERING INDEX";
- }else if( flags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
+ }else if( flags & WHERE_IDX_ONLY ){
zFmt = "COVERING INDEX %s";
}else{
zFmt = "INDEX %s";
}
if( zFmt ){
@@ -158650,54 +158579,15 @@
sqlite3LogEstToInt(pLoop->nOut));
}else{
sqlite3_str_append(&str, " (~1 row)", 9);
}
#endif
-#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
zMsg = sqlite3StrAccumFinish(&str);
sqlite3ExplainBreakpoint("",zMsg);
-#endif
-
- assert( pOp->opcode==OP_Explain );
- assert( pOp->p4type==P4_DYNAMIC || pOp->p4.z==0 );
- sqlite3DbFree(db, pOp->p4.z);
- pOp->p4type = P4_DYNAMIC;
- pOp->p4.z = sqlite3StrAccumFinish(&str);
- }
-}
-
-
-/*
-** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
-** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
-** was defined at compile-time. If it is not a no-op, a single OP_Explain
-** opcode is added to the output to describe the table scan strategy in pLevel.
-**
-** If an OP_Explain opcode is added to the VM, its address is returned.
-** Otherwise, if no OP_Explain is coded, zero is returned.
-*/
-SQLITE_PRIVATE int sqlite3WhereExplainOneScan(
- Parse *pParse, /* Parse context */
- SrcList *pTabList, /* Table list this loop refers to */
- WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
- u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
-){
- int ret = 0;
-#if !defined(SQLITE_DEBUG)
- if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
-#endif
- {
- if( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0
- && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
- ){
- Vdbe *v = pParse->pVdbe;
- int addr = sqlite3VdbeCurrentAddr(v);
- ret = sqlite3VdbeAddOp3(
- v, OP_Explain, addr, pParse->addrExplain, pLevel->pWLoop->rRun
- );
- sqlite3WhereAddExplainText(pParse, addr, pTabList, pLevel, wctrlFlags);
- }
+ ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
+ pParse->addrExplain, pLoop->rRun,
+ zMsg, P4_DYNAMIC);
}
return ret;
}
/*
@@ -158792,14 +158682,13 @@
if( wsFlags & WHERE_INDEXED ){
sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur);
}
}else{
int addr;
- VdbeOp *pOp;
assert( pSrclist->a[pLvl->iFrom].fg.isSubquery );
addr = pSrclist->a[pLvl->iFrom].u4.pSubq->addrFillSub;
- pOp = sqlite3VdbeGetOp(v, addr-1);
+ VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-1);
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->opcode==OP_InitCoroutine );
assert( sqlite3VdbeDb(v)->mallocFailed || pOp->p2>addr );
sqlite3VdbeScanStatusRange(v, addrExplain, addr, pOp->p2-1);
}
}
@@ -159048,11 +158937,10 @@
if( pOrigLhs ){
sqlite3ExprListDelete(db, pOrigLhs);
pNew->pLeft->x.pList = pLhs;
}
pSelect->pEList = pRhs;
- pSelect->selId = ++pParse->nSelect; /* Req'd for SubrtnSig validity */
if( pLhs && pLhs->nExpr==1 ){
/* Take care here not to generate a TK_VECTOR containing only a
** single value. Since the parser never creates such a vector, some
** of the subroutines do not handle this case. */
Expr *p = pLhs->a[0].pExpr;
@@ -164121,11 +164009,11 @@
|| pTerm->pExpr->w.iJoin != pSrc->iCursor
){
return 0;
}
if( (pSrc->fg.jointype & (JT_LEFT|JT_RIGHT))!=0
- && NEVER(ExprHasProperty(pTerm->pExpr, EP_InnerON))
+ && ExprHasProperty(pTerm->pExpr, EP_InnerON)
){
return 0;
}
return 1;
}
@@ -165614,11 +165502,11 @@
return rc;
}
#endif /* SQLITE_ENABLE_STAT4 */
-#if defined(WHERETRACE_ENABLED) || defined(SQLITE_DEBUG)
+#ifdef WHERETRACE_ENABLED
/*
** Print the content of a WhereTerm object
*/
SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm==0 ){
@@ -165658,13 +165546,10 @@
}
sqlite3DebugPrintf("\n");
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
}
}
-SQLITE_PRIVATE void sqlite3ShowWhereTerm(WhereTerm *pTerm){
- sqlite3WhereTermPrint(pTerm, 0);
-}
#endif
#ifdef WHERETRACE_ENABLED
/*
** Show the complete content of a WhereClause
@@ -165868,11 +165753,11 @@
** Return TRUE if X is a proper subset of Y but is of equal or less cost.
** In other words, return true if all constraints of X are also part of Y
** and Y has additional constraints that might speed the search that X lacks
** but the cost of running X is not more than the cost of running Y.
**
-** In other words, return true if the cost relationship between X and Y
+** In other words, return true if the cost relationwship between X and Y
** is inverted and needs to be adjusted.
**
** Case 1:
**
** (1a) X and Y use the same index.
@@ -166846,10 +166731,11 @@
pParse = pWC->pWInfo->pParse;
while( pWhere->op==TK_AND ){
if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
}
+ if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){
Expr *pExpr;
pExpr = pTerm->pExpr;
if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
&& ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
@@ -169506,11 +169392,11 @@
break;
}
}
if( hasRightJoin
&& ExprHasProperty(pTerm->pExpr, EP_InnerON)
- && NEVER(pTerm->pExpr->w.iJoin==pItem->iCursor)
+ && pTerm->pExpr->w.iJoin==pItem->iCursor
){
break; /* restriction (5) */
}
}
if( pTermflags & SQLITE_VdbeAddopTrace)==0 ) return;
sqlite3VdbePrintOp(0, pc, pOp);
- sqlite3ShowWhereTerm(0); /* So compiler won't complain about unused func */
}
#endif
/*
** Generate the end of the WHERE loop. See comments on
@@ -170726,32 +170611,18 @@
x = sqlite3TableColumnToIndex(pIdx, x);
if( x>=0 ){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
- }else if( pLoop->wsFlags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
+ }else{
+ /* Unable to translate the table reference into an index
+ ** reference. Verify that this is harmless - that the
+ ** table being referenced really is open.
+ */
if( pLoop->wsFlags & WHERE_IDX_ONLY ){
- /* An error. pLoop is supposed to be a covering index loop,
- ** and yet the VM code refers to a column of the table that
- ** is not part of the index. */
sqlite3ErrorMsg(pParse, "internal query planner error");
pParse->rc = SQLITE_INTERNAL;
- }else{
- /* The WHERE_EXPRIDX flag is set by the planner when it is likely
- ** that pLoop is a covering index loop, but it is not possible
- ** to be 100% sure. In this case, any OP_Explain opcode
- ** corresponding to this loop describes the index as a "COVERING
- ** INDEX". But, pOp proves that pLoop is not actually a covering
- ** index loop. So clear the WHERE_EXPRIDX flag and rewrite the
- ** text that accompanies the OP_Explain opcode, if any. */
- pLoop->wsFlags &= ~WHERE_EXPRIDX;
- sqlite3WhereAddExplainText(pParse,
- pLevel->addrBody-1,
- pTabList,
- pLevel,
- pWInfo->wctrlFlags
- );
}
}
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;
@@ -172455,11 +172326,10 @@
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
FuncDef *pFunc = pWin->pWFunc;
int regArg;
int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin);
int i;
- int addrIf = 0;
assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
/* All OVER clauses in the same window function aggregate step must
** be the same. */
@@ -172472,22 +172342,10 @@
sqlite3VdbeAddOp3(v, OP_Column, pMWin->iEphCsr, pWin->iArgCol+i, reg+i);
}
}
regArg = reg;
- if( pWin->pFilter ){
- int regTmp;
- assert( ExprUseXList(pWin->pOwner) );
- assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
- assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
- regTmp = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
- addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
- VdbeCoverage(v);
- sqlite3ReleaseTempReg(pParse, regTmp);
- }
-
if( pMWin->regStartRowid==0
&& (pFunc->funcFlags & SQLITE_FUNC_MINMAX)
&& (pWin->eStart!=TK_UNBOUNDED)
){
int addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regArg);
@@ -172503,17 +172361,29 @@
sqlite3VdbeAddOp1(v, OP_Delete, pWin->csrApp);
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
}
sqlite3VdbeJumpHere(v, addrIsNull);
}else if( pWin->regApp ){
- assert( pWin->pFilter==0 );
assert( pFunc->zName==nth_valueName
|| pFunc->zName==first_valueName
);
assert( bInverse==0 || bInverse==1 );
sqlite3VdbeAddOp2(v, OP_AddImm, pWin->regApp+1-bInverse, 1);
}else if( pFunc->xSFunc!=noopStepFunc ){
+ int addrIf = 0;
+ if( pWin->pFilter ){
+ int regTmp;
+ assert( ExprUseXList(pWin->pOwner) );
+ assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
+ assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
+ regTmp = sqlite3GetTempReg(pParse);
+ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
+ addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
+ VdbeCoverage(v);
+ sqlite3ReleaseTempReg(pParse, regTmp);
+ }
+
if( pWin->bExprArgs ){
int iOp = sqlite3VdbeCurrentAddr(v);
int iEnd;
assert( ExprUseXList(pWin->pOwner) );
@@ -172536,17 +172406,16 @@
sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
}
sqlite3VdbeAddOp3(v, bInverse? OP_AggInverse : OP_AggStep,
bInverse, regArg, pWin->regAccum);
sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF);
- sqlite3VdbeChangeP5(v, (u16)nArg);
+ sqlite3VdbeChangeP5(v, (u8)nArg);
if( pWin->bExprArgs ){
sqlite3ReleaseTempRange(pParse, regArg, nArg);
}
+ if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
}
-
- if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
}
}
/*
** Values that may be passed as the second argument to windowCodeOp().
@@ -173969,17 +173838,10 @@
*/
struct TrigEvent { int a; IdList * b; };
struct FrameBound { int eType; Expr *pExpr; };
-/*
-** Generate a syntax error
-*/
-static void parserSyntaxError(Parse *pParse, Token *p){
- sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", p);
-}
-
/*
** Disable lookaside memory allocation for objects that might be
** shared across database connections.
*/
static void disableLookaside(Parse *pParse){
@@ -177868,15 +177730,11 @@
}
break;
case 84: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0};
- if( (pParse->db->mDbFlags & DBFLAG_EncodingFixed)!=0
- || sqlite3ReadSchema(pParse)==SQLITE_OK
- ){
- sqlite3Select(pParse, yymsp[0].minor.yy555, &dest);
- }
+ sqlite3Select(pParse, yymsp[0].minor.yy555, &dest);
sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy555);
}
break;
case 85: /* select ::= WITH wqlist selectnowith */
{yymsp[-2].minor.yy555 = attachWithToSelect(pParse,yymsp[0].minor.yy555,yymsp[-1].minor.yy59);}
@@ -178343,11 +178201,11 @@
** that look like this: #1 #2 ... These terms refer to registers
** in the virtual machine. #N is the N-th register. */
Token t = yymsp[0].minor.yy0; /*A-overwrites-X*/
assert( t.n>=2 );
if( pParse->nested==0 ){
- parserSyntaxError(pParse, &t);
+ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
yymsp[0].minor.yy454 = 0;
}else{
yymsp[0].minor.yy454 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
if( yymsp[0].minor.yy454 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy454->iTable);
}
@@ -179191,11 +179049,11 @@
#define TOKEN yyminor
/************ Begin %syntax_error code ****************************************/
UNUSED_PARAMETER(yymajor); /* Silence some compiler warnings */
if( TOKEN.z[0] ){
- parserSyntaxError(pParse, &TOKEN);
+ sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
}else{
sqlite3ErrorMsg(pParse, "incomplete input");
}
/************ End %syntax_error code ******************************************/
sqlite3ParserARG_STORE /* Suppress warning about unused %extra_argument variable */
@@ -180682,13 +180540,11 @@
}
if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){
if( pParse->zErrMsg==0 ){
pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
}
- if( (pParse->prepFlags & SQLITE_PREPARE_DONT_LOG)==0 ){
- sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
- }
+ sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
nErr++;
}
pParse->zTail = zSql;
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_free(pParse->apVtabLock);
@@ -182657,10 +182513,14 @@
#endif
sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
sqlite3ValueFree(db->pErr);
sqlite3CloseExtensions(db);
+#if SQLITE_USER_AUTHENTICATION
+ sqlite3_free(db->auth.zAuthUser);
+ sqlite3_free(db->auth.zAuthPW);
+#endif
db->eOpenState = SQLITE_STATE_ERROR;
/* The temp-database schema is allocated differently from the other schema
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
@@ -184091,12 +183951,12 @@
# error SQLITE_MAX_COMPOUND_SELECT must be at least 2
#endif
#if SQLITE_MAX_VDBE_OP<40
# error SQLITE_MAX_VDBE_OP must be at least 40
#endif
-#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>32767
-# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 32767
+#if SQLITE_MAX_FUNCTION_ARG<0 || SQLITE_MAX_FUNCTION_ARG>127
+# error SQLITE_MAX_FUNCTION_ARG must be between 0 and 127
#endif
#if SQLITE_MAX_ATTACHED<0 || SQLITE_MAX_ATTACHED>125
# error SQLITE_MAX_ATTACHED must be between 0 and 125
#endif
#if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
@@ -184159,12 +184019,12 @@
}
oldLimit = db->aLimit[limitId];
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
- }else if( newLimitaLimit[limitId] = newLimit;
}
return oldLimit; /* IMP: R-53341-35419 */
}
@@ -185504,10 +185364,11 @@
rc = x;
#if defined(SQLITE_DEBUG)
/* Invoke these debugging routines so that the compiler does not
** issue "defined but not used" warnings. */
if( x==9999 ){
+ sqlite3ShowExpr(0);
sqlite3ShowExpr(0);
sqlite3ShowExprList(0);
sqlite3ShowIdList(0);
sqlite3ShowSrcList(0);
sqlite3ShowWith(0);
@@ -189935,19 +189796,14 @@
assert_fts3_nc( p!=0 && *p1!=0 && *p2!=0 );
if( *p1==POS_COLUMN ){
p1++;
p1 += fts3GetVarint32(p1, &iCol1);
- /* iCol1==0 indicates corruption. Column 0 does not have a POS_COLUMN
- ** entry, so this is actually end-of-doclist. */
- if( iCol1==0 ) return 0;
}
if( *p2==POS_COLUMN ){
p2++;
p2 += fts3GetVarint32(p2, &iCol2);
- /* As above, iCol2==0 indicates corruption. */
- if( iCol2==0 ) return 0;
}
while( 1 ){
if( iCol1==iCol2 ){
char *pSave = p;
@@ -193114,11 +192970,11 @@
for(p=pExpr; p->pLeft; p=p->pLeft){
assert( p->pRight->pPhrase->doclist.nList>0 );
nTmp += p->pRight->pPhrase->doclist.nList;
}
nTmp += p->pPhrase->doclist.nList;
- aTmp = sqlite3_malloc64(nTmp*2 + FTS3_VARINT_MAX);
+ aTmp = sqlite3_malloc64(nTmp*2);
if( !aTmp ){
*pRc = SQLITE_NOMEM;
res = 0;
}else{
char *aPoslist = p->pPhrase->doclist.pList;
@@ -193765,11 +193621,11 @@
SQLITE_PRIVATE int sqlite3Fts3Corrupt(){
return SQLITE_CORRUPT_VTAB;
}
#endif
-#if !defined(SQLITE_CORE)
+#if !SQLITE_CORE
/*
** Initialize API pointer table, if required.
*/
#ifdef _WIN32
__declspec(dllexport)
@@ -194667,15 +194523,14 @@
rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos);
if( rc==SQLITE_OK ){
Fts3PhraseToken *pToken;
p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken));
+ if( !p ) goto no_mem;
+
zTemp = fts3ReallocOrFree(zTemp, nTemp + nByte);
- if( !zTemp || !p ){
- rc = SQLITE_NOMEM;
- goto getnextstring_out;
- }
+ if( !zTemp ) goto no_mem;
assert( nToken==ii );
pToken = &((Fts3Phrase *)(&p[1]))->aToken[ii];
memset(pToken, 0, sizeof(Fts3PhraseToken));
@@ -194686,51 +194541,53 @@
pToken->isPrefix = (iEndbFirst = (iBegin>0 && zInput[iBegin-1]=='^');
nToken = ii+1;
}
}
+
+ pModule->xClose(pCursor);
+ pCursor = 0;
}
if( rc==SQLITE_DONE ){
int jj;
char *zBuf = 0;
p = fts3ReallocOrFree(p, nSpace + nToken*sizeof(Fts3PhraseToken) + nTemp);
- if( !p ){
- rc = SQLITE_NOMEM;
- goto getnextstring_out;
- }
+ if( !p ) goto no_mem;
memset(p, 0, (char *)&(((Fts3Phrase *)&p[1])->aToken[0])-(char *)p);
p->eType = FTSQUERY_PHRASE;
p->pPhrase = (Fts3Phrase *)&p[1];
p->pPhrase->iColumn = pParse->iDefaultCol;
p->pPhrase->nToken = nToken;
zBuf = (char *)&p->pPhrase->aToken[nToken];
- assert( nTemp==0 || zTemp );
if( zTemp ){
memcpy(zBuf, zTemp, nTemp);
+ sqlite3_free(zTemp);
+ }else{
+ assert( nTemp==0 );
}
for(jj=0; jjpPhrase->nToken; jj++){
p->pPhrase->aToken[jj].z = zBuf;
zBuf += p->pPhrase->aToken[jj].n;
}
rc = SQLITE_OK;
}
- getnextstring_out:
+ *ppExpr = p;
+ return rc;
+no_mem:
+
if( pCursor ){
pModule->xClose(pCursor);
}
sqlite3_free(zTemp);
- if( rc!=SQLITE_OK ){
- sqlite3_free(p);
- p = 0;
- }
- *ppExpr = p;
- return rc;
+ sqlite3_free(p);
+ *ppExpr = 0;
+ return SQLITE_NOMEM;
}
/*
** The output variable *ppExpr is populated with an allocated Fts3Expr
** structure, or set to 0 if the end of the input buffer is reached.
@@ -215538,12 +215395,12 @@
#endif
}
sqlite3_str_append(pOut, "}", 1);
}
errCode = sqlite3_str_errcode(pOut);
- sqlite3_result_error_code(ctx, errCode);
sqlite3_result_text(ctx, sqlite3_str_finish(pOut), -1, sqlite3_free);
+ sqlite3_result_error_code(ctx, errCode);
}
/* This routine implements an SQL function that returns the "depth" parameter
** from the front of a blob that is an r-tree node. For example:
**
@@ -218055,11 +217912,11 @@
return sqlite3_create_function_v2(db, zQueryFunc, -1, SQLITE_ANY,
(void *)pGeomCtx, geomCallback, 0, 0, rtreeFreeCallback
);
}
-#ifndef SQLITE_CORE
+#if !SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
SQLITE_API int sqlite3_rtree_init(
sqlite3 *db,
@@ -218646,11 +218503,11 @@
}
return rc;
}
-#ifndef SQLITE_CORE
+#if !SQLITE_CORE
#ifdef _WIN32
__declspec(dllexport)
#endif
SQLITE_API int sqlite3_icu_init(
sqlite3 *db,
@@ -226320,12 +226177,10 @@
if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){
unsigned char *aPage = sqlite3PagerGetData(pDbPage);
memcpy(aPage, pData, szPage);
pTab->pgnoTrunc = 0;
}
- }else{
- pTab->pgnoTrunc = 0;
}
sqlite3PagerUnref(pDbPage);
return rc;
update_fail:
@@ -226355,15 +226210,11 @@
static int dbpageSync(sqlite3_vtab *pVtab){
DbpageTable *pTab = (DbpageTable *)pVtab;
if( pTab->pgnoTrunc>0 ){
Btree *pBt = pTab->db->aDb[pTab->iDbTrunc].pBt;
Pager *pPager = sqlite3BtreePager(pBt);
- sqlite3BtreeEnter(pBt);
- if( pTab->pgnoTruncpgnoTrunc);
- }
- sqlite3BtreeLeave(pBt);
+ sqlite3PagerTruncateImage(pPager, pTab->pgnoTrunc);
}
pTab->pgnoTrunc = 0;
return SQLITE_OK;
}
@@ -232953,46 +232804,20 @@
#endif /* SQLITE_ENABLE_SESSION && SQLITE_ENABLE_PREUPDATE_HOOK */
/************** End of sqlite3session.c **************************************/
/************** Begin file fts5.c ********************************************/
-/*
-** This, the "fts5.c" source file, is a composite file that is itself
-** assembled from the following files:
-**
-** fts5.h
-** fts5Int.h
-** fts5parse.h <--- Generated from fts5parse.y by Lemon
-** fts5parse.c <--- Generated from fts5parse.y by Lemon
-** fts5_aux.c
-** fts5_buffer.c
-** fts5_config.c
-** fts5_expr.c
-** fts5_hash.c
-** fts5_index.c
-** fts5_main.c
-** fts5_storage.c
-** fts5_tokenize.c
-** fts5_unicode2.c
-** fts5_varint.c
-** fts5_vocab.c
-*/
+
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5)
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
# define NDEBUG 1
#endif
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
# undef NDEBUG
#endif
-#ifdef HAVE_STDINT_H
-/* #include */
-#endif
-#ifdef HAVE_INTTYPES_H
-/* #include */
-#endif
/*
** 2014 May 31
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
@@ -233289,33 +233114,18 @@
** This is used to access token iToken of phrase hit iIdx within the
** current row. If iIdx is less than zero or greater than or equal to the
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
** output variable (*ppToken) is set to point to a buffer containing the
** matching document token, and (*pnToken) to the size of that buffer in
-** bytes.
+** bytes. This API is not available if the specified token matches a
+** prefix query term. In that case both output variables are always set
+** to 0.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
-** This API may be slow in some cases if the token identified by parameters
-** iIdx and iToken matched a prefix token in the query. In most cases, the
-** first call to this API for each prefix token in the query is forced
-** to scan the portion of the full-text index that matches the prefix
-** token to collect the extra data required by this API. If the prefix
-** token matches a large number of token instances in the document set,
-** this may be a performance problem.
-**
-** If the user knows in advance that a query may use this API for a
-** prefix token, FTS5 may be configured to collect all required data as part
-** of the initial querying of the full-text index, avoiding the second scan
-** entirely. This also causes prefix queries that do not use this API to
-** run more slowly and use more memory. FTS5 may be configured in this way
-** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
-** option, or on a per-query basis using the
-** [fts5_insttoken | fts5_insttoken()] user function.
-**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
**
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
** If parameter iCol is less than zero, or greater than or equal to the
@@ -233993,12 +233803,11 @@
int nUsermerge; /* 'usermerge' setting */
int nHashSize; /* Bytes of memory for in-memory hash */
char *zRank; /* Name of rank function */
char *zRankArgs; /* Arguments to rank function */
int bSecureDelete; /* 'secure-delete' */
- int nDeleteMerge; /* 'deletemerge' */
- int bPrefixInsttoken; /* 'prefix-insttoken' */
+ int nDeleteMerge; /* 'deletemerge' */
/* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
char **pzErrmsg;
#ifdef SQLITE_DEBUG
@@ -234251,18 +234060,11 @@
static int sqlite3Fts5StructureTest(Fts5Index*, void*);
/*
** Used by xInstToken():
*/
-static int sqlite3Fts5IterToken(
- Fts5IndexIter *pIndexIter,
- const char *pToken, int nToken,
- i64 iRowid,
- int iCol,
- int iOff,
- const char **ppOut, int *pnOut
-);
+static int sqlite3Fts5IterToken(Fts5IndexIter*, i64, int, int, const char**, int*);
/*
** Insert or remove data to or from the index. Each time a document is
** added to or removed from the index, this function is called one or more
** times.
@@ -238472,23 +238274,10 @@
if( bVal<0 ){
*pbBadkey = 1;
}else{
pConfig->bSecureDelete = (bVal ? 1 : 0);
}
- }
-
- else if( 0==sqlite3_stricmp(zKey, "insttoken") ){
- int bVal = -1;
- if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
- bVal = sqlite3_value_int(pVal);
- }
- if( bVal<0 ){
- *pbBadkey = 1;
- }else{
- pConfig->bPrefixInsttoken = (bVal ? 1 : 0);
- }
-
}else{
*pbBadkey = 1;
}
return rc;
}
@@ -241620,11 +241409,11 @@
&& memcmp(pT->pTerm, pToken, pT->nQueryTerm)==0
){
int rc = sqlite3Fts5PoslistWriterAppend(
&pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
);
- if( rc==SQLITE_OK && (pExpr->pConfig->bTokendata || pT->bPrefix) ){
+ if( rc==SQLITE_OK && pExpr->pConfig->bTokendata && !pT->bPrefix ){
int iCol = p->iOff>>32;
int iTokOff = p->iOff & 0x7FFFFFFF;
rc = sqlite3Fts5IndexIterWriteTokendata(
pT->pIter, pToken, nToken, iRowid, iCol, iTokOff
);
@@ -241813,18 +241602,19 @@
pPhrase = pExpr->apExprPhrase[iPhrase];
if( iToken<0 || iToken>=pPhrase->nTerm ){
return SQLITE_RANGE;
}
pTerm = &pPhrase->aTerm[iToken];
- if( pExpr->pConfig->bTokendata || pTerm->bPrefix ){
- rc = sqlite3Fts5IterToken(
- pTerm->pIter, pTerm->pTerm, pTerm->nQueryTerm,
- iRowid, iCol, iOff+iToken, ppOut, pnOut
- );
- }else{
- *ppOut = pTerm->pTerm;
- *pnOut = pTerm->nFullTerm;
+ if( pTerm->bPrefix==0 ){
+ if( pExpr->pConfig->bTokendata ){
+ rc = sqlite3Fts5IterToken(
+ pTerm->pIter, iRowid, iCol, iOff+iToken, ppOut, pnOut
+ );
+ }else{
+ *ppOut = pTerm->pTerm;
+ *pnOut = pTerm->nFullTerm;
+ }
}
return rc;
}
/*
@@ -248635,387 +248425,10 @@
fts5BufferFree(&tmp);
memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
*p1 = out;
}
-
-/*
-** Iterate through a range of entries in the FTS index, invoking the xVisit
-** callback for each of them.
-**
-** Parameter pToken points to an nToken buffer containing an FTS index term
-** (i.e. a document term with the preceding 1 byte index identifier -
-** FTS5_MAIN_PREFIX or similar). If bPrefix is true, then the call visits
-** all entries for terms that have pToken/nToken as a prefix. If bPrefix
-** is false, then only entries with pToken/nToken as the entire key are
-** visited.
-**
-** If the current table is a tokendata=1 table, then if bPrefix is true then
-** each index term is treated separately. However, if bPrefix is false, then
-** all index terms corresponding to pToken/nToken are collapsed into a single
-** term before the callback is invoked.
-**
-** The callback invoked for each entry visited is specified by paramter xVisit.
-** Each time it is invoked, it is passed a pointer to the Fts5Index object,
-** a copy of the 7th paramter to this function (pCtx) and a pointer to the
-** iterator that indicates the current entry. If the current entry is the
-** first with a new term (i.e. different from that of the previous entry,
-** including the very first term), then the final two parameters are passed
-** a pointer to the term and its size in bytes, respectively. If the current
-** entry is not the first associated with its term, these two parameters
-** are passed 0.
-**
-** If parameter pColset is not NULL, then it is used to filter entries before
-** the callback is invoked.
-*/
-static int fts5VisitEntries(
- Fts5Index *p, /* Fts5 index object */
- Fts5Colset *pColset, /* Columns filter to apply, or NULL */
- u8 *pToken, /* Buffer containing token */
- int nToken, /* Size of buffer pToken in bytes */
- int bPrefix, /* True for a prefix scan */
- void (*xVisit)(Fts5Index*, void *pCtx, Fts5Iter *pIter, const u8*, int),
- void *pCtx /* Passed as second argument to xVisit() */
-){
- const int flags = (bPrefix ? FTS5INDEX_QUERY_SCAN : 0)
- | FTS5INDEX_QUERY_SKIPEMPTY
- | FTS5INDEX_QUERY_NOOUTPUT;
- Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
- int bNewTerm = 1;
- Fts5Structure *pStruct = fts5StructureRead(p);
-
- fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
- fts5IterSetOutputCb(&p->rc, p1);
- for( /* no-op */ ;
- fts5MultiIterEof(p, p1)==0;
- fts5MultiIterNext2(p, p1, &bNewTerm)
- ){
- Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
- int nNew = 0;
- const u8 *pNew = 0;
-
- p1->xSetOutputs(p1, pSeg);
- if( p->rc ) break;
-
- if( bNewTerm ){
- nNew = pSeg->term.n;
- pNew = pSeg->term.p;
- if( nNewrc;
-}
-
-
-/*
-** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
-** array of these for each row it visits (so all iRowid fields are the same).
-** Or, for an iterator used by an "ORDER BY rank" query, it accumulates an
-** array of these for the entire query (in which case iRowid fields may take
-** a variety of values).
-**
-** Each instance in the array indicates the iterator (and therefore term)
-** associated with position iPos of rowid iRowid. This is used by the
-** xInstToken() API.
-**
-** iRowid:
-** Rowid for the current entry.
-**
-** iPos:
-** Position of current entry within row. In the usual ((iCol<<32)+iOff)
-** format (e.g. see macros FTS5_POS2COLUMN() and FTS5_POS2OFFSET()).
-**
-** iIter:
-** If the Fts5TokenDataIter iterator that the entry is part of is
-** actually an iterator (i.e. with nIter>0, not just a container for
-** Fts5TokenDataMap structures), then this variable is an index into
-** the apIter[] array. The corresponding term is that which the iterator
-** at apIter[iIter] currently points to.
-**
-** Or, if the Fts5TokenDataIter iterator is just a container object
-** (nIter==0), then iIter is an index into the term.p[] buffer where
-** the term is stored.
-**
-** nByte:
-** In the case where iIter is an index into term.p[], this variable
-** is the size of the term in bytes. If iIter is an index into apIter[],
-** this variable is unused.
-*/
-struct Fts5TokenDataMap {
- i64 iRowid; /* Row this token is located in */
- i64 iPos; /* Position of token */
- int iIter; /* Iterator token was read from */
- int nByte; /* Length of token in bytes (or 0) */
-};
-
-/*
-** An object used to supplement Fts5Iter for tokendata=1 iterators.
-**
-** This object serves two purposes. The first is as a container for an array
-** of Fts5TokenDataMap structures, which are used to find the token required
-** when the xInstToken() API is used. This is done by the nMapAlloc, nMap and
-** aMap[] variables.
-*/
-struct Fts5TokenDataIter {
- int nMapAlloc; /* Allocated size of aMap[] in entries */
- int nMap; /* Number of valid entries in aMap[] */
- Fts5TokenDataMap *aMap; /* Array of (rowid+pos -> token) mappings */
-
- /* The following are used for prefix-queries only. */
- Fts5Buffer terms;
-
- /* The following are used for other full-token tokendata queries only. */
- int nIter;
- int nIterAlloc;
- Fts5PoslistReader *aPoslistReader;
- int *aPoslistToIter;
- Fts5Iter *apIter[1];
-};
-
-/*
-** The two input arrays - a1[] and a2[] - are in sorted order. This function
-** merges the two arrays together and writes the result to output array
-** aOut[]. aOut[] is guaranteed to be large enough to hold the result.
-**
-** Duplicate entries are copied into the output. So the size of the output
-** array is always (n1+n2) entries.
-*/
-static void fts5TokendataMerge(
- Fts5TokenDataMap *a1, int n1, /* Input array 1 */
- Fts5TokenDataMap *a2, int n2, /* Input array 2 */
- Fts5TokenDataMap *aOut /* Output array */
-){
- int i1 = 0;
- int i2 = 0;
-
- assert( n1>=0 && n2>=0 );
- while( i1=n2 || (i1rc==SQLITE_OK ){
- if( pT->nMap==pT->nMapAlloc ){
- int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
- int nAlloc = nNew * sizeof(Fts5TokenDataMap);
- Fts5TokenDataMap *aNew;
-
- aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nAlloc);
- if( aNew==0 ){
- p->rc = SQLITE_NOMEM;
- return;
- }
-
- pT->aMap = aNew;
- pT->nMapAlloc = nNew;
- }
-
- pT->aMap[pT->nMap].iRowid = iRowid;
- pT->aMap[pT->nMap].iPos = iPos;
- pT->aMap[pT->nMap].iIter = iIter;
- pT->aMap[pT->nMap].nByte = nByte;
- pT->nMap++;
- }
-}
-
-/*
-** Sort the contents of the pT->aMap[] array.
-**
-** The sorting algorithm requries a malloc(). If this fails, an error code
-** is left in Fts5Index.rc before returning.
-*/
-static void fts5TokendataIterSortMap(Fts5Index *p, Fts5TokenDataIter *pT){
- Fts5TokenDataMap *aTmp = 0;
- int nByte = pT->nMap * sizeof(Fts5TokenDataMap);
-
- aTmp = (Fts5TokenDataMap*)sqlite3Fts5MallocZero(&p->rc, nByte);
- if( aTmp ){
- Fts5TokenDataMap *a1 = pT->aMap;
- Fts5TokenDataMap *a2 = aTmp;
- i64 nHalf;
-
- for(nHalf=1; nHalfnMap; nHalf=nHalf*2){
- int i1;
- for(i1=0; i1nMap; i1+=(nHalf*2)){
- int n1 = MIN(nHalf, pT->nMap-i1);
- int n2 = MIN(nHalf, pT->nMap-i1-n1);
- fts5TokendataMerge(&a1[i1], n1, &a1[i1+n1], n2, &a2[i1]);
- }
- SWAPVAL(Fts5TokenDataMap*, a1, a2);
- }
-
- if( a1!=pT->aMap ){
- memcpy(pT->aMap, a1, pT->nMap*sizeof(Fts5TokenDataMap));
- }
- sqlite3_free(aTmp);
-
-#ifdef SQLITE_DEBUG
- {
- int ii;
- for(ii=1; iinMap; ii++){
- Fts5TokenDataMap *p1 = &pT->aMap[ii-1];
- Fts5TokenDataMap *p2 = &pT->aMap[ii];
- assert( p1->iRowidiRowid
- || (p1->iRowid==p2->iRowid && p1->iPos<=p2->iPos)
- );
- }
- }
-#endif
- }
-}
-
-/*
-** Delete an Fts5TokenDataIter structure and its contents.
-*/
-static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
- if( pSet ){
- int ii;
- for(ii=0; iinIter; ii++){
- fts5MultiIterFree(pSet->apIter[ii]);
- }
- fts5BufferFree(&pSet->terms);
- sqlite3_free(pSet->aPoslistReader);
- sqlite3_free(pSet->aMap);
- sqlite3_free(pSet);
- }
-}
-
-
-/*
-** fts5VisitEntries() context object used by fts5SetupPrefixIterTokendata()
-** to pass data to prefixIterSetupTokendataCb().
-*/
-typedef struct TokendataSetupCtx TokendataSetupCtx;
-struct TokendataSetupCtx {
- Fts5TokenDataIter *pT; /* Object being populated with mappings */
- int iTermOff; /* Offset of current term in terms.p[] */
- int nTermByte; /* Size of current term in bytes */
-};
-
-/*
-** fts5VisitEntries() callback used by fts5SetupPrefixIterTokendata(). This
-** callback adds an entry to the Fts5TokenDataIter.aMap[] array for each
-** position in the current position-list. It doesn't matter that some of
-** these may be out of order - they will be sorted later.
-*/
-static void prefixIterSetupTokendataCb(
- Fts5Index *p,
- void *pCtx,
- Fts5Iter *p1,
- const u8 *pNew,
- int nNew
-){
- TokendataSetupCtx *pSetup = (TokendataSetupCtx*)pCtx;
- int iPosOff = 0;
- i64 iPos = 0;
-
- if( pNew ){
- pSetup->nTermByte = nNew-1;
- pSetup->iTermOff = pSetup->pT->terms.n;
- fts5BufferAppendBlob(&p->rc, &pSetup->pT->terms, nNew-1, pNew+1);
- }
-
- while( 0==sqlite3Fts5PoslistNext64(
- p1->base.pData, p1->base.nData, &iPosOff, &iPos
- ) ){
- fts5TokendataIterAppendMap(p,
- pSetup->pT, pSetup->iTermOff, pSetup->nTermByte, p1->base.iRowid, iPos
- );
- }
-}
-
-
-/*
-** Context object passed by fts5SetupPrefixIter() to fts5VisitEntries().
-*/
-typedef struct PrefixSetupCtx PrefixSetupCtx;
-struct PrefixSetupCtx {
- void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
- void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
- i64 iLastRowid;
- int nMerge;
- Fts5Buffer *aBuf;
- int nBuf;
- Fts5Buffer doclist;
- TokendataSetupCtx *pTokendata;
-};
-
-/*
-** fts5VisitEntries() callback used by fts5SetupPrefixIter()
-*/
-static void prefixIterSetupCb(
- Fts5Index *p,
- void *pCtx,
- Fts5Iter *p1,
- const u8 *pNew,
- int nNew
-){
- PrefixSetupCtx *pSetup = (PrefixSetupCtx*)pCtx;
- const int nMerge = pSetup->nMerge;
-
- if( p1->base.nData>0 ){
- if( p1->base.iRowid<=pSetup->iLastRowid && pSetup->doclist.n>0 ){
- int i;
- for(i=0; p->rc==SQLITE_OK && pSetup->doclist.n; i++){
- int i1 = i*nMerge;
- int iStore;
- assert( i1+nMerge<=pSetup->nBuf );
- for(iStore=i1; iStoreaBuf[iStore].n==0 ){
- fts5BufferSwap(&pSetup->doclist, &pSetup->aBuf[iStore]);
- fts5BufferZero(&pSetup->doclist);
- break;
- }
- }
- if( iStore==i1+nMerge ){
- pSetup->xMerge(p, &pSetup->doclist, nMerge, &pSetup->aBuf[i1]);
- for(iStore=i1; iStoreaBuf[iStore]);
- }
- }
- }
- pSetup->iLastRowid = 0;
- }
-
- pSetup->xAppend(
- p, (u64)p1->base.iRowid-(u64)pSetup->iLastRowid, p1, &pSetup->doclist
- );
- pSetup->iLastRowid = p1->base.iRowid;
- }
-
- if( pSetup->pTokendata ){
- prefixIterSetupTokendataCb(p, (void*)pSetup->pTokendata, p1, pNew, nNew);
- }
-}
-
static void fts5SetupPrefixIter(
Fts5Index *p, /* Index to read from */
int bDesc, /* True for "ORDER BY rowid DESC" */
int iIdx, /* Index to scan for data */
u8 *pToken, /* Buffer containing prefix to match */
@@ -249022,91 +248435,137 @@
int nToken, /* Size of buffer pToken in bytes */
Fts5Colset *pColset, /* Restrict matches to these columns */
Fts5Iter **ppIter /* OUT: New iterator */
){
Fts5Structure *pStruct;
- PrefixSetupCtx s;
- TokendataSetupCtx s2;
-
- memset(&s, 0, sizeof(s));
- memset(&s2, 0, sizeof(s2));
-
- s.nMerge = 1;
- s.iLastRowid = 0;
- s.nBuf = 32;
- if( iIdx==0
- && p->pConfig->eDetail==FTS5_DETAIL_FULL
- && p->pConfig->bPrefixInsttoken
- ){
- s.pTokendata = &s2;
- s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
- }
-
+ Fts5Buffer *aBuf;
+ int nBuf = 32;
+ int nMerge = 1;
+
+ void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
+ void (*xAppend)(Fts5Index*, u64, Fts5Iter*, Fts5Buffer*);
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
- s.xMerge = fts5MergeRowidLists;
- s.xAppend = fts5AppendRowid;
+ xMerge = fts5MergeRowidLists;
+ xAppend = fts5AppendRowid;
}else{
- s.nMerge = FTS5_MERGE_NLIST-1;
- s.nBuf = s.nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
- s.xMerge = fts5MergePrefixLists;
- s.xAppend = fts5AppendPoslist;
+ nMerge = FTS5_MERGE_NLIST-1;
+ nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
+ xMerge = fts5MergePrefixLists;
+ xAppend = fts5AppendPoslist;
}
- s.aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*s.nBuf);
+ aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
pStruct = fts5StructureRead(p);
- assert( p->rc!=SQLITE_OK || (s.aBuf && pStruct) );
+ assert( p->rc!=SQLITE_OK || (aBuf && pStruct) );
if( p->rc==SQLITE_OK ){
- void *pCtx = (void*)&s;
+ const int flags = FTS5INDEX_QUERY_SCAN
+ | FTS5INDEX_QUERY_SKIPEMPTY
+ | FTS5INDEX_QUERY_NOOUTPUT;
int i;
+ i64 iLastRowid = 0;
+ Fts5Iter *p1 = 0; /* Iterator used to gather data from index */
Fts5Data *pData;
+ Fts5Buffer doclist;
+ int bNewTerm = 1;
+
+ memset(&doclist, 0, sizeof(doclist));
/* If iIdx is non-zero, then it is the number of a prefix-index for
** prefixes 1 character longer than the prefix being queried for. That
** index contains all the doclists required, except for the one
** corresponding to the prefix itself. That one is extracted from the
** main term index here. */
if( iIdx!=0 ){
+ int dummy = 0;
+ const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
pToken[0] = FTS5_MAIN_PREFIX;
- fts5VisitEntries(p, pColset, pToken, nToken, 0, prefixIterSetupCb, pCtx);
+ fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
+ fts5IterSetOutputCb(&p->rc, p1);
+ for(;
+ fts5MultiIterEof(p, p1)==0;
+ fts5MultiIterNext2(p, p1, &dummy)
+ ){
+ Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
+ p1->xSetOutputs(p1, pSeg);
+ if( p1->base.nData ){
+ xAppend(p, (u64)p1->base.iRowid-(u64)iLastRowid, p1, &doclist);
+ iLastRowid = p1->base.iRowid;
+ }
+ }
+ fts5MultiIterFree(p1);
}
pToken[0] = FTS5_MAIN_PREFIX + iIdx;
- fts5VisitEntries(p, pColset, pToken, nToken, 1, prefixIterSetupCb, pCtx);
+ fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
+ fts5IterSetOutputCb(&p->rc, p1);
- assert( (s.nBuf%s.nMerge)==0 );
- for(i=0; iaSeg[ p1->aFirst[1].iFirst ];
+ int nTerm = pSeg->term.n;
+ const u8 *pTerm = pSeg->term.p;
+ p1->xSetOutputs(p1, pSeg);
+
+ assert_nc( memcmp(pToken, pTerm, MIN(nToken, nTerm))<=0 );
+ if( bNewTerm ){
+ if( nTermbase.nData==0 ) continue;
+ if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
+ for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
+ int i1 = i*nMerge;
+ int iStore;
+ assert( i1+nMerge<=nBuf );
+ for(iStore=i1; iStorebase.iRowid-(u64)iLastRowid, p1, &doclist);
+ iLastRowid = p1->base.iRowid;
+ }
+
+ assert( (nBuf%nMerge)==0 );
+ for(i=0; irc==SQLITE_OK ){
- s.xMerge(p, &s.doclist, s.nMerge, &s.aBuf[i]);
+ xMerge(p, &doclist, nMerge, &aBuf[i]);
}
- for(iFree=i; iFreerc!=SQLITE_OK );
+ pData = fts5IdxMalloc(p, sizeof(*pData)+doclist.n+FTS5_DATA_ZERO_PADDING);
if( pData ){
pData->p = (u8*)&pData[1];
- pData->nn = pData->szLeaf = s.doclist.n;
- if( s.doclist.n ) memcpy(pData->p, s.doclist.p, s.doclist.n);
+ pData->nn = pData->szLeaf = doclist.n;
+ if( doclist.n ) memcpy(pData->p, doclist.p, doclist.n);
fts5MultiIterNew2(p, pData, bDesc, ppIter);
}
-
- assert( (*ppIter)!=0 || p->rc!=SQLITE_OK );
- if( p->rc==SQLITE_OK && s.pTokendata ){
- fts5TokendataIterSortMap(p, s2.pT);
- (*ppIter)->pTokenDataIter = s2.pT;
- s2.pT = 0;
- }
+ fts5BufferFree(&doclist);
}
- fts5TokendataIterDelete(s2.pT);
- fts5BufferFree(&s.doclist);
fts5StructureRelease(pStruct);
- sqlite3_free(s.aBuf);
+ sqlite3_free(aBuf);
}
/*
** Indicate that all subsequent calls to sqlite3Fts5IndexWrite() pertain
@@ -249356,10 +248815,42 @@
static void fts5SegIterSetEOF(Fts5SegIter *pSeg){
fts5DataRelease(pSeg->pLeaf);
pSeg->pLeaf = 0;
}
+/*
+** Usually, a tokendata=1 iterator (struct Fts5TokenDataIter) accumulates an
+** array of these for each row it visits. Or, for an iterator used by an
+** "ORDER BY rank" query, it accumulates an array of these for the entire
+** query.
+**
+** Each instance in the array indicates the iterator (and therefore term)
+** associated with position iPos of rowid iRowid. This is used by the
+** xInstToken() API.
+*/
+struct Fts5TokenDataMap {
+ i64 iRowid; /* Row this token is located in */
+ i64 iPos; /* Position of token */
+ int iIter; /* Iterator token was read from */
+};
+
+/*
+** An object used to supplement Fts5Iter for tokendata=1 iterators.
+*/
+struct Fts5TokenDataIter {
+ int nIter;
+ int nIterAlloc;
+
+ int nMap;
+ int nMapAlloc;
+ Fts5TokenDataMap *aMap;
+
+ Fts5PoslistReader *aPoslistReader;
+ int *aPoslistToIter;
+ Fts5Iter *apIter[1];
+};
+
/*
** This function appends iterator pAppend to Fts5TokenDataIter pIn and
** returns the result.
*/
static Fts5TokenDataIter *fts5AppendTokendataIter(
@@ -249391,10 +248882,58 @@
}
assert( pRet==0 || pRet->nIter<=pRet->nIterAlloc );
return pRet;
}
+
+/*
+** Delete an Fts5TokenDataIter structure and its contents.
+*/
+static void fts5TokendataIterDelete(Fts5TokenDataIter *pSet){
+ if( pSet ){
+ int ii;
+ for(ii=0; iinIter; ii++){
+ fts5MultiIterFree(pSet->apIter[ii]);
+ }
+ sqlite3_free(pSet->aPoslistReader);
+ sqlite3_free(pSet->aMap);
+ sqlite3_free(pSet);
+ }
+}
+
+/*
+** Append a mapping to the token-map belonging to object pT.
+*/
+static void fts5TokendataIterAppendMap(
+ Fts5Index *p,
+ Fts5TokenDataIter *pT,
+ int iIter,
+ i64 iRowid,
+ i64 iPos
+){
+ if( p->rc==SQLITE_OK ){
+ if( pT->nMap==pT->nMapAlloc ){
+ int nNew = pT->nMapAlloc ? pT->nMapAlloc*2 : 64;
+ int nByte = nNew * sizeof(Fts5TokenDataMap);
+ Fts5TokenDataMap *aNew;
+
+ aNew = (Fts5TokenDataMap*)sqlite3_realloc(pT->aMap, nByte);
+ if( aNew==0 ){
+ p->rc = SQLITE_NOMEM;
+ return;
+ }
+
+ pT->aMap = aNew;
+ pT->nMapAlloc = nNew;
+ }
+
+ pT->aMap[pT->nMap].iRowid = iRowid;
+ pT->aMap[pT->nMap].iPos = iPos;
+ pT->aMap[pT->nMap].iIter = iIter;
+ pT->nMap++;
+ }
+}
/*
** The iterator passed as the only argument must be a tokendata=1 iterator
** (pIter->pTokenDataIter!=0). This function sets the iterator output
** variables (pIter->base.*) according to the contents of the current
@@ -249432,11 +248971,11 @@
int eDetail = pIter->pIndex->pConfig->eDetail;
pIter->base.bEof = 0;
pIter->base.iRowid = iRowid;
if( nHit==1 && eDetail==FTS5_DETAIL_FULL ){
- fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, 0, iRowid, -1);
+ fts5TokendataIterAppendMap(pIter->pIndex, pT, iMin, iRowid, -1);
}else
if( nHit>1 && eDetail!=FTS5_DETAIL_NONE ){
int nReader = 0;
int nByte = 0;
i64 iPrev = 0;
@@ -249685,11 +249224,10 @@
if( p->rc==SQLITE_OK ){
pRet = fts5MultiIterAlloc(p, 0);
}
if( pRet ){
- pRet->nSeg = 0;
pRet->pTokenDataIter = pSet;
if( pSet ){
fts5IterSetOutputsTokendata(pRet);
}else{
pRet->base.bEof = 1;
@@ -249700,10 +249238,11 @@
fts5StructureRelease(pStruct);
fts5BufferFree(&bSeek);
return pRet;
}
+
/*
** Open a new iterator to iterate though all rowid that match the
** specified token or token prefix.
*/
@@ -249723,18 +249262,12 @@
if( sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
int iPrefixIdx = 0; /* +1 prefix index */
int bTokendata = pConfig->bTokendata;
- assert( buf.p!=0 );
if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
- /* The NOTOKENDATA flag is set when each token in a tokendata=1 table
- ** should be treated individually, instead of merging all those with
- ** a common prefix into a single entry. This is used, for example, by
- ** queries performed as part of an integrity-check, or by the fts5vocab
- ** module. */
if( flags & (FTS5INDEX_QUERY_NOTOKENDATA|FTS5INDEX_QUERY_SCAN) ){
bTokendata = 0;
}
/* Figure out which index to search and set iIdx accordingly. If this
@@ -249761,11 +249294,11 @@
if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
}
}
if( bTokendata && iIdx==0 ){
- buf.p[0] = FTS5_MAIN_PREFIX;
+ buf.p[0] = '0';
pRet = fts5SetupTokendataIter(p, buf.p, nToken+1, pColset);
}else if( iIdx<=pConfig->nPrefix ){
/* Straight index lookup */
Fts5Structure *pStruct = fts5StructureRead(p);
buf.p[0] = (u8)(FTS5_MAIN_PREFIX + iIdx);
@@ -249774,11 +249307,11 @@
pColset, buf.p, nToken+1, -1, 0, &pRet
);
fts5StructureRelease(pStruct);
}
}else{
- /* Scan multiple terms in the main index for a prefix query. */
+ /* Scan multiple terms in the main index */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
if( pRet==0 ){
assert( p->rc!=SQLITE_OK );
}else{
@@ -249810,12 +249343,11 @@
** Move to the next matching rowid.
*/
static int sqlite3Fts5IterNext(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
assert( pIter->pIndex->rc==SQLITE_OK );
- if( pIter->nSeg==0 ){
- assert( pIter->pTokenDataIter );
+ if( pIter->pTokenDataIter ){
fts5TokendataIterNext(pIter, 0, 0);
}else{
fts5MultiIterNext(pIter->pIndex, pIter, 0, 0);
}
return fts5IndexReturn(pIter->pIndex);
@@ -249848,12 +249380,11 @@
** definition of "at or after" depends on whether this iterator iterates
** in ascending or descending rowid order.
*/
static int sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMatch){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- if( pIter->nSeg==0 ){
- assert( pIter->pTokenDataIter );
+ if( pIter->pTokenDataIter ){
fts5TokendataIterNext(pIter, 1, iMatch);
}else{
fts5MultiIterNextFrom(pIter->pIndex, pIter, iMatch);
}
return fts5IndexReturn(pIter->pIndex);
@@ -249868,88 +249399,32 @@
assert_nc( z || n<=1 );
*pn = n-1;
return (z ? &z[1] : 0);
}
-/*
-** pIter is a prefix query. This function populates pIter->pTokenDataIter
-** with an Fts5TokenDataIter object containing mappings for all rows
-** matched by the query.
-*/
-static int fts5SetupPrefixIterTokendata(
- Fts5Iter *pIter,
- const char *pToken, /* Token prefix to search for */
- int nToken /* Size of pToken in bytes */
-){
- Fts5Index *p = pIter->pIndex;
- Fts5Buffer token = {0, 0, 0};
- TokendataSetupCtx ctx;
-
- memset(&ctx, 0, sizeof(ctx));
-
- fts5BufferGrow(&p->rc, &token, nToken+1);
- assert( token.p!=0 || p->rc!=SQLITE_OK );
- ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
-
- if( p->rc==SQLITE_OK ){
-
- /* Fill in the token prefix to search for */
- token.p[0] = FTS5_MAIN_PREFIX;
- memcpy(&token.p[1], pToken, nToken);
- token.n = nToken+1;
-
- fts5VisitEntries(
- p, 0, token.p, token.n, 1, prefixIterSetupTokendataCb, (void*)&ctx
- );
-
- fts5TokendataIterSortMap(p, ctx.pT);
- }
-
- if( p->rc==SQLITE_OK ){
- pIter->pTokenDataIter = ctx.pT;
- }else{
- fts5TokendataIterDelete(ctx.pT);
- }
- fts5BufferFree(&token);
-
- return fts5IndexReturn(p);
-}
-
/*
** This is used by xInstToken() to access the token at offset iOff, column
** iCol of row iRowid. The token is returned via output variables *ppOut
** and *pnOut. The iterator passed as the first argument must be a tokendata=1
** iterator (pIter->pTokenDataIter!=0).
-**
-** pToken/nToken:
*/
static int sqlite3Fts5IterToken(
Fts5IndexIter *pIndexIter,
- const char *pToken, int nToken,
i64 iRowid,
int iCol,
int iOff,
const char **ppOut, int *pnOut
){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
+ Fts5TokenDataMap *aMap = pT->aMap;
i64 iPos = (((i64)iCol)<<32) + iOff;
- Fts5TokenDataMap *aMap = 0;
+
int i1 = 0;
- int i2 = 0;
+ int i2 = pT->nMap;
int iTest = 0;
- assert( pT || (pToken && pIter->nSeg>0) );
- if( pT==0 ){
- int rc = fts5SetupPrefixIterTokendata(pIter, pToken, nToken);
- if( rc!=SQLITE_OK ) return rc;
- pT = pIter->pTokenDataIter;
- }
-
- i2 = pT->nMap;
- aMap = pT->aMap;
-
while( i2>i1 ){
iTest = (i1 + i2) / 2;
if( aMap[iTest].iRowidi1 ){
- if( pIter->nSeg==0 ){
- Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
- *ppOut = (const char*)pMap->aSeg[0].term.p+1;
- *pnOut = pMap->aSeg[0].term.n-1;
- }else{
- Fts5TokenDataMap *p = &aMap[iTest];
- *ppOut = (const char*)&pT->terms.p[p->iIter];
- *pnOut = aMap[iTest].nByte;
- }
+ Fts5Iter *pMap = pT->apIter[aMap[iTest].iIter];
+ *ppOut = (const char*)pMap->aSeg[0].term.p+1;
+ *pnOut = pMap->aSeg[0].term.n-1;
}
return SQLITE_OK;
}
@@ -249988,13 +249457,11 @@
** Clear any existing entries from the token-map associated with the
** iterator passed as the only argument.
*/
static void sqlite3Fts5IndexIterClearTokendata(Fts5IndexIter *pIndexIter){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
- if( pIter && pIter->pTokenDataIter
- && (pIter->nSeg==0 || pIter->pIndex->pConfig->eDetail!=FTS5_DETAIL_FULL)
- ){
+ if( pIter && pIter->pTokenDataIter ){
pIter->pTokenDataIter->nMap = 0;
}
}
/*
@@ -250010,33 +249477,21 @@
i64 iRowid, int iCol, int iOff
){
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
Fts5TokenDataIter *pT = pIter->pTokenDataIter;
Fts5Index *p = pIter->pIndex;
- i64 iPos = (((i64)iCol)<<32) + iOff;
+ int ii;
assert( p->pConfig->eDetail!=FTS5_DETAIL_FULL );
- assert( pIter->pTokenDataIter || pIter->nSeg>0 );
- if( pIter->nSeg>0 ){
- /* This is a prefix term iterator. */
- if( pT==0 ){
- pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
- pIter->pTokenDataIter = pT;
- }
- if( pT ){
- fts5TokendataIterAppendMap(p, pT, pT->terms.n, nToken, iRowid, iPos);
- fts5BufferAppendBlob(&p->rc, &pT->terms, nToken, (const u8*)pToken);
- }
- }else{
- int ii;
- for(ii=0; iinIter; ii++){
- Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
- if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
- }
- if( iinIter ){
- fts5TokendataIterAppendMap(p, pT, ii, 0, iRowid, iPos);
- }
+ assert( pIter->pTokenDataIter );
+
+ for(ii=0; iinIter; ii++){
+ Fts5Buffer *pTerm = &pT->apIter[ii]->aSeg[0].term;
+ if( nToken==pTerm->n-1 && memcmp(pToken, pTerm->p+1, nToken)==0 ) break;
+ }
+ if( iinIter ){
+ fts5TokendataIterAppendMap(p, pT, ii, iRowid, (((i64)iCol)<<32) + iOff);
}
return fts5IndexReturn(p);
}
/*
@@ -251937,11 +251392,10 @@
** containing a copy of the header from an Fts5Config pointer.
*/
#define FTS5_LOCALE_HDR_SIZE ((int)sizeof( ((Fts5Global*)0)->aLocaleHdr ))
#define FTS5_LOCALE_HDR(pConfig) ((const u8*)(pConfig->pGlobal->aLocaleHdr))
-#define FTS5_INSTTOKEN_SUBTYPE 73
/*
** Each auxiliary function registered with the FTS5 module is represented
** by an object of the following type. All such objects are stored as part
** of the Fts5Global.pAux list.
@@ -252477,11 +251931,10 @@
){
/* A MATCH operator or equivalent */
if( p->usable==0 || iCol<0 ){
/* As there exists an unusable MATCH constraint this is an
** unusable plan. Return SQLITE_CONSTRAINT. */
- idxStr[iIdxStr] = 0;
return SQLITE_CONSTRAINT;
}else{
if( iCol==nCol+1 ){
if( bSeenRank ) continue;
idxStr[iIdxStr++] = 'r';
@@ -253263,11 +252716,10 @@
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
int iCol; /* Column on LHS of MATCH operator */
char **pzErrmsg = pConfig->pzErrmsg;
- int bPrefixInsttoken = pConfig->bPrefixInsttoken;
int i;
int iIdxStr = 0;
Fts5Expr *pExpr = 0;
assert( pConfig->bLock==0 );
@@ -253299,13 +252751,10 @@
int bInternal = 0;
rc = fts5ExtractExprText(pConfig, apVal[i], &zText, &bFreeAndReset);
if( rc!=SQLITE_OK ) goto filter_out;
if( zText==0 ) zText = "";
- if( sqlite3_value_subtype(apVal[i])==FTS5_INSTTOKEN_SUBTYPE ){
- pConfig->bPrefixInsttoken = 1;
- }
iCol = 0;
do{
iCol = iCol*10 + (idxStr[iIdxStr]-'0');
iIdxStr++;
@@ -253442,11 +252891,10 @@
}
filter_out:
sqlite3Fts5ExprFree(pExpr);
pConfig->pzErrmsg = pzErrmsg;
- pConfig->bPrefixInsttoken = bPrefixInsttoken;
return rc;
}
/*
** This is the xEof method of the virtual table. SQLite calls this
@@ -255438,11 +254886,11 @@
int nArg, /* Number of args */
sqlite3_value **apUnused /* Function arguments */
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlite3_result_text(pCtx, "fts5: 2024-12-30 21:23:53 2b17bc49655c577029919c2d409de994b0d252f8efb5da1ba0913f2c96bee552", -1, SQLITE_TRANSIENT);
+ sqlite3_result_text(pCtx, "fts5: 2024-10-18 12:31:21 a31a94644113c226a06316a3f95fb38b605821f1c123e2cda06ba90bfcacf59f", -1, SQLITE_TRANSIENT);
}
/*
** Implementation of fts5_locale(LOCALE, TEXT) function.
**
@@ -255502,24 +254950,10 @@
sqlite3_result_blob(pCtx, pBlob, nBlob, sqlite3_free);
}
}
-/*
-** Implementation of fts5_insttoken() function.
-*/
-static void fts5InsttokenFunc(
- sqlite3_context *pCtx, /* Function call context */
- int nArg, /* Number of args */
- sqlite3_value **apArg /* Function arguments */
-){
- assert( nArg==1 );
- (void)nArg;
- sqlite3_result_value(pCtx, apArg[0]);
- sqlite3_result_subtype(pCtx, FTS5_INSTTOKEN_SUBTYPE);
-}
-
/*
** Return true if zName is the extension on one of the shadow tables used
** by this module.
*/
static int fts5ShadowName(const char *zName){
@@ -255645,19 +255079,12 @@
);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5_locale", 2,
- SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE|SQLITE_SUBTYPE,
- p, fts5LocaleFunc, 0, 0
- );
- }
- if( rc==SQLITE_OK ){
- rc = sqlite3_create_function(
- db, "fts5_insttoken", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_RESULT_SUBTYPE,
- p, fts5InsttokenFunc, 0, 0
+ p, fts5LocaleFunc, 0, 0
);
}
}
/* If SQLITE_FTS5_ENABLE_TEST_MI is defined, assume that the file
@@ -258580,22 +258007,22 @@
int rc = SQLITE_OK;
char aBuf[32];
char *zOut = aBuf;
int ii;
const unsigned char *zIn = (const unsigned char*)pText;
- const unsigned char *zEof = (zIn ? &zIn[nText] : 0);
- u32 iCode = 0;
+ const unsigned char *zEof = &zIn[nText];
+ u32 iCode;
int aStart[3]; /* Input offset of each character in aBuf[] */
UNUSED_PARAM(unusedFlags);
/* Populate aBuf[] with the characters for the first trigram. */
for(ii=0; ii<3; ii++){
do {
aStart[ii] = zIn - (const unsigned char*)pText;
- if( zIn>=zEof ) return SQLITE_OK;
READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) return SQLITE_OK;
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
}while( iCode==0 );
WRITE_UTF8(zOut, iCode);
}
@@ -258612,15 +258039,12 @@
const char *z1;
/* Read characters from the input up until the first non-diacritic */
do {
iNext = zIn - (const unsigned char*)pText;
- if( zIn>=zEof ){
- iCode = 0;
- break;
- }
READ_UTF8(zIn, zEof, iCode);
+ if( iCode==0 ) break;
if( p->bFold ) iCode = sqlite3Fts5UnicodeFold(iCode, p->iFoldParam);
}while( iCode==0 );
/* Pass the current trigram back to fts5 */
rc = xToken(pCtx, 0, aBuf, zOut-aBuf, aStart[0], iNext);
@@ -260653,11 +260077,11 @@
return sqlite3_create_module_v2(db, "fts5vocab", &fts5Vocab, p, 0);
}
-/* Here ends the fts5.c composite file. */
+
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS5) */
/************** End of fts5.c ************************************************/
/************** Begin file stmt.c ********************************************/
/*
@@ -261009,7 +260433,6 @@
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
/* Return the source-id for this library */
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
-#endif /* SQLITE_AMALGAMATION */
/************************** End of sqlite3.c ******************************/
Index: src/sqlite3.h
==================================================================
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -144,13 +144,13 @@
**
** See also: [sqlite3_libversion()],
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.48.0"
-#define SQLITE_VERSION_NUMBER 3048000
-#define SQLITE_SOURCE_ID "2024-12-30 21:23:53 2b17bc49655c577029919c2d409de994b0d252f8efb5da1ba0913f2c96bee552"
+#define SQLITE_VERSION "3.47.0"
+#define SQLITE_VERSION_NUMBER 3047000
+#define SQLITE_SOURCE_ID "2024-10-18 12:31:21 a31a94644113c226a06316a3f95fb38b605821f1c123e2cda06ba90bfcacf59f"
/*
** CAPI3REF: Run-Time Library Version Numbers
** KEYWORDS: sqlite3_version sqlite3_sourceid
**
@@ -650,17 +650,10 @@
**
** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying
** filesystem supports doing multiple write operations atomically when those
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
-**
-** The SQLITE_IOCAP_SUBPAGE_READ property means that it is ok to read
-** from the database file in amounts that are not a multiple of the
-** page size and that do not begin at a page boundary. Without this
-** property, SQLite is careful to only do full-page reads and write
-** on aligned pages, with the one exception that it will do a sub-page
-** read of the first page to access the database header.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
#define SQLITE_IOCAP_ATOMIC1K 0x00000004
#define SQLITE_IOCAP_ATOMIC2K 0x00000008
@@ -673,11 +666,10 @@
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
-#define SQLITE_IOCAP_SUBPAGE_READ 0x00008000
/*
** CAPI3REF: File Locking Levels
**
** SQLite uses one of these integer values as the second
@@ -820,11 +812,10 @@
** [SQLITE_IOCAP_SEQUENTIAL]
** [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
** [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
** [SQLITE_IOCAP_IMMUTABLE]
** [SQLITE_IOCAP_BATCH_ATOMIC]
-** [SQLITE_IOCAP_SUBPAGE_READ]
**
**
** The SQLITE_IOCAP_ATOMIC property means that all writes of
** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
** mean that writes of blocks that are nnn bytes in size and
@@ -1098,15 +1089,10 @@
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
-** [[SQLITE_FCNTL_NULL_IO]]
-** The [SQLITE_FCNTL_NULL_IO] opcode sets the low-level file descriptor
-** or file handle for the [sqlite3_file] object such that it will no longer
-** read or write to the database file.
-**
** [[SQLITE_FCNTL_WAL_BLOCK]]
** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
** be advantageous to block on the next WAL lock if the lock is not immediately
** available. The WAL subsystem issues this signal during rare
** circumstances in order to fix a problem with priority inversion.
@@ -1256,11 +1242,10 @@
#define SQLITE_FCNTL_RESERVE_BYTES 38
#define SQLITE_FCNTL_CKPT_START 39
#define SQLITE_FCNTL_EXTERNAL_READER 40
#define SQLITE_FCNTL_CKSM_FILE 41
#define SQLITE_FCNTL_RESET_CACHE 42
-#define SQLITE_FCNTL_NULL_IO 43
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -2635,18 +2620,14 @@
**
** ^These functions return the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter.
** The two functions are identical except for the type of the return value
-** and that if the number of rows modified by the most recent INSERT, UPDATE,
+** and that if the number of rows modified by the most recent INSERT, UPDATE
** or DELETE is greater than the maximum value supported by type "int", then
** the return value of sqlite3_changes() is undefined. ^Executing any other
** type of SQL statement does not modify the value returned by these functions.
-** For the purposes of this interface, a CREATE TABLE AS SELECT statement
-** does not count as an INSERT, UPDATE or DELETE statement and hence the rows
-** added to the new table by the CREATE TABLE AS SELECT statement are not
-** counted.
**
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
** [foreign key actions] or [REPLACE] constraint resolution are not counted.
**
@@ -4202,26 +4183,15 @@
**
** [[SQLITE_PREPARE_NO_VTAB]] SQLITE_PREPARE_NO_VTAB
** The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
** to return an error (error code SQLITE_ERROR) if the statement uses
** any virtual tables.
-**
-** [[SQLITE_PREPARE_DONT_LOG]] SQLITE_PREPARE_DONT_LOG
-** The SQLITE_PREPARE_DONT_LOG flag prevents SQL compiler
-** errors from being sent to the error log defined by
-** [SQLITE_CONFIG_LOG]. This can be used, for example, to do test
-** compiles to see if some SQL syntax is well-formed, without generating
-** messages on the global error log when it is not. If the test compile
-** fails, the sqlite3_prepare_v3() call returns the same error indications
-** with or without this flag; it just omits the call to [sqlite3_log()] that
-** logs the error.
**
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
#define SQLITE_PREPARE_NORMALIZE 0x02
#define SQLITE_PREPARE_NO_VTAB 0x04
-#define SQLITE_PREPARE_DONT_LOG 0x10
/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
** METHOD: sqlite3
@@ -10908,11 +10878,11 @@
#endif
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
#endif
-/* #endif for SQLITE3_H will be added by mksqlite3.tcl */
+#endif /* SQLITE3_H */
/******** Begin file sqlite3rtree.h *********/
/*
** 2010 August 30
**
@@ -13159,33 +13129,18 @@
** This is used to access token iToken of phrase hit iIdx within the
** current row. If iIdx is less than zero or greater than or equal to the
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
** output variable (*ppToken) is set to point to a buffer containing the
** matching document token, and (*pnToken) to the size of that buffer in
-** bytes.
+** bytes. This API is not available if the specified token matches a
+** prefix query term. In that case both output variables are always set
+** to 0.
**
** The output text is not a copy of the document text that was tokenized.
** It is the output of the tokenizer module. For tokendata=1 tables, this
** includes any embedded 0x00 and trailing data.
**
-** This API may be slow in some cases if the token identified by parameters
-** iIdx and iToken matched a prefix token in the query. In most cases, the
-** first call to this API for each prefix token in the query is forced
-** to scan the portion of the full-text index that matches the prefix
-** token to collect the extra data required by this API. If the prefix
-** token matches a large number of token instances in the document set,
-** this may be a performance problem.
-**
-** If the user knows in advance that a query may use this API for a
-** prefix token, FTS5 may be configured to collect all required data as part
-** of the initial querying of the full-text index, avoiding the second scan
-** entirely. This also causes prefix queries that do not use this API to
-** run more slowly and use more memory. FTS5 may be configured in this way
-** either on a per-table basis using the [FTS5 insttoken | 'insttoken']
-** option, or on a per-query basis using the
-** [fts5_insttoken | fts5_insttoken()] user function.
-**
** This API can be quite slow if used with an FTS5 table created with the
** "detail=none" or "detail=column" option.
**
** xColumnLocale(pFts5, iIdx, pzLocale, pnLocale)
** If parameter iCol is less than zero, or greater than or equal to the
@@ -13615,6 +13570,5 @@
#endif
#endif /* _FTS5_H */
/******** End of fts5.h *********/
-#endif /* SQLITE3_H */
Index: src/sqllogictest.c
==================================================================
--- src/sqllogictest.c
+++ src/sqllogictest.c
@@ -1,24 +1,25 @@
/*
** Copyright (c) 2008 D. Richard Hipp
**
-** This program is free software. As far as the author is
-** concerned, you can redistribute it and/or modify the code
-** as you see fit. No attribution is required. Use whichever
-** of the following license terms best applies to your situation.
-**
-** 1. GNU General Public License
-** 2. BSD License
-** 3. MIT License
-** 4. CC0 License
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public
+** License version 2 as published by the Free Software Foundation.
**
** This program is distributed in the hope that it will be useful,
-** but without any warranty; without even the implied warranty of
-** merchantability or fitness for a particular purpose.
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
**
+** You should have received a copy of the GNU General Public
+** License along with this library; if not, write to the
+** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+** Boston, MA 02111-1307, USA.
+**
** Author contact information:
-** drh@sqlite.org
+** drh@hwaci.com
+** http://www.hwaci.com/drh/
**
*******************************************************************************
**
** This main driver for the sqllogictest program.
*/