001: package liquibase.database.structure;
002:
003: import liquibase.database.Database;
004: import liquibase.database.MSSQLDatabase;
005: import liquibase.database.PostgresDatabase;
006: import liquibase.util.SqlUtil;
007:
008: import java.sql.Types;
009: import java.util.Arrays;
010: import java.util.List;
011:
012: public class Column implements DatabaseObject, Comparable<Column> {
013: private Table table;
014: private View view;
015: private String name;
016: private int dataType;
017: private int columnSize;
018: private int decimalDigits;
019: private Boolean nullable;
020: private String typeName;
021: private Object defaultValue;
022: private boolean autoIncrement = false;
023: private boolean primaryKey = false;
024: private boolean unique = false;
025:
026: public Table getTable() {
027: return table;
028: }
029:
030: public void setTable(Table table) {
031: this .table = table;
032: }
033:
034: public View getView() {
035: return view;
036: }
037:
038: public void setView(View view) {
039: this .view = view;
040: }
041:
042: public String getName() {
043: return name;
044: }
045:
046: public void setName(String name) {
047: this .name = name;
048: }
049:
050: public int getDataType() {
051: return dataType;
052: }
053:
054: public void setDataType(int dataType) {
055: this .dataType = dataType;
056: }
057:
058: public int getColumnSize() {
059: return columnSize;
060: }
061:
062: public void setColumnSize(int columnSize) {
063: this .columnSize = columnSize;
064: }
065:
066: public int getDecimalDigits() {
067: return decimalDigits;
068: }
069:
070: public void setDecimalDigits(int decimalDigits) {
071: this .decimalDigits = decimalDigits;
072: }
073:
074: public Boolean isNullable() {
075: return nullable;
076: }
077:
078: public void setNullable(Boolean nullable) {
079: this .nullable = nullable;
080: }
081:
082: public String getTypeName() {
083: return typeName;
084: }
085:
086: public void setTypeName(String typeName) {
087: this .typeName = typeName;
088: }
089:
090: public Object getDefaultValue() {
091: return defaultValue;
092: }
093:
094: public void setDefaultValue(Object defaultValue) {
095: this .defaultValue = defaultValue;
096: }
097:
098: public String toString() {
099: String tableOrViewName;
100: if (table == null) {
101: tableOrViewName = view.getName();
102: } else {
103: tableOrViewName = table.getName();
104: }
105: return tableOrViewName + "." + getName();
106: }
107:
108: public int compareTo(Column o) {
109: try {
110: //noinspection UnusedAssignment
111: int returnValue = 0;
112: if (this .getTable() != null && o.getTable() == null) {
113: return 1;
114: } else if (this .getTable() == null && o.getTable() != null) {
115: return -1;
116: } else if (this .getTable() == null && o.getTable() == null) {
117: returnValue = this .getView().compareTo(o.getView());
118: } else {
119: returnValue = this .getTable().compareTo(o.getTable());
120: }
121:
122: if (returnValue == 0) {
123: returnValue = this .getName().compareTo(o.getName());
124: }
125:
126: return returnValue;
127: } catch (Exception e) {
128: throw new RuntimeException(e);
129: }
130: }
131:
132: public boolean equals(Object o) {
133: try {
134: if (this == o)
135: return true;
136: if (o == null || getClass() != o.getClass())
137: return false;
138:
139: Column column = (Column) o;
140:
141: return name.equalsIgnoreCase(column.name)
142: && !(table != null ? !table.equals(column.table)
143: : column.table != null)
144: && !(view != null ? !view.equals(column.view)
145: : column.view != null);
146: } catch (Exception e) {
147: throw new RuntimeException(e);
148: }
149:
150: }
151:
152: public int hashCode() {
153: try {
154: int result;
155: result = (table != null ? table.hashCode() : 0);
156: result = 31 * result + (view != null ? view.hashCode() : 0);
157: result = 31 * result + name.toUpperCase().hashCode();
158: return result;
159: } catch (Exception e) {
160: throw new RuntimeException(e);
161: }
162: }
163:
164: /**
165: * Returns the type name and any parameters suitable for SQL.
166: */
167: public String getDataTypeString(Database database) {
168: List<Integer> noParens = Arrays.asList(Types.ARRAY,
169: Types.BIGINT, Types.BINARY, Types.BIT, Types.BLOB,
170: Types.BOOLEAN, Types.CLOB, Types.DATALINK, Types.DATE,
171: Types.DISTINCT, Types.INTEGER, Types.JAVA_OBJECT,
172: Types.LONGVARBINARY, Types.NULL, Types.OTHER,
173: Types.REF, Types.SMALLINT, Types.STRUCT, Types.TIME,
174: Types.TIMESTAMP, Types.TINYINT, Types.LONGVARCHAR);
175:
176: List<Integer> oneParam = Arrays.asList(Types.CHAR,
177: Types.VARCHAR, Types.VARBINARY);
178:
179: List<Integer> twoParams = Arrays.asList(Types.DECIMAL,
180: Types.DOUBLE, Types.FLOAT, Types.NUMERIC, Types.REAL);
181:
182: String translatedTypeName = this .getTypeName();
183: if (database instanceof PostgresDatabase) {
184: if ("bpchar".equals(translatedTypeName)) {
185: translatedTypeName = "char";
186: }
187: }
188:
189: String dataType;
190: if (noParens.contains(this .getDataType())) {
191: dataType = translatedTypeName;
192: } else if (oneParam.contains(this .getDataType())) {
193: if (database instanceof PostgresDatabase
194: && translatedTypeName.equals("text")) {
195: return translatedTypeName;
196: } else if (database instanceof MSSQLDatabase
197: && translatedTypeName.equals("uniqueidentifier")) {
198: return translatedTypeName;
199: }
200: dataType = translatedTypeName + "(" + this .getColumnSize()
201: + ")";
202: } else if (twoParams.contains(this .getDataType())) {
203: if (database instanceof PostgresDatabase
204: && this .getColumnSize() == 131089) {
205: dataType = "DECIMAL";
206: } else if (database instanceof MSSQLDatabase
207: && translatedTypeName.equalsIgnoreCase("money")) {
208: dataType = translatedTypeName.toUpperCase();
209: } else {
210: dataType = translatedTypeName + "("
211: + this .getColumnSize() + ","
212: + this .getDecimalDigits() + ")";
213: }
214: } else {
215: throw new RuntimeException("Unknown Data Type: "
216: + this .getDataType() + " (" + this .getTypeName()
217: + ")");
218: }
219: return dataType;
220: }
221:
222: public boolean isNumeric() {
223: return SqlUtil.isNumeric(getDataType());
224: }
225:
226: public boolean isUnique() {
227: return unique;
228: }
229:
230: public void setUnique(boolean unique) {
231: this .unique = unique;
232: }
233:
234: public boolean isAutoIncrement() {
235: return autoIncrement;
236: }
237:
238: public void setAutoIncrement(boolean autoIncrement) {
239: this .autoIncrement = autoIncrement;
240: }
241:
242: public boolean isDataTypeDifferent(Column otherColumn) {
243: return this .getDataType() != otherColumn.getDataType()
244: || this .getColumnSize() != otherColumn.getColumnSize()
245: || this .getDecimalDigits() != otherColumn
246: .getDecimalDigits();
247: }
248:
249: @SuppressWarnings({"SimplifiableIfStatement"})
250: public boolean isNullabilityDifferent(Column otherColumn) {
251: if (this .isNullable() == null
252: && otherColumn.isNullable() == null) {
253: return false;
254: }
255: if (this .isNullable() == null
256: && otherColumn.isNullable() != null) {
257: return true;
258: }
259: if (this .isNullable() != null
260: && otherColumn.isNullable() == null) {
261: return true;
262: }
263: return !this .isNullable().equals(otherColumn.isNullable());
264: }
265:
266: public boolean isDifferent(Column otherColumn) {
267: return isDataTypeDifferent(otherColumn)
268: || isNullabilityDifferent(otherColumn);
269: }
270:
271: public boolean isPrimaryKey() {
272: return primaryKey;
273: }
274:
275: public void setPrimaryKey(boolean primaryKey) {
276: this.primaryKey = primaryKey;
277: }
278: }
|