Commit 4f3eab58 authored by unknown's avatar unknown

Fix for bug #33834: FRAC_SECOND: Applicability not clear in

                    documentation

While the manual mentions FRAC_SECOND only for the TIMESTAMPADD()
function, it was also possible to use FRAC_SECOND with DATE_ADD(),
DATE_SUB() and +/- INTERVAL.

Fixed the parser to match the manual, i.e. using FRAC_SECOND for 
anything other than TIMESTAMPADD()/TIMESTAMPDIFF() now produces a 
syntax error.

Additionally, the patch allows MICROSECOND to be used in TIMESTAMPADD/
TIMESTAMPDIFF and marks FRAC_SECOND as deprecated.


mysql-test/r/func_time.result:
  Added a test case for bug #33834.
mysql-test/t/func_time.test:
  Added a test case for bug #33834.
sql/sql_yacc.yy:
  Reject FRAC_SECOND for anything other than TIMESTAMPADD() or
  TIMESTAMPDIFF().
  Allow MICROSECOND to be used with TIMESTAMPADD()/TIMESTAMPDIFF().
  Warn about FRAC_SECOND being a deprecated unit.
parent c4fc5b09
...@@ -666,6 +666,8 @@ timestampadd(SQL_TSI_SECOND, 1, date) ...@@ -666,6 +666,8 @@ timestampadd(SQL_TSI_SECOND, 1, date)
select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1; select timestampadd(SQL_TSI_FRAC_SECOND, 1, date) from t1;
timestampadd(SQL_TSI_FRAC_SECOND, 1, date) timestampadd(SQL_TSI_FRAC_SECOND, 1, date)
2003-01-02 00:00:00.000001 2003-01-02 00:00:00.000001
Warnings:
Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead
select timestampdiff(MONTH, '2001-02-01', '2001-05-01') as a; select timestampdiff(MONTH, '2001-02-01', '2001-05-01') as a;
a a
3 3
...@@ -699,6 +701,8 @@ a ...@@ -699,6 +701,8 @@ a
select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a; select timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a;
a a
7689538999999 7689538999999
Warnings:
Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead
select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1, select timestampdiff(SQL_TSI_DAY, '1986-02-01', '1986-03-01') as a1,
timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2, timestampdiff(SQL_TSI_DAY, '1900-02-01', '1900-03-01') as a2,
timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3, timestampdiff(SQL_TSI_DAY, '1996-02-01', '1996-03-01') as a3,
...@@ -1069,6 +1073,7 @@ timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12: ...@@ -1069,6 +1073,7 @@ timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings: Warnings:
Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead
Note 1003 select timestampdiff(WEEK,_latin1'2001-02-01',_latin1'2001-05-01') AS `a1`,timestampdiff(SECOND_FRAC,_latin1'2001-02-01 12:59:59.120000',_latin1'2001-05-01 12:58:58.119999') AS `a2` Note 1003 select timestampdiff(WEEK,_latin1'2001-02-01',_latin1'2001-05-01') AS `a1`,timestampdiff(SECOND_FRAC,_latin1'2001-02-01 12:59:59.120000',_latin1'2001-05-01 12:58:58.119999') AS `a2`
select last_day('2005-00-00'); select last_day('2005-00-00');
last_day('2005-00-00') last_day('2005-00-00')
...@@ -1285,4 +1290,22 @@ DATE_ADD(20071108, INTERVAL 1 DAY) ...@@ -1285,4 +1290,22 @@ DATE_ADD(20071108, INTERVAL 1 DAY)
select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND; select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND;
LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND
2007-12-30 23:59:59 2007-12-30 23:59:59
SELECT TIMESTAMPADD(FRAC_SECOND, 1, '2008-02-18');
TIMESTAMPADD(FRAC_SECOND, 1, '2008-02-18')
2008-02-18 00:00:00.000001
Warnings:
Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead
SELECT TIMESTAMPDIFF(FRAC_SECOND, '2008-02-17', '2008-02-18');
TIMESTAMPDIFF(FRAC_SECOND, '2008-02-17', '2008-02-18')
86400000000
Warnings:
Warning 1287 'FRAC_SECOND' is deprecated; use 'MICROSECOND' instead
SELECT DATE_ADD('2008-02-18', INTERVAL 1 FRAC_SECOND);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND)' at line 1
SELECT DATE_SUB('2008-02-18', INTERVAL 1 FRAC_SECOND);
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND)' at line 1
SELECT '2008-02-18' + INTERVAL 1 FRAC_SECOND;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND' at line 1
SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND' at line 1
End of 5.0 tests End of 5.0 tests
...@@ -804,4 +804,23 @@ select DATE_ADD(20071108, INTERVAL 1 DAY); ...@@ -804,4 +804,23 @@ select DATE_ADD(20071108, INTERVAL 1 DAY);
select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND; select LAST_DAY('2007-12-06 08:59:19.05') - INTERVAL 1 SECOND;
#
# Bug#33834: FRAC_SECOND: Applicability not clear in documentation
#
# Show that he use of FRAC_SECOND, for anything other than
# TIMESTAMPADD / TIMESTAMPDIFF, is a server error.
SELECT TIMESTAMPADD(FRAC_SECOND, 1, '2008-02-18');
SELECT TIMESTAMPDIFF(FRAC_SECOND, '2008-02-17', '2008-02-18');
--error ER_PARSE_ERROR
SELECT DATE_ADD('2008-02-18', INTERVAL 1 FRAC_SECOND);
--error ER_PARSE_ERROR
SELECT DATE_SUB('2008-02-18', INTERVAL 1 FRAC_SECOND);
--error ER_PARSE_ERROR
SELECT '2008-02-18' + INTERVAL 1 FRAC_SECOND;
--error ER_PARSE_ERROR
SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -458,10 +458,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -458,10 +458,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%pure_parser /* We have threads */ %pure_parser /* We have threads */
/* /*
Currently there are 245 shift/reduce conflicts. Currently there are 240 shift/reduce conflicts.
We should not introduce new conflicts any more. We should not introduce new conflicts any more.
*/ */
%expect 245 %expect 240
%token END_OF_INPUT %token END_OF_INPUT
...@@ -1111,6 +1111,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1111,6 +1111,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <interval_time_st> interval_time_st %type <interval_time_st> interval_time_st
%type <interval_time_st> interval_time_stamp
%type <db_type> storage_engines %type <db_type> storage_engines
%type <row_type> row_types %type <row_type> row_types
...@@ -5027,9 +5029,9 @@ simple_expr: ...@@ -5027,9 +5029,9 @@ simple_expr:
{ $$= new Item_datetime_typecast($3); } { $$= new Item_datetime_typecast($3); }
| TIMESTAMP '(' expr ',' expr ')' | TIMESTAMP '(' expr ',' expr ')'
{ $$= new Item_func_add_time($3, $5, 1, 0); } { $$= new Item_func_add_time($3, $5, 1, 0); }
| TIMESTAMP_ADD '(' interval_time_st ',' expr ',' expr ')' | TIMESTAMP_ADD '(' interval_time_stamp ',' expr ',' expr ')'
{ $$= new Item_date_add_interval($7,$5,$3,0); } { $$= new Item_date_add_interval($7,$5,$3,0); }
| TIMESTAMP_DIFF '(' interval_time_st ',' expr ',' expr ')' | TIMESTAMP_DIFF '(' interval_time_stamp ',' expr ',' expr ')'
{ $$= new Item_func_timestamp_diff($5,$7,$3); } { $$= new Item_func_timestamp_diff($5,$7,$3); }
| TRIM '(' expr ')' | TRIM '(' expr ')'
{ $$= new Item_func_trim($3); } { $$= new Item_func_trim($3); }
...@@ -6005,21 +6007,40 @@ interval: ...@@ -6005,21 +6007,40 @@ interval:
| HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; } | HOUR_MICROSECOND_SYM { $$=INTERVAL_HOUR_MICROSECOND; }
| HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; } | HOUR_MINUTE_SYM { $$=INTERVAL_HOUR_MINUTE; }
| HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; } | HOUR_SECOND_SYM { $$=INTERVAL_HOUR_SECOND; }
| MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; }
| MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; } | MINUTE_MICROSECOND_SYM { $$=INTERVAL_MINUTE_MICROSECOND; }
| MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; } | MINUTE_SECOND_SYM { $$=INTERVAL_MINUTE_SECOND; }
| SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; } | SECOND_MICROSECOND_SYM { $$=INTERVAL_SECOND_MICROSECOND; }
| YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; }; | YEAR_MONTH_SYM { $$=INTERVAL_YEAR_MONTH; };
interval_time_stamp:
interval_time_st {}
| FRAC_SECOND_SYM {
$$=INTERVAL_MICROSECOND;
/*
FRAC_SECOND was mistakenly implemented with
a wrong resolution. According to the ODBC
standard it should be nanoseconds, not
microseconds. Changing it to nanoseconds
in MySQL would mean making TIMESTAMPDIFF
and TIMESTAMPADD to return DECIMAL, since
the return value would be too big for BIGINT
Hence we just deprecate the incorrect
implementation without changing its
resolution.
*/
WARN_DEPRECATED("FRAC_SECOND", "MICROSECOND"); // Will be removed in 6.2
}
;
interval_time_st: interval_time_st:
DAY_SYM { $$=INTERVAL_DAY; } DAY_SYM { $$=INTERVAL_DAY; }
| WEEK_SYM { $$=INTERVAL_WEEK; } | WEEK_SYM { $$=INTERVAL_WEEK; }
| HOUR_SYM { $$=INTERVAL_HOUR; } | HOUR_SYM { $$=INTERVAL_HOUR; }
| FRAC_SECOND_SYM { $$=INTERVAL_MICROSECOND; }
| MINUTE_SYM { $$=INTERVAL_MINUTE; } | MINUTE_SYM { $$=INTERVAL_MINUTE; }
| MONTH_SYM { $$=INTERVAL_MONTH; } | MONTH_SYM { $$=INTERVAL_MONTH; }
| QUARTER_SYM { $$=INTERVAL_QUARTER; } | QUARTER_SYM { $$=INTERVAL_QUARTER; }
| SECOND_SYM { $$=INTERVAL_SECOND; } | SECOND_SYM { $$=INTERVAL_SECOND; }
| MICROSECOND_SYM { $$=INTERVAL_MICROSECOND; }
| YEAR_SYM { $$=INTERVAL_YEAR; } | YEAR_SYM { $$=INTERVAL_YEAR; }
; ;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment