001/*- 002 * #%L 003 * HAPI FHIR Server - SQL Migration 004 * %% 005 * Copyright (C) 2014 - 2025 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( 047 DriverTypeEnum.ConnectionProperties theConnectionProperties, 048 String theTableName, 049 String theOldIndexName, 050 String theNewIndexName, 051 DriverTypeEnum theDriverType) 052 throws SQLException { 053 Validate.notBlank(theOldIndexName, "theOldIndexName must not be blank"); 054 Validate.notBlank(theNewIndexName, "theNewIndexName must not be blank"); 055 Validate.notBlank(theTableName, "theTableName must not be blank"); 056 057 if (!JdbcUtils.getIndexNames(theConnectionProperties, theTableName).contains(theOldIndexName)) { 058 return Collections.emptyList(); 059 } 060 061 List<String> sql = new ArrayList<>(); 062 063 // Drop constraint 064 switch (theDriverType) { 065 case MYSQL_5_7: 066 case MARIADB_10_1: 067 // Quote the index names as "PRIMARY" is a reserved word in MySQL 068 sql.add("rename index `" + theOldIndexName + "` to `" + theNewIndexName + "`"); 069 break; 070 case DERBY_EMBEDDED: 071 sql.add("rename index " + theOldIndexName + " to " + theNewIndexName); 072 break; 073 case H2_EMBEDDED: 074 case POSTGRES_9_4: 075 case ORACLE_12C: 076 case COCKROACHDB_21_1: 077 sql.add("alter index " + theOldIndexName + " rename to " + theNewIndexName); 078 break; 079 case MSSQL_2012: 080 sql.add("EXEC sp_rename '" + theTableName + "." + theOldIndexName + "', '" + theNewIndexName + "'"); 081 break; 082 } 083 return sql; 084 } 085 086 @Override 087 public void validate() { 088 super.validate(); 089 Validate.notBlank(myOldIndexName, "The old index name must not be blank"); 090 Validate.notBlank(myNewIndexName, "The new index name must not be blank"); 091 092 setDescription("Rename index from " + myOldIndexName + " to " + myNewIndexName + " on table " + getTableName()); 093 } 094 095 @Override 096 public void doExecute() throws SQLException { 097 Set<String> indexNames = JdbcUtils.getIndexNames(getConnectionProperties(), getTableName()); 098 099 if (!indexNames.contains(myOldIndexName)) { 100 logInfo(ourLog, "Index {} does not exist on table {} - No action needed", myOldIndexName, getTableName()); 101 return; 102 } 103 104 List<String> sqls = createRenameIndexSql( 105 getConnectionProperties(), getTableName(), myOldIndexName, myNewIndexName, getDriverType()); 106 if (!sqls.isEmpty()) { 107 logInfo(ourLog, "Renaming index from {} to {} on table {}", myOldIndexName, myNewIndexName, getTableName()); 108 } 109 for (@Language("SQL") String sql : sqls) { 110 executeSql(getTableName(), sql); 111 } 112 } 113 114 public RenameIndexTask setNewIndexName(String theNewIndexName) { 115 myNewIndexName = theNewIndexName; 116 return this; 117 } 118 119 public RenameIndexTask setOldIndexName(String theOldIndexName) { 120 myOldIndexName = theOldIndexName; 121 return this; 122 } 123 124 @Override 125 protected void generateEquals(EqualsBuilder theBuilder, BaseTask theOtherObject) { 126 RenameIndexTask otherObject = (RenameIndexTask) theOtherObject; 127 super.generateEquals(theBuilder, otherObject); 128 theBuilder.append(myOldIndexName, otherObject.myOldIndexName); 129 theBuilder.append(myNewIndexName, otherObject.myNewIndexName); 130 } 131 132 @Override 133 protected void generateHashCode(HashCodeBuilder theBuilder) { 134 super.generateHashCode(theBuilder); 135 theBuilder.append(myOldIndexName); 136 theBuilder.append(myNewIndexName); 137 } 138}