From 0f91e6c97bb6544c51b31d52b765d7a3e77fee76 Mon Sep 17 00:00:00 2001
From: unknown <bell@sanja.is.com.ua>
Date: Tue, 10 Feb 2004 02:18:22 +0200
Subject: [PATCH] after merge & valgrind test fixes (BUG#2120)

sql/sql_derived.cc:
  memory leack fixed
sql/sql_lex.cc:
  flag to avoid double cleaning
sql/sql_lex.h:
  flag to avoid double cleaning
sql/sql_select.cc:
  right way to cleanup JOIN_TAB
sql/sql_select.h:
  right way to cleanup JOIN_TAB
sql/sql_union.cc:
  flag to avoid double cleaning
---
 sql/sql_derived.cc |  2 ++
 sql/sql_lex.cc     |  1 +
 sql/sql_lex.h      |  3 ++-
 sql/sql_select.cc  | 66 ++++++++++++++++++++++++++--------------------
 sql/sql_select.h   |  2 ++
 sql/sql_union.cc   |  6 +++++
 6 files changed, 50 insertions(+), 30 deletions(-)

diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 6e70fdd46d5..0e04316a2e7 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -204,6 +204,8 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
       table->file->info(HA_STATUS_VARIABLE);
     }
 
+    if (!lex->describe)
+      unit->cleanup();
     if (res)
       free_tmp_table(thd, table);
     else
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 62f255ea178..65357328927 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -988,6 +988,7 @@ void st_select_lex_unit::init_query()
   union_result= 0;
   table= 0;
   fake_select_lex= 0;
+  cleaned= 0;
 }
 
 void st_select_lex::init_query()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 3b1b3873706..3f56be18c4a 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -305,7 +305,8 @@ class st_select_lex_unit: public st_select_lex_node {
   ulong found_rows_for_union;
   bool  prepared, // prepare phase already performed for UNION (unit)
     optimized, // optimize phase already performed for UNION (unit)
-    executed; // already executed
+    executed, // already executed
+    cleaned;
 
 public:
   // list of fields which points to temporary table for union
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 082a06d97de..ea5050f2550 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1510,12 +1510,7 @@ JOIN::cleanup()
       JOIN_TAB *tab, *end;
       for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
       {
-	delete tab->select;
-	delete tab->quick;
-	tab->select=0;
-	tab->quick=0;
-	x_free(tab->cache.buff);
-	tab->cache.buff= 0;
+	tab->cleanup();
       }
     }
     tmp_join->tmp_join= 0;
@@ -3759,6 +3754,41 @@ bool error_if_full_join(JOIN *join)
 }
 
 
+/*
+  cleanup JOIN_TAB
+
+  SYNOPSIS
+    JOIN_TAB::cleanup()
+*/
+
+void JOIN_TAB::cleanup()
+{
+  delete select;
+  select= 0;
+  delete quick;
+  quick= 0;
+  x_free(cache.buff);
+  cache.buff= 0;
+  if (table)
+  {
+    if (table->key_read)
+    {
+      table->key_read= 0;
+      table->file->extra(HA_EXTRA_NO_KEYREAD);
+    }
+    /* Don't free index if we are using read_record */
+    if (!read_record.table)
+      table->file->index_end();
+    /*
+      We need to reset this for next select
+      (Tested in part_of_refkey)
+    */
+    table->reginfo.join_tab= 0;
+  }
+  end_read_record(&read_record);
+}
+
+
 /*
   Free resources of given join
 
@@ -3803,29 +3833,7 @@ JOIN::join_free(bool full)
     {
       for (tab= join_tab, end= tab+tables; tab != end; tab++)
       {
-	delete tab->select;
-	delete tab->quick;
-	tab->select=0;
-	tab->quick=0;
-	x_free(tab->cache.buff);
-	tab->cache.buff= 0;
-	if (tab->table)
-	{
-	  if (tab->table->key_read)
-	  {
-	    tab->table->key_read= 0;
-	    tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
-	  }
-	  /* Don't free index if we are using read_record */
-	  if (!tab->read_record.table)
-	    tab->table->file->index_end();
-	  /*
-	    We need to reset this for next select
-	    (Tested in part_of_refkey)
-	  */
-	  tab->table->reginfo.join_tab= 0;
-	}
-	end_read_record(&tab->read_record);
+	tab->cleanup();
       }
       table= 0;
     }
diff --git a/sql/sql_select.h b/sql/sql_select.h
index a463378006b..36526bee066 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -108,6 +108,8 @@ typedef struct st_join_table {
   TABLE_REF	ref;
   JOIN_CACHE	cache;
   JOIN		*join;
+
+  void cleanup();
 } JOIN_TAB;
 
 
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 226086d0d24..75fd9be88bd 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -442,6 +442,12 @@ int st_select_lex_unit::cleanup()
   int error= 0;
   DBUG_ENTER("st_select_lex_unit::cleanup");
 
+  if (cleaned)
+  {
+    DBUG_RETURN(0);
+  }
+  cleaned= 0;
+
   if (union_result)
   {
     delete union_result;
-- 
2.30.9