[patches] [PATCH 3/3] sql: delegate SQL primary key check to Tarantool

Nikita Pettik korablev at tarantool.org
Wed Feb 14 15:38:12 MSK 2018


As last point of removing colflag attribute from struct Column,
table_column_is_primkey() function is added. It checks via Tarantool
facilities whether column belongs to PK or not (after space creation).
However, during initializing of SQL iternals and before actual creation
of struct space, colflag attribute (as indicator of PK) still can be used.
Since this is the only purpose of attribute, one has been renamed.

Closes #3118

Signed-off-by: Nikita Pettik <korablev at tarantool.org>
---
 src/box/sql/alter.c     |  2 +-
 src/box/sql/build.c     | 34 ++++++++++++++++++++++++++++++----
 src/box/sql/fkey.c      |  2 +-
 src/box/sql/pragma.c    |  3 +--
 src/box/sql/sqliteInt.h |  7 ++-----
 src/box/sql/update.c    | 11 ++++-------
 6 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index 2794c52cc..0bab035e0 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -231,7 +231,7 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
 	 * If there is a NOT NULL constraint, then the default value for the
 	 * column must not be NULL.
 	 */
-	if (pCol->colFlags & COLFLAG_PRIMKEY) {
+	if (pCol->is_primkey) {
 		sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
 		return;
 	}
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 851a8f760..8f69901bf 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -47,6 +47,7 @@
 #include "vdbeInt.h"
 #include "tarantoolInt.h"
 #include "box/session.h"
+#include "box/schema.h"
 
 /*
  * This routine is called after a single SQL statement has been
@@ -433,6 +434,32 @@ sqlite3DeleteColumnNames(sqlite3 * db, Table * pTable)
 	}
 }
 
+/* Return true if given column is part of primary key. */
+bool
+table_column_is_primkey(Table *table, uint32_t column)
+{
+	uint32_t space_id = SQLITE_PAGENO_TO_SPACEID(table->tnum);
+	struct space *space = space_by_id(space_id);
+	assert(space != NULL);
+
+	struct index *primary_idx = index_find(space, 0 /* PK */);
+	/* Views don't have any indexes. */
+	if (primary_idx == NULL)
+		return false;
+	struct index_def *idx_def = primary_idx->def;
+	uint64_t pk_mask = idx_def->key_def->column_mask;
+	if (column < 63) {
+		return pk_mask & (1UL << column);
+	} else if ((pk_mask & (1UL << 1)) != 0) {
+		for (uint32_t i = 0; i < idx_def->key_def->part_count; ++i) {
+			struct key_part *part = &idx_def->key_def->parts[i];
+			if (part->fieldno == column)
+				return true;
+		}
+	}
+	return false;
+}
+
 /*
  * Remove the memory data structures associated with the given
  * Table.  No changes are made to disk by this routine.
@@ -1040,7 +1067,7 @@ sqlite3AddPrimaryKey(Parse * pParse,	/* Parsing context */
 	if (pList == 0) {
 		iCol = pTab->nCol - 1;
 		pCol = &pTab->aCol[iCol];
-		pCol->colFlags |= COLFLAG_PRIMKEY;
+		pCol->is_primkey = 1;
 		nTerm = 1;
 	} else {
 		nTerm = pList->nExpr;
@@ -1058,8 +1085,7 @@ sqlite3AddPrimaryKey(Parse * pParse,	/* Parsing context */
 				    (zCName,
 				     pTab->aCol[iCol].zName) == 0) {
 					pCol = &pTab->aCol[iCol];
-					pCol->colFlags |=
-					    COLFLAG_PRIMKEY;
+					pCol->is_primkey = 1;
 					break;
 				}
 			}
@@ -1423,7 +1449,7 @@ convertToWithoutRowidTable(Parse * pParse, Table * pTab)
 	 */
 	if (!db->init.imposterTable) {
 		for (i = 0; i < pTab->nCol; i++) {
-			if ((pTab->aCol[i].colFlags & COLFLAG_PRIMKEY) != 0) {
+			if (pTab->aCol[i].is_primkey) {
 				pTab->aCol[i].notNull = OE_Abort;
 			}
 		}
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index d803a0df9..75930ebda 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -865,7 +865,7 @@ fkParentIsModified(Table * pTab, FKey * p, int *aChange)
 					if (0 ==
 					    strcmp(pCol->zName, zKey))
 						return 1;
-				} else if (pCol->colFlags & COLFLAG_PRIMKEY) {
+				} else if (table_column_is_primkey(pTab, iKey)) {
 					return 1;
 				}
 			}
diff --git a/src/box/sql/pragma.c b/src/box/sql/pragma.c
index 4aa3b2961..2b5cca435 100644
--- a/src/box/sql/pragma.c
+++ b/src/box/sql/pragma.c
@@ -352,8 +352,7 @@ sqlite3Pragma(Parse * pParse, Token * pId,	/* First part of [schema.]id field */
 				sqlite3ViewGetColumnNames(pParse, pTab);
 				for (i = 0, pCol = pTab->aCol; i < pTab->nCol;
 				     i++, pCol++) {
-					if ((pCol->
-					     colFlags & COLFLAG_PRIMKEY) == 0) {
+					if (!table_column_is_primkey(pTab, i)) {
 						k = 0;
 					} else if (pPk == 0) {
 						k = 1;
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 5fc612dea..fd732fa9e 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1354,13 +1354,9 @@ struct Column {
 	u8 notNull;		/* An OE_ code for handling a NOT NULL constraint */
 	char affinity;		/* One of the SQLITE_AFF_... values */
 	u8 szEst;		/* Estimated size of value in this column. sizeof(INT)==1 */
-	u8 colFlags;		/* Boolean properties.  See COLFLAG_ defines below */
+	u8 is_primkey;		/* Boolean propertie for being PK */
 };
 
-/* Allowed values for Column.colFlags:
- */
-#define COLFLAG_PRIMKEY  0x0001	/* Column is part of the primary key */
-
 /*
  * A sort order can be either ASC or DESC.
  */
@@ -3100,6 +3096,7 @@ void sqlite3ResetAllSchemasOfConnection(sqlite3 *);
 void sqlite3ResetOneSchema(sqlite3 *);
 void sqlite3CommitInternalChanges();
 void sqlite3DeleteColumnNames(sqlite3 *, Table *);
+bool table_column_is_primkey(Table *, uint32_t);
 int sqlite3ColumnsFromExprList(Parse *, ExprList *, i16 *, Column **);
 void sqlite3SelectAddColumnTypeAndCollation(Parse *, Table *, Select *);
 Table *sqlite3ResultSetOfSelect(Parse *, Select *);
diff --git a/src/box/sql/update.c b/src/box/sql/update.c
index 8d0fe73ff..114f3c350 100644
--- a/src/box/sql/update.c
+++ b/src/box/sql/update.c
@@ -232,12 +232,9 @@ sqlite3Update(Parse * pParse,		/* The parser context */
 			goto update_cleanup;
 		}
 		for (j = 0; j < pTab->nCol; j++) {
-			if (strcmp
-			    (pTab->aCol[j].zName, pChanges->a[i].zName) == 0) {
-				if (pPk
-					   && (pTab->aCol[j].
-					       colFlags & COLFLAG_PRIMKEY) !=
-					   0) {
+			if (strcmp(pTab->aCol[j].zName,
+				   pChanges->a[i].zName) == 0) {
+				if (pPk && table_column_is_primkey(pTab, j)) {
 					chngPk = 1;
 				}
 				aXRef[j] = i;
@@ -490,7 +487,7 @@ sqlite3Update(Parse * pParse,		/* The parser context */
 		for (i = 0; i < pTab->nCol; i++) {
 			if (oldmask == 0xffffffff
 			    || (i < 32 && (oldmask & MASKBIT32(i)) != 0)
-			    || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY) != 0) {
+			    || table_column_is_primkey(pTab, i)) {
 				testcase(oldmask != 0xffffffff && i == 31);
 				sqlite3ExprCodeGetColumnOfTable(v, pTab,
 								iDataCur, i,
-- 
2.15.1




More information about the Tarantool-patches mailing list