001package ca.uhn.fhir.jpa.migrate.taskdef;
002
003/*-
004 * #%L
005 * HAPI FHIR Server - SQL Migration
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.i18n.Msg;
024import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
025import ca.uhn.fhir.jpa.migrate.JdbcUtils;
026import org.apache.commons.lang3.Validate;
027import org.apache.commons.lang3.builder.EqualsBuilder;
028import org.apache.commons.lang3.builder.HashCodeBuilder;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031
032import javax.annotation.Nonnull;
033import java.sql.SQLException;
034import java.util.ArrayList;
035import java.util.List;
036import java.util.Set;
037
038import static org.apache.commons.lang3.StringUtils.isNotBlank;
039
040public class DropForeignKeyTask extends BaseTableTask {
041
042        private static final Logger ourLog = LoggerFactory.getLogger(DropForeignKeyTask.class);
043        private String myConstraintName;
044        private String myParentTableName;
045
046        public DropForeignKeyTask(String theProductVersion, String theSchemaVersion) {
047                super(theProductVersion, theSchemaVersion);
048        }
049
050        @Nonnull
051        static List<String> generateSql(String theTableName, String theConstraintName, DriverTypeEnum theDriverType) {
052                List<String> sqls = new ArrayList<>();
053                switch (theDriverType) {
054                        case MYSQL_5_7:
055                        case MARIADB_10_1:
056                                // Lousy MYQL....
057                                sqls.add("alter table " + theTableName + " drop foreign key " + theConstraintName);
058                                break;
059                        case POSTGRES_9_4:
060                        case DERBY_EMBEDDED:
061                        case H2_EMBEDDED:
062                        case ORACLE_12C:
063                        case MSSQL_2012:
064                                sqls.add("alter table " + theTableName + " drop constraint " + theConstraintName);
065                                break;
066                        case COCKROACHDB_21_1:
067                                sqls.add("drop index if exists " + theTableName + "@" + theConstraintName + " cascade");
068                                break;
069                        default:
070                                throw new IllegalStateException(Msg.code(59));
071                }
072                return sqls;
073        }
074
075        public void setConstraintName(String theConstraintName) {
076                myConstraintName = theConstraintName;
077        }
078
079        public void setParentTableName(String theParentTableName) {
080                myParentTableName = theParentTableName;
081        }
082
083        @Override
084        public void validate() {
085                super.validate();
086
087                Validate.isTrue(isNotBlank(myConstraintName));
088                Validate.isTrue(isNotBlank(myParentTableName));
089                setDescription("Drop foreign key " + myConstraintName + " from table " + getTableName());
090
091        }
092
093        @Override
094        public void doExecute() throws SQLException {
095
096                Set<String> existing = JdbcUtils.getForeignKeys(getConnectionProperties(), myParentTableName, getTableName());
097                if (!existing.contains(myConstraintName)) {
098                        logInfo(ourLog, "Don't have constraint named {} - No action performed", myConstraintName);
099                        return;
100                }
101
102                List<String> sqls = generateSql(getTableName(), myConstraintName, getDriverType());
103
104                for (String next : sqls) {
105                        executeSql(getTableName(), next);
106                }
107
108        }
109
110        @Override
111        protected void generateEquals(EqualsBuilder theBuilder, BaseTask theOtherObject) {
112                DropForeignKeyTask otherObject = (DropForeignKeyTask) theOtherObject;
113                super.generateEquals(theBuilder, otherObject);
114                theBuilder.append(myConstraintName, otherObject.myConstraintName);
115                theBuilder.append(myParentTableName, otherObject.myParentTableName);
116        }
117
118        @Override
119        protected void generateHashCode(HashCodeBuilder theBuilder) {
120                super.generateHashCode(theBuilder);
121                theBuilder.append(myConstraintName);
122                theBuilder.append(myParentTableName);
123        }
124}