Skip to content

Commit

Permalink
Improve snapshot extensibility for NoSQL databases (#5619)
Browse files Browse the repository at this point in the history
* Introduce generic supports and deprecate other support methods

* Bypass generators when database does not support the capability

* Do not include unsupported types of snapshot objects

* Rewrite chain snapshot to actually invoke the whole chain

* Throw if snapshot object has been re-instantiated

That way, snapshot generators are strongly advised to add to
existing snapshot instances, instead of creating new ones.

For built-in generators that do not comply to this, the only
option is to replace them, as suggested by the error message.

* Fix HSQL schema support

* Delegate to super for MySQL

* Rewrite test with more accurate assertions

The only difference with before is that Schema gets filtered out
since MySQL does not support it.

* Add coverage for snapshot generator chain

* Allow null database

* Reinstate null check

* Add missing super calls for supports

* fix: firebird workaround + sonar

* fix: this validation breaks function snapshot capabilities

* Revert "fix: this validation breaks function snapshot capabilities"

This reverts commit 317c141.

---------

Co-authored-by: filipe <flautert@liquibase.org>
Co-authored-by: rberezen <ruslan.berezenskyi@gmail.com>
  • Loading branch information
3 people authored Apr 4, 2024
1 parent 58e9c3d commit 2b1c363
Show file tree
Hide file tree
Showing 58 changed files with 705 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,11 @@ protected void wipeDatabase() {
String altSchema = testSystem.getAltSchema();
String altCatalog = testSystem.getAltCatalog();

if (database.supportsSchemas()) {
if (database.supports(Schema.class)) {
emptyTestSchema(null, altSchema, database);
}
if (supportsAltCatalogTests()) {
if (database.supportsSchemas() && database.supportsCatalogs()) {
if (database.supports(Schema.class) && database.supports(Catalog.class)) {
emptyTestSchema(altCatalog, altSchema, database);
}
}
Expand Down Expand Up @@ -264,7 +264,7 @@ protected void emptyTestSchema(String catalogName, String schemaName, Database d
}

protected boolean supportsAltCatalogTests() {
return database.supportsCatalogs();
return database.supports(Catalog.class);
}

protected Properties createProperties() {
Expand Down Expand Up @@ -756,7 +756,7 @@ public void testRerunDiffChangeLogAltSchema() throws Exception {
if (database.getShortName().equalsIgnoreCase("mssql")) {
return; // not possible on MSSQL.
}
if (!database.supportsSchemas()) {
if (!database.supports(Schema.class)) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import liquibase.sql.Sql;
import liquibase.sqlgenerator.SqlGeneratorFactory;
import liquibase.statement.SqlStatement;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Table;
import liquibase.test.TestContext;
import org.junit.After;
Expand Down Expand Up @@ -231,7 +232,7 @@ public void resetAvailableDatabases() throws Exception {
}
connection.commit();

if (database.supportsSchemas()) {
if (database.supports(Schema.class)) {
try {
database.dropDatabaseObjects(new CatalogAndSchema(null, testSystem.getAltSchema()));
} catch (DatabaseException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import liquibase.CatalogAndSchema;
import liquibase.database.jvm.JdbcConnection;
import liquibase.structure.core.Catalog;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Sequence;
import org.junit.Before;
import org.junit.Test;

Expand Down Expand Up @@ -72,11 +75,13 @@ public void testGetDefaultDriver() {
@Test
public void testSupportsSchemas() {
assertTrue(database.supportsSchemas());
assertTrue(database.supports(Schema.class));
}

@Test
public void testSupportsCatalogs() {
assertTrue(database.supportsCatalogs());
assertTrue(database.supports(Catalog.class));
}

@Test
Expand All @@ -87,6 +92,7 @@ public void testSupportsCatalogInObjectName() {
@Test
public void testSupportsSequences() {
assertTrue(database.supportsSequences());
assertTrue(database.supports(Sequence.class));
}

@Test
Expand Down
12 changes: 6 additions & 6 deletions liquibase-standard/src/main/java/liquibase/CatalogAndSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public enum CatalogAndSchemaCase {
}

public boolean equals(CatalogAndSchema catalogAndSchema, Database accordingTo) {
if (!accordingTo.supportsCatalogs()) {
if (!accordingTo.supports(Catalog.class)) {
return true;
}

Expand All @@ -47,7 +47,7 @@ public boolean equals(CatalogAndSchema catalogAndSchema, Database accordingTo) {
return false;
}

if (accordingTo.supportsSchemas()) {
if (accordingTo.supports(Schema.class)) {
if (workCatalogAndSchema.getSchemaName() == null) {
return thisCatalogAndSchema.getSchemaName() == null;
} else {
Expand All @@ -73,11 +73,11 @@ public CatalogAndSchema standardize(Database accordingTo) {
String workCatalogName = StringUtil.trimToNull(getCatalogName());
String workSchemaName = StringUtil.trimToNull(getSchemaName());

if (!accordingTo.supportsCatalogs()) {
if (!accordingTo.supports(Catalog.class)) {
return new CatalogAndSchema(null, null);
}

if (accordingTo.supportsSchemas()) {
if (accordingTo.supports(Schema.class)) {
if ((workSchemaName != null) && workSchemaName.equalsIgnoreCase(accordingTo.getDefaultSchemaName())) {
workSchemaName = null;
}
Expand All @@ -94,7 +94,7 @@ public CatalogAndSchema standardize(Database accordingTo) {
if (workSchemaName != null && equals(accordingTo, workSchemaName, accordingTo.getDefaultSchemaName())) {
workSchemaName = null;
}
if (!accordingTo.supportsSchemas() && (workCatalogName != null) && (workSchemaName != null) &&
if (!accordingTo.supports(Schema.class) && (workCatalogName != null) && (workSchemaName != null) &&
!workCatalogName.equals(workSchemaName)) {
workSchemaName = null;
}
Expand Down Expand Up @@ -137,7 +137,7 @@ public CatalogAndSchema customize(Database accordingTo) {
String workSchemaName = standard.getSchemaName();

if (workCatalogName == null) {
if (!accordingTo.supportsSchemas() && (workSchemaName != null)) {
if (!accordingTo.supports(Schema.class) && (workSchemaName != null)) {
return new CatalogAndSchema(accordingTo.correctObjectName(workSchemaName, Catalog.class), null);
}
workCatalogName = accordingTo.getDefaultCatalogName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import liquibase.database.DatabaseList;
import liquibase.exception.DatabaseException;
import liquibase.exception.UnknownChangeLogParameterException;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Sequence;
import liquibase.util.StringUtil;
import lombok.Getter;

Expand Down Expand Up @@ -88,8 +90,8 @@ public ChangeLogParameters(Database database) {
this.set("database.supportsForeignKeyDisable", database.supportsForeignKeyDisable());
this.set("database.supportsInitiallyDeferrableColumns", database.supportsInitiallyDeferrableColumns());
this.set("database.supportsRestrictForeignKeys", database.supportsRestrictForeignKeys());
this.set("database.supportsSchemas", database.supportsSchemas());
this.set("database.supportsSequences", database.supportsSequences());
this.set("database.supportsSchemas", database.supports(Schema.class));
this.set("database.supportsSequences", database.supports(Sequence.class));
this.set("database.supportsTablespaces", database.supportsTablespaces());
this.set("database.supportsNotNullConstraintNames", database.supportsNotNullConstraintNames());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import liquibase.snapshot.*;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.DatabaseObjectFactory;
import liquibase.structure.core.Schema;
import liquibase.util.StringUtil;

import java.io.PrintStream;
Expand Down Expand Up @@ -134,7 +135,7 @@ protected DatabaseSnapshot getTargetSnapshot(CommandResultsBuilder resultsBuilde
int i = 0;
for (CompareControl.SchemaComparison comparison : compareControl.getSchemaComparisons()) {
CatalogAndSchema schema;
if (targetDatabase.supportsSchemas()) {
if (targetDatabase.supports(Schema.class)) {
schema = new CatalogAndSchema(targetDatabase.getDefaultCatalogName(), comparison.getComparisonSchema().getSchemaName());
} else {
schema = new CatalogAndSchema(comparison.getComparisonSchema().getSchemaName(), comparison.getComparisonSchema().getSchemaName());
Expand Down Expand Up @@ -175,7 +176,7 @@ protected DatabaseSnapshot createReferenceSnapshot(CommandResultsBuilder results
int i = 0;
for (CompareControl.SchemaComparison comparison : compareControl.getSchemaComparisons()) {
CatalogAndSchema schema;
if (referenceDatabase.supportsSchemas()) {
if (referenceDatabase.supports(Schema.class)) {
schema = new CatalogAndSchema(referenceDatabase.getDefaultCatalogName(), comparison.getReferenceSchema().getSchemaName());
} else {
schema = new CatalogAndSchema(comparison.getReferenceSchema().getSchemaName(), comparison.getReferenceSchema().getSchemaName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import liquibase.exception.DatabaseException;
import liquibase.integration.commandline.LiquibaseCommandLineConfiguration;
import liquibase.resource.ResourceAccessor;
import liquibase.structure.core.Schema;
import liquibase.util.StringUtil;

import java.util.ResourceBundle;
Expand Down Expand Up @@ -73,7 +74,7 @@ protected Database createDatabaseObject(String url,
database = DatabaseFactory.getInstance().openDatabase(url, username, password, driver,
databaseClassName, driverPropertiesFile, propertyProviderClass, resourceAccessor);

if (!database.supportsSchemas()) {
if (!database.supports(Schema.class)) {
if ((defaultSchemaName != null) && (defaultCatalogName == null)) {
defaultCatalogName = defaultSchemaName;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ public int getDatabaseMinorVersion() throws DatabaseException {
@Override
public String getDefaultCatalogName() {
if (defaultCatalogName == null) {
if ((defaultSchemaName != null) && !this.supportsSchemas()) {
if ((defaultSchemaName != null) && !this.supports(Schema.class)) {
return defaultSchemaName;
}

Expand Down Expand Up @@ -303,7 +303,7 @@ public CatalogAndSchema getDefaultSchema() {

@Override
public String getDefaultSchemaName() {
if (!supportsSchemas()) {
if (!supports(Schema.class)) {
return getDefaultCatalogName();
}

Expand All @@ -326,7 +326,7 @@ public Integer getDefaultScaleForNativeDataType(String nativeDataType) {
@Override
public void setDefaultSchemaName(final String schemaName) {
this.defaultSchemaName = correctObjectName(schemaName, Schema.class);
if (!supportsSchemas()) {
if (!supports(Schema.class)) {
defaultCatalogSet = schemaName != null;
}
}
Expand Down Expand Up @@ -841,7 +841,7 @@ public String escapeTableName(final String catalogName, final String schemaName,
@Override
public String escapeObjectName(String catalogName, String schemaName, final String objectName,
final Class<? extends DatabaseObject> objectType) {
if (supportsSchemas()) {
if (supports(Schema.class)) {
catalogName = StringUtil.trimToNull(catalogName);
schemaName = StringUtil.trimToNull(schemaName);

Expand Down Expand Up @@ -873,7 +873,7 @@ public String escapeObjectName(String catalogName, String schemaName, final Stri
return escapeObjectName(catalogName, Catalog.class) + "." + escapeObjectName(schemaName, Schema.class) + "." + escapeObjectName(objectName, objectType);
}
}
} else if (supportsCatalogs()) {
} else if (supports(Catalog.class)) {
catalogName = StringUtil.trimToNull(catalogName);
schemaName = StringUtil.trimToNull(schemaName);

Expand Down Expand Up @@ -1415,7 +1415,7 @@ public void setCurrentDateTimeFunction(final String function) {

@Override
public boolean isDefaultSchema(final String catalog, final String schema) {
if (!supportsSchemas()) {
if (!supports(Schema.class)) {
return true;
}

Expand All @@ -1427,7 +1427,7 @@ public boolean isDefaultSchema(final String catalog, final String schema) {

@Override
public boolean isDefaultCatalog(final String catalog) {
if (!supportsCatalogs()) {
if (!supports(Catalog.class)) {
return true;
}

Expand Down
20 changes: 20 additions & 0 deletions liquibase-standard/src/main/java/liquibase/database/Database.java
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ default String getDisplayName() {
*/
boolean supportsInitiallyDeferrableColumns();

/**
* Whether this database supports sequences
* @deprecated please call {@link Database#supports(Class)} with the {@link liquibase.structure.core.Sequence} type instead
*/
@Deprecated
boolean supportsSequences();

boolean supportsDropTableCascadeConstraints();
Expand Down Expand Up @@ -380,10 +385,25 @@ default void addCompleteSqlToScope(String completeSql) {

boolean supportsTablespaces();

/**
* Whether this database supports catalogs
* @deprecated please call {@link Database#supports(Class)} with the {@link liquibase.structure.core.Catalog} type instead
*/
@Deprecated
boolean supportsCatalogs();

default boolean supports(Class<? extends DatabaseObject> object) {
return true;
}


CatalogAndSchema.CatalogAndSchemaCase getSchemaAndCatalogCase();

/**
* Whether this database supports schemas
* @deprecated please call {@link Database#supports(Class)} with the {@link liquibase.structure.core.Schema} type instead
*/
@Deprecated
boolean supportsSchemas();

boolean supportsCatalogInObjectName(Class<? extends DatabaseObject> type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ public Integer getDefaultPort() {
return 446;
}

@Override
public boolean supports(Class<? extends DatabaseObject> object) {
if (Schema.class.isAssignableFrom(object)) {
return false;
}
return true;
}

@Override
public boolean supportsSchemas() {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import liquibase.executor.ExecutorService;
import liquibase.statement.core.RawSqlStatement;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Sequence;

import java.sql.Driver;
import java.sql.DriverManager;
Expand Down Expand Up @@ -73,6 +75,18 @@ public int getPriority() {
return PRIORITY_DEFAULT;
}


@Override
public boolean supports(Class<? extends DatabaseObject> object) {
if (Schema.class.isAssignableFrom(object)) {
return false;
}
if (Sequence.class.isAssignableFrom(object)) {
return ((driverVersionMajor == 10) && (driverVersionMinor >= 6)) || (driverVersionMajor >= 11);
}
return super.supports(object);
}

@Override
public boolean supportsSchemas() {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import liquibase.database.DatabaseConnection;
import liquibase.exception.DatabaseException;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Catalog;
import liquibase.structure.core.Schema;
import liquibase.structure.core.Table;

import java.util.Locale;
Expand Down Expand Up @@ -86,6 +88,17 @@ public boolean supportsAutoIncrement() {
return false;
}

@Override
public boolean supports(Class<? extends DatabaseObject> object) {
if (Schema.class.isAssignableFrom(object)) {
return false;
}
if (Catalog.class.isAssignableFrom(object)) {
return false;
}
return super.supports(object);
}

@Override
public boolean supportsSchemas() {
return false;
Expand Down
Loading

0 comments on commit 2b1c363

Please sign in to comment.