summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2018-05-03 17:49:16 +0300
committerMonty <monty@mariadb.org>2018-05-03 17:49:39 +0300
commit57c3dd991b2e9dfd1159e889f9ea7ab7ceebd40c (patch)
tree76d269b3edfcd367f18a18bf6ee5159c69fbf835
parent6c43068d6342bd1a7c1dbb24079ac4da4ba9b4ff (diff)
downloadmariadb-git-57c3dd991b2e9dfd1159e889f9ea7ab7ceebd40c.tar.gz
MDEV-15106 Unexpected ER_WRONG_INSERT_INTO_SEQUENCE upon INSERT with multiple locks on sequences
Fixed by removing the check of single lock in sequence insert and let MDL code handle deadlock detection
-rw-r--r--mysql-test/suite/sql_sequence/lock.result5
-rw-r--r--mysql-test/suite/sql_sequence/lock.test13
-rw-r--r--mysql-test/suite/sql_sequence/other.result18
-rw-r--r--mysql-test/suite/sql_sequence/other.test11
-rw-r--r--sql/ha_sequence.cc22
5 files changed, 50 insertions, 19 deletions
diff --git a/mysql-test/suite/sql_sequence/lock.result b/mysql-test/suite/sql_sequence/lock.result
index 05a06b218b3..92c75ff8188 100644
--- a/mysql-test/suite/sql_sequence/lock.result
+++ b/mysql-test/suite/sql_sequence/lock.result
@@ -27,3 +27,8 @@ DROP SEQUENCE s1;
ERROR HY000: Table 's1' was locked with a READ lock and can't be updated
unlock tables;
DROP SEQUENCE s1;
+CREATE SEQUENCE seq1;
+CREATE SEQUENCE seq2;
+LOCK TABLE seq1 WRITE, seq2 WRITE;
+INSERT INTO seq1 VALUES (1, 1, 100000, 1, 1, 100, 1, 1);
+DROP SEQUENCE seq1, seq2;
diff --git a/mysql-test/suite/sql_sequence/lock.test b/mysql-test/suite/sql_sequence/lock.test
index 2208a1f1ffa..730404abf38 100644
--- a/mysql-test/suite/sql_sequence/lock.test
+++ b/mysql-test/suite/sql_sequence/lock.test
@@ -38,3 +38,16 @@ SELECT NEXTVAL(s);
DROP SEQUENCE s1;
unlock tables;
DROP SEQUENCE s1;
+
+
+#
+# MDEV-15106 Unexpected ER_WRONG_INSERT_INTO_SEQUENCE upon INSERT with
+# multiple locks on sequences
+#
+
+CREATE SEQUENCE seq1;
+CREATE SEQUENCE seq2;
+LOCK TABLE seq1 WRITE, seq2 WRITE;
+INSERT INTO seq1 VALUES (1, 1, 100000, 1, 1, 100, 1, 1);
+DROP SEQUENCE seq1, seq2;
+
diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result
index e3ec94cf2c5..a56eb4d09a7 100644
--- a/mysql-test/suite/sql_sequence/other.result
+++ b/mysql-test/suite/sql_sequence/other.result
@@ -49,10 +49,6 @@ insert into s1 (next_not_cached_value, minimum_value) values (100,1000);
ERROR HY000: Field 'maximum_value' doesn't have a default value
insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0);
ERROR HY000: Table 's1' is specified twice, both as a target for 'INSERT' and as a separate source for data
-insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
-ERROR HY000: Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a sequence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead.
-insert into s1 select * from s2;
-ERROR HY000: Wrong INSERT into a SEQUENCE. One can only do single table INSERT into a sequence object (like with mysqldump). If you want to change the SEQUENCE, use ALTER SEQUENCE instead.
insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0);
ERROR HY000: Sequence 'test.s1' values are conflicting
insert into s1 values(0,9223372036854775806,1,1,1,1000,0,0);
@@ -72,6 +68,20 @@ next_not_cached_value minimum_value maximum_value start_value increment cache_si
2000 1 9223372036854775806 1 1 1000 0 0
insert into s2 values(0, 1, 10, 1, 2, 1, 1, 0);
ERROR HY000: Sequence 'test.s2' values are conflicting
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+2000 1 9223372036854775806 1 1 1000 0 0
+insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1 1 9223372036854775806 1 1 1000 0 0
+select * from s2;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1001 1 9223372036854775806 1 1 1000 0 0
+insert into s1 select * from s2;
+select * from s1;
+next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
+1001 1 9223372036854775806 1 1 1000 0 0
drop sequence s1,s2;
#
# UPDATE and DELETE
diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test
index ff0db9e158d..a493687faa3 100644
--- a/mysql-test/suite/sql_sequence/other.test
+++ b/mysql-test/suite/sql_sequence/other.test
@@ -38,10 +38,6 @@ create sequence s2;
insert into s1 (next_not_cached_value, minimum_value) values (100,1000);
--error ER_UPDATE_TABLE_USED
insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0);
---error ER_WRONG_INSERT_INTO_SEQUENCE
-insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
---error ER_WRONG_INSERT_INTO_SEQUENCE
-insert into s1 select * from s2;
--error ER_SEQUENCE_INVALID_DATA
insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0);
--error ER_SEQUENCE_INVALID_DATA
@@ -53,6 +49,13 @@ select next value for s1;
select * from s1;
--error ER_SEQUENCE_INVALID_DATA
insert into s2 values(0, 1, 10, 1, 2, 1, 1, 0);
+
+select * from s1;
+insert into s1 values (next value for s2, 1,9223372036854775806,1,1,1000,0,0);
+select * from s1;
+select * from s2;
+insert into s1 select * from s2;
+select * from s1;
drop sequence s1,s2;
--echo #
diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc
index b500ce3c1f6..df9d9656c56 100644
--- a/sql/ha_sequence.cc
+++ b/sql/ha_sequence.cc
@@ -84,14 +84,18 @@ int ha_sequence::open(const char *name, int mode, uint flags)
if (!(error= file->open(name, mode, flags)))
{
/*
- Copy values set by handler::open() in the underlying handler
- Reuse original storage engine data for duplicate key reference
- It would be easier to do this if we would have another handler
- call: fixup_after_open()...
- */
- ref= file->ref;
+ Allocate ref in table's mem_root. We can't use table's ref
+ as it's allocated by ha_ caller that allocates this.
+ */
ref_length= file->ref_length;
- dup_ref= file->dup_ref;
+ if (!(ref= (uchar*) alloc_root(&table->mem_root,ALIGN_SIZE(ref_length)*2)))
+ {
+ file->ha_close();
+ error=HA_ERR_OUT_OF_MEM;
+ DBUG_RETURN(error);
+ }
+ file->ref= ref;
+ file->dup_ref= dup_ref= ref+ALIGN_SIZE(file->ref_length);
/*
ha_open() sets the following for us. We have to set this for the
@@ -229,14 +233,10 @@ int ha_sequence::write_row(uchar *buf)
- Get an exclusive lock for the table. This is needed to ensure that
we excute all full inserts (same as ALTER SEQUENCE) in same order
on master and slaves
- - Check that we are only using one table.
- This is to avoid deadlock problems when upgrading lock to exlusive.
- Check that the new row is an accurate SEQUENCE object
*/
THD *thd= table->in_use;
- if (thd->lock->table_count != 1)
- DBUG_RETURN(ER_WRONG_INSERT_INTO_SEQUENCE);
if (table->s->tmp_table == NO_TMP_TABLE &&
thd->mdl_context.upgrade_shared_lock(table->mdl_ticket,
MDL_EXCLUSIVE,