001/*-
002 * #%L
003 * HAPI FHIR Server - SQL Migration
004 * %%
005 * Copyright (C) 2014 - 2026 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.migrate.taskdef;
021
022import ca.uhn.fhir.i18n.Msg;
023import ca.uhn.fhir.jpa.migrate.JdbcUtils;
024import org.apache.commons.lang3.Validate;
025import org.apache.commons.lang3.builder.EqualsBuilder;
026import org.apache.commons.lang3.builder.HashCodeBuilder;
027import org.slf4j.Logger;
028import org.slf4j.LoggerFactory;
029
030import java.sql.SQLException;
031import java.util.Set;
032import java.util.stream.Collectors;
033
034import static org.apache.commons.lang3.StringUtils.isNotBlank;
035
036public class AddIdGeneratorTask extends BaseTask {
037
038        private static final Integer DEFAULT_INCREMENT = 50;
039        private static final Logger ourLog = LoggerFactory.getLogger(AddIdGeneratorTask.class);
040        private final String myGeneratorName;
041        private final Integer myIncrement;
042
043        public AddIdGeneratorTask(String theProductVersion, String theSchemaVersion, String theGeneratorName) {
044                super(theProductVersion, theSchemaVersion);
045                myGeneratorName = theGeneratorName;
046                myIncrement = DEFAULT_INCREMENT;
047        }
048
049        public AddIdGeneratorTask(
050                        String theProductVersion, String theSchemaVersion, String theGeneratorName, Integer theIncrement) {
051                super(theProductVersion, theSchemaVersion);
052                myGeneratorName = theGeneratorName;
053                myIncrement = theIncrement;
054        }
055
056        @Override
057        public void validate() {
058                Validate.notBlank(myGeneratorName);
059                setDescription("Add id generator " + myGeneratorName);
060        }
061
062        @Override
063        public void doExecute() throws SQLException {
064                Set<String> tableNames = JdbcUtils.getTableNames(getConnectionProperties());
065                String sql = null;
066
067                switch (getDriverType()) {
068                        case MARIADB_10_1:
069                        case MYSQL_5_7:
070                                // These require a separate table
071                                // Increment value is controlled globally using the auto_increment_increment variable
072                                if (!tableNames.contains(myGeneratorName)) {
073
074                                        String creationSql = "create table " + myGeneratorName + " ( next_val bigint ) engine=InnoDB";
075                                        executeSql(myGeneratorName, creationSql);
076
077                                        String initSql = "insert into " + myGeneratorName + " values ( 1 )";
078                                        executeSql(myGeneratorName, initSql);
079                                }
080                                break;
081                        case DERBY_EMBEDDED:
082                        case H2_EMBEDDED:
083                        case ORACLE_12C:
084                        case MSSQL_2012:
085                                sql = "create sequence " + myGeneratorName + " start with 1 increment by " + myIncrement;
086                                break;
087                        case COCKROACHDB_21_1:
088                        case POSTGRES_9_4:
089                                sql = "create sequence " + myGeneratorName + " start 1000 increment " + myIncrement;
090                                break;
091                        default:
092                                throw new IllegalStateException(Msg.code(63));
093                }
094
095                if (isNotBlank(sql)) {
096                        Set<String> sequenceNames = JdbcUtils.getSequenceNames(getConnectionProperties()).stream()
097                                        .map(String::toLowerCase)
098                                        .collect(Collectors.toSet());
099                        ourLog.debug("Currently have sequences: {}", sequenceNames);
100                        if (sequenceNames.contains(myGeneratorName.toLowerCase())) {
101                                logInfo(ourLog, "Sequence {} already exists - No action performed", myGeneratorName);
102                                return;
103                        }
104
105                        executeSql(myGeneratorName, sql);
106                }
107        }
108
109        @Override
110        protected void generateEquals(EqualsBuilder theBuilder, BaseTask theOtherObject) {
111                AddIdGeneratorTask otherObject = (AddIdGeneratorTask) theOtherObject;
112                theBuilder.append(myGeneratorName, otherObject.myGeneratorName);
113        }
114
115        @Override
116        protected void generateHashCode(HashCodeBuilder theBuilder) {
117                theBuilder.append(myGeneratorName);
118        }
119}