HHH-7472 - Introduce a "schema management" service
This commit is contained in:
parent
f43c8bab1b
commit
47f6360225
|
@ -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<String> reservedWords;
|
||||
private final SqlExceptionHelper sqlExceptionHelper;
|
||||
|
||||
public JdbcEnvironmentImpl(
|
||||
Dialect dialect,
|
||||
SchemaCatalogSupport schemaCatalogSupport,
|
||||
SchemaNameResolver schemaNameResolver,
|
||||
ExistingSequenceMetadataExtractor sequenceMetadataExtractor,
|
||||
Set<String> reservedWords) {
|
||||
public JdbcEnvironmentImpl(DatabaseMetaData dbmd, Dialect dialect, Map properties) throws SQLException {
|
||||
this.dialect = dialect;
|
||||
this.schemaCatalogSupport = schemaCatalogSupport;
|
||||
this.schemaNameResolver = schemaNameResolver;
|
||||
this.sequenceMetadataExtractor = sequenceMetadataExtractor;
|
||||
|
||||
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( "," ) ) );
|
||||
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<String> reservedWords = new HashSet<String>();
|
||||
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
|
||||
|
|
|
@ -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) <null> 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 <currentCatalog>
|
||||
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 <currentSchema>
|
||||
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 );
|
||||
}
|
||||
}
|
|
@ -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<ExistingSequenceMetadata> 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>();
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
@ -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<String> getReservedWords();
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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<ExistingSequenceMetadata> 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<ExistingSequenceMetadata> sequenceMetadataList = new ArrayList<ExistingSequenceMetadata>();
|
||||
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<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 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<String> reservedWords = new HashSet<String>();
|
||||
reservedWords.addAll( dialect.getKeywords() );
|
||||
|
||||
return new JdbcEnvironmentImpl(
|
||||
dialect,
|
||||
schemaCatalogSupport,
|
||||
FOR_NOW_SCHEMA_NAME_RESOLVER,
|
||||
FOR_NOW_SEQ_META_EXTRACTOR,
|
||||
reservedWords
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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<ObjectName,ExistingTableMetadataImpl> tables = new HashMap<ObjectName, ExistingTableMetadataImpl>();
|
||||
private final Map<ObjectName,ExistingSequenceMetadata> 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<ObjectName,ExistingSequenceMetadata> loadSequenceMetadataMap() throws SQLException {
|
||||
Map<ObjectName,ExistingSequenceMetadata> sequences = new HashMap<ObjectName, ExistingSequenceMetadata>();
|
||||
final Iterable<ExistingSequenceMetadata> 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<Identifier, ExistingColumnMetadata> 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) <null> 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 <currentCatalog>
|
||||
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 <currentSchema>
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,5 @@ import java.sql.SQLException;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ExistingSequenceMetadataExtractor {
|
||||
public Iterable<ExistingSequenceMetadata> extractMetadata(
|
||||
DatabaseMetaData databaseMetaData,
|
||||
IdentifierHelper identifierHelper) throws SQLException;
|
||||
public Iterable<ExistingSequenceMetadata> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException;
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue