From d33b968f0304161bdd0c74764f71630862e33a9a Mon Sep 17 00:00:00 2001
From: unknown <timour@mysql.com>
Date: Wed, 17 Aug 2005 17:19:31 +0300
Subject: [PATCH] WL#2486 - natural and using join according to SQL:2003 -
 fixed a problem with RIGHT JOIN ON and enabled corresponding tests in
 select.test - fixed a memory leak

mysql-test/r/select.result:
  Fixed a problem with RIGHT JOIN ON queries, enabling the corresponding tests.
mysql-test/t/select.test:
  Fixed a problem with RIGHT JOIN ON queries, enabling the corresponding tests.
sql/sql_base.cc:
  Fixed a problem with RIGHT JOINs that have operand(s) which are NATURAL JOIN(s).
sql/table.h:
  Inherit from Sql_alloc for proper memory allocation.
  The change fixes a memory leak.
---
 mysql-test/r/select.result | 17 +++++++++++++++++
 mysql-test/t/select.test   |  6 ++----
 sql/sql_base.cc            | 27 +++++++++++++++++++++++----
 sql/table.h                |  2 +-
 4 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 580ccc44a7..1b35df534a 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -2218,6 +2218,23 @@ a
 1
 2
 3
+select * from (t1 as t2 left join t1 as t3 using (a)) right join t1 on t1.a>1;
+a	a
+NULL	1
+1	2
+2	2
+3	2
+1	3
+2	3
+3	3
+select * from t1 right join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+a	a
+2	1
+3	1
+2	2
+3	2
+2	3
+3	3
 select * from (t1 as t2 left join t1 as t3 using (a)) right outer join t1 using ( a );
 a
 1
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index e0c4d66633..390c4372f1 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -1850,10 +1850,8 @@ select * from t1 left join (t1 as t2 left join t1 as t3 using (a)) using ( a );
 select * from (t1 as t2 left join t1 as t3 using (a)) natural left join t1;
 select * from t1 natural left join (t1 as t2 left join t1 as t3 using (a));
 # right join on
-# TODO: WL#2486 - there is a problem in the order of tables in RIGHT JOIN
-#       check how we set next_name_resolution_table
-# select * from (t1 as t2 left join t1 as t3 using (a)) right join t1 on t1.a>1;
-# select * from t1 right join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
+select * from (t1 as t2 left join t1 as t3 using (a)) right join t1 on t1.a>1;
+select * from t1 right join (t1 as t2 left join t1 as t3 using (a)) on t1.a>1;
 # right [outer] joing using
 select * from (t1 as t2 left join t1 as t3 using (a)) right outer join t1 using ( a );
 select * from t1 right outer join (t1 as t2 left join t1 as t3 using (a)) using ( a );
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 4d4f9ae48d..98ce12eb7d 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3790,10 +3790,29 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref,
     {
       TABLE_LIST *cur_table_ref= cur_left_neighbor;
       cur_left_neighbor= nested_it++;
-     if (cur_table_ref->nested_join &&
-         store_top_level_join_columns(thd, cur_table_ref,
-                                      cur_left_neighbor, cur_right_neighbor))
-         DBUG_RETURN(TRUE);
+      /*
+        The order of RIGHT JOIN operands is reversed in 'join list' to
+        transform it into a LEFT JOIN. However, in this procedure we need
+        the join operands in their lexical order, so below we reverse the
+        join operands. Notice that this happens only in the first loop, and
+        not in the second one, as in the second loop cur_left_neighbor == NULL.
+        This is the correct behavior, because the second loop
+        sets cur_table_ref reference correctly after the join operands are
+        swapped in the first loop.
+      */
+      if (cur_left_neighbor &&
+          cur_table_ref->outer_join & JOIN_TYPE_RIGHT)
+      {
+        DBUG_ASSERT(cur_table_ref);
+        /* This can happen only for JOIN ... ON. */
+        DBUG_ASSERT(table_ref->nested_join->join_list.elements == 2);
+        swap_variables(TABLE_LIST*, cur_left_neighbor, cur_table_ref);
+      }
+
+      if (cur_table_ref->nested_join &&
+          store_top_level_join_columns(thd, cur_table_ref,
+                                       cur_left_neighbor, cur_right_neighbor))
+        DBUG_RETURN(TRUE);
      cur_right_neighbor= cur_table_ref;
     }
   }
diff --git a/sql/table.h b/sql/table.h
index bb9de5dc86..3d4f02e389 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -374,7 +374,7 @@ struct Field_translator
   Field (for tables), or a Field_translator (for views).
 */
 
-class Natural_join_column
+class Natural_join_column: public Sql_alloc
 {
 public:
   Field_translator *view_field;  /* Column reference of merge view. */
-- 
2.30.9