Skip to content

Commit e53e7cd

Browse files
committed
MDEV-20545 Assertion col.vers_sys_end() in dict_index_t::vers_history_row
Index values for row_start/row_end was wrongly calculated for inplace ALTER for some layout of virtual fields. Possible impact 1. history row is not detected upon build clustered index for inplace ALTER which may lead to duplicate key errors on auto-increment and FTS index add. 2. foreign key constraint may falsely fail. 3. after inplace ALTER before server restart trx-based system versioning can cause server crash or incorrect data written upon UPDATE.
1 parent 1710b64 commit e53e7cd

File tree

4 files changed

+137
-4
lines changed

4 files changed

+137
-4
lines changed

mysql-test/suite/versioning/r/alter.result

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,3 +786,62 @@ with system versioning,
786786
modify row_start varchar(8);
787787
ERROR HY000: PERIOD FOR SYSTEM_TIME must use columns `row_start` and `row_end`
788788
drop table t1;
789+
#
790+
# MDEV-20545 Assertion (col.vers_sys_end()) upon inplace ALTER with virtual columns
791+
#
792+
create table t1 (
793+
a int,
794+
va int as (a) virtual,
795+
b int,
796+
vb int as (b) virtual,
797+
c int,
798+
vc int as (c) virtual,
799+
d int,
800+
e int,
801+
index(va)
802+
) engine=innodb with system versioning;
803+
replace into t1 () values (),();
804+
set statement system_versioning_alter_history=keep for alter table t1 drop e;
805+
alter table t1 algorithm=inplace, drop system versioning;
806+
drop table t1;
807+
#
808+
# MDEV-20765 Assertion (type.vers_sys_end()) upon inplace ALTER with virtual columns
809+
#
810+
create table t1 (
811+
a int,
812+
b int as (a) virtual,
813+
c int,
814+
d int as (c) virtual,
815+
e int,
816+
f int as (e) virtual,
817+
g int,
818+
h int,
819+
i int,
820+
index(d),
821+
key(h),
822+
foreign key (g) references t1 (h)
823+
) engine=innodb with system versioning;
824+
set system_versioning_alter_history= keep;
825+
alter table t1 drop column i;
826+
insert into t1 (g,h) values (1,1);
827+
drop table t1;
828+
#
829+
# MDEV-29034 Assertion (o->ind == vers_start) upon inplace ALTER with virtual columns
830+
#
831+
create table b (
832+
pk integer auto_increment,
833+
col_int_key integer,
834+
col_varchar_key varchar(1),
835+
o bit, n bit,
836+
h float as ( n + 2 ) virtual,
837+
v bit,
838+
primary key (pk),
839+
key (col_varchar_key, col_int_key)
840+
) engine = innodb;
841+
set `system_versioning_alter_history`= keep;
842+
alter table `b` add system versioning;
843+
alter table `b` add column if not exists ( w bit, v serial );
844+
Warnings:
845+
Note 1060 Duplicate column name 'v'
846+
alter table `b` add column if not exists ( p bit );
847+
drop table `b`;

mysql-test/suite/versioning/t/alter.test

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,3 +677,65 @@ alter table t1
677677
modify row_start varchar(8);
678678
# cleanup
679679
drop table t1;
680+
681+
--echo #
682+
--echo # MDEV-20545 Assertion (col.vers_sys_end()) upon inplace ALTER with virtual columns
683+
--echo #
684+
create table t1 (
685+
a int,
686+
va int as (a) virtual,
687+
b int,
688+
vb int as (b) virtual,
689+
c int,
690+
vc int as (c) virtual,
691+
d int,
692+
e int,
693+
index(va)
694+
) engine=innodb with system versioning;
695+
replace into t1 () values (),();
696+
set statement system_versioning_alter_history=keep for alter table t1 drop e;
697+
alter table t1 algorithm=inplace, drop system versioning;
698+
# cleanup
699+
drop table t1;
700+
701+
--echo #
702+
--echo # MDEV-20765 Assertion (type.vers_sys_end()) upon inplace ALTER with virtual columns
703+
--echo #
704+
create table t1 (
705+
a int,
706+
b int as (a) virtual,
707+
c int,
708+
d int as (c) virtual,
709+
e int,
710+
f int as (e) virtual,
711+
g int,
712+
h int,
713+
i int,
714+
index(d),
715+
key(h),
716+
foreign key (g) references t1 (h)
717+
) engine=innodb with system versioning;
718+
set system_versioning_alter_history= keep;
719+
alter table t1 drop column i;
720+
insert into t1 (g,h) values (1,1);
721+
# cleanup
722+
drop table t1;
723+
724+
--echo #
725+
--echo # MDEV-29034 Assertion (o->ind == vers_start) upon inplace ALTER with virtual columns
726+
--echo #
727+
create table b (
728+
pk integer auto_increment,
729+
col_int_key integer,
730+
col_varchar_key varchar(1),
731+
o bit, n bit,
732+
h float as ( n + 2 ) virtual,
733+
v bit,
734+
primary key (pk),
735+
key (col_varchar_key, col_int_key)
736+
) engine = innodb;
737+
set `system_versioning_alter_history`= keep;
738+
alter table `b` add system versioning;
739+
alter table `b` add column if not exists ( w bit, v serial );
740+
alter table `b` add column if not exists ( p bit );
741+
drop table `b`;

sql/field.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,16 @@ class Field: public Value_source
16121612
return flags & (VERS_ROW_START | VERS_ROW_END);
16131613
}
16141614

1615+
bool vers_sys_start() const
1616+
{
1617+
return flags & VERS_ROW_START;
1618+
}
1619+
1620+
bool vers_sys_end() const
1621+
{
1622+
return flags & VERS_ROW_END;
1623+
}
1624+
16151625
bool vers_update_unversioned() const
16161626
{
16171627
return flags & VERS_UPDATE_UNVERSIONED_FLAG;

storage/innobase/handler/handler0alter.cc

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4556,10 +4556,12 @@ innobase_build_col_map(
45564556
col_map[old_i - num_old_v] = i;
45574557
if (old_table->versioned()
45584558
&& altered_table->versioned()) {
4559-
if (old_i == old_table->vers_start) {
4560-
new_table->vers_start = i + num_v;
4561-
} else if (old_i == old_table->vers_end) {
4562-
new_table->vers_end = i + num_v;
4559+
if (old_i - num_old_v == old_table->vers_start) {
4560+
ut_ad(field->vers_sys_start());
4561+
new_table->vers_start = i;
4562+
} else if (old_i - num_old_v == old_table->vers_end) {
4563+
ut_ad(field->vers_sys_end());
4564+
new_table->vers_end = i;
45634565
}
45644566
}
45654567
goto found_col;

0 commit comments

Comments
 (0)