List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:March 9 2011 2:31pm
Subject:bzr commit into mysql-trunk branch (Georgi.Kodinov:3738)
View as plain text  
#At file:///Users/kgeorge/mysql/work/merge-trunk/ based on revid:andrei.elkin@stripped6fg413

 3738 Georgi Kodinov	2011-03-09 [merge]
      merge mysql-5.5->mysql-trunk

    modified:
      mysql-test/r/grant.result
      mysql-test/suite/funcs_1/r/innodb_storedproc_06.result
      mysql-test/suite/funcs_1/r/memory_storedproc_06.result
      mysql-test/suite/funcs_1/r/myisam_storedproc_06.result
      mysql-test/suite/funcs_1/storedproc/storedproc_06.inc
      mysql-test/t/grant.test
      sql/sql_acl.cc
=== modified file 'mysql-test/r/grant.result'
--- a/mysql-test/r/grant.result	2011-02-08 15:54:12 +0000
+++ b/mysql-test/r/grant.result	2011-03-09 14:30:37 +0000
@@ -1452,6 +1452,199 @@ DROP DATABASE mysqltest2;
 DROP USER testuser@localhost;
 use test;
 
+#
+# Test for bug #36544 "DROP USER does not remove stored function
+#                      privileges".
+#
+create database mysqltest1;
+create function mysqltest1.f1() returns int return 0;
+create procedure mysqltest1.p1() begin end;
+#
+# 1) Check that DROP USER properly removes privileges on both
+#    stored procedures and functions.
+#
+create user mysqluser1@localhost;
+grant execute on function mysqltest1.f1 to mysqluser1@localhost;
+grant execute on procedure mysqltest1.p1 to mysqluser1@localhost;
+# Quick test that granted privileges are properly reflected
+# in privilege tables and in in-memory structures.
+show grants for mysqluser1@localhost;
+Grants for mysqluser1@localhost
+GRANT USAGE ON *.* TO 'mysqluser1'@'localhost'
+GRANT EXECUTE ON PROCEDURE `mysqltest1`.`p1` TO 'mysqluser1'@'localhost'
+GRANT EXECUTE ON FUNCTION `mysqltest1`.`f1` TO 'mysqluser1'@'localhost'
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost';
+db	routine_name	routine_type	proc_priv
+mysqltest1	f1	FUNCTION	Execute
+mysqltest1	p1	PROCEDURE	Execute
+#
+# Create connection 'bug_36544_con1' as 'mysqluser1@localhost'.
+call mysqltest1.p1();
+select mysqltest1.f1();
+mysqltest1.f1()
+0
+#
+# Switch to connection 'default'.
+drop user mysqluser1@localhost;
+#
+# Test that dropping of user is properly reflected in
+# both privilege tables and in in-memory structures.
+#
+# Switch to connection 'bug36544_con1'.
+# The connection cold be alive but should not be able to
+# access to any of the stored routines.
+call mysqltest1.p1();
+ERROR 42000: execute command denied to user 'mysqluser1'@'localhost' for routine 'mysqltest1.p1'
+select mysqltest1.f1();
+ERROR 42000: execute command denied to user 'mysqluser1'@'localhost' for routine 'mysqltest1.f1'
+#
+# Switch to connection 'default'.
+#
+# Now create user with the same name and check that he
+# has not inherited privileges.
+create user mysqluser1@localhost;
+show grants for mysqluser1@localhost;
+Grants for mysqluser1@localhost
+GRANT USAGE ON *.* TO 'mysqluser1'@'localhost'
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost';
+db	routine_name	routine_type	proc_priv
+#
+# Create connection 'bug_36544_con2' as 'mysqluser1@localhost'.
+# Newly created user should not be able to access any of the routines.
+call mysqltest1.p1();
+ERROR 42000: execute command denied to user 'mysqluser1'@'localhost' for routine 'mysqltest1.p1'
+select mysqltest1.f1();
+ERROR 42000: execute command denied to user 'mysqluser1'@'localhost' for routine 'mysqltest1.f1'
+#
+# Switch to connection 'default'.
+#
+# 2) Check that RENAME USER properly updates privileges on both
+#    stored procedures and functions.
+#
+grant execute on function mysqltest1.f1 to mysqluser1@localhost;
+grant execute on procedure mysqltest1.p1 to mysqluser1@localhost;
+#
+# Create one more user to make in-memory hashes non-trivial.
+# User names 'mysqluser11' and 'mysqluser10' were selected
+# to trigger bug discovered during code inspection.
+create user mysqluser11@localhost;
+grant execute on function mysqltest1.f1 to mysqluser11@localhost;
+grant execute on procedure mysqltest1.p1 to mysqluser11@localhost;
+# Also create a couple of tables to test for another bug
+# discovered during code inspection (again table names were
+# chosen especially to trigger the bug).
+create table mysqltest1.t11 (i int);
+create table mysqltest1.t22 (i int);
+grant select on mysqltest1.t22 to mysqluser1@localhost;
+grant select on mysqltest1.t11 to mysqluser1@localhost;
+# Quick test that granted privileges are properly reflected
+# in privilege tables and in in-memory structures.
+show grants for mysqluser1@localhost;
+Grants for mysqluser1@localhost
+GRANT USAGE ON *.* TO 'mysqluser1'@'localhost'
+GRANT SELECT ON `mysqltest1`.`t11` TO 'mysqluser1'@'localhost'
+GRANT SELECT ON `mysqltest1`.`t22` TO 'mysqluser1'@'localhost'
+GRANT EXECUTE ON PROCEDURE `mysqltest1`.`p1` TO 'mysqluser1'@'localhost'
+GRANT EXECUTE ON FUNCTION `mysqltest1`.`f1` TO 'mysqluser1'@'localhost'
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost';
+db	routine_name	routine_type	proc_priv
+mysqltest1	f1	FUNCTION	Execute
+mysqltest1	p1	PROCEDURE	Execute
+select db, table_name, table_priv from mysql.tables_priv where user='mysqluser1' and host='localhost';
+db	table_name	table_priv
+mysqltest1	t11	Select
+mysqltest1	t22	Select
+#
+# Switch to connection 'bug36544_con2'.
+call mysqltest1.p1();
+select mysqltest1.f1();
+mysqltest1.f1()
+0
+select * from mysqltest1.t11;
+i
+select * from mysqltest1.t22;
+i
+#
+# Switch to connection 'default'.
+rename user mysqluser1@localhost to mysqluser10@localhost;
+#
+# Test that there are no privileges left for mysqluser1.
+#
+# Switch to connection 'bug36544_con2'.
+# The connection cold be alive but should not be able to
+# access to any of the stored routines or tables.
+call mysqltest1.p1();
+ERROR 42000: execute command denied to user 'mysqluser1'@'localhost' for routine 'mysqltest1.p1'
+select mysqltest1.f1();
+ERROR 42000: execute command denied to user 'mysqluser1'@'localhost' for routine 'mysqltest1.f1'
+select * from mysqltest1.t11;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 't11'
+select * from mysqltest1.t22;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 't22'
+#
+# Switch to connection 'default'.
+#
+# Now create user with the old name and check that he
+# has not inherited privileges.
+create user mysqluser1@localhost;
+show grants for mysqluser1@localhost;
+Grants for mysqluser1@localhost
+GRANT USAGE ON *.* TO 'mysqluser1'@'localhost'
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost';
+db	routine_name	routine_type	proc_priv
+select db, table_name, table_priv from mysql.tables_priv where user='mysqluser1' and host='localhost';
+db	table_name	table_priv
+#
+# Create connection 'bug_36544_con3' as 'mysqluser1@localhost'.
+# Newly created user should not be able to access to any of the
+# stored routines or tables.
+call mysqltest1.p1();
+ERROR 42000: execute command denied to user 'mysqluser1'@'localhost' for routine 'mysqltest1.p1'
+select mysqltest1.f1();
+ERROR 42000: execute command denied to user 'mysqluser1'@'localhost' for routine 'mysqltest1.f1'
+select * from mysqltest1.t11;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 't11'
+select * from mysqltest1.t22;
+ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 't22'
+#
+# Switch to connection 'default'.
+#
+# Now check that privileges became associated with a new user
+# name - mysqluser10.
+#
+show grants for mysqluser10@localhost;
+Grants for mysqluser10@localhost
+GRANT USAGE ON *.* TO 'mysqluser10'@'localhost'
+GRANT SELECT ON `mysqltest1`.`t22` TO 'mysqluser10'@'localhost'
+GRANT SELECT ON `mysqltest1`.`t11` TO 'mysqluser10'@'localhost'
+GRANT EXECUTE ON PROCEDURE `mysqltest1`.`p1` TO 'mysqluser10'@'localhost'
+GRANT EXECUTE ON FUNCTION `mysqltest1`.`f1` TO 'mysqluser10'@'localhost'
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser10' and host='localhost';
+db	routine_name	routine_type	proc_priv
+mysqltest1	f1	FUNCTION	Execute
+mysqltest1	p1	PROCEDURE	Execute
+select db, table_name, table_priv from mysql.tables_priv where user='mysqluser10' and host='localhost';
+db	table_name	table_priv
+mysqltest1	t11	Select
+mysqltest1	t22	Select
+#
+# Create connection 'bug_36544_con4' as 'mysqluser10@localhost'.
+call mysqltest1.p1();
+select mysqltest1.f1();
+mysqltest1.f1()
+0
+select * from mysqltest1.t11;
+i
+select * from mysqltest1.t22;
+i
+#
+# Switch to connection 'default'.
+#
+# Clean-up.
+drop user mysqluser1@localhost;
+drop user mysqluser10@localhost;
+drop user mysqluser11@localhost;
+drop database mysqltest1;
 End of 5.0 tests
 set names utf8;
 grant select on test.* to юзер_юзер@localhost;
@@ -1546,11 +1739,7 @@ fn2()
 2
 DROP USER 'userbug33464'@'localhost';
 DROP FUNCTION fn1;
-Warnings:
-Warning	1403	There is no such grant defined for user 'userbug33464' on host 'localhost' on routine 'fn1'
 DROP FUNCTION fn2;
-Warnings:
-Warning	1403	There is no such grant defined for user 'userbug33464' on host 'localhost' on routine 'fn2'
 DROP PROCEDURE sp3;
 DROP USER 'userbug33464'@'localhost';
 USE test;

=== modified file 'mysql-test/suite/funcs_1/r/innodb_storedproc_06.result'
--- a/mysql-test/suite/funcs_1/r/innodb_storedproc_06.result	2010-10-07 16:01:17 +0000
+++ b/mysql-test/suite/funcs_1/r/innodb_storedproc_06.result	2011-03-09 14:04:50 +0000
@@ -128,8 +128,6 @@ root@localhost	db_storedproc_1
 drop user 'user_1'@'localhost';
 DROP PROCEDURE sp3;
 DROP FUNCTION fn1;
-Warnings:
-Warning	1403	There is no such grant defined for user 'user_1' on host 'localhost' on routine 'fn1'
 
 Testcase 3.1.6.4:
 -----------------

=== modified file 'mysql-test/suite/funcs_1/r/memory_storedproc_06.result'
--- a/mysql-test/suite/funcs_1/r/memory_storedproc_06.result	2010-10-07 16:01:17 +0000
+++ b/mysql-test/suite/funcs_1/r/memory_storedproc_06.result	2011-03-09 14:04:50 +0000
@@ -129,8 +129,6 @@ root@localhost	db_storedproc_1
 drop user 'user_1'@'localhost';
 DROP PROCEDURE sp3;
 DROP FUNCTION fn1;
-Warnings:
-Warning	1403	There is no such grant defined for user 'user_1' on host 'localhost' on routine 'fn1'
 
 Testcase 3.1.6.4:
 -----------------

=== modified file 'mysql-test/suite/funcs_1/r/myisam_storedproc_06.result'
--- a/mysql-test/suite/funcs_1/r/myisam_storedproc_06.result	2010-10-07 16:01:17 +0000
+++ b/mysql-test/suite/funcs_1/r/myisam_storedproc_06.result	2011-03-09 14:04:50 +0000
@@ -129,8 +129,6 @@ root@localhost	db_storedproc_1
 drop user 'user_1'@'localhost';
 DROP PROCEDURE sp3;
 DROP FUNCTION fn1;
-Warnings:
-Warning	1403	There is no such grant defined for user 'user_1' on host 'localhost' on routine 'fn1'
 
 Testcase 3.1.6.4:
 -----------------

=== modified file 'mysql-test/suite/funcs_1/storedproc/storedproc_06.inc'
--- a/mysql-test/suite/funcs_1/storedproc/storedproc_06.inc	2010-10-07 16:01:17 +0000
+++ b/mysql-test/suite/funcs_1/storedproc/storedproc_06.inc	2011-03-09 14:04:50 +0000
@@ -149,10 +149,6 @@ USE db_storedproc_1;
 
 drop user 'user_1'@'localhost';
 DROP PROCEDURE sp3;
-# This drop function shouldn't generated a warning as the
-# privileges should have been removed when the user was
-# dropped. Reported as Bug#36544 DROP USER does not remove
-# stored function privileges
 DROP FUNCTION fn1;
 
 

=== modified file 'mysql-test/t/grant.test'
--- a/mysql-test/t/grant.test	2011-02-23 04:53:07 +0000
+++ b/mysql-test/t/grant.test	2011-03-09 14:30:37 +0000
@@ -1396,6 +1396,183 @@ DROP USER testuser@localhost;
 use test;
 --echo
 
+
+--echo #
+--echo # Test for bug #36544 "DROP USER does not remove stored function
+--echo #                      privileges".
+--echo #
+create database mysqltest1;
+create function mysqltest1.f1() returns int return 0;
+create procedure mysqltest1.p1() begin end;
+--echo #
+--echo # 1) Check that DROP USER properly removes privileges on both
+--echo #    stored procedures and functions.
+--echo #
+create user mysqluser1@localhost;
+grant execute on function mysqltest1.f1 to mysqluser1@localhost;
+grant execute on procedure mysqltest1.p1 to mysqluser1@localhost;
+
+--echo # Quick test that granted privileges are properly reflected
+--echo # in privilege tables and in in-memory structures.
+show grants for mysqluser1@localhost;
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost';
+--echo #
+--echo # Create connection 'bug_36544_con1' as 'mysqluser1@localhost'.
+--connect (bug36544_con1,localhost,mysqluser1,,)
+call mysqltest1.p1();
+select mysqltest1.f1();
+
+--echo #
+--echo # Switch to connection 'default'.
+--connection default
+drop user mysqluser1@localhost;
+
+--echo #
+--echo # Test that dropping of user is properly reflected in
+--echo # both privilege tables and in in-memory structures.
+--echo #
+--echo # Switch to connection 'bug36544_con1'.
+--connection bug36544_con1
+--echo # The connection cold be alive but should not be able to
+--echo # access to any of the stored routines.
+--error ER_PROCACCESS_DENIED_ERROR
+call mysqltest1.p1();
+--error ER_PROCACCESS_DENIED_ERROR
+select mysqltest1.f1();
+--disconnect bug36544_con1
+
+--echo #
+--echo # Switch to connection 'default'.
+--connection default
+--echo #
+--echo # Now create user with the same name and check that he
+--echo # has not inherited privileges.
+create user mysqluser1@localhost;
+show grants for mysqluser1@localhost;
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost';
+--echo #
+--echo # Create connection 'bug_36544_con2' as 'mysqluser1@localhost'.
+--connect (bug36544_con2,localhost,mysqluser1,,)
+--echo # Newly created user should not be able to access any of the routines.
+--error ER_PROCACCESS_DENIED_ERROR
+call mysqltest1.p1();
+--error ER_PROCACCESS_DENIED_ERROR
+select mysqltest1.f1();
+--echo #
+--echo # Switch to connection 'default'.
+--connection default
+
+--echo #
+--echo # 2) Check that RENAME USER properly updates privileges on both
+--echo #    stored procedures and functions.
+--echo #
+grant execute on function mysqltest1.f1 to mysqluser1@localhost;
+grant execute on procedure mysqltest1.p1 to mysqluser1@localhost;
+--echo #
+--echo # Create one more user to make in-memory hashes non-trivial.
+--echo # User names 'mysqluser11' and 'mysqluser10' were selected
+--echo # to trigger bug discovered during code inspection.
+create user mysqluser11@localhost;
+grant execute on function mysqltest1.f1 to mysqluser11@localhost;
+grant execute on procedure mysqltest1.p1 to mysqluser11@localhost;
+--echo # Also create a couple of tables to test for another bug
+--echo # discovered during code inspection (again table names were
+--echo # chosen especially to trigger the bug).
+create table mysqltest1.t11 (i int);
+create table mysqltest1.t22 (i int);
+grant select on mysqltest1.t22 to mysqluser1@localhost;
+grant select on mysqltest1.t11 to mysqluser1@localhost;
+
+--echo # Quick test that granted privileges are properly reflected
+--echo # in privilege tables and in in-memory structures.
+show grants for mysqluser1@localhost;
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost';
+select db, table_name, table_priv from mysql.tables_priv where user='mysqluser1' and host='localhost';
+--echo #
+--echo # Switch to connection 'bug36544_con2'.
+--connection bug36544_con2
+call mysqltest1.p1();
+select mysqltest1.f1();
+select * from mysqltest1.t11;
+select * from mysqltest1.t22;
+
+--echo #
+--echo # Switch to connection 'default'.
+--connection default
+rename user mysqluser1@localhost to mysqluser10@localhost;
+
+--echo #
+--echo # Test that there are no privileges left for mysqluser1.
+--echo #
+--echo # Switch to connection 'bug36544_con2'.
+--connection bug36544_con2
+--echo # The connection cold be alive but should not be able to
+--echo # access to any of the stored routines or tables.
+--error ER_PROCACCESS_DENIED_ERROR
+call mysqltest1.p1();
+--error ER_PROCACCESS_DENIED_ERROR
+select mysqltest1.f1();
+--error ER_TABLEACCESS_DENIED_ERROR
+select * from mysqltest1.t11;
+--error ER_TABLEACCESS_DENIED_ERROR
+select * from mysqltest1.t22;
+--disconnect bug36544_con2
+
+--echo #
+--echo # Switch to connection 'default'.
+--connection default
+--echo #
+--echo # Now create user with the old name and check that he
+--echo # has not inherited privileges.
+create user mysqluser1@localhost;
+show grants for mysqluser1@localhost;
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost';
+select db, table_name, table_priv from mysql.tables_priv where user='mysqluser1' and host='localhost';
+--echo #
+--echo # Create connection 'bug_36544_con3' as 'mysqluser1@localhost'.
+--connect (bug36544_con3,localhost,mysqluser1,,)
+--echo # Newly created user should not be able to access to any of the
+--echo # stored routines or tables.
+--error ER_PROCACCESS_DENIED_ERROR
+call mysqltest1.p1();
+--error ER_PROCACCESS_DENIED_ERROR
+select mysqltest1.f1();
+--error ER_TABLEACCESS_DENIED_ERROR
+select * from mysqltest1.t11;
+--error ER_TABLEACCESS_DENIED_ERROR
+select * from mysqltest1.t22;
+--disconnect bug36544_con3
+
+--echo #
+--echo # Switch to connection 'default'.
+--connection default
+--echo #
+--echo # Now check that privileges became associated with a new user
+--echo # name - mysqluser10.
+--echo #
+show grants for mysqluser10@localhost;
+select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser10' and host='localhost';
+select db, table_name, table_priv from mysql.tables_priv where user='mysqluser10' and host='localhost';
+--echo #
+--echo # Create connection 'bug_36544_con4' as 'mysqluser10@localhost'.
+--connect (bug36544_con4,localhost,mysqluser10,,)
+call mysqltest1.p1();
+select mysqltest1.f1();
+select * from mysqltest1.t11;
+select * from mysqltest1.t22;
+--disconnect bug36544_con4
+
+--echo #
+--echo # Switch to connection 'default'.
+--connection default
+--echo #
+--echo # Clean-up.
+drop user mysqluser1@localhost;
+drop user mysqluser10@localhost;
+drop user mysqluser11@localhost;
+drop database mysqltest1;
+
+
 --echo End of 5.0 tests
 
 #

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2011-02-18 09:56:51 +0000
+++ b/sql/sql_acl.cc	2011-03-09 14:30:37 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -6003,18 +6003,15 @@ static int handle_grant_table(TABLE_LIST
 }
 
 
-/*
+/**
   Handle an in-memory privilege structure.
 
-  SYNOPSIS
-    handle_grant_struct()
-    struct_no                   The number of the structure to handle (0..3).
-    drop                        If user_from is to be dropped.
-    user_from                   The the user to be searched/dropped/renamed.
-    user_to                     The new name for the user if to be renamed,
-                                NULL otherwise.
+  @param struct_no  The number of the structure to handle (0..5).
+  @param drop       If user_from is to be dropped.
+  @param user_from  The the user to be searched/dropped/renamed.
+  @param user_to    The new name for the user if to be renamed, NULL otherwise.
 
-  DESCRIPTION
+  @note
     Scan through all elements in an in-memory grant structure and apply
     the requested operation.
     Delete from grant structure if drop is true.
@@ -6024,12 +6021,13 @@ static int handle_grant_table(TABLE_LIST
     0 acl_users
     1 acl_dbs
     2 column_priv_hash
-    3 procs_priv_hash
-
-  RETURN
-    > 0         At least one element matched.
-    0           OK, but no element matched.
-    -1		Wrong arguments to function
+    3 proc_priv_hash
+    4 func_priv_hash
+    5 acl_proxy_users
+
+  @retval > 0  At least one element matched.
+  @retval 0    OK, but no element matched.
+  @retval -1   Wrong arguments to function.
 */
 
 static int handle_grant_struct(uint struct_no, bool drop,
@@ -6044,6 +6042,7 @@ static int handle_grant_struct(uint stru
   ACL_DB *acl_db= NULL;
   ACL_PROXY_USER *acl_proxy_user= NULL;
   GRANT_NAME *grant_name= NULL;
+  HASH *grant_name_hash= NULL;
   DBUG_ENTER("handle_grant_struct");
   DBUG_PRINT("info",("scan struct: %u  search: '%s'@'%s'",
                      struct_no, user_from->user.str, user_from->host.str));
@@ -6063,9 +6062,15 @@ static int handle_grant_struct(uint stru
     break;
   case 2:
     elements= column_priv_hash.records;
+    grant_name_hash= &column_priv_hash;
     break;
   case 3:
     elements= proc_priv_hash.records;
+    grant_name_hash= &proc_priv_hash;
+    break;
+  case 4:
+    elements= func_priv_hash.records;
+    grant_name_hash= &func_priv_hash;
     break;
   case 5:
     elements= acl_proxy_users.elements;
@@ -6098,21 +6103,19 @@ static int handle_grant_struct(uint stru
       break;
 
     case 2:
-      grant_name= (GRANT_NAME*) my_hash_element(&column_priv_hash, idx);
-      user= grant_name->user;
-      host= grant_name->host.hostname;
-      break;
-
     case 3:
-      grant_name= (GRANT_NAME*) my_hash_element(&proc_priv_hash, idx);
+    case 4:
+      grant_name= (GRANT_NAME*) my_hash_element(grant_name_hash, idx);
       user= grant_name->user;
       host= grant_name->host.hostname;
       break;
+
     case 5:
       acl_proxy_user= dynamic_element(&acl_proxy_users, idx, ACL_PROXY_USER*);
       user= acl_proxy_user->get_user();
       host= acl_proxy_user->get_host();
       break;
+
     default:
       MY_ASSERT_UNREACHABLE();
     }
@@ -6142,11 +6145,9 @@ static int handle_grant_struct(uint stru
         break;
 
       case 2:
-        my_hash_delete(&column_priv_hash, (uchar*) grant_name);
-	break;
-
       case 3:
-        my_hash_delete(&proc_priv_hash, (uchar*) grant_name);
+      case 4:
+        my_hash_delete(grant_name_hash, (uchar*) grant_name);
 	break;
 
       case 5:
@@ -6155,6 +6156,19 @@ static int handle_grant_struct(uint stru
 
       }
       elements--;
+      /*
+        - If we are iterating through an array then we just have moved all
+          elements after the current element one position closer to its head.
+          This means that we have to take another look at the element at
+          current position as it is a new element from the array's tail.
+        - If we are iterating through a hash the current element was replaced
+          with one of elements from the tail. So we also have to take a look
+          at the new element in current position.
+          Note that in our HASH implementation hash_delete() won't move any
+          elements with position after current one to position before the
+          current (i.e. from the tail to the head), so it is safe to continue
+          iteration without re-starting.
+      */
       idx--;
     }
     else if ( user_to )
@@ -6172,22 +6186,41 @@ static int handle_grant_struct(uint stru
 
       case 2:
       case 3:
-        /* 
-          Update the grant structure with the new user name and
-          host name
-        */
-        grant_name->set_user_details(user_to->host.str, grant_name->db,
-                                     user_to->user.str, grant_name->tname,
-                                     TRUE);
-
-        /*
-          Since username is part of the hash key, when the user name
-          is renamed, the hash key is changed. Update the hash to
-          ensure that the position matches the new hash key value
-        */
-        my_hash_update(&column_priv_hash, (uchar*) grant_name,
-                       (uchar*) grant_name->hash_key, grant_name->key_length);
-	break;
+      case 4:
+        {
+          /*
+            Save old hash key and its length to be able properly update
+            element position in hash.
+          */
+          char *old_key= grant_name->hash_key;
+          size_t old_key_length= grant_name->key_length;
+
+          /*
+            Update the grant structure with the new user name and host name.
+          */
+          grant_name->set_user_details(user_to->host.str, grant_name->db,
+                                       user_to->user.str, grant_name->tname,
+                                       TRUE);
+
+          /*
+            Since username is part of the hash key, when the user name
+            is renamed, the hash key is changed. Update the hash to
+            ensure that the position matches the new hash key value
+          */
+          my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
+                         old_key_length);
+          /*
+            hash_update() operation could have moved element from the tail
+            of the hash to the current position. So we need to take a look
+            at the element in current position once again.
+            Thanks to the fact that hash_update() for our HASH implementation
+            won't move any elements from the tail of the hash to the positions
+            before the current one (a.k.a. head) it is safe to continue
+            iteration without restarting.
+          */
+          idx--;
+          break;
+        }
 
       case 5:
         acl_proxy_user->set_user (&mem, user_to->user.str);
@@ -6279,7 +6312,7 @@ static int handle_grant_data(TABLE_LIST 
     }
   }
 
-  /* Handle procedures table. */
+  /* Handle stored routines table. */
   if ((found= handle_grant_table(tables, 4, drop, user_from, user_to)) < 0)
   {
     /* Handle of table failed, don't touch in-memory array. */
@@ -6296,6 +6329,15 @@ static int handle_grant_data(TABLE_LIST 
       if (! drop && ! user_to)
         goto end;
     }
+    /* Handle funcs array. */
+    if (((handle_grant_struct(4, drop, user_from, user_to) && ! result) ||
+         found) && ! result)
+    {
+      result= 1; /* At least one record/element found. */
+      /* If search is requested, we do not need to search further. */
+      if (! drop && ! user_to)
+        goto end;
+    }
   }
 
   /* Handle tables table. */

No bundle (reason: revision is a merge (you can force generation of a bundle with env var BZR_FORCE_BUNDLE=1)).
Thread
bzr commit into mysql-trunk branch (Georgi.Kodinov:3738) Georgi Kodinov9 Mar