-C CLI\simprovement:\s\sNew\scommand-line\soption\s"--cmdline-edit\sBOOLEAN"\sto\nenable/disable\scommand-line\sediting.\s\sCommand-line\sediting\sis\sdisabled\nby\sdefault\sif\seither\sstdin\sor\sstdout\sis\snot\sa\stty.
-D 2026-07-23T12:12:37.978
+C Add\sthe\sability\sfor\sBloom\sfilters\sto\swork\son\stext\svalues,\sas\slong\sas\nthe\scollating\ssequence\sis\sBINARY.
+D 2026-07-23T16:00:10.290
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F src/btree.c 462c140d0c1af68d75fd13a082f3c08883cc90496c2f02054ec6ca3592ee4b1c
F src/btree.h 2ee0ddfdf4f8530ad1d46afffd7da21a0e243bfab10973011ac6f6b7fb4109a1
F src/btreeInt.h 1e4a7d04e809e98abc39654b6089c60d749a724598041ff553b392a3277e9b98
-F src/build.c dda58ec56d7bfa6193c21e2ccb66547412169cd488d9f7f2d462c30cfd90ea64
+F src/build.c 6d55fcda11273ae382e1bcf9695468ca0c05547a2e2f6f09d64f30cb64f4400e
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9a
F src/dbpage.c c6a9de13b0a01f0bc94a41e16213ab1ecd15ccfe86df7255ced40fda9446257d
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451
-F src/expr.c 15033331b4a3d90c9dedd97706e70224fbf8f6f6f9150265362e82ceb4dc84be
+F src/expr.c b63b6d46f4531df5d35307cec69b0bda3b1c50dfcde6f0c14915291e02012ca3
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
F src/func.c 208b4d073a1e823df8d0e19d0529093c09a9984851dcfda9808445541cefe6d0
F src/sqlite.h.in 2101a2b494cbc282d0dc1c3f631c4fb83060c52876cc9d7615b091ad66d932b1
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 0efd4723bad9124ea1f581d9f1ea0254ac1c6f3e5fb29e4f3dcf36c72485a456
-F src/sqliteInt.h 2637dcfb389e48068388146940e541da7c90cb799d42effe9f4f3215fa73618c
+F src/sqliteInt.h b793a8b93acafdc0e9f0865f78f3ad4041b91565ee7f114b339136ff7059ecae
F src/sqliteLimit.h 7617f2ee673dab382046beba4552283f442cf1a181bb169ac38eb908135dd8da
F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c fcab5d997364c657e973e2bd3b9d2181aeb0926be0c028f20dfd4445894af3b4
F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
-F src/vdbe.c 30a41b3b7452eba63ad6451d74b8363096b82eecb27c4c9ab1cb9c2aa6cf4ffb
+F src/vdbe.c 5ddbf3be0d2a32ee32da6beb17eba46de0d46b4010e8c3aa231e7a7fbf8baa1c
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
F src/vdbeapi.c 6ad0c841b6cb87de068f71787f385149d794e8830176bf72d09a36b9f655ac5b
F src/wal.c abfd99239725a258af4f733681b24dd7a9ee298babe389a36d29c197e2443ebf
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
-F src/where.c 18943748b107b94f35c9170a68b583d0fdea3a2107ce5300f502ae9b954fab31
-F src/whereInt.h 8d94cb116c9e06205c3d5ac87af065fc044f8cf08bfdccd94b6ea1c1308e65da
-F src/wherecode.c bc39ccbe3648f01157038b16cc55bdbff128590972b7185521b5526dc2815765
-F src/whereexpr.c b48dd990a15d36173e12acbcf961b81b2ea9917adeda01b2fdb9821e2cea08f8
+F src/where.c 2f5b4091f37bfac7658ea3d52b2c192d8fb2ec062f232815e0eb5152a46267db
+F src/whereInt.h f039ad303bc2913de673e431821ef8db3b619d249e6e5548d90072a684e72285
+F src/wherecode.c dd500ffc8682ec57d3ac7edee3699b675338c4e885c6d1fdb86c791103ebe1dd
+F src/whereexpr.c 40264a22a796358bd56440daa0355a6513651115fd79bb39ef9cd934a184fdeb
F src/window.c 0d7dacdf2e84c6ee8ff498d5cc881dd245fcb2f14f6c5976e97e112ce96e90dc
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
F test/autoinc.test 9df9930966dbe92c55ef37a4d89112cfd537be0d0596d397177c12db9e581be0
-F test/autoindex1.test 2523a76f30734742c3f4d948d0cbf3b6627f775e7833814f425a2e289ba58b22
+F test/autoindex1.test adb42c4967aba3b7f14f60a70d0a0c83b02d3ac540c6919dd2e2617fafbeace9
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
F test/autoindex3.test ca502c8050166ac6107a7b4fe4e951f4d3270a23a958af02b14f1b962b83c4b6
F test/autoindex4.test 3c2105e9172920e26f950ba3c5823e4972190e022c1e6f260ba476b0af24c593
F test/bindxfer.test efecd12c580c14df5f4ad3b3e83c667744a4f7e0
F test/bitvec.test 75894a880520164d73b1305c1c3f96882615e142
F test/blob.test e7ac6c7d3a985cc4678c64f325292529a69ae252
-F test/bloom1.test 3b6277a647ac503b5d5df331037b0c01c40e88cc9537b94eaf2d8aa334ed4c8f
+F test/bloom1.test dd9847746e1a52db2f19bc5c8cb751990b2eb04692aee6e8c9972b84cd4069bf
F test/boundary1.tcl 6421b2d920d8b09539503a8673339d32f7609eb1
F test/boundary1.test 66d7f4706ccdb42d58eafdb081de07b0eb42d77b
F test/boundary2.tcl e34ef4e930cf1083150d4d2c603e146bd3b76bcb
F test/strict1.test a7f9091603fe71cdc62baab0766684cba12a97ec69bfbb70be965532669cd77a
F test/strict2.test b22c7a98b5000aef937f1990776497f0e979b1a23bc4f63e2d53b00e59b20070
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
-F test/subquery.test 23087f9b1c15ab9cc5231d04946bdebc51db527c95eb9d7434a2222127e17a84
+F test/subquery.test 0a8fc4fc4eb04b9ee40b17f2cc5416aacfbf756b583fa8880b801e395d5abb36
F test/subquery2.test ab96ff3fa9c4e3dce0d699f74e61c50250ed4335bc8f400e127707d552a8999e
F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303
F test/substr.test a673e3763e247e9b5e497a6cacbaf3da2bd8ec8921c0677145c109f2e633f36b
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P f8c408f66257881937ed18b77e274f71dba2d97dd44546372fa0b0a9629efbd2
-R bad555b624f4fd2230e93ef522552de4
+P 675ed9a486fecc734a6aad2e80fd800183c33f72dce1435a193f0e4cf4ede944
+R 00ac7f20a2b69e84c5ddcc65062ebf36
+T *branch * bloom-filter-on-text
+T *sym-bloom-filter-on-text *
+T -sym-trunk *
U drh
-Z 924a5276b6b3c8953d98d053fbac0712
+Z 541ba4b4a08222b7d4ea7f9be1e7e44a
# Remove this line to create a well-formed Fossil manifest.
-branch trunk
-tag trunk
+branch bloom-filter-on-text
+tag bloom-filter-on-text
-675ed9a486fecc734a6aad2e80fd800183c33f72dce1435a193f0e4cf4ede944
+2577edc796505a0a6dabccbcc1bb6a828457092caa4d074561da5e58a6f065a2
return SQLITE_OK;
}
+/*
+** Return true if the index pIdx can support a Bloom filter on its
+** first N columns. Specifically, return true if all of the first N
+** columns have the BINARY collating sequence or no collating sequence
+** at all, and return false if there are any non-BINARY collating
+** seqeuences on any of the first N columns. tag-202607231411
+*/
+int sqlite3IndexBloomable(const Index *pIdx, int N){
+ int i;
+ assert( pIdx!=0 );
+ assert( N <= pIdx->nColumn );
+ for(i=0; i<N; i++){
+ if( sqlite3StrICmp(pIdx->azColl[i],"BINARY")!=0 ) return 0;
+ }
+ return 1;
+}
+
/*
** Estimate the total row width for a table.
*/
}
#endif
pKeyInfo = sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
+ assert( pKeyInfo!=0 || pParse->nErr );
+ if( pKeyInfo==0 ) return;
if( ExprUseXSelect(pExpr) ){
/* Case 1: expr IN (SELECT ...)
sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
+ assert( pEList!=0 );
+ assert( pEList->nExpr>0 );
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ for(i=0; i<nVal; i++){
+ Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
+ CollSeq *pColl;
+ pKeyInfo->aColl[i] = pColl = sqlite3BinaryCompareCollSeq(
+ pParse, p, pEList->a[i].pExpr
+ );
+ if( !sqlite3IsBinary(pColl) ){
+ allowBloom = 0; /* tag-202607231411 */
+ }
+ }
if( addrOnce
&& allowBloom
&& OptimizationEnabled(pParse->db, SQLITE_BloomFilter)
dest.iSDParm2 = regBloom;
}
testcase( pSelect->selFlags & SF_Distinct );
- testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
rc = pParse->db->mallocFailed ? 1 :sqlite3Select(pParse, pCopy, &dest);
sqlite3SelectDelete(pParse->db, pCopy);
sqlite3KeyInfoUnref(pKeyInfo);
return;
}
- assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
- assert( pEList!=0 );
- assert( pEList->nExpr>0 );
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- for(i=0; i<nVal; i++){
- Expr *p = sqlite3VectorFieldSubexpr(pLeft, i);
- pKeyInfo->aColl[i] = sqlite3BinaryCompareCollSeq(
- pParse, p, pEList->a[i].pExpr
- );
- }
}
}else if( ALWAYS(pExpr->x.pList!=0) ){
/* Case 2: expr IN (exprlist)
void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
void sqlite3SrcListDelete(sqlite3*, SrcList*);
Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**);
+int sqlite3IndexBloomable(const Index*,int);
void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Expr*, int, int, u8);
void sqlite3DropIndex(Parse*, SrcList*, int);
/*
** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning
** with pOp->p3. Return the hash.
+**
+** IMPORTANT RESTRICTION (tag-202607231411): This hash is only valid if the
+** collating sequence for TEXT is BINARY. Hence, Bloom filters that use this
+** hash will not work for look-ups that use any other collating sequence.
*/
static u64 filterHash(const Mem *aMem, const Op *pOp){
int i, mx;
}else if( p->flags & MEM_Real ){
h += sqlite3VdbeIntValue(p);
}else if( p->flags & (MEM_Str|MEM_Blob) ){
- /* All strings have the same hash and all blobs have the same hash,
- ** though, at least, those hashes are different from each other and
- ** from NULL. */
- h += 4093 + (p->flags & (MEM_Str|MEM_Blob));
+ u64 x;
+ h += p->n;
+ if( p->n >= sizeof(x) ){
+ memcpy(&x, p->z, sizeof(x));
+ h += x;
+ memcpy(&x, p->z + p->n - sizeof(x), sizeof(x));
+ h += x;
+ }else{
+ x = 0;
+ memcpy(&x, p->z, p->n);
+ h += x;
+ }
}
}
return h;
Bitmask idxCols; /* Bitmap of columns used for indexing */
Bitmask extraCols; /* Bitmap of additional columns */
u8 sentWarning = 0; /* True if a warning has been issued */
- u8 useBloomFilter = 0; /* True to also add a Bloom filter */
+ u8 useBloomFilter = 1; /* True to also add a Bloom filter */
Expr *pPartial = 0; /* Partial Index Expression */
int iContinue = 0; /* Jump here to skip excluded rows */
SrcList *pTabList; /* The complete FROM clause */
pIdx->aiColumn[n] = pTerm->u.x.leftColumn;
pColl = sqlite3ExprCompareCollSeq(pParse, pX);
assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
+ if( !sqlite3IsBinary(pColl) ){
+ /* Disallow the use of a Bloom filter if any non-BINARY collating
+ ** sequence is involved. tag-202607231411 */
+ useBloomFilter = 0;
+ }
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
n++;
- if( ALWAYS(pX->pLeft!=0)
- && sqlite3ExprAffinity(pX->pLeft)!=SQLITE_AFF_TEXT
- ){
- /* TUNING: only use a Bloom filter on an automatic index
- ** if one or more key columns has the ability to hold numeric
- ** values, since strings all have the same hash in the Bloom
- ** filter implementation and hence a Bloom filter on a text column
- ** is not usually helpful. */
- useBloomFilter = 1;
- }
}
}
}
pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
);
if( pLevel->regFilter ){
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0,
regBase, pLoop->u.btree.nEq);
}
}else if( sz>10000000 ){
sz = 10000000;
}
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter);
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
int n = pLoop->u.btree.nEq;
int r1 = sqlite3GetTempRange(pParse, n);
int jj;
+ assert( pIdx!=0 );
for(jj=0; jj<n; jj++){
assert( pIdx->pTable==pItem->pSTab );
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iCur, jj, r1+jj);
pTab->tabFlags |= TF_MaybeReanalyze;
if( i>=1
&& (pLoop->wsFlags & reqFlags)==reqFlags
- /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */
- && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0)
+ && sqlite3WhereLoopBloomable(pLoop)
+ && nSearch > pTab->nRowLogEst
){
- if( nSearch > pTab->nRowLogEst ){
- testcase( pItem->fg.jointype & JT_LEFT );
- pLoop->wsFlags |= WHERE_BLOOMFILTER;
- pLoop->wsFlags &= ~WHERE_IDX_ONLY;
- WHERETRACE(0xffffffff, (
- "-> use Bloom-filter on loop %c because there are ~%.1e "
- "lookups into %s which has only ~%.1e rows\n",
- pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
- (double)sqlite3LogEstToInt(pTab->nRowLogEst)));
- }
+ testcase( pItem->fg.jointype & JT_LEFT );
+ pLoop->wsFlags |= WHERE_BLOOMFILTER;
+ pLoop->wsFlags &= ~WHERE_IDX_ONLY;
+ WHERETRACE(0xffffffff, (
+ "-> use Bloom-filter on loop %c because there are ~%.1e "
+ "lookups into %s which has only ~%.1e rows\n",
+ pLoop->cId, (double)sqlite3LogEstToInt(nSearch), pTab->zName,
+ (double)sqlite3LogEstToInt(pTab->nRowLogEst)));
}
nSearch += pLoop->nOut;
}
&& (pLevel->pRJ = sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0
){
WhereRightJoin *pRJ = pLevel->pRJ;
+ int bBloomable = 0;
pRJ->iMatch = pParse->nTab++;
- pRJ->regBloom = ++pParse->nMem;
- sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
pRJ->regReturn = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn);
assert( pTab==pTabItem->pSTab );
if( HasRowid(pTab) ){
KeyInfo *pInfo;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1);
+ bBloomable = 1;
pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0);
if( pInfo ){
pInfo->aColl[0] = 0;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+ bBloomable = sqlite3IndexBloomable(pPk,pPk->nKeyCol);
+ }
+ if( bBloomable ){
+ pRJ->regBloom = ++pParse->nMem;
+ sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
+ }else{
+ pRJ->regBloom = 0;
}
pLoop->wsFlags &= ~WHERE_IDX_ONLY;
/* The nature of RIGHT JOIN processing is such that it messes up
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
-
-
-
-
+int sqlite3WhereLoopBloomable(const WhereLoop*);
/*
** Bitmasks for the operators on WhereTerm objects. These are all
regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid);
sqlite3VdbeAddOp2(pParse->pVdbe, OP_MustBeInt, regRowid, addrNxt);
VdbeCoverage(pParse->pVdbe);
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, regRowid, 1);
VdbeCoverage(pParse->pVdbe);
r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff);
codeApplyAffinity(pParse, r1, nEq, zStartAff);
sqlite3DbFree(pParse->db, zStartAff);
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
addrNxt, r1, nEq);
VdbeCoverage(pParse->pVdbe);
VdbeComment((v, "NULL-scan pass ctr"));
}
if( pLevel->regFilter ){
+ assert( sqlite3WhereLoopBloomable(pLoop) );
sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
regBase, nEq);
VdbeCoverage(v);
VdbeComment((v, "match against %s", pTab->zName));
sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk);
- sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk);
- sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ if( pRJ->regBloom ){
+ sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ }
sqlite3VdbeJumpHere(v, jmp1);
sqlite3ReleaseTempRange(pParse, r, nPk+1);
}
int iCur = pLevel->iTabCur;
int r = ++pParse->nMem;
int nPk;
- int jmp;
+ int jmp = 0;
int addrCont = sqlite3WhereContinueLabel(pSubWInfo);
Table *pTab = pTabItem->pSTab;
if( HasRowid(pTab) ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
}
}
- jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk);
- VdbeCoverage(v);
+ if( pRJ->regBloom ){
+ jmp = sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk);
+ VdbeCoverage(v);
+ }
sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk);
VdbeCoverage(v);
- sqlite3VdbeJumpHere(v, jmp);
+ if( jmp ) sqlite3VdbeJumpHere(v, jmp);
sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn);
sqlite3WhereEnd(pSubWInfo);
}
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
}
}
+
+/*
+** Return true if the WhereLoop pLoop can be use a Bloom filter.
+** tag-202607231411
+*/
+int sqlite3WhereLoopBloomable(const WhereLoop *pLoop){
+ if( pLoop->wsFlags & WHERE_IPK ) return 1;
+ if( (pLoop->wsFlags & WHERE_INDEXED)!=0 ){
+ return sqlite3IndexBloomable(pLoop->u.btree.pIndex, pLoop->u.btree.nEq);
+ }
+ return 0;
+}
| `--CORRELATED SCALAR SUBQUERY xxxxxx
| `--SEARCH later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)
|--SCAN x USING INDEX sheep_reg_flock_index
+ |--BLOOM FILTER ON y (sheep_no=?)
`--SEARCH y USING AUTOMATIC COVERING INDEX (sheep_no=?) LEFT-JOIN
}
`--SEARCH t0 USING AUTOMATIC PARTIAL COVERING INDEX (x=?)
}
# ^^^^^--- The key feature in the previous result is that no Bloom filter
-# is used. In the following, a Bloom filter is used because the data type
-# is INT instead of TEXT.
+# is used because of the COLLATE rtrim. In the following, a Bloom filter
+# is omitted because collating sequence is binary instead.
do_execsql_test 3.3 {
- CREATE TABLE t1(x INT COLLATE rtrim);
+ CREATE TABLE t1(x INT COLLATE binary);
INSERT INTO t1(x) VALUES ('a'), ('b'), ('c');
CREATE VIEW v1(y) AS SELECT DISTINCT x FROM t1;
- SELECT count(*) FROM t1, v1 WHERE x='b ';
+ SELECT count(*) FROM t1, v1 WHERE x='b';
} 3
do_eqp_test 3.4 {
- SELECT count(*) FROM t1, v1 WHERE x='b ';
+ SELECT count(*) FROM t1, v1 WHERE x='b';
} {
QUERY PLAN
|--CO-ROUTINE v1
| |--SCAN t2
| `--USE TEMP B-TREE FOR GROUP BY
|--SEARCH t1 USING INDEX x11 (bb=?)
+ |--BLOOM FILTER ON v2 (aa=?)
`--SEARCH v2 USING AUTOMATIC COVERING INDEX (aa=?)
}
# ^^^^^^^^^^^^^
# Follow-up on 2025-04-14. Performance issue found while working
# on Fossil (Fossil check-in 2025-04-13T19:54).
#
-do_execsql_test 10.3 {
+do_execsql_test subquery-10.3 {
CREATE TABLE blob(
rid INTEGER PRIMARY KEY,
size INT,