org.dspace.storage.rdbms.MigrationUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.dspace.storage.rdbms.MigrationUtils.java

Source

/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 * http://www.dspace.org/license/
 */
package org.dspace.storage.rdbms;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.commons.lang.StringUtils;

/**
 * This Utility class offers utility methods which may be of use to perform
 * common Java migration task(s).
 *
 * @author Tim Donohue
 */
public class MigrationUtils {
    /**
     * Drop a given Database Constraint (based on the current database type).
     * Returns a "checksum" for this migration which can be used as part of
     * a Flyway Java migration
     *
     * @param connection the current Database connection
     * @param tableName the name of the table the constraint applies to
     * @param columnName the name of the column the constraint applies to
     * @param constraintSuffix Only used for PostgreSQL, whose constraint naming convention depends on a suffix (key, fkey, etc)
     * @return migration checksum as an Integer
     * @throws SQLException if a database error occurs
     */
    public static Integer dropDBConstraint(Connection connection, String tableName, String columnName,
            String constraintSuffix) throws SQLException {
        Integer checksum = -1;

        // First, in order to drop the appropriate Database constraint, we
        // must determine the unique name of the constraint. As constraint
        // naming is DB specific, this is dependent on our DB Type
        DatabaseMetaData meta = connection.getMetaData();
        // NOTE: We use "findDbKeyword()" here as it won't cause
        // DatabaseManager.initialize() to be called (which in turn re-calls Flyway)
        String dbtype = DatabaseManager.findDbKeyword(meta);
        String constraintName = null;
        String constraintNameSQL = null;
        switch (dbtype) {
        case DatabaseManager.DBMS_POSTGRES:
            // In Postgres, constraints are always named:
            // {tablename}_{columnname(s)}_{suffix}
            // see: http://stackoverflow.com/a/4108266/3750035
            constraintName = StringUtils.lowerCase(tableName) + "_" + StringUtils.lowerCase(columnName) + "_"
                    + StringUtils.lowerCase(constraintSuffix);
            break;
        case DatabaseManager.DBMS_ORACLE:
            // In Oracle, constraints are listed in the USER_CONS_COLUMNS table
            constraintNameSQL = "SELECT CONSTRAINT_NAME " + "FROM USER_CONS_COLUMNS "
                    + "WHERE TABLE_NAME = ? AND COLUMN_NAME = ?";
            break;
        case DatabaseManager.DBMS_H2:
            // In H2, constraints are listed in the "information_schema.constraints" table
            constraintNameSQL = "SELECT DISTINCT CONSTRAINT_NAME " + "FROM information_schema.constraints "
                    + "WHERE table_name = ? AND column_list = ?";
            break;
        default:
            throw new SQLException("DBMS " + dbtype + " is unsupported in this migration.");
        }

        // If we have a SQL query to run for the constraint name, then run it
        if (constraintNameSQL != null) {
            // Run the query to obtain the constraint name, passing it the parameters
            PreparedStatement statement = connection.prepareStatement(constraintNameSQL);
            statement.setString(1, StringUtils.upperCase(tableName));
            statement.setString(2, StringUtils.upperCase(columnName));
            try {
                ResultSet results = statement.executeQuery();
                if (results.next()) {
                    constraintName = results.getString("CONSTRAINT_NAME");
                }
                results.close();
            } finally {
                statement.close();
            }
        }

        // As long as we have a constraint name, drop it
        if (constraintName != null && !constraintName.isEmpty()) {
            // This drop constaint SQL should be the same in all databases
            String dropConstraintSQL = "ALTER TABLE " + tableName + " DROP CONSTRAINT " + constraintName;

            PreparedStatement statement = connection.prepareStatement(dropConstraintSQL);
            try {
                statement.execute();
            } finally {
                statement.close();
            }
            // Return the size of the query we just ran
            // This will be our "checksum" for this Flyway migration (see getChecksum())
            checksum = dropConstraintSQL.length();
        }

        return checksum;
    }
}