001package ca.uhn.fhir.jpa.migrate.taskdef;
002
003/*-
004 * #%L
005 * HAPI FHIR Server - SQL Migration
006 * %%
007 * Copyright (C) 2014 - 2023 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.i18n.Msg;
024import ca.uhn.fhir.jpa.migrate.JdbcUtils;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028import java.sql.SQLException;
029import java.util.Set;
030
031public class AddColumnTask extends BaseTableColumnTypeTask {
032
033        private static final Logger ourLog = LoggerFactory.getLogger(AddColumnTask.class);
034
035        public AddColumnTask() {
036                this(null, null);
037                setDryRun(true);
038                myCheckForExistingTables = false;
039        }
040
041        public AddColumnTask(String theProductVersion, String theSchemaVersion) {
042                super(theProductVersion, theSchemaVersion);
043        }
044
045        @Override
046        public void validate() {
047                super.validate();
048                setDescription("Add column " + getColumnName() + " on table " + getTableName());
049        }
050
051        @Override
052        public void doExecute() throws SQLException {
053                if (myCheckForExistingTables) {
054                        Set<String> columnNames = JdbcUtils.getColumnNames(getConnectionProperties(), getTableName());
055                        if (columnNames.contains(getColumnName())) {
056                                logInfo(ourLog, "Column {} already exists on table {} - No action performed", getColumnName(), getTableName());
057                                return;
058                        }
059                }
060
061                String typeStatement = getTypeStatement();
062
063                String sql;
064                switch (getDriverType()) {
065                        case MYSQL_5_7:
066                        case MARIADB_10_1:
067                                // Quote the column name as "SYSTEM" is a reserved word in MySQL
068                                sql = "alter table " + getTableName() + " add column `" + getColumnName() + "` " + typeStatement;
069                                break;
070                        case DERBY_EMBEDDED:
071                        case POSTGRES_9_4:
072                                sql = "alter table " + getTableName() + " add column " + getColumnName() + " " + typeStatement;
073                                break;
074                        case MSSQL_2012:
075                        case ORACLE_12C:
076                        case H2_EMBEDDED:
077                                sql = "alter table " + getTableName() + " add " + getColumnName() + " " + typeStatement;
078                                break;
079                        default:
080                                throw new IllegalStateException(Msg.code(60));
081                }
082
083                logInfo(ourLog, "Adding column {} of type {} to table {}", getColumnName(), getSqlType(), getTableName());
084                executeSql(getTableName(), sql);
085        }
086
087        public String getTypeStatement() {
088                String type = getSqlType();
089                String nullable = getSqlNotNull();
090                if (isNullable()) {
091                        nullable = "";
092                }
093                if (myPrettyPrint) {
094                        nullable = nullable.trim();
095                }
096                String space = isNullable() ? "" : " ";
097                return type + space + nullable;
098        }
099
100}