Skip to content

Commit

Permalink
A cleanup for MDEV-9217 Split Item::tmp_table_field_from_field_type()…
Browse files Browse the repository at this point in the history
… into virtual methods in Type_handler

Fixing that the server tried to create the old decimal for:

  CREATE TABLE t2 AS SELECT old_decimal_field FROM t1
               UNION SELECT bigint_field FROM t1;

  CREATE TABLE t2 AS SELECT old_decimal_field FROM t1
               UNION SELECT mediumint_field FROM t1;

  CREATE TABLE t2 AS SELECT year FROM t1
               UNION SELECT old_decimal_field FROM t1;

  CREATE TABLE t2 AS SELCT COALESCE(old_decimal_field) FROM t1;

Solution:

1. field_types_merge_rules[][] had three MYSQL_TYPE_DECIMAL remainders.
   Fixing to MYSQL_TYPE_NEWDECIMAL, like it is done for all other type pairs.
   This fixes the above queries with UNION.

2. Convert MYSQL_TYPE_DECIMAL to MYSQL_TYPE_NEWDECIMAL in
   Item::tmp_table_field_from_field_type().
   This fixed the above query with COALESCE.

3. Adding "new Field_decimal" into Type_handler_olddecimal::make_table_field().
   In case if something goes wrong it will crash on assert only in debug builds,
   while create the old decimal in release.
   Note, this "new Field_decimal" will be needed later anyway,
   when we reuse Type_handler::make_table_field() in make_field() in field.cc.
  • Loading branch information
Alexander Barkov committed Apr 24, 2017
1 parent 7913743 commit 5f1544f
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 4 deletions.
49 changes: 49 additions & 0 deletions mysql-test/r/type_decimal.result
Original file line number Diff line number Diff line change
Expand Up @@ -1019,3 +1019,52 @@ cast('-0.0' as decimal(5,1)) < 0
#
# End of 5.5 tests
#
#
# Start of 10.3 tests
#
#
# MDEV-9217 Split Item::tmp_table_field_from_field_type() into virtual methods in Type_handler
#
# This creates the old DECIMAL. Will be fixed in MDEV-12574.
CREATE TABLE t1 AS SELECT MAX(a) FROM t1dec102;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`MAX(a)` decimal(10,2)/*old*/ DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 AS SELECT COALESCE(a) FROM t1dec102;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE(a)` decimal(12,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a BIGINT);
CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` decimal(21,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a MEDIUMINT);
CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` decimal(12,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (a YEAR);
CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1dec102;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` decimal(12,2) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
DROP TABLE t1dec102;
43 changes: 43 additions & 0 deletions mysql-test/t/type_decimal.test
Original file line number Diff line number Diff line change
Expand Up @@ -612,3 +612,46 @@ select cast('-0.0' as decimal(5,1)) < 0;
--echo #
--echo # End of 5.5 tests
--echo #

--echo #
--echo # Start of 10.3 tests
--echo #

--echo #
--echo # MDEV-9217 Split Item::tmp_table_field_from_field_type() into virtual methods in Type_handler
--echo #

let $MYSQLD_DATADIR= `select @@datadir`;

--copy_file std_data/old_decimal/t1dec102.frm $MYSQLD_DATADIR/test/t1dec102.frm
--copy_file std_data/old_decimal/t1dec102.MYD $MYSQLD_DATADIR/test/t1dec102.MYD
--copy_file std_data/old_decimal/t1dec102.MYI $MYSQLD_DATADIR/test/t1dec102.MYI

--echo # This creates the old DECIMAL. Will be fixed in MDEV-12574.
CREATE TABLE t1 AS SELECT MAX(a) FROM t1dec102;
SHOW CREATE TABLE t1;
DROP TABLE t1;

CREATE TABLE t1 AS SELECT COALESCE(a) FROM t1dec102;
SHOW CREATE TABLE t1;
DROP TABLE t1;

CREATE TABLE t1 (a BIGINT);
CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;

CREATE TABLE t1 (a MEDIUMINT);
CREATE TABLE t2 AS SELECT a FROM t1dec102 UNION SELECT a FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;

CREATE TABLE t1 (a YEAR);
CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT a FROM t1dec102;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;

DROP TABLE t1dec102;
4 changes: 2 additions & 2 deletions sql/field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
//MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP
MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_DECIMAL,
MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
//MYSQL_TYPE_DATE MYSQL_TYPE_TIME
MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR,
//MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR
Expand Down Expand Up @@ -520,7 +520,7 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
/* MYSQL_TYPE_YEAR -> */
{
//MYSQL_TYPE_DECIMAL MYSQL_TYPE_TINY
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_TINY,
//MYSQL_TYPE_SHORT MYSQL_TYPE_LONG
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
//MYSQL_TYPE_FLOAT MYSQL_TYPE_DOUBLE
Expand Down
3 changes: 3 additions & 0 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6284,6 +6284,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
Record_addr addr(maybe_null);

switch (handler->field_type()) {
case MYSQL_TYPE_DECIMAL:
handler= &type_handler_newdecimal;
break;
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_ENUM:
Expand Down
8 changes: 6 additions & 2 deletions sql/sql_type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1281,11 +1281,15 @@ Type_handler_olddecimal::make_table_field(const LEX_CSTRING *name,
/*
Currently make_table_field() is used for Item purpose only.
On Item level we have type_handler_newdecimal only.
Will be implemented when we reuse Type_handler::make_table_field()
For now we have DBUG_ASSERT(0).
It will be removed when we reuse Type_handler::make_table_field()
in make_field() in field.cc, to open old tables with old decimal.
*/
DBUG_ASSERT(0);
return NULL;
return new (table->in_use->mem_root)
Field_decimal(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
Field::NONE, name, attr.decimals,
0/*zerofill*/,attr.unsigned_flag);
}


Expand Down

0 comments on commit 5f1544f

Please sign in to comment.