Skip to content
Permalink
Browse files

MDEV-20303 SPACE(-1) returns a wrong data type

  • Loading branch information...
abarkov committed Aug 9, 2019
1 parent 2dac123 commit 43882e764d6867c6855b1ff057758a3f08b25c55
Showing with 158 additions and 57 deletions.
  1. +68 −0 mysql-test/main/func_str.result
  2. +47 −0 mysql-test/main/func_str.test
  3. +43 −57 sql/item_strfunc.cc
@@ -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
#
@@ -2035,13 +2035,60 @@ 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;
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 #
@@ -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 @@ String *Item_func_repeat::val_str(String *str)
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;
}


0 comments on commit 43882e7

Please sign in to comment.
You can’t perform that action at this time.