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