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))); } }