Commit ac151414 authored by Dmitry Shulga's avatar Dmitry Shulga

MDEV-32369: Memory leak when executing PS for query with IN subquery

The memory allocated for an instance of the class Item_direct_ref_to_item
was leaked on second execution of a query run as a prepared statement and
involving conversion of strings with different character sets.

The reason of leaking the memory was caused by the fact that a statement
arena could be already set by the moment the method
Type_std_attributes::agg_item_set_converter() is called.
parent 6f835378
#
# MDEV-32369: Memory leak when executing PS for query with IN subquery
#
CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MYISAM;
CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8) ENGINE=MYISAM;
INSERT INTO t1 VALUES ('b');
INSERT INTO t2 VALUES ('b');
PREPARE stmt FROM "SELECT t1.a FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2)";
EXECUTE stmt;
a
b
EXECUTE stmt;
a
b
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
# This file contains test cases that use the memory leaks detection feature
# provided by the cmake build option -DWITH_PROTECT_STATEMENT_MEMROOT
--source include/not_embedded.inc
# The cmake option -DWITH_PROTECT_STATEMENT_MEMROOT is used only
# for debug build
--source include/have_debug.inc
--echo #
--echo # MDEV-32369: Memory leak when executing PS for query with IN subquery
--echo #
CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MYISAM;
CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8) ENGINE=MYISAM;
INSERT INTO t1 VALUES ('b');
INSERT INTO t2 VALUES ('b');
PREPARE stmt FROM "SELECT t1.a FROM t1 WHERE t1.a IN (SELECT t2.b FROM t2)";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
......@@ -2584,18 +2584,21 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll,
if (conv->fix_fields_if_needed(thd, arg))
return TRUE;
if (!thd->stmt_arena->is_conventional())
{
Query_arena *arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup);
if (arena)
{
Item_direct_ref_to_item *ref=
new (thd->mem_root) Item_direct_ref_to_item(thd, *arg);
if ((ref == NULL) || ref->fix_fields(thd, (Item **)&ref))
{
if (arena)
thd->restore_active_arena(arena, &backup);
return TRUE;
}
*arg= ref;
if (arena)
thd->restore_active_arena(arena, &backup);
ref->change_item(thd, conv);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment