Add a Native Executor
Prerequisites
Implementing Liquibase extensions requires an understanding of Java. You will be creating classes, overriding methods, and working with inheritance hierarchies.
Project Setup
If you have not already created a repository to hold your code, see Your First Extension in the Getting Started guide.
Overview
When adding support for a new runWith
option or replacing the default, the interface you are going to implement is liquibase.executor.Executor.
Tip
There is a liquibase.executor.AbstractExecutor base class you can use which limits the number of methods you must implement.
If you are wrapping custom logic around a JDBC connection, you can subclass liquibase.executor.jvm.JdbcExecutor
to further limit what you need to implement.
API Documentation
A complete description of the API, including what methods must be implemented and how is available on the liquibase.executor.Executor API page.
Example Code
package com.example.executor;
import liquibase.Scope;
import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.executor.AbstractExecutor;
import liquibase.sql.Sql;
import liquibase.sql.visitor.SqlVisitor;
import liquibase.sqlgenerator.SqlGeneratorFactory;
import liquibase.statement.SqlStatement;
import java.util.List;
import java.util.Map;
public class ExampleExecutor extends AbstractExecutor {
@Override
public boolean supports(Database database) {
return true;
}
@Override
public String getName() {
return "example";
}
@Override
public int getPriority() {
return PRIORITY_SPECIALIZED;
}
@Override
public boolean updatesDatabase() {
return true;
}
@Override
public void comment(String message) throws DatabaseException {
Scope.getCurrentScope().getLog(getClass()).fine(message);
}
@Override
public void execute(SqlStatement sql) throws DatabaseException {
this.execute(sql, null);
}
@Override
public void execute(SqlStatement sqlStatement, List<SqlVisitor> sqlVisitors) throws DatabaseException {
Scope.getCurrentScope().getLog(getClass()).info("Executing with the '" + getName() + "' executor");
Sql[] sqls = SqlGeneratorFactory.getInstance().generateSql(sqlStatement, database);
try {
for (Sql sql : sqls) {
String actualSqlString = sql.toSql();
for (SqlVisitor visitor : sqlVisitors) {
visitor.modifySql(actualSqlString, database);
}
Scope.getCurrentScope().getLog(getClass()).info("Generated SQL for change is " + actualSqlString);
//TODO: SEND `sql` TO YOUR DATABASE
}
}
catch (Exception e) {
throw new DatabaseException(e);
}
}
/// remaining methods are unused when this is only used in runWith changesets
@Override
public int update(SqlStatement sql) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public int update(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public <T> T queryForObject(SqlStatement sql, Class<T> requiredType) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public <T> T queryForObject(SqlStatement sql, Class<T> requiredType, List<SqlVisitor> sqlVisitors) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public long queryForLong(SqlStatement sql) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public long queryForLong(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public int queryForInt(SqlStatement sql) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public int queryForInt(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public List queryForList(SqlStatement sql, Class elementType) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public List queryForList(SqlStatement sql, Class elementType, List<SqlVisitor> sqlVisitors) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public List<Map<String, ?>> queryForList(SqlStatement sql) throws DatabaseException {
throw new UnsupportedOperationException();
}
@Override
public List<Map<String, ?>> queryForList(SqlStatement sql, List<SqlVisitor> sqlVisitors) throws DatabaseException {
throw new UnsupportedOperationException();
}
}