1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

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.
This commit is contained in:
Alexander Barkov
2023-10-17 12:46:31 +04:00
parent b1c8ea83a5
commit eb19638418
6 changed files with 109 additions and 2 deletions

View File

@ -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
# #

View File

@ -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 #

View File

@ -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
# #

View File

@ -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

View File

@ -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,
{ {
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
/*************************************************************************/ /*************************************************************************/
/*
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++)

View File

@ -4820,6 +4820,12 @@ public:
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;
}; };