Skip to content



To run statements against your target database, Liquibase creates liquibase.statement.SqlStatement objects describing the operation to perform.

These could be more declarative requests, like liquibase.statement.core.CreateTableStatement or one that simply specifies exactly what should be run like liquibase.statement.core.RawSqlStatement.

However, the SqlStatement only describes the operation to perform -- it is up to the liquibase.executor.Executor to know how to run that statement against the database.

    participant Calling Code
    participant SqlStatement
    participant Executor
    participant Database
    Calling Code->>SqlStatement: Creates
    Calling Code->>Executor: Sends SqlStatement
    Executor->>Database: Performs operation
The default Executor is liquibase.executor.jvm.JdbcExecutor which converts the SqlStatements to SQL and sends them to the database through the JDBC driver.

However, other implementations perform other database interactions instead. For example, you could send the desired SQL through an external CLI instead, or simply log the SQL without executing it.

Executor Selection

Each Executor has a "name", and the calling code always sends each SqlStatement to a particular executor name. By default, the executor name used is jdbc, but that can be overridden in code or with the runWith attribute on changeSet.

To determine which Executor to use, Liquibase will find all the implementations that use the given name and supports the given database, then chooses the one with the highest priority. This allows extensions to either define a new name OR override an existing Executor with a given name.

API Highlights


Changes are dynamically discovered, so must have a no-arg constructor and be registered in the META-INF/services/liquibase.executor.Executor file.


Returns the "name" of the executor to be used when selecting the instance to use.

Names should be lowercase with no spaces or special characters.


Used in [selecting the instance to use](#executor-selection


Used in [selecting the instance to use](#executor-selection


Allows the executor to verify whether it supports the given SqlStatement and/or its configuration.


Returns false if the executor does not actually update the database. This is used to determine if the current state of the database can be trusted in preconditions during update operations.

Execute methods

These methods are where the logic for running the SqlStatements go.

Executors that deal with SQL rely on liquibase.sqlgenerator.SqlGeneratorFactory to generate SQL from the SqlStatements.

Query and update methods

ALL database operations in Liquibase go through an executor, not just changeSets. To support all the needed database interactions, the Executor interface includes a set of methods that are only called against Executors with the name "jdbc":

  • query* methods
  • update*

Non-"jdbc" executors will throw UnsupportedOperationException from all these methods.


Comments can be sent to the executor to describe what is being run. Most executors ignore them, but ones that log what would have been executed may want to log the comments as well.

API Details

The complete javadocs for liquibase.executor.Executor is available at

Extension Guides

The following guides provide relevant examples:

Last update: April 5, 2023
Created: March 28, 2023