[#5960] Add a DiagnosticsListener SPI

This commit is contained in:
lukaseder 2018-01-23 18:01:58 +01:00
parent cd176e0ad5
commit 622b3a526c
14 changed files with 1123 additions and 4 deletions

View File

@ -50,6 +50,7 @@ import javax.sql.DataSource;
import org.jooq.conf.Settings;
import org.jooq.impl.DataSourceConnectionProvider;
import org.jooq.impl.DefaultConnectionProvider;
import org.jooq.impl.DefaultDiagnosticsListenerProvider;
import org.jooq.impl.DefaultExecuteListenerProvider;
import org.jooq.impl.DefaultExecutorProvider;
import org.jooq.impl.DefaultRecordListenerProvider;
@ -293,6 +294,12 @@ public interface Configuration extends Serializable {
*/
TransactionListenerProvider[] transactionListenerProviders();
/**
* Get the configured <code>DiagnosticsListenerProvider</code>s from this
* configuration.
*/
DiagnosticsListenerProvider[] diagnosticsListenerProviders();
/**
* Get this configuration's underlying record mapper provider.
*/
@ -651,6 +658,33 @@ public interface Configuration extends Serializable {
*/
Configuration set(TransactionListenerProvider... newTransactionListenerProviders);
/**
* Change this configuration to hold a new diagnostics listeners.
* <p>
* This will wrap the argument {@link DiagnosticsListener} in a
* {@link DefaultDiagnosticsListenerProvider} for convenience.
* <p>
* This method is not thread-safe and should not be used in globally
* available <code>Configuration</code> objects.
*
* @param newDiagnosticsListeners The new diagnostics listeners to be
* contained in the changed configuration.
* @return The changed configuration.
*/
Configuration set(DiagnosticsListener... newDiagnosticsListeners);
/**
* Change this configuration to hold a new diagnostics listener providers.
* <p>
* This method is not thread-safe and should not be used in globally
* available <code>Configuration</code> objects.
*
* @param newDiagnosticsListenerProviders The new diagnostics listener
* providers to be contained in the changed configuration.
* @return The changed configuration.
*/
Configuration set(DiagnosticsListenerProvider... newDiagnosticsListenerProviders);
/**
* Change this configuration to hold a new converter provider.
* <p>
@ -907,6 +941,26 @@ public interface Configuration extends Serializable {
*/
Configuration derive(TransactionListenerProvider... newTransactionListenerProviders);
/**
* Create a derived configuration from this one, with new diagnostics
* listeners.
*
* @param newDiagnosticsListeners The new diagnostics listeners to be
* contained in the derived configuration.
* @return The derived configuration.
*/
Configuration derive(DiagnosticsListener... newDiagnosticsListeners);
/**
* Create a derived configuration from this one, with new diagnostics
* listener providers.
*
* @param newDiagnosticsListenerProviders The new diagnostics listener
* providers to be contained in the derived configuration.
* @return The derived configuration.
*/
Configuration derive(DiagnosticsListenerProvider... newDiagnosticsListenerProviders);
/**
* Create a derived configuration from this one, with new converter
* provider.

View File

@ -216,6 +216,14 @@ public interface DSLContext extends Scope , AutoCloseable {
*/
Connection parsingConnection();
/**
* A JDBC connection that proxies the underlying connection to run the jOOQ
* Diagnostics Pack on executed queries.
* <p>
* <strong>This is experimental functionality.</strong>
*/
Connection diagnosticsConnection();
/**
* Access the database meta data.
* <p>

View File

@ -0,0 +1,76 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
import java.sql.ResultSet;
/**
* A parameter object that is passed to {@link DiagnosticsListener} methods.
*
* @author Lukas Eder
*/
public interface DiagnosticsContext {
/**
* The {@link ResultSet} available in this context, or <code>null</code>, if
* there was no result set.
*/
ResultSet resultSet();
/**
* The number of rows that were fetched from {@link #resultSet()}, or
* <code>-1</code> if there was no result set.
*/
int resultSetFetchedRows();
/**
* The number of rows that were actually available from
* {@link #resultSet()}, or <code>-1</code> if there was no result set.
* <p>
* Calling this method will try to scroll to the end of the
* {@link #resultSet()}, in order to count the number of rows, which incurs
* overhead!
* <p>
* If the result set is still being consumed (i.e. prior to the
* {@link ResultSet#close()} call), and scrolling back to the current row
* after scrolling to the end of {@link #resultSet()} is not possible (e.g.
* because the driver supports only {@link ResultSet#TYPE_FORWARD_ONLY}),
* then this will return the same value as {@link #resultSetFetchedRows()}.
*/
int resultSetActualRows();
}

View File

@ -0,0 +1,62 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
import java.sql.ResultSet;
/**
* A diagnostics listener.
*
* @author Lukas Eder
*/
public interface DiagnosticsListener {
/**
* The fetched JDBC {@link ResultSet} was too large.
* <p>
* An event indicating that a JDBC {@link ResultSet} was fetched with
* <code>A</code> rows, but only <code>B</code> rows (<code>B &lt; A</code>)
* were consumed.
* <p>
* Typically, this problem can be remedied by applying the appropriate
* <code>LIMIT</code> clause in SQL, or {@link SelectLimitStep#limit(int)}
* clause in jOOQ.
*/
void resultSetTooLarge(DiagnosticsContext ctx);
}

View File

@ -0,0 +1,76 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
import org.jooq.impl.DefaultDiagnosticsListenerProvider;
/**
* A provider for {@link TransactionListener} instances.
* <p>
* In order to facilitate the lifecycle management of
* <code>TransactionListener</code> instances that are provided to a jOOQ
* {@link Configuration}, clients can implement this API. To jOOQ, it is thus
* irrelevant, if transaction listeners are stateful or stateless, local to an
* execution, or global to an application.
*
* @author Lukas Eder
* @see TransactionListener
* @see Configuration
*/
@FunctionalInterface
public interface DiagnosticsListenerProvider {
/**
* Provide an <code>DiagnosticsListener</code> instance.
* <p>
* Implementations are free to choose whether this method returns new
* instances at every call or whether the same instance is returned
* repetitively.
* <p>
* The lifecycle of the <code>DiagnosticsListener</code> is not specified.
* New instances can be provided any time clients want to reset their
* diagnostics.
*
* @return A <code>DiagnosticsListener</code> instance.
* @see DiagnosticsListener
* @see DefaultDiagnosticsListenerProvider
*/
DiagnosticsListener provide();
}

View File

@ -59,6 +59,8 @@ import org.jooq.Configuration;
import org.jooq.ConnectionProvider;
import org.jooq.ConverterProvider;
import org.jooq.DSLContext;
import org.jooq.DiagnosticsListener;
import org.jooq.DiagnosticsListenerProvider;
import org.jooq.ExecuteListener;
import org.jooq.ExecuteListenerProvider;
import org.jooq.ExecutorProvider;
@ -115,6 +117,7 @@ public class DefaultConfiguration implements Configuration {
private transient ExecuteListenerProvider[] executeListenerProviders;
private transient VisitListenerProvider[] visitListenerProviders;
private transient TransactionListenerProvider[] transactionListenerProviders;
private transient DiagnosticsListenerProvider[] diagnosticsListenerProviders;
private transient ConverterProvider converterProvider;
// [#7062] Apart from the possibility of containing user defined objects, the data
@ -462,6 +465,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
null,
converterProvider,
null,
@ -472,6 +476,60 @@ public class DefaultConfiguration implements Configuration {
);
}
/**
* Create the actual configuration object.
* <p>
* This constructor has been made package-private to allow for adding new
* configuration properties in the future, without breaking client code.
* Consider creating a configuration by chaining calls to various
* <code>derive()</code> methods.
*
* @deprecated Use
* {@link #DefaultConfiguration(ConnectionProvider, ExecutorProvider, TransactionProvider, RecordMapperProvider, RecordUnmapperProvider, RecordListenerProvider[], ExecuteListenerProvider[], VisitListenerProvider[], TransactionListenerProvider[], DiagnosticsListenerProvider[], ConverterProvider, SQLDialect, Settings, Map)}
* instead. This constructor is maintained to provide jOOQ 3.2,
* 3.3, 3.7, 3.8, 3.9, 3.10 backwards-compatibility if called with
* reflection from Spring configurations.
*/
@Deprecated
DefaultConfiguration(
ConnectionProvider connectionProvider,
ExecutorProvider executorProvider,
TransactionProvider transactionProvider,
RecordMapperProvider recordMapperProvider,
RecordUnmapperProvider recordUnmapperProvider,
RecordListenerProvider[] recordListenerProviders,
ExecuteListenerProvider[] executeListenerProviders,
VisitListenerProvider[] visitListenerProviders,
TransactionListenerProvider[] transactionListenerProviders,
ConverterProvider converterProvider,
Clock clock,
SQLDialect dialect,
Settings settings,
Map<Object, Object> data)
{
this(
connectionProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
recordUnmapperProvider,
recordListenerProviders,
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
null,
converterProvider,
clock,
dialect,
settings,
data
);
}
/**
* Create the actual configuration object.
* <p>
@ -490,6 +548,7 @@ public class DefaultConfiguration implements Configuration {
ExecuteListenerProvider[] executeListenerProviders,
VisitListenerProvider[] visitListenerProviders,
TransactionListenerProvider[] transactionListenerProviders,
DiagnosticsListenerProvider[] diagnosticsListenerProviders,
ConverterProvider converterProvider,
Clock clock,
@ -507,6 +566,7 @@ public class DefaultConfiguration implements Configuration {
set(executeListenerProviders);
set(visitListenerProviders);
set(transactionListenerProviders);
set(diagnosticsListenerProviders);
set(converterProvider);
set(clock);
@ -559,6 +619,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -586,6 +647,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -608,6 +670,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -635,6 +698,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -662,6 +726,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -689,6 +754,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -716,6 +782,7 @@ public class DefaultConfiguration implements Configuration {
newExecuteListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -743,6 +810,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
newVisitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -770,6 +838,35 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
newTransactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
dialect,
settings,
data
);
}
@Override
public final Configuration derive(DiagnosticsListener... newDiagnosticsListeners) {
return derive(DefaultDiagnosticsListenerProvider.providers(newDiagnosticsListeners));
}
@Override
public final Configuration derive(DiagnosticsListenerProvider... newDiagnosticsListenerProviders) {
return new DefaultConfiguration(
connectionProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
recordUnmapperProvider,
recordListenerProviders,
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
newDiagnosticsListenerProviders,
converterProvider,
clock,
@ -792,6 +889,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
newConverterProvider,
clock,
@ -815,6 +913,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
newClock,
dialect,
@ -836,6 +935,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -858,6 +958,7 @@ public class DefaultConfiguration implements Configuration {
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
@ -1004,6 +1105,20 @@ public class DefaultConfiguration implements Configuration {
return this;
}
@Override
public final Configuration set(DiagnosticsListener... newDiagnosticsListeners) {
return set(DefaultDiagnosticsListenerProvider.providers(newDiagnosticsListeners));
}
@Override
public final Configuration set(DiagnosticsListenerProvider... newDiagnosticsListenerProviders) {
this.diagnosticsListenerProviders = newDiagnosticsListenerProviders != null
? newDiagnosticsListenerProviders
: new DiagnosticsListenerProvider[0];
return this;
}
@Override
public final Configuration set(ConverterProvider newConverterProvider) {
this.converterProvider = newConverterProvider != null
@ -1212,6 +1327,11 @@ public class DefaultConfiguration implements Configuration {
return transactionListenerProviders;
}
@Override
public final DiagnosticsListenerProvider[] diagnosticsListenerProviders() {
return diagnosticsListenerProviders;
}
@Override
public final ConverterProvider converterProvider() {
return converterProvider;
@ -1299,6 +1419,7 @@ public class DefaultConfiguration implements Configuration {
oos.writeObject(cloneSerializables(recordListenerProviders));
oos.writeObject(cloneSerializables(visitListenerProviders));
oos.writeObject(cloneSerializables(transactionListenerProviders));
oos.writeObject(cloneSerializables(diagnosticsListenerProviders));
oos.writeObject(converterProvider instanceof Serializable
? converterProvider
@ -1342,6 +1463,7 @@ public class DefaultConfiguration implements Configuration {
recordListenerProviders = (RecordListenerProvider[]) ois.readObject();
visitListenerProviders = (VisitListenerProvider[]) ois.readObject();
transactionListenerProviders = (TransactionListenerProvider[]) ois.readObject();
diagnosticsListenerProviders = (DiagnosticsListenerProvider[]) ois.readObject();
converterProvider = (ConverterProvider) ois.readObject();
data = new ConcurrentHashMap<Object, Object>();

View File

@ -304,7 +304,7 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
}
public DefaultDSLContext(SQLDialect dialect, Settings settings) {
this(new DefaultConfiguration(new NoConnectionProvider(), null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
this(new DefaultConfiguration(new NoConnectionProvider(), null, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
}
public DefaultDSLContext(Connection connection, SQLDialect dialect) {
@ -312,7 +312,7 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
}
public DefaultDSLContext(Connection connection, SQLDialect dialect, Settings settings) {
this(new DefaultConfiguration(new DefaultConnectionProvider(connection), null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
this(new DefaultConfiguration(new DefaultConnectionProvider(connection), null, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
}
public DefaultDSLContext(DataSource datasource, SQLDialect dialect) {
@ -320,7 +320,7 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
}
public DefaultDSLContext(DataSource datasource, SQLDialect dialect, Settings settings) {
this(new DefaultConfiguration(new DataSourceConnectionProvider(datasource), null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
this(new DefaultConfiguration(new DataSourceConnectionProvider(datasource), null, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
}
public DefaultDSLContext(ConnectionProvider connectionProvider, SQLDialect dialect) {
@ -328,7 +328,7 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
}
public DefaultDSLContext(ConnectionProvider connectionProvider, SQLDialect dialect, Settings settings) {
this(new DefaultConfiguration(connectionProvider, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
this(new DefaultConfiguration(connectionProvider, null, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
}
public DefaultDSLContext(Configuration configuration) {
@ -381,6 +381,11 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
return new ParsingConnection(configuration());
}
@Override
public Connection diagnosticsConnection() {
return new DiagnosticsConnection(configuration());
}
@Override
public Meta meta() {
return new MetaImpl(configuration());

View File

@ -0,0 +1,78 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.jooq.DiagnosticsContext;
/**
* @author Lukas Eder
*/
final class DefaultDiagnosticsContext implements DiagnosticsContext {
ResultSet resultSet;
int resultSetFetchedRows;
int resultSetActualRows;
@Override
public final ResultSet resultSet() {
return resultSet;
}
@Override
public final int resultSetFetchedRows() {
return resultSet == null ? -1 : resultSetFetchedRows;
}
@Override
public final int resultSetActualRows() {
if (resultSet == null)
return -1;
try {
while (resultSet.next())
resultSetActualRows++;
resultSet.absolute(resultSetFetchedRows);
}
catch (SQLException ignore) {}
return resultSetActualRows;
}
}

View File

@ -0,0 +1,56 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import org.jooq.DiagnosticsContext;
import org.jooq.DiagnosticsListener;
/**
* A publicly available default implementation of {@link DiagnosticsListener}.
* <p>
* Use this to stay compatible with future API changes (i.e. added methods to
* <code>DiagnosticsListener</code>)
*
* @author Lukas Eder
*/
public class DefaultDiagnosticsListener implements DiagnosticsListener {
@Override
public void resultSetTooLarge(DiagnosticsContext ctx) {}
}

View File

@ -0,0 +1,103 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.io.Serializable;
import org.jooq.DiagnosticsListener;
import org.jooq.DiagnosticsListenerProvider;
/**
* A default implementation for {@link DiagnosticsListenerProvider}.
* <p>
* This implementation just wraps an instance of {@link DiagnosticsListener},
* always providing the same.
*
* @author Lukas Eder
*/
public class DefaultDiagnosticsListenerProvider implements DiagnosticsListenerProvider, Serializable {
/**
* Generated UID.
*/
private static final long serialVersionUID = -2122007794302549679L;
/**
* The delegate listener.
*/
private final DiagnosticsListener listener;
/**
* Convenience method to construct an array of
* <code>DefaultDiagnosticsListenerProvider</code> from an array of
* <code>DiagnosticsListener</code> instances.
*/
public static DiagnosticsListenerProvider[] providers(DiagnosticsListener... listeners) {
DiagnosticsListenerProvider[] result = new DiagnosticsListenerProvider[listeners.length];
for (int i = 0; i < listeners.length; i++)
result[i] = new DefaultDiagnosticsListenerProvider(listeners[i]);
return result;
}
/**
* Create a new provider instance from an argument listener.
*
* @param listener The argument listener.
*/
public DefaultDiagnosticsListenerProvider(DiagnosticsListener listener) {
this.listener = listener;
}
/**
* {@inheritDoc}
*/
@Override
public final DiagnosticsListener provide() {
return listener;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return listener.toString();
}
}

View File

@ -0,0 +1,127 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.jooq.Configuration;
import org.jooq.tools.jdbc.DefaultConnection;
/**
* @author Lukas Eder
*/
final class DiagnosticsConnection extends DefaultConnection {
final Configuration configuration;
final DiagnosticsListeners listeners;
DiagnosticsConnection(Configuration configuration) {
super(configuration.connectionProvider().acquire());
this.configuration = configuration;
this.listeners = DiagnosticsListeners.get(configuration);
}
@Override
public final Statement createStatement() throws SQLException {
return new DiagnosticsStatement(this, getDelegate().createStatement());
}
@Override
public final Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().createStatement(resultSetType, resultSetConcurrency));
}
@Override
public final Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().createStatement(resultSetType, resultSetConcurrency, resultSetHoldability));
}
@Override
public final PreparedStatement prepareStatement(String sql) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareStatement(sql));
}
@Override
public final PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareStatement(sql, resultSetType, resultSetConcurrency));
}
@Override
public final PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability));
}
@Override
public final PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareStatement(sql, autoGeneratedKeys));
}
@Override
public final PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareStatement(sql, columnIndexes));
}
@Override
public final PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareStatement(sql, columnNames));
}
@Override
public final CallableStatement prepareCall(String sql) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareCall(sql));
}
@Override
public final CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareCall(sql, resultSetType, resultSetConcurrency));
}
@Override
public final CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return new DiagnosticsStatement(this, getDelegate().prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability));
}
@Override
public final void close() throws SQLException {
configuration.connectionProvider().release(getDelegate());
}
}

View File

@ -0,0 +1,69 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import org.jooq.Configuration;
import org.jooq.DiagnosticsContext;
import org.jooq.DiagnosticsListener;
import org.jooq.DiagnosticsListenerProvider;
/**
* @author Lukas Eder
*/
final class DiagnosticsListeners implements DiagnosticsListener {
final DiagnosticsListener[] listeners;
DiagnosticsListeners(DiagnosticsListenerProvider[] providers) {
listeners = new DiagnosticsListener[providers.length];
for (int i = 0; i < listeners.length; i++)
listeners[i] = providers[i].provide();
}
static final DiagnosticsListeners get(Configuration configuration) {
return new DiagnosticsListeners(configuration.diagnosticsListenerProviders());
}
@Override
public final void resultSetTooLarge(DiagnosticsContext ctx) {
for (DiagnosticsListener listener : listeners)
listener.resultSetTooLarge(ctx);
}
}

View File

@ -0,0 +1,145 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.jooq.tools.jdbc.DefaultResultSet;
/**
* @author Lukas Eder
*/
final class DiagnosticsResultSet extends DefaultResultSet {
final DiagnosticsConnection connection;
int current;
int rows;
public DiagnosticsResultSet(ResultSet delegate, Statement creator, DiagnosticsConnection connection) {
super(delegate, creator);
this.connection = connection;
}
// ------------------------------------------------------------------------
// XXX Navigational methods
// ------------------------------------------------------------------------
@Override
public void beforeFirst() throws SQLException {
super.beforeFirst();
moveAbsolute(true, super.getRow());
}
@Override
public void afterLast() throws SQLException {
super.afterLast();
moveAbsolute(true, super.getRow());
}
@Override
public boolean first() throws SQLException {
return moveAbsolute(super.first(), super.getRow());
}
@Override
public boolean last() throws SQLException {
return moveAbsolute(super.last(), super.getRow());
}
@Override
public boolean absolute(int row) throws SQLException {
return moveAbsolute(super.absolute(row), super.getRow());
}
@Override
public boolean relative(int relative) throws SQLException {
return moveRelative(super.relative(relative), relative);
}
@Override
public boolean next() throws SQLException {
return moveRelative(super.next(), 1);
}
@Override
public boolean previous() throws SQLException {
return moveRelative(super.previous(), -1);
}
private final boolean moveRelative(boolean success, int relative) {
if (success) {
current = current + relative;
rows = Math.max(rows, current);
}
return success;
}
private final boolean moveAbsolute(boolean success, int absolute) {
if (success) {
current = absolute;
rows = Math.max(rows, current);
}
return success;
}
@Override
public void close() throws SQLException {
try {
if (current < rows)
super.absolute(current = rows);
if (super.next()) {
DefaultDiagnosticsContext ctx = new DefaultDiagnosticsContext();
ctx.resultSet = super.getDelegate();
ctx.resultSetFetchedRows = current;
ctx.resultSetActualRows = current + 1;
connection.listeners.resultSetTooLarge(ctx);
}
}
catch (SQLException ignore) {}
super.close();
}
}

View File

@ -0,0 +1,138 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq.impl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.jooq.tools.jdbc.DefaultCallableStatement;
/**
* @author Lukas Eder
*/
final class DiagnosticsStatement extends DefaultCallableStatement {
private final DiagnosticsConnection connection;
DiagnosticsStatement(DiagnosticsConnection connection, Statement statement) {
super(statement);
this.connection = connection;
}
@Override
public final ResultSet executeQuery(String sql) throws SQLException {
return new DiagnosticsResultSet(super.executeQuery(sql), this, connection);
}
@Override
public final int executeUpdate(String sql) throws SQLException {
return super.executeUpdate(sql);
}
@Override
public final int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
return super.executeUpdate(sql, autoGeneratedKeys);
}
@Override
public final int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
return super.executeUpdate(sql, columnIndexes);
}
@Override
public final int executeUpdate(String sql, String[] columnNames) throws SQLException {
return super.executeUpdate(sql, columnNames);
}
@Override
public final boolean execute(String sql) throws SQLException {
return super.execute(sql);
}
@Override
public final boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
return super.execute(sql, autoGeneratedKeys);
}
@Override
public final boolean execute(String sql, int[] columnIndexes) throws SQLException {
return super.execute(sql, columnIndexes);
}
@Override
public final boolean execute(String sql, String[] columnNames) throws SQLException {
return super.execute(sql, columnNames);
}
@Override
public final long executeLargeUpdate(String sql) throws SQLException {
return super.executeLargeUpdate(sql);
}
@Override
public final long executeLargeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
return super.executeLargeUpdate(sql, autoGeneratedKeys);
}
@Override
public final long executeLargeUpdate(String sql, int[] columnIndexes) throws SQLException {
return super.executeLargeUpdate(sql, columnIndexes);
}
@Override
public final long executeLargeUpdate(String sql, String[] columnNames) throws SQLException {
return super.executeLargeUpdate(sql, columnNames);
}
@Override
public final void addBatch(String sql) throws SQLException {
super.addBatch(sql);
}
@Override
public final Connection getConnection() throws SQLException {
return connection;
}
}