From 40bc7540512d9ee1583c5e70b42bb6d59a105308 Mon Sep 17 00:00:00 2001 From: ianmarshall Date: Mon, 1 Feb 2021 15:52:41 -0500 Subject: [PATCH] Address gaps in migration that can occur with Oracle DB when flyway is disabled. --- .../ca/uhn/fhir/jpa/migrate/JdbcUtils.java | 2 + .../tasks/HapiFhirJpaMigrationTasks.java | 4 +- .../fhir/jpa/migrate/tasks/api/Builder.java | 3 +- .../uhn/fhir/jpa/migrate/JdbcUtilsTest.java | 67 +++++++++++++++++++ .../taskdef/AddTableByColumnTaskTest.java | 14 ++-- 5 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/JdbcUtilsTest.java diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/JdbcUtils.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/JdbcUtils.java index 48e1e210066..fb4af862dd6 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/JdbcUtils.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/JdbcUtils.java @@ -258,6 +258,8 @@ public class JdbcUtils { return new ColumnType(ColumnTypeEnum.CLOB, length); case Types.DOUBLE: return new ColumnType(ColumnTypeEnum.DOUBLE, length); + case Types.FLOAT: + return new ColumnType(ColumnTypeEnum.FLOAT, length); default: throw new IllegalArgumentException("Don't know how to handle datatype " + dataType + " for column " + theColumnName + " on table " + theTableName); } diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java index 82eed2fefda..ec2e34b732c 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/HapiFhirJpaMigrationTasks.java @@ -667,10 +667,12 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks { version.startSectionWithMessage("Processing table: TRM_VALUESET_CONCEPT, swapping index for unique constraint"); termValueSetConceptTable.dropIndex("20190801.1", "IDX_VALUESET_CONCEPT_CS_CD"); + // This index has been renamed in later versions. As such, allowing failure here as some DBs disallow + // multiple indexes referencing the same set of columns. termValueSetConceptTable .addIndex("20190801.2", "IDX_VS_CONCEPT_CS_CD") .unique(true) - .withColumns("VALUESET_PID", "SYSTEM_URL", "CODEVAL"); + .withColumns("VALUESET_PID", "SYSTEM_URL", "CODEVAL").failureAllowed(); // TermValueSetConceptDesignation version.startSectionWithMessage("Processing table: TRM_VALUESET_C_DESIGNATION"); diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/Builder.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/Builder.java index 7b2284e2a16..6fecd36e110 100644 --- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/Builder.java +++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/Builder.java @@ -402,7 +402,7 @@ public class Builder { super(theVersion, theColumnName); } - public void references(String theForeignTable, String theForeignColumn) { + public BuilderCompleteTask references(String theForeignTable, String theForeignColumn) { AddForeignKeyTask task = new AddForeignKeyTask(myRelease, myVersion); task.setTableName(myTableName); task.setConstraintName(myForeignKeyName); @@ -410,6 +410,7 @@ public class Builder { task.setForeignTableName(theForeignTable); task.setForeignColumnName(theForeignColumn); addTask(task); + return new BuilderCompleteTask(task); } } } diff --git a/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/JdbcUtilsTest.java b/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/JdbcUtilsTest.java new file mode 100644 index 00000000000..42eaf645543 --- /dev/null +++ b/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/JdbcUtilsTest.java @@ -0,0 +1,67 @@ +package ca.uhn.fhir.jpa.migrate; + +import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeEnum; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; + +import static org.mockito.Mockito.when; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(MockitoExtension.class) +public class JdbcUtilsTest { + + @Mock + DataSource myDataSource; + @Mock + Connection myConnection; + @Mock + DatabaseMetaData myDatabaseMetaData; + @Mock + ResultSet myResultSet; + + + @Test + public void testGetColumnType_verifyTypeMappings() throws SQLException { + testGetColumnType_verifyTypeMapping(Types.BIT, ColumnTypeEnum.BOOLEAN); + testGetColumnType_verifyTypeMapping(Types.BOOLEAN, ColumnTypeEnum.BOOLEAN); + testGetColumnType_verifyTypeMapping(Types.VARCHAR, ColumnTypeEnum.STRING); + testGetColumnType_verifyTypeMapping(Types.NUMERIC, ColumnTypeEnum.LONG); + testGetColumnType_verifyTypeMapping(Types.BIGINT, ColumnTypeEnum.LONG); + testGetColumnType_verifyTypeMapping(Types.DECIMAL, ColumnTypeEnum.LONG); + testGetColumnType_verifyTypeMapping(Types.INTEGER, ColumnTypeEnum.INT); + testGetColumnType_verifyTypeMapping(Types.TIMESTAMP, ColumnTypeEnum.DATE_TIMESTAMP); + testGetColumnType_verifyTypeMapping(Types.TIMESTAMP_WITH_TIMEZONE, ColumnTypeEnum.DATE_TIMESTAMP); + testGetColumnType_verifyTypeMapping(Types.BLOB, ColumnTypeEnum.BLOB); + testGetColumnType_verifyTypeMapping(Types.CLOB, ColumnTypeEnum.CLOB); + testGetColumnType_verifyTypeMapping(Types.DOUBLE, ColumnTypeEnum.DOUBLE); + testGetColumnType_verifyTypeMapping(Types.FLOAT, ColumnTypeEnum.FLOAT); + + } + + private void testGetColumnType_verifyTypeMapping(int theExistingDataType, ColumnTypeEnum theExpectedColumnType) throws SQLException { + when(myResultSet.next()).thenReturn(true).thenReturn(false); + when(myResultSet.getString("TABLE_NAME")).thenReturn("TEST_TABLE"); + when(myResultSet.getString("COLUMN_NAME")).thenReturn("TEST_COLUMN"); + when(myResultSet.getInt("DATA_TYPE")).thenReturn(theExistingDataType); + when(myResultSet.getLong("COLUMN_SIZE")).thenReturn(17L); + + when(myDatabaseMetaData.getColumns("Catalog", "Schema", "TEST_TABLE", null)).thenReturn(myResultSet); + when(myConnection.getMetaData()).thenReturn(myDatabaseMetaData); + when(myConnection.getCatalog()).thenReturn("Catalog"); + when(myConnection.getSchema()).thenReturn("Schema"); + when(myDataSource.getConnection()).thenReturn(myConnection); + DriverTypeEnum.ConnectionProperties myConnectionProperties = DriverTypeEnum.H2_EMBEDDED.newConnectionProperties(myDataSource); + JdbcUtils.ColumnType testColumnType = JdbcUtils.getColumnType(myConnectionProperties, "TEST_TABLE", "TEST_COLUMN"); + + assertEquals(theExpectedColumnType, testColumnType.getColumnTypeEnum()); + } +} diff --git a/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTaskTest.java b/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTaskTest.java index 59fb3e45e8f..c1989522d4c 100644 --- a/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTaskTest.java +++ b/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableByColumnTaskTest.java @@ -49,19 +49,21 @@ public class AddTableByColumnTaskTest extends BaseTest { Builder.BuilderWithTableName targetTable = v.addTableByColumns("1", "TGT_TABLE", "PID"); targetTable.addColumn("2", "PID").nonNullable().type(ColumnTypeEnum.LONG); + targetTable.addColumn("3", "PID2").nonNullable().type(ColumnTypeEnum.LONG); - Builder.BuilderAddTableByColumns fooTable = v.addTableByColumns("3", "FOO_TABLE", "PID"); + Builder.BuilderAddTableByColumns fooTable = v.addTableByColumns("4", "FOO_TABLE", "PID"); fooTable.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG); fooTable.addColumn("HELLO").nullable().type(ColumnTypeEnum.STRING, 200); fooTable.addColumn("GOODBYE").nullable().type(ColumnTypeEnum.STRING, 200); fooTable.addColumn("COL_REF").nullable().type(ColumnTypeEnum.LONG); - fooTable.addIndex("4", "IDX_HELLO").unique(true).withColumns("HELLO"); - fooTable.addIndex("5", "IDX_GOODBYE").unique(true).withColumnsStub("GOODBYE"); - fooTable.dropIndexStub("6", "IDX_HELLO"); - fooTable.addForeignKey("7", "FK_REF").toColumn("COL_REF").references("TGT_TABLE", "PID"); + fooTable.addIndex("5", "IDX_HELLO").unique(true).withColumns("HELLO"); + fooTable.addIndex("6", "IDX_GOODBYE").unique(true).withColumnsStub("GOODBYE"); + fooTable.dropIndexStub("7", "IDX_HELLO"); + fooTable.addForeignKey("8", "FK_REF").toColumn("COL_REF").references("TGT_TABLE", "PID"); + fooTable.addForeignKey("9", "FK_REF_INVALID").toColumn("COL_REF_INVALID").references("TGT_TABLE", "PID2").failureAllowed(); Builder.BuilderWithTableName renameIndexTable = v.onTable("FOO_TABLE"); - renameIndexTable.renameIndex("8", "IDX_HELLO", "IDX_BONJOUR"); + renameIndexTable.renameIndex("10", "IDX_HELLO", "IDX_BONJOUR"); } } }