[Tarantool-patches] [PATCH v1 1/7] sql: remove enum field_type from struct Mem

imeevma at tarantool.org imeevma at tarantool.org
Wed Aug 11 19:01:40 MSK 2021


This patch removes the enum field_type from the struct MEM since the
only place where this field was used is in the typeof() function. After
this patch, typeof() will return "NULL" if it receives NULL. Prior to
this patch, the field type was returned if it was set, otherwise it was
returned "boolean". Another reason for the removal was that field_type
was quite volatile and could change in unexpected places.

Also, this patch made another change: values of the field type NUMBER
will now be processed by the typeof() as INTEGER or DOUBLE, depending
on the storage type. However, this will be fixed in the next patch.

Part of #5956
Needed for #6221
---
 .../gh-5956-remove-field-types-from-mem.md    |   3 +
 src/box/sql/func.c                            |  15 +--
 src/box/sql/mem.c                             | 120 +++---------------
 src/box/sql/mem.h                             |   7 -
 src/box/sql/vdbe.c                            |  25 +---
 src/box/sql/vdbeInt.h                         |   3 -
 src/box/sql/vdbesort.c                        |   6 -
 test/sql-tap/cast.test.lua                    |  16 +--
 test/sql-tap/default.test.lua                 |   2 +-
 test/sql-tap/func.test.lua                    |  12 +-
 test/sql-tap/func5.test.lua                   |  75 ++++++++++-
 test/sql-tap/select7.test.lua                 |   4 +-
 test/sql-tap/table.test.lua                   |   4 +-
 test/sql-tap/tkt-3998683a16.test.lua          |   1 -
 test/sql/boolean.result                       |   4 +-
 test/sql/gh-4697-scalar-bool-sort-cmp.result  |   4 +-
 test/sql/types.result                         |   8 +-
 17 files changed, 128 insertions(+), 181 deletions(-)
 create mode 100644 changelogs/unreleased/gh-5956-remove-field-types-from-mem.md

diff --git a/changelogs/unreleased/gh-5956-remove-field-types-from-mem.md b/changelogs/unreleased/gh-5956-remove-field-types-from-mem.md
new file mode 100644
index 000000000..81fc21233
--- /dev/null
+++ b/changelogs/unreleased/gh-5956-remove-field-types-from-mem.md
@@ -0,0 +1,3 @@
+## feature/sql
+
+* The typeof() function with NULL as an argument now returns "NULL" (gh-5956).
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 1622104d3..5ac5c5e56 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -162,17 +162,6 @@ typeofFunc(sql_context * context, int NotUsed, sql_value ** argv)
 {
 	const char *z = 0;
 	UNUSED_PARAMETER(NotUsed);
-	enum field_type f_t = argv[0]->field_type;
-	/*
-	 * SCALAR is not a basic type, but rather an aggregation of
-	 * types. Thus, ignore SCALAR field type and return msgpack
-	 * format type.
-	 */
-	if (f_t != field_type_MAX && f_t != FIELD_TYPE_SCALAR) {
-		sql_result_text(context, field_type_strs[argv[0]->field_type],
-				-1, SQL_STATIC);
-		return;
-	}
 	switch (argv[0]->type) {
 	case MEM_TYPE_INT:
 	case MEM_TYPE_UINT:
@@ -190,9 +179,11 @@ typeofFunc(sql_context * context, int NotUsed, sql_value ** argv)
 		z = "varbinary";
 		break;
 	case MEM_TYPE_BOOL:
-	case MEM_TYPE_NULL:
 		z = "boolean";
 		break;
+	case MEM_TYPE_NULL:
+		z = "NULL";
+		break;
 	case MEM_TYPE_UUID:
 		z = "uuid";
 		break;
diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index d1ef92a86..773ef4d40 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -193,7 +193,6 @@ mem_create(struct Mem *mem)
 {
 	mem->type = MEM_TYPE_NULL;
 	mem->flags = 0;
-	mem->field_type = field_type_MAX;
 	mem->n = 0;
 	mem->z = NULL;
 	mem->zMalloc = NULL;
@@ -226,7 +225,6 @@ mem_clear(struct Mem *mem)
 	}
 	mem->type = MEM_TYPE_NULL;
 	mem->flags = 0;
-	mem->field_type = field_type_MAX;
 }
 
 void
@@ -255,7 +253,6 @@ mem_set_int(struct Mem *mem, int64_t value, bool is_neg)
 	mem->u.i = value;
 	mem->type = is_neg ? MEM_TYPE_INT : MEM_TYPE_UINT;
 	assert(mem->flags == 0);
-	mem->field_type = FIELD_TYPE_INTEGER;
 }
 
 void
@@ -265,7 +262,6 @@ mem_set_uint(struct Mem *mem, uint64_t value)
 	mem->u.u = value;
 	mem->type = MEM_TYPE_UINT;
 	assert(mem->flags == 0);
-	mem->field_type = FIELD_TYPE_UNSIGNED;
 }
 
 void
@@ -275,14 +271,12 @@ mem_set_bool(struct Mem *mem, bool value)
 	mem->u.b = value;
 	mem->type = MEM_TYPE_BOOL;
 	assert(mem->flags == 0);
-	mem->field_type = FIELD_TYPE_BOOLEAN;
 }
 
 void
 mem_set_double(struct Mem *mem, double value)
 {
 	mem_clear(mem);
-	mem->field_type = FIELD_TYPE_DOUBLE;
 	assert(mem->flags == 0);
 	if (sqlIsNaN(value))
 		return;
@@ -294,7 +288,6 @@ void
 mem_set_uuid(struct Mem *mem, const struct tt_uuid *uuid)
 {
 	mem_clear(mem);
-	mem->field_type = FIELD_TYPE_UUID;
 	mem->u.uuid = *uuid;
 	mem->type = MEM_TYPE_UUID;
 	assert(mem->flags == 0);
@@ -309,7 +302,6 @@ set_str_const(struct Mem *mem, char *value, uint32_t len, int alloc_type)
 	mem->n = len;
 	mem->type = MEM_TYPE_STR;
 	mem->flags = alloc_type;
-	mem->field_type = FIELD_TYPE_STRING;
 }
 
 static inline void
@@ -323,7 +315,6 @@ set_str_dynamic(struct Mem *mem, char *value, uint32_t len, int alloc_type)
 	mem->n = len;
 	mem->type = MEM_TYPE_STR;
 	mem->flags = alloc_type;
-	mem->field_type = FIELD_TYPE_STRING;
 	if (alloc_type == MEM_Dyn) {
 		mem->xDel = sql_free;
 	} else {
@@ -395,7 +386,6 @@ mem_copy_str(struct Mem *mem, const char *value, uint32_t len)
 			return -1;
 		mem->type = MEM_TYPE_STR;
 		mem->flags = 0;
-		mem->field_type = FIELD_TYPE_STRING;
 		return 0;
 	}
 	mem_clear(mem);
@@ -405,7 +395,6 @@ mem_copy_str(struct Mem *mem, const char *value, uint32_t len)
 	mem->n = len;
 	mem->type = MEM_TYPE_STR;
 	assert(mem->flags == 0);
-	mem->field_type = FIELD_TYPE_STRING;
 	return 0;
 }
 
@@ -429,7 +418,6 @@ set_bin_const(struct Mem *mem, char *value, uint32_t size, int alloc_type)
 	mem->n = size;
 	mem->type = MEM_TYPE_BIN;
 	mem->flags = alloc_type;
-	mem->field_type = FIELD_TYPE_VARBINARY;
 }
 
 static inline void
@@ -443,7 +431,6 @@ set_bin_dynamic(struct Mem *mem, char *value, uint32_t size, int alloc_type)
 	mem->n = size;
 	mem->type = MEM_TYPE_BIN;
 	mem->flags = alloc_type;
-	mem->field_type = FIELD_TYPE_VARBINARY;
 	if (alloc_type == MEM_Dyn) {
 		mem->xDel = sql_free;
 	} else {
@@ -487,7 +474,6 @@ mem_copy_bin(struct Mem *mem, const char *value, uint32_t size)
 			return -1;
 		mem->type = MEM_TYPE_BIN;
 		mem->flags = 0;
-		mem->field_type = FIELD_TYPE_VARBINARY;
 		return 0;
 	}
 	mem_clear(mem);
@@ -497,7 +483,6 @@ mem_copy_bin(struct Mem *mem, const char *value, uint32_t size)
 	mem->n = size;
 	mem->type = MEM_TYPE_BIN;
 	assert(mem->flags == 0);
-	mem->field_type = FIELD_TYPE_VARBINARY;
 	return 0;
 }
 
@@ -512,76 +497,73 @@ mem_set_zerobin(struct Mem *mem, int n)
 	mem->n = 0;
 	mem->type = MEM_TYPE_BIN;
 	mem->flags = MEM_Zero;
-	mem->field_type = FIELD_TYPE_VARBINARY;
 }
 
 static inline void
 set_msgpack_value(struct Mem *mem, char *value, uint32_t size, int alloc_type,
-		  enum field_type type)
+		  enum mem_type type)
 {
-	assert(type == FIELD_TYPE_MAP || type == FIELD_TYPE_ARRAY);
 	if (alloc_type == MEM_Ephem || alloc_type == MEM_Static)
 		set_bin_const(mem, value, size, alloc_type);
 	else
 		set_bin_dynamic(mem, value, size, alloc_type);
-	mem->type = type == FIELD_TYPE_MAP ? MEM_TYPE_MAP : MEM_TYPE_ARRAY;
-	mem->field_type = type;
+	mem->type = type;
 }
 
 void
 mem_set_map_ephemeral(struct Mem *mem, char *value, uint32_t size)
 {
 	assert(mp_typeof(*value) == MP_MAP);
-	set_msgpack_value(mem, value, size, MEM_Ephem, FIELD_TYPE_MAP);
+	set_msgpack_value(mem, value, size, MEM_Ephem, MEM_TYPE_MAP);
 }
 
 void
 mem_set_map_static(struct Mem *mem, char *value, uint32_t size)
 {
 	assert(mp_typeof(*value) == MP_MAP);
-	set_msgpack_value(mem, value, size, MEM_Static, FIELD_TYPE_MAP);
+	set_msgpack_value(mem, value, size, MEM_Static, MEM_TYPE_MAP);
 }
 
 void
 mem_set_map_dynamic(struct Mem *mem, char *value, uint32_t size)
 {
 	assert(mp_typeof(*value) == MP_MAP);
-	set_msgpack_value(mem, value, size, MEM_Dyn, FIELD_TYPE_MAP);
+	set_msgpack_value(mem, value, size, MEM_Dyn, MEM_TYPE_MAP);
 }
 
 void
 mem_set_map_allocated(struct Mem *mem, char *value, uint32_t size)
 {
 	assert(mp_typeof(*value) == MP_MAP);
-	set_msgpack_value(mem, value, size, 0, FIELD_TYPE_MAP);
+	set_msgpack_value(mem, value, size, 0, MEM_TYPE_MAP);
 }
 
 void
 mem_set_array_ephemeral(struct Mem *mem, char *value, uint32_t size)
 {
 	assert(mp_typeof(*value) == MP_ARRAY);
-	set_msgpack_value(mem, value, size, MEM_Ephem, FIELD_TYPE_ARRAY);
+	set_msgpack_value(mem, value, size, MEM_Ephem, MEM_TYPE_ARRAY);
 }
 
 void
 mem_set_array_static(struct Mem *mem, char *value, uint32_t size)
 {
 	assert(mp_typeof(*value) == MP_ARRAY);
-	set_msgpack_value(mem, value, size, MEM_Static, FIELD_TYPE_ARRAY);
+	set_msgpack_value(mem, value, size, MEM_Static, MEM_TYPE_ARRAY);
 }
 
 void
 mem_set_array_dynamic(struct Mem *mem, char *value, uint32_t size)
 {
 	assert(mp_typeof(*value) == MP_ARRAY);
-	set_msgpack_value(mem, value, size, MEM_Dyn, FIELD_TYPE_ARRAY);
+	set_msgpack_value(mem, value, size, MEM_Dyn, MEM_TYPE_ARRAY);
 }
 
 void
 mem_set_array_allocated(struct Mem *mem, char *value, uint32_t size)
 {
 	assert(mp_typeof(*value) == MP_ARRAY);
-	set_msgpack_value(mem, value, size, 0, FIELD_TYPE_ARRAY);
+	set_msgpack_value(mem, value, size, 0, MEM_TYPE_ARRAY);
 }
 
 void
@@ -623,7 +605,6 @@ mem_set_agg(struct Mem *mem, struct func *func, int size)
 	mem->type = MEM_TYPE_AGG;
 	assert(mem->flags == 0);
 	mem->u.func = func;
-	mem->field_type = field_type_MAX;
 	return 0;
 }
 
@@ -646,7 +627,6 @@ int_to_double(struct Mem *mem)
 	mem->u.r = d;
 	mem->type = MEM_TYPE_DOUBLE;
 	assert(mem->flags == 0);
-	mem->field_type = FIELD_TYPE_DOUBLE;
 	return 0;
 }
 
@@ -660,7 +640,6 @@ int_to_double_precise(struct Mem *mem)
 		return -1;
 	mem->u.r = d;
 	mem->type = MEM_TYPE_DOUBLE;
-	mem->field_type = FIELD_TYPE_DOUBLE;
 	return 0;
 }
 
@@ -677,7 +656,6 @@ int_to_double_forced(struct Mem *mem)
 	double d = (double)i;
 	mem->u.r = d;
 	mem->type = MEM_TYPE_DOUBLE;
-	mem->field_type = FIELD_TYPE_DOUBLE;
 	return CMP_OLD_NEW(i, d, int64_t);
 }
 
@@ -691,7 +669,6 @@ uint_to_double_precise(struct Mem *mem)
 		return -1;
 	mem->u.r = d;
 	mem->type = MEM_TYPE_DOUBLE;
-	mem->field_type = FIELD_TYPE_DOUBLE;
 	return 0;
 }
 
@@ -708,7 +685,6 @@ uint_to_double_forced(struct Mem *mem)
 	double d = (double)u;
 	mem->u.r = d;
 	mem->type = MEM_TYPE_DOUBLE;
-	mem->field_type = FIELD_TYPE_DOUBLE;
 	return CMP_OLD_NEW(u, d, uint64_t);
 }
 
@@ -732,7 +708,6 @@ str_to_str0(struct Mem *mem)
 		return -1;
 	mem->z[mem->n] = '\0';
 	mem->flags |= MEM_Term;
-	mem->field_type = FIELD_TYPE_STRING;
 	return 0;
 }
 
@@ -742,7 +717,6 @@ str_to_bin(struct Mem *mem)
 	assert(mem->type == MEM_TYPE_STR);
 	mem->type = MEM_TYPE_BIN;
 	mem->flags &= ~MEM_Term;
-	mem->field_type = FIELD_TYPE_VARBINARY;
 	return 0;
 }
 
@@ -791,7 +765,6 @@ bin_to_str(struct Mem *mem)
 	if (ExpandBlob(mem) != 0)
 		return -1;
 	mem->type = MEM_TYPE_STR;
-	mem->field_type = FIELD_TYPE_STRING;
 	return 0;
 }
 
@@ -806,7 +779,6 @@ bin_to_str0(struct Mem *mem)
 	mem->z[mem->n] = '\0';
 	mem->type = MEM_TYPE_STR;
 	mem->flags = MEM_Term;
-	mem->field_type = FIELD_TYPE_STRING;
 	return 0;
 }
 
@@ -869,14 +841,12 @@ double_to_int(struct Mem *mem)
 		mem->u.i = (int64_t)d;
 		mem->type = MEM_TYPE_INT;
 		assert(mem->flags == 0);
-		mem->field_type = FIELD_TYPE_INTEGER;
 		return 0;
 	}
 	if (d > -1.0 && d < (double)UINT64_MAX) {
 		mem->u.u = (uint64_t)d;
 		mem->type = MEM_TYPE_UINT;
 		assert(mem->flags == 0);
-		mem->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	return -1;
@@ -891,14 +861,12 @@ double_to_int_precise(struct Mem *mem)
 		mem->u.i = (int64_t)d;
 		mem->type = MEM_TYPE_INT;
 		assert(mem->flags == 0);
-		mem->field_type = FIELD_TYPE_INTEGER;
 		return 0;
 	}
 	if (d > -1.0 && d < (double)UINT64_MAX && (double)(uint64_t)d == d) {
 		mem->u.u = (uint64_t)d;
 		mem->type = MEM_TYPE_UINT;
 		assert(mem->flags == 0);
-		mem->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	return -1;
@@ -937,7 +905,6 @@ double_to_int_forced(struct Mem *mem)
 	}
 	mem->u.i = i;
 	mem->type = type;
-	mem->field_type = FIELD_TYPE_INTEGER;
 	return res;
 }
 
@@ -950,7 +917,6 @@ double_to_uint(struct Mem *mem)
 		mem->u.u = (uint64_t)d;
 		mem->type = MEM_TYPE_UINT;
 		assert(mem->flags == 0);
-		mem->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	return -1;
@@ -965,7 +931,6 @@ double_to_uint_precise(struct Mem *mem)
 		mem->u.u = (uint64_t)d;
 		mem->type = MEM_TYPE_UINT;
 		assert(mem->flags == 0);
-		mem->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	return -1;
@@ -995,7 +960,6 @@ double_to_uint_forced(struct Mem *mem)
 	}
 	mem->u.u = u;
 	mem->type = MEM_TYPE_UINT;
-	mem->field_type = FIELD_TYPE_UNSIGNED;
 	return res;
 }
 
@@ -1009,7 +973,6 @@ double_to_str0(struct Mem *mem)
 	mem->n = strlen(mem->z);
 	mem->type = MEM_TYPE_STR;
 	mem->flags = MEM_Term;
-	mem->field_type = FIELD_TYPE_STRING;
 	return 0;
 }
 
@@ -1165,10 +1128,8 @@ mem_to_str(struct Mem *mem)
 int
 mem_cast_explicit(struct Mem *mem, enum field_type type)
 {
-	if (mem->type == MEM_TYPE_NULL) {
-		mem->field_type = type;
+	if (mem->type == MEM_TYPE_NULL)
 		return 0;
-	}
 	switch (type) {
 	case FIELD_TYPE_UNSIGNED:
 		switch (mem->type) {
@@ -1227,10 +1188,8 @@ mem_cast_explicit(struct Mem *mem, enum field_type type)
 int
 mem_cast_implicit(struct Mem *mem, enum field_type type)
 {
-	if (mem->type == MEM_TYPE_NULL) {
-		mem->field_type = type;
+	if (mem->type == MEM_TYPE_NULL)
 		return 0;
-	}
 	switch (type) {
 	case FIELD_TYPE_UNSIGNED:
 		if (mem->type == MEM_TYPE_UINT)
@@ -1301,12 +1260,10 @@ mem_cast_implicit_number(struct Mem *mem, enum field_type type)
 	case FIELD_TYPE_UNSIGNED:
 		switch (mem->type) {
 		case MEM_TYPE_UINT:
-			mem->field_type = FIELD_TYPE_UNSIGNED;
 			return 0;
 		case MEM_TYPE_INT:
 			mem->u.u = 0;
 			mem->type = MEM_TYPE_UINT;
-			mem->field_type = FIELD_TYPE_UNSIGNED;
 			return -1;
 		case MEM_TYPE_DOUBLE:
 			return double_to_uint_forced(mem);
@@ -1330,7 +1287,6 @@ mem_cast_implicit_number(struct Mem *mem, enum field_type type)
 		switch (mem->type) {
 		case MEM_TYPE_UINT:
 		case MEM_TYPE_INT:
-			mem->field_type = FIELD_TYPE_INTEGER;
 			return 0;
 		case MEM_TYPE_DOUBLE:
 			return double_to_int_forced(mem);
@@ -1487,7 +1443,6 @@ mem_copy(struct Mem *to, const struct Mem *from)
 	to->u = from->u;
 	to->type = from->type;
 	to->flags = from->flags;
-	to->field_type = from->field_type;
 	to->n = from->n;
 	to->z = from->z;
 	if (!mem_is_bytes(to))
@@ -1514,7 +1469,6 @@ mem_copy_as_ephemeral(struct Mem *to, const struct Mem *from)
 	to->u = from->u;
 	to->type = from->type;
 	to->flags = from->flags;
-	to->field_type = from->field_type;
 	to->n = from->n;
 	to->z = from->z;
 	if (!mem_is_bytes(to))
@@ -1537,30 +1491,13 @@ mem_move(struct Mem *to, struct Mem *from)
 	from->zMalloc = NULL;
 }
 
-static bool
-try_return_null(const struct Mem *a, const struct Mem *b, struct Mem *result,
-		enum field_type type)
-{
-	mem_clear(result);
-	result->field_type = type;
-	return ((a->type | b->type) & MEM_TYPE_NULL) != 0;
-}
-
 int
 mem_concat(struct Mem *a, struct Mem *b, struct Mem *result)
 {
-	assert(result != b);
-	if (a != result) {
-		if (try_return_null(a, b, result, FIELD_TYPE_STRING))
-			return 0;
-	} else {
-		if (((a->type | b->type) & MEM_TYPE_NULL) != 0) {
-			mem_clear(a);
-			result->field_type = FIELD_TYPE_STRING;
-			return 0;
-		}
+	if (mem_is_any_null(a, b)) {
+		mem_set_null(result);
+		return 0;
 	}
-
 	/* Concatenation operation can be applied only to strings and blobs. */
 	if (((b->type & (MEM_TYPE_STR | MEM_TYPE_BIN)) == 0)) {
 		diag_set(ClientError, ER_INCONSISTENT_TYPES,
@@ -1593,8 +1530,6 @@ mem_concat(struct Mem *a, struct Mem *b, struct Mem *result)
 
 	result->type = a->type;
 	result->flags = 0;
-	if (result->type == MEM_TYPE_BIN)
-		result->field_type = FIELD_TYPE_VARBINARY;
 	if (result != a)
 		memcpy(result->z, a->z, a->n);
 	memcpy(&result->z[a->n], b->z, b->n);
@@ -1607,7 +1542,6 @@ mem_add(const struct Mem *left, const struct Mem *right, struct Mem *result)
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_NUMBER;
 		return 0;
 	}
 	if (!mem_is_num(right)) {
@@ -1644,7 +1578,6 @@ mem_sub(const struct Mem *left, const struct Mem *right, struct Mem *result)
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_NUMBER;
 		return 0;
 	}
 	if (!mem_is_num(right)) {
@@ -1681,7 +1614,6 @@ mem_mul(const struct Mem *left, const struct Mem *right, struct Mem *result)
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_NUMBER;
 		return 0;
 	}
 	if (!mem_is_num(right)) {
@@ -1718,7 +1650,6 @@ mem_div(const struct Mem *left, const struct Mem *right, struct Mem *result)
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_NUMBER;
 		return 0;
 	}
 	if (!mem_is_num(right)) {
@@ -1764,7 +1695,6 @@ mem_rem(const struct Mem *left, const struct Mem *right, struct Mem *result)
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_INTEGER;
 		return 0;
 	}
 	if (!mem_is_int(right)) {
@@ -1797,7 +1727,6 @@ mem_bit_and(const struct Mem *left, const struct Mem *right, struct Mem *result)
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	if (right->type != MEM_TYPE_UINT) {
@@ -1819,7 +1748,6 @@ mem_bit_or(const struct Mem *left, const struct Mem *right, struct Mem *result)
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	if (right->type != MEM_TYPE_UINT) {
@@ -1842,7 +1770,6 @@ mem_shift_left(const struct Mem *left, const struct Mem *right,
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	if (right->type != MEM_TYPE_UINT) {
@@ -1865,7 +1792,6 @@ mem_shift_right(const struct Mem *left, const struct Mem *right,
 {
 	if (mem_is_any_null(left, right)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	if (right->type != MEM_TYPE_UINT) {
@@ -1887,7 +1813,6 @@ mem_bit_not(const struct Mem *mem, struct Mem *result)
 {
 	if (mem_is_null(mem)) {
 		mem_set_null(result);
-		result->field_type = FIELD_TYPE_UNSIGNED;
 		return 0;
 	}
 	if (mem->type != MEM_TYPE_UINT) {
@@ -2557,7 +2482,6 @@ sql_vdbemem_finalize(struct Mem *mem, struct func *func)
 	t.type = MEM_TYPE_NULL;
 	assert(t.flags == 0);
 	t.db = mem->db;
-	t.field_type = field_type_MAX;
 	ctx.pOut = &t;
 	ctx.pMem = mem;
 	ctx.func = func;
@@ -2604,7 +2528,6 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len)
 		mem->n = buf - mem->z;
 		mem->type = MEM_TYPE_ARRAY;
 		mem->flags = MEM_Ephem;
-		mem->field_type = FIELD_TYPE_ARRAY;
 		break;
 	}
 	case MP_MAP: {
@@ -2613,7 +2536,6 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len)
 		mem->n = buf - mem->z;
 		mem->type = MEM_TYPE_MAP;
 		mem->flags = MEM_Ephem;
-		mem->field_type = FIELD_TYPE_MAP;
 		break;
 	}
 	case MP_EXT: {
@@ -2630,7 +2552,6 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len)
 			}
 			mem->type = MEM_TYPE_UUID;
 			mem->flags = 0;
-			mem->field_type = FIELD_TYPE_UUID;
 			break;
 		}
 		buf += size;
@@ -2638,21 +2559,18 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len)
 		mem->n = buf - svp;
 		mem->type = MEM_TYPE_BIN;
 		mem->flags = MEM_Ephem;
-		mem->field_type = FIELD_TYPE_VARBINARY;
 		break;
 	}
 	case MP_NIL: {
 		mp_decode_nil(&buf);
 		mem->type = MEM_TYPE_NULL;
 		mem->flags = 0;
-		mem->field_type = field_type_MAX;
 		break;
 	}
 	case MP_BOOL: {
 		mem->u.b = mp_decode_bool(&buf);
 		mem->type = MEM_TYPE_BOOL;
 		mem->flags = 0;
-		mem->field_type = FIELD_TYPE_BOOLEAN;
 		break;
 	}
 	case MP_UINT: {
@@ -2660,14 +2578,12 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len)
 		mem->u.u = v;
 		mem->type = MEM_TYPE_UINT;
 		mem->flags = 0;
-		mem->field_type = FIELD_TYPE_INTEGER;
 		break;
 	}
 	case MP_INT: {
 		mem->u.i = mp_decode_int(&buf);
 		mem->type = MEM_TYPE_INT;
 		mem->flags = 0;
-		mem->field_type = FIELD_TYPE_INTEGER;
 		break;
 	}
 	case MP_STR: {
@@ -2675,7 +2591,6 @@ mem_from_mp_ephemeral(struct Mem *mem, const char *buf, uint32_t *len)
 		mem->n = (int) mp_decode_strl(&buf);
 		mem->type = MEM_TYPE_STR;
 		mem->flags = MEM_Ephem;
-		mem->field_type = FIELD_TYPE_STRING;
 install_blob:
 		mem->z = (char *)buf;
 		buf += mem->n;
@@ -2686,7 +2601,6 @@ install_blob:
 		mem->n = (int) mp_decode_binl(&buf);
 		mem->type = MEM_TYPE_BIN;
 		mem->flags = MEM_Ephem;
-		mem->field_type = FIELD_TYPE_VARBINARY;
 		goto install_blob;
 	}
 	case MP_FLOAT: {
@@ -2694,11 +2608,9 @@ install_blob:
 		if (sqlIsNaN(mem->u.r)) {
 			mem->type = MEM_TYPE_NULL;
 			mem->flags = 0;
-			mem->field_type = FIELD_TYPE_DOUBLE;
 		} else {
 			mem->type = MEM_TYPE_DOUBLE;
 			mem->flags = 0;
-			mem->field_type = FIELD_TYPE_DOUBLE;
 		}
 		break;
 	}
@@ -2707,11 +2619,9 @@ install_blob:
 		if (sqlIsNaN(mem->u.r)) {
 			mem->type = MEM_TYPE_NULL;
 			mem->flags = 0;
-			mem->field_type = FIELD_TYPE_DOUBLE;
 		} else {
 			mem->type = MEM_TYPE_DOUBLE;
 			mem->flags = 0;
-			mem->field_type = FIELD_TYPE_DOUBLE;
 		}
 		break;
 	}
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index 9681fc736..958907aaf 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -79,13 +79,6 @@ struct Mem {
 	/** Type of the value this MEM contains. */
 	enum mem_type type;
 	u32 flags;		/* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
-	/**
-	 * If value is fetched from tuple, then this property
-	 * contains type of corresponding space's field. If it's
-	 * value field_type_MAX then we can rely on on format
-	 * (msgpack) type which is represented by 'flags'.
-	 */
-	enum field_type field_type;
 	int n;			/* size (in bytes) of string value, excluding trailing '\0' */
 	char *z;		/* String or BLOB value */
 	/* ShallowCopy only needs to copy the information above */
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index 14caa6f82..db5f96b62 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -277,7 +277,6 @@ vdbe_prepare_null_out(struct Vdbe *v, int n)
 	struct Mem *out = &v->aMem[n];
 	memAboutToChange(v, out);
 	mem_set_null(out);
-	out->field_type = field_type_MAX;
 	return out;
 }
 
@@ -1354,7 +1353,7 @@ case OP_BitAnd: {               /* same as TK_BITAND, in1, in2, out3 */
 	pOut = &aMem[pOp->p3];
 	if (mem_bit_and(pIn2, pIn1, pOut) != 0)
 		goto abort_due_to_error;
-	assert(pOut->field_type == FIELD_TYPE_UNSIGNED);
+	assert(pOut->type == MEM_TYPE_UINT || pOut->type == MEM_TYPE_NULL);
 	break;
 }
 
@@ -1371,7 +1370,7 @@ case OP_BitOr: {                /* same as TK_BITOR, in1, in2, out3 */
 	pOut = &aMem[pOp->p3];
 	if (mem_bit_or(pIn2, pIn1, pOut) != 0)
 		goto abort_due_to_error;
-	assert(pOut->field_type == FIELD_TYPE_UNSIGNED);
+	assert(pOut->type == MEM_TYPE_UINT || pOut->type == MEM_TYPE_NULL);
 	break;
 }
 
@@ -1389,7 +1388,7 @@ case OP_ShiftLeft: {            /* same as TK_LSHIFT, in1, in2, out3 */
 	pOut = &aMem[pOp->p3];
 	if (mem_shift_left(pIn2, pIn1, pOut) != 0)
 		goto abort_due_to_error;
-	assert(pOut->field_type == FIELD_TYPE_UNSIGNED);
+	assert(pOut->type == MEM_TYPE_UINT || pOut->type == MEM_TYPE_NULL);
 	break;
 }
 
@@ -1407,7 +1406,7 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
 	pOut = &aMem[pOp->p3];
 	if (mem_shift_right(pIn2, pIn1, pOut) != 0)
 		goto abort_due_to_error;
-	assert(pOut->field_type == FIELD_TYPE_UNSIGNED);
+	assert(pOut->type == MEM_TYPE_UINT || pOut->type == MEM_TYPE_NULL);
 	break;
 }
 
@@ -1465,13 +1464,6 @@ case OP_Cast: {                  /* in1 */
 	if (ExpandBlob(pIn1) != 0)
 		goto abort_due_to_error;
 	rc = mem_cast_explicit(pIn1, pOp->p2);
-	/*
-	 * SCALAR is not type itself, but rather an aggregation
-	 * of types. Hence, cast to this type shouldn't change
-	 * original type of argument.
-	 */
-	if (pOp->p2 != FIELD_TYPE_SCALAR)
-		pIn1->field_type = pOp->p2;
 	UPDATE_MAX_BLOBSIZE(pIn1);
 	if (rc == 0)
 		break;
@@ -1809,7 +1801,6 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 case OP_Not: {                /* same as TK_NOT, in1, out2 */
 	pIn1 = &aMem[pOp->p1];
 	pOut = vdbe_prepare_null_out(p, pOp->p2);
-	pOut->field_type = FIELD_TYPE_BOOLEAN;
 	if (!mem_is_null(pIn1)) {
 		if (!mem_is_bool(pIn1)) {
 			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
@@ -1979,11 +1970,8 @@ case OP_Column: {
 		}
 		pC->cacheStatus = p->cacheCtr;
 	}
-	enum field_type field_type = field_type_MAX;
-	if (pC->eCurType == CURTYPE_TARANTOOL)
-		field_type = pC->uc.pCursor->space->def->fields[p2].type;
-	else if (pC->eCurType == CURTYPE_SORTER)
-		field_type = vdbe_sorter_get_field_type(pC->uc.pSorter, p2);
+	assert(pC->eCurType == CURTYPE_TARANTOOL ||
+	       pC->eCurType == CURTYPE_PSEUDO);
 	struct Mem *default_val_mem =
 		pOp->p4type == P4_MEM ? pOp->p4.pMem : NULL;
 	if (vdbe_field_ref_fetch(&pC->field_ref, p2, pDest) != 0)
@@ -1994,7 +1982,6 @@ case OP_Column: {
 	    default_val_mem != NULL) {
 		mem_copy_as_ephemeral(pDest, default_val_mem);
 	}
-	pDest->field_type = field_type;
 op_column_out:
 	REGISTER_TRACE(p, pOp->p3, pDest);
 	break;
diff --git a/src/box/sql/vdbeInt.h b/src/box/sql/vdbeInt.h
index b4ad8b774..cfe743b94 100644
--- a/src/box/sql/vdbeInt.h
+++ b/src/box/sql/vdbeInt.h
@@ -341,9 +341,6 @@ int sqlVdbeFrameRestore(VdbeFrame *);
 int sqlVdbeSorterInit(struct sql *db, struct VdbeCursor *cursor);
 void sqlVdbeSorterReset(sql *, VdbeSorter *);
 
-enum field_type
-vdbe_sorter_get_field_type(struct VdbeSorter *sorter, uint32_t field_no);
-
 void sqlVdbeSorterClose(sql *, VdbeCursor *);
 int sqlVdbeSorterRowkey(const VdbeCursor *, Mem *);
 int sqlVdbeSorterNext(sql *, const VdbeCursor *, int *);
diff --git a/src/box/sql/vdbesort.c b/src/box/sql/vdbesort.c
index 3da425be4..aadafeabd 100644
--- a/src/box/sql/vdbesort.c
+++ b/src/box/sql/vdbesort.c
@@ -969,12 +969,6 @@ sqlVdbeSorterReset(sql * db, VdbeSorter * pSorter)
 	pSorter->pUnpacked = 0;
 }
 
-enum field_type
-vdbe_sorter_get_field_type(struct VdbeSorter *sorter, uint32_t field_no)
-{
-	return sorter->key_def->parts[field_no].type;
-}
-
 /*
  * Free any cursor components allocated by sqlVdbeSorterXXX routines.
  */
diff --git a/test/sql-tap/cast.test.lua b/test/sql-tap/cast.test.lua
index 927114772..4f2bff93e 100755
--- a/test/sql-tap/cast.test.lua
+++ b/test/sql-tap/cast.test.lua
@@ -120,7 +120,7 @@ test:do_execsql_test(
         SELECT typeof(NULL)
     ]], {
         -- <cast-1.12>
-        "boolean"
+        "NULL"
         -- </cast-1.12>
     })
 
@@ -140,7 +140,7 @@ test:do_execsql_test(
         SELECT typeof(CAST(NULL AS text))
     ]], {
         -- <cast-1.14>
-        "string"
+        "NULL"
         -- </cast-1.14>
     })
 
@@ -160,7 +160,7 @@ test:do_execsql_test(
         SELECT typeof(CAST(NULL AS NUMBER))
     ]], {
         -- <cast-1.16>
-        "number"
+        "NULL"
         -- </cast-1.16>
     })
 
@@ -180,7 +180,7 @@ test:do_execsql_test(
         SELECT typeof(CAST(NULL AS SCALAR))
     ]], {
         -- <cast-1.18>
-        "boolean"
+        "NULL"
         -- </cast-1.18>
     })
 
@@ -200,7 +200,7 @@ test:do_execsql_test(
         SELECT typeof(CAST(NULL AS integer))
     ]], {
         -- <cast-1.20>
-        "integer"
+        "NULL"
         -- </cast-1.20>
     })
 
@@ -511,7 +511,7 @@ test:do_execsql_test(
         SELECT typeof(CAST(null AS NUMBER))
     ]], {
         -- <case-1.61>
-        "number"
+        "NULL"
         -- </case-1.61>
     })
 
@@ -531,7 +531,7 @@ test:do_execsql_test(
         SELECT typeof(CAST(1 AS NUMBER))
     ]], {
         -- <case-1.63>
-        "number"
+        "integer"
         -- </case-1.63>
     })
 
@@ -551,7 +551,7 @@ test:do_execsql_test(
         SELECT typeof(CAST('1' AS NUMBER))
     ]], {
         -- <case-1.65>
-        "number"
+        "integer"
         -- </case-1.65>
     })
 
diff --git a/test/sql-tap/default.test.lua b/test/sql-tap/default.test.lua
index 9c15220eb..59dc2a2a1 100755
--- a/test/sql-tap/default.test.lua
+++ b/test/sql-tap/default.test.lua
@@ -115,7 +115,7 @@ test:do_execsql_test(
 	g, typeof(g) FROM t3;
 	]], {
 	-- <default-3.1>
-	1, "integer", 5, "integer", "row1", "string", 5.25, "number", 8.67, "number", "321", "string", 432, "integer"
+	1, "integer", 5, "integer", "row1", "string", 5.25, "double", 8.67, "double", "321", "string", 432, "integer"
 	-- </default-3.1>
 })
 
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index df55ff9cf..4cc722d1e 100755
--- a/test/sql-tap/func.test.lua
+++ b/test/sql-tap/func.test.lua
@@ -1814,7 +1814,7 @@ test:do_execsql_test(
         SELECT typeof(replace('This is the main test string', NULL, 'ALT'));
     ]], {
         -- <func-21.3>
-        "boolean"
+        "NULL"
         -- </func-21.3>
     })
 
@@ -1824,7 +1824,7 @@ test:do_execsql_test(
         SELECT typeof(replace(NULL, 'main', 'ALT'));
     ]], {
         -- <func-21.4>
-        "boolean"
+        "NULL"
         -- </func-21.4>
     })
 
@@ -1834,7 +1834,7 @@ test:do_execsql_test(
         SELECT typeof(replace('This is the main test string', 'main', NULL));
     ]], {
         -- <func-21.5>
-        "boolean"
+        "NULL"
         -- </func-21.5>
     })
 
@@ -2055,7 +2055,7 @@ test:do_execsql_test(
         SELECT typeof(trim(NULL));
     ]], {
         -- <func-22.20>
-        "boolean"
+        "NULL"
         -- </func-22.20>
     })
 
@@ -2065,7 +2065,7 @@ test:do_execsql_test(
         SELECT typeof(TRIM('xyz' FROM NULL));
     ]], {
         -- <func-22.21>
-        "boolean"
+        "NULL"
         -- </func-22.21>
     })
 
@@ -2075,7 +2075,7 @@ test:do_execsql_test(
         SELECT typeof(TRIM(NULL FROM 'hello'));
     ]], {
         -- <func-22.22>
-        "boolean"
+        "NULL"
         -- </func-22.22>
     })
 
diff --git a/test/sql-tap/func5.test.lua b/test/sql-tap/func5.test.lua
index f07fc5fd9..44755b1f7 100755
--- a/test/sql-tap/func5.test.lua
+++ b/test/sql-tap/func5.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 local test = require("sqltester")
-test:plan(29)
+test:plan(38)
 
 --!./tcltestrunner.lua
 -- 2010 August 27
@@ -371,4 +371,77 @@ test:do_execsql_test(
         111
     })
 
+-- gh-5956: typeof(NULL) now returns 'NULL'.
+test:do_execsql_test(
+    "func-8.1",
+    [[
+        SELECT typeof(CAST(NULL AS UUID));
+    ]], {
+        'NULL'
+    })
+
+test:do_execsql_test(
+    "func-8.2",
+    [[
+        SELECT typeof(CAST(NULL AS SCALAR));
+    ]], {
+        'NULL'
+    })
+
+test:do_execsql_test(
+    "func-8.3",
+    [[
+        SELECT typeof(CAST(NULL AS BOOLEAN));
+    ]], {
+        'NULL'
+    })
+
+test:do_execsql_test(
+    "func-8.4",
+    [[
+        SELECT typeof(CAST(NULL AS INTEGER));
+    ]], {
+        'NULL'
+    })
+
+test:do_execsql_test(
+    "func-8.5",
+    [[
+        SELECT typeof(CAST(NULL AS UNSIGNED));
+    ]], {
+        'NULL'
+    })
+
+test:do_execsql_test(
+    "func-8.6",
+    [[
+        SELECT typeof(CAST(NULL AS DOUBLE));
+    ]], {
+        'NULL'
+    })
+
+test:do_execsql_test(
+    "func-8.7",
+    [[
+        SELECT typeof(CAST(NULL AS NUMBER));
+    ]], {
+        'NULL'
+    })
+
+test:do_execsql_test(
+    "func-8.8",
+    [[
+        SELECT typeof(CAST(NULL AS STRING));
+    ]], {
+        'NULL'
+    })
+
+test:do_execsql_test(
+    "func-8.9",
+    [[
+        SELECT typeof(CAST(NULL AS VARBINARY));
+    ]], {
+        'NULL'
+    })
+
 test:finish_test()
diff --git a/test/sql-tap/select7.test.lua b/test/sql-tap/select7.test.lua
index 815f9110b..47e7240ed 100755
--- a/test/sql-tap/select7.test.lua
+++ b/test/sql-tap/select7.test.lua
@@ -235,7 +235,7 @@ test:do_execsql_test(
         SELECT a=0, typeof(a) FROM t4
     ]], {
         -- <select7-7.5>
-        false, "number", false, "number"
+        false, "double", false, "double"
         -- </select7-7.5>
     })
 
@@ -245,7 +245,7 @@ test:do_execsql_test(
         SELECT a=0, typeof(a) FROM t4 GROUP BY a
     ]], {
         -- <select7-7.6>
-        false, "number", false, "number"
+        false, "double", false, "double"
         -- </select7-7.6>
     })
 
diff --git a/test/sql-tap/table.test.lua b/test/sql-tap/table.test.lua
index ecd9adcd8..4592909ff 100755
--- a/test/sql-tap/table.test.lua
+++ b/test/sql-tap/table.test.lua
@@ -906,7 +906,7 @@ test:do_execsql_test(
         FROM t7 LIMIT 1;
     ]], {
         -- <table-11.1>
-        "integer", "number", "string", "string", "boolean", "boolean", "string", "string"
+        "integer", "NULL", "NULL", "NULL", "NULL", "NULL", "NULL", "NULL"
         -- </table-11.1>
     })
 
@@ -917,7 +917,7 @@ test:do_execsql_test(
         FROM t7 LIMIT 1;
     ]], {
         -- <table-11.2>
-        "number", "string", "number", "string"
+        "NULL", "NULL", "NULL", "NULL"
         -- </table-11.2>
     })
 
diff --git a/test/sql-tap/tkt-3998683a16.test.lua b/test/sql-tap/tkt-3998683a16.test.lua
index 44ce7087a..81c7806ad 100755
--- a/test/sql-tap/tkt-3998683a16.test.lua
+++ b/test/sql-tap/tkt-3998683a16.test.lua
@@ -36,7 +36,6 @@ test:do_test(
         ]]
     end, {
         -- <tkt-3998683a16.1>
-        1, 2, 3, 4, 5, 6
         -- </tkt-3998683a16.1>
     })
 
diff --git a/test/sql/boolean.result b/test/sql/boolean.result
index 6e7ad179f..d027a56e3 100644
--- a/test/sql/boolean.result
+++ b/test/sql/boolean.result
@@ -331,8 +331,8 @@ SELECT typeof(a) FROM t0;
  |   rows:
  |   - ['boolean']
  |   - ['boolean']
- |   - ['boolean']
- |   - ['boolean']
+ |   - ['NULL']
+ |   - ['NULL']
  | ...
 
 -- Check BOOLEAN as argument of aggregate function.
diff --git a/test/sql/gh-4697-scalar-bool-sort-cmp.result b/test/sql/gh-4697-scalar-bool-sort-cmp.result
index 6f7fbd62b..e69c625bd 100644
--- a/test/sql/gh-4697-scalar-bool-sort-cmp.result
+++ b/test/sql/gh-4697-scalar-bool-sort-cmp.result
@@ -33,7 +33,7 @@ SELECT s2, typeof(s2) FROM test ORDER BY s2;
  |   - name: COLUMN_1
  |     type: string
  |   rows:
- |   - [null, 'boolean']
+ |   - [null, 'NULL']
  |   - [true, 'boolean']
  |   - [1, 'integer']
  |   - [1.1, 'double']
@@ -46,7 +46,7 @@ SELECT s3, typeof(s3) FROM test ORDER BY s3;
  |   - name: COLUMN_1
  |     type: string
  |   rows:
- |   - [null, 'boolean']
+ |   - [null, 'NULL']
  |   - [true, 'boolean']
  |   - [1, 'integer']
  |   - [1.1, 'double']
diff --git a/test/sql/types.result b/test/sql/types.result
index 07d5b46e4..e8ebdae84 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -1481,7 +1481,7 @@ box.execute("SELECT typeof(a), typeof(s) FROM t;")
     type: string
   rows:
   - ['integer', 'integer']
-  - ['integer', 'boolean']
+  - ['NULL', 'NULL']
 ...
 box.execute('CREATE TABLE t1 (id INTEGER PRIMARY KEY, a INTEGER, b INTEGER)')
 ---
@@ -1497,7 +1497,7 @@ box.execute('SELECT typeof(a & b) FROM t1;')
   - name: COLUMN_1
     type: string
   rows:
-  - ['unsigned']
+  - ['NULL']
 ...
 box.execute('SELECT typeof(a), typeof(b), typeof(a & b) FROM t1')
 ---
@@ -1509,7 +1509,7 @@ box.execute('SELECT typeof(a), typeof(b), typeof(a & b) FROM t1')
   - name: COLUMN_3
     type: string
   rows:
-  - ['integer', 'integer', 'unsigned']
+  - ['NULL', 'NULL', 'NULL']
 ...
 box.execute("SELECT typeof(CAST(0 AS UNSIGNED));")
 ---
@@ -1517,7 +1517,7 @@ box.execute("SELECT typeof(CAST(0 AS UNSIGNED));")
   - name: COLUMN_1
     type: string
   rows:
-  - ['unsigned']
+  - ['integer']
 ...
 box.space.T:drop()
 ---
-- 
2.25.1



More information about the Tarantool-patches mailing list