Search in sources :

Example 1 with SqlStatement

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();
    }
}
Also used : DiffOutputControl(liquibase.diff.output.DiffOutputControl) Change(liquibase.change.Change) DropTableChange(liquibase.change.core.DropTableChange) SqlStatement(liquibase.statement.SqlStatement) EmptyDatabaseSnapshot(liquibase.snapshot.EmptyDatabaseSnapshot) DatabaseObject(liquibase.structure.DatabaseObject) CompareControl(liquibase.diff.compare.CompareControl) DiffToChangeLog(liquibase.diff.output.changelog.DiffToChangeLog) DropTableChange(liquibase.change.core.DropTableChange) DiffResult(liquibase.diff.DiffResult) DatabaseSnapshot(liquibase.snapshot.DatabaseSnapshot) EmptyDatabaseSnapshot(liquibase.snapshot.EmptyDatabaseSnapshot) SnapshotControl(liquibase.snapshot.SnapshotControl)

Example 2 with SqlStatement

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 };
}
Also used : OracleDatabase(liquibase.database.core.OracleDatabase) SqlStatement(liquibase.statement.SqlStatement) UpdateStatement(liquibase.statement.core.UpdateStatement) UpdateExecutablePreparedStatement(liquibase.statement.UpdateExecutablePreparedStatement)

Example 3 with SqlStatement

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);
            }
        }
    }
}
Also used : Change(liquibase.change.Change) EmptyChange(liquibase.change.core.EmptyChange) RawSQLChange(liquibase.change.core.RawSQLChange) DbmsTargetedChange(liquibase.change.DbmsTargetedChange) ParsedNodeException(liquibase.parser.core.ParsedNodeException) SqlStatement(liquibase.statement.SqlStatement) Executor(liquibase.executor.Executor) DbmsTargetedChange(liquibase.change.DbmsTargetedChange)

Example 4 with SqlStatement

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 };
}
Also used : SqlStatement(liquibase.statement.SqlStatement) InformixDatabase(liquibase.database.core.InformixDatabase) Column(liquibase.structure.core.Column) InsertExecutablePreparedStatement(liquibase.statement.InsertExecutablePreparedStatement) InvalidExampleException(liquibase.snapshot.InvalidExampleException) DatabaseException(liquibase.exception.DatabaseException) InsertStatement(liquibase.statement.core.InsertStatement)

Example 5 with SqlStatement

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) {
                ;
            }
        }
    }
}
Also used : InsertOrUpdateStatement(liquibase.statement.core.InsertOrUpdateStatement) ColumnConfig(liquibase.change.ColumnConfig) Logger(liquibase.logging.Logger) InsertStatement(liquibase.statement.core.InsertStatement) SqlStatement(liquibase.statement.SqlStatement) Column(liquibase.structure.core.Column) MSSQLDatabase(liquibase.database.core.MSSQLDatabase) InsertExecutablePreparedStatement(liquibase.statement.InsertExecutablePreparedStatement) CSVReader(liquibase.util.csv.CSVReader) MySQLDatabase(liquibase.database.core.MySQLDatabase) IOException(java.io.IOException) AbstractJdbcDatabase(liquibase.database.AbstractJdbcDatabase) PostgresDatabase(liquibase.database.core.PostgresDatabase) InsertSetStatement(liquibase.statement.core.InsertSetStatement) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException)

Aggregations

SqlStatement (liquibase.statement.SqlStatement)49 ArrayList (java.util.ArrayList)17 Test (org.junit.Test)9 Column (liquibase.structure.core.Column)8 DB2Database (liquibase.database.core.DB2Database)7 UnexpectedLiquibaseException (liquibase.exception.UnexpectedLiquibaseException)7 ReorganizeTableStatement (liquibase.statement.core.ReorganizeTableStatement)7 SQLiteDatabase (liquibase.database.core.SQLiteDatabase)6 DatabaseException (liquibase.exception.DatabaseException)6 Database (liquibase.database.Database)5 MSSQLDatabase (liquibase.database.core.MSSQLDatabase)5 Sql (liquibase.sql.Sql)5 RawSqlStatement (liquibase.statement.core.RawSqlStatement)5 UpdateStatement (liquibase.statement.core.UpdateStatement)5 Index (liquibase.structure.core.Index)5 Change (liquibase.change.Change)4 ColumnConfig (liquibase.change.ColumnConfig)4 AddColumnChange (liquibase.change.core.AddColumnChange)3 PostgresDatabase (liquibase.database.core.PostgresDatabase)3 AlterTableVisitor (liquibase.database.core.SQLiteDatabase.AlterTableVisitor)3