[jOOQ/jOOQ#11892] Add Settings.fetchIntermediateResult

This commit is contained in:
Lukas Eder 2021-05-19 11:09:03 +02:00
parent 4ed5d923b4
commit 48e882081e
5 changed files with 164 additions and 1 deletions

View File

@ -0,0 +1,39 @@
package org.jooq.conf;
import javax.xml.bind.annotation.XmlEnum;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for FetchIntermediateResult.
*
* <p>The following schema fragment specifies the expected content contained within this class.
* <pre>
* &lt;simpleType name="FetchIntermediateResult"&gt;
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}string"&gt;
* &lt;enumeration value="ALWAYS"/&gt;
* &lt;enumeration value="WHEN_EXECUTE_LISTENERS_PRESENT"/&gt;
* &lt;enumeration value="WHEN_RESULT_REQUESTED"/&gt;
* &lt;/restriction&gt;
* &lt;/simpleType&gt;
* </pre>
*
*/
@XmlType(name = "FetchIntermediateResult")
@XmlEnum
public enum FetchIntermediateResult {
ALWAYS,
WHEN_EXECUTE_LISTENERS_PRESENT,
WHEN_RESULT_REQUESTED;
public String value() {
return name();
}
public static FetchIntermediateResult fromValue(String v) {
return valueOf(v);
}
}

View File

@ -106,6 +106,9 @@ public class Settings
protected Boolean bindOffsetTimeType = false;
@XmlElement(defaultValue = "true")
protected Boolean fetchTriggerValuesAfterSQLServerOutput = true;
@XmlElement(defaultValue = "WHEN_RESULT_REQUESTED")
@XmlSchemaType(name = "string")
protected FetchIntermediateResult fetchIntermediateResult = FetchIntermediateResult.WHEN_RESULT_REQUESTED;
@XmlElement(defaultValue = "false")
protected Boolean transformAnsiJoinToTableLists = false;
@XmlElement(defaultValue = "WHEN_NEEDED")
@ -1020,6 +1023,40 @@ public class Settings
this.fetchTriggerValuesAfterSQLServerOutput = value;
}
/**
* Whether to fetch data into intermediate {@link org.jooq.Result} instances.
* <p>
* By default, a {@link org.jooq.ResultQuery} produces no intermediate {@link org.jooq.Result}
* instances if they are not explicitly requested by the caller, e.g. by calling
* {@link org.jooq.ResultQuery#fetch()}, or in the presence of {@link org.jooq.ExecuteListener}
* instances, which may require access to {@link org.jooq.ExecuteContext#result()}.
* This default behaviour helps avoid unnecessary allocations of possibly large data structures.
* <p>
* Using this flag, fetching of intermediate results can be turned off even when execute listeners
* are present, or turned on even if they're absent.
*
*/
public FetchIntermediateResult getFetchIntermediateResult() {
return fetchIntermediateResult;
}
/**
* Whether to fetch data into intermediate {@link org.jooq.Result} instances.
* <p>
* By default, a {@link org.jooq.ResultQuery} produces no intermediate {@link org.jooq.Result}
* instances if they are not explicitly requested by the caller, e.g. by calling
* {@link org.jooq.ResultQuery#fetch()}, or in the presence of {@link org.jooq.ExecuteListener}
* instances, which may require access to {@link org.jooq.ExecuteContext#result()}.
* This default behaviour helps avoid unnecessary allocations of possibly large data structures.
* <p>
* Using this flag, fetching of intermediate results can be turned off even when execute listeners
* are present, or turned on even if they're absent.
*
*/
public void setFetchIntermediateResult(FetchIntermediateResult value) {
this.fetchIntermediateResult = value;
}
/**
* Transform ANSI join to table lists if possible.
* <p>
@ -3123,6 +3160,24 @@ public class Settings
return this;
}
/**
* Whether to fetch data into intermediate {@link org.jooq.Result} instances.
* <p>
* By default, a {@link org.jooq.ResultQuery} produces no intermediate {@link org.jooq.Result}
* instances if they are not explicitly requested by the caller, e.g. by calling
* {@link org.jooq.ResultQuery#fetch()}, or in the presence of {@link org.jooq.ExecuteListener}
* instances, which may require access to {@link org.jooq.ExecuteContext#result()}.
* This default behaviour helps avoid unnecessary allocations of possibly large data structures.
* <p>
* Using this flag, fetching of intermediate results can be turned off even when execute listeners
* are present, or turned on even if they're absent.
*
*/
public Settings withFetchIntermediateResult(FetchIntermediateResult value) {
setFetchIntermediateResult(value);
return this;
}
public Settings withTransformAnsiJoinToTableLists(Boolean value) {
setTransformAnsiJoinToTableLists(value);
return this;
@ -3894,6 +3949,7 @@ public class Settings
builder.append("bindOffsetDateTimeType", bindOffsetDateTimeType);
builder.append("bindOffsetTimeType", bindOffsetTimeType);
builder.append("fetchTriggerValuesAfterSQLServerOutput", fetchTriggerValuesAfterSQLServerOutput);
builder.append("fetchIntermediateResult", fetchIntermediateResult);
builder.append("transformAnsiJoinToTableLists", transformAnsiJoinToTableLists);
builder.append("transformInConditionSubqueryWithLimitToDerivedTable", transformInConditionSubqueryWithLimitToDerivedTable);
builder.append("transformQualify", transformQualify);
@ -4265,6 +4321,15 @@ public class Settings
return false;
}
}
if (fetchIntermediateResult == null) {
if (other.fetchIntermediateResult!= null) {
return false;
}
} else {
if (!fetchIntermediateResult.equals(other.fetchIntermediateResult)) {
return false;
}
}
if (transformAnsiJoinToTableLists == null) {
if (other.transformAnsiJoinToTableLists!= null) {
return false;
@ -5102,6 +5167,7 @@ public class Settings
result = ((prime*result)+((bindOffsetDateTimeType == null)? 0 :bindOffsetDateTimeType.hashCode()));
result = ((prime*result)+((bindOffsetTimeType == null)? 0 :bindOffsetTimeType.hashCode()));
result = ((prime*result)+((fetchTriggerValuesAfterSQLServerOutput == null)? 0 :fetchTriggerValuesAfterSQLServerOutput.hashCode()));
result = ((prime*result)+((fetchIntermediateResult == null)? 0 :fetchIntermediateResult.hashCode()));
result = ((prime*result)+((transformAnsiJoinToTableLists == null)? 0 :transformAnsiJoinToTableLists.hashCode()));
result = ((prime*result)+((transformInConditionSubqueryWithLimitToDerivedTable == null)? 0 :transformInConditionSubqueryWithLimitToDerivedTable.hashCode()));
result = ((prime*result)+((transformQualify == null)? 0 :transformQualify.hashCode()));

View File

@ -37,6 +37,8 @@
*/
package org.jooq.conf;
import static org.jooq.conf.FetchIntermediateResult.WHEN_EXECUTE_LISTENERS_PRESENT;
import static org.jooq.conf.FetchIntermediateResult.WHEN_RESULT_REQUESTED;
import static org.jooq.conf.ParamType.INDEXED;
import static org.jooq.conf.ParamType.INLINED;
import static org.jooq.conf.StatementType.PREPARED_STATEMENT;
@ -50,7 +52,9 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.Locale;
import org.jooq.Configuration;
import org.jooq.tools.JooqLogger;
import org.jooq.tools.StringUtils;
import org.jooq.util.jaxb.tools.MiniJAXB;
/**
@ -391,6 +395,22 @@ public final class SettingsTools {
: 0;
}
/**
* Return <code>FetchIntermediateResult</code>.
*/
public static final boolean fetchIntermediateResult(Configuration configuration) {
switch (defaultIfNull(configuration.settings().getFetchIntermediateResult(), WHEN_RESULT_REQUESTED)) {
case ALWAYS:
return true;
case WHEN_EXECUTE_LISTENERS_PRESENT:
return configuration.executeListenerProviders().length > 0;
case WHEN_RESULT_REQUESTED:
return false;
default:
throw new IllegalStateException("Unhandled FetchIntermediateResult: " + configuration.settings().getFetchIntermediateResult());
}
}
/**
* Return <code>fetchSize</code> if it is not <code>0</code>, or the specified
* {@link Settings#getFetchSize()}.

View File

@ -41,6 +41,7 @@ import static org.jooq.Records.intoGroups;
import static org.jooq.Records.intoList;
import static org.jooq.Records.intoMap;
import static org.jooq.Records.intoSet;
import static org.jooq.conf.SettingsTools.fetchIntermediateResult;
import static org.jooq.impl.Tools.blocking;
import static org.jooq.tools.jdbc.JDBCUtils.safeClose;
@ -99,6 +100,7 @@ import org.jooq.ResultQuery;
import org.jooq.Results;
import org.jooq.Select;
import org.jooq.Table;
import org.jooq.conf.SettingsTools;
import org.jooq.exception.DataAccessException;
import org.jooq.impl.R2DBC.BlockingRecordSubscription;
import org.jooq.impl.R2DBC.QuerySubscription;
@ -278,7 +280,10 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
@Override
default ResultSet fetchResultSet() {
return fetchLazy().resultSet();
if (fetchIntermediateResult(Tools.configuration(this)))
return fetch().intoResultSet();
else
return fetchLazy().resultSet();
}
@Override
@ -298,6 +303,9 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
@Override
default Stream<R> fetchStream() {
if (fetchIntermediateResult(Tools.configuration(this)))
return fetch().stream();
AtomicReference<Cursor<R>> r = new AtomicReference<>();
// [#11895] Don't use the Stream.of(1).flatMap(i -> fetchLazy().stream())
@ -332,6 +340,9 @@ interface ResultQueryTrait<R extends Record> extends QueryPartInternal, ResultQu
@Override
default <X, A> X collect(Collector<? super R, A, X> collector) {
if (fetchIntermediateResult(Tools.configuration(this)))
return fetch().collect(collector);
try (Cursor<R> c = fetchLazyNonAutoClosing()) {
return c.collect(collector);
}

View File

@ -245,6 +245,19 @@ included in the <code>OUTPUT</code> clause.
For details, see <a href="https://github.com/jOOQ/jOOQ/issues/4498">https://github.com/jOOQ/jOOQ/issues/4498</a>.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="fetchIntermediateResult" type="jooq-runtime:FetchIntermediateResult" minOccurs="0" maxOccurs="1" default="WHEN_RESULT_REQUESTED">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Whether to fetch data into intermediate {@link org.jooq.Result} instances.
<p>
By default, a {@link org.jooq.ResultQuery} produces no intermediate {@link org.jooq.Result}
instances if they are not explicitly requested by the caller, e.g. by calling
{@link org.jooq.ResultQuery#fetch()}, or in the presence of {@link org.jooq.ExecuteListener}
instances, which may require access to {@link org.jooq.ExecuteContext#result()}.
This default behaviour helps avoid unnecessary allocations of possibly large data structures.
<p>
Using this flag, fetching of intermediate results can be turned off even when execute listeners
are present, or turned on even if they're absent.]]></jxb:javadoc></jxb:property></appinfo></annotation>
</element>
<element name="transformAnsiJoinToTableLists" type="boolean" minOccurs="0" maxOccurs="1" default="false">
<annotation><appinfo><jxb:property><jxb:javadoc><![CDATA[Transform ANSI join to table lists if possible.
<p>
@ -1340,4 +1353,18 @@ Either &lt;input/&gt; or &lt;inputExpression/&gt; must be provided]]></jxb:javad
<enumeration value="ALWAYS"/>
</restriction>
</simpleType>
<simpleType name="FetchIntermediateResult">
<restriction base="string">
<!-- Always fetch intermediate results -->
<enumeration value="ALWAYS"/>
<!-- Fetch intermediate results only when explicitly requested or when execute listeners are present -->
<enumeration value="WHEN_EXECUTE_LISTENERS_PRESENT"/>
<!-- Fetch intermediate results only when explicitly requested -->
<enumeration value="WHEN_RESULT_REQUESTED"/>
</restriction>
</simpleType>
</schema>