summaryrefslogtreecommitdiff
path: root/sql/sql_select.cc
diff options
context:
space:
mode:
authorgkodinov/kgeorge@macbook.gmz <>2006-10-17 16:20:26 +0300
committergkodinov/kgeorge@macbook.gmz <>2006-10-17 16:20:26 +0300
commitf7b8937661e3c8ceb1e16a868c92585b2c66d01c (patch)
treee9d042b9e6f984142988ab80b1e498e226ff394a /sql/sql_select.cc
parent00a2f232c97c425672d2d71916244557075dc98e (diff)
downloadmariadb-git-f7b8937661e3c8ceb1e16a868c92585b2c66d01c.tar.gz
Bug#21798: memory leak during query execution with subquery in column
list using a function When executing dependent subqueries they are re-inited and re-exec() for each row of the outer context. The cause for the bug is that during subquery reinitialization/re-execution, the optimizer reallocates JOIN::join_tab, JOIN::table in make_simple_join() and the local variable in 'sortorder' in create_sort_index(), which is allocated by make_unireg_sortorder(). Care must be taken not to allocate anything into the thread's memory pool while re-initializing query plan structures between subquery re-executions. All such items mush be cached and reused because the thread's memory pool is freed at the end of the whole query. Note that they must be cached and reused even for queries that are not otherwise cacheable because otherwise it will grow the thread's memory pool every time a cacheable query is re-executed. We provide additional members to the JOIN structure to store references to the items that need to be cached.
Diffstat (limited to 'sql/sql_select.cc')
-rw-r--r--sql/sql_select.cc40
1 files changed, 32 insertions, 8 deletions
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4d2b3cac254..8f169a9d390 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1574,6 +1574,7 @@ JOIN::exec()
{
DBUG_VOID_RETURN;
}
+ sortorder= curr_join->sortorder;
}
thd->proc_info="Copying to group table";
@@ -1783,6 +1784,7 @@ JOIN::exec()
(select_options & OPTION_FOUND_ROWS ?
HA_POS_ERROR : unit->select_limit_cnt)))
DBUG_VOID_RETURN;
+ sortorder= curr_join->sortorder;
}
}
/* XXX: When can we have here thd->net.report_error not zero? */
@@ -4949,9 +4951,28 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
JOIN_TAB *join_tab;
DBUG_ENTER("make_simple_join");
- if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) ||
- !(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
- DBUG_RETURN(TRUE);
+ /*
+ Reuse TABLE * and JOIN_TAB if already allocated by a previous call
+ to this function through JOIN::exec (may happen for sub-queries).
+ */
+ if (!join->table_cache)
+ {
+ if (!(join->table_cache= (TABLE**) join->thd->alloc(sizeof(TABLE*))))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ if (join->tmp_join)
+ join->tmp_join->table_cache= join->table_cache;
+ }
+ if (!join->join_tab_cache)
+ {
+ if (!(join->join_tab_cache=
+ (JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ if (join->tmp_join)
+ join->tmp_join->join_tab_cache= join->join_tab_cache;
+ }
+ tableptr= join->table_cache;
+ join_tab= join->join_tab_cache;
+
join->join_tab=join_tab;
join->table=tableptr; tableptr[0]=tmp_table;
join->tables=1;
@@ -11971,7 +11992,6 @@ static int
create_sort_index(THD *thd, JOIN *join, ORDER *order,
ha_rows filesort_limit, ha_rows select_limit)
{
- SORT_FIELD *sortorder;
uint length;
ha_rows examined_rows;
TABLE *table;
@@ -11987,7 +12007,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
if (test_if_skip_sort_order(tab,order,select_limit,0))
DBUG_RETURN(0);
- if (!(sortorder=make_unireg_sortorder(order,&length)))
+ if (!(join->sortorder=
+ make_unireg_sortorder(order,&length,join->sortorder)))
goto err; /* purecov: inspected */
/* It's not fatal if the following alloc fails */
table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
@@ -12034,7 +12055,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
if (table->s->tmp_table)
table->file->info(HA_STATUS_VARIABLE); // Get record count
- table->sort.found_records=filesort(thd, table,sortorder, length,
+ table->sort.found_records=filesort(thd, table,join->sortorder, length,
select, filesort_limit, &examined_rows);
tab->records= table->sort.found_records; // For SQL_CALC_ROWS
if (select)
@@ -12381,7 +12402,8 @@ err:
}
-SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
+SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length,
+ SORT_FIELD *sortorder)
{
uint count;
SORT_FIELD *sort,*pos;
@@ -12390,7 +12412,9 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
count=0;
for (ORDER *tmp = order; tmp; tmp=tmp->next)
count++;
- pos=sort=(SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD)*(count+1));
+ if (!sortorder)
+ sortorder= (SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD)*(count+1));
+ pos=sort=sortorder;
if (!pos)
return 0;