MySQL 8.4.0
Source Code Documentation File Reference
#include "sql/tztime.h"
#include <algorithm>
#include <assert.h>
#include <fcntl.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "lex_string.h"
#include "map_helpers.h"
#include "mutex_lock.h"
#include "my_alloc.h"
#include "my_base.h"
#include "my_compiler.h"
#include "my_dbug.h"
#include "my_dir.h"
#include "my_inttypes.h"
#include "my_io.h"
#include "my_macros.h"
#include "my_pointer_arithmetic.h"
#include "my_psi_config.h"
#include "my_sys.h"
#include "my_time.h"
#include "mysql/components/services/bits/mysql_mutex_bits.h"
#include "mysql/components/services/bits/psi_bits.h"
#include "mysql/components/services/bits/psi_memory_bits.h"
#include "mysql/components/services/bits/psi_mutex_bits.h"
#include "mysql/components/services/log_builtins.h"
#include "mysql/components/services/log_shared.h"
#include "mysql/my_loglevel.h"
#include "mysql/psi/mysql_file.h"
#include "mysql/psi/mysql_memory.h"
#include "mysql/psi/mysql_mutex.h"
#include "mysql/strings/m_ctype.h"
#include "mysqld_error.h"
#include "sql/dd/types/event.h"
#include "sql/field.h"
#include "sql/handler.h"
#include "sql/psi_memory_key.h"
#include "sql/sql_const.h"
#include "sql/sql_error.h"
#include "sql/system_variables.h"
#include "sql/thr_malloc.h"
#include "sql/time_zone_common.h"
#include "sql/tzfile.h"
#include "string_with_len.h"
#include "template_utils.h"
#include "thr_lock.h"
#include "thr_mutex.h"
#include "sql/debug_sync.h"
#include "sql/log.h"
#include "sql/mysqld.h"
#include "sql/sql_base.h"
#include "sql/sql_class.h"
#include "sql/sql_time.h"
#include "sql/table.h"
#include "sql_string.h"
#include "strmake.h"
#include <string>
#include <unordered_map>
#include <utility>
#include "print_version.h"
#include "welcome_copyright_notice.h"


class  Time_zone_system
class  Time_zone_utc
class  Time_zone_db
class  Time_zone_offset
class  Tz_names_entry


#define LEAPS_THRU_END_OF(y)   ((y) / 4 - (y) / 100 + (y) / 400)


void sec_to_TIME (MYSQL_TIME *tmp, my_time_t t, int64 offset)
static uint find_time_range (my_time_t t, const my_time_t *range_boundaries, uint higher_bound)
static const TRAN_TYPE_INFOfind_transition_type (my_time_t t, const TIME_ZONE_INFO *sp)
static void gmt_sec_to_TIME (MYSQL_TIME *tmp, my_time_t sec_in_utc, const TIME_ZONE_INFO *sp)
static my_time_t sec_since_epoch (int year, int mon, int mday, int hour, int min, int sec)
static int64_t sec_since_epoch64 (const MYSQL_TIME &mt)
 Converts time from a MYSQL_TIME struct to a unix timestamp-like 64 bit integer. More...
static my_time_t sec_since_epoch (const MYSQL_TIME &mt)
static my_time_t TIME_to_gmt_sec (const MYSQL_TIME *t, const TIME_ZONE_INFO *sp, bool *in_dst_time_gap)
Time_zonemy_tz_find (const int64 displacement)
static void raise_time_zone_conversion_error (const MYSQL_TIME &mt)
bool check_time_zone_convertibility (const MYSQL_TIME &mt)
 Checks that this temporal value can be converted from its specified time zone (if any) to the current time zone. More...
bool convert_time_zone_displacement (const Time_zone *tz, MYSQL_TIME *mt)
 Converts a date/time value with time zone to the corresponding date/time value without time zone, converted to be in time zone specified by argument tz. More...
static void tz_init_table_list (Table_ref *tz_tabs)
static void init_tz_psi_keys (void)
bool my_tz_init (THD *org_thd, const char *default_tzname, bool bootstrap)
void my_tz_free ()
static Time_zonetz_load_from_open_tables (const String *tz_name, Table_ref *tz_tables)
static bool str_to_offset (const char *str, size_t length, int *offset)
Time_zonemy_tz_find (THD *thd, const String *name)
 Get Time_zone object for specified time zone. More...


static const uint mon_lengths [2][MONS_PER_YEAR]
static const uint mon_starts [2][MONS_PER_YEAR]
static const uint year_lengths [2] = {DAYS_PER_NYEAR, DAYS_PER_LYEAR}
static const String tz_SYSTEM_name ("SYSTEM", 6, &my_charset_latin1)
static Time_zone_utc tz_UTC
static Time_zone_system tz_SYSTEM
static Time_zone_offset tz_OFFSET0 (0)
Time_zonemy_tz_OFFSET0 = &tz_OFFSET0
Time_zonemy_tz_UTC = &tz_UTC
Time_zonemy_tz_SYSTEM = &tz_SYSTEM
static MEM_ROOT tz_storage
static mysql_mutex_t tz_LOCK
 This mutex has two orthogonal purposes: More...
static bool tz_inited = false
static uint tz_leapcnt = 0
static LS_INFOtz_lsis = nullptr
static bool time_zone_tables_exist = true
static const LEX_CSTRING tz_tables_names [MY_TZ_TABLES_COUNT]
static const LEX_CSTRING tz_tables_db_name = {STRING_WITH_LEN("mysql")}
static PSI_memory_key key_memory_tz_storage
static PSI_mutex_key key_tz_LOCK
static PSI_mutex_info all_tz_mutexes []
static PSI_memory_info all_tz_memory []
static collation_unordered_map< std::string, Tz_names_entry * > tz_names
static malloc_unordered_map< long, Time_zone_offset * > offset_tzs

Macro Definition Documentation


#define LEAPS_THRU_END_OF (   y)    ((y) / 4 - (y) / 100 + (y) / 400)

Function Documentation

◆ check_time_zone_convertibility()

bool check_time_zone_convertibility ( const MYSQL_TIME mt)

Checks that this temporal value can be converted from its specified time zone (if any) to the current time zone.

Specifically, temporal values with zero months or days cannot be converted between time zones.

mtThe time to check.
Return values
falseThe temporal value has no time zone or can be converted.
trueOtherwise, and an error was raised.

◆ convert_time_zone_displacement()

bool convert_time_zone_displacement ( const Time_zone tz,

Converts a date/time value with time zone to the corresponding date/time value without time zone, converted to be in time zone specified by argument tz.

Since MySQL doesn't have a data type for temporal values with time zone information, all such values are converted to a value without time zone using this function.

This function is intended only for values with a time zone, and is a no-op for all other types.

The converted value may not fall outside the range of the DATETIME type. Also some invalid values cannot be converted because the conversion result would be undefined. In these cases an error is raised.

tzThe time zone to convert according to.
[in,out]mtDate/Time value to be converted.
false on success. true if an error was raised.

◆ find_time_range()

static uint find_time_range ( my_time_t  t,
const my_time_t range_boundaries,
uint  higher_bound 

◆ find_transition_type()

static const TRAN_TYPE_INFO * find_transition_type ( my_time_t  t,
const TIME_ZONE_INFO sp 

◆ gmt_sec_to_TIME()

static void gmt_sec_to_TIME ( MYSQL_TIME tmp,
my_time_t  sec_in_utc,
const TIME_ZONE_INFO sp 

◆ init_tz_psi_keys()

static void init_tz_psi_keys ( void  )

◆ my_tz_find() [1/2]

Time_zone * my_tz_find ( const int64  displacement)

◆ my_tz_find() [2/2]

Time_zone * my_tz_find ( THD thd,
const String name 

Get Time_zone object for specified time zone.

[in]thdPointer to thread THD structure.
[in]nameTime zone specification.
This function checks if name is one of time zones described in db, predefined SYSTEM time zone or valid time zone specification as offset from UTC (In last case it will create proper Time_zone_offset object if there were not any.). If name is ok it returns corresponding Time_zone object.
Clients of this function are not responsible for releasing resources occupied by returned Time_zone object so they can just forget pointers to Time_zone object if they are not needed longer.
Other important property of this function: if some Time_zone found once it will be for sure found later, so this function can also be used for checking if proper Time_zone object exists (and if there will be error it will be reported during first call).
If name pointer is 0 then this function returns 0 (this allows to pass 0 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*), opening and locking them, and closing afterwards. It won't perform such lookup if no time zone describing tables were found during server start up.
Return values
0bad time zone specification or other error.
Time_zoneobject pointer.

◆ my_tz_free()

void my_tz_free ( )

◆ my_tz_init()

bool my_tz_init ( THD org_thd,
const char *  default_tzname,
bool  bootstrap 

◆ raise_time_zone_conversion_error()

static void raise_time_zone_conversion_error ( const MYSQL_TIME mt)

◆ sec_since_epoch() [1/2]

static my_time_t sec_since_epoch ( const MYSQL_TIME mt)

◆ sec_since_epoch() [2/2]

static my_time_t sec_since_epoch ( int  year,
int  mon,
int  mday,
int  hour,
int  min,
int  sec 

◆ sec_since_epoch64()

static int64_t sec_since_epoch64 ( const MYSQL_TIME mt)

Converts time from a MYSQL_TIME struct to a unix timestamp-like 64 bit integer.

The function is guaranteed to use 64 bits on any platform.

mtThe time to convert.
A value compatible with a 64 bit Unix timestamp.

◆ sec_to_TIME()

void sec_to_TIME ( MYSQL_TIME tmp,
my_time_t  t,
int64  offset 

◆ str_to_offset()

static bool str_to_offset ( const char *  str,
size_t  length,
int *  offset 

◆ TIME_to_gmt_sec()

static my_time_t TIME_to_gmt_sec ( const MYSQL_TIME t,
const TIME_ZONE_INFO sp,
bool *  in_dst_time_gap 

◆ tz_init_table_list()

static void tz_init_table_list ( Table_ref tz_tabs)

◆ tz_load_from_open_tables()

static Time_zone * tz_load_from_open_tables ( const String tz_name,
Table_ref tz_tables 

Variable Documentation

◆ all_tz_memory

PSI_memory_info all_tz_memory[]
Initial value:
= {{&key_memory_tz_storage, "tz_storage",
"Shared time zone data."}}
Global stat only flag.
Definition: psi_bits.h:112
static PSI_memory_key key_memory_tz_storage

◆ all_tz_mutexes

PSI_mutex_info all_tz_mutexes[]
Initial value:
= {
Definition: component_common.h:29
Singleton flag.
Definition: component_common.h:35
static PSI_mutex_key key_tz_LOCK

◆ key_memory_tz_storage

PSI_memory_key key_memory_tz_storage

◆ key_tz_LOCK

PSI_mutex_key key_tz_LOCK

◆ mon_lengths

const uint mon_lengths[2][MONS_PER_YEAR]
Initial value:
= {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}

◆ mon_starts

const uint mon_starts[2][MONS_PER_YEAR]
Initial value:
= {
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}}

◆ my_tz_OFFSET0

Time_zone* my_tz_OFFSET0 = &tz_OFFSET0

◆ my_tz_SYSTEM

Time_zone* my_tz_SYSTEM = &tz_SYSTEM

◆ my_tz_UTC

Time_zone* my_tz_UTC = &tz_UTC

◆ offset_tzs

malloc_unordered_map<long, Time_zone_offset *> offset_tzs
Initial value:

◆ time_zone_tables_exist

bool time_zone_tables_exist = true

◆ tz_inited

bool tz_inited = false

◆ tz_leapcnt

uint tz_leapcnt = 0

◆ tz_LOCK

mysql_mutex_t tz_LOCK

This mutex has two orthogonal purposes:

  1. When the caller of my_tz_find() needs a Time_zone object representing a time zone specified as a numeric displacement. The mutex is then taken in order to protect the offset_tzs map and the performance_schema key tz_storage. my_tz_find() uses a shared pool of Time_zone objects and will search to see if there is an existing time zone, and will otherwise create and insert one. So contention is low.
  2. When the caller of my_tz_find() needs a Time_zone object by name. First the tz_names map is searched, and if nothing is found, the database tables are consulted. If nothing is found there either, an error is thrown. If one is found, tz_load_from_open_tables() tries to insert it in the map, and if it is already there, it fails, logging an "out of memory" event. And that's the reason the whole procedure must take place under a mutex, so that another session couldn't have inserted it in the mean time.

It is not clear why the same mutex is used for both operations, or for that matter why it is taken even before we have decided which of the two paths above to take.

◆ tz_lsis

LS_INFO* tz_lsis = nullptr

◆ tz_names

collation_unordered_map<std::string, Tz_names_entry *> tz_names
Initial value:

◆ tz_OFFSET0

Time_zone_offset tz_OFFSET0(0) ( )

◆ tz_storage

MEM_ROOT tz_storage


Time_zone_system tz_SYSTEM

◆ tz_SYSTEM_name

const String tz_SYSTEM_name("SYSTEM", 6, &my_charset_latin1) ( "SYSTEM"  ,

◆ tz_tables_db_name

const LEX_CSTRING tz_tables_db_name = {STRING_WITH_LEN("mysql")}

◆ tz_tables_names

const LEX_CSTRING tz_tables_names[MY_TZ_TABLES_COUNT]
Initial value:
= {
Definition: string_with_len.h:29

◆ tz_UTC

Time_zone_utc tz_UTC

◆ year_lengths

const uint year_lengths[2] = {DAYS_PER_NYEAR, DAYS_PER_LYEAR}