diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index 77c3b2289b..6f00bfb812 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -85,6 +85,8 @@ public class Settings @XmlElement(defaultValue = "IMPLICIT_NULL") @XmlSchemaType(name = "string") protected RenderDefaultNullability renderDefaultNullability = RenderDefaultNullability.IMPLICIT_NULL; + @XmlElement(defaultValue = "false") + protected Boolean renderCoalesceToEmptyStringInConcat = false; @XmlElement(defaultValue = "true") protected Boolean renderOrderByRownumberForEmulatedPagination = true; @XmlElement(defaultValue = "true") @@ -700,6 +702,35 @@ public class Settings this.renderDefaultNullability = value; } + /** + * Whether stored function calls should be wrapped in scalar subqueries. + *

+ * Oracle 11g (and potentially, other databases too) implements scalar subquery caching. With this flag + * set to true, users can automatically profit from this feature in all SQL statements. + *

+ * This feature is available in the commercial distribution only. + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isRenderCoalesceToEmptyStringInConcat() { + return renderCoalesceToEmptyStringInConcat; + } + + /** + * Sets the value of the renderCoalesceToEmptyStringInConcat property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setRenderCoalesceToEmptyStringInConcat(Boolean value) { + this.renderCoalesceToEmptyStringInConcat = value; + } + /** * Whether an additional ORDER BY rn clause should be rendered on emulated paginated queries. *

@@ -2829,6 +2860,11 @@ public class Settings return this; } + public Settings withRenderCoalesceToEmptyStringInConcat(Boolean value) { + setRenderCoalesceToEmptyStringInConcat(value); + return this; + } + public Settings withRenderOrderByRownumberForEmulatedPagination(Boolean value) { setRenderOrderByRownumberForEmulatedPagination(value); return this; @@ -3564,6 +3600,7 @@ public class Settings builder.append("renderScalarSubqueriesForStoredFunctions", renderScalarSubqueriesForStoredFunctions); builder.append("renderImplicitJoinType", renderImplicitJoinType); builder.append("renderDefaultNullability", renderDefaultNullability); + builder.append("renderCoalesceToEmptyStringInConcat", renderCoalesceToEmptyStringInConcat); builder.append("renderOrderByRownumberForEmulatedPagination", renderOrderByRownumberForEmulatedPagination); builder.append("renderOutputForSQLServerReturningClause", renderOutputForSQLServerReturningClause); builder.append("renderParenthesisAroundSetOperationQueries", renderParenthesisAroundSetOperationQueries); @@ -3847,6 +3884,15 @@ public class Settings return false; } } + if (renderCoalesceToEmptyStringInConcat == null) { + if (other.renderCoalesceToEmptyStringInConcat!= null) { + return false; + } + } else { + if (!renderCoalesceToEmptyStringInConcat.equals(other.renderCoalesceToEmptyStringInConcat)) { + return false; + } + } if (renderOrderByRownumberForEmulatedPagination == null) { if (other.renderOrderByRownumberForEmulatedPagination!= null) { return false; @@ -4692,6 +4738,7 @@ public class Settings result = ((prime*result)+((renderScalarSubqueriesForStoredFunctions == null)? 0 :renderScalarSubqueriesForStoredFunctions.hashCode())); result = ((prime*result)+((renderImplicitJoinType == null)? 0 :renderImplicitJoinType.hashCode())); result = ((prime*result)+((renderDefaultNullability == null)? 0 :renderDefaultNullability.hashCode())); + result = ((prime*result)+((renderCoalesceToEmptyStringInConcat == null)? 0 :renderCoalesceToEmptyStringInConcat.hashCode())); result = ((prime*result)+((renderOrderByRownumberForEmulatedPagination == null)? 0 :renderOrderByRownumberForEmulatedPagination.hashCode())); result = ((prime*result)+((renderOutputForSQLServerReturningClause == null)? 0 :renderOutputForSQLServerReturningClause.hashCode())); result = ((prime*result)+((renderParenthesisAroundSetOperationQueries == null)? 0 :renderParenthesisAroundSetOperationQueries.hashCode())); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java index fc3756840f..8a70808b2c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractField.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractField.java @@ -137,6 +137,10 @@ abstract class AbstractField extends AbstractTypedNamed implements Field extends AbstractParamX implements SimpleQuery this.value = value; } + @Override + final boolean isPossiblyNullable() { + return !inline || value == null; + } + /** * A utility method that generates a field name. *

diff --git a/jOOQ/src/main/java/org/jooq/impl/Concat.java b/jOOQ/src/main/java/org/jooq/impl/Concat.java index 30950b709f..572c0366a1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Concat.java +++ b/jOOQ/src/main/java/org/jooq/impl/Concat.java @@ -38,6 +38,7 @@ package org.jooq.impl; import static org.jooq.impl.DSL.function; +import static org.jooq.impl.DSL.inline; import static org.jooq.impl.ExpressionOperator.ADD; import static org.jooq.impl.ExpressionOperator.BIT_AND; import static org.jooq.impl.ExpressionOperator.CONCAT; @@ -71,6 +72,14 @@ final class Concat extends AbstractField { // [#461] Type cast the concat expression, if this isn't a VARCHAR field Field[] cast = castAllIfNeeded(arguments, String.class); + if (Boolean.TRUE.equals(ctx.settings().isRenderCoalesceToEmptyStringInConcat()) && ctx.configuration().commercial(() -> "Auto-coalescing of CONCAT arguments is available in the jOOQ 3.15 Professional Edition and jOOQ Enterprise Edition, see https://github.com/jOOQ/jOOQ/issues/11757")) { + + + + + + } + // If there is only one argument, return it immediately if (cast.length == 1) { ctx.visit(cast[0]); diff --git a/jOOQ/src/main/java/org/jooq/impl/Tools.java b/jOOQ/src/main/java/org/jooq/impl/Tools.java index c6aba7d656..ba6207a3cd 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Tools.java +++ b/jOOQ/src/main/java/org/jooq/impl/Tools.java @@ -3136,6 +3136,10 @@ final class Tools { return part instanceof SimpleQueryPart && ((SimpleQueryPart) part).isSimple(); } + static final boolean isPossiblyNullable(Field f) { + return f instanceof AbstractField && ((AbstractField) f).isPossiblyNullable(); + } + static final Val extractVal(Field field) { return field instanceof Val ? (Val) field diff --git a/jOOQ/src/main/resources/xsd/jooq-runtime-3.15.0.xsd b/jOOQ/src/main/resources/xsd/jooq-runtime-3.15.0.xsd index 3b56975b81..b574bc3fb8 100644 --- a/jOOQ/src/main/resources/xsd/jooq-runtime-3.15.0.xsd +++ b/jOOQ/src/main/resources/xsd/jooq-runtime-3.15.0.xsd @@ -140,6 +140,15 @@ set to true, users can automatically profit from this feature in all SQL stateme + + + +Oracle 11g (and potentially, other databases too) implements scalar subquery caching. With this flag +set to true, users can automatically profit from this feature in all SQL statements. +

+This feature is available in the commercial distribution only.]]> + ORDER BY rn clause should be rendered on emulated paginated queries.