diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 0d5c1aed485..2b8ef07636f 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2897,3 +2897,23 @@ select * from t1 natural join t2 where a = 'b'; a b drop table t1, t2; +create table t1 (a int, c int); +create table t2 (b int); +create table t3 (b int, a int); +create table t4 (c int); +insert into t1 values (1,1); +insert into t2 values (1); +insert into t3 values (1,1); +insert into t4 values (1); +select * from t1 join t2 join t3 on (t2.b = t3.b and t1.a = t3.a); +a c b b a +1 1 1 1 1 +select * from t1, t2 join t3 on (t2.b = t3.b and t1.a = t3.a); +ERROR 42S22: Unknown column 't1.a' in 'on clause' +select * from t1 join t2 join t3 join t4 on (t1.a = t4.c and t2.b = t4.c); +a c b b a c +1 1 1 1 1 1 +select * from t1 join t2 join t4 using (c); +c a b +1 1 1 +drop table t1, t2, t3, t4; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index fad01ac9acf..37fbd7a296e 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2465,3 +2465,26 @@ insert into t2 values ('b'),('c'),('d'); select a from t1 natural join t2; select * from t1 natural join t2 where a = 'b'; drop table t1, t2; + +# +# Bug #12943 Incorrect nesting of [INNER| CROSS] JOIN due to unspecified +# associativity in the parser. +# + +create table t1 (a int, c int); +create table t2 (b int); +create table t3 (b int, a int); +create table t4 (c int); +insert into t1 values (1,1); +insert into t2 values (1); +insert into t3 values (1,1); +insert into t4 values (1); + +select * from t1 join t2 join t3 on (t2.b = t3.b and t1.a = t3.a); +# Notice that ',' has lower priority than 'join', thus we have that: +# t1, t2 join t3 <==> t1, (t2 join t3). +-- error 1054 +select * from t1, t2 join t3 on (t2.b = t3.b and t1.a = t3.a); +select * from t1 join t2 join t3 join t4 on (t1.a = t4.c and t2.b = t4.c); +select * from t1 join t2 join t4 using (c); +drop table t1, t2, t3, t4; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e3f9c0dc148..d7d3da8288b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6354,7 +6354,7 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) SYNOPSIS make_join_on_context() thd pointer to current thread - left_op lefto operand of the JOIN + left_op left operand of the JOIN right_op rigth operand of the JOIN DESCRIPTION diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a39ee7c82aa..520b6190410 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -660,6 +660,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token YEAR_SYM %token ZEROFILL +%left JOIN_SYM +/* A dummy token to force the priority of table_ref production in a join. */ +%left TABLE_REF_PRIORITY %left SET_VAR %left OR_OR_SYM OR_SYM OR2_SYM XOR %left AND_SYM AND_AND_SYM @@ -5189,7 +5192,13 @@ derived_table_list: ; join_table: - table_ref normal_join table_ref { YYERROR_UNLESS($1 && ($$=$3)); } + /* + Evaluate production 'table_ref' before 'normal_join' so that + [INNER | CROSS] JOIN is properly nested as other left-associative + joins. + */ + table_ref %prec TABLE_REF_PRIORITY normal_join table_ref + { YYERROR_UNLESS($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref