|
@@ -1,6 +1,6 @@
|
|
|
/******************************************************************************
|
|
/******************************************************************************
|
|
|
** This file is an amalgamation of many separate C source files from SQLite
|
|
** This file is an amalgamation of many separate C source files from SQLite
|
|
|
-** version 3.7.16. By combining all the individual C code files into this
|
|
|
|
|
|
|
+** version 3.7.16.1. By combining all the individual C code files into this
|
|
|
** single large file, the entire code can be compiled as a single translation
|
|
** 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
|
|
** unit. This allows many compilers to do optimizations that would not be
|
|
|
** possible if the files were compiled separately. Performance improvements
|
|
** possible if the files were compiled separately. Performance improvements
|
|
@@ -678,9 +678,9 @@ extern "C" {
|
|
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
|
*/
|
|
*/
|
|
|
-#define SQLITE_VERSION "3.7.16"
|
|
|
|
|
|
|
+#define SQLITE_VERSION "3.7.16.1"
|
|
|
#define SQLITE_VERSION_NUMBER 3007016
|
|
#define SQLITE_VERSION_NUMBER 3007016
|
|
|
-#define SQLITE_SOURCE_ID "2013-03-20 12:04:29 5b22053f918d16f593227a432a5d5b4c195bb0b5"
|
|
|
|
|
|
|
+#define SQLITE_SOURCE_ID "2013-03-27 20:41:15 274d2a22660c7b34b8bbd85f3c29cbafbcb1b4e7"
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
@@ -3279,7 +3279,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
|
|
** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
|
|
** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
|
|
|
** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
|
|
** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
|
|
|
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
|
|
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
|
|
|
-** a URI filename, its value overrides any behaviour requested by setting
|
|
|
|
|
|
|
+** a URI filename, its value overrides any behavior requested by setting
|
|
|
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
|
|
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
|
|
|
** </ul>
|
|
** </ul>
|
|
|
**
|
|
**
|
|
@@ -6990,7 +6990,7 @@ struct sqlite3_pcache_page {
|
|
|
** parameter to help it determined what action to take:
|
|
** parameter to help it determined what action to take:
|
|
|
**
|
|
**
|
|
|
** <table border=1 width=85% align=center>
|
|
** <table border=1 width=85% align=center>
|
|
|
-** <tr><th> createFlag <th> Behaviour when page is not already in cache
|
|
|
|
|
|
|
+** <tr><th> createFlag <th> Behavior when page is not already in cache
|
|
|
** <tr><td> 0 <td> Do not allocate a new page. Return NULL.
|
|
** <tr><td> 0 <td> Do not allocate a new page. Return NULL.
|
|
|
** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
|
|
** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
|
|
|
** Otherwise return NULL.
|
|
** Otherwise return NULL.
|
|
@@ -7795,7 +7795,7 @@ struct sqlite3_rtree_geometry {
|
|
|
** May you share freely, never taking more than you give.
|
|
** May you share freely, never taking more than you give.
|
|
|
**
|
|
**
|
|
|
*************************************************************************
|
|
*************************************************************************
|
|
|
-** This is the header file for the generic hash-table implemenation
|
|
|
|
|
|
|
+** This is the header file for the generic hash-table implementation
|
|
|
** used in SQLite.
|
|
** used in SQLite.
|
|
|
*/
|
|
*/
|
|
|
#ifndef _SQLITE_HASH_H_
|
|
#ifndef _SQLITE_HASH_H_
|
|
@@ -13002,9 +13002,6 @@ static const char * const azCompileOpt[] = {
|
|
|
#ifdef SQLITE_OMIT_MEMORYDB
|
|
#ifdef SQLITE_OMIT_MEMORYDB
|
|
|
"OMIT_MEMORYDB",
|
|
"OMIT_MEMORYDB",
|
|
|
#endif
|
|
#endif
|
|
|
-#ifdef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
- "OMIT_MERGE_SORT",
|
|
|
|
|
-#endif
|
|
|
|
|
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
|
|
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
|
|
|
"OMIT_OR_OPTIMIZATION",
|
|
"OMIT_OR_OPTIMIZATION",
|
|
|
#endif
|
|
#endif
|
|
@@ -13593,15 +13590,6 @@ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
|
|
|
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
|
|
|
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
|
|
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
|
|
|
|
|
|
|
|
-#ifdef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
-# define sqlite3VdbeSorterInit(Y,Z) SQLITE_OK
|
|
|
|
|
-# define sqlite3VdbeSorterWrite(X,Y,Z) SQLITE_OK
|
|
|
|
|
-# define sqlite3VdbeSorterClose(Y,Z)
|
|
|
|
|
-# define sqlite3VdbeSorterRowkey(Y,Z) SQLITE_OK
|
|
|
|
|
-# define sqlite3VdbeSorterRewind(X,Y,Z) SQLITE_OK
|
|
|
|
|
-# define sqlite3VdbeSorterNext(X,Y,Z) SQLITE_OK
|
|
|
|
|
-# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
|
|
|
|
|
-#else
|
|
|
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
|
|
|
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
|
|
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
|
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
|
|
@@ -13609,7 +13597,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
|
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
|
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
|
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
|
|
|
-#endif
|
|
|
|
|
|
|
|
|
|
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
|
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
|
|
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
|
|
@@ -23463,7 +23450,7 @@ static int openDirectory(const char*, int*);
|
|
|
** to all overrideable system calls.
|
|
** to all overrideable system calls.
|
|
|
*/
|
|
*/
|
|
|
static struct unix_syscall {
|
|
static struct unix_syscall {
|
|
|
- const char *zName; /* Name of the sytem call */
|
|
|
|
|
|
|
+ const char *zName; /* Name of the system call */
|
|
|
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
|
|
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
|
|
|
sqlite3_syscall_ptr pDefault; /* Default value */
|
|
sqlite3_syscall_ptr pDefault; /* Default value */
|
|
|
} aSyscall[] = {
|
|
} aSyscall[] = {
|
|
@@ -25035,7 +25022,7 @@ static int nolockClose(sqlite3_file *id) {
|
|
|
/******************************************************************************
|
|
/******************************************************************************
|
|
|
************************* Begin dot-file Locking ******************************
|
|
************************* Begin dot-file Locking ******************************
|
|
|
**
|
|
**
|
|
|
-** The dotfile locking implementation uses the existance of separate lock
|
|
|
|
|
|
|
+** The dotfile locking implementation uses the existence of separate lock
|
|
|
** files (really a directory) to control access to the database. This works
|
|
** files (really a directory) to control access to the database. This works
|
|
|
** on just about every filesystem imaginable. But there are serious downsides:
|
|
** on just about every filesystem imaginable. But there are serious downsides:
|
|
|
**
|
|
**
|
|
@@ -25050,7 +25037,7 @@ static int nolockClose(sqlite3_file *id) {
|
|
|
**
|
|
**
|
|
|
** Dotfile locking works by creating a subdirectory in the same directory as
|
|
** Dotfile locking works by creating a subdirectory in the same directory as
|
|
|
** the database and with the same name but with a ".lock" extension added.
|
|
** the database and with the same name but with a ".lock" extension added.
|
|
|
-** The existance of a lock directory implies an EXCLUSIVE lock. All other
|
|
|
|
|
|
|
+** The existence of a lock directory implies an EXCLUSIVE lock. All other
|
|
|
** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
|
|
** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
@@ -26539,7 +26526,7 @@ static int unixSync(sqlite3_file *id, int flags){
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Also fsync the directory containing the file if the DIRSYNC flag
|
|
/* Also fsync the directory containing the file if the DIRSYNC flag
|
|
|
- ** is set. This is a one-time occurrance. Many systems (examples: AIX)
|
|
|
|
|
|
|
+ ** is set. This is a one-time occurrence. Many systems (examples: AIX)
|
|
|
** are unable to fsync a directory, so ignore errors on the fsync.
|
|
** are unable to fsync a directory, so ignore errors on the fsync.
|
|
|
*/
|
|
*/
|
|
|
if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
|
|
if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
|
|
@@ -27913,7 +27900,7 @@ static int fillInUnixFile(
|
|
|
unixEnterMutex();
|
|
unixEnterMutex();
|
|
|
rc = findInodeInfo(pNew, &pNew->pInode);
|
|
rc = findInodeInfo(pNew, &pNew->pInode);
|
|
|
if( rc!=SQLITE_OK ){
|
|
if( rc!=SQLITE_OK ){
|
|
|
- /* If an error occured in findInodeInfo(), close the file descriptor
|
|
|
|
|
|
|
+ /* If an error occurred in findInodeInfo(), close the file descriptor
|
|
|
** immediately, before releasing the mutex. findInodeInfo() may fail
|
|
** immediately, before releasing the mutex. findInodeInfo() may fail
|
|
|
** in two scenarios:
|
|
** in two scenarios:
|
|
|
**
|
|
**
|
|
@@ -28551,7 +28538,7 @@ static int unixDelete(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
-** Test the existance of or access permissions of file zPath. The
|
|
|
|
|
|
|
+** Test the existence of or access permissions of file zPath. The
|
|
|
** test performed depends on the value of flags:
|
|
** test performed depends on the value of flags:
|
|
|
**
|
|
**
|
|
|
** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
|
|
** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
|
|
@@ -30669,7 +30656,7 @@ static int sqlite3_os_type = 0;
|
|
|
** to all overrideable system calls.
|
|
** to all overrideable system calls.
|
|
|
*/
|
|
*/
|
|
|
static struct win_syscall {
|
|
static struct win_syscall {
|
|
|
- const char *zName; /* Name of the sytem call */
|
|
|
|
|
|
|
+ const char *zName; /* Name of the system call */
|
|
|
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
|
|
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
|
|
|
sqlite3_syscall_ptr pDefault; /* Default value */
|
|
sqlite3_syscall_ptr pDefault; /* Default value */
|
|
|
} aSyscall[] = {
|
|
} aSyscall[] = {
|
|
@@ -32388,7 +32375,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
|
|
|
** containing the lower 32-bits of the new file-offset. Or, if it fails,
|
|
** containing the lower 32-bits of the new file-offset. Or, if it fails,
|
|
|
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
|
|
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
|
|
|
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
|
|
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
|
|
|
- ** whether an error has actually occured, it is also necessary to call
|
|
|
|
|
|
|
+ ** whether an error has actually occurred, it is also necessary to call
|
|
|
** GetLastError().
|
|
** GetLastError().
|
|
|
*/
|
|
*/
|
|
|
dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
|
|
dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
|
|
@@ -32534,7 +32521,7 @@ static int winWrite(
|
|
|
int amt, /* Number of bytes to write */
|
|
int amt, /* Number of bytes to write */
|
|
|
sqlite3_int64 offset /* Offset into the file to begin writing at */
|
|
sqlite3_int64 offset /* Offset into the file to begin writing at */
|
|
|
){
|
|
){
|
|
|
- int rc = 0; /* True if error has occured, else false */
|
|
|
|
|
|
|
+ int rc = 0; /* True if error has occurred, else false */
|
|
|
winFile *pFile = (winFile*)id; /* File handle */
|
|
winFile *pFile = (winFile*)id; /* File handle */
|
|
|
int nRetry = 0; /* Number of retries */
|
|
int nRetry = 0; /* Number of retries */
|
|
|
|
|
|
|
@@ -34356,7 +34343,7 @@ static int winDelete(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
-** Check the existance and status of a file.
|
|
|
|
|
|
|
+** Check the existence and status of a file.
|
|
|
*/
|
|
*/
|
|
|
static int winAccess(
|
|
static int winAccess(
|
|
|
sqlite3_vfs *pVfs, /* Not used on win32 */
|
|
sqlite3_vfs *pVfs, /* Not used on win32 */
|
|
@@ -34965,7 +34952,7 @@ SQLITE_API int sqlite3_os_end(void){
|
|
|
/*
|
|
/*
|
|
|
** A bitmap is an instance of the following structure.
|
|
** A bitmap is an instance of the following structure.
|
|
|
**
|
|
**
|
|
|
-** This bitmap records the existance of zero or more bits
|
|
|
|
|
|
|
+** This bitmap records the existence of zero or more bits
|
|
|
** with values between 1 and iSize, inclusive.
|
|
** with values between 1 and iSize, inclusive.
|
|
|
**
|
|
**
|
|
|
** There are three possible representations of the bitmap.
|
|
** There are three possible representations of the bitmap.
|
|
@@ -37867,7 +37854,7 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
|
|
|
** * A write transaction is active.
|
|
** * A write transaction is active.
|
|
|
** * An EXCLUSIVE or greater lock is held on the database file.
|
|
** * An EXCLUSIVE or greater lock is held on the database file.
|
|
|
** * All writing and syncing of journal and database data has finished.
|
|
** * All writing and syncing of journal and database data has finished.
|
|
|
-** If no error occured, all that remains is to finalize the journal to
|
|
|
|
|
|
|
+** If no error occurred, all that remains is to finalize the journal to
|
|
|
** commit the transaction. If an error did occur, the caller will need
|
|
** commit the transaction. If an error did occur, the caller will need
|
|
|
** to rollback the transaction.
|
|
** to rollback the transaction.
|
|
|
**
|
|
**
|
|
@@ -38115,7 +38102,7 @@ struct PagerSavepoint {
|
|
|
**
|
|
**
|
|
|
** doNotSpill, doNotSyncSpill
|
|
** doNotSpill, doNotSyncSpill
|
|
|
**
|
|
**
|
|
|
-** These two boolean variables control the behaviour of cache-spills
|
|
|
|
|
|
|
+** These two boolean variables control the behavior of cache-spills
|
|
|
** (calls made by the pcache module to the pagerStress() routine to
|
|
** (calls made by the pcache module to the pagerStress() routine to
|
|
|
** write cached data to the file-system in order to free up memory).
|
|
** write cached data to the file-system in order to free up memory).
|
|
|
**
|
|
**
|
|
@@ -38993,7 +38980,7 @@ static int writeJournalHdr(Pager *pPager){
|
|
|
memset(zHeader, 0, sizeof(aJournalMagic)+4);
|
|
memset(zHeader, 0, sizeof(aJournalMagic)+4);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* The random check-hash initialiser */
|
|
|
|
|
|
|
+ /* The random check-hash initializer */
|
|
|
sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
|
|
sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
|
|
|
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
|
|
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
|
|
|
/* The initial database size */
|
|
/* The initial database size */
|
|
@@ -41325,7 +41312,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|
|
|
** dirty page were to be discarded from the cache via the pagerStress()
|
|
** dirty page were to be discarded from the cache via the pagerStress()
|
|
|
** routine, pagerStress() would not write the current page content to
|
|
** routine, pagerStress() would not write the current page content to
|
|
|
** the database file. If a savepoint transaction were rolled back after
|
|
** the database file. If a savepoint transaction were rolled back after
|
|
|
-** this happened, the correct behaviour would be to restore the current
|
|
|
|
|
|
|
+** this happened, the correct behavior would be to restore the current
|
|
|
** content of the page. However, since this content is not present in either
|
|
** content of the page. However, since this content is not present in either
|
|
|
** the database file or the portion of the rollback journal and
|
|
** the database file or the portion of the rollback journal and
|
|
|
** sub-journal rolled back the content could not be restored and the
|
|
** sub-journal rolled back the content could not be restored and the
|
|
@@ -49168,6 +49155,19 @@ static void btreeClearHasContent(BtShared *pBt){
|
|
|
pBt->pHasContent = 0;
|
|
pBt->pHasContent = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+** Release all of the apPage[] pages for a cursor.
|
|
|
|
|
+*/
|
|
|
|
|
+static void btreeReleaseAllCursorPages(BtCursor *pCur){
|
|
|
|
|
+ int i;
|
|
|
|
|
+ for(i=0; i<=pCur->iPage; i++){
|
|
|
|
|
+ releasePage(pCur->apPage[i]);
|
|
|
|
|
+ pCur->apPage[i] = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ pCur->iPage = -1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
** Save the current cursor position in the variables BtCursor.nKey
|
|
** Save the current cursor position in the variables BtCursor.nKey
|
|
|
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
|
|
** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
|
|
@@ -49207,12 +49207,7 @@ static int saveCursorPosition(BtCursor *pCur){
|
|
|
assert( !pCur->apPage[0]->intKey || !pCur->pKey );
|
|
assert( !pCur->apPage[0]->intKey || !pCur->pKey );
|
|
|
|
|
|
|
|
if( rc==SQLITE_OK ){
|
|
if( rc==SQLITE_OK ){
|
|
|
- int i;
|
|
|
|
|
- for(i=0; i<=pCur->iPage; i++){
|
|
|
|
|
- releasePage(pCur->apPage[i]);
|
|
|
|
|
- pCur->apPage[i] = 0;
|
|
|
|
|
- }
|
|
|
|
|
- pCur->iPage = -1;
|
|
|
|
|
|
|
+ btreeReleaseAllCursorPages(pCur);
|
|
|
pCur->eState = CURSOR_REQUIRESEEK;
|
|
pCur->eState = CURSOR_REQUIRESEEK;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -49230,11 +49225,15 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
|
assert( pExcept==0 || pExcept->pBt==pBt );
|
|
assert( pExcept==0 || pExcept->pBt==pBt );
|
|
|
for(p=pBt->pCursor; p; p=p->pNext){
|
|
for(p=pBt->pCursor; p; p=p->pNext){
|
|
|
- if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) &&
|
|
|
|
|
- p->eState==CURSOR_VALID ){
|
|
|
|
|
- int rc = saveCursorPosition(p);
|
|
|
|
|
- if( SQLITE_OK!=rc ){
|
|
|
|
|
- return rc;
|
|
|
|
|
|
|
+ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
|
|
|
|
|
+ if( p->eState==CURSOR_VALID ){
|
|
|
|
|
+ int rc = saveCursorPosition(p);
|
|
|
|
|
+ if( SQLITE_OK!=rc ){
|
|
|
|
|
+ return rc;
|
|
|
|
|
+ }
|
|
|
|
|
+ }else{
|
|
|
|
|
+ testcase( p->iPage>0 );
|
|
|
|
|
+ btreeReleaseAllCursorPages(p);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -50822,7 +50821,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
|
|
|
** known that the shared b-tree mutex is held, but the mutex on the
|
|
** known that the shared b-tree mutex is held, but the mutex on the
|
|
|
** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
|
|
** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
|
|
|
** were to be called, it might collide with some other operation on the
|
|
** were to be called, it might collide with some other operation on the
|
|
|
-** database handle that owns *p, causing undefined behaviour.
|
|
|
|
|
|
|
+** database handle that owns *p, causing undefined behavior.
|
|
|
*/
|
|
*/
|
|
|
SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
|
|
SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
|
|
|
assert( sqlite3_mutex_held(p->pBt->mutex) );
|
|
assert( sqlite3_mutex_held(p->pBt->mutex) );
|
|
@@ -54102,7 +54101,7 @@ static int fillInCell(
|
|
|
** If this is the first overflow page, then write a partial entry
|
|
** If this is the first overflow page, then write a partial entry
|
|
|
** to the pointer-map. If we write nothing to this pointer-map slot,
|
|
** to the pointer-map. If we write nothing to this pointer-map slot,
|
|
|
** then the optimistic overflow chain processing in clearCell()
|
|
** then the optimistic overflow chain processing in clearCell()
|
|
|
- ** may misinterpret the uninitialised values and delete the
|
|
|
|
|
|
|
+ ** may misinterpret the uninitialized values and delete the
|
|
|
** wrong pages from the database.
|
|
** wrong pages from the database.
|
|
|
*/
|
|
*/
|
|
|
if( pBt->autoVacuum && rc==SQLITE_OK ){
|
|
if( pBt->autoVacuum && rc==SQLITE_OK ){
|
|
@@ -55575,7 +55574,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
|
|
|
insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
|
|
insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
|
|
|
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
|
|
assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
|
|
|
|
|
|
|
|
- /* If no error has occured and pPage has an overflow cell, call balance()
|
|
|
|
|
|
|
+ /* If no error has occurred and pPage has an overflow cell, call balance()
|
|
|
** to redistribute the cells within the tree. Since balance() may move
|
|
** to redistribute the cells within the tree. Since balance() may move
|
|
|
** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
|
|
** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
|
|
|
** variables.
|
|
** variables.
|
|
@@ -59309,7 +59308,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|
|
|
}
|
|
}
|
|
|
sqlite3DbFree(v->db, sIter.apSub);
|
|
sqlite3DbFree(v->db, sIter.apSub);
|
|
|
|
|
|
|
|
- /* Return true if hasAbort==mayAbort. Or if a malloc failure occured.
|
|
|
|
|
|
|
+ /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
|
|
|
** If malloc failed, then the while() loop above may not have iterated
|
|
** If malloc failed, then the while() loop above may not have iterated
|
|
|
** through all opcodes and hasAbort may be set incorrectly. Return
|
|
** through all opcodes and hasAbort may be set incorrectly. Return
|
|
|
** true for this case to prevent the assert() in the callers frame
|
|
** true for this case to prevent the assert() in the callers frame
|
|
@@ -60941,7 +60940,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
|
|
|
|
|
|
|
|
/* If p->iStatement is greater than zero, then this Vdbe opened a
|
|
/* If p->iStatement is greater than zero, then this Vdbe opened a
|
|
|
** statement transaction that should be closed here. The only exception
|
|
** statement transaction that should be closed here. The only exception
|
|
|
- ** is that an IO error may have occured, causing an emergency rollback.
|
|
|
|
|
|
|
+ ** is that an IO error may have occurred, causing an emergency rollback.
|
|
|
** In this case (db->nStatement==0), and there is nothing to do.
|
|
** In this case (db->nStatement==0), and there is nothing to do.
|
|
|
*/
|
|
*/
|
|
|
if( db->nStatement && p->iStatement ){
|
|
if( db->nStatement && p->iStatement ){
|
|
@@ -61077,7 +61076,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
|
|
|
**
|
|
**
|
|
|
** Even if the statement is read-only, it is important to perform
|
|
** Even if the statement is read-only, it is important to perform
|
|
|
** a statement or transaction rollback operation. If the error
|
|
** a statement or transaction rollback operation. If the error
|
|
|
- ** occured while writing to the journal, sub-journal or database
|
|
|
|
|
|
|
+ ** occurred while writing to the journal, sub-journal or database
|
|
|
** file as part of an effort to free up cache space (see function
|
|
** file as part of an effort to free up cache space (see function
|
|
|
** pagerStress() in pager.c), the rollback is required to restore
|
|
** pagerStress() in pager.c), the rollback is required to restore
|
|
|
** the pager to a consistent state.
|
|
** the pager to a consistent state.
|
|
@@ -61491,7 +61490,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
|
|
|
** the blob of data that it corresponds to. In a table record, all serial
|
|
** the blob of data that it corresponds to. In a table record, all serial
|
|
|
** types are stored at the start of the record, and the blobs of data at
|
|
** types are stored at the start of the record, and the blobs of data at
|
|
|
** the end. Hence these functions allow the caller to handle the
|
|
** the end. Hence these functions allow the caller to handle the
|
|
|
-** serial-type and data blob seperately.
|
|
|
|
|
|
|
+** serial-type and data blob separately.
|
|
|
**
|
|
**
|
|
|
** The following table describes the various storage classes for data:
|
|
** The following table describes the various storage classes for data:
|
|
|
**
|
|
**
|
|
@@ -62631,7 +62630,7 @@ end_of_step:
|
|
|
assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
|
|
assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
|
|
|
if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
|
|
if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
|
|
|
/* If this statement was prepared using sqlite3_prepare_v2(), and an
|
|
/* If this statement was prepared using sqlite3_prepare_v2(), and an
|
|
|
- ** error has occured, then return the error code in p->rc to the
|
|
|
|
|
|
|
+ ** error has occurred, then return the error code in p->rc to the
|
|
|
** caller. Set the error code in the database handle to the same value.
|
|
** caller. Set the error code in the database handle to the same value.
|
|
|
*/
|
|
*/
|
|
|
rc = sqlite3VdbeTransferError(p);
|
|
rc = sqlite3VdbeTransferError(p);
|
|
@@ -63921,11 +63920,7 @@ SQLITE_API int sqlite3_found_count = 0;
|
|
|
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
|
|
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
|
|
|
|
|
|
|
|
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
|
|
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
|
|
|
-#ifdef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
-# define isSorter(x) 0
|
|
|
|
|
-#else
|
|
|
|
|
# define isSorter(x) ((x)->pSorter!=0)
|
|
# define isSorter(x) ((x)->pSorter!=0)
|
|
|
-#endif
|
|
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
** Argument pMem points at a register that will be passed to a
|
|
** Argument pMem points at a register that will be passed to a
|
|
@@ -67660,17 +67655,12 @@ case OP_SorterOpen: {
|
|
|
VdbeCursor *pCx;
|
|
VdbeCursor *pCx;
|
|
|
#endif /* local variables moved into u.ba */
|
|
#endif /* local variables moved into u.ba */
|
|
|
|
|
|
|
|
-#ifndef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
|
|
u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
|
|
|
if( u.ba.pCx==0 ) goto no_mem;
|
|
if( u.ba.pCx==0 ) goto no_mem;
|
|
|
u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
|
|
u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
|
|
|
u.ba.pCx->pKeyInfo->enc = ENC(p->db);
|
|
u.ba.pCx->pKeyInfo->enc = ENC(p->db);
|
|
|
u.ba.pCx->isSorter = 1;
|
|
u.ba.pCx->isSorter = 1;
|
|
|
rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
|
|
rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
|
|
|
-#else
|
|
|
|
|
- pOp->opcode = OP_OpenEphemeral;
|
|
|
|
|
- pc--;
|
|
|
|
|
-#endif
|
|
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -68575,15 +68565,10 @@ case OP_SorterData: {
|
|
|
VdbeCursor *pC;
|
|
VdbeCursor *pC;
|
|
|
#endif /* local variables moved into u.bl */
|
|
#endif /* local variables moved into u.bl */
|
|
|
|
|
|
|
|
-#ifndef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
pOut = &aMem[pOp->p2];
|
|
pOut = &aMem[pOp->p2];
|
|
|
u.bl.pC = p->apCsr[pOp->p1];
|
|
u.bl.pC = p->apCsr[pOp->p1];
|
|
|
assert( u.bl.pC->isSorter );
|
|
assert( u.bl.pC->isSorter );
|
|
|
rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
|
|
rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
|
|
|
-#else
|
|
|
|
|
- pOp->opcode = OP_RowKey;
|
|
|
|
|
- pc--;
|
|
|
|
|
-#endif
|
|
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -68790,9 +68775,6 @@ case OP_Last: { /* jump */
|
|
|
** correctly optimizing out sorts.
|
|
** correctly optimizing out sorts.
|
|
|
*/
|
|
*/
|
|
|
case OP_SorterSort: /* jump */
|
|
case OP_SorterSort: /* jump */
|
|
|
-#ifdef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
- pOp->opcode = OP_Sort;
|
|
|
|
|
-#endif
|
|
|
|
|
case OP_Sort: { /* jump */
|
|
case OP_Sort: { /* jump */
|
|
|
#ifdef SQLITE_TEST
|
|
#ifdef SQLITE_TEST
|
|
|
sqlite3_sort_count++;
|
|
sqlite3_sort_count++;
|
|
@@ -68873,9 +68855,6 @@ case OP_Rewind: { /* jump */
|
|
|
** number P5-1 in the prepared statement is incremented.
|
|
** number P5-1 in the prepared statement is incremented.
|
|
|
*/
|
|
*/
|
|
|
case OP_SorterNext: /* jump */
|
|
case OP_SorterNext: /* jump */
|
|
|
-#ifdef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
- pOp->opcode = OP_Next;
|
|
|
|
|
-#endif
|
|
|
|
|
case OP_Prev: /* jump */
|
|
case OP_Prev: /* jump */
|
|
|
case OP_Next: { /* jump */
|
|
case OP_Next: { /* jump */
|
|
|
#if 0 /* local variables moved into u.br */
|
|
#if 0 /* local variables moved into u.br */
|
|
@@ -68928,9 +68907,6 @@ case OP_Next: { /* jump */
|
|
|
** for tables is OP_Insert.
|
|
** for tables is OP_Insert.
|
|
|
*/
|
|
*/
|
|
|
case OP_SorterInsert: /* in2 */
|
|
case OP_SorterInsert: /* in2 */
|
|
|
-#ifdef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
- pOp->opcode = OP_IdxInsert;
|
|
|
|
|
-#endif
|
|
|
|
|
case OP_IdxInsert: { /* in2 */
|
|
case OP_IdxInsert: { /* in2 */
|
|
|
#if 0 /* local variables moved into u.bs */
|
|
#if 0 /* local variables moved into u.bs */
|
|
|
VdbeCursor *pC;
|
|
VdbeCursor *pC;
|
|
@@ -70199,7 +70175,7 @@ case OP_VOpen: {
|
|
|
/* Initialize sqlite3_vtab_cursor base class */
|
|
/* Initialize sqlite3_vtab_cursor base class */
|
|
|
u.cm.pVtabCursor->pVtab = u.cm.pVtab;
|
|
u.cm.pVtabCursor->pVtab = u.cm.pVtab;
|
|
|
|
|
|
|
|
- /* Initialise vdbe cursor object */
|
|
|
|
|
|
|
+ /* Initialize vdbe cursor object */
|
|
|
u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
|
|
u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
|
|
|
if( u.cm.pCur ){
|
|
if( u.cm.pCur ){
|
|
|
u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
|
|
u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
|
|
@@ -71181,7 +71157,6 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
-#ifndef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
|
|
|
|
|
typedef struct VdbeSorterIter VdbeSorterIter;
|
|
typedef struct VdbeSorterIter VdbeSorterIter;
|
|
|
typedef struct SorterRecord SorterRecord;
|
|
typedef struct SorterRecord SorterRecord;
|
|
@@ -72201,8 +72176,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
|
|
|
return SQLITE_OK;
|
|
return SQLITE_OK;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
|
|
|
|
|
-
|
|
|
|
|
/************** End of vdbesort.c ********************************************/
|
|
/************** End of vdbesort.c ********************************************/
|
|
|
/************** Begin file journal.c *****************************************/
|
|
/************** Begin file journal.c *****************************************/
|
|
|
/*
|
|
/*
|
|
@@ -77740,7 +77713,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
|
|
|
int r1, r2;
|
|
int r1, r2;
|
|
|
|
|
|
|
|
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
|
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
|
|
- if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */
|
|
|
|
|
|
|
+ if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
|
|
|
if( NEVER(pExpr==0) ) return; /* No way this can happen */
|
|
if( NEVER(pExpr==0) ) return; /* No way this can happen */
|
|
|
op = pExpr->op;
|
|
op = pExpr->op;
|
|
|
switch( op ){
|
|
switch( op ){
|
|
@@ -77860,7 +77833,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
|
|
|
int r1, r2;
|
|
int r1, r2;
|
|
|
|
|
|
|
|
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
|
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
|
|
- if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */
|
|
|
|
|
|
|
+ if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
|
|
|
if( pExpr==0 ) return;
|
|
if( pExpr==0 ) return;
|
|
|
|
|
|
|
|
/* The value of pExpr->op and op are related as follows:
|
|
/* The value of pExpr->op and op are related as follows:
|
|
@@ -80457,7 +80430,7 @@ static void attachFunc(
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* Allocate the new entry in the db->aDb[] array and initialise the schema
|
|
|
|
|
|
|
+ /* Allocate the new entry in the db->aDb[] array and initialize the schema
|
|
|
** hash tables.
|
|
** hash tables.
|
|
|
*/
|
|
*/
|
|
|
if( db->aDb==db->aDbStatic ){
|
|
if( db->aDb==db->aDbStatic ){
|
|
@@ -80474,7 +80447,7 @@ static void attachFunc(
|
|
|
|
|
|
|
|
/* Open the database file. If the btree is successfully opened, use
|
|
/* Open the database file. If the btree is successfully opened, use
|
|
|
** it to obtain the database schema. At this point the schema may
|
|
** it to obtain the database schema. At this point the schema may
|
|
|
- ** or may not be initialised.
|
|
|
|
|
|
|
+ ** or may not be initialized.
|
|
|
*/
|
|
*/
|
|
|
flags = db->openFlags;
|
|
flags = db->openFlags;
|
|
|
rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
|
|
rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
|
|
@@ -83260,7 +83233,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in
|
|
|
/* Drop all SQLITE_MASTER table and index entries that refer to the
|
|
/* Drop all SQLITE_MASTER table and index entries that refer to the
|
|
|
** table. The program name loops through the master table and deletes
|
|
** table. The program name loops through the master table and deletes
|
|
|
** every row that refers to a table of the same name as the one being
|
|
** every row that refers to a table of the same name as the one being
|
|
|
- ** dropped. Triggers are handled seperately because a trigger can be
|
|
|
|
|
|
|
+ ** dropped. Triggers are handled separately because a trigger can be
|
|
|
** created in the temp database that refers to a table in another
|
|
** created in the temp database that refers to a table in another
|
|
|
** database.
|
|
** database.
|
|
|
*/
|
|
*/
|
|
@@ -83552,9 +83525,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
|
|
int tnum; /* Root page of index */
|
|
int tnum; /* Root page of index */
|
|
|
Vdbe *v; /* Generate code into this virtual machine */
|
|
Vdbe *v; /* Generate code into this virtual machine */
|
|
|
KeyInfo *pKey; /* KeyInfo for index */
|
|
KeyInfo *pKey; /* KeyInfo for index */
|
|
|
-#ifdef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
- int regIdxKey; /* Registers containing the index key */
|
|
|
|
|
-#endif
|
|
|
|
|
int regRecord; /* Register holding assemblied index record */
|
|
int regRecord; /* Register holding assemblied index record */
|
|
|
sqlite3 *db = pParse->db; /* The database connection */
|
|
sqlite3 *db = pParse->db; /* The database connection */
|
|
|
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
|
int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
|
|
@@ -83582,13 +83552,9 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
|
|
(char *)pKey, P4_KEYINFO_HANDOFF);
|
|
(char *)pKey, P4_KEYINFO_HANDOFF);
|
|
|
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
|
|
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
|
|
|
|
|
|
|
|
-#ifndef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
/* Open the sorter cursor if we are to use one. */
|
|
/* Open the sorter cursor if we are to use one. */
|
|
|
iSorter = pParse->nTab++;
|
|
iSorter = pParse->nTab++;
|
|
|
sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
|
|
sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
|
|
|
-#else
|
|
|
|
|
- iSorter = iTab;
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
|
|
/* Open the table. Loop through all rows of the table, inserting index
|
|
/* Open the table. Loop through all rows of the table, inserting index
|
|
|
** records into the sorter. */
|
|
** records into the sorter. */
|
|
@@ -83596,7 +83562,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
|
|
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
|
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
|
|
regRecord = sqlite3GetTempReg(pParse);
|
|
regRecord = sqlite3GetTempReg(pParse);
|
|
|
|
|
|
|
|
-#ifndef SQLITE_OMIT_MERGE_SORT
|
|
|
|
|
sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
|
|
sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
|
|
|
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
|
|
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
|
|
|
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
|
|
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
|
|
@@ -83616,30 +83581,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
|
|
sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
|
|
sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
|
|
|
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
|
|
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
|
|
|
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
|
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
|
|
-#else
|
|
|
|
|
- regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
|
|
|
|
|
- addr2 = addr1 + 1;
|
|
|
|
|
- if( pIndex->onError!=OE_None ){
|
|
|
|
|
- const int regRowid = regIdxKey + pIndex->nColumn;
|
|
|
|
|
- const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
|
|
|
|
|
- void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
|
|
|
|
|
-
|
|
|
|
|
- /* The registers accessed by the OP_IsUnique opcode were allocated
|
|
|
|
|
- ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
|
|
|
|
|
- ** call above. Just before that function was freed they were released
|
|
|
|
|
- ** (made available to the compiler for reuse) using
|
|
|
|
|
- ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
|
|
|
|
|
- ** opcode use the values stored within seems dangerous. However, since
|
|
|
|
|
- ** we can be sure that no other temp registers have been allocated
|
|
|
|
|
- ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
|
|
|
|
|
- */
|
|
|
|
|
- sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
|
|
|
|
|
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
|
|
|
|
|
- "indexed columns are not unique", P4_STATIC);
|
|
|
|
|
- }
|
|
|
|
|
- sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
|
|
|
|
|
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
|
|
|
|
-#endif
|
|
|
|
|
sqlite3ReleaseTempReg(pParse, regRecord);
|
|
sqlite3ReleaseTempReg(pParse, regRecord);
|
|
|
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
|
|
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
|
|
|
sqlite3VdbeJumpHere(v, addr1);
|
|
sqlite3VdbeJumpHere(v, addr1);
|
|
@@ -83999,7 +83940,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
|
|
|
** However the ON CONFLICT clauses are different. If both this
|
|
** However the ON CONFLICT clauses are different. If both this
|
|
|
** constraint and the previous equivalent constraint have explicit
|
|
** constraint and the previous equivalent constraint have explicit
|
|
|
** ON CONFLICT clauses this is an error. Otherwise, use the
|
|
** ON CONFLICT clauses this is an error. Otherwise, use the
|
|
|
- ** explicitly specified behaviour for the index.
|
|
|
|
|
|
|
+ ** explicitly specified behavior for the index.
|
|
|
*/
|
|
*/
|
|
|
if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
|
|
if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
|
|
|
sqlite3ErrorMsg(pParse,
|
|
sqlite3ErrorMsg(pParse,
|
|
@@ -94328,7 +94269,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
|
|
|
|
|
|
|
/* zMasterSchema and zInitScript are set to point at the master schema
|
|
/* zMasterSchema and zInitScript are set to point at the master schema
|
|
|
** and initialisation script appropriate for the database being
|
|
** and initialisation script appropriate for the database being
|
|
|
- ** initialised. zMasterName is the name of the master table.
|
|
|
|
|
|
|
+ ** initialized. zMasterName is the name of the master table.
|
|
|
*/
|
|
*/
|
|
|
if( !OMIT_TEMPDB && iDb==1 ){
|
|
if( !OMIT_TEMPDB && iDb==1 ){
|
|
|
zMasterSchema = temp_master_schema;
|
|
zMasterSchema = temp_master_schema;
|
|
@@ -94553,7 +94494,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /* Once all the other databases have been initialised, load the schema
|
|
|
|
|
|
|
+ /* Once all the other databases have been initialized, load the schema
|
|
|
** for the TEMP database. This is loaded last, as the TEMP database
|
|
** for the TEMP database. This is loaded last, as the TEMP database
|
|
|
** schema may contain references to objects in other databases.
|
|
** schema may contain references to objects in other databases.
|
|
|
*/
|
|
*/
|
|
@@ -94576,7 +94517,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
-** This routine is a no-op if the database schema is already initialised.
|
|
|
|
|
|
|
+** This routine is a no-op if the database schema is already initialized.
|
|
|
** Otherwise, the schema is loaded. An error code is returned.
|
|
** Otherwise, the schema is loaded. An error code is returned.
|
|
|
*/
|
|
*/
|
|
|
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){
|
|
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){
|
|
@@ -99590,7 +99531,7 @@ SQLITE_PRIVATE int sqlite3Select(
|
|
|
** value of x, the only row required).
|
|
** value of x, the only row required).
|
|
|
**
|
|
**
|
|
|
** A special flag must be passed to sqlite3WhereBegin() to slightly
|
|
** A special flag must be passed to sqlite3WhereBegin() to slightly
|
|
|
- ** modify behaviour as follows:
|
|
|
|
|
|
|
+ ** modify behavior as follows:
|
|
|
**
|
|
**
|
|
|
** + If the query is a "SELECT min(x)", then the loop coded by
|
|
** + If the query is a "SELECT min(x)", then the loop coded by
|
|
|
** where.c should not iterate over any values with a NULL value
|
|
** where.c should not iterate over any values with a NULL value
|
|
@@ -101583,7 +101524,7 @@ SQLITE_PRIVATE void sqlite3Update(
|
|
|
|
|
|
|
|
/* The row-trigger may have deleted the row being updated. In this
|
|
/* The row-trigger may have deleted the row being updated. In this
|
|
|
** case, jump to the next row. No updates or AFTER triggers are
|
|
** case, jump to the next row. No updates or AFTER triggers are
|
|
|
- ** required. This behaviour - what happens when the row being updated
|
|
|
|
|
|
|
+ ** required. This behavior - what happens when the row being updated
|
|
|
** is deleted or renamed by a BEFORE trigger - is left undefined in the
|
|
** is deleted or renamed by a BEFORE trigger - is left undefined in the
|
|
|
** documentation.
|
|
** documentation.
|
|
|
*/
|
|
*/
|
|
@@ -103512,6 +103453,8 @@ struct WhereCost {
|
|
|
#define WHERE_REVERSE 0x01000000 /* Scan in reverse order */
|
|
#define WHERE_REVERSE 0x01000000 /* Scan in reverse order */
|
|
|
#define WHERE_UNIQUE 0x02000000 /* Selects no more than one row */
|
|
#define WHERE_UNIQUE 0x02000000 /* Selects no more than one row */
|
|
|
#define WHERE_ALL_UNIQUE 0x04000000 /* This and all prior have one row */
|
|
#define WHERE_ALL_UNIQUE 0x04000000 /* This and all prior have one row */
|
|
|
|
|
+#define WHERE_OB_UNIQUE 0x00004000 /* Values in ORDER BY columns are
|
|
|
|
|
+ ** different for every output row */
|
|
|
#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
|
|
#define WHERE_VIRTUALTABLE 0x08000000 /* Use virtual-table processing */
|
|
|
#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
|
|
#define WHERE_MULTI_OR 0x10000000 /* OR using multiple indices */
|
|
|
#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
|
|
#define WHERE_TEMP_INDEX 0x20000000 /* Uses an ephemeral index */
|
|
@@ -103812,7 +103755,7 @@ static int allowedOp(int op){
|
|
|
** Commute a comparison operator. Expressions of the form "X op Y"
|
|
** Commute a comparison operator. Expressions of the form "X op Y"
|
|
|
** are converted into "Y op X".
|
|
** are converted into "Y op X".
|
|
|
**
|
|
**
|
|
|
-** If left/right precendence rules come into play when determining the
|
|
|
|
|
|
|
+** If left/right precedence rules come into play when determining the
|
|
|
** collating
|
|
** collating
|
|
|
** side of the comparison, it remains associated with the same side after
|
|
** side of the comparison, it remains associated with the same side after
|
|
|
** the commutation. So "Y collate NOCASE op X" becomes
|
|
** the commutation. So "Y collate NOCASE op X" becomes
|
|
@@ -106153,7 +106096,8 @@ static int isSortingIndex(
|
|
|
WhereBestIdx *p, /* Best index search context */
|
|
WhereBestIdx *p, /* Best index search context */
|
|
|
Index *pIdx, /* The index we are testing */
|
|
Index *pIdx, /* The index we are testing */
|
|
|
int base, /* Cursor number for the table to be sorted */
|
|
int base, /* Cursor number for the table to be sorted */
|
|
|
- int *pbRev /* Set to 1 for reverse-order scan of pIdx */
|
|
|
|
|
|
|
+ int *pbRev, /* Set to 1 for reverse-order scan of pIdx */
|
|
|
|
|
+ int *pbObUnique /* ORDER BY column values will different in every row */
|
|
|
){
|
|
){
|
|
|
int i; /* Number of pIdx terms used */
|
|
int i; /* Number of pIdx terms used */
|
|
|
int j; /* Number of ORDER BY terms satisfied */
|
|
int j; /* Number of ORDER BY terms satisfied */
|
|
@@ -106167,12 +106111,16 @@ static int isSortingIndex(
|
|
|
int nPriorSat; /* ORDER BY terms satisfied by outer loops */
|
|
int nPriorSat; /* ORDER BY terms satisfied by outer loops */
|
|
|
int seenRowid = 0; /* True if an ORDER BY rowid term is seen */
|
|
int seenRowid = 0; /* True if an ORDER BY rowid term is seen */
|
|
|
int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */
|
|
int uniqueNotNull; /* pIdx is UNIQUE with all terms are NOT NULL */
|
|
|
|
|
+ int outerObUnique; /* Outer loops generate different values in
|
|
|
|
|
+ ** every row for the ORDER BY columns */
|
|
|
|
|
|
|
|
if( p->i==0 ){
|
|
if( p->i==0 ){
|
|
|
nPriorSat = 0;
|
|
nPriorSat = 0;
|
|
|
|
|
+ outerObUnique = 1;
|
|
|
}else{
|
|
}else{
|
|
|
|
|
+ u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
|
|
|
nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
|
|
nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
|
|
|
- if( (p->aLevel[p->i-1].plan.wsFlags & WHERE_ORDERED)==0 ){
|
|
|
|
|
|
|
+ if( (wsFlags & WHERE_ORDERED)==0 ){
|
|
|
/* This loop cannot be ordered unless the next outer loop is
|
|
/* This loop cannot be ordered unless the next outer loop is
|
|
|
** also ordered */
|
|
** also ordered */
|
|
|
return nPriorSat;
|
|
return nPriorSat;
|
|
@@ -106182,6 +106130,9 @@ static int isSortingIndex(
|
|
|
** optimization is disabled */
|
|
** optimization is disabled */
|
|
|
return nPriorSat;
|
|
return nPriorSat;
|
|
|
}
|
|
}
|
|
|
|
|
+ testcase( wsFlags & WHERE_OB_UNIQUE );
|
|
|
|
|
+ testcase( wsFlags & WHERE_ALL_UNIQUE );
|
|
|
|
|
+ outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
|
|
|
}
|
|
}
|
|
|
pOrderBy = p->pOrderBy;
|
|
pOrderBy = p->pOrderBy;
|
|
|
assert( pOrderBy!=0 );
|
|
assert( pOrderBy!=0 );
|
|
@@ -106323,11 +106274,26 @@ static int isSortingIndex(
|
|
|
uniqueNotNull = 0;
|
|
uniqueNotNull = 0;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ if( seenRowid ){
|
|
|
|
|
+ uniqueNotNull = 1;
|
|
|
|
|
+ }else if( uniqueNotNull==0 || i<pIdx->nColumn ){
|
|
|
|
|
+ uniqueNotNull = 0;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
/* If we have not found at least one ORDER BY term that matches the
|
|
/* If we have not found at least one ORDER BY term that matches the
|
|
|
** index, then show no progress. */
|
|
** index, then show no progress. */
|
|
|
if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
|
|
if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
|
|
|
|
|
|
|
|
|
|
+ /* Either the outer queries must generate rows where there are no two
|
|
|
|
|
+ ** rows with the same values in all ORDER BY columns, or else this
|
|
|
|
|
+ ** loop must generate just a single row of output. Example: Suppose
|
|
|
|
|
+ ** the outer loops generate A=1 and A=1, and this loop generates B=3
|
|
|
|
|
+ ** and B=4. Then without the following test, ORDER BY A,B would
|
|
|
|
|
+ ** generate the wrong order output: 1,3 1,4 1,3 1,4
|
|
|
|
|
+ */
|
|
|
|
|
+ if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
|
|
|
|
|
+ *pbObUnique = uniqueNotNull;
|
|
|
|
|
+
|
|
|
/* Return the necessary scan order back to the caller */
|
|
/* Return the necessary scan order back to the caller */
|
|
|
*pbRev = sortOrder & 1;
|
|
*pbRev = sortOrder & 1;
|
|
|
|
|
|
|
@@ -106335,7 +106301,7 @@ static int isSortingIndex(
|
|
|
** possible for a single row from this table to match, then skip over
|
|
** possible for a single row from this table to match, then skip over
|
|
|
** any additional ORDER BY terms dealing with this table.
|
|
** any additional ORDER BY terms dealing with this table.
|
|
|
*/
|
|
*/
|
|
|
- if( seenRowid || (uniqueNotNull && i>=pIdx->nColumn) ){
|
|
|
|
|
|
|
+ if( uniqueNotNull ){
|
|
|
/* Advance j over additional ORDER BY terms associated with base */
|
|
/* Advance j over additional ORDER BY terms associated with base */
|
|
|
WhereMaskSet *pMS = p->pWC->pMaskSet;
|
|
WhereMaskSet *pMS = p->pWC->pMaskSet;
|
|
|
Bitmask m = ~getMask(pMS, base);
|
|
Bitmask m = ~getMask(pMS, base);
|
|
@@ -106619,12 +106585,14 @@ static void bestBtreeIndex(WhereBestIdx *p){
|
|
|
** variable. */
|
|
** variable. */
|
|
|
if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
|
|
if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
|
|
|
int bRev = 2;
|
|
int bRev = 2;
|
|
|
- WHERETRACE((" --> before isSortingIndex: nPriorSat=%d\n",nPriorSat));
|
|
|
|
|
- pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
|
|
|
|
|
- WHERETRACE((" --> after isSortingIndex: bRev=%d nOBSat=%d\n",
|
|
|
|
|
- bRev, pc.plan.nOBSat));
|
|
|
|
|
|
|
+ int bObUnique = 0;
|
|
|
|
|
+ WHERETRACE((" --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
|
|
|
|
|
+ pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
|
|
|
|
|
+ WHERETRACE((" --> after isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
|
|
|
|
|
+ bRev, bObUnique, pc.plan.nOBSat));
|
|
|
if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
|
|
if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
|
|
|
pc.plan.wsFlags |= WHERE_ORDERED;
|
|
pc.plan.wsFlags |= WHERE_ORDERED;
|
|
|
|
|
+ if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
|
|
|
}
|
|
}
|
|
|
if( nOrderBy==pc.plan.nOBSat ){
|
|
if( nOrderBy==pc.plan.nOBSat ){
|
|
|
bSort = 0;
|
|
bSort = 0;
|
|
@@ -106718,7 +106686,8 @@ static void bestBtreeIndex(WhereBestIdx *p){
|
|
|
** So this computation assumes table records are about twice as big
|
|
** So this computation assumes table records are about twice as big
|
|
|
** as index records
|
|
** as index records
|
|
|
*/
|
|
*/
|
|
|
- if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED))==WHERE_IDX_ONLY
|
|
|
|
|
|
|
+ if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
|
|
|
|
|
+ ==WHERE_IDX_ONLY
|
|
|
&& (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
|
|
&& (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
|
|
|
&& sqlite3GlobalConfig.bUseCis
|
|
&& sqlite3GlobalConfig.bUseCis
|
|
|
&& OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
|
|
&& OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
|
|
@@ -106878,7 +106847,7 @@ static void bestBtreeIndex(WhereBestIdx *p){
|
|
|
/* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
|
|
/* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
|
|
|
** is set, then reverse the order that the index will be scanned
|
|
** is set, then reverse the order that the index will be scanned
|
|
|
** in. This is used for application testing, to help find cases
|
|
** in. This is used for application testing, to help find cases
|
|
|
- ** where application behaviour depends on the (undefined) order that
|
|
|
|
|
|
|
+ ** where application behavior depends on the (undefined) order that
|
|
|
** SQLite outputs rows in in the absence of an ORDER BY clause. */
|
|
** SQLite outputs rows in in the absence of an ORDER BY clause. */
|
|
|
if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
|
|
if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
|
|
|
p->cost.plan.wsFlags |= WHERE_REVERSE;
|
|
p->cost.plan.wsFlags |= WHERE_REVERSE;
|
|
@@ -114575,7 +114544,7 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
|
|
|
|
|
|
|
/* If we reach this point, it means that the database connection has
|
|
/* If we reach this point, it means that the database connection has
|
|
|
** closed all sqlite3_stmt and sqlite3_backup objects and has been
|
|
** closed all sqlite3_stmt and sqlite3_backup objects and has been
|
|
|
- ** pased to sqlite3_close (meaning that it is a zombie). Therefore,
|
|
|
|
|
|
|
+ ** passed to sqlite3_close (meaning that it is a zombie). Therefore,
|
|
|
** go ahead and free all resources.
|
|
** go ahead and free all resources.
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
@@ -118733,7 +118702,7 @@ struct sqlite3_tokenizer_module {
|
|
|
** This method should return either SQLITE_OK (0), or an SQLite error
|
|
** This method should return either SQLITE_OK (0), or an SQLite error
|
|
|
** code. If SQLITE_OK is returned, then *ppTokenizer should be set
|
|
** code. If SQLITE_OK is returned, then *ppTokenizer should be set
|
|
|
** to point at the newly created tokenizer structure. The generic
|
|
** to point at the newly created tokenizer structure. The generic
|
|
|
- ** sqlite3_tokenizer.pModule variable should not be initialised by
|
|
|
|
|
|
|
+ ** sqlite3_tokenizer.pModule variable should not be initialized by
|
|
|
** this callback. The caller will do so.
|
|
** this callback. The caller will do so.
|
|
|
*/
|
|
*/
|
|
|
int (*xCreate)(
|
|
int (*xCreate)(
|
|
@@ -118838,7 +118807,7 @@ int fts3_term_cnt(int iTerm, int iCol);
|
|
|
** May you share freely, never taking more than you give.
|
|
** May you share freely, never taking more than you give.
|
|
|
**
|
|
**
|
|
|
*************************************************************************
|
|
*************************************************************************
|
|
|
-** This is the header file for the generic hash-table implemenation
|
|
|
|
|
|
|
+** This is the header file for the generic hash-table implementation
|
|
|
** used in SQLite. We've modified it slightly to serve as a standalone
|
|
** used in SQLite. We've modified it slightly to serve as a standalone
|
|
|
** hash table implementation for the full-text indexing module.
|
|
** hash table implementation for the full-text indexing module.
|
|
|
**
|
|
**
|
|
@@ -120745,7 +120714,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
|
|
|
}else{
|
|
}else{
|
|
|
rc = sqlite3_reset(pCsr->pStmt);
|
|
rc = sqlite3_reset(pCsr->pStmt);
|
|
|
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
|
|
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
|
|
|
- /* If no row was found and no error has occured, then the %_content
|
|
|
|
|
|
|
+ /* If no row was found and no error has occurred, then the %_content
|
|
|
** table is missing a row that is present in the full-text index.
|
|
** table is missing a row that is present in the full-text index.
|
|
|
** The data structures are corrupt. */
|
|
** The data structures are corrupt. */
|
|
|
rc = FTS_CORRUPT_VTAB;
|
|
rc = FTS_CORRUPT_VTAB;
|
|
@@ -121985,7 +121954,7 @@ static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
-** This function retreives the doclist for the specified term (or term
|
|
|
|
|
|
|
+** This function retrieves the doclist for the specified term (or term
|
|
|
** prefix) from the database.
|
|
** prefix) from the database.
|
|
|
*/
|
|
*/
|
|
|
static int fts3TermSelect(
|
|
static int fts3TermSelect(
|
|
@@ -122737,7 +122706,7 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const
|
|
|
SQLITE_PRIVATE void sqlite3Fts3SubLatinTokenizerModule(sqlite3_tokenizer_module const**ppModule);
|
|
SQLITE_PRIVATE void sqlite3Fts3SubLatinTokenizerModule(sqlite3_tokenizer_module const**ppModule);
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
-** Initialise the fts3 extension. If this extension is built as part
|
|
|
|
|
|
|
+** Initialize the fts3 extension. If this extension is built as part
|
|
|
** of the sqlite library, then this function is called directly by
|
|
** of the sqlite library, then this function is called directly by
|
|
|
** SQLite. If fts3 is built as a dynamically loadable extension, this
|
|
** SQLite. If fts3 is built as a dynamically loadable extension, this
|
|
|
** function is called by the sqlite3_extension_init() entry point.
|
|
** function is called by the sqlite3_extension_init() entry point.
|
|
@@ -122774,7 +122743,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
|
|
|
sqlite3Fts3PorterTokenizerModule(&pPorter);
|
|
sqlite3Fts3PorterTokenizerModule(&pPorter);
|
|
|
sqlite3Fts3SubLatinTokenizerModule(&pSubLatin);
|
|
sqlite3Fts3SubLatinTokenizerModule(&pSubLatin);
|
|
|
|
|
|
|
|
- /* Allocate and initialise the hash-table used to store tokenizers. */
|
|
|
|
|
|
|
+ /* Allocate and initialize the hash-table used to store tokenizers. */
|
|
|
pHash = sqlite3_malloc(sizeof(Fts3Hash));
|
|
pHash = sqlite3_malloc(sizeof(Fts3Hash));
|
|
|
if( !pHash ){
|
|
if( !pHash ){
|
|
|
rc = SQLITE_NOMEM;
|
|
rc = SQLITE_NOMEM;
|
|
@@ -124373,7 +124342,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
|
|
|
** of the current row.
|
|
** of the current row.
|
|
|
**
|
|
**
|
|
|
** More specifically, the returned buffer contains 1 varint for each
|
|
** More specifically, the returned buffer contains 1 varint for each
|
|
|
-** occurence of the phrase in the column, stored using the normal (delta+2)
|
|
|
|
|
|
|
+** occurrence of the phrase in the column, stored using the normal (delta+2)
|
|
|
** compression and is terminated by either an 0x01 or 0x00 byte. For example,
|
|
** compression and is terminated by either an 0x01 or 0x00 byte. For example,
|
|
|
** if the requested column contains "a b X c d X X" and the position-list
|
|
** if the requested column contains "a b X c d X X" and the position-list
|
|
|
** for 'X' is requested, the buffer returned may contain:
|
|
** for 'X' is requested, the buffer returned may contain:
|
|
@@ -125112,7 +125081,7 @@ struct ParseContext {
|
|
|
** This function is equivalent to the standard isspace() function.
|
|
** This function is equivalent to the standard isspace() function.
|
|
|
**
|
|
**
|
|
|
** The standard isspace() can be awkward to use safely, because although it
|
|
** The standard isspace() can be awkward to use safely, because although it
|
|
|
-** is defined to accept an argument of type int, its behaviour when passed
|
|
|
|
|
|
|
+** is defined to accept an argument of type int, its behavior when passed
|
|
|
** an integer that falls outside of the range of the unsigned char type
|
|
** an integer that falls outside of the range of the unsigned char type
|
|
|
** is undefined (and sometimes, "undefined" means segfault). This wrapper
|
|
** is undefined (and sometimes, "undefined" means segfault). This wrapper
|
|
|
** is defined to accept an argument of type char, and always returns 0 for
|
|
** is defined to accept an argument of type char, and always returns 0 for
|
|
@@ -127480,7 +127449,7 @@ static void intTestFunc(
|
|
|
/*
|
|
/*
|
|
|
** Set up SQL objects in database db used to access the contents of
|
|
** Set up SQL objects in database db used to access the contents of
|
|
|
** the hash table pointed to by argument pHash. The hash table must
|
|
** the hash table pointed to by argument pHash. The hash table must
|
|
|
-** been initialised to use string keys, and to take a private copy
|
|
|
|
|
|
|
+** been initialized to use string keys, and to take a private copy
|
|
|
** of the key when a value is inserted. i.e. by a call similar to:
|
|
** of the key when a value is inserted. i.e. by a call similar to:
|
|
|
**
|
|
**
|
|
|
** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
|
|
** sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
|
|
@@ -129259,6 +129228,7 @@ static int fts3SegReaderNextDocid(
|
|
|
*pnOffsetList = (int)(p - pReader->pOffsetList - 1);
|
|
*pnOffsetList = (int)(p - pReader->pOffsetList - 1);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /* List may have been edited in place by fts3EvalNearTrim() */
|
|
|
while( p<pEnd && *p==0 ) p++;
|
|
while( p<pEnd && *p==0 ) p++;
|
|
|
|
|
|
|
|
/* If there are no more entries in the doclist, set pOffsetList to
|
|
/* If there are no more entries in the doclist, set pOffsetList to
|
|
@@ -130274,9 +130244,13 @@ static int fts3DeleteSegdir(
|
|
|
**
|
|
**
|
|
|
** If there are no entries in the input position list for column iCol, then
|
|
** If there are no entries in the input position list for column iCol, then
|
|
|
** *pnList is set to zero before returning.
|
|
** *pnList is set to zero before returning.
|
|
|
|
|
+**
|
|
|
|
|
+** If parameter bZero is non-zero, then any part of the input list following
|
|
|
|
|
+** the end of the output list is zeroed before returning.
|
|
|
*/
|
|
*/
|
|
|
static void fts3ColumnFilter(
|
|
static void fts3ColumnFilter(
|
|
|
int iCol, /* Column to filter on */
|
|
int iCol, /* Column to filter on */
|
|
|
|
|
+ int bZero, /* Zero out anything following *ppList */
|
|
|
char **ppList, /* IN/OUT: Pointer to position list */
|
|
char **ppList, /* IN/OUT: Pointer to position list */
|
|
|
int *pnList /* IN/OUT: Size of buffer *ppList in bytes */
|
|
int *pnList /* IN/OUT: Size of buffer *ppList in bytes */
|
|
|
){
|
|
){
|
|
@@ -130305,6 +130279,9 @@ static void fts3ColumnFilter(
|
|
|
p += sqlite3Fts3GetVarint32(p, &iCurrent);
|
|
p += sqlite3Fts3GetVarint32(p, &iCurrent);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if( bZero && &pList[nList]!=pEnd ){
|
|
|
|
|
+ memset(&pList[nList], 0, pEnd - &pList[nList]);
|
|
|
|
|
+ }
|
|
|
*ppList = pList;
|
|
*ppList = pList;
|
|
|
*pnList = nList;
|
|
*pnList = nList;
|
|
|
}
|
|
}
|
|
@@ -130378,19 +130355,19 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
|
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
|
fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
|
|
fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
|
|
|
|
|
|
|
|
|
|
+ if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
|
|
|
|
|
+ rc = fts3MsrBufferData(pMsr, pList, nList+1);
|
|
|
|
|
+ if( rc!=SQLITE_OK ) return rc;
|
|
|
|
|
+ assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
|
|
|
|
|
+ pList = pMsr->aBuffer;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if( pMsr->iColFilter>=0 ){
|
|
if( pMsr->iColFilter>=0 ){
|
|
|
- fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
|
|
|
|
|
|
|
+ fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if( nList>0 ){
|
|
if( nList>0 ){
|
|
|
- if( fts3SegReaderIsPending(apSegment[0]) ){
|
|
|
|
|
- rc = fts3MsrBufferData(pMsr, pList, nList+1);
|
|
|
|
|
- if( rc!=SQLITE_OK ) return rc;
|
|
|
|
|
- *paPoslist = pMsr->aBuffer;
|
|
|
|
|
- assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
|
|
|
|
|
- }else{
|
|
|
|
|
- *paPoslist = pList;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ *paPoslist = pList;
|
|
|
*piDocid = iDocid;
|
|
*piDocid = iDocid;
|
|
|
*pnPoslist = nList;
|
|
*pnPoslist = nList;
|
|
|
break;
|
|
break;
|
|
@@ -130633,7 +130610,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if( isColFilter ){
|
|
if( isColFilter ){
|
|
|
- fts3ColumnFilter(pFilter->iCol, &pList, &nList);
|
|
|
|
|
|
|
+ fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if( !isIgnoreEmpty || nList>0 ){
|
|
if( !isIgnoreEmpty || nList>0 ){
|
|
@@ -133570,9 +133547,9 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
|
|
|
** is the snippet with the highest score, where scores are calculated
|
|
** is the snippet with the highest score, where scores are calculated
|
|
|
** by adding:
|
|
** by adding:
|
|
|
**
|
|
**
|
|
|
-** (a) +1 point for each occurence of a matchable phrase in the snippet.
|
|
|
|
|
|
|
+** (a) +1 point for each occurrence of a matchable phrase in the snippet.
|
|
|
**
|
|
**
|
|
|
-** (b) +1000 points for the first occurence of each matchable phrase in
|
|
|
|
|
|
|
+** (b) +1000 points for the first occurrence of each matchable phrase in
|
|
|
** the snippet for which the corresponding mCovered bit is not set.
|
|
** the snippet for which the corresponding mCovered bit is not set.
|
|
|
**
|
|
**
|
|
|
** The selected snippet parameters are stored in structure *pFragment before
|
|
** The selected snippet parameters are stored in structure *pFragment before
|
|
@@ -135168,7 +135145,7 @@ static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
|
|
|
**
|
|
**
|
|
|
** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
|
|
** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
|
|
|
** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
|
|
** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
|
|
|
-** It is not possible to change the behaviour of the tokenizer with respect
|
|
|
|
|
|
|
+** It is not possible to change the behavior of the tokenizer with respect
|
|
|
** to these codepoints.
|
|
** to these codepoints.
|
|
|
*/
|
|
*/
|
|
|
static int unicodeAddExceptions(
|
|
static int unicodeAddExceptions(
|
|
@@ -138471,7 +138448,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
|
|
|
RtreeNode *pRoot; /* Root node of rtree structure */
|
|
RtreeNode *pRoot; /* Root node of rtree structure */
|
|
|
|
|
|
|
|
|
|
|
|
|
- /* Obtain a reference to the root node to initialise Rtree.iDepth */
|
|
|
|
|
|
|
+ /* Obtain a reference to the root node to initialize Rtree.iDepth */
|
|
|
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
|
|
rc = nodeAcquire(pRtree, 1, 0, &pRoot);
|
|
|
|
|
|
|
|
/* Obtain a reference to the leaf node that contains the entry
|
|
/* Obtain a reference to the leaf node that contains the entry
|