From 2406f7ec5092896113906d281ece7eb0d2c47db0 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 21 Nov 2024 16:30:45 +0100 Subject: [PATCH] [jOOQ/jOOQ#9506] [jOOQ/jOOQ#17646] Diff should ignore constraint changes where (synthetically) named constraint is replaced by an equivalent unnamed constraint. Users may use unnamed constraints in migration scripts. When comparing the schema with the existing schema in the database, we must ignore the database's synthetic constraint names. --- .../maven/AbstractMigrationsMojo.java | 10 +++- .../src/main/java/org/jooq/conf/Settings.java | 46 +++++++++++++++++++ jOOQ/src/main/java/org/jooq/impl/Diff.java | 14 ++++-- .../java/org/jooq/impl/MigrationImpl.java | 3 +- .../org/jooq/xsd/jooq-runtime-3.20.0.xsd | 4 ++ 5 files changed, 70 insertions(+), 7 deletions(-) diff --git a/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AbstractMigrationsMojo.java b/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AbstractMigrationsMojo.java index 0257944ad7..6b946e5c92 100644 --- a/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AbstractMigrationsMojo.java +++ b/jOOQ-migrations-maven/src/main/java/org/jooq/migrations/maven/AbstractMigrationsMojo.java @@ -214,8 +214,14 @@ abstract class AbstractMigrationsMojo extends AbstractMojo { ); - ctx.settings().setMigrationSchemataCreateSchemaIfNotExists(schemataCreateSchemaIfNotExists); - ctx.settings().setMigrationHistorySchemaCreateSchemaIfNotExists(historySchemaCreateSchemaIfNotExists); + ctx.settings() + .withMigrationSchemataCreateSchemaIfNotExists(schemataCreateSchemaIfNotExists) + .withMigrationHistorySchemaCreateSchemaIfNotExists(historySchemaCreateSchemaIfNotExists) + + // [#9506] [#17646] Users may use unnamed constraints in migration scripts. + // When comparing the schema with the existing schema in the database, + // we must ignore the database's synthetic constraint names. + .withMigrationIgnoreUnnamedConstraintDiffs(true); // Initialise connection // --------------------------------------------------------------------- diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index 7ff4a73bbe..e53a77b7d4 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -491,6 +491,8 @@ public class Settings protected Boolean migrationAutoVerification = true; @XmlElement(defaultValue = "true") protected Boolean migrationIgnoreDefaultTimestampPrecisionDiffs = true; + @XmlElement(defaultValue = "false") + protected Boolean migrationIgnoreUnnamedConstraintDiffs = false; @XmlElement(type = String.class) @XmlJavaTypeAdapter(LocaleAdapter.class) protected Locale locale; @@ -6312,6 +6314,30 @@ public class Settings this.migrationIgnoreDefaultTimestampPrecisionDiffs = value; } + /** + * Various migrateTo() methods (e.g. {@link org.jooq.Meta#migrateTo(org.jooq.Meta)}) ignore the difference between (possibly synthetically) name constraints and unnamed constraints, if the structure of the constraint is the same. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isMigrationIgnoreUnnamedConstraintDiffs() { + return migrationIgnoreUnnamedConstraintDiffs; + } + + /** + * Various migrateTo() methods (e.g. {@link org.jooq.Meta#migrateTo(org.jooq.Meta)}) ignore the difference between (possibly synthetically) name constraints and unnamed constraints, if the structure of the constraint is the same. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setMigrationIgnoreUnnamedConstraintDiffs(Boolean value) { + this.migrationIgnoreUnnamedConstraintDiffs = value; + } + /** * The Locale to be used with any locale dependent logic if there is not a more specific locale available. More specific locales include e.g. {@link #getRenderLocale()}, {@link #getParseLocale()}, or {@link #getInterpreterLocale()}. * @@ -9376,6 +9402,15 @@ public class Settings return this; } + /** + * Various migrateTo() methods (e.g. {@link org.jooq.Meta#migrateTo(org.jooq.Meta)}) ignore the difference between (possibly synthetically) name constraints and unnamed constraints, if the structure of the constraint is the same. + * + */ + public Settings withMigrationIgnoreUnnamedConstraintDiffs(Boolean value) { + setMigrationIgnoreUnnamedConstraintDiffs(value); + return this; + } + /** * The Locale to be used with any locale dependent logic if there is not a more specific locale available. More specific locales include e.g. {@link #getRenderLocale()}, {@link #getParseLocale()}, or {@link #getInterpreterLocale()}. * @@ -9891,6 +9926,7 @@ public class Settings builder.append("migrationAutoBaseline", migrationAutoBaseline); builder.append("migrationAutoVerification", migrationAutoVerification); builder.append("migrationIgnoreDefaultTimestampPrecisionDiffs", migrationIgnoreDefaultTimestampPrecisionDiffs); + builder.append("migrationIgnoreUnnamedConstraintDiffs", migrationIgnoreUnnamedConstraintDiffs); builder.append("locale", locale); builder.append("parseDialect", parseDialect); builder.append("parseLocale", parseLocale); @@ -11776,6 +11812,15 @@ public class Settings return false; } } + if (migrationIgnoreUnnamedConstraintDiffs == null) { + if (other.migrationIgnoreUnnamedConstraintDiffs!= null) { + return false; + } + } else { + if (!migrationIgnoreUnnamedConstraintDiffs.equals(other.migrationIgnoreUnnamedConstraintDiffs)) { + return false; + } + } if (locale == null) { if (other.locale!= null) { return false; @@ -12239,6 +12284,7 @@ public class Settings result = ((prime*result)+((migrationAutoBaseline == null)? 0 :migrationAutoBaseline.hashCode())); result = ((prime*result)+((migrationAutoVerification == null)? 0 :migrationAutoVerification.hashCode())); result = ((prime*result)+((migrationIgnoreDefaultTimestampPrecisionDiffs == null)? 0 :migrationIgnoreDefaultTimestampPrecisionDiffs.hashCode())); + result = ((prime*result)+((migrationIgnoreUnnamedConstraintDiffs == null)? 0 :migrationIgnoreUnnamedConstraintDiffs.hashCode())); result = ((prime*result)+((locale == null)? 0 :locale.hashCode())); result = ((prime*result)+((parseDialect == null)? 0 :parseDialect.hashCode())); result = ((prime*result)+((parseLocale == null)? 0 :parseLocale.hashCode())); diff --git a/jOOQ/src/main/java/org/jooq/impl/Diff.java b/jOOQ/src/main/java/org/jooq/impl/Diff.java index 2087d01e08..e444cf9b97 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Diff.java +++ b/jOOQ/src/main/java/org/jooq/impl/Diff.java @@ -38,6 +38,7 @@ package org.jooq.impl; import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; import static java.util.Arrays.asList; // ... import static org.jooq.SQLDialect.IGNITE; @@ -533,15 +534,20 @@ final class Diff { return (r, k1, k2) -> { Name n1 = k1.getUnqualifiedName(); Name n2 = k2.getUnqualifiedName(); + boolean allowRenames = true; if (n1.empty() ^ n2.empty()) { - drop.drop(r, k1); - create.create(r, k2); + if (n1.empty() || !TRUE.equals(ctx.settings().isMigrationIgnoreUnnamedConstraintDiffs())) { + drop.drop(r, k1); + create.create(r, k2); - return; + return; + } + else + allowRenames = false; } - if (NAMED_COMP.compare(k1, k2) != 0) + if (allowRenames && NAMED_COMP.compare(k1, k2) != 0) // [#10813] Don't rename constraints in MySQL if (type != PRIMARY_KEY || !NO_SUPPORT_PK_NAMES.contains(ctx.dialect())) diff --git a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java index b5ac99d7d7..bec7db1de9 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MigrationImpl.java @@ -55,6 +55,7 @@ import static org.jooq.impl.HistoryStatus.STARTING; import static org.jooq.impl.HistoryStatus.SUCCESS; import static org.jooq.impl.SchemaImpl.DEFAULT_SCHEMA; import static org.jooq.impl.Tools.map; +import static org.jooq.tools.StringUtils.isEmpty; import java.io.PrintWriter; import java.io.StringWriter; @@ -181,7 +182,7 @@ final class MigrationImpl extends AbstractScope implements Migration { throw new DataMigrationVerificationException("Commit is not available from CommitProvider: " + commit.id()); for (Schema schema : history.lookup(commit.meta().getSchemas())) - if (!ctx.migratedSchemas().contains(schema)) + if (!isEmpty(schema.getName()) && !ctx.migratedSchemas().contains(schema)) throw new DataMigrationVerificationException( """ Schema is referenced from commit, but not configured for migration: {schema}. diff --git a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.20.0.xsd b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.20.0.xsd index 909fb7af3d..9b37e42e80 100644 --- a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.20.0.xsd +++ b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.20.0.xsd @@ -1563,6 +1563,10 @@ deployed on an RDBMS that does not.]]> migrateTo() methods (e.g. {@link org.jooq.Meta#migrateTo(org.jooq.Meta)}) ignore the difference between TIMESTAMP and TIMESTAMP(6), if 6 is the default precision for timestamps on the configured dialect.]]> + + + migrateTo() methods (e.g. {@link org.jooq.Meta#migrateTo(org.jooq.Meta)}) ignore the difference between (possibly synthetically) name constraints and unnamed constraints, if the structure of the constraint is the same.]]> +