package liquibase.database.typeconversion.core;
import liquibase.database.Database;
import liquibase.database.core.OracleDatabase;
import liquibase.database.structure.Column;
import liquibase.database.structure.type.*;
import java.sql.Types;
import java.text.ParseException;
public class OracleTypeConverter extends AbstractTypeConverter {
public int getPriority() {
return PRIORITY_DATABASE;
}
public boolean supports(Database database) {
return database instanceof OracleDatabase;
}
/**
* Extension of super.getDataType(String columnTypeString, Boolean autoIncrement, String dataTypeName, String precision)<br>
* Contains definition of Oracle's data-types
* */
@Override
protected DataType getDataType(String columnTypeString, Boolean autoIncrement, String dataTypeName, String precision, String additionalInformation) {
// Try to define data type by searching of common standard types
DataType returnTypeName = super.getDataType(columnTypeString, autoIncrement, dataTypeName, precision, additionalInformation);
// If we found CustomType (it means - nothing compatible) then search for oracle types
if (returnTypeName instanceof CustomType) {
if (columnTypeString.toUpperCase().startsWith("VARCHAR2")) {
// Varchar2 type pattern: VARCHAR2(50 BYTE) | VARCHAR2(50 CHAR)
returnTypeName = getVarcharType();
if (precision != null) {
String[] typeParams = precision.split(" ");
returnTypeName.setFirstParameter(typeParams[0].trim());
if (typeParams.length > 1) {
returnTypeName.setUnit(typeParams[1]);
}
}
} else if (columnTypeString.toUpperCase().startsWith("NVARCHAR2")) {
// NVarchar2 type pattern: VARCHAR2(50 BYTE) | VARCHAR2(50 CHAR)
returnTypeName = getNVarcharType();
if (precision != null) {
String[] typeParams = precision.split(" ");
returnTypeName.setFirstParameter(typeParams[0].trim());
if (typeParams.length > 1) {
returnTypeName.setUnit(typeParams[1]);
}
}
}
}
return returnTypeName;
}
@Override
public String convertToDatabaseTypeString(Column referenceColumn, Database database) {
String translatedTypeName = referenceColumn.getTypeName();
if ("NVARCHAR2".equals(translatedTypeName)) {
translatedTypeName = translatedTypeName+ "(" + referenceColumn.getColumnSize() + ")";
} else if ("BINARY_FLOAT".equals(translatedTypeName) || "BINARY_DOUBLE".equals(translatedTypeName)) {
// nothing to do
} else {
translatedTypeName = super.convertToDatabaseTypeString(referenceColumn, database);
}
return translatedTypeName;
}
@Override
public Object convertDatabaseValueToObject(Object defaultValue, int dataType, int columnSize, int decimalDigits, Database database) throws ParseException {
if (defaultValue != null) {
if (defaultValue instanceof String) {
if (dataType == Types.DATE || dataType == Types.TIME || dataType == Types.TIMESTAMP) {
if (((String) defaultValue).indexOf("YYYY-MM-DD HH") > 0) {
defaultValue = ((String) defaultValue).replaceFirst("^to_date\\('", "").replaceFirst("', 'YYYY-MM-DD HH24:MI:SS'\\)$", "");
} else if (((String) defaultValue).indexOf("YYYY-MM-DD") > 0) {
defaultValue = ((String) defaultValue).replaceFirst("^to_date\\('", "").replaceFirst("', 'YYYY-MM-DD'\\)$", "");
} else {
defaultValue = ((String) defaultValue).replaceFirst("^to_date\\('", "").replaceFirst("', 'HH24:MI:SS'\\)$", "");
}
} else if (
dataType == Types.BIGINT ||
dataType == Types.NUMERIC ||
dataType == Types.BIT ||
dataType == Types.SMALLINT ||
dataType == Types.DECIMAL ||
dataType == Types.INTEGER ||
dataType == Types.TINYINT ||
dataType == Types.FLOAT ||
dataType == Types.REAL
) {
/*
* if dataType is numeric-type then cut "(" , ")" symbols
* Cause: Column's default value option may be set by both ways:
* DEFAULT 0
* DEFAULT (0)
* */
defaultValue = ((String) defaultValue).replaceFirst("\\(", "").replaceFirst("\\)", "");
}
defaultValue = ((String) defaultValue).replaceFirst("'\\s*$", "'"); //sometimes oracle adds an extra space after the trailing ' (see http://sourceforge.net/tracker/index.php?func=detail&aid=1824663&group_id=187970&atid=923443).
}
}
return super.convertDatabaseValueToObject(defaultValue, dataType, columnSize, decimalDigits, database);
}
@Override
protected Object convertToCorrectObjectType(String value, int dataType, int columnSize, int decimalDigits, Database database) throws ParseException {
Object returnValue = super.convertToCorrectObjectType(value, dataType, columnSize, decimalDigits, database);
// I'll do it lately.
// It needs to design and create Database Function Dictionary first.
/*if (dataType == Types.BLOB || dataType == Types.TIMESTAMP) {
if (database.containsDatabaseFunction(value)) {
returnValue = value;
}
}*/
return returnValue;
}
@Override
public BooleanType getBooleanType() {
return new BooleanType.NumericBooleanType("NUMBER(1)");
}
@Override
public CurrencyType getCurrencyType() {
return new CurrencyType("NUMBER(15, 2)");
}
@Override
public UUIDType getUUIDType() {
return new UUIDType("RAW(16)");
}
@Override
public TimeType getTimeType() {
return new TimeType("DATE");
}
@Override
public DateTimeType getDateTimeType() {
return new DateTimeType("TIMESTAMP");
}
@Override
public BigIntType getBigIntType() {
return new BigIntType("NUMBER(38,0)");
}
@Override
public IntType getIntType() {
return new IntType("INTEGER");
}
@Override
public VarcharType getVarcharType() {
return new VarcharType("VARCHAR2");
}
@Override
public NVarcharType getNVarcharType() {
return new NVarcharType("NVARCHAR2");
}
@Override
public DoubleType getDoubleType() {
return new DoubleType("FLOAT(24)");
}
@Override
public TinyIntType getTinyIntType() {
return new TinyIntType("NUMBER(3)");
}
}