summaryrefslogtreecommitdiff
path: root/sql/tztime.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/tztime.cc')
-rw-r--r--sql/tztime.cc306
1 files changed, 170 insertions, 136 deletions
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 2ed55f2fa4e..757272d332f 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1359,6 +1359,13 @@ static bool tz_inited= 0;
static uint tz_leapcnt= 0;
static LS_INFO *tz_lsis= 0;
+/*
+ Shows whenever we have found time zone tables during start-up.
+ Used for avoiding of putting those tables to global table list
+ for queries that use time zone info.
+*/
+static bool time_zone_tables_exist= 1;
+
typedef struct st_tz_names_entry: public Sql_alloc
{
@@ -1388,6 +1395,68 @@ extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length,
/*
+ Prepare table list with time zone related tables from preallocated array.
+
+ SYNOPSIS
+ tz_init_table_list()
+ tz_tabs - pointer to preallocated array of 4 TABLE_LIST objects.
+
+ DESCRIPTION
+ This function prepares list of TABLE_LIST objects which can be used
+ for opening of time zone tables from preallocated array.
+*/
+
+void
+tz_init_table_list(TABLE_LIST *tz_tabs)
+{
+ bzero(tz_tabs, sizeof(TABLE_LIST) * 4);
+ tz_tabs[0].alias= tz_tabs[0].real_name= (char*)"time_zone_name";
+ tz_tabs[1].alias= tz_tabs[1].real_name= (char*)"time_zone";
+ tz_tabs[2].alias= tz_tabs[2].real_name= (char*)"time_zone_transition_type";
+ tz_tabs[3].alias= tz_tabs[3].real_name= (char*)"time_zone_transition";
+ tz_tabs[0].next= tz_tabs+1;
+ tz_tabs[1].next= tz_tabs+2;
+ tz_tabs[2].next= tz_tabs+3;
+ tz_tabs[0].lock_type= tz_tabs[1].lock_type= tz_tabs[2].lock_type=
+ tz_tabs[3].lock_type= TL_READ;
+ tz_tabs[0].db= tz_tabs[1].db= tz_tabs[2].db= tz_tabs[3].db= (char *)"mysql";
+}
+
+
+/*
+ Create table list with time zone related tables.
+
+ SYNOPSIS
+ my_tz_get_table_list()
+ thd - current thread object
+
+ DESCRIPTION
+ This function creates list of TABLE_LIST objects allocated in thd's
+ memroot, which can be used for opening of time zone tables.
+
+ RETURN VALUES
+ Returns pointer to first TABLE_LIST object, (could be 0 if time zone
+ tables don't exist) and &fake_time_zone_tables_list in case of error.
+*/
+
+TABLE_LIST *
+my_tz_get_table_list(THD *thd)
+{
+ TABLE_LIST *tz_tabs;
+
+ if (!time_zone_tables_exist)
+ return 0;
+
+ if (!(tz_tabs= (TABLE_LIST *)thd->alloc(sizeof(TABLE_LIST) * 4)))
+ return &fake_time_zone_tables_list;
+
+ tz_init_table_list(tz_tabs);
+
+ return tz_tabs;
+}
+
+
+/*
Initialize time zone support infrastructure.
SYNOPSIS
@@ -1399,13 +1468,13 @@ extern "C" byte* my_offset_tzs_get_key(Time_zone_offset *entry, uint *length,
DESCRIPTION
This function will init memory structures needed for time zone support,
it will register mandatory SYSTEM time zone in them. It will try to open
- mysql.time_zone_leap_seconds table and and load information which further
- will be shared among all time zones loaded. It will also try to load
- information about default time zone. If system tables with time zone
- descriptions don't exist it won't fail (unless default_tzname is time zone
- from tables). If bootstrap parameter is true then this routine assumes that
- we are in bootstrap mode and won't load time zone descriptions unless someone
- specifies default time zone which is supposedly stored in those tables.
+ mysql.time_zone* tables and load information about default time zone and
+ information which further will be shared among all time zones loaded.
+ If system tables with time zone descriptions don't exist it won't fail
+ (unless default_tzname is time zone from tables). If bootstrap parameter
+ is true then this routine assumes that we are in bootstrap mode and won't
+ load time zone descriptions unless someone specifies default time zone
+ which is supposedly stored in those tables.
It'll also set default time zone if it is specified.
RETURN VALUES
@@ -1416,14 +1485,13 @@ my_bool
my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
{
THD *thd;
- TABLE_LIST tables;
+ TABLE_LIST *tables= 0;
+ TABLE_LIST tables_buff[5];
TABLE *table;
- TABLE *lock_ptr;
- MYSQL_LOCK *lock;
TZ_NAMES_ENTRY *tmp_tzname;
my_bool return_val= 1;
int res;
- uint not_used;
+ uint counter;
DBUG_ENTER("my_tz_init");
/*
@@ -1468,7 +1536,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
if (bootstrap)
{
/* If we are in bootstrap mode we should not load time zone tables */
- return_val= 0;
+ return_val= time_zone_tables_exist= 0;
goto end_with_setting_default_tz;
}
@@ -1480,28 +1548,25 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
thd->db= my_strdup("mysql",MYF(0));
thd->db_length= 5; // Safety
- bzero((char*) &tables,sizeof(tables));
- tables.alias= tables.real_name= (char*)"time_zone_leap_second";
- tables.lock_type= TL_READ;
- tables.db= thd->db;
-
- if (open_tables(thd, &tables, &not_used))
+ bzero((char*) &tables_buff, sizeof(TABLE_LIST));
+ tables_buff[0].alias= tables_buff[0].real_name=
+ (char*)"time_zone_leap_second";
+ tables_buff[0].lock_type= TL_READ;
+ tables_buff[0].db= thd->db;
+ tables_buff[0].next= tables_buff + 1;
+ /* Fill TABLE_LIST for rest of the time zone describing tables */
+ tz_init_table_list(tables_buff + 1);
+
+ if (open_tables(thd, tables_buff, &counter) ||
+ lock_tables(thd, tables_buff, counter))
{
- sql_print_error("Warning: Can't open time zone table: %s "
+ sql_print_error("Warning: Can't open and lock time zone table: %s "
"trying to live without them", thd->net.last_error);
/* We will try emulate that everything is ok */
- return_val= 0;
+ return_val= time_zone_tables_exist= 0;
goto end_with_setting_default_tz;
}
-
- lock_ptr= tables.table;
- if (!(lock= mysql_lock_tables(thd, &lock_ptr, 1)))
- {
- sql_print_error("Fatal error: Can't lock time zone table: %s",
- thd->net.last_error);
- goto end_with_close;
- }
-
+ tables= tables_buff + 1;
/*
Now we are going to load leap seconds descriptions that are shared
@@ -1514,11 +1579,16 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
{
sql_print_error("Fatal error: Out of memory while loading "
"mysql.time_zone_leap_second table");
- goto end_with_unlock;
+ goto end_with_close;
}
- table= tables.table;
- table->file->ha_index_init(0);
+ table= tables_buff[0].table;
+ /*
+ It is OK to ignore ha_index_init()/ha_index_end() return values since
+ mysql.time_zone* tables are MyISAM and these operations always succeed
+ for MyISAM.
+ */
+ (void)table->file->ha_index_init(0);
tz_leapcnt= 0;
res= table->file->index_first(table->record[0]);
@@ -1530,7 +1600,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
sql_print_error("Fatal error: While loading mysql.time_zone_leap_second"
" table: too much leaps");
table->file->ha_index_end();
- goto end_with_unlock;
+ goto end_with_close;
}
tz_lsis[tz_leapcnt].ls_trans= (my_time_t)table->field[0]->val_int();
@@ -1546,13 +1616,13 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
res= table->file->index_next(table->record[0]);
}
- table->file->ha_index_end();
+ (void)table->file->ha_index_end();
if (res != HA_ERR_END_OF_FILE)
{
sql_print_error("Fatal error: Error while loading "
"mysql.time_zone_leap_second table");
- goto end_with_unlock;
+ goto end_with_close;
}
/*
@@ -1562,19 +1632,12 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
return_val= 0;
-end_with_unlock:
- mysql_unlock_tables(thd, lock);
-
-end_with_close:
- close_thread_tables(thd);
- thd->version--; /* Force close to free memory */
-
end_with_setting_default_tz:
- /* If not an error and have default time zone try to load it */
- if (!return_val && default_tzname)
+ /* If we have default time zone try to load it */
+ if (default_tzname)
{
String tzname(default_tzname, &my_charset_latin1);
- if (!(global_system_variables.time_zone= my_tz_find(thd, &tzname)))
+ if (!(global_system_variables.time_zone= my_tz_find(&tzname, tables)))
{
sql_print_error("Fatal error: Illegal or unknown default time zone '%s'",
default_tzname);
@@ -1582,6 +1645,10 @@ end_with_setting_default_tz:
}
}
+end_with_close:
+ thd->version--; /* Force close to free memory */
+ close_thread_tables(thd);
+
end_with_cleanup:
/* if there were error free time zone describing structs */
@@ -1625,29 +1692,27 @@ void my_tz_free()
Load time zone description from system tables.
SYNOPSIS
- tz_load_from_db()
- thd - current thread object
- tz_name - name of time zone that should be loaded.
+ tz_load_from_open_tables()
+ tz_name - name of time zone that should be loaded.
+ tz_tables - list of tables from which time zone description
+ should be loaded
DESCRIPTION
- This function will try to open system tables describing time zones
- and to load information about time zone specified. It will also update
- information in hash used for time zones lookup.
+ This function will try to load information about time zone specified
+ from the list of the already opened and locked tables (first table in
+ tz_tables should be time_zone_name, next time_zone, then
+ time_zone_transition_type and time_zone_transition should be last).
+ It will also update information in hash used for time zones lookup.
RETURN VALUES
Returns pointer to newly created Time_zone object or 0 in case of error.
*/
+
static Time_zone*
-tz_load_from_db(THD *thd, const String *tz_name)
+tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
{
- TABLE_LIST tables[4];
TABLE *table= 0;
- TABLE *lock_ptr[4];
- MYSQL_LOCK *lock;
- char system_db_name[]= "mysql";
- char *db_save;
- uint db_length_save;
TIME_ZONE_INFO *tz_info;
TZ_NAMES_ENTRY *tmp_tzname;
Time_zone *return_val= 0;
@@ -1667,9 +1732,8 @@ tz_load_from_db(THD *thd, const String *tz_name)
#ifdef ABBR_ARE_USED
char chars[max(TZ_MAX_CHARS + 1, (2 * (MY_TZNAME_MAX + 1)))];
#endif
- uint not_used;
- DBUG_ENTER("tz_load_from_db");
+ DBUG_ENTER("tz_load_from_open_tables");
/* Prepare tz_info for loading also let us make copy of time zone name */
@@ -1690,76 +1754,45 @@ tz_load_from_db(THD *thd, const String *tz_name)
strmake(tz_name_buff, tz_name->ptr(), tz_name->length());
/*
- Open and lock time zone description tables
- */
- db_save= thd->db;
- db_length_save= thd->db_length;
- thd->db= system_db_name;
- thd->db_length= 5;
-
- bzero((char*) &tables,sizeof(tables));
- tables[0].alias= tables[0].real_name= (char*)"time_zone_name";
- tables[1].alias= tables[1].real_name= (char*)"time_zone";
- tables[2].alias= tables[2].real_name= (char*)"time_zone_transition";
- tables[3].alias= tables[3].real_name= (char*)"time_zone_transition_type";
- tables[0].next= tables+1;
- tables[1].next= tables+2;
- tables[2].next= tables+3;
- tables[0].lock_type= tables[1].lock_type= tables[2].lock_type=
- tables[3].lock_type= TL_READ;
- tables[0].db= tables[1].db= tables[2].db= tables[3].db= thd->db;
- if (open_tables(thd, tables, &not_used))
- {
- sql_print_error("Error: Can't open time zone tables: %s",
- thd->net.last_error);
- goto end;
- }
-
- lock_ptr[0]= tables[0].table;
- lock_ptr[1]= tables[1].table;
- lock_ptr[2]= tables[2].table;
- lock_ptr[3]= tables[3].table;
- if (!(lock= mysql_lock_tables(thd, lock_ptr, 4)))
- {
- sql_print_error("Error: Can't lock time zone tables: %s",
- thd->net.last_error);
- goto end_with_close;
- }
-
- /*
Let us find out time zone id by its name (there is only one index
and it is specifically for this purpose).
*/
- table= tables[0].table;
-
+ table= tz_tables->table;
+ tz_tables= tz_tables->next;
table->field[0]->store(tz_name->ptr(), tz_name->length(), &my_charset_latin1);
- table->file->ha_index_init(0);
+ /*
+ It is OK to ignore ha_index_init()/ha_index_end() return values since
+ mysql.time_zone* tables are MyISAM and these operations always succeed
+ for MyISAM.
+ */
+ (void)table->file->ha_index_init(0);
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
0, HA_READ_KEY_EXACT))
{
sql_print_error("Error: Can't find description of time zone.");
- goto end_with_unlock;
+ goto end;
}
tzid= (uint)table->field[1]->val_int();
- table->file->ha_index_end();
+ (void)table->file->ha_index_end();
/*
Now we need to lookup record in mysql.time_zone table in order to
understand whenever this timezone uses leap seconds (again we are
using the only index in this table).
*/
- table= tables[1].table;
+ table= tz_tables->table;
+ tz_tables= tz_tables->next;
table->field[0]->store((longlong)tzid);
- table->file->ha_index_init(0);
+ (void)table->file->ha_index_init(0);
if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
0, HA_READ_KEY_EXACT))
{
sql_print_error("Error: Can't find description of time zone.");
- goto end_with_unlock;
+ goto end;
}
/* If Uses_leap_seconds == 'Y' */
@@ -1769,7 +1802,7 @@ tz_load_from_db(THD *thd, const String *tz_name)
tz_info->lsis= tz_lsis;
}
- table->file->ha_index_end();
+ (void)table->file->ha_index_end();
/*
Now we will iterate through records for out time zone in
@@ -1777,9 +1810,10 @@ tz_load_from_db(THD *thd, const String *tz_name)
only for our time zone guess what are we doing?
Right - using special index.
*/
- table= tables[3].table;
+ table= tz_tables->table;
+ tz_tables= tz_tables->next;
table->field[0]->store((longlong)tzid);
- table->file->ha_index_init(0);
+ (void)table->file->ha_index_init(0);
// FIXME Is there any better approach than explicitly specifying 4 ???
res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
@@ -1793,7 +1827,7 @@ tz_load_from_db(THD *thd, const String *tz_name)
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition_type table: too big "
"transition type id");
- goto end_with_unlock;
+ goto end;
}
ttis[ttid].tt_gmtoff= (long)table->field[2]->val_int();
@@ -1807,7 +1841,7 @@ tz_load_from_db(THD *thd, const String *tz_name)
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition_type table: not enough "
"room for abbreviations");
- goto end_with_unlock;
+ goto end;
}
ttis[ttid].tt_abbrind= tz_info->charcnt;
memcpy(chars + tz_info->charcnt, abbr.ptr(), abbr.length());
@@ -1838,10 +1872,10 @@ tz_load_from_db(THD *thd, const String *tz_name)
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition_type table");
- goto end_with_unlock;
+ goto end;
}
- table->file->ha_index_end();
+ (void)table->file->ha_index_end();
/*
@@ -1849,9 +1883,9 @@ tz_load_from_db(THD *thd, const String *tz_name)
mysql.time_zone_transition table. Here we additionaly need records
in ascending order by index scan also satisfies us.
*/
- table= tables[2].table;
+ table= tz_tables->table;
table->field[0]->store((longlong)tzid);
- table->file->ha_index_init(0);
+ (void)table->file->ha_index_init(0);
// FIXME Is there any better approach than explicitly specifying 4 ???
res= table->file->index_read(table->record[0], (byte*)table->field[0]->ptr,
@@ -1866,14 +1900,14 @@ tz_load_from_db(THD *thd, const String *tz_name)
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition table: "
"too much transitions");
- goto end_with_unlock;
+ goto end;
}
if (ttid + 1 > tz_info->typecnt)
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition table: "
"bad transition type id");
- goto end_with_unlock;
+ goto end;
}
ats[tz_info->timecnt]= ttime;
@@ -1896,10 +1930,10 @@ tz_load_from_db(THD *thd, const String *tz_name)
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition table");
- goto end_with_unlock;
+ goto end;
}
- table->file->ha_index_end();
+ (void)table->file->ha_index_end();
table= 0;
/*
@@ -1916,7 +1950,7 @@ tz_load_from_db(THD *thd, const String *tz_name)
{
sql_print_error("Error: Out of memory while loading time zone "
"description");
- goto end_with_unlock;
+ goto end;
}
@@ -1941,12 +1975,12 @@ tz_load_from_db(THD *thd, const String *tz_name)
if (tz_info->typecnt < 1)
{
sql_print_error("Error: loading time zone without transition types");
- goto end_with_unlock;
+ goto end;
}
if (prepare_tz_info(tz_info, &tz_storage))
{
sql_print_error("Error: Unable to build mktime map for time zone");
- goto end_with_unlock;
+ goto end;
}
@@ -1958,7 +1992,7 @@ tz_load_from_db(THD *thd, const String *tz_name)
my_hash_insert(&tz_names, (const byte *)tmp_tzname)))
{
sql_print_error("Error: Out of memory while loading time zone");
- goto end_with_unlock;
+ goto end;
}
/*
@@ -1966,19 +2000,11 @@ tz_load_from_db(THD *thd, const String *tz_name)
*/
return_val= tmp_tzname->tz;
-end_with_unlock:
+end:
if (table)
- table->file->ha_index_end();
-
- mysql_unlock_tables(thd, lock);
+ (void)table->file->ha_index_end();
-end_with_close:
- close_thread_tables(thd);
-
-end:
- thd->db= db_save;
- thd->db_length= db_length_save;
DBUG_RETURN(return_val);
}
@@ -2068,8 +2094,8 @@ str_to_offset(const char *str, uint length, long *offset)
SYNOPSIS
my_tz_find()
- thd - current thread
name - time zone specification
+ tz_tables - list of opened'n'locked time zone describing tables
DESCRIPTION
This function checks if name is one of time zones described in db,
@@ -2091,7 +2117,11 @@ str_to_offset(const char *str, uint length, long *offset)
values as parameter without additional external check and this property
is used by @@time_zone variable handling code).
- It will perform lookup in system tables (mysql.time_zone*) if needed.
+ It will perform lookup in system tables (mysql.time_zone*) if needed
+ using tz_tables as list of already opened tables (for info about this
+ list look at tz_load_from_open_tables() description). It won't perform
+ such lookup if no time zone describing tables were found during server
+ start up.
RETURN VALUE
Pointer to corresponding Time_zone object. 0 - in case of bad time zone
@@ -2099,7 +2129,7 @@ str_to_offset(const char *str, uint length, long *offset)
*/
Time_zone *
-my_tz_find(THD *thd, const String * name)
+my_tz_find(const String * name, TABLE_LIST *tz_tables)
{
TZ_NAMES_ENTRY *tmp_tzname;
Time_zone *result_tz= 0;
@@ -2109,6 +2139,8 @@ my_tz_find(THD *thd, const String * name)
DBUG_PRINT("enter", ("time zone name='%s'",
name ? ((String *)name)->c_ptr() : "NULL"));
+ DBUG_ASSERT(!time_zone_tables_exist || tz_tables);
+
if (!name)
DBUG_RETURN(0);
@@ -2136,8 +2168,10 @@ my_tz_find(THD *thd, const String * name)
(const byte *)name->ptr(),
name->length())))
result_tz= tmp_tzname->tz;
+ else if(time_zone_tables_exist)
+ result_tz= tz_load_from_open_tables(name, tz_tables);
else
- result_tz= tz_load_from_db(thd, name);
+ result_tz= 0;
}
VOID(pthread_mutex_unlock(&tz_LOCK));