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.apache.commons.lang3.Validate; 025import org.apache.commons.lang3.builder.EqualsBuilder; 026import org.apache.commons.lang3.builder.HashCodeBuilder; 027import org.intellij.lang.annotations.Language; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031import java.sql.SQLException; 032import java.util.ArrayList; 033import java.util.Collections; 034import java.util.List; 035import java.util.Set; 036 037public class RenameIndexTask extends BaseTableTask { 038 private static final Logger ourLog = LoggerFactory.getLogger(RenameIndexTask.class); 039 private String myOldIndexName; 040 private String myNewIndexName; 041 042 public RenameIndexTask(String theProductVersion, String theSchemaVersion) { 043 super(theProductVersion, theSchemaVersion); 044 } 045 046 static List<String> createRenameIndexSql(DriverTypeEnum.ConnectionProperties theConnectionProperties, String theTableName, String theOldIndexName, String theNewIndexName, DriverTypeEnum theDriverType) throws SQLException { 047 Validate.notBlank(theOldIndexName, "theOldIndexName must not be blank"); 048 Validate.notBlank(theNewIndexName, "theNewIndexName must not be blank"); 049 Validate.notBlank(theTableName, "theTableName must not be blank"); 050 051 if (!JdbcUtils.getIndexNames(theConnectionProperties, theTableName).contains(theOldIndexName)) { 052 return Collections.emptyList(); 053 } 054 055 List<String> sql = new ArrayList<>(); 056 057 // Drop constraint 058 switch (theDriverType) { 059 case MYSQL_5_7: 060 case MARIADB_10_1: 061 // Quote the index names as "PRIMARY" is a reserved word in MySQL 062 sql.add("rename index `" + theOldIndexName + "` to `" + theNewIndexName + "`"); 063 break; 064 case DERBY_EMBEDDED: 065 sql.add("rename index " + theOldIndexName + " to " + theNewIndexName); 066 break; 067 case H2_EMBEDDED: 068 case POSTGRES_9_4: 069 case ORACLE_12C: 070 case COCKROACHDB_21_1: 071 sql.add("alter index " + theOldIndexName + " rename to " + theNewIndexName); 072 break; 073 case MSSQL_2012: 074 sql.add("EXEC sp_rename '" + theTableName + "." + theOldIndexName + "', '" + theNewIndexName + "'"); 075 break; 076 } 077 return sql; 078 } 079 080 @Override 081 public void validate() { 082 super.validate(); 083 Validate.notBlank(myOldIndexName, "The old index name must not be blank"); 084 Validate.notBlank(myNewIndexName, "The new index name must not be blank"); 085 086 setDescription("Rename index from " + myOldIndexName + " to " + myNewIndexName + " on table " + getTableName()); 087 } 088 089 @Override 090 public void doExecute() throws SQLException { 091 Set<String> indexNames = JdbcUtils.getIndexNames(getConnectionProperties(), getTableName()); 092 093 if (!indexNames.contains(myOldIndexName)) { 094 logInfo(ourLog, "Index {} does not exist on table {} - No action needed", myOldIndexName, getTableName()); 095 return; 096 } 097 098 List<String> sqls = createRenameIndexSql(getConnectionProperties(), getTableName(), myOldIndexName, myNewIndexName, getDriverType()); 099 if (!sqls.isEmpty()) { 100 logInfo(ourLog, "Renaming index from {} to {} on table {}", myOldIndexName, myNewIndexName, getTableName()); 101 } 102 for (@Language("SQL") String sql : sqls) { 103 executeSql(getTableName(), sql); 104 } 105 } 106 107 public RenameIndexTask setNewIndexName(String theNewIndexName) { 108 myNewIndexName = theNewIndexName; 109 return this; 110 } 111 112 public RenameIndexTask setOldIndexName(String theOldIndexName) { 113 myOldIndexName = theOldIndexName; 114 return this; 115 } 116 117 @Override 118 protected void generateEquals(EqualsBuilder theBuilder, BaseTask theOtherObject) { 119 RenameIndexTask otherObject = (RenameIndexTask) theOtherObject; 120 super.generateEquals(theBuilder, otherObject); 121 theBuilder.append(myOldIndexName, otherObject.myOldIndexName); 122 theBuilder.append(myNewIndexName, otherObject.myNewIndexName); 123 } 124 125 @Override 126 protected void generateHashCode(HashCodeBuilder theBuilder) { 127 super.generateHashCode(theBuilder); 128 theBuilder.append(myOldIndexName); 129 theBuilder.append(myNewIndexName); 130 } 131}