Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COPY- generateChangelog optionally creates runOnChange=true and replaceIfExists=true for createView changes #5345

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0e959ae
generateChangelog optionally creates runOnChange=true and replaceIfEx…
mkarg Aug 9, 2023
f9fe3de
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Aug 10, 2023
0bee9ed
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Aug 10, 2023
7c0800a
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Aug 10, 2023
f5c3a0f
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Aug 10, 2023
addb42c
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Aug 10, 2023
b93f41b
Merge branch 'issue-4634' of https://github.com/mkarg/liquibase into …
MalloD12 Aug 23, 2023
a32ac7e
Merge remote-tracking branch 'origin/master' into mkarg-issue-4634
MalloD12 Aug 24, 2023
5a44b0b
Merge branch 'master' into issue-4634
filipelautert Aug 29, 2023
62ee23a
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Nov 2, 2023
8c1a7fb
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Nov 2, 2023
c87d9ea
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Nov 2, 2023
4eba1c9
fixup! generateChangelog optionally creates runOnChange=true and repl…
mkarg Nov 2, 2023
838ec6a
Merge branch 'master' into issue-4634
filipelautert Nov 3, 2023
77b039c
Merge branch 'issue-4634' of https://github.com/mkarg/liquibase into …
MalloD12 Nov 9, 2023
58e9f4e
- Fixed generateChangelog definition test.
MalloD12 Nov 10, 2023
47c11b6
Merge branch 'master' into mkarg-issue-4634
MalloD12 Nov 10, 2023
c9791cb
Merge branch 'master' into issue-4634
filipelautert Nov 21, 2023
59a7589
Merge branch 'master' into mkarg-issue-4634
MalloD12 Dec 6, 2023
6129608
- Extend changes to DiffChangelog command as well.
MalloD12 Dec 7, 2023
cc19be5
Merge branch 'master' into mkarg-issue-4634
MalloD12 Dec 7, 2023
0218208
Merge branch 'issue-4634' of https://github.com/mkarg/liquibase into …
MalloD12 Dec 7, 2023
135022b
- Fixed command argument type from GeneraChangelogMySQL suite.
MalloD12 Dec 7, 2023
324f078
Merge branch 'master' into issue-4634
rberezen Dec 8, 2023
1ae4260
generateChangelog optionally creates runOnChange=true and replaceIfEx…
mkarg Aug 9, 2023
42bdf68
Merge branch 'issue-4634' of https://github.com/mkarg/liquibase into …
MalloD12 Dec 9, 2023
6cb637f
Merge branch 'master' into 4635-copy
MalloD12 Dec 13, 2023
26b2d9b
- Added abstractchangelog argument to generate-changelog and diff-cha…
MalloD12 Dec 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,29 @@ create table str4 (
CommandUtil.runDropAll(mysql)

}

def "Ensure generate changelog set runOnChange and replaceIfExists properties correctly for a created view changeset"() {
given:
CommandUtil.runUpdate(mysql, "changelogs/mysql/complete/createtable.and.view.changelog.xml", null, null, null)
OutputStream outputStream = new ByteArrayOutputStream()

when:
CommandScope commandScope = new CommandScope(GenerateChangelogCommandStep.COMMAND_NAME)
commandScope.addArgumentValue(DbUrlConnectionArgumentsCommandStep.URL_ARG, mysql.getConnectionUrl())
commandScope.addArgumentValue(DbUrlConnectionArgumentsCommandStep.USERNAME_ARG, mysql.getUsername())
commandScope.addArgumentValue(DbUrlConnectionArgumentsCommandStep.PASSWORD_ARG, mysql.getPassword())
commandScope.addArgumentValue(GenerateChangelogCommandStep.REPLACE_IF_EXISTS_TYPES_ARG, "createView")
commandScope.addArgumentValue(GenerateChangelogCommandStep.RUN_ON_CHANGE_TYPES_ARG, "createView")
commandScope.setOutput(outputStream)
commandScope.execute()

then:
def outputContent = outputStream.toString();
outputContent.contains(" runOnChange=\"true\">")
outputContent.contains(" replaceIfExists=\"true\"")

cleanup:
CommandUtil.runDropAll(mysql)
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,37 @@ COMMENT ON COLUMN $viewName.$columnName IS '$columnComment';
targetDatabase.close()
CommandUtil.runDropAll(postgres)
}

def "Ensure diff-changelog set runOnChange and replaceIfExists properties correctly for a created view changeset"() {
given:
CommandUtil.runUpdate(postgres, "changelogs/mysql/complete/createtable.and.view.changelog.xml", null, null, null)
def outputChangelogFile = String.format("diffChangelogFile-%s-output.xml", StringUtil.randomIdentifer(10))
Database refDatabase = DatabaseFactory.instance.openDatabase(postgres.getConnectionUrl(), postgres.getUsername(), postgres.getPassword(), null, null)

Database targetDatabase =
DatabaseFactory.instance.openDatabase(postgres.getConnectionUrl().replace("lbcat", "lbcat2"), postgres.getUsername(), postgres.getPassword(), null, null)

when:
CommandScope commandScope = new CommandScope(DiffChangelogCommandStep.COMMAND_NAME)
commandScope.addArgumentValue(DbUrlConnectionArgumentsCommandStep.DATABASE_ARG, targetDatabase)
commandScope.addArgumentValue(DiffChangelogCommandStep.CHANGELOG_FILE_ARG, outputChangelogFile)
commandScope.addArgumentValue(DiffChangelogCommandStep.REPLACE_IF_EXISTS_TYPES_ARG, "createView")
commandScope.addArgumentValue(DiffChangelogCommandStep.RUN_ON_CHANGE_TYPES_ARG, "createView")
commandScope.addArgumentValue(ReferenceDbUrlConnectionCommandStep.REFERENCE_DATABASE_ARG, refDatabase)
commandScope.execute()

then:

def outputFile = new File(outputChangelogFile)
def outputContent = FileUtil.getContents(outputFile)
outputContent.contains(" runOnChange=\"true\">")
outputContent.contains(" replaceIfExists=\"true\"")

cleanup:
outputFile.delete()
refDatabase.close()
targetDatabase.close()
CommandUtil.runDropAll(postgres)
postgres.getConnection().close()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>

<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">

<changeSet id="createTable" author="mallod">
<createTable tableName="test_table">
<column name="id" type="int"/>
<column name="name" type="varchar(255)"/>
</createTable>
</changeSet>

<changeSet id="createView" author="mallod">
<createView viewName="testView">
select * from test_table
</createView>
</changeSet>
</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ Optional Args:
Default: null
referenceUsername (String) The reference database username
Default: null
replaceIfExistsTypes (String) Sets replaceIfExists="true" for changes of these types (supported types: createProcedure, createView)
Default: none
runOnChangeTypes (String) Sets runOnChange="true" for changesets containing solely changes of these types (e. g. createView, createProcedure, ...).
Default: none
schemas (String) Schemas to include in diff
Default: null
username (String) Username to use to connect to the database
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ Optional Args:
password (String) Password to use to connect to the database
Default: null
OBFUSCATED
replaceIfExistsTypes (String) Sets replaceIfExists="true" for changes of these types (supported types: createProcedure, createView)
Default: none
runOnChangeTypes (String) Sets runOnChange="true" for changesets containing solely changes of these types (e. g. createView, createProcedure, ...).
Default: none
schemas (String) Schemas to include in diff
Default: null
username (String) Username to use to connect to the database
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package liquibase.change;

/**
* Marker interface for all {@link Change}s providing a {@code setReplaceIfExists()} method.
*/
public interface ReplaceIfExists {
void setReplaceIfExists(Boolean replaceIfExists);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import java.util.Map;

@DatabaseChange(name = "createProcedure", description = "Defines a stored procedure.", priority = ChangeMetaData.PRIORITY_DEFAULT)
public class CreateProcedureChange extends AbstractChange implements DbmsTargetedChange {
public class CreateProcedureChange extends AbstractChange implements DbmsTargetedChange, ReplaceIfExists {
private String comments;
private String catalogName;
private String schemaName;
Expand Down Expand Up @@ -175,6 +175,7 @@ public Boolean getReplaceIfExists() {
return replaceIfExists;
}

@Override
public void setReplaceIfExists(Boolean replaceIfExists) {
this.replaceIfExists = replaceIfExists;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
* Creates a new view.
*/
@DatabaseChange(name = "createView", description = "Create a new database view", priority = ChangeMetaData.PRIORITY_DEFAULT)
public class CreateViewChange extends AbstractChange {
public class CreateViewChange extends AbstractChange implements ReplaceIfExists {

private String catalogName;
private String schemaName;
Expand Down Expand Up @@ -96,6 +96,7 @@ public Boolean getReplaceIfExists() {
return replaceIfExists;
}

@Override
public void setReplaceIfExists(Boolean replaceIfExists) {
this.replaceIfExists = replaceIfExists;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import liquibase.Scope;
import liquibase.command.*;
import liquibase.command.core.helpers.AbstractChangelogCommandStep;
import liquibase.command.core.helpers.DiffOutputControlCommandStep;
import liquibase.command.providers.ReferenceDatabase;
import liquibase.database.Database;
Expand All @@ -16,11 +17,9 @@
import liquibase.util.StringUtil;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.*;

public class DiffChangelogCommandStep extends AbstractCommandStep {
public class DiffChangelogCommandStep extends AbstractChangelogCommandStep {

public static final String[] COMMAND_NAME = {"diffChangelog"};

Expand All @@ -43,6 +42,10 @@ public class DiffChangelogCommandStep extends AbstractCommandStep {
.addAlias("contexts")
.description("Changeset contexts to generate")
.build();

builder.addArgument(AbstractChangelogCommandStep.RUN_ON_CHANGE_TYPES_ARG).build();

builder.addArgument(AbstractChangelogCommandStep.REPLACE_IF_EXISTS_TYPES_ARG).build();
}

@Override
Expand Down Expand Up @@ -88,6 +91,8 @@ public void run(CommandResultsBuilder resultsBuilder) throws Exception {
changeLogWriter.setChangeSetContext(commandScope.getArgumentValue(CONTEXTS_ARG));
changeLogWriter.setChangeSetLabels(commandScope.getArgumentValue(LABEL_FILTER_ARG));
changeLogWriter.setChangeSetAuthor(commandScope.getArgumentValue(AUTHOR_ARG));
changeLogWriter.setChangeSetRunOnChangeTypes(commandScope.getArgumentValue(RUN_ON_CHANGE_TYPES_ARG).split("\\s*,\\s*"));
changeLogWriter.setChangeReplaceIfExistsTypes(commandScope.getArgumentValue(REPLACE_IF_EXISTS_TYPES_ARG).split("\\s*,\\s*"));
if (StringUtil.trimToNull(changeLogFile) == null) {
changeLogWriter.print(outputStream);
} else {
Expand All @@ -112,6 +117,8 @@ public void run(CommandResultsBuilder resultsBuilder) throws Exception {
@Override
public void validate(CommandScope commandScope) throws CommandValidationException {
commandScope.addArgumentValue(DiffCommandStep.FORMAT_ARG, "none");
validateReplaceIfExistsTypes(commandScope);
validateRunOnChangeTypes(commandScope);
}

protected DiffToChangeLog createDiffToChangeLogObject(DiffResult diffResult, DiffOutputControl diffOutputControl) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import liquibase.Scope;
import liquibase.command.*;
import liquibase.command.core.helpers.AbstractChangelogCommandStep;
import liquibase.command.core.helpers.DbUrlConnectionArgumentsCommandStep;
import liquibase.command.core.helpers.DiffOutputControlCommandStep;
import liquibase.command.core.helpers.ReferenceDbUrlConnectionCommandStep;
Expand All @@ -21,8 +22,9 @@
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class GenerateChangelogCommandStep extends AbstractCommandStep {
public class GenerateChangelogCommandStep extends AbstractChangelogCommandStep {

public static final String[] COMMAND_NAME = {"generateChangelog"};

Expand All @@ -37,7 +39,6 @@ public class GenerateChangelogCommandStep extends AbstractCommandStep {
public static final CommandArgumentDefinition<String> DATA_OUTPUT_DIR_ARG;
public static final CommandArgumentDefinition<Boolean> OVERWRITE_OUTPUT_FILE_ARG;
public static final CommandArgumentDefinition<String> CHANGELOG_FILE_ARG;

public static final CommandArgumentDefinition<String> REFERENCE_URL_ARG;
public static final CommandArgumentDefinition<String> REFERENCE_USERNAME_ARG;
public static final CommandArgumentDefinition<String> REFERENCE_PASSWORD_ARG;
Expand Down Expand Up @@ -88,6 +89,10 @@ public class GenerateChangelogCommandStep extends AbstractCommandStep {
.hidden().build();
REFERENCE_LIQUIBASE_CATALOG_NAME_ARG = builder.argument("referenceLiquibaseCatalogName", String.class)
.hidden().build();

builder.addArgument(AbstractChangelogCommandStep.RUN_ON_CHANGE_TYPES_ARG).build();

builder.addArgument(AbstractChangelogCommandStep.REPLACE_IF_EXISTS_TYPES_ARG).build();
}

@Override
Expand Down Expand Up @@ -131,6 +136,8 @@ public void run(CommandResultsBuilder resultsBuilder) throws Exception {
changeLogWriter.setChangeSetLabels(commandScope.getArgumentValue(LABEL_FILTER_ARG));
}
changeLogWriter.setChangeSetPath(changeLogFile);
changeLogWriter.setChangeSetRunOnChangeTypes(commandScope.getArgumentValue(RUN_ON_CHANGE_TYPES_ARG).split("\\s*,\\s*"));
changeLogWriter.setChangeReplaceIfExistsTypes(commandScope.getArgumentValue(REPLACE_IF_EXISTS_TYPES_ARG).split("\\s*,\\s*"));

ObjectQuotingStrategy originalStrategy = referenceDatabase.getObjectQuotingStrategy();
try {
Expand Down Expand Up @@ -165,6 +172,8 @@ public void validate(CommandScope commandScope) throws CommandValidationExceptio
commandScope.addArgumentValue(DbUrlConnectionArgumentsCommandStep.SKIP_DATABASE_STEP_ARG, true);
commandScope.addArgumentValue(DiffCommandStep.FORMAT_ARG, "none");
validateConditionsToOverwriteChangelogFile(commandScope);
validateReplaceIfExistsTypes(commandScope);
validateRunOnChangeTypes(commandScope);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package liquibase.command.core.helpers;

import liquibase.Scope;
import liquibase.change.ChangeFactory;
import liquibase.change.ReplaceIfExists;
import liquibase.command.AbstractCommandStep;
import liquibase.command.CommandArgumentDefinition;
import liquibase.command.CommandBuilder;
import liquibase.command.CommandScope;
import liquibase.exception.CommandValidationException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public abstract class AbstractChangelogCommandStep extends AbstractCommandStep {

protected static final String[] COMMAND_NAME = {"abstractChangelogCommandStep"};
public static final CommandArgumentDefinition<String> RUN_ON_CHANGE_TYPES_ARG;
public static final CommandArgumentDefinition<String> REPLACE_IF_EXISTS_TYPES_ARG;

static {
final CommandBuilder builder = new CommandBuilder(COMMAND_NAME);
RUN_ON_CHANGE_TYPES_ARG = builder.argument("runOnChangeTypes", String.class)
.defaultValue("none").description("Sets runOnChange=\"true\" for changesets containing solely changes of these types (e. g. createView, createProcedure, ...).").build();
final String replaceIfExistsTypeNames = supportedReplaceIfExistsTypes().collect(Collectors.joining(", "));
REPLACE_IF_EXISTS_TYPES_ARG = builder.argument("replaceIfExistsTypes", String.class)
.defaultValue("none")
.description(String.format("Sets replaceIfExists=\"true\" for changes of these types (supported types: %s)", replaceIfExistsTypeNames)).build();
}

protected static void validateRunOnChangeTypes(final CommandScope commandScope) throws CommandValidationException {
final Collection<String> runOnChangeTypes = new ArrayList(Arrays.asList(commandScope.getArgumentValue(RUN_ON_CHANGE_TYPES_ARG).split("\\s*,\\s*")));
final Collection<String> supportedRunOnChangeTypes = supportedRunOnChangeTypes().collect(Collectors.toList());
supportedRunOnChangeTypes.add("none");
runOnChangeTypes.removeAll(supportedRunOnChangeTypes);
if (!runOnChangeTypes.isEmpty())
throw new CommandValidationException("Invalid types for --run-on-change-types: " + runOnChangeTypes.stream().collect(Collectors.joining(", ")));
}

protected static void validateReplaceIfExistsTypes(final CommandScope commandScope) throws CommandValidationException {
final Collection<String> replaceIfExistsTypes = new ArrayList(Arrays.asList(commandScope.getArgumentValue(REPLACE_IF_EXISTS_TYPES_ARG).split("\\s*,\\s*")));
final Collection<String> supportedReplaceIfExistsTypes = supportedReplaceIfExistsTypes().collect(Collectors.toList());
supportedReplaceIfExistsTypes.add("none");
replaceIfExistsTypes.removeAll(supportedReplaceIfExistsTypes);
if (!replaceIfExistsTypes.isEmpty())
throw new CommandValidationException("Invalid types for --replace-if-exists-types: " + replaceIfExistsTypes.stream().collect(Collectors.joining(", ")));
}

protected static Stream<String> supportedRunOnChangeTypes() {
final ChangeFactory changeFactory = Scope.getCurrentScope().getSingleton(ChangeFactory.class);
return changeFactory.getDefinedChanges().stream();
}

protected static Stream<String> supportedReplaceIfExistsTypes() {
final ChangeFactory changeFactory = Scope.getCurrentScope().getSingleton(ChangeFactory.class);
return changeFactory.getDefinedChanges().stream().filter(changeType -> changeFactory.create(changeType) instanceof ReplaceIfExists);
}
}
Loading
Loading