Skip to content

Commit

Permalink
MDEV-12775 Reuse data type aggregation code for hybrid functions and …
Browse files Browse the repository at this point in the history
…UNION

Introducing a new class Type_holder (used internally in sql_union.cc),
to reuse exactly the same data type attribute aggregation Type_handler API
for hybrid functions and UNION.

This fixes a number of bugs in UNION:

- MDEV-9495 Wrong field type for a UNION of a signed and an unsigned INT expression
- MDEV-9497 UNION and COALESCE produce different field types for DECIMAL+INT
- MDEV-12594 UNION between fixed length double columns does not always preserve scale
- MDEV-12595 UNION converts INT to BIGINT
- MDEV-12599 UNION is not symmetric when mixing INT and CHAR

Details:

- sql_union.cc: Reusing attribute aggregation for UNION.
  Adding new methods:
  * st_select_lex_unit::join_union_type_handlers()
  * st_select_lex_unit::join_union_type_attributes()
  * st_select_lex_unit::join_union_item_types()
  Removing the old join_types()-based code.

- Changing Type_handler::Item_hybrid_func_fix_attributes()
  to accept "name", Type_handler_hybrid_field_type, Type_all_attributes
  as three separate parameters instead of a single Item_hybrid_func parameter,
  to make it possible to pass both Item_hybrid_func and Type_holder.

- Moving the former special GEOMETRY and ENUM/SET attribute aggregation code
  from Item_type_holder::join_types() to
  * Type_handler_typelib::Item_hybrid_func_fix_attributes().
  * Type_handler_geometry::Item_hybrid_func_fix_attrubutes().
  This makes GEOMETRY/ENUM/SET symmetric with all other data types
  (from the UNION point of view).
  Removing Item_type_holder::join_types() and Item_type_holder::get_full_info().

- Adding new methods into Type_all_attributes:
  * Type_all_attributes::set_geometry_type() and
    Item_hybrid_func::set_geometry_type().
  * Adding Type_all_attributes::get_typelib().
  * Adding Type_all_attributes::set_typelib().

- Adding Type_handler_typelib as a common parent for
  Type_handler_enum and Type_handler_set, to avoid code duplication: they have
  already had two common methods, and we're adding one more shared method.

- Adding Type_all_attributes::set_maybe_null(), as some type handlers
  may want to set maybe_null (e.g. Type_handler_geometry) during data type
  attribute aggregation.

- Changing Type_geometry_attributes() to accept Type_handler
  and Type_all_attributes as two separate parameters, instead
  of a single Item parameter, to make it possible to pass Type_holder.

- Adding Item_args::add_argument().

- Moving Item_args::alloc_arguments() from "protected" to "public".

- Moving Item_type_holder::Item_type_holder() from item.cc to item.h, as
  now it's very simple.
  Btw, this constructor should probably be eventually removed.
  It's now used only in sql_show.cc, which could be modified to use
  Item_return_decimal (for symmetry with Item_return_xxx created for all
  other data types). Or, another option: remove all Item_return_xxx and
  use Item_type_holder for all data types instead.

- storage/tokudb/mysql-test/tokudb/r/type_float.result
  Recording new results (MDEV-12594).

- mysql-test/r/cte_recursive.result
  Recording new results (MDEV-9497)

- mysql-test/r/subselect*.result
  Recording new results (MDEV-12595)

- mysql-test/r/metadata.result
  Recording new results (MDEV-9495)

- mysql-test/r/temp_table.result
  Recording new results (MDEV-12594)

- mysql-test/r/type_float.result
  Recording new results (MDEV-12594)
  • Loading branch information
Alexander Barkov committed May 15, 2017
1 parent 7c44b8a commit 705fc43
Show file tree
Hide file tree
Showing 21 changed files with 755 additions and 325 deletions.
2 changes: 1 addition & 1 deletion mysql-test/r/cte_recursive.result
Expand Up @@ -130,7 +130,7 @@ select t2.a+1 from t1,t2 where t1.a=t2.a
select * from t1;
show columns from v1;
Field Type Null Key Default Extra
a bigint(20) YES NULL
a bigint(12) YES NULL
# WITH RECURSIVE : types of t1 columns are determined by anchor parts
create view v2 as
with recursive
Expand Down
6 changes: 3 additions & 3 deletions mysql-test/r/metadata.result
Expand Up @@ -147,7 +147,7 @@ id data data
2 female no
select t1.id from t1 union select t2.id from t2;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def id id 1 4 1 Y 32768 0 63
def id id 246 4 1 Y 32768 0 63
id
1
2
Expand All @@ -168,12 +168,12 @@ def aaa @arg00 @arg00 8 20 1 Y 32768 0 63
1
select 1 union select 1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def 1 1 3 11 1 N 32769 0 63
def 1 1 3 1 1 N 32769 0 63
1
1
select * from (select 1 union select 1) aaa;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def aaa 1 1 3 11 1 N 32769 0 63
def aaa 1 1 3 1 1 N 32769 0 63
1
1
drop table t1;
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/r/subselect.result
Expand Up @@ -1260,7 +1260,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/r/subselect_no_exists_to_in.result
Expand Up @@ -1264,7 +1264,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/r/subselect_no_mat.result
Expand Up @@ -1267,7 +1267,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/r/subselect_no_opts.result
Expand Up @@ -1263,7 +1263,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/r/subselect_no_scache.result
Expand Up @@ -1266,7 +1266,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
Expand Down
2 changes: 1 addition & 1 deletion mysql-test/r/subselect_no_semijoin.result
Expand Up @@ -1263,7 +1263,7 @@ a
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` bigint(20) NOT NULL
`a` int(3) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a int);
Expand Down
16 changes: 8 additions & 8 deletions mysql-test/r/temp_table.result
Expand Up @@ -181,20 +181,20 @@ CREATE TABLE t2 ( c FLOAT(30,18) );
INSERT INTO t2 VALUES( 123456 );
SELECT AVG( c ) FROM t1 UNION SELECT 1;
AVG( c )
12139
1
12139.000000000000000000
1.000000000000000000
SELECT 1 UNION SELECT AVG( c ) FROM t1;
1
1
12139
1.000000000000000000
12139.000000000000000000
SELECT 1 UNION SELECT * FROM t2 UNION SELECT 1;
1
1
123456
1.000000000000000000
123456.000000000000000000
SELECT c/1 FROM t1 UNION SELECT 1;
c/1
12139
1
12139.000000000000000000
1.000000000000000000
DROP TABLE t1, t2;
create temporary table t1 (a int);
insert into t1 values (4711);
Expand Down
6 changes: 3 additions & 3 deletions mysql-test/r/type_float.result
Expand Up @@ -232,12 +232,12 @@ insert into t2 values ("1.23456780");
create table t3 select * from t2 union select * from t1;
select * from t3;
d
1.2345678
100000000
1.234567800
100000000.000000000
show create table t3;
Table Create Table
t3 CREATE TABLE `t3` (
`d` double DEFAULT NULL
`d` double(18,9) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2, t3;
create table t1 select 105213674794682365.00 + 0.0 x;
Expand Down
215 changes: 211 additions & 4 deletions mysql-test/r/union.result
Expand Up @@ -852,7 +852,7 @@ select * from t1;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` int(11) NOT NULL DEFAULT 0
`1` int(2) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 select _latin1"test" union select _latin2"testt" ;
Expand Down Expand Up @@ -1608,7 +1608,7 @@ NULL binary(0) YES NULL
CREATE TABLE t5 SELECT NULL UNION SELECT NULL;
DESC t5;
Field Type Null Key Default Extra
NULL binary(0) YES NULL
NULL null YES NULL
CREATE TABLE t6
SELECT * FROM (SELECT * FROM (SELECT NULL)a) b UNION SELECT a FROM t1;
DESC t6;
Expand Down Expand Up @@ -2195,16 +2195,223 @@ CREATE OR REPLACE TABLE t1 AS SELECT 1 UNION SELECT 1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` int(11) NOT NULL DEFAULT 0
`1` int(1) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT * FROM (SELECT 1 UNION SELECT 1) AS t0;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` int(11) NOT NULL DEFAULT 0
`1` int(1) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# MDEV-9495 Wrong field type for a UNION of a signed and an unsigned INT expression
#
CREATE TABLE t1 (a INT, b INT UNSIGNED);
INSERT INTO t1 VALUES (0x7FFFFFFF,0xFFFFFFFF);
CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` decimal(10,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2 ORDER BY a;
a
2147483647
4294967295
DROP TABLE t2;
CREATE TABLE t2 AS SELECT COALESCE(a,b), COALESCE(b,a) FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`COALESCE(a,b)` decimal(10,0) DEFAULT NULL,
`COALESCE(b,a)` decimal(10,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
COALESCE(a,b) COALESCE(b,a)
2147483647 4294967295
DROP TABLE t2;
DROP TABLE t1;
#
# MDEV-9497 UNION and COALESCE produce different field types for DECIMAL+INT
#
CREATE TABLE t1 AS SELECT COALESCE(10.1,CAST(10 AS UNSIGNED)) AS a;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` decimal(3,1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT 10.1 AS a UNION SELECT CAST(10 AS UNSIGNED);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` decimal(3,1) NOT NULL DEFAULT 0.0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# MDEV-12594 UNION between fixed length double columns does not always preserve scale
#
CREATE TABLE t1 (a FLOAT(20,4), b FLOAT(20,3), c FLOAT(20,4));
INSERT INTO t1 VALUES (1111,2222,3333);
CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` float(20,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE OR REPLACE TABLE t2 SELECT a FROM t1 UNION SELECT c FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` float(20,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE OR REPLACE TABLE t2 SELECT b FROM t1 UNION SELECT b FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`b` float(20,3) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE OR REPLACE TABLE t2 SELECT c FROM t1 UNION SELECT c FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c` float(20,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE OR REPLACE TABLE t2 SELECT c FROM t1 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c` float(20,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE OR REPLACE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` float(21,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
CREATE OR REPLACE TABLE t2 AS SELECT b FROM t1 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`b` float(21,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
# Corner case
CREATE TABLE t1 (a FLOAT(255,4), b FLOAT(255,3));
INSERT INTO t1 VALUES (1111,2222);
CREATE OR REPLACE TABLE t2 AS SELECT b FROM t1 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`b` float(255,4) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
#
# MDEV-12595 UNION converts INT to BIGINT
#
CREATE TABLE t1 AS SELECT
1,
-1,
COALESCE(1,1),
COALESCE(-1,-1),
COALESCE(1,-1),
COALESCE(-1,1);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`1` int(1) NOT NULL,
`-1` int(2) NOT NULL,
`COALESCE(1,1)` int(1) NOT NULL,
`COALESCE(-1,-1)` int(2) NOT NULL,
`COALESCE(1,-1)` int(2) NOT NULL,
`COALESCE(-1,1)` int(2) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 AS SELECT 1 AS c1,1 AS c2,-1 AS c3,-1 AS c4 UNION SELECT 1,-1,1,-1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(1) NOT NULL DEFAULT 0,
`c2` int(2) NOT NULL DEFAULT 0,
`c3` int(2) NOT NULL DEFAULT 0,
`c4` int(2) NOT NULL DEFAULT 0
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# MDEV-12599 UNION is not symmetric when mixing INT and CHAR
#
CREATE OR REPLACE TABLE t1 AS SELECT 1 AS c1, 'a' AS c2 UNION SELECT 'a', 1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(1) NOT NULL DEFAULT '',
`c2` varchar(1) NOT NULL DEFAULT ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT 11112222 AS c1, 'a' AS c2 UNION SELECT 'a', 11112222;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(8) NOT NULL DEFAULT '',
`c2` varchar(8) NOT NULL DEFAULT ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT 111122223333 AS c1, 'a' AS c2 UNION SELECT 'a', 111122223333;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(12) NOT NULL DEFAULT '',
`c2` varchar(12) NOT NULL DEFAULT ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE OR REPLACE TABLE t1 AS SELECT 1111222233334444 AS c1, 'a' AS c2 UNION SELECT 'a', 1111222233334444;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` varchar(16) NOT NULL DEFAULT '',
`c2` varchar(16) NOT NULL DEFAULT ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a INT(3), b VARCHAR(1));
CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` varchar(11) DEFAULT NULL,
`b` varchar(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a BIGINT(3), b VARCHAR(1));
CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` varchar(20) DEFAULT NULL,
`b` varchar(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a BIGINT(12), b VARCHAR(1));
CREATE TABLE t2 AS SELECT a,b FROM t1 UNION SELECT b,a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` varchar(20) DEFAULT NULL,
`b` varchar(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
#
# End of 10.3 tests
#

0 comments on commit 705fc43

Please sign in to comment.