HHH-9848 - Allow disabling auto-quoting of database object names (tables, columns, etc)
This commit is contained in:
parent
5b1da92498
commit
30b260f14f
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.boot;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import javax.persistence.AttributeConverter;
|
||||
import javax.persistence.SharedCacheMode;
|
||||
|
||||
|
@ -23,6 +24,7 @@ import org.hibernate.cache.spi.access.AccessType;
|
|||
import org.hibernate.cfg.AttributeConverterDefinition;
|
||||
import org.hibernate.cfg.MetadataSourceType;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.usertype.CompositeUserType;
|
||||
import org.hibernate.usertype.UserType;
|
||||
|
|
|
@ -540,6 +540,8 @@ public class MetadataBuilderImpl implements MetadataBuilder, TypeContributions {
|
|||
|
||||
private IdGeneratorInterpreterImpl idGenerationTypeInterpreter = new IdGeneratorInterpreterImpl();
|
||||
|
||||
private boolean autoQuoteKeywords;
|
||||
|
||||
// private PersistentAttributeMemberResolver persistentAttributeMemberResolver =
|
||||
// StandardPersistentAttributeMemberResolver.INSTANCE;
|
||||
|
||||
|
|
|
@ -18,24 +18,24 @@ import org.hibernate.cache.spi.access.AccessType;
|
|||
* @since 5.0
|
||||
*/
|
||||
public interface MappingDefaults {
|
||||
public static final String DEFAULT_IDENTIFIER_COLUMN_NAME = "id";
|
||||
public static final String DEFAULT_TENANT_IDENTIFIER_COLUMN_NAME = "tenant_id";
|
||||
public static final String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "class";
|
||||
public static final String DEFAULT_CASCADE_NAME = "none";
|
||||
public static final String DEFAULT_PROPERTY_ACCESS_NAME = "property";
|
||||
String DEFAULT_IDENTIFIER_COLUMN_NAME = "id";
|
||||
String DEFAULT_TENANT_IDENTIFIER_COLUMN_NAME = "tenant_id";
|
||||
String DEFAULT_DISCRIMINATOR_COLUMN_NAME = "class";
|
||||
String DEFAULT_CASCADE_NAME = "none";
|
||||
String DEFAULT_PROPERTY_ACCESS_NAME = "property";
|
||||
/**
|
||||
* Identifies the database schema name to use if none specified in the mapping.
|
||||
*
|
||||
* @return The implicit schema name; may be {@code null}
|
||||
*/
|
||||
public String getImplicitSchemaName();
|
||||
String getImplicitSchemaName();
|
||||
|
||||
/**
|
||||
* Identifies the database catalog name to use if none specified in the mapping.
|
||||
*
|
||||
* @return The implicit catalog name; may be {@code null}
|
||||
*/
|
||||
public String getImplicitCatalogName();
|
||||
String getImplicitCatalogName();
|
||||
|
||||
/**
|
||||
* Should all database identifiers encountered in this context be implicitly quoted?
|
||||
|
@ -46,7 +46,7 @@ public interface MappingDefaults {
|
|||
*
|
||||
* @return {@code true}/{@code false}
|
||||
*/
|
||||
public boolean shouldImplicitlyQuoteIdentifiers();
|
||||
boolean shouldImplicitlyQuoteIdentifiers();
|
||||
|
||||
/**
|
||||
* Identifies the column name to use for the identifier column if none specified in
|
||||
|
@ -54,7 +54,7 @@ public interface MappingDefaults {
|
|||
*
|
||||
* @return The implicit identifier column name
|
||||
*/
|
||||
public String getImplicitIdColumnName();
|
||||
String getImplicitIdColumnName();
|
||||
|
||||
/**
|
||||
* Identifies the column name to use for the tenant identifier column if none is
|
||||
|
@ -62,7 +62,7 @@ public interface MappingDefaults {
|
|||
*
|
||||
* @return The implicit tenant identifier column name
|
||||
*/
|
||||
public String getImplicitTenantIdColumnName();
|
||||
String getImplicitTenantIdColumnName();
|
||||
|
||||
/**
|
||||
* Identifies the column name to use for the discriminator column if none specified
|
||||
|
@ -70,7 +70,7 @@ public interface MappingDefaults {
|
|||
*
|
||||
* @return The implicit discriminator column name
|
||||
*/
|
||||
public String getImplicitDiscriminatorColumnName();
|
||||
String getImplicitDiscriminatorColumnName();
|
||||
|
||||
/**
|
||||
* Identifies the package name to use if none specified in the mapping. Really only
|
||||
|
@ -78,21 +78,21 @@ public interface MappingDefaults {
|
|||
*
|
||||
* @return The implicit package name.
|
||||
*/
|
||||
public String getImplicitPackageName();
|
||||
String getImplicitPackageName();
|
||||
|
||||
/**
|
||||
* Is auto-importing of entity (short) names enabled?
|
||||
*
|
||||
* @return {@code true} if auto-importing is enabled; {@code false} otherwise.
|
||||
*/
|
||||
public boolean isAutoImportEnabled();
|
||||
boolean isAutoImportEnabled();
|
||||
|
||||
/**
|
||||
* Identifies the cascade style to apply to associations if none specified in the mapping.
|
||||
*
|
||||
* @return The implicit cascade style
|
||||
*/
|
||||
public String getImplicitCascadeStyleName();
|
||||
String getImplicitCascadeStyleName();
|
||||
|
||||
/**
|
||||
* Identifies the default {@link org.hibernate.property.access.spi.PropertyAccessStrategy} name to use if none specified in the
|
||||
|
@ -102,7 +102,7 @@ public interface MappingDefaults {
|
|||
*
|
||||
* @see org.hibernate.property.access.spi.PropertyAccessStrategy
|
||||
*/
|
||||
public String getImplicitPropertyAccessorName();
|
||||
String getImplicitPropertyAccessorName();
|
||||
|
||||
/**
|
||||
* Identifies whether singular associations (many-to-one, one-to-one) are lazy
|
||||
|
@ -110,19 +110,19 @@ public interface MappingDefaults {
|
|||
*
|
||||
* @return The implicit association laziness
|
||||
*/
|
||||
public boolean areEntitiesImplicitlyLazy();
|
||||
boolean areEntitiesImplicitlyLazy();
|
||||
|
||||
/**
|
||||
* Identifies whether plural attributes are lazy by default if not specified in the mapping.
|
||||
*
|
||||
* @return The implicit association laziness
|
||||
*/
|
||||
public boolean areCollectionsImplicitlyLazy();
|
||||
boolean areCollectionsImplicitlyLazy();
|
||||
|
||||
/**
|
||||
* The cache access type to use if none is specified
|
||||
*
|
||||
* @return The implicit cache access type.
|
||||
*/
|
||||
public AccessType getImplicitCacheAccessType();
|
||||
AccessType getImplicitCacheAccessType();
|
||||
}
|
||||
|
|
|
@ -746,9 +746,11 @@ public interface AvailableSettings {
|
|||
*/
|
||||
String LOG_SESSION_METRICS = "hibernate.session.events.log";
|
||||
|
||||
/**
|
||||
* Defines a default {@link org.hibernate.SessionEventListener} to be applied to opened Sessions.
|
||||
*/
|
||||
String AUTO_SESSION_EVENTS_LISTENER = "hibernate.session.events.auto";
|
||||
|
||||
|
||||
/**
|
||||
* The deprecated name. Use {@link #SCANNER} or {@link #SCANNER_ARCHIVE_INTERPRETER} instead.
|
||||
*/
|
||||
|
@ -820,4 +822,12 @@ public interface AvailableSettings {
|
|||
* annotations (combined with {@code orm.xml} mappings).
|
||||
*/
|
||||
String ARTIFACT_PROCESSING_ORDER = "hibernate.mapping.precedence";
|
||||
|
||||
/**
|
||||
* Specifies whether to automatically quote any names that are deemed keywords. Auto-quoting
|
||||
* is enabled by default. Set to false to disable.
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
String KEYWORD_AUTO_QUOTING_ENABLED = "hibernate.auto_quote_keyword";
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import org.hibernate.dialect.Dialect;
|
|||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
|
||||
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
|
@ -78,6 +77,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
|
|||
|
||||
final IdentifierHelperBuilder identifierHelperBuilder = IdentifierHelperBuilder.from( this );
|
||||
identifierHelperBuilder.setGloballyQuoteIdentifiers( globalQuoting( cfgService ) );
|
||||
identifierHelperBuilder.setGloballyQuoteIdentifiers( autoQuoting( cfgService ) );
|
||||
identifierHelperBuilder.setNameQualifierSupport( nameQualifierSupport );
|
||||
|
||||
IdentifierHelper identifierHelper = null;
|
||||
|
@ -113,6 +113,14 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
|
|||
);
|
||||
}
|
||||
|
||||
private static boolean autoQuoting(ConfigurationService cfgService) {
|
||||
return cfgService.getSetting(
|
||||
AvailableSettings.KEYWORD_AUTO_QUOTING_ENABLED,
|
||||
StandardConverters.BOOLEAN,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor form used from testing
|
||||
*
|
||||
|
@ -207,6 +215,7 @@ public class JdbcEnvironmentImpl implements JdbcEnvironment {
|
|||
|
||||
final IdentifierHelperBuilder identifierHelperBuilder = IdentifierHelperBuilder.from( this );
|
||||
identifierHelperBuilder.setGloballyQuoteIdentifiers( globalQuoting( cfgService ) );
|
||||
identifierHelperBuilder.setAutoQuoteKeywords( autoQuoting( cfgService ) );
|
||||
identifierHelperBuilder.setNameQualifierSupport( nameQualifierSupport );
|
||||
IdentifierHelper identifierHelper = null;
|
||||
try {
|
||||
|
|
|
@ -28,6 +28,7 @@ public class NormalizingIdentifierHelperImpl implements IdentifierHelper {
|
|||
|
||||
private final NameQualifierSupport nameQualifierSupport;
|
||||
private final boolean globallyQuoteIdentifiers;
|
||||
private final boolean autoQuoteKeywords;
|
||||
private final Set<String> reservedWords = new TreeSet<String>( String.CASE_INSENSITIVE_ORDER );
|
||||
private final IdentifierCaseStrategy unquotedCaseStrategy;
|
||||
private final IdentifierCaseStrategy quotedCaseStrategy;
|
||||
|
@ -36,12 +37,14 @@ public class NormalizingIdentifierHelperImpl implements IdentifierHelper {
|
|||
JdbcEnvironment jdbcEnvironment,
|
||||
NameQualifierSupport nameQualifierSupport,
|
||||
boolean globallyQuoteIdentifiers,
|
||||
boolean autoQuoteKeywords,
|
||||
Set<String> reservedWords,
|
||||
IdentifierCaseStrategy unquotedCaseStrategy,
|
||||
IdentifierCaseStrategy quotedCaseStrategy) {
|
||||
this.jdbcEnvironment = jdbcEnvironment;
|
||||
this.nameQualifierSupport = nameQualifierSupport;
|
||||
this.globallyQuoteIdentifiers = globallyQuoteIdentifiers;
|
||||
this.autoQuoteKeywords = autoQuoteKeywords;
|
||||
if ( reservedWords != null ) {
|
||||
this.reservedWords.addAll( reservedWords );
|
||||
}
|
||||
|
@ -66,7 +69,7 @@ public class NormalizingIdentifierHelperImpl implements IdentifierHelper {
|
|||
return Identifier.toIdentifier( identifier.getText(), true );
|
||||
}
|
||||
|
||||
if ( isReservedWord( identifier.getText() ) ) {
|
||||
if ( autoQuoteKeywords && isReservedWord( identifier.getText() ) ) {
|
||||
log.tracef( "Forcing identifier [%s] to quoted as recognized reserveed word", identifier );
|
||||
return Identifier.toIdentifier( identifier.getText(), true );
|
||||
}
|
||||
|
@ -208,7 +211,7 @@ public class NormalizingIdentifierHelperImpl implements IdentifierHelper {
|
|||
return Identifier.toIdentifier( text, true );
|
||||
}
|
||||
|
||||
if ( isReservedWord( text ) ) {
|
||||
if ( autoQuoteKeywords && isReservedWord( text ) ) {
|
||||
// unequivocally it needs to be quoted...
|
||||
log.trace( "Forcing DatabaseMetaData return value as quoted as it was recognized as a reserved word" );
|
||||
return Identifier.toIdentifier( text, true );
|
||||
|
|
|
@ -34,6 +34,7 @@ public class IdentifierHelperBuilder {
|
|||
|
||||
private Set<String> reservedWords = new TreeSet<String>( String.CASE_INSENSITIVE_ORDER );
|
||||
private boolean globallyQuoteIdentifiers = false;
|
||||
private boolean autoQuoteKeywords = true;
|
||||
private IdentifierCaseStrategy unquotedCaseStrategy = IdentifierCaseStrategy.UPPER;
|
||||
private IdentifierCaseStrategy quotedCaseStrategy = IdentifierCaseStrategy.MIXED;
|
||||
|
||||
|
@ -135,6 +136,10 @@ public class IdentifierHelperBuilder {
|
|||
this.globallyQuoteIdentifiers = globallyQuoteIdentifiers;
|
||||
}
|
||||
|
||||
public void setAutoQuoteKeywords(boolean autoQuoteKeywords) {
|
||||
this.autoQuoteKeywords = autoQuoteKeywords;
|
||||
}
|
||||
|
||||
public NameQualifierSupport getNameQualifierSupport() {
|
||||
return nameQualifierSupport;
|
||||
}
|
||||
|
@ -186,6 +191,7 @@ public class IdentifierHelperBuilder {
|
|||
jdbcEnvironment,
|
||||
nameQualifierSupport,
|
||||
globallyQuoteIdentifiers,
|
||||
autoQuoteKeywords,
|
||||
reservedWords,
|
||||
unquotedCaseStrategy,
|
||||
quotedCaseStrategy
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.schemaupdate;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
import org.hibernate.testing.boot.ServiceRegistryTestingImpl;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class IdentifierHelperTest extends BaseUnitTestCase {
|
||||
@Test
|
||||
public void testAutoQuotingDisabled() {
|
||||
ServiceRegistry sr = ServiceRegistryTestingImpl.forUnitTesting(
|
||||
Collections.singletonMap(
|
||||
AvailableSettings.KEYWORD_AUTO_QUOTING_ENABLED,
|
||||
// true is the default, but to be sure...
|
||||
true
|
||||
)
|
||||
);
|
||||
Identifier identifier = sr.getService( JdbcEnvironment.class ).getIdentifierHelper().toIdentifier( "select" );
|
||||
assertTrue( identifier.isQuoted() );
|
||||
StandardServiceRegistryBuilder.destroy( sr );
|
||||
|
||||
sr = ServiceRegistryTestingImpl.forUnitTesting(
|
||||
Collections.singletonMap(
|
||||
AvailableSettings.KEYWORD_AUTO_QUOTING_ENABLED,
|
||||
false
|
||||
)
|
||||
);
|
||||
identifier = sr.getService( JdbcEnvironment.class ).getIdentifierHelper().toIdentifier( "select" );
|
||||
assertFalse( identifier.isQuoted() );
|
||||
StandardServiceRegistryBuilder.destroy( sr );
|
||||
}
|
||||
}
|
|
@ -45,6 +45,19 @@ public class ServiceRegistryTestingImpl
|
|||
);
|
||||
}
|
||||
|
||||
public static ServiceRegistryTestingImpl forUnitTesting(Map settings) {
|
||||
return new ServiceRegistryTestingImpl(
|
||||
true,
|
||||
new BootstrapServiceRegistryBuilder().build(),
|
||||
StandardServiceInitiators.LIST,
|
||||
Arrays.asList(
|
||||
dialectFactoryService(),
|
||||
connectionProviderService()
|
||||
),
|
||||
settings
|
||||
);
|
||||
}
|
||||
|
||||
private static ProvidedService dialectFactoryService() {
|
||||
return new ProvidedService<DialectFactory>( DialectFactory.class, new DialectFactoryTestingImpl() );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue