Commit 58cc5073 authored by unknown's avatar unknown

Fix for BUG#12943.

The problem was that in the first production in rule 'join_table', that
processes simple cross joins, the parser was processing the second join operand
before the first one due to unspecified priorities of JOINs. As a result in the
case of cross joins the parser constructed a tree with incorrect nesting:
the expression "t1 join t2 join t3 on some_cond" was interpreted as
"t1 join (t2 join t3 on some_cond)" instead of
"(t1 join t2) join t3 on some_cond".
Because of this incorrect nesting the method make_join_on_context picked an
incorrect table as the first table of the name resolution context.

The solution assignes correct priorities to the related production.


mysql-test/r/select.result:
  Added test for BUG#12943.
mysql-test/t/select.test:
  Added test for BUG#12943.
sql/sql_parse.cc:
  Fixed typo.
sql/sql_yacc.yy:
  Provide explicit priorities of the JOIN operator and the 'table_ref' rule,
  to enforce left-associativity of [INNER | CROSS] JOIN.
parent fc3ddc07
...@@ -2897,3 +2897,23 @@ select * from t1 natural join t2 where a = 'b'; ...@@ -2897,3 +2897,23 @@ select * from t1 natural join t2 where a = 'b';
a a
b b
drop table t1, t2; 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;
...@@ -2465,3 +2465,26 @@ insert into t2 values ('b'),('c'),('d'); ...@@ -2465,3 +2465,26 @@ insert into t2 values ('b'),('c'),('d');
select a from t1 natural join t2; select a from t1 natural join t2;
select * from t1 natural join t2 where a = 'b'; select * from t1 natural join t2 where a = 'b';
drop table t1, t2; 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;
...@@ -6354,7 +6354,7 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type) ...@@ -6354,7 +6354,7 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
SYNOPSIS SYNOPSIS
make_join_on_context() make_join_on_context()
thd pointer to current thread 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 right_op rigth operand of the JOIN
DESCRIPTION DESCRIPTION
......
...@@ -660,6 +660,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -660,6 +660,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token YEAR_SYM %token YEAR_SYM
%token ZEROFILL %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 SET_VAR
%left OR_OR_SYM OR_SYM OR2_SYM XOR %left OR_OR_SYM OR_SYM OR2_SYM XOR
%left AND_SYM AND_AND_SYM %left AND_SYM AND_AND_SYM
...@@ -5189,7 +5192,13 @@ derived_table_list: ...@@ -5189,7 +5192,13 @@ derived_table_list:
; ;
join_table: 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 | table_ref STRAIGHT_JOIN table_factor
{ YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; } { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; }
| table_ref normal_join table_ref | table_ref normal_join table_ref
......
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