Skip to content
/ server Public

Commit 37274ae

Browse files
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 6f8ef26)
1 parent a6f5555 commit 37274ae

File tree

4 files changed

+175
-0
lines changed

4 files changed

+175
-0
lines changed

mysql-test/suite/sql_sequence/alter.result

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,76 @@ DROP SEQUENCE s2;
420420
# End of 10.6 tests
421421
#
422422
#
423+
# MDEV-36032 Check when doing ALTER TABLE table_name sequence=1 that table can be a sequence
424+
#
425+
create sequence s;
426+
alter table s sequence=0;
427+
insert into s values (3,1,9223372036854775806,1,1,1000,0,0);
428+
alter table s sequence=1;
429+
ERROR HY000: More than one row in the table
430+
drop table s;
431+
create sequence s;
432+
alter table s sequence=0;
433+
delete from s;
434+
insert into s values (2,500,200,1,1,1000,0,0);
435+
select * from s;
436+
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
437+
2 500 200 1 1 1000 0 0
438+
alter table s sequence=1;
439+
ERROR HY000: Sequence 'test.s' has out of range value for options
440+
check table s;
441+
Table Op Msg_type Msg_text
442+
test.s check status OK
443+
select * from s;
444+
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
445+
2 500 200 1 1 1000 0 0
446+
check table s;
447+
Table Op Msg_type Msg_text
448+
test.s check status OK
449+
drop table s;
450+
CREATE TABLE `s` (
451+
# `next_not_cached_value` bigint(21) NOT NULL,
452+
`minimum_value` bigint(21) NOT NULL,
453+
`maximum_value` bigint(21) NOT NULL,
454+
`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
455+
`increment` bigint(21) NOT NULL COMMENT 'increment value',
456+
`cache_size` bigint(21) unsigned NOT NULL,
457+
`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',
458+
`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
459+
) ENGINE=innodb;
460+
alter table s sequence=1;
461+
ERROR HY000: Sequence 'test.s' table structure is invalid (Wrong number of columns)
462+
drop table s;
463+
create sequence s;
464+
alter table s drop column next_not_cached_value;
465+
ERROR HY000: Sequence 'test.s' table structure is invalid (Wrong number of columns)
466+
drop sequence s;
467+
CREATE TABLE `s1` (
468+
`next_not_cached_value` bigint(21) NOT NULL,
469+
`minimum_value` bigint(21) NOT NULL,
470+
`maximum_value` bigint(21) NOT NULL,
471+
`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
472+
`increment` bigint(21) NOT NULL COMMENT 'increment value',
473+
`cache_size` bigint(21) unsigned NOT NULL,
474+
`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',
475+
`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
476+
) ENGINE=innodb;
477+
alter table s1 sequence=1;
478+
ERROR HY000: Fewer than one row in the table
479+
alter table s1 sequence=0;
480+
insert into s1 values (1,1,9223372036854775806,1,1,1000,0,0);
481+
alter table s1 sequence=1;
482+
alter table s1 sequence=0;
483+
insert into s1 values (2,1,9223372036854775806,1,1,1000,0,0);
484+
alter table s1 sequence=1;
485+
ERROR HY000: More than one row in the table
486+
alter table s1 sequence=0;
487+
insert into s1 values (3,1,9223372036854775806,1,1,1000,0,0);
488+
alter table s1 sequence=1;
489+
ERROR HY000: More than one row in the table
490+
drop table s1;
491+
# End of 10.11 tests
492+
#
423493
# MDEV-28152 Features for sequence
424494
#
425495
create sequence s maxvalue 12345;

mysql-test/suite/sql_sequence/alter.test

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,87 @@ DROP SEQUENCE s2;
294294
--echo # End of 10.6 tests
295295
--echo #
296296

297+
--echo #
298+
--echo # MDEV-36032 Check when doing ALTER TABLE table_name sequence=1 that table can be a sequence
299+
--echo #
300+
301+
## Too many rows
302+
create sequence s;
303+
alter table s sequence=0;
304+
insert into s values (3,1,9223372036854775806,1,1,1000,0,0);
305+
--error ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS
306+
alter table s sequence=1;
307+
drop table s;
308+
309+
## Insert a wrong row (min > max)
310+
create sequence s;
311+
alter table s sequence=0;
312+
delete from s;
313+
insert into s values (2,500,200,1,1,1000,0,0);
314+
select * from s;
315+
--error ER_SEQUENCE_INVALID_DATA
316+
alter table s sequence=1;
317+
check table s;
318+
select * from s;
319+
check table s;
320+
drop table s;
321+
322+
## Invalid table structure (already implemented before MDEV-36032)
323+
CREATE TABLE `s` (
324+
# `next_not_cached_value` bigint(21) NOT NULL,
325+
`minimum_value` bigint(21) NOT NULL,
326+
`maximum_value` bigint(21) NOT NULL,
327+
`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
328+
`increment` bigint(21) NOT NULL COMMENT 'increment value',
329+
`cache_size` bigint(21) unsigned NOT NULL,
330+
`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',
331+
`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
332+
) ENGINE=innodb;
333+
--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
334+
alter table s sequence=1;
335+
drop table s;
336+
337+
## Altering a sequence table to a wrong structure is detected (already
338+
## implemented before MDEV-36032)
339+
create sequence s;
340+
--error ER_SEQUENCE_INVALID_TABLE_STRUCTURE
341+
alter table s drop column next_not_cached_value;
342+
drop sequence s;
343+
344+
## Create a normal table then alter to sequence
345+
CREATE TABLE `s1` (
346+
`next_not_cached_value` bigint(21) NOT NULL,
347+
`minimum_value` bigint(21) NOT NULL,
348+
`maximum_value` bigint(21) NOT NULL,
349+
`start_value` bigint(21) NOT NULL COMMENT 'start value when sequences is created or value if RESTART is used',
350+
`increment` bigint(21) NOT NULL COMMENT 'increment value',
351+
`cache_size` bigint(21) unsigned NOT NULL,
352+
`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',
353+
`cycle_count` bigint(21) NOT NULL COMMENT 'How many cycles have been done'
354+
) ENGINE=innodb;
355+
356+
--error ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS
357+
alter table s1 sequence=1;
358+
# (for coverage) alter a non sequence table with sequence=0
359+
alter table s1 sequence=0;
360+
insert into s1 values (1,1,9223372036854775806,1,1,1000,0,0);
361+
alter table s1 sequence=1;
362+
363+
alter table s1 sequence=0;
364+
insert into s1 values (2,1,9223372036854775806,1,1,1000,0,0);
365+
--error ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS
366+
alter table s1 sequence=1;
367+
368+
# (for coverage) alter a non sequence table with sequence=0
369+
alter table s1 sequence=0;
370+
insert into s1 values (3,1,9223372036854775806,1,1,1000,0,0);
371+
--error ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS
372+
alter table s1 sequence=1;
373+
374+
drop table s1;
375+
376+
--echo # End of 10.11 tests
377+
297378
--echo #
298379
--echo # MDEV-28152 Features for sequence
299380
--echo #

sql/handler.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5777,6 +5777,9 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
57775777
(table->s->row_type != create_info->row_type))
57785778
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
57795779

5780+
if (create_info->sequence)
5781+
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
5782+
57805783
uint table_changes= (ha_alter_info->handler_flags &
57815784
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) ?
57825785
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;

sql/sql_table.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12588,6 +12588,16 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
1258812588
copy_end=copy;
1258912589
to->s->default_fields= 0;
1259012590
error= 1;
12591+
if (to->s->table_type == TABLE_TYPE_SEQUENCE &&
12592+
from->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT &&
12593+
from->file->stats.records != 1)
12594+
{
12595+
if (from->file->stats.records > 1)
12596+
my_error(ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS, MYF(0));
12597+
else
12598+
my_error(ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS, MYF(0));
12599+
goto err;
12600+
}
1259112601
for (Field **ptr=to->field ; *ptr ; ptr++)
1259212602
{
1259312603
def=it++;
@@ -12798,6 +12808,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
1279812808
else
1279912809
to->next_number_field->reset();
1280012810
}
12811+
if (to->s->table_type == TABLE_TYPE_SEQUENCE && found_count == 1)
12812+
{
12813+
my_error(ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS, MYF(0));
12814+
error= 1;
12815+
break;
12816+
}
1280112817
error= to->file->ha_write_row(to->record[0]);
1280212818
to->auto_increment_field_not_null= FALSE;
1280312819
if (unlikely(error))
@@ -12869,6 +12885,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
1286912885

1287012886
DEBUG_SYNC(thd, "alter_table_copy_end");
1287112887

12888+
if (to->s->table_type == TABLE_TYPE_SEQUENCE && found_count == 0)
12889+
{
12890+
my_error(ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS, MYF(0));
12891+
error= 1;
12892+
}
1287212893
THD_STAGE_INFO(thd, stage_enabling_keys);
1287312894
thd_progress_next_stage(thd);
1287412895

0 commit comments

Comments
 (0)