From 0385016856b40c037e66d86ecf203a6751fb0b0d Mon Sep 17 00:00:00 2001 From: "philipp.kleber" Date: Thu, 28 Nov 2024 20:33:55 +0100 Subject: [PATCH] Implement multi-schema support --- .../hibernate/database/HibernateDatabase.java | 26 +++--- .../snapshot/SchemaSnapshotGenerator.java | 8 +- .../snapshot/SequenceSnapshotGenerator.java | 6 ++ .../snapshot/TableSnapshotGenerator.java | 18 +++- .../multischema/auction/AuctionInfo.java | 60 +++++++++++++ .../multischema/auction/AuctionItem.java | 86 +++++++++++++++++++ .../multischema/auction/AuditedItem.java | 34 ++++++++ .../com/example/multischema/auction/Bid.java | 64 ++++++++++++++ .../example/multischema/auction/BuyNow.java | 19 ++++ .../multischema/auction/FirstTable.java | 41 +++++++++ .../com/example/multischema/auction/Item.java | 32 +++++++ .../com/example/multischema/auction/Name.java | 48 +++++++++++ .../multischema/auction/Persistent.java | 21 +++++ .../multischema/auction/SecondTable.java | 19 ++++ .../auction/SecondarySchemaEntity.java | 43 ++++++++++ .../com/example/multischema/auction/User.java | 74 ++++++++++++++++ .../example/multischema/auction/Watcher.java | 19 ++++ .../hibernate/HibernateMultiSchemaTest.java | 64 ++++++++++++++ 18 files changed, 667 insertions(+), 15 deletions(-) create mode 100644 src/test/java/com/example/multischema/auction/AuctionInfo.java create mode 100644 src/test/java/com/example/multischema/auction/AuctionItem.java create mode 100755 src/test/java/com/example/multischema/auction/AuditedItem.java create mode 100644 src/test/java/com/example/multischema/auction/Bid.java create mode 100644 src/test/java/com/example/multischema/auction/BuyNow.java create mode 100644 src/test/java/com/example/multischema/auction/FirstTable.java create mode 100644 src/test/java/com/example/multischema/auction/Item.java create mode 100644 src/test/java/com/example/multischema/auction/Name.java create mode 100644 src/test/java/com/example/multischema/auction/Persistent.java create mode 100644 src/test/java/com/example/multischema/auction/SecondTable.java create mode 100644 src/test/java/com/example/multischema/auction/SecondarySchemaEntity.java create mode 100644 src/test/java/com/example/multischema/auction/User.java create mode 100644 src/test/java/com/example/multischema/auction/Watcher.java create mode 100644 src/test/java/liquibase/ext/hibernate/HibernateMultiSchemaTest.java diff --git a/src/main/java/liquibase/ext/hibernate/database/HibernateDatabase.java b/src/main/java/liquibase/ext/hibernate/database/HibernateDatabase.java index 0f1136b9..fbaaa183 100644 --- a/src/main/java/liquibase/ext/hibernate/database/HibernateDatabase.java +++ b/src/main/java/liquibase/ext/hibernate/database/HibernateDatabase.java @@ -36,13 +36,11 @@ public abstract class HibernateDatabase extends AbstractJdbcDatabase { protected Dialect dialect; private boolean indexesForForeignKeys = false; - public static final String DEFAULT_SCHEMA = "HIBERNATE"; + public static final String DEFAULT_DEFAULT_CATALOG_NAME = "HIBERNATE"; + public static final String DEFAULT_DEFAULT_SCHEMA_NAME = "HIBERNATE"; public static final String HIBERNATE_TEMP_USE_JDBC_METADATA_DEFAULTS = "hibernate.temp.use_jdbc_metadata_defaults"; - public HibernateDatabase() { - setDefaultCatalogName(DEFAULT_SCHEMA); - setDefaultSchemaName(DEFAULT_SCHEMA); - } + public HibernateDatabase() { } public boolean requiresPassword() { return false; @@ -295,23 +293,28 @@ public boolean supportsTablespaces() { } @Override - protected String getConnectionCatalogName() throws DatabaseException { - return getDefaultCatalogName(); + protected String getConnectionCatalogName() { + return DEFAULT_DEFAULT_CATALOG_NAME; } @Override protected String getConnectionSchemaName() { - return getDefaultSchemaName(); + return DEFAULT_DEFAULT_SCHEMA_NAME; } @Override public String getDefaultSchemaName() { - return DEFAULT_SCHEMA; + final String defaultSchemaName = super.getDefaultSchemaName(); + if (defaultSchemaName != null) { + return defaultSchemaName; + } + + return DEFAULT_DEFAULT_SCHEMA_NAME; } @Override public String getDefaultCatalogName() { - return DEFAULT_SCHEMA; + return DEFAULT_DEFAULT_CATALOG_NAME; } @Override @@ -334,6 +337,9 @@ public boolean supportsCatalogs() { return true; } + @Override + public void setDefaultCatalogName(String defaultCatalogName) { } + /** * Used by hibernate to ensure no database access is performed. */ diff --git a/src/main/java/liquibase/ext/hibernate/snapshot/SchemaSnapshotGenerator.java b/src/main/java/liquibase/ext/hibernate/snapshot/SchemaSnapshotGenerator.java index f3838dc4..74ef6349 100644 --- a/src/main/java/liquibase/ext/hibernate/snapshot/SchemaSnapshotGenerator.java +++ b/src/main/java/liquibase/ext/hibernate/snapshot/SchemaSnapshotGenerator.java @@ -1,5 +1,6 @@ package liquibase.ext.hibernate.snapshot; +import liquibase.Scope; import liquibase.exception.DatabaseException; import liquibase.snapshot.DatabaseSnapshot; import liquibase.snapshot.InvalidExampleException; @@ -18,7 +19,12 @@ public SchemaSnapshotGenerator() { @Override protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot snapshot) throws DatabaseException, InvalidExampleException { - return new Schema(snapshot.getDatabase().getDefaultCatalogName(), snapshot.getDatabase().getDefaultSchemaName()).setDefault(true); + Schema schema = new Schema(example.getSchema().getCatalog(), example.getSchema().getName()); + if (snapshot.getDatabase().getDefaultSchemaName() != null && snapshot.getDatabase().getDefaultSchemaName().equalsIgnoreCase(schema.getName())) { + schema.setDefault(true); + } + + return schema; } @Override diff --git a/src/main/java/liquibase/ext/hibernate/snapshot/SequenceSnapshotGenerator.java b/src/main/java/liquibase/ext/hibernate/snapshot/SequenceSnapshotGenerator.java index a19b4adb..e8c4f85a 100644 --- a/src/main/java/liquibase/ext/hibernate/snapshot/SequenceSnapshotGenerator.java +++ b/src/main/java/liquibase/ext/hibernate/snapshot/SequenceSnapshotGenerator.java @@ -34,6 +34,12 @@ protected void addTo(DatabaseObject foundObject, DatabaseSnapshot snapshot) thro Schema schema = (Schema) foundObject; HibernateDatabase database = (HibernateDatabase) snapshot.getDatabase(); for (org.hibernate.boot.model.relational.Namespace namespace : database.getMetadata().getDatabase().getNamespaces()) { + boolean namespaceMatchesSchema = (namespace.getName().getSchema() != null && namespace.getName().getSchema().matches(foundObject.getName())) + || (namespace.getName().getSchema() == null && ((Schema) foundObject).isDefault()); + if (!namespaceMatchesSchema) { + continue; + } + for (org.hibernate.boot.model.relational.Sequence sequence : namespace.getSequences()) { schema.addDatabaseObject(new Sequence() .setName(sequence.getName().getSequenceName().getText()) diff --git a/src/main/java/liquibase/ext/hibernate/snapshot/TableSnapshotGenerator.java b/src/main/java/liquibase/ext/hibernate/snapshot/TableSnapshotGenerator.java index 0aa05b76..326befd2 100644 --- a/src/main/java/liquibase/ext/hibernate/snapshot/TableSnapshotGenerator.java +++ b/src/main/java/liquibase/ext/hibernate/snapshot/TableSnapshotGenerator.java @@ -12,7 +12,10 @@ import liquibase.structure.core.Table; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.generator.Generator; -import org.hibernate.mapping.*; +import org.hibernate.mapping.Join; +import org.hibernate.mapping.PersistentClass; +import org.hibernate.mapping.RootClass; +import org.hibernate.mapping.SimpleValue; import java.util.ArrayList; import java.util.Collection; @@ -38,13 +41,21 @@ protected DatabaseObject snapshotObject(DatabaseObject example, DatabaseSnapshot return example; } - Table table = new Table().setName(hibernateTable.getName()); - Scope.getCurrentScope().getLog(getClass()).info("Found table " + table.getName()); + boolean schemaMatches = (example.getSchema().getName() != null && example.getSchema().getName().equalsIgnoreCase(hibernateTable.getSchema())) + || (example.getSchema().isDefault() && hibernateTable.getSchema() == null); + if (!schemaMatches) { + Scope.getCurrentScope().getLog(getClass()).info("Skipping table " + hibernateTable.getName() + " for schema " + example.getSchema().getName() + ", because it is part of another one."); + return null; + } + + Table table = new Table(); + table.setName(hibernateTable.getName()); table.setSchema(example.getSchema()); if (hibernateTable.getComment() != null && !hibernateTable.getComment().isEmpty()) { table.setRemarks(hibernateTable.getComment()); } + Scope.getCurrentScope().getLog(getClass()).info("Found table " + example.getSchema().getName() + "." + table.getName()); return table; } @@ -115,7 +126,6 @@ protected void addTo(DatabaseObject foundObject, DatabaseSnapshot snapshot) thro private void addDatabaseObjectToSchema(org.hibernate.mapping.Table join, Schema schema, DatabaseSnapshot snapshot) throws DatabaseException, InvalidExampleException { Table joinTable = new Table().setName(join.getName()); joinTable.setSchema(schema); - Scope.getCurrentScope().getLog(getClass()).info("Found table " + joinTable.getName()); schema.addDatabaseObject(snapshotObject(joinTable, snapshot)); } } diff --git a/src/test/java/com/example/multischema/auction/AuctionInfo.java b/src/test/java/com/example/multischema/auction/AuctionInfo.java new file mode 100644 index 00000000..4af49da0 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/AuctionInfo.java @@ -0,0 +1,60 @@ +package com.example.multischema.auction; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +import java.util.Date; + +@Entity +@Table(schema = "PUBLIC") +public class AuctionInfo { + private String id; + private String description; + private Date ends; + private Float maxAmount; + + @Column(length = 1000) + public String getDescription() { + return description; + } + + public Date getEnds() { + return ends; + } + + @Id + public String getId() { + return id; + } + + + public Float getMaxAmount() { + return maxAmount; + } + + public void setId(String id) { + this.id = id; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setEnds(Date ends) { + this.ends = ends; + } + + public void setMaxAmount(Float maxAmount) { + this.maxAmount = maxAmount; + } + + public AuctionInfo(String id, String description, Date ends, Float maxAmount) { + this.id = id; + this.description = description; + this.ends = ends; + this.maxAmount = maxAmount; + } + +} diff --git a/src/test/java/com/example/multischema/auction/AuctionItem.java b/src/test/java/com/example/multischema/auction/AuctionItem.java new file mode 100644 index 00000000..c682b9f4 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/AuctionItem.java @@ -0,0 +1,86 @@ +package com.example.multischema.auction; + +import jakarta.persistence.*; + +import java.util.Date; +import java.util.List; + +@Entity +@Table(schema = "PUBLIC") +public class AuctionItem extends Persistent { + private String description; + private String shortDescription; + private List bids; + private Bid successfulBid; + private User seller; + private Date ends; + private int condition; + + @OneToMany(mappedBy = "item", cascade = CascadeType.ALL) + public List getBids() { + return bids; + } + + @Column(length = 1000) + public String getDescription() { + return description; + } + + @ManyToOne + public User getSeller() { + return seller; + } + + @ManyToOne + public Bid getSuccessfulBid() { + return successfulBid; + } + + public void setBids(List bids) { + this.bids = bids; + } + + public void setDescription(String string) { + description = string; + } + + public void setSeller(User user) { + seller = user; + } + + public void setSuccessfulBid(Bid bid) { + successfulBid = bid; + } + + public Date getEnds() { + return ends; + } + + public void setEnds(Date date) { + ends = date; + } + + public int getCondition() { + return condition; + } + + public void setCondition(int i) { + condition = i; + } + + public String toString() { + return shortDescription + " (" + description + ": " + condition + + "/10)"; + } + + @Column(length = 200) + public String getShortDescription() { + return shortDescription; + } + + public void setShortDescription(String shortDescription) { + this.shortDescription = shortDescription; + } + + +} diff --git a/src/test/java/com/example/multischema/auction/AuditedItem.java b/src/test/java/com/example/multischema/auction/AuditedItem.java new file mode 100755 index 00000000..94a4bff9 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/AuditedItem.java @@ -0,0 +1,34 @@ +package com.example.multischema.auction; + +import jakarta.persistence.*; +import org.hibernate.envers.Audited; + +@Audited +@Entity +@Table(schema = "PUBLIC") +public class AuditedItem { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "AUDITED_ITEM_SEQ") + @SequenceGenerator(name = "AUDITED_ITEM_SEQ", sequenceName = "AUDITED_ITEM_SEQ") + private long id; + @Column(unique = true) + private String name; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/src/test/java/com/example/multischema/auction/Bid.java b/src/test/java/com/example/multischema/auction/Bid.java new file mode 100644 index 00000000..97f6bf87 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/Bid.java @@ -0,0 +1,64 @@ +package com.example.multischema.auction; + +import jakarta.persistence.*; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +import java.util.Date; + +@Entity +@Table(schema = "PUBLIC") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorValue("Y") +@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) +public class Bid extends Persistent { + private AuctionItem item; + private float amount; + private Date datetime; + private User bidder; + + @ManyToOne + public AuctionItem getItem() { + return item; + } + + public void setItem(AuctionItem item) { + this.item = item; + } + + public float getAmount() { + return amount; + } + + @Column(nullable = false, name = "datetime") + public Date getDatetime() { + return datetime; + } + + public void setAmount(float f) { + amount = f; + } + + public void setDatetime(Date date) { + datetime = date; + } + + @ManyToOne(optional = false) + public User getBidder() { + return bidder; + } + + public void setBidder(User user) { + bidder = user; + } + + public String toString() { + return bidder.getUserName() + " $" + amount; + } + + @Transient + public boolean isBuyNow() { + return false; + } + +} diff --git a/src/test/java/com/example/multischema/auction/BuyNow.java b/src/test/java/com/example/multischema/auction/BuyNow.java new file mode 100644 index 00000000..b31c4b11 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/BuyNow.java @@ -0,0 +1,19 @@ +package com.example.multischema.auction; + +import jakarta.persistence.Entity; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; + +@Entity +@Table(schema = "PUBLIC") +public class BuyNow extends Bid { + + @Transient + public boolean isBuyNow() { + return true; + } + + public String toString() { + return super.toString() + " (buy now)"; + } +} diff --git a/src/test/java/com/example/multischema/auction/FirstTable.java b/src/test/java/com/example/multischema/auction/FirstTable.java new file mode 100644 index 00000000..f3288c2f --- /dev/null +++ b/src/test/java/com/example/multischema/auction/FirstTable.java @@ -0,0 +1,41 @@ +package com.example.multischema.auction; + +import jakarta.persistence.*; + +@Entity +@Table(schema = "PUBLIC") +@SecondaryTable(name = "second_table", pkJoinColumns = @PrimaryKeyJoinColumn(name = "first_table_id")) +public class FirstTable { + @Id + private Long id; + + @Column(name = "name") + private String name; + + @Embedded + private SecondTable secondTable; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public SecondTable getSecondTable() { + return secondTable; + } + + public void setSecondTable(SecondTable secondTable) { + this.secondTable = secondTable; + } +} diff --git a/src/test/java/com/example/multischema/auction/Item.java b/src/test/java/com/example/multischema/auction/Item.java new file mode 100644 index 00000000..9e4bf366 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/Item.java @@ -0,0 +1,32 @@ +package com.example.multischema.auction; + +import jakarta.persistence.*; + +@Entity +@Table(schema = "PUBLIC") +public class Item { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ITEM_SEQ") + @SequenceGenerator(name = "ITEM_SEQ", sequenceName = "ITEM_SEQ", initialValue = 1000, allocationSize = 100) + private long id; + @Column(unique = true) + private String name; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/src/test/java/com/example/multischema/auction/Name.java b/src/test/java/com/example/multischema/auction/Name.java new file mode 100644 index 00000000..d65efc7b --- /dev/null +++ b/src/test/java/com/example/multischema/auction/Name.java @@ -0,0 +1,48 @@ +package com.example.multischema.auction; + +import jakarta.persistence.Embeddable; + +@Embeddable +public class Name { + private String firstName; + private String lastName; + private Character initial; + + public Name(String first, Character middle, String last) { + firstName = first; + initial = middle; + lastName = last; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public Character getInitial() { + return initial; + } + + public void setInitial(Character initial) { + this.initial = initial; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String toString() { + StringBuffer buf = new StringBuffer().append(firstName).append(' '); + if (initial != null) + buf.append(initial).append(' '); + return buf.append(lastName).toString(); + } + +} diff --git a/src/test/java/com/example/multischema/auction/Persistent.java b/src/test/java/com/example/multischema/auction/Persistent.java new file mode 100644 index 00000000..5a73eff5 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/Persistent.java @@ -0,0 +1,21 @@ +package com.example.multischema.auction; + +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; + +@MappedSuperclass +public class Persistent { + private Long id; + + @Id + @GeneratedValue + public Long getId() { + return id; + } + + public void setId(Long long1) { + id = long1; + } + +} diff --git a/src/test/java/com/example/multischema/auction/SecondTable.java b/src/test/java/com/example/multischema/auction/SecondTable.java new file mode 100644 index 00000000..425302ca --- /dev/null +++ b/src/test/java/com/example/multischema/auction/SecondTable.java @@ -0,0 +1,19 @@ +package com.example.multischema.auction; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; + +@Embeddable +public class SecondTable { + + @Column(table = "second_table") + private String secondName; + + public String getSecondName() { + return secondName; + } + + public void setSecondName(String secondName) { + this.secondName = secondName; + } +} diff --git a/src/test/java/com/example/multischema/auction/SecondarySchemaEntity.java b/src/test/java/com/example/multischema/auction/SecondarySchemaEntity.java new file mode 100644 index 00000000..e80e94e9 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/SecondarySchemaEntity.java @@ -0,0 +1,43 @@ +package com.example.multischema.auction; + +import jakarta.persistence.*; + +@Entity +@Table(schema = "SECOND") +@SequenceGenerator(name = "secondary_schema_entity_seq", schema = "SECOND") +public class SecondarySchemaEntity { + + private Long id; + + private String email; + + private Name name; + + + @Id + @GeneratedValue(generator = "secondary_schema_entity_seq") + public Long getId() { + return id; + } + + public void setId(Long long1) { + id = long1; + } + + public String getEmail() { + return email; + } + + public void setEmail(String string) { + email = string; + } + + public Name getName() { + return name; + } + + public void setName(Name name) { + this.name = name; + } + +} diff --git a/src/test/java/com/example/multischema/auction/User.java b/src/test/java/com/example/multischema/auction/User.java new file mode 100644 index 00000000..e2da1328 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/User.java @@ -0,0 +1,74 @@ +package com.example.multischema.auction; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; + +import java.util.List; + +@Entity +@Table(schema = "PUBLIC") +public class User extends Persistent { + private String userName; + private String password; + private String email; + private Name name; + private List bids; + private List auctions; + + public String getEmail() { + return email; + } + + public String getPassword() { + return password; + } + + public String getUserName() { + return userName; + } + + public void setEmail(String string) { + email = string; + } + + public void setPassword(String string) { + password = string; + } + + public void setUserName(String string) { + userName = string; + } + + @OneToMany(mappedBy = "seller", cascade = CascadeType.ALL) + public List getAuctions() { + return auctions; + } + + @OneToMany(mappedBy = "bidder", cascade = CascadeType.ALL) + public List getBids() { + return bids; + } + + public void setAuctions(List list) { + auctions = list; + } + + public void setBids(List list) { + bids = list; + } + + public String toString() { + return userName; + } + + public Name getName() { + return name; + } + + public void setName(Name name) { + this.name = name; + } + +} diff --git a/src/test/java/com/example/multischema/auction/Watcher.java b/src/test/java/com/example/multischema/auction/Watcher.java new file mode 100644 index 00000000..04e738a2 --- /dev/null +++ b/src/test/java/com/example/multischema/auction/Watcher.java @@ -0,0 +1,19 @@ +package com.example.multischema.auction; + +import jakarta.persistence.*; + +@Entity +@Table // schema "PUBLIC" via default +public class Watcher { + + @Id + @GeneratedValue(strategy = GenerationType.TABLE, generator = "WATCHER_SEQ") + @TableGenerator(name = "WATCHER_SEQ", table = "WatcherSeqTable") + private Integer id; + + @SuppressWarnings("unused") + private String name; + + @ManyToOne + private AuctionItem auctionItem; +} \ No newline at end of file diff --git a/src/test/java/liquibase/ext/hibernate/HibernateMultiSchemaTest.java b/src/test/java/liquibase/ext/hibernate/HibernateMultiSchemaTest.java new file mode 100644 index 00000000..953ff041 --- /dev/null +++ b/src/test/java/liquibase/ext/hibernate/HibernateMultiSchemaTest.java @@ -0,0 +1,64 @@ +package liquibase.ext.hibernate; + +import liquibase.database.Database; +import liquibase.database.core.H2Database; +import liquibase.database.jvm.JdbcConnection; +import liquibase.integration.commandline.LiquibaseCommandLine; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; + +public class HibernateMultiSchemaTest { + + private Database database; + private Connection connection; + + @Before + public void setUp() throws Exception { + Class.forName("org.h2.Driver"); + connection = DriverManager.getConnection("jdbc:h2:mem:TESTDB" + System.currentTimeMillis(), "SA", ""); + database = new H2Database(); + database.setConnection(new JdbcConnection(connection)); + } + + @After + public void tearDown() throws Exception { + database.close(); + connection = null; + database = null; + } + + @Test + public void runCommandLineDiffChangelog() throws Exception { + final File changelogFile = File.createTempFile("diffChangeLog-test", ".yaml"); + + //we don't ship jansi, so we know we can disable it without having to do the slow class checking + System.setProperty("org.fusesource.jansi.Ansi.disable", "true"); + final LiquibaseCommandLine cli = new LiquibaseCommandLine(); + + int returnCode = cli.execute(new String[] { + "--changelogFile=" + changelogFile.getAbsolutePath(), + "--referenceUrl=hibernate:spring:com.example.multischema.auction?dialect=org.hibernate.dialect.H2Dialect", + "--referenceDriver=liquibase.ext.hibernate.database.connection.HibernateDriver", + "--referenceDefaultSchemaName=PUBLIC", + "--url=jdbc:h2:mem:TESTDB" + System.currentTimeMillis(), + "--driver=org.h2.Driver", + "--username=SA", + "--password=", + "--includeSchema=true", + "--schemas=PUBLIC,SECOND", + "--log-level=INFO", + "diffChangelog", + "--author=test", + }); + + if (returnCode != 0) { + throw new RuntimeException("LiquibaseCommandLine failed: " + returnCode); + } + } + +}