HHH-16787 Multi-valued parameter with single element parameter list fails with no such element exception
This commit is contained in:
parent
6034d357bb
commit
521a36f5d6
|
@ -197,15 +197,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)`
|
||||
|
|
|
@ -14,7 +14,6 @@ import org.hibernate.query.ReturnableType;
|
|||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingOrderedSetAggregateFunctionSqlAstExpression;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingSqmAggregateFunction;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingSqmOrderedSetAggregateFunction;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
|
@ -110,7 +109,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(
|
||||
|
|
|
@ -160,7 +160,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
|
||||
|
|
|
@ -14,7 +14,6 @@ import org.hibernate.query.ReturnableType;
|
|||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingOrderedSetAggregateFunctionSqlAstExpression;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingSqmAggregateFunction;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingSqmOrderedSetAggregateFunction;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
|
||||
|
@ -105,7 +104,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(
|
||||
|
|
|
@ -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 )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>( sqmArguments.size() );
|
||||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||
sqlAstArguments.add(
|
||||
(SqlAstNode) ( (SqmVisitableNode) sqmArguments.get( i ) ).accept( walker )
|
||||
(SqlAstNode) sqmArguments.get( i ).accept( walker )
|
||||
);
|
||||
}
|
||||
return sqlAstArguments;
|
||||
|
@ -129,7 +129,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||
typeAccess.argumentIndex = i;
|
||||
sqlAstArguments.add(
|
||||
(SqlAstNode) walker.visitWithInferredType( (SqmVisitableNode) sqmArguments.get( i ), typeAccess )
|
||||
(SqlAstNode) walker.visitWithInferredType( sqmArguments.get( i ), typeAccess )
|
||||
);
|
||||
}
|
||||
return sqlAstArguments;
|
||||
|
@ -150,7 +150,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
getRenderingSupport(),
|
||||
arguments,
|
||||
resultType,
|
||||
resultType == null ? null : getMappingModelExpressible( walker, resultType )
|
||||
resultType == null ? null : getMappingModelExpressible( walker, resultType, arguments )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -175,11 +175,19 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
return resultType;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
protected MappingModelExpressible<?> getMappingModelExpressible(
|
||||
SqmToSqlAstConverter walker,
|
||||
ReturnableType<?> resultType) {
|
||||
return getMappingModelExpressible( walker, resultType, resolveSqlAstArguments( getArguments(), walker ) );
|
||||
}
|
||||
|
||||
protected MappingModelExpressible<?> getMappingModelExpressible(
|
||||
SqmToSqlAstConverter walker,
|
||||
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;
|
||||
|
@ -204,7 +212,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
|||
return null; // this works at least approximately
|
||||
}
|
||||
},
|
||||
resolveSqlAstArguments( getArguments(), walker )
|
||||
arguments
|
||||
);
|
||||
}
|
||||
return mapping;
|
||||
|
|
|
@ -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 )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ public class SelfRenderingSqmWindowFunction<T> extends SelfRenderingSqmFunction<
|
|||
respectNulls,
|
||||
fromFirst,
|
||||
resultType,
|
||||
getMappingModelExpressible( walker, resultType )
|
||||
getMappingModelExpressible( walker, resultType, arguments )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue