diff options
Diffstat (limited to 'sql/tztime.cc')
-rw-r--r-- | sql/tztime.cc | 253 |
1 files changed, 186 insertions, 67 deletions
diff --git a/sql/tztime.cc b/sql/tztime.cc index 9af33526c98..bd8e43075c4 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -880,7 +880,8 @@ sec_since_epoch(int year, int mon, int mday, int hour, int min ,int sec) 0 in case of error. */ static my_time_t -TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap) +TIME_to_gmt_sec(const TIME *t, const TIME_ZONE_INFO *sp, + my_bool *in_dst_time_gap) { my_time_t local_t; uint saved_seconds; @@ -1006,8 +1007,9 @@ static const String tz_SYSTEM_name("SYSTEM", 6, &my_charset_latin1); class Time_zone_system : public Time_zone { public: + Time_zone_system() {} /* Remove gcc warning */ virtual my_time_t TIME_to_gmt_sec(const TIME *t, - bool *in_dst_time_gap) const; + my_bool *in_dst_time_gap) const; virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const; virtual const String * get_name() const; }; @@ -1039,7 +1041,7 @@ public: Corresponding my_time_t value or 0 in case of error */ my_time_t -Time_zone_system::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const +Time_zone_system::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const { long not_used; return my_system_gmt_sec(t, ¬_used, in_dst_time_gap); @@ -1099,8 +1101,9 @@ Time_zone_system::get_name() const class Time_zone_utc : public Time_zone { public: + Time_zone_utc() {} /* Remove gcc warning */ virtual my_time_t TIME_to_gmt_sec(const TIME *t, - bool *in_dst_time_gap) const; + my_bool *in_dst_time_gap) const; virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const; virtual const String * get_name() const; }; @@ -1126,7 +1129,7 @@ public: 0 */ my_time_t -Time_zone_utc::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const +Time_zone_utc::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const { /* Should be never called */ DBUG_ASSERT(0); @@ -1189,7 +1192,7 @@ class Time_zone_db : public Time_zone public: Time_zone_db(TIME_ZONE_INFO *tz_info_arg, const String * tz_name_arg); virtual my_time_t TIME_to_gmt_sec(const TIME *t, - bool *in_dst_time_gap) const; + my_bool *in_dst_time_gap) const; virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const; virtual const String * get_name() const; private: @@ -1238,7 +1241,7 @@ Time_zone_db::Time_zone_db(TIME_ZONE_INFO *tz_info_arg, Corresponding my_time_t value or 0 in case of error */ my_time_t -Time_zone_db::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const +Time_zone_db::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const { return ::TIME_to_gmt_sec(t, tz_info, in_dst_time_gap); } @@ -1285,7 +1288,7 @@ class Time_zone_offset : public Time_zone public: Time_zone_offset(long tz_offset_arg); virtual my_time_t TIME_to_gmt_sec(const TIME *t, - bool *in_dst_time_gap) const; + my_bool *in_dst_time_gap) const; virtual void gmt_sec_to_TIME(TIME *tmp, my_time_t t) const; virtual const String * get_name() const; /* @@ -1337,7 +1340,7 @@ Time_zone_offset::Time_zone_offset(long tz_offset_arg): Corresponding my_time_t value or 0 in case of error */ my_time_t -Time_zone_offset::TIME_to_gmt_sec(const TIME *t, bool *in_dst_time_gap) const +Time_zone_offset::TIME_to_gmt_sec(const TIME *t, my_bool *in_dst_time_gap) const { my_time_t local_t; @@ -1428,11 +1431,30 @@ static LS_INFO *tz_lsis= 0; static bool time_zone_tables_exist= 1; -typedef struct st_tz_names_entry: public Sql_alloc +/* + Names of tables (with their lengths) that are needed + for dynamical loading of time zone descriptions. +*/ + +static const LEX_STRING tz_tables_names[MY_TZ_TABLES_COUNT]= +{ + {(char *) STRING_WITH_LEN("time_zone_name")}, + {(char *) STRING_WITH_LEN("time_zone")}, + {(char *) STRING_WITH_LEN("time_zone_transition_type")}, + {(char *) STRING_WITH_LEN("time_zone_transition")} +}; + +/* Name of database to which those tables belong. */ + +static const LEX_STRING tz_tables_db_name= {(char *) STRING_WITH_LEN("mysql")}; + + +class Tz_names_entry: public Sql_alloc { +public: String name; Time_zone *tz; -} TZ_NAMES_ENTRY; +}; /* @@ -1440,7 +1462,7 @@ typedef struct st_tz_names_entry: public Sql_alloc they should obey C calling conventions. */ -extern "C" byte* my_tz_names_get_key(TZ_NAMES_ENTRY *entry, uint *length, +extern "C" byte* my_tz_names_get_key(Tz_names_entry *entry, uint *length, my_bool not_used __attribute__((unused))) { *length= entry->name.length(); @@ -1456,48 +1478,78 @@ 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 MY_TZ_TABLES_COUNT + 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].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"; + bzero(tz_tabs, sizeof(TABLE_LIST) * MY_TZ_TABLES_COUNT); + + for (int i= 0; i < MY_TZ_TABLES_COUNT; i++) + { + tz_tabs[i].alias= tz_tabs[i].table_name= tz_tables_names[i].str; + tz_tabs[i].table_name_length= tz_tables_names[i].length; + tz_tabs[i].db= tz_tables_db_name.str; + tz_tabs[i].db_length= tz_tables_db_name.length; + tz_tabs[i].lock_type= TL_READ; + + if (i != MY_TZ_TABLES_COUNT - 1) + tz_tabs[i].next_global= tz_tabs[i].next_local= &tz_tabs[i+1]; + if (i != 0) + tz_tabs[i].prev_global= &tz_tabs[i-1].next_global; + } + + /* Link into global list */ + tz_tabs[0].prev_global= *global_next_ptr; + **global_next_ptr= tz_tabs; + /* Update last-global-pointer to point to pointer in last table */ + *global_next_ptr= &tz_tabs[MY_TZ_TABLES_COUNT-1].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 - elements of list created are allocated as TABLE_LIST[4] array. + elements of list created are allocated as TABLE_LIST[MY_TZ_TABLES_COUNT] + array. RETURN VALUES Returns pointer to first TABLE_LIST object, (could be 0 if time zone @@ -1505,19 +1557,21 @@ 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; + if (!(tz_tabs= (TABLE_LIST *)thd->alloc(sizeof(TABLE_LIST) * + MY_TZ_TABLES_COUNT))) + 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); } @@ -1551,12 +1605,12 @@ 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[1+MY_TZ_TABLES_COUNT], **last_global_next_ptr; TABLE *table; - TZ_NAMES_ENTRY *tmp_tzname; + Tz_names_entry *tmp_tzname; my_bool return_val= 1; + char db[]= "mysql"; int res; - uint counter; DBUG_ENTER("my_tz_init"); /* @@ -1564,6 +1618,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) */ if (!(thd= new THD)) DBUG_RETURN(1); + thd->thread_stack= (char*) &thd; thd->store_globals(); /* Init all memory structures that require explicit destruction */ @@ -1585,12 +1640,12 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) tz_inited= 1; /* Add 'SYSTEM' time zone to tz_names hash */ - if (!(tmp_tzname= new (&tz_storage) TZ_NAMES_ENTRY())) + if (!(tmp_tzname= new (&tz_storage) Tz_names_entry())) { sql_print_error("Fatal error: OOM while initializing time zones"); goto end_with_cleanup; } - tmp_tzname->name.set("SYSTEM", 6, &my_charset_latin1); + tmp_tzname->name.set(STRING_WITH_LEN("SYSTEM"), &my_charset_latin1); tmp_tzname->tz= my_tz_SYSTEM; if (my_hash_insert(&tz_names, (const byte *)tmp_tzname)) { @@ -1611,19 +1666,20 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) leap seconds shared by all time zones. */ - thd->db= my_strdup("mysql",MYF(0)); - thd->db_length= 5; // Safety + thd->set_db(db, sizeof(db)-1); 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); + tables_buff[0].db= db; + /* + 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); @@ -1779,7 +1835,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) { TABLE *table= 0; TIME_ZONE_INFO *tz_info; - TZ_NAMES_ENTRY *tmp_tzname; + Tz_names_entry *tmp_tzname; Time_zone *return_val= 0; int res; uint tzid, ttid; @@ -1822,8 +1878,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 @@ -1854,8 +1911,8 @@ 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; - table->field[0]->store((longlong)tzid); + tz_tables= tz_tables->next_local; + table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0); if (table->file->index_read(table->record[0], (byte*)table->field[0]->ptr, @@ -1881,8 +1938,8 @@ 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; - table->field[0]->store((longlong)tzid); + tz_tables= tz_tables->next_local; + table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0); // FIXME Is there any better approach than explicitly specifying 4 ??? @@ -1954,7 +2011,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) in ascending order by index scan also satisfies us. */ table= tz_tables->table; - table->field[0]->store((longlong)tzid); + table->field[0]->store((longlong) tzid, TRUE); (void)table->file->ha_index_init(0); // FIXME Is there any better approach than explicitly specifying 4 ??? @@ -2053,7 +2110,7 @@ tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables) } - if (!(tmp_tzname= new (&tz_storage) TZ_NAMES_ENTRY()) || + if (!(tmp_tzname= new (&tz_storage) Tz_names_entry()) || !(tmp_tzname->tz= new (&tz_storage) Time_zone_db(tz_info, &(tmp_tzname->name))) || (tmp_tzname->name.set(tz_name_buff, tz_name->length(), @@ -2200,7 +2257,7 @@ str_to_offset(const char *str, uint length, long *offset) Time_zone * my_tz_find(const String * name, TABLE_LIST *tz_tables) { - TZ_NAMES_ENTRY *tmp_tzname; + Tz_names_entry *tmp_tzname; Time_zone *result_tz= 0; long offset; @@ -2208,7 +2265,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); @@ -2236,11 +2293,11 @@ my_tz_find(const String * name, TABLE_LIST *tz_tables) else { result_tz= 0; - if ((tmp_tzname= (TZ_NAMES_ENTRY *)hash_search(&tz_names, + if ((tmp_tzname= (Tz_names_entry *)hash_search(&tz_names, (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); } @@ -2249,6 +2306,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[MY_TZ_TABLES_COUNT]; + 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) */ @@ -2531,8 +2640,6 @@ main(int argc, char **argv) time_t t, t1, t2; char fullname[FN_REFLEN+1]; char *str_end; - long not_used; - bool not_used_2; MEM_ROOT tz_storage; MY_INIT(argv[0]); @@ -2642,14 +2749,21 @@ main(int argc, char **argv) dates. */ for (time_tmp.year= 1980; time_tmp.year < 2010; time_tmp.year++) + { for (time_tmp.month= 1; time_tmp.month < 13; time_tmp.month++) + { for (time_tmp.day= 1; time_tmp.day < mon_lengths[isleap(time_tmp.year)][time_tmp.month-1]; time_tmp.day++) + { for (time_tmp.hour= 0; time_tmp.hour < 24; time_tmp.hour++) + { for (time_tmp.minute= 0; time_tmp.minute < 60; time_tmp.minute+= 5) + { for (time_tmp.second=0; time_tmp.second<60; time_tmp.second+=25) { + long not_used; + my_bool not_used_2; t= (time_t)my_system_gmt_sec(&time_tmp, ¬_used, ¬_used_2); t1= (time_t)TIME_to_gmt_sec(&time_tmp, &tz_info, ¬_used_2); if (t != t1) @@ -2681,6 +2795,11 @@ main(int argc, char **argv) return 1; } } + } + } + } + } + } printf("TIME_to_gmt_sec = my_system_gmt_sec for test range\n"); |