diff options
author | He Zhenxing <zhenxing.he@sun.com> | 2009-03-05 18:10:44 +0800 |
---|---|---|
committer | He Zhenxing <zhenxing.he@sun.com> | 2009-03-05 18:10:44 +0800 |
commit | b4fdb8aec14b533db4a5ea2f99c1a9f3ce07946c (patch) | |
tree | c6ec33b757dfff8d69335ab97419c2842f1f61cb /sql/sql_parse.cc | |
parent | 62d5d85c5d19b113b772ecadbf32f198831b543b (diff) | |
download | mariadb-git-b4fdb8aec14b533db4a5ea2f99c1a9f3ce07946c.tar.gz |
BUG#37051 Replication rules not evaluated correctly
Backporting patch to 5.0.
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1d3632fd468..dafe4baa9e5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2584,6 +2584,10 @@ mysql_execute_command(THD *thd) TABLE_LIST *all_tables; /* most outer SELECT_LEX_UNIT of query */ SELECT_LEX_UNIT *unit= &lex->unit; +#ifdef HAVE_REPLICATION + /* have table map for update for multi-update statement (BUG#37051) */ + bool have_table_map_for_update= FALSE; +#endif /* Saved variable value */ DBUG_ENTER("mysql_execute_command"); thd->net.no_send_error= 0; @@ -2663,6 +2667,48 @@ mysql_execute_command(THD *thd) // force searching in slave.cc:tables_ok() all_tables->updating= 1; } + + /* + For fix of BUG#37051, the master stores the table map for update + in the Query_log_event, and the value is assigned to + thd->variables.table_map_for_update before executing the update + query. + + If thd->variables.table_map_for_update is set, then we are + replicating from a new master, we can use this value to apply + filter rules without opening all the tables. However If + thd->variables.table_map_for_update is not set, then we are + replicating from an old master, so we just skip this and + continue with the old method. And of course, the bug would still + exist for old masters. + */ + if (lex->sql_command == SQLCOM_UPDATE_MULTI && + thd->table_map_for_update) + { + have_table_map_for_update= TRUE; + table_map table_map_for_update= thd->table_map_for_update; + uint nr= 0; + TABLE_LIST *table; + for (table=all_tables; table; table=table->next_global, nr++) + { + if (table_map_for_update & ((table_map)1 << nr)) + table->updating= TRUE; + else + table->updating= FALSE; + } + + if (all_tables_not_ok(thd, all_tables)) + { + /* we warn the slave SQL thread */ + my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); + if (thd->one_shot_set) + reset_one_shot_variables(thd); + DBUG_RETURN(0); + } + + for (table=all_tables; table; table=table->next_global) + table->updating= TRUE; + } /* Check if statment should be skipped because of slave filtering @@ -3608,7 +3654,7 @@ end_with_restore_list: #ifdef HAVE_REPLICATION /* Check slave filtering rules */ - if (unlikely(thd->slave_thread)) + if (unlikely(thd->slave_thread && !have_table_map_for_update)) { if (all_tables_not_ok(thd, all_tables)) { |