4049 magnus.blaudd@stripped 2012-06-21 [merge]
Merge trunk-wl6004 -> trunk
modified:
mysql-test/r/flush_read_lock.result
mysql-test/t/flush_read_lock.test
sql/event_db_repository.cc
sql/sql_acl.cc
sql/sql_acl.h
4048 Dmitry Lenev 2012-06-21
Fix for bug #14156617 "INPLACE ALTER: NOT SUPPORTED ALTER TABLE ...
ADD PARTITION CAUSES CRASH".
Attempt to add a new partition to a partitioned NDB table led to crash
due to debug assertion in server built from mysql-trunk-cluster tree.
This also caused ndb_partition_range test failures in this tree.
The assertion failure occurred due to fact that prep_alter_part_table()
has added new partition partition_info object for TABLE instance
representing old version of table. Since NDB tables do not support
"fast" changes of partitioning, after that we tried to carry out
ALTER TABLE by copying data from old version of table to the new
version. As in the process we tried to use TABLE object with modified
partition_info for reading data, which resulted in assertion failure
due to discrepancy between real table structure and its description
in partition_info.
This patch solves the problem by ensuring that we don't modify
partition_info object for TABLE instances representing old version
of table in cases when "fast" changes of partitioning is not going
to be used. Instead we create a copy of partition_info, adjust it
and use for .FRM/.PAR files creation. Unfortunately we can't easily
use this copy in all cases, since current "fast" partitioning API
assumes that changes to partitioning are communicated to it through
TABLE::part_info object.
There is no test case as bug is not repeatable without NDB (and
thus not repeatable in trunk) and mysql-trunk-cluster tree already
contains ndb_partition_range.test which provides test coverage for
this bug.
modified:
sql/sql_partition.cc
=== modified file 'mysql-test/r/flush_read_lock.result'
--- a/mysql-test/r/flush_read_lock.result 2012-05-15 03:49:03 +0000
+++ b/mysql-test/r/flush_read_lock.result 2012-06-20 09:19:32 +0000
@@ -384,9 +384,11 @@ Success: FTWRL is blocked when 'create e
#
# 8.9) CREATE USER should be incompatible with FTWRL.
#
+# Skip last part of testing as this statement does
+# implicit commit and releases metadata locks in
+# non-standard place.
Success: Was not able to run 'create user mysqltest_u1' under FTWRL.
Success: 'create user mysqltest_u1' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'create user mysqltest_u1' is active in another connection.
#
# 8.x) The rest of CREATE variants (CREATE LOGFILE GROUP,
# CREATE TABLESPACE and CREATE SERVER) are too special
@@ -578,23 +580,28 @@ Success: FTWRL is blocked when 'drop dat
#
# 13.4) DROP FUNCTION is incompatible with FTWRL.
#
+# Skip last part of testing as this statement does
+# implicit commit and releases metadata locks in
+# non-standard place.
Success: Was not able to run 'drop function f1' under FTWRL.
Success: 'drop function f1' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'drop function f1' is active in another connection.
#
# 13.5) DROP PROCEDURE is incompatible with FTWRL.
#
+# Skip last part of testing as this statement does
+# implicit commit and releases metadata locks in
+# non-standard place.
Success: Was not able to run 'drop procedure p1' under FTWRL.
Success: 'drop procedure p1' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'drop procedure p1' is active in another connection.
#
# 13.6) DROP USER should be incompatible with FTWRL.
#
create user mysqltest_u1;
+# Skip last part of testing as this statement does
+# implicit commit and releases metadata locks in
+# non-standard place.
Success: Was not able to run 'drop user mysqltest_u1' under FTWRL.
Success: 'drop user mysqltest_u1' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'drop user mysqltest_u1' is active in another connection.
-drop user mysqltest_u1;
#
# 13.7) DROP VIEW should be incompatible with FTWRL.
#
@@ -695,9 +702,11 @@ Success: Was able to run FTWRL while 'fl
#
# 15) GRANT statement should be incompatible with FTWRL.
#
+# Skip last part of testing as this statement does
+# implicit commit and releases metadata locks in
+# non-standard place.
Success: Was not able to run 'grant all privileges on t1_base to mysqltest_u1' under FTWRL.
Success: 'grant all privileges on t1_base to mysqltest_u1' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'grant all privileges on t1_base to mysqltest_u1' is active in another connection.
drop user mysqltest_u1;
#
# 16) All HANDLER variants are half-compatible with FTWRL.
@@ -997,9 +1006,11 @@ Success: FTWRL is blocked when 'rename t
#
# 26.2) RENAME USER is incompatible with FTWRL.
create user mysqltest_u1;
+# Skip last part of testing as this statement does
+# implicit commit and releases metadata locks in
+# non-standard place.
Success: Was not able to run 'rename user mysqltest_u1 to mysqltest_u2' under FTWRL.
Success: 'rename user mysqltest_u1 to mysqltest_u2' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'rename user mysqltest_u1 to mysqltest_u2' is active in another connection.
drop user mysqltest_u1;
#
# 27) REPAIR TABLE statement.
@@ -1060,14 +1071,18 @@ Success: Was able to run FTWRL while 're
#
# 29.1) REVOKE privileges is incompatible with FTWRL.
grant all privileges on t1_base to mysqltest_u1;
+# Skip last part of testing as this statement does
+# implicit commit and releases metadata locks in
+# non-standard place.
Success: Was not able to run 'revoke all privileges on t1_base from mysqltest_u1' under FTWRL.
Success: 'revoke all privileges on t1_base from mysqltest_u1' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'revoke all privileges on t1_base from mysqltest_u1' is active in another connection.
#
# 29.2) REVOKE ALL PRIVILEGES, GRANT OPTION is incompatible with FTWRL.
+# Skip last part of testing as this statement does
+# implicit commit and releases metadata locks in
+# non-standard place.
Success: Was not able to run 'revoke all privileges, grant option from mysqltest_u1' under FTWRL.
Success: 'revoke all privileges, grant option from mysqltest_u1' is blocked by FTWRL active in another connection.
-Success: FTWRL is blocked when 'revoke all privileges, grant option from mysqltest_u1' is active in another connection.
drop user mysqltest_u1;
#
# 30) Compatibility of SELECT statement with FTWRL depends on
=== modified file 'mysql-test/t/flush_read_lock.test'
--- a/mysql-test/t/flush_read_lock.test 2012-02-01 11:43:43 +0000
+++ b/mysql-test/t/flush_read_lock.test 2012-06-20 09:19:32 +0000
@@ -496,7 +496,12 @@ let $cleanup_stmt1= drop event e2;
--echo #
let $statement= create user mysqltest_u1;
let $cleanup_stmt1= drop user mysqltest_u1;
+--echo # Skip last part of testing as this statement does
+--echo # implicit commit and releases metadata locks in
+--echo # non-standard place.
+let $skip_3rd_check= 1;
--source include/check_ftwrl_incompatible.inc
+let $skip_3rd_check= ;
--echo #
--echo # 8.x) The rest of CREATE variants (CREATE LOGFILE GROUP,
@@ -749,14 +754,24 @@ let $cleanup_stmt1= create database mysq
--echo #
let $statement= drop function f1;
let $cleanup_stmt1= create function f1() returns int return 0;
+--echo # Skip last part of testing as this statement does
+--echo # implicit commit and releases metadata locks in
+--echo # non-standard place.
+let $skip_3rd_check= 1;
--source include/check_ftwrl_incompatible.inc
+let $skip_3rd_check= ;
--echo #
--echo # 13.5) DROP PROCEDURE is incompatible with FTWRL.
--echo #
let $statement= drop procedure p1;
let $cleanup_stmt1= create procedure p1() begin end;
+--echo # Skip last part of testing as this statement does
+--echo # implicit commit and releases metadata locks in
+--echo # non-standard place.
+let $skip_3rd_check= 1;
--source include/check_ftwrl_incompatible.inc
+let $skip_3rd_check= ;
--echo #
--echo # 13.6) DROP USER should be incompatible with FTWRL.
@@ -764,8 +779,12 @@ let $cleanup_stmt1= create procedure p1(
create user mysqltest_u1;
let $statement= drop user mysqltest_u1;
let $cleanup_stmt1= create user mysqltest_u1;
+--echo # Skip last part of testing as this statement does
+--echo # implicit commit and releases metadata locks in
+--echo # non-standard place.
+let $skip_3rd_check= 1;
--source include/check_ftwrl_incompatible.inc
-drop user mysqltest_u1;
+let $skip_3rd_check= ;
--echo #
--echo # 13.7) DROP VIEW should be incompatible with FTWRL.
@@ -894,7 +913,12 @@ let $cleanup_stmt= ;
--echo #
let $statement= grant all privileges on t1_base to mysqltest_u1;
let $cleanup_stmt1= revoke all privileges on t1_base from mysqltest_u1;
+--echo # Skip last part of testing as this statement does
+--echo # implicit commit and releases metadata locks in
+--echo # non-standard place.
+let $skip_3rd_check= 1;
--source include/check_ftwrl_incompatible.inc
+let $skip_3rd_check= ;
drop user mysqltest_u1;
@@ -1289,7 +1313,12 @@ let $cleanup_stmt1= rename table t3_base
create user mysqltest_u1;
let $statement= rename user mysqltest_u1 to mysqltest_u2;
let $cleanup_stmt1= rename user mysqltest_u2 to mysqltest_u1;
+--echo # Skip last part of testing as this statement does
+--echo # implicit commit and releases metadata locks in
+--echo # non-standard place.
+let $skip_3rd_check= 1;
--source include/check_ftwrl_incompatible.inc
+let $skip_3rd_check= ;
drop user mysqltest_u1;
@@ -1370,13 +1399,23 @@ let $cleanup_stmt= ;
grant all privileges on t1_base to mysqltest_u1;
let $statement= revoke all privileges on t1_base from mysqltest_u1;
let $cleanup_stmt1= grant all privileges on t1_base to mysqltest_u1;
+--echo # Skip last part of testing as this statement does
+--echo # implicit commit and releases metadata locks in
+--echo # non-standard place.
+let $skip_3rd_check= 1;
--source include/check_ftwrl_incompatible.inc
+let $skip_3rd_check= ;
--echo #
--echo # 29.2) REVOKE ALL PRIVILEGES, GRANT OPTION is incompatible with FTWRL.
let $statement= revoke all privileges, grant option from mysqltest_u1;
let $cleanup_stmt1= grant all privileges on t1_base to mysqltest_u1;
+--echo # Skip last part of testing as this statement does
+--echo # implicit commit and releases metadata locks in
+--echo # non-standard place.
+let $skip_3rd_check= 1;
--source include/check_ftwrl_incompatible.inc
+let $skip_3rd_check= ;
drop user mysqltest_u1;
=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc 2012-04-27 14:30:32 +0000
+++ b/sql/event_db_repository.cc 2012-06-20 09:19:32 +0000
@@ -1191,8 +1191,7 @@ Event_db_repository::check_system_tables
{
if (table_intact.check(tables.table, &mysql_db_table_def))
ret= 1;
-
- close_mysql_tables(thd);
+ close_acl_tables(thd);
}
/* Check mysql.user */
tables.init_one_table("mysql", 5, "user", 4, "user", TL_READ);
@@ -1212,7 +1211,7 @@ Event_db_repository::check_system_tables
event_priv_column_position);
ret= 1;
}
- close_mysql_tables(thd);
+ close_acl_tables(thd);
}
/* Check mysql.event */
tables.init_one_table("mysql", 5, "event", 5, "event", TL_READ);
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2012-06-19 09:17:50 +0000
+++ b/sql/sql_acl.cc 2012-06-20 09:19:32 +0000
@@ -1458,6 +1458,79 @@ void acl_free(bool end)
}
+/**
+ A helper function to commit statement transaction and close
+ ACL tables after reading some data from them as part of FLUSH
+ PRIVILEGES statement or during server initialization.
+
+ @note We assume that we have only read from the tables so commit
+ can't fail. @sa close_mysql_tables().
+*/
+
+void close_acl_tables(THD *thd)
+{
+#ifndef DBUG_OFF
+ bool res=
+#endif
+ trans_commit_stmt(thd);
+ DBUG_ASSERT(res == false);
+
+ close_mysql_tables(thd);
+}
+
+
+/**
+ Commit ACL statement (and transaction) ignoring the fact that it might have
+ ended with an error, close tables which it has opened and release metadata
+ locks.
+
+ @note In case of failure to commit transaction we try to restore correct
+ state of in-memory structures by reloading privileges.
+
+ @retval False - Success.
+ @retval True - Error.
+*/
+
+static bool acl_trans_commit_and_close_tables(THD *thd)
+{
+ bool result;
+
+ /*
+ Try to commit a transaction even if we had some failures.
+
+ Without this step changes to privilege tables will be rolled back at the
+ end of mysql_execute_command() in the presence of error, leaving on-disk
+ and in-memory descriptions of privileges out of sync and making behavior
+ of ACL statements for transactional tables incompatible with legacy
+ behavior.
+
+ We need to commit both statement and normal transaction to make behavior
+ consistent with both autocommit on and off.
+
+ It is safe to do so since ACL statement always do implicit commit at the
+ end of statement.
+ */
+ DBUG_ASSERT(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END));
+
+ result= trans_commit_stmt(thd);
+ result|= trans_commit_implicit(thd);
+ close_thread_tables(thd);
+ thd->mdl_context.release_transactional_locks();
+
+ if (result)
+ {
+ /*
+ Try to bring in-memory structures back in sync with on-disk data if we
+ have failed to commit our changes.
+ */
+ (void) acl_reload(thd);
+ (void) grant_reload(thd);
+ }
+
+ return result;
+}
+
+
/*
Forget current user/db-level privileges and read new privileges
from the privilege tables.
@@ -1553,7 +1626,7 @@ my_bool acl_reload(THD *thd)
if (old_initialized)
mysql_mutex_unlock(&acl_cache->lock);
end:
- close_mysql_tables(thd);
+ close_acl_tables(thd);
DBUG_RETURN(return_val);
}
@@ -2379,18 +2452,14 @@ bool change_password(THD *thd, const cha
acl_cache->clear(1); // Clear locked hostname cache
mysql_mutex_unlock(&acl_cache->lock);
result= 0;
- if (mysql_bin_log.is_open())
- {
- query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
- acl_user->user ? acl_user->user : "",
- acl_user->host.get_host() ? acl_user->host.get_host() : "",
- new_password);
- thd->clear_error();
- result= thd->binlog_query(THD::STMT_QUERY_TYPE, buff, query_length,
- FALSE, FALSE, FALSE, 0);
- }
+ query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
+ acl_user->user ? acl_user->user : "",
+ acl_user->host.get_host() ? acl_user->host.get_host() : "",
+ new_password);
+ result= write_bin_log(thd, true, buff, query_length,
+ table->file->has_transactions());
end:
- close_mysql_tables(thd);
+ result|= acl_trans_commit_and_close_tables(thd);
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
@@ -4131,6 +4200,7 @@ int mysql_table_grant(THD *thd, TABLE_LI
char *db_name, *table_name;
bool save_binlog_row_based;
bool should_write_to_binlog= FALSE;
+ bool transactional_tables;
DBUG_ENTER("mysql_table_grant");
if (!initialized)
@@ -4273,6 +4343,11 @@ int mysql_table_grant(THD *thd, TABLE_LI
DBUG_RETURN(TRUE); /* purecov: deadcode */
}
+ transactional_tables= (tables[0].table->file->has_transactions() ||
+ tables[1].table->file->has_transactions() ||
+ (tables[2].table &&
+ tables[2].table->file->has_transactions()));
+
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
bool result= FALSE;
@@ -4405,13 +4480,16 @@ int mysql_table_grant(THD *thd, TABLE_LI
if (should_write_to_binlog)
result= result |
- write_bin_log(thd, FALSE, thd->query(), thd->query_length());
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length(),
+ transactional_tables);
+
mysql_rwlock_unlock(&LOCK_grant);
+ result|= acl_trans_commit_and_close_tables(thd);
+
if (!result) /* success */
my_ok(thd);
- /* 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());
@@ -4446,6 +4524,7 @@ bool mysql_routine_grant(THD *thd, TABLE
bool create_new_users=0, result=0;
char *db_name, *table_name;
bool save_binlog_row_based, should_write_to_binlog= FALSE;
+ bool transactional_tables;
DBUG_ENTER("mysql_routine_grant");
if (!initialized)
@@ -4515,6 +4594,9 @@ bool mysql_routine_grant(THD *thd, TABLE
DBUG_RETURN(TRUE);
}
+ transactional_tables= (tables[0].table->file->has_transactions() ||
+ tables[1].table->file->has_transactions());
+
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
mysql_rwlock_wrlock(&LOCK_grant);
@@ -4593,7 +4675,8 @@ bool mysql_routine_grant(THD *thd, TABLE
{
if (revoke_grant)
{
- if (write_bin_log(thd, FALSE, thd->query(), thd->query_length()))
+ if (write_bin_log(thd, FALSE, thd->query(), thd->query_length(),
+ transactional_tables))
result= TRUE;
}
else
@@ -4601,18 +4684,21 @@ bool mysql_routine_grant(THD *thd, TABLE
DBUG_ASSERT(thd->rewritten_query.length());
if (write_bin_log(thd, FALSE,
thd->rewritten_query.c_ptr_safe(),
- thd->rewritten_query.length()))
+ thd->rewritten_query.length(),
+ transactional_tables))
result= TRUE;
}
}
mysql_rwlock_unlock(&LOCK_grant);
+
+ result|= acl_trans_commit_and_close_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();
-
- /* Tables are automatically closed */
+
DBUG_RETURN(result);
}
@@ -4700,6 +4786,7 @@ bool mysql_grant(THD *thd, const char *d
TABLE_LIST tables[2];
bool save_binlog_row_based;
bool should_write_to_binlog= FALSE;
+ bool transactional_tables;
DBUG_ENTER("mysql_grant");
if (!initialized)
{
@@ -4777,6 +4864,9 @@ bool mysql_grant(THD *thd, const char *d
DBUG_RETURN(TRUE); /* purecov: deadcode */
}
+ transactional_tables= (tables[0].table->file->has_transactions() ||
+ tables[1].table->file->has_transactions());
+
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
@@ -4844,16 +4934,21 @@ bool mysql_grant(THD *thd, const char *d
result= result |
write_bin_log(thd, FALSE,
thd->rewritten_query.c_ptr_safe(),
- thd->rewritten_query.length());
+ thd->rewritten_query.length(),
+ transactional_tables);
else
result= result |
- write_bin_log(thd, FALSE, thd->query(), thd->query_length());
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length(),
+ transactional_tables);
}
mysql_rwlock_unlock(&LOCK_grant);
+ result|= acl_trans_commit_and_close_tables(thd);
+
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)
@@ -5136,7 +5231,7 @@ static my_bool grant_reload_procs_priv(T
}
mysql_rwlock_unlock(&LOCK_grant);
- close_mysql_tables(thd);
+ close_acl_tables(thd);
DBUG_RETURN(return_val);
}
@@ -5207,7 +5302,7 @@ my_bool grant_reload(THD *thd)
free_root(&old_mem,MYF(0));
}
mysql_rwlock_unlock(&LOCK_grant);
- close_mysql_tables(thd);
+ close_acl_tables(thd);
/*
It is OK failing to load procs_priv table because we may be
@@ -6460,29 +6555,33 @@ void get_mqh(const char *user, const cha
mysql_mutex_unlock(&acl_cache->lock);
}
-/*
+/**
Open the grant tables.
- SYNOPSIS
- open_grant_tables()
- thd The current thread.
- tables (out) The 4 elements array for the opened tables.
+ @param thd The current thread.
+ @param[in/out] tables Array of GRANT_TABLES table list elements
+ which will be used for opening tables.
+ @param[out] transactional_tables Set to true if one of grant tables is
+ transactional, false otherwise.
- DESCRIPTION
+ @note
Tables are numbered as follows:
0 user
1 db
2 tables_priv
3 columns_priv
+ 4 procs_priv
+ 5 proxies_priv
- RETURN
- 1 Skip GRANT handling during replication.
- 0 OK.
- < 0 Error.
+ @retval 1 Skip GRANT handling during replication.
+ @retval 0 OK.
+ @retval < 0 Error.
*/
#define GRANT_TABLES 6
-int open_grant_tables(THD *thd, TABLE_LIST *tables)
+
+static int
+open_grant_tables(THD *thd, TABLE_LIST *tables, bool *transactional_tables)
{
DBUG_ENTER("open_grant_tables");
@@ -6492,6 +6591,8 @@ int open_grant_tables(THD *thd, TABLE_LI
DBUG_RETURN(-1);
}
+ *transactional_tables= false;
+
tables->init_one_table(C_STRING_WITH_LEN("mysql"),
C_STRING_WITH_LEN("user"), "user", TL_WRITE);
(tables+1)->init_one_table(C_STRING_WITH_LEN("mysql"),
@@ -6541,35 +6642,14 @@ int open_grant_tables(THD *thd, TABLE_LI
DBUG_RETURN(-1);
}
+ for (uint i= 0; i < GRANT_TABLES; ++i)
+ *transactional_tables= (*transactional_tables ||
+ (tables[i].table &&
+ tables[i].table->file->has_transactions()));
+
DBUG_RETURN(0);
}
-ACL_USER *check_acl_user(LEX_USER *user_name,
- uint *acl_acl_userdx)
-{
- ACL_USER *acl_user= 0;
- uint counter;
-
- mysql_mutex_assert_owner(&acl_cache->lock);
-
- for (counter= 0 ; counter < acl_users.elements ; counter++)
- {
- const char *user,*host;
- acl_user= dynamic_element(&acl_users, counter, ACL_USER*);
- if (!(user=acl_user->user))
- user= "";
- if (!(host=acl_user->host.get_host()))
- host= "";
- if (!strcmp(user_name->user.str,user) &&
- !my_strcasecmp(system_charset_info, user_name->host.str, host))
- break;
- }
- if (counter == acl_users.elements)
- return 0;
-
- *acl_acl_userdx= counter;
- return acl_user;
-}
/*
Modify a privilege table.
@@ -7288,6 +7368,7 @@ bool mysql_create_user(THD *thd, List <L
TABLE_LIST tables[GRANT_TABLES];
bool some_users_created= FALSE;
bool save_binlog_row_based;
+ bool transactional_tables;
DBUG_ENTER("mysql_create_user");
/*
@@ -7299,7 +7380,7 @@ bool mysql_create_user(THD *thd, List <L
thd->clear_current_stmt_binlog_format_row();
/* CREATE USER may be skipped on replication client. */
- if ((result= open_grant_tables(thd, tables)))
+ if ((result= open_grant_tables(thd, tables, &transactional_tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
@@ -7366,10 +7447,14 @@ bool mysql_create_user(THD *thd, List <L
{
result|= write_bin_log(thd, FALSE,
thd->rewritten_query.c_ptr_safe(),
- thd->rewritten_query.length());
+ thd->rewritten_query.length(),
+ transactional_tables);
}
mysql_rwlock_unlock(&LOCK_grant);
+
+ result|= acl_trans_commit_and_close_tables(thd);
+
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
@@ -7401,6 +7486,7 @@ bool mysql_drop_user(THD *thd, List <LEX
bool some_users_deleted= FALSE;
sql_mode_t old_sql_mode= thd->variables.sql_mode;
bool save_binlog_row_based;
+ bool transactional_tables;
DBUG_ENTER("mysql_drop_user");
/*
@@ -7412,7 +7498,7 @@ bool mysql_drop_user(THD *thd, List <LEX
thd->clear_current_stmt_binlog_format_row();
/* DROP USER may be skipped on replication client. */
- if ((result= open_grant_tables(thd, tables)))
+ if ((result= open_grant_tables(thd, tables, &transactional_tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
@@ -7451,9 +7537,13 @@ bool mysql_drop_user(THD *thd, List <LEX
my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe());
if (some_users_deleted)
- result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
+ result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length(),
+ transactional_tables);
mysql_rwlock_unlock(&LOCK_grant);
+
+ result|= acl_trans_commit_and_close_tables(thd);
+
thd->variables.sql_mode= old_sql_mode;
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
@@ -7486,6 +7576,7 @@ bool mysql_rename_user(THD *thd, List <L
TABLE_LIST tables[GRANT_TABLES];
bool some_users_renamed= FALSE;
bool save_binlog_row_based;
+ bool transactional_tables;
DBUG_ENTER("mysql_rename_user");
/*
@@ -7497,7 +7588,7 @@ bool mysql_rename_user(THD *thd, List <L
thd->clear_current_stmt_binlog_format_row();
/* RENAME USER may be skipped on replication client. */
- if ((result= open_grant_tables(thd, tables)))
+ if ((result= open_grant_tables(thd, tables, &transactional_tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
@@ -7546,10 +7637,14 @@ bool mysql_rename_user(THD *thd, List <L
if (result)
my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr_safe());
- if (some_users_renamed && mysql_bin_log.is_open())
- result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
+ if (some_users_renamed)
+ result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length(),
+ transactional_tables);
mysql_rwlock_unlock(&LOCK_grant);
+
+ result|= acl_trans_commit_and_close_tables(thd);
+
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
@@ -7650,27 +7745,27 @@ bool mysql_user_password_expire(THD *thd
acl_cache->clear(1); // Clear locked hostname cache
mysql_mutex_unlock(&acl_cache->lock);
- if (!result && some_passwords_expired && mysql_bin_log.is_open())
+ if (result)
+ my_error(ER_CANNOT_USER, MYF(0), "ALTER USER", wrong_users.c_ptr_safe());
+
+ if (!result && some_passwords_expired)
{
const char *query= thd->rewritten_query.length() ?
thd->rewritten_query.c_ptr_safe() : thd->query();
const size_t query_length= thd->rewritten_query.length() ?
thd->rewritten_query.length() : thd->query_length();
- result= (write_bin_log(thd, false, query, query_length) != 0);
+ result= (write_bin_log(thd, false, query, query_length,
+ table->file->has_transactions()) != 0);
}
mysql_rwlock_unlock(&LOCK_grant);
- close_mysql_tables(thd);
+ result|= acl_trans_commit_and_close_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();
-
- if (result)
- my_error(ER_CANNOT_USER, MYF(0), "ALTER USER", wrong_users.c_ptr_safe());
-
DBUG_RETURN(result);
}
@@ -7696,6 +7791,7 @@ bool mysql_revoke_all(THD *thd, List <L
ACL_DB *acl_db;
TABLE_LIST tables[GRANT_TABLES];
bool save_binlog_row_based, should_write_to_binlog= FALSE;
+ bool transactional_tables;
DBUG_ENTER("mysql_revoke_all");
/*
@@ -7706,7 +7802,7 @@ bool mysql_revoke_all(THD *thd, List <L
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)))
+ if ((result= open_grant_tables(thd, tables, &transactional_tables)))
{
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
@@ -7868,10 +7964,14 @@ bool mysql_revoke_all(THD *thd, List <L
if (should_write_to_binlog)
{
result= result |
- write_bin_log(thd, FALSE, thd->query(), thd->query_length());
+ write_bin_log(thd, FALSE, thd->query(), thd->query_length(),
+ transactional_tables);
}
mysql_rwlock_unlock(&LOCK_grant);
+
+ result|= acl_trans_commit_and_close_tables(thd);
+
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
if (save_binlog_row_based)
@@ -7968,9 +8068,10 @@ bool sp_revoke_privileges(THD *thd, cons
HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash;
Silence_routine_definer_errors error_handler;
bool save_binlog_row_based;
+ bool not_used;
DBUG_ENTER("sp_revoke_privileges");
- if ((result= open_grant_tables(thd, tables)))
+ if ((result= open_grant_tables(thd, tables, ¬_used)))
DBUG_RETURN(result != 1);
/* Be sure to pop this before exiting this scope! */
@@ -8019,13 +8120,16 @@ bool sp_revoke_privileges(THD *thd, cons
mysql_mutex_unlock(&acl_cache->lock);
mysql_rwlock_unlock(&LOCK_grant);
+ result= acl_trans_commit_and_close_tables(thd);
+
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());
+ DBUG_RETURN(error_handler.has_errors() || result);
}
=== modified file 'sql/sql_acl.h'
--- a/sql/sql_acl.h 2012-06-04 15:35:18 +0000
+++ b/sql/sql_acl.h 2012-06-20 09:19:32 +0000
@@ -308,6 +308,7 @@ void check_password_policy(String *passw
#define check_grant(A,B,C,D,E,F) 0
#define check_grant_db(A,B) 0
#endif
+void close_acl_tables(THD *thd);
/**
Result of an access check for an internal schema or table.
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (magnus.blaudd:4048 to 4049) | magnus.blaudd | 25 Jun |