mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
MDEV-30143 Segfault on select query using index for group-by and filesort
The problem was trying to access JOIN_TAB::select which is set to NULL when using the filesort. The correct way is accessing either JOIN_TAB::select or JOIN_TAB::filesort->select depending on whether the filesort is used. This commit introduces member function JOIN_TAB::get_sql_select() encapsulating that check so the code duplication is eliminated. The new condition (s->table->quick_keys.is_set(best_key->key)) was added to best_access_path() to eliminate a Valgrind error. The cause of that error was using TRASH_ALLOC(quick_key_parts) instead of bzero(quick_key_parts); hence, accessing s->table->quick_key_parts[best_key->key]) without prior checking for quick_keys.is_set() might have caused reading "dirty" memory
This commit is contained in:
parent
131ef14a6e
commit
60f0765b58
4 changed files with 54 additions and 6 deletions
|
@ -308,6 +308,28 @@ NULL bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
|||
NULL aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
NULL aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
drop table t1,t2;
|
||||
#
|
||||
# MDEV-30143: Segfault on select query using index for group-by and filesort
|
||||
#
|
||||
CREATE TABLE t1 (a varchar(35), b varchar(4)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES
|
||||
('Albania','AXA'),('Australia','AUS'),('American Samoa','AMSA'),('Bahamas','BS');
|
||||
CREATE TABLE t2 (a varchar(4), b varchar(50), PRIMARY KEY (b,a), KEY (a)) ENGINE=InnoDB;
|
||||
INSERT INTO t2 VALUES
|
||||
('BERM','African Methodist Episcopal'),('AUS','Anglican'),('BERM','Anglican'),('BS','Anglican'),('BS','Baptist'),('BS','Methodist');
|
||||
EXPLAIN SELECT t1.a
|
||||
FROM (SELECT a FROM t2 GROUP BY a ORDER BY COUNT(DISTINCT b) LIMIT 1) dt
|
||||
JOIN t1 ON dt.a=t1.b;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL #
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL # Using where; Using join buffer (flat, BNL join)
|
||||
2 DERIVED t2 range a a 58 NULL # Using index for group-by (scanning); Using temporary; Using filesort
|
||||
SELECT t1.a
|
||||
FROM (SELECT a FROM t2 GROUP BY a ORDER BY COUNT(DISTINCT b) LIMIT 1) dt
|
||||
JOIN t1 ON dt.a=t1.b;
|
||||
a
|
||||
Australia
|
||||
DROP TABLES t1, t2;
|
||||
set global innodb_stats_persistent= @innodb_stats_persistent_save;
|
||||
set global innodb_stats_persistent_sample_pages=
|
||||
@innodb_stats_persistent_sample_pages_save;
|
||||
|
|
|
@ -251,7 +251,28 @@ insert into t2 values (1,repeat("a",1000)),(2,repeat("a",1000)),(3,repeat("b",10
|
|||
SELECT GROUP_CONCAT(t1.language_id SEPARATOR ',') AS `translation_resources`, `d`.`serialized_c` FROM t2 AS `d` LEFT JOIN t1 ON `d`.`voter_id` = t1.`voter_id` GROUP BY `d`.`voter_id` ORDER BY 10-d.voter_id+RAND()*0;
|
||||
drop table t1,t2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-30143: Segfault on select query using index for group-by and filesort
|
||||
--echo #
|
||||
CREATE TABLE t1 (a varchar(35), b varchar(4)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES
|
||||
('Albania','AXA'),('Australia','AUS'),('American Samoa','AMSA'),('Bahamas','BS');
|
||||
|
||||
CREATE TABLE t2 (a varchar(4), b varchar(50), PRIMARY KEY (b,a), KEY (a)) ENGINE=InnoDB;
|
||||
INSERT INTO t2 VALUES
|
||||
('BERM','African Methodist Episcopal'),('AUS','Anglican'),('BERM','Anglican'),('BS','Anglican'),('BS','Baptist'),('BS','Methodist');
|
||||
|
||||
let query=
|
||||
SELECT t1.a
|
||||
FROM (SELECT a FROM t2 GROUP BY a ORDER BY COUNT(DISTINCT b) LIMIT 1) dt
|
||||
JOIN t1 ON dt.a=t1.b;
|
||||
--replace_column 9 #
|
||||
eval EXPLAIN $query;
|
||||
eval $query;
|
||||
|
||||
DROP TABLES t1, t2;
|
||||
|
||||
set global innodb_stats_persistent= @innodb_stats_persistent_save;
|
||||
set global innodb_stats_persistent_sample_pages=
|
||||
@innodb_stats_persistent_sample_pages_save;
|
||||
|
||||
|
|
|
@ -8120,6 +8120,7 @@ best_access_path(JOIN *join,
|
|||
if ((records >= s->found_records || best > s->read_time) && // (1)
|
||||
!(best_key && best_key->key == MAX_KEY) && // (2)
|
||||
!(s->quick && best_key && s->quick->index == best_key->key && // (2)
|
||||
s->table->quick_keys.is_set(best_key->key) && // (2)
|
||||
best_max_key_part >= s->table->quick_key_parts[best_key->key]) &&// (2)
|
||||
!((s->table->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX) && // (3)
|
||||
! s->table->covering_keys.is_clear_all() && best_key && !s->quick) &&// (3)
|
||||
|
@ -13791,7 +13792,7 @@ double JOIN_TAB::scan_time()
|
|||
ha_rows JOIN_TAB::get_examined_rows()
|
||||
{
|
||||
double examined_rows;
|
||||
SQL_SELECT *sel= filesort? filesort->select : this->select;
|
||||
const SQL_SELECT *sel= get_sql_select();
|
||||
|
||||
if (sel && sel->quick && use_quick != 2)
|
||||
examined_rows= (double)sel->quick->records;
|
||||
|
@ -26858,13 +26859,12 @@ bool JOIN_TAB::save_explain_data(Explain_table_access *eta,
|
|||
eta->key.clear();
|
||||
eta->quick_info= NULL;
|
||||
|
||||
SQL_SELECT *tab_select;
|
||||
/*
|
||||
We assume that if this table does pre-sorting, then it doesn't do filtering
|
||||
with SQL_SELECT.
|
||||
*/
|
||||
DBUG_ASSERT(!(select && filesort));
|
||||
tab_select= (filesort)? filesort->select : select;
|
||||
const SQL_SELECT *tab_select= get_sql_select();
|
||||
|
||||
if (filesort)
|
||||
{
|
||||
|
|
|
@ -546,14 +546,19 @@ typedef struct st_join_table {
|
|||
void cleanup();
|
||||
inline bool is_using_loose_index_scan()
|
||||
{
|
||||
const SQL_SELECT *sel= filesort ? filesort->select : select;
|
||||
const SQL_SELECT *sel= get_sql_select();
|
||||
return (sel && sel->quick &&
|
||||
(sel->quick->get_type() == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX));
|
||||
}
|
||||
bool is_using_agg_loose_index_scan ()
|
||||
{
|
||||
const SQL_SELECT *sel= get_sql_select();
|
||||
return (is_using_loose_index_scan() &&
|
||||
((QUICK_GROUP_MIN_MAX_SELECT *)select->quick)->is_agg_distinct());
|
||||
((QUICK_GROUP_MIN_MAX_SELECT *)sel->quick)->is_agg_distinct());
|
||||
}
|
||||
const SQL_SELECT *get_sql_select()
|
||||
{
|
||||
return filesort ? filesort->select : select;
|
||||
}
|
||||
bool is_inner_table_of_semi_join_with_first_match()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue