MDEV-36032 Check whether a table can be a sequence when ALTERed with SEQUENCE=1

To check the rows, the table needs to be opened. To that end, and like
MDEV-36038, we force COPY algorithm on ALTER TABLE ... SEQUENCE=1.
This also results in checking the sequence state / metadata.

The table structure was already validated before this patch.

(cherry picked from commit 6f8ef26885073e1d0e3f69145d88c9452c0f4cf6)
This commit is contained in:
Thirunarayanan Balathandayuthapani 2025-05-28 13:58:47 +05:30
parent a6f5555008
commit 37274ae01f
4 changed files with 175 additions and 0 deletions

View File

@ -420,6 +420,76 @@ DROP SEQUENCE s2;
# End of 10.6 tests # 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 # MDEV-28152 Features for sequence
# #
create sequence s maxvalue 12345; create sequence s maxvalue 12345;

View File

@ -294,6 +294,87 @@ DROP SEQUENCE s2;
--echo # End of 10.6 tests --echo # End of 10.6 tests
--echo # --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 #
--echo # MDEV-28152 Features for sequence --echo # MDEV-28152 Features for sequence
--echo # --echo #

View File

@ -5777,6 +5777,9 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
(table->s->row_type != create_info->row_type)) (table->s->row_type != create_info->row_type))
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); 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 & uint table_changes= (ha_alter_info->handler_flags &
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) ? ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) ?
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES; IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;

View File

@ -12588,6 +12588,16 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
copy_end=copy; copy_end=copy;
to->s->default_fields= 0; to->s->default_fields= 0;
error= 1; 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++) for (Field **ptr=to->field ; *ptr ; ptr++)
{ {
def=it++; def=it++;
@ -12798,6 +12808,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
else else
to->next_number_field->reset(); 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]); error= to->file->ha_write_row(to->record[0]);
to->auto_increment_field_not_null= FALSE; to->auto_increment_field_not_null= FALSE;
if (unlikely(error)) if (unlikely(error))
@ -12869,6 +12885,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
DEBUG_SYNC(thd, "alter_table_copy_end"); 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_STAGE_INFO(thd, stage_enabling_keys);
thd_progress_next_stage(thd); thd_progress_next_stage(thd);