PostgreSQL database support module for Flyway migration tool with specialized implementations for PostgreSQL and CockroachDB databases
—
Specialized database support for CockroachDB databases, providing retry logic, version detection, and database-specific optimizations within the Flyway migration framework.
Database type implementation that provides CockroachDB-specific functionality while maintaining PostgreSQL wire protocol compatibility.
/**
* CockroachDB database type implementation
*/
public class CockroachDBDatabaseType extends BaseDatabaseType {
/**
* Returns the database name identifier
* @return "CockroachDB"
*/
public String getName();
/**
* Returns the null type identifier for this database
* @return Types.NULL
*/
public int getNullType();
/**
* Indicates whether CockroachDB supports read-only transactions
* @return false (CockroachDB does not support read-only transactions)
*/
public boolean supportsReadOnlyTransactions();
/**
* Checks if this database type can handle the given JDBC URL
* Uses PostgreSQL driver but with CockroachDB-specific detection
* @param url JDBC URL to check
* @return true for PostgreSQL URLs (detection happens later)
*/
public boolean handlesJDBCUrl(String url);
/**
* Returns the priority for database type selection
* @return 1 (higher than PostgreSQL to be checked first)
*/
public int getPriority();
/**
* Returns the JDBC driver class for CockroachDB
* @param url JDBC URL
* @param classLoader Class loader for loading driver
* @return PostgreSQL driver class name
*/
public String getDriverClass(String url, ClassLoader classLoader);
/**
* Detects CockroachDB by checking database product name and version output
* @param databaseProductName Database product name from JDBC metadata
* @param databaseProductVersion Database version
* @param connection JDBC connection for additional queries
* @return true if SELECT VERSION() output contains "CockroachDB"
*/
public boolean handlesDatabaseProductNameAndVersion(String databaseProductName,
String databaseProductVersion,
Connection connection);
/**
* Creates a CockroachDB database instance
* @param configuration Flyway configuration
* @param jdbcConnectionFactory Connection factory
* @param statementInterceptor Statement interceptor
* @return CockroachDBDatabase instance
*/
public Database createDatabase(Configuration configuration,
JdbcConnectionFactory jdbcConnectionFactory,
StatementInterceptor statementInterceptor);
/**
* Creates a CockroachDB parser instance
* @param configuration Flyway configuration
* @param resourceProvider Resource provider for loading SQL files
* @param parsingContext Parsing context
* @return CockroachDBParser instance
*/
public Parser createParser(Configuration configuration,
ResourceProvider resourceProvider,
ParsingContext parsingContext);
/**
* Creates CockroachDB-specific execution strategy with retry logic
* @param connection JDBC connection
* @return CockroachDBRetryingStrategy for handling transaction retries
*/
public DatabaseExecutionStrategy createExecutionStrategy(Connection connection);
/**
* Creates transactional execution template with CockroachDB retry logic
* @param connection JDBC connection
* @param rollbackOnException Whether to rollback on exceptions
* @return CockroachRetryingTransactionalExecutionTemplate
*/
public ExecutionTemplate createTransactionalExecutionTemplate(Connection connection,
boolean rollbackOnException);
}Usage Examples:
import org.flywaydb.database.cockroachdb.CockroachDBDatabaseType;
// Database type is automatically registered and detected
// CockroachDB connections use PostgreSQL JDBC URLs
Flyway flyway = Flyway.configure()
.dataSource("jdbc:postgresql://localhost:26257/mydb", "root", "")
.locations("classpath:db/migration")
.load();
// CockroachDB is automatically detected via version string
CockroachDBDatabaseType dbType = new CockroachDBDatabaseType();
boolean hasHigherPriority = dbType.getPriority() > 0; // true - checked before PostgreSQL
// Verify database capabilities
boolean supportsReadOnly = dbType.supportsReadOnlyTransactions(); // falseMain database implementation providing CockroachDB-specific operations and version detection.
/**
* CockroachDB database implementation
*/
public class CockroachDBDatabase extends Database<CockroachDBConnection> {
/**
* Creates a new CockroachDB database instance
* Automatically detects and stores the CockroachDB version
* @param configuration Flyway configuration
* @param jdbcConnectionFactory Connection factory
* @param statementInterceptor Statement interceptor
*/
public CockroachDBDatabase(Configuration configuration,
JdbcConnectionFactory jdbcConnectionFactory,
StatementInterceptor statementInterceptor);
/**
* Creates a CockroachDB connection wrapper
* @param connection Raw JDBC connection
* @return CockroachDBConnection instance
*/
protected CockroachDBConnection doGetConnection(Connection connection);
/**
* Ensures the CockroachDB version is supported by Flyway
* @param configuration Flyway configuration
* @throws FlywayException if version is not supported
*/
public void ensureSupported(Configuration configuration);
/**
* Generates the SQL script for creating the Flyway schema history table
* Uses CREATE TABLE IF NOT EXISTS for CockroachDB compatibility
* @param table The table to create
* @param baseline Whether to include baseline entry
* @return SQL script for table creation with CockroachDB-specific syntax
*/
public String getRawCreateScript(Table table, boolean baseline);
/**
* Determines the CockroachDB version from database metadata
* @return Parsed version (e.g., "22.1" from "v22.1.2")
*/
protected MigrationVersion determineVersion();
/**
* Checks if this CockroachDB version supports schemas
* @return true for version 20.2 and later
*/
boolean supportsSchemas();
/**
* Gets the current database user
* @return Current user name from SHOW SESSION_USER
* @throws SQLException if user cannot be determined
*/
protected String doGetCurrentUser() throws SQLException;
/**
* Indicates whether CockroachDB supports DDL transactions
* @return false (CockroachDB limitation)
*/
public boolean supportsDdlTransactions();
/**
* Returns the CockroachDB boolean true literal
* @return "TRUE"
*/
public String getBooleanTrue();
/**
* Returns the CockroachDB boolean false literal
* @return "FALSE"
*/
public String getBooleanFalse();
/**
* Indicates whether catalog equals schema in CockroachDB
* @return false
*/
public boolean catalogIsSchema();
/**
* Determines connection usage strategy for CockroachDB
* @return false (always use multiple connections due to retry requirements)
*/
public boolean useSingleConnection();
}CockroachDB-specific connection handling with schema support and database version awareness.
/**
* CockroachDB connection implementation
*/
public class CockroachDBConnection extends Connection<CockroachDBDatabase> {
/**
* Creates a new CockroachDB connection wrapper
* @param database The CockroachDB database instance
* @param connection The raw JDBC connection
*/
public CockroachDBConnection(CockroachDBDatabase database, java.sql.Connection connection);
/**
* Gets a schema by name (requires CockroachDB 20.2+)
* @param name Schema name
* @return CockroachDBSchema instance
*/
public Schema getSchema(String name);
/**
* Gets the current schema for this connection
* @return Current schema or null if schemas not supported
* @throws SQLException if current schema cannot be determined
*/
public Schema doGetCurrentSchema() throws SQLException;
}CockroachDB-specific SQL parser that extends PostgreSQL parsing capabilities.
/**
* CockroachDB SQL parser implementation
*/
public class CockroachDBParser extends Parser {
/**
* Creates a new CockroachDB parser
* @param configuration Flyway configuration
* @param parsingContext Parser context information
*/
public CockroachDBParser(Configuration configuration, ParsingContext parsingContext);
}Usage Examples:
import org.flywaydb.database.cockroachdb.CockroachDBDatabase;
// Database is typically created via CockroachDBDatabaseType.createDatabase()
CockroachDBDatabase database = (CockroachDBDatabase) flyway.getConfiguration()
.getDatabaseType()
.createDatabase(config, connectionFactory, interceptor);
// Check version-specific capabilities
boolean hasSchemaSupport = database.supportsSchemas(); // true for v20.2+
boolean supportsDdlTx = database.supportsDdlTransactions(); // false
// Version information
MigrationVersion version = database.getVersion();
System.out.println("CockroachDB version: " + version.getVersion());
// Table creation with CockroachDB syntax
Table historyTable = database.getTable("flyway_schema_history");
String createScript = database.getRawCreateScript(historyTable, false);
// Uses "CREATE TABLE IF NOT EXISTS" syntaxCockroachDB requires special handling for transaction retries due to its distributed nature:
/**
* CockroachDB-specific execution strategy with retry logic
*/
public class CockroachDBRetryingStrategy implements DatabaseExecutionStrategy {
// Implementation handles CockroachDB transaction retry logic
}
/**
* Transactional execution template with CockroachDB retry handling
*/
public class CockroachRetryingTransactionalExecutionTemplate extends ExecutionTemplate {
/**
* Creates retry-enabled transactional execution template
* @param connection JDBC connection
* @param rollbackOnException Whether to rollback on exceptions
*/
public CockroachRetryingTransactionalExecutionTemplate(Connection connection,
boolean rollbackOnException);
}// Version detection from CockroachDB system tables
// SELECT value FROM crdb_internal.node_build_info WHERE field='Version'
// or field='Tag' as fallback
// Example version strings:
// "v22.1.2" -> parsed as MigrationVersion "22.1"
// "v21.2.15" -> parsed as MigrationVersion "21.2"// CockroachDB does NOT support DDL in transactions
boolean supportsDdl = database.supportsDdlTransactions(); // returns false
// This means schema changes cannot be rolled back automatically
// Each DDL statement is committed immediately// Schema support is version-dependent
if (database.supportsSchemas()) {
// CockroachDB 20.2+ supports schemas
Schema schema = connection.getSchema("my_schema");
schema.create();
} else {
// Pre-20.2 versions use default schema only
System.out.println("Schema operations not supported in this CockroachDB version");
}// CockroachDB always uses multiple connections
boolean singleConnection = database.useSingleConnection(); // always false
// This is required for proper retry logic handling
// Retry operations need separate connection contexts// CockroachDB migrations automatically handle retries
// No special code needed - handled by CockroachRetryingTransactionalExecutionTemplate
Flyway flyway = Flyway.configure()
.dataSource("jdbc:postgresql://localhost:26257/mydb", "root", "")
.locations("classpath:db/migration")
.load();
// Migrations automatically retry on serialization failures
flyway.migrate();-- Each DDL statement is auto-committed in CockroachDB
-- Good practice: Keep DDL statements atomic and independent
-- Good: Simple, atomic operations
CREATE TABLE users (id SERIAL PRIMARY KEY, name STRING);
CREATE INDEX idx_users_name ON users(name);
-- Avoid: Complex multi-step DDL in single migration
-- Better to split across multiple migration files-- For CockroachDB 20.2+
CREATE SCHEMA app_schema;
CREATE TABLE app_schema.users (id SERIAL PRIMARY KEY, name STRING);
-- For older versions, use default schema
CREATE TABLE users (id SERIAL PRIMARY KEY, name STRING);// CockroachDB-specific error handling
try {
flyway.migrate();
} catch (FlywayException e) {
if (e.getMessage().contains("restart transaction")) {
System.out.println("Transaction retry handled automatically");
} else if (e.getMessage().contains("schema operations not supported")) {
System.out.println("Upgrade CockroachDB to 20.2+ for schema support");
}
}import org.flywaydb.core.Flyway;
import org.flywaydb.database.cockroachdb.CockroachDBDatabase;
// Complete CockroachDB integration
Flyway flyway = Flyway.configure()
.dataSource("jdbc:postgresql://localhost:26257/mycompany", "root", "")
.locations("classpath:db/migration")
.table("schema_version") // Custom history table name
.load();
// Migrate with automatic CockroachDB detection and retry handling
flyway.migrate();
// Access CockroachDB-specific functionality
CockroachDBDatabase database = (CockroachDBDatabase) flyway.getConfiguration()
.getDatabaseType()
.createDatabase(flyway.getConfiguration(), null, null);
System.out.println("CockroachDB version: " + database.getVersion());
System.out.println("Schema support: " + database.supportsSchemas());Install with Tessl CLI
npx tessl i tessl/maven-org-flywaydb--flyway-database-postgresql