From 73f48615754833e637ba05d2a0d92a0ea5c2d5cf Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 29 Mar 2014 11:33:20 +0100 Subject: MDEV-5969 Crash in prepared statement with NO_ZERO_IN_DATE and ROLLUP MDEV-5971 Asymmetry between CAST(DATE'2001-00-00') to INT and TO CHAR in prepared statements Consistently set maybe_null flag, even not-NULL temporal literal may become NULL in the restrictive sql_mode. --- sql/item.cc | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) (limited to 'sql/item.cc') diff --git a/sql/item.cc b/sql/item.cc index 7c04dc00880..9b27f730e80 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -341,12 +341,29 @@ String *Item::val_string_from_decimal(String *str) } +/* + All val_xxx_from_date() must call this method, to expose consistent behaviour + regarding SQL_MODE when converting DATE/DATETIME to other data types. +*/ +bool Item::get_temporal_with_sql_mode(MYSQL_TIME *ltime) +{ + return get_date(ltime, field_type() == MYSQL_TYPE_TIME + ? TIME_TIME_ONLY + : sql_mode_for_dates(current_thd)); +} + + +bool Item::is_null_from_temporal() +{ + MYSQL_TIME ltime; + return get_temporal_with_sql_mode(<ime); +} + + String *Item::val_string_from_date(String *str) { MYSQL_TIME ltime; - if (get_date(<ime, field_type() == MYSQL_TYPE_TIME - ? TIME_TIME_ONLY - : sql_mode_for_dates(current_thd)) || + if (get_temporal_with_sql_mode(<ime) || str->alloc(MAX_DATE_STRING_REP_LENGTH)) { null_value= 1; @@ -403,7 +420,7 @@ my_decimal *Item::val_decimal_from_date(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; - if (get_date(<ime, sql_mode_for_dates(current_thd))) + if (get_temporal_with_sql_mode(<ime)) { my_decimal_set_zero(decimal_value); null_value= 1; // set NULL, stop processing @@ -430,7 +447,7 @@ longlong Item::val_int_from_date() { DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; - if (get_date(<ime, 0)) + if (get_temporal_with_sql_mode(<ime)) return 0; longlong v= TIME_to_ulonglong(<ime); return ltime.neg ? -v : v; @@ -441,7 +458,7 @@ double Item::val_real_from_date() { DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; - if (get_date(<ime, 0)) + if (get_temporal_with_sql_mode(<ime)) return 0; return TIME_to_double(<ime); } -- cgit v1.2.1