summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2010-07-30 16:35:06 +0300
committerGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2010-07-30 16:35:06 +0300
commitde5029a4586176b9fed06ab96fb3a6e0bbcd8c54 (patch)
treec865d4e903d025224e801e5b65e4fd170156fa61
parent415fea54c5e6073ec5a40b465ba1d6eeb6032dd1 (diff)
downloadmariadb-git-de5029a4586176b9fed06ab96fb3a6e0bbcd8c54.tar.gz
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.
-rw-r--r--mysql-test/r/group_by.result35
-rw-r--r--mysql-test/t/group_by.test14
-rw-r--r--sql/item.h1
-rw-r--r--sql/item_buff.cc6
4 files changed, 54 insertions, 2 deletions
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index 645dd460735..f74584f6bcf 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -1810,4 +1810,39 @@ MAX(t2.a)
2
DROP TABLE t1, t2;
#
+# Bug#55188: GROUP BY, GROUP_CONCAT and TEXT - inconsistent results
+#
+CREATE TABLE t1 (a text, b varchar(10));
+INSERT INTO t1 VALUES (repeat('1', 1300),'one'), (repeat('1', 1300),'two');
+EXPLAIN
+SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
+id 1
+select_type SIMPLE
+table t1
+type ALL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows 2
+Extra Using filesort
+SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
+SUBSTRING(a,1,10) LENGTH(a) GROUP_CONCAT(b)
+1111111111 1300 one,two
+EXPLAIN
+SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
+id 1
+select_type SIMPLE
+table t1
+type ALL
+possible_keys NULL
+key NULL
+key_len NULL
+ref NULL
+rows 2
+Extra Using temporary; Using filesort
+SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
+SUBSTRING(a,1,10) LENGTH(a)
+1111111111 1300
+DROP TABLE t1;
# End of 5.1 tests
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index c5b27ee1a62..75ec1d82b02 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -1221,5 +1221,19 @@ DROP TABLE t1, t2;
--echo #
+--echo # Bug#55188: GROUP BY, GROUP_CONCAT and TEXT - inconsistent results
+--echo #
+
+CREATE TABLE t1 (a text, b varchar(10));
+INSERT INTO t1 VALUES (repeat('1', 1300),'one'), (repeat('1', 1300),'two');
+
+query_vertical EXPLAIN
+SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
+SELECT SUBSTRING(a,1,10), LENGTH(a), GROUP_CONCAT(b) FROM t1 GROUP BY a;
+query_vertical EXPLAIN
+SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
+SELECT SUBSTRING(a,1,10), LENGTH(a) FROM t1 GROUP BY a;
+DROP TABLE t1;
+
--echo # End of 5.1 tests
diff --git a/sql/item.h b/sql/item.h
index 174995b43e6..57abb43010e 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2740,6 +2740,7 @@ public:
class Cached_item_str :public Cached_item
{
Item *item;
+ uint32 value_max_length;
String value,tmp_value;
public:
Cached_item_str(THD *thd, Item *arg);
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 2f45d0a17c2..0ac4edb3656 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -58,7 +58,9 @@ Cached_item::~Cached_item() {}
*/
Cached_item_str::Cached_item_str(THD *thd, Item *arg)
- :item(arg), value(min(arg->max_length, thd->variables.max_sort_length))
+ :item(arg),
+ value_max_length(min(arg->max_length, thd->variables.max_sort_length)),
+ value(value_max_length)
{}
bool Cached_item_str::cmp(void)
@@ -67,7 +69,7 @@ bool Cached_item_str::cmp(void)
bool tmp;
if ((res=item->val_str(&tmp_value)))
- res->length(min(res->length(), value.alloced_length()));
+ res->length(min(res->length(), value_max_length));
if (null_value != item->null_value)
{
if ((null_value= item->null_value))