MDEV-24593 Signal 11 when group by primary key of table joined to information_schema.columns

I_S tables were materialized too late, an attempt to use table
statistics before the table was created caused a crash.

Let's move table creation up. it only needs read_set to
be calculated properly, this happens in JOIN::optimize_inner(),
after semijoin transformation.

Note that tables are not populated at that point, so most of the
statistics would make no sense anyway. But at least field sizes
will be correct. And it won't crash.
This commit is contained in:
Sergei Golubchik 2021-01-21 16:40:36 +01:00
parent 61feb568bb
commit 4e503aec7f
7 changed files with 79 additions and 55 deletions

View File

@ -2282,5 +2282,14 @@ create table t2 (n int);
insert into t1 set n = (select table_rows from information_schema.tables where table_name='t2');
drop table t1, t2;
#
# MDEV-24593 Signal 11 when group by primary key of table joined to information_schema.columns
#
create table t1 (f varchar(64) primary key);
select f from information_schema.columns i
inner join t1 on f=i.column_name
group by f;
f
drop table t1;
#
# End of 10.3 tests
#

View File

@ -2007,6 +2007,16 @@ create table t2 (n int);
insert into t1 set n = (select table_rows from information_schema.tables where table_name='t2');
drop table t1, t2;
--echo #
--echo # MDEV-24593 Signal 11 when group by primary key of table joined to information_schema.columns
--echo #
create table t1 (f varchar(64) primary key);
select f from information_schema.columns i
inner join t1 on f=i.column_name
group by f;
drop table t1;
--echo #
--echo # End of 10.3 tests
--echo #

View File

@ -1556,7 +1556,7 @@ int JOIN::init_join_caches()
int
JOIN::optimize_inner()
{
DBUG_ENTER("JOIN::optimize");
DBUG_ENTER("JOIN::optimize_inner");
subq_exit_fl= false;
do_send_rows = (unit->select_limit_cnt) ? 1 : 0;
@ -1624,6 +1624,10 @@ JOIN::optimize_inner()
table_count= select_lex->leaf_tables.elements;
if (select_lex->options & OPTION_SCHEMA_TABLE &&
optimize_schema_tables_memory_usage(select_lex->leaf_tables))
DBUG_RETURN(1);
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
DBUG_RETURN(-1);

View File

@ -8658,55 +8658,64 @@ end:
}
static int optimize_schema_tables_memory_usage(TABLE_LIST *table_list)
bool optimize_schema_tables_memory_usage(List<TABLE_LIST> &tables)
{
TABLE *table= table_list->table;
THD *thd=table->in_use;
if (!table->is_created())
List_iterator<TABLE_LIST> tli(tables);
while (TABLE_LIST *table_list= tli++)
{
TMP_TABLE_PARAM *p= table_list->schema_table_param;
TMP_ENGINE_COLUMNDEF *from_recinfo, *to_recinfo;
DBUG_ASSERT(table->s->keys == 0);
DBUG_ASSERT(table->s->uniques == 0);
TABLE *table= table_list->table;
THD *thd=table->in_use;
uchar *cur= table->field[0]->ptr;
/* first recinfo could be a NULL bitmap, not an actual Field */
from_recinfo= to_recinfo= p->start_recinfo + (cur != table->record[0]);
for (uint i=0; i < table->s->fields; i++, from_recinfo++)
{
Field *field= table->field[i];
DBUG_ASSERT(field->vcol_info == 0);
DBUG_ASSERT(from_recinfo->length);
DBUG_ASSERT(from_recinfo->length == field->pack_length_in_rec());
if (bitmap_is_set(table->read_set, i))
{
field->move_field(cur);
*to_recinfo++= *from_recinfo;
cur+= from_recinfo->length;
}
else
{
field= new (thd->mem_root) Field_string(cur, 0, field->null_ptr,
field->null_bit, Field::NONE,
&field->field_name, field->dtcollation());
field->init(table);
field->field_index= i;
DBUG_ASSERT(field->pack_length_in_rec() == 0);
table->field[i]= field;
}
}
if ((table->s->reclength= (ulong)(cur - table->record[0])) == 0)
{
/* all fields were optimized away. Force a non-0-length row */
table->s->reclength= to_recinfo->length= 1;
to_recinfo++;
}
p->recinfo= to_recinfo;
if (!table_list->schema_table || !thd->fill_information_schema_tables())
continue;
// TODO switch from Aria to Memory if all blobs were optimized away?
if (instantiate_tmp_table(table, p->keyinfo, p->start_recinfo, &p->recinfo,
table_list->select_lex->options | thd->variables.option_bits))
return 1;
if (!table->is_created())
{
TMP_TABLE_PARAM *p= table_list->schema_table_param;
TMP_ENGINE_COLUMNDEF *from_recinfo, *to_recinfo;
DBUG_ASSERT(table->s->keys == 0);
DBUG_ASSERT(table->s->uniques == 0);
uchar *cur= table->field[0]->ptr;
/* first recinfo could be a NULL bitmap, not an actual Field */
from_recinfo= to_recinfo= p->start_recinfo + (cur != table->record[0]);
for (uint i=0; i < table->s->fields; i++, from_recinfo++)
{
Field *field= table->field[i];
DBUG_ASSERT(field->vcol_info == 0);
DBUG_ASSERT(from_recinfo->length);
DBUG_ASSERT(from_recinfo->length == field->pack_length_in_rec());
if (bitmap_is_set(table->read_set, i))
{
field->move_field(cur);
*to_recinfo++= *from_recinfo;
cur+= from_recinfo->length;
}
else
{
field= new (thd->mem_root) Field_string(cur, 0, field->null_ptr,
field->null_bit, Field::NONE,
&field->field_name, field->dtcollation());
field->init(table);
field->field_index= i;
DBUG_ASSERT(field->pack_length_in_rec() == 0);
table->field[i]= field;
}
}
if ((table->s->reclength= (ulong)(cur - table->record[0])) == 0)
{
/* all fields were optimized away. Force a non-0-length row */
table->s->reclength= to_recinfo->length= 1;
to_recinfo++;
}
p->recinfo= to_recinfo;
// TODO switch from Aria to Memory if all blobs were optimized away?
if (instantiate_tmp_table(table, p->keyinfo, p->start_recinfo, &p->recinfo,
table_list->select_lex->options | thd->variables.option_bits))
return 1;
}
}
return 0;
}
@ -8732,9 +8741,6 @@ bool optimize_schema_tables_reads(JOIN *join)
TABLE_LIST *table_list= tab->table->pos_in_table_list;
if (table_list->schema_table && thd->fill_information_schema_tables())
{
if (optimize_schema_tables_memory_usage(table_list))
DBUG_RETURN(1);
/* A value of 0 indicates a dummy implementation */
if (table_list->schema_table->fill_table == 0)
continue;

View File

@ -238,6 +238,7 @@ public:
};
bool optimize_schema_tables_reads(JOIN *join);
bool optimize_schema_tables_memory_usage(List<TABLE_LIST> &tables);
/* Handle the ignored database directories list for SHOW/I_S. */
bool ignore_db_dirs_init();

View File

@ -363,9 +363,6 @@ int ha_heap::info(uint flag)
{
HEAPINFO hp_info;
if (!table)
return 0;
(void) heap_info(file,&hp_info,flag);
errkey= hp_info.errkey;

View File

@ -2440,9 +2440,6 @@ int ha_maria::info(uint flag)
MARIA_INFO maria_info;
char name_buff[FN_REFLEN];
if (!table)
return 0;
(void) maria_status(file, &maria_info, flag);
if (flag & HA_STATUS_VARIABLE)
{