Skip to content

Commit 5089df2

Browse files
committed
HHH-15912 adaptively choose the DDL type for ORDINAL enums based on the number of members
this amounts to a reversion of HHH-15288 for 99.99% of enums
1 parent 7007baf commit 5089df2

File tree

8 files changed

+50
-32
lines changed

8 files changed

+50
-32
lines changed

hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.hibernate.type.BasicType;
2626
import org.hibernate.type.CustomType;
2727
import org.hibernate.type.SerializableType;
28-
import org.hibernate.type.SqlTypes;
2928
import org.hibernate.type.descriptor.java.BasicPluralJavaType;
3029
import org.hibernate.type.descriptor.java.BasicJavaType;
3130
import org.hibernate.type.descriptor.java.EnumJavaType;
@@ -38,6 +37,9 @@
3837
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
3938
import org.hibernate.type.spi.TypeConfiguration;
4039

40+
import static org.hibernate.type.SqlTypes.SMALLINT;
41+
import static org.hibernate.type.SqlTypes.TINYINT;
42+
4143
/**
4244
* BasicValue.Resolution resolver for cases where no explicit
4345
* type info was supplied.
@@ -344,19 +346,19 @@ private static <E extends Enum<E>, N extends Number> InferredBasicValueResolutio
344346
TypeConfiguration typeConfiguration) {
345347
return ordinalResolution(
346348
enumJavaType,
347-
integerJavaType( explicitJavaType, typeConfiguration ),
348-
integerJdbcType( explicitJdbcType, typeConfiguration ),
349+
ordinalJavaType( explicitJavaType, typeConfiguration ),
350+
ordinalJdbcType( explicitJdbcType, enumJavaType, typeConfiguration ),
349351
typeConfiguration
350352
);
351353
}
352354

353-
private static JdbcType integerJdbcType(JdbcType explicitJdbcType, TypeConfiguration typeConfiguration) {
355+
private static JdbcType ordinalJdbcType(JdbcType explicitJdbcType, EnumJavaType<?> enumJavaType, TypeConfiguration typeConfiguration) {
354356
return explicitJdbcType != null
355357
? explicitJdbcType
356-
: typeConfiguration.getJdbcTypeRegistry().getDescriptor( SqlTypes.SMALLINT );
358+
: typeConfiguration.getJdbcTypeRegistry().getDescriptor( enumJavaType.hasManyValues() ? SMALLINT : TINYINT );
357359
}
358360

359-
private static <N extends Number> JavaType<N> integerJavaType(JavaType<N> explicitJavaType, TypeConfiguration typeConfiguration) {
361+
private static <N extends Number> JavaType<N> ordinalJavaType(JavaType<N> explicitJavaType, TypeConfiguration typeConfiguration) {
360362
if ( explicitJavaType != null ) {
361363
if ( !Integer.class.isAssignableFrom( explicitJavaType.getJavaTypeClass() ) ) {
362364
throw new MappingException(

hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1326,7 +1326,6 @@ public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType,
13261326
public boolean equivalentTypes(int typeCode1, int typeCode2) {
13271327
return typeCode1==typeCode2
13281328
|| isNumericOrDecimal(typeCode1) && isNumericOrDecimal(typeCode2)
1329-
|| isSmallOrTinyInt(typeCode1) && isSmallOrTinyInt(typeCode2) //special case for HHH-15288 migration
13301329
// || isIntegral(typeCode1) && isIntegral(typeCode2)
13311330
|| isFloatOrRealOrDouble(typeCode1) && isFloatOrRealOrDouble(typeCode2)
13321331
|| isVarcharType(typeCode1) && isVarcharType(typeCode2)

hibernate-core/src/main/java/org/hibernate/type/descriptor/java/EnumJavaType.java

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,22 @@
66
*/
77
package org.hibernate.type.descriptor.java;
88

9-
import java.sql.Types;
109
import jakarta.persistence.EnumType;
1110

12-
import org.hibernate.type.SqlTypes;
11+
import org.hibernate.AssertionFailure;
1312
import org.hibernate.type.descriptor.WrapperOptions;
1413
import org.hibernate.type.descriptor.jdbc.JdbcType;
1514
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
1615
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
1716

17+
import static jakarta.persistence.EnumType.ORDINAL;
18+
import static org.hibernate.type.SqlTypes.CHAR;
19+
import static org.hibernate.type.SqlTypes.NCHAR;
20+
import static org.hibernate.type.SqlTypes.NVARCHAR;
21+
import static org.hibernate.type.SqlTypes.SMALLINT;
22+
import static org.hibernate.type.SqlTypes.TINYINT;
23+
import static org.hibernate.type.SqlTypes.VARCHAR;
24+
1825
/**
1926
* Describes a Java {@code enum} type.
2027
*
@@ -27,23 +34,29 @@ public EnumJavaType(Class<T> type) {
2734

2835
@Override
2936
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) {
30-
JdbcTypeRegistry registry = context.getTypeConfiguration().getJdbcTypeRegistry();
31-
if ( context.getEnumeratedType() != null && context.getEnumeratedType() == EnumType.STRING ) {
32-
if ( context.getColumnLength() == 1 ) {
37+
final JdbcTypeRegistry registry = context.getTypeConfiguration().getJdbcTypeRegistry();
38+
final EnumType type = context.getEnumeratedType();
39+
switch ( type == null ? ORDINAL : type ) {
40+
case ORDINAL:
41+
return registry.getDescriptor( hasManyValues() ? SMALLINT : TINYINT );
42+
case STRING:
43+
if ( context.getColumnLength() == 1 ) {
44+
return context.isNationalized()
45+
? registry.getDescriptor( NCHAR )
46+
: registry.getDescriptor( CHAR );
47+
}
3348
return context.isNationalized()
34-
? registry.getDescriptor( Types.NCHAR )
35-
: registry.getDescriptor( Types.CHAR );
36-
}
37-
38-
return context.isNationalized()
39-
? registry.getDescriptor( Types.NVARCHAR )
40-
: registry.getDescriptor( Types.VARCHAR );
41-
}
42-
else {
43-
return registry.getDescriptor( SqlTypes.SMALLINT );
49+
? registry.getDescriptor( NVARCHAR )
50+
: registry.getDescriptor( VARCHAR );
51+
default:
52+
throw new AssertionFailure("unknown EnumType");
4453
}
4554
}
4655

56+
public boolean hasManyValues() {
57+
return getJavaTypeClass().getEnumConstants().length > 128; // a bit arbitrary, but gives us some headroom
58+
}
59+
4760
@Override
4861
public String toString(T value) {
4962
return value == null ? "<null>" : value.name();

hibernate-core/src/test/java/org/hibernate/orm/test/annotations/enumerated/EnumeratedSmokeTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ private void validateEnumMapping(JdbcTypeRegistry jdbcRegistry, Property propert
7979
assertThat( hibernateMappingEnumType.isOrdinal(), is(expectedJpaEnumType==EnumType.ORDINAL) );
8080
final int expectedJdbcTypeCode = jdbcRegistry.getDescriptor(
8181
expectedJpaEnumType == EnumType.ORDINAL ?
82-
Types.SMALLINT :
82+
Types.TINYINT :
8383
Types.VARCHAR
8484
).getJdbcTypeCode();
8585
assertThat(

hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/binding/annotations/basics/EnumResolutionTests.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public void testRawEnumResolution(DomainModelScope scope) {
6060

6161
verifyEnumResolution(
6262
entityBinding.getProperty( "rawEnum" ),
63-
Types.SMALLINT,
63+
Types.TINYINT,
6464
Integer.class,
6565
OrdinalEnumValueConverter.class,
6666
true
@@ -75,7 +75,7 @@ public void testUnspecifiedMappingEnumResolution(DomainModelScope scope) {
7575

7676
verifyEnumResolution(
7777
entityBinding.getProperty( "unspecifiedMappingEnum" ),
78-
Types.SMALLINT,
78+
Types.TINYINT,
7979
Integer.class,
8080
OrdinalEnumValueConverter.class,
8181
true
@@ -90,7 +90,7 @@ public void testOrdinalEnumResolution(DomainModelScope scope) {
9090

9191
verifyEnumResolution(
9292
entityBinding.getProperty( "ordinalEnum" ),
93-
Types.SMALLINT,
93+
Types.TINYINT,
9494
Integer.class,
9595
OrdinalEnumValueConverter.class,
9696
true
@@ -143,7 +143,7 @@ public void testExplicitEnumResolution(DomainModelScope scope) {
143143

144144
verifyEnumResolution(
145145
entityBinding.getProperty( "explicitEnum" ),
146-
Types.TINYINT,
146+
Types.SMALLINT,
147147
Integer.class,
148148
OrdinalEnumValueConverter.class,
149149
true
@@ -222,7 +222,7 @@ public static class EntityWithEnums {
222222
private Values namedEnum;
223223

224224
@Enumerated( ORDINAL )
225-
@JdbcTypeCode( Types.TINYINT )
225+
@JdbcTypeCode( Types.SMALLINT )
226226
private Values explicitEnum;
227227
}
228228

hibernate-core/src/test/java/org/hibernate/orm/test/mapping/SmokeTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public void testSimpleEntity(SessionFactoryScope scope) {
104104

105105
assertThat(
106106
jdbcTypeRegistry.getDescriptor( valueConverter.getJdbcTypeCode() ),
107-
is( jdbcTypeRegistry.getDescriptor( Types.SMALLINT ) )
107+
is( jdbcTypeRegistry.getDescriptor( Types.TINYINT ) )
108108
);
109109
}
110110

hibernate-core/src/test/java/org/hibernate/orm/test/sql/ast/SmokeTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ public void testConvertedHqlInterpretation(SessionFactoryScope scope) {
191191
assertThat( enumConverter.getRelationalJavaType().getJavaTypeClass(), AssignableMatcher.assignableTo( Integer.class ) );
192192
assertThat(
193193
basicType.getJdbcType(),
194-
is( jdbcTypeRegistry.getDescriptor( Types.SMALLINT ) )
194+
is( jdbcTypeRegistry.getDescriptor( Types.TINYINT ) )
195195
);
196196

197197

hibernate-core/src/test/java/org/hibernate/orm/test/type/EnumArrayTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
package org.hibernate.orm.test.type;
88

99
import org.hibernate.dialect.AbstractHANADialect;
10+
import org.hibernate.dialect.DB2Dialect;
11+
import org.hibernate.dialect.DerbyDialect;
1012
import org.hibernate.dialect.HSQLDialect;
13+
import org.hibernate.dialect.MySQLDialect;
1114
import org.hibernate.dialect.OracleDialect;
1215
import org.hibernate.dialect.SybaseASEDialect;
1316

@@ -24,8 +27,6 @@
2427
import jakarta.persistence.Table;
2528
import jakarta.persistence.TypedQuery;
2629

27-
import org.hibernate.testing.DialectChecks;
28-
import org.hibernate.testing.RequiresDialectFeature;
2930
import org.hibernate.testing.SkipForDialect;
3031
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
3132
import org.junit.Test;
@@ -113,6 +114,9 @@ public void testNativeQueryById() {
113114
@Test
114115
@SkipForDialect( value = HSQLDialect.class, comment = "HSQL does not like plain parameters in the distinct from predicate")
115116
@SkipForDialect( value = OracleDialect.class, comment = "Oracle requires a special function to compare XML")
117+
@SkipForDialect( value = MySQLDialect.class )
118+
@SkipForDialect( value = DerbyDialect.class )
119+
@SkipForDialect( value = DB2Dialect.class )
116120
public void testNativeQuery() {
117121
inSession( em -> {
118122
final String op = em.getJdbcServices().getDialect().supportsDistinctFromPredicate() ? "IS NOT DISTINCT FROM" : "=";

0 commit comments

Comments
 (0)