From 2efc0f51cf3e80cd49c1ea0dee9a440936ee6287 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 4 Apr 2007 12:50:39 +0200 Subject: Bug #26242 UPDATE with subquery and triggers failing with cluster tables In certain cases AFTER UPDATE/DELETE triggers on NDB tables that referenced subject table didn't see the results of operation which caused invocation of those triggers. In other words AFTER trigger invoked as result of update (or deletion) of particular row saw version of this row before update (or deletion). The problem occured because NDB handler in those cases postponed actual update/delete operations to be able to perform them later as one batch. This fix solves the problem by disabling this optimization for particular operation if subject table has AFTER trigger for this operation defined. To achieve this we introduce two new flags for handler::extra() method: HA_EXTRA_DELETE_CANNOT_BATCH and HA_EXTRA_UPDATE_CANNOT_BATCH. These are called if there exists AFTER DELETE/UPDATE triggers during a statement that potentially can generate calls to delete_row()/update_row(). This includes multi_delete/multi_update statements as well as insert statements that do delete/update as part of an ON DUPLICATE statement. include/my_base.h: Added HA_EXTRA_DELETE_CANNOT_BATCH and HA_EXTRA_UPDATE_CANNOT_BATCH to inform handler when batching of delete/update is not possible. mysql-test/r/ndb_trigger.result: Bug #26242 UPDATE with subquery and triggers failing with cluster tables --- Added new test cases mysql-test/t/ndb_trigger.test: Bug #26242 UPDATE with subquery and triggers failing with cluster tables --- Added new test cases sql/ha_ndbcluster.cc: Bug #26242 UPDATE with subquery and triggers failing with cluster tables: Use HA_EXTRA_DELETE_CANNOT_BATCH and HA_EXTRA_UPDATE_CANNOT_BATCH to inform handler when batching of delete/update is not possible sql/ha_ndbcluster.h: Bug #26242 UPDATE with subquery and triggers failing with cluster tables: Added member variables for handling of HA_EXTRA_DELETE_CANNOT_BATCH and HA_EXTRA_UPDATE_CANNOT_BATCH to inform handler when batching of delete/update is not possible sql/mysql_priv.h: Added new method prepare_triggers_for_insert_stmt to check if batching of delete/update must be disallowed. sql/sql_delete.cc: Use HA_EXTRA_DELETE_CANNOT_BATCH to inform handler when batching of delete is not possible sql/sql_insert.cc: Added method prepare_triggers_for_insert_stmt to check if batching of delete/update must be dissallowed. Use HA_EXTRA_DELETE_CANNOT_BATCH and HA_EXTRA_UPDATE_CANNOT_BATCH to inform handler when batching of delete/update is not possible sql/sql_load.cc: Call prepare_triggers_for_insert_stmt to check if batching of delete/update must be dissallowed and mark fields used by triggers for the insert statement. sql/sql_trigger.h: Added has_triggers to support what particular triggers exist on a table. sql/sql_update.cc: Use HA_EXTRA_UPDATE_CANNOT_BATCH to inform handler when batching of update is not possible --- sql/sql_update.cc | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'sql/sql_update.cc') diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d431b671f18..8ec4fcbbc4d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -435,7 +435,19 @@ int mysql_update(THD *thd, MODE_STRICT_ALL_TABLES))); if (table->triggers) + { table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE); + if (table->triggers->has_triggers(TRG_EVENT_UPDATE, + TRG_ACTION_AFTER)) + { + /* + The table has AFTER UPDATE triggers that might access to subject + table and therefore might need update to be done immediately. + So we turn-off the batching. + */ + (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH); + } + } /* We can use compare_record() to optimize away updates if @@ -1000,6 +1012,20 @@ int multi_update::prepare(List ¬_used_values, table->no_keyread=1; table->used_keys.clear_all(); table->pos_in_table_list= tl; + if (table->triggers) + { + table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE); + if (table->triggers->has_triggers(TRG_EVENT_UPDATE, + TRG_ACTION_AFTER)) + { + /* + The table has AFTER UPDATE triggers that might access to subject + table and therefore might need update to be done immediately. + So we turn-off the batching. + */ + (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH); + } + } } } -- cgit v1.2.1