diff options
Diffstat (limited to 'sql/tztime.cc')
-rw-r--r-- | sql/tztime.cc | 151 |
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) */ |