summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item_timefunc.cc148
-rw-r--r--sql/item_timefunc.h80
-rw-r--r--sql/lex.h3
-rw-r--r--sql/sql_yacc.yy19
4 files changed, 197 insertions, 53 deletions
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 62d8afd7ec0..2948438d76f 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -571,21 +571,21 @@ longlong Item_func_from_days::val_int()
void Item_func_curdate::fix_length_and_dec()
{
- struct tm tm_tmp,*start;
- time_t query_start=current_thd->query_start();
+ struct tm start;
collation.set(default_charset());
decimals=0;
max_length=10*default_charset()->mbmaxlen;
- localtime_r(&query_start,&tm_tmp);
- start=&tm_tmp;
- value=(longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
- ((uint) start->tm_mon+1)*100+
- (uint) start->tm_mday);
+
+ store_now_in_tm(current_thd->query_start(),&start);
+
+ value=(longlong) ((ulong) ((uint) start.tm_year+1900)*10000L+
+ ((uint) start.tm_mon+1)*100+
+ (uint) start.tm_mday);
/* For getdate */
- ltime.year= start->tm_year+1900;
- ltime.month= start->tm_mon+1;
- ltime.day= start->tm_mday;
+ ltime.year= start.tm_year+1900;
+ ltime.month= start.tm_mon+1;
+ ltime.day= start.tm_mday;
ltime.hour= 0;
ltime.minute= 0;
ltime.second= 0;
@@ -594,6 +594,7 @@ void Item_func_curdate::fix_length_and_dec()
ltime.time_type=TIMESTAMP_DATE;
}
+
bool Item_func_curdate::get_date(TIME *res,
bool fuzzy_date __attribute__((unused)))
{
@@ -601,6 +602,27 @@ bool Item_func_curdate::get_date(TIME *res,
return 0;
}
+
+/*
+ Converts time in time_t to struct tm represenatation for local timezone.
+ Defines timezone (local) used for whole CURDATE function
+*/
+void Item_func_curdate_local::store_now_in_tm(time_t now, struct tm *now_tm)
+{
+ localtime_r(&now,now_tm);
+}
+
+
+/*
+ Converts time in time_t to struct tm represenatation for UTC
+ Defines timezone (UTC) used for whole UTC_DATE function
+*/
+void Item_func_curdate_utc::store_now_in_tm(time_t now, struct tm *now_tm)
+{
+ gmtime_r(&now,now_tm);
+}
+
+
String *Item_func_curtime::val_str(String *str)
{
str_value.set(buff,buff_length,default_charset());
@@ -609,23 +631,43 @@ String *Item_func_curtime::val_str(String *str)
void Item_func_curtime::fix_length_and_dec()
{
- struct tm tm_tmp,*start;
- time_t query_start=current_thd->query_start();
- CHARSET_INFO *cs=default_charset();
+ struct tm start;
+ CHARSET_INFO *cs= default_charset();
decimals=0;
max_length=8*cs->mbmaxlen;
- localtime_r(&query_start,&tm_tmp);
- start=&tm_tmp;
collation.set(cs);
- value=(longlong) ((ulong) ((uint) start->tm_hour)*10000L+
- (ulong) (((uint) start->tm_min)*100L+
- (uint) start->tm_sec));
+
+ store_now_in_tm(current_thd->query_start(),&start);
+
+ value=(longlong) ((ulong) ((uint) start.tm_hour)*10000L+
+ (ulong) (((uint) start.tm_min)*100L+
+ (uint) start.tm_sec));
buff_length=cs->cset->snprintf(cs,buff,sizeof(buff),"%02d:%02d:%02d",
- (int) start->tm_hour,
- (int) start->tm_min,
- (int) start->tm_sec);
+ (int) start.tm_hour,
+ (int) start.tm_min,
+ (int) start.tm_sec);
+}
+
+
+/*
+ Converts time in time_t to struct tm represenatation for local timezone.
+ Defines timezone (local) used for whole CURTIME function
+*/
+void Item_func_curtime_local::store_now_in_tm(time_t now, struct tm *now_tm)
+{
+ localtime_r(&now,now_tm);
+}
+
+
+/*
+ Converts time in time_t to struct tm represenatation for UTC.
+ Defines timezone (UTC) used for whole UTC_TIME function
+*/
+void Item_func_curtime_utc::store_now_in_tm(time_t now, struct tm *now_tm)
+{
+ gmtime_r(&now,now_tm);
}
@@ -638,37 +680,37 @@ String *Item_func_now::val_str(String *str)
void Item_func_now::fix_length_and_dec()
{
- struct tm tm_tmp,*start;
- time_t query_start=current_thd->query_start();
+ struct tm start;
CHARSET_INFO *cs= &my_charset_bin;
decimals=0;
max_length=19*cs->mbmaxlen;
collation.set(cs);
- localtime_r(&query_start,&tm_tmp);
- start=&tm_tmp;
- value=((longlong) ((ulong) ((uint) start->tm_year+1900)*10000L+
- (((uint) start->tm_mon+1)*100+
- (uint) start->tm_mday))*(longlong) 1000000L+
- (longlong) ((ulong) ((uint) start->tm_hour)*10000L+
- (ulong) (((uint) start->tm_min)*100L+
- (uint) start->tm_sec)));
+
+ store_now_in_tm(current_thd->query_start(),&start);
+
+ value=((longlong) ((ulong) ((uint) start.tm_year+1900)*10000L+
+ (((uint) start.tm_mon+1)*100+
+ (uint) start.tm_mday))*(longlong) 1000000L+
+ (longlong) ((ulong) ((uint) start.tm_hour)*10000L+
+ (ulong) (((uint) start.tm_min)*100L+
+ (uint) start.tm_sec)));
buff_length= (uint) cs->cset->snprintf(cs,buff, sizeof(buff),
"%04d-%02d-%02d %02d:%02d:%02d",
- ((int) (start->tm_year+1900)) % 10000,
- (int) start->tm_mon+1,
- (int) start->tm_mday,
- (int) start->tm_hour,
- (int) start->tm_min,
- (int) start->tm_sec);
+ ((int) (start.tm_year+1900)) % 10000,
+ (int) start.tm_mon+1,
+ (int) start.tm_mday,
+ (int) start.tm_hour,
+ (int) start.tm_min,
+ (int) start.tm_sec);
/* For getdate */
- ltime.year= start->tm_year+1900;
- ltime.month= start->tm_mon+1;
- ltime.day= start->tm_mday;
- ltime.hour= start->tm_hour;
- ltime.minute= start->tm_min;
- ltime.second= start->tm_sec;
+ ltime.year= start.tm_year+1900;
+ ltime.month= start.tm_mon+1;
+ ltime.day= start.tm_mday;
+ ltime.hour= start.tm_hour;
+ ltime.minute= start.tm_min;
+ ltime.second= start.tm_sec;
ltime.second_part=0;
ltime.neg=0;
ltime.time_type=TIMESTAMP_FULL;
@@ -690,6 +732,26 @@ int Item_func_now::save_in_field(Field *to, bool no_conversions)
}
+/*
+ Converts time in time_t to struct tm represenatation for local timezone.
+ Defines timezone (local) used for whole CURRENT_TIMESTAMP function
+*/
+void Item_func_now_local::store_now_in_tm(time_t now, struct tm *now_tm)
+{
+ localtime_r(&now,now_tm);
+}
+
+
+/*
+ Converts time in time_t to struct tm represenatation for UTC.
+ Defines timezone (UTC) used for whole UTC_TIMESTAMP function
+*/
+void Item_func_now_utc::store_now_in_tm(time_t now, struct tm *now_tm)
+{
+ gmtime_r(&now,now_tm);
+}
+
+
String *Item_func_sec_to_time::val_str(String *str)
{
char buff[23*2];
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index a6fb9b11de4..2196f83884a 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -350,6 +350,8 @@ public:
};
+/* Abstract CURTIME function. Children should define what timezone is used */
+
class Item_func_curtime :public Item_func
{
longlong value;
@@ -363,29 +365,77 @@ public:
double val() { return (double) value; }
longlong val_int() { return value; }
String *val_str(String *str);
- const char *func_name() const { return "curtime"; }
void fix_length_and_dec();
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (new Field_time(maybe_null, name, t_arg, default_charset()));
- }
+ }
+ /*
+ Abstract method that defines which time zone is used for conversion.
+ Converts time from time_t representation to broken down representation
+ in struct tm using gmtime_r or localtime_r functions.
+ */
+ virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
};
+class Item_func_curtime_local :public Item_func_curtime
+{
+public:
+ Item_func_curtime_local() :Item_func_curtime() {}
+ Item_func_curtime_local(Item *a) :Item_func_curtime(a) {}
+ const char *func_name() const { return "curtime"; }
+ void store_now_in_tm(time_t now, struct tm *now_tm);
+};
+
+
+class Item_func_curtime_utc :public Item_func_curtime
+{
+public:
+ Item_func_curtime_utc() :Item_func_curtime() {}
+ Item_func_curtime_utc(Item *a) :Item_func_curtime(a) {}
+ const char *func_name() const { return "utc_time"; }
+ void store_now_in_tm(time_t now, struct tm *now_tm);
+};
+
+
+/* Abstract CURDATE function. See also Item_func_curtime. */
+
class Item_func_curdate :public Item_date
{
longlong value;
TIME ltime;
public:
Item_func_curdate() :Item_date() {}
+ void set_result_from_tm(struct tm *now);
longlong val_int() { return (value) ; }
- const char *func_name() const { return "curdate"; }
- void fix_length_and_dec(); /* Retrieves curtime */
+ void fix_length_and_dec();
bool get_date(TIME *res,bool fuzzy_date);
+ virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
+};
+
+
+class Item_func_curdate_local :public Item_func_curdate
+{
+public:
+ Item_func_curdate_local() :Item_func_curdate() {}
+ const char *func_name() const { return "curdate"; }
+ void store_now_in_tm(time_t now, struct tm *now_tm);
};
+class Item_func_curdate_utc :public Item_func_curdate
+{
+public:
+ Item_func_curdate_utc() :Item_func_curdate() {}
+ const char *func_name() const { return "utc_date"; }
+ void store_now_in_tm(time_t now, struct tm *now_tm);
+};
+
+
+/* Abstract CURRENT_TIMESTAMP function. See also Item_func_curtime */
+
class Item_func_now :public Item_date_func
{
longlong value;
@@ -400,9 +450,29 @@ public:
longlong val_int() { return value; }
int save_in_field(Field *to, bool no_conversions);
String *val_str(String *str);
- const char *func_name() const { return "now"; }
void fix_length_and_dec();
bool get_date(TIME *res,bool fuzzy_date);
+ virtual void store_now_in_tm(time_t now, struct tm *now_tm)=0;
+};
+
+
+class Item_func_now_local :public Item_func_now
+{
+public:
+ Item_func_now_local() :Item_func_now() {}
+ Item_func_now_local(Item *a) :Item_func_now(a) {}
+ const char *func_name() const { return "now"; }
+ void store_now_in_tm(time_t now, struct tm *now_tm);
+};
+
+
+class Item_func_now_utc :public Item_func_now
+{
+public:
+ Item_func_now_utc() :Item_func_now() {}
+ Item_func_now_utc(Item *a) :Item_func_now(a) {}
+ const char *func_name() const { return "utc_timestamp"; }
+ void store_now_in_tm(time_t now, struct tm *now_tm);
};
diff --git a/sql/lex.h b/sql/lex.h
index c2860f4551a..35c4d990b32 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -404,6 +404,9 @@ static SYMBOL symbols[] = {
{ "USE_FRM", SYM(USE_FRM),0,0},
{ "USER", SYM(USER),0,0},
{ "USING", SYM(USING),0,0},
+ { "UTC_DATE", SYM(UTC_DATE_SYM),0,0},
+ { "UTC_TIME", SYM(UTC_TIME_SYM),0,0},
+ { "UTC_TIMESTAMP", SYM(UTC_TIMESTAMP_SYM),0,0},
{ "UPDATE", SYM(UPDATE_SYM),0,0},
{ "USAGE", SYM(USAGE),0,0},
{ "VALUE", SYM(VALUE_SYM),0,0},
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index aef58e6cb94..856cc3842fc 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -526,6 +526,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token UNIQUE_USERS
%token UNIX_TIMESTAMP
%token USER
+%token UTC_DATE_SYM
+%token UTC_TIME_SYM
+%token UTC_TIMESTAMP_SYM
%token WEEK_SYM
%token WHEN_SYM
%token WORK_SYM
@@ -2372,12 +2375,12 @@ simple_expr:
| CONCAT_WS '(' expr ',' expr_list ')'
{ $$= new Item_func_concat_ws($3, *$5); }
| CURDATE optional_braces
- { $$= new Item_func_curdate(); Lex->safe_to_cache_query=0; }
+ { $$= new Item_func_curdate_local(); Lex->safe_to_cache_query=0; }
| CURTIME optional_braces
- { $$= new Item_func_curtime(); Lex->safe_to_cache_query=0; }
+ { $$= new Item_func_curtime_local(); Lex->safe_to_cache_query=0; }
| CURTIME '(' expr ')'
{
- $$= new Item_func_curtime($3);
+ $$= new Item_func_curtime_local($3);
Lex->safe_to_cache_query=0;
}
| DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
@@ -2539,9 +2542,9 @@ simple_expr:
{ $$= new Item_func_spatial_collection(* $3,
Geometry::wkbMultiPolygon, Geometry::wkbPolygon ); }
| NOW_SYM optional_braces
- { $$= new Item_func_now(); Lex->safe_to_cache_query=0;}
+ { $$= new Item_func_now_local(); Lex->safe_to_cache_query=0;}
| NOW_SYM '(' expr ')'
- { $$= new Item_func_now($3); Lex->safe_to_cache_query=0;}
+ { $$= new Item_func_now_local($3); Lex->safe_to_cache_query=0;}
| PASSWORD '(' expr ')'
{ $$= new Item_func_password($3); }
| PASSWORD '(' expr ',' expr ')'
@@ -2669,6 +2672,12 @@ simple_expr:
{ $$= new Item_func_unix_timestamp($3); }
| USER '(' ')'
{ $$= new Item_func_user(); Lex->safe_to_cache_query=0; }
+ | UTC_DATE_SYM optional_braces
+ { $$= new Item_func_curdate_utc(); Lex->safe_to_cache_query=0;}
+ | UTC_TIME_SYM optional_braces
+ { $$= new Item_func_curtime_utc(); Lex->safe_to_cache_query=0;}
+ | UTC_TIMESTAMP_SYM optional_braces
+ { $$= new Item_func_now_utc(); Lex->safe_to_cache_query=0;}
| WEEK_SYM '(' expr ')'
{
$$= new Item_func_week($3,new Item_int((char*) "0",