summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2017-12-27 17:50:39 +0200
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2017-12-27 17:50:39 +0200
commitd1c2cd30b76cc5e79da990507877b689887009f6 (patch)
tree9ef397cd935d1c0002f294d7993452877850c88a
parent5377242fff5d2260510e65c58e4e52d7c4b222f6 (diff)
parent4b8cd4536a2c6376284288cd4617369a5e48236a (diff)
downloadmariadb-git-d1c2cd30b76cc5e79da990507877b689887009f6.tar.gz
Merge remote-tracking branch '10.0' into 10.1
-rw-r--r--mysql-test/suite/innodb/r/innodb.result80
-rw-r--r--mysql-test/suite/innodb/t/innodb.test70
-rw-r--r--sql/sql_acl.cc26
3 files changed, 161 insertions, 15 deletions
diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result
index d50b9b36a4f..2cc08a833dc 100644
--- a/mysql-test/suite/innodb/r/innodb.result
+++ b/mysql-test/suite/innodb/r/innodb.result
@@ -3144,3 +3144,83 @@ show status like "handler_read_key";
Variable_name Value
Handler_read_key 0
drop table t1;
+CREATE TABLE t1 (c1 INT) ENGINE=InnoDB;
+CREATE TEMPORARY TABLE t2 (c1 INT) ENGINE=InnoDB;
+START TRANSACTION READ ONLY;
+INSERT INTO t2 VALUES(0);
+INSERT INTO t1 VALUES(0);
+ERROR 25006: Cannot execute statement in a READ ONLY transaction.
+ROLLBACK;
+SELECT * FROM t1;
+c1
+SELECT * FROM t2;
+c1
+START TRANSACTION READ ONLY;
+INSERT INTO t1 VALUES(0);
+ERROR 25006: Cannot execute statement in a READ ONLY transaction.
+INSERT INTO t2 VALUES(1);
+COMMIT;
+SET TRANSACTION READ ONLY;
+START TRANSACTION;
+INSERT INTO t2 VALUES(3);
+INSERT INTO t1 VALUES(0);
+ERROR 25006: Cannot execute statement in a READ ONLY transaction.
+COMMIT;
+SELECT * FROM t1;
+c1
+SELECT * FROM t2;
+c1
+1
+3
+DROP TABLE t2;
+CREATE TEMPORARY TABLE t2 (
+c1 INT AUTO_INCREMENT PRIMARY KEY,
+c2 INT, INDEX idx(c2)) ENGINE=InnoDB;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TEMPORARY TABLE `t2` (
+ `c1` int(11) NOT NULL AUTO_INCREMENT,
+ `c2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`c1`),
+ KEY `idx` (`c2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+START TRANSACTION READ ONLY;
+INSERT INTO t2 VALUES(NULL,1),(NULL,2),(NULL,3);
+INSERT INTO t1 VALUES(0);
+ERROR 25006: Cannot execute statement in a READ ONLY transaction.
+ROLLBACK;
+SELECT * FROM t1;
+c1
+SELECT * FROM t2;
+c1 c2
+START TRANSACTION READ ONLY;
+INSERT INTO t1 VALUES(0);
+ERROR 25006: Cannot execute statement in a READ ONLY transaction.
+INSERT INTO t2 VALUES(NULL,1),(NULL,2),(NULL,3);
+COMMIT;
+SET TRANSACTION READ ONLY;
+START TRANSACTION;
+INSERT INTO t2 VALUES(NULL,1),(NULL,2),(NULL,3);
+INSERT INTO t1 VALUES(0);
+ERROR 25006: Cannot execute statement in a READ ONLY transaction.
+COMMIT;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TEMPORARY TABLE `t2` (
+ `c1` int(11) NOT NULL AUTO_INCREMENT,
+ `c2` int(11) DEFAULT NULL,
+ PRIMARY KEY (`c1`),
+ KEY `idx` (`c2`)
+) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1
+SELECT * FROM t1;
+c1
+SELECT * FROM t2;
+c1 c2
+4 1
+7 1
+5 2
+8 2
+6 3
+9 3
+DROP TABLE t1;
+DROP TABLE t2;
diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test
index 2e7306c8e29..ad07f68f804 100644
--- a/mysql-test/suite/innodb/t/innodb.test
+++ b/mysql-test/suite/innodb/t/innodb.test
@@ -2530,6 +2530,76 @@ select f1 from t1;
show status like "handler_read_key";
drop table t1;
+#
+# Test handling of writes to TEMPORARY tables for read-only transactions
+#
+CREATE TABLE t1 (c1 INT) ENGINE=InnoDB;
+CREATE TEMPORARY TABLE t2 (c1 INT) ENGINE=InnoDB;
+
+# Check that the rollback works
+START TRANSACTION READ ONLY;
+INSERT INTO t2 VALUES(0);
+--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
+INSERT INTO t1 VALUES(0);
+ROLLBACK;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+START TRANSACTION READ ONLY;
+--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
+INSERT INTO t1 VALUES(0);
+INSERT INTO t2 VALUES(1);
+COMMIT;
+
+SET TRANSACTION READ ONLY;
+START TRANSACTION;
+INSERT INTO t2 VALUES(3);
+--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
+INSERT INTO t1 VALUES(0);
+COMMIT;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TABLE t2;
+
+# This time with some indexes
+CREATE TEMPORARY TABLE t2 (
+ c1 INT AUTO_INCREMENT PRIMARY KEY,
+ c2 INT, INDEX idx(c2)) ENGINE=InnoDB;
+
+SHOW CREATE TABLE t2;
+
+# Check that the rollback works
+START TRANSACTION READ ONLY;
+INSERT INTO t2 VALUES(NULL,1),(NULL,2),(NULL,3);
+--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
+INSERT INTO t1 VALUES(0);
+ROLLBACK;
+
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+START TRANSACTION READ ONLY;
+--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
+INSERT INTO t1 VALUES(0);
+INSERT INTO t2 VALUES(NULL,1),(NULL,2),(NULL,3);
+COMMIT;
+
+SET TRANSACTION READ ONLY;
+START TRANSACTION;
+INSERT INTO t2 VALUES(NULL,1),(NULL,2),(NULL,3);
+--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
+INSERT INTO t1 VALUES(0);
+COMMIT;
+
+SHOW CREATE TABLE t2;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TABLE t1;
+DROP TABLE t2;
#######################################################################
# #
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 503b65f2be0..07b0715dc84 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -5672,6 +5672,8 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)),
if (--grantee->counter)
return 1; // don't recurse into grantee just yet
+ grantee->counter= 1; // Mark the grantee as merged.
+
/* if we'll do db/table/routine privileges, create a hash of role names */
role_hash_t role_hash(role_key);
if (data->what != PRIVS_TO_MERGE::GLOBAL)
@@ -6761,14 +6763,16 @@ end_index_init:
DBUG_RETURN(return_val);
}
-static my_bool collect_leaf_roles(void *role_ptr,
- void *roles_array)
+static my_bool propagate_role_grants_action(void *role_ptr,
+ void *ptr __attribute__((unused)))
{
ACL_ROLE *role= static_cast<ACL_ROLE *>(role_ptr);
- Dynamic_array<ACL_ROLE *> *array=
- static_cast<Dynamic_array<ACL_ROLE *> *>(roles_array);
- if (!role->counter)
- array->push(role);
+ if (role->counter)
+ return 0;
+
+ mysql_mutex_assert_owner(&acl_cache->lock);
+ PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 };
+ traverse_role_graph_up(role, &data, NULL, merge_role_privileges);
return 0;
}
@@ -6835,15 +6839,7 @@ bool grant_reload(THD *thd)
}
mysql_mutex_lock(&acl_cache->lock);
- Dynamic_array<ACL_ROLE *> leaf_roles;
- my_hash_iterate(&acl_roles, collect_leaf_roles, &leaf_roles);
- PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 };
- for (size_t i= 0; i < leaf_roles.elements(); i++)
- {
- traverse_role_graph_up(leaf_roles.at(i), &data, NULL,
- merge_role_privileges);
- }
-
+ my_hash_iterate(&acl_roles, propagate_role_grants_action, NULL);
mysql_mutex_unlock(&acl_cache->lock);
mysql_rwlock_unlock(&LOCK_grant);