Add new routines to simplify dealing with collating sequences in expressions:
sqlite3ExprNNCollSeq() and sqlite3ExprCollSeqMatch().
FossilOrigin-Name: 490e488ea963fe725b16212822c8608f2b6abce688931b611446bc2cbfe6b87c
diff --git a/src/expr.c b/src/expr.c
index b482faf..8282c99 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -124,6 +124,11 @@
** Return the collation sequence for the expression pExpr. If
** there is no defined collating sequence, return NULL.
**
+** See also: sqlite3ExprNNCollSeq()
+**
+** The sqlite3ExprNNCollSeq() works the same exact that it returns the
+** default collation if pExpr has no defined collation.
+**
** The collating sequence might be determined by a COLLATE operator
** or by the presence of a column with a defined collating sequence.
** COLLATE operators take first precedence. Left operands take
@@ -189,6 +194,32 @@
}
/*
+** Return the collation sequence for the expression pExpr. If
+** there is no defined collating sequence, return a pointer to the
+** defautl collation sequence.
+**
+** See also: sqlite3ExprCollSeq()
+**
+** The sqlite3ExprCollSeq() routine works the same except that it
+** returns NULL if there is no defined collation.
+*/
+CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
+ CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
+ if( p==0 ) p = pParse->db->pDfltColl;
+ assert( p!=0 );
+ return p;
+}
+
+/*
+** Return TRUE if the two expressions have equivalent collating sequences.
+*/
+int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
+ CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
+ CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
+ return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
+}
+
+/*
** pExpr is an operand of a comparison operator. aff2 is the
** type affinity of the other operand. This routine returns the
** type affinity that should be used for the comparison operator.
@@ -1843,8 +1874,8 @@
for(i=0; i<pGroupBy->nExpr; i++){
Expr *p = pGroupBy->a[i].pExpr;
if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){
- CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p);
- if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){
+ CollSeq *pColl = sqlite3ExprNNCollSeq(pWalker->pParse, p);
+ if( sqlite3_stricmp("BINARY", pColl->zName)==0 ){
return WRC_Prune;
}
}
diff --git a/src/select.c b/src/select.c
index 971e7f5..79abda9 100644
--- a/src/select.c
+++ b/src/select.c
@@ -1109,10 +1109,7 @@
if( pInfo ){
assert( sqlite3KeyInfoIsWriteable(pInfo) );
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
- CollSeq *pColl;
- pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- pInfo->aColl[i-iStart] = pColl;
+ pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
}
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 1451400..3259df8 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -4004,6 +4004,8 @@
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
+CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
+int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
Expr *sqlite3ExprSkipCollate(Expr*);
diff --git a/src/where.c b/src/where.c
index a02923c..5a3d44f 100644
--- a/src/where.c
+++ b/src/where.c
@@ -403,8 +403,8 @@
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
- CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
- if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){
+ CollSeq *pColl = sqlite3ExprNNCollSeq(pParse, pList->a[i].pExpr);
+ if( 0==sqlite3StrICmp(pColl->zName, zColl) ){
return i;
}
}
@@ -3579,14 +3579,10 @@
if( j>=pLoop->nLTerm ) continue;
}
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
- const char *z1, *z2;
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- z1 = pColl->zName;
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pTerm->pExpr);
- if( !pColl ) pColl = db->pDfltColl;
- z2 = pColl->zName;
- if( sqlite3StrICmp(z1, z2)!=0 ) continue;
+ if( sqlite3ExprCollSeqMatch(pWInfo->pParse,
+ pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){
+ continue;
+ }
testcase( pTerm->pExpr->op==TK_IS );
}
obSat |= MASKBIT(i);
@@ -3696,8 +3692,7 @@
}
}
if( iColumn!=XN_ROWID ){
- pColl = sqlite3ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
- if( !pColl ) pColl = db->pDfltColl;
+ pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
}
pLoop->u.btree.nIdxCol = j+1;
diff --git a/src/whereexpr.c b/src/whereexpr.c
index da07f56..9f83a84 100644
--- a/src/whereexpr.c
+++ b/src/whereexpr.c
@@ -842,7 +842,6 @@
static int termIsEquivalence(Parse *pParse, Expr *pExpr){
char aff1, aff2;
CollSeq *pColl;
- const char *zColl1, *zColl2;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
@@ -855,11 +854,7 @@
}
pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
if( pColl==0 || sqlite3StrICmp(pColl->zName, "BINARY")==0 ) return 1;
- pColl = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
- zColl1 = pColl ? pColl->zName : 0;
- pColl = sqlite3ExprCollSeq(pParse, pExpr->pRight);
- zColl2 = pColl ? pColl->zName : 0;
- return sqlite3_stricmp(zColl1, zColl2)==0;
+ return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
}
/*