Commit 6b368824 authored by Michael Widenius's avatar Michael Widenius

Switch automaticly to statement based replication for statements that can't...

Switch automaticly to statement based replication for statements that can't generate row based events. This is needed to avoid getting
updates to system, statistics and admin tables logged to binary log.
- Removed special code used to temporarily change to statement based replication.
- Changed to a faster and smaller interface for temporarily switching to statement based replication.

sql/event_db_repository.cc:
  Change to new interface to not use row based replication for system table changes.
sql/events.cc:
  Change to new interface to not use row based replication for system table changes.
sql/sp.cc:
  Removed temporarily switching to statement based replication (this is now done automaticly in mysql_execute_command())
sql/sql_acl.cc:
  Change to new interface to not use row based replication for system table changes.
  Removed temporarily switching to statement based replication (this is now done automaticly in mysql_execute_command())
sql/sql_class.h:
  Added new interface for temporarily switching to statement based replication.
sql/sql_parse.cc:
  Mark commands that needs original replication mode with CF_FORCE_ORIGINAL_BINLOG_FORMAT.
  Switch automaticly to statement based replication for statements that can't generate row based events (and can't change replication mode)
sql/sql_udf.cc:
  Removed temporarily switching to statement based replication (this is now done automaticly in mysql_execute_command())
parent 73cbecac
......@@ -1112,17 +1112,15 @@ update_timing_fields_for_event(THD *thd,
TABLE *table= NULL;
Field **fields;
int ret= 1;
bool save_binlog_row_based;
enum_binlog_format save_binlog_format;
MYSQL_TIME time;
DBUG_ENTER("Event_db_repository::update_timing_fields_for_event");
/*
Turn off row binlogging of event timing updates. These are not used
for RBR of events replicated to the slave.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL);
......@@ -1157,10 +1155,7 @@ update_timing_fields_for_event(THD *thd,
if (table)
close_mysql_tables(thd);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(test(ret));
}
......
......@@ -306,7 +306,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
bool if_not_exists)
{
bool ret;
bool save_binlog_row_based, event_already_exists;
bool event_already_exists;
enum_binlog_format save_binlog_format;
DBUG_ENTER("Events::create_event");
if (check_if_system_tables_error())
......@@ -338,8 +339,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for CREATE EVENT command.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
if (lock_object_name(thd, MDL_key::EVENT,
parse_data->dbname.str, parse_data->name.str))
......@@ -398,10 +398,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
}
}
}
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
}
......@@ -431,7 +429,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
LEX_STRING *new_dbname, LEX_STRING *new_name)
{
int ret;
bool save_binlog_row_based;
enum_binlog_format save_binlog_format;
Event_queue_element *new_element;
DBUG_ENTER("Events::update_event");
......@@ -478,8 +476,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for UPDATE EVENT command.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
if (lock_object_name(thd, MDL_key::EVENT,
parse_data->dbname.str, parse_data->name.str))
......@@ -513,11 +510,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
}
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
}
......@@ -550,7 +544,7 @@ bool
Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
{
int ret;
bool save_binlog_row_based;
enum_binlog_format save_binlog_format;
DBUG_ENTER("Events::drop_event");
if (check_if_system_tables_error())
......@@ -563,8 +557,7 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
Turn off row binlogging of this statement and use statement-based so
that all supporting tables are updated for DROP EVENT command.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
if (lock_object_name(thd, MDL_key::EVENT,
dbname.str, name.str))
......@@ -578,10 +571,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
DBUG_ASSERT(thd->query() && thd->query_length());
ret= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
}
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(ret);
}
......
......@@ -984,9 +984,6 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
enum_check_fields saved_count_cuted_fields;
bool store_failed= FALSE;
bool save_binlog_row_based;
DBUG_ENTER("sp_create_routine");
DBUG_PRINT("enter", ("type: %d name: %.*s", (int) type,
(int) sp->m_name.length,
......@@ -1004,14 +1001,6 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
/* Reset sql_mode during data dictionary operations. */
thd->variables.sql_mode= 0;
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
saved_count_cuted_fields= thd->count_cuted_fields;
thd->count_cuted_fields= CHECK_FIELD_WARN;
......@@ -1217,10 +1206,7 @@ sp_create_routine(THD *thd, stored_procedure_type type, sp_head *sp)
done:
thd->count_cuted_fields= saved_count_cuted_fields;
thd->variables.sql_mode= saved_mode;
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(ret);
}
......@@ -1245,7 +1231,6 @@ sp_drop_routine(THD *thd, stored_procedure_type type, sp_name *name)
{
TABLE *table;
int ret;
bool save_binlog_row_based;
MDL_key::enum_mdl_namespace mdl_type= type == TYPE_ENUM_FUNCTION ?
MDL_key::FUNCTION : MDL_key::PROCEDURE;
DBUG_ENTER("sp_drop_routine");
......@@ -1267,9 +1252,6 @@ sp_drop_routine(THD *thd, stored_procedure_type type, sp_name *name)
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
{
if (table->file->ha_delete_row(table->record[0]))
......@@ -1296,10 +1278,7 @@ sp_drop_routine(THD *thd, stored_procedure_type type, sp_name *name)
sp_cache_flush_obsolete(spc, &sp);
}
}
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(ret);
}
......@@ -1327,7 +1306,6 @@ sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
{
TABLE *table;
int ret;
bool save_binlog_row_based;
MDL_key::enum_mdl_namespace mdl_type= type == TYPE_ENUM_FUNCTION ?
MDL_key::FUNCTION : MDL_key::PROCEDURE;
DBUG_ENTER("sp_update_routine");
......@@ -1345,14 +1323,6 @@ sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
if (!(table= open_proc_table_for_update(thd)))
DBUG_RETURN(SP_OPEN_TABLE_FAILED);
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
if ((ret= db_find_routine_aux(thd, type, name, table)) == SP_OK)
{
if (type == TYPE_ENUM_FUNCTION && ! trust_function_creators &&
......@@ -1406,10 +1376,7 @@ sp_update_routine(THD *thd, stored_procedure_type type, sp_name *name,
sp_cache_invalidate();
}
err:
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(ret);
}
......
......@@ -1877,7 +1877,7 @@ bool change_password(THD *thd, const char *host, const char *user,
/* Buffer should be extended when password length is extended. */
char buff[512];
ulong query_length;
bool save_binlog_row_based;
enum_binlog_format save_binlog_format;
uint new_password_len= (uint) strlen(new_password);
bool result= 1;
DBUG_ENTER("change_password");
......@@ -1914,9 +1914,10 @@ bool change_password(THD *thd, const char *host, const char *user,
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
This has to be handled here as it's called by set_var.cc, which is
not automaticly handled by sql_parse.cc
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
save_binlog_format= thd->set_current_stmt_binlog_format_stmt();
mysql_mutex_lock(&acl_cache->lock);
ACL_USER *acl_user;
......@@ -1965,11 +1966,7 @@ bool change_password(THD *thd, const char *host, const char *user,
}
end:
close_mysql_tables(thd);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
thd->restore_stmt_binlog_format(save_binlog_format);
DBUG_RETURN(result);
}
......@@ -3540,7 +3537,6 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
TABLE_LIST tables[3];
bool create_new_users=0;
char *db_name, *table_name;
bool save_binlog_row_based;
DBUG_ENTER("mysql_table_grant");
if (!initialized)
......@@ -3630,14 +3626,6 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (column_priv || (revoke_grant && ((rights & COL_ACLS) || columns.elements)))
tables[1].next_local= tables[1].next_global= tables+2;
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
......@@ -3651,13 +3639,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
*/
tables[0].updating= tables[1].updating= tables[2].updating= 1;
if (!(thd->spcont || rpl_filter->tables_ok(0, tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(FALSE);
}
}
#endif
......@@ -3675,11 +3657,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
thd->lex->sql_command= backup.sql_command;
if (open_and_lock_tables(thd, tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
{ // Should never happen
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
thd->lex->restore_backup_query_tables_list(&backup);
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(TRUE); /* purecov: deadcode */
}
......@@ -3807,9 +3785,6 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
/* Tables are automatically closed */
thd->lex->restore_backup_query_tables_list(&backup);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result);
}
......@@ -3838,7 +3813,6 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
TABLE_LIST tables[2];
bool create_new_users=0, result=0;
char *db_name, *table_name;
bool save_binlog_row_based;
DBUG_ENTER("mysql_routine_grant");
if (!initialized)
......@@ -3868,14 +3842,6 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
C_STRING_WITH_LEN("procs_priv"), "procs_priv", TL_WRITE);
tables[0].next_local= tables[0].next_global= tables+1;
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
......@@ -3890,23 +3856,15 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
tables[0].updating= tables[1].updating= 1;
if (!(thd->spcont || rpl_filter->tables_ok(0, tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(FALSE);
}
}
#endif
if (open_and_lock_tables(thd, tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
{ // Should never happen
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(TRUE);
}
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
......@@ -3981,10 +3939,6 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc,
}
mysql_rwlock_unlock(&LOCK_grant);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
/* Tables are automatically closed */
DBUG_RETURN(result);
......@@ -3999,8 +3953,8 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
char tmp_db[SAFE_NAME_LEN+1];
bool create_new_users=0;
TABLE_LIST tables[2];
bool save_binlog_row_based;
DBUG_ENTER("mysql_grant");
if (!initialized)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
......@@ -4037,14 +3991,6 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
TL_WRITE);
tables[0].next_local= tables[0].next_global= tables+1;
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
#ifdef HAVE_REPLICATION
/*
GRANT and REVOKE are applied the slave in/exclusion rules as they are
......@@ -4058,24 +4004,14 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
*/
tables[0].updating= tables[1].updating= 1;
if (!(thd->spcont || rpl_filter->tables_ok(0, tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(FALSE);
}
}
#endif
if (open_and_lock_tables(thd, tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
{ // This should never happen
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(TRUE); /* purecov: deadcode */
}
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
......@@ -4139,10 +4075,6 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
if (!result)
my_ok(thd);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result);
}
......@@ -6453,26 +6385,11 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
List_iterator <LEX_USER> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
bool some_users_created= FALSE;
bool save_binlog_row_based;
DBUG_ENTER("mysql_create_user");
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
/* CREATE USER may be skipped on replication client. */
if ((result= open_grant_tables(thd, tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result != 1);
}
mysql_rwlock_wrlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock);
......@@ -6513,10 +6430,6 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list)
result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
mysql_rwlock_unlock(&LOCK_grant);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result);
}
......@@ -6543,26 +6456,11 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
TABLE_LIST tables[GRANT_TABLES];
bool some_users_deleted= FALSE;
ulonglong old_sql_mode= thd->variables.sql_mode;
bool save_binlog_row_based;
DBUG_ENTER("mysql_drop_user");
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
/* DROP USER may be skipped on replication client. */
if ((result= open_grant_tables(thd, tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result != 1);
}
thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
......@@ -6598,10 +6496,6 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
mysql_rwlock_unlock(&LOCK_grant);
thd->variables.sql_mode= old_sql_mode;
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result);
}
......@@ -6628,26 +6522,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
List_iterator <LEX_USER> user_list(list);
TABLE_LIST tables[GRANT_TABLES];
bool some_users_renamed= FALSE;
bool save_binlog_row_based;
DBUG_ENTER("mysql_rename_user");
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
/* RENAME USER may be skipped on replication client. */
if ((result= open_grant_tables(thd, tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result != 1);
}
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
mysql_rwlock_wrlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock);
......@@ -6693,10 +6574,6 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
mysql_rwlock_unlock(&LOCK_grant);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result);
}
......@@ -6721,25 +6598,12 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
int result;
ACL_DB *acl_db;
TABLE_LIST tables[GRANT_TABLES];
bool save_binlog_row_based;
DBUG_ENTER("mysql_revoke_all");
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
if ((result= open_grant_tables(thd, tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result != 1);
}
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
mysql_rwlock_wrlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock);
......@@ -6890,10 +6754,6 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
write_bin_log(thd, FALSE, thd->query(), thd->query_length());
mysql_rwlock_unlock(&LOCK_grant);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(result);
}
......@@ -6985,26 +6845,19 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
TABLE_LIST tables[GRANT_TABLES];
HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash;
Silence_routine_definer_errors error_handler;
bool save_binlog_row_based;
DBUG_ENTER("sp_revoke_privileges");
if ((result= open_grant_tables(thd, tables)))
DBUG_RETURN(result != 1);
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
/* Be sure to pop this before exiting this scope! */
thd->push_internal_handler(&error_handler);
mysql_rwlock_wrlock(&LOCK_grant);
mysql_mutex_lock(&acl_cache->lock);
/*
This statement will be replicated as a statement, even when using
row-based replication. The flag will be reset at the end of the
statement.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
/* Remove procedure access */
do
{
......@@ -7038,10 +6891,6 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name,
mysql_rwlock_unlock(&LOCK_grant);
thd->pop_internal_handler();
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(error_handler.has_errors());
}
......
......@@ -2722,6 +2722,27 @@ class THD :public Statement,
void set_n_backup_active_arena(Query_arena *set, Query_arena *backup);
void restore_active_arena(Query_arena *set, Query_arena *backup);
inline void get_binlog_format(enum_binlog_format *format,
enum_binlog_format *current_format)
{
*format= (enum_binlog_format) variables.binlog_format;
*current_format= current_stmt_binlog_format;
}
inline void set_binlog_format(enum_binlog_format format,
enum_binlog_format current_format)
{
DBUG_ENTER("set_binlog_format");
variables.binlog_format= format;
current_stmt_binlog_format= current_format;
DBUG_VOID_RETURN;
}
inline void set_binlog_format_stmt()
{
DBUG_ENTER("set_binlog_format_stmt");
variables.binlog_format= BINLOG_FORMAT_STMT;
current_stmt_binlog_format= BINLOG_FORMAT_STMT;
DBUG_VOID_RETURN;
}
/*
@todo Make these methods private or remove them completely. Only
decide_logging_format should call them. /Sven
......@@ -2752,16 +2773,26 @@ class THD :public Statement,
DBUG_VOID_RETURN;
}
inline void set_current_stmt_binlog_format_row()
{
DBUG_ENTER("set_current_stmt_binlog_format_row");
current_stmt_binlog_format= BINLOG_FORMAT_ROW;
DBUG_VOID_RETURN;
}
inline void clear_current_stmt_binlog_format_row()
/* Set binlog format temporarily to statement. Returns old format */
inline enum_binlog_format set_current_stmt_binlog_format_stmt()
{
DBUG_ENTER("clear_current_stmt_binlog_format_row");
enum_binlog_format orig_format= current_stmt_binlog_format;
DBUG_ENTER("set_current_stmt_binlog_format_stmt");
current_stmt_binlog_format= BINLOG_FORMAT_STMT;
DBUG_RETURN(orig_format);
}
inline void restore_stmt_binlog_format(enum_binlog_format format)
{
DBUG_ENTER("restore_stmt_binlog_format");
DBUG_ASSERT(!is_current_stmt_binlog_format_row());
current_stmt_binlog_format= format;
DBUG_VOID_RETURN;
}
inline void reset_current_stmt_binlog_format_row()
......@@ -2791,7 +2822,7 @@ class THD :public Statement,
if (variables.binlog_format == BINLOG_FORMAT_ROW)
set_current_stmt_binlog_format_row();
else if (temporary_tables == NULL)
clear_current_stmt_binlog_format_row();
set_current_stmt_binlog_format_stmt();
}
DBUG_VOID_RETURN;
}
......@@ -4085,6 +4116,11 @@ class select_dumpvar :public select_result_interceptor {
*/
#define CF_CAN_GENERATE_ROW_EVENTS (1U << 9)
/**
Statement that need the binlog format to be unchanged.
*/
#define CF_FORCE_ORIGINAL_BINLOG_FORMAT (1U << 10)
/* Bits in server_command_flags */
/**
......
......@@ -350,7 +350,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_BINLOG_BASE64_EVENT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_BINLOG_BASE64_EVENT]= CF_STATUS_COMMAND | CF_CAN_GENERATE_ROW_EVENTS;
sql_command_flags[SQLCOM_SHOW_CLIENT_STATS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_USER_STATS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_TABLE_STATS]= CF_STATUS_COMMAND;
......@@ -385,6 +385,19 @@ void init_update_queries(void)
CF_CAN_GENERATE_ROW_EVENTS;
sql_command_flags[SQLCOM_EXECUTE]= CF_CAN_GENERATE_ROW_EVENTS;
/*
We don't want to change to statement based replication for these commands
*/
sql_command_flags[SQLCOM_ROLLBACK]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* We don't want to replicate ALTER TABLE for temp tables in row format */
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* We don't want to replicate TRUNCATE for temp tables in row format */
sql_command_flags[SQLCOM_TRUNCATE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* We don't want to replicate DROP for temp tables in row format */
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/* One can change replication mode with SET */
sql_command_flags[SQLCOM_SET_OPTION]|= CF_FORCE_ORIGINAL_BINLOG_FORMAT;
/*
The following admin table operations are allowed
on log tables.
......@@ -2102,6 +2115,22 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(thd->transaction.stmt.modified_non_trans_table == FALSE);
/* store old value of binlog format */
enum_binlog_format orig_binlog_format,orig_current_stmt_binlog_format;
thd->get_binlog_format(&orig_binlog_format,
&orig_current_stmt_binlog_format);
/*
Force statement logging for DDL commands to allow us to update
privilege, system or statistic tables directly without the updates
getting logged.
*/
if (!(sql_command_flags[lex->sql_command] &
(CF_CAN_GENERATE_ROW_EVENTS | CF_FORCE_ORIGINAL_BINLOG_FORMAT |
CF_STATUS_COMMAND)))
thd->set_binlog_format_stmt();
/*
End a active transaction so that this command will have it's
own transaction and will also sync the binary log. If a DDL is
......@@ -4529,6 +4558,11 @@ case SQLCOM_PREPARE:
if (lex->sql_command != SQLCOM_SET_OPTION && ! thd->in_sub_stmt)
DEBUG_SYNC(thd, "execute_command_after_close_tables");
#endif
if (!(sql_command_flags[lex->sql_command] &
(CF_CAN_GENERATE_ROW_EVENTS | CF_FORCE_ORIGINAL_BINLOG_FORMAT |
CF_STATUS_COMMAND)))
thd->set_binlog_format(orig_binlog_format,
orig_current_stmt_binlog_format);
if (stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END))
{
......
......@@ -428,7 +428,6 @@ int mysql_create_function(THD *thd,udf_func *udf)
TABLE *table;
TABLE_LIST tables;
udf_func *u_d;
bool save_binlog_row_based;
DBUG_ENTER("mysql_create_function");
if (!initialized)
......@@ -459,13 +458,6 @@ int mysql_create_function(THD *thd,udf_func *udf)
DBUG_RETURN(1);
}
/*
Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for CREATE FUNCTION command.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
mysql_rwlock_wrlock(&THR_LOCK_udf);
if ((my_hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length)))
{
......@@ -533,27 +525,14 @@ int mysql_create_function(THD *thd,udf_func *udf)
/* Binlog the create function. */
if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(1);
}
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(0);
err:
if (new_dl)
dlclose(dl);
mysql_rwlock_unlock(&THR_LOCK_udf);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(1);
}
......@@ -565,7 +544,6 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
udf_func *udf;
char *exact_name_str;
uint exact_name_len;
bool save_binlog_row_based;
DBUG_ENTER("mysql_drop_function");
if (!initialized)
......@@ -577,13 +555,6 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
DBUG_RETURN(1);
}
/*
Turn off row binlogging of this statement and use statement-based
so that all supporting tables are updated for DROP FUNCTION command.
*/
if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
thd->clear_current_stmt_binlog_format_row();
mysql_rwlock_wrlock(&THR_LOCK_udf);
if (!(udf=(udf_func*) my_hash_search(&udf_hash,(uchar*) udf_name->str,
(uint) udf_name->length)))
......@@ -623,24 +594,12 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
while binlogging, to avoid binlog inconsistency.
*/
if (write_bin_log(thd, TRUE, thd->query(), thd->query_length()))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(1);
}
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(0);
err:
mysql_rwlock_unlock(&THR_LOCK_udf);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(1);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment