Skip to content

Commit 0099c2f

Browse files
committed
MDEV-30786 SIGFPE in cost_group_min_max on EXP
The problem was that for merge tables without any underlaying tables the block size was 0, which the code could not handle. Fixed by ensuring that MERGE tables never have a block size of 0. Fixed also a wrong assumption of number of seeks needed to scan merge tables.
1 parent 3bdc554 commit 0099c2f

File tree

3 files changed

+32
-17
lines changed

3 files changed

+32
-17
lines changed

mysql-test/main/merge.result

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3965,5 +3965,19 @@ SELECT DISTINCT f FROM tm WHERE f IN (47, 126, 97, 48, 73, 0);
39653965
f
39663966
DROP TABLE tm, t1, t2;
39673967
#
3968+
# MDEV-30786 SIGFPE in cost_group_min_max on EXP
3969+
#
3970+
SET use_stat_tables='preferably';
3971+
CREATE TABLE t1 (a INT,b INT,KEY i1 (a),KEY i2 (b)) ENGINE=MRG_MyISAM;
3972+
ANALYZE LOCAL TABLE t1;
3973+
Table Op Msg_type Msg_text
3974+
test.t1 analyze status Engine-independent statistics collected
3975+
test.t1 analyze note The storage engine for the table doesn't support analyze
3976+
EXPLAIN SELECT DISTINCT a FROM t1;
3977+
id select_type table type possible_keys key key_len ref rows Extra
3978+
1 SIMPLE t1 range NULL i1 5 NULL 1 Using index for group-by
3979+
drop table t1;
3980+
set use_stat_tables=default;
3981+
#
39683982
# End of 11.0 tests
39693983
#

mysql-test/main/merge.test

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2922,6 +2922,16 @@ CREATE TABLE tm (f INT, KEY(f)) ENGINE=MERGE UNION = (t1, t2);
29222922
SELECT DISTINCT f FROM tm WHERE f IN (47, 126, 97, 48, 73, 0);
29232923
DROP TABLE tm, t1, t2;
29242924

2925+
--echo #
2926+
--echo # MDEV-30786 SIGFPE in cost_group_min_max on EXP
2927+
--echo #
2928+
SET use_stat_tables='preferably';
2929+
CREATE TABLE t1 (a INT,b INT,KEY i1 (a),KEY i2 (b)) ENGINE=MRG_MyISAM;
2930+
ANALYZE LOCAL TABLE t1;
2931+
EXPLAIN SELECT DISTINCT a FROM t1;
2932+
drop table t1;
2933+
set use_stat_tables=default;
2934+
29252935
--echo #
29262936
--echo # End of 11.0 tests
29272937
--echo #

storage/myisammrg/ha_myisammrg.cc

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ IO_AND_CPU_COST ha_myisammrg::rnd_pos_time(ha_rows rows)
343343
{
344344
IO_AND_CPU_COST cost= handler::rnd_pos_time(rows);
345345
/*
346-
Row data is notcached. costs.row_lookup_cost includes the cost of
346+
Row data is not cached. costs.row_lookup_cost includes the cost of
347347
the reading the row from system (probably cached by the OS).
348348
*/
349349
cost.io= 0;
@@ -1300,26 +1300,17 @@ int ha_myisammrg::info(uint flag)
13001300
table->s->keys_in_use.set_prefix(table->s->keys);
13011301
stats.mean_rec_length= mrg_info.reclength;
13021302

1303-
/*
1303+
/*
13041304
The handler::block_size is used all over the code in index scan cost
13051305
calculations. It is used to get number of disk seeks required to
13061306
retrieve a number of index tuples.
1307-
If the merge table has N underlying tables, then (assuming underlying
1308-
tables have equal size, the only "simple" approach we can use)
1309-
retrieving X index records from a merge table will require N times more
1310-
disk seeks compared to doing the same on a MyISAM table with equal
1311-
number of records.
1312-
In the edge case (file_tables > myisam_block_size) we'll get
1313-
block_size==0, and index calculation code will act as if we need one
1314-
disk seek to retrieve one index tuple.
1315-
1316-
TODO: In 5.2 index scan cost calculation will be factored out into a
1317-
virtual function in class handler and we'll be able to remove this hack.
1307+
If the merge table has N underlying tables, there will be
1308+
N more disk seeks compared to a scanning a normal MyISAM table.
1309+
The number of bytes read is the rougly the same for a normal MyISAM
1310+
and a MyISAM merge tables.
13181311
*/
1319-
stats.block_size= 0;
1320-
if (file->tables)
1321-
stats.block_size= myisam_block_size / file->tables;
1322-
1312+
stats.block_size= myisam_block_size;
1313+
13231314
stats.update_time= 0;
13241315
#if SIZEOF_OFF_T > 4
13251316
ref_length=6; // Should be big enough

0 commit comments

Comments
 (0)