Skip to content

Commit 6f8ef26

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.
1 parent cafd22d commit 6f8ef26

File tree

5 files changed

+180
-0
lines changed

5 files changed

+180
-0
lines changed

mysql-test/suite/sql_sequence/alter.result

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,3 +419,73 @@ DROP SEQUENCE s2;
419419
#
420420
# End of 10.6 tests
421421
#
422+
#
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

mysql-test/suite/sql_sequence/alter.test

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

sql/handler.cc

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

5457+
if (create_info->sequence)
5458+
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
5459+
54575460
uint table_changes= (ha_alter_info->handler_flags &
54585461
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) ?
54595462
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;

sql/share/errmsg-utf8.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10758,3 +10758,7 @@ ER_CM_OPTION_MISSING_REQUIREMENT
1075810758
eng "CHANGE MASTER TO option '%s=%s' is missing requirement %s"
1075910759
ER_SLAVE_STATEMENT_TIMEOUT 70100
1076010760
eng "Slave log event execution was interrupted (slave_max_statement_time exceeded)"
10761+
ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS
10762+
eng "Fewer than one row in the table"
10763+
ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS
10764+
eng "More than one row in the table"

sql/sql_table.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12154,6 +12154,16 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, bool ignore,
1215412154
Create_field *def;
1215512155
copy_end=copy;
1215612156
to->s->default_fields= 0;
12157+
if (to->s->table_type == TABLE_TYPE_SEQUENCE &&
12158+
from->file->ha_table_flags() & HA_STATS_RECORDS_IS_EXACT &&
12159+
from->file->stats.records != 1)
12160+
{
12161+
if (from->file->stats.records > 1)
12162+
my_error(ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS, MYF(0));
12163+
else
12164+
my_error(ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS, MYF(0));
12165+
goto err;
12166+
}
1215712167
for (Field **ptr=to->field ; *ptr ; ptr++)
1215812168
{
1215912169
def=it++;
@@ -12337,6 +12347,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, bool ignore,
1233712347
else
1233812348
to->next_number_field->reset();
1233912349
}
12350+
if (to->s->table_type == TABLE_TYPE_SEQUENCE && found_count == 1)
12351+
{
12352+
my_error(ER_SEQUENCE_TABLE_HAS_TOO_MANY_ROWS, MYF(0));
12353+
error= 1;
12354+
break;
12355+
}
1234012356
error= to->file->ha_write_row(to->record[0]);
1234112357
to->auto_increment_field_not_null= FALSE;
1234212358
if (unlikely(error))
@@ -12356,6 +12372,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, bool ignore,
1235612372
thd->get_stmt_da()->inc_current_row_for_warning();
1235712373
}
1235812374

12375+
if (to->s->table_type == TABLE_TYPE_SEQUENCE && found_count == 0)
12376+
{
12377+
my_error(ER_SEQUENCE_TABLE_HAS_TOO_FEW_ROWS, MYF(0));
12378+
error= 1;
12379+
}
12380+
1235912381
THD_STAGE_INFO(thd, stage_enabling_keys);
1236012382
thd_progress_next_stage(thd);
1236112383

0 commit comments

Comments
 (0)