Skip to content

Commit d765e30

Browse files
committed
Bug #55188: GROUP BY, GROUP_CONCAT and TEXT - inconsistent results
In order to be able to check if the set of the grouping fields in a GROUP BY has changed (and thus to start a new group) the optimizer caches the current values of these fields in a set of Cached_item derived objects. The Cached_item_str, used for caching varchar and TEXT columns, is limited in length by the max_sort_length variable. A String buffer to store the value with an alloced length of either the max length of the string or the value of max_sort_length (whichever is smaller) in Cached_item_str's constructor. Then, at compare time the value of the string to compare to was truncated to the alloced length of the string buffer inside Cached_item_str. This is all fine and valid, but only if you're not assigning values near or equal to the alloced length of this buffer. Because when assigning values like this the alloced length is rounded up and as a result the next set of data will not match the group buffer, thus leading to wrong results because of the changed alloced_length. Fixed by preserving the original maximum length in the Cached_item_str's constructor and using this instead of the alloced_length to limit the string to compare to. Test case added.
1 parent 93e81cc commit d765e30

4 files changed

Lines changed: 54 additions & 2 deletions

File tree

mysql-test/r/group_by.result

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,4 +1810,39 @@ MAX(t2.a)
18101810
2
18111811
DROP TABLE t1, t2;
18121812
#
1813+
# Bug#55188: GROUP BY, GROUP_CONCAT and TEXT - inconsistent results
1814+
#
1815+
CREATE TABLE t1 (a text, b varchar(10));
1816+
INSERT INTO t1 VALUES (repeat('1', 1300),'one'), (repeat('1', 1300),'two');
1817+
EXPLAIN
1818+
SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
1819+
id 1
1820+
select_type SIMPLE
1821+
table t1
1822+
type ALL
1823+
possible_keys NULL
1824+
key NULL
1825+
key_len NULL
1826+
ref NULL
1827+
rows 2
1828+
Extra Using filesort
1829+
SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
1830+
SUBSTRING(a,1,10) LENGTH(a) GROUP_CONCAT(b)
1831+
1111111111 1300 one,two
1832+
EXPLAIN
1833+
SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
1834+
id 1
1835+
select_type SIMPLE
1836+
table t1
1837+
type ALL
1838+
possible_keys NULL
1839+
key NULL
1840+
key_len NULL
1841+
ref NULL
1842+
rows 2
1843+
Extra Using temporary; Using filesort
1844+
SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
1845+
SUBSTRING(a,1,10) LENGTH(a)
1846+
1111111111 1300
1847+
DROP TABLE t1;
18131848
# End of 5.1 tests

mysql-test/t/group_by.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,5 +1221,19 @@ DROP TABLE t1, t2;
12211221

12221222

12231223
--echo #
1224+
--echo # Bug#55188: GROUP BY, GROUP_CONCAT and TEXT - inconsistent results
1225+
--echo #
1226+
1227+
CREATE TABLE t1 (a text, b varchar(10));
1228+
INSERT INTO t1 VALUES (repeat('1', 1300),'one'), (repeat('1', 1300),'two');
1229+
1230+
query_vertical EXPLAIN
1231+
SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
1232+
SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
1233+
query_vertical EXPLAIN
1234+
SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
1235+
SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
1236+
DROP TABLE t1;
1237+
12241238

12251239
--echo # End of 5.1 tests

sql/item.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,6 +2740,7 @@ class Cached_item :public Sql_alloc
27402740
class Cached_item_str :public Cached_item
27412741
{
27422742
Item *item;
2743+
uint32 value_max_length;
27432744
String value,tmp_value;
27442745
public:
27452746
Cached_item_str(THD *thd, Item *arg);

sql/item_buff.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ Cached_item::~Cached_item() {}
5858
*/
5959

6060
Cached_item_str::Cached_item_str(THD *thd, Item *arg)
61-
:item(arg), value(min(arg->max_length, thd->variables.max_sort_length))
61+
:item(arg),
62+
value_max_length(min(arg->max_length, thd->variables.max_sort_length)),
63+
value(value_max_length)
6264
{}
6365

6466
bool Cached_item_str::cmp(void)
@@ -67,7 +69,7 @@ bool Cached_item_str::cmp(void)
6769
bool tmp;
6870

6971
if ((res=item->val_str(&tmp_value)))
70-
res->length(min(res->length(), value.alloced_length()));
72+
res->length(min(res->length(), value_max_length));
7173
if (null_value != item->null_value)
7274
{
7375
if ((null_value= item->null_value))

0 commit comments

Comments
 (0)