[tarantool-patches] [PATCH 07/10] sql: remove index type from struct Index

Nikita Pettik korablev at tarantool.org
Sun Aug 12 17:13:03 MSK 2018


Part of #3561
---
 src/box/sql.c           |  2 +-
 src/box/sql/analyze.c   |  2 +-
 src/box/sql/build.c     | 92 +++++++++++++++++++------------------------------
 src/box/sql/insert.c    | 14 ++++----
 src/box/sql/pragma.c    |  7 +---
 src/box/sql/prepare.c   |  9 +----
 src/box/sql/sqliteInt.h | 18 ++++------
 src/box/sql/update.c    |  2 +-
 src/box/sql/where.c     |  4 +--
 src/box/sql/wherecode.c |  4 +--
 10 files changed, 58 insertions(+), 96 deletions(-)

diff --git a/src/box/sql.c b/src/box/sql.c
index ae12cae36..a0aced27b 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1511,7 +1511,7 @@ int tarantoolSqlite3MakeIdxOpts(SqliteIndex *index, const char *zSql, void *buf)
 	 * INSERT OR REPLACE/IGNORE uniqueness checks will be also done by
 	 * Tarantool.
 	 */
-	p = enc->encode_bool(p, IsUniqueIndex(index));
+	p = enc->encode_bool(p, sql_index_is_unique(index));
 	p = enc->encode_str(p, "sql", 3);
 	p = enc->encode_str(p, zSql, zSql ? strlen(zSql) : 0);
 	return (int)(p - base);
diff --git a/src/box/sql/analyze.c b/src/box/sql/analyze.c
index 00d96d220..74f5ae827 100644
--- a/src/box/sql/analyze.c
+++ b/src/box/sql/analyze.c
@@ -831,7 +831,7 @@ analyzeOneTable(Parse * pParse,	/* Parser context */
 		 * names. Thus, for the sake of clarity, use
 		 * instead more familiar table name.
 		 */
-		if (IsPrimaryKeyIndex(pIdx))
+		if (sql_index_is_primary(pIdx))
 			idx_name = pTab->def->name;
 		else
 			idx_name = pIdx->def->name;
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 01d4d52a3..3ef9ea96e 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -145,7 +145,7 @@ actualize_on_conflict_actions(struct Parse *parser, struct Table *table)
 
 	for (struct Index *idx = table->pIndex; idx; idx = idx->pNext) {
 		if (idx->onError == ON_CONFLICT_ACTION_REPLACE &&
-		    !IsPrimaryKeyIndex(idx))
+		    !sql_index_is_primary(idx))
 			goto non_pk_on_conflict_error;
 	}
 
@@ -421,8 +421,8 @@ Index *
 sqlite3PrimaryKeyIndex(Table * pTab)
 {
 	Index *p;
-	for (p = pTab->pIndex; p && !IsPrimaryKeyIndex(p); p = p->pNext) {
-	}
+	for (p = pTab->pIndex; p != NULL && !sql_index_is_primary(p);
+	     p = p->pNext);
 	return p;
 }
 
@@ -1280,8 +1280,11 @@ createIndex(Parse * pParse, Index * pIndex, int iSpaceId, int iIndexId,
 			  SQL_SUBTYPE_MSGPACK,zParts, P4_STATIC);
 	sqlite3VdbeAddOp3(v, OP_MakeRecord, iFirstCol, 6, iRecord);
 	sqlite3VdbeAddOp2(v, OP_SInsert, BOX_INDEX_ID, iRecord);
-	if (pIndex->index_type == SQL_INDEX_TYPE_NON_UNIQUE ||
-	    pIndex->index_type == SQL_INDEX_TYPE_UNIQUE)
+	/*
+	 * Non-NULL value means that index has been created via
+	 * separate CREATE INDEX statement.
+	 */
+	if (zSql != NULL)
 		sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);
 }
 
@@ -1383,38 +1386,6 @@ createSpace(Parse * pParse, int iSpaceId, char *zStmt)
 	sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);
 }
 
-/*
- * Generate code to create implicit indexes in the new table.
- * iSpaceId is a register storing the id of the space.
- * iCursor is a cursor to access _index.
- */
-static void
-createImplicitIndices(Parse * pParse, int iSpaceId)
-{
-	Table *p = pParse->pNewTable;
-	Index *pIdx, *pPrimaryIdx = sqlite3PrimaryKeyIndex(p);
-	int i;
-
-	if (pPrimaryIdx) {
-		/* Tarantool quirk: primary index is created first */
-		createIndex(pParse, pPrimaryIdx, iSpaceId, 0, NULL);
-	} else {
-		/*
-		 * This branch should not be taken.
-		 * If it is, then the current CREATE TABLE statement fails to
-		 * specify the PRIMARY KEY. The error is reported elsewhere.
-		 */
-		unreachable();
-	}
-
-	/* (pIdx->i) mapping must be consistent with parseTableSchemaRecord */
-	for (pIdx = p->pIndex, i = 0; pIdx; pIdx = pIdx->pNext) {
-		if (pIdx == pPrimaryIdx)
-			continue;
-		createIndex(pParse, pIdx, iSpaceId, ++i, NULL);
-	}
-}
-
 /*
  * Generate code to emit and parse table schema record.
  * iSpaceId is a register storing the id of the space.
@@ -1436,7 +1407,6 @@ parseTableSchemaRecord(Parse * pParse, int iSpaceId, char *zStmt)
 	sqlite3VdbeAddOp4(v, OP_String8, 0, iTop + 3, 0, zStmt, P4_DYNAMIC);
 
 	pPrimaryIdx = sqlite3PrimaryKeyIndex(p);
-	/* (pIdx->i) mapping must be consistent with createImplicitIndices */
 	for (pIdx = p->pIndex, i = 0; pIdx; pIdx = pIdx->pNext) {
 		if (pIdx == pPrimaryIdx)
 			continue;
@@ -1753,8 +1723,12 @@ sqlite3EndTable(Parse * pParse,	/* Parse context */
 	int reg_space_id = getNewSpaceId(pParse);
 	createSpace(pParse, reg_space_id, stmt);
 	/* Indexes aren't required for VIEW's.. */
-	if (!p->def->opts.is_view)
-		createImplicitIndices(pParse, reg_space_id);
+	if (!p->def->opts.is_view) {
+		struct Index *idx = sqlite3PrimaryKeyIndex(p);
+		assert(idx != NULL);
+		for (uint32_t i = 0; idx != NULL; idx = idx->pNext, i++)
+			createIndex(pParse, idx, reg_space_id, i, NULL);
+	}
 
 	/*
 	 * Check to see if we need to create an _sequence table
@@ -2553,7 +2527,7 @@ sqlite3RefillIndex(Parse * pParse, Index * pIndex)
 
 	addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
 	VdbeCoverage(v);
-	if (IsUniqueIndex(pIndex)) {
+	if (sql_index_is_unique(pIndex)) {
 		int j2 = sqlite3VdbeCurrentAddr(v) + 3;
 		sqlite3VdbeGoto(v, j2);
 		addr2 = sqlite3VdbeCurrentAddr(v);
@@ -2749,6 +2723,18 @@ constraint_is_named(const char *name)
 		strncmp(name, "unique_unnamed_", strlen("unique_unnamed_"));
 }
 
+bool
+sql_index_is_primary(const struct Index *idx)
+{
+	return idx->def->iid == 0;
+}
+
+bool
+sql_index_is_unique(const struct Index *idx)
+{
+	return idx->def->opts.is_unique;
+}
+
 void
 sql_create_index(struct Parse *parse, struct Token *token,
 		 struct SrcList *tbl_name, struct ExprList *col_list,
@@ -2913,7 +2899,6 @@ sql_create_index(struct Parse *parse, struct Token *token,
 
 	index->pTable = table;
 	index->onError = (u8) on_error;
-	index->index_type = idx_type;
 
 	/*
 	 * TODO: Issue a warning if two or more columns of the
@@ -2939,9 +2924,6 @@ sql_create_index(struct Parse *parse, struct Token *token,
 	 * still must have iid == 0.
 	 */
 	uint32_t iid = idx_type != SQL_INDEX_TYPE_CONSTRAINT_PK;
-	if (db->init.busy)
-		iid = db->init.index_id;
-
 	if (index_fill_def(parse, index, table, iid, name, strlen(name),
 			   col_list, idx_type, sql_stmt) != 0)
 		goto exit_create_index;
@@ -3039,14 +3021,10 @@ sql_create_index(struct Parse *parse, struct Token *token,
 			bool is_named =
 				constraint_is_named(existing_idx->def->name);
 			/* CREATE TABLE t(a, UNIQUE(a), PRIMARY KEY(a)). */
-			if (idx_type == SQL_INDEX_TYPE_CONSTRAINT_PK) {
-				if (existing_idx->index_type ==
-				    SQL_INDEX_TYPE_CONSTRAINT_UNIQUE &&
-				    !is_named) {
-					existing_idx->index_type =
-						SQL_INDEX_TYPE_CONSTRAINT_PK;
-					goto exit_create_index;
-				}
+			if (idx_type == SQL_INDEX_TYPE_CONSTRAINT_PK &&
+			    !sql_index_is_primary(existing_idx) && !is_named) {
+				existing_idx->def->iid = 0;
+				goto exit_create_index;
 			}
 
 			/* CREATE TABLE t(a, PRIMARY KEY(a), UNIQUE(a)). */
@@ -3057,10 +3035,12 @@ sql_create_index(struct Parse *parse, struct Token *token,
 	}
 	/*
 	 * Link the new Index structure to its table and to the
-	 * other in-memory database structures.
+	 * other in-memory database structures. If index created
+	 * within CREATE TABLE statement, its iid is assigned
+	 * in sql_init_callback().
 	 */
 	assert(parse->nErr == 0);
-	if (db->init.busy) {
+	if (db->init.busy && tbl_name != NULL) {
 		user_session->sql_flags |= SQLITE_InternChanges;
 		index->def->iid = db->init.index_id;
 	}
@@ -3752,7 +3732,7 @@ parser_emit_unique_constraint(struct Parse *parser,
 		sqlite3XPrintf(&err_accum, "%s.%s", def->name, col_name);
 	}
 	char *err_msg = sqlite3StrAccumFinish(&err_accum);
-	sqlite3HaltConstraint(parser, IsPrimaryKeyIndex(index) ?
+	sqlite3HaltConstraint(parser, sql_index_is_primary(index) ?
 			      SQLITE_CONSTRAINT_PRIMARYKEY :
 			      SQLITE_CONSTRAINT_UNIQUE, on_error, err_msg,
 			      P4_DYNAMIC, P5_ConstraintUnique);
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 853265ead..cb120384a 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -1159,7 +1159,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 
 		bool table_ipk_autoinc = false;
 		int reg_pk = -1;
-		if (IsPrimaryKeyIndex(pIdx)) {
+		if (sql_index_is_primary(pIdx)) {
 			/* If PK is marked as INTEGER, use it as strict type,
 			 * not as affinity. Emit code for type checking */
 			if (part_count == 1) {
@@ -1197,7 +1197,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 			sqlite3VdbeResolveLabel(v, addrUniqueOk);
 			continue;
 		}
-		if (!IsUniqueIndex(pIdx)) {
+		if (!sql_index_is_unique(pIdx)) {
 			sqlite3VdbeResolveLabel(v, addrUniqueOk);
 			continue;
 		}
@@ -1304,7 +1304,7 @@ sqlite3GenerateConstraintChecks(Parse * pParse,		/* The parser context */
 				int addrJump = sqlite3VdbeCurrentAddr(v) +
 					       pk_part_count;
 				int op = OP_Ne;
-				int regCmp = IsPrimaryKeyIndex(pIdx) ?
+				int regCmp = sql_index_is_primary(pIdx) ?
 					     regIdx : regR;
 				struct key_part *part =
 					pPk->def->key_def->parts;
@@ -1483,9 +1483,9 @@ sqlite3OpenTableAndIndices(Parse * pParse,	/* Parsing context */
 		 * iteration and don't open new index cursor
 		 */
 
-		if (isUpdate || 			/* Condition 1 */
-		    IsPrimaryKeyIndex(pIdx) ||		/* Condition 2 */
+		if (isUpdate ||
 		    ! rlist_empty(&space->parent_fkey) ||
+		    sql_index_is_primary(pIdx) ||
 		    /* Condition 4 */
 		    (pIdx->def->opts.is_unique &&
 		     pIdx->onError != ON_CONFLICT_ACTION_DEFAULT &&
@@ -1495,7 +1495,7 @@ sqlite3OpenTableAndIndices(Parse * pParse,	/* Parsing context */
 		     overrideError == ON_CONFLICT_ACTION_ROLLBACK) {
 
 			int iIdxCur = iBase++;
-			if (IsPrimaryKeyIndex(pIdx)) {
+			if (sql_index_is_primary(pIdx)) {
 				if (piDataCur)
 					*piDataCur = iIdxCur;
 				p5 = 0;
@@ -1812,7 +1812,7 @@ xferOptimization(Parse * pParse,	/* Parser context */
 		VdbeCoverage(v);
 		sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
 		sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
-		if (pDestIdx->index_type == SQL_INDEX_TYPE_CONSTRAINT_PK)
+		if (sql_index_is_primary(pDestIdx))
 			sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE);
 		sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1 + 1);
 		VdbeCoverage(v);
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index 0ba651567..822db69ba 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -506,15 +506,10 @@ sqlite3Pragma(Parse * pParse, Token * pId,	/* First part of [schema.]id field */
 					pParse->nMem = 5;
 					for (pIdx = pTab->pIndex, i = 0; pIdx;
 					     pIdx = pIdx->pNext, i++) {
-						const char *azOrigin[] =
-						    { "c", "u", "u", "pk" };
 						sqlite3VdbeMultiLoad(v, 1,
 								     "isisi", i,
 								     pIdx->def->name,
-								     pIdx->def->opts.is_unique,
-								     azOrigin
-								     [pIdx->
-								      index_type]);
+								     pIdx->def->opts.is_unique);
 						sqlite3VdbeAddOp2(v,
 								  OP_ResultRow,
 								  1, 5);
diff --git a/src/box/sql/prepare.c b/src/box/sql/prepare.c
index db5ee5e97..e8b8e94ae 100644
--- a/src/box/sql/prepare.c
+++ b/src/box/sql/prepare.c
@@ -120,14 +120,7 @@ sql_init_callback(struct init_data *init, const char *name,
 		struct space *space = space_by_id(space_id);
 		const char *zSpace = space_name(space);
 		pIndex = sqlite3LocateIndex(db, name, zSpace);
-		if (pIndex == NULL) {
-			/* This can occur if there exists an index on a TEMP table which
-			 * has the same name as another index on a permanent index.  Since
-			 * the permanent table is hidden by the TEMP table, we can also
-			 * safely ignore the index on the permanent table.
-			 */
-			/* Do Nothing */ ;
-		}
+		assert(pIndex != NULL);
 		pIndex->def->iid = index_id;
 	}
 	return 0;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index eb20fb31a..0ffc8d548 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1987,13 +1987,13 @@ enum sql_index_type {
     SQL_INDEX_TYPE_CONSTRAINT_PK,
 };
 
-/* Return true if index X is a PRIMARY KEY index */
-#define IsPrimaryKeyIndex(X)  ((X)->index_type==SQL_INDEX_TYPE_CONSTRAINT_PK)
+/** Simple wrapper to test index id on zero. */
+bool
+sql_index_is_primary(const struct Index *idx);
 
-/* Return true if index X is a UNIQUE index */
-#define IsUniqueIndex(X)  (((X)->index_type == SQL_INDEX_TYPE_CONSTRAINT_UNIQUE) || \
-			   ((X)->index_type == SQL_INDEX_TYPE_CONSTRAINT_PK) || \
-			   ((X)->index_type == SQL_INDEX_TYPE_UNIQUE))
+/** Simple getter around opts.is_unique. */
+bool
+sql_index_is_unique(const struct Index *idx);
 
 /*
  * Each SQL index is represented in memory by an
@@ -2015,12 +2015,6 @@ struct Index {
 	 * unique index.
 	 */
 	u8 onError;
-	/**
-	 * Index type: non-unique index, unique index, index
-	 * implementing UNIQUE constraint or index implementing
-	 * PK constraint.
-	 */
-	enum sql_index_type index_type;
 	/** Index definition. */
 	struct index_def *def;
 };
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 54b30705a..3fdf5a9af 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -162,7 +162,7 @@ sqlite3Update(Parse * pParse,		/* The parser context */
 	iIdxCur = iDataCur + 1;
 	pPk = is_view ? 0 : sqlite3PrimaryKeyIndex(pTab);
 	for (nIdx = 0, pIdx = pTab->pIndex; pIdx; pIdx = pIdx->pNext, nIdx++) {
-		if (IsPrimaryKeyIndex(pIdx) && pPk != 0) {
+		if (sql_index_is_primary(pIdx) && pPk != 0) {
 			iDataCur = pParse->nTab;
 			pTabList->a[0].iCursor = iDataCur;
 		}
diff --git a/src/box/sql/where.c b/src/box/sql/where.c
index a57bad5b7..73fe070fd 100644
--- a/src/box/sql/where.c
+++ b/src/box/sql/where.c
@@ -3009,7 +3009,7 @@ whereLoopAddBtree(WhereLoopBuilder * pBuilder,	/* WHERE clause information */
 			 * of secondary indexes, because secondary indexes
 			 * are not really store any data (only pointers to tuples).
 			 */
-			int notPkPenalty = IsPrimaryKeyIndex(pProbe) ? 0 : 4;
+			int notPkPenalty = sql_index_is_primary(pProbe) ? 0 : 4;
 			pNew->rRun = rSize + 16 + notPkPenalty;
 			whereLoopOutputAdjust(pWC, pNew, rSize);
 			rc = whereLoopInsert(pBuilder, pNew);
@@ -4684,7 +4684,7 @@ sqlite3WhereBegin(Parse * pParse,	/* The parser context */
 			 */
 			if (idx_def == NULL && pIx == NULL)
 				continue;
-			bool is_primary = (pIx != NULL && IsPrimaryKeyIndex(pIx)) ||
+			bool is_primary = (pIx != NULL && sql_index_is_primary(pIx)) ||
 					  (idx_def != NULL && (idx_def->iid == 0));
 			if (is_primary
 			    && (wctrlFlags & WHERE_OR_SUBCLAUSE) != 0) {
diff --git a/src/box/sql/wherecode.c b/src/box/sql/wherecode.c
index 6b3f2f78a..1c16d5323 100644
--- a/src/box/sql/wherecode.c
+++ b/src/box/sql/wherecode.c
@@ -226,7 +226,7 @@ sqlite3WhereExplainOneScan(Parse * pParse,	/* Parse context */
 			assert(pIdx != NULL || idx_def != NULL);
 			assert(!(flags & WHERE_AUTO_INDEX)
 			       || (flags & WHERE_IDX_ONLY));
-			if ((pIdx != NULL && IsPrimaryKeyIndex(pIdx)) ||
+			if ((pIdx != NULL && sql_index_is_primary(pIdx)) ||
 			    (idx_def != NULL && idx_def->iid == 0)) {
 				if (isSearch) {
 					zFmt = "PRIMARY KEY";
@@ -1626,7 +1626,7 @@ sqlite3WhereCodeOneLoopStart(WhereInfo * pWInfo,	/* Complete information about t
 					assert((pSubLoop->wsFlags & WHERE_AUTO_INDEX) == 0);
 					if ((pSubLoop->wsFlags & WHERE_INDEXED) != 0
 					    && (ii == 0 || pSubLoop->pIndex == pCov)
-					    && (!IsPrimaryKeyIndex(pSubLoop->pIndex))
+					    && (!sql_index_is_primary(pSubLoop->pIndex))
 					    ) {
 						assert(pSubWInfo->a[0].
 						       iIdxCur == iCovCur);
-- 
2.15.1





More information about the Tarantool-patches mailing list