summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2017-05-02 19:23:00 +0300
committerMonty <monty@mariadb.org>2017-05-08 02:33:34 +0300
commit276b0c8ef03046cc210e4eeab7231cb8d9f16bac (patch)
treed17df40168443e461b10c8e4f9b101a11270e183
parentc619fbeafe8d5019e37fcb7ba5e1a6ce2d431270 (diff)
downloadmariadb-git-276b0c8ef03046cc210e4eeab7231cb8d9f16bac.tar.gz
Fixed crash with SEQUENCE when using REPAIR
-rw-r--r--mysql-test/suite/sql_sequence/other.result42
-rw-r--r--mysql-test/suite/sql_sequence/other.test29
-rw-r--r--sql/ha_sequence.cc6
-rw-r--r--sql/sql_sequence.cc12
-rw-r--r--sql/sql_sequence.h4
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;