aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2024-04-23 12:02:03 +0000
committerdrh <>2024-04-23 12:02:03 +0000
commit14602eafa74c2551deeb606b8de2ff9e4190be46 (patch)
tree0e079a13bb88d899088fb19b8f321a587bb08622 /src
parent3ac612dd7d242c5ed0d23000b7cb212e75a10874 (diff)
parent0309fb919aef74ee2df3b87871c43da025cefeb4 (diff)
downloadsqlite-14602eafa74c2551deeb606b8de2ff9e4190be46.tar.gz
sqlite-14602eafa74c2551deeb606b8de2ff9e4190be46.zip
Fix a problem with vector IN operators used with an index where the affinities
and collations for the various vector terms are different. FossilOrigin-Name: 86e8c782e7494377de3c27b750cd83a7eb2302c1182ee2004d3864db50fca557
Diffstat (limited to 'src')
-rw-r--r--src/where.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/src/where.c b/src/where.c
index 95bea115d..39210ddb2 100644
--- a/src/where.c
+++ b/src/where.c
@@ -303,6 +303,42 @@ static Expr *whereRightSubexprIsColumn(Expr *p){
}
/*
+** Term pTerm is guaranteed to be a WO_IN term. It may be a component term
+** of a vector IN expression of the form "(x, y, ...) IN (SELECT ...)".
+** This function checks to see if the term is compatible with an index
+** column with affinity idxaff (one of the SQLITE_AFF_XYZ values). If so,
+** it returns a pointer to the name of the collation sequence (e.g. "BINARY"
+** or "NOCASE") used by the comparison in pTerm. If it is not compatible
+** with affinity idxaff, NULL is returned.
+*/
+static SQLITE_NOINLINE const char *indexInAffinityOk(
+ Parse *pParse,
+ WhereTerm *pTerm,
+ u8 idxaff
+){
+ Expr *pX = pTerm->pExpr;
+ Expr inexpr;
+
+ assert( pTerm->eOperator & WO_IN );
+
+ if( sqlite3ExprIsVector(pX->pLeft) ){
+ int iField = pTerm->u.x.iField - 1;
+ inexpr.flags = 0;
+ inexpr.op = TK_EQ;
+ inexpr.pLeft = pX->pLeft->x.pList->a[iField].pExpr;
+ assert( ExprUseXSelect(pX) );
+ inexpr.pRight = pX->x.pSelect->pEList->a[iField].pExpr;
+ pX = &inexpr;
+ }
+
+ if( sqlite3IndexAffinityOk(pX, idxaff) ){
+ CollSeq *pRet = sqlite3ExprCompareCollSeq(pParse, pX);
+ return pRet ? pRet->zName : sqlite3StrBINARY;
+ }
+ return 0;
+}
+
+/*
** Advance to the next WhereTerm that matches according to the criteria
** established when the pScan object was initialized by whereScanInit().
** Return NULL if there are no more matching WhereTerms.
@@ -352,16 +388,24 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
if( (pTerm->eOperator & pScan->opMask)!=0 ){
/* Verify the affinity and collating sequence match */
if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){
- CollSeq *pColl;
+ const char *zCollName;
Parse *pParse = pWC->pWInfo->pParse;
pX = pTerm->pExpr;
- if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
- continue;
+
+ if( (pTerm->eOperator & WO_IN) ){
+ zCollName = indexInAffinityOk(pParse, pTerm, pScan->idxaff);
+ if( !zCollName ) continue;
+ }else{
+ CollSeq *pColl;
+ if( !sqlite3IndexAffinityOk(pX, pScan->idxaff) ){
+ continue;
+ }
+ assert(pX->pLeft);
+ pColl = sqlite3ExprCompareCollSeq(pParse, pX);
+ zCollName = pColl ? pColl->zName : sqlite3StrBINARY;
}
- assert(pX->pLeft);
- pColl = sqlite3ExprCompareCollSeq(pParse, pX);
- if( pColl==0 ) pColl = pParse->db->pDfltColl;
- if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
+
+ if( sqlite3StrICmp(zCollName, pScan->zCollName) ){
continue;
}
}