diff options
35 files changed, 1169 insertions, 216 deletions
diff --git a/Docs/mysqld_error.txt b/Docs/mysqld_error.txt index c164e8bd3a0..6370d8aac46 100644 --- a/Docs/mysqld_error.txt +++ b/Docs/mysqld_error.txt @@ -539,8 +539,8 @@ character-set=latin1 "Using storage engine %s for table '%s'", #define ER_CANT_AGGREGATE_2COLLATIONS 1267 "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -#define ER_DROP_USER 1268 -"Can't drop one or more of the requested users", +#define ER_HANDLE_USER 1268 +"Operation %s failed for %d of the requested users", #define ER_REVOKE_GRANTS 1269 "Can't revoke all privileges, grant for one or more of the requested users", #define ER_CANT_AGGREGATE_3COLLATIONS 1270 diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 478b46dd246..f5994e8e71d 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -284,7 +284,7 @@ #define ER_WARN_DATA_TRUNCATED 1265 #define ER_WARN_USING_OTHER_HANDLER 1266 #define ER_CANT_AGGREGATE_2COLLATIONS 1267 -#define ER_DROP_USER 1268 +#define ER_HANDLE_USER 1268 #define ER_REVOKE_GRANTS 1269 #define ER_CANT_AGGREGATE_3COLLATIONS 1270 #define ER_CANT_AGGREGATE_NCOLLATIONS 1271 diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 1ac6165e383..262afc3ce2f 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -218,17 +218,19 @@ grant select on test.* to drop_user3@localhost; grant select on *.* to drop_user4@localhost; drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; -ERROR HY000: Can't drop one or more of the requested users revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +ERROR HY000: Operation DROP USER failed for 4 of the requested users drop table t1; grant usage on *.* to mysqltest_1@localhost identified by "password"; -grant select, update, insert on test.* to mysqltest@localhost; +grant select, update, insert on test.* to mysqltest_1@localhost; show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' +GRANT SELECT, INSERT, UPDATE ON `test`.* TO 'mysqltest_1'@'localhost' drop user mysqltest_1@localhost; SET NAMES koi8r; CREATE DATABASE ÂÄ; @@ -252,6 +254,7 @@ Grants for ÀÚÅÒ@localhost GRANT USAGE ON *.* TO 'ÀÚÅÒ'@'localhost' GRANT SELECT (ËÏÌ) ON `ÂÄ`.`ÔÁÂ` TO 'ÀÚÅÒ'@'localhost' REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost; +DROP USER ÀÚÅÒ@localhost; DROP DATABASE ÂÄ; SET NAMES latin1; USE test; diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 9e1e5d50f31..fee9150ca50 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -60,3 +60,166 @@ use test; delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; flush privileges; +set sql_mode='maxdb'; +drop table if exists t1, t2; +create table t1(c1 int); +create table t2(c1 int, c2 int); +create user 'mysqltest_1'; +create user 'mysqltest_1'; +ERROR HY000: Operation CREATE USER failed for 1 of the requested users +create user 'mysqltest_2' identified by 'Mysqltest-2'; +create user 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff'; +grant select on *.* to 'mysqltest_2'; +grant insert on test.* to 'mysqltest_2'; +grant update on test.t1 to 'mysqltest_2'; +grant update (c2) on test.t2 to 'mysqltest_2'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +host user password +% mysqltest_1 +% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +host db user +% test mysqltest_2 +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +host db user table_name +% test mysqltest_2 t1 +% test mysqltest_2 t2 +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +host db user table_name column_name +% test mysqltest_2 t2 c2 +show grants for 'mysqltest_1'; +Grants for mysqltest_1@% +GRANT USAGE ON *.* TO 'mysqltest_1'@'%' +show grants for 'mysqltest_2'; +Grants for mysqltest_2@% +GRANT SELECT ON *.* TO 'mysqltest_2'@'%' IDENTIFIED BY PASSWORD '*BD447CBA355AF58578D3AE33BA2E2CD388BA08D1' +GRANT INSERT ON "test".* TO 'mysqltest_2'@'%' +GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_2'@'%' +GRANT UPDATE ON "test"."t1" TO 'mysqltest_2'@'%' +drop user 'mysqltest_1'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +host user password +% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +host db user +% test mysqltest_2 +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +host db user table_name +% test mysqltest_2 t1 +% test mysqltest_2 t2 +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +host db user table_name column_name +% test mysqltest_2 t2 c2 +show grants for 'mysqltest_1'; +ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' +rename user 'mysqltest_2' to 'mysqltest_1'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +host user password +% mysqltest_1 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +host db user +% test mysqltest_1 +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +host db user table_name +% test mysqltest_1 t1 +% test mysqltest_1 t2 +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +host db user table_name column_name +% test mysqltest_1 t2 c2 +show grants for 'mysqltest_1'; +Grants for mysqltest_1@% +GRANT SELECT ON *.* TO 'mysqltest_1'@'%' IDENTIFIED BY PASSWORD '*BD447CBA355AF58578D3AE33BA2E2CD388BA08D1' +GRANT INSERT ON "test".* TO 'mysqltest_1'@'%' +GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_1'@'%' +GRANT UPDATE ON "test"."t1" TO 'mysqltest_1'@'%' +drop user 'mysqltest_1', 'mysqltest_3'; +drop table t1, t2; +insert into mysql.db set user='mysqltest_1', db='%', host='%'; +flush privileges; +show grants for 'mysqltest_1'; +ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' +revoke all privileges, grant option from 'mysqltest_1'; +ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users +drop user 'mysqltest_1'; +select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user; +host db user +insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1'; +flush privileges; +show grants for 'mysqltest_1'; +ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' +drop user 'mysqltest_1'; +select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name; +host db user table_name +insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1'; +flush privileges; +show grants for 'mysqltest_1'; +ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%' +drop user 'mysqltest_1'; +select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name; +host db user table_name column_name +create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +create user 'mysqltest_1', 'mysqltest_2' identified by 'Mysqltest-2', 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff'; +rename user 'mysqltest_1' to 'mysqltest_1a', 'mysqltest_2' TO 'mysqltest_2a', 'mysqltest_3' TO 'mysqltest_3a'; +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +ERROR HY000: Operation DROP USER failed for 3 of the requested users +drop user 'mysqltest_1a', 'mysqltest_2a', 'mysqltest_3a'; +create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +create user 'mysqltest_1a', 'mysqltest_2', 'mysqltest_3a'; +ERROR HY000: Operation CREATE USER failed for 1 of the requested users +rename user 'mysqltest_1a' to 'mysqltest_1b', 'mysqltest_2a' TO 'mysqltest_2b', 'mysqltest_3a' TO 'mysqltest_3b'; +ERROR HY000: Operation RENAME USER failed for 1 of the requested users +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +drop user 'mysqltest_1b', 'mysqltest_2b', 'mysqltest_3b'; +ERROR HY000: Operation DROP USER failed for 1 of the requested users +create user 'mysqltest_2' identified by 'Mysqltest-2'; +drop user 'mysqltest_2' identified by 'Mysqltest-2'; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by 'Mysqltest-2'' at line 1 +create user '%@b'@'b'; +show grants for '%@b'@'b'; +Grants for %@b@b +GRANT USAGE ON *.* TO '%@b'@'b' +grant select on mysql.* to '%@b'@'b'; +show grants for '%@b'@'b'; +Grants for %@b@b +GRANT USAGE ON *.* TO '%@b'@'b' +GRANT SELECT ON "mysql".* TO '%@b'@'b' +rename user '%@b'@'b' to '%@a'@'a'; +show grants for '%@b'@'b'; +ERROR 42000: There is no such grant defined for user '%@b' on host 'b' +show grants for '%@a'@'a'; +Grants for %@a@a +GRANT USAGE ON *.* TO '%@a'@'a' +GRANT SELECT ON "mysql".* TO '%@a'@'a' +drop user '%@a'@'a'; +create user mysqltest_2@localhost; +grant usage on *.* to mysqltest_2@localhost with grant option; +select host,user,password from mysql.user order by host,user,password; +ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'mysql' +create user mysqltest_A@'%'; +rename user mysqltest_A@'%' to mysqltest_B@'%'; +drop user mysqltest_B@'%'; +drop user mysqltest_2@localhost; +create user mysqltest_3@localhost; +grant all privileges on mysql.* to mysqltest_3@localhost; +select host,user,password from mysql.user order by host,user,password; +host user password +% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1 +127.0.0.1 root +chilla% +chilla% root +localhost +localhost mysqltest_3 +localhost root +insert into mysql.user set host='%', user='mysqltest_B'; +create user mysqltest_A@'%'; +ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql' +rename user mysqltest_B@'%' to mysqltest_C@'%'; +ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql' +drop user mysqltest_B@'%'; +ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql' +drop user mysqltest_B@'%'; +drop user mysqltest_3@localhost; diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result index e8d8e4063f1..9b12b0baa1d 100644 --- a/mysql-test/r/ps_1general.result +++ b/mysql-test/r/ps_1general.result @@ -835,19 +835,19 @@ identified by 'looser' ; show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' drop table mysqltest.t9 ; show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' prepare s_t1 from 'select a as my_col from t1' ; execute s_t1 ; my_col diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index dfd5f4db7c6..c004699d901 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -162,16 +162,18 @@ grant select(a) on test.t1 to drop_user1@localhost; grant select on test.t1 to drop_user2@localhost; grant select on test.* to drop_user3@localhost; grant select on *.* to drop_user4@localhost; ---error 1268 +# Drop user now implicitly revokes all privileges. drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +--error 1269 revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; +--error 1268 drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; drop table t1; grant usage on *.* to mysqltest_1@localhost identified by "password"; -grant select, update, insert on test.* to mysqltest@localhost; +grant select, update, insert on test.* to mysqltest_1@localhost; show grants for mysqltest_1@localhost; drop user mysqltest_1@localhost; @@ -195,6 +197,9 @@ GRANT SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ TO ÀÚÅÒ@localhost; SHOW GRANTS FOR ÀÚÅÒ@localhost; REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost; +# Revoke does not drop user. Leave a clean user table for the next tests. +DROP USER ÀÚÅÒ@localhost; + DROP DATABASE ÂÄ; SET NAMES latin1; diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index fe4a5b55b82..c439bd05d2f 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -78,3 +78,150 @@ use test; delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; flush privileges; + +# +# Create and drop user +# +set sql_mode='maxdb'; +--disable_warnings +drop table if exists t1, t2; +--enable_warnings +create table t1(c1 int); +create table t2(c1 int, c2 int); +# +# Three forms of CREATE USER +create user 'mysqltest_1'; +--error 1268 +create user 'mysqltest_1'; +create user 'mysqltest_2' identified by 'Mysqltest-2'; +create user 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff'; +grant select on *.* to 'mysqltest_2'; +grant insert on test.* to 'mysqltest_2'; +grant update on test.t1 to 'mysqltest_2'; +grant update (c2) on test.t2 to 'mysqltest_2'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +show grants for 'mysqltest_1'; +show grants for 'mysqltest_2'; +# +# Drop +drop user 'mysqltest_1'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +--error 1141 +show grants for 'mysqltest_1'; +# +# Rename +rename user 'mysqltest_2' to 'mysqltest_1'; +select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password; +select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user; +select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name; +select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name; +show grants for 'mysqltest_1'; +drop user 'mysqltest_1', 'mysqltest_3'; +# +# Grant must not create user +#grant all on test.t1 to 'mysqltest_1'; +#drop user 'mysqltest_1'; +# +# Cleanup +drop table t1, t2; +# +# Add a stray record +insert into mysql.db set user='mysqltest_1', db='%', host='%'; +flush privileges; +--error 1141 +show grants for 'mysqltest_1'; +--error 1269 +revoke all privileges, grant option from 'mysqltest_1'; +drop user 'mysqltest_1'; +select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user; +# +# Add a stray record +insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1'; +flush privileges; +--error 1141 +show grants for 'mysqltest_1'; +drop user 'mysqltest_1'; +select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name; +# +# Add a stray record +insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1'; +flush privileges; +--error 1141 +show grants for 'mysqltest_1'; +drop user 'mysqltest_1'; +select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name; +# +# Handle multi user lists +create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +create user 'mysqltest_1', 'mysqltest_2' identified by 'Mysqltest-2', 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff'; +rename user 'mysqltest_1' to 'mysqltest_1a', 'mysqltest_2' TO 'mysqltest_2a', 'mysqltest_3' TO 'mysqltest_3a'; +--error 1268 +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +drop user 'mysqltest_1a', 'mysqltest_2a', 'mysqltest_3a'; +# +# Let one of multiple users fail +create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +--error 1268 +create user 'mysqltest_1a', 'mysqltest_2', 'mysqltest_3a'; +--error 1268 +rename user 'mysqltest_1a' to 'mysqltest_1b', 'mysqltest_2a' TO 'mysqltest_2b', 'mysqltest_3a' TO 'mysqltest_3b'; +drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3'; +--error 1268 +drop user 'mysqltest_1b', 'mysqltest_2b', 'mysqltest_3b'; +# +# Obsolete syntax has been dropped +create user 'mysqltest_2' identified by 'Mysqltest-2'; +--error 1064 +drop user 'mysqltest_2' identified by 'Mysqltest-2'; +# +# Strange user names +create user '%@b'@'b'; +show grants for '%@b'@'b'; +grant select on mysql.* to '%@b'@'b'; +show grants for '%@b'@'b'; +rename user '%@b'@'b' to '%@a'@'a'; +--error 1141 +show grants for '%@b'@'b'; +show grants for '%@a'@'a'; +drop user '%@a'@'a'; +# +# USAGE WITH GRANT OPTION is sufficient. +create user mysqltest_2@localhost; +grant usage on *.* to mysqltest_2@localhost with grant option; +connect (user2,localhost,mysqltest_2,,); +connection user2; +--error 1044 +select host,user,password from mysql.user order by host,user,password; +create user mysqltest_A@'%'; +rename user mysqltest_A@'%' to mysqltest_B@'%'; +drop user mysqltest_B@'%'; +disconnect user2; +connection default; +drop user mysqltest_2@localhost; +# +# ALL PRIVILEGES without GRANT OPTION is not sufficient. +create user mysqltest_3@localhost; +grant all privileges on mysql.* to mysqltest_3@localhost; +connect (user3,localhost,mysqltest_3,,); +connection user3; +select host,user,password from mysql.user order by host,user,password; +insert into mysql.user set host='%', user='mysqltest_B'; +--error 1044 +create user mysqltest_A@'%'; +--error 1044 +rename user mysqltest_B@'%' to mysqltest_C@'%'; +--error 1044 +drop user mysqltest_B@'%'; +disconnect user3; +connection default; +drop user mysqltest_B@'%'; +drop user mysqltest_3@localhost; +# + diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 55a8499145a..54d22e62dba 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -296,7 +296,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index ee1341cf095..7385be9545c 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -287,7 +287,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 26ff759ca40..7015ed90789 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -296,7 +296,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 8abb684fe11..54ca033657e 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -284,7 +284,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 1211bd305dd..b89ebb42500 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -289,7 +289,7 @@ character-set=latin7 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 5c54b5e01a8..4e370a63099 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -284,7 +284,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 4d1a4a17ebe..b4afa45ee46 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -297,7 +297,7 @@ character-set=latin1 "Daten abgeschnitten für Spalte '%s' in Zeile %ld", "Für Tabelle '%s' wird Speicher-Engine %s benutzt", "Unerlaubte Vermischung der Kollationen (%s,%s) und (%s,%s) für die Operation '%s'", -"Kann einen oder mehrere der angegebenen Benutzer nicht löschen", +"Das Kommando %s scheiterte für %d von den betroffenen Benutzern", "Kann nicht alle Berechtigungen widerrufen, grant for one or more of the requested users", "Unerlaubte Vermischung der Kollationen (%s,%s), (%s,%s), (%s,%s) für die Operation '%s'", "Unerlaubte Vermischung der Kollationen für die Operation '%s'", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 146d25cfaee..afc91d0c69e 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -284,7 +284,7 @@ character-set=greek "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index be195b86503..61c112170b2 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -289,7 +289,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 685d2d0c972..e6a00332093 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -284,7 +284,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 665e1991198..98282af52d6 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -288,7 +288,7 @@ character-set=ujis "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index d4f59b768ff..b10a83beee9 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -284,7 +284,7 @@ character-set=euckr "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 780bfd8d8ca..e5a41b7d3d9 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -286,7 +286,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index d723d0cc475..334313c1916 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -286,7 +286,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index b3242c46310..0d8deb30e77 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -289,7 +289,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index b2a993bf002..e47a69a5c25 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -286,7 +286,7 @@ character-set=latin1 "Dado truncado para coluna '%s' na linha %ld", "Usando engine de armazenamento %s para tabela '%s'", "Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'", -"Não pode remover um ou mais dos usuários pedidos", +"Operation %s failed for %d of the requested users", "Não pode revocar todos os privilégios, grant para um ou mais dos usuários pedidos", "Ilegal combinação de collations (%s,%s), (%s,%s), (%s,%s) para operação '%s'", "Ilegal combinação de collations para operação '%s'", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 7f5ef856d3a..c5a63223c22 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -289,7 +289,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 74cafac8b52..04c51d5f532 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -289,7 +289,7 @@ character-set=koi8r "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 9a09358a35a..f267faeccbd 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -277,7 +277,7 @@ character-set=cp1250 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 4c694fecc88..8b7bb730cf0 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -292,7 +292,7 @@ character-set=latin2 "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 94316edd083..c0e663d6484 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -288,7 +288,7 @@ character-set=latin1 "Datos truncados para columna '%s' en la línea %ld", "Usando motor de almacenamiento %s para tabla '%s'", "Ilegal mezcla de collations (%s,%s) y (%s,%s) para operación '%s'", -"No puede remover uno o mas de los usuarios solicitados", +"Operation %s failed for %d of the requested users", "No puede revocar todos los privilegios, derecho para uno o mas de los usuarios solicitados", "Ilegal mezcla de collations (%s,%s), (%s,%s), (%s,%s) para operación '%s'", "Ilegal mezcla de collations para operación '%s'", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index cd57653969f..831ccfbe978 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -284,7 +284,7 @@ character-set=latin1 "Data truncated for column '%s' at row %ld", "Använder handler %s för tabell '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 0b3400a4e88..46a0adf922f 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -290,7 +290,7 @@ character-set=koi8u "Data truncated for column '%s' at row %ld", "Using storage engine %s for table '%s'", "Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'", -"Can't drop one or more of the requested users", +"Operation %s failed for %d of the requested users", "Can't revoke all privileges, grant for one or more of the requested users", "Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'", "Illegal mix of collations for operation '%s'", diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 9ce00a01e31..d3bfb5b4d1d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -919,7 +919,7 @@ static void acl_update_user(const char *user, const char *host, { if (!acl_user->host.hostname && !host[0] || acl_user->host.hostname && - !my_strcasecmp(&my_charset_latin1, host, acl_user->host.hostname)) + !my_strcasecmp(system_charset_info, host, acl_user->host.hostname)) { acl_user->access=privileges; if (mqh->bits & 1) @@ -998,7 +998,7 @@ static void acl_update_db(const char *user, const char *host, const char *db, { if (!acl_db->host.hostname && !host[0] || acl_db->host.hostname && - !my_strcasecmp(&my_charset_latin1, host, acl_db->host.hostname)) + !my_strcasecmp(system_charset_info, host, acl_db->host.hostname)) { if (!acl_db->db && !db[0] || acl_db->db && !strcmp(db,acl_db->db)) @@ -1141,7 +1141,7 @@ static void init_check_host(void) DBUG_ENTER("init_check_host"); VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip), acl_users.elements,1)); - VOID(hash_init(&acl_check_hosts,&my_charset_latin1,acl_users.elements,0,0, + VOID(hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0, (hash_get_key) check_get_key,0,0)); if (!allow_all_hosts) { @@ -1157,7 +1157,7 @@ static void init_check_host(void) { // Check if host already exists acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,j, acl_host_and_ip *); - if (!my_strcasecmp(&my_charset_latin1, + if (!my_strcasecmp(system_charset_info, acl_user->host.hostname, acl->hostname)) break; // already stored } @@ -1233,7 +1233,7 @@ bool check_change_password(THD *thd, const char *host, const char *user, } if (!thd->slave_thread && (strcmp(thd->user,user) || - my_strcasecmp(&my_charset_latin1, host, thd->host_or_ip))) + my_strcasecmp(system_charset_info, host, thd->host_or_ip))) { if (check_access(thd, UPDATE_ACL, "mysql",0,1,0)) return(1); @@ -1402,7 +1402,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, return (tmp & host->ip_mask) == host->ip; } return (!host->hostname || - (hostname && !wild_case_compare(&my_charset_latin1, + (hostname && !wild_case_compare(system_charset_info, hostname,host->hostname)) || (ip && !wild_compare(ip,host->hostname,0))); } @@ -1415,7 +1415,7 @@ bool hostname_requires_resolving(const char *hostname) int namelen= strlen(hostname); int lhlen= strlen(my_localhost); if ((namelen == lhlen) && - !my_strnncoll(&my_charset_latin1, (const uchar *)hostname, namelen, + !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen, (const uchar *)my_localhost, strlen(my_localhost))) return FALSE; for (; (cur=*hostname); hostname++) @@ -1464,8 +1464,8 @@ static bool update_user_table(THD *thd, const char *host, const char *user, if (!(table=open_ltable(thd,&tables,TL_WRITE))) DBUG_RETURN(1); /* purecov: deadcode */ - table->field[0]->store(host,(uint) strlen(host), &my_charset_latin1); - table->field[1]->store(user,(uint) strlen(user), &my_charset_latin1); + table->field[0]->store(host,(uint) strlen(host), system_charset_info); + table->field[1]->store(user,(uint) strlen(user), system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, @@ -1478,7 +1478,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user, DBUG_RETURN(1); /* purecov: deadcode */ } store_record(table,record[1]); - table->field[2]->store(new_password, new_password_len, &my_charset_latin1); + table->field[2]->store(new_password, new_password_len, system_charset_info); if ((error=table->file->update_row(table->record[1],table->record[0]))) { table->file->print_error(error,MYF(0)); /* purecov: deadcode */ @@ -1546,8 +1546,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, password=combo.password.str; } - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(combo.user.str,combo.user.length, system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0], 0, (byte*) table->field[0]->ptr, @@ -1581,11 +1581,11 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, old_row_exists = 0; restore_record(table,default_values); // cp empty row from default_values table->field[0]->store(combo.host.str,combo.host.length, - &my_charset_latin1); + system_charset_info); table->field[1]->store(combo.user.str,combo.user.length, - &my_charset_latin1); + system_charset_info); table->field[2]->store(password, password_len, - &my_charset_latin1); + system_charset_info); } else { @@ -1596,14 +1596,14 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, DBUG_ASSERT(combo.host.str); if (thd->user && combo.password.str && (strcmp(thd->user,combo.user.str) || - my_strcasecmp(&my_charset_latin1, + my_strcasecmp(system_charset_info, combo.host.str, thd->host_or_ip)) && check_access(thd, UPDATE_ACL, "mysql",0,1,0)) goto end; old_row_exists = 1; store_record(table,record[1]); // Save copy for update if (combo.password.str) // If password given - table->field[2]->store(password, password_len, &my_charset_latin1); + table->field[2]->store(password, password_len, system_charset_info); else if (!rights && !revoke_grant && lex->ssl_type == SSL_TYPE_NOT_SPECIFIED && !lex->mqh.bits) { @@ -1648,13 +1648,13 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, table->field[27]->store("", 0, &my_charset_latin1); if (lex->ssl_cipher) table->field[25]->store(lex->ssl_cipher, - strlen(lex->ssl_cipher), &my_charset_latin1); + strlen(lex->ssl_cipher), system_charset_info); if (lex->x509_issuer) table->field[26]->store(lex->x509_issuer, - strlen(lex->x509_issuer), &my_charset_latin1); + strlen(lex->x509_issuer), system_charset_info); if (lex->x509_subject) table->field[27]->store(lex->x509_subject, - strlen(lex->x509_subject), &my_charset_latin1); + strlen(lex->x509_subject), system_charset_info); break; case SSL_TYPE_NOT_SPECIFIED: break; @@ -1756,9 +1756,9 @@ static int replace_db_table(TABLE *table, const char *db, DBUG_RETURN(-1); } - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, (byte*) table->field[0]->ptr, @@ -1772,9 +1772,9 @@ static int replace_db_table(TABLE *table, const char *db, } old_row_exists = 0; restore_record(table,default_values); // cp empty row from default_values - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); } else { @@ -1862,6 +1862,7 @@ public: GRANT_TABLE(const char *h, const char *d,const char *u, const char *t, ulong p, ulong c); GRANT_TABLE (TABLE *form, TABLE *col_privs); + ~GRANT_TABLE(); bool ok() { return privs != 0 || cols != 0; } }; @@ -1887,7 +1888,7 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; hash_key = (char*) alloc_root(&memex,key_length); strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); - (void) hash_init(&hash_columns,&my_charset_latin1, + (void) hash_init(&hash_columns,system_charset_info, 0,0,0, (hash_get_key) get_key_column,0,0); } @@ -1911,7 +1912,8 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) if (!db || !tname) { /* Wrong table row; Ignore it */ - privs = cols = 0; /* purecov: inspected */ + hash_clear(&hash_columns); /* allow for destruction */ + privs= cols= 0; /* purecov: inspected */ return; /* purecov: inspected */ } if (lower_case_table_names) @@ -1928,16 +1930,16 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) privs = fix_rights_for_table(privs); cols = fix_rights_for_column(cols); - (void) hash_init(&hash_columns,&my_charset_latin1, + (void) hash_init(&hash_columns,system_charset_info, 0,0,0, (hash_get_key) get_key_column,0,0); if (cols) { int key_len; col_privs->field[0]->store(orig_host,(uint) strlen(orig_host), - &my_charset_latin1); - col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1); - col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1); + system_charset_info); + col_privs->field[1]->store(db,(uint) strlen(db), system_charset_info); + col_privs->field[2]->store(user,(uint) strlen(user), system_charset_info); + col_privs->field[3]->store(tname,(uint) strlen(tname), system_charset_info); key_len=(col_privs->field[0]->pack_length()+ col_privs->field[1]->pack_length()+ col_privs->field[2]->pack_length()+ @@ -1975,6 +1977,12 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) } +GRANT_TABLE::~GRANT_TABLE() +{ + hash_free(&hash_columns); +} + + static byte* get_grant_table(GRANT_TABLE *buff,uint *length, my_bool not_used __attribute__((unused))) { @@ -2011,15 +2019,15 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip, if (exact) { if ((host && - !my_strcasecmp(&my_charset_latin1, host, grant_table->host)) || + !my_strcasecmp(system_charset_info, host, grant_table->host)) || (ip && !strcmp(ip,grant_table->host))) return grant_table; } else { - if (((host && !wild_case_compare(&my_charset_latin1, + if (((host && !wild_case_compare(system_charset_info, host,grant_table->host)) || - (ip && !wild_case_compare(&my_charset_latin1, + (ip && !wild_case_compare(system_charset_info, ip,grant_table->host))) && (!found || found->sort < grant_table->sort)) found=grant_table; // Host ok @@ -2048,10 +2056,10 @@ static int replace_column_table(GRANT_TABLE *g_t, byte key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_column_table"); - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); - table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); + table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info); key_length=(table->field[0]->pack_length()+ table->field[1]->pack_length()+ table->field[2]->pack_length()+ table->field[3]->pack_length()); key_copy(key,table->record[0],table->key_info,key_length); @@ -2069,7 +2077,7 @@ static int replace_column_table(GRANT_TABLE *g_t, bool old_row_exists=0; key_restore(table->record[0],key,table->key_info,key_length); table->field[4]->store(xx->column.ptr(),xx->column.length(), - &my_charset_latin1); + system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr, @@ -2088,7 +2096,7 @@ static int replace_column_table(GRANT_TABLE *g_t, restore_record(table,default_values); // Get empty record key_restore(table->record[0],key,table->key_info,key_length); table->field[4]->store(xx->column.ptr(),xx->column.length(), - &my_charset_latin1); + system_charset_info); } else { @@ -2160,7 +2168,7 @@ static int replace_column_table(GRANT_TABLE *g_t, { GRANT_COLUMN *grant_column = NULL; char colum_name_buf[HOSTNAME_LENGTH+1]; - String column_name(colum_name_buf,sizeof(colum_name_buf),&my_charset_latin1); + String column_name(colum_name_buf,sizeof(colum_name_buf),system_charset_info); privileges&= ~rights; table->field[6]->store((longlong) @@ -2231,10 +2239,10 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } restore_record(table,default_values); // Get empty record - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); - table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); + table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info); store_record(table,record[1]); // store at pos 1 table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, @@ -2279,7 +2287,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } } - table->field[4]->store(grantor,(uint) strlen(grantor), &my_charset_latin1); + table->field[4]->store(grantor,(uint) strlen(grantor), system_charset_info); table->field[6]->store((longlong) store_table_rights); table->field[7]->store((longlong) store_col_rights); rights=fix_rights_for_table(store_table_rights); @@ -2694,7 +2702,7 @@ my_bool grant_init(THD *org_thd) DBUG_ENTER("grant_init"); grant_option = FALSE; - (void) hash_init(&column_priv_hash,&my_charset_latin1, + (void) hash_init(&column_priv_hash,system_charset_info, 0,0,0, (hash_get_key) get_grant_table, (hash_free_key) free_grant_table,0); init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); @@ -2759,8 +2767,11 @@ my_bool grant_init(THD *org_thd) } } - if (mem_check->ok() && my_hash_insert(&column_priv_hash,(byte*) mem_check)) + if (! mem_check->ok()) + delete mem_check; + else if (my_hash_insert(&column_priv_hash,(byte*) mem_check)) { + delete mem_check; grant_option= FALSE; goto end_unlock; } @@ -3077,9 +3088,9 @@ bool check_grant_db(THD *thd,const char *db) idx); if (len < grant_table->key_length && !memcmp(grant_table->hash_key,helping,len) && - (thd->host && !wild_case_compare(&my_charset_latin1, + (thd->host && !wild_case_compare(system_charset_info, thd->host,grant_table->host) || - (thd->ip && !wild_case_compare(&my_charset_latin1, + (thd->ip && !wild_case_compare(system_charset_info, thd->ip,grant_table->host)))) { error=0; // Found match @@ -3230,7 +3241,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (!(host=acl_user->host.hostname)) host= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) break; } if (counter == acl_users.elements) @@ -3284,7 +3295,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append(lex_user->user.str, lex_user->user.length, system_charset_info); global.append ("'@'",3); - global.append(lex_user->host.str,lex_user->host.length); + global.append(lex_user->host.str,lex_user->host.length, + system_charset_info); global.append ('\''); if (acl_user->salt_len) { @@ -3318,7 +3330,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (ssl_options++) global.append(' '); global.append("SUBJECT \'",9); - global.append(acl_user->x509_subject,strlen(acl_user->x509_subject)); + global.append(acl_user->x509_subject,strlen(acl_user->x509_subject), + system_charset_info); global.append('\''); } if (acl_user->ssl_cipher) @@ -3326,7 +3339,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) if (ssl_options++) global.append(' '); global.append("CIPHER '",8); - global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher)); + global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher), + system_charset_info); global.append('\''); } } @@ -3365,7 +3379,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) host= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { want_access=acl_db->access; if (want_access) @@ -3399,7 +3413,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) db.append(lex_user->user.str, lex_user->user.length, system_charset_info); db.append ("'@'",3); - db.append(lex_user->host.str, lex_user->host.length); + db.append(lex_user->host.str, lex_user->host.length, + system_charset_info); db.append ('\''); if (want_access & GRANT_ACL) db.append(" WITH GRANT OPTION",18); @@ -3425,7 +3440,7 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) user= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, + !my_strcasecmp(system_charset_info, lex_user->host.str, grant_table->orig_host)) { ulong table_access= grant_table->privs; @@ -3505,7 +3520,8 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) global.append(lex_user->user.str, lex_user->user.length, system_charset_info); global.append("'@'",3); - global.append(lex_user->host.str,lex_user->host.length); + global.append(lex_user->host.str,lex_user->host.length, + system_charset_info); global.append('\''); if (table_access & GRANT_ACL) global.append(" WITH GRANT OPTION",18); @@ -3565,6 +3581,27 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc) bzero((char*) &uc->user_resources, sizeof(uc->user_resources)); } +/* + Open the grant tables. + + SYNOPSIS + open_grant_tables() + thd The current thread. + tables (out) The 4 elements array for the opened tables. + + DESCRIPTION + Tables are numbered as follows: + 0 user + 1 db + 2 tables_priv + 3 columns_priv + + RETURN + 1 Skip GRANT handling during replication. + 0 OK. + < 0 Error. +*/ + int open_grant_tables(THD *thd, TABLE_LIST *tables) { DBUG_ENTER("open_grant_tables"); @@ -3640,111 +3677,641 @@ ACL_USER *check_acl_user(LEX_USER *user_name, } -bool mysql_drop_user(THD *thd, List <LEX_USER> &list) +/* + Modify a privilege table. + + SYNOPSIS + modify_grant_table() + table The table to modify. + host_field The host name field. + user_field The user name field. + user_to The new name for the user if to be renamed, + NULL otherwise. + + DESCRIPTION + Update user/host in the current record if user_to is not NULL. + Delete the current record if user_to is NULL. + + RETURN + 0 OK. + != 0 Error. +*/ + +static int modify_grant_table(TABLE *table, Field *host_field, + Field *user_field, LEX_USER *user_to) { - uint counter, acl_userd; - int result; - ACL_USER *acl_user; - ACL_DB *acl_db; - TABLE_LIST tables[4]; + int error; + DBUG_ENTER("modify_grant_table"); - DBUG_ENTER("mysql_drop_user"); + if (user_to) + { + /* rename */ + store_record(table, record[1]); + host_field->store(user_to->host.str, user_to->host.length, + system_charset_info); + user_field->store(user_to->user.str, user_to->user.length, + system_charset_info); + if ((error= table->file->update_row(table->record[1], table->record[0]))) + table->file->print_error(error, MYF(0)); + } + else + { + /* delete */ + if ((error=table->file->delete_row(table->record[0]))) + table->file->print_error(error, MYF(0)); + } - if ((result= open_grant_tables(thd, tables))) - DBUG_RETURN(result != 1); + DBUG_RETURN(error); +} - rw_wrlock(&LOCK_grant); - VOID(pthread_mutex_lock(&acl_cache->lock)); - LEX_USER *user_name; - List_iterator <LEX_USER> user_list(list); - while ((user_name=user_list++)) +/* + Handle a privilege table. + + SYNOPSIS + handle_grant_table() + tables The array with the four open tables. + table_no The number of the table 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. + + DESCRIPTION + Scan through all records in a grant table and apply the requested + operation. For the "user" table, a single index access is sufficient, + since there is an unique index on (host, user). + Delete from grant table if drop is true. + Update in grant table if drop is false and user_to is not NULL. + Search in grant table if drop is false and user_to is NULL. + Tables are numbered as follows: + 0 user + 1 db + 2 tables_priv + 3 columns_priv + + RETURN + > 0 At least one record matched. + 0 OK, but no record matched. + < 0 Error. +*/ + +static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop, + LEX_USER *user_from, LEX_USER *user_to) +{ + int result= 0; + int error; + TABLE *table= tables[table_no].table; + Field *host_field= table->field[0]; + Field *user_field= table->field[table_no ? 2 : 1]; + char *host_str= user_from->host.str; + char *user_str= user_from->user.str; + const char *host; + const char *user; + DBUG_ENTER("handle_grant_table"); + + if (! table_no) { - if (!(acl_user= check_acl_user(user_name, &counter))) + /* + The 'user' table has an unique index on (host, user). + Thus, we can handle everything with a single index access. + The host- and user fields are consecutive in the user table records. + So we set host- and user fields of table->record[0] and use the + pointer to the host field as key. + index_read_idx() will replace table->record[0] (its first argument) + by the searched record, if it exists. + */ + DBUG_PRINT("info",("read table: '%s' search: '%s'@'%s'", + table->real_name, user_str, host_str)); + host_field->store(host_str, user_from->host.length, system_charset_info); + user_field->store(user_str, user_from->user.length, system_charset_info); + if ((error= table->file->index_read_idx(table->record[0], 0, + (byte*) host_field->ptr, 0, + HA_READ_KEY_EXACT))) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; No such user", - user_name->user.str, - user_name->host.str); - result= -1; - continue; + if (error != HA_ERR_KEY_NOT_FOUND) + { + table->file->print_error(error, MYF(0)); + result= -1; + } } - if ((acl_user->access & ~0)) + else { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Global privileges exists", - user_name->user.str, - user_name->host.str); + /* If requested, delete or update the record. */ + result= ((drop || user_to) && + modify_grant_table(table, host_field, user_field, user_to)) ? + -1 : 1; /* Error or found. */ + } + DBUG_PRINT("info",("read result: %d", result)); + } + else + { + /* + The non-'user' table do not have indexes on (host, user). + And their host- and user fields are not consecutive. + Thus, we need to do a table scan to find all matching records. + */ + if ((error= table->file->ha_rnd_init(1))) + { + table->file->print_error(error, MYF(0)); result= -1; + } + else + { +#ifdef EXTRA_DEBUG + DBUG_PRINT("info",("scan table: '%s' search: '%s'@'%s'", + table->real_name, user_str, host_str)); +#endif + while ((error= table->file->rnd_next(table->record[0])) != + HA_ERR_END_OF_FILE) + { + if (error) + { + /* Most probable 'deleted record'. */ + DBUG_PRINT("info",("scan error: %d", error)); + continue; + } + if (! (host= get_field(&mem, host_field))) + host= ""; + if (! (user= get_field(&mem, user_field))) + user= ""; + +#ifdef EXTRA_DEBUG + DBUG_PRINT("loop",("scan fields: '%s'@'%s' '%s' '%s' '%s'", + user, host, + get_field(&mem, table->field[1]) /*db*/, + get_field(&mem, table->field[3]) /*table*/, + get_field(&mem, table->field[4]) /*column*/)); +#endif + if (strcmp(user_str, user) || + my_strcasecmp(system_charset_info, host_str, host)) + continue; + + /* If requested, delete or update the record. */ + result= ((drop || user_to) && + modify_grant_table(table, host_field, user_field, user_to)) ? + -1 : result ? result : 1; /* Error or keep result or found. */ + /* If search is requested, we do not need to search further. */ + if (! drop && ! user_to) + break ; + } + (void) table->file->ha_rnd_end(); + DBUG_PRINT("info",("scan result: %d", result)); + } + } + + DBUG_RETURN(result); +} + + +/* + Handle an in-memory privilege structure. + + SYNOPSIS + handle_grant_struct() + struct_no The number of the structure to handle (0..2). + 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. + + DESCRIPTION + Scan through all elements in an in-memory grant structure and apply + the requested operation. + Delete from grant structure if drop is true. + Update in grant structure if drop is false and user_to is not NULL. + Search in grant structure if drop is false and user_to is NULL. + Structures are numbered as follows: + 0 acl_users + 1 acl_dbs + 2 column_priv_hash + + RETURN + > 0 At least one element matched. + 0 OK, but no element matched. +*/ + +static int handle_grant_struct(uint struct_no, bool drop, + LEX_USER *user_from, LEX_USER *user_to) +{ + int result= 0; + uint idx; + uint elements; + const char *user; + const char *host; + ACL_USER *acl_user; + ACL_DB *acl_db; + GRANT_TABLE *grant_table; + DBUG_ENTER("handle_grant_struct"); + LINT_INIT(acl_user); + LINT_INIT(acl_db); + LINT_INIT(grant_table); + DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'", + struct_no, user_from->user.str, user_from->host.str)); + + /* Get the number of elements in the in-memory structure. */ + switch (struct_no) + { + case 0: + elements= acl_users.elements; + break; + case 1: + elements= acl_dbs.elements; + break; + default: + elements= column_priv_hash.records; + } + +#ifdef EXTRA_DEBUG + DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'", + struct_no, user_from->user.str, user_from->host.str)); +#endif + /* Loop over all elements. */ + for (idx= 0; idx < elements; idx++) + { + /* + Get a pointer to the element. + Unfortunaltely, the host default differs for the structures. + */ + switch (struct_no) + { + case 0: + acl_user= dynamic_element(&acl_users, idx, ACL_USER*); + user= acl_user->user; + if (!(host= acl_user->host.hostname)) + host= "%"; + break; + + case 1: + acl_db= dynamic_element(&acl_dbs, idx, ACL_DB*); + user= acl_db->user; + host= acl_db->host.hostname; + break; + + default: + grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, idx); + user= grant_table->user; + host= grant_table->host; + } + if (! user) + user= ""; + if (! host) + host= ""; +#ifdef EXTRA_DEBUG + DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'", + struct_no, idx, user, host)); +#endif + if (strcmp(user_from->user.str, user) || + my_strcasecmp(system_charset_info, user_from->host.str, host)) continue; + + result= 1; /* At least one element found. */ + if ( drop ) + { + switch ( struct_no ) + { + case 0: + delete_dynamic_element(&acl_users, idx); + break; + + case 1: + delete_dynamic_element(&acl_dbs, idx); + break; + + default: + hash_delete(&column_priv_hash, (byte*) grant_table); + } + elements--; + idx--; } - acl_userd= counter; + else if ( user_to ) + { + switch ( struct_no ) + { + case 0: + acl_user->user= strdup_root(&mem, user_to->user.str); + acl_user->host.hostname= strdup_root(&mem, user_to->host.str); + break; + + case 1: + acl_db->user= strdup_root(&mem, user_to->user.str); + acl_db->host.hostname= strdup_root(&mem, user_to->host.str); + break; - for (counter= 0 ; counter < acl_dbs.elements ; counter++) + default: + grant_table->user= strdup_root(&mem, user_to->user.str); + grant_table->host= strdup_root(&mem, user_to->host.str); + } + } + else { - const char *user,*host; - acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); - if (!(user= acl_db->user)) - user= ""; - if (!(host= acl_db->host.hostname)) - host= ""; - - if (!strcmp(user_name->user.str,user) && - !my_strcasecmp(system_charset_info, user_name->host.str, host)) - break; + /* If search is requested, we do not need to search further. */ + break; + } + } +#ifdef EXTRA_DEBUG + DBUG_PRINT("loop",("scan struct: %u result %d", struct_no, result)); +#endif + + DBUG_RETURN(result); +} + + +/* + Handle all privilege tables and in-memory privilege structures. + + SYNOPSIS + handle_grant_data() + tables The array with the four open tables. + 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. + + DESCRIPTION + Go through all grant tables and in-memory grant structures and apply + the requested operation. + Delete from grant data if drop is true. + Update in grant data if drop is false and user_to is not NULL. + Search in grant data if drop is false and user_to is NULL. + + RETURN + > 0 At least one element matched. + 0 OK, but no element matched. + < 0 Error. +*/ + +static int handle_grant_data(TABLE_LIST *tables, bool drop, + LEX_USER *user_from, LEX_USER *user_to) +{ + int result= 0; + int found; + DBUG_ENTER("handle_grant_data"); + + /* Handle user table. */ + if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0) + { + /* Handle of table failed, don't touch the in-memory array. */ + result= -1; + } + else + { + /* Handle user array. */ + if ((handle_grant_struct(0, drop, user_from, user_to) && ! result) || found) + { + 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; } - if (counter != acl_dbs.elements) + } + + /* Handle db table. */ + if ((found= handle_grant_table(tables, 1, drop, user_from, user_to)) < 0) + { + /* Handle of table failed, don't touch the in-memory array. */ + result= -1; + } + else + { + /* Handle db array. */ + if (((handle_grant_struct(1, drop, user_from, user_to) && ! result) || + found) && ! result) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Database privileges exists", - user_name->user.str, - user_name->host.str); - result= -1; - continue; + 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; } + } - for (counter= 0 ; counter < column_priv_hash.records ; counter++) + /* Handle tables table. */ + if ((found= handle_grant_table(tables, 2, drop, user_from, user_to)) < 0) + { + /* Handle of table failed, don't touch columns and in-memory array. */ + result= -1; + } + else + { + if (found && ! result) { - const char *user,*host; - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, - counter); - if (!(user=grant_table->user)) - user= ""; - if (!(host=grant_table->host)) - host= ""; - - if (!strcmp(user_name->user.str,user) && - !my_strcasecmp(system_charset_info, user_name->host.str, host)) - break; + result= 1; /* At least one record found. */ + /* If search is requested, we do not need to search further. */ + if (! drop && ! user_to) + goto end; } - if (counter != column_priv_hash.records) + + /* Handle columns table. */ + if ((found= handle_grant_table(tables, 3, drop, user_from, user_to)) < 0) { - sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Table privileges exists", - user_name->user.str, - user_name->host.str); + /* Handle of table failed, don't touch the in-memory array. */ result= -1; - continue; } + else + { + /* Handle columns hash. */ + if (((handle_grant_struct(2, drop, user_from, user_to) && ! result) || + found) && ! result) + result= 1; /* At least one record/element found. */ + } + } + end: + DBUG_RETURN(result); +} + + +/* + Create a list of users. + + SYNOPSIS + mysql_create_user() + thd The current thread. + list The users to create. + + RETURN + FALSE OK. + TRUE Error. +*/ + +bool mysql_create_user(THD *thd, List <LEX_USER> &list) +{ + int result; + int found; + uint failures; + ulong sql_mode; + LEX_USER *user_name; + List_iterator <LEX_USER> user_list(list); + TABLE_LIST tables[4]; + DBUG_ENTER("mysql_create_user"); + + /* CREATE USER may be skipped on replication client. */ + if ((result= open_grant_tables(thd, tables))) + DBUG_RETURN(result != 1); + + rw_wrlock(&LOCK_grant); + VOID(pthread_mutex_lock(&acl_cache->lock)); + + failures= 0; + while ((user_name= user_list++)) + { + /* + Search all in-memory structures and grant tables + for a mention of the new user name. + */ + if ((found= handle_grant_data(tables, 0, user_name, NULL))) + { + if (found > 0) + sql_print_error("CREATE USER: Cannot create user: '%s'@'%s': " + "User exists", + user_name->user.str, + user_name->host.str); + failures++; + result= TRUE; + } + + sql_mode= thd->variables.sql_mode; + thd->variables.sql_mode&= ~MODE_NO_AUTO_CREATE_USER; + if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1)) + { + failures++; + result= TRUE; + } + thd->variables.sql_mode= sql_mode; + } + + VOID(pthread_mutex_unlock(&acl_cache->lock)); + rw_unlock(&LOCK_grant); + close_thread_tables(thd); + if (result) + my_error(ER_HANDLE_USER, MYF(0), "CREATE USER" , failures ); + DBUG_RETURN(result); +} + + +/* + Drop a list of users and all their privileges. + + SYNOPSIS + mysql_drop_user() + thd The current thread. + list The users to drop. + + RETURN + FALSE OK. + TRUE Error. +*/ + +bool mysql_drop_user(THD *thd, List <LEX_USER> &list) +{ + int result; + int found; + uint failures; + LEX_USER *user_name; + List_iterator <LEX_USER> user_list(list); + TABLE_LIST tables[4]; + DBUG_ENTER("mysql_drop_user"); + + /* CREATE USER may be skipped on replication client. */ + if ((result= open_grant_tables(thd, tables))) + DBUG_RETURN(result != 1); + + rw_wrlock(&LOCK_grant); + VOID(pthread_mutex_lock(&acl_cache->lock)); + + failures= 0; + while ((user_name= user_list++)) + { + if ((found= handle_grant_data(tables, 1, user_name, NULL)) < 0) + { + failures++; + result= TRUE; + } + else if (! found) + { + sql_print_error("DROP USER: Cannot drop user '%s'@'%s': " + "No such user", + user_name->user.str, + user_name->host.str); + failures++; + result= TRUE; + } + } + + VOID(pthread_mutex_unlock(&acl_cache->lock)); + rw_unlock(&LOCK_grant); + close_thread_tables(thd); + if (result) + my_error(ER_HANDLE_USER, MYF(0), "DROP USER" , failures ); + DBUG_RETURN(result); +} + - tables[0].table->field[0]->store(user_name->host.str,(uint) - user_name->host.length, - system_charset_info); - tables[0].table->field[1]->store(user_name->user.str,(uint) - user_name->user.length, - system_charset_info); - tables[0].table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); - if (!tables[0].table->file->index_read_idx(tables[0].table->record[0],0, - (byte*) tables[0].table-> - field[0]->ptr, - tables[0].table-> - key_info[0].key_length, - HA_READ_KEY_EXACT)) +/* + Rename a user. + + SYNOPSIS + mysql_rename_user() + thd The current thread. + list The user name pairs: (from, to). + + RETURN + FALSE OK. + TRUE Error. +*/ + +bool mysql_rename_user(THD *thd, List <LEX_USER> &list) +{ + int result= 0; + int found; + uint failures; + LEX_USER *user_from; + LEX_USER *user_to; + List_iterator <LEX_USER> user_list(list); + TABLE_LIST tables[4]; + DBUG_ENTER("mysql_rename_user"); + + /* CREATE USER may be skipped on replication client. */ + if ((result= open_grant_tables(thd, tables))) + DBUG_RETURN(result != 1); + + rw_wrlock(&LOCK_grant); + VOID(pthread_mutex_lock(&acl_cache->lock)); + + failures= 0; + while ((user_from= user_list++)) + { + user_to= user_list++; + DBUG_ASSERT((user_to)); /* Syntax enforces pairs of users. */ + + /* + Search all in-memory structures and grant tables + for a mention of the new user name. + */ + if ((found= handle_grant_data(tables, 0, user_to, NULL))) { - int error; - if ((error = tables[0].table->file->delete_row(tables[0].table-> - record[0]))) + if (found > 0) + sql_print_error("RENAME USER: Cannot rename to: '%s'@'%s': User exists", + user_to->user.str, + user_to->host.str); + failures++; + result= TRUE; + } + else + { + if ((found= handle_grant_data(tables, 0, user_from, user_to)) < 0) { - tables[0].table->file->print_error(error, MYF(0)); - DBUG_RETURN(TRUE); + failures++; + result= TRUE; + } + else if (! found) + { + sql_print_error("RENAME USER: Cannot rename user: '%s'@'%s': " + "No such user", + user_from->user.str, + user_from->host.str); + failures++; + result= TRUE; } - delete_dynamic_element(&acl_users, acl_userd); } } @@ -3752,10 +4319,24 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list) rw_unlock(&LOCK_grant); close_thread_tables(thd); if (result) - my_message(ER_DROP_USER, ER(ER_DROP_USER), MYF(0)); + my_error(ER_HANDLE_USER, MYF(0), "RENAME USER", failures); DBUG_RETURN(result); } +/* + Revoke all privileges from a list of users. + + SYNOPSIS + mysql_revoke_all() + thd The current thread. + list The users to revoke all privileges from. + + RETURN + > 0 Error. Error message already sent. + 0 OK. + < 0 Error. Error message not yet sent. +*/ + bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) { uint counter, revoked; diff --git a/sql/sql_acl.h b/sql/sql_acl.h index f6074da5279..8f3ee072f43 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -182,7 +182,9 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant, bool mysql_show_grants(THD *thd, LEX_USER *user); void get_privilege_desc(char *to, uint max_length, ulong access); void get_mqh(const char *user, const char *host, USER_CONN *uc); +bool mysql_create_user(THD *thd, List <LEX_USER> &list); bool mysql_drop_user(THD *thd, List <LEX_USER> &list); +bool mysql_rename_user(THD *thd, List <LEX_USER> &list); bool mysql_revoke_all(THD *thd, List <LEX_USER> &list); void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 605204fe35d..e911b0ad4d1 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -78,7 +78,8 @@ enum enum_sql_command { SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO, SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS, SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES, - SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM, + SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER, + SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM, SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL, SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION, SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index fce8d294456..2dba134f54e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3370,6 +3370,21 @@ create_error: break; } #ifndef NO_EMBEDDED_ACCESS_CHECKS + case SQLCOM_CREATE_USER: + { + if (check_access(thd, GRANT_ACL,"mysql",0,1,0)) + break; + if (!(res= mysql_create_user(thd, lex->users_list))) + { + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); + } + send_ok(thd); + } + break; + } case SQLCOM_DROP_USER: { if (check_access(thd, GRANT_ACL,"mysql",0,1,0)) @@ -3378,8 +3393,23 @@ create_error: { if (mysql_bin_log.is_open()) { - Query_log_event qinfo(thd, thd->query, thd->query_length, 0); - mysql_bin_log.write(&qinfo); + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); + } + send_ok(thd); + } + break; + } + case SQLCOM_RENAME_USER: + { + if (check_access(thd, GRANT_ACL,"mysql",0,1,0)) + break; + if (!(res= mysql_rename_user(thd, lex->users_list))) + { + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query, thd->query_length, 0); + mysql_bin_log.write(&qinfo); } send_ok(thd); } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index dd9cd4af0f3..8e9b649acc3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -788,9 +788,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); opt_delete_options opt_delete_option varchar nchar nvarchar opt_outer table_list table_name opt_option opt_place opt_attribute opt_attribute_list attribute column_list column_list_id - opt_column_list grant_privileges opt_table user_list grant_option - grant_privilege grant_privilege_list - flush_options flush_option + opt_column_list grant_privileges opt_table grant_list grant_option + grant_privilege grant_privilege_list user_list rename_list + clear_privileges flush_options flush_option equal optional_braces opt_key_definition key_usage_list2 opt_mi_check_type opt_to mi_check_types normal_join table_to_table_list table_to_table opt_table_list opt_as @@ -1287,8 +1287,26 @@ create: TL_WRITE)) YYABORT; } + | CREATE USER clear_privileges grant_list + { + Lex->sql_command = SQLCOM_CREATE_USER; + } ; +clear_privileges: + /* Nothing */ + { + LEX *lex=Lex; + lex->users_list.empty(); + lex->columns.empty(); + lex->grant= lex->grant_tot_col= 0; + lex->select_lex.db= 0; + lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; + lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; + bzero((char *)&(lex->mqh),sizeof(lex->mqh)); + } + ; + sp_name: IDENT_sys '.' IDENT_sys { @@ -3671,8 +3689,25 @@ rename: } table_to_table_list {} + | RENAME USER clear_privileges rename_list + { + Lex->sql_command = SQLCOM_RENAME_USER; + } ; +rename_list: + user TO_SYM user + { + if (Lex->users_list.push_back($1) || Lex->users_list.push_back($3)) + YYABORT; + } + | rename_list ',' user TO_SYM user + { + if (Lex->users_list.push_back($3) || Lex->users_list.push_back($5)) + YYABORT; + } + ; + table_to_table_list: table_to_table | table_to_table_list ',' table_to_table; @@ -5479,14 +5514,10 @@ drop: lex->drop_if_exists= $3; lex->spname= $4; } - | DROP USER + | DROP USER clear_privileges user_list { - LEX *lex=Lex; - lex->sql_command = SQLCOM_DROP_USER; - lex->users_list.empty(); - } - user_list - {} + Lex->sql_command = SQLCOM_DROP_USER; + } | DROP VIEW_SYM if_exists table_list opt_restrict { THD *thd= YYTHD; @@ -7478,48 +7509,28 @@ handler_rkey_mode: /* GRANT / REVOKE */ revoke: - REVOKE - { - LEX *lex=Lex; - lex->sql_command = SQLCOM_REVOKE; - lex->users_list.empty(); - lex->columns.empty(); - lex->grant= lex->grant_tot_col=0; - lex->select_lex.db=0; - lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; - bzero((char*) &lex->mqh, sizeof(lex->mqh)); - } - revoke_command + REVOKE clear_privileges revoke_command {} ; revoke_command: - grant_privileges ON opt_table FROM user_list - {} + grant_privileges ON opt_table FROM grant_list + { + Lex->sql_command = SQLCOM_REVOKE; + } | - ALL opt_privileges ',' GRANT OPTION FROM user_list + ALL opt_privileges ',' GRANT OPTION FROM grant_list { Lex->sql_command = SQLCOM_REVOKE_ALL; } ; grant: - GRANT - { - LEX *lex=Lex; - lex->users_list.empty(); - lex->columns.empty(); - lex->sql_command = SQLCOM_GRANT; - lex->grant= lex->grant_tot_col= 0; - lex->select_lex.db= 0; - lex->ssl_type= SSL_TYPE_NOT_SPECIFIED; - lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0; - bzero((char *)&(lex->mqh),sizeof(lex->mqh)); - } - grant_privileges ON opt_table TO_SYM user_list + GRANT clear_privileges grant_privileges ON opt_table TO_SYM grant_list require_clause grant_options - {} + { + Lex->sql_command = SQLCOM_GRANT; + } ; grant_privileges: @@ -7659,8 +7670,18 @@ opt_table: user_list: + user { if (Lex->users_list.push_back($1)) YYABORT;} + | user_list ',' user + { + if (Lex->users_list.push_back($3)) + YYABORT; + } + ; + + +grant_list: grant_user { if (Lex->users_list.push_back($1)) YYABORT;} - | user_list ',' grant_user + | grant_list ',' grant_user { if (Lex->users_list.push_back($3)) YYABORT; |