0
# Database Support
1
2
This document covers Liquibase's multi-database abstraction layer, including the Database interface, factory system, and platform-specific implementations.
3
4
## Imports
5
6
```java { .api }
7
import liquibase.database.Database;
8
import liquibase.database.DatabaseFactory;
9
import liquibase.database.DatabaseConnection;
10
11
// Core database implementations
12
import liquibase.database.core.*;
13
14
// JDBC connection wrapper
15
import liquibase.database.jvm.JdbcConnection;
16
17
// Exception handling
18
import liquibase.exception.DatabaseException;
19
import liquibase.exception.LiquibaseException;
20
21
// Schema and catalog support
22
import liquibase.CatalogAndSchema;
23
24
import java.sql.Connection;
25
import java.util.List;
26
```
27
28
## Database Interface
29
30
The Database interface provides the core abstraction for all database implementations.
31
32
### Connection Management
33
34
```java { .api }
35
/**
36
* Check if this database implementation supports the given connection
37
* @param conn Database connection to check
38
* @return true if this implementation can handle the connection
39
*/
40
public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException
41
42
/**
43
* Get the default JDBC driver for a given database URL
44
* @param url Database URL
45
* @return JDBC driver class name
46
*/
47
public String getDefaultDriver(String url)
48
49
/**
50
* Get the current database connection
51
* @return DatabaseConnection instance
52
*/
53
public DatabaseConnection getConnection()
54
55
/**
56
* Set the database connection
57
* @param conn DatabaseConnection to use
58
*/
59
public void setConnection(DatabaseConnection conn) throws DatabaseException
60
```
61
62
### Database Information
63
64
```java { .api }
65
/**
66
* Get the database product name
67
* @return Database product name (e.g., "PostgreSQL", "MySQL")
68
*/
69
public String getDatabaseProductName() throws DatabaseException
70
71
/**
72
* Get the database product version
73
* @return Database version string
74
*/
75
public String getDatabaseProductVersion() throws DatabaseException
76
77
/**
78
* Get short name for user selection
79
* @return Short database name (e.g., "postgresql", "mysql")
80
*/
81
public String getShortName()
82
83
/**
84
* Get formatted display name
85
* @return Display name for user interfaces
86
*/
87
public String getDisplayName()
88
89
/**
90
* Get default port for this database type
91
* @return Default port number, or null if not applicable
92
*/
93
public Integer getDefaultPort()
94
```
95
96
### Schema and Catalog Management
97
98
```java { .api }
99
/**
100
* Get the default catalog name
101
* @return Default catalog name
102
*/
103
public String getDefaultCatalogName() throws DatabaseException
104
105
/**
106
* Set the default catalog name
107
* @param catalogName Catalog name to use
108
*/
109
public void setDefaultCatalogName(String catalogName) throws DatabaseException
110
111
/**
112
* Get the default schema name
113
* @return Default schema name
114
*/
115
public String getDefaultSchemaName() throws DatabaseException
116
117
/**
118
* Set the default schema name
119
* @param schemaName Schema name to use
120
*/
121
public void setDefaultSchemaName(String schemaName) throws DatabaseException
122
123
/**
124
* Get catalog name for Liquibase objects
125
* @return Liquibase catalog name
126
*/
127
public String getLiquibaseCatalogName()
128
129
/**
130
* Get schema name for Liquibase objects
131
* @return Liquibase schema name
132
*/
133
public String getLiquibaseSchemaName()
134
```
135
136
### Capability Queries
137
138
```java { .api }
139
/**
140
* Check if database supports auto-increment columns
141
* @return true if auto-increment is supported
142
*/
143
public boolean supportsAutoIncrement()
144
145
/**
146
* Check if database supports sequences
147
* @return true if sequences are supported
148
* @deprecated Use supportsSequences() on specific database objects
149
*/
150
@Deprecated
151
public boolean supportsSequences()
152
153
/**
154
* Check if database supports initially deferred columns
155
* @return true if initially deferred is supported
156
*/
157
public boolean supportsInitiallyDeferrableColumns()
158
159
/**
160
* Check if database supports DROP TABLE CASCADE CONSTRAINTS
161
* @return true if cascade drop is supported
162
*/
163
public boolean supportsDropTableCascadeConstraints()
164
165
/**
166
* Check if database supports DDL in transactions
167
* @return true if DDL can be run in transactions
168
*/
169
public boolean supportsDDLInTransaction()
170
```
171
172
### SQL Generation
173
174
```java { .api }
175
/**
176
* Generate date literal for this database
177
* @param isoDate ISO date string
178
* @return Database-specific date literal
179
*/
180
public String getDateLiteral(String isoDate)
181
182
/**
183
* Get current datetime function for this database
184
* @return Function name/expression for current datetime
185
*/
186
public String getCurrentDateTimeFunction()
187
188
/**
189
* Generate concatenation SQL for this database
190
* @param values Values to concatenate
191
* @return Database-specific concatenation expression
192
*/
193
public String getConcatSql(String... values)
194
195
/**
196
* Generate auto-increment clause for column definition
197
* @return Auto-increment clause, or empty string if not supported
198
*/
199
public String getAutoIncrementClause()
200
```
201
202
## DatabaseFactory Class
203
204
The DatabaseFactory provides database instance creation and management.
205
206
### Factory Methods
207
208
```java { .api }
209
/**
210
* Get the singleton DatabaseFactory instance
211
* @return DatabaseFactory instance
212
*/
213
public static DatabaseFactory getInstance()
214
215
/**
216
* Find correct database implementation for connection
217
* @param connection Database connection
218
* @return Database implementation
219
* @throws DatabaseException if no suitable implementation found
220
*/
221
public Database findCorrectDatabaseImplementation(DatabaseConnection connection) throws DatabaseException
222
223
/**
224
* Open database connection with parameters
225
* @param url Database URL
226
* @param username Database username
227
* @param password Database password
228
* @param driver JDBC driver class name (optional)
229
* @param driverPropertiesFile Driver properties file (optional)
230
* @param propertyProviderClass Property provider class (optional)
231
* @return Database instance
232
* @throws DatabaseException if connection fails
233
*/
234
public Database openDatabase(String url, String username, String password,
235
String driver, String driverPropertiesFile,
236
String propertyProviderClass) throws DatabaseException
237
238
/**
239
* Open database connection
240
* @param url Database URL
241
* @param username Database username
242
* @param password Database password
243
* @param driver JDBC driver class name
244
* @return DatabaseConnection instance
245
* @throws DatabaseException if connection fails
246
*/
247
public DatabaseConnection openConnection(String url, String username, String password, String driver) throws DatabaseException
248
249
/**
250
* Find default driver for database URL
251
* @param url Database URL
252
* @return JDBC driver class name
253
*/
254
public String findDefaultDriver(String url)
255
256
/**
257
* Get all implemented database types
258
* @return List of available Database implementations
259
*/
260
public List<Database> getImplementedDatabases()
261
```
262
263
## Core Database Implementations
264
265
### PostgreSQL Database
266
267
```java { .api }
268
public class PostgresDatabase extends AbstractJdbcDatabase {
269
// PostgreSQL-specific implementation
270
public String getShortName() { return "postgresql"; }
271
public String getDefaultDriver(String url) { return "org.postgresql.Driver"; }
272
public Integer getDefaultPort() { return 5432; }
273
274
// PostgreSQL capabilities
275
public boolean supportsSequences() { return true; }
276
public boolean supportsAutoIncrement() { return true; }
277
public boolean supportsDDLInTransaction() { return true; }
278
}
279
```
280
281
### MySQL Database
282
283
```java { .api }
284
public class MySQLDatabase extends AbstractJdbcDatabase {
285
// MySQL-specific implementation
286
public String getShortName() { return "mysql"; }
287
public String getDefaultDriver(String url) { return "com.mysql.cj.jdbc.Driver"; }
288
public Integer getDefaultPort() { return 3306; }
289
290
// MySQL capabilities
291
public boolean supportsSequences() { return false; }
292
public boolean supportsAutoIncrement() { return true; }
293
public boolean supportsDDLInTransaction() { return false; }
294
}
295
```
296
297
### Oracle Database
298
299
```java { .api }
300
public class OracleDatabase extends AbstractJdbcDatabase {
301
// Oracle-specific implementation
302
public String getShortName() { return "oracle"; }
303
public String getDefaultDriver(String url) { return "oracle.jdbc.OracleDriver"; }
304
public Integer getDefaultPort() { return 1521; }
305
306
// Oracle capabilities
307
public boolean supportsSequences() { return true; }
308
public boolean supportsAutoIncrement() { return false; } // Before 12c
309
public boolean supportsDDLInTransaction() { return false; }
310
}
311
```
312
313
### SQL Server Database
314
315
```java { .api }
316
public class MSSQLDatabase extends AbstractJdbcDatabase {
317
// SQL Server-specific implementation
318
public String getShortName() { return "mssql"; }
319
public String getDefaultDriver(String url) { return "com.microsoft.sqlserver.jdbc.SQLServerDriver"; }
320
public Integer getDefaultPort() { return 1433; }
321
322
// SQL Server capabilities
323
public boolean supportsSequences() { return true; } // SQL Server 2012+
324
public boolean supportsAutoIncrement() { return true; }
325
public boolean supportsDDLInTransaction() { return true; }
326
}
327
```
328
329
### H2 Database
330
331
```java { .api }
332
public class H2Database extends AbstractJdbcDatabase {
333
// H2-specific implementation (in-memory/embedded)
334
public String getShortName() { return "h2"; }
335
public String getDefaultDriver(String url) { return "org.h2.Driver"; }
336
public Integer getDefaultPort() { return null; } // Embedded database
337
338
// H2 capabilities
339
public boolean supportsSequences() { return true; }
340
public boolean supportsAutoIncrement() { return true; }
341
public boolean supportsDDLInTransaction() { return true; }
342
}
343
```
344
345
### SQLite Database
346
347
```java { .api }
348
public class SQLiteDatabase extends AbstractJdbcDatabase {
349
// SQLite-specific implementation
350
public String getShortName() { return "sqlite"; }
351
public String getDefaultDriver(String url) { return "org.sqlite.JDBC"; }
352
public Integer getDefaultPort() { return null; } // File-based database
353
354
// SQLite capabilities
355
public boolean supportsSequences() { return false; }
356
public boolean supportsAutoIncrement() { return true; }
357
public boolean supportsDDLInTransaction() { return true; }
358
}
359
```
360
361
## Complete Database Support List
362
363
All database implementations available in Liquibase:
364
365
```java { .api }
366
// Core relational databases
367
OracleDatabase // Oracle Database
368
MySQLDatabase // MySQL
369
MariaDBDatabase // MariaDB
370
PostgresDatabase // PostgreSQL
371
MSSQLDatabase // Microsoft SQL Server
372
DB2Database // IBM DB2
373
SybaseDatabase // Sybase ASE
374
375
// Embedded/lightweight databases
376
H2Database // H2 Database Engine
377
SQLiteDatabase // SQLite
378
DerbyDatabase // Apache Derby
379
HsqlDatabase // HSQLDB
380
381
// Specialized databases
382
FirebirdDatabase // Firebird
383
CockroachDatabase // CockroachDB
384
385
// Testing and fallback
386
MockDatabase // Mock database for testing
387
UnsupportedDatabase // Fallback for unknown databases
388
```
389
390
## Example Usage
391
392
### Basic Database Connection
393
394
```java { .api }
395
import liquibase.database.DatabaseFactory;
396
import liquibase.database.Database;
397
import liquibase.database.jvm.JdbcConnection;
398
import java.sql.DriverManager;
399
400
// Create JDBC connection
401
Connection jdbcConnection = DriverManager.getConnection(
402
"jdbc:postgresql://localhost:5432/mydb",
403
"username",
404
"password"
405
);
406
407
// Wrap in Liquibase connection
408
DatabaseConnection databaseConnection = new JdbcConnection(jdbcConnection);
409
410
// Get appropriate database implementation
411
DatabaseFactory factory = DatabaseFactory.getInstance();
412
Database database = factory.findCorrectDatabaseImplementation(databaseConnection);
413
414
System.out.println("Database type: " + database.getShortName());
415
System.out.println("Database product: " + database.getDatabaseProductName());
416
System.out.println("Database version: " + database.getDatabaseProductVersion());
417
```
418
419
### Using DatabaseFactory for Connection
420
421
```java { .api }
422
// Let factory handle connection creation
423
DatabaseFactory factory = DatabaseFactory.getInstance();
424
Database database = factory.openDatabase(
425
"jdbc:mysql://localhost:3306/mydb",
426
"username",
427
"password",
428
"com.mysql.cj.jdbc.Driver",
429
null, // driver properties file
430
null // property provider class
431
);
432
433
// Use database
434
System.out.println("Connected to: " + database.getDatabaseProductName());
435
```
436
437
### Database Capability Detection
438
439
```java { .api }
440
// Check database capabilities
441
if (database.supportsAutoIncrement()) {
442
System.out.println("Database supports auto-increment columns");
443
}
444
445
if (database.supportsSequences()) {
446
System.out.println("Database supports sequences");
447
}
448
449
if (database.supportsDDLInTransaction()) {
450
System.out.println("Database supports DDL in transactions");
451
} else {
452
System.out.println("DDL changes will be auto-committed");
453
}
454
455
// Check specific features
456
if (database.supportsInitiallyDeferrableColumns()) {
457
System.out.println("Database supports deferred constraints");
458
}
459
460
if (database.supportsDropTableCascadeConstraints()) {
461
System.out.println("Database supports CASCADE DROP");
462
}
463
```
464
465
### Schema and Catalog Management
466
467
```java { .api }
468
// Set default schema and catalog
469
database.setDefaultSchemaName("app_schema");
470
database.setDefaultCatalogName("app_catalog");
471
472
// Get current settings
473
String currentSchema = database.getDefaultSchemaName();
474
String currentCatalog = database.getDefaultCatalogName();
475
476
System.out.println("Current schema: " + currentSchema);
477
System.out.println("Current catalog: " + currentCatalog);
478
479
// Liquibase table placement
480
String liquibaseSchema = database.getLiquibaseSchemaName();
481
String liquibaseCatalog = database.getLiquibaseCatalogName();
482
483
System.out.println("Liquibase tables in: " + liquibaseCatalog + "." + liquibaseSchema);
484
```
485
486
### Database-Specific SQL Generation
487
488
```java { .api }
489
// Generate database-specific SQL
490
String dateSQL = database.getDateLiteral("2023-12-25");
491
System.out.println("Date literal: " + dateSQL);
492
493
String currentTimeSQL = database.getCurrentDateTimeFunction();
494
System.out.println("Current time function: " + currentTimeSQL);
495
496
String concatSQL = database.getConcatSql("'Hello'", "' '", "'World'");
497
System.out.println("Concatenation SQL: " + concatSQL);
498
499
String autoIncSQL = database.getAutoIncrementClause();
500
if (!autoIncSQL.isEmpty()) {
501
System.out.println("Auto-increment clause: " + autoIncSQL);
502
}
503
```
504
505
### Multi-Database Support
506
507
```java { .api }
508
// Support multiple database types
509
public class MultiDatabaseService {
510
511
public Database connectToDatabase(String type, String url, String user, String pass)
512
throws DatabaseException {
513
DatabaseFactory factory = DatabaseFactory.getInstance();
514
Database database = factory.openDatabase(url, user, pass, null, null, null);
515
516
// Configure based on database type
517
switch (database.getShortName()) {
518
case "postgresql":
519
configurePostgreSQL(database);
520
break;
521
case "mysql":
522
configureMySQL(database);
523
break;
524
case "oracle":
525
configureOracle(database);
526
break;
527
case "mssql":
528
configureSQLServer(database);
529
break;
530
default:
531
configureGeneric(database);
532
}
533
534
return database;
535
}
536
537
private void configurePostgreSQL(Database database) throws DatabaseException {
538
// PostgreSQL-specific configuration
539
database.setDefaultSchemaName("public");
540
}
541
542
private void configureMySQL(Database database) throws DatabaseException {
543
// MySQL-specific configuration
544
// MySQL doesn't use schemas in the same way
545
}
546
547
private void configureOracle(Database database) throws DatabaseException {
548
// Oracle-specific configuration
549
// Set appropriate tablespace if needed
550
}
551
552
private void configureSQLServer(Database database) throws DatabaseException {
553
// SQL Server-specific configuration
554
database.setDefaultSchemaName("dbo");
555
}
556
557
private void configureGeneric(Database database) throws DatabaseException {
558
// Generic configuration for unknown databases
559
}
560
}
561
```
562
563
### Testing with Mock Database
564
565
```java { .api }
566
import liquibase.database.core.MockDatabase;
567
568
// Create mock database for testing
569
MockDatabase mockDatabase = new MockDatabase();
570
mockDatabase.setConnection(new MockDatabaseConnection());
571
572
// Mock database provides controllable behavior for testing
573
System.out.println("Mock database type: " + mockDatabase.getShortName());
574
575
// All operations will be simulated without actual database interaction
576
```
577
578
### Error Handling
579
580
```java { .api }
581
try {
582
DatabaseFactory factory = DatabaseFactory.getInstance();
583
Database database = factory.findCorrectDatabaseImplementation(connection);
584
585
if (database instanceof UnsupportedDatabase) {
586
System.err.println("Database type not supported by Liquibase");
587
// Handle unsupported database scenario
588
}
589
590
} catch (DatabaseException e) {
591
System.err.println("Database connection failed: " + e.getMessage());
592
// Handle connection errors
593
throw e;
594
}
595
```