summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-08-09 14:18:13 +0400
committerAlexander Barkov <bar@mariadb.com>2019-08-09 14:18:13 +0400
commit43882e764d6867c6855b1ff057758a3f08b25c55 (patch)
tree002b065eb90bc438c56ee6ff321b86c4941eec61
parent2dac1235150681433bdf6480e479e2f787b40f8b (diff)
downloadmariadb-git-43882e764d6867c6855b1ff057758a3f08b25c55.tar.gz
MDEV-20303 SPACE(-1) returns a wrong data type
-rw-r--r--mysql-test/main/func_str.result68
-rw-r--r--mysql-test/main/func_str.test47
-rw-r--r--sql/item_strfunc.cc100
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;
}