From 2eafa492547efdbab2ef190a546db8ae8f07f8fd Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Thu, 30 Jan 2020 16:57:50 +0100 Subject: [PATCH] [jOOQ/jOOQ#9508] Add Settings.interpreterDelayForeignKeyDeclarations --- .../src/main/java/org/jooq/conf/Settings.java | 42 +++++++++++++++++++ .../main/java/org/jooq/impl/Interpreter.java | 42 +++++++++++++++++++ .../resources/xsd/jooq-runtime-3.13.0.xsd | 4 ++ 3 files changed, 88 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index 9cd213eea4..8cd506d720 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -207,6 +207,8 @@ public class Settings @XmlJavaTypeAdapter(LocaleAdapter.class) protected Locale interpreterLocale; @XmlElement(defaultValue = "false") + protected Boolean interpreterDelayForeignKeyDeclarations = false; + @XmlElement(defaultValue = "false") protected Boolean migrationAllowsUndo = false; @XmlElement(defaultValue = "false") protected Boolean migrationRevertUntracked = false; @@ -1773,6 +1775,30 @@ public class Settings this.interpreterLocale = value; } + /** + * Using this flag, the interpreter will be able to delay the addition of foreign key declarations until the end of the interpretation run. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isInterpreterDelayForeignKeyDeclarations() { + return interpreterDelayForeignKeyDeclarations; + } + + /** + * Sets the value of the interpreterDelayForeignKeyDeclarations property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setInterpreterDelayForeignKeyDeclarations(Boolean value) { + this.interpreterDelayForeignKeyDeclarations = value; + } + /** * Whether migrations are allowed to be executed in inverse order.

This is a potentially destructive feature, which should not be turned on in production. It is useful mostly to quickly switch between branches in a development environment. This feature is available only in commercial distributions. * @@ -2597,6 +2623,11 @@ public class Settings return this; } + public Settings withInterpreterDelayForeignKeyDeclarations(Boolean value) { + setInterpreterDelayForeignKeyDeclarations(value); + return this; + } + public Settings withMigrationAllowsUndo(Boolean value) { setMigrationAllowsUndo(value); return this; @@ -2812,6 +2843,7 @@ public class Settings builder.append("interpreterDialect", interpreterDialect); builder.append("interpreterNameLookupCaseSensitivity", interpreterNameLookupCaseSensitivity); builder.append("interpreterLocale", interpreterLocale); + builder.append("interpreterDelayForeignKeyDeclarations", interpreterDelayForeignKeyDeclarations); builder.append("migrationAllowsUndo", migrationAllowsUndo); builder.append("migrationRevertUntracked", migrationRevertUntracked); builder.append("migrationAutoValidation", migrationAutoValidation); @@ -3478,6 +3510,15 @@ public class Settings return false; } } + if (interpreterDelayForeignKeyDeclarations == null) { + if (other.interpreterDelayForeignKeyDeclarations!= null) { + return false; + } + } else { + if (!interpreterDelayForeignKeyDeclarations.equals(other.interpreterDelayForeignKeyDeclarations)) { + return false; + } + } if (migrationAllowsUndo == null) { if (other.migrationAllowsUndo!= null) { return false; @@ -3690,6 +3731,7 @@ public class Settings result = ((prime*result)+((interpreterDialect == null)? 0 :interpreterDialect.hashCode())); result = ((prime*result)+((interpreterNameLookupCaseSensitivity == null)? 0 :interpreterNameLookupCaseSensitivity.hashCode())); result = ((prime*result)+((interpreterLocale == null)? 0 :interpreterLocale.hashCode())); + result = ((prime*result)+((interpreterDelayForeignKeyDeclarations == null)? 0 :interpreterDelayForeignKeyDeclarations.hashCode())); result = ((prime*result)+((migrationAllowsUndo == null)? 0 :migrationAllowsUndo.hashCode())); result = ((prime*result)+((migrationRevertUntracked == null)? 0 :migrationRevertUntracked.hashCode())); result = ((prime*result)+((migrationAutoValidation == null)? 0 :migrationAutoValidation.hashCode())); diff --git a/jOOQ/src/main/java/org/jooq/impl/Interpreter.java b/jOOQ/src/main/java/org/jooq/impl/Interpreter.java index e99940cb1b..c6693361bc 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Interpreter.java +++ b/jOOQ/src/main/java/org/jooq/impl/Interpreter.java @@ -37,6 +37,7 @@ */ package org.jooq.impl; +import static java.lang.Boolean.TRUE; import static org.jooq.Name.Quoted.QUOTED; import static org.jooq.conf.SettingsTools.interpreterLocale; import static org.jooq.impl.AbstractName.NO_NAME; @@ -54,8 +55,10 @@ import static org.jooq.impl.Tools.reverseIterable; import static org.jooq.tools.StringUtils.defaultIfNull; import java.util.AbstractList; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.Deque; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -113,6 +116,8 @@ final class Interpreter { private final MutableCatalog defaultCatalog; private final MutableSchema defaultSchema; private MutableSchema currentSchema; + private boolean delayForeignKeyDeclarations; + private final Deque delayedForeignKeyDeclarations; // Caches private final Map interpretedCatalogs = new HashMap<>(); @@ -125,6 +130,8 @@ final class Interpreter { Interpreter(Configuration configuration) { this.configuration = configuration; + this.delayForeignKeyDeclarations = TRUE.equals(configuration.settings().isInterpreterDelayForeignKeyDeclarations()); + this.delayedForeignKeyDeclarations = new ArrayDeque<>(); this.caseSensitivity = caseSensitivity(configuration); this.locale = interpreterLocale(configuration.settings()); this.defaultCatalog = new MutableCatalog(NO_NAME); @@ -133,6 +140,8 @@ final class Interpreter { } final Meta meta() { + applyDelayedForeignKeys(); + return new AbstractMeta(configuration) { private static final long serialVersionUID = 2052806256506059701L; @@ -308,6 +317,39 @@ final class Interpreter { } private final void addForeignKey(MutableSchema schema, MutableTable mt, ConstraintImpl impl) { + if (delayForeignKeyDeclarations) + delayForeignKey(schema, mt, impl); + else + addForeignKey0(schema, mt, impl); + } + + private static class DelayedForeignKey { + final MutableSchema schema; + final MutableTable table; + final ConstraintImpl constraint; + + DelayedForeignKey(MutableSchema schema, MutableTable mt, ConstraintImpl constraint) { + this.schema = schema; + this.table = mt; + this.constraint = constraint; + } + } + + private final void delayForeignKey(MutableSchema schema, MutableTable mt, ConstraintImpl impl) { + delayedForeignKeyDeclarations.add(new DelayedForeignKey(schema, mt, impl)); + } + + private final void applyDelayedForeignKeys() { + Iterator it = delayedForeignKeyDeclarations.iterator(); + + while (it.hasNext()) { + DelayedForeignKey key = it.next(); + addForeignKey0(key.schema, key.table, key.constraint); + it.remove(); + } + } + + private final void addForeignKey0(MutableSchema schema, MutableTable mt, ConstraintImpl impl) { MutableTable mrf = schema.table(impl.$referencesTable()); MutableUniqueKey mu = null; diff --git a/jOOQ/src/main/resources/xsd/jooq-runtime-3.13.0.xsd b/jOOQ/src/main/resources/xsd/jooq-runtime-3.13.0.xsd index 2802c9b296..abb700491c 100644 --- a/jOOQ/src/main/resources/xsd/jooq-runtime-3.13.0.xsd +++ b/jOOQ/src/main/resources/xsd/jooq-runtime-3.13.0.xsd @@ -439,6 +439,10 @@ jOOQ queries, for which no specific fetchSize value was specified.]]> + + + + This is a potentially destructive feature, which should not be turned on in production. It is useful mostly to quickly switch between branches in a development environment. This feature is available only in commercial distributions.]]>