use of liquibase.change.ColumnConfig in project liquibase by liquibase.
the class LoadDataChange method generateStatements.
@Override
public SqlStatement[] generateStatements(Database database) {
CSVReader reader = null;
try {
reader = getCSVReader();
if (reader == null) {
throw new UnexpectedLiquibaseException("Unable to read file " + this.getFile());
}
String[] headers = reader.readNext();
if (headers == null) {
throw new UnexpectedLiquibaseException("Data file " + getFile() + " was empty");
}
List<SqlStatement> statements = new ArrayList<SqlStatement>();
boolean anyPreparedStatements = false;
String[] line;
// Start at '1' to take into account the header (already processed)
int lineNumber = 1;
boolean isCommentingEnabled = StringUtils.isNotEmpty(commentLineStartsWith);
while ((line = reader.readNext()) != null) {
lineNumber++;
if (line.length == 0 || (line.length == 1 && StringUtils.trimToNull(line[0]) == null) || (isCommentingEnabled && isLineCommented(line))) {
//nothing on this line
continue;
}
// (Failure could indicate unquoted strings with commas, for example).
if (line.length != headers.length) {
throw new UnexpectedLiquibaseException("CSV file " + getFile() + " Line " + lineNumber + " has " + line.length + " values defined, Header has " + headers.length + ". Numbers MUST be equal (check for unquoted string with embedded commas)");
}
boolean needsPreparedStatement = false;
List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
for (int i = 0; i < headers.length; i++) {
Object value = line[i];
String columnName = headers[i].trim();
ColumnConfig valueConfig = new ColumnConfig();
ColumnConfig columnConfig = getColumnConfig(i, headers[i].trim());
if (columnConfig != null) {
if ("skip".equalsIgnoreCase(columnConfig.getType())) {
continue;
}
// don't overwrite header name unless there is actually a value to override it with
if (columnConfig.getName() != null) {
columnName = columnConfig.getName();
}
valueConfig.setName(columnName);
if (columnConfig.getType() != null) {
if (columnConfig.getType().equalsIgnoreCase("BOOLEAN")) {
if (value.toString().equalsIgnoreCase("NULL")) {
valueConfig.setValue(null);
} else {
valueConfig.setValueBoolean(BooleanParser.parseBoolean(value.toString().toLowerCase()));
}
} else if (columnConfig.getType().equalsIgnoreCase("NUMERIC")) {
if (value.toString().equalsIgnoreCase("NULL")) {
valueConfig.setValue(null);
} else {
valueConfig.setValueNumeric(value.toString());
}
} else if (columnConfig.getType().toLowerCase().contains("date") || columnConfig.getType().toLowerCase().contains("time")) {
if (value.toString().equalsIgnoreCase("NULL")) {
valueConfig.setValue(null);
} else {
valueConfig.setValueDate(value.toString());
}
} else if (columnConfig.getType().equalsIgnoreCase("STRING")) {
if (value.toString().equalsIgnoreCase("NULL")) {
valueConfig.setValue(null);
} else {
valueConfig.setValue(value.toString());
}
} else if (columnConfig.getType().equalsIgnoreCase("COMPUTED")) {
if (value.toString().equalsIgnoreCase("NULL")) {
valueConfig.setValue(null);
} else {
liquibase.statement.DatabaseFunction function = new liquibase.statement.DatabaseFunction(value.toString());
valueConfig.setValueComputed(function);
}
} else if (columnConfig.getType().equalsIgnoreCase("SEQUENCE")) {
String sequenceName;
if (value.toString().equalsIgnoreCase("NULL")) {
sequenceName = columnConfig.getDefaultValue();
if (sequenceName == null) {
throw new UnexpectedLiquibaseException("Must set a sequence name in the loadData column defaultValue attribute");
}
} else {
sequenceName = value.toString();
}
liquibase.statement.SequenceNextValueFunction function = new liquibase.statement.SequenceNextValueFunction(sequenceName);
valueConfig.setValueComputed(function);
} else if (columnConfig.getType().equalsIgnoreCase("BLOB")) {
if (value.toString().equalsIgnoreCase("NULL")) {
valueConfig.setValue(null);
} else {
valueConfig.setValueBlobFile(value.toString());
needsPreparedStatement = true;
}
} else if (columnConfig.getType().equalsIgnoreCase("CLOB")) {
if (value.toString().equalsIgnoreCase("NULL")) {
valueConfig.setValue(null);
} else {
valueConfig.setValueClobFile(value.toString());
needsPreparedStatement = true;
}
} else {
throw new UnexpectedLiquibaseException("loadData type of " + columnConfig.getType() + " is not supported. Please use BOOLEAN, NUMERIC, DATE, STRING, COMPUTED, SEQUENCE or SKIP");
}
}
} else {
if (columnName.contains("(") || columnName.contains(")") && database instanceof AbstractJdbcDatabase) {
columnName = ((AbstractJdbcDatabase) database).quoteObject(columnName, Column.class);
}
valueConfig.setName(columnName);
if (value == null || value.toString().equalsIgnoreCase("NULL")) {
// value is always going to be a string unless overridden by ColumnConfig
valueConfig.setValue((String) value);
} else {
valueConfig.setValue(value.toString());
}
}
columns.add(valueConfig);
}
if (needsPreparedStatement) {
anyPreparedStatements = true;
statements.add(new InsertExecutablePreparedStatement(database, getCatalogName(), getSchemaName(), getTableName(), columns, getChangeSet(), getResourceAccessor()));
} else {
InsertStatement insertStatement = this.createStatement(getCatalogName(), getSchemaName(), getTableName());
for (ColumnConfig column : columns) {
String columnName = column.getName();
Object value = column.getValueObject();
if (value == null) {
value = "NULL";
}
insertStatement.addColumnValue(columnName, value);
}
statements.add(insertStatement);
}
}
if (anyPreparedStatements) {
return statements.toArray(new SqlStatement[statements.size()]);
} else {
InsertSetStatement statementSet = this.createStatementSet(getCatalogName(), getSchemaName(), getTableName());
for (SqlStatement stmt : statements) {
statementSet.addInsertStatement((InsertStatement) stmt);
}
if (database instanceof MSSQLDatabase || database instanceof MySQLDatabase || database instanceof PostgresDatabase) {
List<InsertStatement> innerStatements = statementSet.getStatements();
if (innerStatements != null && innerStatements.size() > 0 && innerStatements.get(0) instanceof InsertOrUpdateStatement) {
//cannot do insert or update in a single statement
return statementSet.getStatementsArray();
}
// we only return a single "statement" - it's capable of emitting multiple sub-statements, should the need arise, on generation.
return new SqlStatement[] { statementSet };
} else {
return statementSet.getStatementsArray();
}
}
} catch (IOException e) {
throw new RuntimeException(e);
} catch (UnexpectedLiquibaseException ule) {
if (getChangeSet() != null && getChangeSet().getFailOnError() != null && !getChangeSet().getFailOnError()) {
Logger log = LogFactory.getLogger();
log.info("Change set " + getChangeSet().toString(false) + " failed, but failOnError was false. Error: " + ule.getMessage());
return new SqlStatement[0];
} else {
throw ule;
}
} finally {
if (null != reader) {
try {
reader.close();
} catch (IOException e) {
;
}
}
}
}
use of liquibase.change.ColumnConfig in project liquibase by liquibase.
the class MissingDataChangeGenerator method fixMissing.
@Override
public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl outputControl, Database referenceDatabase, Database comparisionDatabase, ChangeGeneratorChain chain) {
Statement stmt = null;
ResultSet rs = null;
try {
Data data = (Data) missingObject;
Table table = data.getTable();
if (referenceDatabase.isLiquibaseObject(table)) {
return null;
}
String sql = "SELECT * FROM " + referenceDatabase.escapeTableName(table.getSchema().getCatalogName(), table.getSchema().getName(), table.getName());
stmt = ((JdbcConnection) referenceDatabase.getConnection()).createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(1000);
rs = stmt.executeQuery(sql);
List<String> columnNames = new ArrayList<String>();
for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
columnNames.add(rs.getMetaData().getColumnName(i + 1));
}
List<Change> changes = new ArrayList<Change>();
while (rs.next()) {
InsertDataChange change = new InsertDataChange();
if (outputControl.getIncludeCatalog()) {
change.setCatalogName(table.getSchema().getCatalogName());
}
if (outputControl.getIncludeSchema()) {
change.setSchemaName(table.getSchema().getName());
}
change.setTableName(table.getName());
// loop over all columns for this row
for (int i = 0; i < columnNames.size(); i++) {
ColumnConfig column = new ColumnConfig();
column.setName(columnNames.get(i));
Object value = JdbcUtils.getResultSetValue(rs, i + 1);
if (value == null) {
column.setValue(null);
} else if (value instanceof Number) {
column.setValueNumeric((Number) value);
} else if (value instanceof Boolean) {
column.setValueBoolean((Boolean) value);
} else if (value instanceof Date) {
column.setValueDate((Date) value);
} else if (value instanceof byte[]) {
if (referenceDatabase instanceof InformixDatabase) {
column.setValue(new String((byte[]) value, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()));
}
column.setValueComputed(new DatabaseFunction("UNSUPPORTED FOR DIFF: BINARY DATA"));
} else {
// fall back to simple string
column.setValue(value.toString().replace("\\", "\\\\"));
}
change.addColumn(column);
}
// for each row, add a new change
// (there will be one group per table)
changes.add(change);
}
return changes.toArray(new Change[changes.size()]);
} catch (Exception e) {
throw new UnexpectedLiquibaseException(e);
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException ignore) {
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException ignore) {
}
}
}
}
use of liquibase.change.ColumnConfig in project liquibase by liquibase.
the class AddColumnGeneratorSQLite method generateSql.
@Override
public Sql[] generateSql(final AddColumnStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) {
// SQLite does not support this ALTER TABLE operation until now.
// For more information see: http://www.sqlite.org/omitted.html.
// This is a small work around...
List<Sql> sql = new ArrayList<Sql>();
// define alter table logic
SQLiteDatabase.AlterTableVisitor rename_alter_visitor = new SQLiteDatabase.AlterTableVisitor() {
public ColumnConfig[] getColumnsToAdd() {
return new ColumnConfig[] { new ColumnConfig().setName(statement.getColumnName()).setType(statement.getColumnType()).setAutoIncrement(statement.isAutoIncrement()) };
}
public boolean copyThisColumn(ColumnConfig column) {
return !column.getName().equals(statement.getColumnName());
}
public boolean createThisColumn(ColumnConfig column) {
return true;
}
public boolean createThisIndex(Index index) {
return true;
}
};
try {
// alter table
List<SqlStatement> alterTableStatements = SQLiteDatabase.getAlterTableStatements(rename_alter_visitor, database, statement.getCatalogName(), statement.getSchemaName(), statement.getTableName());
sql.addAll(Arrays.asList(SqlGeneratorFactory.getInstance().generateSql(alterTableStatements.toArray(new SqlStatement[alterTableStatements.size()]), database)));
} catch (DatabaseException e) {
System.err.println(e);
e.printStackTrace();
}
return sql.toArray(new Sql[sql.size()]);
}
use of liquibase.change.ColumnConfig in project liquibase by liquibase.
the class ExecutablePreparedStatementBase method execute.
@Override
public void execute(PreparedStatementFactory factory) throws DatabaseException {
// build the sql statement
List<ColumnConfig> cols = new ArrayList<ColumnConfig>(getColumns().size());
String sql = generateSql(cols);
log.info("Prepared statement: " + sql);
log.debug("Number of columns = " + cols.size());
// create prepared statement
PreparedStatement stmt = factory.create(sql);
try {
// attach params
// index starts from 1
int i = 1;
for (ColumnConfig col : cols) {
log.debug("Applying column parameter = " + i + " for column " + col.getName());
applyColumnParameter(stmt, i, col);
i++;
}
// trigger execution
stmt.execute();
} catch (SQLException e) {
throw new DatabaseException(e);
} finally {
for (Closeable closeable : closeables) {
StreamUtil.closeQuietly(closeable);
}
JdbcUtils.closeStatement(stmt);
}
}
use of liquibase.change.ColumnConfig in project liquibase by liquibase.
the class ExecutablePreparedStatementBase method applyColumnParameter.
private void applyColumnParameter(PreparedStatement stmt, int i, ColumnConfig col) throws SQLException, DatabaseException {
if (col.getValue() != null) {
log.debug("value is string = " + col.getValue());
stmt.setString(i, col.getValue());
} else if (col.getValueBoolean() != null) {
log.debug("value is boolean = " + col.getValueBoolean());
stmt.setBoolean(i, col.getValueBoolean());
} else if (col.getValueNumeric() != null) {
log.debug("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 {
// TODO: Consider throwing an exception here
}
} else if (col.getValueDate() != null) {
log.debug("value is date = " + col.getValueDate());
if (col.getValueDate() instanceof Timestamp) {
stmt.setTimestamp(i, (Timestamp) col.getValueDate());
} else {
stmt.setDate(i, new java.sql.Date(col.getValueDate().getTime()));
}
} else if (col.getValueBlobFile() != null) {
log.debug("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 e) {
// wrap
throw new DatabaseException(e.getMessage(), e);
}
} else if (col.getValueClobFile() != null) {
try {
log.debug("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 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.debug("value is explicit null");
stmt.setNull(i, java.sql.Types.NULL);
}
}
Aggregations