liquibase.changelog.StandardChangeLogHistoryService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of liquibase-core Show documentation
Show all versions of liquibase-core Show documentation
Liquibase is a tool for managing and executing database changes.
package liquibase.changelog;
import liquibase.*;
import liquibase.change.Change;
import liquibase.change.CheckSum;
import liquibase.change.ColumnConfig;
import liquibase.database.Database;
import liquibase.database.core.DB2Database;
import liquibase.database.core.MSSQLDatabase;
import liquibase.database.core.SQLiteDatabase;
import liquibase.diff.output.DiffOutputControl;
import liquibase.diff.output.changelog.ChangeGeneratorFactory;
import liquibase.exception.DatabaseException;
import liquibase.exception.DatabaseHistoryException;
import liquibase.exception.LiquibaseException;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.executor.Executor;
import liquibase.executor.ExecutorService;
import liquibase.executor.jvm.ChangelogJdbcMdcListener;
import liquibase.snapshot.InvalidExampleException;
import liquibase.snapshot.SnapshotControl;
import liquibase.snapshot.SnapshotGeneratorFactory;
import liquibase.sqlgenerator.SqlGeneratorFactory;
import liquibase.statement.SqlStatement;
import liquibase.statement.core.*;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Column;
import liquibase.structure.core.DataType;
import liquibase.structure.core.Table;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
public class StandardChangeLogHistoryService extends AbstractChangeLogHistoryService {
private List ranChangeSetList;
private boolean serviceInitialized;
private Boolean hasDatabaseChangeLogTable;
private boolean databaseChecksumsCompatible = true;
private Integer lastChangeSetSequenceValue;
protected static final String LABELS_SIZE = "255";
protected static final String CONTEXTS_SIZE = "255";
@Override
public int getPriority() {
return PRIORITY_DEFAULT;
}
@Override
public boolean supports(Database database) {
return true;
}
public String getDatabaseChangeLogTableName() {
return getDatabase().getDatabaseChangeLogTableName();
}
public String getLiquibaseSchemaName() {
return getDatabase().getLiquibaseSchemaName();
}
public String getLiquibaseCatalogName() {
return getDatabase().getLiquibaseCatalogName();
}
public boolean canCreateChangeLogTable() {
return true;
}
@Override
public void reset() {
this.ranChangeSetList = null;
this.serviceInitialized = false;
this.hasDatabaseChangeLogTable = null;
}
public boolean hasDatabaseChangeLogTable() {
if (hasDatabaseChangeLogTable == null) {
try {
hasDatabaseChangeLogTable = SnapshotGeneratorFactory.getInstance().hasDatabaseChangeLogTable
(getDatabase());
} catch (LiquibaseException e) {
throw new UnexpectedLiquibaseException(e);
}
}
return hasDatabaseChangeLogTable;
}
protected String getCharTypeName() {
if ((getDatabase() instanceof MSSQLDatabase) && ((MSSQLDatabase) getDatabase())
.sendsStringParametersAsUnicode()) {
return "nvarchar";
}
return "varchar";
}
@Override
public void init() throws DatabaseException {
if (serviceInitialized) {
return;
}
Database database = getDatabase();
Table changeLogTable = null;
try {
changeLogTable = SnapshotGeneratorFactory.getInstance().getDatabaseChangeLogTable(new SnapshotControl
(database, false, Table.class, Column.class), database);
} catch (LiquibaseException e) {
throw new UnexpectedLiquibaseException(e);
}
List statementsToExecute = new ArrayList<>();
boolean changeLogCreateAttempted = false;
Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor( "jdbc", getDatabase());
if (changeLogTable != null) {
boolean hasDescription = changeLogTable.getColumn("DESCRIPTION") != null;
boolean hasComments = changeLogTable.getColumn("COMMENTS") != null;
boolean hasTag = changeLogTable.getColumn("TAG") != null;
boolean hasLiquibase = changeLogTable.getColumn("LIQUIBASE") != null;
boolean hasContexts = changeLogTable.getColumn("CONTEXTS") != null;
boolean hasLabels = changeLogTable.getColumn("LABELS") != null;
boolean liquibaseColumnNotRightSize = false;
if (!(this.getDatabase() instanceof SQLiteDatabase)) {
DataType type = changeLogTable.getColumn("LIQUIBASE").getType();
if (type.getTypeName().toLowerCase().startsWith("varchar")) {
Integer columnSize = type.getColumnSize();
liquibaseColumnNotRightSize = (columnSize != null) && (columnSize < 20);
} else {
liquibaseColumnNotRightSize = false;
}
}
boolean hasOrderExecuted = changeLogTable.getColumn("ORDEREXECUTED") != null;
boolean checksumNotRightSize = false;
if (!(this.getDatabase() instanceof SQLiteDatabase)) {
DataType type = changeLogTable.getColumn("MD5SUM").getType();
if (type.getTypeName().toLowerCase().startsWith("varchar") || type.getTypeName().toLowerCase().startsWith("character varying")) {
Integer columnSize = type.getColumnSize();
checksumNotRightSize = (columnSize != null) && (columnSize < 35);
} else {
liquibaseColumnNotRightSize = false;
}
}
boolean hasExecTypeColumn = changeLogTable.getColumn("EXECTYPE") != null;
String charTypeName = getCharTypeName();
boolean hasDeploymentIdColumn = changeLogTable.getColumn("DEPLOYMENT_ID") != null;
if (!hasDescription) {
executor.comment("Adding missing databasechangelog.description column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "DESCRIPTION", charTypeName + "(255)", null));
}
if (!hasTag) {
executor.comment("Adding missing databasechangelog.tag column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "TAG", charTypeName + "(255)", null));
}
if (!hasComments) {
executor.comment("Adding missing databasechangelog.comments column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "COMMENTS", charTypeName + "(255)", null));
}
if (!hasLiquibase) {
executor.comment("Adding missing databasechangelog.liquibase column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "LIQUIBASE", charTypeName + "(20)",
null));
}
if (!hasOrderExecuted) {
executor.comment("Adding missing databasechangelog.orderexecuted column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "ORDEREXECUTED", "int", null));
statementsToExecute.add(new UpdateStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName()).addNewColumnValue("ORDEREXECUTED", -1));
statementsToExecute.add(new SetNullableStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "ORDEREXECUTED", "int", false));
}
if (checksumNotRightSize) {
executor.comment("Modifying size of databasechangelog.md5sum column");
statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "MD5SUM", charTypeName + "(35)"));
}
if (liquibaseColumnNotRightSize) {
executor.comment("Modifying size of databasechangelog.liquibase column");
statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "LIQUIBASE", charTypeName + "(20)"));
}
if (!hasExecTypeColumn) {
executor.comment("Adding missing databasechangelog.exectype column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "EXECTYPE", charTypeName + "(10)",
null));
statementsToExecute.add(new UpdateStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName()).addNewColumnValue("EXECTYPE", "EXECUTED"));
statementsToExecute.add(new SetNullableStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "EXECTYPE", charTypeName + "(10)",
false));
}
if (hasContexts) {
Integer columnSize = changeLogTable.getColumn("CONTEXTS").getType().getColumnSize();
if ((columnSize != null) && (columnSize < Integer.parseInt(getContextsSize()))) {
executor.comment("Modifying size of databasechangelog.contexts column");
statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(),
getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "CONTEXTS",
charTypeName + "("+ getContextsSize()+")"));
}
} else {
executor.comment("Adding missing databasechangelog.contexts column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "CONTEXTS", charTypeName + "("
+ getContextsSize() + ")", null));
}
if (hasLabels) {
Integer columnSize = changeLogTable.getColumn("LABELS").getType().getColumnSize();
if ((columnSize != null) && (columnSize < Integer.parseInt(getLabelsSize()))) {
executor.comment("Modifying size of databasechangelog.labels column");
statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(),
getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LABELS",
charTypeName + "(" + getLabelsSize() + ")"));
}
} else {
executor.comment("Adding missing databasechangelog.labels column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "LABELS", charTypeName + "(" +
getLabelsSize() + ")", null));
}
if (!hasDeploymentIdColumn) {
executor.comment("Adding missing databasechangelog.deployment_id column");
statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(),
getDatabaseChangeLogTableName(), "DEPLOYMENT_ID", "VARCHAR(10)", null));
if (database instanceof DB2Database) {
statementsToExecute.add(new ReorganizeTableStatement(getLiquibaseCatalogName(),
getLiquibaseSchemaName(), getDatabaseChangeLogTableName()));
}
}
SqlStatement databaseChangeLogStatement = new SelectFromDatabaseChangeLogStatement(
new SelectFromDatabaseChangeLogStatement.ByNotNullCheckSum(),
new ColumnConfig().setName("MD5SUM"));
List