diff options
author | Alexander Barkov <bar@mariadb.com> | 2019-08-09 14:18:13 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2019-08-09 14:18:13 +0400 |
commit | 43882e764d6867c6855b1ff057758a3f08b25c55 (patch) | |
tree | 002b065eb90bc438c56ee6ff321b86c4941eec61 | |
parent | 2dac1235150681433bdf6480e479e2f787b40f8b (diff) | |
download | mariadb-git-43882e764d6867c6855b1ff057758a3f08b25c55.tar.gz |
MDEV-20303 SPACE(-1) returns a wrong data type
-rw-r--r-- | mysql-test/main/func_str.result | 68 | ||||
-rw-r--r-- | mysql-test/main/func_str.test | 47 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 100 |
3 files changed, 158 insertions, 57 deletions
diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index eb00837eaaf..2d86d384288 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -5073,16 +5073,84 @@ DROP TABLE t1; CREATE OR REPLACE TABLE t1 (i BIGINT); INSERT INTO t1 VALUES (42); CREATE OR REPLACE TABLE t2 AS SELECT +REPEAT(i,NULL) AS cn, REPEAT(i,0) AS c0, REPEAT(i,-1) AS c1 FROM t1; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( + `cn` char(0) CHARACTER SET utf8 DEFAULT NULL, `c0` char(0) CHARACTER SET utf8 DEFAULT NULL, `c1` char(0) CHARACTER SET utf8 DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1, t2; # +# MDEV-20303 SPACE(-1) returns a wrong data type +# +CREATE TABLE t1 (i BIGINT); +INSERT INTO t1 VALUES (42); +CREATE TABLE t2 AS SELECT +SPACE(NULL) AS cn, +SPACE(0) AS c0, +SPACE(-1) AS c1 +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `cn` char(0) CHARACTER SET utf8 DEFAULT NULL, + `c0` char(0) CHARACTER SET utf8 DEFAULT NULL, + `c1` char(0) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1, t2; +CREATE TABLE t1 (i BIGINT); +INSERT INTO t1 VALUES (42); +CREATE TABLE t2 AS SELECT +LPAD(i,NULL,'a') AS cn, +LPAD(i,0,'a') AS c0, +LPAD(i,-1,'a') AS c1 +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `cn` char(0) CHARACTER SET utf8 DEFAULT NULL, + `c0` char(0) CHARACTER SET utf8 DEFAULT NULL, + `c1` char(0) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1, t2; +CREATE TABLE t1 (i BIGINT); +INSERT INTO t1 VALUES (42); +CREATE TABLE t2 AS SELECT +RPAD(i,NULL,'a') AS cn, +RPAD(i,0,'a') AS c0, +RPAD(i,-1,'a') AS c1 +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `cn` char(0) CHARACTER SET utf8 DEFAULT NULL, + `c0` char(0) CHARACTER SET utf8 DEFAULT NULL, + `c1` char(0) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1, t2; +CREATE TABLE t1 (i BIGINT); +INSERT INTO t1 VALUES (42); +CREATE TABLE t2 AS SELECT +LEFT(i,NULL) AS cn, +LEFT(i,0) AS c0, +LEFT(i,18446744073709551615) AS c1 +FROM t1; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `cn` char(0) CHARACTER SET utf8 DEFAULT NULL, + `c0` char(0) CHARACTER SET utf8 DEFAULT NULL, + `c1` varchar(20) CHARACTER SET utf8 DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +SELECT c1 FROM t2; +c1 +42 +DROP TABLE t1, t2; +# # End of 10.3 tests # diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test index 135d00bcd8c..60a142cda20 100644 --- a/mysql-test/main/func_str.test +++ b/mysql-test/main/func_str.test @@ -2035,6 +2035,7 @@ DROP TABLE t1; CREATE OR REPLACE TABLE t1 (i BIGINT); INSERT INTO t1 VALUES (42); CREATE OR REPLACE TABLE t2 AS SELECT + REPEAT(i,NULL) AS cn, REPEAT(i,0) AS c0, REPEAT(i,-1) AS c1 FROM t1; @@ -2043,5 +2044,51 @@ DROP TABLE t1, t2; --echo # +--echo # MDEV-20303 SPACE(-1) returns a wrong data type +--echo # + +CREATE TABLE t1 (i BIGINT); +INSERT INTO t1 VALUES (42); +CREATE TABLE t2 AS SELECT + SPACE(NULL) AS cn, + SPACE(0) AS c0, + SPACE(-1) AS c1 +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + +CREATE TABLE t1 (i BIGINT); +INSERT INTO t1 VALUES (42); +CREATE TABLE t2 AS SELECT + LPAD(i,NULL,'a') AS cn, + LPAD(i,0,'a') AS c0, + LPAD(i,-1,'a') AS c1 +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + +CREATE TABLE t1 (i BIGINT); +INSERT INTO t1 VALUES (42); +CREATE TABLE t2 AS SELECT + RPAD(i,NULL,'a') AS cn, + RPAD(i,0,'a') AS c0, + RPAD(i,-1,'a') AS c1 +FROM t1; +SHOW CREATE TABLE t2; +DROP TABLE t1, t2; + +CREATE TABLE t1 (i BIGINT); +INSERT INTO t1 VALUES (42); +CREATE TABLE t2 AS SELECT + LEFT(i,NULL) AS cn, + LEFT(i,0) AS c0, + LEFT(i,18446744073709551615) AS c1 +FROM t1; +SHOW CREATE TABLE t2; +SELECT c1 FROM t2; +DROP TABLE t1, t2; + + +--echo # --echo # End of 10.3 tests --echo # diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 65acc071237..b170634d864 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -58,6 +58,27 @@ C_MODE_END size_t username_char_length= 80; + +class Repeat_count +{ + ulonglong m_count; +public: + Repeat_count(Item *item) + :m_count(0) + { + Longlong_hybrid nr= item->to_longlong_hybrid(); + if (!item->null_value && !nr.neg()) + { + // Assume that the maximum length of a String is < INT_MAX32 + m_count= (ulonglong) nr.value(); + if (m_count > (ulonglong) INT_MAX32) + m_count= (ulonglong) INT_MAX32; + } + } + ulonglong count() const { return m_count; } +}; + + /* For the Items which have only val_str_ascii() method and don't have their own "native" val_str(), @@ -1635,13 +1656,10 @@ String *Item_func_left::val_str(String *str) void Item_str_func::left_right_max_length() { uint32 char_length= args[0]->max_char_length(); - if (args[1]->const_item()) + if (args[1]->const_item() && !args[1]->is_expensive()) { - int length= (int) args[1]->val_int(); - if (args[1]->null_value || length <= 0) - char_length=0; - else - set_if_smaller(char_length, (uint) length); + Repeat_count tmp(args[1]); + set_if_smaller(char_length, (uint) tmp.count()); } fix_char_length(char_length); } @@ -2969,25 +2987,14 @@ bool Item_func_repeat::fix_length_and_dec() DBUG_ASSERT(collation.collation != NULL); if (args[1]->const_item() && !args[1]->is_expensive()) { - Longlong_hybrid nr= args[1]->to_longlong_hybrid(); - if (args[1]->null_value || nr.neg()) - fix_char_length(0); - else - { - /* Assumes that the maximum length of a String is < INT_MAX32. */ - longlong count= nr.value(); - if (count > INT_MAX32) - count= INT_MAX32; - ulonglong char_length= (ulonglong) args[0]->max_char_length() * count; - fix_char_length_ulonglong(char_length); - } - } - else - { - max_length= MAX_BLOB_WIDTH; - maybe_null= 1; + Repeat_count tmp(args[1]); + ulonglong char_length= (ulonglong) args[0]->max_char_length() * tmp.count(); + fix_char_length_ulonglong(char_length); + return false; } - return FALSE; + max_length= MAX_BLOB_WIDTH; + maybe_null= true; + return false; } /** @@ -3052,26 +3059,14 @@ err: bool Item_func_space::fix_length_and_dec() { collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); - if (args[0]->const_item()) + if (args[0]->const_item() && !args[0]->is_expensive()) { - /* must be longlong to avoid truncation */ - longlong count= args[0]->val_int(); - if (args[0]->null_value) - goto end; - /* - Assumes that the maximum length of a String is < INT_MAX32. - Set here so that rest of code sees out-of-bound value as such. - */ - if (count > INT_MAX32) - count= INT_MAX32; - fix_char_length_ulonglong(count); - return FALSE; + fix_char_length_ulonglong(Repeat_count(args[0]).count()); + return false; } - -end: max_length= MAX_BLOB_WIDTH; - maybe_null= 1; - return FALSE; + maybe_null= true; + return false; } @@ -3182,24 +3177,15 @@ bool Item_func_pad::fix_length_and_dec() pad_str.append(" ", 1); } - if (args[1]->const_item()) - { - ulonglong char_length= (ulonglong) args[1]->val_int(); - DBUG_ASSERT(collation.collation->mbmaxlen > 0); - /* Assumes that the maximum length of a String is < INT_MAX32. */ - /* Set here so that rest of code sees out-of-bound value as such. */ - if (args[1]->null_value) - char_length= 0; - else if (char_length > INT_MAX32) - char_length= INT_MAX32; - fix_char_length_ulonglong(char_length); - } - else + DBUG_ASSERT(collation.collation->mbmaxlen > 0); + if (args[1]->const_item() && !args[1]->is_expensive()) { - max_length= MAX_BLOB_WIDTH; - maybe_null= 1; + fix_char_length(Repeat_count(args[1]).count()); + return false; } - return FALSE; + max_length= MAX_BLOB_WIDTH; + maybe_null= true; + return false; } |