From: Date: April 1 2007 2:04pm Subject: [PATCH] Proposed patch for bug #21975 List-Archive: http://lists.mysql.com/internals/34466 Message-Id: <460F9FE2.4050805@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------070709040804070703080707" --------------070709040804070703080707 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Hi, here goes a patch for the bug . The fix suggested here is to do implicit commit with every GRANT/REVOKE statement. It looks like being in concert with another DDL and administrative statements behavior. If this approach (and the patch) approved I'd also suggest to add the following sentence to the Manual at the very end of the 3rd paragraph of the subclause 13.4.3 "Statements That Cause an Implicit Commit": "Beginning with MySQL 5.0.40, the GRANT and REVOKE statements cause an implicit commit." Great thanks to Konstantin Osipov for the hint and explanations. In the hope it helps. Regards, Vladimir --------------070709040804070703080707 Content-Type: text/x-patch; name="bug21975.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="bug21975.patch" ===== sql/sql_parse.cc 1.612 vs edited ===== --- mysql-5.0/sql/sql_parse.cc.orig 2007-04-01 15:52:55 +04:00 +++ mysql-5.0/sql/sql_parse.cc 2007-04-01 06:52:47 +04:00 @@ -4033,6 +4033,8 @@ if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && check_global_access(thd,CREATE_USER_ACL)) break; + if (end_active_trans(thd)) + goto error; /* Conditionally writes to binlog */ if (!(res = mysql_revoke_all(thd, lex->users_list))) send_ok(thd); @@ -4049,6 +4051,8 @@ select_lex->db ? is_schema_db(select_lex->db) : 0)) goto error; + if (end_active_trans(thd)) + goto error; if (thd->security_ctx->user) // If not replication { LEX_USER *user, *tmp_user; ===== sql/sp_head.cc 1.239 vs edited ===== --- mysql-5.0/sql/sp_head.cc.orig 2007-04-01 15:52:55 +04:00 +++ mysql-5.0/sql/sp_head.cc 2007-04-01 06:52:47 +04:00 @@ -242,11 +242,14 @@ case SQLCOM_CREATE_TRIGGER: case SQLCOM_CREATE_USER: case SQLCOM_ALTER_TABLE: + case SQLCOM_GRANT: + case SQLCOM_REVOKE: case SQLCOM_BEGIN: case SQLCOM_RENAME_TABLE: case SQLCOM_RENAME_USER: case SQLCOM_DROP_INDEX: case SQLCOM_DROP_DB: + case SQLCOM_REVOKE_ALL: case SQLCOM_DROP_USER: case SQLCOM_DROP_VIEW: case SQLCOM_DROP_TRIGGER: ===== mysql-test/t/sp-error.test 1.113 vs edited ===== --- mysql-5.0/mysql-test/t/sp-error.test.orig 2007-04-01 15:52:53 +04:00 +++ mysql-5.0/mysql-test/t/sp-error.test 2007-04-01 06:52:47 +04:00 @@ -1383,6 +1383,21 @@ CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END | -- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN grant select on t1 to 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug21975() returns int BEGIN grant select on t1 to 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke select on t1 from 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug21975() returns int BEGIN revoke select on t1 from 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke all privileges on *.* from 'mysqltest_1'; END | +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +CREATE FUNCTION bug21975() returns int BEGIN revoke all privileges on *.* from 'mysqltest_1'; return 1; END | + +-- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END | -- error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END | ===== mysql-test/r/sp-error.result 1.112 vs edited ===== --- mysql-5.0/mysql-test/r/sp-error.result.orig 2007-04-01 15:52:52 +04:00 +++ mysql-5.0/mysql-test/r/sp-error.result 2007-04-01 06:52:47 +04:00 @@ -969,6 +969,18 @@ ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. CREATE FUNCTION bug_13627_f() returns int BEGIN create user 'mysqltest_1'; return 1; END | ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN grant select on t1 to 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug21975() returns int BEGIN grant select on t1 to 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke select on t1 from 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug21975() returns int BEGIN revoke select on t1 from 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE TRIGGER bug21975 BEFORE INSERT ON t1 FOR EACH ROW BEGIN revoke all privileges on *.* from 'mysqltest_1'; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +CREATE FUNCTION bug21975() returns int BEGIN revoke all privileges on *.* from 'mysqltest_1'; return 1; END | +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW BEGIN drop user 'mysqltest_1'; END | ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. CREATE FUNCTION bug_13627_f() returns int BEGIN drop user 'mysqltest_1'; return 1; END | ===== New file: mysql-test/t/grant-binlog.test ===== --- /dev/null 2007-03-24 07:53:03 +03:00 +++ mysql-5.0/mysql-test/t/grant-binlog.test 2007-04-01 06:36:42 +04:00 @@ -0,0 +1,39 @@ +-- source include/have_innodb.inc +-- source include/not_embedded.inc + +let $VERSION=`select version()`; + +# Bug #21975: grant/revoke statements in transaction +# used to disappear from binlog upon rallback. +# Now GRANT/REVOKE do implicitly commit +# transaction + +--disable-warnings +drop database if exists d1; +create database d1; +use d1; +create table t (s1 int) engine=innodb; +set @@autocommit=0; +start transaction; +insert into t values (1); +grant select on t to x@y; +# +# There is no active transaction here +# +rollback; +show grants for x@y; +--replace_result $VERSION VERSION +show binlog events; +start transaction; +insert into t values (2); +revoke select on t from x@y; +# +# There is no active transaction here +# +commit; +select * from t; +show grants for x@y; +--replace_result $VERSION VERSION +show binlog events; +drop user x@y; +drop database d1; ===== New file: mysql-test/r/grant-binlog.result ===== --- /dev/null 2007-03-24 07:53:03 +03:00 +++ mysql-5.0/mysql-test/r/grant-binlog.result 2007-04-01 15:47:03 +04:00 @@ -0,0 +1,52 @@ +drop database if exists d1; +Warnings: +Note 1008 Can't drop database 'd1'; database doesn't exist +create database d1; +use d1; +create table t (s1 int) engine=innodb; +set @@autocommit=0; +start transaction; +insert into t values (1); +grant select on t to x@y; +rollback; +show grants for x@y; +Grants for x@y +GRANT USAGE ON *.* TO 'x'@'y' +GRANT SELECT ON `d1`.`t` TO 'x'@'y' +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 98 Server ver: VERSION, Binlog ver: 4 +master-bin.000001 98 Query 1 185 drop database if exists d1 +master-bin.000001 185 Query 1 264 create database d1 +master-bin.000001 264 Query 1 362 use `d1`; create table t (s1 int) engine=innodb +master-bin.000001 362 Query 1 428 use `d1`; BEGIN +master-bin.000001 428 Query 1 85 use `d1`; insert into t values (1) +master-bin.000001 513 Xid 1 540 COMMIT /* xid=11 */ +master-bin.000001 540 Query 1 625 use `d1`; grant select on t to x@y +start transaction; +insert into t values (2); +revoke select on t from x@y; +commit; +select * from t; +s1 +1 +2 +show grants for x@y; +Grants for x@y +GRANT USAGE ON *.* TO 'x'@'y' +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 98 Server ver: VERSION, Binlog ver: 4 +master-bin.000001 98 Query 1 185 drop database if exists d1 +master-bin.000001 185 Query 1 264 create database d1 +master-bin.000001 264 Query 1 362 use `d1`; create table t (s1 int) engine=innodb +master-bin.000001 362 Query 1 428 use `d1`; BEGIN +master-bin.000001 428 Query 1 85 use `d1`; insert into t values (1) +master-bin.000001 513 Xid 1 540 COMMIT /* xid=11 */ +master-bin.000001 540 Query 1 625 use `d1`; grant select on t to x@y +master-bin.000001 625 Query 1 691 use `d1`; BEGIN +master-bin.000001 691 Query 1 85 use `d1`; insert into t values (2) +master-bin.000001 776 Xid 1 803 COMMIT /* xid=17 */ +master-bin.000001 803 Query 1 891 use `d1`; revoke select on t from x@y +drop user x@y; +drop database d1; --------------070709040804070703080707--