Skip to content

Commit

Permalink
MDEV-6743 crash in GROUP_CONCAT(IF () ORDER BY 1)
Browse files Browse the repository at this point in the history
mysql-test/r/func_group.result:
  Test case
mysql-test/t/func_group.test:
  Test case
sql/item_sum.cc:
  Restore ORDER for prepared statements
  • Loading branch information
montywi committed Sep 23, 2014
1 parent e41bca0 commit bab638d
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 10 deletions.
33 changes: 32 additions & 1 deletion mysql-test/r/func_group.result
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
drop table if exists t1,t2;
drop table if exists t1,t2,t3,t4,t5,t6;
set @sav_dpi= @@div_precision_increment;
set div_precision_increment= 5;
show variables like 'div_precision_increment';
Expand Down Expand Up @@ -2239,3 +2239,34 @@ explain select MIN(b) from t1 where b >= inet_aton('192.168.119.32');
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
DROP TABLE t1;
#
# MDEV-6743 crash in GROUP_CONCAT(IF () ORDER BY 1)
#
CREATE TABLE t1 (pk INT, t2_id INT, t5_id INT, PRIMARY KEY (pk));
INSERT INTO t1 VALUES (1,3,12),(2,3,15);
CREATE TABLE t2 (pk INT, PRIMARY KEY (pk));
INSERT INTO t2 VALUES (4),(5);
CREATE TABLE t3 (t2_id INT, t4_id INT);
INSERT INTO t3 VALUES (6,11),(7,12);
CREATE TABLE t4 (id INT);
INSERT INTO t4 VALUES (13),(14);
CREATE TABLE t5 (pk INT, f VARCHAR(50), t6_id INT, PRIMARY KEY (pk));
INSERT INTO t5 VALUES (9,'FOO',NULL);
CREATE TABLE t6 (pk INT, f VARCHAR(120), b TINYINT(4), PRIMARY KEY (pk));
PREPARE stmt FROM "
SELECT t1.t2_id, GROUP_CONCAT(IF (t6.b, t6.f, t5.f) ORDER BY 1)
FROM t1
JOIN t2 ON t1.t2_id = t2.pk
JOIN t3 ON t2.pk = t3.t2_id
JOIN t4 ON t4.id = t3.t4_id
JOIN t5 ON t1.t5_id = t5.pk
LEFT JOIN t6 ON t6.pk = t5.t6_id
GROUP BY t1.t2_id
";
EXECUTE stmt;
t2_id GROUP_CONCAT(IF (t6.b, t6.f, t5.f) ORDER BY 1)
EXECUTE stmt;
t2_id GROUP_CONCAT(IF (t6.b, t6.f, t5.f) ORDER BY 1)
EXECUTE stmt;
t2_id GROUP_CONCAT(IF (t6.b, t6.f, t5.f) ORDER BY 1)
DROP TABLE t1,t2,t3,t4,t5,t6;
39 changes: 38 additions & 1 deletion mysql-test/t/func_group.test
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#

--disable_warnings
drop table if exists t1,t2;
drop table if exists t1,t2,t3,t4,t5,t6;
--enable_warnings

set @sav_dpi= @@div_precision_increment;
Expand Down Expand Up @@ -1528,3 +1528,40 @@ insert into t1 (b) values (INET_ATON('192.168.200.200'));
explain select MIN(b) from t1 where b >= inet_aton('192.168.119.32');
DROP TABLE t1;

--echo #
--echo # MDEV-6743 crash in GROUP_CONCAT(IF () ORDER BY 1)
--echo #

CREATE TABLE t1 (pk INT, t2_id INT, t5_id INT, PRIMARY KEY (pk));
INSERT INTO t1 VALUES (1,3,12),(2,3,15);

CREATE TABLE t2 (pk INT, PRIMARY KEY (pk));
INSERT INTO t2 VALUES (4),(5);

CREATE TABLE t3 (t2_id INT, t4_id INT);
INSERT INTO t3 VALUES (6,11),(7,12);

CREATE TABLE t4 (id INT);
INSERT INTO t4 VALUES (13),(14);

CREATE TABLE t5 (pk INT, f VARCHAR(50), t6_id INT, PRIMARY KEY (pk));
INSERT INTO t5 VALUES (9,'FOO',NULL);

CREATE TABLE t6 (pk INT, f VARCHAR(120), b TINYINT(4), PRIMARY KEY (pk));

PREPARE stmt FROM "
SELECT t1.t2_id, GROUP_CONCAT(IF (t6.b, t6.f, t5.f) ORDER BY 1)
FROM t1
JOIN t2 ON t1.t2_id = t2.pk
JOIN t3 ON t2.pk = t3.t2_id
JOIN t4 ON t4.id = t3.t4_id
JOIN t5 ON t1.t5_id = t5.pk
LEFT JOIN t6 ON t6.pk = t5.t6_id
GROUP BY t1.t2_id
";

EXECUTE stmt;
EXECUTE stmt;
EXECUTE stmt;

DROP TABLE t1,t2,t3,t4,t5,t6;
26 changes: 18 additions & 8 deletions sql/item_sum.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3181,19 +3181,13 @@ Item_func_group_concat(Name_resolution_context *context_arg,
/*
We need to allocate:
args - arg_count_field+arg_count_order
(for possible order items in temporare tables)
(for possible order items in temporary tables)
order - arg_count_order
*/
if (!(args= (Item**) sql_alloc(sizeof(Item*) * arg_count +
if (!(args= (Item**) sql_alloc(sizeof(Item*) * arg_count * 2 +
sizeof(ORDER*)*arg_count_order)))
return;

if (!(orig_args= (Item **) sql_alloc(sizeof(Item *) * arg_count)))
{
args= NULL;
return;
}

order= (ORDER**)(args + arg_count);

/* fill args items of show and sort */
Expand All @@ -3214,6 +3208,9 @@ Item_func_group_concat(Name_resolution_context *context_arg,
order_item->item= arg_ptr++;
}
}

/* orig_args is only used for print() */
orig_args= (Item**) (order + arg_count_order);
memcpy(orig_args, args, sizeof(Item*) * arg_count);
}

Expand Down Expand Up @@ -3297,6 +3294,19 @@ void Item_func_group_concat::cleanup()
}
DBUG_ASSERT(tree == 0);
}

/*
For prepared statements we have to restore pointers for ORDER BY as
they may point to areas that are freed at cleanup().
*/
if (!current_thd->stmt_arena->is_conventional() && arg_count_order)
{
memcpy(args + arg_count_field, orig_args + arg_count_field,
sizeof(Item*) * arg_count_order);

for (uint i= 0 ; i < arg_count_order ; i++)
order[i]->item = args + arg_count_field + i;
}
DBUG_VOID_RETURN;
}

Expand Down

0 comments on commit bab638d

Please sign in to comment.