[tarantool-patches] [PATCH 2/3] sql: remove expressions from SQL indexes

Kirill Yukhin kyukhin at tarantool.org
Fri Jun 1 18:16:11 MSK 2018


Legacy SQL FE was able to create indexes w/ expressions.
Tarantool will employ diofferenct scheme to implement
functional indexes, thus code  handling it in SQL FE is
dead and redundant. Remove it.

Part of #3235
---
 src/box/sql/build.c     | 22 ++++++---------
 src/box/sql/delete.c    |  3 +--
 src/box/sql/expr.c      | 12 ++-------
 src/box/sql/insert.c    | 72 +++++++++++++++----------------------------------
 src/box/sql/sqliteInt.h |  6 -----
 src/box/sql/where.c     | 27 ++-----------------
 src/box/sql/wherecode.c | 13 +++------
 src/box/sql/whereexpr.c | 36 +++----------------------
 8 files changed, 42 insertions(+), 149 deletions(-)

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 28e4d7a..65bba1f 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -252,7 +252,6 @@ static void
 freeIndex(sqlite3 * db, Index * p)
 {
 	sql_expr_delete(db, p->pPartIdxWhere, false);
-	sql_expr_list_delete(db, p->aColExpr);
 	sqlite3DbFree(db, p->zColAff);
 	sqlite3DbFree(db, p);
 }
@@ -3042,8 +3041,7 @@ sql_create_index(struct Parse *parse, struct Token *token,
 
 	/* Analyze the list of expressions that form the terms of the index and
 	 * report any errors.  In the common case where the expression is exactly
-	 * a table column, store that column in aiColumn[].  For general expressions,
-	 * populate pIndex->aColExpr and store XN_EXPR (-2) in aiColumn[].
+	 * a table column, store that column in aiColumn[].
 	 *
 	 * TODO: Issue a warning if two or more columns of the index are identical.
 	 * TODO: Issue a warning if the table primary key is used as part of the
@@ -3938,17 +3936,13 @@ sqlite3UniqueConstraint(Parse * pParse,	/* Parsing context */
 	Table *pTab = pIdx->pTable;
 
 	sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200);
-	if (pIdx->aColExpr) {
-		sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName);
-	} else {
-		for (j = 0; j < pIdx->nColumn; j++) {
-			char *zCol;
-			assert(pIdx->aiColumn[j] >= 0);
-			zCol = pTab->def->fields[pIdx->aiColumn[j]].name;
-			if (j)
-				sqlite3StrAccumAppend(&errMsg, ", ", 2);
-			sqlite3XPrintf(&errMsg, "%s.%s", pTab->def->name, zCol);
-		}
+	for (j = 0; j < pIdx->nColumn; j++) {
+		char *zCol;
+		assert(pIdx->aiColumn[j] >= 0);
+		zCol = pTab->def->fields[pIdx->aiColumn[j]].name;
+		if (j)
+			sqlite3StrAccumAppend(&errMsg, ", ", 2);
+		sqlite3XPrintf(&errMsg, "%s.%s", pTab->def->name, zCol);
 	}
 	zErr = sqlite3StrAccumFinish(&errMsg);
 	sqlite3HaltConstraint(pParse,
diff --git a/src/box/sql/delete.c b/src/box/sql/delete.c
index 28713c8..2b59130 100644
--- a/src/box/sql/delete.c
+++ b/src/box/sql/delete.c
@@ -564,8 +564,7 @@ sql_generate_index_key(struct Parse *parse, struct Index *index, int cursor,
 			     prev->pPartIdxWhere != NULL))
 		prev = NULL;
 	for (int j = 0; j < col_cnt; j++) {
-		if (prev != NULL && prev->aiColumn[j] == index->aiColumn[j]
-		    && prev->aiColumn[j] != XN_EXPR) {
+		if (prev != NULL && prev->aiColumn[j] == index->aiColumn[j]) {
 			/*
 			 * This column was already computed by the
 			 * previous index.
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 8866f6f..a69d38b 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -3484,16 +3484,8 @@ sqlite3ExprCodeLoadIndexColumn(Parse * pParse,	/* The parsing context */
     )
 {
 	i16 iTabCol = pIdx->aiColumn[iIdxCol];
-	if (iTabCol == XN_EXPR) {
-		assert(pIdx->aColExpr);
-		assert(pIdx->aColExpr->nExpr > iIdxCol);
-		pParse->iSelfTab = iTabCur;
-		sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[iIdxCol].pExpr,
-				    regOut);
-	} else {
-		sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable->def,
-						iTabCur, iTabCol, regOut);
-	}
+	sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pIdx->pTable->def,
+					iTabCur, iTabCol, regOut);
 }
 
 void
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 59c61c7..3dbf855 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -98,21 +98,9 @@ sqlite3IndexAffinityStr(sqlite3 * db, Index * pIdx)
 		}
 		for (n = 0; n < nColumn; n++) {
 			i16 x = pIdx->aiColumn[n];
-			if (x >= 0) {
-				char affinity = pIdx->pTable->
-					def->fields[x].affinity;
-				pIdx->zColAff[n] = affinity;
-			} else {
-				char aff;
-				assert(x == XN_EXPR);
-				assert(pIdx->aColExpr != 0);
-				aff =
-				    sqlite3ExprAffinity(pIdx->aColExpr->a[n].
-							pExpr);
-				if (aff == 0)
-					aff = AFFINITY_BLOB;
-				pIdx->zColAff[n] = aff;
-			}
+			char affinity = pIdx->pTable->
+				def->fields[x].affinity;
+			pIdx->zColAff[n] = affinity;
 		}
 		pIdx->zColAff[n] = 0;
 	}
@@ -1256,34 +1244,24 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 		for (i = 0; i < nIdxCol; i++) {
 			int iField = pIdx->aiColumn[i];
 			int x;
-			if (iField == XN_EXPR) {
-				pParse->ckBase = regNewData + 1;
-				sqlite3ExprCodeCopy(pParse,
-						    pIdx->aColExpr->a[i].pExpr,
-						    regIdx + i);
-				pParse->ckBase = 0;
-				VdbeComment((v, "%s column %d", pIdx->zName,
-					     i));
-			} else {
-				/* OP_SCopy copies value in separate register,
-				 * which later will be used by OP_NoConflict.
-				 * But OP_NoConflict is necessary only in cases
-				 * when bytecode is needed for proper UNIQUE
-				 * constraint handling.
-				 */
-				if (uniqueByteCodeNeeded) {
-					if (iField == pTab->iPKey)
-						x = regNewData;
-					else
-						x = iField + regNewData + 1;
-
-					assert(iField >= 0);
-					sqlite3VdbeAddOp2(v, OP_SCopy,
-							  x, regIdx + i);
-					VdbeComment((v, "%s",
-						     pTab->def->fields[
-							iField].name));
-				}
+			/* OP_SCopy copies value in separate register,
+			 * which later will be used by OP_NoConflict.
+			 * But OP_NoConflict is necessary only in cases
+			 * when bytecode is needed for proper UNIQUE
+			 * constraint handling.
+			 */
+			if (uniqueByteCodeNeeded) {
+				if (iField == pTab->iPKey)
+					x = regNewData;
+				else
+					x = iField + regNewData + 1;
+
+				assert(iField >= 0);
+				sqlite3VdbeAddOp2(v, OP_SCopy,
+						  x, regIdx + i);
+				VdbeComment((v, "%s",
+					     pTab->def->fields[
+						     iField].name));
 			}
 		}
 
@@ -1688,14 +1666,6 @@ xferCompatibleIndex(Index * pDest, Index * pSrc)
 		if (pSrc->aiColumn[i] != pDest->aiColumn[i]) {
 			return 0;	/* Different columns indexed */
 		}
-		if (pSrc->aiColumn[i] == XN_EXPR) {
-			assert(pSrc->aColExpr != 0 && pDest->aColExpr != 0);
-			if (sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr,
-					       pDest->aColExpr->a[i].pExpr,
-					       -1) != 0) {
-				return 0;	/* Different expressions in the index */
-			}
-		}
 		if (sql_index_column_sort_order(pSrc, i) !=
 		    sql_index_column_sort_order(pDest, i)) {
 			return 0;	/* Different sort orders */
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 01351a1..943fda9 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -2116,7 +2116,6 @@ struct Index {
 	/** Array of collation identifiers. */
 	uint32_t *coll_id_array;
 	Expr *pPartIdxWhere;	/* WHERE clause for partial indices */
-	ExprList *aColExpr;	/* Column expressions */
 	int tnum;		/* DB Page containing root of this index */
 	u16 nColumn;		/* Number of columns stored in the index */
 	u8 onError;		/* ON_CONFLICT_ACTION_ABORT, _IGNORE, _REPLACE,
@@ -2161,11 +2160,6 @@ index_field_tuple_est(struct Index *idx, uint32_t field);
 #define IsUniqueIndex(X)      (((X)->idxType == SQLITE_IDXTYPE_UNIQUE) || \
 				((X)->idxType == SQLITE_IDXTYPE_PRIMARYKEY))
 
-/* The Index.aiColumn[] values are normally positive integer.  But
- * there are some negative values that have special meaning:
- */
-#define XN_EXPR      (-2)	/* Indexed column is an expression */
-
 #ifdef DEFAULT_TUPLE_COUNT
 #undef DEFAULT_TUPLE_COUNT
 #endif
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index e791647..d312587 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -265,11 +265,6 @@ whereScanNext(WhereScan * pScan)
 			for (pTerm = pWC->a + k; k < pWC->nTerm; k++, pTerm++) {
 				if (pTerm->leftCursor == iCur
 				    && pTerm->u.leftColumn == iColumn
-				    && (iColumn != XN_EXPR
-					|| sqlite3ExprCompare(pTerm->pExpr->
-							      pLeft,
-							      pScan->pIdxExpr,
-							      iCur) == 0)
 				    && (pScan->iEquiv <= 1
 					|| !ExprHasProperty(pTerm->pExpr,
 							    EP_FromJoin))
@@ -377,9 +372,7 @@ whereScanInit(WhereScan * pScan,	/* The WhereScan object being initialized */
 	if (pIdx) {
 		int j = iColumn;
 		iColumn = pIdx->aiColumn[j];
-		if (iColumn == XN_EXPR) {
-			pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
-		} else if (iColumn >= 0) {
+		if (iColumn >= 0) {
 			char affinity =
 				pIdx->pTable->def->fields[iColumn].affinity;
 			pScan->idxaff = affinity;
@@ -387,8 +380,6 @@ whereScanInit(WhereScan * pScan,	/* The WhereScan object being initialized */
 			pScan->coll = sql_index_collation(pIdx, j, &id);
 			pScan->is_column_seen = true;
 		}
-	} else if (iColumn == XN_EXPR) {
-		return 0;
 	}
 	pScan->opMask = opMask;
 	pScan->k = 0;
@@ -2713,7 +2704,6 @@ indexMightHelpWithOrderBy(WhereLoopBuilder * pBuilder,
 			  Index * pIndex, int iCursor)
 {
 	ExprList *pOB;
-	ExprList *aColExpr;
 	int ii, jj;
 	int nIdxCol = index_column_count(pIndex);
 	if (index_is_unordered(pIndex))
@@ -2729,16 +2719,6 @@ indexMightHelpWithOrderBy(WhereLoopBuilder * pBuilder,
 				if (pExpr->iColumn == pIndex->aiColumn[jj])
 					return 1;
 			}
-		} else if ((aColExpr = pIndex->aColExpr) != 0) {
-			for (jj = 0; jj < nIdxCol; jj++) {
-				if (pIndex->aiColumn[jj] != XN_EXPR)
-					continue;
-				if (sqlite3ExprCompare
-				    (pExpr, aColExpr->a[jj].pExpr,
-				     iCursor) == 0) {
-					return 1;
-				}
-			}
 		}
 	}
 	return 0;
@@ -3429,10 +3409,7 @@ wherePathSatisfiesOrderBy(WhereInfo * pWInfo,	/* The WHERE clause */
 						if (pOBExpr->iColumn != iColumn)
 							continue;
 					} else {
-						if (sqlite3ExprCompare(pOBExpr,
-								       pIndex->aColExpr->a[j].pExpr, iCur)) {
-							continue;
-						}
+						continue;
 					}
 					if (iColumn >= 0) {
 						bool is_found;
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 09b2671..bf2a2a2 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -48,8 +48,6 @@ static const char *
 explainIndexColumnName(Index * pIdx, int i)
 {
 	i = pIdx->aiColumn[i];
-	if (i == XN_EXPR)
-		return "<expr>";
 	return pIdx->pTable->def->fields[i].name;
 }
 
@@ -719,7 +717,6 @@ codeAllEqualityTerms(Parse * pParse,	/* Parsing context */
 		for (j = 0; j < nSkip; j++) {
 			sqlite3VdbeAddOp3(v, OP_Column, iIdxCur,
 					  pIdx->aiColumn[j], regBase + j);
-			testcase(pIdx->aiColumn[j] == XN_EXPR);
 			VdbeComment((v, "%s", explainIndexColumnName(pIdx, j)));
 		}
 	}
@@ -1259,8 +1256,8 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo,	/* Complete information about t
 			 * FYI: entries in an index are ordered as follows:
 			 *      NULL, ... NULL, min_value, ...
 			 */
-			if ((j >= 0 && pIdx->pTable->def->fields[j].is_nullable)
-			    || j == XN_EXPR) {
+			if (j >= 0
+			    && pIdx->pTable->def->fields[j].is_nullable) {
 				assert(pLoop->nSkip == 0);
 				bSeekPastNull = 1;
 				nExtraReg = 1;
@@ -1305,11 +1302,9 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo,	/* Complete information about t
 #endif
 			if (pRangeStart == 0) {
 				j = pIdx->aiColumn[nEq];
-				if ((j >= 0 &&
-				     pIdx->pTable->def->fields[j].is_nullable)||
-				    j == XN_EXPR) {
+				if (j >= 0 &&
+				    pIdx->pTable->def->fields[j].is_nullable)
 					bSeekPastNull = 1;
-				}
 			}
 		}
 		assert(pRangeEnd == 0
diff --git a/src/box/sql/whereexpr.c b/src/box/sql/whereexpr.c
index aa6d452..e5d6b44 100644
--- a/src/box/sql/whereexpr.c
+++ b/src/box/sql/whereexpr.c
@@ -887,26 +887,19 @@ exprSelectUsage(WhereMaskSet * pMaskSet, Select * pS)
  * in any index.  Return TRUE (1) if pExpr is an indexed term and return
  * FALSE (0) if not.  If TRUE is returned, also set *piCur to the cursor
  * number of the table that is indexed and *piColumn to the column number
- * of the column that is indexed, or XN_EXPR (-2) if an expression is being
- * indexed.
+ * of the column that is indexed.
  *
  * If pExpr is a TK_COLUMN column reference, then this routine always returns
  * true even if that particular column is not indexed, because the column
  * might be added to an automatic index later.
  */
 static int
-exprMightBeIndexed(SrcList * pFrom,	/* The FROM clause */
-		   int op,	/* The specific comparison operator */
-		   Bitmask mPrereq,	/* Bitmask of FROM clause terms referenced by pExpr */
+exprMightBeIndexed(int op,	/* The specific comparison operator */
 		   Expr * pExpr,	/* An operand of a comparison operator */
 		   int *piCur,	/* Write the referenced table cursor number here */
 		   int *piColumn	/* Write the referenced table column number here */
     )
 {
-	Index *pIdx;
-	int i;
-	int iCur;
-
 	/* If this expression is a vector to the left or right of a
 	 * inequality constraint (>, <, >= or <=), perform the processing
 	 * on the first element of the vector.
@@ -923,27 +916,6 @@ exprMightBeIndexed(SrcList * pFrom,	/* The FROM clause */
 		*piColumn = pExpr->iColumn;
 		return 1;
 	}
-	if (mPrereq == 0)
-		return 0;	/* No table references */
-	if ((mPrereq & (mPrereq - 1)) != 0)
-		return 0;	/* Refs more than one table */
-	for (i = 0; mPrereq > 1; i++, mPrereq >>= 1) {
-	}
-	iCur = pFrom->a[i].iCursor;
-	for (pIdx = pFrom->a[i].pTab->pIndex; pIdx; pIdx = pIdx->pNext) {
-		if (pIdx->aColExpr == 0)
-			continue;
-		for (i = 0; i < pIdx->nColumn; i++) {
-			if (pIdx->aiColumn[i] != XN_EXPR)
-				continue;
-			if (sqlite3ExprCompare
-			    (pExpr, pIdx->aColExpr->a[i].pExpr, iCur) == 0) {
-				*piCur = iCur;
-				*piColumn = XN_EXPR;
-				return 1;
-			}
-		}
-	}
 	return 0;
 }
 
@@ -1038,13 +1010,13 @@ exprAnalyze(SrcList * pSrc,	/* the FROM clause */
 		}
 
 		if (exprMightBeIndexed
-		    (pSrc, op, prereqLeft, pLeft, &iCur, &iColumn)) {
+		    (op, pLeft, &iCur, &iColumn)) {
 			pTerm->leftCursor = iCur;
 			pTerm->u.leftColumn = iColumn;
 			pTerm->eOperator = operatorMask(op) & opMask;
 		}
 		if (pRight
-		    && exprMightBeIndexed(pSrc, op, pTerm->prereqRight, pRight,
+		    && exprMightBeIndexed(op, pRight,
 					  &iCur, &iColumn)
 		    ) {
 			WhereTerm *pNew;
-- 
2.16.2





More information about the Tarantool-patches mailing list