mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-12506 Split Item_func_min_max::fix_length_and_dec() into methods 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.
This commit is contained in:
@@ -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)));
|
||||
@@ -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));
|
||||
|
@@ -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)));
|
||||
@@ -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));
|
||||
|
@@ -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)));
|
||||
@@ -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));
|
||||
|
@@ -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)));
|
||||
@@ -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));
|
||||
|
@@ -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)));
|
||||
@@ -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));
|
||||
|
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -3050,7 +3050,7 @@ 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
|
||||
@@ -3058,9 +3058,14 @@ 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;
|
||||
@@ -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
|
||||
#
|
||||
|
@@ -2792,7 +2792,7 @@ t2 CREATE TABLE `t2` (
|
||||
CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types set and geometry for operation 'UNION'
|
||||
# This does not preserve geometry type (MDEV-9405)
|
||||
# This does not preserve geometry type (MDEV-12560)
|
||||
CREATE TABLE t1 AS SELECT COALESCE(NULL, Point(1,1));
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
@@ -3711,6 +3711,195 @@ CASE a WHEN POINT(1,1) THEN "a" WHEN POINT(1,2) THEN "b" END
|
||||
DROP PROCEDURE p1;
|
||||
DROP PROCEDURE p2;
|
||||
#
|
||||
# MDEV-12506 Split Item_func_min_max::fix_length_and_dec() into methods in Type_handler
|
||||
#
|
||||
CREATE PROCEDURE p2(query TEXT)
|
||||
BEGIN
|
||||
DECLARE errcount INT DEFAULT 0;
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
SET errcount = errcount+1;
|
||||
#SHOW WARNINGS;
|
||||
GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT;
|
||||
SELECT @p AS `ERROR: `;
|
||||
END;
|
||||
SELECT query AS ``;
|
||||
EXECUTE IMMEDIATE query;
|
||||
IF errcount = 0
|
||||
THEN
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1(query TEXT)
|
||||
BEGIN
|
||||
SELECT query AS `-------------------------------------`;
|
||||
EXECUTE IMMEDIATE query;
|
||||
CALL p2('CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1');
|
||||
DROP TABLE t1;
|
||||
END;
|
||||
$$
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a CHAR(10), b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`LEAST(a,b)` longblob DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a VARCHAR(10), b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`LEAST(a,b)` longblob DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a TINYTEXT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`LEAST(a,b)` longblob DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a TEXT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`LEAST(a,b)` longblob DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a MEDIUMTEXT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`LEAST(a,b)` longblob DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a LONGTEXT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`LEAST(a,b)` longblob DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a TINYINT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types tinyint and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a SMALLINT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types smallint and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a MEDIUMINT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types mediumint and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a INT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types int and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a BIGINT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types bigint and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a FLOAT, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types float and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a DOUBLE, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types double and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a DECIMAL(10,2), b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types decimal and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a BIT(8), b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types bit and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a TIME, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types time and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a DATE, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types date and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a DATETIME, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types datetime and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a TIMESTAMP, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types timestamp and geometry for operation 'least'
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a YEAR, b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
ERROR:
|
||||
Illegal parameter data types year and geometry for operation 'least'
|
||||
# This LEAST(ENUM,GEOMETRY) creates BLOB, but fails on error with UNION (see MDEV-12503)
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a ENUM(0x61), b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`LEAST(a,b)` longblob DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
-------------------------------------
|
||||
CREATE TABLE t1 (a SET(0x61), b Point)
|
||||
|
||||
CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
`LEAST(a,b)` longblob DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
# This does not preserve geometry type (MDEV-9405)
|
||||
CREATE TABLE t1 AS SELECT LEAST(NULL, Point(1,1));
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`LEAST(NULL, Point(1,1))` geometry DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
DROP PROCEDURE p2;
|
||||
#
|
||||
# MDEV-12001 Split Item_func_round::fix_length_and_dec to virtual methods in Type_handler
|
||||
#
|
||||
CREATE TABLE t1 (a GEOMETRY);
|
||||
|
@@ -155,6 +155,8 @@ CREATE TABLE t1 (a TIMESTAMP);
|
||||
INSERT INTO t1 VALUES ('2010-01-01 10:20:30');
|
||||
# Expect TIMESTAMP type (7) in metadata
|
||||
SELECT GREATEST(a,a) FROM t1;
|
||||
# Similar to this one
|
||||
SELECT COALESCE(a,a) FROM t1;
|
||||
DROP TABLE t1;
|
||||
--disable_metadata
|
||||
--enable_ps_protocol
|
||||
@@ -459,3 +461,47 @@ DROP TABLE t1;
|
||||
--echo #
|
||||
--echo # End of 10.1 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # Start of 10.3 tests
|
||||
--echo #
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12497 Wrong data type for LEAST(latin1_expr, utf8_expr)
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 AS SELECT
|
||||
LEAST(_latin1'aaa',_utf8 0xC39F) AS c1,
|
||||
COALESCE(_latin1'aaa',_utf8 0xC39F) AS c2;
|
||||
SHOW CREATE TABLE t1;
|
||||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12504 Wrong data type for LEAST(date_expr,time_expr)
|
||||
--echo #
|
||||
|
||||
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;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12505 Wrong data type for GREATEST(bit_column, int_column)
|
||||
--echo #
|
||||
|
||||
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;
|
||||
CREATE TABLE t2 AS SELECT COALESCE(a,b),GREATEST(a,b) FROM t1;
|
||||
SELECT * FROM t2;
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
--echo #
|
||||
|
||||
|
@@ -1789,7 +1789,7 @@ CALL p1('CREATE TABLE t1 (a ENUM(0x61), b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a SET(0x61), b Point)');
|
||||
--enable_query_log
|
||||
|
||||
--echo # This does not preserve geometry type (MDEV-9405)
|
||||
--echo # This does not preserve geometry type (MDEV-12560)
|
||||
CREATE TABLE t1 AS SELECT COALESCE(NULL, Point(1,1));
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
@@ -1869,6 +1869,77 @@ DROP PROCEDURE p1;
|
||||
DROP PROCEDURE p2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12506 Split Item_func_min_max::fix_length_and_dec() into methods in Type_handler
|
||||
--echo #
|
||||
|
||||
DELIMITER $$;
|
||||
CREATE PROCEDURE p2(query TEXT)
|
||||
BEGIN
|
||||
DECLARE errcount INT DEFAULT 0;
|
||||
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
SET errcount = errcount+1;
|
||||
#SHOW WARNINGS;
|
||||
GET DIAGNOSTICS CONDITION 1 @p= MESSAGE_TEXT;
|
||||
SELECT @p AS `ERROR: `;
|
||||
END;
|
||||
SELECT query AS ``;
|
||||
EXECUTE IMMEDIATE query;
|
||||
IF errcount = 0
|
||||
THEN
|
||||
SHOW CREATE TABLE t2;
|
||||
DROP TABLE t2;
|
||||
END IF;
|
||||
END;
|
||||
$$
|
||||
CREATE PROCEDURE p1(query TEXT)
|
||||
BEGIN
|
||||
SELECT query AS `-------------------------------------`;
|
||||
EXECUTE IMMEDIATE query;
|
||||
CALL p2('CREATE TABLE t2 AS SELECT LEAST(a,b) FROM t1');
|
||||
DROP TABLE t1;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
||||
|
||||
--disable_query_log
|
||||
CALL p1('CREATE TABLE t1 (a CHAR(10), b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a VARCHAR(10), b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a TINYTEXT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a TEXT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a MEDIUMTEXT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a LONGTEXT, b Point)');
|
||||
|
||||
CALL p1('CREATE TABLE t1 (a TINYINT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a SMALLINT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a MEDIUMINT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a INT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a BIGINT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a FLOAT, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a DOUBLE, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a DECIMAL(10,2), b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a BIT(8), b Point)');
|
||||
|
||||
CALL p1('CREATE TABLE t1 (a TIME, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a DATE, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a DATETIME, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a TIMESTAMP, b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a YEAR, b Point)');
|
||||
|
||||
--echo # This LEAST(ENUM,GEOMETRY) creates BLOB, but fails on error with UNION (see MDEV-12503)
|
||||
CALL p1('CREATE TABLE t1 (a ENUM(0x61), b Point)');
|
||||
CALL p1('CREATE TABLE t1 (a SET(0x61), b Point)');
|
||||
--enable_query_log
|
||||
|
||||
--echo # This does not preserve geometry type (MDEV-9405)
|
||||
CREATE TABLE t1 AS SELECT LEAST(NULL, Point(1,1));
|
||||
SHOW CREATE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
DROP PROCEDURE p1;
|
||||
DROP PROCEDURE p2;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-12001 Split Item_func_round::fix_length_and_dec to virtual methods in Type_handler
|
||||
--echo #
|
||||
|
@@ -10187,7 +10187,8 @@ void Item_cache_row::set_null()
|
||||
Item_type_holder::Item_type_holder(THD *thd, Item *item)
|
||||
:Item(thd, item),
|
||||
Type_handler_hybrid_field_type(item->real_type_handler()),
|
||||
enum_set_typelib(0)
|
||||
enum_set_typelib(0),
|
||||
geometry_type(Field::GEOM_GEOMETRY)
|
||||
{
|
||||
DBUG_ASSERT(item->fixed);
|
||||
maybe_null= item->maybe_null;
|
||||
|
117
sql/item_func.cc
117
sql/item_func.cc
@@ -2697,119 +2697,12 @@ double Item_func_units::val_real()
|
||||
}
|
||||
|
||||
|
||||
void Item_func_min_max::fix_length_and_dec()
|
||||
bool Item_func_min_max::fix_attributes(Item **items, uint nitems)
|
||||
{
|
||||
uint unsigned_count= 0;
|
||||
int max_int_part=0;
|
||||
decimals=0;
|
||||
max_length=0;
|
||||
maybe_null=0;
|
||||
Item_result tmp_cmp_type= args[0]->cmp_type();
|
||||
uint string_type_count= 0;
|
||||
uint temporal_type_count= 0;
|
||||
enum_field_types temporal_field_type= MYSQL_TYPE_DATETIME;
|
||||
|
||||
for (uint i=0 ; i < arg_count ; i++)
|
||||
{
|
||||
set_if_bigger(max_length, args[i]->max_length);
|
||||
set_if_bigger(decimals, args[i]->decimals);
|
||||
set_if_bigger(max_int_part, args[i]->decimal_int_part());
|
||||
unsigned_count+= args[i]->unsigned_flag;
|
||||
if (args[i]->maybe_null)
|
||||
maybe_null= 1;
|
||||
tmp_cmp_type= item_cmp_type(tmp_cmp_type, args[i]->cmp_type());
|
||||
string_type_count+= args[i]->cmp_type() == STRING_RESULT;
|
||||
if (args[i]->cmp_type() == TIME_RESULT)
|
||||
{
|
||||
if (!temporal_type_count)
|
||||
temporal_field_type= args[i]->field_type();
|
||||
else
|
||||
temporal_field_type= Field::field_type_merge(temporal_field_type,
|
||||
args[i]->field_type());
|
||||
temporal_type_count++;
|
||||
}
|
||||
}
|
||||
unsigned_flag= unsigned_count == arg_count; // if all args are unsigned
|
||||
|
||||
switch (tmp_cmp_type) {
|
||||
case TIME_RESULT:
|
||||
// At least one temporal argument was found.
|
||||
collation.set_numeric();
|
||||
set_handler_by_field_type(temporal_field_type);
|
||||
if (is_temporal_type_with_time(temporal_field_type))
|
||||
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
||||
else
|
||||
decimals= 0;
|
||||
break;
|
||||
|
||||
case STRING_RESULT:
|
||||
if (aggregate_for_result(func_name(), args, arg_count, false))
|
||||
return;
|
||||
/*
|
||||
All arguments are of string-alike types:
|
||||
CHAR, VARCHAR, TEXT, BINARY, VARBINARY, BLOB, SET, ENUM
|
||||
No numeric and no temporal types were found.
|
||||
*/
|
||||
agg_arg_charsets_for_string_result_with_comparison(collation,
|
||||
args, arg_count);
|
||||
break;
|
||||
|
||||
case INT_RESULT:
|
||||
/*
|
||||
All arguments have INT-alike types:
|
||||
TINY, SHORT, LONG, LONGLONG, INT24, YEAR, BIT.
|
||||
*/
|
||||
collation.set_numeric();
|
||||
fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
|
||||
decimals,
|
||||
decimals,
|
||||
unsigned_flag));
|
||||
if (unsigned_count != 0 && unsigned_count != arg_count)
|
||||
{
|
||||
/*
|
||||
If all args are of INT-alike type, but have different unsigned_flag,
|
||||
then change type to DECIMAL.
|
||||
*/
|
||||
set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
There are only INT-alike arguments with equal unsigned_flag.
|
||||
Aggregate types to get the best covering type.
|
||||
Treat BIT as LONGLONG when aggregating to non-BIT types.
|
||||
Possible final type: TINY, SHORT, LONG, LONGLONG, INT24, YEAR, BIT.
|
||||
*/
|
||||
if (aggregate_for_result(func_name(), args, arg_count, true))
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case DECIMAL_RESULT:
|
||||
// All arguments are of DECIMAL type
|
||||
collation.set_numeric();
|
||||
fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
|
||||
decimals,
|
||||
decimals,
|
||||
unsigned_flag));
|
||||
set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
|
||||
break;
|
||||
|
||||
case ROW_RESULT:
|
||||
DBUG_ASSERT(0);
|
||||
// Pass through
|
||||
case REAL_RESULT:
|
||||
collation.set_numeric();
|
||||
fix_char_length(float_length(decimals));
|
||||
/*
|
||||
Set type to DOUBLE, as Item_func::create_tmp_field() does not
|
||||
distinguish between DOUBLE and FLOAT and always creates Field_double.
|
||||
Perhaps we should eventually change this to use aggregate_for_result()
|
||||
and fix Item_func::create_tmp_field() to create Field_float when possible.
|
||||
*/
|
||||
set_handler_by_field_type(MYSQL_TYPE_DOUBLE);
|
||||
break;
|
||||
}
|
||||
bool rc= Item_func_min_max::type_handler()->
|
||||
Item_func_min_max_fix_attributes(current_thd, this, items, nitems);
|
||||
DBUG_ASSERT(!rc || current_thd->is_error());
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1434,6 +1434,8 @@ class Item_func_min_max :public Item_hybrid_func
|
||||
{
|
||||
String tmp_value;
|
||||
int cmp_sign;
|
||||
protected:
|
||||
bool fix_attributes(Item **item, uint nitems);
|
||||
public:
|
||||
Item_func_min_max(THD *thd, List<Item> &list, int cmp_sign_arg):
|
||||
Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg)
|
||||
@@ -1474,7 +1476,32 @@ public:
|
||||
return Item_func_min_max::type_handler()->
|
||||
Item_func_min_max_get_date(this, res, fuzzy_date);
|
||||
}
|
||||
void fix_length_and_dec();
|
||||
void aggregate_attributes_real(Item **items, uint nitems)
|
||||
{
|
||||
/*
|
||||
Aggregating attributes for the double data type for LEAST/GREATEST
|
||||
is almost the same with aggregating for CASE-alike hybrid functions,
|
||||
(CASE..THEN, COALESCE, IF, etc).
|
||||
There is one notable difference though, when a numeric argument is mixed
|
||||
with a string argument:
|
||||
- CASE-alike functions return a string data type in such cases
|
||||
COALESCE(10,'x') -> VARCHAR(2) = '10'
|
||||
- LEAST/GREATEST returns double:
|
||||
GREATEST(10,'10e4') -> DOUBLE = 100000
|
||||
As the string argument can represent a number in the scientific notation,
|
||||
like in the example above, max_length of the result can be longer than
|
||||
max_length of the arguments. To handle this properly, max_length is
|
||||
additionally assigned to the result of float_length(decimals).
|
||||
*/
|
||||
Item_func::aggregate_attributes_real(items, nitems);
|
||||
max_length= float_length(decimals);
|
||||
}
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
if (aggregate_for_min_max(func_name(), args, arg_count))
|
||||
return;
|
||||
fix_attributes(args, arg_count);
|
||||
}
|
||||
};
|
||||
|
||||
class Item_func_min :public Item_func_min_max
|
||||
|
167
sql/sql_type.cc
167
sql/sql_type.cc
@@ -370,7 +370,6 @@ Type_handler_hybrid_field_type::aggregate_for_result(const char *funcname,
|
||||
return true;
|
||||
}
|
||||
set_handler(items[0]->type_handler());
|
||||
uint unsigned_count= items[0]->unsigned_flag;
|
||||
for (uint i= 1 ; i < nitems ; i++)
|
||||
{
|
||||
const Type_handler *cur= items[i]->type_handler();
|
||||
@@ -388,26 +387,6 @@ Type_handler_hybrid_field_type::aggregate_for_result(const char *funcname,
|
||||
type_handler()->name().ptr(), cur->name().ptr(), funcname);
|
||||
return true;
|
||||
}
|
||||
unsigned_count+= items[i]->unsigned_flag;
|
||||
}
|
||||
switch (field_type()) {
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
case MYSQL_TYPE_BIT:
|
||||
if (unsigned_count != 0 && unsigned_count != nitems)
|
||||
{
|
||||
/*
|
||||
If all arguments are of INT-alike type but have different
|
||||
unsigned_flag, then convert to DECIMAL.
|
||||
*/
|
||||
set_handler(&type_handler_newdecimal);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -479,6 +458,114 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Aggregate data type handler for LEAST/GRATEST.
|
||||
aggregate_for_min_max() is close to aggregate_for_comparison(),
|
||||
but tries to preserve the exact type handler for string, int and temporal
|
||||
data types (instead of converting to super-types).
|
||||
FLOAT is not preserved and is converted to its super-type (DOUBLE).
|
||||
This should probably fixed eventually, for symmetry.
|
||||
*/
|
||||
|
||||
bool
|
||||
Type_handler_hybrid_field_type::aggregate_for_min_max(const Type_handler *h)
|
||||
{
|
||||
if (!m_type_handler->is_traditional_type() ||
|
||||
!h->is_traditional_type())
|
||||
{
|
||||
/*
|
||||
If at least one data type is non-traditional,
|
||||
do aggregation for result immediately.
|
||||
For now we suppose that these two expressions:
|
||||
- LEAST(type1, type2)
|
||||
- COALESCE(type1, type2)
|
||||
return the same data type (or both expressions return error)
|
||||
if type1 and/or type2 are non-traditional.
|
||||
This may change in the future.
|
||||
*/
|
||||
h= type_handler_data->
|
||||
m_type_aggregator_for_result.find_handler(m_type_handler, h);
|
||||
if (!h)
|
||||
return true;
|
||||
m_type_handler= h;
|
||||
return false;
|
||||
}
|
||||
|
||||
Item_result a= cmp_type();
|
||||
Item_result b= h->cmp_type();
|
||||
DBUG_ASSERT(a != ROW_RESULT); // Disallowed by check_cols() in fix_fields()
|
||||
DBUG_ASSERT(b != ROW_RESULT); // Disallowed by check_cols() in fix_fields()
|
||||
|
||||
if (a == STRING_RESULT && b == STRING_RESULT)
|
||||
m_type_handler=
|
||||
Type_handler::aggregate_for_result_traditional(m_type_handler, h);
|
||||
else if (a == INT_RESULT && b == INT_RESULT)
|
||||
{
|
||||
// BIT aggregates with non-BIT as BIGINT
|
||||
if (m_type_handler != h)
|
||||
{
|
||||
if (m_type_handler == &type_handler_bit)
|
||||
m_type_handler= &type_handler_longlong;
|
||||
else if (h == &type_handler_bit)
|
||||
h= &type_handler_longlong;
|
||||
}
|
||||
m_type_handler=
|
||||
Type_handler::aggregate_for_result_traditional(m_type_handler, h);
|
||||
}
|
||||
else if (a == TIME_RESULT || b == TIME_RESULT)
|
||||
{
|
||||
if ((a == TIME_RESULT) + (b == TIME_RESULT) == 1)
|
||||
{
|
||||
/*
|
||||
We're here if there's only one temporal data type:
|
||||
either m_type_handler or h.
|
||||
*/
|
||||
if (b == TIME_RESULT)
|
||||
m_type_handler= h; // Temporal types bit non-temporal types
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
We're here if both m_type_handler and h are temporal data types.
|
||||
*/
|
||||
m_type_handler=
|
||||
Type_handler::aggregate_for_result_traditional(m_type_handler, h);
|
||||
}
|
||||
}
|
||||
else if ((a == INT_RESULT || a == DECIMAL_RESULT) &&
|
||||
(b == INT_RESULT || b == DECIMAL_RESULT))
|
||||
{
|
||||
m_type_handler= &type_handler_newdecimal;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_type_handler= &type_handler_double;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Type_handler_hybrid_field_type::aggregate_for_min_max(const char *funcname,
|
||||
Item **items, uint nitems)
|
||||
{
|
||||
// LEAST/GREATEST require at least two arguments
|
||||
DBUG_ASSERT(nitems > 1);
|
||||
set_handler(items[0]->type_handler());
|
||||
for (uint i= 1; i < nitems; i++)
|
||||
{
|
||||
const Type_handler *cur= items[i]->type_handler();
|
||||
if (aggregate_for_min_max(cur))
|
||||
{
|
||||
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
||||
type_handler()->name().ptr(), cur->name().ptr(), funcname);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const Type_handler *
|
||||
Type_handler::aggregate_for_num_op_traditional(const Type_handler *h0,
|
||||
const Type_handler *h1)
|
||||
@@ -1313,6 +1400,17 @@ bool Type_handler_int_result::
|
||||
Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
uint unsigned_flag= items[0]->unsigned_flag;
|
||||
for (uint i= 1; i < nitems; i++)
|
||||
{
|
||||
if (unsigned_flag != items[i]->unsigned_flag)
|
||||
{
|
||||
// Convert a mixture of signed and unsigned int to decimal
|
||||
func->set_handler(&type_handler_newdecimal);
|
||||
func->aggregate_attributes_decimal(items, nitems);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
func->aggregate_attributes_int(items, nitems);
|
||||
return false;
|
||||
}
|
||||
@@ -1379,6 +1477,33 @@ bool Type_handler_timestamp_common::
|
||||
return false;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool Type_handler::
|
||||
Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
/*
|
||||
Aggregating attributes for LEAST/GREATES is exactly the same
|
||||
with aggregating for CASE-alike functions (e.g. COALESCE)
|
||||
for the majority of data type handlers.
|
||||
*/
|
||||
return Item_hybrid_func_fix_attributes(thd, func, items, nitems);
|
||||
}
|
||||
|
||||
|
||||
bool Type_handler_real_result::
|
||||
Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
|
||||
Item **items, uint nitems) const
|
||||
{
|
||||
/*
|
||||
DOUBLE is an exception and aggregates attributes differently
|
||||
for LEAST/GREATEST vs CASE-alike functions. See the comment in
|
||||
Item_func_min_max::aggregate_attributes_real().
|
||||
*/
|
||||
func->aggregate_attributes_real(items, nitems);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
|
@@ -485,6 +485,10 @@ public:
|
||||
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item **items,
|
||||
uint nitems) const= 0;
|
||||
virtual bool Item_func_min_max_fix_attributes(THD *thd,
|
||||
Item_func_min_max *func,
|
||||
Item **items,
|
||||
uint nitems) const;
|
||||
virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0;
|
||||
virtual bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const= 0;
|
||||
virtual bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const= 0;
|
||||
@@ -840,6 +844,8 @@ public:
|
||||
bool set_comparator_func(Arg_comparator *cmp) const;
|
||||
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
|
||||
Item **items, uint nitems) const;
|
||||
bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
|
||||
Item **items, uint nitems) const;
|
||||
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
|
||||
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
|
||||
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
|
||||
@@ -1602,6 +1608,7 @@ public:
|
||||
class Type_handler_hybrid_field_type
|
||||
{
|
||||
const Type_handler *m_type_handler;
|
||||
bool aggregate_for_min_max(const Type_handler *other);
|
||||
public:
|
||||
Type_handler_hybrid_field_type();
|
||||
Type_handler_hybrid_field_type(const Type_handler *handler)
|
||||
@@ -1657,6 +1664,8 @@ public:
|
||||
bool aggregate_for_result(const Type_handler *other);
|
||||
bool aggregate_for_result(const char *funcname,
|
||||
Item **item, uint nitems, bool treat_bit_as_number);
|
||||
bool aggregate_for_min_max(const char *funcname, Item **item, uint nitems);
|
||||
|
||||
bool aggregate_for_num_op(const class Type_aggregator *aggregator,
|
||||
const Type_handler *h0, const Type_handler *h1);
|
||||
};
|
||||
|
Reference in New Issue
Block a user