Add hidden column "rank". Currently this always returns the same value as the bm25() function.
FossilOrigin-Name: 4cc048c3651e830a6aeded924c7f3a60b634e133
This commit is contained in:
+231
-77
@@ -56,6 +56,7 @@ struct Fts5Table {
|
||||
Fts5Index *pIndex; /* Full-text index */
|
||||
Fts5Storage *pStorage; /* Document store */
|
||||
Fts5Global *pGlobal; /* Global (connection wide) data */
|
||||
Fts5Cursor *pSortCsr; /* Sort data from this cursor */
|
||||
};
|
||||
|
||||
struct Fts5MatchPhrase {
|
||||
@@ -63,6 +64,20 @@ struct Fts5MatchPhrase {
|
||||
int nTerm; /* Size of phrase in terms */
|
||||
};
|
||||
|
||||
/*
|
||||
** Variable pStmt is set to a compiled SQL statement of the form:
|
||||
**
|
||||
** SELECT rowid, <fts> FROM <fts> ORDER BY +rank;
|
||||
**
|
||||
*/
|
||||
struct Fts5Sorter {
|
||||
sqlite3_stmt *pStmt;
|
||||
i64 iRowid; /* Current rowid */
|
||||
u8 *aPoslist; /* Position lists for current row */
|
||||
int nIdx; /* Number of entries in aIdx[] */
|
||||
int aIdx[0]; /* Offsets into aPoslist for current row */
|
||||
};
|
||||
|
||||
/*
|
||||
** Virtual-table cursor object.
|
||||
*/
|
||||
@@ -71,13 +86,15 @@ struct Fts5Cursor {
|
||||
int idxNum; /* idxNum passed to xFilter() */
|
||||
sqlite3_stmt *pStmt; /* Statement used to read %_content */
|
||||
Fts5Expr *pExpr; /* Expression for MATCH queries */
|
||||
Fts5Sorter *pSorter; /* Sorter for "ORDER BY rank" queries */
|
||||
int csrflags; /* Mask of cursor flags (see below) */
|
||||
Fts5Cursor *pNext; /* Next cursor in Fts5Cursor.pCsr list */
|
||||
Fts5Auxiliary *pRank; /* Rank callback (or NULL) */
|
||||
|
||||
/* Variables used by auxiliary functions */
|
||||
i64 iCsrId; /* Cursor id */
|
||||
Fts5Auxiliary *pAux; /* Currently executing extension function */
|
||||
Fts5Auxdata *pAuxdata; /* First in linked list of aux-data */
|
||||
Fts5Auxdata *pAuxdata; /* First in linked list of saved aux-data */
|
||||
int *aColumnSize; /* Values for xColumnSize() */
|
||||
};
|
||||
|
||||
@@ -227,9 +244,11 @@ static int fts5CreateMethod(
|
||||
/*
|
||||
** The three query plans xBestIndex may choose between.
|
||||
*/
|
||||
#define FTS5_PLAN_SCAN 1 /* No usable constraint */
|
||||
#define FTS5_PLAN_MATCH 2 /* (<tbl> MATCH ?) */
|
||||
#define FTS5_PLAN_ROWID 3 /* (rowid = ?) */
|
||||
#define FTS5_PLAN_SCAN 1 /* No usable constraint */
|
||||
#define FTS5_PLAN_MATCH 2 /* (<tbl> MATCH ?) */
|
||||
#define FTS5_PLAN_SORTED_MATCH 3 /* (<tbl> MATCH ? ORDER BY rank) */
|
||||
#define FTS5_PLAN_ROWID 4 /* (rowid = ?) */
|
||||
#define FTS5_PLAN_SOURCE 5 /* A source cursor for SORTED_MATCH */
|
||||
|
||||
#define FTS5_PLAN(idxNum) ((idxNum) & 0x7)
|
||||
|
||||
@@ -284,9 +303,20 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
pInfo->estimatedCost = 10000000.0;
|
||||
}
|
||||
|
||||
if( pInfo->nOrderBy==1 && pInfo->aOrderBy[0].iColumn<0 ){
|
||||
pInfo->orderByConsumed = 1;
|
||||
ePlan |= pInfo->aOrderBy[0].desc ? FTS5_ORDER_DESC : FTS5_ORDER_ASC;
|
||||
if( pInfo->nOrderBy==1 ){
|
||||
int iSort = pInfo->aOrderBy[0].iColumn;
|
||||
if( iSort<0 ){
|
||||
/* ORDER BY rowid [ASC|DESC] */
|
||||
pInfo->orderByConsumed = 1;
|
||||
}else if( iSort==(pConfig->nCol+1) && ePlan==FTS5_PLAN_MATCH ){
|
||||
/* ORDER BY rank [ASC|DESC] */
|
||||
pInfo->orderByConsumed = 1;
|
||||
ePlan = FTS5_PLAN_SORTED_MATCH;
|
||||
}
|
||||
|
||||
if( pInfo->orderByConsumed ){
|
||||
ePlan |= pInfo->aOrderBy[0].desc ? FTS5_ORDER_DESC : FTS5_ORDER_ASC;
|
||||
}
|
||||
}
|
||||
|
||||
pInfo->idxNum = ePlan;
|
||||
@@ -341,7 +371,15 @@ static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
|
||||
int eStmt = fts5StmtType(pCsr->idxNum);
|
||||
sqlite3Fts5StorageStmtRelease(pTab->pStorage, eStmt, pCsr->pStmt);
|
||||
}
|
||||
sqlite3Fts5ExprFree(pCsr->pExpr);
|
||||
if( pCsr->pSorter ){
|
||||
Fts5Sorter *pSorter = pCsr->pSorter;
|
||||
sqlite3_finalize(pSorter->pStmt);
|
||||
sqlite3_free(pSorter);
|
||||
}
|
||||
|
||||
if( pCsr->idxNum!=FTS5_PLAN_SOURCE ){
|
||||
sqlite3Fts5ExprFree(pCsr->pExpr);
|
||||
}
|
||||
|
||||
for(pData=pCsr->pAuxdata; pData; pData=pNext){
|
||||
pNext = pData->pNext;
|
||||
@@ -357,6 +395,21 @@ static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int fts5SorterNext(Fts5Cursor *pCsr){
|
||||
Fts5Sorter *pSorter = pCsr->pSorter;
|
||||
int rc;
|
||||
|
||||
rc = sqlite3_step(pSorter->pStmt);
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
||||
}else if( rc==SQLITE_ROW ){
|
||||
rc = SQLITE_OK;
|
||||
pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the cursor to the next row in the table that matches the
|
||||
@@ -371,25 +424,77 @@ static int fts5NextMethod(sqlite3_vtab_cursor *pCursor){
|
||||
int ePlan = FTS5_PLAN(pCsr->idxNum);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( ePlan!=FTS5_PLAN_MATCH ){
|
||||
rc = sqlite3_step(pCsr->pStmt);
|
||||
if( rc!=SQLITE_ROW ){
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
||||
rc = sqlite3_reset(pCsr->pStmt);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
switch( ePlan ){
|
||||
case FTS5_PLAN_MATCH:
|
||||
case FTS5_PLAN_SOURCE:
|
||||
rc = sqlite3Fts5ExprNext(pCsr->pExpr);
|
||||
if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
||||
}
|
||||
CsrFlagSet(pCsr, FTS5CSR_REQUIRE_CONTENT | FTS5CSR_REQUIRE_DOCSIZE );
|
||||
break;
|
||||
|
||||
case FTS5_PLAN_SORTED_MATCH: {
|
||||
rc = fts5SorterNext(pCsr);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
rc = sqlite3Fts5ExprNext(pCsr->pExpr);
|
||||
if( sqlite3Fts5ExprEof(pCsr->pExpr) ){
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
||||
}
|
||||
CsrFlagSet(pCsr, FTS5CSR_REQUIRE_CONTENT | FTS5CSR_REQUIRE_DOCSIZE );
|
||||
|
||||
default:
|
||||
rc = sqlite3_step(pCsr->pStmt);
|
||||
if( rc!=SQLITE_ROW ){
|
||||
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
||||
rc = sqlite3_reset(pCsr->pStmt);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bAsc){
|
||||
Fts5Config *pConfig = pTab->pConfig;
|
||||
Fts5Sorter *pSorter;
|
||||
int nPhrase;
|
||||
int nByte;
|
||||
int rc = SQLITE_OK;
|
||||
char *zSql;
|
||||
|
||||
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
|
||||
nByte = sizeof(Fts5Sorter) + sizeof(int) * nPhrase;
|
||||
pSorter = (Fts5Sorter*)sqlite3_malloc(nByte);
|
||||
if( pSorter==0 ) return SQLITE_NOMEM;
|
||||
memset(pSorter, 0, nByte);
|
||||
|
||||
zSql = sqlite3_mprintf("SELECT rowid, %Q FROM %Q.%Q ORDER BY +%s %s",
|
||||
pConfig->zName, pConfig->zDb, pConfig->zName, FTS5_RANK_NAME,
|
||||
bAsc ? "ASC" : "DESC"
|
||||
);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pSorter->pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
pCsr->pSorter = pSorter;
|
||||
if( rc==SQLITE_OK ){
|
||||
assert( pTab->pSortCsr==0 );
|
||||
pTab->pSortCsr = pCsr;
|
||||
rc = fts5SorterNext(pCsr);
|
||||
pTab->pSortCsr = 0;
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_finalize(pSorter->pStmt);
|
||||
sqlite3_free(pSorter);
|
||||
pCsr->pSorter = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fts5CursorFirst(Fts5Table *pTab, Fts5Cursor *pCsr, int bAsc){
|
||||
int rc;
|
||||
rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->pIndex, bAsc);
|
||||
@@ -414,30 +519,43 @@ static int fts5FilterMethod(
|
||||
){
|
||||
Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
|
||||
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
|
||||
int rc = SQLITE_OK;
|
||||
int ePlan = FTS5_PLAN(idxNum);
|
||||
int eStmt = fts5StmtType(idxNum);
|
||||
int bAsc = ((idxNum & FTS5_ORDER_ASC) ? 1 : 0);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
pCsr->idxNum = idxNum;
|
||||
assert( pCsr->pStmt==0 );
|
||||
assert( pCsr->pExpr==0 );
|
||||
assert( pCsr->csrflags==0 );
|
||||
assert( pCsr->pRank==0 );
|
||||
|
||||
rc = sqlite3Fts5StorageStmt(pTab->pStorage, eStmt, &pCsr->pStmt);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ePlan==FTS5_PLAN_MATCH ){
|
||||
char **pzErr = &pTab->base.zErrMsg;
|
||||
const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
|
||||
rc = sqlite3Fts5ExprNew(pTab->pConfig, zExpr, &pCsr->pExpr, pzErr);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5CursorFirst(pTab, pCsr, bAsc);
|
||||
if( pTab->pSortCsr ){
|
||||
pCsr->idxNum = FTS5_PLAN_SOURCE;
|
||||
pCsr->pRank = pTab->pSortCsr->pRank;
|
||||
pCsr->pExpr = pTab->pSortCsr->pExpr;
|
||||
rc = fts5CursorFirst(pTab, pCsr, bAsc);
|
||||
}else{
|
||||
int ePlan = FTS5_PLAN(idxNum);
|
||||
int eStmt = fts5StmtType(idxNum);
|
||||
pCsr->idxNum = idxNum;
|
||||
rc = sqlite3Fts5StorageStmt(pTab->pStorage, eStmt, &pCsr->pStmt);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ePlan==FTS5_PLAN_MATCH || ePlan==FTS5_PLAN_SORTED_MATCH ){
|
||||
char **pzErr = &pTab->base.zErrMsg;
|
||||
const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
|
||||
pCsr->pRank = pTab->pGlobal->pAux;
|
||||
rc = sqlite3Fts5ExprNew(pTab->pConfig, zExpr, &pCsr->pExpr, pzErr);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( ePlan==FTS5_PLAN_MATCH ){
|
||||
rc = fts5CursorFirst(pTab, pCsr, bAsc);
|
||||
}else{
|
||||
rc = fts5CursorFirstSorted(pTab, pCsr, bAsc);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( ePlan==FTS5_PLAN_ROWID ){
|
||||
sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
|
||||
}
|
||||
rc = fts5NextMethod(pCursor);
|
||||
}
|
||||
}else{
|
||||
if( ePlan==FTS5_PLAN_ROWID ){
|
||||
sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
|
||||
}
|
||||
rc = fts5NextMethod(pCursor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,10 +582,19 @@ static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
|
||||
int ePlan = FTS5_PLAN(pCsr->idxNum);
|
||||
|
||||
assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
|
||||
if( ePlan!=FTS5_PLAN_MATCH ){
|
||||
*pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
|
||||
}else{
|
||||
*pRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
|
||||
switch( ePlan ){
|
||||
case FTS5_PLAN_SOURCE:
|
||||
case FTS5_PLAN_MATCH:
|
||||
*pRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
|
||||
break;
|
||||
|
||||
case FTS5_PLAN_SORTED_MATCH:
|
||||
*pRowid = pCsr->pSorter->iRowid;
|
||||
break;
|
||||
|
||||
default:
|
||||
*pRowid = sqlite3_column_int64(pCsr->pStmt, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
@@ -497,36 +624,6 @@ static int fts5SeekCursor(Fts5Cursor *pCsr){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the xColumn method, called by SQLite to request a value from
|
||||
** the row that the supplied cursor currently points to.
|
||||
*/
|
||||
static int fts5ColumnMethod(
|
||||
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
|
||||
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
|
||||
int iCol /* Index of column to read value from */
|
||||
){
|
||||
Fts5Config *pConfig = ((Fts5Table*)(pCursor->pVtab))->pConfig;
|
||||
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
|
||||
|
||||
if( iCol==pConfig->nCol ){
|
||||
/* User is requesting the value of the special column with the same name
|
||||
** as the table. Return the cursor integer id number. This value is only
|
||||
** useful in that it may be passed as the first argument to an FTS5
|
||||
** auxiliary function. */
|
||||
sqlite3_result_int64(pCtx, pCsr->iCsrId);
|
||||
}else{
|
||||
rc = fts5SeekCursor(pCsr);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is called to handle an FTS INSERT command. In other words,
|
||||
** an INSERT statement of the form:
|
||||
@@ -573,7 +670,15 @@ static int fts5UpdateMethod(
|
||||
int eConflict; /* ON CONFLICT for this DML */
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
|
||||
assert( nArg==1 || nArg==(2 + pConfig->nCol + 1) );
|
||||
/* A delete specifies a single argument - the rowid of the row to remove.
|
||||
** Update and insert operations pass:
|
||||
**
|
||||
** 1. The "old" rowid, or NULL.
|
||||
** 2. The "new" rowid.
|
||||
** 3. Values for each of the nCol matchable columns.
|
||||
** 4. Values for the two hidden columns (<tablename> and "rank").
|
||||
*/
|
||||
assert( nArg==1 || nArg==(2 + pConfig->nCol + 2) );
|
||||
|
||||
if( nArg>1 && SQLITE_NULL!=sqlite3_value_type(apVal[2 + pConfig->nCol]) ){
|
||||
return fts5SpecialCommand(pTab, apVal[2 + pConfig->nCol]);
|
||||
@@ -840,6 +945,19 @@ static int fts5ApiQueryPhrase(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void fts5ApiInvoke(
|
||||
Fts5Auxiliary *pAux,
|
||||
Fts5Cursor *pCsr,
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
assert( pCsr->pAux==0 );
|
||||
pCsr->pAux = pAux;
|
||||
pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
|
||||
pCsr->pAux = 0;
|
||||
}
|
||||
|
||||
static void fts5ApiCallback(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
@@ -861,13 +979,49 @@ static void fts5ApiCallback(
|
||||
char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
}else{
|
||||
assert( pCsr->pAux==0 );
|
||||
pCsr->pAux = pAux;
|
||||
pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc-1, &argv[1]);
|
||||
pCsr->pAux = 0;
|
||||
fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the xColumn method, called by SQLite to request a value from
|
||||
** the row that the supplied cursor currently points to.
|
||||
*/
|
||||
static int fts5ColumnMethod(
|
||||
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
|
||||
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
|
||||
int iCol /* Index of column to read value from */
|
||||
){
|
||||
Fts5Config *pConfig = ((Fts5Table*)(pCursor->pVtab))->pConfig;
|
||||
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
assert( CsrFlagTest(pCsr, FTS5CSR_EOF)==0 );
|
||||
|
||||
if( iCol==pConfig->nCol ){
|
||||
if( FTS5_PLAN(pCsr->idxNum)==FTS5_PLAN_SOURCE ){
|
||||
/* todo */
|
||||
}else{
|
||||
/* User is requesting the value of the special column with the same name
|
||||
** as the table. Return the cursor integer id number. This value is only
|
||||
** useful in that it may be passed as the first argument to an FTS5
|
||||
** auxiliary function. */
|
||||
sqlite3_result_int64(pCtx, pCsr->iCsrId);
|
||||
}
|
||||
}else if( iCol==pConfig->nCol+1 ){
|
||||
/* The value of the "rank" column. */
|
||||
if( pCsr->pRank ){
|
||||
fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, 0, 0);
|
||||
}
|
||||
}else{
|
||||
rc = fts5SeekCursor(pCsr);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This routine implements the xFindFunction method for the FTS3
|
||||
|
||||
+15
-2
@@ -28,6 +28,9 @@
|
||||
|
||||
#define FTS5_DEFAULT_NEARDIST 10
|
||||
|
||||
/* Name of rank column */
|
||||
#define FTS5_RANK_NAME "rank"
|
||||
|
||||
/**************************************************************************
|
||||
** Interface to code in fts5_config.c. fts5_config.c contains contains code
|
||||
** to parse the arguments passed to the CREATE VIRTUAL TABLE statement.
|
||||
@@ -394,7 +397,6 @@ void sqlite3Fts5ParseSetColumn(Fts5Parse*, Fts5ExprNearset*, Fts5Token*);
|
||||
void sqlite3Fts5ParseFinished(Fts5Parse *pParse, Fts5ExprNode *p);
|
||||
void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token*);
|
||||
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5_expr.c.
|
||||
**************************************************************************/
|
||||
@@ -423,7 +425,18 @@ int sqlite3Fts5CreateAux(
|
||||
|
||||
int sqlite3Fts5AuxInit(Fts5Global*);
|
||||
/*
|
||||
** End of interface to code in fts5_expr.c.
|
||||
** End of interface to code in fts5_aux.c.
|
||||
**************************************************************************/
|
||||
|
||||
/**************************************************************************
|
||||
** Interface to code in fts5_sorter.c.
|
||||
*/
|
||||
typedef struct Fts5Sorter Fts5Sorter;
|
||||
|
||||
int sqlite3Fts5SorterNew(Fts5Expr *pExpr, Fts5Sorter **pp);
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5_sorter.c.
|
||||
**************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -956,10 +956,10 @@ int sqlite3Fts5AuxInit(Fts5Global *pGlobal){
|
||||
fts5_extension_function xFunc;/* Callback function */
|
||||
void (*xDestroy)(void*); /* Destructor function */
|
||||
} aBuiltin [] = {
|
||||
{ "bm25", 0, fts5Bm25Function, 0 },
|
||||
{ "bm25debug", (void*)1, fts5Bm25Function, 0 },
|
||||
{ "snippet", 0, fts5SnippetFunction, 0 },
|
||||
{ "fts5_test", 0, fts5TestFunction, 0 },
|
||||
{ "bm25", 0, fts5Bm25Function, 0 },
|
||||
};
|
||||
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
|
||||
+13
-3
@@ -165,7 +165,10 @@ int sqlite3Fts5ConfigParse(
|
||||
pRet->azCol = (char**)sqlite3_malloc(sizeof(char*) * nArg);
|
||||
pRet->zDb = fts5Strdup(azArg[1]);
|
||||
pRet->zName = fts5Strdup(azArg[2]);
|
||||
if( pRet->azCol==0 || pRet->zDb==0 || pRet->zName==0 ){
|
||||
if( sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){
|
||||
*pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName);
|
||||
rc = SQLITE_ERROR;
|
||||
}else if( pRet->azCol==0 || pRet->zDb==0 || pRet->zName==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
int i;
|
||||
@@ -189,10 +192,15 @@ int sqlite3Fts5ConfigParse(
|
||||
}
|
||||
}
|
||||
|
||||
/* If it is not a special directive, it must be a column name */
|
||||
/* If it is not a special directive, it must be a column name. In
|
||||
** this case, check that it is not the reserved column name "rank". */
|
||||
if( zDup ){
|
||||
sqlite3Fts5Dequote(zDup);
|
||||
pRet->azCol[pRet->nCol++] = zDup;
|
||||
if( sqlite3_stricmp(zDup, FTS5_RANK_NAME)==0 ){
|
||||
*pzErr = sqlite3_mprintf("reserved fts5 column name: %s", zDup);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,7 +257,9 @@ int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig){
|
||||
|
||||
if( zSql ){
|
||||
zOld = zSql;
|
||||
zSql = sqlite3_mprintf("%s, %Q HIDDEN)", zOld, pConfig->zName);
|
||||
zSql = sqlite3_mprintf("%s, %Q HIDDEN, %s HIDDEN)",
|
||||
zOld, pConfig->zName, FTS5_RANK_NAME
|
||||
);
|
||||
sqlite3_free(zOld);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ struct Fts5Expr {
|
||||
Fts5ExprNode *pRoot;
|
||||
int bAsc;
|
||||
int nPhrase; /* Number of phrases in expression */
|
||||
Fts5ExprPhrase **apPhrase; /* Pointers to phrase objects */
|
||||
Fts5ExprPhrase **apExprPhrase; /* Pointers to phrase objects */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -216,7 +216,7 @@ int sqlite3Fts5ExprNew(
|
||||
}else{
|
||||
pNew->pRoot = sParse.pExpr;
|
||||
pNew->pIndex = 0;
|
||||
pNew->apPhrase = sParse.apPhrase;
|
||||
pNew->apExprPhrase = sParse.apPhrase;
|
||||
pNew->nPhrase = sParse.nPhrase;
|
||||
sParse.apPhrase = 0;
|
||||
}
|
||||
@@ -275,7 +275,7 @@ int sqlite3Fts5ExprPhraseExpr(
|
||||
Fts5ExprNearset *pNear;
|
||||
Fts5ExprPhrase *pCopy;
|
||||
|
||||
pOrig = pExpr->apPhrase[iPhrase];
|
||||
pOrig = pExpr->apExprPhrase[iPhrase];
|
||||
pNew = (Fts5Expr*)fts5ExprMalloc(&rc, sizeof(Fts5Expr));
|
||||
apPhrase = (Fts5ExprPhrase**)fts5ExprMalloc(&rc, sizeof(Fts5ExprPhrase*));
|
||||
pNode = (Fts5ExprNode*)fts5ExprMalloc(&rc, sizeof(Fts5ExprNode));
|
||||
@@ -296,8 +296,8 @@ int sqlite3Fts5ExprPhraseExpr(
|
||||
pNew->pIndex = pExpr->pIndex;
|
||||
pNew->pRoot = pNode;
|
||||
pNew->nPhrase = 1;
|
||||
pNew->apPhrase = apPhrase;
|
||||
pNew->apPhrase[0] = pCopy;
|
||||
pNew->apExprPhrase = apPhrase;
|
||||
pNew->apExprPhrase[0] = pCopy;
|
||||
|
||||
pNode->eType = FTS5_STRING;
|
||||
pNode->pNear = pNear;
|
||||
@@ -345,7 +345,7 @@ void sqlite3Fts5ParseNodeFree(Fts5ExprNode *p){
|
||||
void sqlite3Fts5ExprFree(Fts5Expr *p){
|
||||
if( p ){
|
||||
sqlite3Fts5ParseNodeFree(p->pRoot);
|
||||
sqlite3_free(p->apPhrase);
|
||||
sqlite3_free(p->apExprPhrase);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
}
|
||||
@@ -1588,7 +1588,7 @@ int sqlite3Fts5ExprPhraseCount(Fts5Expr *pExpr){
|
||||
*/
|
||||
int sqlite3Fts5ExprPhraseSize(Fts5Expr *pExpr, int iPhrase){
|
||||
if( iPhrase<0 || iPhrase>=pExpr->nPhrase ) return 0;
|
||||
return pExpr->apPhrase[iPhrase]->nTerm;
|
||||
return pExpr->apExprPhrase[iPhrase]->nTerm;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1597,7 +1597,7 @@ int sqlite3Fts5ExprPhraseSize(Fts5Expr *pExpr, int iPhrase){
|
||||
*/
|
||||
int sqlite3Fts5ExprPoslist(Fts5Expr *pExpr, int iPhrase, const u8 **pa){
|
||||
if( iPhrase>=0 && iPhrase<pExpr->nPhrase ){
|
||||
Fts5ExprPhrase *pPhrase = pExpr->apPhrase[iPhrase];
|
||||
Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase];
|
||||
Fts5ExprNode *pNode = pPhrase->pNode;
|
||||
if( pNode->bEof==0 && pNode->iRowid==pExpr->pRoot->iRowid ){
|
||||
*pa = pPhrase->poslist.p;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Add\sthe\s"loadfts"\sprogram,\sfor\sperformance\stesting\sthe\sloading\sof\sdata\sinto\sfts3/fts4/fts5\stables.
|
||||
D 2014-07-28T20:14:02.001
|
||||
C Add\shidden\scolumn\s"rank".\sCurrently\sthis\salways\sreturns\sthe\ssame\svalue\sas\sthe\sbm25()\sfunction.
|
||||
D 2014-07-30T19:41:58.841
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in b03432313a3aad96c706f8164fb9f5307eaf19f5
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -103,13 +103,13 @@ F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl dc6f268eb526710e2c6e496c372471d773d0c368
|
||||
F ext/fts5/fts5.c 1496aff16dd9b0a013d14b6c8cf5b7df8c170abe
|
||||
F ext/fts5/fts5.c f786dd1a3d091f7cb6572f6ee95f10f09de52224
|
||||
F ext/fts5/fts5.h 8ace10d5b249a3baa983c79e7a1306d2a79cfd6a
|
||||
F ext/fts5/fts5Int.h 92fb9c4f759674ef569aebc338f363e167a8933c
|
||||
F ext/fts5/fts5_aux.c 243156c197384e17983d6a3ed149fa2270b5bb85
|
||||
F ext/fts5/fts5Int.h 9a195c1706876c538902f007149b39e982e9da53
|
||||
F ext/fts5/fts5_aux.c 3cae4225d458af41b64bb40ed9dcc052eb41b9a0
|
||||
F ext/fts5/fts5_buffer.c 248c61ac9fec001602efc72a45704f3b8d367c00
|
||||
F ext/fts5/fts5_config.c 2138741013e189724b5d40ea7af0f48952a44916
|
||||
F ext/fts5/fts5_expr.c e426baa54b9473cb31b8d891d7d1b923bfb5d017
|
||||
F ext/fts5/fts5_config.c f4ebf143e141b8c77355e3b15aba81b7be51d710
|
||||
F ext/fts5/fts5_expr.c e764d75c58a3accda795f1da1b45960ac87dc77a
|
||||
F ext/fts5/fts5_index.c 68d2d41b5c6d2f8838c3d6ebdc8b242718b8e997
|
||||
F ext/fts5/fts5_storage.c 2866e7e1de9dc851756c3a9c76b6e1d75e0facb7
|
||||
F ext/fts5/fts5parse.y 777da8e5819f75c217982c79c29d014c293acac9
|
||||
@@ -595,11 +595,11 @@ F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849
|
||||
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
|
||||
F test/fts5aa.test a2c7bbc18f25f0b57ea8fc483c8a8830273b9ed4
|
||||
F test/fts5aa.test f90836c002804a82386d66c79b380128c5f3005e
|
||||
F test/fts5ab.test dc04ed48cf93ca957d174406e6c192f2ff4f3397
|
||||
F test/fts5ac.test 9be418d037763f4cc5d86f4239db41fc86bb4f85
|
||||
F test/fts5ad.test 2ed38bbc865678cb2905247120d02ebba7f20e07
|
||||
F test/fts5ae.test 24b337571c51a10da1ae439b96b70317813a2fd4
|
||||
F test/fts5ae.test cb37b3135a00d3afd5492ec534ecf654be5ff69e
|
||||
F test/fts5af.test 5f53d0a52280b63caf5a519d6994c4d428835155
|
||||
F test/fts5ea.test ff43b40f8879ba50b82def70f2ab67c195d1a1d4
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
@@ -1197,7 +1197,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 71d32f53e81921e43c933cc968cb1c18d83fe1e0
|
||||
R 378763b2640fc19d9f72a0522c9f77b1
|
||||
P 770b9540c19ad1e3d24adff382332bf032065efd
|
||||
R b6911e3c357a5fea00c97182f6d0088b
|
||||
U dan
|
||||
Z 3cf4ed481646bab9077300595c244e00
|
||||
Z 526c63f1e91d68c01d64fde27fedef0b
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
770b9540c19ad1e3d24adff382332bf032065efd
|
||||
4cc048c3651e830a6aeded924c7f3a60b634e133
|
||||
@@ -276,5 +276,14 @@ foreach {rowid x y} $d10 {
|
||||
do_execsql_test 10.4.1 { DELETE FROM t1 }
|
||||
do_execsql_test 10.4.2 { INSERT INTO t1(t1) VALUES('integrity-check') }
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_catchsql_test 11.1 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(a, b, c, rank);
|
||||
} {1 {reserved fts5 column name: rank}}
|
||||
do_catchsql_test 11.2 {
|
||||
CREATE VIRTUAL TABLE rank USING fts5(a, b, c);
|
||||
} {1 {reserved fts5 table name: rank}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
+9
-1
@@ -261,9 +261,17 @@ foreach {tn q res} {
|
||||
5 {g AND (e OR f)} {5 4}
|
||||
6 {j AND (h OR i)} {5 6}
|
||||
} {
|
||||
do_execsql_test 8.2.$tn {
|
||||
do_execsql_test 8.2.$tn.1 {
|
||||
SELECT rowid FROM t8 WHERE t8 MATCH $q ORDER BY bm25(t8) DESC;
|
||||
} $res
|
||||
|
||||
do_execsql_test 8.2.$tn.2 {
|
||||
SELECT rowid FROM t8 WHERE t8 MATCH $q ORDER BY +rank DESC;
|
||||
} $res
|
||||
|
||||
do_execsql_test 8.3.$tn.3 {
|
||||
SELECT rowid FROM t8 WHERE t8 MATCH $q ORDER BY rank DESC;
|
||||
} $res
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user