[tarantool-patches] [PATCH v4 4/7] sql: start using collations and is_nullable from space_def

Kirill Shcherbatov kshcherbatov at tarantool.org
Sat Apr 28 21:26:55 MSK 2018


Part of #3272.
---
 src/box/sql.c           | 36 +++++++++++++++++++++++++-----------
 src/box/sql/alter.c     | 11 ++++++++---
 src/box/sql/build.c     | 20 +++++++++++++-------
 src/box/sql/fkey.c      |  7 ++-----
 src/box/sql/select.c    |  6 ++++--
 src/box/sql/sqliteInt.h |  7 -------
 src/box/sql/vdbeaux.c   |  5 ++++-
 7 files changed, 56 insertions(+), 36 deletions(-)

diff --git a/src/box/sql.c b/src/box/sql.c
index 2893d70..ef11eb9 100644
--- a/src/box/sql.c
+++ b/src/box/sql.c
@@ -1449,7 +1449,9 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 
 	for (i = 0; i < n; i++) {
 		const char *t;
-		struct coll *coll = aCol[i].coll;
+		struct coll *coll =
+			coll_by_id(pTable->def->fields[i].coll_id);
+
 		struct field_def *field = &def->fields[i];
 		const char *zToken = field->default_value;
 		int base_len = 4;
@@ -1461,19 +1463,25 @@ int tarantoolSqlite3MakeTableFormat(Table *pTable, void *buf)
 		p = enc->encode_str(p, "name", 4);
 		p = enc->encode_str(p, field->name, strlen(field->name));
 		p = enc->encode_str(p, "type", 4);
+
+		assert(def->fields[i].is_nullable ==
+		       (def->fields[i].nullable_action ==
+			ON_CONFLICT_ACTION_NONE));
+
 		if (i == pk_forced_int) {
 			t = "integer";
 		} else {
 			t = aCol[i].affinity == SQLITE_AFF_BLOB ? "scalar" :
-				convertSqliteAffinity(aCol[i].affinity, aCol[i].notNull == 0);
+				convertSqliteAffinity(aCol[i].affinity,
+						      def->fields[i].is_nullable);
 		}
 		p = enc->encode_str(p, t, strlen(t));
 		p = enc->encode_str(p, "is_nullable", 11);
-		p = enc->encode_bool(p, aCol[i].notNull ==
-				     ON_CONFLICT_ACTION_NONE);
+		p = enc->encode_bool(p, def->fields[i].is_nullable);
 		p = enc->encode_str(p, "nullable_action", 15);
-		assert(aCol[i].notNull < on_conflict_action_MAX);
-		const char *action = on_conflict_action_strs[aCol[i].notNull];
+		assert(def->fields[i].nullable_action < on_conflict_action_MAX);
+		const char *action =
+			on_conflict_action_strs[def->fields[i].nullable_action];
 		p = enc->encode_str(p, action, strlen(action));
 		if (coll != NULL) {
 			p = enc->encode_str(p, "collation", strlen("collation"));
@@ -1552,11 +1560,16 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
 	p = enc->encode_array(base, n);
 	for (i = 0; i < n; i++) {
 		int col = pIndex->aiColumn[i];
+		assert(def->fields[col].is_nullable ==
+		       (def->fields[col].nullable_action ==
+			ON_CONFLICT_ACTION_NONE));
 		const char *t;
-		if (pk_forced_int == col)
+		if (pk_forced_int == col) {
 			t = "integer";
-		else
-			t = convertSqliteAffinity(aCol[col].affinity, aCol[col].notNull == 0);
+		} else {
+			t = convertSqliteAffinity(aCol[col].affinity,
+						  def->fields[col].is_nullable);
+		}
 		/* do not decode default collation */
 		p = enc->encode_map(p, pIndex->coll_array[i] == NULL ? 4 : 5);
 		p = enc->encode_str(p, "type", sizeof("type")-1);
@@ -1568,9 +1581,10 @@ int tarantoolSqlite3MakeIdxParts(SqliteIndex *pIndex, void *buf)
 			p = enc->encode_uint(p, pIndex->coll_array[i]->id);
 		}
 		p = enc->encode_str(p, "is_nullable", 11);
-		p = enc->encode_bool(p, aCol[col].notNull == ON_CONFLICT_ACTION_NONE);
+		p = enc->encode_bool(p, def->fields[col].is_nullable);
 		p = enc->encode_str(p, "nullable_action", 15);
-		const char *action_str = on_conflict_action_strs[aCol[col].notNull];
+		const char *action_str =
+			on_conflict_action_strs[def->fields[col].nullable_action];
 		p = enc->encode_str(p, action_str, strlen(action_str));
 	}
 	return (int)(p - base);
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index bedf602..f830a15 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -198,7 +198,12 @@ sqlite3AlterFinishAddColumn(Parse * pParse, Token * pColDef)
 				"Cannot add a REFERENCES column with non-NULL default value");
 		return;
 	}
-	if (pCol->notNull && !pDflt) {
+	assert(pNew->def->fields[pNew->def->field_count - 1].is_nullable ==
+	       (pNew->def->fields[pNew->def->field_count - 1].nullable_action ==
+		ON_CONFLICT_ACTION_NONE));
+
+	if (pNew->def->fields[pNew->def->field_count - 1].nullable_action
+	    && !pDflt) {
 		sqlite3ErrorMsg(pParse,
 				"Cannot add a NOT NULL column with default value NULL");
 		return;
@@ -307,9 +312,9 @@ sqlite3AlterBeginAddColumn(Parse * pParse, SrcList * pSrc)
 	}
 	memcpy(pNew->aCol, pTab->aCol, sizeof(Column) * pNew->def->field_count);
 	for (i = 0; i < pNew->def->field_count; i++) {
-		Column *pCol = &pNew->aCol[i];
+		/* FIXME: Column *pCol = &pNew->aCol[i]; */
 		/* FIXME: pCol->zName = sqlite3DbStrDup(db, pCol->zName); */
-		pCol->coll = NULL;
+		/* FIXME: pCol->coll = NULL; */
 	}
 	pNew->pSchema = db->pSchema;
 	pNew->addColOffset = pTab->addColOffset;
diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 99059b3..e9c0686 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -694,6 +694,8 @@ sqlite3AddColumn(Parse * pParse, Token * pName, Token * pType)
 	memset(pCol, 0, sizeof(p->aCol[0]));
 	struct field_def *column_def = &p->def->fields[p->def->field_count];
 	column_def->name = z;
+	column_def->is_nullable = true;
+	column_def->nullable_action = ON_CONFLICT_ACTION_NONE;
 	if (pType->n == 0) {
 		/* If there is no type specified, columns have the default affinity
 		 * 'BLOB' and type SCALAR.
@@ -740,7 +742,9 @@ sqlite3AddNotNull(Parse * pParse, int onError)
 	p = pParse->pNewTable;
 	if (p == 0 || NEVER(p->def->field_count < 1))
 		return;
-	p->aCol[p->def->field_count - 1].notNull = (u8) onError;
+	p->def->fields[p->def->field_count - 1].nullable_action = (u8)onError;
+	p->def->fields[p->def->field_count - 1].is_nullable =
+		(onError == ON_CONFLICT_ACTION_NONE);
 }
 
 /*
@@ -1018,10 +1022,10 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
 	if (!zColl)
 		return;
 
-	struct coll *coll = sqlite3LocateCollSeq(pParse, db, zColl);
+	struct coll *coll = coll_by_name(zColl, strlen(zColl));
 	if (coll != NULL) {
 		Index *pIdx;
-		p->aCol[i].coll = coll;
+		p->def->fields[i].coll_id = coll->id;
 
 		/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
 		 * then an index may have been created on this column before the
@@ -1032,8 +1036,6 @@ sqlite3AddCollateType(Parse * pParse, Token * pToken)
 			if (pIdx->aiColumn[0] == i)
 				pIdx->coll_array[0] = sql_column_collation(p, i);
 		}
-	} else {
-		sqlite3DbFree(db, zColl);
 	}
 }
 
@@ -1064,7 +1066,9 @@ sql_column_collation(Table *table, uint32_t column)
 	 */
 	if (space == NULL || space_index(space, 0) == NULL) {
 		assert(column < (uint32_t)table->def->field_count);
-		return table->aCol[column].coll;
+		struct coll *coll =
+			coll_by_id(table->def->fields[column].coll_id);
+		return coll;
 	}
 
 	return space->format->fields[column].coll;
@@ -1411,7 +1415,9 @@ convertToWithoutRowidTable(Parse * pParse, Table * pTab)
 	if (!db->init.imposterTable) {
 		for (i = 0; i < (int)pTab->def->field_count; i++) {
 			if (pTab->aCol[i].is_primkey) {
-				pTab->aCol[i].notNull = ON_CONFLICT_ACTION_ABORT;
+				pTab->def->fields[i].nullable_action
+					= ON_CONFLICT_ACTION_ABORT;
+				pTab->def->fields[i].is_nullable = false;
 			}
 		}
 	}
diff --git a/src/box/sql/fkey.c b/src/box/sql/fkey.c
index c15ad8c..8c015c9 100644
--- a/src/box/sql/fkey.c
+++ b/src/box/sql/fkey.c
@@ -34,6 +34,7 @@
  * support to compiled SQL statements.
  */
 #include <box/coll.h>
+#include "box/coll_cache.h"
 #include "sqliteInt.h"
 #include "box/session.h"
 #include "tarantoolInt.h"
@@ -535,11 +536,7 @@ exprTableRegister(Parse * pParse,	/* Parsing and code generating context */
 			pCol = &pTab->aCol[iCol];
 			pExpr->iTable = regBase + iCol + 1;
 			pExpr->affinity = pCol->affinity;
-			const char *coll_name;
-			if (pCol->coll == NULL && pCol->coll != NULL)
-				coll_name = pCol->coll->name;
-			else
-				coll_name = "binary";
+			const char *coll_name = "binary";
 			pExpr = sqlite3ExprAddCollateString(pParse, pExpr,
 							    coll_name);
 		} else {
diff --git a/src/box/sql/select.c b/src/box/sql/select.c
index 03bfcf9..fa1de9b 100644
--- a/src/box/sql/select.c
+++ b/src/box/sql/select.c
@@ -1836,6 +1836,8 @@ sqlite3ColumnsFromExprList(Parse * pParse,	/* Parsing context */
 	pTable->def->fields =
 		region_alloc(region, nCol*sizeof(pTable->def->fields[0]));
 	memset(pTable->def->fields, 0, nCol*sizeof(pTable->def->fields[0]));
+	for (int i = 0; i < nCol; i++)
+		pTable->def->fields[i].is_nullable = true;
 	pTable->def->field_count = (uint32_t)nCol;
 	pTable->aCol = aCol;
 
@@ -1961,8 +1963,8 @@ sqlite3SelectAddColumnTypeAndCollation(Parse * pParse,		/* Parsing contexts */
 			pCol->affinity = SQLITE_AFF_BLOB;
 		bool unused;
 		struct coll *coll = sql_expr_coll(pParse, p, &unused);
-		if (coll != NULL && pCol->coll == NULL)
-			pCol->coll = coll;
+		if (coll != NULL && pTab->def->fields[i].coll_id == COLL_NONE)
+			pTab->def->fields[i].coll_id = coll->id;
 	}
 	pTab->szTabRow = sqlite3LogEst(szAll * 4);
 }
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 520b74c..a045286 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -1867,13 +1867,6 @@ struct Savepoint {
  * of this structure.
  */
 struct Column {
-	/** Collating sequence. */
-	struct coll *coll;
-	/**
-	 * An ON_CONFLICT_ACTION code for handling a NOT NULL
-	 * constraint.
-	 */
-	enum on_conflict_action notNull;
 	char affinity;		/* One of the SQLITE_AFF_... values */
 	u8 szEst;		/* Estimated size of value in this column. sizeof(INT)==1 */
 	u8 is_primkey;		/* Boolean propertie for being PK */
diff --git a/src/box/sql/vdbeaux.c b/src/box/sql/vdbeaux.c
index b3998ea..f76c689 100644
--- a/src/box/sql/vdbeaux.c
+++ b/src/box/sql/vdbeaux.c
@@ -4743,6 +4743,9 @@ table_column_is_nullable(struct Table *tab, uint32_t column)
 			ON_CONFLICT_ACTION_NONE;
 	} else {
 		/* tab is ephemeral (in SQLite sense).  */
-		return tab->aCol[column].notNull == 0;
+		assert(tab->def->fields[column].is_nullable ==
+		       (tab->def->fields[column].nullable_action ==
+			ON_CONFLICT_ACTION_NONE));
+		return tab->def->fields[column].is_nullable;
 	}
 }
-- 
2.7.4





More information about the Tarantool-patches mailing list