0
# Changelog Management
1
2
This document covers Liquibase's changelog and changeset management system, including changelog parsing, changeset definition, and change types.
3
4
## Imports
5
6
```java { .api }
7
import liquibase.changelog.DatabaseChangeLog;
8
import liquibase.changelog.ChangeSet;
9
import liquibase.changelog.ChangeLogParameters;
10
import liquibase.change.Change;
11
12
// Core change types
13
import liquibase.change.core.*;
14
15
// Context and label filtering
16
import liquibase.Contexts;
17
import liquibase.Labels;
18
import liquibase.LabelExpression;
19
20
// Validation
21
import liquibase.exception.ValidationErrors;
22
import liquibase.exception.LiquibaseException;
23
24
// Database
25
import liquibase.database.Database;
26
27
import java.util.List;
28
import java.util.Set;
29
```
30
31
## DatabaseChangeLog Class
32
33
The DatabaseChangeLog represents a complete changelog containing multiple changesets.
34
35
### File Management
36
37
```java { .api }
38
/**
39
* Get the physical file path of the changelog
40
* @return Physical file path
41
*/
42
public String getPhysicalFilePath()
43
44
/**
45
* Set the physical file path
46
* @param physicalFilePath Physical path to the changelog file
47
*/
48
public void setPhysicalFilePath(String physicalFilePath)
49
50
/**
51
* Get the logical file path used for includes
52
* @return Logical file path
53
*/
54
public String getLogicalFilePath()
55
56
/**
57
* Set the logical file path for includes
58
* @param logicalFilePath Logical path for changelog references
59
*/
60
public void setLogicalFilePath(String logicalFilePath)
61
```
62
63
### ChangeSet Management
64
65
```java { .api }
66
/**
67
* Get all changesets in the changelog
68
* @return List of all changesets
69
*/
70
public List<ChangeSet> getChangeSets()
71
72
/**
73
* Add a changeset to the changelog
74
* @param changeSet ChangeSet to add
75
*/
76
public void addChangeSet(ChangeSet changeSet)
77
78
/**
79
* Find specific changeset by identifiers
80
* @param path File path
81
* @param author Changeset author
82
* @param id Changeset ID
83
* @return ChangeSet if found, null otherwise
84
*/
85
public ChangeSet getChangeSet(String path, String author, String id)
86
```
87
88
### Validation
89
90
```java { .api }
91
/**
92
* Validate changelog against database
93
* @param database Target database
94
* @param contexts Execution contexts for filtering
95
* @param labelExpression Label expression for filtering
96
* @throws LiquibaseException if validation fails
97
*/
98
public void validate(Database database, Contexts contexts, LabelExpression labelExpression) throws LiquibaseException
99
100
/**
101
* Validate multiple changelogs
102
* @param database Target database
103
* @param changeLogsToValidate Changelogs to validate
104
* @return ValidationErrors containing any validation issues
105
*/
106
public ValidationErrors validate(Database database, DatabaseChangeLog... changeLogsToValidate)
107
```
108
109
### Parameters
110
111
```java { .api }
112
/**
113
* Get changelog parameters
114
* @return ChangeLogParameters instance
115
*/
116
public ChangeLogParameters getChangeLogParameters()
117
118
/**
119
* Set changelog parameters
120
* @param changeLogParameters Parameters to set
121
*/
122
public void setChangeLogParameters(ChangeLogParameters changeLogParameters)
123
```
124
125
## ChangeSet Class
126
127
The ChangeSet represents a single changeset containing one or more changes.
128
129
### Identification Properties
130
131
```java { .api }
132
/**
133
* Get unique changeset ID
134
* @return Changeset ID
135
*/
136
public String getId()
137
138
/**
139
* Get changeset author
140
* @return Author name
141
*/
142
public String getAuthor()
143
144
/**
145
* Get file path containing this changeset
146
* @return File path
147
*/
148
public String getFilePath()
149
```
150
151
### Execution Control Properties
152
153
```java { .api }
154
/**
155
* Get execution contexts for this changeset
156
* @return Contexts object
157
*/
158
public Contexts getContexts()
159
160
/**
161
* Get execution labels for this changeset
162
* @return Labels object
163
*/
164
public Labels getLabels()
165
166
/**
167
* Get target database types for this changeset
168
* @return Set of database type names
169
*/
170
public Set<String> getDbms()
171
172
/**
173
* Check if changeset should re-run when changed
174
* @return true if runOnChange is enabled
175
*/
176
public Boolean getRunOnChange()
177
178
/**
179
* Check if changeset should always run
180
* @return true if runAlways is enabled
181
*/
182
public Boolean getRunAlways()
183
184
/**
185
* Check if changeset should fail on error
186
* @return true if failOnError is enabled (default)
187
*/
188
public Boolean getFailOnError()
189
```
190
191
### Change Management
192
193
```java { .api }
194
/**
195
* Get list of changes in this changeset
196
* @return List of Change objects
197
*/
198
public List<Change> getChanges()
199
200
/**
201
* Add a change to this changeset
202
* @param change Change to add
203
*/
204
public void addChange(Change change)
205
```
206
207
### Rollback Management
208
209
```java { .api }
210
/**
211
* Get rollback changes for this changeset
212
* @return List of rollback changes
213
*/
214
public List<Change> getRollback()
215
216
/**
217
* Add a rollback change
218
* @param change Rollback change to add
219
*/
220
public void addRollbackChange(Change change)
221
```
222
223
## Core Change Types
224
225
### Table Operations
226
227
Create, modify, and drop tables:
228
229
```java { .api }
230
// Create table
231
public class CreateTableChange extends AbstractChange {
232
public void setTableName(String tableName)
233
public void setSchemaName(String schemaName)
234
public void setCatalogName(String catalogName)
235
public void addColumn(ColumnConfig column)
236
}
237
238
// Drop table
239
public class DropTableChange extends AbstractChange {
240
public void setTableName(String tableName)
241
public void setSchemaName(String schemaName)
242
public void setCatalogName(String catalogName)
243
public void setCascadeConstraints(Boolean cascadeConstraints)
244
}
245
246
// Rename table
247
public class RenameTableChange extends AbstractChange {
248
public void setOldTableName(String oldTableName)
249
public void setNewTableName(String newTableName)
250
public void setSchemaName(String schemaName)
251
public void setCatalogName(String catalogName)
252
}
253
```
254
255
### Column Operations
256
257
Add, modify, and drop columns:
258
259
```java { .api }
260
// Add column
261
public class AddColumnChange extends AbstractChange {
262
public void setTableName(String tableName)
263
public void setSchemaName(String schemaName)
264
public void addColumn(ColumnConfig column)
265
}
266
267
// Drop column
268
public class DropColumnChange extends AbstractChange {
269
public void setTableName(String tableName)
270
public void setColumnName(String columnName)
271
public void setSchemaName(String schemaName)
272
}
273
274
// Modify data type
275
public class ModifyDataTypeChange extends AbstractChange {
276
public void setTableName(String tableName)
277
public void setColumnName(String columnName)
278
public void setNewDataType(String newDataType)
279
public void setSchemaName(String schemaName)
280
}
281
282
// Rename column
283
public class RenameColumnChange extends AbstractChange {
284
public void setTableName(String tableName)
285
public void setOldColumnName(String oldColumnName)
286
public void setNewColumnName(String newColumnName)
287
public void setColumnDataType(String columnDataType)
288
public void setSchemaName(String schemaName)
289
}
290
```
291
292
### Constraint Operations
293
294
Manage various database constraints:
295
296
```java { .api }
297
// Add primary key
298
public class AddPrimaryKeyChange extends AbstractChange {
299
public void setTableName(String tableName)
300
public void setColumnNames(String columnNames)
301
public void setConstraintName(String constraintName)
302
public void setSchemaName(String schemaName)
303
}
304
305
// Drop primary key
306
public class DropPrimaryKeyChange extends AbstractChange {
307
public void setTableName(String tableName)
308
public void setConstraintName(String constraintName)
309
public void setSchemaName(String schemaName)
310
}
311
312
// Add foreign key
313
public class AddForeignKeyConstraintChange extends AbstractChange {
314
public void setBaseTableName(String baseTableName)
315
public void setBaseColumnNames(String baseColumnNames)
316
public void setReferencedTableName(String referencedTableName)
317
public void setReferencedColumnNames(String referencedColumnNames)
318
public void setConstraintName(String constraintName)
319
public void setOnDelete(String onDelete)
320
public void setOnUpdate(String onUpdate)
321
}
322
323
// Drop foreign key
324
public class DropForeignKeyConstraintChange extends AbstractChange {
325
public void setBaseTableName(String baseTableName)
326
public void setConstraintName(String constraintName)
327
public void setBaseTableSchemaName(String baseTableSchemaName)
328
}
329
330
// Add unique constraint
331
public class AddUniqueConstraintChange extends AbstractChange {
332
public void setTableName(String tableName)
333
public void setColumnNames(String columnNames)
334
public void setConstraintName(String constraintName)
335
public void setSchemaName(String schemaName)
336
}
337
338
// Drop unique constraint
339
public class DropUniqueConstraintChange extends AbstractChange {
340
public void setTableName(String tableName)
341
public void setConstraintName(String constraintName)
342
public void setSchemaName(String schemaName)
343
}
344
345
// Add not null constraint
346
public class AddNotNullConstraintChange extends AbstractChange {
347
public void setTableName(String tableName)
348
public void setColumnName(String columnName)
349
public void setColumnDataType(String columnDataType)
350
public void setDefaultNullValue(String defaultNullValue)
351
public void setSchemaName(String schemaName)
352
}
353
354
// Drop not null constraint
355
public class DropNotNullConstraintChange extends AbstractChange {
356
public void setTableName(String tableName)
357
public void setColumnName(String columnName)
358
public void setColumnDataType(String columnDataType)
359
public void setSchemaName(String schemaName)
360
}
361
```
362
363
### Index Operations
364
365
Create and drop database indexes:
366
367
```java { .api }
368
// Create index
369
public class CreateIndexChange extends AbstractChange {
370
public void setTableName(String tableName)
371
public void setIndexName(String indexName)
372
public void addColumn(ColumnConfig column)
373
public void setUnique(Boolean unique)
374
public void setSchemaName(String schemaName)
375
}
376
377
// Drop index
378
public class DropIndexChange extends AbstractChange {
379
public void setTableName(String tableName)
380
public void setIndexName(String indexName)
381
public void setSchemaName(String schemaName)
382
}
383
```
384
385
### Data Operations
386
387
Manipulate table data:
388
389
```java { .api }
390
// Insert data
391
public class InsertDataChange extends AbstractChange {
392
public void setTableName(String tableName)
393
public void addColumn(ColumnConfig column)
394
public void setSchemaName(String schemaName)
395
}
396
397
// Update data
398
public class UpdateDataChange extends AbstractChange {
399
public void setTableName(String tableName)
400
public void addColumn(ColumnConfig column)
401
public void addWhereParam(ColumnConfig whereParam)
402
public void setWhere(String where)
403
public void setSchemaName(String schemaName)
404
}
405
406
// Delete data
407
public class DeleteDataChange extends AbstractChange {
408
public void setTableName(String tableName)
409
public void addWhereParam(ColumnConfig whereParam)
410
public void setWhere(String where)
411
public void setSchemaName(String schemaName)
412
}
413
414
// Load data from file
415
public class LoadDataChange extends AbstractChange {
416
public void setTableName(String tableName)
417
public void setFile(String file)
418
public void setRelativeToChangelogFile(Boolean relativeToChangelogFile)
419
public void setEncoding(String encoding)
420
public void setSeparator(String separator)
421
public void setQuotchar(String quotchar)
422
public void addColumn(LoadDataColumnConfig column)
423
}
424
425
// Load and update data
426
public class LoadUpdateDataChange extends AbstractChange {
427
public void setTableName(String tableName)
428
public void setFile(String file)
429
public void setPrimaryKey(String primaryKey)
430
public void addColumn(LoadDataColumnConfig column)
431
}
432
```
433
434
### View and Procedure Operations
435
436
Manage views and stored procedures:
437
438
```java { .api }
439
// Create view
440
public class CreateViewChange extends AbstractChange {
441
public void setViewName(String viewName)
442
public void setSelectQuery(String selectQuery)
443
public void setSchemaName(String schemaName)
444
public void setReplaceIfExists(Boolean replaceIfExists)
445
}
446
447
// Drop view
448
public class DropViewChange extends AbstractChange {
449
public void setViewName(String viewName)
450
public void setSchemaName(String schemaName)
451
}
452
453
// Create stored procedure
454
public class CreateProcedureChange extends AbstractChange {
455
public void setProcedureName(String procedureName)
456
public void setProcedureText(String procedureText)
457
public void setSchemaName(String schemaName)
458
}
459
460
// Drop stored procedure
461
public class DropProcedureChange extends AbstractChange {
462
public void setProcedureName(String procedureName)
463
public void setSchemaName(String schemaName)
464
}
465
```
466
467
### SQL Operations
468
469
Execute custom SQL:
470
471
```java { .api }
472
// Execute raw SQL
473
public class SQLChange extends AbstractChange {
474
public void setSql(String sql)
475
public void setEndDelimiter(String endDelimiter)
476
public void setSplitStatements(Boolean splitStatements)
477
public void setStripComments(Boolean stripComments)
478
}
479
480
// Execute SQL from file
481
public class SQLFileChange extends AbstractChange {
482
public void setPath(String path)
483
public void setRelativeToChangelogFile(Boolean relativeToChangelogFile)
484
public void setEncoding(String encoding)
485
public void setEndDelimiter(String endDelimiter)
486
public void setSplitStatements(Boolean splitStatements)
487
}
488
```
489
490
## Example Usage
491
492
### Creating a DatabaseChangeLog Programmatically
493
494
```java { .api }
495
import liquibase.changelog.DatabaseChangeLog;
496
import liquibase.changelog.ChangeSet;
497
import liquibase.change.core.CreateTableChange;
498
import liquibase.change.ColumnConfig;
499
500
// Create changelog
501
DatabaseChangeLog changelog = new DatabaseChangeLog();
502
changelog.setPhysicalFilePath("db/changelog/programmatic-changelog.xml");
503
504
// Create changeset
505
ChangeSet changeSet = new ChangeSet(
506
"1", // id
507
"admin", // author
508
false, // alwaysRun
509
false, // runOnChange
510
"db/changelog/programmatic-changelog.xml", // filePath
511
null, // contextFilter
512
null, // dbmsList
513
null, // labels
514
true, // runInTransaction
515
null, // objectQuotingStrategy
516
changelog // changeLog
517
);
518
519
// Create table change
520
CreateTableChange createTable = new CreateTableChange();
521
createTable.setTableName("users");
522
createTable.setSchemaName("public");
523
524
// Add columns
525
ColumnConfig idColumn = new ColumnConfig();
526
idColumn.setName("id");
527
idColumn.setType("BIGINT");
528
idColumn.setAutoIncrement(true);
529
ColumnConfig constraints = new ColumnConfig.ConstraintsConfig();
530
constraints.setPrimaryKey(true);
531
constraints.setNullable(false);
532
idColumn.setConstraints(constraints);
533
createTable.addColumn(idColumn);
534
535
ColumnConfig nameColumn = new ColumnConfig();
536
nameColumn.setName("name");
537
nameColumn.setType("VARCHAR(255)");
538
ColumnConfig nameConstraints = new ColumnConfig.ConstraintsConfig();
539
nameConstraints.setNullable(false);
540
nameColumn.setConstraints(nameConstraints);
541
createTable.addColumn(nameColumn);
542
543
ColumnConfig emailColumn = new ColumnConfig();
544
emailColumn.setName("email");
545
emailColumn.setType("VARCHAR(255)");
546
ColumnConfig emailConstraints = new ColumnConfig.ConstraintsConfig();
547
emailConstraints.setUnique(true);
548
emailColumn.setConstraints(emailConstraints);
549
createTable.addColumn(emailColumn);
550
551
// Add change to changeset
552
changeSet.addChange(createTable);
553
554
// Add changeset to changelog
555
changelog.addChangeSet(changeSet);
556
```
557
558
### Complete Changeset with Multiple Changes
559
560
```java { .api }
561
// Create comprehensive changeset
562
ChangeSet complexChangeSet = new ChangeSet(
563
"2", "admin", false, false,
564
"db/changelog/complex-changes.xml",
565
null, null, null, true, null, changelog
566
);
567
568
// Add table
569
CreateTableChange createOrdersTable = new CreateTableChange();
570
createOrdersTable.setTableName("orders");
571
createOrdersTable.setSchemaName("public");
572
573
ColumnConfig orderIdColumn = new ColumnConfig();
574
orderIdColumn.setName("order_id");
575
orderIdColumn.setType("BIGINT");
576
orderIdColumn.setAutoIncrement(true);
577
ColumnConfig orderIdConstraints = new ColumnConfig.ConstraintsConfig();
578
orderIdConstraints.setPrimaryKey(true);
579
orderIdColumn.setConstraints(orderIdConstraints);
580
createOrdersTable.addColumn(orderIdColumn);
581
582
ColumnConfig userIdColumn = new ColumnConfig();
583
userIdColumn.setName("user_id");
584
userIdColumn.setType("BIGINT");
585
ColumnConfig userIdConstraints = new ColumnConfig.ConstraintsConfig();
586
userIdConstraints.setNullable(false);
587
userIdColumn.setConstraints(userIdConstraints);
588
createOrdersTable.addColumn(userIdColumn);
589
590
complexChangeSet.addChange(createOrdersTable);
591
592
// Add foreign key
593
AddForeignKeyConstraintChange addFK = new AddForeignKeyConstraintChange();
594
addFK.setBaseTableName("orders");
595
addFK.setBaseColumnNames("user_id");
596
addFK.setReferencedTableName("users");
597
addFK.setReferencedColumnNames("id");
598
addFK.setConstraintName("fk_orders_user_id");
599
addFK.setOnDelete("CASCADE");
600
601
complexChangeSet.addChange(addFK);
602
603
// Add index
604
CreateIndexChange createIndex = new CreateIndexChange();
605
createIndex.setTableName("orders");
606
createIndex.setIndexName("idx_orders_user_id");
607
ColumnConfig indexColumn = new ColumnConfig();
608
indexColumn.setName("user_id");
609
createIndex.addColumn(indexColumn);
610
611
complexChangeSet.addChange(createIndex);
612
613
// Insert sample data
614
InsertDataChange insertData = new InsertDataChange();
615
insertData.setTableName("users");
616
ColumnConfig nameData = new ColumnConfig();
617
nameData.setName("name");
618
nameData.setValue("John Doe");
619
insertData.addColumn(nameData);
620
ColumnConfig emailData = new ColumnConfig();
621
emailData.setName("email");
622
emailData.setValue("john.doe@example.com");
623
insertData.addColumn(emailData);
624
625
complexChangeSet.addChange(insertData);
626
627
changelog.addChangeSet(complexChangeSet);
628
```
629
630
### Changeset with Context and Labels
631
632
```java { .api }
633
// Create changeset with filtering
634
ChangeSet filteredChangeSet = new ChangeSet(
635
"3", "developer", false, false,
636
"db/changelog/dev-changes.xml",
637
"development,testing", // contexts
638
null, // dbms
639
"feature-auth,version-2.0", // labels
640
true, null, changelog
641
);
642
643
// Add development-specific change
644
CreateTableChange devTable = new CreateTableChange();
645
devTable.setTableName("debug_log");
646
devTable.setSchemaName("public");
647
648
ColumnConfig logIdColumn = new ColumnConfig();
649
logIdColumn.setName("log_id");
650
logIdColumn.setType("BIGINT");
651
logIdColumn.setAutoIncrement(true);
652
ColumnConfig logIdConstraints = new ColumnConfig.ConstraintsConfig();
653
logIdConstraints.setPrimaryKey(true);
654
logIdColumn.setConstraints(logIdConstraints);
655
devTable.addColumn(logIdColumn);
656
657
ColumnConfig messageColumn = new ColumnConfig();
658
messageColumn.setName("message");
659
messageColumn.setType("TEXT");
660
devTable.addColumn(messageColumn);
661
662
filteredChangeSet.addChange(devTable);
663
changelog.addChangeSet(filteredChangeSet);
664
```
665
666
### Changeset with Custom SQL
667
668
```java { .api }
669
// Create changeset with custom SQL
670
ChangeSet sqlChangeSet = new ChangeSet(
671
"4", "dba", false, false,
672
"db/changelog/custom-sql.xml",
673
null, null, null, true, null, changelog
674
);
675
676
// Add custom SQL change
677
SQLChange customSQL = new SQLChange();
678
customSQL.setSql(
679
"CREATE OR REPLACE FUNCTION calculate_order_total(order_id BIGINT) " +
680
"RETURNS DECIMAL(10,2) AS $$ " +
681
"BEGIN " +
682
" RETURN (SELECT SUM(quantity * price) FROM order_items WHERE order_id = $1); " +
683
"END; " +
684
"$$ LANGUAGE plpgsql;"
685
);
686
customSQL.setEndDelimiter(";");
687
customSQL.setSplitStatements(false);
688
689
sqlChangeSet.addChange(customSQL);
690
691
// Add rollback SQL
692
SQLChange rollbackSQL = new SQLChange();
693
rollbackSQL.setSql("DROP FUNCTION IF EXISTS calculate_order_total(BIGINT);");
694
sqlChangeSet.addRollbackChange(rollbackSQL);
695
696
changelog.addChangeSet(sqlChangeSet);
697
```
698
699
### Validation Example
700
701
```java { .api }
702
import liquibase.database.Database;
703
import liquibase.Contexts;
704
import liquibase.LabelExpression;
705
import liquibase.exception.ValidationErrors;
706
707
// Validate changelog
708
try {
709
changelog.validate(database, new Contexts("production"), new LabelExpression());
710
System.out.println("Changelog validation passed");
711
} catch (LiquibaseException e) {
712
System.err.println("Changelog validation failed: " + e.getMessage());
713
}
714
715
// Detailed validation
716
ValidationErrors errors = changelog.validate(database);
717
if (errors.hasErrors()) {
718
System.out.println("Validation errors found:");
719
for (String error : errors.getErrorMessages()) {
720
System.out.println(" - " + error);
721
}
722
}
723
```