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 ...@@ -1859,5 +1859,25 @@ cc 18446744073709551615
cr 18446744073709551615 cr 18446744073709551615
ct 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 # End of 10.4 tests
# #
...@@ -543,6 +543,22 @@ DELIMITER ;$$ ...@@ -543,6 +543,22 @@ DELIMITER ;$$
--horizontal_results --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 #
--echo # End of 10.4 tests --echo # End of 10.4 tests
--echo # --echo #
...@@ -675,5 +675,25 @@ FLOOR(a) int(4) unsigned YES NULL ...@@ -675,5 +675,25 @@ FLOOR(a) int(4) unsigned YES NULL
CEILING(a) int(4) unsigned YES NULL CEILING(a) int(4) unsigned YES NULL
DROP TABLE t2,t1; 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 # 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 ...@@ -354,6 +354,20 @@ CREATE TABLE t2 AS SELECT a, ROUND(a), TRUNCATE(a,0), FLOOR(a), CEILING(a) FROM
DESC t2; DESC t2;
DROP TABLE t2,t1; 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 #
--echo # End of 10.4 tests --echo # End of 10.4 tests
......
...@@ -1588,6 +1588,7 @@ Type_handler::bit_and_int_mixture_handler(uint max_char_length) ...@@ -1588,6 +1588,7 @@ Type_handler::bit_and_int_mixture_handler(uint max_char_length)
Note, independently from "treat_bit_as_number": Note, independently from "treat_bit_as_number":
- a single BIT argument gives BIT as a result - a single BIT argument gives BIT as a result
- two BIT couterparts give 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. @details This function aggregates field types from the array of items.
Found type is supposed to be used later as the result field type 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, ...@@ -1620,8 +1621,11 @@ Type_handler_hybrid_field_type::aggregate_for_result(const char *funcname,
{ {
const Type_handler *cur= items[i]->type_handler(); const Type_handler *cur= items[i]->type_handler();
set_if_bigger(max_display_length, items[i]->max_display_length()); set_if_bigger(max_display_length, items[i]->max_display_length());
if (treat_bit_as_number && uint bit_count= (type_handler() == &type_handler_bit) +
((type_handler() == &type_handler_bit) ^ (cur == &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; bit_and_non_bit_mixture_found= true;
if (type_handler() == &type_handler_bit) if (type_handler() == &type_handler_bit)
...@@ -4067,12 +4071,39 @@ Type_handler_timestamp_common::create_item_copy(THD *thd, Item *item) const ...@@ -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:: bool Type_handler_int_result::
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func_fix_attributes(THD *thd,
const char *func_name, const char *func_name,
Type_handler_hybrid_field_type *handler, Type_handler_hybrid_field_type *handler,
Type_all_attributes *func, Type_all_attributes *func,
Item **items, uint nitems) const 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; bool unsigned_flag= items[0]->unsigned_flag;
for (uint i= 1; i < nitems; i++) for (uint i= 1; i < nitems; i++)
......
...@@ -4820,6 +4820,12 @@ class Type_handler_general_purpose_int: public Type_handler_int_result ...@@ -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; type_limits_int_by_unsigned_flag(bool unsigned_flag) const= 0;
uint32 max_display_length(const Item *item) const; uint32 max_display_length(const Item *item) const;
uint32 Item_decimal_notation_int_digits(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; 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