diff --git a/jOOQ/src/main/java/org/jooq/conf/Settings.java b/jOOQ/src/main/java/org/jooq/conf/Settings.java index 9e43ae8d67..28c622a44e 100644 --- a/jOOQ/src/main/java/org/jooq/conf/Settings.java +++ b/jOOQ/src/main/java/org/jooq/conf/Settings.java @@ -107,6 +107,8 @@ public class Settings protected Boolean renderVariablesInDerivedTablesForEmulations = true; @XmlElement(defaultValue = "true") protected Boolean renderRowConditionForSeekClause = true; + @XmlElement(defaultValue = "false") + protected Boolean renderRedundantConditionForSeekClause = false; @XmlElement(defaultValue = ".") protected String namePathSeparator = "."; @XmlElement(defaultValue = "false") @@ -1180,6 +1182,33 @@ public class Settings this.renderRowConditionForSeekClause = value; } + /** + * Whether a redundant (a <= :a) predicate should be rendered for a (a, b) < (:a, :b) predicate for the SEEK clause. + *

+ * Some RDBMS may not be able to properly optimise (a, b) < ('a', 'b') or (a < 'a') OR (a = 'a' AND b < 'b'), and choose an appropriate index. By adding an additional redundant predicate, + * jOOQ may help the optimiser, e.g. (a <= :a) AND (a, b) < ('a', 'b') or (a <= :a) AND ((a < 'a') OR (a = 'a' AND b < 'b')) + * + * @return + * possible object is + * {@link Boolean } + * + */ + public Boolean isRenderRedundantConditionForSeekClause() { + return renderRedundantConditionForSeekClause; + } + + /** + * Sets the value of the renderRedundantConditionForSeekClause property. + * + * @param value + * allowed object is + * {@link Boolean } + * + */ + public void setRenderRedundantConditionForSeekClause(Boolean value) { + this.renderRedundantConditionForSeekClause = value; + } + /** * The character(s) to be used as a separator in paths encoded in a {@link Name} *

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

@@ -7141,6 +7175,7 @@ public class Settings builder.append("renderParenthesisAroundSetOperationQueries", renderParenthesisAroundSetOperationQueries); builder.append("renderVariablesInDerivedTablesForEmulations", renderVariablesInDerivedTablesForEmulations); builder.append("renderRowConditionForSeekClause", renderRowConditionForSeekClause); + builder.append("renderRedundantConditionForSeekClause", renderRedundantConditionForSeekClause); builder.append("namePathSeparator", namePathSeparator); builder.append("bindOffsetDateTimeType", bindOffsetDateTimeType); builder.append("bindOffsetTimeType", bindOffsetTimeType); @@ -7601,6 +7636,15 @@ public class Settings return false; } } + if (renderRedundantConditionForSeekClause == null) { + if (other.renderRedundantConditionForSeekClause!= null) { + return false; + } + } else { + if (!renderRedundantConditionForSeekClause.equals(other.renderRedundantConditionForSeekClause)) { + return false; + } + } if (namePathSeparator == null) { if (other.namePathSeparator!= null) { return false; @@ -9239,6 +9283,7 @@ public class Settings result = ((prime*result)+((renderParenthesisAroundSetOperationQueries == null)? 0 :renderParenthesisAroundSetOperationQueries.hashCode())); result = ((prime*result)+((renderVariablesInDerivedTablesForEmulations == null)? 0 :renderVariablesInDerivedTablesForEmulations.hashCode())); result = ((prime*result)+((renderRowConditionForSeekClause == null)? 0 :renderRowConditionForSeekClause.hashCode())); + result = ((prime*result)+((renderRedundantConditionForSeekClause == null)? 0 :renderRedundantConditionForSeekClause.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/SelectQueryImpl.java b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java index 860cdacde7..9e756dbd68 100644 --- a/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/SelectQueryImpl.java @@ -4010,6 +4010,13 @@ final class SelectQueryImpl extends AbstractResultQuery imp c = or; } + if (o.size() > 1 && TRUE.equals(ctx.settings().isRenderRedundantConditionForSeekClause())) { + if (o.get(0).getOrder() != DESC ^ seekBefore) + c = ((Field) o.get(0).$field()).ge(getSeek().get(0)).and(c); + else + c = ((Field) o.get(0).$field()).le(getSeek().get(0)).and(c); + } + return c; } 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 45d9929d97..bdc6382339 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 @@ -228,6 +228,13 @@ This flag allows for expanding the predicate to the much more verbose, but equiv by this flag.]]> + + (a <= :a) predicate should be rendered for a (a, b) < (:a, :b) predicate for the SEEK clause. +

+Some RDBMS may not be able to properly optimise (a, b) < ('a', 'b') or (a < 'a') OR (a = 'a' AND b < 'b'), and choose an appropriate index. By adding an additional redundant predicate, +jOOQ may help the optimiser, e.g. (a <= :a) AND (a, b) < ('a', 'b') or (a <= :a) AND ((a < 'a') OR (a = 'a' AND b < 'b'))]]> + +