001    package liquibase.change.core;
002    
003    import liquibase.change.AbstractChange;
004    import liquibase.change.ChangeMetaData;
005    import liquibase.change.ColumnConfig;
006    import liquibase.database.Database;
007    import liquibase.database.core.DB2Database;
008    import liquibase.database.core.SQLiteDatabase;
009    import liquibase.database.core.SQLiteDatabase.AlterTableVisitor;
010    import liquibase.database.structure.Index;
011    import liquibase.statement.SqlStatement;
012    import liquibase.statement.core.DropColumnStatement;
013    import liquibase.statement.core.ReorganizeTableStatement;
014    import liquibase.util.StringUtils;
015    
016    import java.util.ArrayList;
017    import java.util.List;
018    
019    /**
020     * Drops an existing column from a table.
021     */
022    public class DropColumnChange extends AbstractChange {
023    
024        private String schemaName;
025        private String tableName;
026        private String columnName;
027    
028        public DropColumnChange() {
029            super("dropColumn", "Drop Column", ChangeMetaData.PRIORITY_DEFAULT);
030        }
031    
032        public String getColumnName() {
033            return columnName;
034        }
035    
036        public void setColumnName(String columnName) {
037            this.columnName = columnName;
038        }
039    
040        public String getSchemaName() {
041            return schemaName;
042        }
043    
044        public void setSchemaName(String schemaName) {
045            this.schemaName = StringUtils.trimToNull(schemaName);
046        }
047    
048        public String getTableName() {
049            return tableName;
050        }
051    
052        public void setTableName(String tableName) {
053            this.tableName = tableName;
054        }
055    
056        public SqlStatement[] generateStatements(Database database) {
057    
058            // todo if (database instanceof SQLiteDatabase) {
059            // // return special statements for SQLite databases
060            // return generateStatementsForSQLiteDatabase(database);
061            // }
062    
063            List<SqlStatement> statements = new ArrayList<SqlStatement>();
064            String schemaName = getSchemaName() == null ? database.getDefaultSchemaName() : getSchemaName();
065    
066            statements.add(new DropColumnStatement(schemaName, getTableName(), getColumnName()));
067            if (database instanceof DB2Database) {
068                statements.add(new ReorganizeTableStatement(schemaName, getTableName()));
069            }
070    
071            return statements.toArray(new SqlStatement[statements.size()]);
072        }
073    
074        private SqlStatement[] generateStatementsForSQLiteDatabase(Database database) {
075    
076            // SQLite does not support this ALTER TABLE operation until now.
077            // For more information see: http://www.sqlite.org/omitted.html.
078            // This is a small work around...
079    
080            List<SqlStatement> statements = new ArrayList<SqlStatement>();
081    
082            // define alter table logic
083            AlterTableVisitor rename_alter_visitor = new AlterTableVisitor() {
084                public ColumnConfig[] getColumnsToAdd() {
085                    return new ColumnConfig[0];
086                }
087    
088                public boolean createThisColumn(ColumnConfig column) {
089                    return !column.getName().equals(getColumnName());
090                }
091    
092                public boolean copyThisColumn(ColumnConfig column) {
093                    return !column.getName().equals(getColumnName());
094                }
095    
096                public boolean createThisIndex(Index index) {
097                    return !index.getColumns().contains(getColumnName());
098                }
099            };
100    
101            try {
102                // alter table
103                statements.addAll(SQLiteDatabase.getAlterTableStatements(rename_alter_visitor, database, getSchemaName(),
104                        getTableName()));
105    
106            } catch (Exception e) {
107                e.printStackTrace();
108            }
109    
110            return statements.toArray(new SqlStatement[statements.size()]);
111        }
112    
113        public String getConfirmationMessage() {
114            return "Column " + getTableName() + "." + getColumnName() + " dropped";
115        }
116    }