summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAjo Robert <ajo.robert@oracle.com>2015-08-07 16:26:10 +0530
committerAjo Robert <ajo.robert@oracle.com>2015-08-07 16:26:10 +0530
commitf3dce250f45b3a02a30743b2c0928f8aaf132e88 (patch)
tree87b766abaf235a99efe778b5ab5169359a3feca9
parentc28626d0af640dddfb2c4d970f0ce4f6ec1776cc (diff)
downloadmariadb-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.cc55
-rw-r--r--sql/sql_select.cc1
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;