HHH-16564 introduce BottomType

This commit is contained in:
Gavin 2023-05-07 10:44:26 +02:00 committed by Gavin King
parent 8c1f9c4aad
commit d5b6f769a4
3 changed files with 51 additions and 14 deletions

View File

@ -389,15 +389,13 @@ import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
import org.hibernate.type.BasicType;
import org.hibernate.type.BottomType;
import org.hibernate.type.JavaObjectType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.java.AbstractClassJavaType;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.JavaTypeHelper;
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
import org.hibernate.type.descriptor.jdbc.NullJdbcType;
import org.hibernate.type.internal.BasicTypeImpl;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.UserVersionType;
@ -4876,16 +4874,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final MappingModelExpressible<?> keyExpressible = getKeyExpressible( mappingModelExpressible );
if ( keyExpressible == null ) {
// treat Void as the bottom type, the class of null
return new QueryLiteral<>( null, new JavaObjectType(NullJdbcType.INSTANCE, new AbstractClassJavaType<>(Void.class) {
@Override
public <X> X unwrap(Object value, Class<X> type, WrapperOptions options) {
return null;
}
@Override
public <X> Void wrap(X value, WrapperOptions options) {
return null;
}
} ) );
return new QueryLiteral<>( null, BottomType.INSTANCE );
}
final List<Expression> expressions = new ArrayList<>( keyExpressible.getJdbcTypeCount() );

View File

@ -57,7 +57,7 @@ public class Compatibility {
assert to != null;
assert from != null;
if ( from == Void.class ) {
if ( from == Void.class && !to.isPrimitive() ) {
// treat Void as the bottom type, the class of null
return true;
}

View File

@ -0,0 +1,48 @@
/*
* 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.type;
import org.hibernate.Internal;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractClassJavaType;
import org.hibernate.type.descriptor.jdbc.NullJdbcType;
/**
* A type that is assignable to every non-primitive type,
* that is, the type of {@code null}. Note that this not
* a true bottom type, since {@code null} cannot be assigned
* to primitive types.
* <p>
* Since the Java language does not have an explicit bottom
* type, we follow the type system developed for the Ceylon
* language and treat {@link Void} as the Java bottom type.
*
* @author Gavin King
*/
@Internal
public class BottomType extends AbstractSingleColumnStandardBasicType<Void> {
public static final BottomType INSTANCE = new BottomType();
private BottomType() {
super( NullJdbcType.INSTANCE, new AbstractClassJavaType<>(Void.class) {
@Override
public <X> X unwrap(Void value, Class<X> type, WrapperOptions options) {
return null;
}
@Override
public <X> Void wrap(X value, WrapperOptions options) {
return null;
}
} );
}
@Override
public String getName() {
return "NULL";
}
}