From: dan Date: Wed, 30 Jul 2014 20:26:24 +0000 (+0000) Subject: Fix things so that the fts5 extension API works with "ORDER BY rank" queries. X-Git-Tag: version-3.8.11~114^2~152 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3fc4a856a229de7c9f00e3e22de7292909cd26df;p=thirdparty%2Fsqlite.git Fix things so that the fts5 extension API works with "ORDER BY rank" queries. FossilOrigin-Name: f1b4e1a98d49ecaba962beba16f8224175e4ba59 --- diff --git a/ext/fts5/fts5.c b/ext/fts5/fts5.c index 22df7a62f7..794dc791d4 100644 --- a/ext/fts5/fts5.c +++ b/ext/fts5/fts5.c @@ -73,7 +73,7 @@ struct Fts5MatchPhrase { struct Fts5Sorter { sqlite3_stmt *pStmt; i64 iRowid; /* Current rowid */ - u8 *aPoslist; /* Position lists for current row */ + const u8 *aPoslist; /* Position lists for current row */ int nIdx; /* Number of entries in aIdx[] */ int aIdx[0]; /* Offsets into aPoslist for current row */ }; @@ -404,8 +404,22 @@ static int fts5SorterNext(Fts5Cursor *pCsr){ rc = SQLITE_OK; CsrFlagSet(pCsr, FTS5CSR_EOF); }else if( rc==SQLITE_ROW ){ + const u8 *a; + const u8 *aBlob; + int nBlob; + int i; rc = SQLITE_OK; + pSorter->iRowid = sqlite3_column_int64(pSorter->pStmt, 0); + nBlob = sqlite3_column_bytes(pSorter->pStmt, 1); + aBlob = a = sqlite3_column_blob(pSorter->pStmt, 1); + + for(i=0; i<(pSorter->nIdx-1); i++){ + a += getVarint32(a, pSorter->aIdx[i]); + } + pSorter->aIdx[i] = &aBlob[nBlob] - a; + pSorter->aPoslist = a; + CsrFlagSet(pCsr, FTS5CSR_REQUIRE_CONTENT | FTS5CSR_REQUIRE_DOCSIZE ); } return rc; @@ -467,7 +481,7 @@ static int fts5CursorFirstSorted(Fts5Table *pTab, Fts5Cursor *pCsr, int bAsc){ if( pSorter==0 ) return SQLITE_NOMEM; memset(pSorter, 0, nByte); - zSql = sqlite3_mprintf("SELECT rowid, %Q FROM %Q.%Q ORDER BY +%s %s", + zSql = sqlite3_mprintf("SELECT rowid, %s FROM %Q.%Q ORDER BY +%s %s", pConfig->zName, pConfig->zDb, pConfig->zName, FTS5_RANK_NAME, bAsc ? "ASC" : "DESC" ); @@ -571,6 +585,21 @@ static int fts5EofMethod(sqlite3_vtab_cursor *pCursor){ return (CsrFlagTest(pCsr, FTS5CSR_EOF) ? 1 : 0); } +/* +** Return the rowid that the cursor currently points to. +*/ +static i64 fts5CursorRowid(Fts5Cursor *pCsr){ + assert( FTS5_PLAN(pCsr->idxNum)==FTS5_PLAN_MATCH + || FTS5_PLAN(pCsr->idxNum)==FTS5_PLAN_SORTED_MATCH + || FTS5_PLAN(pCsr->idxNum)==FTS5_PLAN_SOURCE + ); + if( pCsr->pSorter ){ + return pCsr->pSorter->iRowid; + }else{ + return sqlite3Fts5ExprRowid(pCsr->pExpr); + } +} + /* ** This is the xRowid method. The SQLite core calls this routine to ** retrieve the rowid for the current row of the result set. fts5 @@ -585,11 +614,8 @@ static int fts5RowidMethod(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ switch( ePlan ){ case FTS5_PLAN_SOURCE: case FTS5_PLAN_MATCH: - *pRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); - break; - case FTS5_PLAN_SORTED_MATCH: - *pRowid = pCsr->pSorter->iRowid; + *pRowid = fts5CursorRowid(pCsr); break; default: @@ -609,7 +635,7 @@ static int fts5SeekCursor(Fts5Cursor *pCsr){ if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){ assert( pCsr->pExpr ); sqlite3_reset(pCsr->pStmt); - sqlite3_bind_int64(pCsr->pStmt, 1, sqlite3Fts5ExprRowid(pCsr->pExpr)); + sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr)); rc = sqlite3_step(pCsr->pStmt); if( rc==SQLITE_ROW ){ rc = SQLITE_OK; @@ -786,7 +812,7 @@ static int fts5ApiPhraseSize(Fts5Context *pCtx, int iPhrase){ static sqlite3_int64 fts5ApiRowid(Fts5Context *pCtx){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; - return sqlite3Fts5ExprRowid(pCsr->pExpr); + return fts5CursorRowid((Fts5Cursor*)pCtx); } static int fts5ApiColumnText( @@ -810,7 +836,7 @@ static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){ int rc = SQLITE_OK; if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){ - i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr); + i64 iRowid = fts5CursorRowid(pCsr); rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize); } if( iCol>=0 && iColpConfig->nCol ){ @@ -829,7 +855,14 @@ static int fts5ApiPoslist( ){ Fts5Cursor *pCsr = (Fts5Cursor*)pCtx; const u8 *a; int n; /* Poslist for phrase iPhrase */ - n = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, &a); + if( pCsr->pSorter ){ + Fts5Sorter *pSorter = pCsr->pSorter; + int i1 = (iPhrase ? 0 : pSorter->aIdx[iPhrase-1]); + n = pSorter->aIdx[iPhrase] - i1; + a = &pSorter->aPoslist[i1]; + }else{ + n = sqlite3Fts5ExprPoslist(pCsr->pExpr, iPhrase, &a); + } return sqlite3Fts5PoslistNext64(a, n, pi, piPos); } @@ -983,6 +1016,31 @@ static void fts5ApiCallback( } } +static int fts5PoslistBlob(sqlite3_context *pCtx, Fts5Cursor *pCsr){ + int i; + int rc = SQLITE_OK; + int nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr); + Fts5Buffer val; + int iOff = 0; + + memset(&val, 0, sizeof(Fts5Buffer)); + for(i=0; ipExpr, i, &dummy); + } + + for(i=0; ipExpr, i, &pPoslist); + sqlite3Fts5BufferAppendBlob(&rc, &val, nPoslist, pPoslist); + } + + sqlite3_result_blob(pCtx, val.p, val.n, sqlite3_free); + return rc; +} + /* ** This is the xColumn method, called by SQLite to request a value from ** the row that the supplied cursor currently points to. @@ -1000,7 +1058,7 @@ static int fts5ColumnMethod( if( iCol==pConfig->nCol ){ if( FTS5_PLAN(pCsr->idxNum)==FTS5_PLAN_SOURCE ){ - /* todo */ + fts5PoslistBlob(pCtx, pCsr); }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 diff --git a/manifest b/manifest index 7af098c004..405af5b550 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\shidden\scolumn\s"rank".\sCurrently\sthis\salways\sreturns\sthe\ssame\svalue\sas\sthe\sbm25()\sfunction. -D 2014-07-30T19:41:58.841 +C Fix\sthings\sso\sthat\sthe\sfts5\sextension\sAPI\sworks\swith\s"ORDER\sBY\srank"\squeries. +D 2014-07-30T20:26:24.443 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in b03432313a3aad96c706f8164fb9f5307eaf19f5 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -103,7 +103,7 @@ 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 f786dd1a3d091f7cb6572f6ee95f10f09de52224 +F ext/fts5/fts5.c f322286c6a37dcea4b46b00677e9aad2e59abe9d F ext/fts5/fts5.h 8ace10d5b249a3baa983c79e7a1306d2a79cfd6a F ext/fts5/fts5Int.h 9a195c1706876c538902f007149b39e982e9da53 F ext/fts5/fts5_aux.c 3cae4225d458af41b64bb40ed9dcc052eb41b9a0 @@ -600,7 +600,7 @@ F test/fts5ab.test dc04ed48cf93ca957d174406e6c192f2ff4f3397 F test/fts5ac.test 9be418d037763f4cc5d86f4239db41fc86bb4f85 F test/fts5ad.test 2ed38bbc865678cb2905247120d02ebba7f20e07 F test/fts5ae.test cb37b3135a00d3afd5492ec534ecf654be5ff69e -F test/fts5af.test 5f53d0a52280b63caf5a519d6994c4d428835155 +F test/fts5af.test 9ebe23aa3875896076952c7bc6e8308813a63c74 F test/fts5ea.test ff43b40f8879ba50b82def70f2ab67c195d1a1d4 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef @@ -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 770b9540c19ad1e3d24adff382332bf032065efd -R b6911e3c357a5fea00c97182f6d0088b +P 4cc048c3651e830a6aeded924c7f3a60b634e133 +R e80b35a7b7fca0c8edda241edc415407 U dan -Z 526c63f1e91d68c01d64fde27fedef0b +Z fdc04c3e2e7e600dae907e07830ae6e8 diff --git a/manifest.uuid b/manifest.uuid index 62005c928a..25423418e3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4cc048c3651e830a6aeded924c7f3a60b634e133 \ No newline at end of file +f1b4e1a98d49ecaba962beba16f8224175e4ba59 \ No newline at end of file diff --git a/test/fts5af.test b/test/fts5af.test index 2412b4a7a4..d59df77291 100644 --- a/test/fts5af.test +++ b/test/fts5af.test @@ -47,6 +47,14 @@ proc do_snippet_test {tn doc match res} { SELECT snippet(t1, '[', ']', '...', 7) FROM t1 WHERE t1 MATCH $v2; } [list $res] + do_execsql_test $tn.3 { + DELETE FROM t1; + INSERT INTO t1 VALUES($v1, NULL); + SELECT snippet(t1, '[', ']', '...', 7) FROM t1 WHERE t1 MATCH $v2 + ORDER BY rank DESC; + } [list $res] + + }