mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-8605 MariaDB not use DEFAULT value even when inserted NULL for NOT NULLABLE column
NOT NULL constraint must be checked *after* the BEFORE triggers. That is for INSERT and UPDATE statements even NOT NULL fields must be able to store a NULL temporarily at least while BEFORE INSERT/UPDATE triggers are running.
This commit is contained in:
@ -8818,7 +8818,61 @@ err:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
Prepare Item_field's for fill_record_n_invoke_before_triggers()
|
||||
|
||||
This means redirecting from table->field to
|
||||
table->field_to_fill(), if needed.
|
||||
*/
|
||||
void switch_to_nullable_trigger_fields(List<Item> &items, TABLE *table)
|
||||
{
|
||||
Field** field= table->field_to_fill();
|
||||
|
||||
if (field != table->field)
|
||||
{
|
||||
List_iterator_fast<Item> it(items);
|
||||
Item *item;
|
||||
|
||||
while ((item= it++))
|
||||
item->walk(&Item::switch_to_nullable_fields_processor, 1, (uchar*)field);
|
||||
table->triggers->reset_extra_null_bitmap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test NOT NULL constraint after BEFORE triggers
|
||||
*/
|
||||
static bool not_null_fields_have_null_values(TABLE *table)
|
||||
{
|
||||
Field **orig_field= table->field;
|
||||
Field **filled_field= table->field_to_fill();
|
||||
|
||||
if (filled_field != orig_field)
|
||||
{
|
||||
THD *thd=table->in_use;
|
||||
for (uint i=0; i < table->s->fields; i++)
|
||||
{
|
||||
Field *of= orig_field[i];
|
||||
Field *ff= filled_field[i];
|
||||
if (ff != of)
|
||||
{
|
||||
// copy after-update flags to of, copy before-update flags to ff
|
||||
swap_variables(uint32, of->flags, ff->flags);
|
||||
if (ff->is_real_null())
|
||||
{
|
||||
ff->set_notnull(); // for next row WHERE condition in UPDATE
|
||||
if (convert_null_to_field_value_or_error(of) || thd->is_error())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Fill fields in list with values from the list of items and invoke
|
||||
before triggers.
|
||||
|
||||
@ -8846,9 +8900,13 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, List<Item> &fields,
|
||||
{
|
||||
bool result;
|
||||
Table_triggers_list *triggers= table->triggers;
|
||||
result= (fill_record(thd, table, fields, values, ignore_errors) ||
|
||||
(triggers && triggers->process_triggers(thd, event,
|
||||
TRG_ACTION_BEFORE, TRUE)));
|
||||
|
||||
result= fill_record(thd, table, fields, values, ignore_errors);
|
||||
|
||||
if (!result && triggers)
|
||||
result= triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, TRUE) ||
|
||||
not_null_fields_have_null_values(table);
|
||||
|
||||
/*
|
||||
Re-calculate virtual fields to cater for cases when base columns are
|
||||
updated by the triggers.
|
||||
@ -8994,9 +9052,12 @@ fill_record_n_invoke_before_triggers(THD *thd, TABLE *table, Field **ptr,
|
||||
{
|
||||
bool result;
|
||||
Table_triggers_list *triggers= table->triggers;
|
||||
result= (fill_record(thd, table, ptr, values, ignore_errors, FALSE) ||
|
||||
(triggers && triggers->process_triggers(thd, event,
|
||||
TRG_ACTION_BEFORE, TRUE)));
|
||||
|
||||
result= fill_record(thd, table, ptr, values, ignore_errors, FALSE);
|
||||
|
||||
if (!result && triggers && *ptr)
|
||||
result= triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, TRUE) ||
|
||||
not_null_fields_have_null_values(table);
|
||||
/*
|
||||
Re-calculate virtual fields to cater for cases when base columns are
|
||||
updated by the triggers.
|
||||
|
Reference in New Issue
Block a user