Added tests for cases where a renamed column is used in a Foreign Key constraint.
This commit is contained in:
parent
eb990e9a68
commit
5d22af45bf
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
|
||||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||||
import ca.uhn.fhir.jpa.migrate.JdbcUtils;
|
import ca.uhn.fhir.jpa.migrate.JdbcUtils;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import org.apache.commons.lang3.Validate;
|
import org.apache.commons.lang3.Validate;
|
||||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -42,6 +43,8 @@ public class RenameColumnTask extends BaseTableTask {
|
||||||
private boolean myIsOkayIfNeitherColumnExists;
|
private boolean myIsOkayIfNeitherColumnExists;
|
||||||
private boolean myDeleteTargetColumnFirstIfBothExist;
|
private boolean myDeleteTargetColumnFirstIfBothExist;
|
||||||
|
|
||||||
|
private boolean mySimulateMySQLForTest = false;
|
||||||
|
|
||||||
public RenameColumnTask(String theProductVersion, String theSchemaVersion) {
|
public RenameColumnTask(String theProductVersion, String theSchemaVersion) {
|
||||||
super(theProductVersion, theSchemaVersion);
|
super(theProductVersion, theSchemaVersion);
|
||||||
}
|
}
|
||||||
|
@ -84,8 +87,8 @@ public class RenameColumnTask extends BaseTableTask {
|
||||||
throw new SQLException("Can not rename " + getTableName() + "." + myOldName + " to " + myNewName + " because both columns exist and data exists in " + myNewName);
|
throw new SQLException("Can not rename " + getTableName() + "." + myOldName + " to " + myNewName + " because both columns exist and data exists in " + myNewName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getDriverType().equals(DriverTypeEnum.MYSQL_5_7)) {
|
if (getDriverType().equals(DriverTypeEnum.MYSQL_5_7) || mySimulateMySQLForTest) {
|
||||||
// Some DBs such as MYSQL require that foreign keys depending on the column be dropped before the column itself is dropped.
|
// Some DBs such as MYSQL require that foreign keys depending on the column be explicitly dropped before the column itself is dropped.
|
||||||
logInfo(ourLog, "Table {} has columns {} and {} - Going to drop any foreign keys depending on column {} before renaming", getTableName(), myOldName, myNewName, myNewName);
|
logInfo(ourLog, "Table {} has columns {} and {} - Going to drop any foreign keys depending on column {} before renaming", getTableName(), myOldName, myNewName, myNewName);
|
||||||
Set<String> foreignKeys = JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), myNewName, getTableName());
|
Set<String> foreignKeys = JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), myNewName, getTableName());
|
||||||
if(foreignKeys != null) {
|
if(foreignKeys != null) {
|
||||||
|
@ -173,4 +176,9 @@ public class RenameColumnTask extends BaseTableTask {
|
||||||
theBuilder.append(myOldName);
|
theBuilder.append(myOldName);
|
||||||
theBuilder.append(myNewName);
|
theBuilder.append(myNewName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setSimulateMySQLForTest(boolean theSimulateMySQLForTest) {
|
||||||
|
mySimulateMySQLForTest = theSimulateMySQLForTest;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,10 @@ import java.sql.SQLException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
@ -35,6 +38,41 @@ public class RenameColumnTaskTest extends BaseTest {
|
||||||
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "SOMETABLE"), containsInAnyOrder("PID", "TEXTCOL"));
|
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "SOMETABLE"), containsInAnyOrder("PID", "TEXTCOL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testForeignKeyColumnAlreadyExists_MySql() throws SQLException {
|
||||||
|
testForeignKeyColumnAlreadyExists(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testForeignKeyColumnAlreadyExists(boolean isMySql) throws SQLException {
|
||||||
|
executeSql("create table PARENT (PID bigint not null, TEXTCOL varchar(255), primary key (PID))");
|
||||||
|
executeSql("create table CHILD (PID bigint not null, PARENTREF bigint)");
|
||||||
|
executeSql("alter table CHILD add constraint FK_MOM foreign key (PARENTREF) references PARENT(PID)");
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeys(getConnectionProperties(), "PARENT", "CHILD"), hasSize(1));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), "PARENTREF", "CHILD"), containsInAnyOrder("FK_MOM"));
|
||||||
|
|
||||||
|
RenameColumnTask task = new RenameColumnTask("1", "1");
|
||||||
|
task.setTableName("CHILD");
|
||||||
|
task.setOldName("myParentRef");
|
||||||
|
task.setNewName("PARENTREF");
|
||||||
|
task.setSimulateMySQLForTest(isMySql);
|
||||||
|
getMigrator().addTask(task);
|
||||||
|
|
||||||
|
getMigrator().migrate();
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeys(getConnectionProperties(), "PARENT", "CHILD"), hasSize(1));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "CHILD"), containsInAnyOrder("PID", "PARENTREF"));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), "PARENTREF", "CHILD"), containsInAnyOrder("FK_MOM"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testForeignKeyColumnAlreadyExists_OtherDB() throws SQLException {
|
||||||
|
testForeignKeyColumnAlreadyExists(false);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBothExistDeleteTargetFirst() throws SQLException {
|
public void testBothExistDeleteTargetFirst() throws SQLException {
|
||||||
executeSql("create table SOMETABLE (PID bigint not null, TEXTCOL varchar(255), myTextCol varchar(255))");
|
executeSql("create table SOMETABLE (PID bigint not null, TEXTCOL varchar(255), myTextCol varchar(255))");
|
||||||
|
@ -53,6 +91,48 @@ public class RenameColumnTaskTest extends BaseTest {
|
||||||
assertThat(columnNames.toString(), columnNames, containsInAnyOrder("PID", "TEXTCOL"));
|
assertThat(columnNames.toString(), columnNames, containsInAnyOrder("PID", "TEXTCOL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testForeignKeyColumnBothExistDeleteTargetFirst_MySql() throws SQLException {
|
||||||
|
testForeignKeyColumnBothExistDeleteTargetFirst(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testForeignKeyColumnBothExistDeleteTargetFirst(boolean isMySql) throws SQLException {
|
||||||
|
executeSql("create table PARENT (PARENTID bigint not null, TEXTCOL varchar(255), primary key (PARENTID))");
|
||||||
|
executeSql("create table RELATION (RELATIONID bigint not null, TEXTCOL varchar(255), primary key (RELATIONID))");
|
||||||
|
executeSql("create table CHILD (PID bigint not null, PARENTREF bigint, NOKREF bigint)");
|
||||||
|
executeSql("alter table CHILD add constraint FK_MOM foreign key (PARENTREF) references PARENT(PARENTID)");
|
||||||
|
executeSql("alter table CHILD add constraint FK_NOK foreign key (NOKREF) references RELATION(RELATIONID)");
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeys(getConnectionProperties(), "PARENT", "CHILD"), hasSize(1));
|
||||||
|
assertThat(JdbcUtils.getForeignKeys(getConnectionProperties(), "RELATION", "CHILD"), hasSize(1));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), "PARENTREF", "CHILD"), containsInAnyOrder("FK_MOM"));
|
||||||
|
assertThat(JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), "NOKREF", "CHILD"), containsInAnyOrder("FK_NOK"));
|
||||||
|
|
||||||
|
RenameColumnTask task = new RenameColumnTask("1", "1");
|
||||||
|
task.setTableName("CHILD");
|
||||||
|
task.setOldName("PARENTREF");
|
||||||
|
task.setNewName("NOKREF");
|
||||||
|
task.setDeleteTargetColumnFirstIfBothExist(true);
|
||||||
|
task.setSimulateMySQLForTest(isMySql);
|
||||||
|
getMigrator().addTask(task);
|
||||||
|
|
||||||
|
getMigrator().migrate();
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeys(getConnectionProperties(), "RELATION", "CHILD"), empty());
|
||||||
|
assertThat(JdbcUtils.getForeignKeys(getConnectionProperties(), "PARENT", "CHILD"), hasSize(1));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "CHILD"), containsInAnyOrder("PID", "NOKREF"));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), "NOKREF", "CHILD"), containsInAnyOrder("FK_MOM"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testForeignKeyColumnBothExistDeleteTargetFirst_OtherDB() throws SQLException {
|
||||||
|
testForeignKeyColumnBothExistDeleteTargetFirst(false);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBothExistDeleteTargetFirstDataExistsInSourceAndTarget() throws SQLException {
|
public void testBothExistDeleteTargetFirstDataExistsInSourceAndTarget() throws SQLException {
|
||||||
executeSql("create table SOMETABLE (PID bigint not null, TEXTCOL varchar(255), myTextCol varchar(255))");
|
executeSql("create table SOMETABLE (PID bigint not null, TEXTCOL varchar(255), myTextCol varchar(255))");
|
||||||
|
@ -91,6 +171,42 @@ public class RenameColumnTaskTest extends BaseTest {
|
||||||
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "SOMETABLE"), containsInAnyOrder("PID", "TEXTCOL"));
|
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "SOMETABLE"), containsInAnyOrder("PID", "TEXTCOL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testForeignKeyColumnDoesntAlreadyExist_MySql() throws SQLException {
|
||||||
|
testForeignKeyColumnDoesntAlreadyExist(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testForeignKeyColumnDoesntAlreadyExist(boolean isMySql) throws SQLException {
|
||||||
|
executeSql("create table PARENT (PARENTID bigint not null, TEXTCOL varchar(255), primary key (PARENTID))");
|
||||||
|
executeSql("create table CHILD (PID bigint not null, PARENTREF bigint)");
|
||||||
|
executeSql("alter table CHILD add constraint FK_MOM foreign key (PARENTREF) references PARENT(PARENTID)");
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeys(getConnectionProperties(), "PARENT", "CHILD"), hasSize(1));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), "PARENTREF", "CHILD"), containsInAnyOrder("FK_MOM"));
|
||||||
|
|
||||||
|
RenameColumnTask task = new RenameColumnTask("1", "1");
|
||||||
|
task.setTableName("CHILD");
|
||||||
|
task.setOldName("PARENTREF");
|
||||||
|
task.setNewName("MOMREF");
|
||||||
|
task.setSimulateMySQLForTest(isMySql);
|
||||||
|
getMigrator().addTask(task);
|
||||||
|
|
||||||
|
getMigrator().migrate();
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeys(getConnectionProperties(), "PARENT", "CHILD"), hasSize(1));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getColumnNames(getConnectionProperties(), "CHILD"), containsInAnyOrder("PID", "MOMREF"));
|
||||||
|
|
||||||
|
assertThat(JdbcUtils.getForeignKeysForColumn(getConnectionProperties(), "MOMREF", "CHILD"), containsInAnyOrder("FK_MOM"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testForeignKeyColumnDoesntAlreadyExist_OtherDB() throws SQLException {
|
||||||
|
testForeignKeyColumnDoesntAlreadyExist(false);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNeitherColumnExists() {
|
public void testNeitherColumnExists() {
|
||||||
executeSql("create table SOMETABLE (PID bigint not null)");
|
executeSql("create table SOMETABLE (PID bigint not null)");
|
||||||
|
|
Loading…
Reference in New Issue