Search in sources :

Example 1 with LiquibaseDataType

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);
            }
        }
    }
}
Also used : ColumnConfig(liquibase.change.ColumnConfig) Logger(liquibase.logging.Logger) java.sql(java.sql) LiquibaseDataType(liquibase.datatype.LiquibaseDataType) BigDecimal(java.math.BigDecimal) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException) DatabaseException(liquibase.exception.DatabaseException) LiquibaseException(liquibase.exception.LiquibaseException) BigInteger(java.math.BigInteger) PostgresDatabase(liquibase.database.core.PostgresDatabase) SQLiteDatabase(liquibase.database.core.SQLiteDatabase) BigInteger(java.math.BigInteger) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException) LiquibaseException(liquibase.exception.LiquibaseException) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException) DatabaseException(liquibase.exception.DatabaseException)

Example 2 with LiquibaseDataType

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;
}
Also used : HsqlDatabase(liquibase.database.core.HsqlDatabase) DatabaseFunction(liquibase.statement.DatabaseFunction) ValidationErrors(liquibase.exception.ValidationErrors) LiquibaseDataType(liquibase.datatype.LiquibaseDataType) BooleanType(liquibase.datatype.core.BooleanType) SequenceNextValueFunction(liquibase.statement.SequenceNextValueFunction) CharType(liquibase.datatype.core.CharType)

Example 3 with LiquibaseDataType

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());
}
Also used : DateTimeType(liquibase.datatype.core.DateTimeType) InformixDatabase(liquibase.database.core.InformixDatabase) DatabaseFunction(liquibase.statement.DatabaseFunction) LiquibaseDataType(liquibase.datatype.LiquibaseDataType) DatabaseObject(liquibase.structure.DatabaseObject)

Example 4 with LiquibaseDataType

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);
        }
    }
}
Also used : ISODateFormat(liquibase.util.ISODateFormat) DatabaseFunction(liquibase.statement.DatabaseFunction) LiquibaseDataType(liquibase.datatype.LiquibaseDataType) BooleanType(liquibase.datatype.core.BooleanType) DatabaseObject(liquibase.structure.DatabaseObject) Difference(liquibase.diff.Difference) Date(java.util.Date)

Example 5 with LiquibaseDataType

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()]);
}
Also used : DB2Database(liquibase.database.core.DB2Database) UpdateStatement(liquibase.statement.core.UpdateStatement) DatabaseFunction(liquibase.statement.DatabaseFunction) ReorganizeTableStatement(liquibase.statement.core.ReorganizeTableStatement) LiquibaseDataType(liquibase.datatype.LiquibaseDataType) ArrayList(java.util.ArrayList) BooleanType(liquibase.datatype.core.BooleanType) SqlStatement(liquibase.statement.SqlStatement) PostgresDatabase(liquibase.database.core.PostgresDatabase) SetNullableStatement(liquibase.statement.core.SetNullableStatement) Column(liquibase.structure.core.Column)

Aggregations

LiquibaseDataType (liquibase.datatype.LiquibaseDataType)12 DatabaseFunction (liquibase.statement.DatabaseFunction)5 PostgresDatabase (liquibase.database.core.PostgresDatabase)4 BooleanType (liquibase.datatype.core.BooleanType)4 ArrayList (java.util.ArrayList)3 ColumnConfig (liquibase.change.ColumnConfig)3 MSSQLDatabase (liquibase.database.core.MSSQLDatabase)3 MySQLDatabase (liquibase.database.core.MySQLDatabase)3 SQLiteDatabase (liquibase.database.core.SQLiteDatabase)3 Column (liquibase.structure.core.Column)3 BigDecimal (java.math.BigDecimal)2 BigInteger (java.math.BigInteger)2 Date (java.util.Date)2 Change (liquibase.change.Change)2 AbstractDb2Database (liquibase.database.core.AbstractDb2Database)2 HsqlDatabase (liquibase.database.core.HsqlDatabase)2 OracleDatabase (liquibase.database.core.OracleDatabase)2 CharType (liquibase.datatype.core.CharType)2 Difference (liquibase.diff.Difference)2 UnexpectedLiquibaseException (liquibase.exception.UnexpectedLiquibaseException)2