From 2449f09b9d6d6d7e9927fa477f3e509415dde6e5 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Mon, 10 Oct 2022 17:55:56 +0200 Subject: [PATCH] [jOOQ/jOOQ#14065] Add internal utilities to help avoid repeating expressions --- .../src/main/java/org/jooq/conf/Settings.java | 44 ++++++++++++++ jOOQ/src/main/java/org/jooq/impl/Tools.java | 58 +++++++++++++++++++ .../org/jooq/xsd/jooq-runtime-3.18.0.xsd | 6 ++ 3 files changed, 108 insertions(+) diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index c6746329b7..2fec5d9957 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -103,6 +103,8 @@ public class Settings protected Boolean renderGroupConcatMaxLenSessionVariable = true; @XmlElement(defaultValue = "false") protected Boolean renderParenthesisAroundSetOperationQueries = false; + @XmlElement(defaultValue = "true") + protected Boolean renderVariablesInDerivedTablesForEmulations = true; @XmlElement(defaultValue = ".") protected String namePathSeparator = "."; @XmlElement(defaultValue = "false") @@ -1036,6 +1038,32 @@ public class Settings this.renderParenthesisAroundSetOperationQueries = value; } + /** + * Whether emulations that require repeating expressions should render variables for those expressions in derived tables. + *

+ * For details, see https://github.com/jOOQ/jOOQ/issues/14065. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isRenderVariablesInDerivedTablesForEmulations() { + return renderVariablesInDerivedTablesForEmulations; + } + + /** + * Sets the value of the renderVariablesInDerivedTablesForEmulations property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setRenderVariablesInDerivedTablesForEmulations(Boolean value) { + this.renderVariablesInDerivedTablesForEmulations = value; + } + /** * The character(s) to be used as a separator in paths encoded in a {@link Name} *

@@ -4463,6 +4491,11 @@ public class Settings return this; } + public Settings withRenderVariablesInDerivedTablesForEmulations(Boolean value) { + setRenderVariablesInDerivedTablesForEmulations(value); + return this; + } + /** * The character(s) to be used as a separator in paths encoded in a {@link Name} *

@@ -5525,6 +5558,7 @@ public class Settings builder.append("renderOutputForSQLServerReturningClause", renderOutputForSQLServerReturningClause); builder.append("renderGroupConcatMaxLenSessionVariable", renderGroupConcatMaxLenSessionVariable); builder.append("renderParenthesisAroundSetOperationQueries", renderParenthesisAroundSetOperationQueries); + builder.append("renderVariablesInDerivedTablesForEmulations", renderVariablesInDerivedTablesForEmulations); builder.append("namePathSeparator", namePathSeparator); builder.append("bindOffsetDateTimeType", bindOffsetDateTimeType); builder.append("bindOffsetTimeType", bindOffsetTimeType); @@ -5925,6 +5959,15 @@ public class Settings return false; } } + if (renderVariablesInDerivedTablesForEmulations == null) { + if (other.renderVariablesInDerivedTablesForEmulations!= null) { + return false; + } + } else { + if (!renderVariablesInDerivedTablesForEmulations.equals(other.renderVariablesInDerivedTablesForEmulations)) { + return false; + } + } if (namePathSeparator == null) { if (other.namePathSeparator!= null) { return false; @@ -7183,6 +7226,7 @@ public class Settings result = ((prime*result)+((renderOutputForSQLServerReturningClause == null)? 0 :renderOutputForSQLServerReturningClause.hashCode())); result = ((prime*result)+((renderGroupConcatMaxLenSessionVariable == null)? 0 :renderGroupConcatMaxLenSessionVariable.hashCode())); result = ((prime*result)+((renderParenthesisAroundSetOperationQueries == null)? 0 :renderParenthesisAroundSetOperationQueries.hashCode())); + result = ((prime*result)+((renderVariablesInDerivedTablesForEmulations == null)? 0 :renderVariablesInDerivedTablesForEmulations.hashCode())); result = ((prime*result)+((namePathSeparator == null)? 0 :namePathSeparator.hashCode())); result = ((prime*result)+((bindOffsetDateTimeType == null)? 0 :bindOffsetDateTimeType.hashCode())); result = ((prime*result)+((bindOffsetTimeType == null)? 0 :bindOffsetTimeType.hashCode())); diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index 2470630d1f..7369b81027 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -123,6 +123,7 @@ import static org.jooq.impl.DSL.unquotedName; import static org.jooq.impl.DSL.val; import static org.jooq.impl.DefaultExecuteContext.localConnection; import static org.jooq.impl.DefaultParseContext.SUPPORTS_HASH_COMMENT_SYNTAX; +import static org.jooq.impl.DerivedTable.NO_SUPPORT_CORRELATED_DERIVED_TABLE; import static org.jooq.impl.Identifiers.QUOTES; import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER; import static org.jooq.impl.Identifiers.QUOTE_END_DELIMITER_ESCAPED; @@ -279,6 +280,9 @@ import org.jooq.FieldOrRow; import org.jooq.FieldOrRowOrSelect; import org.jooq.Fields; import org.jooq.ForeignKey; +import org.jooq.Function1; +import org.jooq.Function2; +import org.jooq.Function3; import org.jooq.Generator; import org.jooq.JSON; import org.jooq.JSONB; @@ -308,6 +312,7 @@ import org.jooq.Scope; import org.jooq.ContextConverter; import org.jooq.Select; import org.jooq.SelectFieldOrAsterisk; +import org.jooq.SelectJoinStep; import org.jooq.SortField; import org.jooq.Source; import org.jooq.Table; @@ -7161,4 +7166,57 @@ final class Tools { static final ConverterContext converterContext(Configuration configuration) { return new DefaultConverterContext(configuration(configuration)); } + + /** + * Wrap an expression in a derived table to allow for simplifying + * referencing it. + */ + static final Field derivedTable( + Context ctx, + Field f1, + Function1, ? extends Field> f + ) { + if (derivedTableEnabled(ctx) && !isSimple(ctx, f1)) + return DSL.field(select(f.apply(f1.as("f1"))).from(select(f1.as("f1")).asTable("t"))); + else + return f.apply(f1); + } + + /** + * Wrap expressions in a derived table to allow for simplifying referencing + * them. + */ + static final Field derivedTable( + Context ctx, + Field f1, + Field f2, + Function2, ? super Field, ? extends Field> f + ) { + if (derivedTableEnabled(ctx) && !isSimple(ctx, f1) && !isSimple(ctx, f2)) + return DSL.field(select(f.apply(f1.as("f1"), f2.as("f2"))).from(select(f1.as("f1"), f2.as("f2")).asTable("t"))); + else + return f.apply(f1, f2); + } + + /** + * Wrap expressions in a derived table to allow for simplifying referencing + * them. + */ + static final Field derivedTable( + Context ctx, + Field f1, + Field f2, + Field f3, + Function3, ? super Field, ? super Field, ? extends Field> f + ) { + if (derivedTableEnabled(ctx) && !isSimple(ctx, f1) && !isSimple(ctx, f2) && !isSimple(ctx, f3)) + return DSL.field(select(f.apply(f1.as("f1"), f2.as("f2"), f3.as("f3"))).from(select(f1.as("f1"), f2.as("f2"), f3.as("f3")).asTable("t"))); + else + return f.apply(f1, f2, f3); + } + + private static boolean derivedTableEnabled(Context ctx) { + return !FALSE.equals(ctx.settings().isRenderVariablesInDerivedTablesForEmulations()) + && !NO_SUPPORT_CORRELATED_DERIVED_TABLE.contains(ctx.dialect()); + } } diff --git a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.18.0.xsd b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.18.0.xsd index 3bd4ddc160..03e78a20a6 100644 --- a/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.18.0.xsd +++ b/jOOQ/src/main/resources/org/jooq/xsd/jooq-runtime-3.18.0.xsd @@ -214,6 +214,12 @@ When this setting is set to true the queries combined with set oper For details, see https://github.com/jOOQ/jOOQ/issues/3676 and https://github.com/jOOQ/jOOQ/issues/9751.]]> + + +For details, see https://github.com/jOOQ/jOOQ/issues/14065.]]> + +