Fossil SCM

Update the built-in SQLite to the latest 3.11.0 alpha version.

drh 2016-01-14 14:20 trunk
Commit c9fad621f72c44cc33c8bb6996a30c6562cd144e
2 files changed +2057 -759 +73 -9
+2057 -759
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
11
/******************************************************************************
22
** This file is an amalgamation of many separate C source files from SQLite
3
-** version 3.10.0. By combining all the individual C code files into this
3
+** version 3.11.0. By combining all the individual C code files into this
44
** single large file, the entire code can be compiled as a single translation
55
** unit. This allows many compilers to do optimizations that would not be
66
** possible if the files were compiled separately. Performance improvements
77
** of 5% or more are commonly seen when SQLite is compiled as a single
88
** translation unit.
@@ -119,10 +119,12 @@
119119
#define SQLITE_ENABLE_LOCKING_STYLE 0
120120
#define HAVE_UTIME 1
121121
#else
122122
/* This is not VxWorks. */
123123
#define OS_VXWORKS 0
124
+#define HAVE_FCHOWN 1
125
+#define HAVE_READLINK 1
124126
#endif /* defined(_WRS_KERNEL) */
125127
126128
/************** End of vxworks.h *********************************************/
127129
/************** Continuing where we left off in sqliteInt.h ******************/
128130
@@ -323,13 +325,13 @@
323325
**
324326
** See also: [sqlite3_libversion()],
325327
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
326328
** [sqlite_version()] and [sqlite_source_id()].
327329
*/
328
-#define SQLITE_VERSION "3.10.0"
329
-#define SQLITE_VERSION_NUMBER 3010000
330
-#define SQLITE_SOURCE_ID "2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566"
330
+#define SQLITE_VERSION "3.11.0"
331
+#define SQLITE_VERSION_NUMBER 3011000
332
+#define SQLITE_SOURCE_ID "2016-01-14 14:19:50 d17bc2c92f4d086280e49a3cc72993be7fee2da7"
331333
332334
/*
333335
** CAPI3REF: Run-Time Library Version Numbers
334336
** KEYWORDS: sqlite3_version, sqlite3_sourceid
335337
**
@@ -1006,12 +1008,17 @@
10061008
** improve performance on some systems.
10071009
**
10081010
** <li>[[SQLITE_FCNTL_FILE_POINTER]]
10091011
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
10101012
** to the [sqlite3_file] object associated with a particular database
1011
-** connection. See the [sqlite3_file_control()] documentation for
1012
-** additional information.
1013
+** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER].
1014
+**
1015
+** <li>[[SQLITE_FCNTL_JOURNAL_POINTER]]
1016
+** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer
1017
+** to the [sqlite3_file] object associated with the journal file (either
1018
+** the [rollback journal] or the [write-ahead log]) for a particular database
1019
+** connection. See also [SQLITE_FCNTL_FILE_POINTER].
10131020
**
10141021
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
10151022
** No longer in use.
10161023
**
10171024
** <li>[[SQLITE_FCNTL_SYNC]]
@@ -1222,10 +1229,11 @@
12221229
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
12231230
#define SQLITE_FCNTL_WAL_BLOCK 24
12241231
#define SQLITE_FCNTL_ZIPVFS 25
12251232
#define SQLITE_FCNTL_RBU 26
12261233
#define SQLITE_FCNTL_VFS_POINTER 27
1234
+#define SQLITE_FCNTL_JOURNAL_POINTER 28
12271235
12281236
/* deprecated names */
12291237
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
12301238
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
12311239
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -8399,10 +8407,13 @@
83998407
** If parameter iCol is greater than or equal to the number of columns
84008408
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
84018409
** an OOM condition or IO error), an appropriate SQLite error code is
84028410
** returned.
84038411
**
8412
+** This function may be quite inefficient if used with an FTS5 table
8413
+** created with the "columnsize=0" option.
8414
+**
84048415
** xColumnText:
84058416
** This function attempts to retrieve the text of column iCol of the
84068417
** current document. If successful, (*pz) is set to point to a buffer
84078418
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
84088419
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -8419,18 +8430,32 @@
84198430
** xInstCount:
84208431
** Set *pnInst to the total number of occurrences of all phrases within
84218432
** the query within the current row. Return SQLITE_OK if successful, or
84228433
** an error code (i.e. SQLITE_NOMEM) if an error occurs.
84238434
**
8435
+** This API can be quite slow if used with an FTS5 table created with the
8436
+** "detail=none" or "detail=column" option. If the FTS5 table is created
8437
+** with either "detail=none" or "detail=column" and "content=" option
8438
+** (i.e. if it is a contentless table), then this API always returns 0.
8439
+**
84248440
** xInst:
84258441
** Query for the details of phrase match iIdx within the current row.
84268442
** Phrase matches are numbered starting from zero, so the iIdx argument
84278443
** should be greater than or equal to zero and smaller than the value
84288444
** output by xInstCount().
8445
+**
8446
+** Usually, output parameter *piPhrase is set to the phrase number, *piCol
8447
+** to the column in which it occurs and *piOff the token offset of the
8448
+** first token of the phrase. The exception is if the table was created
8449
+** with the offsets=0 option specified. In this case *piOff is always
8450
+** set to -1.
84298451
**
84308452
** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
84318453
** if an error occurs.
8454
+**
8455
+** This API can be quite slow if used with an FTS5 table created with the
8456
+** "detail=none" or "detail=column" option.
84328457
**
84338458
** xRowid:
84348459
** Returns the rowid of the current row.
84358460
**
84368461
** xTokenize:
@@ -8511,25 +8536,63 @@
85118536
** through instances of phrase iPhrase, use the following code:
85128537
**
85138538
** Fts5PhraseIter iter;
85148539
** int iCol, iOff;
85158540
** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
8516
-** iOff>=0;
8541
+** iCol>=0;
85178542
** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
85188543
** ){
85198544
** // An instance of phrase iPhrase at offset iOff of column iCol
85208545
** }
85218546
**
85228547
** The Fts5PhraseIter structure is defined above. Applications should not
85238548
** modify this structure directly - it should only be used as shown above
8524
-** with the xPhraseFirst() and xPhraseNext() API methods.
8549
+** with the xPhraseFirst() and xPhraseNext() API methods (and by
8550
+** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
8551
+**
8552
+** This API can be quite slow if used with an FTS5 table created with the
8553
+** "detail=none" or "detail=column" option. If the FTS5 table is created
8554
+** with either "detail=none" or "detail=column" and "content=" option
8555
+** (i.e. if it is a contentless table), then this API always iterates
8556
+** through an empty set (all calls to xPhraseFirst() set iCol to -1).
85258557
**
85268558
** xPhraseNext()
85278559
** See xPhraseFirst above.
8560
+**
8561
+** xPhraseFirstColumn()
8562
+** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
8563
+** and xPhraseNext() APIs described above. The difference is that instead
8564
+** of iterating through all instances of a phrase in the current row, these
8565
+** APIs are used to iterate through the set of columns in the current row
8566
+** that contain one or more instances of a specified phrase. For example:
8567
+**
8568
+** Fts5PhraseIter iter;
8569
+** int iCol;
8570
+** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
8571
+** iCol>=0;
8572
+** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
8573
+** ){
8574
+** // Column iCol contains at least one instance of phrase iPhrase
8575
+** }
8576
+**
8577
+** This API can be quite slow if used with an FTS5 table created with the
8578
+** "detail=none" option. If the FTS5 table is created with either
8579
+** "detail=none" "content=" option (i.e. if it is a contentless table),
8580
+** then this API always iterates through an empty set (all calls to
8581
+** xPhraseFirstColumn() set iCol to -1).
8582
+**
8583
+** The information accessed using this API and its companion
8584
+** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
8585
+** (or xInst/xInstCount). The chief advantage of this API is that it is
8586
+** significantly more efficient than those alternatives when used with
8587
+** "detail=column" tables.
8588
+**
8589
+** xPhraseNextColumn()
8590
+** See xPhraseFirstColumn above.
85288591
*/
85298592
struct Fts5ExtensionApi {
8530
- int iVersion; /* Currently always set to 1 */
8593
+ int iVersion; /* Currently always set to 3 */
85318594
85328595
void *(*xUserData)(Fts5Context*);
85338596
85348597
int (*xColumnCount)(Fts5Context*);
85358598
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -8555,12 +8618,15 @@
85558618
int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
85568619
);
85578620
int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
85588621
void *(*xGetAuxdata)(Fts5Context*, int bClear);
85598622
8560
- void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
8623
+ int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
85618624
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
8625
+
8626
+ int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
8627
+ void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
85628628
};
85638629
85648630
/*
85658631
** CUSTOM AUXILIARY FUNCTIONS
85668632
*************************************************************************/
@@ -9976,14 +10042,10 @@
997610042
/*
997710043
** Default maximum size of memory used by memory-mapped I/O in the VFS
997810044
*/
997910045
#ifdef __APPLE__
998010046
# include <TargetConditionals.h>
9981
-# if TARGET_OS_IPHONE
9982
-# undef SQLITE_MAX_MMAP_SIZE
9983
-# define SQLITE_MAX_MMAP_SIZE 0
9984
-# endif
998510047
#endif
998610048
#ifndef SQLITE_MAX_MMAP_SIZE
998710049
# if defined(__linux__) \
998810050
|| defined(_WIN32) \
998910051
|| (defined(__APPLE__) && defined(__MACH__)) \
@@ -10479,19 +10541,21 @@
1047910541
** Enter and Leave procedures no-ops.
1048010542
*/
1048110543
#ifndef SQLITE_OMIT_SHARED_CACHE
1048210544
SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*);
1048310545
SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*);
10546
+SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*);
10547
+SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*);
1048410548
#else
1048510549
# define sqlite3BtreeEnter(X)
1048610550
# define sqlite3BtreeEnterAll(X)
10551
+# define sqlite3BtreeSharable(X) 0
10552
+# define sqlite3BtreeEnterCursor(X)
1048710553
#endif
1048810554
1048910555
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
10490
-SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*);
1049110556
SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*);
10492
-SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*);
1049310557
SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*);
1049410558
SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*);
1049510559
#ifndef NDEBUG
1049610560
/* These routines are used inside assert() statements only. */
1049710561
SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*);
@@ -10498,13 +10562,11 @@
1049810562
SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*);
1049910563
SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
1050010564
#endif
1050110565
#else
1050210566
10503
-# define sqlite3BtreeSharable(X) 0
1050410567
# define sqlite3BtreeLeave(X)
10505
-# define sqlite3BtreeEnterCursor(X)
1050610568
# define sqlite3BtreeLeaveCursor(X)
1050710569
# define sqlite3BtreeLeaveAll(X)
1050810570
1050910571
# define sqlite3BtreeHoldsMutex(X) 1
1051010572
# define sqlite3BtreeHoldsAllMutexes(X) 1
@@ -11215,10 +11277,11 @@
1121511277
#endif
1121611278
SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
1121711279
SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
1121811280
SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*);
1121911281
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
11282
+SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*);
1122011283
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
1122111284
SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
1122211285
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
1122311286
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
1122411287
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
@@ -11309,10 +11372,12 @@
1130911372
#define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before
1131011373
** writing this page to the database */
1131111374
#define PGHDR_NEED_READ 0x010 /* Content is unread */
1131211375
#define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
1131311376
#define PGHDR_MMAP 0x040 /* This is an mmap page object */
11377
+
11378
+#define PGHDR_WAL_APPEND 0x080 /* Appended to wal file */
1131411379
1131511380
/* Initialize and shutdown the page cache subsystem */
1131611381
SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
1131711382
SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
1131811383
@@ -14135,11 +14200,10 @@
1413514200
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
1413614201
SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
1413714202
SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
1413814203
SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
1413914204
SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
14140
-SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
1414114205
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
1414214206
SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
1414314207
SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
1414414208
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
1414514209
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
@@ -16066,15 +16130,19 @@
1606616130
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
1606716131
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
1606816132
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
1606916133
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
1607016134
16071
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
16135
+#if !defined(SQLITE_OMIT_SHARED_CACHE)
1607216136
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
16073
-SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
1607416137
#else
1607516138
# define sqlite3VdbeEnter(X)
16139
+#endif
16140
+
16141
+#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
16142
+SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
16143
+#else
1607616144
# define sqlite3VdbeLeave(X)
1607716145
#endif
1607816146
1607916147
#ifdef SQLITE_DEBUG
1608016148
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
@@ -19758,10 +19826,11 @@
1975819826
/*
1975919827
** Mutex to control access to the memory allocation subsystem.
1976019828
*/
1976119829
sqlite3_mutex *mutex;
1976219830
19831
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
1976319832
/*
1976419833
** Performance statistics
1976519834
*/
1976619835
u64 nAlloc; /* Total number of calls to malloc */
1976719836
u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
@@ -19769,10 +19838,11 @@
1976919838
u32 currentOut; /* Current checkout, including internal fragmentation */
1977019839
u32 currentCount; /* Current number of distinct checkouts */
1977119840
u32 maxOut; /* Maximum instantaneous currentOut */
1977219841
u32 maxCount; /* Maximum instantaneous currentCount */
1977319842
u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
19843
+#endif
1977419844
1977519845
/*
1977619846
** Lists of free blocks. aiFreelist[0] is a list of free blocks of
1977719847
** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
1977819848
** aiFreelist[2] holds free blocks of size szAtom*4. And so forth.
@@ -19880,18 +19950,21 @@
1988019950
int iLogsize; /* Log2 of iFullSz/POW2_MIN */
1988119951
1988219952
/* nByte must be a positive */
1988319953
assert( nByte>0 );
1988419954
19955
+ /* No more than 1GiB per allocation */
19956
+ if( nByte > 0x40000000 ) return 0;
19957
+
19958
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
1988519959
/* Keep track of the maximum allocation request. Even unfulfilled
1988619960
** requests are counted */
1988719961
if( (u32)nByte>mem5.maxRequest ){
19888
- /* Abort if the requested allocation size is larger than the largest
19889
- ** power of two that we can represent using 32-bit signed integers. */
19890
- if( nByte > 0x40000000 ) return 0;
1989119962
mem5.maxRequest = nByte;
1989219963
}
19964
+#endif
19965
+
1989319966
1989419967
/* Round nByte up to the next valid power of two */
1989519968
for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){}
1989619969
1989719970
/* Make sure mem5.aiFreelist[iLogsize] contains at least one free
@@ -19914,18 +19987,20 @@
1991419987
mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
1991519988
memsys5Link(i+newSize, iBin);
1991619989
}
1991719990
mem5.aCtrl[i] = iLogsize;
1991819991
19992
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
1991919993
/* Update allocator performance statistics. */
1992019994
mem5.nAlloc++;
1992119995
mem5.totalAlloc += iFullSz;
1992219996
mem5.totalExcess += iFullSz - nByte;
1992319997
mem5.currentCount++;
1992419998
mem5.currentOut += iFullSz;
1992519999
if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
1992620000
if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
20001
+#endif
1992720002
1992820003
#ifdef SQLITE_DEBUG
1992920004
/* Make sure the allocated memory does not assume that it is set to zero
1993020005
** or retains a value from a previous allocation */
1993120006
memset(&mem5.zPool[i*mem5.szAtom], 0xAA, iFullSz);
@@ -19956,16 +20031,19 @@
1995620031
size = 1<<iLogsize;
1995720032
assert( iBlock+size-1<(u32)mem5.nBlock );
1995820033
1995920034
mem5.aCtrl[iBlock] |= CTRL_FREE;
1996020035
mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
20036
+
20037
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
1996120038
assert( mem5.currentCount>0 );
1996220039
assert( mem5.currentOut>=(size*mem5.szAtom) );
1996320040
mem5.currentCount--;
1996420041
mem5.currentOut -= size*mem5.szAtom;
1996520042
assert( mem5.currentOut>0 || mem5.currentCount==0 );
1996620043
assert( mem5.currentCount>0 || mem5.currentOut==0 );
20044
+#endif
1996720045
1996820046
mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
1996920047
while( ALWAYS(iLogsize<LOGMAX) ){
1997020048
int iBuddy;
1997120049
if( (iBlock>>iLogsize) & 1 ){
@@ -27479,37 +27557,55 @@
2747927557
#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
2748027558
2748127559
{ "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
2748227560
#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
2748327561
27562
+#if defined(HAVE_FCHOWN)
2748427563
{ "fchown", (sqlite3_syscall_ptr)fchown, 0 },
27564
+#else
27565
+ { "fchown", (sqlite3_syscall_ptr)0, 0 },
27566
+#endif
2748527567
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
2748627568
2748727569
{ "geteuid", (sqlite3_syscall_ptr)geteuid, 0 },
2748827570
#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
2748927571
2749027572
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
27491
- { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
27573
+ { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
27574
+#else
27575
+ { "mmap", (sqlite3_syscall_ptr)0, 0 },
27576
+#endif
2749227577
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
2749327578
27579
+#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
2749427580
{ "munmap", (sqlite3_syscall_ptr)munmap, 0 },
27581
+#else
27582
+ { "munmap", (sqlite3_syscall_ptr)0, 0 },
27583
+#endif
2749527584
#define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent)
2749627585
27497
-#if HAVE_MREMAP
27586
+#if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
2749827587
{ "mremap", (sqlite3_syscall_ptr)mremap, 0 },
2749927588
#else
2750027589
{ "mremap", (sqlite3_syscall_ptr)0, 0 },
2750127590
#endif
2750227591
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent)
2750327592
27593
+#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
2750427594
{ "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
27595
+#else
27596
+ { "getpagesize", (sqlite3_syscall_ptr)0, 0 },
27597
+#endif
2750527598
#define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent)
2750627599
27600
+#if defined(HAVE_READLINK)
2750727601
{ "readlink", (sqlite3_syscall_ptr)readlink, 0 },
27602
+#else
27603
+ { "readlink", (sqlite3_syscall_ptr)0, 0 },
27604
+#endif
2750827605
#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
2750927606
27510
-#endif
2751127607
2751227608
}; /* End of the overrideable system calls */
2751327609
2751427610
2751527611
/*
@@ -27516,14 +27612,14 @@
2751627612
** On some systems, calls to fchown() will trigger a message in a security
2751727613
** log if they come from non-root processes. So avoid calling fchown() if
2751827614
** we are not running as root.
2751927615
*/
2752027616
static int robustFchown(int fd, uid_t uid, gid_t gid){
27521
-#if OS_VXWORKS
27522
- return 0;
27523
-#else
27617
+#if defined(HAVE_FCHOWN)
2752427618
return osGeteuid() ? 0 : osFchown(fd,uid,gid);
27619
+#else
27620
+ return 0;
2752527621
#endif
2752627622
}
2752727623
2752827624
/*
2752927625
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
@@ -32986,10 +33082,11 @@
3298633082
SimulateIOError( return SQLITE_ERROR );
3298733083
3298833084
assert( pVfs->mxPathname==MAX_PATHNAME );
3298933085
UNUSED_PARAMETER(pVfs);
3299033086
33087
+#if defined(HAVE_READLINK)
3299133088
/* Attempt to resolve the path as if it were a symbolic link. If it is
3299233089
** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if
3299333090
** the identified file is not a symbolic link or does not exist, then
3299433091
** zPath is copied directly into zOut. Either way, nByte is left set to
3299533092
** the size of the string copied into zOut[] in bytes. */
@@ -33001,10 +33098,11 @@
3300133098
sqlite3_snprintf(nOut, zOut, "%s", zPath);
3300233099
nByte = sqlite3Strlen30(zOut);
3300333100
}else{
3300433101
zOut[nByte] = '\0';
3300533102
}
33103
+#endif
3300633104
3300733105
/* If buffer zOut[] now contains an absolute path there is nothing more
3300833106
** to do. If it contains a relative path, do the following:
3300933107
**
3301033108
** * move the relative path string so that it is at the end of th
@@ -43327,10 +43425,11 @@
4332743425
# define sqlite3WalCallback(z) 0
4332843426
# define sqlite3WalExclusiveMode(y,z) 0
4332943427
# define sqlite3WalHeapMemory(z) 0
4333043428
# define sqlite3WalFramesize(z) 0
4333143429
# define sqlite3WalFindFrame(x,y,z) 0
43430
+# define sqlite3WalFile(x) 0
4333243431
#else
4333343432
4333443433
#define WAL_SAVEPOINT_NDATA 4
4333543434
4333643435
/* Connection to a write-ahead log (WAL) file.
@@ -43421,10 +43520,13 @@
4342143520
** stored in each frame (i.e. the db page-size when the WAL was created).
4342243521
*/
4342343522
SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
4342443523
#endif
4342543524
43525
+/* Return the sqlite3_file object for the WAL file */
43526
+SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
43527
+
4342643528
#endif /* ifndef SQLITE_OMIT_WAL */
4342743529
#endif /* _WAL_H_ */
4342843530
4342943531
/************** End of wal.h *************************************************/
4343043532
/************** Continuing where we left off in pager.c **********************/
@@ -49032,11 +49134,11 @@
4903249134
if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
4903349135
rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
4903449136
if( rc!=SQLITE_OK ){
4903549137
return rc;
4903649138
}
49037
- sqlite3WalExclusiveMode(pPager->pWal, 1);
49139
+ (void)sqlite3WalExclusiveMode(pPager->pWal, 1);
4903849140
}
4903949141
4904049142
/* Grab the write lock on the log file. If successful, upgrade to
4904149143
** PAGER_RESERVED state. Otherwise, return an error code to the caller.
4904249144
** The busy-handler is not invoked if another connection already
@@ -50096,10 +50198,22 @@
5009650198
** not yet been opened.
5009750199
*/
5009850200
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
5009950201
return pPager->fd;
5010050202
}
50203
+
50204
+/*
50205
+** Return the file handle for the journal file (if it exists).
50206
+** This will be either the rollback journal or the WAL file.
50207
+*/
50208
+SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
50209
+#if SQLITE_OMIT_WAL
50210
+ return pPager->jfd;
50211
+#else
50212
+ return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
50213
+#endif
50214
+}
5010150215
5010250216
/*
5010350217
** Return the full pathname of the journal file.
5010450218
*/
5010550219
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
@@ -51202,10 +51316,11 @@
5120251316
u8 truncateOnCommit; /* True to truncate WAL file on commit */
5120351317
u8 syncHeader; /* Fsync the WAL header if true */
5120451318
u8 padToSectorBoundary; /* Pad transactions out to the next sector */
5120551319
WalIndexHdr hdr; /* Wal-index header for current transaction */
5120651320
u32 minFrame; /* Ignore wal frames before this one */
51321
+ u32 iReCksum; /* On commit, recalculate checksums from here */
5120751322
const char *zWalName; /* Name of WAL file */
5120851323
u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
5120951324
#ifdef SQLITE_DEBUG
5121051325
u8 lockError; /* True if a locking error has occurred */
5121151326
#endif
@@ -51455,18 +51570,22 @@
5145551570
int nativeCksum; /* True for native byte-order checksums */
5145651571
u32 *aCksum = pWal->hdr.aFrameCksum;
5145751572
assert( WAL_FRAME_HDRSIZE==24 );
5145851573
sqlite3Put4byte(&aFrame[0], iPage);
5145951574
sqlite3Put4byte(&aFrame[4], nTruncate);
51460
- memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
51461
-
51462
- nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
51463
- walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
51464
- walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
51465
-
51466
- sqlite3Put4byte(&aFrame[16], aCksum[0]);
51467
- sqlite3Put4byte(&aFrame[20], aCksum[1]);
51575
+ if( pWal->iReCksum==0 ){
51576
+ memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
51577
+
51578
+ nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
51579
+ walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
51580
+ walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
51581
+
51582
+ sqlite3Put4byte(&aFrame[16], aCksum[0]);
51583
+ sqlite3Put4byte(&aFrame[20], aCksum[1]);
51584
+ }else{
51585
+ memset(&aFrame[8], 0, 16);
51586
+ }
5146851587
}
5146951588
5147051589
/*
5147151590
** Check to see if the frame with header in aFrame[] and content
5147251591
** in aData[] is valid. If it is a valid frame, fill *piPage and
@@ -53389,10 +53508,11 @@
5338953508
int rc;
5339053509
5339153510
/* Cannot start a write transaction without first holding a read
5339253511
** transaction. */
5339353512
assert( pWal->readLock>=0 );
53513
+ assert( pWal->writeLock==0 && pWal->iReCksum==0 );
5339453514
5339553515
if( pWal->readOnly ){
5339653516
return SQLITE_READONLY;
5339753517
}
5339853518
@@ -53424,10 +53544,11 @@
5342453544
*/
5342553545
SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){
5342653546
if( pWal->writeLock ){
5342753547
walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
5342853548
pWal->writeLock = 0;
53549
+ pWal->iReCksum = 0;
5342953550
pWal->truncateOnCommit = 0;
5343053551
}
5343153552
return SQLITE_OK;
5343253553
}
5343353554
@@ -53641,10 +53762,63 @@
5364153762
if( rc ) return rc;
5364253763
/* Write the page data */
5364353764
rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
5364453765
return rc;
5364553766
}
53767
+
53768
+/*
53769
+** This function is called as part of committing a transaction within which
53770
+** one or more frames have been overwritten. It updates the checksums for
53771
+** all frames written to the wal file by the current transaction starting
53772
+** with the earliest to have been overwritten.
53773
+**
53774
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
53775
+*/
53776
+static int walRewriteChecksums(Wal *pWal, u32 iLast){
53777
+ const int szPage = pWal->szPage;/* Database page size */
53778
+ int rc = SQLITE_OK; /* Return code */
53779
+ u8 *aBuf; /* Buffer to load data from wal file into */
53780
+ u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-headers in */
53781
+ u32 iRead; /* Next frame to read from wal file */
53782
+ i64 iCksumOff;
53783
+
53784
+ aBuf = sqlite3_malloc(szPage + WAL_FRAME_HDRSIZE);
53785
+ if( aBuf==0 ) return SQLITE_NOMEM;
53786
+
53787
+ /* Find the checksum values to use as input for the recalculating the
53788
+ ** first checksum. If the first frame is frame 1 (implying that the current
53789
+ ** transaction restarted the wal file), these values must be read from the
53790
+ ** wal-file header. Otherwise, read them from the frame header of the
53791
+ ** previous frame. */
53792
+ assert( pWal->iReCksum>0 );
53793
+ if( pWal->iReCksum==1 ){
53794
+ iCksumOff = 24;
53795
+ }else{
53796
+ iCksumOff = walFrameOffset(pWal->iReCksum-1, szPage) + 16;
53797
+ }
53798
+ rc = sqlite3OsRead(pWal->pWalFd, aBuf, sizeof(u32)*2, iCksumOff);
53799
+ pWal->hdr.aFrameCksum[0] = sqlite3Get4byte(aBuf);
53800
+ pWal->hdr.aFrameCksum[1] = sqlite3Get4byte(&aBuf[sizeof(u32)]);
53801
+
53802
+ iRead = pWal->iReCksum;
53803
+ pWal->iReCksum = 0;
53804
+ for(; rc==SQLITE_OK && iRead<=iLast; iRead++){
53805
+ i64 iOff = walFrameOffset(iRead, szPage);
53806
+ rc = sqlite3OsRead(pWal->pWalFd, aBuf, szPage+WAL_FRAME_HDRSIZE, iOff);
53807
+ if( rc==SQLITE_OK ){
53808
+ u32 iPgno, nDbSize;
53809
+ iPgno = sqlite3Get4byte(aBuf);
53810
+ nDbSize = sqlite3Get4byte(&aBuf[4]);
53811
+
53812
+ walEncodeFrame(pWal, iPgno, nDbSize, &aBuf[WAL_FRAME_HDRSIZE], aFrame);
53813
+ rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOff);
53814
+ }
53815
+ }
53816
+
53817
+ sqlite3_free(aBuf);
53818
+ return rc;
53819
+}
5364653820
5364753821
/*
5364853822
** Write a set of frames to the log. The caller must hold the write-lock
5364953823
** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
5365053824
*/
@@ -53662,10 +53836,12 @@
5366253836
PgHdr *pLast = 0; /* Last frame in list */
5366353837
int nExtra = 0; /* Number of extra copies of last page */
5366453838
int szFrame; /* The size of a single frame */
5366553839
i64 iOffset; /* Next byte to write in WAL file */
5366653840
WalWriter w; /* The writer */
53841
+ u32 iFirst = 0; /* First frame that may be overwritten */
53842
+ WalIndexHdr *pLive; /* Pointer to shared header */
5366753843
5366853844
assert( pList );
5366953845
assert( pWal->writeLock );
5367053846
5367153847
/* If this frame set completes a transaction, then nTruncate>0. If
@@ -53676,10 +53852,15 @@
5367653852
{ int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
5367753853
WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
5367853854
pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
5367953855
}
5368053856
#endif
53857
+
53858
+ pLive = (WalIndexHdr*)walIndexHdr(pWal);
53859
+ if( memcmp(&pWal->hdr, (void *)pLive, sizeof(WalIndexHdr))!=0 ){
53860
+ iFirst = pLive->mxFrame+1;
53861
+ }
5368153862
5368253863
/* See if it is possible to write these frames into the start of the
5368353864
** log file, instead of appending to it at pWal->hdr.mxFrame.
5368453865
*/
5368553866
if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
@@ -53741,17 +53922,45 @@
5374153922
szFrame = szPage + WAL_FRAME_HDRSIZE;
5374253923
5374353924
/* Write all frames into the log file exactly once */
5374453925
for(p=pList; p; p=p->pDirty){
5374553926
int nDbSize; /* 0 normally. Positive == commit flag */
53927
+
53928
+ /* Check if this page has already been written into the wal file by
53929
+ ** the current transaction. If so, overwrite the existing frame and
53930
+ ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that
53931
+ ** checksums must be recomputed when the transaction is committed. */
53932
+ if( iFirst && (p->pDirty || isCommit==0) ){
53933
+ u32 iWrite = 0;
53934
+ VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite);
53935
+ assert( rc==SQLITE_OK || iWrite==0 );
53936
+ if( iWrite>=iFirst ){
53937
+ i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
53938
+ if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){
53939
+ pWal->iReCksum = iWrite;
53940
+ }
53941
+ rc = sqlite3OsWrite(pWal->pWalFd, p->pData, szPage, iOff);
53942
+ if( rc ) return rc;
53943
+ p->flags &= ~PGHDR_WAL_APPEND;
53944
+ continue;
53945
+ }
53946
+ }
53947
+
5374653948
iFrame++;
5374753949
assert( iOffset==walFrameOffset(iFrame, szPage) );
5374853950
nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0;
5374953951
rc = walWriteOneFrame(&w, p, nDbSize, iOffset);
5375053952
if( rc ) return rc;
5375153953
pLast = p;
5375253954
iOffset += szFrame;
53955
+ p->flags |= PGHDR_WAL_APPEND;
53956
+ }
53957
+
53958
+ /* Recalculate checksums within the wal file if required. */
53959
+ if( isCommit && pWal->iReCksum ){
53960
+ rc = walRewriteChecksums(pWal, iFrame);
53961
+ if( rc ) return rc;
5375353962
}
5375453963
5375553964
/* If this is the end of a transaction, then we might need to pad
5375653965
** the transaction and/or sync the WAL file.
5375753966
**
@@ -53799,10 +54008,11 @@
5379954008
** guarantees that there are no other writers, and no data that may
5380054009
** be in use by existing readers is being overwritten.
5380154010
*/
5380254011
iFrame = pWal->hdr.mxFrame;
5380354012
for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
54013
+ if( (p->flags & PGHDR_WAL_APPEND)==0 ) continue;
5380454014
iFrame++;
5380554015
rc = walIndexAppend(pWal, iFrame, p->pgno);
5380654016
}
5380754017
while( rc==SQLITE_OK && nExtra>0 ){
5380854018
iFrame++;
@@ -53911,10 +54121,11 @@
5391154121
}
5391254122
}
5391354123
5391454124
/* Copy data from the log to the database file. */
5391554125
if( rc==SQLITE_OK ){
54126
+
5391654127
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
5391754128
rc = SQLITE_CORRUPT_BKPT;
5391854129
}else{
5391954130
rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
5392054131
}
@@ -54066,10 +54277,16 @@
5406654277
SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
5406754278
assert( pWal==0 || pWal->readLock>=0 );
5406854279
return (pWal ? pWal->szPage : 0);
5406954280
}
5407054281
#endif
54282
+
54283
+/* Return the sqlite3_file object for the WAL file
54284
+*/
54285
+SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
54286
+ return pWal->pWalFd;
54287
+}
5407154288
5407254289
#endif /* #ifndef SQLITE_OMIT_WAL */
5407354290
5407454291
/************** End of wal.c *************************************************/
5407554292
/************** Begin file btmutex.c *****************************************/
@@ -54368,11 +54585,10 @@
5436854585
struct MemPage {
5436954586
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
5437054587
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
5437154588
u8 intKey; /* True if table b-trees. False for index b-trees */
5437254589
u8 intKeyLeaf; /* True if the leaf of an intKey table */
54373
- u8 noPayload; /* True if internal intKey page (thus w/o data) */
5437454590
u8 leaf; /* True if a leaf page */
5437554591
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
5437654592
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
5437754593
u8 max1bytePayload; /* min(maxLocal,127) */
5437854594
u8 bBusy; /* Prevent endless loops on corrupt database files */
@@ -54955,25 +55171,10 @@
5495555171
5495655172
return (p->sharable==0 || p->locked);
5495755173
}
5495855174
#endif
5495955175
54960
-
54961
-#ifndef SQLITE_OMIT_INCRBLOB
54962
-/*
54963
-** Enter and leave a mutex on a Btree given a cursor owned by that
54964
-** Btree. These entry points are used by incremental I/O and can be
54965
-** omitted if that module is not used.
54966
-*/
54967
-SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){
54968
- sqlite3BtreeEnter(pCur->pBtree);
54969
-}
54970
-SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
54971
- sqlite3BtreeLeave(pCur->pBtree);
54972
-}
54973
-#endif /* SQLITE_OMIT_INCRBLOB */
54974
-
5497555176
5497655177
/*
5497755178
** Enter the mutex on every Btree associated with a database
5497855179
** connection. This is needed (for example) prior to parsing
5497955180
** a statement since we will be comparing table and column names
@@ -55004,18 +55205,10 @@
5500455205
p = db->aDb[i].pBt;
5500555206
if( p ) sqlite3BtreeLeave(p);
5500655207
}
5500755208
}
5500855209
55009
-/*
55010
-** Return true if a particular Btree requires a lock. Return FALSE if
55011
-** no lock is ever required since it is not sharable.
55012
-*/
55013
-SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){
55014
- return p->sharable;
55015
-}
55016
-
5501755210
#ifndef NDEBUG
5501855211
/*
5501955212
** Return true if the current thread holds the database connection
5502055213
** mutex and all required BtShared mutexes.
5502155214
**
@@ -55085,10 +55278,29 @@
5508555278
p->pBt->db = p->db;
5508655279
}
5508755280
}
5508855281
}
5508955282
#endif /* if SQLITE_THREADSAFE */
55283
+
55284
+#ifndef SQLITE_OMIT_INCRBLOB
55285
+/*
55286
+** Enter a mutex on a Btree given a cursor owned by that Btree.
55287
+**
55288
+** These entry points are used by incremental I/O only. Enter() is required
55289
+** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not
55290
+** the build is threadsafe. Leave() is only required by threadsafe builds.
55291
+*/
55292
+SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){
55293
+ sqlite3BtreeEnter(pCur->pBtree);
55294
+}
55295
+# if SQLITE_THREADSAFE
55296
+SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
55297
+ sqlite3BtreeLeave(pCur->pBtree);
55298
+}
55299
+# endif
55300
+#endif /* ifndef SQLITE_OMIT_INCRBLOB */
55301
+
5509055302
#endif /* ifndef SQLITE_OMIT_SHARED_CACHE */
5509155303
5509255304
/************** End of btmutex.c *********************************************/
5509355305
/************** Begin file btree.c *******************************************/
5509455306
/*
@@ -55541,10 +55753,14 @@
5554155753
*/
5554255754
#ifdef SQLITE_DEBUG
5554355755
static int cursorHoldsMutex(BtCursor *p){
5554455756
return sqlite3_mutex_held(p->pBt->mutex);
5554555757
}
55758
+static int cursorOwnsBtShared(BtCursor *p){
55759
+ assert( cursorHoldsMutex(p) );
55760
+ return (p->pBtree->db==p->pBt->db);
55761
+}
5554655762
#endif
5554755763
5554855764
/*
5554955765
** Invalidate the overflow cache of the cursor passed as the first argument.
5555055766
** on the shared btree structure pBt.
@@ -55877,11 +56093,11 @@
5587756093
** saveCursorPosition().
5587856094
*/
5587956095
static int btreeRestoreCursorPosition(BtCursor *pCur){
5588056096
int rc;
5588156097
int skipNext;
55882
- assert( cursorHoldsMutex(pCur) );
56098
+ assert( cursorOwnsBtShared(pCur) );
5588356099
assert( pCur->eState>=CURSOR_REQUIRESEEK );
5588456100
if( pCur->eState==CURSOR_FAULT ){
5588556101
return pCur->skipNext;
5588656102
}
5588756103
pCur->eState = CURSOR_INVALID;
@@ -56166,11 +56382,10 @@
5616656382
u8 *pCell, /* Pointer to the cell text. */
5616756383
CellInfo *pInfo /* Fill in this structure */
5616856384
){
5616956385
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
5617056386
assert( pPage->leaf==0 );
56171
- assert( pPage->noPayload );
5617256387
assert( pPage->childPtrSize==4 );
5617356388
#ifndef SQLITE_DEBUG
5617456389
UNUSED_PARAMETER(pPage);
5617556390
#endif
5617656391
pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
@@ -56188,12 +56403,10 @@
5618856403
u32 nPayload; /* Number of bytes of cell payload */
5618956404
u64 iKey; /* Extracted Key value */
5619056405
5619156406
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
5619256407
assert( pPage->leaf==0 || pPage->leaf==1 );
56193
- assert( pPage->intKeyLeaf || pPage->noPayload );
56194
- assert( pPage->noPayload==0 );
5619556408
assert( pPage->intKeyLeaf );
5619656409
assert( pPage->childPtrSize==0 );
5619756410
pIter = pCell;
5619856411
5619956412
/* The next block of code is equivalent to:
@@ -56258,11 +56471,10 @@
5625856471
u32 nPayload; /* Number of bytes of cell payload */
5625956472
5626056473
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
5626156474
assert( pPage->leaf==0 || pPage->leaf==1 );
5626256475
assert( pPage->intKeyLeaf==0 );
56263
- assert( pPage->noPayload==0 );
5626456476
pIter = pCell + pPage->childPtrSize;
5626556477
nPayload = *pIter;
5626656478
if( nPayload>=0x80 ){
5626756479
u8 *pEnd = &pIter[8];
5626856480
nPayload &= 0x7f;
@@ -56319,11 +56531,10 @@
5631956531
** this function verifies that this invariant is not violated. */
5632056532
CellInfo debuginfo;
5632156533
pPage->xParseCell(pPage, pCell, &debuginfo);
5632256534
#endif
5632356535
56324
- assert( pPage->noPayload==0 );
5632556536
nSize = *pIter;
5632656537
if( nSize>=0x80 ){
5632756538
pEnd = &pIter[8];
5632856539
nSize &= 0x7f;
5632956540
do{
@@ -56777,15 +56988,13 @@
5677756988
** table b-tree page. */
5677856989
assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
5677956990
pPage->intKey = 1;
5678056991
if( pPage->leaf ){
5678156992
pPage->intKeyLeaf = 1;
56782
- pPage->noPayload = 0;
5678356993
pPage->xParseCell = btreeParseCellPtr;
5678456994
}else{
5678556995
pPage->intKeyLeaf = 0;
56786
- pPage->noPayload = 1;
5678756996
pPage->xCellSize = cellSizePtrNoPayload;
5678856997
pPage->xParseCell = btreeParseCellPtrNoPayload;
5678956998
}
5679056999
pPage->maxLocal = pBt->maxLeaf;
5679157000
pPage->minLocal = pBt->minLeaf;
@@ -56796,11 +57005,10 @@
5679657005
/* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf
5679757006
** index b-tree page. */
5679857007
assert( (PTF_ZERODATA|PTF_LEAF)==10 );
5679957008
pPage->intKey = 0;
5680057009
pPage->intKeyLeaf = 0;
56801
- pPage->noPayload = 0;
5680257010
pPage->xParseCell = btreeParseCellPtrIndex;
5680357011
pPage->maxLocal = pBt->maxLocal;
5680457012
pPage->minLocal = pBt->minLocal;
5680557013
}else{
5680657014
/* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
@@ -58217,11 +58425,10 @@
5821758425
** no progress. By returning SQLITE_BUSY and not invoking the busy callback
5821858426
** when A already has a read lock, we encourage A to give up and let B
5821958427
** proceed.
5822058428
*/
5822158429
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
58222
- sqlite3 *pBlock = 0;
5822358430
BtShared *pBt = p->pBt;
5822458431
int rc = SQLITE_OK;
5822558432
5822658433
sqlite3BtreeEnter(p);
5822758434
btreeIntegrity(p);
@@ -58240,31 +58447,34 @@
5824058447
rc = SQLITE_READONLY;
5824158448
goto trans_begun;
5824258449
}
5824358450
5824458451
#ifndef SQLITE_OMIT_SHARED_CACHE
58245
- /* If another database handle has already opened a write transaction
58246
- ** on this shared-btree structure and a second write transaction is
58247
- ** requested, return SQLITE_LOCKED.
58248
- */
58249
- if( (wrflag && pBt->inTransaction==TRANS_WRITE)
58250
- || (pBt->btsFlags & BTS_PENDING)!=0
58251
- ){
58252
- pBlock = pBt->pWriter->db;
58253
- }else if( wrflag>1 ){
58254
- BtLock *pIter;
58255
- for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
58256
- if( pIter->pBtree!=p ){
58257
- pBlock = pIter->pBtree->db;
58258
- break;
58259
- }
58260
- }
58261
- }
58262
- if( pBlock ){
58263
- sqlite3ConnectionBlocked(p->db, pBlock);
58264
- rc = SQLITE_LOCKED_SHAREDCACHE;
58265
- goto trans_begun;
58452
+ {
58453
+ sqlite3 *pBlock = 0;
58454
+ /* If another database handle has already opened a write transaction
58455
+ ** on this shared-btree structure and a second write transaction is
58456
+ ** requested, return SQLITE_LOCKED.
58457
+ */
58458
+ if( (wrflag && pBt->inTransaction==TRANS_WRITE)
58459
+ || (pBt->btsFlags & BTS_PENDING)!=0
58460
+ ){
58461
+ pBlock = pBt->pWriter->db;
58462
+ }else if( wrflag>1 ){
58463
+ BtLock *pIter;
58464
+ for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
58465
+ if( pIter->pBtree!=p ){
58466
+ pBlock = pIter->pBtree->db;
58467
+ break;
58468
+ }
58469
+ }
58470
+ }
58471
+ if( pBlock ){
58472
+ sqlite3ConnectionBlocked(p->db, pBlock);
58473
+ rc = SQLITE_LOCKED_SHAREDCACHE;
58474
+ goto trans_begun;
58475
+ }
5826658476
}
5826758477
#endif
5826858478
5826958479
/* Any read-only or read-write transaction implies a read-lock on
5827058480
** page 1. So if some other shared-cache client already has a write-lock
@@ -59377,11 +59587,11 @@
5937759587
** Failure is not possible. This function always returns SQLITE_OK.
5937859588
** It might just as well be a procedure (returning void) but we continue
5937959589
** to return an integer result code for historical reasons.
5938059590
*/
5938159591
SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
59382
- assert( cursorHoldsMutex(pCur) );
59592
+ assert( cursorOwnsBtShared(pCur) );
5938359593
assert( pCur->eState==CURSOR_VALID );
5938459594
assert( pCur->iPage>=0 );
5938559595
assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
5938659596
assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
5938759597
getCellInfo(pCur);
@@ -59757,11 +59967,11 @@
5975759967
if ( pCur->eState==CURSOR_INVALID ){
5975859968
return SQLITE_ABORT;
5975959969
}
5976059970
#endif
5976159971
59762
- assert( cursorHoldsMutex(pCur) );
59972
+ assert( cursorOwnsBtShared(pCur) );
5976359973
rc = restoreCursorPosition(pCur);
5976459974
if( rc==SQLITE_OK ){
5976559975
assert( pCur->eState==CURSOR_VALID );
5976659976
assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
5976759977
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
@@ -59795,11 +60005,11 @@
5979560005
){
5979660006
u32 amt;
5979760007
assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
5979860008
assert( pCur->eState==CURSOR_VALID );
5979960009
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
59800
- assert( cursorHoldsMutex(pCur) );
60010
+ assert( cursorOwnsBtShared(pCur) );
5980160011
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
5980260012
assert( pCur->info.nSize>0 );
5980360013
assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
5980460014
assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
5980560015
amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload);
@@ -59841,11 +60051,11 @@
5984160051
** vice-versa).
5984260052
*/
5984360053
static int moveToChild(BtCursor *pCur, u32 newPgno){
5984460054
BtShared *pBt = pCur->pBt;
5984560055
59846
- assert( cursorHoldsMutex(pCur) );
60056
+ assert( cursorOwnsBtShared(pCur) );
5984760057
assert( pCur->eState==CURSOR_VALID );
5984860058
assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
5984960059
assert( pCur->iPage>=0 );
5985060060
if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
5985160061
return SQLITE_CORRUPT_BKPT;
@@ -59887,11 +60097,11 @@
5988760097
** to the page we are coming from. If we are coming from the
5988860098
** right-most child page then pCur->idx is set to one more than
5988960099
** the largest cell index.
5989060100
*/
5989160101
static void moveToParent(BtCursor *pCur){
59892
- assert( cursorHoldsMutex(pCur) );
60102
+ assert( cursorOwnsBtShared(pCur) );
5989360103
assert( pCur->eState==CURSOR_VALID );
5989460104
assert( pCur->iPage>0 );
5989560105
assert( pCur->apPage[pCur->iPage] );
5989660106
assertParentIndex(
5989760107
pCur->apPage[pCur->iPage-1],
@@ -59927,11 +60137,11 @@
5992760137
*/
5992860138
static int moveToRoot(BtCursor *pCur){
5992960139
MemPage *pRoot;
5993060140
int rc = SQLITE_OK;
5993160141
59932
- assert( cursorHoldsMutex(pCur) );
60142
+ assert( cursorOwnsBtShared(pCur) );
5993360143
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
5993460144
assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
5993560145
assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
5993660146
if( pCur->eState>=CURSOR_REQUIRESEEK ){
5993760147
if( pCur->eState==CURSOR_FAULT ){
@@ -60006,11 +60216,11 @@
6000660216
static int moveToLeftmost(BtCursor *pCur){
6000760217
Pgno pgno;
6000860218
int rc = SQLITE_OK;
6000960219
MemPage *pPage;
6001060220
60011
- assert( cursorHoldsMutex(pCur) );
60221
+ assert( cursorOwnsBtShared(pCur) );
6001260222
assert( pCur->eState==CURSOR_VALID );
6001360223
while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
6001460224
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
6001560225
pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
6001660226
rc = moveToChild(pCur, pgno);
@@ -60031,11 +60241,11 @@
6003160241
static int moveToRightmost(BtCursor *pCur){
6003260242
Pgno pgno;
6003360243
int rc = SQLITE_OK;
6003460244
MemPage *pPage = 0;
6003560245
60036
- assert( cursorHoldsMutex(pCur) );
60246
+ assert( cursorOwnsBtShared(pCur) );
6003760247
assert( pCur->eState==CURSOR_VALID );
6003860248
while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
6003960249
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
6004060250
pCur->aiIdx[pCur->iPage] = pPage->nCell;
6004160251
rc = moveToChild(pCur, pgno);
@@ -60052,11 +60262,11 @@
6005260262
** or set *pRes to 1 if the table is empty.
6005360263
*/
6005460264
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
6005560265
int rc;
6005660266
60057
- assert( cursorHoldsMutex(pCur) );
60267
+ assert( cursorOwnsBtShared(pCur) );
6005860268
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
6005960269
rc = moveToRoot(pCur);
6006060270
if( rc==SQLITE_OK ){
6006160271
if( pCur->eState==CURSOR_INVALID ){
6006260272
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
@@ -60075,11 +60285,11 @@
6007560285
** or set *pRes to 1 if the table is empty.
6007660286
*/
6007760287
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
6007860288
int rc;
6007960289
60080
- assert( cursorHoldsMutex(pCur) );
60290
+ assert( cursorOwnsBtShared(pCur) );
6008160291
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
6008260292
6008360293
/* If the cursor already points to the last entry, this is a no-op. */
6008460294
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
6008560295
#ifdef SQLITE_DEBUG
@@ -60153,11 +60363,11 @@
6015360363
int *pRes /* Write search results here */
6015460364
){
6015560365
int rc;
6015660366
RecordCompare xRecordCompare;
6015760367
60158
- assert( cursorHoldsMutex(pCur) );
60368
+ assert( cursorOwnsBtShared(pCur) );
6015960369
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
6016060370
assert( pRes );
6016160371
assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
6016260372
6016360373
/* If the cursor is already positioned at the point we are trying
@@ -60401,11 +60611,11 @@
6040160611
static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
6040260612
int rc;
6040360613
int idx;
6040460614
MemPage *pPage;
6040560615
60406
- assert( cursorHoldsMutex(pCur) );
60616
+ assert( cursorOwnsBtShared(pCur) );
6040760617
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
6040860618
assert( *pRes==0 );
6040960619
if( pCur->eState!=CURSOR_VALID ){
6041060620
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
6041160621
rc = restoreCursorPosition(pCur);
@@ -60465,11 +60675,11 @@
6046560675
return moveToLeftmost(pCur);
6046660676
}
6046760677
}
6046860678
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
6046960679
MemPage *pPage;
60470
- assert( cursorHoldsMutex(pCur) );
60680
+ assert( cursorOwnsBtShared(pCur) );
6047160681
assert( pRes!=0 );
6047260682
assert( *pRes==0 || *pRes==1 );
6047360683
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
6047460684
pCur->info.nSize = 0;
6047560685
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
@@ -60510,11 +60720,11 @@
6051060720
*/
6051160721
static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
6051260722
int rc;
6051360723
MemPage *pPage;
6051460724
60515
- assert( cursorHoldsMutex(pCur) );
60725
+ assert( cursorOwnsBtShared(pCur) );
6051660726
assert( pRes!=0 );
6051760727
assert( *pRes==0 );
6051860728
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
6051960729
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
6052060730
assert( pCur->info.nSize==0 );
@@ -60566,11 +60776,11 @@
6056660776
}
6056760777
}
6056860778
return rc;
6056960779
}
6057060780
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
60571
- assert( cursorHoldsMutex(pCur) );
60781
+ assert( cursorOwnsBtShared(pCur) );
6057260782
assert( pRes!=0 );
6057360783
assert( *pRes==0 || *pRes==1 );
6057460784
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
6057560785
*pRes = 0;
6057660786
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
@@ -63046,11 +63256,11 @@
6304663256
if( pCur->eState==CURSOR_FAULT ){
6304763257
assert( pCur->skipNext!=SQLITE_OK );
6304863258
return pCur->skipNext;
6304963259
}
6305063260
63051
- assert( cursorHoldsMutex(pCur) );
63261
+ assert( cursorOwnsBtShared(pCur) );
6305263262
assert( (pCur->curFlags & BTCF_WriteFlag)!=0
6305363263
&& pBt->inTransaction==TRANS_WRITE
6305463264
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
6305563265
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
6305663266
@@ -63193,11 +63403,11 @@
6319363403
int iCellIdx; /* Index of cell to delete */
6319463404
int iCellDepth; /* Depth of node containing pCell */
6319563405
u16 szCell; /* Size of the cell being deleted */
6319663406
int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
6319763407
63198
- assert( cursorHoldsMutex(pCur) );
63408
+ assert( cursorOwnsBtShared(pCur) );
6319963409
assert( pBt->inTransaction==TRANS_WRITE );
6320063410
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
6320163411
assert( pCur->curFlags & BTCF_WriteFlag );
6320263412
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
6320363413
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
@@ -64655,11 +64865,11 @@
6465564865
** parameters that attempt to write past the end of the existing data,
6465664866
** no modifications are made and SQLITE_CORRUPT is returned.
6465764867
*/
6465864868
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
6465964869
int rc;
64660
- assert( cursorHoldsMutex(pCsr) );
64870
+ assert( cursorOwnsBtShared(pCsr) );
6466164871
assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
6466264872
assert( pCsr->curFlags & BTCF_Incrblob );
6466364873
6466464874
rc = restoreCursorPosition(pCsr);
6466564875
if( rc!=SQLITE_OK ){
@@ -64762,10 +64972,19 @@
6476264972
6476364973
/*
6476464974
** Return the size of the header added to each page by this module.
6476564975
*/
6476664976
SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
64977
+
64978
+#if !defined(SQLITE_OMIT_SHARED_CACHE)
64979
+/*
64980
+** Return true if the Btree passed as the only argument is sharable.
64981
+*/
64982
+SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){
64983
+ return p->sharable;
64984
+}
64985
+#endif
6476764986
6476864987
/************** End of btree.c ***********************************************/
6476964988
/************** Begin file backup.c ******************************************/
6477064989
/*
6477164990
** 2009 January 28
@@ -67593,12 +67812,11 @@
6759367812
** The zWhere string must have been obtained from sqlite3_malloc().
6759467813
** This routine will take ownership of the allocated memory.
6759567814
*/
6759667815
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
6759767816
int j;
67598
- int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
67599
- sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
67817
+ sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
6760067818
for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
6760167819
}
6760267820
6760367821
/*
6760467822
** Add an opcode that includes the p4 value as an integer.
@@ -68093,11 +68311,11 @@
6809368311
*/
6809468312
static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
6809568313
if( aOp ){
6809668314
Op *pOp;
6809768315
for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
68098
- freeP4(db, pOp->p4type, pOp->p4.p);
68316
+ if( pOp->p4type ) freeP4(db, pOp->p4type, pOp->p4.p);
6809968317
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
6810068318
sqlite3DbFree(db, pOp->zComment);
6810168319
#endif
6810268320
}
6810368321
}
@@ -68155,65 +68373,60 @@
6815568373
** to a string or structure that is guaranteed to exist for the lifetime of
6815668374
** the Vdbe. In these cases we can just copy the pointer.
6815768375
**
6815868376
** If addr<0 then change P4 on the most recently inserted instruction.
6815968377
*/
68378
+static void SQLITE_NOINLINE vdbeChangeP4Full(
68379
+ Vdbe *p,
68380
+ Op *pOp,
68381
+ const char *zP4,
68382
+ int n
68383
+){
68384
+ if( pOp->p4type ){
68385
+ freeP4(p->db, pOp->p4type, pOp->p4.p);
68386
+ pOp->p4type = 0;
68387
+ pOp->p4.p = 0;
68388
+ }
68389
+ if( n<0 ){
68390
+ sqlite3VdbeChangeP4(p, (int)(pOp - p->aOp), zP4, n);
68391
+ }else{
68392
+ if( n==0 ) n = sqlite3Strlen30(zP4);
68393
+ pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
68394
+ pOp->p4type = P4_DYNAMIC;
68395
+ }
68396
+}
6816068397
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
6816168398
Op *pOp;
6816268399
sqlite3 *db;
6816368400
assert( p!=0 );
6816468401
db = p->db;
6816568402
assert( p->magic==VDBE_MAGIC_INIT );
68166
- if( p->aOp==0 || db->mallocFailed ){
68167
- if( n!=P4_VTAB ){
68168
- freeP4(db, n, (void*)*(char**)&zP4);
68169
- }
68403
+ assert( p->aOp!=0 || db->mallocFailed );
68404
+ if( db->mallocFailed ){
68405
+ if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
6817068406
return;
6817168407
}
6817268408
assert( p->nOp>0 );
6817368409
assert( addr<p->nOp );
6817468410
if( addr<0 ){
6817568411
addr = p->nOp - 1;
6817668412
}
6817768413
pOp = &p->aOp[addr];
68178
- assert( pOp->p4type==P4_NOTUSED
68179
- || pOp->p4type==P4_INT32
68180
- || pOp->p4type==P4_KEYINFO );
68181
- freeP4(db, pOp->p4type, pOp->p4.p);
68182
- pOp->p4.p = 0;
68414
+ if( n>=0 || pOp->p4type ){
68415
+ vdbeChangeP4Full(p, pOp, zP4, n);
68416
+ return;
68417
+ }
6818368418
if( n==P4_INT32 ){
6818468419
/* Note: this cast is safe, because the origin data point was an int
6818568420
** that was cast to a (const char *). */
6818668421
pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
6818768422
pOp->p4type = P4_INT32;
68188
- }else if( zP4==0 ){
68189
- pOp->p4.p = 0;
68190
- pOp->p4type = P4_NOTUSED;
68191
- }else if( n==P4_KEYINFO ){
68192
- pOp->p4.p = (void*)zP4;
68193
- pOp->p4type = P4_KEYINFO;
68194
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
68195
- }else if( n==P4_EXPR ){
68196
- /* Responsibility for deleting the Expr tree is handed over to the
68197
- ** VDBE by this operation. The caller should have already invoked
68198
- ** sqlite3ExprDup() or whatever other routine is needed to make a
68199
- ** private copy of the tree. */
68200
- pOp->p4.pExpr = (Expr*)zP4;
68201
- pOp->p4type = P4_EXPR;
68202
-#endif
68203
- }else if( n==P4_VTAB ){
68204
- pOp->p4.p = (void*)zP4;
68205
- pOp->p4type = P4_VTAB;
68206
- sqlite3VtabLock((VTable *)zP4);
68207
- assert( ((VTable *)zP4)->db==p->db );
68208
- }else if( n<0 ){
68423
+ }else if( zP4!=0 ){
68424
+ assert( n<0 );
6820968425
pOp->p4.p = (void*)zP4;
6821068426
pOp->p4type = (signed char)n;
68211
- }else{
68212
- if( n==0 ) n = sqlite3Strlen30(zP4);
68213
- pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
68214
- pOp->p4type = P4_DYNAMIC;
68427
+ if( n==P4_VTAB ) sqlite3VtabLock((VTable*)zP4);
6821568428
}
6821668429
}
6821768430
6821868431
/*
6821968432
** Set the P4 on the most recently added opcode to the KeyInfo for the
@@ -68605,11 +68818,11 @@
6860568818
if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
6860668819
DbMaskSet(p->lockMask, i);
6860768820
}
6860868821
}
6860968822
68610
-#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
68823
+#if !defined(SQLITE_OMIT_SHARED_CACHE)
6861168824
/*
6861268825
** If SQLite is compiled to support shared-cache mode and to be threadsafe,
6861368826
** this routine obtains the mutex associated with each BtShared structure
6861468827
** that may be accessed by the VM passed as an argument. In doing so it also
6861568828
** sets the BtShared.db member of each of the BtShared structures, ensuring
@@ -76059,11 +76272,10 @@
7605976272
const u8 *zEndHdr; /* Pointer to first byte after the header */
7606076273
u32 offset; /* Offset into the data */
7606176274
u64 offset64; /* 64-bit offset */
7606276275
u32 avail; /* Number of bytes of available data */
7606376276
u32 t; /* A type code from the record header */
76064
- u16 fx; /* pDest->flags value */
7606576277
Mem *pReg; /* PseudoTable input register */
7606676278
7606776279
p2 = pOp->p2;
7606876280
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
7606976281
pDest = &aMem[pOp->p3];
@@ -76237,14 +76449,35 @@
7623776449
assert( p2<pC->nHdrParsed );
7623876450
assert( rc==SQLITE_OK );
7623976451
assert( sqlite3VdbeCheckMemInvariants(pDest) );
7624076452
if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest);
7624176453
assert( t==pC->aType[p2] );
76454
+ pDest->enc = encoding;
7624276455
if( pC->szRow>=aOffset[p2+1] ){
7624376456
/* This is the common case where the desired content fits on the original
7624476457
** page - where the content is not on an overflow page */
76245
- sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], t, pDest);
76458
+ zData = pC->aRow + aOffset[p2];
76459
+ if( t<12 ){
76460
+ sqlite3VdbeSerialGet(zData, t, pDest);
76461
+ }else{
76462
+ /* If the column value is a string, we need a persistent value, not
76463
+ ** a MEM_Ephem value. This branch is a fast short-cut that is equivalent
76464
+ ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize().
76465
+ */
76466
+ static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
76467
+ pDest->n = len = (t-12)/2;
76468
+ if( pDest->szMalloc < len+2 ){
76469
+ pDest->flags = MEM_Null;
76470
+ if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
76471
+ }else{
76472
+ pDest->z = pDest->zMalloc;
76473
+ }
76474
+ memcpy(pDest->z, zData, len);
76475
+ pDest->z[len] = 0;
76476
+ pDest->z[len+1] = 0;
76477
+ pDest->flags = aFlag[t&1];
76478
+ }
7624676479
}else{
7624776480
/* This branch happens only when content is on overflow pages */
7624876481
if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
7624976482
&& ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
7625076483
|| (len = sqlite3VdbeSerialTypeLen(t))==0
@@ -76252,42 +76485,24 @@
7625276485
/* Content is irrelevant for
7625376486
** 1. the typeof() function,
7625476487
** 2. the length(X) function if X is a blob, and
7625576488
** 3. if the content length is zero.
7625676489
** So we might as well use bogus content rather than reading
76257
- ** content from disk. NULL will work for the value for strings
76258
- ** and blobs and whatever is in the payloadSize64 variable
76259
- ** will work for everything else. */
76260
- sqlite3VdbeSerialGet(t<=13 ? (u8*)&payloadSize64 : 0, t, pDest);
76490
+ ** content from disk. */
76491
+ static u8 aZero[8]; /* This is the bogus content */
76492
+ sqlite3VdbeSerialGet(aZero, t, pDest);
7626176493
}else{
7626276494
rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
7626376495
pDest);
76264
- if( rc!=SQLITE_OK ){
76265
- goto op_column_error;
76266
- }
76267
- sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
76268
- pDest->flags &= ~MEM_Ephem;
76269
- }
76270
- }
76271
- pDest->enc = encoding;
76272
-
76273
-op_column_out:
76274
- /* If the column value is an ephemeral string, go ahead and persist
76275
- ** that string in case the cursor moves before the column value is
76276
- ** used. The following code does the equivalent of Deephemeralize()
76277
- ** but does it faster. */
76278
- if( (pDest->flags & MEM_Ephem)!=0 && pDest->z ){
76279
- fx = pDest->flags & (MEM_Str|MEM_Blob);
76280
- assert( fx!=0 );
76281
- zData = (const u8*)pDest->z;
76282
- len = pDest->n;
76283
- if( sqlite3VdbeMemClearAndResize(pDest, len+2) ) goto no_mem;
76284
- memcpy(pDest->z, zData, len);
76285
- pDest->z[len] = 0;
76286
- pDest->z[len+1] = 0;
76287
- pDest->flags = fx|MEM_Term;
76288
- }
76496
+ if( rc==SQLITE_OK ){
76497
+ sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
76498
+ pDest->flags &= ~MEM_Ephem;
76499
+ }
76500
+ }
76501
+ }
76502
+
76503
+op_column_out:
7628976504
op_column_error:
7629076505
UPDATE_MAX_BLOBSIZE(pDest);
7629176506
REGISTER_TRACE(pOp->p3, pDest);
7629276507
break;
7629376508
}
@@ -81685,11 +81900,11 @@
8168581900
assert( pReadr->aBuffer==0 );
8168681901
assert( pReadr->aMap==0 );
8168781902
8168881903
rc = vdbePmaReaderSeek(pTask, pReadr, pFile, iStart);
8168981904
if( rc==SQLITE_OK ){
81690
- u64 nByte; /* Size of PMA in bytes */
81905
+ u64 nByte = 0; /* Size of PMA in bytes */
8169181906
rc = vdbePmaReadVarint(pReadr, &nByte);
8169281907
pReadr->iEof = pReadr->iReadOff + nByte;
8169381908
*pnByte += nByte;
8169481909
}
8169581910
@@ -84243,13 +84458,12 @@
8424384458
** return the top-level walk call.
8424484459
**
8424584460
** The return value from this routine is WRC_Abort to abandon the tree walk
8424684461
** and WRC_Continue to continue.
8424784462
*/
84248
-SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
84463
+static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
8424984464
int rc;
84250
- if( pExpr==0 ) return WRC_Continue;
8425184465
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
8425284466
testcase( ExprHasProperty(pExpr, EP_Reduced) );
8425384467
rc = pWalker->xExprCallback(pWalker, pExpr);
8425484468
if( rc==WRC_Continue
8425584469
&& !ExprHasProperty(pExpr,EP_TokenOnly) ){
@@ -84260,10 +84474,13 @@
8426084474
}else{
8426184475
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
8426284476
}
8426384477
}
8426484478
return rc & WRC_Abort;
84479
+}
84480
+SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
84481
+ return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue;
8426584482
}
8426684483
8426784484
/*
8426884485
** Call sqlite3WalkExpr() for every expression in list p or until
8426984486
** an abort request is seen.
@@ -86327,12 +86544,13 @@
8632786544
|| sqlite3GetInt32(pToken->z, &iValue)==0 ){
8632886545
nExtra = pToken->n+1;
8632986546
assert( iValue>=0 );
8633086547
}
8633186548
}
86332
- pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
86549
+ pNew = sqlite3DbMallocRaw(db, sizeof(Expr)+nExtra);
8633386550
if( pNew ){
86551
+ memset(pNew, 0, sizeof(Expr));
8633486552
pNew->op = (u8)op;
8633586553
pNew->iAgg = -1;
8633686554
if( pToken ){
8633786555
if( nExtra==0 ){
8633886556
pNew->flags |= EP_IntValue;
@@ -93723,19 +93941,10 @@
9372393941
** COMMIT
9372493942
** ROLLBACK
9372593943
*/
9372693944
/* #include "sqliteInt.h" */
9372793945
93728
-/*
93729
-** This routine is called when a new SQL statement is beginning to
93730
-** be parsed. Initialize the pParse structure as needed.
93731
-*/
93732
-SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){
93733
- pParse->explain = (u8)explainFlag;
93734
- pParse->nVar = 0;
93735
-}
93736
-
9373793946
#ifndef SQLITE_OMIT_SHARED_CACHE
9373893947
/*
9373993948
** The TableLock structure is only used by the sqlite3TableLock() and
9374093949
** codeTableLocks() functions.
9374193950
*/
@@ -100072,14 +100281,14 @@
100072100281
100073100282
/*
100074100283
** A structure defining how to do GLOB-style comparisons.
100075100284
*/
100076100285
struct compareInfo {
100077
- u8 matchAll;
100078
- u8 matchOne;
100079
- u8 matchSet;
100080
- u8 noCase;
100286
+ u8 matchAll; /* "*" or "%" */
100287
+ u8 matchOne; /* "?" or "_" */
100288
+ u8 matchSet; /* "[" or 0 */
100289
+ u8 noCase; /* true to ignore case differences */
100081100290
};
100082100291
100083100292
/*
100084100293
** For LIKE and GLOB matching on EBCDIC machines, assume that every
100085100294
** character is exactly one byte in size. Also, provde the Utf8Read()
@@ -100138,26 +100347,18 @@
100138100347
*/
100139100348
static int patternCompare(
100140100349
const u8 *zPattern, /* The glob pattern */
100141100350
const u8 *zString, /* The string to compare against the glob */
100142100351
const struct compareInfo *pInfo, /* Information about how to do the compare */
100143
- u32 esc /* The escape character */
100352
+ u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */
100144100353
){
100145100354
u32 c, c2; /* Next pattern and input string chars */
100146100355
u32 matchOne = pInfo->matchOne; /* "?" or "_" */
100147100356
u32 matchAll = pInfo->matchAll; /* "*" or "%" */
100148
- u32 matchOther; /* "[" or the escape character */
100149100357
u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
100150100358
const u8 *zEscaped = 0; /* One past the last escaped input char */
100151100359
100152
- /* The GLOB operator does not have an ESCAPE clause. And LIKE does not
100153
- ** have the matchSet operator. So we either have to look for one or
100154
- ** the other, never both. Hence the single variable matchOther is used
100155
- ** to store the one we have to look for.
100156
- */
100157
- matchOther = esc ? esc : pInfo->matchSet;
100158
-
100159100360
while( (c = Utf8Read(zPattern))!=0 ){
100160100361
if( c==matchAll ){ /* Match "*" */
100161100362
/* Skip over multiple "*" characters in the pattern. If there
100162100363
** are also "?" characters, skip those as well, but consume a
100163100364
** single character of the input string for each "?" skipped */
@@ -100167,19 +100368,19 @@
100167100368
}
100168100369
}
100169100370
if( c==0 ){
100170100371
return 1; /* "*" at the end of the pattern matches */
100171100372
}else if( c==matchOther ){
100172
- if( esc ){
100373
+ if( pInfo->matchSet==0 ){
100173100374
c = sqlite3Utf8Read(&zPattern);
100174100375
if( c==0 ) return 0;
100175100376
}else{
100176100377
/* "[...]" immediately follows the "*". We have to do a slow
100177100378
** recursive search in this case, but it is an unusual case. */
100178100379
assert( matchOther<0x80 ); /* '[' is a single-byte character */
100179100380
while( *zString
100180
- && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
100381
+ && patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){
100181100382
SQLITE_SKIP_UTF8(zString);
100182100383
}
100183100384
return *zString!=0;
100184100385
}
100185100386
}
@@ -100201,22 +100402,22 @@
100201100402
}else{
100202100403
cx = c;
100203100404
}
100204100405
while( (c2 = *(zString++))!=0 ){
100205100406
if( c2!=c && c2!=cx ) continue;
100206
- if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
100407
+ if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
100207100408
}
100208100409
}else{
100209100410
while( (c2 = Utf8Read(zString))!=0 ){
100210100411
if( c2!=c ) continue;
100211
- if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
100412
+ if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
100212100413
}
100213100414
}
100214100415
return 0;
100215100416
}
100216100417
if( c==matchOther ){
100217
- if( esc ){
100418
+ if( pInfo->matchSet==0 ){
100218100419
c = sqlite3Utf8Read(&zPattern);
100219100420
if( c==0 ) return 0;
100220100421
zEscaped = zPattern;
100221100422
}else{
100222100423
u32 prior_c = 0;
@@ -100265,11 +100466,11 @@
100265100466
100266100467
/*
100267100468
** The sqlite3_strglob() interface.
100268100469
*/
100269100470
SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlobPattern, const char *zString){
100270
- return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
100471
+ return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0;
100271100472
}
100272100473
100273100474
/*
100274100475
** The sqlite3_strlike() interface.
100275100476
*/
@@ -100303,13 +100504,14 @@
100303100504
sqlite3_context *context,
100304100505
int argc,
100305100506
sqlite3_value **argv
100306100507
){
100307100508
const unsigned char *zA, *zB;
100308
- u32 escape = 0;
100509
+ u32 escape;
100309100510
int nPat;
100310100511
sqlite3 *db = sqlite3_context_db_handle(context);
100512
+ struct compareInfo *pInfo = sqlite3_user_data(context);
100311100513
100312100514
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
100313100515
if( sqlite3_value_type(argv[0])==SQLITE_BLOB
100314100516
|| sqlite3_value_type(argv[1])==SQLITE_BLOB
100315100517
){
@@ -100345,17 +100547,17 @@
100345100547
sqlite3_result_error(context,
100346100548
"ESCAPE expression must be a single character", -1);
100347100549
return;
100348100550
}
100349100551
escape = sqlite3Utf8Read(&zEsc);
100552
+ }else{
100553
+ escape = pInfo->matchSet;
100350100554
}
100351100555
if( zA && zB ){
100352
- struct compareInfo *pInfo = sqlite3_user_data(context);
100353100556
#ifdef SQLITE_TEST
100354100557
sqlite3_like_count++;
100355100558
#endif
100356
-
100357100559
sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
100358100560
}
100359100561
}
100360100562
100361100563
/*
@@ -109688,10 +109890,11 @@
109688109890
int nOBSat; /* Number of ORDER BY terms satisfied by indices */
109689109891
int iECursor; /* Cursor number for the sorter */
109690109892
int regReturn; /* Register holding block-output return address */
109691109893
int labelBkOut; /* Start label for the block-output subroutine */
109692109894
int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */
109895
+ int labelDone; /* Jump here when done, ex: LIMIT reached */
109693109896
u8 sortFlags; /* Zero or more SORTFLAG_* bits */
109694109897
};
109695109898
#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
109696109899
109697109900
/*
@@ -109745,33 +109948,41 @@
109745109948
Expr *pOffset /* OFFSET value. NULL means no offset */
109746109949
){
109747109950
Select *pNew;
109748109951
Select standin;
109749109952
sqlite3 *db = pParse->db;
109750
- pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
109953
+ pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
109751109954
if( pNew==0 ){
109752109955
assert( db->mallocFailed );
109753109956
pNew = &standin;
109754
- memset(pNew, 0, sizeof(*pNew));
109755109957
}
109756109958
if( pEList==0 ){
109757109959
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
109758109960
}
109759109961
pNew->pEList = pEList;
109962
+ pNew->op = TK_SELECT;
109963
+ pNew->selFlags = selFlags;
109964
+ pNew->iLimit = 0;
109965
+ pNew->iOffset = 0;
109966
+#if SELECTTRACE_ENABLED
109967
+ pNew->zSelName[0] = 0;
109968
+#endif
109969
+ pNew->addrOpenEphm[0] = -1;
109970
+ pNew->addrOpenEphm[1] = -1;
109971
+ pNew->nSelectRow = 0;
109760109972
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
109761109973
pNew->pSrc = pSrc;
109762109974
pNew->pWhere = pWhere;
109763109975
pNew->pGroupBy = pGroupBy;
109764109976
pNew->pHaving = pHaving;
109765109977
pNew->pOrderBy = pOrderBy;
109766
- pNew->selFlags = selFlags;
109767
- pNew->op = TK_SELECT;
109978
+ pNew->pPrior = 0;
109979
+ pNew->pNext = 0;
109768109980
pNew->pLimit = pLimit;
109769109981
pNew->pOffset = pOffset;
109982
+ pNew->pWith = 0;
109770109983
assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
109771
- pNew->addrOpenEphm[0] = -1;
109772
- pNew->addrOpenEphm[1] = -1;
109773109984
if( db->mallocFailed ) {
109774109985
clearSelect(db, pNew, pNew!=&standin);
109775109986
pNew = 0;
109776109987
}else{
109777109988
assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -110142,10 +110353,11 @@
110142110353
int nBase = nExpr + bSeq + nData; /* Fields in sorter record */
110143110354
int regBase; /* Regs for sorter record */
110144110355
int regRecord = ++pParse->nMem; /* Assembled sorter record */
110145110356
int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */
110146110357
int op; /* Opcode to add sorter record to sorter */
110358
+ int iLimit; /* LIMIT counter */
110147110359
110148110360
assert( bSeq==0 || bSeq==1 );
110149110361
assert( nData==1 || regData==regOrigData );
110150110362
if( nPrefixReg ){
110151110363
assert( nPrefixReg==nExpr+bSeq );
@@ -110152,19 +110364,21 @@
110152110364
regBase = regData - nExpr - bSeq;
110153110365
}else{
110154110366
regBase = pParse->nMem + 1;
110155110367
pParse->nMem += nBase;
110156110368
}
110369
+ assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
110370
+ iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
110371
+ pSort->labelDone = sqlite3VdbeMakeLabel(v);
110157110372
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
110158110373
SQLITE_ECEL_DUP|SQLITE_ECEL_REF);
110159110374
if( bSeq ){
110160110375
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
110161110376
}
110162110377
if( nPrefixReg==0 ){
110163110378
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
110164110379
}
110165
-
110166110380
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
110167110381
if( nOBSat>0 ){
110168110382
int regPrevKey; /* The first nOBSat columns of the previous row */
110169110383
int addrFirst; /* Address of the OP_IfNot opcode */
110170110384
int addrJmp; /* Address of the OP_Jump opcode */
@@ -110195,10 +110409,14 @@
110195110409
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
110196110410
pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
110197110411
pSort->regReturn = ++pParse->nMem;
110198110412
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
110199110413
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
110414
+ if( iLimit ){
110415
+ sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone);
110416
+ VdbeCoverage(v);
110417
+ }
110200110418
sqlite3VdbeJumpHere(v, addrFirst);
110201110419
sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat);
110202110420
sqlite3VdbeJumpHere(v, addrJmp);
110203110421
}
110204110422
if( pSort->sortFlags & SORTFLAG_UseSorter ){
@@ -110205,18 +110423,12 @@
110205110423
op = OP_SorterInsert;
110206110424
}else{
110207110425
op = OP_IdxInsert;
110208110426
}
110209110427
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
110210
- if( pSelect->iLimit ){
110428
+ if( iLimit ){
110211110429
int addr;
110212
- int iLimit;
110213
- if( pSelect->iOffset ){
110214
- iLimit = pSelect->iOffset+1;
110215
- }else{
110216
- iLimit = pSelect->iLimit;
110217
- }
110218110430
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
110219110431
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
110220110432
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
110221110433
sqlite3VdbeJumpHere(v, addr);
110222110434
}
@@ -110816,11 +111028,11 @@
110816111028
SortCtx *pSort, /* Information on the ORDER BY clause */
110817111029
int nColumn, /* Number of columns of data */
110818111030
SelectDest *pDest /* Write the sorted results here */
110819111031
){
110820111032
Vdbe *v = pParse->pVdbe; /* The prepared statement */
110821
- int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */
111033
+ int addrBreak = pSort->labelDone; /* Jump here to exit loop */
110822111034
int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
110823111035
int addr;
110824111036
int addrOnce = 0;
110825111037
int iTab;
110826111038
ExprList *pOrderBy = pSort->pOrderBy;
@@ -110835,10 +111047,11 @@
110835111047
int bSeq; /* True if sorter record includes seq. no. */
110836111048
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
110837111049
struct ExprList_item *aOutEx = p->pEList->a;
110838111050
#endif
110839111051
111052
+ assert( addrBreak<0 );
110840111053
if( pSort->labelBkOut ){
110841111054
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
110842111055
sqlite3VdbeGoto(v, addrBreak);
110843111056
sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
110844111057
}
@@ -126875,12 +127088,11 @@
126875127088
testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS );
126876127089
if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){
126877127090
Bitmask b = pTabItem->colUsed;
126878127091
int n = 0;
126879127092
for(; b; b=b>>1, n++){}
126880
- sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
126881
- SQLITE_INT_TO_PTR(n), P4_INT32);
127093
+ sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32);
126882127094
assert( n<=pTab->nCol );
126883127095
}
126884127096
#ifdef SQLITE_ENABLE_CURSOR_HINTS
126885127097
if( pLoop->u.btree.pIndex!=0 ){
126886127098
sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete);
@@ -129343,18 +129555,15 @@
129343129555
** { ... } // User supplied code
129344129556
** #line <lineno> <thisfile>
129345129557
** break;
129346129558
*/
129347129559
/********** Begin reduce actions **********************************************/
129348
- case 5: /* explain ::= */
129349
-{ sqlite3BeginParse(pParse, 0); }
129350
- break;
129351129560
case 6: /* explain ::= EXPLAIN */
129352
-{ sqlite3BeginParse(pParse, 1); }
129561
+{ pParse->explain = 1; }
129353129562
break;
129354129563
case 7: /* explain ::= EXPLAIN QUERY PLAN */
129355
-{ sqlite3BeginParse(pParse, 2); }
129564
+{ pParse->explain = 2; }
129356129565
break;
129357129566
case 8: /* cmdx ::= cmd */
129358129567
{ sqlite3FinishCoding(pParse); }
129359129568
break;
129360129569
case 9: /* cmd ::= BEGIN transtype trans_opt */
@@ -130525,10 +130734,11 @@
130525130734
/* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
130526130735
/* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
130527130736
/* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
130528130737
/* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);
130529130738
/* (4) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==4);
130739
+ /* (5) explain ::= */ yytestcase(yyruleno==5);
130530130740
/* (10) trans_opt ::= */ yytestcase(yyruleno==10);
130531130741
/* (11) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==11);
130532130742
/* (12) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==12);
130533130743
/* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20);
130534130744
/* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
@@ -135450,10 +135660,13 @@
135450135660
*(sqlite3_file**)pArg = fd;
135451135661
rc = SQLITE_OK;
135452135662
}else if( op==SQLITE_FCNTL_VFS_POINTER ){
135453135663
*(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager);
135454135664
rc = SQLITE_OK;
135665
+ }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){
135666
+ *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
135667
+ rc = SQLITE_OK;
135455135668
}else if( fd->pMethods ){
135456135669
rc = sqlite3OsFileControl(fd, op, pArg);
135457135670
}else{
135458135671
rc = SQLITE_NOTFOUND;
135459135672
}
@@ -161083,11 +161296,11 @@
161083161296
*/
161084161297
static void *rbuMalloc(sqlite3rbu *p, int nByte){
161085161298
void *pRet = 0;
161086161299
if( p->rc==SQLITE_OK ){
161087161300
assert( nByte>0 );
161088
- pRet = sqlite3_malloc(nByte);
161301
+ pRet = sqlite3_malloc64(nByte);
161089161302
if( pRet==0 ){
161090161303
p->rc = SQLITE_NOMEM;
161091161304
}else{
161092161305
memset(pRet, 0, nByte);
161093161306
}
@@ -161129,12 +161342,12 @@
161129161342
static char *rbuStrndup(const char *zStr, int *pRc){
161130161343
char *zRet = 0;
161131161344
161132161345
assert( *pRc==SQLITE_OK );
161133161346
if( zStr ){
161134
- int nCopy = strlen(zStr) + 1;
161135
- zRet = (char*)sqlite3_malloc(nCopy);
161347
+ size_t nCopy = strlen(zStr) + 1;
161348
+ zRet = (char*)sqlite3_malloc64(nCopy);
161136161349
if( zRet ){
161137161350
memcpy(zRet, zStr, nCopy);
161138161351
}else{
161139161352
*pRc = SQLITE_NOMEM;
161140161353
}
@@ -162478,11 +162691,11 @@
162478162691
162479162692
pRbu->pgsz = iAmt;
162480162693
if( pRbu->nFrame==pRbu->nFrameAlloc ){
162481162694
int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2;
162482162695
RbuFrame *aNew;
162483
- aNew = (RbuFrame*)sqlite3_realloc(pRbu->aFrame, nNew * sizeof(RbuFrame));
162696
+ aNew = (RbuFrame*)sqlite3_realloc64(pRbu->aFrame, nNew * sizeof(RbuFrame));
162484162697
if( aNew==0 ) return SQLITE_NOMEM;
162485162698
pRbu->aFrame = aNew;
162486162699
pRbu->nFrameAlloc = nNew;
162487162700
}
162488162701
@@ -162543,11 +162756,11 @@
162543162756
162544162757
nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
162545162758
if( nChar==0 ){
162546162759
return 0;
162547162760
}
162548
- zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) );
162761
+ zWideFilename = sqlite3_malloc64( nChar*sizeof(zWideFilename[0]) );
162549162762
if( zWideFilename==0 ){
162550162763
return 0;
162551162764
}
162552162765
memset(zWideFilename, 0, nChar*sizeof(zWideFilename[0]));
162553162766
nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
@@ -163177,15 +163390,16 @@
163177163390
const char *zTarget,
163178163391
const char *zRbu,
163179163392
const char *zState
163180163393
){
163181163394
sqlite3rbu *p;
163182
- int nTarget = strlen(zTarget);
163183
- int nRbu = strlen(zRbu);
163184
- int nState = zState ? strlen(zState) : 0;
163395
+ size_t nTarget = strlen(zTarget);
163396
+ size_t nRbu = strlen(zRbu);
163397
+ size_t nState = zState ? strlen(zState) : 0;
163398
+ size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1+ nState+1;
163185163399
163186
- p = (sqlite3rbu*)sqlite3_malloc(sizeof(sqlite3rbu)+nTarget+1+nRbu+1+nState+1);
163400
+ p = (sqlite3rbu*)sqlite3_malloc64(nByte);
163187163401
if( p ){
163188163402
RbuState *pState = 0;
163189163403
163190163404
/* Create the custom VFS. */
163191163405
memset(p, 0, sizeof(sqlite3rbu));
@@ -163318,11 +163532,11 @@
163318163532
** the pattern "rbu_imp_[0-9]*".
163319163533
*/
163320163534
static void rbuEditErrmsg(sqlite3rbu *p){
163321163535
if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){
163322163536
int i;
163323
- int nErrmsg = strlen(p->zErrmsg);
163537
+ size_t nErrmsg = strlen(p->zErrmsg);
163324163538
for(i=0; i<(nErrmsg-8); i++){
163325163539
if( memcmp(&p->zErrmsg[i], "rbu_imp_", 8)==0 ){
163326163540
int nDel = 8;
163327163541
while( p->zErrmsg[i+nDel]>='0' && p->zErrmsg[i+nDel]<='9' ) nDel++;
163328163542
memmove(&p->zErrmsg[i], &p->zErrmsg[i+nDel], nErrmsg + 1 - i - nDel);
@@ -163782,11 +163996,11 @@
163782163996
** instead of a file on disk. */
163783163997
assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
163784163998
if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){
163785163999
if( iRegion<=p->nShm ){
163786164000
int nByte = (iRegion+1) * sizeof(char*);
163787
- char **apNew = (char**)sqlite3_realloc(p->apShm, nByte);
164001
+ char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte);
163788164002
if( apNew==0 ){
163789164003
rc = SQLITE_NOMEM;
163790164004
}else{
163791164005
memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm));
163792164006
p->apShm = apNew;
@@ -163793,11 +164007,11 @@
163793164007
p->nShm = iRegion+1;
163794164008
}
163795164009
}
163796164010
163797164011
if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){
163798
- char *pNew = (char*)sqlite3_malloc(szRegion);
164012
+ char *pNew = (char*)sqlite3_malloc64(szRegion);
163799164013
if( pNew==0 ){
163800164014
rc = SQLITE_NOMEM;
163801164015
}else{
163802164016
memset(pNew, 0, szRegion);
163803164017
p->apShm[iRegion] = pNew;
@@ -163903,11 +164117,11 @@
163903164117
/* A main database has just been opened. The following block sets
163904164118
** (pFd->zWal) to point to a buffer owned by SQLite that contains
163905164119
** the name of the *-wal file this db connection will use. SQLite
163906164120
** happens to pass a pointer to this buffer when using xAccess()
163907164121
** or xOpen() to operate on the *-wal file. */
163908
- int n = strlen(zName);
164122
+ int n = (int)strlen(zName);
163909164123
const char *z = &zName[n];
163910164124
if( flags & SQLITE_OPEN_URI ){
163911164125
int odd = 0;
163912164126
while( 1 ){
163913164127
if( z[0]==0 ){
@@ -163929,12 +164143,12 @@
163929164143
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
163930164144
/* This call is to open a *-wal file. Intead, open the *-oal. This
163931164145
** code ensures that the string passed to xOpen() is terminated by a
163932164146
** pair of '\0' bytes in case the VFS attempts to extract a URI
163933164147
** parameter from it. */
163934
- int nCopy = strlen(zName);
163935
- char *zCopy = sqlite3_malloc(nCopy+2);
164148
+ size_t nCopy = strlen(zName);
164149
+ char *zCopy = sqlite3_malloc64(nCopy+2);
163936164150
if( zCopy ){
163937164151
memcpy(zCopy, zName, nCopy);
163938164152
zCopy[nCopy-3] = 'o';
163939164153
zCopy[nCopy] = '\0';
163940164154
zCopy[nCopy+1] = '\0';
@@ -164159,17 +164373,17 @@
164159164373
0, /* xCurrentTimeInt64 (version 2) */
164160164374
0, 0, 0 /* Unimplemented version 3 methods */
164161164375
};
164162164376
164163164377
rbu_vfs *pNew = 0; /* Newly allocated VFS */
164164
- int nName;
164165164378
int rc = SQLITE_OK;
164379
+ size_t nName;
164380
+ size_t nByte;
164166164381
164167
- int nByte;
164168164382
nName = strlen(zName);
164169164383
nByte = sizeof(rbu_vfs) + nName + 1;
164170
- pNew = (rbu_vfs*)sqlite3_malloc(nByte);
164384
+ pNew = (rbu_vfs*)sqlite3_malloc64(nByte);
164171164385
if( pNew==0 ){
164172164386
rc = SQLITE_NOMEM;
164173164387
}else{
164174164388
sqlite3_vfs *pParent; /* Parent VFS */
164175164389
memset(pNew, 0, nByte);
@@ -167174,10 +167388,13 @@
167174167388
** If parameter iCol is greater than or equal to the number of columns
167175167389
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
167176167390
** an OOM condition or IO error), an appropriate SQLite error code is
167177167391
** returned.
167178167392
**
167393
+** This function may be quite inefficient if used with an FTS5 table
167394
+** created with the "columnsize=0" option.
167395
+**
167179167396
** xColumnText:
167180167397
** This function attempts to retrieve the text of column iCol of the
167181167398
** current document. If successful, (*pz) is set to point to a buffer
167182167399
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
167183167400
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -167194,18 +167411,32 @@
167194167411
** xInstCount:
167195167412
** Set *pnInst to the total number of occurrences of all phrases within
167196167413
** the query within the current row. Return SQLITE_OK if successful, or
167197167414
** an error code (i.e. SQLITE_NOMEM) if an error occurs.
167198167415
**
167416
+** This API can be quite slow if used with an FTS5 table created with the
167417
+** "detail=none" or "detail=column" option. If the FTS5 table is created
167418
+** with either "detail=none" or "detail=column" and "content=" option
167419
+** (i.e. if it is a contentless table), then this API always returns 0.
167420
+**
167199167421
** xInst:
167200167422
** Query for the details of phrase match iIdx within the current row.
167201167423
** Phrase matches are numbered starting from zero, so the iIdx argument
167202167424
** should be greater than or equal to zero and smaller than the value
167203167425
** output by xInstCount().
167426
+**
167427
+** Usually, output parameter *piPhrase is set to the phrase number, *piCol
167428
+** to the column in which it occurs and *piOff the token offset of the
167429
+** first token of the phrase. The exception is if the table was created
167430
+** with the offsets=0 option specified. In this case *piOff is always
167431
+** set to -1.
167204167432
**
167205167433
** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
167206167434
** if an error occurs.
167435
+**
167436
+** This API can be quite slow if used with an FTS5 table created with the
167437
+** "detail=none" or "detail=column" option.
167207167438
**
167208167439
** xRowid:
167209167440
** Returns the rowid of the current row.
167210167441
**
167211167442
** xTokenize:
@@ -167286,25 +167517,63 @@
167286167517
** through instances of phrase iPhrase, use the following code:
167287167518
**
167288167519
** Fts5PhraseIter iter;
167289167520
** int iCol, iOff;
167290167521
** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
167291
-** iOff>=0;
167522
+** iCol>=0;
167292167523
** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
167293167524
** ){
167294167525
** // An instance of phrase iPhrase at offset iOff of column iCol
167295167526
** }
167296167527
**
167297167528
** The Fts5PhraseIter structure is defined above. Applications should not
167298167529
** modify this structure directly - it should only be used as shown above
167299
-** with the xPhraseFirst() and xPhraseNext() API methods.
167530
+** with the xPhraseFirst() and xPhraseNext() API methods (and by
167531
+** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
167532
+**
167533
+** This API can be quite slow if used with an FTS5 table created with the
167534
+** "detail=none" or "detail=column" option. If the FTS5 table is created
167535
+** with either "detail=none" or "detail=column" and "content=" option
167536
+** (i.e. if it is a contentless table), then this API always iterates
167537
+** through an empty set (all calls to xPhraseFirst() set iCol to -1).
167300167538
**
167301167539
** xPhraseNext()
167302167540
** See xPhraseFirst above.
167541
+**
167542
+** xPhraseFirstColumn()
167543
+** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
167544
+** and xPhraseNext() APIs described above. The difference is that instead
167545
+** of iterating through all instances of a phrase in the current row, these
167546
+** APIs are used to iterate through the set of columns in the current row
167547
+** that contain one or more instances of a specified phrase. For example:
167548
+**
167549
+** Fts5PhraseIter iter;
167550
+** int iCol;
167551
+** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
167552
+** iCol>=0;
167553
+** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
167554
+** ){
167555
+** // Column iCol contains at least one instance of phrase iPhrase
167556
+** }
167557
+**
167558
+** This API can be quite slow if used with an FTS5 table created with the
167559
+** "detail=none" option. If the FTS5 table is created with either
167560
+** "detail=none" "content=" option (i.e. if it is a contentless table),
167561
+** then this API always iterates through an empty set (all calls to
167562
+** xPhraseFirstColumn() set iCol to -1).
167563
+**
167564
+** The information accessed using this API and its companion
167565
+** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
167566
+** (or xInst/xInstCount). The chief advantage of this API is that it is
167567
+** significantly more efficient than those alternatives when used with
167568
+** "detail=column" tables.
167569
+**
167570
+** xPhraseNextColumn()
167571
+** See xPhraseFirstColumn above.
167303167572
*/
167304167573
struct Fts5ExtensionApi {
167305
- int iVersion; /* Currently always set to 1 */
167574
+ int iVersion; /* Currently always set to 3 */
167306167575
167307167576
void *(*xUserData)(Fts5Context*);
167308167577
167309167578
int (*xColumnCount)(Fts5Context*);
167310167579
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -167330,12 +167599,15 @@
167330167599
int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
167331167600
);
167332167601
int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
167333167602
void *(*xGetAuxdata)(Fts5Context*, int bClear);
167334167603
167335
- void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
167604
+ int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
167336167605
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
167606
+
167607
+ int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
167608
+ void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
167337167609
};
167338167610
167339167611
/*
167340167612
** CUSTOM AUXILIARY FUNCTIONS
167341167613
*************************************************************************/
@@ -167762,10 +168034,11 @@
167762168034
int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */
167763168035
int eContent; /* An FTS5_CONTENT value */
167764168036
char *zContent; /* content table */
167765168037
char *zContentRowid; /* "content_rowid=" option value */
167766168038
int bColumnsize; /* "columnsize=" option value (dflt==1) */
168039
+ int eDetail; /* FTS5_DETAIL_XXX value */
167767168040
char *zContentExprlist;
167768168041
Fts5Tokenizer *pTok;
167769168042
fts5_tokenizer *pTokApi;
167770168043
167771168044
/* Values loaded from the %_config table */
@@ -167790,10 +168063,13 @@
167790168063
167791168064
#define FTS5_CONTENT_NORMAL 0
167792168065
#define FTS5_CONTENT_NONE 1
167793168066
#define FTS5_CONTENT_EXTERNAL 2
167794168067
168068
+#define FTS5_DETAIL_FULL 0
168069
+#define FTS5_DETAIL_NONE 1
168070
+#define FTS5_DETAIL_COLUMNS 2
167795168071
167796168072
167797168073
167798168074
static int sqlite3Fts5ConfigParse(
167799168075
Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
@@ -167903,10 +168179,17 @@
167903168179
static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
167904168180
167905168181
/* Character set tests (like isspace(), isalpha() etc.) */
167906168182
static int sqlite3Fts5IsBareword(char t);
167907168183
168184
+
168185
+/* Bucket of terms object used by the integrity-check in offsets=0 mode. */
168186
+typedef struct Fts5Termset Fts5Termset;
168187
+static int sqlite3Fts5TermsetNew(Fts5Termset**);
168188
+static int sqlite3Fts5TermsetAdd(Fts5Termset*, int, const char*, int, int *pbPresent);
168189
+static void sqlite3Fts5TermsetFree(Fts5Termset*);
168190
+
167908168191
/*
167909168192
** End of interface to code in fts5_buffer.c.
167910168193
**************************************************************************/
167911168194
167912168195
/**************************************************************************
@@ -168024,11 +168307,10 @@
168024168307
static int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);
168025168308
168026168309
/*
168027168310
** Functions called by the storage module as part of integrity-check.
168028168311
*/
168029
-static u64 sqlite3Fts5IndexCksum(Fts5Config*,i64,int,int,const char*,int);
168030168312
static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
168031168313
168032168314
/*
168033168315
** Called during virtual module initialization to register UDF
168034168316
** fts5_decode() with SQLite
@@ -168046,10 +168328,12 @@
168046168328
static int sqlite3Fts5IndexReinit(Fts5Index *p);
168047168329
static int sqlite3Fts5IndexOptimize(Fts5Index *p);
168048168330
static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge);
168049168331
168050168332
static int sqlite3Fts5IndexLoadConfig(Fts5Index *p);
168333
+
168334
+static int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*);
168051168335
168052168336
/*
168053168337
** End of interface to code in fts5_index.c.
168054168338
**************************************************************************/
168055168339
@@ -168103,11 +168387,11 @@
168103168387
typedef struct Fts5Hash Fts5Hash;
168104168388
168105168389
/*
168106168390
** Create a hash table, free a hash table.
168107168391
*/
168108
-static int sqlite3Fts5HashNew(Fts5Hash**, int *pnSize);
168392
+static int sqlite3Fts5HashNew(Fts5Config*, Fts5Hash**, int *pnSize);
168109168393
static void sqlite3Fts5HashFree(Fts5Hash*);
168110168394
168111168395
static int sqlite3Fts5HashWrite(
168112168396
Fts5Hash*,
168113168397
i64 iRowid, /* Rowid for this entry */
@@ -168239,12 +168523,22 @@
168239168523
static int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);
168240168524
168241168525
static int sqlite3Fts5ExprPhraseCount(Fts5Expr*);
168242168526
static int sqlite3Fts5ExprPhraseSize(Fts5Expr*, int iPhrase);
168243168527
static int sqlite3Fts5ExprPoslist(Fts5Expr*, int, const u8 **);
168528
+
168529
+typedef struct Fts5PoslistPopulator Fts5PoslistPopulator;
168530
+static Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr*, int);
168531
+static int sqlite3Fts5ExprPopulatePoslists(
168532
+ Fts5Config*, Fts5Expr*, Fts5PoslistPopulator*, int, const char*, int
168533
+);
168534
+static void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64);
168535
+static void sqlite3Fts5ExprClearEof(Fts5Expr*);
168244168536
168245168537
static int sqlite3Fts5ExprClonePhrase(Fts5Config*, Fts5Expr*, int, Fts5Expr**);
168538
+
168539
+static int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *);
168246168540
168247168541
/*******************************************
168248168542
** The fts5_expr.c API above this point is used by the other hand-written
168249168543
** C code in this module. The interfaces below this point are called by
168250168544
** the parser code in fts5parse.y. */
@@ -170397,10 +170691,93 @@
170397170691
170398170692
return (t & 0x80) || aBareword[(int)t];
170399170693
}
170400170694
170401170695
170696
+/*************************************************************************
170697
+*/
170698
+typedef struct Fts5TermsetEntry Fts5TermsetEntry;
170699
+struct Fts5TermsetEntry {
170700
+ char *pTerm;
170701
+ int nTerm;
170702
+ int iIdx; /* Index (main or aPrefix[] entry) */
170703
+ Fts5TermsetEntry *pNext;
170704
+};
170705
+
170706
+struct Fts5Termset {
170707
+ Fts5TermsetEntry *apHash[512];
170708
+};
170709
+
170710
+static int sqlite3Fts5TermsetNew(Fts5Termset **pp){
170711
+ int rc = SQLITE_OK;
170712
+ *pp = sqlite3Fts5MallocZero(&rc, sizeof(Fts5Termset));
170713
+ return rc;
170714
+}
170715
+
170716
+static int sqlite3Fts5TermsetAdd(
170717
+ Fts5Termset *p,
170718
+ int iIdx,
170719
+ const char *pTerm, int nTerm,
170720
+ int *pbPresent
170721
+){
170722
+ int rc = SQLITE_OK;
170723
+ *pbPresent = 0;
170724
+ if( p ){
170725
+ int i;
170726
+ int hash;
170727
+ Fts5TermsetEntry *pEntry;
170728
+
170729
+ /* Calculate a hash value for this term */
170730
+ hash = 104 + iIdx;
170731
+ for(i=0; i<nTerm; i++){
170732
+ hash += (hash << 3) + (int)pTerm[i];
170733
+ }
170734
+ hash = hash % ArraySize(p->apHash);
170735
+
170736
+ for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){
170737
+ if( pEntry->iIdx==iIdx
170738
+ && pEntry->nTerm==nTerm
170739
+ && memcmp(pEntry->pTerm, pTerm, nTerm)==0
170740
+ ){
170741
+ *pbPresent = 1;
170742
+ break;
170743
+ }
170744
+ }
170745
+
170746
+ if( pEntry==0 ){
170747
+ pEntry = sqlite3Fts5MallocZero(&rc, sizeof(Fts5TermsetEntry) + nTerm);
170748
+ if( pEntry ){
170749
+ pEntry->pTerm = (char*)&pEntry[1];
170750
+ pEntry->nTerm = nTerm;
170751
+ pEntry->iIdx = iIdx;
170752
+ memcpy(pEntry->pTerm, pTerm, nTerm);
170753
+ pEntry->pNext = p->apHash[hash];
170754
+ p->apHash[hash] = pEntry;
170755
+ }
170756
+ }
170757
+ }
170758
+
170759
+ return rc;
170760
+}
170761
+
170762
+static void sqlite3Fts5TermsetFree(Fts5Termset *p){
170763
+ if( p ){
170764
+ int i;
170765
+ for(i=0; i<ArraySize(p->apHash); i++){
170766
+ Fts5TermsetEntry *pEntry = p->apHash[i];
170767
+ while( pEntry ){
170768
+ Fts5TermsetEntry *pDel = pEntry;
170769
+ pEntry = pEntry->pNext;
170770
+ sqlite3_free(pDel);
170771
+ }
170772
+ }
170773
+ sqlite3_free(p);
170774
+ }
170775
+}
170776
+
170777
+
170778
+
170402170779
170403170780
/*
170404170781
** 2014 Jun 09
170405170782
**
170406170783
** The author disclaims copyright to this source code. In place of
@@ -170412,11 +170789,10 @@
170412170789
**
170413170790
******************************************************************************
170414170791
**
170415170792
** This is an SQLite module implementing full-text search.
170416170793
*/
170417
-
170418170794
170419170795
170420170796
/* #include "fts5Int.h" */
170421170797
170422170798
#define FTS5_DEFAULT_PAGE_SIZE 4050
@@ -170595,10 +170971,37 @@
170595170971
if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
170596170972
fts5Dequote(z);
170597170973
}
170598170974
}
170599170975
170976
+
170977
+struct Fts5Enum {
170978
+ const char *zName;
170979
+ int eVal;
170980
+};
170981
+typedef struct Fts5Enum Fts5Enum;
170982
+
170983
+static int fts5ConfigSetEnum(
170984
+ const Fts5Enum *aEnum,
170985
+ const char *zEnum,
170986
+ int *peVal
170987
+){
170988
+ int nEnum = strlen(zEnum);
170989
+ int i;
170990
+ int iVal = -1;
170991
+
170992
+ for(i=0; aEnum[i].zName; i++){
170993
+ if( sqlite3_strnicmp(aEnum[i].zName, zEnum, nEnum)==0 ){
170994
+ if( iVal>=0 ) return SQLITE_ERROR;
170995
+ iVal = aEnum[i].eVal;
170996
+ }
170997
+ }
170998
+
170999
+ *peVal = iVal;
171000
+ return iVal<0 ? SQLITE_ERROR : SQLITE_OK;
171001
+}
171002
+
170600171003
/*
170601171004
** Parse a "special" CREATE VIRTUAL TABLE directive and update
170602171005
** configuration object pConfig as appropriate.
170603171006
**
170604171007
** If successful, object pConfig is updated and SQLITE_OK returned. If
@@ -170744,10 +171147,24 @@
170744171147
}else{
170745171148
pConfig->bColumnsize = (zArg[0]=='1');
170746171149
}
170747171150
return rc;
170748171151
}
171152
+
171153
+ if( sqlite3_strnicmp("detail", zCmd, nCmd)==0 ){
171154
+ const Fts5Enum aDetail[] = {
171155
+ { "none", FTS5_DETAIL_NONE },
171156
+ { "full", FTS5_DETAIL_FULL },
171157
+ { "columns", FTS5_DETAIL_COLUMNS },
171158
+ { 0, 0 }
171159
+ };
171160
+
171161
+ if( (rc = fts5ConfigSetEnum(aDetail, zArg, &pConfig->eDetail)) ){
171162
+ *pzErr = sqlite3_mprintf("malformed detail=... directive");
171163
+ }
171164
+ return rc;
171165
+ }
170749171166
170750171167
*pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
170751171168
return SQLITE_ERROR;
170752171169
}
170753171170
@@ -170900,10 +171317,11 @@
170900171317
pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
170901171318
pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
170902171319
pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
170903171320
pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
170904171321
pRet->bColumnsize = 1;
171322
+ pRet->eDetail = FTS5_DETAIL_FULL;
170905171323
#ifdef SQLITE_DEBUG
170906171324
pRet->bPrefixIndex = 1;
170907171325
#endif
170908171326
if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){
170909171327
*pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName);
@@ -171346,10 +171764,11 @@
171346171764
#endif
171347171765
171348171766
171349171767
struct Fts5Expr {
171350171768
Fts5Index *pIndex;
171769
+ Fts5Config *pConfig;
171351171770
Fts5ExprNode *pRoot;
171352171771
int bDesc; /* Iterate in descending rowid order */
171353171772
int nPhrase; /* Number of phrases in expression */
171354171773
Fts5ExprPhrase **apExprPhrase; /* Pointers to phrase objects */
171355171774
};
@@ -171541,10 +171960,11 @@
171541171960
sParse.rc = SQLITE_NOMEM;
171542171961
sqlite3Fts5ParseNodeFree(sParse.pExpr);
171543171962
}else{
171544171963
pNew->pRoot = sParse.pExpr;
171545171964
pNew->pIndex = 0;
171965
+ pNew->pConfig = pConfig;
171546171966
pNew->apExprPhrase = sParse.apPhrase;
171547171967
pNew->nPhrase = sParse.nPhrase;
171548171968
sParse.apPhrase = 0;
171549171969
}
171550171970
}
@@ -171605,12 +172025,13 @@
171605172025
}
171606172026
171607172027
/*
171608172028
** Argument pTerm must be a synonym iterator.
171609172029
*/
171610
-static int fts5ExprSynonymPoslist(
172030
+static int fts5ExprSynonymList(
171611172031
Fts5ExprTerm *pTerm,
172032
+ int bCollist,
171612172033
Fts5Colset *pColset,
171613172034
i64 iRowid,
171614172035
int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */
171615172036
u8 **pa, int *pn
171616172037
){
@@ -171625,13 +172046,20 @@
171625172046
for(p=pTerm; p; p=p->pSynonym){
171626172047
Fts5IndexIter *pIter = p->pIter;
171627172048
if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){
171628172049
const u8 *a;
171629172050
int n;
171630
- i64 dummy;
171631
- rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy);
172051
+
172052
+ if( bCollist ){
172053
+ rc = sqlite3Fts5IterCollist(pIter, &a, &n);
172054
+ }else{
172055
+ i64 dummy;
172056
+ rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy);
172057
+ }
172058
+
171632172059
if( rc!=SQLITE_OK ) goto synonym_poslist_out;
172060
+ if( n==0 ) continue;
171633172061
if( nIter==nAlloc ){
171634172062
int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
171635172063
Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
171636172064
if( aNew==0 ){
171637172065
rc = SQLITE_NOMEM;
@@ -171728,12 +172156,12 @@
171728172156
i64 dummy;
171729172157
int n = 0;
171730172158
int bFlag = 0;
171731172159
const u8 *a = 0;
171732172160
if( pTerm->pSynonym ){
171733
- rc = fts5ExprSynonymPoslist(
171734
- pTerm, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n
172161
+ rc = fts5ExprSynonymList(
172162
+ pTerm, 0, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n
171735172163
);
171736172164
}else{
171737172165
rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy);
171738172166
}
171739172167
if( rc!=SQLITE_OK ) goto ismatch_out;
@@ -172063,34 +172491,55 @@
172063172491
Fts5Expr *pExpr, /* Expression that pNear is a part of */
172064172492
Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */
172065172493
){
172066172494
Fts5ExprNearset *pNear = pNode->pNear;
172067172495
int rc = *pRc;
172068
- int i;
172069
-
172070
- /* Check that each phrase in the nearset matches the current row.
172071
- ** Populate the pPhrase->poslist buffers at the same time. If any
172072
- ** phrase is not a match, break out of the loop early. */
172073
- for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
172074
- Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
172075
- if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){
172076
- int bMatch = 0;
172077
- rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch);
172078
- if( bMatch==0 ) break;
172079
- }else{
172080
- rc = sqlite3Fts5IterPoslistBuffer(
172081
- pPhrase->aTerm[0].pIter, &pPhrase->poslist
172082
- );
172083
- }
172084
- }
172085
-
172086
- *pRc = rc;
172087
- if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){
172088
- return 1;
172089
- }
172090
-
172091
- return 0;
172496
+
172497
+ if( pExpr->pConfig->eDetail!=FTS5_DETAIL_FULL ){
172498
+ Fts5ExprTerm *pTerm;
172499
+ Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
172500
+ pPhrase->poslist.n = 0;
172501
+ for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
172502
+ Fts5IndexIter *pIter = pTerm->pIter;
172503
+ if( sqlite3Fts5IterEof(pIter)==0 ){
172504
+ int n;
172505
+ i64 iRowid;
172506
+ rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid);
172507
+ if( rc!=SQLITE_OK ){
172508
+ *pRc = rc;
172509
+ return 0;
172510
+ }else if( iRowid==pNode->iRowid && n>0 ){
172511
+ pPhrase->poslist.n = 1;
172512
+ }
172513
+ }
172514
+ }
172515
+ return pPhrase->poslist.n;
172516
+ }else{
172517
+ int i;
172518
+
172519
+ /* Check that each phrase in the nearset matches the current row.
172520
+ ** Populate the pPhrase->poslist buffers at the same time. If any
172521
+ ** phrase is not a match, break out of the loop early. */
172522
+ for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
172523
+ Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
172524
+ if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){
172525
+ int bMatch = 0;
172526
+ rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch);
172527
+ if( bMatch==0 ) break;
172528
+ }else{
172529
+ rc = sqlite3Fts5IterPoslistBuffer(
172530
+ pPhrase->aTerm[0].pIter, &pPhrase->poslist
172531
+ );
172532
+ }
172533
+ }
172534
+
172535
+ *pRc = rc;
172536
+ if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){
172537
+ return 1;
172538
+ }
172539
+ return 0;
172540
+ }
172092172541
}
172093172542
172094172543
static int fts5ExprTokenTest(
172095172544
Fts5Expr *pExpr, /* Expression that pNear is a part of */
172096172545
Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */
@@ -172524,10 +172973,13 @@
172524172973
if( cmp || p2->bNomatch ) break;
172525172974
rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
172526172975
}
172527172976
pNode->bEof = p1->bEof;
172528172977
pNode->iRowid = p1->iRowid;
172978
+ if( p1->bEof ){
172979
+ fts5ExprNodeZeroPoslist(p2);
172980
+ }
172529172981
break;
172530172982
}
172531172983
}
172532172984
}
172533172985
return rc;
@@ -172909,10 +173361,11 @@
172909173361
}
172910173362
172911173363
if( rc==SQLITE_OK ){
172912173364
/* All the allocations succeeded. Put the expression object together. */
172913173365
pNew->pIndex = pExpr->pIndex;
173366
+ pNew->pConfig = pExpr->pConfig;
172914173367
pNew->nPhrase = 1;
172915173368
pNew->apExprPhrase[0] = sCtx.pPhrase;
172916173369
pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
172917173370
pNew->pRoot->pNear->nPhrase = 1;
172918173371
sCtx.pPhrase->pNode = pNew->pRoot;
@@ -173050,10 +173503,19 @@
173050173503
static void sqlite3Fts5ParseSetColset(
173051173504
Fts5Parse *pParse,
173052173505
Fts5ExprNearset *pNear,
173053173506
Fts5Colset *pColset
173054173507
){
173508
+ if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
173509
+ pParse->rc = SQLITE_ERROR;
173510
+ pParse->zErr = sqlite3_mprintf(
173511
+ "fts5: column queries are not supported (detail=none)"
173512
+ );
173513
+ sqlite3_free(pColset);
173514
+ return;
173515
+ }
173516
+
173055173517
if( pNear ){
173056173518
pNear->pColset = pColset;
173057173519
}else{
173058173520
sqlite3_free(pColset);
173059173521
}
@@ -173111,15 +173573,24 @@
173111173573
if( eType==FTS5_STRING ){
173112173574
int iPhrase;
173113173575
for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
173114173576
pNear->apPhrase[iPhrase]->pNode = pRet;
173115173577
}
173116
- if( pNear->nPhrase==1
173117
- && pNear->apPhrase[0]->nTerm==1
173118
- && pNear->apPhrase[0]->aTerm[0].pSynonym==0
173119
- ){
173120
- pRet->eType = FTS5_TERM;
173578
+ if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){
173579
+ if( pNear->apPhrase[0]->aTerm[0].pSynonym==0 ){
173580
+ pRet->eType = FTS5_TERM;
173581
+ }
173582
+ }else if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
173583
+ assert( pParse->rc==SQLITE_OK );
173584
+ pParse->rc = SQLITE_ERROR;
173585
+ assert( pParse->zErr==0 );
173586
+ pParse->zErr = sqlite3_mprintf(
173587
+ "fts5: %s queries are not supported (detail!=full)",
173588
+ pNear->nPhrase==1 ? "phrase": "NEAR"
173589
+ );
173590
+ sqlite3_free(pRet);
173591
+ pRet = 0;
173121173592
}
173122173593
}else{
173123173594
fts5ExprAddChildren(pRet, pLeft);
173124173595
fts5ExprAddChildren(pRet, pRight);
173125173596
}
@@ -173229,10 +173700,13 @@
173229173700
173230173701
zRet = fts5PrintfAppend(zRet, " {");
173231173702
for(iTerm=0; zRet && iTerm<pPhrase->nTerm; iTerm++){
173232173703
char *zTerm = pPhrase->aTerm[iTerm].zTerm;
173233173704
zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm);
173705
+ if( pPhrase->aTerm[iTerm].bPrefix ){
173706
+ zRet = fts5PrintfAppend(zRet, "*");
173707
+ }
173234173708
}
173235173709
173236173710
if( zRet ) zRet = fts5PrintfAppend(zRet, "}");
173237173711
if( zRet==0 ) return 0;
173238173712
}
@@ -173541,10 +174015,237 @@
173541174015
*pa = 0;
173542174016
nRet = 0;
173543174017
}
173544174018
return nRet;
173545174019
}
174020
+
174021
+struct Fts5PoslistPopulator {
174022
+ Fts5PoslistWriter writer;
174023
+ int bOk; /* True if ok to populate */
174024
+ int bMiss;
174025
+};
174026
+
174027
+static Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
174028
+ Fts5PoslistPopulator *pRet;
174029
+ pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
174030
+ if( pRet ){
174031
+ int i;
174032
+ memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
174033
+ for(i=0; i<pExpr->nPhrase; i++){
174034
+ Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist;
174035
+ Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
174036
+ assert( pExpr->apExprPhrase[i]->nTerm==1 );
174037
+ if( bLive &&
174038
+ (pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof)
174039
+ ){
174040
+ pRet[i].bMiss = 1;
174041
+ }else{
174042
+ pBuf->n = 0;
174043
+ }
174044
+ }
174045
+ }
174046
+ return pRet;
174047
+}
174048
+
174049
+struct Fts5ExprCtx {
174050
+ Fts5Expr *pExpr;
174051
+ Fts5PoslistPopulator *aPopulator;
174052
+ i64 iOff;
174053
+};
174054
+typedef struct Fts5ExprCtx Fts5ExprCtx;
174055
+
174056
+/*
174057
+** TODO: Make this more efficient!
174058
+*/
174059
+static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){
174060
+ int i;
174061
+ for(i=0; i<pColset->nCol; i++){
174062
+ if( pColset->aiCol[i]==iCol ) return 1;
174063
+ }
174064
+ return 0;
174065
+}
174066
+
174067
+static int fts5ExprPopulatePoslistsCb(
174068
+ void *pCtx, /* Copy of 2nd argument to xTokenize() */
174069
+ int tflags, /* Mask of FTS5_TOKEN_* flags */
174070
+ const char *pToken, /* Pointer to buffer containing token */
174071
+ int nToken, /* Size of token in bytes */
174072
+ int iStart, /* Byte offset of token within input text */
174073
+ int iEnd /* Byte offset of end of token within input text */
174074
+){
174075
+ Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx;
174076
+ Fts5Expr *pExpr = p->pExpr;
174077
+ int i;
174078
+
174079
+ if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++;
174080
+ for(i=0; i<pExpr->nPhrase; i++){
174081
+ Fts5ExprTerm *pTerm;
174082
+ if( p->aPopulator[i].bOk==0 ) continue;
174083
+ for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
174084
+ int nTerm = strlen(pTerm->zTerm);
174085
+ if( (nTerm==nToken || (nTerm<nToken && pTerm->bPrefix))
174086
+ && memcmp(pTerm->zTerm, pToken, nTerm)==0
174087
+ ){
174088
+ int rc = sqlite3Fts5PoslistWriterAppend(
174089
+ &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
174090
+ );
174091
+ if( rc ) return rc;
174092
+ break;
174093
+ }
174094
+ }
174095
+ }
174096
+ return SQLITE_OK;
174097
+}
174098
+
174099
+static int sqlite3Fts5ExprPopulatePoslists(
174100
+ Fts5Config *pConfig,
174101
+ Fts5Expr *pExpr,
174102
+ Fts5PoslistPopulator *aPopulator,
174103
+ int iCol,
174104
+ const char *z, int n
174105
+){
174106
+ int i;
174107
+ Fts5ExprCtx sCtx;
174108
+ sCtx.pExpr = pExpr;
174109
+ sCtx.aPopulator = aPopulator;
174110
+ sCtx.iOff = (((i64)iCol) << 32) - 1;
174111
+
174112
+ for(i=0; i<pExpr->nPhrase; i++){
174113
+ Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
174114
+ Fts5Colset *pColset = pNode->pNear->pColset;
174115
+ if( (pColset && 0==fts5ExprColsetTest(pColset, iCol))
174116
+ || aPopulator[i].bMiss
174117
+ ){
174118
+ aPopulator[i].bOk = 0;
174119
+ }else{
174120
+ aPopulator[i].bOk = 1;
174121
+ }
174122
+ }
174123
+
174124
+ return sqlite3Fts5Tokenize(pConfig,
174125
+ FTS5_TOKENIZE_AUX, z, n, (void*)&sCtx, fts5ExprPopulatePoslistsCb
174126
+ );
174127
+}
174128
+
174129
+static void fts5ExprClearPoslists(Fts5ExprNode *pNode){
174130
+ if( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING ){
174131
+ pNode->pNear->apPhrase[0]->poslist.n = 0;
174132
+ }else{
174133
+ int i;
174134
+ for(i=0; i<pNode->nChild; i++){
174135
+ fts5ExprClearPoslists(pNode->apChild[i]);
174136
+ }
174137
+ }
174138
+}
174139
+
174140
+static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){
174141
+ if( pNode ){
174142
+ pNode->iRowid = iRowid;
174143
+ pNode->bEof = 0;
174144
+ switch( pNode->eType ){
174145
+ case FTS5_TERM:
174146
+ case FTS5_STRING:
174147
+ return (pNode->pNear->apPhrase[0]->poslist.n>0);
174148
+
174149
+ case FTS5_AND: {
174150
+ int i;
174151
+ for(i=0; i<pNode->nChild; i++){
174152
+ if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid)==0 ){
174153
+ fts5ExprClearPoslists(pNode);
174154
+ return 0;
174155
+ }
174156
+ }
174157
+ break;
174158
+ }
174159
+
174160
+ case FTS5_OR: {
174161
+ int i;
174162
+ int bRet = 0;
174163
+ for(i=0; i<pNode->nChild; i++){
174164
+ if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid) ){
174165
+ bRet = 1;
174166
+ }
174167
+ }
174168
+ if( bRet==0 ){
174169
+ fts5ExprClearPoslists(pNode);
174170
+ }
174171
+ return bRet;
174172
+ }
174173
+
174174
+ default: {
174175
+ assert( pNode->eType==FTS5_NOT );
174176
+ if( 0==fts5ExprCheckPoslists(pNode->apChild[0], iRowid)
174177
+ || 0!=fts5ExprCheckPoslists(pNode->apChild[1], iRowid)
174178
+ ){
174179
+ fts5ExprClearPoslists(pNode);
174180
+ return 0;
174181
+ }
174182
+ break;
174183
+ }
174184
+ }
174185
+ }
174186
+ return 1;
174187
+}
174188
+
174189
+static void sqlite3Fts5ExprCheckPoslists(Fts5Expr *pExpr, i64 iRowid){
174190
+ fts5ExprCheckPoslists(pExpr->pRoot, iRowid);
174191
+}
174192
+
174193
+static void fts5ExprClearEof(Fts5ExprNode *pNode){
174194
+ int i;
174195
+ for(i=0; i<pNode->nChild; i++){
174196
+ fts5ExprClearEof(pNode->apChild[i]);
174197
+ }
174198
+ pNode->bEof = 0;
174199
+}
174200
+static void sqlite3Fts5ExprClearEof(Fts5Expr *pExpr){
174201
+ fts5ExprClearEof(pExpr->pRoot);
174202
+}
174203
+
174204
+/*
174205
+** This function is only called for detail=columns tables.
174206
+*/
174207
+static int sqlite3Fts5ExprPhraseCollist(
174208
+ Fts5Expr *pExpr,
174209
+ int iPhrase,
174210
+ const u8 **ppCollist,
174211
+ int *pnCollist
174212
+){
174213
+ Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase];
174214
+ Fts5ExprNode *pNode = pPhrase->pNode;
174215
+ int rc = SQLITE_OK;
174216
+
174217
+ assert( iPhrase>=0 && iPhrase<pExpr->nPhrase );
174218
+ if( pNode->bEof==0
174219
+ && pNode->iRowid==pExpr->pRoot->iRowid
174220
+ && pPhrase->poslist.n>0
174221
+ ){
174222
+ Fts5ExprTerm *pTerm = &pPhrase->aTerm[0];
174223
+ if( pTerm->pSynonym ){
174224
+ int bDel = 0;
174225
+ u8 *a;
174226
+ rc = fts5ExprSynonymList(
174227
+ pTerm, 1, 0, pNode->iRowid, &bDel, &a, pnCollist
174228
+ );
174229
+ if( bDel ){
174230
+ sqlite3Fts5BufferSet(&rc, &pPhrase->poslist, *pnCollist, a);
174231
+ *ppCollist = pPhrase->poslist.p;
174232
+ sqlite3_free(a);
174233
+ }else{
174234
+ *ppCollist = a;
174235
+ }
174236
+ }else{
174237
+ sqlite3Fts5IterCollist(pPhrase->aTerm[0].pIter, ppCollist, pnCollist);
174238
+ }
174239
+ }else{
174240
+ *ppCollist = 0;
174241
+ *pnCollist = 0;
174242
+ }
174243
+
174244
+ return rc;
174245
+}
174246
+
173546174247
173547174248
/*
173548174249
** 2014 August 11
173549174250
**
173550174251
** The author disclaims copyright to this source code. In place of
@@ -173570,10 +174271,11 @@
173570174271
** segment.
173571174272
*/
173572174273
173573174274
173574174275
struct Fts5Hash {
174276
+ int eDetail; /* Copy of Fts5Config.eDetail */
173575174277
int *pnByte; /* Pointer to bytes counter */
173576174278
int nEntry; /* Number of entries currently in hash */
173577174279
int nSlot; /* Size of aSlot[] array */
173578174280
Fts5HashEntry *pScan; /* Current ordered scan item */
173579174281
Fts5HashEntry **aSlot; /* Array of hash slots */
@@ -173606,10 +174308,11 @@
173606174308
173607174309
int nAlloc; /* Total size of allocation */
173608174310
int iSzPoslist; /* Offset of space for 4-byte poslist size */
173609174311
int nData; /* Total bytes of data (incl. structure) */
173610174312
u8 bDel; /* Set delete-flag @ iSzPoslist */
174313
+ u8 bContent; /* Set content-flag (detail=none mode) */
173611174314
173612174315
int iCol; /* Column of last value written */
173613174316
int iPos; /* Position of last value written */
173614174317
i64 iRowid; /* Rowid of last value written */
173615174318
char zKey[8]; /* Nul-terminated entry key */
@@ -173623,11 +174326,11 @@
173623174326
173624174327
173625174328
/*
173626174329
** Allocate a new hash table.
173627174330
*/
173628
-static int sqlite3Fts5HashNew(Fts5Hash **ppNew, int *pnByte){
174331
+static int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){
173629174332
int rc = SQLITE_OK;
173630174333
Fts5Hash *pNew;
173631174334
173632174335
*ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash));
173633174336
if( pNew==0 ){
@@ -173634,10 +174337,11 @@
173634174337
rc = SQLITE_NOMEM;
173635174338
}else{
173636174339
int nByte;
173637174340
memset(pNew, 0, sizeof(Fts5Hash));
173638174341
pNew->pnByte = pnByte;
174342
+ pNew->eDetail = pConfig->eDetail;
173639174343
173640174344
pNew->nSlot = 1024;
173641174345
nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
173642174346
pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
173643174347
if( pNew->aSlot==0 ){
@@ -173726,30 +174430,50 @@
173726174430
pHash->nSlot = nNew;
173727174431
pHash->aSlot = apNew;
173728174432
return SQLITE_OK;
173729174433
}
173730174434
173731
-static void fts5HashAddPoslistSize(Fts5HashEntry *p){
174435
+static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){
173732174436
if( p->iSzPoslist ){
173733174437
u8 *pPtr = (u8*)p;
173734
- int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */
173735
- int nPos = nSz*2 + p->bDel; /* Value of nPos field */
173736
-
173737
- assert( p->bDel==0 || p->bDel==1 );
173738
- if( nPos<=127 ){
173739
- pPtr[p->iSzPoslist] = (u8)nPos;
173740
- }else{
173741
- int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
173742
- memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
173743
- sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos);
173744
- p->nData += (nByte-1);
173745
- }
173746
- p->bDel = 0;
174438
+ if( pHash->eDetail==FTS5_DETAIL_NONE ){
174439
+ assert( p->nData==p->iSzPoslist );
174440
+ if( p->bDel ){
174441
+ pPtr[p->nData++] = 0x00;
174442
+ if( p->bContent ){
174443
+ pPtr[p->nData++] = 0x00;
174444
+ }
174445
+ }
174446
+ }else{
174447
+ int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */
174448
+ int nPos = nSz*2 + p->bDel; /* Value of nPos field */
174449
+
174450
+ assert( p->bDel==0 || p->bDel==1 );
174451
+ if( nPos<=127 ){
174452
+ pPtr[p->iSzPoslist] = (u8)nPos;
174453
+ }else{
174454
+ int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
174455
+ memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
174456
+ sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos);
174457
+ p->nData += (nByte-1);
174458
+ }
174459
+ }
174460
+
173747174461
p->iSzPoslist = 0;
174462
+ p->bDel = 0;
174463
+ p->bContent = 0;
173748174464
}
173749174465
}
173750174466
174467
+/*
174468
+** Add an entry to the in-memory hash table. The key is the concatenation
174469
+** of bByte and (pToken/nToken). The value is (iRowid/iCol/iPos).
174470
+**
174471
+** (bByte || pToken) -> (iRowid,iCol,iPos)
174472
+**
174473
+** Or, if iCol is negative, then the value is a delete marker.
174474
+*/
173751174475
static int sqlite3Fts5HashWrite(
173752174476
Fts5Hash *pHash,
173753174477
i64 iRowid, /* Rowid for this entry */
173754174478
int iCol, /* Column token appears in (-ve -> delete) */
173755174479
int iPos, /* Position of token within column */
@@ -173758,10 +174482,13 @@
173758174482
){
173759174483
unsigned int iHash;
173760174484
Fts5HashEntry *p;
173761174485
u8 *pPtr;
173762174486
int nIncr = 0; /* Amount to increment (*pHash->pnByte) by */
174487
+ int bNew; /* If non-delete entry should be written */
174488
+
174489
+ bNew = (pHash->eDetail==FTS5_DETAIL_FULL);
173763174490
173764174491
/* Attempt to locate an existing hash entry */
173765174492
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
173766174493
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
173767174494
if( p->zKey[0]==bByte
@@ -173772,92 +174499,120 @@
173772174499
}
173773174500
}
173774174501
173775174502
/* If an existing hash entry cannot be found, create a new one. */
173776174503
if( p==0 ){
174504
+ /* Figure out how much space to allocate */
173777174505
int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64;
173778174506
if( nByte<128 ) nByte = 128;
173779174507
174508
+ /* Grow the Fts5Hash.aSlot[] array if necessary. */
173780174509
if( (pHash->nEntry*2)>=pHash->nSlot ){
173781174510
int rc = fts5HashResize(pHash);
173782174511
if( rc!=SQLITE_OK ) return rc;
173783174512
iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
173784174513
}
173785174514
174515
+ /* Allocate new Fts5HashEntry and add it to the hash table. */
173786174516
p = (Fts5HashEntry*)sqlite3_malloc(nByte);
173787174517
if( !p ) return SQLITE_NOMEM;
173788174518
memset(p, 0, FTS5_HASHENTRYSIZE);
173789174519
p->nAlloc = nByte;
173790174520
p->zKey[0] = bByte;
173791174521
memcpy(&p->zKey[1], pToken, nToken);
173792174522
assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) );
173793174523
p->zKey[nToken+1] = '\0';
173794174524
p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE;
173795
- p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid);
173796
- p->iSzPoslist = p->nData;
173797
- p->nData += 1;
173798
- p->iRowid = iRowid;
173799174525
p->pHashNext = pHash->aSlot[iHash];
173800174526
pHash->aSlot[iHash] = p;
173801174527
pHash->nEntry++;
174528
+
174529
+ /* Add the first rowid field to the hash-entry */
174530
+ p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid);
174531
+ p->iRowid = iRowid;
174532
+
174533
+ p->iSzPoslist = p->nData;
174534
+ if( pHash->eDetail!=FTS5_DETAIL_NONE ){
174535
+ p->nData += 1;
174536
+ p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
174537
+ }
174538
+
173802174539
nIncr += p->nData;
173803
- }
173804
-
173805
- /* Check there is enough space to append a new entry. Worst case scenario
173806
- ** is:
173807
- **
173808
- ** + 9 bytes for a new rowid,
173809
- ** + 4 byte reserved for the "poslist size" varint.
173810
- ** + 1 byte for a "new column" byte,
173811
- ** + 3 bytes for a new column number (16-bit max) as a varint,
173812
- ** + 5 bytes for the new position offset (32-bit max).
173813
- */
173814
- if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
173815
- int nNew = p->nAlloc * 2;
173816
- Fts5HashEntry *pNew;
173817
- Fts5HashEntry **pp;
173818
- pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
173819
- if( pNew==0 ) return SQLITE_NOMEM;
173820
- pNew->nAlloc = nNew;
173821
- for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
173822
- *pp = pNew;
173823
- p = pNew;
173824
- }
173825
- pPtr = (u8*)p;
173826
- nIncr -= p->nData;
174540
+ }else{
174541
+
174542
+ /* Appending to an existing hash-entry. Check that there is enough
174543
+ ** space to append the largest possible new entry. Worst case scenario
174544
+ ** is:
174545
+ **
174546
+ ** + 9 bytes for a new rowid,
174547
+ ** + 4 byte reserved for the "poslist size" varint.
174548
+ ** + 1 byte for a "new column" byte,
174549
+ ** + 3 bytes for a new column number (16-bit max) as a varint,
174550
+ ** + 5 bytes for the new position offset (32-bit max).
174551
+ */
174552
+ if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
174553
+ int nNew = p->nAlloc * 2;
174554
+ Fts5HashEntry *pNew;
174555
+ Fts5HashEntry **pp;
174556
+ pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
174557
+ if( pNew==0 ) return SQLITE_NOMEM;
174558
+ pNew->nAlloc = nNew;
174559
+ for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
174560
+ *pp = pNew;
174561
+ p = pNew;
174562
+ }
174563
+ nIncr -= p->nData;
174564
+ }
174565
+ assert( (p->nAlloc - p->nData) >= (9 + 4 + 1 + 3 + 5) );
174566
+
174567
+ pPtr = (u8*)p;
173827174568
173828174569
/* If this is a new rowid, append the 4-byte size field for the previous
173829174570
** entry, and the new rowid for this entry. */
173830174571
if( iRowid!=p->iRowid ){
173831
- fts5HashAddPoslistSize(p);
174572
+ fts5HashAddPoslistSize(pHash, p);
173832174573
p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
174574
+ p->iRowid = iRowid;
174575
+ bNew = 1;
173833174576
p->iSzPoslist = p->nData;
173834
- p->nData += 1;
173835
- p->iCol = 0;
173836
- p->iPos = 0;
173837
- p->iRowid = iRowid;
174577
+ if( pHash->eDetail!=FTS5_DETAIL_NONE ){
174578
+ p->nData += 1;
174579
+ p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
174580
+ p->iPos = 0;
174581
+ }
173838174582
}
173839174583
173840174584
if( iCol>=0 ){
173841
- /* Append a new column value, if necessary */
173842
- assert( iCol>=p->iCol );
173843
- if( iCol!=p->iCol ){
173844
- pPtr[p->nData++] = 0x01;
173845
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
173846
- p->iCol = iCol;
173847
- p->iPos = 0;
173848
- }
173849
-
173850
- /* Append the new position offset */
173851
- p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iPos - p->iPos + 2);
173852
- p->iPos = iPos;
174585
+ if( pHash->eDetail==FTS5_DETAIL_NONE ){
174586
+ p->bContent = 1;
174587
+ }else{
174588
+ /* Append a new column value, if necessary */
174589
+ assert( iCol>=p->iCol );
174590
+ if( iCol!=p->iCol ){
174591
+ if( pHash->eDetail==FTS5_DETAIL_FULL ){
174592
+ pPtr[p->nData++] = 0x01;
174593
+ p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
174594
+ p->iCol = iCol;
174595
+ p->iPos = 0;
174596
+ }else{
174597
+ bNew = 1;
174598
+ p->iCol = iPos = iCol;
174599
+ }
174600
+ }
174601
+
174602
+ /* Append the new position offset, if necessary */
174603
+ if( bNew ){
174604
+ p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iPos - p->iPos + 2);
174605
+ p->iPos = iPos;
174606
+ }
174607
+ }
173853174608
}else{
173854174609
/* This is a delete. Set the delete flag. */
173855174610
p->bDel = 1;
173856174611
}
174612
+
173857174613
nIncr += p->nData;
173858
-
173859174614
*pHash->pnByte += nIncr;
173860174615
return SQLITE_OK;
173861174616
}
173862174617
173863174618
@@ -173967,11 +174722,11 @@
173967174722
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
173968174723
if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break;
173969174724
}
173970174725
173971174726
if( p ){
173972
- fts5HashAddPoslistSize(p);
174727
+ fts5HashAddPoslistSize(pHash, p);
173973174728
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
173974174729
*pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
173975174730
}else{
173976174731
*ppDoclist = 0;
173977174732
*pnDoclist = 0;
@@ -174003,11 +174758,11 @@
174003174758
int *pnDoclist /* OUT: size of doclist in bytes */
174004174759
){
174005174760
Fts5HashEntry *p;
174006174761
if( (p = pHash->pScan) ){
174007174762
int nTerm = (int)strlen(p->zKey);
174008
- fts5HashAddPoslistSize(p);
174763
+ fts5HashAddPoslistSize(pHash, p);
174009174764
*pzTerm = p->zKey;
174010174765
*ppDoclist = (const u8*)&p->zKey[nTerm+1];
174011174766
*pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
174012174767
}else{
174013174768
*pzTerm = 0;
@@ -174450,10 +175205,13 @@
174450175205
int iLeafPgno; /* Current leaf page number */
174451175206
Fts5Data *pLeaf; /* Current leaf data */
174452175207
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
174453175208
int iLeafOffset; /* Byte offset within current leaf */
174454175209
175210
+ /* Next method */
175211
+ void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
175212
+
174455175213
/* The page and offset from which the current term was read. The offset
174456175214
** is the offset of the first rowid in the current doclist. */
174457175215
int iTermLeafPgno;
174458175216
int iTermLeafOffset;
174459175217
@@ -174469,11 +175227,11 @@
174469175227
174470175228
/* Variables populated based on current entry. */
174471175229
Fts5Buffer term; /* Current term */
174472175230
i64 iRowid; /* Current rowid */
174473175231
int nPos; /* Number of bytes in current position list */
174474
- int bDel; /* True if the delete flag is set */
175232
+ u8 bDel; /* True if the delete flag is set */
174475175233
};
174476175234
174477175235
/*
174478175236
** Argument is a pointer to an Fts5Data structure that contains a
174479175237
** leaf page.
@@ -174482,11 +175240,10 @@
174482175240
(x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \
174483175241
)
174484175242
174485175243
#define FTS5_SEGITER_ONETERM 0x01
174486175244
#define FTS5_SEGITER_REVERSE 0x02
174487
-
174488175245
174489175246
/*
174490175247
** Argument is a pointer to an Fts5Data structure that contains a leaf
174491175248
** page. This macro evaluates to true if the leaf contains no terms, or
174492175249
** false if it contains at least one term.
@@ -175509,17 +176266,33 @@
175509176266
** position list content (if any).
175510176267
*/
175511176268
static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
175512176269
if( p->rc==SQLITE_OK ){
175513176270
int iOff = pIter->iLeafOffset; /* Offset to read at */
175514
- int nSz;
175515176271
ASSERT_SZLEAF_OK(pIter->pLeaf);
175516
- fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz);
175517
- pIter->bDel = (nSz & 0x0001);
175518
- pIter->nPos = nSz>>1;
176272
+ if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
176273
+ int iEod = MIN(pIter->iEndofDoclist, pIter->pLeaf->szLeaf);
176274
+ pIter->bDel = 0;
176275
+ pIter->nPos = 1;
176276
+ if( iOff<iEod && pIter->pLeaf->p[iOff]==0 ){
176277
+ pIter->bDel = 1;
176278
+ iOff++;
176279
+ if( iOff<iEod && pIter->pLeaf->p[iOff]==0 ){
176280
+ pIter->nPos = 1;
176281
+ iOff++;
176282
+ }else{
176283
+ pIter->nPos = 0;
176284
+ }
176285
+ }
176286
+ }else{
176287
+ int nSz;
176288
+ fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz);
176289
+ pIter->bDel = (nSz & 0x0001);
176290
+ pIter->nPos = nSz>>1;
176291
+ assert_nc( pIter->nPos>=0 );
176292
+ }
175519176293
pIter->iLeafOffset = iOff;
175520
- assert_nc( pIter->nPos>=0 );
175521176294
}
175522176295
}
175523176296
175524176297
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
175525176298
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
@@ -175575,10 +176348,24 @@
175575176348
pIter->iEndofDoclist += nExtra;
175576176349
}
175577176350
175578176351
fts5SegIterLoadRowid(p, pIter);
175579176352
}
176353
+
176354
+static void fts5SegIterNext(Fts5Index*, Fts5SegIter*, int*);
176355
+static void fts5SegIterNext_Reverse(Fts5Index*, Fts5SegIter*, int*);
176356
+static void fts5SegIterNext_None(Fts5Index*, Fts5SegIter*, int*);
176357
+
176358
+static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
176359
+ if( pIter->flags & FTS5_SEGITER_REVERSE ){
176360
+ pIter->xNext = fts5SegIterNext_Reverse;
176361
+ }else if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
176362
+ pIter->xNext = fts5SegIterNext_None;
176363
+ }else{
176364
+ pIter->xNext = fts5SegIterNext;
176365
+ }
176366
+}
175580176367
175581176368
/*
175582176369
** Initialize the iterator object pIter to iterate through the entries in
175583176370
** segment pSeg. The iterator is left pointing to the first entry when
175584176371
** this function returns.
@@ -175601,10 +176388,11 @@
175601176388
return;
175602176389
}
175603176390
175604176391
if( p->rc==SQLITE_OK ){
175605176392
memset(pIter, 0, sizeof(*pIter));
176393
+ fts5SegIterSetNext(p, pIter);
175606176394
pIter->pSeg = pSeg;
175607176395
pIter->iLeafPgno = pSeg->pgnoFirst-1;
175608176396
fts5SegIterNextPage(p, pIter);
175609176397
}
175610176398
@@ -175632,10 +176420,11 @@
175632176420
** aRowidOffset[] and iRowidOffset variables. At this point the iterator
175633176421
** is in its regular state - Fts5SegIter.iLeafOffset points to the first
175634176422
** byte of the position list content associated with said rowid.
175635176423
*/
175636176424
static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
176425
+ int eDetail = p->pConfig->eDetail;
175637176426
int n = pIter->pLeaf->szLeaf;
175638176427
int i = pIter->iLeafOffset;
175639176428
u8 *a = pIter->pLeaf->p;
175640176429
int iRowidOffset = 0;
175641176430
@@ -175644,19 +176433,28 @@
175644176433
}
175645176434
175646176435
ASSERT_SZLEAF_OK(pIter->pLeaf);
175647176436
while( 1 ){
175648176437
i64 iDelta = 0;
175649
- int nPos;
175650
- int bDummy;
175651176438
175652
- i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
175653
- i += nPos;
176439
+ if( eDetail==FTS5_DETAIL_NONE ){
176440
+ /* todo */
176441
+ if( i<n && a[i]==0 ){
176442
+ i++;
176443
+ if( i<n && a[i]==0 ) i++;
176444
+ }
176445
+ }else{
176446
+ int nPos;
176447
+ int bDummy;
176448
+ i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
176449
+ i += nPos;
176450
+ }
175654176451
if( i>=n ) break;
175655176452
i += fts5GetVarint(&a[i], (u64*)&iDelta);
175656176453
pIter->iRowid += iDelta;
175657176454
176455
+ /* If necessary, grow the pIter->aRowidOffset[] array. */
175658176456
if( iRowidOffset>=pIter->nRowidOffset ){
175659176457
int nNew = pIter->nRowidOffset + 8;
175660176458
int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
175661176459
if( aNew==0 ){
175662176460
p->rc = SQLITE_NOMEM;
@@ -175730,10 +176528,112 @@
175730176528
*/
175731176529
static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5IndexIter *pIter){
175732176530
Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
175733176531
return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0);
175734176532
}
176533
+
176534
+/*
176535
+** Advance iterator pIter to the next entry.
176536
+**
176537
+** This version of fts5SegIterNext() is only used by reverse iterators.
176538
+*/
176539
+static void fts5SegIterNext_Reverse(
176540
+ Fts5Index *p, /* FTS5 backend object */
176541
+ Fts5SegIter *pIter, /* Iterator to advance */
176542
+ int *pbNewTerm /* OUT: Set for new term */
176543
+){
176544
+ assert( pIter->flags & FTS5_SEGITER_REVERSE );
176545
+ assert( pIter->pNextLeaf==0 );
176546
+ if( pIter->iRowidOffset>0 ){
176547
+ u8 *a = pIter->pLeaf->p;
176548
+ int iOff;
176549
+ i64 iDelta;
176550
+
176551
+ pIter->iRowidOffset--;
176552
+ pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
176553
+ fts5SegIterLoadNPos(p, pIter);
176554
+ iOff = pIter->iLeafOffset;
176555
+ if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
176556
+ iOff += pIter->nPos;
176557
+ }
176558
+ fts5GetVarint(&a[iOff], (u64*)&iDelta);
176559
+ pIter->iRowid -= iDelta;
176560
+ }else{
176561
+ fts5SegIterReverseNewPage(p, pIter);
176562
+ }
176563
+}
176564
+
176565
+/*
176566
+** Advance iterator pIter to the next entry.
176567
+**
176568
+** This version of fts5SegIterNext() is only used if detail=none and the
176569
+** iterator is not a reverse direction iterator.
176570
+*/
176571
+static void fts5SegIterNext_None(
176572
+ Fts5Index *p, /* FTS5 backend object */
176573
+ Fts5SegIter *pIter, /* Iterator to advance */
176574
+ int *pbNewTerm /* OUT: Set for new term */
176575
+){
176576
+ int iOff;
176577
+
176578
+ assert( p->rc==SQLITE_OK );
176579
+ assert( (pIter->flags & FTS5_SEGITER_REVERSE)==0 );
176580
+ assert( p->pConfig->eDetail==FTS5_DETAIL_NONE );
176581
+
176582
+ ASSERT_SZLEAF_OK(pIter->pLeaf);
176583
+ iOff = pIter->iLeafOffset;
176584
+
176585
+ /* Next entry is on the next page */
176586
+ if( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){
176587
+ fts5SegIterNextPage(p, pIter);
176588
+ if( p->rc || pIter->pLeaf==0 ) return;
176589
+ pIter->iRowid = 0;
176590
+ iOff = 4;
176591
+ }
176592
+
176593
+ if( iOff<pIter->iEndofDoclist ){
176594
+ /* Next entry is on the current page */
176595
+ i64 iDelta;
176596
+ iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
176597
+ pIter->iLeafOffset = iOff;
176598
+ pIter->iRowid += iDelta;
176599
+ }else if( (pIter->flags & FTS5_SEGITER_ONETERM)==0 ){
176600
+ if( pIter->pSeg ){
176601
+ int nKeep = 0;
176602
+ if( iOff!=fts5LeafFirstTermOff(pIter->pLeaf) ){
176603
+ iOff += fts5GetVarint32(&pIter->pLeaf->p[iOff], nKeep);
176604
+ }
176605
+ pIter->iLeafOffset = iOff;
176606
+ fts5SegIterLoadTerm(p, pIter, nKeep);
176607
+ }else{
176608
+ const u8 *pList = 0;
176609
+ const char *zTerm = 0;
176610
+ int nList;
176611
+ sqlite3Fts5HashScanNext(p->pHash);
176612
+ sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
176613
+ if( pList==0 ) goto next_none_eof;
176614
+ pIter->pLeaf->p = (u8*)pList;
176615
+ pIter->pLeaf->nn = nList;
176616
+ pIter->pLeaf->szLeaf = nList;
176617
+ pIter->iEndofDoclist = nList;
176618
+ sqlite3Fts5BufferSet(&p->rc,&pIter->term, (int)strlen(zTerm), (u8*)zTerm);
176619
+ pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
176620
+ }
176621
+
176622
+ if( pbNewTerm ) *pbNewTerm = 1;
176623
+ }else{
176624
+ goto next_none_eof;
176625
+ }
176626
+
176627
+ fts5SegIterLoadNPos(p, pIter);
176628
+
176629
+ return;
176630
+ next_none_eof:
176631
+ fts5DataRelease(pIter->pLeaf);
176632
+ pIter->pLeaf = 0;
176633
+}
176634
+
175735176635
175736176636
/*
175737176637
** Advance iterator pIter to the next entry.
175738176638
**
175739176639
** If an error occurs, Fts5Index.rc is set to an appropriate error code. It
@@ -175743,144 +176643,133 @@
175743176643
static void fts5SegIterNext(
175744176644
Fts5Index *p, /* FTS5 backend object */
175745176645
Fts5SegIter *pIter, /* Iterator to advance */
175746176646
int *pbNewTerm /* OUT: Set for new term */
175747176647
){
175748
- assert( pbNewTerm==0 || *pbNewTerm==0 );
175749
- if( p->rc==SQLITE_OK ){
175750
- if( pIter->flags & FTS5_SEGITER_REVERSE ){
175751
- assert( pIter->pNextLeaf==0 );
175752
- if( pIter->iRowidOffset>0 ){
175753
- u8 *a = pIter->pLeaf->p;
175754
- int iOff;
175755
- int nPos;
175756
- int bDummy;
175757
- i64 iDelta;
175758
-
175759
- pIter->iRowidOffset--;
175760
- pIter->iLeafOffset = iOff = pIter->aRowidOffset[pIter->iRowidOffset];
175761
- iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDummy);
175762
- iOff += nPos;
175763
- fts5GetVarint(&a[iOff], (u64*)&iDelta);
175764
- pIter->iRowid -= iDelta;
175765
- fts5SegIterLoadNPos(p, pIter);
175766
- }else{
175767
- fts5SegIterReverseNewPage(p, pIter);
175768
- }
175769
- }else{
175770
- Fts5Data *pLeaf = pIter->pLeaf;
175771
- int iOff;
175772
- int bNewTerm = 0;
175773
- int nKeep = 0;
175774
-
175775
- /* Search for the end of the position list within the current page. */
175776
- u8 *a = pLeaf->p;
175777
- int n = pLeaf->szLeaf;
175778
-
175779
- ASSERT_SZLEAF_OK(pLeaf);
175780
- iOff = pIter->iLeafOffset + pIter->nPos;
175781
-
175782
- if( iOff<n ){
175783
- /* The next entry is on the current page. */
175784
- assert_nc( iOff<=pIter->iEndofDoclist );
175785
- if( iOff>=pIter->iEndofDoclist ){
175786
- bNewTerm = 1;
175787
- if( iOff!=fts5LeafFirstTermOff(pLeaf) ){
175788
- iOff += fts5GetVarint32(&a[iOff], nKeep);
175789
- }
175790
- }else{
175791
- u64 iDelta;
175792
- iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta);
175793
- pIter->iRowid += iDelta;
175794
- assert_nc( iDelta>0 );
175795
- }
175796
- pIter->iLeafOffset = iOff;
175797
-
175798
- }else if( pIter->pSeg==0 ){
175799
- const u8 *pList = 0;
175800
- const char *zTerm = 0;
175801
- int nList = 0;
175802
- assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
175803
- if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
175804
- sqlite3Fts5HashScanNext(p->pHash);
175805
- sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
175806
- }
175807
- if( pList==0 ){
175808
- fts5DataRelease(pIter->pLeaf);
175809
- pIter->pLeaf = 0;
175810
- }else{
175811
- pIter->pLeaf->p = (u8*)pList;
175812
- pIter->pLeaf->nn = nList;
175813
- pIter->pLeaf->szLeaf = nList;
175814
- pIter->iEndofDoclist = nList+1;
175815
- sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm),
175816
- (u8*)zTerm);
175817
- pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
175818
- *pbNewTerm = 1;
175819
- }
175820
- }else{
175821
- iOff = 0;
175822
- /* Next entry is not on the current page */
175823
- while( iOff==0 ){
175824
- fts5SegIterNextPage(p, pIter);
175825
- pLeaf = pIter->pLeaf;
175826
- if( pLeaf==0 ) break;
175827
- ASSERT_SZLEAF_OK(pLeaf);
175828
- if( (iOff = fts5LeafFirstRowidOff(pLeaf)) && iOff<pLeaf->szLeaf ){
175829
- iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid);
175830
- pIter->iLeafOffset = iOff;
175831
-
175832
- if( pLeaf->nn>pLeaf->szLeaf ){
175833
- pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
175834
- &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist
175835
- );
175836
- }
175837
-
175838
- }
175839
- else if( pLeaf->nn>pLeaf->szLeaf ){
175840
- pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
175841
- &pLeaf->p[pLeaf->szLeaf], iOff
175842
- );
175843
- pIter->iLeafOffset = iOff;
175844
- pIter->iEndofDoclist = iOff;
175845
- bNewTerm = 1;
175846
- }
175847
- if( iOff>=pLeaf->szLeaf ){
175848
- p->rc = FTS5_CORRUPT;
175849
- return;
175850
- }
175851
- }
175852
- }
175853
-
175854
- /* Check if the iterator is now at EOF. If so, return early. */
175855
- if( pIter->pLeaf ){
175856
- if( bNewTerm ){
175857
- if( pIter->flags & FTS5_SEGITER_ONETERM ){
175858
- fts5DataRelease(pIter->pLeaf);
175859
- pIter->pLeaf = 0;
175860
- }else{
175861
- fts5SegIterLoadTerm(p, pIter, nKeep);
175862
- fts5SegIterLoadNPos(p, pIter);
175863
- if( pbNewTerm ) *pbNewTerm = 1;
175864
- }
175865
- }else{
175866
- /* The following could be done by calling fts5SegIterLoadNPos(). But
175867
- ** this block is particularly performance critical, so equivalent
175868
- ** code is inlined. */
175869
- int nSz;
175870
- assert( p->rc==SQLITE_OK );
175871
- fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
175872
- pIter->bDel = (nSz & 0x0001);
175873
- pIter->nPos = nSz>>1;
175874
- assert_nc( pIter->nPos>=0 );
175875
- }
175876
- }
176648
+ Fts5Data *pLeaf = pIter->pLeaf;
176649
+ int iOff;
176650
+ int bNewTerm = 0;
176651
+ int nKeep = 0;
176652
+
176653
+ assert( pbNewTerm==0 || *pbNewTerm==0 );
176654
+ assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
176655
+
176656
+ /* Search for the end of the position list within the current page. */
176657
+ u8 *a = pLeaf->p;
176658
+ int n = pLeaf->szLeaf;
176659
+
176660
+ ASSERT_SZLEAF_OK(pLeaf);
176661
+ iOff = pIter->iLeafOffset + pIter->nPos;
176662
+
176663
+ if( iOff<n ){
176664
+ /* The next entry is on the current page. */
176665
+ assert_nc( iOff<=pIter->iEndofDoclist );
176666
+ if( iOff>=pIter->iEndofDoclist ){
176667
+ bNewTerm = 1;
176668
+ if( iOff!=fts5LeafFirstTermOff(pLeaf) ){
176669
+ iOff += fts5GetVarint32(&a[iOff], nKeep);
176670
+ }
176671
+ }else{
176672
+ u64 iDelta;
176673
+ iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta);
176674
+ pIter->iRowid += iDelta;
176675
+ assert_nc( iDelta>0 );
176676
+ }
176677
+ pIter->iLeafOffset = iOff;
176678
+
176679
+ }else if( pIter->pSeg==0 ){
176680
+ const u8 *pList = 0;
176681
+ const char *zTerm = 0;
176682
+ int nList = 0;
176683
+ assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
176684
+ if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
176685
+ sqlite3Fts5HashScanNext(p->pHash);
176686
+ sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
176687
+ }
176688
+ if( pList==0 ){
176689
+ fts5DataRelease(pIter->pLeaf);
176690
+ pIter->pLeaf = 0;
176691
+ }else{
176692
+ pIter->pLeaf->p = (u8*)pList;
176693
+ pIter->pLeaf->nn = nList;
176694
+ pIter->pLeaf->szLeaf = nList;
176695
+ pIter->iEndofDoclist = nList+1;
176696
+ sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm),
176697
+ (u8*)zTerm);
176698
+ pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
176699
+ *pbNewTerm = 1;
176700
+ }
176701
+ }else{
176702
+ iOff = 0;
176703
+ /* Next entry is not on the current page */
176704
+ while( iOff==0 ){
176705
+ fts5SegIterNextPage(p, pIter);
176706
+ pLeaf = pIter->pLeaf;
176707
+ if( pLeaf==0 ) break;
176708
+ ASSERT_SZLEAF_OK(pLeaf);
176709
+ if( (iOff = fts5LeafFirstRowidOff(pLeaf)) && iOff<pLeaf->szLeaf ){
176710
+ iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid);
176711
+ pIter->iLeafOffset = iOff;
176712
+
176713
+ if( pLeaf->nn>pLeaf->szLeaf ){
176714
+ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
176715
+ &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist
176716
+ );
176717
+ }
176718
+
176719
+ }
176720
+ else if( pLeaf->nn>pLeaf->szLeaf ){
176721
+ pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
176722
+ &pLeaf->p[pLeaf->szLeaf], iOff
176723
+ );
176724
+ pIter->iLeafOffset = iOff;
176725
+ pIter->iEndofDoclist = iOff;
176726
+ bNewTerm = 1;
176727
+ }
176728
+ assert_nc( iOff<pLeaf->szLeaf );
176729
+ if( iOff>pLeaf->szLeaf ){
176730
+ p->rc = FTS5_CORRUPT;
176731
+ return;
176732
+ }
176733
+ }
176734
+ }
176735
+
176736
+ /* Check if the iterator is now at EOF. If so, return early. */
176737
+ if( pIter->pLeaf ){
176738
+ if( bNewTerm ){
176739
+ if( pIter->flags & FTS5_SEGITER_ONETERM ){
176740
+ fts5DataRelease(pIter->pLeaf);
176741
+ pIter->pLeaf = 0;
176742
+ }else{
176743
+ fts5SegIterLoadTerm(p, pIter, nKeep);
176744
+ fts5SegIterLoadNPos(p, pIter);
176745
+ if( pbNewTerm ) *pbNewTerm = 1;
176746
+ }
176747
+ }else{
176748
+ /* The following could be done by calling fts5SegIterLoadNPos(). But
176749
+ ** this block is particularly performance critical, so equivalent
176750
+ ** code is inlined.
176751
+ **
176752
+ ** Later: Switched back to fts5SegIterLoadNPos() because it supports
176753
+ ** detail=none mode. Not ideal.
176754
+ */
176755
+ int nSz;
176756
+ assert( p->rc==SQLITE_OK );
176757
+ fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
176758
+ pIter->bDel = (nSz & 0x0001);
176759
+ pIter->nPos = nSz>>1;
176760
+ assert_nc( pIter->nPos>=0 );
175877176761
}
175878176762
}
175879176763
}
175880176764
175881176765
#define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; }
176766
+
176767
+#define fts5IndexSkipVarint(a, iOff) { \
176768
+ int iEnd = iOff+9; \
176769
+ while( (a[iOff++] & 0x80) && iOff<iEnd ); \
176770
+}
175882176771
175883176772
/*
175884176773
** Iterator pIter currently points to the first rowid in a doclist. This
175885176774
** function sets the iterator up so that iterates in reverse order through
175886176775
** the doclist.
@@ -175898,11 +176787,21 @@
175898176787
Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
175899176788
175900176789
/* Currently, Fts5SegIter.iLeafOffset points to the first byte of
175901176790
** position-list content for the current rowid. Back it up so that it
175902176791
** points to the start of the position-list size field. */
175903
- pIter->iLeafOffset -= sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel);
176792
+ int iPoslist;
176793
+ if( pIter->iTermLeafPgno==pIter->iLeafPgno ){
176794
+ iPoslist = pIter->iTermLeafOffset;
176795
+ }else{
176796
+ iPoslist = 4;
176797
+ }
176798
+ fts5IndexSkipVarint(pLeaf->p, iPoslist);
176799
+ assert( p->pConfig->eDetail==FTS5_DETAIL_NONE || iPoslist==(
176800
+ pIter->iLeafOffset - sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel)
176801
+ ));
176802
+ pIter->iLeafOffset = iPoslist;
175904176803
175905176804
/* If this condition is true then the largest rowid for the current
175906176805
** term may not be stored on the current page. So search forward to
175907176806
** see where said rowid really is. */
175908176807
if( pIter->iEndofDoclist>=pLeaf->szLeaf ){
@@ -175982,15 +176881,10 @@
175982176881
}
175983176882
175984176883
pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
175985176884
}
175986176885
175987
-#define fts5IndexSkipVarint(a, iOff) { \
175988
- int iEnd = iOff+9; \
175989
- while( (a[iOff++] & 0x80) && iOff<iEnd ); \
175990
-}
175991
-
175992176886
/*
175993176887
** The iterator object passed as the second argument currently contains
175994176888
** no valid values except for the Fts5SegIter.pLeaf member variable. This
175995176889
** function searches the leaf page for a term matching (pTerm/nTerm).
175996176890
**
@@ -176189,10 +177083,12 @@
176189177083
fts5SegIterReverse(p, pIter);
176190177084
}
176191177085
}
176192177086
}
176193177087
177088
+ fts5SegIterSetNext(p, pIter);
177089
+
176194177090
/* Either:
176195177091
**
176196177092
** 1) an error has occurred, or
176197177093
** 2) the iterator points to EOF, or
176198177094
** 3) the iterator points to an entry with term (pTerm/nTerm), or
@@ -176246,19 +177142,21 @@
176246177142
if( pLeaf==0 ) return;
176247177143
pLeaf->p = (u8*)pList;
176248177144
pLeaf->nn = pLeaf->szLeaf = nList;
176249177145
pIter->pLeaf = pLeaf;
176250177146
pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
176251
- pIter->iEndofDoclist = pLeaf->nn+1;
177147
+ pIter->iEndofDoclist = pLeaf->nn;
176252177148
176253177149
if( flags & FTS5INDEX_QUERY_DESC ){
176254177150
pIter->flags |= FTS5_SEGITER_REVERSE;
176255177151
fts5SegIterReverseInitPage(p, pIter);
176256177152
}else{
176257177153
fts5SegIterLoadNPos(p, pIter);
176258177154
}
176259177155
}
177156
+
177157
+ fts5SegIterSetNext(p, pIter);
176260177158
}
176261177159
176262177160
/*
176263177161
** Zero the iterator passed as the only argument.
176264177162
*/
@@ -176498,11 +177396,11 @@
176498177396
bMove = 0;
176499177397
}
176500177398
}
176501177399
176502177400
do{
176503
- if( bMove ) fts5SegIterNext(p, pIter, 0);
177401
+ if( bMove && p->rc==SQLITE_OK ) pIter->xNext(p, pIter, 0);
176504177402
if( pIter->pLeaf==0 ) break;
176505177403
if( bRev==0 && pIter->iRowid>=iMatch ) break;
176506177404
if( bRev!=0 && pIter->iRowid<=iMatch ) break;
176507177405
bMove = 1;
176508177406
}while( p->rc==SQLITE_OK );
@@ -176532,11 +177430,13 @@
176532177430
){
176533177431
int i;
176534177432
for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){
176535177433
int iEq;
176536177434
if( (iEq = fts5MultiIterDoCompare(pIter, i)) ){
176537
- fts5SegIterNext(p, &pIter->aSeg[iEq], 0);
177435
+ Fts5SegIter *pSeg = &pIter->aSeg[iEq];
177436
+ assert( p->rc==SQLITE_OK );
177437
+ pSeg->xNext(p, pSeg, 0);
176538177438
i = pIter->nSeg + iEq;
176539177439
}
176540177440
}
176541177441
}
176542177442
@@ -176619,11 +177519,11 @@
176619177519
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
176620177520
assert( p->rc==SQLITE_OK );
176621177521
if( bUseFrom && pSeg->pDlidx ){
176622177522
fts5SegIterNextFrom(p, pSeg, iFrom);
176623177523
}else{
176624
- fts5SegIterNext(p, pSeg, &bNewTerm);
177524
+ pSeg->xNext(p, pSeg, &bNewTerm);
176625177525
}
176626177526
176627177527
if( pSeg->pLeaf==0 || bNewTerm
176628177528
|| fts5MultiIterAdvanceRowid(p, pIter, iFirst)
176629177529
){
@@ -176647,11 +177547,12 @@
176647177547
do {
176648177548
int iFirst = pIter->aFirst[1].iFirst;
176649177549
Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
176650177550
int bNewTerm = 0;
176651177551
176652
- fts5SegIterNext(p, pSeg, &bNewTerm);
177552
+ assert( p->rc==SQLITE_OK );
177553
+ pSeg->xNext(p, pSeg, &bNewTerm);
176653177554
if( pSeg->pLeaf==0 || bNewTerm
176654177555
|| fts5MultiIterAdvanceRowid(p, pIter, iFirst)
176655177556
){
176656177557
fts5MultiIterAdvanced(p, pIter, iFirst, 1);
176657177558
fts5MultiIterSetEof(pIter);
@@ -176767,11 +177668,12 @@
176767177668
** object and set the output variable to NULL. */
176768177669
if( p->rc==SQLITE_OK ){
176769177670
for(iIter=pNew->nSeg-1; iIter>0; iIter--){
176770177671
int iEq;
176771177672
if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){
176772
- fts5SegIterNext(p, &pNew->aSeg[iEq], 0);
177673
+ Fts5SegIter *pSeg = &pNew->aSeg[iEq];
177674
+ if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0);
176773177675
fts5MultiIterAdvanced(p, pNew, iEq, iIter);
176774177676
}
176775177677
}
176776177678
fts5MultiIterSetEof(pNew);
176777177679
fts5AssertMultiIterSetup(p, pNew);
@@ -176817,10 +177719,11 @@
176817177719
}
176818177720
pData = 0;
176819177721
}else{
176820177722
pNew->bEof = 1;
176821177723
}
177724
+ fts5SegIterSetNext(p, pIter);
176822177725
176823177726
*ppOut = pNew;
176824177727
}
176825177728
176826177729
fts5DataRelease(pData);
@@ -176885,10 +177788,13 @@
176885177788
Fts5Data *pData = 0;
176886177789
u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset];
176887177790
int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset);
176888177791
int pgno = pSeg->iLeafPgno;
176889177792
int pgnoSave = 0;
177793
+
177794
+ /* This function does notmwork with detail=none databases. */
177795
+ assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
176890177796
176891177797
if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
176892177798
pgnoSave = pgno+1;
176893177799
}
176894177800
@@ -177309,12 +178215,11 @@
177309178215
** Append a rowid and position-list size field to the writers output.
177310178216
*/
177311178217
static void fts5WriteAppendRowid(
177312178218
Fts5Index *p,
177313178219
Fts5SegWriter *pWriter,
177314
- i64 iRowid,
177315
- int nPos
178220
+ i64 iRowid
177316178221
){
177317178222
if( p->rc==SQLITE_OK ){
177318178223
Fts5PageWriter *pPage = &pWriter->writer;
177319178224
177320178225
if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){
@@ -177337,12 +178242,10 @@
177337178242
fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
177338178243
}
177339178244
pWriter->iPrevRowid = iRowid;
177340178245
pWriter->bFirstRowidInDoclist = 0;
177341178246
pWriter->bFirstRowidInPage = 0;
177342
-
177343
- fts5BufferAppendVarint(&p->rc, &pPage->buf, nPos);
177344178247
}
177345178248
}
177346178249
177347178250
static void fts5WriteAppendPoslistData(
177348178251
Fts5Index *p,
@@ -177534,10 +178437,11 @@
177534178437
int nInput; /* Number of input segments */
177535178438
Fts5SegWriter writer; /* Writer object */
177536178439
Fts5StructureSegment *pSeg; /* Output segment */
177537178440
Fts5Buffer term;
177538178441
int bOldest; /* True if the output segment is the oldest */
178442
+ int eDetail = p->pConfig->eDetail;
177539178443
177540178444
assert( iLvl<pStruct->nLevel );
177541178445
assert( pLvl->nMerge<=pLvl->nSeg );
177542178446
177543178447
memset(&writer, 0, sizeof(Fts5SegWriter));
@@ -177603,15 +178507,25 @@
177603178507
fts5BufferSet(&p->rc, &term, nTerm, pTerm);
177604178508
}
177605178509
177606178510
/* Append the rowid to the output */
177607178511
/* WRITEPOSLISTSIZE */
177608
- nPos = pSegIter->nPos*2 + pSegIter->bDel;
177609
- fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter), nPos);
178512
+ fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter));
177610178513
177611
- /* Append the position-list data to the output */
177612
- fts5ChunkIterate(p, pSegIter, (void*)&writer, fts5MergeChunkCallback);
178514
+ if( eDetail==FTS5_DETAIL_NONE ){
178515
+ if( pSegIter->bDel ){
178516
+ fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0);
178517
+ if( pSegIter->nPos>0 ){
178518
+ fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0);
178519
+ }
178520
+ }
178521
+ }else{
178522
+ /* Append the position-list data to the output */
178523
+ nPos = pSegIter->nPos*2 + pSegIter->bDel;
178524
+ fts5BufferAppendVarint(&p->rc, &writer.writer.buf, nPos);
178525
+ fts5ChunkIterate(p, pSegIter, (void*)&writer, fts5MergeChunkCallback);
178526
+ }
177613178527
}
177614178528
177615178529
/* Flush the last leaf page to disk. Set the output segment b-tree height
177616178530
** and last leaf page number at the same time. */
177617178531
fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
@@ -177795,11 +178709,11 @@
177795178709
pStruct = fts5StructureRead(p);
177796178710
iSegid = fts5AllocateSegid(p, pStruct);
177797178711
177798178712
if( iSegid ){
177799178713
const int pgsz = p->pConfig->pgsz;
177800
-
178714
+ int eDetail = p->pConfig->eDetail;
177801178715
Fts5StructureSegment *pSeg; /* New segment within pStruct */
177802178716
Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */
177803178717
Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */
177804178718
177805178719
Fts5SegWriter writer;
@@ -177838,16 +178752,11 @@
177838178752
177839178753
/* The entire doclist will not fit on this leaf. The following
177840178754
** loop iterates through the poslists that make up the current
177841178755
** doclist. */
177842178756
while( p->rc==SQLITE_OK && iOff<nDoclist ){
177843
- int nPos;
177844
- int nCopy;
177845
- int bDummy;
177846178757
iOff += fts5GetVarint(&pDoclist[iOff], (u64*)&iDelta);
177847
- nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy);
177848
- nCopy += nPos;
177849178758
iRowid += iDelta;
177850178759
177851178760
if( writer.bFirstRowidInPage ){
177852178761
fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */
177853178762
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
@@ -177856,38 +178765,56 @@
177856178765
}else{
177857178766
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
177858178767
}
177859178768
assert( pBuf->n<=pBuf->nSpace );
177860178769
177861
- if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){
177862
- /* The entire poslist will fit on the current leaf. So copy
177863
- ** it in one go. */
177864
- fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy);
177865
- }else{
177866
- /* The entire poslist will not fit on this leaf. So it needs
177867
- ** to be broken into sections. The only qualification being
177868
- ** that each varint must be stored contiguously. */
177869
- const u8 *pPoslist = &pDoclist[iOff];
177870
- int iPos = 0;
177871
- while( p->rc==SQLITE_OK ){
177872
- int nSpace = pgsz - pBuf->n - pPgidx->n;
177873
- int n = 0;
177874
- if( (nCopy - iPos)<=nSpace ){
177875
- n = nCopy - iPos;
177876
- }else{
177877
- n = fts5PoslistPrefix(&pPoslist[iPos], nSpace);
177878
- }
177879
- assert( n>0 );
177880
- fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n);
177881
- iPos += n;
177882
- if( (pBuf->n + pPgidx->n)>=pgsz ){
177883
- fts5WriteFlushLeaf(p, &writer);
177884
- }
177885
- if( iPos>=nCopy ) break;
177886
- }
177887
- }
177888
- iOff += nCopy;
178770
+ if( eDetail==FTS5_DETAIL_NONE ){
178771
+ if( iOff<nDoclist && pDoclist[iOff]==0 ){
178772
+ pBuf->p[pBuf->n++] = 0;
178773
+ iOff++;
178774
+ if( iOff<nDoclist && pDoclist[iOff]==0 ){
178775
+ pBuf->p[pBuf->n++] = 0;
178776
+ iOff++;
178777
+ }
178778
+ }
178779
+ if( (pBuf->n + pPgidx->n)>=pgsz ){
178780
+ fts5WriteFlushLeaf(p, &writer);
178781
+ }
178782
+ }else{
178783
+ int bDummy;
178784
+ int nPos;
178785
+ int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy);
178786
+ nCopy += nPos;
178787
+ if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){
178788
+ /* The entire poslist will fit on the current leaf. So copy
178789
+ ** it in one go. */
178790
+ fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy);
178791
+ }else{
178792
+ /* The entire poslist will not fit on this leaf. So it needs
178793
+ ** to be broken into sections. The only qualification being
178794
+ ** that each varint must be stored contiguously. */
178795
+ const u8 *pPoslist = &pDoclist[iOff];
178796
+ int iPos = 0;
178797
+ while( p->rc==SQLITE_OK ){
178798
+ int nSpace = pgsz - pBuf->n - pPgidx->n;
178799
+ int n = 0;
178800
+ if( (nCopy - iPos)<=nSpace ){
178801
+ n = nCopy - iPos;
178802
+ }else{
178803
+ n = fts5PoslistPrefix(&pPoslist[iPos], nSpace);
178804
+ }
178805
+ assert( n>0 );
178806
+ fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n);
178807
+ iPos += n;
178808
+ if( (pBuf->n + pPgidx->n)>=pgsz ){
178809
+ fts5WriteFlushLeaf(p, &writer);
178810
+ }
178811
+ if( iPos>=nCopy ) break;
178812
+ }
178813
+ }
178814
+ iOff += nCopy;
178815
+ }
177889178816
}
177890178817
}
177891178818
177892178819
/* TODO2: Doclist terminator written here. */
177893178820
/* pBuf->p[pBuf->n++] = '\0'; */
@@ -178018,10 +178945,18 @@
178018178945
Fts5Buffer *pBuf; /* Append to this buffer */
178019178946
Fts5Colset *pColset; /* Restrict matches to this column */
178020178947
int eState; /* See above */
178021178948
};
178022178949
178950
+typedef struct PoslistOffsetsCtx PoslistOffsetsCtx;
178951
+struct PoslistOffsetsCtx {
178952
+ Fts5Buffer *pBuf; /* Append to this buffer */
178953
+ Fts5Colset *pColset; /* Restrict matches to this column */
178954
+ int iRead;
178955
+ int iWrite;
178956
+};
178957
+
178023178958
/*
178024178959
** TODO: Make this more efficient!
178025178960
*/
178026178961
static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
178027178962
int i;
@@ -178028,10 +178963,32 @@
178028178963
for(i=0; i<pColset->nCol; i++){
178029178964
if( pColset->aiCol[i]==iCol ) return 1;
178030178965
}
178031178966
return 0;
178032178967
}
178968
+
178969
+static void fts5PoslistOffsetsCallback(
178970
+ Fts5Index *p,
178971
+ void *pContext,
178972
+ const u8 *pChunk, int nChunk
178973
+){
178974
+ PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext;
178975
+ assert_nc( nChunk>=0 );
178976
+ if( nChunk>0 ){
178977
+ int i = 0;
178978
+ while( i<nChunk ){
178979
+ int iVal;
178980
+ i += fts5GetVarint32(&pChunk[i], iVal);
178981
+ iVal += pCtx->iRead - 2;
178982
+ pCtx->iRead = iVal;
178983
+ if( fts5IndexColsetTest(pCtx->pColset, iVal) ){
178984
+ fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite);
178985
+ pCtx->iWrite = iVal;
178986
+ }
178987
+ }
178988
+ }
178989
+}
178033178990
178034178991
static void fts5PoslistFilterCallback(
178035178992
Fts5Index *p,
178036178993
void *pContext,
178037178994
const u8 *pChunk, int nChunk
@@ -178096,16 +179053,24 @@
178096179053
){
178097179054
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
178098179055
if( pColset==0 ){
178099179056
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
178100179057
}else{
178101
- PoslistCallbackCtx sCtx;
178102
- sCtx.pBuf = pBuf;
178103
- sCtx.pColset = pColset;
178104
- sCtx.eState = fts5IndexColsetTest(pColset, 0);
178105
- assert( sCtx.eState==0 || sCtx.eState==1 );
178106
- fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
179058
+ if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
179059
+ PoslistCallbackCtx sCtx;
179060
+ sCtx.pBuf = pBuf;
179061
+ sCtx.pColset = pColset;
179062
+ sCtx.eState = fts5IndexColsetTest(pColset, 0);
179063
+ assert( sCtx.eState==0 || sCtx.eState==1 );
179064
+ fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
179065
+ }else{
179066
+ PoslistOffsetsCtx sCtx;
179067
+ memset(&sCtx, 0, sizeof(sCtx));
179068
+ sCtx.pBuf = pBuf;
179069
+ sCtx.pColset = pColset;
179070
+ fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback);
179071
+ }
178107179072
}
178108179073
}
178109179074
}
178110179075
178111179076
/*
@@ -178144,10 +179109,20 @@
178144179109
prev = *p++;
178145179110
}
178146179111
return p - (*pa);
178147179112
}
178148179113
179114
+static int fts5AppendRowid(
179115
+ Fts5Index *p,
179116
+ i64 iDelta,
179117
+ Fts5IndexIter *pMulti,
179118
+ Fts5Colset *pColset,
179119
+ Fts5Buffer *pBuf
179120
+){
179121
+ fts5BufferAppendVarint(&p->rc, pBuf, iDelta);
179122
+ return 0;
179123
+}
178149179124
178150179125
/*
178151179126
** Iterator pMulti currently points to a valid entry (not EOF). This
178152179127
** function appends the following to buffer pBuf:
178153179128
**
@@ -178171,12 +179146,12 @@
178171179146
if( p->rc==SQLITE_OK ){
178172179147
Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ];
178173179148
assert( fts5MultiIterEof(p, pMulti)==0 );
178174179149
assert( pSeg->nPos>0 );
178175179150
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){
178176
-
178177
- if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
179151
+ if( p->pConfig->eDetail==FTS5_DETAIL_FULL
179152
+ && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
178178179153
&& (pColset==0 || pColset->nCol==1)
178179179154
){
178180179155
const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
178181179156
int nPos;
178182179157
if( pColset ){
@@ -178217,16 +179192,16 @@
178217179192
sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2);
178218179193
}
178219179194
}
178220179195
}
178221179196
}
178222
-
178223179197
}
178224179198
}
178225179199
178226179200
return 0;
178227179201
}
179202
+
178228179203
178229179204
static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
178230179205
u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
178231179206
178232179207
assert( pIter->aPoslist );
@@ -178283,10 +179258,73 @@
178283179258
#define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \
178284179259
assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \
178285179260
fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
178286179261
(iLastRowid) = (iRowid); \
178287179262
}
179263
+
179264
+/*
179265
+** Swap the contents of buffer *p1 with that of *p2.
179266
+*/
179267
+static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){
179268
+ Fts5Buffer tmp = *p1;
179269
+ *p1 = *p2;
179270
+ *p2 = tmp;
179271
+}
179272
+
179273
+static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){
179274
+ int i = *piOff;
179275
+ if( i>=pBuf->n ){
179276
+ *piOff = -1;
179277
+ }else{
179278
+ u64 iVal;
179279
+ *piOff = i + sqlite3Fts5GetVarint(&pBuf->p[i], &iVal);
179280
+ *piRowid += iVal;
179281
+ }
179282
+}
179283
+
179284
+/*
179285
+** This is the equivalent of fts5MergePrefixLists() for detail=none mode.
179286
+** In this case the buffers consist of a delta-encoded list of rowids only.
179287
+*/
179288
+static void fts5MergeRowidLists(
179289
+ Fts5Index *p, /* FTS5 backend object */
179290
+ Fts5Buffer *p1, /* First list to merge */
179291
+ Fts5Buffer *p2 /* Second list to merge */
179292
+){
179293
+ int i1 = 0;
179294
+ int i2 = 0;
179295
+ i64 iRowid1 = 0;
179296
+ i64 iRowid2 = 0;
179297
+ i64 iOut = 0;
179298
+
179299
+ Fts5Buffer out;
179300
+ memset(&out, 0, sizeof(out));
179301
+ sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
179302
+ if( p->rc ) return;
179303
+
179304
+ fts5NextRowid(p1, &i1, &iRowid1);
179305
+ fts5NextRowid(p2, &i2, &iRowid2);
179306
+ while( i1>=0 || i2>=0 ){
179307
+ if( i1>=0 && (i2<0 || iRowid1<iRowid2) ){
179308
+ assert( iOut==0 || iRowid1>iOut );
179309
+ fts5BufferSafeAppendVarint(&out, iRowid1 - iOut);
179310
+ iOut = iRowid1;
179311
+ fts5NextRowid(p1, &i1, &iRowid1);
179312
+ }else{
179313
+ assert( iOut==0 || iRowid2>iOut );
179314
+ fts5BufferSafeAppendVarint(&out, iRowid2 - iOut);
179315
+ iOut = iRowid2;
179316
+ if( i1>=0 && iRowid1==iRowid2 ){
179317
+ fts5NextRowid(p1, &i1, &iRowid1);
179318
+ }
179319
+ fts5NextRowid(p2, &i2, &iRowid2);
179320
+ }
179321
+ }
179322
+
179323
+ fts5BufferSwap(&out, p1);
179324
+ fts5BufferFree(&out);
179325
+}
178288179326
178289179327
/*
178290179328
** Buffers p1 and p2 contain doclists. This function merges the content
178291179329
** of the two doclists together and sets buffer p1 to the result before
178292179330
** returning.
@@ -178352,11 +179390,13 @@
178352179390
sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
178353179391
if( iPos1==iPos2 ){
178354179392
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1);
178355179393
}
178356179394
}
178357
- p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew);
179395
+ if( iNew!=writer.iPrev || tmp.n==0 ){
179396
+ p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew);
179397
+ }
178358179398
}
178359179399
178360179400
/* WRITEPOSLISTSIZE */
178361179401
fts5BufferSafeAppendVarint(&out, tmp.n * 2);
178362179402
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
@@ -178369,16 +179409,10 @@
178369179409
fts5BufferFree(&tmp);
178370179410
fts5BufferFree(&out);
178371179411
}
178372179412
}
178373179413
178374
-static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){
178375
- Fts5Buffer tmp = *p1;
178376
- *p1 = *p2;
178377
- *p2 = tmp;
178378
-}
178379
-
178380179414
static void fts5SetupPrefixIter(
178381179415
Fts5Index *p, /* Index to read from */
178382179416
int bDesc, /* True for "ORDER BY rowid DESC" */
178383179417
const u8 *pToken, /* Buffer containing prefix to match */
178384179418
int nToken, /* Size of buffer pToken in bytes */
@@ -178386,10 +179420,20 @@
178386179420
Fts5IndexIter **ppIter /* OUT: New iterator */
178387179421
){
178388179422
Fts5Structure *pStruct;
178389179423
Fts5Buffer *aBuf;
178390179424
const int nBuf = 32;
179425
+
179426
+ void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
179427
+ int (*xAppend)(Fts5Index*, i64, Fts5IndexIter*, Fts5Colset*, Fts5Buffer*);
179428
+ if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
179429
+ xMerge = fts5MergeRowidLists;
179430
+ xAppend = fts5AppendRowid;
179431
+ }else{
179432
+ xMerge = fts5MergePrefixLists;
179433
+ xAppend = fts5AppendPoslist;
179434
+ }
178391179435
178392179436
aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
178393179437
pStruct = fts5StructureRead(p);
178394179438
178395179439
if( aBuf && pStruct ){
@@ -178419,25 +179463,25 @@
178419179463
assert( i<nBuf );
178420179464
if( aBuf[i].n==0 ){
178421179465
fts5BufferSwap(&doclist, &aBuf[i]);
178422179466
fts5BufferZero(&doclist);
178423179467
}else{
178424
- fts5MergePrefixLists(p, &doclist, &aBuf[i]);
179468
+ xMerge(p, &doclist, &aBuf[i]);
178425179469
fts5BufferZero(&aBuf[i]);
178426179470
}
178427179471
}
178428179472
iLastRowid = 0;
178429179473
}
178430179474
178431
- if( !fts5AppendPoslist(p, iRowid-iLastRowid, p1, pColset, &doclist) ){
179475
+ if( !xAppend(p, iRowid-iLastRowid, p1, pColset, &doclist) ){
178432179476
iLastRowid = iRowid;
178433179477
}
178434179478
}
178435179479
178436179480
for(i=0; i<nBuf; i++){
178437179481
if( p->rc==SQLITE_OK ){
178438
- fts5MergePrefixLists(p, &doclist, &aBuf[i]);
179482
+ xMerge(p, &doclist, &aBuf[i]);
178439179483
}
178440179484
fts5BufferFree(&aBuf[i]);
178441179485
}
178442179486
fts5MultiIterFree(p, p1);
178443179487
@@ -178463,11 +179507,11 @@
178463179507
static int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
178464179508
assert( p->rc==SQLITE_OK );
178465179509
178466179510
/* Allocate the hash table if it has not already been allocated */
178467179511
if( p->pHash==0 ){
178468
- p->rc = sqlite3Fts5HashNew(&p->pHash, &p->nPendingData);
179512
+ p->rc = sqlite3Fts5HashNew(p->pConfig, &p->pHash, &p->nPendingData);
178469179513
}
178470179514
178471179515
/* Flush the hash table to disk if required */
178472179516
if( iRowid<p->iWriteRowid
178473179517
|| (iRowid==p->iWriteRowid && p->bDelete==0)
@@ -178584,11 +179628,15 @@
178584179628
/*
178585179629
** Argument p points to a buffer containing utf-8 text that is n bytes in
178586179630
** size. Return the number of bytes in the nChar character prefix of the
178587179631
** buffer, or 0 if there are less than nChar characters in total.
178588179632
*/
178589
-static int fts5IndexCharlenToBytelen(const char *p, int nByte, int nChar){
179633
+static int sqlite3Fts5IndexCharlenToBytelen(
179634
+ const char *p,
179635
+ int nByte,
179636
+ int nChar
179637
+){
178590179638
int n = 0;
178591179639
int i;
178592179640
for(i=0; i<nChar; i++){
178593179641
if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
178594179642
if( (unsigned char)p[n++]>=0xc0 ){
@@ -178641,11 +179689,12 @@
178641179689
rc = sqlite3Fts5HashWrite(
178642179690
p->pHash, p->iWriteRowid, iCol, iPos, FTS5_MAIN_PREFIX, pToken, nToken
178643179691
);
178644179692
178645179693
for(i=0; i<pConfig->nPrefix && rc==SQLITE_OK; i++){
178646
- int nByte = fts5IndexCharlenToBytelen(pToken, nToken, pConfig->aPrefix[i]);
179694
+ const int nChar = pConfig->aPrefix[i];
179695
+ int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
178647179696
if( nByte ){
178648179697
rc = sqlite3Fts5HashWrite(p->pHash,
178649179698
p->iWriteRowid, iCol, iPos, (char)(FTS5_MAIN_PREFIX+i+1), pToken,
178650179699
nByte
178651179700
);
@@ -178819,13 +179868,20 @@
178819179868
const u8 **pp, /* OUT: Pointer to position-list data */
178820179869
int *pn, /* OUT: Size of position-list in bytes */
178821179870
i64 *piRowid /* OUT: Current rowid */
178822179871
){
178823179872
Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
179873
+ int eDetail = pIter->pIndex->pConfig->eDetail;
179874
+
178824179875
assert( pIter->pIndex->rc==SQLITE_OK );
178825179876
*piRowid = pSeg->iRowid;
178826
- if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
179877
+ if( eDetail==FTS5_DETAIL_NONE ){
179878
+ *pn = pSeg->nPos;
179879
+ }else
179880
+ if( eDetail==FTS5_DETAIL_FULL
179881
+ && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
179882
+ ){
178827179883
u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
178828179884
if( pColset==0 || pIter->bFiltered ){
178829179885
*pn = pSeg->nPos;
178830179886
*pp = pPos;
178831179887
}else if( pColset->nCol==1 ){
@@ -178838,15 +179894,28 @@
178838179894
*pn = pIter->poslist.n;
178839179895
}
178840179896
}else{
178841179897
fts5BufferZero(&pIter->poslist);
178842179898
fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
178843
- *pp = pIter->poslist.p;
179899
+ if( eDetail==FTS5_DETAIL_FULL ){
179900
+ *pp = pIter->poslist.p;
179901
+ }
178844179902
*pn = pIter->poslist.n;
178845179903
}
178846179904
return fts5IndexReturn(pIter->pIndex);
178847179905
}
179906
+
179907
+static int sqlite3Fts5IterCollist(
179908
+ Fts5IndexIter *pIter,
179909
+ const u8 **pp, /* OUT: Pointer to position-list data */
179910
+ int *pn /* OUT: Size of position-list in bytes */
179911
+){
179912
+ assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
179913
+ *pp = pIter->poslist.p;
179914
+ *pn = pIter->poslist.n;
179915
+ return SQLITE_OK;
179916
+}
178848179917
178849179918
/*
178850179919
** This function is similar to sqlite3Fts5IterPoslist(), except that it
178851179920
** copies the position list into the buffer supplied as the second
178852179921
** argument.
@@ -178957,11 +180026,11 @@
178957180026
*/
178958180027
178959180028
/*
178960180029
** Return a simple checksum value based on the arguments.
178961180030
*/
178962
-static u64 fts5IndexEntryCksum(
180031
+static u64 sqlite3Fts5IndexEntryCksum(
178963180032
i64 iRowid,
178964180033
int iCol,
178965180034
int iPos,
178966180035
int iIdx,
178967180036
const char *pTerm,
@@ -179027,34 +180096,41 @@
179027180096
const char *z, /* Index key to query for */
179028180097
int n, /* Size of index key in bytes */
179029180098
int flags, /* Flags for Fts5IndexQuery */
179030180099
u64 *pCksum /* IN/OUT: Checksum value */
179031180100
){
180101
+ int eDetail = p->pConfig->eDetail;
179032180102
u64 cksum = *pCksum;
179033180103
Fts5IndexIter *pIdxIter = 0;
180104
+ Fts5Buffer buf = {0, 0, 0};
179034180105
int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter);
179035180106
179036180107
while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){
179037
- i64 dummy;
179038
- const u8 *pPos;
179039
- int nPos;
179040180108
i64 rowid = sqlite3Fts5IterRowid(pIdxIter);
179041
- rc = sqlite3Fts5IterPoslist(pIdxIter, 0, &pPos, &nPos, &dummy);
180109
+
180110
+ if( eDetail==FTS5_DETAIL_NONE ){
180111
+ cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
180112
+ }else{
180113
+ rc = sqlite3Fts5IterPoslistBuffer(pIdxIter, &buf);
180114
+ if( rc==SQLITE_OK ){
180115
+ Fts5PoslistReader sReader;
180116
+ for(sqlite3Fts5PoslistReaderInit(buf.p, buf.n, &sReader);
180117
+ sReader.bEof==0;
180118
+ sqlite3Fts5PoslistReaderNext(&sReader)
180119
+ ){
180120
+ int iCol = FTS5_POS2COLUMN(sReader.iPos);
180121
+ int iOff = FTS5_POS2OFFSET(sReader.iPos);
180122
+ cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n);
180123
+ }
180124
+ }
180125
+ }
179042180126
if( rc==SQLITE_OK ){
179043
- Fts5PoslistReader sReader;
179044
- for(sqlite3Fts5PoslistReaderInit(pPos, nPos, &sReader);
179045
- sReader.bEof==0;
179046
- sqlite3Fts5PoslistReaderNext(&sReader)
179047
- ){
179048
- int iCol = FTS5_POS2COLUMN(sReader.iPos);
179049
- int iOff = FTS5_POS2OFFSET(sReader.iPos);
179050
- cksum ^= fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n);
179051
- }
179052180127
rc = sqlite3Fts5IterNext(pIdxIter);
179053180128
}
179054180129
}
179055180130
sqlite3Fts5IterClose(pIdxIter);
180131
+ fts5BufferFree(&buf);
179056180132
179057180133
*pCksum = cksum;
179058180134
return rc;
179059180135
}
179060180136
@@ -179344,18 +180420,19 @@
179344180420
179345180421
179346180422
/*
179347180423
** Run internal checks to ensure that the FTS index (a) is internally
179348180424
** consistent and (b) contains entries for which the XOR of the checksums
179349
-** as calculated by fts5IndexEntryCksum() is cksum.
180425
+** as calculated by sqlite3Fts5IndexEntryCksum() is cksum.
179350180426
**
179351180427
** Return SQLITE_CORRUPT if any of the internal checks fail, or if the
179352180428
** checksum does not match. Return SQLITE_OK if all checks pass without
179353180429
** error, or some other SQLite error code if another error (e.g. OOM)
179354180430
** occurs.
179355180431
*/
179356180432
static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
180433
+ int eDetail = p->pConfig->eDetail;
179357180434
u64 cksum2 = 0; /* Checksum based on contents of indexes */
179358180435
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
179359180436
Fts5IndexIter *pIter; /* Used to iterate through entire index */
179360180437
Fts5Structure *pStruct; /* Index structure */
179361180438
@@ -179403,16 +180480,22 @@
179403180480
char *z = (char*)fts5MultiIterTerm(pIter, &n);
179404180481
179405180482
/* If this is a new term, query for it. Update cksum3 with the results. */
179406180483
fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
179407180484
179408
- poslist.n = 0;
179409
- fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst] , 0, &poslist);
179410
- while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
179411
- int iCol = FTS5_POS2COLUMN(iPos);
179412
- int iTokOff = FTS5_POS2OFFSET(iPos);
179413
- cksum2 ^= fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n);
180485
+ if( eDetail==FTS5_DETAIL_NONE ){
180486
+ if( 0==fts5MultiIterIsEmpty(p, pIter) ){
180487
+ cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, 0, 0, -1, z, n);
180488
+ }
180489
+ }else{
180490
+ poslist.n = 0;
180491
+ fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist);
180492
+ while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
180493
+ int iCol = FTS5_POS2COLUMN(iPos);
180494
+ int iTokOff = FTS5_POS2OFFSET(iPos);
180495
+ cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n);
180496
+ }
179414180497
}
179415180498
}
179416180499
fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
179417180500
179418180501
fts5MultiIterFree(p, pIter);
@@ -179424,38 +180507,10 @@
179424180507
#endif
179425180508
fts5BufferFree(&poslist);
179426180509
return fts5IndexReturn(p);
179427180510
}
179428180511
179429
-
179430
-/*
179431
-** Calculate and return a checksum that is the XOR of the index entry
179432
-** checksum of all entries that would be generated by the token specified
179433
-** by the final 5 arguments.
179434
-*/
179435
-static u64 sqlite3Fts5IndexCksum(
179436
- Fts5Config *pConfig, /* Configuration object */
179437
- i64 iRowid, /* Document term appears in */
179438
- int iCol, /* Column term appears in */
179439
- int iPos, /* Position term appears in */
179440
- const char *pTerm, int nTerm /* Term at iPos */
179441
-){
179442
- u64 ret = 0; /* Return value */
179443
- int iIdx; /* For iterating through indexes */
179444
-
179445
- ret = fts5IndexEntryCksum(iRowid, iCol, iPos, 0, pTerm, nTerm);
179446
-
179447
- for(iIdx=0; iIdx<pConfig->nPrefix; iIdx++){
179448
- int nByte = fts5IndexCharlenToBytelen(pTerm, nTerm, pConfig->aPrefix[iIdx]);
179449
- if( nByte ){
179450
- ret ^= fts5IndexEntryCksum(iRowid, iCol, iPos, iIdx+1, pTerm, nByte);
179451
- }
179452
- }
179453
-
179454
- return ret;
179455
-}
179456
-
179457180512
/*************************************************************************
179458180513
**************************************************************************
179459180514
** Below this point is the implementation of the fts5_decode() scalar
179460180515
** function only.
179461180516
*/
@@ -180039,10 +181094,11 @@
180039181094
#define FTS5CSR_REQUIRE_DOCSIZE 0x02
180040181095
#define FTS5CSR_REQUIRE_INST 0x04
180041181096
#define FTS5CSR_EOF 0x08
180042181097
#define FTS5CSR_FREE_ZRANK 0x10
180043181098
#define FTS5CSR_REQUIRE_RESEEK 0x20
181099
+#define FTS5CSR_REQUIRE_POSLIST 0x40
180044181100
180045181101
#define BitFlagAllTest(x,y) (((x) & (y))==(y))
180046181102
#define BitFlagTest(x,y) (((x) & (y))!=0)
180047181103
180048181104
@@ -180452,10 +181508,11 @@
180452181508
static void fts5CsrNewrow(Fts5Cursor *pCsr){
180453181509
CsrFlagSet(pCsr,
180454181510
FTS5CSR_REQUIRE_CONTENT
180455181511
| FTS5CSR_REQUIRE_DOCSIZE
180456181512
| FTS5CSR_REQUIRE_INST
181513
+ | FTS5CSR_REQUIRE_POSLIST
180457181514
);
180458181515
}
180459181516
180460181517
static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
180461181518
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
@@ -180534,19 +181591,22 @@
180534181591
180535181592
pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
180536181593
nBlob = sqlite3_column_bytes(pSorter->pStmt, 1);
180537181594
aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1);
180538181595
180539
- for(i=0; i<(pSorter->nIdx-1); i++){
180540
- int iVal;
180541
- a += fts5GetVarint32(a, iVal);
180542
- iOff += iVal;
180543
- pSorter->aIdx[i] = iOff;
180544
- }
180545
- pSorter->aIdx[i] = &aBlob[nBlob] - a;
180546
-
180547
- pSorter->aPoslist = a;
181596
+ /* nBlob==0 in detail=none mode. */
181597
+ if( nBlob>0 ){
181598
+ for(i=0; i<(pSorter->nIdx-1); i++){
181599
+ int iVal;
181600
+ a += fts5GetVarint32(a, iVal);
181601
+ iOff += iVal;
181602
+ pSorter->aIdx[i] = iOff;
181603
+ }
181604
+ pSorter->aIdx[i] = &aBlob[nBlob] - a;
181605
+ pSorter->aPoslist = a;
181606
+ }
181607
+
180548181608
fts5CsrNewrow(pCsr);
180549181609
}
180550181610
180551181611
return rc;
180552181612
}
@@ -180980,10 +182040,11 @@
180980182040
assert( pCsr->iLastRowid==LARGEST_INT64 );
180981182041
assert( pCsr->iFirstRowid==SMALLEST_INT64 );
180982182042
pCsr->ePlan = FTS5_PLAN_SOURCE;
180983182043
pCsr->pExpr = pTab->pSortCsr->pExpr;
180984182044
rc = fts5CursorFirst(pTab, pCsr, bDesc);
182045
+ sqlite3Fts5ExprClearEof(pCsr->pExpr);
180985182046
}else if( pMatch ){
180986182047
const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
180987182048
if( zExpr==0 ) zExpr = "";
180988182049
180989182050
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
@@ -181409,10 +182470,12 @@
181409182470
fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
181410182471
rc = sqlite3Fts5StorageRollback(pTab->pStorage);
181411182472
return rc;
181412182473
}
181413182474
182475
+static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);
182476
+
181414182477
static void *fts5ApiUserData(Fts5Context *pCtx){
181415182478
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
181416182479
return pCsr->pAux->pUserData;
181417182480
}
181418182481
@@ -181458,21 +182521,76 @@
181458182521
static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
181459182522
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
181460182523
return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
181461182524
}
181462182525
181463
-static int fts5CsrPoslist(Fts5Cursor *pCsr, int iPhrase, const u8 **pa){
181464
- int n;
181465
- if( pCsr->pSorter ){
182526
+static int fts5ApiColumnText(
182527
+ Fts5Context *pCtx,
182528
+ int iCol,
182529
+ const char **pz,
182530
+ int *pn
182531
+){
182532
+ int rc = SQLITE_OK;
182533
+ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182534
+ if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
182535
+ *pz = 0;
182536
+ *pn = 0;
182537
+ }else{
182538
+ rc = fts5SeekCursor(pCsr, 0);
182539
+ if( rc==SQLITE_OK ){
182540
+ *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
182541
+ *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
182542
+ }
182543
+ }
182544
+ return rc;
182545
+}
182546
+
182547
+static int fts5CsrPoslist(
182548
+ Fts5Cursor *pCsr,
182549
+ int iPhrase,
182550
+ const u8 **pa,
182551
+ int *pn
182552
+){
182553
+ Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
182554
+ int rc = SQLITE_OK;
182555
+ int bLive = (pCsr->pSorter==0);
182556
+
182557
+ if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
182558
+
182559
+ if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
182560
+ Fts5PoslistPopulator *aPopulator;
182561
+ int i;
182562
+ aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
182563
+ if( aPopulator==0 ) rc = SQLITE_NOMEM;
182564
+ for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
182565
+ int n; const char *z;
182566
+ rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n);
182567
+ if( rc==SQLITE_OK ){
182568
+ rc = sqlite3Fts5ExprPopulatePoslists(
182569
+ pConfig, pCsr->pExpr, aPopulator, i, z, n
182570
+ );
182571
+ }
182572
+ }
182573
+ sqlite3_free(aPopulator);
182574
+
182575
+ if( pCsr->pSorter ){
182576
+ sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
182577
+ }
182578
+ }
182579
+ CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
182580
+ }
182581
+
182582
+ if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
181466182583
Fts5Sorter *pSorter = pCsr->pSorter;
181467182584
int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
181468
- n = pSorter->aIdx[iPhrase] - i1;
182585
+ *pn = pSorter->aIdx[iPhrase] - i1;
181469182586
*pa = &pSorter->aPoslist[i1];
181470182587
}else{
181471
- n = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
182588
+ *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
181472182589
}
181473
- return n;
182590
+
182591
+ return rc;
181474182592
}
181475182593
181476182594
/*
181477182595
** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
181478182596
** correctly for the current view. Return SQLITE_OK if successful, or an
@@ -181493,47 +182611,50 @@
181493182611
if( aIter ){
181494182612
int nInst = 0; /* Number instances seen so far */
181495182613
int i;
181496182614
181497182615
/* Initialize all iterators */
181498
- for(i=0; i<nIter; i++){
182616
+ for(i=0; i<nIter && rc==SQLITE_OK; i++){
181499182617
const u8 *a;
181500
- int n = fts5CsrPoslist(pCsr, i, &a);
182618
+ int n;
182619
+ rc = fts5CsrPoslist(pCsr, i, &a, &n);
181501182620
sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
181502182621
}
181503182622
181504
- while( 1 ){
181505
- int *aInst;
181506
- int iBest = -1;
181507
- for(i=0; i<nIter; i++){
181508
- if( (aIter[i].bEof==0)
181509
- && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos)
181510
- ){
181511
- iBest = i;
181512
- }
181513
- }
181514
- if( iBest<0 ) break;
181515
-
181516
- nInst++;
181517
- if( nInst>=pCsr->nInstAlloc ){
181518
- pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
181519
- aInst = (int*)sqlite3_realloc(
181520
- pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
181521
- );
181522
- if( aInst ){
181523
- pCsr->aInst = aInst;
181524
- }else{
181525
- rc = SQLITE_NOMEM;
181526
- break;
181527
- }
181528
- }
181529
-
181530
- aInst = &pCsr->aInst[3 * (nInst-1)];
181531
- aInst[0] = iBest;
181532
- aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
181533
- aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
181534
- sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
182623
+ if( rc==SQLITE_OK ){
182624
+ while( 1 ){
182625
+ int *aInst;
182626
+ int iBest = -1;
182627
+ for(i=0; i<nIter; i++){
182628
+ if( (aIter[i].bEof==0)
182629
+ && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos)
182630
+ ){
182631
+ iBest = i;
182632
+ }
182633
+ }
182634
+ if( iBest<0 ) break;
182635
+
182636
+ nInst++;
182637
+ if( nInst>=pCsr->nInstAlloc ){
182638
+ pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
182639
+ aInst = (int*)sqlite3_realloc(
182640
+ pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
182641
+ );
182642
+ if( aInst ){
182643
+ pCsr->aInst = aInst;
182644
+ }else{
182645
+ rc = SQLITE_NOMEM;
182646
+ break;
182647
+ }
182648
+ }
182649
+
182650
+ aInst = &pCsr->aInst[3 * (nInst-1)];
182651
+ aInst[0] = iBest;
182652
+ aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
182653
+ aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
182654
+ sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
182655
+ }
181535182656
}
181536182657
181537182658
pCsr->nInstCount = nInst;
181538182659
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
181539182660
}
@@ -181562,10 +182683,16 @@
181562182683
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
181563182684
|| SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
181564182685
){
181565182686
if( iIdx<0 || iIdx>=pCsr->nInstCount ){
181566182687
rc = SQLITE_RANGE;
182688
+#if 0
182689
+ }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){
182690
+ *piPhrase = pCsr->aInst[iIdx*3];
182691
+ *piCol = pCsr->aInst[iIdx*3 + 2];
182692
+ *piOff = -1;
182693
+#endif
181567182694
}else{
181568182695
*piPhrase = pCsr->aInst[iIdx*3];
181569182696
*piCol = pCsr->aInst[iIdx*3 + 1];
181570182697
*piOff = pCsr->aInst[iIdx*3 + 2];
181571182698
}
@@ -181575,31 +182702,10 @@
181575182702
181576182703
static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){
181577182704
return fts5CursorRowid((Fts5Cursor*)pCtx);
181578182705
}
181579182706
181580
-static int fts5ApiColumnText(
181581
- Fts5Context *pCtx,
181582
- int iCol,
181583
- const char **pz,
181584
- int *pn
181585
-){
181586
- int rc = SQLITE_OK;
181587
- Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
181588
- if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
181589
- *pz = 0;
181590
- *pn = 0;
181591
- }else{
181592
- rc = fts5SeekCursor(pCsr, 0);
181593
- if( rc==SQLITE_OK ){
181594
- *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
181595
- *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
181596
- }
181597
- }
181598
- return rc;
181599
-}
181600
-
181601182707
static int fts5ColumnSizeCb(
181602182708
void *pContext, /* Pointer to int */
181603182709
int tflags,
181604182710
const char *pToken, /* Buffer containing token */
181605182711
int nToken, /* Size of token in bytes */
@@ -181740,23 +182846,94 @@
181740182846
}
181741182847
*piOff += (iVal-2);
181742182848
}
181743182849
}
181744182850
181745
-static void fts5ApiPhraseFirst(
182851
+static int fts5ApiPhraseFirst(
181746182852
Fts5Context *pCtx,
181747182853
int iPhrase,
181748182854
Fts5PhraseIter *pIter,
181749182855
int *piCol, int *piOff
181750182856
){
181751182857
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
181752
- int n = fts5CsrPoslist(pCsr, iPhrase, &pIter->a);
181753
- pIter->b = &pIter->a[n];
181754
- *piCol = 0;
181755
- *piOff = 0;
181756
- fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
182858
+ int n;
182859
+ int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
182860
+ if( rc==SQLITE_OK ){
182861
+ pIter->b = &pIter->a[n];
182862
+ *piCol = 0;
182863
+ *piOff = 0;
182864
+ fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
182865
+ }
182866
+ return rc;
181757182867
}
182868
+
182869
+static void fts5ApiPhraseNextColumn(
182870
+ Fts5Context *pCtx,
182871
+ Fts5PhraseIter *pIter,
182872
+ int *piCol
182873
+){
182874
+ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182875
+ Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
182876
+
182877
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
182878
+ if( pIter->a>=pIter->b ){
182879
+ *piCol = -1;
182880
+ }else{
182881
+ int iIncr;
182882
+ pIter->a += fts5GetVarint32(&pIter->a[0], iIncr);
182883
+ *piCol += (iIncr-2);
182884
+ }
182885
+ }else{
182886
+ while( 1 ){
182887
+ int dummy;
182888
+ if( pIter->a>=pIter->b ){
182889
+ *piCol = -1;
182890
+ return;
182891
+ }
182892
+ if( pIter->a[0]==0x01 ) break;
182893
+ pIter->a += fts5GetVarint32(pIter->a, dummy);
182894
+ }
182895
+ pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
182896
+ }
182897
+}
182898
+
182899
+static int fts5ApiPhraseFirstColumn(
182900
+ Fts5Context *pCtx,
182901
+ int iPhrase,
182902
+ Fts5PhraseIter *pIter,
182903
+ int *piCol
182904
+){
182905
+ int rc = SQLITE_OK;
182906
+ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182907
+ Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
182908
+
182909
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
182910
+ int n;
182911
+ rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
182912
+ if( rc==SQLITE_OK ){
182913
+ pIter->b = &pIter->a[n];
182914
+ *piCol = 0;
182915
+ fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
182916
+ }
182917
+ }else{
182918
+ int n;
182919
+ rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
182920
+ if( rc==SQLITE_OK ){
182921
+ pIter->b = &pIter->a[n];
182922
+ if( n<=0 ){
182923
+ *piCol = -1;
182924
+ }else if( pIter->a[0]==0x01 ){
182925
+ pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
182926
+ }else{
182927
+ *piCol = 0;
182928
+ }
182929
+ }
182930
+ }
182931
+
182932
+ return rc;
182933
+}
182934
+
181758182935
181759182936
static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
181760182937
int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
181761182938
);
181762182939
@@ -181777,12 +182954,13 @@
181777182954
fts5ApiQueryPhrase,
181778182955
fts5ApiSetAuxdata,
181779182956
fts5ApiGetAuxdata,
181780182957
fts5ApiPhraseFirst,
181781182958
fts5ApiPhraseNext,
182959
+ fts5ApiPhraseFirstColumn,
182960
+ fts5ApiPhraseNextColumn,
181782182961
};
181783
-
181784182962
181785182963
/*
181786182964
** Implementation of API function xQueryPhrase().
181787182965
*/
181788182966
static int fts5ApiQueryPhrase(
@@ -181911,24 +183089,50 @@
181911183089
int rc = SQLITE_OK;
181912183090
int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
181913183091
Fts5Buffer val;
181914183092
181915183093
memset(&val, 0, sizeof(Fts5Buffer));
181916
-
181917
- /* Append the varints */
181918
- for(i=0; i<(nPhrase-1); i++){
181919
- const u8 *dummy;
181920
- int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
181921
- sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
181922
- }
181923
-
181924
- /* Append the position lists */
181925
- for(i=0; i<nPhrase; i++){
181926
- const u8 *pPoslist;
181927
- int nPoslist;
181928
- nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
181929
- sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
183094
+ switch( ((Fts5Table*)(pCsr->base.pVtab))->pConfig->eDetail ){
183095
+ case FTS5_DETAIL_FULL:
183096
+
183097
+ /* Append the varints */
183098
+ for(i=0; i<(nPhrase-1); i++){
183099
+ const u8 *dummy;
183100
+ int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
183101
+ sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
183102
+ }
183103
+
183104
+ /* Append the position lists */
183105
+ for(i=0; i<nPhrase; i++){
183106
+ const u8 *pPoslist;
183107
+ int nPoslist;
183108
+ nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
183109
+ sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
183110
+ }
183111
+ break;
183112
+
183113
+ case FTS5_DETAIL_COLUMNS:
183114
+
183115
+ /* Append the varints */
183116
+ for(i=0; rc==SQLITE_OK && i<(nPhrase-1); i++){
183117
+ const u8 *dummy;
183118
+ int nByte;
183119
+ rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &dummy, &nByte);
183120
+ sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
183121
+ }
183122
+
183123
+ /* Append the position lists */
183124
+ for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
183125
+ const u8 *pPoslist;
183126
+ int nPoslist;
183127
+ rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &pPoslist, &nPoslist);
183128
+ sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
183129
+ }
183130
+ break;
183131
+
183132
+ default:
183133
+ break;
181930183134
}
181931183135
181932183136
sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
181933183137
return rc;
181934183138
}
@@ -182247,11 +183451,11 @@
182247183451
sqlite3_context *pCtx, /* Function call context */
182248183452
int nArg, /* Number of args */
182249183453
sqlite3_value **apVal /* Function arguments */
182250183454
){
182251183455
assert( nArg==0 );
182252
- sqlite3_result_text(pCtx, "fts5: 2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566", -1, SQLITE_TRANSIENT);
183456
+ sqlite3_result_text(pCtx, "fts5: 2016-01-14 14:19:50 d17bc2c92f4d086280e49a3cc72993be7fee2da7", -1, SQLITE_TRANSIENT);
182253183457
}
182254183458
182255183459
static int fts5Init(sqlite3 *db){
182256183460
static const sqlite3_module fts5Mod = {
182257183461
/* iVersion */ 2,
@@ -183179,32 +184383,77 @@
183179184383
struct Fts5IntegrityCtx {
183180184384
i64 iRowid;
183181184385
int iCol;
183182184386
int szCol;
183183184387
u64 cksum;
184388
+ Fts5Termset *pTermset;
183184184389
Fts5Config *pConfig;
183185184390
};
184391
+
183186184392
183187184393
/*
183188184394
** Tokenization callback used by integrity check.
183189184395
*/
183190184396
static int fts5StorageIntegrityCallback(
183191
- void *pContext, /* Pointer to Fts5InsertCtx object */
184397
+ void *pContext, /* Pointer to Fts5IntegrityCtx object */
183192184398
int tflags,
183193184399
const char *pToken, /* Buffer containing token */
183194184400
int nToken, /* Size of token in bytes */
183195184401
int iStart, /* Start offset of token */
183196184402
int iEnd /* End offset of token */
183197184403
){
183198184404
Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext;
184405
+ Fts5Termset *pTermset = pCtx->pTermset;
184406
+ int bPresent;
184407
+ int ii;
184408
+ int rc = SQLITE_OK;
184409
+ int iPos;
184410
+ int iCol;
184411
+
183199184412
if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
183200184413
pCtx->szCol++;
183201184414
}
183202
- pCtx->cksum ^= sqlite3Fts5IndexCksum(
183203
- pCtx->pConfig, pCtx->iRowid, pCtx->iCol, pCtx->szCol-1, pToken, nToken
183204
- );
183205
- return SQLITE_OK;
184415
+
184416
+ switch( pCtx->pConfig->eDetail ){
184417
+ case FTS5_DETAIL_FULL:
184418
+ iPos = pCtx->szCol-1;
184419
+ iCol = pCtx->iCol;
184420
+ break;
184421
+
184422
+ case FTS5_DETAIL_COLUMNS:
184423
+ iPos = pCtx->iCol;
184424
+ iCol = 0;
184425
+ break;
184426
+
184427
+ default:
184428
+ assert( pCtx->pConfig->eDetail==FTS5_DETAIL_NONE );
184429
+ iPos = 0;
184430
+ iCol = 0;
184431
+ break;
184432
+ }
184433
+
184434
+ rc = sqlite3Fts5TermsetAdd(pTermset, 0, pToken, nToken, &bPresent);
184435
+ if( rc==SQLITE_OK && bPresent==0 ){
184436
+ pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
184437
+ pCtx->iRowid, iCol, iPos, 0, pToken, nToken
184438
+ );
184439
+ }
184440
+
184441
+ for(ii=0; rc==SQLITE_OK && ii<pCtx->pConfig->nPrefix; ii++){
184442
+ const int nChar = pCtx->pConfig->aPrefix[ii];
184443
+ int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
184444
+ if( nByte ){
184445
+ rc = sqlite3Fts5TermsetAdd(pTermset, ii+1, pToken, nByte, &bPresent);
184446
+ if( bPresent==0 ){
184447
+ pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
184448
+ pCtx->iRowid, iCol, iPos, ii+1, pToken, nByte
184449
+ );
184450
+ }
184451
+ }
184452
+ }
184453
+
184454
+ return rc;
183206184455
}
183207184456
183208184457
/*
183209184458
** Check that the contents of the FTS index match that of the %_content
183210184459
** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return
@@ -183235,27 +184484,42 @@
183235184484
int i;
183236184485
ctx.iRowid = sqlite3_column_int64(pScan, 0);
183237184486
ctx.szCol = 0;
183238184487
if( pConfig->bColumnsize ){
183239184488
rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
184489
+ }
184490
+ if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
184491
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
183240184492
}
183241184493
for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
183242184494
if( pConfig->abUnindexed[i] ) continue;
183243184495
ctx.iCol = i;
183244184496
ctx.szCol = 0;
183245
- rc = sqlite3Fts5Tokenize(pConfig,
183246
- FTS5_TOKENIZE_DOCUMENT,
183247
- (const char*)sqlite3_column_text(pScan, i+1),
183248
- sqlite3_column_bytes(pScan, i+1),
183249
- (void*)&ctx,
183250
- fts5StorageIntegrityCallback
183251
- );
183252
- if( pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
184497
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
184498
+ rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
184499
+ }
184500
+ if( rc==SQLITE_OK ){
184501
+ rc = sqlite3Fts5Tokenize(pConfig,
184502
+ FTS5_TOKENIZE_DOCUMENT,
184503
+ (const char*)sqlite3_column_text(pScan, i+1),
184504
+ sqlite3_column_bytes(pScan, i+1),
184505
+ (void*)&ctx,
184506
+ fts5StorageIntegrityCallback
184507
+ );
184508
+ }
184509
+ if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
183253184510
rc = FTS5_CORRUPT;
183254184511
}
183255184512
aTotalSize[i] += ctx.szCol;
184513
+ if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
184514
+ sqlite3Fts5TermsetFree(ctx.pTermset);
184515
+ ctx.pTermset = 0;
184516
+ }
183256184517
}
184518
+ sqlite3Fts5TermsetFree(ctx.pTermset);
184519
+ ctx.pTermset = 0;
184520
+
183257184521
if( rc!=SQLITE_OK ) break;
183258184522
}
183259184523
rc2 = sqlite3_reset(pScan);
183260184524
if( rc==SQLITE_OK ) rc = rc2;
183261184525
}
@@ -185777,11 +187041,11 @@
185777187041
185778187042
pCsr->rowid++;
185779187043
185780187044
if( pTab->eType==FTS5_VOCAB_COL ){
185781187045
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
185782
- if( pCsr->aCnt[pCsr->iCol] ) break;
187046
+ if( pCsr->aDoc[pCsr->iCol] ) break;
185783187047
}
185784187048
}
185785187049
185786187050
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
185787187051
if( sqlite3Fts5IterEof(pCsr->pIter) ){
@@ -185810,28 +187074,56 @@
185810187074
i64 dummy;
185811187075
const u8 *pPos; int nPos; /* Position list */
185812187076
i64 iPos = 0; /* 64-bit position read from poslist */
185813187077
int iOff = 0; /* Current offset within position list */
185814187078
185815
- rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy);
185816
- if( rc==SQLITE_OK ){
185817
- if( pTab->eType==FTS5_VOCAB_ROW ){
185818
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
185819
- pCsr->aCnt[0]++;
185820
- }
185821
- pCsr->aDoc[0]++;
185822
- }else{
185823
- int iCol = -1;
185824
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
185825
- int ii = FTS5_POS2COLUMN(iPos);
185826
- pCsr->aCnt[ii]++;
185827
- if( iCol!=ii ){
185828
- pCsr->aDoc[ii]++;
185829
- iCol = ii;
185830
- }
185831
- }
185832
- }
187079
+ switch( pCsr->pConfig->eDetail ){
187080
+ case FTS5_DETAIL_FULL:
187081
+ rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy);
187082
+ if( rc==SQLITE_OK ){
187083
+ if( pTab->eType==FTS5_VOCAB_ROW ){
187084
+ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
187085
+ pCsr->aCnt[0]++;
187086
+ }
187087
+ pCsr->aDoc[0]++;
187088
+ }else{
187089
+ int iCol = -1;
187090
+ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
187091
+ int ii = FTS5_POS2COLUMN(iPos);
187092
+ pCsr->aCnt[ii]++;
187093
+ if( iCol!=ii ){
187094
+ pCsr->aDoc[ii]++;
187095
+ iCol = ii;
187096
+ }
187097
+ }
187098
+ }
187099
+ }
187100
+ break;
187101
+
187102
+ case FTS5_DETAIL_COLUMNS:
187103
+ if( pTab->eType==FTS5_VOCAB_ROW ){
187104
+ pCsr->aDoc[0]++;
187105
+ }else{
187106
+ Fts5Buffer buf = {0, 0, 0};
187107
+ rc = sqlite3Fts5IterPoslistBuffer(pCsr->pIter, &buf);
187108
+ if( rc==SQLITE_OK ){
187109
+ while( 0==sqlite3Fts5PoslistNext64(buf.p, buf.n, &iOff,&iPos) ){
187110
+ assert_nc( iPos>=0 && iPos<nCol );
187111
+ if( iPos<nCol ) pCsr->aDoc[iPos]++;
187112
+ }
187113
+ }
187114
+ sqlite3Fts5BufferFree(&buf);
187115
+ }
187116
+ break;
187117
+
187118
+ default:
187119
+ assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE );
187120
+ pCsr->aDoc[0]++;
187121
+ break;
187122
+ }
187123
+
187124
+ if( rc==SQLITE_OK ){
185833187125
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
185834187126
}
185835187127
185836187128
if( rc==SQLITE_OK ){
185837187129
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
@@ -185843,11 +187135,11 @@
185843187135
}
185844187136
}
185845187137
}
185846187138
185847187139
if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
185848
- while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++;
187140
+ while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++;
185849187141
assert( pCsr->iCol<pCsr->pConfig->nCol );
185850187142
}
185851187143
return rc;
185852187144
}
185853187145
@@ -185923,34 +187215,40 @@
185923187215
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
185924187216
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
185925187217
int iCol /* Index of column to read value from */
185926187218
){
185927187219
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
187220
+ int eDetail = pCsr->pConfig->eDetail;
187221
+ int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
187222
+ i64 iVal = 0;
185928187223
185929187224
if( iCol==0 ){
185930187225
sqlite3_result_text(
185931187226
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
185932187227
);
185933
- }
185934
- else if( ((Fts5VocabTable*)(pCursor->pVtab))->eType==FTS5_VOCAB_COL ){
187228
+ }else if( eType==FTS5_VOCAB_COL ){
185935187229
assert( iCol==1 || iCol==2 || iCol==3 );
185936187230
if( iCol==1 ){
185937
- const char *z = pCsr->pConfig->azCol[pCsr->iCol];
185938
- sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
187231
+ if( eDetail!=FTS5_DETAIL_NONE ){
187232
+ const char *z = pCsr->pConfig->azCol[pCsr->iCol];
187233
+ sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
187234
+ }
185939187235
}else if( iCol==2 ){
185940
- sqlite3_result_int64(pCtx, pCsr->aDoc[pCsr->iCol]);
187236
+ iVal = pCsr->aDoc[pCsr->iCol];
185941187237
}else{
185942
- sqlite3_result_int64(pCtx, pCsr->aCnt[pCsr->iCol]);
187238
+ iVal = pCsr->aCnt[pCsr->iCol];
185943187239
}
185944187240
}else{
185945187241
assert( iCol==1 || iCol==2 );
185946187242
if( iCol==1 ){
185947
- sqlite3_result_int64(pCtx, pCsr->aDoc[0]);
187243
+ iVal = pCsr->aDoc[0];
185948187244
}else{
185949
- sqlite3_result_int64(pCtx, pCsr->aCnt[0]);
187245
+ iVal = pCsr->aCnt[0];
185950187246
}
185951187247
}
187248
+
187249
+ if( iVal>0 ) sqlite3_result_int64(pCtx, iVal);
185952187250
return SQLITE_OK;
185953187251
}
185954187252
185955187253
/*
185956187254
** This is the xRowid method. The SQLite core calls this routine to
185957187255
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.10.0. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -119,10 +119,12 @@
119 #define SQLITE_ENABLE_LOCKING_STYLE 0
120 #define HAVE_UTIME 1
121 #else
122 /* This is not VxWorks. */
123 #define OS_VXWORKS 0
 
 
124 #endif /* defined(_WRS_KERNEL) */
125
126 /************** End of vxworks.h *********************************************/
127 /************** Continuing where we left off in sqliteInt.h ******************/
128
@@ -323,13 +325,13 @@
323 **
324 ** See also: [sqlite3_libversion()],
325 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
326 ** [sqlite_version()] and [sqlite_source_id()].
327 */
328 #define SQLITE_VERSION "3.10.0"
329 #define SQLITE_VERSION_NUMBER 3010000
330 #define SQLITE_SOURCE_ID "2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566"
331
332 /*
333 ** CAPI3REF: Run-Time Library Version Numbers
334 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
335 **
@@ -1006,12 +1008,17 @@
1006 ** improve performance on some systems.
1007 **
1008 ** <li>[[SQLITE_FCNTL_FILE_POINTER]]
1009 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
1010 ** to the [sqlite3_file] object associated with a particular database
1011 ** connection. See the [sqlite3_file_control()] documentation for
1012 ** additional information.
 
 
 
 
 
1013 **
1014 ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
1015 ** No longer in use.
1016 **
1017 ** <li>[[SQLITE_FCNTL_SYNC]]
@@ -1222,10 +1229,11 @@
1222 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23
1223 #define SQLITE_FCNTL_WAL_BLOCK 24
1224 #define SQLITE_FCNTL_ZIPVFS 25
1225 #define SQLITE_FCNTL_RBU 26
1226 #define SQLITE_FCNTL_VFS_POINTER 27
 
1227
1228 /* deprecated names */
1229 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1230 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1231 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -8399,10 +8407,13 @@
8399 ** If parameter iCol is greater than or equal to the number of columns
8400 ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
8401 ** an OOM condition or IO error), an appropriate SQLite error code is
8402 ** returned.
8403 **
 
 
 
8404 ** xColumnText:
8405 ** This function attempts to retrieve the text of column iCol of the
8406 ** current document. If successful, (*pz) is set to point to a buffer
8407 ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
8408 ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -8419,18 +8430,32 @@
8419 ** xInstCount:
8420 ** Set *pnInst to the total number of occurrences of all phrases within
8421 ** the query within the current row. Return SQLITE_OK if successful, or
8422 ** an error code (i.e. SQLITE_NOMEM) if an error occurs.
8423 **
 
 
 
 
 
8424 ** xInst:
8425 ** Query for the details of phrase match iIdx within the current row.
8426 ** Phrase matches are numbered starting from zero, so the iIdx argument
8427 ** should be greater than or equal to zero and smaller than the value
8428 ** output by xInstCount().
 
 
 
 
 
 
8429 **
8430 ** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
8431 ** if an error occurs.
 
 
 
8432 **
8433 ** xRowid:
8434 ** Returns the rowid of the current row.
8435 **
8436 ** xTokenize:
@@ -8511,25 +8536,63 @@
8511 ** through instances of phrase iPhrase, use the following code:
8512 **
8513 ** Fts5PhraseIter iter;
8514 ** int iCol, iOff;
8515 ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
8516 ** iOff>=0;
8517 ** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
8518 ** ){
8519 ** // An instance of phrase iPhrase at offset iOff of column iCol
8520 ** }
8521 **
8522 ** The Fts5PhraseIter structure is defined above. Applications should not
8523 ** modify this structure directly - it should only be used as shown above
8524 ** with the xPhraseFirst() and xPhraseNext() API methods.
 
 
 
 
 
 
 
8525 **
8526 ** xPhraseNext()
8527 ** See xPhraseFirst above.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8528 */
8529 struct Fts5ExtensionApi {
8530 int iVersion; /* Currently always set to 1 */
8531
8532 void *(*xUserData)(Fts5Context*);
8533
8534 int (*xColumnCount)(Fts5Context*);
8535 int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -8555,12 +8618,15 @@
8555 int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
8556 );
8557 int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
8558 void *(*xGetAuxdata)(Fts5Context*, int bClear);
8559
8560 void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
8561 void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
 
 
 
8562 };
8563
8564 /*
8565 ** CUSTOM AUXILIARY FUNCTIONS
8566 *************************************************************************/
@@ -9976,14 +10042,10 @@
9976 /*
9977 ** Default maximum size of memory used by memory-mapped I/O in the VFS
9978 */
9979 #ifdef __APPLE__
9980 # include <TargetConditionals.h>
9981 # if TARGET_OS_IPHONE
9982 # undef SQLITE_MAX_MMAP_SIZE
9983 # define SQLITE_MAX_MMAP_SIZE 0
9984 # endif
9985 #endif
9986 #ifndef SQLITE_MAX_MMAP_SIZE
9987 # if defined(__linux__) \
9988 || defined(_WIN32) \
9989 || (defined(__APPLE__) && defined(__MACH__)) \
@@ -10479,19 +10541,21 @@
10479 ** Enter and Leave procedures no-ops.
10480 */
10481 #ifndef SQLITE_OMIT_SHARED_CACHE
10482 SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*);
10483 SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*);
 
 
10484 #else
10485 # define sqlite3BtreeEnter(X)
10486 # define sqlite3BtreeEnterAll(X)
 
 
10487 #endif
10488
10489 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
10490 SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*);
10491 SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*);
10492 SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*);
10493 SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*);
10494 SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*);
10495 #ifndef NDEBUG
10496 /* These routines are used inside assert() statements only. */
10497 SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*);
@@ -10498,13 +10562,11 @@
10498 SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*);
10499 SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
10500 #endif
10501 #else
10502
10503 # define sqlite3BtreeSharable(X) 0
10504 # define sqlite3BtreeLeave(X)
10505 # define sqlite3BtreeEnterCursor(X)
10506 # define sqlite3BtreeLeaveCursor(X)
10507 # define sqlite3BtreeLeaveAll(X)
10508
10509 # define sqlite3BtreeHoldsMutex(X) 1
10510 # define sqlite3BtreeHoldsAllMutexes(X) 1
@@ -11215,10 +11277,11 @@
11215 #endif
11216 SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
11217 SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
11218 SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*);
11219 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
 
11220 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
11221 SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
11222 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
11223 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
11224 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
@@ -11309,10 +11372,12 @@
11309 #define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before
11310 ** writing this page to the database */
11311 #define PGHDR_NEED_READ 0x010 /* Content is unread */
11312 #define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
11313 #define PGHDR_MMAP 0x040 /* This is an mmap page object */
 
 
11314
11315 /* Initialize and shutdown the page cache subsystem */
11316 SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
11317 SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
11318
@@ -14135,11 +14200,10 @@
14135 SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
14136 SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
14137 SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
14138 SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
14139 SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
14140 SQLITE_PRIVATE void sqlite3BeginParse(Parse*,int);
14141 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
14142 SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
14143 SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
14144 SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
14145 SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
@@ -16066,15 +16130,19 @@
16066 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
16067 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
16068 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
16069 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
16070
16071 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
16072 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
16073 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
16074 #else
16075 # define sqlite3VdbeEnter(X)
 
 
 
 
 
16076 # define sqlite3VdbeLeave(X)
16077 #endif
16078
16079 #ifdef SQLITE_DEBUG
16080 SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
@@ -19758,10 +19826,11 @@
19758 /*
19759 ** Mutex to control access to the memory allocation subsystem.
19760 */
19761 sqlite3_mutex *mutex;
19762
 
19763 /*
19764 ** Performance statistics
19765 */
19766 u64 nAlloc; /* Total number of calls to malloc */
19767 u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
@@ -19769,10 +19838,11 @@
19769 u32 currentOut; /* Current checkout, including internal fragmentation */
19770 u32 currentCount; /* Current number of distinct checkouts */
19771 u32 maxOut; /* Maximum instantaneous currentOut */
19772 u32 maxCount; /* Maximum instantaneous currentCount */
19773 u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
 
19774
19775 /*
19776 ** Lists of free blocks. aiFreelist[0] is a list of free blocks of
19777 ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
19778 ** aiFreelist[2] holds free blocks of size szAtom*4. And so forth.
@@ -19880,18 +19950,21 @@
19880 int iLogsize; /* Log2 of iFullSz/POW2_MIN */
19881
19882 /* nByte must be a positive */
19883 assert( nByte>0 );
19884
 
 
 
 
19885 /* Keep track of the maximum allocation request. Even unfulfilled
19886 ** requests are counted */
19887 if( (u32)nByte>mem5.maxRequest ){
19888 /* Abort if the requested allocation size is larger than the largest
19889 ** power of two that we can represent using 32-bit signed integers. */
19890 if( nByte > 0x40000000 ) return 0;
19891 mem5.maxRequest = nByte;
19892 }
 
 
19893
19894 /* Round nByte up to the next valid power of two */
19895 for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){}
19896
19897 /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
@@ -19914,18 +19987,20 @@
19914 mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
19915 memsys5Link(i+newSize, iBin);
19916 }
19917 mem5.aCtrl[i] = iLogsize;
19918
 
19919 /* Update allocator performance statistics. */
19920 mem5.nAlloc++;
19921 mem5.totalAlloc += iFullSz;
19922 mem5.totalExcess += iFullSz - nByte;
19923 mem5.currentCount++;
19924 mem5.currentOut += iFullSz;
19925 if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
19926 if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
 
19927
19928 #ifdef SQLITE_DEBUG
19929 /* Make sure the allocated memory does not assume that it is set to zero
19930 ** or retains a value from a previous allocation */
19931 memset(&mem5.zPool[i*mem5.szAtom], 0xAA, iFullSz);
@@ -19956,16 +20031,19 @@
19956 size = 1<<iLogsize;
19957 assert( iBlock+size-1<(u32)mem5.nBlock );
19958
19959 mem5.aCtrl[iBlock] |= CTRL_FREE;
19960 mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
 
 
19961 assert( mem5.currentCount>0 );
19962 assert( mem5.currentOut>=(size*mem5.szAtom) );
19963 mem5.currentCount--;
19964 mem5.currentOut -= size*mem5.szAtom;
19965 assert( mem5.currentOut>0 || mem5.currentCount==0 );
19966 assert( mem5.currentCount>0 || mem5.currentOut==0 );
 
19967
19968 mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
19969 while( ALWAYS(iLogsize<LOGMAX) ){
19970 int iBuddy;
19971 if( (iBlock>>iLogsize) & 1 ){
@@ -27479,37 +27557,55 @@
27479 #define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
27480
27481 { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
27482 #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
27483
 
27484 { "fchown", (sqlite3_syscall_ptr)fchown, 0 },
 
 
 
27485 #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
27486
27487 { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 },
27488 #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
27489
27490 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
27491 { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
 
 
 
27492 #define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
27493
 
27494 { "munmap", (sqlite3_syscall_ptr)munmap, 0 },
 
 
 
27495 #define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent)
27496
27497 #if HAVE_MREMAP
27498 { "mremap", (sqlite3_syscall_ptr)mremap, 0 },
27499 #else
27500 { "mremap", (sqlite3_syscall_ptr)0, 0 },
27501 #endif
27502 #define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent)
27503
 
27504 { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
 
 
 
27505 #define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent)
27506
 
27507 { "readlink", (sqlite3_syscall_ptr)readlink, 0 },
 
 
 
27508 #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
27509
27510 #endif
27511
27512 }; /* End of the overrideable system calls */
27513
27514
27515 /*
@@ -27516,14 +27612,14 @@
27516 ** On some systems, calls to fchown() will trigger a message in a security
27517 ** log if they come from non-root processes. So avoid calling fchown() if
27518 ** we are not running as root.
27519 */
27520 static int robustFchown(int fd, uid_t uid, gid_t gid){
27521 #if OS_VXWORKS
27522 return 0;
27523 #else
27524 return osGeteuid() ? 0 : osFchown(fd,uid,gid);
 
 
27525 #endif
27526 }
27527
27528 /*
27529 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
@@ -32986,10 +33082,11 @@
32986 SimulateIOError( return SQLITE_ERROR );
32987
32988 assert( pVfs->mxPathname==MAX_PATHNAME );
32989 UNUSED_PARAMETER(pVfs);
32990
 
32991 /* Attempt to resolve the path as if it were a symbolic link. If it is
32992 ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if
32993 ** the identified file is not a symbolic link or does not exist, then
32994 ** zPath is copied directly into zOut. Either way, nByte is left set to
32995 ** the size of the string copied into zOut[] in bytes. */
@@ -33001,10 +33098,11 @@
33001 sqlite3_snprintf(nOut, zOut, "%s", zPath);
33002 nByte = sqlite3Strlen30(zOut);
33003 }else{
33004 zOut[nByte] = '\0';
33005 }
 
33006
33007 /* If buffer zOut[] now contains an absolute path there is nothing more
33008 ** to do. If it contains a relative path, do the following:
33009 **
33010 ** * move the relative path string so that it is at the end of th
@@ -43327,10 +43425,11 @@
43327 # define sqlite3WalCallback(z) 0
43328 # define sqlite3WalExclusiveMode(y,z) 0
43329 # define sqlite3WalHeapMemory(z) 0
43330 # define sqlite3WalFramesize(z) 0
43331 # define sqlite3WalFindFrame(x,y,z) 0
 
43332 #else
43333
43334 #define WAL_SAVEPOINT_NDATA 4
43335
43336 /* Connection to a write-ahead log (WAL) file.
@@ -43421,10 +43520,13 @@
43421 ** stored in each frame (i.e. the db page-size when the WAL was created).
43422 */
43423 SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
43424 #endif
43425
 
 
 
43426 #endif /* ifndef SQLITE_OMIT_WAL */
43427 #endif /* _WAL_H_ */
43428
43429 /************** End of wal.h *************************************************/
43430 /************** Continuing where we left off in pager.c **********************/
@@ -49032,11 +49134,11 @@
49032 if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
49033 rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
49034 if( rc!=SQLITE_OK ){
49035 return rc;
49036 }
49037 sqlite3WalExclusiveMode(pPager->pWal, 1);
49038 }
49039
49040 /* Grab the write lock on the log file. If successful, upgrade to
49041 ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
49042 ** The busy-handler is not invoked if another connection already
@@ -50096,10 +50198,22 @@
50096 ** not yet been opened.
50097 */
50098 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
50099 return pPager->fd;
50100 }
 
 
 
 
 
 
 
 
 
 
 
 
50101
50102 /*
50103 ** Return the full pathname of the journal file.
50104 */
50105 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
@@ -51202,10 +51316,11 @@
51202 u8 truncateOnCommit; /* True to truncate WAL file on commit */
51203 u8 syncHeader; /* Fsync the WAL header if true */
51204 u8 padToSectorBoundary; /* Pad transactions out to the next sector */
51205 WalIndexHdr hdr; /* Wal-index header for current transaction */
51206 u32 minFrame; /* Ignore wal frames before this one */
 
51207 const char *zWalName; /* Name of WAL file */
51208 u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
51209 #ifdef SQLITE_DEBUG
51210 u8 lockError; /* True if a locking error has occurred */
51211 #endif
@@ -51455,18 +51570,22 @@
51455 int nativeCksum; /* True for native byte-order checksums */
51456 u32 *aCksum = pWal->hdr.aFrameCksum;
51457 assert( WAL_FRAME_HDRSIZE==24 );
51458 sqlite3Put4byte(&aFrame[0], iPage);
51459 sqlite3Put4byte(&aFrame[4], nTruncate);
51460 memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
51461
51462 nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
51463 walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
51464 walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
51465
51466 sqlite3Put4byte(&aFrame[16], aCksum[0]);
51467 sqlite3Put4byte(&aFrame[20], aCksum[1]);
 
 
 
 
51468 }
51469
51470 /*
51471 ** Check to see if the frame with header in aFrame[] and content
51472 ** in aData[] is valid. If it is a valid frame, fill *piPage and
@@ -53389,10 +53508,11 @@
53389 int rc;
53390
53391 /* Cannot start a write transaction without first holding a read
53392 ** transaction. */
53393 assert( pWal->readLock>=0 );
 
53394
53395 if( pWal->readOnly ){
53396 return SQLITE_READONLY;
53397 }
53398
@@ -53424,10 +53544,11 @@
53424 */
53425 SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){
53426 if( pWal->writeLock ){
53427 walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
53428 pWal->writeLock = 0;
 
53429 pWal->truncateOnCommit = 0;
53430 }
53431 return SQLITE_OK;
53432 }
53433
@@ -53641,10 +53762,63 @@
53641 if( rc ) return rc;
53642 /* Write the page data */
53643 rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
53644 return rc;
53645 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53646
53647 /*
53648 ** Write a set of frames to the log. The caller must hold the write-lock
53649 ** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
53650 */
@@ -53662,10 +53836,12 @@
53662 PgHdr *pLast = 0; /* Last frame in list */
53663 int nExtra = 0; /* Number of extra copies of last page */
53664 int szFrame; /* The size of a single frame */
53665 i64 iOffset; /* Next byte to write in WAL file */
53666 WalWriter w; /* The writer */
 
 
53667
53668 assert( pList );
53669 assert( pWal->writeLock );
53670
53671 /* If this frame set completes a transaction, then nTruncate>0. If
@@ -53676,10 +53852,15 @@
53676 { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
53677 WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
53678 pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
53679 }
53680 #endif
 
 
 
 
 
53681
53682 /* See if it is possible to write these frames into the start of the
53683 ** log file, instead of appending to it at pWal->hdr.mxFrame.
53684 */
53685 if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
@@ -53741,17 +53922,45 @@
53741 szFrame = szPage + WAL_FRAME_HDRSIZE;
53742
53743 /* Write all frames into the log file exactly once */
53744 for(p=pList; p; p=p->pDirty){
53745 int nDbSize; /* 0 normally. Positive == commit flag */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53746 iFrame++;
53747 assert( iOffset==walFrameOffset(iFrame, szPage) );
53748 nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0;
53749 rc = walWriteOneFrame(&w, p, nDbSize, iOffset);
53750 if( rc ) return rc;
53751 pLast = p;
53752 iOffset += szFrame;
 
 
 
 
 
 
 
53753 }
53754
53755 /* If this is the end of a transaction, then we might need to pad
53756 ** the transaction and/or sync the WAL file.
53757 **
@@ -53799,10 +54008,11 @@
53799 ** guarantees that there are no other writers, and no data that may
53800 ** be in use by existing readers is being overwritten.
53801 */
53802 iFrame = pWal->hdr.mxFrame;
53803 for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
 
53804 iFrame++;
53805 rc = walIndexAppend(pWal, iFrame, p->pgno);
53806 }
53807 while( rc==SQLITE_OK && nExtra>0 ){
53808 iFrame++;
@@ -53911,10 +54121,11 @@
53911 }
53912 }
53913
53914 /* Copy data from the log to the database file. */
53915 if( rc==SQLITE_OK ){
 
53916 if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
53917 rc = SQLITE_CORRUPT_BKPT;
53918 }else{
53919 rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
53920 }
@@ -54066,10 +54277,16 @@
54066 SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
54067 assert( pWal==0 || pWal->readLock>=0 );
54068 return (pWal ? pWal->szPage : 0);
54069 }
54070 #endif
 
 
 
 
 
 
54071
54072 #endif /* #ifndef SQLITE_OMIT_WAL */
54073
54074 /************** End of wal.c *************************************************/
54075 /************** Begin file btmutex.c *****************************************/
@@ -54368,11 +54585,10 @@
54368 struct MemPage {
54369 u8 isInit; /* True if previously initialized. MUST BE FIRST! */
54370 u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
54371 u8 intKey; /* True if table b-trees. False for index b-trees */
54372 u8 intKeyLeaf; /* True if the leaf of an intKey table */
54373 u8 noPayload; /* True if internal intKey page (thus w/o data) */
54374 u8 leaf; /* True if a leaf page */
54375 u8 hdrOffset; /* 100 for page 1. 0 otherwise */
54376 u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
54377 u8 max1bytePayload; /* min(maxLocal,127) */
54378 u8 bBusy; /* Prevent endless loops on corrupt database files */
@@ -54955,25 +55171,10 @@
54955
54956 return (p->sharable==0 || p->locked);
54957 }
54958 #endif
54959
54960
54961 #ifndef SQLITE_OMIT_INCRBLOB
54962 /*
54963 ** Enter and leave a mutex on a Btree given a cursor owned by that
54964 ** Btree. These entry points are used by incremental I/O and can be
54965 ** omitted if that module is not used.
54966 */
54967 SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){
54968 sqlite3BtreeEnter(pCur->pBtree);
54969 }
54970 SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
54971 sqlite3BtreeLeave(pCur->pBtree);
54972 }
54973 #endif /* SQLITE_OMIT_INCRBLOB */
54974
54975
54976 /*
54977 ** Enter the mutex on every Btree associated with a database
54978 ** connection. This is needed (for example) prior to parsing
54979 ** a statement since we will be comparing table and column names
@@ -55004,18 +55205,10 @@
55004 p = db->aDb[i].pBt;
55005 if( p ) sqlite3BtreeLeave(p);
55006 }
55007 }
55008
55009 /*
55010 ** Return true if a particular Btree requires a lock. Return FALSE if
55011 ** no lock is ever required since it is not sharable.
55012 */
55013 SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){
55014 return p->sharable;
55015 }
55016
55017 #ifndef NDEBUG
55018 /*
55019 ** Return true if the current thread holds the database connection
55020 ** mutex and all required BtShared mutexes.
55021 **
@@ -55085,10 +55278,29 @@
55085 p->pBt->db = p->db;
55086 }
55087 }
55088 }
55089 #endif /* if SQLITE_THREADSAFE */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55090 #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */
55091
55092 /************** End of btmutex.c *********************************************/
55093 /************** Begin file btree.c *******************************************/
55094 /*
@@ -55541,10 +55753,14 @@
55541 */
55542 #ifdef SQLITE_DEBUG
55543 static int cursorHoldsMutex(BtCursor *p){
55544 return sqlite3_mutex_held(p->pBt->mutex);
55545 }
 
 
 
 
55546 #endif
55547
55548 /*
55549 ** Invalidate the overflow cache of the cursor passed as the first argument.
55550 ** on the shared btree structure pBt.
@@ -55877,11 +56093,11 @@
55877 ** saveCursorPosition().
55878 */
55879 static int btreeRestoreCursorPosition(BtCursor *pCur){
55880 int rc;
55881 int skipNext;
55882 assert( cursorHoldsMutex(pCur) );
55883 assert( pCur->eState>=CURSOR_REQUIRESEEK );
55884 if( pCur->eState==CURSOR_FAULT ){
55885 return pCur->skipNext;
55886 }
55887 pCur->eState = CURSOR_INVALID;
@@ -56166,11 +56382,10 @@
56166 u8 *pCell, /* Pointer to the cell text. */
56167 CellInfo *pInfo /* Fill in this structure */
56168 ){
56169 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
56170 assert( pPage->leaf==0 );
56171 assert( pPage->noPayload );
56172 assert( pPage->childPtrSize==4 );
56173 #ifndef SQLITE_DEBUG
56174 UNUSED_PARAMETER(pPage);
56175 #endif
56176 pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
@@ -56188,12 +56403,10 @@
56188 u32 nPayload; /* Number of bytes of cell payload */
56189 u64 iKey; /* Extracted Key value */
56190
56191 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
56192 assert( pPage->leaf==0 || pPage->leaf==1 );
56193 assert( pPage->intKeyLeaf || pPage->noPayload );
56194 assert( pPage->noPayload==0 );
56195 assert( pPage->intKeyLeaf );
56196 assert( pPage->childPtrSize==0 );
56197 pIter = pCell;
56198
56199 /* The next block of code is equivalent to:
@@ -56258,11 +56471,10 @@
56258 u32 nPayload; /* Number of bytes of cell payload */
56259
56260 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
56261 assert( pPage->leaf==0 || pPage->leaf==1 );
56262 assert( pPage->intKeyLeaf==0 );
56263 assert( pPage->noPayload==0 );
56264 pIter = pCell + pPage->childPtrSize;
56265 nPayload = *pIter;
56266 if( nPayload>=0x80 ){
56267 u8 *pEnd = &pIter[8];
56268 nPayload &= 0x7f;
@@ -56319,11 +56531,10 @@
56319 ** this function verifies that this invariant is not violated. */
56320 CellInfo debuginfo;
56321 pPage->xParseCell(pPage, pCell, &debuginfo);
56322 #endif
56323
56324 assert( pPage->noPayload==0 );
56325 nSize = *pIter;
56326 if( nSize>=0x80 ){
56327 pEnd = &pIter[8];
56328 nSize &= 0x7f;
56329 do{
@@ -56777,15 +56988,13 @@
56777 ** table b-tree page. */
56778 assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
56779 pPage->intKey = 1;
56780 if( pPage->leaf ){
56781 pPage->intKeyLeaf = 1;
56782 pPage->noPayload = 0;
56783 pPage->xParseCell = btreeParseCellPtr;
56784 }else{
56785 pPage->intKeyLeaf = 0;
56786 pPage->noPayload = 1;
56787 pPage->xCellSize = cellSizePtrNoPayload;
56788 pPage->xParseCell = btreeParseCellPtrNoPayload;
56789 }
56790 pPage->maxLocal = pBt->maxLeaf;
56791 pPage->minLocal = pBt->minLeaf;
@@ -56796,11 +57005,10 @@
56796 /* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf
56797 ** index b-tree page. */
56798 assert( (PTF_ZERODATA|PTF_LEAF)==10 );
56799 pPage->intKey = 0;
56800 pPage->intKeyLeaf = 0;
56801 pPage->noPayload = 0;
56802 pPage->xParseCell = btreeParseCellPtrIndex;
56803 pPage->maxLocal = pBt->maxLocal;
56804 pPage->minLocal = pBt->minLocal;
56805 }else{
56806 /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
@@ -58217,11 +58425,10 @@
58217 ** no progress. By returning SQLITE_BUSY and not invoking the busy callback
58218 ** when A already has a read lock, we encourage A to give up and let B
58219 ** proceed.
58220 */
58221 SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
58222 sqlite3 *pBlock = 0;
58223 BtShared *pBt = p->pBt;
58224 int rc = SQLITE_OK;
58225
58226 sqlite3BtreeEnter(p);
58227 btreeIntegrity(p);
@@ -58240,31 +58447,34 @@
58240 rc = SQLITE_READONLY;
58241 goto trans_begun;
58242 }
58243
58244 #ifndef SQLITE_OMIT_SHARED_CACHE
58245 /* If another database handle has already opened a write transaction
58246 ** on this shared-btree structure and a second write transaction is
58247 ** requested, return SQLITE_LOCKED.
58248 */
58249 if( (wrflag && pBt->inTransaction==TRANS_WRITE)
58250 || (pBt->btsFlags & BTS_PENDING)!=0
58251 ){
58252 pBlock = pBt->pWriter->db;
58253 }else if( wrflag>1 ){
58254 BtLock *pIter;
58255 for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
58256 if( pIter->pBtree!=p ){
58257 pBlock = pIter->pBtree->db;
58258 break;
58259 }
58260 }
58261 }
58262 if( pBlock ){
58263 sqlite3ConnectionBlocked(p->db, pBlock);
58264 rc = SQLITE_LOCKED_SHAREDCACHE;
58265 goto trans_begun;
 
 
 
58266 }
58267 #endif
58268
58269 /* Any read-only or read-write transaction implies a read-lock on
58270 ** page 1. So if some other shared-cache client already has a write-lock
@@ -59377,11 +59587,11 @@
59377 ** Failure is not possible. This function always returns SQLITE_OK.
59378 ** It might just as well be a procedure (returning void) but we continue
59379 ** to return an integer result code for historical reasons.
59380 */
59381 SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
59382 assert( cursorHoldsMutex(pCur) );
59383 assert( pCur->eState==CURSOR_VALID );
59384 assert( pCur->iPage>=0 );
59385 assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
59386 assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
59387 getCellInfo(pCur);
@@ -59757,11 +59967,11 @@
59757 if ( pCur->eState==CURSOR_INVALID ){
59758 return SQLITE_ABORT;
59759 }
59760 #endif
59761
59762 assert( cursorHoldsMutex(pCur) );
59763 rc = restoreCursorPosition(pCur);
59764 if( rc==SQLITE_OK ){
59765 assert( pCur->eState==CURSOR_VALID );
59766 assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
59767 assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
@@ -59795,11 +60005,11 @@
59795 ){
59796 u32 amt;
59797 assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
59798 assert( pCur->eState==CURSOR_VALID );
59799 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
59800 assert( cursorHoldsMutex(pCur) );
59801 assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
59802 assert( pCur->info.nSize>0 );
59803 assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
59804 assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
59805 amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload);
@@ -59841,11 +60051,11 @@
59841 ** vice-versa).
59842 */
59843 static int moveToChild(BtCursor *pCur, u32 newPgno){
59844 BtShared *pBt = pCur->pBt;
59845
59846 assert( cursorHoldsMutex(pCur) );
59847 assert( pCur->eState==CURSOR_VALID );
59848 assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
59849 assert( pCur->iPage>=0 );
59850 if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
59851 return SQLITE_CORRUPT_BKPT;
@@ -59887,11 +60097,11 @@
59887 ** to the page we are coming from. If we are coming from the
59888 ** right-most child page then pCur->idx is set to one more than
59889 ** the largest cell index.
59890 */
59891 static void moveToParent(BtCursor *pCur){
59892 assert( cursorHoldsMutex(pCur) );
59893 assert( pCur->eState==CURSOR_VALID );
59894 assert( pCur->iPage>0 );
59895 assert( pCur->apPage[pCur->iPage] );
59896 assertParentIndex(
59897 pCur->apPage[pCur->iPage-1],
@@ -59927,11 +60137,11 @@
59927 */
59928 static int moveToRoot(BtCursor *pCur){
59929 MemPage *pRoot;
59930 int rc = SQLITE_OK;
59931
59932 assert( cursorHoldsMutex(pCur) );
59933 assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
59934 assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
59935 assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
59936 if( pCur->eState>=CURSOR_REQUIRESEEK ){
59937 if( pCur->eState==CURSOR_FAULT ){
@@ -60006,11 +60216,11 @@
60006 static int moveToLeftmost(BtCursor *pCur){
60007 Pgno pgno;
60008 int rc = SQLITE_OK;
60009 MemPage *pPage;
60010
60011 assert( cursorHoldsMutex(pCur) );
60012 assert( pCur->eState==CURSOR_VALID );
60013 while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
60014 assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
60015 pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
60016 rc = moveToChild(pCur, pgno);
@@ -60031,11 +60241,11 @@
60031 static int moveToRightmost(BtCursor *pCur){
60032 Pgno pgno;
60033 int rc = SQLITE_OK;
60034 MemPage *pPage = 0;
60035
60036 assert( cursorHoldsMutex(pCur) );
60037 assert( pCur->eState==CURSOR_VALID );
60038 while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
60039 pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
60040 pCur->aiIdx[pCur->iPage] = pPage->nCell;
60041 rc = moveToChild(pCur, pgno);
@@ -60052,11 +60262,11 @@
60052 ** or set *pRes to 1 if the table is empty.
60053 */
60054 SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
60055 int rc;
60056
60057 assert( cursorHoldsMutex(pCur) );
60058 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
60059 rc = moveToRoot(pCur);
60060 if( rc==SQLITE_OK ){
60061 if( pCur->eState==CURSOR_INVALID ){
60062 assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
@@ -60075,11 +60285,11 @@
60075 ** or set *pRes to 1 if the table is empty.
60076 */
60077 SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
60078 int rc;
60079
60080 assert( cursorHoldsMutex(pCur) );
60081 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
60082
60083 /* If the cursor already points to the last entry, this is a no-op. */
60084 if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
60085 #ifdef SQLITE_DEBUG
@@ -60153,11 +60363,11 @@
60153 int *pRes /* Write search results here */
60154 ){
60155 int rc;
60156 RecordCompare xRecordCompare;
60157
60158 assert( cursorHoldsMutex(pCur) );
60159 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
60160 assert( pRes );
60161 assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
60162
60163 /* If the cursor is already positioned at the point we are trying
@@ -60401,11 +60611,11 @@
60401 static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
60402 int rc;
60403 int idx;
60404 MemPage *pPage;
60405
60406 assert( cursorHoldsMutex(pCur) );
60407 assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
60408 assert( *pRes==0 );
60409 if( pCur->eState!=CURSOR_VALID ){
60410 assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
60411 rc = restoreCursorPosition(pCur);
@@ -60465,11 +60675,11 @@
60465 return moveToLeftmost(pCur);
60466 }
60467 }
60468 SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
60469 MemPage *pPage;
60470 assert( cursorHoldsMutex(pCur) );
60471 assert( pRes!=0 );
60472 assert( *pRes==0 || *pRes==1 );
60473 assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
60474 pCur->info.nSize = 0;
60475 pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
@@ -60510,11 +60720,11 @@
60510 */
60511 static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
60512 int rc;
60513 MemPage *pPage;
60514
60515 assert( cursorHoldsMutex(pCur) );
60516 assert( pRes!=0 );
60517 assert( *pRes==0 );
60518 assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
60519 assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
60520 assert( pCur->info.nSize==0 );
@@ -60566,11 +60776,11 @@
60566 }
60567 }
60568 return rc;
60569 }
60570 SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
60571 assert( cursorHoldsMutex(pCur) );
60572 assert( pRes!=0 );
60573 assert( *pRes==0 || *pRes==1 );
60574 assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
60575 *pRes = 0;
60576 pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
@@ -63046,11 +63256,11 @@
63046 if( pCur->eState==CURSOR_FAULT ){
63047 assert( pCur->skipNext!=SQLITE_OK );
63048 return pCur->skipNext;
63049 }
63050
63051 assert( cursorHoldsMutex(pCur) );
63052 assert( (pCur->curFlags & BTCF_WriteFlag)!=0
63053 && pBt->inTransaction==TRANS_WRITE
63054 && (pBt->btsFlags & BTS_READ_ONLY)==0 );
63055 assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
63056
@@ -63193,11 +63403,11 @@
63193 int iCellIdx; /* Index of cell to delete */
63194 int iCellDepth; /* Depth of node containing pCell */
63195 u16 szCell; /* Size of the cell being deleted */
63196 int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
63197
63198 assert( cursorHoldsMutex(pCur) );
63199 assert( pBt->inTransaction==TRANS_WRITE );
63200 assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
63201 assert( pCur->curFlags & BTCF_WriteFlag );
63202 assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
63203 assert( !hasReadConflicts(p, pCur->pgnoRoot) );
@@ -64655,11 +64865,11 @@
64655 ** parameters that attempt to write past the end of the existing data,
64656 ** no modifications are made and SQLITE_CORRUPT is returned.
64657 */
64658 SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
64659 int rc;
64660 assert( cursorHoldsMutex(pCsr) );
64661 assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
64662 assert( pCsr->curFlags & BTCF_Incrblob );
64663
64664 rc = restoreCursorPosition(pCsr);
64665 if( rc!=SQLITE_OK ){
@@ -64762,10 +64972,19 @@
64762
64763 /*
64764 ** Return the size of the header added to each page by this module.
64765 */
64766 SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
 
 
 
 
 
 
 
 
 
64767
64768 /************** End of btree.c ***********************************************/
64769 /************** Begin file backup.c ******************************************/
64770 /*
64771 ** 2009 January 28
@@ -67593,12 +67812,11 @@
67593 ** The zWhere string must have been obtained from sqlite3_malloc().
67594 ** This routine will take ownership of the allocated memory.
67595 */
67596 SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
67597 int j;
67598 int addr = sqlite3VdbeAddOp3(p, OP_ParseSchema, iDb, 0, 0);
67599 sqlite3VdbeChangeP4(p, addr, zWhere, P4_DYNAMIC);
67600 for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
67601 }
67602
67603 /*
67604 ** Add an opcode that includes the p4 value as an integer.
@@ -68093,11 +68311,11 @@
68093 */
68094 static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
68095 if( aOp ){
68096 Op *pOp;
68097 for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
68098 freeP4(db, pOp->p4type, pOp->p4.p);
68099 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
68100 sqlite3DbFree(db, pOp->zComment);
68101 #endif
68102 }
68103 }
@@ -68155,65 +68373,60 @@
68155 ** to a string or structure that is guaranteed to exist for the lifetime of
68156 ** the Vdbe. In these cases we can just copy the pointer.
68157 **
68158 ** If addr<0 then change P4 on the most recently inserted instruction.
68159 */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68160 SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
68161 Op *pOp;
68162 sqlite3 *db;
68163 assert( p!=0 );
68164 db = p->db;
68165 assert( p->magic==VDBE_MAGIC_INIT );
68166 if( p->aOp==0 || db->mallocFailed ){
68167 if( n!=P4_VTAB ){
68168 freeP4(db, n, (void*)*(char**)&zP4);
68169 }
68170 return;
68171 }
68172 assert( p->nOp>0 );
68173 assert( addr<p->nOp );
68174 if( addr<0 ){
68175 addr = p->nOp - 1;
68176 }
68177 pOp = &p->aOp[addr];
68178 assert( pOp->p4type==P4_NOTUSED
68179 || pOp->p4type==P4_INT32
68180 || pOp->p4type==P4_KEYINFO );
68181 freeP4(db, pOp->p4type, pOp->p4.p);
68182 pOp->p4.p = 0;
68183 if( n==P4_INT32 ){
68184 /* Note: this cast is safe, because the origin data point was an int
68185 ** that was cast to a (const char *). */
68186 pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
68187 pOp->p4type = P4_INT32;
68188 }else if( zP4==0 ){
68189 pOp->p4.p = 0;
68190 pOp->p4type = P4_NOTUSED;
68191 }else if( n==P4_KEYINFO ){
68192 pOp->p4.p = (void*)zP4;
68193 pOp->p4type = P4_KEYINFO;
68194 #ifdef SQLITE_ENABLE_CURSOR_HINTS
68195 }else if( n==P4_EXPR ){
68196 /* Responsibility for deleting the Expr tree is handed over to the
68197 ** VDBE by this operation. The caller should have already invoked
68198 ** sqlite3ExprDup() or whatever other routine is needed to make a
68199 ** private copy of the tree. */
68200 pOp->p4.pExpr = (Expr*)zP4;
68201 pOp->p4type = P4_EXPR;
68202 #endif
68203 }else if( n==P4_VTAB ){
68204 pOp->p4.p = (void*)zP4;
68205 pOp->p4type = P4_VTAB;
68206 sqlite3VtabLock((VTable *)zP4);
68207 assert( ((VTable *)zP4)->db==p->db );
68208 }else if( n<0 ){
68209 pOp->p4.p = (void*)zP4;
68210 pOp->p4type = (signed char)n;
68211 }else{
68212 if( n==0 ) n = sqlite3Strlen30(zP4);
68213 pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
68214 pOp->p4type = P4_DYNAMIC;
68215 }
68216 }
68217
68218 /*
68219 ** Set the P4 on the most recently added opcode to the KeyInfo for the
@@ -68605,11 +68818,11 @@
68605 if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
68606 DbMaskSet(p->lockMask, i);
68607 }
68608 }
68609
68610 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
68611 /*
68612 ** If SQLite is compiled to support shared-cache mode and to be threadsafe,
68613 ** this routine obtains the mutex associated with each BtShared structure
68614 ** that may be accessed by the VM passed as an argument. In doing so it also
68615 ** sets the BtShared.db member of each of the BtShared structures, ensuring
@@ -76059,11 +76272,10 @@
76059 const u8 *zEndHdr; /* Pointer to first byte after the header */
76060 u32 offset; /* Offset into the data */
76061 u64 offset64; /* 64-bit offset */
76062 u32 avail; /* Number of bytes of available data */
76063 u32 t; /* A type code from the record header */
76064 u16 fx; /* pDest->flags value */
76065 Mem *pReg; /* PseudoTable input register */
76066
76067 p2 = pOp->p2;
76068 assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
76069 pDest = &aMem[pOp->p3];
@@ -76237,14 +76449,35 @@
76237 assert( p2<pC->nHdrParsed );
76238 assert( rc==SQLITE_OK );
76239 assert( sqlite3VdbeCheckMemInvariants(pDest) );
76240 if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest);
76241 assert( t==pC->aType[p2] );
 
76242 if( pC->szRow>=aOffset[p2+1] ){
76243 /* This is the common case where the desired content fits on the original
76244 ** page - where the content is not on an overflow page */
76245 sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], t, pDest);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76246 }else{
76247 /* This branch happens only when content is on overflow pages */
76248 if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
76249 && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
76250 || (len = sqlite3VdbeSerialTypeLen(t))==0
@@ -76252,42 +76485,24 @@
76252 /* Content is irrelevant for
76253 ** 1. the typeof() function,
76254 ** 2. the length(X) function if X is a blob, and
76255 ** 3. if the content length is zero.
76256 ** So we might as well use bogus content rather than reading
76257 ** content from disk. NULL will work for the value for strings
76258 ** and blobs and whatever is in the payloadSize64 variable
76259 ** will work for everything else. */
76260 sqlite3VdbeSerialGet(t<=13 ? (u8*)&payloadSize64 : 0, t, pDest);
76261 }else{
76262 rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
76263 pDest);
76264 if( rc!=SQLITE_OK ){
76265 goto op_column_error;
76266 }
76267 sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
76268 pDest->flags &= ~MEM_Ephem;
76269 }
76270 }
76271 pDest->enc = encoding;
76272
76273 op_column_out:
76274 /* If the column value is an ephemeral string, go ahead and persist
76275 ** that string in case the cursor moves before the column value is
76276 ** used. The following code does the equivalent of Deephemeralize()
76277 ** but does it faster. */
76278 if( (pDest->flags & MEM_Ephem)!=0 && pDest->z ){
76279 fx = pDest->flags & (MEM_Str|MEM_Blob);
76280 assert( fx!=0 );
76281 zData = (const u8*)pDest->z;
76282 len = pDest->n;
76283 if( sqlite3VdbeMemClearAndResize(pDest, len+2) ) goto no_mem;
76284 memcpy(pDest->z, zData, len);
76285 pDest->z[len] = 0;
76286 pDest->z[len+1] = 0;
76287 pDest->flags = fx|MEM_Term;
76288 }
76289 op_column_error:
76290 UPDATE_MAX_BLOBSIZE(pDest);
76291 REGISTER_TRACE(pOp->p3, pDest);
76292 break;
76293 }
@@ -81685,11 +81900,11 @@
81685 assert( pReadr->aBuffer==0 );
81686 assert( pReadr->aMap==0 );
81687
81688 rc = vdbePmaReaderSeek(pTask, pReadr, pFile, iStart);
81689 if( rc==SQLITE_OK ){
81690 u64 nByte; /* Size of PMA in bytes */
81691 rc = vdbePmaReadVarint(pReadr, &nByte);
81692 pReadr->iEof = pReadr->iReadOff + nByte;
81693 *pnByte += nByte;
81694 }
81695
@@ -84243,13 +84458,12 @@
84243 ** return the top-level walk call.
84244 **
84245 ** The return value from this routine is WRC_Abort to abandon the tree walk
84246 ** and WRC_Continue to continue.
84247 */
84248 SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
84249 int rc;
84250 if( pExpr==0 ) return WRC_Continue;
84251 testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
84252 testcase( ExprHasProperty(pExpr, EP_Reduced) );
84253 rc = pWalker->xExprCallback(pWalker, pExpr);
84254 if( rc==WRC_Continue
84255 && !ExprHasProperty(pExpr,EP_TokenOnly) ){
@@ -84260,10 +84474,13 @@
84260 }else{
84261 if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
84262 }
84263 }
84264 return rc & WRC_Abort;
 
 
 
84265 }
84266
84267 /*
84268 ** Call sqlite3WalkExpr() for every expression in list p or until
84269 ** an abort request is seen.
@@ -86327,12 +86544,13 @@
86327 || sqlite3GetInt32(pToken->z, &iValue)==0 ){
86328 nExtra = pToken->n+1;
86329 assert( iValue>=0 );
86330 }
86331 }
86332 pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
86333 if( pNew ){
 
86334 pNew->op = (u8)op;
86335 pNew->iAgg = -1;
86336 if( pToken ){
86337 if( nExtra==0 ){
86338 pNew->flags |= EP_IntValue;
@@ -93723,19 +93941,10 @@
93723 ** COMMIT
93724 ** ROLLBACK
93725 */
93726 /* #include "sqliteInt.h" */
93727
93728 /*
93729 ** This routine is called when a new SQL statement is beginning to
93730 ** be parsed. Initialize the pParse structure as needed.
93731 */
93732 SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){
93733 pParse->explain = (u8)explainFlag;
93734 pParse->nVar = 0;
93735 }
93736
93737 #ifndef SQLITE_OMIT_SHARED_CACHE
93738 /*
93739 ** The TableLock structure is only used by the sqlite3TableLock() and
93740 ** codeTableLocks() functions.
93741 */
@@ -100072,14 +100281,14 @@
100072
100073 /*
100074 ** A structure defining how to do GLOB-style comparisons.
100075 */
100076 struct compareInfo {
100077 u8 matchAll;
100078 u8 matchOne;
100079 u8 matchSet;
100080 u8 noCase;
100081 };
100082
100083 /*
100084 ** For LIKE and GLOB matching on EBCDIC machines, assume that every
100085 ** character is exactly one byte in size. Also, provde the Utf8Read()
@@ -100138,26 +100347,18 @@
100138 */
100139 static int patternCompare(
100140 const u8 *zPattern, /* The glob pattern */
100141 const u8 *zString, /* The string to compare against the glob */
100142 const struct compareInfo *pInfo, /* Information about how to do the compare */
100143 u32 esc /* The escape character */
100144 ){
100145 u32 c, c2; /* Next pattern and input string chars */
100146 u32 matchOne = pInfo->matchOne; /* "?" or "_" */
100147 u32 matchAll = pInfo->matchAll; /* "*" or "%" */
100148 u32 matchOther; /* "[" or the escape character */
100149 u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
100150 const u8 *zEscaped = 0; /* One past the last escaped input char */
100151
100152 /* The GLOB operator does not have an ESCAPE clause. And LIKE does not
100153 ** have the matchSet operator. So we either have to look for one or
100154 ** the other, never both. Hence the single variable matchOther is used
100155 ** to store the one we have to look for.
100156 */
100157 matchOther = esc ? esc : pInfo->matchSet;
100158
100159 while( (c = Utf8Read(zPattern))!=0 ){
100160 if( c==matchAll ){ /* Match "*" */
100161 /* Skip over multiple "*" characters in the pattern. If there
100162 ** are also "?" characters, skip those as well, but consume a
100163 ** single character of the input string for each "?" skipped */
@@ -100167,19 +100368,19 @@
100167 }
100168 }
100169 if( c==0 ){
100170 return 1; /* "*" at the end of the pattern matches */
100171 }else if( c==matchOther ){
100172 if( esc ){
100173 c = sqlite3Utf8Read(&zPattern);
100174 if( c==0 ) return 0;
100175 }else{
100176 /* "[...]" immediately follows the "*". We have to do a slow
100177 ** recursive search in this case, but it is an unusual case. */
100178 assert( matchOther<0x80 ); /* '[' is a single-byte character */
100179 while( *zString
100180 && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
100181 SQLITE_SKIP_UTF8(zString);
100182 }
100183 return *zString!=0;
100184 }
100185 }
@@ -100201,22 +100402,22 @@
100201 }else{
100202 cx = c;
100203 }
100204 while( (c2 = *(zString++))!=0 ){
100205 if( c2!=c && c2!=cx ) continue;
100206 if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
100207 }
100208 }else{
100209 while( (c2 = Utf8Read(zString))!=0 ){
100210 if( c2!=c ) continue;
100211 if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
100212 }
100213 }
100214 return 0;
100215 }
100216 if( c==matchOther ){
100217 if( esc ){
100218 c = sqlite3Utf8Read(&zPattern);
100219 if( c==0 ) return 0;
100220 zEscaped = zPattern;
100221 }else{
100222 u32 prior_c = 0;
@@ -100265,11 +100466,11 @@
100265
100266 /*
100267 ** The sqlite3_strglob() interface.
100268 */
100269 SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlobPattern, const char *zString){
100270 return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
100271 }
100272
100273 /*
100274 ** The sqlite3_strlike() interface.
100275 */
@@ -100303,13 +100504,14 @@
100303 sqlite3_context *context,
100304 int argc,
100305 sqlite3_value **argv
100306 ){
100307 const unsigned char *zA, *zB;
100308 u32 escape = 0;
100309 int nPat;
100310 sqlite3 *db = sqlite3_context_db_handle(context);
 
100311
100312 #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
100313 if( sqlite3_value_type(argv[0])==SQLITE_BLOB
100314 || sqlite3_value_type(argv[1])==SQLITE_BLOB
100315 ){
@@ -100345,17 +100547,17 @@
100345 sqlite3_result_error(context,
100346 "ESCAPE expression must be a single character", -1);
100347 return;
100348 }
100349 escape = sqlite3Utf8Read(&zEsc);
 
 
100350 }
100351 if( zA && zB ){
100352 struct compareInfo *pInfo = sqlite3_user_data(context);
100353 #ifdef SQLITE_TEST
100354 sqlite3_like_count++;
100355 #endif
100356
100357 sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
100358 }
100359 }
100360
100361 /*
@@ -109688,10 +109890,11 @@
109688 int nOBSat; /* Number of ORDER BY terms satisfied by indices */
109689 int iECursor; /* Cursor number for the sorter */
109690 int regReturn; /* Register holding block-output return address */
109691 int labelBkOut; /* Start label for the block-output subroutine */
109692 int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */
 
109693 u8 sortFlags; /* Zero or more SORTFLAG_* bits */
109694 };
109695 #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
109696
109697 /*
@@ -109745,33 +109948,41 @@
109745 Expr *pOffset /* OFFSET value. NULL means no offset */
109746 ){
109747 Select *pNew;
109748 Select standin;
109749 sqlite3 *db = pParse->db;
109750 pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
109751 if( pNew==0 ){
109752 assert( db->mallocFailed );
109753 pNew = &standin;
109754 memset(pNew, 0, sizeof(*pNew));
109755 }
109756 if( pEList==0 ){
109757 pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
109758 }
109759 pNew->pEList = pEList;
 
 
 
 
 
 
 
 
 
 
109760 if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
109761 pNew->pSrc = pSrc;
109762 pNew->pWhere = pWhere;
109763 pNew->pGroupBy = pGroupBy;
109764 pNew->pHaving = pHaving;
109765 pNew->pOrderBy = pOrderBy;
109766 pNew->selFlags = selFlags;
109767 pNew->op = TK_SELECT;
109768 pNew->pLimit = pLimit;
109769 pNew->pOffset = pOffset;
 
109770 assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
109771 pNew->addrOpenEphm[0] = -1;
109772 pNew->addrOpenEphm[1] = -1;
109773 if( db->mallocFailed ) {
109774 clearSelect(db, pNew, pNew!=&standin);
109775 pNew = 0;
109776 }else{
109777 assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -110142,10 +110353,11 @@
110142 int nBase = nExpr + bSeq + nData; /* Fields in sorter record */
110143 int regBase; /* Regs for sorter record */
110144 int regRecord = ++pParse->nMem; /* Assembled sorter record */
110145 int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */
110146 int op; /* Opcode to add sorter record to sorter */
 
110147
110148 assert( bSeq==0 || bSeq==1 );
110149 assert( nData==1 || regData==regOrigData );
110150 if( nPrefixReg ){
110151 assert( nPrefixReg==nExpr+bSeq );
@@ -110152,19 +110364,21 @@
110152 regBase = regData - nExpr - bSeq;
110153 }else{
110154 regBase = pParse->nMem + 1;
110155 pParse->nMem += nBase;
110156 }
 
 
 
110157 sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
110158 SQLITE_ECEL_DUP|SQLITE_ECEL_REF);
110159 if( bSeq ){
110160 sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
110161 }
110162 if( nPrefixReg==0 ){
110163 sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
110164 }
110165
110166 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
110167 if( nOBSat>0 ){
110168 int regPrevKey; /* The first nOBSat columns of the previous row */
110169 int addrFirst; /* Address of the OP_IfNot opcode */
110170 int addrJmp; /* Address of the OP_Jump opcode */
@@ -110195,10 +110409,14 @@
110195 sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
110196 pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
110197 pSort->regReturn = ++pParse->nMem;
110198 sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
110199 sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
 
 
 
 
110200 sqlite3VdbeJumpHere(v, addrFirst);
110201 sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat);
110202 sqlite3VdbeJumpHere(v, addrJmp);
110203 }
110204 if( pSort->sortFlags & SORTFLAG_UseSorter ){
@@ -110205,18 +110423,12 @@
110205 op = OP_SorterInsert;
110206 }else{
110207 op = OP_IdxInsert;
110208 }
110209 sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
110210 if( pSelect->iLimit ){
110211 int addr;
110212 int iLimit;
110213 if( pSelect->iOffset ){
110214 iLimit = pSelect->iOffset+1;
110215 }else{
110216 iLimit = pSelect->iLimit;
110217 }
110218 addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
110219 sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
110220 sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
110221 sqlite3VdbeJumpHere(v, addr);
110222 }
@@ -110816,11 +111028,11 @@
110816 SortCtx *pSort, /* Information on the ORDER BY clause */
110817 int nColumn, /* Number of columns of data */
110818 SelectDest *pDest /* Write the sorted results here */
110819 ){
110820 Vdbe *v = pParse->pVdbe; /* The prepared statement */
110821 int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */
110822 int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
110823 int addr;
110824 int addrOnce = 0;
110825 int iTab;
110826 ExprList *pOrderBy = pSort->pOrderBy;
@@ -110835,10 +111047,11 @@
110835 int bSeq; /* True if sorter record includes seq. no. */
110836 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
110837 struct ExprList_item *aOutEx = p->pEList->a;
110838 #endif
110839
 
110840 if( pSort->labelBkOut ){
110841 sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
110842 sqlite3VdbeGoto(v, addrBreak);
110843 sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
110844 }
@@ -126875,12 +127088,11 @@
126875 testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS );
126876 if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){
126877 Bitmask b = pTabItem->colUsed;
126878 int n = 0;
126879 for(; b; b=b>>1, n++){}
126880 sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1,
126881 SQLITE_INT_TO_PTR(n), P4_INT32);
126882 assert( n<=pTab->nCol );
126883 }
126884 #ifdef SQLITE_ENABLE_CURSOR_HINTS
126885 if( pLoop->u.btree.pIndex!=0 ){
126886 sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete);
@@ -129343,18 +129555,15 @@
129343 ** { ... } // User supplied code
129344 ** #line <lineno> <thisfile>
129345 ** break;
129346 */
129347 /********** Begin reduce actions **********************************************/
129348 case 5: /* explain ::= */
129349 { sqlite3BeginParse(pParse, 0); }
129350 break;
129351 case 6: /* explain ::= EXPLAIN */
129352 { sqlite3BeginParse(pParse, 1); }
129353 break;
129354 case 7: /* explain ::= EXPLAIN QUERY PLAN */
129355 { sqlite3BeginParse(pParse, 2); }
129356 break;
129357 case 8: /* cmdx ::= cmd */
129358 { sqlite3FinishCoding(pParse); }
129359 break;
129360 case 9: /* cmd ::= BEGIN transtype trans_opt */
@@ -130525,10 +130734,11 @@
130525 /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
130526 /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
130527 /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
130528 /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);
130529 /* (4) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==4);
 
130530 /* (10) trans_opt ::= */ yytestcase(yyruleno==10);
130531 /* (11) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==11);
130532 /* (12) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==12);
130533 /* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20);
130534 /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
@@ -135450,10 +135660,13 @@
135450 *(sqlite3_file**)pArg = fd;
135451 rc = SQLITE_OK;
135452 }else if( op==SQLITE_FCNTL_VFS_POINTER ){
135453 *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager);
135454 rc = SQLITE_OK;
 
 
 
135455 }else if( fd->pMethods ){
135456 rc = sqlite3OsFileControl(fd, op, pArg);
135457 }else{
135458 rc = SQLITE_NOTFOUND;
135459 }
@@ -161083,11 +161296,11 @@
161083 */
161084 static void *rbuMalloc(sqlite3rbu *p, int nByte){
161085 void *pRet = 0;
161086 if( p->rc==SQLITE_OK ){
161087 assert( nByte>0 );
161088 pRet = sqlite3_malloc(nByte);
161089 if( pRet==0 ){
161090 p->rc = SQLITE_NOMEM;
161091 }else{
161092 memset(pRet, 0, nByte);
161093 }
@@ -161129,12 +161342,12 @@
161129 static char *rbuStrndup(const char *zStr, int *pRc){
161130 char *zRet = 0;
161131
161132 assert( *pRc==SQLITE_OK );
161133 if( zStr ){
161134 int nCopy = strlen(zStr) + 1;
161135 zRet = (char*)sqlite3_malloc(nCopy);
161136 if( zRet ){
161137 memcpy(zRet, zStr, nCopy);
161138 }else{
161139 *pRc = SQLITE_NOMEM;
161140 }
@@ -162478,11 +162691,11 @@
162478
162479 pRbu->pgsz = iAmt;
162480 if( pRbu->nFrame==pRbu->nFrameAlloc ){
162481 int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2;
162482 RbuFrame *aNew;
162483 aNew = (RbuFrame*)sqlite3_realloc(pRbu->aFrame, nNew * sizeof(RbuFrame));
162484 if( aNew==0 ) return SQLITE_NOMEM;
162485 pRbu->aFrame = aNew;
162486 pRbu->nFrameAlloc = nNew;
162487 }
162488
@@ -162543,11 +162756,11 @@
162543
162544 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
162545 if( nChar==0 ){
162546 return 0;
162547 }
162548 zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) );
162549 if( zWideFilename==0 ){
162550 return 0;
162551 }
162552 memset(zWideFilename, 0, nChar*sizeof(zWideFilename[0]));
162553 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
@@ -163177,15 +163390,16 @@
163177 const char *zTarget,
163178 const char *zRbu,
163179 const char *zState
163180 ){
163181 sqlite3rbu *p;
163182 int nTarget = strlen(zTarget);
163183 int nRbu = strlen(zRbu);
163184 int nState = zState ? strlen(zState) : 0;
 
163185
163186 p = (sqlite3rbu*)sqlite3_malloc(sizeof(sqlite3rbu)+nTarget+1+nRbu+1+nState+1);
163187 if( p ){
163188 RbuState *pState = 0;
163189
163190 /* Create the custom VFS. */
163191 memset(p, 0, sizeof(sqlite3rbu));
@@ -163318,11 +163532,11 @@
163318 ** the pattern "rbu_imp_[0-9]*".
163319 */
163320 static void rbuEditErrmsg(sqlite3rbu *p){
163321 if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){
163322 int i;
163323 int nErrmsg = strlen(p->zErrmsg);
163324 for(i=0; i<(nErrmsg-8); i++){
163325 if( memcmp(&p->zErrmsg[i], "rbu_imp_", 8)==0 ){
163326 int nDel = 8;
163327 while( p->zErrmsg[i+nDel]>='0' && p->zErrmsg[i+nDel]<='9' ) nDel++;
163328 memmove(&p->zErrmsg[i], &p->zErrmsg[i+nDel], nErrmsg + 1 - i - nDel);
@@ -163782,11 +163996,11 @@
163782 ** instead of a file on disk. */
163783 assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
163784 if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){
163785 if( iRegion<=p->nShm ){
163786 int nByte = (iRegion+1) * sizeof(char*);
163787 char **apNew = (char**)sqlite3_realloc(p->apShm, nByte);
163788 if( apNew==0 ){
163789 rc = SQLITE_NOMEM;
163790 }else{
163791 memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm));
163792 p->apShm = apNew;
@@ -163793,11 +164007,11 @@
163793 p->nShm = iRegion+1;
163794 }
163795 }
163796
163797 if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){
163798 char *pNew = (char*)sqlite3_malloc(szRegion);
163799 if( pNew==0 ){
163800 rc = SQLITE_NOMEM;
163801 }else{
163802 memset(pNew, 0, szRegion);
163803 p->apShm[iRegion] = pNew;
@@ -163903,11 +164117,11 @@
163903 /* A main database has just been opened. The following block sets
163904 ** (pFd->zWal) to point to a buffer owned by SQLite that contains
163905 ** the name of the *-wal file this db connection will use. SQLite
163906 ** happens to pass a pointer to this buffer when using xAccess()
163907 ** or xOpen() to operate on the *-wal file. */
163908 int n = strlen(zName);
163909 const char *z = &zName[n];
163910 if( flags & SQLITE_OPEN_URI ){
163911 int odd = 0;
163912 while( 1 ){
163913 if( z[0]==0 ){
@@ -163929,12 +164143,12 @@
163929 if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
163930 /* This call is to open a *-wal file. Intead, open the *-oal. This
163931 ** code ensures that the string passed to xOpen() is terminated by a
163932 ** pair of '\0' bytes in case the VFS attempts to extract a URI
163933 ** parameter from it. */
163934 int nCopy = strlen(zName);
163935 char *zCopy = sqlite3_malloc(nCopy+2);
163936 if( zCopy ){
163937 memcpy(zCopy, zName, nCopy);
163938 zCopy[nCopy-3] = 'o';
163939 zCopy[nCopy] = '\0';
163940 zCopy[nCopy+1] = '\0';
@@ -164159,17 +164373,17 @@
164159 0, /* xCurrentTimeInt64 (version 2) */
164160 0, 0, 0 /* Unimplemented version 3 methods */
164161 };
164162
164163 rbu_vfs *pNew = 0; /* Newly allocated VFS */
164164 int nName;
164165 int rc = SQLITE_OK;
 
 
164166
164167 int nByte;
164168 nName = strlen(zName);
164169 nByte = sizeof(rbu_vfs) + nName + 1;
164170 pNew = (rbu_vfs*)sqlite3_malloc(nByte);
164171 if( pNew==0 ){
164172 rc = SQLITE_NOMEM;
164173 }else{
164174 sqlite3_vfs *pParent; /* Parent VFS */
164175 memset(pNew, 0, nByte);
@@ -167174,10 +167388,13 @@
167174 ** If parameter iCol is greater than or equal to the number of columns
167175 ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
167176 ** an OOM condition or IO error), an appropriate SQLite error code is
167177 ** returned.
167178 **
 
 
 
167179 ** xColumnText:
167180 ** This function attempts to retrieve the text of column iCol of the
167181 ** current document. If successful, (*pz) is set to point to a buffer
167182 ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
167183 ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -167194,18 +167411,32 @@
167194 ** xInstCount:
167195 ** Set *pnInst to the total number of occurrences of all phrases within
167196 ** the query within the current row. Return SQLITE_OK if successful, or
167197 ** an error code (i.e. SQLITE_NOMEM) if an error occurs.
167198 **
 
 
 
 
 
167199 ** xInst:
167200 ** Query for the details of phrase match iIdx within the current row.
167201 ** Phrase matches are numbered starting from zero, so the iIdx argument
167202 ** should be greater than or equal to zero and smaller than the value
167203 ** output by xInstCount().
 
 
 
 
 
 
167204 **
167205 ** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
167206 ** if an error occurs.
 
 
 
167207 **
167208 ** xRowid:
167209 ** Returns the rowid of the current row.
167210 **
167211 ** xTokenize:
@@ -167286,25 +167517,63 @@
167286 ** through instances of phrase iPhrase, use the following code:
167287 **
167288 ** Fts5PhraseIter iter;
167289 ** int iCol, iOff;
167290 ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
167291 ** iOff>=0;
167292 ** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
167293 ** ){
167294 ** // An instance of phrase iPhrase at offset iOff of column iCol
167295 ** }
167296 **
167297 ** The Fts5PhraseIter structure is defined above. Applications should not
167298 ** modify this structure directly - it should only be used as shown above
167299 ** with the xPhraseFirst() and xPhraseNext() API methods.
 
 
 
 
 
 
 
167300 **
167301 ** xPhraseNext()
167302 ** See xPhraseFirst above.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167303 */
167304 struct Fts5ExtensionApi {
167305 int iVersion; /* Currently always set to 1 */
167306
167307 void *(*xUserData)(Fts5Context*);
167308
167309 int (*xColumnCount)(Fts5Context*);
167310 int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -167330,12 +167599,15 @@
167330 int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
167331 );
167332 int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
167333 void *(*xGetAuxdata)(Fts5Context*, int bClear);
167334
167335 void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
167336 void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
 
 
 
167337 };
167338
167339 /*
167340 ** CUSTOM AUXILIARY FUNCTIONS
167341 *************************************************************************/
@@ -167762,10 +168034,11 @@
167762 int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */
167763 int eContent; /* An FTS5_CONTENT value */
167764 char *zContent; /* content table */
167765 char *zContentRowid; /* "content_rowid=" option value */
167766 int bColumnsize; /* "columnsize=" option value (dflt==1) */
 
167767 char *zContentExprlist;
167768 Fts5Tokenizer *pTok;
167769 fts5_tokenizer *pTokApi;
167770
167771 /* Values loaded from the %_config table */
@@ -167790,10 +168063,13 @@
167790
167791 #define FTS5_CONTENT_NORMAL 0
167792 #define FTS5_CONTENT_NONE 1
167793 #define FTS5_CONTENT_EXTERNAL 2
167794
 
 
 
167795
167796
167797
167798 static int sqlite3Fts5ConfigParse(
167799 Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
@@ -167903,10 +168179,17 @@
167903 static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
167904
167905 /* Character set tests (like isspace(), isalpha() etc.) */
167906 static int sqlite3Fts5IsBareword(char t);
167907
 
 
 
 
 
 
 
167908 /*
167909 ** End of interface to code in fts5_buffer.c.
167910 **************************************************************************/
167911
167912 /**************************************************************************
@@ -168024,11 +168307,10 @@
168024 static int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);
168025
168026 /*
168027 ** Functions called by the storage module as part of integrity-check.
168028 */
168029 static u64 sqlite3Fts5IndexCksum(Fts5Config*,i64,int,int,const char*,int);
168030 static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
168031
168032 /*
168033 ** Called during virtual module initialization to register UDF
168034 ** fts5_decode() with SQLite
@@ -168046,10 +168328,12 @@
168046 static int sqlite3Fts5IndexReinit(Fts5Index *p);
168047 static int sqlite3Fts5IndexOptimize(Fts5Index *p);
168048 static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge);
168049
168050 static int sqlite3Fts5IndexLoadConfig(Fts5Index *p);
 
 
168051
168052 /*
168053 ** End of interface to code in fts5_index.c.
168054 **************************************************************************/
168055
@@ -168103,11 +168387,11 @@
168103 typedef struct Fts5Hash Fts5Hash;
168104
168105 /*
168106 ** Create a hash table, free a hash table.
168107 */
168108 static int sqlite3Fts5HashNew(Fts5Hash**, int *pnSize);
168109 static void sqlite3Fts5HashFree(Fts5Hash*);
168110
168111 static int sqlite3Fts5HashWrite(
168112 Fts5Hash*,
168113 i64 iRowid, /* Rowid for this entry */
@@ -168239,12 +168523,22 @@
168239 static int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);
168240
168241 static int sqlite3Fts5ExprPhraseCount(Fts5Expr*);
168242 static int sqlite3Fts5ExprPhraseSize(Fts5Expr*, int iPhrase);
168243 static int sqlite3Fts5ExprPoslist(Fts5Expr*, int, const u8 **);
 
 
 
 
 
 
 
 
168244
168245 static int sqlite3Fts5ExprClonePhrase(Fts5Config*, Fts5Expr*, int, Fts5Expr**);
 
 
168246
168247 /*******************************************
168248 ** The fts5_expr.c API above this point is used by the other hand-written
168249 ** C code in this module. The interfaces below this point are called by
168250 ** the parser code in fts5parse.y. */
@@ -170397,10 +170691,93 @@
170397
170398 return (t & 0x80) || aBareword[(int)t];
170399 }
170400
170401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170402
170403 /*
170404 ** 2014 Jun 09
170405 **
170406 ** The author disclaims copyright to this source code. In place of
@@ -170412,11 +170789,10 @@
170412 **
170413 ******************************************************************************
170414 **
170415 ** This is an SQLite module implementing full-text search.
170416 */
170417
170418
170419
170420 /* #include "fts5Int.h" */
170421
170422 #define FTS5_DEFAULT_PAGE_SIZE 4050
@@ -170595,10 +170971,37 @@
170595 if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
170596 fts5Dequote(z);
170597 }
170598 }
170599
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170600 /*
170601 ** Parse a "special" CREATE VIRTUAL TABLE directive and update
170602 ** configuration object pConfig as appropriate.
170603 **
170604 ** If successful, object pConfig is updated and SQLITE_OK returned. If
@@ -170744,10 +171147,24 @@
170744 }else{
170745 pConfig->bColumnsize = (zArg[0]=='1');
170746 }
170747 return rc;
170748 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170749
170750 *pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
170751 return SQLITE_ERROR;
170752 }
170753
@@ -170900,10 +171317,11 @@
170900 pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
170901 pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
170902 pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
170903 pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
170904 pRet->bColumnsize = 1;
 
170905 #ifdef SQLITE_DEBUG
170906 pRet->bPrefixIndex = 1;
170907 #endif
170908 if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){
170909 *pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName);
@@ -171346,10 +171764,11 @@
171346 #endif
171347
171348
171349 struct Fts5Expr {
171350 Fts5Index *pIndex;
 
171351 Fts5ExprNode *pRoot;
171352 int bDesc; /* Iterate in descending rowid order */
171353 int nPhrase; /* Number of phrases in expression */
171354 Fts5ExprPhrase **apExprPhrase; /* Pointers to phrase objects */
171355 };
@@ -171541,10 +171960,11 @@
171541 sParse.rc = SQLITE_NOMEM;
171542 sqlite3Fts5ParseNodeFree(sParse.pExpr);
171543 }else{
171544 pNew->pRoot = sParse.pExpr;
171545 pNew->pIndex = 0;
 
171546 pNew->apExprPhrase = sParse.apPhrase;
171547 pNew->nPhrase = sParse.nPhrase;
171548 sParse.apPhrase = 0;
171549 }
171550 }
@@ -171605,12 +172025,13 @@
171605 }
171606
171607 /*
171608 ** Argument pTerm must be a synonym iterator.
171609 */
171610 static int fts5ExprSynonymPoslist(
171611 Fts5ExprTerm *pTerm,
 
171612 Fts5Colset *pColset,
171613 i64 iRowid,
171614 int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */
171615 u8 **pa, int *pn
171616 ){
@@ -171625,13 +172046,20 @@
171625 for(p=pTerm; p; p=p->pSynonym){
171626 Fts5IndexIter *pIter = p->pIter;
171627 if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){
171628 const u8 *a;
171629 int n;
171630 i64 dummy;
171631 rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy);
 
 
 
 
 
 
171632 if( rc!=SQLITE_OK ) goto synonym_poslist_out;
 
171633 if( nIter==nAlloc ){
171634 int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
171635 Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
171636 if( aNew==0 ){
171637 rc = SQLITE_NOMEM;
@@ -171728,12 +172156,12 @@
171728 i64 dummy;
171729 int n = 0;
171730 int bFlag = 0;
171731 const u8 *a = 0;
171732 if( pTerm->pSynonym ){
171733 rc = fts5ExprSynonymPoslist(
171734 pTerm, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n
171735 );
171736 }else{
171737 rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy);
171738 }
171739 if( rc!=SQLITE_OK ) goto ismatch_out;
@@ -172063,34 +172491,55 @@
172063 Fts5Expr *pExpr, /* Expression that pNear is a part of */
172064 Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */
172065 ){
172066 Fts5ExprNearset *pNear = pNode->pNear;
172067 int rc = *pRc;
172068 int i;
172069
172070 /* Check that each phrase in the nearset matches the current row.
172071 ** Populate the pPhrase->poslist buffers at the same time. If any
172072 ** phrase is not a match, break out of the loop early. */
172073 for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
172074 Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
172075 if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){
172076 int bMatch = 0;
172077 rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch);
172078 if( bMatch==0 ) break;
172079 }else{
172080 rc = sqlite3Fts5IterPoslistBuffer(
172081 pPhrase->aTerm[0].pIter, &pPhrase->poslist
172082 );
172083 }
172084 }
172085
172086 *pRc = rc;
172087 if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){
172088 return 1;
172089 }
172090
172091 return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172092 }
172093
172094 static int fts5ExprTokenTest(
172095 Fts5Expr *pExpr, /* Expression that pNear is a part of */
172096 Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */
@@ -172524,10 +172973,13 @@
172524 if( cmp || p2->bNomatch ) break;
172525 rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
172526 }
172527 pNode->bEof = p1->bEof;
172528 pNode->iRowid = p1->iRowid;
 
 
 
172529 break;
172530 }
172531 }
172532 }
172533 return rc;
@@ -172909,10 +173361,11 @@
172909 }
172910
172911 if( rc==SQLITE_OK ){
172912 /* All the allocations succeeded. Put the expression object together. */
172913 pNew->pIndex = pExpr->pIndex;
 
172914 pNew->nPhrase = 1;
172915 pNew->apExprPhrase[0] = sCtx.pPhrase;
172916 pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
172917 pNew->pRoot->pNear->nPhrase = 1;
172918 sCtx.pPhrase->pNode = pNew->pRoot;
@@ -173050,10 +173503,19 @@
173050 static void sqlite3Fts5ParseSetColset(
173051 Fts5Parse *pParse,
173052 Fts5ExprNearset *pNear,
173053 Fts5Colset *pColset
173054 ){
 
 
 
 
 
 
 
 
 
173055 if( pNear ){
173056 pNear->pColset = pColset;
173057 }else{
173058 sqlite3_free(pColset);
173059 }
@@ -173111,15 +173573,24 @@
173111 if( eType==FTS5_STRING ){
173112 int iPhrase;
173113 for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
173114 pNear->apPhrase[iPhrase]->pNode = pRet;
173115 }
173116 if( pNear->nPhrase==1
173117 && pNear->apPhrase[0]->nTerm==1
173118 && pNear->apPhrase[0]->aTerm[0].pSynonym==0
173119 ){
173120 pRet->eType = FTS5_TERM;
 
 
 
 
 
 
 
 
 
173121 }
173122 }else{
173123 fts5ExprAddChildren(pRet, pLeft);
173124 fts5ExprAddChildren(pRet, pRight);
173125 }
@@ -173229,10 +173700,13 @@
173229
173230 zRet = fts5PrintfAppend(zRet, " {");
173231 for(iTerm=0; zRet && iTerm<pPhrase->nTerm; iTerm++){
173232 char *zTerm = pPhrase->aTerm[iTerm].zTerm;
173233 zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm);
 
 
 
173234 }
173235
173236 if( zRet ) zRet = fts5PrintfAppend(zRet, "}");
173237 if( zRet==0 ) return 0;
173238 }
@@ -173541,10 +174015,237 @@
173541 *pa = 0;
173542 nRet = 0;
173543 }
173544 return nRet;
173545 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173546
173547 /*
173548 ** 2014 August 11
173549 **
173550 ** The author disclaims copyright to this source code. In place of
@@ -173570,10 +174271,11 @@
173570 ** segment.
173571 */
173572
173573
173574 struct Fts5Hash {
 
173575 int *pnByte; /* Pointer to bytes counter */
173576 int nEntry; /* Number of entries currently in hash */
173577 int nSlot; /* Size of aSlot[] array */
173578 Fts5HashEntry *pScan; /* Current ordered scan item */
173579 Fts5HashEntry **aSlot; /* Array of hash slots */
@@ -173606,10 +174308,11 @@
173606
173607 int nAlloc; /* Total size of allocation */
173608 int iSzPoslist; /* Offset of space for 4-byte poslist size */
173609 int nData; /* Total bytes of data (incl. structure) */
173610 u8 bDel; /* Set delete-flag @ iSzPoslist */
 
173611
173612 int iCol; /* Column of last value written */
173613 int iPos; /* Position of last value written */
173614 i64 iRowid; /* Rowid of last value written */
173615 char zKey[8]; /* Nul-terminated entry key */
@@ -173623,11 +174326,11 @@
173623
173624
173625 /*
173626 ** Allocate a new hash table.
173627 */
173628 static int sqlite3Fts5HashNew(Fts5Hash **ppNew, int *pnByte){
173629 int rc = SQLITE_OK;
173630 Fts5Hash *pNew;
173631
173632 *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash));
173633 if( pNew==0 ){
@@ -173634,10 +174337,11 @@
173634 rc = SQLITE_NOMEM;
173635 }else{
173636 int nByte;
173637 memset(pNew, 0, sizeof(Fts5Hash));
173638 pNew->pnByte = pnByte;
 
173639
173640 pNew->nSlot = 1024;
173641 nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
173642 pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
173643 if( pNew->aSlot==0 ){
@@ -173726,30 +174430,50 @@
173726 pHash->nSlot = nNew;
173727 pHash->aSlot = apNew;
173728 return SQLITE_OK;
173729 }
173730
173731 static void fts5HashAddPoslistSize(Fts5HashEntry *p){
173732 if( p->iSzPoslist ){
173733 u8 *pPtr = (u8*)p;
173734 int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */
173735 int nPos = nSz*2 + p->bDel; /* Value of nPos field */
173736
173737 assert( p->bDel==0 || p->bDel==1 );
173738 if( nPos<=127 ){
173739 pPtr[p->iSzPoslist] = (u8)nPos;
173740 }else{
173741 int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
173742 memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
173743 sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos);
173744 p->nData += (nByte-1);
173745 }
173746 p->bDel = 0;
 
 
 
 
 
 
 
 
 
 
173747 p->iSzPoslist = 0;
 
 
173748 }
173749 }
173750
 
 
 
 
 
 
 
 
173751 static int sqlite3Fts5HashWrite(
173752 Fts5Hash *pHash,
173753 i64 iRowid, /* Rowid for this entry */
173754 int iCol, /* Column token appears in (-ve -> delete) */
173755 int iPos, /* Position of token within column */
@@ -173758,10 +174482,13 @@
173758 ){
173759 unsigned int iHash;
173760 Fts5HashEntry *p;
173761 u8 *pPtr;
173762 int nIncr = 0; /* Amount to increment (*pHash->pnByte) by */
 
 
 
173763
173764 /* Attempt to locate an existing hash entry */
173765 iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
173766 for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
173767 if( p->zKey[0]==bByte
@@ -173772,92 +174499,120 @@
173772 }
173773 }
173774
173775 /* If an existing hash entry cannot be found, create a new one. */
173776 if( p==0 ){
 
173777 int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64;
173778 if( nByte<128 ) nByte = 128;
173779
 
173780 if( (pHash->nEntry*2)>=pHash->nSlot ){
173781 int rc = fts5HashResize(pHash);
173782 if( rc!=SQLITE_OK ) return rc;
173783 iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
173784 }
173785
 
173786 p = (Fts5HashEntry*)sqlite3_malloc(nByte);
173787 if( !p ) return SQLITE_NOMEM;
173788 memset(p, 0, FTS5_HASHENTRYSIZE);
173789 p->nAlloc = nByte;
173790 p->zKey[0] = bByte;
173791 memcpy(&p->zKey[1], pToken, nToken);
173792 assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) );
173793 p->zKey[nToken+1] = '\0';
173794 p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE;
173795 p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid);
173796 p->iSzPoslist = p->nData;
173797 p->nData += 1;
173798 p->iRowid = iRowid;
173799 p->pHashNext = pHash->aSlot[iHash];
173800 pHash->aSlot[iHash] = p;
173801 pHash->nEntry++;
 
 
 
 
 
 
 
 
 
 
 
173802 nIncr += p->nData;
173803 }
173804
173805 /* Check there is enough space to append a new entry. Worst case scenario
173806 ** is:
173807 **
173808 ** + 9 bytes for a new rowid,
173809 ** + 4 byte reserved for the "poslist size" varint.
173810 ** + 1 byte for a "new column" byte,
173811 ** + 3 bytes for a new column number (16-bit max) as a varint,
173812 ** + 5 bytes for the new position offset (32-bit max).
173813 */
173814 if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
173815 int nNew = p->nAlloc * 2;
173816 Fts5HashEntry *pNew;
173817 Fts5HashEntry **pp;
173818 pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
173819 if( pNew==0 ) return SQLITE_NOMEM;
173820 pNew->nAlloc = nNew;
173821 for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
173822 *pp = pNew;
173823 p = pNew;
173824 }
173825 pPtr = (u8*)p;
173826 nIncr -= p->nData;
 
 
 
 
173827
173828 /* If this is a new rowid, append the 4-byte size field for the previous
173829 ** entry, and the new rowid for this entry. */
173830 if( iRowid!=p->iRowid ){
173831 fts5HashAddPoslistSize(p);
173832 p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
 
 
173833 p->iSzPoslist = p->nData;
173834 p->nData += 1;
173835 p->iCol = 0;
173836 p->iPos = 0;
173837 p->iRowid = iRowid;
 
173838 }
173839
173840 if( iCol>=0 ){
173841 /* Append a new column value, if necessary */
173842 assert( iCol>=p->iCol );
173843 if( iCol!=p->iCol ){
173844 pPtr[p->nData++] = 0x01;
173845 p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
173846 p->iCol = iCol;
173847 p->iPos = 0;
173848 }
173849
173850 /* Append the new position offset */
173851 p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iPos - p->iPos + 2);
173852 p->iPos = iPos;
 
 
 
 
 
 
 
 
 
 
 
173853 }else{
173854 /* This is a delete. Set the delete flag. */
173855 p->bDel = 1;
173856 }
 
173857 nIncr += p->nData;
173858
173859 *pHash->pnByte += nIncr;
173860 return SQLITE_OK;
173861 }
173862
173863
@@ -173967,11 +174722,11 @@
173967 for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
173968 if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break;
173969 }
173970
173971 if( p ){
173972 fts5HashAddPoslistSize(p);
173973 *ppDoclist = (const u8*)&p->zKey[nTerm+1];
173974 *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
173975 }else{
173976 *ppDoclist = 0;
173977 *pnDoclist = 0;
@@ -174003,11 +174758,11 @@
174003 int *pnDoclist /* OUT: size of doclist in bytes */
174004 ){
174005 Fts5HashEntry *p;
174006 if( (p = pHash->pScan) ){
174007 int nTerm = (int)strlen(p->zKey);
174008 fts5HashAddPoslistSize(p);
174009 *pzTerm = p->zKey;
174010 *ppDoclist = (const u8*)&p->zKey[nTerm+1];
174011 *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
174012 }else{
174013 *pzTerm = 0;
@@ -174450,10 +175205,13 @@
174450 int iLeafPgno; /* Current leaf page number */
174451 Fts5Data *pLeaf; /* Current leaf data */
174452 Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
174453 int iLeafOffset; /* Byte offset within current leaf */
174454
 
 
 
174455 /* The page and offset from which the current term was read. The offset
174456 ** is the offset of the first rowid in the current doclist. */
174457 int iTermLeafPgno;
174458 int iTermLeafOffset;
174459
@@ -174469,11 +175227,11 @@
174469
174470 /* Variables populated based on current entry. */
174471 Fts5Buffer term; /* Current term */
174472 i64 iRowid; /* Current rowid */
174473 int nPos; /* Number of bytes in current position list */
174474 int bDel; /* True if the delete flag is set */
174475 };
174476
174477 /*
174478 ** Argument is a pointer to an Fts5Data structure that contains a
174479 ** leaf page.
@@ -174482,11 +175240,10 @@
174482 (x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \
174483 )
174484
174485 #define FTS5_SEGITER_ONETERM 0x01
174486 #define FTS5_SEGITER_REVERSE 0x02
174487
174488
174489 /*
174490 ** Argument is a pointer to an Fts5Data structure that contains a leaf
174491 ** page. This macro evaluates to true if the leaf contains no terms, or
174492 ** false if it contains at least one term.
@@ -175509,17 +176266,33 @@
175509 ** position list content (if any).
175510 */
175511 static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
175512 if( p->rc==SQLITE_OK ){
175513 int iOff = pIter->iLeafOffset; /* Offset to read at */
175514 int nSz;
175515 ASSERT_SZLEAF_OK(pIter->pLeaf);
175516 fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz);
175517 pIter->bDel = (nSz & 0x0001);
175518 pIter->nPos = nSz>>1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175519 pIter->iLeafOffset = iOff;
175520 assert_nc( pIter->nPos>=0 );
175521 }
175522 }
175523
175524 static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
175525 u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
@@ -175575,10 +176348,24 @@
175575 pIter->iEndofDoclist += nExtra;
175576 }
175577
175578 fts5SegIterLoadRowid(p, pIter);
175579 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175580
175581 /*
175582 ** Initialize the iterator object pIter to iterate through the entries in
175583 ** segment pSeg. The iterator is left pointing to the first entry when
175584 ** this function returns.
@@ -175601,10 +176388,11 @@
175601 return;
175602 }
175603
175604 if( p->rc==SQLITE_OK ){
175605 memset(pIter, 0, sizeof(*pIter));
 
175606 pIter->pSeg = pSeg;
175607 pIter->iLeafPgno = pSeg->pgnoFirst-1;
175608 fts5SegIterNextPage(p, pIter);
175609 }
175610
@@ -175632,10 +176420,11 @@
175632 ** aRowidOffset[] and iRowidOffset variables. At this point the iterator
175633 ** is in its regular state - Fts5SegIter.iLeafOffset points to the first
175634 ** byte of the position list content associated with said rowid.
175635 */
175636 static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
 
175637 int n = pIter->pLeaf->szLeaf;
175638 int i = pIter->iLeafOffset;
175639 u8 *a = pIter->pLeaf->p;
175640 int iRowidOffset = 0;
175641
@@ -175644,19 +176433,28 @@
175644 }
175645
175646 ASSERT_SZLEAF_OK(pIter->pLeaf);
175647 while( 1 ){
175648 i64 iDelta = 0;
175649 int nPos;
175650 int bDummy;
175651
175652 i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
175653 i += nPos;
 
 
 
 
 
 
 
 
 
 
175654 if( i>=n ) break;
175655 i += fts5GetVarint(&a[i], (u64*)&iDelta);
175656 pIter->iRowid += iDelta;
175657
 
175658 if( iRowidOffset>=pIter->nRowidOffset ){
175659 int nNew = pIter->nRowidOffset + 8;
175660 int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
175661 if( aNew==0 ){
175662 p->rc = SQLITE_NOMEM;
@@ -175730,10 +176528,112 @@
175730 */
175731 static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5IndexIter *pIter){
175732 Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
175733 return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0);
175734 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175735
175736 /*
175737 ** Advance iterator pIter to the next entry.
175738 **
175739 ** If an error occurs, Fts5Index.rc is set to an appropriate error code. It
@@ -175743,144 +176643,133 @@
175743 static void fts5SegIterNext(
175744 Fts5Index *p, /* FTS5 backend object */
175745 Fts5SegIter *pIter, /* Iterator to advance */
175746 int *pbNewTerm /* OUT: Set for new term */
175747 ){
175748 assert( pbNewTerm==0 || *pbNewTerm==0 );
175749 if( p->rc==SQLITE_OK ){
175750 if( pIter->flags & FTS5_SEGITER_REVERSE ){
175751 assert( pIter->pNextLeaf==0 );
175752 if( pIter->iRowidOffset>0 ){
175753 u8 *a = pIter->pLeaf->p;
175754 int iOff;
175755 int nPos;
175756 int bDummy;
175757 i64 iDelta;
175758
175759 pIter->iRowidOffset--;
175760 pIter->iLeafOffset = iOff = pIter->aRowidOffset[pIter->iRowidOffset];
175761 iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDummy);
175762 iOff += nPos;
175763 fts5GetVarint(&a[iOff], (u64*)&iDelta);
175764 pIter->iRowid -= iDelta;
175765 fts5SegIterLoadNPos(p, pIter);
175766 }else{
175767 fts5SegIterReverseNewPage(p, pIter);
175768 }
175769 }else{
175770 Fts5Data *pLeaf = pIter->pLeaf;
175771 int iOff;
175772 int bNewTerm = 0;
175773 int nKeep = 0;
175774
175775 /* Search for the end of the position list within the current page. */
175776 u8 *a = pLeaf->p;
175777 int n = pLeaf->szLeaf;
175778
175779 ASSERT_SZLEAF_OK(pLeaf);
175780 iOff = pIter->iLeafOffset + pIter->nPos;
175781
175782 if( iOff<n ){
175783 /* The next entry is on the current page. */
175784 assert_nc( iOff<=pIter->iEndofDoclist );
175785 if( iOff>=pIter->iEndofDoclist ){
175786 bNewTerm = 1;
175787 if( iOff!=fts5LeafFirstTermOff(pLeaf) ){
175788 iOff += fts5GetVarint32(&a[iOff], nKeep);
175789 }
175790 }else{
175791 u64 iDelta;
175792 iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta);
175793 pIter->iRowid += iDelta;
175794 assert_nc( iDelta>0 );
175795 }
175796 pIter->iLeafOffset = iOff;
175797
175798 }else if( pIter->pSeg==0 ){
175799 const u8 *pList = 0;
175800 const char *zTerm = 0;
175801 int nList = 0;
175802 assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
175803 if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
175804 sqlite3Fts5HashScanNext(p->pHash);
175805 sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
175806 }
175807 if( pList==0 ){
175808 fts5DataRelease(pIter->pLeaf);
175809 pIter->pLeaf = 0;
175810 }else{
175811 pIter->pLeaf->p = (u8*)pList;
175812 pIter->pLeaf->nn = nList;
175813 pIter->pLeaf->szLeaf = nList;
175814 pIter->iEndofDoclist = nList+1;
175815 sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm),
175816 (u8*)zTerm);
175817 pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
175818 *pbNewTerm = 1;
175819 }
175820 }else{
175821 iOff = 0;
175822 /* Next entry is not on the current page */
175823 while( iOff==0 ){
175824 fts5SegIterNextPage(p, pIter);
175825 pLeaf = pIter->pLeaf;
175826 if( pLeaf==0 ) break;
175827 ASSERT_SZLEAF_OK(pLeaf);
175828 if( (iOff = fts5LeafFirstRowidOff(pLeaf)) && iOff<pLeaf->szLeaf ){
175829 iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid);
175830 pIter->iLeafOffset = iOff;
175831
175832 if( pLeaf->nn>pLeaf->szLeaf ){
175833 pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
175834 &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist
175835 );
175836 }
175837
175838 }
175839 else if( pLeaf->nn>pLeaf->szLeaf ){
175840 pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
175841 &pLeaf->p[pLeaf->szLeaf], iOff
175842 );
175843 pIter->iLeafOffset = iOff;
175844 pIter->iEndofDoclist = iOff;
175845 bNewTerm = 1;
175846 }
175847 if( iOff>=pLeaf->szLeaf ){
175848 p->rc = FTS5_CORRUPT;
175849 return;
175850 }
175851 }
175852 }
175853
175854 /* Check if the iterator is now at EOF. If so, return early. */
175855 if( pIter->pLeaf ){
175856 if( bNewTerm ){
175857 if( pIter->flags & FTS5_SEGITER_ONETERM ){
175858 fts5DataRelease(pIter->pLeaf);
175859 pIter->pLeaf = 0;
175860 }else{
175861 fts5SegIterLoadTerm(p, pIter, nKeep);
175862 fts5SegIterLoadNPos(p, pIter);
175863 if( pbNewTerm ) *pbNewTerm = 1;
175864 }
175865 }else{
175866 /* The following could be done by calling fts5SegIterLoadNPos(). But
175867 ** this block is particularly performance critical, so equivalent
175868 ** code is inlined. */
175869 int nSz;
175870 assert( p->rc==SQLITE_OK );
175871 fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
175872 pIter->bDel = (nSz & 0x0001);
175873 pIter->nPos = nSz>>1;
175874 assert_nc( pIter->nPos>=0 );
175875 }
175876 }
175877 }
175878 }
175879 }
175880
175881 #define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; }
 
 
 
 
 
175882
175883 /*
175884 ** Iterator pIter currently points to the first rowid in a doclist. This
175885 ** function sets the iterator up so that iterates in reverse order through
175886 ** the doclist.
@@ -175898,11 +176787,21 @@
175898 Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
175899
175900 /* Currently, Fts5SegIter.iLeafOffset points to the first byte of
175901 ** position-list content for the current rowid. Back it up so that it
175902 ** points to the start of the position-list size field. */
175903 pIter->iLeafOffset -= sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel);
 
 
 
 
 
 
 
 
 
 
175904
175905 /* If this condition is true then the largest rowid for the current
175906 ** term may not be stored on the current page. So search forward to
175907 ** see where said rowid really is. */
175908 if( pIter->iEndofDoclist>=pLeaf->szLeaf ){
@@ -175982,15 +176881,10 @@
175982 }
175983
175984 pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
175985 }
175986
175987 #define fts5IndexSkipVarint(a, iOff) { \
175988 int iEnd = iOff+9; \
175989 while( (a[iOff++] & 0x80) && iOff<iEnd ); \
175990 }
175991
175992 /*
175993 ** The iterator object passed as the second argument currently contains
175994 ** no valid values except for the Fts5SegIter.pLeaf member variable. This
175995 ** function searches the leaf page for a term matching (pTerm/nTerm).
175996 **
@@ -176189,10 +177083,12 @@
176189 fts5SegIterReverse(p, pIter);
176190 }
176191 }
176192 }
176193
 
 
176194 /* Either:
176195 **
176196 ** 1) an error has occurred, or
176197 ** 2) the iterator points to EOF, or
176198 ** 3) the iterator points to an entry with term (pTerm/nTerm), or
@@ -176246,19 +177142,21 @@
176246 if( pLeaf==0 ) return;
176247 pLeaf->p = (u8*)pList;
176248 pLeaf->nn = pLeaf->szLeaf = nList;
176249 pIter->pLeaf = pLeaf;
176250 pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
176251 pIter->iEndofDoclist = pLeaf->nn+1;
176252
176253 if( flags & FTS5INDEX_QUERY_DESC ){
176254 pIter->flags |= FTS5_SEGITER_REVERSE;
176255 fts5SegIterReverseInitPage(p, pIter);
176256 }else{
176257 fts5SegIterLoadNPos(p, pIter);
176258 }
176259 }
 
 
176260 }
176261
176262 /*
176263 ** Zero the iterator passed as the only argument.
176264 */
@@ -176498,11 +177396,11 @@
176498 bMove = 0;
176499 }
176500 }
176501
176502 do{
176503 if( bMove ) fts5SegIterNext(p, pIter, 0);
176504 if( pIter->pLeaf==0 ) break;
176505 if( bRev==0 && pIter->iRowid>=iMatch ) break;
176506 if( bRev!=0 && pIter->iRowid<=iMatch ) break;
176507 bMove = 1;
176508 }while( p->rc==SQLITE_OK );
@@ -176532,11 +177430,13 @@
176532 ){
176533 int i;
176534 for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){
176535 int iEq;
176536 if( (iEq = fts5MultiIterDoCompare(pIter, i)) ){
176537 fts5SegIterNext(p, &pIter->aSeg[iEq], 0);
 
 
176538 i = pIter->nSeg + iEq;
176539 }
176540 }
176541 }
176542
@@ -176619,11 +177519,11 @@
176619 Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
176620 assert( p->rc==SQLITE_OK );
176621 if( bUseFrom && pSeg->pDlidx ){
176622 fts5SegIterNextFrom(p, pSeg, iFrom);
176623 }else{
176624 fts5SegIterNext(p, pSeg, &bNewTerm);
176625 }
176626
176627 if( pSeg->pLeaf==0 || bNewTerm
176628 || fts5MultiIterAdvanceRowid(p, pIter, iFirst)
176629 ){
@@ -176647,11 +177547,12 @@
176647 do {
176648 int iFirst = pIter->aFirst[1].iFirst;
176649 Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
176650 int bNewTerm = 0;
176651
176652 fts5SegIterNext(p, pSeg, &bNewTerm);
 
176653 if( pSeg->pLeaf==0 || bNewTerm
176654 || fts5MultiIterAdvanceRowid(p, pIter, iFirst)
176655 ){
176656 fts5MultiIterAdvanced(p, pIter, iFirst, 1);
176657 fts5MultiIterSetEof(pIter);
@@ -176767,11 +177668,12 @@
176767 ** object and set the output variable to NULL. */
176768 if( p->rc==SQLITE_OK ){
176769 for(iIter=pNew->nSeg-1; iIter>0; iIter--){
176770 int iEq;
176771 if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){
176772 fts5SegIterNext(p, &pNew->aSeg[iEq], 0);
 
176773 fts5MultiIterAdvanced(p, pNew, iEq, iIter);
176774 }
176775 }
176776 fts5MultiIterSetEof(pNew);
176777 fts5AssertMultiIterSetup(p, pNew);
@@ -176817,10 +177719,11 @@
176817 }
176818 pData = 0;
176819 }else{
176820 pNew->bEof = 1;
176821 }
 
176822
176823 *ppOut = pNew;
176824 }
176825
176826 fts5DataRelease(pData);
@@ -176885,10 +177788,13 @@
176885 Fts5Data *pData = 0;
176886 u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset];
176887 int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset);
176888 int pgno = pSeg->iLeafPgno;
176889 int pgnoSave = 0;
 
 
 
176890
176891 if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
176892 pgnoSave = pgno+1;
176893 }
176894
@@ -177309,12 +178215,11 @@
177309 ** Append a rowid and position-list size field to the writers output.
177310 */
177311 static void fts5WriteAppendRowid(
177312 Fts5Index *p,
177313 Fts5SegWriter *pWriter,
177314 i64 iRowid,
177315 int nPos
177316 ){
177317 if( p->rc==SQLITE_OK ){
177318 Fts5PageWriter *pPage = &pWriter->writer;
177319
177320 if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){
@@ -177337,12 +178242,10 @@
177337 fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
177338 }
177339 pWriter->iPrevRowid = iRowid;
177340 pWriter->bFirstRowidInDoclist = 0;
177341 pWriter->bFirstRowidInPage = 0;
177342
177343 fts5BufferAppendVarint(&p->rc, &pPage->buf, nPos);
177344 }
177345 }
177346
177347 static void fts5WriteAppendPoslistData(
177348 Fts5Index *p,
@@ -177534,10 +178437,11 @@
177534 int nInput; /* Number of input segments */
177535 Fts5SegWriter writer; /* Writer object */
177536 Fts5StructureSegment *pSeg; /* Output segment */
177537 Fts5Buffer term;
177538 int bOldest; /* True if the output segment is the oldest */
 
177539
177540 assert( iLvl<pStruct->nLevel );
177541 assert( pLvl->nMerge<=pLvl->nSeg );
177542
177543 memset(&writer, 0, sizeof(Fts5SegWriter));
@@ -177603,15 +178507,25 @@
177603 fts5BufferSet(&p->rc, &term, nTerm, pTerm);
177604 }
177605
177606 /* Append the rowid to the output */
177607 /* WRITEPOSLISTSIZE */
177608 nPos = pSegIter->nPos*2 + pSegIter->bDel;
177609 fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter), nPos);
177610
177611 /* Append the position-list data to the output */
177612 fts5ChunkIterate(p, pSegIter, (void*)&writer, fts5MergeChunkCallback);
 
 
 
 
 
 
 
 
 
 
 
177613 }
177614
177615 /* Flush the last leaf page to disk. Set the output segment b-tree height
177616 ** and last leaf page number at the same time. */
177617 fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
@@ -177795,11 +178709,11 @@
177795 pStruct = fts5StructureRead(p);
177796 iSegid = fts5AllocateSegid(p, pStruct);
177797
177798 if( iSegid ){
177799 const int pgsz = p->pConfig->pgsz;
177800
177801 Fts5StructureSegment *pSeg; /* New segment within pStruct */
177802 Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */
177803 Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */
177804
177805 Fts5SegWriter writer;
@@ -177838,16 +178752,11 @@
177838
177839 /* The entire doclist will not fit on this leaf. The following
177840 ** loop iterates through the poslists that make up the current
177841 ** doclist. */
177842 while( p->rc==SQLITE_OK && iOff<nDoclist ){
177843 int nPos;
177844 int nCopy;
177845 int bDummy;
177846 iOff += fts5GetVarint(&pDoclist[iOff], (u64*)&iDelta);
177847 nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy);
177848 nCopy += nPos;
177849 iRowid += iDelta;
177850
177851 if( writer.bFirstRowidInPage ){
177852 fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */
177853 pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
@@ -177856,38 +178765,56 @@
177856 }else{
177857 pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
177858 }
177859 assert( pBuf->n<=pBuf->nSpace );
177860
177861 if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){
177862 /* The entire poslist will fit on the current leaf. So copy
177863 ** it in one go. */
177864 fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy);
177865 }else{
177866 /* The entire poslist will not fit on this leaf. So it needs
177867 ** to be broken into sections. The only qualification being
177868 ** that each varint must be stored contiguously. */
177869 const u8 *pPoslist = &pDoclist[iOff];
177870 int iPos = 0;
177871 while( p->rc==SQLITE_OK ){
177872 int nSpace = pgsz - pBuf->n - pPgidx->n;
177873 int n = 0;
177874 if( (nCopy - iPos)<=nSpace ){
177875 n = nCopy - iPos;
177876 }else{
177877 n = fts5PoslistPrefix(&pPoslist[iPos], nSpace);
177878 }
177879 assert( n>0 );
177880 fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n);
177881 iPos += n;
177882 if( (pBuf->n + pPgidx->n)>=pgsz ){
177883 fts5WriteFlushLeaf(p, &writer);
177884 }
177885 if( iPos>=nCopy ) break;
177886 }
177887 }
177888 iOff += nCopy;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177889 }
177890 }
177891
177892 /* TODO2: Doclist terminator written here. */
177893 /* pBuf->p[pBuf->n++] = '\0'; */
@@ -178018,10 +178945,18 @@
178018 Fts5Buffer *pBuf; /* Append to this buffer */
178019 Fts5Colset *pColset; /* Restrict matches to this column */
178020 int eState; /* See above */
178021 };
178022
 
 
 
 
 
 
 
 
178023 /*
178024 ** TODO: Make this more efficient!
178025 */
178026 static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
178027 int i;
@@ -178028,10 +178963,32 @@
178028 for(i=0; i<pColset->nCol; i++){
178029 if( pColset->aiCol[i]==iCol ) return 1;
178030 }
178031 return 0;
178032 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178033
178034 static void fts5PoslistFilterCallback(
178035 Fts5Index *p,
178036 void *pContext,
178037 const u8 *pChunk, int nChunk
@@ -178096,16 +179053,24 @@
178096 ){
178097 if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
178098 if( pColset==0 ){
178099 fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
178100 }else{
178101 PoslistCallbackCtx sCtx;
178102 sCtx.pBuf = pBuf;
178103 sCtx.pColset = pColset;
178104 sCtx.eState = fts5IndexColsetTest(pColset, 0);
178105 assert( sCtx.eState==0 || sCtx.eState==1 );
178106 fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
 
 
 
 
 
 
 
 
178107 }
178108 }
178109 }
178110
178111 /*
@@ -178144,10 +179109,20 @@
178144 prev = *p++;
178145 }
178146 return p - (*pa);
178147 }
178148
 
 
 
 
 
 
 
 
 
 
178149
178150 /*
178151 ** Iterator pMulti currently points to a valid entry (not EOF). This
178152 ** function appends the following to buffer pBuf:
178153 **
@@ -178171,12 +179146,12 @@
178171 if( p->rc==SQLITE_OK ){
178172 Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ];
178173 assert( fts5MultiIterEof(p, pMulti)==0 );
178174 assert( pSeg->nPos>0 );
178175 if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){
178176
178177 if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
178178 && (pColset==0 || pColset->nCol==1)
178179 ){
178180 const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
178181 int nPos;
178182 if( pColset ){
@@ -178217,16 +179192,16 @@
178217 sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2);
178218 }
178219 }
178220 }
178221 }
178222
178223 }
178224 }
178225
178226 return 0;
178227 }
 
178228
178229 static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
178230 u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
178231
178232 assert( pIter->aPoslist );
@@ -178283,10 +179258,73 @@
178283 #define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \
178284 assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \
178285 fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
178286 (iLastRowid) = (iRowid); \
178287 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178288
178289 /*
178290 ** Buffers p1 and p2 contain doclists. This function merges the content
178291 ** of the two doclists together and sets buffer p1 to the result before
178292 ** returning.
@@ -178352,11 +179390,13 @@
178352 sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
178353 if( iPos1==iPos2 ){
178354 sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1);
178355 }
178356 }
178357 p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew);
 
 
178358 }
178359
178360 /* WRITEPOSLISTSIZE */
178361 fts5BufferSafeAppendVarint(&out, tmp.n * 2);
178362 fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
@@ -178369,16 +179409,10 @@
178369 fts5BufferFree(&tmp);
178370 fts5BufferFree(&out);
178371 }
178372 }
178373
178374 static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){
178375 Fts5Buffer tmp = *p1;
178376 *p1 = *p2;
178377 *p2 = tmp;
178378 }
178379
178380 static void fts5SetupPrefixIter(
178381 Fts5Index *p, /* Index to read from */
178382 int bDesc, /* True for "ORDER BY rowid DESC" */
178383 const u8 *pToken, /* Buffer containing prefix to match */
178384 int nToken, /* Size of buffer pToken in bytes */
@@ -178386,10 +179420,20 @@
178386 Fts5IndexIter **ppIter /* OUT: New iterator */
178387 ){
178388 Fts5Structure *pStruct;
178389 Fts5Buffer *aBuf;
178390 const int nBuf = 32;
 
 
 
 
 
 
 
 
 
 
178391
178392 aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
178393 pStruct = fts5StructureRead(p);
178394
178395 if( aBuf && pStruct ){
@@ -178419,25 +179463,25 @@
178419 assert( i<nBuf );
178420 if( aBuf[i].n==0 ){
178421 fts5BufferSwap(&doclist, &aBuf[i]);
178422 fts5BufferZero(&doclist);
178423 }else{
178424 fts5MergePrefixLists(p, &doclist, &aBuf[i]);
178425 fts5BufferZero(&aBuf[i]);
178426 }
178427 }
178428 iLastRowid = 0;
178429 }
178430
178431 if( !fts5AppendPoslist(p, iRowid-iLastRowid, p1, pColset, &doclist) ){
178432 iLastRowid = iRowid;
178433 }
178434 }
178435
178436 for(i=0; i<nBuf; i++){
178437 if( p->rc==SQLITE_OK ){
178438 fts5MergePrefixLists(p, &doclist, &aBuf[i]);
178439 }
178440 fts5BufferFree(&aBuf[i]);
178441 }
178442 fts5MultiIterFree(p, p1);
178443
@@ -178463,11 +179507,11 @@
178463 static int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
178464 assert( p->rc==SQLITE_OK );
178465
178466 /* Allocate the hash table if it has not already been allocated */
178467 if( p->pHash==0 ){
178468 p->rc = sqlite3Fts5HashNew(&p->pHash, &p->nPendingData);
178469 }
178470
178471 /* Flush the hash table to disk if required */
178472 if( iRowid<p->iWriteRowid
178473 || (iRowid==p->iWriteRowid && p->bDelete==0)
@@ -178584,11 +179628,15 @@
178584 /*
178585 ** Argument p points to a buffer containing utf-8 text that is n bytes in
178586 ** size. Return the number of bytes in the nChar character prefix of the
178587 ** buffer, or 0 if there are less than nChar characters in total.
178588 */
178589 static int fts5IndexCharlenToBytelen(const char *p, int nByte, int nChar){
 
 
 
 
178590 int n = 0;
178591 int i;
178592 for(i=0; i<nChar; i++){
178593 if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
178594 if( (unsigned char)p[n++]>=0xc0 ){
@@ -178641,11 +179689,12 @@
178641 rc = sqlite3Fts5HashWrite(
178642 p->pHash, p->iWriteRowid, iCol, iPos, FTS5_MAIN_PREFIX, pToken, nToken
178643 );
178644
178645 for(i=0; i<pConfig->nPrefix && rc==SQLITE_OK; i++){
178646 int nByte = fts5IndexCharlenToBytelen(pToken, nToken, pConfig->aPrefix[i]);
 
178647 if( nByte ){
178648 rc = sqlite3Fts5HashWrite(p->pHash,
178649 p->iWriteRowid, iCol, iPos, (char)(FTS5_MAIN_PREFIX+i+1), pToken,
178650 nByte
178651 );
@@ -178819,13 +179868,20 @@
178819 const u8 **pp, /* OUT: Pointer to position-list data */
178820 int *pn, /* OUT: Size of position-list in bytes */
178821 i64 *piRowid /* OUT: Current rowid */
178822 ){
178823 Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
 
 
178824 assert( pIter->pIndex->rc==SQLITE_OK );
178825 *piRowid = pSeg->iRowid;
178826 if( pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf ){
 
 
 
 
 
178827 u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
178828 if( pColset==0 || pIter->bFiltered ){
178829 *pn = pSeg->nPos;
178830 *pp = pPos;
178831 }else if( pColset->nCol==1 ){
@@ -178838,15 +179894,28 @@
178838 *pn = pIter->poslist.n;
178839 }
178840 }else{
178841 fts5BufferZero(&pIter->poslist);
178842 fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
178843 *pp = pIter->poslist.p;
 
 
178844 *pn = pIter->poslist.n;
178845 }
178846 return fts5IndexReturn(pIter->pIndex);
178847 }
 
 
 
 
 
 
 
 
 
 
 
178848
178849 /*
178850 ** This function is similar to sqlite3Fts5IterPoslist(), except that it
178851 ** copies the position list into the buffer supplied as the second
178852 ** argument.
@@ -178957,11 +180026,11 @@
178957 */
178958
178959 /*
178960 ** Return a simple checksum value based on the arguments.
178961 */
178962 static u64 fts5IndexEntryCksum(
178963 i64 iRowid,
178964 int iCol,
178965 int iPos,
178966 int iIdx,
178967 const char *pTerm,
@@ -179027,34 +180096,41 @@
179027 const char *z, /* Index key to query for */
179028 int n, /* Size of index key in bytes */
179029 int flags, /* Flags for Fts5IndexQuery */
179030 u64 *pCksum /* IN/OUT: Checksum value */
179031 ){
 
179032 u64 cksum = *pCksum;
179033 Fts5IndexIter *pIdxIter = 0;
 
179034 int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter);
179035
179036 while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){
179037 i64 dummy;
179038 const u8 *pPos;
179039 int nPos;
179040 i64 rowid = sqlite3Fts5IterRowid(pIdxIter);
179041 rc = sqlite3Fts5IterPoslist(pIdxIter, 0, &pPos, &nPos, &dummy);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179042 if( rc==SQLITE_OK ){
179043 Fts5PoslistReader sReader;
179044 for(sqlite3Fts5PoslistReaderInit(pPos, nPos, &sReader);
179045 sReader.bEof==0;
179046 sqlite3Fts5PoslistReaderNext(&sReader)
179047 ){
179048 int iCol = FTS5_POS2COLUMN(sReader.iPos);
179049 int iOff = FTS5_POS2OFFSET(sReader.iPos);
179050 cksum ^= fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n);
179051 }
179052 rc = sqlite3Fts5IterNext(pIdxIter);
179053 }
179054 }
179055 sqlite3Fts5IterClose(pIdxIter);
 
179056
179057 *pCksum = cksum;
179058 return rc;
179059 }
179060
@@ -179344,18 +180420,19 @@
179344
179345
179346 /*
179347 ** Run internal checks to ensure that the FTS index (a) is internally
179348 ** consistent and (b) contains entries for which the XOR of the checksums
179349 ** as calculated by fts5IndexEntryCksum() is cksum.
179350 **
179351 ** Return SQLITE_CORRUPT if any of the internal checks fail, or if the
179352 ** checksum does not match. Return SQLITE_OK if all checks pass without
179353 ** error, or some other SQLite error code if another error (e.g. OOM)
179354 ** occurs.
179355 */
179356 static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
 
179357 u64 cksum2 = 0; /* Checksum based on contents of indexes */
179358 Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
179359 Fts5IndexIter *pIter; /* Used to iterate through entire index */
179360 Fts5Structure *pStruct; /* Index structure */
179361
@@ -179403,16 +180480,22 @@
179403 char *z = (char*)fts5MultiIterTerm(pIter, &n);
179404
179405 /* If this is a new term, query for it. Update cksum3 with the results. */
179406 fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
179407
179408 poslist.n = 0;
179409 fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst] , 0, &poslist);
179410 while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
179411 int iCol = FTS5_POS2COLUMN(iPos);
179412 int iTokOff = FTS5_POS2OFFSET(iPos);
179413 cksum2 ^= fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n);
 
 
 
 
 
 
179414 }
179415 }
179416 fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
179417
179418 fts5MultiIterFree(p, pIter);
@@ -179424,38 +180507,10 @@
179424 #endif
179425 fts5BufferFree(&poslist);
179426 return fts5IndexReturn(p);
179427 }
179428
179429
179430 /*
179431 ** Calculate and return a checksum that is the XOR of the index entry
179432 ** checksum of all entries that would be generated by the token specified
179433 ** by the final 5 arguments.
179434 */
179435 static u64 sqlite3Fts5IndexCksum(
179436 Fts5Config *pConfig, /* Configuration object */
179437 i64 iRowid, /* Document term appears in */
179438 int iCol, /* Column term appears in */
179439 int iPos, /* Position term appears in */
179440 const char *pTerm, int nTerm /* Term at iPos */
179441 ){
179442 u64 ret = 0; /* Return value */
179443 int iIdx; /* For iterating through indexes */
179444
179445 ret = fts5IndexEntryCksum(iRowid, iCol, iPos, 0, pTerm, nTerm);
179446
179447 for(iIdx=0; iIdx<pConfig->nPrefix; iIdx++){
179448 int nByte = fts5IndexCharlenToBytelen(pTerm, nTerm, pConfig->aPrefix[iIdx]);
179449 if( nByte ){
179450 ret ^= fts5IndexEntryCksum(iRowid, iCol, iPos, iIdx+1, pTerm, nByte);
179451 }
179452 }
179453
179454 return ret;
179455 }
179456
179457 /*************************************************************************
179458 **************************************************************************
179459 ** Below this point is the implementation of the fts5_decode() scalar
179460 ** function only.
179461 */
@@ -180039,10 +181094,11 @@
180039 #define FTS5CSR_REQUIRE_DOCSIZE 0x02
180040 #define FTS5CSR_REQUIRE_INST 0x04
180041 #define FTS5CSR_EOF 0x08
180042 #define FTS5CSR_FREE_ZRANK 0x10
180043 #define FTS5CSR_REQUIRE_RESEEK 0x20
 
180044
180045 #define BitFlagAllTest(x,y) (((x) & (y))==(y))
180046 #define BitFlagTest(x,y) (((x) & (y))!=0)
180047
180048
@@ -180452,10 +181508,11 @@
180452 static void fts5CsrNewrow(Fts5Cursor *pCsr){
180453 CsrFlagSet(pCsr,
180454 FTS5CSR_REQUIRE_CONTENT
180455 | FTS5CSR_REQUIRE_DOCSIZE
180456 | FTS5CSR_REQUIRE_INST
 
180457 );
180458 }
180459
180460 static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
180461 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
@@ -180534,19 +181591,22 @@
180534
180535 pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
180536 nBlob = sqlite3_column_bytes(pSorter->pStmt, 1);
180537 aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1);
180538
180539 for(i=0; i<(pSorter->nIdx-1); i++){
180540 int iVal;
180541 a += fts5GetVarint32(a, iVal);
180542 iOff += iVal;
180543 pSorter->aIdx[i] = iOff;
180544 }
180545 pSorter->aIdx[i] = &aBlob[nBlob] - a;
180546
180547 pSorter->aPoslist = a;
 
 
 
180548 fts5CsrNewrow(pCsr);
180549 }
180550
180551 return rc;
180552 }
@@ -180980,10 +182040,11 @@
180980 assert( pCsr->iLastRowid==LARGEST_INT64 );
180981 assert( pCsr->iFirstRowid==SMALLEST_INT64 );
180982 pCsr->ePlan = FTS5_PLAN_SOURCE;
180983 pCsr->pExpr = pTab->pSortCsr->pExpr;
180984 rc = fts5CursorFirst(pTab, pCsr, bDesc);
 
180985 }else if( pMatch ){
180986 const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
180987 if( zExpr==0 ) zExpr = "";
180988
180989 rc = fts5CursorParseRank(pConfig, pCsr, pRank);
@@ -181409,10 +182470,12 @@
181409 fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
181410 rc = sqlite3Fts5StorageRollback(pTab->pStorage);
181411 return rc;
181412 }
181413
 
 
181414 static void *fts5ApiUserData(Fts5Context *pCtx){
181415 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
181416 return pCsr->pAux->pUserData;
181417 }
181418
@@ -181458,21 +182521,76 @@
181458 static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
181459 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
181460 return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
181461 }
181462
181463 static int fts5CsrPoslist(Fts5Cursor *pCsr, int iPhrase, const u8 **pa){
181464 int n;
181465 if( pCsr->pSorter ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181466 Fts5Sorter *pSorter = pCsr->pSorter;
181467 int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
181468 n = pSorter->aIdx[iPhrase] - i1;
181469 *pa = &pSorter->aPoslist[i1];
181470 }else{
181471 n = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
181472 }
181473 return n;
 
181474 }
181475
181476 /*
181477 ** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
181478 ** correctly for the current view. Return SQLITE_OK if successful, or an
@@ -181493,47 +182611,50 @@
181493 if( aIter ){
181494 int nInst = 0; /* Number instances seen so far */
181495 int i;
181496
181497 /* Initialize all iterators */
181498 for(i=0; i<nIter; i++){
181499 const u8 *a;
181500 int n = fts5CsrPoslist(pCsr, i, &a);
 
181501 sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
181502 }
181503
181504 while( 1 ){
181505 int *aInst;
181506 int iBest = -1;
181507 for(i=0; i<nIter; i++){
181508 if( (aIter[i].bEof==0)
181509 && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos)
181510 ){
181511 iBest = i;
181512 }
181513 }
181514 if( iBest<0 ) break;
181515
181516 nInst++;
181517 if( nInst>=pCsr->nInstAlloc ){
181518 pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
181519 aInst = (int*)sqlite3_realloc(
181520 pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
181521 );
181522 if( aInst ){
181523 pCsr->aInst = aInst;
181524 }else{
181525 rc = SQLITE_NOMEM;
181526 break;
181527 }
181528 }
181529
181530 aInst = &pCsr->aInst[3 * (nInst-1)];
181531 aInst[0] = iBest;
181532 aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
181533 aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
181534 sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
 
 
181535 }
181536
181537 pCsr->nInstCount = nInst;
181538 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
181539 }
@@ -181562,10 +182683,16 @@
181562 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
181563 || SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
181564 ){
181565 if( iIdx<0 || iIdx>=pCsr->nInstCount ){
181566 rc = SQLITE_RANGE;
 
 
 
 
 
 
181567 }else{
181568 *piPhrase = pCsr->aInst[iIdx*3];
181569 *piCol = pCsr->aInst[iIdx*3 + 1];
181570 *piOff = pCsr->aInst[iIdx*3 + 2];
181571 }
@@ -181575,31 +182702,10 @@
181575
181576 static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){
181577 return fts5CursorRowid((Fts5Cursor*)pCtx);
181578 }
181579
181580 static int fts5ApiColumnText(
181581 Fts5Context *pCtx,
181582 int iCol,
181583 const char **pz,
181584 int *pn
181585 ){
181586 int rc = SQLITE_OK;
181587 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
181588 if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
181589 *pz = 0;
181590 *pn = 0;
181591 }else{
181592 rc = fts5SeekCursor(pCsr, 0);
181593 if( rc==SQLITE_OK ){
181594 *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
181595 *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
181596 }
181597 }
181598 return rc;
181599 }
181600
181601 static int fts5ColumnSizeCb(
181602 void *pContext, /* Pointer to int */
181603 int tflags,
181604 const char *pToken, /* Buffer containing token */
181605 int nToken, /* Size of token in bytes */
@@ -181740,23 +182846,94 @@
181740 }
181741 *piOff += (iVal-2);
181742 }
181743 }
181744
181745 static void fts5ApiPhraseFirst(
181746 Fts5Context *pCtx,
181747 int iPhrase,
181748 Fts5PhraseIter *pIter,
181749 int *piCol, int *piOff
181750 ){
181751 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
181752 int n = fts5CsrPoslist(pCsr, iPhrase, &pIter->a);
181753 pIter->b = &pIter->a[n];
181754 *piCol = 0;
181755 *piOff = 0;
181756 fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
 
 
 
 
181757 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181758
181759 static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
181760 int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
181761 );
181762
@@ -181777,12 +182954,13 @@
181777 fts5ApiQueryPhrase,
181778 fts5ApiSetAuxdata,
181779 fts5ApiGetAuxdata,
181780 fts5ApiPhraseFirst,
181781 fts5ApiPhraseNext,
 
 
181782 };
181783
181784
181785 /*
181786 ** Implementation of API function xQueryPhrase().
181787 */
181788 static int fts5ApiQueryPhrase(
@@ -181911,24 +183089,50 @@
181911 int rc = SQLITE_OK;
181912 int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
181913 Fts5Buffer val;
181914
181915 memset(&val, 0, sizeof(Fts5Buffer));
181916
181917 /* Append the varints */
181918 for(i=0; i<(nPhrase-1); i++){
181919 const u8 *dummy;
181920 int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
181921 sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
181922 }
181923
181924 /* Append the position lists */
181925 for(i=0; i<nPhrase; i++){
181926 const u8 *pPoslist;
181927 int nPoslist;
181928 nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
181929 sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181930 }
181931
181932 sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
181933 return rc;
181934 }
@@ -182247,11 +183451,11 @@
182247 sqlite3_context *pCtx, /* Function call context */
182248 int nArg, /* Number of args */
182249 sqlite3_value **apVal /* Function arguments */
182250 ){
182251 assert( nArg==0 );
182252 sqlite3_result_text(pCtx, "fts5: 2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566", -1, SQLITE_TRANSIENT);
182253 }
182254
182255 static int fts5Init(sqlite3 *db){
182256 static const sqlite3_module fts5Mod = {
182257 /* iVersion */ 2,
@@ -183179,32 +184383,77 @@
183179 struct Fts5IntegrityCtx {
183180 i64 iRowid;
183181 int iCol;
183182 int szCol;
183183 u64 cksum;
 
183184 Fts5Config *pConfig;
183185 };
 
183186
183187 /*
183188 ** Tokenization callback used by integrity check.
183189 */
183190 static int fts5StorageIntegrityCallback(
183191 void *pContext, /* Pointer to Fts5InsertCtx object */
183192 int tflags,
183193 const char *pToken, /* Buffer containing token */
183194 int nToken, /* Size of token in bytes */
183195 int iStart, /* Start offset of token */
183196 int iEnd /* End offset of token */
183197 ){
183198 Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext;
 
 
 
 
 
 
 
183199 if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
183200 pCtx->szCol++;
183201 }
183202 pCtx->cksum ^= sqlite3Fts5IndexCksum(
183203 pCtx->pConfig, pCtx->iRowid, pCtx->iCol, pCtx->szCol-1, pToken, nToken
183204 );
183205 return SQLITE_OK;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183206 }
183207
183208 /*
183209 ** Check that the contents of the FTS index match that of the %_content
183210 ** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return
@@ -183235,27 +184484,42 @@
183235 int i;
183236 ctx.iRowid = sqlite3_column_int64(pScan, 0);
183237 ctx.szCol = 0;
183238 if( pConfig->bColumnsize ){
183239 rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
 
 
 
183240 }
183241 for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
183242 if( pConfig->abUnindexed[i] ) continue;
183243 ctx.iCol = i;
183244 ctx.szCol = 0;
183245 rc = sqlite3Fts5Tokenize(pConfig,
183246 FTS5_TOKENIZE_DOCUMENT,
183247 (const char*)sqlite3_column_text(pScan, i+1),
183248 sqlite3_column_bytes(pScan, i+1),
183249 (void*)&ctx,
183250 fts5StorageIntegrityCallback
183251 );
183252 if( pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
 
 
 
 
 
183253 rc = FTS5_CORRUPT;
183254 }
183255 aTotalSize[i] += ctx.szCol;
 
 
 
 
183256 }
 
 
 
183257 if( rc!=SQLITE_OK ) break;
183258 }
183259 rc2 = sqlite3_reset(pScan);
183260 if( rc==SQLITE_OK ) rc = rc2;
183261 }
@@ -185777,11 +187041,11 @@
185777
185778 pCsr->rowid++;
185779
185780 if( pTab->eType==FTS5_VOCAB_COL ){
185781 for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
185782 if( pCsr->aCnt[pCsr->iCol] ) break;
185783 }
185784 }
185785
185786 if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
185787 if( sqlite3Fts5IterEof(pCsr->pIter) ){
@@ -185810,28 +187074,56 @@
185810 i64 dummy;
185811 const u8 *pPos; int nPos; /* Position list */
185812 i64 iPos = 0; /* 64-bit position read from poslist */
185813 int iOff = 0; /* Current offset within position list */
185814
185815 rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy);
185816 if( rc==SQLITE_OK ){
185817 if( pTab->eType==FTS5_VOCAB_ROW ){
185818 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
185819 pCsr->aCnt[0]++;
185820 }
185821 pCsr->aDoc[0]++;
185822 }else{
185823 int iCol = -1;
185824 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
185825 int ii = FTS5_POS2COLUMN(iPos);
185826 pCsr->aCnt[ii]++;
185827 if( iCol!=ii ){
185828 pCsr->aDoc[ii]++;
185829 iCol = ii;
185830 }
185831 }
185832 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185833 rc = sqlite3Fts5IterNextScan(pCsr->pIter);
185834 }
185835
185836 if( rc==SQLITE_OK ){
185837 zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
@@ -185843,11 +187135,11 @@
185843 }
185844 }
185845 }
185846
185847 if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
185848 while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++;
185849 assert( pCsr->iCol<pCsr->pConfig->nCol );
185850 }
185851 return rc;
185852 }
185853
@@ -185923,34 +187215,40 @@
185923 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
185924 sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
185925 int iCol /* Index of column to read value from */
185926 ){
185927 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
 
 
 
185928
185929 if( iCol==0 ){
185930 sqlite3_result_text(
185931 pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
185932 );
185933 }
185934 else if( ((Fts5VocabTable*)(pCursor->pVtab))->eType==FTS5_VOCAB_COL ){
185935 assert( iCol==1 || iCol==2 || iCol==3 );
185936 if( iCol==1 ){
185937 const char *z = pCsr->pConfig->azCol[pCsr->iCol];
185938 sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
 
 
185939 }else if( iCol==2 ){
185940 sqlite3_result_int64(pCtx, pCsr->aDoc[pCsr->iCol]);
185941 }else{
185942 sqlite3_result_int64(pCtx, pCsr->aCnt[pCsr->iCol]);
185943 }
185944 }else{
185945 assert( iCol==1 || iCol==2 );
185946 if( iCol==1 ){
185947 sqlite3_result_int64(pCtx, pCsr->aDoc[0]);
185948 }else{
185949 sqlite3_result_int64(pCtx, pCsr->aCnt[0]);
185950 }
185951 }
 
 
185952 return SQLITE_OK;
185953 }
185954
185955 /*
185956 ** This is the xRowid method. The SQLite core calls this routine to
185957
--- src/sqlite3.c
+++ src/sqlite3.c
@@ -1,8 +1,8 @@
1 /******************************************************************************
2 ** This file is an amalgamation of many separate C source files from SQLite
3 ** version 3.11.0. By combining all the individual C code files into this
4 ** single large file, the entire code can be compiled as a single translation
5 ** unit. This allows many compilers to do optimizations that would not be
6 ** possible if the files were compiled separately. Performance improvements
7 ** of 5% or more are commonly seen when SQLite is compiled as a single
8 ** translation unit.
@@ -119,10 +119,12 @@
119 #define SQLITE_ENABLE_LOCKING_STYLE 0
120 #define HAVE_UTIME 1
121 #else
122 /* This is not VxWorks. */
123 #define OS_VXWORKS 0
124 #define HAVE_FCHOWN 1
125 #define HAVE_READLINK 1
126 #endif /* defined(_WRS_KERNEL) */
127
128 /************** End of vxworks.h *********************************************/
129 /************** Continuing where we left off in sqliteInt.h ******************/
130
@@ -323,13 +325,13 @@
325 **
326 ** See also: [sqlite3_libversion()],
327 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
328 ** [sqlite_version()] and [sqlite_source_id()].
329 */
330 #define SQLITE_VERSION "3.11.0"
331 #define SQLITE_VERSION_NUMBER 3011000
332 #define SQLITE_SOURCE_ID "2016-01-14 14:19:50 d17bc2c92f4d086280e49a3cc72993be7fee2da7"
333
334 /*
335 ** CAPI3REF: Run-Time Library Version Numbers
336 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
337 **
@@ -1006,12 +1008,17 @@
1008 ** improve performance on some systems.
1009 **
1010 ** <li>[[SQLITE_FCNTL_FILE_POINTER]]
1011 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
1012 ** to the [sqlite3_file] object associated with a particular database
1013 ** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER].
1014 **
1015 ** <li>[[SQLITE_FCNTL_JOURNAL_POINTER]]
1016 ** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer
1017 ** to the [sqlite3_file] object associated with the journal file (either
1018 ** the [rollback journal] or the [write-ahead log]) for a particular database
1019 ** connection. See also [SQLITE_FCNTL_FILE_POINTER].
1020 **
1021 ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
1022 ** No longer in use.
1023 **
1024 ** <li>[[SQLITE_FCNTL_SYNC]]
@@ -1222,10 +1229,11 @@
1229 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23
1230 #define SQLITE_FCNTL_WAL_BLOCK 24
1231 #define SQLITE_FCNTL_ZIPVFS 25
1232 #define SQLITE_FCNTL_RBU 26
1233 #define SQLITE_FCNTL_VFS_POINTER 27
1234 #define SQLITE_FCNTL_JOURNAL_POINTER 28
1235
1236 /* deprecated names */
1237 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1238 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1239 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -8399,10 +8407,13 @@
8407 ** If parameter iCol is greater than or equal to the number of columns
8408 ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
8409 ** an OOM condition or IO error), an appropriate SQLite error code is
8410 ** returned.
8411 **
8412 ** This function may be quite inefficient if used with an FTS5 table
8413 ** created with the "columnsize=0" option.
8414 **
8415 ** xColumnText:
8416 ** This function attempts to retrieve the text of column iCol of the
8417 ** current document. If successful, (*pz) is set to point to a buffer
8418 ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
8419 ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -8419,18 +8430,32 @@
8430 ** xInstCount:
8431 ** Set *pnInst to the total number of occurrences of all phrases within
8432 ** the query within the current row. Return SQLITE_OK if successful, or
8433 ** an error code (i.e. SQLITE_NOMEM) if an error occurs.
8434 **
8435 ** This API can be quite slow if used with an FTS5 table created with the
8436 ** "detail=none" or "detail=column" option. If the FTS5 table is created
8437 ** with either "detail=none" or "detail=column" and "content=" option
8438 ** (i.e. if it is a contentless table), then this API always returns 0.
8439 **
8440 ** xInst:
8441 ** Query for the details of phrase match iIdx within the current row.
8442 ** Phrase matches are numbered starting from zero, so the iIdx argument
8443 ** should be greater than or equal to zero and smaller than the value
8444 ** output by xInstCount().
8445 **
8446 ** Usually, output parameter *piPhrase is set to the phrase number, *piCol
8447 ** to the column in which it occurs and *piOff the token offset of the
8448 ** first token of the phrase. The exception is if the table was created
8449 ** with the offsets=0 option specified. In this case *piOff is always
8450 ** set to -1.
8451 **
8452 ** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
8453 ** if an error occurs.
8454 **
8455 ** This API can be quite slow if used with an FTS5 table created with the
8456 ** "detail=none" or "detail=column" option.
8457 **
8458 ** xRowid:
8459 ** Returns the rowid of the current row.
8460 **
8461 ** xTokenize:
@@ -8511,25 +8536,63 @@
8536 ** through instances of phrase iPhrase, use the following code:
8537 **
8538 ** Fts5PhraseIter iter;
8539 ** int iCol, iOff;
8540 ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
8541 ** iCol>=0;
8542 ** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
8543 ** ){
8544 ** // An instance of phrase iPhrase at offset iOff of column iCol
8545 ** }
8546 **
8547 ** The Fts5PhraseIter structure is defined above. Applications should not
8548 ** modify this structure directly - it should only be used as shown above
8549 ** with the xPhraseFirst() and xPhraseNext() API methods (and by
8550 ** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
8551 **
8552 ** This API can be quite slow if used with an FTS5 table created with the
8553 ** "detail=none" or "detail=column" option. If the FTS5 table is created
8554 ** with either "detail=none" or "detail=column" and "content=" option
8555 ** (i.e. if it is a contentless table), then this API always iterates
8556 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
8557 **
8558 ** xPhraseNext()
8559 ** See xPhraseFirst above.
8560 **
8561 ** xPhraseFirstColumn()
8562 ** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
8563 ** and xPhraseNext() APIs described above. The difference is that instead
8564 ** of iterating through all instances of a phrase in the current row, these
8565 ** APIs are used to iterate through the set of columns in the current row
8566 ** that contain one or more instances of a specified phrase. For example:
8567 **
8568 ** Fts5PhraseIter iter;
8569 ** int iCol;
8570 ** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
8571 ** iCol>=0;
8572 ** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
8573 ** ){
8574 ** // Column iCol contains at least one instance of phrase iPhrase
8575 ** }
8576 **
8577 ** This API can be quite slow if used with an FTS5 table created with the
8578 ** "detail=none" option. If the FTS5 table is created with either
8579 ** "detail=none" "content=" option (i.e. if it is a contentless table),
8580 ** then this API always iterates through an empty set (all calls to
8581 ** xPhraseFirstColumn() set iCol to -1).
8582 **
8583 ** The information accessed using this API and its companion
8584 ** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
8585 ** (or xInst/xInstCount). The chief advantage of this API is that it is
8586 ** significantly more efficient than those alternatives when used with
8587 ** "detail=column" tables.
8588 **
8589 ** xPhraseNextColumn()
8590 ** See xPhraseFirstColumn above.
8591 */
8592 struct Fts5ExtensionApi {
8593 int iVersion; /* Currently always set to 3 */
8594
8595 void *(*xUserData)(Fts5Context*);
8596
8597 int (*xColumnCount)(Fts5Context*);
8598 int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -8555,12 +8618,15 @@
8618 int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
8619 );
8620 int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
8621 void *(*xGetAuxdata)(Fts5Context*, int bClear);
8622
8623 int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
8624 void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
8625
8626 int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
8627 void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
8628 };
8629
8630 /*
8631 ** CUSTOM AUXILIARY FUNCTIONS
8632 *************************************************************************/
@@ -9976,14 +10042,10 @@
10042 /*
10043 ** Default maximum size of memory used by memory-mapped I/O in the VFS
10044 */
10045 #ifdef __APPLE__
10046 # include <TargetConditionals.h>
 
 
 
 
10047 #endif
10048 #ifndef SQLITE_MAX_MMAP_SIZE
10049 # if defined(__linux__) \
10050 || defined(_WIN32) \
10051 || (defined(__APPLE__) && defined(__MACH__)) \
@@ -10479,19 +10541,21 @@
10541 ** Enter and Leave procedures no-ops.
10542 */
10543 #ifndef SQLITE_OMIT_SHARED_CACHE
10544 SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*);
10545 SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*);
10546 SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*);
10547 SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*);
10548 #else
10549 # define sqlite3BtreeEnter(X)
10550 # define sqlite3BtreeEnterAll(X)
10551 # define sqlite3BtreeSharable(X) 0
10552 # define sqlite3BtreeEnterCursor(X)
10553 #endif
10554
10555 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
 
10556 SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*);
 
10557 SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*);
10558 SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*);
10559 #ifndef NDEBUG
10560 /* These routines are used inside assert() statements only. */
10561 SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*);
@@ -10498,13 +10562,11 @@
10562 SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*);
10563 SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
10564 #endif
10565 #else
10566
 
10567 # define sqlite3BtreeLeave(X)
 
10568 # define sqlite3BtreeLeaveCursor(X)
10569 # define sqlite3BtreeLeaveAll(X)
10570
10571 # define sqlite3BtreeHoldsMutex(X) 1
10572 # define sqlite3BtreeHoldsAllMutexes(X) 1
@@ -11215,10 +11277,11 @@
11277 #endif
11278 SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
11279 SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
11280 SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*);
11281 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
11282 SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*);
11283 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
11284 SQLITE_PRIVATE int sqlite3PagerNosync(Pager*);
11285 SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
11286 SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
11287 SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
@@ -11309,10 +11372,12 @@
11372 #define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before
11373 ** writing this page to the database */
11374 #define PGHDR_NEED_READ 0x010 /* Content is unread */
11375 #define PGHDR_DONT_WRITE 0x020 /* Do not write content to disk */
11376 #define PGHDR_MMAP 0x040 /* This is an mmap page object */
11377
11378 #define PGHDR_WAL_APPEND 0x080 /* Appended to wal file */
11379
11380 /* Initialize and shutdown the page cache subsystem */
11381 SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
11382 SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
11383
@@ -14135,11 +14200,10 @@
14200 SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
14201 SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
14202 SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
14203 SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
14204 SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
 
14205 SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
14206 SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
14207 SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
14208 SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
14209 SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
@@ -16066,15 +16130,19 @@
16130 SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
16131 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
16132 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
16133 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
16134
16135 #if !defined(SQLITE_OMIT_SHARED_CACHE)
16136 SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
 
16137 #else
16138 # define sqlite3VdbeEnter(X)
16139 #endif
16140
16141 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
16142 SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
16143 #else
16144 # define sqlite3VdbeLeave(X)
16145 #endif
16146
16147 #ifdef SQLITE_DEBUG
16148 SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
@@ -19758,10 +19826,11 @@
19826 /*
19827 ** Mutex to control access to the memory allocation subsystem.
19828 */
19829 sqlite3_mutex *mutex;
19830
19831 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
19832 /*
19833 ** Performance statistics
19834 */
19835 u64 nAlloc; /* Total number of calls to malloc */
19836 u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
@@ -19769,10 +19838,11 @@
19838 u32 currentOut; /* Current checkout, including internal fragmentation */
19839 u32 currentCount; /* Current number of distinct checkouts */
19840 u32 maxOut; /* Maximum instantaneous currentOut */
19841 u32 maxCount; /* Maximum instantaneous currentCount */
19842 u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
19843 #endif
19844
19845 /*
19846 ** Lists of free blocks. aiFreelist[0] is a list of free blocks of
19847 ** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
19848 ** aiFreelist[2] holds free blocks of size szAtom*4. And so forth.
@@ -19880,18 +19950,21 @@
19950 int iLogsize; /* Log2 of iFullSz/POW2_MIN */
19951
19952 /* nByte must be a positive */
19953 assert( nByte>0 );
19954
19955 /* No more than 1GiB per allocation */
19956 if( nByte > 0x40000000 ) return 0;
19957
19958 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
19959 /* Keep track of the maximum allocation request. Even unfulfilled
19960 ** requests are counted */
19961 if( (u32)nByte>mem5.maxRequest ){
 
 
 
19962 mem5.maxRequest = nByte;
19963 }
19964 #endif
19965
19966
19967 /* Round nByte up to the next valid power of two */
19968 for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){}
19969
19970 /* Make sure mem5.aiFreelist[iLogsize] contains at least one free
@@ -19914,18 +19987,20 @@
19987 mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
19988 memsys5Link(i+newSize, iBin);
19989 }
19990 mem5.aCtrl[i] = iLogsize;
19991
19992 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
19993 /* Update allocator performance statistics. */
19994 mem5.nAlloc++;
19995 mem5.totalAlloc += iFullSz;
19996 mem5.totalExcess += iFullSz - nByte;
19997 mem5.currentCount++;
19998 mem5.currentOut += iFullSz;
19999 if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
20000 if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
20001 #endif
20002
20003 #ifdef SQLITE_DEBUG
20004 /* Make sure the allocated memory does not assume that it is set to zero
20005 ** or retains a value from a previous allocation */
20006 memset(&mem5.zPool[i*mem5.szAtom], 0xAA, iFullSz);
@@ -19956,16 +20031,19 @@
20031 size = 1<<iLogsize;
20032 assert( iBlock+size-1<(u32)mem5.nBlock );
20033
20034 mem5.aCtrl[iBlock] |= CTRL_FREE;
20035 mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
20036
20037 #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
20038 assert( mem5.currentCount>0 );
20039 assert( mem5.currentOut>=(size*mem5.szAtom) );
20040 mem5.currentCount--;
20041 mem5.currentOut -= size*mem5.szAtom;
20042 assert( mem5.currentOut>0 || mem5.currentCount==0 );
20043 assert( mem5.currentCount>0 || mem5.currentOut==0 );
20044 #endif
20045
20046 mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
20047 while( ALWAYS(iLogsize<LOGMAX) ){
20048 int iBuddy;
20049 if( (iBlock>>iLogsize) & 1 ){
@@ -27479,37 +27557,55 @@
27557 #define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
27558
27559 { "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
27560 #define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
27561
27562 #if defined(HAVE_FCHOWN)
27563 { "fchown", (sqlite3_syscall_ptr)fchown, 0 },
27564 #else
27565 { "fchown", (sqlite3_syscall_ptr)0, 0 },
27566 #endif
27567 #define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
27568
27569 { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 },
27570 #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
27571
27572 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
27573 { "mmap", (sqlite3_syscall_ptr)mmap, 0 },
27574 #else
27575 { "mmap", (sqlite3_syscall_ptr)0, 0 },
27576 #endif
27577 #define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
27578
27579 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
27580 { "munmap", (sqlite3_syscall_ptr)munmap, 0 },
27581 #else
27582 { "munmap", (sqlite3_syscall_ptr)0, 0 },
27583 #endif
27584 #define osMunmap ((void*(*)(void*,size_t))aSyscall[23].pCurrent)
27585
27586 #if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
27587 { "mremap", (sqlite3_syscall_ptr)mremap, 0 },
27588 #else
27589 { "mremap", (sqlite3_syscall_ptr)0, 0 },
27590 #endif
27591 #define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent)
27592
27593 #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
27594 { "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
27595 #else
27596 { "getpagesize", (sqlite3_syscall_ptr)0, 0 },
27597 #endif
27598 #define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent)
27599
27600 #if defined(HAVE_READLINK)
27601 { "readlink", (sqlite3_syscall_ptr)readlink, 0 },
27602 #else
27603 { "readlink", (sqlite3_syscall_ptr)0, 0 },
27604 #endif
27605 #define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
27606
 
27607
27608 }; /* End of the overrideable system calls */
27609
27610
27611 /*
@@ -27516,14 +27612,14 @@
27612 ** On some systems, calls to fchown() will trigger a message in a security
27613 ** log if they come from non-root processes. So avoid calling fchown() if
27614 ** we are not running as root.
27615 */
27616 static int robustFchown(int fd, uid_t uid, gid_t gid){
27617 #if defined(HAVE_FCHOWN)
 
 
27618 return osGeteuid() ? 0 : osFchown(fd,uid,gid);
27619 #else
27620 return 0;
27621 #endif
27622 }
27623
27624 /*
27625 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
@@ -32986,10 +33082,11 @@
33082 SimulateIOError( return SQLITE_ERROR );
33083
33084 assert( pVfs->mxPathname==MAX_PATHNAME );
33085 UNUSED_PARAMETER(pVfs);
33086
33087 #if defined(HAVE_READLINK)
33088 /* Attempt to resolve the path as if it were a symbolic link. If it is
33089 ** a symbolic link, the resolved path is stored in buffer zOut[]. Or, if
33090 ** the identified file is not a symbolic link or does not exist, then
33091 ** zPath is copied directly into zOut. Either way, nByte is left set to
33092 ** the size of the string copied into zOut[] in bytes. */
@@ -33001,10 +33098,11 @@
33098 sqlite3_snprintf(nOut, zOut, "%s", zPath);
33099 nByte = sqlite3Strlen30(zOut);
33100 }else{
33101 zOut[nByte] = '\0';
33102 }
33103 #endif
33104
33105 /* If buffer zOut[] now contains an absolute path there is nothing more
33106 ** to do. If it contains a relative path, do the following:
33107 **
33108 ** * move the relative path string so that it is at the end of th
@@ -43327,10 +43425,11 @@
43425 # define sqlite3WalCallback(z) 0
43426 # define sqlite3WalExclusiveMode(y,z) 0
43427 # define sqlite3WalHeapMemory(z) 0
43428 # define sqlite3WalFramesize(z) 0
43429 # define sqlite3WalFindFrame(x,y,z) 0
43430 # define sqlite3WalFile(x) 0
43431 #else
43432
43433 #define WAL_SAVEPOINT_NDATA 4
43434
43435 /* Connection to a write-ahead log (WAL) file.
@@ -43421,10 +43520,13 @@
43520 ** stored in each frame (i.e. the db page-size when the WAL was created).
43521 */
43522 SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
43523 #endif
43524
43525 /* Return the sqlite3_file object for the WAL file */
43526 SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
43527
43528 #endif /* ifndef SQLITE_OMIT_WAL */
43529 #endif /* _WAL_H_ */
43530
43531 /************** End of wal.h *************************************************/
43532 /************** Continuing where we left off in pager.c **********************/
@@ -49032,11 +49134,11 @@
49134 if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
49135 rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
49136 if( rc!=SQLITE_OK ){
49137 return rc;
49138 }
49139 (void)sqlite3WalExclusiveMode(pPager->pWal, 1);
49140 }
49141
49142 /* Grab the write lock on the log file. If successful, upgrade to
49143 ** PAGER_RESERVED state. Otherwise, return an error code to the caller.
49144 ** The busy-handler is not invoked if another connection already
@@ -50096,10 +50198,22 @@
50198 ** not yet been opened.
50199 */
50200 SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
50201 return pPager->fd;
50202 }
50203
50204 /*
50205 ** Return the file handle for the journal file (if it exists).
50206 ** This will be either the rollback journal or the WAL file.
50207 */
50208 SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
50209 #if SQLITE_OMIT_WAL
50210 return pPager->jfd;
50211 #else
50212 return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
50213 #endif
50214 }
50215
50216 /*
50217 ** Return the full pathname of the journal file.
50218 */
50219 SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager *pPager){
@@ -51202,10 +51316,11 @@
51316 u8 truncateOnCommit; /* True to truncate WAL file on commit */
51317 u8 syncHeader; /* Fsync the WAL header if true */
51318 u8 padToSectorBoundary; /* Pad transactions out to the next sector */
51319 WalIndexHdr hdr; /* Wal-index header for current transaction */
51320 u32 minFrame; /* Ignore wal frames before this one */
51321 u32 iReCksum; /* On commit, recalculate checksums from here */
51322 const char *zWalName; /* Name of WAL file */
51323 u32 nCkpt; /* Checkpoint sequence counter in the wal-header */
51324 #ifdef SQLITE_DEBUG
51325 u8 lockError; /* True if a locking error has occurred */
51326 #endif
@@ -51455,18 +51570,22 @@
51570 int nativeCksum; /* True for native byte-order checksums */
51571 u32 *aCksum = pWal->hdr.aFrameCksum;
51572 assert( WAL_FRAME_HDRSIZE==24 );
51573 sqlite3Put4byte(&aFrame[0], iPage);
51574 sqlite3Put4byte(&aFrame[4], nTruncate);
51575 if( pWal->iReCksum==0 ){
51576 memcpy(&aFrame[8], pWal->hdr.aSalt, 8);
51577
51578 nativeCksum = (pWal->hdr.bigEndCksum==SQLITE_BIGENDIAN);
51579 walChecksumBytes(nativeCksum, aFrame, 8, aCksum, aCksum);
51580 walChecksumBytes(nativeCksum, aData, pWal->szPage, aCksum, aCksum);
51581
51582 sqlite3Put4byte(&aFrame[16], aCksum[0]);
51583 sqlite3Put4byte(&aFrame[20], aCksum[1]);
51584 }else{
51585 memset(&aFrame[8], 0, 16);
51586 }
51587 }
51588
51589 /*
51590 ** Check to see if the frame with header in aFrame[] and content
51591 ** in aData[] is valid. If it is a valid frame, fill *piPage and
@@ -53389,10 +53508,11 @@
53508 int rc;
53509
53510 /* Cannot start a write transaction without first holding a read
53511 ** transaction. */
53512 assert( pWal->readLock>=0 );
53513 assert( pWal->writeLock==0 && pWal->iReCksum==0 );
53514
53515 if( pWal->readOnly ){
53516 return SQLITE_READONLY;
53517 }
53518
@@ -53424,10 +53544,11 @@
53544 */
53545 SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal){
53546 if( pWal->writeLock ){
53547 walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
53548 pWal->writeLock = 0;
53549 pWal->iReCksum = 0;
53550 pWal->truncateOnCommit = 0;
53551 }
53552 return SQLITE_OK;
53553 }
53554
@@ -53641,10 +53762,63 @@
53762 if( rc ) return rc;
53763 /* Write the page data */
53764 rc = walWriteToLog(p, pData, p->szPage, iOffset+sizeof(aFrame));
53765 return rc;
53766 }
53767
53768 /*
53769 ** This function is called as part of committing a transaction within which
53770 ** one or more frames have been overwritten. It updates the checksums for
53771 ** all frames written to the wal file by the current transaction starting
53772 ** with the earliest to have been overwritten.
53773 **
53774 ** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
53775 */
53776 static int walRewriteChecksums(Wal *pWal, u32 iLast){
53777 const int szPage = pWal->szPage;/* Database page size */
53778 int rc = SQLITE_OK; /* Return code */
53779 u8 *aBuf; /* Buffer to load data from wal file into */
53780 u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-headers in */
53781 u32 iRead; /* Next frame to read from wal file */
53782 i64 iCksumOff;
53783
53784 aBuf = sqlite3_malloc(szPage + WAL_FRAME_HDRSIZE);
53785 if( aBuf==0 ) return SQLITE_NOMEM;
53786
53787 /* Find the checksum values to use as input for the recalculating the
53788 ** first checksum. If the first frame is frame 1 (implying that the current
53789 ** transaction restarted the wal file), these values must be read from the
53790 ** wal-file header. Otherwise, read them from the frame header of the
53791 ** previous frame. */
53792 assert( pWal->iReCksum>0 );
53793 if( pWal->iReCksum==1 ){
53794 iCksumOff = 24;
53795 }else{
53796 iCksumOff = walFrameOffset(pWal->iReCksum-1, szPage) + 16;
53797 }
53798 rc = sqlite3OsRead(pWal->pWalFd, aBuf, sizeof(u32)*2, iCksumOff);
53799 pWal->hdr.aFrameCksum[0] = sqlite3Get4byte(aBuf);
53800 pWal->hdr.aFrameCksum[1] = sqlite3Get4byte(&aBuf[sizeof(u32)]);
53801
53802 iRead = pWal->iReCksum;
53803 pWal->iReCksum = 0;
53804 for(; rc==SQLITE_OK && iRead<=iLast; iRead++){
53805 i64 iOff = walFrameOffset(iRead, szPage);
53806 rc = sqlite3OsRead(pWal->pWalFd, aBuf, szPage+WAL_FRAME_HDRSIZE, iOff);
53807 if( rc==SQLITE_OK ){
53808 u32 iPgno, nDbSize;
53809 iPgno = sqlite3Get4byte(aBuf);
53810 nDbSize = sqlite3Get4byte(&aBuf[4]);
53811
53812 walEncodeFrame(pWal, iPgno, nDbSize, &aBuf[WAL_FRAME_HDRSIZE], aFrame);
53813 rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOff);
53814 }
53815 }
53816
53817 sqlite3_free(aBuf);
53818 return rc;
53819 }
53820
53821 /*
53822 ** Write a set of frames to the log. The caller must hold the write-lock
53823 ** on the log file (obtained using sqlite3WalBeginWriteTransaction()).
53824 */
@@ -53662,10 +53836,12 @@
53836 PgHdr *pLast = 0; /* Last frame in list */
53837 int nExtra = 0; /* Number of extra copies of last page */
53838 int szFrame; /* The size of a single frame */
53839 i64 iOffset; /* Next byte to write in WAL file */
53840 WalWriter w; /* The writer */
53841 u32 iFirst = 0; /* First frame that may be overwritten */
53842 WalIndexHdr *pLive; /* Pointer to shared header */
53843
53844 assert( pList );
53845 assert( pWal->writeLock );
53846
53847 /* If this frame set completes a transaction, then nTruncate>0. If
@@ -53676,10 +53852,15 @@
53852 { int cnt; for(cnt=0, p=pList; p; p=p->pDirty, cnt++){}
53853 WALTRACE(("WAL%p: frame write begin. %d frames. mxFrame=%d. %s\n",
53854 pWal, cnt, pWal->hdr.mxFrame, isCommit ? "Commit" : "Spill"));
53855 }
53856 #endif
53857
53858 pLive = (WalIndexHdr*)walIndexHdr(pWal);
53859 if( memcmp(&pWal->hdr, (void *)pLive, sizeof(WalIndexHdr))!=0 ){
53860 iFirst = pLive->mxFrame+1;
53861 }
53862
53863 /* See if it is possible to write these frames into the start of the
53864 ** log file, instead of appending to it at pWal->hdr.mxFrame.
53865 */
53866 if( SQLITE_OK!=(rc = walRestartLog(pWal)) ){
@@ -53741,17 +53922,45 @@
53922 szFrame = szPage + WAL_FRAME_HDRSIZE;
53923
53924 /* Write all frames into the log file exactly once */
53925 for(p=pList; p; p=p->pDirty){
53926 int nDbSize; /* 0 normally. Positive == commit flag */
53927
53928 /* Check if this page has already been written into the wal file by
53929 ** the current transaction. If so, overwrite the existing frame and
53930 ** set Wal.writeLock to WAL_WRITELOCK_RECKSUM - indicating that
53931 ** checksums must be recomputed when the transaction is committed. */
53932 if( iFirst && (p->pDirty || isCommit==0) ){
53933 u32 iWrite = 0;
53934 VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite);
53935 assert( rc==SQLITE_OK || iWrite==0 );
53936 if( iWrite>=iFirst ){
53937 i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE;
53938 if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){
53939 pWal->iReCksum = iWrite;
53940 }
53941 rc = sqlite3OsWrite(pWal->pWalFd, p->pData, szPage, iOff);
53942 if( rc ) return rc;
53943 p->flags &= ~PGHDR_WAL_APPEND;
53944 continue;
53945 }
53946 }
53947
53948 iFrame++;
53949 assert( iOffset==walFrameOffset(iFrame, szPage) );
53950 nDbSize = (isCommit && p->pDirty==0) ? nTruncate : 0;
53951 rc = walWriteOneFrame(&w, p, nDbSize, iOffset);
53952 if( rc ) return rc;
53953 pLast = p;
53954 iOffset += szFrame;
53955 p->flags |= PGHDR_WAL_APPEND;
53956 }
53957
53958 /* Recalculate checksums within the wal file if required. */
53959 if( isCommit && pWal->iReCksum ){
53960 rc = walRewriteChecksums(pWal, iFrame);
53961 if( rc ) return rc;
53962 }
53963
53964 /* If this is the end of a transaction, then we might need to pad
53965 ** the transaction and/or sync the WAL file.
53966 **
@@ -53799,10 +54008,11 @@
54008 ** guarantees that there are no other writers, and no data that may
54009 ** be in use by existing readers is being overwritten.
54010 */
54011 iFrame = pWal->hdr.mxFrame;
54012 for(p=pList; p && rc==SQLITE_OK; p=p->pDirty){
54013 if( (p->flags & PGHDR_WAL_APPEND)==0 ) continue;
54014 iFrame++;
54015 rc = walIndexAppend(pWal, iFrame, p->pgno);
54016 }
54017 while( rc==SQLITE_OK && nExtra>0 ){
54018 iFrame++;
@@ -53911,10 +54121,11 @@
54121 }
54122 }
54123
54124 /* Copy data from the log to the database file. */
54125 if( rc==SQLITE_OK ){
54126
54127 if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
54128 rc = SQLITE_CORRUPT_BKPT;
54129 }else{
54130 rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
54131 }
@@ -54066,10 +54277,16 @@
54277 SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal){
54278 assert( pWal==0 || pWal->readLock>=0 );
54279 return (pWal ? pWal->szPage : 0);
54280 }
54281 #endif
54282
54283 /* Return the sqlite3_file object for the WAL file
54284 */
54285 SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal){
54286 return pWal->pWalFd;
54287 }
54288
54289 #endif /* #ifndef SQLITE_OMIT_WAL */
54290
54291 /************** End of wal.c *************************************************/
54292 /************** Begin file btmutex.c *****************************************/
@@ -54368,11 +54585,10 @@
54585 struct MemPage {
54586 u8 isInit; /* True if previously initialized. MUST BE FIRST! */
54587 u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
54588 u8 intKey; /* True if table b-trees. False for index b-trees */
54589 u8 intKeyLeaf; /* True if the leaf of an intKey table */
 
54590 u8 leaf; /* True if a leaf page */
54591 u8 hdrOffset; /* 100 for page 1. 0 otherwise */
54592 u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
54593 u8 max1bytePayload; /* min(maxLocal,127) */
54594 u8 bBusy; /* Prevent endless loops on corrupt database files */
@@ -54955,25 +55171,10 @@
55171
55172 return (p->sharable==0 || p->locked);
55173 }
55174 #endif
55175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55176
55177 /*
55178 ** Enter the mutex on every Btree associated with a database
55179 ** connection. This is needed (for example) prior to parsing
55180 ** a statement since we will be comparing table and column names
@@ -55004,18 +55205,10 @@
55205 p = db->aDb[i].pBt;
55206 if( p ) sqlite3BtreeLeave(p);
55207 }
55208 }
55209
 
 
 
 
 
 
 
 
55210 #ifndef NDEBUG
55211 /*
55212 ** Return true if the current thread holds the database connection
55213 ** mutex and all required BtShared mutexes.
55214 **
@@ -55085,10 +55278,29 @@
55278 p->pBt->db = p->db;
55279 }
55280 }
55281 }
55282 #endif /* if SQLITE_THREADSAFE */
55283
55284 #ifndef SQLITE_OMIT_INCRBLOB
55285 /*
55286 ** Enter a mutex on a Btree given a cursor owned by that Btree.
55287 **
55288 ** These entry points are used by incremental I/O only. Enter() is required
55289 ** any time OMIT_SHARED_CACHE is not defined, regardless of whether or not
55290 ** the build is threadsafe. Leave() is only required by threadsafe builds.
55291 */
55292 SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){
55293 sqlite3BtreeEnter(pCur->pBtree);
55294 }
55295 # if SQLITE_THREADSAFE
55296 SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
55297 sqlite3BtreeLeave(pCur->pBtree);
55298 }
55299 # endif
55300 #endif /* ifndef SQLITE_OMIT_INCRBLOB */
55301
55302 #endif /* ifndef SQLITE_OMIT_SHARED_CACHE */
55303
55304 /************** End of btmutex.c *********************************************/
55305 /************** Begin file btree.c *******************************************/
55306 /*
@@ -55541,10 +55753,14 @@
55753 */
55754 #ifdef SQLITE_DEBUG
55755 static int cursorHoldsMutex(BtCursor *p){
55756 return sqlite3_mutex_held(p->pBt->mutex);
55757 }
55758 static int cursorOwnsBtShared(BtCursor *p){
55759 assert( cursorHoldsMutex(p) );
55760 return (p->pBtree->db==p->pBt->db);
55761 }
55762 #endif
55763
55764 /*
55765 ** Invalidate the overflow cache of the cursor passed as the first argument.
55766 ** on the shared btree structure pBt.
@@ -55877,11 +56093,11 @@
56093 ** saveCursorPosition().
56094 */
56095 static int btreeRestoreCursorPosition(BtCursor *pCur){
56096 int rc;
56097 int skipNext;
56098 assert( cursorOwnsBtShared(pCur) );
56099 assert( pCur->eState>=CURSOR_REQUIRESEEK );
56100 if( pCur->eState==CURSOR_FAULT ){
56101 return pCur->skipNext;
56102 }
56103 pCur->eState = CURSOR_INVALID;
@@ -56166,11 +56382,10 @@
56382 u8 *pCell, /* Pointer to the cell text. */
56383 CellInfo *pInfo /* Fill in this structure */
56384 ){
56385 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
56386 assert( pPage->leaf==0 );
 
56387 assert( pPage->childPtrSize==4 );
56388 #ifndef SQLITE_DEBUG
56389 UNUSED_PARAMETER(pPage);
56390 #endif
56391 pInfo->nSize = 4 + getVarint(&pCell[4], (u64*)&pInfo->nKey);
@@ -56188,12 +56403,10 @@
56403 u32 nPayload; /* Number of bytes of cell payload */
56404 u64 iKey; /* Extracted Key value */
56405
56406 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
56407 assert( pPage->leaf==0 || pPage->leaf==1 );
 
 
56408 assert( pPage->intKeyLeaf );
56409 assert( pPage->childPtrSize==0 );
56410 pIter = pCell;
56411
56412 /* The next block of code is equivalent to:
@@ -56258,11 +56471,10 @@
56471 u32 nPayload; /* Number of bytes of cell payload */
56472
56473 assert( sqlite3_mutex_held(pPage->pBt->mutex) );
56474 assert( pPage->leaf==0 || pPage->leaf==1 );
56475 assert( pPage->intKeyLeaf==0 );
 
56476 pIter = pCell + pPage->childPtrSize;
56477 nPayload = *pIter;
56478 if( nPayload>=0x80 ){
56479 u8 *pEnd = &pIter[8];
56480 nPayload &= 0x7f;
@@ -56319,11 +56531,10 @@
56531 ** this function verifies that this invariant is not violated. */
56532 CellInfo debuginfo;
56533 pPage->xParseCell(pPage, pCell, &debuginfo);
56534 #endif
56535
 
56536 nSize = *pIter;
56537 if( nSize>=0x80 ){
56538 pEnd = &pIter[8];
56539 nSize &= 0x7f;
56540 do{
@@ -56777,15 +56988,13 @@
56988 ** table b-tree page. */
56989 assert( (PTF_LEAFDATA|PTF_INTKEY|PTF_LEAF)==13 );
56990 pPage->intKey = 1;
56991 if( pPage->leaf ){
56992 pPage->intKeyLeaf = 1;
 
56993 pPage->xParseCell = btreeParseCellPtr;
56994 }else{
56995 pPage->intKeyLeaf = 0;
 
56996 pPage->xCellSize = cellSizePtrNoPayload;
56997 pPage->xParseCell = btreeParseCellPtrNoPayload;
56998 }
56999 pPage->maxLocal = pBt->maxLeaf;
57000 pPage->minLocal = pBt->minLeaf;
@@ -56796,11 +57005,10 @@
57005 /* EVIDENCE-OF: R-16571-11615 A value of 10 means the page is a leaf
57006 ** index b-tree page. */
57007 assert( (PTF_ZERODATA|PTF_LEAF)==10 );
57008 pPage->intKey = 0;
57009 pPage->intKeyLeaf = 0;
 
57010 pPage->xParseCell = btreeParseCellPtrIndex;
57011 pPage->maxLocal = pBt->maxLocal;
57012 pPage->minLocal = pBt->minLocal;
57013 }else{
57014 /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
@@ -58217,11 +58425,10 @@
58425 ** no progress. By returning SQLITE_BUSY and not invoking the busy callback
58426 ** when A already has a read lock, we encourage A to give up and let B
58427 ** proceed.
58428 */
58429 SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
 
58430 BtShared *pBt = p->pBt;
58431 int rc = SQLITE_OK;
58432
58433 sqlite3BtreeEnter(p);
58434 btreeIntegrity(p);
@@ -58240,31 +58447,34 @@
58447 rc = SQLITE_READONLY;
58448 goto trans_begun;
58449 }
58450
58451 #ifndef SQLITE_OMIT_SHARED_CACHE
58452 {
58453 sqlite3 *pBlock = 0;
58454 /* If another database handle has already opened a write transaction
58455 ** on this shared-btree structure and a second write transaction is
58456 ** requested, return SQLITE_LOCKED.
58457 */
58458 if( (wrflag && pBt->inTransaction==TRANS_WRITE)
58459 || (pBt->btsFlags & BTS_PENDING)!=0
58460 ){
58461 pBlock = pBt->pWriter->db;
58462 }else if( wrflag>1 ){
58463 BtLock *pIter;
58464 for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
58465 if( pIter->pBtree!=p ){
58466 pBlock = pIter->pBtree->db;
58467 break;
58468 }
58469 }
58470 }
58471 if( pBlock ){
58472 sqlite3ConnectionBlocked(p->db, pBlock);
58473 rc = SQLITE_LOCKED_SHAREDCACHE;
58474 goto trans_begun;
58475 }
58476 }
58477 #endif
58478
58479 /* Any read-only or read-write transaction implies a read-lock on
58480 ** page 1. So if some other shared-cache client already has a write-lock
@@ -59377,11 +59587,11 @@
59587 ** Failure is not possible. This function always returns SQLITE_OK.
59588 ** It might just as well be a procedure (returning void) but we continue
59589 ** to return an integer result code for historical reasons.
59590 */
59591 SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
59592 assert( cursorOwnsBtShared(pCur) );
59593 assert( pCur->eState==CURSOR_VALID );
59594 assert( pCur->iPage>=0 );
59595 assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
59596 assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
59597 getCellInfo(pCur);
@@ -59757,11 +59967,11 @@
59967 if ( pCur->eState==CURSOR_INVALID ){
59968 return SQLITE_ABORT;
59969 }
59970 #endif
59971
59972 assert( cursorOwnsBtShared(pCur) );
59973 rc = restoreCursorPosition(pCur);
59974 if( rc==SQLITE_OK ){
59975 assert( pCur->eState==CURSOR_VALID );
59976 assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
59977 assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
@@ -59795,11 +60005,11 @@
60005 ){
60006 u32 amt;
60007 assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
60008 assert( pCur->eState==CURSOR_VALID );
60009 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
60010 assert( cursorOwnsBtShared(pCur) );
60011 assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
60012 assert( pCur->info.nSize>0 );
60013 assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
60014 assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
60015 amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload);
@@ -59841,11 +60051,11 @@
60051 ** vice-versa).
60052 */
60053 static int moveToChild(BtCursor *pCur, u32 newPgno){
60054 BtShared *pBt = pCur->pBt;
60055
60056 assert( cursorOwnsBtShared(pCur) );
60057 assert( pCur->eState==CURSOR_VALID );
60058 assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
60059 assert( pCur->iPage>=0 );
60060 if( pCur->iPage>=(BTCURSOR_MAX_DEPTH-1) ){
60061 return SQLITE_CORRUPT_BKPT;
@@ -59887,11 +60097,11 @@
60097 ** to the page we are coming from. If we are coming from the
60098 ** right-most child page then pCur->idx is set to one more than
60099 ** the largest cell index.
60100 */
60101 static void moveToParent(BtCursor *pCur){
60102 assert( cursorOwnsBtShared(pCur) );
60103 assert( pCur->eState==CURSOR_VALID );
60104 assert( pCur->iPage>0 );
60105 assert( pCur->apPage[pCur->iPage] );
60106 assertParentIndex(
60107 pCur->apPage[pCur->iPage-1],
@@ -59927,11 +60137,11 @@
60137 */
60138 static int moveToRoot(BtCursor *pCur){
60139 MemPage *pRoot;
60140 int rc = SQLITE_OK;
60141
60142 assert( cursorOwnsBtShared(pCur) );
60143 assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
60144 assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
60145 assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
60146 if( pCur->eState>=CURSOR_REQUIRESEEK ){
60147 if( pCur->eState==CURSOR_FAULT ){
@@ -60006,11 +60216,11 @@
60216 static int moveToLeftmost(BtCursor *pCur){
60217 Pgno pgno;
60218 int rc = SQLITE_OK;
60219 MemPage *pPage;
60220
60221 assert( cursorOwnsBtShared(pCur) );
60222 assert( pCur->eState==CURSOR_VALID );
60223 while( rc==SQLITE_OK && !(pPage = pCur->apPage[pCur->iPage])->leaf ){
60224 assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
60225 pgno = get4byte(findCell(pPage, pCur->aiIdx[pCur->iPage]));
60226 rc = moveToChild(pCur, pgno);
@@ -60031,11 +60241,11 @@
60241 static int moveToRightmost(BtCursor *pCur){
60242 Pgno pgno;
60243 int rc = SQLITE_OK;
60244 MemPage *pPage = 0;
60245
60246 assert( cursorOwnsBtShared(pCur) );
60247 assert( pCur->eState==CURSOR_VALID );
60248 while( !(pPage = pCur->apPage[pCur->iPage])->leaf ){
60249 pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
60250 pCur->aiIdx[pCur->iPage] = pPage->nCell;
60251 rc = moveToChild(pCur, pgno);
@@ -60052,11 +60262,11 @@
60262 ** or set *pRes to 1 if the table is empty.
60263 */
60264 SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
60265 int rc;
60266
60267 assert( cursorOwnsBtShared(pCur) );
60268 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
60269 rc = moveToRoot(pCur);
60270 if( rc==SQLITE_OK ){
60271 if( pCur->eState==CURSOR_INVALID ){
60272 assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
@@ -60075,11 +60285,11 @@
60285 ** or set *pRes to 1 if the table is empty.
60286 */
60287 SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
60288 int rc;
60289
60290 assert( cursorOwnsBtShared(pCur) );
60291 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
60292
60293 /* If the cursor already points to the last entry, this is a no-op. */
60294 if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
60295 #ifdef SQLITE_DEBUG
@@ -60153,11 +60363,11 @@
60363 int *pRes /* Write search results here */
60364 ){
60365 int rc;
60366 RecordCompare xRecordCompare;
60367
60368 assert( cursorOwnsBtShared(pCur) );
60369 assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
60370 assert( pRes );
60371 assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
60372
60373 /* If the cursor is already positioned at the point we are trying
@@ -60401,11 +60611,11 @@
60611 static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
60612 int rc;
60613 int idx;
60614 MemPage *pPage;
60615
60616 assert( cursorOwnsBtShared(pCur) );
60617 assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
60618 assert( *pRes==0 );
60619 if( pCur->eState!=CURSOR_VALID ){
60620 assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
60621 rc = restoreCursorPosition(pCur);
@@ -60465,11 +60675,11 @@
60675 return moveToLeftmost(pCur);
60676 }
60677 }
60678 SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
60679 MemPage *pPage;
60680 assert( cursorOwnsBtShared(pCur) );
60681 assert( pRes!=0 );
60682 assert( *pRes==0 || *pRes==1 );
60683 assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
60684 pCur->info.nSize = 0;
60685 pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
@@ -60510,11 +60720,11 @@
60720 */
60721 static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
60722 int rc;
60723 MemPage *pPage;
60724
60725 assert( cursorOwnsBtShared(pCur) );
60726 assert( pRes!=0 );
60727 assert( *pRes==0 );
60728 assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
60729 assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
60730 assert( pCur->info.nSize==0 );
@@ -60566,11 +60776,11 @@
60776 }
60777 }
60778 return rc;
60779 }
60780 SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
60781 assert( cursorOwnsBtShared(pCur) );
60782 assert( pRes!=0 );
60783 assert( *pRes==0 || *pRes==1 );
60784 assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
60785 *pRes = 0;
60786 pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
@@ -63046,11 +63256,11 @@
63256 if( pCur->eState==CURSOR_FAULT ){
63257 assert( pCur->skipNext!=SQLITE_OK );
63258 return pCur->skipNext;
63259 }
63260
63261 assert( cursorOwnsBtShared(pCur) );
63262 assert( (pCur->curFlags & BTCF_WriteFlag)!=0
63263 && pBt->inTransaction==TRANS_WRITE
63264 && (pBt->btsFlags & BTS_READ_ONLY)==0 );
63265 assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
63266
@@ -63193,11 +63403,11 @@
63403 int iCellIdx; /* Index of cell to delete */
63404 int iCellDepth; /* Depth of node containing pCell */
63405 u16 szCell; /* Size of the cell being deleted */
63406 int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
63407
63408 assert( cursorOwnsBtShared(pCur) );
63409 assert( pBt->inTransaction==TRANS_WRITE );
63410 assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
63411 assert( pCur->curFlags & BTCF_WriteFlag );
63412 assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
63413 assert( !hasReadConflicts(p, pCur->pgnoRoot) );
@@ -64655,11 +64865,11 @@
64865 ** parameters that attempt to write past the end of the existing data,
64866 ** no modifications are made and SQLITE_CORRUPT is returned.
64867 */
64868 SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
64869 int rc;
64870 assert( cursorOwnsBtShared(pCsr) );
64871 assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
64872 assert( pCsr->curFlags & BTCF_Incrblob );
64873
64874 rc = restoreCursorPosition(pCsr);
64875 if( rc!=SQLITE_OK ){
@@ -64762,10 +64972,19 @@
64972
64973 /*
64974 ** Return the size of the header added to each page by this module.
64975 */
64976 SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void){ return ROUND8(sizeof(MemPage)); }
64977
64978 #if !defined(SQLITE_OMIT_SHARED_CACHE)
64979 /*
64980 ** Return true if the Btree passed as the only argument is sharable.
64981 */
64982 SQLITE_PRIVATE int sqlite3BtreeSharable(Btree *p){
64983 return p->sharable;
64984 }
64985 #endif
64986
64987 /************** End of btree.c ***********************************************/
64988 /************** Begin file backup.c ******************************************/
64989 /*
64990 ** 2009 January 28
@@ -67593,12 +67812,11 @@
67812 ** The zWhere string must have been obtained from sqlite3_malloc().
67813 ** This routine will take ownership of the allocated memory.
67814 */
67815 SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
67816 int j;
67817 sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
 
67818 for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
67819 }
67820
67821 /*
67822 ** Add an opcode that includes the p4 value as an integer.
@@ -68093,11 +68311,11 @@
68311 */
68312 static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
68313 if( aOp ){
68314 Op *pOp;
68315 for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
68316 if( pOp->p4type ) freeP4(db, pOp->p4type, pOp->p4.p);
68317 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
68318 sqlite3DbFree(db, pOp->zComment);
68319 #endif
68320 }
68321 }
@@ -68155,65 +68373,60 @@
68373 ** to a string or structure that is guaranteed to exist for the lifetime of
68374 ** the Vdbe. In these cases we can just copy the pointer.
68375 **
68376 ** If addr<0 then change P4 on the most recently inserted instruction.
68377 */
68378 static void SQLITE_NOINLINE vdbeChangeP4Full(
68379 Vdbe *p,
68380 Op *pOp,
68381 const char *zP4,
68382 int n
68383 ){
68384 if( pOp->p4type ){
68385 freeP4(p->db, pOp->p4type, pOp->p4.p);
68386 pOp->p4type = 0;
68387 pOp->p4.p = 0;
68388 }
68389 if( n<0 ){
68390 sqlite3VdbeChangeP4(p, (int)(pOp - p->aOp), zP4, n);
68391 }else{
68392 if( n==0 ) n = sqlite3Strlen30(zP4);
68393 pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
68394 pOp->p4type = P4_DYNAMIC;
68395 }
68396 }
68397 SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
68398 Op *pOp;
68399 sqlite3 *db;
68400 assert( p!=0 );
68401 db = p->db;
68402 assert( p->magic==VDBE_MAGIC_INIT );
68403 assert( p->aOp!=0 || db->mallocFailed );
68404 if( db->mallocFailed ){
68405 if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
 
68406 return;
68407 }
68408 assert( p->nOp>0 );
68409 assert( addr<p->nOp );
68410 if( addr<0 ){
68411 addr = p->nOp - 1;
68412 }
68413 pOp = &p->aOp[addr];
68414 if( n>=0 || pOp->p4type ){
68415 vdbeChangeP4Full(p, pOp, zP4, n);
68416 return;
68417 }
 
68418 if( n==P4_INT32 ){
68419 /* Note: this cast is safe, because the origin data point was an int
68420 ** that was cast to a (const char *). */
68421 pOp->p4.i = SQLITE_PTR_TO_INT(zP4);
68422 pOp->p4type = P4_INT32;
68423 }else if( zP4!=0 ){
68424 assert( n<0 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68425 pOp->p4.p = (void*)zP4;
68426 pOp->p4type = (signed char)n;
68427 if( n==P4_VTAB ) sqlite3VtabLock((VTable*)zP4);
 
 
 
68428 }
68429 }
68430
68431 /*
68432 ** Set the P4 on the most recently added opcode to the KeyInfo for the
@@ -68605,11 +68818,11 @@
68818 if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
68819 DbMaskSet(p->lockMask, i);
68820 }
68821 }
68822
68823 #if !defined(SQLITE_OMIT_SHARED_CACHE)
68824 /*
68825 ** If SQLite is compiled to support shared-cache mode and to be threadsafe,
68826 ** this routine obtains the mutex associated with each BtShared structure
68827 ** that may be accessed by the VM passed as an argument. In doing so it also
68828 ** sets the BtShared.db member of each of the BtShared structures, ensuring
@@ -76059,11 +76272,10 @@
76272 const u8 *zEndHdr; /* Pointer to first byte after the header */
76273 u32 offset; /* Offset into the data */
76274 u64 offset64; /* 64-bit offset */
76275 u32 avail; /* Number of bytes of available data */
76276 u32 t; /* A type code from the record header */
 
76277 Mem *pReg; /* PseudoTable input register */
76278
76279 p2 = pOp->p2;
76280 assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
76281 pDest = &aMem[pOp->p3];
@@ -76237,14 +76449,35 @@
76449 assert( p2<pC->nHdrParsed );
76450 assert( rc==SQLITE_OK );
76451 assert( sqlite3VdbeCheckMemInvariants(pDest) );
76452 if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest);
76453 assert( t==pC->aType[p2] );
76454 pDest->enc = encoding;
76455 if( pC->szRow>=aOffset[p2+1] ){
76456 /* This is the common case where the desired content fits on the original
76457 ** page - where the content is not on an overflow page */
76458 zData = pC->aRow + aOffset[p2];
76459 if( t<12 ){
76460 sqlite3VdbeSerialGet(zData, t, pDest);
76461 }else{
76462 /* If the column value is a string, we need a persistent value, not
76463 ** a MEM_Ephem value. This branch is a fast short-cut that is equivalent
76464 ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize().
76465 */
76466 static const u16 aFlag[] = { MEM_Blob, MEM_Str|MEM_Term };
76467 pDest->n = len = (t-12)/2;
76468 if( pDest->szMalloc < len+2 ){
76469 pDest->flags = MEM_Null;
76470 if( sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
76471 }else{
76472 pDest->z = pDest->zMalloc;
76473 }
76474 memcpy(pDest->z, zData, len);
76475 pDest->z[len] = 0;
76476 pDest->z[len+1] = 0;
76477 pDest->flags = aFlag[t&1];
76478 }
76479 }else{
76480 /* This branch happens only when content is on overflow pages */
76481 if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
76482 && ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
76483 || (len = sqlite3VdbeSerialTypeLen(t))==0
@@ -76252,42 +76485,24 @@
76485 /* Content is irrelevant for
76486 ** 1. the typeof() function,
76487 ** 2. the length(X) function if X is a blob, and
76488 ** 3. if the content length is zero.
76489 ** So we might as well use bogus content rather than reading
76490 ** content from disk. */
76491 static u8 aZero[8]; /* This is the bogus content */
76492 sqlite3VdbeSerialGet(aZero, t, pDest);
 
76493 }else{
76494 rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, !pC->isTable,
76495 pDest);
76496 if( rc==SQLITE_OK ){
76497 sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
76498 pDest->flags &= ~MEM_Ephem;
76499 }
76500 }
76501 }
76502
76503 op_column_out:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76504 op_column_error:
76505 UPDATE_MAX_BLOBSIZE(pDest);
76506 REGISTER_TRACE(pOp->p3, pDest);
76507 break;
76508 }
@@ -81685,11 +81900,11 @@
81900 assert( pReadr->aBuffer==0 );
81901 assert( pReadr->aMap==0 );
81902
81903 rc = vdbePmaReaderSeek(pTask, pReadr, pFile, iStart);
81904 if( rc==SQLITE_OK ){
81905 u64 nByte = 0; /* Size of PMA in bytes */
81906 rc = vdbePmaReadVarint(pReadr, &nByte);
81907 pReadr->iEof = pReadr->iReadOff + nByte;
81908 *pnByte += nByte;
81909 }
81910
@@ -84243,13 +84458,12 @@
84458 ** return the top-level walk call.
84459 **
84460 ** The return value from this routine is WRC_Abort to abandon the tree walk
84461 ** and WRC_Continue to continue.
84462 */
84463 static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
84464 int rc;
 
84465 testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
84466 testcase( ExprHasProperty(pExpr, EP_Reduced) );
84467 rc = pWalker->xExprCallback(pWalker, pExpr);
84468 if( rc==WRC_Continue
84469 && !ExprHasProperty(pExpr,EP_TokenOnly) ){
@@ -84260,10 +84474,13 @@
84474 }else{
84475 if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
84476 }
84477 }
84478 return rc & WRC_Abort;
84479 }
84480 SQLITE_PRIVATE int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
84481 return pExpr ? walkExpr(pWalker,pExpr) : WRC_Continue;
84482 }
84483
84484 /*
84485 ** Call sqlite3WalkExpr() for every expression in list p or until
84486 ** an abort request is seen.
@@ -86327,12 +86544,13 @@
86544 || sqlite3GetInt32(pToken->z, &iValue)==0 ){
86545 nExtra = pToken->n+1;
86546 assert( iValue>=0 );
86547 }
86548 }
86549 pNew = sqlite3DbMallocRaw(db, sizeof(Expr)+nExtra);
86550 if( pNew ){
86551 memset(pNew, 0, sizeof(Expr));
86552 pNew->op = (u8)op;
86553 pNew->iAgg = -1;
86554 if( pToken ){
86555 if( nExtra==0 ){
86556 pNew->flags |= EP_IntValue;
@@ -93723,19 +93941,10 @@
93941 ** COMMIT
93942 ** ROLLBACK
93943 */
93944 /* #include "sqliteInt.h" */
93945
 
 
 
 
 
 
 
 
 
93946 #ifndef SQLITE_OMIT_SHARED_CACHE
93947 /*
93948 ** The TableLock structure is only used by the sqlite3TableLock() and
93949 ** codeTableLocks() functions.
93950 */
@@ -100072,14 +100281,14 @@
100281
100282 /*
100283 ** A structure defining how to do GLOB-style comparisons.
100284 */
100285 struct compareInfo {
100286 u8 matchAll; /* "*" or "%" */
100287 u8 matchOne; /* "?" or "_" */
100288 u8 matchSet; /* "[" or 0 */
100289 u8 noCase; /* true to ignore case differences */
100290 };
100291
100292 /*
100293 ** For LIKE and GLOB matching on EBCDIC machines, assume that every
100294 ** character is exactly one byte in size. Also, provde the Utf8Read()
@@ -100138,26 +100347,18 @@
100347 */
100348 static int patternCompare(
100349 const u8 *zPattern, /* The glob pattern */
100350 const u8 *zString, /* The string to compare against the glob */
100351 const struct compareInfo *pInfo, /* Information about how to do the compare */
100352 u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */
100353 ){
100354 u32 c, c2; /* Next pattern and input string chars */
100355 u32 matchOne = pInfo->matchOne; /* "?" or "_" */
100356 u32 matchAll = pInfo->matchAll; /* "*" or "%" */
 
100357 u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
100358 const u8 *zEscaped = 0; /* One past the last escaped input char */
100359
 
 
 
 
 
 
 
100360 while( (c = Utf8Read(zPattern))!=0 ){
100361 if( c==matchAll ){ /* Match "*" */
100362 /* Skip over multiple "*" characters in the pattern. If there
100363 ** are also "?" characters, skip those as well, but consume a
100364 ** single character of the input string for each "?" skipped */
@@ -100167,19 +100368,19 @@
100368 }
100369 }
100370 if( c==0 ){
100371 return 1; /* "*" at the end of the pattern matches */
100372 }else if( c==matchOther ){
100373 if( pInfo->matchSet==0 ){
100374 c = sqlite3Utf8Read(&zPattern);
100375 if( c==0 ) return 0;
100376 }else{
100377 /* "[...]" immediately follows the "*". We have to do a slow
100378 ** recursive search in this case, but it is an unusual case. */
100379 assert( matchOther<0x80 ); /* '[' is a single-byte character */
100380 while( *zString
100381 && patternCompare(&zPattern[-1],zString,pInfo,matchOther)==0 ){
100382 SQLITE_SKIP_UTF8(zString);
100383 }
100384 return *zString!=0;
100385 }
100386 }
@@ -100201,22 +100402,22 @@
100402 }else{
100403 cx = c;
100404 }
100405 while( (c2 = *(zString++))!=0 ){
100406 if( c2!=c && c2!=cx ) continue;
100407 if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
100408 }
100409 }else{
100410 while( (c2 = Utf8Read(zString))!=0 ){
100411 if( c2!=c ) continue;
100412 if( patternCompare(zPattern,zString,pInfo,matchOther) ) return 1;
100413 }
100414 }
100415 return 0;
100416 }
100417 if( c==matchOther ){
100418 if( pInfo->matchSet==0 ){
100419 c = sqlite3Utf8Read(&zPattern);
100420 if( c==0 ) return 0;
100421 zEscaped = zPattern;
100422 }else{
100423 u32 prior_c = 0;
@@ -100265,11 +100466,11 @@
100466
100467 /*
100468 ** The sqlite3_strglob() interface.
100469 */
100470 SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlobPattern, const char *zString){
100471 return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[')==0;
100472 }
100473
100474 /*
100475 ** The sqlite3_strlike() interface.
100476 */
@@ -100303,13 +100504,14 @@
100504 sqlite3_context *context,
100505 int argc,
100506 sqlite3_value **argv
100507 ){
100508 const unsigned char *zA, *zB;
100509 u32 escape;
100510 int nPat;
100511 sqlite3 *db = sqlite3_context_db_handle(context);
100512 struct compareInfo *pInfo = sqlite3_user_data(context);
100513
100514 #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
100515 if( sqlite3_value_type(argv[0])==SQLITE_BLOB
100516 || sqlite3_value_type(argv[1])==SQLITE_BLOB
100517 ){
@@ -100345,17 +100547,17 @@
100547 sqlite3_result_error(context,
100548 "ESCAPE expression must be a single character", -1);
100549 return;
100550 }
100551 escape = sqlite3Utf8Read(&zEsc);
100552 }else{
100553 escape = pInfo->matchSet;
100554 }
100555 if( zA && zB ){
 
100556 #ifdef SQLITE_TEST
100557 sqlite3_like_count++;
100558 #endif
 
100559 sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
100560 }
100561 }
100562
100563 /*
@@ -109688,10 +109890,11 @@
109890 int nOBSat; /* Number of ORDER BY terms satisfied by indices */
109891 int iECursor; /* Cursor number for the sorter */
109892 int regReturn; /* Register holding block-output return address */
109893 int labelBkOut; /* Start label for the block-output subroutine */
109894 int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */
109895 int labelDone; /* Jump here when done, ex: LIMIT reached */
109896 u8 sortFlags; /* Zero or more SORTFLAG_* bits */
109897 };
109898 #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
109899
109900 /*
@@ -109745,33 +109948,41 @@
109948 Expr *pOffset /* OFFSET value. NULL means no offset */
109949 ){
109950 Select *pNew;
109951 Select standin;
109952 sqlite3 *db = pParse->db;
109953 pNew = sqlite3DbMallocRaw(db, sizeof(*pNew) );
109954 if( pNew==0 ){
109955 assert( db->mallocFailed );
109956 pNew = &standin;
 
109957 }
109958 if( pEList==0 ){
109959 pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
109960 }
109961 pNew->pEList = pEList;
109962 pNew->op = TK_SELECT;
109963 pNew->selFlags = selFlags;
109964 pNew->iLimit = 0;
109965 pNew->iOffset = 0;
109966 #if SELECTTRACE_ENABLED
109967 pNew->zSelName[0] = 0;
109968 #endif
109969 pNew->addrOpenEphm[0] = -1;
109970 pNew->addrOpenEphm[1] = -1;
109971 pNew->nSelectRow = 0;
109972 if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
109973 pNew->pSrc = pSrc;
109974 pNew->pWhere = pWhere;
109975 pNew->pGroupBy = pGroupBy;
109976 pNew->pHaving = pHaving;
109977 pNew->pOrderBy = pOrderBy;
109978 pNew->pPrior = 0;
109979 pNew->pNext = 0;
109980 pNew->pLimit = pLimit;
109981 pNew->pOffset = pOffset;
109982 pNew->pWith = 0;
109983 assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
 
 
109984 if( db->mallocFailed ) {
109985 clearSelect(db, pNew, pNew!=&standin);
109986 pNew = 0;
109987 }else{
109988 assert( pNew->pSrc!=0 || pParse->nErr>0 );
@@ -110142,10 +110353,11 @@
110353 int nBase = nExpr + bSeq + nData; /* Fields in sorter record */
110354 int regBase; /* Regs for sorter record */
110355 int regRecord = ++pParse->nMem; /* Assembled sorter record */
110356 int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */
110357 int op; /* Opcode to add sorter record to sorter */
110358 int iLimit; /* LIMIT counter */
110359
110360 assert( bSeq==0 || bSeq==1 );
110361 assert( nData==1 || regData==regOrigData );
110362 if( nPrefixReg ){
110363 assert( nPrefixReg==nExpr+bSeq );
@@ -110152,19 +110364,21 @@
110364 regBase = regData - nExpr - bSeq;
110365 }else{
110366 regBase = pParse->nMem + 1;
110367 pParse->nMem += nBase;
110368 }
110369 assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
110370 iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
110371 pSort->labelDone = sqlite3VdbeMakeLabel(v);
110372 sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
110373 SQLITE_ECEL_DUP|SQLITE_ECEL_REF);
110374 if( bSeq ){
110375 sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
110376 }
110377 if( nPrefixReg==0 ){
110378 sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
110379 }
 
110380 sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
110381 if( nOBSat>0 ){
110382 int regPrevKey; /* The first nOBSat columns of the previous row */
110383 int addrFirst; /* Address of the OP_IfNot opcode */
110384 int addrJmp; /* Address of the OP_Jump opcode */
@@ -110195,10 +110409,14 @@
110409 sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
110410 pSort->labelBkOut = sqlite3VdbeMakeLabel(v);
110411 pSort->regReturn = ++pParse->nMem;
110412 sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
110413 sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
110414 if( iLimit ){
110415 sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone);
110416 VdbeCoverage(v);
110417 }
110418 sqlite3VdbeJumpHere(v, addrFirst);
110419 sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat);
110420 sqlite3VdbeJumpHere(v, addrJmp);
110421 }
110422 if( pSort->sortFlags & SORTFLAG_UseSorter ){
@@ -110205,18 +110423,12 @@
110423 op = OP_SorterInsert;
110424 }else{
110425 op = OP_IdxInsert;
110426 }
110427 sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
110428 if( iLimit ){
110429 int addr;
 
 
 
 
 
 
110430 addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
110431 sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
110432 sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
110433 sqlite3VdbeJumpHere(v, addr);
110434 }
@@ -110816,11 +111028,11 @@
111028 SortCtx *pSort, /* Information on the ORDER BY clause */
111029 int nColumn, /* Number of columns of data */
111030 SelectDest *pDest /* Write the sorted results here */
111031 ){
111032 Vdbe *v = pParse->pVdbe; /* The prepared statement */
111033 int addrBreak = pSort->labelDone; /* Jump here to exit loop */
111034 int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */
111035 int addr;
111036 int addrOnce = 0;
111037 int iTab;
111038 ExprList *pOrderBy = pSort->pOrderBy;
@@ -110835,10 +111047,11 @@
111047 int bSeq; /* True if sorter record includes seq. no. */
111048 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
111049 struct ExprList_item *aOutEx = p->pEList->a;
111050 #endif
111051
111052 assert( addrBreak<0 );
111053 if( pSort->labelBkOut ){
111054 sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
111055 sqlite3VdbeGoto(v, addrBreak);
111056 sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
111057 }
@@ -126875,12 +127088,11 @@
127088 testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS );
127089 if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){
127090 Bitmask b = pTabItem->colUsed;
127091 int n = 0;
127092 for(; b; b=b>>1, n++){}
127093 sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32);
 
127094 assert( n<=pTab->nCol );
127095 }
127096 #ifdef SQLITE_ENABLE_CURSOR_HINTS
127097 if( pLoop->u.btree.pIndex!=0 ){
127098 sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete);
@@ -129343,18 +129555,15 @@
129555 ** { ... } // User supplied code
129556 ** #line <lineno> <thisfile>
129557 ** break;
129558 */
129559 /********** Begin reduce actions **********************************************/
 
 
 
129560 case 6: /* explain ::= EXPLAIN */
129561 { pParse->explain = 1; }
129562 break;
129563 case 7: /* explain ::= EXPLAIN QUERY PLAN */
129564 { pParse->explain = 2; }
129565 break;
129566 case 8: /* cmdx ::= cmd */
129567 { sqlite3FinishCoding(pParse); }
129568 break;
129569 case 9: /* cmd ::= BEGIN transtype trans_opt */
@@ -130525,10 +130734,11 @@
130734 /* (0) input ::= cmdlist */ yytestcase(yyruleno==0);
130735 /* (1) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==1);
130736 /* (2) cmdlist ::= ecmd */ yytestcase(yyruleno==2);
130737 /* (3) ecmd ::= SEMI */ yytestcase(yyruleno==3);
130738 /* (4) ecmd ::= explain cmdx SEMI */ yytestcase(yyruleno==4);
130739 /* (5) explain ::= */ yytestcase(yyruleno==5);
130740 /* (10) trans_opt ::= */ yytestcase(yyruleno==10);
130741 /* (11) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==11);
130742 /* (12) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==12);
130743 /* (20) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==20);
130744 /* (21) savepoint_opt ::= */ yytestcase(yyruleno==21);
@@ -135450,10 +135660,13 @@
135660 *(sqlite3_file**)pArg = fd;
135661 rc = SQLITE_OK;
135662 }else if( op==SQLITE_FCNTL_VFS_POINTER ){
135663 *(sqlite3_vfs**)pArg = sqlite3PagerVfs(pPager);
135664 rc = SQLITE_OK;
135665 }else if( op==SQLITE_FCNTL_JOURNAL_POINTER ){
135666 *(sqlite3_file**)pArg = sqlite3PagerJrnlFile(pPager);
135667 rc = SQLITE_OK;
135668 }else if( fd->pMethods ){
135669 rc = sqlite3OsFileControl(fd, op, pArg);
135670 }else{
135671 rc = SQLITE_NOTFOUND;
135672 }
@@ -161083,11 +161296,11 @@
161296 */
161297 static void *rbuMalloc(sqlite3rbu *p, int nByte){
161298 void *pRet = 0;
161299 if( p->rc==SQLITE_OK ){
161300 assert( nByte>0 );
161301 pRet = sqlite3_malloc64(nByte);
161302 if( pRet==0 ){
161303 p->rc = SQLITE_NOMEM;
161304 }else{
161305 memset(pRet, 0, nByte);
161306 }
@@ -161129,12 +161342,12 @@
161342 static char *rbuStrndup(const char *zStr, int *pRc){
161343 char *zRet = 0;
161344
161345 assert( *pRc==SQLITE_OK );
161346 if( zStr ){
161347 size_t nCopy = strlen(zStr) + 1;
161348 zRet = (char*)sqlite3_malloc64(nCopy);
161349 if( zRet ){
161350 memcpy(zRet, zStr, nCopy);
161351 }else{
161352 *pRc = SQLITE_NOMEM;
161353 }
@@ -162478,11 +162691,11 @@
162691
162692 pRbu->pgsz = iAmt;
162693 if( pRbu->nFrame==pRbu->nFrameAlloc ){
162694 int nNew = (pRbu->nFrameAlloc ? pRbu->nFrameAlloc : 64) * 2;
162695 RbuFrame *aNew;
162696 aNew = (RbuFrame*)sqlite3_realloc64(pRbu->aFrame, nNew * sizeof(RbuFrame));
162697 if( aNew==0 ) return SQLITE_NOMEM;
162698 pRbu->aFrame = aNew;
162699 pRbu->nFrameAlloc = nNew;
162700 }
162701
@@ -162543,11 +162756,11 @@
162756
162757 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
162758 if( nChar==0 ){
162759 return 0;
162760 }
162761 zWideFilename = sqlite3_malloc64( nChar*sizeof(zWideFilename[0]) );
162762 if( zWideFilename==0 ){
162763 return 0;
162764 }
162765 memset(zWideFilename, 0, nChar*sizeof(zWideFilename[0]));
162766 nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
@@ -163177,15 +163390,16 @@
163390 const char *zTarget,
163391 const char *zRbu,
163392 const char *zState
163393 ){
163394 sqlite3rbu *p;
163395 size_t nTarget = strlen(zTarget);
163396 size_t nRbu = strlen(zRbu);
163397 size_t nState = zState ? strlen(zState) : 0;
163398 size_t nByte = sizeof(sqlite3rbu) + nTarget+1 + nRbu+1+ nState+1;
163399
163400 p = (sqlite3rbu*)sqlite3_malloc64(nByte);
163401 if( p ){
163402 RbuState *pState = 0;
163403
163404 /* Create the custom VFS. */
163405 memset(p, 0, sizeof(sqlite3rbu));
@@ -163318,11 +163532,11 @@
163532 ** the pattern "rbu_imp_[0-9]*".
163533 */
163534 static void rbuEditErrmsg(sqlite3rbu *p){
163535 if( p->rc==SQLITE_CONSTRAINT && p->zErrmsg ){
163536 int i;
163537 size_t nErrmsg = strlen(p->zErrmsg);
163538 for(i=0; i<(nErrmsg-8); i++){
163539 if( memcmp(&p->zErrmsg[i], "rbu_imp_", 8)==0 ){
163540 int nDel = 8;
163541 while( p->zErrmsg[i+nDel]>='0' && p->zErrmsg[i+nDel]<='9' ) nDel++;
163542 memmove(&p->zErrmsg[i], &p->zErrmsg[i+nDel], nErrmsg + 1 - i - nDel);
@@ -163782,11 +163996,11 @@
163996 ** instead of a file on disk. */
163997 assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
163998 if( eStage==RBU_STAGE_OAL || eStage==RBU_STAGE_MOVE ){
163999 if( iRegion<=p->nShm ){
164000 int nByte = (iRegion+1) * sizeof(char*);
164001 char **apNew = (char**)sqlite3_realloc64(p->apShm, nByte);
164002 if( apNew==0 ){
164003 rc = SQLITE_NOMEM;
164004 }else{
164005 memset(&apNew[p->nShm], 0, sizeof(char*) * (1 + iRegion - p->nShm));
164006 p->apShm = apNew;
@@ -163793,11 +164007,11 @@
164007 p->nShm = iRegion+1;
164008 }
164009 }
164010
164011 if( rc==SQLITE_OK && p->apShm[iRegion]==0 ){
164012 char *pNew = (char*)sqlite3_malloc64(szRegion);
164013 if( pNew==0 ){
164014 rc = SQLITE_NOMEM;
164015 }else{
164016 memset(pNew, 0, szRegion);
164017 p->apShm[iRegion] = pNew;
@@ -163903,11 +164117,11 @@
164117 /* A main database has just been opened. The following block sets
164118 ** (pFd->zWal) to point to a buffer owned by SQLite that contains
164119 ** the name of the *-wal file this db connection will use. SQLite
164120 ** happens to pass a pointer to this buffer when using xAccess()
164121 ** or xOpen() to operate on the *-wal file. */
164122 int n = (int)strlen(zName);
164123 const char *z = &zName[n];
164124 if( flags & SQLITE_OPEN_URI ){
164125 int odd = 0;
164126 while( 1 ){
164127 if( z[0]==0 ){
@@ -163929,12 +164143,12 @@
164143 if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
164144 /* This call is to open a *-wal file. Intead, open the *-oal. This
164145 ** code ensures that the string passed to xOpen() is terminated by a
164146 ** pair of '\0' bytes in case the VFS attempts to extract a URI
164147 ** parameter from it. */
164148 size_t nCopy = strlen(zName);
164149 char *zCopy = sqlite3_malloc64(nCopy+2);
164150 if( zCopy ){
164151 memcpy(zCopy, zName, nCopy);
164152 zCopy[nCopy-3] = 'o';
164153 zCopy[nCopy] = '\0';
164154 zCopy[nCopy+1] = '\0';
@@ -164159,17 +164373,17 @@
164373 0, /* xCurrentTimeInt64 (version 2) */
164374 0, 0, 0 /* Unimplemented version 3 methods */
164375 };
164376
164377 rbu_vfs *pNew = 0; /* Newly allocated VFS */
 
164378 int rc = SQLITE_OK;
164379 size_t nName;
164380 size_t nByte;
164381
 
164382 nName = strlen(zName);
164383 nByte = sizeof(rbu_vfs) + nName + 1;
164384 pNew = (rbu_vfs*)sqlite3_malloc64(nByte);
164385 if( pNew==0 ){
164386 rc = SQLITE_NOMEM;
164387 }else{
164388 sqlite3_vfs *pParent; /* Parent VFS */
164389 memset(pNew, 0, nByte);
@@ -167174,10 +167388,13 @@
167388 ** If parameter iCol is greater than or equal to the number of columns
167389 ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
167390 ** an OOM condition or IO error), an appropriate SQLite error code is
167391 ** returned.
167392 **
167393 ** This function may be quite inefficient if used with an FTS5 table
167394 ** created with the "columnsize=0" option.
167395 **
167396 ** xColumnText:
167397 ** This function attempts to retrieve the text of column iCol of the
167398 ** current document. If successful, (*pz) is set to point to a buffer
167399 ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
167400 ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -167194,18 +167411,32 @@
167411 ** xInstCount:
167412 ** Set *pnInst to the total number of occurrences of all phrases within
167413 ** the query within the current row. Return SQLITE_OK if successful, or
167414 ** an error code (i.e. SQLITE_NOMEM) if an error occurs.
167415 **
167416 ** This API can be quite slow if used with an FTS5 table created with the
167417 ** "detail=none" or "detail=column" option. If the FTS5 table is created
167418 ** with either "detail=none" or "detail=column" and "content=" option
167419 ** (i.e. if it is a contentless table), then this API always returns 0.
167420 **
167421 ** xInst:
167422 ** Query for the details of phrase match iIdx within the current row.
167423 ** Phrase matches are numbered starting from zero, so the iIdx argument
167424 ** should be greater than or equal to zero and smaller than the value
167425 ** output by xInstCount().
167426 **
167427 ** Usually, output parameter *piPhrase is set to the phrase number, *piCol
167428 ** to the column in which it occurs and *piOff the token offset of the
167429 ** first token of the phrase. The exception is if the table was created
167430 ** with the offsets=0 option specified. In this case *piOff is always
167431 ** set to -1.
167432 **
167433 ** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
167434 ** if an error occurs.
167435 **
167436 ** This API can be quite slow if used with an FTS5 table created with the
167437 ** "detail=none" or "detail=column" option.
167438 **
167439 ** xRowid:
167440 ** Returns the rowid of the current row.
167441 **
167442 ** xTokenize:
@@ -167286,25 +167517,63 @@
167517 ** through instances of phrase iPhrase, use the following code:
167518 **
167519 ** Fts5PhraseIter iter;
167520 ** int iCol, iOff;
167521 ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
167522 ** iCol>=0;
167523 ** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
167524 ** ){
167525 ** // An instance of phrase iPhrase at offset iOff of column iCol
167526 ** }
167527 **
167528 ** The Fts5PhraseIter structure is defined above. Applications should not
167529 ** modify this structure directly - it should only be used as shown above
167530 ** with the xPhraseFirst() and xPhraseNext() API methods (and by
167531 ** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
167532 **
167533 ** This API can be quite slow if used with an FTS5 table created with the
167534 ** "detail=none" or "detail=column" option. If the FTS5 table is created
167535 ** with either "detail=none" or "detail=column" and "content=" option
167536 ** (i.e. if it is a contentless table), then this API always iterates
167537 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
167538 **
167539 ** xPhraseNext()
167540 ** See xPhraseFirst above.
167541 **
167542 ** xPhraseFirstColumn()
167543 ** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
167544 ** and xPhraseNext() APIs described above. The difference is that instead
167545 ** of iterating through all instances of a phrase in the current row, these
167546 ** APIs are used to iterate through the set of columns in the current row
167547 ** that contain one or more instances of a specified phrase. For example:
167548 **
167549 ** Fts5PhraseIter iter;
167550 ** int iCol;
167551 ** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
167552 ** iCol>=0;
167553 ** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
167554 ** ){
167555 ** // Column iCol contains at least one instance of phrase iPhrase
167556 ** }
167557 **
167558 ** This API can be quite slow if used with an FTS5 table created with the
167559 ** "detail=none" option. If the FTS5 table is created with either
167560 ** "detail=none" "content=" option (i.e. if it is a contentless table),
167561 ** then this API always iterates through an empty set (all calls to
167562 ** xPhraseFirstColumn() set iCol to -1).
167563 **
167564 ** The information accessed using this API and its companion
167565 ** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
167566 ** (or xInst/xInstCount). The chief advantage of this API is that it is
167567 ** significantly more efficient than those alternatives when used with
167568 ** "detail=column" tables.
167569 **
167570 ** xPhraseNextColumn()
167571 ** See xPhraseFirstColumn above.
167572 */
167573 struct Fts5ExtensionApi {
167574 int iVersion; /* Currently always set to 3 */
167575
167576 void *(*xUserData)(Fts5Context*);
167577
167578 int (*xColumnCount)(Fts5Context*);
167579 int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -167330,12 +167599,15 @@
167599 int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
167600 );
167601 int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
167602 void *(*xGetAuxdata)(Fts5Context*, int bClear);
167603
167604 int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
167605 void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
167606
167607 int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
167608 void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
167609 };
167610
167611 /*
167612 ** CUSTOM AUXILIARY FUNCTIONS
167613 *************************************************************************/
@@ -167762,10 +168034,11 @@
168034 int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */
168035 int eContent; /* An FTS5_CONTENT value */
168036 char *zContent; /* content table */
168037 char *zContentRowid; /* "content_rowid=" option value */
168038 int bColumnsize; /* "columnsize=" option value (dflt==1) */
168039 int eDetail; /* FTS5_DETAIL_XXX value */
168040 char *zContentExprlist;
168041 Fts5Tokenizer *pTok;
168042 fts5_tokenizer *pTokApi;
168043
168044 /* Values loaded from the %_config table */
@@ -167790,10 +168063,13 @@
168063
168064 #define FTS5_CONTENT_NORMAL 0
168065 #define FTS5_CONTENT_NONE 1
168066 #define FTS5_CONTENT_EXTERNAL 2
168067
168068 #define FTS5_DETAIL_FULL 0
168069 #define FTS5_DETAIL_NONE 1
168070 #define FTS5_DETAIL_COLUMNS 2
168071
168072
168073
168074 static int sqlite3Fts5ConfigParse(
168075 Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
@@ -167903,10 +168179,17 @@
168179 static char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn);
168180
168181 /* Character set tests (like isspace(), isalpha() etc.) */
168182 static int sqlite3Fts5IsBareword(char t);
168183
168184
168185 /* Bucket of terms object used by the integrity-check in offsets=0 mode. */
168186 typedef struct Fts5Termset Fts5Termset;
168187 static int sqlite3Fts5TermsetNew(Fts5Termset**);
168188 static int sqlite3Fts5TermsetAdd(Fts5Termset*, int, const char*, int, int *pbPresent);
168189 static void sqlite3Fts5TermsetFree(Fts5Termset*);
168190
168191 /*
168192 ** End of interface to code in fts5_buffer.c.
168193 **************************************************************************/
168194
168195 /**************************************************************************
@@ -168024,11 +168307,10 @@
168307 static int sqlite3Fts5IndexSetAverages(Fts5Index *p, const u8*, int);
168308
168309 /*
168310 ** Functions called by the storage module as part of integrity-check.
168311 */
 
168312 static int sqlite3Fts5IndexIntegrityCheck(Fts5Index*, u64 cksum);
168313
168314 /*
168315 ** Called during virtual module initialization to register UDF
168316 ** fts5_decode() with SQLite
@@ -168046,10 +168328,12 @@
168328 static int sqlite3Fts5IndexReinit(Fts5Index *p);
168329 static int sqlite3Fts5IndexOptimize(Fts5Index *p);
168330 static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge);
168331
168332 static int sqlite3Fts5IndexLoadConfig(Fts5Index *p);
168333
168334 static int sqlite3Fts5IterCollist(Fts5IndexIter*, const u8 **, int*);
168335
168336 /*
168337 ** End of interface to code in fts5_index.c.
168338 **************************************************************************/
168339
@@ -168103,11 +168387,11 @@
168387 typedef struct Fts5Hash Fts5Hash;
168388
168389 /*
168390 ** Create a hash table, free a hash table.
168391 */
168392 static int sqlite3Fts5HashNew(Fts5Config*, Fts5Hash**, int *pnSize);
168393 static void sqlite3Fts5HashFree(Fts5Hash*);
168394
168395 static int sqlite3Fts5HashWrite(
168396 Fts5Hash*,
168397 i64 iRowid, /* Rowid for this entry */
@@ -168239,12 +168523,22 @@
168523 static int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);
168524
168525 static int sqlite3Fts5ExprPhraseCount(Fts5Expr*);
168526 static int sqlite3Fts5ExprPhraseSize(Fts5Expr*, int iPhrase);
168527 static int sqlite3Fts5ExprPoslist(Fts5Expr*, int, const u8 **);
168528
168529 typedef struct Fts5PoslistPopulator Fts5PoslistPopulator;
168530 static Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr*, int);
168531 static int sqlite3Fts5ExprPopulatePoslists(
168532 Fts5Config*, Fts5Expr*, Fts5PoslistPopulator*, int, const char*, int
168533 );
168534 static void sqlite3Fts5ExprCheckPoslists(Fts5Expr*, i64);
168535 static void sqlite3Fts5ExprClearEof(Fts5Expr*);
168536
168537 static int sqlite3Fts5ExprClonePhrase(Fts5Config*, Fts5Expr*, int, Fts5Expr**);
168538
168539 static int sqlite3Fts5ExprPhraseCollist(Fts5Expr *, int, const u8 **, int *);
168540
168541 /*******************************************
168542 ** The fts5_expr.c API above this point is used by the other hand-written
168543 ** C code in this module. The interfaces below this point are called by
168544 ** the parser code in fts5parse.y. */
@@ -170397,10 +170691,93 @@
170691
170692 return (t & 0x80) || aBareword[(int)t];
170693 }
170694
170695
170696 /*************************************************************************
170697 */
170698 typedef struct Fts5TermsetEntry Fts5TermsetEntry;
170699 struct Fts5TermsetEntry {
170700 char *pTerm;
170701 int nTerm;
170702 int iIdx; /* Index (main or aPrefix[] entry) */
170703 Fts5TermsetEntry *pNext;
170704 };
170705
170706 struct Fts5Termset {
170707 Fts5TermsetEntry *apHash[512];
170708 };
170709
170710 static int sqlite3Fts5TermsetNew(Fts5Termset **pp){
170711 int rc = SQLITE_OK;
170712 *pp = sqlite3Fts5MallocZero(&rc, sizeof(Fts5Termset));
170713 return rc;
170714 }
170715
170716 static int sqlite3Fts5TermsetAdd(
170717 Fts5Termset *p,
170718 int iIdx,
170719 const char *pTerm, int nTerm,
170720 int *pbPresent
170721 ){
170722 int rc = SQLITE_OK;
170723 *pbPresent = 0;
170724 if( p ){
170725 int i;
170726 int hash;
170727 Fts5TermsetEntry *pEntry;
170728
170729 /* Calculate a hash value for this term */
170730 hash = 104 + iIdx;
170731 for(i=0; i<nTerm; i++){
170732 hash += (hash << 3) + (int)pTerm[i];
170733 }
170734 hash = hash % ArraySize(p->apHash);
170735
170736 for(pEntry=p->apHash[hash]; pEntry; pEntry=pEntry->pNext){
170737 if( pEntry->iIdx==iIdx
170738 && pEntry->nTerm==nTerm
170739 && memcmp(pEntry->pTerm, pTerm, nTerm)==0
170740 ){
170741 *pbPresent = 1;
170742 break;
170743 }
170744 }
170745
170746 if( pEntry==0 ){
170747 pEntry = sqlite3Fts5MallocZero(&rc, sizeof(Fts5TermsetEntry) + nTerm);
170748 if( pEntry ){
170749 pEntry->pTerm = (char*)&pEntry[1];
170750 pEntry->nTerm = nTerm;
170751 pEntry->iIdx = iIdx;
170752 memcpy(pEntry->pTerm, pTerm, nTerm);
170753 pEntry->pNext = p->apHash[hash];
170754 p->apHash[hash] = pEntry;
170755 }
170756 }
170757 }
170758
170759 return rc;
170760 }
170761
170762 static void sqlite3Fts5TermsetFree(Fts5Termset *p){
170763 if( p ){
170764 int i;
170765 for(i=0; i<ArraySize(p->apHash); i++){
170766 Fts5TermsetEntry *pEntry = p->apHash[i];
170767 while( pEntry ){
170768 Fts5TermsetEntry *pDel = pEntry;
170769 pEntry = pEntry->pNext;
170770 sqlite3_free(pDel);
170771 }
170772 }
170773 sqlite3_free(p);
170774 }
170775 }
170776
170777
170778
170779
170780 /*
170781 ** 2014 Jun 09
170782 **
170783 ** The author disclaims copyright to this source code. In place of
@@ -170412,11 +170789,10 @@
170789 **
170790 ******************************************************************************
170791 **
170792 ** This is an SQLite module implementing full-text search.
170793 */
 
170794
170795
170796 /* #include "fts5Int.h" */
170797
170798 #define FTS5_DEFAULT_PAGE_SIZE 4050
@@ -170595,10 +170971,37 @@
170971 if( quote=='[' || quote=='\'' || quote=='"' || quote=='`' ){
170972 fts5Dequote(z);
170973 }
170974 }
170975
170976
170977 struct Fts5Enum {
170978 const char *zName;
170979 int eVal;
170980 };
170981 typedef struct Fts5Enum Fts5Enum;
170982
170983 static int fts5ConfigSetEnum(
170984 const Fts5Enum *aEnum,
170985 const char *zEnum,
170986 int *peVal
170987 ){
170988 int nEnum = strlen(zEnum);
170989 int i;
170990 int iVal = -1;
170991
170992 for(i=0; aEnum[i].zName; i++){
170993 if( sqlite3_strnicmp(aEnum[i].zName, zEnum, nEnum)==0 ){
170994 if( iVal>=0 ) return SQLITE_ERROR;
170995 iVal = aEnum[i].eVal;
170996 }
170997 }
170998
170999 *peVal = iVal;
171000 return iVal<0 ? SQLITE_ERROR : SQLITE_OK;
171001 }
171002
171003 /*
171004 ** Parse a "special" CREATE VIRTUAL TABLE directive and update
171005 ** configuration object pConfig as appropriate.
171006 **
171007 ** If successful, object pConfig is updated and SQLITE_OK returned. If
@@ -170744,10 +171147,24 @@
171147 }else{
171148 pConfig->bColumnsize = (zArg[0]=='1');
171149 }
171150 return rc;
171151 }
171152
171153 if( sqlite3_strnicmp("detail", zCmd, nCmd)==0 ){
171154 const Fts5Enum aDetail[] = {
171155 { "none", FTS5_DETAIL_NONE },
171156 { "full", FTS5_DETAIL_FULL },
171157 { "columns", FTS5_DETAIL_COLUMNS },
171158 { 0, 0 }
171159 };
171160
171161 if( (rc = fts5ConfigSetEnum(aDetail, zArg, &pConfig->eDetail)) ){
171162 *pzErr = sqlite3_mprintf("malformed detail=... directive");
171163 }
171164 return rc;
171165 }
171166
171167 *pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
171168 return SQLITE_ERROR;
171169 }
171170
@@ -170900,10 +171317,11 @@
171317 pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte);
171318 pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
171319 pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
171320 pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
171321 pRet->bColumnsize = 1;
171322 pRet->eDetail = FTS5_DETAIL_FULL;
171323 #ifdef SQLITE_DEBUG
171324 pRet->bPrefixIndex = 1;
171325 #endif
171326 if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){
171327 *pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName);
@@ -171346,10 +171764,11 @@
171764 #endif
171765
171766
171767 struct Fts5Expr {
171768 Fts5Index *pIndex;
171769 Fts5Config *pConfig;
171770 Fts5ExprNode *pRoot;
171771 int bDesc; /* Iterate in descending rowid order */
171772 int nPhrase; /* Number of phrases in expression */
171773 Fts5ExprPhrase **apExprPhrase; /* Pointers to phrase objects */
171774 };
@@ -171541,10 +171960,11 @@
171960 sParse.rc = SQLITE_NOMEM;
171961 sqlite3Fts5ParseNodeFree(sParse.pExpr);
171962 }else{
171963 pNew->pRoot = sParse.pExpr;
171964 pNew->pIndex = 0;
171965 pNew->pConfig = pConfig;
171966 pNew->apExprPhrase = sParse.apPhrase;
171967 pNew->nPhrase = sParse.nPhrase;
171968 sParse.apPhrase = 0;
171969 }
171970 }
@@ -171605,12 +172025,13 @@
172025 }
172026
172027 /*
172028 ** Argument pTerm must be a synonym iterator.
172029 */
172030 static int fts5ExprSynonymList(
172031 Fts5ExprTerm *pTerm,
172032 int bCollist,
172033 Fts5Colset *pColset,
172034 i64 iRowid,
172035 int *pbDel, /* OUT: Caller should sqlite3_free(*pa) */
172036 u8 **pa, int *pn
172037 ){
@@ -171625,13 +172046,20 @@
172046 for(p=pTerm; p; p=p->pSynonym){
172047 Fts5IndexIter *pIter = p->pIter;
172048 if( sqlite3Fts5IterEof(pIter)==0 && sqlite3Fts5IterRowid(pIter)==iRowid ){
172049 const u8 *a;
172050 int n;
172051
172052 if( bCollist ){
172053 rc = sqlite3Fts5IterCollist(pIter, &a, &n);
172054 }else{
172055 i64 dummy;
172056 rc = sqlite3Fts5IterPoslist(pIter, pColset, &a, &n, &dummy);
172057 }
172058
172059 if( rc!=SQLITE_OK ) goto synonym_poslist_out;
172060 if( n==0 ) continue;
172061 if( nIter==nAlloc ){
172062 int nByte = sizeof(Fts5PoslistReader) * nAlloc * 2;
172063 Fts5PoslistReader *aNew = (Fts5PoslistReader*)sqlite3_malloc(nByte);
172064 if( aNew==0 ){
172065 rc = SQLITE_NOMEM;
@@ -171728,12 +172156,12 @@
172156 i64 dummy;
172157 int n = 0;
172158 int bFlag = 0;
172159 const u8 *a = 0;
172160 if( pTerm->pSynonym ){
172161 rc = fts5ExprSynonymList(
172162 pTerm, 0, pColset, pNode->iRowid, &bFlag, (u8**)&a, &n
172163 );
172164 }else{
172165 rc = sqlite3Fts5IterPoslist(pTerm->pIter, pColset, &a, &n, &dummy);
172166 }
172167 if( rc!=SQLITE_OK ) goto ismatch_out;
@@ -172063,34 +172491,55 @@
172491 Fts5Expr *pExpr, /* Expression that pNear is a part of */
172492 Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */
172493 ){
172494 Fts5ExprNearset *pNear = pNode->pNear;
172495 int rc = *pRc;
172496
172497 if( pExpr->pConfig->eDetail!=FTS5_DETAIL_FULL ){
172498 Fts5ExprTerm *pTerm;
172499 Fts5ExprPhrase *pPhrase = pNear->apPhrase[0];
172500 pPhrase->poslist.n = 0;
172501 for(pTerm=&pPhrase->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
172502 Fts5IndexIter *pIter = pTerm->pIter;
172503 if( sqlite3Fts5IterEof(pIter)==0 ){
172504 int n;
172505 i64 iRowid;
172506 rc = sqlite3Fts5IterPoslist(pIter, pNear->pColset, 0, &n, &iRowid);
172507 if( rc!=SQLITE_OK ){
172508 *pRc = rc;
172509 return 0;
172510 }else if( iRowid==pNode->iRowid && n>0 ){
172511 pPhrase->poslist.n = 1;
172512 }
172513 }
172514 }
172515 return pPhrase->poslist.n;
172516 }else{
172517 int i;
172518
172519 /* Check that each phrase in the nearset matches the current row.
172520 ** Populate the pPhrase->poslist buffers at the same time. If any
172521 ** phrase is not a match, break out of the loop early. */
172522 for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
172523 Fts5ExprPhrase *pPhrase = pNear->apPhrase[i];
172524 if( pPhrase->nTerm>1 || pPhrase->aTerm[0].pSynonym || pNear->pColset ){
172525 int bMatch = 0;
172526 rc = fts5ExprPhraseIsMatch(pNode, pNear->pColset, pPhrase, &bMatch);
172527 if( bMatch==0 ) break;
172528 }else{
172529 rc = sqlite3Fts5IterPoslistBuffer(
172530 pPhrase->aTerm[0].pIter, &pPhrase->poslist
172531 );
172532 }
172533 }
172534
172535 *pRc = rc;
172536 if( i==pNear->nPhrase && (i==1 || fts5ExprNearIsMatch(pRc, pNear)) ){
172537 return 1;
172538 }
172539 return 0;
172540 }
172541 }
172542
172543 static int fts5ExprTokenTest(
172544 Fts5Expr *pExpr, /* Expression that pNear is a part of */
172545 Fts5ExprNode *pNode /* The "NEAR" node (FTS5_TERM) */
@@ -172524,10 +172973,13 @@
172973 if( cmp || p2->bNomatch ) break;
172974 rc = fts5ExprNodeNext(pExpr, p1, 0, 0);
172975 }
172976 pNode->bEof = p1->bEof;
172977 pNode->iRowid = p1->iRowid;
172978 if( p1->bEof ){
172979 fts5ExprNodeZeroPoslist(p2);
172980 }
172981 break;
172982 }
172983 }
172984 }
172985 return rc;
@@ -172909,10 +173361,11 @@
173361 }
173362
173363 if( rc==SQLITE_OK ){
173364 /* All the allocations succeeded. Put the expression object together. */
173365 pNew->pIndex = pExpr->pIndex;
173366 pNew->pConfig = pExpr->pConfig;
173367 pNew->nPhrase = 1;
173368 pNew->apExprPhrase[0] = sCtx.pPhrase;
173369 pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
173370 pNew->pRoot->pNear->nPhrase = 1;
173371 sCtx.pPhrase->pNode = pNew->pRoot;
@@ -173050,10 +173503,19 @@
173503 static void sqlite3Fts5ParseSetColset(
173504 Fts5Parse *pParse,
173505 Fts5ExprNearset *pNear,
173506 Fts5Colset *pColset
173507 ){
173508 if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
173509 pParse->rc = SQLITE_ERROR;
173510 pParse->zErr = sqlite3_mprintf(
173511 "fts5: column queries are not supported (detail=none)"
173512 );
173513 sqlite3_free(pColset);
173514 return;
173515 }
173516
173517 if( pNear ){
173518 pNear->pColset = pColset;
173519 }else{
173520 sqlite3_free(pColset);
173521 }
@@ -173111,15 +173573,24 @@
173573 if( eType==FTS5_STRING ){
173574 int iPhrase;
173575 for(iPhrase=0; iPhrase<pNear->nPhrase; iPhrase++){
173576 pNear->apPhrase[iPhrase]->pNode = pRet;
173577 }
173578 if( pNear->nPhrase==1 && pNear->apPhrase[0]->nTerm==1 ){
173579 if( pNear->apPhrase[0]->aTerm[0].pSynonym==0 ){
173580 pRet->eType = FTS5_TERM;
173581 }
173582 }else if( pParse->pConfig->eDetail!=FTS5_DETAIL_FULL ){
173583 assert( pParse->rc==SQLITE_OK );
173584 pParse->rc = SQLITE_ERROR;
173585 assert( pParse->zErr==0 );
173586 pParse->zErr = sqlite3_mprintf(
173587 "fts5: %s queries are not supported (detail!=full)",
173588 pNear->nPhrase==1 ? "phrase": "NEAR"
173589 );
173590 sqlite3_free(pRet);
173591 pRet = 0;
173592 }
173593 }else{
173594 fts5ExprAddChildren(pRet, pLeft);
173595 fts5ExprAddChildren(pRet, pRight);
173596 }
@@ -173229,10 +173700,13 @@
173700
173701 zRet = fts5PrintfAppend(zRet, " {");
173702 for(iTerm=0; zRet && iTerm<pPhrase->nTerm; iTerm++){
173703 char *zTerm = pPhrase->aTerm[iTerm].zTerm;
173704 zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm);
173705 if( pPhrase->aTerm[iTerm].bPrefix ){
173706 zRet = fts5PrintfAppend(zRet, "*");
173707 }
173708 }
173709
173710 if( zRet ) zRet = fts5PrintfAppend(zRet, "}");
173711 if( zRet==0 ) return 0;
173712 }
@@ -173541,10 +174015,237 @@
174015 *pa = 0;
174016 nRet = 0;
174017 }
174018 return nRet;
174019 }
174020
174021 struct Fts5PoslistPopulator {
174022 Fts5PoslistWriter writer;
174023 int bOk; /* True if ok to populate */
174024 int bMiss;
174025 };
174026
174027 static Fts5PoslistPopulator *sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
174028 Fts5PoslistPopulator *pRet;
174029 pRet = sqlite3_malloc(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
174030 if( pRet ){
174031 int i;
174032 memset(pRet, 0, sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
174033 for(i=0; i<pExpr->nPhrase; i++){
174034 Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist;
174035 Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
174036 assert( pExpr->apExprPhrase[i]->nTerm==1 );
174037 if( bLive &&
174038 (pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof)
174039 ){
174040 pRet[i].bMiss = 1;
174041 }else{
174042 pBuf->n = 0;
174043 }
174044 }
174045 }
174046 return pRet;
174047 }
174048
174049 struct Fts5ExprCtx {
174050 Fts5Expr *pExpr;
174051 Fts5PoslistPopulator *aPopulator;
174052 i64 iOff;
174053 };
174054 typedef struct Fts5ExprCtx Fts5ExprCtx;
174055
174056 /*
174057 ** TODO: Make this more efficient!
174058 */
174059 static int fts5ExprColsetTest(Fts5Colset *pColset, int iCol){
174060 int i;
174061 for(i=0; i<pColset->nCol; i++){
174062 if( pColset->aiCol[i]==iCol ) return 1;
174063 }
174064 return 0;
174065 }
174066
174067 static int fts5ExprPopulatePoslistsCb(
174068 void *pCtx, /* Copy of 2nd argument to xTokenize() */
174069 int tflags, /* Mask of FTS5_TOKEN_* flags */
174070 const char *pToken, /* Pointer to buffer containing token */
174071 int nToken, /* Size of token in bytes */
174072 int iStart, /* Byte offset of token within input text */
174073 int iEnd /* Byte offset of end of token within input text */
174074 ){
174075 Fts5ExprCtx *p = (Fts5ExprCtx*)pCtx;
174076 Fts5Expr *pExpr = p->pExpr;
174077 int i;
174078
174079 if( (tflags & FTS5_TOKEN_COLOCATED)==0 ) p->iOff++;
174080 for(i=0; i<pExpr->nPhrase; i++){
174081 Fts5ExprTerm *pTerm;
174082 if( p->aPopulator[i].bOk==0 ) continue;
174083 for(pTerm=&pExpr->apExprPhrase[i]->aTerm[0]; pTerm; pTerm=pTerm->pSynonym){
174084 int nTerm = strlen(pTerm->zTerm);
174085 if( (nTerm==nToken || (nTerm<nToken && pTerm->bPrefix))
174086 && memcmp(pTerm->zTerm, pToken, nTerm)==0
174087 ){
174088 int rc = sqlite3Fts5PoslistWriterAppend(
174089 &pExpr->apExprPhrase[i]->poslist, &p->aPopulator[i].writer, p->iOff
174090 );
174091 if( rc ) return rc;
174092 break;
174093 }
174094 }
174095 }
174096 return SQLITE_OK;
174097 }
174098
174099 static int sqlite3Fts5ExprPopulatePoslists(
174100 Fts5Config *pConfig,
174101 Fts5Expr *pExpr,
174102 Fts5PoslistPopulator *aPopulator,
174103 int iCol,
174104 const char *z, int n
174105 ){
174106 int i;
174107 Fts5ExprCtx sCtx;
174108 sCtx.pExpr = pExpr;
174109 sCtx.aPopulator = aPopulator;
174110 sCtx.iOff = (((i64)iCol) << 32) - 1;
174111
174112 for(i=0; i<pExpr->nPhrase; i++){
174113 Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
174114 Fts5Colset *pColset = pNode->pNear->pColset;
174115 if( (pColset && 0==fts5ExprColsetTest(pColset, iCol))
174116 || aPopulator[i].bMiss
174117 ){
174118 aPopulator[i].bOk = 0;
174119 }else{
174120 aPopulator[i].bOk = 1;
174121 }
174122 }
174123
174124 return sqlite3Fts5Tokenize(pConfig,
174125 FTS5_TOKENIZE_AUX, z, n, (void*)&sCtx, fts5ExprPopulatePoslistsCb
174126 );
174127 }
174128
174129 static void fts5ExprClearPoslists(Fts5ExprNode *pNode){
174130 if( pNode->eType==FTS5_TERM || pNode->eType==FTS5_STRING ){
174131 pNode->pNear->apPhrase[0]->poslist.n = 0;
174132 }else{
174133 int i;
174134 for(i=0; i<pNode->nChild; i++){
174135 fts5ExprClearPoslists(pNode->apChild[i]);
174136 }
174137 }
174138 }
174139
174140 static int fts5ExprCheckPoslists(Fts5ExprNode *pNode, i64 iRowid){
174141 if( pNode ){
174142 pNode->iRowid = iRowid;
174143 pNode->bEof = 0;
174144 switch( pNode->eType ){
174145 case FTS5_TERM:
174146 case FTS5_STRING:
174147 return (pNode->pNear->apPhrase[0]->poslist.n>0);
174148
174149 case FTS5_AND: {
174150 int i;
174151 for(i=0; i<pNode->nChild; i++){
174152 if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid)==0 ){
174153 fts5ExprClearPoslists(pNode);
174154 return 0;
174155 }
174156 }
174157 break;
174158 }
174159
174160 case FTS5_OR: {
174161 int i;
174162 int bRet = 0;
174163 for(i=0; i<pNode->nChild; i++){
174164 if( fts5ExprCheckPoslists(pNode->apChild[i], iRowid) ){
174165 bRet = 1;
174166 }
174167 }
174168 if( bRet==0 ){
174169 fts5ExprClearPoslists(pNode);
174170 }
174171 return bRet;
174172 }
174173
174174 default: {
174175 assert( pNode->eType==FTS5_NOT );
174176 if( 0==fts5ExprCheckPoslists(pNode->apChild[0], iRowid)
174177 || 0!=fts5ExprCheckPoslists(pNode->apChild[1], iRowid)
174178 ){
174179 fts5ExprClearPoslists(pNode);
174180 return 0;
174181 }
174182 break;
174183 }
174184 }
174185 }
174186 return 1;
174187 }
174188
174189 static void sqlite3Fts5ExprCheckPoslists(Fts5Expr *pExpr, i64 iRowid){
174190 fts5ExprCheckPoslists(pExpr->pRoot, iRowid);
174191 }
174192
174193 static void fts5ExprClearEof(Fts5ExprNode *pNode){
174194 int i;
174195 for(i=0; i<pNode->nChild; i++){
174196 fts5ExprClearEof(pNode->apChild[i]);
174197 }
174198 pNode->bEof = 0;
174199 }
174200 static void sqlite3Fts5ExprClearEof(Fts5Expr *pExpr){
174201 fts5ExprClearEof(pExpr->pRoot);
174202 }
174203
174204 /*
174205 ** This function is only called for detail=columns tables.
174206 */
174207 static int sqlite3Fts5ExprPhraseCollist(
174208 Fts5Expr *pExpr,
174209 int iPhrase,
174210 const u8 **ppCollist,
174211 int *pnCollist
174212 ){
174213 Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase];
174214 Fts5ExprNode *pNode = pPhrase->pNode;
174215 int rc = SQLITE_OK;
174216
174217 assert( iPhrase>=0 && iPhrase<pExpr->nPhrase );
174218 if( pNode->bEof==0
174219 && pNode->iRowid==pExpr->pRoot->iRowid
174220 && pPhrase->poslist.n>0
174221 ){
174222 Fts5ExprTerm *pTerm = &pPhrase->aTerm[0];
174223 if( pTerm->pSynonym ){
174224 int bDel = 0;
174225 u8 *a;
174226 rc = fts5ExprSynonymList(
174227 pTerm, 1, 0, pNode->iRowid, &bDel, &a, pnCollist
174228 );
174229 if( bDel ){
174230 sqlite3Fts5BufferSet(&rc, &pPhrase->poslist, *pnCollist, a);
174231 *ppCollist = pPhrase->poslist.p;
174232 sqlite3_free(a);
174233 }else{
174234 *ppCollist = a;
174235 }
174236 }else{
174237 sqlite3Fts5IterCollist(pPhrase->aTerm[0].pIter, ppCollist, pnCollist);
174238 }
174239 }else{
174240 *ppCollist = 0;
174241 *pnCollist = 0;
174242 }
174243
174244 return rc;
174245 }
174246
174247
174248 /*
174249 ** 2014 August 11
174250 **
174251 ** The author disclaims copyright to this source code. In place of
@@ -173570,10 +174271,11 @@
174271 ** segment.
174272 */
174273
174274
174275 struct Fts5Hash {
174276 int eDetail; /* Copy of Fts5Config.eDetail */
174277 int *pnByte; /* Pointer to bytes counter */
174278 int nEntry; /* Number of entries currently in hash */
174279 int nSlot; /* Size of aSlot[] array */
174280 Fts5HashEntry *pScan; /* Current ordered scan item */
174281 Fts5HashEntry **aSlot; /* Array of hash slots */
@@ -173606,10 +174308,11 @@
174308
174309 int nAlloc; /* Total size of allocation */
174310 int iSzPoslist; /* Offset of space for 4-byte poslist size */
174311 int nData; /* Total bytes of data (incl. structure) */
174312 u8 bDel; /* Set delete-flag @ iSzPoslist */
174313 u8 bContent; /* Set content-flag (detail=none mode) */
174314
174315 int iCol; /* Column of last value written */
174316 int iPos; /* Position of last value written */
174317 i64 iRowid; /* Rowid of last value written */
174318 char zKey[8]; /* Nul-terminated entry key */
@@ -173623,11 +174326,11 @@
174326
174327
174328 /*
174329 ** Allocate a new hash table.
174330 */
174331 static int sqlite3Fts5HashNew(Fts5Config *pConfig, Fts5Hash **ppNew, int *pnByte){
174332 int rc = SQLITE_OK;
174333 Fts5Hash *pNew;
174334
174335 *ppNew = pNew = (Fts5Hash*)sqlite3_malloc(sizeof(Fts5Hash));
174336 if( pNew==0 ){
@@ -173634,10 +174337,11 @@
174337 rc = SQLITE_NOMEM;
174338 }else{
174339 int nByte;
174340 memset(pNew, 0, sizeof(Fts5Hash));
174341 pNew->pnByte = pnByte;
174342 pNew->eDetail = pConfig->eDetail;
174343
174344 pNew->nSlot = 1024;
174345 nByte = sizeof(Fts5HashEntry*) * pNew->nSlot;
174346 pNew->aSlot = (Fts5HashEntry**)sqlite3_malloc(nByte);
174347 if( pNew->aSlot==0 ){
@@ -173726,30 +174430,50 @@
174430 pHash->nSlot = nNew;
174431 pHash->aSlot = apNew;
174432 return SQLITE_OK;
174433 }
174434
174435 static void fts5HashAddPoslistSize(Fts5Hash *pHash, Fts5HashEntry *p){
174436 if( p->iSzPoslist ){
174437 u8 *pPtr = (u8*)p;
174438 if( pHash->eDetail==FTS5_DETAIL_NONE ){
174439 assert( p->nData==p->iSzPoslist );
174440 if( p->bDel ){
174441 pPtr[p->nData++] = 0x00;
174442 if( p->bContent ){
174443 pPtr[p->nData++] = 0x00;
174444 }
174445 }
174446 }else{
174447 int nSz = (p->nData - p->iSzPoslist - 1); /* Size in bytes */
174448 int nPos = nSz*2 + p->bDel; /* Value of nPos field */
174449
174450 assert( p->bDel==0 || p->bDel==1 );
174451 if( nPos<=127 ){
174452 pPtr[p->iSzPoslist] = (u8)nPos;
174453 }else{
174454 int nByte = sqlite3Fts5GetVarintLen((u32)nPos);
174455 memmove(&pPtr[p->iSzPoslist + nByte], &pPtr[p->iSzPoslist + 1], nSz);
174456 sqlite3Fts5PutVarint(&pPtr[p->iSzPoslist], nPos);
174457 p->nData += (nByte-1);
174458 }
174459 }
174460
174461 p->iSzPoslist = 0;
174462 p->bDel = 0;
174463 p->bContent = 0;
174464 }
174465 }
174466
174467 /*
174468 ** Add an entry to the in-memory hash table. The key is the concatenation
174469 ** of bByte and (pToken/nToken). The value is (iRowid/iCol/iPos).
174470 **
174471 ** (bByte || pToken) -> (iRowid,iCol,iPos)
174472 **
174473 ** Or, if iCol is negative, then the value is a delete marker.
174474 */
174475 static int sqlite3Fts5HashWrite(
174476 Fts5Hash *pHash,
174477 i64 iRowid, /* Rowid for this entry */
174478 int iCol, /* Column token appears in (-ve -> delete) */
174479 int iPos, /* Position of token within column */
@@ -173758,10 +174482,13 @@
174482 ){
174483 unsigned int iHash;
174484 Fts5HashEntry *p;
174485 u8 *pPtr;
174486 int nIncr = 0; /* Amount to increment (*pHash->pnByte) by */
174487 int bNew; /* If non-delete entry should be written */
174488
174489 bNew = (pHash->eDetail==FTS5_DETAIL_FULL);
174490
174491 /* Attempt to locate an existing hash entry */
174492 iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
174493 for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
174494 if( p->zKey[0]==bByte
@@ -173772,92 +174499,120 @@
174499 }
174500 }
174501
174502 /* If an existing hash entry cannot be found, create a new one. */
174503 if( p==0 ){
174504 /* Figure out how much space to allocate */
174505 int nByte = FTS5_HASHENTRYSIZE + (nToken+1) + 1 + 64;
174506 if( nByte<128 ) nByte = 128;
174507
174508 /* Grow the Fts5Hash.aSlot[] array if necessary. */
174509 if( (pHash->nEntry*2)>=pHash->nSlot ){
174510 int rc = fts5HashResize(pHash);
174511 if( rc!=SQLITE_OK ) return rc;
174512 iHash = fts5HashKey2(pHash->nSlot, (u8)bByte, (const u8*)pToken, nToken);
174513 }
174514
174515 /* Allocate new Fts5HashEntry and add it to the hash table. */
174516 p = (Fts5HashEntry*)sqlite3_malloc(nByte);
174517 if( !p ) return SQLITE_NOMEM;
174518 memset(p, 0, FTS5_HASHENTRYSIZE);
174519 p->nAlloc = nByte;
174520 p->zKey[0] = bByte;
174521 memcpy(&p->zKey[1], pToken, nToken);
174522 assert( iHash==fts5HashKey(pHash->nSlot, (u8*)p->zKey, nToken+1) );
174523 p->zKey[nToken+1] = '\0';
174524 p->nData = nToken+1 + 1 + FTS5_HASHENTRYSIZE;
 
 
 
 
174525 p->pHashNext = pHash->aSlot[iHash];
174526 pHash->aSlot[iHash] = p;
174527 pHash->nEntry++;
174528
174529 /* Add the first rowid field to the hash-entry */
174530 p->nData += sqlite3Fts5PutVarint(&((u8*)p)[p->nData], iRowid);
174531 p->iRowid = iRowid;
174532
174533 p->iSzPoslist = p->nData;
174534 if( pHash->eDetail!=FTS5_DETAIL_NONE ){
174535 p->nData += 1;
174536 p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
174537 }
174538
174539 nIncr += p->nData;
174540 }else{
174541
174542 /* Appending to an existing hash-entry. Check that there is enough
174543 ** space to append the largest possible new entry. Worst case scenario
174544 ** is:
174545 **
174546 ** + 9 bytes for a new rowid,
174547 ** + 4 byte reserved for the "poslist size" varint.
174548 ** + 1 byte for a "new column" byte,
174549 ** + 3 bytes for a new column number (16-bit max) as a varint,
174550 ** + 5 bytes for the new position offset (32-bit max).
174551 */
174552 if( (p->nAlloc - p->nData) < (9 + 4 + 1 + 3 + 5) ){
174553 int nNew = p->nAlloc * 2;
174554 Fts5HashEntry *pNew;
174555 Fts5HashEntry **pp;
174556 pNew = (Fts5HashEntry*)sqlite3_realloc(p, nNew);
174557 if( pNew==0 ) return SQLITE_NOMEM;
174558 pNew->nAlloc = nNew;
174559 for(pp=&pHash->aSlot[iHash]; *pp!=p; pp=&(*pp)->pHashNext);
174560 *pp = pNew;
174561 p = pNew;
174562 }
174563 nIncr -= p->nData;
174564 }
174565 assert( (p->nAlloc - p->nData) >= (9 + 4 + 1 + 3 + 5) );
174566
174567 pPtr = (u8*)p;
174568
174569 /* If this is a new rowid, append the 4-byte size field for the previous
174570 ** entry, and the new rowid for this entry. */
174571 if( iRowid!=p->iRowid ){
174572 fts5HashAddPoslistSize(pHash, p);
174573 p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iRowid - p->iRowid);
174574 p->iRowid = iRowid;
174575 bNew = 1;
174576 p->iSzPoslist = p->nData;
174577 if( pHash->eDetail!=FTS5_DETAIL_NONE ){
174578 p->nData += 1;
174579 p->iCol = (pHash->eDetail==FTS5_DETAIL_FULL ? 0 : -1);
174580 p->iPos = 0;
174581 }
174582 }
174583
174584 if( iCol>=0 ){
174585 if( pHash->eDetail==FTS5_DETAIL_NONE ){
174586 p->bContent = 1;
174587 }else{
174588 /* Append a new column value, if necessary */
174589 assert( iCol>=p->iCol );
174590 if( iCol!=p->iCol ){
174591 if( pHash->eDetail==FTS5_DETAIL_FULL ){
174592 pPtr[p->nData++] = 0x01;
174593 p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iCol);
174594 p->iCol = iCol;
174595 p->iPos = 0;
174596 }else{
174597 bNew = 1;
174598 p->iCol = iPos = iCol;
174599 }
174600 }
174601
174602 /* Append the new position offset, if necessary */
174603 if( bNew ){
174604 p->nData += sqlite3Fts5PutVarint(&pPtr[p->nData], iPos - p->iPos + 2);
174605 p->iPos = iPos;
174606 }
174607 }
174608 }else{
174609 /* This is a delete. Set the delete flag. */
174610 p->bDel = 1;
174611 }
174612
174613 nIncr += p->nData;
 
174614 *pHash->pnByte += nIncr;
174615 return SQLITE_OK;
174616 }
174617
174618
@@ -173967,11 +174722,11 @@
174722 for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
174723 if( memcmp(p->zKey, pTerm, nTerm)==0 && p->zKey[nTerm]==0 ) break;
174724 }
174725
174726 if( p ){
174727 fts5HashAddPoslistSize(pHash, p);
174728 *ppDoclist = (const u8*)&p->zKey[nTerm+1];
174729 *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
174730 }else{
174731 *ppDoclist = 0;
174732 *pnDoclist = 0;
@@ -174003,11 +174758,11 @@
174758 int *pnDoclist /* OUT: size of doclist in bytes */
174759 ){
174760 Fts5HashEntry *p;
174761 if( (p = pHash->pScan) ){
174762 int nTerm = (int)strlen(p->zKey);
174763 fts5HashAddPoslistSize(pHash, p);
174764 *pzTerm = p->zKey;
174765 *ppDoclist = (const u8*)&p->zKey[nTerm+1];
174766 *pnDoclist = p->nData - (FTS5_HASHENTRYSIZE + nTerm + 1);
174767 }else{
174768 *pzTerm = 0;
@@ -174450,10 +175205,13 @@
175205 int iLeafPgno; /* Current leaf page number */
175206 Fts5Data *pLeaf; /* Current leaf data */
175207 Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
175208 int iLeafOffset; /* Byte offset within current leaf */
175209
175210 /* Next method */
175211 void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
175212
175213 /* The page and offset from which the current term was read. The offset
175214 ** is the offset of the first rowid in the current doclist. */
175215 int iTermLeafPgno;
175216 int iTermLeafOffset;
175217
@@ -174469,11 +175227,11 @@
175227
175228 /* Variables populated based on current entry. */
175229 Fts5Buffer term; /* Current term */
175230 i64 iRowid; /* Current rowid */
175231 int nPos; /* Number of bytes in current position list */
175232 u8 bDel; /* True if the delete flag is set */
175233 };
175234
175235 /*
175236 ** Argument is a pointer to an Fts5Data structure that contains a
175237 ** leaf page.
@@ -174482,11 +175240,10 @@
175240 (x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \
175241 )
175242
175243 #define FTS5_SEGITER_ONETERM 0x01
175244 #define FTS5_SEGITER_REVERSE 0x02
 
175245
175246 /*
175247 ** Argument is a pointer to an Fts5Data structure that contains a leaf
175248 ** page. This macro evaluates to true if the leaf contains no terms, or
175249 ** false if it contains at least one term.
@@ -175509,17 +176266,33 @@
176266 ** position list content (if any).
176267 */
176268 static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
176269 if( p->rc==SQLITE_OK ){
176270 int iOff = pIter->iLeafOffset; /* Offset to read at */
 
176271 ASSERT_SZLEAF_OK(pIter->pLeaf);
176272 if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
176273 int iEod = MIN(pIter->iEndofDoclist, pIter->pLeaf->szLeaf);
176274 pIter->bDel = 0;
176275 pIter->nPos = 1;
176276 if( iOff<iEod && pIter->pLeaf->p[iOff]==0 ){
176277 pIter->bDel = 1;
176278 iOff++;
176279 if( iOff<iEod && pIter->pLeaf->p[iOff]==0 ){
176280 pIter->nPos = 1;
176281 iOff++;
176282 }else{
176283 pIter->nPos = 0;
176284 }
176285 }
176286 }else{
176287 int nSz;
176288 fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz);
176289 pIter->bDel = (nSz & 0x0001);
176290 pIter->nPos = nSz>>1;
176291 assert_nc( pIter->nPos>=0 );
176292 }
176293 pIter->iLeafOffset = iOff;
 
176294 }
176295 }
176296
176297 static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
176298 u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
@@ -175575,10 +176348,24 @@
176348 pIter->iEndofDoclist += nExtra;
176349 }
176350
176351 fts5SegIterLoadRowid(p, pIter);
176352 }
176353
176354 static void fts5SegIterNext(Fts5Index*, Fts5SegIter*, int*);
176355 static void fts5SegIterNext_Reverse(Fts5Index*, Fts5SegIter*, int*);
176356 static void fts5SegIterNext_None(Fts5Index*, Fts5SegIter*, int*);
176357
176358 static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
176359 if( pIter->flags & FTS5_SEGITER_REVERSE ){
176360 pIter->xNext = fts5SegIterNext_Reverse;
176361 }else if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
176362 pIter->xNext = fts5SegIterNext_None;
176363 }else{
176364 pIter->xNext = fts5SegIterNext;
176365 }
176366 }
176367
176368 /*
176369 ** Initialize the iterator object pIter to iterate through the entries in
176370 ** segment pSeg. The iterator is left pointing to the first entry when
176371 ** this function returns.
@@ -175601,10 +176388,11 @@
176388 return;
176389 }
176390
176391 if( p->rc==SQLITE_OK ){
176392 memset(pIter, 0, sizeof(*pIter));
176393 fts5SegIterSetNext(p, pIter);
176394 pIter->pSeg = pSeg;
176395 pIter->iLeafPgno = pSeg->pgnoFirst-1;
176396 fts5SegIterNextPage(p, pIter);
176397 }
176398
@@ -175632,10 +176420,11 @@
176420 ** aRowidOffset[] and iRowidOffset variables. At this point the iterator
176421 ** is in its regular state - Fts5SegIter.iLeafOffset points to the first
176422 ** byte of the position list content associated with said rowid.
176423 */
176424 static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
176425 int eDetail = p->pConfig->eDetail;
176426 int n = pIter->pLeaf->szLeaf;
176427 int i = pIter->iLeafOffset;
176428 u8 *a = pIter->pLeaf->p;
176429 int iRowidOffset = 0;
176430
@@ -175644,19 +176433,28 @@
176433 }
176434
176435 ASSERT_SZLEAF_OK(pIter->pLeaf);
176436 while( 1 ){
176437 i64 iDelta = 0;
 
 
176438
176439 if( eDetail==FTS5_DETAIL_NONE ){
176440 /* todo */
176441 if( i<n && a[i]==0 ){
176442 i++;
176443 if( i<n && a[i]==0 ) i++;
176444 }
176445 }else{
176446 int nPos;
176447 int bDummy;
176448 i += fts5GetPoslistSize(&a[i], &nPos, &bDummy);
176449 i += nPos;
176450 }
176451 if( i>=n ) break;
176452 i += fts5GetVarint(&a[i], (u64*)&iDelta);
176453 pIter->iRowid += iDelta;
176454
176455 /* If necessary, grow the pIter->aRowidOffset[] array. */
176456 if( iRowidOffset>=pIter->nRowidOffset ){
176457 int nNew = pIter->nRowidOffset + 8;
176458 int *aNew = (int*)sqlite3_realloc(pIter->aRowidOffset, nNew*sizeof(int));
176459 if( aNew==0 ){
176460 p->rc = SQLITE_NOMEM;
@@ -175730,10 +176528,112 @@
176528 */
176529 static int fts5MultiIterIsEmpty(Fts5Index *p, Fts5IndexIter *pIter){
176530 Fts5SegIter *pSeg = &pIter->aSeg[pIter->aFirst[1].iFirst];
176531 return (p->rc==SQLITE_OK && pSeg->pLeaf && pSeg->nPos==0);
176532 }
176533
176534 /*
176535 ** Advance iterator pIter to the next entry.
176536 **
176537 ** This version of fts5SegIterNext() is only used by reverse iterators.
176538 */
176539 static void fts5SegIterNext_Reverse(
176540 Fts5Index *p, /* FTS5 backend object */
176541 Fts5SegIter *pIter, /* Iterator to advance */
176542 int *pbNewTerm /* OUT: Set for new term */
176543 ){
176544 assert( pIter->flags & FTS5_SEGITER_REVERSE );
176545 assert( pIter->pNextLeaf==0 );
176546 if( pIter->iRowidOffset>0 ){
176547 u8 *a = pIter->pLeaf->p;
176548 int iOff;
176549 i64 iDelta;
176550
176551 pIter->iRowidOffset--;
176552 pIter->iLeafOffset = pIter->aRowidOffset[pIter->iRowidOffset];
176553 fts5SegIterLoadNPos(p, pIter);
176554 iOff = pIter->iLeafOffset;
176555 if( p->pConfig->eDetail!=FTS5_DETAIL_NONE ){
176556 iOff += pIter->nPos;
176557 }
176558 fts5GetVarint(&a[iOff], (u64*)&iDelta);
176559 pIter->iRowid -= iDelta;
176560 }else{
176561 fts5SegIterReverseNewPage(p, pIter);
176562 }
176563 }
176564
176565 /*
176566 ** Advance iterator pIter to the next entry.
176567 **
176568 ** This version of fts5SegIterNext() is only used if detail=none and the
176569 ** iterator is not a reverse direction iterator.
176570 */
176571 static void fts5SegIterNext_None(
176572 Fts5Index *p, /* FTS5 backend object */
176573 Fts5SegIter *pIter, /* Iterator to advance */
176574 int *pbNewTerm /* OUT: Set for new term */
176575 ){
176576 int iOff;
176577
176578 assert( p->rc==SQLITE_OK );
176579 assert( (pIter->flags & FTS5_SEGITER_REVERSE)==0 );
176580 assert( p->pConfig->eDetail==FTS5_DETAIL_NONE );
176581
176582 ASSERT_SZLEAF_OK(pIter->pLeaf);
176583 iOff = pIter->iLeafOffset;
176584
176585 /* Next entry is on the next page */
176586 if( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){
176587 fts5SegIterNextPage(p, pIter);
176588 if( p->rc || pIter->pLeaf==0 ) return;
176589 pIter->iRowid = 0;
176590 iOff = 4;
176591 }
176592
176593 if( iOff<pIter->iEndofDoclist ){
176594 /* Next entry is on the current page */
176595 i64 iDelta;
176596 iOff += sqlite3Fts5GetVarint(&pIter->pLeaf->p[iOff], (u64*)&iDelta);
176597 pIter->iLeafOffset = iOff;
176598 pIter->iRowid += iDelta;
176599 }else if( (pIter->flags & FTS5_SEGITER_ONETERM)==0 ){
176600 if( pIter->pSeg ){
176601 int nKeep = 0;
176602 if( iOff!=fts5LeafFirstTermOff(pIter->pLeaf) ){
176603 iOff += fts5GetVarint32(&pIter->pLeaf->p[iOff], nKeep);
176604 }
176605 pIter->iLeafOffset = iOff;
176606 fts5SegIterLoadTerm(p, pIter, nKeep);
176607 }else{
176608 const u8 *pList = 0;
176609 const char *zTerm = 0;
176610 int nList;
176611 sqlite3Fts5HashScanNext(p->pHash);
176612 sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
176613 if( pList==0 ) goto next_none_eof;
176614 pIter->pLeaf->p = (u8*)pList;
176615 pIter->pLeaf->nn = nList;
176616 pIter->pLeaf->szLeaf = nList;
176617 pIter->iEndofDoclist = nList;
176618 sqlite3Fts5BufferSet(&p->rc,&pIter->term, (int)strlen(zTerm), (u8*)zTerm);
176619 pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
176620 }
176621
176622 if( pbNewTerm ) *pbNewTerm = 1;
176623 }else{
176624 goto next_none_eof;
176625 }
176626
176627 fts5SegIterLoadNPos(p, pIter);
176628
176629 return;
176630 next_none_eof:
176631 fts5DataRelease(pIter->pLeaf);
176632 pIter->pLeaf = 0;
176633 }
176634
176635
176636 /*
176637 ** Advance iterator pIter to the next entry.
176638 **
176639 ** If an error occurs, Fts5Index.rc is set to an appropriate error code. It
@@ -175743,144 +176643,133 @@
176643 static void fts5SegIterNext(
176644 Fts5Index *p, /* FTS5 backend object */
176645 Fts5SegIter *pIter, /* Iterator to advance */
176646 int *pbNewTerm /* OUT: Set for new term */
176647 ){
176648 Fts5Data *pLeaf = pIter->pLeaf;
176649 int iOff;
176650 int bNewTerm = 0;
176651 int nKeep = 0;
176652
176653 assert( pbNewTerm==0 || *pbNewTerm==0 );
176654 assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
176655
176656 /* Search for the end of the position list within the current page. */
176657 u8 *a = pLeaf->p;
176658 int n = pLeaf->szLeaf;
176659
176660 ASSERT_SZLEAF_OK(pLeaf);
176661 iOff = pIter->iLeafOffset + pIter->nPos;
176662
176663 if( iOff<n ){
176664 /* The next entry is on the current page. */
176665 assert_nc( iOff<=pIter->iEndofDoclist );
176666 if( iOff>=pIter->iEndofDoclist ){
176667 bNewTerm = 1;
176668 if( iOff!=fts5LeafFirstTermOff(pLeaf) ){
176669 iOff += fts5GetVarint32(&a[iOff], nKeep);
176670 }
176671 }else{
176672 u64 iDelta;
176673 iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta);
176674 pIter->iRowid += iDelta;
176675 assert_nc( iDelta>0 );
176676 }
176677 pIter->iLeafOffset = iOff;
176678
176679 }else if( pIter->pSeg==0 ){
176680 const u8 *pList = 0;
176681 const char *zTerm = 0;
176682 int nList = 0;
176683 assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
176684 if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
176685 sqlite3Fts5HashScanNext(p->pHash);
176686 sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
176687 }
176688 if( pList==0 ){
176689 fts5DataRelease(pIter->pLeaf);
176690 pIter->pLeaf = 0;
176691 }else{
176692 pIter->pLeaf->p = (u8*)pList;
176693 pIter->pLeaf->nn = nList;
176694 pIter->pLeaf->szLeaf = nList;
176695 pIter->iEndofDoclist = nList+1;
176696 sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm),
176697 (u8*)zTerm);
176698 pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
176699 *pbNewTerm = 1;
176700 }
176701 }else{
176702 iOff = 0;
176703 /* Next entry is not on the current page */
176704 while( iOff==0 ){
176705 fts5SegIterNextPage(p, pIter);
176706 pLeaf = pIter->pLeaf;
176707 if( pLeaf==0 ) break;
176708 ASSERT_SZLEAF_OK(pLeaf);
176709 if( (iOff = fts5LeafFirstRowidOff(pLeaf)) && iOff<pLeaf->szLeaf ){
176710 iOff += sqlite3Fts5GetVarint(&pLeaf->p[iOff], (u64*)&pIter->iRowid);
176711 pIter->iLeafOffset = iOff;
176712
176713 if( pLeaf->nn>pLeaf->szLeaf ){
176714 pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
176715 &pLeaf->p[pLeaf->szLeaf], pIter->iEndofDoclist
176716 );
176717 }
176718
176719 }
176720 else if( pLeaf->nn>pLeaf->szLeaf ){
176721 pIter->iPgidxOff = pLeaf->szLeaf + fts5GetVarint32(
176722 &pLeaf->p[pLeaf->szLeaf], iOff
176723 );
176724 pIter->iLeafOffset = iOff;
176725 pIter->iEndofDoclist = iOff;
176726 bNewTerm = 1;
176727 }
176728 assert_nc( iOff<pLeaf->szLeaf );
176729 if( iOff>pLeaf->szLeaf ){
176730 p->rc = FTS5_CORRUPT;
176731 return;
176732 }
176733 }
176734 }
176735
176736 /* Check if the iterator is now at EOF. If so, return early. */
176737 if( pIter->pLeaf ){
176738 if( bNewTerm ){
176739 if( pIter->flags & FTS5_SEGITER_ONETERM ){
176740 fts5DataRelease(pIter->pLeaf);
176741 pIter->pLeaf = 0;
176742 }else{
176743 fts5SegIterLoadTerm(p, pIter, nKeep);
176744 fts5SegIterLoadNPos(p, pIter);
176745 if( pbNewTerm ) *pbNewTerm = 1;
176746 }
176747 }else{
176748 /* The following could be done by calling fts5SegIterLoadNPos(). But
176749 ** this block is particularly performance critical, so equivalent
176750 ** code is inlined.
176751 **
176752 ** Later: Switched back to fts5SegIterLoadNPos() because it supports
176753 ** detail=none mode. Not ideal.
176754 */
176755 int nSz;
176756 assert( p->rc==SQLITE_OK );
176757 fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
176758 pIter->bDel = (nSz & 0x0001);
176759 pIter->nPos = nSz>>1;
176760 assert_nc( pIter->nPos>=0 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176761 }
176762 }
176763 }
176764
176765 #define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; }
176766
176767 #define fts5IndexSkipVarint(a, iOff) { \
176768 int iEnd = iOff+9; \
176769 while( (a[iOff++] & 0x80) && iOff<iEnd ); \
176770 }
176771
176772 /*
176773 ** Iterator pIter currently points to the first rowid in a doclist. This
176774 ** function sets the iterator up so that iterates in reverse order through
176775 ** the doclist.
@@ -175898,11 +176787,21 @@
176787 Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
176788
176789 /* Currently, Fts5SegIter.iLeafOffset points to the first byte of
176790 ** position-list content for the current rowid. Back it up so that it
176791 ** points to the start of the position-list size field. */
176792 int iPoslist;
176793 if( pIter->iTermLeafPgno==pIter->iLeafPgno ){
176794 iPoslist = pIter->iTermLeafOffset;
176795 }else{
176796 iPoslist = 4;
176797 }
176798 fts5IndexSkipVarint(pLeaf->p, iPoslist);
176799 assert( p->pConfig->eDetail==FTS5_DETAIL_NONE || iPoslist==(
176800 pIter->iLeafOffset - sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel)
176801 ));
176802 pIter->iLeafOffset = iPoslist;
176803
176804 /* If this condition is true then the largest rowid for the current
176805 ** term may not be stored on the current page. So search forward to
176806 ** see where said rowid really is. */
176807 if( pIter->iEndofDoclist>=pLeaf->szLeaf ){
@@ -175982,15 +176881,10 @@
176881 }
176882
176883 pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
176884 }
176885
 
 
 
 
 
176886 /*
176887 ** The iterator object passed as the second argument currently contains
176888 ** no valid values except for the Fts5SegIter.pLeaf member variable. This
176889 ** function searches the leaf page for a term matching (pTerm/nTerm).
176890 **
@@ -176189,10 +177083,12 @@
177083 fts5SegIterReverse(p, pIter);
177084 }
177085 }
177086 }
177087
177088 fts5SegIterSetNext(p, pIter);
177089
177090 /* Either:
177091 **
177092 ** 1) an error has occurred, or
177093 ** 2) the iterator points to EOF, or
177094 ** 3) the iterator points to an entry with term (pTerm/nTerm), or
@@ -176246,19 +177142,21 @@
177142 if( pLeaf==0 ) return;
177143 pLeaf->p = (u8*)pList;
177144 pLeaf->nn = pLeaf->szLeaf = nList;
177145 pIter->pLeaf = pLeaf;
177146 pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
177147 pIter->iEndofDoclist = pLeaf->nn;
177148
177149 if( flags & FTS5INDEX_QUERY_DESC ){
177150 pIter->flags |= FTS5_SEGITER_REVERSE;
177151 fts5SegIterReverseInitPage(p, pIter);
177152 }else{
177153 fts5SegIterLoadNPos(p, pIter);
177154 }
177155 }
177156
177157 fts5SegIterSetNext(p, pIter);
177158 }
177159
177160 /*
177161 ** Zero the iterator passed as the only argument.
177162 */
@@ -176498,11 +177396,11 @@
177396 bMove = 0;
177397 }
177398 }
177399
177400 do{
177401 if( bMove && p->rc==SQLITE_OK ) pIter->xNext(p, pIter, 0);
177402 if( pIter->pLeaf==0 ) break;
177403 if( bRev==0 && pIter->iRowid>=iMatch ) break;
177404 if( bRev!=0 && pIter->iRowid<=iMatch ) break;
177405 bMove = 1;
177406 }while( p->rc==SQLITE_OK );
@@ -176532,11 +177430,13 @@
177430 ){
177431 int i;
177432 for(i=(pIter->nSeg+iChanged)/2; i>=iMinset && p->rc==SQLITE_OK; i=i/2){
177433 int iEq;
177434 if( (iEq = fts5MultiIterDoCompare(pIter, i)) ){
177435 Fts5SegIter *pSeg = &pIter->aSeg[iEq];
177436 assert( p->rc==SQLITE_OK );
177437 pSeg->xNext(p, pSeg, 0);
177438 i = pIter->nSeg + iEq;
177439 }
177440 }
177441 }
177442
@@ -176619,11 +177519,11 @@
177519 Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
177520 assert( p->rc==SQLITE_OK );
177521 if( bUseFrom && pSeg->pDlidx ){
177522 fts5SegIterNextFrom(p, pSeg, iFrom);
177523 }else{
177524 pSeg->xNext(p, pSeg, &bNewTerm);
177525 }
177526
177527 if( pSeg->pLeaf==0 || bNewTerm
177528 || fts5MultiIterAdvanceRowid(p, pIter, iFirst)
177529 ){
@@ -176647,11 +177547,12 @@
177547 do {
177548 int iFirst = pIter->aFirst[1].iFirst;
177549 Fts5SegIter *pSeg = &pIter->aSeg[iFirst];
177550 int bNewTerm = 0;
177551
177552 assert( p->rc==SQLITE_OK );
177553 pSeg->xNext(p, pSeg, &bNewTerm);
177554 if( pSeg->pLeaf==0 || bNewTerm
177555 || fts5MultiIterAdvanceRowid(p, pIter, iFirst)
177556 ){
177557 fts5MultiIterAdvanced(p, pIter, iFirst, 1);
177558 fts5MultiIterSetEof(pIter);
@@ -176767,11 +177668,12 @@
177668 ** object and set the output variable to NULL. */
177669 if( p->rc==SQLITE_OK ){
177670 for(iIter=pNew->nSeg-1; iIter>0; iIter--){
177671 int iEq;
177672 if( (iEq = fts5MultiIterDoCompare(pNew, iIter)) ){
177673 Fts5SegIter *pSeg = &pNew->aSeg[iEq];
177674 if( p->rc==SQLITE_OK ) pSeg->xNext(p, pSeg, 0);
177675 fts5MultiIterAdvanced(p, pNew, iEq, iIter);
177676 }
177677 }
177678 fts5MultiIterSetEof(pNew);
177679 fts5AssertMultiIterSetup(p, pNew);
@@ -176817,10 +177719,11 @@
177719 }
177720 pData = 0;
177721 }else{
177722 pNew->bEof = 1;
177723 }
177724 fts5SegIterSetNext(p, pIter);
177725
177726 *ppOut = pNew;
177727 }
177728
177729 fts5DataRelease(pData);
@@ -176885,10 +177788,13 @@
177788 Fts5Data *pData = 0;
177789 u8 *pChunk = &pSeg->pLeaf->p[pSeg->iLeafOffset];
177790 int nChunk = MIN(nRem, pSeg->pLeaf->szLeaf - pSeg->iLeafOffset);
177791 int pgno = pSeg->iLeafPgno;
177792 int pgnoSave = 0;
177793
177794 /* This function does notmwork with detail=none databases. */
177795 assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
177796
177797 if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
177798 pgnoSave = pgno+1;
177799 }
177800
@@ -177309,12 +178215,11 @@
178215 ** Append a rowid and position-list size field to the writers output.
178216 */
178217 static void fts5WriteAppendRowid(
178218 Fts5Index *p,
178219 Fts5SegWriter *pWriter,
178220 i64 iRowid
 
178221 ){
178222 if( p->rc==SQLITE_OK ){
178223 Fts5PageWriter *pPage = &pWriter->writer;
178224
178225 if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){
@@ -177337,12 +178242,10 @@
178242 fts5BufferAppendVarint(&p->rc, &pPage->buf, iRowid - pWriter->iPrevRowid);
178243 }
178244 pWriter->iPrevRowid = iRowid;
178245 pWriter->bFirstRowidInDoclist = 0;
178246 pWriter->bFirstRowidInPage = 0;
 
 
178247 }
178248 }
178249
178250 static void fts5WriteAppendPoslistData(
178251 Fts5Index *p,
@@ -177534,10 +178437,11 @@
178437 int nInput; /* Number of input segments */
178438 Fts5SegWriter writer; /* Writer object */
178439 Fts5StructureSegment *pSeg; /* Output segment */
178440 Fts5Buffer term;
178441 int bOldest; /* True if the output segment is the oldest */
178442 int eDetail = p->pConfig->eDetail;
178443
178444 assert( iLvl<pStruct->nLevel );
178445 assert( pLvl->nMerge<=pLvl->nSeg );
178446
178447 memset(&writer, 0, sizeof(Fts5SegWriter));
@@ -177603,15 +178507,25 @@
178507 fts5BufferSet(&p->rc, &term, nTerm, pTerm);
178508 }
178509
178510 /* Append the rowid to the output */
178511 /* WRITEPOSLISTSIZE */
178512 fts5WriteAppendRowid(p, &writer, fts5MultiIterRowid(pIter));
 
178513
178514 if( eDetail==FTS5_DETAIL_NONE ){
178515 if( pSegIter->bDel ){
178516 fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0);
178517 if( pSegIter->nPos>0 ){
178518 fts5BufferAppendVarint(&p->rc, &writer.writer.buf, 0);
178519 }
178520 }
178521 }else{
178522 /* Append the position-list data to the output */
178523 nPos = pSegIter->nPos*2 + pSegIter->bDel;
178524 fts5BufferAppendVarint(&p->rc, &writer.writer.buf, nPos);
178525 fts5ChunkIterate(p, pSegIter, (void*)&writer, fts5MergeChunkCallback);
178526 }
178527 }
178528
178529 /* Flush the last leaf page to disk. Set the output segment b-tree height
178530 ** and last leaf page number at the same time. */
178531 fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
@@ -177795,11 +178709,11 @@
178709 pStruct = fts5StructureRead(p);
178710 iSegid = fts5AllocateSegid(p, pStruct);
178711
178712 if( iSegid ){
178713 const int pgsz = p->pConfig->pgsz;
178714 int eDetail = p->pConfig->eDetail;
178715 Fts5StructureSegment *pSeg; /* New segment within pStruct */
178716 Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */
178717 Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */
178718
178719 Fts5SegWriter writer;
@@ -177838,16 +178752,11 @@
178752
178753 /* The entire doclist will not fit on this leaf. The following
178754 ** loop iterates through the poslists that make up the current
178755 ** doclist. */
178756 while( p->rc==SQLITE_OK && iOff<nDoclist ){
 
 
 
178757 iOff += fts5GetVarint(&pDoclist[iOff], (u64*)&iDelta);
 
 
178758 iRowid += iDelta;
178759
178760 if( writer.bFirstRowidInPage ){
178761 fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */
178762 pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid);
@@ -177856,38 +178765,56 @@
178765 }else{
178766 pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta);
178767 }
178768 assert( pBuf->n<=pBuf->nSpace );
178769
178770 if( eDetail==FTS5_DETAIL_NONE ){
178771 if( iOff<nDoclist && pDoclist[iOff]==0 ){
178772 pBuf->p[pBuf->n++] = 0;
178773 iOff++;
178774 if( iOff<nDoclist && pDoclist[iOff]==0 ){
178775 pBuf->p[pBuf->n++] = 0;
178776 iOff++;
178777 }
178778 }
178779 if( (pBuf->n + pPgidx->n)>=pgsz ){
178780 fts5WriteFlushLeaf(p, &writer);
178781 }
178782 }else{
178783 int bDummy;
178784 int nPos;
178785 int nCopy = fts5GetPoslistSize(&pDoclist[iOff], &nPos, &bDummy);
178786 nCopy += nPos;
178787 if( (pBuf->n + pPgidx->n + nCopy) <= pgsz ){
178788 /* The entire poslist will fit on the current leaf. So copy
178789 ** it in one go. */
178790 fts5BufferSafeAppendBlob(pBuf, &pDoclist[iOff], nCopy);
178791 }else{
178792 /* The entire poslist will not fit on this leaf. So it needs
178793 ** to be broken into sections. The only qualification being
178794 ** that each varint must be stored contiguously. */
178795 const u8 *pPoslist = &pDoclist[iOff];
178796 int iPos = 0;
178797 while( p->rc==SQLITE_OK ){
178798 int nSpace = pgsz - pBuf->n - pPgidx->n;
178799 int n = 0;
178800 if( (nCopy - iPos)<=nSpace ){
178801 n = nCopy - iPos;
178802 }else{
178803 n = fts5PoslistPrefix(&pPoslist[iPos], nSpace);
178804 }
178805 assert( n>0 );
178806 fts5BufferSafeAppendBlob(pBuf, &pPoslist[iPos], n);
178807 iPos += n;
178808 if( (pBuf->n + pPgidx->n)>=pgsz ){
178809 fts5WriteFlushLeaf(p, &writer);
178810 }
178811 if( iPos>=nCopy ) break;
178812 }
178813 }
178814 iOff += nCopy;
178815 }
178816 }
178817 }
178818
178819 /* TODO2: Doclist terminator written here. */
178820 /* pBuf->p[pBuf->n++] = '\0'; */
@@ -178018,10 +178945,18 @@
178945 Fts5Buffer *pBuf; /* Append to this buffer */
178946 Fts5Colset *pColset; /* Restrict matches to this column */
178947 int eState; /* See above */
178948 };
178949
178950 typedef struct PoslistOffsetsCtx PoslistOffsetsCtx;
178951 struct PoslistOffsetsCtx {
178952 Fts5Buffer *pBuf; /* Append to this buffer */
178953 Fts5Colset *pColset; /* Restrict matches to this column */
178954 int iRead;
178955 int iWrite;
178956 };
178957
178958 /*
178959 ** TODO: Make this more efficient!
178960 */
178961 static int fts5IndexColsetTest(Fts5Colset *pColset, int iCol){
178962 int i;
@@ -178028,10 +178963,32 @@
178963 for(i=0; i<pColset->nCol; i++){
178964 if( pColset->aiCol[i]==iCol ) return 1;
178965 }
178966 return 0;
178967 }
178968
178969 static void fts5PoslistOffsetsCallback(
178970 Fts5Index *p,
178971 void *pContext,
178972 const u8 *pChunk, int nChunk
178973 ){
178974 PoslistOffsetsCtx *pCtx = (PoslistOffsetsCtx*)pContext;
178975 assert_nc( nChunk>=0 );
178976 if( nChunk>0 ){
178977 int i = 0;
178978 while( i<nChunk ){
178979 int iVal;
178980 i += fts5GetVarint32(&pChunk[i], iVal);
178981 iVal += pCtx->iRead - 2;
178982 pCtx->iRead = iVal;
178983 if( fts5IndexColsetTest(pCtx->pColset, iVal) ){
178984 fts5BufferSafeAppendVarint(pCtx->pBuf, iVal + 2 - pCtx->iWrite);
178985 pCtx->iWrite = iVal;
178986 }
178987 }
178988 }
178989 }
178990
178991 static void fts5PoslistFilterCallback(
178992 Fts5Index *p,
178993 void *pContext,
178994 const u8 *pChunk, int nChunk
@@ -178096,16 +179053,24 @@
179053 ){
179054 if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
179055 if( pColset==0 ){
179056 fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
179057 }else{
179058 if( p->pConfig->eDetail==FTS5_DETAIL_FULL ){
179059 PoslistCallbackCtx sCtx;
179060 sCtx.pBuf = pBuf;
179061 sCtx.pColset = pColset;
179062 sCtx.eState = fts5IndexColsetTest(pColset, 0);
179063 assert( sCtx.eState==0 || sCtx.eState==1 );
179064 fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
179065 }else{
179066 PoslistOffsetsCtx sCtx;
179067 memset(&sCtx, 0, sizeof(sCtx));
179068 sCtx.pBuf = pBuf;
179069 sCtx.pColset = pColset;
179070 fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistOffsetsCallback);
179071 }
179072 }
179073 }
179074 }
179075
179076 /*
@@ -178144,10 +179109,20 @@
179109 prev = *p++;
179110 }
179111 return p - (*pa);
179112 }
179113
179114 static int fts5AppendRowid(
179115 Fts5Index *p,
179116 i64 iDelta,
179117 Fts5IndexIter *pMulti,
179118 Fts5Colset *pColset,
179119 Fts5Buffer *pBuf
179120 ){
179121 fts5BufferAppendVarint(&p->rc, pBuf, iDelta);
179122 return 0;
179123 }
179124
179125 /*
179126 ** Iterator pMulti currently points to a valid entry (not EOF). This
179127 ** function appends the following to buffer pBuf:
179128 **
@@ -178171,12 +179146,12 @@
179146 if( p->rc==SQLITE_OK ){
179147 Fts5SegIter *pSeg = &pMulti->aSeg[ pMulti->aFirst[1].iFirst ];
179148 assert( fts5MultiIterEof(p, pMulti)==0 );
179149 assert( pSeg->nPos>0 );
179150 if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+9+9) ){
179151 if( p->pConfig->eDetail==FTS5_DETAIL_FULL
179152 && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
179153 && (pColset==0 || pColset->nCol==1)
179154 ){
179155 const u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
179156 int nPos;
179157 if( pColset ){
@@ -178217,16 +179192,16 @@
179192 sqlite3Fts5PutVarint(&pBuf->p[iSv2], nActual*2);
179193 }
179194 }
179195 }
179196 }
 
179197 }
179198 }
179199
179200 return 0;
179201 }
179202
179203
179204 static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
179205 u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
179206
179207 assert( pIter->aPoslist );
@@ -178283,10 +179258,73 @@
179258 #define fts5MergeAppendDocid(pBuf, iLastRowid, iRowid) { \
179259 assert( (pBuf)->n!=0 || (iLastRowid)==0 ); \
179260 fts5BufferSafeAppendVarint((pBuf), (iRowid) - (iLastRowid)); \
179261 (iLastRowid) = (iRowid); \
179262 }
179263
179264 /*
179265 ** Swap the contents of buffer *p1 with that of *p2.
179266 */
179267 static void fts5BufferSwap(Fts5Buffer *p1, Fts5Buffer *p2){
179268 Fts5Buffer tmp = *p1;
179269 *p1 = *p2;
179270 *p2 = tmp;
179271 }
179272
179273 static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){
179274 int i = *piOff;
179275 if( i>=pBuf->n ){
179276 *piOff = -1;
179277 }else{
179278 u64 iVal;
179279 *piOff = i + sqlite3Fts5GetVarint(&pBuf->p[i], &iVal);
179280 *piRowid += iVal;
179281 }
179282 }
179283
179284 /*
179285 ** This is the equivalent of fts5MergePrefixLists() for detail=none mode.
179286 ** In this case the buffers consist of a delta-encoded list of rowids only.
179287 */
179288 static void fts5MergeRowidLists(
179289 Fts5Index *p, /* FTS5 backend object */
179290 Fts5Buffer *p1, /* First list to merge */
179291 Fts5Buffer *p2 /* Second list to merge */
179292 ){
179293 int i1 = 0;
179294 int i2 = 0;
179295 i64 iRowid1 = 0;
179296 i64 iRowid2 = 0;
179297 i64 iOut = 0;
179298
179299 Fts5Buffer out;
179300 memset(&out, 0, sizeof(out));
179301 sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
179302 if( p->rc ) return;
179303
179304 fts5NextRowid(p1, &i1, &iRowid1);
179305 fts5NextRowid(p2, &i2, &iRowid2);
179306 while( i1>=0 || i2>=0 ){
179307 if( i1>=0 && (i2<0 || iRowid1<iRowid2) ){
179308 assert( iOut==0 || iRowid1>iOut );
179309 fts5BufferSafeAppendVarint(&out, iRowid1 - iOut);
179310 iOut = iRowid1;
179311 fts5NextRowid(p1, &i1, &iRowid1);
179312 }else{
179313 assert( iOut==0 || iRowid2>iOut );
179314 fts5BufferSafeAppendVarint(&out, iRowid2 - iOut);
179315 iOut = iRowid2;
179316 if( i1>=0 && iRowid1==iRowid2 ){
179317 fts5NextRowid(p1, &i1, &iRowid1);
179318 }
179319 fts5NextRowid(p2, &i2, &iRowid2);
179320 }
179321 }
179322
179323 fts5BufferSwap(&out, p1);
179324 fts5BufferFree(&out);
179325 }
179326
179327 /*
179328 ** Buffers p1 and p2 contain doclists. This function merges the content
179329 ** of the two doclists together and sets buffer p1 to the result before
179330 ** returning.
@@ -178352,11 +179390,13 @@
179390 sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
179391 if( iPos1==iPos2 ){
179392 sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1,&iPos1);
179393 }
179394 }
179395 if( iNew!=writer.iPrev || tmp.n==0 ){
179396 p->rc = sqlite3Fts5PoslistWriterAppend(&tmp, &writer, iNew);
179397 }
179398 }
179399
179400 /* WRITEPOSLISTSIZE */
179401 fts5BufferSafeAppendVarint(&out, tmp.n * 2);
179402 fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
@@ -178369,16 +179409,10 @@
179409 fts5BufferFree(&tmp);
179410 fts5BufferFree(&out);
179411 }
179412 }
179413
 
 
 
 
 
 
179414 static void fts5SetupPrefixIter(
179415 Fts5Index *p, /* Index to read from */
179416 int bDesc, /* True for "ORDER BY rowid DESC" */
179417 const u8 *pToken, /* Buffer containing prefix to match */
179418 int nToken, /* Size of buffer pToken in bytes */
@@ -178386,10 +179420,20 @@
179420 Fts5IndexIter **ppIter /* OUT: New iterator */
179421 ){
179422 Fts5Structure *pStruct;
179423 Fts5Buffer *aBuf;
179424 const int nBuf = 32;
179425
179426 void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
179427 int (*xAppend)(Fts5Index*, i64, Fts5IndexIter*, Fts5Colset*, Fts5Buffer*);
179428 if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
179429 xMerge = fts5MergeRowidLists;
179430 xAppend = fts5AppendRowid;
179431 }else{
179432 xMerge = fts5MergePrefixLists;
179433 xAppend = fts5AppendPoslist;
179434 }
179435
179436 aBuf = (Fts5Buffer*)fts5IdxMalloc(p, sizeof(Fts5Buffer)*nBuf);
179437 pStruct = fts5StructureRead(p);
179438
179439 if( aBuf && pStruct ){
@@ -178419,25 +179463,25 @@
179463 assert( i<nBuf );
179464 if( aBuf[i].n==0 ){
179465 fts5BufferSwap(&doclist, &aBuf[i]);
179466 fts5BufferZero(&doclist);
179467 }else{
179468 xMerge(p, &doclist, &aBuf[i]);
179469 fts5BufferZero(&aBuf[i]);
179470 }
179471 }
179472 iLastRowid = 0;
179473 }
179474
179475 if( !xAppend(p, iRowid-iLastRowid, p1, pColset, &doclist) ){
179476 iLastRowid = iRowid;
179477 }
179478 }
179479
179480 for(i=0; i<nBuf; i++){
179481 if( p->rc==SQLITE_OK ){
179482 xMerge(p, &doclist, &aBuf[i]);
179483 }
179484 fts5BufferFree(&aBuf[i]);
179485 }
179486 fts5MultiIterFree(p, p1);
179487
@@ -178463,11 +179507,11 @@
179507 static int sqlite3Fts5IndexBeginWrite(Fts5Index *p, int bDelete, i64 iRowid){
179508 assert( p->rc==SQLITE_OK );
179509
179510 /* Allocate the hash table if it has not already been allocated */
179511 if( p->pHash==0 ){
179512 p->rc = sqlite3Fts5HashNew(p->pConfig, &p->pHash, &p->nPendingData);
179513 }
179514
179515 /* Flush the hash table to disk if required */
179516 if( iRowid<p->iWriteRowid
179517 || (iRowid==p->iWriteRowid && p->bDelete==0)
@@ -178584,11 +179628,15 @@
179628 /*
179629 ** Argument p points to a buffer containing utf-8 text that is n bytes in
179630 ** size. Return the number of bytes in the nChar character prefix of the
179631 ** buffer, or 0 if there are less than nChar characters in total.
179632 */
179633 static int sqlite3Fts5IndexCharlenToBytelen(
179634 const char *p,
179635 int nByte,
179636 int nChar
179637 ){
179638 int n = 0;
179639 int i;
179640 for(i=0; i<nChar; i++){
179641 if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
179642 if( (unsigned char)p[n++]>=0xc0 ){
@@ -178641,11 +179689,12 @@
179689 rc = sqlite3Fts5HashWrite(
179690 p->pHash, p->iWriteRowid, iCol, iPos, FTS5_MAIN_PREFIX, pToken, nToken
179691 );
179692
179693 for(i=0; i<pConfig->nPrefix && rc==SQLITE_OK; i++){
179694 const int nChar = pConfig->aPrefix[i];
179695 int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
179696 if( nByte ){
179697 rc = sqlite3Fts5HashWrite(p->pHash,
179698 p->iWriteRowid, iCol, iPos, (char)(FTS5_MAIN_PREFIX+i+1), pToken,
179699 nByte
179700 );
@@ -178819,13 +179868,20 @@
179868 const u8 **pp, /* OUT: Pointer to position-list data */
179869 int *pn, /* OUT: Size of position-list in bytes */
179870 i64 *piRowid /* OUT: Current rowid */
179871 ){
179872 Fts5SegIter *pSeg = &pIter->aSeg[ pIter->aFirst[1].iFirst ];
179873 int eDetail = pIter->pIndex->pConfig->eDetail;
179874
179875 assert( pIter->pIndex->rc==SQLITE_OK );
179876 *piRowid = pSeg->iRowid;
179877 if( eDetail==FTS5_DETAIL_NONE ){
179878 *pn = pSeg->nPos;
179879 }else
179880 if( eDetail==FTS5_DETAIL_FULL
179881 && pSeg->iLeafOffset+pSeg->nPos<=pSeg->pLeaf->szLeaf
179882 ){
179883 u8 *pPos = &pSeg->pLeaf->p[pSeg->iLeafOffset];
179884 if( pColset==0 || pIter->bFiltered ){
179885 *pn = pSeg->nPos;
179886 *pp = pPos;
179887 }else if( pColset->nCol==1 ){
@@ -178838,15 +179894,28 @@
179894 *pn = pIter->poslist.n;
179895 }
179896 }else{
179897 fts5BufferZero(&pIter->poslist);
179898 fts5SegiterPoslist(pIter->pIndex, pSeg, pColset, &pIter->poslist);
179899 if( eDetail==FTS5_DETAIL_FULL ){
179900 *pp = pIter->poslist.p;
179901 }
179902 *pn = pIter->poslist.n;
179903 }
179904 return fts5IndexReturn(pIter->pIndex);
179905 }
179906
179907 static int sqlite3Fts5IterCollist(
179908 Fts5IndexIter *pIter,
179909 const u8 **pp, /* OUT: Pointer to position-list data */
179910 int *pn /* OUT: Size of position-list in bytes */
179911 ){
179912 assert( pIter->pIndex->pConfig->eDetail==FTS5_DETAIL_COLUMNS );
179913 *pp = pIter->poslist.p;
179914 *pn = pIter->poslist.n;
179915 return SQLITE_OK;
179916 }
179917
179918 /*
179919 ** This function is similar to sqlite3Fts5IterPoslist(), except that it
179920 ** copies the position list into the buffer supplied as the second
179921 ** argument.
@@ -178957,11 +180026,11 @@
180026 */
180027
180028 /*
180029 ** Return a simple checksum value based on the arguments.
180030 */
180031 static u64 sqlite3Fts5IndexEntryCksum(
180032 i64 iRowid,
180033 int iCol,
180034 int iPos,
180035 int iIdx,
180036 const char *pTerm,
@@ -179027,34 +180096,41 @@
180096 const char *z, /* Index key to query for */
180097 int n, /* Size of index key in bytes */
180098 int flags, /* Flags for Fts5IndexQuery */
180099 u64 *pCksum /* IN/OUT: Checksum value */
180100 ){
180101 int eDetail = p->pConfig->eDetail;
180102 u64 cksum = *pCksum;
180103 Fts5IndexIter *pIdxIter = 0;
180104 Fts5Buffer buf = {0, 0, 0};
180105 int rc = sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIdxIter);
180106
180107 while( rc==SQLITE_OK && 0==sqlite3Fts5IterEof(pIdxIter) ){
 
 
 
180108 i64 rowid = sqlite3Fts5IterRowid(pIdxIter);
180109
180110 if( eDetail==FTS5_DETAIL_NONE ){
180111 cksum ^= sqlite3Fts5IndexEntryCksum(rowid, 0, 0, iIdx, z, n);
180112 }else{
180113 rc = sqlite3Fts5IterPoslistBuffer(pIdxIter, &buf);
180114 if( rc==SQLITE_OK ){
180115 Fts5PoslistReader sReader;
180116 for(sqlite3Fts5PoslistReaderInit(buf.p, buf.n, &sReader);
180117 sReader.bEof==0;
180118 sqlite3Fts5PoslistReaderNext(&sReader)
180119 ){
180120 int iCol = FTS5_POS2COLUMN(sReader.iPos);
180121 int iOff = FTS5_POS2OFFSET(sReader.iPos);
180122 cksum ^= sqlite3Fts5IndexEntryCksum(rowid, iCol, iOff, iIdx, z, n);
180123 }
180124 }
180125 }
180126 if( rc==SQLITE_OK ){
 
 
 
 
 
 
 
 
 
180127 rc = sqlite3Fts5IterNext(pIdxIter);
180128 }
180129 }
180130 sqlite3Fts5IterClose(pIdxIter);
180131 fts5BufferFree(&buf);
180132
180133 *pCksum = cksum;
180134 return rc;
180135 }
180136
@@ -179344,18 +180420,19 @@
180420
180421
180422 /*
180423 ** Run internal checks to ensure that the FTS index (a) is internally
180424 ** consistent and (b) contains entries for which the XOR of the checksums
180425 ** as calculated by sqlite3Fts5IndexEntryCksum() is cksum.
180426 **
180427 ** Return SQLITE_CORRUPT if any of the internal checks fail, or if the
180428 ** checksum does not match. Return SQLITE_OK if all checks pass without
180429 ** error, or some other SQLite error code if another error (e.g. OOM)
180430 ** occurs.
180431 */
180432 static int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
180433 int eDetail = p->pConfig->eDetail;
180434 u64 cksum2 = 0; /* Checksum based on contents of indexes */
180435 Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
180436 Fts5IndexIter *pIter; /* Used to iterate through entire index */
180437 Fts5Structure *pStruct; /* Index structure */
180438
@@ -179403,16 +180480,22 @@
180480 char *z = (char*)fts5MultiIterTerm(pIter, &n);
180481
180482 /* If this is a new term, query for it. Update cksum3 with the results. */
180483 fts5TestTerm(p, &term, z, n, cksum2, &cksum3);
180484
180485 if( eDetail==FTS5_DETAIL_NONE ){
180486 if( 0==fts5MultiIterIsEmpty(p, pIter) ){
180487 cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, 0, 0, -1, z, n);
180488 }
180489 }else{
180490 poslist.n = 0;
180491 fts5SegiterPoslist(p, &pIter->aSeg[pIter->aFirst[1].iFirst], 0, &poslist);
180492 while( 0==sqlite3Fts5PoslistNext64(poslist.p, poslist.n, &iOff, &iPos) ){
180493 int iCol = FTS5_POS2COLUMN(iPos);
180494 int iTokOff = FTS5_POS2OFFSET(iPos);
180495 cksum2 ^= sqlite3Fts5IndexEntryCksum(iRowid, iCol, iTokOff, -1, z, n);
180496 }
180497 }
180498 }
180499 fts5TestTerm(p, &term, 0, 0, cksum2, &cksum3);
180500
180501 fts5MultiIterFree(p, pIter);
@@ -179424,38 +180507,10 @@
180507 #endif
180508 fts5BufferFree(&poslist);
180509 return fts5IndexReturn(p);
180510 }
180511
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180512 /*************************************************************************
180513 **************************************************************************
180514 ** Below this point is the implementation of the fts5_decode() scalar
180515 ** function only.
180516 */
@@ -180039,10 +181094,11 @@
181094 #define FTS5CSR_REQUIRE_DOCSIZE 0x02
181095 #define FTS5CSR_REQUIRE_INST 0x04
181096 #define FTS5CSR_EOF 0x08
181097 #define FTS5CSR_FREE_ZRANK 0x10
181098 #define FTS5CSR_REQUIRE_RESEEK 0x20
181099 #define FTS5CSR_REQUIRE_POSLIST 0x40
181100
181101 #define BitFlagAllTest(x,y) (((x) & (y))==(y))
181102 #define BitFlagTest(x,y) (((x) & (y))!=0)
181103
181104
@@ -180452,10 +181508,11 @@
181508 static void fts5CsrNewrow(Fts5Cursor *pCsr){
181509 CsrFlagSet(pCsr,
181510 FTS5CSR_REQUIRE_CONTENT
181511 | FTS5CSR_REQUIRE_DOCSIZE
181512 | FTS5CSR_REQUIRE_INST
181513 | FTS5CSR_REQUIRE_POSLIST
181514 );
181515 }
181516
181517 static void fts5FreeCursorComponents(Fts5Cursor *pCsr){
181518 Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
@@ -180534,19 +181591,22 @@
181591
181592 pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
181593 nBlob = sqlite3_column_bytes(pSorter->pStmt, 1);
181594 aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1);
181595
181596 /* nBlob==0 in detail=none mode. */
181597 if( nBlob>0 ){
181598 for(i=0; i<(pSorter->nIdx-1); i++){
181599 int iVal;
181600 a += fts5GetVarint32(a, iVal);
181601 iOff += iVal;
181602 pSorter->aIdx[i] = iOff;
181603 }
181604 pSorter->aIdx[i] = &aBlob[nBlob] - a;
181605 pSorter->aPoslist = a;
181606 }
181607
181608 fts5CsrNewrow(pCsr);
181609 }
181610
181611 return rc;
181612 }
@@ -180980,10 +182040,11 @@
182040 assert( pCsr->iLastRowid==LARGEST_INT64 );
182041 assert( pCsr->iFirstRowid==SMALLEST_INT64 );
182042 pCsr->ePlan = FTS5_PLAN_SOURCE;
182043 pCsr->pExpr = pTab->pSortCsr->pExpr;
182044 rc = fts5CursorFirst(pTab, pCsr, bDesc);
182045 sqlite3Fts5ExprClearEof(pCsr->pExpr);
182046 }else if( pMatch ){
182047 const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
182048 if( zExpr==0 ) zExpr = "";
182049
182050 rc = fts5CursorParseRank(pConfig, pCsr, pRank);
@@ -181409,10 +182470,12 @@
182470 fts5CheckTransactionState(pTab, FTS5_ROLLBACK, 0);
182471 rc = sqlite3Fts5StorageRollback(pTab->pStorage);
182472 return rc;
182473 }
182474
182475 static int fts5CsrPoslist(Fts5Cursor*, int, const u8**, int*);
182476
182477 static void *fts5ApiUserData(Fts5Context *pCtx){
182478 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182479 return pCsr->pAux->pUserData;
182480 }
182481
@@ -181458,21 +182521,76 @@
182521 static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){
182522 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182523 return sqlite3Fts5ExprPhraseSize(pCsr->pExpr, iPhrase);
182524 }
182525
182526 static int fts5ApiColumnText(
182527 Fts5Context *pCtx,
182528 int iCol,
182529 const char **pz,
182530 int *pn
182531 ){
182532 int rc = SQLITE_OK;
182533 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182534 if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
182535 *pz = 0;
182536 *pn = 0;
182537 }else{
182538 rc = fts5SeekCursor(pCsr, 0);
182539 if( rc==SQLITE_OK ){
182540 *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
182541 *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
182542 }
182543 }
182544 return rc;
182545 }
182546
182547 static int fts5CsrPoslist(
182548 Fts5Cursor *pCsr,
182549 int iPhrase,
182550 const u8 **pa,
182551 int *pn
182552 ){
182553 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
182554 int rc = SQLITE_OK;
182555 int bLive = (pCsr->pSorter==0);
182556
182557 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_POSLIST) ){
182558
182559 if( pConfig->eDetail!=FTS5_DETAIL_FULL ){
182560 Fts5PoslistPopulator *aPopulator;
182561 int i;
182562 aPopulator = sqlite3Fts5ExprClearPoslists(pCsr->pExpr, bLive);
182563 if( aPopulator==0 ) rc = SQLITE_NOMEM;
182564 for(i=0; i<pConfig->nCol && rc==SQLITE_OK; i++){
182565 int n; const char *z;
182566 rc = fts5ApiColumnText((Fts5Context*)pCsr, i, &z, &n);
182567 if( rc==SQLITE_OK ){
182568 rc = sqlite3Fts5ExprPopulatePoslists(
182569 pConfig, pCsr->pExpr, aPopulator, i, z, n
182570 );
182571 }
182572 }
182573 sqlite3_free(aPopulator);
182574
182575 if( pCsr->pSorter ){
182576 sqlite3Fts5ExprCheckPoslists(pCsr->pExpr, pCsr->pSorter->iRowid);
182577 }
182578 }
182579 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_POSLIST);
182580 }
182581
182582 if( pCsr->pSorter && pConfig->eDetail==FTS5_DETAIL_FULL ){
182583 Fts5Sorter *pSorter = pCsr->pSorter;
182584 int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
182585 *pn = pSorter->aIdx[iPhrase] - i1;
182586 *pa = &pSorter->aPoslist[i1];
182587 }else{
182588 *pn = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, pa);
182589 }
182590
182591 return rc;
182592 }
182593
182594 /*
182595 ** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
182596 ** correctly for the current view. Return SQLITE_OK if successful, or an
@@ -181493,47 +182611,50 @@
182611 if( aIter ){
182612 int nInst = 0; /* Number instances seen so far */
182613 int i;
182614
182615 /* Initialize all iterators */
182616 for(i=0; i<nIter && rc==SQLITE_OK; i++){
182617 const u8 *a;
182618 int n;
182619 rc = fts5CsrPoslist(pCsr, i, &a, &n);
182620 sqlite3Fts5PoslistReaderInit(a, n, &aIter[i]);
182621 }
182622
182623 if( rc==SQLITE_OK ){
182624 while( 1 ){
182625 int *aInst;
182626 int iBest = -1;
182627 for(i=0; i<nIter; i++){
182628 if( (aIter[i].bEof==0)
182629 && (iBest<0 || aIter[i].iPos<aIter[iBest].iPos)
182630 ){
182631 iBest = i;
182632 }
182633 }
182634 if( iBest<0 ) break;
182635
182636 nInst++;
182637 if( nInst>=pCsr->nInstAlloc ){
182638 pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
182639 aInst = (int*)sqlite3_realloc(
182640 pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
182641 );
182642 if( aInst ){
182643 pCsr->aInst = aInst;
182644 }else{
182645 rc = SQLITE_NOMEM;
182646 break;
182647 }
182648 }
182649
182650 aInst = &pCsr->aInst[3 * (nInst-1)];
182651 aInst[0] = iBest;
182652 aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
182653 aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
182654 sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
182655 }
182656 }
182657
182658 pCsr->nInstCount = nInst;
182659 CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
182660 }
@@ -181562,10 +182683,16 @@
182683 if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST)==0
182684 || SQLITE_OK==(rc = fts5CacheInstArray(pCsr))
182685 ){
182686 if( iIdx<0 || iIdx>=pCsr->nInstCount ){
182687 rc = SQLITE_RANGE;
182688 #if 0
182689 }else if( fts5IsOffsetless((Fts5Table*)pCsr->base.pVtab) ){
182690 *piPhrase = pCsr->aInst[iIdx*3];
182691 *piCol = pCsr->aInst[iIdx*3 + 2];
182692 *piOff = -1;
182693 #endif
182694 }else{
182695 *piPhrase = pCsr->aInst[iIdx*3];
182696 *piCol = pCsr->aInst[iIdx*3 + 1];
182697 *piOff = pCsr->aInst[iIdx*3 + 2];
182698 }
@@ -181575,31 +182702,10 @@
182702
182703 static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){
182704 return fts5CursorRowid((Fts5Cursor*)pCtx);
182705 }
182706
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182707 static int fts5ColumnSizeCb(
182708 void *pContext, /* Pointer to int */
182709 int tflags,
182710 const char *pToken, /* Buffer containing token */
182711 int nToken, /* Size of token in bytes */
@@ -181740,23 +182846,94 @@
182846 }
182847 *piOff += (iVal-2);
182848 }
182849 }
182850
182851 static int fts5ApiPhraseFirst(
182852 Fts5Context *pCtx,
182853 int iPhrase,
182854 Fts5PhraseIter *pIter,
182855 int *piCol, int *piOff
182856 ){
182857 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182858 int n;
182859 int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
182860 if( rc==SQLITE_OK ){
182861 pIter->b = &pIter->a[n];
182862 *piCol = 0;
182863 *piOff = 0;
182864 fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
182865 }
182866 return rc;
182867 }
182868
182869 static void fts5ApiPhraseNextColumn(
182870 Fts5Context *pCtx,
182871 Fts5PhraseIter *pIter,
182872 int *piCol
182873 ){
182874 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182875 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
182876
182877 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
182878 if( pIter->a>=pIter->b ){
182879 *piCol = -1;
182880 }else{
182881 int iIncr;
182882 pIter->a += fts5GetVarint32(&pIter->a[0], iIncr);
182883 *piCol += (iIncr-2);
182884 }
182885 }else{
182886 while( 1 ){
182887 int dummy;
182888 if( pIter->a>=pIter->b ){
182889 *piCol = -1;
182890 return;
182891 }
182892 if( pIter->a[0]==0x01 ) break;
182893 pIter->a += fts5GetVarint32(pIter->a, dummy);
182894 }
182895 pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
182896 }
182897 }
182898
182899 static int fts5ApiPhraseFirstColumn(
182900 Fts5Context *pCtx,
182901 int iPhrase,
182902 Fts5PhraseIter *pIter,
182903 int *piCol
182904 ){
182905 int rc = SQLITE_OK;
182906 Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
182907 Fts5Config *pConfig = ((Fts5Table*)(pCsr->base.pVtab))->pConfig;
182908
182909 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
182910 int n;
182911 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
182912 if( rc==SQLITE_OK ){
182913 pIter->b = &pIter->a[n];
182914 *piCol = 0;
182915 fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
182916 }
182917 }else{
182918 int n;
182919 rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
182920 if( rc==SQLITE_OK ){
182921 pIter->b = &pIter->a[n];
182922 if( n<=0 ){
182923 *piCol = -1;
182924 }else if( pIter->a[0]==0x01 ){
182925 pIter->a += 1 + fts5GetVarint32(&pIter->a[1], *piCol);
182926 }else{
182927 *piCol = 0;
182928 }
182929 }
182930 }
182931
182932 return rc;
182933 }
182934
182935
182936 static int fts5ApiQueryPhrase(Fts5Context*, int, void*,
182937 int(*)(const Fts5ExtensionApi*, Fts5Context*, void*)
182938 );
182939
@@ -181777,12 +182954,13 @@
182954 fts5ApiQueryPhrase,
182955 fts5ApiSetAuxdata,
182956 fts5ApiGetAuxdata,
182957 fts5ApiPhraseFirst,
182958 fts5ApiPhraseNext,
182959 fts5ApiPhraseFirstColumn,
182960 fts5ApiPhraseNextColumn,
182961 };
 
182962
182963 /*
182964 ** Implementation of API function xQueryPhrase().
182965 */
182966 static int fts5ApiQueryPhrase(
@@ -181911,24 +183089,50 @@
183089 int rc = SQLITE_OK;
183090 int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
183091 Fts5Buffer val;
183092
183093 memset(&val, 0, sizeof(Fts5Buffer));
183094 switch( ((Fts5Table*)(pCsr->base.pVtab))->pConfig->eDetail ){
183095 case FTS5_DETAIL_FULL:
183096
183097 /* Append the varints */
183098 for(i=0; i<(nPhrase-1); i++){
183099 const u8 *dummy;
183100 int nByte = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
183101 sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
183102 }
183103
183104 /* Append the position lists */
183105 for(i=0; i<nPhrase; i++){
183106 const u8 *pPoslist;
183107 int nPoslist;
183108 nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &pPoslist);
183109 sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
183110 }
183111 break;
183112
183113 case FTS5_DETAIL_COLUMNS:
183114
183115 /* Append the varints */
183116 for(i=0; rc==SQLITE_OK && i<(nPhrase-1); i++){
183117 const u8 *dummy;
183118 int nByte;
183119 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &dummy, &nByte);
183120 sqlite3Fts5BufferAppendVarint(&rc, &val, nByte);
183121 }
183122
183123 /* Append the position lists */
183124 for(i=0; rc==SQLITE_OK && i<nPhrase; i++){
183125 const u8 *pPoslist;
183126 int nPoslist;
183127 rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, i, &pPoslist, &nPoslist);
183128 sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist);
183129 }
183130 break;
183131
183132 default:
183133 break;
183134 }
183135
183136 sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free);
183137 return rc;
183138 }
@@ -182247,11 +183451,11 @@
183451 sqlite3_context *pCtx, /* Function call context */
183452 int nArg, /* Number of args */
183453 sqlite3_value **apVal /* Function arguments */
183454 ){
183455 assert( nArg==0 );
183456 sqlite3_result_text(pCtx, "fts5: 2016-01-14 14:19:50 d17bc2c92f4d086280e49a3cc72993be7fee2da7", -1, SQLITE_TRANSIENT);
183457 }
183458
183459 static int fts5Init(sqlite3 *db){
183460 static const sqlite3_module fts5Mod = {
183461 /* iVersion */ 2,
@@ -183179,32 +184383,77 @@
184383 struct Fts5IntegrityCtx {
184384 i64 iRowid;
184385 int iCol;
184386 int szCol;
184387 u64 cksum;
184388 Fts5Termset *pTermset;
184389 Fts5Config *pConfig;
184390 };
184391
184392
184393 /*
184394 ** Tokenization callback used by integrity check.
184395 */
184396 static int fts5StorageIntegrityCallback(
184397 void *pContext, /* Pointer to Fts5IntegrityCtx object */
184398 int tflags,
184399 const char *pToken, /* Buffer containing token */
184400 int nToken, /* Size of token in bytes */
184401 int iStart, /* Start offset of token */
184402 int iEnd /* End offset of token */
184403 ){
184404 Fts5IntegrityCtx *pCtx = (Fts5IntegrityCtx*)pContext;
184405 Fts5Termset *pTermset = pCtx->pTermset;
184406 int bPresent;
184407 int ii;
184408 int rc = SQLITE_OK;
184409 int iPos;
184410 int iCol;
184411
184412 if( (tflags & FTS5_TOKEN_COLOCATED)==0 || pCtx->szCol==0 ){
184413 pCtx->szCol++;
184414 }
184415
184416 switch( pCtx->pConfig->eDetail ){
184417 case FTS5_DETAIL_FULL:
184418 iPos = pCtx->szCol-1;
184419 iCol = pCtx->iCol;
184420 break;
184421
184422 case FTS5_DETAIL_COLUMNS:
184423 iPos = pCtx->iCol;
184424 iCol = 0;
184425 break;
184426
184427 default:
184428 assert( pCtx->pConfig->eDetail==FTS5_DETAIL_NONE );
184429 iPos = 0;
184430 iCol = 0;
184431 break;
184432 }
184433
184434 rc = sqlite3Fts5TermsetAdd(pTermset, 0, pToken, nToken, &bPresent);
184435 if( rc==SQLITE_OK && bPresent==0 ){
184436 pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
184437 pCtx->iRowid, iCol, iPos, 0, pToken, nToken
184438 );
184439 }
184440
184441 for(ii=0; rc==SQLITE_OK && ii<pCtx->pConfig->nPrefix; ii++){
184442 const int nChar = pCtx->pConfig->aPrefix[ii];
184443 int nByte = sqlite3Fts5IndexCharlenToBytelen(pToken, nToken, nChar);
184444 if( nByte ){
184445 rc = sqlite3Fts5TermsetAdd(pTermset, ii+1, pToken, nByte, &bPresent);
184446 if( bPresent==0 ){
184447 pCtx->cksum ^= sqlite3Fts5IndexEntryCksum(
184448 pCtx->iRowid, iCol, iPos, ii+1, pToken, nByte
184449 );
184450 }
184451 }
184452 }
184453
184454 return rc;
184455 }
184456
184457 /*
184458 ** Check that the contents of the FTS index match that of the %_content
184459 ** table. Return SQLITE_OK if they do, or SQLITE_CORRUPT if not. Return
@@ -183235,27 +184484,42 @@
184484 int i;
184485 ctx.iRowid = sqlite3_column_int64(pScan, 0);
184486 ctx.szCol = 0;
184487 if( pConfig->bColumnsize ){
184488 rc = sqlite3Fts5StorageDocsize(p, ctx.iRowid, aColSize);
184489 }
184490 if( rc==SQLITE_OK && pConfig->eDetail==FTS5_DETAIL_NONE ){
184491 rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
184492 }
184493 for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
184494 if( pConfig->abUnindexed[i] ) continue;
184495 ctx.iCol = i;
184496 ctx.szCol = 0;
184497 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
184498 rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
184499 }
184500 if( rc==SQLITE_OK ){
184501 rc = sqlite3Fts5Tokenize(pConfig,
184502 FTS5_TOKENIZE_DOCUMENT,
184503 (const char*)sqlite3_column_text(pScan, i+1),
184504 sqlite3_column_bytes(pScan, i+1),
184505 (void*)&ctx,
184506 fts5StorageIntegrityCallback
184507 );
184508 }
184509 if( rc==SQLITE_OK && pConfig->bColumnsize && ctx.szCol!=aColSize[i] ){
184510 rc = FTS5_CORRUPT;
184511 }
184512 aTotalSize[i] += ctx.szCol;
184513 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
184514 sqlite3Fts5TermsetFree(ctx.pTermset);
184515 ctx.pTermset = 0;
184516 }
184517 }
184518 sqlite3Fts5TermsetFree(ctx.pTermset);
184519 ctx.pTermset = 0;
184520
184521 if( rc!=SQLITE_OK ) break;
184522 }
184523 rc2 = sqlite3_reset(pScan);
184524 if( rc==SQLITE_OK ) rc = rc2;
184525 }
@@ -185777,11 +187041,11 @@
187041
187042 pCsr->rowid++;
187043
187044 if( pTab->eType==FTS5_VOCAB_COL ){
187045 for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
187046 if( pCsr->aDoc[pCsr->iCol] ) break;
187047 }
187048 }
187049
187050 if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
187051 if( sqlite3Fts5IterEof(pCsr->pIter) ){
@@ -185810,28 +187074,56 @@
187074 i64 dummy;
187075 const u8 *pPos; int nPos; /* Position list */
187076 i64 iPos = 0; /* 64-bit position read from poslist */
187077 int iOff = 0; /* Current offset within position list */
187078
187079 switch( pCsr->pConfig->eDetail ){
187080 case FTS5_DETAIL_FULL:
187081 rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy);
187082 if( rc==SQLITE_OK ){
187083 if( pTab->eType==FTS5_VOCAB_ROW ){
187084 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
187085 pCsr->aCnt[0]++;
187086 }
187087 pCsr->aDoc[0]++;
187088 }else{
187089 int iCol = -1;
187090 while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
187091 int ii = FTS5_POS2COLUMN(iPos);
187092 pCsr->aCnt[ii]++;
187093 if( iCol!=ii ){
187094 pCsr->aDoc[ii]++;
187095 iCol = ii;
187096 }
187097 }
187098 }
187099 }
187100 break;
187101
187102 case FTS5_DETAIL_COLUMNS:
187103 if( pTab->eType==FTS5_VOCAB_ROW ){
187104 pCsr->aDoc[0]++;
187105 }else{
187106 Fts5Buffer buf = {0, 0, 0};
187107 rc = sqlite3Fts5IterPoslistBuffer(pCsr->pIter, &buf);
187108 if( rc==SQLITE_OK ){
187109 while( 0==sqlite3Fts5PoslistNext64(buf.p, buf.n, &iOff,&iPos) ){
187110 assert_nc( iPos>=0 && iPos<nCol );
187111 if( iPos<nCol ) pCsr->aDoc[iPos]++;
187112 }
187113 }
187114 sqlite3Fts5BufferFree(&buf);
187115 }
187116 break;
187117
187118 default:
187119 assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE );
187120 pCsr->aDoc[0]++;
187121 break;
187122 }
187123
187124 if( rc==SQLITE_OK ){
187125 rc = sqlite3Fts5IterNextScan(pCsr->pIter);
187126 }
187127
187128 if( rc==SQLITE_OK ){
187129 zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
@@ -185843,11 +187135,11 @@
187135 }
187136 }
187137 }
187138
187139 if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
187140 while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++;
187141 assert( pCsr->iCol<pCsr->pConfig->nCol );
187142 }
187143 return rc;
187144 }
187145
@@ -185923,34 +187215,40 @@
187215 sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
187216 sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
187217 int iCol /* Index of column to read value from */
187218 ){
187219 Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
187220 int eDetail = pCsr->pConfig->eDetail;
187221 int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType;
187222 i64 iVal = 0;
187223
187224 if( iCol==0 ){
187225 sqlite3_result_text(
187226 pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
187227 );
187228 }else if( eType==FTS5_VOCAB_COL ){
 
187229 assert( iCol==1 || iCol==2 || iCol==3 );
187230 if( iCol==1 ){
187231 if( eDetail!=FTS5_DETAIL_NONE ){
187232 const char *z = pCsr->pConfig->azCol[pCsr->iCol];
187233 sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
187234 }
187235 }else if( iCol==2 ){
187236 iVal = pCsr->aDoc[pCsr->iCol];
187237 }else{
187238 iVal = pCsr->aCnt[pCsr->iCol];
187239 }
187240 }else{
187241 assert( iCol==1 || iCol==2 );
187242 if( iCol==1 ){
187243 iVal = pCsr->aDoc[0];
187244 }else{
187245 iVal = pCsr->aCnt[0];
187246 }
187247 }
187248
187249 if( iVal>0 ) sqlite3_result_int64(pCtx, iVal);
187250 return SQLITE_OK;
187251 }
187252
187253 /*
187254 ** This is the xRowid method. The SQLite core calls this routine to
187255
+73 -9
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -109,13 +109,13 @@
109109
**
110110
** See also: [sqlite3_libversion()],
111111
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112112
** [sqlite_version()] and [sqlite_source_id()].
113113
*/
114
-#define SQLITE_VERSION "3.10.0"
115
-#define SQLITE_VERSION_NUMBER 3010000
116
-#define SQLITE_SOURCE_ID "2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566"
114
+#define SQLITE_VERSION "3.11.0"
115
+#define SQLITE_VERSION_NUMBER 3011000
116
+#define SQLITE_SOURCE_ID "2016-01-14 14:19:50 d17bc2c92f4d086280e49a3cc72993be7fee2da7"
117117
118118
/*
119119
** CAPI3REF: Run-Time Library Version Numbers
120120
** KEYWORDS: sqlite3_version, sqlite3_sourceid
121121
**
@@ -792,12 +792,17 @@
792792
** improve performance on some systems.
793793
**
794794
** <li>[[SQLITE_FCNTL_FILE_POINTER]]
795795
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
796796
** to the [sqlite3_file] object associated with a particular database
797
-** connection. See the [sqlite3_file_control()] documentation for
798
-** additional information.
797
+** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER].
798
+**
799
+** <li>[[SQLITE_FCNTL_JOURNAL_POINTER]]
800
+** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer
801
+** to the [sqlite3_file] object associated with the journal file (either
802
+** the [rollback journal] or the [write-ahead log]) for a particular database
803
+** connection. See also [SQLITE_FCNTL_FILE_POINTER].
799804
**
800805
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
801806
** No longer in use.
802807
**
803808
** <li>[[SQLITE_FCNTL_SYNC]]
@@ -1008,10 +1013,11 @@
10081013
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
10091014
#define SQLITE_FCNTL_WAL_BLOCK 24
10101015
#define SQLITE_FCNTL_ZIPVFS 25
10111016
#define SQLITE_FCNTL_RBU 26
10121017
#define SQLITE_FCNTL_VFS_POINTER 27
1018
+#define SQLITE_FCNTL_JOURNAL_POINTER 28
10131019
10141020
/* deprecated names */
10151021
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
10161022
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
10171023
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -8185,10 +8191,13 @@
81858191
** If parameter iCol is greater than or equal to the number of columns
81868192
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
81878193
** an OOM condition or IO error), an appropriate SQLite error code is
81888194
** returned.
81898195
**
8196
+** This function may be quite inefficient if used with an FTS5 table
8197
+** created with the "columnsize=0" option.
8198
+**
81908199
** xColumnText:
81918200
** This function attempts to retrieve the text of column iCol of the
81928201
** current document. If successful, (*pz) is set to point to a buffer
81938202
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
81948203
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -8205,18 +8214,32 @@
82058214
** xInstCount:
82068215
** Set *pnInst to the total number of occurrences of all phrases within
82078216
** the query within the current row. Return SQLITE_OK if successful, or
82088217
** an error code (i.e. SQLITE_NOMEM) if an error occurs.
82098218
**
8219
+** This API can be quite slow if used with an FTS5 table created with the
8220
+** "detail=none" or "detail=column" option. If the FTS5 table is created
8221
+** with either "detail=none" or "detail=column" and "content=" option
8222
+** (i.e. if it is a contentless table), then this API always returns 0.
8223
+**
82108224
** xInst:
82118225
** Query for the details of phrase match iIdx within the current row.
82128226
** Phrase matches are numbered starting from zero, so the iIdx argument
82138227
** should be greater than or equal to zero and smaller than the value
82148228
** output by xInstCount().
8229
+**
8230
+** Usually, output parameter *piPhrase is set to the phrase number, *piCol
8231
+** to the column in which it occurs and *piOff the token offset of the
8232
+** first token of the phrase. The exception is if the table was created
8233
+** with the offsets=0 option specified. In this case *piOff is always
8234
+** set to -1.
82158235
**
82168236
** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
82178237
** if an error occurs.
8238
+**
8239
+** This API can be quite slow if used with an FTS5 table created with the
8240
+** "detail=none" or "detail=column" option.
82188241
**
82198242
** xRowid:
82208243
** Returns the rowid of the current row.
82218244
**
82228245
** xTokenize:
@@ -8297,25 +8320,63 @@
82978320
** through instances of phrase iPhrase, use the following code:
82988321
**
82998322
** Fts5PhraseIter iter;
83008323
** int iCol, iOff;
83018324
** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
8302
-** iOff>=0;
8325
+** iCol>=0;
83038326
** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
83048327
** ){
83058328
** // An instance of phrase iPhrase at offset iOff of column iCol
83068329
** }
83078330
**
83088331
** The Fts5PhraseIter structure is defined above. Applications should not
83098332
** modify this structure directly - it should only be used as shown above
8310
-** with the xPhraseFirst() and xPhraseNext() API methods.
8333
+** with the xPhraseFirst() and xPhraseNext() API methods (and by
8334
+** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
8335
+**
8336
+** This API can be quite slow if used with an FTS5 table created with the
8337
+** "detail=none" or "detail=column" option. If the FTS5 table is created
8338
+** with either "detail=none" or "detail=column" and "content=" option
8339
+** (i.e. if it is a contentless table), then this API always iterates
8340
+** through an empty set (all calls to xPhraseFirst() set iCol to -1).
83118341
**
83128342
** xPhraseNext()
83138343
** See xPhraseFirst above.
8344
+**
8345
+** xPhraseFirstColumn()
8346
+** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
8347
+** and xPhraseNext() APIs described above. The difference is that instead
8348
+** of iterating through all instances of a phrase in the current row, these
8349
+** APIs are used to iterate through the set of columns in the current row
8350
+** that contain one or more instances of a specified phrase. For example:
8351
+**
8352
+** Fts5PhraseIter iter;
8353
+** int iCol;
8354
+** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
8355
+** iCol>=0;
8356
+** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
8357
+** ){
8358
+** // Column iCol contains at least one instance of phrase iPhrase
8359
+** }
8360
+**
8361
+** This API can be quite slow if used with an FTS5 table created with the
8362
+** "detail=none" option. If the FTS5 table is created with either
8363
+** "detail=none" "content=" option (i.e. if it is a contentless table),
8364
+** then this API always iterates through an empty set (all calls to
8365
+** xPhraseFirstColumn() set iCol to -1).
8366
+**
8367
+** The information accessed using this API and its companion
8368
+** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
8369
+** (or xInst/xInstCount). The chief advantage of this API is that it is
8370
+** significantly more efficient than those alternatives when used with
8371
+** "detail=column" tables.
8372
+**
8373
+** xPhraseNextColumn()
8374
+** See xPhraseFirstColumn above.
83148375
*/
83158376
struct Fts5ExtensionApi {
8316
- int iVersion; /* Currently always set to 1 */
8377
+ int iVersion; /* Currently always set to 3 */
83178378
83188379
void *(*xUserData)(Fts5Context*);
83198380
83208381
int (*xColumnCount)(Fts5Context*);
83218382
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -8341,12 +8402,15 @@
83418402
int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
83428403
);
83438404
int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
83448405
void *(*xGetAuxdata)(Fts5Context*, int bClear);
83458406
8346
- void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
8407
+ int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
83478408
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
8409
+
8410
+ int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
8411
+ void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
83488412
};
83498413
83508414
/*
83518415
** CUSTOM AUXILIARY FUNCTIONS
83528416
*************************************************************************/
83538417
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -109,13 +109,13 @@
109 **
110 ** See also: [sqlite3_libversion()],
111 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112 ** [sqlite_version()] and [sqlite_source_id()].
113 */
114 #define SQLITE_VERSION "3.10.0"
115 #define SQLITE_VERSION_NUMBER 3010000
116 #define SQLITE_SOURCE_ID "2016-01-06 11:01:07 fd0a50f0797d154fefff724624f00548b5320566"
117
118 /*
119 ** CAPI3REF: Run-Time Library Version Numbers
120 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
121 **
@@ -792,12 +792,17 @@
792 ** improve performance on some systems.
793 **
794 ** <li>[[SQLITE_FCNTL_FILE_POINTER]]
795 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
796 ** to the [sqlite3_file] object associated with a particular database
797 ** connection. See the [sqlite3_file_control()] documentation for
798 ** additional information.
 
 
 
 
 
799 **
800 ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
801 ** No longer in use.
802 **
803 ** <li>[[SQLITE_FCNTL_SYNC]]
@@ -1008,10 +1013,11 @@
1008 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23
1009 #define SQLITE_FCNTL_WAL_BLOCK 24
1010 #define SQLITE_FCNTL_ZIPVFS 25
1011 #define SQLITE_FCNTL_RBU 26
1012 #define SQLITE_FCNTL_VFS_POINTER 27
 
1013
1014 /* deprecated names */
1015 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1016 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1017 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -8185,10 +8191,13 @@
8185 ** If parameter iCol is greater than or equal to the number of columns
8186 ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
8187 ** an OOM condition or IO error), an appropriate SQLite error code is
8188 ** returned.
8189 **
 
 
 
8190 ** xColumnText:
8191 ** This function attempts to retrieve the text of column iCol of the
8192 ** current document. If successful, (*pz) is set to point to a buffer
8193 ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
8194 ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -8205,18 +8214,32 @@
8205 ** xInstCount:
8206 ** Set *pnInst to the total number of occurrences of all phrases within
8207 ** the query within the current row. Return SQLITE_OK if successful, or
8208 ** an error code (i.e. SQLITE_NOMEM) if an error occurs.
8209 **
 
 
 
 
 
8210 ** xInst:
8211 ** Query for the details of phrase match iIdx within the current row.
8212 ** Phrase matches are numbered starting from zero, so the iIdx argument
8213 ** should be greater than or equal to zero and smaller than the value
8214 ** output by xInstCount().
 
 
 
 
 
 
8215 **
8216 ** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
8217 ** if an error occurs.
 
 
 
8218 **
8219 ** xRowid:
8220 ** Returns the rowid of the current row.
8221 **
8222 ** xTokenize:
@@ -8297,25 +8320,63 @@
8297 ** through instances of phrase iPhrase, use the following code:
8298 **
8299 ** Fts5PhraseIter iter;
8300 ** int iCol, iOff;
8301 ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
8302 ** iOff>=0;
8303 ** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
8304 ** ){
8305 ** // An instance of phrase iPhrase at offset iOff of column iCol
8306 ** }
8307 **
8308 ** The Fts5PhraseIter structure is defined above. Applications should not
8309 ** modify this structure directly - it should only be used as shown above
8310 ** with the xPhraseFirst() and xPhraseNext() API methods.
 
 
 
 
 
 
 
8311 **
8312 ** xPhraseNext()
8313 ** See xPhraseFirst above.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8314 */
8315 struct Fts5ExtensionApi {
8316 int iVersion; /* Currently always set to 1 */
8317
8318 void *(*xUserData)(Fts5Context*);
8319
8320 int (*xColumnCount)(Fts5Context*);
8321 int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -8341,12 +8402,15 @@
8341 int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
8342 );
8343 int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
8344 void *(*xGetAuxdata)(Fts5Context*, int bClear);
8345
8346 void (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
8347 void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
 
 
 
8348 };
8349
8350 /*
8351 ** CUSTOM AUXILIARY FUNCTIONS
8352 *************************************************************************/
8353
--- src/sqlite3.h
+++ src/sqlite3.h
@@ -109,13 +109,13 @@
109 **
110 ** See also: [sqlite3_libversion()],
111 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
112 ** [sqlite_version()] and [sqlite_source_id()].
113 */
114 #define SQLITE_VERSION "3.11.0"
115 #define SQLITE_VERSION_NUMBER 3011000
116 #define SQLITE_SOURCE_ID "2016-01-14 14:19:50 d17bc2c92f4d086280e49a3cc72993be7fee2da7"
117
118 /*
119 ** CAPI3REF: Run-Time Library Version Numbers
120 ** KEYWORDS: sqlite3_version, sqlite3_sourceid
121 **
@@ -792,12 +792,17 @@
792 ** improve performance on some systems.
793 **
794 ** <li>[[SQLITE_FCNTL_FILE_POINTER]]
795 ** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
796 ** to the [sqlite3_file] object associated with a particular database
797 ** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER].
798 **
799 ** <li>[[SQLITE_FCNTL_JOURNAL_POINTER]]
800 ** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer
801 ** to the [sqlite3_file] object associated with the journal file (either
802 ** the [rollback journal] or the [write-ahead log]) for a particular database
803 ** connection. See also [SQLITE_FCNTL_FILE_POINTER].
804 **
805 ** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
806 ** No longer in use.
807 **
808 ** <li>[[SQLITE_FCNTL_SYNC]]
@@ -1008,10 +1013,11 @@
1013 #define SQLITE_FCNTL_WIN32_SET_HANDLE 23
1014 #define SQLITE_FCNTL_WAL_BLOCK 24
1015 #define SQLITE_FCNTL_ZIPVFS 25
1016 #define SQLITE_FCNTL_RBU 26
1017 #define SQLITE_FCNTL_VFS_POINTER 27
1018 #define SQLITE_FCNTL_JOURNAL_POINTER 28
1019
1020 /* deprecated names */
1021 #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
1022 #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
1023 #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
@@ -8185,10 +8191,13 @@
8191 ** If parameter iCol is greater than or equal to the number of columns
8192 ** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
8193 ** an OOM condition or IO error), an appropriate SQLite error code is
8194 ** returned.
8195 **
8196 ** This function may be quite inefficient if used with an FTS5 table
8197 ** created with the "columnsize=0" option.
8198 **
8199 ** xColumnText:
8200 ** This function attempts to retrieve the text of column iCol of the
8201 ** current document. If successful, (*pz) is set to point to a buffer
8202 ** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
8203 ** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
@@ -8205,18 +8214,32 @@
8214 ** xInstCount:
8215 ** Set *pnInst to the total number of occurrences of all phrases within
8216 ** the query within the current row. Return SQLITE_OK if successful, or
8217 ** an error code (i.e. SQLITE_NOMEM) if an error occurs.
8218 **
8219 ** This API can be quite slow if used with an FTS5 table created with the
8220 ** "detail=none" or "detail=column" option. If the FTS5 table is created
8221 ** with either "detail=none" or "detail=column" and "content=" option
8222 ** (i.e. if it is a contentless table), then this API always returns 0.
8223 **
8224 ** xInst:
8225 ** Query for the details of phrase match iIdx within the current row.
8226 ** Phrase matches are numbered starting from zero, so the iIdx argument
8227 ** should be greater than or equal to zero and smaller than the value
8228 ** output by xInstCount().
8229 **
8230 ** Usually, output parameter *piPhrase is set to the phrase number, *piCol
8231 ** to the column in which it occurs and *piOff the token offset of the
8232 ** first token of the phrase. The exception is if the table was created
8233 ** with the offsets=0 option specified. In this case *piOff is always
8234 ** set to -1.
8235 **
8236 ** Returns SQLITE_OK if successful, or an error code (i.e. SQLITE_NOMEM)
8237 ** if an error occurs.
8238 **
8239 ** This API can be quite slow if used with an FTS5 table created with the
8240 ** "detail=none" or "detail=column" option.
8241 **
8242 ** xRowid:
8243 ** Returns the rowid of the current row.
8244 **
8245 ** xTokenize:
@@ -8297,25 +8320,63 @@
8320 ** through instances of phrase iPhrase, use the following code:
8321 **
8322 ** Fts5PhraseIter iter;
8323 ** int iCol, iOff;
8324 ** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
8325 ** iCol>=0;
8326 ** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
8327 ** ){
8328 ** // An instance of phrase iPhrase at offset iOff of column iCol
8329 ** }
8330 **
8331 ** The Fts5PhraseIter structure is defined above. Applications should not
8332 ** modify this structure directly - it should only be used as shown above
8333 ** with the xPhraseFirst() and xPhraseNext() API methods (and by
8334 ** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
8335 **
8336 ** This API can be quite slow if used with an FTS5 table created with the
8337 ** "detail=none" or "detail=column" option. If the FTS5 table is created
8338 ** with either "detail=none" or "detail=column" and "content=" option
8339 ** (i.e. if it is a contentless table), then this API always iterates
8340 ** through an empty set (all calls to xPhraseFirst() set iCol to -1).
8341 **
8342 ** xPhraseNext()
8343 ** See xPhraseFirst above.
8344 **
8345 ** xPhraseFirstColumn()
8346 ** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
8347 ** and xPhraseNext() APIs described above. The difference is that instead
8348 ** of iterating through all instances of a phrase in the current row, these
8349 ** APIs are used to iterate through the set of columns in the current row
8350 ** that contain one or more instances of a specified phrase. For example:
8351 **
8352 ** Fts5PhraseIter iter;
8353 ** int iCol;
8354 ** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
8355 ** iCol>=0;
8356 ** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
8357 ** ){
8358 ** // Column iCol contains at least one instance of phrase iPhrase
8359 ** }
8360 **
8361 ** This API can be quite slow if used with an FTS5 table created with the
8362 ** "detail=none" option. If the FTS5 table is created with either
8363 ** "detail=none" "content=" option (i.e. if it is a contentless table),
8364 ** then this API always iterates through an empty set (all calls to
8365 ** xPhraseFirstColumn() set iCol to -1).
8366 **
8367 ** The information accessed using this API and its companion
8368 ** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
8369 ** (or xInst/xInstCount). The chief advantage of this API is that it is
8370 ** significantly more efficient than those alternatives when used with
8371 ** "detail=column" tables.
8372 **
8373 ** xPhraseNextColumn()
8374 ** See xPhraseFirstColumn above.
8375 */
8376 struct Fts5ExtensionApi {
8377 int iVersion; /* Currently always set to 3 */
8378
8379 void *(*xUserData)(Fts5Context*);
8380
8381 int (*xColumnCount)(Fts5Context*);
8382 int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
@@ -8341,12 +8402,15 @@
8402 int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
8403 );
8404 int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
8405 void *(*xGetAuxdata)(Fts5Context*, int bClear);
8406
8407 int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
8408 void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
8409
8410 int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
8411 void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
8412 };
8413
8414 /*
8415 ** CUSTOM AUXILIARY FUNCTIONS
8416 *************************************************************************/
8417

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button