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(ourLog, "Column {} already exists on table {} - No action performed", getColumnName(), getTableName());
056                                return;
057                        }
058                }
059
060                String typeStatement = getTypeStatement();
061
062                String sql;
063                switch (getDriverType()) {
064                        case MYSQL_5_7:
065                        case MARIADB_10_1:
066                                // Quote the column name as "SYSTEM" is a reserved word in MySQL
067                                sql = "alter table " + getTableName() + " add column `" + getColumnName() + "` " + typeStatement;
068                                break;
069                        case DERBY_EMBEDDED:
070                        case POSTGRES_9_4:
071                                sql = "alter table " + getTableName() + " add column " + getColumnName() + " " + typeStatement;
072                                break;
073                        case MSSQL_2012:
074                        case ORACLE_12C:
075                        case H2_EMBEDDED:
076                                sql = "alter table " + getTableName() + " add " + getColumnName() + " " + typeStatement;
077                                break;
078                        default:
079                                throw new IllegalStateException(Msg.code(60));
080                }
081
082                logInfo(ourLog, "Adding column {} of type {} to table {}", getColumnName(), getSqlType(), getTableName());
083                executeSql(getTableName(), sql);
084        }
085
086        public String getTypeStatement() {
087                String type = getSqlType();
088                String nullable = getSqlNotNull();
089                if (isNullable()) {
090                        nullable = "";
091                }
092                if (myPrettyPrint) {
093                        nullable = nullable.trim();
094                }
095                String space = isNullable() ? "" : " ";
096                return type + space + nullable;
097        }
098
099}