MySQL 9.1.0
Source Code Documentation
tztime.cc 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"

Classes

class  Time_zone_system
 
class  Time_zone_utc
 
class  Time_zone_db
 
class  Time_zone_offset
 
class  Tz_names_entry
 

Macros

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

Functions

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...
 

Variables

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

◆ LEAPS_THRU_END_OF

#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.

Parameters
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,
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.

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.

Parameters
tzThe time zone to convert according to.
[in,out]mtDate/Time value to be converted.
Returns
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 
)
static

◆ find_transition_type()

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

◆ gmt_sec_to_TIME()

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

◆ init_tz_psi_keys()

static void init_tz_psi_keys ( void  )
static

◆ 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.

Parameters
[in]thdPointer to thread THD structure.
[in]nameTime zone specification.
Note
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)
static

◆ sec_since_epoch() [1/2]

static my_time_t sec_since_epoch ( const MYSQL_TIME mt)
static

◆ sec_since_epoch() [2/2]

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

◆ sec_since_epoch64()

static int64_t sec_since_epoch64 ( const MYSQL_TIME mt)
static

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.

Parameters
mtThe time to convert.
Returns
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 
)
static

◆ 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 
)
static

◆ tz_init_table_list()

static void tz_init_table_list ( Table_ref tz_tabs)
static

◆ tz_load_from_open_tables()

static Time_zone * tz_load_from_open_tables ( const String tz_name,
Table_ref tz_tables 
)
static

Variable Documentation

◆ all_tz_memory

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

◆ all_tz_mutexes

PSI_mutex_info all_tz_mutexes[]
static
Initial value:
= {
#define PSI_DOCUMENT_ME
Definition: component_common.h:29
#define PSI_FLAG_SINGLETON
Singleton flag.
Definition: component_common.h:35
static PSI_mutex_key key_tz_LOCK
Definition: tztime.cc:1134

◆ key_memory_tz_storage

PSI_memory_key key_memory_tz_storage
static

◆ key_tz_LOCK

PSI_mutex_key key_tz_LOCK
static

◆ mon_lengths

const uint mon_lengths[2][MONS_PER_YEAR]
static
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]
static
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
static
Initial value:

◆ time_zone_tables_exist

bool time_zone_tables_exist = true
static

◆ tz_inited

bool tz_inited = false
static

◆ tz_leapcnt

uint tz_leapcnt = 0
static

◆ tz_LOCK

mysql_mutex_t tz_LOCK
static

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
static

◆ tz_names

collation_unordered_map<std::string, Tz_names_entry *> tz_names
static
Initial value:
{
MYSQL_STRINGS_EXPORT CHARSET_INFO my_charset_latin1
Definition: ctype-latin1.cc:366

◆ tz_OFFSET0

Time_zone_offset tz_OFFSET0(0) ( )
static

◆ tz_storage

MEM_ROOT tz_storage
static

◆ tz_SYSTEM

Time_zone_system tz_SYSTEM
static

◆ tz_SYSTEM_name

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

◆ tz_tables_db_name

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

◆ tz_tables_names

const LEX_CSTRING tz_tables_names[MY_TZ_TABLES_COUNT]
static
Initial value:
= {
{STRING_WITH_LEN("time_zone_name")},
{STRING_WITH_LEN("time_zone")},
{STRING_WITH_LEN("time_zone_transition_type")},
{STRING_WITH_LEN("time_zone_transition")}}
#define STRING_WITH_LEN(X)
Definition: string_with_len.h:29

◆ tz_UTC

Time_zone_utc tz_UTC
static

◆ year_lengths

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