SqlGenerator

Purpose

liquibase.sqlgenerator.SqlGenerator implementations convert database-independent SqlStatement classes into database-specific SQL.  Create custom SqlGenerator implementations if you want to override, modify, or add to the SQL generated by a SqlStatement.

Examples

  • The InsertData SqlStatement only generates "insert into ..." statements, it does not wrap them with the "set identity insert" statements you need for inserting values into an identity field in MSSQL.  You can create a custom SqlGenerator to add the additional SQL.

How to Create

To create a new SqlGenerator implementation, implement the liquibase.sqlgenerator.SqlGenerator interface.  There are four methods exposed:

public boolean supports(SqlStatement statement, Database database)

Return "true" if the generator suppots the passed SqlStatement/Database combination.  Note: your SqlGenerator implementation can pass a SqlStatement as a generic to the class.  If you do, the supports method will automatically include a check for the correct SqlStatement type.

public int getPriority();

For each SqlStatement, a chain of SqlGenerators can be supplied from all classes that return true from supports().  The SqlGenerators in the chain will be ordered via getPriority from higest (executed first) to lowest.  Core Liquibase SqlGenerators use priorities of 1 and 5.

public ValidationErrors validate(StatementType statement, Database database, SqlGeneratorChain sqlGeneratorChain);

Before executing a SqlGeneratorChain, the validate method will be called on the first (highest priority) SqlGenerator.  If your SqlGenerator is completely replacing lower priority generators, you do not need to call sqlGeneratorChain.validate().  If you are appending to, or wish to allow lower priority generators to still run their validation checks, call sqlGeneratorChain.validate() and include the returned ValidationErrors in your ValidationErrors object.  If any errors are returned, the SqlStatement will not be executed by Liquibase.

public Sql[] generateSql(StatementType statement, Database database, SqlGeneratorChain sqlGeneratorChain);

Returns the SQL you wish to have executed.  If you wish, you can call sqlGeneratorChain.generateSql() and modify or include the returned Sql as you see fit.

Registering Custom SqlGenerators

There are two ways to register a custom SqlGenerator:

  1. Create the class in the package "liquibase.sqlgenerator.ext".  Liquibase automatically registers SqlGenerators it finds in that package
  2. Call liquibase.sqlgenerator.SqlGeneratorFactory.getInstance().register(yourSqlGenerator)

Threading/Singleton notes

SqlGenerator implementations should be created thread safe.  Once an instance of SqlGenerator is registered, SqlGeneratorFactory will continue to use the same instance.