From: dan Date: Wed, 30 Jul 2014 19:41:58 +0000 (+0000) Subject: Add hidden column "rank". Currently this always returns the same value as the bm25... X-Git-Tag: version-3.8.11~114^2~153 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fdb4a30af29797184ddb38d2cf85b0fb06137be1;p=thirdparty%2Fsqlite.git Add hidden column "rank". Currently this always returns the same value as the bm25() function. FossilOrigin-Name: 4cc048c3651e830a6aeded924c7f3a60b634e133 --- diff --git a/ext/fts5/fts5.c b/ext/fts5/fts5.c index e89817d04e..22df7a62f7 100644 --- a/ext/fts5/fts5.c +++ b/ext/fts5/fts5.c @@ -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, FROM 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 /* ( MATCH ?) */ -#define FTS5_PLAN_ROWID 3 /* (rowid = ?) */ +#define FTS5_PLAN_SCAN 1 /* No usable constraint */ +#define FTS5_PLAN_MATCH 2 /* ( MATCH ?) */ +#define FTS5_PLAN_SORTED_MATCH 3 /* ( 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; - } - }else{ - rc = sqlite3Fts5ExprNext(pCsr->pExpr); - if( sqlite3Fts5ExprEof(pCsr->pExpr) ){ - CsrFlagSet(pCsr, FTS5CSR_EOF); + 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; } - 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); - } - }else{ - if( ePlan==FTS5_PLAN_ROWID ){ - sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); + 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); } - 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 ( 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 diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 21c6d459d9..bfbc8d7aca 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -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 diff --git a/ext/fts5/fts5_aux.c b/ext/fts5/fts5_aux.c index 5214296e35..dbf63a1c43 100644 --- a/ext/fts5/fts5_aux.c +++ b/ext/fts5/fts5_aux.c @@ -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 */ diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index 5bed69def3..d326f60cc8 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -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); } diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 2fd7f63f76..68d8a75b9a 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -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 && iPhrasenPhrase ){ - 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; diff --git a/manifest b/manifest index 36de4c8844..7af098c004 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index 2f2c34352f..62005c928a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -770b9540c19ad1e3d24adff382332bf032065efd \ No newline at end of file +4cc048c3651e830a6aeded924c7f3a60b634e133 \ No newline at end of file diff --git a/test/fts5aa.test b/test/fts5aa.test index 1206a0cae8..c59183512a 100644 --- a/test/fts5aa.test +++ b/test/fts5aa.test @@ -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 diff --git a/test/fts5ae.test b/test/fts5ae.test index bb4904f210..4a5e4d041e 100644 --- a/test/fts5ae.test +++ b/test/fts5ae.test @@ -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 }