From: imeevma@tarantool.org To: korablev@tarantool.org, tsafin@tarantool.org, tarantool-patches@dev.tarantool.org Subject: [Tarantool-patches] [PATCH v4 1/3] sql: fix CAST() from STRING to INTEGER Date: Fri, 27 Mar 2020 14:33:40 +0300 [thread overview] Message-ID: <01024a2279b5c030f272d2a97ce8bd83f8ababc3.1585308644.git.imeevma@gmail.com> (raw) In-Reply-To: <cover.1585308644.git.imeevma@gmail.com> Prior to this patch, STRING, which contains the DOUBLE value, could be cast to INTEGER. This was done by converting STRING to DOUBLE and then converting this DOUBLE value to INTEGER. This may affect the accuracy of CAST(), so it was forbidden. Before patch: box.execute("SELECT CAST('111.1' as INTEGER);") Result: 111 After patch: box.execute("SELECT CAST('1.1' as INTEGER);") Result: 'Type mismatch: can not convert 1.1 to integer' box.execute("SELECT CAST('1.0' as INTEGER);") Result: 'Type mismatch: can not convert 1.0 to integer' box.execute("SELECT CAST('1.' as INTEGER);") Result: 'Type mismatch: can not convert 1. to integer' Part of #4766 --- src/box/sql/vdbemem.c | 16 +++++- .../gh-4766-wrong-cast-from-blob-to-int.test.lua | 57 ++++++++++++++++++++++ test/sql/types.result | 23 ++++----- 3 files changed, 80 insertions(+), 16 deletions(-) create mode 100755 test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c index aad030d..de1d9c3 100644 --- a/src/box/sql/vdbemem.c +++ b/src/box/sql/vdbemem.c @@ -696,7 +696,7 @@ sqlVdbeMemCast(Mem * pMem, enum field_type type) return -1; case FIELD_TYPE_INTEGER: case FIELD_TYPE_UNSIGNED: - if ((pMem->flags & MEM_Blob) != 0) { + if ((pMem->flags & (MEM_Blob | MEM_Str)) != 0) { bool is_neg; int64_t val; if (sql_atoi64(pMem->z, &val, &is_neg, pMem->n) != 0) @@ -711,8 +711,20 @@ sqlVdbeMemCast(Mem * pMem, enum field_type type) MemSetTypeFlag(pMem, MEM_UInt); return 0; } - if (sqlVdbeMemIntegerify(pMem) != 0) + if ((pMem->flags & MEM_Real) != 0) { + double d; + if (sqlVdbeRealValue(pMem, &d) != 0) + return -1; + if (d < INT64_MAX && d >= INT64_MIN) { + mem_set_int(pMem, d, d <= -1); + return 0; + } + if (d >= INT64_MAX && d < UINT64_MAX) { + mem_set_u64(pMem, d); + return 0; + } return -1; + } if (type == FIELD_TYPE_UNSIGNED && (pMem->flags & MEM_UInt) == 0) return -1; 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 new file mode 100755 index 0000000..0865c4e --- /dev/null +++ b/test/sql-tap/gh-4766-wrong-cast-from-blob-to-int.test.lua @@ -0,0 +1,57 @@ +#!/usr/bin/env tarantool +test = require("sqltester") +test:plan(6) + +-- +-- Make sure that STRING or BLOB that contains DOUBLE value cannot +-- be cast to INTEGER. +-- +test:do_catchsql_test( + "gh-4766-1", + [[ + SELECT CAST('1.1' AS INTEGER) + ]], { + 1, "Type mismatch: can not convert 1.1 to integer" + }) + +test:do_catchsql_test( + "gh-4766-2", + [[ + SELECT CAST(x'312e31' AS INTEGER) + ]], { + 1, "Type mismatch: can not convert varbinary to integer" + }) + +test:do_catchsql_test( + "gh-4766-3", + [[ + SELECT CAST('2.0' AS INTEGER) + ]], { + 1, "Type mismatch: can not convert 2.0 to integer" + }) + +test:do_catchsql_test( + "gh-4766-4", + [[ + SELECT CAST(x'322e30' AS INTEGER) + ]], { + 1, "Type mismatch: can not convert varbinary to integer" + }) + +test:do_catchsql_test( + "gh-4766-5", + [[ + SELECT CAST('2.' AS INTEGER) + ]], { + 1, "Type mismatch: can not convert 2. to integer" + }) + +test:do_catchsql_test( + "gh-4766-6", + [[ + SELECT CAST(x'322e' AS INTEGER) + ]], { + 1, "Type mismatch: can not convert varbinary to integer" + }) + +test:finish_test() diff --git a/test/sql/types.result b/test/sql/types.result index 38e4385..54aff46 100644 --- a/test/sql/types.result +++ b/test/sql/types.result @@ -269,11 +269,8 @@ box.space.T1:drop() -- box.execute("SELECT CAST('1.123' AS INTEGER);") --- -- metadata: - - name: CAST('1.123' AS INTEGER) - type: integer - rows: - - [1] +- null +- 'Type mismatch: can not convert 1.123 to integer' ... box.execute("CREATE TABLE t1 (f TEXT PRIMARY KEY);") --- @@ -285,13 +282,8 @@ box.execute("INSERT INTO t1 VALUES('0.0'), ('1.5'), ('3.9312453');") ... box.execute("SELECT CAST(f AS INTEGER) FROM t1;") --- -- metadata: - - name: CAST(f AS INTEGER) - type: integer - rows: - - [0] - - [1] - - [3] +- null +- 'Type mismatch: can not convert 0.0 to integer' ... box.space.T1:drop() --- @@ -1105,8 +1097,11 @@ box.execute("SELECT CAST(1.5 AS UNSIGNED);") ... box.execute("SELECT CAST(-1.5 AS UNSIGNED);") --- -- null -- 'Type mismatch: can not convert -1 to unsigned' +- metadata: + - name: CAST(-1.5 AS UNSIGNED) + type: unsigned + rows: + - [-1] ... box.execute("SELECT CAST(true AS UNSIGNED);") --- -- 2.7.4
next prev parent reply other threads:[~2020-03-27 11:33 UTC|newest] Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-03-27 11:33 [Tarantool-patches] [PATCH v4 0/3] sql: fix CAST() from BLOB " imeevma 2020-03-27 11:33 ` imeevma [this message] 2020-03-27 16:46 ` [Tarantool-patches] [PATCH v4 1/3] sql: fix CAST() from STRING " Nikita Pettik 2020-04-10 10:39 ` Mergen Imeev 2020-04-10 10:43 ` Mergen Imeev 2020-04-10 13:05 ` Nikita Pettik 2020-04-10 17:06 ` Imeev Mergen 2020-04-15 11:13 ` Nikita Pettik 2020-04-10 12:46 ` Nikita Pettik 2020-04-10 13:05 ` Imeev Mergen 2020-03-27 11:33 ` [Tarantool-patches] [PATCH v4 2/3] sql: fix implicit cast " imeevma 2020-03-27 16:54 ` Nikita Pettik 2020-04-10 10:41 ` Mergen Imeev 2020-04-10 12:57 ` Nikita Pettik 2020-04-10 18:09 ` Mergen Imeev 2020-03-27 11:33 ` [Tarantool-patches] [PATCH v4 3/3] sql: add '\0' to the BLOB when it is cast " imeevma 2020-03-27 16:54 ` Nikita Pettik 2020-04-16 0:03 ` [Tarantool-patches] [PATCH v4 0/3] sql: fix CAST() from BLOB " Nikita Pettik
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=01024a2279b5c030f272d2a97ce8bd83f8ababc3.1585308644.git.imeevma@gmail.com \ --to=imeevma@tarantool.org \ --cc=korablev@tarantool.org \ --cc=tarantool-patches@dev.tarantool.org \ --cc=tsafin@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH v4 1/3] sql: fix CAST() from STRING to INTEGER' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox