Tarantool development patches archive
 help / color / mirror / Atom feed
From: Mergen Imeev via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: v.shpilevoy@tarantool.org
Cc: tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH v2 1/4] sql: truncate values in type mismatch error
Date: Mon,  5 Jul 2021 18:27:50 +0300
Message-ID: <dadda45fb1a3e4b2dbc1c853f936826ce3b39b47.1625498636.git.imeevma@gmail.com> (raw)
In-Reply-To: <cover.1625498636.git.imeevma@gmail.com>

STRING, MAP, and ARRAY values that are too long can make the type
mismatch error description less descriptive than necessary. This patch
truncates values that are too long and adds "..." to indicate that the
value has been truncated.

Part of #6176
---
 src/box/sql/mem.c                             | 22 ++++++---
 src/box/sql/mem.h                             |  3 +-
 ...-4766-wrong-cast-from-blob-to-int.test.lua |  7 +--
 test/sql-tap/sql-errors.test.lua              | 47 ++++++++++++++++++-
 test/sql/types.result                         |  6 +--
 5 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/src/box/sql/mem.c b/src/box/sql/mem.c
index 6f3bf52e5..630f1a135 100644
--- a/src/box/sql/mem.c
+++ b/src/box/sql/mem.c
@@ -56,6 +56,7 @@ sqlVdbeMemGrow(struct Mem *pMem, int n, int preserve);
 
 enum {
 	BUF_SIZE = 32,
+	STR_VALUE_MAX_LEN = 128,
 };
 
 bool
@@ -71,26 +72,35 @@ mem_is_field_compatible(const struct Mem *mem, enum field_type type)
 const char *
 mem_str(const struct Mem *mem)
 {
-	char buf[BUF_SIZE];
+	char buf[STR_VALUE_MAX_LEN + 1];
 	switch (mem->type) {
 	case MEM_TYPE_NULL:
 		return "NULL";
 	case MEM_TYPE_STR:
-		if ((mem->flags & MEM_Term) != 0)
-			return mem->z;
+		if (mem->n > STR_VALUE_MAX_LEN) {
+			memcpy(buf, mem->z, STR_VALUE_MAX_LEN);
+			buf[STR_VALUE_MAX_LEN] = '\0';
+			return tt_sprintf("%s...", buf);
+		}
 		return tt_cstr(mem->z, mem->n);
 	case MEM_TYPE_INT:
 		return tt_sprintf("%lld", mem->u.i);
 	case MEM_TYPE_UINT:
 		return tt_sprintf("%llu", mem->u.u);
 	case MEM_TYPE_DOUBLE:
-		sql_snprintf(BUF_SIZE, &buf[0], "%!.15g", mem->u.r);
+		sql_snprintf(STR_VALUE_MAX_LEN + 1, buf, "%!.15g", mem->u.r);
 		return tt_sprintf("%s", buf);
 	case MEM_TYPE_BIN:
 		return "varbinary";
 	case MEM_TYPE_MAP:
-	case MEM_TYPE_ARRAY:
-		return mp_str(mem->z);
+	case MEM_TYPE_ARRAY: {
+		const char *str = mp_str(mem->z);
+		if (strlen(str) <= STR_VALUE_MAX_LEN)
+			return str;
+		memcpy(buf, str, STR_VALUE_MAX_LEN);
+		buf[STR_VALUE_MAX_LEN] = '\0';
+		return tt_sprintf("%s...", buf);
+	}
 	case MEM_TYPE_UUID:
 		return tt_uuid_str(&mem->u.uuid);
 	case MEM_TYPE_BOOL:
diff --git a/src/box/sql/mem.h b/src/box/sql/mem.h
index b3cd5c545..0bbc63e68 100644
--- a/src/box/sql/mem.h
+++ b/src/box/sql/mem.h
@@ -264,7 +264,8 @@ mem_is_field_compatible(const struct Mem *mem, enum field_type type);
 
 /**
  * Return a string that represent content of MEM. String is either allocated
- * using static_alloc() of just a static variable.
+ * using static_alloc() of just a static variable. This function should only be
+ * used for debugging or displaying MEM values in errors.
  */
 const char *
 mem_str(const struct Mem *mem);
diff --git a/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua b/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua
index da8c2dcd6..28cf50184 100755
--- a/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua
+++ b/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua
@@ -34,12 +34,7 @@ test:do_catchsql_test(
     "SELECT CAST('" .. long_str .. "1234'" .. " AS INTEGER);", {
         1, "Type mismatch: can not convert 000000000000000000000000000000000" ..
         "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "0000000000000000000000000000000000000000000000000000000000000000000" ..
-        "000000000000000000000000000000000000000000000"
+        "0000000000000000000000000000... to integer"
     })
 
 test:finish_test()
diff --git a/test/sql-tap/sql-errors.test.lua b/test/sql-tap/sql-errors.test.lua
index 469193a2b..96ee683eb 100755
--- a/test/sql-tap/sql-errors.test.lua
+++ b/test/sql-tap/sql-errors.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 local test = require("sqltester")
-test:plan(72)
+test:plan(76)
 
 test:execsql([[
 	CREATE TABLE t0 (i INT PRIMARY KEY, a INT);
@@ -780,4 +780,49 @@ test:do_catchsql_test(
 		-- </sql-errors-2.9>
 	})
 
+--
+-- gh-6176: Make sure that type mismatch error description with too long STRING,
+-- MAP or ARRAY is printed correctly.
+--
+local str1 = string.rep('a', 200)
+local str2 = string.rep('ы', 200)
+
+test:do_catchsql_test(
+	"sql-errors-3.1",
+	"SELECT CAST('"..str1.."'AS UNSIGNED);", {
+		1, "Type mismatch: can not convert aaaaaaaaaaaaaaaaaaaaaaaaaa"..
+		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..
+		"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... to unsigned"
+	})
+
+test:do_catchsql_test(
+	"sql-errors-3.2",
+	"SELECT CAST('"..str2.."'AS UNSIGNED);", {
+		1, "Type mismatch: can not convert ыыыыыыыыыыыыыыыыыыыыыыыыыы"..
+		"ыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыыы... to unsigned"
+	})
+
+local format = {{'I', 'integer'}, {'A', 'array'}, {'M', 'map'}}
+local s = box.schema.space.create('TEST', {format=format})
+s:create_index('I')
+s:insert({1, {str1}, {a = 1, b = str1}})
+
+test:do_catchsql_test(
+	"sql-errors-3.3",
+	"SELECT CAST(a AS UNSIGNED) from test;", {
+		1, 'Type mismatch: can not convert ["aaaaaaaaaaaaaaaaaaaaaaaa'..
+		'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'..
+		'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... to unsigned'
+	})
+
+test:do_catchsql_test(
+	"sql-errors-3.4",
+	"SELECT CAST(m AS UNSIGNED) from test;", {
+		1, 'Type mismatch: can not convert {"a": 1, "b": "aaaaaaaaaaa'..
+		'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'..
+		'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... to unsigned'
+	})
+
+test:execsql('DROP TABLE test;')
+
 test:finish_test()
diff --git a/test/sql/types.result b/test/sql/types.result
index 687ca3b15..a46967158 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -1651,11 +1651,7 @@ box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
 - null
 - 'Type mismatch: can not convert [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
-  35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
-  55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
-  75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
-  95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
-  112, 113, 114, 115, 116, 117, 11'
+  ... to scalar'
 ...
 s:drop()
 ---
-- 
2.25.1


  reply	other threads:[~2021-07-05 15:28 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-05 15:27 [Tarantool-patches] [PATCH v2 0/4] sql: fix description of " Mergen Imeev via Tarantool-patches
2021-07-05 15:27 ` Mergen Imeev via Tarantool-patches [this message]
2021-07-07 22:09   ` [Tarantool-patches] [PATCH v2 1/4] sql: truncate values in " Vladislav Shpilevoy via Tarantool-patches
2021-07-12  8:50     ` Mergen Imeev via Tarantool-patches
2021-07-05 15:27 ` [Tarantool-patches] [PATCH v2 2/4] sql: properly show " Mergen Imeev via Tarantool-patches
2021-07-07 22:09   ` Vladislav Shpilevoy via Tarantool-patches
2021-07-12  8:56     ` Mergen Imeev via Tarantool-patches
2021-07-05 15:27 ` [Tarantool-patches] [PATCH v2 3/4] sql: use proper type names in error descriptions Mergen Imeev via Tarantool-patches
2021-07-05 15:27 ` [Tarantool-patches] [PATCH v2 4/4] sql: make type mismatch error more informative Mergen Imeev via Tarantool-patches
2021-07-07 22:10   ` Vladislav Shpilevoy via Tarantool-patches
2021-07-12  8:58     ` Mergen Imeev via Tarantool-patches
2021-07-12 21:38 ` [Tarantool-patches] [PATCH v2 0/4] sql: fix description of type mismatch error Vladislav Shpilevoy via Tarantool-patches
2021-07-13  7:03 [Tarantool-patches] [PATCH v2 0/4] sql: fix description of type mismatch errors Mergen Imeev via Tarantool-patches
2021-07-13  7:03 ` [Tarantool-patches] [PATCH v2 1/4] sql: truncate values in type mismatch error Mergen Imeev via Tarantool-patches
2021-07-13  8:51   ` Timur Safin via Tarantool-patches

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=dadda45fb1a3e4b2dbc1c853f936826ce3b39b47.1625498636.git.imeevma@gmail.com \
    --to=tarantool-patches@dev.tarantool.org \
    --cc=imeevma@tarantool.org \
    --cc=v.shpilevoy@tarantool.org \
    /path/to/YOUR_REPLY

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

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

Tarantool development patches archive

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://lists.tarantool.org/tarantool-patches/0 tarantool-patches/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 tarantool-patches tarantool-patches/ https://lists.tarantool.org/tarantool-patches \
		tarantool-patches@dev.tarantool.org.
	public-inbox-index tarantool-patches

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git