diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index ef53f227ec0..e10bcba36c2 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -527,3 +527,23 @@ SELECT * FROM t1 WHERE a = INTERVAL(3,2,1) + 1; a b 3 1998-01-01 00:00:00 DROP TABLE t1; +DROP TABLE IF EXISTS t1,t2,t3; +CREATE TABLE t1 (a1 INT, a2 INT, a3 INT, a4 DATETIME); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; +SELECT t1.* FROM t1 AS t0, { OJ t2 INNER JOIN t1 ON (t1.a1=t2.a1) } WHERE t0.a3=2; +a1 a2 a3 a4 +SELECT t1.*,t2.* FROM { OJ ((t1 INNER JOIN t2 ON (t1.a1=t2.a2)) LEFT OUTER JOIN t3 ON t3.a3=t2.a1)}; +a1 a2 a3 a4 a1 a2 a3 a4 +SELECT t1.*,t2.* FROM { OJ ((t1 LEFT OUTER JOIN t2 ON t1.a3=t2.a2) INNER JOIN t3 ON (t3.a1=t2.a2))}; +a1 a2 a3 a4 a1 a2 a3 a4 +SELECT t1.*,t2.* FROM { OJ (t1 LEFT OUTER JOIN t2 ON t1.a1=t2.a2) CROSS JOIN t3 ON (t3.a2=t2.a3)}; +a1 a2 a3 a4 a1 a2 a3 a4 +SELECT * FROM {oj t1 LEFT OUTER JOIN t2 ON t1.a1=t2.a3} WHERE t1.a2 > 10; +a1 a2 a3 a4 a1 a2 a3 a4 +SELECT {fn CONCAT(a1,a2)} FROM t1; +{fn CONCAT(a1,a2)} +UPDATE t3 SET a4={d '1789-07-14'} WHERE a1=0; +SELECT a1, a4 FROM t2 WHERE a4 LIKE {fn UCASE('1789-07-14')}; +a1 a4 +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/parser.test b/mysql-test/t/parser.test index 9170308a4f2..800d717cf6b 100644 --- a/mysql-test/t/parser.test +++ b/mysql-test/t/parser.test @@ -657,3 +657,23 @@ 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; + +# +# Bug#28317 Left Outer Join with {oj outer-join} +# + +--disable_warnings +DROP TABLE IF EXISTS t1,t2,t3; +--enable_warnings +CREATE TABLE t1 (a1 INT, a2 INT, a3 INT, a4 DATETIME); +CREATE TABLE t2 LIKE t1; +CREATE TABLE t3 LIKE t1; +SELECT t1.* FROM t1 AS t0, { OJ t2 INNER JOIN t1 ON (t1.a1=t2.a1) } WHERE t0.a3=2; +SELECT t1.*,t2.* FROM { OJ ((t1 INNER JOIN t2 ON (t1.a1=t2.a2)) LEFT OUTER JOIN t3 ON t3.a3=t2.a1)}; +SELECT t1.*,t2.* FROM { OJ ((t1 LEFT OUTER JOIN t2 ON t1.a3=t2.a2) INNER JOIN t3 ON (t3.a1=t2.a2))}; +SELECT t1.*,t2.* FROM { OJ (t1 LEFT OUTER JOIN t2 ON t1.a1=t2.a2) CROSS JOIN t3 ON (t3.a2=t2.a3)}; +SELECT * FROM {oj t1 LEFT OUTER JOIN t2 ON t1.a1=t2.a3} WHERE t1.a2 > 10; +SELECT {fn CONCAT(a1,a2)} FROM t1; +UPDATE t3 SET a4={d '1789-07-14'} WHERE a1=0; +SELECT a1, a4 FROM t2 WHERE a4 LIKE {fn UCASE('1789-07-14')}; +DROP TABLE t1, t2, t3; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b4d8bb2dfb8..72800c7485a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -508,10 +508,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %pure_parser /* We have threads */ /* - Currently there are 177 shift/reduce conflicts. + Currently there are 169 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 177 +%expect 169 /* Comments for TOKENS. @@ -1193,7 +1193,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type join_table_list join_table - table_factor table_ref + table_factor table_ref esc_table_ref select_derived derived_table_list %type date_time_type; @@ -7444,10 +7444,22 @@ join_table_list: derived_table_list { MYSQL_YYABORT_UNLESS($$=$1); } ; +/* + The ODBC escape syntax for Outer Join is: '{' OJ join_table '}' + The parser does not define OJ as a token, any ident is accepted + instead in $2 (ident). Also, all productions from table_ref can + be escaped, not only join_table. Both syntax extensions are safe + and are ignored. +*/ +esc_table_ref: + table_ref { $$=$1; } + | '{' ident table_ref '}' { $$=$3; } + ; + /* Warning - may return NULL in case of incomplete SELECT */ derived_table_list: - table_ref { $$=$1; } - | derived_table_list ',' table_ref + esc_table_ref { $$=$1; } + | derived_table_list ',' esc_table_ref { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); } @@ -7612,25 +7624,6 @@ table_factor: MYSQL_YYABORT; Select->add_joined_table($$); } - | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref - ON - { - /* Change the current name resolution context to a local context. */ - if (push_new_name_resolution_context(YYTHD, $3, $7)) - MYSQL_YYABORT; - - } - expr '}' - { - LEX *lex= Lex; - MYSQL_YYABORT_UNLESS($3 && $7); - add_join_on($7,$10); - Lex->pop_context(); - $7->outer_join|=JOIN_TYPE_LEFT; - $$=$7; - if (!($$= lex->current_select->nest_last_join(lex->thd))) - MYSQL_YYABORT; - } | select_derived_init get_select_lex select_derived2 { LEX *lex= Lex;