diff options
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b5ede32e6fe..110f140afe0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. +/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2010, 2011 Monty Program Ab This program is free software; you can redistribute it and/or modify @@ -217,7 +217,8 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list); static void free_cache_entry(TABLE *entry); static bool has_write_table_with_auto_increment(TABLE_LIST *tables); - +static bool +has_write_table_with_auto_increment_and_select(TABLE_LIST *tables); uint cached_open_tables(void) { @@ -5729,9 +5730,20 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, *(ptr++)= table->table; } + /* + DML statements that modify a table with an auto_increment column based on + rows selected from a table are unsafe as the order in which the rows are + fetched fron the select tables cannot be determined and may differ on + master and slave. + */ + if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && + has_write_table_with_auto_increment_and_select(tables)) + thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT); + /* We have to emulate LOCK TABLES if we are statement needs prelocking. */ if (thd->lex->requires_prelocking()) { + /* A query that modifies autoinc column in sub-statement can make the master and slave inconsistent. @@ -9406,6 +9418,41 @@ has_write_table_with_auto_increment(TABLE_LIST *tables) return 0; } +/* + checks if we have select tables in the table list and write tables + with auto-increment column. + + SYNOPSIS + has_two_write_locked_tables_with_auto_increment_and_select + tables Table list + + RETURN VALUES + + -true if the table list has atleast one table with auto-increment column + + + and atleast one table to select from. + -false otherwise +*/ + +static bool +has_write_table_with_auto_increment_and_select(TABLE_LIST *tables) +{ + bool has_select= false; + bool has_auto_increment_tables = has_write_table_with_auto_increment(tables); + for(TABLE_LIST *table= tables; table; table= table->next_global) + { + if (!table->placeholder() && + (table->lock_type <= TL_READ_NO_INSERT)) + { + has_select= true; + break; + } + } + return(has_select && has_auto_increment_tables); +} + + /* Open and lock system tables for read. |