mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-8910 Wrong metadata or field type for MAX(COALESCE(string_field))
This commit is contained in:
@ -3059,5 +3059,177 @@ DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
SET timestamp=DEFAULT;
|
||||
#
|
||||
# MDEV-8910 Wrong metadata or field type for MAX(COALESCE(string_field))
|
||||
#
|
||||
CREATE TABLE t1 (c1 TINYBLOB, c2 MEDIUMBLOB, c3 BLOB, c4 LONGBLOB);
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3,
|
||||
MAX(COALESCE(c4)) AS c4
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`c1` varbinary(255) DEFAULT NULL,
|
||||
`c2` mediumblob,
|
||||
`c3` blob,
|
||||
`c4` longblob
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3,
|
||||
MAX(COALESCE(c4)) AS c4
|
||||
FROM t1;
|
||||
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
|
||||
def c1 253 255 0 Y 128 31 63
|
||||
def c2 250 16777215 0 Y 128 31 63
|
||||
def c3 252 65535 0 Y 128 31 63
|
||||
def c4 251 4294967295 0 Y 128 31 63
|
||||
c1 c2 c3 c4
|
||||
NULL NULL NULL NULL
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 CHAR(1), c2 CHAR(255)) CHARACTER SET latin1;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`c1` varchar(1) DEFAULT NULL,
|
||||
`c2` varchar(255) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2
|
||||
FROM t1;
|
||||
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
|
||||
def c1 253 1 0 Y 0 31 8
|
||||
def c2 253 255 0 Y 0 31 8
|
||||
c1 c2
|
||||
NULL NULL
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 CHAR(1), c2 CHAR(255)) CHARACTER SET utf8;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL,
|
||||
`c2` varchar(255) CHARACTER SET utf8 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2
|
||||
FROM t1;
|
||||
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
|
||||
def c1 253 1 0 Y 0 31 8
|
||||
def c2 253 255 0 Y 0 31 8
|
||||
c1 c2
|
||||
NULL NULL
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 VARCHAR(1), c2 VARCHAR(255), c3 VARCHAR(20000)) CHARACTER SET latin1;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`c1` varchar(1) DEFAULT NULL,
|
||||
`c2` varchar(255) DEFAULT NULL,
|
||||
`c3` text
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3
|
||||
FROM t1;
|
||||
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
|
||||
def c1 253 1 0 Y 0 31 8
|
||||
def c2 253 255 0 Y 0 31 8
|
||||
def c3 252 20000 0 Y 0 31 8
|
||||
c1 c2 c3
|
||||
NULL NULL NULL
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 VARCHAR(1), c2 VARCHAR(255), c3 VARCHAR(20000)) CHARACTER SET utf8;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL,
|
||||
`c2` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
|
||||
`c3` text CHARACTER SET utf8
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3
|
||||
FROM t1;
|
||||
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
|
||||
def c1 253 1 0 Y 0 31 8
|
||||
def c2 253 255 0 Y 0 31 8
|
||||
def c3 252 60000 0 Y 0 31 8
|
||||
c1 c2 c3
|
||||
NULL NULL NULL
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 ENUM('a')) CHARACTER SET latin1;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`c1` varchar(1) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1
|
||||
FROM t1;
|
||||
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
|
||||
def c1 253 1 0 Y 0 31 8
|
||||
c1
|
||||
NULL
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 ENUM('a')) CHARACTER SET utf8;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1
|
||||
FROM t1;
|
||||
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
|
||||
def c1 253 1 0 Y 0 31 8
|
||||
c1
|
||||
NULL
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# End of 10.1 tests
|
||||
#
|
||||
|
@ -165,6 +165,140 @@ DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
SET timestamp=DEFAULT;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-8910 Wrong metadata or field type for MAX(COALESCE(string_field))
|
||||
--echo #
|
||||
CREATE TABLE t1 (c1 TINYBLOB, c2 MEDIUMBLOB, c3 BLOB, c4 LONGBLOB);
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3,
|
||||
MAX(COALESCE(c4)) AS c4
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
--disable_ps_protocol
|
||||
--enable_metadata
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3,
|
||||
MAX(COALESCE(c4)) AS c4
|
||||
FROM t1;
|
||||
--disable_metadata
|
||||
--enable_ps_protocol
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (c1 CHAR(1), c2 CHAR(255)) CHARACTER SET latin1;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
--disable_ps_protocol
|
||||
--enable_metadata
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2
|
||||
FROM t1;
|
||||
--disable_metadata
|
||||
--enable_ps_protocol
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (c1 CHAR(1), c2 CHAR(255)) CHARACTER SET utf8;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
--disable_ps_protocol
|
||||
--enable_metadata
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2
|
||||
FROM t1;
|
||||
--disable_metadata
|
||||
--enable_ps_protocol
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (c1 VARCHAR(1), c2 VARCHAR(255), c3 VARCHAR(20000)) CHARACTER SET latin1;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
--disable_ps_protocol
|
||||
--enable_metadata
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3
|
||||
FROM t1;
|
||||
--disable_metadata
|
||||
--enable_ps_protocol
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (c1 VARCHAR(1), c2 VARCHAR(255), c3 VARCHAR(20000)) CHARACTER SET utf8;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
--disable_ps_protocol
|
||||
--enable_metadata
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1,
|
||||
MAX(COALESCE(c2)) AS c2,
|
||||
MAX(COALESCE(c3)) AS c3
|
||||
FROM t1;
|
||||
--disable_metadata
|
||||
--enable_ps_protocol
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (c1 ENUM('a')) CHARACTER SET latin1;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
--disable_ps_protocol
|
||||
--enable_metadata
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1
|
||||
FROM t1;
|
||||
--disable_metadata
|
||||
--enable_ps_protocol
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1 (c1 ENUM('a')) CHARACTER SET utf8;
|
||||
CREATE TABLE t2 AS
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1
|
||||
FROM t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
--disable_ps_protocol
|
||||
--enable_metadata
|
||||
SELECT
|
||||
MAX(COALESCE(c1)) AS c1
|
||||
FROM t1;
|
||||
--disable_metadata
|
||||
--enable_ps_protocol
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.1 tests
|
||||
--echo #
|
||||
|
11
sql/item.cc
11
sql/item.cc
@ -5362,17 +5362,6 @@ void Item::make_field(Send_field *tmp_field)
|
||||
}
|
||||
|
||||
|
||||
enum_field_types Item::string_field_type() const
|
||||
{
|
||||
enum_field_types f_type= MYSQL_TYPE_VAR_STRING;
|
||||
if (max_length >= 16777216)
|
||||
f_type= MYSQL_TYPE_LONG_BLOB;
|
||||
else if (max_length >= 65536)
|
||||
f_type= MYSQL_TYPE_MEDIUM_BLOB;
|
||||
return f_type;
|
||||
}
|
||||
|
||||
|
||||
void Item_empty_string::make_field(Send_field *tmp_field)
|
||||
{
|
||||
init_make_field(tmp_field, string_field_type());
|
||||
|
@ -761,7 +761,10 @@ public:
|
||||
/* ... while cmp_type() specifies how it should be compared */
|
||||
Item_result cmp_type() const;
|
||||
virtual Item_result cast_to_int_type() const { return cmp_type(); }
|
||||
virtual enum_field_types string_field_type() const;
|
||||
enum_field_types string_field_type() const
|
||||
{
|
||||
return Type_handler::string_type_handler(max_length)->field_type();
|
||||
}
|
||||
enum_field_types field_type() const;
|
||||
virtual enum Type type() const =0;
|
||||
/*
|
||||
|
@ -1187,7 +1187,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
|
||||
if ((!item->fixed && item->fix_fields(thd, args)) ||
|
||||
(item= args[0])->check_cols(1))
|
||||
return TRUE;
|
||||
decimals=item->decimals;
|
||||
Type_std_attributes::set(args[0]);
|
||||
with_subselect= args[0]->with_subselect;
|
||||
|
||||
Item *item2= item->real_item();
|
||||
@ -1196,13 +1196,13 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
|
||||
else if (item->cmp_type() == TIME_RESULT)
|
||||
set_handler_by_field_type(item2->field_type());
|
||||
else
|
||||
set_handler_by_result_type(item2->result_type());
|
||||
set_handler_by_result_type(item2->result_type(),
|
||||
max_length, collation.collation);
|
||||
|
||||
switch (Item_sum_hybrid::result_type()) {
|
||||
case INT_RESULT:
|
||||
case DECIMAL_RESULT:
|
||||
case STRING_RESULT:
|
||||
max_length= item->max_length;
|
||||
break;
|
||||
case REAL_RESULT:
|
||||
max_length= float_length(decimals);
|
||||
@ -1214,7 +1214,6 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
|
||||
setup_hybrid(thd, args[0], NULL);
|
||||
/* MIN/MAX can return NULL for empty set indepedent of the used column */
|
||||
maybe_null= 1;
|
||||
unsigned_flag=item->unsigned_flag;
|
||||
result_field=0;
|
||||
null_value=1;
|
||||
fix_length_and_dec();
|
||||
|
@ -15,6 +15,7 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "sql_type.h"
|
||||
#include "sql_const.h"
|
||||
|
||||
static Type_handler_tiny type_handler_tiny;
|
||||
static Type_handler_short type_handler_short;
|
||||
@ -41,9 +42,47 @@ static Type_handler_blob type_handler_blob;
|
||||
static Type_handler_geometry type_handler_geometry;
|
||||
|
||||
|
||||
Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
|
||||
:m_type_handler(&type_handler_double)
|
||||
/**
|
||||
This method is used by:
|
||||
- Item_func_set_user_var
|
||||
- Item_func_get_user_var
|
||||
- Item_user_var_as_out_param
|
||||
- Item_func_udf_str
|
||||
|
||||
TODO: type_handler_adjusted_to_max_octet_length() and string_type_handler()
|
||||
provide very similar functionality, to properly choose between
|
||||
VARCHAR/VARBINARY vs TEXT/BLOB variations taking into accoung maximum
|
||||
possible octet length.
|
||||
|
||||
We should probably get rid of either of them and use the same method
|
||||
all around the code.
|
||||
*/
|
||||
const Type_handler *
|
||||
Type_handler::string_type_handler(uint max_octet_length) const
|
||||
{
|
||||
if (max_octet_length >= 16777216)
|
||||
return &type_handler_long_blob;
|
||||
else if (max_octet_length >= 65536)
|
||||
return &type_handler_medium_blob;
|
||||
return &type_handler_varchar;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This method is used by Item_sum_hybrid, e.g. MAX(item), MIN(item).
|
||||
*/
|
||||
const Type_handler *
|
||||
Type_handler_string_result::type_handler_adjusted_to_max_octet_length(
|
||||
uint max_octet_length,
|
||||
CHARSET_INFO *cs) const
|
||||
{
|
||||
if (max_octet_length / cs->mbmaxlen <= CONVERT_IF_BIGGER_TO_BLOB)
|
||||
return &type_handler_varchar; // See also Item::too_big_for_varchar()
|
||||
if (max_octet_length >= 16777216)
|
||||
return &type_handler_long_blob;
|
||||
else if (max_octet_length >= 65536)
|
||||
return &type_handler_medium_blob;
|
||||
return &type_handler_blob;
|
||||
}
|
||||
|
||||
|
||||
@ -64,6 +103,12 @@ Type_handler_hybrid_field_type::get_handler_by_result_type(Item_result type)
|
||||
}
|
||||
|
||||
|
||||
Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
|
||||
:m_type_handler(&type_handler_double)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *
|
||||
Type_handler_hybrid_field_type::get_handler_by_field_type(enum_field_types type)
|
||||
const
|
||||
|
@ -25,12 +25,19 @@
|
||||
|
||||
class Type_handler
|
||||
{
|
||||
protected:
|
||||
const Type_handler *string_type_handler(uint max_octet_length) const;
|
||||
public:
|
||||
virtual enum_field_types field_type() const= 0;
|
||||
virtual Item_result result_type() const= 0;
|
||||
virtual Item_result cmp_type() const= 0;
|
||||
virtual const Type_handler*
|
||||
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
|
||||
CHARSET_INFO *cs) const
|
||||
{ return this; }
|
||||
};
|
||||
|
||||
|
||||
/*** Abstract classes for every XXX_RESULT */
|
||||
|
||||
class Type_handler_real_result: public Type_handler
|
||||
@ -70,6 +77,9 @@ class Type_handler_string_result: public Type_handler
|
||||
public:
|
||||
Item_result result_type() const { return STRING_RESULT; }
|
||||
Item_result cmp_type() const { return STRING_RESULT; }
|
||||
const Type_handler *
|
||||
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
|
||||
CHARSET_INFO *cs) const;
|
||||
};
|
||||
|
||||
|
||||
@ -283,10 +293,27 @@ public:
|
||||
{
|
||||
return (m_type_handler= get_handler_by_result_type(type));
|
||||
}
|
||||
const Type_handler *set_handler_by_result_type(Item_result type,
|
||||
uint max_octet_length,
|
||||
CHARSET_INFO *cs)
|
||||
{
|
||||
m_type_handler= get_handler_by_result_type(type);
|
||||
return m_type_handler=
|
||||
m_type_handler->type_handler_adjusted_to_max_octet_length(max_octet_length,
|
||||
cs);
|
||||
}
|
||||
const Type_handler *set_handler_by_field_type(enum_field_types type)
|
||||
{
|
||||
return (m_type_handler= get_handler_by_field_type(type));
|
||||
}
|
||||
const Type_handler *
|
||||
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
|
||||
CHARSET_INFO *cs) const
|
||||
{
|
||||
return
|
||||
m_type_handler->type_handler_adjusted_to_max_octet_length(max_octet_length,
|
||||
cs);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* SQL_TYPE_H_INCLUDED */
|
||||
|
Reference in New Issue
Block a user