Tarantool development patches archive
 help / color / mirror / Atom feed
From: Mergen Imeev via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: v.shpilevoy@tarantool.org
Cc: tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH v1 1/7] sql: remove enum field_type from struct Mem
Date: Wed, 11 Aug 2021 19:01:40 +0300	[thread overview]
Message-ID: <53edb7f037875e1bb0ce509518524f3a6b862440.1628697448.git.imeevma@gmail.com> (raw)
In-Reply-To: <cover.1628697448.git.imeevma@gmail.com>

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


  reply	other threads:[~2021-08-11 16:02 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-11 16:01 [Tarantool-patches] [PATCH v1 0/7] Rework SCALAR and NUMBER types in SQL Mergen Imeev via Tarantool-patches
2021-08-11 16:01 ` Mergen Imeev via Tarantool-patches [this message]
2021-08-11 16:01 ` [Tarantool-patches] [PATCH v1 2/7] sql: re-introduce NUMBER and SCALAR meta-types Mergen Imeev via Tarantool-patches
2021-08-12 18:51   ` Vladislav Shpilevoy via Tarantool-patches
2021-08-12 22:22     ` Mergen Imeev via Tarantool-patches
2021-08-11 16:01 ` [Tarantool-patches] [PATCH v1 3/7] sql: disallow implicit cast from NUMBER and SCALAR Mergen Imeev via Tarantool-patches
2021-08-11 16:01 ` [Tarantool-patches] [PATCH v1 4/7] sql: disallow arithmetic for " Mergen Imeev via Tarantool-patches
2021-08-11 16:01 ` [Tarantool-patches] [PATCH v1 5/7] sql: disallow bitwise " Mergen Imeev via Tarantool-patches
2021-08-11 16:01 ` [Tarantool-patches] [PATCH v1 6/7] sql: disallow concatination for SCALAR Mergen Imeev via Tarantool-patches
2021-08-11 16:01 ` [Tarantool-patches] [PATCH v1 7/7] sql: fix comparison with SCALAR value Mergen Imeev via Tarantool-patches
2021-08-12 18:50   ` Vladislav Shpilevoy via Tarantool-patches
2021-08-12 22:23     ` Mergen Imeev via Tarantool-patches
2021-08-13  3:12 [Tarantool-patches] [PATCH v1 0/7] Rework SCALAR and NUMBER types in SQL Mergen Imeev via Tarantool-patches
2021-08-13  3:12 ` [Tarantool-patches] [PATCH v1 1/7] sql: remove enum field_type from struct Mem Mergen Imeev via Tarantool-patches

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53edb7f037875e1bb0ce509518524f3a6b862440.1628697448.git.imeevma@gmail.com \
    --to=tarantool-patches@dev.tarantool.org \
    --cc=imeevma@tarantool.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='Re: [Tarantool-patches] [PATCH v1 1/7] sql: remove enum field_type from struct Mem' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox