/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.framework.persistence;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.mifos.db.upgrade.DatabaseUpgradeSupport;
import org.mifos.framework.hibernate.helper.StaticHibernateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
/**
* This class handles automated database schema and data changes.
*
* <ul>
* <li>read (for example) application/src/main/resources/sql/upgrades.txt (a file containing names of available upgrades
* from checkpoint 2 releases back)</li>
* <li>read which upgrades from upgrades.txt have been applied to a database</li>
* <li>determine if the database needs upgrading</li>
* <li>apply any upgrades not currently applied to the database</li>
* </ul>
*/
public class DatabaseMigrator {
private static final Logger logger = LoggerFactory.getLogger(DatabaseMigrator.class);
private Connection connection;
private static final String APPLIED_UPGRADES = "applied_upgrades";
public DatabaseMigrator() {
this.connection = StaticHibernateUtil.getSessionTL().connection();
try {
connection.setAutoCommit(false);
} catch (SQLException e) {
logger.error("couldn't change autocommit", e);
}
}
public void upgrade(ApplicationContext applicationContext) throws Exception {
DatabaseUpgradeSupport databaseUpgradeSupport = (DatabaseUpgradeSupport) applicationContext.getBean("databaseUpgradeSupport");
databaseUpgradeSupport.expansion();
}
public List<Integer> getAppliedUpgrades() {
List<Integer> appliedUpgrades = new ArrayList<Integer>();
Statement stmt = null;
try {
stmt = connection.createStatement(ResultSet.FETCH_FORWARD, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("select upgrade_id from " + APPLIED_UPGRADES + " order by upgrade_id");
while (rs.next()) {
appliedUpgrades.add(rs.getInt(1));
}
rs.close();
stmt.close();
} catch (SQLException e) {
logger.error("error fetching applied upgrades", e);
}
return appliedUpgrades;
}
public boolean isNSDU() throws SQLException {
ResultSet results = connection.getMetaData().getColumns(null, null, APPLIED_UPGRADES, "upgrade_id");
boolean foundAppliedUpgrades = results.next();
results.close();
results = connection.getMetaData().getColumns(null, null, "database_version", "database_version");
boolean foundDatabaseVersion = results.next();
if (!(foundAppliedUpgrades || foundDatabaseVersion)) {
throw new RuntimeException("Database is too old to be upgraded");
}
return foundAppliedUpgrades;
}
}