Commit 4e503aec authored by Sergei Golubchik's avatar Sergei Golubchik

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.
parent 61feb568
......@@ -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
#
......@@ -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 #
......@@ -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);
......
......@@ -8658,55 +8658,64 @@ static bool optimize_for_get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond
}
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())
{
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))
List_iterator<TABLE_LIST> tli(tables);
while (TABLE_LIST *table_list= tli++)
{
TABLE *table= table_list->table;
THD *thd=table->in_use;
if (!table_list->schema_table || !thd->fill_information_schema_tables())
continue;
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->move_field(cur);
*to_recinfo++= *from_recinfo;
cur+= from_recinfo->length;
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;
}
}
else
if ((table->s->reclength= (ulong)(cur - table->record[0])) == 0)
{
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;
/* all fields were optimized away. Force a non-0-length row */
table->s->reclength= to_recinfo->length= 1;
to_recinfo++;
}
}
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;
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;
// 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;
......
......@@ -238,6 +238,7 @@ class IS_table_read_plan : public Sql_alloc
};
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();
......
......@@ -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;
......
......@@ -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)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment