From 47f6360225f036a5cecc377f4ba4e6e09c7a2069 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Sat, 28 Jul 2012 00:04:20 -0500 Subject: [PATCH] HHH-7472 - Introduce a "schema management" service --- .../env/internal/JdbcEnvironmentImpl.java | 125 ++++++++- .../NormalizingIdentifierHelperImpl.java | 199 ++++++++++++++ ...raryExistingSequenceMetadataExtractor.java | 101 +++++++ .../internal/TemporarySchemaNameResolver.java | 69 +++++ .../jdbc/env}/spi/IdentifierHelper.java | 2 +- .../engine/jdbc/env/spi/JdbcEnvironment.java | 8 +- .../{ => env}/spi/SchemaNameResolver.java | 2 +- .../spi/StandardJdbcEnvironmentBuilder.java | 168 ------------ .../jdbc/internal/JdbcServicesImpl.java | 2 +- .../ExistingDatabaseMetaDataImpl.java | 253 ++++-------------- .../ExistingSequenceMetadataExtractor.java | 4 +- .../ExistingDatabaseMetaDataImplTest.java | 36 ++- 12 files changed, 564 insertions(+), 405 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/TemporaryExistingSequenceMetadataExtractor.java create mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/TemporarySchemaNameResolver.java rename hibernate-core/src/main/java/org/hibernate/{service/schema => engine/jdbc/env}/spi/IdentifierHelper.java (97%) rename hibernate-core/src/main/java/org/hibernate/engine/jdbc/{ => env}/spi/SchemaNameResolver.java (97%) delete mode 100644 hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardJdbcEnvironmentBuilder.java diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java index 0d0ca63809..084c9409f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/JdbcEnvironmentImpl.java @@ -23,17 +23,25 @@ */ package org.hibernate.engine.jdbc.env.internal; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; import java.util.Set; +import org.hibernate.cfg.AvailableSettings; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.env.spi.SchemaCatalogSupport; -import org.hibernate.engine.jdbc.spi.SchemaNameResolver; +import org.hibernate.engine.jdbc.env.spi.StandardSchemaCatalogSupportImpl; 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.schema.spi.ExistingSequenceMetadataExtractor; /** @@ -41,24 +49,58 @@ import org.hibernate.service.schema.spi.ExistingSequenceMetadataExtractor; */ public class JdbcEnvironmentImpl implements JdbcEnvironment { private final Dialect dialect; + private final IdentifierHelper identifierHelper; + private final Identifier currentCatalog; + private final Identifier currentSchema; private final SchemaCatalogSupport schemaCatalogSupport; - private final SchemaNameResolver schemaNameResolver; private ExistingSequenceMetadataExtractor sequenceMetadataExtractor; private final Set reservedWords; private final SqlExceptionHelper sqlExceptionHelper; - public JdbcEnvironmentImpl( - Dialect dialect, - SchemaCatalogSupport schemaCatalogSupport, - SchemaNameResolver schemaNameResolver, - ExistingSequenceMetadataExtractor sequenceMetadataExtractor, - Set reservedWords) { + public JdbcEnvironmentImpl(DatabaseMetaData dbmd, Dialect dialect, Map properties) throws SQLException { this.dialect = dialect; - this.schemaCatalogSupport = schemaCatalogSupport; - this.schemaNameResolver = schemaNameResolver; - this.sequenceMetadataExtractor = sequenceMetadataExtractor; + + Set reservedWords = new HashSet(); + reservedWords.addAll( dialect.getKeywords() ); + // todo : do we need to explicitly handle SQL:2003 keywords? + reservedWords.addAll( Arrays.asList( dbmd.getSQLKeywords().split( "," ) ) ); this.reservedWords = reservedWords; + this.identifierHelper = new NormalizingIdentifierHelperImpl( + this, + dbmd.storesMixedCaseQuotedIdentifiers(), + dbmd.storesLowerCaseQuotedIdentifiers(), + dbmd.storesUpperCaseQuotedIdentifiers(), + dbmd.storesUpperCaseIdentifiers(), + dbmd.storesLowerCaseIdentifiers() + ); + + String currentCatalogName = dbmd.getConnection().getCatalog(); + if ( currentCatalogName != null ) { + // intentionally using fromMetaDataObjectName rather than fromMetaDataCatalogName !!! + currentCatalog = identifierHelper.fromMetaDataObjectName( currentCatalogName ); + } + else { + currentCatalogName = (String) properties.get( AvailableSettings.DEFAULT_CATALOG ); + currentCatalog = Identifier.toIdentifier( currentCatalogName ); + } + + String currentSchemaName = TemporarySchemaNameResolver.INSTANCE.resolveSchemaName( dbmd.getConnection() ); + if ( currentSchemaName != null ) { + // intentionally using fromMetaDataObjectName rather than fromMetaDataSchemaName !!! + currentSchema = identifierHelper.fromMetaDataObjectName( currentSchemaName ); + } + else { + currentSchemaName = (String) properties.get( AvailableSettings.DEFAULT_SCHEMA ); + currentSchema = Identifier.toIdentifier( currentSchemaName ); + } + + schemaCatalogSupport = new StandardSchemaCatalogSupportImpl( + dbmd.getCatalogSeparator(), + dbmd.isCatalogAtStart(), + dialect.openQuote(), + dialect.closeQuote() + ); SQLExceptionConverter sqlExceptionConverter = dialect.buildSQLExceptionConverter(); if ( sqlExceptionConverter == null ) { @@ -66,11 +108,56 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment { sqlExceptionConverter = converter; converter.addDelegate( dialect.buildSQLExceptionConversionDelegate() ); converter.addDelegate( new SQLExceptionTypeDelegate( dialect ) ); - // todo : vary this based on extractedMetaDataSupport.getSqlStateType() converter.addDelegate( new SQLStateConversionDelegate( dialect ) ); } this.sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter ); + this.sequenceMetadataExtractor = new TemporaryExistingSequenceMetadataExtractor( this ); + } + + public JdbcEnvironmentImpl(Dialect dialect, Map properties) { + this.dialect = dialect; + + Set reservedWords = new HashSet(); + reservedWords.addAll( dialect.getKeywords() ); + // todo : do we need to explicitly handle SQL:2003 keywords? + this.reservedWords = reservedWords; + + // again, a simple temporary impl that works on H2 + this.identifierHelper = new NormalizingIdentifierHelperImpl( + this, + true, // storesMixedCaseQuotedIdentifiers + false, // storesLowerCaseQuotedIdentifiers + false, // storesUpperCaseQuotedIdentifiers + true, // storesUpperCaseIdentifiers + false // storesLowerCaseIdentifiers + ); + + String currentCatalogName = (String) properties.get( AvailableSettings.DEFAULT_CATALOG ); + currentCatalog = Identifier.toIdentifier( currentCatalogName ); + + String currentSchemaName = (String) properties.get( AvailableSettings.DEFAULT_SCHEMA ); + currentSchema = Identifier.toIdentifier( currentSchemaName ); + + // again, a simple temporary impl that works on H2 + schemaCatalogSupport = new StandardSchemaCatalogSupportImpl( + ".", + true, + dialect.openQuote(), + dialect.closeQuote() + ); + + 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 ) ); + } + this.sqlExceptionHelper = new SqlExceptionHelper( sqlExceptionConverter ); + + this.sequenceMetadataExtractor = new TemporaryExistingSequenceMetadataExtractor( this ); } @Override @@ -78,14 +165,24 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment { return dialect; } + @Override + public Identifier getCurrentCatalog() { + return currentCatalog; + } + + @Override + public Identifier getCurrentSchema() { + return currentSchema; + } + @Override public SchemaCatalogSupport getSchemaCatalogSupport() { return schemaCatalogSupport; } @Override - public SchemaNameResolver getSchemaNameResolver() { - return schemaNameResolver; + public IdentifierHelper getIdentifierHelper() { + return identifierHelper; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java new file mode 100644 index 0000000000..2c3669c8a1 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/NormalizingIdentifierHelperImpl.java @@ -0,0 +1,199 @@ +/* + * 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.engine.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.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Identifier; + +/** +* @author Steve Ebersole +*/ +public class NormalizingIdentifierHelperImpl implements IdentifierHelper { + private static final Logger log = Logger.getLogger( NormalizingIdentifierHelperImpl.class ); + + private final JdbcEnvironment jdbcEnvironment; + + private final boolean storesMixedCaseQuotedIdentifiers; + private final boolean storesLowerCaseQuotedIdentifiers; + private final boolean storesUpperCaseQuotedIdentifiers; + private final boolean storesUpperCaseIdentifiers; + private final boolean storesLowerCaseIdentifiers; + + public NormalizingIdentifierHelperImpl( + JdbcEnvironment jdbcEnvironment, boolean storesMixedCaseQuotedIdentifiers, + boolean storesLowerCaseQuotedIdentifiers, + boolean storesUpperCaseQuotedIdentifiers, + boolean storesUpperCaseIdentifiers, + boolean storesLowerCaseIdentifiers) { + this.jdbcEnvironment = jdbcEnvironment; + this.storesMixedCaseQuotedIdentifiers = storesMixedCaseQuotedIdentifiers; + this.storesLowerCaseQuotedIdentifiers = storesLowerCaseQuotedIdentifiers; + this.storesUpperCaseQuotedIdentifiers = storesUpperCaseQuotedIdentifiers; + this.storesUpperCaseIdentifiers = storesUpperCaseIdentifiers; + this.storesLowerCaseIdentifiers = storesLowerCaseIdentifiers; + + if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in mixed, upper and lower case" ); + } + else if ( storesMixedCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and upper case" ); + } + else if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and lower case" ); + } + + if ( storesUpperCaseIdentifiers && storesLowerCaseIdentifiers ) { + log.warn( "JDBC Driver reports it stores non-quoted identifiers in both upper and lower case" ); + } + + if ( storesUpperCaseIdentifiers && storesUpperCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in upper case" ); + } + + if ( storesLowerCaseIdentifiers && storesLowerCaseQuotedIdentifiers ) { + log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in lower case" ); + } + } + + // In the DatabaseMetaData method params for catalog and schema name have the following meaning: + // 1) <""> means to match things "without a catalog/schema" + // 2) means to not limit results based on this field + // + // todo : not sure how "without a catalog/schema" is interpreted. Current? + + @Override + public String toMetaDataCatalogName(Identifier identifier) { + if ( identifier == null ) { + // todo : not sure if this is interpreted as <""> or + return jdbcEnvironment.getCurrentCatalog().getText(); + } + + return toText( identifier ); + } + + private String toText(Identifier identifier) { + if ( identifier == null ) { + throw new IllegalArgumentException( "Identifier cannot be null; bad usage" ); + } + + if ( identifier.isQuoted() && storesMixedCaseQuotedIdentifiers ) { + return identifier.getText(); + } + else if ( ( identifier.isQuoted() && storesUpperCaseQuotedIdentifiers ) + || ( !identifier.isQuoted() && storesUpperCaseIdentifiers ) ) { + return StringHelper.toUpperCase( identifier.getText() ); + } + else if ( ( identifier.isQuoted() && storesLowerCaseQuotedIdentifiers ) + || ( !identifier.isQuoted() && storesLowerCaseIdentifiers ) ) { + return StringHelper.toLowerCase( identifier.getText() ); + } + return identifier.getText(); + } + + @Override + public String toMetaDataSchemaName(Identifier identifier) { + if ( identifier == null ) { + // todo : not sure if this is interpreted as <""> or + return jdbcEnvironment.getCurrentSchema().getText(); + } + + return toText( identifier ); + } + + @Override + public String toMetaDataObjectName(Identifier identifier) { + if ( identifier == null ) { + // if this method was called, the value is needed + throw new IllegalArgumentException( ); + } + return toText( identifier ); + } + + @Override + public Identifier fromMetaDataCatalogName(String catalogName) { + if ( catalogName == null ) { + return null; + } + + if ( catalogName.equals( jdbcEnvironment.getCurrentCatalog().getText() ) ) { + return null; + } + + return toIdentifier( catalogName ); + // note really sure the best way to know (can you?) whether the identifier is quoted + + } + + private Identifier toIdentifier(String incomingName) { + // lovely decipher of whether the incoming value represents a quoted identifier... + final boolean isUpperCase = incomingName.toUpperCase().equals( incomingName ); + final boolean isLowerCase = incomingName.toLowerCase().equals( incomingName ); + final boolean isMixedCase = ! isLowerCase && ! isUpperCase; + + if ( jdbcEnvironment.getReservedWords().contains( incomingName ) ) { + // unequivocally it needs to be quoted... + return Identifier.toIdentifier( incomingName, true ); + } + + if ( storesMixedCaseQuotedIdentifiers && isMixedCase ) { + return Identifier.toIdentifier( incomingName, true ); + } + + if ( storesLowerCaseQuotedIdentifiers && isLowerCase ) { + return Identifier.toIdentifier( incomingName, true ); + } + + if ( storesUpperCaseQuotedIdentifiers && isUpperCase ) { + return Identifier.toIdentifier( incomingName, true ); + } + + return Identifier.toIdentifier( incomingName ); + } + + @Override + public Identifier fromMetaDataSchemaName(String schemaName) { + if ( schemaName == null ) { + return null; + } + + if ( schemaName.equals( jdbcEnvironment.getCurrentSchema().getText() ) ) { + return null; + } + + return toIdentifier( schemaName ); + } + + @Override + public Identifier fromMetaDataObjectName(String objectName) { + if ( objectName == null ) { + return null; + } + + return toIdentifier( objectName ); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/TemporaryExistingSequenceMetadataExtractor.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/TemporaryExistingSequenceMetadataExtractor.java new file mode 100644 index 0000000000..92c06940d3 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/TemporaryExistingSequenceMetadataExtractor.java @@ -0,0 +1,101 @@ +/* + * 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.engine.jdbc.env.internal; + +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +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; + +/** + * Temporary implementation that works for H2. + * + * @author Steve Ebersole + */ +public class TemporaryExistingSequenceMetadataExtractor implements ExistingSequenceMetadataExtractor { + private final JdbcEnvironmentImpl jdbcEnvironment; + + public TemporaryExistingSequenceMetadataExtractor(JdbcEnvironmentImpl jdbcEnvironment) { + this.jdbcEnvironment = jdbcEnvironment; + } + + @Override + public Iterable 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 sequenceMetadataList = new ArrayList(); + while ( resultSet.next() ) { + sequenceMetadataList.add( + new ExistingSequenceMetadataImpl( + new ObjectName( + jdbcEnvironment.getIdentifierHelper().fromMetaDataCatalogName( + resultSet.getString( + "SEQUENCE_CATALOG" + ) + ), + jdbcEnvironment.getIdentifierHelper().fromMetaDataSchemaName( + resultSet.getString( + "SEQUENCE_SCHEMA" + ) + ), + jdbcEnvironment.getIdentifierHelper().fromMetaDataCatalogName( + resultSet.getString( + "SEQUENCE_NAME" + ) + ) + ) + ) + ); + } + return sequenceMetadataList; + } + finally { + try { + resultSet.close(); + } + catch (SQLException ignore) { + } + } + } + finally { + try { + statement.close(); + } + catch (SQLException ignore) { + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/TemporarySchemaNameResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/TemporarySchemaNameResolver.java new file mode 100644 index 0000000000..287514d47e --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/TemporarySchemaNameResolver.java @@ -0,0 +1,69 @@ +/* + * 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.engine.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; + +/** + * Temporary implementation that works for H2. + * + * @author Steve Ebersole + */ +public class TemporarySchemaNameResolver implements SchemaNameResolver { + public static final TemporarySchemaNameResolver INSTANCE = new TemporarySchemaNameResolver(); + + @Override + public String resolveSchemaName(Connection connection) throws SQLException { + // the H2 variant... + Statement statement = connection.createStatement(); + try { + ResultSet resultSet = statement.executeQuery( "call schema()" ); + try { + if ( ! resultSet.next() ) { + return null; + } + return resultSet.getString( 1 ); + } + finally { + try { + resultSet.close(); + } + catch (SQLException ignore) { + } + } + } + finally { + try { + statement.close(); + } + catch (SQLException ignore) { + } + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/schema/spi/IdentifierHelper.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/service/schema/spi/IdentifierHelper.java rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java index ef9eca8dbc..f873e6a5f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/schema/spi/IdentifierHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/IdentifierHelper.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.service.schema.spi; +package org.hibernate.engine.jdbc.env.spi; import org.hibernate.metamodel.spi.relational.Identifier; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java index 7cab09ff58..f20ccbd728 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java @@ -26,8 +26,8 @@ package org.hibernate.engine.jdbc.env.spi; import java.util.Set; import org.hibernate.dialect.Dialect; -import org.hibernate.engine.jdbc.spi.SchemaNameResolver; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; +import org.hibernate.metamodel.spi.relational.Identifier; import org.hibernate.service.schema.spi.ExistingSequenceMetadataExtractor; /** @@ -39,9 +39,13 @@ import org.hibernate.service.schema.spi.ExistingSequenceMetadataExtractor; public interface JdbcEnvironment { public Dialect getDialect(); + public Identifier getCurrentCatalog(); + + public Identifier getCurrentSchema(); + public SchemaCatalogSupport getSchemaCatalogSupport(); - public SchemaNameResolver getSchemaNameResolver(); + public IdentifierHelper getIdentifierHelper(); public Set getReservedWords(); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SchemaNameResolver.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java similarity index 97% rename from hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SchemaNameResolver.java rename to hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java index 47c61c0cfb..7783143bfe 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SchemaNameResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java @@ -21,7 +21,7 @@ * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ -package org.hibernate.engine.jdbc.spi; +package org.hibernate.engine.jdbc.env.spi; import java.sql.Connection; import java.sql.SQLException; diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardJdbcEnvironmentBuilder.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardJdbcEnvironmentBuilder.java deleted file mode 100644 index 12c2fcbc13..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/StandardJdbcEnvironmentBuilder.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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.engine.jdbc.env.spi; - -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.hibernate.dialect.Dialect; -import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl; -import org.hibernate.engine.jdbc.spi.SchemaNameResolver; -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.schema.spi.IdentifierHelper; - -/** - * @author Steve Ebersole - */ -public class StandardJdbcEnvironmentBuilder { - public static final StandardJdbcEnvironmentBuilder INSTANCE = new StandardJdbcEnvironmentBuilder(); - - private static final SchemaNameResolver FOR_NOW_SCHEMA_NAME_RESOLVER = new SchemaNameResolver() { - @Override - public String resolveSchemaName(Connection connection) throws SQLException { - // the H2 variant... - Statement statement = connection.createStatement(); - try { - ResultSet resultSet = statement.executeQuery( "call schema()" ); - try { - if ( ! resultSet.next() ) { - return null; - } - return resultSet.getString( 1 ); - } - finally { - try { - resultSet.close(); - } - catch (SQLException ignore) { - } - } - } - finally { - try { - statement.close(); - } - catch (SQLException ignore) { - } - } - } - }; - - private static final ExistingSequenceMetadataExtractor FOR_NOW_SEQ_META_EXTRACTOR = new ExistingSequenceMetadataExtractor() { - @Override - public Iterable extractMetadata( - DatabaseMetaData databaseMetaData, - IdentifierHelper identifierHelper) throws SQLException { - // again, the H2 variant... - Statement statement = databaseMetaData.getConnection().createStatement(); - try { - ResultSet resultSet = statement.executeQuery( - "select SEQUENCE_CATALOG, SEQUENCE_SCHEMA, SEQUENCE_NAME " + - "from information_schema.sequences" - ); - try { - final List sequenceMetadataList = new ArrayList(); - while ( resultSet.next() ) { - sequenceMetadataList.add( - new ExistingSequenceMetadataImpl( - new ObjectName( - identifierHelper.fromMetaDataCatalogName( - resultSet.getString( - "SEQUENCE_CATALOG" - ) - ), - identifierHelper.fromMetaDataSchemaName( resultSet.getString( "SEQUENCE_SCHEMA" ) ), - identifierHelper.fromMetaDataCatalogName( resultSet.getString( "SEQUENCE_NAME" ) ) - ) - ) - ); - } - return sequenceMetadataList; - } - finally { - try { - resultSet.close(); - } - catch (SQLException ignore) { - } - } - } - finally { - try { - statement.close(); - } - catch (SQLException ignore) { - } - } - } - }; - - public JdbcEnvironment buildJdbcEnvironment(DatabaseMetaData dbmd, Dialect dialect) throws SQLException { - SchemaCatalogSupport schemaCatalogSupport = new StandardSchemaCatalogSupportImpl( - dbmd.getCatalogSeparator(), - dbmd.isCatalogAtStart(), - dialect.openQuote(), - dialect.closeQuote() - ); - - Set reservedWords = new HashSet(); - reservedWords.addAll( dialect.getKeywords() ); - // todo : do we need to explicitly handle SQL:2003 keywords? - reservedWords.addAll( Arrays.asList( dbmd.getSQLKeywords().split( "," ) ) ); - - return new JdbcEnvironmentImpl( - dialect, - schemaCatalogSupport, - FOR_NOW_SCHEMA_NAME_RESOLVER, - FOR_NOW_SEQ_META_EXTRACTOR, - reservedWords - ); - } - - public JdbcEnvironment buildJdbcEnvironment(Dialect dialect) throws SQLException { - SchemaCatalogSupport schemaCatalogSupport = new StandardSchemaCatalogSupportImpl( dialect ); - - Set reservedWords = new HashSet(); - reservedWords.addAll( dialect.getKeywords() ); - - return new JdbcEnvironmentImpl( - dialect, - schemaCatalogSupport, - FOR_NOW_SCHEMA_NAME_RESOLVER, - FOR_NOW_SEQ_META_EXTRACTOR, - reservedWords - ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java index d0b845e833..714686bc65 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java @@ -46,7 +46,7 @@ import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.spi.JdbcConnectionAccess; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.ResultSetWrapper; -import org.hibernate.engine.jdbc.spi.SchemaNameResolver; +import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.exception.internal.SQLExceptionTypeDelegate; diff --git a/hibernate-core/src/main/java/org/hibernate/service/schema/internal/ExistingDatabaseMetaDataImpl.java b/hibernate-core/src/main/java/org/hibernate/service/schema/internal/ExistingDatabaseMetaDataImpl.java index d110155186..0c11cf8ff0 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/schema/internal/ExistingDatabaseMetaDataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/service/schema/internal/ExistingDatabaseMetaDataImpl.java @@ -30,11 +30,9 @@ import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; -import org.jboss.logging.Logger; - import org.hibernate.TruthValue; +import org.hibernate.engine.jdbc.env.spi.IdentifierHelper; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; -import org.hibernate.internal.util.StringHelper; import org.hibernate.metamodel.spi.relational.Identifier; import org.hibernate.metamodel.spi.relational.ObjectName; import org.hibernate.metamodel.spi.relational.Schema; @@ -42,19 +40,14 @@ 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.IdentifierHelper; /** * @author Steve Ebersole */ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { - private static final Logger log = Logger.getLogger( ExistingDatabaseMetaDataImpl.class ); - private final JdbcEnvironment jdbcEnvironment; private final DatabaseMetaData databaseMetaData; - private final IdentifierHelperImpl identifierHelper; - private final Map tables = new HashMap(); private final Map sequences; @@ -70,34 +63,28 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { private ExistingDatabaseMetaDataImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException { this.jdbcEnvironment = jdbcEnvironment; this.databaseMetaData = databaseMetaData; - this.identifierHelper = new IdentifierHelperImpl( - databaseMetaData.getConnection().getCatalog(), - jdbcEnvironment.getSchemaNameResolver().resolveSchemaName( databaseMetaData.getConnection() ), - databaseMetaData.storesMixedCaseQuotedIdentifiers(), - databaseMetaData.storesLowerCaseQuotedIdentifiers(), - databaseMetaData.storesUpperCaseQuotedIdentifiers(), - databaseMetaData.storesUpperCaseIdentifiers(), - databaseMetaData.storesLowerCaseIdentifiers() - ); + this.sequences = loadSequenceMetadataMap(); + } - sequences = loadSequenceMetadataMap(); + public IdentifierHelper identifierHelper() { + return jdbcEnvironment.getIdentifierHelper(); } private static final String[] TABLE_TYPES = new String[] { "TABLE", "VIEW" }; private void loadTableMetadata(ResultSet resultSet) throws SQLException { while ( resultSet.next() ) { - final Identifier catalogIdentifier = identifierHelper.fromMetaDataCatalogName( + final Identifier catalogIdentifier = identifierHelper().fromMetaDataCatalogName( resultSet.getString( "TABLE_CAT" ) ); - final Identifier schemaIdentifier = identifierHelper.fromMetaDataSchemaName( + final Identifier schemaIdentifier = identifierHelper().fromMetaDataSchemaName( resultSet.getString( "TABLE_SCHEM" ) ); - final Identifier tableIdentifier = identifierHelper.fromMetaDataObjectName( + final Identifier tableIdentifier = identifierHelper().fromMetaDataObjectName( resultSet.getString( "TABLE_NAME" ) @@ -110,20 +97,17 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { } tableMetadata = new ExistingTableMetadataImpl( this, tableName ); - tables.put( tableName, tableMetadata ); + tables.put( toMapKey( tableName ), tableMetadata ); } } private Map loadSequenceMetadataMap() throws SQLException { Map sequences = new HashMap(); final Iterable sequenceMetadatas = - jdbcEnvironment.getExistingSequenceMetadataExtractor().extractMetadata( - databaseMetaData, - identifierHelper - ); + jdbcEnvironment.getExistingSequenceMetadataExtractor().extractMetadata( databaseMetaData ); if ( sequenceMetadatas != null ) { for ( ExistingSequenceMetadata sequenceMetadata :sequenceMetadatas ) { - sequences.put( sequenceMetadata.getSequenceName(), sequenceMetadata ); + sequences.put( toMapKey( sequenceMetadata.getSequenceName() ), sequenceMetadata ); } } return sequences; @@ -131,12 +115,37 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { @Override public ExistingTableMetadata getTableMetadata(ObjectName tableName) { - return tables.get( tableName ); + return tables.get( toMapKey( tableName ) ); + } + + public static ObjectName toMapKey(ObjectName qualifiedName) { + Identifier catalog = qualifiedName.getCatalog(); + if ( catalog != null ) { + if ( ! catalog.isQuoted() ) { + catalog = Identifier.toIdentifier( catalog.getText().toUpperCase() ); + } + } + + Identifier schema = qualifiedName.getSchema(); + if ( schema != null ) { + if ( ! schema.isQuoted() ) { + schema = Identifier.toIdentifier( schema.getText().toUpperCase() ); + } + } + + Identifier name = qualifiedName.getName(); + if ( name != null ) { + if ( ! name.isQuoted() ) { + name = Identifier.toIdentifier( name.getText().toUpperCase() ); + } + } + + return new ObjectName( catalog, schema, name ); } @Override public ExistingSequenceMetadata getSequenceMetadata(ObjectName sequenceName) { - return sequences.get( sequenceName ); + return sequences.get( toMapKey( sequenceName ) ); } public Map getColumnMetadata(ExistingTableMetadata tableMetadata) { @@ -144,9 +153,9 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { try { ResultSet resultSet = databaseMetaData.getColumns( - identifierHelper.toMetaDataCatalogName( tableMetadata.getName().getCatalog() ), - identifierHelper.toMetaDataSchemaName( tableMetadata.getName().getSchema() ), - identifierHelper.toMetaDataObjectName( tableMetadata.getName().getName() ), + identifierHelper().toMetaDataCatalogName( tableMetadata.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableMetadata.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableMetadata.getName().getName() ), "%" ); @@ -194,9 +203,9 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { try { ResultSet resultSet = databaseMetaData.getImportedKeys( - identifierHelper.toMetaDataCatalogName( tableMetadata.getName().getCatalog() ), - identifierHelper.toMetaDataSchemaName( tableMetadata.getName().getSchema() ), - identifierHelper.toMetaDataObjectName( tableMetadata.getName().getName() ) + identifierHelper().toMetaDataCatalogName( tableMetadata.getName().getCatalog() ), + identifierHelper().toMetaDataSchemaName( tableMetadata.getName().getSchema() ), + identifierHelper().toMetaDataObjectName( tableMetadata.getName().getName() ) ); // todo : need to account for getCrossReference() as well... @@ -271,172 +280,6 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { return TruthValue.UNKNOWN; } - public class IdentifierHelperImpl implements IdentifierHelper { - private final String currentCatalog; - private final String currentSchema; - private final boolean storesMixedCaseQuotedIdentifiers; - private final boolean storesLowerCaseQuotedIdentifiers; - private final boolean storesUpperCaseQuotedIdentifiers; - private final boolean storesUpperCaseIdentifiers; - private final boolean storesLowerCaseIdentifiers; - - public IdentifierHelperImpl( - String currentCatalog, - String currentSchema, - boolean storesMixedCaseQuotedIdentifiers, - boolean storesLowerCaseQuotedIdentifiers, - boolean storesUpperCaseQuotedIdentifiers, - boolean storesUpperCaseIdentifiers, - boolean storesLowerCaseIdentifiers) { - this.currentCatalog = currentCatalog; - this.currentSchema = currentSchema; - this.storesMixedCaseQuotedIdentifiers = storesMixedCaseQuotedIdentifiers; - this.storesLowerCaseQuotedIdentifiers = storesLowerCaseQuotedIdentifiers; - this.storesUpperCaseQuotedIdentifiers = storesUpperCaseQuotedIdentifiers; - this.storesUpperCaseIdentifiers = storesUpperCaseIdentifiers; - this.storesLowerCaseIdentifiers = storesLowerCaseIdentifiers; - - if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) { - log.warn( "JDBC Driver reports it stores quoted identifiers in mixed, upper and lower case" ); - } - else if ( storesMixedCaseQuotedIdentifiers && storesUpperCaseQuotedIdentifiers ) { - log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and upper case" ); - } - else if ( storesMixedCaseQuotedIdentifiers && storesLowerCaseQuotedIdentifiers ) { - log.warn( "JDBC Driver reports it stores quoted identifiers in both mixed and lower case" ); - } - - if ( storesUpperCaseIdentifiers && storesLowerCaseIdentifiers ) { - log.warn( "JDBC Driver reports it stores non-quoted identifiers in both upper and lower case" ); - } - - if ( storesUpperCaseIdentifiers && storesUpperCaseQuotedIdentifiers ) { - log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in upper case" ); - } - - if ( storesLowerCaseIdentifiers && storesLowerCaseQuotedIdentifiers ) { - log.warn( "JDBC Driver reports it stores both quoted and non-quoted identifiers in lower case" ); - } - } - - // In the DatabaseMetaData method params for catalog and schema name have the following meaning: - // 1) <""> means to match things "without a catalog/schema" - // 2) means to not limit results based on this field - // - // todo : not sure how "without a catalog/schema" is interpreted. Current? - - @Override - public String toMetaDataCatalogName(Identifier identifier) { - if ( identifier == null ) { - // todo : not sure if this is interpreted as <""> or - return currentCatalog; - } - - return toText( identifier ); - } - - private String toText(Identifier identifier) { - if ( identifier == null ) { - throw new IllegalArgumentException( "Identifier cannot be null; bad usage" ); - } - - if ( identifier.isQuoted() && storesMixedCaseQuotedIdentifiers ) { - return identifier.getText(); - } - else if ( ( identifier.isQuoted() && storesUpperCaseQuotedIdentifiers ) - || ( !identifier.isQuoted() && storesUpperCaseIdentifiers ) ) { - return StringHelper.toUpperCase( identifier.getText() ); - } - else if ( ( identifier.isQuoted() && storesLowerCaseQuotedIdentifiers ) - || ( !identifier.isQuoted() && storesLowerCaseIdentifiers ) ) { - return StringHelper.toLowerCase( identifier.getText() ); - } - return identifier.getText(); - } - - @Override - public String toMetaDataSchemaName(Identifier identifier) { - if ( identifier == null ) { - // todo : not sure if this is interpreted as <""> or - return currentSchema; - } - - return toText( identifier ); - } - - @Override - public String toMetaDataObjectName(Identifier identifier) { - if ( identifier == null ) { - // if this method was called, the value is needed - throw new IllegalArgumentException( ); - } - return toText( identifier ); - } - - @Override - public Identifier fromMetaDataCatalogName(String catalogName) { - if ( catalogName == null ) { - return null; - } - - if ( catalogName.equals( currentCatalog ) ) { - return null; - } - - return toIdentifier( catalogName ); - // note really sure the best way to know (can you?) whether the identifier is quoted - - } - - private Identifier toIdentifier(String incomingName) { - // lovely decipher of whether the incoming value represents a quoted identifier... - final boolean isUpperCase = incomingName.toUpperCase().equals( incomingName ); - final boolean isLowerCase = incomingName.toLowerCase().equals( incomingName ); - final boolean isMixedCase = ! isLowerCase && ! isUpperCase; - - if ( jdbcEnvironment.getReservedWords().contains( incomingName ) ) { - // unequivocally it needs to be quoted... - return Identifier.toIdentifier( incomingName, true ); - } - - if ( storesMixedCaseQuotedIdentifiers && isMixedCase ) { - return Identifier.toIdentifier( incomingName, true ); - } - - if ( storesLowerCaseQuotedIdentifiers && isLowerCase ) { - return Identifier.toIdentifier( incomingName, true ); - } - - if ( storesUpperCaseQuotedIdentifiers && isUpperCase ) { - return Identifier.toIdentifier( incomingName, true ); - } - - return Identifier.toIdentifier( incomingName ); - } - - @Override - public Identifier fromMetaDataSchemaName(String schemaName) { - if ( schemaName == null ) { - return null; - } - - if ( schemaName.equals( currentSchema ) ) { - return null; - } - - return toIdentifier( schemaName ); - } - - @Override - public Identifier fromMetaDataObjectName(String objectName) { - if ( objectName == null ) { - return null; - } - - return toIdentifier( objectName ); - } - } - public static interface Builder { public Builder prepareAll(); public Builder prepareCatalogAndSchema(Schema.Name schemaName); @@ -487,8 +330,8 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { @Override public Builder prepareCatalogAndSchema(Schema.Name schemaName) { prepare( - it.identifierHelper.toMetaDataCatalogName( schemaName.getCatalog() ), - it.identifierHelper.toMetaDataSchemaName( schemaName.getSchema() ) + it.identifierHelper().toMetaDataCatalogName( schemaName.getCatalog() ), + it.identifierHelper().toMetaDataSchemaName( schemaName.getSchema() ) ); return this; } @@ -496,7 +339,7 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { @Override public Builder prepareCatalog(Identifier catalog) { prepare( - it.identifierHelper.toMetaDataCatalogName( catalog ), + it.identifierHelper().toMetaDataCatalogName( catalog ), null ); return this; @@ -506,7 +349,7 @@ public class ExistingDatabaseMetaDataImpl implements ExistingDatabaseMetaData { public Builder prepareSchema(Identifier schema) { prepare( null, - it.identifierHelper.toMetaDataSchemaName( schema ) + it.identifierHelper().toMetaDataSchemaName( schema ) ); return this; } diff --git a/hibernate-core/src/main/java/org/hibernate/service/schema/spi/ExistingSequenceMetadataExtractor.java b/hibernate-core/src/main/java/org/hibernate/service/schema/spi/ExistingSequenceMetadataExtractor.java index 07526cf0ca..6601abb9fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/service/schema/spi/ExistingSequenceMetadataExtractor.java +++ b/hibernate-core/src/main/java/org/hibernate/service/schema/spi/ExistingSequenceMetadataExtractor.java @@ -31,7 +31,5 @@ import java.sql.SQLException; * @author Steve Ebersole */ public interface ExistingSequenceMetadataExtractor { - public Iterable extractMetadata( - DatabaseMetaData databaseMetaData, - IdentifierHelper identifierHelper) throws SQLException; + public Iterable extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException; } diff --git a/hibernate-core/src/test/java/org/hibernate/test/service/schema/internal/ExistingDatabaseMetaDataImplTest.java b/hibernate-core/src/test/java/org/hibernate/test/service/schema/internal/ExistingDatabaseMetaDataImplTest.java index 2c1722b176..92f9f762d0 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/service/schema/internal/ExistingDatabaseMetaDataImplTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/service/schema/internal/ExistingDatabaseMetaDataImplTest.java @@ -30,8 +30,9 @@ import java.util.Properties; import org.hibernate.cfg.Environment; import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; -import org.hibernate.engine.jdbc.env.spi.StandardJdbcEnvironmentBuilder; +import org.hibernate.metamodel.spi.relational.ObjectName; import org.hibernate.service.schema.internal.ExistingDatabaseMetaDataImpl; import org.hibernate.service.schema.spi.ExistingDatabaseMetaData; @@ -41,6 +42,8 @@ import org.junit.Test; import org.hibernate.testing.junit4.BaseUnitTestCase; +import static org.junit.Assert.assertNotNull; + /** * @author Steve Ebersole */ @@ -56,18 +59,15 @@ public class ExistingDatabaseMetaDataImplTest extends BaseUnitTestCase { props.getProperty( Environment.USER ), props.getProperty( Environment.PASS ) ); - connection.createStatement().execute( "CREATE SCHEMA \"another_schema\"" ); + connection.createStatement().execute( "CREATE SCHEMA another_schema" ); connection.createStatement().execute( "CREATE TABLE t1 (name varchar)" ); - connection.createStatement().execute( "CREATE TABLE db1.\"another_schema\".t2 (name varchar)" ); + connection.createStatement().execute( "CREATE TABLE another_schema.t2 (name varchar)" ); connection.createStatement().execute( "CREATE SEQUENCE seq1" ); - connection.createStatement().execute( "CREATE SEQUENCE db1.\"another_schema\".seq1" ); + connection.createStatement().execute( "CREATE SEQUENCE db1.another_schema.seq2" ); - jdbcEnvironment = StandardJdbcEnvironmentBuilder.INSTANCE.buildJdbcEnvironment( - connection.getMetaData(), - Dialect.getDialect( props ) - ); + jdbcEnvironment = new JdbcEnvironmentImpl( connection.getMetaData(), Dialect.getDialect( props ), props ); } @After @@ -81,10 +81,26 @@ public class ExistingDatabaseMetaDataImplTest extends BaseUnitTestCase { } } -// @Test + @Test public void testGetTableMetadata() throws Exception { ExistingDatabaseMetaData databaseMetaData = ExistingDatabaseMetaDataImpl.builder( jdbcEnvironment, connection.getMetaData() ).prepareAll().build(); - databaseMetaData.toString(); + + ObjectName name = new ObjectName( null, null, "t1" ); + assertNotNull( databaseMetaData.getTableMetadata( name ) ); + + name = new ObjectName( null, "another_schema", "t2" ); + assertNotNull( databaseMetaData.getTableMetadata( name ) ); + + name = new ObjectName( null, null, "seq1" ); + assertNotNull( databaseMetaData.getSequenceMetadata( name ) ); + + name = new ObjectName( null, "another_schema", "seq2" ); + assertNotNull( databaseMetaData.getSequenceMetadata( name ) ); + + // knowing if identifiers coming back from the database are quoted is all dicked up... + // see org.hibernate.engine.jdbc.env.internal.NormalizingIdentifierHelperImpl + // + // surely JDBC has a better way to determine this right? } }