[Tarantool-patches] [PATCH v1 1/1] sql: check arguments types of built-in functions

imeevma at tarantool.org imeevma at tarantool.org
Thu Oct 8 12:03:55 MSK 2020


After this patch, the argument types of the SQL built-in functions will
be checked. Implicit casting rules will be applied during this check.

Closes #4159
---
https://github.com/tarantool/tarantool/issues/4159
https://github.com/tarantool/tarantool/tree/imeevma/gh-4159-refactor-sql-builtins

@ChangeLog
 - Argument types of built-in functions now properly checked (gh-4159).

 src/box/sql/func.c              |  283 ++--
 test/sql-tap/aggnested.test.lua |    8 +-
 test/sql-tap/cse.test.lua       |    4 +-
 test/sql-tap/e_select1.test.lua |   12 +-
 test/sql-tap/func.test.lua      |   28 +-
 test/sql-tap/orderby1.test.lua  |    2 +-
 test/sql-tap/position.test.lua  |   16 +-
 test/sql-tap/tkt2942.test.lua   |    8 +-
 test/sql-tap/view.test.lua      |    2 +-
 test/sql-tap/with1.test.lua     |    2 +-
 test/sql/boolean.result         |   39 +-
 test/sql/prepared.result        |    2 +-
 test/sql/prepared.test.lua      |    2 +-
 test/sql/types.result           | 2478 ++++++++++++++++++++++++++++++-
 test/sql/types.test.lua         |  391 +++++
 15 files changed, 3053 insertions(+), 224 deletions(-)

diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 0aedb2d3d..d348c3d09 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -467,30 +467,21 @@ lengthFunc(sql_context * context, int argc, sql_value ** argv)
 
 	assert(argc == 1);
 	UNUSED_PARAMETER(argc);
-	switch (sql_value_type(argv[0])) {
-	case MP_BIN:
-	case MP_ARRAY:
-	case MP_MAP:
-	case MP_INT:
-	case MP_UINT:
-	case MP_BOOL:
-	case MP_DOUBLE:{
-			sql_result_uint(context, sql_value_bytes(argv[0]));
-			break;
-		}
-	case MP_STR:{
-			const unsigned char *z = sql_value_text(argv[0]);
-			if (z == 0)
-				return;
-			len = sql_utf8_char_count(z, sql_value_bytes(argv[0]));
-			sql_result_uint(context, len);
-			break;
-		}
-	default:{
-			sql_result_null(context);
-			break;
-		}
-	}
+	enum mp_type type = mem_mp_type(argv[0]);
+	if (type == MP_NIL)
+		return sql_result_null(context);
+	if (type == MP_STR) {
+		const unsigned char *z = sql_value_text(argv[0]);
+		if (z == NULL)
+			return sql_result_null(context);
+		len = sql_utf8_char_count(z, sql_value_bytes(argv[0]));
+		return sql_result_uint(context, len);
+	}
+	if (type == MP_BIN)
+		return sql_result_uint(context, sql_value_bytes(argv[0]));
+	diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+		 sql_value_to_diag_str(argv[0]), "string or varbinary");
+	context->is_aborted = true;
 }
 
 /*
@@ -504,44 +495,24 @@ absFunc(sql_context * context, int argc, sql_value ** argv)
 {
 	assert(argc == 1);
 	UNUSED_PARAMETER(argc);
-	switch (sql_value_type(argv[0])) {
-	case MP_UINT: {
-		sql_result_uint(context, sql_value_uint64(argv[0]));
-		break;
-	}
-	case MP_INT: {
+	enum mp_type type = mem_mp_type(argv[0]);
+	if (type == MP_NIL)
+		return sql_result_null(context);
+	if (type == MP_UINT)
+		return sql_result_uint(context, sql_value_uint64(argv[0]));
+	if (type == MP_INT) {
 		int64_t value = sql_value_int64(argv[0]);
-		assert(value < 0);
-		sql_result_uint(context, -value);
-		break;
-	}
-	case MP_NIL:{
-			/* IMP: R-37434-19929 Abs(X) returns NULL if X is NULL. */
-			sql_result_null(context);
-			break;
-		}
-	case MP_BOOL:
-	case MP_BIN:
-	case MP_ARRAY:
-	case MP_MAP: {
-		diag_set(ClientError, ER_INCONSISTENT_TYPES, "number",
-			 mem_type_to_str(argv[0]));
-		context->is_aborted = true;
-		return;
+		return sql_result_uint(context, (uint64_t)(-value));
 	}
-	default:{
-			/* Because sql_value_double() returns 0.0 if the argument is not
-			 * something that can be converted into a number, we have:
-			 * IMP: R-01992-00519 Abs(X) returns 0.0 if X is a string or blob
-			 * that cannot be converted to a numeric value.
-			 */
-			double rVal = sql_value_double(argv[0]);
-			if (rVal < 0)
-				rVal = -rVal;
-			sql_result_double(context, rVal);
-			break;
-		}
+	if (type == MP_DOUBLE) {
+		double value = sql_value_double(argv[0]);
+		if (value < 0)
+			value = -value;
+		return sql_result_double(context, value);
 	}
+	diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+		 sql_value_to_diag_str(argv[0]), "number");
+	context->is_aborted = true;
 }
 
 /**
@@ -566,29 +537,23 @@ position_func(struct sql_context *context, int argc, struct Mem **argv)
 
 	if (haystack_type == MP_NIL || needle_type == MP_NIL)
 		return;
-	/*
-	 * Position function can be called only with string
-	 * or blob params.
-	 */
-	struct Mem *inconsistent_type_arg = NULL;
-	if (needle_type != MP_STR && needle_type != MP_BIN)
-		inconsistent_type_arg = needle;
-	if (haystack_type != MP_STR && haystack_type != MP_BIN)
-		inconsistent_type_arg = haystack;
-	if (inconsistent_type_arg != NULL) {
-		diag_set(ClientError, ER_INCONSISTENT_TYPES,
-			 "text or varbinary",
-			 mem_type_to_str(inconsistent_type_arg));
+	if (needle_type != MP_STR && needle_type != MP_BIN) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(needle), "string or varbinary");
+		context->is_aborted = true;
+		return;
+	}
+	if (haystack_type != MP_STR && haystack_type != MP_BIN) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(haystack),
+			 "string or varbinary");
 		context->is_aborted = true;
 		return;
 	}
-	/*
-	 * Both params of Position function must be of the same
-	 * type.
-	 */
 	if (haystack_type != needle_type) {
-		diag_set(ClientError, ER_INCONSISTENT_TYPES,
-			 mem_type_to_str(needle), mem_type_to_str(haystack));
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(haystack),
+			 mem_type_to_str(needle));
 		context->is_aborted = true;
 		return;
 	}
@@ -725,7 +690,7 @@ substrFunc(sql_context * context, int argc, sql_value ** argv)
 	const unsigned char *z;
 	const unsigned char *z2;
 	int len;
-	int p0type;
+	enum mp_type p0type;
 	i64 p1, p2;
 	int negP2 = 0;
 
@@ -735,12 +700,24 @@ substrFunc(sql_context * context, int argc, sql_value ** argv)
 		context->is_aborted = true;
 		return;
 	}
-	if (sql_value_is_null(argv[1])
+	if (sql_value_is_null(argv[0]) || sql_value_is_null(argv[1])
 	    || (argc == 3 && sql_value_is_null(argv[2]))
 	    ) {
 		return;
 	}
 	p0type = sql_value_type(argv[0]);
+	if (p0type != MP_STR && p0type != MP_BIN) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[0]), "string or varbinary");
+		context->is_aborted = true;
+		return;
+	}
+	if (!mp_type_is_numeric(mem_mp_type(argv[1]))) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[1]), "integer");
+		context->is_aborted = true;
+		return;
+	}
 	p1 = sql_value_int(argv[1]);
 	if (p0type == MP_BIN) {
 		len = sql_value_bytes(argv[0]);
@@ -757,6 +734,12 @@ substrFunc(sql_context * context, int argc, sql_value ** argv)
 			len = sql_utf8_char_count(z, sql_value_bytes(argv[0]));
 	}
 	if (argc == 3) {
+		if (!mp_type_is_numeric(mem_mp_type(argv[2]))) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sql_value_to_diag_str(argv[2]), "integer");
+			context->is_aborted = true;
+			return;
+		}
 		p2 = sql_value_int(argv[2]);
 		if (p2 < 0) {
 			p2 = -p2;
@@ -839,6 +822,12 @@ roundFunc(sql_context * context, int argc, sql_value ** argv)
 	if (argc == 2) {
 		if (sql_value_is_null(argv[1]))
 			return;
+		if (!mp_type_is_numeric(mem_mp_type(argv[1]))) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sql_value_to_diag_str(argv[1]), "integer");
+			context->is_aborted = true;
+			return;
+		}
 		n = sql_value_int(argv[1]);
 		if (n < 0)
 			n = 0;
@@ -846,7 +835,7 @@ roundFunc(sql_context * context, int argc, sql_value ** argv)
 	if (sql_value_is_null(argv[0]))
 		return;
 	enum mp_type mp_type = sql_value_type(argv[0]);
-	if (mp_type_is_bloblike(mp_type)) {
+	if (!mp_type_is_numeric(mp_type)) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_to_diag_str(argv[0]), "numeric");
 		context->is_aborted = true;
@@ -907,9 +896,11 @@ case_type##ICUFunc(sql_context *context, int argc, sql_value **argv)   \
 	int n;                                                                 \
 	UNUSED_PARAMETER(argc);                                                \
 	int arg_type = sql_value_type(argv[0]);                                \
-	if (mp_type_is_bloblike(arg_type)) {                                   \
-		diag_set(ClientError, ER_INCONSISTENT_TYPES, "text",           \
-			 "varbinary");                                         \
+	if (arg_type == MP_NIL)                                                \
+		return;                                                        \
+	if (arg_type != MP_STR) {                                              \
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,                    \
+			 sql_value_to_diag_str(argv[0]), "string");            \
 		context->is_aborted = true;                                    \
 		return;                                                        \
 	}                                                                      \
@@ -988,9 +979,9 @@ randomBlob(sql_context * context, int argc, sql_value ** argv)
 	unsigned char *p;
 	assert(argc == 1);
 	UNUSED_PARAMETER(argc);
-	if (mp_type_is_bloblike(sql_value_type(argv[0]))) {
+	if (!mp_type_is_numeric(sql_value_type(argv[0]))) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-			 sql_value_to_diag_str(argv[0]), "numeric");
+			 sql_value_to_diag_str(argv[0]), "integer");
 		context->is_aborted = true;
 		return;
 	}
@@ -1238,14 +1229,17 @@ likeFunc(sql_context *context, int argc, sql_value **argv)
 	int rhs_type = sql_value_type(argv[0]);
 	int lhs_type = sql_value_type(argv[1]);
 
-	if (lhs_type != MP_STR || rhs_type != MP_STR) {
-		if (lhs_type == MP_NIL || rhs_type == MP_NIL)
-			return;
-		char *inconsistent_type = rhs_type != MP_STR ?
-					  mem_type_to_str(argv[0]) :
-					  mem_type_to_str(argv[1]);
-		diag_set(ClientError, ER_INCONSISTENT_TYPES, "text",
-			 inconsistent_type);
+	if (lhs_type == MP_NIL || rhs_type == MP_NIL)
+		return;
+	if (rhs_type != MP_STR) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[0]), "string");
+		context->is_aborted = true;
+		return;
+	}
+	if (lhs_type != MP_STR) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[1]), "string");
 		context->is_aborted = true;
 		return;
 	}
@@ -1452,6 +1446,15 @@ quoteFunc(sql_context * context, int argc, sql_value ** argv)
 static void
 unicodeFunc(sql_context * context, int argc, sql_value ** argv)
 {
+	enum mp_type type = mem_mp_type(argv[0]);
+	if (type == MP_NIL)
+		return;
+	if (type != MP_STR && type != MP_BIN) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[0]), "string or varbinary");
+		context->is_aborted = true;
+		return;
+	}
 	const unsigned char *z = sql_value_text(argv[0]);
 	(void)argc;
 	if (z && z[0])
@@ -1476,10 +1479,16 @@ charFunc(sql_context * context, int argc, sql_value ** argv)
 	for (i = 0; i < argc; i++) {
 		uint64_t x;
 		unsigned c;
-		if (sql_value_type(argv[i]) == MP_INT)
-			x = 0xfffd;
-		else
-			x = sql_value_uint64(argv[i]);
+		if (sql_value_is_null(argv[i]))
+			continue;
+		if (!mp_type_is_numeric(mem_mp_type(argv[i]))) {
+			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+				 sql_value_to_diag_str(argv[i]), "integer");
+			context->is_aborted = true;
+			return;
+		}
+		int y = sql_value_int(argv[i]);
+		x = y < 0 ? 0xfffd : y;
 		if (x > 0x10ffff)
 			x = 0xfffd;
 		c = (unsigned)(x & 0x1fffff);
@@ -1538,6 +1547,12 @@ zeroblobFunc(sql_context * context, int argc, sql_value ** argv)
 	i64 n;
 	assert(argc == 1);
 	UNUSED_PARAMETER(argc);
+	if (!mp_type_is_numeric(sql_value_type(argv[0]))) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[0]), "integer");
+		context->is_aborted = true;
+		return;
+	}
 	n = sql_value_int64(argv[0]);
 	if (n < 0)
 		n = 0;
@@ -1570,6 +1585,43 @@ replaceFunc(sql_context * context, int argc, sql_value ** argv)
 
 	assert(argc == 3);
 	UNUSED_PARAMETER(argc);
+	enum mp_type type0 = mem_mp_type(argv[0]);
+	enum mp_type type1 = mem_mp_type(argv[1]);
+	enum mp_type type2 = mem_mp_type(argv[2]);
+	if (type0 == MP_NIL || type1 == MP_NIL || type2 == MP_NIL)
+		return;
+	if (type0 != MP_STR && type0 != MP_BIN) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[0]), "string or varbinary");
+		context->is_aborted = true;
+		return;
+	}
+	if (type1 != MP_STR && type1 != MP_BIN) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[1]), "string or varbinary");
+		context->is_aborted = true;
+		return;
+	}
+	if (type2 != MP_STR && type2 != MP_BIN) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[2]), "string or varbinary");
+		context->is_aborted = true;
+		return;
+	}
+	if (type1 != type0) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[1]),
+			 mem_type_to_str(argv[0]));
+		context->is_aborted = true;
+		return;
+	}
+	if (type2 != type0) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[2]),
+			 mem_type_to_str(argv[0]));
+		context->is_aborted = true;
+		return;
+	}
 	zStr = sql_value_text(argv[0]);
 	if (zStr == 0)
 		return;
@@ -1880,7 +1932,9 @@ soundexFunc(sql_context * context, int argc, sql_value ** argv)
 	};
 	assert(argc == 1);
 	enum mp_type mp_type = sql_value_type(argv[0]);
-	if (mp_type_is_bloblike(mp_type)) {
+	if (mp_type == MP_NIL)
+		return;
+	if (mp_type != MP_STR) {
 		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
 			 sql_value_to_diag_str(argv[0]), "text");
 		context->is_aborted = true;
@@ -1953,13 +2007,10 @@ sum_step(struct sql_context *context, int argc, sql_value **argv)
 	if (type == MP_NIL || p == NULL)
 		return;
 	if (type != MP_DOUBLE && type != MP_INT && type != MP_UINT) {
-		if (mem_apply_numeric_type(argv[0]) != 0) {
-			diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
-				 sql_value_to_diag_str(argv[0]), "number");
-			context->is_aborted = true;
-			return;
-		}
-		type = sql_value_type(argv[0]);
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[0]), "number");
+		context->is_aborted = true;
+		return;
 	}
 	p->cnt++;
 	if (type == MP_INT || type == MP_UINT) {
@@ -2121,8 +2172,26 @@ groupConcatStep(sql_context * context, int argc, sql_value ** argv)
 		context->is_aborted = true;
 		return;
 	}
-	if (sql_value_is_null(argv[0]))
+	enum mp_type type0 = mem_mp_type(argv[0]);
+	if (type0 == MP_NIL)
+		return;
+	if (type0 != MP_STR && type0 != MP_BIN) {
+		diag_set(ClientError, ER_SQL_TYPE_MISMATCH,
+			 sql_value_to_diag_str(argv[0]), "string or varbinary");
+		context->is_aborted = true;
 		return;
+	}
+	if (argc == 2) {
+		enum mp_type type1 = mem_mp_type(argv[1]);
+		if (type1 != MP_NIL && type1 != type0) {
+			diag_set(ClientError,
+				 ER_SQL_TYPE_MISMATCH,
+				 sql_value_to_diag_str(argv[1]),
+				 mem_type_to_str(argv[0]));
+			context->is_aborted = true;
+			return;
+		}
+	}
 	pAccum =
 	    (StrAccum *) sql_aggregate_context(context, sizeof(*pAccum));
 
diff --git a/test/sql-tap/aggnested.test.lua b/test/sql-tap/aggnested.test.lua
index 67a9ba891..a09e654e7 100755
--- a/test/sql-tap/aggnested.test.lua
+++ b/test/sql-tap/aggnested.test.lua
@@ -28,7 +28,7 @@ test:do_execsql_test(
         INSERT INTO t1 VALUES(1), (2), (3);
         CREATE TABLE t2(b1 INTEGER PRIMARY KEY);
         INSERT INTO t2 VALUES(4), (5);
-        SELECT (SELECT group_concat(a1,'x') FROM t2 LIMIT 1) FROM t1;
+        SELECT (SELECT group_concat(CAST(a1 AS STRING),'x') FROM t2 LIMIT 1) FROM t1;
     ]],
     {
         -- <aggnested-1.1>
@@ -40,7 +40,7 @@ test:do_execsql_test(
     "aggnested-1.2",
     [[
         SELECT
-         (SELECT group_concat(a1,'x') || '-' || group_concat(b1,'y') FROM t2)
+         (SELECT group_concat(CAST(a1 AS STRING),'x') || '-' || group_concat(CAST(b1 AS STRING),'y') FROM t2)
         FROM t1;
     ]],
     {
@@ -51,7 +51,7 @@ test:do_execsql_test(
 
 test:do_execsql_test("aggnested-1.3",
     [[
-        SELECT (SELECT group_concat(b1,a1) FROM t2) FROM t1;
+        SELECT (SELECT group_concat(CAST(b1 AS STRING),CAST(a1 AS STRING)) FROM t2) FROM t1;
     ]],
     {
         -- <aggnested-1.3>
@@ -61,7 +61,7 @@ test:do_execsql_test("aggnested-1.3",
 
 test:do_execsql_test("aggnested-1.4",
     [[
-        SELECT (SELECT group_concat(a1,b1) FROM t2) FROM t1;
+        SELECT (SELECT group_concat(CAST(a1 AS STRING),CAST(b1 AS STRING)) FROM t2) FROM t1;
     ]],
     {
         -- <aggnested-1.4>
diff --git a/test/sql-tap/cse.test.lua b/test/sql-tap/cse.test.lua
index 341b6de01..cfb642cfe 100755
--- a/test/sql-tap/cse.test.lua
+++ b/test/sql-tap/cse.test.lua
@@ -198,7 +198,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "cse-1.13",
     [[
-        SELECT upper(b), typeof(b), b FROM t1
+        SELECT upper(CAST(b AS STRING)), typeof(b), b FROM t1
     ]], {
         -- <cse-1.13>
         "11", "integer", 11, "21", "integer", 21
@@ -208,7 +208,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "cse-1.14",
     [[
-        SELECT b, typeof(b), upper(b), typeof(b), b FROM t1
+        SELECT b, typeof(b), upper(CAST(b AS STRING)), typeof(b), b FROM t1
     ]], {
         -- <cse-1.14>
         11, "integer", "11", "integer", 11, 21, "integer", "21", "integer", 21
diff --git a/test/sql-tap/e_select1.test.lua b/test/sql-tap/e_select1.test.lua
index 578620fca..438779898 100755
--- a/test/sql-tap/e_select1.test.lua
+++ b/test/sql-tap/e_select1.test.lua
@@ -940,7 +940,7 @@ test:do_select_tests(
         {"4", "SELECT *, count(*) FROM a1 JOIN a2", {4, 10, 10, 4, 16}},
         {"5", "SELECT *, sum(three) FROM a1 NATURAL JOIN a2", {3, 6, 2, 3}},
         {"6", "SELECT *, sum(three) FROM a1 NATURAL JOIN a2", {3, 6, 2, 3}},
-        {"7", "SELECT group_concat(three, ''), a1.* FROM a1 NATURAL JOIN a2", {"12", 3, 6}},
+        {"7", "SELECT group_concat(CAST(three AS STRING), ''), a1.* FROM a1 NATURAL JOIN a2", {"12", 3, 6}},
     })
 
 -- EVIDENCE-OF: R-04486-07266 Or, if the dataset contains zero rows, then
@@ -1022,10 +1022,10 @@ test:do_execsql_test(
 test:do_select_tests(
     "e_select-4.9",
     {
-        {"1", "SELECT group_concat(one), two FROM b1 GROUP BY two", {"4,5","f","1","o","6,7","s","2,3","t"}},
-        {"2", "SELECT group_concat(one), sum(one) FROM b1 GROUP BY (one>4)", {"1,2,3,4",10,"5,6,7",18}},
-        {"3", "SELECT group_concat(one) FROM b1 GROUP BY (two>'o'), one%2", {"4","1,5","2,6","3,7"}},
-        {"4", "SELECT group_concat(one) FROM b1 GROUP BY (one==2 OR two=='o')", {"3,4,5,6,7","1,2"}},
+        {"1", "SELECT group_concat(CAST(one AS STRING)), two FROM b1 GROUP BY two", {"4,5","f","1","o","6,7","s","2,3","t"}},
+        {"2", "SELECT group_concat(CAST(one AS STRING)), sum(one) FROM b1 GROUP BY (one>4)", {"1,2,3,4",10,"5,6,7",18}},
+        {"3", "SELECT group_concat(CAST(one AS STRING)) FROM b1 GROUP BY (two>'o'), one%2", {"4","1,5","2,6","3,7"}},
+        {"4", "SELECT group_concat(CAST(one AS STRING)) FROM b1 GROUP BY (one==2 OR two=='o')", {"3,4,5,6,7","1,2"}},
     })
 
 -- EVIDENCE-OF: R-14926-50129 For the purposes of grouping rows, NULL
@@ -1034,7 +1034,7 @@ test:do_select_tests(
 test:do_select_tests(
     "e_select-4.10",
     {
-        {"1", "SELECT group_concat(y) FROM b2 GROUP BY x", {"0,1","3","2,4"}},
+        {"1", "SELECT group_concat(CAST(y AS STRING)) FROM b2 GROUP BY x", {"0,1","3","2,4"}},
         {"2", "SELECT count(*) FROM b2 GROUP BY CASE WHEN y<4 THEN NULL ELSE 0 END", {4, 1}},
     })
 
diff --git a/test/sql-tap/func.test.lua b/test/sql-tap/func.test.lua
index 3c088920f..71da86220 100755
--- a/test/sql-tap/func.test.lua
+++ b/test/sql-tap/func.test.lua
@@ -95,7 +95,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-1.4",
     [[
-        SELECT coalesce(length(a),-1) FROM t2
+        SELECT coalesce(length(CAST(a AS STRING)),-1) FROM t2
     ]], {
         -- <func-1.4>
         1, -1, 3, -1, 5
@@ -197,7 +197,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-2.9",
     [[
-        SELECT substr(a,1,1) FROM t2
+        SELECT substr(CAST(a AS STRING),1,1) FROM t2
     ]], {
         -- <func-2.9>
         "1", "", "3", "", "6"
@@ -207,7 +207,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-2.10",
     [[
-        SELECT substr(a,2,2) FROM t2
+        SELECT substr(CAST(a AS STRING),2,2) FROM t2
     ]], {
         -- <func-2.10>
         "", "", "45", "", "78"
@@ -412,13 +412,13 @@ test:do_execsql_test(
         -- </func-4.4.1>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "func-4.4.2",
     [[
         SELECT abs(t1) FROM tbl1
     ]], {
         -- <func-4.4.2>
-        0.0, 0.0, 0.0, 0.0, 0.0
+        1, "Type mismatch: can not convert this to number"
         -- </func-4.4.2>
     })
 
@@ -502,13 +502,13 @@ test:do_execsql_test(
         -- </func-4.12>
     })
 
-test:do_execsql_test(
+test:do_catchsql_test(
     "func-4.13",
     [[
         SELECT round(t1,2) FROM tbl1
     ]], {
         -- <func-4.13>
-        0.0, 0.0, 0.0, 0.0, 0.0
+        1, "Type mismatch: can not convert this to numeric"
         -- </func-4.13>
     })
 
@@ -763,7 +763,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-5.3",
     [[
-        SELECT upper(a), lower(a) FROM t2
+        SELECT upper(CAST(a AS STRING)), lower(CAST(a AS STRING)) FROM t2
     ]], {
         -- <func-5.3>
         "1","1","","","345","345","","","67890","67890"
@@ -797,7 +797,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-6.2",
     [[
-        SELECT coalesce(upper(a),'nil') FROM t2
+        SELECT coalesce(upper(CAST(a AS STRING)),'nil') FROM t2
     ]], {
         -- <func-6.2>
         "1","nil","345","nil","67890"
@@ -893,7 +893,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-8.5",
     [[
-        SELECT sum(x) FROM (SELECT '9223372036' || '854775807' AS x
+        SELECT sum(x) FROM (SELECT CAST('9223372036' || '854775807' AS NUMBER) AS x
                             UNION ALL SELECT -9223372036854775807)
     ]], {
         -- <func-8.5>
@@ -904,7 +904,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-8.6",
     [[
-        SELECT typeof(sum(x)) FROM (SELECT '9223372036' || '854775807' AS x
+        SELECT typeof(sum(x)) FROM (SELECT CAST('9223372036' || '854775807' AS NUMBER) AS x
                             UNION ALL SELECT -9223372036854775807)
     ]], {
         -- <func-8.6>
@@ -915,7 +915,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-8.7",
     [[
-        SELECT typeof(sum(x)) FROM (SELECT '9223372036' || '854775808' AS x
+        SELECT typeof(sum(x)) FROM (SELECT CAST('9223372036' || '854775808' AS NUMBER) AS x
                             UNION ALL SELECT -9223372036854775807)
     ]], {
         -- <func-8.7>
@@ -926,7 +926,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "func-8.8",
     [[
-        SELECT sum(x)>0.0 FROM (SELECT '9223372036' || '854775808' AS x
+        SELECT sum(x)>0.0 FROM (SELECT CAST('9223372036' || '854775808' AS NUMBER) AS x
                             UNION ALL SELECT -9223372036850000000)
     ]], {
         -- <func-8.8>
@@ -2928,7 +2928,7 @@ test:do_catchsql_test(
         SELECT RANDOMBLOB(X'FF')
     ]], {
         -- <func-76.2>
-        1, "Type mismatch: can not convert varbinary to numeric"
+        1, "Type mismatch: can not convert varbinary to integer"
         -- </func-76.2>
     })
 
diff --git a/test/sql-tap/orderby1.test.lua b/test/sql-tap/orderby1.test.lua
index 51e8d301f..95a8de487 100755
--- a/test/sql-tap/orderby1.test.lua
+++ b/test/sql-tap/orderby1.test.lua
@@ -735,7 +735,7 @@ test:do_execsql_test(
         SELECT (
           SELECT 'hardware' FROM ( 
             SELECT 'software' ORDER BY 'firmware' ASC, 'sportswear' DESC
-          ) GROUP BY 1 HAVING length(b) <> 0
+          ) GROUP BY 1 HAVING length(CAST(b AS STRING)) <> 0
         )
         FROM abc;
     ]], {
diff --git a/test/sql-tap/position.test.lua b/test/sql-tap/position.test.lua
index e0455abc9..c3fce6673 100755
--- a/test/sql-tap/position.test.lua
+++ b/test/sql-tap/position.test.lua
@@ -228,7 +228,7 @@ test:do_test(
         return test:catchsql "SELECT position(34, 12345);"
     end, {
         -- <position-1.23>
-        1, "Inconsistent types: expected text or varbinary got unsigned"
+        1, "Type mismatch: can not convert 34 to string or varbinary"
         -- </position-1.23>
     })
 
@@ -238,7 +238,7 @@ test:do_test(
         return test:catchsql "SELECT position(34, 123456.78);"
     end, {
         -- <position-1.24>
-        1, "Inconsistent types: expected text or varbinary got real"
+        1, "Type mismatch: can not convert 34 to string or varbinary"
         -- </position-1.24>
     })
 
@@ -248,7 +248,7 @@ test:do_test(
         return test:catchsql "SELECT position(x'3334', 123456.78);"
     end, {
         -- <position-1.25>
-        1, "Inconsistent types: expected text or varbinary got real"
+        1, "Type mismatch: can not convert 123456.78 to string or varbinary"
         -- </position-1.25>
     })
 
@@ -554,7 +554,7 @@ test:do_test(
         return test:catchsql("SELECT position('x', x'78c3a4e282ac79');")
     end, {
         -- <position-1.54>
-        1, "Inconsistent types: expected text got varbinary"
+        1, "Type mismatch: can not convert varbinary to text"
         -- </position-1.54>
     })
 
@@ -564,7 +564,7 @@ test:do_test(
         return test:catchsql "SELECT position('y', x'78c3a4e282ac79');"
     end, {
         -- <position-1.55>
-        1, "Inconsistent types: expected text got varbinary"
+        1, "Type mismatch: can not convert varbinary to text"
         -- </position-1.55>
     })
 
@@ -614,7 +614,7 @@ test:do_test(
         return test:catchsql "SELECT position(x'79', 'xä€y');"
     end, {
         -- <position-1.57.1>
-        1, "Inconsistent types: expected varbinary got text"
+        1, "Type mismatch: can not convert xä€y to varbinary"
         -- </position-1.57.1>
     })
 
@@ -624,7 +624,7 @@ test:do_test(
         return test:catchsql "SELECT position(x'a4', 'xä€y');"
     end, {
         -- <position-1.57.2>
-        1, "Inconsistent types: expected varbinary got text"
+        1, "Type mismatch: can not convert xä€y to varbinary"
         -- </position-1.57.2>
     })
 
@@ -634,7 +634,7 @@ test:do_test(
         return test:catchsql "SELECT position('y', x'78c3a4e282ac79');"
     end, {
         -- <position-1.57.3>
-        1, "Inconsistent types: expected text got varbinary"
+        1, "Type mismatch: can not convert varbinary to text"
         -- </position-1.57.3>
     })
 
diff --git a/test/sql-tap/tkt2942.test.lua b/test/sql-tap/tkt2942.test.lua
index f83d30c2b..cac833472 100755
--- a/test/sql-tap/tkt2942.test.lua
+++ b/test/sql-tap/tkt2942.test.lua
@@ -40,7 +40,7 @@ test:do_execsql_test(
         insert into t1 values (2, 1);
         insert into t1 values (3, 3);
         insert into t1 values (4, 4);
-        SELECT group_concat("num") FROM (SELECT "num" FROM t1 ORDER BY "num" DESC);
+        SELECT group_concat(CAST("num" AS STRING)) FROM (SELECT "num" FROM t1 ORDER BY "num" DESC);
     ]], {
         -- <tkt2942.1>
         "4,3,2,1"
@@ -50,7 +50,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt2942.2",
     [[
-        SELECT group_concat("num") FROM (SELECT "num" FROM t1 ORDER BY "num");
+        SELECT group_concat(CAST("num" AS STRING)) FROM (SELECT "num" FROM t1 ORDER BY "num");
     ]], {
         -- <tkt2942.2>
         "1,2,3,4"
@@ -60,7 +60,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt2942.3",
     [[
-        SELECT group_concat("num") FROM (SELECT "num" FROM t1);
+        SELECT group_concat(CAST("num" AS STRING)) FROM (SELECT "num" FROM t1);
     ]], {
         -- <tkt2942.3>
         "2,1,3,4"
@@ -70,7 +70,7 @@ test:do_execsql_test(
 test:do_execsql_test(
     "tkt2942.4",
     [[
-        SELECT group_concat("num") FROM (SELECT "num" FROM t1 ORDER BY id DESC);
+        SELECT group_concat(CAST("num" AS STRING)) FROM (SELECT "num" FROM t1 ORDER BY id DESC);
     ]], {
         -- <tkt2942.4>
         "4,3,1,2"
diff --git a/test/sql-tap/view.test.lua b/test/sql-tap/view.test.lua
index 60dfc927a..19ad171cb 100755
--- a/test/sql-tap/view.test.lua
+++ b/test/sql-tap/view.test.lua
@@ -1317,7 +1317,7 @@ test:do_execsql_test(
             a(t) AS (
                 SELECT group_concat( substr('a', 1+least(iter/7,4), 1), '') FROM m2 GROUP BY cy
             )
-          SELECT group_concat(trim(t),x'0a') FROM a;
+          SELECT group_concat(trim(t),CAST(x'0a' AS STRING)) FROM a;
         SELECT * FROM v;
     ]], {
         -- <view-24.5>
diff --git a/test/sql-tap/with1.test.lua b/test/sql-tap/with1.test.lua
index 75935108c..21d18b9a8 100755
--- a/test/sql-tap/with1.test.lua
+++ b/test/sql-tap/with1.test.lua
@@ -550,7 +550,7 @@ test:do_execsql_test("8.1-mandelbrot", [[
       SELECT group_concat( substr(' .+*#', 1+LEAST(iter/7,4), 1), '')
       FROM m2 GROUP BY cy
     )
-  SELECT group_concat(TRIM(TRAILING FROM t),x'0a') FROM a;
+  SELECT group_concat(TRIM(TRAILING FROM t),CAST(x'0a' AS STRING)) FROM a;
 ]], {
   -- <8.1-mandelbrot>
   [[                                    ....#
diff --git a/test/sql/boolean.result b/test/sql/boolean.result
index 51ec5820b..9ccef44bb 100644
--- a/test/sql/boolean.result
+++ b/test/sql/boolean.result
@@ -276,29 +276,17 @@ SELECT is_boolean('true');
 SELECT abs(a) FROM t0;
  | ---
  | - null
- | - 'Inconsistent types: expected number got boolean'
+ | - 'Type mismatch: can not convert FALSE to number'
  | ...
 SELECT lower(a) FROM t0;
  | ---
- | - metadata:
- |   - name: COLUMN_1
- |     type: string
- |   rows:
- |   - ['false']
- |   - ['true']
- |   - [null]
- |   - [null]
+ | - null
+ | - 'Type mismatch: can not convert FALSE to string'
  | ...
 SELECT upper(a) FROM t0;
  | ---
- | - metadata:
- |   - name: COLUMN_1
- |     type: string
- |   rows:
- |   - ['FALSE']
- |   - ['TRUE']
- |   - [null]
- |   - [null]
+ | - null
+ | - 'Type mismatch: can not convert FALSE to string'
  | ...
 SELECT quote(a) FROM t0;
  | ---
@@ -314,14 +302,8 @@ SELECT quote(a) FROM t0;
 -- gh-4462: LENGTH didn't take BOOLEAN arguments.
 SELECT length(a) FROM t0;
  | ---
- | - metadata:
- |   - name: COLUMN_1
- |     type: integer
- |   rows:
- |   - [5]
- |   - [4]
- |   - [null]
- |   - [null]
+ | - null
+ | - 'Type mismatch: can not convert FALSE to string or varbinary'
  | ...
 SELECT typeof(a) FROM t0;
  | ---
@@ -377,11 +359,8 @@ SELECT TOTAL(a) FROM t0;
  | ...
 SELECT GROUP_CONCAT(a, ' +++ ') FROM t0;
  | ---
- | - metadata:
- |   - name: COLUMN_1
- |     type: string
- |   rows:
- |   - ['FALSE +++ TRUE']
+ | - null
+ | - 'Type mismatch: can not convert FALSE to string or varbinary'
  | ...
 
 -- Check BOOLEAN as binding parameter.
diff --git a/test/sql/prepared.result b/test/sql/prepared.result
index 0db2cc03f..45933f4af 100644
--- a/test/sql/prepared.result
+++ b/test/sql/prepared.result
@@ -471,7 +471,7 @@ s = prepare([[WITH RECURSIVE \
                       a(t) AS ( \
                           SELECT group_concat( substr(' .+*#', 1+LEAST(iter/7,4), 1), '') \
                               FROM m2 GROUP BY cy) \
-                  SELECT group_concat(TRIM(TRAILING FROM t),x'0a') FROM a;]])
+                  SELECT group_concat(TRIM(TRAILING FROM t),CAST(x'0a' AS STRING)) FROM a;]])
  | ---
  | ...
 
diff --git a/test/sql/prepared.test.lua b/test/sql/prepared.test.lua
index d8e8a44cb..7df3857ee 100644
--- a/test/sql/prepared.test.lua
+++ b/test/sql/prepared.test.lua
@@ -176,7 +176,7 @@ s = prepare([[WITH RECURSIVE \
                       a(t) AS ( \
                           SELECT group_concat( substr(' .+*#', 1+LEAST(iter/7,4), 1), '') \
                               FROM m2 GROUP BY cy) \
-                  SELECT group_concat(TRIM(TRAILING FROM t),x'0a') FROM a;]])
+                  SELECT group_concat(TRIM(TRAILING FROM t),CAST(x'0a' AS STRING)) FROM a;]])
 
 res = execute(s.stmt_id)
 res.metadata
diff --git a/test/sql/types.result b/test/sql/types.result
index 442245186..daebf9b39 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -215,17 +215,17 @@ box.execute("INSERT INTO t1 VALUES (randomblob(5));")
 box.execute("SELECT * FROM t1 WHERE s LIKE 'blob';")
 ---
 - null
-- 'Inconsistent types: expected text got varbinary'
+- 'Type mismatch: can not convert varbinary to string'
 ...
 box.execute("SELECT * FROM t1 WHERE 'blob' LIKE s;")
 ---
 - null
-- 'Inconsistent types: expected text got varbinary'
+- 'Type mismatch: can not convert varbinary to string'
 ...
 box.execute("SELECT * FROM t1 WHERE 'blob' LIKE x'0000';")
 ---
 - null
-- 'Inconsistent types: expected text got varbinary'
+- 'Type mismatch: can not convert varbinary to string'
 ...
 box.execute("SELECT s LIKE NULL FROM t1;")
 ---
@@ -246,12 +246,12 @@ box.execute("INSERT INTO t1 VALUES (1);")
 box.execute("SELECT * FROM t1 WHERE s LIKE 'int';")
 ---
 - null
-- 'Inconsistent types: expected text got unsigned'
+- 'Type mismatch: can not convert 1 to string'
 ...
 box.execute("SELECT * FROM t1 WHERE 'int' LIKE 4;")
 ---
 - null
-- 'Inconsistent types: expected text got unsigned'
+- 'Type mismatch: can not convert 4 to string'
 ...
 box.execute("SELECT NULL LIKE s FROM t1;")
 ---
@@ -818,11 +818,8 @@ box.execute("SELECT count(i) FROM t;")
 ...
 box.execute("SELECT group_concat(i) FROM t;")
 ---
-- metadata:
-  - name: COLUMN_1
-    type: string
-  rows:
-  - ['1,-1,18446744073709551613']
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
 ...
 box.execute("DELETE FROM t WHERE i < 18446744073709551613;")
 ---
@@ -830,19 +827,13 @@ box.execute("DELETE FROM t WHERE i < 18446744073709551613;")
 ...
 box.execute("SELECT lower(i) FROM t;")
 ---
-- metadata:
-  - name: COLUMN_1
-    type: string
-  rows:
-  - ['18446744073709551613']
+- null
+- 'Type mismatch: can not convert 18446744073709551613 to string'
 ...
 box.execute("SELECT upper(i) FROM t;")
 ---
-- metadata:
-  - name: COLUMN_1
-    type: string
-  rows:
-  - ['18446744073709551613']
+- null
+- 'Type mismatch: can not convert 18446744073709551613 to string'
 ...
 box.execute("SELECT abs(i) FROM t;")
 ---
@@ -1312,17 +1303,17 @@ box.execute("SELECT group_concat(v) FROM t;")
 box.execute("SELECT lower(v) FROM t;")
 ---
 - null
-- 'Inconsistent types: expected text got varbinary'
+- 'Type mismatch: can not convert varbinary to string'
 ...
 box.execute("SELECT upper(v) FROM t;")
 ---
 - null
-- 'Inconsistent types: expected text got varbinary'
+- 'Type mismatch: can not convert varbinary to string'
 ...
 box.execute("SELECT abs(v) FROM t;")
 ---
 - null
-- 'Inconsistent types: expected number got varbinary'
+- 'Type mismatch: can not convert varbinary to number'
 ...
 box.execute("SELECT typeof(v) FROM t;")
 ---
@@ -1871,33 +1862,18 @@ box.execute("SELECT count(d) FROM t;")
 ...
 box.execute("SELECT group_concat(d) FROM t;")
 ---
-- metadata:
-  - name: COLUMN_1
-    type: string
-  rows:
-  - ['10.0,-2.0,3.3,1.8e+19']
+- null
+- 'Type mismatch: can not convert 10.0 to string or varbinary'
 ...
 box.execute("SELECT lower(d) FROM t;")
 ---
-- metadata:
-  - name: COLUMN_1
-    type: string
-  rows:
-  - ['10.0']
-  - ['-2.0']
-  - ['3.3']
-  - ['1.8e+19']
+- null
+- 'Type mismatch: can not convert 10.0 to string'
 ...
 box.execute("SELECT upper(d) FROM t;")
 ---
-- metadata:
-  - name: COLUMN_1
-    type: string
-  rows:
-  - ['10.0']
-  - ['-2.0']
-  - ['3.3']
-  - ['1.8E+19']
+- null
+- 'Type mismatch: can not convert 10.0 to string'
 ...
 box.execute("SELECT abs(d) FROM t;")
 ---
@@ -2795,3 +2771,2417 @@ box.execute([[DROP TABLE ts;]])
 ---
 - row_count: 1
 ...
+-- Make sure the function argument types are checked.
+box.execute([[SELECT abs(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1]
+...
+box.execute([[SELECT abs(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1]
+...
+box.execute([[SELECT abs(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT abs(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT abs(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to number'
+...
+box.execute([[SELECT abs('a');]])
+---
+- null
+- 'Type mismatch: can not convert a to number'
+...
+box.execute([[SELECT abs(X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to number'
+...
+box.execute([[SELECT abs(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [null]
+...
+box.execute([[SELECT char(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['�']
+...
+box.execute([[SELECT char(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ["\x01"]
+...
+box.execute([[SELECT char(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ["\x01"]
+...
+box.execute([[SELECT char(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['�']
+...
+box.execute([[SELECT char(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to integer'
+...
+box.execute([[SELECT char('a');]])
+---
+- null
+- 'Type mismatch: can not convert a to integer'
+...
+box.execute([[SELECT char(X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to integer'
+...
+box.execute([[SELECT char(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['']
+...
+box.execute([[SELECT character_length(-1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT character_length(1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT character_length(1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT character_length(-1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string or varbinary'
+...
+box.execute([[SELECT character_length(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT character_length('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT character_length(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT character_length(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT char_length(-1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT char_length(1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT char_length(1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT char_length(-1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string or varbinary'
+...
+box.execute([[SELECT char_length(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT char_length('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT char_length(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT char_length(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT coalesce(-1, -1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1]
+...
+box.execute([[SELECT coalesce(1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1]
+...
+box.execute([[SELECT coalesce(1.5, 1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT coalesce(-1.5, -1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT coalesce(true, true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [true]
+...
+box.execute([[SELECT coalesce('a', 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['a']
+...
+box.execute([[SELECT coalesce(X'33', X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['3']
+...
+box.execute([[SELECT coalesce(NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT coalesce(1, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1]
+...
+box.execute([[SELECT coalesce(NULL, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1]
+...
+box.execute([[SELECT greatest(-1, -1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1]
+...
+box.execute([[SELECT greatest(1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1]
+...
+box.execute([[SELECT greatest(1.5, 1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT greatest(-1.5, -1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT greatest(true, true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [true]
+...
+box.execute([[SELECT greatest('a', 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['a']
+...
+box.execute([[SELECT greatest(X'33', X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['3']
+...
+box.execute([[SELECT greatest(NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT greatest(NULL, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT greatest(1, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT hex(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['2D31']
+...
+box.execute([[SELECT hex(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['31']
+...
+box.execute([[SELECT hex(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['312E35']
+...
+box.execute([[SELECT hex(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['2D312E35']
+...
+box.execute([[SELECT hex(true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['54525545']
+...
+box.execute([[SELECT hex('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['61']
+...
+box.execute([[SELECT hex(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['33']
+...
+box.execute([[SELECT hex(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['']
+...
+box.execute([[SELECT ifnull(-1, -1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [-1]
+...
+box.execute([[SELECT ifnull(1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT ifnull(1.5, 1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT ifnull(-1.5, -1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT ifnull(true, true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [true]
+...
+box.execute([[SELECT ifnull('a', 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - ['a']
+...
+box.execute([[SELECT ifnull(X'33', X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - ['3']
+...
+box.execute([[SELECT ifnull(NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT ifnull(NULL, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT ifnull(1, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT least(-1, -1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1]
+...
+box.execute([[SELECT least(1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1]
+...
+box.execute([[SELECT least(1.5, 1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT least(-1.5, -1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT least(true, true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [true]
+...
+box.execute([[SELECT least('a', 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['a']
+...
+box.execute([[SELECT least(X'33', X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['3']
+...
+box.execute([[SELECT least(NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT least(NULL, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT least(1, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT length(-1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT length(1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT length(1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT length(-1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string or varbinary'
+...
+box.execute([[SELECT length(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT length('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT length(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT length(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT likelihood(-1, -1);]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood(1, 1);]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood(1.5, 1.5);]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood(-1.5, -1.5);]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood(true, true);]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood('a', 'a');]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood(X'33', X'33');]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood(NULL, NULL);]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood(NULL, 1);]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likelihood(1, NULL);]])
+---
+- null
+- Illegal parameters, second argument to likelihood() must be a constant between 0.0
+  and 1.0
+...
+box.execute([[SELECT likely(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [-1]
+...
+box.execute([[SELECT likely(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT likely(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: double
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT likely(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: double
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT likely(true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: boolean
+  rows:
+  - [true]
+...
+box.execute([[SELECT likely('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT likely(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - ['3']
+...
+box.execute([[SELECT likely(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT lower(-1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string'
+...
+box.execute([[SELECT lower(1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string'
+...
+box.execute([[SELECT lower(1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string'
+...
+box.execute([[SELECT lower(-1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string'
+...
+box.execute([[SELECT lower(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string'
+...
+box.execute([[SELECT lower('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT lower(X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to string'
+...
+box.execute([[SELECT lower(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(-1, -1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(1.5, 1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(-1.5, -1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(true, true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif('a', 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(X'33', X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(NULL, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT nullif(1, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1]
+...
+box.execute([[SELECT position(-1, -1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT position(1, 1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT position(1.5, 1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT position(-1.5, -1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string or varbinary'
+...
+box.execute([[SELECT position(true, true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT position('a', 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT position('a', 1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT position(1, 'a');]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT position(X'33', X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT position(X'33', 1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT position(NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT position(NULL, 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT position('a', NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT printf(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['-1']
+...
+box.execute([[SELECT printf(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['1']
+...
+box.execute([[SELECT printf(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['1.5']
+...
+box.execute([[SELECT printf(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['-1.5']
+...
+box.execute([[SELECT printf(true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['TRUE']
+...
+box.execute([[SELECT printf('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT printf(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['3']
+...
+box.execute([[SELECT printf(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT quote(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [-1]
+...
+box.execute([[SELECT quote(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [1]
+...
+box.execute([[SELECT quote(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['1.5']
+...
+box.execute([[SELECT quote(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['-1.5']
+...
+box.execute([[SELECT quote(true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['TRUE']
+...
+box.execute([[SELECT quote('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['''a''']
+...
+box.execute([[SELECT quote(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['X''33''']
+...
+box.execute([[SELECT quote(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['NULL']
+...
+box.execute([[SELECT randomblob(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - [null]
+...
+box.execute([[SELECT randomblob(0);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - [null]
+...
+box.execute([[SELECT randomblob(0.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - [null]
+...
+box.execute([[SELECT randomblob(-0.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - [null]
+...
+box.execute([[SELECT randomblob(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to integer'
+...
+box.execute([[SELECT randomblob('a');]])
+---
+- null
+- 'Type mismatch: can not convert a to integer'
+...
+box.execute([[SELECT randomblob(X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to integer'
+...
+box.execute([[SELECT randomblob(NULL);]])
+---
+- null
+- 'Type mismatch: can not convert (null) to integer'
+...
+box.execute([[SELECT replace(-1, -1, -1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT replace(1, 1, 1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT replace(1.5, 1.5, 1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT replace(-1.5, -1.5, -1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string or varbinary'
+...
+box.execute([[SELECT replace(true, true, true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT replace('a', 'a', 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT replace('a', 'a', 1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT replace('a', 1, 'a');]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT replace(1, 'a', 'a');]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT replace('a', 'a', X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to text'
+...
+box.execute([[SELECT replace('a', X'33', 'a');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to text'
+...
+box.execute([[SELECT replace(X'33', 'a', X'33');]])
+---
+- null
+- 'Type mismatch: can not convert a to varbinary'
+...
+box.execute([[SELECT replace(X'33', X'33', 'a');]])
+---
+- null
+- 'Type mismatch: can not convert a to varbinary'
+...
+box.execute([[SELECT replace(X'33', X'33', X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['3']
+...
+box.execute([[SELECT replace(X'33', X'33', 1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT replace(X'33', 1, X'33');]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT replace(1, X'33', X'33');]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT replace(NULL, NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT replace(NULL, NULL, 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT replace(NULL, 'a', NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT replace(NULL, 'a', 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT replace('a', NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT replace('a', NULL, 'a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT replace('a', 'a', NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT round(-1, -1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [-1]
+...
+box.execute([[SELECT round(1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT round(1.5, 1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT round(-1.5, -1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [-2]
+...
+box.execute([[SELECT round(1.5, true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to integer'
+...
+box.execute([[SELECT round(true, 1.5);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to numeric'
+...
+box.execute([[SELECT round(true, true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to integer'
+...
+box.execute([[SELECT round('a', 'a');]])
+---
+- null
+- 'Type mismatch: can not convert a to integer'
+...
+box.execute([[SELECT round(X'33', X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to integer'
+...
+box.execute([[SELECT round(NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT round(NULL, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT round(1, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT soundex(-1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to text'
+...
+box.execute([[SELECT soundex(1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to text'
+...
+box.execute([[SELECT soundex(1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to text'
+...
+box.execute([[SELECT soundex(-1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to text'
+...
+box.execute([[SELECT soundex(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to text'
+...
+box.execute([[SELECT soundex('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['A000']
+...
+box.execute([[SELECT soundex(X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to text'
+...
+box.execute([[SELECT soundex(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT substr(-1, -1, -1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT substr(1, 1, 1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT substr(1.5, 1.5, 1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT substr(true, true, true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT substr('a', 'a', 'a');]])
+---
+- null
+- 'Type mismatch: can not convert a to integer'
+...
+box.execute([[SELECT substr('a', 'a', 1);]])
+---
+- null
+- 'Type mismatch: can not convert a to integer'
+...
+box.execute([[SELECT substr('a', 1, 'a');]])
+---
+- null
+- 'Type mismatch: can not convert a to integer'
+...
+box.execute([[SELECT substr('a', 1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT substr(X'33', X'33', X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to integer'
+...
+box.execute([[SELECT substr(X'33', X'33', 1);]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to integer'
+...
+box.execute([[SELECT substr(X'33', 1, X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to integer'
+...
+box.execute([[SELECT substr(X'33', 1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['3']
+...
+box.execute([[SELECT substr(1, X'33', 1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT substr(1, 1, X'33');]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT substr(NULL, NULL, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT substr(NULL, 1, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT substr('a', NULL, 1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT substr('a', 1, NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT typeof(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['integer']
+...
+box.execute([[SELECT typeof(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['integer']
+...
+box.execute([[SELECT typeof(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['double']
+...
+box.execute([[SELECT typeof(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['double']
+...
+box.execute([[SELECT typeof(true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['boolean']
+...
+box.execute([[SELECT typeof('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['string']
+...
+box.execute([[SELECT typeof(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['varbinary']
+...
+box.execute([[SELECT typeof(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['boolean']
+...
+box.execute([[SELECT unicode(-1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT unicode(1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT unicode(1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT unicode(-1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string or varbinary'
+...
+box.execute([[SELECT unicode(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT unicode('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [97]
+...
+box.execute([[SELECT unicode(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [51]
+...
+box.execute([[SELECT unicode(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT unlikely(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [-1]
+...
+box.execute([[SELECT unlikely(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT unlikely(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: double
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT unlikely(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: double
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT unlikely(true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: boolean
+  rows:
+  - [true]
+...
+box.execute([[SELECT unlikely('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT unlikely(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - ['3']
+...
+box.execute([[SELECT unlikely(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT upper(-1);]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string'
+...
+box.execute([[SELECT upper(1);]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string'
+...
+box.execute([[SELECT upper(1.5);]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string'
+...
+box.execute([[SELECT upper(-1.5);]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string'
+...
+box.execute([[SELECT upper(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string'
+...
+box.execute([[SELECT upper('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['A']
+...
+box.execute([[SELECT upper(X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to string'
+...
+box.execute([[SELECT upper(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT zeroblob(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - ['']
+...
+box.execute([[SELECT zeroblob(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - ["\0"]
+...
+box.execute([[SELECT zeroblob(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - ["\0"]
+...
+box.execute([[SELECT zeroblob(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: varbinary
+  rows:
+  - ['']
+...
+box.execute([[SELECT zeroblob(true);]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to integer'
+...
+box.execute([[SELECT zeroblob('a');]])
+---
+- null
+- 'Type mismatch: can not convert a to integer'
+...
+box.execute([[SELECT zeroblob(X'33');]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to integer'
+...
+box.execute([[SELECT zeroblob(NULL);]])
+---
+- null
+- 'Type mismatch: can not convert (null) to integer'
+...
+box.execute([[SELECT trim(-1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['-1']
+...
+box.execute([[SELECT trim(1);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['1']
+...
+box.execute([[SELECT trim(1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['1.5']
+...
+box.execute([[SELECT trim(-1.5);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['-1.5']
+...
+box.execute([[SELECT trim(true);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['TRUE']
+...
+box.execute([[SELECT trim('a');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT trim(X'33');]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['3']
+...
+box.execute([[SELECT trim(NULL);]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT -1 like -1;]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string'
+...
+box.execute([[SELECT 1 like 1;]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string'
+...
+box.execute([[SELECT 1.5 like 1.5;]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string'
+...
+box.execute([[SELECT true like true;]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string'
+...
+box.execute([[SELECT 'a' like 'a';]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [true]
+...
+box.execute([[SELECT 'a' like 1;]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string'
+...
+box.execute([[SELECT 1 like 'a';]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string'
+...
+box.execute([[SELECT X'33' like X'33';]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to string'
+...
+box.execute([[SELECT NULL like NULL;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT 'a' like NULL;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[SELECT NULL like 'a';]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [null]
+...
+box.execute([[CREATE TABLE t (i INTEGER PRIMARY KEY, u UNSIGNED, d DOUBLE, o DOUBLE, b BOOLEAN, s STRING, v VARBINARY, n SCALAR);]])
+---
+- row_count: 1
+...
+box.execute([[INSERT INTO t VALUES (-1, 1, 1.5, -1.5, true, 'a', X'33', NULL);]])
+---
+- row_count: 1
+...
+box.execute([[SELECT avg(i) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [-1]
+...
+box.execute([[SELECT avg(u) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1]
+...
+box.execute([[SELECT avg(d) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT avg(0) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [0]
+...
+box.execute([[SELECT avg(b) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to number'
+...
+box.execute([[SELECT avg(s) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert a to number'
+...
+box.execute([[SELECT avg(v) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to number'
+...
+box.execute([[SELECT avg(n) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [null]
+...
+box.execute([[SELECT count(i) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT count(u) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT count(d) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT count(0) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT count(b) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT count(s) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT count(v) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [1]
+...
+box.execute([[SELECT count(n) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: integer
+  rows:
+  - [0]
+...
+box.execute([[SELECT group_concat(i) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT group_concat(u) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT group_concat(d) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT group_concat(o) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string or varbinary'
+...
+box.execute([[SELECT group_concat(b) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT group_concat(s) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT group_concat(v) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['3']
+...
+box.execute([[SELECT group_concat(n) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT group_concat(i, i) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert -1 to string or varbinary'
+...
+box.execute([[SELECT group_concat(u, u) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert 1 to string or varbinary'
+...
+box.execute([[SELECT group_concat(d, d) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert 1.5 to string or varbinary'
+...
+box.execute([[SELECT group_concat(o, o) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert -1.5 to string or varbinary'
+...
+box.execute([[SELECT group_concat(b, b) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to string or varbinary'
+...
+box.execute([[SELECT group_concat(s, i) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert -1 to text'
+...
+box.execute([[SELECT group_concat(s, s) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - ['a']
+...
+box.execute([[SELECT group_concat(s, v) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to text'
+...
+box.execute([[SELECT group_concat(v, s) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert a to varbinary'
+...
+box.execute([[SELECT group_concat(n, n) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: string
+  rows:
+  - [null]
+...
+box.execute([[SELECT max(i) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1]
+...
+box.execute([[SELECT max(u) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1]
+...
+box.execute([[SELECT max(d) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT max(o) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT max(b) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [true]
+...
+box.execute([[SELECT max(s) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['a']
+...
+box.execute([[SELECT max(v) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['3']
+...
+box.execute([[SELECT max(n) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT min(i) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1]
+...
+box.execute([[SELECT min(u) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1]
+...
+box.execute([[SELECT min(d) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT min(o) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT min(b) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [true]
+...
+box.execute([[SELECT min(s) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['a']
+...
+box.execute([[SELECT min(v) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - ['3']
+...
+box.execute([[SELECT min(n) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: scalar
+  rows:
+  - [null]
+...
+box.execute([[SELECT sum(i) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [-1]
+...
+box.execute([[SELECT sum(u) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1]
+...
+box.execute([[SELECT sum(d) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT sum(o) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT sum(b) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to number'
+...
+box.execute([[SELECT sum(s) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert a to number'
+...
+box.execute([[SELECT sum(v) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to number'
+...
+box.execute([[SELECT sum(n) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [null]
+...
+box.execute([[SELECT total(i) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [-1]
+...
+box.execute([[SELECT total(u) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1]
+...
+box.execute([[SELECT total(d) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [1.5]
+...
+box.execute([[SELECT total(o) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [-1.5]
+...
+box.execute([[SELECT total(b) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert TRUE to number'
+...
+box.execute([[SELECT total(s) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert a to number'
+...
+box.execute([[SELECT total(v) FROM t;]])
+---
+- null
+- 'Type mismatch: can not convert varbinary to number'
+...
+box.execute([[SELECT total(n) FROM t;]])
+---
+- metadata:
+  - name: COLUMN_1
+    type: number
+  rows:
+  - [0]
+...
+box.execute([[DROP TABLE t;]])
+---
+- row_count: 1
+...
diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua
index 0270d9f8a..5f6a658b1 100644
--- a/test/sql/types.test.lua
+++ b/test/sql/types.test.lua
@@ -623,3 +623,394 @@ box.execute([[DROP TABLE tb;]])
 box.execute([[DROP TABLE tt;]])
 box.execute([[DROP TABLE tv;]])
 box.execute([[DROP TABLE ts;]])
+
+
+-- Make sure the function argument types are checked.
+box.execute([[SELECT abs(-1);]])
+box.execute([[SELECT abs(1);]])
+box.execute([[SELECT abs(1.5);]])
+box.execute([[SELECT abs(-1.5);]])
+box.execute([[SELECT abs(true);]])
+box.execute([[SELECT abs('a');]])
+box.execute([[SELECT abs(X'33');]])
+box.execute([[SELECT abs(NULL);]])
+
+box.execute([[SELECT char(-1);]])
+box.execute([[SELECT char(1);]])
+box.execute([[SELECT char(1.5);]])
+box.execute([[SELECT char(-1.5);]])
+box.execute([[SELECT char(true);]])
+box.execute([[SELECT char('a');]])
+box.execute([[SELECT char(X'33');]])
+box.execute([[SELECT char(NULL);]])
+
+box.execute([[SELECT character_length(-1);]])
+box.execute([[SELECT character_length(1);]])
+box.execute([[SELECT character_length(1.5);]])
+box.execute([[SELECT character_length(-1.5);]])
+box.execute([[SELECT character_length(true);]])
+box.execute([[SELECT character_length('a');]])
+box.execute([[SELECT character_length(X'33');]])
+box.execute([[SELECT character_length(NULL);]])
+
+box.execute([[SELECT char_length(-1);]])
+box.execute([[SELECT char_length(1);]])
+box.execute([[SELECT char_length(1.5);]])
+box.execute([[SELECT char_length(-1.5);]])
+box.execute([[SELECT char_length(true);]])
+box.execute([[SELECT char_length('a');]])
+box.execute([[SELECT char_length(X'33');]])
+box.execute([[SELECT char_length(NULL);]])
+
+box.execute([[SELECT coalesce(-1, -1);]])
+box.execute([[SELECT coalesce(1, 1);]])
+box.execute([[SELECT coalesce(1.5, 1.5);]])
+box.execute([[SELECT coalesce(-1.5, -1.5);]])
+box.execute([[SELECT coalesce(true, true);]])
+box.execute([[SELECT coalesce('a', 'a');]])
+box.execute([[SELECT coalesce(X'33', X'33');]])
+box.execute([[SELECT coalesce(NULL, NULL);]])
+box.execute([[SELECT coalesce(1, NULL);]])
+box.execute([[SELECT coalesce(NULL, 1);]])
+
+box.execute([[SELECT greatest(-1, -1);]])
+box.execute([[SELECT greatest(1, 1);]])
+box.execute([[SELECT greatest(1.5, 1.5);]])
+box.execute([[SELECT greatest(-1.5, -1.5);]])
+box.execute([[SELECT greatest(true, true);]])
+box.execute([[SELECT greatest('a', 'a');]])
+box.execute([[SELECT greatest(X'33', X'33');]])
+box.execute([[SELECT greatest(NULL, NULL);]])
+box.execute([[SELECT greatest(NULL, 1);]])
+box.execute([[SELECT greatest(1, NULL);]])
+
+box.execute([[SELECT hex(-1);]])
+box.execute([[SELECT hex(1);]])
+box.execute([[SELECT hex(1.5);]])
+box.execute([[SELECT hex(-1.5);]])
+box.execute([[SELECT hex(true);]])
+box.execute([[SELECT hex('a');]])
+box.execute([[SELECT hex(X'33');]])
+box.execute([[SELECT hex(NULL);]])
+
+box.execute([[SELECT ifnull(-1, -1);]])
+box.execute([[SELECT ifnull(1, 1);]])
+box.execute([[SELECT ifnull(1.5, 1.5);]])
+box.execute([[SELECT ifnull(-1.5, -1.5);]])
+box.execute([[SELECT ifnull(true, true);]])
+box.execute([[SELECT ifnull('a', 'a');]])
+box.execute([[SELECT ifnull(X'33', X'33');]])
+box.execute([[SELECT ifnull(NULL, NULL);]])
+box.execute([[SELECT ifnull(NULL, 1);]])
+box.execute([[SELECT ifnull(1, NULL);]])
+
+box.execute([[SELECT least(-1, -1);]])
+box.execute([[SELECT least(1, 1);]])
+box.execute([[SELECT least(1.5, 1.5);]])
+box.execute([[SELECT least(-1.5, -1.5);]])
+box.execute([[SELECT least(true, true);]])
+box.execute([[SELECT least('a', 'a');]])
+box.execute([[SELECT least(X'33', X'33');]])
+box.execute([[SELECT least(NULL, NULL);]])
+box.execute([[SELECT least(NULL, 1);]])
+box.execute([[SELECT least(1, NULL);]])
+
+box.execute([[SELECT length(-1);]])
+box.execute([[SELECT length(1);]])
+box.execute([[SELECT length(1.5);]])
+box.execute([[SELECT length(-1.5);]])
+box.execute([[SELECT length(true);]])
+box.execute([[SELECT length('a');]])
+box.execute([[SELECT length(X'33');]])
+box.execute([[SELECT length(NULL);]])
+
+box.execute([[SELECT likelihood(-1, -1);]])
+box.execute([[SELECT likelihood(1, 1);]])
+box.execute([[SELECT likelihood(1.5, 1.5);]])
+box.execute([[SELECT likelihood(-1.5, -1.5);]])
+box.execute([[SELECT likelihood(true, true);]])
+box.execute([[SELECT likelihood('a', 'a');]])
+box.execute([[SELECT likelihood(X'33', X'33');]])
+box.execute([[SELECT likelihood(NULL, NULL);]])
+box.execute([[SELECT likelihood(NULL, 1);]])
+box.execute([[SELECT likelihood(1, NULL);]])
+
+box.execute([[SELECT likely(-1);]])
+box.execute([[SELECT likely(1);]])
+box.execute([[SELECT likely(1.5);]])
+box.execute([[SELECT likely(-1.5);]])
+box.execute([[SELECT likely(true);]])
+box.execute([[SELECT likely('a');]])
+box.execute([[SELECT likely(X'33');]])
+box.execute([[SELECT likely(NULL);]])
+
+box.execute([[SELECT lower(-1);]])
+box.execute([[SELECT lower(1);]])
+box.execute([[SELECT lower(1.5);]])
+box.execute([[SELECT lower(-1.5);]])
+box.execute([[SELECT lower(true);]])
+box.execute([[SELECT lower('a');]])
+box.execute([[SELECT lower(X'33');]])
+box.execute([[SELECT lower(NULL);]])
+
+box.execute([[SELECT nullif(-1, -1);]])
+box.execute([[SELECT nullif(1, 1);]])
+box.execute([[SELECT nullif(1.5, 1.5);]])
+box.execute([[SELECT nullif(-1.5, -1.5);]])
+box.execute([[SELECT nullif(true, true);]])
+box.execute([[SELECT nullif('a', 'a');]])
+box.execute([[SELECT nullif(X'33', X'33');]])
+box.execute([[SELECT nullif(NULL, NULL);]])
+box.execute([[SELECT nullif(NULL, 1);]])
+box.execute([[SELECT nullif(1, NULL);]])
+
+box.execute([[SELECT position(-1, -1);]])
+box.execute([[SELECT position(1, 1);]])
+box.execute([[SELECT position(1.5, 1.5);]])
+box.execute([[SELECT position(-1.5, -1.5);]])
+box.execute([[SELECT position(true, true);]])
+box.execute([[SELECT position('a', 'a');]])
+box.execute([[SELECT position('a', 1);]])
+box.execute([[SELECT position(1, 'a');]])
+box.execute([[SELECT position(X'33', X'33');]])
+box.execute([[SELECT position(X'33', 1);]])
+box.execute([[SELECT position(NULL, NULL);]])
+box.execute([[SELECT position(NULL, 'a');]])
+box.execute([[SELECT position('a', NULL);]])
+
+box.execute([[SELECT printf(-1);]])
+box.execute([[SELECT printf(1);]])
+box.execute([[SELECT printf(1.5);]])
+box.execute([[SELECT printf(-1.5);]])
+box.execute([[SELECT printf(true);]])
+box.execute([[SELECT printf('a');]])
+box.execute([[SELECT printf(X'33');]])
+box.execute([[SELECT printf(NULL);]])
+
+box.execute([[SELECT quote(-1);]])
+box.execute([[SELECT quote(1);]])
+box.execute([[SELECT quote(1.5);]])
+box.execute([[SELECT quote(-1.5);]])
+box.execute([[SELECT quote(true);]])
+box.execute([[SELECT quote('a');]])
+box.execute([[SELECT quote(X'33');]])
+box.execute([[SELECT quote(NULL);]])
+
+box.execute([[SELECT randomblob(-1);]])
+box.execute([[SELECT randomblob(0);]])
+box.execute([[SELECT randomblob(0.5);]])
+box.execute([[SELECT randomblob(-0.5);]])
+box.execute([[SELECT randomblob(true);]])
+box.execute([[SELECT randomblob('a');]])
+box.execute([[SELECT randomblob(X'33');]])
+box.execute([[SELECT randomblob(NULL);]])
+
+box.execute([[SELECT replace(-1, -1, -1);]])
+box.execute([[SELECT replace(1, 1, 1);]])
+box.execute([[SELECT replace(1.5, 1.5, 1.5);]])
+box.execute([[SELECT replace(-1.5, -1.5, -1.5);]])
+box.execute([[SELECT replace(true, true, true);]])
+box.execute([[SELECT replace('a', 'a', 'a');]])
+box.execute([[SELECT replace('a', 'a', 1);]])
+box.execute([[SELECT replace('a', 1, 'a');]])
+box.execute([[SELECT replace(1, 'a', 'a');]])
+box.execute([[SELECT replace('a', 'a', X'33');]])
+box.execute([[SELECT replace('a', X'33', 'a');]])
+box.execute([[SELECT replace(X'33', 'a', X'33');]])
+box.execute([[SELECT replace(X'33', X'33', 'a');]])
+box.execute([[SELECT replace(X'33', X'33', X'33');]])
+box.execute([[SELECT replace(X'33', X'33', 1);]])
+box.execute([[SELECT replace(X'33', 1, X'33');]])
+box.execute([[SELECT replace(1, X'33', X'33');]])
+box.execute([[SELECT replace(NULL, NULL, NULL);]])
+box.execute([[SELECT replace(NULL, NULL, 'a');]])
+box.execute([[SELECT replace(NULL, 'a', NULL);]])
+box.execute([[SELECT replace(NULL, 'a', 'a');]])
+box.execute([[SELECT replace('a', NULL, NULL);]])
+box.execute([[SELECT replace('a', NULL, 'a');]])
+box.execute([[SELECT replace('a', 'a', NULL);]])
+
+box.execute([[SELECT round(-1, -1);]])
+box.execute([[SELECT round(1, 1);]])
+box.execute([[SELECT round(1.5, 1.5);]])
+box.execute([[SELECT round(-1.5, -1.5);]])
+box.execute([[SELECT round(1.5, true);]])
+box.execute([[SELECT round(true, 1.5);]])
+box.execute([[SELECT round(true, true);]])
+box.execute([[SELECT round('a', 'a');]])
+box.execute([[SELECT round(X'33', X'33');]])
+box.execute([[SELECT round(NULL, NULL);]])
+box.execute([[SELECT round(NULL, 1);]])
+box.execute([[SELECT round(1, NULL);]])
+
+box.execute([[SELECT soundex(-1);]])
+box.execute([[SELECT soundex(1);]])
+box.execute([[SELECT soundex(1.5);]])
+box.execute([[SELECT soundex(-1.5);]])
+box.execute([[SELECT soundex(true);]])
+box.execute([[SELECT soundex('a');]])
+box.execute([[SELECT soundex(X'33');]])
+box.execute([[SELECT soundex(NULL);]])
+
+box.execute([[SELECT substr(-1, -1, -1);]])
+box.execute([[SELECT substr(1, 1, 1);]])
+box.execute([[SELECT substr(1.5, 1.5, 1.5);]])
+box.execute([[SELECT substr(true, true, true);]])
+box.execute([[SELECT substr('a', 'a', 'a');]])
+box.execute([[SELECT substr('a', 'a', 1);]])
+box.execute([[SELECT substr('a', 1, 'a');]])
+box.execute([[SELECT substr('a', 1, 1);]])
+box.execute([[SELECT substr(X'33', X'33', X'33');]])
+box.execute([[SELECT substr(X'33', X'33', 1);]])
+box.execute([[SELECT substr(X'33', 1, X'33');]])
+box.execute([[SELECT substr(X'33', 1, 1);]])
+box.execute([[SELECT substr(1, X'33', 1);]])
+box.execute([[SELECT substr(1, 1, X'33');]])
+box.execute([[SELECT substr(NULL, NULL, NULL);]])
+box.execute([[SELECT substr(NULL, 1, 1);]])
+box.execute([[SELECT substr('a', NULL, 1);]])
+box.execute([[SELECT substr('a', 1, NULL);]])
+
+box.execute([[SELECT typeof(-1);]])
+box.execute([[SELECT typeof(1);]])
+box.execute([[SELECT typeof(1.5);]])
+box.execute([[SELECT typeof(-1.5);]])
+box.execute([[SELECT typeof(true);]])
+box.execute([[SELECT typeof('a');]])
+box.execute([[SELECT typeof(X'33');]])
+box.execute([[SELECT typeof(NULL);]])
+
+box.execute([[SELECT unicode(-1);]])
+box.execute([[SELECT unicode(1);]])
+box.execute([[SELECT unicode(1.5);]])
+box.execute([[SELECT unicode(-1.5);]])
+box.execute([[SELECT unicode(true);]])
+box.execute([[SELECT unicode('a');]])
+box.execute([[SELECT unicode(X'33');]])
+box.execute([[SELECT unicode(NULL);]])
+
+box.execute([[SELECT unlikely(-1);]])
+box.execute([[SELECT unlikely(1);]])
+box.execute([[SELECT unlikely(1.5);]])
+box.execute([[SELECT unlikely(-1.5);]])
+box.execute([[SELECT unlikely(true);]])
+box.execute([[SELECT unlikely('a');]])
+box.execute([[SELECT unlikely(X'33');]])
+box.execute([[SELECT unlikely(NULL);]])
+
+box.execute([[SELECT upper(-1);]])
+box.execute([[SELECT upper(1);]])
+box.execute([[SELECT upper(1.5);]])
+box.execute([[SELECT upper(-1.5);]])
+box.execute([[SELECT upper(true);]])
+box.execute([[SELECT upper('a');]])
+box.execute([[SELECT upper(X'33');]])
+box.execute([[SELECT upper(NULL);]])
+
+box.execute([[SELECT zeroblob(-1);]])
+box.execute([[SELECT zeroblob(1);]])
+box.execute([[SELECT zeroblob(1.5);]])
+box.execute([[SELECT zeroblob(-1.5);]])
+box.execute([[SELECT zeroblob(true);]])
+box.execute([[SELECT zeroblob('a');]])
+box.execute([[SELECT zeroblob(X'33');]])
+box.execute([[SELECT zeroblob(NULL);]])
+
+box.execute([[SELECT trim(-1);]])
+box.execute([[SELECT trim(1);]])
+box.execute([[SELECT trim(1.5);]])
+box.execute([[SELECT trim(-1.5);]])
+box.execute([[SELECT trim(true);]])
+box.execute([[SELECT trim('a');]])
+box.execute([[SELECT trim(X'33');]])
+box.execute([[SELECT trim(NULL);]])
+
+box.execute([[SELECT -1 like -1;]])
+box.execute([[SELECT 1 like 1;]])
+box.execute([[SELECT 1.5 like 1.5;]])
+box.execute([[SELECT true like true;]])
+box.execute([[SELECT 'a' like 'a';]])
+box.execute([[SELECT 'a' like 1;]])
+box.execute([[SELECT 1 like 'a';]])
+box.execute([[SELECT X'33' like X'33';]])
+box.execute([[SELECT NULL like NULL;]])
+box.execute([[SELECT 'a' like NULL;]])
+box.execute([[SELECT NULL like 'a';]])
+
+box.execute([[CREATE TABLE t (i INTEGER PRIMARY KEY, u UNSIGNED, d DOUBLE, o DOUBLE, b BOOLEAN, s STRING, v VARBINARY, n SCALAR);]])
+box.execute([[INSERT INTO t VALUES (-1, 1, 1.5, -1.5, true, 'a', X'33', NULL);]])
+
+box.execute([[SELECT avg(i) FROM t;]])
+box.execute([[SELECT avg(u) FROM t;]])
+box.execute([[SELECT avg(d) FROM t;]])
+box.execute([[SELECT avg(0) FROM t;]])
+box.execute([[SELECT avg(b) FROM t;]])
+box.execute([[SELECT avg(s) FROM t;]])
+box.execute([[SELECT avg(v) FROM t;]])
+box.execute([[SELECT avg(n) FROM t;]])
+
+box.execute([[SELECT count(i) FROM t;]])
+box.execute([[SELECT count(u) FROM t;]])
+box.execute([[SELECT count(d) FROM t;]])
+box.execute([[SELECT count(0) FROM t;]])
+box.execute([[SELECT count(b) FROM t;]])
+box.execute([[SELECT count(s) FROM t;]])
+box.execute([[SELECT count(v) FROM t;]])
+box.execute([[SELECT count(n) FROM t;]])
+
+box.execute([[SELECT group_concat(i) FROM t;]])
+box.execute([[SELECT group_concat(u) FROM t;]])
+box.execute([[SELECT group_concat(d) FROM t;]])
+box.execute([[SELECT group_concat(o) FROM t;]])
+box.execute([[SELECT group_concat(b) FROM t;]])
+box.execute([[SELECT group_concat(s) FROM t;]])
+box.execute([[SELECT group_concat(v) FROM t;]])
+box.execute([[SELECT group_concat(n) FROM t;]])
+box.execute([[SELECT group_concat(i, i) FROM t;]])
+box.execute([[SELECT group_concat(u, u) FROM t;]])
+box.execute([[SELECT group_concat(d, d) FROM t;]])
+box.execute([[SELECT group_concat(o, o) FROM t;]])
+box.execute([[SELECT group_concat(b, b) FROM t;]])
+box.execute([[SELECT group_concat(s, i) FROM t;]])
+box.execute([[SELECT group_concat(s, s) FROM t;]])
+box.execute([[SELECT group_concat(s, v) FROM t;]])
+box.execute([[SELECT group_concat(v, s) FROM t;]])
+box.execute([[SELECT group_concat(n, n) FROM t;]])
+
+box.execute([[SELECT max(i) FROM t;]])
+box.execute([[SELECT max(u) FROM t;]])
+box.execute([[SELECT max(d) FROM t;]])
+box.execute([[SELECT max(o) FROM t;]])
+box.execute([[SELECT max(b) FROM t;]])
+box.execute([[SELECT max(s) FROM t;]])
+box.execute([[SELECT max(v) FROM t;]])
+box.execute([[SELECT max(n) FROM t;]])
+
+box.execute([[SELECT min(i) FROM t;]])
+box.execute([[SELECT min(u) FROM t;]])
+box.execute([[SELECT min(d) FROM t;]])
+box.execute([[SELECT min(o) FROM t;]])
+box.execute([[SELECT min(b) FROM t;]])
+box.execute([[SELECT min(s) FROM t;]])
+box.execute([[SELECT min(v) FROM t;]])
+box.execute([[SELECT min(n) FROM t;]])
+
+box.execute([[SELECT sum(i) FROM t;]])
+box.execute([[SELECT sum(u) FROM t;]])
+box.execute([[SELECT sum(d) FROM t;]])
+box.execute([[SELECT sum(o) FROM t;]])
+box.execute([[SELECT sum(b) FROM t;]])
+box.execute([[SELECT sum(s) FROM t;]])
+box.execute([[SELECT sum(v) FROM t;]])
+box.execute([[SELECT sum(n) FROM t;]])
+
+box.execute([[SELECT total(i) FROM t;]])
+box.execute([[SELECT total(u) FROM t;]])
+box.execute([[SELECT total(d) FROM t;]])
+box.execute([[SELECT total(o) FROM t;]])
+box.execute([[SELECT total(b) FROM t;]])
+box.execute([[SELECT total(s) FROM t;]])
+box.execute([[SELECT total(v) FROM t;]])
+box.execute([[SELECT total(n) FROM t;]])
+
+box.execute([[DROP TABLE t;]])
-- 
2.25.1



More information about the Tarantool-patches mailing list