summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc75
1 files changed, 68 insertions, 7 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1ab496325a8..b05bbfaead6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -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.