Fix JPA Criteria parameter inference for case when expressions
This commit is contained in:
parent
e59f2b9761
commit
bc6022459d
|
@ -18,6 +18,8 @@ import org.hibernate.query.sqm.tree.SqmExpressableAccessor;
|
||||||
import org.hibernate.query.sqm.tree.SqmStatement;
|
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||||
import org.hibernate.query.sqm.tree.domain.SqmIndexedCollectionAccessPath;
|
import org.hibernate.query.sqm.tree.domain.SqmIndexedCollectionAccessPath;
|
||||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmCaseSearched;
|
||||||
|
import org.hibernate.query.sqm.tree.expression.SqmCaseSimple;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
import org.hibernate.query.sqm.tree.expression.SqmExpression;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||||
|
@ -139,6 +141,97 @@ public class ParameterCollector extends BaseSemanticQueryWalker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitSimpleCaseExpression(SqmCaseSimple<?, ?> expression) {
|
||||||
|
final SqmExpressableAccessor<?> inferenceSupplier = this.inferenceBasis;
|
||||||
|
withTypeInference(
|
||||||
|
() -> {
|
||||||
|
for ( SqmCaseSimple.WhenFragment<?, ?> whenFragment : expression.getWhenFragments() ) {
|
||||||
|
final SqmExpressable<?> resolved = whenFragment.getCheckValue().getExpressable();
|
||||||
|
if ( resolved instanceof AllowableParameterType<?> ) {
|
||||||
|
return (SqmExpressable<Object>) resolved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
() -> expression.getFixture().accept( this )
|
||||||
|
);
|
||||||
|
SqmExpressableAccessor<?> resolved = determineCurrentExpressable( expression );
|
||||||
|
for ( SqmCaseSimple.WhenFragment<?, ?> whenFragment : expression.getWhenFragments() ) {
|
||||||
|
withTypeInference(
|
||||||
|
expression.getFixture(),
|
||||||
|
() -> whenFragment.getCheckValue().accept( this )
|
||||||
|
);
|
||||||
|
withTypeInference(
|
||||||
|
resolved == null && inferenceSupplier != null ? inferenceSupplier : resolved,
|
||||||
|
() -> whenFragment.getResult().accept( this )
|
||||||
|
);
|
||||||
|
resolved = highestPrecedence( resolved, whenFragment.getResult() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( expression.getOtherwise() != null ) {
|
||||||
|
withTypeInference(
|
||||||
|
resolved == null && inferenceSupplier != null ? inferenceSupplier : resolved,
|
||||||
|
() -> expression.getOtherwise().accept( this )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object visitSearchedCaseExpression(SqmCaseSearched<?> expression) {
|
||||||
|
final SqmExpressableAccessor<?> inferenceSupplier = this.inferenceBasis;
|
||||||
|
SqmExpressableAccessor<?> resolved = determineCurrentExpressable( expression );
|
||||||
|
|
||||||
|
for ( SqmCaseSearched.WhenFragment<?> whenFragment : expression.getWhenFragments() ) {
|
||||||
|
withTypeInference(
|
||||||
|
null,
|
||||||
|
() -> whenFragment.getPredicate().accept( this )
|
||||||
|
);
|
||||||
|
withTypeInference(
|
||||||
|
resolved == null && inferenceSupplier != null ? inferenceSupplier : resolved,
|
||||||
|
() -> whenFragment.getResult().accept( this )
|
||||||
|
);
|
||||||
|
resolved = highestPrecedence( resolved, whenFragment.getResult() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( expression.getOtherwise() != null ) {
|
||||||
|
withTypeInference(
|
||||||
|
resolved == null && inferenceSupplier != null ? inferenceSupplier : resolved,
|
||||||
|
() -> expression.getOtherwise().accept( this )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmExpressableAccessor<?> highestPrecedence(SqmExpressableAccessor<?> type1, SqmExpressableAccessor<?> type2) {
|
||||||
|
if ( type1 == null ) {
|
||||||
|
return type2;
|
||||||
|
}
|
||||||
|
if ( type2 == null ) {
|
||||||
|
return type1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type1.getExpressable() instanceof AllowableParameterType<?> ) {
|
||||||
|
return type1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type2.getExpressable() instanceof AllowableParameterType<?> ) {
|
||||||
|
return type2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return type1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqmExpressableAccessor<?> determineCurrentExpressable(SqmExpression<?> expression) {
|
||||||
|
if ( expression.getExpressable() instanceof AllowableParameterType<?> ) {
|
||||||
|
return () -> (SqmExpressable<Object>) expression.getExpressable();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object visitIndexedPluralAccessPath(SqmIndexedCollectionAccessPath<?> path) {
|
public Object visitIndexedPluralAccessPath(SqmIndexedCollectionAccessPath<?> path) {
|
||||||
path.getLhs().accept( this );
|
path.getLhs().accept( this );
|
||||||
|
|
Loading…
Reference in New Issue