public void printNonRenames(DatabaseSnapshot reference, DatabaseSnapshot target, StringBuilder sb)
      throws Exception {
    CompareControl compareControl =
        new CompareControl(reference.getSnapshotControl().getTypesToInclude());
    DiffResult diffResult =
        DiffGeneratorFactory.getInstance().compare(reference, target, compareControl);

    DiffToChangeLog diffToChangeLog =
        new DiffToChangeLog(diffResult, new DiffOutputControl(false, false, false));

    SqlGeneratorFactory generatorFactory = SqlGeneratorFactory.getInstance();
    for (ChangeSet changeSet : diffToChangeLog.generateChangeSets()) {
      for (Change change : changeSet.getChanges()) {
        for (SqlStatement sqlStatement :
            change.generateStatements(LiquibaseModelFactory.DATABASE)) {
          for (Sql sql :
              generatorFactory.generateSql(sqlStatement, LiquibaseModelFactory.DATABASE)) {

            final String sqlString = sql.toSql();
            if (sqlString.endsWith("DROP INDEX")) {
              sb.append(StringUtils.substringBefore(sqlString, " DROP INDEX")).append(";\n");
            } else {
              sb.append(sqlString).append(";\n");
            }
          }
        }
      }
    }
  }
Exemple #2
0
  protected Change toChange(ParsedNode value, ResourceAccessor resourceAccessor)
      throws ParsedNodeException {
    Change change = ChangeFactory.getInstance().create(value.getName());
    if (change == null) {
      return null;
    } else {
      change.load(value, resourceAccessor);

      return change;
    }
  }
Exemple #3
0
  public boolean supportsRollback(Database database) {
    if (rollback != null && rollback.getChanges() != null && rollback.getChanges().size() > 0) {
      return true;
    }

    for (Change change : getChanges()) {
      if (!change.supportsRollback(database)) {
        return false;
      }
    }
    return true;
  }
Exemple #4
0
  public CheckSum generateCheckSum() {
    StringBuffer stringToMD5 = new StringBuffer();
    for (Change change : getChanges()) {
      stringToMD5.append(change.generateCheckSum()).append(":");
    }

    for (SqlVisitor visitor : this.getSqlVisitors()) {
      stringToMD5.append(visitor.generateCheckSum()).append(";");
    }

    return CheckSum.compute(stringToMD5.toString());
  }
Exemple #5
0
  public String getDescription() {
    List<Change> changes = getChanges();
    if (changes.size() == 0) {
      return "empty";
    }

    List<String> messages = new ArrayList<String>();
    for (Change change : changes) {
      messages.add(change.getDescription());
    }

    return StringUtils.limitSize(StringUtils.join(messages, "; "), 255);
  }
  @Test
  public void lessThanMinimumFails() throws Exception {
    ChangeFactory changeFactory = ChangeFactory.getInstance();
    for (String changeName : changeFactory.getDefinedChanges()) {
      for (Database database : DatabaseFactory.getInstance().getImplementedDatabases()) {
        if (database.getShortName() == null) {
          continue;
        }

        Change change = changeFactory.create(changeName);
        if (!change.supports(database)) {
          continue;
        }
        if (change.generateStatementsVolatile(database)) {
          continue;
        }
        ChangeMetaData changeMetaData = ChangeFactory.getInstance().getChangeMetaData(change);

        change.setResourceAccessor(new JUnitResourceAccessor());

        ArrayList<String> requiredParams =
            new ArrayList<String>(changeMetaData.getRequiredParameters(database).keySet());
        for (String paramName : requiredParams) {
          ChangeParameterMetaData param = changeMetaData.getParameters().get(paramName);
          Object paramValue = param.getExampleValue();
          param.setValue(change, paramValue);
        }

        for (int i = 0; i < requiredParams.size(); i++) {
          String paramToRemove = requiredParams.get(i);
          ChangeParameterMetaData paramToRemoveMetadata =
              changeMetaData.getParameters().get(paramToRemove);
          Object currentValue = paramToRemoveMetadata.getCurrentValue(change);
          paramToRemoveMetadata.setValue(change, null);

          assertTrue(
              "No errors even with "
                  + changeMetaData.getName()
                  + " with a null "
                  + paramToRemove
                  + " on "
                  + database.getShortName(),
              change.validate(database).hasErrors());
          paramToRemoveMetadata.setValue(change, currentValue);
        }
      }
    }
  }
Exemple #7
0
 public void addRollbackChange(Change change) {
   if (change == null) {
     return;
   }
   rollback.getChanges().add(change);
   change.setChangeSet(this);
 }
Exemple #8
0
 public void addChange(Change change) {
   if (change == null) {
     return;
   }
   changes.add(change);
   change.setChangeSet(this);
 }
  @Override
  public void executeStatements(
      Change change, DatabaseChangeLog changeLog, List<SqlVisitor> sqlVisitors)
      throws LiquibaseException, UnsupportedChangeException {
    SqlStatement[] statements = change.generateStatements(this);

    execute(statements, sqlVisitors);
  }
  @Override
  public void executeStatements(
      final Change change, final DatabaseChangeLog changeLog, final List<SqlVisitor> sqlVisitors)
      throws LiquibaseException {
    SqlStatement[] statements = change.generateStatements(this);

    execute(statements, sqlVisitors);
  }
 @Override
 public void saveRollbackStatement(Change change, List<SqlVisitor> sqlVisitors, Writer writer)
     throws IOException, UnsupportedChangeException, RollbackImpossibleException,
         StatementNotSupportedOnDatabaseException, LiquibaseException {
   SqlStatement[] statements = change.generateRollbackStatements(this);
   for (SqlStatement statement : statements) {
     for (Sql sql : SqlGeneratorFactory.getInstance().generateSql(statement, this)) {
       writer.append(sql.toSql()).append(sql.getEndDelimiter()).append("\n\n");
     }
   }
 }
  @Test
  public void parseAndGenerate() throws Exception {
    Database database = liquiBase.getDatabase();
    ResourceAccessor resourceAccessor = new ClassLoaderResourceAccessor();

    ChangeLogParameters changeLogParameters = new ChangeLogParameters();

    DatabaseChangeLog changeLog =
        ChangeLogParserFactory.getInstance()
            .getParser(changeLogFile, resourceAccessor)
            .parse(changeLogFile, changeLogParameters, resourceAccessor);

    database.checkDatabaseChangeLogTable(false, changeLog, null);
    changeLog.validate(database);

    List<ChangeSet> changeSets = changeLog.getChangeSets();

    List<String> expectedQuery = new ArrayList<String>();

    expectedQuery.add(
        "MERGE INTO LIQUIBASE.myTable2 m "
            + "USING LIQUIBASE.myTable d "
            + "ON (m.pid=d.pid) "
            + "WHEN MATCHED THEN UPDATE SET m.sales=m.sales+d.sales,m.status=d.status "
            + "DELETE WHERE (m.status='OBS') "
            + "WHEN NOT MATCHED THEN INSERT VALUES(d.pid,d.sales,'OLD')");

    int i = 0;

    for (ChangeSet changeSet : changeSets) {
      for (Change change : changeSet.getChanges()) {
        Sql[] sql =
            SqlGeneratorFactory.getInstance()
                .generateSql(change.generateStatements(database)[0], database);
        if (i == 3) {
          assertEquals(expectedQuery.get(0), sql[0].toSql());
        }
      }
      i++;
    }
  }
 @Override
 public void executeRollbackStatements(Change change, List<SqlVisitor> sqlVisitors)
     throws LiquibaseException, UnsupportedChangeException, RollbackImpossibleException {
   SqlStatement[] statements = change.generateRollbackStatements(this);
   List<SqlVisitor> rollbackVisitors = new ArrayList<SqlVisitor>();
   if (sqlVisitors != null) {
     for (SqlVisitor visitor : sqlVisitors) {
       if (visitor.isApplyToRollback()) {
         rollbackVisitors.add(visitor);
       }
     }
   }
   execute(statements, rollbackVisitors);
 }
 @Override
 public void saveStatements(
     final Change change, final List<SqlVisitor> sqlVisitors, final Writer writer)
     throws IOException, StatementNotSupportedOnDatabaseException, LiquibaseException {
   SqlStatement[] statements = change.generateStatements(this);
   for (SqlStatement statement : statements) {
     for (Sql sql : SqlGeneratorFactory.getInstance().generateSql(statement, this)) {
       writer
           .append(sql.toSql())
           .append(sql.getEndDelimiter())
           .append(StreamUtil.getLineSeparator())
           .append(StreamUtil.getLineSeparator());
     }
   }
 }
Exemple #15
0
  /**
   * This method will actually execute each of the changes in the list against the specified
   * database.
   *
   * @return should change set be marked as ran
   */
  public ExecType execute(
      DatabaseChangeLog databaseChangeLog, ChangeExecListener listener, Database database)
      throws MigrationFailedException {
    if (validationFailed) {
      return ExecType.MARK_RAN;
    }

    long startTime = new Date().getTime();

    ExecType execType = null;

    boolean skipChange = false;

    Executor executor = ExecutorService.getInstance().getExecutor(database);
    try {
      // set object quoting strategy
      database.setObjectQuotingStrategy(objectQuotingStrategy);

      // set auto-commit based on runInTransaction if database supports DDL in transactions
      if (database.supportsDDLInTransaction()) {
        database.setAutoCommit(!runInTransaction);
      }

      executor.comment("Changeset " + toString(false));
      if (StringUtils.trimToNull(getComments()) != null) {
        String comments = getComments();
        String[] lines = comments.split("\\n");
        for (int i = 0; i < lines.length; i++) {
          if (i > 0) {
            lines[i] = database.getLineComment() + " " + lines[i];
          }
        }
        executor.comment(StringUtils.join(Arrays.asList(lines), "\n"));
      }

      try {
        if (preconditions != null) {
          preconditions.check(database, databaseChangeLog, this);
        }
      } catch (PreconditionFailedException e) {
        if (listener != null) {
          listener.preconditionFailed(e, preconditions.getOnFail());
        }
        StringBuffer message = new StringBuffer();
        message.append(StreamUtil.getLineSeparator());
        for (FailedPrecondition invalid : e.getFailedPreconditions()) {
          message.append("          ").append(invalid.toString());
          message.append(StreamUtil.getLineSeparator());
        }

        if (preconditions.getOnFail().equals(PreconditionContainer.FailOption.HALT)) {
          throw new MigrationFailedException(this, message.toString(), e);
        } else if (preconditions.getOnFail().equals(PreconditionContainer.FailOption.CONTINUE)) {
          skipChange = true;
          execType = ExecType.SKIPPED;

          LogFactory.getLogger()
              .info(
                  "Continuing past: "
                      + toString()
                      + " despite precondition failure due to onFail='CONTINUE': "
                      + message);
        } else if (preconditions.getOnFail().equals(PreconditionContainer.FailOption.MARK_RAN)) {
          execType = ExecType.MARK_RAN;
          skipChange = true;

          log.info(
              "Marking ChangeSet: "
                  + toString()
                  + " ran despite precondition failure due to onFail='MARK_RAN': "
                  + message);
        } else if (preconditions.getOnFail().equals(PreconditionContainer.FailOption.WARN)) {
          execType = null; // already warned
        } else {
          throw new UnexpectedLiquibaseException(
              "Unexpected precondition onFail attribute: " + preconditions.getOnFail(), e);
        }
      } catch (PreconditionErrorException e) {
        if (listener != null) {
          listener.preconditionErrored(e, preconditions.getOnError());
        }

        StringBuffer message = new StringBuffer();
        message.append(StreamUtil.getLineSeparator());
        for (ErrorPrecondition invalid : e.getErrorPreconditions()) {
          message.append("          ").append(invalid.toString());
          message.append(StreamUtil.getLineSeparator());
        }

        if (preconditions.getOnError().equals(PreconditionContainer.ErrorOption.HALT)) {
          throw new MigrationFailedException(this, message.toString(), e);
        } else if (preconditions.getOnError().equals(PreconditionContainer.ErrorOption.CONTINUE)) {
          skipChange = true;
          execType = ExecType.SKIPPED;

        } else if (preconditions.getOnError().equals(PreconditionContainer.ErrorOption.MARK_RAN)) {
          execType = ExecType.MARK_RAN;
          skipChange = true;

          log.info(
              "Marking ChangeSet: " + toString() + " ran despite precondition error: " + message);
        } else if (preconditions.getOnError().equals(PreconditionContainer.ErrorOption.WARN)) {
          execType = null; // already logged
        } else {
          throw new UnexpectedLiquibaseException(
              "Unexpected precondition onError attribute: " + preconditions.getOnError(), e);
        }

        database.rollback();
      } finally {
        database.rollback();
      }

      if (!skipChange) {
        for (Change change : changes) {
          try {
            change.finishInitialization();
          } catch (SetupException se) {
            throw new MigrationFailedException(this, se);
          }
        }

        log.debug("Reading ChangeSet: " + toString());
        for (Change change : getChanges()) {
          if ((!(change instanceof DbmsTargetedChange))
              || DatabaseList.definitionMatches(
                  ((DbmsTargetedChange) change).getDbms(), database, true)) {
            if (listener != null) {
              listener.willRun(change, this, changeLog, database);
            }
            if (change.generateStatementsVolatile(database)) {
              executor.comment(
                  "WARNING The following SQL is possibly incorrect, invalid, and/or may change on each run:");
            }

            database.executeStatements(change, databaseChangeLog, sqlVisitors);
            log.info(change.getConfirmationMessage());
            if (listener != null) {
              listener.ran(change, this, changeLog, database);
            }
          } else {
            log.debug(
                "Change "
                    + change.getSerializedObjectName()
                    + " not included for database "
                    + database.getShortName());
          }
        }

        if (runInTransaction) {
          database.commit();
        }
        log.info(
            "ChangeSet "
                + toString(false)
                + " ran successfully in "
                + (new Date().getTime() - startTime + "ms"));
        if (execType == null) {
          execType = ExecType.EXECUTED;
        }
      } else {
        log.debug("Skipping ChangeSet: " + toString());
      }

    } catch (Exception e) {
      try {
        database.rollback();
      } catch (Exception e1) {
        throw new MigrationFailedException(this, e);
      }
      if (getFailOnError() != null && !getFailOnError()) {
        log.info(
            "Change set "
                + toString(false)
                + " failed, but failOnError was false.  Error: "
                + e.getMessage());
        log.debug("Failure Stacktrace", e);
        execType = ExecType.FAILED;
      } else {
        // just log the message, dont log the stacktrace by appending exception. Its logged anyway
        // to stdout
        log.severe("Change Set " + toString(false) + " failed.  Error: " + e.getMessage());
        if (e instanceof MigrationFailedException) {
          throw ((MigrationFailedException) e);
        } else {
          throw new MigrationFailedException(this, e);
        }
      }
    } finally {
      // restore auto-commit to false if this ChangeSet was not run in a transaction,
      // but only if the database supports DDL in transactions
      if (!runInTransaction && database.supportsDDLInTransaction()) {
        try {
          database.setAutoCommit(false);
        } catch (DatabaseException e) {
          throw new MigrationFailedException(this, "Could not resetInternalState autocommit", e);
        }
      }
    }
    return execType;
  }
  /** 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).addIncludedSchema(schemaToDrop))
              .generateChangeSets();
      LogFactory.getLogger()
          .debug(
              String.format(
                  "ChangeSet to Remove Database Objects generated in %d ms.",
                  System.currentTimeMillis() - changeSetStarted));

      boolean previousAutoCommit = this.getAutoCommitMode();
      this.commit(); // clear out currently executed statements
      this.setAutoCommit(false); // some DDL doesn't work in autocommit mode
      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();
    }
  }
 @Override
 public void executeRollbackStatements(final Change change, final List<SqlVisitor> sqlVisitors)
     throws LiquibaseException, RollbackImpossibleException {
   final SqlStatement[] statements = change.generateRollbackStatements(this);
   executeRollbackStatements(statements, sqlVisitors);
 }
Exemple #18
0
  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;
          }
          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 {
      // restore auto-commit to false if this ChangeSet was not run in a transaction,
      // 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);
        }
      }
    }
  }
  @Test
  public void minimumRequiredIsValidSql() throws Exception {
    ChangeFactory changeFactory = ChangeFactory.getInstance();
    for (String changeName : changeFactory.getDefinedChanges()) {
      if (changeName.equals("addDefaultValue")) {
        continue; // need to better handle strange "one of defaultValue* is required" logic
      }
      if (changeName.equals("changeWithNestedTags") || changeName.equals("sampleChange")) {
        continue; // not a real change
      }
      for (Database database : DatabaseFactory.getInstance().getImplementedDatabases()) {
        if (database.getShortName() == null) {
          continue;
        }

        TestState state =
            new TestState(
                name.getMethodName(), changeName, database.getShortName(), TestState.Type.SQL);
        state.addComment("Database: " + database.getShortName());

        Change change = changeFactory.create(changeName);
        if (!change.supports(database)) {
          continue;
        }
        if (change.generateStatementsVolatile(database)) {
          continue;
        }
        ChangeMetaData changeMetaData = ChangeFactory.getInstance().getChangeMetaData(change);

        change.setResourceAccessor(new JUnitResourceAccessor());

        for (String paramName :
            new TreeSet<String>(changeMetaData.getRequiredParameters(database).keySet())) {
          ChangeParameterMetaData param = changeMetaData.getParameters().get(paramName);
          Object paramValue = param.getExampleValue();
          String serializedValue;
          serializedValue = formatParameter(paramValue);
          state.addComment("Change Parameter: " + param.getParameterName() + "=" + serializedValue);
          param.setValue(change, paramValue);
        }

        ValidationErrors errors = change.validate(database);
        assertFalse(
            "Validation errors for "
                + changeMetaData.getName()
                + " on "
                + database.getShortName()
                + ": "
                + errors.toString(),
            errors.hasErrors());

        SqlStatement[] sqlStatements = change.generateStatements(database);
        for (SqlStatement statement : sqlStatements) {
          Sql[] sql = SqlGeneratorFactory.getInstance().generateSql(statement, database);
          if (sql == null) {
            System.out.println("Null sql for " + statement + " on " + database.getShortName());
          } else {
            for (Sql line : sql) {
              String sqlLine = line.toSql();
              assertFalse(
                  "Change "
                      + changeMetaData.getName()
                      + " contains 'null' for "
                      + database.getShortName()
                      + ": "
                      + sqlLine,
                  sqlLine.contains(" null "));

              state.addValue(sqlLine + ";");
            }
          }
        }
        state.test();
      }
    }
  }
  @Test
  public void extraParamsIsValidSql() throws Exception {
    ChangeFactory changeFactory = ChangeFactory.getInstance();
    for (String changeName : changeFactory.getDefinedChanges()) {
      if (changeName.equals("addDefaultValue")) {
        continue; // need to better handle strange "one of defaultValue* is required" logic
      }

      for (Database database : DatabaseFactory.getInstance().getImplementedDatabases()) {
        if (database.getShortName() == null) {
          continue;
        }

        TestState state =
            new TestState(
                name.getMethodName(), changeName, database.getShortName(), TestState.Type.SQL);
        state.addComment("Database: " + database.getShortName());

        Change baseChange = changeFactory.create(changeName);
        if (!baseChange.supports(database)) {
          continue;
        }
        if (baseChange.generateStatementsVolatile(database)) {
          continue;
        }
        ChangeMetaData changeMetaData = ChangeFactory.getInstance().getChangeMetaData(baseChange);
        ArrayList<String> optionalParameters =
            new ArrayList<String>(changeMetaData.getOptionalParameters(database).keySet());
        Collections.sort(optionalParameters);

        List<List<String>> paramLists = powerSet(optionalParameters);
        Collections.sort(
            paramLists,
            new Comparator<List<String>>() {
              @Override
              public int compare(List<String> o1, List<String> o2) {
                int comp = Integer.valueOf(o1.size()).compareTo(o2.size());
                if (comp == 0) {
                  comp = StringUtils.join(o1, ",").compareTo(StringUtils.join(o2, ","));
                }
                return comp;
              }
            });
        for (List<String> permutation : paramLists) {
          Change change = changeFactory.create(changeName);
          change.setResourceAccessor(new JUnitResourceAccessor());
          //
          for (String paramName :
              new TreeSet<String>(changeMetaData.getRequiredParameters(database).keySet())) {
            ChangeParameterMetaData param = changeMetaData.getParameters().get(paramName);
            Object paramValue = param.getExampleValue();
            String serializedValue;
            serializedValue = formatParameter(paramValue);
            state.addComment(
                "Required Change Parameter: " + param.getParameterName() + "=" + serializedValue);
            param.setValue(change, paramValue);
          }

          for (String paramName : permutation) {
            ChangeParameterMetaData param = changeMetaData.getParameters().get(paramName);
            if (!param.supports(database)) {
              continue;
            }
            Object paramValue = param.getExampleValue();
            String serializedValue;
            serializedValue = formatParameter(paramValue);
            state.addComment(
                "Optional Change Parameter: " + param.getParameterName() + "=" + serializedValue);
            param.setValue(change, paramValue);
          }

          ValidationErrors errors = change.validate(database);
          assertFalse(
              "Validation errors for "
                  + changeMetaData.getName()
                  + " on "
                  + database.getShortName()
                  + ": "
                  + errors.toString(),
              errors.hasErrors());
          //
          //                    SqlStatement[] sqlStatements = change.generateStatements(database);
          //                    for (SqlStatement statement : sqlStatements) {
          //                        Sql[] sql =
          // SqlGeneratorFactory.getInstance().generateSql(statement, database);
          //                        if (sql == null) {
          //                            System.out.println("Null sql for "+statement+" on
          // "+database.getShortName());
          //                        } else {
          //                            for (Sql line : sql) {
          //                                state.addValue(line.toSql()+";");
          //                            }
          //                        }
          //                    }
          //                    state.test();
        }
      }
    }
  }
  /**
   * Drops all objects owned by the connected user.
   *
   * @param schema
   */
  @Override
  public void dropDatabaseObjects(String schema) throws DatabaseException {
    try {
      DatabaseSnapshotGeneratorFactory factory = DatabaseSnapshotGeneratorFactory.getInstance();
      SnapshotContext context = new SnapshotContext();
      context.setDatabase(this);
      context.setSchema(schema);
      context.setListeners(new HashSet<DiffStatusListener>());
      DatabaseSnapshot snapshot = factory.createSnapshot(context);

      List<Change> dropChanges = new ArrayList<Change>();

      for (View view : snapshot.getViews()) {
        DropViewChange dropChange = new DropViewChange();
        dropChange.setViewName(view.getName());
        dropChange.setSchemaName(schema);

        dropChanges.add(dropChange);
      }

      if (!supportsForeignKeyDisable()) {
        for (ForeignKey fk : snapshot.getForeignKeys()) {
          DropForeignKeyConstraintChange dropFK = new DropForeignKeyConstraintChange();
          dropFK.setBaseTableSchemaName(schema);
          dropFK.setBaseTableName(fk.getForeignKeyTable().getName());
          dropFK.setConstraintName(fk.getName());

          dropChanges.add(dropFK);
        }
      }

      // for (Index index : snapshotGenerator.getIndexes()) {
      // DropIndexChange dropChange = new DropIndexChange();
      // dropChange.setIndexName(index.getName());
      // dropChange.setSchemaName(schema);
      // dropChange.setTableName(index.getTableName());
      //
      // dropChanges.add(dropChange);
      // }

      for (Table table : snapshot.getTables()) {
        DropTableChange dropChange = new DropTableChange();
        dropChange.setSchemaName(schema);
        dropChange.setTableName(table.getName());
        if (supportsDropTableCascadeConstraints()) {
          dropChange.setCascadeConstraints(true);
        }

        dropChanges.add(dropChange);
      }

      if (this.supportsSequences()) {
        for (Sequence seq : snapshot.getSequences()) {
          DropSequenceChange dropChange = new DropSequenceChange();
          dropChange.setSequenceName(seq.getName());
          dropChange.setSchemaName(schema);

          dropChanges.add(dropChange);
        }
      }

      if (snapshot.hasDatabaseChangeLogTable()) {
        dropChanges.add(new AnonymousChange(new ClearDatabaseChangeLogTableStatement(schema)));
      }

      final boolean reEnableFK = supportsForeignKeyDisable() && disableForeignKeyChecks();
      try {
        for (Change change : dropChanges) {
          for (SqlStatement statement : change.generateStatements(this)) {
            ExecutorService.getInstance().getExecutor(this).execute(statement);
          }
        }
      } finally {
        if (reEnableFK) {
          enableForeignKeyChecks();
        }
      }

    } finally {
      this.commit();
    }
  }