One more set of migrator tweaks to account for latest changes

This commit is contained in:
James Agnew 2019-07-19 10:10:00 -04:00
parent fd23190b4c
commit f53746cd63
8 changed files with 84 additions and 34 deletions

View File

@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.util;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.reflect.ClassPath; import com.google.common.reflect.ClassPath;
import com.google.common.reflect.ClassPath.ClassInfo; import com.google.common.reflect.ClassPath.ClassInfo;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@ -38,10 +39,7 @@ import java.io.InputStream;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Arrays; import java.util.*;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.google.common.base.Ascii.toUpperCase; import static com.google.common.base.Ascii.toUpperCase;
@ -145,6 +143,13 @@ public class TestUtil {
private static void scan(AnnotatedElement theAnnotatedElement, Set<String> theNames, boolean theIsSuperClass) { private static void scan(AnnotatedElement theAnnotatedElement, Set<String> theNames, boolean theIsSuperClass) {
Table table = theAnnotatedElement.getAnnotation(Table.class); Table table = theAnnotatedElement.getAnnotation(Table.class);
if (table != null) { if (table != null) {
// Banned name because we already used it once
ArrayList<String> bannedNames = Lists.newArrayList("CDR_USER_2FA", "TRM_VALUESET_CODE");
Validate.isTrue(!bannedNames.contains(table.name().toUpperCase()));
Validate.isTrue(table.name().toUpperCase().equals(table.name()));
assertNotADuplicateName(table.name(), theNames); assertNotADuplicateName(table.name(), theNames);
for (UniqueConstraint nextConstraint : table.uniqueConstraints()) { for (UniqueConstraint nextConstraint : table.uniqueConstraints()) {
assertNotADuplicateName(nextConstraint.name(), theNames); assertNotADuplicateName(nextConstraint.name(), theNames);

View File

@ -80,7 +80,9 @@ public class JdbcUtils {
indexNames.add(indexName); indexNames.add(indexName);
} }
indexNames.removeIf(i -> i == null);
return indexNames; return indexNames;
} catch (SQLException e) { } catch (SQLException e) {
throw new InternalErrorException(e); throw new InternalErrorException(e);
} }

View File

@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
*/ */
import ca.uhn.fhir.jpa.migrate.JdbcUtils; import ca.uhn.fhir.jpa.migrate.JdbcUtils;
import org.intellij.lang.annotations.Language;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -40,9 +41,16 @@ public class DropColumnTask extends BaseTableColumnTask<DropColumnTask> {
return; return;
} }
String sql = "alter table " + getTableName() + " drop column " + getColumnName(); String tableName = getTableName();
String columnName = getColumnName();
String sql = createSql(tableName, columnName);
ourLog.info("Dropping column {} on table {}", getColumnName(), getTableName()); ourLog.info("Dropping column {} on table {}", getColumnName(), getTableName());
executeSql(getTableName(), sql); executeSql(getTableName(), sql);
} }
@Language("SQL")
static String createSql(String theTableName, String theColumnName) {
return "alter table " + theTableName + " drop column " + theColumnName;
}
} }

View File

@ -65,6 +65,9 @@ public class DropIndexTask extends BaseTableTask<DropIndexTask> {
@Nonnull @Nonnull
static String createDropIndexSql(DriverTypeEnum.ConnectionProperties theConnectionProperties, String theTableName, String theIndexName, DriverTypeEnum theDriverType) throws SQLException { static String createDropIndexSql(DriverTypeEnum.ConnectionProperties theConnectionProperties, String theTableName, String theIndexName, DriverTypeEnum theDriverType) throws SQLException {
Validate.notBlank(theIndexName, "theIndexName must not be blank");
Validate.notBlank(theTableName, "theTableName must not be blank");
boolean isUnique = JdbcUtils.isIndexUnique(theConnectionProperties, theTableName, theIndexName); boolean isUnique = JdbcUtils.isIndexUnique(theConnectionProperties, theTableName, theIndexName);
String sql = null; String sql = null;

View File

@ -34,6 +34,11 @@ public class RenameColumnTask extends BaseTableTask<RenameColumnTask> {
private String myOldName; private String myOldName;
private String myNewName; private String myNewName;
private boolean myAllowNeitherColumnToExist; private boolean myAllowNeitherColumnToExist;
private boolean myDeleteTargetColumnFirstIfBothExist;
public void setDeleteTargetColumnFirstIfBothExist(boolean theDeleteTargetColumnFirstIfBothExist) {
myDeleteTargetColumnFirstIfBothExist = theDeleteTargetColumnFirstIfBothExist;
}
public void setOldName(String theOldName) { public void setOldName(String theOldName) {
Validate.notBlank(theOldName); Validate.notBlank(theOldName);
@ -51,15 +56,19 @@ public class RenameColumnTask extends BaseTableTask<RenameColumnTask> {
boolean haveOldName = columnNames.contains(myOldName.toUpperCase()); boolean haveOldName = columnNames.contains(myOldName.toUpperCase());
boolean haveNewName = columnNames.contains(myNewName.toUpperCase()); boolean haveNewName = columnNames.contains(myNewName.toUpperCase());
if (haveOldName && haveNewName) { if (haveOldName && haveNewName) {
if (myDeleteTargetColumnFirstIfBothExist) {
ourLog.info("Table {} has columns {} and {} - Going to drop {} before renaming", getTableName(), myOldName, myNewName, myNewName);
String sql = DropColumnTask.createSql(getTableName(), myNewName);
executeSql(getTableName(), sql);
} else {
throw new SQLException("Can not rename " + getTableName() + "." + myOldName + " to " + myNewName + " because both columns exist!"); throw new SQLException("Can not rename " + getTableName() + "." + myOldName + " to " + myNewName + " because both columns exist!");
} }
if (!haveOldName && !haveNewName) { } else if (!haveOldName && !haveNewName) {
if (isAllowNeitherColumnToExist()) { if (isAllowNeitherColumnToExist()) {
return; return;
} }
throw new SQLException("Can not rename " + getTableName() + "." + myOldName + " to " + myNewName + " because neither column exists!"); throw new SQLException("Can not rename " + getTableName() + "." + myOldName + " to " + myNewName + " because neither column exists!");
} } else if (haveNewName) {
if (haveNewName) {
ourLog.info("Column {} already exists on table {} - No action performed", myNewName, getTableName()); ourLog.info("Column {} already exists on table {} - No action performed", myNewName, getTableName());
return; return;
} }
@ -94,11 +103,11 @@ public class RenameColumnTask extends BaseTableTask<RenameColumnTask> {
} }
public void setAllowNeitherColumnToExist(boolean theAllowNeitherColumnToExist) {
myAllowNeitherColumnToExist = theAllowNeitherColumnToExist;
}
public boolean isAllowNeitherColumnToExist() { public boolean isAllowNeitherColumnToExist() {
return myAllowNeitherColumnToExist; return myAllowNeitherColumnToExist;
} }
public void setAllowNeitherColumnToExist(boolean theAllowNeitherColumnToExist) {
myAllowNeitherColumnToExist = theAllowNeitherColumnToExist;
}
} }

View File

@ -63,32 +63,35 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
protected void init400() { protected void init400() {
Builder version = forVersion(VersionEnum.V4_0_0); Builder version = forVersion(VersionEnum.V4_0_0);
// Interim builds used this name
version.onTable("TRM_VALUESET_CODE").dropThisTable();
version.onTable("TRM_CONCEPT_MAP_GROUP") version.onTable("TRM_CONCEPT_MAP_GROUP")
.renameColumn("myConceptMapUrl", "CONCEPT_MAP_URL") .renameColumn("myConceptMapUrl", "CONCEPT_MAP_URL", false, true)
.renameColumn("mySourceValueSet", "SOURCE_VS") .renameColumn("mySourceValueSet", "SOURCE_VS", false, true)
.renameColumn("myTargetValueSet", "TARGET_VS"); .renameColumn("myTargetValueSet", "TARGET_VS", false, true);
version.onTable("TRM_CONCEPT_MAP_GRP_ELEMENT") version.onTable("TRM_CONCEPT_MAP_GRP_ELEMENT")
.renameColumn("myConceptMapUrl", "CONCEPT_MAP_URL") .renameColumn("myConceptMapUrl", "CONCEPT_MAP_URL", false, true)
.renameColumn("mySystem", "SYSTEM_URL") .renameColumn("mySystem", "SYSTEM_URL", false, true)
.renameColumn("mySystemVersion", "SYSTEM_VERSION") .renameColumn("mySystemVersion", "SYSTEM_VERSION", false, true)
.renameColumn("myValueSet", "VALUESET_URL"); .renameColumn("myValueSet", "VALUESET_URL", false, true);
version.onTable("TRM_CONCEPT_MAP_GRP_ELM_TGT") version.onTable("TRM_CONCEPT_MAP_GRP_ELM_TGT")
.renameColumn("myConceptMapUrl", "CONCEPT_MAP_URL") .renameColumn("myConceptMapUrl", "CONCEPT_MAP_URL", false, true)
.renameColumn("mySystem", "SYSTEM_URL") .renameColumn("mySystem", "SYSTEM_URL", false, true)
.renameColumn("mySystemVersion", "SYSTEM_VERSION") .renameColumn("mySystemVersion", "SYSTEM_VERSION", false, true)
.renameColumn("myValueSet", "VALUESET_URL"); .renameColumn("myValueSet", "VALUESET_URL", false, true);
version.onTable("TRM_VALUESET") version.onTable("TRM_VALUESET")
.renameColumn("NAME", "VSNAME", true); .renameColumn("NAME", "VSNAME", true, true);
version.onTable("TRM_VALUESET_CONCEPT") version.onTable("TRM_VALUESET_CONCEPT")
.renameColumn("CODE", "CODEVAL", true) .renameColumn("CODE", "CODEVAL", true, true)
.renameColumn("SYSTEM", "SYSTEM_URL", true); .renameColumn("SYSTEM", "SYSTEM_URL", true, true);
version.onTable("TRM_CONCEPT") version.onTable("TRM_CONCEPT")
.renameColumn("CODE", "CODEVAL"); .renameColumn("CODE", "CODEVAL", false, true);
// TermValueSet // TermValueSet
version.startSectionWithMessage("Processing table: TRM_VALUESET"); version.startSectionWithMessage("Processing table: TRM_VALUESET");
@ -117,12 +120,12 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
.addForeignKey("FK_TRM_VALUESET_PID") .addForeignKey("FK_TRM_VALUESET_PID")
.toColumn("VALUESET_PID") .toColumn("VALUESET_PID")
.references("TRM_VALUESET", "PID"); .references("TRM_VALUESET", "PID");
termValueSetConceptTable.addColumn("SYSTEM").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermCodeSystem.MAX_URL_LENGTH); termValueSetConceptTable.addColumn("SYSTEM_URL").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermCodeSystem.MAX_URL_LENGTH);
termValueSetConceptTable.addColumn("CODE").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermConcept.MAX_CODE_LENGTH); termValueSetConceptTable.addColumn("CODEVAL").nonNullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermConcept.MAX_CODE_LENGTH);
termValueSetConceptTable termValueSetConceptTable
.addIndex("IDX_VALUESET_CONCEPT_CS_CD") .addIndex("IDX_VALUESET_CONCEPT_CS_CD")
.unique(false) .unique(false)
.withColumns("SYSTEM", "CODE"); .withColumns("SYSTEM_URL", "CODEVAL");
termValueSetConceptTable.addColumn("DISPLAY").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermConcept.MAX_DESC_LENGTH); termValueSetConceptTable.addColumn("DISPLAY").nullable().type(BaseTableColumnTypeTask.ColumnTypeEnum.STRING, TermConcept.MAX_DESC_LENGTH);
// TermValueSetConceptDesignation // TermValueSetConceptDesignation

View File

@ -174,15 +174,16 @@ public class BaseMigrationTasks<T extends Enum> {
} }
public BuilderWithTableName renameColumn(String theOldName, String theNewName) { public BuilderWithTableName renameColumn(String theOldName, String theNewName) {
return renameColumn(theOldName, theNewName, false); return renameColumn(theOldName, theNewName, false, false);
} }
public BuilderWithTableName renameColumn(String theOldName, String theNewName, boolean theAllowNeitherColumnToExist) { public BuilderWithTableName renameColumn(String theOldName, String theNewName, boolean theAllowNeitherColumnToExist, boolean theDeleteTargetColumnFirstIfBothEixst) {
RenameColumnTask task = new RenameColumnTask(); RenameColumnTask task = new RenameColumnTask();
task.setTableName(myTableName); task.setTableName(myTableName);
task.setOldName(theOldName); task.setOldName(theOldName);
task.setNewName(theNewName); task.setNewName(theNewName);
task.setAllowNeitherColumnToExist(theAllowNeitherColumnToExist); task.setAllowNeitherColumnToExist(theAllowNeitherColumnToExist);
task.setDeleteTargetColumnFirstIfBothExist(theDeleteTargetColumnFirstIfBothEixst);
addTask(task); addTask(task);
return this; return this;
} }

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import org.junit.Test; import org.junit.Test;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Set;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
@ -28,6 +29,24 @@ public class RenameColumnTaskTest extends BaseTest {
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "SOMETABLE"), containsInAnyOrder("PID", "TEXTCOL")); assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "SOMETABLE"), containsInAnyOrder("PID", "TEXTCOL"));
} }
@Test
public void testBothExistDeleteTargetFirst() throws SQLException {
executeSql("create table SOMETABLE (PID bigint not null, TEXTCOL varchar(255), myTextCol varchar(255))");
RenameColumnTask task = new RenameColumnTask();
task.setTableName("SOMETABLE");
task.setDescription("Drop an index");
task.setOldName("myTextCol");
task.setNewName("TEXTCOL");
task.setDeleteTargetColumnFirstIfBothExist(true);
getMigrator().addTask(task);
getMigrator().migrate();
Set<String> columnNames = JdbcUtils.getColumnNames(getConnectionProperties(), "SOMETABLE");
assertThat(columnNames.toString(), columnNames, containsInAnyOrder("PID", "TEXTCOL"));
}
@Test @Test
public void testColumnDoesntAlreadyExist() throws SQLException { public void testColumnDoesntAlreadyExist() throws SQLException {
executeSql("create table SOMETABLE (PID bigint not null, myTextCol varchar(255))"); executeSql("create table SOMETABLE (PID bigint not null, myTextCol varchar(255))");