mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-09 14:33:32 +00:00
fix oracle issue
This commit is contained in:
parent
388e191ab3
commit
9a14e02f85
@ -52,7 +52,7 @@ public class HapiMigrator {
|
||||
public HapiMigrator(DriverTypeEnum theDriverType, DataSource theDataSource, String theMigrationTableName) {
|
||||
myDriverType = theDriverType;
|
||||
myDataSource = theDataSource;
|
||||
myHapiMigrationStorageSvc = new HapiMigrationStorageSvc(new HapiMigrationDao(theDataSource, theMigrationTableName));
|
||||
myHapiMigrationStorageSvc = new HapiMigrationStorageSvc(new HapiMigrationDao(theDataSource, theDriverType, theMigrationTableName));
|
||||
}
|
||||
|
||||
public DataSource getDataSource() {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package ca.uhn.fhir.jpa.migrate.dao;
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.entity.HapiMigrationEntity;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.util.VersionEnum;
|
||||
@ -20,11 +21,6 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class HapiMigrationDao {
|
||||
static {
|
||||
// required for most databases for boolean columns
|
||||
System.setProperty("com.healthmarketscience.sqlbuilder.useBooleanLiterals", "true");
|
||||
}
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(HapiMigrationDao.class);
|
||||
|
||||
private final JdbcTemplate myJdbcTemplate;
|
||||
@ -32,18 +28,18 @@ public class HapiMigrationDao {
|
||||
private final MigrationQueryBuilder myMigrationQueryBuilder;
|
||||
private final DataSource myDataSource;
|
||||
|
||||
public HapiMigrationDao(DataSource theDataSource, String theMigrationTablename) {
|
||||
public HapiMigrationDao(DataSource theDataSource, DriverTypeEnum theDriverType, String theMigrationTablename) {
|
||||
myDataSource = theDataSource;
|
||||
myJdbcTemplate = new JdbcTemplate(theDataSource);
|
||||
myMigrationTablename = theMigrationTablename;
|
||||
myMigrationQueryBuilder = new MigrationQueryBuilder(theMigrationTablename);
|
||||
myMigrationQueryBuilder = new MigrationQueryBuilder(theDriverType, theMigrationTablename);
|
||||
}
|
||||
|
||||
public Set<MigrationVersion> fetchSuccessfulMigrationVersions() {
|
||||
String query = myMigrationQueryBuilder.findSuccessfulVersionQuery();
|
||||
List<String> result = myJdbcTemplate.queryForList(query, String.class);
|
||||
|
||||
return result.stream()
|
||||
List<HapiMigrationEntity> allEntries = findAll();
|
||||
return allEntries.stream()
|
||||
.filter(HapiMigrationEntity::getSuccess)
|
||||
.map(HapiMigrationEntity::getVersion)
|
||||
.map(MigrationVersion::fromVersion)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
@ -112,6 +108,6 @@ public class HapiMigrationDao {
|
||||
}
|
||||
|
||||
public List<HapiMigrationEntity> findAll() {
|
||||
return myJdbcTemplate.query(myMigrationQueryBuilder.findAll(), HapiMigrationEntity.rowMapper());
|
||||
return myJdbcTemplate.query(myMigrationQueryBuilder.findAllQuery(), HapiMigrationEntity.rowMapper());
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
package ca.uhn.fhir.jpa.migrate.dao;
|
||||
|
||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.entity.HapiMigrationEntity;
|
||||
import com.healthmarketscience.sqlbuilder.BinaryCondition;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeToDriverTypeToSqlType;
|
||||
import com.healthmarketscience.common.util.AppendableExt;
|
||||
import com.healthmarketscience.sqlbuilder.CreateIndexQuery;
|
||||
import com.healthmarketscience.sqlbuilder.CreateTableQuery;
|
||||
import com.healthmarketscience.sqlbuilder.DeleteQuery;
|
||||
@ -9,6 +12,8 @@ import com.healthmarketscience.sqlbuilder.FunctionCall;
|
||||
import com.healthmarketscience.sqlbuilder.InsertQuery;
|
||||
import com.healthmarketscience.sqlbuilder.JdbcEscape;
|
||||
import com.healthmarketscience.sqlbuilder.SelectQuery;
|
||||
import com.healthmarketscience.sqlbuilder.SqlObject;
|
||||
import com.healthmarketscience.sqlbuilder.ValidationContext;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSchema;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbSpec;
|
||||
@ -16,6 +21,7 @@ import com.healthmarketscience.sqlbuilder.dbspec.basic.DbTable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Types;
|
||||
|
||||
public class MigrationQueryBuilder {
|
||||
@ -34,13 +40,14 @@ public class MigrationQueryBuilder {
|
||||
private final DbColumn myInstalledOnCol;
|
||||
private final DbColumn myExecutionTimeCol;
|
||||
private final DbColumn mySuccessCol;
|
||||
|
||||
private final String myBuildSuccessfulVersionQuery;
|
||||
private final String myDeleteAll;
|
||||
private final String myHighestKeyQuery;
|
||||
private final DriverTypeEnum myDriverType;
|
||||
private final String myMigrationTablename;
|
||||
private final String myBooleanType;
|
||||
|
||||
public MigrationQueryBuilder(String theMigrationTablename) {
|
||||
public MigrationQueryBuilder(DriverTypeEnum theDriverType, String theMigrationTablename) {
|
||||
myDriverType = theDriverType;
|
||||
myMigrationTablename = theMigrationTablename;
|
||||
|
||||
mySpec = new DbSpec();
|
||||
@ -71,26 +78,15 @@ public class MigrationQueryBuilder {
|
||||
|
||||
myExecutionTimeCol = myTable.addColumn("\"execution_time\"", Types.INTEGER, null);
|
||||
myExecutionTimeCol.notNull();
|
||||
mySuccessCol = myTable.addColumn("\"success\"", Types.BOOLEAN, null);
|
||||
|
||||
myBooleanType = ColumnTypeToDriverTypeToSqlType.getColumnTypeToDriverTypeToSqlType().get(ColumnTypeEnum.BOOLEAN).get(theDriverType);
|
||||
mySuccessCol = myTable.addColumn("\"success\"", myBooleanType, null);
|
||||
mySuccessCol.notNull();
|
||||
|
||||
myBuildSuccessfulVersionQuery = buildFindSuccessfulVersionQuery();
|
||||
myDeleteAll = new DeleteQuery(myTable).toString();
|
||||
myHighestKeyQuery = buildHighestKeyQuery();
|
||||
}
|
||||
|
||||
private String buildFindSuccessfulVersionQuery() {
|
||||
return new SelectQuery()
|
||||
.addColumns(myVersionCol)
|
||||
.addCondition(BinaryCondition.equalTo(mySuccessCol, true))
|
||||
.validate()
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String findSuccessfulVersionQuery() {
|
||||
return myBuildSuccessfulVersionQuery;
|
||||
}
|
||||
|
||||
public String deleteAll() {
|
||||
return myDeleteAll;
|
||||
}
|
||||
@ -117,10 +113,33 @@ public class MigrationQueryBuilder {
|
||||
.addColumn(myInstalledByCol, theEntity.getInstalledBy())
|
||||
.addColumn(myInstalledOnCol, JdbcEscape.timestamp(theEntity.getInstalledOn()))
|
||||
.addColumn(myExecutionTimeCol, theEntity.getExecutionTime())
|
||||
.addColumn(mySuccessCol, theEntity.getSuccess())
|
||||
.addColumn(mySuccessCol, getBooleanValue(theEntity.getSuccess()))
|
||||
.validate()
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
sqlbuilder doesn't know about different database types, so we have to manually map boolean columns ourselves :-(
|
||||
I'm gaining a new appreciation for Hibernate. I tried using hibernate for maintaining this table, but it added
|
||||
a lot of overhead for managing just one table. Seeing this sort of nonsense though makes me wonder if we should
|
||||
just use it instead of sqlbuilder. Disappointed that sqlbuilder doesn't handle boolean well out of the box.
|
||||
(It does support a static option via System.setProperty("com.healthmarketscience.sqlbuilder.useBooleanLiterals", "true");
|
||||
but that only works at classloading time which isn't much help to us.
|
||||
*/
|
||||
|
||||
private SqlObject getBooleanValue(Boolean theBoolean) {
|
||||
SqlObject retval = new SqlObject() {
|
||||
@Override
|
||||
protected void collectSchemaObjects(ValidationContext vContext) {}
|
||||
|
||||
@Override
|
||||
public void appendTo(AppendableExt app) throws IOException {
|
||||
String stringValue = ColumnTypeToDriverTypeToSqlType.toBooleanValue(myDriverType, theBoolean);
|
||||
app.append(stringValue);
|
||||
}
|
||||
};
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
public String createTableStatement() {
|
||||
@ -137,7 +156,7 @@ public class MigrationQueryBuilder {
|
||||
.toString();
|
||||
}
|
||||
|
||||
public String findAll() {
|
||||
public String findAllQuery() {
|
||||
return new SelectQuery()
|
||||
.addFromTable(myTable)
|
||||
.addAllColumns()
|
||||
|
@ -115,9 +115,4 @@ public abstract class BaseTableColumnTypeTask extends BaseTableColumnTask {
|
||||
}
|
||||
return myColumnType.name();
|
||||
}
|
||||
|
||||
public ColumnTypeToDriverTypeToSqlType getColumnTypeToDriverTypeToSqlType() {
|
||||
return myColumnTypeToDriverTypeToSqlType;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class BaseTableTask extends BaseTask {
|
||||
protected final ColumnTypeToDriverTypeToSqlType myColumnTypeToDriverTypeToSqlType = new ColumnTypeToDriverTypeToSqlType();
|
||||
private String myTableName;
|
||||
|
||||
|
||||
@ -57,7 +56,7 @@ public abstract class BaseTableTask extends BaseTask {
|
||||
}
|
||||
|
||||
protected String getSqlType(ColumnTypeEnum theColumnType, Long theColumnLength) {
|
||||
String retVal = myColumnTypeToDriverTypeToSqlType.getColumnTypeToDriverTypeToSqlType().get(theColumnType).get(getDriverType());
|
||||
String retVal = ColumnTypeToDriverTypeToSqlType.getColumnTypeToDriverTypeToSqlType().get(theColumnType).get(getDriverType());
|
||||
Objects.requireNonNull(retVal);
|
||||
|
||||
if (theColumnType == ColumnTypeEnum.STRING) {
|
||||
|
@ -26,10 +26,12 @@ import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ColumnTypeToDriverTypeToSqlType {
|
||||
Map<ColumnTypeEnum, Map<DriverTypeEnum, String>> myColumnTypeToDriverTypeToSqlType = new HashMap<>();
|
||||
public final class ColumnTypeToDriverTypeToSqlType {
|
||||
|
||||
public ColumnTypeToDriverTypeToSqlType() {
|
||||
private ColumnTypeToDriverTypeToSqlType() {}
|
||||
static Map<ColumnTypeEnum, Map<DriverTypeEnum, String>> myColumnTypeToDriverTypeToSqlType = new HashMap<>();
|
||||
|
||||
static {
|
||||
setColumnType(ColumnTypeEnum.INT, DriverTypeEnum.H2_EMBEDDED, "integer");
|
||||
setColumnType(ColumnTypeEnum.INT, DriverTypeEnum.DERBY_EMBEDDED, "integer");
|
||||
setColumnType(ColumnTypeEnum.INT, DriverTypeEnum.MARIADB_10_1, "integer");
|
||||
@ -111,15 +113,26 @@ public class ColumnTypeToDriverTypeToSqlType {
|
||||
setColumnType(ColumnTypeEnum.CLOB, DriverTypeEnum.MSSQL_2012, "varchar(MAX)");
|
||||
}
|
||||
|
||||
public Map<ColumnTypeEnum, Map<DriverTypeEnum, String>> getColumnTypeToDriverTypeToSqlType() {
|
||||
public static Map<ColumnTypeEnum, Map<DriverTypeEnum, String>> getColumnTypeToDriverTypeToSqlType() {
|
||||
return myColumnTypeToDriverTypeToSqlType;
|
||||
}
|
||||
|
||||
private void setColumnType(ColumnTypeEnum theColumnType, DriverTypeEnum theDriverType, String theColumnTypeSql) {
|
||||
private static void setColumnType(ColumnTypeEnum theColumnType, DriverTypeEnum theDriverType, String theColumnTypeSql) {
|
||||
Map<DriverTypeEnum, String> columnSqlType = myColumnTypeToDriverTypeToSqlType.computeIfAbsent(theColumnType, k -> new HashMap<>());
|
||||
if (columnSqlType.containsKey(theDriverType)) {
|
||||
throw new IllegalStateException(Msg.code(65) + "Duplicate key: " + theDriverType);
|
||||
}
|
||||
columnSqlType.put(theDriverType, theColumnTypeSql);
|
||||
}
|
||||
|
||||
public static String toBooleanValue(DriverTypeEnum theDriverType, Boolean theBoolean) {
|
||||
switch (theDriverType) {
|
||||
case H2_EMBEDDED:
|
||||
case DERBY_EMBEDDED:
|
||||
case POSTGRES_9_4:
|
||||
return theBoolean.toString();
|
||||
default:
|
||||
return theBoolean ? "1" : "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ public abstract class BaseMigrationTest {
|
||||
|
||||
@BeforeAll
|
||||
public static void beforeAll() {
|
||||
ourHapiMigrationDao = new HapiMigrationDao(getDataSource(), TABLE_NAME);
|
||||
ourHapiMigrationDao = new HapiMigrationDao(getDataSource(), DriverTypeEnum.H2_EMBEDDED, TABLE_NAME);
|
||||
ourHapiMigrationDao.createMigrationTableIfRequired();
|
||||
ourHapiMigrationStorageSvc = new HapiMigrationStorageSvc(ourHapiMigrationDao);
|
||||
}
|
||||
|
@ -0,0 +1,39 @@
|
||||
package ca.uhn.fhir.jpa.migrate.dao;
|
||||
|
||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.entity.HapiMigrationEntity;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
|
||||
class MigrationQueryBuilderTest {
|
||||
|
||||
private static final String TABLE = "TEST_TABLE_NAME";
|
||||
|
||||
@Test
|
||||
void derby_insert() {
|
||||
MigrationQueryBuilder mqb = new MigrationQueryBuilder(DriverTypeEnum.DERBY_EMBEDDED, TABLE);
|
||||
HapiMigrationEntity entity = buildEntity();
|
||||
String insertSql = mqb.insertStatement(entity);
|
||||
assertThat(insertSql, endsWith(",NULL,true)"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void oracle_insert() {
|
||||
MigrationQueryBuilder mqb = new MigrationQueryBuilder(DriverTypeEnum.ORACLE_12C, TABLE);
|
||||
HapiMigrationEntity entity = buildEntity();
|
||||
String insertSql = mqb.insertStatement(entity);
|
||||
assertThat(insertSql, endsWith(",NULL,1)"));
|
||||
}
|
||||
|
||||
private HapiMigrationEntity buildEntity() {
|
||||
HapiMigrationEntity retval = new HapiMigrationEntity();
|
||||
retval.setInstalledOn(new Date());
|
||||
retval.setSuccess(true);
|
||||
return retval;
|
||||
}
|
||||
|
||||
}
|
@ -92,7 +92,7 @@ public abstract class BaseTest {
|
||||
myConnectionProperties = testDatabaseDetails.myConnectionProperties;
|
||||
myDataSource = testDatabaseDetails.myDataSource;
|
||||
myMigrator = testDatabaseDetails.myMigrator;
|
||||
myHapiMigrationDao = new HapiMigrationDao(testDatabaseDetails.myDataSource, SchemaMigrator.HAPI_FHIR_MIGRATION_TABLENAME);
|
||||
myHapiMigrationDao = new HapiMigrationDao(testDatabaseDetails.myDataSource, testDatabaseDetails.getDriverType(), SchemaMigrator.HAPI_FHIR_MIGRATION_TABLENAME);
|
||||
|
||||
myHapiMigrationDao.createMigrationTableIfRequired();
|
||||
myHapiMigrationStorageSvc = new HapiMigrationStorageSvc(myHapiMigrationDao);
|
||||
|
Loading…
x
Reference in New Issue
Block a user