mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Handle equality and range constraints on the "term" column of fts5vocab tables. Also have the same module report columns using names instead of indexes.
FossilOrigin-Name: 6020d96ab47a0bebe41f691a3f44fd55d8b2d2b7
This commit is contained in:
@ -475,7 +475,7 @@ int sqlite3Fts5GetTokenizer(
|
|||||||
char **pzErr
|
char **pzErr
|
||||||
);
|
);
|
||||||
|
|
||||||
Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, int*);
|
Fts5Index *sqlite3Fts5IndexFromCsrid(Fts5Global*, i64, Fts5Config **);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** End of interface to code in fts5.c.
|
** End of interface to code in fts5.c.
|
||||||
|
@ -4597,9 +4597,7 @@ int sqlite3Fts5IndexQuery(
|
|||||||
Fts5Buffer buf = {0, 0, 0};
|
Fts5Buffer buf = {0, 0, 0};
|
||||||
|
|
||||||
/* If the QUERY_SCAN flag is set, all other flags must be clear. */
|
/* If the QUERY_SCAN flag is set, all other flags must be clear. */
|
||||||
assert( (flags & FTS5INDEX_QUERY_SCAN)==0
|
assert( (flags & FTS5INDEX_QUERY_SCAN)==0 || flags==FTS5INDEX_QUERY_SCAN );
|
||||||
|| (flags & FTS5INDEX_QUERY_SCAN)==FTS5INDEX_QUERY_SCAN
|
|
||||||
);
|
|
||||||
|
|
||||||
if( sqlite3Fts5BufferGrow(&p->rc, &buf, nToken+1)==0 ){
|
if( sqlite3Fts5BufferGrow(&p->rc, &buf, nToken+1)==0 ){
|
||||||
memcpy(&buf.p[1], pToken, nToken);
|
memcpy(&buf.p[1], pToken, nToken);
|
||||||
|
@ -2021,20 +2021,20 @@ static void fts5ApiCallback(
|
|||||||
** Given cursor id iId, return a pointer to the corresponding Fts5Index
|
** Given cursor id iId, return a pointer to the corresponding Fts5Index
|
||||||
** object. Or NULL If the cursor id does not exist.
|
** object. Or NULL If the cursor id does not exist.
|
||||||
**
|
**
|
||||||
** If successful, set *pnCol to the number of indexed columns in the
|
** If successful, set *ppConfig to point to the associated config object
|
||||||
** table before returning.
|
** before returning.
|
||||||
*/
|
*/
|
||||||
Fts5Index *sqlite3Fts5IndexFromCsrid(
|
Fts5Index *sqlite3Fts5IndexFromCsrid(
|
||||||
Fts5Global *pGlobal,
|
Fts5Global *pGlobal, /* FTS5 global context for db handle */
|
||||||
i64 iCsrId,
|
i64 iCsrId, /* Id of cursor to find */
|
||||||
int *pnCol
|
Fts5Config **ppConfig /* OUT: Configuration object */
|
||||||
){
|
){
|
||||||
Fts5Cursor *pCsr;
|
Fts5Cursor *pCsr;
|
||||||
Fts5Table *pTab;
|
Fts5Table *pTab;
|
||||||
|
|
||||||
pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
|
pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
|
||||||
pTab = (Fts5Table*)pCsr->base.pVtab;
|
pTab = (Fts5Table*)pCsr->base.pVtab;
|
||||||
*pnCol = pTab->pConfig->nCol;
|
*ppConfig = pTab->pConfig;
|
||||||
|
|
||||||
return pTab->pIndex;
|
return pTab->pIndex;
|
||||||
}
|
}
|
||||||
|
@ -55,16 +55,18 @@ struct Fts5VocabCursor {
|
|||||||
int bEof; /* True if this cursor is at EOF */
|
int bEof; /* True if this cursor is at EOF */
|
||||||
Fts5IndexIter *pIter; /* Term/rowid iterator object */
|
Fts5IndexIter *pIter; /* Term/rowid iterator object */
|
||||||
|
|
||||||
|
int nLeTerm; /* Size of zLeTerm in bytes */
|
||||||
|
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
|
||||||
|
|
||||||
/* These are used by 'col' tables only */
|
/* These are used by 'col' tables only */
|
||||||
int nCol;
|
Fts5Config *pConfig; /* Fts5 table configuration */
|
||||||
int iCol;
|
int iCol;
|
||||||
i64 *aCnt;
|
i64 *aCnt;
|
||||||
i64 *aDoc;
|
i64 *aDoc;
|
||||||
|
|
||||||
/* Output values */
|
/* Output values used by 'row' and 'col' tables */
|
||||||
i64 rowid; /* This table's current rowid value */
|
i64 rowid; /* This table's current rowid value */
|
||||||
Fts5Buffer term; /* Current value of 'term' column */
|
Fts5Buffer term; /* Current value of 'term' column */
|
||||||
i64 aVal[3]; /* Up to three columns left of 'term' */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FTS5_VOCAB_COL 0
|
#define FTS5_VOCAB_COL 0
|
||||||
@ -73,6 +75,14 @@ struct Fts5VocabCursor {
|
|||||||
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
|
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
|
||||||
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
|
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
|
||||||
|
*/
|
||||||
|
#define FTS5_VOCAB_TERM_EQ 0x01
|
||||||
|
#define FTS5_VOCAB_TERM_GE 0x02
|
||||||
|
#define FTS5_VOCAB_TERM_LE 0x04
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Translate a string containing an fts5vocab table type to an
|
** Translate a string containing an fts5vocab table type to an
|
||||||
** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
|
** FTS5_VOCAB_XXX constant. If successful, set *peType to the output
|
||||||
@ -230,6 +240,46 @@ static int fts5VocabBestIndexMethod(
|
|||||||
sqlite3_vtab *pVTab,
|
sqlite3_vtab *pVTab,
|
||||||
sqlite3_index_info *pInfo
|
sqlite3_index_info *pInfo
|
||||||
){
|
){
|
||||||
|
int i;
|
||||||
|
int iTermEq = -1;
|
||||||
|
int iTermGe = -1;
|
||||||
|
int iTermLe = -1;
|
||||||
|
int idxNum = 0;
|
||||||
|
int nArg = 0;
|
||||||
|
|
||||||
|
for(i=0; i<pInfo->nConstraint; i++){
|
||||||
|
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||||
|
if( p->usable==0 ) continue;
|
||||||
|
if( p->iColumn==0 ){ /* term column */
|
||||||
|
if( p->op==SQLITE_INDEX_CONSTRAINT_EQ ) iTermEq = i;
|
||||||
|
if( p->op==SQLITE_INDEX_CONSTRAINT_LE ) iTermLe = i;
|
||||||
|
if( p->op==SQLITE_INDEX_CONSTRAINT_LT ) iTermLe = i;
|
||||||
|
if( p->op==SQLITE_INDEX_CONSTRAINT_GE ) iTermGe = i;
|
||||||
|
if( p->op==SQLITE_INDEX_CONSTRAINT_GT ) iTermGe = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( iTermEq>=0 ){
|
||||||
|
idxNum |= FTS5_VOCAB_TERM_EQ;
|
||||||
|
pInfo->aConstraintUsage[iTermEq].argvIndex = ++nArg;
|
||||||
|
pInfo->aConstraintUsage[iTermEq].omit = 1;
|
||||||
|
pInfo->estimatedCost = 100;
|
||||||
|
}else{
|
||||||
|
pInfo->estimatedCost = 1000000;
|
||||||
|
if( iTermGe>=0 ){
|
||||||
|
idxNum |= FTS5_VOCAB_TERM_GE;
|
||||||
|
pInfo->aConstraintUsage[iTermGe].argvIndex = ++nArg;
|
||||||
|
pInfo->estimatedCost = pInfo->estimatedCost / 2;
|
||||||
|
}
|
||||||
|
if( iTermLe>=0 ){
|
||||||
|
idxNum |= FTS5_VOCAB_TERM_LE;
|
||||||
|
pInfo->aConstraintUsage[iTermLe].argvIndex = ++nArg;
|
||||||
|
pInfo->estimatedCost = pInfo->estimatedCost / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pInfo->idxNum = idxNum;
|
||||||
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,12 +292,11 @@ static int fts5VocabOpenMethod(
|
|||||||
){
|
){
|
||||||
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
|
Fts5VocabTable *pTab = (Fts5VocabTable*)pVTab;
|
||||||
Fts5Index *pIndex = 0;
|
Fts5Index *pIndex = 0;
|
||||||
int nCol = 0;
|
Fts5Config *pConfig = 0;
|
||||||
Fts5VocabCursor *pCsr = 0;
|
Fts5VocabCursor *pCsr = 0;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
sqlite3_stmt *pStmt = 0;
|
sqlite3_stmt *pStmt = 0;
|
||||||
char *zSql = 0;
|
char *zSql = 0;
|
||||||
int nByte;
|
|
||||||
|
|
||||||
zSql = sqlite3Fts5Mprintf(&rc,
|
zSql = sqlite3Fts5Mprintf(&rc,
|
||||||
"SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
|
"SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
|
||||||
@ -262,7 +311,7 @@ static int fts5VocabOpenMethod(
|
|||||||
|
|
||||||
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
|
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||||
i64 iId = sqlite3_column_int64(pStmt, 0);
|
i64 iId = sqlite3_column_int64(pStmt, 0);
|
||||||
pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &nCol);
|
pIndex = sqlite3Fts5IndexFromCsrid(pTab->pGlobal, iId, &pConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc==SQLITE_OK && pIndex==0 ){
|
if( rc==SQLITE_OK && pIndex==0 ){
|
||||||
@ -276,14 +325,17 @@ static int fts5VocabOpenMethod(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nByte = nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
|
if( rc==SQLITE_OK ){
|
||||||
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
|
int nByte = pConfig->nCol * sizeof(i64) * 2 + sizeof(Fts5VocabCursor);
|
||||||
|
pCsr = (Fts5VocabCursor*)sqlite3Fts5MallocZero(&rc, nByte);
|
||||||
|
}
|
||||||
|
|
||||||
if( pCsr ){
|
if( pCsr ){
|
||||||
pCsr->pIndex = pIndex;
|
pCsr->pIndex = pIndex;
|
||||||
pCsr->pStmt = pStmt;
|
pCsr->pStmt = pStmt;
|
||||||
pCsr->nCol = nCol;
|
pCsr->pConfig = pConfig;
|
||||||
pCsr->aCnt = (i64*)&pCsr[1];
|
pCsr->aCnt = (i64*)&pCsr[1];
|
||||||
pCsr->aDoc = &pCsr->aCnt[nCol];
|
pCsr->aDoc = &pCsr->aCnt[pConfig->nCol];
|
||||||
}else{
|
}else{
|
||||||
sqlite3_finalize(pStmt);
|
sqlite3_finalize(pStmt);
|
||||||
}
|
}
|
||||||
@ -296,6 +348,9 @@ static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
|
|||||||
pCsr->rowid = 0;
|
pCsr->rowid = 0;
|
||||||
sqlite3Fts5IterClose(pCsr->pIter);
|
sqlite3Fts5IterClose(pCsr->pIter);
|
||||||
pCsr->pIter = 0;
|
pCsr->pIter = 0;
|
||||||
|
sqlite3_free(pCsr->zLeTerm);
|
||||||
|
pCsr->nLeTerm = -1;
|
||||||
|
pCsr->zLeTerm = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -319,16 +374,17 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
|||||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||||
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
|
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
int nCol = pCsr->pConfig->nCol;
|
||||||
|
|
||||||
pCsr->rowid++;
|
pCsr->rowid++;
|
||||||
|
|
||||||
if( pTab->eType==FTS5_VOCAB_COL ){
|
if( pTab->eType==FTS5_VOCAB_COL ){
|
||||||
for(pCsr->iCol++; pCsr->iCol<pCsr->nCol; pCsr->iCol++){
|
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
|
||||||
if( pCsr->aCnt[pCsr->iCol] ) break;
|
if( pCsr->aCnt[pCsr->iCol] ) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=pCsr->nCol ){
|
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
|
||||||
if( sqlite3Fts5IterEof(pCsr->pIter) ){
|
if( sqlite3Fts5IterEof(pCsr->pIter) ){
|
||||||
pCsr->bEof = 1;
|
pCsr->bEof = 1;
|
||||||
}else{
|
}else{
|
||||||
@ -336,10 +392,18 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
|||||||
int nTerm;
|
int nTerm;
|
||||||
|
|
||||||
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
||||||
|
if( pCsr->nLeTerm>=0 ){
|
||||||
|
int nCmp = MIN(nTerm, pCsr->nLeTerm);
|
||||||
|
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
|
||||||
|
if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
|
||||||
|
pCsr->bEof = 1;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
|
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
|
||||||
memset(pCsr->aVal, 0, sizeof(pCsr->aVal));
|
memset(pCsr->aCnt, 0, nCol * sizeof(i64));
|
||||||
memset(pCsr->aCnt, 0, pCsr->nCol * sizeof(i64));
|
memset(pCsr->aDoc, 0, nCol * sizeof(i64));
|
||||||
memset(pCsr->aDoc, 0, pCsr->nCol * sizeof(i64));
|
|
||||||
pCsr->iCol = 0;
|
pCsr->iCol = 0;
|
||||||
|
|
||||||
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
|
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
|
||||||
@ -353,9 +417,9 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
|||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( pTab->eType==FTS5_VOCAB_ROW ){
|
if( pTab->eType==FTS5_VOCAB_ROW ){
|
||||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||||
pCsr->aVal[1]++;
|
pCsr->aCnt[0]++;
|
||||||
}
|
}
|
||||||
pCsr->aVal[0]++;
|
pCsr->aDoc[0]++;
|
||||||
}else{
|
}else{
|
||||||
int iCol = -1;
|
int iCol = -1;
|
||||||
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
|
||||||
@ -369,9 +433,12 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
|||||||
}
|
}
|
||||||
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
|
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
|
||||||
if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ) break;
|
if( nTerm!=pCsr->term.n || memcmp(zTerm, pCsr->term.p, nTerm) ){
|
||||||
|
break;
|
||||||
|
}
|
||||||
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
|
if( sqlite3Fts5IterEof(pCsr->pIter) ) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,9 +447,7 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
|
|||||||
|
|
||||||
if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
|
if( pCsr->bEof==0 && pTab->eType==FTS5_VOCAB_COL ){
|
||||||
while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++;
|
while( pCsr->aCnt[pCsr->iCol]==0 ) pCsr->iCol++;
|
||||||
pCsr->aVal[0] = pCsr->iCol;
|
assert( pCsr->iCol<pCsr->pConfig->nCol );
|
||||||
pCsr->aVal[1] = pCsr->aDoc[pCsr->iCol];
|
|
||||||
pCsr->aVal[2] = pCsr->aCnt[pCsr->iCol];
|
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -399,10 +464,46 @@ static int fts5VocabFilterMethod(
|
|||||||
){
|
){
|
||||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||||
int rc;
|
int rc;
|
||||||
const int flags = FTS5INDEX_QUERY_SCAN;
|
|
||||||
|
int iVal = 0;
|
||||||
|
int f = FTS5INDEX_QUERY_SCAN;
|
||||||
|
const char *zTerm = 0;
|
||||||
|
int nTerm = 0;
|
||||||
|
|
||||||
|
sqlite3_value *pEq = 0;
|
||||||
|
sqlite3_value *pGe = 0;
|
||||||
|
sqlite3_value *pLe = 0;
|
||||||
|
|
||||||
fts5VocabResetCursor(pCsr);
|
fts5VocabResetCursor(pCsr);
|
||||||
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, 0, 0, flags, 0, &pCsr->pIter);
|
if( idxNum & FTS5_VOCAB_TERM_EQ ) pEq = apVal[iVal++];
|
||||||
|
if( idxNum & FTS5_VOCAB_TERM_GE ) pGe = apVal[iVal++];
|
||||||
|
if( idxNum & FTS5_VOCAB_TERM_LE ) pLe = apVal[iVal++];
|
||||||
|
|
||||||
|
if( pEq ){
|
||||||
|
zTerm = sqlite3_value_text(pEq);
|
||||||
|
nTerm = sqlite3_value_bytes(pEq);
|
||||||
|
f = 0;
|
||||||
|
}else{
|
||||||
|
if( pGe ){
|
||||||
|
zTerm = sqlite3_value_text(pGe);
|
||||||
|
nTerm = sqlite3_value_bytes(pGe);
|
||||||
|
}
|
||||||
|
if( pLe ){
|
||||||
|
const char *zCopy = sqlite3_value_text(pLe);
|
||||||
|
pCsr->nLeTerm = sqlite3_value_bytes(pLe);
|
||||||
|
pCsr->zLeTerm = sqlite3_malloc(pCsr->nLeTerm+1);
|
||||||
|
if( pCsr->zLeTerm==0 ){
|
||||||
|
rc = SQLITE_NOMEM;
|
||||||
|
}else{
|
||||||
|
memcpy(pCsr->zLeTerm, zCopy, pCsr->nLeTerm+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
|
||||||
|
}
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
rc = fts5VocabNextMethod(pCursor);
|
rc = fts5VocabNextMethod(pCursor);
|
||||||
}
|
}
|
||||||
@ -425,17 +526,29 @@ static int fts5VocabColumnMethod(
|
|||||||
int iCol /* Index of column to read value from */
|
int iCol /* Index of column to read value from */
|
||||||
){
|
){
|
||||||
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
|
||||||
switch( iCol ){
|
|
||||||
case 0: /* term */
|
|
||||||
sqlite3_result_text(
|
|
||||||
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if( iCol==0 ){
|
||||||
assert( iCol<4 && iCol>0 );
|
sqlite3_result_text(
|
||||||
sqlite3_result_int64(pCtx, pCsr->aVal[iCol-1]);
|
pCtx, (const char*)pCsr->term.p, pCsr->term.n, SQLITE_TRANSIENT
|
||||||
break;
|
);
|
||||||
|
}
|
||||||
|
else if( ((Fts5VocabTable*)(pCursor->pVtab))->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);
|
||||||
|
}else if( iCol==2 ){
|
||||||
|
sqlite3_result_int64(pCtx, pCsr->aDoc[pCsr->iCol]);
|
||||||
|
}else{
|
||||||
|
sqlite3_result_int64(pCtx, pCsr->aCnt[pCsr->iCol]);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
assert( iCol==1 || iCol==2 );
|
||||||
|
if( iCol==1 ){
|
||||||
|
sqlite3_result_int64(pCtx, pCsr->aDoc[0]);
|
||||||
|
}else{
|
||||||
|
sqlite3_result_int64(pCtx, pCsr->aCnt[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ do_execsql_test 1.4.1 {
|
|||||||
|
|
||||||
do_execsql_test 1.4.2 {
|
do_execsql_test 1.4.2 {
|
||||||
SELECT * FROM v2;
|
SELECT * FROM v2;
|
||||||
} {x 0 2 4 y 0 1 1 z 0 1 1}
|
} {x one 2 4 y one 1 1 z one 1 1}
|
||||||
|
|
||||||
do_execsql_test 1.5.1 {
|
do_execsql_test 1.5.1 {
|
||||||
BEGIN;
|
BEGIN;
|
||||||
@ -67,7 +67,7 @@ do_execsql_test 1.5.1 {
|
|||||||
do_execsql_test 1.5.2 {
|
do_execsql_test 1.5.2 {
|
||||||
SELECT * FROM v2 WHERE term<'d';
|
SELECT * FROM v2 WHERE term<'d';
|
||||||
COMMIT;
|
COMMIT;
|
||||||
} {a 0 1 1 b 0 1 1 c 0 1 1}
|
} {a one 1 1 b one 1 1 c one 1 1}
|
||||||
|
|
||||||
do_execsql_test 1.6 {
|
do_execsql_test 1.6 {
|
||||||
DELETE FROM t1 WHERE one = 'a b c';
|
DELETE FROM t1 WHERE one = 'a b c';
|
||||||
@ -91,14 +91,14 @@ do_execsql_test 2.0 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set res_col {
|
set res_col {
|
||||||
a 0 6 11 a 1 7 9
|
a a 6 11 a b 7 9
|
||||||
b 0 6 7 b 1 7 7
|
b a 6 7 b b 7 7
|
||||||
c 0 6 12 c 1 5 8
|
c a 6 12 c b 5 8
|
||||||
d 0 4 6 d 1 9 13
|
d a 4 6 d b 9 13
|
||||||
e 0 6 7 e 1 6 6
|
e a 6 7 e b 6 6
|
||||||
f 0 9 10 f 1 7 10
|
f a 9 10 f b 7 10
|
||||||
g 0 5 7 g 1 5 7
|
g a 5 7 g b 5 7
|
||||||
x 0 1 1 y 1 1 1
|
x a 1 1 y b 1 1
|
||||||
}
|
}
|
||||||
set res_row {
|
set res_row {
|
||||||
a 10 20 b 9 14 c 9 20 d 9 19
|
a 10 20 b 9 14 c 9 20 d 9 19
|
||||||
@ -213,5 +213,128 @@ do_catchsql_test 6.2 {
|
|||||||
SELECT * FROM vocab3;
|
SELECT * FROM vocab3;
|
||||||
} {1 {no such fts5 table: main.lll}}
|
} {1 {no such fts5 table: main.lll}}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Test single term queries on fts5vocab tables (i.e. those with term=?
|
||||||
|
# constraints in the WHERE clause).
|
||||||
|
#
|
||||||
|
do_execsql_test 7.0 {
|
||||||
|
CREATE VIRTUAL TABLE tx USING fts5(one, two);
|
||||||
|
INSERT INTO tx VALUES('g a ggg g a b eee', 'cc d aa ff g ee');
|
||||||
|
INSERT INTO tx VALUES('dd fff i a i jjj', 'f fff hh jj e f');
|
||||||
|
INSERT INTO tx VALUES('ggg a f f fff dd aa', 'd ggg f f j gg ddd');
|
||||||
|
INSERT INTO tx VALUES('e bb h jjj ii gg', 'e aa e f c fff');
|
||||||
|
INSERT INTO tx VALUES('j ff aa a h', 'h a j bbb bb');
|
||||||
|
INSERT INTO tx VALUES('cc i ff c d f', 'dd ii fff f c cc d');
|
||||||
|
INSERT INTO tx VALUES('jjj g i bb cc eee', 'hhh iii aaa b bbb aaa');
|
||||||
|
INSERT INTO tx VALUES('hhh hhh hhh bb fff f', 'fff gg aa ii h a');
|
||||||
|
INSERT INTO tx VALUES('b c cc aaa iii ggg f', 'iii ff ee a ff c cc');
|
||||||
|
INSERT INTO tx VALUES('hhh b hhh aaa j i i', 'dd ee ee aa bbb iii');
|
||||||
|
INSERT INTO tx VALUES('hh dd h b g ff i', 'ccc bb cc ccc f a d');
|
||||||
|
INSERT INTO tx VALUES('g d b ggg jj', 'fff jj ff jj g gg ee');
|
||||||
|
INSERT INTO tx VALUES('g ee ggg ggg cc bb eee', 'aa j jjj bbb dd eee ff');
|
||||||
|
INSERT INTO tx VALUES('c jjj hh ddd dd h', 'e aaa h jjj gg');
|
||||||
|
|
||||||
|
CREATE VIRTUAL TABLE txr USING fts5vocab(tx, row);
|
||||||
|
CREATE VIRTUAL TABLE txc USING fts5vocab(tx, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
proc cont {L elem} {
|
||||||
|
set n 0
|
||||||
|
foreach e $L { if {$elem==$e} {incr n} }
|
||||||
|
set n
|
||||||
|
}
|
||||||
|
db func cont cont
|
||||||
|
|
||||||
|
foreach {term} {
|
||||||
|
a aa aaa
|
||||||
|
b bb bbb
|
||||||
|
c cc ccc
|
||||||
|
d dd ddd
|
||||||
|
e ee eee
|
||||||
|
f ff fff
|
||||||
|
g gg ggg
|
||||||
|
h hh hhh
|
||||||
|
i ii iii
|
||||||
|
j jj jjj
|
||||||
|
} {
|
||||||
|
set resr [db eval {
|
||||||
|
SELECT $term,
|
||||||
|
sum(cont(one || ' ' || two, $term) > 0),
|
||||||
|
sum(cont(one || ' ' || two, $term))
|
||||||
|
FROM tx
|
||||||
|
}]
|
||||||
|
if {[lindex $resr 1]==0} {set resr [list]}
|
||||||
|
|
||||||
|
set r1 [db eval {
|
||||||
|
SELECT $term, 'one', sum(cont(one, $term)>0), sum(cont(one, $term)) FROM tx
|
||||||
|
}]
|
||||||
|
if {[lindex $r1 2]==0} {set r1 [list]}
|
||||||
|
|
||||||
|
set r2 [db eval {
|
||||||
|
SELECT $term, 'two', sum(cont(two, $term)>0), sum(cont(two, $term)) FROM tx
|
||||||
|
}]
|
||||||
|
if {[lindex $r2 2]==0} {set r2 [list]}
|
||||||
|
|
||||||
|
set resc [concat $r1 $r2]
|
||||||
|
do_execsql_test 7.$term.1 {SELECT * FROM txc WHERE term=$term} $resc
|
||||||
|
do_execsql_test 7.$term.2 {SELECT * FROM txr WHERE term=$term} $resr
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 7.1 {
|
||||||
|
CREATE TABLE txr_c AS SELECT * FROM txr;
|
||||||
|
CREATE TABLE txc_c AS SELECT * FROM txc;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test range queries on the fts5vocab tables created above.
|
||||||
|
#
|
||||||
|
foreach {tn a b} {
|
||||||
|
1 a jjj
|
||||||
|
2 bb j
|
||||||
|
3 ccc ddd
|
||||||
|
4 dd xyz
|
||||||
|
5 xzy dd
|
||||||
|
6 h hh
|
||||||
|
} {
|
||||||
|
do_execsql_test 7.2.$tn.1 {
|
||||||
|
SELECT * FROM txr WHERE term>=$a
|
||||||
|
} [db eval {SELECT * FROM txr_c WHERE term>=$a}]
|
||||||
|
do_execsql_test 7.2.$tn.2 {
|
||||||
|
SELECT * FROM txr WHERE term<=$b
|
||||||
|
} [db eval {SELECT * FROM txr_c WHERE term <=$b}]
|
||||||
|
do_execsql_test 7.2.$tn.3 {
|
||||||
|
SELECT * FROM txr WHERE term>=$a AND term<=$b
|
||||||
|
} [db eval {SELECT * FROM txr_c WHERE term>=$a AND term <=$b}]
|
||||||
|
|
||||||
|
do_execsql_test 7.2.$tn.4 {
|
||||||
|
SELECT * FROM txc WHERE term>=$a
|
||||||
|
} [db eval {SELECT * FROM txc_c WHERE term>=$a}]
|
||||||
|
do_execsql_test 7.2.$tn.5 {
|
||||||
|
SELECT * FROM txc WHERE term<=$b
|
||||||
|
} [db eval {SELECT * FROM txc_c WHERE term <=$b}]
|
||||||
|
do_execsql_test 7.2.$tn.6 {
|
||||||
|
SELECT * FROM txc WHERE term>=$a AND term<=$b
|
||||||
|
} [db eval {SELECT * FROM txc_c WHERE term>=$a AND term <=$b}]
|
||||||
|
|
||||||
|
do_execsql_test 7.2.$tn.7 {
|
||||||
|
SELECT * FROM txr WHERE term>$a
|
||||||
|
} [db eval {SELECT * FROM txr_c WHERE term>$a}]
|
||||||
|
do_execsql_test 7.2.$tn.8 {
|
||||||
|
SELECT * FROM txr WHERE term<$b
|
||||||
|
} [db eval {SELECT * FROM txr_c WHERE term<$b}]
|
||||||
|
do_execsql_test 7.2.$tn.9 {
|
||||||
|
SELECT * FROM txr WHERE term>$a AND term<$b
|
||||||
|
} [db eval {SELECT * FROM txr_c WHERE term>$a AND term <$b}]
|
||||||
|
|
||||||
|
do_execsql_test 7.2.$tn.10 {
|
||||||
|
SELECT * FROM txc WHERE term>$a
|
||||||
|
} [db eval {SELECT * FROM txc_c WHERE term>$a}]
|
||||||
|
do_execsql_test 7.2.$tn.11 {
|
||||||
|
SELECT * FROM txc WHERE term<$b
|
||||||
|
} [db eval {SELECT * FROM txc_c WHERE term<$b}]
|
||||||
|
do_execsql_test 7.2.$tn.12 {
|
||||||
|
SELECT * FROM txc WHERE term>$a AND term<$b
|
||||||
|
} [db eval {SELECT * FROM txc_c WHERE term>$a AND term <$b}]
|
||||||
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
|||||||
C Fix\sa\scomment\sin\sexpr.c\sand\sadd\sa\sCORRUPT_DB\sto\san\sassert()\sin\sbtree.c.
|
C Handle\sequality\sand\srange\sconstraints\son\sthe\s"term"\scolumn\sof\sfts5vocab\stables.\sAlso\shave\sthe\ssame\smodule\sreport\scolumns\susing\snames\sinstead\sof\sindexes.
|
||||||
D 2015-10-16T23:55:08.882
|
D 2015-10-17T19:49:01.860
|
||||||
F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
|
F Makefile.in 2ea961bc09e441874eb3d1bf7398e04feb24f3ee
|
||||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||||
F Makefile.msc 4eb750e0fdf52050a06d881e1b060f4bb116ed7e
|
F Makefile.msc 4eb750e0fdf52050a06d881e1b060f4bb116ed7e
|
||||||
@ -103,21 +103,21 @@ 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 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9
|
F ext/fts5/fts5.h 8b9a13b309b180e9fb88ea5666c0d8d73c6102d9
|
||||||
F ext/fts5/fts5Int.h 38667e39859ff3f3bc91f47efe672023a145a118
|
F ext/fts5/fts5Int.h 0332d12fdca0f4fe2231df71bd7544b3cef81122
|
||||||
F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35
|
F ext/fts5/fts5_aux.c 1f384972d606375b8fa078319f25ab4b5feb1b35
|
||||||
F ext/fts5/fts5_buffer.c 9a3aa73a4e7b26b1c805b9c92c1344ba3d19d2a8
|
F ext/fts5/fts5_buffer.c 9a3aa73a4e7b26b1c805b9c92c1344ba3d19d2a8
|
||||||
F ext/fts5/fts5_config.c 88a77f5d5e4dfbb2355b8f6cc9969b7f02d94685
|
F ext/fts5/fts5_config.c 88a77f5d5e4dfbb2355b8f6cc9969b7f02d94685
|
||||||
F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900
|
F ext/fts5/fts5_expr.c 28b15c9ae296204bc0a2e5cf7a667d840a9d2900
|
||||||
F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f
|
F ext/fts5/fts5_hash.c a9d4c1efebc2a91d26ad7ebdfcbf2678ceac405f
|
||||||
F ext/fts5/fts5_index.c c76d636d6cd22e3b82b1dbf3a3993447091c3bed
|
F ext/fts5/fts5_index.c 632fdcb1971f6c9d7d6b2bd31f6c41e4189162bb
|
||||||
F ext/fts5/fts5_main.c d3fde32e1fdd7962dc7062400d1d8c7ec2297acf
|
F ext/fts5/fts5_main.c 520a29136ba07448331f73bdc36d0ffa1e9dcfef
|
||||||
F ext/fts5/fts5_storage.c 9b30115742b758706de70595a8d1d084e940c978
|
F ext/fts5/fts5_storage.c 9b30115742b758706de70595a8d1d084e940c978
|
||||||
F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd
|
F ext/fts5/fts5_tcl.c 3bf445e66de32137d4693694ff7b1fd6074e32bd
|
||||||
F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
|
F ext/fts5/fts5_test_mi.c e96be827aa8f571031e65e481251dc1981d608bf
|
||||||
F ext/fts5/fts5_tokenize.c 12c5d925286491a71bb3dad7c8924ce9cfd18320
|
F ext/fts5/fts5_tokenize.c 12c5d925286491a71bb3dad7c8924ce9cfd18320
|
||||||
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
|
F ext/fts5/fts5_unicode2.c 78273fbd588d1d9bd0a7e4e0ccc9207348bae33c
|
||||||
F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
|
F ext/fts5/fts5_varint.c 3f86ce09cab152e3d45490d7586b7ed2e40c13f1
|
||||||
F ext/fts5/fts5_vocab.c 85ebf2e93089c9d3d136cc69163370592fc040f3
|
F ext/fts5/fts5_vocab.c f7c03dabb858896d42165bc54e4aa4f82650ecea
|
||||||
F ext/fts5/fts5parse.y e83dca6028e3309178d05b5bd920e372dc295d35
|
F ext/fts5/fts5parse.y e83dca6028e3309178d05b5bd920e372dc295d35
|
||||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||||
F ext/fts5/test/fts5_common.tcl 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d
|
F ext/fts5/test/fts5_common.tcl 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d
|
||||||
@ -180,7 +180,7 @@ F ext/fts5/test/fts5unicode2.test c1dd890ba32b7609adba78e420faa847abe43b59
|
|||||||
F ext/fts5/test/fts5unicode3.test 35c3d02aa7acf7d43d8de3bfe32c15ba96e8928e
|
F ext/fts5/test/fts5unicode3.test 35c3d02aa7acf7d43d8de3bfe32c15ba96e8928e
|
||||||
F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680
|
F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680
|
||||||
F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e
|
F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e
|
||||||
F ext/fts5/test/fts5vocab.test cdf97b9678484e9bad5062edf9c9106e5c3b0c5c
|
F ext/fts5/test/fts5vocab.test 7dec771fd2388c11f7c336d6d155d31e12e4001a
|
||||||
F ext/fts5/tool/fts5txt2db.tcl 3d19fb8ffb234031d33d7d2151acfbc55e9cfcc4
|
F ext/fts5/tool/fts5txt2db.tcl 3d19fb8ffb234031d33d7d2151acfbc55e9cfcc4
|
||||||
F ext/fts5/tool/loadfts5.tcl 58e90407cc5c2b1770460119488fd7c0090d4dd3
|
F ext/fts5/tool/loadfts5.tcl 58e90407cc5c2b1770460119488fd7c0090d4dd3
|
||||||
F ext/fts5/tool/mkfts5c.tcl 09ce6a7997440508360f5ba1651ab7e923a8bf31
|
F ext/fts5/tool/mkfts5c.tcl 09ce6a7997440508360f5ba1651ab7e923a8bf31
|
||||||
@ -1391,7 +1391,7 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
|||||||
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 39e8a5d93fa370afb03223bf0c20ea0f3448b9fc
|
P 0df371d1a51c2028aefa4c704707773750317689
|
||||||
R 7f916530a28273810e372e1a6552332a
|
R 97767b5f8bc213fefd21674fa8888cb4
|
||||||
U drh
|
U dan
|
||||||
Z 831fa17e60715846d1a74c0ef53a246d
|
Z b5428af5c06a042c6ac8c829b1afb62f
|
||||||
|
@ -1 +1 @@
|
|||||||
0df371d1a51c2028aefa4c704707773750317689
|
6020d96ab47a0bebe41f691a3f44fd55d8b2d2b7
|
Reference in New Issue
Block a user