Commit 8cac2c05 authored by unknown's avatar unknown

Manual merge of fixes for bugs #7899 "CREATE TABLE .. SELECT .. and

CONVERT_TZ() function does not work well together" and bug #7705 
"CONVERT_TZ() crashes with subquery/WHERE on index column" in 5.0
tree.


mysql-test/r/timezone2.result:
  Auto merged
mysql-test/t/timezone2.test:
  Auto merged
sql/item_timefunc.cc:
  Auto merged
sql/item_timefunc.h:
  Auto merged
sql/set_var.h:
  Auto merged
sql/set_var.cc:
  Manual merge.
sql/sql_lex.cc:
  Ignoring changes in st_lex::unlink_first_table()/link_first_table_back()
  made in 4.1 since they are not applicable to 5.0.
sql/tztime.cc:
  Manual merge.
parents a6bfe13c bf89dc06
...@@ -305,3 +305,11 @@ delete from mysql.db where user like 'mysqltest\_%'; ...@@ -305,3 +305,11 @@ delete from mysql.db where user like 'mysqltest\_%';
delete from mysql.tables_priv where user like 'mysqltest\_%'; delete from mysql.tables_priv where user like 'mysqltest\_%';
flush privileges; flush privileges;
drop table t1, t2; drop table t1, t2;
select convert_tz('2005-01-14 17:00:00', 'UTC', custTimeZone) from (select 'UTC' as custTimeZone) as tmp;
convert_tz('2005-01-14 17:00:00', 'UTC', custTimeZone)
2005-01-14 17:00:00
create table t1 select convert_tz(NULL, NULL, NULL);
select * from t1;
convert_tz(NULL, NULL, NULL)
NULL
drop table t1;
...@@ -266,3 +266,20 @@ delete from mysql.db where user like 'mysqltest\_%'; ...@@ -266,3 +266,20 @@ delete from mysql.db where user like 'mysqltest\_%';
delete from mysql.tables_priv where user like 'mysqltest\_%'; delete from mysql.tables_priv where user like 'mysqltest\_%';
flush privileges; flush privileges;
drop table t1, t2; drop table t1, t2;
#
# Test for bug #7705 "CONVERT_TZ() crashes with subquery/WHERE on index
# column". Queries in which one of time zone arguments of CONVERT_TZ() is
# determined as constant only at val() stage (not at fix_fields() stage),
# should not crash server.
#
select convert_tz('2005-01-14 17:00:00', 'UTC', custTimeZone) from (select 'UTC' as custTimeZone) as tmp;
#
# Test for bug #7899 "CREATE TABLE .. SELECT .. and CONVERT_TZ() function
# does not work well together". The following statement should return only
# one NULL row and not result of full join.
#
create table t1 select convert_tz(NULL, NULL, NULL);
select * from t1;
drop table t1;
...@@ -1662,6 +1662,7 @@ void Item_func_convert_tz::fix_length_and_dec() ...@@ -1662,6 +1662,7 @@ void Item_func_convert_tz::fix_length_and_dec()
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
decimals= 0; decimals= 0;
max_length= MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; max_length= MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null= 1;
} }
...@@ -1674,12 +1675,6 @@ Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **re ...@@ -1674,12 +1675,6 @@ Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **re
tz_tables= thd_arg->lex->time_zone_tables_used; tz_tables= thd_arg->lex->time_zone_tables_used;
if (args[1]->const_item())
from_tz= my_tz_find(args[1]->val_str(&str), tz_tables);
if (args[2]->const_item())
to_tz= my_tz_find(args[2]->val_str(&str), tz_tables);
return FALSE; return FALSE;
} }
...@@ -1720,11 +1715,17 @@ bool Item_func_convert_tz::get_date(TIME *ltime, ...@@ -1720,11 +1715,17 @@ bool Item_func_convert_tz::get_date(TIME *ltime,
bool not_used; bool not_used;
String str; String str;
if (!args[1]->const_item()) if (!from_tz_cached)
{
from_tz= my_tz_find(args[1]->val_str(&str), tz_tables); from_tz= my_tz_find(args[1]->val_str(&str), tz_tables);
from_tz_cached= args[1]->const_item();
}
if (!args[2]->const_item()) if (!to_tz_cached)
{
to_tz= my_tz_find(args[2]->val_str(&str), tz_tables); to_tz= my_tz_find(args[2]->val_str(&str), tz_tables);
to_tz_cached= args[2]->const_item();
}
if (from_tz==0 || to_tz==0 || get_arg0_date(ltime, TIME_NO_ZERO_DATE)) if (from_tz==0 || to_tz==0 || get_arg0_date(ltime, TIME_NO_ZERO_DATE))
{ {
...@@ -1747,6 +1748,13 @@ bool Item_func_convert_tz::get_date(TIME *ltime, ...@@ -1747,6 +1748,13 @@ bool Item_func_convert_tz::get_date(TIME *ltime,
} }
void Item_func_convert_tz::cleanup()
{
from_tz_cached= to_tz_cached= 0;
Item_date_func::cleanup();
}
void Item_date_add_interval::fix_length_and_dec() void Item_date_add_interval::fix_length_and_dec()
{ {
enum_field_types arg0_field_type; enum_field_types arg0_field_type;
......
...@@ -545,12 +545,15 @@ class Item_func_convert_tz :public Item_date_func ...@@ -545,12 +545,15 @@ class Item_func_convert_tz :public Item_date_func
TABLE_LIST *tz_tables; TABLE_LIST *tz_tables;
/* /*
If time zone parameters are constants we are caching objects that If time zone parameters are constants we are caching objects that
represent them. represent them (we use separate from_tz_cached/to_tz_cached members
to indicate this fact, since NULL is legal value for from_tz/to_tz
members.
*/ */
bool from_tz_cached, to_tz_cached;
Time_zone *from_tz, *to_tz; Time_zone *from_tz, *to_tz;
public: public:
Item_func_convert_tz(Item *a, Item *b, Item *c): Item_func_convert_tz(Item *a, Item *b, Item *c):
Item_date_func(a, b, c) {} Item_date_func(a, b, c), from_tz_cached(0), to_tz_cached(0) {}
longlong val_int(); longlong val_int();
double val_real() { return (double) val_int(); } double val_real() { return (double) val_int(); }
String *val_str(String *str); String *val_str(String *str);
...@@ -558,6 +561,7 @@ class Item_func_convert_tz :public Item_date_func ...@@ -558,6 +561,7 @@ class Item_func_convert_tz :public Item_date_func
bool fix_fields(THD *, struct st_table_list *, Item **); bool fix_fields(THD *, struct st_table_list *, Item **);
void fix_length_and_dec(); void fix_length_and_dec();
bool get_date(TIME *res, uint fuzzy_date); bool get_date(TIME *res, uint fuzzy_date);
void cleanup();
}; };
......
...@@ -2505,8 +2505,15 @@ bool sys_var_thd_time_zone::check(THD *thd, set_var *var) ...@@ -2505,8 +2505,15 @@ bool sys_var_thd_time_zone::check(THD *thd, set_var *var)
bool sys_var_thd_time_zone::update(THD *thd, set_var *var) bool sys_var_thd_time_zone::update(THD *thd, set_var *var)
{ {
/* We are using Time_zone object found during check() phase */ /* We are using Time_zone object found during check() phase. */
*get_tz_ptr(thd,var->type)= var->save_result.time_zone; if (var->type == OPT_GLOBAL)
{
pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.time_zone= var->save_result.time_zone;
pthread_mutex_unlock(&LOCK_global_system_variables);
}
else
thd->variables.time_zone= var->save_result.time_zone;
return 0; return 0;
} }
...@@ -2518,27 +2525,25 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, ...@@ -2518,27 +2525,25 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type,
We can use ptr() instead of c_ptr() here because String contaning We can use ptr() instead of c_ptr() here because String contaning
time zone name is guaranteed to be zero ended. time zone name is guaranteed to be zero ended.
*/ */
return (byte *)((*get_tz_ptr(thd,type))->get_name()->ptr());
}
Time_zone** sys_var_thd_time_zone::get_tz_ptr(THD *thd,
enum_var_type type)
{
if (type == OPT_GLOBAL) if (type == OPT_GLOBAL)
return &global_system_variables.time_zone; return (byte *)(global_system_variables.time_zone->get_name()->ptr());
else else
return &thd->variables.time_zone; return (byte *)(thd->variables.time_zone->get_name()->ptr());
} }
void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type) void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
{ {
pthread_mutex_lock(&LOCK_global_system_variables);
if (type == OPT_GLOBAL) if (type == OPT_GLOBAL)
{ {
if (default_tz_name) if (default_tz_name)
{ {
String str(default_tz_name, &my_charset_latin1); String str(default_tz_name, &my_charset_latin1);
/*
We are guaranteed to find this time zone since its existence
is checked during start-up.
*/
global_system_variables.time_zone= global_system_variables.time_zone=
my_tz_find(&str, thd->lex->time_zone_tables_used); my_tz_find(&str, thd->lex->time_zone_tables_used);
} }
...@@ -2547,6 +2552,7 @@ void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type) ...@@ -2547,6 +2552,7 @@ void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type)
} }
else else
thd->variables.time_zone= global_system_variables.time_zone; thd->variables.time_zone= global_system_variables.time_zone;
pthread_mutex_unlock(&LOCK_global_system_variables);
} }
......
...@@ -724,7 +724,6 @@ public: ...@@ -724,7 +724,6 @@ public:
bool update(THD *thd, set_var *var); bool update(THD *thd, set_var *var);
byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
virtual void set_default(THD *thd, enum_var_type type); virtual void set_default(THD *thd, enum_var_type type);
Time_zone **get_tz_ptr(THD *thd, enum_var_type type);
}; };
......
...@@ -1807,8 +1807,11 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) ...@@ -1807,8 +1807,11 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
0, HA_READ_KEY_EXACT)) 0, HA_READ_KEY_EXACT))
{ {
#ifdef EXTRA_DEBUG #ifdef EXTRA_DEBUG
sql_print_error("Can't find description of time zone '%.*s'", tz_name->length(), /*
tz_name->ptr()); Most probably user has mistyped time zone name, so no need to bark here
unless we need it for debugging.
*/
sql_print_error("Can't find description of time zone '%s'", tz_name_buff);
#endif #endif
goto end; goto end;
} }
......
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