Large diffs are not rendered by default.

@@ -39,7 +39,7 @@
import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.internal.proxy.ProxyBuilder;
import org.hibernate.engine.jdbc.spi.ConnectionObserver;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.spi.JdbcResourceRegistry;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.LogicalConnectionImplementor;
@@ -29,7 +29,8 @@
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.Service;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;

@@ -44,6 +45,7 @@ public interface JdbcServices extends Service {
*
* @return The connection provider.
*/
@Deprecated
public ConnectionProvider getConnectionProvider();

/**
@@ -39,7 +39,7 @@
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.internal.CriteriaImpl;
@@ -26,7 +26,7 @@
import java.io.Serializable;

import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;

/**
* Access to services needed in the context of processing transaction requests.
@@ -39,7 +39,7 @@
import org.hibernate.StoredProcedureCall;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.NativeSQLQueryPlan;
import org.hibernate.engine.query.spi.ParameterMetadata;
@@ -333,6 +333,11 @@ public Connection obtainConnection() throws SQLException {
public void releaseConnection(Connection connection) throws SQLException {
connectionProvider.closeConnection( connection );
}

@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}

private class ContextualJdbcConnectionAccess implements JdbcConnectionAccess, Serializable {
@@ -357,5 +362,10 @@ public void releaseConnection(Connection connection) throws SQLException {
}
connectionProvider.releaseConnection( tenantIdentifier, connection );
}

@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}
}
@@ -47,7 +47,7 @@
import org.hibernate.StoredProcedureOutputs;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
import org.hibernate.engine.spi.QueryParameters;
@@ -34,7 +34,7 @@

import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.Metadata;
@@ -47,7 +47,7 @@ public class ObjectName {
/**
* Tries to create an {@code ObjectName} from a name. This form explicitly looks for the form
* {@code catalog.schema.name}. If you need db specific parsing use
* {@link org.hibernate.engine.jdbc.env.spi.SchemaCatalogSupport#parseName} instead
* {@link org.hibernate.service.jdbc.env.spi.QualifiedObjectNameSupport#parseName} instead
*
* @param text simple or qualified name of the database object.
*/
@@ -41,9 +41,11 @@
import org.hibernate.service.jdbc.cursor.internal.RefCursorSupportInitiator;
import org.hibernate.service.jdbc.dialect.internal.DialectFactoryInitiator;
import org.hibernate.service.jdbc.dialect.internal.DialectResolverInitiator;
import org.hibernate.service.jdbc.env.internal.JdbcEnvironmentInitiator;
import org.hibernate.service.jmx.internal.JmxServiceInitiator;
import org.hibernate.service.jndi.internal.JndiServiceInitiator;
import org.hibernate.service.jta.platform.internal.JtaPlatformInitiator;
import org.hibernate.service.schema.internal.SchemaManagementToolInitiator;
import org.hibernate.service.spi.BasicServiceInitiator;
import org.hibernate.tool.hbm2ddl.ImportSqlCommandExtractorInitiator;

@@ -72,9 +74,12 @@ private static List<BasicServiceInitiator> buildStandardServiceInitiatorList() {
serviceInitiators.add( DialectResolverInitiator.INSTANCE );
serviceInitiators.add( DialectFactoryInitiator.INSTANCE );
serviceInitiators.add( BatchBuilderInitiator.INSTANCE );
serviceInitiators.add( JdbcEnvironmentInitiator.INSTANCE );
serviceInitiators.add( JdbcServicesInitiator.INSTANCE );
serviceInitiators.add( RefCursorSupportInitiator.INSTANCE );

serviceInitiators.add( SchemaManagementToolInitiator.INSTANCE );

serviceInitiators.add( MutableIdentifierGeneratorFactoryInitiator.INSTANCE);

serviceInitiators.add( JtaPlatformInitiator.INSTANCE );
@@ -21,15 +21,15 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;
package org.hibernate.service.jdbc.connections.internal;

import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.hibernate.HibernateException;

/**
* Because JDBC (at least up to an including Java 7, JDBC 4) still does not have a notion of
* @author Steve Ebersole
*/
public interface ExistingSequenceMetadataExtractor {
public Iterable<ExistingSequenceMetadata> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException;
public class UserSuppliedConnectionException extends HibernateException {
public UserSuppliedConnectionException() {
super( "The application must supply JDBC connections" );
}
}
@@ -22,6 +22,7 @@
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.jdbc.connections.internal;

import java.sql.Connection;
import java.sql.SQLException;

@@ -55,23 +56,17 @@ public <T> T unwrap(Class<T> unwrapType) {
}
}

/**
* {@inheritDoc}
*/
@Override
public Connection getConnection() throws SQLException {
throw new UnsupportedOperationException( "The application must supply JDBC connections" );
throw new UserSuppliedConnectionException();
}

/**
* {@inheritDoc}
*/
@Override
public void closeConnection(Connection conn) throws SQLException {
throw new UnsupportedOperationException( "The application must supply JDBC connections" );
throw new UserSuppliedConnectionException();
}

/**
* {@inheritDoc}
*/
@Override
public boolean supportsAggressiveRelease() {
return false;
}
@@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.spi;
package org.hibernate.service.jdbc.connections.spi;

import java.io.Serializable;
import java.sql.Connection;
@@ -34,6 +34,30 @@
* @author Steve Ebersole
*/
public interface JdbcConnectionAccess extends Serializable {
/**
* Obtain a JDBC connection
*
* @return The obtained connection
*
* @throws SQLException Indicates a problem getting the connection
*/
public Connection obtainConnection() throws SQLException;

/**
* Release a previously obtained connection
*
* @param connection The connection to release
*
* @throws SQLException Indicates a problem releasing the connection
*/
public void releaseConnection(Connection connection) throws SQLException;

/**
* Does the underlying provider of connections support aggressive releasing of connections (and re-acquisition
* of those connections later, if need be) in JTA environments?
*
* @see ConnectionProvider#supportsAggressiveRelease()
* @see MultiTenantConnectionProvider#supportsAggressiveRelease()
*/
public boolean supportsAggressiveRelease();
}
@@ -0,0 +1,142 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.jdbc.env.internal;

import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.SQLStateType;

/**
* Standard implementation of ExtractedDatabaseMetaData
*
* @author Steve Ebersole
*/
public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData {
private final JdbcEnvironment jdbcEnvironment;

private final boolean supportsRefCursors;
private final boolean supportsNamedParameters;
private final boolean supportsScrollableResults;
private final boolean supportsGetGeneratedKeys;
private final boolean supportsBatchUpdates;
private final boolean supportsDataDefinitionInTransaction;
private final boolean doesDataDefinitionCauseTransactionCommit;
private final SQLStateType sqlStateType;
private final boolean lobLocatorUpdateCopy;

/**
* Form used when {@link java.sql.DatabaseMetaData} is not available.
*
* @param jdbcEnvironment The JDBC environment containing this metadata.
*/
public ExtractedDatabaseMetaDataImpl(JdbcEnvironment jdbcEnvironment) {
this.jdbcEnvironment = jdbcEnvironment;

// if possible, set values that will allow things to still work....
this.supportsRefCursors = false; // Java 8 feature, safest to say not.
this.supportsNamedParameters = false;
this.supportsScrollableResults = true;
this.supportsGetGeneratedKeys = false;
this.supportsBatchUpdates = true;
this.sqlStateType = SQLStateType.UNKNOWN;
this.lobLocatorUpdateCopy = true;

// ugh my favorites...
this.supportsDataDefinitionInTransaction = false;
this.doesDataDefinitionCauseTransactionCommit = false;
}

public ExtractedDatabaseMetaDataImpl(
JdbcEnvironmentImpl jdbcEnvironment,
boolean supportsRefCursors,
boolean supportsNamedParameters,
boolean supportsScrollableResults,
boolean supportsGetGeneratedKeys,
boolean supportsBatchUpdates,
boolean supportsDataDefinitionInTransaction,
boolean doesDataDefinitionCauseTransactionCommit,
SQLStateType sqlStateType,
boolean lobLocatorUpdateCopy) {
this.jdbcEnvironment = jdbcEnvironment;
this.supportsRefCursors = supportsRefCursors;
this.supportsNamedParameters = supportsNamedParameters;
this.supportsScrollableResults = supportsScrollableResults;
this.supportsGetGeneratedKeys = supportsGetGeneratedKeys;
this.supportsBatchUpdates = supportsBatchUpdates;
this.supportsDataDefinitionInTransaction = supportsDataDefinitionInTransaction;
this.doesDataDefinitionCauseTransactionCommit = doesDataDefinitionCauseTransactionCommit;
this.sqlStateType = sqlStateType;
this.lobLocatorUpdateCopy = lobLocatorUpdateCopy;
}

@Override
public JdbcEnvironment getJdbcEnvironment() {
return jdbcEnvironment;
}

@Override
public boolean supportsRefCursors() {
return supportsRefCursors;
}

@Override
public boolean supportsNamedParameters() {
return supportsNamedParameters;
}

@Override
public boolean supportsScrollableResults() {
return supportsScrollableResults;
}

@Override
public boolean supportsGetGeneratedKeys() {
return supportsGetGeneratedKeys;
}

@Override
public boolean supportsBatchUpdates() {
return supportsBatchUpdates;
}

@Override
public boolean supportsDataDefinitionInTransaction() {
return supportsDataDefinitionInTransaction;
}

@Override
public boolean doesDataDefinitionCauseTransactionCommit() {
return doesDataDefinitionCauseTransactionCommit;
}

@Override
public SQLStateType getSqlStateType() {
return sqlStateType;
}

@Override
public boolean doesLobLocatorUpdateCopy() {
return lobLocatorUpdateCopy;
}
}
@@ -0,0 +1,117 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.jdbc.env.internal;

import java.util.Set;

import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.internal.TypeInfo;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.Service;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.QualifiedObjectNameSupport;

/**
* Initial look at this concept we keep talking about with merging information from {@link java.sql.DatabaseMetaData}
* and {@link org.hibernate.dialect.Dialect}
*
* @author Steve Ebersole
*/
public interface JdbcEnvironment extends Service {
/**
* Get the dialect for this environment.
*
* @return The dialect.
*/
public Dialect getDialect();

/**
* Access to the bits of information we pulled off the JDBC {@link java.sql.DatabaseMetaData} (that did not get
* "interpreted" into the helpers/delegates available here).
*
* @return The values extracted from JDBC DatabaseMetaData
*/
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData();

/**
* Get the current database catalog. Typically will come from either {@link java.sql.Connection#getCatalog()}
* or {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
*
* @return The current catalog.
*/
public Identifier getCurrentCatalog();

/**
* Get the current database catalog. Typically will come from either
* {@link org.hibernate.service.jdbc.env.spi.SchemaNameResolver#resolveSchemaName(java.sql.Connection)} or
* {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
*
* @return The current schema
*/
public Identifier getCurrentSchema();

/**
* Obtain support for reading and writing qualified object names.
*
* @return Qualified name support.
*/
public QualifiedObjectNameSupport getQualifiedObjectNameSupport();

/**
* Obtain the helper for dealing with identifiers in this environment.
*
* @return The identifier helper.
*/
public IdentifierHelper getIdentifierHelper();

/**
* Get the complete set of reserved words for this environment. These are significant because they represent
* the complete set of terms that MUST BE quoted if used as identifiers. This allows us to apply auto-quoting
* in the metamodel based on these terms.
*
* Note that the standard IdentifierHelper returned by {@link #getIdentifierHelper()} already accounts for
* auto-quoting :) yaay!
*
* @return Reserved words
*/
public Set<String> getReservedWords();

/**
* Obtain the helper for dealing with JDBC {@link java.sql.SQLException} faults.
*
* @return This environment's helper.
*/
public SqlExceptionHelper getSqlExceptionHelper();

/**
* Find type information for the type identified by the given "JDBC type code".
*
* @param jdbcTypeCode The JDBC type code.
*
* @return The corresponding type info.
*/
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode);
}
@@ -0,0 +1,294 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.jdbc.env.internal;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.internal.TypeInfo;
import org.hibernate.engine.jdbc.internal.TypeInfoExtracter;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.exception.internal.SQLExceptionTypeDelegate;
import org.hibernate.exception.internal.SQLStateConversionDelegate;
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.classloading.spi.ClassLoaderService;
import org.hibernate.service.config.spi.ConfigurationService;
import org.hibernate.service.config.spi.StandardConverters;
import org.hibernate.service.jdbc.cursor.internal.StandardRefCursorSupport;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.LobCreatorBuilder;
import org.hibernate.service.jdbc.env.spi.QualifiedObjectNameSupport;
import org.hibernate.service.jdbc.env.spi.SQLStateType;
import org.hibernate.service.jdbc.env.spi.SchemaNameResolver;
import org.hibernate.service.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl;
import org.hibernate.service.spi.ServiceRegistryImplementor;

/**
* @author Steve Ebersole
*/
public class JdbcEnvironmentImpl implements JdbcEnvironment {
private final ServiceRegistryImplementor serviceRegistry;
private final Dialect dialect;

private final SqlExceptionHelper sqlExceptionHelper;
private final ExtractedDatabaseMetaData extractedMetaDataSupport;
private final Set<String> reservedWords;
private final Identifier currentCatalog;
private final Identifier currentSchema;
private final IdentifierHelper identifierHelper;
private final QualifiedObjectNameSupport qualifiedObjectNameSupport;
private final LobCreatorBuilderImpl lobCreatorBuilder;
private final LinkedHashSet<TypeInfo> typeInfoSet = new LinkedHashSet<TypeInfo>();

/**
* Constructor form used when the JDBC {@link DatabaseMetaData} is not available.
*
* @param serviceRegistry The service registry
* @param dialect The resolved dialect.
*/
public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect) {
this.serviceRegistry = serviceRegistry;
this.dialect = dialect;

this.sqlExceptionHelper = buildSqlExceptionHelper( dialect );
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl( this );

// make sure reserved-words, current-catalog and current-schema happen before the identifier-helper!
this.reservedWords = dialect.getKeywords();
this.currentCatalog = Identifier.toIdentifier(
serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING )
);
this.currentSchema = Identifier.toIdentifier(
serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING )
);

// a simple temporary impl that works on H2
this.identifierHelper = new NormalizingIdentifierHelperImpl(
this,
true, // storesMixedCaseQuotedIdentifiers
false, // storesLowerCaseQuotedIdentifiers
false, // storesUpperCaseQuotedIdentifiers
true, // storesUpperCaseIdentifiers
false // storesLowerCaseIdentifiers
);

// again, a simple temporary impl that works on H2
this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl(
".",
true,
dialect.openQuote(),
dialect.closeQuote()
);

this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder();
}

public JdbcEnvironmentImpl(ServiceRegistryImplementor serviceRegistry, Dialect dialect, DatabaseMetaData dbmd) throws SQLException {
this.serviceRegistry = serviceRegistry;
this.dialect = dialect;

this.sqlExceptionHelper = buildSqlExceptionHelper( dialect );

this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl(
this,
StandardRefCursorSupport.supportsRefCursors( dbmd ),
dbmd.supportsNamedParameters(),
dbmd.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ),
dbmd.supportsGetGeneratedKeys(),
dbmd.supportsBatchUpdates(),
!dbmd.dataDefinitionIgnoredInTransactions(),
dbmd.dataDefinitionCausesTransactionCommit(),
parseSQLStateType( dbmd.getSQLStateType() ),
dbmd.locatorsUpdateCopy()
);

// make sure reserved-words happen before the identifier-helper!
this.reservedWords = buildMergedReservedWords( dialect, dbmd );

this.identifierHelper = new NormalizingIdentifierHelperImpl(
this,
dbmd.storesMixedCaseQuotedIdentifiers(),
dbmd.storesLowerCaseQuotedIdentifiers(),
dbmd.storesUpperCaseQuotedIdentifiers(),
dbmd.storesUpperCaseIdentifiers(),
dbmd.storesLowerCaseIdentifiers()
);

// and that current-catalog and current-schema happen after it
this.currentCatalog = determineCurrentCatalog( dbmd );
this.currentSchema = determineCurrentSchema( dbmd );

this.qualifiedObjectNameSupport = new StandardQualifiedObjectNameSupportImpl(
dbmd.getCatalogSeparator(),
dbmd.isCatalogAtStart(),
dialect.openQuote(),
dialect.closeQuote()
);

this.typeInfoSet.addAll( TypeInfoExtracter.extractTypeInfo( dbmd ) );

this.lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder(
serviceRegistry.getService( ConfigurationService.class ).getSettings(),
dbmd.getConnection()
);
}

private SQLStateType parseSQLStateType(int sqlStateType) {
switch ( sqlStateType ) {
case DatabaseMetaData.sqlStateSQL99 : {
return SQLStateType.SQL99;
}
case DatabaseMetaData.sqlStateXOpen : {
return SQLStateType.XOpen;
}
default : {
return SQLStateType.UNKNOWN;
}
}
}

@SuppressWarnings("deprecation")
private SqlExceptionHelper buildSqlExceptionHelper(Dialect dialect) {
SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter();
if ( sqlExceptionConverter == null ) {
final StandardSQLExceptionConverter converter = new StandardSQLExceptionConverter();
sqlExceptionConverter = converter;
converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() );
converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) );
converter.addDelegate( new SQLStateConversionDelegate( dialect ) );
}
return new SqlExceptionHelper( sqlExceptionConverter );
}

private Identifier determineCurrentCatalog(DatabaseMetaData dbmd) throws SQLException {
String currentCatalogName = dbmd.getConnection().getCatalog();
if ( currentCatalogName != null ) {
// intentionally using fromMetaDataObjectName rather than fromMetaDataCatalogName !!!
return identifierHelper.fromMetaDataObjectName( currentCatalogName );
}
else {
currentCatalogName = serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DEFAULT_CATALOG, StandardConverters.STRING );
return Identifier.toIdentifier( currentCatalogName );
}
}

private Identifier determineCurrentSchema(DatabaseMetaData dbmd) throws SQLException {
String currentSchemaName = locateSchemaNameResolver().resolveSchemaName( dbmd.getConnection() );
if ( currentSchemaName != null ) {
// intentionally using fromMetaDataObjectName rather than fromMetaDataSchemaName !!!
return identifierHelper.fromMetaDataObjectName( currentSchemaName );
}
else {
currentSchemaName = serviceRegistry.getService( ConfigurationService.class )
.getSetting( AvailableSettings.DEFAULT_SCHEMA, StandardConverters.STRING );
return Identifier.toIdentifier( currentSchemaName );
}
}

private SchemaNameResolver locateSchemaNameResolver() {
final Object setting = serviceRegistry.getService( ConfigurationService.class )
.getSettings()
.get( AvailableSettings.SCHEMA_NAME_RESOLVER );
return serviceRegistry.getService( ClassLoaderService.class )
.getStrategyInstanceResolver()
.resolveDefaultableStrategyInstance( setting, SchemaNameResolver.class, TemporarySchemaNameResolver.INSTANCE );
}

private Set<String> buildMergedReservedWords(Dialect dialect, DatabaseMetaData dbmd) throws SQLException {
Set<String> reservedWords = new HashSet<String>();
reservedWords.addAll( dialect.getKeywords() );
// todo : do we need to explicitly handle SQL:2003 keywords?
reservedWords.addAll( Arrays.asList( dbmd.getSQLKeywords().split( "," ) ) );
return reservedWords;
}

@Override
public Dialect getDialect() {
return dialect;
}

@Override
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() {
return extractedMetaDataSupport;
}

@Override
public Identifier getCurrentCatalog() {
return currentCatalog;
}

@Override
public Identifier getCurrentSchema() {
return currentSchema;
}

@Override
public QualifiedObjectNameSupport getQualifiedObjectNameSupport() {
return qualifiedObjectNameSupport;
}

@Override
public IdentifierHelper getIdentifierHelper() {
return identifierHelper;
}

@Override
public Set<String> getReservedWords() {
return reservedWords;
}

@Override
public SqlExceptionHelper getSqlExceptionHelper() {
return sqlExceptionHelper;
}

@Override
public LobCreatorBuilder getLobCreatorBuilder() {
return lobCreatorBuilder;
}

@Override
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) {
for ( TypeInfo typeInfo : typeInfoSet ) {
if ( typeInfo.getJdbcTypeCode() == jdbcTypeCode ) {
return typeInfo;
}
}
return null;
}
}
@@ -0,0 +1,186 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.jdbc.env.internal;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;

import org.jboss.logging.Logger;

import org.hibernate.MultiTenancyStrategy;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.jdbc.connections.internal.UserSuppliedConnectionException;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.spi.BasicServiceInitiator;
import org.hibernate.service.spi.ServiceRegistryImplementor;

/**
* @author Steve Ebersole
*/
public class JdbcEnvironmentInitiator implements BasicServiceInitiator<JdbcEnvironment> {
private static final CoreMessageLogger log = Logger.getMessageLogger(
CoreMessageLogger.class,
JdbcEnvironmentInitiator.class.getName()
);

public static final JdbcEnvironmentInitiator INSTANCE = new JdbcEnvironmentInitiator();

@Override
public Class<JdbcEnvironment> getServiceInitiated() {
return JdbcEnvironment.class;
}

@Override
public JdbcEnvironment initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
final DialectFactory dialectFactory = registry.getService( DialectFactory.class );

boolean useJdbcMetadata = ConfigurationHelper.getBoolean(
"hibernate.temp.use_jdbc_metadata_defaults",
configurationValues,
true
);

if ( useJdbcMetadata ) {
final JdbcConnectionAccess jdbcConnectionAccess = buildJdbcConnectionAccess( configurationValues, registry );
try {
final Connection connection = jdbcConnectionAccess.obtainConnection();
try {
final DatabaseMetaData dbmd = connection.getMetaData();
if ( log.isDebugEnabled() ) {
log.debugf(
"Database ->\n"
+ " name : %s\n"
+ " version : %s\n"
+ " major : %s\n"
+ " minor : %s",
dbmd.getDatabaseProductName(),
dbmd.getDatabaseProductVersion(),
dbmd.getDatabaseMajorVersion(),
dbmd.getDatabaseMinorVersion()
);
log.debugf(
"Driver ->\n"
+ " name : %s\n"
+ " version : %s\n"
+ " major : %s\n"
+ " minor : %s",
dbmd.getDriverName(),
dbmd.getDriverVersion(),
dbmd.getDriverMajorVersion(),
dbmd.getDriverMinorVersion()
);
log.debugf( "JDBC version : %s.%s", dbmd.getJDBCMajorVersion(), dbmd.getJDBCMinorVersion() );
}

return new JdbcEnvironmentImpl(
registry,
dialectFactory.buildDialect( configurationValues, connection ),
dbmd
);
}
catch (SQLException e) {
log.unableToObtainConnectionMetadata( e.getMessage() );
}
finally {
try {
jdbcConnectionAccess.releaseConnection( connection );
}
catch (SQLException ignore) {
}
}
}
catch (Exception e) {
log.unableToObtainConnectionToQueryMetadata( e.getMessage() );
}
}

// if we get here, either we were asked to not use JDBC metadata or accessing the JDBC metadata failed.
return new JdbcEnvironmentImpl( registry, dialectFactory.buildDialect( configurationValues, null ) );
}

private JdbcConnectionAccess buildJdbcConnectionAccess(Map configValues, ServiceRegistryImplementor registry) {
final MultiTenancyStrategy multiTenancyStrategy = MultiTenancyStrategy.determineMultiTenancyStrategy( configValues );
if ( MultiTenancyStrategy.NONE == multiTenancyStrategy ) {
ConnectionProvider connectionProvider = registry.getService( ConnectionProvider.class );
return new ConnectionProviderJdbcConnectionAccess( connectionProvider );
}
else {
final MultiTenantConnectionProvider multiTenantConnectionProvider = registry.getService( MultiTenantConnectionProvider.class );
return new MultiTenantConnectionProviderJdbcConnectionAccess( multiTenantConnectionProvider );
}
}

private static class ConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess {
private final ConnectionProvider connectionProvider;

public ConnectionProviderJdbcConnectionAccess(ConnectionProvider connectionProvider) {
this.connectionProvider = connectionProvider;
}

@Override
public Connection obtainConnection() throws SQLException {
return connectionProvider.getConnection();
}

@Override
public void releaseConnection(Connection connection) throws SQLException {
connectionProvider.closeConnection( connection );
}

@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}

private static class MultiTenantConnectionProviderJdbcConnectionAccess implements JdbcConnectionAccess {
private final MultiTenantConnectionProvider connectionProvider;

public MultiTenantConnectionProviderJdbcConnectionAccess(MultiTenantConnectionProvider connectionProvider) {
this.connectionProvider = connectionProvider;
}

@Override
public Connection obtainConnection() throws SQLException {
return connectionProvider.getAnyConnection();
}

@Override
public void releaseConnection(Connection connection) throws SQLException {
connectionProvider.releaseAnyConnection( connection );
}

@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}
}
@@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.internal;
package org.hibernate.service.jdbc.env.internal;

import java.lang.reflect.Method;
import java.sql.Connection;
@@ -38,49 +38,70 @@
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.jdbc.env.spi.LobCreatorBuilder;

/**
* Builds {@link LobCreator} instances based on the capabilities of the environment.
*
* @author Steve Ebersole
*/
public class LobCreatorBuilder {
public class LobCreatorBuilderImpl implements LobCreatorBuilder {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, LobCreatorBuilderImpl.class.getName());

private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, LobCreatorBuilder.class.getName());
private final boolean useContextualLobCreation;

private boolean useContextualLobCreation;
private LobCreatorBuilderImpl(boolean useContextualLobCreation) {
this.useContextualLobCreation = useContextualLobCreation;
}

@Override
public LobCreator buildLobCreator(LobCreationContext lobCreationContext) {
return useContextualLobCreation
? new ContextualLobCreator( lobCreationContext )
: NonContextualLobCreator.INSTANCE;
}


// factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/**
* The public factory method for obtaining the appropriate (according to given JDBC {@link java.sql.Connection}.
*
* The public factory method for obtaining the appropriate LOB creator (according to given
* JDBC {@link java.sql.Connection}).
*
* @param jdbcConnection A JDBC {@link java.sql.Connection} which can be used to gauge the drivers level of support,
* specifically for creating LOB references.
*/
public LobCreatorBuilder(Map configValues, Connection jdbcConnection) {
this.useContextualLobCreation = useContextualLobCreation( configValues, jdbcConnection );
public static LobCreatorBuilderImpl makeLobCreatorBuilder(Map configValues, Connection jdbcConnection) {
return new LobCreatorBuilderImpl( useContextualLobCreation( configValues, jdbcConnection ) );
}

private static final Class[] NO_ARG_SIG = new Class[0];
private static final Object[] NO_ARGS = new Object[0];

/**
* Basically here we are simply checking whether we can call the {@link Connection} methods for
* LOB creation added in JDBC 4. We not only check whether the {@link Connection} declares these methods,
* but also whether the actual {@link Connection} instance implements them (i.e. can be called without simply
* throwing an exception).
*
* @param jdbcConnection The connection which can be used in level-of-support testing.
* For used when JDBC Connection is not available.
*
* @return True if the connection can be used to create LOBs; false otherwise.
* @return Appropriate LobCreatorBuilder
*/
public static LobCreatorBuilderImpl makeLobCreatorBuilder() {
LOG.disablingContextualLOBCreationSinceConnectionNull();
return new LobCreatorBuilderImpl( false );
}

private static final Class[] NO_ARG_SIG = new Class[0];
private static final Object[] NO_ARGS = new Object[0];

private static boolean useContextualLobCreation(Map configValues, Connection jdbcConnection) {
// Basically here we are simply checking whether we can call the {@link Connection} methods for
// LOB creation added in JDBC 4. We not only check whether the {@link Connection} declares these methods,
// but also whether the actual {@link Connection} instance implements them (i.e. can be called without simply
// throwing an exception).

// First, did the user explicitly configure to use non-contextual creation?
boolean isNonContextualLobCreationRequired =
ConfigurationHelper.getBoolean( Environment.NON_CONTEXTUAL_LOB_CREATION, configValues );
if ( isNonContextualLobCreationRequired ) {
LOG.disablingContextualLOBCreation( Environment.NON_CONTEXTUAL_LOB_CREATION );
return false;
}

if ( jdbcConnection == null ) {
LOG.disablingContextualLOBCreationSinceConnectionNull();
return false;
@@ -126,10 +147,4 @@ private static boolean useContextualLobCreation(Map configValues, Connection jdb

return false;
}

public LobCreator buildLobCreator(LobCreationContext lobCreationContext) {
return useContextualLobCreation
? new ContextualLobCreator( lobCreationContext )
: NonContextualLobCreator.INSTANCE;
}
}
@@ -21,12 +21,12 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.internal;
package org.hibernate.service.jdbc.env.internal;

import org.jboss.logging.Logger;

import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.spi.relational.Identifier;

@@ -21,14 +21,14 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.internal;
package org.hibernate.service.jdbc.env.internal;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
import org.hibernate.service.jdbc.env.spi.SchemaNameResolver;

/**
* Temporary implementation that works for H2.
@@ -0,0 +1 @@
package org.hibernate.service.jdbc.env;
@@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.spi;
package org.hibernate.service.jdbc.env.spi;

import java.util.LinkedHashSet;
import java.util.Set;
@@ -37,12 +37,12 @@
*/
@SuppressWarnings( {"UnusedDeclaration"})
public interface ExtractedDatabaseMetaData {

public enum SQLStateType {
XOpen,
SQL99,
UNKOWN
}
/**
* Obtain the JDBC Environment from which this metadata came.
*
* @return The JDBC environment
*/
public JdbcEnvironment getJdbcEnvironment();

/**
* Does the driver report supporting named parameters?
@@ -107,15 +107,6 @@ public enum SQLStateType {
*/
public boolean doesDataDefinitionCauseTransactionCommit();

/**
* Get the list of extra keywords (beyond standard SQL92 keywords) reported by the driver.
*
* @return The extra keywords used by this database.
*
* @see java.sql.DatabaseMetaData#getSQLKeywords()
*/
public Set<String> getExtraKeywords();

/**
* Retrieve the type of codes the driver says it uses for {@code SQLState}. They might follow either
* the X/Open standard or the SQL92 standard.
@@ -134,36 +125,4 @@ public enum SQLStateType {
* @see java.sql.DatabaseMetaData#locatorsUpdateCopy()
*/
public boolean doesLobLocatorUpdateCopy();

/**
* Retrieve the name of the schema in effect when we connected to the database.
*
* @return The schema name
*/
public String getConnectionSchemaName();

/**
* Retrieve the name of the catalog in effect when we connected to the database.
*
* @return The catalog name
*/
public String getConnectionCatalogName();

/**
* Set of type info reported by the driver.
*
* @return The type information obtained from the driver.
*
* @see java.sql.DatabaseMetaData#getTypeInfo()
*/
public LinkedHashSet<TypeInfo> getTypeInfoSet();

/**
* Set of type info reported by the driver.
*
* @return The type information obtained from the driver.
*
* @see java.sql.DatabaseMetaData#getTypeInfo()
*/
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode);
}
@@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
package org.hibernate.service.jdbc.env.spi;

import org.hibernate.metamodel.spi.relational.Identifier;

@@ -0,0 +1,121 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.jdbc.env.spi;

import java.util.Set;

import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.internal.TypeInfo;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.Service;

/**
* Initial look at this concept we keep talking about with merging information from {@link java.sql.DatabaseMetaData}
* and {@link org.hibernate.dialect.Dialect}
*
* @author Steve Ebersole
*/
public interface JdbcEnvironment extends Service {
/**
* Get the dialect for this environment.
*
* @return The dialect.
*/
public Dialect getDialect();

/**
* Access to the bits of information we pulled off the JDBC {@link java.sql.DatabaseMetaData} (that did not get
* "interpreted" into the helpers/delegates available here).
*
* @return The values extracted from JDBC DatabaseMetaData
*/
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData();

/**
* Get the current database catalog. Typically will come from either {@link java.sql.Connection#getCatalog()}
* or {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
*
* @return The current catalog.
*/
public Identifier getCurrentCatalog();

/**
* Get the current database catalog. Typically will come from either
* {@link SchemaNameResolver#resolveSchemaName(java.sql.Connection)} or
* {@link org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
*
* @return The current schema
*/
public Identifier getCurrentSchema();

/**
* Obtain support for reading and writing qualified object names.
*
* @return Qualified name support.
*/
public QualifiedObjectNameSupport getQualifiedObjectNameSupport();

/**
* Obtain the helper for dealing with identifiers in this environment.
*
* @return The identifier helper.
*/
public IdentifierHelper getIdentifierHelper();

/**
* Get the complete set of reserved words for this environment. These are significant because they represent
* the complete set of terms that MUST BE quoted if used as identifiers. This allows us to apply auto-quoting
* in the metamodel based on these terms.
*
* Note that the standard IdentifierHelper returned by {@link #getIdentifierHelper()} already accounts for
* auto-quoting :) yaay!
*
* @return Reserved words
*/
public Set<String> getReservedWords();

/**
* Obtain the helper for dealing with JDBC {@link java.sql.SQLException} faults.
*
* @return This environment's helper.
*/
public SqlExceptionHelper getSqlExceptionHelper();

/**
* Retrieve the delegate for building {@link org.hibernate.engine.jdbc.LobCreator} instances.
*
* @return The LobCreator builder.
*/
public LobCreatorBuilder getLobCreatorBuilder();

/**
* Find type information for the type identified by the given "JDBC type code".
*
* @param jdbcTypeCode The JDBC type code.
*
* @return The corresponding type info.
*/
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode);
}
@@ -21,35 +21,14 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;
package org.hibernate.service.jdbc.env.spi;

import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;

/**
* Information about existing columns
*
* @author Christoph Sturm
* @author Steve Ebersole
*/
public interface ExistingColumnMetadata {
public ExistingTableMetadata getContainingTableMetadata();

public Identifier getColumnIdentifier();

public TruthValue getNullable();

public int getTypeCode();

public String getTypeName();

public int getColumnSize();

public int getDecimalDigits();
public interface LobCreatorBuilder {
LobCreator buildLobCreator(LobCreationContext lobCreationContext);
}






@@ -21,16 +21,18 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
package org.hibernate.service.jdbc.env.spi;

import org.hibernate.metamodel.spi.relational.ObjectName;

/**
* Defines the support for dealing with schemas and catalogs
* Defines support for reading and writing qualified object names to and from the database. Generally speaking
* Hibernate itself only uses {@link #formatName}. Most times when it is "parsing" object names it is coming from
* mappings, in which case we expect simple dot-separated syntax and apply {@link ObjectName#parse}
*
* @author Steve Ebersole
*/
public interface SchemaCatalogSupport {
public interface QualifiedObjectNameSupport {
/**
* Performs formatting of an ObjectName to its String representation
*
@@ -21,15 +21,15 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;

import org.hibernate.metamodel.spi.relational.ObjectName;
package org.hibernate.service.jdbc.env.spi;

/**
* Access to information about existing sequences
* Enum interpretation of the valid values from {@link java.sql.DatabaseMetaData#getSQLStateType()}
*
* @author Steve Ebersole
*/
public interface ExistingSequenceMetadata {
public ObjectName getSequenceName();
public enum SQLStateType {
XOpen,
SQL99,
UNKNOWN
}
@@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
package org.hibernate.service.jdbc.env.spi;

import java.sql.Connection;
import java.sql.SQLException;
@@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.spi;
package org.hibernate.service.jdbc.env.spi;

import java.util.regex.Pattern;

@@ -33,7 +33,7 @@
/**
* @author Steve Ebersole
*/
public class StandardSchemaCatalogSupportImpl implements SchemaCatalogSupport {
public class StandardQualifiedObjectNameSupportImpl implements QualifiedObjectNameSupport {
public static final char DEFAULT_QUOTE_START = '\'';
public static final char DEFAULT_QUOTE_END = '\'';
public static final String DEFAULT_CATALOG_SEPARATOR = ".";
@@ -45,7 +45,7 @@ public class StandardSchemaCatalogSupportImpl implements SchemaCatalogSupport {

private final Pattern splitPattern;

public StandardSchemaCatalogSupportImpl(
public StandardQualifiedObjectNameSupportImpl(
String catalogSeparator,
boolean catalogAfterName,
char quotedStart,
@@ -60,19 +60,19 @@ public StandardSchemaCatalogSupportImpl(
: Pattern.compile( "[\\." + catalogSeparator + "]" );
}

public StandardSchemaCatalogSupportImpl() {
public StandardQualifiedObjectNameSupportImpl() {
this( DEFAULT_CATALOG_SEPARATOR, false, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END );
}

public StandardSchemaCatalogSupportImpl(String catalogSeparator, boolean catalogAfterName, Dialect dialect) {
public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName, Dialect dialect) {
this( catalogSeparator, catalogAfterName, dialect.openQuote(), dialect.closeQuote() );
}

public StandardSchemaCatalogSupportImpl(Dialect dialect) {
public StandardQualifiedObjectNameSupportImpl(Dialect dialect) {
this( DEFAULT_CATALOG_SEPARATOR, false, dialect );
}

public StandardSchemaCatalogSupportImpl(String catalogSeparator, boolean catalogAfterName) {
public StandardQualifiedObjectNameSupportImpl(String catalogSeparator, boolean catalogAfterName) {
this( catalogSeparator, catalogAfterName, DEFAULT_QUOTE_START, DEFAULT_QUOTE_END );
}

@@ -25,15 +25,17 @@

import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.schema.spi.ExistingColumnMetadata;
import org.hibernate.service.schema.spi.ExistingTableMetadata;
import org.hibernate.service.schema.spi.ColumnInformation;
import org.hibernate.service.schema.spi.TableInformation;

/**
* JDBC column metadata
*
* @author Christoph Sturm
* @author Steve Ebersole
*/
public class ExistingColumnMetadataImpl implements ExistingColumnMetadata {
private final ExistingTableMetadata containingTableMetadata;
public class ColumnInformationImpl implements ColumnInformation {
private final TableInformation containingTableInformation;
private final Identifier columnIdentifier;

private final int typeCode;
@@ -42,15 +44,15 @@ public class ExistingColumnMetadataImpl implements ExistingColumnMetadata {
private final int decimalDigits;
private final TruthValue nullable;

public ExistingColumnMetadataImpl(
ExistingTableMetadata containingTableMetadata,
public ColumnInformationImpl(
TableInformation containingTableInformation,
Identifier columnIdentifier,
int typeCode,
String typeName,
int columnSize,
int decimalDigits,
TruthValue nullable) {
this.containingTableMetadata = containingTableMetadata;
this.containingTableInformation = containingTableInformation;
this.columnIdentifier = columnIdentifier;
this.typeCode = typeCode;
this.typeName = typeName;
@@ -60,8 +62,8 @@ public ExistingColumnMetadataImpl(
}

@Override
public ExistingTableMetadata getContainingTableMetadata() {
return containingTableMetadata;
public TableInformation getContainingTableInformation() {
return containingTableInformation;
}

@Override
@@ -95,7 +97,7 @@ public TruthValue getNullable() {
}

public String toString() {
return "ExistingColumnMetadata(" + columnIdentifier + ')';
return "ColumnInformation(" + columnIdentifier + ')';
}

}
@@ -31,25 +31,25 @@
import java.util.StringTokenizer;

import org.hibernate.TruthValue;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.service.schema.spi.ExistingColumnMetadata;
import org.hibernate.service.schema.spi.ExistingDatabaseMetaData;
import org.hibernate.service.schema.spi.ExistingSequenceMetadata;
import org.hibernate.service.schema.spi.ExistingTableMetadata;
import org.hibernate.service.schema.spi.ColumnInformation;
import org.hibernate.service.schema.spi.DatabaseInformation;
import org.hibernate.service.schema.spi.SequenceInformation;
import org.hibernate.service.schema.spi.TableInformation;

/**
* @author Steve Ebersole
*/
public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData {
public class DatabaseInformationImpl implements DatabaseInformation {
private final JdbcEnvironment jdbcEnvironment;
private final DatabaseMetaData databaseMetaData;

private final Map<ObjectName,ExistingTableMetadataImpl> tables = new HashMap<ObjectName, ExistingTableMetadataImpl>();
private final Map<ObjectName,ExistingSequenceMetadata> sequences;
private final Map<ObjectName,TableInformationImpl> tables = new HashMap<ObjectName, TableInformationImpl>();
private final Map<ObjectName,SequenceInformation> sequences;

public static Builder builder(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) {
try {
@@ -60,7 +60,7 @@ public static Builder builder(JdbcEnvironment jdbcEnvironment, DatabaseMetaData
}
}

private ExistingDatabaseMetaDataImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException {
private DatabaseInformationImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException {
this.jdbcEnvironment = jdbcEnvironment;
this.databaseMetaData = databaseMetaData;
this.sequences = loadSequenceMetadataMap();
@@ -91,30 +91,31 @@ private void loadTableMetadata(ResultSet resultSet) throws SQLException {
);
final ObjectName tableName = new ObjectName( catalogIdentifier, schemaIdentifier, tableIdentifier );
// make sure it does not already exist...
ExistingTableMetadataImpl tableMetadata = tables.get( tableName );
TableInformationImpl tableMetadata = tables.get( tableName );
if ( tableMetadata != null ) {
throw new IllegalStateException( "Table already found on parsing database metadata [" + tableName + "]" );
}

tableMetadata = new ExistingTableMetadataImpl( this, tableName );
tableMetadata = new TableInformationImpl( this, tableName );
tables.put( toMapKey( tableName ), tableMetadata );
}
}

private Map<ObjectName,ExistingSequenceMetadata> loadSequenceMetadataMap() throws SQLException {
Map<ObjectName,ExistingSequenceMetadata> sequences = new HashMap<ObjectName, ExistingSequenceMetadata>();
final Iterable<ExistingSequenceMetadata> sequenceMetadatas =
jdbcEnvironment.getExistingSequenceMetadataExtractor().extractMetadata( databaseMetaData );
private Map<ObjectName,SequenceInformation> loadSequenceMetadataMap() throws SQLException {
Map<ObjectName,SequenceInformation> sequences = new HashMap<ObjectName, SequenceInformation>();
// todo : temporary impl!
final Iterable<SequenceInformation> sequenceMetadatas =
new TemporarySequenceInformationExtractor( jdbcEnvironment ).extractMetadata( databaseMetaData );
if ( sequenceMetadatas != null ) {
for ( ExistingSequenceMetadata sequenceMetadata :sequenceMetadatas ) {
sequences.put( toMapKey( sequenceMetadata.getSequenceName() ), sequenceMetadata );
for ( SequenceInformation sequenceInformation :sequenceMetadatas ) {
sequences.put( toMapKey( sequenceInformation.getSequenceName() ), sequenceInformation );
}
}
return sequences;
}

@Override
public ExistingTableMetadata getTableMetadata(ObjectName tableName) {
public TableInformation getTableInformation(ObjectName tableName) {
return tables.get( toMapKey( tableName ) );
}

@@ -144,18 +145,18 @@ public static ObjectName toMapKey(ObjectName qualifiedName) {
}

@Override
public ExistingSequenceMetadata getSequenceMetadata(ObjectName sequenceName) {
public SequenceInformation getSequenceInformation(ObjectName sequenceName) {
return sequences.get( toMapKey( sequenceName ) );
}

public Map<Identifier, ExistingColumnMetadata> getColumnMetadata(ExistingTableMetadata tableMetadata) {
final Map<Identifier, ExistingColumnMetadata> results = new HashMap<Identifier, ExistingColumnMetadata>();
public Map<Identifier, ColumnInformation> getColumnMetadata(TableInformation tableInformation) {
final Map<Identifier, ColumnInformation> results = new HashMap<Identifier, ColumnInformation>();

try {
ResultSet resultSet = databaseMetaData.getColumns(
identifierHelper().toMetaDataCatalogName( tableMetadata.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableMetadata.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableMetadata.getName().getName() ),
identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ),
"%"
);

@@ -171,8 +172,8 @@ public Map<Identifier, ExistingColumnMetadata> getColumnMetadata(ExistingTableMe
continue;
}

final ExistingColumnMetadataImpl meta = new ExistingColumnMetadataImpl(
tableMetadata,
final ColumnInformationImpl meta = new ColumnInformationImpl(
tableInformation,
columnIdentifier,
resultSet.getInt( "DATA_TYPE" ),
new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(),
@@ -190,16 +191,16 @@ public Map<Identifier, ExistingColumnMetadata> getColumnMetadata(ExistingTableMe
catch (SQLException e) {
throw jdbcEnvironment.getSqlExceptionHelper().convert(
e,
"Error accessing column metadata: " + tableMetadata.getName().toString()
"Error accessing column metadata: " + tableInformation.getName().toString()
);
}

return results;
}

public Map<Identifier, ExistingForeignKeyMetadataImpl> getForeignKeyMetadata(ExistingTableMetadataImpl tableMetadata) {
final Map<Identifier, ExistingForeignKeyMetadataImpl.Builder> fkBuilders
= new HashMap<Identifier, ExistingForeignKeyMetadataImpl.Builder>();
public Map<Identifier, ForeignKeyInformationImpl> getForeignKeyMetadata(TableInformationImpl tableMetadata) {
final Map<Identifier, ForeignKeyInformationImpl.Builder> fkBuilders
= new HashMap<Identifier, ForeignKeyInformationImpl.Builder>();

try {
ResultSet resultSet = databaseMetaData.getImportedKeys(
@@ -214,15 +215,15 @@ public Map<Identifier, ExistingForeignKeyMetadataImpl> getForeignKeyMetadata(Exi
while ( resultSet.next() ) {
// IMPL NOTE : intentionally build the builder early!
final Identifier fkIdentifier = Identifier.toIdentifier( resultSet.getString( "FK_NAME" ) );
ExistingForeignKeyMetadataImpl.Builder fkBuilder = fkBuilders.get( fkIdentifier );
ForeignKeyInformationImpl.Builder fkBuilder = fkBuilders.get( fkIdentifier );
if ( fkBuilder == null ) {
fkBuilder = ExistingForeignKeyMetadataImpl.builder( fkIdentifier );
fkBuilder = ForeignKeyInformationImpl.builder( fkIdentifier );
fkBuilders.put( fkIdentifier, fkBuilder );
}

final ObjectName incomingPkTableName = extractKeyTableName( resultSet, "PK" );

final ExistingTableMetadataImpl pkTableMetadata = tables.get( incomingPkTableName );
final TableInformationImpl pkTableMetadata = tables.get( incomingPkTableName );
if ( pkTableMetadata == null ) {
// the assumption here is that we have not seen this table already based on fully-qualified name
// during previous step of building all table metadata so most likely this is
@@ -235,8 +236,8 @@ public Map<Identifier, ExistingForeignKeyMetadataImpl> getForeignKeyMetadata(Exi
final Identifier pkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "PKCOLUMN_NAME" ) );

fkBuilder.addColumnMapping(
tableMetadata.getColumnMetadata( fkColumnIdentifier ),
pkTableMetadata.getColumnMetadata( pkColumnIdentifier )
tableMetadata.getColumnInformation( fkColumnIdentifier ),
pkTableMetadata.getColumnInformation( pkColumnIdentifier )
);
}
}
@@ -251,9 +252,9 @@ public Map<Identifier, ExistingForeignKeyMetadataImpl> getForeignKeyMetadata(Exi
);
}

final Map<Identifier, ExistingForeignKeyMetadataImpl> fks = new HashMap<Identifier, ExistingForeignKeyMetadataImpl>();
for ( ExistingForeignKeyMetadataImpl.Builder fkBuilder : fkBuilders.values() ) {
ExistingForeignKeyMetadataImpl fk = fkBuilder.build();
final Map<Identifier, ForeignKeyInformationImpl> fks = new HashMap<Identifier, ForeignKeyInformationImpl>();
for ( ForeignKeyInformationImpl.Builder fkBuilder : fkBuilders.values() ) {
ForeignKeyInformationImpl fk = fkBuilder.build();
fks.put( fk.getForeignKeyIdentifier(), fk );
}
return fks;
@@ -285,14 +286,14 @@ public static interface Builder {
public Builder prepareCatalogAndSchema(Schema.Name schemaName);
public Builder prepareCatalog(Identifier catalog);
public Builder prepareSchema(Identifier schema);
public ExistingDatabaseMetaData build();
public DatabaseInformation build();
}

private static class BuilderImpl implements Builder {
private final ExistingDatabaseMetaDataImpl it;
private final DatabaseInformationImpl it;

public BuilderImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException {
it = new ExistingDatabaseMetaDataImpl( jdbcEnvironment, databaseMetaData );
it = new DatabaseInformationImpl( jdbcEnvironment, databaseMetaData );
}

@Override
@@ -355,7 +356,7 @@ public Builder prepareSchema(Identifier schema) {
}

@Override
public ExistingDatabaseMetaData build() {
public DatabaseInformation build() {
return it;
}
}
@@ -27,18 +27,18 @@
import java.util.List;

import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.schema.spi.ExistingColumnMetadata;
import org.hibernate.service.schema.spi.ExistingForeignKeyMetadata;
import org.hibernate.service.schema.spi.ColumnInformation;
import org.hibernate.service.schema.spi.ForeignKeyInformation;
import org.hibernate.service.schema.spi.SchemaManagementException;

/**
* @author Steve Ebersole
*/
public class ExistingForeignKeyMetadataImpl implements ExistingForeignKeyMetadata {
public class ForeignKeyInformationImpl implements ForeignKeyInformation {
private final Identifier fkIdentifier;
private final List<ColumnReferenceMapping> columnMappingList;

public ExistingForeignKeyMetadataImpl(
public ForeignKeyInformationImpl(
Identifier fkIdentifier,
List<ColumnReferenceMapping> columnMappingList) {
this.fkIdentifier = fkIdentifier;
@@ -67,38 +67,38 @@ public Builder(Identifier fkIdentifier) {
this.fkIdentifier = fkIdentifier;
}

public Builder addColumnMapping(ExistingColumnMetadata referencing, ExistingColumnMetadata referenced) {
public Builder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced) {
columnMappingList.add( new ColumnReferenceMappingImpl( referencing, referenced ) );
return this;
}

public ExistingForeignKeyMetadataImpl build() {
public ForeignKeyInformationImpl build() {
if ( columnMappingList.isEmpty() ) {
throw new SchemaManagementException(
"Attempt to resolve foreign key metadata from JDBC metadata failed to find " +
"column mappings for foreign key named [" + fkIdentifier.getText() + "]"
);
}
return new ExistingForeignKeyMetadataImpl( fkIdentifier, columnMappingList );
return new ForeignKeyInformationImpl( fkIdentifier, columnMappingList );
}
}

public static class ColumnReferenceMappingImpl implements ColumnReferenceMapping {
private final ExistingColumnMetadata referencing;
private final ExistingColumnMetadata referenced;
private final ColumnInformation referencing;
private final ColumnInformation referenced;

public ColumnReferenceMappingImpl(ExistingColumnMetadata referencing, ExistingColumnMetadata referenced) {
public ColumnReferenceMappingImpl(ColumnInformation referencing, ColumnInformation referenced) {
this.referencing = referencing;
this.referenced = referenced;
}

@Override
public ExistingColumnMetadata getReferencingColumnMetadata() {
public ColumnInformation getReferencingColumnMetadata() {
return referencing;
}

@Override
public ExistingColumnMetadata getReferencedColumnMetadata() {
public ColumnInformation getReferencedColumnMetadata() {
return referenced;
}
}
@@ -27,41 +27,41 @@
import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.metamodel.spi.relational.Sequence;
import org.hibernate.metamodel.spi.relational.Table;
import org.hibernate.service.schema.spi.ExistingDatabaseMetaData;
import org.hibernate.service.schema.spi.ExistingSequenceMetadata;
import org.hibernate.service.schema.spi.ExistingTableMetadata;
import org.hibernate.service.schema.spi.DatabaseInformation;
import org.hibernate.service.schema.spi.SequenceInformation;
import org.hibernate.service.schema.spi.TableInformation;
import org.hibernate.service.schema.spi.SchemaValidator;

/**
* @author Steve Ebersole
*/
public class SchemaValidatorImpl implements SchemaValidator {
@Override
public void doValidation(Database database, ExistingDatabaseMetaData existingDatabaseMetaData) {
public void doValidation(Database database, DatabaseInformation databaseInformation) {
for ( Schema schema : database.getSchemas() ) {
for ( Table table : schema.getTables() ) {
final ExistingTableMetadata existingTableMetadata = existingDatabaseMetaData.getTableMetadata(
final TableInformation tableInformation = databaseInformation.getTableInformation(
table.getTableName()
);
validateTable( table, existingTableMetadata );
validateTable( table, tableInformation );
}
}

for ( Schema schema : database.getSchemas() ) {
for ( Sequence sequence : schema.getSequences() ) {
final ExistingSequenceMetadata existingSequenceMetadata = existingDatabaseMetaData.getSequenceMetadata(
final SequenceInformation sequenceInformation = databaseInformation.getSequenceInformation(
sequence.getName()
);
validateSequence( sequence, existingSequenceMetadata );
validateSequence( sequence, sequenceInformation );
}
}
}

private void validateTable(Table table, ExistingTableMetadata existingTableMetadata) {
private void validateTable(Table table, TableInformation tableInformation) {
//To change body of created methods use File | Settings | File Templates.
}

private void validateSequence(Sequence sequence, ExistingSequenceMetadata existingSequenceMetadata) {
private void validateSequence(Sequence sequence, SequenceInformation sequenceInformation) {
//To change body of created methods use File | Settings | File Templates.
}
}
@@ -24,17 +24,17 @@
package org.hibernate.service.schema.internal;

import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.schema.spi.ExistingSequenceMetadata;
import org.hibernate.service.schema.spi.SequenceInformation;

/**
* For now we only collect sequence name. If all databases support it, would really like to see INCREMENT here as well.
*
* @author Steve Ebersole
*/
public class ExistingSequenceMetadataImpl implements ExistingSequenceMetadata {
public class SequenceInformationImpl implements SequenceInformation {
private ObjectName sequenceName;

public ExistingSequenceMetadataImpl(ObjectName sequenceName) {
public SequenceInformationImpl(ObjectName sequenceName) {
this.sequenceName = sequenceName;
}

@@ -25,12 +25,11 @@

import java.util.Map;

import org.hibernate.metamodel.spi.relational.ForeignKey;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.schema.spi.ExistingColumnMetadata;
import org.hibernate.service.schema.spi.ExistingForeignKeyMetadata;
import org.hibernate.service.schema.spi.ExistingTableMetadata;
import org.hibernate.service.schema.spi.ColumnInformation;
import org.hibernate.service.schema.spi.ForeignKeyInformation;
import org.hibernate.service.schema.spi.TableInformation;
import org.hibernate.tool.hbm2ddl.IndexMetadata;

/**
@@ -40,14 +39,14 @@
* @author Max Rydahl Andersen
* @author Steve Ebersole
*/
public class ExistingTableMetadataImpl implements ExistingTableMetadata {
private final ExistingDatabaseMetaDataImpl database;
public class TableInformationImpl implements TableInformation {
private final DatabaseInformationImpl database;
private final ObjectName tableName;
private final Map<Identifier, ExistingColumnMetadata> columns;
private final Map<Identifier, ColumnInformation> columns;

private Map<Identifier, ExistingForeignKeyMetadataImpl> foreignKeys;
private Map<Identifier, ForeignKeyInformationImpl> foreignKeys;

public ExistingTableMetadataImpl(ExistingDatabaseMetaDataImpl database, ObjectName tableName) {
public TableInformationImpl(DatabaseInformationImpl database, ObjectName tableName) {
this.database = database;
this.tableName = tableName;
this.columns = database.getColumnMetadata( this );
@@ -59,33 +58,27 @@ public ObjectName getName() {
}

@Override
public ExistingColumnMetadata getColumnMetadata(Identifier columnIdentifier) {
public ColumnInformation getColumnInformation(Identifier columnIdentifier) {
return columns.get( columnIdentifier );
}

@Override
public ExistingForeignKeyMetadata getForeignKeyMetadata(Identifier fkIdentifier) {
public ForeignKeyInformation getForeignKeyInformation(Identifier fkIdentifier) {
if ( foreignKeys == null ) {
foreignKeys = database.getForeignKeyMetadata( this );
}
return foreignKeys.get( fkIdentifier );
}

@Override
public ExistingForeignKeyMetadata getForeignKeyMetadata(ForeignKey fk) {
// Iterator it = foreignKeys.values().iterator();
// while ( it.hasNext() ) {
// ForeignKeyMetadata existingFk = ( ForeignKeyMetadata ) it.next();
// if ( existingFk.matches( fk ) ) {
// return existingFk;
// }
// }
return null;
@SuppressWarnings("unchecked")
public Iterable getForeignKeyInformations() {
return foreignKeys.values();
}

@Override
public String toString() {
return "ExistingTableMetadataImpl(" + tableName.toString() + ')';
return "TableInformationImpl(" + tableName.toString() + ')';
}

@Override
@@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.jdbc.env.internal;
package org.hibernate.service.schema.internal;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
@@ -31,35 +31,35 @@
import java.util.List;

import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.schema.internal.ExistingSequenceMetadataImpl;
import org.hibernate.service.schema.spi.ExistingSequenceMetadata;
import org.hibernate.service.schema.spi.ExistingSequenceMetadataExtractor;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.schema.spi.SequenceInformation;
import org.hibernate.service.schema.spi.SequenceInformationExtractor;

/**
* Temporary implementation that works for H2.
*
* @author Steve Ebersole
*/
public class TemporaryExistingSequenceMetadataExtractor implements ExistingSequenceMetadataExtractor {
private final JdbcEnvironmentImpl jdbcEnvironment;
public class TemporarySequenceInformationExtractor implements SequenceInformationExtractor {
private final JdbcEnvironment jdbcEnvironment;

public TemporaryExistingSequenceMetadataExtractor(JdbcEnvironmentImpl jdbcEnvironment) {
public TemporarySequenceInformationExtractor(JdbcEnvironment jdbcEnvironment) {
this.jdbcEnvironment = jdbcEnvironment;
}

@Override
public Iterable<ExistingSequenceMetadata> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException {
public Iterable<SequenceInformation> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException {
Statement statement = databaseMetaData.getConnection().createStatement();
try {
ResultSet resultSet = statement.executeQuery(
"select SEQUENCE_CATALOG, SEQUENCE_SCHEMA, SEQUENCE_NAME " +
"from information_schema.sequences"
);
try {
final List<ExistingSequenceMetadata> sequenceMetadataList = new ArrayList<ExistingSequenceMetadata>();
final List<SequenceInformation> sequenceInformationList = new ArrayList<SequenceInformation>();
while ( resultSet.next() ) {
sequenceMetadataList.add(
new ExistingSequenceMetadataImpl(
sequenceInformationList.add(
new SequenceInformationImpl(
new ObjectName(
jdbcEnvironment.getIdentifierHelper().fromMetaDataCatalogName(
resultSet.getString(
@@ -80,7 +80,7 @@ public Iterable<ExistingSequenceMetadata> extractMetadata(DatabaseMetaData datab
)
);
}
return sequenceMetadataList;
return sequenceInformationList;
}
finally {
try {
@@ -0,0 +1,92 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;

import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;

/**
* Provides access to information about existing table columns
*
* @author Christoph Sturm
* @author Steve Ebersole
*/
public interface ColumnInformation {
/**
* Access to the containing table.
*
* @return The containing table information
*/
public TableInformation getContainingTableInformation();

/**
* The simple (not qualified) column name.
*
* @return The column simple identifier.
*/
public Identifier getColumnIdentifier();

/**
* Is the column nullable. The database is allowed to report unknown, hence the use of TruthValue
*
* @return nullability.
*/
public TruthValue getNullable();

/**
* The JDBC type-code.
*
* @return JDBC type-code
*/
public int getTypeCode();

/**
* The database specific type name.
*
* @return Type name
*/
public String getTypeName();

// todo : wrap these in org.hibernate.metamodel.spi.relational.Size ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/**
* The column size (length).
*
* @return The column length
*/
public int getColumnSize();

/**
* The precision, for numeric types
*
* @return The numeric precision
*/
public int getDecimalDigits();
}






@@ -23,27 +23,31 @@
*/
package org.hibernate.service.schema.spi;

import org.hibernate.metamodel.spi.relational.ForeignKey;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.hbm2ddl.ForeignKeyMetadata;
import org.hibernate.tool.hbm2ddl.IndexMetadata;

/**
* Provides access to information about existing schema objects (tables, sequences etc) of existing database.
*
* @author Christoph Sturm
* @author Max Rydahl Andersen
* @author Teodor Danciu
* @author Steve Ebersole
*/
public interface ExistingTableMetadata {
public ObjectName getName();
public interface DatabaseInformation {
/**
* Obtain reference to the named TableInformation
*
* @param tableName The qualified table name
*
* @return The table information. May return {@code null} if not found.
*/
public TableInformation getTableInformation(ObjectName tableName);

public ExistingColumnMetadata getColumnMetadata(Identifier columnIdentifier);

public ExistingForeignKeyMetadata getForeignKeyMetadata(Identifier keyName);

public ExistingForeignKeyMetadata getForeignKeyMetadata(ForeignKey fk);

public IndexMetadata getIndexMetadata(Identifier indexName);
/**
* Obtain reference to the named SequenceInformation
*
* @param sequenceName The qualified sequence name
*
* @return The sequence information. May return {@code null} if not found.
*/
public SequenceInformation getSequenceInformation(ObjectName sequenceName);
}
@@ -30,7 +30,7 @@
/**
* @author Steve Ebersole
*/
public interface ExistingForeignKeyMetadata {
public interface ForeignKeyInformation {
/**
* Obtain the identifier for this FK.
*
@@ -52,13 +52,13 @@ public static interface ColumnReferenceMapping {
*
* @return The referencing column.
*/
public ExistingColumnMetadata getReferencingColumnMetadata();
public ColumnInformation getReferencingColumnMetadata();

/**
* Obtain the information about the referenced column (the target side).
*
* @return The referenced column
*/
public ExistingColumnMetadata getReferencedColumnMetadata();
public ColumnInformation getReferencedColumnMetadata();
}
}
@@ -42,5 +42,5 @@ public interface SchemaMigrator {
*
* @throws SchemaManagementException
*/
public void doMigration(Database database, ExistingDatabaseMetaData existingDatabase, List<Target> targets) throws SchemaManagementException;
public void doMigration(Database database, DatabaseInformation existingDatabase, List<Target> targets) throws SchemaManagementException;
}
@@ -35,9 +35,9 @@ public interface SchemaValidator {
* Handle schema validation requests
*
* @param database The current Hibernate relational model
* @param existingDatabaseMetaData Access to the existing database information.
* @param databaseInformation Access to the existing database information.
*
* @throws SchemaManagementException
*/
public void doValidation(Database database, ExistingDatabaseMetaData existingDatabaseMetaData) throws SchemaManagementException;
public void doValidation(Database database, DatabaseInformation databaseInformation) throws SchemaManagementException;
}
@@ -26,13 +26,18 @@
import org.hibernate.metamodel.spi.relational.ObjectName;

/**
* Provides access to information about existing schema objects (tables, sequences etc) of existing database.
* Access to information about existing sequences.
*
* For now we only support retrieving the names (for existence checking from validation). However,
* at least INCREMENT would be valuable as well. Just need to make sure all dbs support that.
*
* @author Christoph Sturm
* @author Teodor Danciu
* @author Steve Ebersole
*/
public interface ExistingDatabaseMetaData {
public ExistingTableMetadata getTableMetadata(ObjectName tableName);
public ExistingSequenceMetadata getSequenceMetadata(ObjectName sequenceName);
public interface SequenceInformation {
/**
* The qualified sequence name.
*
* @return The sequence name
*/
public ObjectName getSequenceName();
}
@@ -0,0 +1,47 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;

import java.sql.DatabaseMetaData;
import java.sql.SQLException;

/**
* Because JDBC (at least up to an including Java 7, JDBC 4) still does not have support for obtaining information
* about sequences from DatabaseMetaData.
*
* @author Steve Ebersole
*/
public interface SequenceInformationExtractor {
/**
* Get the information about sequences.
*
* @param databaseMetaData The JDBC DatabaseMetadata
*
* @return The extracted information about existing sequences.
*
* @throws SQLException Don't bother handling SQLExceptions (unless you want to), we will deal with them in the
* caller.
*/
public Iterable<SequenceInformation> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException;
}
@@ -0,0 +1,75 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.service.schema.spi;

import org.hibernate.metamodel.spi.relational.ForeignKey;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.hbm2ddl.IndexMetadata;

/**
* Provides access to information about existing tables in the database
*
* @author Christoph Sturm
* @author Max Rydahl Andersen
* @author Steve Ebersole
*/
public interface TableInformation {
/**
* Get the qualified name of the table.
*
* @return The qualified table name
*/
public ObjectName getName();

/**
* Retrieve the named ColumnInformation
*
* @param columnIdentifier The column identifier (simple name)
*
* @return The matching column information. May return {@code null}
*/
public ColumnInformation getColumnInformation(Identifier columnIdentifier);

/**
* Retrieve the named ForeignKeyInformation
*
* @param keyName The foreign key identifier (simple name)
*
* @return The matching foreign key information. May return {@code null}
*/
public ForeignKeyInformation getForeignKeyInformation(Identifier keyName);

/**
* Obtain an iterable over all the table's defined foreign keys.
*
* @return The iterable.
*/
public Iterable<ForeignKeyInformation> getForeignKeyInformations();

/**
* todo : create an IndexInformation...
*/
public IndexMetadata getIndexMetadata(Identifier indexName);
}
@@ -50,7 +50,7 @@
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.jdbc.WrappedBlob;
import org.hibernate.engine.jdbc.WrappedClob;
import org.hibernate.engine.jdbc.internal.LobCreatorBuilder;
import org.hibernate.service.jdbc.env.internal.LobCreatorBuilderImpl;

import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -65,8 +65,7 @@ public void testConnectedLobCreator() throws SQLException {
final Connection connection = createConnectionProxy( 4, new JdbcLobBuilderImpl( true ) );
LobCreationContext lobCreationContext = new LobCreationContextImpl( connection );

LobCreator lobCreator =
new LobCreatorBuilder( new Properties(), connection )
LobCreator lobCreator = LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection )
.buildLobCreator( lobCreationContext );
assertTrue( lobCreator instanceof ContextualLobCreator );
testLobCreation( lobCreator );
@@ -78,8 +77,7 @@ public void testJdbc3LobCreator() throws SQLException {
final Connection connection = createConnectionProxy( 3, new JdbcLobBuilderImpl( false) );
LobCreationContext lobCreationContext = new LobCreationContextImpl( connection );

LobCreator lobCreator =
new LobCreatorBuilder( new Properties(), connection )
LobCreator lobCreator = LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection )
.buildLobCreator( lobCreationContext );
assertSame( NonContextualLobCreator.INSTANCE, lobCreator );

@@ -91,8 +89,7 @@ public void testJdbc4UnsupportedLobCreator() throws SQLException {
final Connection connection = createConnectionProxy( 4, new JdbcLobBuilderImpl( false ) );
LobCreationContext lobCreationContext = new LobCreationContextImpl( connection );

LobCreator lobCreator =
new LobCreatorBuilder( new Properties(), connection )
LobCreator lobCreator = LobCreatorBuilderImpl.makeLobCreatorBuilder( new Properties(), connection )
.buildLobCreator( lobCreationContext );
assertSame( NonContextualLobCreator.INSTANCE, lobCreator );

@@ -106,8 +103,7 @@ public void testConfiguredNonContextualLobCreator() throws SQLException {

Properties props = new Properties();
props.setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" );
LobCreator lobCreator =
new LobCreatorBuilder( props, connection )
LobCreator lobCreator = LobCreatorBuilderImpl.makeLobCreatorBuilder( props, connection )
.buildLobCreator( lobCreationContext );
assertSame( NonContextualLobCreator.INSTANCE, lobCreator );

@@ -24,22 +24,28 @@
package org.hibernate.test.common;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.LobCreationContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.internal.ResultSetWrapperImpl;
import org.hibernate.engine.jdbc.internal.TypeInfo;
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.ResultSetWrapper;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.service.jdbc.env.internal.ExtractedDatabaseMetaDataImpl;
import org.hibernate.service.jdbc.env.internal.LobCreatorBuilderImpl;
import org.hibernate.service.jdbc.env.spi.ExtractedDatabaseMetaData;
import org.hibernate.service.jdbc.env.spi.IdentifierHelper;
import org.hibernate.service.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.service.jdbc.env.spi.LobCreatorBuilder;
import org.hibernate.service.jdbc.env.spi.QualifiedObjectNameSupport;
import org.hibernate.service.spi.Stoppable;

import org.hibernate.testing.env.ConnectionProviderBuilder;


@@ -50,11 +56,9 @@
* @author Steve Ebersole
*/
public class BasicTestingJdbcServiceImpl implements JdbcServices {
private ConnectionProvider connectionProvider;
private Dialect dialect;
private SqlStatementLogger sqlStatementLogger;
private SqlExceptionHelper exceptionHelper;
private final ExtractedDatabaseMetaData metaDataSupport = new MetaDataSupportImpl();
private TestingJdbcEnvironmentImpl jdbcEnvironment;

private final SqlStatementLogger sqlStatementLogger = new SqlStatementLogger( true, false );
private final ResultSetWrapper resultSetWrapper = ResultSetWrapperImpl.INSTANCE;

public void start() {
@@ -65,107 +69,107 @@ public void stop() {
}

public void prepare(boolean allowAggressiveRelease) {
connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease );
dialect = ConnectionProviderBuilder.getCorrespondingDialect();
sqlStatementLogger = new SqlStatementLogger( true, false );
exceptionHelper = new SqlExceptionHelper();

jdbcEnvironment = new TestingJdbcEnvironmentImpl( allowAggressiveRelease );
}

public void release() {
if ( connectionProvider instanceof Stoppable ) {
( (Stoppable) connectionProvider ).stop();
if ( jdbcEnvironment.connectionProvider instanceof Stoppable ) {
( (Stoppable) jdbcEnvironment.connectionProvider ).stop();
}
}

public ConnectionProvider getConnectionProvider() {
return connectionProvider;
return jdbcEnvironment.connectionProvider;
}

public Dialect getDialect() {
return dialect;
return jdbcEnvironment.dialect;
}

public LobCreator getLobCreator(LobCreationContext lobCreationContext) {
return null;
return jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext );
}

public ResultSetWrapper getResultSetWrapper() {
return null;
return resultSetWrapper;
}

@Override
public JdbcEnvironment getJdbcEnvironment() {
return null;
return jdbcEnvironment;
}

public SqlStatementLogger getSqlStatementLogger() {
return sqlStatementLogger;
}

public SqlExceptionHelper getSqlExceptionHelper() {
return exceptionHelper;
return jdbcEnvironment.exceptionHelper;
}

public ExtractedDatabaseMetaData getExtractedMetaDataSupport() {
return metaDataSupport;
return jdbcEnvironment.extractedDatabaseMetaData;
}

private static class MetaDataSupportImpl implements ExtractedDatabaseMetaData {
@Override
public boolean supportsRefCursors() {
return false;
}

@Override
public boolean supportsNamedParameters() {
return false;
}
private static class TestingJdbcEnvironmentImpl implements JdbcEnvironment {
private final ExtractedDatabaseMetaData extractedDatabaseMetaData = new ExtractedDatabaseMetaDataImpl( this );
private final SqlExceptionHelper exceptionHelper = new SqlExceptionHelper();
private final LobCreatorBuilder lobCreatorBuilder = LobCreatorBuilderImpl.makeLobCreatorBuilder();

public boolean supportsScrollableResults() {
return false;
}
private ConnectionProvider connectionProvider;
private Dialect dialect;

public boolean supportsGetGeneratedKeys() {
return false;
private TestingJdbcEnvironmentImpl(boolean allowAggressiveRelease) {
connectionProvider = ConnectionProviderBuilder.buildConnectionProvider( allowAggressiveRelease );
dialect = ConnectionProviderBuilder.getCorrespondingDialect();
}

public boolean supportsBatchUpdates() {
return false;
@Override
public Dialect getDialect() {
return dialect;
}

public boolean supportsDataDefinitionInTransaction() {
return false;
@Override
public ExtractedDatabaseMetaData getExtractedDatabaseMetaData() {
return extractedDatabaseMetaData;
}

public boolean doesDataDefinitionCauseTransactionCommit() {
return false;
@Override
public Identifier getCurrentCatalog() {
return null;
}

public Set<String> getExtraKeywords() {
return Collections.emptySet();
@Override
public Identifier getCurrentSchema() {
return null;
}

public SQLStateType getSqlStateType() {
return SQLStateType.UNKOWN;
@Override
public QualifiedObjectNameSupport getQualifiedObjectNameSupport() {
return null;
}

public boolean doesLobLocatorUpdateCopy() {
return false;
@Override
public IdentifierHelper getIdentifierHelper() {
return null;
}

public String getConnectionSchemaName() {
return null;
@Override
public Set<String> getReservedWords() {
return Collections.emptySet();
}

public String getConnectionCatalogName() {
return null;
@Override
public SqlExceptionHelper getSqlExceptionHelper() {
return exceptionHelper;
}

public LinkedHashSet<TypeInfo> getTypeInfoSet() {
return null;
@Override
public LobCreatorBuilder getLobCreatorBuilder() {
return lobCreatorBuilder;
}

@Override
public TypeInfo getTypeInfoForJdbcCode(int jdbcTypeCode) {
return null;
}
@@ -26,7 +26,7 @@
import java.sql.Connection;
import java.sql.SQLException;

import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
@@ -58,4 +58,9 @@ public Connection obtainConnection() throws SQLException {
public void releaseConnection(Connection connection) throws SQLException {
connectionProvider.closeConnection( connection );
}

@Override
public boolean supportsAggressiveRelease() {
return connectionProvider.supportsAggressiveRelease();
}
}
@@ -24,7 +24,7 @@
package org.hibernate.test.common;

import org.hibernate.ConnectionReleaseMode;
import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess;
import org.hibernate.service.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.transaction.spi.TransactionContext;
import org.hibernate.engine.transaction.spi.TransactionEnvironment;
import org.hibernate.engine.transaction.spi.TransactionImplementor;
@@ -23,7 +23,7 @@
*/
package org.hibernate.test.engine.jdbc.env;

import org.hibernate.engine.jdbc.env.spi.StandardSchemaCatalogSupportImpl;
import org.hibernate.service.jdbc.env.spi.StandardQualifiedObjectNameSupportImpl;
import org.hibernate.metamodel.spi.relational.ObjectName;

import org.junit.Test;
@@ -37,8 +37,8 @@
* @author Steve Ebersole
*/
public class StandardSchemaCatalogSupportImplTest extends BaseUnitTestCase {
private final StandardSchemaCatalogSupportImpl basic = new StandardSchemaCatalogSupportImpl();
private final StandardSchemaCatalogSupportImpl oracle = new StandardSchemaCatalogSupportImpl( "@", true );
private final StandardQualifiedObjectNameSupportImpl basic = new StandardQualifiedObjectNameSupportImpl();
private final StandardQualifiedObjectNameSupportImpl oracle = new StandardQualifiedObjectNameSupportImpl( "@", true );

@Test
public void testFormatName() throws Exception {