Defining a New Database
Overview
When adding support for a new database, the first class to create is a new liquibase.database.Database implementation. This class acts as the "dialect" definition and the facade to your database.
The Database interface defines methods for:
- Reading metadata about the database (
getDatabaseMajorVersion()
,getDefaultPort()
,getDefaultSchema()
, etc.) - Checking capabilities of the database (
isCaseSensitive()
,supportsInitiallyDeferrableColumns
,supportsSchemas()
, etc.) - Performing common logic (
escapeObjectName()
,commit()
,rollback()
, etc.)
Subclassing an existing Database Class
If your database generally attempts to be compatible with another database, your new Database implementation can extend the existing Database class.
For example, many databases strive for PostgreSQL compatibility. Those databases can extend liquibase.database.core.PostgresDatabase
and only override what is special about the new database.
Note
To correctly differentiate your database from the "standard" version, you must always implement:
- getPriority()
- getShortName()
- getDatabaseProductName()
See the liquibase.database.Database API documentation for more information.
Example Code
package com.example.database;
import liquibase.database.DatabaseConnection;
import liquibase.database.core.PostgresDatabase;
import liquibase.exception.DatabaseException;
public class ExamplePostgresDatabase extends PostgresDatabase {
@Override
public int getPriority() {
return PRIORITY_DATABASE;
}
@Override
public boolean isCorrectDatabaseImplementation(DatabaseConnection databaseConnection) throws DatabaseException {
return databaseConnection.getDatabaseProductName().equals("ExampleDB");
}
@Override
public String getShortName() {
return "example";
}
@Override
protected String getDefaultDatabaseProductName() {
return "Example Database";
}
}
Extending AbstractJdbcDatabase
If your database is more unique, you will likely want to extend from liquibase.database.AbstractJdbcDatabase
rather than PostgresDatabase
or one of the other implementations which derive from it.
How many methods you need to implement or override will depend on how much your database varies from the included superclass logic.
Example Code
package com.example.database;
import liquibase.database.AbstractJdbcDatabase;
import liquibase.database.DatabaseConnection;
import liquibase.exception.DatabaseException;
public class ExampleDatabase extends AbstractJdbcDatabase {
@Override
public int getPriority() {
return PRIORITY_DEFAULT;
}
@Override
public boolean isCorrectDatabaseImplementation(DatabaseConnection databaseConnection) throws DatabaseException {
return databaseConnection.getDatabaseProductName().equals("ExampleDB");
}
@Override
public String getShortName() {
return "example";
}
@Override
protected String getDefaultDatabaseProductName() {
return "Example Database";
}
@Override
public String getDefaultDriver(String s) {
return "com.example.db.Driver";
}
@Override
public Integer getDefaultPort() {
return 55555;
}
@Override
public boolean supportsInitiallyDeferrableColumns() {
return false;
}
@Override
public boolean supportsTablespaces() {
return true;
}
}
API Documentation
A complete description of the API, including what methods must be implemented and how, is available on the liquibase.database.Database API page.
Next Step
After you have created your Database class, it's time to test it out