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 00000000000..558bb23de0a --- /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 00000000000..368c6fc8cb1 --- /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 7c3c4e824d5..c87ecfe8fa6 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. +@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 fde94a15a28..e86949198f8 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 76d68bb9676..3f393d9d431 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( 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 @@ created_clustered: /* 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 @@ created_clustered: 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 @@ created_clustered: index->fields = static_cast( 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 d2514ea78b6..9e007809471 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. +@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 2b9e9f7711c..de353d46202 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 1c8b65a5696..806f5b977d4 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 6b628198275..cd0f3ef57d1 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. +@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 aaeebf91e24..88ecb584475 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 bb58a92ed1a..b3a41ae70da 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( 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 @@ created_clustered: /* 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 @@ created_clustered: 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 @@ created_clustered: index->fields = static_cast( 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 88203595108..def7b246ead 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. +@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 390c0ce038b..57b93b307cd 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 5d88d750478..ecbea7fcb87 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); }