Fix JPA nullable primitive columns (#5926)
* Fix JPA nullable primitive columns * Add changelog * Spotless * License headers * Migration fix * Spotless * Cleanup * Cleanup * Add task skipping * Update docs * CLeanup * Spotless * Address review comments * Test fix * HAPI FHIR version bump
This commit is contained in:
parent
ec0021cd40
commit
47d6e357b6
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-bom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
<name>HAPI FHIR BOM</name>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -26,8 +26,6 @@ import org.apache.commons.cli.CommandLine;
|
|||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -40,12 +38,12 @@ import static org.apache.commons.lang3.StringUtils.defaultString;
|
|||
* NB since 2019-12-05: This class is kind of weirdly named now, since it can either use Flyway or not use Flyway
|
||||
*/
|
||||
public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends BaseCommand {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseFlywayMigrateDatabaseCommand.class);
|
||||
|
||||
public static final String MIGRATE_DATABASE = "migrate-database";
|
||||
public static final String NO_COLUMN_SHRINK = "no-column-shrink";
|
||||
public static final String STRICT_ORDER = "strict-order";
|
||||
public static final String SKIP_VERSIONS = "skip-versions";
|
||||
public static final String ENABLE_HEAVYWEIGHT_MIGRATIONS = "enable-heavyweight-migrations";
|
||||
|
||||
private Set<String> myFlags;
|
||||
private String myMigrationTableName;
|
||||
|
||||
|
@ -100,6 +98,12 @@ public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends B
|
|||
SKIP_VERSIONS,
|
||||
"Versions",
|
||||
"A comma separated list of schema versions to skip. E.g. 4_1_0.20191214.2,4_1_0.20191214.4");
|
||||
addOptionalOption(
|
||||
retVal,
|
||||
null,
|
||||
ENABLE_HEAVYWEIGHT_MIGRATIONS,
|
||||
false,
|
||||
"If this flag is set, additional migration tasks will be executed that are considered unnecessary to execute on a database with a significant amount of data loaded. This option is not generally necessary.");
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
@ -125,6 +129,7 @@ public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends B
|
|||
|
||||
boolean dryRun = theCommandLine.hasOption("r");
|
||||
boolean noColumnShrink = theCommandLine.hasOption(BaseFlywayMigrateDatabaseCommand.NO_COLUMN_SHRINK);
|
||||
boolean runHeavyweight = theCommandLine.hasOption(ENABLE_HEAVYWEIGHT_MIGRATIONS);
|
||||
|
||||
String flags = theCommandLine.getOptionValue("x");
|
||||
myFlags = Arrays.stream(defaultString(flags).split(","))
|
||||
|
@ -139,6 +144,7 @@ public abstract class BaseFlywayMigrateDatabaseCommand<T extends Enum> extends B
|
|||
|
||||
migrator.createMigrationTableIfRequired();
|
||||
migrator.setDryRun(dryRun);
|
||||
migrator.setRunHeavyweightSkippableTasks(runHeavyweight);
|
||||
migrator.setNoColumnShrink(noColumnShrink);
|
||||
String skipVersions = theCommandLine.getOptionValue(BaseFlywayMigrateDatabaseCommand.SKIP_VERSIONS);
|
||||
addTasks(migrator, skipVersions);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 5926
|
||||
title: "A number of columns in the JPA schema use primitive types (and therefore can never have a null value) but aren't marked as non-null."
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 5926
|
||||
title: "A regression in HAPI FHIR 6.4.0 meant that ther JPA server schema migrator ran all tasks
|
||||
even when the database was initially empty and the schema was being initialized by script.
|
||||
This did not produce any incorrect results, but did impact the amount of time taken to initialize
|
||||
an empty database. This has been corrected."
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -119,13 +119,13 @@ public class Batch2JobInstanceEntity implements Serializable {
|
|||
@Column(name = "WORK_CHUNKS_PURGED", nullable = false)
|
||||
private boolean myWorkChunksPurged;
|
||||
|
||||
@Column(name = "PROGRESS_PCT")
|
||||
@Column(name = "PROGRESS_PCT", nullable = false)
|
||||
private double myProgress;
|
||||
|
||||
@Column(name = "ERROR_MSG", length = ERROR_MSG_MAX_LENGTH, nullable = true)
|
||||
private String myErrorMessage;
|
||||
|
||||
@Column(name = "ERROR_COUNT")
|
||||
@Column(name = "ERROR_COUNT", nullable = false)
|
||||
private int myErrorCount;
|
||||
|
||||
@Column(name = "EST_REMAINING", length = TIME_REMAINING_LENGTH, nullable = true)
|
||||
|
|
|
@ -138,6 +138,10 @@ public class Batch2WorkChunkEntity implements Serializable {
|
|||
|
||||
/**
|
||||
* The number of times the work chunk has had its state set back to POLL_WAITING.
|
||||
* <p>
|
||||
* TODO: Note that this column was added in 7.2.0, so it is nullable in order to
|
||||
* account for existing rows that were added before the column was added. In
|
||||
* the future we should make this non-null.
|
||||
*/
|
||||
@Column(name = "POLL_ATTEMPTS", nullable = true)
|
||||
private Integer myPollAttempts;
|
||||
|
@ -145,7 +149,9 @@ public class Batch2WorkChunkEntity implements Serializable {
|
|||
/**
|
||||
* Default constructor for Hibernate.
|
||||
*/
|
||||
public Batch2WorkChunkEntity() {}
|
||||
public Batch2WorkChunkEntity() {
|
||||
myPollAttempts = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Projection constructor for no-data path.
|
||||
|
@ -184,7 +190,7 @@ public class Batch2WorkChunkEntity implements Serializable {
|
|||
myRecordsProcessed = theRecordsProcessed;
|
||||
myWarningMessage = theWarningMessage;
|
||||
myNextPollTime = theNextPollTime;
|
||||
myPollAttempts = thePollAttempts;
|
||||
myPollAttempts = thePollAttempts != null ? thePollAttempts : 0;
|
||||
}
|
||||
|
||||
public static Batch2WorkChunkEntity fromWorkChunk(WorkChunk theWorkChunk) {
|
||||
|
|
|
@ -58,7 +58,7 @@ public class HapiFhirEnversRevision implements Serializable {
|
|||
@SequenceGenerator(name = "SEQ_HFJ_REVINFO", sequenceName = "SEQ_HFJ_REVINFO")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_HFJ_REVINFO")
|
||||
@RevisionNumber
|
||||
@Column(name = "REV")
|
||||
@Column(name = "REV", nullable = false)
|
||||
private long myRev;
|
||||
|
||||
@RevisionTimestamp
|
||||
|
|
|
@ -117,11 +117,12 @@ public class TermConcept implements Serializable {
|
|||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(
|
||||
name = "CODESYSTEM_PID",
|
||||
nullable = false,
|
||||
referencedColumnName = "PID",
|
||||
foreignKey = @ForeignKey(name = "FK_CONCEPT_PID_CS_PID"))
|
||||
private TermCodeSystemVersion myCodeSystem;
|
||||
|
||||
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false)
|
||||
@Column(name = "CODESYSTEM_PID", insertable = false, updatable = false, nullable = false)
|
||||
@GenericField(name = "myCodeSystemVersionPid")
|
||||
private long myCodeSystemVersionPid;
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ import ca.uhn.fhir.jpa.entity.BulkImportJobEntity;
|
|||
import ca.uhn.fhir.jpa.entity.Search;
|
||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.ArbitrarySqlTask;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.CalculateHashesTask;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.CalculateOrdinalDatesTask;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeEnum;
|
||||
|
@ -33,6 +32,7 @@ import ca.uhn.fhir.jpa.migrate.taskdef.ForceIdMigrationCopyTask;
|
|||
import ca.uhn.fhir.jpa.migrate.taskdef.ForceIdMigrationFixTask;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.BaseMigrationTasks;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.Builder;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
|
@ -135,6 +135,121 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
.toColumn("RES_ID")
|
||||
.references("HFJ_RESOURCE", "RES_ID");
|
||||
}
|
||||
|
||||
/*
|
||||
* Make a bunch of columns non-nullable. Note that we won't actually apply this migration
|
||||
* on the live system as it would take a loooooong time to execute these on heavily loaded
|
||||
* databases.
|
||||
*/
|
||||
// Skipping numbers 20240601.1 and 20240601.2 as they were found to not
|
||||
// be needed during code review.
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.3", "SP_HAS_LINKS")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.4", "SP_COORDS_PRESENT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.5", "SP_DATE_PRESENT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.6", "SP_NUMBER_PRESENT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.7", "SP_QUANTITY_PRESENT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.8", "SP_QUANTITY_NRML_PRESENT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.9", "SP_STRING_PRESENT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.10", "SP_TOKEN_PRESENT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.11", "SP_URI_PRESENT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20240601.12", "RES_VER")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("TRM_CONCEPT")
|
||||
.modifyColumn("20240601.13", "CODESYSTEM_PID")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("BT2_JOB_INSTANCE")
|
||||
.modifyColumn("20240601.14", "PROGRESS_PCT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.DOUBLE)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("BT2_JOB_INSTANCE")
|
||||
.modifyColumn("20240601.15", "ERROR_COUNT")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.INT)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_BINARY_STORAGE_BLOB")
|
||||
.modifyColumn("20240601.16", "BLOB_SIZE")
|
||||
.nonNullable()
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.heavyweightSkipByDefault()
|
||||
.failureAllowed();
|
||||
|
||||
/*
|
||||
* Add RES_ID to two indexes on HFJ_RES_VER which support history operations.
|
||||
* This makes server and type level _history work properly on large databases
|
||||
* on postgres. These are both marked as heavyweightSkipByDefault because the
|
||||
* necessary reindexing would be very expensive for a rarely used FHIR feature.
|
||||
*/
|
||||
version.onTable("HFJ_RES_VER")
|
||||
.dropIndex("20240601.17", "IDX_RESVER_TYPE_DATE")
|
||||
.heavyweightSkipByDefault();
|
||||
version.onTable("HFJ_RES_VER")
|
||||
.addIndex("20240601.18", "IDX_RESVER_TYPE_DATE")
|
||||
.unique(false)
|
||||
.withColumns("RES_TYPE", "RES_UPDATED", "RES_ID")
|
||||
.heavyweightSkipByDefault();
|
||||
version.onTable("HFJ_RES_VER")
|
||||
.dropIndex("20240601.19", "IDX_RESVER_DATE")
|
||||
.heavyweightSkipByDefault();
|
||||
version.onTable("HFJ_RES_VER")
|
||||
.addIndex("20240601.20", "IDX_RESVER_DATE")
|
||||
.unique(false)
|
||||
.withColumns("RES_UPDATED", "RES_ID")
|
||||
.heavyweightSkipByDefault();
|
||||
}
|
||||
|
||||
protected void init720() {
|
||||
|
@ -162,15 +277,15 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
binaryStorageBlobTable
|
||||
.renameColumn("20240404.1", "BLOB_ID", "CONTENT_ID")
|
||||
.getLastAddedTask()
|
||||
.ifPresent(BaseTask::doNothing);
|
||||
.ifPresent(t -> t.addFlag(TaskFlagEnum.DO_NOTHING));
|
||||
binaryStorageBlobTable
|
||||
.renameColumn("20240404.2", "BLOB_SIZE", "CONTENT_SIZE")
|
||||
.getLastAddedTask()
|
||||
.ifPresent(BaseTask::doNothing);
|
||||
.ifPresent(t -> t.addFlag(TaskFlagEnum.DO_NOTHING));
|
||||
binaryStorageBlobTable
|
||||
.renameColumn("20240404.3", "BLOB_HASH", "CONTENT_HASH")
|
||||
.getLastAddedTask()
|
||||
.ifPresent(BaseTask::doNothing);
|
||||
.ifPresent(t -> t.addFlag(TaskFlagEnum.DO_NOTHING));
|
||||
|
||||
binaryStorageBlobTable
|
||||
.modifyColumn("20240404.4", "BLOB_DATA")
|
||||
|
@ -262,7 +377,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
|
||||
// Move forced_id constraints to hfj_resource and the new fhir_id column
|
||||
// Note: we leave the HFJ_FORCED_ID.IDX_FORCEDID_TYPE_FID index in place to support old writers for a while.
|
||||
version.addTask(new ForceIdMigrationCopyTask(version.getRelease(), "20231018.1").setDoNothing(true));
|
||||
version.addTask(
|
||||
new ForceIdMigrationCopyTask(version.getRelease(), "20231018.1").addFlag(TaskFlagEnum.DO_NOTHING));
|
||||
|
||||
Builder.BuilderWithTableName hfjResource = version.onTable("HFJ_RESOURCE");
|
||||
// commented out to make numeric space for the fix task below.
|
||||
|
@ -331,7 +447,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
}
|
||||
|
||||
// This fix was bad for MSSQL, it has been set to do nothing.
|
||||
version.addTask(new ForceIdMigrationFixTask(version.getRelease(), "20231213.1").setDoNothing(true));
|
||||
version.addTask(
|
||||
new ForceIdMigrationFixTask(version.getRelease(), "20231213.1").addFlag(TaskFlagEnum.DO_NOTHING));
|
||||
|
||||
// This fix will work for MSSQL or Oracle.
|
||||
version.addTask(new ForceIdMigrationFixTask(version.getRelease(), "20231222.1"));
|
||||
|
@ -814,8 +931,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_RES_VER")
|
||||
.modifyColumn("20230421.1", "RES_TEXT_VC")
|
||||
.nullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.TEXT);
|
||||
.withType(ColumnTypeEnum.TEXT)
|
||||
.failureAllowed();
|
||||
|
||||
{
|
||||
// add hash_norm to res_id to speed up joins on a second string.
|
||||
|
@ -1751,8 +1868,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_RES_LINK")
|
||||
.modifyColumn("20210505.1", "SRC_PATH")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 500);
|
||||
.withType(ColumnTypeEnum.STRING, 500)
|
||||
.failureAllowed();
|
||||
}
|
||||
|
||||
private void init530() {
|
||||
|
@ -1813,8 +1930,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
quantityTable
|
||||
.modifyColumn("20210116.1", "SP_VALUE")
|
||||
.nullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.DOUBLE);
|
||||
.withType(ColumnTypeEnum.DOUBLE)
|
||||
.failureAllowed();
|
||||
|
||||
// HFJ_RES_LINK
|
||||
version.onTable("HFJ_RES_LINK")
|
||||
|
@ -2011,8 +2128,8 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_RES_VER")
|
||||
.modifyColumn("20200220.1", "RES_ID")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.LONG);
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.failureAllowed();
|
||||
//
|
||||
|
||||
// Drop unused column
|
||||
|
@ -2168,38 +2285,38 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_SPIDX_STRING")
|
||||
.modifyColumn("20200420.36", "SP_MISSING")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.BOOLEAN);
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_COORDS")
|
||||
.modifyColumn("20200420.37", "SP_MISSING")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.BOOLEAN);
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_NUMBER")
|
||||
.modifyColumn("20200420.38", "SP_MISSING")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.BOOLEAN);
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_TOKEN")
|
||||
.modifyColumn("20200420.39", "SP_MISSING")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.BOOLEAN);
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_DATE")
|
||||
.modifyColumn("20200420.40", "SP_MISSING")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.BOOLEAN);
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_URI")
|
||||
.modifyColumn("20200420.41", "SP_MISSING")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.BOOLEAN);
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_QUANTITY")
|
||||
.modifyColumn("20200420.42", "SP_MISSING")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.BOOLEAN);
|
||||
.withType(ColumnTypeEnum.BOOLEAN)
|
||||
.failureAllowed();
|
||||
|
||||
// Add support for integer comparisons during day-precision date search.
|
||||
Builder.BuilderWithTableName spidxDate = version.onTable("HFJ_SPIDX_DATE");
|
||||
|
@ -2309,38 +2426,38 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_SPIDX_NUMBER")
|
||||
.modifyColumn("20190920.1", "RES_ID")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.LONG);
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_COORDS")
|
||||
.modifyColumn("20190920.2", "RES_ID")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.LONG);
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_TOKEN")
|
||||
.modifyColumn("20190920.3", "RES_ID")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.LONG);
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_STRING")
|
||||
.modifyColumn("20190920.4", "RES_ID")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.LONG);
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_DATE")
|
||||
.modifyColumn("20190920.5", "RES_ID")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.LONG);
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_QUANTITY")
|
||||
.modifyColumn("20190920.6", "RES_ID")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.LONG);
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_URI")
|
||||
.modifyColumn("20190920.7", "RES_ID")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.LONG);
|
||||
.withType(ColumnTypeEnum.LONG)
|
||||
.failureAllowed();
|
||||
|
||||
// HFJ_SEARCH
|
||||
version.onTable("HFJ_SEARCH")
|
||||
|
@ -2469,33 +2586,33 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_RESOURCE")
|
||||
.modifyColumn("20191002.1", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 40);
|
||||
.withType(ColumnTypeEnum.STRING, 40)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RES_VER")
|
||||
.modifyColumn("20191002.2", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 40);
|
||||
.withType(ColumnTypeEnum.STRING, 40)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_HISTORY_TAG")
|
||||
.modifyColumn("20191002.3", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 40);
|
||||
.withType(ColumnTypeEnum.STRING, 40)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RES_LINK")
|
||||
.modifyColumn("20191002.4", "SOURCE_RESOURCE_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 40);
|
||||
.withType(ColumnTypeEnum.STRING, 40)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RES_LINK")
|
||||
.modifyColumn("20191002.5", "TARGET_RESOURCE_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 40);
|
||||
.withType(ColumnTypeEnum.STRING, 40)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_RES_TAG")
|
||||
.modifyColumn("20191002.6", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 40);
|
||||
.withType(ColumnTypeEnum.STRING, 40)
|
||||
.failureAllowed();
|
||||
|
||||
// TermConceptDesignation
|
||||
version.startSectionWithMessage("Processing table: TRM_CONCEPT_DESIG");
|
||||
|
@ -2765,18 +2882,18 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_SPIDX_COORDS")
|
||||
.modifyColumn("20190814.9", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 100);
|
||||
.withType(ColumnTypeEnum.STRING, 100)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_DATE")
|
||||
.modifyColumn("20190814.10", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 100);
|
||||
.withType(ColumnTypeEnum.STRING, 100)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_STRING")
|
||||
.modifyColumn("20190814.11", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 100);
|
||||
.withType(ColumnTypeEnum.STRING, 100)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_STRING")
|
||||
.addColumn("20190814.12", "HASH_IDENTITY")
|
||||
.nullable()
|
||||
|
@ -2788,50 +2905,50 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
version.onTable("HFJ_SPIDX_COORDS")
|
||||
.modifyColumn("20190814.14", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 100);
|
||||
.withType(ColumnTypeEnum.STRING, 100)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_QUANTITY")
|
||||
.modifyColumn("20190814.15", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 100);
|
||||
.withType(ColumnTypeEnum.STRING, 100)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_QUANTITY").dropColumn("20190814.16", "HASH_UNITS_AND_VALPREFIX");
|
||||
version.onTable("HFJ_SPIDX_QUANTITY").dropColumn("20190814.17", "HASH_VALPREFIX");
|
||||
version.onTable("HFJ_SPIDX_NUMBER")
|
||||
.modifyColumn("20190814.18", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 100);
|
||||
.withType(ColumnTypeEnum.STRING, 100)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_TOKEN")
|
||||
.modifyColumn("20190814.19", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 100);
|
||||
.withType(ColumnTypeEnum.STRING, 100)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_URI")
|
||||
.modifyColumn("20190814.20", "RES_TYPE")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 100);
|
||||
.withType(ColumnTypeEnum.STRING, 100)
|
||||
.failureAllowed();
|
||||
version.onTable("HFJ_SPIDX_URI")
|
||||
.modifyColumn("20190814.21", "SP_URI")
|
||||
.nullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 254);
|
||||
.withType(ColumnTypeEnum.STRING, 254)
|
||||
.failureAllowed();
|
||||
version.onTable("TRM_CODESYSTEM")
|
||||
.modifyColumn("20190814.22", "CODE_SYSTEM_URI")
|
||||
.nonNullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 200);
|
||||
.withType(ColumnTypeEnum.STRING, 200)
|
||||
.failureAllowed();
|
||||
version.onTable("TRM_CODESYSTEM")
|
||||
.modifyColumn("20190814.23", "CS_NAME")
|
||||
.nullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 200);
|
||||
.withType(ColumnTypeEnum.STRING, 200)
|
||||
.failureAllowed();
|
||||
version.onTable("TRM_CODESYSTEM_VER")
|
||||
.modifyColumn("20190814.24", "CS_VERSION_ID")
|
||||
.nullable()
|
||||
.failureAllowed()
|
||||
.withType(ColumnTypeEnum.STRING, 200);
|
||||
.withType(ColumnTypeEnum.STRING, 200)
|
||||
.failureAllowed();
|
||||
}
|
||||
|
||||
private void init360() { // 20180918 - 20181112
|
||||
|
|
|
@ -524,8 +524,12 @@ public class InstanceReindexServiceImpl implements IInstanceReindexService {
|
|||
String theParamTypeName) {
|
||||
Parameters.ParametersParameterComponent retVal =
|
||||
super.addIndexValue(theAction, theParent, theParam, theParamTypeName);
|
||||
if (theParam.getLatitude() != null) {
|
||||
retVal.addPart().setName("Latitude").setValue(new DecimalType(theParam.getLatitude()));
|
||||
}
|
||||
if (theParam.getLongitude() != null) {
|
||||
retVal.addPart().setName("Longitude").setValue(new DecimalType(theParam.getLongitude()));
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -45,7 +45,7 @@ public class BinaryStorageEntity {
|
|||
@Column(name = "RESOURCE_ID", length = 100, nullable = false)
|
||||
private String myResourceId;
|
||||
|
||||
@Column(name = "BLOB_SIZE", nullable = true)
|
||||
@Column(name = "BLOB_SIZE", nullable = false)
|
||||
private long mySize;
|
||||
|
||||
@Column(name = "CONTENT_TYPE", nullable = false, length = 100)
|
||||
|
|
|
@ -60,9 +60,9 @@ import java.util.Collection;
|
|||
columnNames = {"RES_ID", "RES_VER"})
|
||||
},
|
||||
indexes = {
|
||||
@Index(name = "IDX_RESVER_TYPE_DATE", columnList = "RES_TYPE,RES_UPDATED"),
|
||||
@Index(name = "IDX_RESVER_TYPE_DATE", columnList = "RES_TYPE,RES_UPDATED,RES_ID"),
|
||||
@Index(name = "IDX_RESVER_ID_DATE", columnList = "RES_ID,RES_UPDATED"),
|
||||
@Index(name = "IDX_RESVER_DATE", columnList = "RES_UPDATED")
|
||||
@Index(name = "IDX_RESVER_DATE", columnList = "RES_UPDATED,RES_ID")
|
||||
})
|
||||
public class ResourceHistoryTable extends BaseHasResource implements Serializable {
|
||||
public static final String IDX_RESVER_ID_VER = "IDX_RESVER_ID_VER";
|
||||
|
|
|
@ -135,12 +135,14 @@ public class ResourceIndexedComboStringUnique extends BasePartitionable
|
|||
myIndexString = theIndexString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTable getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResource(ResourceTable theResource) {
|
||||
Validate.notNull(theResource);
|
||||
Validate.notNull(theResource, "theResource must not be null");
|
||||
myResource = theResource;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.model.entity;
|
|||
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.Entity;
|
||||
|
@ -56,13 +57,11 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
|
|||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Column(name = "SP_LATITUDE")
|
||||
// @FullTextField
|
||||
public double myLatitude;
|
||||
@Column(name = "SP_LATITUDE", nullable = true)
|
||||
public Double myLatitude;
|
||||
|
||||
@Column(name = "SP_LONGITUDE")
|
||||
// @FullTextField
|
||||
public double myLongitude;
|
||||
@Column(name = "SP_LONGITUDE", nullable = true)
|
||||
public Double myLongitude;
|
||||
|
||||
@Id
|
||||
@SequenceGenerator(name = "SEQ_SPIDX_COORDS", sequenceName = "SEQ_SPIDX_COORDS")
|
||||
|
@ -162,7 +161,8 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
|
|||
myId = theId;
|
||||
}
|
||||
|
||||
public double getLatitude() {
|
||||
@Nullable
|
||||
public Double getLatitude() {
|
||||
return myLatitude;
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,8 @@ public class ResourceIndexedSearchParamCoords extends BaseResourceIndexedSearchP
|
|||
return this;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
@Nullable
|
||||
public Double getLongitude() {
|
||||
return myLongitude;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@OptimisticLock(excluded = true)
|
||||
private String myHashSha256;
|
||||
|
||||
@Column(name = "SP_HAS_LINKS")
|
||||
@Column(name = "SP_HAS_LINKS", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private boolean myHasLinks;
|
||||
|
||||
|
@ -203,7 +203,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedSearchParamCoords> myParamsCoords;
|
||||
|
||||
@Column(name = "SP_COORDS_PRESENT")
|
||||
@Column(name = "SP_COORDS_PRESENT", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private boolean myParamsCoordsPopulated;
|
||||
|
||||
|
@ -215,7 +215,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedSearchParamDate> myParamsDate;
|
||||
|
||||
@Column(name = "SP_DATE_PRESENT")
|
||||
@Column(name = "SP_DATE_PRESENT", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private boolean myParamsDatePopulated;
|
||||
|
||||
|
@ -227,7 +227,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
orphanRemoval = false)
|
||||
private Collection<ResourceIndexedSearchParamNumber> myParamsNumber;
|
||||
|
||||
@Column(name = "SP_NUMBER_PRESENT")
|
||||
@Column(name = "SP_NUMBER_PRESENT", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private boolean myParamsNumberPopulated;
|
||||
|
||||
|
@ -239,7 +239,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedSearchParamQuantity> myParamsQuantity;
|
||||
|
||||
@Column(name = "SP_QUANTITY_PRESENT")
|
||||
@Column(name = "SP_QUANTITY_PRESENT", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private boolean myParamsQuantityPopulated;
|
||||
|
||||
|
@ -260,7 +260,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
* NOTE : use Boolean class instead of boolean primitive, in order to set the existing rows to null
|
||||
* since 5.3.0
|
||||
*/
|
||||
@Column(name = "SP_QUANTITY_NRML_PRESENT")
|
||||
@Column(name = "SP_QUANTITY_NRML_PRESENT", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private Boolean myParamsQuantityNormalizedPopulated = Boolean.FALSE;
|
||||
|
||||
|
@ -272,7 +272,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedSearchParamString> myParamsString;
|
||||
|
||||
@Column(name = "SP_STRING_PRESENT")
|
||||
@Column(name = "SP_STRING_PRESENT", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private boolean myParamsStringPopulated;
|
||||
|
||||
|
@ -284,7 +284,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedSearchParamToken> myParamsToken;
|
||||
|
||||
@Column(name = "SP_TOKEN_PRESENT")
|
||||
@Column(name = "SP_TOKEN_PRESENT", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private boolean myParamsTokenPopulated;
|
||||
|
||||
|
@ -296,7 +296,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedSearchParamUri> myParamsUri;
|
||||
|
||||
@Column(name = "SP_URI_PRESENT")
|
||||
@Column(name = "SP_URI_PRESENT", nullable = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private boolean myParamsUriPopulated;
|
||||
|
||||
|
@ -404,7 +404,7 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
private Boolean mySearchUrlPresent = false;
|
||||
|
||||
@Version
|
||||
@Column(name = "RES_VER")
|
||||
@Column(name = "RES_VER", nullable = false)
|
||||
private long myVersion;
|
||||
|
||||
@OneToMany(mappedBy = "myResourceTable", fetch = FetchType.LAZY)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
@ -21,7 +21,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-caching-api</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -23,6 +23,7 @@ import ca.uhn.fhir.i18n.Msg;
|
|||
import ca.uhn.fhir.jpa.migrate.dao.HapiMigrationDao;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.InitializeSchemaTask;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum;
|
||||
import ca.uhn.fhir.system.HapiSystemProperties;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -44,6 +45,7 @@ public class HapiMigrator {
|
|||
private static final Logger ourLog = LoggerFactory.getLogger(HapiMigrator.class);
|
||||
private final MigrationTaskList myTaskList = new MigrationTaskList();
|
||||
private boolean myDryRun;
|
||||
private boolean myRunHeavyweightSkippableTasks;
|
||||
private boolean myNoColumnShrink;
|
||||
private final DriverTypeEnum myDriverType;
|
||||
private final DataSource myDataSource;
|
||||
|
@ -69,6 +71,24 @@ public class HapiMigrator {
|
|||
myDryRun = theDryRun;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we run the tasks marked with {@link ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum#HEAVYWEIGHT_SKIP_BY_DEFAULT}
|
||||
*
|
||||
* @since 7.4.0
|
||||
*/
|
||||
public boolean isRunHeavyweightSkippableTasks() {
|
||||
return myRunHeavyweightSkippableTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we run the tasks marked with {@link ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum#HEAVYWEIGHT_SKIP_BY_DEFAULT}
|
||||
*
|
||||
* @since 7.4.0
|
||||
*/
|
||||
public void setRunHeavyweightSkippableTasks(boolean theRunHeavyweightSkippableTasks) {
|
||||
myRunHeavyweightSkippableTasks = theRunHeavyweightSkippableTasks;
|
||||
}
|
||||
|
||||
public boolean isNoColumnShrink() {
|
||||
return myNoColumnShrink;
|
||||
}
|
||||
|
@ -131,14 +151,27 @@ public class HapiMigrator {
|
|||
try (DriverTypeEnum.ConnectionProperties connectionProperties =
|
||||
getDriverType().newConnectionProperties(getDataSource())) {
|
||||
|
||||
newTaskList.forEach(next -> {
|
||||
if (!isRunHeavyweightSkippableTasks()) {
|
||||
newTaskList.removeIf(BaseTask::isHeavyweightSkippableTask);
|
||||
}
|
||||
|
||||
boolean initializedSchema = false;
|
||||
for (BaseTask next : newTaskList) {
|
||||
if (initializedSchema && !next.hasFlag(TaskFlagEnum.RUN_DURING_SCHEMA_INITIALIZATION)) {
|
||||
ourLog.info("Skipping task {} because schema is being initialized", next.getMigrationVersion());
|
||||
recordTaskAsCompletedIfNotDryRun(next, 0L, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
next.setDriverType(getDriverType());
|
||||
next.setDryRun(isDryRun());
|
||||
next.setNoColumnShrink(isNoColumnShrink());
|
||||
next.setConnectionProperties(connectionProperties);
|
||||
|
||||
executeTask(next, retval);
|
||||
});
|
||||
|
||||
initializedSchema |= next.initializedSchema();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ourLog.error("Migration failed", e);
|
||||
|
@ -167,13 +200,13 @@ public class HapiMigrator {
|
|||
}
|
||||
preExecute(theTask);
|
||||
theTask.execute();
|
||||
postExecute(theTask, sw, true);
|
||||
recordTaskAsCompletedIfNotDryRun(theTask, sw.getMillis(), true);
|
||||
theMigrationResult.changes += theTask.getChangesCount();
|
||||
theMigrationResult.executedStatements.addAll(theTask.getExecutedStatements());
|
||||
theMigrationResult.succeededTasks.add(theTask);
|
||||
} catch (SQLException | HapiMigrationException e) {
|
||||
theMigrationResult.failedTasks.add(theTask);
|
||||
postExecute(theTask, sw, false);
|
||||
recordTaskAsCompletedIfNotDryRun(theTask, sw.getMillis(), false);
|
||||
String description = theTask.getDescription();
|
||||
if (isBlank(description)) {
|
||||
description = theTask.getClass().getSimpleName();
|
||||
|
@ -187,9 +220,9 @@ public class HapiMigrator {
|
|||
myCallbacks.forEach(action -> action.preExecution(theTask));
|
||||
}
|
||||
|
||||
private void postExecute(BaseTask theNext, StopWatch theStopWatch, boolean theSuccess) {
|
||||
private void recordTaskAsCompletedIfNotDryRun(BaseTask theNext, long theExecutionMillis, boolean theSuccess) {
|
||||
if (!theNext.isDryRun()) {
|
||||
myHapiMigrationStorageSvc.saveTask(theNext, Math.toIntExact(theStopWatch.getMillis()), theSuccess);
|
||||
myHapiMigrationStorageSvc.saveTask(theNext, Math.toIntExact(theExecutionMillis), theSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,7 +244,7 @@ public class HapiMigrator {
|
|||
}
|
||||
|
||||
public void setCallbacks(@Nonnull List<IHapiMigrationCallback> theCallbacks) {
|
||||
Validate.notNull(theCallbacks);
|
||||
Validate.notNull(theCallbacks, "theCallbacks must not be null");
|
||||
myCallbacks = theCallbacks;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MigrationTaskList implements Iterable<BaseTask> {
|
||||
|
@ -95,4 +96,12 @@ public class MigrationTaskList implements Iterable<BaseTask> {
|
|||
.reduce((first, second) -> second)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public void removeIf(Predicate<BaseTask> theFilter) {
|
||||
myTasks.removeIf(theFilter);
|
||||
}
|
||||
|
||||
public BaseTask[] toTaskArray() {
|
||||
return myTasks.toArray(new BaseTask[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package ca.uhn.fhir.jpa.migrate;
|
||||
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -49,7 +50,7 @@ public class MigrationTaskSkipper {
|
|||
for (BaseTask task : theTasks) {
|
||||
if (skippedVersionSet.contains(task.getMigrationVersion())) {
|
||||
ourLog.info("Will skip {}: {}", task.getMigrationVersion(), task.getDescription());
|
||||
task.setDoNothing(true);
|
||||
task.addFlag(TaskFlagEnum.DO_NOTHING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,12 +35,6 @@ public class AddColumnTask extends BaseTableColumnTypeTask {
|
|||
return new AddColumnTask(null, null, ColumnNameCase.ALL_LOWER, theColumnDriverMappingOverrides);
|
||||
}
|
||||
|
||||
public AddColumnTask() {
|
||||
this(null, null);
|
||||
setDryRun(true);
|
||||
myCheckForExistingTables = false;
|
||||
}
|
||||
|
||||
public AddColumnTask(String theProductVersion, String theSchemaVersion) {
|
||||
super(theProductVersion, theSchemaVersion);
|
||||
}
|
||||
|
@ -84,6 +78,7 @@ public class AddColumnTask extends BaseTableColumnTypeTask {
|
|||
break;
|
||||
case DERBY_EMBEDDED:
|
||||
case POSTGRES_9_4:
|
||||
case COCKROACHDB_21_1:
|
||||
sql = "alter table " + getTableName() + " add column " + getColumnName() + " " + typeStatement;
|
||||
break;
|
||||
case MSSQL_2012:
|
||||
|
|
|
@ -56,7 +56,7 @@ public class AddTableByColumnTask extends BaseTableTask {
|
|||
this(theProductVersion, theSchemaVersion, null);
|
||||
}
|
||||
|
||||
private AddTableByColumnTask(
|
||||
public AddTableByColumnTask(
|
||||
String theProductVersion, String theSchemaVersion, Comparator<AddColumnTask> theColumnSortingRules) {
|
||||
super(theProductVersion, theSchemaVersion);
|
||||
myColumnSortingRules = theColumnSortingRules;
|
||||
|
|
|
@ -46,6 +46,9 @@ public class ArbitrarySqlTask extends BaseTask {
|
|||
private String myExecuteOnlyIfTableExists;
|
||||
private List<TableAndColumn> myConditionalOnExistenceOf = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ArbitrarySqlTask(VersionEnum theRelease, String theVersion, String theTableName, String theDescription) {
|
||||
super(theRelease.toString(), theVersion);
|
||||
myTableName = theTableName;
|
||||
|
|
|
@ -22,10 +22,14 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
|
|||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.HapiMigrationException;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum;
|
||||
import ca.uhn.fhir.system.HapiSystemProperties;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.flywaydb.core.api.MigrationVersion;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -38,6 +42,7 @@ import java.sql.SQLException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -51,11 +56,42 @@ public abstract class BaseTask {
|
|||
private static final Pattern versionPattern = Pattern.compile(MIGRATION_VERSION_PATTERN);
|
||||
private final String myProductVersion;
|
||||
private final String mySchemaVersion;
|
||||
private final List<ExecuteTaskPrecondition> myPreconditions = new ArrayList<>();
|
||||
private final EnumSet<TaskFlagEnum> myFlags = EnumSet.noneOf(TaskFlagEnum.class);
|
||||
private final List<ExecutedStatement> myExecutedStatements = new ArrayList<>();
|
||||
/**
|
||||
* Whether to check for existing tables
|
||||
* before generating SQL
|
||||
*/
|
||||
protected boolean myCheckForExistingTables = true;
|
||||
/**
|
||||
* Whether to generate the SQL in a 'readable format'
|
||||
*/
|
||||
protected boolean myPrettyPrint = false;
|
||||
|
||||
private DriverTypeEnum.ConnectionProperties myConnectionProperties;
|
||||
private DriverTypeEnum myDriverType;
|
||||
private String myDescription;
|
||||
private Integer myChangesCount = 0;
|
||||
private boolean myDryRun;
|
||||
private boolean myTransactional = true;
|
||||
private Set<DriverTypeEnum> myOnlyAppliesToPlatforms = new HashSet<>();
|
||||
private boolean myNoColumnShrink;
|
||||
|
||||
protected BaseTask(String theProductVersion, String theSchemaVersion) {
|
||||
myProductVersion = theProductVersion;
|
||||
mySchemaVersion = theSchemaVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a flag if it's not already present, otherwise this call is ignored.
|
||||
*
|
||||
* @param theFlag The flag, must not be null
|
||||
*/
|
||||
public BaseTask addFlag(@Nonnull TaskFlagEnum theFlag) {
|
||||
myFlags.add(theFlag);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some migrations can not be run in a transaction.
|
||||
|
@ -65,48 +101,12 @@ public abstract class BaseTask {
|
|||
myTransactional = theTransactional;
|
||||
}
|
||||
|
||||
private boolean myTransactional = true;
|
||||
private boolean myDoNothing;
|
||||
private List<ExecutedStatement> myExecutedStatements = new ArrayList<>();
|
||||
private Set<DriverTypeEnum> myOnlyAppliesToPlatforms = new HashSet<>();
|
||||
private boolean myNoColumnShrink;
|
||||
private boolean myFailureAllowed;
|
||||
private boolean myRunDuringSchemaInitialization;
|
||||
/**
|
||||
* Whether or not to check for existing tables
|
||||
* before generating SQL
|
||||
*/
|
||||
protected boolean myCheckForExistingTables = true;
|
||||
|
||||
/**
|
||||
* Whether or not to generate the SQL in a 'readable format'
|
||||
*/
|
||||
protected boolean myPrettyPrint = false;
|
||||
|
||||
protected BaseTask(String theProductVersion, String theSchemaVersion) {
|
||||
myProductVersion = theProductVersion;
|
||||
mySchemaVersion = theSchemaVersion;
|
||||
}
|
||||
|
||||
public boolean isRunDuringSchemaInitialization() {
|
||||
return myRunDuringSchemaInitialization;
|
||||
}
|
||||
|
||||
public void setPrettyPrint(boolean thePrettyPrint) {
|
||||
myPrettyPrint = thePrettyPrint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this task run even if we're doing the very first initialization of an empty schema. By
|
||||
* default we skip most tasks during that pass, since they just take up time and the
|
||||
* schema should be fully initialized by the {@link InitializeSchemaTask}
|
||||
*/
|
||||
public void setRunDuringSchemaInitialization(boolean theRunDuringSchemaInitialization) {
|
||||
myRunDuringSchemaInitialization = theRunDuringSchemaInitialization;
|
||||
}
|
||||
|
||||
public void setOnlyAppliesToPlatforms(Set<DriverTypeEnum> theOnlyAppliesToPlatforms) {
|
||||
Validate.notNull(theOnlyAppliesToPlatforms);
|
||||
Validate.notNull(theOnlyAppliesToPlatforms, "theOnlyAppliesToPlatforms must not be null");
|
||||
myOnlyAppliesToPlatforms = theOnlyAppliesToPlatforms;
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ public abstract class BaseTask {
|
|||
|
||||
private Integer doExecuteSqlList(List<String> theSqlStatements) {
|
||||
int changesCount = 0;
|
||||
for (String nextSql : theSqlStatements) {
|
||||
for (@Language("SQL") String nextSql : theSqlStatements) {
|
||||
changesCount += doExecuteSql(nextSql);
|
||||
}
|
||||
|
||||
|
@ -206,7 +206,7 @@ public abstract class BaseTask {
|
|||
}
|
||||
return changesCount;
|
||||
} catch (DataAccessException e) {
|
||||
if (myFailureAllowed) {
|
||||
if (myFlags.contains(TaskFlagEnum.FAILURE_ALLOWED)) {
|
||||
ourLog.info("Task {} did not exit successfully, but task is allowed to fail", getMigrationVersion());
|
||||
ourLog.debug("Error was: {}", e.getMessage(), e);
|
||||
return 0;
|
||||
|
@ -219,7 +219,7 @@ public abstract class BaseTask {
|
|||
|
||||
protected void captureExecutedStatement(
|
||||
String theTableName, @Language("SQL") String theSql, Object... theArguments) {
|
||||
myExecutedStatements.add(new ExecutedStatement(theTableName, theSql, theArguments));
|
||||
myExecutedStatements.add(new ExecutedStatement(mySchemaVersion, theTableName, theSql, theArguments));
|
||||
}
|
||||
|
||||
public DriverTypeEnum.ConnectionProperties getConnectionProperties() {
|
||||
|
@ -250,10 +250,8 @@ public abstract class BaseTask {
|
|||
return getConnectionProperties().newJdbcTemplate();
|
||||
}
|
||||
|
||||
private final List<ExecuteTaskPrecondition> myPreconditions = new ArrayList<>();
|
||||
|
||||
public void execute() throws SQLException {
|
||||
if (myDoNothing) {
|
||||
if (myFlags.contains(TaskFlagEnum.DO_NOTHING)) {
|
||||
ourLog.info("Skipping stubbed task: {}", getDescription());
|
||||
return;
|
||||
}
|
||||
|
@ -278,14 +276,6 @@ public abstract class BaseTask {
|
|||
|
||||
protected abstract void doExecute() throws SQLException;
|
||||
|
||||
protected boolean isFailureAllowed() {
|
||||
return myFailureAllowed;
|
||||
}
|
||||
|
||||
public void setFailureAllowed(boolean theFailureAllowed) {
|
||||
myFailureAllowed = theFailureAllowed;
|
||||
}
|
||||
|
||||
public String getMigrationVersion() {
|
||||
String releasePart = myProductVersion;
|
||||
if (releasePart.startsWith("V")) {
|
||||
|
@ -296,6 +286,7 @@ public abstract class BaseTask {
|
|||
return migrationVersion.getVersion();
|
||||
}
|
||||
|
||||
@SuppressWarnings("StringConcatenationArgumentToLogCall")
|
||||
protected void logInfo(Logger theLog, String theFormattedMessage, Object... theArguments) {
|
||||
theLog.info(getMigrationVersion() + ": " + theFormattedMessage, theArguments);
|
||||
}
|
||||
|
@ -308,23 +299,6 @@ public abstract class BaseTask {
|
|||
}
|
||||
}
|
||||
|
||||
public void doNothing() {
|
||||
setDoNothing(true);
|
||||
}
|
||||
|
||||
public void failureAllowed() {
|
||||
setFailureAllowed(true);
|
||||
}
|
||||
|
||||
public boolean isDoNothing() {
|
||||
return myDoNothing;
|
||||
}
|
||||
|
||||
public BaseTask setDoNothing(boolean theDoNothing) {
|
||||
myDoNothing = theDoNothing;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addPrecondition(ExecuteTaskPrecondition thePrecondition) {
|
||||
myPreconditions.add(thePrecondition);
|
||||
}
|
||||
|
@ -343,7 +317,6 @@ public abstract class BaseTask {
|
|||
if (theObject == null || getClass().equals(theObject.getClass()) == false) {
|
||||
return false;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
BaseTask otherObject = (BaseTask) theObject;
|
||||
|
||||
EqualsBuilder b = new EqualsBuilder();
|
||||
|
@ -357,17 +330,35 @@ public abstract class BaseTask {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isDoNothing() {
|
||||
return myFlags.contains(TaskFlagEnum.DO_NOTHING);
|
||||
}
|
||||
|
||||
public boolean isHeavyweightSkippableTask() {
|
||||
return myFlags.contains(TaskFlagEnum.HEAVYWEIGHT_SKIP_BY_DEFAULT);
|
||||
}
|
||||
|
||||
public boolean hasFlag(TaskFlagEnum theFlag) {
|
||||
return myFlags.contains(theFlag);
|
||||
}
|
||||
|
||||
public static class ExecutedStatement {
|
||||
private final String mySql;
|
||||
private final List<Object> myArguments;
|
||||
private final String myTableName;
|
||||
private final String mySchemaVersion;
|
||||
|
||||
public ExecutedStatement(String theDescription, String theSql, Object[] theArguments) {
|
||||
public ExecutedStatement(String theSchemaVersion, String theDescription, String theSql, Object[] theArguments) {
|
||||
mySchemaVersion = theSchemaVersion;
|
||||
myTableName = theDescription;
|
||||
mySql = theSql;
|
||||
myArguments = theArguments != null ? Arrays.asList(theArguments) : Collections.emptyList();
|
||||
}
|
||||
|
||||
public String getSchemaVersion() {
|
||||
return mySchemaVersion;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return myTableName;
|
||||
}
|
||||
|
@ -379,5 +370,14 @@ public abstract class BaseTask {
|
|||
public List<Object> getArguments() {
|
||||
return myArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
.append("tableName", myTableName)
|
||||
.append("sql", mySql)
|
||||
.append("arguments", myArguments)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,13 @@ public class ForceIdMigrationFixTask extends BaseTask {
|
|||
switch (getDriverType()) {
|
||||
case MSSQL_2012:
|
||||
return " where (fhir_id is null or DATALENGTH(fhir_id) > LEN(fhir_id)) ";
|
||||
case H2_EMBEDDED:
|
||||
case DERBY_EMBEDDED:
|
||||
case MARIADB_10_1:
|
||||
case MYSQL_5_7:
|
||||
case POSTGRES_9_4:
|
||||
case ORACLE_12C:
|
||||
case COCKROACHDB_21_1:
|
||||
default:
|
||||
return " where (fhir_id is null or fhir_id <> trim(fhir_id)) ";
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
|
|||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.JdbcUtils;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.ISchemaInitializationProvider;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -44,11 +45,7 @@ public class InitializeSchemaTask extends BaseTask {
|
|||
super(theProductVersion, theSchemaVersion);
|
||||
mySchemaInitializationProvider = theSchemaInitializationProvider;
|
||||
setDescription(DESCRIPTION_PREFIX + mySchemaInitializationProvider.getSchemaDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunDuringSchemaInitialization() {
|
||||
return true;
|
||||
addFlag(TaskFlagEnum.RUN_DURING_SCHEMA_INITIALIZATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,12 +99,12 @@ public class InitializeSchemaTask extends BaseTask {
|
|||
@Override
|
||||
protected void generateEquals(EqualsBuilder theBuilder, BaseTask theOtherObject) {
|
||||
InitializeSchemaTask otherObject = (InitializeSchemaTask) theOtherObject;
|
||||
theBuilder.append(mySchemaInitializationProvider, otherObject.mySchemaInitializationProvider);
|
||||
theBuilder.append(getSchemaInitializationProvider(), otherObject.getSchemaInitializationProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateHashCode(HashCodeBuilder theBuilder) {
|
||||
theBuilder.append(mySchemaInitializationProvider);
|
||||
theBuilder.append(getSchemaInitializationProvider());
|
||||
}
|
||||
|
||||
public ISchemaInitializationProvider getSchemaInitializationProvider() {
|
||||
|
|
|
@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
|
|||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.migrate.JdbcUtils;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import org.intellij.lang.annotations.Language;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -159,8 +160,8 @@ public class ModifyColumnTask extends BaseTableColumnTypeTask {
|
|||
throw new IllegalStateException(Msg.code(67) + "Dont know how to handle " + getDriverType());
|
||||
}
|
||||
|
||||
if (!isFailureAllowed() && isShrinkOnly) {
|
||||
setFailureAllowed(true);
|
||||
if (isShrinkOnly) {
|
||||
addFlag(TaskFlagEnum.FAILURE_ALLOWED);
|
||||
}
|
||||
|
||||
logInfo(ourLog, "Updating column {} on table {} to type {}", getColumnName(), getTableName(), type);
|
||||
|
|
|
@ -99,6 +99,7 @@ public class RenameTableTask extends BaseTableTask {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateHashCode(HashCodeBuilder theBuilder) {
|
||||
super.generateHashCode(theBuilder);
|
||||
theBuilder.append(myOldTableName);
|
||||
|
|
|
@ -23,6 +23,7 @@ import ca.uhn.fhir.context.ConfigurationException;
|
|||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.ISchemaInitializationProvider;
|
||||
import ca.uhn.fhir.util.ClasspathUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Charsets;
|
||||
import jakarta.annotation.Nonnull;
|
||||
|
@ -71,11 +72,7 @@ public class SchemaInitializationProvider implements ISchemaInitializationProvid
|
|||
|
||||
String initScript = mySchemaFileClassPath + "/" + getInitScript(theDriverType);
|
||||
try {
|
||||
InputStream sqlFileInputStream = SchemaInitializationProvider.class.getResourceAsStream(initScript);
|
||||
if (sqlFileInputStream == null) {
|
||||
throw new ConfigurationException(
|
||||
Msg.code(49) + "Schema initialization script " + initScript + " not found on classpath");
|
||||
}
|
||||
InputStream sqlFileInputStream = ClasspathUtil.loadResourceAsStream(initScript);
|
||||
// Assumes no escaped semicolons...
|
||||
String sqlString = IOUtils.toString(sqlFileInputStream, Charsets.UTF_8);
|
||||
parseSqlFileIntoIndividualStatements(theDriverType, retval, sqlString);
|
||||
|
@ -91,7 +88,7 @@ public class SchemaInitializationProvider implements ISchemaInitializationProvid
|
|||
String sqlString = theSqlString.replaceAll("--.*", "");
|
||||
|
||||
String sqlStringNoComments = preProcessSqlString(theDriverType, sqlString);
|
||||
String[] statements = sqlStringNoComments.split("\\;");
|
||||
String[] statements = sqlStringNoComments.split(";");
|
||||
for (String statement : statements) {
|
||||
String cleanedStatement = preProcessSqlStatement(theDriverType, statement);
|
||||
if (!isBlank(cleanedStatement)) {
|
||||
|
|
|
@ -85,18 +85,17 @@ public class Builder {
|
|||
}
|
||||
|
||||
public BuilderCompleteTask executeRawSql(String theVersion, @Language("SQL") String theSql) {
|
||||
ExecuteRawSqlTask task = executeRawSqlOptional(false, theVersion, theSql);
|
||||
ExecuteRawSqlTask task = executeRawSqlOptional(theVersion, theSql);
|
||||
return new BuilderCompleteTask(task);
|
||||
}
|
||||
|
||||
public void executeRawSqlStub(String theVersion, @Language("SQL") String theSql) {
|
||||
executeRawSqlOptional(true, theVersion, theSql);
|
||||
BuilderCompleteTask task = executeRawSql(theVersion, theSql);
|
||||
task.withFlag(TaskFlagEnum.DO_NOTHING);
|
||||
}
|
||||
|
||||
private ExecuteRawSqlTask executeRawSqlOptional(
|
||||
boolean theDoNothing, String theVersion, @Language("SQL") String theSql) {
|
||||
private ExecuteRawSqlTask executeRawSqlOptional(String theVersion, @Language("SQL") String theSql) {
|
||||
ExecuteRawSqlTask task = new ExecuteRawSqlTask(myRelease, theVersion).addSql(theSql);
|
||||
task.setDoNothing(theDoNothing);
|
||||
mySink.addTask(task);
|
||||
return task;
|
||||
}
|
||||
|
@ -172,10 +171,10 @@ public class Builder {
|
|||
addTask(task);
|
||||
}
|
||||
|
||||
public DropIdGeneratorTask dropIdGenerator(String theVersion, String theIdGeneratorName) {
|
||||
public BuilderCompleteTask dropIdGenerator(String theVersion, String theIdGeneratorName) {
|
||||
DropIdGeneratorTask task = new DropIdGeneratorTask(myRelease, theVersion, theIdGeneratorName);
|
||||
addTask(task);
|
||||
return task;
|
||||
return new BuilderCompleteTask(task);
|
||||
}
|
||||
|
||||
public void addNop(String theVersion) {
|
||||
|
@ -199,7 +198,7 @@ public class Builder {
|
|||
}
|
||||
|
||||
public BuilderCompleteTask dropIndex(String theVersion, String theIndexName) {
|
||||
BaseTask task = dropIndexOptional(false, theVersion, theIndexName);
|
||||
BaseTask task = dropIndexOptional(theVersion, theIndexName);
|
||||
return new BuilderCompleteTask(task);
|
||||
}
|
||||
|
||||
|
@ -207,20 +206,20 @@ public class Builder {
|
|||
* Drop index without taking write lock on PG, Oracle, MSSQL.
|
||||
*/
|
||||
public BuilderCompleteTask dropIndexOnline(String theVersion, String theIndexName) {
|
||||
DropIndexTask task = dropIndexOptional(false, theVersion, theIndexName);
|
||||
DropIndexTask task = dropIndexOptional(theVersion, theIndexName);
|
||||
task.setOnline(true);
|
||||
return new BuilderCompleteTask(task);
|
||||
}
|
||||
|
||||
public void dropIndexStub(String theVersion, String theIndexName) {
|
||||
dropIndexOptional(true, theVersion, theIndexName);
|
||||
DropIndexTask task = dropIndexOptional(theVersion, theIndexName);
|
||||
task.addFlag(TaskFlagEnum.DO_NOTHING);
|
||||
}
|
||||
|
||||
private DropIndexTask dropIndexOptional(boolean theDoNothing, String theVersion, String theIndexName) {
|
||||
private DropIndexTask dropIndexOptional(String theVersion, String theIndexName) {
|
||||
DropIndexTask task = new DropIndexTask(myRelease, theVersion);
|
||||
task.setIndexName(theIndexName);
|
||||
task.setTableName(myTableName);
|
||||
task.setDoNothing(theDoNothing);
|
||||
addTask(task);
|
||||
return task;
|
||||
}
|
||||
|
@ -230,24 +229,24 @@ public class Builder {
|
|||
*/
|
||||
@Deprecated
|
||||
public void renameIndex(String theVersion, String theOldIndexName, String theNewIndexName) {
|
||||
renameIndexOptional(false, theVersion, theOldIndexName, theNewIndexName);
|
||||
renameIndexOptional(theVersion, theOldIndexName, theNewIndexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Do not rename indexes - It is too hard to figure out what happened if something goes wrong
|
||||
*/
|
||||
public void renameIndexStub(String theVersion, String theOldIndexName, String theNewIndexName) {
|
||||
renameIndexOptional(true, theVersion, theOldIndexName, theNewIndexName);
|
||||
RenameIndexTask task = renameIndexOptional(theVersion, theOldIndexName, theNewIndexName);
|
||||
task.addFlag(TaskFlagEnum.DO_NOTHING);
|
||||
}
|
||||
|
||||
private void renameIndexOptional(
|
||||
boolean theDoNothing, String theVersion, String theOldIndexName, String theNewIndexName) {
|
||||
private RenameIndexTask renameIndexOptional(String theVersion, String theOldIndexName, String theNewIndexName) {
|
||||
RenameIndexTask task = new RenameIndexTask(myRelease, theVersion);
|
||||
task.setOldIndexName(theOldIndexName);
|
||||
task.setNewIndexName(theNewIndexName);
|
||||
task.setTableName(myTableName);
|
||||
task.setDoNothing(theDoNothing);
|
||||
addTask(task);
|
||||
return task;
|
||||
}
|
||||
|
||||
public void dropThisTable(String theVersion) {
|
||||
|
@ -388,27 +387,22 @@ public class Builder {
|
|||
}
|
||||
|
||||
public void withColumnsStub(String... theColumnNames) {
|
||||
withColumnsOptional(true, theColumnNames);
|
||||
BuilderCompleteTask task = withColumns(theColumnNames);
|
||||
task.withFlag(TaskFlagEnum.DO_NOTHING);
|
||||
}
|
||||
|
||||
public BuilderCompleteTask withColumns(String... theColumnNames) {
|
||||
BaseTask task = withColumnsOptional(false, theColumnNames);
|
||||
return new BuilderCompleteTask(task);
|
||||
}
|
||||
|
||||
private AddIndexTask withColumnsOptional(boolean theDoNothing, String... theColumnNames) {
|
||||
AddIndexTask task = new AddIndexTask(myRelease, myVersion);
|
||||
task.setTableName(myTableName);
|
||||
task.setIndexName(myIndexName);
|
||||
task.setUnique(myUnique);
|
||||
task.setColumns(theColumnNames);
|
||||
task.setDoNothing(theDoNothing);
|
||||
task.setOnline(myOnline);
|
||||
if (myIncludeColumns != null) {
|
||||
task.setIncludeColumns(myIncludeColumns);
|
||||
}
|
||||
addTask(task);
|
||||
return task;
|
||||
return new BuilderCompleteTask(task);
|
||||
}
|
||||
|
||||
public BuilderAddIndexUnique includeColumns(String... theIncludeColumns) {
|
||||
|
@ -453,18 +447,17 @@ public class Builder {
|
|||
public class BuilderModifyColumnWithNameAndNullable {
|
||||
private final String myVersion;
|
||||
private final boolean myNullable;
|
||||
private boolean myFailureAllowed;
|
||||
|
||||
public BuilderModifyColumnWithNameAndNullable(String theVersion, boolean theNullable) {
|
||||
myVersion = theVersion;
|
||||
myNullable = theNullable;
|
||||
}
|
||||
|
||||
public void withType(ColumnTypeEnum theColumnType) {
|
||||
withType(theColumnType, null);
|
||||
public BuilderCompleteTask withType(ColumnTypeEnum theColumnType) {
|
||||
return withType(theColumnType, null);
|
||||
}
|
||||
|
||||
public void withType(ColumnTypeEnum theColumnType, Integer theLength) {
|
||||
public BuilderCompleteTask withType(ColumnTypeEnum theColumnType, Integer theLength) {
|
||||
if (theColumnType == ColumnTypeEnum.STRING) {
|
||||
if (theLength == null || theLength == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
|
@ -478,6 +471,7 @@ public class Builder {
|
|||
}
|
||||
|
||||
ModifyColumnTask task = new ModifyColumnTask(myRelease, myVersion);
|
||||
|
||||
task.setColumnName(myColumnName);
|
||||
task.setTableName(myTableName);
|
||||
if (theLength != null) {
|
||||
|
@ -485,13 +479,8 @@ public class Builder {
|
|||
}
|
||||
task.setNullable(myNullable);
|
||||
task.setColumnType(theColumnType);
|
||||
task.setFailureAllowed(myFailureAllowed);
|
||||
addTask(task);
|
||||
}
|
||||
|
||||
public BuilderModifyColumnWithNameAndNullable failureAllowed() {
|
||||
myFailureAllowed = true;
|
||||
return this;
|
||||
return new BuilderCompleteTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -596,12 +585,12 @@ public class Builder {
|
|||
}
|
||||
|
||||
public BuilderCompleteTask failureAllowed() {
|
||||
myTask.setFailureAllowed(true);
|
||||
myTask.addFlag(TaskFlagEnum.FAILURE_ALLOWED);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BuilderCompleteTask doNothing() {
|
||||
myTask.setDoNothing(true);
|
||||
myTask.addFlag(TaskFlagEnum.DO_NOTHING);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -646,7 +635,7 @@ public class Builder {
|
|||
}
|
||||
|
||||
public BuilderCompleteTask runEvenDuringSchemaInitialization() {
|
||||
myTask.setRunDuringSchemaInitialization(true);
|
||||
myTask.addFlag(TaskFlagEnum.RUN_DURING_SCHEMA_INITIALIZATION);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -654,6 +643,16 @@ public class Builder {
|
|||
myTask.setTransactional(theFlag);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BuilderCompleteTask heavyweightSkipByDefault() {
|
||||
myTask.addFlag(TaskFlagEnum.HEAVYWEIGHT_SKIP_BY_DEFAULT);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BuilderCompleteTask withFlag(TaskFlagEnum theFlag) {
|
||||
myTask.addFlag(theFlag);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class BuilderAddTableRawSql {
|
||||
|
@ -707,9 +706,8 @@ public class Builder {
|
|||
}
|
||||
}
|
||||
|
||||
public BuilderAddTableByColumns failureAllowed() {
|
||||
myTask.setFailureAllowed(true);
|
||||
return this;
|
||||
public BuilderCompleteTask withFlags() {
|
||||
return new BuilderCompleteTask(myTask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR Server - SQL Migration
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
package ca.uhn.fhir.jpa.migrate.tasks.api;
|
||||
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.InitializeSchemaTask;
|
||||
|
||||
public enum TaskFlagEnum {
|
||||
|
||||
/**
|
||||
* This task should be skipped by default on live system migrations. Use this flag
|
||||
* in cases where the benefit of applying a migration doesn't justify the effort, and
|
||||
* only use this flag in cases where skipping the task will not leave the system in
|
||||
* an unusable state.
|
||||
* <p>
|
||||
* This flag is intended for situations where a change to the schema would be useful
|
||||
* to add to the default initialized schema, but would not be worth the effort of
|
||||
* applying in-place to large databases due to the outsized effort it would take.
|
||||
* </p>
|
||||
* <p>
|
||||
* USE THIS FLAG WITH CAUTION: It means that the migrator unit tests will execute the
|
||||
* task, but live migrations probably won't. So think long and hard before you set it!
|
||||
* </p>
|
||||
*/
|
||||
HEAVYWEIGHT_SKIP_BY_DEFAULT,
|
||||
|
||||
/**
|
||||
* Should this task run even if we're doing the very first initialization of an empty schema. By
|
||||
* default, we skip most tasks during that pass, since they just take up time and the
|
||||
* schema should be fully initialized by the {@link InitializeSchemaTask}
|
||||
*/
|
||||
RUN_DURING_SCHEMA_INITIALIZATION,
|
||||
|
||||
/**
|
||||
* This task is allowed to fail, and failure won't abort the migration. Upon any
|
||||
* detected failures, the task will still be recorded as having been successfully
|
||||
* complected. A failure in this context means that the SQL statement(s) being
|
||||
* executed returned a non-successful response, or timed out.
|
||||
*/
|
||||
FAILURE_ALLOWED,
|
||||
|
||||
/**
|
||||
* This task should not actually do anything, and will always be recorded as
|
||||
* a success. Use this flag for tasks that are no longer needed, e.g. because
|
||||
* they are superseded by later tasks or because they turned out to be a bad
|
||||
* idea.
|
||||
*/
|
||||
DO_NOTHING
|
||||
}
|
|
@ -128,7 +128,7 @@ class HapiMigrationStorageSvcTest extends BaseMigrationTest {
|
|||
return taskList;
|
||||
}
|
||||
|
||||
public Builder forVersion(MigrationTaskList theTaskList) {
|
||||
public static Builder forVersion(MigrationTaskList theTaskList) {
|
||||
BaseMigrationTasks.IAcceptsTasks sink = theTask -> {
|
||||
theTask.validate();
|
||||
theTaskList.add(theTask);
|
||||
|
|
|
@ -3,7 +3,11 @@ package ca.uhn.fhir.jpa.migrate;
|
|||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.jpa.migrate.dao.HapiMigrationDao;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.ColumnTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.taskdef.NopTask;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.SchemaInitializationProvider;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.Builder;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum;
|
||||
import ca.uhn.test.concurrency.IPointcutLatch;
|
||||
import ca.uhn.test.concurrency.PointcutLatch;
|
||||
import jakarta.annotation.Nonnull;
|
||||
|
@ -13,6 +17,8 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
|
|||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
@ -23,12 +29,15 @@ import java.util.concurrent.ExecutionException;
|
|||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
@SuppressWarnings("SqlDialectInspection")
|
||||
class HapiMigratorIT {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(HapiMigratorIT.class);
|
||||
private static final String MIGRATION_TABLENAME = "TEST_MIGRATOR_TABLE";
|
||||
|
@ -42,6 +51,7 @@ class HapiMigratorIT {
|
|||
HapiMigrator migrator = buildMigrator();
|
||||
migrator.createMigrationTableIfRequired();
|
||||
Integer count = myJdbcTemplate.queryForObject("SELECT COUNT(*) FROM " + MIGRATION_TABLENAME, Integer.class);
|
||||
assertNotNull(count);
|
||||
assertTrue(count > 0);
|
||||
HapiMigrationDao migrationDao = new HapiMigrationDao(myDataSource, DriverTypeEnum.H2_EMBEDDED, MIGRATION_TABLENAME);
|
||||
myMigrationStorageSvc = new HapiMigrationStorageSvc(migrationDao);
|
||||
|
@ -56,6 +66,62 @@ class HapiMigratorIT {
|
|||
System.clearProperty(HapiMigrationLock.CLEAR_LOCK_TABLE_WITH_DESCRIPTION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeSchema() {
|
||||
SchemaInitializationProvider schemaInitProvider = new SchemaInitializationProvider(
|
||||
"A schema",
|
||||
"/hapi-migrator-it-init-schema",
|
||||
"HFJ_RES_REINDEX_JOB",
|
||||
true
|
||||
);
|
||||
|
||||
MigrationTaskList taskList = new MigrationTaskList();
|
||||
Builder version = HapiMigrationStorageSvcTest.forVersion(taskList);
|
||||
|
||||
version.initializeSchema("1", schemaInitProvider);
|
||||
|
||||
Builder.BuilderAddTableByColumns nonSchemaInit = version.addTableByColumns("2", "NON_SCHEMA_INIT", "PID");
|
||||
nonSchemaInit.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
|
||||
Builder.BuilderAddTableByColumns schemaInit = version.addTableByColumns("3", "SCHEMA_INIT", "PID");
|
||||
schemaInit.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
schemaInit.withFlags().runEvenDuringSchemaInitialization();
|
||||
|
||||
HapiMigrator migrator;
|
||||
MigrationResult outcome;
|
||||
|
||||
/*
|
||||
* Run the migrator for the first time. This should execute 2 tasks: the initial
|
||||
* schema initialization, and the task set to run even during initialization. Task
|
||||
* 2 should not run.
|
||||
*/
|
||||
migrator = buildMigrator(taskList.toTaskArray());
|
||||
outcome = migrator.migrate();
|
||||
assertThat(toTaskVersionList(outcome)).as(toTaskStatementDescriptions(outcome)).containsExactly("1", "3");
|
||||
|
||||
/*
|
||||
* Run again - Nothing should happen since we've already finished the migration
|
||||
*/
|
||||
migrator = buildMigrator(taskList.toTaskArray());
|
||||
outcome = migrator.migrate();
|
||||
assertThat(toTaskVersionList(outcome)).as(toTaskStatementDescriptions(outcome)).isEmpty();
|
||||
|
||||
/*
|
||||
* Add another pair of tasks - Both should run
|
||||
*/
|
||||
Builder.BuilderAddTableByColumns nonSchemaInit2 = version.addTableByColumns("4", "NON_SCHEMA_INIT_2", "PID");
|
||||
nonSchemaInit2.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
|
||||
Builder.BuilderAddTableByColumns schemaInit2 = version.addTableByColumns("5", "SCHEMA_INIT_2", "PID");
|
||||
schemaInit2.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
schemaInit2.withFlags().runEvenDuringSchemaInitialization();
|
||||
|
||||
migrator = buildMigrator(taskList.toTaskArray());
|
||||
outcome = migrator.migrate();
|
||||
assertThat(toTaskVersionList(outcome)).as(toTaskStatementDescriptions(outcome)).containsExactly("4", "5");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_onecall_noblock() throws InterruptedException, ExecutionException {
|
||||
|
||||
|
@ -65,7 +131,7 @@ class HapiMigratorIT {
|
|||
HapiMigrator migrator = buildMigrator(latchMigrationTask);
|
||||
|
||||
latchMigrationTask.setExpectedCount(1);
|
||||
Future<MigrationResult> future = executor.submit(() -> migrator.migrate());
|
||||
Future<MigrationResult> future = executor.submit(migrator::migrate);
|
||||
latchMigrationTask.awaitExpected();
|
||||
latchMigrationTask.release("1");
|
||||
|
||||
|
@ -91,7 +157,7 @@ class HapiMigratorIT {
|
|||
// is released, the first one will have already run so there will be nothing to do
|
||||
|
||||
latchMigrationTask1.setExpectedCount(1);
|
||||
Future<MigrationResult> future1 = executor.submit(() -> migrator1.migrate());
|
||||
Future<MigrationResult> future1 = executor.submit(migrator1::migrate);
|
||||
latchMigrationTask1.awaitExpected();
|
||||
|
||||
// We wait until the first migration is in the middle of executing the migration task before we start the second one
|
||||
|
@ -101,7 +167,7 @@ class HapiMigratorIT {
|
|||
latchMigrationTask1.release("1");
|
||||
|
||||
latchMigrationTask2.setExpectedCount(1);
|
||||
Future<MigrationResult> future2 = executor.submit(() -> migrator2.migrate());
|
||||
Future<MigrationResult> future2 = executor.submit(migrator2::migrate);
|
||||
latchMigrationTask2.awaitExpected();
|
||||
|
||||
// This second call shouldn't be necessary, but it will help the test fail faster with a clearer error
|
||||
|
@ -127,7 +193,7 @@ class HapiMigratorIT {
|
|||
|
||||
{
|
||||
latchMigrationTask.setExpectedCount(1);
|
||||
Future<MigrationResult> future = executor.submit(() -> migrator.migrate());
|
||||
Future<MigrationResult> future = executor.submit(migrator::migrate);
|
||||
latchMigrationTask.awaitExpected();
|
||||
assertEquals(1, countLockRecords());
|
||||
latchMigrationTask.release("1");
|
||||
|
@ -138,7 +204,7 @@ class HapiMigratorIT {
|
|||
}
|
||||
|
||||
{
|
||||
Future<MigrationResult> future = executor.submit(() -> migrator.migrate());
|
||||
Future<MigrationResult> future = executor.submit(migrator::migrate);
|
||||
|
||||
MigrationResult result = future.get();
|
||||
assertEquals(0, countLockRecords());
|
||||
|
@ -147,7 +213,6 @@ class HapiMigratorIT {
|
|||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void test_oldLockFails_block() {
|
||||
HapiMigrationLock.setMaxRetryAttempts(0);
|
||||
|
@ -176,7 +241,31 @@ class HapiMigratorIT {
|
|||
assertThat(result.succeededTasks).hasSize(1);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
void test_HeavyweightSkippable(boolean theShouldRun) throws InterruptedException, ExecutionException {
|
||||
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
LatchMigrationTask latchMigrationTask = new LatchMigrationTask("only", "1");
|
||||
latchMigrationTask.addFlag(TaskFlagEnum.HEAVYWEIGHT_SKIP_BY_DEFAULT);
|
||||
|
||||
HapiMigrator migrator = buildMigrator(latchMigrationTask);
|
||||
int expectedInvocations = 0;
|
||||
if (theShouldRun) {
|
||||
migrator.setRunHeavyweightSkippableTasks(true);
|
||||
expectedInvocations = 1;
|
||||
}
|
||||
latchMigrationTask.setExpectedCount(expectedInvocations);
|
||||
|
||||
Future<MigrationResult> future = executor.submit(migrator::migrate);
|
||||
latchMigrationTask.awaitExpected();
|
||||
latchMigrationTask.release("1");
|
||||
|
||||
MigrationResult result = future.get();
|
||||
assertThat(result.succeededTasks).hasSize(expectedInvocations);
|
||||
}
|
||||
|
||||
@SuppressWarnings("DataFlowIssue")
|
||||
private int countLockRecords() {
|
||||
return myJdbcTemplate.queryForObject("SELECT COUNT(*) FROM " + MIGRATION_TABLENAME + " WHERE \"installed_rank\" = " + HapiMigrationLock.LOCK_PID, Integer.class);
|
||||
}
|
||||
|
@ -195,8 +284,15 @@ class HapiMigratorIT {
|
|||
return new HapiMigrator(MIGRATION_TABLENAME, myDataSource, DriverTypeEnum.H2_EMBEDDED);
|
||||
}
|
||||
|
||||
private static @Nonnull String toTaskStatementDescriptions(MigrationResult outcome) {
|
||||
return "Statements:\n * " + outcome.executedStatements.stream().map(BaseTask.ExecutedStatement::toString).collect(Collectors.joining("\n * "));
|
||||
}
|
||||
|
||||
private class LatchMigrationTask extends BaseTask implements IPointcutLatch {
|
||||
private static @Nonnull List<String> toTaskVersionList(MigrationResult outcome) {
|
||||
return outcome.executedStatements.stream().map(BaseTask.ExecutedStatement::getSchemaVersion).toList();
|
||||
}
|
||||
|
||||
private static class LatchMigrationTask extends BaseTask implements IPointcutLatch {
|
||||
private final PointcutLatch myLatch;
|
||||
private final PointcutLatch myWaitLatch;
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ public class AddTableByColumnTaskTest extends BaseTest {
|
|||
return theTask1.getColumnName().compareTo(theTask2.getColumnName());
|
||||
};
|
||||
|
||||
final AddTableByColumnTask addTableByColumnTask = new AddTableByColumnTask(comparator);
|
||||
final AddTableByColumnTask addTableByColumnTask = new AddTableByColumnTask("1", "1", comparator);
|
||||
addTableByColumnTask.setTableName(tableName);
|
||||
addTableByColumnTask.setDriverType(driverType);
|
||||
addTableByColumnTask.setPkColumns(Collections.singletonList(columnNameId));
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.migrate.taskdef;
|
|||
import ca.uhn.fhir.jpa.migrate.DriverTypeEnum;
|
||||
import ca.uhn.fhir.jpa.migrate.HapiMigrationException;
|
||||
import ca.uhn.fhir.jpa.migrate.JdbcUtils;
|
||||
import ca.uhn.fhir.jpa.migrate.tasks.api.TaskFlagEnum;
|
||||
import jakarta.annotation.Nonnull;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -17,6 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
@SuppressWarnings("SqlDialectInspection")
|
||||
public class ModifyColumnTest extends BaseTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}: {0}")
|
||||
|
@ -232,14 +234,11 @@ public class ModifyColumnTest extends BaseTest {
|
|||
@SuppressWarnings("EnumSwitchStatementWhichMissesCases")
|
||||
@Nonnull
|
||||
private JdbcUtils.ColumnType getLongColumnType(Supplier<TestDatabaseDetails> theTestDatabaseDetails) {
|
||||
switch (theTestDatabaseDetails.get().getDriverType()) {
|
||||
case H2_EMBEDDED:
|
||||
return new JdbcUtils.ColumnType(ColumnTypeEnum.LONG, 64);
|
||||
case DERBY_EMBEDDED:
|
||||
return new JdbcUtils.ColumnType(ColumnTypeEnum.LONG, 19);
|
||||
default:
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
return switch (theTestDatabaseDetails.get().getDriverType()) {
|
||||
case H2_EMBEDDED -> new JdbcUtils.ColumnType(ColumnTypeEnum.LONG, 64);
|
||||
case DERBY_EMBEDDED -> new JdbcUtils.ColumnType(ColumnTypeEnum.LONG, 19);
|
||||
default -> throw new UnsupportedOperationException();
|
||||
};
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{index}: {0}")
|
||||
|
@ -270,11 +269,11 @@ public class ModifyColumnTest extends BaseTest {
|
|||
executeSql("insert into SOMETABLE (TEXTCOL) values ('HELLO')");
|
||||
|
||||
ModifyColumnTask task = new ModifyColumnTask("1", "1");
|
||||
task.addFlag(TaskFlagEnum.FAILURE_ALLOWED);
|
||||
task.setTableName("SOMETABLE");
|
||||
task.setColumnName("TEXTCOL");
|
||||
task.setColumnType(ColumnTypeEnum.LONG);
|
||||
task.setNullable(true);
|
||||
task.setFailureAllowed(true);
|
||||
getMigrator().addTask(task);
|
||||
|
||||
getMigrator().migrate();
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
create table HFJ_RES_REINDEX_JOB (
|
||||
PID bigint not null,
|
||||
RES_TYPE varchar(100),
|
||||
primary key (PID)
|
||||
);
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -187,7 +187,8 @@ public class JpaModelScannerAndVerifier {
|
|||
scan(nextField, theNames, theIsSuperClass, isView);
|
||||
|
||||
Id id = nextField.getAnnotation(Id.class);
|
||||
if (id != null) {
|
||||
boolean isId = id != null;
|
||||
if (isId) {
|
||||
Validate.isTrue(!foundId, "Multiple fields annotated with @Id");
|
||||
foundId = true;
|
||||
|
||||
|
@ -241,12 +242,24 @@ public class JpaModelScannerAndVerifier {
|
|||
|
||||
int columnLength = 16;
|
||||
String columnName = null;
|
||||
boolean nullable = false;
|
||||
if (hasColumn) {
|
||||
columnName = nextField.getAnnotation(Column.class).name();
|
||||
columnLength = nextField.getAnnotation(Column.class).length();
|
||||
Column column = nextField.getAnnotation(Column.class);
|
||||
columnName = column.name();
|
||||
columnLength = column.length();
|
||||
nullable = column.nullable();
|
||||
}
|
||||
if (hasJoinColumn) {
|
||||
columnName = nextField.getAnnotation(JoinColumn.class).name();
|
||||
JoinColumn joinColumn = nextField.getAnnotation(JoinColumn.class);
|
||||
columnName = joinColumn.name();
|
||||
nullable = joinColumn.nullable();
|
||||
}
|
||||
if (isId) {
|
||||
nullable = false;
|
||||
}
|
||||
|
||||
if (nullable && !isView) {
|
||||
Validate.isTrue(!nextField.getType().isPrimitive(), "Field [%s] has a nullable primitive type: %s", nextField.getName(), nextField.getType());
|
||||
}
|
||||
|
||||
if (columnName != null) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>7.3.7-SNAPSHOT</version>
|
||||
<version>7.3.8-SNAPSHOT</version>
|
||||
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue