001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Arnaud Kervern
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.core.storage.sql.jdbc;
021
022import java.sql.Connection;
023import java.sql.SQLException;
024import java.util.ArrayList;
025import java.util.List;
026
027import org.apache.commons.logging.Log;
028import org.apache.commons.logging.LogFactory;
029import org.nuxeo.ecm.core.storage.sql.RepositoryImpl;
030import org.nuxeo.ecm.core.storage.sql.jdbc.db.Column;
031import org.nuxeo.ecm.core.storage.sql.jdbc.dialect.SQLStatement.ListCollector;
032
033/**
034 * Helper to provide SQL migration calls while adding a column.
035 *
036 * @since 5.4.2
037 */
038public class TableUpgrader {
039
040    protected static class TableUpgrade {
041        public final String tableKey;
042
043        public final String columnName;
044
045        public final String sqlProcedure;
046
047        public final String testProp;
048
049        public TableUpgrade(String tableKey, String columnName, String sqlProcedure, String testProp) {
050            this.tableKey = tableKey;
051            this.columnName = columnName;
052            this.sqlProcedure = sqlProcedure;
053            this.testProp = testProp;
054        }
055    }
056
057    protected List<TableUpgrade> tableUpgrades = new ArrayList<>();
058
059    private SQLInfo sqlInfo;
060
061    private Connection connection;
062
063    private JDBCLogger logger;
064
065    private static final Log log = LogFactory.getLog(TableUpgrader.class);
066
067    public TableUpgrader(SQLInfo sqlInfo, Connection connection, JDBCLogger logger) {
068        this.sqlInfo = sqlInfo;
069        this.connection = connection;
070        this.logger = logger;
071    }
072
073    /**
074     * Add a couple table/column associated with a sql procedure to be executed when the column is added and a a test
075     * flag to force his execution.
076     *
077     * @param tableKey table name
078     * @param columnName desired added column
079     * @param sqlProcedure sql procedure name
080     * @param testProp test flag name
081     */
082    public void add(String tableKey, String columnName, String sqlProcedure, String testProp) {
083        tableUpgrades.add(new TableUpgrade(tableKey, columnName, sqlProcedure, testProp));
084    }
085
086    /**
087     * Check if there is an added column that match with a upgrade process. If one exists, it executes the associated
088     * sql in the category. If not, nothing happend.
089     *
090     * @param tableKey table name
091     * @param addedColumns list of added column
092     * @throws SQLException Exception thrown by JDBC
093     */
094    public void upgrade(String tableKey, List<Column> addedColumns, String ddlMode, ListCollector ddlCollector)
095            throws SQLException {
096        for (TableUpgrade upgrade : tableUpgrades) {
097            if (!upgrade.tableKey.equals(tableKey)) {
098                continue;
099            }
100            boolean doUpgrade;
101            if (addedColumns == null) {
102                // table created
103                doUpgrade = RepositoryImpl.testProps.containsKey(upgrade.testProp);
104            } else {
105                // columns added
106                doUpgrade = false;
107                for (Column col : addedColumns) {
108                    if (col.getKey().equals(upgrade.columnName)) {
109                        doUpgrade = true;
110                        break;
111                    }
112                }
113            }
114            if (doUpgrade) {
115                log.info("Upgrading table: " + tableKey);
116                sqlInfo.executeSQLStatements(upgrade.sqlProcedure, ddlMode, connection, logger, ddlCollector);
117            }
118        }
119    }
120}