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}