[patches] [PATCH 2/2] sql: use Tarantool routine to get collation

Nikita Pettik korablev at tarantool.org
Wed Feb 28 19:10:09 MSK 2018


As part of data dictionary integration into SQL, it is required to get
collation via Tarantool facilities. This patch makes SQL fetch collation
directly from Tarantool internal structures where it is possible,
instead of SQL structures such as Index, Column or sqlite3*.  Other
usages take place when space is still under construction or space is
ephemeral. In both cases it is impossible find space by its id and as a
consequence - collation as well.

Closes #3123
---
 src/box/sql.c           |  4 +--
 src/box/sql/analyze.c   |  4 +--
 src/box/sql/build.c     | 73 +++++++++++++++++++++++++++++++++++++++++++------
 src/box/sql/callback.c  | 19 +++++++------
 src/box/sql/expr.c      |  9 +++---
 src/box/sql/fkey.c      | 12 ++++----
 src/box/sql/insert.c    |  8 ++++--
 src/box/sql/main.c      |  5 +---
 src/box/sql/pragma.c    |  4 +--
 src/box/sql/select.c    |  8 +++---
 src/box/sql/sqliteInt.h | 10 +++++--
 src/box/sql/vdbesort.c  |  2 +-
 src/box/sql/where.c     | 21 ++++++++------
 13 files changed, 119 insertions(+), 60 deletions(-)

diff --git a/src/box/sql.c b/src/box/sql.c
index b5762a297..a637cc108 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1564,7 +1564,7 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 		struct coll *coll = NULL;
 		if (aCol[i].zColl &&
 		    sqlite3StrICmp(aCol[i].zColl, "binary") != 0) {
-			coll = sqlite3FindCollSeq(NULL, aCol[i].zColl, 0);
+			coll = sqlite3FindCollSeq(aCol[i].zColl);
 		}
 		p = enc->encode_map(p, coll ? 5 : 4);
 		p = enc->encode_str(p, "name", 4);
@@ -1655,7 +1655,7 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
 			t = convertSqliteAffinity(aCol[col].affinity, aCol[col].notNull == 0);
 		/* do not decode default collation */
 		if (sqlite3StrICmp(pIndex->azColl[i], "binary") != 0){
-			collation = sqlite3FindCollSeq(NULL, pIndex->azColl[i], 0);
+			collation = sqlite3FindCollSeq(pIndex->azColl[i]);
 			/* 
 			 * At this point, the collation has already been found 
 			 * once and the assert should not fire.
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index ca8d37c76..bf2b2cb8f 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -975,11 +975,11 @@ analyzeOneTable(Parse * pParse,	/* Parser context */
 				VdbeCoverage(v);
 			}
 			for (i = 0; i < nColTest; i++) {
+				char *zCollName = index_collation_name(pIdx, i);
 				char *pColl =
 				    (char *)sqlite3LocateCollSeq(pParse,
 								 pParse->db,
-								 pIdx->
-								 azColl[i]);
+								 zCollName);
 				sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
 				sqlite3VdbeAddOp3(v, OP_Column, iIdxCur,
 						  pIdx->aiColumn[i], regTemp);
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 9f45c6224..498abd7a1 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -48,6 +48,8 @@
 #include "tarantoolInt.h"
 #include "box/session.h"
 #include "box/identifier.h"
+#include "box/schema.h"
+#include "box/tuple_format.h"
 
 /*
  * This routine is called after a single SQL statement has been
@@ -1157,7 +1159,7 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
 		for (pIdx = p->pIndex; pIdx; pIdx = pIdx->pNext) {
 			assert(pIdx->nKeyCol == 1);
 			if (pIdx->aiColumn[0] == i) {
-				pIdx->azColl[0] = p->aCol[i].zColl;
+				pIdx->azColl[0] = column_collation_name(p, i);
 			}
 		}
 	} else {
@@ -1165,6 +1167,61 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
 	}
 }
 
+/* Return name of collation for given column. */
+char *
+column_collation_name(Table *table, uint32_t column)
+{
+	assert(table != NULL);
+	uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum);
+	struct space *space = space_by_id(space_id);
+	/**
+	 * It is not always possible to fetch collation directly
+	 * from struct space. To be more precise when:
+	 * 1. space is ephemeral. Thus, its id is zero and
+	 *    it can't be found in space cache.
+	 * 2. space is a view. Hence, it lacks any functional
+	 *    parts such as indexes or fields.
+	 * 3. space is under construction. So, the same as p.1
+	 *    it can't be found in space cache.
+	 * In cases mentioned above collation is fetched from
+	 * SQL specific structures.
+	 */
+	if (space == NULL || space_index(space, 0) == NULL)
+		return table->aCol[column].zColl;
+
+	/* "BINARY" is a name for default collation in SQL. */
+	char *coll_name = (char *)sqlite3StrBINARY;
+	if (space->format->fields[column].coll != NULL) {
+		coll_name = space->format->fields[column].coll->name;
+	}
+	return coll_name;
+}
+
+/* Return name of given column collation from index. */
+char *
+index_collation_name(Index *idx, uint32_t column)
+{
+	assert(idx != NULL);
+	uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(idx->pTable->tnum);
+	struct space *space = space_by_id(space_id);
+	/**
+	 * If space is still under construction, or it is
+	 * an ephemeral space, than fetch collation from
+	 * SQL internal structure.
+	 */
+	if (space == NULL)
+		return (char *)idx->azColl[column];
+
+	uint32_t index_id = SQLITE_PAGENO_TO_INDEXID(idx->tnum);
+	struct index *index = space_index(space, index_id);
+	assert(index != NULL && index->def->key_def->part_count >= column);
+	struct coll *coll = index->def->key_def->parts[column].coll;
+	/* "BINARY" is a name for default collation in SQL. */
+	if (coll == NULL)
+		return (char *)sqlite3StrBINARY;
+	return index->def->key_def->parts[column].coll->name;
+}
+
 /*
  * This function returns the collation sequence for database native text
  * encoding identified by the string zName, length nName.
@@ -1192,7 +1249,7 @@ sqlite3LocateCollSeq(Parse * pParse, sqlite3 * db, const char *zName)
 	struct coll *pColl;
 	initbusy = db->init.busy;
 
-	pColl = sqlite3FindCollSeq(db, zName, initbusy);
+	pColl = sqlite3FindCollSeq(zName);
 	if (!initbusy && (!pColl)) {
 		pColl = sqlite3GetCollSeq(pParse, db, pColl, zName);
 	}
@@ -3130,7 +3187,7 @@ sqlite3CreateIndex(Parse * pParse,	/* All information about this parse */
 			zExtra += nColl;
 			nExtra -= nColl;
 		} else if (j >= 0) {
-			zColl = pTab->aCol[j].zColl;
+			zColl = column_collation_name(pTab, j);
 		}
 		if (!zColl)
 			zColl = sqlite3StrBINARY;
@@ -3189,8 +3246,8 @@ sqlite3CreateIndex(Parse * pParse,	/* All information about this parse */
 				assert(pIdx->aiColumn[k] >= 0);
 				if (pIdx->aiColumn[k] != pIndex->aiColumn[k])
 					break;
-				z1 = pIdx->azColl[k];
-				z2 = pIndex->azColl[k];
+				z1 = index_collation_name(pIdx, k);
+				z2 = index_collation_name(pIndex, k);
 				if (strcmp(z1, z2))
 					break;
 			}
@@ -4129,7 +4186,7 @@ collationMatch(const char *zColl, Index * pIndex)
 	int i;
 	assert(zColl != 0);
 	for (i = 0; i < pIndex->nColumn; i++) {
-		const char *z = pIndex->azColl[i];
+		const char *z = index_collation_name(pIndex, i);
 		assert(z != 0 || pIndex->aiColumn[i] < 0);
 		if (pIndex->aiColumn[i] >= 0 && 0 == sqlite3StrICmp(z, zColl)) {
 			return 1;
@@ -4222,7 +4279,7 @@ sqlite3Reindex(Parse * pParse, Token * pName1, Token * pName2)
 		zColl = sqlite3NameFromToken(pParse->db, pName1);
 		if (!zColl)
 			return;
-		pColl = sqlite3FindCollSeq(db, zColl, 0);
+		pColl = sqlite3FindCollSeq(zColl);
 		if (pColl) {
 			reindexDatabases(pParse, zColl);
 			sqlite3DbFree(db, zColl);
@@ -4299,7 +4356,7 @@ sqlite3KeyInfoOfIndex(Parse * pParse, sqlite3 * db, Index * pIdx)
 	if (pKey) {
 		assert(sqlite3KeyInfoIsWriteable(pKey));
 		for (i = 0; i < nCol; i++) {
-			const char *zColl = pIdx->azColl[i];
+			const char *zColl = index_collation_name(pIdx, i);
 			pKey->aColl[i] = zColl == sqlite3StrBINARY ? 0 :
 			    sqlite3LocateCollSeq(pParse, db, zColl);
 			pKey->aSortOrder[i] = pIdx->aSortOrder[i];
diff --git a/src/box/sql/callback.c b/src/box/sql/callback.c
index 5f2ddeaee..8cc224253 100644
--- a/src/box/sql/callback.c
+++ b/src/box/sql/callback.c
@@ -60,11 +60,12 @@ sqlite3GetCollSeq(Parse * pParse,	/* Parsing context */
 		  const char *zName	/* Collating sequence name */
     )
 {
+	(void)db;
 	struct coll *p;
 
 	p = pColl;
 	if (!p) {
-		p = sqlite3FindCollSeq(db, zName, 0);
+		p = sqlite3FindCollSeq(zName);
 	}
 	if (p == 0) {
 		if (pParse)
@@ -141,13 +142,15 @@ static struct coll_plus_name_struct binary_coll_with_name =
 		"BINARY"};
 static struct coll * binary_coll = (struct coll*)&binary_coll_with_name;
 
+struct coll *
+sql_default_coll()
+{
+	return binary_coll;
+}
+
 /*
  * Parameter zName points to a UTF-8 encoded string nName bytes long.
- * Return the CollSeq* pointer for the collation sequence named zName
- * for the encoding 'enc' from the database 'db'.
- *
- * If the entry specified is not found and 'create' is true, then create a
- * new entry.  Otherwise return NULL.
+ * Return the CollSeq* pointer for the collation sequence named zName.
  *
  * A separate function sqlite3LocateCollSeq() is a wrapper around
  * this routine.  sqlite3LocateCollSeq() invokes the collation factory
@@ -157,10 +160,8 @@ static struct coll * binary_coll = (struct coll*)&binary_coll_with_name;
  * See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()
  */
 struct coll *
-sqlite3FindCollSeq(sqlite3 * db, const char *zName, int create)
+sqlite3FindCollSeq(const char *zName)
 {
-	(void)db;
-	(void)create;
 	if (zName == NULL || sqlite3StrICmp(zName, "binary")==0){
 		return binary_coll;
 	}
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index b69a176cb..7ca6bef34 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -195,9 +195,9 @@ sqlite3ExprCollSeq(Parse * pParse, Expr * pExpr)
 			 */
 			int j = p->iColumn;
 			if (j >= 0) {
-				const char *zColl = p->pTab->aCol[j].zColl;
+				const char *zColl = column_collation_name(p->pTab, j);
 				pColl =
-				    sqlite3FindCollSeq(db, zColl, 0);
+				    sqlite3FindCollSeq(zColl);
 			}
 			break;
 		}
@@ -2552,10 +2552,9 @@ sqlite3FindInIndex(Parse * pParse,	/* Parsing context */
 						if (pIdx->aiColumn[j]
 						    != pRhs->iColumn)
 							continue;
-						assert(pIdx->azColl[j]);
 						if (pReq != 0 && strcmp
 						    (pReq->name,
-						     pIdx->azColl[j]) != 0) {
+						     index_collation_name(pIdx, j)) != 0) {
 							continue;
 						}
 						break;
@@ -4217,7 +4216,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 			}
 			if (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL) {
 				if (!pColl)
-					pColl = db->pDfltColl;
+					pColl = sql_default_coll();
 				sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0,
 						  (char *)pColl, P4_COLLSEQ);
 			}
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index 088d84e27..2ce99459b 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -296,11 +296,11 @@ sqlite3FkLocateIndex(Parse * pParse,	/* Parse context to store any error in */
 					 * the default collation sequence for the column, this index is
 					 * unusable. Bail out early in this case.
 					 */
-					zDfltColl = pParent->aCol[iCol].zColl;
-					if (!zDfltColl)
-						zDfltColl = sqlite3StrBINARY;
+					zDfltColl =
+						column_collation_name(pParent,
+								      iCol);
 					if (strcmp
-					    (pIdx->azColl[i], zDfltColl))
+					    (index_collation_name(pIdx, i), zDfltColl))
 						break;
 
 					zIdxCol = pParent->aCol[iCol].zName;
@@ -534,9 +534,7 @@ exprTableRegister(Parse * pParse,	/* Parsing and code generating context */
 			pCol = &pTab->aCol[iCol];
 			pExpr->iTable = regBase + iCol + 1;
 			pExpr->affinity = pCol->affinity;
-			zColl = pCol->zColl;
-			if (zColl == 0)
-				zColl = db->pDfltColl->name;
+			zColl = column_collation_name(pTab, iCol);
 			pExpr =
 			    sqlite3ExprAddCollateString(pParse, pExpr, zColl);
 		} else {
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index b20a47970..da50f1c31 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -1403,7 +1403,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 				for (i = 0; i < pPk->nKeyCol; i++) {
 					char *p4 = (char *)
 						sqlite3LocateCollSeq(pParse, db,
-								     pPk->azColl[i]);
+								     index_collation_name(pPk, i));
 					x = pPk->aiColumn[i];
 					assert(x >= 0);
 					if (i == (pPk->nKeyCol - 1)) {
@@ -1687,7 +1687,8 @@ xferCompatibleIndex(Index * pDest, Index * pSrc)
 		if (pSrc->aSortOrder[i] != pDest->aSortOrder[i]) {
 			return 0;	/* Different sort orders */
 		}
-		if (sqlite3_stricmp(pSrc->azColl[i], pDest->azColl[i]) != 0) {
+		if (sqlite3_stricmp(index_collation_name(pSrc, i),
+				    index_collation_name(pDest, i)) != 0) {
 			return 0;	/* Different collating sequences */
 		}
 	}
@@ -1832,7 +1833,8 @@ xferOptimization(Parse * pParse,	/* Parser context */
 		if (pDestCol->affinity != pSrcCol->affinity) {
 			return 0;	/* Affinity must be the same on all columns */
 		}
-		if (sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl) != 0) {
+		if (sqlite3_stricmp(column_collation_name(pDest, i),
+				    column_collation_name(pSrc, i)) != 0) {
 			return 0;	/* Collating sequence must be the same on all columns */
 		}
 		if (!table_column_is_nullable(pDest, i)
diff --git a/src/box/sql/main.c b/src/box/sql/main.c
index 9cda5f3e9..d58b3e8b6 100644
--- a/src/box/sql/main.c
+++ b/src/box/sql/main.c
@@ -2417,9 +2417,6 @@ openDatabase(const char *zFilename,	/* Database filename UTF-8 encoded */
 	/* EVIDENCE-OF: R-08308-17224 The default collating function for all
 	 * strings is BINARY.
 	 */
-	db->pDfltColl =
-	    sqlite3FindCollSeq(db, sqlite3StrBINARY, 0);
-	assert(db->pDfltColl != 0);
 
 	db->openFlags = flags;
 	/* Parse the filename/URI argument. */
@@ -2719,7 +2716,7 @@ sqlite3_table_column_metadata(sqlite3 * db,		/* Connection handle */
 	 */
 	if (pCol) {
 		zDataType = sqlite3ColumnType(pCol, 0);
-		zCollSeq = pCol->zColl;
+		zCollSeq = column_collation_name(pTab, iCol);
 		notnull = table_column_is_nullable(pTab, iCol) == 0;
 		primarykey = (pCol->colFlags & COLFLAG_PRIMKEY) != 0;
 		autoinc = pTab->iPKey == iCol
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index 03ae926e0..17d8f369b 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -460,9 +460,7 @@ sqlite3Pragma(Parse * pParse, Token * pId,	/* First part of [schema.]id field */
 									     pIdx->
 									     aSortOrder
 									     [i],
-									     pIdx->
-									     azColl
-									     [i],
+									     index_collation_name(pIdx, i),
 									     i <
 									     pIdx->
 									     nKeyCol);
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 041e6ca87..f716d9200 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1297,7 +1297,7 @@ keyInfoFromExprList(Parse * pParse,	/* Parsing context */
 			struct coll *pColl;
 			pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);
 			if (!pColl)
-				pColl = db->pDfltColl;
+				pColl = sql_default_coll();
 			pInfo->aColl[i - iStart] = pColl;
 			pInfo->aSortOrder[i - iStart] = pItem->sortOrder;
 		}
@@ -2232,7 +2232,7 @@ multiSelectOrderByKeyInfo(Parse * pParse, Select * p, int nExtra)
 				    multiSelectCollSeq(pParse, p,
 						       pItem->u.x.iOrderByCol - 1);
 				if (pColl == 0)
-					pColl = db->pDfltColl;
+					pColl = sql_default_coll();
 				pOrderBy->a[i].pExpr =
 				    sqlite3ExprAddCollateString(pParse, pTerm,
 								pColl->name);
@@ -2893,7 +2893,7 @@ multiSelect(Parse * pParse,	/* Parsing context */
 		for (i = 0, apColl = pKeyInfo->aColl; i < nCol; i++, apColl++) {
 			*apColl = multiSelectCollSeq(pParse, p, i);
 			if (0 == *apColl) {
-				*apColl = db->pDfltColl;
+				*apColl = sql_default_coll();
 			}
 		}
 
@@ -5336,7 +5336,7 @@ updateAccumulator(Parse * pParse, AggInfo * pAggInfo)
 				    sqlite3ExprCollSeq(pParse, pItem->pExpr);
 			}
 			if (!pColl) {
-				pColl = pParse->db->pDfltColl;
+				pColl = sql_default_coll();
 			}
 			if (regHit == 0 && pAggInfo->nAccumulator)
 				regHit = ++pParse->nMem;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index aebb61029..3962c29da 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1091,8 +1091,6 @@ struct sqlite3 {
 					   sqlite3_int64);
 	PreUpdate *pPreUpdate;	/* Context for active pre-update callback */
 #endif				/* SQLITE_ENABLE_PREUPDATE_HOOK */
-	void (*xCollNeeded) (void *, sqlite3 *, const char *);
-	void *pCollNeededArg;
 	sqlite3_value *pErr;	/* Most recent error message */
 	union {
 		volatile int isInterrupted;	/* True if sqlite3_interrupt has been called */
@@ -3117,6 +3115,12 @@ void sqlite3AddPrimaryKey(Parse *, ExprList *, int, int, int);
 void sqlite3AddCheckConstraint(Parse *, Expr *);
 void sqlite3AddDefaultValue(Parse *, ExprSpan *);
 void sqlite3AddCollateType(Parse *, Token *);
+char *
+column_collation_name(Table *, uint32_t);
+char *
+index_collation_name(Index *, uint32_t);
+struct coll *
+sql_default_coll();
 void sqlite3EndTable(Parse *, Token *, Token *, u8, Select *);
 int sqlite3ParseUri(const char *, const char *, unsigned int *,
 		    sqlite3_vfs **, char **, char **);
@@ -3412,7 +3416,7 @@ const char *sqlite3ErrName(int);
 
 const char *sqlite3ErrStr(int);
 int sqlite3ReadSchema(Parse * pParse);
-struct coll *sqlite3FindCollSeq(sqlite3 *, const char *, int);
+struct coll *sqlite3FindCollSeq(const char *);
 struct coll *sqlite3LocateCollSeq(Parse * pParse, sqlite3 * db, const char *zName);
 struct coll *sqlite3ExprCollSeq(Parse * pParse, Expr * pExpr);
 Expr *sqlite3ExprAddCollateToken(Parse * pParse, Expr *, const Token *, int);
diff --git a/src/box/sql/vdbesort.c b/src/box/sql/vdbesort.c
index 5bfd644ba..ec3214fab 100644
--- a/src/box/sql/vdbesort.c
+++ b/src/box/sql/vdbesort.c
@@ -942,7 +942,7 @@ sqlite3VdbeSorterInit(sqlite3 * db,	/* Database connection (for malloc()) */
 
 		if ((pKeyInfo->nField + pKeyInfo->nXField) < 13
 		    && (pKeyInfo->aColl[0] == 0
-			|| pKeyInfo->aColl[0] == db->pDfltColl)
+			|| pKeyInfo->aColl[0] == sql_default_coll())
 		    ) {
 			pSorter->typeMask =
 			    SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index 2f1c627e5..7b5698e07 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -314,7 +314,7 @@ whereScanNext(WhereScan * pScan)
 							     pX->pRight);
 							if (pColl == 0)
 								pColl =
-								    pParse->db->pDfltColl;
+									sql_default_coll();
 							if (strcmp(pColl->name,
 									   pScan->zCollName)) {
 								continue;
@@ -384,7 +384,7 @@ whereScanInit(WhereScan * pScan,	/* The WhereScan object being initialized */
 			pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
 		} else if (iColumn >= 0) {
 			pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
-			pScan->zCollName = pIdx->azColl[j];
+			pScan->zCollName = index_collation_name(pIdx, j);
 		}
 	} else if (iColumn == XN_EXPR) {
 		return 0;
@@ -466,7 +466,7 @@ findIndexCol(Parse * pParse,	/* Parse context */
 	     int iCol)		/* Column of index to match */
 {
 	int i;
-	const char *zColl = pIdx->azColl[iCol];
+	const char *zColl = index_collation_name(pIdx, iCol);
 
 	for (i = 0; i < pList->nExpr; i++) {
 		Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
@@ -1174,7 +1174,7 @@ whereRangeSkipScanEst(Parse * pParse,		/* Parsing & code generating context */
 	sqlite3_value *p2 = 0;	/* Value extracted from pUpper */
 	sqlite3_value *pVal = 0;	/* Value extracted from record */
 
-	pColl = sqlite3LocateCollSeq(pParse, db, p->azColl[nEq]);
+	pColl = sqlite3LocateCollSeq(pParse, db, index_collation_name(p, nEq));
 	if (pLower) {
 		rc = sqlite3Stat4ValueFromExpr(pParse, pLower->pExpr->pRight,
 					       aff, &p1);
@@ -2246,7 +2246,8 @@ whereRangeVectorLen(Parse * pParse,	/* Parsing context */
 		pColl = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
 		if (pColl == 0)
 			break;
-		if (strcmp(pColl->name, pIdx->azColl[i + nEq]))
+		char *zCollName = index_collation_name(pIdx, i + nEq);
+		if (zCollName && strcmp(pColl->name, zCollName))
 			break;
 	}
 	return i;
@@ -3267,13 +3268,13 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo,	/* The WHERE clause */
 				    sqlite3ExprCollSeq(pWInfo->pParse,
 						       pOrderBy->a[i].pExpr);
 				if (!pColl)
-					pColl = db->pDfltColl;
+					pColl = sql_default_coll();
 				z1 = pColl->name;
 				pColl =
 				    sqlite3ExprCollSeq(pWInfo->pParse,
 						       pTerm->pExpr);
 				if (!pColl)
-					pColl = db->pDfltColl;
+					pColl = sql_default_coll();
 				z2 = pColl->name;
 				if (strcmp(z1, z2) != 0)
 					continue;
@@ -3405,9 +3406,11 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo,	/* The WHERE clause */
 						    sqlite3ExprCollSeq(pWInfo->pParse,
 								       pOrderBy->a[i].pExpr);
 						if (!pColl)
-							pColl = db->pDfltColl;
+							pColl = sql_default_coll();
+						char *zCollName =
+							index_collation_name(pIndex, j);
 						if (strcmp(pColl->name,
-								   pIndex->azColl[j]) != 0)
+							   zCollName) != 0)
 							continue;
 					}
 					isMatch = 1;
-- 
2.15.1




More information about the Tarantool-patches mailing list