From 4832ebce861836db812dd2863ee134e53c44963b Mon Sep 17 00:00:00 2001
From: unknown <bell@sanja.is.com.ua>
Date: Mon, 11 Nov 2002 10:49:41 +0200
Subject: [PATCH] prevent using expernal fields in derived tables

mysql-test/r/subselect.result:
  test of derived table external field bug
mysql-test/t/subselect.test:
  test of derived table external field bug
sql/sql_derived.cc:
  lex->current_select always should point on current SELECT_LEX_NODE during query execution
---
 mysql-test/r/subselect.result |  2 ++
 mysql-test/t/subselect.test   |  2 ++
 sql/item.cc                   | 29 ++++++++++++++++++++---------
 sql/sql_derived.cc            |  6 +++++-
 4 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 4eaacfe66f7..0d3617b7512 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -240,4 +240,6 @@ SELECT numeropost,maxnumrep FROM forumconthardwarefr7 WHERE exists (SELECT 1 FRO
 numeropost	maxnumrep
 43506	2
 40143	1
+SELECT (SELECT 1) as a FROM (SELECT 1 FROM forumconthardwarefr7 HAVING a=1);
+Unknown column 'a' in 'having clause'
 drop table forumconthardwarefr7, searchconthardwarefr7;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 12df155bc7f..93ad115155e 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -137,5 +137,7 @@ CREATE TABLE `searchconthardwarefr7` (
 INSERT INTO searchconthardwarefr7 (mot,topic,date,pseudo) VALUES ('joce','40143','2002-10-22','joce'), ('joce','43506','2002-10-22','joce');
 
 SELECT numeropost,maxnumrep FROM forumconthardwarefr7 WHERE exists (SELECT 1 FROM searchconthardwarefr7 WHERE (mot='joce') AND date >= '2002-10-21' AND forumconthardwarefr7.numeropost = searchconthardwarefr7.topic) ORDER BY maxnumrep DESC LIMIT 0, 20;
+-- error 1054
+SELECT (SELECT 1) as a FROM (SELECT 1 FROM forumconthardwarefr7 HAVING a=1);
 
 drop table forumconthardwarefr7, searchconthardwarefr7;
\ No newline at end of file
diff --git a/sql/item.cc b/sql/item.cc
index 9c70dad045c..ea797679957 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -444,13 +444,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
 	cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
       */
       SELECT_LEX *last= 0;
-      for (SELECT_LEX *sl= thd->lex.current_select->outer_select();
-	   sl;
-	   sl= sl->outer_select())
-	if ((tmp= find_field_in_tables(thd, this,
-				       (last= sl)->get_table_list(),
-				       0)) != not_found_field)
-	  break;
+      
+      // Prevent using outer fields in subselects, that is not supported now
+      if (thd->lex.current_select->linkage != DERIVED_TABLE_TYPE)
+	for (SELECT_LEX *sl= thd->lex.current_select->outer_select();
+	     sl;
+	     sl= sl->outer_select())
+	  if ((tmp= find_field_in_tables(thd, this,
+					 (last= sl)->get_table_list(),
+					 0)) != not_found_field)
+	    break;
       if (!tmp)
 	return -1;
       else if (tmp == not_found_field)
@@ -812,10 +815,18 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
   if (!ref)
   {
     SELECT_LEX *sl= thd->lex.current_select->outer_select();
+    /*
+      Finding only in current select will be performed for selects that have 
+      not outer one and for derived tables (which not support using outer 
+      fields for now)
+    */
     if ((ref= find_item_in_list(this, 
 				*(thd->lex.current_select->get_item_list()),
-				(sl ? REPORT_EXCEPT_NOT_FOUND :
-				 REPORT_ALL_ERRORS))) ==
+				((sl && 
+				  thd->lex.current_select->linkage !=
+				  DERIVED_TABLE_TYPE) ? 
+				  REPORT_EXCEPT_NOT_FOUND :
+				  REPORT_ALL_ERRORS))) ==
 	(Item **)not_found_item)
     {
       /*
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 93627409d27..5dbbf39e7d4 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -94,13 +94,17 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
 	unit->select_limit_cnt= HA_POS_ERROR;
       if (unit->select_limit_cnt == HA_POS_ERROR)
 	sl->options&= ~OPTION_FOUND_ROWS;
-    
+
+      SELECT_LEX_NODE *save_current_select= lex->current_select;
+      lex->current_select= sl;
       res= mysql_select(thd, tables,  sl->item_list,
 			sl->where, (ORDER *) sl->order_list.first,
 			(ORDER*) sl->group_list.first,
 			sl->having, (ORDER*) NULL,
 			sl->options | thd->options | SELECT_NO_UNLOCK,
 			derived_result, unit, sl, 0);
+      lex->current_select= save_current_select;
+
       if (!res)
       {
 // Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
-- 
2.30.9