]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add support for AND, OR and NOT to fts5.
authordan <dan@noemail.net>
Sat, 5 Jul 2014 15:15:41 +0000 (15:15 +0000)
committerdan <dan@noemail.net>
Sat, 5 Jul 2014 15:15:41 +0000 (15:15 +0000)
FossilOrigin-Name: 8682b87e794767cefcaa080fd53c8973c24c556a

ext/fts5/fts5_expr.c
manifest
manifest.uuid
test/fts5ac.test

index 8a84f958bafef9c8356b49ff27724f990986c650..e528757bb4510c3e5ecce3128eca74c66bc43325 100644 (file)
@@ -317,14 +317,6 @@ void sqlite3Fts5ExprFree(Fts5Expr *p){
   }
 }
 
-/*
-**
-*/
-static int fts5ExprNodeTest(Fts5Expr *pExpr, Fts5ExprNode *pNode){
-  assert( 0 );
-  return SQLITE_OK;
-}
-
 /*
 ** All individual term iterators in pPhrase are guaranteed to be valid and
 ** pointing to the same rowid when this function is called. This function 
@@ -462,8 +454,8 @@ static int fts5ExprNearIsMatch(Fts5ExprNearset *pNear, int *pbMatch){
 }
 
 /*
-** Advance each phrase iterator in phrase pNear. If any reach EOF, set
-** output variable *pbEof to true before returning.
+** Advance each term iterator in each phrase in pNear. If any reach EOF, 
+** set output variable *pbEof to true before returning.
 */
 static int fts5ExprNearAdvanceAll(
   Fts5Expr *pExpr,                /* Expression pPhrase belongs to */
@@ -650,17 +642,131 @@ static int fts5ExprNearInitAll(
   return SQLITE_OK;
 }
 
-static int fts5ExprNearNext(
-  Fts5Expr *pExpr,                /* Expression that pNear is a part of */
-  Fts5ExprNode *pNode
-){
-  int rc = fts5ExprNearAdvanceAll(pExpr, pNode->pNear, &pNode->bEof);
-  if( rc==SQLITE_OK && pNode->bEof==0 ){
-    rc = fts5ExprNearNextMatch(pExpr, pNode);
+/* fts3ExprNodeNext() calls fts5ExprNodeNextMatch(). And vice-versa. */
+static int fts5ExprNodeNextMatch(Fts5Expr*, Fts5ExprNode*);
+
+/*
+** Nodes at EOF are considered larger than all other nodes. A node that
+** points to a *smaller* rowid is considered larger.
+** 
+**    res = (*p1) - (*p2)
+*/
+static int fts5NodeCompare(Fts5ExprNode *p1, Fts5ExprNode *p2){
+  if( p2->bEof ) return -1;
+  if( p1->bEof ) return +1;
+  if( p1->iRowid>p2->iRowid ) return -1;
+  return (p1->iRowid < p2->iRowid);
+}
+
+static int fts5ExprNodeNext(Fts5Expr *pExpr, Fts5ExprNode *pNode){
+  int rc = SQLITE_OK;
+
+  if( pNode->bEof==0 ){
+    switch( pNode->eType ){
+      case FTS5_STRING: {
+        rc = fts5ExprNearAdvanceAll(pExpr, pNode->pNear, &pNode->bEof);
+        break;
+      };
+
+      case FTS5_AND: {
+        rc = fts5ExprNodeNext(pExpr, pNode->pLeft);
+        if( rc==SQLITE_OK ) rc = fts5ExprNodeNext(pExpr, pNode->pRight);
+        break;
+      }
+
+      case FTS5_OR: {
+        Fts5ExprNode *p1 = pNode->pLeft;
+        Fts5ExprNode *p2 = pNode->pRight;
+        int cmp = fts5NodeCompare(p1, p2);
+
+        if( cmp==0 ){
+          rc = fts5ExprNodeNext(pExpr, p1);
+          if( rc==SQLITE_OK ) rc = fts5ExprNodeNext(pExpr, p2);
+        }else{
+          rc = fts5ExprNodeNext(pExpr, (cmp < 0) ? p1 : p2);
+        }
+
+        break;
+      }
+
+      default: assert( pNode->eType==FTS5_NOT ); {
+        rc = fts5ExprNodeNext(pExpr, pNode->pLeft);
+        break;
+      }
+    }
+
+    if( rc==SQLITE_OK ){
+      rc = fts5ExprNodeNextMatch(pExpr, pNode);
+    }
   }
+
   return rc;
 }
+
+/*
+**
+*/
+static int fts5ExprNodeNextMatch(Fts5Expr *pExpr, Fts5ExprNode *pNode){
+  int rc = SQLITE_OK;
+  if( pNode->bEof==0 ){
+    switch( pNode->eType ){
+
+      case FTS5_STRING: {
+        rc = fts5ExprNearNextMatch(pExpr, pNode);
+        break;
+      }
+
+      case FTS5_AND: {
+        Fts5ExprNode *p1 = pNode->pLeft;
+        Fts5ExprNode *p2 = pNode->pRight;
+
+        while( p1->bEof==0 && p2->bEof==0 && p2->iRowid!=p1->iRowid ){
+          Fts5ExprNode *pAdv = (p1->iRowid > p2->iRowid) ? p1 : p2;
+          rc = fts5ExprNodeNext(pExpr, pAdv);
+          if( rc!=SQLITE_OK ) break;
+        }
+        pNode->bEof = p1->bEof || p2->bEof;
+        pNode->iRowid = p1->iRowid;
+        break;
+      }
+
+      case FTS5_OR: {
+        Fts5ExprNode *p1 = pNode->pLeft;
+        Fts5ExprNode *p2 = pNode->pRight;
+        Fts5ExprNode *pNext = (fts5NodeCompare(p1, p2) > 0 ? p2 : p1);
+        pNode->bEof = pNext->bEof;
+        pNode->iRowid = pNext->iRowid;
+        break;
+      }
+
+      default: assert( pNode->eType==FTS5_NOT ); {
+        Fts5ExprNode *p1 = pNode->pLeft;
+        Fts5ExprNode *p2 = pNode->pRight;
+        while( rc==SQLITE_OK ){
+          int cmp;
+          while( rc==SQLITE_OK && (cmp = fts5NodeCompare(p1, p2))>0 ){
+            rc = fts5ExprNodeNext(pExpr, p2);
+          }
+          if( rc || cmp ) break;
+          rc = fts5ExprNodeNext(pExpr, p1);
+        }
+        pNode->bEof = p1->bEof;
+        pNode->iRowid = p1->iRowid;
+        break;
+      }
+    }
+  }
+  return rc;
+}
+
  
+/*
+** Set node pNode, which is part of expression pExpr, to point to the first
+** match. If there are no matches, set the Node.bEof flag to indicate EOF.
+**
+** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
+** It is not an error if there are no matches.
+*/
 static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
   int rc = SQLITE_OK;
   pNode->bEof = 0;
@@ -681,23 +787,12 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
       rc = fts5ExprNodeFirst(pExpr, pNode->pRight);
     }
     if( rc==SQLITE_OK ){
-      rc = fts5ExprNodeTest(pExpr, pNode);
+      rc = fts5ExprNodeNextMatch(pExpr, pNode);
     }
   }
   return rc;
 }
 
-static int fts5ExprNodeNext(Fts5Expr *pExpr, Fts5ExprNode *pNode){
-  int rc = SQLITE_OK;
-
-  if( pNode->eType==FTS5_STRING ){
-    rc = fts5ExprNearNext(pExpr, pNode);
-  }else{
-    assert( 0 );
-  }
-  return rc;
-}
-
 
 
 /*
index 0526a1e9b947e2bf43c309eee3889addafc81630..f794442bdacf7abfbffb0b6cb80598c56e2e6e33 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\ssupport\sfor\sthe\s"colname\s:\s<nearset>"\ssyntax\sto\sfts5.
-D 2014-07-05T07:54:01.680
+C Add\ssupport\sfor\sAND,\sOR\sand\sNOT\sto\sfts5.
+D 2014-07-05T15:15:41.850
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in b03432313a3aad96c706f8164fb9f5307eaf19f5
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -107,7 +107,7 @@ F ext/fts5/fts5.c 1af3184dd9c0e5c1686f71202d6b6cac8f225f05
 F ext/fts5/fts5Int.h b7a684ff3508ab24437886f8bc873a16f494a7db
 F ext/fts5/fts5_buffer.c f1a26a79e2943fe4388e531fa141941b5eb6d31a
 F ext/fts5/fts5_config.c 94f1b4cb4de6a7cd5780c14adb0198e289df8cef
-F ext/fts5/fts5_expr.c 618e6641c8dc428c146ec84bf30ff0b3da6b28c7
+F ext/fts5/fts5_expr.c a341fe4f6d49875a7aeaa443036a3dc6aa2bff52
 F ext/fts5/fts5_index.c d8ab9712e38dc1beb9a9145ec89e18dc083c0467
 F ext/fts5/fts5_storage.c 7848d8f8528d798bba159900ea310a6d4a279da8
 F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
@@ -594,7 +594,7 @@ F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849
 F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
 F test/fts5aa.test c8d3b9694f6b2864161c7437408464a535d19343
 F test/fts5ab.test 4db86a9473ee2a8c2cb30e0d81df21c6022f99b6
-F test/fts5ac.test c7ca34a477d638195a839c961e1b572890dc5d0d
+F test/fts5ac.test d3aeb7a079d40093b34ac8053fc5e4c0ed7e88dc
 F test/fts5ea.test ff43b40f8879ba50b82def70f2ab67c195d1a1d4
 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
 F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
@@ -1190,7 +1190,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 250ae8d40115e2e47cc5a1e8a427fa8c0a89124d
-R 213fb14ea45e358dcb308401853c4570
+P 004667106e552e832a564b77e242b86f183d4441
+R 4ab8db5e873de873b3febadf2e9942c6
 U dan
-Z 0b8632fefc20738326985d3c409c9be8
+Z fcdcd2fcf8de98f33f86410b0c7d6d38
index 506ee6aff0d74f9a32de3eaa5bcafe46d40f1d3c..3630392fc94408a9304f2ad864cf0076306fab94 100644 (file)
@@ -1 +1 @@
-004667106e552e832a564b77e242b86f183d4441
\ No newline at end of file
+8682b87e794767cefcaa080fd53c8973c24c556a
\ No newline at end of file
index c4586481bf338e78f95f7d211c31e40801affa35..849ea52e5e9148548c97755cc0f37503246afa0b 100644 (file)
@@ -208,7 +208,7 @@ proc nearset {aCol args} {
   return $bMatch
 }
 
-proc matchdata {expr} {
+proc matchdata {expr {print 0}} {
   set tclexpr [db one {SELECT fts5_expr_tcl($expr, 'nearset $cols', 'x', 'y')}]
   set res [list]
   foreach {id x y} $::data {
@@ -217,6 +217,9 @@ proc matchdata {expr} {
       set res [concat $id $res]
     }
   }
+  if {$print} {
+    puts $tclexpr
+  }
   return $res
 }
 
@@ -272,10 +275,18 @@ foreach {tn expr} {
   9  { y : NEAR(r c) }
   10 { x : "r c" }
   11 { y : "r c" }
+  12 { a AND b }
+  13 { a AND b AND c }
+  14a { a }
+  14b { a OR b }
+  15 { a OR b AND c }
+  16 { c AND b OR a }
+  17 { c AND (b OR a) }
+  18 { c NOT (b OR a) }
+  19 { c NOT b OR a AND d }
 } {
-
   set res [matchdata $expr]
-  do_execsql_test 2.$tn.[llength $res] { 
+  do_execsql_test 4.$tn.[llength $res] { 
     SELECT rowid FROM xx WHERE xx match $expr
   } $res
 }