[#5296] [#7162] Add a MetaProvider Configuration.metaProvider() SPI

This commit is contained in:
lukaseder 2018-02-12 14:46:09 +01:00
parent b38859dfa1
commit b5a645a5ff
8 changed files with 292 additions and 12 deletions

View File

@ -254,6 +254,11 @@ public interface Configuration extends Serializable {
*/
ConnectionProvider connectionProvider();
/**
* Get this configuration's underlying meta provider.
*/
MetaProvider metaProvider();
/**
* Get this configuration's underlying executor provider.
* <p>
@ -431,6 +436,18 @@ public interface Configuration extends Serializable {
*/
Configuration set(ConnectionProvider newConnectionProvider);
/**
* Change this configuration to hold a new meta provider.
* <p>
* This method is not thread-safe and should not be used in globally
* available <code>Configuration</code> objects.
*
* @param newMetaProvider The new meta provider to be contained in the
* changed configuration.
* @return The changed configuration.
*/
Configuration set(MetaProvider newMetaProvider);
/**
* Change this configuration to hold a new executor provider.
* <p>
@ -776,6 +793,15 @@ public interface Configuration extends Serializable {
*/
Configuration derive(ConnectionProvider newConnectionProvider);
/**
* Create a derived configuration from this one, with a new meta provider.
*
* @param newMetaProvider The new meta provider to be contained in the
* derived configuration.
* @return The derived configuration.
*/
Configuration derive(MetaProvider newMetaProvider);
/**
* Create a derived configuration from this one, with a new executor.
* <p>

View File

@ -65,6 +65,7 @@ import static org.jooq.SQLDialect.SQLITE;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
@ -250,7 +251,27 @@ public interface DSLContext extends Scope , AutoCloseable {
Meta meta();
/**
* Access the databse meta data from its serialised form.
* Access the database meta data from JDBC {@link DatabaseMetaData}.
*/
Meta meta(DatabaseMetaData meta);
/**
* Access the database meta data from catalog information.
*/
Meta meta(Catalog... catalogs);
/**
* Access the database meta data from schema information.
*/
Meta meta(Schema... schemas);
/**
* Access the database meta data from table information.
*/
Meta meta(Table<?>... tables);
/**
* Access the database meta data from an JAXB-annotated meta model.
*/
Meta meta(InformationSchema schema);

View File

@ -0,0 +1,60 @@
/*
* 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.DatabaseMetaData;
/**
* An SPI that can produce dynamic catalog, schema, table meta data information.
* <p>
* The default implementation will produce information based on
* {@link DatabaseMetaData} obtained from the enclosing
* {@link Configuration#connectionProvider()}.
*
* @author Lukas Eder
*/
@FunctionalInterface
public interface MetaProvider {
/**
* Provide meta data information.
*/
Meta provide();
}

View File

@ -64,6 +64,7 @@ import org.jooq.DiagnosticsListenerProvider;
import org.jooq.ExecuteListener;
import org.jooq.ExecuteListenerProvider;
import org.jooq.ExecutorProvider;
import org.jooq.MetaProvider;
import org.jooq.Record;
import org.jooq.RecordListener;
import org.jooq.RecordListenerProvider;
@ -109,6 +110,7 @@ public class DefaultConfiguration implements Configuration {
// These objects may be user defined and thus not necessarily serialisable
private transient ConnectionProvider connectionProvider;
private transient MetaProvider metaProvider;
private transient ExecutorProvider executorProvider;
private transient TransactionProvider transactionProvider;
private transient RecordMapperProvider recordMapperProvider;
@ -457,6 +459,7 @@ public class DefaultConfiguration implements Configuration {
{
this(
connectionProvider,
null,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -511,6 +514,7 @@ public class DefaultConfiguration implements Configuration {
{
this(
connectionProvider,
null,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -540,6 +544,7 @@ public class DefaultConfiguration implements Configuration {
*/
DefaultConfiguration(
ConnectionProvider connectionProvider,
MetaProvider metaProvider,
ExecutorProvider executorProvider,
TransactionProvider transactionProvider,
RecordMapperProvider recordMapperProvider,
@ -558,6 +563,7 @@ public class DefaultConfiguration implements Configuration {
Map<Object, Object> data)
{
set(connectionProvider);
set(metaProvider);
set(executorProvider);
set(transactionProvider);
set(recordMapperProvider);
@ -611,6 +617,31 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(ConnectionProvider newConnectionProvider) {
return new DefaultConfiguration(
newConnectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
recordUnmapperProvider,
recordListenerProviders,
executeListenerProviders,
visitListenerProviders,
transactionListenerProviders,
diagnosticsListenerProviders,
converterProvider,
clock,
dialect,
settings,
data
);
}
@Override
public final Configuration derive(MetaProvider newMetaProvider) {
return new DefaultConfiguration(
connectionProvider,
newMetaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -639,6 +670,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(ExecutorProvider newExecutorProvider) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
newExecutorProvider,
transactionProvider,
recordMapperProvider,
@ -662,6 +694,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(TransactionProvider newTransactionProvider) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
newTransactionProvider,
recordMapperProvider,
@ -690,6 +723,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(RecordMapperProvider newRecordMapperProvider) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
newRecordMapperProvider,
@ -718,6 +752,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(RecordUnmapperProvider newRecordUnmapperProvider) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -746,6 +781,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(RecordListenerProvider... newRecordListenerProviders) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -774,6 +810,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(ExecuteListenerProvider... newExecuteListenerProviders) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -802,6 +839,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(VisitListenerProvider... newVisitListenerProviders) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -830,6 +868,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(TransactionListenerProvider... newTransactionListenerProviders) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -858,6 +897,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(DiagnosticsListenerProvider... newDiagnosticsListenerProviders) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -881,6 +921,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(ConverterProvider newConverterProvider) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -905,6 +946,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(Clock newClock) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -927,6 +969,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(SQLDialect newDialect) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -950,6 +993,7 @@ public class DefaultConfiguration implements Configuration {
public final Configuration derive(Settings newSettings) {
return new DefaultConfiguration(
connectionProvider,
metaProvider,
executorProvider,
transactionProvider,
recordMapperProvider,
@ -1001,6 +1045,12 @@ public class DefaultConfiguration implements Configuration {
return this;
}
@Override
public final Configuration set(MetaProvider newMetaProvider) {
this.metaProvider = newMetaProvider;
return this;
}
@Override
public final Configuration set(Executor newExecutor) {
return set(new ExecutorWrapper(newExecutor));
@ -1268,6 +1318,13 @@ public class DefaultConfiguration implements Configuration {
return transactional == null ? connectionProvider : transactional;
}
@Override
public final MetaProvider metaProvider() {
return metaProvider != null
? metaProvider
: new DefaultMetaProvider(this);
}
@Override
public final ExecutorProvider executorProvider() {
return executorProvider != null
@ -1405,6 +1462,9 @@ public class DefaultConfiguration implements Configuration {
oos.writeObject(connectionProvider instanceof Serializable
? connectionProvider
: null);
oos.writeObject(metaProvider instanceof Serializable
? metaProvider
: null);
oos.writeObject(transactionProvider instanceof Serializable
? transactionProvider
: null);
@ -1456,6 +1516,7 @@ public class DefaultConfiguration implements Configuration {
ois.defaultReadObject();
connectionProvider = (ConnectionProvider) ois.readObject();
metaProvider = (MetaProvider) ois.readObject();
transactionProvider = (TransactionProvider) ois.readObject();
recordMapperProvider = (RecordMapperProvider) ois.readObject();
recordUnmapperProvider = (RecordUnmapperProvider) ois.readObject();

View File

@ -65,6 +65,7 @@ import java.io.Serializable;
import java.io.StringReader;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
@ -305,7 +306,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, null, dialect, settings, null));
this(new DefaultConfiguration(new NoConnectionProvider(), null, null, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
}
public DefaultDSLContext(Connection connection, SQLDialect dialect) {
@ -313,7 +314,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, null, dialect, settings, null));
this(new DefaultConfiguration(new DefaultConnectionProvider(connection), null, null, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
}
public DefaultDSLContext(DataSource datasource, SQLDialect dialect) {
@ -321,7 +322,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, null, dialect, settings, null));
this(new DefaultConfiguration(new DataSourceConnectionProvider(datasource), null, null, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
}
public DefaultDSLContext(ConnectionProvider connectionProvider, SQLDialect dialect) {
@ -329,7 +330,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, null, dialect, settings, null));
this(new DefaultConfiguration(connectionProvider, null, null, null, null, null, null, null, null, null, null, null, null, dialect, settings, null));
}
public DefaultDSLContext(Configuration configuration) {
@ -399,7 +400,27 @@ public class DefaultDSLContext extends AbstractScope implements DSLContext, Seri
@Override
public Meta meta() {
return new MetaImpl(configuration());
return configuration().metaProvider().provide();
}
@Override
public Meta meta(DatabaseMetaData meta) {
return new MetaImpl(configuration(), meta);
}
@Override
public Meta meta(Catalog... catalogs) {
return null;
}
@Override
public Meta meta(Schema... schemas) {
return null;
}
@Override
public Meta meta(Table<?>... tables) {
return null;
}
@Override

View File

@ -0,0 +1,64 @@
/*
* 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.DatabaseMetaData;
import org.jooq.Configuration;
import org.jooq.Meta;
import org.jooq.MetaProvider;
/**
* A default implementation of the {@link MetaProvider}, which provides meta
* data information based on the JDBC {@link DatabaseMetaData} API.
*
* @author Lukas Eder
*/
public class DefaultMetaProvider implements MetaProvider {
private final Configuration configuration;
public DefaultMetaProvider(Configuration configuration) {
this.configuration = configuration;
}
@Override
public Meta provide() {
return new MetaImpl(configuration, null);
}
}

View File

@ -119,6 +119,7 @@ import org.jooq.SortField;
import org.jooq.Table;
import org.jooq.TableField;
import org.jooq.UniqueKey;
import org.jooq.exception.DataAccessException;
import org.jooq.exception.SQLDialectNotSupportedException;
import org.jooq.tools.StringUtils;
@ -142,11 +143,13 @@ final class MetaImpl implements Meta, Serializable {
private final DSLContext ctx;
private final Configuration configuration;
private final DatabaseMetaData databaseMetaData;
private final boolean inverseSchemaCatalog;
MetaImpl(Configuration configuration) {
MetaImpl(Configuration configuration, DatabaseMetaData databaseMetaData) {
this.ctx = DSL.using(configuration);
this.configuration = configuration;
this.databaseMetaData = databaseMetaData;
this.inverseSchemaCatalog = INVERSE_SCHEMA_CATALOG.contains(configuration.family());
}
@ -155,12 +158,20 @@ final class MetaImpl implements Meta, Serializable {
}
private final Result<Record> meta(final MetaFunction consumer) {
return ctx.connectionResult(new ConnectionCallable<Result<Record>>() {
@Override
public Result<Record> run(Connection connection) throws SQLException {
return consumer.run(connection.getMetaData());
if (databaseMetaData == null)
return ctx.connectionResult(new ConnectionCallable<Result<Record>>() {
@Override
public Result<Record> run(Connection connection) throws SQLException {
return consumer.run(connection.getMetaData());
}
});
else
try {
return consumer.run(databaseMetaData);
}
catch (SQLException e) {
throw new DataAccessException("Error while running MetaFunction", e);
}
});
}
@Override

View File

@ -53,6 +53,7 @@ import org.jooq.DiagnosticsListenerProvider;
import org.jooq.ExecuteListener;
import org.jooq.ExecuteListenerProvider;
import org.jooq.ExecutorProvider;
import org.jooq.MetaProvider;
import org.jooq.RecordListener;
import org.jooq.RecordListenerProvider;
import org.jooq.RecordMapper;
@ -124,6 +125,11 @@ public class MockConfiguration implements Configuration {
return new MockConnectionProvider(delegate.connectionProvider(), provider);
}
@Override
public MetaProvider metaProvider() {
return delegate.metaProvider();
}
@Override
public ExecutorProvider executorProvider() {
return delegate.executorProvider();
@ -206,6 +212,11 @@ public class MockConfiguration implements Configuration {
return delegate.set(newConnectionProvider);
}
@Override
public Configuration set(MetaProvider newMetaProvider) {
return delegate.set(newMetaProvider);
}
@Override
public Configuration set(Connection newConnection) {
return delegate.set(newConnection);
@ -343,6 +354,11 @@ public class MockConfiguration implements Configuration {
return delegate.derive(newConnectionProvider);
}
@Override
public Configuration derive(MetaProvider newMetaProvider) {
return delegate.derive(newMetaProvider);
}
@Override
public Configuration derive(Executor newExecutor) {
return delegate.derive(newExecutor);