Commit eb196384 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-32244 Wrong bit encoding using COALESCE

When aggregating pairs BIT+NULL and NULL+BIT for result, e.g.
in COALESCE(), preserve the BIT data type (ignore explicit NULLs).

The same fix applied to YEAR.
parent b1c8ea83
......@@ -1859,5 +1859,25 @@ cc 18446744073709551615
cr 18446744073709551615
ct 18446744073709551615
#
# MDEV-32244 Wrong bit encoding using COALESCE
#
CREATE TABLE t1 (c1 BIT);
INSERT INTO t1 (c1) VALUES (0x01);
CREATE TABLE t2 AS SELECT
c1,
COALESCE(c1, c1) AS c2,
COALESCE(c1, null) AS c3,
COALESCE(null, c1) AS c4 FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` bit(1) DEFAULT NULL,
`c2` bit(1) DEFAULT NULL,
`c3` bit(1) DEFAULT NULL,
`c4` bit(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
DROP TABLE t2;
DROP TABLE t1;
#
# End of 10.4 tests
#
......@@ -543,6 +543,22 @@ DELIMITER ;$$
--horizontal_results
--echo #
--echo # MDEV-32244 Wrong bit encoding using COALESCE
--echo #
CREATE TABLE t1 (c1 BIT);
INSERT INTO t1 (c1) VALUES (0x01);
CREATE TABLE t2 AS SELECT
c1,
COALESCE(c1, c1) AS c2,
COALESCE(c1, null) AS c3,
COALESCE(null, c1) AS c4 FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -675,5 +675,25 @@ FLOOR(a) int(4) unsigned YES NULL
CEILING(a) int(4) unsigned YES NULL
DROP TABLE t2,t1;
#
# MDEV-32244 Wrong bit encoding using COALESCE
#
CREATE TABLE t1 (c1 YEAR);
INSERT INTO t1 (c1) VALUES (0x01);
CREATE TABLE t2 AS SELECT
c1,
COALESCE(c1, c1) AS c2,
COALESCE(c1, null) AS c3,
COALESCE(null, c1) AS c4 FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` year(4) DEFAULT NULL,
`c2` year(4) DEFAULT NULL,
`c3` year(4) DEFAULT NULL,
`c4` year(4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
DROP TABLE t2;
DROP TABLE t1;
#
# End of 10.4 tests
#
......@@ -354,6 +354,20 @@ CREATE TABLE t2 AS SELECT a, ROUND(a), TRUNCATE(a,0), FLOOR(a), CEILING(a) FROM
DESC t2;
DROP TABLE t2,t1;
--echo #
--echo # MDEV-32244 Wrong bit encoding using COALESCE
--echo #
CREATE TABLE t1 (c1 YEAR);
INSERT INTO t1 (c1) VALUES (0x01);
CREATE TABLE t2 AS SELECT
c1,
COALESCE(c1, c1) AS c2,
COALESCE(c1, null) AS c3,
COALESCE(null, c1) AS c4 FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
......
......@@ -1588,6 +1588,7 @@ Type_handler::bit_and_int_mixture_handler(uint max_char_length)
Note, independently from "treat_bit_as_number":
- a single BIT argument gives BIT as a result
- two BIT couterparts give BIT as a result
- (BIT + explicit NULL) or (explicit NULL + BIT) give BIT
@details This function aggregates field types from the array of items.
Found type is supposed to be used later as the result field type
......@@ -1620,8 +1621,11 @@ Type_handler_hybrid_field_type::aggregate_for_result(const char *funcname,
{
const Type_handler *cur= items[i]->type_handler();
set_if_bigger(max_display_length, items[i]->max_display_length());
if (treat_bit_as_number &&
((type_handler() == &type_handler_bit) ^ (cur == &type_handler_bit)))
uint bit_count= (type_handler() == &type_handler_bit) +
(cur == &type_handler_bit);
uint null_count= (type_handler() == &type_handler_null) +
(cur == &type_handler_null);
if (treat_bit_as_number && bit_count == 1 && null_count == 0)
{
bit_and_non_bit_mixture_found= true;
if (type_handler() == &type_handler_bit)
......@@ -4067,12 +4071,39 @@ Type_handler_timestamp_common::create_item_copy(THD *thd, Item *item) const
/*************************************************************************/
/*
This method handles YEAR and BIT data types.
It does not switch the data type to DECIAMAL on a
unsigned_flag mistmatch. This important for combinations
like YEAR+NULL, BIT+NULL.
*/
bool Type_handler_int_result::
Item_hybrid_func_fix_attributes(THD *thd,
const char *func_name,
Type_handler_hybrid_field_type *handler,
Type_all_attributes *func,
Item **items, uint nitems) const
{
func->aggregate_attributes_int(items, nitems);
return false;
}
/*
This method handles general purpose integer data types
TINYINT, SHORTINT, MEDIUNINT, BIGINT.
It switches to DECIMAL in case if a mismatch in unsigned_flag found.
Note, we should fix this to ignore all items with
type_handler()==&type_handler_null.
It's too late for 10.4. Let's do it eventually in a higher version.
*/
bool Type_handler_general_purpose_int::
Item_hybrid_func_fix_attributes(THD *thd,
const char *func_name,
Type_handler_hybrid_field_type *handler,
Type_all_attributes *func,
Item **items, uint nitems) const
{
bool unsigned_flag= items[0]->unsigned_flag;
for (uint i= 1; i < nitems; i++)
......
......@@ -4820,6 +4820,12 @@ class Type_handler_general_purpose_int: public Type_handler_int_result
type_limits_int_by_unsigned_flag(bool unsigned_flag) const= 0;
uint32 max_display_length(const Item *item) const;
uint32 Item_decimal_notation_int_digits(const Item *item) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
Type_all_attributes *atrr,
Item **items,
uint nitems) const;
bool Vers_history_point_resolve_unit(THD *thd, Vers_history_point *p) const;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment