Skip to content

Commit 3c6b771

Browse files
committed
MDEV-9045 Inconsistent handling of "ALGORITHM=INPLACE" with PERSISTENT generated columns
Only set Alter_inplace_info::ALTER_COLUMN_VCOL flag if a vcol might be affected by the ALTER TABLE statement
1 parent 48ea84f commit 3c6b771

File tree

4 files changed

+106
-5
lines changed

4 files changed

+106
-5
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
create table t1(id int auto_increment primary key, handle int, data bigint not null default 0) engine = innodb;
2+
insert into t1(handle) values(12),(54),(NULL);
3+
select *, md5(handle) from t1;
4+
id handle data md5(handle)
5+
1 12 0 c20ad4d76fe97759aa27a0c99bff6710
6+
2 54 0 a684eceee76fc522773286a895bc8436
7+
3 NULL 0 NULL
8+
alter table t1 add index handle(handle), algorithm=inplace;
9+
alter table t1 add column hash varchar(32) as (md5(handle)) persistent, algorithm=inplace;
10+
ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
11+
alter table t1 add column hash varchar(32) as (md5(handle)) persistent, add unique index hash(hash), algorithm=inplace;
12+
ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
13+
alter table t1 add column hash varchar(32) as (md5(handle)) persistent, add unique index hash(hash), algorithm=copy;
14+
select * from t1;
15+
id handle data hash
16+
1 12 0 c20ad4d76fe97759aa27a0c99bff6710
17+
2 54 0 a684eceee76fc522773286a895bc8436
18+
3 NULL 0 NULL
19+
alter table t1 modify column hash varchar(32) as (md5(handle+1)) persistent, algorithm=inplace;
20+
ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
21+
alter table t1 modify column hash varchar(32) as (md5(handle+1)) persistent, algorithm=copy;
22+
select * from t1;
23+
id handle data hash
24+
1 12 0 c51ce410c124a10e0db5e4b97fc2af39
25+
2 54 0 b53b3a3d6ab90ce0268229151c9bde11
26+
3 NULL 0 NULL
27+
alter table t1 modify column handle int not null, algorithm=inplace;
28+
ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
29+
alter table t1 modify column handle int not null, algorithm=copy;
30+
Warnings:
31+
Warning 1265 Data truncated for column 'handle' at row 3
32+
select * from t1;
33+
id handle data hash
34+
1 12 0 c51ce410c124a10e0db5e4b97fc2af39
35+
2 54 0 b53b3a3d6ab90ce0268229151c9bde11
36+
3 0 0 c4ca4238a0b923820dcc509a6f75849b
37+
alter table t1 drop index handle, algorithm=inplace;
38+
create index data on t1(data) algorithm=inplace;
39+
alter table t1 drop column data, algorithm=inplace;
40+
alter table t1 add column sha varchar(32) as (sha1(handle)) persistent, algorithm=inplace;
41+
ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
42+
alter table t1 add column sha varchar(32), algorithm=inplace;
43+
alter table t1 drop column hash, algorithm=inplace;
44+
drop table t1;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#
2+
# MDEV-9045 Inconsistent handling of "ALGORITHM=INPLACE" with PERSISTENT generated columns
3+
#
4+
--source include/have_innodb.inc
5+
6+
create table t1(id int auto_increment primary key, handle int, data bigint not null default 0) engine = innodb;
7+
insert into t1(handle) values(12),(54),(NULL);
8+
select *, md5(handle) from t1;
9+
alter table t1 add index handle(handle), algorithm=inplace;
10+
--error ER_ALTER_OPERATION_NOT_SUPPORTED
11+
alter table t1 add column hash varchar(32) as (md5(handle)) persistent, algorithm=inplace;
12+
--error ER_ALTER_OPERATION_NOT_SUPPORTED
13+
alter table t1 add column hash varchar(32) as (md5(handle)) persistent, add unique index hash(hash), algorithm=inplace;
14+
alter table t1 add column hash varchar(32) as (md5(handle)) persistent, add unique index hash(hash), algorithm=copy;
15+
select * from t1;
16+
--error ER_ALTER_OPERATION_NOT_SUPPORTED
17+
alter table t1 modify column hash varchar(32) as (md5(handle+1)) persistent, algorithm=inplace;
18+
alter table t1 modify column hash varchar(32) as (md5(handle+1)) persistent, algorithm=copy;
19+
select * from t1;
20+
--error ER_ALTER_OPERATION_NOT_SUPPORTED
21+
alter table t1 modify column handle int not null, algorithm=inplace;
22+
alter table t1 modify column handle int not null, algorithm=copy;
23+
select * from t1;
24+
alter table t1 drop index handle, algorithm=inplace;
25+
create index data on t1(data) algorithm=inplace;
26+
alter table t1 drop column data, algorithm=inplace;
27+
--error ER_ALTER_OPERATION_NOT_SUPPORTED
28+
alter table t1 add column sha varchar(32) as (sha1(handle)) persistent, algorithm=inplace;
29+
alter table t1 add column sha varchar(32), algorithm=inplace;
30+
alter table t1 drop column hash, algorithm=inplace;
31+
drop table t1;

sql/field.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,13 @@ class Virtual_column_info: public Sql_alloc
283283
{
284284
in_partitioning_expr= TRUE;
285285
}
286+
bool is_equal(Virtual_column_info* vcol)
287+
{
288+
return field_type == vcol->get_real_type()
289+
&& stored_in_db == vcol->is_stored()
290+
&& expr_str.length == vcol->expr_str.length
291+
&& memcmp(expr_str.str, vcol->expr_str.str, expr_str.length) == 0;
292+
}
286293
};
287294

288295
class Field

sql/sql_table.cc

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6146,6 +6146,7 @@ static bool fill_alter_inplace_info(THD *thd,
61466146
c) flags passed to storage engine contain more detailed information
61476147
about nature of changes than those provided from parser.
61486148
*/
6149+
bool maybe_alter_vcol= false;
61496150
for (f_ptr= table->field; (field= *f_ptr); f_ptr++)
61506151
{
61516152
/* Clear marker for renamed or dropped field
@@ -6169,7 +6170,8 @@ static bool fill_alter_inplace_info(THD *thd,
61696170
/*
61706171
Check if type of column has changed to some incompatible type.
61716172
*/
6172-
switch (field->is_equal(new_field))
6173+
uint is_equal= field->is_equal(new_field);
6174+
switch (is_equal)
61736175
{
61746176
case IS_EQUAL_NO:
61756177
/* New column type is incompatible with old one. */
@@ -6222,15 +6224,17 @@ static bool fill_alter_inplace_info(THD *thd,
62226224
}
62236225

62246226
/*
6225-
Check if the altered column is computed and either
6227+
Check if the column is computed and either
62266228
is stored or is used in the partitioning expression.
6227-
TODO: Mark such a column with an alter flag only if
6228-
the defining expression has changed.
62296229
*/
62306230
if (field->vcol_info &&
62316231
(field->stored_in_db || field->vcol_info->is_in_partitioning_expr()))
62326232
{
6233-
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL;
6233+
if (is_equal == IS_EQUAL_NO ||
6234+
!field->vcol_info->is_equal(new_field->vcol_info))
6235+
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL;
6236+
else
6237+
maybe_alter_vcol= true;
62346238
}
62356239

62366240
/* Check if field was renamed */
@@ -6296,6 +6300,21 @@ static bool fill_alter_inplace_info(THD *thd,
62966300
}
62976301
}
62986302

6303+
if (maybe_alter_vcol)
6304+
{
6305+
/*
6306+
No virtual column was altered, but perhaps one of the other columns was,
6307+
and that column was part of the vcol expression?
6308+
We don't detect this correctly (FIXME), so let's just say that a vcol
6309+
*might* be affected if any other column was altered.
6310+
*/
6311+
if (ha_alter_info->handler_flags &
6312+
( Alter_inplace_info::ALTER_COLUMN_TYPE
6313+
| Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE
6314+
| Alter_inplace_info::ALTER_COLUMN_OPTION ))
6315+
ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_VCOL;
6316+
}
6317+
62996318
new_field_it.init(alter_info->create_list);
63006319
while ((new_field= new_field_it++))
63016320
{

0 commit comments

Comments
 (0)