Below is the list of changes that have just been committed into a local
5.0 repository of kgeorge. When kgeorge does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-09-14 11:20:41+03:00, gkodinov@stripped +8 -0
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.
Care must be taken not to allocate anything into the thread's memory pool
while reiniting that.
All such items mush be cached and reused because the thread's memory pool
is freed at the end of the whole query.
Most of the stuff that is allocated in JOIN::exec is taken care of (e.g.
JOIN::exec_tmp_table2), but there are some that remain.
Note that they must be cached and reused even for queries that are not
otherwise cacheable.
So we provide a structure (initialized and maintained as an unit) to
store references to the items that need to be cached.
mysql-test/r/subselect.result@stripped, 2006-09-14 11:20:24+03:00, gkodinov@stripped +26
-0
Bug#21798: memory leak during query execution with subquery in column
list using a function
- test case
mysql-test/t/subselect.test@stripped, 2006-09-14 11:20:26+03:00, gkodinov@stripped +26
-0
Bug#21798: memory leak during query execution with subquery in column
list using a function
- test case
sql/mysql_priv.h@stripped, 2006-09-14 11:20:27+03:00, gkodinov@stripped +2 -1
Bug#21798: memory leak during query execution with subquery in column
list using a function
- need to cache the entities allocated in the threads memory pool by
JOIN::exec ().
sql/sql_delete.cc@stripped, 2006-09-14 11:20:28+03:00, gkodinov@stripped +1 -1
Bug#21798: memory leak during query execution with subquery in column
list using a function
- need to cache the entities allocated in the threads memory pool by
JOIN::exec ().
sql/sql_select.cc@stripped, 2006-09-14 11:20:30+03:00, gkodinov@stripped +36 -9
Bug#21798: memory leak during query execution with subquery in column
list using a function
- need to cache the entities allocated in the threads memory pool by
JOIN::exec ().
It is better to collect all such items in unified storage for cacheable
items inside JOIN.
sql/sql_select.h@stripped, 2006-09-14 11:20:31+03:00, gkodinov@stripped +13 -0
Bug#21798: memory leak during query execution with subquery in column
list using a function
- need to cache the entities allocated in the threads memory pool by
JOIN::exec ().
It is better to collect all such items in unified storage for cacheable
items inside JOIN.
sql/sql_table.cc@stripped, 2006-09-14 11:20:32+03:00, gkodinov@stripped +1 -1
Bug#21798: memory leak during query execution with subquery in column
list using a function
- need to cache the entities allocated in the threads memory pool by
JOIN::exec ().
sql/sql_update.cc@stripped, 2006-09-14 11:20:33+03:00, gkodinov@stripped +1 -1
Bug#21798: memory leak during query execution with subquery in column
list using a function
- need to cache the entities allocated in the threads memory pool by
JOIN::exec ().
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: gkodinov
# Host: macbook.gmz
# Root: /Users/kgeorge/mysql/work/B21798-5.0-opt
--- 1.407/sql/mysql_priv.h 2006-09-14 11:21:02 +03:00
+++ 1.408/sql/mysql_priv.h 2006-09-14 11:21:02 +03:00
@@ -708,7 +708,8 @@ bool mysql_xa_recover(THD *thd);
bool check_simple_select();
-SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
+SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length,
+ SORT_FIELD *cache, uint cached_len);
int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List <Item> &all_fields, ORDER *order);
int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
--- 1.178/sql/sql_delete.cc 2006-09-14 11:21:02 +03:00
+++ 1.179/sql/sql_delete.cc 2006-09-14 11:21:02 +03:00
@@ -167,7 +167,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
MYF(MY_FAE | MY_ZEROFILL));
if (!(sortorder= make_unireg_sortorder((ORDER*) order->first,
- &length)) ||
+ &length, NULL, 0)) ||
(table->sort.found_records = filesort(thd, table, sortorder, length,
select, HA_POS_ERROR,
&examined_rows))
--- 1.450/sql/sql_select.cc 2006-09-14 11:21:03 +03:00
+++ 1.451/sql/sql_select.cc 2006-09-14 11:21:03 +03:00
@@ -76,7 +76,9 @@ static store_key *get_store_key(THD *thd
KEYUSE *keyuse, table_map used_tables,
KEY_PART_INFO *key_part, char *key_buff,
uint maybe_null);
-static bool make_simple_join(JOIN *join,TABLE *tmp_table);
+static bool make_simple_join(JOIN *join,TABLE *tmp_table,
+ TABLE ***simplejoin_tableptr_cache,
+ JOIN_TAB **simplejoin_tab_cache);
static void make_outerjoin_info(JOIN *join);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void make_join_readinfo(JOIN *join,uint options);
@@ -1273,7 +1275,10 @@ JOIN::reinit()
memcpy(join_tab, join_tab_save, sizeof(JOIN_TAB) * tables);
if (tmp_join)
+ {
+ memcpy(&subq_cache, &tmp_join->subq_cache, sizeof (subq_cache));
restore_tmp();
+ }
/* Reset of sum functions */
if (sum_funcs)
@@ -1435,6 +1440,7 @@ JOIN::exec()
(curr_join may have been modified during last exection and we need
to reset it)
*/
+ tmp_join->subq_cache= curr_join->subq_cache;
curr_join= tmp_join;
}
curr_tmp_table= exec_tmp_table1;
@@ -1523,7 +1529,9 @@ JOIN::exec()
/* Free first data from old join */
curr_join->join_free();
- if (make_simple_join(curr_join, curr_tmp_table))
+ if (make_simple_join(curr_join, curr_tmp_table,
+ &curr_join->subq_cache.simplejoin_table_ptr_cache1,
+ &curr_join->subq_cache.simplejoin_tab_cache1))
DBUG_VOID_RETURN;
calc_group_buffer(curr_join, group_list);
count_field_types(&curr_join->tmp_table_param,
@@ -1642,7 +1650,9 @@ JOIN::exec()
curr_join->select_distinct=0;
}
curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
- if (make_simple_join(curr_join, curr_tmp_table))
+ if (make_simple_join(curr_join, curr_tmp_table,
+ &curr_join->subq_cache.simplejoin_table_ptr_cache2,
+ &curr_join->subq_cache.simplejoin_tab_cache2))
DBUG_VOID_RETURN;
calc_group_buffer(curr_join, curr_join->group_list);
count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
@@ -4943,15 +4953,25 @@ store_val_in_field(Field *field, Item *i
static bool
-make_simple_join(JOIN *join,TABLE *tmp_table)
+make_simple_join(JOIN *join,TABLE *tmp_table,
+ TABLE ***simplejoin_tableptr_cache,
+ JOIN_TAB **simplejoin_tab_cache)
{
TABLE **tableptr;
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))))
+ if (*simplejoin_tableptr_cache)
+ tableptr= *simplejoin_tableptr_cache;
+ else if (!(*simplejoin_tableptr_cache=
+ tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))))
DBUG_RETURN(TRUE);
+ if (*simplejoin_tab_cache)
+ join_tab= *simplejoin_tab_cache;
+ else if (!(*simplejoin_tab_cache=
+ join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
+ DBUG_RETURN(TRUE);
+
join->join_tab=join_tab;
join->table=tableptr; tableptr[0]=tmp_table;
join->tables=1;
@@ -11987,8 +12007,12 @@ create_sort_index(THD *thd, JOIN *join,
if (test_if_skip_sort_order(tab,order,select_limit,0))
DBUG_RETURN(0);
- if (!(sortorder=make_unireg_sortorder(order,&length)))
+ if (!(join->subq_cache.sortorder_cache=
+ sortorder= make_unireg_sortorder(order,&length,
+ join->subq_cache.sortorder_cache,
+ join->subq_cache.sortorder_cache_len)))
goto err; /* purecov: inspected */
+ join->subq_cache.sortorder_cache_len= length;
/* It's not fatal if the following alloc fails */
table->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
MYF(MY_WME | MY_ZEROFILL));
@@ -12381,7 +12405,8 @@ err:
}
-SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length)
+SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length,
+ SORT_FIELD *cache, uint cached_len)
{
uint count;
SORT_FIELD *sort,*pos;
@@ -12390,7 +12415,9 @@ SORT_FIELD *make_unireg_sortorder(ORDER
count=0;
for (ORDER *tmp = order; tmp; tmp=tmp->next)
count++;
- pos=sort=(SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD)*(count+1));
+ if (!cache || cached_len != count)
+ cache= (SORT_FIELD*) sql_alloc(sizeof(SORT_FIELD)*(count+1));
+ pos= sort= cache;
if (!pos)
return 0;
--- 1.109/sql/sql_select.h 2006-09-14 11:21:03 +03:00
+++ 1.110/sql/sql_select.h 2006-09-14 11:21:03 +03:00
@@ -282,6 +282,18 @@ public:
bool union_part; // this subselect is part of union
bool optimized; // flag to avoid double optimization in EXPLAIN
+ /*
+ cache for the the transformed JOIN elements used by make_simple_join
+ We need to preserve these elements even if the join itself is not
+ cacheable
+ */
+ struct {
+ TABLE **simplejoin_table_ptr_cache1, **simplejoin_table_ptr_cache2;
+ JOIN_TAB *simplejoin_tab_cache1, *simplejoin_tab_cache2;
+ SORT_FIELD *sortorder_cache;
+ uint sortorder_cache_len;
+ } subq_cache;
+
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg)
:fields_list(fields_arg)
@@ -307,6 +319,7 @@ public:
examined_rows= 0;
exec_tmp_table1= 0;
exec_tmp_table2= 0;
+ bzero (&subq_cache, sizeof (subq_cache));
thd= thd_arg;
sum_funcs= sum_funcs2= 0;
procedure= 0;
--- 1.320/sql/sql_table.cc 2006-09-14 11:21:03 +03:00
+++ 1.321/sql/sql_table.cc 2006-09-14 11:21:03 +03:00
@@ -4044,7 +4044,7 @@ copy_data_between_tables(TABLE *from,TAB
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
- !(sortorder=make_unireg_sortorder(order, &length)) ||
+ !(sortorder=make_unireg_sortorder(order, &length, NULL, 0)) ||
(from->sort.found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
&examined_rows)) ==
--- 1.196/sql/sql_update.cc 2006-09-14 11:21:03 +03:00
+++ 1.197/sql/sql_update.cc 2006-09-14 11:21:03 +03:00
@@ -311,7 +311,7 @@ int mysql_update(THD *thd,
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
- if (!(sortorder=make_unireg_sortorder(order, &length)) ||
+ if (!(sortorder=make_unireg_sortorder(order, &length, NULL, 0)) ||
(table->sort.found_records = filesort(thd, table, sortorder, length,
select, limit,
&examined_rows))
--- 1.156/mysql-test/r/subselect.result 2006-09-14 11:21:03 +03:00
+++ 1.157/mysql-test/r/subselect.result 2006-09-14 11:21:03 +03:00
@@ -3393,3 +3393,29 @@ id select_type table type possible_keys
4 UNION t12 system NULL NULL NULL NULL 0 const row not found
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(250), b INT auto_increment, PRIMARY KEY (b));
+insert into t1 (a) values (FLOOR(rand() * 100));
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+SELECT a,
+(SELECT REPEAT(' ',250) FROM t1 i1
+WHERE i1.b=t1.a ORDER BY RAND() LIMIT 1) AS a
+FROM t1 ORDER BY a LIMIT 5;
+a a
+0 NULL
+0 NULL
+0 NULL
+0 NULL
+0 NULL
+DROP TABLE t1;
--- 1.126/mysql-test/t/subselect.test 2006-09-14 11:21:03 +03:00
+++ 1.127/mysql-test/t/subselect.test 2006-09-14 11:21:03 +03:00
@@ -2306,3 +2306,29 @@ explain select * from t1 where not exist
((select t11.i from t1 t11) union (select t12.i from t1 t12));
DROP TABLE t1;
+
+#
+# Bug#21798: memory leak during query execution with subquery in column
+# list using a function
+#
+CREATE TABLE t1 (a VARCHAR(250), b INT auto_increment, PRIMARY KEY (b));
+insert into t1 (a) values (FLOOR(rand() * 100));
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+insert into t1 (a) select FLOOR(rand() * 100) from t1;
+
+SELECT a,
+ (SELECT REPEAT(' ',250) FROM t1 i1
+ WHERE i1.b=t1.a ORDER BY RAND() LIMIT 1) AS a
+FROM t1 ORDER BY a LIMIT 5;
+DROP TABLE t1;
| Thread |
|---|
| • bk commit into 5.0 tree (gkodinov:1.2261) BUG#21798 | kgeorge | 14 Sep |