Commit cf003933 authored by Sergei Golubchik's avatar Sergei Golubchik

Race condition in DEFAULT() with expressions

Item_default_value::calculate was updating table->s->default_values,
but it is supposed to be read-only
parent cd4dd2b6
create table t1 (a int, b int default (a+1));
insert t1 values (1,10), (2,20), (3,30);
connect con1, localhost, root;
select a,b,default(b) from t1;
a b default(b)
1 10 2
2 20 3
3 30 4
set debug_sync='after_Item_default_value_calculate WAIT_FOR go';
select a,b,default(b) from t1;
connection default;
set debug_sync='ha_write_row_start SIGNAL go';
insert t1 values (100,default(b));
connection con1;
a b default(b)
1 10 2
2 20 3
3 30 4
connection default;
drop table t1;
set debug_sync='RESET';
#
# Race condition in DEFAULT() with expressions
#
source include/have_debug_sync.inc;
create table t1 (a int, b int default (a+1));
insert t1 values (1,10), (2,20), (3,30);
connect (con1, localhost, root);
select a,b,default(b) from t1;
set debug_sync='after_Item_default_value_calculate WAIT_FOR go';
send select a,b,default(b) from t1;
connection default;
set debug_sync='ha_write_row_start SIGNAL go';
insert t1 values (100,default(b));
connection con1;
reap;
connection default;
drop table t1;
set debug_sync='RESET';
......@@ -8758,17 +8758,22 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
goto error;
memcpy((void *)def_field, (void *)field_arg->field,
field_arg->field->size_of());
def_field->move_field_offset((my_ptrdiff_t)
(def_field->table->s->default_values -
def_field->table->record[0]));
set_field(def_field);
if (field->default_value)
IF_DBUG(def_field->is_stat_field=1,); // a hack to fool ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED
if (def_field->default_value && def_field->default_value->flags)
{
fix_session_vcol_expr_for_read(thd, field, field->default_value);
uchar *newptr= (uchar*) thd->alloc(1+def_field->pack_length());
if (!newptr)
goto error;
fix_session_vcol_expr_for_read(thd, def_field, def_field->default_value);
if (thd->mark_used_columns != MARK_COLUMNS_NONE)
field->default_value->expr->walk(&Item::register_field_in_read_map, 1, 0);
IF_DBUG(def_field->is_stat_field=1,); // a hack to fool ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED
def_field->default_value->expr->walk(&Item::register_field_in_read_map, 1, 0);
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:
......@@ -8793,6 +8798,7 @@ void Item_default_value::calculate()
{
if (field->default_value)
field->set_default();
DEBUG_SYNC(field->table->in_use, "after_Item_default_value_calculate");
}
String *Item_default_value::val_str(String *str)
......
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