001/*-
002 * #%L
003 * HAPI FHIR Server - SQL Migration
004 * %%
005 * Copyright (C) 2014 - 2023 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.migrate.taskdef;
021
022import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
023import ca.uhn.fhir.jpa.migrate.JdbcUtils;
024import org.intellij.lang.annotations.Language;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028import java.sql.SQLException;
029import java.util.List;
030import java.util.Set;
031
032public class DropColumnTask extends BaseTableColumnTask {
033
034        private static final Logger ourLog = LoggerFactory.getLogger(DropColumnTask.class);
035
036        /**
037         * Constructor
038         */
039        public DropColumnTask(String theProductVersion, String theSchemaVersion) {
040                super(theProductVersion, theSchemaVersion);
041        }
042
043        @Language("SQL")
044        static String createSql(String theTableName, String theColumnName) {
045                return "alter table " + theTableName + " drop column " + theColumnName;
046        }
047
048        @Override
049        public void validate() {
050                super.validate();
051                setDescription("Drop column " + getColumnName() + " from table " + getTableName());
052        }
053
054        @Override
055        public void doExecute() throws SQLException {
056                Set<String> columnNames = JdbcUtils.getColumnNames(getConnectionProperties(), getTableName());
057                if (!columnNames.contains(getColumnName())) {
058                        logInfo(ourLog, "Column {} does not exist on table {} - No action performed", getColumnName(), getTableName());
059                        return;
060                }
061
062                if (getDriverType().equals(DriverTypeEnum.MYSQL_5_7) || getDriverType().equals(DriverTypeEnum.MARIADB_10_1)
063                        || getDriverType().equals(DriverTypeEnum.MSSQL_2012)) {
064                        // Some DBs such as MYSQL and Maria DB require that foreign keys depending on the column be dropped before the column itself is dropped.
065                        logInfo(ourLog, "Dropping any foreign keys on table {} depending on column {}", getTableName(), getColumnName());
066                        Set<String> foreignKeys = JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), getColumnName(), getTableName());
067                        if (foreignKeys != null) {
068                                for (String foreignKey : foreignKeys) {
069                                        List<String> dropFkSqls = DropForeignKeyTask.generateSql(getTableName(), foreignKey, getDriverType());
070                                        for (String dropFkSql : dropFkSqls) {
071                                                executeSql(getTableName(), dropFkSql);
072                                        }
073                                }
074                        }
075                }
076
077                String tableName = getTableName();
078                String columnName = getColumnName();
079                String sql = createSql(tableName, columnName);
080                logInfo(ourLog, "Dropping column {} on table {}", getColumnName(), getTableName());
081                executeSql(getTableName(), sql);
082        }
083
084
085}