use of liquibase.datatype.LiquibaseDataType in project liquibase by liquibase.
the class ExecutablePreparedStatementBase method applyColumnParameter.
/**
* Sets a single bind variable for a statement to its designated value
* @param stmt the PreparedStatement whose parameter is to be set
* @param i the parameter index (first bind variable is 1)
* @param col a ColumnConfig with information about the column, its type, and the desired value
* @throws SQLException if JDBC objects to a setting (non-existent bind number, wrong column type etc.)
* @throws DatabaseException if an I/O error occurs during the read of LOB values
*/
private void applyColumnParameter(PreparedStatement stmt, int i, ColumnConfig col) throws SQLException, DatabaseException {
final Logger LOG = Scope.getCurrentScope().getLog(getClass());
if (col.getValue() != null) {
LOG.fine("value is string/UUID/blob = " + col.getValue());
if (col.getType() != null && col.getType().equalsIgnoreCase(LoadDataChange.LOAD_DATA_TYPE.UUID.name())) {
stmt.setObject(i, UUID.fromString(col.getValue()));
} else if (col.getType() != null && col.getType().equalsIgnoreCase(LoadDataChange.LOAD_DATA_TYPE.OTHER.name())) {
stmt.setObject(i, col.getValue(), Types.OTHER);
} else if (LoadDataChange.LOAD_DATA_TYPE.BLOB.name().equalsIgnoreCase(col.getType())) {
stmt.setBlob(i, new ByteArrayInputStream(Base64.getDecoder().decode(col.getValue())));
} else if (LoadDataChange.LOAD_DATA_TYPE.CLOB.name().equalsIgnoreCase(col.getType())) {
try {
if (database instanceof PostgresDatabase || database instanceof SQLiteDatabase) {
// JDBC driver does not have the .createClob() call implemented yet
stmt.setString(i, col.getValue());
} else {
Clob clobValue = stmt.getConnection().createClob();
clobValue.setString(1, col.getValue());
stmt.setClob(i, clobValue);
}
} catch (SQLFeatureNotSupportedException e) {
stmt.setString(i, col.getValue());
}
} else {
stmt.setString(i, col.getValue());
}
} else if (col.getValueBoolean() != null) {
LOG.fine("value is boolean = " + col.getValueBoolean());
stmt.setBoolean(i, col.getValueBoolean());
} else if (col.getValueNumeric() != null) {
LOG.fine("value is numeric = " + col.getValueNumeric());
Number number = col.getValueNumeric();
if (number instanceof ColumnConfig.ValueNumeric) {
ColumnConfig.ValueNumeric valueNumeric = (ColumnConfig.ValueNumeric) number;
number = valueNumeric.getDelegate();
}
if (number instanceof Long) {
stmt.setLong(i, number.longValue());
} else if (number instanceof Integer) {
stmt.setInt(i, number.intValue());
} else if (number instanceof Double) {
stmt.setDouble(i, number.doubleValue());
} else if (number instanceof Float) {
stmt.setFloat(i, number.floatValue());
} else if (number instanceof BigDecimal) {
stmt.setBigDecimal(i, (BigDecimal) number);
} else if (number instanceof BigInteger) {
stmt.setInt(i, number.intValue());
} else {
throw new UnexpectedLiquibaseException(String.format(coreBundle.getString("jdbc.bind.parameter.unknown.numeric.value.type"), col.getName(), col.getValueNumeric().toString(), col.getValueNumeric().getClass().getName()));
}
} else if (col.getValueDate() != null) {
LOG.fine("value is date = " + col.getValueDate());
if (col.getValueDate() instanceof Timestamp) {
stmt.setTimestamp(i, (Timestamp) col.getValueDate());
} else if (col.getValueDate() instanceof Time) {
stmt.setTime(i, (Time) col.getValueDate());
} else {
stmt.setDate(i, new java.sql.Date(col.getValueDate().getTime()));
}
} else if (col.getValueBlobFile() != null) {
LOG.fine("value is blob = " + col.getValueBlobFile());
try {
LOBContent<InputStream> lob = toBinaryStream(col.getValueBlobFile());
if (lob.length <= Integer.MAX_VALUE) {
stmt.setBinaryStream(i, lob.content, (int) lob.length);
} else {
stmt.setBinaryStream(i, lob.content, lob.length);
}
} catch (IOException | LiquibaseException e) {
// wrap
throw new DatabaseException(e.getMessage(), e);
}
} else if (col.getValueClobFile() != null) {
try {
LOG.fine("value is clob = " + col.getValueClobFile());
LOBContent<Reader> lob = toCharacterStream(col.getValueClobFile(), col.getEncoding());
if (lob.length <= Integer.MAX_VALUE) {
stmt.setCharacterStream(i, lob.content, (int) lob.length);
} else {
stmt.setCharacterStream(i, lob.content, lob.length);
}
} catch (IOException | LiquibaseException e) {
// wrap
throw new DatabaseException(e.getMessage(), e);
}
} else {
// NULL values might intentionally be set into a change, we must also add them to the prepared statement
LOG.fine("value is explicit null");
if (col.getType() == null) {
stmt.setNull(i, java.sql.Types.NULL);
return;
}
if (col.getType().toLowerCase().contains("datetime")) {
stmt.setNull(i, java.sql.Types.TIMESTAMP);
} else {
//
// Get the array of aliases and use them to find the
// correct java.sql.Types constant for the call to setNull
//
boolean isSet = false;
LiquibaseDataType dataType = DataTypeFactory.getInstance().fromDescription(col.getType(), database);
String[] aliases = dataType.getAliases();
for (String alias : aliases) {
if (!alias.contains("java.sql.Types")) {
continue;
}
String name = alias.replaceAll("java.sql.Types.", "");
try {
JDBCType jdbcType = Enum.valueOf(JDBCType.class, name);
stmt.setNull(i, jdbcType.getVendorTypeNumber());
isSet = true;
} catch (Exception e) {
//
// fall back to using java.sql.Types.NULL by catching any exceptions
//
}
break;
}
if (!isSet) {
LOG.info(String.format("Using java.sql.Types.NULL to set null value for type %s", dataType.getName()));
stmt.setNull(i, java.sql.Types.NULL);
}
}
}
}
use of liquibase.datatype.LiquibaseDataType in project liquibase by liquibase.
the class AddDefaultValueGenerator method validate.
@Override
public ValidationErrors validate(AddDefaultValueStatement addDefaultValueStatement, Database database, SqlGeneratorChain sqlGeneratorChain) {
Object defaultValue = addDefaultValueStatement.getDefaultValue();
ValidationErrors validationErrors = new ValidationErrors();
validationErrors.checkRequiredField("defaultValue", defaultValue, true);
validationErrors.checkRequiredField("columnName", addDefaultValueStatement.getColumnName());
validationErrors.checkRequiredField("tableName", addDefaultValueStatement.getTableName());
if (!database.supportsSequences() && (defaultValue instanceof SequenceNextValueFunction)) {
validationErrors.addError("Database " + database.getShortName() + " does not support sequences");
}
if (database instanceof HsqlDatabase) {
if (defaultValue instanceof SequenceNextValueFunction) {
validationErrors.addError("Database " + database.getShortName() + " does not support adding sequence-based default values");
} else if ((defaultValue instanceof DatabaseFunction) && !HsqlDatabase.supportsDefaultValueComputed(addDefaultValueStatement.getColumnDataType(), defaultValue.toString())) {
validationErrors.addError("Database " + database.getShortName() + " does not support adding function-based default values");
}
}
String columnDataType = addDefaultValueStatement.getColumnDataType();
if (columnDataType != null) {
LiquibaseDataType dataType = DataTypeFactory.getInstance().fromDescription(columnDataType, database);
boolean typeMismatch = false;
if (dataType instanceof BooleanType) {
if (!(defaultValue instanceof Boolean) && !(defaultValue instanceof DatabaseFunction)) {
typeMismatch = true;
}
} else if (dataType instanceof CharType) {
if (!(defaultValue instanceof String) && !(defaultValue instanceof DatabaseFunction)) {
typeMismatch = true;
}
}
if (typeMismatch) {
validationErrors.addError("Default value of " + defaultValue + " does not match defined type of " + columnDataType);
}
}
return validationErrors;
}
use of liquibase.datatype.LiquibaseDataType in project liquibase by liquibase.
the class MissingTableChangeGenerator method setDefaultValue.
public static void setDefaultValue(ColumnConfig columnConfig, Column column, Database database) {
LiquibaseDataType dataType = DataTypeFactory.getInstance().from(column.getType(), database);
Object defaultValue = column.getDefaultValue();
if (defaultValue == null) {
// do nothing
} else if (column.isAutoIncrement()) {
// do nothing
} else if (defaultValue instanceof Date) {
columnConfig.setDefaultValueDate((Date) defaultValue);
} else if (defaultValue instanceof Boolean) {
columnConfig.setDefaultValueBoolean(((Boolean) defaultValue));
} else if (defaultValue instanceof Number) {
columnConfig.setDefaultValueNumeric(((Number) defaultValue));
} else if (defaultValue instanceof DatabaseFunction) {
DatabaseFunction function = (DatabaseFunction) defaultValue;
if ("current".equals(function.getValue())) {
if (database instanceof InformixDatabase) {
if (dataType instanceof DateTimeType) {
if ((dataType.getAdditionalInformation() == null) || dataType.getAdditionalInformation().isEmpty()) {
if ((dataType.getParameters() != null) && (dataType.getParameters().length > 0)) {
String parameter = String.valueOf(dataType.getParameters()[0]);
if ("4365".equals(parameter)) {
function = new DatabaseFunction("current year to fraction(3)");
}
if ("3594".equals(parameter)) {
function = new DatabaseFunction("current year to second");
}
if ("3080".equals(parameter)) {
function = new DatabaseFunction("current year to minute");
}
if ("2052".equals(parameter)) {
function = new DatabaseFunction("current year to day");
}
}
}
}
}
}
columnConfig.setDefaultValueComputed(function);
} else {
String defaultValueString = null;
try {
defaultValueString = DataTypeFactory.getInstance().from(column.getType(), database).objectToSql(defaultValue, database);
} catch (NullPointerException e) {
throw e;
}
if (defaultValueString != null) {
defaultValueString = defaultValueString.replaceFirst("'", "").replaceAll("'$", "");
}
columnConfig.setDefaultValue(defaultValueString);
}
columnConfig.setDefaultValueConstraintName(column.getDefaultValueConstraintName());
}
use of liquibase.datatype.LiquibaseDataType in project liquibase by liquibase.
the class ChangedColumnChangeGenerator method handleDefaultValueDifferences.
protected void handleDefaultValueDifferences(Column column, ObjectDifferences differences, DiffOutputControl control, List<Change> changes, Database referenceDatabase, Database comparisonDatabase) {
Difference difference = differences.getDifference("defaultValue");
if (difference != null) {
Object value = difference.getReferenceValue();
LiquibaseDataType columnDataType = DataTypeFactory.getInstance().from(column.getType(), comparisonDatabase);
if (value == null) {
DropDefaultValueChange change = new DropDefaultValueChange();
if (control.getIncludeCatalog()) {
change.setCatalogName(column.getRelation().getSchema().getCatalog().getName());
}
if (control.getIncludeSchema()) {
change.setSchemaName(column.getRelation().getSchema().getName());
}
change.setTableName(column.getRelation().getName());
change.setColumnName(column.getName());
change.setColumnDataType(columnDataType.toString());
changes.add(change);
} else if (shouldTriggerAddDefaultChange(column, difference, comparisonDatabase)) {
AddDefaultValueChange change = new AddDefaultValueChange();
if (control.getIncludeCatalog()) {
change.setCatalogName(column.getRelation().getSchema().getCatalog().getName());
}
if (control.getIncludeSchema()) {
change.setSchemaName(column.getRelation().getSchema().getName());
}
change.setTableName(column.getRelation().getName());
change.setColumnName(column.getName());
change.setColumnDataType(columnDataType.toString());
//
if (value instanceof Boolean || columnDataType instanceof BooleanType) {
if (value instanceof Boolean) {
change.setDefaultValueBoolean((Boolean) value);
} else if (columnDataType instanceof BooleanType) {
if (value instanceof DatabaseFunction) {
if (value.equals(new DatabaseFunction("'false'"))) {
change.setDefaultValueBoolean(false);
} else if (value.equals(new DatabaseFunction("'true'"))) {
change.setDefaultValueBoolean(true);
} else {
change.setDefaultValueComputed(((DatabaseFunction) value));
}
}
}
} else if (value instanceof Date) {
change.setDefaultValueDate(new ISODateFormat().format(((Date) value)));
} else if (value instanceof Number) {
change.setDefaultValueNumeric(value.toString());
} else if (value instanceof DatabaseFunction) {
change.setDefaultValueComputed(((DatabaseFunction) value));
} else {
change.setDefaultValue(value.toString());
}
change.setDefaultValueConstraintName(column.getDefaultValueConstraintName());
changes.add(change);
}
}
}
use of liquibase.datatype.LiquibaseDataType in project liquibase by liquibase.
the class AddNotNullConstraintChange method generateStatements.
@Override
public SqlStatement[] generateStatements(Database database) {
List<SqlStatement> statements = new ArrayList<>();
if (defaultNullValue != null && !defaultNullValue.equalsIgnoreCase("null")) {
final String columnDataType = this.getColumnDataType();
Object finalDefaultNullValue = defaultNullValue;
if (columnDataType != null) {
final LiquibaseDataType datatype = DataTypeFactory.getInstance().fromDescription(columnDataType, database);
if (datatype instanceof BooleanType) {
// need to detect a boolean or bit type and handle it correctly sometimes or it is not converted to the correct datatype
finalDefaultNullValue = datatype.objectToSql(finalDefaultNullValue, database);
if (finalDefaultNullValue.equals("0")) {
finalDefaultNullValue = 0;
} else if (finalDefaultNullValue.equals("1")) {
finalDefaultNullValue = 1;
}
if (columnDataType.toLowerCase().contains("bit")) {
if (BooleanUtil.parseBoolean(finalDefaultNullValue.toString())) {
finalDefaultNullValue = 1;
} else {
finalDefaultNullValue = 0;
}
}
if (database instanceof PostgresDatabase) {
if (finalDefaultNullValue.equals(0)) {
finalDefaultNullValue = new DatabaseFunction("B'0'");
} else if (finalDefaultNullValue.equals(1)) {
finalDefaultNullValue = new DatabaseFunction("B'1'");
}
}
}
}
statements.add(new UpdateStatement(getCatalogName(), getSchemaName(), getTableName()).addNewColumnValue(getColumnName(), finalDefaultNullValue).setWhereClause(database.escapeObjectName(getColumnName(), Column.class) + " IS NULL"));
}
statements.add(new SetNullableStatement(getCatalogName(), getSchemaName(), getTableName(), getColumnName(), getColumnDataType(), false, getConstraintName(), shouldValidate));
if (database instanceof DB2Database) {
statements.add(new ReorganizeTableStatement(getCatalogName(), getSchemaName(), getTableName()));
}
return statements.toArray(new SqlStatement[statements.size()]);
}
Aggregations