Support implicit joins in plural path parts and fix issues with type resolving of sub query paths

This commit is contained in:
Christian Beikov 2022-02-21 16:07:41 +01:00
parent 247689824f
commit 277f10d987
4 changed files with 26 additions and 35 deletions

View File

@ -3871,8 +3871,19 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
); );
final SqmSelectClause selectClause = new SqmSelectClause( false, 1, creationContext.getNodeBuilder() ); final SqmSelectClause selectClause = new SqmSelectClause( false, 1, creationContext.getNodeBuilder() );
final SqmFromClause fromClause = new SqmFromClause( 1 ); final SqmFromClause fromClause = new SqmFromClause( 1 );
final SqmCorrelation<?, ?> correlation = ( (AbstractSqmFrom<?, ?>) pluralAttributePath.getLhs() ).createCorrelation(); SqmPath<?> lhs = pluralAttributePath.getLhs();
final SqmAttributeJoin<?, ?> collectionJoin = correlation.join( pluralAttributePath.getNavigablePath().getUnaliasedLocalName() ); final List<String> implicitJoinPaths = new ArrayList<>();
while ( !( lhs instanceof AbstractSqmFrom<?, ?> ) ) {
implicitJoinPaths.add( lhs.getNavigablePath().getUnaliasedLocalName() );
lhs = lhs.getLhs();
}
final AbstractSqmFrom<?, ?> correlationBase = (AbstractSqmFrom<?, ?>) lhs;
final SqmCorrelation<?, ?> correlation = correlationBase.createCorrelation();
SqmFrom<?, ?> joinBase = correlation;
for ( int i = implicitJoinPaths.size() - 1; i >= 0; i-- ) {
joinBase = joinBase.join( implicitJoinPaths.get( i ) );
}
final SqmAttributeJoin<?, ?> collectionJoin = joinBase.join( pluralAttributePath.getNavigablePath().getUnaliasedLocalName() );
fromClause.addRoot( correlation.getCorrelatedRoot() ); fromClause.addRoot( correlation.getCorrelatedRoot() );
if ( collectionReferenceCtx == null ) { if ( collectionReferenceCtx == null ) {
final SqmLiteral<Integer> literal = new SqmLiteral<>( final SqmLiteral<Integer> literal = new SqmLiteral<>(

View File

@ -185,7 +185,14 @@ public class SqmMappingModelHelper {
return domainModel.findEntityDescriptor( entityDomainType.getHibernateEntityName() ); return domainModel.findEntityDescriptor( entityDomainType.getHibernateEntityName() );
} }
final TableGroup lhsTableGroup = tableGroupLocator.apply( sqmPath.getLhs().getNavigablePath() ); final TableGroup lhsTableGroup = tableGroupLocator.apply( sqmPath.getLhs().getNavigablePath() );
return lhsTableGroup.getModelPart().findSubPart( sqmPath.getReferencedPathSource().getPathName(), null ); final ModelPartContainer modelPart;
if ( lhsTableGroup == null ) {
modelPart = (ModelPartContainer) resolveSqmPath( sqmPath.getLhs(), domainModel, tableGroupLocator );
}
else {
modelPart = lhsTableGroup.getModelPart();
}
return modelPart.findSubPart( sqmPath.getReferencedPathSource().getPathName(), null );
} }
public static EntityMappingType resolveExplicitTreatTarget( public static EntityMappingType resolveExplicitTreatTarget(

View File

@ -4555,7 +4555,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
else if ( sqmExpression instanceof SqmPath ) { else if ( sqmExpression instanceof SqmPath ) {
log.debugf( "Determining mapping-model type for SqmPath : %s ", sqmExpression ); log.debugf( "Determining mapping-model type for SqmPath : %s ", sqmExpression );
prepareReusablePath( (SqmPath<?>) sqmExpression, fromClauseIndex, () -> null );
final MappingMetamodel domainModel = creationContext.getSessionFactory() final MappingMetamodel domainModel = creationContext.getSessionFactory()
.getRuntimeMetamodels() .getRuntimeMetamodels()
.getMappingMetamodel(); .getMappingMetamodel();
@ -4577,40 +4576,16 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final SqmSelectClause selectClause = subQuery.getQuerySpec().getSelectClause(); final SqmSelectClause selectClause = subQuery.getQuerySpec().getSelectClause();
if ( selectClause.getSelections().size() == 1 ) { if ( selectClause.getSelections().size() == 1 ) {
final SqmSelection<?> subQuerySelection = selectClause.getSelections().get( 0 ); final SqmSelection<?> subQuerySelection = selectClause.getSelections().get( 0 );
final SqmSelectableNode<?> selectableNode = subQuerySelection.getSelectableNode();
if ( selectableNode instanceof SqmExpression<?> ) {
return determineValueMapping( (SqmExpression<?>) selectableNode, fromClauseIndex );
}
final SqmExpressible<?> selectionNodeType = subQuerySelection.getNodeType(); final SqmExpressible<?> selectionNodeType = subQuerySelection.getNodeType();
if ( selectionNodeType != null ) { if ( selectionNodeType != null ) {
final SqmExpressible<?> sqmExpressible;
if ( selectionNodeType instanceof PluralPersistentAttribute ) {
sqmExpressible = ( (PluralPersistentAttribute<?,?,?>) selectionNodeType ).getElementPathSource();
}
else if ( selectionNodeType instanceof SqmPathSource<?>) {
final SqmPathSource<?> pathSource = (SqmPathSource<?>) selectionNodeType;
final CollectionPart.Nature partNature = CollectionPart.Nature.fromName(
pathSource.getPathName()
);
if ( partNature == null ) {
sqmExpressible = selectionNodeType;
}
else {
final SqmPath<?> sqmPath = (SqmPath<?>) subQuerySelection.getSelectableNode();
final NavigablePath navigablePath = sqmPath.getNavigablePath().getParent();
if ( navigablePath.getParent() != null ) {
final TableGroup parentTableGroup = fromClauseIndex.findTableGroup( navigablePath.getParent() );
final PluralAttributeMapping pluralPart = (PluralAttributeMapping) parentTableGroup.getModelPart()
.findSubPart( navigablePath.getUnaliasedLocalName(), null );
return pluralPart.findSubPart( pathSource.getPathName(), null );
}
return fromClauseIndex.findTableGroup( navigablePath ).getModelPart();
}
}
else {
sqmExpressible = selectionNodeType;
}
final MappingMetamodel domainModel = creationContext.getSessionFactory() final MappingMetamodel domainModel = creationContext.getSessionFactory()
.getRuntimeMetamodels() .getRuntimeMetamodels()
.getMappingMetamodel(); .getMappingMetamodel();
final MappingModelExpressible<?> expressible = domainModel.resolveMappingExpressible(sqmExpressible, this::findTableGroupByPath ); final MappingModelExpressible<?> expressible = domainModel.resolveMappingExpressible(selectionNodeType, this::findTableGroupByPath );
if ( expressible != null ) { if ( expressible != null ) {
return expressible; return expressible;

View File

@ -9,7 +9,6 @@ package org.hibernate.orm.test.mapping.collections.mapcompelem;
import java.util.List; import java.util.List;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.NotImplementedYet;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -61,7 +60,6 @@ public class MapCompositeElementTest {
@SuppressWarnings( {"unchecked"}) @SuppressWarnings( {"unchecked"})
@Test @Test
@NotImplementedYet( strict = false )
public void testQueryMapCompositeElement(SessionFactoryScope scope) { public void testQueryMapCompositeElement(SessionFactoryScope scope) {
scope.inTransaction( (s) -> { scope.inTransaction( (s) -> {
Part top = new Part("top", "The top part"); Part top = new Part("top", "The top part");