Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 50 additions & 8 deletions lib/MySQL_Set_Stmt_Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,16 +244,58 @@ void MySQL_Set_Stmt_Parser::generateRE_parse1v2() {
vp = "(?:| *(?:\\+|\\-) *)\\d+(?:|\\.\\d+)"; // a signed or unsigned integer or decimal , N7 = merge of N3 and N6
var_patterns.push_back(vp);

/**
* @page time_zone_parsing MySQL time_zone Variable Parsing
*
* The MySQL @c time_zone system variable accepts two formats:
*
* @section tz_numeric_format Numeric Offset Format
* Specifies timezone as an offset from UTC in the format [+|-]HH:MM.
* Examples: @c '+08:00' , @c '-05:30' , @c '+00:00' (UTC)
*
* @section tz_iana_format IANA Timezone Name Format
* Specifies timezone using IANA timezone database names.
* The naming convention follows the pattern @c Area/Location or
* @c Area/Country/Location.
*
* @subsection tz_iana_components IANA Timezone Name Components
* - **Area**: Continent, ocean, or special region (e.g., America, Europe, Asia, Etc)
* - **Location**: City, island, or country name
*
* IANA timezone names may contain:
* - Word characters (letters, digits, underscores): @c [a-zA-Z0-9_]
* - Hyphens in place of spaces: @c Port-au-Prince , @c Rio_Gallegos
*
* @subsection tz_iana_examples IANA Timezone Examples
* - 2 components: @c Europe/London , @c America/New_York , @c Asia/Tokyo
* - 3 components: @c America/Argentina/Buenos_Aires , @c America/Indiana/Indianapolis
* - With hyphens: @c America/Port-au-Prince , @c America/Blanc-Sablon
*
* @subsection tz_special_values Special Values
* The following special values are also supported (matched by other patterns):
* - @c SYSTEM : Use the system's timezone
* - @c UTC : Coordinated Universal Time
*
* @subsection tz_limitations Limitations
* The regex pattern limits matching to 2-3 components (e.g., @c Area/Location or
* @c Area/Country/Location). While IANA timezone names with 4+ components are
* theoretically possible, they are extremely rare and not currently supported.
*
* @see https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html
* @see https://www.iana.org/time-zones
*/
{
// time_zone in numeric format:
// - +/- sign
// 1 or 2 digits
// :
// 2 digits
// time_zone in numeric format: [+|-]HH:MM
// Examples: '+08:00', '-05:30', '+00:00'
string tzd = "(?:(?:\\+|\\-)(?:|\\d)\\d:\\d\\d)";
// time_zone in string format:
// word / word
string tzw = "(?:\\w+/\\w+)";
// time_zone in string format: IANA timezone names
// Supports 2-3 components with optional hyphens:
// - 2 components: Area/Location (e.g., Europe/London, America/New_York)
// - 3 components: Area/Country/Location (e.g., America/Argentina/Buenos_Aires)
// - With hyphens: America/Port-au-Prince, America/Blanc-Sablon
// Note: Does not match bare words like 'SYSTEM' or 'UTC' - these are matched
// by other patterns in var_patterns (e.g., vp2 at line ~197)
string tzw = "(?:[\\w-]+(?:/[\\w-]+){1,2})";
vp = "(?:" + tzd + "|" + tzw + ")"; // time_zone in numeric and string format
}
for (auto it = quote_symbol.begin(); it != quote_symbol.end(); it++) {
Expand Down
19 changes: 19 additions & 0 deletions test/tap/tests/setparser_test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ static Test syntax_errors[] = {
};

static Test time_zone[] = {
// Original tests - 2 component timezone names
{ "SET @@time_zone = 'Europe/Paris'", { Expected("time_zone", {"Europe/Paris"}) } },
{ "SET @@time_zone = '+00:00'", { Expected("time_zone", {"+00:00"}) } },
{ "SET @@time_zone = \"Europe/Paris\"", { Expected("time_zone", {"Europe/Paris"}) } },
Expand All @@ -144,6 +145,24 @@ static Test time_zone[] = {
{ "SET @@TIME_ZONE = @OLD_TIME_ZONE", { Expected("time_zone", {"@OLD_TIME_ZONE"}) } },
{ "SET @@TIME_ZONE := 'SYSTEM'", { Expected("time_zone", {"SYSTEM"}) } },
{ "SET time_zone := 'SYSTEM'", { Expected("time_zone", {"SYSTEM"}) } },
// Special values - UTC and SYSTEM
{ "SET time_zone = 'UTC'", { Expected("time_zone", {"UTC"}) } },
{ "SET time_zone = SYSTEM", { Expected("time_zone", {"SYSTEM"}) } },
{ "SET time_zone = UTC", { Expected("time_zone", {"UTC"}) } },
// 3 component timezone names (bug fix for GitHub issue #4993)
{ "SET time_zone = 'America/Argentina/Buenos_Aires'", { Expected("time_zone", {"America/Argentina/Buenos_Aires"}) } },
{ "SET time_zone = 'America/Indiana/Indianapolis'", { Expected("time_zone", {"America/Indiana/Indianapolis"}) } },
{ "SET time_zone = \"America/Kentucky/Louisville\"", { Expected("time_zone", {"America/Kentucky/Louisville"}) } },
// Timezone names with hyphens (additional fix)
{ "SET time_zone = 'America/Port-au-Prince'", { Expected("time_zone", {"America/Port-au-Prince"}) } },
{ "SET time_zone = 'America/Blanc-Sablon'", { Expected("time_zone", {"America/Blanc-Sablon"}) } },
{ "SET time_zone = \"Atlantic/Canary\"", { Expected("time_zone", {"Atlantic/Canary"}) } },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test case for Atlantic/Canary is valid, but it doesn't test the new hyphen support as the comment on line 156 suggests, since the name contains no hyphens and would have been matched by the old regex. To make this test more specific to the hyphen-support feature, consider replacing it with a name that does contain a hyphen, such as US/East-Indiana.

Suggested change
{ "SET time_zone = \"Atlantic/Canary\"", { Expected("time_zone", {"Atlantic/Canary"}) } },
{ "SET time_zone = \"US/East-Indiana\"", { Expected("time_zone", {"US/East-Indiana"}) } },

// Various numeric offsets
{ "SET time_zone = '+08:00'", { Expected("time_zone", {"+08:00"}) } },
{ "SET time_zone = '-05:30'", { Expected("time_zone", {"-05:30"}) } },
{ "SET time_zone = '-10:00'", { Expected("time_zone", {"-10:00"}) } },
// Combined with other SET variables
{ "SET time_zone = 'America/Argentina/Buenos_Aires', sql_mode = 'TRADITIONAL'", { Expected("time_zone", {"America/Argentina/Buenos_Aires"}), Expected("sql_mode", {"TRADITIONAL"}) } },
};

static Test session_track_gtids[] = {
Expand Down
Loading