HHH-16787 Multi-valued parameter with single element parameter list fails with no such element exception

This commit is contained in:
Christian Beikov 2023-06-13 19:10:43 +02:00
parent 694eee977f
commit 2ad5cdd9b9
9 changed files with 100 additions and 13 deletions

View File

@ -196,15 +196,15 @@ public class FormatFunction extends AbstractSqmFunctionDescriptor implements Fun
@Override
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
final ReturnableType<?> resultType = resolveResultType(
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
);
final MappingModelExpressible<?> mappingModelExpressible = resultType == null ? null : getMappingModelExpressible(
walker,
resultType
resultType,
arguments
);
final List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
final SqlAstNode expression = arguments.get( 0 );
if ( expression instanceof SqlTupleContainer ) {
// SqlTupleContainer means this is a composite temporal type i.e. uses `@TimeZoneStorage(COLUMN)`

View File

@ -108,7 +108,7 @@ public class HypotheticalSetWindowEmulation extends HypotheticalSetFunction {
getFilter() == null ? null : (Predicate) getFilter().accept( walker ),
Collections.emptyList(),
resultType,
getMappingModelExpressible( walker, resultType )
getMappingModelExpressible( walker, resultType, arguments )
);
final Over<Object> windowFunction = new Over<>( function, new ArrayList<>(), withinGroup );
walker.registerQueryTransformer(

View File

@ -164,7 +164,8 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
@Override
protected MappingModelExpressible<?> getMappingModelExpressible(
SqmToSqlAstConverter walker,
ReturnableType<?> resultType) {
ReturnableType<?> resultType,
List<SqlAstNode> arguments) {
MappingModelExpressible<?> mapping;
if ( resultType instanceof MappingModelExpressible) {
// here we have a BasicType, which can be cast

View File

@ -103,7 +103,7 @@ public class InverseDistributionWindowEmulation extends InverseDistributionFunct
getFilter() == null ? null : (Predicate) getFilter().accept( walker ),
withinGroup,
resultType,
getMappingModelExpressible( walker, resultType )
getMappingModelExpressible( walker, resultType, arguments )
);
final Over<Object> windowFunction = new Over<>( function, new ArrayList<>(), Collections.emptyList() );
walker.registerQueryTransformer(

View File

@ -89,7 +89,7 @@ public class SelfRenderingSqmAggregateFunction<T> extends SelfRenderingSqmFuncti
arguments,
filter == null ? null : walker.visitNestedTopLevelPredicate( filter ),
resultType,
getMappingModelExpressible( walker, resultType )
getMappingModelExpressible( walker, resultType, arguments )
);
}

View File

@ -149,7 +149,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
getRenderingSupport(),
arguments,
resultType,
resultType == null ? null : getMappingModelExpressible( walker, resultType )
resultType == null ? null : getMappingModelExpressible( walker, resultType, arguments )
);
}
@ -176,9 +176,10 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
protected MappingModelExpressible<?> getMappingModelExpressible(
SqmToSqlAstConverter walker,
ReturnableType<?> resultType) {
ReturnableType<?> resultType,
List<SqlAstNode> arguments) {
MappingModelExpressible<?> mapping;
if ( resultType instanceof MappingModelExpressible) {
if ( resultType instanceof MappingModelExpressible ) {
// here we have a BasicType, which can be cast
// directly to BasicValuedMapping
mapping = (MappingModelExpressible<?>) resultType;
@ -203,7 +204,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
return null; // this works at least approximately
}
},
resolveSqlAstArguments( getArguments(), walker )
arguments
);
}
return mapping;

View File

@ -127,7 +127,7 @@ public class SelfRenderingSqmOrderedSetAggregateFunction<T> extends SelfRenderin
getFilter() == null ? null : walker.visitNestedTopLevelPredicate( getFilter() ),
withinGroup,
resultType,
getMappingModelExpressible( walker, resultType )
getMappingModelExpressible( walker, resultType, arguments )
);
}

View File

@ -99,7 +99,7 @@ public class SelfRenderingSqmWindowFunction<T> extends SelfRenderingSqmFunction<
respectNulls,
fromFirst,
resultType,
getMappingModelExpressible( walker, resultType )
getMappingModelExpressible( walker, resultType, arguments )
);
}

View File

@ -0,0 +1,85 @@
/*
* 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.orm.test.query.hql;
import java.util.Arrays;
import java.util.Collections;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.FunctionContributor;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry;
import org.hibernate.testing.orm.junit.BootstrapServiceRegistry.JavaService;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@BootstrapServiceRegistry(
javaServices = {
@JavaService(role = FunctionContributor.class, impl = MultiValuedParameterInFunctionTest.MyFunctionContributor.class)
}
)
@DomainModel(annotatedClasses = MultiValuedParameterInFunctionTest.Post.class)
@SessionFactory
@RequiresDialect(H2Dialect.class)
public class MultiValuedParameterInFunctionTest {
@Test
@JiraKey( "HHH-16787" )
public void testAsQueryParameter(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.createQuery( "from Post p where my_function((select p2.id from Post p2 where p2.title in (:name)))=1" )
.setParameter( "name", Collections.singletonList( "1" ) )
.list();
} );
}
@AfterEach
public void dropTestData(SessionFactoryScope scope) {
scope.inTransaction( (session) -> session.createQuery( "delete Post" ).executeUpdate() );
}
@Entity(name = "Post")
@Table(name = "Post")
public static class Post {
@Id
public Integer id;
@Basic
public String title;
private Post() {
// for Hibernate use
}
public Post(Integer id, String title) {
this.id = id;
this.title = title;
}
}
public static class MyFunctionContributor implements FunctionContributor {
@Override
public void contributeFunctions(FunctionContributions functionContributions) {
functionContributions.getFunctionRegistry().registerPattern(
"my_function",
"?1"
);
}
}
}