Commit f3dce250 authored by Ajo Robert's avatar Ajo Robert

Bug #20760261 mysqld crashed in materialized_cursor::

send_result_set_metadata

Analysis
--------
Cursor inside trigger accessing NEW/OLD row leads server exit.

The reason for the bug was that implementation of function
create_tmp_table() was not considering Item::TRIGGER_FIELD_ITEM
as possible alternative for type of class being instantiated.
This was resulting in a mismatch between a number of columns
in result list and temp table definition. This mismatch leads
to the failure of assertion
DBUG_ASSERT(send_result_set_metadata.elements == item_list.elements)
in the method Materialized_cursor::send_result_set_metadata
in debug mode.

Fix:
---
Added code to consider Item::TRIGGER_FIELD_ITEM as valid
type while creating fields.
parent c28626d0
/*
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -3531,7 +3531,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
/* Add selected items to field list */
List_iterator_fast<Item> it(*items);
Item *item;
Field *tmp_field;
bool not_used;
DBUG_ENTER("create_table_from_items");
......@@ -3549,22 +3548,48 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
while ((item=it++))
{
Create_field *cr_field;
Field *field, *def_field;
Field *tmp_table_field;
if (item->type() == Item::FUNC_ITEM)
{
if (item->result_type() != STRING_RESULT)
field= item->tmp_table_field(&tmp_table);
tmp_table_field= item->tmp_table_field(&tmp_table);
else
field= item->tmp_table_field_from_field_type(&tmp_table, 0);
tmp_table_field= item->tmp_table_field_from_field_type(&tmp_table, 0);
}
else
field= create_tmp_field(thd, &tmp_table, item, item->type(),
(Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0,
0);
if (!field ||
!(cr_field=new Create_field(field,(item->type() == Item::FIELD_ITEM ?
((Item_field *)item)->field :
(Field*) 0))))
DBUG_RETURN(0);
{
Field *from_field, *default_field;
tmp_table_field= create_tmp_field(thd, &tmp_table, item, item->type(),
(Item ***) 0, &from_field, &default_field,
0, 0, 0, 0, 0);
}
if (!tmp_table_field)
DBUG_RETURN(NULL);
Field *table_field;
switch (item->type())
{
/*
We have to take into account both the real table's fields and
pseudo-fields used in trigger's body. These fields are used
to copy defaults values later inside constructor of
the class Create_field.
*/
case Item::FIELD_ITEM:
case Item::TRIGGER_FIELD_ITEM:
table_field= ((Item_field *) item)->field;
break;
default:
table_field= NULL;
}
Create_field *cr_field= new Create_field(tmp_table_field, table_field);
if (!cr_field)
DBUG_RETURN(NULL);
if (item->maybe_null)
cr_field->flags &= ~NOT_NULL_FLAG;
alter_info->create_list.push_back(cr_field);
......@@ -3639,7 +3664,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
}
reenable_binlog(thd);
if (!table) // open failed
DBUG_RETURN(0);
DBUG_RETURN(NULL);
}
DBUG_EXECUTE_IF("sleep_create_select_before_lock", my_sleep(6000000););
......
......@@ -9820,6 +9820,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
}
case Item::FIELD_ITEM:
case Item::DEFAULT_VALUE_ITEM:
case Item::TRIGGER_FIELD_ITEM:
{
Item_field *field= (Item_field*) item;
bool orig_modify= modify_item;
......
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