diff --git a/src/box/errcode.h b/src/box/errcode.h
index 04f4f34eee11c8332d5e8231ffd74e836d3f5bff..4eb7fced5da575e1d0144af9d8d486173793c5bf 100644
--- a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -223,6 +223,7 @@ struct errcode_record {
 	/*168 */_(ER_DROP_FK_CONSTRAINT,	"Failed to drop foreign key constraint '%s': %s") \
 	/*169 */_(ER_NO_SUCH_CONSTRAINT,	"Constraint %s does not exist") \
 	/*170 */_(ER_CONSTRAINT_EXISTS,		"Constraint %s already exists") \
+	/*171 */_(ER_SQL_TYPE_MISMATCH,		"Type mismatch: can not convert %s to %s") \
 
 /*
  * !IMPORTANT! Please follow instructions at start of the file
diff --git a/src/box/field_def.c b/src/box/field_def.c
index 8dbead63fedbb46f69b15130f2140054b399e801..3a9ff3703e2b71933607fe2728e4fe1907e5493e 100644
--- a/src/box/field_def.c
+++ b/src/box/field_def.c
@@ -33,6 +33,24 @@
 #include "trivia/util.h"
 #include "key_def.h"
 
+static const char *affinity_type_strs[] = {
+	/* [UNDEFINED] */ "undefined",
+	/* [BLOB - 'A'] */ "blob",
+	/* [TEXT - 'A'] */ "text",
+	/* [NUMERIC - 'A'] */ "numeric",
+	/* [INTEGER - 'A'] */ "integer",
+	/* [REAL - 'A'] */ "real",
+};
+
+const char *
+affinity_type_str(enum affinity_type type)
+{
+	if (type < 'A')
+		return affinity_type_strs[type];
+	else
+		return affinity_type_strs[type - 'A' + 1];
+}
+
 const char *field_type_strs[] = {
 	/* [FIELD_TYPE_ANY]      = */ "any",
 	/* [FIELD_TYPE_UNSIGNED] = */ "unsigned",
diff --git a/src/box/field_def.h b/src/box/field_def.h
index 05f80d40922e3a1231813e467e78d8d2a7341336..de0ecec51d5dfe044d5b4b04cf59d8b10a71ce67 100644
--- a/src/box/field_def.h
+++ b/src/box/field_def.h
@@ -78,6 +78,11 @@ enum affinity_type {
     AFFINITY_INTEGER = 'D',
     AFFINITY_REAL = 'E',
 };
+
+/** String name of @a type. */
+const char *
+affinity_type_str(enum affinity_type type);
+
 /** \endcond public */
 
 extern const char *field_type_strs[];
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 824e619fa24f9ee28c9cf1623095ca791fb11f86..4d1c1a6347ce813058cb2219b86e4f16b347be0b 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -3072,15 +3072,21 @@ sqlite3ExprCodeIN(Parse * pParse,	/* Parsing and code generating context */
 		assert(!ExprHasProperty(pExpr, EP_xIsSelect));
 		if (destIfNull != destIfFalse) {
 			regCkNull = sqlite3GetTempReg(pParse);
-			sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
+			sqlite3VdbeAddOp2(v, OP_Integer, 0, regCkNull);
+			int lCheckNull = sqlite3VdbeMakeLabel(v);
+			sqlite3VdbeAddOp2(v, OP_NotNull, rLhs, lCheckNull);
+			sqlite3VdbeAddOp2(v, OP_Null, 0, regCkNull);
+			sqlite3VdbeResolveLabel(v, lCheckNull);
 		}
 		for (ii = 0; ii < pList->nExpr; ii++) {
 			r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr,
 						 &regToFree);
 			if (regCkNull
 			    && sqlite3ExprCanBeNull(pList->a[ii].pExpr)) {
-				sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2,
-						  regCkNull);
+				int lCheckNull = sqlite3VdbeMakeLabel(v);
+				sqlite3VdbeAddOp2(v, OP_NotNull, r2, lCheckNull);
+				sqlite3VdbeAddOp2(v, OP_Null, 0, regCkNull);
+				sqlite3VdbeResolveLabel(v, lCheckNull);
 			}
 			if (ii < pList->nExpr - 1 || destIfNull != destIfFalse) {
 				sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2,
@@ -3649,6 +3655,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 	case TK_AGG_COLUMN:{
 			AggInfo *pAggInfo = pExpr->pAggInfo;
 			struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
+			pExpr->affinity = pCol->pExpr->affinity;
 			if (!pAggInfo->directMode) {
 				assert(pCol->iMem > 0);
 				return pCol->iMem;
@@ -3663,10 +3670,11 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 		}
 	case TK_COLUMN:{
 			int iTab = pExpr->iTable;
+			int col = pExpr->iColumn;
 			if (iTab < 0) {
 				if (pParse->ckBase > 0) {
 					/* Generating CHECK constraints. */
-					return pExpr->iColumn + pParse->ckBase;
+					return col + pParse->ckBase;
 				} else {
 					/* Coding an expression that is part of an index where column names
 					 * in the index refer to the table to which the index belongs
@@ -3674,22 +3682,28 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 					iTab = pParse->iSelfTab;
 				}
 			}
-			return sqlite3ExprCodeGetColumn(pParse, pExpr->space_def,
-							pExpr->iColumn, iTab,
-							target, pExpr->op2);
+			pExpr->affinity =
+				pExpr->space_def->fields[col].affinity;
+			return sqlite3ExprCodeGetColumn(pParse,
+							pExpr->space_def, col,
+							iTab, target,
+							pExpr->op2);
 		}
 	case TK_INTEGER:{
+			pExpr->affinity = AFFINITY_INTEGER;
 			expr_code_int(pParse, pExpr, false, target);
 			return target;
 		}
 #ifndef SQLITE_OMIT_FLOATING_POINT
 	case TK_FLOAT:{
+			pExpr->affinity = AFFINITY_REAL;
 			assert(!ExprHasProperty(pExpr, EP_IntValue));
 			codeReal(v, pExpr->u.zToken, 0, target);
 			return target;
 		}
 #endif
 	case TK_STRING:{
+			pExpr->affinity = AFFINITY_TEXT;
 			assert(!ExprHasProperty(pExpr, EP_IntValue));
 			sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
 			return target;
@@ -3707,6 +3721,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 			assert(pExpr->u.zToken[0] == 'x'
 			       || pExpr->u.zToken[0] == 'X');
 			assert(pExpr->u.zToken[1] == '\'');
+			pExpr->affinity = AFFINITY_BLOB;
 			z = &pExpr->u.zToken[2];
 			n = sqlite3Strlen30(z) - 1;
 			assert(z[n] == '\'');
@@ -3788,6 +3803,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 				testcase(regFree1 == 0);
 				testcase(regFree2 == 0);
 			}
+			pExpr->affinity = AFFINITY_INTEGER;
 			break;
 		}
 	case TK_AND:
@@ -3831,10 +3847,15 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 			sqlite3VdbeAddOp3(v, op, r2, r1, target);
 			testcase(regFree1 == 0);
 			testcase(regFree2 == 0);
+			if (op != TK_CONCAT)
+				pExpr->affinity = AFFINITY_NUMERIC;
+			else
+				pExpr->affinity = AFFINITY_TEXT;
 			break;
 		}
 	case TK_UMINUS:{
 			Expr *pLeft = pExpr->pLeft;
+			pExpr->affinity = AFFINITY_NUMERIC;
 			assert(pLeft);
 			if (pLeft->op == TK_INTEGER) {
 				expr_code_int(pParse, pLeft, true, target);
@@ -3861,6 +3882,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 		}
 	case TK_BITNOT:
 	case TK_NOT:{
+			pExpr->affinity = AFFINITY_INTEGER;
 			assert(TK_BITNOT == OP_BitNot);
 			testcase(op == TK_BITNOT);
 			assert(TK_NOT == OP_Not);
@@ -3874,6 +3896,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 	case TK_ISNULL:
 	case TK_NOTNULL:{
 			int addr;
+			pExpr->affinity = AFFINITY_INTEGER;
 			assert(TK_ISNULL == OP_IsNull);
 			testcase(op == TK_ISNULL);
 			assert(TK_NOTNULL == OP_NotNull);
@@ -3897,6 +3920,7 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 						"misuse of aggregate: %s()",
 						pExpr->u.zToken);
 			} else {
+				pExpr->affinity = pInfo->aFunc->pFunc->ret_type;
 				return pInfo->aFunc[pExpr->iAgg].iMem;
 			}
 			break;
@@ -3933,6 +3957,18 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 				break;
 			}
 
+			if (pDef->ret_type != AFFINITY_UNDEFINED) {
+				pExpr->affinity = pDef->ret_type;
+			} else {
+				/*
+				 * Otherwise, use first arg as
+				 * expression affinity.
+				 */
+				if (pFarg && pFarg->nExpr > 0) {
+					pExpr->affinity =
+						pFarg->a[0].pExpr->affinity;
+				}
+			}
 			/* Attempt a direct implementation of the built-in COALESCE() and
 			 * IFNULL() functions.  This avoids unnecessary evaluation of
 			 * arguments past the first non-NULL argument.
@@ -4076,12 +4112,14 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 	case TK_IN:{
 			int destIfFalse = sqlite3VdbeMakeLabel(v);
 			int destIfNull = sqlite3VdbeMakeLabel(v);
+			pExpr->affinity = AFFINITY_INTEGER;
 			sqlite3VdbeAddOp2(v, OP_Null, 0, target);
 			sqlite3ExprCodeIN(pParse, pExpr, destIfFalse,
 					  destIfNull);
 			sqlite3VdbeAddOp2(v, OP_Integer, 1, target);
+			sqlite3VdbeGoto(v, destIfNull);
 			sqlite3VdbeResolveLabel(v, destIfFalse);
-			sqlite3VdbeAddOp2(v, OP_AddImm, target, 0);
+			sqlite3VdbeAddOp2(v, OP_Integer, 0, target);
 			sqlite3VdbeResolveLabel(v, destIfNull);
 			return target;
 		}
@@ -4098,12 +4136,18 @@ sqlite3ExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 		 * Z is stored in pExpr->pList->a[1].pExpr.
 		 */
 	case TK_BETWEEN:{
+			pExpr->affinity = AFFINITY_INTEGER;
 			exprCodeBetween(pParse, pExpr, target, 0, 0);
 			return target;
 		}
 	case TK_SPAN:
-	case TK_COLLATE:
+	case TK_COLLATE:{
+			pExpr->affinity = AFFINITY_TEXT;
+			return sqlite3ExprCodeTarget(pParse, pExpr->pLeft,
+						     target);
+		}
 	case TK_UPLUS:{
+			pExpr->affinity = AFFINITY_NUMERIC;
 			return sqlite3ExprCodeTarget(pParse, pExpr->pLeft,
 						     target);
 		}
diff --git a/src/box/sql/insert.c b/src/box/sql/insert.c
index 5ebd072694db8455394aef5971e4bec862e378ae..fd05c02543ef0c64732b8f67010beeedf84d78a3 100644
--- a/src/box/sql/insert.c
+++ b/src/box/sql/insert.c
@@ -77,8 +77,20 @@ sql_emit_table_affinity(struct Vdbe *v, struct space_def *def, int reg)
 	char *colls_aff = (char *) sqlite3DbMallocZero(db, field_count + 1);
 	if (colls_aff == NULL)
 		return;
-	for (uint32_t i = 0; i < field_count; ++i)
+	for (uint32_t i = 0; i < field_count; ++i) {
 		colls_aff[i] = def->fields[i].affinity;
+		/*
+		 * Force INTEGER type to handle queries like:
+		 * CREATE TABLE t1 (id INT PRIMARY KEY);
+		 * INSERT INTO t1 VALUES (1.123);
+		 *
+		 * In this case 1.123 should be truncated to 1.
+		 */
+		if (colls_aff[i] == AFFINITY_INTEGER) {
+			sqlite3VdbeAddOp2(v, OP_Cast, reg + i,
+					  AFFINITY_INTEGER);
+		}
+	}
 	sqlite3VdbeAddOp4(v, OP_Affinity, reg, field_count, 0, colls_aff,
 			  P4_DYNAMIC);
 }
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index e61c51d66b83865d001e8a2be94447617ac5945a..6b8f305d75e766503b3b86b3cb3a0ececb9eb031 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -40,6 +40,7 @@
  * commenting and indentation practices when changing or adding code.
  */
 #include "box/box.h"
+#include "box/error.h"
 #include "box/fkey.h"
 #include "box/txn.h"
 #include "box/session.h"
@@ -304,53 +305,71 @@ applyNumericAffinity(Mem *pRec, int bTryForInt)
 	return 0;
 }
 
-/*
+/**
  * Processing is determine by the affinity parameter:
  *
  * AFFINITY_INTEGER:
  * AFFINITY_REAL:
  * AFFINITY_NUMERIC:
- *    Try to convert pRec to an integer representation or a
+ *    Try to convert mem to an integer representation or a
  *    floating-point representation if an integer representation
  *    is not possible.  Note that the integer representation is
  *    always preferred, even if the affinity is REAL, because
  *    an integer representation is more space efficient on disk.
  *
  * AFFINITY_TEXT:
- *    Convert pRec to a text representation.
+ *    Convert mem to a text representation.
  *
  * AFFINITY_BLOB:
- *    No-op.  pRec is unchanged.
+ *    No-op. mem is unchanged.
+ *
+ * @param record The value to apply affinity to.
+ * @param affinity The affinity to be applied.
  */
-static void
-applyAffinity(
-	Mem *pRec,          /* The value to apply affinity to */
-	char affinity       /* The affinity to be applied */
-	)
+static int
+mem_apply_affinity(struct Mem *record, enum affinity_type affinity)
 {
-	if (affinity>=AFFINITY_NUMERIC) {
-		assert(affinity==AFFINITY_INTEGER || affinity==AFFINITY_REAL
-			|| affinity==AFFINITY_NUMERIC);
-		if ((pRec->flags & MEM_Int)==0) { /*OPTIMIZATION-IF-FALSE*/
-			if ((pRec->flags & MEM_Real)==0) {
-				if (pRec->flags & MEM_Str) applyNumericAffinity(pRec,1);
-			} else {
-				sqlite3VdbeIntegerAffinity(pRec);
+	if ((record->flags & MEM_Null) != 0)
+		return 0;
+	switch (affinity) {
+	case AFFINITY_INTEGER:
+		if ((record->flags & MEM_Int) == MEM_Int)
+			return 0;
+		if ((record->flags & MEM_Real) == MEM_Real) {
+			int64_t i = (int64_t) record->u.r;
+			if (i == record->u.r) {
+				record->u.i = i;
+				MemSetTypeFlag(record, MEM_Int);
 			}
+			return 0;
 		}
-	} else if (affinity==AFFINITY_TEXT) {
-		/* Only attempt the conversion to TEXT if there is an integer or real
-		 * representation (blob and NULL do not get converted) but no string
-		 * representation.  It would be harmless to repeat the conversion if
-		 * there is already a string rep, but it is pointless to waste those
-		 * CPU cycles.
+		return sqlite3VdbeMemIntegerify(record, false);
+	case AFFINITY_REAL:
+		if ((record->flags & MEM_Real) == MEM_Real)
+			return 0;
+		return sqlite3VdbeMemRealify(record);
+	case AFFINITY_NUMERIC:
+		if ((record->flags & (MEM_Real | MEM_Int)) != 0)
+			return 0;
+		return sqlite3VdbeMemNumerify(record);
+	case AFFINITY_TEXT:
+		/*
+		 * Only attempt the conversion to TEXT if there is
+		 * an integer or real representation (BLOB and
+		 * NULL do not get converted).
 		 */
-		if (0==(pRec->flags&MEM_Str)) { /*OPTIMIZATION-IF-FALSE*/
-			if ((pRec->flags&(MEM_Real|MEM_Int))) {
-				sqlite3VdbeMemStringify(pRec, 1);
-			}
+		if ((record->flags & MEM_Str) == 0) {
+			if ((record->flags & (MEM_Real | MEM_Int)))
+				sqlite3VdbeMemStringify(record, 1);
 		}
-		pRec->flags &= ~(MEM_Real|MEM_Int);
+		record->flags &= ~(MEM_Real | MEM_Int);
+		return 0;
+	case AFFINITY_BLOB:
+		if (record->flags & (MEM_Str | MEM_Blob))
+			record->flags |= MEM_Blob;
+		return 0;
+	default:
+		return -1;
 	}
 }
 
@@ -371,7 +390,7 @@ int sqlite3_value_numeric_type(sqlite3_value *pVal) {
 }
 
 /*
- * Exported version of applyAffinity(). This one works on sqlite3_value*,
+ * Exported version of mem_apply_affinity(). This one works on sqlite3_value*,
  * not the internal Mem* type.
  */
 void
@@ -379,7 +398,7 @@ sqlite3ValueApplyAffinity(
 	sqlite3_value *pVal,
 	u8 affinity)
 {
-	applyAffinity((Mem *)pVal, affinity);
+	mem_apply_affinity((Mem *) pVal, affinity);
 }
 
 /*
@@ -1598,8 +1617,18 @@ case OP_Remainder: {           /* same as TK_REM, in1, in2, out3 */
 	} else {
 		bIntint = 0;
 	fp_math:
-		rA = sqlite3VdbeRealValue(pIn1);
-		rB = sqlite3VdbeRealValue(pIn2);
+		if (sqlite3VdbeRealValue(pIn1, &rA) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn1), "numeric");
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
+		if (sqlite3VdbeRealValue(pIn2, &rB) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn2), "numeric");
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
 		switch( pOp->opcode) {
 		case OP_Add:         rB += rA;       break;
 		case OP_Subtract:    rB -= rA;       break;
@@ -1828,8 +1857,18 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
 		sqlite3VdbeMemSetNull(pOut);
 		break;
 	}
-	iA = sqlite3VdbeIntValue(pIn2);
-	iB = sqlite3VdbeIntValue(pIn1);
+	if (sqlite3VdbeIntValue(pIn2, (int64_t *) &iA) != 0) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sqlite3_value_text(pIn2), "integer");
+		rc = SQL_TARANTOOL_ERROR;
+		goto abort_due_to_error;
+	}
+	if (sqlite3VdbeIntValue(pIn1, (int64_t *) &iB) != 0) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sqlite3_value_text(pIn1), "integer");
+		rc = SQL_TARANTOOL_ERROR;
+		goto abort_due_to_error;
+	}
 	op = pOp->opcode;
 	if (op==OP_BitAnd) {
 		iA &= iB;
@@ -1875,7 +1914,7 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
 case OP_AddImm: {            /* in1 */
 	pIn1 = &aMem[pOp->p1];
 	memAboutToChange(p, pIn1);
-	sqlite3VdbeMemIntegerify(pIn1);
+	sqlite3VdbeMemIntegerify(pIn1, false);
 	pIn1->u.i += pOp->p2;
 	break;
 }
@@ -1890,7 +1929,7 @@ case OP_AddImm: {            /* in1 */
 case OP_MustBeInt: {            /* jump, in1 */
 	pIn1 = &aMem[pOp->p1];
 	if ((pIn1->flags & MEM_Int)==0) {
-		applyAffinity(pIn1, AFFINITY_NUMERIC);
+		mem_apply_affinity(pIn1, AFFINITY_INTEGER);
 		VdbeBranchTaken((pIn1->flags&MEM_Int)==0, 2);
 		if ((pIn1->flags & MEM_Int)==0) {
 			if (pOp->p2==0) {
@@ -1948,12 +1987,17 @@ case OP_Cast: {                  /* in1 */
 	testcase( pOp->p2==AFFINITY_INTEGER);
 	testcase( pOp->p2==AFFINITY_REAL);
 	pIn1 = &aMem[pOp->p1];
-	memAboutToChange(p, pIn1);
 	rc = ExpandBlob(pIn1);
-	sqlite3VdbeMemCast(pIn1, pOp->p2);
+	if (rc != 0)
+		goto abort_due_to_error;
+	rc = sqlite3VdbeMemCast(pIn1, pOp->p2);
 	UPDATE_MAX_BLOBSIZE(pIn1);
-	if (rc) goto abort_due_to_error;
-	break;
+	if (rc == 0)
+		break;
+	diag_set(ClientError, ER_SQL_TYPE_MISMATCH, sqlite3_value_text(pIn1),
+		 affinity_type_str(pOp->p2));
+	rc = SQL_TARANTOOL_ERROR;
+	goto abort_due_to_error;
 }
 #endif /* SQLITE_OMIT_CAST */
 
@@ -2116,10 +2160,11 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 				}
 				if ((flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str) {
 					if (applyNumericAffinity(pIn3,0) != 0) {
-						sqlite3VdbeError(p,
-								 "Can't convert to numeric %s",
-								 sqlite3_value_text(pIn3));
-						rc = SQLITE_MISMATCH;
+						diag_set(ClientError,
+							 ER_SQL_TYPE_MISMATCH,
+							 sqlite3_value_text(pIn3),
+							 "numeric");
+						rc = SQL_TARANTOOL_ERROR;
 						goto abort_due_to_error;
 					}
 
@@ -2164,7 +2209,7 @@ case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
 	default:       res2 = res>=0;     break;
 	}
 
-	/* Undo any changes made by applyAffinity() to the input registers. */
+	/* Undo any changes made by mem_apply_affinity() to the input registers. */
 	assert((pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn));
 	pIn1->flags = flags1;
 	assert((pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn));
@@ -2358,13 +2403,27 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 	if (pIn1->flags & MEM_Null) {
 		v1 = 2;
 	} else {
-		v1 = sqlite3VdbeIntValue(pIn1)!=0;
+		int64_t i;
+		if (sqlite3VdbeIntValue(pIn1, &i) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn1), "integer");
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
+		v1 = i != 0;
 	}
 	pIn2 = &aMem[pOp->p2];
 	if (pIn2->flags & MEM_Null) {
 		v2 = 2;
 	} else {
-		v2 = sqlite3VdbeIntValue(pIn2)!=0;
+		int64_t i;
+		if (sqlite3VdbeIntValue(pIn2, &i) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn2), "integer");
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
+		v2 = i != 0;
 	}
 	if (pOp->opcode==OP_And) {
 		static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 };
@@ -2395,8 +2454,15 @@ case OP_Not: {                /* same as TK_NOT, in1, out2 */
 	pOut = &aMem[pOp->p2];
 	sqlite3VdbeMemSetNull(pOut);
 	if ((pIn1->flags & MEM_Null)==0) {
+		int64_t i;
+		if (sqlite3VdbeIntValue(pIn1, &i) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn1), "integer");
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
 		pOut->flags = MEM_Int;
-		pOut->u.i = !sqlite3VdbeIntValue(pIn1);
+		pOut->u.i = !i;
 	}
 	break;
 }
@@ -2413,8 +2479,15 @@ case OP_BitNot: {             /* same as TK_BITNOT, in1, out2 */
 	pOut = &aMem[pOp->p2];
 	sqlite3VdbeMemSetNull(pOut);
 	if ((pIn1->flags & MEM_Null)==0) {
+		int64_t i;
+		if (sqlite3VdbeIntValue(pIn1, &i) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn1), "integer");
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
 		pOut->flags = MEM_Int;
-		pOut->u.i = ~sqlite3VdbeIntValue(pIn1);
+		pOut->u.i = ~i;
 	}
 	break;
 }
@@ -2456,11 +2529,14 @@ case OP_IfNot: {            /* jump, in1 */
 	if (pIn1->flags & MEM_Null) {
 		c = pOp->p3;
 	} else {
-#ifdef SQLITE_OMIT_FLOATING_POINT
-		c = sqlite3VdbeIntValue(pIn1)!=0;
-#else
-		c = sqlite3VdbeRealValue(pIn1)!=0.0;
-#endif
+		double v;
+		if (sqlite3VdbeRealValue(pIn1, &v) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn1), "real");
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
+		c = v != 0;
 		if (pOp->opcode==OP_IfNot) c = !c;
 	}
 	VdbeBranchTaken(c!=0, 2);
@@ -2717,7 +2793,13 @@ case OP_Affinity: {
 	while( (cAff = *(zAffinity++))!=0) {
 		assert(pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)]);
 		assert(memIsValid(pIn1));
-		applyAffinity(pIn1, cAff);
+		if (mem_apply_affinity(pIn1, cAff) != 0) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn1),
+				 affinity_type_str(cAff));
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
 		pIn1++;
 	}
 	break;
@@ -2785,7 +2867,7 @@ case OP_MakeRecord: {
 	if (zAffinity) {
 		pRec = pData0;
 		do{
-			applyAffinity(pRec++, *(zAffinity++));
+			mem_apply_affinity(pRec++, *(zAffinity++));
 			assert(zAffinity[0]==0 || pRec<=pLast);
 		}while( zAffinity[0]);
 	}
@@ -3407,7 +3489,23 @@ case OP_SeekGT: {       /* jump, in3 */
 		if ((pIn3->flags & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str) {
 			applyNumericAffinity(pIn3, 0);
 		}
-		iKey = sqlite3VdbeIntValue(pIn3);
+		int64_t i;
+		if ((pIn3->flags & MEM_Int) == MEM_Int) {
+			i = pIn3->u.i;
+		} else if ((pIn3->flags & MEM_Real) == MEM_Real) {
+			if (pIn3->u.r > INT64_MAX)
+				i = INT64_MAX;
+			else if (pIn3->u.r < INT64_MIN)
+				i = INT64_MIN;
+			else
+				i = pIn3->u.r;
+		} else {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sqlite3_value_text(pIn3), "integer");
+			rc = SQL_TARANTOOL_ERROR;
+			goto abort_due_to_error;
+		}
+		iKey = i;
 
 		/* If the P3 value could not be converted into an integer without
 		 * loss of information, then special processing is required...
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index ce97f4984e49fd2dafbbe5a62956ce8457f785bd..174f5980f46c178084b460b38b83f04a517ac175 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -461,13 +461,13 @@ void sqlite3VdbeMemSetNull(Mem *);
 void sqlite3VdbeMemSetZeroBlob(Mem *, int);
 int sqlite3VdbeMemMakeWriteable(Mem *);
 int sqlite3VdbeMemStringify(Mem *, u8);
-i64 sqlite3VdbeIntValue(Mem *);
-int sqlite3VdbeMemIntegerify(Mem *);
-double sqlite3VdbeRealValue(Mem *);
-void sqlite3VdbeIntegerAffinity(Mem *);
+int sqlite3VdbeIntValue(Mem *, int64_t *);
+int sqlite3VdbeMemIntegerify(Mem *, bool is_forced);
+int sqlite3VdbeRealValue(Mem *, double *);
+int sqlite3VdbeIntegerAffinity(Mem *);
 int sqlite3VdbeMemRealify(Mem *);
 int sqlite3VdbeMemNumerify(Mem *);
-void sqlite3VdbeMemCast(Mem *, u8);
+int sqlite3VdbeMemCast(Mem *, u8);
 int sqlite3VdbeMemFromBtree(BtCursor *, u32, u32, Mem *);
 void sqlite3VdbeMemRelease(Mem * p);
 int sqlite3VdbeMemFinalize(Mem *, FuncDef *);
diff --git a/src/box/sql/vdbeapi.c b/src/box/sql/vdbeapi.c
index d3a91e24e351c8f9ead47338381fe9e81a524cba..04e60a079fec4b65b8a037dd2b44f498bcaf222c 100644
--- a/src/box/sql/vdbeapi.c
+++ b/src/box/sql/vdbeapi.c
@@ -206,19 +206,25 @@ sqlite3_value_bytes(sqlite3_value * pVal)
 double
 sqlite3_value_double(sqlite3_value * pVal)
 {
-	return sqlite3VdbeRealValue((Mem *) pVal);
+	double v;
+	sqlite3VdbeRealValue((Mem *) pVal, &v);
+	return v;
 }
 
 int
 sqlite3_value_int(sqlite3_value * pVal)
 {
-	return (int)sqlite3VdbeIntValue((Mem *) pVal);
+	int64_t i;
+	sqlite3VdbeIntValue((Mem *) pVal, &i);
+	return (int)i;
 }
 
 sqlite_int64
 sqlite3_value_int64(sqlite3_value * pVal)
 {
-	return sqlite3VdbeIntValue((Mem *) pVal);
+	int64_t i;
+	sqlite3VdbeIntValue((Mem *) pVal, &i);
+	return i;
 }
 
 enum sql_subtype
diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index 072a05066b3f1bfe0a944f6991ba01104fb78b81..22beba8be7b847973f699e3c77e13fae84c9a973 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -283,8 +283,10 @@ sqlite3VdbeMemStringify(Mem * pMem, u8 bForce)
 	int fg = pMem->flags;
 	const int nByte = 32;
 
+	if ((fg & (MEM_Null | MEM_Str | MEM_Blob)) != 0)
+		return SQLITE_OK;
+
 	assert(!(fg & MEM_Zero));
-	assert(!(fg & (MEM_Str | MEM_Blob)));
 	assert(fg & (MEM_Int | MEM_Real));
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 
@@ -411,12 +413,13 @@ sqlite3VdbeMemRelease(Mem * p)
  * If the double is out of range of a 64-bit signed integer then
  * return the closest available 64-bit signed integer.
  */
-static i64
-doubleToInt64(double r)
+static int
+doubleToInt64(double r, int64_t *i)
 {
 #ifdef SQLITE_OMIT_FLOATING_POINT
 	/* When floating-point is omitted, double and int64 are the same thing */
-	return r;
+	*i = r;
+	return 0;
 #else
 	/*
 	 * Many compilers we encounter do not define constants for the
@@ -425,15 +428,18 @@ doubleToInt64(double r)
 	 * So we define our own static constants here using nothing
 	 * larger than a 32-bit integer constant.
 	 */
-	static const i64 maxInt = LARGEST_INT64;
-	static const i64 minInt = SMALLEST_INT64;
+	static const int64_t maxInt = LARGEST_INT64;
+	static const int64_t minInt = SMALLEST_INT64;
 
 	if (r <= (double)minInt) {
-		return minInt;
+		*i = minInt;
+		return -1;
 	} else if (r >= (double)maxInt) {
-		return maxInt;
+		*i = maxInt;
+		return -1;
 	} else {
-		return (i64) r;
+		*i = (int64_t) r;
+		return *i != r;
 	}
 #endif
 }
@@ -449,24 +455,23 @@ doubleToInt64(double r)
  *
  * If pMem represents a string value, its encoding might be changed.
  */
-i64
-sqlite3VdbeIntValue(Mem * pMem)
+int
+sqlite3VdbeIntValue(Mem * pMem, int64_t *i)
 {
 	int flags;
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 	flags = pMem->flags;
 	if (flags & MEM_Int) {
-		return pMem->u.i;
+		*i = pMem->u.i;
+		return 0;
 	} else if (flags & MEM_Real) {
-		return doubleToInt64(pMem->u.r);
-	} else if (flags & (MEM_Str | MEM_Blob)) {
-		int64_t value = 0;
+		return doubleToInt64(pMem->u.r, i);
+	} else if (flags & (MEM_Str)) {
 		assert(pMem->z || pMem->n == 0);
-		sql_atoi64(pMem->z, &value, pMem->n);
-		return value;
-	} else {
-		return 0;
+		if (sql_atoi64(pMem->z, (int64_t *)i, pMem->n) == 0)
+			return 0;
 	}
+	return -1;
 }
 
 /*
@@ -475,65 +480,68 @@ sqlite3VdbeIntValue(Mem * pMem)
  * value.  If it is a string or blob, try to convert it to a double.
  * If it is a NULL, return 0.0.
  */
-double
-sqlite3VdbeRealValue(Mem * pMem)
+int
+sqlite3VdbeRealValue(Mem * pMem, double *v)
 {
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 	if (pMem->flags & MEM_Real) {
-		return pMem->u.r;
+		*v = pMem->u.r;
+		return 0;
 	} else if (pMem->flags & MEM_Int) {
-		return (double)pMem->u.i;
-	} else if (pMem->flags & (MEM_Str | MEM_Blob)) {
-		/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
-		double val = (double)0;
-		sqlite3AtoF(pMem->z, &val, pMem->n);
-		return val;
-	} else {
-		/* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */
-		return (double)0;
+		*v = (double)pMem->u.i;
+		return 0;
+	} else if (pMem->flags & MEM_Str) {
+		if (sqlite3AtoF(pMem->z, v, pMem->n))
+			return 0;
 	}
+	return -1;
 }
 
 /*
  * The MEM structure is already a MEM_Real.  Try to also make it a
  * MEM_Int if we can.
  */
-void
+int
 sqlite3VdbeIntegerAffinity(Mem * pMem)
 {
+	int rc;
 	i64 ix;
 	assert(pMem->flags & MEM_Real);
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 
-	ix = doubleToInt64(pMem->u.r);
-
-	/* Only mark the value as an integer if
-	 *
-	 *    (1) the round-trip conversion real->int->real is a no-op, and
-	 *    (2) The integer is neither the largest nor the smallest
-	 *        possible integer (ticket #3922)
-	 *
-	 * The second and third terms in the following conditional enforces
-	 * the second condition under the assumption that addition overflow causes
-	 * values to wrap around.
-	 */
-	if (pMem->u.r == ix && ix > SMALLEST_INT64 && ix < LARGEST_INT64) {
+	if ((rc = doubleToInt64(pMem->u.r, (int64_t *) &ix)) == 0) {
 		pMem->u.i = ix;
 		MemSetTypeFlag(pMem, MEM_Int);
 	}
+	return rc;
 }
 
 /*
  * Convert pMem to type integer.  Invalidate any prior representations.
  */
 int
-sqlite3VdbeMemIntegerify(Mem * pMem)
+sqlite3VdbeMemIntegerify(Mem * pMem, bool is_forced)
 {
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 
-	pMem->u.i = sqlite3VdbeIntValue(pMem);
+	int64_t i;
+	if (sqlite3VdbeIntValue(pMem, &i) == 0) {
+		pMem->u.i = i;
+		MemSetTypeFlag(pMem, MEM_Int);
+		return 0;
+	} else if ((pMem->flags & MEM_Real) != 0 && is_forced) {
+		pMem->u.i = (int) pMem->u.r;
+		MemSetTypeFlag(pMem, MEM_Int);
+		return 0;
+	}
+
+	double d;
+	if (sqlite3VdbeRealValue(pMem, &d) || (int64_t) d != d) {
+		return SQLITE_ERROR;
+	}
+	pMem->u.i = (int64_t) d;
 	MemSetTypeFlag(pMem, MEM_Int);
-	return SQLITE_OK;
+	return 0;
 }
 
 /*
@@ -544,8 +552,11 @@ int
 sqlite3VdbeMemRealify(Mem * pMem)
 {
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
+	double v;
+	if (sqlite3VdbeRealValue(pMem, &v))
+		return SQLITE_ERROR;
 
-	pMem->u.r = sqlite3VdbeRealValue(pMem);
+	pMem->u.r = v;
 	MemSetTypeFlag(pMem, MEM_Real);
 	return SQLITE_OK;
 }
@@ -566,7 +577,10 @@ sqlite3VdbeMemNumerify(Mem * pMem)
 		if (0 == sql_atoi64(pMem->z, (int64_t *)&pMem->u.i, pMem->n)) {
 			MemSetTypeFlag(pMem, MEM_Int);
 		} else {
-			pMem->u.r = sqlite3VdbeRealValue(pMem);
+			double v;
+			if (sqlite3VdbeRealValue(pMem, &v))
+				return SQLITE_ERROR;
+			pMem->u.r = v;
 			MemSetTypeFlag(pMem, MEM_Real);
 			sqlite3VdbeIntegerAffinity(pMem);
 		}
@@ -583,46 +597,56 @@ sqlite3VdbeMemNumerify(Mem * pMem)
  * affinity even if that results in loss of data.  This routine is
  * used (for example) to implement the SQL "cast()" operator.
  */
-void
+int
 sqlite3VdbeMemCast(Mem * pMem, u8 aff)
 {
 	if (pMem->flags & MEM_Null)
-		return;
-	switch (aff) {
-	case AFFINITY_BLOB:{	/* Really a cast to BLOB */
-			if ((pMem->flags & MEM_Blob) == 0) {
-				sqlite3ValueApplyAffinity(pMem, AFFINITY_TEXT);
-				assert(pMem->flags & MEM_Str
-				       || pMem->db->mallocFailed);
-				if (pMem->flags & MEM_Str)
-					MemSetTypeFlag(pMem, MEM_Blob);
-			} else {
-				pMem->flags &= ~(MEM_TypeMask & ~MEM_Blob);
-			}
-			break;
-		}
-	case AFFINITY_NUMERIC:{
-			sqlite3VdbeMemNumerify(pMem);
-			break;
+		return SQLITE_OK;
+	if ((pMem->flags & MEM_Blob) != 0 &&
+	    (aff == AFFINITY_REAL || aff == AFFINITY_NUMERIC)) {
+		if (sql_atoi64(pMem->z, (int64_t *) &pMem->u.i, pMem->n) == 0) {
+			MemSetTypeFlag(pMem, MEM_Real);
+			pMem->u.r = pMem->u.i;
+			return 0;
 		}
-	case AFFINITY_INTEGER:{
-			sqlite3VdbeMemIntegerify(pMem);
-			break;
+		return ! sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n);
+	}
+	switch (aff) {
+	case AFFINITY_BLOB:
+		if (pMem->flags & MEM_Blob)
+			return SQLITE_OK;
+		if (pMem->flags & MEM_Str) {
+			MemSetTypeFlag(pMem, MEM_Blob);
+			return SQLITE_OK;
 		}
-	case AFFINITY_REAL:{
-			sqlite3VdbeMemRealify(pMem);
-			break;
+		if (pMem->flags & MEM_Int || pMem->flags & MEM_Real) {
+			if (sqlite3VdbeMemStringify(pMem, 1) != 0)
+				return -1;
+			MemSetTypeFlag(pMem, MEM_Blob);
+			return 0;
 		}
-	default:{
-			assert(aff == AFFINITY_TEXT);
-			assert(MEM_Str == (MEM_Blob >> 3));
-			pMem->flags |= (pMem->flags & MEM_Blob) >> 3;
-			sqlite3ValueApplyAffinity(pMem, AFFINITY_TEXT);
-			assert(pMem->flags & MEM_Str || pMem->db->mallocFailed);
-			pMem->flags &=
-			    ~(MEM_Int | MEM_Real | MEM_Blob | MEM_Zero);
-			break;
+		return SQLITE_ERROR;
+	case AFFINITY_NUMERIC:
+		return sqlite3VdbeMemNumerify(pMem);
+	case AFFINITY_INTEGER:
+		if ((pMem->flags & MEM_Blob) != 0) {
+			if (sql_atoi64(pMem->z, (int64_t *) &pMem->u.i,
+				       pMem->n) != 0)
+				return -1;
+			MemSetTypeFlag(pMem, MEM_Int);
+			return 0;
 		}
+		return sqlite3VdbeMemIntegerify(pMem, true);
+	case AFFINITY_REAL:
+		return sqlite3VdbeMemRealify(pMem);
+	default:
+		assert(aff == AFFINITY_TEXT);
+		assert(MEM_Str == (MEM_Blob >> 3));
+		pMem->flags |= (pMem->flags & MEM_Blob) >> 3;
+		sqlite3ValueApplyAffinity(pMem, AFFINITY_TEXT);
+		assert(pMem->flags & MEM_Str || pMem->db->mallocFailed);
+		pMem->flags &= ~(MEM_Int | MEM_Real | MEM_Blob | MEM_Zero);
+		return SQLITE_OK;
 	}
 }
 
@@ -1306,7 +1330,8 @@ valueFromExpr(sqlite3 * db,	/* The database connection */
 		if (SQLITE_OK ==
 		    sqlite3ValueFromExpr(db, pExpr->pLeft, affinity, &pVal)
 		    && pVal != 0) {
-			sqlite3VdbeMemNumerify(pVal);
+			if ((rc = sqlite3VdbeMemNumerify(pVal)) != SQLITE_OK)
+				return rc;
 			if (pVal->flags & MEM_Real) {
 				pVal->u.r = -pVal->u.r;
 			} else if (pVal->u.i == SMALLEST_INT64) {
@@ -1321,7 +1346,8 @@ valueFromExpr(sqlite3 * db,	/* The database connection */
 		pVal = valueNew(db, pCtx);
 		if (pVal == 0)
 			goto no_mem;
-		sqlite3VdbeMemNumerify(pVal);
+		if ((rc = sqlite3VdbeMemNumerify(pVal)) != SQLITE_OK)
+			return rc;
 	}
 #ifndef SQLITE_OMIT_BLOB_LITERAL
 	else if (op == TK_BLOB) {
diff --git a/test/box/misc.result b/test/box/misc.result
index 3d7317caf8b59aba2b7ff4ca85faf5dead093be2..3ada82fb77dd9507ff92d82bbac0cb0d089e688d 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -497,6 +497,7 @@ t;
   168: box.error.DROP_FK_CONSTRAINT
   169: box.error.NO_SUCH_CONSTRAINT
   170: box.error.CONSTRAINT_EXISTS
+  171: box.error.SQL_TYPE_MISMATCH
 ...
 test_run:cmd("setopt delimiter ''");
 ---
diff --git a/test/sql-tap/analyze9.test.lua b/test/sql-tap/analyze9.test.lua
index d884addcef38ed31077f7c7041d27afb6769e2c0..2de7e2542535ae2f6108c7cd472f0b7bd7143706 100755
--- a/test/sql-tap/analyze9.test.lua
+++ b/test/sql-tap/analyze9.test.lua
@@ -104,7 +104,7 @@ test:do_execsql_test(
         SELECT msgpack_decode_sample("sample") FROM "_sql_stat4";
     ]], {
         -- <2.1>
-        "some text 14", "text 12", "some text", 22
+        "text 12","some text 14","text","some text"
         -- </2.1>
     })
 
diff --git a/test/sql-tap/autoinc.test.lua b/test/sql-tap/autoinc.test.lua
index e361a00d1d356906a255a7fb7d06bee0d469597e..3ac9a856a4fddd12d2be7df4110d480e3b7df743 100755
--- a/test/sql-tap/autoinc.test.lua
+++ b/test/sql-tap/autoinc.test.lua
@@ -618,7 +618,7 @@ test:do_catchsql_test(
             INSERT INTO t2 VALUES('asd'); 
     ]], {
         -- <autoinc-10.2>
-        1, "datatype mismatch"
+        1, "Type mismatch: can not convert asd to integer"
         -- </autoinc-10.2>
     })
 
diff --git a/test/sql-tap/badutf1.test.lua b/test/sql-tap/badutf1.test.lua
index a90cf0527d188f1b7eb1dc2000d1b6660b2010dd..534c762baa5bd7467a57f08a47c1d40d4452e923 100755
--- a/test/sql-tap/badutf1.test.lua
+++ b/test/sql-tap/badutf1.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(25)
+test:plan(23)
 
 --!./tcltestrunner.lua
 -- 2007 May 15
@@ -208,27 +208,6 @@ test:do_test(
 end
 
 
-test:do_test(
-    "badutf-2.1",
-    function()
-        return test:execsql2("SELECT '\x80'=CAST(x'80' AS text) AS x")
-    end, {
-        -- <badutf-2.1>
-        "X", 1
-        -- </badutf-2.1>
-    })
-
-test:do_test(
-    "badutf-2.2",
-    function()
-        return test:execsql2("SELECT CAST('\x80' AS blob)=x'80' AS x")
-    end, {
-        -- <badutf-2.2>
-        "X", 1
-        -- </badutf-2.2>
-    })
-
-
 
 test:do_test(
     "badutf-3.1",
diff --git a/test/sql-tap/cast.test.lua b/test/sql-tap/cast.test.lua
index e3b7b12483072380bbcafefc9d08a4dad3ab2cef..51d55793732a7a3ce942c552cafa421aa228b167 100755
--- a/test/sql-tap/cast.test.lua
+++ b/test/sql-tap/cast.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(89)
+test:plan(82)
 
 --!./tcltestrunner.lua
 -- 2005 June 25
@@ -64,26 +64,16 @@ test:do_execsql_test(
         -- </cast-1.4>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "cast-1.5",
     [[
         SELECT CAST(x'616263' AS numeric)
     ]], {
         -- <cast-1.5>
-        0
+        1, 'Type mismatch: can not convert abc to real'
         -- </cast-1.5>
     })
 
-test:do_execsql_test(
-    "cast-1.6",
-    [[
-        SELECT typeof(CAST(x'616263' AS numeric))
-    ]], {
-        -- <cast-1.6>
-        "real"
-        -- </cast-1.6>
-    })
-
 test:do_execsql_test(
     "cast-1.7",
     [[
@@ -104,28 +94,16 @@ test:do_execsql_test(
         -- </cast-1.8>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "cast-1.9",
     [[
         SELECT CAST(x'616263' AS integer)
     ]], {
         -- <cast-1.9>
-        0
+        1, 'Type mismatch: can not convert abc to integer'
         -- </cast-1.9>
     })
 
-test:do_execsql_test(
-    "cast-1.10",
-    [[
-        SELECT typeof(CAST(x'616263' AS integer))
-    ]], {
-        -- <cast-1.10>
-        "integer"
-        -- </cast-1.10>
-    })
-
-
-
 test:do_execsql_test(
     "cast-1.11",
     [[
@@ -466,36 +444,16 @@ test:do_execsql_test(
         -- </cast-1.44>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "cast-1.45",
     [[
         SELECT CAST('123abc' AS numeric)
     ]], {
         -- <cast-1.45>
-        123
+        1, 'Type mismatch: can not convert 123abc to real'
         -- </cast-1.45>
     })
 
-test:do_execsql_test(
-    "cast-1.46",
-    [[
-        SELECT typeof(CAST('123abc' AS numeric))
-    ]], {
-        -- <cast-1.46>
-        "real"
-        -- </cast-1.46>
-    })
-
-test:do_execsql_test(
-    "cast-1.47",
-    [[
-        SELECT CAST('123abc' AS blob)
-    ]], {
-        -- <cast-1.47>
-        "123abc"
-        -- </cast-1.47>
-    })
-
 test:do_execsql_test(
     "cast-1.48",
     [[
@@ -506,46 +464,37 @@ test:do_execsql_test(
         -- </cast-1.48>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "cast-1.49",
     [[
         SELECT CAST('123abc' AS integer)
     ]], {
         -- <cast-1.49>
-        123
+        1, 'Type mismatch: can not convert 123abc to integer'
         -- </cast-1.49>
     })
 
-test:do_execsql_test(
-    "cast-1.50",
-    [[
-        SELECT typeof(CAST('123abc' AS integer))
-    ]], {
-        -- <cast-1.50>
-        "integer"
-        -- </cast-1.50>
-    })
-
-test:do_execsql_test(
+test:do_catchsql_test(
     "cast-1.51",
     [[
         SELECT CAST('123.5abc' AS numeric)
     ]], {
         -- <cast-1.51>
-        123.5
+        1, 'Type mismatch: can not convert 123.5abc to real'
         -- </cast-1.51>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "cast-1.53",
     [[
         SELECT CAST('123.5abc' AS integer)
     ]], {
         -- <cast-1.53>
-        123
+        1, 'Type mismatch: can not convert 123.5abc to integer'
         -- </cast-1.53>
     })
 
+
 test:do_execsql_test(
     "case-1.60",
     [[
@@ -606,26 +555,16 @@ test:do_execsql_test(
         -- </case-1.65>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "case-1.66",
     [[
         SELECT CAST('abc' AS REAL)
     ]], {
         -- <case-1.66>
-        0.0
+        1, 'Type mismatch: can not convert abc to real'
         -- </case-1.66>
     })
 
-test:do_execsql_test(
-    "case-1.67",
-    [[
-        SELECT typeof(CAST('abc' AS REAL))
-    ]], {
-        -- <case-1.67>
-        "real"
-        -- </case-1.67>
-    })
-
 test:do_execsql_test(
     "case-1.68",
     [[
@@ -905,50 +844,38 @@ end
 test:do_test(
     "cast-4.1",
     function()
-        return test:execsql [[
+        return test:catchsql [[
             CREATE TABLE t1(a TEXT primary key);
             INSERT INTO t1 VALUES('abc');
             SELECT a, CAST(a AS integer) FROM t1;
         ]]
     end, {
         -- <cast-4.1>
-        "abc", 0
+        1, 'Type mismatch: can not convert abc to integer'
         -- </cast-4.1>
     })
 
 test:do_test(
     "cast-4.2",
     function()
-        return test:execsql [[
+        return test:catchsql [[
             SELECT CAST(a AS integer), a FROM t1;
         ]]
     end, {
         -- <cast-4.2>
-        0, "abc"
+        1, 'Type mismatch: can not convert abc to integer'
         -- </cast-4.2>
     })
 
-test:do_test(
-    "cast-4.3",
-    function()
-        return test:execsql [[
-            SELECT a, CAST(a AS integer), a FROM t1;
-        ]]
-    end, {
-        -- <cast-4.3>
-        "abc", 0, "abc"
-        -- </cast-4.3>
-    })
-
 test:do_test(
     "cast-4.4",
     function()
-        return test:execsql [[
-            SELECT CAST(a AS integer), a, CAST(a AS real), a FROM t1;
+        return test:catchsql [[
+            SELECT a, CAST(a AS real), a FROM t1;
         ]]
     end, {
         -- <cast-4.4>
-        0, "abc", 0.0, "abc"
+        1, 'Type mismatch: can not convert abc to real'
         -- </cast-4.4>
     })
 
diff --git a/test/sql-tap/default.test.lua b/test/sql-tap/default.test.lua
index 314a35cd7515e18baff131edcf5ea0dabf03d7e2..1780a81c7418b9f1c4c1705496d7296e13d1c141 100755
--- a/test/sql-tap/default.test.lua
+++ b/test/sql-tap/default.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(16)
+test:plan(15)
 
 --!./tcltestrunner.lua
 -- 2005 August 18
@@ -241,7 +241,7 @@ test:do_catchsql_test(
 test:do_execsql_test(
     "default-5.4",
     [[
-        CREATE TABLE t6(id INTEGER PRIMARY KEY, b INT DEFAULT('id'));
+        CREATE TABLE t6(id INTEGER PRIMARY KEY, b TEXT DEFAULT('id'));
         INSERT INTO t6(id) VALUES(1);
         SELECT * FROM t6;
     ]], {
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index b1e113cc9f759840bce4b75d394e6080445354a4..47fb7a80958327f852a671b34a0d44e055fe0058 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -1574,7 +1574,7 @@ test:drop_all_tables()
 test:do_execsql_test(
     "e_select-7.10.0",
     [[
-        CREATE TABLE y1(a  TEXT COLLATE "unicode_ci" PRIMARY KEY, b  TEXT COLLATE binary, c INT );
+        CREATE TABLE y1(a  TEXT COLLATE "unicode_ci" PRIMARY KEY, b  TEXT COLLATE binary, c TEXT );
         INSERT INTO y1 VALUES('Abc', 'abc', 'aBC');
     ]], {
         -- <e_select-7.10.0>
diff --git a/test/sql-tap/fkey2.test.lua b/test/sql-tap/fkey2.test.lua
index 55849bdf87c75ba4b5694e60e020b12c54874118..61db29f32bc3d6b83bfe2ed2420437ddfcbbc17d 100755
--- a/test/sql-tap/fkey2.test.lua
+++ b/test/sql-tap/fkey2.test.lua
@@ -269,7 +269,7 @@ test:do_catchsql_test(
 test:do_catchsql_test(
     "fkey2-1.26",
     [[
-        INSERT INTO t8 VALUES(666, 'b');
+        INSERT INTO t8 VALUES(666, 54644);
     ]], {
         -- <fkey2-1.26>
         1, "FOREIGN KEY constraint failed"
diff --git a/test/sql-tap/in4.test.lua b/test/sql-tap/in4.test.lua
index 70fb207fd8041fdfe23b84fcf417fff8852b0a49..ef426b0925474147c833fe41c4862e52a6d6df71 100755
--- a/test/sql-tap/in4.test.lua
+++ b/test/sql-tap/in4.test.lua
@@ -673,7 +673,7 @@ test:do_execsql_test(
         SELECT c FROM t4b WHERE +b IN (a);
     ]], {
         -- <in4-4.19>
-        
+        4
         -- </in4-4.19>
     })
 
diff --git a/test/sql-tap/index1.test.lua b/test/sql-tap/index1.test.lua
index 8618ce8b5052da463bb2a29496e3998b2111ee20..49f61a52a3df34c3a73e7f107d83aa66f4d0c62a 100755
--- a/test/sql-tap/index1.test.lua
+++ b/test/sql-tap/index1.test.lua
@@ -785,7 +785,7 @@ test:do_catchsql_test(
         SELECT c FROM t6 WHERE a>123;
     ]], {
         -- <index-14.6>
-        1, "Can't convert to numeric "
+        1, "Type mismatch: can not convert  to numeric"
         -- </index-14.6>
     })
 
@@ -795,7 +795,7 @@ test:do_catchsql_test(
         SELECT c FROM t6 WHERE a>=123;
     ]], {
         -- <index-14.7>
-        1, "Can't convert to numeric "
+        1, "Type mismatch: can not convert  to numeric"
         -- </index-14.7>
     })
 
diff --git a/test/sql-tap/insert3.test.lua b/test/sql-tap/insert3.test.lua
index 720f5d7deb0808135e0733e91d3dba2f54c831fc..5a303a77f12db548c0d8d697ab054f17cfae0105 100755
--- a/test/sql-tap/insert3.test.lua
+++ b/test/sql-tap/insert3.test.lua
@@ -28,18 +28,18 @@ test:plan(18)
 test:do_execsql_test(
     "insert3-1.0",
     [[
-            CREATE TABLE t1(rowid INTEGER PRIMARY KEY AUTOINCREMENT, a INT ,b INT );
-            CREATE TABLE log(rowid INTEGER PRIMARY KEY AUTOINCREMENT, x  INT UNIQUE, y INT );
+            CREATE TABLE t1(rowid INTEGER PRIMARY KEY AUTOINCREMENT, a TEXT ,b INT);
+            CREATE TABLE log(rowid INTEGER PRIMARY KEY AUTOINCREMENT, x TEXT UNIQUE, y INT );
             CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN
               UPDATE log SET y=y+1 WHERE x=new.a;
               INSERT OR IGNORE INTO log(x, y) VALUES(new.a, 1);
             END;
-            INSERT INTO t1(a, b) VALUES('hello','world');
-            INSERT INTO t1(a, b) VALUES(5,10);
+            INSERT INTO t1(a, b) VALUES('hello',5);
+            INSERT INTO t1(a, b) VALUES('5',1);
             SELECT x,y FROM log ORDER BY x;
     ]], {
         -- <insert3-1.0>
-        5, 1, "hello", 1
+        "5", 1, "hello", 1
         -- </insert3-1.0>
 })
 
@@ -50,23 +50,23 @@ test:do_execsql_test(
             SELECT x, y FROM log ORDER BY x;
     ]], {
         -- <insert3-1.1>
-        5, 2, "hello", 2
+        "5", 2, "hello", 2
         -- </insert3-1.1>
 })
 
 test:do_execsql_test(
     "insert3-1.2",
     [[
-            CREATE TABLE log2(rowid INTEGER PRIMARY KEY AUTOINCREMENT, x  INT UNIQUE,y INT );
+            CREATE TABLE log2(rowid INTEGER PRIMARY KEY AUTOINCREMENT, x TEXT UNIQUE,y INT );
             CREATE TRIGGER r2 BEFORE INSERT ON t1 BEGIN
               UPDATE log2 SET y=y+1 WHERE x=new.b;
               INSERT OR IGNORE INTO log2(x, y) VALUES(new.b,1);
             END;
-            INSERT INTO t1(a, b) VALUES(453,'hi');
+            INSERT INTO t1(a, b) VALUES('hi', 453);
             SELECT x,y FROM log ORDER BY x;
     ]], {
         -- <insert3-1.2>
-        5, 2, 453, 1, "hello", 2
+        "5",2,"hello",2,"hi",1
         -- </insert3-1.2>
 })
 
@@ -76,7 +76,7 @@ test:do_execsql_test(
             SELECT x,y FROM log2 ORDER BY x;
     ]], {
         -- <insert3-1.3>
-        "hi", 1
+        "453", 1
         -- </insert3-1.3>
 })
 
@@ -88,7 +88,7 @@ test:do_execsql_test(
                 SELECT 'b:', x, y FROM log2 ORDER BY x;
     ]], {
         -- <insert3-1.4.1>
-        "a:", 5, 4, "b:", 10, 2, "b:", 20, 1, "a:", 453, 2, "a:", "hello", 4, "b:", "hi", 2, "b:", "world", 1
+        "b:","1",1,"b:","11",1,"b:","15",1,"b:","453",2,"a:","5",4,"b:","5",1,"a:","hello",4,"a:","hi",2
         -- </insert3-1.4.1>
 })
 
@@ -99,7 +99,7 @@ test:do_execsql_test(
                 SELECT 'b:', x, y FROM log2 ORDER BY x, y;
     ]], {
         -- <insert3-1.4.2>
-        "a:", 5, 4, "b:", 10, 2, "b:", 20, 1, "a:", 453, 2, "a:", "hello", 4, "b:", "hi", 2, "b:", "world", 1
+        "b:","1",1,"b:","11",1,"b:","15",1,"b:","453",2,"b:","5",1,"a:","5",4,"a:","hello",4,"a:","hi",2
         -- </insert3-1.4.2>
 })
 
@@ -110,7 +110,7 @@ test:do_execsql_test(
             SELECT x,y FROM log ORDER BY x;
     ]], {
         -- <insert3-1.5>
-        5, 4, 453, 2, "hello", 4, "xyz", 1
+        "5",4,"hello",4,"hi",2,"xyz",1
         -- </insert3-1.5>
 })
 
@@ -121,10 +121,10 @@ test:do_execsql_test(
     [[
             CREATE TABLE t2(
               a INTEGER PRIMARY KEY AUTOINCREMENT,
-              b  INT DEFAULT 'b',
-              c  INT DEFAULT 'c'
+              b TEXT DEFAULT 'b',
+              c TEXT DEFAULT 'c'
             );
-            CREATE TABLE t2dup(rowid INTEGER PRIMARY KEY AUTOINCREMENT, a INT ,b INT ,c INT );
+            CREATE TABLE t2dup(rowid INTEGER PRIMARY KEY AUTOINCREMENT, a INT ,b TEXT, c TEXT);
             CREATE TRIGGER t2r1 BEFORE INSERT ON t2 BEGIN
               INSERT INTO t2dup(a,b,c) VALUES(new.a,new.b,new.c);
             END;
@@ -134,7 +134,7 @@ test:do_execsql_test(
             SELECT * FROM t2dup;
     ]], {
         -- <insert3-2.1>
-        1, 123, "b", "c", 2, -1, 234, "c", 3, -1, "b", 345
+        1, 123, "b", "c", 2, -1, "234", "c", 3, -1, "b", "345"
         -- </insert3-2.1>
 })
 
@@ -148,7 +148,7 @@ test:do_execsql_test(
             SELECT * FROM t2dup;
     ]], {
         -- <insert3-2.2>
-        4, 1, "b", "c", 5, -1, 987, "c", 6, -1, "b", 876
+        4, 1, "b", "c", 5, -1, "987", "c", 6, -1, "b", "876"
         -- </insert3-2.2>
 })
 
@@ -209,7 +209,7 @@ test:do_execsql_test(
     [[
             CREATE TABLE t5(
               a INTEGER PRIMARY KEY AUTOINCREMENT,
-              b  INT DEFAULT 'xyz'
+              b TEXT DEFAULT 'xyz'
             );
             INSERT INTO t5 DEFAULT VALUES;
             SELECT * FROM t5;
@@ -233,7 +233,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "insert3-3.7",
     [[
-            CREATE TABLE t6(id INTEGER PRIMARY KEY AUTOINCREMENT, x INT ,y  INT DEFAULT 4.3, z  INT DEFAULT x'6869');
+            CREATE TABLE t6(id INTEGER PRIMARY KEY AUTOINCREMENT, x INT ,y FLOAT DEFAULT 4.3, z TEXT DEFAULT 'hi');
             INSERT INTO t6 DEFAULT VALUES;
             SELECT * FROM t6;
     ]], {
diff --git a/test/sql-tap/like3.test.lua b/test/sql-tap/like3.test.lua
index ea6824ba7a8048298e89f1701205c50c89b17353..f9adb31bd9c392f34c1b2a7de01e99846953f767 100755
--- a/test/sql-tap/like3.test.lua
+++ b/test/sql-tap/like3.test.lua
@@ -93,46 +93,46 @@ test:do_execsql_test(
 test:do_execsql_test(
     "like3-2.2",
     [[
-        SELECT a, b FROM t2 WHERE b>=x'6162' AND b GLOB 'ab*'
+        SELECT a, b FROM t2 WHERE b>='ab' AND b GLOB 'ab*'
     ]], {
         -- <like3-2.2>
-        4, "abc"
+        1, "abc", 4, "abc"
         -- </like3-2.2>
     })
 
 test:do_execsql_test(
     "like3-2.3",
     [[
-        SELECT a, b FROM t2 WHERE +b>=x'6162' AND +b GLOB 'ab*'
+        SELECT a, b FROM t2 WHERE +b>='ab' AND +b GLOB 'ab*'
     ]], {
         -- <like3-2.3>
-        4, "abc"
+        1, "abc", 4, "abc"
         -- </like3-2.3>
     })
 
 test:do_execsql_test(
     "like3-2.4",
     [[
-        SELECT a, b FROM t2 WHERE b GLOB 'ab*' AND b>=x'6162'
+        SELECT a, b FROM t2 WHERE b GLOB 'ab*' AND b>='ab'
     ]], {
         -- <like3-2.4>
-        4, "abc"
+        1, "abc", 4, "abc"
         -- </like3-2.4>
     })
 
 test:do_execsql_test(
     "like3-2.5",
     [[
-        SELECT a, b FROM t2 WHERE +b GLOB 'ab*' AND +b>=x'6162'
+        SELECT a, b FROM t2 WHERE +b GLOB 'ab*' AND +b>='ab'
     ]], {
         -- <like3-2.5>
-        4, "abc"
+        1, "abc", 4, "abc"
         -- </like3-2.5>
     })
+
 test:execsql([[
     CREATE TABLE t3(x TEXT PRIMARY KEY COLLATE "unicode_ci");
     INSERT INTO t3(x) VALUES('aaa'),('abc'),('abd'),('abe'),('acz');
-    INSERT INTO t3(x) SELECT CAST(x AS blob) FROM t3;
 ]])
 
 -- MUST_WORK #1476 collate nocase
diff --git a/test/sql-tap/misc1.test.lua b/test/sql-tap/misc1.test.lua
index 73506ded161fe525f0e47ba1c54cd14ded97e03d..0bf680fe67b646f6cfa20c5f5159987dea8baa3b 100755
--- a/test/sql-tap/misc1.test.lua
+++ b/test/sql-tap/misc1.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(59)
+test:plan(58)
 
 --!./tcltestrunner.lua
 -- 2001 September 15.
@@ -1047,17 +1047,6 @@ test:do_catchsql_test(
         -- </misc1-21.2>
     })
 
--- 2015-04-15
-test:do_execsql_test(
-    "misc1-22.1",
-    [[
-        SELECT ''+3 FROM (SELECT ''+5);
-    ]], {
-        -- <misc1-22.1>
-        3
-        -- </misc1-22.1>
-    })
-
 -- # 2015-04-19: NULL pointer dereference on a corrupt schema
 -- #
 -- db close
diff --git a/test/sql-tap/numcast.test.lua b/test/sql-tap/numcast.test.lua
index f917e5a51e71d18c8e1e2d293efe5d34af754d35..a335d45e435c596f0991fc80497018e3f6ff807c 100755
--- a/test/sql-tap/numcast.test.lua
+++ b/test/sql-tap/numcast.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(17)
+test:plan(11)
 
 --!./tcltestrunner.lua
 -- 2013 March 20
@@ -40,9 +40,6 @@ for _, enc in ipairs({"utf8"}) do
         {"3", "-12345.0e0", -12345.0, -12345},
         {"4", "-12345.25", -12345.25, -12345},
         {"5", "-12345.0", -12345.0, -12345},
-        {"6", "'876xyz'", 876.0, 876},
-        {"7", "'456Ä·89'", 456.0, 456},
-        {"8", "'Ä  321.5'", 0.0, 0},
     }
     for _, val in ipairs(data) do
         local idx = val[1]
diff --git a/test/sql-tap/quote.test.lua b/test/sql-tap/quote.test.lua
index 61eb3153b09a7794328045490aca73f0bf572c15..3f0bf865d006a50a891c88a091b5db7cd3446535 100755
--- a/test/sql-tap/quote.test.lua
+++ b/test/sql-tap/quote.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(9)
+test:plan(8)
 
 --!./tcltestrunner.lua
 -- 2001 September 15
@@ -68,16 +68,6 @@ test:do_catchsql_test(
 
 test:do_catchsql_test(
     "quote-1.3.1",
-    [[
-        SELECT '!pqr', '#xyz'+5 FROM "abc5_"
-    ]], {
-        -- <quote-1.3.1>
-        0, {"!pqr", 5}
-        -- </quote-1.3.1>
-    })
-
-test:do_catchsql_test(
-    "quote-1.3.2",
     [[
         SELECT "!pqr", "#xyz"+5 FROM "abc5_"
     ]], {
diff --git a/test/sql-tap/select1.test.lua b/test/sql-tap/select1.test.lua
index 62bfc393c752f0f1550af92f8d5037c562c7a9be..65fd7daf448739fb41626013450940385ff6e59a 100755
--- a/test/sql-tap/select1.test.lua
+++ b/test/sql-tap/select1.test.lua
@@ -314,7 +314,7 @@ test:do_catchsql_test(
         SELECT count(*),count(a),count(b) FROM t4 WHERE b=5
     ]], {
         -- <select1-2.5.3>
-        1, "Can't convert to numeric This is a string that is too big to fit inside a NBFS buffer"
+        1, "Type mismatch: can not convert This is a string that is too big to fit inside a NBFS buffer to numeric"
         -- </select1-2.5.3>
     })
 
diff --git a/test/sql-tap/selectA.test.lua b/test/sql-tap/selectA.test.lua
index 9161cba91347cc456dd525f3f005223426b98e72..6540bf1665cc3d412e59c54b0b1c5cbfb4e023b0 100755
--- a/test/sql-tap/selectA.test.lua
+++ b/test/sql-tap/selectA.test.lua
@@ -88,7 +88,7 @@ test:do_execsql_test(
         ORDER BY a,b,c
     ]], {
         -- <selectA-2.1>
-        "","C","c","","U","u",-23,"Y","y",1,"a","a",4,"Z","z",9,"b","B",4444,"m","M",5200000,"X","x"
+        "","C","c","","U","u",-23,"Y","y",-9,"e","e",1,"a","a",4,"Z","z",4,"d","D",9,"b","B",4444,"m","M",5200000,"X","x"
         -- </selectA-2.1>
     })
 
@@ -102,7 +102,7 @@ test:do_test(
         ]]
     end, {
         -- <selectA-2.1.1>
-        "","C","c","","U","u",-23,"Y","y",1,"a","a",4,"Z","z",9,"b","B",4444,"m","M",5200000,"X","x"
+        "","C","c","","U","u",-23,"Y","y",-9,"e","e",1,"a","a",4,"Z","z",4,"d","D",9,"b","B",4444,"m","M",5200000,"X","x"
         -- </selectA-2.1.1>
     })
 
@@ -116,7 +116,7 @@ test:do_test(
         ]]
     end, {
         -- <selectA-2.1.2>
-        5200000,"X","x",4444,"m","M",9,"b","B",4,"Z","z",1,"a","a",-23,"Y","y","","C","c","","U","u"
+        "","C","c","","U","u",-23,"Y","y",-9,"e","e",1,"a","a",4,"Z","z",4,"d","D",9,"b","B",4444,"m","M",5200000,"X","x"
         -- </selectA-2.1.2>
     })
 
@@ -127,7 +127,7 @@ test:do_execsql_test(
         ORDER BY a DESC,b,c
     ]], {
         -- <selectA-2.2>
-        5200000,"X","x",4444,"m","M",9,"b","B",4,"Z","z",1,"a","a",-23,"Y","y","","C","c","","U","u"
+        5200000,"X","x",4444,"m","M",9,"b","B",4,"Z","z",4,"d","D",1,"a","a",-9,"e","e",-23,"Y","y","","C","c","","U","u"
         -- </selectA-2.2>
     })
 
@@ -138,7 +138,7 @@ test:do_execsql_test(
         ORDER BY a,c,b
     ]], {
         -- <selectA-2.3>
-        "","C","c","","U","u",-23,"Y","y",1,"a","a",4,"Z","z",9,"b","B",4444,"m","M",5200000,"X","x"
+        "","C","c","","U","u",-23,"Y","y",-9,"e","e",1,"a","a",4,"d","D",4,"Z","z",9,"b","B",4444,"m","M",5200000,"X","x"
         -- </selectA-2.3>
     })
 
@@ -149,7 +149,7 @@ test:do_execsql_test(
         ORDER BY b,a,c
     ]], {
         -- <selectA-2.4>
-        "","C","c","","U","u",5200000,"X","x",-23,"Y","y",4,"Z","z",1,"a","a",9,"b","B",4444,"m","M"
+        "","C","c","","U","u",5200000,"X","x",-23,"Y","y",4,"Z","z",1,"a","a",9,"b","B",4,"d","D",-9,"e","e",4444,"m","M"
         -- </selectA-2.4>
     })
 
@@ -160,7 +160,7 @@ test:do_execsql_test(
         ORDER BY b COLLATE "unicode_ci",a,c
     ]], {
         -- <selectA-2.5>
-        "","C","c","","U","u",5200000,"X","x",-23,"Y","y",4,"Z","z",1,"a","a",9,"b","B",4444,"m","M"
+        1,"a","a",9,"b","B","","C","c",4,"d","D",-9,"e","e",4444,"m","M","","U","u",5200000,"X","x",-23,"Y","y",4,"Z","z"
         -- </selectA-2.5>
     })
 
@@ -171,7 +171,7 @@ test:do_execsql_test(
         ORDER BY b COLLATE "unicode_ci" DESC,a,c
     ]], {
         -- <selectA-2.6>
-        "mad", "Z", "z", -23, "Y", "y", 5200000.0, "X", "x", "", "U", "u", "hare", "m", "M", "abc", "e", "e", "hello", "d", "D", "", "C", "c", 9.9, "b", "B", 1, "a", "a"
+        4,"Z","z",-23,"Y","y",5200000,"X","x","","U","u",4444,"m","M",-9,"e","e",4,"d","D","","C","c",9,"b","B",1,"a","a"
         -- </selectA-2.6>
     })
 
@@ -2370,8 +2370,8 @@ test:do_execsql_test(
     [[
         DROP TABLE IF EXISTS t4;
         DROP TABLE IF EXISTS t5;
-        CREATE TABLE t4(id int primary key, a int, b INT );
-        CREATE TABLE t5(id int primary key, c int, d INT );
+        CREATE TABLE t4(id int primary key, a int, b TEXT);
+        CREATE TABLE t5(id int primary key, c int, d TEXT);
 
         INSERT INTO t5 VALUES(0, 1, 'x');
         INSERT INTO t5 VALUES(1, 2, 'x');
diff --git a/test/sql-tap/sort.test.lua b/test/sql-tap/sort.test.lua
index 240c7db583f6d1e343f0fca42af74759c262afcc..144c9a00c914e67b4fd70f840c540138a67a42c2 100755
--- a/test/sql-tap/sort.test.lua
+++ b/test/sql-tap/sort.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(62)
+test:plan(60)
 
 --!./tcltestrunner.lua
 -- 2001 September 15.
@@ -257,16 +257,6 @@ test:do_execsql_test(
         -- </sort-2.1.2>
     })
 
-test:do_execsql_test(
-    "sort-2.1.3",
-    [[
-        SELECT v FROM t1 ORDER BY substr(v,2,999)+0.0;
-    ]], {
-        -- <sort-2.1.3>
-        "x-4221.0", "x-123.0", "x-3.141592653", "x-2.15", "x-2b", "x0.0013442", "x1.6", "x11.0"
-        -- </sort-2.1.3>
-    })
-
 test:do_execsql_test(
     "sort-2.1.4",
     [[
@@ -277,16 +267,6 @@ test:do_execsql_test(
         -- </sort-2.1.4>
     })
 
-test:do_execsql_test(
-    "sort-2.1.5",
-    [[
-        SELECT v FROM t1 ORDER BY substr(v,2,999)+0.0 DESC;
-    ]], {
-        -- <sort-2.1.5>
-        "x11.0", "x1.6", "x0.0013442", "x-2b", "x-2.15", "x-3.141592653", "x-123.0", "x-4221.0"
-        -- </sort-2.1.5>
-    })
-
 -- This is a bug fix for 2.2.4.
 -- Strings are normally mapped to upper-case for a caseless comparison.
 -- But this can cause problems for characters in between 'Z' and 'a'.
diff --git a/test/sql-tap/tkt-a8a0d2996a.test.lua b/test/sql-tap/tkt-a8a0d2996a.test.lua
index 6f5860f82ba516aefdb04337fab4370e3a1b7a31..aefc2be0c87d7eef4adac908652294bd634acb06 100755
--- a/test/sql-tap/tkt-a8a0d2996a.test.lua
+++ b/test/sql-tap/tkt-a8a0d2996a.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(22)
+test:plan(12)
 
 --!./tcltestrunner.lua
 -- 2014-03-24
@@ -72,57 +72,6 @@ test:do_execsql_test(
         -- </1.4>
     })
 
-test:do_execsql_test(
-    2.0,
-    [[
-        UPDATE t SET x='1xyzzy';
-        SELECT typeof(x), typeof(y) FROM t WHERE 1=x+0 AND y=='1';
-    ]], {
-        -- <2.0>
-        "text", "text"
-        -- </2.0>
-    })
-
-test:do_execsql_test(
-    2.1,
-    [[
-        SELECT typeof(x), typeof(y) FROM t WHERE 1=x-0 AND y=='1';
-    ]], {
-        -- <2.1>
-        "text", "text"
-        -- </2.1>
-    })
-
-test:do_execsql_test(
-    2.2,
-    [[
-        SELECT typeof(x), typeof(y) FROM t WHERE 1=x*1 AND y=='1';
-    ]], {
-        -- <2.2>
-        "text", "text"
-        -- </2.2>
-    })
-
-test:do_execsql_test(
-    2.3,
-    [[
-        SELECT typeof(x), typeof(y) FROM t WHERE 1=x/1 AND y=='1';
-    ]], {
-        -- <2.3>
-        "text", "text"
-        -- </2.3>
-    })
-
-test:do_execsql_test(
-    2.4,
-    [[
-        SELECT typeof(x), typeof(y) FROM t WHERE 1=x%4 AND y=='1';
-    ]], {
-        -- <2.4>
-        "text", "text"
-        -- </2.4>
-    })
-
 test:do_execsql_test(
     3.0,
     [[
@@ -194,54 +143,4 @@ test:do_execsql_test(
         -- </4.1>
     })
 
-test:do_execsql_test(
-    4.2,
-    [[
-        SELECT '100x'+'-2y';
-    ]], {
-        -- <4.2>
-        98
-        -- </4.2>
-    })
-
-test:do_execsql_test(
-    4.3,
-    [[
-        SELECT '100x'+'4.5y';
-    ]], {
-        -- <4.3>
-        104.5
-        -- </4.3>
-    })
-
-test:do_execsql_test(
-    4.4,
-    [[
-        SELECT '-9223372036854775807x'-'1x';
-    ]], {
-        -- <4.4>
-        -9223372036854775808
-        -- </4.4>
-    })
-
-test:do_execsql_test(
-    4.5,
-    [[
-        SELECT '9223372036854775806x'+'1x';
-    ]], {
-        -- <4.5>
-        9223372036854775808
-        -- </4.5>
-    })
-
-test:do_execsql_test(
-    4.6,
-    [[
-        SELECT '1234x'/'10y';
-    ]], {
-        -- <4.6>
-        123.4
-        -- </4.6>
-    })
-
 test:finish_test()
diff --git a/test/sql-tap/tkt3493.test.lua b/test/sql-tap/tkt3493.test.lua
index 31d81d52915bdc559e091063ea7ed9664af3bfd9..26ca2271bb3d79816d03ad9004e2760377681b43 100755
--- a/test/sql-tap/tkt3493.test.lua
+++ b/test/sql-tap/tkt3493.test.lua
@@ -169,7 +169,7 @@ test:do_execsql_test(
         SELECT count(*), +a=123 FROM t1 
     ]], {
         -- <tkt3493-2.2.5>
-        1, 0
+        1, 1
         -- </tkt3493-2.2.5>
     })
 
diff --git a/test/sql-tap/triggerC.test.lua b/test/sql-tap/triggerC.test.lua
index 2303b5ca6d0c62169131881078a46c6b0f909e5a..59a6d236797f459180542d39a57ba06699be222a 100755
--- a/test/sql-tap/triggerC.test.lua
+++ b/test/sql-tap/triggerC.test.lua
@@ -974,7 +974,7 @@ test:do_execsql_test(
         PRAGMA recursive_triggers = 1;
         CREATE TABLE node(
             id int not null primary key,
-            pid int not null default 0 references node,
+            pid int not null default 0,
             key TEXT not null,
             path TEXT default '',
             unique(pid, key)
diff --git a/test/sql-tap/types2.test.lua b/test/sql-tap/types2.test.lua
index 6b10bc226df75ed78601a392422aebc0413e5ea8..2049d93720ba7d6513c51caa58c3be8e7beb96fc 100755
--- a/test/sql-tap/types2.test.lua
+++ b/test/sql-tap/types2.test.lua
@@ -112,7 +112,7 @@ test_bool("types2-1.28", "o1='500'", "'500.0' = o1", 0)
 local vals = { 10, "10.0", "'10'", "'10.0'", 20, "20.0", "'20'", "'20.0'", 30, "30.0", "'30'", "'30.0'" }
 --             1    2      3         4      5  6       7        8      9    10       11   12
 test:execsql [[
-    CREATE TABLE t2(id  INT primary key, i INTEGER, n NUMERIC, t TEXT, o XBLOBY);
+    CREATE TABLE t2(id  INT primary key, i INTEGER, n NUMERIC, t TEXT, o BLOB);
     CREATE INDEX t2i1 ON t2(i);
     CREATE INDEX t2i2 ON t2(n);
     CREATE INDEX t2i3 ON t2(t);
@@ -306,7 +306,7 @@ test_bool("types2-7.15", "o1='2'", "o1 IN (SELECT o||'' FROM t3)", 1)
 -- set vals [list 10 10.0 '10' '10.0' 20 20.0 '20' '20.0' 30 30.0 '30' '30.0']
 --                1  2    3    4      5  6    7    8      9  10   11   12
 test:execsql [[
-    CREATE TABLE t4(id  INT primary key, i INTEGER, n NUMERIC, t VARCHAR(20), o  INT LARGE BLOB);
+    CREATE TABLE t4(id  INT primary key, i INTEGER, n NUMERIC, t VARCHAR(20), o BLOB);
     INSERT INTO t4 VALUES(1, 10, 20, 20, 30);
 ]]
 test_boolset("types2-8.1", "i IN (SELECT i FROM t4)", {1, 2, 3, 4})
diff --git a/test/sql-tap/where2.test.lua b/test/sql-tap/where2.test.lua
index 8e30f11cb339697142bb8d08e722df0b6e713d71..a2b60e3471dfcdca833187673ba8aafd7290320b 100755
--- a/test/sql-tap/where2.test.lua
+++ b/test/sql-tap/where2.test.lua
@@ -688,7 +688,7 @@ test:do_test(
   ]])
         end, {
             -- <where2-6.10>
-            "nosort", "T2249B", "*", "T2249A", "*"
+            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
             -- </where2-6.10>
         })
 
@@ -805,7 +805,7 @@ test:do_test(
     ]])
         end, {
             -- <where2-6.13>
-            "nosort", "T2249B", "*", "T2249A", "*"
+            123, "0123", "nosort", "T2249B", "*", "T2249A", "*"
             -- </where2-6.13>
         })
 
diff --git a/test/sql-tap/whereB.test.lua b/test/sql-tap/whereB.test.lua
index d92b834812ddd06bc1e0f65cddcacf63f652d253..42d90fa1884e118599e3820400a011abee04e318 100755
--- a/test/sql-tap/whereB.test.lua
+++ b/test/sql-tap/whereB.test.lua
@@ -74,6 +74,7 @@ test:do_execsql_test(
     ]],
     {
     -- <whereB-1.4>
+    1, 2, 1
     -- </whereB-1.4>
     })
 
@@ -107,7 +108,7 @@ test:do_execsql_test(
     ]],
     {
     -- <whereB-1.102>
-    
+    1, 2, 1
     -- </whereB-1.102>
     })
 
diff --git a/test/sql/persistency.result b/test/sql/persistency.result
index 36a7d555ba76a98414e174f268e539b542d9a48a..09f8eab2903b16fb9410427f1d28abc05dc70514 100644
--- a/test/sql/persistency.result
+++ b/test/sql/persistency.result
@@ -180,7 +180,7 @@ box.sql.execute("SELECT \"name\", \"opts\" FROM \"_trigger\"");
 -- ... functional
 box.sql.execute("INSERT INTO foobar VALUES ('foobar trigger test', 8888)")
 ---
-- error: datatype mismatch
+- error: 'Type mismatch: can not convert foobar trigger test to integer'
 ...
 box.sql.execute("SELECT * FROM barfoo WHERE foo = 9999");
 ---
diff --git a/test/sql/triggers.result b/test/sql/triggers.result
index 60e9a0ca87925153aa4c81e1801825aaafe20b67..45d231f7205e4be995742c83a90feeada1d7471a 100644
--- a/test/sql/triggers.result
+++ b/test/sql/triggers.result
@@ -253,7 +253,7 @@ box.sql.execute("DROP TABLE T1;")
 box.sql.execute("PRAGMA sql_default_engine ('vinyl');")
 ---
 ...
-box.sql.execute("CREATE TABLE m (s1 NUMERIC PRIMARY KEY);")
+box.sql.execute("CREATE TABLE m (s1 TEXT PRIMARY KEY);")
 ---
 ...
 box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = DATETIME('now'); END;")
@@ -262,10 +262,10 @@ box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE
 box.sql.execute("PRAGMA sql_default_engine('memtx');")
 ---
 ...
-box.sql.execute("CREATE TABLE n (s1 TEXT PRIMARY KEY, s2 TEXT);")
+box.sql.execute("CREATE TABLE n (s1 TEXT PRIMARY KEY, s2 REAL);")
 ---
 ...
-box.sql.execute("INSERT INTO m VALUES (0);")
+box.sql.execute("INSERT INTO m VALUES ('0');")
 ---
 ...
 box.sql.execute("INSERT INTO n VALUES ('',null);")
@@ -289,7 +289,7 @@ box.sql.execute("DROP TABLE n;")
 box.sql.execute("PRAGMA sql_default_engine ('memtx');")
 ---
 ...
-box.sql.execute("CREATE TABLE m (s1 NUMERIC PRIMARY KEY);")
+box.sql.execute("CREATE TABLE m (s1 TEXT PRIMARY KEY);")
 ---
 ...
 box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = DATETIME('now'); END;")
@@ -298,10 +298,10 @@ box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE
 box.sql.execute("PRAGMA sql_default_engine('vinyl');")
 ---
 ...
-box.sql.execute("CREATE TABLE n (s1 TEXT PRIMARY KEY, s2 TEXT);")
+box.sql.execute("CREATE TABLE n (s1 TEXT PRIMARY KEY, s2 REAL);")
 ---
 ...
-box.sql.execute("INSERT INTO m VALUES (0);")
+box.sql.execute("INSERT INTO m VALUES ('0');")
 ---
 ...
 box.sql.execute("INSERT INTO n VALUES ('',null);")
diff --git a/test/sql/triggers.test.lua b/test/sql/triggers.test.lua
index 243e9fc0b3d6799bdaa9e441938ba71b96a782a2..a322b2f0290703c240790074388ac0180b35fa0f 100644
--- a/test/sql/triggers.test.lua
+++ b/test/sql/triggers.test.lua
@@ -101,11 +101,11 @@ box.sql.execute("DROP TABLE T1;")
 --
 -- Case 1: Src 'vinyl' table; Dst 'memtx' table
 box.sql.execute("PRAGMA sql_default_engine ('vinyl');")
-box.sql.execute("CREATE TABLE m (s1 NUMERIC PRIMARY KEY);")
+box.sql.execute("CREATE TABLE m (s1 TEXT PRIMARY KEY);")
 box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = DATETIME('now'); END;")
 box.sql.execute("PRAGMA sql_default_engine('memtx');")
-box.sql.execute("CREATE TABLE n (s1 TEXT PRIMARY KEY, s2 TEXT);")
-box.sql.execute("INSERT INTO m VALUES (0);")
+box.sql.execute("CREATE TABLE n (s1 TEXT PRIMARY KEY, s2 REAL);")
+box.sql.execute("INSERT INTO m VALUES ('0');")
 box.sql.execute("INSERT INTO n VALUES ('',null);")
 box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
 
@@ -117,11 +117,11 @@ box.sql.execute("DROP TABLE n;")
 
 -- Case 2: Src 'memtx' table; Dst 'vinyl' table
 box.sql.execute("PRAGMA sql_default_engine ('memtx');")
-box.sql.execute("CREATE TABLE m (s1 NUMERIC PRIMARY KEY);")
+box.sql.execute("CREATE TABLE m (s1 TEXT PRIMARY KEY);")
 box.sql.execute("CREATE TRIGGER m1 BEFORE UPDATE ON m FOR EACH ROW BEGIN UPDATE n SET s2 = DATETIME('now'); END;")
 box.sql.execute("PRAGMA sql_default_engine('vinyl');")
-box.sql.execute("CREATE TABLE n (s1 TEXT PRIMARY KEY, s2 TEXT);")
-box.sql.execute("INSERT INTO m VALUES (0);")
+box.sql.execute("CREATE TABLE n (s1 TEXT PRIMARY KEY, s2 REAL);")
+box.sql.execute("INSERT INTO m VALUES ('0');")
 box.sql.execute("INSERT INTO n VALUES ('',null);")
 box.sql.execute("UPDATE m SET s1 = 'The Rain In Spain';")
 
diff --git a/test/sql/types.result b/test/sql/types.result
new file mode 100644
index 0000000000000000000000000000000000000000..1daeb7a8cae95ed64182026c3117acdacf66c86c
--- /dev/null
+++ b/test/sql/types.result
@@ -0,0 +1,106 @@
+env = require('test_run')
+---
+...
+test_run = env.new()
+---
+...
+-- gh-3018: typeless columns are prohibited.
+--
+box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY);")
+---
+- error: keyword "PRIMARY" is reserved
+...
+box.sql.execute("CREATE TABLE t1 (a, id INT PRIMARY KEY);")
+---
+- error: 'near ",": syntax error'
+...
+box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY, a INT);")
+---
+- error: keyword "PRIMARY" is reserved
+...
+box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a);")
+---
+- error: 'near ")": syntax error'
+...
+box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b UNIQUE);")
+---
+- error: keyword "UNIQUE" is reserved
+...
+-- gh-3104: real type is stored in space format.
+--
+box.sql.execute("CREATE TABLE t1 (id TEXT PRIMARY KEY, a REAL, b INT, c TEXT, d BLOB);")
+---
+...
+box.space.T1:format()
+---
+- [{'affinity': 66, 'type': 'string', 'nullable_action': 'abort', 'name': 'ID', 'is_nullable': false},
+  {'affinity': 69, 'type': 'number', 'nullable_action': 'none', 'name': 'A', 'is_nullable': true},
+  {'affinity': 68, 'type': 'integer', 'nullable_action': 'none', 'name': 'B', 'is_nullable': true},
+  {'affinity': 66, 'type': 'string', 'nullable_action': 'none', 'name': 'C', 'is_nullable': true},
+  {'affinity': 65, 'type': 'scalar', 'nullable_action': 'none', 'name': 'D', 'is_nullable': true}]
+...
+box.sql.execute("CREATE VIEW v1 AS SELECT b + a, b - a FROM t1;")
+---
+...
+box.space.V1:format()
+---
+- [{'affinity': 67, 'type': 'number', 'nullable_action': 'none', 'name': 'b + a',
+    'is_nullable': true}, {'affinity': 67, 'type': 'number', 'nullable_action': 'none',
+    'name': 'b - a', 'is_nullable': true}]
+...
+-- gh-2494: index's part also features correct declared type.
+--
+box.sql.execute("CREATE INDEX i1 ON t1 (a);")
+---
+...
+box.sql.execute("CREATE INDEX i2 ON t1 (b);")
+---
+...
+box.sql.execute("CREATE INDEX i3 ON t1 (c);")
+---
+...
+box.sql.execute("CREATE INDEX i4 ON t1 (id, c, b, a, d);")
+---
+...
+box.space.T1.index.I1.parts
+---
+- - type: number
+    is_nullable: true
+    fieldno: 2
+...
+box.space.T1.index.I2.parts
+---
+- - type: integer
+    is_nullable: true
+    fieldno: 3
+...
+box.space.T1.index.I3.parts
+---
+- - type: string
+    is_nullable: true
+    fieldno: 4
+...
+box.space.T1.index.I4.parts
+---
+- - type: string
+    is_nullable: false
+    fieldno: 1
+  - type: string
+    is_nullable: true
+    fieldno: 4
+  - type: integer
+    is_nullable: true
+    fieldno: 3
+  - type: number
+    is_nullable: true
+    fieldno: 2
+  - type: scalar
+    is_nullable: true
+    fieldno: 5
+...
+box.sql.execute("DROP VIEW v1;")
+---
+...
+box.sql.execute("DROP TABLE t1;")
+---
+...
diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua
new file mode 100644
index 0000000000000000000000000000000000000000..5f6b4dc49e1db36356cc8df3683da53dd48c7232
--- /dev/null
+++ b/test/sql/types.test.lua
@@ -0,0 +1,31 @@
+env = require('test_run')
+test_run = env.new()
+
+-- gh-3018: typeless columns are prohibited.
+--
+box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY);")
+box.sql.execute("CREATE TABLE t1 (a, id INT PRIMARY KEY);")
+box.sql.execute("CREATE TABLE t1 (id PRIMARY KEY, a INT);")
+box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a);")
+box.sql.execute("CREATE TABLE t1 (id INT PRIMARY KEY, a INT, b UNIQUE);")
+
+-- gh-3104: real type is stored in space format.
+--
+box.sql.execute("CREATE TABLE t1 (id TEXT PRIMARY KEY, a REAL, b INT, c TEXT, d BLOB);")
+box.space.T1:format()
+box.sql.execute("CREATE VIEW v1 AS SELECT b + a, b - a FROM t1;")
+box.space.V1:format()
+
+-- gh-2494: index's part also features correct declared type.
+--
+box.sql.execute("CREATE INDEX i1 ON t1 (a);")
+box.sql.execute("CREATE INDEX i2 ON t1 (b);")
+box.sql.execute("CREATE INDEX i3 ON t1 (c);")
+box.sql.execute("CREATE INDEX i4 ON t1 (id, c, b, a, d);")
+box.space.T1.index.I1.parts
+box.space.T1.index.I2.parts
+box.space.T1.index.I3.parts
+box.space.T1.index.I4.parts
+
+box.sql.execute("DROP VIEW v1;")
+box.sql.execute("DROP TABLE t1;")