001: package liquibase.change;
002:
003: import liquibase.database.DB2Database;
004: import liquibase.database.Database;
005: import liquibase.database.sql.*;
006: import liquibase.database.structure.Column;
007: import liquibase.database.structure.DatabaseObject;
008: import liquibase.database.structure.Table;
009: import liquibase.exception.UnsupportedChangeException;
010: import liquibase.util.StringUtils;
011: import org.w3c.dom.Document;
012: import org.w3c.dom.Element;
013:
014: import java.util.*;
015:
016: /**
017: * Adds a column to an existing table.
018: */
019: public class AddColumnChange extends AbstractChange {
020:
021: private String schemaName;
022: private String tableName;
023: private List<ColumnConfig> columns;
024:
025: public AddColumnChange() {
026: super ("addColumn", "Add Column");
027: columns = new ArrayList<ColumnConfig>();
028: }
029:
030: public String getSchemaName() {
031: return schemaName;
032: }
033:
034: public void setSchemaName(String schemaName) {
035: this .schemaName = schemaName;
036: }
037:
038: public String getTableName() {
039: return tableName;
040: }
041:
042: public void setTableName(String tableName) {
043: this .tableName = tableName;
044: }
045:
046: public List<ColumnConfig> getColumns() {
047: return columns;
048: }
049:
050: public ColumnConfig getLastColumn() {
051: return (columns.size() > 0) ? columns.get(columns.size() - 1)
052: : null;
053: }
054:
055: public void addColumn(ColumnConfig column) {
056: columns.add(column);
057: }
058:
059: public void removeColumn(ColumnConfig column) {
060: columns.remove(column);
061: }
062:
063: public SqlStatement[] generateStatements(Database database)
064: throws UnsupportedChangeException {
065: List<SqlStatement> sql = new ArrayList<SqlStatement>();
066:
067: String schemaName = getSchemaName() == null ? database
068: .getDefaultSchemaName() : getSchemaName();
069: for (ColumnConfig aColumn : columns) {
070: Set<ColumnConstraint> constraints = new HashSet<ColumnConstraint>();
071: if (aColumn.getConstraints() != null) {
072: if (aColumn.getConstraints().isNullable() != null
073: && !aColumn.getConstraints().isNullable()) {
074: constraints.add(new NotNullConstraint());
075: }
076: }
077:
078: AddColumnStatement addColumnStatement = new AddColumnStatement(
079: schemaName, getTableName(), aColumn.getName(),
080: aColumn.getType(), aColumn.getDefaultValueObject(),
081: constraints
082: .toArray(new ColumnConstraint[constraints
083: .size()]));
084:
085: sql.add(addColumnStatement);
086:
087: if (aColumn.getValueObject() != null) {
088: UpdateStatement updateStatement = new UpdateStatement(
089: schemaName, getTableName());
090: updateStatement.addNewColumnValue(aColumn.getName(),
091: aColumn.getValueObject());
092: sql.add(updateStatement);
093: }
094: }
095:
096: for (ColumnConfig aColumn : columns) {
097: if (aColumn.getConstraints() != null) {
098: if (aColumn.getConstraints().isPrimaryKey() != null
099: && aColumn.getConstraints().isPrimaryKey()) {
100: AddPrimaryKeyChange change = new AddPrimaryKeyChange();
101: change.setSchemaName(schemaName);
102: change.setTableName(getTableName());
103: change.setColumnNames(aColumn.getName());
104:
105: sql.addAll(Arrays.asList(change
106: .generateStatements(database)));
107: }
108: }
109: }
110:
111: if (database instanceof DB2Database) {
112: sql.add(new ReorganizeTableStatement(schemaName,
113: getTableName()));
114: }
115:
116: return sql.toArray(new SqlStatement[sql.size()]);
117: }
118:
119: protected Change[] createInverses() {
120: List<Change> inverses = new ArrayList<Change>();
121:
122: for (ColumnConfig aColumn : columns) {
123: if (aColumn.hasDefaultValue()) {
124: DropDefaultValueChange dropChange = new DropDefaultValueChange();
125: dropChange.setTableName(getTableName());
126: dropChange.setColumnName(aColumn.getName());
127:
128: inverses.add(dropChange);
129: }
130:
131: DropColumnChange inverse = new DropColumnChange();
132: inverse.setSchemaName(getSchemaName());
133: inverse.setColumnName(aColumn.getName());
134: inverse.setTableName(getTableName());
135: inverses.add(inverse);
136: }
137:
138: return inverses.toArray(new Change[inverses.size()]);
139: }
140:
141: public String getConfirmationMessage() {
142: List<String> names = new ArrayList<String>(columns.size());
143: for (ColumnConfig col : columns) {
144: names.add(col.getName() + "(" + col.getType() + ")");
145: }
146:
147: return "Columns " + StringUtils.join(names, ",") + " added to "
148: + tableName;
149: }
150:
151: public Element createNode(Document currentChangeLogFileDOM) {
152: Element node = currentChangeLogFileDOM
153: .createElement("addColumn");
154: if (getSchemaName() != null) {
155: node.setAttribute("schemaName", getSchemaName());
156: }
157: node.setAttribute("tableName", getTableName());
158:
159: for (ColumnConfig col : getColumns()) {
160: Element subNode = col.createNode(currentChangeLogFileDOM);
161: node.appendChild(subNode);
162: }
163:
164: return node;
165: }
166:
167: public Set<DatabaseObject> getAffectedDatabaseObjects() {
168: List<DatabaseObject> result = new ArrayList<DatabaseObject>(
169: columns.size());
170:
171: Table table = new Table(getTableName());
172: result.add(table);
173: for (ColumnConfig aColumn : columns) {
174: Column each = new Column();
175: each.setTable(table);
176: each.setName(aColumn.getName());
177: result.add(each);
178: }
179:
180: return new HashSet<DatabaseObject>(result);
181: }
182: }
|