diff --git a/jOOQ/src/main/java/org/jooq/BindingGetResultSetContext.java b/jOOQ/src/main/java/org/jooq/BindingGetResultSetContext.java index 7d3ba6d1df..f5f00419a8 100644 --- a/jOOQ/src/main/java/org/jooq/BindingGetResultSetContext.java +++ b/jOOQ/src/main/java/org/jooq/BindingGetResultSetContext.java @@ -45,7 +45,7 @@ import java.sql.ResultSet; * * @author Lukas Eder */ -public interface BindingGetResultSetContext extends Scope { +public interface BindingGetResultSetContext extends ExecuteScope { /** * The {@link ResultSet} from which a value is retrieved. diff --git a/jOOQ/src/main/java/org/jooq/BindingGetSQLInputContext.java b/jOOQ/src/main/java/org/jooq/BindingGetSQLInputContext.java index 17afe5c644..5b3775f9af 100644 --- a/jOOQ/src/main/java/org/jooq/BindingGetSQLInputContext.java +++ b/jOOQ/src/main/java/org/jooq/BindingGetSQLInputContext.java @@ -45,7 +45,7 @@ import java.sql.SQLInput; * * @author Lukas Eder */ -public interface BindingGetSQLInputContext extends Scope { +public interface BindingGetSQLInputContext extends ExecuteScope { /** * The {@link SQLInput} from which a value is retrieved. diff --git a/jOOQ/src/main/java/org/jooq/BindingGetStatementContext.java b/jOOQ/src/main/java/org/jooq/BindingGetStatementContext.java index d4b6c474db..83f946f0e0 100644 --- a/jOOQ/src/main/java/org/jooq/BindingGetStatementContext.java +++ b/jOOQ/src/main/java/org/jooq/BindingGetStatementContext.java @@ -45,7 +45,7 @@ import java.sql.CallableStatement; * * @author Lukas Eder */ -public interface BindingGetStatementContext extends Scope { +public interface BindingGetStatementContext extends ExecuteScope { /** * The {@link CallableStatement} from which a value is retrieved. diff --git a/jOOQ/src/main/java/org/jooq/BindingRegisterContext.java b/jOOQ/src/main/java/org/jooq/BindingRegisterContext.java index 9d934176ae..7daeec8fcc 100644 --- a/jOOQ/src/main/java/org/jooq/BindingRegisterContext.java +++ b/jOOQ/src/main/java/org/jooq/BindingRegisterContext.java @@ -45,7 +45,7 @@ import java.sql.CallableStatement; * * @author Lukas Eder */ -public interface BindingRegisterContext extends Scope { +public interface BindingRegisterContext extends ExecuteScope { /** * The {@link CallableStatement} on which a bind variable should be diff --git a/jOOQ/src/main/java/org/jooq/BindingSetSQLOutputContext.java b/jOOQ/src/main/java/org/jooq/BindingSetSQLOutputContext.java index 85a84df30a..5a9d2d143d 100644 --- a/jOOQ/src/main/java/org/jooq/BindingSetSQLOutputContext.java +++ b/jOOQ/src/main/java/org/jooq/BindingSetSQLOutputContext.java @@ -45,7 +45,7 @@ import java.sql.SQLOutput; * * @author Lukas Eder */ -public interface BindingSetSQLOutputContext extends ResourceManagingScope { +public interface BindingSetSQLOutputContext extends ResourceManagingScope, ExecuteScope { /** * The {@link SQLOutput} to which a bind variable should be bound. diff --git a/jOOQ/src/main/java/org/jooq/BindingSetStatementContext.java b/jOOQ/src/main/java/org/jooq/BindingSetStatementContext.java index de8782dd84..21fad6e44d 100644 --- a/jOOQ/src/main/java/org/jooq/BindingSetStatementContext.java +++ b/jOOQ/src/main/java/org/jooq/BindingSetStatementContext.java @@ -45,7 +45,7 @@ import java.sql.PreparedStatement; * * @author Lukas Eder */ -public interface BindingSetStatementContext extends ResourceManagingScope { +public interface BindingSetStatementContext extends ResourceManagingScope, ExecuteScope { /** * The {@link PreparedStatement} to which a bind variable should be bound. diff --git a/jOOQ/src/main/java/org/jooq/ExecuteScope.java b/jOOQ/src/main/java/org/jooq/ExecuteScope.java new file mode 100644 index 0000000000..d9d83411ed --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/ExecuteScope.java @@ -0,0 +1,55 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq; + +import org.jetbrains.annotations.Nullable; + +/** + * A {@link Scope} that knows its {@link ExecuteContext}. + */ +public interface ExecuteScope extends Scope { + + /** + * The {@link ExecuteContext} that created this scope. + * + * @return The execute context. Can be null e.g. when running + * in an R2DBC context, see [#11717]. + */ + @Nullable + ExecuteContext executeContext(); +} diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractExecuteScope.java b/jOOQ/src/main/java/org/jooq/impl/AbstractExecuteScope.java new file mode 100644 index 0000000000..d6286f5680 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractExecuteScope.java @@ -0,0 +1,62 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import org.jooq.ExecuteContext; +import org.jooq.ExecuteScope; + +/** + * Base class for {@link ExecuteScope}. + * + * @author Lukas Eder + */ +abstract class AbstractExecuteScope extends AbstractScope implements ExecuteScope { + + final ExecuteContext ctx; + + AbstractExecuteScope(ExecuteContext ctx) { + super(ctx.configuration(), ctx.data()); + + this.ctx = ctx; + } + + @Override + public ExecuteContext executeContext() { + return ctx; + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractQualifiedRecord.java b/jOOQ/src/main/java/org/jooq/impl/AbstractQualifiedRecord.java index 1eb45276a6..3533bf07ea 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractQualifiedRecord.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractQualifiedRecord.java @@ -37,7 +37,7 @@ */ package org.jooq.impl; -import static org.jooq.impl.DefaultExecuteContext.localScope; +import static org.jooq.impl.DefaultExecuteContext.localExecuteContext; import static org.jooq.impl.Tools.fieldsArray; import static org.jooq.impl.Tools.getMappedUDTName; import static org.jooq.impl.Tools.row0; @@ -47,6 +47,7 @@ import java.sql.SQLInput; import java.sql.SQLOutput; import org.jooq.Converter; +import org.jooq.ExecuteContext; import org.jooq.Field; import org.jooq.QualifiedRecord; import org.jooq.RecordQualifier; @@ -112,18 +113,18 @@ abstract class AbstractQualifiedRecord> extends Abs // [#1693] This needs to return the fully qualified SQL type name, in // case the connected user is not the owner of the UDT - return getMappedUDTName(localScope(), this); + return getMappedUDTName(localExecuteContext(), this); } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public final void readSQL(SQLInput stream, String typeName) throws SQLException { - Scope scope = localScope(); + ExecuteContext ctx = localExecuteContext(); Field[] f = getQualifier().fields(); for (int i = 0; i < f.length; i++) { Field field = f[i]; - DefaultBindingGetSQLInputContext out = new DefaultBindingGetSQLInputContext(scope.configuration(), scope.data(), stream); + DefaultBindingGetSQLInputContext out = new DefaultBindingGetSQLInputContext(ctx, stream); field.getBinding().get(out); set(i, field, out.value()); } @@ -132,10 +133,10 @@ abstract class AbstractQualifiedRecord> extends Abs @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public final void writeSQL(SQLOutput stream) throws SQLException { - Scope scope = localScope(); + ExecuteContext ctx = localExecuteContext(); Field[] f = getQualifier().fields(); for (int i = 0; i < f.length; i++) - f[i].getBinding().set(new DefaultBindingSetSQLOutputContext(scope.configuration(), scope.data(), stream, get(i))); + f[i].getBinding().set(new DefaultBindingSetSQLOutputContext(ctx, stream, get(i))); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java index 4bbb7420ae..987b04a0f0 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRoutine.java @@ -1312,10 +1312,6 @@ implements - - - - @@ -1463,8 +1459,7 @@ implements { DefaultBindingGetStatementContext out = new DefaultBindingGetStatementContext<>( - ctx.configuration(), - ctx.data(), + ctx, (CallableStatement) ctx.statement(), resultIndexes.get(parameter) ); @@ -1476,17 +1471,16 @@ implements private final void registerOutParameters(ExecuteContext ctx) throws SQLException { Configuration c = ctx.configuration(); - Map data = ctx.data(); CallableStatement statement = (CallableStatement) ctx.statement(); // Register all out / inout parameters according to their position // Note that some RDBMS do not support binding by name very well for (Parameter parameter : getParameters0(ctx.configuration())) if (resultParameter(c, parameter)) - registerOutParameter(c, data, statement, parameter); + registerOutParameter(ctx, statement, parameter); } - private final void registerOutParameter(Configuration c, Map data, CallableStatement statement, Parameter parameter) throws SQLException { + private final void registerOutParameter(ExecuteContext ctx, CallableStatement statement, Parameter parameter) throws SQLException { @@ -1495,7 +1489,7 @@ implements - parameter.getBinding().register(new DefaultBindingRegisterContext<>(c, data, statement, resultIndexes.get(parameter))); + parameter.getBinding().register(new DefaultBindingRegisterContext<>(ctx, statement, resultIndexes.get(parameter))); } // ------------------------------------------------------------------------ diff --git a/jOOQ/src/main/java/org/jooq/impl/CursorImpl.java b/jOOQ/src/main/java/org/jooq/impl/CursorImpl.java index 6b4f95a8a4..b4d23d6092 100644 --- a/jOOQ/src/main/java/org/jooq/impl/CursorImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/CursorImpl.java @@ -129,7 +129,7 @@ final class CursorImpl extends AbstractCursor { this.keepStatement = keepStatement; this.keepResultSet = keepResultSet; this.rs = new CursorResultSet(); - this.rsContext = new DefaultBindingGetResultSetContext<>(ctx.configuration(), ctx.data(), rs, 0); + this.rsContext = new DefaultBindingGetResultSetContext<>(ctx, rs, 0); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java index 3b7cc3bebb..5e7d18ce4d 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindContext.java @@ -60,7 +60,7 @@ final class DefaultBindContext extends AbstractBindContext { try { ((Field) field).getBinding().set( - new DefaultBindingSetStatementContext<>(configuration(), data(), stmt, nextIndex, value) + new DefaultBindingSetStatementContext<>(new SimpleExecuteContext(configuration(), data()), stmt, nextIndex, value) ); } catch (Exception e) { diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java index 4d281d71be..3c189b2603 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBinding.java @@ -88,6 +88,7 @@ import static org.jooq.impl.DefaultBinding.DefaultDoubleBinding.REQUIRES_LITERAL import static org.jooq.impl.DefaultBinding.DefaultDoubleBinding.infinity; import static org.jooq.impl.DefaultBinding.DefaultDoubleBinding.nan; import static org.jooq.impl.DefaultBinding.DefaultJSONBBinding.EMULATE_AS_BLOB; +import static org.jooq.impl.DefaultExecuteContext.localExecuteContext; import static org.jooq.impl.DefaultExecuteContext.localTargetConnection; import static org.jooq.impl.Internal.arrayType; import static org.jooq.impl.Keywords.K_ARRAY; @@ -203,6 +204,7 @@ import org.jooq.Converter; import org.jooq.Converters; import org.jooq.DataType; import org.jooq.EnumType; +import org.jooq.ExecuteScope; import org.jooq.Field; import org.jooq.JSON; import org.jooq.JSONB; @@ -1261,7 +1263,7 @@ public class DefaultBinding implements Binding { * Workarounds for the unimplemented Postgres JDBC driver features */ @SuppressWarnings("unchecked") - private static final T pgGetArray(Scope ctx, ResultSet rs, DataType dataType, int index) throws SQLException { + private static final T pgGetArray(ExecuteScope ctx, ResultSet rs, DataType dataType, int index) throws SQLException { // Get the JDBC Array and check for null. If null, that's OK Array array = null; @@ -1289,7 +1291,7 @@ public class DefaultBinding implements Binding { // Try fetching the array as a JDBC ResultSet try (ResultSet arrayRs = array.getResultSet()) { Binding binding = binding((DataType) dataType.getArrayComponentDataType()); - DefaultBindingGetResultSetContext out = new DefaultBindingGetResultSetContext<>(ctx.configuration(), ctx.data(), arrayRs, 2); + DefaultBindingGetResultSetContext out = new DefaultBindingGetResultSetContext<>(ctx.executeContext(), arrayRs, 2); while (arrayRs.next()) { binding.get(out); @@ -1507,7 +1509,6 @@ public class DefaultBinding implements Binding { - static final class DefaultBigDecimalBinding extends AbstractBinding { @@ -3552,7 +3553,7 @@ public class DefaultBinding implements Binding { if (REQUIRE_RECORD_CAST.contains(ctx.dialect()) && value != null) ctx.statement().setString(ctx.index(), PostgresUtils.toPGString(value)); else - ctx.statement().setObject(ctx.index(), value); + localExecuteContext(ctx.executeContext(), () -> { ctx.statement().setObject(ctx.index(), value); return null; }); } @SuppressWarnings({ "rawtypes", "unchecked" }) @@ -3587,7 +3588,7 @@ public class DefaultBinding implements Binding { return pgNewRecord(dataType.getType(), null, ctx.resultSet().getObject(ctx.index())); default: - return (Record) ctx.resultSet().getObject(ctx.index(), typeMap(dataType.getType(), ctx)); + return localExecuteContext(ctx.executeContext(), () -> (Record) ctx.resultSet().getObject(ctx.index(), typeMap(dataType.getType(), ctx))); } } @@ -3601,7 +3602,7 @@ public class DefaultBinding implements Binding { return pgNewRecord(dataType.getType(), null, ctx.statement().getObject(ctx.index())); default: - return (Record) ctx.statement().getObject(ctx.index(), typeMap(dataType.getType(), ctx)); + return localExecuteContext(ctx.executeContext(), () -> (Record) ctx.statement().getObject(ctx.index(), typeMap(dataType.getType(), ctx))); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetResultSetContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetResultSetContext.java index f3bfea2e85..b4a493f857 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetResultSetContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetResultSetContext.java @@ -38,26 +38,25 @@ package org.jooq.impl; import java.sql.ResultSet; -import java.util.Map; import org.jooq.BindingGetResultSetContext; -import org.jooq.Configuration; import org.jooq.Converter; +import org.jooq.ExecuteContext; import org.jooq.Field; /** * @author Lukas Eder */ -class DefaultBindingGetResultSetContext extends AbstractScope implements BindingGetResultSetContext { +class DefaultBindingGetResultSetContext extends AbstractExecuteScope implements BindingGetResultSetContext { private final ResultSet resultSet; private int index; private Field field; private U value; - DefaultBindingGetResultSetContext(Configuration configuration, Map data, ResultSet resultSet, int index) { - super(configuration, data); + DefaultBindingGetResultSetContext(ExecuteContext ctx, ResultSet resultSet, int index) { + super(ctx); this.resultSet = resultSet; this.index = index; @@ -99,7 +98,7 @@ class DefaultBindingGetResultSetContext extends AbstractScope implements Bind public final BindingGetResultSetContext convert(final Converter converter) { final DefaultBindingGetResultSetContext outer = this; - return new DefaultBindingGetResultSetContext(configuration, data, resultSet, index) { + return new DefaultBindingGetResultSetContext(ctx, resultSet, index) { @Override public void value(T v) { outer.value(converter.from(v)); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetSQLInputContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetSQLInputContext.java index 6ebb04fde0..0dab16b38f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetSQLInputContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetSQLInputContext.java @@ -38,22 +38,21 @@ package org.jooq.impl; import java.sql.SQLInput; -import java.util.Map; import org.jooq.BindingGetSQLInputContext; -import org.jooq.Configuration; import org.jooq.Converter; +import org.jooq.ExecuteContext; /** * @author Lukas Eder */ -class DefaultBindingGetSQLInputContext extends AbstractScope implements BindingGetSQLInputContext { +class DefaultBindingGetSQLInputContext extends AbstractExecuteScope implements BindingGetSQLInputContext { private final SQLInput input; private U value; - DefaultBindingGetSQLInputContext(Configuration configuration, Map data, SQLInput input) { - super(configuration, data); + DefaultBindingGetSQLInputContext(ExecuteContext ctx, SQLInput input) { + super(ctx); this.input = input; } @@ -76,7 +75,7 @@ class DefaultBindingGetSQLInputContext extends AbstractScope implements Bindi public final BindingGetSQLInputContext convert(final Converter converter) { final DefaultBindingGetSQLInputContext outer = this; - return new DefaultBindingGetSQLInputContext(configuration, data, input) { + return new DefaultBindingGetSQLInputContext(ctx, input) { @Override public void value(T v) { outer.value(converter.from(v)); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetStatementContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetStatementContext.java index 1a6e9e6003..8d77e76416 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetStatementContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingGetStatementContext.java @@ -38,23 +38,22 @@ package org.jooq.impl; import java.sql.CallableStatement; -import java.util.Map; import org.jooq.BindingGetStatementContext; -import org.jooq.Configuration; import org.jooq.Converter; +import org.jooq.ExecuteContext; /** * @author Lukas Eder */ -class DefaultBindingGetStatementContext extends AbstractScope implements BindingGetStatementContext { +class DefaultBindingGetStatementContext extends AbstractExecuteScope implements BindingGetStatementContext { private final CallableStatement statement; private final int index; private U value; - DefaultBindingGetStatementContext(Configuration configuration, Map data, CallableStatement statement, int index) { - super(configuration, data); + DefaultBindingGetStatementContext(ExecuteContext ctx, CallableStatement statement, int index) { + super(ctx); this.statement = statement; this.index = index; @@ -83,7 +82,7 @@ class DefaultBindingGetStatementContext extends AbstractScope implements Bind public final BindingGetStatementContext convert(final Converter converter) { final DefaultBindingGetStatementContext outer = this; - return new DefaultBindingGetStatementContext(configuration, data, statement, index) { + return new DefaultBindingGetStatementContext(ctx, statement, index) { @Override public void value(T v) { outer.value(converter.from(v)); diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingRegisterContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingRegisterContext.java index b74d6ae1b5..f3ff98451a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingRegisterContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingRegisterContext.java @@ -38,22 +38,21 @@ package org.jooq.impl; import java.sql.CallableStatement; -import java.util.Map; import org.jooq.BindingRegisterContext; -import org.jooq.Configuration; import org.jooq.Converter; +import org.jooq.ExecuteContext; /** * @author Lukas Eder */ -class DefaultBindingRegisterContext extends AbstractScope implements BindingRegisterContext { +class DefaultBindingRegisterContext extends AbstractExecuteScope implements BindingRegisterContext { private final CallableStatement statement; private final int index; - DefaultBindingRegisterContext(Configuration configuration, Map data, CallableStatement statement, int index) { - super(configuration, data); + DefaultBindingRegisterContext(ExecuteContext ctx, CallableStatement statement, int index) { + super(ctx); this.statement = statement; this.index = index; @@ -71,7 +70,7 @@ class DefaultBindingRegisterContext extends AbstractScope implements BindingR @Override public final BindingRegisterContext convert(Converter converter) { - return new DefaultBindingRegisterContext<>(configuration, data, statement, index); + return new DefaultBindingRegisterContext<>(ctx, statement, index); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingSetSQLOutputContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingSetSQLOutputContext.java index dc30f6a18a..6cdc20780b 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingSetSQLOutputContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingSetSQLOutputContext.java @@ -38,22 +38,21 @@ package org.jooq.impl; import java.sql.SQLOutput; -import java.util.Map; import org.jooq.BindingSetSQLOutputContext; -import org.jooq.Configuration; import org.jooq.Converter; +import org.jooq.ExecuteContext; /** * @author Lukas Eder */ -class DefaultBindingSetSQLOutputContext extends AbstractResourceManagingScope implements BindingSetSQLOutputContext { +class DefaultBindingSetSQLOutputContext extends AbstractExecuteScope implements BindingSetSQLOutputContext, ResourceManagingScopeTrait { private final SQLOutput output; private final U value; - DefaultBindingSetSQLOutputContext(Configuration configuration, Map data, SQLOutput output, U value) { - super(configuration, data); + DefaultBindingSetSQLOutputContext(ExecuteContext ctx, SQLOutput output, U value) { + super(ctx); this.output = output; this.value = value; @@ -71,7 +70,7 @@ class DefaultBindingSetSQLOutputContext extends AbstractResourceManagingScope @Override public final BindingSetSQLOutputContext convert(Converter converter) { - return new DefaultBindingSetSQLOutputContext<>(configuration, data, output, converter.to(value)); + return new DefaultBindingSetSQLOutputContext<>(ctx, output, converter.to(value)); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingSetStatementContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingSetStatementContext.java index c3e843df7c..de8a632c2f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultBindingSetStatementContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultBindingSetStatementContext.java @@ -38,23 +38,22 @@ package org.jooq.impl; import java.sql.PreparedStatement; -import java.util.Map; import org.jooq.BindingSetStatementContext; -import org.jooq.Configuration; import org.jooq.Converter; +import org.jooq.ExecuteContext; /** * @author Lukas Eder */ -class DefaultBindingSetStatementContext extends AbstractResourceManagingScope implements BindingSetStatementContext { +class DefaultBindingSetStatementContext extends AbstractExecuteScope implements BindingSetStatementContext, ResourceManagingScopeTrait { private final PreparedStatement statement; private final int index; private final U value; - DefaultBindingSetStatementContext(Configuration configuration, Map data, PreparedStatement statement, int index, U value) { - super(configuration, data); + DefaultBindingSetStatementContext(ExecuteContext ctx, PreparedStatement statement, int index, U value) { + super(ctx); this.statement = statement; this.index = index; @@ -78,7 +77,7 @@ class DefaultBindingSetStatementContext extends AbstractResourceManagingScope @Override public final BindingSetStatementContext convert(Converter converter) { - return new DefaultBindingSetStatementContext<>(configuration, data, statement, index, converter.to(value)); + return new DefaultBindingSetStatementContext<>(ctx, statement, index, converter.to(value)); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java index dafb70369d..56b33c6ac5 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultExecuteContext.java @@ -169,7 +169,6 @@ class DefaultExecuteContext implements ExecuteContext { RESOURCES.remove(); } - LOCAL_SCOPE.remove(); LOCAL_CONNECTION.remove(); } @@ -219,17 +218,39 @@ class DefaultExecuteContext implements ExecuteContext { // XXX: Static utility methods for handling Configuration lifecycle // ------------------------------------------------------------------------ - private static final ThreadLocal LOCAL_SCOPE = new ThreadLocal<>(); + private static final ThreadLocal LOCAL_EXECUTE_CONTEXT = new ThreadLocal<>(); /** - * Get the registered scope. + * Get the registered {@link ExecuteContext}. *

* It can be safely assumed that such a configuration is available once the * {@link ExecuteContext} has been established, until the statement is * closed. */ - static final Scope localScope() { - return LOCAL_SCOPE.get(); + static final ExecuteContext localExecuteContext() { + return LOCAL_EXECUTE_CONTEXT.get(); + } + + /** + * Run a runnable with a new {@link #localExecuteContext()}. + */ + static final void localExecuteContext(ExecuteContext ctx, ThrowingRunnable runnable) throws E { + localExecuteContext(ctx, () -> { runnable.run(); return null; }); + } + + /** + * Run a supplier with a new {@link #localExecuteContext()}. + */ + static final T localExecuteContext(ExecuteContext ctx, ThrowingSupplier supplier) throws E { + ExecuteContext old = localExecuteContext(); + + try { + LOCAL_EXECUTE_CONTEXT.set(ctx); + return supplier.get(); + } + finally { + LOCAL_EXECUTE_CONTEXT.set(old); + } } // ------------------------------------------------------------------------ @@ -339,7 +360,6 @@ class DefaultExecuteContext implements ExecuteContext { } clean(); - LOCAL_SCOPE.set(this); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/R2DBC.java b/jOOQ/src/main/java/org/jooq/impl/R2DBC.java index 02b1010087..6f37983a7c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/R2DBC.java +++ b/jOOQ/src/main/java/org/jooq/impl/R2DBC.java @@ -313,9 +313,8 @@ final class R2DBC { return (R) delegate.operate(record -> { // TODO: What data to pass here? - DefaultBindingGetResultSetContext ctx = new DefaultBindingGetResultSetContext<>( - query.configuration(), - query.configuration().data(), + DefaultBindingGetResultSetContext ctx = new DefaultBindingGetResultSetContext( + new SimpleExecuteContext(query.configuration(), query.configuration().data()), new R2DBCResultSet(query.configuration(), row, meta), 0 ); diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResourceManagingScope.java b/jOOQ/src/main/java/org/jooq/impl/ResourceManagingScopeTrait.java similarity index 73% rename from jOOQ/src/main/java/org/jooq/impl/AbstractResourceManagingScope.java rename to jOOQ/src/main/java/org/jooq/impl/ResourceManagingScopeTrait.java index 5a84068334..cdcc36b4b8 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractResourceManagingScope.java +++ b/jOOQ/src/main/java/org/jooq/impl/ResourceManagingScopeTrait.java @@ -42,60 +42,50 @@ import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.SQLXML; -import java.util.Map; -import org.jooq.Configuration; import org.jooq.ResourceManagingScope; /** * @author Lukas Eder */ -abstract class AbstractResourceManagingScope extends AbstractScope implements ResourceManagingScope { - - AbstractResourceManagingScope(Configuration configuration) { - super(configuration); - } - - AbstractResourceManagingScope(Configuration configuration, Map data) { - super(configuration, data); - } +interface ResourceManagingScopeTrait extends ResourceManagingScope { // ------------------------------------------------------------------------ // XXX ResourceManagingScope API // ------------------------------------------------------------------------ @Override - public final Array autoFree(Array array) { + default Array autoFree(Array array) { DefaultExecuteContext.register(array); return array; } @Override - public final Blob autoFree(Blob blob) { + default Blob autoFree(Blob blob) { DefaultExecuteContext.register(blob); return blob; } @Override - public final Clob autoFree(Clob clob) { + default Clob autoFree(Clob clob) { DefaultExecuteContext.register(clob); return clob; } @Override - public final SQLXML autoFree(SQLXML xml) { + default SQLXML autoFree(SQLXML xml) { DefaultExecuteContext.register(xml); return xml; } @Override - public final R autoClose(R closeable) { + default R autoClose(R closeable) { DefaultExecuteContext.register(closeable); return closeable; } @Override - public final R autoClose(R closeable) { + default R autoClose(R closeable) { DefaultExecuteContext.register(closeable); return closeable; } diff --git a/jOOQ/src/main/java/org/jooq/impl/SimpleExecuteContext.java b/jOOQ/src/main/java/org/jooq/impl/SimpleExecuteContext.java new file mode 100644 index 0000000000..4976844a59 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/SimpleExecuteContext.java @@ -0,0 +1,208 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Other licenses: + * ----------------------------------------------------------------------------- + * Commercial licenses for this work are available. These replace the above + * ASL 2.0 and offer limited warranties, support, maintenance, and commercial + * database integrations. + * + * For more information, please visit: http://www.jooq.org/licenses + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ +package org.jooq.impl; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.util.Map; + +import org.jooq.Configuration; +import org.jooq.ConnectionProvider; +import org.jooq.DSLContext; +import org.jooq.ExecuteContext; +import org.jooq.ExecuteType; +import org.jooq.Query; +import org.jooq.Record; +import org.jooq.Result; +import org.jooq.Routine; +import org.jooq.SQLDialect; +import org.jooq.conf.Settings; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A simple implementation of {@link ExecuteContext} containing + * {@link #configuration()} and {@link #data()} where no actual context is + * available. + * + * @author Lukas Eder + */ +final class SimpleExecuteContext extends AbstractScope implements ExecuteContext { + + SimpleExecuteContext(Configuration configuration, Map data) { + super(configuration, data); + } + + @Override + public final Connection connection() { + return null; + } + + @Override + public final ExecuteType type() { + return null; + } + + @Override + public final Query query() { + return null; + } + + @Override + public final Query[] batchQueries() { + return null; + } + + @Override + public final Routine routine() { + return null; + } + + @Override + public final String sql() { + return null; + } + + @Override + public final void sql(String sql) { + } + + @Override + public final String[] batchSQL() { + return null; + } + + @Override + public final void connectionProvider(ConnectionProvider connectionProvider) { + } + + @Override + public final PreparedStatement statement() { + return null; + } + + @Override + public final void statement(PreparedStatement statement) { + } + + @Override + public final int statementExecutionCount() { + return 0; + } + + @Override + public final ResultSet resultSet() { + return null; + } + + @Override + public final void resultSet(ResultSet resultSet) { + } + + @Override + public final Record record() { + return null; + } + + @Override + public final void record(Record record) { + } + + @Override + public final int rows() { + return 0; + } + + @Override + public final void rows(int rows) { + } + + @Override + public final int [] batchRows() { + return null; + } + + @Override + public final Result result() { + return null; + } + + @Override + public final void result(Result result) { + } + + @Override + public final RuntimeException exception() { + return null; + } + + @Override + public final void exception(RuntimeException e) { + } + + @Override + public final SQLException sqlException() { + return null; + } + + @Override + public final void sqlException(SQLException e) { + } + + @Override + public final SQLWarning sqlWarning() { + return null; + } + + @Override + public final void sqlWarning(SQLWarning e) { + } + + @Override + public final String[] serverOutput() { + return null; + } + + @Override + public final void serverOutput(String[] output) { + } +}