mirror of
https://github.com/MariaDB/server.git
synced 2026-01-06 05:22:24 +03:00
Fix for bug#13479 "REPLACE activates UPDATE trigger, not the DELETE and
INSERT triggers".
In cases when REPLACE was internally executed via update and table had
on update (on delete) triggers defined we exposed the fact that such
optimization used by callng on update (not calling on delete) triggers.
Such behavior contradicts our documentation which describes REPLACE as
INSERT with optional DELETE.
This fix just disables this optimization for tables with on delete triggers.
The optimization is still applied for tables which have on update but have
no on delete triggers, we just don't invoke on update triggers in this case
and thus don't expose information about optimization to user.
Also added test coverage for values returned by ROW_COUNT() function (and
thus for values returned by mysql_affected_rows()) for various forms of
INSERT.
mysql-test/r/insert.result:
Added test for values returned by ROW_COUNT() function (and thus for values
returned by mysql_affected_rows()) for various forms of INSERT. We didn't
have coverage for this before and since this fix touches related code it is
better to add it now.
mysql-test/r/trigger.result:
Adjusted test after fixing bug#13479 "REPLACE activates UPDATE trigger, not
the DELETE and INSERT triggers".
mysql-test/t/insert.test:
Added test for values returned by ROW_COUNT() function (and thus for values
returned by mysql_affected_rows()) for various forms of INSERT. We didn't
have coverage for this before and since this fix touches related code it is
better to add it now.
mysql-test/t/trigger.test:
Adjusted test after fixing bug#13479 "REPLACE activates UPDATE trigger, not
the DELETE and INSERT triggers".
sql/sql_insert.cc:
write_record():
We should not expose that internally we sometimes execute REPLACE
via UPDATE instead of documented INSERT + DELETE pair. So we should not
use this optimization for tables with on delete triggers. OTOH it is ok
to use it for tables which have on update but have no on delete triggers,
we just should not invoke on update triggers in this case.
This commit is contained in:
@@ -1057,16 +1057,19 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
to convert the latter operation internally to an UPDATE.
|
||||
We also should not perform this conversion if we have
|
||||
timestamp field with ON UPDATE which is different from DEFAULT.
|
||||
Another case when conversion should not be performed is when
|
||||
we have ON DELETE trigger on table so user may notice that
|
||||
we cheat here. Note that it is ok to do such conversion for
|
||||
tables which have ON UPDATE but have no ON DELETE triggers,
|
||||
we just should not expose this fact to users by invoking
|
||||
ON UPDATE triggers.
|
||||
*/
|
||||
if (last_uniq_key(table,key_nr) &&
|
||||
!table->file->referenced_by_foreign_key() &&
|
||||
(table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
|
||||
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
|
||||
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) &&
|
||||
(!table->triggers || !table->triggers->has_delete_triggers()))
|
||||
{
|
||||
if (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||
TRG_ACTION_BEFORE, TRUE))
|
||||
goto before_trg_err;
|
||||
if (thd->clear_next_insert_id)
|
||||
{
|
||||
/* Reset auto-increment cacheing if we do an update */
|
||||
@@ -1077,13 +1080,11 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
table->record[0])))
|
||||
goto err;
|
||||
info->deleted++;
|
||||
trg_error= (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||
TRG_ACTION_AFTER,
|
||||
TRUE));
|
||||
/* Update logfile and count */
|
||||
info->copied++;
|
||||
goto ok_or_after_trg_err;
|
||||
/*
|
||||
Since we pretend that we have done insert we should call
|
||||
its after triggers.
|
||||
*/
|
||||
goto after_trg_n_copied_inc;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1107,10 +1108,6 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
}
|
||||
}
|
||||
}
|
||||
info->copied++;
|
||||
trg_error= (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
|
||||
TRG_ACTION_AFTER, TRUE));
|
||||
}
|
||||
else if ((error=table->file->write_row(table->record[0])))
|
||||
{
|
||||
@@ -1118,14 +1115,14 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
||||
(error != HA_ERR_FOUND_DUPP_KEY && error != HA_ERR_FOUND_DUPP_UNIQUE))
|
||||
goto err;
|
||||
table->file->restore_auto_increment();
|
||||
goto ok_or_after_trg_err;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->copied++;
|
||||
trg_error= (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
|
||||
TRG_ACTION_AFTER, TRUE));
|
||||
}
|
||||
|
||||
after_trg_n_copied_inc:
|
||||
info->copied++;
|
||||
trg_error= (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
|
||||
TRG_ACTION_AFTER, TRUE));
|
||||
|
||||
ok_or_after_trg_err:
|
||||
if (key)
|
||||
|
||||
Reference in New Issue
Block a user