Commit c875b8eb authored by evgen@moonbone.local's avatar evgen@moonbone.local

Fixed bug#12185: Data type aggregation may produce wrong result

The Item::tmp_table_field_from_field_type() function creates Field_datetime
object instead of Field_timestamp object for timestamp field thus always
changing data type is a tmp table is used.

The Field_blob object constructor which is used in the 
Item::tmp_table_field_from_field_type() is always setting packlength field of
newly created blob to 4. This leads to changing fields data type for example
from the blob to the longblob if a temporary table is used.

The Item::make_string_field() function always converts Field_string objects 
to Field_varstring objects. This leads to changing data type from the 
char/binary to varchar/varbinary.

Added appropriate Field_timestamp object constructor for using in the 
Item::tmp_table_field_from_field_type() function.

Added Field_blob object constructor which sets pack length according to
max_length argument.

The Item::tmp_table_field_from_field_type() function now creates
Field_timestamp object for a timestamp field.

The Item_type_holder::display_length() now returns correct NULL length NULL
length. 

The Item::make_string_field() function now doesn't change Field_string to
Field_varstring in the case of Item_type_holder. 

The Item::tmp_table_field_from_field_type() function now uses the Field_blob
constructor which sets packlength according to max_length.
parent fdc2b921
......@@ -452,7 +452,7 @@ t2 CREATE TABLE `t2` (
`ifnull(h,h)` decimal(5,4) default NULL,
`ifnull(i,i)` year(4) default NULL,
`ifnull(j,j)` date default NULL,
`ifnull(k,k)` datetime NOT NULL default '0000-00-00 00:00:00',
`ifnull(k,k)` timestamp NOT NULL default '0000-00-00 00:00:00',
`ifnull(l,l)` datetime default NULL,
`ifnull(m,m)` varchar(1) default NULL,
`ifnull(n,n)` varchar(3) default NULL,
......
......@@ -1473,8 +1473,8 @@ Error 1146 Table 'test.t4' doesn't exist
drop table t1,t2,t3;
create table t1 (id int, name char(10) not null, name2 char(10) not null) engine=innodb;
insert into t1 values(1,'first','fff'),(2,'second','sss'),(3,'third','ttt');
select name2 from t1 union all select name from t1 union all select id from t1;
name2
select trim(name2) from t1 union all select trim(name) from t1 union all select trim(id) from t1;
trim(name2)
fff
sss
ttt
......
......@@ -691,9 +691,9 @@ t1 CREATE TABLE `t1` (
`da` datetime default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT dt from t2 UNION select sc from t2;
select * from t1;
dt
create table t1 SELECT dt from t2 UNION select trim(sc) from t2;
select trim(dt) from t1;
trim(dt)
1972-10-22 11:50:00
testc
show create table t1;
......@@ -732,7 +732,7 @@ tetetetetest
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`dt` longblob
`dt` blob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT sv from t2 UNION select b from t2;
......@@ -743,7 +743,7 @@ tetetetetest
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`sv` longblob
`sv` blob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT i from t2 UNION select d from t2 UNION select b from t2;
......@@ -755,7 +755,7 @@ tetetetetest
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`i` longblob
`i` blob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT sv from t2 UNION select tx from t2;
......@@ -766,7 +766,7 @@ teeeeeeeeeeeest
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`sv` longtext
`sv` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT b from t2 UNION select tx from t2;
......@@ -777,7 +777,7 @@ teeeeeeeeeeeest
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`b` longblob
`b` blob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2;
create table t1 select 1 union select -1;
......@@ -1306,3 +1306,18 @@ id
5
99
drop table t1;
create table t1(f1 char(1), f2 char(5), f3 binary(1), f4 binary(5), f5 timestamp, f6 varchar(1) character set utf8 collate utf8_general_ci, f7 text);
create table t2 as select *, f6 as f8 from t1 union select *, f7 from t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
`f1` char(1) default NULL,
`f2` char(5) default NULL,
`f3` binary(1) default NULL,
`f4` binary(5) default NULL,
`f5` timestamp NOT NULL default '0000-00-00 00:00:00',
`f6` varchar(1) character set utf8 default NULL,
`f7` text,
`f8` text character set utf8
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1, t2;
......@@ -1079,7 +1079,7 @@ drop table t1,t2,t3;
#
create table t1 (id int, name char(10) not null, name2 char(10) not null) engine=innodb;
insert into t1 values(1,'first','fff'),(2,'second','sss'),(3,'third','ttt');
select name2 from t1 union all select name from t1 union all select id from t1;
select trim(name2) from t1 union all select trim(name) from t1 union all select trim(id) from t1;
drop table t1;
#
......
......@@ -390,8 +390,8 @@ create table t1 SELECT da from t2 UNION select dt from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT dt from t2 UNION select sc from t2;
select * from t1;
create table t1 SELECT dt from t2 UNION select trim(sc) from t2;
select trim(dt) from t1;
show create table t1;
drop table t1;
create table t1 SELECT dt from t2 UNION select sv from t2;
......@@ -793,3 +793,11 @@ select id from t1 union all select 99 order by 1;
drop table t1;
# End of 4.1 tests
#
# Bug#12185: Data type aggregation may produce wrong result
#
create table t1(f1 char(1), f2 char(5), f3 binary(1), f4 binary(5), f5 timestamp, f6 varchar(1) character set utf8 collate utf8_general_ci, f7 text);
create table t2 as select *, f6 as f8 from t1 union select *, f7 from t1;
show create table t2;
drop table t1, t2;
......@@ -4484,6 +4484,24 @@ Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
}
Field_timestamp::Field_timestamp(bool maybe_null_arg,
const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0, 19, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, table_arg, cs)
{
/* For 4.0 MYD and 4.0 InnoDB compatibility */
flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
if (table && !table->timestamp_field &&
unireg_check != NONE)
{
/* This timestamp has auto-update */
table->timestamp_field= this;
flags|=TIMESTAMP_FLAG;
}
}
/*
Get auto-set type for TIMESTAMP field.
......
......@@ -781,6 +781,8 @@ public:
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,
CHARSET_INFO *cs);
Field_timestamp(bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs);
enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
enum Item_result cmp_type () const { return INT_RESULT; }
......@@ -1129,6 +1131,21 @@ public:
{
flags|= BLOB_FLAG;
}
Field_blob(uint32 len_arg,bool maybe_null_arg, const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs, bool set_packlength)
:Field_longstr((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0, 0,
NONE, field_name_arg, table_arg, cs)
{
flags|= BLOB_FLAG;
packlength= 4;
if (set_packlength)
{
uint32 char_lengt= len_arg/cs->mbmaxlen;
packlength= char_length <= 255 ? 1 :
char_length <= 65535 ? 2 :
char_length <= 16777215 ? 3 : 4;
}
}
enum_field_types type() const { return FIELD_TYPE_BLOB;}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
......
......@@ -3874,7 +3874,9 @@ Field *Item::make_string_field(TABLE *table)
if (max_length/collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB)
return new Field_blob(max_length, maybe_null, name, table,
collation.collation);
if (max_length > 0)
/* Item_type_holder holds the exact type, do not change it */
if (max_length > 0 &&
(type() != Item::TYPE_HOLDER || field_type() != MYSQL_TYPE_STRING))
return new Field_varstring(max_length, maybe_null, name, table,
collation.collation);
return new Field_string(max_length, maybe_null, name, table,
......@@ -3938,6 +3940,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
case MYSQL_TYPE_TIME:
return new Field_time(maybe_null, name, table, &my_charset_bin);
case MYSQL_TYPE_TIMESTAMP:
return new Field_timestamp(maybe_null, name, table, &my_charset_bin);
case MYSQL_TYPE_DATETIME:
return new Field_datetime(maybe_null, name, table, &my_charset_bin);
case MYSQL_TYPE_YEAR:
......@@ -3961,7 +3964,11 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
return new Field_blob(max_length, maybe_null, name, table,
if (this->type() == Item::TYPE_HOLDER)
return new Field_blob(max_length, maybe_null, name, table,
collation.collation, 1);
else
return new Field_blob(max_length, maybe_null, name, table,
collation.collation);
break; // Blob handled outside of case
}
......@@ -6117,7 +6124,7 @@ uint32 Item_type_holder::display_length(Item *item)
case MYSQL_TYPE_DOUBLE:
return 53;
case MYSQL_TYPE_NULL:
return 4;
return 0;
case MYSQL_TYPE_LONGLONG:
return 20;
case MYSQL_TYPE_INT24:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment