package liquibase.ext.spatial.sqlgenerator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import liquibase.database.Database;
import liquibase.database.core.DerbyDatabase;
import liquibase.database.core.H2Database;
import liquibase.exception.ValidationErrors;
import liquibase.ext.spatial.statement.DropSpatialIndexStatement;
import liquibase.ext.spatial.utils.GeometryColumnsUtils;
import liquibase.sql.Sql;
import liquibase.sql.UnparsedSql;
import liquibase.sqlgenerator.SqlGeneratorChain;
import liquibase.sqlgenerator.core.DropColumnGenerator;
import liquibase.statement.core.DropColumnStatement;
import liquibase.structure.core.Column;
/**
* <code>DropGeometryColumnGeneratorGeoDB</code> is a {@link DropColumnGenerator} that specializes
* in GeoDB. If there exists an index on the column, <code>DropSpatialIndex</code> is invoked first.
* If the column to be dropped is the geometry column, the <code>DropGeometryColumn</code> procedure
* is invoked instead of performing the typical <code>ALTER TABLE</code> statement. Otherwise, the
* next SQL generator in the chain is invoked to handle the request.
*/
public class DropGeometryColumnGeneratorGeoDB extends DropColumnGenerator {
/**
* @see liquibase.sqlgenerator.core.AbstractSqlGenerator#supports(liquibase.statement.SqlStatement,
* liquibase.database.Database)
*/
@Override
public boolean supports(final DropColumnStatement statement, final Database database) {
return database instanceof DerbyDatabase || database instanceof H2Database;
}
/**
* @see liquibase.sqlgenerator.core.AbstractSqlGenerator#getPriority()
*/
@Override
public int getPriority() {
return super.getPriority() + 1;
}
@Override
public ValidationErrors validate(final DropColumnStatement statement, final Database database,
final SqlGeneratorChain sqlGeneratorChain) {
return sqlGeneratorChain.validate(statement, database);
}
@Override
public Sql[] generateSql(final DropColumnStatement statement, final Database database,
final SqlGeneratorChain sqlGeneratorChain) {
String schemaName = statement.getSchemaName();
if (schemaName == null) {
schemaName = database.getDefaultSchemaName();
}
final String tableName = statement.getTableName();
final String columnName = statement.getColumnName();
final boolean isGeometryColumn = GeometryColumnsUtils.isGeometryColumn(database, schemaName,
tableName, columnName);
final List<Sql> list = new ArrayList<Sql>();
if (isGeometryColumn) {
dropSpatialIndexIfExists(statement.getCatalogName(), schemaName, tableName, database, list);
final String sql = "CALL DropGeometryColumn('" + schemaName + "', '" + tableName + "', '"
+ columnName + "')";
final Column column = getAffectedColumn(statement);
final Sql dropGeometryColumn = new UnparsedSql(sql, column);
list.add(dropGeometryColumn);
} else {
list.addAll(Arrays.asList(sqlGeneratorChain.generateSql(statement, database)));
}
return list.toArray(new Sql[list.size()]);
}
/**
* Adds the SQL statement to drop the spatial index if it is present.
*
* @param catalogName
* the catalog name.
* @param schemaName
* the schema name.
* @param tableName
* the table name.
* @param database
* the database.
* @param list
* the list of SQL statements to execute.
*/
protected void dropSpatialIndexIfExists(final String catalogName, final String schemaName,
final String tableName, final Database database, final List<Sql> list) {
final DropSpatialIndexGeneratorGeoDB generator = new DropSpatialIndexGeneratorGeoDB();
final DropSpatialIndexStatement statement = new DropSpatialIndexStatement(null, catalogName,
schemaName, tableName);
list.addAll(Arrays.asList(generator.generateSqlIfExists(statement, database)));
}
}