summaryrefslogtreecommitdiff
path: root/sql/tztime.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/tztime.cc')
-rw-r--r--sql/tztime.cc151
1 files changed, 117 insertions, 34 deletions
diff --git a/sql/tztime.cc b/sql/tztime.cc
index b5ebc9f350a..f5111459da2 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1396,44 +1396,72 @@ 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.
+ Prepare table list with time zone related tables from preallocated array
+ and add to global table list.
SYNOPSIS
tz_init_table_list()
- tz_tabs - pointer to preallocated array of 4 TABLE_LIST objects.
+ tz_tabs - pointer to preallocated array of 4 TABLE_LIST objects
+ global_next_ptr - pointer to variable which points to global_next member
+ of last element of global table list (or list root
+ then list is empty) (in/out).
DESCRIPTION
This function prepares list of TABLE_LIST objects which can be used
- for opening of time zone tables from preallocated array.
+ for opening of time zone tables from preallocated array. It also links
+ this list to the end of global table list (it will read and update
+ accordingly variable pointed by global_next_ptr for this).
*/
-void
-tz_init_table_list(TABLE_LIST *tz_tabs)
+static void
+tz_init_table_list(TABLE_LIST *tz_tabs, TABLE_LIST ***global_next_ptr)
{
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].alias= tz_tabs[0].table_name= (char*)"time_zone_name";
+ tz_tabs[1].alias= tz_tabs[1].table_name= (char*)"time_zone";
+ tz_tabs[2].alias= tz_tabs[2].table_name= (char*)"time_zone_transition_type";
+ tz_tabs[3].alias= tz_tabs[3].table_name= (char*)"time_zone_transition";
+ tz_tabs[0].next_global= tz_tabs[0].next_local= tz_tabs+1;
+ tz_tabs[1].next_global= tz_tabs[1].next_local= tz_tabs+2;
+ tz_tabs[2].next_global= tz_tabs[2].next_local= 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";
+
+ /* Link into global list */
+ tz_tabs[0].prev_global= *global_next_ptr;
+ tz_tabs[1].prev_global= &tz_tabs[0].next_global;
+ tz_tabs[2].prev_global= &tz_tabs[1].next_global;
+ tz_tabs[3].prev_global= &tz_tabs[2].next_global;
+
+ **global_next_ptr= tz_tabs;
+ /* Update last-global-pointer to point to pointer in last table */
+ *global_next_ptr= &tz_tabs[3].next_global;
}
/*
- Create table list with time zone related tables.
+ Fake table list object, pointer to which is returned by
+ my_tz_get_tables_list() as indication of error.
+*/
+TABLE_LIST fake_time_zone_tables_list;
+
+/*
+ Create table list with time zone related tables and add it to the end
+ of global table list.
SYNOPSIS
my_tz_get_table_list()
- thd - current thread object
+ thd - current thread object
+ global_next_ptr - pointer to variable which points to global_next member
+ of last element of global table list (or list root
+ then list is empty) (in/out).
DESCRIPTION
This function creates list of TABLE_LIST objects allocated in thd's
- memroot, which can be used for opening of time zone tables.
+ memroot, which can be used for opening of time zone tables. It will also
+ link this list to the end of global table list (it will read and update
+ accordingly variable pointed by global_next_ptr for this).
NOTE
my_tz_check_n_skip_implicit_tables() function depends on fact that
@@ -1445,19 +1473,20 @@ tz_init_table_list(TABLE_LIST *tz_tabs)
*/
TABLE_LIST *
-my_tz_get_table_list(THD *thd)
+my_tz_get_table_list(THD *thd, TABLE_LIST ***global_next_ptr)
{
TABLE_LIST *tz_tabs;
+ DBUG_ENTER("my_tz_get_table_list");
if (!time_zone_tables_exist)
- return 0;
+ DBUG_RETURN(0);
if (!(tz_tabs= (TABLE_LIST *)thd->alloc(sizeof(TABLE_LIST) * 4)))
- return &fake_time_zone_tables_list;
+ DBUG_RETURN(&fake_time_zone_tables_list);
- tz_init_table_list(tz_tabs);
+ tz_init_table_list(tz_tabs, global_next_ptr);
- return tz_tabs;
+ DBUG_RETURN(tz_tabs);
}
@@ -1491,12 +1520,11 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
{
THD *thd;
TABLE_LIST *tables= 0;
- TABLE_LIST tables_buff[5];
+ TABLE_LIST tables_buff[5], **last_global_next_ptr;
TABLE *table;
TZ_NAMES_ENTRY *tmp_tzname;
my_bool return_val= 1;
int res;
- uint counter;
DBUG_ENTER("my_tz_init");
/*
@@ -1554,16 +1582,18 @@ 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_buff, sizeof(TABLE_LIST));
- tables_buff[0].alias= tables_buff[0].real_name=
+ tables_buff[0].alias= tables_buff[0].table_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);
+ /*
+ Fill TABLE_LIST for the rest of the time zone describing tables
+ and link it to first one.
+ */
+ last_global_next_ptr= &(tables_buff[0].next_global);
+ tz_init_table_list(tables_buff + 1, &last_global_next_ptr);
- if (open_tables(thd, tables_buff, &counter) ||
- lock_tables(thd, tables_buff, counter))
+ if (simple_open_n_lock_tables(thd, tables_buff))
{
sql_print_warning("Can't open and lock time zone table: %s "
"trying to live without them", thd->net.last_error);
@@ -1762,8 +1792,9 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
and it is specifically for this purpose).
*/
table= tz_tables->table;
- tz_tables= tz_tables->next;
- table->field[0]->store(tz_name->ptr(), tz_name->length(), &my_charset_latin1);
+ tz_tables= tz_tables->next_local;
+ table->field[0]->store(tz_name->ptr(), tz_name->length(),
+ &my_charset_latin1);
/*
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
@@ -1794,7 +1825,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
using the only index in this table).
*/
table= tz_tables->table;
- tz_tables= tz_tables->next;
+ tz_tables= tz_tables->next_local;
table->field[0]->store((longlong)tzid);
(void)table->file->ha_index_init(0);
@@ -1821,7 +1852,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
Right - using special index.
*/
table= tz_tables->table;
- tz_tables= tz_tables->next;
+ tz_tables= tz_tables->next_local;
table->field[0]->store((longlong)tzid);
(void)table->file->ha_index_init(0);
@@ -2148,7 +2179,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
DBUG_PRINT("enter", ("time zone name='%s'",
name ? ((String *)name)->c_ptr() : "NULL"));
- DBUG_ASSERT(!time_zone_tables_exist || tz_tables);
+ DBUG_ASSERT(!time_zone_tables_exist || tz_tables || current_thd->slave_thread);
if (!name)
DBUG_RETURN(0);
@@ -2180,7 +2211,7 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
(const byte *)name->ptr(),
name->length())))
result_tz= tmp_tzname->tz;
- else if (time_zone_tables_exist)
+ else if (time_zone_tables_exist && tz_tables)
result_tz= tz_load_from_open_tables(name, tz_tables);
}
@@ -2189,6 +2220,58 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables)
DBUG_RETURN(result_tz);
}
+
+/*
+ A more standalone version of my_tz_find(): will open tz tables if needed.
+ This is so far only used by replication, where time zone setting does not
+ happen in the usual query context.
+
+ SYNOPSIS
+ my_tz_find_with_opening_tz_tables()
+ thd - pointer to thread's THD structure
+ name - time zone specification
+
+ DESCRIPTION
+ This function tries to find a time zone which matches the named passed in
+ argument. If it fails, it will open time zone tables and re-try the
+ search.
+ This function is needed for the slave SQL thread, which does not do the
+ addition of time zone tables which is usually done during query parsing
+ (as time zone setting by slave does not happen in mysql_parse() but
+ before). So it needs to open tz tables by itself if needed.
+ See notes of my_tz_find() as they also apply here.
+
+ RETURN VALUE
+ Pointer to corresponding Time_zone object. 0 - in case of bad time zone
+ specification or other error.
+
+*/
+Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name)
+{
+ Time_zone *tz;
+ DBUG_ENTER("my_tz_find_with_opening_tables");
+ DBUG_ASSERT(thd);
+ DBUG_ASSERT(thd->slave_thread); // intended for use with slave thread only
+ if (!(tz= my_tz_find(name, 0)) && time_zone_tables_exist)
+ {
+ /*
+ Probably we have not loaded this time zone yet so let us look it up in
+ our time zone tables. Note that if we don't have tz tables on this
+ slave, we don't even try.
+ */
+ TABLE_LIST tables[4];
+ TABLE_LIST *dummy;
+ TABLE_LIST **dummyp= &dummy;
+ tz_init_table_list(tables, &dummyp);
+ if (simple_open_n_lock_tables(thd, tables))
+ DBUG_RETURN(0);
+ tz= my_tz_find(name, tables);
+ /* We need to close tables _now_ to not pollute coming query */
+ close_thread_tables(thd);
+ }
+ DBUG_RETURN(tz);
+}
+
#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */