use of liquibase.statement.SqlStatement in project liquibase by liquibase.
the class AbstractJdbcDatabase method dropDatabaseObjects.
// ------- DATABASE OBJECT DROPPING METHODS ---- //
/**
* Drops all objects owned by the connected user.
*/
@Override
public void dropDatabaseObjects(final CatalogAndSchema schemaToDrop) throws LiquibaseException {
ObjectQuotingStrategy currentStrategy = this.getObjectQuotingStrategy();
this.setObjectQuotingStrategy(ObjectQuotingStrategy.QUOTE_ALL_OBJECTS);
try {
DatabaseSnapshot snapshot;
try {
final SnapshotControl snapshotControl = new SnapshotControl(this);
final Set<Class<? extends DatabaseObject>> typesToInclude = snapshotControl.getTypesToInclude();
//We do not need to remove indexes and primary/unique keys explicitly. They should be removed
//as part of tables.
typesToInclude.remove(Index.class);
typesToInclude.remove(PrimaryKey.class);
typesToInclude.remove(UniqueConstraint.class);
if (supportsForeignKeyDisable()) {
//We do not remove ForeignKey because they will be disabled and removed as parts of tables.
typesToInclude.remove(ForeignKey.class);
}
final long createSnapshotStarted = System.currentTimeMillis();
snapshot = SnapshotGeneratorFactory.getInstance().createSnapshot(schemaToDrop, this, snapshotControl);
LogFactory.getLogger().debug(String.format("Database snapshot generated in %d ms. Snapshot includes: %s", System.currentTimeMillis() - createSnapshotStarted, typesToInclude));
} catch (LiquibaseException e) {
throw new UnexpectedLiquibaseException(e);
}
final long changeSetStarted = System.currentTimeMillis();
DiffResult diffResult = DiffGeneratorFactory.getInstance().compare(new EmptyDatabaseSnapshot(this), snapshot, new CompareControl(snapshot.getSnapshotControl().getTypesToInclude()));
List<ChangeSet> changeSets = new DiffToChangeLog(diffResult, new DiffOutputControl(true, true, false, null).addIncludedSchema(schemaToDrop)).generateChangeSets();
LogFactory.getLogger().debug(String.format("ChangeSet to Remove Database Objects generated in %d ms.", System.currentTimeMillis() - changeSetStarted));
boolean previousAutoCommit = this.getAutoCommitMode();
//clear out currently executed statements
this.commit();
//some DDL doesn't work in autocommit mode
this.setAutoCommit(false);
final boolean reEnableFK = supportsForeignKeyDisable() && disableForeignKeyChecks();
try {
for (ChangeSet changeSet : changeSets) {
changeSet.setFailOnError(false);
for (Change change : changeSet.getChanges()) {
if (change instanceof DropTableChange) {
((DropTableChange) change).setCascadeConstraints(true);
}
SqlStatement[] sqlStatements = change.generateStatements(this);
for (SqlStatement statement : sqlStatements) {
ExecutorService.getInstance().getExecutor(this).execute(statement);
}
}
this.commit();
}
} finally {
if (reEnableFK) {
enableForeignKeyChecks();
}
}
ChangeLogHistoryServiceFactory.getInstance().getChangeLogService(this).destroy();
LockServiceFactory.getInstance().getLockService(this).destroy();
this.setAutoCommit(previousAutoCommit);
} finally {
this.setObjectQuotingStrategy(currentStrategy);
this.commit();
}
}
use of liquibase.statement.SqlStatement in project liquibase by liquibase.
the class UpdateDataChange method generateStatements.
@Override
public SqlStatement[] generateStatements(Database database) {
boolean needsPreparedStatement = false;
for (ColumnConfig column : getColumns()) {
if (column.getValueBlobFile() != null) {
needsPreparedStatement = true;
}
if (column.getValueClobFile() != null) {
needsPreparedStatement = true;
}
if (database instanceof OracleDatabase && column.getType() != null && column.getType().equalsIgnoreCase("CLOB") && column.getValue() != null && column.getValue().length() >= 4000) {
needsPreparedStatement = true;
}
}
if (needsPreparedStatement) {
UpdateExecutablePreparedStatement statement = new UpdateExecutablePreparedStatement(database, catalogName, schemaName, tableName, columns, getChangeSet(), this.getResourceAccessor());
statement.setWhereClause(where);
for (ColumnConfig whereParam : whereParams) {
if (whereParam.getName() != null) {
statement.addWhereColumnName(whereParam.getName());
}
statement.addWhereParameter(whereParam.getValueObject());
}
return new SqlStatement[] { statement };
}
UpdateStatement statement = new UpdateStatement(getCatalogName(), getSchemaName(), getTableName());
for (ColumnConfig column : getColumns()) {
statement.addNewColumnValue(column.getName(), column.getValueObject());
}
statement.setWhereClause(where);
for (ColumnConfig whereParam : whereParams) {
if (whereParam.getName() != null) {
statement.addWhereColumnName(whereParam.getName());
}
statement.addWhereParameter(whereParam.getValueObject());
}
return new SqlStatement[] { statement };
}
use of liquibase.statement.SqlStatement in project liquibase by liquibase.
the class ChangeSet method rollback.
public void rollback(Database database) throws RollbackFailedException {
try {
Executor executor = ExecutorService.getInstance().getExecutor(database);
executor.comment("Rolling Back ChangeSet: " + toString());
database.setObjectQuotingStrategy(objectQuotingStrategy);
// set auto-commit based on runInTransaction if database supports DDL in transactions
if (database.supportsDDLInTransaction()) {
database.setAutoCommit(!runInTransaction);
}
RanChangeSet ranChangeSet = database.getRanChangeSet(this);
if (hasCustomRollbackChanges()) {
final List<SqlStatement> statements = new LinkedList<SqlStatement>();
for (Change change : rollback.getChanges()) {
if (((change instanceof DbmsTargetedChange)) && !DatabaseList.definitionMatches(((DbmsTargetedChange) change).getDbms(), database, true)) {
continue;
}
ValidationErrors errors = change.validate(database);
if (errors.hasErrors()) {
throw new RollbackFailedException("Rollback statement failed validation: " + errors.toString());
}
SqlStatement[] changeStatements = change.generateStatements(database);
if (changeStatements != null) {
statements.addAll(Arrays.asList(changeStatements));
}
}
if (!statements.isEmpty()) {
database.executeRollbackStatements(statements.toArray(new SqlStatement[] {}), sqlVisitors);
}
} else {
List<Change> changes = getChanges();
for (int i = changes.size() - 1; i >= 0; i--) {
Change change = changes.get(i);
database.executeRollbackStatements(change, sqlVisitors);
}
}
if (runInTransaction) {
database.commit();
}
log.debug("ChangeSet " + toString() + " has been successfully rolled back.");
} catch (Exception e) {
try {
database.rollback();
} catch (DatabaseException e1) {
//ok
}
throw new RollbackFailedException(e);
} finally {
// but only if the database supports DDL in transactions
if (!runInTransaction && database.supportsDDLInTransaction()) {
try {
database.setAutoCommit(false);
} catch (DatabaseException e) {
throw new RollbackFailedException("Could not resetInternalState autocommit", e);
}
}
}
}
use of liquibase.statement.SqlStatement in project liquibase by liquibase.
the class InsertDataChange method generateStatements.
@Override
public SqlStatement[] generateStatements(Database database) {
boolean needsPreparedStatement = false;
for (ColumnConfig column : columns) {
if (column.getValueBlobFile() != null) {
needsPreparedStatement = true;
}
if (column.getValueClobFile() != null) {
needsPreparedStatement = true;
}
if (!needsPreparedStatement && database instanceof InformixDatabase) {
if (column.getValue() != null) {
try {
Column snapshot = SnapshotGeneratorFactory.getInstance().createSnapshot(new Column(column), database);
if (snapshot != null) {
needsPreparedStatement = true;
}
} catch (Exception ignore) {
//assume it's not a clob
}
}
}
}
if (needsPreparedStatement) {
return new SqlStatement[] { new InsertExecutablePreparedStatement(database, catalogName, schemaName, tableName, columns, getChangeSet(), this.getResourceAccessor()) };
}
InsertStatement statement = new InsertStatement(getCatalogName(), getSchemaName(), getTableName());
for (ColumnConfig column : columns) {
if (database.supportsAutoIncrement() && column.isAutoIncrement() != null && column.isAutoIncrement()) {
// skip auto increment columns as they will be generated by the database
continue;
}
statement.addColumnValue(column.getName(), column.getValueObject());
}
return new SqlStatement[] { statement };
}
use of liquibase.statement.SqlStatement 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) {
;
}
}
}
}
Aggregations