mirror of https://github.com/sqlite/sqlite
Remove the 0x00 terminators from the end of doclists stored on disk.
FossilOrigin-Name: 00d990061dec3661b0376bd167082942d5563bfe
This commit is contained in:
parent
60f8139a96
commit
fe8e2eba0a
|
@ -117,6 +117,12 @@ typedef struct Fts5Config Fts5Config;
|
||||||
** bColumnsize:
|
** bColumnsize:
|
||||||
** True if the %_docsize table is created.
|
** True if the %_docsize table is created.
|
||||||
**
|
**
|
||||||
|
** bPrefixIndex:
|
||||||
|
** This is only used for debugging. If set to false, any prefix indexes
|
||||||
|
** are ignored. This value is configured using:
|
||||||
|
**
|
||||||
|
** INSERT INTO tbl(tbl, rank) VALUES('prefix-index', $bPrefixIndex);
|
||||||
|
**
|
||||||
*/
|
*/
|
||||||
struct Fts5Config {
|
struct Fts5Config {
|
||||||
sqlite3 *db; /* Database handle */
|
sqlite3 *db; /* Database handle */
|
||||||
|
@ -145,6 +151,10 @@ struct Fts5Config {
|
||||||
|
|
||||||
/* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
|
/* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */
|
||||||
char **pzErrmsg;
|
char **pzErrmsg;
|
||||||
|
|
||||||
|
#ifdef SQLITE_DEBUG
|
||||||
|
int bPrefixIndex; /* True to use prefix-indexes */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Current expected value of %_config table 'version' field */
|
/* Current expected value of %_config table 'version' field */
|
||||||
|
|
|
@ -16,12 +16,14 @@
|
||||||
#include "fts5Int.h"
|
#include "fts5Int.h"
|
||||||
|
|
||||||
int sqlite3Fts5BufferGrow(int *pRc, Fts5Buffer *pBuf, int nByte){
|
int sqlite3Fts5BufferGrow(int *pRc, Fts5Buffer *pBuf, int nByte){
|
||||||
/* A no-op if an error has already occurred */
|
|
||||||
if( *pRc ) return 1;
|
|
||||||
|
|
||||||
if( (pBuf->n + nByte) > pBuf->nSpace ){
|
if( (pBuf->n + nByte) > pBuf->nSpace ){
|
||||||
u8 *pNew;
|
u8 *pNew;
|
||||||
int nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64;
|
int nNew = pBuf->nSpace ? pBuf->nSpace*2 : 64;
|
||||||
|
|
||||||
|
/* A no-op if an error has already occurred */
|
||||||
|
if( *pRc ) return 1;
|
||||||
|
|
||||||
while( nNew<(pBuf->n + nByte) ){
|
while( nNew<(pBuf->n + nByte) ){
|
||||||
nNew = nNew * 2;
|
nNew = nNew * 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -480,6 +480,9 @@ int sqlite3Fts5ConfigParse(
|
||||||
pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
|
pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
|
||||||
pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
|
pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
|
||||||
pRet->bColumnsize = 1;
|
pRet->bColumnsize = 1;
|
||||||
|
#ifdef SQLITE_DEBUG
|
||||||
|
pRet->bPrefixIndex = 1;
|
||||||
|
#endif
|
||||||
if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){
|
if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){
|
||||||
*pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName);
|
*pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
|
|
|
@ -475,6 +475,9 @@ struct Fts5CResult {
|
||||||
** For each rowid on the page corresponding to the current term, the
|
** For each rowid on the page corresponding to the current term, the
|
||||||
** corresponding aRowidOffset[] entry is set to the byte offset of the
|
** corresponding aRowidOffset[] entry is set to the byte offset of the
|
||||||
** start of the "position-list-size" field within the page.
|
** start of the "position-list-size" field within the page.
|
||||||
|
**
|
||||||
|
** iTermIdx:
|
||||||
|
** Index of current term on iTermLeafPgno.
|
||||||
*/
|
*/
|
||||||
struct Fts5SegIter {
|
struct Fts5SegIter {
|
||||||
Fts5StructureSegment *pSeg; /* Segment to iterate through */
|
Fts5StructureSegment *pSeg; /* Segment to iterate through */
|
||||||
|
@ -489,6 +492,9 @@ struct Fts5SegIter {
|
||||||
int iTermLeafPgno;
|
int iTermLeafPgno;
|
||||||
int iTermLeafOffset;
|
int iTermLeafOffset;
|
||||||
|
|
||||||
|
int iTermIdx;
|
||||||
|
int iEndofDoclist;
|
||||||
|
|
||||||
/* The following are only used if the FTS5_SEGITER_REVERSE flag is set. */
|
/* The following are only used if the FTS5_SEGITER_REVERSE flag is set. */
|
||||||
int iRowidOffset; /* Current entry in aRowidOffset[] */
|
int iRowidOffset; /* Current entry in aRowidOffset[] */
|
||||||
int nRowidOffset; /* Allocated size of aRowidOffset[] array */
|
int nRowidOffset; /* Allocated size of aRowidOffset[] array */
|
||||||
|
@ -508,7 +514,7 @@ struct Fts5SegIter {
|
||||||
** leaf page.
|
** leaf page.
|
||||||
*/
|
*/
|
||||||
#define ASSERT_SZLEAF_OK(x) assert( \
|
#define ASSERT_SZLEAF_OK(x) assert( \
|
||||||
(x)->szLeaf==fts5GetU16(&(x)->p[2]) || (x)->szLeaf==(x)->nn \
|
(x)->szLeaf==(x)->nn || (x)->szLeaf==fts5GetU16(&(x)->p[2]) \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define FTS5_SEGITER_ONETERM 0x01
|
#define FTS5_SEGITER_ONETERM 0x01
|
||||||
|
@ -522,9 +528,12 @@ struct Fts5SegIter {
|
||||||
*/
|
*/
|
||||||
#define fts5LeafIsTermless(x) ((x)->szLeaf >= (x)->nn)
|
#define fts5LeafIsTermless(x) ((x)->szLeaf >= (x)->nn)
|
||||||
|
|
||||||
#define fts5LeafFirstTermOff(x) (fts5GetU16(&(x)->p[(x)->szLeaf]))
|
#define fts5LeafTermOff(x, i) (fts5GetU16(&(x)->p[(x)->szLeaf + (i)*2]))
|
||||||
|
|
||||||
#define fts5LeafFirstRowidOff(x) (fts5GetU16((x)->p))
|
#define fts5LeafFirstRowidOff(x) (fts5GetU16((x)->p))
|
||||||
|
|
||||||
|
#define fts5LeafFirstTermOff(x) fts5LeafTermOff(x, 0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** poslist:
|
** poslist:
|
||||||
** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
|
** Used by sqlite3Fts5IterPoslist() when the poslist needs to be buffered.
|
||||||
|
@ -1153,8 +1162,9 @@ static void fts5StructurePromote(
|
||||||
int szPromote = 0; /* Promote anything this size or smaller */
|
int szPromote = 0; /* Promote anything this size or smaller */
|
||||||
Fts5StructureSegment *pSeg; /* Segment just written */
|
Fts5StructureSegment *pSeg; /* Segment just written */
|
||||||
int szSeg; /* Size of segment just written */
|
int szSeg; /* Size of segment just written */
|
||||||
|
int nSeg = pStruct->aLevel[iLvl].nSeg;
|
||||||
|
|
||||||
|
if( nSeg==0 ) return;
|
||||||
pSeg = &pStruct->aLevel[iLvl].aSeg[pStruct->aLevel[iLvl].nSeg-1];
|
pSeg = &pStruct->aLevel[iLvl].aSeg[pStruct->aLevel[iLvl].nSeg-1];
|
||||||
szSeg = (1 + pSeg->pgnoLast - pSeg->pgnoFirst);
|
szSeg = (1 + pSeg->pgnoLast - pSeg->pgnoFirst);
|
||||||
|
|
||||||
|
@ -1464,6 +1474,14 @@ static void fts5SegIterNextPage(
|
||||||
}else{
|
}else{
|
||||||
pIter->pLeaf = 0;
|
pIter->pLeaf = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( pIter->pLeaf ){
|
||||||
|
if( fts5LeafIsTermless(pIter->pLeaf) ){
|
||||||
|
pIter->iEndofDoclist = pIter->pLeaf->nn+1;
|
||||||
|
}else{
|
||||||
|
pIter->iEndofDoclist = fts5LeafFirstTermOff(pIter->pLeaf);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1505,6 +1523,20 @@ static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fts5SegIterLoadEod(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
|
Fts5Data *pLeaf = pIter->pLeaf;
|
||||||
|
int nPg = (pLeaf->nn - pLeaf->szLeaf) / 2;
|
||||||
|
|
||||||
|
assert( pIter->iLeafPgno==pIter->iTermLeafPgno );
|
||||||
|
if( (pIter->iTermIdx+1)<nPg ){
|
||||||
|
int iRead = pLeaf->szLeaf + (pIter->iTermIdx + 1) * 2;
|
||||||
|
pIter->iEndofDoclist = fts5GetU16(&pLeaf->p[iRead]);
|
||||||
|
}else{
|
||||||
|
pIter->iEndofDoclist = pLeaf->nn+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
|
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
|
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
|
||||||
int iOff = pIter->iLeafOffset;
|
int iOff = pIter->iLeafOffset;
|
||||||
|
@ -1551,6 +1583,7 @@ static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
|
||||||
pIter->iTermLeafPgno = pIter->iLeafPgno;
|
pIter->iTermLeafPgno = pIter->iLeafPgno;
|
||||||
pIter->iLeafOffset = iOff;
|
pIter->iLeafOffset = iOff;
|
||||||
|
|
||||||
|
fts5SegIterLoadEod(p, pIter);
|
||||||
fts5SegIterLoadRowid(p, pIter);
|
fts5SegIterLoadRowid(p, pIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1585,9 +1618,10 @@ static void fts5SegIterInit(
|
||||||
}
|
}
|
||||||
|
|
||||||
if( p->rc==SQLITE_OK ){
|
if( p->rc==SQLITE_OK ){
|
||||||
u8 *a = pIter->pLeaf->p;
|
|
||||||
pIter->iLeafOffset = 4;
|
pIter->iLeafOffset = 4;
|
||||||
|
assert_nc( pIter->pLeaf->nn>4 );
|
||||||
assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
|
assert( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
|
||||||
|
pIter->iTermIdx = 0;
|
||||||
fts5SegIterLoadTerm(p, pIter, 0);
|
fts5SegIterLoadTerm(p, pIter, 0);
|
||||||
fts5SegIterLoadNPos(p, pIter);
|
fts5SegIterLoadNPos(p, pIter);
|
||||||
}
|
}
|
||||||
|
@ -1614,6 +1648,10 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
u8 *a = pIter->pLeaf->p;
|
u8 *a = pIter->pLeaf->p;
|
||||||
int iRowidOffset = 0;
|
int iRowidOffset = 0;
|
||||||
|
|
||||||
|
if( n>pIter->iEndofDoclist ){
|
||||||
|
n = pIter->iEndofDoclist;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT_SZLEAF_OK(pIter->pLeaf);
|
ASSERT_SZLEAF_OK(pIter->pLeaf);
|
||||||
while( 1 ){
|
while( 1 ){
|
||||||
i64 iDelta = 0;
|
i64 iDelta = 0;
|
||||||
|
@ -1624,7 +1662,6 @@ static void fts5SegIterReverseInitPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
i += nPos;
|
i += nPos;
|
||||||
if( i>=n ) break;
|
if( i>=n ) break;
|
||||||
i += fts5GetVarint(&a[i], (u64*)&iDelta);
|
i += fts5GetVarint(&a[i], (u64*)&iDelta);
|
||||||
if( iDelta==0 ) break;
|
|
||||||
pIter->iRowid += iDelta;
|
pIter->iRowid += iDelta;
|
||||||
|
|
||||||
if( iRowidOffset>=pIter->nRowidOffset ){
|
if( iRowidOffset>=pIter->nRowidOffset ){
|
||||||
|
@ -1667,8 +1704,8 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
pIter->iLeafOffset = pIter->iTermLeafOffset;
|
pIter->iLeafOffset = pIter->iTermLeafOffset;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
int iRowidOff, dummy;
|
int iRowidOff;
|
||||||
fts5LeafHeader(pNew, &iRowidOff, &dummy);
|
iRowidOff = fts5LeafFirstRowidOff(pNew);
|
||||||
if( iRowidOff ){
|
if( iRowidOff ){
|
||||||
pIter->pLeaf = pNew;
|
pIter->pLeaf = pNew;
|
||||||
pIter->iLeafOffset = iRowidOff;
|
pIter->iLeafOffset = iRowidOff;
|
||||||
|
@ -1686,6 +1723,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pIter->pLeaf ){
|
if( pIter->pLeaf ){
|
||||||
|
pIter->iEndofDoclist = pIter->pLeaf->nn+1;
|
||||||
fts5SegIterReverseInitPage(p, pIter);
|
fts5SegIterReverseInitPage(p, pIter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1747,21 +1785,26 @@ static void fts5SegIterNext(
|
||||||
iOff = pIter->iLeafOffset + pIter->nPos;
|
iOff = pIter->iLeafOffset + pIter->nPos;
|
||||||
|
|
||||||
if( iOff<n ){
|
if( iOff<n ){
|
||||||
/* The next entry is on the current page */
|
/* The next entry is on the current page. */
|
||||||
u64 iDelta;
|
assert_nc( iOff<=pIter->iEndofDoclist );
|
||||||
iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta);
|
if( iOff>=pIter->iEndofDoclist ){
|
||||||
pIter->iLeafOffset = iOff;
|
|
||||||
if( iDelta==0 ){
|
|
||||||
bNewTerm = 1;
|
bNewTerm = 1;
|
||||||
if( iOff>=n ){
|
if( pIter->iTermLeafPgno==pIter->iLeafPgno ){
|
||||||
fts5SegIterNextPage(p, pIter);
|
pIter->iTermIdx++;
|
||||||
pIter->iLeafOffset = 4;
|
}else{
|
||||||
}else if( iOff!=fts5LeafFirstTermOff(pLeaf) ){
|
pIter->iTermIdx = 0;
|
||||||
pIter->iLeafOffset += fts5GetVarint32(&a[iOff], nKeep);
|
}
|
||||||
|
if( iOff!=fts5LeafFirstTermOff(pLeaf) ){
|
||||||
|
iOff += fts5GetVarint32(&a[iOff], nKeep);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
u64 iDelta;
|
||||||
|
iOff += sqlite3Fts5GetVarint(&a[iOff], &iDelta);
|
||||||
pIter->iRowid += iDelta;
|
pIter->iRowid += iDelta;
|
||||||
|
assert_nc( iDelta>0 );
|
||||||
}
|
}
|
||||||
|
pIter->iLeafOffset = iOff;
|
||||||
|
|
||||||
}else if( pIter->pSeg==0 ){
|
}else if( pIter->pSeg==0 ){
|
||||||
const u8 *pList = 0;
|
const u8 *pList = 0;
|
||||||
const char *zTerm = 0;
|
const char *zTerm = 0;
|
||||||
|
@ -1777,6 +1820,7 @@ static void fts5SegIterNext(
|
||||||
pIter->pLeaf->p = (u8*)pList;
|
pIter->pLeaf->p = (u8*)pList;
|
||||||
pIter->pLeaf->nn = nList;
|
pIter->pLeaf->nn = nList;
|
||||||
pIter->pLeaf->szLeaf = nList;
|
pIter->pLeaf->szLeaf = nList;
|
||||||
|
pIter->iEndofDoclist = nList+1;
|
||||||
sqlite3Fts5BufferSet(&p->rc, &pIter->term, strlen(zTerm), (u8*)zTerm);
|
sqlite3Fts5BufferSet(&p->rc, &pIter->term, strlen(zTerm), (u8*)zTerm);
|
||||||
pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
|
pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
|
||||||
}
|
}
|
||||||
|
@ -1796,6 +1840,7 @@ static void fts5SegIterNext(
|
||||||
iOff = fts5LeafFirstTermOff(pLeaf);
|
iOff = fts5LeafFirstTermOff(pLeaf);
|
||||||
pIter->iLeafOffset = iOff;
|
pIter->iLeafOffset = iOff;
|
||||||
bNewTerm = 1;
|
bNewTerm = 1;
|
||||||
|
pIter->iTermIdx = 0;
|
||||||
}
|
}
|
||||||
if( iOff>=pLeaf->szLeaf ){
|
if( iOff>=pLeaf->szLeaf ){
|
||||||
p->rc = FTS5_CORRUPT;
|
p->rc = FTS5_CORRUPT;
|
||||||
|
@ -1847,31 +1892,11 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
** byte of position-list content for the current rowid. Back it up
|
** byte of position-list content for the current rowid. Back it up
|
||||||
** so that it points to the start of the position-list size field. */
|
** so that it points to the start of the position-list size field. */
|
||||||
pIter->iLeafOffset -= sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel);
|
pIter->iLeafOffset -= sqlite3Fts5GetVarintLen(pIter->nPos*2+pIter->bDel);
|
||||||
iOff = pIter->iLeafOffset;
|
|
||||||
assert( iOff>=4 );
|
|
||||||
|
|
||||||
/* Search for a new term within the current leaf. If one can be found,
|
|
||||||
** then this page contains the largest rowid for the current term. */
|
|
||||||
while( iOff<pLeaf->szLeaf ){
|
|
||||||
int nPos;
|
|
||||||
i64 iDelta;
|
|
||||||
int bDummy;
|
|
||||||
|
|
||||||
/* Read the position-list size field */
|
|
||||||
iOff += fts5GetPoslistSize(&pLeaf->p[iOff], &nPos, &bDummy);
|
|
||||||
iOff += nPos;
|
|
||||||
if( iOff>=pLeaf->szLeaf ) break;
|
|
||||||
|
|
||||||
/* Rowid delta. Or, if 0x00, the end of doclist marker. */
|
|
||||||
nPos = fts5GetVarint(&pLeaf->p[iOff], (u64*)&iDelta);
|
|
||||||
if( iDelta==0 ) break;
|
|
||||||
iOff += nPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this condition is true then the largest rowid for the current
|
/* If this condition is true then the largest rowid for the current
|
||||||
** term may not be stored on the current page. So search forward to
|
** term may not be stored on the current page. So search forward to
|
||||||
** see where said rowid really is. */
|
** see where said rowid really is. */
|
||||||
if( iOff>=pLeaf->szLeaf ){
|
if( pIter->iEndofDoclist>=pLeaf->szLeaf ){
|
||||||
int pgno;
|
int pgno;
|
||||||
Fts5StructureSegment *pSeg = pIter->pSeg;
|
Fts5StructureSegment *pSeg = pIter->pSeg;
|
||||||
|
|
||||||
|
@ -1905,14 +1930,20 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
** first rowid on this page.
|
** first rowid on this page.
|
||||||
*/
|
*/
|
||||||
if( pLast ){
|
if( pLast ){
|
||||||
int dummy;
|
|
||||||
int iOff;
|
int iOff;
|
||||||
fts5DataRelease(pIter->pLeaf);
|
fts5DataRelease(pIter->pLeaf);
|
||||||
pIter->pLeaf = pLast;
|
pIter->pLeaf = pLast;
|
||||||
pIter->iLeafPgno = pgnoLast;
|
pIter->iLeafPgno = pgnoLast;
|
||||||
fts5LeafHeader(pLast, &iOff, &dummy);
|
iOff = fts5LeafFirstRowidOff(pLast);
|
||||||
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
|
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
|
||||||
pIter->iLeafOffset = iOff;
|
pIter->iLeafOffset = iOff;
|
||||||
|
|
||||||
|
if( fts5LeafIsTermless(pLast) ){
|
||||||
|
pIter->iEndofDoclist = pLast->nn+1;
|
||||||
|
}else{
|
||||||
|
pIter->iEndofDoclist = fts5LeafTermOff(pLast, 0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fts5SegIterReverseInitPage(p, pIter);
|
fts5SegIterReverseInitPage(p, pIter);
|
||||||
|
@ -1935,30 +1966,20 @@ static void fts5SegIterLoadDlidx(Fts5Index *p, Fts5SegIter *pIter){
|
||||||
/* Check if the current doclist ends on this page. If it does, return
|
/* Check if the current doclist ends on this page. If it does, return
|
||||||
** early without loading the doclist-index (as it belongs to a different
|
** early without loading the doclist-index (as it belongs to a different
|
||||||
** term. */
|
** term. */
|
||||||
if( pIter->iTermLeafPgno==pIter->iLeafPgno ){
|
if( pIter->iTermLeafPgno==pIter->iLeafPgno
|
||||||
int iOff = pIter->iLeafOffset + pIter->nPos;
|
&& pIter->iEndofDoclist<pLeaf->szLeaf
|
||||||
while( iOff<pLeaf->szLeaf ){
|
){
|
||||||
int bDummy;
|
return;
|
||||||
int nPos;
|
|
||||||
i64 iDelta;
|
|
||||||
|
|
||||||
/* iOff is currently the offset of the start of position list data */
|
|
||||||
iOff += fts5GetVarint(&pLeaf->p[iOff], (u64*)&iDelta);
|
|
||||||
if( iDelta==0 ) return;
|
|
||||||
assert_nc( iOff<pLeaf->szLeaf );
|
|
||||||
iOff += fts5GetPoslistSize(&pLeaf->p[iOff], &nPos, &bDummy);
|
|
||||||
iOff += nPos;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
|
pIter->pDlidx = fts5DlidxIterInit(p, bRev, iSeg, pIter->iTermLeafPgno);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define fts5IndexGetVarint32(a, iOff, nVal) { \
|
#define fts5IndexGetVarint32(a, iOff, nVal) { \
|
||||||
nVal = a[iOff++]; \
|
nVal = (a)[iOff++]; \
|
||||||
if( nVal & 0x80 ){ \
|
if( nVal & 0x80 ){ \
|
||||||
iOff--; \
|
iOff--; \
|
||||||
iOff += fts5GetVarint32(&a[iOff], nVal); \
|
iOff += fts5GetVarint32(&(a)[iOff], nVal); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2037,41 +2058,12 @@ static void fts5LeafSeek(
|
||||||
}
|
}
|
||||||
iOff += nNew;
|
iOff += nNew;
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Skip past the doclist. If the end of the page is reached, bail out. */
|
|
||||||
while( 1 ){
|
|
||||||
int nPos;
|
|
||||||
|
|
||||||
/* Skip past rowid delta */
|
|
||||||
fts5IndexSkipVarint(a, iOff);
|
|
||||||
|
|
||||||
/* Skip past position list */
|
|
||||||
fts5IndexGetVarint32(a, iOff, nPos);
|
|
||||||
iOff += (nPos >> 1);
|
|
||||||
if( iOff>=(n-1) ){
|
|
||||||
iOff = n;
|
|
||||||
goto search_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If this is the end of the doclist, break out of the loop */
|
|
||||||
if( a[iOff]==0x00 ){
|
|
||||||
iOff++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
iTerm++;
|
|
||||||
assert( iTerm<nPgTerm );
|
|
||||||
assert( iOff==fts5GetU16(&a[n + iTerm*2]) );
|
|
||||||
|
|
||||||
#else
|
|
||||||
iTerm++;
|
iTerm++;
|
||||||
if( iTerm>=nPgTerm ){
|
if( iTerm>=nPgTerm ){
|
||||||
iOff = n;
|
iOff = n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
iOff = fts5GetU16(&a[n + iTerm*2]);
|
iOff = fts5GetU16(&a[n + iTerm*2]);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read the nKeep field of the next term. */
|
/* Read the nKeep field of the next term. */
|
||||||
fts5IndexGetVarint32(a, iOff, nKeep);
|
fts5IndexGetVarint32(a, iOff, nKeep);
|
||||||
|
@ -2084,6 +2076,7 @@ static void fts5LeafSeek(
|
||||||
return;
|
return;
|
||||||
}else if( iOff>=n ){
|
}else if( iOff>=n ){
|
||||||
do {
|
do {
|
||||||
|
iTerm = 0;
|
||||||
fts5SegIterNextPage(p, pIter);
|
fts5SegIterNextPage(p, pIter);
|
||||||
if( pIter->pLeaf==0 ) return;
|
if( pIter->pLeaf==0 ) return;
|
||||||
a = pIter->pLeaf->p;
|
a = pIter->pLeaf->p;
|
||||||
|
@ -2101,6 +2094,8 @@ static void fts5LeafSeek(
|
||||||
}
|
}
|
||||||
|
|
||||||
search_success:
|
search_success:
|
||||||
|
pIter->iTermIdx = iTerm;
|
||||||
|
|
||||||
pIter->iLeafOffset = iOff + nNew;
|
pIter->iLeafOffset = iOff + nNew;
|
||||||
pIter->iTermLeafOffset = pIter->iLeafOffset;
|
pIter->iTermLeafOffset = pIter->iLeafOffset;
|
||||||
pIter->iTermLeafPgno = pIter->iLeafPgno;
|
pIter->iTermLeafPgno = pIter->iLeafPgno;
|
||||||
|
@ -2108,6 +2103,7 @@ static void fts5LeafSeek(
|
||||||
fts5BufferSet(&p->rc, &pIter->term, nKeep, pTerm);
|
fts5BufferSet(&p->rc, &pIter->term, nKeep, pTerm);
|
||||||
fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
|
fts5BufferAppendBlob(&p->rc, &pIter->term, nNew, &a[iOff]);
|
||||||
|
|
||||||
|
fts5SegIterLoadEod(p, pIter);
|
||||||
fts5SegIterLoadRowid(p, pIter);
|
fts5SegIterLoadRowid(p, pIter);
|
||||||
fts5SegIterLoadNPos(p, pIter);
|
fts5SegIterLoadNPos(p, pIter);
|
||||||
}
|
}
|
||||||
|
@ -2243,6 +2239,7 @@ static void fts5SegIterHashInit(
|
||||||
pLeaf->nn = pLeaf->szLeaf = nList;
|
pLeaf->nn = pLeaf->szLeaf = nList;
|
||||||
pIter->pLeaf = pLeaf;
|
pIter->pLeaf = pLeaf;
|
||||||
pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
|
pIter->iLeafOffset = fts5GetVarint(pLeaf->p, (u64*)&pIter->iRowid);
|
||||||
|
pIter->iEndofDoclist = pLeaf->nn+1;
|
||||||
|
|
||||||
if( flags & FTS5INDEX_QUERY_DESC ){
|
if( flags & FTS5INDEX_QUERY_DESC ){
|
||||||
pIter->flags |= FTS5_SEGITER_REVERSE;
|
pIter->flags |= FTS5_SEGITER_REVERSE;
|
||||||
|
@ -2770,6 +2767,7 @@ static void fts5MultiIterNew2(
|
||||||
if( pData->szLeaf>0 ){
|
if( pData->szLeaf>0 ){
|
||||||
pIter->pLeaf = pData;
|
pIter->pLeaf = pData;
|
||||||
pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid);
|
pIter->iLeafOffset = fts5GetVarint(pData->p, (u64*)&pIter->iRowid);
|
||||||
|
pIter->iEndofDoclist = pData->nn;
|
||||||
pNew->aFirst[1].iFirst = 1;
|
pNew->aFirst[1].iFirst = 1;
|
||||||
if( bDesc ){
|
if( bDesc ){
|
||||||
pNew->bRev = 1;
|
pNew->bRev = 1;
|
||||||
|
@ -3201,25 +3199,23 @@ static void fts5WriteAppendTerm(
|
||||||
Fts5PageWriter *pPage = &pWriter->writer;
|
Fts5PageWriter *pPage = &pWriter->writer;
|
||||||
Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
|
Fts5Buffer *pPgidx = &pWriter->writer.pgidx;
|
||||||
|
|
||||||
assert( pPage->buf.n==0 || pPage->buf.n>4 );
|
|
||||||
if( pPage->buf.n==0 ){
|
|
||||||
/* Zero the first term and first rowid fields */
|
|
||||||
static const u8 zero[] = { 0x00, 0x00, 0x00, 0x00 };
|
|
||||||
fts5BufferAppendBlob(&p->rc, &pPage->buf, 4, zero);
|
|
||||||
assert( pWriter->bFirstTermInPage );
|
|
||||||
}
|
|
||||||
if( p->rc ) return;
|
if( p->rc ) return;
|
||||||
|
assert( pPage->buf.n>=4 );
|
||||||
|
assert( pPage->buf.n>4 || pWriter->bFirstTermInPage );
|
||||||
|
|
||||||
|
/* If the current leaf page is full, flush it to disk. */
|
||||||
|
if( (pPage->buf.n + pPage->pgidx.n + nTerm + 2)>=p->pConfig->pgsz ){
|
||||||
|
if( pPage->buf.n>4 ){
|
||||||
|
fts5WriteFlushLeaf(p, pWriter);
|
||||||
|
}
|
||||||
|
fts5BufferGrow(&p->rc, &pPage->buf, nTerm+FTS5_DATA_PADDING);
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO1: Can this be consolidated with FlushOneHash version? */
|
/* TODO1: Updating pgidx here. */
|
||||||
fts5PutU16(&pPgidx->p[pPgidx->n], pPage->buf.n);
|
fts5PutU16(&pPgidx->p[pPgidx->n], pPage->buf.n);
|
||||||
pPgidx->n += 2;
|
pPgidx->n += 2;
|
||||||
|
|
||||||
if( pWriter->bFirstTermInPage ){
|
if( pWriter->bFirstTermInPage ){
|
||||||
/* Update the "first term" field of the page header. */
|
|
||||||
#if 0
|
|
||||||
assert( pPage->buf.p[2]==0 && pPage->buf.p[3]==0 );
|
|
||||||
fts5PutU16(&pPage->buf.p[2], pPage->buf.n);
|
|
||||||
#endif
|
|
||||||
nPrefix = 0;
|
nPrefix = 0;
|
||||||
if( pPage->pgno!=1 ){
|
if( pPage->pgno!=1 ){
|
||||||
/* This is the first term on a leaf that is not the leftmost leaf in
|
/* This is the first term on a leaf that is not the leftmost leaf in
|
||||||
|
@ -3261,11 +3257,6 @@ static void fts5WriteAppendTerm(
|
||||||
|
|
||||||
assert( p->rc || (pWriter->nDlidx>0 && pWriter->aDlidx[0].buf.n==0) );
|
assert( p->rc || (pWriter->nDlidx>0 && pWriter->aDlidx[0].buf.n==0) );
|
||||||
pWriter->aDlidx[0].pgno = pPage->pgno;
|
pWriter->aDlidx[0].pgno = pPage->pgno;
|
||||||
|
|
||||||
/* If the current leaf page is full, flush it to disk. */
|
|
||||||
if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){
|
|
||||||
fts5WriteFlushLeaf(p, pWriter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3280,6 +3271,10 @@ static void fts5WriteAppendRowid(
|
||||||
if( p->rc==SQLITE_OK ){
|
if( p->rc==SQLITE_OK ){
|
||||||
Fts5PageWriter *pPage = &pWriter->writer;
|
Fts5PageWriter *pPage = &pWriter->writer;
|
||||||
|
|
||||||
|
if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){
|
||||||
|
fts5WriteFlushLeaf(p, pWriter);
|
||||||
|
}
|
||||||
|
|
||||||
/* If this is to be the first rowid written to the page, set the
|
/* If this is to be the first rowid written to the page, set the
|
||||||
** rowid-pointer in the page-header. Also append a value to the dlidx
|
** rowid-pointer in the page-header. Also append a value to the dlidx
|
||||||
** buffer, in case a doclist-index is required. */
|
** buffer, in case a doclist-index is required. */
|
||||||
|
@ -3300,10 +3295,6 @@ static void fts5WriteAppendRowid(
|
||||||
pWriter->bFirstRowidInPage = 0;
|
pWriter->bFirstRowidInPage = 0;
|
||||||
|
|
||||||
fts5BufferAppendVarint(&p->rc, &pPage->buf, nPos);
|
fts5BufferAppendVarint(&p->rc, &pPage->buf, nPos);
|
||||||
|
|
||||||
if( (pPage->buf.n + pPage->pgidx.n)>=p->pConfig->pgsz ){
|
|
||||||
fts5WriteFlushLeaf(p, pWriter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3383,6 +3374,8 @@ static void fts5WriteInit(
|
||||||
Fts5SegWriter *pWriter,
|
Fts5SegWriter *pWriter,
|
||||||
int iSegid
|
int iSegid
|
||||||
){
|
){
|
||||||
|
const int nBuffer = p->pConfig->pgsz + FTS5_DATA_PADDING;
|
||||||
|
|
||||||
memset(pWriter, 0, sizeof(Fts5SegWriter));
|
memset(pWriter, 0, sizeof(Fts5SegWriter));
|
||||||
pWriter->iSegid = iSegid;
|
pWriter->iSegid = iSegid;
|
||||||
|
|
||||||
|
@ -3391,7 +3384,10 @@ static void fts5WriteInit(
|
||||||
pWriter->bFirstTermInPage = 1;
|
pWriter->bFirstTermInPage = 1;
|
||||||
pWriter->iBtPage = 1;
|
pWriter->iBtPage = 1;
|
||||||
|
|
||||||
fts5BufferGrow(&p->rc, &pWriter->writer.pgidx, p->pConfig->pgsz + 20);
|
/* Grow the two buffers to pgsz + padding bytes in size. */
|
||||||
|
fts5BufferGrow(&p->rc, &pWriter->writer.pgidx, nBuffer);
|
||||||
|
fts5BufferGrow(&p->rc, &pWriter->writer.buf, nBuffer);
|
||||||
|
|
||||||
if( p->pIdxWriter==0 ){
|
if( p->pIdxWriter==0 ){
|
||||||
Fts5Config *pConfig = p->pConfig;
|
Fts5Config *pConfig = p->pConfig;
|
||||||
fts5IndexPrepareStmt(p, &p->pIdxWriter, sqlite3_mprintf(
|
fts5IndexPrepareStmt(p, &p->pIdxWriter, sqlite3_mprintf(
|
||||||
|
@ -3401,6 +3397,13 @@ static void fts5WriteInit(
|
||||||
}
|
}
|
||||||
|
|
||||||
if( p->rc==SQLITE_OK ){
|
if( p->rc==SQLITE_OK ){
|
||||||
|
/* Initialize the 4-byte leaf-page header to 0x00. */
|
||||||
|
memset(pWriter->writer.buf.p, 0, 4);
|
||||||
|
pWriter->writer.buf.n = 4;
|
||||||
|
|
||||||
|
/* Bind the current output segment id to the index-writer. This is an
|
||||||
|
** optimization over binding the same value over and over as rows are
|
||||||
|
** inserted into %_idx by the current writer. */
|
||||||
sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid);
|
sqlite3_bind_int(p->pIdxWriter, 1, pWriter->iSegid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3414,38 +3417,39 @@ static void fts5WriteInit(
|
||||||
** This function appends a page-index to the buffer. The buffer is
|
** This function appends a page-index to the buffer. The buffer is
|
||||||
** guaranteed to be large enough to fit the page-index.
|
** guaranteed to be large enough to fit the page-index.
|
||||||
*/
|
*/
|
||||||
static void fts5MakePageidx(Fts5Index *p, Fts5Buffer *pBuf){
|
static void fts5MakePageidx(
|
||||||
|
Fts5Index *p, /* Fts index object to store any error in */
|
||||||
|
Fts5Data *pOld, /* Original page data */
|
||||||
|
int iOldidx, /* Index of term in pOld pgidx */
|
||||||
|
Fts5Buffer *pBuf /* Buffer containing new page (no pgidx) */
|
||||||
|
){
|
||||||
if( p->rc==SQLITE_OK ){
|
if( p->rc==SQLITE_OK ){
|
||||||
u8 *a = pBuf->p;
|
int iOff;
|
||||||
int szLeaf = pBuf->n;
|
int iEnd;
|
||||||
int iOff = 4;
|
int nByte;
|
||||||
int nTerm;
|
int iEndOld; /* Byte after term iOldIdx on old page */
|
||||||
|
int iEndNew; /* Byte after term iOldIdx on new page */
|
||||||
|
int ii;
|
||||||
|
int nPgIdx = (pOld->nn - pOld->szLeaf) / 2;
|
||||||
|
|
||||||
fts5PutU16(&pBuf->p[pBuf->n], iOff);
|
/* Determine end of term on old page */
|
||||||
|
iEndOld = fts5LeafTermOff(pOld, iOldidx);
|
||||||
|
if( iOldidx>0 ){
|
||||||
|
iEndOld += fts5GetVarint32(&pOld->p[iEndOld], nByte);
|
||||||
|
}
|
||||||
|
iEndOld += fts5GetVarint32(&pOld->p[iEndOld], nByte);
|
||||||
|
iEndOld += nByte;
|
||||||
|
|
||||||
|
/* Determine end of term on new page */
|
||||||
|
iEndNew = 4 + fts5GetVarint32(&pBuf->p[4], nByte);
|
||||||
|
iEndNew += nByte;
|
||||||
|
|
||||||
|
fts5PutU16(&pBuf->p[pBuf->n], 4);
|
||||||
pBuf->n += 2;
|
pBuf->n += 2;
|
||||||
fts5IndexGetVarint32(a, iOff, nTerm);
|
for(ii=iOldidx+1; ii<nPgIdx; ii++){
|
||||||
iOff += nTerm;
|
int iVal = fts5LeafTermOff(pOld, ii);
|
||||||
|
fts5PutU16(&pBuf->p[pBuf->n], iVal + (iEndNew - iEndOld));
|
||||||
while( iOff<szLeaf ){
|
pBuf->n += 2;
|
||||||
/* Skip the rowid delta rowid delta. */
|
|
||||||
fts5IndexSkipVarint(a, iOff);
|
|
||||||
if( iOff>=szLeaf ) break;
|
|
||||||
|
|
||||||
/* Skip past position list */
|
|
||||||
fts5IndexGetVarint32(a, iOff, nTerm);
|
|
||||||
iOff += (nTerm >> 1);
|
|
||||||
|
|
||||||
if( iOff>=(szLeaf-2) ) break;
|
|
||||||
|
|
||||||
/* If this is the end of the doclist, break out of the loop */
|
|
||||||
if( a[iOff]==0x00 ){
|
|
||||||
iOff++;
|
|
||||||
fts5PutU16(&pBuf->p[pBuf->n], iOff);
|
|
||||||
pBuf->n += 2;
|
|
||||||
fts5IndexGetVarint32(a, iOff, nTerm);
|
|
||||||
fts5IndexGetVarint32(a, iOff, nTerm);
|
|
||||||
iOff += nTerm;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3491,7 +3495,7 @@ static void fts5TrimSegments(Fts5Index *p, Fts5IndexIter *pIter){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the new page-index array */
|
/* Set up the new page-index array */
|
||||||
fts5MakePageidx(p, &buf);
|
fts5MakePageidx(p, pData, pSeg->iTermIdx, &buf);
|
||||||
|
|
||||||
fts5DataRelease(pData);
|
fts5DataRelease(pData);
|
||||||
pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
|
pSeg->pSeg->pgnoFirst = pSeg->iTermLeafPgno;
|
||||||
|
@ -3595,8 +3599,9 @@ static void fts5IndexMergeLevel(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a new term. Append a term to the output segment. */
|
/* This is a new term. Append a term to the output segment. */
|
||||||
|
/* TODO2: Doclist 0x00 term */
|
||||||
if( bRequireDoclistTerm ){
|
if( bRequireDoclistTerm ){
|
||||||
fts5WriteAppendZerobyte(p, &writer);
|
/* fts5WriteAppendZerobyte(p, &writer); */
|
||||||
}
|
}
|
||||||
fts5WriteAppendTerm(p, &writer, nTerm, pTerm);
|
fts5WriteAppendTerm(p, &writer, nTerm, pTerm);
|
||||||
fts5BufferSet(&p->rc, &term, nTerm, pTerm);
|
fts5BufferSet(&p->rc, &term, nTerm, pTerm);
|
||||||
|
@ -3739,6 +3744,7 @@ static void fts5IndexCrisismerge(
|
||||||
assert( p->rc!=SQLITE_OK || pStruct->nLevel>0 );
|
assert( p->rc!=SQLITE_OK || pStruct->nLevel>0 );
|
||||||
while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){
|
while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){
|
||||||
fts5IndexMergeLevel(p, &pStruct, iLvl, 0);
|
fts5IndexMergeLevel(p, &pStruct, iLvl, 0);
|
||||||
|
assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) );
|
||||||
fts5StructurePromote(p, iLvl+1, pStruct);
|
fts5StructurePromote(p, iLvl+1, pStruct);
|
||||||
iLvl++;
|
iLvl++;
|
||||||
}
|
}
|
||||||
|
@ -3766,10 +3772,12 @@ static int fts5PoslistPrefix(const u8 *aBuf, int nMax){
|
||||||
int ret;
|
int ret;
|
||||||
u32 dummy;
|
u32 dummy;
|
||||||
ret = fts5GetVarint32(aBuf, dummy);
|
ret = fts5GetVarint32(aBuf, dummy);
|
||||||
while( 1 ){
|
if( ret<nMax ){
|
||||||
int i = fts5GetVarint32(&aBuf[ret], dummy);
|
while( 1 ){
|
||||||
if( (ret + i) > nMax ) break;
|
int i = fts5GetVarint32(&aBuf[ret], dummy);
|
||||||
ret += i;
|
if( (ret + i) > nMax ) break;
|
||||||
|
ret += i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -3810,72 +3818,32 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||||
Fts5SegWriter writer;
|
Fts5SegWriter writer;
|
||||||
fts5WriteInit(p, &writer, iSegid);
|
fts5WriteInit(p, &writer, iSegid);
|
||||||
|
|
||||||
/* Pre-allocate the buffer used to assemble leaf pages to the target
|
|
||||||
** page size. */
|
|
||||||
assert( pgsz>0 );
|
|
||||||
pBuf = &writer.writer.buf;
|
pBuf = &writer.writer.buf;
|
||||||
pPgidx = &writer.writer.pgidx;
|
pPgidx = &writer.writer.pgidx;
|
||||||
fts5BufferGrow(&p->rc, pBuf, pgsz + 20);
|
|
||||||
|
/* fts5WriteInit() should have initialized the buffers to (most likely)
|
||||||
|
** the maximum space required. */
|
||||||
|
assert( p->rc || pBuf->nSpace>=(pgsz + FTS5_DATA_PADDING) );
|
||||||
|
assert( p->rc || pPgidx->nSpace>=(pgsz + FTS5_DATA_PADDING) );
|
||||||
|
|
||||||
/* Begin scanning through hash table entries. This loop runs once for each
|
/* Begin scanning through hash table entries. This loop runs once for each
|
||||||
** term/doclist currently stored within the hash table. */
|
** term/doclist currently stored within the hash table. */
|
||||||
if( p->rc==SQLITE_OK ){
|
if( p->rc==SQLITE_OK ){
|
||||||
memset(pBuf->p, 0, 4);
|
|
||||||
pBuf->n = 4;
|
|
||||||
p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0);
|
p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0);
|
||||||
}
|
}
|
||||||
while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){
|
while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){
|
||||||
const char *zTerm; /* Buffer containing term */
|
const char *zTerm; /* Buffer containing term */
|
||||||
int nTerm; /* Size of zTerm in bytes */
|
|
||||||
const u8 *pDoclist; /* Pointer to doclist for this term */
|
const u8 *pDoclist; /* Pointer to doclist for this term */
|
||||||
int nDoclist; /* Size of doclist in bytes */
|
int nDoclist; /* Size of doclist in bytes */
|
||||||
int nSuffix; /* Size of term suffix */
|
int nSuffix; /* Size of term suffix */
|
||||||
|
|
||||||
|
/* Write the term for this entry to disk. */
|
||||||
sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
|
sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist);
|
||||||
nTerm = strlen(zTerm);
|
fts5WriteAppendTerm(p, &writer, strlen(zTerm), zTerm);
|
||||||
|
|
||||||
/* Decide if the term will fit on the current leaf. If it will not,
|
if( writer.bFirstRowidInPage==0
|
||||||
** flush the leaf to disk here.
|
&& pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1)
|
||||||
** TODO1: Is this calculation still correct? */
|
){
|
||||||
if( pBuf->n>4 && (pBuf->n + nTerm + 2 + pPgidx->n + 2) > pgsz ){
|
|
||||||
fts5WriteFlushLeaf(p, &writer);
|
|
||||||
if( (nTerm + 32) > pBuf->nSpace ){
|
|
||||||
fts5BufferGrow(&p->rc, pBuf, nTerm + 32 - pBuf->n);
|
|
||||||
if( p->rc ) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write the term to the leaf. And if it is the first on the leaf, and
|
|
||||||
** the leaf is not page number 1, push it up into the b-tree hierarchy
|
|
||||||
** as well. */
|
|
||||||
|
|
||||||
/* TODO1: Writing pgidx here! */
|
|
||||||
fts5PutU16(&pPgidx->p[pPgidx->n], pBuf->n);
|
|
||||||
pPgidx->n += 2;
|
|
||||||
if( writer.bFirstTermInPage==0 ){
|
|
||||||
int nPre = fts5PrefixCompress(nTerm, zPrev, nTerm, (const u8*)zTerm);
|
|
||||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], nPre);
|
|
||||||
nSuffix = nTerm - nPre;
|
|
||||||
}else{
|
|
||||||
writer.bFirstTermInPage = 0;
|
|
||||||
if( writer.writer.pgno!=1 ){
|
|
||||||
int nPre = fts5PrefixCompress(nTerm, zPrev, nTerm, (const u8*)zTerm);
|
|
||||||
fts5WriteBtreeTerm(p, &writer, nPre+1, (const u8*)zTerm);
|
|
||||||
pBuf = &writer.writer.buf;
|
|
||||||
assert( nPre<nTerm );
|
|
||||||
}
|
|
||||||
nSuffix = nTerm;
|
|
||||||
}
|
|
||||||
pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], nSuffix);
|
|
||||||
fts5BufferSafeAppendBlob(pBuf, (const u8*)&zTerm[nTerm-nSuffix], nSuffix);
|
|
||||||
|
|
||||||
/* We just wrote a term into page writer.aWriter[0].pgno. If a
|
|
||||||
** doclist-index is to be generated for this doclist, it will be
|
|
||||||
** associated with this page. */
|
|
||||||
assert( writer.nDlidx>0 && writer.aDlidx[0].buf.n==0 );
|
|
||||||
writer.aDlidx[0].pgno = writer.writer.pgno;
|
|
||||||
|
|
||||||
if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){
|
|
||||||
/* The entire doclist will fit on the current leaf. */
|
/* The entire doclist will fit on the current leaf. */
|
||||||
fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
|
fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
|
||||||
}else{
|
}else{
|
||||||
|
@ -3883,7 +3851,7 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||||
i64 iDelta = 0;
|
i64 iDelta = 0;
|
||||||
int iOff = 0;
|
int iOff = 0;
|
||||||
|
|
||||||
writer.bFirstRowidInPage = 0;
|
/* writer.bFirstRowidInPage = 0; */
|
||||||
|
|
||||||
/* The entire doclist will not fit on this leaf. The following
|
/* The entire doclist will not fit on this leaf. The following
|
||||||
** loop iterates through the poslists that make up the current
|
** loop iterates through the poslists that make up the current
|
||||||
|
@ -3938,7 +3906,8 @@ static void fts5FlushOneHash(Fts5Index *p){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pBuf->p[pBuf->n++] = '\0';
|
/* TODO2: Doclist terminator written here. */
|
||||||
|
/* pBuf->p[pBuf->n++] = '\0'; */
|
||||||
assert( pBuf->n<=pBuf->nSpace );
|
assert( pBuf->n<=pBuf->nSpace );
|
||||||
zPrev = (const u8*)zTerm;
|
zPrev = (const u8*)zTerm;
|
||||||
sqlite3Fts5HashScanNext(pHash);
|
sqlite3Fts5HashScanNext(pHash);
|
||||||
|
@ -4527,7 +4496,7 @@ int sqlite3Fts5IndexQuery(
|
||||||
** evaluate the prefix query using the main FTS index. This is used
|
** evaluate the prefix query using the main FTS index. This is used
|
||||||
** for internal sanity checking by the integrity-check in debug
|
** for internal sanity checking by the integrity-check in debug
|
||||||
** mode only. */
|
** mode only. */
|
||||||
if( flags & FTS5INDEX_QUERY_TEST_NOIDX ){
|
if( pConfig->bPrefixIndex==0 || (flags & FTS5INDEX_QUERY_TEST_NOIDX) ){
|
||||||
assert( flags & FTS5INDEX_QUERY_PREFIX );
|
assert( flags & FTS5INDEX_QUERY_PREFIX );
|
||||||
iIdx = 1+pConfig->nPrefix;
|
iIdx = 1+pConfig->nPrefix;
|
||||||
}else
|
}else
|
||||||
|
@ -4971,6 +4940,48 @@ static void fts5IndexIntegrityCheckEmpty(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fts5IntegrityCheckPgidx(Fts5Index *p, Fts5Data *pLeaf){
|
||||||
|
int nPg = (pLeaf->nn - pLeaf->szLeaf) / 2;
|
||||||
|
int ii;
|
||||||
|
Fts5Buffer buf1 = {0,0,0};
|
||||||
|
Fts5Buffer buf2 = {0,0,0};
|
||||||
|
|
||||||
|
for(ii=0; p->rc==SQLITE_OK && ii<nPg; ii++){
|
||||||
|
int res;
|
||||||
|
int iOff = fts5LeafTermOff(pLeaf, ii);
|
||||||
|
if( iOff>=pLeaf->szLeaf ){
|
||||||
|
p->rc = FTS5_CORRUPT;
|
||||||
|
}else if( ii==0 ){
|
||||||
|
int nByte;
|
||||||
|
iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
|
||||||
|
if( (iOff+nByte)>pLeaf->szLeaf ){
|
||||||
|
p->rc = FTS5_CORRUPT;
|
||||||
|
}else{
|
||||||
|
fts5BufferSet(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
int nKeep, nByte;
|
||||||
|
iOff += fts5GetVarint32(&pLeaf->p[iOff], nKeep);
|
||||||
|
iOff += fts5GetVarint32(&pLeaf->p[iOff], nByte);
|
||||||
|
if( nKeep>buf1.n || (iOff+nByte)>pLeaf->szLeaf ){
|
||||||
|
p->rc = FTS5_CORRUPT;
|
||||||
|
}else{
|
||||||
|
buf1.n = nKeep;
|
||||||
|
fts5BufferAppendBlob(&p->rc, &buf1, nByte, &pLeaf->p[iOff]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( p->rc==SQLITE_OK ){
|
||||||
|
res = fts5BufferCompare(&buf1, &buf2);
|
||||||
|
if( res<=0 ) p->rc = FTS5_CORRUPT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fts5BufferSet(&p->rc, &buf2, buf1.n, buf1.p);
|
||||||
|
}
|
||||||
|
|
||||||
|
fts5BufferFree(&buf1);
|
||||||
|
fts5BufferFree(&buf2);
|
||||||
|
}
|
||||||
|
|
||||||
static void fts5IndexIntegrityCheckSegment(
|
static void fts5IndexIntegrityCheckSegment(
|
||||||
Fts5Index *p, /* FTS5 backend object */
|
Fts5Index *p, /* FTS5 backend object */
|
||||||
Fts5StructureSegment *pSeg /* Segment to check internal consistency */
|
Fts5StructureSegment *pSeg /* Segment to check internal consistency */
|
||||||
|
@ -5027,6 +5038,8 @@ static void fts5IndexIntegrityCheckSegment(
|
||||||
if( res==0 ) res = nTerm - nIdxTerm;
|
if( res==0 ) res = nTerm - nIdxTerm;
|
||||||
if( res<0 ) p->rc = FTS5_CORRUPT;
|
if( res<0 ) p->rc = FTS5_CORRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fts5IntegrityCheckPgidx(p, pLeaf);
|
||||||
}
|
}
|
||||||
fts5DataRelease(pLeaf);
|
fts5DataRelease(pLeaf);
|
||||||
if( p->rc ) break;
|
if( p->rc ) break;
|
||||||
|
@ -5418,51 +5431,56 @@ static void fts5DecodeFunction(
|
||||||
int szLeaf = 0;
|
int szLeaf = 0;
|
||||||
int iRowidOff = 0;
|
int iRowidOff = 0;
|
||||||
int iOff;
|
int iOff;
|
||||||
int nKeep = 0;
|
int nPgTerm = 0;
|
||||||
|
int nDoclist;
|
||||||
|
int i;
|
||||||
|
|
||||||
memset(&term, 0, sizeof(Fts5Buffer));
|
memset(&term, 0, sizeof(Fts5Buffer));
|
||||||
|
|
||||||
if( n>=4 ){
|
if( n<4 ){
|
||||||
iRowidOff = fts5GetU16(&a[0]);
|
|
||||||
szLeaf = fts5GetU16(&a[2]);
|
|
||||||
if( szLeaf<n ){
|
|
||||||
iTermOff = fts5GetU16(&a[szLeaf]);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
sqlite3Fts5BufferSet(&rc, &s, 8, (const u8*)"corrupt");
|
sqlite3Fts5BufferSet(&rc, &s, 8, (const u8*)"corrupt");
|
||||||
goto decode_out;
|
goto decode_out;
|
||||||
|
}else{
|
||||||
|
iRowidOff = fts5GetU16(&a[0]);
|
||||||
|
szLeaf = fts5GetU16(&a[2]);
|
||||||
|
nPgTerm = (n - szLeaf) / 2;
|
||||||
|
if( nPgTerm ){
|
||||||
|
iTermOff = fts5GetU16(&a[szLeaf]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( iRowidOff ){
|
/* Decode the position list tail at the start of the page */
|
||||||
|
if( iRowidOff!=0 ){
|
||||||
iOff = iRowidOff;
|
iOff = iRowidOff;
|
||||||
}else if( iTermOff ){
|
}else if( iTermOff!=0 ){
|
||||||
iOff = iTermOff;
|
iOff = iTermOff;
|
||||||
}else{
|
}else{
|
||||||
iOff = szLeaf;
|
iOff = szLeaf;
|
||||||
}
|
}
|
||||||
fts5DecodePoslist(&rc, &s, &a[4], iOff-4);
|
fts5DecodePoslist(&rc, &s, &a[4], iOff-4);
|
||||||
|
|
||||||
assert( iRowidOff==0 || iOff==iRowidOff );
|
/* Decode any more doclist data that appears on the page before the
|
||||||
if( iRowidOff ){
|
** first term. */
|
||||||
iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], szLeaf-iOff);
|
nDoclist = (iTermOff ? iTermOff : szLeaf) - iOff;
|
||||||
}
|
fts5DecodeDoclist(&rc, &s, &a[iOff], nDoclist);
|
||||||
|
|
||||||
assert( iTermOff==0 || iOff==iTermOff );
|
for(i=0; i<nPgTerm; i++){
|
||||||
while( iOff<szLeaf ){
|
|
||||||
int nByte;
|
int nByte;
|
||||||
|
int iEnd = (i+1)<nPgTerm ? fts5GetU16(&a[szLeaf+i*2+2]) : szLeaf;
|
||||||
|
iOff = fts5GetU16(&a[szLeaf + i*2]);
|
||||||
|
if( i>0 ){
|
||||||
|
iOff += fts5GetVarint32(&a[iOff], nByte);
|
||||||
|
term.n = nByte;
|
||||||
|
}
|
||||||
iOff += fts5GetVarint32(&a[iOff], nByte);
|
iOff += fts5GetVarint32(&a[iOff], nByte);
|
||||||
term.n= nKeep;
|
|
||||||
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
|
fts5BufferAppendBlob(&rc, &term, nByte, &a[iOff]);
|
||||||
iOff += nByte;
|
iOff += nByte;
|
||||||
|
|
||||||
sqlite3Fts5BufferAppendPrintf(
|
sqlite3Fts5BufferAppendPrintf(
|
||||||
&rc, &s, " term=%.*s", term.n, (const char*)term.p
|
&rc, &s, " term=%.*s", term.n, (const char*)term.p
|
||||||
);
|
);
|
||||||
iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], szLeaf-iOff);
|
iOff += fts5DecodeDoclist(&rc, &s, &a[iOff], iEnd-iOff);
|
||||||
if( iOff<szLeaf ){
|
|
||||||
iOff += fts5GetVarint32(&a[iOff], nKeep);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fts5BufferFree(&term);
|
fts5BufferFree(&term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1317,6 +1317,10 @@ static int fts5SpecialInsert(
|
||||||
rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
|
rc = sqlite3Fts5StorageMerge(pTab->pStorage, nMerge);
|
||||||
}else if( 0==sqlite3_stricmp("integrity-check", z) ){
|
}else if( 0==sqlite3_stricmp("integrity-check", z) ){
|
||||||
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
|
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage);
|
||||||
|
#ifdef SQLITE_TEST
|
||||||
|
}else if( 0==sqlite3_stricmp("prefix-index", z) ){
|
||||||
|
pConfig->bPrefixIndex = sqlite3_value_int(pVal);
|
||||||
|
#endif
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
|
rc = sqlite3Fts5IndexLoadConfig(pTab->pIndex);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
|
|
|
@ -203,11 +203,6 @@ for {set i 1} {$i <= 10} {incr i} {
|
||||||
if {[set_test_counter errors]} break
|
if {[set_test_counter errors]} break
|
||||||
}
|
}
|
||||||
|
|
||||||
#db eval { SELECT fts5_decode(rowid, block) as x FROM t1_data } { puts $x }
|
|
||||||
#puts [db eval {SELECT rowid FROM t1 WHERE t1 MATCH 'aaa' ORDER BY rowid ASC}]
|
|
||||||
#puts [db eval {SELECT rowid FROM t1 WHERE t1 MATCH 'aaa' ORDER BY rowid DESC}]
|
|
||||||
#exit
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
reset_db
|
reset_db
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||||
set testprefix fts5aa
|
set testprefix fts5simple
|
||||||
|
|
||||||
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
|
||||||
ifcapable !fts5 {
|
ifcapable !fts5 {
|
||||||
|
@ -50,7 +50,6 @@ do_execsql_test 2.1 {
|
||||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||||
} {}
|
} {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
@ -63,12 +62,58 @@ do_execsql_test 3.0 {
|
||||||
SELECT * FROM t1 WHERE t1 MATCH 'o*';
|
SELECT * FROM t1 WHERE t1 MATCH 'o*';
|
||||||
} {one}
|
} {one}
|
||||||
|
|
||||||
breakpoint
|
|
||||||
do_execsql_test 3.1 {
|
do_execsql_test 3.1 {
|
||||||
INSERT INTO t1(t1) VALUES('integrity-check');
|
INSERT INTO t1(t1) VALUES('integrity-check');
|
||||||
} {}
|
} {}
|
||||||
|
|
||||||
# db eval { SELECT fts5_decode(rowid, block) as x FROM t1_data } { puts $x }
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 4.1 {
|
||||||
|
CREATE VIRTUAL TABLE t11 USING fts5(content);
|
||||||
|
INSERT INTO t11(t11, rank) VALUES('pgsz', 32);
|
||||||
|
INSERT INTO t11 VALUES('another');
|
||||||
|
INSERT INTO t11 VALUES('string');
|
||||||
|
INSERT INTO t11 VALUES('of');
|
||||||
|
INSERT INTO t11 VALUES('text');
|
||||||
|
}
|
||||||
|
do_test 4.2 {
|
||||||
|
execsql { INSERT INTO t11(t11) VALUES('optimize') }
|
||||||
|
} {}
|
||||||
|
do_execsql_test 4.3 {
|
||||||
|
INSERT INTO t11(t11) VALUES('integrity-check');
|
||||||
|
} {}
|
||||||
|
|
||||||
|
#db eval { SELECT fts5_decode(rowid, block) as x FROM t11_data } { puts $x }
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
set doc [string repeat "x y " 5]
|
||||||
|
do_execsql_test 5.1 {
|
||||||
|
CREATE VIRTUAL TABLE yy USING fts5(content);
|
||||||
|
INSERT INTO yy(yy, rank) VALUES('pgsz', 32);
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO yy VALUES($doc);
|
||||||
|
INSERT INTO yy VALUES($doc);
|
||||||
|
INSERT INTO yy VALUES($doc);
|
||||||
|
INSERT INTO yy VALUES($doc);
|
||||||
|
INSERT INTO yy VALUES($doc);
|
||||||
|
INSERT INTO yy VALUES($doc);
|
||||||
|
INSERT INTO yy VALUES($doc);
|
||||||
|
INSERT INTO yy VALUES($doc);
|
||||||
|
COMMIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 5.2 {
|
||||||
|
SELECT rowid FROM yy WHERE yy MATCH 'y' ORDER BY rowid ASC
|
||||||
|
} {1 2 3 4 5 6 7 8}
|
||||||
|
|
||||||
|
do_execsql_test 5.3 {
|
||||||
|
SELECT rowid FROM yy WHERE yy MATCH 'y' ORDER BY rowid DESC
|
||||||
|
} {8 7 6 5 4 3 2 1}
|
||||||
|
|
||||||
|
#db eval { SELECT fts5_decode(rowid, block) as x FROM yy_data } { puts $x }
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|
4
main.mk
4
main.mk
|
@ -332,7 +332,9 @@ TESTSRC += \
|
||||||
$(TOP)/ext/misc/vfslog.c \
|
$(TOP)/ext/misc/vfslog.c \
|
||||||
$(TOP)/ext/fts5/fts5_tcl.c \
|
$(TOP)/ext/fts5/fts5_tcl.c \
|
||||||
$(TOP)/ext/fts5/fts5_test_mi.c \
|
$(TOP)/ext/fts5/fts5_test_mi.c \
|
||||||
fts5.c
|
$(FTS5_SRC)
|
||||||
|
|
||||||
|
# fts5.c
|
||||||
|
|
||||||
|
|
||||||
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
|
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
|
||||||
|
|
26
manifest
26
manifest
|
@ -1,5 +1,5 @@
|
||||||
C Use\smacros\sto\smake\sthe\scode\sin\sfts5_index.c\seasier\sto\sread.
|
C Remove\sthe\s0x00\sterminators\sfrom\sthe\send\sof\sdoclists\sstored\son\sdisk.
|
||||||
D 2015-09-07T08:14:30.857
|
D 2015-09-08T19:55:26.385
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in f85066ce844a28b671aaeeff320921cd0ce36239
|
F Makefile.in f85066ce844a28b671aaeeff320921cd0ce36239
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
|
@ -106,14 +106,14 @@ F ext/fts3/unicode/mkunicode.tcl 95cf7ec186e48d4985e433ff8a1c89090a774252
|
||||||
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
||||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||||
F ext/fts5/fts5.h f04659e0df5af83731b102189a32280f74f4a6bc
|
F ext/fts5/fts5.h f04659e0df5af83731b102189a32280f74f4a6bc
|
||||||
F ext/fts5/fts5Int.h f65d41f66accad0a289d6bd66b13c07d2932f9be
|
F ext/fts5/fts5Int.h 7e6002582133cb795a21468732cf7c35027a28e4
|
||||||
F ext/fts5/fts5_aux.c 7a307760a9c57c750d043188ec0bad59f5b5ec7e
|
F ext/fts5/fts5_aux.c 7a307760a9c57c750d043188ec0bad59f5b5ec7e
|
||||||
F ext/fts5/fts5_buffer.c 80f9ba4431848cb857e3d2158f5280093dcd8015
|
F ext/fts5/fts5_buffer.c 64dcaf36a3ebda9e84b7c3b8788887ec325e12a4
|
||||||
F ext/fts5/fts5_config.c 80b61fd2c6844b64a3e72a64572d50a812da9384
|
F ext/fts5/fts5_config.c 57ee5fe71578cb494574fc0e6e51acb9a22a8695
|
||||||
F ext/fts5/fts5_expr.c 1c24e1a2ffb286bfe37e537a43b7fadabfe993d4
|
F ext/fts5/fts5_expr.c 1c24e1a2ffb286bfe37e537a43b7fadabfe993d4
|
||||||
F ext/fts5/fts5_hash.c 4bf4b99708848357b8a2b5819e509eb6d3df9246
|
F ext/fts5/fts5_hash.c 4bf4b99708848357b8a2b5819e509eb6d3df9246
|
||||||
F ext/fts5/fts5_index.c 213e5aea27100a2ebb7a576d6574bcc28c594520
|
F ext/fts5/fts5_index.c 677c859b2064e00903a9ad847a1cfca8d36ce595
|
||||||
F ext/fts5/fts5_main.c e9d0892424bb7f0a8b58613d4ff75cb650cf286e
|
F ext/fts5/fts5_main.c 3ec19f23693e034028afb9b4fa7c800dc3eda5ab
|
||||||
F ext/fts5/fts5_storage.c 120f7b143688b5b7710dacbd48cff211609b8059
|
F ext/fts5/fts5_storage.c 120f7b143688b5b7710dacbd48cff211609b8059
|
||||||
F ext/fts5/fts5_tcl.c 6da58d6e8f42a93c4486b5ba9b187a7f995dee37
|
F ext/fts5/fts5_tcl.c 6da58d6e8f42a93c4486b5ba9b187a7f995dee37
|
||||||
F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
|
F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
|
||||||
|
@ -124,7 +124,7 @@ F ext/fts5/fts5_vocab.c 4622e0b7d84a488a1585aaa56eb214ee67a988bc
|
||||||
F ext/fts5/fts5parse.y 833db1101b78c0c47686ab1b84918e38c36e9452
|
F ext/fts5/fts5parse.y 833db1101b78c0c47686ab1b84918e38c36e9452
|
||||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||||
F ext/fts5/test/fts5_common.tcl b6e6a40ef5d069c8e86ca4fbad491e1195485dbc
|
F ext/fts5/test/fts5_common.tcl b6e6a40ef5d069c8e86ca4fbad491e1195485dbc
|
||||||
F ext/fts5/test/fts5aa.test 1ac5a3bd88406183b00ea7cb4701bd58e5c3c7ff
|
F ext/fts5/test/fts5aa.test fb84c53e90dc4f9b4dc485858b53e70b67d6f064
|
||||||
F ext/fts5/test/fts5ab.test 6fe3a56731d15978afbb74ae51b355fc9310f2ad
|
F ext/fts5/test/fts5ab.test 6fe3a56731d15978afbb74ae51b355fc9310f2ad
|
||||||
F ext/fts5/test/fts5ac.test 9737992d08c56bfd4803e933744d2d764e23795c
|
F ext/fts5/test/fts5ac.test 9737992d08c56bfd4803e933744d2d764e23795c
|
||||||
F ext/fts5/test/fts5ad.test e3dfb150fce971b4fd832498c29f56924d451b63
|
F ext/fts5/test/fts5ad.test e3dfb150fce971b4fd832498c29f56924d451b63
|
||||||
|
@ -173,7 +173,7 @@ F ext/fts5/test/fts5rank.test 11dcebba31d822f7e99685b4ea2c2ae3ec0b16f1
|
||||||
F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b
|
F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b
|
||||||
F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
|
F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
|
||||||
F ext/fts5/test/fts5rowid.test 6f9833b23b176dc4aa15b7fc02afeb2b220fd460
|
F ext/fts5/test/fts5rowid.test 6f9833b23b176dc4aa15b7fc02afeb2b220fd460
|
||||||
F ext/fts5/test/fts5simple.test f520b360c40a5a61aabebead53e1e5f68683e5a3
|
F ext/fts5/test/fts5simple.test 40b76f77d56524a882473664c792bd4e8f2f2a0a
|
||||||
F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671
|
F ext/fts5/test/fts5synonym.test cf88c0a56d5ea9591e3939ef1f6e294f7f2d0671
|
||||||
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
|
F ext/fts5/test/fts5tokenizer.test ea4df698b35cc427ebf2ba22829d0e28386d8c89
|
||||||
F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841
|
F ext/fts5/test/fts5unicode.test fbef8d8a3b4b88470536cc57604a82ca52e51841
|
||||||
|
@ -261,7 +261,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||||
F main.mk 61821e43596648bfacce2d6283377bee35986131
|
F main.mk e67b73755e1f28c2d18d7953ca75c901c0be617b
|
||||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||||
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
|
F mkopcodeh.awk 0e7f04a8eb90f92259e47d80110e4e98d7ce337a
|
||||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||||
|
@ -1384,7 +1384,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P a1f4c3b543eed84e808f6b901a38179786fffe16
|
P 67ff5ae81357eb7fa28049bb724a22cb6f52e076
|
||||||
R d9f9c87817152716ded47406f74ba235
|
R 7e6723f8162dfa594f88012bb5737a33
|
||||||
U dan
|
U dan
|
||||||
Z 4c8df884c6ae97a50d0e8662a6ca4b0e
|
Z 0d6a020581263053b4291f892521bd3c
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
67ff5ae81357eb7fa28049bb724a22cb6f52e076
|
00d990061dec3661b0376bd167082942d5563bfe
|
Loading…
Reference in New Issue