package liquibase.ext.spatial.utils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import liquibase.database.Database;
import liquibase.database.DatabaseConnection;
import liquibase.database.core.DerbyDatabase;
import liquibase.database.core.H2Database;
import liquibase.database.core.PostgresDatabase;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.LiquibaseException;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.snapshot.SnapshotGeneratorFactory;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Table;
import liquibase.structure.core.View;
/**
* <code>GeometryColumnsUtils</code> provides useful methods for checking the
* <code>GEOMETRY_COLUMNS</code> table.
*/
public class GeometryColumnsUtils {
/**
* Hide the default constructor.
*/
private GeometryColumnsUtils() {
}
/**
* Determines if the given table is in <code>GEOMETRY_COLUMNS</code> and,
* therefore, has a geometry column.
*
* @param database
* the database to query.
* @param schemaName
* the schema name.
* @param tableName
* the table name to check.
* @return <code>true</code> if the table has a geometry column.
*/
public static boolean hasGeometryColumn(final Database database,
final String schemaName, final String tableName) {
boolean isSpatialColumn = false;
Statement jdbcStatement = null;
try {
if (geometryColumnsExists(database)) {
final String query = "SELECT * FROM geometry_columns WHERE f_table_schema = '"
+ (schemaName == null ? database.getDefaultSchemaName()
: schemaName)
+ "' AND f_table_name = '"
+ tableName
+ "'";
final DatabaseConnection databaseConnection = database
.getConnection();
final JdbcConnection jdbcConnection = (JdbcConnection) databaseConnection;
jdbcStatement = jdbcConnection.getUnderlyingConnection()
.createStatement();
final ResultSet rs = jdbcStatement.executeQuery(query);
isSpatialColumn = rs.next();
}
} catch (final SQLException e) {
throw new UnexpectedLiquibaseException(
"Failed to determine if the table has a geometry column", e);
} finally {
if (jdbcStatement != null) {
try {
jdbcStatement.close();
} catch (final SQLException ignore) {
}
}
}
return isSpatialColumn;
}
/**
* Determines if the given column is in <code>GEOMETRY_COLUMNS</code>.
*
* @param database
* the database to query.
* @param schemaName
* the schema name.
* @param tableName
* the table name.
* @param columnName
* the column name.
* @return <code>true</code> if the column is a geometry column.
*/
public static boolean isGeometryColumn(final Database database,
final String schemaName, final String tableName,
final String columnName) {
boolean isSpatialColumn = false;
Statement jdbcStatement = null;
try {
if (geometryColumnsExists(database)) {
final String query = "SELECT * FROM geometry_columns WHERE f_table_schema = '"
+ (schemaName == null ? database.getDefaultSchemaName()
: schemaName)
+ "' AND f_table_name = '"
+ tableName
+ "' AND upper(f_geometry_column) = '"
+ columnName.toUpperCase() + "'";
final DatabaseConnection databaseConnection = database
.getConnection();
final JdbcConnection jdbcConnection = (JdbcConnection) databaseConnection;
jdbcStatement = jdbcConnection.getUnderlyingConnection()
.createStatement();
final ResultSet rs = jdbcStatement.executeQuery(query);
isSpatialColumn = rs.next();
}
} catch (final SQLException e) {
throw new UnexpectedLiquibaseException(
"Failed to determine if the column to be dropped is a geometry column",
e);
} finally {
if (jdbcStatement != null) {
try {
jdbcStatement.close();
} catch (final SQLException ignore) {
}
}
}
return isSpatialColumn;
}
/**
* Indicates if the <code>GEOMETRY_COLUMNS</code> table or view exists.
*
* @param database
* the database to check.
* @return <code>true</code> if the table or view exists.
*/
public static boolean geometryColumnsExists(final Database database) {
String geometryColumnsName = database.correctObjectName(
"geometry_columns", Table.class);
DatabaseObject example = null;
if (database instanceof DerbyDatabase || database instanceof H2Database) {
final Table tableExample = new Table();
tableExample.setName(geometryColumnsName);
tableExample.setSchema(database.getDefaultCatalogName(),
database.getDefaultSchemaName());
example = tableExample;
} else if (database instanceof PostgresDatabase) {
final View viewExample = new View();
viewExample.setName(geometryColumnsName);
viewExample.setSchema(database.getDefaultCatalogName(), "public");
example = viewExample;
}
try {
return example != null
&& SnapshotGeneratorFactory.getInstance().has(example, database);
} catch (final LiquibaseException e) {
throw new UnexpectedLiquibaseException(
"Failed to determine if the geometry_columns table or view exists",
e);
}
}
}