@Override
  public void init() throws DatabaseException {

    boolean createdTable = false;
    Executor executor = ExecutorService.getInstance().getExecutor(database);
    if (!hasDatabaseChangeLogLockTable()) {

      executor.comment("Create Database Lock Table");
      executor.execute(new CreateDatabaseChangeLogLockTableStatement());
      database.commit();
      LogFactory.getLogger()
          .debug(
              "Created database lock table with name: "
                  + database.escapeTableName(
                      database.getLiquibaseCatalogName(),
                      database.getLiquibaseSchemaName(),
                      database.getDatabaseChangeLogLockTableName()));
      this.hasDatabaseChangeLogLockTable = true;
      createdTable = true;
    }

    if (!isDatabaseChangeLogLockTableInitialized(createdTable)) {
      executor.comment("Initialize Database Lock Table");
      executor.execute(new InitializeDatabaseChangeLogLockTableStatement());
      database.commit();
    }

    if (database instanceof DerbyDatabase
        && ((DerbyDatabase) database)
            .supportsBooleanDataType()) { // check if the changelog table is of an old smallint vs.
                                          // boolean format
      String lockTable =
          database.escapeTableName(
              database.getLiquibaseCatalogName(),
              database.getLiquibaseSchemaName(),
              database.getDatabaseChangeLogLockTableName());
      Object obj =
          executor.queryForObject(
              new RawSqlStatement(
                  "select min(locked) as test from " + lockTable + " fetch first row only"),
              Object.class);
      if (!(obj instanceof Boolean)) { // wrong type, need to recreate table
        executor.execute(
            new DropTableStatement(
                database.getLiquibaseCatalogName(),
                database.getLiquibaseSchemaName(),
                database.getDatabaseChangeLogLockTableName(),
                false));
        executor.execute(new CreateDatabaseChangeLogLockTableStatement());
        executor.execute(new InitializeDatabaseChangeLogLockTableStatement());
      }
    }
  }
  public boolean isDatabaseChangeLogLockTableInitialized(final boolean tableJustCreated)
      throws DatabaseException {
    if (!isDatabaseChangeLogLockTableInitialized) {
      Executor executor = ExecutorService.getInstance().getExecutor(database);

      try {
        isDatabaseChangeLogLockTableInitialized =
            executor.queryForInt(
                    new RawSqlStatement(
                        "select count(*) from "
                            + database.escapeTableName(
                                database.getLiquibaseCatalogName(),
                                database.getLiquibaseSchemaName(),
                                database.getDatabaseChangeLogLockTableName())))
                > 0;
      } catch (LiquibaseException e) {
        if (executor.updatesDatabase()) {
          throw new UnexpectedLiquibaseException(e);
        } else {
          // probably didn't actually create the table yet.
          isDatabaseChangeLogLockTableInitialized = !tableJustCreated;
        }
      }
    }
    return isDatabaseChangeLogLockTableInitialized;
  }
  public void releaseLock() throws DatabaseException, LockException {
    Executor executor = ExecutorService.getInstance().getExecutor(database);
    try {
      if (database.hasDatabaseChangeLogLockTable()) {
        executor.comment("Release Database Lock");
        database.rollback();
        int updatedRows = executor.update(new UnlockDatabaseChangeLogStatement());
        if (updatedRows != 1) {
          throw new LockException(
              "Did not update change log lock correctly.\n\n"
                  + updatedRows
                  + " rows were updated instead of the expected 1 row using executor "
                  + executor.getClass().getName()
                  + " there are "
                  + executor.queryForInt(
                      new RawSqlStatement(
                          "select count(*) from " + database.getDatabaseChangeLogLockTableName()))
                  + " rows in the table");
        }
        database.commit();
        hasChangeLogLock = false;

        instances.remove(this.database);

        database.setCanCacheLiquibaseTableInfo(false);

        LogFactory.getLogger().info("Successfully released change log lock");
      }
    } finally {
      database.rollback();
    }
  }
 @Override
 public void destroy() throws DatabaseException {
   try {
     if (SnapshotGeneratorFactory.getInstance()
         .has(
             new Table()
                 .setName(database.getDatabaseChangeLogLockTableName())
                 .setSchema(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName()),
             database)) {
       ExecutorService.getInstance()
           .getExecutor(database)
           .execute(
               new DropTableStatement(
                   database.getLiquibaseCatalogName(),
                   database.getLiquibaseSchemaName(),
                   database.getDatabaseChangeLogLockTableName(),
                   false));
     }
   } catch (InvalidExampleException e) {
     throw new UnexpectedLiquibaseException(e);
   }
 }