mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Bug#24630 Subselect query crashes mysqld
The crash happens because second filling of the same I_S table happens in case of subselect with order by. table->sort.io_cache previously allocated in create_sort_index() is deleted during second filling (function get_schema_tables_result). There are two places where I_S table can be filled: JOIN::exec and create_sort_index(). To fix the bug we should check if the table was already filled in one of these places and skip processing of the table in second.
This commit is contained in:
@ -1278,3 +1278,40 @@ table_name
|
|||||||
t1
|
t1
|
||||||
t2
|
t2
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
select 1 as f1 from information_schema.tables where "CHARACTER_SETS"=
|
||||||
|
(select cast(table_name as char) from information_schema.tables
|
||||||
|
order by table_name limit 1) limit 1;
|
||||||
|
f1
|
||||||
|
1
|
||||||
|
select t.table_name, group_concat(t.table_schema, '.', t.table_name),
|
||||||
|
count(*) as num1
|
||||||
|
from information_schema.tables t
|
||||||
|
inner join information_schema.columns c1
|
||||||
|
on t.table_schema = c1.table_schema AND t.table_name = c1.table_name
|
||||||
|
where t.table_schema = 'information_schema' and
|
||||||
|
c1.ordinal_position =
|
||||||
|
(select isnull(c2.column_type) -
|
||||||
|
isnull(group_concat(c2.table_schema, '.', c2.table_name)) +
|
||||||
|
count(*) as num
|
||||||
|
from information_schema.columns c2 where
|
||||||
|
c2.table_schema='information_schema' and
|
||||||
|
(c2.column_type = 'varchar(7)' or c2.column_type = 'varchar(20)')
|
||||||
|
group by c2.column_type order by num limit 1)
|
||||||
|
group by t.table_name order by num1, t.table_name;
|
||||||
|
table_name group_concat(t.table_schema, '.', t.table_name) num1
|
||||||
|
CHARACTER_SETS information_schema.CHARACTER_SETS 1
|
||||||
|
COLLATIONS information_schema.COLLATIONS 1
|
||||||
|
COLLATION_CHARACTER_SET_APPLICABILITY information_schema.COLLATION_CHARACTER_SET_APPLICABILITY 1
|
||||||
|
COLUMNS information_schema.COLUMNS 1
|
||||||
|
COLUMN_PRIVILEGES information_schema.COLUMN_PRIVILEGES 1
|
||||||
|
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
|
||||||
|
ROUTINES information_schema.ROUTINES 1
|
||||||
|
SCHEMATA information_schema.SCHEMATA 1
|
||||||
|
SCHEMA_PRIVILEGES information_schema.SCHEMA_PRIVILEGES 1
|
||||||
|
STATISTICS information_schema.STATISTICS 1
|
||||||
|
TABLES information_schema.TABLES 1
|
||||||
|
TABLE_CONSTRAINTS information_schema.TABLE_CONSTRAINTS 1
|
||||||
|
TABLE_PRIVILEGES information_schema.TABLE_PRIVILEGES 1
|
||||||
|
TRIGGERS information_schema.TRIGGERS 1
|
||||||
|
USER_PRIVILEGES information_schema.USER_PRIVILEGES 1
|
||||||
|
VIEWS information_schema.VIEWS 1
|
||||||
|
@ -999,4 +999,28 @@ where table_schema = 'test' and table_name not in
|
|||||||
where table_schema = 'test' and column_name = 'f3');
|
where table_schema = 'test' and column_name = 'f3');
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#24630 Subselect query crashes mysqld
|
||||||
|
#
|
||||||
|
select 1 as f1 from information_schema.tables where "CHARACTER_SETS"=
|
||||||
|
(select cast(table_name as char) from information_schema.tables
|
||||||
|
order by table_name limit 1) limit 1;
|
||||||
|
|
||||||
|
select t.table_name, group_concat(t.table_schema, '.', t.table_name),
|
||||||
|
count(*) as num1
|
||||||
|
from information_schema.tables t
|
||||||
|
inner join information_schema.columns c1
|
||||||
|
on t.table_schema = c1.table_schema AND t.table_name = c1.table_name
|
||||||
|
where t.table_schema = 'information_schema' and
|
||||||
|
c1.ordinal_position =
|
||||||
|
(select isnull(c2.column_type) -
|
||||||
|
isnull(group_concat(c2.table_schema, '.', c2.table_name)) +
|
||||||
|
count(*) as num
|
||||||
|
from information_schema.columns c2 where
|
||||||
|
c2.table_schema='information_schema' and
|
||||||
|
(c2.column_type = 'varchar(7)' or c2.column_type = 'varchar(20)')
|
||||||
|
group by c2.column_type order by num limit 1)
|
||||||
|
group by t.table_name order by num1, t.table_name;
|
||||||
|
|
||||||
# End of 5.0 tests.
|
# End of 5.0 tests.
|
||||||
|
@ -932,7 +932,8 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
|
|||||||
int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
|
int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
|
||||||
int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
|
int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
|
||||||
int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
|
int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
|
||||||
bool get_schema_tables_result(JOIN *join);
|
bool get_schema_tables_result(JOIN *join,
|
||||||
|
enum enum_schema_table_state executed_place);
|
||||||
#define is_schema_db(X) \
|
#define is_schema_db(X) \
|
||||||
!my_strcasecmp(system_charset_info, information_schema_name.str, (X))
|
!my_strcasecmp(system_charset_info, information_schema_name.str, (X))
|
||||||
|
|
||||||
|
@ -1505,7 +1505,7 @@ JOIN::exec()
|
|||||||
|
|
||||||
if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
|
if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
|
||||||
!thd->lex->describe &&
|
!thd->lex->describe &&
|
||||||
get_schema_tables_result(curr_join))
|
get_schema_tables_result(curr_join, PROCESSED_BY_JOIN_EXEC))
|
||||||
{
|
{
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -12372,7 +12372,7 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order,
|
|||||||
/* Fill schema tables with data before filesort if it's necessary */
|
/* Fill schema tables with data before filesort if it's necessary */
|
||||||
if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
|
if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
|
||||||
!thd->lex->describe &&
|
!thd->lex->describe &&
|
||||||
get_schema_tables_result(join))
|
get_schema_tables_result(join, PROCESSED_BY_CREATE_SORT_INDEX))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (table->s->tmp_table)
|
if (table->s->tmp_table)
|
||||||
|
@ -3938,13 +3938,15 @@ int make_schema_select(THD *thd, SELECT_LEX *sel,
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
get_schema_tables_result()
|
get_schema_tables_result()
|
||||||
join join which use schema tables
|
join join which use schema tables
|
||||||
|
executed_place place where I_S table processed
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
FALSE success
|
FALSE success
|
||||||
TRUE error
|
TRUE error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool get_schema_tables_result(JOIN *join)
|
bool get_schema_tables_result(JOIN *join,
|
||||||
|
enum enum_schema_table_state executed_place)
|
||||||
{
|
{
|
||||||
JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
|
JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
|
||||||
THD *thd= join->thd;
|
THD *thd= join->thd;
|
||||||
@ -3964,14 +3966,24 @@ bool get_schema_tables_result(JOIN *join)
|
|||||||
bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
|
bool is_subselect= (&lex->unit != lex->current_select->master_unit() &&
|
||||||
lex->current_select->master_unit()->item);
|
lex->current_select->master_unit()->item);
|
||||||
/*
|
/*
|
||||||
The schema table is already processed and
|
If schema table is already processed and
|
||||||
the statement is not a subselect.
|
the statement is not a subselect then
|
||||||
So we don't need to handle this table again.
|
we don't need to fill this table again.
|
||||||
|
If schema table is already processed and
|
||||||
|
schema_table_state != executed_place then
|
||||||
|
table is already processed and
|
||||||
|
we should skip second data processing.
|
||||||
*/
|
*/
|
||||||
if (table_list->is_schema_table_processed && !is_subselect)
|
if (table_list->schema_table_state &&
|
||||||
|
(!is_subselect || table_list->schema_table_state != executed_place))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (is_subselect) // is subselect
|
/*
|
||||||
|
if table is used in a subselect and
|
||||||
|
table has been processed earlier with the same
|
||||||
|
'executed_place' value then we should refresh the table.
|
||||||
|
*/
|
||||||
|
if (table_list->schema_table_state && is_subselect)
|
||||||
{
|
{
|
||||||
table_list->table->file->extra(HA_EXTRA_NO_CACHE);
|
table_list->table->file->extra(HA_EXTRA_NO_CACHE);
|
||||||
table_list->table->file->extra(HA_EXTRA_RESET_STATE);
|
table_list->table->file->extra(HA_EXTRA_RESET_STATE);
|
||||||
@ -3988,10 +4000,10 @@ bool get_schema_tables_result(JOIN *join)
|
|||||||
{
|
{
|
||||||
result= 1;
|
result= 1;
|
||||||
join->error= 1;
|
join->error= 1;
|
||||||
table_list->is_schema_table_processed= TRUE;
|
table_list->schema_table_state= executed_place;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
table_list->is_schema_table_processed= TRUE;
|
table_list->schema_table_state= executed_place;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thd->no_warnings_for_error= 0;
|
thd->no_warnings_for_error= 0;
|
||||||
|
@ -3031,7 +3031,7 @@ void st_table_list::reinit_before_use(THD *thd)
|
|||||||
*/
|
*/
|
||||||
table= 0;
|
table= 0;
|
||||||
/* Reset is_schema_table_processed value(needed for I_S tables */
|
/* Reset is_schema_table_processed value(needed for I_S tables */
|
||||||
is_schema_table_processed= FALSE;
|
schema_table_state= NOT_PROCESSED;
|
||||||
|
|
||||||
TABLE_LIST *embedded; /* The table at the current level of nesting. */
|
TABLE_LIST *embedded; /* The table at the current level of nesting. */
|
||||||
TABLE_LIST *embedding= this; /* The parent nested table reference. */
|
TABLE_LIST *embedding= this; /* The parent nested table reference. */
|
||||||
|
@ -287,6 +287,12 @@ struct st_table {
|
|||||||
void reset_item_list(List<Item> *item_list) const;
|
void reset_item_list(List<Item> *item_list) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum enum_schema_table_state
|
||||||
|
{
|
||||||
|
NOT_PROCESSED= 0,
|
||||||
|
PROCESSED_BY_CREATE_SORT_INDEX,
|
||||||
|
PROCESSED_BY_JOIN_EXEC
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct st_foreign_key_info
|
typedef struct st_foreign_key_info
|
||||||
{
|
{
|
||||||
@ -529,7 +535,6 @@ typedef struct st_table_list
|
|||||||
st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
|
st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
|
||||||
ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
|
ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
|
||||||
st_select_lex *schema_select_lex;
|
st_select_lex *schema_select_lex;
|
||||||
bool is_schema_table_processed;
|
|
||||||
/*
|
/*
|
||||||
True when the view field translation table is used to convert
|
True when the view field translation table is used to convert
|
||||||
schema table fields for backwards compatibility with SHOW command.
|
schema table fields for backwards compatibility with SHOW command.
|
||||||
@ -638,6 +643,7 @@ typedef struct st_table_list
|
|||||||
*/
|
*/
|
||||||
bool prelocking_placeholder;
|
bool prelocking_placeholder;
|
||||||
|
|
||||||
|
enum enum_schema_table_state schema_table_state;
|
||||||
void calc_md5(char *buffer);
|
void calc_md5(char *buffer);
|
||||||
void set_underlying_merge();
|
void set_underlying_merge();
|
||||||
int view_check_option(THD *thd, bool ignore_failure);
|
int view_check_option(THD *thd, bool ignore_failure);
|
||||||
|
Reference in New Issue
Block a user