From 658082551ffd49a89d5473775bef5197e572d17e Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 22 Apr 2017 23:47:27 +0400 Subject: 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. --- mysql-test/r/gis.result | 191 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 190 insertions(+), 1 deletion(-) (limited to 'mysql-test/r/gis.result') diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index 6a7b7e7b8bf..77150ee3142 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -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); -- cgit v1.2.1