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:
parent
a6f5555008
commit
37274ae01f
@ -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;
|
||||
|
@ -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 #
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user