From 763af1a8a3a894df7326303b062bc55121103cb0 Mon Sep 17 00:00:00 2001
From: Sergey Petrunya <psergey@askmonty.org>
Date: Mon, 1 Apr 2013 18:03:14 +0400
Subject: [PATCH] MDEV-4240: mariadb 5.3.12 using more memory than MySQL 5.1
 for an inefficient query - Let index_merge allocate table handlers on quick
 select's MEM_ROOT,   not on statement's MEM_ROOT.   This is crucial for big
 "range checked for each record" queries, where   index_merge can be created
 and deleted many times during query exection.   We should not make O(#rows)
 allocations on statement's MEM_ROOT.

---
 sql/opt_range.cc | 15 ++++++++-------
 sql/opt_range.h  |  6 +++---
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index df1d691ca58..2cab05b26ab 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1970,7 +1970,7 @@ int QUICK_ROR_INTERSECT_SELECT::init()
     1  error
 */
 
-int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
+int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc)
 {
   handler *save_file= file, *org_file;
   my_bool org_key_read;
@@ -1997,7 +1997,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
   }
 
   thd= head->in_use;
-  if (!(file= head->file->clone(head->s->normalized_path.str, thd->mem_root)))
+  if (!(file= head->file->clone(head->s->normalized_path.str, alloc)))
   {
     /* 
       Manually set the error flag. Note: there seems to be quite a few
@@ -2084,7 +2084,8 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
     0     OK
     other error code
 */
-int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
+int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler, 
+                                                     MEM_ROOT *alloc)
 {
   List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects);
   QUICK_SELECT_WITH_RECORD *cur;
@@ -2101,14 +2102,14 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
       There is no use of this->file. Use it for the first of merged range
       selects.
     */
-    if (quick->init_ror_merged_scan(TRUE))
+    if (quick->init_ror_merged_scan(TRUE, alloc))
       DBUG_RETURN(1);
     quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
   }
   while ((cur= quick_it++))
   {
     quick= cur->quick;
-    if (quick->init_ror_merged_scan(FALSE))
+    if (quick->init_ror_merged_scan(FALSE, alloc))
       DBUG_RETURN(1);
     quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
     /* All merged scans share the same record buffer in intersection. */
@@ -2136,7 +2137,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
 int QUICK_ROR_INTERSECT_SELECT::reset()
 {
   DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::reset");
-  if (!scans_inited && init_ror_merged_scan(TRUE))
+  if (!scans_inited && init_ror_merged_scan(TRUE, &alloc))
     DBUG_RETURN(1);
   scans_inited= TRUE;
   List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
@@ -2268,7 +2269,7 @@ int QUICK_ROR_UNION_SELECT::reset()
     List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
     while ((quick= it++))
     {
-      if (quick->init_ror_merged_scan(FALSE))
+      if (quick->init_ror_merged_scan(FALSE, &alloc))
         DBUG_RETURN(1);
     }
     scans_inited= TRUE;
diff --git a/sql/opt_range.h b/sql/opt_range.h
index d4b92015042..17bb6d16da8 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -310,7 +310,7 @@ class QUICK_SELECT_I
       0     Ok
       other Error
   */
-  virtual int init_ror_merged_scan(bool reuse_handler)
+  virtual int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc)
   { DBUG_ASSERT(0); return 1; }
 
   /*
@@ -448,7 +448,7 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I
                       uchar *cur_prefix);
   bool reverse_sorted() { return 0; }
   bool unique_key_range();
-  int init_ror_merged_scan(bool reuse_handler);
+  int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc);
   void save_last_pos()
   { file->position(record); }
   int get_type() { return QS_TYPE_RANGE; }
@@ -681,7 +681,7 @@ class QUICK_ROR_INTERSECT_SELECT : public QUICK_SELECT_I
 #ifndef DBUG_OFF
   void dbug_dump(int indent, bool verbose);
 #endif
-  int init_ror_merged_scan(bool reuse_handler);
+  int init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc);
   bool push_quick_back(MEM_ROOT *alloc, QUICK_RANGE_SELECT *quick_sel_range);
 
   class QUICK_SELECT_WITH_RECORD : public Sql_alloc
-- 
2.30.9