HHH-15718 Polymorphic queries with condition do not work
This commit is contained in:
parent
a65579e268
commit
6f0a631917
|
@ -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()
|
||||||
)
|
)
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue