]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix things so that the fts5 extension API works with "ORDER BY rank" queries.
authordan <dan@noemail.net>
Wed, 30 Jul 2014 20:26:24 +0000 (20:26 +0000)
committerdan <dan@noemail.net>
Wed, 30 Jul 2014 20:26:24 +0000 (20:26 +0000)
FossilOrigin-Name: f1b4e1a98d49ecaba962beba16f8224175e4ba59

ext/fts5/fts5.c
manifest
manifest.uuid
test/fts5af.test

index 22df7a62f724ccc6286ec02413ff17c59c0da7ef..794dc791d495e3619e58eb8440725f9441ea7728 100644 (file)
@@ -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 && iCol<pTab->pConfig->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; i<nPhrase; i++){
+    const u8 *dummy;
+    if( i ) sqlite3Fts5BufferAppendVarint(&rc, &val, iOff);
+    iOff += sqlite3Fts5ExprPoslist(pCsr->pExpr, i, &dummy);
+  }
+
+  for(i=0; i<nPhrase; i++){
+    const u8 *pPoslist;
+    int nPoslist;
+    nPoslist = sqlite3Fts5ExprPoslist(pCsr->pExpr, 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
index 7af098c00418fb648db1712c7febab644cb75605..405af5b550d53ff5b22b44df2f894e09c93397c8 100644 (file)
--- 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
index 62005c928ac541a0c579d072b493e7d0de8e8130..25423418e342b4c5b7e5255ca46c1e898ef28c04 100644 (file)
@@ -1 +1 @@
-4cc048c3651e830a6aeded924c7f3a60b634e133
\ No newline at end of file
+f1b4e1a98d49ecaba962beba16f8224175e4ba59
\ No newline at end of file
index 2412b4a7a477eb1763bedc5f12d8a9456d2192bf..d59df77291b4ec82ee7d888c9a79b9c71165ad08 100644 (file)
@@ -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]
+
+
 }