iface) throws SQLException {
return iface.cast(this);
}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/ConditionallyCloseableConnection.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/ConditionallyCloseableConnection.java
index 7a0889268d9..91ba7b95e89 100644
--- a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/ConditionallyCloseableConnection.java
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/ConditionallyCloseableConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,24 +15,48 @@
*/
package io.helidon.integrations.jdbc;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
import java.sql.SQLException;
+import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.ShardingKey;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
/**
- * A {@link DelegatingConnection} whose {@link #close()} method
- * performs a close only if the {@link #isCloseable()} method returns
- * {@code true}.
+ * A JDBC
+ * 4.3-compliant {@link DelegatingConnection} whose {@link #close()} method may or may not close it depending on
+ * other partial state.
*
* Thread Safety
*
- * Instances of this class are not necessarily safe for concurrent
- * use by multiple threads.
+ * Instances of this class are not necessarily safe for concurrent use by multiple threads because their {@link
+ * Connection} delegates may not be. JDBC 4.3 does not require thread safety from any JDBC construct.
+ *
+ * @see #isClosed()
*
* @see #isCloseable()
*
* @see #setCloseable(boolean)
*
* @see #close()
+ *
+ * @see #isClosePending()
+ *
+ * @see #ConditionallyCloseableConnection(Connection, boolean, boolean)
*/
public class ConditionallyCloseableConnection extends DelegatingConnection {
@@ -43,14 +67,55 @@ public class ConditionallyCloseableConnection extends DelegatingConnection {
/**
- * Whether or not the {@link #close()} method will actually close
- * this {@link DelegatingConnection}.
+ * A {@link SQLRunnable} representing the logic run by the {@link #checkOpen()} method.
+ *
+ * This field is never {@code null}.
+ *
+ * This field is set based on the value of the {@code strictClosedChecking} argument supplied to the {@link
+ * #ConditionallyCloseableConnection(Connection, boolean, boolean)} constructor. It may end up deliberately doing
+ * nothing.
+ *
+ * @see #ConditionallyCloseableConnection(Connection, boolean, boolean)
+ */
+ private final SQLRunnable closedChecker;
+
+ /**
+ * A {@link SQLBooleanSupplier} that is the effective body of the {@link #isClosed()} method.
+ *
+ * This field is never {@code null}.
+ *
+ * This field is set based on the value of the {@code strictClosedChecking} argument supplied to the {@link
+ * #ConditionallyCloseableConnection(Connection, boolean, boolean)} constructor.
+ *
+ * @see #isClosed()
+ *
+ * @see #ConditionallyCloseableConnection(Connection, boolean, boolean)
+ */
+ private SQLBooleanSupplier isClosedFunction;
+
+ /**
+ * Whether or not the {@link #close()} method will actually close this {@link DelegatingConnection}.
+ *
+ *
This field is set based on the value of the {@code strictClosedChecking} argument supplied to the {@link
+ * #ConditionallyCloseableConnection(Connection, boolean, boolean)} constructor. It may end up deliberately doing
+ * nothing.
*
* @see #isCloseable()
*
* @see #setCloseable(boolean)
+ *
+ * @see #ConditionallyCloseableConnection(Connection, boolean, boolean)
*/
- private boolean closeable;
+ private volatile boolean closeable;
+
+ /**
+ * Whether or not a {@link #close()} request has been issued from another thread.
+ *
+ * @see #isClosePending()
+ *
+ * @see #isClosed()
+ */
+ private volatile boolean closePending;
/*
@@ -59,44 +124,93 @@ public class ConditionallyCloseableConnection extends DelegatingConnection {
/**
- * Creates a new {@link ConditionallyCloseableConnection} and
- * {@linkplain #setCloseable(boolean) sets its closeable status to
- * true
}.
+ * Creates a new {@link ConditionallyCloseableConnection} and {@linkplain #setCloseable(boolean) sets its closeable
+ * status to true
}.
*
- * @param delegate the {@link Connection} to wrap; must not be
- * {@code null}
+ * @param delegate the {@link Connection} to wrap; must not be {@code null}
*
- * @exception NullPointerException if {@code delegate} is {@code
- * null}
+ * @exception NullPointerException if {@code delegate} is {@code null}
*
- * @see #ConditionallyCloseableConnection(Connection, boolean)
+ * @see #ConditionallyCloseableConnection(Connection, boolean, boolean)
*
- * @see #setCloseable(boolean)
+ * @deprecated This constructor continues to exist for backwards compatibility only and its use is strongly
+ * discouraged. Please use the {@link #ConditionallyCloseableConnection(Connection, boolean, boolean)}
+ * constructor instead and consider supplying {@code true} for its {@code strictClosedChecking}
+ * parameter. In the future, this constructor may change, without prior notice, to cause new {@link
+ * ConditionallyCloseableConnection} instances created by it to behave as if they were created by invocations of the
+ * {@link #ConditionallyCloseableConnection(Connection, boolean, boolean)} constructor instead, with {@code true}
+ * supplied for its {@code strictClosedChecking} parameter.
+ */
+ @Deprecated(since = "3.0.3")
+ public ConditionallyCloseableConnection(Connection delegate) {
+ this(delegate, true, false);
+ }
+
+ /**
+ * Creates a new {@link ConditionallyCloseableConnection}.
+ *
+ * @param delegate the {@link Connection} to wrap; must not be {@code null}
+ *
+ * @param closeable the initial value for this {@link ConditionallyCloseableConnection}'s {@linkplain #isCloseable()
+ * closeable} status
+ *
+ * @exception NullPointerException if {@code delegate} is {@code null}
+ *
+ * @see ConditionallyCloseableConnection(Connection, boolean, boolean)
+ *
+ * @deprecated This constructor continues to exist for backwards compatibility only and its use is strongly
+ * discouraged. Please use the {@link #ConditionallyCloseableConnection(Connection, boolean, boolean)}
+ * constructor instead and consider supplying {@code true} for its {@code strictClosedChecking}
+ * parameter. In the future, this constructor may change, without prior notice, to cause new {@link
+ * ConditionallyCloseableConnection} instances created by it to behave as if they were created by invocations of the
+ * {@link #ConditionallyCloseableConnection(Connection, boolean, boolean)} constructor instead, with {@code true}
+ * supplied for its {@code strictClosedChecking} parameter.
*/
- public ConditionallyCloseableConnection(final Connection delegate) {
- this(delegate, true);
+ @Deprecated(since = "3.0.3")
+ public ConditionallyCloseableConnection(Connection delegate, boolean closeable) {
+ this(delegate, closeable, false);
}
/**
* Creates a new {@link ConditionallyCloseableConnection}.
*
- * @param delegate the {@link Connection} to wrap; must not be
- * {@code null}
+ * @param delegate the {@link Connection} to wrap; must not be {@code null}
*
- * @param closeable the initial value for this {@link
- * ConditionallyCloseableConnection}'s {@linkplain #isCloseable()
+ * @param closeable the initial value for this {@link ConditionallyCloseableConnection}'s {@linkplain #isCloseable()
* closeable} status
*
- * @exception NullPointerException if {@code delegate} is {@code
- * null}
+ * @param strictClosedChecking if {@code true}, then this {@link ConditionallyCloseableConnection}'s {@link
+ * #isClosed()} method will be invoked before every operation that cannot take place on a closed connection, and, if
+ * it returns {@code true}, the operation in question will fail with a {@link SQLException}; it is strongly
+ * recommended to supply {@code true} as the argument for this parameter ({@code false} is permitted for
+ * backwards compatibility reasons only)
+ *
+ * @exception NullPointerException if {@code delegate} is {@code null}
+ *
+ * @see #isCloseable()
*
* @see #setCloseable(boolean)
*
+ * @see #close()
+ *
+ * @see #isClosed()
+ *
+ * @see #isClosePending()
+ *
* @see DelegatingConnection#DelegatingConnection(Connection)
*/
- public ConditionallyCloseableConnection(final Connection delegate, final boolean closeable) {
+ public ConditionallyCloseableConnection(Connection delegate,
+ boolean closeable,
+ boolean strictClosedChecking) {
super(delegate);
- this.setCloseable(closeable);
+ if (strictClosedChecking) {
+ this.closedChecker = this::failWhenClosed;
+ this.isClosedFunction = () -> this.isClosePending() || super.isClosed();
+ } else {
+ this.closedChecker = ConditionallyCloseableConnection::doNothing;
+ this.isClosedFunction = super::isClosed;
+ }
+ this.closeable = closeable;
}
@@ -106,74 +220,650 @@ public ConditionallyCloseableConnection(final Connection delegate, final boolean
/**
- * Overrides the {@link DelegatingConnection#close()} method so
- * that when it is invoked this {@link
- * ConditionallyCloseableConnection} is {@linkplain
- * Connection#close() closed} only if it {@linkplain
- * #isCloseable() is closeable}.
+ * Overrides the {@link DelegatingConnection#close()} method so that when it is invoked this {@link
+ * ConditionallyCloseableConnection} is {@linkplain Connection#close() closed} only if it {@linkplain #isCloseable()
+ * is closeable}.
+ *
+ * Subclasses that override this method must not directly or indirectly call {@link #failWhenClosed()} or
+ * undefined behavior may result.
+ *
+ * If {@code strictClosedChecking} was {@code true} {@linkplain #ConditionallyCloseableConnection(Connection,
+ * boolean, boolean) at construction time} (strongly recommended), then the following pre- and post-conditions
+ * apply:
*
- * Overrides should normally call {@code super.close()} as part
- * of their implementation.
+ *
If {@link #isCloseable()} returns {@code true} at the point of an invocation of this method, then after this
+ * method completes, successfully or not, {@link #isClosePending()} will return {@code false}.
+ *
+ * If {@link #isCloseable()} returns {@code false} at the point of an invocation of this method, then after this
+ * method completes, successfully or not, {@link #isClosePending()} will return {@code true}.
+ *
+ * Overrides should normally call {@code super.close()} as part of their implementation.
*
* @exception SQLException if an error occurs
*
+ * @see #isClosed()
+ *
* @see #isCloseable()
+ *
+ * @see #setCloseable(boolean)
+ *
+ * @see #isClosePending()
*/
- @Override
+ @Override // DelegatingConnection
public void close() throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
if (this.isCloseable()) {
- super.close();
+ try {
+ super.close();
+ } finally {
+ this.closePending = false;
+ this.onClose();
+ }
+ } else {
+ this.closePending = true;
}
}
/**
- * Returns {@code true} if a call to {@link #close()} will
- * actually close this {@link ConditionallyCloseableConnection}.
+ * Called by the {@link #close()} method to perform work after an actual close operation has completed.
+ *
+ * During an invocation of this method by the {@link #close()} method:
+ *
+ *
+ *
+ * - The {@link #isClosed()} method will return {@code true}.
+ *
+ * - The {@link #isCloseable()} method will return {@code false}.
+ *
+ * - The {@link #isClosePending()} method will return {@code false}.
+ *
+ *
*
- * This method returns {@code true} when {@link
- * #setCloseable(boolean)} has been called with a value of {@code
- * true} and the {@link #isClosed()} method returns {@code
- * false}.
+ * The default implementation of this method does nothing.
*
- * @return {@code true} if a call to {@link #close()} will
- * actually close this {@link ConditionallyCloseableConnection};
- * {@code false} in all other cases
+ * Invoking this method directly may result in undefined behavior, depending on how it is overridden.
*
- * @exception SQLException if {@link #isClosed()} throws a {@link
- * SQLException}
+ * Overrides of this method must not call {@link #close()} or undefined behavior, such as an infinite loop, may
+ * result.
+ *
+ * Overrides of this method must be idempotent.
+ *
+ * @exception SQLException if a database error occurs
+ *
+ * @see #isClosed()
+ *
+ * @see #isCloseable()
*
* @see #setCloseable(boolean)
*
+ * @see #isClosePending()
+ *
* @see #close()
+ */
+ protected void onClose() throws SQLException {
+
+ }
+
+ /**
+ * Returns {@code true} if a call to {@link #close()} will actually close this {@link
+ * ConditionallyCloseableConnection}.
+ *
+ * This method returns {@code true} when {@link #setCloseable(boolean)} has been called with a value of {@code
+ * true} and the {@link #isClosed()} method returns {@code false}.
+ *
+ * Subclasses that override this method must not directly or indirectly call {@link #failWhenClosed()} or
+ * undefined behavior may result.
+ *
+ * @return {@code true} if a call to {@link #close()} will actually close this {@link
+ * ConditionallyCloseableConnection}; {@code false} in all other cases
+ *
+ * @exception SQLException if {@link #isClosed()} throws a {@link SQLException}
*
* @see #isClosed()
+ *
+ * @see #setCloseable(boolean)
+ *
+ * @see #close()
+ *
+ * @see #isClosePending()
*/
- public final boolean isCloseable() throws SQLException {
+ public boolean isCloseable() throws SQLException {
+ // this.checkOpen(); // Deliberately omitted.
return this.closeable && !this.isClosed();
}
/**
- * Sets the closeable status of this {@link
- * ConditionallyCloseableConnection}.
+ * Sets the closeable status of this {@link ConditionallyCloseableConnection} and, if the supplied {@code closeable}
+ * agrument is {@code true}, sets the {@linkplain #isClosePending() close pending status} to {@code false}.
+ *
+ * Subclasses that override this method must not directly or indirectly call {@link #failWhenClosed()} or
+ * undefined behavior may result.
+ *
+ * Note that calling this method with a value of {@code true} does not necessarily mean that the {@link
+ * #isCloseable()} method will subsequently return {@code true}, since the {@link #isClosed()} method may return
+ * {@code true}.
+ *
+ * Design Note
*
- * Note that calling this method with a value of {@code true}
- * does not necessarily mean that the {@link #isCloseable()}
- * method will subsequently return {@code true}, since the {@link
- * #isClosed()} method may return {@code true}.
+ * This method does not throw {@link SQLException} only because of an oversight in the design of the original
+ * version of this class. Callers should consider catching {@link UncheckedSQLException} where appropriate
+ * instead. The default implementation of this method does not throw any exceptions of any kind.
*
- * @param closeable whether or not a call to {@link #close()} will
- * actually close this {@link ConditionallyCloseableConnection}
+ * @param closeable whether or not a call to {@link #close()} will actually close this {@link
+ * ConditionallyCloseableConnection}
+ *
+ * @see #isClosed()
*
* @see #isCloseable()
*
* @see #close()
*
+ * @see #isClosePending()
+ *
* @see Connection#close()
+ */
+ public void setCloseable(boolean closeable) {
+ // this.checkOpen(); // Deliberately omitted.
+ this.closeable = closeable;
+ if (closeable) {
+ this.closePending = false;
+ }
+ }
+
+ /**
+ * Returns {@code true} if and only if this {@link ConditionallyCloseableConnection} is behaving as if the {@link
+ * #close()} method has been invoked while this {@link ConditionallyCloseableConnection} was {@linkplain
+ * #isCloseable() not closeable}.
+ *
+ * Subclasses that override this method must not directly or indirectly call {@link #failWhenClosed()} or
+ * undefined behavior may result.
+ *
+ * Subclasses that override this method must not directly or indirectly mutate the state of this {@link
+ * ConditionallyCloseableConnection} or undefined behavior may result.
+ *
+ * @return {@code true} if and only if a close operation is pending
*
* @see #isClosed()
+ *
+ * @see #isCloseable()
+ *
+ * @see #setCloseable(boolean)
+ *
+ * @see #close()
*/
- public final void setCloseable(final boolean closeable) {
- this.closeable = closeable;
+ public boolean isClosePending() {
+ // this.checkOpen(); // Deliberately omitted.
+ return this.closePending;
+ }
+
+ @Override // DelegatingConnection
+ public Statement createStatement() throws SQLException {
+ this.checkOpen();
+ return super.createStatement();
+ }
+
+ @Override // DelegatingConnection
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ this.checkOpen();
+ return super.prepareStatement(sql);
+ }
+
+ @Override // DelegatingConnection
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ this.checkOpen();
+ return super.prepareCall(sql);
+ }
+
+ @Override // DelegatingConnection
+ public String nativeSQL(String sql) throws SQLException {
+ this.checkOpen();
+ return super.nativeSQL(sql);
+ }
+
+ @Override // DelegatingConnection
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ this.checkOpen();
+ super.setAutoCommit(autoCommit);
+ }
+
+ @Override // DelegatingConnection
+ public boolean getAutoCommit() throws SQLException {
+ this.checkOpen();
+ return super.getAutoCommit();
+ }
+
+ @Override // DelegatingConnection
+ public void commit() throws SQLException {
+ this.checkOpen();
+ super.commit();
+ }
+
+ @Override // DelegatingConnection
+ public void rollback() throws SQLException {
+ this.checkOpen();
+ super.rollback();
+ }
+
+ /**
+ * Returns {@code true} if and only if this {@link ConditionallyCloseableConnection} either is, or is to be
+ * considered to be, closed, such that operations which must throw a {@link SQLException} when invoked on a closed
+ * connection will do so.
+ *
+ * If {@code true} was supplied for the {@code strictClosedChecking} parameter {@linkplain
+ * #ConditionallyCloseableConnection(Connection, boolean, boolean) at construction time} (strongly recommended), the
+ * default implementation of this method returns a value as if produced by the following implementation: {@code
+ * this.}{@link #isClosePending() isClosePending() }{@code || super.isClosed()}.
+ *
+ * If {@code false} was supplied for the {@code strictClosedChecking} parameter {@linkplain
+ * #ConditionallyCloseableConnection(Connection, boolean, boolean) at construction time} (not recommended), the
+ * default implementation of this method returns a value as if produced by the following implementation: {@code
+ * super.isClosed()}.
+ *
+ * Subclasses that override this method must not directly or indirectly call {@link #failWhenClosed()} or
+ * undefined behavior may result.
+ *
+ * @return {@code true} if and only if this {@link ConditionallyCloseableConnection} either is, or is to be
+ * considered to be, closed
+ *
+ * @exception SQLException if a database access error occurs
+ *
+ * @see #isCloseable()
+ *
+ * @see #setCloseable(boolean)
+ *
+ * @see #close()
+ *
+ * @see #isClosePending()
+ */
+ @Override // DelegatingConnection
+ public boolean isClosed() throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec (and common sense).
+ return this.isClosedFunction.getAsBoolean();
+ }
+
+ @Override // DelegatingConnection
+ public DatabaseMetaData getMetaData() throws SQLException {
+ this.checkOpen();
+ return super.getMetaData();
+ }
+
+ @Override // DelegatingConnection
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ this.checkOpen();
+ super.setReadOnly(readOnly);
+ }
+
+ @Override // DelegatingConnection
+ public boolean isReadOnly() throws SQLException {
+ this.checkOpen();
+ return super.isReadOnly();
+ }
+
+ @Override // DelegatingConnection
+ public void setCatalog(String catalog) throws SQLException {
+ this.checkOpen();
+ super.setCatalog(catalog);
+ }
+
+ @Override // DelegatingConnection
+ public String getCatalog() throws SQLException {
+ this.checkOpen();
+ return super.getCatalog();
+ }
+
+ @Override // DelegatingConnection
+ public void setTransactionIsolation(int level) throws SQLException {
+ this.checkOpen();
+ super.setTransactionIsolation(level);
+ }
+
+ @Override // DelegatingConnection
+ public int getTransactionIsolation() throws SQLException {
+ this.checkOpen();
+ return super.getTransactionIsolation();
+ }
+
+ @Override // DelegatingConnection
+ public SQLWarning getWarnings() throws SQLException {
+ this.checkOpen();
+ return super.getWarnings();
+ }
+
+ @Override // DelegatingConnection
+ public void clearWarnings() throws SQLException {
+ this.checkOpen();
+ super.clearWarnings();
+ }
+
+ @Override // DelegatingConnection
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ this.checkOpen();
+ return super.createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ @Override // DelegatingConnection
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ this.checkOpen();
+ return super.prepareStatement(sql, resultSetType, resultSetConcurrency);
+ }
+
+ @Override // DelegatingConnection
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ this.checkOpen();
+ return super.prepareCall(sql, resultSetType, resultSetConcurrency);
+ }
+
+ @Override // DelegatingConnection
+ public Map> getTypeMap() throws SQLException {
+ this.checkOpen();
+ return super.getTypeMap();
+ }
+
+ @Override // DelegatingConnection
+ public void setTypeMap(Map> map) throws SQLException {
+ this.checkOpen();
+ super.setTypeMap(map);
+ }
+
+ @Override // DelegatingConnection
+ public void setHoldability(int holdability) throws SQLException {
+ this.checkOpen();
+ super.setHoldability(holdability);
+ }
+
+ @Override // DelegatingConnection
+ public int getHoldability() throws SQLException {
+ this.checkOpen();
+ return super.getHoldability();
+ }
+
+ @Override // DelegatingConnection
+ public Savepoint setSavepoint() throws SQLException {
+ this.checkOpen();
+ return super.setSavepoint();
+ }
+
+ @Override // DelegatingConnection
+ public Savepoint setSavepoint(String name) throws SQLException {
+ this.checkOpen();
+ return super.setSavepoint(name);
+ }
+
+ @Override // DelegatingConnection
+ public void rollback(Savepoint savepoint) throws SQLException {
+ this.checkOpen();
+ super.rollback(savepoint);
+ }
+
+ @Override // DelegatingConnection
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ this.checkOpen();
+ super.releaseSavepoint(savepoint);
+ }
+
+ @Override // DelegatingConnection
+ public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ this.checkOpen();
+ return super.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override // DelegatingConnection
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ this.checkOpen();
+ return super.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override // DelegatingConnection
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ this.checkOpen();
+ return super.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override // DelegatingConnection
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ this.checkOpen();
+ return super.prepareStatement(sql, autoGeneratedKeys);
+ }
+
+ @Override // DelegatingConnection
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ this.checkOpen();
+ return super.prepareStatement(sql, columnIndexes);
+ }
+
+ @Override // DelegatingConnection
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ this.checkOpen();
+ return super.prepareStatement(sql, columnNames);
+ }
+
+ @Override // DelegatingConnection
+ public Clob createClob() throws SQLException {
+ this.checkOpen();
+ return super.createClob();
+ }
+
+ @Override // DelegatingConnection
+ public Blob createBlob() throws SQLException {
+ this.checkOpen();
+ return super.createBlob();
+ }
+
+ @Override // DelegatingConnection
+ public NClob createNClob() throws SQLException {
+ this.checkOpen();
+ return super.createNClob();
+ }
+
+ @Override // DelegatingConnection
+ public SQLXML createSQLXML() throws SQLException {
+ this.checkOpen();
+ return super.createSQLXML();
+ }
+
+ @Override // DelegatingConnection
+ public boolean isValid(int timeout) throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
+ return super.isValid(timeout);
+ }
+
+ @Override // DelegatingConnection
+ public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ try {
+ this.checkOpen();
+ } catch (SQLClientInfoException e) {
+ throw e;
+ } catch (SQLException e) {
+ throw new SQLClientInfoException(e.getMessage(), e.getSQLState(), e.getErrorCode(), Map.of(), e);
+ }
+ super.setClientInfo(name, value);
+ }
+
+ @Override // DelegatingConnection
+ public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ try {
+ this.checkOpen();
+ } catch (SQLClientInfoException e) {
+ throw e;
+ } catch (SQLException e) {
+ throw new SQLClientInfoException(e.getMessage(), e.getSQLState(), e.getErrorCode(), Map.of(), e);
+ }
+ super.setClientInfo(properties);
+ }
+
+ @Override // DelegatingConnection
+ public String getClientInfo(String name) throws SQLException {
+ this.checkOpen();
+ return super.getClientInfo(name);
+ }
+
+ @Override // DelegatingConnection
+ public Properties getClientInfo() throws SQLException {
+ this.checkOpen();
+ return super.getClientInfo();
+ }
+
+ @Override // DelegatingConnection
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ this.checkOpen();
+ return super.createArrayOf(typeName, elements);
+ }
+
+ @Override // DelegatingConnection
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ this.checkOpen();
+ return super.createStruct(typeName, attributes);
+ }
+
+ @Override // DelegatingConnection
+ public void setSchema(String schema) throws SQLException {
+ this.checkOpen();
+ super.setSchema(schema);
+ }
+
+ @Override // DelegatingConnection
+ public String getSchema() throws SQLException {
+ this.checkOpen();
+ return super.getSchema();
+ }
+
+ @Override // DelegatingConnection
+ public void abort(Executor executor) throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
+ super.abort(executor);
+ }
+
+ @Override // DelegatingConnection
+ public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+ this.checkOpen();
+ super.setNetworkTimeout(executor, milliseconds);
+ }
+
+ @Override // DelegatingConnection
+ public int getNetworkTimeout() throws SQLException {
+ this.checkOpen();
+ return super.getNetworkTimeout();
+ }
+
+ @Override // DelegatingConnection
+ public void beginRequest() throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
+ super.beginRequest();
+ }
+
+ @Override // DelegatingConnection
+ public void endRequest() throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
+ super.endRequest();
+ }
+
+ @Override // DelegatingConnection
+ public boolean setShardingKeyIfValid(ShardingKey shardingKey, ShardingKey superShardingKey, int timeout)
+ throws SQLException {
+ this.checkOpen();
+ return super.setShardingKeyIfValid(shardingKey, superShardingKey, timeout);
+ }
+
+ @Override // DelegatingConnection
+ public boolean setShardingKeyIfValid(ShardingKey shardingKey, int timeout) throws SQLException {
+ this.checkOpen();
+ return super.setShardingKeyIfValid(shardingKey, timeout);
+ }
+
+ @Override // DelegatingConnection
+ public void setShardingKey(ShardingKey shardingKey, ShardingKey superShardingKey) throws SQLException {
+ this.checkOpen();
+ super.setShardingKey(shardingKey, superShardingKey);
+ }
+
+ @Override // DelegatingConnection
+ public void setShardingKey(ShardingKey shardingKey) throws SQLException {
+ this.checkOpen();
+ super.setShardingKey(shardingKey);
+ }
+
+ @Override // DelegatingConnection
+ public T unwrap(Class iface) throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
+ return super.unwrap(iface);
+ }
+
+ @Override // DelegatingConnection
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
+ return super.isWrapperFor(iface);
+ }
+
+ /**
+ * Ensures this {@link ConditionallyCloseableConnection} is {@linkplain #isClosed() not closed}, if {@linkplain
+ * #ConditionallyCloseableConnection(Connection, boolean, boolean) strict closed checking was enabled at
+ * construction time}, or simply returns if {@linkplain #ConditionallyCloseableConnection(Connection, boolean,
+ * boolean) strict closed checking was not enabled at construction time}.
+ *
+ * This method is called from almost every method in this class.
+ *
+ * @exception SQLException if this {@link ConditionallyCloseableConnection} was {@linkplain
+ * #ConditionallyCloseableConnection(Connection, boolean, boolean) created with strict closed checking enabled} and
+ * an invocation of the {@link #isClosed()} method returns {@code true}, or if some other database access error
+ * occurs
+ *
+ * @see #closedChecker
+ */
+ private void checkOpen() throws SQLException {
+ this.closedChecker.run();
+ }
+
+ /**
+ * Invokes the {@link #isClosed()} method, and, if it returns {@code true}, throws a new {@link SQLException}
+ * indicating that because the connection is closed the operation cannot proceed.
+ *
+ * If this {@link ConditionallyCloseableConnection} was {@linkplain #ConditionallyCloseableConnection(Connection,
+ * boolean, boolean) created with strict closed checking enabled} (strongly recommended), then this method will be
+ * called where appropriate. Otherwise this method is not called internally by default implementations of the
+ * methods in the {@link ConditionallyCloseableConnection} class. Subclasses may, and often will, call this method
+ * directly for any reason.
+ *
+ * @exception SQLNonTransientConnectionException when an invocation of the {@link #isClosed()} method returns {@code
+ * true}; its {@linkplain SQLException#getSQLState() SQLState} will begin with {@code 08}
+ *
+ * @exception SQLException if {@link #isClosed()} throws a {@link SQLException}
+ *
+ * @see #isClosed()
+ *
+ * @see #isCloseable()
+ *
+ * @see #setCloseable(boolean)
+ *
+ * @see #close()
+ */
+ protected final void failWhenClosed() throws SQLException {
+ if (this.isClosed()) {
+ throw new SQLNonTransientConnectionException("Connection is closed", "08000");
+ }
+ }
+
+
+ /*
+ * Static methods.
+ */
+
+
+ /**
+ * Deliberately does nothing when invoked.
+ *
+ * Used as a method reference only, and then only as a potential value for the {@link #closedChecker} field, and
+ * then only when the {@code strictClosedChecking} argument supplied to the {@link
+ * #ConditionallyCloseableConnection(Connection, boolean, boolean)} constructor was {@code false}.
+ *
+ * @see #closedChecker
+ *
+ * @see #ConditionallyCloseableConnection(Connection, boolean, boolean)
+ */
+ // (Invoked by method reference only.)
+ private static void doNothing() {
+
}
}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingCallableStatement.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingCallableStatement.java
new file mode 100644
index 00000000000..0c9560f56f2
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingCallableStatement.java
@@ -0,0 +1,808 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLType;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+
+/**
+ * A JDBC
+ * 4.3-compliant {@link CallableStatement} that delegates to another JDBC 4.3-compliant {@link CallableStatement}.
+ */
+public class DelegatingCallableStatement extends DelegatingPreparedStatement implements CallableStatement {
+
+ /**
+ * Creates a new {@link DelegatingCallableStatement}.
+ *
+ * @param connection the {@link Connection} that created this {@link DelegatingCallableStatement}; must not be
+ * {@code null}
+ *
+ * @param delegate the {@link CallableStatement} instance to which all operations will be delegated; must not be
+ * {@code null}
+ *
+ * @param closeable the initial value for this {@link DelegatingCallableStatement}'s {@linkplain #isCloseable()
+ * closeable} status
+ *
+ * @param strictClosedChecking if {@code true}, then this {@link DelegatingCallableStatement}'s {@link
+ * #isClosed()} method will be invoked before every operation that cannot take place on a closed statement, and, if
+ * it returns {@code true}, the operation in question will fail with a {@link SQLException}
+ * @exception NullPointerException if either argument is {@code
+ * null}
+ *
+ * @see DelegatingStatement#isCloseable()
+ *
+ * @see DelegatingStatement#setCloseable(boolean)
+ *
+ * @see DelegatingStatement#close()
+ *
+ * @see DelegatingStatement#isClosed()
+ *
+ * @exception NullPointerException if either {@code connection} or
+ * {@code delegate} is {@code null}
+ */
+ public DelegatingCallableStatement(Connection connection,
+ CallableStatement delegate,
+ boolean closeable,
+ boolean strictClosedChecking) {
+ super(connection, delegate, closeable, strictClosedChecking);
+ }
+
+ @Override
+ public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterIndex, sqlType);
+ }
+
+ @Override
+ public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterIndex, sqlType, scale);
+ }
+
+ @Override
+ public boolean wasNull() throws SQLException {
+ checkOpen();
+ return this.delegate().wasNull();
+ }
+
+ @Override
+ public String getString(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getString(parameterIndex);
+ }
+
+ @Override
+ public boolean getBoolean(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBoolean(parameterIndex);
+ }
+
+ @Override
+ public byte getByte(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getByte(parameterIndex);
+ }
+
+ @Override
+ public short getShort(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getShort(parameterIndex);
+ }
+
+ @Override
+ public int getInt(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getInt(parameterIndex);
+ }
+
+ @Override
+ public long getLong(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getLong(parameterIndex);
+ }
+
+ @Override
+ public float getFloat(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getFloat(parameterIndex);
+ }
+
+ @Override
+ public double getDouble(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getDouble(parameterIndex);
+ }
+
+ @Deprecated
+ @Override
+ public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {
+ checkOpen();
+ return this.delegate().getBigDecimal(parameterIndex, scale);
+ }
+
+ @Override
+ public byte[] getBytes(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBytes(parameterIndex);
+ }
+
+ @Override
+ public Date getDate(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getDate(parameterIndex);
+ }
+
+ @Override
+ public Time getTime(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getTime(parameterIndex);
+ }
+
+ @Override
+ public Timestamp getTimestamp(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getTimestamp(parameterIndex);
+ }
+
+ @Override
+ public Object getObject(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(parameterIndex);
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBigDecimal(parameterIndex);
+ }
+
+ @Override
+ public Object getObject(int parameterIndex, Map> map) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(parameterIndex, map);
+ }
+
+ @Override
+ public Ref getRef(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getRef(parameterIndex);
+ }
+
+ @Override
+ public Blob getBlob(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBlob(parameterIndex);
+ }
+
+ @Override
+ public Clob getClob(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getClob(parameterIndex);
+ }
+
+ @Override
+ public Array getArray(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getArray(parameterIndex);
+ }
+
+ @Override
+ public Date getDate(int parameterIndex, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getDate(parameterIndex, cal);
+ }
+
+ @Override
+ public Time getTime(int parameterIndex, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getTime(parameterIndex, cal);
+ }
+
+ @Override
+ public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getTimestamp(parameterIndex, cal);
+ }
+
+ @Override
+ public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterIndex, sqlType, typeName);
+ }
+
+ @Override
+ public void registerOutParameter(String parameterName, int sqlType) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterName, sqlType);
+ }
+
+ @Override
+ public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterName, sqlType, scale);
+ }
+
+ @Override
+ public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterName, sqlType, typeName);
+ }
+
+ @Override
+ public URL getURL(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getURL(parameterIndex);
+ }
+
+ @Override
+ public void setURL(String parameterName, URL val) throws SQLException {
+ checkOpen();
+ this.delegate().setURL(parameterName, val);
+ }
+
+ @Override
+ public void setNull(String parameterName, int sqlType) throws SQLException {
+ checkOpen();
+ this.delegate().setNull(parameterName, sqlType);
+ }
+
+ @Override
+ public void setBoolean(String parameterName, boolean x) throws SQLException {
+ checkOpen();
+ this.delegate().setBoolean(parameterName, x);
+ }
+
+ @Override
+ public void setByte(String parameterName, byte x) throws SQLException {
+ checkOpen();
+ this.delegate().setByte(parameterName, x);
+ }
+
+ @Override
+ public void setShort(String parameterName, short x) throws SQLException {
+ checkOpen();
+ this.delegate().setShort(parameterName, x);
+ }
+
+ @Override
+ public void setInt(String parameterName, int x) throws SQLException {
+ checkOpen();
+ this.delegate().setInt(parameterName, x);
+ }
+
+ @Override
+ public void setLong(String parameterName, long x) throws SQLException {
+ checkOpen();
+ this.delegate().setLong(parameterName, x);
+ }
+
+ @Override
+ public void setFloat(String parameterName, float x) throws SQLException {
+ checkOpen();
+ this.delegate().setFloat(parameterName, x);
+ }
+
+ @Override
+ public void setDouble(String parameterName, double x) throws SQLException {
+ checkOpen();
+ this.delegate().setDouble(parameterName, x);
+ }
+
+ @Override
+ public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {
+ checkOpen();
+ this.delegate().setBigDecimal(parameterName, x);
+ }
+
+ @Override
+ public void setString(String parameterName, String x) throws SQLException {
+ checkOpen();
+ this.delegate().setString(parameterName, x);
+ }
+
+ @Override
+ public void setBytes(String parameterName, byte[] x) throws SQLException {
+ checkOpen();
+ this.delegate().setBytes(parameterName, x);
+ }
+
+ @Override
+ public void setDate(String parameterName, Date x) throws SQLException {
+ checkOpen();
+ this.delegate().setDate(parameterName, x);
+ }
+
+ @Override
+ public void setTime(String parameterName, Time x) throws SQLException {
+ checkOpen();
+ this.delegate().setTime(parameterName, x);
+ }
+
+ @Override
+ public void setTimestamp(String parameterName, Timestamp x) throws SQLException {
+ checkOpen();
+ this.delegate().setTimestamp(parameterName, x);
+ }
+
+ @Override
+ public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().setAsciiStream(parameterName, x, length);
+ }
+
+ @Override
+ public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().setBinaryStream(parameterName, x, length);
+ }
+
+ @Override
+ public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterName, x, targetSqlType, scale);
+ }
+
+ @Override
+ public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterName, x, targetSqlType);
+ }
+
+ @Override
+ public void setObject(String parameterName, Object x) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterName, x);
+ }
+
+ @Override
+ public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException {
+ checkOpen();
+ this.delegate().setCharacterStream(parameterName, reader, length);
+ }
+
+ @Override
+ public void setDate(String parameterName, Date x, Calendar cal) throws SQLException {
+ checkOpen();
+ this.delegate().setDate(parameterName, x, cal);
+ }
+
+ @Override
+ public void setTime(String parameterName, Time x, Calendar cal) throws SQLException {
+ checkOpen();
+ this.delegate().setTime(parameterName, x, cal);
+ }
+
+ @Override
+ public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException {
+ checkOpen();
+ this.delegate().setTimestamp(parameterName, x, cal);
+ }
+
+ @Override
+ public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {
+ checkOpen();
+ this.delegate().setNull(parameterName, sqlType, typeName);
+ }
+
+ @Override
+ public String getString(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getString(parameterName);
+ }
+
+ @Override
+ public boolean getBoolean(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getBoolean(parameterName);
+ }
+
+ @Override
+ public byte getByte(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getByte(parameterName);
+ }
+
+ @Override
+ public short getShort(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getShort(parameterName);
+ }
+
+ @Override
+ public int getInt(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getInt(parameterName);
+ }
+
+ @Override
+ public long getLong(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getLong(parameterName);
+ }
+
+ @Override
+ public float getFloat(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getFloat(parameterName);
+ }
+
+ @Override
+ public double getDouble(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getDouble(parameterName);
+ }
+
+ @Override
+ public byte[] getBytes(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getBytes(parameterName);
+ }
+
+ @Override
+ public Date getDate(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getDate(parameterName);
+ }
+
+ @Override
+ public Time getTime(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getTime(parameterName);
+ }
+
+ @Override
+ public Timestamp getTimestamp(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getTimestamp(parameterName);
+ }
+
+ @Override
+ public Object getObject(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(parameterName);
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getBigDecimal(parameterName);
+ }
+
+ @Override
+ public Object getObject(String parameterName, Map> map) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(parameterName, map);
+ }
+
+ @Override
+ public Ref getRef(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getRef(parameterName);
+ }
+
+ @Override
+ public Blob getBlob(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getBlob(parameterName);
+ }
+
+ @Override
+ public Clob getClob(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getClob(parameterName);
+ }
+
+ @Override
+ public Array getArray(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getArray(parameterName);
+ }
+
+ @Override
+ public Date getDate(String parameterName, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getDate(parameterName, cal);
+ }
+
+ @Override
+ public Time getTime(String parameterName, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getTime(parameterName, cal);
+ }
+
+ @Override
+ public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getTimestamp(parameterName, cal);
+ }
+
+ @Override
+ public URL getURL(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getURL(parameterName);
+ }
+
+ @Override
+ public RowId getRowId(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getRowId(parameterIndex);
+ }
+
+ @Override
+ public RowId getRowId(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getRowId(parameterName);
+ }
+
+ @Override
+ public void setRowId(String parameterName, RowId x) throws SQLException {
+ checkOpen();
+ this.delegate().setRowId(parameterName, x);
+ }
+
+ @Override
+ public void setNString(String parameterName, String value) throws SQLException {
+ checkOpen();
+ this.delegate().setNString(parameterName, value);
+ }
+
+ @Override
+ public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setNCharacterStream(parameterName, value, length);
+ }
+
+ @Override
+ public void setNClob(String parameterName, NClob value) throws SQLException {
+ checkOpen();
+ this.delegate().setNClob(parameterName, value);
+ }
+
+ @Override
+ public void setClob(String parameterName, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setClob(parameterName, reader, length);
+ }
+
+ @Override
+ public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setBlob(parameterName, inputStream, length);
+ }
+
+ @Override
+ public void setNClob(String parameterName, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setNClob(parameterName, reader, length);
+ }
+
+ @Override
+ public NClob getNClob(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getNClob(parameterIndex);
+ }
+
+ @Override
+ public NClob getNClob(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getNClob(parameterName);
+ }
+
+ @Override
+ public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
+ checkOpen();
+ this.delegate().setSQLXML(parameterName, xmlObject);
+ }
+
+ @Override
+ public SQLXML getSQLXML(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getSQLXML(parameterIndex);
+ }
+
+ @Override
+ public SQLXML getSQLXML(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getSQLXML(parameterName);
+ }
+
+ @Override
+ public String getNString(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getNString(parameterIndex);
+ }
+
+ @Override
+ public String getNString(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getNString(parameterName);
+ }
+
+ @Override
+ public Reader getNCharacterStream(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getNCharacterStream(parameterIndex);
+ }
+
+ @Override
+ public Reader getNCharacterStream(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getNCharacterStream(parameterName);
+ }
+
+ @Override
+ public Reader getCharacterStream(int parameterIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getCharacterStream(parameterIndex);
+ }
+
+ @Override
+ public Reader getCharacterStream(String parameterName) throws SQLException {
+ checkOpen();
+ return this.delegate().getCharacterStream(parameterName);
+ }
+
+ @Override
+ public void setBlob(String parameterName, Blob x) throws SQLException {
+ checkOpen();
+ this.delegate().setBlob(parameterName, x);
+ }
+
+ @Override
+ public void setClob(String parameterName, Clob x) throws SQLException {
+ checkOpen();
+ this.delegate().setClob(parameterName, x);
+ }
+
+ @Override
+ public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setAsciiStream(parameterName, x, length);
+ }
+
+ @Override
+ public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setBinaryStream(parameterName, x, length);
+ }
+
+ @Override
+ public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setCharacterStream(parameterName, reader, length);
+ }
+
+ @Override
+ public void setAsciiStream(String parameterName, InputStream x) throws SQLException {
+ checkOpen();
+ this.delegate().setAsciiStream(parameterName, x);
+ }
+
+ @Override
+ public void setBinaryStream(String parameterName, InputStream x) throws SQLException {
+ checkOpen();
+ this.delegate().setBinaryStream(parameterName, x);
+ }
+
+ @Override
+ public void setCharacterStream(String parameterName, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().setCharacterStream(parameterName, reader);
+ }
+
+ @Override
+ public void setNCharacterStream(String parameterName, Reader value) throws SQLException {
+ checkOpen();
+ this.delegate().setNCharacterStream(parameterName, value);
+ }
+
+ @Override
+ public void setClob(String parameterName, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().setClob(parameterName, reader);
+ }
+
+ @Override
+ public void setBlob(String parameterName, InputStream inputStream) throws SQLException {
+ checkOpen();
+ this.delegate().setBlob(parameterName, inputStream);
+ }
+
+ @Override
+ public void setNClob(String parameterName, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().setNClob(parameterName, reader);
+ }
+
+ @Override
+ public T getObject(int parameterIndex, Class type) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(parameterIndex, type);
+ }
+
+ @Override
+ public T getObject(String parameterName, Class type) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(parameterName, type);
+ }
+
+ @Override
+ public void setObject(String parameterName, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterName, x, targetSqlType, scaleOrLength);
+ }
+
+ @Override
+ public void setObject(String parameterName, Object x, SQLType targetSqlType) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterName, x, targetSqlType);
+ }
+
+ @Override
+ public void registerOutParameter(int parameterIndex, SQLType sqlType) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterIndex, sqlType);
+ }
+
+ @Override
+ public void registerOutParameter(int parameterIndex, SQLType sqlType, int scale) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterIndex, sqlType, scale);
+ }
+
+ @Override
+ public void registerOutParameter(int parameterIndex, SQLType sqlType, String typeName) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterIndex, sqlType, typeName);
+ }
+
+ @Override
+ public void registerOutParameter(String parameterName, SQLType sqlType) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterName, sqlType);
+ }
+
+ @Override
+ public void registerOutParameter(String parameterName, SQLType sqlType, int scale) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterName, sqlType, scale);
+ }
+
+ @Override
+ public void registerOutParameter(String parameterName, SQLType sqlType, String typeName) throws SQLException {
+ checkOpen();
+ this.delegate().registerOutParameter(parameterName, sqlType, typeName);
+ }
+
+}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingConnection.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingConnection.java
index 913f61d8631..14b8b242157 100644
--- a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingConnection.java
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,334 +37,399 @@
import java.util.concurrent.Executor;
/**
- * A {@link Connection} that delegates to another {@link Connection}.
+ * A JDBC
+ * 4.3-compliant {@link Connection} that delegates to another JDBC 4.3-compliant {@link Connection}.
*/
public class DelegatingConnection implements Connection {
private final Connection delegate;
- protected DelegatingConnection(final Connection delegate) {
+ /**
+ * Creates a new {@link DelegatingConnection}.
+ *
+ * @param delegate the {@link Connection} to which all operations will be delegated; must not be {@code null}
+ *
+ * @exception NullPointerException if {@code delegate} is {@code null}
+ */
+ public DelegatingConnection(Connection delegate) {
super();
- this.delegate = Objects.requireNonNull(delegate);
+ this.delegate = Objects.requireNonNull(delegate, "delegate");
+ }
+
+ /**
+ * Returns this {@link DelegatingConnection}'s underlying {@link Connection}.
+ *
+ * This method never returns {@code null}.
+ *
+ * @return this {@link DelegatingConnection}'s underlying {@link Connection}; never {@code null}
+ */
+ public final Connection delegate() {
+ return this.delegate;
}
@Override
public Statement createStatement() throws SQLException {
- return this.delegate.createStatement();
+ return
+ new DelegatingStatement<>(this, // NOTE
+ this.delegate().createStatement(),
+ true,
+ true);
}
@Override
- public PreparedStatement prepareStatement(final String sql) throws SQLException {
- return this.delegate.prepareStatement(sql);
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ return
+ new DelegatingPreparedStatement<>(this, // NOTE
+ this.delegate().prepareStatement(sql),
+ true,
+ true);
}
@Override
- public CallableStatement prepareCall(final String sql) throws SQLException {
- return this.delegate.prepareCall(sql);
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ return new DelegatingCallableStatement(this, // NOTE
+ this.delegate().prepareCall(sql),
+ true,
+ true);
}
@Override
- public String nativeSQL(final String sql) throws SQLException {
- return this.delegate.nativeSQL(sql);
+ public String nativeSQL(String sql) throws SQLException {
+ return this.delegate().nativeSQL(sql);
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
- this.delegate.setAutoCommit(autoCommit);
+ this.delegate().setAutoCommit(autoCommit);
}
@Override
public boolean getAutoCommit() throws SQLException {
- return this.delegate.getAutoCommit();
+ return this.delegate().getAutoCommit();
}
@Override
public void commit() throws SQLException {
- this.delegate.commit();
+ this.delegate().commit();
}
@Override
public void rollback() throws SQLException {
- this.delegate.rollback();
+ this.delegate().rollback();
}
@Override
public void close() throws SQLException {
- this.delegate.close();
+ // (No need to check isClosed().)
+ this.delegate().close();
}
@Override
public boolean isClosed() throws SQLException {
- return this.delegate.isClosed();
+ return this.delegate().isClosed();
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
- return this.delegate.getMetaData();
+ return
+ new DelegatingDatabaseMetaData(this, // NOTE
+ this.delegate().getMetaData());
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
- this.delegate.setReadOnly(readOnly);
+ this.delegate().setReadOnly(readOnly);
}
@Override
public boolean isReadOnly() throws SQLException {
- return this.delegate.isReadOnly();
+ return this.delegate().isReadOnly();
}
@Override
public void setCatalog(String catalog) throws SQLException {
- this.delegate.setCatalog(catalog);
+ this.delegate().setCatalog(catalog);
}
@Override
public String getCatalog() throws SQLException {
- return this.delegate.getCatalog();
+ return this.delegate().getCatalog();
}
@Override
- public void setTransactionIsolation(final int level) throws SQLException {
- this.delegate.setTransactionIsolation(level);
+ public void setTransactionIsolation(int level) throws SQLException {
+ this.delegate().setTransactionIsolation(level);
}
@Override
public int getTransactionIsolation() throws SQLException {
- return this.delegate.getTransactionIsolation();
+ return this.delegate().getTransactionIsolation();
}
@Override
public SQLWarning getWarnings() throws SQLException {
- return this.delegate.getWarnings();
+ return this.delegate().getWarnings();
}
@Override
public void clearWarnings() throws SQLException {
- this.delegate.clearWarnings();
+ this.delegate().clearWarnings();
}
@Override
- public Statement createStatement(final int resultSetType, final int resultSetConcurrency) throws SQLException {
- return this.delegate.createStatement(resultSetType, resultSetConcurrency);
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ return
+ new DelegatingStatement<>(this, // NOTE
+ this.delegate().createStatement(resultSetType, resultSetConcurrency),
+ true,
+ true);
}
@Override
- public PreparedStatement prepareStatement(final String sql,
- final int resultSetType,
- final int resultSetConcurrency)
- throws SQLException {
- return this.delegate.prepareStatement(sql, resultSetType, resultSetConcurrency);
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ return
+ new DelegatingPreparedStatement<>(this, // NOTE
+ this.delegate().prepareStatement(sql, resultSetType, resultSetConcurrency),
+ true,
+ true);
}
@Override
- public CallableStatement prepareCall(final String sql,
- final int resultSetType,
- final int resultSetConcurrency)
- throws SQLException {
- return this.delegate.prepareCall(sql, resultSetType, resultSetConcurrency);
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ return
+ new DelegatingCallableStatement(this, // NOTE
+ this.delegate().prepareCall(sql, resultSetType, resultSetConcurrency),
+ true,
+ true);
}
@Override
public Map> getTypeMap() throws SQLException {
- return this.delegate.getTypeMap();
+ return this.delegate().getTypeMap();
}
@Override
public void setTypeMap(Map> map) throws SQLException {
- this.delegate.setTypeMap(map);
+ this.delegate().setTypeMap(map);
}
@Override
- public void setHoldability(final int holdability) throws SQLException {
- this.delegate.setHoldability(holdability);
+ public void setHoldability(int holdability) throws SQLException {
+ this.delegate().setHoldability(holdability);
}
@Override
public int getHoldability() throws SQLException {
- return this.delegate.getHoldability();
+ return this.delegate().getHoldability();
}
@Override
public Savepoint setSavepoint() throws SQLException {
- return this.delegate.setSavepoint();
+ return this.delegate().setSavepoint();
}
@Override
- public Savepoint setSavepoint(final String name) throws SQLException {
- return this.delegate.setSavepoint(name);
+ public Savepoint setSavepoint(String name) throws SQLException {
+ return this.delegate().setSavepoint(name);
}
@Override
- public void rollback(final Savepoint savepoint) throws SQLException {
- this.delegate.rollback(savepoint);
+ public void rollback(Savepoint savepoint) throws SQLException {
+ this.delegate().rollback(savepoint);
}
@Override
- public void releaseSavepoint(final Savepoint savepoint) throws SQLException {
- this.delegate.releaseSavepoint(savepoint);
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ this.delegate().releaseSavepoint(savepoint);
}
@Override
- public Statement createStatement(final int resultSetType,
- final int resultSetConcurrency,
- final int resultSetHoldability)
- throws SQLException {
- return this.delegate.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
+ public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ return
+ new DelegatingStatement<>(this, // NOTE
+ this.delegate().createStatement(resultSetType,
+ resultSetConcurrency,
+ resultSetHoldability),
+ true,
+ true);
}
@Override
- public PreparedStatement prepareStatement(final String sql, final int resultSetType,
- final int resultSetConcurrency,
- final int resultSetHoldability)
- throws SQLException {
- return this.delegate.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return
+ new DelegatingPreparedStatement<>(this, // NOTE
+ this.delegate().prepareStatement(sql,
+ resultSetType,
+ resultSetConcurrency,
+ resultSetHoldability),
+ true,
+ true);
}
@Override
- public CallableStatement prepareCall(final String sql,
- final int resultSetType,
- final int resultSetConcurrency,
- final int resultSetHoldability)
- throws SQLException {
- return this.delegate.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return
+ new DelegatingCallableStatement(this, // NOTE
+ this.delegate().prepareCall(sql,
+ resultSetType,
+ resultSetConcurrency,
+ resultSetHoldability),
+ true,
+ true);
}
@Override
- public PreparedStatement prepareStatement(final String sql, final int autoGeneratedKeys) throws SQLException {
- return this.delegate.prepareStatement(sql, autoGeneratedKeys);
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ return
+ new DelegatingPreparedStatement<>(this, // NOTE
+ this.delegate().prepareStatement(sql, autoGeneratedKeys),
+ true,
+ true);
}
@Override
- public PreparedStatement prepareStatement(final String sql, final int[] columnIndexes) throws SQLException {
- return this.delegate.prepareStatement(sql, columnIndexes);
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ return
+ new DelegatingPreparedStatement<>(this, // NOTE
+ this.delegate().prepareStatement(sql, columnIndexes),
+ true,
+ true);
}
@Override
- public PreparedStatement prepareStatement(final String sql, final String[] columnNames) throws SQLException {
- return this.delegate.prepareStatement(sql, columnNames);
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ return
+ new DelegatingPreparedStatement<>(this, // NOTE
+ this.delegate().prepareStatement(sql, columnNames),
+ true,
+ true);
}
@Override
public Clob createClob() throws SQLException {
- return this.delegate.createClob();
+ return this.delegate().createClob();
}
@Override
public Blob createBlob() throws SQLException {
- return this.delegate.createBlob();
+ return this.delegate().createBlob();
}
@Override
public NClob createNClob() throws SQLException {
- return this.delegate.createNClob();
+ return this.delegate().createNClob();
}
@Override
public SQLXML createSQLXML() throws SQLException {
- return this.delegate.createSQLXML();
+ return this.delegate().createSQLXML();
}
@Override
- public boolean isValid(final int timeout) throws SQLException {
- return this.delegate.isValid(timeout);
+ public boolean isValid(int timeout) throws SQLException {
+ // (No need to check isClosed().)
+ return this.delegate().isValid(timeout);
}
@Override
- public void setClientInfo(final String name, final String value) throws SQLClientInfoException {
- this.delegate.setClientInfo(name, value);
+ public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ this.delegate().setClientInfo(name, value);
}
@Override
- public void setClientInfo(final Properties properties) throws SQLClientInfoException {
- this.delegate.setClientInfo(properties);
+ public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ this.delegate().setClientInfo(properties);
}
@Override
- public String getClientInfo(final String name) throws SQLException {
- return this.delegate.getClientInfo(name);
+ public String getClientInfo(String name) throws SQLException {
+ return this.delegate().getClientInfo(name);
}
@Override
public Properties getClientInfo() throws SQLException {
- return this.delegate.getClientInfo();
+ return this.delegate().getClientInfo();
}
@Override
- public Array createArrayOf(final String typeName, final Object[] elements) throws SQLException {
- return this.delegate.createArrayOf(typeName, elements);
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ return this.delegate().createArrayOf(typeName, elements);
}
@Override
- public Struct createStruct(final String typeName, final Object[] attributes) throws SQLException {
- return this.delegate.createStruct(typeName, attributes);
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ return this.delegate().createStruct(typeName, attributes);
}
@Override
- public void setSchema(final String schema) throws SQLException {
- this.delegate.setSchema(schema);
+ public void setSchema(String schema) throws SQLException {
+ this.delegate().setSchema(schema);
}
@Override
public String getSchema() throws SQLException {
- return this.delegate.getSchema();
+ return this.delegate().getSchema();
}
@Override
- public void abort(final Executor executor) throws SQLException {
- this.delegate.abort(executor);
+ public void abort(Executor executor) throws SQLException {
+ // (No need to check isClosed().)
+ this.delegate().abort(executor);
}
@Override
- public void setNetworkTimeout(final Executor executor, final int milliseconds) throws SQLException {
- this.delegate.setNetworkTimeout(executor, milliseconds);
+ public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+ this.delegate().setNetworkTimeout(executor, milliseconds);
}
@Override
public int getNetworkTimeout() throws SQLException {
- return this.delegate.getNetworkTimeout();
+ return this.delegate().getNetworkTimeout();
}
@Override
public void beginRequest() throws SQLException {
- this.delegate.beginRequest();
+ // (No need to check isClosed().)
+ this.delegate().beginRequest();
}
@Override
public void endRequest() throws SQLException {
- this.delegate.endRequest();
+ // (No need to check isClosed().)
+ this.delegate().endRequest();
}
@Override
- public boolean setShardingKeyIfValid(final ShardingKey shardingKey,
- final ShardingKey superShardingKey,
- final int timeout)
- throws SQLException {
- return this.delegate.setShardingKeyIfValid(shardingKey, superShardingKey, timeout);
+ public boolean setShardingKeyIfValid(ShardingKey shardingKey, ShardingKey superShardingKey, int timeout)
+ throws SQLException {
+ return this.delegate().setShardingKeyIfValid(shardingKey, superShardingKey, timeout);
}
@Override
- public boolean setShardingKeyIfValid(final ShardingKey shardingKey, final int timeout) throws SQLException {
- return this.delegate.setShardingKeyIfValid(shardingKey, timeout);
+ public boolean setShardingKeyIfValid(ShardingKey shardingKey, int timeout) throws SQLException {
+ return this.delegate().setShardingKeyIfValid(shardingKey, timeout);
}
@Override
- public void setShardingKey(final ShardingKey shardingKey, final ShardingKey superShardingKey) throws SQLException {
- this.delegate.setShardingKey(shardingKey, superShardingKey);
+ public void setShardingKey(ShardingKey shardingKey, ShardingKey superShardingKey) throws SQLException {
+ this.delegate().setShardingKey(shardingKey, superShardingKey);
}
@Override
- public void setShardingKey(final ShardingKey shardingKey) throws SQLException {
- this.delegate.setShardingKey(shardingKey);
+ public void setShardingKey(ShardingKey shardingKey) throws SQLException {
+ this.delegate().setShardingKey(shardingKey);
}
@Override
- public T unwrap(final Class iface) throws SQLException {
- return this.delegate.unwrap(iface);
+ public T unwrap(Class iface) throws SQLException {
+ return iface.isInstance(this) ? iface.cast(this) : this.delegate().unwrap(iface);
}
@Override
- public boolean isWrapperFor(final Class> iface) throws SQLException {
- return this.delegate.isWrapperFor(iface);
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ return iface.isInstance(this) || this.delegate().isWrapperFor(iface);
}
}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingDatabaseMetaData.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingDatabaseMetaData.java
new file mode 100644
index 00000000000..a829930b9b4
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingDatabaseMetaData.java
@@ -0,0 +1,968 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.RowIdLifetime;
+import java.sql.SQLException;
+import java.util.Objects;
+
+/**
+ * A JDBC
+ * 4.3-compliant {@link DatabaseMetaData} that delegates to another JDBC 4.3-compliant {@link DatabaseMetaData}.
+ */
+public class DelegatingDatabaseMetaData implements DatabaseMetaData {
+
+ private final Connection connection;
+
+ private final DatabaseMetaData delegate;
+
+ /**
+ * Creates a new {@link DelegatingDatabaseMetaData}.
+ *
+ * @param connection the {@link Connection} that will be returned by the {@link #getConnection()} method; must not
+ * be {@code null}
+ *
+ * @param delegate the {@link DatabaseMetaData} to which all operations will be delegated; must not be {@code null}
+ *
+ * @exception NullPointerException if either {@code connection} or {@code delegate} is {@code null}
+ */
+ protected DelegatingDatabaseMetaData(Connection connection, DatabaseMetaData delegate) {
+ super();
+ this.connection = Objects.requireNonNull(connection, "connection");
+ this.delegate = Objects.requireNonNull(delegate, "delegate");
+ }
+
+ @Override
+ public boolean allProceduresAreCallable() throws SQLException {
+ return this.delegate.allProceduresAreCallable();
+ }
+
+ @Override
+ public boolean allTablesAreSelectable() throws SQLException {
+ return this.delegate.allTablesAreSelectable();
+ }
+
+ @Override
+ public String getURL() throws SQLException {
+ return this.delegate.getURL();
+ }
+
+ @Override
+ public String getUserName() throws SQLException {
+ return this.delegate.getUserName();
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException {
+ return this.delegate.isReadOnly();
+ }
+
+ @Override
+ public boolean nullsAreSortedHigh() throws SQLException {
+ return this.delegate.nullsAreSortedHigh();
+ }
+
+ @Override
+ public boolean nullsAreSortedLow() throws SQLException {
+ return this.delegate.nullsAreSortedLow();
+ }
+
+ @Override
+ public boolean nullsAreSortedAtStart() throws SQLException {
+ return this.delegate.nullsAreSortedAtStart();
+ }
+
+ @Override
+ public boolean nullsAreSortedAtEnd() throws SQLException {
+ return this.delegate.nullsAreSortedAtEnd();
+ }
+
+ @Override
+ public String getDatabaseProductName() throws SQLException {
+ return this.delegate.getDatabaseProductName();
+ }
+
+ @Override
+ public String getDatabaseProductVersion() throws SQLException {
+ return this.delegate.getDatabaseProductVersion();
+ }
+
+ @Override
+ public String getDriverName() throws SQLException {
+ return this.delegate.getDriverName();
+ }
+
+ @Override
+ public String getDriverVersion() throws SQLException {
+ return this.delegate.getDriverVersion();
+ }
+
+ @Override
+ public int getDriverMajorVersion() {
+ return this.delegate.getDriverMajorVersion();
+ }
+
+ @Override
+ public int getDriverMinorVersion() {
+ return this.delegate.getDriverMinorVersion();
+ }
+
+ @Override
+ public boolean usesLocalFiles() throws SQLException {
+ return this.delegate.usesLocalFiles();
+ }
+
+ @Override
+ public boolean usesLocalFilePerTable() throws SQLException {
+ return this.delegate.usesLocalFilePerTable();
+ }
+
+ @Override
+ public boolean supportsMixedCaseIdentifiers() throws SQLException {
+ return this.delegate.supportsMixedCaseIdentifiers();
+ }
+
+ @Override
+ public boolean storesUpperCaseIdentifiers() throws SQLException {
+ return this.delegate.storesUpperCaseIdentifiers();
+ }
+
+ @Override
+ public boolean storesLowerCaseIdentifiers() throws SQLException {
+ return this.delegate.storesLowerCaseIdentifiers();
+ }
+
+ @Override
+ public boolean storesMixedCaseIdentifiers() throws SQLException {
+ return this.delegate.storesMixedCaseIdentifiers();
+ }
+
+ @Override
+ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
+ return this.delegate.supportsMixedCaseQuotedIdentifiers();
+ }
+
+ @Override
+ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
+ return this.delegate.storesUpperCaseQuotedIdentifiers();
+ }
+
+ @Override
+ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
+ return this.delegate.storesLowerCaseQuotedIdentifiers();
+ }
+
+ @Override
+ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
+ return this.delegate.storesMixedCaseQuotedIdentifiers();
+ }
+
+ @Override
+ public String getIdentifierQuoteString() throws SQLException {
+ return this.delegate.getIdentifierQuoteString();
+ }
+
+ @Override
+ public String getSQLKeywords() throws SQLException {
+ return this.delegate.getSQLKeywords();
+ }
+
+ @Override
+ public String getNumericFunctions() throws SQLException {
+ return this.delegate.getNumericFunctions();
+ }
+
+ @Override
+ public String getStringFunctions() throws SQLException {
+ return this.delegate.getStringFunctions();
+ }
+
+ @Override
+ public String getSystemFunctions() throws SQLException {
+ return this.delegate.getSystemFunctions();
+ }
+
+ @Override
+ public String getTimeDateFunctions() throws SQLException {
+ return this.delegate.getTimeDateFunctions();
+ }
+
+ @Override
+ public String getSearchStringEscape() throws SQLException {
+ return this.delegate.getSearchStringEscape();
+ }
+
+ @Override
+ public String getExtraNameCharacters() throws SQLException {
+ return this.delegate.getExtraNameCharacters();
+ }
+
+ @Override
+ public boolean supportsAlterTableWithAddColumn() throws SQLException {
+ return this.delegate.supportsAlterTableWithAddColumn();
+ }
+
+ @Override
+ public boolean supportsAlterTableWithDropColumn() throws SQLException {
+ return this.delegate.supportsAlterTableWithDropColumn();
+ }
+
+ @Override
+ public boolean supportsColumnAliasing() throws SQLException {
+ return this.delegate.supportsColumnAliasing();
+ }
+
+ @Override
+ public boolean nullPlusNonNullIsNull() throws SQLException {
+ return this.delegate.nullPlusNonNullIsNull();
+ }
+
+ @Override
+ public boolean supportsConvert() throws SQLException {
+ return this.delegate.supportsConvert();
+ }
+
+ @Override
+ public boolean supportsConvert(int fromType, int toType) throws SQLException {
+ return this.delegate.supportsConvert(fromType, toType);
+ }
+
+ @Override
+ public boolean supportsTableCorrelationNames() throws SQLException {
+ return this.delegate.supportsTableCorrelationNames();
+ }
+
+ @Override
+ public boolean supportsDifferentTableCorrelationNames() throws SQLException {
+ return this.delegate.supportsDifferentTableCorrelationNames();
+ }
+
+ @Override
+ public boolean supportsExpressionsInOrderBy() throws SQLException {
+ return this.delegate.supportsExpressionsInOrderBy();
+ }
+
+ @Override
+ public boolean supportsOrderByUnrelated() throws SQLException {
+ return this.delegate.supportsOrderByUnrelated();
+ }
+
+ @Override
+ public boolean supportsGroupBy() throws SQLException {
+ return this.delegate.supportsGroupBy();
+ }
+
+ @Override
+ public boolean supportsGroupByUnrelated() throws SQLException {
+ return this.delegate.supportsGroupByUnrelated();
+ }
+
+ @Override
+ public boolean supportsGroupByBeyondSelect() throws SQLException {
+ return this.delegate.supportsGroupByBeyondSelect();
+ }
+
+ @Override
+ public boolean supportsLikeEscapeClause() throws SQLException {
+ return this.delegate.supportsLikeEscapeClause();
+ }
+
+ @Override
+ public boolean supportsMultipleResultSets() throws SQLException {
+ return this.delegate.supportsMultipleResultSets();
+ }
+
+ @Override
+ public boolean supportsMultipleTransactions() throws SQLException {
+ return this.delegate.supportsMultipleTransactions();
+ }
+
+ @Override
+ public boolean supportsNonNullableColumns() throws SQLException {
+ return this.delegate.supportsNonNullableColumns();
+ }
+
+ @Override
+ public boolean supportsMinimumSQLGrammar() throws SQLException {
+ return this.delegate.supportsMinimumSQLGrammar();
+ }
+
+ @Override
+ public boolean supportsCoreSQLGrammar() throws SQLException {
+ return this.delegate.supportsCoreSQLGrammar();
+ }
+
+ @Override
+ public boolean supportsExtendedSQLGrammar() throws SQLException {
+ return this.delegate.supportsExtendedSQLGrammar();
+ }
+
+ @Override
+ public boolean supportsANSI92EntryLevelSQL() throws SQLException {
+ return this.delegate.supportsANSI92EntryLevelSQL();
+ }
+
+ @Override
+ public boolean supportsANSI92IntermediateSQL() throws SQLException {
+ return this.delegate.supportsANSI92IntermediateSQL();
+ }
+
+ @Override
+ public boolean supportsANSI92FullSQL() throws SQLException {
+ return this.delegate.supportsANSI92FullSQL();
+ }
+
+ @Override
+ public boolean supportsIntegrityEnhancementFacility() throws SQLException {
+ return this.delegate.supportsIntegrityEnhancementFacility();
+ }
+
+ @Override
+ public boolean supportsOuterJoins() throws SQLException {
+ return this.delegate.supportsOuterJoins();
+ }
+
+ @Override
+ public boolean supportsFullOuterJoins() throws SQLException {
+ return this.delegate.supportsFullOuterJoins();
+ }
+
+ @Override
+ public boolean supportsLimitedOuterJoins() throws SQLException {
+ return this.delegate.supportsLimitedOuterJoins();
+ }
+
+ @Override
+ public String getSchemaTerm() throws SQLException {
+ return this.delegate.getSchemaTerm();
+ }
+
+ @Override
+ public String getProcedureTerm() throws SQLException {
+ return this.delegate.getProcedureTerm();
+ }
+
+ @Override
+ public String getCatalogTerm() throws SQLException {
+ return this.delegate.getCatalogTerm();
+ }
+
+ @Override
+ public boolean isCatalogAtStart() throws SQLException {
+ return this.delegate.isCatalogAtStart();
+ }
+
+ @Override
+ public String getCatalogSeparator() throws SQLException {
+ return this.delegate.getCatalogSeparator();
+ }
+
+ @Override
+ public boolean supportsSchemasInDataManipulation() throws SQLException {
+ return this.delegate.supportsSchemasInDataManipulation();
+ }
+
+ @Override
+ public boolean supportsSchemasInProcedureCalls() throws SQLException {
+ return this.delegate.supportsSchemasInProcedureCalls();
+ }
+
+ @Override
+ public boolean supportsSchemasInTableDefinitions() throws SQLException {
+ return this.delegate.supportsSchemasInTableDefinitions();
+ }
+
+ @Override
+ public boolean supportsSchemasInIndexDefinitions() throws SQLException {
+ return this.delegate.supportsSchemasInIndexDefinitions();
+ }
+
+ @Override
+ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
+ return this.delegate.supportsSchemasInPrivilegeDefinitions();
+ }
+
+ @Override
+ public boolean supportsCatalogsInDataManipulation() throws SQLException {
+ return this.delegate.supportsCatalogsInDataManipulation();
+ }
+
+ @Override
+ public boolean supportsCatalogsInProcedureCalls() throws SQLException {
+ return this.delegate.supportsCatalogsInProcedureCalls();
+ }
+
+ @Override
+ public boolean supportsCatalogsInTableDefinitions() throws SQLException {
+ return this.delegate.supportsCatalogsInTableDefinitions();
+ }
+
+ @Override
+ public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
+ return this.delegate.supportsCatalogsInIndexDefinitions();
+ }
+
+ @Override
+ public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
+ return this.delegate.supportsCatalogsInPrivilegeDefinitions();
+ }
+
+ @Override
+ public boolean supportsPositionedDelete() throws SQLException {
+ return this.delegate.supportsPositionedDelete();
+ }
+
+ @Override
+ public boolean supportsPositionedUpdate() throws SQLException {
+ return this.delegate.supportsPositionedUpdate();
+ }
+
+ @Override
+ public boolean supportsSelectForUpdate() throws SQLException {
+ return this.delegate.supportsSelectForUpdate();
+ }
+
+ @Override
+ public boolean supportsStoredProcedures() throws SQLException {
+ return this.delegate.supportsStoredProcedures();
+ }
+
+ @Override
+ public boolean supportsSubqueriesInComparisons() throws SQLException {
+ return this.delegate.supportsSubqueriesInComparisons();
+ }
+
+ @Override
+ public boolean supportsSubqueriesInExists() throws SQLException {
+ return this.delegate.supportsSubqueriesInExists();
+ }
+
+ @Override
+ public boolean supportsSubqueriesInIns() throws SQLException {
+ return this.delegate.supportsSubqueriesInIns();
+ }
+
+ @Override
+ public boolean supportsSubqueriesInQuantifieds() throws SQLException {
+ return this.delegate.supportsSubqueriesInQuantifieds();
+ }
+
+ @Override
+ public boolean supportsCorrelatedSubqueries() throws SQLException {
+ return this.delegate.supportsCorrelatedSubqueries();
+ }
+
+ @Override
+ public boolean supportsUnion() throws SQLException {
+ return this.delegate.supportsUnion();
+ }
+
+ @Override
+ public boolean supportsUnionAll() throws SQLException {
+ return this.delegate.supportsUnionAll();
+ }
+
+ @Override
+ public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
+ return this.delegate.supportsOpenCursorsAcrossCommit();
+ }
+
+ @Override
+ public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
+ return this.delegate.supportsOpenCursorsAcrossRollback();
+ }
+
+ @Override
+ public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
+ return this.delegate.supportsOpenStatementsAcrossCommit();
+ }
+
+ @Override
+ public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
+ return this.delegate.supportsOpenStatementsAcrossRollback();
+ }
+
+ @Override
+ public int getMaxBinaryLiteralLength() throws SQLException {
+ return this.delegate.getMaxBinaryLiteralLength();
+ }
+
+ @Override
+ public int getMaxCharLiteralLength() throws SQLException {
+ return this.delegate.getMaxCharLiteralLength();
+ }
+
+ @Override
+ public int getMaxColumnNameLength() throws SQLException {
+ return this.delegate.getMaxColumnNameLength();
+ }
+
+ @Override
+ public int getMaxColumnsInGroupBy() throws SQLException {
+ return this.delegate.getMaxColumnsInGroupBy();
+ }
+
+ @Override
+ public int getMaxColumnsInIndex() throws SQLException {
+ return this.delegate.getMaxColumnsInIndex();
+ }
+
+ @Override
+ public int getMaxColumnsInOrderBy() throws SQLException {
+ return this.delegate.getMaxColumnsInOrderBy();
+ }
+
+ @Override
+ public int getMaxColumnsInSelect() throws SQLException {
+ return this.delegate.getMaxColumnsInSelect();
+ }
+
+ @Override
+ public int getMaxColumnsInTable() throws SQLException {
+ return this.delegate.getMaxColumnsInTable();
+ }
+
+ @Override
+ public int getMaxConnections() throws SQLException {
+ return this.delegate.getMaxConnections();
+ }
+
+ @Override
+ public int getMaxCursorNameLength() throws SQLException {
+ return this.delegate.getMaxCursorNameLength();
+ }
+
+ @Override
+ public int getMaxIndexLength() throws SQLException {
+ return this.delegate.getMaxIndexLength();
+ }
+
+ @Override
+ public int getMaxSchemaNameLength() throws SQLException {
+ return this.delegate.getMaxSchemaNameLength();
+ }
+
+ @Override
+ public int getMaxProcedureNameLength() throws SQLException {
+ return this.delegate.getMaxProcedureNameLength();
+ }
+
+ @Override
+ public int getMaxCatalogNameLength() throws SQLException {
+ return this.delegate.getMaxCatalogNameLength();
+ }
+
+ @Override
+ public int getMaxRowSize() throws SQLException {
+ return this.delegate.getMaxRowSize();
+ }
+
+ @Override
+ public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
+ return this.delegate.doesMaxRowSizeIncludeBlobs();
+ }
+
+ @Override
+ public int getMaxStatementLength() throws SQLException {
+ return this.delegate.getMaxStatementLength();
+ }
+
+ @Override
+ public int getMaxStatements() throws SQLException {
+ return this.delegate.getMaxStatements();
+ }
+
+ @Override
+ public int getMaxTableNameLength() throws SQLException {
+ return this.delegate.getMaxTableNameLength();
+ }
+
+ @Override
+ public int getMaxTablesInSelect() throws SQLException {
+ return this.delegate.getMaxTablesInSelect();
+ }
+
+ @Override
+ public int getMaxUserNameLength() throws SQLException {
+ return this.delegate.getMaxUserNameLength();
+ }
+
+ @Override
+ public int getDefaultTransactionIsolation() throws SQLException {
+ return this.delegate.getDefaultTransactionIsolation();
+ }
+
+ @Override
+ public boolean supportsTransactions() throws SQLException {
+ return this.delegate.supportsTransactions();
+ }
+
+ @Override
+ public boolean supportsTransactionIsolationLevel(int level) throws SQLException {
+ return this.delegate.supportsTransactionIsolationLevel(level);
+ }
+
+ @Override
+ public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException {
+ return this.delegate.supportsDataDefinitionAndDataManipulationTransactions();
+ }
+
+ @Override
+ public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
+ return this.delegate.supportsDataManipulationTransactionsOnly();
+ }
+
+ @Override
+ public boolean dataDefinitionCausesTransactionCommit() throws SQLException {
+ return this.delegate.dataDefinitionCausesTransactionCommit();
+ }
+
+ @Override
+ public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
+ return this.delegate.dataDefinitionIgnoredInTransactions();
+ }
+
+ @Override
+ public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException {
+ return this.delegate.getProcedures(catalog, schemaPattern, procedureNamePattern);
+ }
+
+ @Override
+ public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedurePattern, String columnNamePattern)
+ throws SQLException {
+ return this.delegate.getProcedureColumns(catalog, schemaPattern, procedurePattern, columnNamePattern);
+ }
+
+ @Override
+ public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
+ throws SQLException {
+ return this.delegate.getTables(catalog, schemaPattern, tableNamePattern, types);
+ }
+
+ @Override
+ public ResultSet getSchemas() throws SQLException {
+ return this.delegate.getSchemas();
+ }
+
+ @Override
+ public ResultSet getCatalogs() throws SQLException {
+ return this.delegate.getCatalogs();
+ }
+
+ @Override
+ public ResultSet getTableTypes() throws SQLException {
+ return this.delegate.getTableTypes();
+ }
+
+ @Override
+ public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
+ throws SQLException {
+ return this.delegate.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
+ }
+
+ @Override
+ public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern)
+ throws SQLException {
+ return this.delegate.getColumnPrivileges(catalog, schema, table, columnNamePattern);
+ }
+
+ @Override
+ public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
+ return this.delegate.getTablePrivileges(catalog, schemaPattern, tableNamePattern);
+ }
+
+ @Override
+ public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable)
+ throws SQLException {
+ return this.delegate.getBestRowIdentifier(catalog, schema, table, scope, nullable);
+ }
+
+ @Override
+ public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException {
+ return this.delegate.getVersionColumns(catalog, schema, table);
+ }
+
+ @Override
+ public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException {
+ return this.delegate.getPrimaryKeys(catalog, schema, table);
+ }
+
+ @Override
+ public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
+ return this.delegate.getImportedKeys(catalog, schema, table);
+ }
+
+ @Override
+ public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
+ return this.delegate.getExportedKeys(catalog, schema, table);
+ }
+
+ @Override
+ public ResultSet getCrossReference(String parentCatalog,
+ String parentSchema,
+ String parentTable,
+ String foreignCatalog,
+ String foreignSchema,
+ String foreignTable)
+ throws SQLException {
+ return
+ this.delegate.getCrossReference(parentCatalog,
+ parentSchema,
+ parentTable,
+ foreignCatalog,
+ foreignSchema,
+ foreignTable);
+ }
+
+ @Override
+ public ResultSet getTypeInfo() throws SQLException {
+ return this.delegate.getTypeInfo();
+ }
+
+ @Override
+ public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate)
+ throws SQLException {
+ return this.delegate.getIndexInfo(catalog, schema, table, unique, approximate);
+ }
+
+ @Override
+ public boolean supportsResultSetType(int type) throws SQLException {
+ return this.delegate.supportsResultSetType(type);
+ }
+
+ @Override
+ public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
+ return this.delegate.supportsResultSetConcurrency(type, concurrency);
+ }
+
+ @Override
+ public boolean ownUpdatesAreVisible(int type) throws SQLException {
+ return this.delegate.ownUpdatesAreVisible(type);
+ }
+
+ @Override
+ public boolean ownDeletesAreVisible(int type) throws SQLException {
+ return this.delegate.ownDeletesAreVisible(type);
+ }
+
+ @Override
+ public boolean ownInsertsAreVisible(int type) throws SQLException {
+ return this.delegate.ownInsertsAreVisible(type);
+ }
+
+ @Override
+ public boolean othersUpdatesAreVisible(int type) throws SQLException {
+ return this.delegate.othersUpdatesAreVisible(type);
+ }
+
+ @Override
+ public boolean othersDeletesAreVisible(int type) throws SQLException {
+ return this.delegate.othersDeletesAreVisible(type);
+ }
+
+ @Override
+ public boolean othersInsertsAreVisible(int type) throws SQLException {
+ return this.delegate.othersInsertsAreVisible(type);
+ }
+
+ @Override
+ public boolean updatesAreDetected(int type) throws SQLException {
+ return this.delegate.updatesAreDetected(type);
+ }
+
+ @Override
+ public boolean deletesAreDetected(int type) throws SQLException {
+ return this.delegate.deletesAreDetected(type);
+ }
+
+ @Override
+ public boolean insertsAreDetected(int type) throws SQLException {
+ return this.delegate.insertsAreDetected(type);
+ }
+
+ @Override
+ public boolean supportsBatchUpdates() throws SQLException {
+ return this.delegate.supportsBatchUpdates();
+ }
+
+ @Override
+ public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException {
+ return this.delegate.getUDTs(catalog, schemaPattern, typeNamePattern, types);
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ // NOTE
+ return this.connection;
+ }
+
+ @Override
+ public boolean supportsSavepoints() throws SQLException {
+ return this.delegate.supportsSavepoints();
+ }
+
+ @Override
+ public boolean supportsNamedParameters() throws SQLException {
+ return this.delegate.supportsNamedParameters();
+ }
+
+ @Override
+ public boolean supportsMultipleOpenResults() throws SQLException {
+ return this.delegate.supportsMultipleOpenResults();
+ }
+
+ @Override
+ public boolean supportsGetGeneratedKeys() throws SQLException {
+ return this.delegate.supportsGetGeneratedKeys();
+ }
+
+ @Override
+ public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException {
+ return this.delegate.getSuperTypes(catalog, schemaPattern, typeNamePattern);
+ }
+
+ @Override
+ public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException {
+ return this.delegate.getSuperTables(catalog, schemaPattern, tableNamePattern);
+ }
+
+ @Override
+ public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern)
+ throws SQLException {
+ return this.delegate.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern);
+ }
+
+ @Override
+ public boolean supportsResultSetHoldability(int holdability) throws SQLException {
+ return this.delegate.supportsResultSetHoldability(holdability);
+ }
+
+ @Override
+ public int getResultSetHoldability() throws SQLException {
+ return this.delegate.getResultSetHoldability();
+ }
+
+ @Override
+ public int getDatabaseMajorVersion() throws SQLException {
+ return this.delegate.getDatabaseMajorVersion();
+ }
+
+ @Override
+ public int getDatabaseMinorVersion() throws SQLException {
+ return this.delegate.getDatabaseMinorVersion();
+ }
+
+ @Override
+ public int getJDBCMajorVersion() throws SQLException {
+ return this.delegate.getJDBCMajorVersion();
+ }
+
+ @Override
+ public int getJDBCMinorVersion() throws SQLException {
+ return this.delegate.getJDBCMinorVersion();
+ }
+
+ @Override
+ public int getSQLStateType() throws SQLException {
+ return this.delegate.getSQLStateType();
+ }
+
+ @Override
+ public boolean locatorsUpdateCopy() throws SQLException {
+ return this.delegate.locatorsUpdateCopy();
+ }
+
+ @Override
+ public boolean supportsStatementPooling() throws SQLException {
+ return this.delegate.supportsStatementPooling();
+ }
+
+ @Override
+ public RowIdLifetime getRowIdLifetime() throws SQLException {
+ return this.delegate.getRowIdLifetime();
+ }
+
+ @Override
+ public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException {
+ return this.delegate.getSchemas(catalog, schemaPattern);
+ }
+
+ @Override
+ public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
+ return this.delegate.supportsStoredFunctionsUsingCallSyntax();
+ }
+
+ @Override
+ public boolean autoCommitFailureClosesAllResultSets() throws SQLException {
+ return this.delegate.autoCommitFailureClosesAllResultSets();
+ }
+
+ @Override
+ public ResultSet getClientInfoProperties() throws SQLException {
+ return this.delegate.getClientInfoProperties();
+ }
+
+ @Override
+ public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException {
+ return this.delegate.getFunctions(catalog, schemaPattern, functionNamePattern);
+ }
+
+ @Override
+ public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionPattern, String columnNamePattern)
+ throws SQLException {
+ return this.delegate.getFunctionColumns(catalog, schemaPattern, functionPattern, columnNamePattern);
+ }
+
+ @Override
+ public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
+ throws SQLException {
+ return this.delegate.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
+ }
+
+ @Override
+ public boolean generatedKeyAlwaysReturned() throws SQLException {
+ return this.delegate.generatedKeyAlwaysReturned();
+ }
+
+ @Override
+ public long getMaxLogicalLobSize() throws SQLException {
+ return this.delegate.getMaxLogicalLobSize();
+ }
+
+ @Override
+ public boolean supportsRefCursors() throws SQLException {
+ return this.delegate.supportsRefCursors();
+ }
+
+ @Override
+ public boolean supportsSharding() throws SQLException {
+ return this.delegate.supportsSharding();
+ }
+
+ @Override
+ public T unwrap(Class iface) throws SQLException {
+ return iface.isInstance(this) ? iface.cast(this) : this.delegate.unwrap(iface);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ return iface.isInstance(this) || this.delegate.isWrapperFor(iface);
+ }
+
+}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingPreparedStatement.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingPreparedStatement.java
new file mode 100644
index 00000000000..611a6ae95f5
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingPreparedStatement.java
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLType;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+
+/**
+ * A JDBC
+ * 4.3-compliant {@link PreparedStatement} that delegates to another JDBC 4.3-compliant {@link PreparedStatement}.
+ *
+ * @param the type of the {@link PreparedStatement} subclass
+ */
+public class DelegatingPreparedStatement extends DelegatingStatement implements PreparedStatement {
+
+ /**
+ * Creates a new {@link DelegatingPreparedStatement}.
+ *
+ * @param connection the {@link Connection} that created this {@link DelegatingPreparedStatement}; must not be
+ * {@code null}
+ *
+ * @param delegate the {@link PreparedStatement} instance to which all operations will be delegated; must not be
+ * {@code null}
+ *
+ * @param closeable the initial value for this {@link DelegatingPreparedStatement}'s {@linkplain #isCloseable()
+ * closeable} status
+ *
+ * @param strictClosedChecking if {@code true}, then this {@link DelegatingPreparedStatement}'s {@link
+ * #isClosed()} method will be invoked before every operation that cannot take place on a closed statement, and, if
+ * it returns {@code true}, the operation in question will fail with a {@link SQLException}
+ * @exception NullPointerException if either argument is {@code
+ * null}
+ *
+ * @see DelegatingStatement#isCloseable()
+ *
+ * @see DelegatingStatement#setCloseable(boolean)
+ *
+ * @see DelegatingStatement#close()
+ *
+ * @see DelegatingStatement#isClosed()
+ */
+ public DelegatingPreparedStatement(Connection connection,
+ S delegate,
+ boolean closeable,
+ boolean strictClosedChecking) {
+ super(connection, delegate, closeable, strictClosedChecking);
+ }
+
+ @Override
+ public ResultSet executeQuery() throws SQLException {
+ checkOpen();
+ return
+ new DelegatingResultSet(this, // NOTE
+ this.delegate().executeQuery(),
+ true,
+ true);
+ }
+
+ @Override
+ public int executeUpdate() throws SQLException {
+ checkOpen();
+ return this.delegate().executeUpdate();
+ }
+
+ @Override
+ public void setNull(int parameterIndex, int sqlType) throws SQLException {
+ checkOpen();
+ this.delegate().setNull(parameterIndex, sqlType);
+ }
+
+ @Override
+ public void setBoolean(int parameterIndex, boolean x) throws SQLException {
+ checkOpen();
+ this.delegate().setBoolean(parameterIndex, x);
+ }
+
+ @Override
+ public void setByte(int parameterIndex, byte x) throws SQLException {
+ checkOpen();
+ this.delegate().setByte(parameterIndex, x);
+ }
+
+ @Override
+ public void setShort(int parameterIndex, short x) throws SQLException {
+ checkOpen();
+ this.delegate().setShort(parameterIndex, x);
+ }
+
+ @Override
+ public void setInt(int parameterIndex, int x) throws SQLException {
+ checkOpen();
+ this.delegate().setInt(parameterIndex, x);
+ }
+
+ @Override
+ public void setLong(int parameterIndex, long x) throws SQLException {
+ checkOpen();
+ this.delegate().setLong(parameterIndex, x);
+ }
+
+ @Override
+ public void setFloat(int parameterIndex, float x) throws SQLException {
+ checkOpen();
+ this.delegate().setFloat(parameterIndex, x);
+ }
+
+ @Override
+ public void setDouble(int parameterIndex, double x) throws SQLException {
+ checkOpen();
+ this.delegate().setDouble(parameterIndex, x);
+ }
+
+ @Override
+ public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
+ checkOpen();
+ this.delegate().setBigDecimal(parameterIndex, x);
+ }
+
+ @Override
+ public void setString(int parameterIndex, String x) throws SQLException {
+ checkOpen();
+ this.delegate().setString(parameterIndex, x);
+ }
+
+ @Override
+ public void setBytes(int parameterIndex, byte[] x) throws SQLException {
+ checkOpen();
+ this.delegate().setBytes(parameterIndex, x);
+ }
+
+ @Override
+ public void setDate(int parameterIndex, Date x) throws SQLException {
+ checkOpen();
+ this.delegate().setDate(parameterIndex, x);
+ }
+
+ @Override
+ public void setTime(int parameterIndex, Time x) throws SQLException {
+ checkOpen();
+ this.delegate().setTime(parameterIndex, x);
+ }
+
+ @Override
+ public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
+ checkOpen();
+ this.delegate().setTimestamp(parameterIndex, x);
+ }
+
+ @Override
+ public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().setAsciiStream(parameterIndex, x, length);
+ }
+
+ @Deprecated
+ @Override
+ public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().setUnicodeStream(parameterIndex, x, length);
+ }
+
+ @Override
+ public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().setBinaryStream(parameterIndex, x, length);
+ }
+
+ @Override
+ public void clearParameters() throws SQLException {
+ checkOpen();
+ this.delegate().clearParameters();
+ }
+
+ @Override
+ public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterIndex, x, targetSqlType);
+ }
+
+ @Override
+ public void setObject(int parameterIndex, Object x) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterIndex, x);
+ }
+
+ @Override
+ public boolean execute() throws SQLException {
+ checkOpen();
+ return this.delegate().execute();
+ }
+
+ @Override
+ public void addBatch() throws SQLException {
+ checkOpen();
+ this.delegate().addBatch();
+ }
+
+ @Override
+ public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
+ checkOpen();
+ this.delegate().setCharacterStream(parameterIndex, reader, length);
+ }
+
+ @Override
+ public void setRef(int parameterIndex, Ref x) throws SQLException {
+ checkOpen();
+ this.delegate().setRef(parameterIndex, x);
+ }
+
+ @Override
+ public void setBlob(int parameterIndex, Blob x) throws SQLException {
+ checkOpen();
+ this.delegate().setBlob(parameterIndex, x);
+ }
+
+ @Override
+ public void setClob(int parameterIndex, Clob x) throws SQLException {
+ checkOpen();
+ this.delegate().setClob(parameterIndex, x);
+ }
+
+ @Override
+ public void setArray(int parameterIndex, Array x) throws SQLException {
+ checkOpen();
+ this.delegate().setArray(parameterIndex, x);
+ }
+
+ @Override
+ public ResultSetMetaData getMetaData() throws SQLException {
+ checkOpen();
+ return this.delegate().getMetaData();
+ }
+
+ @Override
+ public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
+ checkOpen();
+ this.delegate().setDate(parameterIndex, x, cal);
+ }
+
+ @Override
+ public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
+ checkOpen();
+ this.delegate().setTime(parameterIndex, x, cal);
+ }
+
+ @Override
+ public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
+ checkOpen();
+ this.delegate().setTimestamp(parameterIndex, x, cal);
+ }
+
+ @Override
+ public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
+ checkOpen();
+ this.delegate().setNull(parameterIndex, sqlType, typeName);
+ }
+
+ @Override
+ public void setURL(int parameterIndex, URL x) throws SQLException {
+ checkOpen();
+ this.delegate().setURL(parameterIndex, x);
+ }
+
+ @Override
+ public ParameterMetaData getParameterMetaData() throws SQLException {
+ checkOpen();
+ return this.delegate().getParameterMetaData();
+ }
+
+ @Override
+ public void setRowId(int parameterIndex, RowId x) throws SQLException {
+ checkOpen();
+ this.delegate().setRowId(parameterIndex, x);
+ }
+
+ @Override
+ public void setNString(int parameterIndex, String value) throws SQLException {
+ checkOpen();
+ this.delegate().setNString(parameterIndex, value);
+ }
+
+ @Override
+ public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setNCharacterStream(parameterIndex, value, length);
+ }
+
+ @Override
+ public void setNClob(int parameterIndex, NClob value) throws SQLException {
+ checkOpen();
+ this.delegate().setNClob(parameterIndex, value);
+ }
+
+ @Override
+ public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setClob(parameterIndex, reader, length);
+ }
+
+ @Override
+ public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setBlob(parameterIndex, inputStream, length);
+ }
+
+ @Override
+ public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setNClob(parameterIndex, reader, length);
+ }
+
+ @Override
+ public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
+ checkOpen();
+ this.delegate().setSQLXML(parameterIndex, xmlObject);
+ }
+
+ @Override
+ public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterIndex, x, targetSqlType, scaleOrLength);
+ }
+
+ @Override
+ public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setAsciiStream(parameterIndex, x, length);
+ }
+
+ @Override
+ public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setBinaryStream(parameterIndex, x, length);
+ }
+
+ @Override
+ public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().setCharacterStream(parameterIndex, reader, length);
+ }
+
+ @Override
+ public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
+ checkOpen();
+ this.delegate().setAsciiStream(parameterIndex, x);
+ }
+
+ @Override
+ public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
+ checkOpen();
+ this.delegate().setBinaryStream(parameterIndex, x);
+ }
+
+ @Override
+ public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().setCharacterStream(parameterIndex, reader);
+ }
+
+ @Override
+ public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
+ checkOpen();
+ this.delegate().setNCharacterStream(parameterIndex, value);
+ }
+
+ @Override
+ public void setClob(int parameterIndex, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().setClob(parameterIndex, reader);
+ }
+
+ @Override
+ public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
+ checkOpen();
+ this.delegate().setBlob(parameterIndex, inputStream);
+ }
+
+ @Override
+ public void setNClob(int parameterIndex, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().setNClob(parameterIndex, reader);
+ }
+
+ @Override
+ public void setObject(int parameterIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterIndex, x, targetSqlType, scaleOrLength);
+ }
+
+ @Override
+ public void setObject(int parameterIndex, Object x, SQLType targetSqlType) throws SQLException {
+ checkOpen();
+ this.delegate().setObject(parameterIndex, x, targetSqlType);
+ }
+
+ @Override
+ public long executeLargeUpdate() throws SQLException {
+ checkOpen();
+ return this.delegate().executeLargeUpdate();
+ }
+
+}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingResultSet.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingResultSet.java
new file mode 100644
index 00000000000..96593c7135a
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingResultSet.java
@@ -0,0 +1,1349 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLType;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * A JDBC
+ * 4.3-compliant {@link ResultSet} that delegates to another JDBC 4.3-compliant {@link ResultSet}.
+ */
+public class DelegatingResultSet implements ResultSet {
+
+ private final Statement statement;
+
+ private final ResultSet delegate;
+
+ private final SQLRunnable closedChecker;
+
+ private volatile boolean closeable;
+
+ /**
+ * Creates a new {@link DelegatingResultSet}.
+ *
+ * @param statement the {@link Statement} that will be returned by the {@link #getStatement()} method; may be {@code
+ * null}
+ *
+ * @param delegate the {@link ResultSet} to which all operations will be delegated; must not be {@code null}
+ *
+ * @param closeable the initial value for this {@link DelegatingResultSet}'s {@linkplain #isCloseable() closeable}
+ * status
+ *
+ * @param strictClosedChecking if {@code true}, then this {@link DelegatingResultSet}'s {@link #isClosed()}
+ * method will be invoked before every operation that cannot take place on a closed statement, and, if it returns
+ * {@code true}, the operation in question will fail with a {@link SQLException}
+ *
+ * @exception NullPointerException if {@code delegate} is {@code null}
+ */
+ public DelegatingResultSet(Statement statement, ResultSet delegate, boolean closeable, boolean strictClosedChecking) {
+ super();
+ this.statement = statement;
+ this.delegate = Objects.requireNonNull(delegate, "delegate");
+ this.closeable = closeable;
+ this.closedChecker = strictClosedChecking ? this::failWhenClosed : DelegatingResultSet::doNothing;
+ }
+
+ /**
+ * Returns the {@link ResultSet} to which all operations will be delegated.
+ *
+ * This method never returns {@code null}.
+ *
+ * @return the {@link ResultSet} to which all operations will be delegated; never {@code null}
+ */
+ protected final ResultSet delegate() {
+ return this.delegate;
+ }
+
+ /**
+ * Ensures this {@link DelegatingResultSet} is {@linkplain #isClosed() not closed}, if {@linkplain
+ * #DelegatingResultSet(Connection, ResultSet, boolean, boolean) strict closed checking was enabled at construction
+ * time}.
+ *
+ * If a subclass overrides the {@link #isClosed()} method, the override must not call this method or undefined
+ * behavior, such as an infinite loop, may result.
+ *
+ * This method is intended for advanced use cases only and almost all users of this class will have no reason to
+ * call it.
+ *
+ * @exception SQLException if this {@link DelegatingResultSet} was {@linkplain #DelegatingResultSet(Connection,
+ * ResultSet, boolean, boolean) created with strict closed checking enabled} and an invocation of the {@link
+ * #isClosed()} method returns {@code true}, or if some other database access error occurs
+ */
+ protected final void checkOpen() throws SQLException {
+ this.closedChecker.run();
+ }
+
+ // (Invoked by method reference only.)
+ private void failWhenClosed() throws SQLException {
+ if (this.isClosed()) {
+ throw new SQLNonTransientConnectionException("ResultSet is closed", "08000");
+ }
+ }
+
+ /**
+ * Returns {@code true} if a call to {@link #close()} will actually close this {@link DelegatingResultSet}.
+ *
+ * This method returns {@code true} when {@link #setCloseable(boolean)} has been called with a value of {@code
+ * true} and the {@link #isClosed()} method returns {@code false}.
+ *
+ * @return {@code true} if a call to {@link #close()} will actually close this {@link DelegatingResultSet}; {@code
+ * false} in all other cases
+ *
+ * @exception SQLException if {@link #isClosed()} throws a {@link SQLException}
+ *
+ * @see #setCloseable(boolean)
+ *
+ * @see #close()
+ *
+ * @see #isClosed()
+ */
+ public boolean isCloseable() throws SQLException {
+ // this.checkOpen(); // Deliberately omitted.
+ return this.closeable && !this.isClosed();
+ }
+
+ /**
+ * Sets the closeable status of this {@link DelegatingResultSet}.
+ *
+ * Note that calling this method with a value of {@code true} does not necessarily mean that the {@link
+ * #isCloseable()} method will subsequently return {@code true}, since the {@link #isClosed()} method may return
+ * {@code true}.
+ *
+ * @param closeable whether or not a call to {@link #close()} will actually close this {@link DelegatingResultSet}
+ *
+ * @see #isCloseable()
+ *
+ * @see #close()
+ *
+ * @see Statement#close()
+ *
+ * @see #isClosed()
+ */
+ public void setCloseable(boolean closeable) {
+ // this.checkOpen(); // Deliberately omitted.
+ this.closeable = closeable;
+ }
+
+ @Override
+ public boolean next() throws SQLException {
+ checkOpen();
+ return this.delegate().next();
+ }
+
+ @Override
+ public void close() throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
+ this.delegate().close();
+ }
+
+ @Override
+ public boolean wasNull() throws SQLException {
+ checkOpen();
+ return this.delegate().wasNull();
+ }
+
+ @Override
+ public String getString(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getString(columnIndex);
+ }
+
+ @Override
+ public boolean getBoolean(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBoolean(columnIndex);
+ }
+
+ @Override
+ public byte getByte(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getByte(columnIndex);
+ }
+
+ @Override
+ public short getShort(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getShort(columnIndex);
+ }
+
+ @Override
+ public int getInt(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getInt(columnIndex);
+ }
+
+ @Override
+ public long getLong(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getLong(columnIndex);
+ }
+
+ @Override
+ public float getFloat(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getFloat(columnIndex);
+ }
+
+ @Override
+ public double getDouble(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getDouble(columnIndex);
+ }
+
+ @Deprecated
+ @Override
+ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
+ checkOpen();
+ return this.delegate().getBigDecimal(columnIndex, scale);
+ }
+
+ @Override
+ public byte[] getBytes(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBytes(columnIndex);
+ }
+
+ @Override
+ public Date getDate(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getDate(columnIndex);
+ }
+
+ @Override
+ public Time getTime(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getTime(columnIndex);
+ }
+
+ @Override
+ public Timestamp getTimestamp(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getTimestamp(columnIndex);
+ }
+
+ @Override
+ public InputStream getAsciiStream(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getAsciiStream(columnIndex);
+ }
+
+ @Deprecated
+ @Override
+ public InputStream getUnicodeStream(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getUnicodeStream(columnIndex);
+ }
+
+ @Override
+ public InputStream getBinaryStream(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBinaryStream(columnIndex);
+ }
+
+ @Override
+ public String getString(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getString(columnLabel);
+ }
+
+ @Override
+ public boolean getBoolean(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getBoolean(columnLabel);
+ }
+
+ @Override
+ public byte getByte(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getByte(columnLabel);
+ }
+
+ @Override
+ public short getShort(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getShort(columnLabel);
+ }
+
+ @Override
+ public int getInt(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getInt(columnLabel);
+ }
+
+ @Override
+ public long getLong(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getLong(columnLabel);
+ }
+
+ @Override
+ public float getFloat(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getFloat(columnLabel);
+ }
+
+ @Override
+ public double getDouble(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getDouble(columnLabel);
+ }
+
+ @Deprecated
+ @Override
+ public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {
+ checkOpen();
+ return this.delegate().getBigDecimal(columnLabel, scale);
+ }
+
+ @Override
+ public byte[] getBytes(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getBytes(columnLabel);
+ }
+
+ @Override
+ public Date getDate(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getDate(columnLabel);
+ }
+
+ @Override
+ public Time getTime(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getTime(columnLabel);
+ }
+
+ @Override
+ public Timestamp getTimestamp(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getTimestamp(columnLabel);
+ }
+
+ @Override
+ public InputStream getAsciiStream(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getAsciiStream(columnLabel);
+ }
+
+ @Deprecated
+ @Override
+ public InputStream getUnicodeStream(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getUnicodeStream(columnLabel);
+ }
+
+ @Override
+ public InputStream getBinaryStream(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getBinaryStream(columnLabel);
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ checkOpen();
+ return this.delegate().getWarnings();
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ checkOpen();
+ this.delegate().clearWarnings();
+ }
+
+ @Override
+ public String getCursorName() throws SQLException {
+ checkOpen();
+ return this.delegate().getCursorName();
+ }
+
+ @Override
+ public ResultSetMetaData getMetaData() throws SQLException {
+ checkOpen();
+ return this.delegate().getMetaData();
+ }
+
+ @Override
+ public Object getObject(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(columnIndex);
+ }
+
+ @Override
+ public Object getObject(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(columnLabel);
+ }
+
+ @Override
+ public int findColumn(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().findColumn(columnLabel);
+ }
+
+ @Override
+ public Reader getCharacterStream(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getCharacterStream(columnIndex);
+ }
+
+ @Override
+ public Reader getCharacterStream(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getCharacterStream(columnLabel);
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBigDecimal(columnIndex);
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getBigDecimal(columnLabel);
+ }
+
+ @Override
+ public boolean isBeforeFirst() throws SQLException {
+ checkOpen();
+ return this.delegate().isBeforeFirst();
+ }
+
+ @Override
+ public boolean isAfterLast() throws SQLException {
+ checkOpen();
+ return this.delegate().isAfterLast();
+ }
+
+ @Override
+ public boolean isFirst() throws SQLException {
+ checkOpen();
+ return this.delegate().isFirst();
+ }
+
+ @Override
+ public boolean isLast() throws SQLException {
+ checkOpen();
+ return this.delegate().isLast();
+ }
+
+ @Override
+ public void beforeFirst() throws SQLException {
+ checkOpen();
+ this.delegate().beforeFirst();
+ }
+
+ @Override
+ public void afterLast() throws SQLException {
+ checkOpen();
+ this.delegate().afterLast();
+ }
+
+ @Override
+ public boolean first() throws SQLException {
+ checkOpen();
+ return this.delegate().first();
+ }
+
+ @Override
+ public boolean last() throws SQLException {
+ checkOpen();
+ return this.delegate().last();
+ }
+
+ @Override
+ public int getRow() throws SQLException {
+ checkOpen();
+ return this.delegate().getRow();
+ }
+
+ @Override
+ public boolean absolute(int row) throws SQLException {
+ checkOpen();
+ return this.delegate().absolute(row);
+ }
+
+ @Override
+ public boolean relative(int rows) throws SQLException {
+ checkOpen();
+ return this.delegate().relative(rows);
+ }
+
+ @Override
+ public boolean previous() throws SQLException {
+ checkOpen();
+ return this.delegate().previous();
+ }
+
+ @Override
+ public void setFetchDirection(int direction) throws SQLException {
+ checkOpen();
+ this.delegate().setFetchDirection(direction);
+ }
+
+ @Override
+ public int getFetchDirection() throws SQLException {
+ checkOpen();
+ return this.delegate().getFetchDirection();
+ }
+
+ @Override
+ public void setFetchSize(int rows) throws SQLException {
+ checkOpen();
+ this.delegate().setFetchSize(rows);
+ }
+
+ @Override
+ public int getFetchSize() throws SQLException {
+ checkOpen();
+ return this.delegate().getFetchSize();
+ }
+
+ @Override
+ public int getType() throws SQLException {
+ checkOpen();
+ return this.delegate().getType();
+ }
+
+ @Override
+ public int getConcurrency() throws SQLException {
+ checkOpen();
+ return this.delegate().getConcurrency();
+ }
+
+ @Override
+ public boolean rowUpdated() throws SQLException {
+ checkOpen();
+ return this.delegate().rowUpdated();
+ }
+
+ @Override
+ public boolean rowInserted() throws SQLException {
+ checkOpen();
+ return this.delegate().rowInserted();
+ }
+
+ @Override
+ public boolean rowDeleted() throws SQLException {
+ checkOpen();
+ return this.delegate().rowDeleted();
+ }
+
+ @Override
+ public void updateNull(int columnIndex) throws SQLException {
+ checkOpen();
+ this.delegate().updateNull(columnIndex);
+ }
+
+ @Override
+ public void updateBoolean(int columnIndex, boolean x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBoolean(columnIndex, x);
+ }
+
+ @Override
+ public void updateByte(int columnIndex, byte x) throws SQLException {
+ checkOpen();
+ this.delegate().updateByte(columnIndex, x);
+ }
+
+ @Override
+ public void updateShort(int columnIndex, short x) throws SQLException {
+ checkOpen();
+ this.delegate().updateShort(columnIndex, x);
+ }
+
+ @Override
+ public void updateInt(int columnIndex, int x) throws SQLException {
+ checkOpen();
+ this.delegate().updateInt(columnIndex, x);
+ }
+
+ @Override
+ public void updateLong(int columnIndex, long x) throws SQLException {
+ checkOpen();
+ this.delegate().updateLong(columnIndex, x);
+ }
+
+ @Override
+ public void updateFloat(int columnIndex, float x) throws SQLException {
+ checkOpen();
+ this.delegate().updateFloat(columnIndex, x);
+ }
+
+ @Override
+ public void updateDouble(int columnIndex, double x) throws SQLException {
+ checkOpen();
+ this.delegate().updateDouble(columnIndex, x);
+ }
+
+ @Override
+ public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBigDecimal(columnIndex, x);
+ }
+
+ @Override
+ public void updateString(int columnIndex, String x) throws SQLException {
+ checkOpen();
+ this.delegate().updateString(columnIndex, x);
+ }
+
+ @Override
+ public void updateBytes(int columnIndex, byte[] x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBytes(columnIndex, x);
+ }
+
+ @Override
+ public void updateDate(int columnIndex, Date x) throws SQLException {
+ checkOpen();
+ this.delegate().updateDate(columnIndex, x);
+ }
+
+ @Override
+ public void updateTime(int columnIndex, Time x) throws SQLException {
+ checkOpen();
+ this.delegate().updateTime(columnIndex, x);
+ }
+
+ @Override
+ public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
+ checkOpen();
+ this.delegate().updateTimestamp(columnIndex, x);
+ }
+
+ @Override
+ public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().updateAsciiStream(columnIndex, x, length);
+ }
+
+ @Override
+ public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().updateBinaryStream(columnIndex, x, length);
+ }
+
+ @Override
+ public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().updateCharacterStream(columnIndex, x, length);
+ }
+
+ @Override
+ public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException {
+ checkOpen();
+ this.delegate().updateObject(columnIndex, x, scaleOrLength);
+ }
+
+ @Override
+ public void updateObject(int columnIndex, Object x) throws SQLException {
+ checkOpen();
+ this.delegate().updateObject(columnIndex, x);
+ }
+
+ @Override
+ public void updateNull(String columnLabel) throws SQLException {
+ checkOpen();
+ this.delegate().updateNull(columnLabel);
+ }
+
+ @Override
+ public void updateBoolean(String columnLabel, boolean x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBoolean(columnLabel, x);
+ }
+
+ @Override
+ public void updateByte(String columnLabel, byte x) throws SQLException {
+ checkOpen();
+ this.delegate().updateByte(columnLabel, x);
+ }
+
+ @Override
+ public void updateShort(String columnLabel, short x) throws SQLException {
+ checkOpen();
+ this.delegate().updateShort(columnLabel, x);
+ }
+
+ @Override
+ public void updateInt(String columnLabel, int x) throws SQLException {
+ checkOpen();
+ this.delegate().updateInt(columnLabel, x);
+ }
+
+ @Override
+ public void updateLong(String columnLabel, long x) throws SQLException {
+ checkOpen();
+ this.delegate().updateLong(columnLabel, x);
+ }
+
+ @Override
+ public void updateFloat(String columnLabel, float x) throws SQLException {
+ checkOpen();
+ this.delegate().updateFloat(columnLabel, x);
+ }
+
+ @Override
+ public void updateDouble(String columnLabel, double x) throws SQLException {
+ checkOpen();
+ this.delegate().updateDouble(columnLabel, x);
+ }
+
+ @Override
+ public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBigDecimal(columnLabel, x);
+ }
+
+ @Override
+ public void updateString(String columnLabel, String x) throws SQLException {
+ checkOpen();
+ this.delegate().updateString(columnLabel, x);
+ }
+
+ @Override
+ public void updateBytes(String columnLabel, byte[] x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBytes(columnLabel, x);
+ }
+
+ @Override
+ public void updateDate(String columnLabel, Date x) throws SQLException {
+ checkOpen();
+ this.delegate().updateDate(columnLabel, x);
+ }
+
+ @Override
+ public void updateTime(String columnLabel, Time x) throws SQLException {
+ checkOpen();
+ this.delegate().updateTime(columnLabel, x);
+ }
+
+ @Override
+ public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException {
+ checkOpen();
+ this.delegate().updateTimestamp(columnLabel, x);
+ }
+
+ @Override
+ public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().updateAsciiStream(columnLabel, x, length);
+ }
+
+ @Override
+ public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException {
+ checkOpen();
+ this.delegate().updateBinaryStream(columnLabel, x, length);
+ }
+
+ @Override
+ public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException {
+ checkOpen();
+ this.delegate().updateCharacterStream(columnLabel, reader, length);
+ }
+
+ @Override
+ public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException {
+ checkOpen();
+ this.delegate().updateObject(columnLabel, x, scaleOrLength);
+ }
+
+ @Override
+ public void updateObject(String columnLabel, Object x) throws SQLException {
+ checkOpen();
+ this.delegate().updateObject(columnLabel, x);
+ }
+
+ @Override
+ public void insertRow() throws SQLException {
+ checkOpen();
+ this.delegate().insertRow();
+ }
+
+ @Override
+ public void updateRow() throws SQLException {
+ checkOpen();
+ this.delegate().updateRow();
+ }
+
+ @Override
+ public void deleteRow() throws SQLException {
+ checkOpen();
+ this.delegate().deleteRow();
+ }
+
+ @Override
+ public void refreshRow() throws SQLException {
+ checkOpen();
+ this.delegate().refreshRow();
+ }
+
+ @Override
+ public void cancelRowUpdates() throws SQLException {
+ checkOpen();
+ this.delegate().cancelRowUpdates();
+ }
+
+ @Override
+ public void moveToInsertRow() throws SQLException {
+ checkOpen();
+ this.delegate().moveToInsertRow();
+ }
+
+ @Override
+ public void moveToCurrentRow() throws SQLException {
+ checkOpen();
+ this.delegate().moveToCurrentRow();
+ }
+
+ @Override
+ public Statement getStatement() throws SQLException {
+ checkOpen();
+ // NOTE
+ return this.statement;
+ }
+
+ @Override
+ public Object getObject(int columnIndex, Map> map) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(columnIndex, map);
+ }
+
+ @Override
+ public Ref getRef(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getRef(columnIndex);
+ }
+
+ @Override
+ public Blob getBlob(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getBlob(columnIndex);
+ }
+
+ @Override
+ public Clob getClob(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getClob(columnIndex);
+ }
+
+ @Override
+ public Array getArray(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getArray(columnIndex);
+ }
+
+ @Override
+ public Object getObject(String columnLabel, Map> map) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(columnLabel, map);
+ }
+
+ @Override
+ public Ref getRef(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getRef(columnLabel);
+ }
+
+ @Override
+ public Blob getBlob(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getBlob(columnLabel);
+ }
+
+ @Override
+ public Clob getClob(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getClob(columnLabel);
+ }
+
+ @Override
+ public Array getArray(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getArray(columnLabel);
+ }
+
+ @Override
+ public Date getDate(int columnIndex, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getDate(columnIndex, cal);
+ }
+
+ @Override
+ public Date getDate(String columnLabel, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getDate(columnLabel, cal);
+ }
+
+ @Override
+ public Time getTime(int columnIndex, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getTime(columnIndex, cal);
+ }
+
+ @Override
+ public Time getTime(String columnLabel, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getTime(columnLabel, cal);
+ }
+
+ @Override
+ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getTimestamp(columnIndex, cal);
+ }
+
+ @Override
+ public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
+ checkOpen();
+ return this.delegate().getTimestamp(columnLabel, cal);
+ }
+
+ @Override
+ public URL getURL(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getURL(columnIndex);
+ }
+
+ @Override
+ public URL getURL(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getURL(columnLabel);
+ }
+
+ @Override
+ public void updateRef(int columnIndex, Ref x) throws SQLException {
+ checkOpen();
+ this.delegate().updateRef(columnIndex, x);
+ }
+
+ @Override
+ public void updateRef(String columnLabel, Ref x) throws SQLException {
+ checkOpen();
+ this.delegate().updateRef(columnLabel, x);
+ }
+
+ @Override
+ public void updateBlob(int columnIndex, Blob x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBlob(columnIndex, x);
+ }
+
+ @Override
+ public void updateBlob(String columnLabel, Blob x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBlob(columnLabel, x);
+ }
+
+ @Override
+ public void updateClob(int columnIndex, Clob x) throws SQLException {
+ checkOpen();
+ this.delegate().updateClob(columnIndex, x);
+ }
+
+ @Override
+ public void updateClob(String columnLabel, Clob x) throws SQLException {
+ checkOpen();
+ this.delegate().updateClob(columnLabel, x);
+ }
+
+ @Override
+ public void updateArray(int columnIndex, Array x) throws SQLException {
+ checkOpen();
+ this.delegate().updateArray(columnIndex, x);
+ }
+
+ @Override
+ public void updateArray(String columnLabel, Array x) throws SQLException {
+ checkOpen();
+ this.delegate().updateArray(columnLabel, x);
+ }
+
+ @Override
+ public RowId getRowId(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getRowId(columnIndex);
+ }
+
+ @Override
+ public RowId getRowId(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getRowId(columnLabel);
+ }
+
+ @Override
+ public void updateRowId(int columnIndex, RowId x) throws SQLException {
+ checkOpen();
+ this.delegate().updateRowId(columnIndex, x);
+ }
+
+ @Override
+ public void updateRowId(String columnLabel, RowId x) throws SQLException {
+ checkOpen();
+ this.delegate().updateRowId(columnLabel, x);
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ checkOpen();
+ return this.delegate().getHoldability();
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ // this.checkOpen(); // Deliberately omitted per spec.
+ return this.delegate().isClosed();
+ }
+
+ @Override
+ public void updateNString(int columnIndex, String nString) throws SQLException {
+ checkOpen();
+ this.delegate().updateNString(columnIndex, nString);
+ }
+
+ @Override
+ public void updateNString(String columnLabel, String nString) throws SQLException {
+ checkOpen();
+ this.delegate().updateNString(columnLabel, nString);
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
+ checkOpen();
+ this.delegate().updateNClob(columnIndex, nClob);
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, NClob nClob) throws SQLException {
+ checkOpen();
+ this.delegate().updateNClob(columnLabel, nClob);
+ }
+
+ @Override
+ public NClob getNClob(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getNClob(columnIndex);
+ }
+
+ @Override
+ public NClob getNClob(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getNClob(columnLabel);
+ }
+
+ @Override
+ public SQLXML getSQLXML(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getSQLXML(columnIndex);
+ }
+
+ @Override
+ public SQLXML getSQLXML(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getSQLXML(columnLabel);
+ }
+
+ @Override
+ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
+ checkOpen();
+ this.delegate().updateSQLXML(columnIndex, xmlObject);
+ }
+
+ @Override
+ public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
+ checkOpen();
+ this.delegate().updateSQLXML(columnLabel, xmlObject);
+ }
+
+ @Override
+ public String getNString(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getNString(columnIndex);
+ }
+
+ @Override
+ public String getNString(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getNString(columnLabel);
+ }
+
+ @Override
+ public Reader getNCharacterStream(int columnIndex) throws SQLException {
+ checkOpen();
+ return this.delegate().getNCharacterStream(columnIndex);
+ }
+
+ @Override
+ public Reader getNCharacterStream(String columnLabel) throws SQLException {
+ checkOpen();
+ return this.delegate().getNCharacterStream(columnLabel);
+ }
+
+ @Override
+ public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateNCharacterStream(columnIndex, x, length);
+ }
+
+ @Override
+ public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateNCharacterStream(columnLabel, reader, length);
+ }
+
+ @Override
+ public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateAsciiStream(columnIndex, x, length);
+ }
+
+ @Override
+ public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateBinaryStream(columnIndex, x, length);
+ }
+
+ @Override
+ public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateCharacterStream(columnIndex, x, length);
+ }
+
+ @Override
+ public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateAsciiStream(columnLabel, x, length);
+ }
+
+ @Override
+ public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateBinaryStream(columnLabel, x, length);
+ }
+
+ @Override
+ public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateCharacterStream(columnLabel, reader, length);
+ }
+
+ @Override
+ public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateBlob(columnIndex, inputStream, length);
+ }
+
+ @Override
+ public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateBlob(columnLabel, inputStream, length);
+ }
+
+ @Override
+ public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateClob(columnIndex, reader, length);
+ }
+
+ @Override
+ public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateClob(columnLabel, reader, length);
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateNClob(columnIndex, reader, length);
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
+ checkOpen();
+ this.delegate().updateNClob(columnLabel, reader, length);
+ }
+
+ @Override
+ public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
+ checkOpen();
+ this.delegate().updateNCharacterStream(columnIndex, x);
+ }
+
+ @Override
+ public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().updateNCharacterStream(columnLabel, reader);
+ }
+
+ @Override
+ public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
+ checkOpen();
+ this.delegate().updateAsciiStream(columnIndex, x);
+ }
+
+ @Override
+ public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBinaryStream(columnIndex, x);
+ }
+
+ @Override
+ public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
+ checkOpen();
+ this.delegate().updateCharacterStream(columnIndex, x);
+ }
+
+ @Override
+ public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
+ checkOpen();
+ this.delegate().updateAsciiStream(columnLabel, x);
+ }
+
+ @Override
+ public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
+ checkOpen();
+ this.delegate().updateBinaryStream(columnLabel, x);
+ }
+
+ @Override
+ public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().updateCharacterStream(columnLabel, reader);
+ }
+
+ @Override
+ public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
+ checkOpen();
+ this.delegate().updateBlob(columnIndex, inputStream);
+ }
+
+ @Override
+ public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
+ checkOpen();
+ this.delegate().updateBlob(columnLabel, inputStream);
+ }
+
+ @Override
+ public void updateClob(int columnIndex, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().updateClob(columnIndex, reader);
+ }
+
+ @Override
+ public void updateClob(String columnLabel, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().updateClob(columnLabel, reader);
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().updateNClob(columnIndex, reader);
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, Reader reader) throws SQLException {
+ checkOpen();
+ this.delegate().updateNClob(columnLabel, reader);
+ }
+
+ @Override
+ public T getObject(int columnIndex, Class type) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(columnIndex, type);
+ }
+
+ @Override
+ public T getObject(String columnLabel, Class type) throws SQLException {
+ checkOpen();
+ return this.delegate().getObject(columnLabel, type);
+ }
+
+ @Override
+ public void updateObject(int columnIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {
+ checkOpen();
+ this.delegate().updateObject(columnIndex, x, targetSqlType, scaleOrLength);
+ }
+
+ @Override
+ public void updateObject(String columnLabel, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {
+ checkOpen();
+ this.delegate().updateObject(columnLabel, x, targetSqlType, scaleOrLength);
+ }
+
+ @Override
+ public void updateObject(int columnIndex, Object x, SQLType targetSqlType) throws SQLException {
+ checkOpen();
+ this.delegate().updateObject(columnIndex, x, targetSqlType);
+ }
+
+ @Override
+ public void updateObject(String columnLabel, Object x, SQLType targetSqlType) throws SQLException {
+ checkOpen();
+ this.delegate().updateObject(columnLabel, x, targetSqlType);
+ }
+
+ @Override
+ public T unwrap(Class iface) throws SQLException {
+ // checkOpen(); // Deliberately omitted per spec.
+ return iface.isInstance(this) ? iface.cast(this) : this.delegate().unwrap(iface);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ // checkOpen(); // Deliberately omitted per spec.
+ return iface.isInstance(this) || this.delegate().isWrapperFor(iface);
+ }
+
+
+ /*
+ * Static methods.
+ */
+
+
+ // (Invoked by method reference only.)
+ private static void doNothing() {
+
+ }
+
+}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingStatement.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingStatement.java
new file mode 100644
index 00000000000..44640b3228f
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/DelegatingStatement.java
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.Objects;
+
+/**
+ * A JDBC
+ * 4.3-compliant {@link Statement} that delegates to another JDBC 4.3-compliant {@link Statement}.
+ *
+ * @param the type of the {@link Statement} subclass
+ */
+public class DelegatingStatement implements Statement {
+
+ private final Connection connection;
+
+ private final S delegate;
+
+ private final SQLRunnable closedChecker;
+
+ private volatile boolean closeable;
+
+ /**
+ * Creates a new {@link DelegatingStatement}.
+ *
+ * @param connection the {@link Connection} that created this {@link DelegatingStatement}; must not be {@code null}
+ *
+ * @param delegate the {@link Statement} instance to which all operations will be delegated; must not be {@code
+ * null}
+ *
+ * @param closeable the initial value for this {@link DelegatingStatement}'s {@linkplain #isCloseable() closeable}
+ * status
+ *
+ * @param strictClosedChecking if {@code true}, then this {@link DelegatingStatement}'s {@link #isClosed()}
+ * method will be invoked before every operation that cannot take place on a closed statement, and, if it returns
+ * {@code true}, the operation in question will fail with a {@link SQLException}
+ *
+ * @exception NullPointerException if either {@code connection} or {@code delegate} is {@code null}
+ *
+ * @see #getConnection()
+ */
+ public DelegatingStatement(Connection connection,
+ S delegate,
+ boolean closeable,
+ boolean strictClosedChecking) {
+ super();
+ this.connection = Objects.requireNonNull(connection, "connection");
+ this.delegate = Objects.requireNonNull(delegate, "delegate");
+ this.closeable = closeable;
+ this.closedChecker = strictClosedChecking ? this::failWhenClosed : DelegatingStatement::doNothing;
+ }
+
+ /**
+ * Returns the {@link Statement} to which all operations will be delegated.
+ *
+ * This method never returns {@code null}.
+ *
+ * @return the {@link Statement} to which all operations will be delegated; never {@code null}
+ */
+ protected final S delegate() {
+ return this.delegate;
+ }
+
+ /**
+ * Returns {@code true} if a call to {@link #close()} will actually close this {@link DelegatingStatement}.
+ *
+ * This method returns {@code true} when {@link #setCloseable(boolean)} has been called with a value of {@code
+ * true} and the {@link #isClosed()} method returns {@code false}.
+ *
+ * @return {@code true} if a call to {@link #close()} will actually close this {@link DelegatingStatement}; {@code
+ * false} in all other cases
+ *
+ * @exception SQLException if {@link #isClosed()} throws a {@link SQLException}
+ *
+ * @see #setCloseable(boolean)
+ *
+ * @see #close()
+ *
+ * @see #isClosed()
+ */
+ public boolean isCloseable() throws SQLException {
+ return this.closeable && !this.isClosed();
+ }
+
+ /**
+ * Sets the closeable status of this {@link DelegatingStatement}.
+ *
+ * Note that calling this method with a value of {@code true} does not necessarily mean that the {@link
+ * #isCloseable()} method will subsequently return {@code true}, since the {@link #isClosed()} method may return
+ * {@code true}.
+ *
+ * @param closeable whether or not a call to {@link #close()} will actually close this {@link DelegatingStatement}
+ *
+ * @see #isCloseable()
+ *
+ * @see #close()
+ *
+ * @see Statement#close()
+ *
+ * @see #isClosed()
+ */
+ public void setCloseable(boolean closeable) {
+ // this.checkOpen(); // Deliberately omitted.
+ this.closeable = closeable;
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ return this.delegate().isClosed();
+ }
+
+ /**
+ * Overrides the {@link Statement#close()} method so that when it is invoked this {@link DelegatingStatement} is
+ * {@linkplain Statement#close() closed} only if it {@linkplain #isCloseable() is closeable}.
+ *
+ * Overrides should normally call {@code super.close()} as part of their implementation.
+ *
+ * @exception SQLException if an error occurs
+ *
+ * @see #isCloseable()
+ */
+ @Override
+ public void close() throws SQLException {
+ // NOTE
+ if (this.isCloseable()) {
+ this.delegate().close();
+ }
+ }
+
+ @Override
+ public ResultSet executeQuery(String sql) throws SQLException {
+ checkOpen();
+ return
+ new DelegatingResultSet(this, // NOTE
+ this.delegate().executeQuery(sql),
+ true,
+ true);
+ }
+
+ @Override
+ public int executeUpdate(String sql) throws SQLException {
+ checkOpen();
+ return this.delegate().executeUpdate(sql);
+ }
+
+ @Override
+ public int getMaxFieldSize() throws SQLException {
+ checkOpen();
+ return this.delegate().getMaxFieldSize();
+ }
+
+ @Override
+ public void setMaxFieldSize(int max) throws SQLException {
+ checkOpen();
+ this.delegate().setMaxFieldSize(max);
+ }
+
+ @Override
+ public int getMaxRows() throws SQLException {
+ checkOpen();
+ return this.delegate().getMaxRows();
+ }
+
+ @Override
+ public void setMaxRows(int max) throws SQLException {
+ checkOpen();
+ this.delegate().setMaxRows(max);
+ }
+
+ @Override
+ public void setEscapeProcessing(boolean enable) throws SQLException {
+ checkOpen();
+ this.delegate().setEscapeProcessing(enable);
+ }
+
+ @Override
+ public int getQueryTimeout() throws SQLException {
+ checkOpen();
+ return this.delegate().getQueryTimeout();
+ }
+
+ @Override
+ public void setQueryTimeout(int seconds) throws SQLException {
+ checkOpen();
+ this.delegate().setQueryTimeout(seconds);
+ }
+
+ @Override
+ public void cancel() throws SQLException {
+ checkOpen();
+ this.delegate().cancel();
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ checkOpen();
+ return this.delegate().getWarnings();
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ checkOpen();
+ this.delegate().clearWarnings();
+ }
+
+ @Override
+ public void setCursorName(String name) throws SQLException {
+ checkOpen();
+ this.delegate().setCursorName(name);
+ }
+
+ @Override
+ public boolean execute(String sql) throws SQLException {
+ checkOpen();
+ return this.delegate().execute(sql);
+ }
+
+ @Override
+ public ResultSet getResultSet() throws SQLException {
+ checkOpen();
+ return
+ new DelegatingResultSet(this, // NOTE
+ this.delegate().getResultSet(),
+ true,
+ true);
+ }
+
+ @Override
+ public int getUpdateCount() throws SQLException {
+ checkOpen();
+ return this.delegate().getUpdateCount();
+ }
+
+ @Override
+ public boolean getMoreResults() throws SQLException {
+ checkOpen();
+ return this.delegate().getMoreResults();
+ }
+
+ @Override
+ public void setFetchDirection(int direction) throws SQLException {
+ checkOpen();
+ this.delegate().setFetchDirection(direction);
+ }
+
+ @Override
+ public int getFetchDirection() throws SQLException {
+ checkOpen();
+ return this.delegate().getFetchDirection();
+ }
+
+ @Override
+ public void setFetchSize(int rows) throws SQLException {
+ checkOpen();
+ this.delegate().setFetchSize(rows);
+ }
+
+ @Override
+ public int getFetchSize() throws SQLException {
+ checkOpen();
+ return this.delegate().getFetchSize();
+ }
+
+ @Override
+ public int getResultSetConcurrency() throws SQLException {
+ checkOpen();
+ return this.delegate().getResultSetConcurrency();
+ }
+
+ @Override
+ public int getResultSetType() throws SQLException {
+ checkOpen();
+ return this.delegate().getResultSetType();
+ }
+
+ @Override
+ public void addBatch(String sql) throws SQLException {
+ checkOpen();
+ this.delegate().addBatch(sql);
+ }
+
+ @Override
+ public void clearBatch() throws SQLException {
+ checkOpen();
+ this.delegate().clearBatch();
+ }
+
+ @Override
+ public int[] executeBatch() throws SQLException {
+ checkOpen();
+ return this.delegate().executeBatch();
+ }
+
+ /**
+ * Returns the {@link Connection} {@linkplain #DelegatingStatement(Connection, Statement, boolean, boolean) supplied
+ * at construction time}.
+ *
+ * @return the {@link Connection} {@linkplain #DelegatingStatement(Connection, Statement, boolean, boolean) supplied
+ * at construction time}; never {@code null}
+ *
+ * @exception SQLException not thrown by the default implementation of this method
+ *
+ * @see #DelegatingStatement(Connection, Statement, boolean, boolean)
+ */
+ @Override
+ public Connection getConnection() throws SQLException {
+ checkOpen();
+ // NOTE
+ return this.connection;
+ }
+
+ @Override
+ public boolean getMoreResults(int current) throws SQLException {
+ checkOpen();
+ return this.delegate().getMoreResults(current);
+ }
+
+ @Override
+ public ResultSet getGeneratedKeys() throws SQLException {
+ checkOpen();
+ return
+ new DelegatingResultSet(this, // NOTE
+ this.delegate().getGeneratedKeys(),
+ true,
+ true);
+ }
+
+ @Override
+ public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
+ checkOpen();
+ return this.delegate().executeUpdate(sql, autoGeneratedKeys);
+ }
+
+ @Override
+ public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
+ checkOpen();
+ return this.delegate().executeUpdate(sql, columnIndexes);
+ }
+
+ @Override
+ public int executeUpdate(String sql, String[] columnNames) throws SQLException {
+ checkOpen();
+ return this.delegate().executeUpdate(sql, columnNames);
+ }
+
+ @Override
+ public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
+ checkOpen();
+ return this.delegate().execute(sql, autoGeneratedKeys);
+ }
+
+ @Override
+ public boolean execute(String sql, int[] columnIndexes) throws SQLException {
+ checkOpen();
+ return this.delegate().execute(sql, columnIndexes);
+ }
+
+ @Override
+ public boolean execute(String sql, String[] columnNames) throws SQLException {
+ checkOpen();
+ return this.delegate().execute(sql, columnNames);
+ }
+
+ @Override
+ public int getResultSetHoldability() throws SQLException {
+ checkOpen();
+ return this.delegate().getResultSetHoldability();
+ }
+
+ @Override
+ public void setPoolable(boolean poolable) throws SQLException {
+ checkOpen();
+ this.delegate().setPoolable(poolable);
+ }
+
+ @Override
+ public boolean isPoolable() throws SQLException {
+ checkOpen();
+ return this.delegate().isPoolable();
+ }
+
+ @Override
+ public void closeOnCompletion() throws SQLException {
+ checkOpen();
+ this.delegate().closeOnCompletion();
+ }
+
+ @Override
+ public boolean isCloseOnCompletion() throws SQLException {
+ checkOpen();
+ return this.delegate().isCloseOnCompletion();
+ }
+
+ @Override
+ public long getLargeUpdateCount() throws SQLException {
+ checkOpen();
+ return this.delegate().getLargeUpdateCount();
+ }
+
+ @Override
+ public void setLargeMaxRows(long max) throws SQLException {
+ checkOpen();
+ this.delegate().setLargeMaxRows(max);
+ }
+
+ @Override
+ public long getLargeMaxRows() throws SQLException {
+ checkOpen();
+ return this.delegate().getLargeMaxRows();
+ }
+
+ @Override
+ public long[] executeLargeBatch() throws SQLException {
+ checkOpen();
+ return this.delegate().executeLargeBatch();
+ }
+
+ @Override
+ public long executeLargeUpdate(String sql) throws SQLException {
+ checkOpen();
+ return this.delegate().executeLargeUpdate(sql);
+ }
+
+ @Override
+ public long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
+ checkOpen();
+ return this.delegate().executeLargeUpdate(sql, autoGeneratedKeys);
+ }
+
+ @Override
+ public long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
+ checkOpen();
+ return this.delegate().executeLargeUpdate(sql, columnIndexes);
+ }
+
+ @Override
+ public long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
+ checkOpen();
+ return this.delegate().executeLargeUpdate(sql, columnNames);
+ }
+
+ @Override
+ public String enquoteLiteral(String val) throws SQLException {
+ checkOpen();
+ return this.delegate().enquoteLiteral(val);
+ }
+
+ @Override
+ public String enquoteIdentifier(String identifier, boolean alwaysQuote) throws SQLException {
+ checkOpen();
+ return this.delegate().enquoteIdentifier(identifier, alwaysQuote);
+ }
+
+ @Override
+ public boolean isSimpleIdentifier(String identifier) throws SQLException {
+ checkOpen();
+ return this.delegate().isSimpleIdentifier(identifier);
+ }
+
+ @Override
+ public String enquoteNCharLiteral(String val) throws SQLException {
+ checkOpen();
+ return this.delegate().enquoteNCharLiteral(val);
+ }
+
+ @Override
+ public T unwrap(Class iface) throws SQLException {
+ // checkOpen(); // Deliberately omitted
+ return iface.isInstance(this) ? iface.cast(this) : this.delegate().unwrap(iface);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class> iface) throws SQLException {
+ // checkOpen(); // Deliberately omitted
+ return iface.isInstance(this) || this.delegate().isWrapperFor(iface);
+ }
+
+ /**
+ * Ensures this {@link DelegatingStatement} is {@linkplain #isClosed() not closed}, if {@linkplain
+ * #DelegatingStatement(Connection, Statement, boolean, boolean) strict closed checking was enabled at construction
+ * time}.
+ *
+ * If a subclass overrides the {@link #isClosed()} method, the override must not call this method or undefined
+ * behavior, such as an infinite loop, may result.
+ *
+ * This method is intended for advanced use cases only and almost all users of this class will have no reason to
+ * call it.
+ *
+ * @exception SQLException if this {@link DelegatingStatement} was {@linkplain #DelegatingStatement(Connection,
+ * Statement, boolean, boolean) created with strict closed checking enabled} and an invocation of the {@link
+ * #isClosed()} method returns {@code true}, or if some other database access error occurs
+ */
+ protected final void checkOpen() throws SQLException {
+ this.closedChecker.run();
+ }
+
+ // (Invoked by method reference only.)
+ private void failWhenClosed() throws SQLException {
+ if (this.isClosed()) {
+ throw new SQLNonTransientConnectionException("Statement is closed", "08000");
+ }
+ }
+
+
+ /*
+ * Static methods.
+ */
+
+
+ // (Invoked by method reference only.)
+ private static void doNothing() {
+
+ }
+
+}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/SQLBooleanSupplier.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/SQLBooleanSupplier.java
new file mode 100644
index 00000000000..de59b6841f6
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/SQLBooleanSupplier.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.sql.SQLException;
+
+/**
+ * A useful functional interface whose implementations can perform work that may throw a {@link SQLException}.
+ *
+ * @see #getAsBoolean()
+ */
+@FunctionalInterface
+public interface SQLBooleanSupplier {
+
+ /**
+ * Performs work and returns the result.
+ *
+ * @return a {@code boolean}
+ *
+ * @exception SQLException if a database access error occurs
+ */
+ boolean getAsBoolean() throws SQLException;
+
+}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/SQLRunnable.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/SQLRunnable.java
new file mode 100644
index 00000000000..e336339c1d7
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/SQLRunnable.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.sql.SQLException;
+
+/**
+ * A useful functional interface whose implementations can perform work that may throw a {@link SQLException}.
+ *
+ * @see #run()
+ */
+@FunctionalInterface
+public interface SQLRunnable {
+
+ /**
+ * Performs work.
+ *
+ * @exception SQLException if a database access error occurs
+ */
+ void run() throws SQLException;
+
+}
diff --git a/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/UncheckedSQLException.java b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/UncheckedSQLException.java
new file mode 100644
index 00000000000..07ff7e30760
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/main/java/io/helidon/integrations/jdbc/UncheckedSQLException.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.sql.SQLException;
+
+/**
+ * A {@link RuntimeException} that wraps a {@link SQLException}.
+ */
+public final class UncheckedSQLException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Creates a new {@link UncheckedSQLException}.
+ *
+ * @param cause the {@link SQLException} that this {@link UncheckedSQLException} will represent; may be {@code null}
+ */
+ public UncheckedSQLException(SQLException cause) {
+ super(cause);
+ }
+
+ /**
+ * Returns the {@link SQLException} this {@link UncheckedSQLException} represents.
+ *
+ * This method may return {@code null}.
+ *
+ * @return the {@link SQLException} this {@link UncheckedSQLException} represents, or {@code null}
+ */
+ @Override
+ public SQLException getCause() {
+ return (SQLException) super.getCause();
+ }
+
+}
diff --git a/integrations/jdbc/jdbc/src/main/java/module-info.java b/integrations/jdbc/jdbc/src/main/java/module-info.java
index 922b2013542..7d056c0cad6 100644
--- a/integrations/jdbc/jdbc/src/main/java/module-info.java
+++ b/integrations/jdbc/jdbc/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,9 @@
*/
module io.helidon.integrations.jdbc {
+ // Tests use H2 which requires resolution of java.naming at compile time only.
+ requires static java.naming;
+
requires transitive java.sql;
exports io.helidon.integrations.jdbc;
diff --git a/integrations/jdbc/jdbc/src/test/java/io/helidon/integrations/jdbc/TestConditionallyCloseableConnection.java b/integrations/jdbc/jdbc/src/test/java/io/helidon/integrations/jdbc/TestConditionallyCloseableConnection.java
new file mode 100644
index 00000000000..a469e723b3f
--- /dev/null
+++ b/integrations/jdbc/jdbc/src/test/java/io/helidon/integrations/jdbc/TestConditionallyCloseableConnection.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2022 Oracle and/or its affiliates.
+ *
+ * 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.
+ */
+package io.helidon.integrations.jdbc;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import javax.sql.DataSource;
+
+import org.h2.jdbcx.JdbcDataSource;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.CoreMatchers.is;
+
+final class TestConditionallyCloseableConnection {
+
+ private DataSource ds;
+
+ private TestConditionallyCloseableConnection() {
+ super();
+ }
+
+ @BeforeEach
+ final void initializeDataSource() throws SQLException {
+ final JdbcDataSource ds = new JdbcDataSource();
+ ds.setURL("jdbc:h2:mem:test");
+ ds.setUser("sa");
+ ds.setPassword("sa");
+ this.ds = ds;
+ }
+
+ @SuppressWarnings("try")
+ @Test
+ final void testLegacyIsCloseable() throws SQLException {
+ try (@SuppressWarnings("deprecation")
+ final ConditionallyCloseableConnection c = new ConditionallyCloseableConnection(this.ds.getConnection());
+ final Statement s = c.createStatement();
+ final ResultSet rs = s.executeQuery("SHOW TABLES")) {
+ assertThat(rs.next(), is(false)); // no tables
+
+ // ConditionallyCloseableConnections are closeable by default.
+ assertThat(c.isCloseable(), is(true));
+
+ c.setCloseable(false);
+ assertThat(c.isCloseable(), is(false));
+
+ // Closing a ConditionallyCloseableConnection when
+ // isCloseable() returns false does not actually close the delegate.
+ c.close();
+ assertThat(c.delegate().isClosed(), is(false));
+
+ // IN BACKWARDS COMPATIBILITY MODE ONLY, it also does not
+ // make the ConditionallyCloseableConnection itself look
+ // like it is closed.
+ assertThat(c.isClosed(), is(false));
+
+ // Make sure we recorded that a close() attempt happened.
+ assertThat(c.isClosePending(), is(true));
+
+ // We can reset the closeable status.
+ c.setCloseable(true);
+ assertThat(c.isCloseable(), is(true));
+ assertThat(c.isClosed(), is(false));
+
+ // This also wipes out the fact that a close was
+ // previously attempted.
+ assertThat(c.isClosePending(), is(false));
+
+ // Closing a ConditionallyCloseableConnection when
+ // isCloseable() returns true actually irrevocably closes
+ // the connection.
+ c.close(); // closes for real
+ assertThat(c.isClosed(), is(true));
+ assertThat(c.isClosePending(), is(false));
+
+ // Still closed.
+ c.setCloseable(false); // won't matter
+ assertThat(c.isClosed(), is(true));
+ assertThat(c.isClosePending(), is(false));
+
+ // Note that the JDBC specification says that closing a
+ // connection will release "this Connection object's
+ // database and JDBC resources immediately"
+ // (https://docs.oracle.com/en/java/javase/19/docs/api/java.sql/java/sql/Connection.html#close()).
+ // However it is unclear whether a Statement constitutes
+ // either a "database" or a "JDBC resource" in this
+ // context. You would think it would, but H2 does not
+ // close open Statements or ResultSets when their creating
+ // Connection is closed, and neither does PostgreSQL.
+ assertThat(s.isClosed(), is(false));
+ assertThat(rs.isClosed(), is(false));
+ }
+ }
+
+ @SuppressWarnings("try")
+ @Test
+ final void testIsCloseable() throws SQLException {
+ try (final ConditionallyCloseableConnection c = new ConditionallyCloseableConnection(this.ds.getConnection(), true, true);
+ final Statement s = c.createStatement();
+ final ResultSet rs = s.executeQuery("SHOW TABLES")) {
+ assertThat(rs.next(), is(false)); // no tables
+
+ // ConditionallyCloseableConnections are closeable by default.
+ assertThat(c.isCloseable(), is(true));
+
+ c.setCloseable(false);
+ assertThat(c.isCloseable(), is(false));
+
+ // Closing a ConditionallyCloseableConnection when
+ // isCloseable() returns false does not actually close the delegate.
+ c.close();
+ assertThat(c.delegate().isClosed(), is(false));
+
+ // It does make the ConditionallyCloseableConnection
+ // itself look like it is closed, however.
+ assertThat(c.isClosed(), is(true));
+
+ // Make sure we recorded that a close() attempt happened.
+ assertThat(c.isClosePending(), is(true));
+
+ // We can reset the closeable status.
+ c.setCloseable(true);
+ assertThat(c.isCloseable(), is(true));
+ assertThat(c.isClosed(), is(false));
+
+ // This also wipes out the fact that a close was
+ // previously attempted.
+ assertThat(c.isClosePending(), is(false));
+
+ // Closing a ConditionallyCloseableConnection when
+ // isCloseable() returns true actually irrevocably closes
+ // the connection.
+ c.close(); // closes for real
+ assertThat(c.isClosed(), is(true));
+ assertThat(c.isClosePending(), is(false));
+
+ // Still closed.
+ c.setCloseable(false); // won't matter
+ assertThat(c.isClosed(), is(true));
+ assertThat(c.isClosePending(), is(false));
+
+ // Note that the JDBC specification says that closing a
+ // connection will release "this Connection object's
+ // database and JDBC resources immediately"
+ // (https://docs.oracle.com/en/java/javase/19/docs/api/java.sql/java/sql/Connection.html#close()).
+ // However it is unclear whether a Statement constitutes
+ // either a "database" or a "JDBC resource" in this
+ // context. You would think it would, but H2 does not
+ // close open Statements or ResultSets when their creating
+ // Connection is closed, and neither does PostgreSQL.
+ assertThat(s.isClosed(), is(false));
+ assertThat(rs.isClosed(), is(false));
+ }
+ }
+
+}