[patches] [PATCH 1/2] sql: rework IsUniqueIndex() macros

Nikita Pettik korablev at tarantool.org
Wed Feb 28 20:50:57 MSK 2018


Originally, SQLite has 3 types of indexes: primary keys, unique indexes
(both are created alongside with table) and indexes which are created
manually using 'CREATE INDEX' statement. The difference between user's
indexes and the rest is in the fact that user's ones can be dropped.  To
test uniqueness, type of error action is checked: for non-unique indexes
it is NONE. Such behaviour seems to be misleading, since Index struct
has separate field for this purpose. Hence, this patch reworks it in
order to use struct Index field to test uniqueness. To point out whether
index is user's or not, check existence of SQL statement in index opts
is checked.

Closes #3189
---
 src/box/sql/build.c     | 26 ++++++++++++++++++++------
 src/box/sql/insert.c    |  2 +-
 src/box/sql/sqliteInt.h |  3 ++-
 3 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 9f45c6224..efc58dad0 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -48,6 +48,7 @@
 #include "tarantoolInt.h"
 #include "box/session.h"
 #include "box/identifier.h"
+#include "box/schema.h"
 
 /*
  * This routine is called after a single SQL statement has been
@@ -3074,7 +3075,12 @@ sqlite3CreateIndex(Parse * pParse,	/* All information about this parse */
 	pIndex->pTable = pTab;
 	pIndex->onError = (u8) onError;
 	pIndex->uniqNotNull = onError != ON_CONFLICT_ACTION_NONE;
-	pIndex->idxType = idxType;
+	if (idxType == SQLITE_IDXTYPE_APPDEF &&
+	    onError != ON_CONFLICT_ACTION_NONE) {
+		pIndex->idxType = SQLITE_IDXTYPE_UNIQUE;
+	} else {
+		pIndex->idxType = idxType;
+	}
 	pIndex->pSchema = db->mdb.pSchema;
 	pIndex->nKeyCol = pList->nExpr;
 	/* Tarantool have access to each column by any index */
@@ -3429,7 +3435,17 @@ sqlite3DropIndex(Parse * pParse, SrcList * pName, Token * pName2, int ifExists)
 		pParse->checkSchema = 1;
 		goto exit_drop_index;
 	}
-	if (pIndex->idxType != SQLITE_IDXTYPE_APPDEF) {
+	uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(pIndex->tnum);
+	uint32_t index_id = SQLITE_PAGENO_TO_INDEXID(pIndex->tnum);
+	struct space *space = space_by_id(space_id);
+	assert(space != NULL);
+	struct index *index = space_index(space, index_id);
+	assert(index != NULL);
+
+	/* If index has been created by user, it has its SQL
+	 * statement. Otherwise (i.e. PK and UNIQUE indexes,
+	 * which are created alongside with table) it is NULL. */
+	if (index->def->opts.sql == NULL) {
 		sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
 				"or PRIMARY KEY constraint cannot be dropped",
 				0);
@@ -3454,10 +3470,8 @@ sqlite3DropIndex(Parse * pParse, SrcList * pName, Token * pName2, int ifExists)
 	sqlite3BeginWriteOperation(pParse, 1);
 	const char *columns[2] = { "id", "iid" };
 	Expr *values[2];
-	values[0] =
-	    sqlite3ExprInteger(db, SQLITE_PAGENO_TO_SPACEID(pIndex->tnum));
-	values[1] =
-	    sqlite3ExprInteger(db, SQLITE_PAGENO_TO_INDEXID(pIndex->tnum));
+	values[0] = sqlite3ExprInteger(db, space_id);
+	values[1] = sqlite3ExprInteger(db, index_id);
 	sqlite3DeleteByKey(pParse, TARANTOOL_SYS_INDEX_NAME,
 			   columns, values, 2);
 	sqlite3ClearStatTables(pParse, "idx", pIndex->zName);
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index b20a47970..e4023e030 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -1945,7 +1945,7 @@ xferOptimization(Parse * pParse,	/* Parser context */
 		addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
 		VdbeCoverage(v);
 		sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
-		if (pDestIdx->idxType == 2) {
+		if (pDestIdx->idxType == SQLITE_IDXTYPE_PRIMARYKEY) {
 			idxInsFlags |= OPFLAG_NCHANGE;
 		}
 		sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index aebb61029..b3405cb61 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1681,7 +1681,8 @@ struct Index {
 #define IsPrimaryKeyIndex(X)  ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
 
 /* Return true if index X is a UNIQUE index */
-#define IsUniqueIndex(X)      ((X)->onError != ON_CONFLICT_ACTION_NONE)
+#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:
-- 
2.15.1




More information about the Tarantool-patches mailing list