mirror of
https://github.com/sqlite/sqlite.git
synced 2026-01-06 08:01:16 +03:00
Allow fts5 to filter on multiple MATCH clauses in a single scan.
FossilOrigin-Name: 9d418a7a491761eeb38a70898677a493e2631e5d62e75ee88431f52d3dfd2344
This commit is contained in:
@@ -695,6 +695,7 @@ int sqlite3Fts5ExprEof(Fts5Expr*);
|
|||||||
i64 sqlite3Fts5ExprRowid(Fts5Expr*);
|
i64 sqlite3Fts5ExprRowid(Fts5Expr*);
|
||||||
|
|
||||||
void sqlite3Fts5ExprFree(Fts5Expr*);
|
void sqlite3Fts5ExprFree(Fts5Expr*);
|
||||||
|
int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2);
|
||||||
|
|
||||||
/* Called during startup to register a UDF with SQLite */
|
/* Called during startup to register a UDF with SQLite */
|
||||||
int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);
|
int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);
|
||||||
|
|||||||
@@ -683,7 +683,7 @@ int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig){
|
|||||||
rc = sqlite3_declare_vtab(pConfig->db, zSql);
|
rc = sqlite3_declare_vtab(pConfig->db, zSql);
|
||||||
sqlite3_free(zSql);
|
sqlite3_free(zSql);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -309,6 +309,42 @@ void sqlite3Fts5ExprFree(Fts5Expr *p){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){
|
||||||
|
Fts5Parse sParse;
|
||||||
|
memset(&sParse, 0, sizeof(sParse));
|
||||||
|
|
||||||
|
if( *pp1 ){
|
||||||
|
Fts5Expr *p1 = *pp1;
|
||||||
|
int nPhrase = p1->nPhrase + p2->nPhrase;
|
||||||
|
|
||||||
|
p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0);
|
||||||
|
p2->pRoot = 0;
|
||||||
|
|
||||||
|
if( sParse.rc==SQLITE_OK ){
|
||||||
|
Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc(
|
||||||
|
p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*)
|
||||||
|
);
|
||||||
|
if( ap==0 ){
|
||||||
|
sParse.rc = SQLITE_NOMEM;
|
||||||
|
}else{
|
||||||
|
int i;
|
||||||
|
memmove(&ap[p2->nPhrase], ap, p1->nPhrase*sizeof(Fts5ExprPhrase*));
|
||||||
|
for(i=0; i<p2->nPhrase; i++){
|
||||||
|
ap[i] = p2->apExprPhrase[i];
|
||||||
|
}
|
||||||
|
p1->nPhrase = nPhrase;
|
||||||
|
p1->apExprPhrase = ap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_free(p2->apExprPhrase);
|
||||||
|
sqlite3_free(p2);
|
||||||
|
}else{
|
||||||
|
*pp1 = p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sParse.rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Argument pTerm must be a synonym iterator. Return the current rowid
|
** Argument pTerm must be a synonym iterator. Return the current rowid
|
||||||
** that it points to.
|
** that it points to.
|
||||||
|
|||||||
@@ -465,17 +465,39 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
|
|||||||
** Implementation of the xBestIndex method for FTS5 tables. Within the
|
** Implementation of the xBestIndex method for FTS5 tables. Within the
|
||||||
** WHERE constraint, it searches for the following:
|
** WHERE constraint, it searches for the following:
|
||||||
**
|
**
|
||||||
** 1. A MATCH constraint against the special column.
|
** 1. A MATCH constraint against the table column.
|
||||||
** 2. A MATCH constraint against the "rank" column.
|
** 2. A MATCH constraint against the "rank" column.
|
||||||
** 3. An == constraint against the rowid column.
|
** 3. A MATCH constraint against some other column.
|
||||||
** 4. A < or <= constraint against the rowid column.
|
** 4. An == constraint against the rowid column.
|
||||||
** 5. A > or >= constraint against the rowid column.
|
** 5. A < or <= constraint against the rowid column.
|
||||||
|
** 6. A > or >= constraint against the rowid column.
|
||||||
**
|
**
|
||||||
** Within the ORDER BY, either:
|
** Within the ORDER BY, the following are supported:
|
||||||
**
|
**
|
||||||
** 5. ORDER BY rank [ASC|DESC]
|
** 5. ORDER BY rank [ASC|DESC]
|
||||||
** 6. ORDER BY rowid [ASC|DESC]
|
** 6. ORDER BY rowid [ASC|DESC]
|
||||||
**
|
**
|
||||||
|
** Information for the xFilter call is passed via both the idxNum and
|
||||||
|
** idxStr variables. Specifically, idxNum is a bitmask of the following
|
||||||
|
** flags used to encode the ORDER BY clause:
|
||||||
|
**
|
||||||
|
** FTS5_BI_ORDER_RANK
|
||||||
|
** FTS5_BI_ORDER_ROWID
|
||||||
|
** FTS5_BI_ORDER_DESC
|
||||||
|
**
|
||||||
|
** idxStr is used to encode data from the WHERE clause. For each argument
|
||||||
|
** passed to the xFilter method, the following is appended to idxStr:
|
||||||
|
**
|
||||||
|
** Match against table column: "m"
|
||||||
|
** Match against rank column: "r"
|
||||||
|
** Match against other column: "<column-number>"
|
||||||
|
** Equality constraint against the rowid: "="
|
||||||
|
** A < or <= against the rowid: "<"
|
||||||
|
** A > or >= against the rowid: ">"
|
||||||
|
**
|
||||||
|
** This function ensures that there is at most one "r" or "=". And that if
|
||||||
|
** there exists an "=" then there is no "<" or ">".
|
||||||
|
**
|
||||||
** Costs are assigned as follows:
|
** Costs are assigned as follows:
|
||||||
**
|
**
|
||||||
** a) If an unusable MATCH operator is present in the WHERE clause, the
|
** a) If an unusable MATCH operator is present in the WHERE clause, the
|
||||||
@@ -503,32 +525,18 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
|||||||
Fts5Config *pConfig = pTab->pConfig;
|
Fts5Config *pConfig = pTab->pConfig;
|
||||||
const int nCol = pConfig->nCol;
|
const int nCol = pConfig->nCol;
|
||||||
int idxFlags = 0; /* Parameter passed through to xFilter() */
|
int idxFlags = 0; /* Parameter passed through to xFilter() */
|
||||||
int bHasMatch;
|
|
||||||
int iNext;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
struct Constraint {
|
char *idxStr;
|
||||||
int op; /* Mask against sqlite3_index_constraint.op */
|
int iIdxStr = 0;
|
||||||
int fts5op; /* FTS5 mask for idxFlags */
|
int iCons = 0;
|
||||||
int iCol; /* 0==rowid, 1==tbl, 2==rank */
|
|
||||||
int omit; /* True to omit this if found */
|
int bSeenEq = 0;
|
||||||
int iConsIndex; /* Index in pInfo->aConstraint[] */
|
int bSeenGt = 0;
|
||||||
} aConstraint[] = {
|
int bSeenLt = 0;
|
||||||
{SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
|
int bSeenMatch = 0;
|
||||||
FTS5_BI_MATCH, 1, 1, -1},
|
int bSeenRank = 0;
|
||||||
{SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
|
|
||||||
FTS5_BI_RANK, 2, 1, -1},
|
|
||||||
{SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1},
|
|
||||||
{SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE,
|
|
||||||
FTS5_BI_ROWID_LE, 0, 0, -1},
|
|
||||||
{SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE,
|
|
||||||
FTS5_BI_ROWID_GE, 0, 0, -1},
|
|
||||||
};
|
|
||||||
|
|
||||||
int aColMap[3];
|
|
||||||
aColMap[0] = -1;
|
|
||||||
aColMap[1] = nCol;
|
|
||||||
aColMap[2] = nCol+1;
|
|
||||||
|
|
||||||
assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
|
assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
|
||||||
assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
|
assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
|
||||||
@@ -543,40 +551,76 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
|||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set idxFlags flags for all WHERE clause terms that will be used. */
|
idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
|
||||||
|
if( idxStr==0 ) return SQLITE_NOMEM;
|
||||||
|
pInfo->idxStr = idxStr;
|
||||||
|
pInfo->needToFreeIdxStr = 1;
|
||||||
|
|
||||||
for(i=0; i<pInfo->nConstraint; i++){
|
for(i=0; i<pInfo->nConstraint; i++){
|
||||||
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||||
int iCol = p->iColumn;
|
int iCol = p->iColumn;
|
||||||
|
if( p->op==SQLITE_INDEX_CONSTRAINT_MATCH
|
||||||
if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
|
|| (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol)
|
||||||
|| (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
|
|
||||||
){
|
){
|
||||||
/* A MATCH operator or equivalent */
|
/* A MATCH operator or equivalent */
|
||||||
if( p->usable ){
|
if( p->usable==0 || iCol<0 ){
|
||||||
idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
|
|
||||||
aConstraint[0].iConsIndex = i;
|
|
||||||
}else{
|
|
||||||
/* As there exists an unusable MATCH constraint this is an
|
/* As there exists an unusable MATCH constraint this is an
|
||||||
** unusable plan. Set a prohibitively high cost. */
|
** unusable plan. Set a prohibitively high cost. */
|
||||||
pInfo->estimatedCost = 1e50;
|
pInfo->estimatedCost = 1e50;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
|
}else{
|
||||||
|
if( iCol==nCol+1 ){
|
||||||
|
if( bSeenRank ) continue;
|
||||||
|
idxStr[iIdxStr++] = 'r';
|
||||||
|
bSeenRank = 1;
|
||||||
|
}else{
|
||||||
|
bSeenMatch = 1;
|
||||||
|
idxStr[iIdxStr++] = 'm';
|
||||||
|
if( iCol<nCol ){
|
||||||
|
sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
|
||||||
|
idxStr += strlen(&idxStr[iIdxStr]);
|
||||||
|
assert( idxStr[iIdxStr]=='\0' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
||||||
|
pInfo->aConstraintUsage[i].omit = 1;
|
||||||
}
|
}
|
||||||
}else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){
|
}
|
||||||
int j;
|
else if( p->usable && bSeenEq==0
|
||||||
for(j=1; j<ArraySize(aConstraint); j++){
|
&& p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
|
||||||
struct Constraint *pC = &aConstraint[j];
|
){
|
||||||
if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){
|
idxStr[iIdxStr++] = '=';
|
||||||
pC->iConsIndex = i;
|
bSeenEq = 1;
|
||||||
idxFlags |= pC->fts5op;
|
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( bSeenEq==0 ){
|
||||||
|
for(i=0; i<pInfo->nConstraint; i++){
|
||||||
|
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
||||||
|
if( p->iColumn<0 && p->usable ){
|
||||||
|
int op = p->op;
|
||||||
|
if( op==SQLITE_INDEX_CONSTRAINT_LT || op==SQLITE_INDEX_CONSTRAINT_LE ){
|
||||||
|
if( bSeenLt ) continue;
|
||||||
|
idxStr[iIdxStr++] = '<';
|
||||||
|
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
||||||
|
bSeenLt = 1;
|
||||||
|
}else
|
||||||
|
if( op==SQLITE_INDEX_CONSTRAINT_GT || op==SQLITE_INDEX_CONSTRAINT_GE ){
|
||||||
|
if( bSeenGt ) continue;
|
||||||
|
idxStr[iIdxStr++] = '>';
|
||||||
|
pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
||||||
|
bSeenGt = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
idxStr[iIdxStr] = '\0';
|
||||||
|
|
||||||
/* Set idxFlags flags for the ORDER BY clause */
|
/* Set idxFlags flags for the ORDER BY clause */
|
||||||
if( pInfo->nOrderBy==1 ){
|
if( pInfo->nOrderBy==1 ){
|
||||||
int iSort = pInfo->aOrderBy[0].iColumn;
|
int iSort = pInfo->aOrderBy[0].iColumn;
|
||||||
if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){
|
if( iSort==(pConfig->nCol+1) && bSeenMatch ){
|
||||||
idxFlags |= FTS5_BI_ORDER_RANK;
|
idxFlags |= FTS5_BI_ORDER_RANK;
|
||||||
}else if( iSort==-1 ){
|
}else if( iSort==-1 ){
|
||||||
idxFlags |= FTS5_BI_ORDER_ROWID;
|
idxFlags |= FTS5_BI_ORDER_ROWID;
|
||||||
@@ -590,26 +634,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the estimated cost based on the flags set in idxFlags. */
|
/* Calculate the estimated cost based on the flags set in idxFlags. */
|
||||||
bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH);
|
if( bSeenEq ){
|
||||||
if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){
|
pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
|
||||||
pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0;
|
if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
|
||||||
if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo);
|
}else if( bSeenLt && bSeenGt ){
|
||||||
}else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
|
pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
|
||||||
pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
|
}else if( bSeenLt || bSeenGt ){
|
||||||
}else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
|
pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
|
||||||
pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0;
|
|
||||||
}else{
|
}else{
|
||||||
pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
|
pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
|
||||||
}
|
|
||||||
|
|
||||||
/* Assign argvIndex values to each constraint in use. */
|
|
||||||
iNext = 1;
|
|
||||||
for(i=0; i<ArraySize(aConstraint); i++){
|
|
||||||
struct Constraint *pC = &aConstraint[i];
|
|
||||||
if( pC->iConsIndex>=0 ){
|
|
||||||
pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
|
|
||||||
pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pInfo->idxNum = idxFlags;
|
pInfo->idxNum = idxFlags;
|
||||||
@@ -1132,7 +1165,7 @@ static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){
|
|||||||
static int fts5FilterMethod(
|
static int fts5FilterMethod(
|
||||||
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
|
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
|
||||||
int idxNum, /* Strategy index */
|
int idxNum, /* Strategy index */
|
||||||
const char *zUnused, /* Unused */
|
const char *idxStr, /* Unused */
|
||||||
int nVal, /* Number of elements in apVal */
|
int nVal, /* Number of elements in apVal */
|
||||||
sqlite3_value **apVal /* Arguments for the indexing scheme */
|
sqlite3_value **apVal /* Arguments for the indexing scheme */
|
||||||
){
|
){
|
||||||
@@ -1140,7 +1173,6 @@ static int fts5FilterMethod(
|
|||||||
Fts5Config *pConfig = pTab->p.pConfig;
|
Fts5Config *pConfig = pTab->p.pConfig;
|
||||||
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
|
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
|
||||||
int rc = SQLITE_OK; /* Error code */
|
int rc = SQLITE_OK; /* Error code */
|
||||||
int iVal = 0; /* Counter for apVal[] */
|
|
||||||
int bDesc; /* True if ORDER BY [rank|rowid] DESC */
|
int bDesc; /* True if ORDER BY [rank|rowid] DESC */
|
||||||
int bOrderByRank; /* True if ORDER BY rank */
|
int bOrderByRank; /* True if ORDER BY rank */
|
||||||
sqlite3_value *pMatch = 0; /* <tbl> MATCH ? expression (or NULL) */
|
sqlite3_value *pMatch = 0; /* <tbl> MATCH ? expression (or NULL) */
|
||||||
@@ -1150,9 +1182,9 @@ static int fts5FilterMethod(
|
|||||||
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
|
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
|
||||||
int iCol; /* Column on LHS of MATCH operator */
|
int iCol; /* Column on LHS of MATCH operator */
|
||||||
char **pzErrmsg = pConfig->pzErrmsg;
|
char **pzErrmsg = pConfig->pzErrmsg;
|
||||||
|
int i;
|
||||||
UNUSED_PARAM(zUnused);
|
int iIdxStr = 0;
|
||||||
UNUSED_PARAM(nVal);
|
Fts5Expr *pExpr = 0;
|
||||||
|
|
||||||
if( pCsr->ePlan ){
|
if( pCsr->ePlan ){
|
||||||
fts5FreeCursorComponents(pCsr);
|
fts5FreeCursorComponents(pCsr);
|
||||||
@@ -1165,23 +1197,60 @@ static int fts5FilterMethod(
|
|||||||
assert( pCsr->pRank==0 );
|
assert( pCsr->pRank==0 );
|
||||||
assert( pCsr->zRank==0 );
|
assert( pCsr->zRank==0 );
|
||||||
assert( pCsr->zRankArgs==0 );
|
assert( pCsr->zRankArgs==0 );
|
||||||
|
assert( pTab->pSortCsr==0 || nVal==0 );
|
||||||
|
|
||||||
assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
|
assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
|
||||||
pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
|
pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
|
||||||
|
|
||||||
/* Decode the arguments passed through to this function.
|
/* Decode the arguments passed through to this function. */
|
||||||
**
|
for(i=0; i<nVal; i++){
|
||||||
** Note: The following set of if(...) statements must be in the same
|
switch( idxStr[iIdxStr++] ){
|
||||||
** order as the corresponding entries in the struct at the top of
|
case 'r':
|
||||||
** fts5BestIndexMethod(). */
|
pRank = apVal[i];
|
||||||
if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++];
|
break;
|
||||||
if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++];
|
case 'm': {
|
||||||
if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
|
char *zText = sqlite3_value_text(apVal[i]);
|
||||||
if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
|
if( zText==0 ) zText = "";
|
||||||
if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
|
|
||||||
iCol = (idxNum>>16);
|
if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
|
||||||
assert( iCol>=0 && iCol<=pConfig->nCol );
|
iCol = 0;
|
||||||
assert( iVal==nVal );
|
do{
|
||||||
|
iCol = iCol*10 + (idxStr[iIdxStr]-'0');
|
||||||
|
iIdxStr++;
|
||||||
|
}while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
|
||||||
|
}else{
|
||||||
|
iCol = pConfig->nCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( zText[0]=='*' ){
|
||||||
|
/* The user has issued a query of the form "MATCH '*...'". This
|
||||||
|
** indicates that the MATCH expression is not a full text query,
|
||||||
|
** but a request for an internal parameter. */
|
||||||
|
rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
|
||||||
|
goto filter_out;
|
||||||
|
}else{
|
||||||
|
char **pzErr = &pTab->p.base.zErrMsg;
|
||||||
|
rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
|
||||||
|
pExpr = 0;
|
||||||
|
}
|
||||||
|
if( rc!=SQLITE_OK ) goto filter_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '=':
|
||||||
|
pRowidEq = apVal[i];
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
pRowidLe = apVal[i];
|
||||||
|
break;
|
||||||
|
default: assert( idxStr[iIdxStr-1]=='>' );
|
||||||
|
pRowidGe = apVal[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
|
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
|
||||||
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
|
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
|
||||||
|
|
||||||
@@ -1221,29 +1290,15 @@ static int fts5FilterMethod(
|
|||||||
pCsr->ePlan = FTS5_PLAN_SOURCE;
|
pCsr->ePlan = FTS5_PLAN_SOURCE;
|
||||||
pCsr->pExpr = pTab->pSortCsr->pExpr;
|
pCsr->pExpr = pTab->pSortCsr->pExpr;
|
||||||
rc = fts5CursorFirst(pTab, pCsr, bDesc);
|
rc = fts5CursorFirst(pTab, pCsr, bDesc);
|
||||||
}else if( pMatch ){
|
}else if( pCsr->pExpr ){
|
||||||
const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
|
|
||||||
if( zExpr==0 ) zExpr = "";
|
|
||||||
|
|
||||||
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
|
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( zExpr[0]=='*' ){
|
if( bOrderByRank ){
|
||||||
/* The user has issued a query of the form "MATCH '*...'". This
|
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
||||||
** indicates that the MATCH expression is not a full text query,
|
rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
|
||||||
** but a request for an internal parameter. */
|
|
||||||
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
|
|
||||||
}else{
|
}else{
|
||||||
char **pzErr = &pTab->p.base.zErrMsg;
|
pCsr->ePlan = FTS5_PLAN_MATCH;
|
||||||
rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
|
rc = fts5CursorFirst(pTab, pCsr, bDesc);
|
||||||
if( rc==SQLITE_OK ){
|
|
||||||
if( bOrderByRank ){
|
|
||||||
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
|
||||||
rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
|
|
||||||
}else{
|
|
||||||
pCsr->ePlan = FTS5_PLAN_MATCH;
|
|
||||||
rc = fts5CursorFirst(pTab, pCsr, bDesc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if( pConfig->zContent==0 ){
|
}else if( pConfig->zContent==0 ){
|
||||||
@@ -1260,7 +1315,7 @@ static int fts5FilterMethod(
|
|||||||
);
|
);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( pCsr->ePlan==FTS5_PLAN_ROWID ){
|
if( pCsr->ePlan==FTS5_PLAN_ROWID ){
|
||||||
sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
|
sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
|
||||||
}else{
|
}else{
|
||||||
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
|
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
|
||||||
sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
|
sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
|
||||||
@@ -1269,6 +1324,8 @@ static int fts5FilterMethod(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
filter_out:
|
||||||
|
sqlite3Fts5ExprFree(pExpr);
|
||||||
pConfig->pzErrmsg = pzErrmsg;
|
pConfig->pzErrmsg = pzErrmsg;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,5 +147,27 @@ do_faultsim_test 5.1 -faults oom* -body {
|
|||||||
faultsim_test_result {0 {1 4}}
|
faultsim_test_result {0 {1 4}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Test OOM injection in a query with two MATCH expressions
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 6.0 {
|
||||||
|
CREATE VIRTUAL TABLE t1 USING fts5(a);
|
||||||
|
INSERT INTO t1 VALUES('a b c d'); -- 1
|
||||||
|
INSERT INTO t1 VALUES('d a b c'); -- 2
|
||||||
|
INSERT INTO t1 VALUES('c d a b'); -- 3
|
||||||
|
INSERT INTO t1 VALUES('b c d a'); -- 4
|
||||||
|
}
|
||||||
|
do_faultsim_test 6.1 -faults oom* -body {
|
||||||
|
execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a' AND t1 MATCH 'b' }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {1 2 3 4}}
|
||||||
|
}
|
||||||
|
do_faultsim_test 6.2 -faults oom* -body {
|
||||||
|
execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a OR b' AND t1 MATCH 'c OR d' }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {1 2 3 4}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|||||||
99
ext/fts5/test/fts5multi.test
Normal file
99
ext/fts5/test/fts5multi.test
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
# 2014 September 13
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source code. In place of
|
||||||
|
# a legal notice, here is a blessing:
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#*************************************************************************
|
||||||
|
# This file implements regression tests for SQLite library. The
|
||||||
|
# focus of this script is testing the FTS5 module.
|
||||||
|
#
|
||||||
|
|
||||||
|
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||||
|
set testprefix fts5multi
|
||||||
|
|
||||||
|
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
|
||||||
|
ifcapable !fts5 {
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fts5_aux_test_functions db
|
||||||
|
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE VIRTUAL TABLE t1 USING fts5(a, b, c);
|
||||||
|
INSERT INTO t1 VALUES('gg bb bb' ,'gg ff gg' ,'ii ii');
|
||||||
|
INSERT INTO t1 VALUES('dd dd hh kk','jj' ,'aa');
|
||||||
|
INSERT INTO t1 VALUES('kk gg ee' ,'hh cc' ,'hh jj aa cc');
|
||||||
|
INSERT INTO t1 VALUES('hh' ,'bb jj cc' ,'kk ii');
|
||||||
|
INSERT INTO t1 VALUES('kk dd kk ii','aa ee aa' ,'ee');
|
||||||
|
INSERT INTO t1 VALUES('ee' ,'ff gg kk aa','ee ff ee');
|
||||||
|
INSERT INTO t1 VALUES('ff jj' ,'gg ee' ,'kk ee gg kk');
|
||||||
|
INSERT INTO t1 VALUES('ff ee dd hh','kk ee' ,'gg dd');
|
||||||
|
INSERT INTO t1 VALUES('bb' ,'aa' ,'bb aa');
|
||||||
|
INSERT INTO t1 VALUES('hh cc bb' ,'ff bb' ,'cc');
|
||||||
|
INSERT INTO t1 VALUES('jj' ,'ff dd bb aa','dd dd ff ff');
|
||||||
|
INSERT INTO t1 VALUES('ff dd gg dd','gg aa bb ff','cc');
|
||||||
|
INSERT INTO t1 VALUES('ff aa cc jj','kk' ,'ii dd');
|
||||||
|
INSERT INTO t1 VALUES('jj dd' ,'cc' ,'ii hh ee aa');
|
||||||
|
INSERT INTO t1 VALUES('ff ii hh' ,'dd' ,'gg');
|
||||||
|
INSERT INTO t1 VALUES('ff dd gg hh','hh' ,'ff dd');
|
||||||
|
INSERT INTO t1 VALUES('cc cc' ,'ff dd ff' ,'bb');
|
||||||
|
INSERT INTO t1 VALUES('ii' ,'bb ii' ,'jj kk');
|
||||||
|
INSERT INTO t1 VALUES('ff hh' ,'hh bb' ,'bb dd ee');
|
||||||
|
INSERT INTO t1 VALUES('jj kk' ,'jj' ,'gg ff cc');
|
||||||
|
INSERT INTO t1 VALUES('dd kk' ,'ii gg' ,'dd');
|
||||||
|
INSERT INTO t1 VALUES('cc' ,'aa ff' ,'ii');
|
||||||
|
INSERT INTO t1 VALUES('bb ff bb ii','bb kk bb aa','hh ff ii dd');
|
||||||
|
INSERT INTO t1 VALUES('aa' ,'ee bb jj jj','dd');
|
||||||
|
INSERT INTO t1 VALUES('kk dd cc' ,'aa jj' ,'ee aa ff');
|
||||||
|
INSERT INTO t1 VALUES('aa gg aa' ,'jj' ,'ii kk hh gg');
|
||||||
|
INSERT INTO t1 VALUES('ff hh aa' ,'jj ii' ,'hh dd bb jj');
|
||||||
|
INSERT INTO t1 VALUES('hh' ,'aa gg kk' ,'bb ee');
|
||||||
|
INSERT INTO t1 VALUES('bb' ,'ee' ,'gg');
|
||||||
|
INSERT INTO t1 VALUES('dd kk' ,'kk bb aa' ,'ee');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach {tn c1 e1 c2 e2} {
|
||||||
|
1 t1 aa t1 bb
|
||||||
|
2 a aa b bb
|
||||||
|
3 a "aa OR bb OR cc" b "jj OR ii OR hh"
|
||||||
|
4 t1 "aa AND bb" t1 "cc"
|
||||||
|
5 c "kk" b "aa OR bb OR cc OR dd OR ee"
|
||||||
|
} {
|
||||||
|
if {$c1=="t1"} {
|
||||||
|
set lhs "( $e1 )"
|
||||||
|
} else {
|
||||||
|
set lhs "$c1 : ( $e1 )"
|
||||||
|
}
|
||||||
|
if {$c2=="t1"} {
|
||||||
|
set rhs "( $e2 )"
|
||||||
|
} else {
|
||||||
|
set rhs "$c2 : ( $e2 )"
|
||||||
|
}
|
||||||
|
|
||||||
|
set q1 "t1 MATCH '($lhs) AND ($rhs)'"
|
||||||
|
set q2 "$c1 MATCH '$e1' AND $c2 MATCH '$e2'"
|
||||||
|
|
||||||
|
set ret [execsql "SELECT rowid FROM t1 WHERE $q1"]
|
||||||
|
set N [llength $ret]
|
||||||
|
do_execsql_test 1.$tn.1.($N) "SELECT rowid FROM t1 WHERE $q2" $ret
|
||||||
|
|
||||||
|
set ret [execsql "SELECT fts5_test_poslist(t1) FROM t1 WHERE $q1"]
|
||||||
|
do_execsql_test 1.$tn.2.($N) "
|
||||||
|
SELECT fts5_test_poslist(t1) FROM t1 WHERE $q2
|
||||||
|
" $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
do_catchsql_test 2.1.1 {
|
||||||
|
SELECT rowid FROM t1 WHERE t1 MATCH '(NOT' AND t1 MATCH 'aa bb';
|
||||||
|
} {1 {fts5: syntax error near "NOT"}}
|
||||||
|
do_catchsql_test 2.1.2 {
|
||||||
|
SELECT rowid FROM t1 WHERE t1 MATCH 'aa bb' AND t1 MATCH '(NOT';
|
||||||
|
} {1 {fts5: syntax error near "NOT"}}
|
||||||
|
|
||||||
|
finish_test
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ do_eqp_test 1.1 {
|
|||||||
} {
|
} {
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
|--SCAN TABLE t1
|
|--SCAN TABLE t1
|
||||||
`--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
|
`--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m
|
||||||
}
|
}
|
||||||
|
|
||||||
do_eqp_test 1.2 {
|
do_eqp_test 1.2 {
|
||||||
@@ -46,7 +46,7 @@ do_eqp_test 1.3 {
|
|||||||
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
|
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
|
||||||
} {
|
} {
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
|
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m
|
||||||
`--USE TEMP B-TREE FOR ORDER BY
|
`--USE TEMP B-TREE FOR ORDER BY
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +60,6 @@ do_eqp_test 1.4 {
|
|||||||
|
|
||||||
do_eqp_test 1.5 {
|
do_eqp_test 1.5 {
|
||||||
SELECT * FROM f1 WHERE rank MATCH ?
|
SELECT * FROM f1 WHERE rank MATCH ?
|
||||||
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:}
|
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|||||||
@@ -467,4 +467,17 @@ do_execsql_test 21.3 {
|
|||||||
SELECT rowid FROM x1($doc);
|
SELECT rowid FROM x1($doc);
|
||||||
} {11112}
|
} {11112}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 22.0 {
|
||||||
|
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||||
|
INSERT INTO x1(x) VALUES('a b c');
|
||||||
|
INSERT INTO x1(x) VALUES('x y z');
|
||||||
|
INSERT INTO x1(x) VALUES('c b a');
|
||||||
|
INSERT INTO x1(x) VALUES('z y x');
|
||||||
|
}
|
||||||
|
|
||||||
|
do_catchsql_test 22.1 {SELECT * FROM x1('')} {1 {fts5: syntax error near ""}}
|
||||||
|
do_catchsql_test 22.2 {SELECT * FROM x1(NULL)} {1 {fts5: syntax error near ""}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|||||||
27
manifest
27
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\stypo\sfor\sone\sinstance\sof\sline\snumber\shandling\sin\sthe\sLemon\stool.
|
C Allow\sfts5\sto\sfilter\son\smultiple\sMATCH\sclauses\sin\sa\ssingle\sscan.
|
||||||
D 2019-09-11T15:25:26.595
|
D 2019-09-12T19:38:40.141
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@@ -110,14 +110,14 @@ F ext/fts3/unicode/mkunicode.tcl bf7fcaa6d68e6d38223467983785d054f1cff4d9e3905dd
|
|||||||
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
|
||||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||||
F ext/fts5/fts5.h 7c9da96f2b9dcfa4dd94081fb2d87ec418d8cdb35b25df56756c334b6b558fd7
|
F ext/fts5/fts5.h 7c9da96f2b9dcfa4dd94081fb2d87ec418d8cdb35b25df56756c334b6b558fd7
|
||||||
F ext/fts5/fts5Int.h d87fb17d12296613cdec2d1f4213ecd8840d3deb34837b6d3889b830d06baac4
|
F ext/fts5/fts5Int.h 0ec19a906a54c0e53f8a380c0ff70f11a866aa259490bc13aa39f8d2491800fd
|
||||||
F ext/fts5/fts5_aux.c dcc627d8b6e3fc773db528ff67b39955dab7b51628f9dba8e15849e5bedfd7fa
|
F ext/fts5/fts5_aux.c dcc627d8b6e3fc773db528ff67b39955dab7b51628f9dba8e15849e5bedfd7fa
|
||||||
F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70
|
F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70
|
||||||
F ext/fts5/fts5_config.c d7523cba5e66da077233c023aecbc3e6a37978ff75a18131c5ab5b1229d5bac7
|
F ext/fts5/fts5_config.c 606a29f2962a8f4508923e6ad833974b32a3ab4093f63fd6de0fb33a87eed54c
|
||||||
F ext/fts5/fts5_expr.c 840c88d55e78083a5e61a35968df877712ae28791b347eced1e98e3b337d2d3c
|
F ext/fts5/fts5_expr.c 5661fe64f4f5a499710df9561075de84b743f01e808af46df4130a9ec343a0fd
|
||||||
F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75
|
F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75
|
||||||
F ext/fts5/fts5_index.c b062bdb836e195656aac8d6684e943585cff4bf7d7c593c80cb67c3b6cfef7ee
|
F ext/fts5/fts5_index.c b062bdb836e195656aac8d6684e943585cff4bf7d7c593c80cb67c3b6cfef7ee
|
||||||
F ext/fts5/fts5_main.c 15dc14ea594ff2ea183f5e79c8f6fea14640ac7c4bd5d93ad1d506a4db80c998
|
F ext/fts5/fts5_main.c e6db945454a0dae2dafcf29905d7d5272b64b00da34a43bd4ce732e2079a159d
|
||||||
F ext/fts5/fts5_storage.c 801b4e3cd33786a60a07b6b01f86d0fbdf7e68325054e08d17176293a8081e99
|
F ext/fts5/fts5_storage.c 801b4e3cd33786a60a07b6b01f86d0fbdf7e68325054e08d17176293a8081e99
|
||||||
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
|
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
|
||||||
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee
|
||||||
@@ -176,7 +176,7 @@ F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd1640
|
|||||||
F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2
|
F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2
|
||||||
F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119
|
F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119
|
||||||
F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
|
F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c
|
||||||
F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e
|
F ext/fts5/test/fts5faultB.test d606bdb8e81aaeb6f41de3fc9fc7ae315733f0903fbff05cf54f5b045b729ab5
|
||||||
F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
|
F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
|
||||||
F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079
|
F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079
|
||||||
F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2
|
F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2
|
||||||
@@ -190,12 +190,13 @@ F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8
|
|||||||
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
|
F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6
|
||||||
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
|
||||||
F ext/fts5/test/fts5misc.test 5becd134b66f7370042968a2b127b92ea7748e249f16cb6a996f450812e89eec
|
F ext/fts5/test/fts5misc.test 5becd134b66f7370042968a2b127b92ea7748e249f16cb6a996f450812e89eec
|
||||||
|
F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
|
||||||
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
|
F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
|
||||||
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
|
F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd
|
||||||
F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
|
F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
|
||||||
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
|
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
|
||||||
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
|
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
|
||||||
F ext/fts5/test/fts5plan.test 00dc4c974938b509db7cb3680407f068ee6e9cc824f492f68cb741a7b679fe41
|
F ext/fts5/test/fts5plan.test 771b999d161e24fd803ce0290adb7c6e7c9b9cc2c6a0adb344813fb89473aa32
|
||||||
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
|
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
|
||||||
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
|
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
|
||||||
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
|
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
|
||||||
@@ -204,7 +205,7 @@ F ext/fts5/test/fts5rank.test c9fd4a1e36b4fa92d572ec13d846469b97da249d1c2f7fd3ee
|
|||||||
F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7
|
F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7
|
||||||
F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415
|
F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415
|
||||||
F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff171013003d8297203a20ad6
|
F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff171013003d8297203a20ad6
|
||||||
F ext/fts5/test/fts5simple.test 313ad28ef38ebe25f0a1673dd18f2fac446e25feb15bbb0c223a65ea00594f72
|
F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b
|
||||||
F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
|
F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0
|
||||||
F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
|
F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f
|
||||||
F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb
|
F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb
|
||||||
@@ -1841,7 +1842,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P a97804620a27acc30bebd2aaa04e38f2f36de48b0931038ca8bdc9cb0c36b8f4
|
P 980be1730dc1239c63a107923bf2e32b4ec7d4bc31b9190e711cc35f18cc2bb4
|
||||||
R 5065e0b2c7f4ffc5b218b4bab44bb95f
|
R f455101857a1853760c9098b8cd2af2d
|
||||||
U mistachkin
|
U dan
|
||||||
Z 05d39d001f8aeefdace9f8a8f5ba54b9
|
Z 191c94e283a8422844a9aa5307aa3f27
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
980be1730dc1239c63a107923bf2e32b4ec7d4bc31b9190e711cc35f18cc2bb4
|
9d418a7a491761eeb38a70898677a493e2631e5d62e75ee88431f52d3dfd2344
|
||||||
Reference in New Issue
Block a user