]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When reducing the truth probability of a LIKE/GLOB constraint, only consider
authordrh <>
Mon, 2 Feb 2026 20:54:28 +0000 (20:54 +0000)
committerdrh <>
Mon, 2 Feb 2026 20:54:28 +0000 (20:54 +0000)
non-wildcard characters in the pattern.

FossilOrigin-Name: 2ba8fc290dbc80d159a217d745d8bd62371c305443d5aed10bfcf34cc98d3985

manifest
manifest.uuid
src/func.c
src/sqliteInt.h
src/where.c

index 351f81bcc995d92916afdfad25004554d9078174..a4ebe93fe1814bbc0f81284ab5b185be35b77139 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\sreduce\sthe\sestimated\struth\sprobability\sof\sLIKE\sand\sGLOB\soperators\nby\squite\sso\smuch.\s\sFix\sa\ssingle\stest\scase\swhose\soutput\schanged.
-D 2026-02-02T16:03:24.852
+C When\sreducing\sthe\struth\sprobability\sof\sa\sLIKE/GLOB\sconstraint,\sonly\sconsider\nnon-wildcard\scharacters\sin\sthe\spattern.
+D 2026-02-02T20:54:28.121
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -692,7 +692,7 @@ F src/delete.c 901499bed747c3b4b2be45be1abe912ba50a3f6a40ba88cc006ccf279f2d0e97
 F src/expr.c 1ca95a1f8d0ef5113ca948ffac815183e30d754403f871e91d9ebb94ec92ee0d
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c c065da737307a29e4d240ac727758dbf4102cb3218a1f651eb689b6a6fa12531
-F src/func.c 315b9e6451f8d2456e4aabc919b5e74b81e8bb1c184df5824a8cc28742fe8746
+F src/func.c a94c0f3e36b39585b0653f31a294676e18255e154c93d9ee33ea7499ff0e45df
 F src/global.c a19e4b1ca1335f560e9560e590fc13081e21f670643367f99cb9e8f9dc7d615b
 F src/hash.c 03c8c0f4be9e8bcb6de65aa26d34a61d48a9430747084a69f9469fbb00ea52ca
 F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
@@ -743,7 +743,7 @@ F src/shell.c.in fe1ad71964401a1bd1fc396aa524634096bcbe6cb20b0091a19490e1789431f
 F src/sqlite.h.in 8bcbaecfe2cbecf8c5c1381354fcdd7d307443e88b4953fccb222456c1267b61
 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
 F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca
-F src/sqliteInt.h f3005a643c484e89a4836773c10f3225ac6153910ec00d18026c6e7c05cac331
+F src/sqliteInt.h a18f7d9f8979d10bea8fa7371c35ddbe5d613390b635de5ea6c0827961fe585d
 F src/sqliteLimit.h 904a3f520362c7065c18165aaabd504fb13cc1b76cb411f38bd41ac219e4af1e
 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -820,7 +820,7 @@ F src/vxworks.h 9d18819c5235b49c2340a8a4d48195ec5d5afb637b152406de95a9436beeaeab
 F src/wal.c 505a98fbc599a971d92cb90371cf54546c404cd61e04fd093e7b0c8ff978f9b6
 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
-F src/where.c d2272132d973644548967121c97ca5a1f392b3439dae7d9bd719929debbc9e43
+F src/where.c 30da9bfdf08a63b4140a7e759ee607bb8b17d4ea8558ff7bcdbf3dc8e17c7613
 F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
 F src/wherecode.c 71c5c6804b7f882dec8ec858758accae02fcfca13df3cc720f1f258e663ec7c5
 F src/whereexpr.c cadb37fbaa2cb6d1ec1687923c3ac21aed4187d198f4500c00a01abb24c3cb44
@@ -2194,8 +2194,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P d9d3d3a807710957f35b023ddc89cb80eea529f654ce3aa0f9aafe6c15b3ce88
-R 25e1fe96e498f9b8b55553d9e6865338
+P fdebbedbd9a99165359761106cdc76d327f74043b22806b7bd96402fbed36f14
+R 614737ef38a63f1da93f92d4f0ce4b50
 U drh
-Z d3b61653b3cf360015a3aeda2564e235
+Z 049a8e06c2c841efc8109a85bd196693
 # Remove this line to create a well-formed Fossil manifest.
index 8f261bbd04f533e4ccaab871f2d2f4fb2b50aa65..1657fdcefd7df31cbf54bb2346138c5a46c5ce68 100644 (file)
@@ -1 +1 @@
-fdebbedbd9a99165359761106cdc76d327f74043b22806b7bd96402fbed36f14
+2ba8fc290dbc80d159a217d745d8bd62371c305443d5aed10bfcf34cc98d3985
index 85af5f57b9a7b5356fb3c68b225faa78e86f2078..fdedada3ba4c1c57b5df88051f85f7ed54d39096 100644 (file)
@@ -2374,10 +2374,35 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
 **
 ** If this node is a string literal that is longer pWalker->sz, then set
 ** pWalker->sz to the byte length of that string literal.
+**
+** pWalker->eCode indicates how to count characters:
+**
+**    eCode==0     Count as a GLOB pattern
+**    eCode==1     Count as a LIKE pattern
 */
 static int exprNodeStrlenEst(Walker *pWalker, Expr *pExpr){
   if( pExpr->op==TK_STRING ){
-    int sz = sqlite3Strlen30(pExpr->u.zToken);
+    int sz = 0;                    /* Pattern size in bytes */
+    u8 *z = (u8*)pExpr->u.zToken;  /* The pattern */
+    u8 c;                          /* Next character of the pattern */
+    u8 c1, c2, c3;                 /* Wildcards */
+    if( pWalker->eCode ){
+      c1 = '%';
+      c2 = '_';
+      c3 = 0;
+    }else{
+      c1 = '*';
+      c2 = '?';
+      c3 = '[';
+    }
+    while( (c = *(z++))!=0 ){
+      if( c==c3 ){
+        if( *z ) z++;
+        while( *z && *z!=']' ) z++;
+      }else if( c!=c1 && c!=c2 ){
+        sz++;
+      }
+    }
     if( sz>pWalker->u.sz ) pWalker->u.sz = sz;
   }
   return WRC_Continue;
@@ -2386,10 +2411,16 @@ static int exprNodeStrlenEst(Walker *pWalker, Expr *pExpr){
 /*
 ** Return the length of the longest string literal in the given
 ** expression.
+**
+** eCode indicates how to count characters:
+**
+**    eCode==0     Count as a GLOB pattern
+**    eCode==1     Count as a LIKE pattern
 */
-int sqlite3ExprStrlenEst(Expr *p){
+int sqlite3ExprStrlenEst(Expr *p, u16 eCode){
   Walker w;
   w.u.sz = 0;
+  w.eCode = eCode;
   w.xExprCallback = exprNodeStrlenEst;
   w.xSelectCallback = sqlite3SelectWalkFail;
 #ifdef SQLITE_DEBUG
@@ -2425,8 +2456,10 @@ int sqlite3ExprStrlenEst(Expr *p){
 **
 ** Case 2:  pIsNocase and aWc are both NULL
 **
-** Return the estimated length  of the pattern. Zero is a possible return
-** value in this case.
+** Return the estimated length of the pattern, in bytes, not counting
+** wildcards.   Zero is a possible return value for this case.  The value
+** returned is used to estimate the percentage of rows in a table for which
+** the LIKE or GLOB operator will be true.
 */
 int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
   FuncDef *pDef;
@@ -2474,7 +2507,8 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
     *pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0;
     return 1;
   }else{
-    return sqlite3ExprStrlenEst(pExpr->x.pList->a[0].pExpr);
+    u16 eCode = pDef->pUserData != (void*)&globInfo;
+    return sqlite3ExprStrlenEst(pExpr->x.pList->a[0].pExpr, eCode);
   }
 }
 
index 97f96793c60fefcca2bca1a4df55d7d114b70ce0..129a09036876f4ebbc49849af0b7443eb865519e 100644 (file)
@@ -5475,7 +5475,7 @@ void sqlite3DeleteIndexSamples(sqlite3*,Index*);
 void sqlite3DefaultRowEst(Index*);
 void sqlite3RegisterLikeFunctions(sqlite3*, int);
 int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
-int sqlite3ExprStrlenEst(Expr*);
+int sqlite3ExprStrlenEst(Expr*,u16);
 void sqlite3SchemaClear(void *);
 Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
 int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
index a4cb4a53350d11a98ac4eb2b36a667e23eb94780..38e63cc1fe9e686fb5fe08e744119e44f0e80a9f 100644 (file)
@@ -3036,8 +3036,8 @@ static void whereLoopOutputAdjust(
           Expr *pExpr = pTerm->pExpr;
           sqlite3 *db = pWC->pWInfo->pParse->db;
           szPattern = sqlite3IsLikeFunction(db, pExpr, 0, 0);
-          if( szPattern>3 ){
-            pLoop->nOut -= szPattern-3;
+          if( szPattern>0 ){
+            pLoop->nOut -= szPattern*2;
           }
         }
       }