summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <ramil/ram@mysql.com/ramil.myoffice.izhnet.ru>2007-10-09 14:37:21 +0500
committerunknown <ramil/ram@mysql.com/ramil.myoffice.izhnet.ru>2007-10-09 14:37:21 +0500
commit1a5f13a12c2a31ffa1a1a5b846bd4ab6e321992f (patch)
tree86dc5161ba458db55814dd72f4c05644f7922396
parent6dc4dfb363ef20f5850a0459d11a8b6ed4777040 (diff)
downloadmariadb-git-1a5f13a12c2a31ffa1a1a5b846bd4ab6e321992f.tar.gz
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. mysql-test/r/type_datetime.result: Fix for bug #31249: Assertion `!table || (!table->write_set || bitmap_is_set(table->write_set, fiel - test result. mysql-test/t/type_datetime.test: Fix for bug #31249: Assertion `!table || (!table->write_set || bitmap_is_set(table->write_set, fiel - test case. sql/item_timefunc.h: Fix for bug #31249: Assertion `!table || (!table->write_set || bitmap_is_set(table->write_set, fiel - set Item_datetime_typecast::max_length properly. sql/sql_select.cc: Fix for bug #31249: Assertion `!table || (!table->write_set || bitmap_is_set(table->write_set, fiel - the group buffer key length for items represented as DATE/TIME fields in the buffer should be calculated using the maximum pack length of such fields (== 8), using max_length here is redundant.
-rw-r--r--mysql-test/r/type_datetime.result14
-rw-r--r--mysql-test/t/type_datetime.test13
-rw-r--r--sql/item_timefunc.h4
-rw-r--r--sql/sql_select.cc26
4 files changed, 52 insertions, 5 deletions
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 9e47b5da2b6..b96ed330d73 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -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
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index ffda593f320..070230bae75 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -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
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 8e925a0156f..94bee28bb6b 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -844,7 +844,9 @@ public:
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;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 1d11f23d854..7d4421b2749 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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();
/*
- 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.
+ 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.
*/
- key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
+ 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);