Index: third_party/sqlite/src/ext/fts5/fts5_vocab.c |
diff --git a/third_party/sqlite/src/ext/fts5/fts5_vocab.c b/third_party/sqlite/src/ext/fts5/fts5_vocab.c |
index 860cfedb9bc4b6a0ff4c069e9a6f50cec2a73415..82c7dc90560b150049badb21948d6b346c8ca7fe 100644 |
--- a/third_party/sqlite/src/ext/fts5/fts5_vocab.c |
+++ b/third_party/sqlite/src/ext/fts5/fts5_vocab.c |
@@ -184,7 +184,7 @@ static int fts5VocabInitVtab( |
rc = fts5VocabTableType(zType, pzErr, &eType); |
if( rc==SQLITE_OK ){ |
- assert( eType>=0 && eType<sizeof(azSchema)/sizeof(azSchema[0]) ); |
+ assert( eType>=0 && eType<ArraySize(azSchema) ); |
rc = sqlite3_declare_vtab(db, azSchema[eType]); |
} |
@@ -237,7 +237,7 @@ static int fts5VocabCreateMethod( |
** Implementation of the xBestIndex method. |
*/ |
static int fts5VocabBestIndexMethod( |
- sqlite3_vtab *pVTab, |
+ sqlite3_vtab *pUnused, |
sqlite3_index_info *pInfo |
){ |
int i; |
@@ -247,6 +247,8 @@ static int fts5VocabBestIndexMethod( |
int idxNum = 0; |
int nArg = 0; |
+ UNUSED_PARAM(pUnused); |
+ |
for(i=0; i<pInfo->nConstraint; i++){ |
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; |
if( p->usable==0 ) continue; |
@@ -277,8 +279,19 @@ static int fts5VocabBestIndexMethod( |
} |
} |
- pInfo->idxNum = idxNum; |
+ /* This virtual table always delivers results in ascending order of |
+ ** the "term" column (column 0). So if the user has requested this |
+ ** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the |
+ ** sqlite3_index_info.orderByConsumed flag to tell the core the results |
+ ** are already in sorted order. */ |
+ if( pInfo->nOrderBy==1 |
+ && pInfo->aOrderBy[0].iColumn==0 |
+ && pInfo->aOrderBy[0].desc==0 |
+ ){ |
+ pInfo->orderByConsumed = 1; |
+ } |
+ pInfo->idxNum = idxNum; |
return SQLITE_OK; |
} |
@@ -379,7 +392,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ |
if( pTab->eType==FTS5_VOCAB_COL ){ |
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){ |
- if( pCsr->aCnt[pCsr->iCol] ) break; |
+ if( pCsr->aDoc[pCsr->iCol] ) break; |
} |
} |
@@ -407,29 +420,60 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ |
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW ); |
while( rc==SQLITE_OK ){ |
- i64 dummy; |
const u8 *pPos; int nPos; /* Position list */ |
i64 iPos = 0; /* 64-bit position read from poslist */ |
int iOff = 0; /* Current offset within position list */ |
- rc = sqlite3Fts5IterPoslist(pCsr->pIter, 0, &pPos, &nPos, &dummy); |
- if( rc==SQLITE_OK ){ |
- if( pTab->eType==FTS5_VOCAB_ROW ){ |
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
- pCsr->aCnt[0]++; |
+ pPos = pCsr->pIter->pData; |
+ nPos = pCsr->pIter->nData; |
+ switch( pCsr->pConfig->eDetail ){ |
+ case FTS5_DETAIL_FULL: |
+ pPos = pCsr->pIter->pData; |
+ nPos = pCsr->pIter->nData; |
+ if( pTab->eType==FTS5_VOCAB_ROW ){ |
+ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
+ pCsr->aCnt[0]++; |
+ } |
+ pCsr->aDoc[0]++; |
+ }else{ |
+ int iCol = -1; |
+ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
+ int ii = FTS5_POS2COLUMN(iPos); |
+ pCsr->aCnt[ii]++; |
+ if( iCol!=ii ){ |
+ if( ii>=nCol ){ |
+ rc = FTS5_CORRUPT; |
+ break; |
+ } |
+ pCsr->aDoc[ii]++; |
+ iCol = ii; |
+ } |
+ } |
} |
- pCsr->aDoc[0]++; |
- }else{ |
- int iCol = -1; |
- while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){ |
- int ii = FTS5_POS2COLUMN(iPos); |
- pCsr->aCnt[ii]++; |
- if( iCol!=ii ){ |
- pCsr->aDoc[ii]++; |
- iCol = ii; |
+ break; |
+ |
+ case FTS5_DETAIL_COLUMNS: |
+ if( pTab->eType==FTS5_VOCAB_ROW ){ |
+ pCsr->aDoc[0]++; |
+ }else{ |
+ while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){ |
+ assert_nc( iPos>=0 && iPos<nCol ); |
+ if( iPos>=nCol ){ |
+ rc = FTS5_CORRUPT; |
+ break; |
+ } |
+ pCsr->aDoc[iPos]++; |
} |
} |
- } |
+ break; |
+ |
+ default: |
+ assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE ); |
+ pCsr->aDoc[0]++; |
+ break; |
+ } |
+ |
+ if( rc==SQLITE_OK ){ |
rc = sqlite3Fts5IterNextScan(pCsr->pIter); |
} |
@@ -444,8 +488,8 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ |
} |
} |
- if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){ |
- while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++; |
+ if( rc==SQLITE_OK && pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){ |
+ while( pCsr->aDoc[pCsr->iCol]==0 ) pCsr->iCol++; |
assert( pCsr->iCol<pCsr->pConfig->nCol ); |
} |
return rc; |
@@ -457,8 +501,8 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){ |
static int fts5VocabFilterMethod( |
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ |
int idxNum, /* Strategy index */ |
- const char *idxStr, /* Unused */ |
- int nVal, /* Number of elements in apVal */ |
+ const char *zUnused, /* Unused */ |
+ int nUnused, /* Number of elements in apVal */ |
sqlite3_value **apVal /* Arguments for the indexing scheme */ |
){ |
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; |
@@ -473,6 +517,8 @@ static int fts5VocabFilterMethod( |
sqlite3_value *pGe = 0; |
sqlite3_value *pLe = 0; |
+ UNUSED_PARAM2(zUnused, nUnused); |
+ |
fts5VocabResetCursor(pCsr); |
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++]; |
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++]; |
@@ -525,30 +571,36 @@ static int fts5VocabColumnMethod( |
int iCol /* Index of column to read value from */ |
){ |
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor; |
+ int eDetail = pCsr->pConfig->eDetail; |
+ int eType = ((Fts5VocabTable*)(pCursor->pVtab))->eType; |
+ i64 iVal = 0; |
if( iCol==0 ){ |
sqlite3_result_text( |
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT |
); |
- } |
- else if( ((Fts5VocabTable*)(pCursor->pVtab))->eType==FTS5_VOCAB_COL ){ |
+ }else if( eType==FTS5_VOCAB_COL ){ |
assert( iCol==1 || iCol==2 || iCol==3 ); |
if( iCol==1 ){ |
- const char *z = pCsr->pConfig->azCol[pCsr->iCol]; |
- sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); |
+ if( eDetail!=FTS5_DETAIL_NONE ){ |
+ const char *z = pCsr->pConfig->azCol[pCsr->iCol]; |
+ sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC); |
+ } |
}else if( iCol==2 ){ |
- sqlite3_result_int64(pCtx, pCsr->aDoc[pCsr->iCol]); |
+ iVal = pCsr->aDoc[pCsr->iCol]; |
}else{ |
- sqlite3_result_int64(pCtx, pCsr->aCnt[pCsr->iCol]); |
+ iVal = pCsr->aCnt[pCsr->iCol]; |
} |
}else{ |
assert( iCol==1 || iCol==2 ); |
if( iCol==1 ){ |
- sqlite3_result_int64(pCtx, pCsr->aDoc[0]); |
+ iVal = pCsr->aDoc[0]; |
}else{ |
- sqlite3_result_int64(pCtx, pCsr->aCnt[0]); |
+ iVal = pCsr->aCnt[0]; |
} |
} |
+ |
+ if( iVal>0 ) sqlite3_result_int64(pCtx, iVal); |
return SQLITE_OK; |
} |