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
|
@Override
|
||||||
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
|
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
|
||||||
|
final List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
|
||||||
final ReturnableType<?> resultType = resolveResultType(
|
final ReturnableType<?> resultType = resolveResultType(
|
||||||
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
|
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
|
||||||
);
|
);
|
||||||
final MappingModelExpressible<?> mappingModelExpressible = resultType == null ? null : getMappingModelExpressible(
|
final MappingModelExpressible<?> mappingModelExpressible = resultType == null ? null : getMappingModelExpressible(
|
||||||
walker,
|
walker,
|
||||||
resultType
|
resultType,
|
||||||
|
arguments
|
||||||
);
|
);
|
||||||
|
|
||||||
final List<SqlAstNode> arguments = resolveSqlAstArguments( getArguments(), walker );
|
|
||||||
final SqlAstNode expression = arguments.get( 0 );
|
final SqlAstNode expression = arguments.get( 0 );
|
||||||
if ( expression instanceof SqlTupleContainer ) {
|
if ( expression instanceof SqlTupleContainer ) {
|
||||||
// SqlTupleContainer means this is a composite temporal type i.e. uses `@TimeZoneStorage(COLUMN)`
|
// 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.spi.QueryEngine;
|
||||||
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||||
import org.hibernate.query.sqm.function.SelfRenderingOrderedSetAggregateFunctionSqlAstExpression;
|
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.function.SelfRenderingSqmOrderedSetAggregateFunction;
|
||||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||||
|
@ -110,7 +109,7 @@ public class HypotheticalSetWindowEmulation extends HypotheticalSetFunction {
|
||||||
getFilter() == null ? null : (Predicate) getFilter().accept( walker ),
|
getFilter() == null ? null : (Predicate) getFilter().accept( walker ),
|
||||||
Collections.emptyList(),
|
Collections.emptyList(),
|
||||||
resultType,
|
resultType,
|
||||||
getMappingModelExpressible( walker, resultType )
|
getMappingModelExpressible( walker, resultType, arguments )
|
||||||
);
|
);
|
||||||
final Over<Object> windowFunction = new Over<>( function, new ArrayList<>(), withinGroup );
|
final Over<Object> windowFunction = new Over<>( function, new ArrayList<>(), withinGroup );
|
||||||
walker.registerQueryTransformer(
|
walker.registerQueryTransformer(
|
||||||
|
|
|
@ -160,7 +160,8 @@ public class InverseDistributionFunction extends AbstractSqmSelfRenderingFunctio
|
||||||
@Override
|
@Override
|
||||||
protected MappingModelExpressible<?> getMappingModelExpressible(
|
protected MappingModelExpressible<?> getMappingModelExpressible(
|
||||||
SqmToSqlAstConverter walker,
|
SqmToSqlAstConverter walker,
|
||||||
ReturnableType<?> resultType) {
|
ReturnableType<?> resultType,
|
||||||
|
List<SqlAstNode> arguments) {
|
||||||
MappingModelExpressible<?> mapping;
|
MappingModelExpressible<?> mapping;
|
||||||
if ( resultType instanceof MappingModelExpressible) {
|
if ( resultType instanceof MappingModelExpressible) {
|
||||||
// here we have a BasicType, which can be cast
|
// 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.spi.QueryEngine;
|
||||||
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||||
import org.hibernate.query.sqm.function.SelfRenderingOrderedSetAggregateFunctionSqlAstExpression;
|
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.function.SelfRenderingSqmOrderedSetAggregateFunction;
|
||||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||||
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
|
import org.hibernate.query.sqm.produce.function.FunctionParameterType;
|
||||||
|
@ -105,7 +104,7 @@ public class InverseDistributionWindowEmulation extends InverseDistributionFunct
|
||||||
getFilter() == null ? null : (Predicate) getFilter().accept( walker ),
|
getFilter() == null ? null : (Predicate) getFilter().accept( walker ),
|
||||||
withinGroup,
|
withinGroup,
|
||||||
resultType,
|
resultType,
|
||||||
getMappingModelExpressible( walker, resultType )
|
getMappingModelExpressible( walker, resultType, arguments )
|
||||||
);
|
);
|
||||||
final Over<Object> windowFunction = new Over<>( function, new ArrayList<>(), Collections.emptyList() );
|
final Over<Object> windowFunction = new Over<>( function, new ArrayList<>(), Collections.emptyList() );
|
||||||
walker.registerQueryTransformer(
|
walker.registerQueryTransformer(
|
||||||
|
|
|
@ -89,7 +89,7 @@ public class SelfRenderingSqmAggregateFunction<T> extends SelfRenderingSqmFuncti
|
||||||
arguments,
|
arguments,
|
||||||
filter == null ? null : walker.visitNestedTopLevelPredicate( filter ),
|
filter == null ? null : walker.visitNestedTopLevelPredicate( filter ),
|
||||||
resultType,
|
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() );
|
final ArrayList<SqlAstNode> sqlAstArguments = new ArrayList<>( sqmArguments.size() );
|
||||||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||||
sqlAstArguments.add(
|
sqlAstArguments.add(
|
||||||
(SqlAstNode) ( (SqmVisitableNode) sqmArguments.get( i ) ).accept( walker )
|
(SqlAstNode) sqmArguments.get( i ).accept( walker )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return sqlAstArguments;
|
return sqlAstArguments;
|
||||||
|
@ -129,7 +129,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
||||||
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
for ( int i = 0; i < sqmArguments.size(); i++ ) {
|
||||||
typeAccess.argumentIndex = i;
|
typeAccess.argumentIndex = i;
|
||||||
sqlAstArguments.add(
|
sqlAstArguments.add(
|
||||||
(SqlAstNode) walker.visitWithInferredType( (SqmVisitableNode) sqmArguments.get( i ), typeAccess )
|
(SqlAstNode) walker.visitWithInferredType( sqmArguments.get( i ), typeAccess )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return sqlAstArguments;
|
return sqlAstArguments;
|
||||||
|
@ -150,7 +150,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
||||||
getRenderingSupport(),
|
getRenderingSupport(),
|
||||||
arguments,
|
arguments,
|
||||||
resultType,
|
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;
|
return resultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated(forRemoval = true)
|
||||||
protected MappingModelExpressible<?> getMappingModelExpressible(
|
protected MappingModelExpressible<?> getMappingModelExpressible(
|
||||||
SqmToSqlAstConverter walker,
|
SqmToSqlAstConverter walker,
|
||||||
ReturnableType<?> resultType) {
|
ReturnableType<?> resultType) {
|
||||||
|
return getMappingModelExpressible( walker, resultType, resolveSqlAstArguments( getArguments(), walker ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MappingModelExpressible<?> getMappingModelExpressible(
|
||||||
|
SqmToSqlAstConverter walker,
|
||||||
|
ReturnableType<?> resultType,
|
||||||
|
List<SqlAstNode> arguments) {
|
||||||
MappingModelExpressible<?> mapping;
|
MappingModelExpressible<?> mapping;
|
||||||
if ( resultType instanceof MappingModelExpressible) {
|
if ( resultType instanceof MappingModelExpressible ) {
|
||||||
// here we have a BasicType, which can be cast
|
// here we have a BasicType, which can be cast
|
||||||
// directly to BasicValuedMapping
|
// directly to BasicValuedMapping
|
||||||
mapping = (MappingModelExpressible<?>) resultType;
|
mapping = (MappingModelExpressible<?>) resultType;
|
||||||
|
@ -204,7 +212,7 @@ public class SelfRenderingSqmFunction<T> extends SqmFunction<T> {
|
||||||
return null; // this works at least approximately
|
return null; // this works at least approximately
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolveSqlAstArguments( getArguments(), walker )
|
arguments
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return mapping;
|
return mapping;
|
||||||
|
|
|
@ -127,7 +127,7 @@ public class SelfRenderingSqmOrderedSetAggregateFunction<T> extends SelfRenderin
|
||||||
getFilter() == null ? null : walker.visitNestedTopLevelPredicate( getFilter() ),
|
getFilter() == null ? null : walker.visitNestedTopLevelPredicate( getFilter() ),
|
||||||
withinGroup,
|
withinGroup,
|
||||||
resultType,
|
resultType,
|
||||||
getMappingModelExpressible( walker, resultType )
|
getMappingModelExpressible( walker, resultType, arguments )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ public class SelfRenderingSqmWindowFunction<T> extends SelfRenderingSqmFunction<
|
||||||
respectNulls,
|
respectNulls,
|
||||||
fromFirst,
|
fromFirst,
|
||||||
resultType,
|
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