/* * Copyright 2006-2007, Unitils.org * * 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. */ package org.unitils.core.dbsupport; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.Set; import org.unitils.core.UnitilsException; import static org.unitils.thirdparty.org.apache.commons.dbutils.DbUtils.closeQuietly; // Copied from: http://jira.unitils.org/browse/UNI-79 /** * Implementation of {@link org.unitils.core.dbsupport.DbSupport} for a H2 * database * * @author Mark Thomas */ public class H2DbSupport extends DbSupport { /** * Creates support for H2 databases. */ public H2DbSupport() { super("h2"); } /** * Returns the names of all tables in the database. * * @return The names of all tables in the database */ @Override public Set<String> getTableNames() { return getSQLHandler().getItemsAsStringSet("select TABLE_NAME from " + "INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'TABLE' AND " + "TABLE_SCHEMA = '" + getSchemaName() + "'"); } /** * Gets the names of all columns of the given table. * * @param tableName The table, not null * @return The names of the columns of the table with the given name */ @Override public Set<String> getColumnNames(String tableName) { return getSQLHandler().getItemsAsStringSet("select COLUMN_NAME from " + "INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = '" + tableName + "' AND TABLE_SCHEMA = '" + getSchemaName() + "'"); } /** * Gets the names of all primary columns of the given table. * * @param tableName The table, not null * @return The names of the primary key columns of the table with the given * name */ @Override public Set<String> getIdentityColumnNames(String tableName) { return getSQLHandler().getItemsAsStringSet("select COLUMN_NAME from " + "INFORMATION_SCHEMA.INDEXES where PRIMARY_KEY = 'TRUE' AND " + "TABLE_NAME = '" + tableName + "' AND TABLE_SCHEMA = '" + getSchemaName() + "'"); } /** * Retrieves the names of all the views in the database schema. * * @return The names of all views in the database */ @Override public Set<String> getViewNames() { return getSQLHandler().getItemsAsStringSet("select TABLE_NAME from " + "INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '" + getSchemaName() + "'"); } /** * Retrieves the names of all the sequences in the database schema. * * @return The names of all sequences in the database */ @Override public Set<String> getSequenceNames() { return getSQLHandler().getItemsAsStringSet("select SEQUENCE_NAME from " + "INFORMATION_SCHEMA.SEQUENCES where SEQUENCE_SCHEMA = '" + getSchemaName() + "'"); } /** * Retrieves the names of all the triggers in the database schema. * * @return The names of all triggers in the database */ @Override public Set<String> getTriggerNames() { return getSQLHandler().getItemsAsStringSet("select TRIGGER_NAME from " + "INFORMATION_SCHEMA.TRIGGERS where TRIGGER_SCHEMA = '" + getSchemaName() + "'"); } /** * Returns the value of the sequence with the given name. * <p/> * Note: this can have the side-effect of increasing the sequence value. * * @param sequenceName The sequence, not null * @return The value of the sequence with the given name */ @Override public long getSequenceValue(String sequenceName) { return getSQLHandler().getItemAsLong("select CURRENT_VALUE from " + "INFORMATION_SCHEMA.SEQUENCES where SEQUENCE_SCHEMA = '" + getSchemaName() + "' and SEQUENCE_NAME = '" + sequenceName + "'"); } /** * Sets the next value of the sequence with the given sequence name to the * given sequence value. * * @param sequenceName The sequence, not null * @param newSequenceValue The value to set */ @Override public void incrementSequenceToValue(String sequenceName, long newSequenceValue) { getSQLHandler().executeUpdate("alter sequence " + qualified(sequenceName) + " restart with " + newSequenceValue); } /** * Increments the identity value for the specified identity column on the * specified table to the given value. * * @param tableName The table with the identity column, not null * @param identityColumnName The column, not null * @param identityValue The new value */ @Override public void incrementIdentityColumnToValue(String tableName, String identityColumnName, long identityValue) { getSQLHandler().executeUpdate("alter table " + qualified(tableName) + " alter column " + quoted(identityColumnName) + " RESTART WITH " + identityValue); } /** * Disables all referential constraints (e.g. foreign keys) on all tables * in the schema */ @Override public void disableReferentialConstraints() { getSQLHandler().executeUpdate( "SET REFERENTIAL_INTEGRITY FALSE"); } /** * Disables all value constraints (e.g. not null) on all tables in the schema */ @Override public void disableValueConstraints() { disableCheckAndUniqueConstraints(); disableNotNullConstraints(); } /** * Disables all check and unique constraints on all tables in the schema */ protected void disableCheckAndUniqueConstraints() { Connection connection = null; Statement queryStatement = null; Statement alterStatement = null; ResultSet resultSet = null; try { connection = getSQLHandler().getDataSource().getConnection(); queryStatement = connection.createStatement(); alterStatement = connection.createStatement(); resultSet = queryStatement.executeQuery("select TABLE_NAME, " + "CONSTRAINT_NAME from INFORMATION_SCHEMA.CONSTRAINTS where " + "CONSTRAINT_TYPE IN ('CHECK', 'UNIQUE') AND CONSTRAINT_SCHEMA " + "= '" + getSchemaName() + "'"); while (resultSet.next()) { String tableName = resultSet.getString("TABLE_NAME"); String constraintName = resultSet.getString("CONSTRAINT_NAME"); alterStatement.executeUpdate("alter table " + qualified(tableName) + " drop constraint " + quoted(constraintName)); } } catch (Exception e) { throw new UnitilsException("Error while disabling check and unique " + "constraints on schema " + getSchemaName(), e); } finally { closeQuietly(queryStatement); closeQuietly(connection, alterStatement, resultSet); } } /** * Disables all not null constraints on all tables in the schema */ protected void disableNotNullConstraints() { Connection connection = null; Statement queryStatement = null; Statement alterStatement = null; ResultSet resultSet = null; try { connection = getSQLHandler().getDataSource().getConnection(); queryStatement = connection.createStatement(); alterStatement = connection.createStatement(); // Do not remove PK constraints resultSet = queryStatement.executeQuery("select col.TABLE_NAME, " + "col.COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS col where " + "col.IS_NULLABLE = 'NO' and col.TABLE_SCHEMA = '" + getSchemaName() + "' " + "AND NOT EXISTS (select COLUMN_NAME " + "from INFORMATION_SCHEMA.INDEXES pk where pk.TABLE_NAME = " + "col.TABLE_NAME and pk.COLUMN_NAME = col.COLUMN_NAME and " + "pk.TABLE_SCHEMA = '" + getSchemaName() + "' AND pk.PRIMARY_KEY = TRUE)"); while (resultSet.next()) { String tableName = resultSet.getString("TABLE_NAME"); String columnName = resultSet.getString("COLUMN_NAME"); alterStatement.executeUpdate("alter table " + qualified(tableName) + " alter column " + quoted(columnName) + " set null"); } } catch (Exception e) { throw new UnitilsException("Error while disabling not null " + "constraints on schema " + getSchemaName(), e); } finally { closeQuietly(queryStatement); closeQuietly(connection, alterStatement, resultSet); } } /** * Sequences are supported. * * @return True */ @Override public boolean supportsSequences() { return true; } /** * Triggers are supported. * * @return True */ @Override public boolean supportsTriggers() { return true; } /** * Identity columns are supported. * * @return True */ @Override public boolean supportsIdentityColumns() { return true; } /** * Cascade are supported. * * @return True */ @Override public boolean supportsCascade() { return true; } }