[Commits] 041d32c: MDEV-7367: Updating a virtual column corrupts table which crashes server

Jan Lindström jan.lindstrom at mariadb.com
Mon Mar 30 18:56:01 EEST 2015


revision-id: 041d32c0dc2d1fa6555cc2d37e8f4311c4be5ee0
parent(s): b311b85ebd7355434ec4d276313ffc82ebd0f4bc
committer: Jan Lindström
branch nick: 10.0-git
timestamp: 2015-03-30 18:53:10 +0300
message:

MDEV-7367: Updating a virtual column corrupts table which crashes server

Analysis: MySQL table definition contains also virtual columns. Similarly,
index fielnr references MySQL table fields. However, InnoDB table definition
does not contain virtual columns. Therefore, when matching MySQL key fieldnr
we need to use actual column name to find out referenced InnoDB dictionary
column name.

Fix: Add new function to match MySQL index key columns to InnoDB dictionary.

---
 .../suite/innodb/r/innodb-virtual-columns.result   | 322 +++++++++++++++++++++
 .../suite/innodb/t/innodb-virtual-columns.test     | 302 +++++++++++++++++++
 storage/innobase/dict/dict0dict.cc                 |  34 +++
 storage/innobase/handler/ha_innodb.cc              |   2 +
 storage/innobase/handler/handler0alter.cc          |  17 +-
 storage/innobase/include/dict0dict.h               |  11 +
 storage/innobase/include/row0merge.h               |   1 +
 storage/innobase/row/row0merge.cc                  |   6 +-
 storage/xtradb/dict/dict0dict.cc                   |  34 +++
 storage/xtradb/handler/ha_innodb.cc                |   2 +
 storage/xtradb/handler/handler0alter.cc            |  18 +-
 storage/xtradb/include/dict0dict.h                 |  11 +
 storage/xtradb/include/row0merge.h                 |   1 +
 storage/xtradb/row/row0merge.cc                    |   6 +-
 14 files changed, 753 insertions(+), 14 deletions(-)

diff --git a/mysql-test/suite/innodb/r/innodb-virtual-columns.result b/mysql-test/suite/innodb/r/innodb-virtual-columns.result
new file mode 100644
index 0000000..558bb23
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb-virtual-columns.result
@@ -0,0 +1,322 @@
+CREATE TABLE IF NOT EXISTS gso_grad_supr (
+term char(4) NOT NULL DEFAULT '',
+uw_id int(8) UNSIGNED NOT NULL DEFAULT 0,
+plan varchar(10) NOT NULL DEFAULT '',
+wdraw_rsn varchar(4) NOT NULL DEFAULT '',
+admit_term char(4) NOT NULL DEFAULT '',
+CONSTRAINT gso_grad_supr_pky PRIMARY KEY (uw_id, term) 
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+INSERT INTO `gso_grad_supr` VALUES ('1031',2,'CSM','','1009');
+INSERT INTO `gso_grad_supr` VALUES ('1035',2,'CSM','ACAD','1009');
+CREATE TABLE IF NOT EXISTS grad_degree (
+student_id int(8) UNSIGNED NOT NULL,
+plan varchar(10) NOT NULL,
+admit_term char(4) NOT NULL,
+wdraw_rsn varchar(4) NOT NULL DEFAULT '',
+ofis_deg_status varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed'
+      ELSE 'Not Completed'
+    END) VIRTUAL,
+deg_start_term char(4) NOT NULL DEFAULT '' COMMENT 'Educated guess at the beginning of the data', 
+deg_as_of_term char(4) NOT NULL COMMENT 'In most cases also end term', 
+CONSTRAINT grad_degree_stu_plan_admit_pky PRIMARY KEY (student_id, plan, admit_term)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE INDEX grad_degree_wdraw_rsn_ndx ON grad_degree (wdraw_rsn);
+CREATE INDEX grad_degree_as_of_term_ndx ON grad_degree (deg_as_of_term);
+INSERT IGNORE grad_degree (
+student_id,
+plan,
+admit_term, 
+wdraw_rsn,
+deg_start_term, 
+deg_as_of_term
+)
+SELECT 
+ggs.uw_id AS c_student_id,
+ggs.plan,
+ggs.admit_term,
+ggs.wdraw_rsn,
+IF( (SELECT COUNT(*) FROM grad_degree AS gd WHERE gd.student_id = ggs.uw_id AND gd.admit_term = ggs.admit_term) > 0, ggs.term, ggs.admit_term ) AS c_deg_start_term, 
+ggs.term AS c_as_of_term 
+FROM gso_grad_supr AS ggs
+LEFT OUTER JOIN
+grad_degree AS gd
+ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+WHERE
+ggs.term = 1031 AND 
+gd.student_id IS NULL
+;
+UPDATE grad_degree AS gd 
+INNER JOIN
+gso_grad_supr AS ggs 
+ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+SET 
+gd.wdraw_rsn = ggs.wdraw_rsn,
+gd.deg_as_of_term = 1035 
+WHERE
+gd.wdraw_rsn NOT IN ('DCMP', 'TRDC') AND 
+ggs.term = 1035 
+;
+drop table grad_degree;
+CREATE TABLE IF NOT EXISTS grad_degree (
+student_id int(8) UNSIGNED NOT NULL,
+plan varchar(10) NOT NULL,
+admit_term char(4) NOT NULL,
+wdraw_rsn varchar(4) NOT NULL DEFAULT '',
+ofis_deg_status varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed'
+      ELSE 'Not Completed'
+    END) VIRTUAL,
+ofis_deg_status2 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress2'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed2'
+      ELSE 'Not Completed2'
+    END) VIRTUAL,
+ofis_deg_status3 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress3'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed3'
+      ELSE 'Not Completed3'
+    END) VIRTUAL,
+ofis_deg_status4 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress4'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed4'
+      ELSE 'Not Completed4'
+    END) VIRTUAL,
+ofis_deg_status5 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress5'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed5'
+      ELSE 'Not Completed5'
+    END) VIRTUAL,
+ofis_deg_status6 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress6'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed6'
+      ELSE 'Not Completed6'
+    END) VIRTUAL,
+ofis_deg_status7 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress7'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed7'
+      ELSE 'Not Completed7'
+    END) VIRTUAL,
+ofis_deg_status8 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress8'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed8'
+      ELSE 'Not Completed8'
+    END) VIRTUAL,
+deg_start_term char(4) NOT NULL DEFAULT '' COMMENT 'Educated guess at the beginning of the data', 
+deg_as_of_term char(4) NOT NULL COMMENT 'In most cases also end term', 
+CONSTRAINT grad_degree_stu_plan_admit_pky PRIMARY KEY (student_id, plan, admit_term)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE INDEX grad_degree_wdraw_rsn_ndx ON grad_degree (wdraw_rsn);
+CREATE INDEX grad_degree_as_of_term_ndx ON grad_degree (deg_as_of_term);
+INSERT IGNORE grad_degree (
+student_id,
+plan,
+admit_term, 
+wdraw_rsn,
+deg_start_term, 
+deg_as_of_term
+)
+SELECT 
+ggs.uw_id AS c_student_id,
+ggs.plan,
+ggs.admit_term,
+ggs.wdraw_rsn,
+IF( (SELECT COUNT(*) FROM grad_degree AS gd WHERE gd.student_id = ggs.uw_id AND gd.admit_term = ggs.admit_term) > 0, ggs.term, ggs.admit_term ) AS c_deg_start_term, 
+ggs.term AS c_as_of_term 
+FROM gso_grad_supr AS ggs
+LEFT OUTER JOIN
+grad_degree AS gd
+ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+WHERE
+ggs.term = 1031 AND 
+gd.student_id IS NULL
+;
+UPDATE grad_degree AS gd 
+INNER JOIN
+gso_grad_supr AS ggs 
+ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+SET 
+gd.wdraw_rsn = ggs.wdraw_rsn,
+gd.deg_as_of_term = 1035 
+WHERE
+gd.wdraw_rsn NOT IN ('DCMP', 'TRDC') AND 
+ggs.term = 1035 
+;
+ALTER TABLE grad_degree DROP INDEX grad_degree_wdraw_rsn_ndx;
+ALTER TABLE grad_degree DROP COLUMN deg_start_term;
+SHOW CREATE TABLE grad_degree;
+Table	Create Table
+grad_degree	CREATE TABLE `grad_degree` (
+  `student_id` int(8) unsigned NOT NULL,
+  `plan` varchar(10) NOT NULL,
+  `admit_term` char(4) NOT NULL,
+  `wdraw_rsn` varchar(4) NOT NULL DEFAULT '',
+  `ofis_deg_status` varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed'
+      ELSE 'Not Completed'
+    END) VIRTUAL,
+  `ofis_deg_status2` varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress2'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed2'
+      ELSE 'Not Completed2'
+    END) VIRTUAL,
+  `ofis_deg_status3` varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress3'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed3'
+      ELSE 'Not Completed3'
+    END) VIRTUAL,
+  `ofis_deg_status4` varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress4'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed4'
+      ELSE 'Not Completed4'
+    END) VIRTUAL,
+  `ofis_deg_status5` varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress5'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed5'
+      ELSE 'Not Completed5'
+    END) VIRTUAL,
+  `ofis_deg_status6` varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress6'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed6'
+      ELSE 'Not Completed6'
+    END) VIRTUAL,
+  `ofis_deg_status7` varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress7'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed7'
+      ELSE 'Not Completed7'
+    END) VIRTUAL,
+  `ofis_deg_status8` varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress8'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed8'
+      ELSE 'Not Completed8'
+    END) VIRTUAL,
+  `deg_as_of_term` char(4) NOT NULL COMMENT 'In most cases also end term',
+  PRIMARY KEY (`student_id`,`plan`,`admit_term`),
+  KEY `grad_degree_as_of_term_ndx` (`deg_as_of_term`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
+DROP TABLE grad_degree;
+CREATE TABLE IF NOT EXISTS grad_degree (
+student_id int(8) UNSIGNED NOT NULL,
+plan varchar(10) NOT NULL,
+admit_term char(4) NOT NULL,
+wdraw_rsn varchar(4) NOT NULL DEFAULT '',
+ofis_deg_status varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed'
+      ELSE 'Not Completed'
+    END) VIRTUAL,
+ofis_deg_status2 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress2'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed2'
+      ELSE 'Not Completed2'
+    END) VIRTUAL,
+ofis_deg_status3 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress3'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed3'
+      ELSE 'Not Completed3'
+    END) VIRTUAL,
+ofis_deg_status4 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress4'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed4'
+      ELSE 'Not Completed4'
+    END) VIRTUAL,
+ofis_deg_status5 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress5'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed5'
+      ELSE 'Not Completed5'
+    END) VIRTUAL,
+ofis_deg_status6 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress6'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed6'
+      ELSE 'Not Completed6'
+    END) VIRTUAL,
+ofis_deg_status7 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress7'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed7'
+      ELSE 'Not Completed7'
+    END) VIRTUAL,
+ofis_deg_status8 varchar(15) AS (
+CASE
+WHEN wdraw_rsn = '' THEN 'In progress8'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed8'
+      ELSE 'Not Completed8'
+    END) VIRTUAL,
+deg_start_term char(4) NOT NULL DEFAULT '' COMMENT 'Educated guess at the beginning of the data', 
+deg_as_of_term char(4) NOT NULL COMMENT 'In most cases also end term', 
+CONSTRAINT grad_degree_stu_plan_admit_pky PRIMARY KEY (student_id, plan, admit_term)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE INDEX grad_degree_wdraw_rsn_ndx ON grad_degree (wdraw_rsn);
+ALTER TABLE grad_degree DROP COLUMN ofis_deg_status2, DROP COLUMN ofis_deg_status3,
+DROP COLUMN ofis_deg_status4, DROP COLUMN ofis_deg_status5, DROP COLUMN ofis_deg_status6,
+DROP COLUMN ofis_deg_status7, DROP COLUMN ofis_deg_status8;
+CREATE INDEX grad_degree_as_of_term_ndx ON grad_degree (deg_as_of_term);
+INSERT IGNORE grad_degree (
+student_id,
+plan,
+admit_term, 
+wdraw_rsn,
+deg_start_term, 
+deg_as_of_term
+)
+SELECT 
+ggs.uw_id AS c_student_id,
+ggs.plan,
+ggs.admit_term,
+ggs.wdraw_rsn,
+IF( (SELECT COUNT(*) FROM grad_degree AS gd WHERE gd.student_id = ggs.uw_id AND gd.admit_term = ggs.admit_term) > 0, ggs.term, ggs.admit_term ) AS c_deg_start_term, 
+ggs.term AS c_as_of_term 
+FROM gso_grad_supr AS ggs
+LEFT OUTER JOIN
+grad_degree AS gd
+ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+WHERE
+ggs.term = 1031 AND 
+gd.student_id IS NULL
+;
+UPDATE grad_degree AS gd 
+INNER JOIN
+gso_grad_supr AS ggs 
+ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+SET 
+gd.wdraw_rsn = ggs.wdraw_rsn,
+gd.deg_as_of_term = 1035 
+WHERE
+gd.wdraw_rsn NOT IN ('DCMP', 'TRDC') AND 
+ggs.term = 1035 
+;
+select * from grad_degree;
+student_id	plan	admit_term	wdraw_rsn	ofis_deg_status	deg_start_term	deg_as_of_term
+2	CSM	1009	ACAD	Not Completed	1009	1035
+select * from gso_grad_supr;
+term	uw_id	plan	wdraw_rsn	admit_term
+1031	2	CSM		1009
+1035	2	CSM	ACAD	1009
+drop table grad_degree;
+drop table gso_grad_supr;
diff --git a/mysql-test/suite/innodb/t/innodb-virtual-columns.test b/mysql-test/suite/innodb/t/innodb-virtual-columns.test
new file mode 100644
index 0000000..368c6fc
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-virtual-columns.test
@@ -0,0 +1,302 @@
+--source include/have_innodb.inc
+
+#
+# MDEV-7367: Updating a virtual column corrupts table which crashes server
+#   MySQL table columns contains virtual columns but InnoDB table 
+#   definition does not.
+#
+CREATE TABLE IF NOT EXISTS gso_grad_supr (
+  term char(4) NOT NULL DEFAULT '',
+  uw_id int(8) UNSIGNED NOT NULL DEFAULT 0,
+  plan varchar(10) NOT NULL DEFAULT '',
+  wdraw_rsn varchar(4) NOT NULL DEFAULT '',
+  admit_term char(4) NOT NULL DEFAULT '',
+  CONSTRAINT gso_grad_supr_pky PRIMARY KEY (uw_id, term) 
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `gso_grad_supr` VALUES ('1031',2,'CSM','','1009');
+INSERT INTO `gso_grad_supr` VALUES ('1035',2,'CSM','ACAD','1009');
+
+CREATE TABLE IF NOT EXISTS grad_degree (
+  student_id int(8) UNSIGNED NOT NULL,
+  plan varchar(10) NOT NULL,
+  admit_term char(4) NOT NULL,
+  wdraw_rsn varchar(4) NOT NULL DEFAULT '',
+  ofis_deg_status varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed'
+      ELSE 'Not Completed'
+    END) VIRTUAL,
+  deg_start_term char(4) NOT NULL DEFAULT '' COMMENT 'Educated guess at the beginning of the data', 
+  deg_as_of_term char(4) NOT NULL COMMENT 'In most cases also end term', 
+  CONSTRAINT grad_degree_stu_plan_admit_pky PRIMARY KEY (student_id, plan, admit_term)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE INDEX grad_degree_wdraw_rsn_ndx ON grad_degree (wdraw_rsn);
+CREATE INDEX grad_degree_as_of_term_ndx ON grad_degree (deg_as_of_term);
+
+INSERT IGNORE grad_degree (
+  student_id,
+  plan,
+  admit_term, 
+  wdraw_rsn,
+  deg_start_term, 
+  deg_as_of_term
+)
+SELECT 
+  ggs.uw_id AS c_student_id,
+  ggs.plan,
+  ggs.admit_term,
+  ggs.wdraw_rsn,
+  IF( (SELECT COUNT(*) FROM grad_degree AS gd WHERE gd.student_id = ggs.uw_id AND gd.admit_term = ggs.admit_term) > 0, ggs.term, ggs.admit_term ) AS c_deg_start_term, 
+  ggs.term AS c_as_of_term 
+FROM gso_grad_supr AS ggs
+LEFT OUTER JOIN
+  grad_degree AS gd
+    ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+WHERE
+  ggs.term = 1031 AND 
+  gd.student_id IS NULL
+;
+
+UPDATE grad_degree AS gd 
+INNER JOIN
+  gso_grad_supr AS ggs 
+    ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+SET 
+  gd.wdraw_rsn = ggs.wdraw_rsn,
+  gd.deg_as_of_term = 1035 
+WHERE
+  gd.wdraw_rsn NOT IN ('DCMP', 'TRDC') AND 
+    ggs.term = 1035 
+;
+
+drop table grad_degree;
+
+#
+# Test with more virtual columns so that MySQL table has
+# more columns than InnoDB and index definition is out
+# of number of actual InnoDB columns.
+#
+CREATE TABLE IF NOT EXISTS grad_degree (
+  student_id int(8) UNSIGNED NOT NULL,
+  plan varchar(10) NOT NULL,
+  admit_term char(4) NOT NULL,
+  wdraw_rsn varchar(4) NOT NULL DEFAULT '',
+  ofis_deg_status varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed'
+      ELSE 'Not Completed'
+    END) VIRTUAL,
+  ofis_deg_status2 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress2'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed2'
+      ELSE 'Not Completed2'
+    END) VIRTUAL,
+  ofis_deg_status3 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress3'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed3'
+      ELSE 'Not Completed3'
+    END) VIRTUAL,
+  ofis_deg_status4 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress4'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed4'
+      ELSE 'Not Completed4'
+    END) VIRTUAL,
+  ofis_deg_status5 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress5'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed5'
+      ELSE 'Not Completed5'
+    END) VIRTUAL,
+  ofis_deg_status6 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress6'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed6'
+      ELSE 'Not Completed6'
+    END) VIRTUAL,
+  ofis_deg_status7 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress7'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed7'
+      ELSE 'Not Completed7'
+    END) VIRTUAL,
+  ofis_deg_status8 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress8'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed8'
+      ELSE 'Not Completed8'
+    END) VIRTUAL,
+  deg_start_term char(4) NOT NULL DEFAULT '' COMMENT 'Educated guess at the beginning of the data', 
+  deg_as_of_term char(4) NOT NULL COMMENT 'In most cases also end term', 
+  CONSTRAINT grad_degree_stu_plan_admit_pky PRIMARY KEY (student_id, plan, admit_term)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE INDEX grad_degree_wdraw_rsn_ndx ON grad_degree (wdraw_rsn);
+CREATE INDEX grad_degree_as_of_term_ndx ON grad_degree (deg_as_of_term);
+
+INSERT IGNORE grad_degree (
+  student_id,
+  plan,
+  admit_term, 
+  wdraw_rsn,
+  deg_start_term, 
+  deg_as_of_term
+)
+SELECT 
+  ggs.uw_id AS c_student_id,
+  ggs.plan,
+  ggs.admit_term,
+  ggs.wdraw_rsn,
+  IF( (SELECT COUNT(*) FROM grad_degree AS gd WHERE gd.student_id = ggs.uw_id AND gd.admit_term = ggs.admit_term) > 0, ggs.term, ggs.admit_term ) AS c_deg_start_term, 
+  ggs.term AS c_as_of_term 
+FROM gso_grad_supr AS ggs
+LEFT OUTER JOIN
+  grad_degree AS gd
+    ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+WHERE
+  ggs.term = 1031 AND 
+  gd.student_id IS NULL
+;
+
+UPDATE grad_degree AS gd 
+INNER JOIN
+  gso_grad_supr AS ggs 
+    ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+SET 
+  gd.wdraw_rsn = ggs.wdraw_rsn,
+  gd.deg_as_of_term = 1035 
+WHERE
+  gd.wdraw_rsn NOT IN ('DCMP', 'TRDC') AND 
+    ggs.term = 1035 
+;
+
+#
+# Verify that indexes can be dropped
+#
+ALTER TABLE grad_degree DROP INDEX grad_degree_wdraw_rsn_ndx;
+
+#
+# Verify that we can drop columns
+#
+ALTER TABLE grad_degree DROP COLUMN deg_start_term;
+
+SHOW CREATE TABLE grad_degree;
+
+DROP TABLE grad_degree;
+
+#
+# Verify after dropping virtual columns
+#
+CREATE TABLE IF NOT EXISTS grad_degree (
+  student_id int(8) UNSIGNED NOT NULL,
+  plan varchar(10) NOT NULL,
+  admit_term char(4) NOT NULL,
+  wdraw_rsn varchar(4) NOT NULL DEFAULT '',
+  ofis_deg_status varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed'
+      ELSE 'Not Completed'
+    END) VIRTUAL,
+  ofis_deg_status2 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress2'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed2'
+      ELSE 'Not Completed2'
+    END) VIRTUAL,
+  ofis_deg_status3 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress3'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed3'
+      ELSE 'Not Completed3'
+    END) VIRTUAL,
+  ofis_deg_status4 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress4'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed4'
+      ELSE 'Not Completed4'
+    END) VIRTUAL,
+  ofis_deg_status5 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress5'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed5'
+      ELSE 'Not Completed5'
+    END) VIRTUAL,
+  ofis_deg_status6 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress6'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed6'
+      ELSE 'Not Completed6'
+    END) VIRTUAL,
+  ofis_deg_status7 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress7'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed7'
+      ELSE 'Not Completed7'
+    END) VIRTUAL,
+  ofis_deg_status8 varchar(15) AS (
+    CASE
+      WHEN wdraw_rsn = '' THEN 'In progress8'
+      WHEN wdraw_rsn = 'DCMP' OR wdraw_rsn = 'TRDC' THEN 'Completed8'
+      ELSE 'Not Completed8'
+    END) VIRTUAL,
+  deg_start_term char(4) NOT NULL DEFAULT '' COMMENT 'Educated guess at the beginning of the data', 
+  deg_as_of_term char(4) NOT NULL COMMENT 'In most cases also end term', 
+  CONSTRAINT grad_degree_stu_plan_admit_pky PRIMARY KEY (student_id, plan, admit_term)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE INDEX grad_degree_wdraw_rsn_ndx ON grad_degree (wdraw_rsn);
+
+ALTER TABLE grad_degree DROP COLUMN ofis_deg_status2, DROP COLUMN ofis_deg_status3,
+DROP COLUMN ofis_deg_status4, DROP COLUMN ofis_deg_status5, DROP COLUMN ofis_deg_status6,
+DROP COLUMN ofis_deg_status7, DROP COLUMN ofis_deg_status8;
+
+CREATE INDEX grad_degree_as_of_term_ndx ON grad_degree (deg_as_of_term);
+
+INSERT IGNORE grad_degree (
+  student_id,
+  plan,
+  admit_term, 
+  wdraw_rsn,
+  deg_start_term, 
+  deg_as_of_term
+)
+SELECT 
+  ggs.uw_id AS c_student_id,
+  ggs.plan,
+  ggs.admit_term,
+  ggs.wdraw_rsn,
+  IF( (SELECT COUNT(*) FROM grad_degree AS gd WHERE gd.student_id = ggs.uw_id AND gd.admit_term = ggs.admit_term) > 0, ggs.term, ggs.admit_term ) AS c_deg_start_term, 
+  ggs.term AS c_as_of_term 
+FROM gso_grad_supr AS ggs
+LEFT OUTER JOIN
+  grad_degree AS gd
+    ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+WHERE
+  ggs.term = 1031 AND 
+  gd.student_id IS NULL
+;
+
+UPDATE grad_degree AS gd 
+INNER JOIN
+  gso_grad_supr AS ggs 
+    ON ( gd.student_id = ggs.uw_id AND gd.plan = ggs.plan AND gd.admit_term = ggs.admit_term )
+SET 
+  gd.wdraw_rsn = ggs.wdraw_rsn,
+  gd.deg_as_of_term = 1035 
+WHERE
+  gd.wdraw_rsn NOT IN ('DCMP', 'TRDC') AND 
+    ggs.term = 1035 
+;
+
+select * from grad_degree;
+select * from gso_grad_supr;
+
+drop table grad_degree;
+drop table gso_grad_supr;
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index 7c3c4e8..c87ecfe 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -648,6 +648,40 @@ dict_table_get_col_name(
 	return(s);
 }
 
+/**********************************************************************//**
+Returns a column's name.
+ at return column name. NOTE: not guaranteed to stay valid if table is
+modified in any way (columns added, etc.). */
+UNIV_INTERN
+const char*
+dict_table_get_col_name_for_mysql(
+/*==============================*/
+	const dict_table_t*	table,	/*!< in: table */
+	const char*		col_name)/*! in: MySQL table column name */
+{
+	ulint		i;
+	const char*	s;
+
+	ut_ad(table);
+	ut_ad(col_name);
+	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+
+	s = table->col_names;
+	if (s) {
+		/* If we have many virtual columns MySQL key_part->fieldnr
+		could be larger than number of columns in InnoDB table
+		when creating new indexes. */
+		for (i = 0; i < table->n_def; i++) {
+
+			if (!innobase_strcasecmp(s, col_name)) {
+				break; /* Found */
+			}
+			s += strlen(s) + 1;
+		}
+	}
+
+	return(s);
+}
 #ifndef UNIV_HOTBACKUP
 /********************************************************************//**
 Acquire the autoinc lock. */
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index fde94a1..e869491 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -4785,6 +4785,8 @@ innobase_match_index_columns(
 			if (innodb_idx_fld >= innodb_idx_fld_end) {
 				DBUG_RETURN(FALSE);
 			}
+
+			mtype = innodb_idx_fld->col->mtype;
 		}
 
                 // MariaDB-5.5 compatibility
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 76d68bb..3f393d9 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1441,8 +1441,9 @@ innobase_create_index_field_def(
 						if a new clustered index is
 						not being created */
 	const KEY_PART_INFO*	key_part,	/*!< in: MySQL key definition */
-	index_field_t*		index_field)	/*!< out: index field
+	index_field_t*		index_field,	/*!< out: index field
 						definition for key_part */
+	const Field**		fields)		/*!< in: MySQL table fields */
 {
 	const Field*	field;
 	ibool		is_unsigned;
@@ -1459,6 +1460,7 @@ innobase_create_index_field_def(
 	ut_a(field);
 
 	index_field->col_no = key_part->fieldnr;
+	index_field->col_name = altered_table ? field->field_name : fields[key_part->fieldnr]->field_name;
 
 	col_type = get_innobase_type_from_mysql_type(&is_unsigned, field);
 
@@ -1493,8 +1495,9 @@ innobase_create_index_def(
 	bool			key_clustered,	/*!< in: true if this is
 						the new clustered index */
 	index_def_t*		index,		/*!< out: index definition */
-	mem_heap_t*		heap)		/*!< in: heap where memory
+	mem_heap_t*		heap,		/*!< in: heap where memory
 						is allocated */
+	const Field**		fields)		/*!z in: MySQL table fields */
 {
 	const KEY*	key = &keys[key_number];
 	ulint		i;
@@ -1507,6 +1510,7 @@ innobase_create_index_def(
 
 	index->fields = static_cast<index_field_t*>(
 		mem_heap_alloc(heap, n_fields * sizeof *index->fields));
+	memset(index->fields, 0, n_fields * sizeof *index->fields);
 
 	index->ind_type = 0;
 	index->key_number = key_number;
@@ -1544,7 +1548,7 @@ innobase_create_index_def(
 
 	for (i = 0; i < n_fields; i++) {
 		innobase_create_index_field_def(
-			altered_table, &key->key_part[i], &index->fields[i]);
+			altered_table, &key->key_part[i], &index->fields[i], fields);
 	}
 
 	DBUG_VOID_RETURN;
@@ -1875,7 +1879,7 @@ innobase_create_key_defs(
 		/* Create the PRIMARY key index definition */
 		innobase_create_index_def(
 			altered_table, key_info, primary_key_number,
-			TRUE, TRUE, indexdef++, heap);
+			TRUE, TRUE, indexdef++, heap, (const Field **)altered_table->field);
 
 created_clustered:
 		n_add = 1;
@@ -1887,7 +1891,7 @@ innobase_create_key_defs(
 			/* Copy the index definitions. */
 			innobase_create_index_def(
 				altered_table, key_info, i, TRUE, FALSE,
-				indexdef, heap);
+				indexdef, heap, (const Field **)altered_table->field);
 
 			if (indexdef->ind_type & DICT_FTS) {
 				n_fts_add++;
@@ -1932,7 +1936,7 @@ innobase_create_key_defs(
 		for (ulint i = 0; i < n_add; i++) {
 			innobase_create_index_def(
 				altered_table, key_info, add[i], FALSE, FALSE,
-				indexdef, heap);
+				indexdef, heap, (const Field **)altered_table->field);
 
 			if (indexdef->ind_type & DICT_FTS) {
 				n_fts_add++;
@@ -1949,6 +1953,7 @@ innobase_create_key_defs(
 
 		index->fields = static_cast<index_field_t*>(
 			mem_heap_alloc(heap, sizeof *index->fields));
+		memset(index->fields, 0, sizeof *index->fields);
 		index->n_fields = 1;
 		index->fields->col_no = fts_doc_id_col;
 		index->fields->prefix_len = 0;
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index d2514ea..9e00780 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -597,6 +597,17 @@ dict_table_get_col_name(
 	ulint			col_nr)	/*!< in: column number */
 	__attribute__((nonnull, warn_unused_result));
 /**********************************************************************//**
+Returns a column's name.
+ at return column name. NOTE: not guaranteed to stay valid if table is
+modified in any way (columns added, etc.). */
+UNIV_INTERN
+const char*
+dict_table_get_col_name_for_mysql(
+/*==============================*/
+	const dict_table_t*	table,	/*!< in: table */
+	const char*		col_name)/*!< in: MySQL table column name */
+	__attribute__((nonnull, warn_unused_result));
+/**********************************************************************//**
 Prints a table data. */
 UNIV_INTERN
 void
diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h
index 2b9e9f7..de353d4 100644
--- a/storage/innobase/include/row0merge.h
+++ b/storage/innobase/include/row0merge.h
@@ -95,6 +95,7 @@ struct index_field_t {
 	ulint		col_no;		/*!< column offset */
 	ulint		prefix_len;	/*!< column prefix length, or 0
 					if indexing the whole column */
+	const char*	col_name;	/*!< column name or NULL */
 };
 
 /** Definition of an index being created */
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 1c8b65a..806f5b9 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -3336,9 +3336,13 @@ row_merge_create_index(
 
 	for (i = 0; i < n_fields; i++) {
 		index_field_t*	ifield = &index_def->fields[i];
+		const char * col_name = ifield->col_name ?
+			dict_table_get_col_name_for_mysql(table, ifield->col_name) :
+			dict_table_get_col_name(table, ifield->col_no);
 
 		dict_mem_index_add_field(
-			index, dict_table_get_col_name(table, ifield->col_no),
+			index,
+			col_name,
 			ifield->prefix_len);
 	}
 
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index 6b62819..cd0f3ef 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -648,6 +648,40 @@ dict_table_get_col_name(
 	return(s);
 }
 
+/**********************************************************************//**
+Returns a column's name.
+ at return column name. NOTE: not guaranteed to stay valid if table is
+modified in any way (columns added, etc.). */
+UNIV_INTERN
+const char*
+dict_table_get_col_name_for_mysql(
+/*==============================*/
+	const dict_table_t*	table,	/*!< in: table */
+	const char*		col_name)/*! in: MySQL table column name */
+{
+	ulint		i;
+	const char*	s;
+
+	ut_ad(table);
+	ut_ad(col_name);
+	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+
+	s = table->col_names;
+	if (s) {
+		/* If we have many virtual columns MySQL key_part->fieldnr
+		could be larger than number of columns in InnoDB table
+		when creating new indexes. */
+		for (i = 0; i < table->n_def; i++) {
+
+			if (!innobase_strcasecmp(s, col_name)) {
+				break; /* Found */
+			}
+			s += strlen(s) + 1;
+		}
+	}
+
+	return(s);
+}
 #ifndef UNIV_HOTBACKUP
 /********************************************************************//**
 Acquire the autoinc lock. */
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index aaeebf9..88ecb58 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -5333,6 +5333,8 @@ innobase_match_index_columns(
 			if (innodb_idx_fld >= innodb_idx_fld_end) {
 				DBUG_RETURN(FALSE);
 			}
+
+			mtype = innodb_idx_fld->col->mtype;
 		}
 
 		if (col_type != mtype) {
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index bb58a92..b3a41ae 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -1442,8 +1442,9 @@ innobase_create_index_field_def(
 						if a new clustered index is
 						not being created */
 	const KEY_PART_INFO*	key_part,	/*!< in: MySQL key definition */
-	index_field_t*		index_field)	/*!< out: index field
+	index_field_t*		index_field,	/*!< out: index field
 						definition for key_part */
+	const Field**		fields)		/*!< in: MySQL table fields */
 {
 	const Field*	field;
 	ibool		is_unsigned;
@@ -1460,6 +1461,7 @@ innobase_create_index_field_def(
 	ut_a(field);
 
 	index_field->col_no = key_part->fieldnr;
+	index_field->col_name = altered_table ? field->field_name : fields[key_part->fieldnr]->field_name;
 
 	col_type = get_innobase_type_from_mysql_type(&is_unsigned, field);
 
@@ -1494,8 +1496,9 @@ innobase_create_index_def(
 	bool			key_clustered,	/*!< in: true if this is
 						the new clustered index */
 	index_def_t*		index,		/*!< out: index definition */
-	mem_heap_t*		heap)		/*!< in: heap where memory
+	mem_heap_t*		heap,		/*!< in: heap where memory
 						is allocated */
+	const Field**		fields)		/*!z in: MySQL table fields */
 {
 	const KEY*	key = &keys[key_number];
 	ulint		i;
@@ -1509,6 +1512,8 @@ innobase_create_index_def(
 	index->fields = static_cast<index_field_t*>(
 		mem_heap_alloc(heap, n_fields * sizeof *index->fields));
 
+	memset(index->fields, 0, n_fields * sizeof *index->fields);
+
 	index->ind_type = 0;
 	index->key_number = key_number;
 	index->n_fields = n_fields;
@@ -1545,7 +1550,7 @@ innobase_create_index_def(
 
 	for (i = 0; i < n_fields; i++) {
 		innobase_create_index_field_def(
-			altered_table, &key->key_part[i], &index->fields[i]);
+			altered_table, &key->key_part[i], &index->fields[i], fields);
 	}
 
 	DBUG_VOID_RETURN;
@@ -1876,7 +1881,7 @@ innobase_create_key_defs(
 		/* Create the PRIMARY key index definition */
 		innobase_create_index_def(
 			altered_table, key_info, primary_key_number,
-			TRUE, TRUE, indexdef++, heap);
+			TRUE, TRUE, indexdef++, heap, (const Field **)altered_table->field);
 
 created_clustered:
 		n_add = 1;
@@ -1888,7 +1893,7 @@ innobase_create_key_defs(
 			/* Copy the index definitions. */
 			innobase_create_index_def(
 				altered_table, key_info, i, TRUE, FALSE,
-				indexdef, heap);
+				indexdef, heap, (const Field **)altered_table->field);
 
 			if (indexdef->ind_type & DICT_FTS) {
 				n_fts_add++;
@@ -1933,7 +1938,7 @@ innobase_create_key_defs(
 		for (ulint i = 0; i < n_add; i++) {
 			innobase_create_index_def(
 				altered_table, key_info, add[i], FALSE, FALSE,
-				indexdef, heap);
+				indexdef, heap, (const Field **)altered_table->field);
 
 			if (indexdef->ind_type & DICT_FTS) {
 				n_fts_add++;
@@ -1950,6 +1955,7 @@ innobase_create_key_defs(
 
 		index->fields = static_cast<index_field_t*>(
 			mem_heap_alloc(heap, sizeof *index->fields));
+		memset(index->fields, 0, sizeof *index->fields);
 		index->n_fields = 1;
 		index->fields->col_no = fts_doc_id_col;
 		index->fields->prefix_len = 0;
diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h
index 8820359..def7b24 100644
--- a/storage/xtradb/include/dict0dict.h
+++ b/storage/xtradb/include/dict0dict.h
@@ -597,6 +597,17 @@ dict_table_get_col_name(
 	ulint			col_nr)	/*!< in: column number */
 	__attribute__((nonnull, warn_unused_result));
 /**********************************************************************//**
+Returns a column's name.
+ at return column name. NOTE: not guaranteed to stay valid if table is
+modified in any way (columns added, etc.). */
+UNIV_INTERN
+const char*
+dict_table_get_col_name_for_mysql(
+/*==============================*/
+	const dict_table_t*	table,	/*!< in: table */
+	const char*		col_name)/*!< in: MySQL table column name */
+	__attribute__((nonnull, warn_unused_result));
+/**********************************************************************//**
 Prints a table data. */
 UNIV_INTERN
 void
diff --git a/storage/xtradb/include/row0merge.h b/storage/xtradb/include/row0merge.h
index 390c0ce..57b93b3 100644
--- a/storage/xtradb/include/row0merge.h
+++ b/storage/xtradb/include/row0merge.h
@@ -95,6 +95,7 @@ struct index_field_t {
 	ulint		col_no;		/*!< column offset */
 	ulint		prefix_len;	/*!< column prefix length, or 0
 					if indexing the whole column */
+	const char*	col_name;	/*!< column name or NULL */
 };
 
 /** Definition of an index being created */
diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc
index 5d88d75..ecbea7f 100644
--- a/storage/xtradb/row/row0merge.cc
+++ b/storage/xtradb/row/row0merge.cc
@@ -3342,9 +3342,13 @@ row_merge_create_index(
 
 	for (i = 0; i < n_fields; i++) {
 		index_field_t*	ifield = &index_def->fields[i];
+		const char * col_name = ifield->col_name ?
+			dict_table_get_col_name_for_mysql(table, ifield->col_name) :
+			dict_table_get_col_name(table, ifield->col_no);
 
 		dict_mem_index_add_field(
-			index, dict_table_get_col_name(table, ifield->col_no),
+			index,
+			col_name,
 			ifield->prefix_len);
 	}
 



More information about the commits mailing list