001/*- 002 * #%L 003 * HAPI FHIR Server - SQL Migration 004 * %% 005 * Copyright (C) 2014 - 2026 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.i18n.Msg; 023import ca.uhn.fhir.jpa.migrate.DriverTypeEnum; 024import ca.uhn.fhir.jpa.migrate.JdbcUtils; 025import jakarta.annotation.Nonnull; 026import org.apache.commons.lang3.Validate; 027import org.apache.commons.lang3.builder.EqualsBuilder; 028import org.apache.commons.lang3.builder.HashCodeBuilder; 029import org.intellij.lang.annotations.Language; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032 033import java.sql.Connection; 034import java.sql.SQLException; 035import java.util.ArrayList; 036import java.util.List; 037import java.util.Locale; 038import java.util.Set; 039 040import static org.apache.commons.lang3.StringUtils.isNotBlank; 041 042public class DropForeignKeyTask extends BaseTableTask { 043 044 private static final Logger ourLog = LoggerFactory.getLogger(DropForeignKeyTask.class); 045 private String myConstraintName; 046 private String myParentTableName; 047 048 public DropForeignKeyTask(String theProductVersion, String theSchemaVersion) { 049 super(theProductVersion, theSchemaVersion); 050 } 051 052 @Nonnull 053 static List<String> generateSql(String theTableName, String theConstraintName, DriverTypeEnum theDriverType) { 054 List<String> sqls = new ArrayList<>(); 055 switch (theDriverType) { 056 case MYSQL_5_7: 057 case MARIADB_10_1: 058 // Lousy MYQL.... 059 sqls.add("alter table " + theTableName + " drop foreign key " + theConstraintName); 060 break; 061 case POSTGRES_9_4: 062 case DERBY_EMBEDDED: 063 case H2_EMBEDDED: 064 case ORACLE_12C: 065 case MSSQL_2012: 066 sqls.add("alter table " + theTableName + " drop constraint " + theConstraintName); 067 break; 068 case COCKROACHDB_21_1: 069 sqls.add("drop index if exists " + theTableName + "@" + theConstraintName + " cascade"); 070 break; 071 default: 072 throw new IllegalStateException(Msg.code(59)); 073 } 074 return sqls; 075 } 076 077 public void setConstraintName(String theConstraintName) { 078 myConstraintName = theConstraintName; 079 } 080 081 public void setParentTableName(String theParentTableName) { 082 myParentTableName = theParentTableName; 083 } 084 085 @Override 086 public void validate() { 087 super.validate(); 088 089 Validate.isTrue(isNotBlank(myConstraintName)); 090 Validate.isTrue(isNotBlank(myParentTableName)); 091 setDescription("Drop foreign key " + myConstraintName + " from table " + getTableName()); 092 } 093 094 @Override 095 public void doExecute() throws SQLException { 096 097 Set<String> existing = JdbcUtils.getForeignKeys(getConnectionProperties(), myParentTableName, getTableName()); 098 if (!existing.contains(myConstraintName.toUpperCase(Locale.US))) { 099 logInfo(ourLog, "Don't have constraint named {} - No action performed", myConstraintName); 100 return; 101 } 102 103 List<String> sqlStatements; 104 try (Connection connection = getConnectionProperties().getDataSource().getConnection()) { 105 String constraintName = JdbcUtils.massageIdentifier(connection.getMetaData(), myConstraintName); 106 sqlStatements = generateSql(getTableName(), constraintName, getDriverType()); 107 } 108 109 for (@Language("SQL") String next : sqlStatements) { 110 executeSql(getTableName(), next); 111 } 112 } 113 114 @Override 115 protected void generateEquals(EqualsBuilder theBuilder, BaseTask theOtherObject) { 116 DropForeignKeyTask otherObject = (DropForeignKeyTask) theOtherObject; 117 super.generateEquals(theBuilder, otherObject); 118 theBuilder.append(myConstraintName, otherObject.myConstraintName); 119 theBuilder.append(myParentTableName, otherObject.myParentTableName); 120 } 121 122 @Override 123 protected void generateHashCode(HashCodeBuilder theBuilder) { 124 super.generateHashCode(theBuilder); 125 theBuilder.append(myConstraintName); 126 theBuilder.append(myParentTableName); 127 } 128}