HHH-15718 Polymorphic queries with condition do not work

This commit is contained in:
Andrea Boriero 2022-11-22 14:25:36 +01:00 committed by Andrea Boriero
parent a65579e268
commit 6f0a631917
2 changed files with 42 additions and 19 deletions

View File

@ -91,7 +91,6 @@ import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import jakarta.persistence.criteria.AbstractQuery; import jakarta.persistence.criteria.AbstractQuery;
import jakarta.persistence.criteria.CriteriaQuery;
/** /**
* Handles splitting queries containing unmapped polymorphic references. * Handles splitting queries containing unmapped polymorphic references.
@ -710,12 +709,15 @@ public class QuerySplitter {
public SqmBasicValuedSimplePath<?> visitBasicValuedPath(SqmBasicValuedSimplePath<?> path) { public SqmBasicValuedSimplePath<?> visitBasicValuedPath(SqmBasicValuedSimplePath<?> path) {
final SqmPathRegistry pathRegistry = getProcessingStateStack().getCurrent().getPathRegistry(); final SqmPathRegistry pathRegistry = getProcessingStateStack().getCurrent().getPathRegistry();
final SqmPath<?> lhs = findLhs( path, pathRegistry );
final SqmBasicValuedSimplePath<?> copy = new SqmBasicValuedSimplePath<>( final SqmBasicValuedSimplePath<?> copy = new SqmBasicValuedSimplePath<>(
path.getNavigablePath(), lhs.getNavigablePath().append( path.getNavigablePath().getLocalName() ),
path.getReferencedPathSource(), path.getReferencedPathSource(),
pathRegistry.findFromByPath( path.getLhs().getNavigablePath() ), lhs,
path.nodeBuilder() path.nodeBuilder()
); );
pathRegistry.register( copy ); pathRegistry.register( copy );
sqmPathCopyMap.put( path.getNavigablePath(), copy ); sqmPathCopyMap.put( path.getNavigablePath(), copy );
return copy; return copy;
@ -724,10 +726,11 @@ public class QuerySplitter {
@Override @Override
public SqmEmbeddedValuedSimplePath<?> visitEmbeddableValuedPath(SqmEmbeddedValuedSimplePath<?> path) { public SqmEmbeddedValuedSimplePath<?> visitEmbeddableValuedPath(SqmEmbeddedValuedSimplePath<?> path) {
final SqmPathRegistry pathRegistry = getProcessingStateStack().getCurrent().getPathRegistry(); final SqmPathRegistry pathRegistry = getProcessingStateStack().getCurrent().getPathRegistry();
final SqmPath<?> lhs = findLhs( path, pathRegistry );
final SqmEmbeddedValuedSimplePath<?> copy = new SqmEmbeddedValuedSimplePath<>( final SqmEmbeddedValuedSimplePath<?> copy = new SqmEmbeddedValuedSimplePath<>(
path.getNavigablePath(), lhs.getNavigablePath().append( path.getNavigablePath().getLocalName() ),
path.getReferencedPathSource(), path.getReferencedPathSource(),
pathRegistry.findFromByPath( path.getLhs().getNavigablePath() ), lhs,
path.nodeBuilder() path.nodeBuilder()
); );
pathRegistry.register( copy ); pathRegistry.register( copy );
@ -738,10 +741,11 @@ public class QuerySplitter {
@Override @Override
public SqmEntityValuedSimplePath<?> visitEntityValuedPath(SqmEntityValuedSimplePath<?> path) { public SqmEntityValuedSimplePath<?> visitEntityValuedPath(SqmEntityValuedSimplePath<?> path) {
final SqmPathRegistry pathRegistry = getProcessingStateStack().getCurrent().getPathRegistry(); final SqmPathRegistry pathRegistry = getProcessingStateStack().getCurrent().getPathRegistry();
final SqmPath<?> lhs = findLhs( path, pathRegistry );
final SqmEntityValuedSimplePath<?> copy = new SqmEntityValuedSimplePath<>( final SqmEntityValuedSimplePath<?> copy = new SqmEntityValuedSimplePath<>(
path.getNavigablePath(), lhs.getNavigablePath().append( path.getNavigablePath().getLocalName() ),
path.getReferencedPathSource(), path.getReferencedPathSource(),
pathRegistry.findFromByPath( path.getLhs().getNavigablePath() ), lhs,
path.nodeBuilder() path.nodeBuilder()
); );
pathRegistry.register( copy ); pathRegistry.register( copy );
@ -752,10 +756,12 @@ public class QuerySplitter {
@Override @Override
public SqmPluralValuedSimplePath<?> visitPluralValuedPath(SqmPluralValuedSimplePath<?> path) { public SqmPluralValuedSimplePath<?> visitPluralValuedPath(SqmPluralValuedSimplePath<?> path) {
final SqmPathRegistry pathRegistry = getProcessingStateStack().getCurrent().getPathRegistry(); final SqmPathRegistry pathRegistry = getProcessingStateStack().getCurrent().getPathRegistry();
SqmPath<?> lhs = findLhs( path, pathRegistry );
final SqmPluralValuedSimplePath<?> copy = new SqmPluralValuedSimplePath<>( final SqmPluralValuedSimplePath<?> copy = new SqmPluralValuedSimplePath<>(
path.getNavigablePath(), path.getNavigablePath(),
path.getReferencedPathSource(), path.getReferencedPathSource(),
pathRegistry.findFromByPath( path.getLhs().getNavigablePath() ), lhs,
path.nodeBuilder() path.nodeBuilder()
); );
pathRegistry.register( copy ); pathRegistry.register( copy );
@ -763,13 +769,25 @@ public class QuerySplitter {
return copy; return copy;
} }
private SqmPath<?> findLhs(SqmPath<?> path, SqmPathRegistry pathRegistry) {
final SqmPath<?> lhs = path.getLhs();
final SqmPath sqmFrom = sqmPathCopyMap.get( lhs.getNavigablePath() );
if ( sqmFrom != null ) {
return pathRegistry.findFromByPath( sqmFrom.getNavigablePath() );
}
else {
return (SqmPath<?>) lhs.accept( this );
}
}
@Override @Override
public SqmSelectClause visitSelectClause(SqmSelectClause selectClause) { public SqmSelectClause visitSelectClause(SqmSelectClause selectClause) {
SqmSelectClause copy = new SqmSelectClause( selectClause.isDistinct(), selectClause.nodeBuilder() ); SqmSelectClause copy = new SqmSelectClause( selectClause.isDistinct(), selectClause.nodeBuilder() );
for ( SqmSelection<?> selection : selectClause.getSelections() ) { for ( SqmSelection<?> selection : selectClause.getSelections() ) {
SqmExpression<?> selectableNode = (SqmExpression<?>) selection.getSelectableNode().accept( this );
copy.addSelection( copy.addSelection(
new SqmSelection<>( new SqmSelection<>(
(SqmExpression<?>) selection.getSelectableNode().accept( this ), selectableNode,
selection.getAlias(), selection.getAlias(),
selectClause.nodeBuilder() selectClause.nodeBuilder()
) )

View File

@ -74,27 +74,32 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
final List<EntityDomainType<?>> subList = implementorsList.subList( 1, implementors.size() - 1 ); final List<EntityDomainType<?>> subList = implementorsList.subList( 1, implementors.size() - 1 );
firstImplementor.visitAttributes( firstImplementor.visitAttributes(
attribute -> { attribute -> {
// for each of its attributes, check whether the other implementors also expose it if ( isACommonAttribute( subList, attribute ) ) {
for ( EntityDomainType navigable : subList ) { // if isACommonAttribute - they all had it. so put it in the workMap
if ( navigable.findAttribute( attribute.getName() ) == null ) {
// we found an implementor that does not expose that attribute,
// so break-out to the next attribute
break;
}
// if we get here - they all had it. so put it in the workMap
// //
// todo (6.0) : Atm We use the attribute from the first implementor directly for each implementor // todo (6.0) : Atm We use the attribute from the first implementor directly for each implementor
// need to handle this in QuerySplitter somehow // need to handle this in QuerySplitter somehow
workMap.put( attribute.getName(), attribute ); workMap.put( attribute.getName(), attribute );
} }
} }
); );
} }
this.commonAttributes = Collections.unmodifiableMap( workMap ); this.commonAttributes = Collections.unmodifiableMap( workMap );
} }
private static boolean isACommonAttribute(List<EntityDomainType<?>> subList, PersistentAttribute<?, ?> attribute) {
// for each of its attributes, check whether the other implementors also expose it
for ( EntityDomainType navigable : subList ) {
if ( navigable.findAttribute( attribute.getName() ) != null ) {
// we found an implementor that does not expose that attribute,
// so break-out to the next attribute
return false;
}
}
return true;
}
public Set<EntityDomainType<?>> getImplementors() { public Set<EntityDomainType<?>> getImplementors() {
return new HashSet<>( implementors ); return new HashSet<>( implementors );
} }