diff options
author | Monty <monty@mariadb.org> | 2017-05-02 19:23:00 +0300 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2017-05-08 02:33:34 +0300 |
commit | 276b0c8ef03046cc210e4eeab7231cb8d9f16bac (patch) | |
tree | d17df40168443e461b10c8e4f9b101a11270e183 | |
parent | c619fbeafe8d5019e37fcb7ba5e1a6ce2d431270 (diff) | |
download | mariadb-git-276b0c8ef03046cc210e4eeab7231cb8d9f16bac.tar.gz |
Fixed crash with SEQUENCE when using REPAIR
-rw-r--r-- | mysql-test/suite/sql_sequence/other.result | 42 | ||||
-rw-r--r-- | mysql-test/suite/sql_sequence/other.test | 29 | ||||
-rw-r--r-- | sql/ha_sequence.cc | 6 | ||||
-rw-r--r-- | sql/sql_sequence.cc | 12 | ||||
-rw-r--r-- | sql/sql_sequence.h | 4 |
5 files changed, 86 insertions, 7 deletions
diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result new file mode 100644 index 00000000000..b9510d46de7 --- /dev/null +++ b/mysql-test/suite/sql_sequence/other.result @@ -0,0 +1,42 @@ +# +# Create and check +# +create sequence s1 engine=innodb; +check table s1; +Table Op Msg_type Msg_text +test.s1 check note The storage engine for the table doesn't support check +select next value for s1; +next value for s1 +1 +flush tables; +check table s1; +Table Op Msg_type Msg_text +test.s1 check note The storage engine for the table doesn't support check +select next value for s1; +next value for s1 +1001 +flush tables; +repair table s1; +Table Op Msg_type Msg_text +test.s1 repair note The storage engine for the table doesn't support repair +select next value for s1; +next value for s1 +2001 +drop sequence s1; +create or replace sequence s1 engine=innodb; +select next value for s1; +next value for s1 +1 +repair table s1; +Table Op Msg_type Msg_text +test.s1 repair note The storage engine for the table doesn't support repair +check table s1; +Table Op Msg_type Msg_text +test.s1 check note The storage engine for the table doesn't support check +select next value for s1; +next value for s1 +1001 +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; diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test new file mode 100644 index 00000000000..c9ed326004a --- /dev/null +++ b/mysql-test/suite/sql_sequence/other.test @@ -0,0 +1,29 @@ +--source include/have_sequence.inc +--source include/have_innodb.inc + +# +# Test various combinations of operations on sequence +# + +--echo # +--echo # Create and check +--echo # + +create sequence s1 engine=innodb; +check table s1; +select next value for s1; +flush tables; +check table s1; +select next value for s1; +flush tables; +repair table s1; +select next value for s1; +drop sequence s1; + +create or replace sequence s1 engine=innodb; +select next value for s1; +repair table s1; +check table s1; +select next value for s1; +select * from s1; +drop sequence s1; diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index 25a1a6e71c4..5ff5a4eb213 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -110,6 +110,8 @@ int ha_sequence::open(const char *name, int mode, uint flags) if ((error= table->s->sequence->read_initial_values(table))) file->ha_close(); } + else + table->m_needs_reopen= true; } DBUG_RETURN(error); } @@ -189,11 +191,13 @@ int ha_sequence::write_row(uchar *buf) DBUG_ASSERT(table->record[0] == buf); row_already_logged= 0; - if (!sequence->initialized) + if (unlikely(sequence->initialized == SEQUENCE::SEQ_IN_PREPARE)) { /* This calls is from ha_open() as part of create table */ DBUG_RETURN(file->write_row(buf)); } + if (unlikely(sequence->initialized != SEQUENCE::SEQ_READY_TO_USE)) + DBUG_RETURN(HA_ERR_WRONG_COMMAND); /* User tries to write a row diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index 98912691904..6b0a03a4e07 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -327,7 +327,9 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list) tmp_disable_binlog(thd); save_write_set= table->write_set; table->write_set= &table->s->all_set; + table->s->sequence->initialized= SEQUENCE::SEQ_IN_PREPARE; error= table->file->ha_write_row(table->record[0]); + table->s->sequence->initialized= SEQUENCE::SEQ_UNINTIALIZED; reenable_binlog(thd); table->write_set= save_write_set; @@ -339,7 +341,7 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list) Sequence structure is up to date and table has one row, sequence is now usable */ - table->s->sequence->initialized= 1; + table->s->sequence->initialized= SEQUENCE::SEQ_READY_TO_USE; } trans_commit_stmt(thd); @@ -353,7 +355,7 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list) /* Create a SQUENCE object */ -SEQUENCE::SEQUENCE() :initialized(0), all_values_used(0), table(0) +SEQUENCE::SEQUENCE() :all_values_used(0), initialized(SEQ_UNINTIALIZED), table(0) { mysql_mutex_init(key_LOCK_SEQUENCE, &mutex, MY_MUTEX_INIT_SLOW); } @@ -376,11 +378,11 @@ int SEQUENCE::read_initial_values(TABLE *table_arg) MDL_request mdl_request; // Empty constructor! DBUG_ENTER("SEQUENCE::read_initial_values"); - if (likely(initialized)) + if (likely(initialized != SEQ_UNINTIALIZED)) DBUG_RETURN(0); table= table_arg; mysql_mutex_lock(&mutex); - if (unlikely(!initialized)) + if (likely(initialized == SEQ_UNINTIALIZED)) { MYSQL_LOCK *lock; bool mdl_lock_used= 0; @@ -419,7 +421,7 @@ int SEQUENCE::read_initial_values(TABLE *table_arg) DBUG_RETURN(HA_ERR_LOCK_WAIT_TIMEOUT); } if (!(error= read_stored_values())) - initialized= 1; + initialized= SEQ_READY_TO_USE; mysql_unlock_tables(thd, lock, 0); if (mdl_lock_used) thd->mdl_context.release_lock(mdl_request.ticket); diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h index f5534d55d9b..1409f86649f 100644 --- a/sql/sql_sequence.h +++ b/sql/sql_sequence.h @@ -66,6 +66,7 @@ public: class SEQUENCE :public sequence_definition { public: + enum seq_init { SEQ_UNINTIALIZED, SEQ_IN_PREPARE, SEQ_READY_TO_USE }; SEQUENCE(); ~SEQUENCE(); int read_initial_values(TABLE *table); @@ -87,8 +88,9 @@ public: } longlong next_value(TABLE *table, bool second_round, int *error); - bool initialized; // If row has been read bool all_values_used; + seq_init initialized; + private: TABLE *table; mysql_mutex_t mutex; |