Bug #46159: simple query that never returns
The external 'for' loop in remove_dup_with_compare() handled HA_ERR_RECORD_DELETED by just starting over without advancing to the next record which caused an infinite loop. This condition could be triggered on certain data by a SELECT query containing DISTINCT, GROUP BY and HAVING clauses. Fixed remove_dup_with_compare() so that we always advance to the next record when receiving HA_ERR_RECORD_DELETED from rnd_next(). mysql-test/r/distinct.result: Added a test case for bug #46159. mysql-test/t/distinct.test: Added a test case for bug #46159. sql/sql_select.cc: Fixed remove_dup_with_compare() so that we always advance to the next record when receiving HA_ERR_RECORD_DELETED from rnd_next().
This commit is contained in:
parent
354f5f7bac
commit
505346028f
@ -763,4 +763,34 @@ a b d c
|
|||||||
1 2 0 2
|
1 2 0 2
|
||||||
1 2 0 3
|
1 2 0 3
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# Bug #46159: simple query that never returns
|
||||||
|
#
|
||||||
|
SET @old_max_heap_table_size = @@max_heap_table_size;
|
||||||
|
SET @@max_heap_table_size = 16384;
|
||||||
|
SET @old_sort_buffer_size = @@sort_buffer_size;
|
||||||
|
SET @@sort_buffer_size = 32804;
|
||||||
|
CREATE TABLE t1(c1 int, c2 VARCHAR(20));
|
||||||
|
INSERT INTO t1 VALUES (1, '1'), (1, '1'), (2, '2'), (3, '1'), (3, '1'), (4, '4');
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
SELECT c1, c2, COUNT(*) FROM t1 GROUP BY c1 LIMIT 4;
|
||||||
|
c1 c2 COUNT(*)
|
||||||
|
1 1 2
|
||||||
|
2 2 1
|
||||||
|
3 1 2
|
||||||
|
4 4 1
|
||||||
|
SELECT DISTINCT c2 FROM t1 GROUP BY c1 HAVING COUNT(*) > 1;
|
||||||
|
c2
|
||||||
|
1
|
||||||
|
5
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @@sort_buffer_size = @old_sort_buffer_size;
|
||||||
|
SET @@max_heap_table_size = @old_max_heap_table_size;
|
||||||
End of 5.1 tests
|
End of 5.1 tests
|
||||||
|
@ -573,4 +573,44 @@ SELECT DISTINCT a, b, d, c FROM t1;
|
|||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Bug #46159: simple query that never returns
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
# Set max_heap_table_size to the minimum value so that GROUP BY table in the
|
||||||
|
# SELECT query below gets converted to MyISAM
|
||||||
|
SET @old_max_heap_table_size = @@max_heap_table_size;
|
||||||
|
SET @@max_heap_table_size = 16384;
|
||||||
|
|
||||||
|
# Set sort_buffer_size to the mininum value so that remove_duplicates() calls
|
||||||
|
# remove_dup_with_compare()
|
||||||
|
SET @old_sort_buffer_size = @@sort_buffer_size;
|
||||||
|
SET @@sort_buffer_size = 32804;
|
||||||
|
|
||||||
|
CREATE TABLE t1(c1 int, c2 VARCHAR(20));
|
||||||
|
INSERT INTO t1 VALUES (1, '1'), (1, '1'), (2, '2'), (3, '1'), (3, '1'), (4, '4');
|
||||||
|
# Now we just need to pad the table with random data so we have enough unique
|
||||||
|
# values to force conversion of the GROUP BY table to MyISAM
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
INSERT INTO t1 SELECT 5 + 10000 * RAND(), '5' FROM t1;
|
||||||
|
|
||||||
|
# First rows of the GROUP BY table that will be processed by
|
||||||
|
# remove_dup_with_compare()
|
||||||
|
SELECT c1, c2, COUNT(*) FROM t1 GROUP BY c1 LIMIT 4;
|
||||||
|
|
||||||
|
# The actual test case
|
||||||
|
SELECT DISTINCT c2 FROM t1 GROUP BY c1 HAVING COUNT(*) > 1;
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
SET @@sort_buffer_size = @old_sort_buffer_size;
|
||||||
|
SET @@max_heap_table_size = @old_max_heap_table_size;
|
||||||
|
|
||||||
--echo End of 5.1 tests
|
--echo End of 5.1 tests
|
||||||
|
@ -13665,7 +13665,10 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
|
|||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
if (error == HA_ERR_RECORD_DELETED)
|
if (error == HA_ERR_RECORD_DELETED)
|
||||||
|
{
|
||||||
|
error= file->rnd_next(record);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
if (error == HA_ERR_END_OF_FILE)
|
if (error == HA_ERR_END_OF_FILE)
|
||||||
break;
|
break;
|
||||||
goto err;
|
goto err;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user