diff --git a/mysql-test/suite/sql_sequence/alter.result b/mysql-test/suite/sql_sequence/alter.result index beda77e3a9d..5bb4063731c 100644 --- a/mysql-test/suite/sql_sequence/alter.result +++ b/mysql-test/suite/sql_sequence/alter.result @@ -420,6 +420,76 @@ DROP SEQUENCE s2; # End of 10.6 tests # # +# MDEV-36032 Check when doing ALTER TABLE table_name sequence=1 that table can be a sequence +# +create sequence s; +alter table s sequence=0; +insert into s values (3,1,9223372036854775806,1,1,1000,0,0); +alter table s sequence=1; +ERROR HY000: More than one row in the table +drop table s; +create sequence s; +alter table s sequence=0; +delete from s; +insert into s values (2,500,200,1,1,1000,0,0); +select * from s; +next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count +2 500 200 1 1 1000 0 0 +alter table s sequence=1; +ERROR HY000: Sequence 'test.s' has out of range value for options +check table s; +Table Op Msg_type Msg_text +test.s check status OK +select * from s; +next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count +2 500 200 1 1 1000 0 0 +check table s; +Table Op Msg_type Msg_text +test.s check status OK +drop table s; +CREATE TABLE `s` ( +# `next_not_cached_value` bigint(21) NOT NULL, +`minimum_value` bigint(21) NOT NULL, +`maximum_value` bigint(21) NOT NULL, +`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', +`increment` bigint(21) NOT NULL COMMENT 'increment value', +`cache_size` bigint(21) unsigned NOT NULL, +`cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', +`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' +) ENGINE=innodb; +alter table s sequence=1; +ERROR HY000: Sequence 'test.s' table structure is invalid (Wrong number of columns) +drop table s; +create sequence s; +alter table s drop column next_not_cached_value; +ERROR HY000: Sequence 'test.s' table structure is invalid (Wrong number of columns) +drop sequence s; +CREATE TABLE `s1` ( +`next_not_cached_value` bigint(21) NOT NULL, +`minimum_value` bigint(21) NOT NULL, +`maximum_value` bigint(21) NOT NULL, +`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', +`increment` bigint(21) NOT NULL COMMENT 'increment value', +`cache_size` bigint(21) unsigned NOT NULL, +`cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', +`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' +) ENGINE=innodb; +alter table s1 sequence=1; +ERROR HY000: Fewer than one row in the table +alter table s1 sequence=0; +insert into s1 values (1,1,9223372036854775806,1,1,1000,0,0); +alter table s1 sequence=1; +alter table s1 sequence=0; +insert into s1 values (2,1,9223372036854775806,1,1,1000,0,0); +alter table s1 sequence=1; +ERROR HY000: More than one row in the table +alter table s1 sequence=0; +insert into s1 values (3,1,9223372036854775806,1,1,1000,0,0); +alter table s1 sequence=1; +ERROR HY000: More than one row in the table +drop table s1; +# End of 10.11 tests +# # MDEV-28152 Features for sequence # create sequence s maxvalue 12345; diff --git a/mysql-test/suite/sql_sequence/alter.test b/mysql-test/suite/sql_sequence/alter.test index 8d6c565e720..95fa56ab2f4 100644 --- a/mysql-test/suite/sql_sequence/alter.test +++ b/mysql-test/suite/sql_sequence/alter.test @@ -294,6 +294,87 @@ DROP SEQUENCE s2; --echo # End of 10.6 tests --echo # +--echo # +--echo # MDEV-36032 Check when doing ALTER TABLE table_name sequence=1 that table can be a sequence +--echo # + +## Too many rows +create sequence s; +alter table s sequence=0; +insert into s values (3,1,9223372036854775806,1,1,1000,0,0); +--error ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS +alter table s sequence=1; +drop table s; + +## Insert a wrong row (min > max) +create sequence s; +alter table s sequence=0; +delete from s; +insert into s values (2,500,200,1,1,1000,0,0); +select * from s; +--error ER_SEQUENCE_INVALID_DATA +alter table s sequence=1; +check table s; +select * from s; +check table s; +drop table s; + +## Invalid table structure (already implemented before MDEV-36032) +CREATE TABLE `s` ( + # `next_not_cached_value` bigint(21) NOT NULL, + `minimum_value` bigint(21) NOT NULL, + `maximum_value` bigint(21) NOT NULL, + `start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', + `increment` bigint(21) NOT NULL COMMENT 'increment value', + `cache_size` bigint(21) unsigned NOT NULL, + `cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', + `cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' +) ENGINE=innodb; +--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE +alter table s sequence=1; +drop table s; + +## Altering a sequence table to a wrong structure is detected (already +## implemented before MDEV-36032) +create sequence s; +--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE +alter table s drop column next_not_cached_value; +drop sequence s; + +## Create a normal table then alter to sequence +CREATE TABLE `s1` ( +`next_not_cached_value` bigint(21) NOT NULL, +`minimum_value` bigint(21) NOT NULL, +`maximum_value` bigint(21) NOT NULL, +`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used', +`increment` bigint(21) NOT NULL COMMENT 'increment value', +`cache_size` bigint(21) unsigned NOT NULL, +`cycle_option` tinyint(1) unsigned NOT NULL COMMENT '0 if no cycles are allowed, 1 if the sequence should begin a new cycle when maximum_value is passed', +`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done' +) ENGINE=innodb; + +--error ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS +alter table s1 sequence=1; +# (for coverage) alter a non sequence table with sequence=0 +alter table s1 sequence=0; +insert into s1 values (1,1,9223372036854775806,1,1,1000,0,0); +alter table s1 sequence=1; + +alter table s1 sequence=0; +insert into s1 values (2,1,9223372036854775806,1,1,1000,0,0); +--error ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS +alter table s1 sequence=1; + +# (for coverage) alter a non sequence table with sequence=0 +alter table s1 sequence=0; +insert into s1 values (3,1,9223372036854775806,1,1,1000,0,0); +--error ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS +alter table s1 sequence=1; + +drop table s1; + +--echo # End of 10.11 tests + --echo # --echo # MDEV-28152 Features for sequence --echo # diff --git a/sql/handler.cc b/sql/handler.cc index e4187a8e3f5..4cd490b702e 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -5777,6 +5777,9 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table, (table->s->row_type != create_info->row_type)) DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + if (create_info->sequence) + DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); + uint table_changes= (ha_alter_info->handler_flags & ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) ? IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index af28890d442..28694674ec3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -12588,6 +12588,16 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, copy_end=copy; to->s->default_fields= 0; error= 1; + if (to->s->table_type == TABLE_TYPE_SEQUENCE && + from->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT && + from->file->stats.records != 1) + { + if (from->file->stats.records > 1) + my_error(ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS, MYF(0)); + else + my_error(ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS, MYF(0)); + goto err; + } for (Field **ptr=to->field ; *ptr ; ptr++) { def=it++; @@ -12798,6 +12808,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, else to->next_number_field->reset(); } + if (to->s->table_type == TABLE_TYPE_SEQUENCE && found_count == 1) + { + my_error(ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS, MYF(0)); + error= 1; + break; + } error= to->file->ha_write_row(to->record[0]); to->auto_increment_field_not_null= FALSE; if (unlikely(error)) @@ -12869,6 +12885,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, DEBUG_SYNC(thd, "alter_table_copy_end"); + if (to->s->table_type == TABLE_TYPE_SEQUENCE && found_count == 0) + { + my_error(ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS, MYF(0)); + error= 1; + } THD_STAGE_INFO(thd, stage_enabling_keys); thd_progress_next_stage(thd);