1
0
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:
Sergei Golubchik
2015-11-14 22:51:54 +01:00
parent ad5db17e88
commit 0686c34d22
22 changed files with 898 additions and 85 deletions

View File

@ -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.