Below is the list of changes that have just been committed into a local
5.1 repository of davi. When davi does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-11-30 09:34:25-02:00, davi@stripped +3 -0
Bug#22312 Syntax error in expression with INTERVAL()
Parser rejects valid INTERVAL() expressions when associated with
arithmetic operators. The problem is the way in which the expression
and interval grammar rules were organized caused shift/reduce conflicts.
The solution is to tweak the interval rules to avoid shift/reduce
conflicts by removing the broken interval_expr rule and explicitly
specify it's content where necessary.
Original fix by Davi Arnaut, revised and improved rules by Marc Alff
mysql-test/r/parser.result@stripped, 2007-11-30 09:34:22-02:00, davi@stripped +43 -0
Add test case result for Bug#22312
mysql-test/t/parser.test@stripped, 2007-11-30 09:34:22-02:00, davi@stripped +28 -0
Add test case for Bug#22312
sql/sql_yacc.yy@stripped, 2007-11-30 09:34:23-02:00, davi@stripped +30 -27
Resolve shift/reduce conflicts by reorganizing the interval
expression rules.
diff -Nrup a/mysql-test/r/parser.result b/mysql-test/r/parser.result
--- a/mysql-test/r/parser.result 2007-08-09 20:30:56 -03:00
+++ b/mysql-test/r/parser.result 2007-11-30 09:34:22 -02:00
@@ -484,3 +484,46 @@ select atan(10, 20 "p2");
ERROR 42000: Incorrect parameters in the call to native function 'atan'
select atan(10 AS p1, 20 AS p2);
ERROR 42000: Incorrect parameters in the call to native function 'atan'
+DROP TABLE IF EXISTS t1;
+SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE;
+STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE
+NULL
+SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL (INTERVAL(1,2,3) + 1) MINUTE;
+STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL (INTERVAL(1,2,3) + 1) MINUTE
+NULL
+SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
+"1997-12-31 23:59:59" + INTERVAL 1 SECOND
+1998-01-01 00:00:00
+SELECT 1 + INTERVAL(1,0,1,2) + 1;
+1 + INTERVAL(1,0,1,2) + 1
+4
+SELECT INTERVAL(1^1,0,1,2) + 1;
+INTERVAL(1^1,0,1,2) + 1
+2
+SELECT INTERVAL(1,0+1,2,3) * 5.5;
+INTERVAL(1,0+1,2,3) * 5.5
+5.5
+SELECT INTERVAL(3,3,1+3,4+4) / 0.5;
+INTERVAL(3,3,1+3,4+4) / 0.5
+2.0000
+SELECT (INTERVAL(1,0,1,2) + 5) * 7 + INTERVAL(1,0,1,2) / 2;
+(INTERVAL(1,0,1,2) + 5) * 7 + INTERVAL(1,0,1,2) / 2
+50.0000
+SELECT INTERVAL(1,0,1,2) + 1, 5 * INTERVAL(1,0,1,2);
+INTERVAL(1,0,1,2) + 1 5 * INTERVAL(1,0,1,2)
+3 10
+SELECT INTERVAL(0,(1*5)/2) + INTERVAL(5,4,3);
+INTERVAL(0,(1*5)/2) + INTERVAL(5,4,3)
+2
+SELECT 1^1 + INTERVAL 1+1 SECOND & 1 + INTERVAL 1+1 SECOND;
+1^1 + INTERVAL 1+1 SECOND & 1 + INTERVAL 1+1 SECOND
+NULL
+SELECT 1%2 - INTERVAL 1^1 SECOND | 1%2 - INTERVAL 1^1 SECOND;
+1%2 - INTERVAL 1^1 SECOND | 1%2 - INTERVAL 1^1 SECOND
+NULL
+CREATE TABLE t1 (a INT, b DATETIME);
+INSERT INTO t1 VALUES (INTERVAL(3,2,1) + 1, "1997-12-31 23:59:59" + INTERVAL 1 SECOND);
+SELECT * FROM t1 WHERE a = INTERVAL(3,2,1) + 1;
+a b
+3 1998-01-01 00:00:00
+DROP TABLE t1;
diff -Nrup a/mysql-test/t/parser.test b/mysql-test/t/parser.test
--- a/mysql-test/t/parser.test 2007-08-09 20:30:56 -03:00
+++ b/mysql-test/t/parser.test 2007-11-30 09:34:22 -02:00
@@ -629,3 +629,31 @@ select atan(10, 20 "p2");
-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT
select atan(10 AS p1, 20 AS p2);
+#
+# Bug#22312 Syntax error in expression with INTERVAL()
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE;
+SELECT STR_TO_DATE('10:00 PM', '%h:%i %p') + INTERVAL (INTERVAL(1,2,3) + 1) MINUTE;
+SELECT "1997-12-31 23:59:59" + INTERVAL 1 SECOND;
+SELECT 1 + INTERVAL(1,0,1,2) + 1;
+SELECT INTERVAL(1^1,0,1,2) + 1;
+SELECT INTERVAL(1,0+1,2,3) * 5.5;
+SELECT INTERVAL(3,3,1+3,4+4) / 0.5;
+SELECT (INTERVAL(1,0,1,2) + 5) * 7 + INTERVAL(1,0,1,2) / 2;
+SELECT INTERVAL(1,0,1,2) + 1, 5 * INTERVAL(1,0,1,2);
+SELECT INTERVAL(0,(1*5)/2) + INTERVAL(5,4,3);
+
+--disable_warnings
+SELECT 1^1 + INTERVAL 1+1 SECOND & 1 + INTERVAL 1+1 SECOND;
+SELECT 1%2 - INTERVAL 1^1 SECOND | 1%2 - INTERVAL 1^1 SECOND;
+--enable_warnings
+
+CREATE TABLE t1 (a INT, b DATETIME);
+INSERT INTO t1 VALUES (INTERVAL(3,2,1) + 1, "1997-12-31 23:59:59" + INTERVAL 1 SECOND);
+SELECT * FROM t1 WHERE a = INTERVAL(3,2,1) + 1;
+DROP TABLE t1;
diff -Nrup a/sql/sql_yacc.yy b/sql/sql_yacc.yy
--- a/sql/sql_yacc.yy 2007-11-28 14:08:26 -02:00
+++ b/sql/sql_yacc.yy 2007-11-30 09:34:23 -02:00
@@ -508,10 +508,10 @@ bool my_yyoverflow(short **a, YYSTYPE **
%pure_parser /* We have threads */
/*
- Currently there are 280 shift/reduce conflicts.
+ Currently there are 177 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 280
+%expect 177
/*
Comments for TOKENS.
@@ -1157,7 +1157,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
variable variable_aux bool_pri
predicate bit_expr
table_wild simple_expr udf_expr
- expr_or_default set_expr_or_default interval_expr
+ expr_or_default set_expr_or_default
param_marker geometry_function
signed_literal now_or_signed_literal opt_escape
sp_opt_default
@@ -6569,10 +6569,10 @@ bit_expr:
{ $$= new Item_func_plus($1,$3); }
| bit_expr '-' bit_expr %prec '-'
{ $$= new Item_func_minus($1,$3); }
- | bit_expr '+' interval_expr interval %prec '+'
- { $$= new Item_date_add_interval($1,$3,$4,0); }
- | bit_expr '-' interval_expr interval %prec '-'
- { $$= new Item_date_add_interval($1,$3,$4,1); }
+ | bit_expr '+' INTERVAL_SYM expr interval %prec '+'
+ { $$= new Item_date_add_interval($1,$4,$5,0); }
+ | bit_expr '-' INTERVAL_SYM expr interval %prec '-'
+ { $$= new Item_date_add_interval($1,$4,$5,1); }
| bit_expr '*' bit_expr %prec '*'
{ $$= new Item_func_mul($1,$3); }
| bit_expr '/' bit_expr %prec '/'
@@ -6622,11 +6622,6 @@ all_or_any:
| ANY_SYM { $$ = 0; }
;
-interval_expr:
- INTERVAL_SYM expr %prec INTERVAL_SYM
- { $$=$2; }
- ;
-
simple_expr:
simple_ident
| function_call_keyword
@@ -6722,18 +6717,9 @@ simple_expr:
$$= new (YYTHD->mem_root) Item_insert_value(Lex->current_context(),
$3);
}
- | interval_expr interval '+' expr
+ | INTERVAL_SYM expr interval '+' expr %prec INTERVAL_SYM
/* we cannot put interval before - */
- { $$= new (YYTHD->mem_root) Item_date_add_interval($4,$1,$2,0); }
- | interval_expr
- {
- if ($1->type() != Item::ROW_ITEM)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
- $$= new (YYTHD->mem_root) Item_func_interval((Item_row *)$1);
- }
+ { $$= new (YYTHD->mem_root) Item_date_add_interval($5,$2,$3,0); }
;
/*
@@ -6761,6 +6747,23 @@ function_call_keyword:
{ $$= new (YYTHD->mem_root) Item_func_hour($3); }
| INSERT '(' expr ',' expr ',' expr ',' expr ')'
{ $$= new (YYTHD->mem_root) Item_func_insert($3,$5,$7,$9); }
+ | INTERVAL_SYM '(' expr ',' expr ')' %prec INTERVAL_SYM
+ {
+ THD *thd= YYTHD;
+ List<Item> *list= new (thd->mem_root) List<Item>;
+ list->push_front($5);
+ list->push_front($3);
+ Item_row *item= new (thd->mem_root) Item_row(*list);
+ $$= new (thd->mem_root) Item_func_interval(item);
+ }
+ | INTERVAL_SYM '(' expr ',' expr ',' expr_list ')' %prec INTERVAL_SYM
+ {
+ THD *thd= YYTHD;
+ $7->push_front($5);
+ $7->push_front($3);
+ Item_row *item= new (thd->mem_root) Item_row(*$7);
+ $$= new (thd->mem_root) Item_func_interval(item);
+ }
| LEFT '(' expr ',' expr ')'
{ $$= new (YYTHD->mem_root) Item_func_left($3,$5); }
| MINUTE_SYM '(' expr ')'
@@ -6838,10 +6841,10 @@ function_call_nonkeyword:
$$= new (YYTHD->mem_root) Item_func_curtime_local($3);
Lex->safe_to_cache_query=0;
}
- | DATE_ADD_INTERVAL '(' expr ',' interval_expr interval ')'
- { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$5,$6,0); }
- | DATE_SUB_INTERVAL '(' expr ',' interval_expr interval ')'
- { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$5,$6,1); }
+ | DATE_ADD_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' %prec INTERVAL_SYM
+ { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$6,$7,0); }
+ | DATE_SUB_INTERVAL '(' expr ',' INTERVAL_SYM expr interval ')' %prec INTERVAL_SYM
+ { $$= new (YYTHD->mem_root) Item_date_add_interval($3,$6,$7,1); }
| EXTRACT_SYM '(' interval FROM expr ')'
{ $$=new (YYTHD->mem_root) Item_extract( $3, $5); }
| GET_FORMAT '(' date_time_type ',' expr ')'