[jOOQ/jOOQ#11830] Add Settings.renderRowConditionForSeekClause to allow for avoiding row predicate usage

This commit is contained in:
Lukas Eder 2022-11-30 17:11:29 +01:00
parent 29a3d17711
commit d445b361eb
3 changed files with 59 additions and 4 deletions

View File

@ -105,6 +105,8 @@ public class Settings
protected Boolean renderParenthesisAroundSetOperationQueries = false;
@XmlElement(defaultValue = "true")
protected Boolean renderVariablesInDerivedTablesForEmulations = true;
@XmlElement(defaultValue = "true")
protected Boolean renderRowConditionForSeekClause = true;
@XmlElement(defaultValue = ".")
protected String namePathSeparator = ".";
@XmlElement(defaultValue = "false")
@ -1150,6 +1152,34 @@ public class Settings
this.renderVariablesInDerivedTablesForEmulations = value;
}
/**
* Whether a <code>(a, b) < (:a, :b)</code> row predicate should be rendered for the <code>SEEK</code> clause.
* <p>
* Some RDBMS may support <code>(a, b) < (:a, :b)</code> row predicate syntax, which is very convenient for <code>SEEK</code> clause implementations, but fail to optimise this predicate as could be expected.
* This flag allows for expanding the predicate to the much more verbose, but equivalent <code>(a < :a) OR (a = :a AND b < :b)</code>. Dialects without native support for row predicates aren't affected
* by this flag.
*
* @return
* possible object is
* {@link Boolean }
*
*/
public Boolean isRenderRowConditionForSeekClause() {
return renderRowConditionForSeekClause;
}
/**
* Sets the value of the renderRowConditionForSeekClause property.
*
* @param value
* allowed object is
* {@link Boolean }
*
*/
public void setRenderRowConditionForSeekClause(Boolean value) {
this.renderRowConditionForSeekClause = value;
}
/**
* The character(s) to be used as a separator in paths encoded in a {@link Name}
* <p>
@ -5819,6 +5849,11 @@ public class Settings
return this;
}
public Settings withRenderRowConditionForSeekClause(Boolean value) {
setRenderRowConditionForSeekClause(value);
return this;
}
/**
* The character(s) to be used as a separator in paths encoded in a {@link Name}
* <p>
@ -7105,6 +7140,7 @@ public class Settings
builder.append("renderGroupConcatMaxLenSessionVariable", renderGroupConcatMaxLenSessionVariable);
builder.append("renderParenthesisAroundSetOperationQueries", renderParenthesisAroundSetOperationQueries);
builder.append("renderVariablesInDerivedTablesForEmulations", renderVariablesInDerivedTablesForEmulations);
builder.append("renderRowConditionForSeekClause", renderRowConditionForSeekClause);
builder.append("namePathSeparator", namePathSeparator);
builder.append("bindOffsetDateTimeType", bindOffsetDateTimeType);
builder.append("bindOffsetTimeType", bindOffsetTimeType);
@ -7556,6 +7592,15 @@ public class Settings
return false;
}
}
if (renderRowConditionForSeekClause == null) {
if (other.renderRowConditionForSeekClause!= null) {
return false;
}
} else {
if (!renderRowConditionForSeekClause.equals(other.renderRowConditionForSeekClause)) {
return false;
}
}
if (namePathSeparator == null) {
if (other.namePathSeparator!= null) {
return false;
@ -9193,6 +9238,7 @@ public class Settings
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)+((renderRowConditionForSeekClause == null)? 0 :renderRowConditionForSeekClause.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()));

View File

@ -37,6 +37,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 java.util.Collections.emptyList;
@ -2558,7 +2559,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
context.formatSeparator()
.visit(K_WHERE)
.sql(' ')
.qualify(false, c -> c.visit(getSeekCondition()));
.qualify(false, c -> c.visit(getSeekCondition(context)));
}
}
@ -3955,7 +3956,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// - There are no unions (union is nested in derived table
// and SEEK predicate is applied outside). See [#7459]
if (!getOrderBy().isEmpty() && !getSeek().isEmpty() && unionOp.isEmpty())
result.addConditions(getSeekCondition());
result.addConditions(getSeekCondition(ctx));
@ -3967,7 +3968,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
}
@SuppressWarnings({ "rawtypes", "unchecked" })
final Condition getSeekCondition() {
final Condition getSeekCondition(Context<?> ctx) {
SortFieldList o = getOrderBy();
Condition c = null;
@ -3979,7 +3980,7 @@ final class SelectQueryImpl<R extends Record> extends AbstractResultQuery<R> imp
// If we have uniform sorting, more efficient row value expression
// predicates can be applied, which can be heavily optimised on some
// databases.
if (o.size() > 1 && o.uniform()) {
if (o.size() > 1 && o.uniform() && !FALSE.equals(ctx.settings().isRenderRowConditionForSeekClause())) {
if (o.get(0).getOrder() != DESC ^ seekBefore)
c = row(o.fields()).gt(row(getSeek()));
else

View File

@ -220,6 +220,14 @@ For details, see <a href="https://github.com/jOOQ/jOOQ/issues/3676">https://gith
For details, see <a href="https://github.com/jOOQ/jOOQ/issues/14065">https://github.com/jOOQ/jOOQ/issues/14065</a>.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="renderRowConditionForSeekClause" type="boolean" minOccurs="0" maxOccurs="1" default="true">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether a <code>(a, b) < (:a, :b)</code> row predicate should be rendered for the <code>SEEK</code> clause.
<p>
Some RDBMS may support <code>(a, b) < (:a, :b)</code> row predicate syntax, which is very convenient for <code>SEEK</code> clause implementations, but fail to optimise this predicate as could be expected.
This flag allows for expanding the predicate to the much more verbose, but equivalent <code>(a < :a) OR (a = :a AND b < :b)</code>. Dialects without native support for row predicates aren't affected
by this flag.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="namePathSeparator" type="string" minOccurs="0" maxOccurs="1" default=".">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[The character(s) to be used as a separator in paths encoded in a {@link Name}
<p>