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