Skip to content

Commit

Permalink
MDEV-12506 Split Item_func_min_max::fix_length_and_dec() into methods…
Browse files Browse the repository at this point in the history
… in Type_handler + MDEV-12497 + MDEV-12504

This patch does the following:

1. Adds a new method Type_handler_hybrid_field_type::aggregate_for_min_max()

   - For non-traditional data types it uses
     type_handler_data->m_type_aggregator_for_result.find_handler()
     This allows pluggable data types to define in the future their
     own behavior of the result data type detection for LEAST/GREATEST.
     Also, this disallows expressions of the GEOMETRY data type
     (and its variants such as POINT) to be mixed in with
     numeric and temporal data types in LEAST/GREATEST.

   - For traditional data types it reproduces the old behavior of
     the result data type detection (but not attributes, see below).

2. Adds a new virtual method Type_handler::Item_func_min_max_fix_attributes()
   and reuses as much as possible the code that calculates data type attributes
   for CASE-alike functions (e.g. CASE..THEN, COALESCE, IF).

   As the old code responsible for attributes calculation in the old
   implementation of Item_func_min_max::fix_length_and_dec()
   was not fully correct, this automatically fixes the following bugs:

   - MDEV-12497 Wrong data type for LEAST(latin1_expr, utf8_expr)
     The old fix_length_and_dec() calculated max_length before
     character set aggregation. Now max_length is calculated after, in
     Item_func::count_string_length() called from
     Item_func::aggregate_attributes_string() called from
     Type_handler_string_result::Item_hybrid_func_fix_attributes() called from
     Type_handler::Item_func_min_max_fix_attributes() called from
     Item_func_min_max::fix_length_and_dec().

   - MDEV-12504 Wrong data type for LEAST(date_expr,time_expr)
     The old fix_length_and_dec() simply used the maximum of max_length
     among all arguments to set its own max_length and did not take
     into account that a mixture of DATE and TIME becomes DATETIME.
     Now this is correctly handled by:
     Type_handler_datetime_common::Item_hybrid_func_fix_attributes() called from
     Type_handler::Item_func_min_max_fix_attributes() called from
     Item_func_min_max::fix_length_and_dec().

3. Removes the old implementation of Item_func_min_max::fix_length_and_dec()
   and replaces it to calls of the new methods.

4. Cleanup: moves the code related to unsigned_flag processing
   from Type_handler_hybrid_field_type::aggregate_for_result()
   to   Type_handler_int_result::Item_hybrid_func_fix_attributes().
   This is done:
   - to avoid code duplication in
     Type_handler_hybrid_field_type::aggregate_for_min_max()
   - to get rid of one more call for field_type(), which is unfriendly
     to the conceipt of pluggable data types.
  • Loading branch information
Alexander Barkov committed Apr 22, 2017
1 parent ba670ed commit 6580825
Show file tree
Hide file tree
Showing 14 changed files with 575 additions and 157 deletions.
4 changes: 2 additions & 2 deletions mysql-test/r/ctype_binary.result
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varbinary(2) DEFAULT NULL
`c1` varbinary(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
Expand All @@ -618,7 +618,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varbinary(2) DEFAULT NULL
`c1` varbinary(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
Expand Down
4 changes: 2 additions & 2 deletions mysql-test/r/ctype_cp1251.result
Original file line number Diff line number Diff line change
Expand Up @@ -1017,7 +1017,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(2) CHARACTER SET cp1251 DEFAULT NULL
`c1` varchar(1) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
Expand All @@ -1027,7 +1027,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(2) CHARACTER SET cp1251 DEFAULT NULL
`c1` varchar(1) CHARACTER SET cp1251 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
Expand Down
4 changes: 2 additions & 2 deletions mysql-test/r/ctype_latin1.result
Original file line number Diff line number Diff line change
Expand Up @@ -1314,7 +1314,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(2) DEFAULT NULL
`c1` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
Expand All @@ -1324,7 +1324,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(2) DEFAULT NULL
`c1` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
Expand Down
4 changes: 2 additions & 2 deletions mysql-test/r/ctype_ucs.result
Original file line number Diff line number Diff line change
Expand Up @@ -2193,7 +2193,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(2) CHARACTER SET ucs2 DEFAULT NULL
`c1` varchar(1) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
Expand All @@ -2203,7 +2203,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(2) CHARACTER SET ucs2 DEFAULT NULL
`c1` varchar(1) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
Expand Down
4 changes: 2 additions & 2 deletions mysql-test/r/ctype_utf8.result
Original file line number Diff line number Diff line change
Expand Up @@ -3065,7 +3065,7 @@ create table t1 as select concat(least(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(2) CHARACTER SET utf8 DEFAULT NULL
`c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(greatest(1,2)));
Expand All @@ -3075,7 +3075,7 @@ create table t1 as select concat(greatest(1,2)) as c1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(2) CHARACTER SET utf8 DEFAULT NULL
`c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select hex(concat(case when 11 then 22 else 33 end));
Expand Down
77 changes: 67 additions & 10 deletions mysql-test/r/func_hybrid_type.result
Original file line number Diff line number Diff line change
Expand Up @@ -1615,8 +1615,8 @@ def coalesce___b 254 1 1 Y 0 39 8
def coalesce_b_b 254 1 1 Y 0 39 8
def if_______b_b 254 1 1 Y 0 39 8
def ifnull___b_b 254 1 1 Y 0 39 8
def least____b_b 254 1 1 Y 0 0 8
def greatest_b_b 254 1 1 Y 0 0 8
def least____b_b 254 1 1 Y 0 39 8
def greatest_b_b 254 1 1 Y 0 39 8
___________a a
case_______a a
case_____a_a a
Expand Down Expand Up @@ -2190,10 +2190,10 @@ def if_______a_b 12 19 19 Y 128 0 63
def if_______b_a 12 19 19 Y 128 0 63
def ifnull___a_b 12 19 19 Y 128 0 63
def ifnull___b_a 12 19 19 Y 128 0 63
def least____a_b 12 10 19 Y 128 0 63
def least____b_a 12 10 19 Y 128 0 63
def greatest_a_b 12 10 19 Y 128 0 63
def greatest_b_a 12 10 19 Y 128 0 63
def least____a_b 12 19 19 Y 128 0 63
def least____b_a 12 19 19 Y 128 0 63
def greatest_a_b 12 19 19 Y 128 0 63
def greatest_b_a 12 19 19 Y 128 0 63
case_____a_b 2010-01-01 00:00:00
case_____b_a 2001-01-01 10:20:30
coalesce_a_b 2010-01-01 00:00:00
Expand Down Expand Up @@ -2317,8 +2317,8 @@ def coalesce___a 7 19 19 N 129 0 63
def coalesce_a_a 7 19 19 N 129 0 63
def if_______a_a 7 19 19 N 129 0 63
def ifnull___a_a 7 19 19 N 129 0 63
def least____a_a 7 19 19 N 161 0 63
def greatest_a_a 7 19 19 N 161 0 63
def least____a_a 7 19 19 N 129 0 63
def greatest_a_a 7 19 19 N 129 0 63
def test t1 t1 b ___________b 11 10 8 Y 128 0 63
def case_______b 11 10 8 Y 128 0 63
def case_____b_b 11 10 8 Y 128 0 63
Expand Down Expand Up @@ -3050,17 +3050,22 @@ DROP TABLE t1;
SET timestamp=UNIX_TIMESTAMP('2010-01-01 01:02:03');
SELECT GREATEST(CURRENT_TIME, CURRENT_DATE), COALESCE(CURRENT_TIME, CURRENT_DATE);
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def GREATEST(CURRENT_TIME, CURRENT_DATE) 12 10 19 N 129 0 63
def GREATEST(CURRENT_TIME, CURRENT_DATE) 12 19 19 N 129 0 63
def COALESCE(CURRENT_TIME, CURRENT_DATE) 12 19 19 N 129 0 63
GREATEST(CURRENT_TIME, CURRENT_DATE) COALESCE(CURRENT_TIME, CURRENT_DATE)
2010-01-01 01:02:03 2010-01-01 01:02:03
CREATE TABLE t1 (a TIMESTAMP);
INSERT INTO t1 VALUES ('2010-01-01 10:20:30');
SELECT GREATEST(a,a) FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def GREATEST(a,a) 7 19 19 N 161 0 63
def GREATEST(a,a) 7 19 19 N 129 0 63
GREATEST(a,a)
2010-01-01 10:20:30
SELECT COALESCE(a,a) FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def COALESCE(a,a) 7 19 19 N 129 0 63
COALESCE(a,a)
2010-01-01 10:20:30
DROP TABLE t1;
CREATE TABLE t1 (a TIMESTAMP, b DATETIME);
CREATE TABLE t2 AS SELECT LEAST(a,a),LEAST(b,b),LEAST(a,b) FROM t1;
Expand Down Expand Up @@ -3445,3 +3450,55 @@ DROP TABLE t1;
#
# End of 10.1 tests
#
#
# Start of 10.3 tests
#
#
# MDEV-12497 Wrong data type for LEAST(latin1_expr, utf8_expr)
#
CREATE TABLE t1 AS SELECT
LEAST(_latin1'aaa',_utf8 0xC39F) AS c1,
COALESCE(_latin1'aaa',_utf8 0xC39F) AS c2;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(3) CHARACTER SET utf8 NOT NULL,
`c2` varchar(3) CHARACTER SET utf8 NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1;
c1 c2
aaa aaa
DROP TABLE t1;
#
# MDEV-12504 Wrong data type for LEAST(date_expr,time_expr)
#
CREATE TABLE t1 AS SELECT
LEAST(DATE'2001-01-01', TIME'10:20:30') AS c1,
CONCAT(LEAST(DATE'2001-01-01', TIME'10:20:30')) AS c2;
SELECT * FROM t1;
c1 c2
2001-01-01 00:00:00 2001-01-01 00:00:00
DROP TABLE t1;
#
# MDEV-12505 Wrong data type for GREATEST(bit_column, int_column)
#
CREATE TABLE t1 (a BIT(64),b INT);
INSERT INTO t1 VALUES (0xFFFFFFFFFFFFFFFF,-1);
SELECT a>b, COALESCE(a,b), GREATEST(a,b) FROM t1;
a>b COALESCE(a,b) GREATEST(a,b)
1 18446744073709551615 18446744073709551615
CREATE TABLE t2 AS SELECT COALESCE(a,b),GREATEST(a,b) FROM t1;
SELECT * FROM t2;
COALESCE(a,b) GREATEST(a,b)
18446744073709551615 18446744073709551615
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`COALESCE(a,b)` decimal(64,0) DEFAULT NULL,
`GREATEST(a,b)` decimal(64,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
#
# End of 10.3 tests
#
Loading

0 comments on commit 6580825

Please sign in to comment.