Skip to content

Commit ade0f40

Browse files
author
Varun Gupta
committed
MDEV-22819: Wrong result or Assertion `ix > 0' failed in read_to_buffer upon select with GROUP BY and GROUP_CONCAT
In the merge_buffers phase for sorting, the sort buffer size is divided between the number of chunks. The chunks have a start and end position (m_buffer_start and m_buffer_end). Then we read the as many records that fit in this buffer for a chunk of the file. The issue here was we were resetting the end of buffer(m_buffer_end) to the number of bytes that was read, this was causing a problem because with dynamic size of sort keys it is possible that later we would not be able to accommodate even one key inside a chunk of file. So the fix was to not reset the end of buffer for a chunk of file.
1 parent ba2c2cf commit ade0f40

File tree

4 files changed

+106
-6
lines changed

4 files changed

+106
-6
lines changed

mysql-test/main/order_by.result

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3965,4 +3965,62 @@ a
39653965
1
39663966
0
39673967
DROP TABLE t1;
3968+
#
3969+
# MDEV-22819:Wrong result or Assertion `ix > 0' failed in read_to_buffer upon select
3970+
# with GROUP BY and GROUP_CONCAT
3971+
#
3972+
CREATE TABLE t1 (a VARCHAR(1000), b CHAR(1));
3973+
INSERT INTO t1 VALUES
3974+
(REPEAT('a',1000),'a'),(REPEAT('t',932),'t'),('x',NULL),('x',NULL),
3975+
(REPEAT('z',298),'z'),(REPEAT('p',1000),'p'),(REPEAT('k',468),'k'),
3976+
(REPEAT('c',1000),'c'),(REPEAT('o',648),'o'),('x',NULL),('x',NULL),
3977+
(REPEAT('c',258),'c'),(REPEAT('t',414),'t'),(REPEAT('f',966),'f'),
3978+
(REPEAT('y',746),'y'),(REPEAT('f',1000),'f');
3979+
INSERT INTO t1 SELECT * FROM t1;
3980+
INSERT INTO t1 SELECT * FROM t1;
3981+
INSERT INTO t1 SELECT * FROM t1;
3982+
INSERT INTO t1 SELECT * FROM t1;
3983+
SET @save_sort_buffer_size= @@sort_buffer_size;
3984+
SET sort_buffer_size= 16384;
3985+
SELECT LEFT(a,1), GROUP_CONCAT(b) FROM t1 GROUP BY a;
3986+
LEFT(a,1) GROUP_CONCAT(b)
3987+
a a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
3988+
c c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c
3989+
c c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c
3990+
f f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f
3991+
f f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f
3992+
k k,k,k,k,k,k,k,k,k,k,k,k,k,k,k,k
3993+
o o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o
3994+
p p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p
3995+
t t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t
3996+
t t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t
3997+
x NULL
3998+
y y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y
3999+
z z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z
4000+
SELECT SUBSTR(a,1,1), LENGTH(a), GROUP_CONCAT(b), COUNT(*) FROM t1 GROUP BY a;
4001+
SUBSTR(a,1,1) LENGTH(a) GROUP_CONCAT(b) COUNT(*)
4002+
a 1000 a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a 16
4003+
c 258 c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c 16
4004+
c 1000 c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c 16
4005+
f 966 f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f 16
4006+
f 1000 f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f 16
4007+
k 468 k,k,k,k,k,k,k,k,k,k,k,k,k,k,k,k 16
4008+
o 648 o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o 16
4009+
p 1000 p,p,p,p,p,p,p,p,p,p,p,p,p,p,p,p 16
4010+
t 414 t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t 16
4011+
t 932 t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t 16
4012+
x 1 NULL 64
4013+
y 746 y,y,y,y,y,y,y,y,y,y,y,y,y,y,y,y 16
4014+
z 298 z,z,z,z,z,z,z,z,z,z,z,z,z,z,z,z 16
4015+
SET @@sort_buffer_size= @save_sort_buffer_size;
4016+
DROP TABLE t1;
4017+
CREATE TABLE t1(a VARCHAR(1027), b INT);
4018+
INSERT INTO t1 SELECT seq, seq from seq_1_to_34;
4019+
SET @save_tmp_memory_table_size= @@tmp_memory_table_size;
4020+
SET tmp_memory_table_size= 1056*2;
4021+
SELECT COUNT(DISTINCT a) FROM t1;
4022+
COUNT(DISTINCT a)
4023+
34
4024+
SET @@tmp_memory_table_size= @save_tmp_memory_table_size;
4025+
DROP TABLE t1;
39684026
# End of 10.5 tests

mysql-test/main/order_by.test

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2465,4 +2465,40 @@ SELECT * FROM t1 ORDER BY CONVERT(AES_ENCRYPT(1,a), CHAR(4));
24652465
--enable_warnings
24662466
DROP TABLE t1;
24672467

2468+
--echo #
2469+
--echo # MDEV-22819:Wrong result or Assertion `ix > 0' failed in read_to_buffer upon select
2470+
--echo # with GROUP BY and GROUP_CONCAT
2471+
--echo #
2472+
2473+
CREATE TABLE t1 (a VARCHAR(1000), b CHAR(1));
2474+
2475+
INSERT INTO t1 VALUES
2476+
(REPEAT('a',1000),'a'),(REPEAT('t',932),'t'),('x',NULL),('x',NULL),
2477+
(REPEAT('z',298),'z'),(REPEAT('p',1000),'p'),(REPEAT('k',468),'k'),
2478+
(REPEAT('c',1000),'c'),(REPEAT('o',648),'o'),('x',NULL),('x',NULL),
2479+
(REPEAT('c',258),'c'),(REPEAT('t',414),'t'),(REPEAT('f',966),'f'),
2480+
(REPEAT('y',746),'y'),(REPEAT('f',1000),'f');
2481+
2482+
INSERT INTO t1 SELECT * FROM t1;
2483+
INSERT INTO t1 SELECT * FROM t1;
2484+
INSERT INTO t1 SELECT * FROM t1;
2485+
INSERT INTO t1 SELECT * FROM t1;
2486+
2487+
SET @save_sort_buffer_size= @@sort_buffer_size;
2488+
SET sort_buffer_size= 16384;
2489+
SELECT LEFT(a,1), GROUP_CONCAT(b) FROM t1 GROUP BY a;
2490+
SELECT SUBSTR(a,1,1), LENGTH(a), GROUP_CONCAT(b), COUNT(*) FROM t1 GROUP BY a;
2491+
2492+
SET @@sort_buffer_size= @save_sort_buffer_size;
2493+
DROP TABLE t1;
2494+
2495+
CREATE TABLE t1(a VARCHAR(1027), b INT);
2496+
INSERT INTO t1 SELECT seq, seq from seq_1_to_34;
2497+
SET @save_tmp_memory_table_size= @@tmp_memory_table_size;
2498+
SET tmp_memory_table_size= 1056*2;
2499+
SELECT COUNT(DISTINCT a) FROM t1;
2500+
SET @@tmp_memory_table_size= @save_tmp_memory_table_size;
2501+
DROP TABLE t1;
2502+
2503+
24682504
--echo # End of 10.5 tests

sql/filesort.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,17 +1845,15 @@ bool merge_buffers(Sort_param *param, IO_CACHE *from_file,
18451845
offsetof(Merge_chunk,m_current_key), 0,
18461846
(queue_compare) cmp, first_cmp_arg, 0, 0)))
18471847
DBUG_RETURN(1); /* purecov: inspected */
1848+
const size_t chunk_sz = (sort_buffer.size()/((uint) (Tb-Fb) +1));
18481849
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
18491850
{
1850-
buffpek->set_buffer(strpos,
1851-
strpos + (sort_buffer.size()/((uint) (Tb-Fb) +1)));
1852-
1851+
buffpek->set_buffer(strpos, strpos + chunk_sz);
18531852
buffpek->set_max_keys(maxcount);
18541853
bytes_read= read_to_buffer(from_file, buffpek, param, packed_format);
18551854
if (unlikely(bytes_read == (ulong) -1))
18561855
goto err; /* purecov: inspected */
1857-
strpos+= bytes_read;
1858-
buffpek->set_buffer_end(strpos);
1856+
strpos+= chunk_sz;
18591857
// If less data in buffers than expected
18601858
buffpek->set_max_keys(buffpek->mem_count());
18611859
queue_insert(&queue, (uchar*) buffpek);

sql/uniques.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,13 @@ bool Unique::merge(TABLE *table, uchar *buff, size_t buff_size,
735735
sort_param.cmp_context.key_compare= tree.compare;
736736
sort_param.cmp_context.key_compare_arg= tree.custom_arg;
737737

738+
/*
739+
We need to remove the size allocated for the unique buffer.
740+
The sort_buffer_size is:
741+
MY_MAX(MERGEBUFF2+1, max_in_memory_size/full_size+1) * full_size;
742+
*/
743+
buff_size-= full_size;
744+
738745
/* Merge the buffers to one file, removing duplicates */
739746
if (merge_many_buff(&sort_param,
740747
Bounds_checked_array<uchar>(buff, buff_size),
@@ -802,7 +809,8 @@ bool Unique::get(TABLE *table)
802809
/* Not enough memory; Save the result to file && free memory used by tree */
803810
if (flush())
804811
DBUG_RETURN(1);
805-
size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size;
812+
size_t buff_sz= MY_MAX(MERGEBUFF2+1, max_in_memory_size/full_size+1) * full_size;
813+
806814
if (!(sort_buffer= (uchar*) my_malloc(key_memory_Unique_sort_buffer, buff_sz,
807815
MYF(MY_THREAD_SPECIFIC|MY_WME))))
808816
DBUG_RETURN(1);

0 commit comments

Comments
 (0)