HHH-16564 allow null in 'select new' argument list

This commit is contained in:
Gavin 2023-05-06 22:22:58 +02:00 committed by Gavin King
parent 7eacbfab3c
commit c922a10df2
3 changed files with 49 additions and 2 deletions

View File

@ -391,10 +391,13 @@
import org.hibernate.type.BasicType;
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;
@ -4872,8 +4875,17 @@ public Expression visitLiteral(SqmLiteral<?> literal) {
}
final MappingModelExpressible<?> keyExpressible = getKeyExpressible( mappingModelExpressible );
if ( keyExpressible == null ) {
// Default to the Object type
return new QueryLiteral<>( null, basicType( Object.class ) );
// 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;
}
} ) );
}
final List<Expression> expressions = new ArrayList<>( keyExpressible.getJdbcTypeCount() );

View File

@ -57,6 +57,11 @@ public static boolean areAssignmentCompatible(Class to, Class from) {
assert to != null;
assert from != null;
if ( from == Void.class ) {
// treat Void as the bottom type, the class of null
return true;
}
if ( to.isAssignableFrom( from ) ) {
return true;
}

View File

@ -61,6 +61,36 @@ public void testSelectNewCastNull(SessionFactoryScope scope) {
);
}
@Test
@TestForIssue(jiraKey = "HHH-16564")
public void testSelectNewNull(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
Person result = (Person) session.createQuery(
"select new Person( id, firstName, null, lastName ) from Person where lastName='Munster'"
).uniqueResult();
assertEquals( "Herman", result.firstName );
assertNull( result.middleName );
assertEquals( "Munster", result.lastName );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-16564")
public void testSelectNull(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
Object[] result = (Object[]) session.createQuery(
"select id, firstName, null, lastName from Person where lastName='Munster'"
).uniqueResult();
assertEquals( "Herman", result[1] );
assertNull( result[2] );
assertEquals( "Munster", result[3] );
}
);
}
@BeforeEach
public void createTestData(SessionFactoryScope scope) {
scope.inTransaction(