public void check(Database database, DatabaseChangeLog changeLog, ChangeSet changeSet)
     throws PreconditionFailedException, PreconditionErrorException {
   try {
     boolean checkPassed;
     if (getForeignKeyTableName() == null) {
       checkPassed =
           DatabaseSnapshotGeneratorFactory.getInstance()
                   .createSnapshot(database, getSchemaName(), null)
                   .getForeignKey(getForeignKeyName())
               != null;
     } else { // much faster if we can limit to correct table
       checkPassed =
           DatabaseSnapshotGeneratorFactory.getInstance()
                   .getGenerator(database)
                   .getForeignKeyByForeignKeyTable(
                       getSchemaName(), getForeignKeyTableName(), getForeignKeyName(), database)
               != null;
     }
     if (!checkPassed) {
       String message = "Foreign Key " + database.escapeStringForDatabase(getForeignKeyName());
       if (getForeignKeyTableName() != null) {
         message += " on table " + getForeignKeyTableName();
       }
       message += " does not exist";
       throw new PreconditionFailedException(message, changeLog, this);
     }
   } catch (DatabaseException e) {
     throw new PreconditionErrorException(e, changeLog, this);
   }
 }
 @Override
 public boolean hasDatabaseChangeLogLockTable() throws DatabaseException {
   if (canCacheLiquibaseTableInfo && hasDatabaseChangeLogLockTable) {
     return true;
   }
   boolean hasTable =
       DatabaseSnapshotGeneratorFactory.getInstance()
           .getGenerator(this)
           .hasDatabaseChangeLogLockTable(this);
   if (canCacheLiquibaseTableInfo) {
     hasDatabaseChangeLogLockTable = hasTable;
   }
   return hasTable;
 }
  @Override
  public void execute() throws BuildException {
    super.execute();

    Liquibase liquibase = null;
    try {
      PrintStream writer = createPrintStream();
      if (writer == null) {
        throw new BuildException("generateChangeLog requires outputFile to be set");
      }

      liquibase = createLiquibase();

      Database database = liquibase.getDatabase();
      DiffControl diffControl =
          new DiffControl(
              getDefaultCatalogName(), getDefaultSchemaName(), null, null, getDiffTypes());
      diffControl.setDataDir(getDataDir());

      DatabaseSnapshot referenceSnapshot =
          DatabaseSnapshotGeneratorFactory.getInstance()
              .createSnapshot(database, diffControl, DiffControl.DatabaseRole.REFERENCE);

      DiffResult diffResult =
          DiffGeneratorFactory.getInstance()
              .compare(referenceSnapshot, new DatabaseSnapshot(database), diffControl);
      //			diff.addStatusListener(new OutDiffStatusListener());

      if (getChangeLogFile() == null) {
        new DiffToChangeLog(diffResult).print(writer);
      } else {
        new DiffToChangeLog(diffResult).print(getChangeLogFile());
      }

      writer.flush();
      writer.close();
    } catch (Exception e) {
      throw new BuildException(e);
    } finally {
      closeDatabase(liquibase);
    }
  }
 public void check(Database database, DatabaseChangeLog changeLog, ChangeSet changeSet)
     throws PreconditionFailedException, PreconditionErrorException {
   String currentSchemaName;
   try {
     currentSchemaName =
         getSchemaName() == null
             ? (database == null ? null : database.getDefaultSchemaName())
             : getSchemaName();
     if (!DatabaseSnapshotGeneratorFactory.getInstance()
         .getGenerator(database)
         .hasView(currentSchemaName, getViewName(), database)) {
       throw new PreconditionFailedException(
           "View "
               + database.escapeTableName(currentSchemaName, getViewName())
               + " does not exist",
           changeLog,
           this);
     }
   } catch (PreconditionFailedException e) {
     throw e;
   } catch (Exception e) {
     throw new PreconditionErrorException(e, changeLog, this);
   }
 }
  /**
   * 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();
    }
  }
  /**
   * This method will check the database ChangeLog table used to keep track of the changes in the
   * file. If the table does not exist it will create one otherwise it will not do anything besides
   * outputting a log message.
   *
   * @param updateExistingNullChecksums
   * @param contexts
   */
  @Override
  public void checkDatabaseChangeLogTable(
      boolean updateExistingNullChecksums, DatabaseChangeLog databaseChangeLog, String... contexts)
      throws DatabaseException {
    Executor executor = ExecutorService.getInstance().getExecutor(this);

    Table changeLogTable =
        DatabaseSnapshotGeneratorFactory.getInstance()
            .getGenerator(this)
            .getDatabaseChangeLogTable(this);

    List<SqlStatement> statementsToExecute = new ArrayList<SqlStatement>();

    boolean changeLogCreateAttempted = false;
    if (changeLogTable != null) {
      boolean hasDescription = changeLogTable.getColumn("DESCRIPTION") != null;
      boolean hasComments = changeLogTable.getColumn("COMMENTS") != null;
      boolean hasTag = changeLogTable.getColumn("TAG") != null;
      boolean hasLiquibase = changeLogTable.getColumn("LIQUIBASE") != null;
      boolean liquibaseColumnNotRightSize =
          changeLogTable.getColumn("LIQUIBASE").getColumnSize() != 20;
      boolean hasOrderExecuted = changeLogTable.getColumn("ORDEREXECUTED") != null;
      boolean checksumNotRightSize = changeLogTable.getColumn("MD5SUM").getColumnSize() != 35;
      boolean hasExecTypeColumn = changeLogTable.getColumn("EXECTYPE") != null;

      if (!hasDescription) {
        executor.comment("Adding missing databasechangelog.description column");
        statementsToExecute.add(
            new AddColumnStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "DESCRIPTION",
                "VARCHAR(255)",
                null));
      }
      if (!hasTag) {
        executor.comment("Adding missing databasechangelog.tag column");
        statementsToExecute.add(
            new AddColumnStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "TAG",
                "VARCHAR(255)",
                null));
      }
      if (!hasComments) {
        executor.comment("Adding missing databasechangelog.comments column");
        statementsToExecute.add(
            new AddColumnStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "COMMENTS",
                "VARCHAR(255)",
                null));
      }
      if (!hasLiquibase) {
        executor.comment("Adding missing databasechangelog.liquibase column");
        statementsToExecute.add(
            new AddColumnStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "LIQUIBASE",
                "VARCHAR(255)",
                null));
      }
      if (!hasOrderExecuted) {
        executor.comment("Adding missing databasechangelog.orderexecuted column");
        statementsToExecute.add(
            new AddColumnStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "ORDEREXECUTED",
                "INT",
                null));
        statementsToExecute.add(
            new UpdateStatement(getLiquibaseSchemaName(), getDatabaseChangeLogTableName())
                .addNewColumnValue("ORDEREXECUTED", -1));
        statementsToExecute.add(
            new SetNullableStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "ORDEREXECUTED",
                "INT",
                false));
      }
      if (checksumNotRightSize) {
        executor.comment("Modifying size of databasechangelog.md5sum column");

        statementsToExecute.add(
            new ModifyDataTypeStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "MD5SUM",
                "VARCHAR(35)"));
      }
      if (liquibaseColumnNotRightSize) {
        executor.comment("Modifying size of databasechangelog.liquibase column");

        statementsToExecute.add(
            new ModifyDataTypeStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "LIQUIBASE",
                "VARCHAR(20)"));
      }
      if (!hasExecTypeColumn) {
        executor.comment("Adding missing databasechangelog.exectype column");
        statementsToExecute.add(
            new AddColumnStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "EXECTYPE",
                "VARCHAR(10)",
                null));
        statementsToExecute.add(
            new UpdateStatement(getLiquibaseSchemaName(), getDatabaseChangeLogTableName())
                .addNewColumnValue("EXECTYPE", "EXECUTED"));
        statementsToExecute.add(
            new SetNullableStatement(
                getLiquibaseSchemaName(),
                getDatabaseChangeLogTableName(),
                "EXECTYPE",
                "VARCHAR(10)",
                false));
      }

      List<Map> md5sumRS =
          ExecutorService.getInstance()
              .getExecutor(this)
              .queryForList(
                  new SelectFromDatabaseChangeLogStatement(
                      new SelectFromDatabaseChangeLogStatement.ByNotNullCheckSum(), "MD5SUM"));
      if (md5sumRS.size() > 0) {
        String md5sum = md5sumRS.get(0).get("MD5SUM").toString();
        if (!md5sum.startsWith(CheckSum.getCurrentVersion() + ":")) {
          executor.comment(
              "DatabaseChangeLog checksums are an incompatible version.  Setting them to null so they will be updated on next database update");
          statementsToExecute.add(
              new RawSqlStatement(
                  "UPDATE "
                      + escapeTableName(getLiquibaseSchemaName(), getDatabaseChangeLogTableName())
                      + " SET MD5SUM=null"));
        }
      }

    } else if (!changeLogCreateAttempted) {
      executor.comment("Create Database Change Log Table");
      SqlStatement createTableStatement = new CreateDatabaseChangeLogTableStatement();
      if (!canCreateChangeLogTable()) {
        throw new DatabaseException(
            "Cannot create "
                + escapeTableName(getDefaultSchemaName(), getDatabaseChangeLogTableName())
                + " table for your database.\n\n"
                + "Please construct it manually using the following SQL as a base and re-run Liquibase:\n\n"
                + createTableStatement);
      }
      // If there is no table in the database for recording change history create one.
      statementsToExecute.add(createTableStatement);
      LogFactory.getLogger()
          .info(
              "Creating database history table with name: "
                  + escapeTableName(getDefaultSchemaName(), getDatabaseChangeLogTableName()));
      // }
    }

    for (SqlStatement sql : statementsToExecute) {
      executor.execute(sql);
      this.commit();
    }

    if (updateExistingNullChecksums) {
      for (RanChangeSet ranChangeSet : this.getRanChangeSetList()) {
        if (ranChangeSet.getLastCheckSum() == null) {
          ChangeSet changeSet = databaseChangeLog.getChangeSet(ranChangeSet);
          if (changeSet != null
              && new ContextChangeSetFilter(contexts).accepts(changeSet)
              && new DbmsChangeSetFilter(this).accepts(changeSet)) {
            LogFactory.getLogger()
                .info(
                    "Updating null or out of date checksum on changeSet "
                        + changeSet
                        + " to correct value");
            executor.execute(new UpdateChangeSetChecksumStatement(changeSet));
          }
        }
      }
      commit();
      this.ranChangeSetList = null;
    }
  }
 public Table getTable(String schemaName, String tableName) throws DatabaseException {
   return DatabaseSnapshotGeneratorFactory.getInstance()
       .getGenerator(this)
       .getTable(schemaName, tableName, this);
 }