Skip to content

Commit 8a39ea9

Browse files
gavinkingbeikov
authored andcommitted
HHH-17677 handle literal null arguments more elegantly in StandardFunctionReturnTypeResolvers
resolves a very confusing error message
1 parent 56deb7d commit 8a39ea9

File tree

3 files changed

+34
-10
lines changed

3 files changed

+34
-10
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/produce/function/StandardFunctionReturnTypeResolvers.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,15 @@
1212
import java.util.function.Supplier;
1313

1414
import org.hibernate.Internal;
15-
import org.hibernate.QueryException;
1615
import org.hibernate.metamodel.mapping.BasicValuedMapping;
1716
import org.hibernate.metamodel.mapping.JdbcMapping;
1817
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
1918
import org.hibernate.metamodel.mapping.MappingModelExpressible;
20-
import org.hibernate.metamodel.model.domain.EntityDomainType;
2119
import org.hibernate.query.ReturnableType;
2220
import org.hibernate.query.sqm.SqmExpressible;
2321
import org.hibernate.query.sqm.SqmPathSource;
2422
import org.hibernate.query.sqm.tree.SqmTypedNode;
23+
import org.hibernate.query.sqm.tree.expression.NullSqmExpressible;
2524
import org.hibernate.sql.ast.tree.SqlAstNode;
2625
import org.hibernate.sql.ast.tree.expression.Expression;
2726
import org.hibernate.type.BasicType;
@@ -252,7 +251,10 @@ public static ReturnableType<?> extractArgumentType(
252251
int position) {
253252
final SqmTypedNode<?> specifiedArgument = arguments.get( position - 1 );
254253
final SqmExpressible<?> specifiedArgType = getArgumentExpressible( specifiedArgument );
255-
if ( specifiedArgType != null && !(specifiedArgType instanceof ReturnableType ) ) {
254+
if ( specifiedArgType == null || specifiedArgType instanceof NullSqmExpressible ) {
255+
return null;
256+
}
257+
else if ( !(specifiedArgType instanceof ReturnableType) ) {
256258
throw new FunctionArgumentException(
257259
String.format(
258260
Locale.ROOT,
@@ -263,18 +265,19 @@ public static ReturnableType<?> extractArgumentType(
263265
)
264266
);
265267
}
266-
267-
return (ReturnableType<?>) specifiedArgType;
268+
else {
269+
return (ReturnableType<?>) specifiedArgType;
270+
}
268271
}
269272

270273
private static SqmExpressible<?> getArgumentExpressible(SqmTypedNode<?> specifiedArgument) {
271274
final SqmExpressible<?> expressible = specifiedArgument.getNodeType();
272275
final SqmExpressible<?> specifiedArgType = expressible instanceof SqmTypedNode<?>
273276
? ( (SqmTypedNode<?>) expressible ).getNodeType()
274277
: expressible;
275-
return specifiedArgType instanceof SqmPathSource ?
276-
( (SqmPathSource<?>) specifiedArgType ).getSqmPathType() :
277-
specifiedArgType;
278+
return specifiedArgType instanceof SqmPathSource
279+
? ( (SqmPathSource<?>) specifiedArgType ).getSqmPathType()
280+
: specifiedArgType;
278281
}
279282

280283
public static JdbcMapping extractArgumentJdbcMapping(

hibernate-core/src/main/java/org/hibernate/sql/results/internal/SqlSelectionImpl.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.hibernate.engine.spi.SessionFactoryImplementor;
1212
import org.hibernate.metamodel.mapping.JdbcMapping;
1313
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
14-
import org.hibernate.metamodel.mapping.SqlExpressible;
1514
import org.hibernate.sql.ast.SqlAstWalker;
1615
import org.hibernate.sql.ast.spi.SqlExpressionAccess;
1716
import org.hibernate.sql.ast.spi.SqlSelection;
@@ -93,7 +92,10 @@ protected SqlSelectionImpl(
9392
}
9493

9594
private static ValueExtractor determineValueExtractor(Expression sqlExpression, JavaType<?> jdbcJavaType) {
96-
final JdbcMapping jdbcMapping = sqlExpression.getExpressionType().getSingleJdbcMapping();
95+
final JdbcMappingContainer expressionType = sqlExpression.getExpressionType();
96+
final JdbcMapping jdbcMapping = expressionType == null
97+
? JavaObjectType.INSTANCE
98+
: expressionType.getSingleJdbcMapping();
9799
if ( jdbcJavaType == null || jdbcMapping.getMappedJavaType() == jdbcJavaType ) {
98100
return jdbcMapping.getJdbcValueExtractor();
99101
}
@@ -102,6 +104,7 @@ private static ValueExtractor determineValueExtractor(Expression sqlExpression,
102104
}
103105
}
104106

107+
105108
@Override
106109
public Expression getExpression() {
107110
return sqlExpression;

hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,4 +2248,22 @@ public void testTupleInSelect(SessionFactoryScope scope) {
22482248
}
22492249
);
22502250
}
2251+
2252+
@Test
2253+
@SkipForDialect(dialectClass = H2Dialect.class)
2254+
@SkipForDialect(dialectClass = DerbyDialect.class)
2255+
@SkipForDialect(dialectClass = HSQLDialect.class)
2256+
@SkipForDialect(dialectClass = DB2Dialect.class)
2257+
public void testNullInCoalesce(SessionFactoryScope scope) {
2258+
scope.inTransaction(s -> {
2259+
assertEquals("hello",
2260+
s.createQuery("select coalesce(null, :word)", String.class)
2261+
.setParameter("word", "hello")
2262+
.getSingleResultOrNull());
2263+
assertEquals("hello",
2264+
s.createQuery("select coalesce(:word, null)", String.class)
2265+
.setParameter("word", "hello")
2266+
.getSingleResultOrNull());
2267+
});
2268+
}
22512269
}

0 commit comments

Comments
 (0)