package liquibase.datatype.core; import liquibase.database.core.*; import liquibase.datatype.DataTypeInfo; import liquibase.datatype.DatabaseDataType; import liquibase.datatype.LiquibaseDataType; import liquibase.exception.DatabaseException; import liquibase.statement.DatabaseFunction; import liquibase.database.Database; import liquibase.util.StringUtils; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; @DataTypeInfo(name="time", aliases = {"java.sql.Types.TIME", "java.sql.Time", "timetz"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT) public class TimeType extends LiquibaseDataType { @Override public DatabaseDataType toDatabaseDataType(Database database) { String originalDefinition = StringUtils.trimToEmpty(getRawDefinition()); if (database instanceof InformixDatabase) { return new DatabaseDataType("INTERVAL HOUR TO FRACTION", 5); } if (database instanceof MSSQLDatabase) { Object[] parameters = getParameters(); try { if (database.getDatabaseMajorVersion() <= 9) { return new DatabaseDataType(database.escapeDataTypeName("datetime")); } } catch (DatabaseException e) { //assume greater than sql 2008 and TIME will work } if (parameters.length == 0) { parameters = new Object[] { 7 }; } else if (parameters.length > 2) { parameters = Arrays.copyOfRange(parameters, 0, 2); } return new DatabaseDataType(database.escapeDataTypeName("time"), parameters); } if (database instanceof MySQLDatabase) { boolean supportsParameters = true; try { supportsParameters = database.getDatabaseMajorVersion() >= 5 && database.getDatabaseMinorVersion() >= 6 && ((MySQLDatabase) database).getDatabasePatchVersion() >= 4; } catch (Exception ignore) { //assume supports parameters } if (supportsParameters && getParameters().length > 0 && Integer.parseInt(getParameters()[0].toString()) <= 6) { return new DatabaseDataType(getName(), getParameters()); } else { return new DatabaseDataType(getName()); } } if (database instanceof OracleDatabase) { return new DatabaseDataType("DATE"); } if (database instanceof PostgresDatabase) { String rawDefinition = originalDefinition.toLowerCase(); if (rawDefinition.contains("tz") || rawDefinition.contains("with time zone")) { return new DatabaseDataType("TIME WITH TIME ZONE"); } else { return new DatabaseDataType("TIME WITHOUT TIME ZONE"); } } return new DatabaseDataType(getName()); } @Override public String objectToSql(Object value, Database database) { if (value == null || value.toString().equalsIgnoreCase("null")) { return null; } else if (value instanceof DatabaseFunction) { return database.generateDatabaseFunctionValue((DatabaseFunction) value); } else if (value instanceof java.sql.Time) { return database.getTimeLiteral(((java.sql.Time) value)); } else { return "'"+((String) value).replaceAll("'","''")+"'"; } } @Override public Object sqlToObject(String value, Database database) { if (zeroTime(value)) { return value; } if (database instanceof DB2Database) { return value.replaceFirst("^\"SYSIBM\".\"TIME\"\\('", "").replaceFirst("'\\)", ""); } if (database instanceof DerbyDatabase) { return value.replaceFirst("^TIME\\('", "").replaceFirst("'\\)", ""); } try { DateFormat timeFormat = getTimeFormat(database); if (database instanceof OracleDatabase && value.matches("to_date\\('\\d+:\\d+:\\d+', 'HH24:MI:SS'\\)")) { timeFormat = new SimpleDateFormat("HH:mm:s"); value = value.replaceFirst(".*?'", "").replaceFirst("',.*",""); } return new java.sql.Time(timeFormat.parse(value).getTime()); } catch (ParseException e) { return new DatabaseFunction(value); } } private boolean zeroTime(String stringVal) { return stringVal.replace("-","").replace(":", "").replace(" ","").replace("0","").equals(""); } protected DateFormat getTimeFormat(Database database) { if (database instanceof DB2Database) { return new SimpleDateFormat("HH.mm.ss"); } return new SimpleDateFormat("HH:mm:ss"); } }