001package ca.uhn.fhir.jpa.migrate;
002
003/*-
004 * #%L
005 * HAPI FHIR Server - SQL Migration
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.jpa.migrate.taskdef.BaseTask;
024import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
025import org.flywaydb.core.api.MigrationVersion;
026import org.flywaydb.core.api.migration.Context;
027import org.flywaydb.core.api.migration.JavaMigration;
028import org.slf4j.Logger;
029import org.slf4j.LoggerFactory;
030
031import java.sql.SQLException;
032
033import static org.apache.commons.lang3.StringUtils.isBlank;
034
035public class FlywayMigrationTask implements JavaMigration {
036        private static final Logger ourLog = LoggerFactory.getLogger(FlywayMigrationTask.class);
037
038        private final BaseTask myTask;
039        private final FlywayMigrator myFlywayMigrator;
040        private DriverTypeEnum.ConnectionProperties myConnectionProperties;
041
042        public FlywayMigrationTask(BaseTask theTask, FlywayMigrator theFlywayMigrator) {
043                myTask = theTask;
044                myFlywayMigrator = theFlywayMigrator;
045        }
046
047        @Override
048        public MigrationVersion getVersion() {
049                return MigrationVersion.fromVersion(myTask.getFlywayVersion());
050        }
051
052        @Override
053        public String getDescription() {
054                return myTask.getDescription();
055        }
056
057        @Override
058        public Integer getChecksum() {
059                return myTask.hashCode();
060        }
061
062        @Override
063        public boolean isUndo() {
064                return false;
065        }
066
067        @Override
068        public boolean canExecuteInTransaction() {
069                return false;
070        }
071
072        @Override
073        public void migrate(Context theContext) {
074                myTask.setDriverType(myFlywayMigrator.getDriverType());
075                myTask.setDryRun(myFlywayMigrator.isDryRun());
076                myTask.setNoColumnShrink(myFlywayMigrator.isNoColumnShrink());
077                myTask.setConnectionProperties(myConnectionProperties);
078                try {
079                        executeTask();
080                } catch (SQLException e) {
081                        String description = myTask.getDescription();
082                        if (isBlank(description)) {
083                                description = myTask.getClass().getSimpleName();
084                        }
085                        String prefix = "Failure executing task \"" + description + "\", aborting! Cause: ";
086                        throw new InternalErrorException(prefix + e.toString(), e);
087                }
088        }
089
090        private void executeTask() throws SQLException {
091                if (myFlywayMigrator.isSchemaWasInitialized() && !myTask.isRunDuringSchemaInitialization()) {
092                        // Empty schema was initialized, stub out this non-schema-init task since we're starting with a fully migrated schema
093                        myTask.setDoNothing(true);
094                }
095                myTask.execute();
096                if (myTask.initializedSchema()) {
097                        ourLog.info("Empty schema was Initialized.  Stubbing out all following migration tasks that are not Schema Initializations.");
098                        myFlywayMigrator.setSchemaWasInitialized(true);
099                }
100
101                myFlywayMigrator.addExecutedStatements(myTask.getExecutedStatements());
102        }
103
104        public void setConnectionProperties(DriverTypeEnum.ConnectionProperties theConnectionProperties) {
105                myConnectionProperties = theConnectionProperties;
106        }
107}