summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/sql_sequence/gtid.result50
-rw-r--r--mysql-test/suite/sql_sequence/gtid.test38
-rw-r--r--mysql-test/suite/sql_sequence/other.result35
-rw-r--r--mysql-test/suite/sql_sequence/other.test27
-rw-r--r--mysql-test/suite/sql_sequence/replication.result2
-rw-r--r--sql/ha_sequence.h2
-rw-r--r--sql/sql_acl.cc12
-rw-r--r--sql/sql_parse.cc9
-rw-r--r--sql/sql_sequence.cc8
-rw-r--r--storage/innobase/handler/ha_innodb.cc5
10 files changed, 181 insertions, 7 deletions
diff --git a/mysql-test/suite/sql_sequence/gtid.result b/mysql-test/suite/sql_sequence/gtid.result
index 366f201d338..ce8e8b7bb80 100644
--- a/mysql-test/suite/sql_sequence/gtid.result
+++ b/mysql-test/suite/sql_sequence/gtid.result
@@ -6,9 +6,11 @@ grant all on s_db.* to normal_1@'%' identified by 'pass';
grant all on test.* to normal_2@'%' identified by 'pass';
grant all on s_db.* to normal_3@'%' identified by 'pass';
grant all on test.* to normal_4@'%' identified by 'pass';
+grant select on test.* to normal_5@'%' identified by 'pass';
connection slave;
connect m_normal_1, 127.0.0.1, normal_1, pass, s_db, $MASTER_MYPORT;
connect m_normal_2, 127.0.0.1, normal_2, pass, test, $MASTER_MYPORT;
+connect m_normal_3, 127.0.0.1, normal_5, pass, test, $MASTER_MYPORT;
connect s_normal_3, 127.0.0.1, normal_3, pass, s_db, $SLAVE_MYPORT;
connect s_normal_4, 127.0.0.1, normal_4, pass, test, $SLAVE_MYPORT;
connection slave;
@@ -171,7 +173,7 @@ create sequence s_db.s2;
drop sequence s_db.s2;
connection m_normal_2;
select next value for s_db.s1;
-ERROR 42000: SELECT command denied to user 'normal_2'@'localhost' for table 's1'
+ERROR 42000: INSERT command denied to user 'normal_2'@'localhost' for table 's1'
create sequence s_db.s2;
ERROR 42000: CREATE command denied to user 'normal_2'@'localhost' for table 's2'
connection m_normal_1;
@@ -771,6 +773,51 @@ next value for s1
drop function f1;
drop table t1;
drop sequence s1;
+##############
+Test GRANT
+##############
+connection m_normal_2;
+create table t1 (a int);
+create sequence s1;
+select next value for s1;
+next value for s1
+1
+insert into t1 values (1);
+connection m_normal_3;
+select * from t1;
+a
+1
+select * from s1;
+next_value min_value max_value start increment cache cycle round
+1001 1 9223372036854775806 1 1 1000 0 0
+select previous value for s1;
+previous value for s1
+NULL
+insert into t1 values (2);
+ERROR 42000: INSERT command denied to user 'normal_5'@'localhost' for table 't1'
+select next value for s1;
+ERROR 42000: INSERT command denied to user 'normal_5'@'localhost' for table 's1'
+do setval(s1,1000,0);
+ERROR 42000: INSERT command denied to user 'normal_5'@'localhost' for table 's1'
+connection master;
+grant insert on test.* to normal_5@'%' identified by 'pass';
+disconnect m_normal_3;
+connect m_normal_3, 127.0.0.1, normal_5, pass, test, $MASTER_MYPORT;
+insert into t1 values (2);
+select t1.*, (next value for s1) from t1;
+a (next value for s1)
+1 2
+2 3
+do setval(s1,10000,0);
+select * from s1;
+next_value min_value max_value start increment cache cycle round
+10000 1 9223372036854775806 1 1 1000 0 0
+connection m_normal_2;
+drop table t1;
+drop sequence s1;
+#
+# Cleanup
+#
connection master;
use s_db;
drop database s_db;
@@ -778,4 +825,5 @@ drop user normal_1@'%';
drop user normal_2@'%';
drop user normal_3@'%';
drop user normal_4@'%';
+drop user normal_5@'%';
include/rpl_end.inc
diff --git a/mysql-test/suite/sql_sequence/gtid.test b/mysql-test/suite/sql_sequence/gtid.test
index 50492cbb329..98760119b53 100644
--- a/mysql-test/suite/sql_sequence/gtid.test
+++ b/mysql-test/suite/sql_sequence/gtid.test
@@ -12,11 +12,13 @@ grant all on s_db.* to normal_1@'%' identified by 'pass';
grant all on test.* to normal_2@'%' identified by 'pass';
grant all on s_db.* to normal_3@'%' identified by 'pass';
grant all on test.* to normal_4@'%' identified by 'pass';
+grant select on test.* to normal_5@'%' identified by 'pass';
--sync_slave_with_master
connect(m_normal_1, 127.0.0.1, normal_1, pass, s_db, $MASTER_MYPORT);
connect(m_normal_2, 127.0.0.1, normal_2, pass, test, $MASTER_MYPORT);
+connect(m_normal_3, 127.0.0.1, normal_5, pass, test, $MASTER_MYPORT);
connect(s_normal_3, 127.0.0.1, normal_3, pass, s_db, $SLAVE_MYPORT);
connect(s_normal_4, 127.0.0.1, normal_4, pass, test, $SLAVE_MYPORT);
@@ -655,6 +657,41 @@ drop function f1;
drop table t1;
drop sequence s1;
+--echo ##############
+--echo Test GRANT
+--echo ##############
+
+connection m_normal_2;
+create table t1 (a int);
+create sequence s1;
+select next value for s1;
+insert into t1 values (1);
+connection m_normal_3;
+select * from t1;
+select * from s1;
+select previous value for s1;
+--error ER_TABLEACCESS_DENIED_ERROR
+insert into t1 values (2);
+--error ER_TABLEACCESS_DENIED_ERROR
+select next value for s1;
+--error ER_TABLEACCESS_DENIED_ERROR
+do setval(s1,1000,0);
+connection master;
+grant insert on test.* to normal_5@'%' identified by 'pass';
+disconnect m_normal_3;
+connect(m_normal_3, 127.0.0.1, normal_5, pass, test, $MASTER_MYPORT);
+insert into t1 values (2);
+select t1.*, (next value for s1) from t1;
+do setval(s1,10000,0);
+select * from s1;
+connection m_normal_2;
+drop table t1;
+drop sequence s1;
+
+--echo #
+--echo # Cleanup
+--echo #
+
connection master;
use s_db;
drop database s_db;
@@ -662,5 +699,6 @@ drop user normal_1@'%';
drop user normal_2@'%';
drop user normal_3@'%';
drop user normal_4@'%';
+drop user normal_5@'%';
--source include/rpl_end.inc
diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result
index e991a595e91..ea72e264b34 100644
--- a/mysql-test/suite/sql_sequence/other.result
+++ b/mysql-test/suite/sql_sequence/other.result
@@ -113,3 +113,38 @@ LOCK TABLES s1 WRITE;
insert into s1 values (1,1,9223372036854775806, 1, 1, 1000, 0, 0);
UNLOCK TABLES;
drop table s1;
+#
+# Many sequence calls with innodb
+#
+create sequence s1 cache=1000 engine=innodb;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+count(nextval(s1))
+2000
+commit;
+select * from s1;
+next_value min_value max_value start increment cache cycle round
+2001 1 9223372036854775806 1 1 1000 0 0
+drop sequence s1;
+create sequence s1 cache=1000 engine=innodb;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+count(nextval(s1))
+2000
+connect addconroot, localhost, root,,;
+connection addconroot;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+count(nextval(s1))
+2000
+select * from s1;
+next_value min_value max_value start increment cache cycle round
+4001 1 9223372036854775806 1 1 1000 0 0
+commit;
+disconnect addconroot;
+connection default;
+select * from s1;
+next_value min_value max_value start increment cache cycle round
+4001 1 9223372036854775806 1 1 1000 0 0
+commit;
+drop sequence s1;
diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test
index 3716b53311a..0caeb342bc9 100644
--- a/mysql-test/suite/sql_sequence/other.test
+++ b/mysql-test/suite/sql_sequence/other.test
@@ -90,3 +90,30 @@ LOCK TABLES s1 WRITE;
insert into s1 values (1,1,9223372036854775806, 1, 1, 1000, 0, 0);
UNLOCK TABLES;
drop table s1;
+
+--echo #
+--echo # Many sequence calls with innodb
+--echo #
+
+create sequence s1 cache=1000 engine=innodb;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+commit;
+select * from s1;
+drop sequence s1;
+
+create sequence s1 cache=1000 engine=innodb;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+
+connect (addconroot, localhost, root,,);
+connection addconroot;
+start transaction;
+select count(nextval(s1)) from seq_1_to_2000;
+select * from s1;
+commit;
+disconnect addconroot;
+connection default;
+select * from s1;
+commit;
+drop sequence s1;
diff --git a/mysql-test/suite/sql_sequence/replication.result b/mysql-test/suite/sql_sequence/replication.result
index 4c1508bad93..12355851f7b 100644
--- a/mysql-test/suite/sql_sequence/replication.result
+++ b/mysql-test/suite/sql_sequence/replication.result
@@ -286,7 +286,7 @@ create sequence s_db.s2;
drop sequence s_db.s2;
connection m_normal_2;
select NEXT VALUE for s_db.s1;
-ERROR 42000: SELECT command denied to user 'normal_2'@'localhost' for table 's1'
+ERROR 42000: INSERT command denied to user 'normal_2'@'localhost' for table 's1'
create sequence s_db.s2;
ERROR 42000: CREATE command denied to user 'normal_2'@'localhost' for table 's2'
connection m_normal_1;
diff --git a/sql/ha_sequence.h b/sql/ha_sequence.h
index 8ab452a9372..fd9da05b591 100644
--- a/sql/ha_sequence.h
+++ b/sql/ha_sequence.h
@@ -152,6 +152,8 @@ public:
{ return file->check_and_repair(thd); }
bool is_crashed() const
{ return file->is_crashed(); }
+ void column_bitmaps_signal()
+ { return file->column_bitmaps_signal(); }
/* New methods */
void register_original_handler(handler *file_arg)
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 5608e0dfc49..d63a2f2bc51 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -7524,7 +7524,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table();
Security_context *sctx= thd->security_ctx;
uint i;
- ulong orig_want_access= want_access;
+ ulong original_want_access= want_access;
bool locked= 0;
GRANT_TABLE *grant_table;
GRANT_TABLE *grant_table_role= NULL;
@@ -7558,6 +7558,16 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
TABLE_LIST *const t_ref=
tl->correspondent_table ? tl->correspondent_table : tl;
sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx;
+ ulong orig_want_access= original_want_access;
+
+ if (t_ref->sequence)
+ {
+ /* We want to have either SELECT or INSERT rights to sequences depending
+ on how they are accessed
+ */
+ orig_want_access= ((t_ref->lock_type == TL_WRITE_ALLOW_WRITE) ?
+ INSERT_ACL : SELECT_ACL);
+ }
const ACL_internal_table_access *access=
get_cached_table_access(&t_ref->grant.m_internal,
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 42bf6a5b97c..7169b5dd068 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7045,6 +7045,15 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables,
thd->security_ctx= sctx;
+ if (table_ref->sequence)
+ {
+ /* We want to have either SELECT or INSERT rights to sequences depending
+ on how they are accessed
+ */
+ want_access= ((table_ref->lock_type == TL_WRITE_ALLOW_WRITE) ?
+ INSERT_ACL : SELECT_ACL);
+ }
+
if (check_access(thd, want_access, table_ref->get_db_name(),
&table_ref->grant.privilege,
&table_ref->grant.m_internal,
diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc
index 1b591f10c9f..35792bfe72e 100644
--- a/sql/sql_sequence.cc
+++ b/sql/sql_sequence.cc
@@ -576,7 +576,7 @@ int sequence_definition::write_initial_sequence(TABLE *table)
int sequence_definition::write(TABLE *table, bool all_fields)
{
int error;
- MY_BITMAP *save_rpl_write_set, *save_write_set;
+ MY_BITMAP *save_rpl_write_set, *save_write_set, *save_read_set;
DBUG_ASSERT(((ha_sequence*) table->file)->is_locked());
save_rpl_write_set= table->rpl_write_set;
@@ -593,12 +593,16 @@ int sequence_definition::write(TABLE *table, bool all_fields)
/* Update table */
save_write_set= table->write_set;
- table->write_set= &table->s->all_set;
+ save_read_set= table->read_set;
+ table->read_set= table->write_set= &table->s->all_set;
+ table->file->column_bitmaps_signal();
store_fields(table);
if ((error= table->file->ha_write_row(table->record[0])))
table->file->print_error(error, MYF(0));
table->rpl_write_set= save_rpl_write_set;
+ table->read_set= save_read_set;
table->write_set= save_write_set;
+ table->file->column_bitmaps_signal();
return error;
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c2ccd0fab36..c69075eac2c 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -8129,10 +8129,11 @@ ha_innobase::build_template(
ibool fetch_primary_key_cols = FALSE;
ulint i;
- if (m_prebuilt->select_lock_type == LOCK_X) {
+ if (m_prebuilt->select_lock_type == LOCK_X || m_prebuilt->table->no_rollback()) {
/* We always retrieve the whole clustered index record if we
use exclusive row level locks, for example, if the read is
- done in an UPDATE statement. */
+ done in an UPDATE statement or if we are using a no rollback
+ table */
whole_row = true;
} else if (!whole_row) {