1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package liquibase.database.typeconversion.ext;
27
28 import liquibase.change.ColumnConfig;
29 import liquibase.database.Database;
30 import liquibase.database.core.*;
31 import liquibase.database.structure.Column;
32 import liquibase.database.structure.type.*;
33 import liquibase.database.typeconversion.TypeConverter;
34 import liquibase.exception.DateParseException;
35 import liquibase.exception.UnexpectedLiquibaseException;
36 import liquibase.logging.LogFactory;
37 import liquibase.statement.DatabaseFunction;
38 import liquibase.util.StringUtils;
39
40 import java.math.BigDecimal;
41 import java.math.BigInteger;
42 import java.lang.reflect.Field;
43 import java.sql.Types;
44 import java.text.ParseException;
45 import java.util.Arrays;
46 import java.util.List;
47
48 import static liquibase.ext.Constants.EXTENSION_PRIORITY;
49
50
51
52
53 public abstract class AbstractTypeConverter extends liquibase.database.typeconversion.core.AbstractTypeConverter implements liquibase.database.typeconversion.TypeConverter {
54 protected static final List<Integer> oneParam = Arrays.asList(
55 Types.CHAR,
56 -15,
57 Types.VARCHAR,
58 -9,
59 Types.VARBINARY,
60 Types.DOUBLE,
61 Types.FLOAT
62 );
63
64 protected static final List<Integer> twoParams = Arrays.asList(
65 Types.DECIMAL,
66 Types.NUMERIC,
67 Types.REAL
68 );
69
70 public int getPriority() {
71 return EXTENSION_PRIORITY;
72 }
73
74 @Override
75 public Object convertDatabaseValueToObject(Object value, int databaseDataType, int firstParameter, int secondParameter, Database database) throws ParseException {
76 if (value == null) {
77 return null;
78 } else if (value instanceof String) {
79 return convertToCorrectObjectType(((String) value).trim().replaceFirst("^'", "").replaceFirst("'$", ""), databaseDataType, firstParameter, secondParameter, database);
80 } else {
81 return value;
82 }
83 }
84
85 @Override
86 public String convertToDatabaseTypeString(Column referenceColumn, Database database) {
87 final StringBuilder retval = new StringBuilder();
88 try {
89 retval.append(getSqlTypeName(referenceColumn.getDataType()));
90 }
91 catch (Exception e) {
92 retval.append(referenceColumn.getTypeName());
93 }
94
95
96 final boolean hasOneParam = oneParam.contains(referenceColumn.getDataType());
97 final boolean hasTwoParams = twoParams.contains(referenceColumn.getDataType());
98
99
100 if (hasOneParam || hasTwoParams) {
101 retval.append("(").append(referenceColumn.getColumnSize());
102 if (hasTwoParams) {
103 retval.append(",").append(referenceColumn.getDecimalDigits());
104 }
105 retval.append(")");
106 }
107
108
109 return retval.toString();
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123
124 protected String getSqlTypeName(final int type) throws Exception {
125 for (final Field field : Types.class.getFields()) {
126 final int sql_type = field.getInt(null);
127 if (type == sql_type) {
128 return "java.sql.Types." + field.getName();
129 }
130 }
131 return null;
132 }
133
134 @Override
135 protected DataType getDataType(String columnTypeString, Boolean autoIncrement, String dataTypeName, String precision, String additionalInformation) {
136
137 DataType returnTypeName = null;
138 if (dataTypeName.equalsIgnoreCase("BIGINT")) {
139 returnTypeName = getBigIntType();
140 } else if (dataTypeName.equalsIgnoreCase("NUMBER")
141 || dataTypeName.equalsIgnoreCase("DECIMAL")
142 || dataTypeName.equalsIgnoreCase("NUMERIC")) {
143 returnTypeName = getNumberType();
144 } else if (dataTypeName.equalsIgnoreCase("BLOB")) {
145 returnTypeName = getBlobType();
146 } else if (dataTypeName.equalsIgnoreCase("BOOLEAN")) {
147 returnTypeName = getBooleanType();
148 } else if (dataTypeName.equalsIgnoreCase("CHAR")) {
149 returnTypeName = getCharType();
150 } else if (dataTypeName.equalsIgnoreCase("CLOB")) {
151 returnTypeName = getClobType();
152 } else if (dataTypeName.equalsIgnoreCase("CURRENCY")) {
153 returnTypeName = getCurrencyType();
154 } else if (dataTypeName.equalsIgnoreCase("DATE") || dataTypeName.equalsIgnoreCase(getDateType().getDataTypeName())) {
155 returnTypeName = getDateType();
156 } else if (dataTypeName.equalsIgnoreCase("DATETIME") || dataTypeName.equalsIgnoreCase(getDateTimeType().getDataTypeName())) {
157 returnTypeName = getDateTimeType();
158 } else if (dataTypeName.equalsIgnoreCase("DOUBLE")) {
159 returnTypeName = getDoubleType();
160 } else if (dataTypeName.equalsIgnoreCase("FLOAT")) {
161 returnTypeName = getFloatType();
162 } else if (dataTypeName.equalsIgnoreCase("INT")) {
163 returnTypeName = getIntType();
164 } else if (dataTypeName.equalsIgnoreCase("INTEGER")) {
165 returnTypeName = getIntType();
166 } else if (dataTypeName.equalsIgnoreCase("LONGBLOB")) {
167 returnTypeName = getLongBlobType();
168 } else if (dataTypeName.equalsIgnoreCase("LONGVARBINARY")) {
169 returnTypeName = getBlobType();
170 } else if (dataTypeName.equalsIgnoreCase("LONGVARCHAR")) {
171 returnTypeName = getClobType();
172 } else if (dataTypeName.equalsIgnoreCase("SMALLINT")) {
173 returnTypeName = getSmallIntType();
174 } else if (dataTypeName.equalsIgnoreCase("TEXT")) {
175 returnTypeName = getClobType();
176 } else if (dataTypeName.equalsIgnoreCase("TIME") || dataTypeName.equalsIgnoreCase(getTimeType().getDataTypeName())) {
177 returnTypeName = getTimeType();
178 } else if (dataTypeName.toUpperCase().contains("TIMESTAMP")) {
179 returnTypeName = getDateTimeType();
180 } else if (dataTypeName.equalsIgnoreCase("TINYINT")) {
181 returnTypeName = getTinyIntType();
182 } else if (dataTypeName.equalsIgnoreCase("UUID")) {
183 returnTypeName = getUUIDType();
184 } else if (dataTypeName.equalsIgnoreCase("VARCHAR")) {
185 returnTypeName = getVarcharType();
186 } else if (dataTypeName.equalsIgnoreCase("NVARCHAR")) {
187 returnTypeName = getNVarcharType();
188 } else {
189 return new CustomType(columnTypeString,0,2);
190 }
191
192 if (returnTypeName == null) {
193 throw new UnexpectedLiquibaseException("Could not determine " + dataTypeName + " for " + this.getClass().getName());
194 }
195 addPrecisionToType(precision, returnTypeName);
196 returnTypeName.setAdditionalInformation(additionalInformation);
197
198 return returnTypeName;
199 }
200 }