/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.util.db.management;
import java.io.File;
import java.sql.SQLInvalidAuthorizationSpecException;
import org.apache.commons.io.FileUtils;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.HSQLDialect;
/**
* Database management for HSQL databases.
*/
public final class HSQLDbManagement extends AbstractDbManagement {
/**
* Singleton instance.
*/
private static final HSQLDbManagement INSTANCE = new HSQLDbManagement();
/**
* The underlying Hibernate dialect.
*/
private HSQLDialect _hibernateDialect;
/**
* Restricted constructor.
*/
private HSQLDbManagement() {
}
/**
* Gets the singleton instance.
*
* @return the instance, not null
*/
public static HSQLDbManagement getInstance() {
return INSTANCE;
}
//-------------------------------------------------------------------------
@Override
public synchronized Dialect getHibernateDialect() {
if (_hibernateDialect == null) {
// constructed lazily so we don't get log message about 'using dialect' if we're not actually using it
_hibernateDialect = new HSQLDialect();
}
return _hibernateDialect;
}
@Override
public Class<?> getJDBCDriverClass() {
return org.hsqldb.jdbcDriver.class;
}
@Override
public String getDatabaseName() {
return "hsqldb";
}
//-------------------------------------------------------------------------
@Override
public void shutdown(String catalog) {
super.shutdown(catalog);
executeSql(catalog, null, "SHUTDOWN");
}
//-------------------------------------------------------------------------
@Override
public String getAllSchemasSQL(String catalog) {
return "SELECT TABLE_SCHEM AS name FROM INFORMATION_SCHEMA.SYSTEM_SCHEMAS";
}
@Override
public String getAllForeignKeyConstraintsSQL(String catalog, String schema) {
String sql = "SELECT FK_NAME AS name, " +
"FKTABLE_NAME AS table_name " +
"FROM INFORMATION_SCHEMA.SYSTEM_CROSSREFERENCE";
if (schema != null) {
sql += " WHERE FKTABLE_SCHEM = '" + schema + "'";
}
return sql;
}
@Override
public String getAllSequencesSQL(String catalog, String schema) {
String sql = "SELECT SEQUENCE_NAME AS name FROM INFORMATION_SCHEMA.SYSTEM_SEQUENCES " +
" WHERE SEQUENCE_NAME <> 'LOB_ID'";
if (schema != null) {
sql += " AND SEQUENCE_SCHEMA = '" + schema + "'";
}
return sql;
}
@Override
public String getAllTablesSQL(String catalog, String schema) {
String sql = "SELECT TABLE_NAME AS name FROM INFORMATION_SCHEMA.SYSTEM_TABLES WHERE TABLE_TYPE = 'TABLE'";
if (schema != null) {
sql += " AND TABLE_SCHEM = '" + schema + "'";
}
return sql;
}
@Override
public String getAllViewsSQL(String catalog, String schema) {
String sql = "SELECT TABLE_NAME AS name FROM INFORMATION_SCHEMA.SYSTEM_TABLES WHERE TABLE_TYPE = 'VIEW'";
if (schema != null) {
sql += " AND TABLE_SCHEM = '" + schema + "'";
}
return sql;
}
@Override
public String getAllColumnsSQL(String catalog, String schema, String table) {
StringBuilder sql = new StringBuilder("SELECT COLUMN_NAME AS name, DATA_TYPE AS datatype, IS_NULLABLE AS allowsnull, COLUMN_DEF AS defaultvalue " +
"FROM INFORMATION_SCHEMA.SYSTEM_COLUMNS WHERE TABLE_NAME='");
sql.append(table).append("'");
if (schema != null) {
sql.append(" AND TABLE_SCHEM='").append(schema).append("'");
}
return sql.toString();
}
@Override
public String getCreateSchemaSQL(String catalog, String schema) {
return "CREATE SCHEMA " + schema;
}
@Override
public String getSchemaVersionTable(String schemaGroupName) {
return (schemaGroupName + SCHEMA_VERSION_TABLE_SUFFIX).toUpperCase();
}
@Override
public String getSchemaVersionSQL(String catalog, String schemaGroupName) {
return "SELECT version_value FROM " + getSchemaVersionTable(schemaGroupName) + " WHERE version_key = 'schema_patch'";
}
@Override
public CatalogCreationStrategy getCatalogCreationStrategy() {
return new HSQLCatalogCreationStrategy();
}
@Override
public void dropSchema(String catalog, String schema) {
try {
super.dropSchema(catalog, schema);
} catch (RuntimeException ex) {
// try deleting database
if (ex.getCause() instanceof SQLInvalidAuthorizationSpecException) {
FileUtils.deleteQuietly(getFile());
super.dropSchema(catalog, schema);
}
}
/*
* NOTE jonathan 2013-04-11 -- this should work but for some reason doesn't
Connection conn = null;
try {
if (!getCatalogCreationStrategy().catalogExists(catalog)) {
System.out.println("Catalog " + catalog + " does not exist");
return; // nothing to drop
}
conn = connect(catalog);
if (schema == null) {
schema = "PUBLIC";
}
Statement statement = conn.createStatement();
statement.executeUpdate("DROP SCHEMA " + schema + " CASCADE");
statement.close();
} catch (SQLException e) {
throw new OpenGammaRuntimeException("Failed to drop schema", e);
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
}
}
*/
}
private File getFile() {
String dbHost = getDbHost().trim();
String filePart = dbHost.substring("jdbc:hsqldb:file:".length());
return new File(filePart);
}
//-------------------------------------------------------------------------
/**
* Strategy for catalog creation.
*/
private class HSQLCatalogCreationStrategy implements CatalogCreationStrategy {
@Override
public boolean catalogExists(String catalog) {
if (getDbHost().toLowerCase().indexOf("jdbc:hsqldb:file:") != 1) {
return true;
}
File catalogDir = new File(getFile(), catalog);
return catalogDir.exists();
}
@Override
public void create(String catalog) {
return; // HSQLDB creates DB automatically on first connect
}
}
}