-C Fix\sthe\snew\sfilterHash()\sfunction\sso\sthat\sit\sworks\scorrectly\sfor\szeroblobs.
-D 2026-07-23T17:41:10.955
+C Improved\sBloom-filter\sinvariant\schecking.
+D 2026-07-23T18:55:12.383
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F src/dbpage.c c6a9de13b0a01f0bc94a41e16213ab1ecd15ccfe86df7255ced40fda9446257d
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451
-F src/expr.c b63b6d46f4531df5d35307cec69b0bda3b1c50dfcde6f0c14915291e02012ca3
+F src/expr.c fb5075dc231746e795817b096c39d0d1423d8ec29697e97959a50db84dcff211
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 931f74cec1dc8038a0217ef340c91ce147dd1bbed08dc40c47ee0ec6edfffb08
F src/func.c 208b4d073a1e823df8d0e19d0529093c09a9984851dcfda9808445541cefe6d0
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 54395ee97eb710e695202d4112cf2b1c1c7767a57afcea745df71abb1c917768
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c 586ccc75f2fa289c51554330f9ff549d00dae4122ac7e2af712437e2ef737cc8
+F src/select.c d2ad83d49c41c30d213873bac8481c6bf099438c61dcb597de52ddb55a6324fb
F src/shell.c.in 0df571dd1eae1a15577361902eb5487a072d3290ea94e1e72e757050b641f870
F src/sqlite.h.in 2101a2b494cbc282d0dc1c3f631c4fb83060c52876cc9d7615b091ad66d932b1
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/where.c 2f5b4091f37bfac7658ea3d52b2c192d8fb2ec062f232815e0eb5152a46267db
F src/whereInt.h f039ad303bc2913de673e431821ef8db3b619d249e6e5548d90072a684e72285
F src/wherecode.c dd500ffc8682ec57d3ac7edee3699b675338c4e885c6d1fdb86c791103ebe1dd
-F src/whereexpr.c 40264a22a796358bd56440daa0355a6513651115fd79bb39ef9cd934a184fdeb
+F src/whereexpr.c 07ffa5d16d970d89a2714cdd92d99058340f88c705e7e7ea6efe272a8ad1f91e
F src/window.c 0d7dacdf2e84c6ee8ff498d5cc881dd245fcb2f14f6c5976e97e112ce96e90dc
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test 4d7a34d328e58ca2a2d78fd76c27614a41ca7ddf4312ded9c68c04f430b3b47d
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 2577edc796505a0a6dabccbcc1bb6a828457092caa4d074561da5e58a6f065a2
-R 87295a0ea0d1f9c5765acc4473724fdc
+P 3013d6ab4afd4f63fa63a773778adcf07821cfcb33e3ae42752aea13fd2b6224
+R 0e1584e2f9d4a83856c66208401cbfea
U drh
-Z 0a7b98af243154566c4b036f9155b275
+Z 3049f8ec6b5a896c591d2da0158d3d82
# Remove this line to create a well-formed Fossil manifest.
-3013d6ab4afd4f63fa63a773778adcf07821cfcb33e3ae42752aea13fd2b6224
+f38f4167110df11ba54816932126f695dc6e114d4001d0261669807a55ad7966
addrBloom = sqlite3VdbeAddOp2(v, OP_Blob, 10000, regBloom);
VdbeComment((v, "Bloom filter"));
dest.iSDParm2 = regBloom;
+ sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
+ pKeyInfo = 0;
}
testcase( pSelect->selFlags & SF_Distinct );
pCopy = sqlite3SelectDup(pParse->db, pSelect, 0);
}else if( affinity==SQLITE_AFF_REAL ){
affinity = SQLITE_AFF_NUMERIC;
}
- if( pKeyInfo ){
- assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
- pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- }
+ assert( pKeyInfo!=0 );
+ assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
+ pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
}
#endif
+#ifdef SQLITE_DEBUG
+/*
+** This is a byte-code validation check that only runs when SQLITE_DEBUG
+** is defined. This routine looks backwards through the bytecode
+** for the definition of cursor with index iCur. It extracts the KeyInfo from
+** that cursor (it must be an index cursor) and verifies that the cursor
+** does not use any collating seqeuences other than BINARY for its first
+** nCol columns.
+**
+** This routine is used inside of an assert(). So it should return true
+** on success and false if the invariant is not satisfied.
+**
+** tag-202607231411
+*/
+static int sqlite3CursorBloomable(Parse *pParse, int iCur, int nCol){
+ int i,k;
+ Vdbe *v = pParse->pVdbe;
+ if( pParse->nErr ) return 1;
+ assert( v );
+ for(k=sqlite3VdbeCurrentAddr(v)-1; k>0; k--){
+ const VdbeOp *pOp = sqlite3VdbeGetOp(v, k);
+ const KeyInfo *pKeyInfo;
+ if( pOp->p1!=iCur ) continue;
+ if( pOp->opcode!=OP_OpenRead
+ && pOp->opcode!=OP_OpenWrite
+ && pOp->opcode!=OP_OpenEphemeral
+ ){
+ continue;
+ }
+ assert( pOp->p4type==P4_KEYINFO );
+ pKeyInfo = (const KeyInfo*)pOp->p4.pKeyInfo;
+ assert( pKeyInfo!=0 );
+ for(i=0; i<nCol; i++){
+ assert( sqlite3IsBinary(pKeyInfo->aColl[i]) );
+ }
+ return 1;
+ }
+ return 0;
+}
+#endif /* SQLITE_DEBUG */
+
+
/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
r1, pDest->zAffSdst, nResultCol);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
if( pDest->iSDParm2 ){
+ assert( sqlite3CursorBloomable(pParse,iParm,nResultCol) );
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
regResult, nResultCol);
ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
if( pDest->iSDParm2>0 ){
+ assert( sqlite3CursorBloomable(pParse, pDest->iSDParm, pIn->nSdst) );
sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pDest->iSDParm2, 0,
pIn->iSdst, pIn->nSdst);
ExplainQueryPlan((pParse, 0, "CREATE BLOOM FILTER"));
*/
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;
+ if( NEVER((pLoop->wsFlags & WHERE_INDEXED)==0) ) return 0;
+ return sqlite3IndexBloomable(pLoop->u.btree.pIndex, pLoop->u.btree.nEq);
}