diff options
author | Ajo Robert <ajo.robert@oracle.com> | 2015-08-07 16:26:10 +0530 |
---|---|---|
committer | Ajo Robert <ajo.robert@oracle.com> | 2015-08-07 16:26:10 +0530 |
commit | f3dce250f45b3a02a30743b2c0928f8aaf132e88 (patch) | |
tree | 87b766abaf235a99efe778b5ab5169359a3feca9 | |
parent | c28626d0af640dddfb2c4d970f0ce4f6ec1776cc (diff) | |
download | mariadb-git-f3dce250f45b3a02a30743b2c0928f8aaf132e88.tar.gz |
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.
-rw-r--r-- | sql/sql_insert.cc | 55 | ||||
-rw-r--r-- | sql/sql_select.cc | 1 |
2 files changed, 41 insertions, 15 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index a59e3fd14e9..1237521e68e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,5 +1,5 @@ /* - 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);); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8a83b907b2e..acf6efa5a13 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -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; |