Commit 09b08edc authored by dlenev@mysql.com's avatar dlenev@mysql.com

Merge bk-internal.mysql.com:/home/bk/mysql-4.1

into mysql.com:/home/dlenev/src/mysql-4.1-tzbug
parents bcf1cb0f c80c503a
...@@ -303,3 +303,11 @@ delete from mysql.db where user like 'mysqltest\_%'; ...@@ -303,3 +303,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;
...@@ -1656,6 +1656,7 @@ void Item_func_convert_tz::fix_length_and_dec() ...@@ -1656,6 +1656,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;
} }
...@@ -1668,12 +1669,6 @@ Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **re ...@@ -1668,12 +1669,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 0; return 0;
} }
...@@ -1713,13 +1708,19 @@ bool Item_func_convert_tz::get_date(TIME *ltime, ...@@ -1713,13 +1708,19 @@ bool Item_func_convert_tz::get_date(TIME *ltime,
my_time_t my_time_tmp; my_time_t my_time_tmp;
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, 0)) if (from_tz==0 || to_tz==0 || get_arg0_date(ltime, 0))
{ {
null_value= 1; null_value= 1;
...@@ -1741,6 +1742,13 @@ bool Item_func_convert_tz::get_date(TIME *ltime, ...@@ -1741,6 +1742,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() { return (double) val_int(); } double val() { 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();
}; };
......
...@@ -2438,8 +2438,15 @@ bool sys_var_thd_time_zone::check(THD *thd, set_var *var) ...@@ -2438,8 +2438,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;
} }
...@@ -2451,27 +2458,25 @@ byte *sys_var_thd_time_zone::value_ptr(THD *thd, enum_var_type type, ...@@ -2451,27 +2458,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);
} }
...@@ -2480,6 +2485,7 @@ void sys_var_thd_time_zone::set_default(THD *thd, enum_var_type type) ...@@ -2480,6 +2485,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);
} }
/* /*
......
...@@ -736,7 +736,6 @@ public: ...@@ -736,7 +736,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);
}; };
/**************************************************************************** /****************************************************************************
......
...@@ -1718,8 +1718,8 @@ st_lex::st_lex() ...@@ -1718,8 +1718,8 @@ st_lex::st_lex()
global_first Save first global table here global_first Save first global table here
local_first Save first local table here local_first Save first local table here
NORES NOTES
global_first & local_first are used to save result for link_first_table_back This function assumes that outer select list is non-empty.
RETURN RETURN
global list without first table global list without first table
...@@ -1729,25 +1729,25 @@ TABLE_LIST *st_lex::unlink_first_table(TABLE_LIST *tables, ...@@ -1729,25 +1729,25 @@ TABLE_LIST *st_lex::unlink_first_table(TABLE_LIST *tables,
TABLE_LIST **global_first, TABLE_LIST **global_first,
TABLE_LIST **local_first) TABLE_LIST **local_first)
{ {
*global_first= tables; DBUG_ASSERT(select_lex.table_list.first != 0);
*local_first= (TABLE_LIST*)select_lex.table_list.first;
/* /*
Exclude from global table list Save pointers to first elements of global table list and list
of tables used in outer select. It does not harm if these lists
are the same.
*/ */
*global_first= tables;
*local_first= (TABLE_LIST*)select_lex.table_list.first;
/* Exclude first elements from these lists */
select_lex.table_list.first= (byte*) (*local_first)->next;
tables= tables->next; tables= tables->next;
/*
and from local list if it is not the same
*/
select_lex.table_list.first= ((&select_lex != all_selects_list) ?
(byte*) (*local_first)->next :
(byte*) tables);
(*global_first)->next= 0; (*global_first)->next= 0;
return tables; return tables;
} }
/* /*
Link table back that was unlinked with unlink_first_table() Link table which was unlinked with unlink_first_table() back.
SYNOPSIS SYNOPSIS
link_first_table_back() link_first_table_back()
...@@ -1763,16 +1763,7 @@ TABLE_LIST *st_lex::link_first_table_back(TABLE_LIST *tables, ...@@ -1763,16 +1763,7 @@ TABLE_LIST *st_lex::link_first_table_back(TABLE_LIST *tables,
TABLE_LIST *local_first) TABLE_LIST *local_first)
{ {
global_first->next= tables; global_first->next= tables;
if (&select_lex != all_selects_list) select_lex.table_list.first= (byte*) local_first;
{
/*
we do not touch local table 'next' field => we need just
put the table in the list
*/
select_lex.table_list.first= (byte*) local_first;
}
else
select_lex.table_list.first= (byte*) global_first;
return global_first; return global_first;
} }
......
...@@ -1773,7 +1773,13 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) ...@@ -1773,7 +1773,13 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr, if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
0, HA_READ_KEY_EXACT)) 0, HA_READ_KEY_EXACT))
{ {
sql_print_error("Can't find description of time zone."); #ifdef EXTRA_DEBUG
/*
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
goto end; goto end;
} }
...@@ -1794,7 +1800,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) ...@@ -1794,7 +1800,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr, if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
0, HA_READ_KEY_EXACT)) 0, HA_READ_KEY_EXACT))
{ {
sql_print_error("Can't find description of time zone."); sql_print_error("Can't find description of time zone '%u'", tzid);
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