Skip to content

Commit 2f84df5

Browse files
author
Guilhem Bichot
committed
bug#21465626: assert/crash on dropping/adding virtual column
It was a communication mismatch between sql layer and innodb. The following Alter_inplace_info flags are split into a flag for virtual columns and a flag for stored columns: ALTER_ADD_COLUMN, ALTER_DROP_COLUMN, ALTER_COLUMN_TYPE, ALTER_COLUMN_ORDER. With this finer-grained information, InnoDB's logic is improved: - more operations are in-place - operations which should not be in-place are better caught. Some flags from Alter_info are not needed anymore and removed: ALTER_STORED_GCOLUMN, ALTER_VIRTUAL_GCOLUMN ; the former was part of Alter_info which is intended for parser<->DDL communication; that flag was used for communication between different functions of the server in a DDL, which isn't the mission of Alter_info but of Alter_table_ctx; it is replaced with a new Alter_table_ctx::requires_generated_column_server_evaluation. HA_ALTER_STORED_GCOL was also unneeded and removed. ALTER_STORED_COLUMN_ORDER is set by a logic which ignores virtual columns; indeed the creation/removal of those is not affecting the format of rows. This allows in-place ALTER when adding/removing a virtual column.
1 parent 9676f0d commit 2f84df5

14 files changed

+394
-248
lines changed

mysql-test/suite/gcol/inc/gcol_column_def_options.inc

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ drop table t1;
4747

4848
--echo # Added columns mixed with virtual GC and other columns
4949
create table t1 (a int);
50-
--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN
50+
insert into t1 values(1);
51+
--enable_info
5152
alter table t1 add column (b int generated always as (a+1) virtual, c int);
52-
--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN
5353
alter table t1 add column (d int, e int generated always as (a+1) virtual);
54-
--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN
5554
alter table t1 add column (f int generated always as (a+1) virtual, g int as(5) stored);
5655
alter table t1 add column (h int generated always as (a+1) virtual, i int as(5) virtual);
56+
--disable_info
5757
drop table t1;
5858

5959
--echo # DEFAULT
@@ -405,3 +405,37 @@ PARTITION BY RANGE (store_id) (
405405

406406
INSERT INTO t1 VALUES(1, 2, default);
407407
DROP TABLE t1;
408+
409+
--echo # Bug#21465626:ASSERT/CRASH ON DROPPING/ADDING VIRTUAL COLUMN
410+
CREATE TABLE t (a int(11), b int(11),
411+
c int(11) GENERATED ALWAYS AS (a+b) VIRTUAL,
412+
d int(11) GENERATED ALWAYS AS (a+b) VIRTUAL);
413+
INSERT INTO t(a,b) VALUES(1,2);
414+
--enable_info
415+
--echo # Mixed drop/add/rename virtual with non-virtual columns,
416+
--echo # ALGORITHM=INPLACE is not supported for InnoDB
417+
ALTER TABLE t DROP d, ADD e varchar(10);
418+
ALTER TABLE t ADD d int, ADD f char(10) AS ('aaa');
419+
ALTER TABLE t CHANGE d dd int, CHANGE f ff varchar(10) AS ('bbb');
420+
--echo # Only drop/add/change virtual, inplace is supported for Innodb
421+
ALTER TABLE t DROP c, DROP ff;
422+
ALTER TABLE t ADD c int(11) as (a+b), ADD f varchar(10) as ('aaa');
423+
ALTER TABLE t CHANGE c c int(11) as (a), CHANGE f f varchar(10) as('bbb');
424+
--echo # Change order should be ALGORITHM=INPLACE on Innodb
425+
ALTER TABLE t CHANGE c c int(11) as (a) after f;
426+
ALTER TABLE t CHANGE b b int(11) after c;
427+
--echo # TODO: Changing virtual column type should be ALGORITHM=INPLACE on InnoDB
428+
ALTER TABLE t CHANGE c c varchar(10) as ('a');
429+
--echo # Changing stored column type is ALGORITHM=COPY
430+
ALTER TABLE t CHANGE dd d varchar(10);
431+
if ($support_virtual_index)
432+
{
433+
434+
ALTER TABLE t ADD INDEX idx(a), ADD INDEX idx1(c);
435+
ALTER TABLE t RENAME INDEX idx TO idx2, RENAME INDEX idx1 TO idx3;
436+
ALTER TABLE t DROP INDEX idx2, DROP INDEX idx3;
437+
ALTER TABLE t ADD INDEX idx(c), ADD INDEX idx1(d);
438+
ALTER TABLE t DROP INDEX idx, DROP INDEX idx1;
439+
}
440+
--disable_info
441+
DROP TABLE t;

mysql-test/suite/gcol/r/gcol_column_def_options_innodb.result

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,19 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
3333
drop table t1;
3434
# Added columns mixed with virtual GC and other columns
3535
create table t1 (a int);
36+
insert into t1 values(1);
3637
alter table t1 add column (b int generated always as (a+1) virtual, c int);
37-
ERROR HY000: 'Adding virtual generated columns and other columns in one single ALTER statement' is not supported for generated columns.
38+
affected rows: 1
39+
info: Records: 1 Duplicates: 0 Warnings: 0
3840
alter table t1 add column (d int, e int generated always as (a+1) virtual);
39-
ERROR HY000: 'Adding virtual generated columns and other columns in one single ALTER statement' is not supported for generated columns.
41+
affected rows: 1
42+
info: Records: 1 Duplicates: 0 Warnings: 0
4043
alter table t1 add column (f int generated always as (a+1) virtual, g int as(5) stored);
41-
ERROR HY000: 'Adding virtual generated columns and other columns in one single ALTER statement' is not supported for generated columns.
44+
affected rows: 1
45+
info: Records: 1 Duplicates: 0 Warnings: 0
4246
alter table t1 add column (h int generated always as (a+1) virtual, i int as(5) virtual);
47+
affected rows: 0
48+
info: Records: 0 Duplicates: 0 Warnings: 0
4349
drop table t1;
4450
# DEFAULT
4551
create table t1 (a int, b int generated always as (a+1) virtual default 0);
@@ -510,6 +516,63 @@ PARTITION p3 VALUES LESS THAN (21)
510516
);
511517
INSERT INTO t1 VALUES(1, 2, default);
512518
DROP TABLE t1;
519+
# Bug#21465626:ASSERT/CRASH ON DROPPING/ADDING VIRTUAL COLUMN
520+
CREATE TABLE t (a int(11), b int(11),
521+
c int(11) GENERATED ALWAYS AS (a+b) VIRTUAL,
522+
d int(11) GENERATED ALWAYS AS (a+b) VIRTUAL);
523+
INSERT INTO t(a,b) VALUES(1,2);
524+
# Mixed drop/add/rename virtual with non-virtual columns,
525+
# ALGORITHM=INPLACE is not supported for InnoDB
526+
ALTER TABLE t DROP d, ADD e varchar(10);
527+
affected rows: 1
528+
info: Records: 1 Duplicates: 0 Warnings: 0
529+
ALTER TABLE t ADD d int, ADD f char(10) AS ('aaa');
530+
affected rows: 1
531+
info: Records: 1 Duplicates: 0 Warnings: 0
532+
ALTER TABLE t CHANGE d dd int, CHANGE f ff varchar(10) AS ('bbb');
533+
affected rows: 0
534+
info: Records: 0 Duplicates: 0 Warnings: 0
535+
# Only drop/add/change virtual, inplace is supported for Innodb
536+
ALTER TABLE t DROP c, DROP ff;
537+
affected rows: 0
538+
info: Records: 0 Duplicates: 0 Warnings: 0
539+
ALTER TABLE t ADD c int(11) as (a+b), ADD f varchar(10) as ('aaa');
540+
affected rows: 0
541+
info: Records: 0 Duplicates: 0 Warnings: 0
542+
ALTER TABLE t CHANGE c c int(11) as (a), CHANGE f f varchar(10) as('bbb');
543+
affected rows: 0
544+
info: Records: 0 Duplicates: 0 Warnings: 0
545+
# Change order should be ALGORITHM=INPLACE on Innodb
546+
ALTER TABLE t CHANGE c c int(11) as (a) after f;
547+
affected rows: 1
548+
info: Records: 1 Duplicates: 0 Warnings: 0
549+
ALTER TABLE t CHANGE b b int(11) after c;
550+
affected rows: 1
551+
info: Records: 1 Duplicates: 0 Warnings: 0
552+
# TODO: Changing virtual column type should be ALGORITHM=INPLACE on InnoDB
553+
ALTER TABLE t CHANGE c c varchar(10) as ('a');
554+
affected rows: 0
555+
info: Records: 0 Duplicates: 0 Warnings: 0
556+
# Changing stored column type is ALGORITHM=COPY
557+
ALTER TABLE t CHANGE dd d varchar(10);
558+
affected rows: 1
559+
info: Records: 1 Duplicates: 0 Warnings: 0
560+
ALTER TABLE t ADD INDEX idx(a), ADD INDEX idx1(c);
561+
affected rows: 0
562+
info: Records: 0 Duplicates: 0 Warnings: 0
563+
ALTER TABLE t RENAME INDEX idx TO idx2, RENAME INDEX idx1 TO idx3;
564+
affected rows: 0
565+
info: Records: 0 Duplicates: 0 Warnings: 0
566+
ALTER TABLE t DROP INDEX idx2, DROP INDEX idx3;
567+
affected rows: 0
568+
info: Records: 0 Duplicates: 0 Warnings: 0
569+
ALTER TABLE t ADD INDEX idx(c), ADD INDEX idx1(d);
570+
affected rows: 0
571+
info: Records: 0 Duplicates: 0 Warnings: 0
572+
ALTER TABLE t DROP INDEX idx, DROP INDEX idx1;
573+
affected rows: 0
574+
info: Records: 0 Duplicates: 0 Warnings: 0
575+
DROP TABLE t;
513576
DROP VIEW IF EXISTS v1,v2;
514577
DROP TABLE IF EXISTS t1,t2,t3;
515578
DROP PROCEDURE IF EXISTS p1;

mysql-test/suite/gcol/r/gcol_column_def_options_myisam.result

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,19 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
3333
drop table t1;
3434
# Added columns mixed with virtual GC and other columns
3535
create table t1 (a int);
36+
insert into t1 values(1);
3637
alter table t1 add column (b int generated always as (a+1) virtual, c int);
37-
ERROR HY000: 'Adding virtual generated columns and other columns in one single ALTER statement' is not supported for generated columns.
38+
affected rows: 1
39+
info: Records: 1 Duplicates: 0 Warnings: 0
3840
alter table t1 add column (d int, e int generated always as (a+1) virtual);
39-
ERROR HY000: 'Adding virtual generated columns and other columns in one single ALTER statement' is not supported for generated columns.
41+
affected rows: 1
42+
info: Records: 1 Duplicates: 0 Warnings: 0
4043
alter table t1 add column (f int generated always as (a+1) virtual, g int as(5) stored);
41-
ERROR HY000: 'Adding virtual generated columns and other columns in one single ALTER statement' is not supported for generated columns.
44+
affected rows: 1
45+
info: Records: 1 Duplicates: 0 Warnings: 0
4246
alter table t1 add column (h int generated always as (a+1) virtual, i int as(5) virtual);
47+
affected rows: 1
48+
info: Records: 1 Duplicates: 0 Warnings: 0
4349
drop table t1;
4450
# DEFAULT
4551
create table t1 (a int, b int generated always as (a+1) virtual default 0);
@@ -478,6 +484,48 @@ PARTITION p3 VALUES LESS THAN (21)
478484
);
479485
INSERT INTO t1 VALUES(1, 2, default);
480486
DROP TABLE t1;
487+
# Bug#21465626:ASSERT/CRASH ON DROPPING/ADDING VIRTUAL COLUMN
488+
CREATE TABLE t (a int(11), b int(11),
489+
c int(11) GENERATED ALWAYS AS (a+b) VIRTUAL,
490+
d int(11) GENERATED ALWAYS AS (a+b) VIRTUAL);
491+
INSERT INTO t(a,b) VALUES(1,2);
492+
# Mixed drop/add/rename virtual with non-virtual columns,
493+
# ALGORITHM=INPLACE is not supported for InnoDB
494+
ALTER TABLE t DROP d, ADD e varchar(10);
495+
affected rows: 1
496+
info: Records: 1 Duplicates: 0 Warnings: 0
497+
ALTER TABLE t ADD d int, ADD f char(10) AS ('aaa');
498+
affected rows: 1
499+
info: Records: 1 Duplicates: 0 Warnings: 0
500+
ALTER TABLE t CHANGE d dd int, CHANGE f ff varchar(10) AS ('bbb');
501+
affected rows: 1
502+
info: Records: 1 Duplicates: 0 Warnings: 0
503+
# Only drop/add/change virtual, inplace is supported for Innodb
504+
ALTER TABLE t DROP c, DROP ff;
505+
affected rows: 1
506+
info: Records: 1 Duplicates: 0 Warnings: 0
507+
ALTER TABLE t ADD c int(11) as (a+b), ADD f varchar(10) as ('aaa');
508+
affected rows: 1
509+
info: Records: 1 Duplicates: 0 Warnings: 0
510+
ALTER TABLE t CHANGE c c int(11) as (a), CHANGE f f varchar(10) as('bbb');
511+
affected rows: 0
512+
info: Records: 0 Duplicates: 0 Warnings: 0
513+
# Change order should be ALGORITHM=INPLACE on Innodb
514+
ALTER TABLE t CHANGE c c int(11) as (a) after f;
515+
affected rows: 1
516+
info: Records: 1 Duplicates: 0 Warnings: 0
517+
ALTER TABLE t CHANGE b b int(11) after c;
518+
affected rows: 1
519+
info: Records: 1 Duplicates: 0 Warnings: 0
520+
# TODO: Changing virtual column type should be ALGORITHM=INPLACE on InnoDB
521+
ALTER TABLE t CHANGE c c varchar(10) as ('a');
522+
affected rows: 1
523+
info: Records: 1 Duplicates: 0 Warnings: 0
524+
# Changing stored column type is ALGORITHM=COPY
525+
ALTER TABLE t CHANGE dd d varchar(10);
526+
affected rows: 1
527+
info: Records: 1 Duplicates: 0 Warnings: 0
528+
DROP TABLE t;
481529
DROP VIEW IF EXISTS v1,v2;
482530
DROP TABLE IF EXISTS t1,t2,t3;
483531
DROP PROCEDURE IF EXISTS p1;

mysql-test/suite/innodb/r/innodb_v_basic.result

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,13 @@ pos base_pos
190190
262148 0
191191
DROP TABLE t1;
192192
CREATE TABLE t1(a INT);
193+
INSERT INTO t1 VALUES(1);
193194
ALTER TABLE t1 add COLUMN (f INT generated always as (a+1) virtual, g INT );
194-
ERROR HY000: 'Adding virtual generated columns and other columns in one single ALTER statement' is not supported for generated columns.
195-
ALTER TABLE t1 add COLUMN (f INT generated always as (a+1) virtual), add INDEX idx (f), algorithm=inplace;
195+
ALTER TABLE t1 add COLUMN (h INT generated always as (a+1) virtual), add INDEX idx (h), algorithm=inplace;
196196
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: INPLACE ADD or DROP of virtual columns cannot be combined with other ALTER TABLE actions. Try ALGORITHM=COPY.
197-
ALTER TABLE t1 add COLUMN (f INT generated always as (a+1) virtual), add INDEX idx (f), algorithm=copy;
197+
ALTER TABLE t1 add COLUMN (h INT generated always as (a+1) virtual), add INDEX idx (h);
198+
affected rows: 1
199+
info: Records: 1 Duplicates: 0 Warnings: 0
198200
DROP TABLE t1;
199201
CREATE TABLE t1(a INT);
200202
CREATE INDEX idx ON t1(a);
@@ -607,8 +609,7 @@ CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10), j I
607609
INSERT INTO t VALUES(11, 22, DEFAULT, "AAA", 8, DEFAULT, "XXX", DEFAULT);
608610
INSERT INTO t VALUES(1, 2, DEFAULT, "uuu", 9, DEFAULT, "uu", DEFAULT);
609611
INSERT INTO t VALUES(3, 4, DEFAULT, "uooo", 1, DEFAULT, "umm", DEFAULT);
610-
alter table t add x int, add m int generated ALWAYS AS(x);
611-
ERROR HY000: 'Adding virtual generated columns and other columns in one single ALTER statement' is not supported for generated columns.
612+
alter table t add x int, add xx int generated ALWAYS AS(x);
612613
DROP TABLE t;
613614
CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10), j INT, m INT GENERATED ALWAYS AS(b + j), n VARCHAR(10), p VARCHAR(20) GENERATED ALWAYS AS(CONCAT(n, h)), INDEX idx1(c), INDEX idx2 (m), INDEX idx3(p));
614615
INSERT INTO t VALUES(11, 22, DEFAULT, "AAA", 8, DEFAULT, "XXX", DEFAULT);
@@ -1077,3 +1078,16 @@ col_int_nokey) VIRTUAL NOT NULL,
10771078
/*!50100 PARTITION BY KEY (col_int_key)
10781079
PARTITIONS 3 */
10791080
DROP TABLE t;
1081+
CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10));
1082+
INSERT INTO t VALUES (11, 3, DEFAULT, "mm");
1083+
INSERT INTO t VALUES (18, 1, DEFAULT, "mm");
1084+
INSERT INTO t VALUES (28, 1, DEFAULT, "mm");
1085+
INSERT INTO t VALUES (null, null, DEFAULT, "mm");
1086+
ALTER TABLE t ADD COLUMN xs INT GENERATED ALWAYS AS(a+b), ADD COLUMN mm INT
1087+
GENERATED ALWAYS AS(a+b) STORED, ALGORITHM = INPLACE;
1088+
ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY.
1089+
ALTER TABLE t ADD COLUMN x INT GENERATED ALWAYS AS(a+b), ALGORITHM = INPLACE;
1090+
ALTER TABLE t DROP COLUMN x, ALGORITHM = INPLACE;
1091+
ALTER TABLE t ADD COLUMN x1 INT GENERATED ALWAYS AS(a+b), DROP COLUMN c,
1092+
ALGORITHM = INPLACE;
1093+
DROP TABLE t;

mysql-test/suite/innodb/t/innodb_v_basic.test

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -193,16 +193,18 @@ SELECT pos, base_pos FROM informatiON_schema.innodb_sys_virtual;
193193
DROP TABLE t1;
194194

195195
CREATE TABLE t1(a INT);
196+
INSERT INTO t1 VALUES(1);
196197

197-
--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN
198198
ALTER TABLE t1 add COLUMN (f INT generated always as (a+1) virtual, g INT );
199199

200-
# Inplace add/DROP virtual COLUMNs can ONly go with their own, not to combine
200+
# Inplace ADD/DROP virtual COLUMNs can only go with their own, not to combine
201201
# with other operatiONs
202202
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
203-
ALTER TABLE t1 add COLUMN (f INT generated always as (a+1) virtual), add INDEX idx (f), algorithm=inplace;
203+
ALTER TABLE t1 add COLUMN (h INT generated always as (a+1) virtual), add INDEX idx (h), algorithm=inplace;
204204

205-
ALTER TABLE t1 add COLUMN (f INT generated always as (a+1) virtual), add INDEX idx (f), algorithm=copy;
205+
--enable_info
206+
ALTER TABLE t1 add COLUMN (h INT generated always as (a+1) virtual), add INDEX idx (h);
207+
--disable_info
206208

207209
DROP TABLE t1;
208210

@@ -607,8 +609,7 @@ INSERT INTO t VALUES(11, 22, DEFAULT, "AAA", 8, DEFAULT, "XXX", DEFAULT);
607609
INSERT INTO t VALUES(1, 2, DEFAULT, "uuu", 9, DEFAULT, "uu", DEFAULT);
608610
INSERT INTO t VALUES(3, 4, DEFAULT, "uooo", 1, DEFAULT, "umm", DEFAULT);
609611

610-
--error ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN
611-
alter table t add x int, add m int generated ALWAYS AS(x);
612+
alter table t add x int, add xx int generated ALWAYS AS(x);
612613

613614
DROP TABLE t;
614615

@@ -933,3 +934,24 @@ ALTER TABLE t DROP COLUMN `pk`;
933934
SHOW CREATE TABLE t;
934935

935936
DROP TABLE t;
937+
938+
CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10));
939+
940+
INSERT INTO t VALUES (11, 3, DEFAULT, "mm");
941+
INSERT INTO t VALUES (18, 1, DEFAULT, "mm");
942+
INSERT INTO t VALUES (28, 1, DEFAULT, "mm");
943+
INSERT INTO t VALUES (null, null, DEFAULT, "mm");
944+
945+
--error ER_ALTER_OPERATION_NOT_SUPPORTED
946+
ALTER TABLE t ADD COLUMN xs INT GENERATED ALWAYS AS(a+b), ADD COLUMN mm INT
947+
GENERATED ALWAYS AS(a+b) STORED, ALGORITHM = INPLACE;
948+
949+
ALTER TABLE t ADD COLUMN x INT GENERATED ALWAYS AS(a+b), ALGORITHM = INPLACE;
950+
951+
ALTER TABLE t DROP COLUMN x, ALGORITHM = INPLACE;
952+
953+
ALTER TABLE t ADD COLUMN x1 INT GENERATED ALWAYS AS(a+b), DROP COLUMN c,
954+
ALGORITHM = INPLACE;
955+
956+
DROP TABLE t;
957+

sql/field.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4318,6 +4318,8 @@ class Create_field :public Sql_alloc
43184318
/* Used to make a clone of this object for ALTER/CREATE TABLE */
43194319
Create_field *clone(MEM_ROOT *mem_root) const
43204320
{ return new (mem_root) Create_field(*this); }
4321+
bool is_virtual_gcol() const
4322+
{ return gcol_info && !gcol_info->get_field_stored(); }
43214323
void create_length_to_internal_length(void);
43224324

43234325
/* Init for a tmp table field. To be extended if need be. */

sql/handler.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4637,7 +4637,6 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
46374637
Alter_inplace_info::CHANGE_CREATE_OPTION |
46384638
Alter_inplace_info::ALTER_RENAME |
46394639
Alter_inplace_info::RENAME_INDEX |
4640-
Alter_inplace_info::HA_ALTER_STORED_GCOL |
46414640
Alter_inplace_info::ALTER_INDEX_COMMENT;
46424641

46434642
/* Is there at least one operation that requires copy algorithm? */

0 commit comments

Comments
 (0)