]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Updates to where.c to handle vtabs in joins more similarly to regular tables.
authordan <Dan Kennedy>
Sat, 13 Sep 2025 19:23:12 +0000 (19:23 +0000)
committerdan <Dan Kennedy>
Sat, 13 Sep 2025 19:23:12 +0000 (19:23 +0000)
FossilOrigin-Name: 991383262b0d07ebc79fdb6bed448013cea3a0ac13292d5397dce012b1e6a673

ext/fts5/fts5Int.h
ext/fts5/fts5_expr.c
ext/fts5/fts5_main.c
ext/fts5/test/fts5join.test [new file with mode: 0644]
ext/fts5/test/fts5misc.test
ext/fts5/test/fts5onepass.test
manifest
manifest.tags
manifest.uuid
src/where.c

index ff65039a5b5ffc18a77a12f4880acf4d3e2a383d..a13a65d3c29a351e59bc3116403501e1a452e4ad 100644 (file)
@@ -815,7 +815,7 @@ int sqlite3Fts5ExprPattern(
 **   i64 iRowid = sqlite3Fts5ExprRowid(pExpr);
 ** }
 */
-int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, int bDesc);
+int sqlite3Fts5ExprFirst(Fts5Expr*, Fts5Index *pIdx, i64 iMin, i64, int bDesc);
 int sqlite3Fts5ExprNext(Fts5Expr*, i64 iMax);
 int sqlite3Fts5ExprEof(Fts5Expr*);
 i64 sqlite3Fts5ExprRowid(Fts5Expr*);
index 0a9b08ed1570c5a66b19182ebd3cfab304775734..352df81f4f6695d9bde5d7e97c099a5a6c81d666 100644 (file)
@@ -1549,7 +1549,13 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){
 ** Return SQLITE_OK if successful, or an SQLite error code otherwise. It
 ** is not considered an error if the query does not match any documents.
 */
-int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
+int sqlite3Fts5ExprFirst(
+  Fts5Expr *p, 
+  Fts5Index *pIdx, 
+  i64 iFirst, 
+  i64 iLast, 
+  int bDesc
+){
   Fts5ExprNode *pRoot = p->pRoot;
   int rc;                         /* Return code */
 
@@ -1571,6 +1577,9 @@ int sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFirst, int bDesc){
     assert( pRoot->bEof==0 );
     rc = fts5ExprNodeNext(p, pRoot, 0, 0);
   }
+  if( fts5RowidCmp(p, pRoot->iRowid, iLast)>0 ){
+    pRoot->bEof = 1;
+  }
   return rc;
 }
 
index 4efc53219f9837f40a59163686a5014963217088..75da545f58e23fe71ade92282e24cb0fdf47c7e4 100644 (file)
@@ -511,6 +511,17 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
 #endif
 }
 
+static void fts5SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
+#if SQLITE_VERSION_NUMBER>=3008002
+#ifndef SQLITE_CORE
+  if( sqlite3_libversion_number()>=3008002 )
+#endif
+  {
+    pIdxInfo->estimatedRows = nRow;
+  }
+#endif
+}
+
 static int fts5UsePatternMatch(
   Fts5Config *pConfig, 
   struct sqlite3_index_constraint *p
@@ -646,7 +657,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
           nSeenMatch++;
           idxStr[iIdxStr++] = 'M';
           sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
-          idxStr += strlen(&idxStr[iIdxStr]);
+          iIdxStr += strlen(&idxStr[iIdxStr]);
           assert( idxStr[iIdxStr]=='\0' );
         }
         pInfo->aConstraintUsage[i].argvIndex = ++iCons;
@@ -665,6 +676,7 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
         idxStr[iIdxStr++] = '=';
         bSeenEq = 1;
         pInfo->aConstraintUsage[i].argvIndex = ++iCons;
+        pInfo->aConstraintUsage[i].omit = 1;
       }
     }
   }
@@ -712,17 +724,21 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
 
   /* Calculate the estimated cost based on the flags set in idxFlags. */
   if( bSeenEq ){
-    pInfo->estimatedCost = nSeenMatch ? 1000.0 : 10.0;
-    if( nSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
-  }else if( bSeenLt && bSeenGt ){
-    pInfo->estimatedCost = nSeenMatch ? 5000.0 : 250000.0;
-  }else if( bSeenLt || bSeenGt ){
-    pInfo->estimatedCost = nSeenMatch ? 7500.0 : 750000.0;
+    pInfo->estimatedCost = nSeenMatch ? 1000.0 : 25.0;
+    fts5SetUniqueFlag(pInfo);
+    fts5SetEstimatedRows(pInfo, 1);
   }else{
-    pInfo->estimatedCost = nSeenMatch ? 10000.0 : 1000000.0;
-  }
-  for(i=1; i<nSeenMatch; i++){
-    pInfo->estimatedCost *= 0.4;
+    if( bSeenLt && bSeenGt ){
+      pInfo->estimatedCost = nSeenMatch ? 5000.0 :   750000.0;
+    }else if( bSeenLt || bSeenGt ){
+      pInfo->estimatedCost = nSeenMatch ? 7500.0 :  2250000.0;
+    }else{
+      pInfo->estimatedCost = nSeenMatch ? 10000.0 : 3000000.0;
+    }
+    for(i=1; i<nSeenMatch; i++){
+      pInfo->estimatedCost *= 0.4;
+    }
+    fts5SetEstimatedRows(pInfo, (i64)(pInfo->estimatedCost / 4.0));
   }
 
   pInfo->idxNum = idxFlags;
@@ -921,7 +937,9 @@ static int fts5CursorReseek(Fts5Cursor *pCsr, int *pbSkip){
     int bDesc = pCsr->bDesc;
     i64 iRowid = sqlite3Fts5ExprRowid(pCsr->pExpr);
 
-    rc = sqlite3Fts5ExprFirst(pCsr->pExpr, pTab->p.pIndex, iRowid, bDesc);
+    rc = sqlite3Fts5ExprFirst(
+        pCsr->pExpr, pTab->p.pIndex, iRowid, pCsr->iLastRowid, bDesc
+    );
     if( rc==SQLITE_OK &&  iRowid!=sqlite3Fts5ExprRowid(pCsr->pExpr) ){
       *pbSkip = 1;
     }
@@ -1093,7 +1111,9 @@ static int fts5CursorFirstSorted(
 static int fts5CursorFirst(Fts5FullTable *pTab, Fts5Cursor *pCsr, int bDesc){
   int rc;
   Fts5Expr *pExpr = pCsr->pExpr;
-  rc = sqlite3Fts5ExprFirst(pExpr, pTab->p.pIndex, pCsr->iFirstRowid, bDesc);
+  rc = sqlite3Fts5ExprFirst(
+      pExpr, pTab->p.pIndex, pCsr->iFirstRowid, pCsr->iLastRowid, bDesc
+  );
   if( sqlite3Fts5ExprEof(pExpr) ){
     CsrFlagSet(pCsr, FTS5CSR_EOF);
   }
diff --git a/ext/fts5/test/fts5join.test b/ext/fts5/test/fts5join.test
new file mode 100644 (file)
index 0000000..e4d3b69
--- /dev/null
@@ -0,0 +1,69 @@
+# 2014 June 17
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#*************************************************************************
+# This file implements regression tests for SQLite library.  The
+# focus of this script is testing the FTS5 module.
+#
+
+source [file join [file dirname [info script]] fts5_common.tcl]
+set testprefix fts5join
+
+# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
+ifcapable !fts5 {
+  finish_test
+  return
+}
+
+do_execsql_test 1.0 {
+  CREATE VIRTUAL TABLE vt USING fts5(x);
+  INSERT INTO vt VALUES('abc');
+  INSERT INTO vt VALUES('xyz');
+
+  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TIMESTAMP);
+  INSERT INTO t1 VALUES(1, 1), (2, 2);
+  CREATE INDEX i1 ON t1(b);
+}
+
+# set sqlite_where_trace [expr 0xFFF]
+
+do_eqp_test 1.1 {
+  SELECT * FROM vt, t1 WHERE vt.rowid = t1.rowid ORDER BY t1.rowid; 
+} {
+  QUERY PLAN
+  |--SCAN t1                                                                    
+  `--SCAN vt VIRTUAL TABLE INDEX 0:=
+}
+
+do_eqp_test 1.2 {
+  SELECT * FROM vt, t1 WHERE vt.rowid = t1.rowid AND b>? ORDER BY b LIMIT 10
+} {
+  QUERY PLAN
+  |--SEARCH t1 USING COVERING INDEX i1 (b>?)
+  `--SCAN vt VIRTUAL TABLE INDEX 0:=
+}
+
+do_eqp_test 1.3 {
+  SELECT * FROM vt, t1 WHERE vt.rowid = t1.rowid AND b>?
+} {
+  QUERY PLAN
+  |--SEARCH t1 USING COVERING INDEX i1 (b>?)
+  `--SCAN vt VIRTUAL TABLE INDEX 0:=
+}
+
+do_eqp_test 1.4 {
+  SELECT * FROM vt, t1 WHERE vt.rowid = t1.rowid ORDER BY b
+} {
+  QUERY PLAN
+  |--SCAN t1 USING COVERING INDEX i1
+  `--SCAN vt VIRTUAL TABLE INDEX 0:=
+}
+
+
+finish_test
index 2aca1986a1fbad070c3a7bd12deeee5746a97316..817be9560cf11f0d6efc291c88f1d9f46c3bdecc 100644 (file)
@@ -685,5 +685,17 @@ do_execsql_test 26.1 {
   COMMIT;
 }
 
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 27.0 {
+  CREATE VIRTUAL TABLE ft1 USING fts5(a, b);
+  INSERT INTO ft1(rowid, a, b) VALUES(3, '3', '3');
+}
+
+do_execsql_test 27.1 {
+  SELECT * FROM ft1 WHERE rowid=3 AND b MATCH 'hello';
+}
+
 finish_test
 
index 01021ed348183e7442b2605b2a27f5f1e6999c91..b334096754df0582b430f30805d443cfaadf6182 100644 (file)
@@ -38,15 +38,15 @@ foreach {tn sql uses} {
   1.2 { DELETE FROM ft WHERE rowid=? } 0
   1.3 { DELETE FROM ft WHERE rowid=? } 0
   1.4 { DELETE FROM ft WHERE ft MATCH '1' } 1
-  1.5 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
-  1.6 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 1
+  1.5 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 0
+  1.6 { DELETE FROM ft WHERE ft MATCH '1' AND rowid=? } 0
 
   2.1 { UPDATE ft SET content='a b c' } 1
   2.2 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
   2.3 { UPDATE ft SET content='a b c' WHERE rowid=? } 0
   2.4 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' } 1
-  2.5 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
-  2.6 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 1
+  2.5 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 0
+  2.6 { UPDATE ft SET content='a b c' WHERE ft MATCH '1' AND rowid=? } 0
 } {
   do_test 1.$tn { sql_uses_stmt db $sql } $uses
 }
index 2b7a3014da85b9d2ec902cc3f7415706edc34007..9c6e3a1e4ceac92b8c349cf8c6acd0db627506ea 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\san\soff-by-one\serror\sin\ssqlite3_rsync.\n[forum:/info/46753431d4|Forum\spost\s46753431d4].
-D 2025-09-11T10:58:49.199
+C Updates\sto\swhere.c\sto\shandle\svtabs\sin\sjoins\smore\ssimilarly\sto\sregular\stables.
+D 2025-09-13T19:23:12.699
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -107,14 +107,14 @@ F ext/fts3/unicode/mkunicode.tcl cbf5f7b5c8ce8014bad731f246f2e520eece908465de477
 F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
 F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
 F ext/fts5/fts5.h ff5d3cc88b29e41612bfb29eb723e29e38973de62ca75ba3e8f94ccb67f5b5f2
-F ext/fts5/fts5Int.h 97f373ecedf024fa7bf23989c3e529132225c169e440fe1f48e9b28dfed05ddc
+F ext/fts5/fts5Int.h 4bba2aeadbbd7378675b1fd2967c377fba3147c9a836350c437844b590068927
 F ext/fts5/fts5_aux.c da4a7a9a11ec15c6df0699d908915a209bcde48f0b04101461316b59f71abffb
 F ext/fts5/fts5_buffer.c f1e6d0324d7c55329d340673befc26681a372a4d36086caa8d1ec7d7c53066c7
 F ext/fts5/fts5_config.c e7d8dd062b44a66cd77e5a0f74f23a2354cd1f3f8575afb967b2773c3384f7f8
-F ext/fts5/fts5_expr.c be9e5f7f11d87e7bd3680832c93c13050fe351994b5052b0215c2ef40312c23a
+F ext/fts5/fts5_expr.c b8c32da1127bafaf10d6b4768b0dcb92285798524bed2d87a8686f99a8e8d259
 F ext/fts5/fts5_hash.c a6266cedd801ab7964fa9e74ebcdda6d30ec6a96107fa24148ec6b7b5b80f6e0
 F ext/fts5/fts5_index.c 2a1be0fb3c1b185f84b08b8032ba332c82defa182ff125833c0fecba0a4938b0
-F ext/fts5/fts5_main.c e558225168845dc708abeb2ad10415696e5a3249bcba1810ba3c7ef80764962e
+F ext/fts5/fts5_main.c a6f8bea608b5f5ffc06bd1407e188bb2284437e7dd0e96b492ff7f3df2c32347
 F ext/fts5/fts5_storage.c 19bc7c4cbe1e6a2dd9849ef7d84b5ca1fcbf194cefc3e386b901e00e08bf05c2
 F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329
 F ext/fts5/fts5_test_mi.c 4308d5658cb1f5eee5998dcbaac7d5bdf7a2ef43c8192ca6e0c843f856ccee26
@@ -200,6 +200,7 @@ F ext/fts5/test/fts5hash.test fd3e0367fbf0b0944d6936fdb22696350f57b9871069c67662
 F ext/fts5/test/fts5integrity.test c423ce16fd1ccadcac7fc22f794226b2bb00f5a187c0ab1d9f8502521b1bae05
 F ext/fts5/test/fts5integrity2.test 4c3636615c0201232c44a8105d5cb14fd5499fd0ee3014d7ffd7e83aac76ece8
 F ext/fts5/test/fts5interrupt.test 20d04204d3e341b104c0c24a41596b6393a3a81eba1044c168db0e106f9ac92c
+F ext/fts5/test/fts5join.test 48b7ed36956948c5b8456c8bcaa5b087808d99000675918a43c4f51a925f1514
 F ext/fts5/test/fts5lastrowid.test f36298a1fb9f988bde060a274a7ce638faa9c38a31400f8d2d27ea9373e0c4a1
 F ext/fts5/test/fts5leftjoin.test 1c14b51f4d1344a89e488160882f05a2246dd7e70c5cf077c8fb473e03c66338
 F ext/fts5/test/fts5limits.test 8ab67cf5d311c124b6ceb0062d0297767176df4572d955fce79fa43004dff01c
@@ -207,11 +208,11 @@ F ext/fts5/test/fts5locale.test 83ba7ee12628b540d3098f39c39c1de0c0440eddff8f7512
 F ext/fts5/test/fts5matchinfo.test bc9e74157773db7f00aec1e85587f1145956ebdf1672c136f0f04323b2752aa0
 F ext/fts5/test/fts5merge.test 2654df0bcdb2d117c2d38b6aeb0168061be01c643f9e9194b36c43a2970e8082
 F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2
-F ext/fts5/test/fts5misc.test f4dee7da898d605a6488c5b7afaace3158ed6bb9addff78faa1b37b402b77fb9
+F ext/fts5/test/fts5misc.test 83d6c5101a092c5db8fb631cfdd69a6482e20528b2750427641ac9050d9d0381
 F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581
 F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45
 F ext/fts5/test/fts5near.test 33d60867581066e5db7016deb5d651628125d7ff4e0233a88175aa5b65874c74
-F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
+F ext/fts5/test/fts5onepass.test b56d4109e841c2bc83555c162515748780ea6e0c455c54cf4afd4bd940d14b84
 F ext/fts5/test/fts5optimize.test 264b9101721c17d06d1d174feb743fda3ddc89fad41dee980fef821428258e47
 F ext/fts5/test/fts5optimize2.test 795d4ae5f66a7239cf8d5aef4c2ea96aeb8bcd907bd9be0cfe22064fc71a44ed
 F ext/fts5/test/fts5optimize3.test 1653029284e10e0715246819893ba30565c4ead0d0fc470adae92c353ea857d3
@@ -823,7 +824,7 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
 F src/wal.c a278339ecf5f194fd71fff1f0da1368de50e3a32edc3e9944e1ee1f4610476ff
 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
-F src/where.c f2f075bd17065922235632feb368efe92a7f03d42797eb575267574fbf6d4218
+F src/where.c 9d7b4095ae0a34d9604c3e185c65cdf6eca5f2e8707403c526eed798867cece4
 F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
 F src/wherecode.c 71c5c6804b7f882dec8ec858758accae02fcfca13df3cc720f1f258e663ec7c5
 F src/whereexpr.c 403a44eeec1a0f0914fccc6a59376b6924bc00ef6728fe6ffce4cf3051b320fc
@@ -2174,8 +2175,11 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
 F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 5bc6b9352236df3091ee69b947d0c397264156539d13e5968ec3b9a6e55dc800
-R a5539b6621653da7959fb888474ce821
-U drh
-Z 3cde64f623da7bc733a5eed51b57ab95
+P ef3b7be6f2037871f6f1b1944fed3dda28216e7f179080d3be2e2620c031f48c
+R 897d11ff33135df378e9ecdf2ba1caed
+T *branch * vtab-planner-fixes
+T *sym-vtab-planner-fixes *
+T -sym-trunk *
+U dan
+Z 99690642a15232d641aa4de8081ee700
 # Remove this line to create a well-formed Fossil manifest.
index bec971799ff1b8ee641c166c7aeb22d12c785393..da9d00b7a1264f3b7f1a398bf0774521127bbc21 100644 (file)
@@ -1,2 +1,2 @@
-branch trunk
-tag trunk
+branch vtab-planner-fixes
+tag vtab-planner-fixes
index ea679c53ec20ebab1980b576f8fff009c8d8875b..4a46a393a711a6b36fbfaae2a63d933d67207359 100644 (file)
@@ -1 +1 @@
-ef3b7be6f2037871f6f1b1944fed3dda28216e7f179080d3be2e2620c031f48c
+991383262b0d07ebc79fdb6bed448013cea3a0ac13292d5397dce012b1e6a673
index b60c4d1c0827bbcbce3def921b51734b77fe3bab..77a976734a6a903c0ed2d843b452b911b25ba98f 100644 (file)
@@ -5104,6 +5104,10 @@ static i8 wherePathSatisfiesOrderBy(
        && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
       ){
         obSat = obDone;
+      }else{
+        /* No further ORDER BY terms may be matched. So this call should
+        ** return >=0, not -1. Clear isOrderDistinct to ensure it does so. */
+        isOrderDistinct = 0;
       }
       break;
     }
@@ -6151,7 +6155,10 @@ static SQLITE_NOINLINE void whereInterstageHeuristic(WhereInfo *pWInfo){
   for(i=0; i<pWInfo->nLevel; i++){
     WhereLoop *p = pWInfo->a[i].pWLoop;
     if( p==0 ) break;
-    if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ) continue;
+    if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
+      /* Treat a vtab scan as similar to a full-table scan */
+      break;
+    }
     if( (p->wsFlags & (WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 ){
       u8 iTab = p->iTab;
       WhereLoop *pLoop;