summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/locale.result71
-rw-r--r--mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result2
-rw-r--r--mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result15
-rw-r--r--mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_main.inc3
-rw-r--r--mysql-test/suite/vcol/t/vcol_supported_sql_funcs_main.inc6
-rw-r--r--mysql-test/t/locale.test28
-rw-r--r--sql/item.cc19
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_create.cc27
-rw-r--r--sql/item_strfunc.cc24
-rw-r--r--sql/item_strfunc.h5
-rw-r--r--sql/item_timefunc.cc25
-rw-r--r--sql/item_timefunc.h27
-rw-r--r--sql/lex.h1
-rw-r--r--sql/sql_yacc.yy16
-rw-r--r--sql/sql_yacc_ora.yy16
16 files changed, 222 insertions, 67 deletions
diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result
index a02e80ed21e..b750d038205 100644
--- a/mysql-test/r/locale.result
+++ b/mysql-test/r/locale.result
@@ -229,15 +229,80 @@ SET lc_time_names=@old_50915_lc_time_names;
# End of 10.1 tests
#
create view v1 as select
+date_format('2001-10-02', '%c %b %M') as a,
+date_format('2001-10-02', '%c %b %M', 'ru_RU') as a1,
format(123456789,2) as b,
format(123456789,2,'rm_CH') as b1;
select * from v1;
-b b1
-123,456,789.00 123'456'789,00
+a a1 b b1
+10 Oct October 10 Окт Октября 123,456,789.00 123'456'789,00
show create view v1;
View Create View character_set_client collation_connection
-v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select format(123456789,2) AS `b`,format(123456789,2,'rm_CH') AS `b1` utf8 utf8_general_ci
+v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select date_format('2001-10-02','%c %b %M') AS `a`,date_format('2001-10-02','%c %b %M','ru_RU') AS `a1`,format(123456789,2) AS `b`,format(123456789,2,'rm_CH') AS `b1` utf8 utf8_general_ci
drop view v1;
#
# End of 10.2 tests
#
+select date_format('2001-01-01', '%w %a %W', 'ro_RO');
+date_format('2001-01-01', '%w %a %W', 'ro_RO')
+1 Lu Luni
+select date_format('2001-01-03', '%w %a %W', 'ro_RO');
+date_format('2001-01-03', '%w %a %W', 'ro_RO')
+3 Mi Miercuri
+select date_format('2001-01-05', '%w %a %W', 'ro_RO');
+date_format('2001-01-05', '%w %a %W', 'ro_RO')
+5 Vi Vineri
+select date_format('2001-01-07', '%w %a %W', 'ro_RO');
+date_format('2001-01-07', '%w %a %W', 'ro_RO')
+0 Du Duminică
+select date_format('2001-01-01', '%w %a %W', 'de_AT');
+date_format('2001-01-01', '%w %a %W', 'de_AT')
+1 Mon Montag
+select date_format('2001-02-01', '%w %a %W', 'de_AT');
+date_format('2001-02-01', '%w %a %W', 'de_AT')
+4 Don Donnerstag
+select date_format('2001-03-01', '%w %a %W', 'de_AT');
+date_format('2001-03-01', '%w %a %W', 'de_AT')
+4 Don Donnerstag
+select date_format('2001-01-01', '%w %a %W', 'en_US');
+date_format('2001-01-01', '%w %a %W', 'en_US')
+1 Mon Monday
+select date_format('2001-03-01', '%c %b %M', 'en_US');
+date_format('2001-03-01', '%c %b %M', 'en_US')
+3 Mar March
+select date_format('2001-01-01', '%w %a %W', 'rm_CH');
+date_format('2001-01-01', '%w %a %W', 'rm_CH')
+1 gli glindesdi
+select date_format('2001-01-03', '%w %a %W', 'rm_CH');
+date_format('2001-01-03', '%w %a %W', 'rm_CH')
+3 me mesemna
+select date_format('2001-01-05', '%w %a %W', 'rm_CH');
+date_format('2001-01-05', '%w %a %W', 'rm_CH')
+5 ve venderdi
+select date_format('2001-01-07', '%w %a %W', 'rm_CH');
+date_format('2001-01-07', '%w %a %W', 'rm_CH')
+0 du dumengia
+select date_format('2001-02-01', '%c %b %M', 'rm_CH');
+date_format('2001-02-01', '%c %b %M', 'rm_CH')
+2 favr favrer
+select date_format('2001-04-01', '%c %b %M', 'rm_CH');
+date_format('2001-04-01', '%c %b %M', 'rm_CH')
+4 avr avrigl
+select date_format('2001-06-01', '%c %b %M', 'rm_CH');
+date_format('2001-06-01', '%c %b %M', 'rm_CH')
+6 zercl zercladur
+select date_format('2001-08-01', '%c %b %M', 'rm_CH');
+date_format('2001-08-01', '%c %b %M', 'rm_CH')
+8 avust avust
+select date_format('2001-10-01', '%c %b %M', 'rm_CH');
+date_format('2001-10-01', '%c %b %M', 'rm_CH')
+10 oct october
+select date_format('2001-12-01', '%c %b %M', 'rm_CH');
+date_format('2001-12-01', '%c %b %M', 'rm_CH')
+12 dec december
+select date_format('2001-01-06', '%w %a %W', 'de_CH');
+date_format('2001-01-06', '%w %a %W', 'de_CH')
+6 Sa Samstag
+select date_format('2001-09-01', '%c %b %M', 'de_CH');
+date_format('2001-09-01', '%c %b %M', 'de_CH')
+9 Sep September
diff --git a/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result
index 6605f7c99b4..2d5bcfe553d 100644
--- a/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result
+++ b/mysql-test/suite/vcol/r/vcol_blocked_sql_funcs.result
@@ -247,3 +247,5 @@ ERROR HY000: Expression in the GENERATED ALWAYS AS clause is too big
# Constant expression
create or replace table t1 (a int as (PI()) PERSISTENT);
drop table if exists t1;
+create table t1 (a timestamp, b varchar(255) as (date_format(a, '%w %a %m %b')) stored);
+ERROR HY000: Function or expression 'date_format()' cannot be used in the GENERATED ALWAYS AS clause of `b`
diff --git a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result
index 3fa4f6e1431..10ab32f9486 100644
--- a/mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result
+++ b/mysql-test/suite/vcol/r/vcol_supported_sql_funcs.result
@@ -2894,6 +2894,21 @@ a b
2012-12-12 Wednesday Wed December Dec
drop table t1;
set sql_warnings = 0;
+# DATE_FORMAT() STORED
+set sql_warnings = 1;
+create table t1 (a date, b varchar(100) as (date_format(a, '%W %a %M %b', 'de_DE')) STORED);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` date DEFAULT NULL,
+ `b` varchar(100) GENERATED ALWAYS AS (date_format(`a`,'%W %a %M %b','de_DE')) STORED
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('2012-12-12',default);
+select * from t1;
+a b
+2012-12-12 Mittwoch Mi Dezember Dez
+drop table t1;
+set sql_warnings = 0;
# CURRENT_USER()
set sql_warnings = 1;
create table t1 (a char, b varchar(32) as (current_user()));
diff --git a/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_main.inc b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_main.inc
index 766d0c7410c..37de02a2b29 100644
--- a/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_main.inc
+++ b/mysql-test/suite/vcol/t/vcol_blocked_sql_funcs_main.inc
@@ -354,3 +354,6 @@ eval create or replace table t1 (a int, b varchar(16384) as (concat(a,'$tmp_long
create or replace table t1 (a int as (PI()) PERSISTENT);
drop table if exists t1;
+
+--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
+create table t1 (a timestamp, b varchar(255) as (date_format(a, '%w %a %m %b')) stored);
diff --git a/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_main.inc b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_main.inc
index dafc42098dd..fa2162e5981 100644
--- a/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_main.inc
+++ b/mysql-test/suite/vcol/t/vcol_supported_sql_funcs_main.inc
@@ -1197,6 +1197,12 @@ let $values1 = '2012-12-12',default;
let $rows = 1;
--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+--echo # DATE_FORMAT() STORED
+let $cols = a date, b varchar(100) as (date_format(a, '%W %a %M %b', 'de_DE')) STORED;
+let $values1 = '2012-12-12',default;
+let $rows = 1;
+--source suite/vcol/inc/vcol_supported_sql_funcs.inc
+
--echo # CURRENT_USER()
let $cols = a char, b varchar(32) as (current_user());
let $values1 = 'a', default;
diff --git a/mysql-test/t/locale.test b/mysql-test/t/locale.test
index 4570b968ecf..a9a507bc387 100644
--- a/mysql-test/t/locale.test
+++ b/mysql-test/t/locale.test
@@ -144,6 +144,8 @@ SET lc_time_names=@old_50915_lc_time_names;
# Item::print
create view v1 as select
+ date_format('2001-10-02', '%c %b %M') as a,
+ date_format('2001-10-02', '%c %b %M', 'ru_RU') as a1,
format(123456789,2) as b,
format(123456789,2,'rm_CH') as b1;
select * from v1;
@@ -153,3 +155,29 @@ drop view v1;
--echo #
--echo # End of 10.2 tests
--echo #
+
+#
+# MDEV-11553 Can't restore a PERSISTENT column that uses DATE_FORMAT()
+#
+# 3-argument syntax for DATE_FORMAT()
+select date_format('2001-01-01', '%w %a %W', 'ro_RO');
+select date_format('2001-01-03', '%w %a %W', 'ro_RO');
+select date_format('2001-01-05', '%w %a %W', 'ro_RO');
+select date_format('2001-01-07', '%w %a %W', 'ro_RO');
+select date_format('2001-01-01', '%w %a %W', 'de_AT');
+select date_format('2001-02-01', '%w %a %W', 'de_AT');
+select date_format('2001-03-01', '%w %a %W', 'de_AT');
+select date_format('2001-01-01', '%w %a %W', 'en_US');
+select date_format('2001-03-01', '%c %b %M', 'en_US');
+select date_format('2001-01-01', '%w %a %W', 'rm_CH');
+select date_format('2001-01-03', '%w %a %W', 'rm_CH');
+select date_format('2001-01-05', '%w %a %W', 'rm_CH');
+select date_format('2001-01-07', '%w %a %W', 'rm_CH');
+select date_format('2001-02-01', '%c %b %M', 'rm_CH');
+select date_format('2001-04-01', '%c %b %M', 'rm_CH');
+select date_format('2001-06-01', '%c %b %M', 'rm_CH');
+select date_format('2001-08-01', '%c %b %M', 'rm_CH');
+select date_format('2001-10-01', '%c %b %M', 'rm_CH');
+select date_format('2001-12-01', '%c %b %M', 'rm_CH');
+select date_format('2001-01-06', '%w %a %W', 'de_CH');
+select date_format('2001-09-01', '%c %b %M', 'de_CH');
diff --git a/sql/item.cc b/sql/item.cc
index 4a3847f800e..9dcc81bbae7 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1451,6 +1451,25 @@ bool Item::get_seconds(ulonglong *sec, ulong *sec_part)
return my_decimal2seconds(dec, sec, sec_part);
}
+const MY_LOCALE *Item::locale_from_val_str()
+{
+ StringBuffer<MAX_FIELD_WIDTH> tmp;
+ String *locale_name= val_str_ascii(&tmp);
+ const MY_LOCALE *lc;
+ if (!locale_name ||
+ !(lc= my_locale_by_name(locale_name->c_ptr_safe())))
+ {
+ THD *thd= current_thd;
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_UNKNOWN_LOCALE,
+ ER_THD(thd, ER_UNKNOWN_LOCALE),
+ locale_name ? locale_name->c_ptr_safe() : "NULL");
+ lc= &my_locale_en_US;
+ }
+ return lc;
+}
+
+
CHARSET_INFO *Item::default_charset()
{
return current_thd->variables.collation_connection;
diff --git a/sql/item.h b/sql/item.h
index 3f8ccb88392..04dad5265d3 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -491,6 +491,8 @@ struct find_selective_predicates_list_processor_data
List<st_cond_statistic> list;
};
+class MY_LOCALE;
+
class Item_equal;
class COND_EQUAL;
@@ -644,6 +646,8 @@ public:
*/
String *val_str() { return val_str(&str_value); }
+ const MY_LOCALE *locale_from_val_str();
+
LEX_CSTRING name; /* Name of item */
/* Original item name (if it was renamed)*/
const char *orig_name;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index b0b33041383..5f1485a1336 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -783,19 +783,6 @@ protected:
#endif
-class Create_func_date_format : public Create_func_arg2
-{
-public:
- virtual Item *create_2_arg(THD *thd, Item *arg1, Item *arg2);
-
- static Create_func_date_format s_singleton;
-
-protected:
- Create_func_date_format() {}
- virtual ~Create_func_date_format() {}
-};
-
-
class Create_func_datediff : public Create_func_arg2
{
public:
@@ -4051,15 +4038,6 @@ Create_func_crosses::create_2_arg(THD *thd, Item *arg1, Item *arg2)
#endif
-Create_func_date_format Create_func_date_format::s_singleton;
-
-Item*
-Create_func_date_format::create_2_arg(THD *thd, Item *arg1, Item *arg2)
-{
- return new (thd->mem_root) Item_func_date_format(thd, arg1, arg2, 0);
-}
-
-
Create_func_datediff Create_func_datediff::s_singleton;
Item*
@@ -4558,7 +4536,7 @@ Create_func_from_unixtime::create_native(THD *thd, LEX_CSTRING *name,
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
Item *ut= new (thd->mem_root) Item_func_from_unixtime(thd, param_1);
- func= new (thd->mem_root) Item_func_date_format(thd, ut, param_2, 0);
+ func= new (thd->mem_root) Item_func_date_format(thd, ut, param_2);
break;
}
default:
@@ -6511,7 +6489,7 @@ Create_func_time_format Create_func_time_format::s_singleton;
Item*
Create_func_time_format::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
- return new (thd->mem_root) Item_func_date_format(thd, arg1, arg2, 1);
+ return new (thd->mem_root) Item_func_time_format(thd, arg1, arg2);
}
@@ -6872,7 +6850,6 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("CRC32") }, BUILDER(Create_func_crc32)},
{ { C_STRING_WITH_LEN("CROSSES") }, GEOM_BUILDER(Create_func_crosses)},
{ { C_STRING_WITH_LEN("DATEDIFF") }, BUILDER(Create_func_datediff)},
- { { C_STRING_WITH_LEN("DATE_FORMAT") }, BUILDER(Create_func_date_format)},
{ { C_STRING_WITH_LEN("DAYNAME") }, BUILDER(Create_func_dayname)},
{ { C_STRING_WITH_LEN("DAYOFMONTH") }, BUILDER(Create_func_dayofmonth)},
{ { C_STRING_WITH_LEN("DAYOFWEEK") }, BUILDER(Create_func_dayofweek)},
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 83432f95612..d29e579bcd9 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2668,24 +2668,6 @@ String *Item_func_soundex::val_str(String *str)
const int FORMAT_MAX_DECIMALS= 30;
-MY_LOCALE *Item_func_format::get_locale(Item *item)
-{
- DBUG_ASSERT(arg_count == 3);
- String tmp, *locale_name= args[2]->val_str_ascii(&tmp);
- MY_LOCALE *lc;
- if (!locale_name ||
- !(lc= my_locale_by_name(locale_name->c_ptr_safe())))
- {
- THD *thd= current_thd;
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_UNKNOWN_LOCALE,
- ER_THD(thd, ER_UNKNOWN_LOCALE),
- locale_name ? locale_name->c_ptr_safe() : "NULL");
- lc= &my_locale_en_US;
- }
- return lc;
-}
-
void Item_func_format::fix_length_and_dec()
{
uint32 char_length= args[0]->max_char_length();
@@ -2693,7 +2675,7 @@ void Item_func_format::fix_length_and_dec()
collation.set(default_charset());
fix_char_length(char_length + max_sep_count + decimals);
if (arg_count == 3)
- locale= args[2]->basic_const_item() ? get_locale(args[2]) : NULL;
+ locale= args[2]->basic_const_item() ? args[2]->locale_from_val_str() : NULL;
else
locale= &my_locale_en_US; /* Two arguments */
}
@@ -2712,7 +2694,7 @@ String *Item_func_format::val_str_ascii(String *str)
int dec;
/* Number of characters used to represent the decimals, including '.' */
uint32 dec_length;
- MY_LOCALE *lc;
+ const MY_LOCALE *lc;
DBUG_ASSERT(fixed == 1);
dec= (int) args[1]->val_int();
@@ -2722,7 +2704,7 @@ String *Item_func_format::val_str_ascii(String *str)
return NULL;
}
- lc= locale ? locale : get_locale(args[2]);
+ lc= locale ? locale : args[2]->locale_from_val_str();
dec= set_zone(dec, 0, FORMAT_MAX_DECIMALS);
dec_length= dec ? dec+1 : 0;
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index a7cad234893..d73bd0b76d7 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -27,8 +27,6 @@
extern size_t username_char_length;
-class MY_LOCALE;
-
class Item_str_func :public Item_func
{
protected:
@@ -932,14 +930,13 @@ public:
class Item_func_format :public Item_str_ascii_func
{
- MY_LOCALE *locale;
+ const MY_LOCALE *locale;
public:
Item_func_format(THD *thd, Item *org, Item *dec):
Item_str_ascii_func(thd, org, dec) {}
Item_func_format(THD *thd, Item *org, Item *dec, Item *lang):
Item_str_ascii_func(thd, org, dec, lang) {}
- MY_LOCALE *get_locale(Item *item);
String *val_str_ascii(String *);
void fix_length_and_dec();
const char *func_name() const { return "format"; }
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 86bde00cced..189addc767b 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -455,7 +455,8 @@ err:
*/
static bool make_date_time(DATE_TIME_FORMAT *format, MYSQL_TIME *l_time,
- timestamp_type type, MY_LOCALE *locale, String *str)
+ timestamp_type type, const MY_LOCALE *locale,
+ String *str)
{
char intbuff[15];
uint hours_i;
@@ -1833,7 +1834,14 @@ overflow:
void Item_func_date_format::fix_length_and_dec()
{
THD* thd= current_thd;
- locale= thd->variables.lc_time_names;
+ if (!is_time_format)
+ {
+ if (arg_count < 3)
+ locale= thd->variables.lc_time_names;
+ else
+ if (args[2]->basic_const_item())
+ locale= args[2]->locale_from_val_str();
+ }
/*
Must use this_item() in case it's a local SP variable
@@ -1875,6 +1883,8 @@ bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const
if (this == item)
return 1;
item_func= (Item_func_date_format*) item;
+ if (arg_count != item_func->arg_count)
+ return 0;
if (!args[0]->eq(item_func->args[0], binary_cmp))
return 0;
/*
@@ -1884,6 +1894,8 @@ bool Item_func_date_format::eq(const Item *item, bool binary_cmp) const
*/
if (!args[1]->eq(item_func->args[1], 1))
return 0;
+ if (arg_count > 2 && !args[2]->eq(item_func->args[2], 1))
+ return 0;
return 1;
}
@@ -1967,15 +1979,18 @@ String *Item_func_date_format::val_str(String *str)
String *format;
MYSQL_TIME l_time;
uint size;
- int is_time_flag = is_time_format ? TIME_TIME_ONLY : 0;
+ const MY_LOCALE *lc= 0;
DBUG_ASSERT(fixed == 1);
- if (get_arg0_date(&l_time, is_time_flag))
+ if (get_arg0_date(&l_time, is_time_format ? TIME_TIME_ONLY : 0))
return 0;
if (!(format = args[1]->val_str(str)) || !format->length())
goto null_date;
+ if (!is_time_format && !(lc= locale) && !(lc= args[2]->locale_from_val_str()))
+ goto null_date; // invalid locale
+
if (fixed_length)
size=max_length;
else
@@ -1998,7 +2013,7 @@ String *Item_func_date_format::val_str(String *str)
if (!make_date_time(&date_time_format, &l_time,
is_time_format ? MYSQL_TIMESTAMP_TIME :
MYSQL_TIMESTAMP_DATE,
- locale, str))
+ lc, str))
return str;
null_date:
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 7d2fe46b644..20ecb4774b3 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -797,22 +797,24 @@ public:
class Item_func_date_format :public Item_str_func
{
- MY_LOCALE *locale;
+ const MY_LOCALE *locale;
int fixed_length;
- const bool is_time_format;
String value;
+protected:
+ bool is_time_format;
public:
- Item_func_date_format(THD *thd, Item *a, Item *b, bool is_time_format_arg):
- Item_str_func(thd, a, b), is_time_format(is_time_format_arg) {}
+ Item_func_date_format(THD *thd, Item *a, Item *b):
+ Item_str_func(thd, a, b), locale(0), is_time_format(false) {}
+ Item_func_date_format(THD *thd, Item *a, Item *b, Item *c):
+ Item_str_func(thd, a, b, c), locale(0), is_time_format(false) {}
String *val_str(String *str);
- const char *func_name() const
- { return is_time_format ? "time_format" : "date_format"; }
+ const char *func_name() const { return "date_format"; }
void fix_length_and_dec();
uint format_length(const String *format);
bool eq(const Item *item, bool binary_cmp) const;
bool check_vcol_func_processor(void *arg)
{
- if (is_time_format)
+ if (arg_count > 2)
return false;
return mark_unsupported_function(func_name(), "()", arg, VCOL_SESSION_FUNC);
}
@@ -820,6 +822,17 @@ public:
{ return get_item_copy<Item_func_date_format>(thd, mem_root, this); }
};
+class Item_func_time_format: public Item_func_date_format
+{
+public:
+ Item_func_time_format(THD *thd, Item *a, Item *b):
+ Item_func_date_format(thd, a, b) { is_time_format= true; }
+ const char *func_name() const { return "time_format"; }
+ bool check_vcol_func_processor(void *arg) { return false; }
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_func_time_format>(thd, mem_root, this); }
+};
+
class Item_func_from_unixtime :public Item_datetimefunc
{
diff --git a/sql/lex.h b/sql/lex.h
index f2dac95fce5..67c3bc8620d 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -726,6 +726,7 @@ static SYMBOL sql_functions[] = {
{ "CURTIME", SYM(CURTIME)},
{ "DATE_ADD", SYM(DATE_ADD_INTERVAL)},
{ "DATE_SUB", SYM(DATE_SUB_INTERVAL)},
+ { "DATE_FORMAT", SYM(DATE_FORMAT_SYM)},
{ "DECODE", SYM(DECODE_SYM)},
{ "DENSE_RANK", SYM(DENSE_RANK_SYM)},
{ "EXTRACT", SYM(EXTRACT_SYM)},
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 7e89ad91a17..17d6f016b2c 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -875,7 +875,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
Comments for TOKENS.
For each token, please include in the same line a comment that contains
the following tags:
- SQL-2011-N : Non Reserved keywird as per SQL-2011
+ SQL-2011-N : Non Reserved keyword as per SQL-2011
SQL-2003-R : Reserved keyword as per SQL-2003
SQL-2003-N : Non Reserved keyword as per SQL-2003
SQL-1999-R : Reserved keyword as per SQL-1999
@@ -1010,6 +1010,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DATA_SYM /* SQL-2003-N */
%token DATETIME
%token DATE_ADD_INTERVAL /* MYSQL-FUNC */
+%token DATE_FORMAT_SYM /* MYSQL-FUNC */
%token DATE_SUB_INTERVAL /* MYSQL-FUNC */
%token DATE_SYM /* SQL-2003-R */
%token DAY_HOUR_SYM
@@ -9806,6 +9807,18 @@ function_call_nonkeyword:
if ($$ == NULL)
MYSQL_YYABORT;
}
+ | DATE_FORMAT_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_date_format(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | DATE_FORMAT_SYM '(' expr ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_date_format(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
| DECODE_SYM '(' expr ',' expr ')'
{
$$= new (thd->mem_root) Item_func_decode(thd, $3, $5);
@@ -14719,6 +14732,7 @@ keyword_sp_not_data_type:
| CYCLE_SYM {}
| DATA_SYM {}
| DATAFILE_SYM {}
+ | DATE_FORMAT_SYM {}
| DAY_SYM {}
| DECODE_SYM {}
| DEFINER_SYM {}
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 8d250abd994..052c219a7a4 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -284,7 +284,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
Comments for TOKENS.
For each token, please include in the same line a comment that contains
the following tags:
- SQL-2011-N : Non Reserved keywird as per SQL-2011
+ SQL-2011-N : Non Reserved keyword as per SQL-2011
SQL-2003-R : Reserved keyword as per SQL-2003
SQL-2003-N : Non Reserved keyword as per SQL-2003
SQL-1999-R : Reserved keyword as per SQL-1999
@@ -419,6 +419,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token DATA_SYM /* SQL-2003-N */
%token DATETIME
%token DATE_ADD_INTERVAL /* MYSQL-FUNC */
+%token DATE_FORMAT_SYM /* MYSQL-FUNC */
%token DATE_SUB_INTERVAL /* MYSQL-FUNC */
%token DATE_SYM /* SQL-2003-R */
%token DAY_HOUR_SYM
@@ -9462,6 +9463,18 @@ column_default_non_parenthesized_expr:
if ($$ == NULL)
MYSQL_YYABORT;
}
+ | DATE_FORMAT_SYM '(' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_date_format(thd, $3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ | DATE_FORMAT_SYM '(' expr ',' expr ',' expr ')'
+ {
+ $$= new (thd->mem_root) Item_func_date_format(thd, $3, $5, $7);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
| DECODE_SYM '(' expr ',' decode_when_list ')'
{
$5->push_front($3, thd->mem_root);
@@ -14893,6 +14906,7 @@ keyword_sp_not_data_type:
| CYCLE_SYM {}
| DATA_SYM {}
| DATAFILE_SYM {}
+ | DATE_FORMAT_SYM {}
| DAY_SYM {}
| DECODE_SYM {}
| DEFINER_SYM {}