Fix for bug #31249: Assertion `!table || (!table->write_set ||

bitmap_is_set(table->write_set, fiel

Problem: creating a temporary table we allocate the group buffer if needed
followed by table bitmaps (see create_tmp_table()). Reserving less memory for 
the group buffer than actually needed (used) for values retrieval may lead 
to overlapping with followed bitmaps in the memory pool that in turn leads 
to unpredictable consequences.

As we use Item->max_length sometimes to calculate group buffer size,
it must be set to proper value. In this particular case 
Item_datetime_typecast::max_length is too small.

Another problem is that we use max_length to calculate the group buffer
key length for items represented as DATE/TIME fields which is superfluous.

Fix: set Item_datetime_typecast::max_length properly,
accurately calculate the group buffer key length for items 
represented as DATE/TIME fields in the buffer.
parent 6e6727d2
......@@ -427,3 +427,17 @@ f1
Warnings:
Warning 1292 Incorrect datetime value: '2007010100000' for column 'f1' at row 1
drop table t1;
create table t1 (a tinyint);
insert into t1 values (), (), ();
select sum(a) from t1 group by convert(a, datetime);
sum(a)
NULL
select convert(a, datetime) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def convert(a, datetime) 12 29 0 Y 128 6 63
convert(a, datetime)
NULL
NULL
NULL
drop table t1;
End of 5.0 tests
......@@ -282,3 +282,16 @@ select * from t1 where f1 between 20020101 and 20070101000000;
select * from t1 where f1 between 2002010 and 20070101000000;
select * from t1 where f1 between 20020101 and 2007010100000;
drop table t1;
#
# Bug #31249: problem with convert(..., datetime)
#
create table t1 (a tinyint);
insert into t1 values (), (), ();
select sum(a) from t1 group by convert(a, datetime);
--enable_metadata
select convert(a, datetime) from t1;
--disable_metadata
drop table t1;
--echo End of 5.0 tests
......@@ -844,7 +844,9 @@ class Item_datetime_typecast :public Item_typecast_maybe_null
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
void fix_length_and_dec()
{
Item_typecast_maybe_null::fix_length_and_dec();
collation.set(&my_charset_bin);
maybe_null= 1;
max_length= MAX_DATETIME_FULL_WIDTH * MY_CHARSET_BIN_MB_MAXLEN;
decimals= DATETIME_DEC;
}
......
......@@ -13902,13 +13902,31 @@ calc_group_buffer(JOIN *join,ORDER *group)
group_item->decimals);
break;
case STRING_RESULT:
{
enum enum_field_types type= group_item->field_type();
/*
As items represented as DATE/TIME fields in the group buffer
have STRING_RESULT result type, we increase the length
by 8 as maximum pack length of such fields.
*/
if (type == MYSQL_TYPE_TIME ||
type == MYSQL_TYPE_DATE ||
type == MYSQL_TYPE_DATETIME ||
type == MYSQL_TYPE_TIMESTAMP)
{
key_length+= 8;
}
else
{
/*
Group strings are taken as varstrings and require an length field.
A field is not yet created by create_tmp_field()
and the sizes should match up.
*/
key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
}
break;
}
default:
/* This case should never be choosen */
DBUG_ASSERT(0);
......
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