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
|
# 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;
|
||||||
|
@ -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 #
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user