MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT, UBSAN runtime error: member call on null pointer of type 'struct TABLE_LIST' in Item_param::save_in_field
This is the prerequisite patch to refactor the method Item_default_value::fix_fields. The former implementation of this method was extracted and placed into the standalone function make_default_field() and the method Item_default_value::tie_field(). The motivation for this modification is upcoming changes for core implementation of the task MDEV-15703 since these functions will be used from several places within the source code.
This commit is contained in:
parent
85db534731
commit
6b2cd78695
@ -1 +1 @@
|
|||||||
Subproject commit 66596ad9e1d7efa8479656872cf09c9c1870a02e
|
Subproject commit 3b3c175af0e993ffaae251871421e206cc41963f
|
@ -1 +1 @@
|
|||||||
Subproject commit 9155b19b462ac15fc69d0b58ae51370b7523ced5
|
Subproject commit ae565eea90dd3053a5a7857e7cdad93342dbc645
|
159
sql/item.cc
159
sql/item.cc
@ -4969,6 +4969,44 @@ bool Item_param::append_for_log(THD *thd, String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate a memory and create on it a copy of Field object.
|
||||||
|
|
||||||
|
@param thd thread handler
|
||||||
|
@param field_arg an instance of Field the new Field object be based on
|
||||||
|
|
||||||
|
@return a new created Field object on success, nullptr on error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Field *make_default_field(THD *thd, Field *field_arg)
|
||||||
|
{
|
||||||
|
Field *def_field;
|
||||||
|
|
||||||
|
if (!(def_field= (Field*) thd->alloc(field_arg->size_of())))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
memcpy((void *)def_field, (void *)field_arg, field_arg->size_of());
|
||||||
|
def_field->reset_fields();
|
||||||
|
// If non-constant default value expression or a blob
|
||||||
|
if (def_field->default_value &&
|
||||||
|
(def_field->default_value->flags || (def_field->flags & BLOB_FLAG)))
|
||||||
|
{
|
||||||
|
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
|
||||||
|
if (!newptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (should_mark_column(thd->column_usage))
|
||||||
|
def_field->default_value->expr->update_used_tables();
|
||||||
|
def_field->move_field(newptr + 1, def_field->maybe_null() ? newptr : 0, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
def_field->move_field_offset((my_ptrdiff_t)
|
||||||
|
(def_field->table->s->default_values -
|
||||||
|
def_field->table->record[0]));
|
||||||
|
return def_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Item_copy_string
|
Item_copy_string
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -9446,69 +9484,10 @@ bool Item_default_value::update_func_default_processor(void *)
|
|||||||
|
|
||||||
bool Item_default_value::fix_fields(THD *thd, Item **items)
|
bool Item_default_value::fix_fields(THD *thd, Item **items)
|
||||||
{
|
{
|
||||||
Item *real_arg;
|
|
||||||
Item_field *field_arg;
|
|
||||||
Field *def_field;
|
|
||||||
DBUG_ASSERT(fixed == 0);
|
DBUG_ASSERT(fixed == 0);
|
||||||
DBUG_ASSERT(arg);
|
DBUG_ASSERT(arg);
|
||||||
|
|
||||||
/*
|
return tie_field(thd);
|
||||||
DEFAULT() do not need table field so should not ask handler to bring
|
|
||||||
field value (mark column for read)
|
|
||||||
*/
|
|
||||||
enum_column_usage save_column_usage= thd->column_usage;
|
|
||||||
/*
|
|
||||||
Fields which has defult value could be read, so it is better hide system
|
|
||||||
invisible columns.
|
|
||||||
*/
|
|
||||||
thd->column_usage= COLUMNS_WRITE;
|
|
||||||
if (arg->fix_fields_if_needed(thd, &arg))
|
|
||||||
{
|
|
||||||
thd->column_usage= save_column_usage;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
thd->column_usage= save_column_usage;
|
|
||||||
|
|
||||||
real_arg= arg->real_item();
|
|
||||||
if (real_arg->type() != FIELD_ITEM)
|
|
||||||
{
|
|
||||||
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name.str);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
field_arg= (Item_field *)real_arg;
|
|
||||||
if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG))
|
|
||||||
{
|
|
||||||
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0),
|
|
||||||
field_arg->field->field_name.str);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (!(def_field= (Field*) thd->alloc(field_arg->field->size_of())))
|
|
||||||
goto error;
|
|
||||||
memcpy((void *)def_field, (void *)field_arg->field,
|
|
||||||
field_arg->field->size_of());
|
|
||||||
def_field->reset_fields();
|
|
||||||
// If non-constant default value expression or a blob
|
|
||||||
if (def_field->default_value &&
|
|
||||||
(def_field->default_value->flags || (def_field->flags & BLOB_FLAG)))
|
|
||||||
{
|
|
||||||
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
|
|
||||||
if (!newptr)
|
|
||||||
goto error;
|
|
||||||
if (should_mark_column(thd->column_usage))
|
|
||||||
def_field->default_value->expr->update_used_tables();
|
|
||||||
def_field->move_field(newptr+1, def_field->maybe_null() ? newptr : 0, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
def_field->move_field_offset((my_ptrdiff_t)
|
|
||||||
(def_field->table->s->default_values -
|
|
||||||
def_field->table->record[0]));
|
|
||||||
set_field(def_field);
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
error:
|
|
||||||
context->process_error(thd);
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item_default_value::cleanup()
|
void Item_default_value::cleanup()
|
||||||
@ -9696,6 +9675,66 @@ Item *Item_default_value::transform(THD *thd, Item_transformer transformer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Call fix_fields for an item representing the default value, create
|
||||||
|
an instance of Field for representing the default value and assign it
|
||||||
|
to the Item_field::field.
|
||||||
|
|
||||||
|
@param thd thread handler
|
||||||
|
|
||||||
|
@return false on success, true on error
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Item_default_value::tie_field(THD *thd)
|
||||||
|
{
|
||||||
|
Item *real_arg;
|
||||||
|
Item_field *field_arg;
|
||||||
|
Field *def_field;
|
||||||
|
|
||||||
|
/*
|
||||||
|
DEFAULT() do not need table field so should not ask handler to bring
|
||||||
|
field value (mark column for read)
|
||||||
|
*/
|
||||||
|
enum_column_usage save_column_usage= thd->column_usage;
|
||||||
|
/*
|
||||||
|
Fields which has defult value could be read, so it is better hide system
|
||||||
|
invisible columns.
|
||||||
|
*/
|
||||||
|
thd->column_usage= COLUMNS_WRITE;
|
||||||
|
if (arg->fix_fields_if_needed(thd, &arg))
|
||||||
|
{
|
||||||
|
thd->column_usage= save_column_usage;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
thd->column_usage= save_column_usage;
|
||||||
|
|
||||||
|
real_arg= arg->real_item();
|
||||||
|
if (real_arg->type() != FIELD_ITEM)
|
||||||
|
{
|
||||||
|
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name.str);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_arg= (Item_field *)real_arg;
|
||||||
|
if ((field_arg->field->flags & NO_DEFAULT_VALUE_FLAG))
|
||||||
|
{
|
||||||
|
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0),
|
||||||
|
field_arg->field->field_name.str);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
def_field= make_default_field(thd, field_arg->field);
|
||||||
|
if (!def_field)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
set_field(def_field);
|
||||||
|
return false;
|
||||||
|
|
||||||
|
error:
|
||||||
|
context->process_error(thd);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
bool Item_insert_value::eq(const Item *item, bool binary_cmp) const
|
bool Item_insert_value::eq(const Item *item, bool binary_cmp) const
|
||||||
{
|
{
|
||||||
return item->type() == INSERT_VALUE_ITEM &&
|
return item->type() == INSERT_VALUE_ITEM &&
|
||||||
|
@ -6580,6 +6580,9 @@ public:
|
|||||||
Item *transform(THD *thd, Item_transformer transformer, uchar *args);
|
Item *transform(THD *thd, Item_transformer transformer, uchar *args);
|
||||||
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
|
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
|
||||||
const Tmp_field_param *param);
|
const Tmp_field_param *param);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool tie_field(THD *thd);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user