diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index c87d28915f..496e7a2584 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -886,7 +886,9 @@ public abstract class BaseSqmToSqlAstConverter extends Base .get( versionMapping.getPartName() ), this, this, - jpaQueryComplianceEnabled ).getColumnReferences(); + jpaQueryComplianceEnabled, + Clause.SET + ).getColumnReferences(); assert targetColumnReferences.size() == 1; final ColumnReference versionColumn = targetColumnReferences.get( 0 ); @@ -1331,7 +1333,8 @@ public abstract class BaseSqmToSqlAstConverter extends Base .get( versionAttributeName ), this, this, - jpaQueryComplianceEnabled + jpaQueryComplianceEnabled, + getCurrentClauseStack().getCurrent() ); final List targetColumnReferences = versionPath.getColumnReferences(); assert targetColumnReferences.size() == 1; @@ -3960,7 +3963,8 @@ public abstract class BaseSqmToSqlAstConverter extends Base sqmPath, this, this, - jpaQueryComplianceEnabled + jpaQueryComplianceEnabled, + getCurrentClauseStack().getCurrent() ) ); Expression result = path; @@ -4058,7 +4062,13 @@ public abstract class BaseSqmToSqlAstConverter extends Base return withTreatRestriction( prepareReusablePath( sqmPath, - () -> EmbeddableValuedPathInterpretation.from( sqmPath, this, this, jpaQueryComplianceEnabled ) + () -> EmbeddableValuedPathInterpretation.from( + sqmPath, + this, + this, + jpaQueryComplianceEnabled, + getCurrentClauseStack().getCurrent() + ) ), sqmPath ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java index 8a5292d66f..02f6fd8930 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java @@ -13,18 +13,21 @@ import java.util.function.Consumer; import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.ManagedMappingType; import org.hibernate.metamodel.mapping.ModelPart; +import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.spi.NavigablePath; import org.hibernate.query.SemanticException; import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.StrictJpaComplianceViolation; import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; +import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.spi.FromClauseAccess; import org.hibernate.sql.ast.spi.SqlAstCreationState; -import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression; @@ -43,7 +46,8 @@ public class BasicValuedPathInterpretation extends AbstractSqmPathInterpretat SqmBasicValuedSimplePath sqmPath, SqlAstCreationState sqlAstCreationState, SemanticQueryWalker sqmWalker, - boolean jpaQueryComplianceEnabled) { + boolean jpaQueryComplianceEnabled, + Clause currentClause) { final FromClauseAccess fromClauseAccess = sqlAstCreationState.getFromClauseAccess(); final TableGroup tableGroup = fromClauseAccess.getTableGroup( sqmPath.getNavigablePath().getParent() ); @@ -68,10 +72,24 @@ public class BasicValuedPathInterpretation extends AbstractSqmPathInterpretat } } - final BasicValuedModelPart mapping = (BasicValuedModelPart) tableGroup.getModelPart().findSubPart( - sqmPath.getReferencedPathSource().getPathName(), - treatTarget - ); + final ModelPartContainer modelPart = tableGroup.getModelPart(); + final BasicValuedModelPart mapping; + // In the select, group by, order by and having clause we have to make sure we render the column of the target table, + // never the FK column, if the lhs is a SqmFrom i.e. something explicitly queried/joined. + if ( ( currentClause == Clause.GROUP || currentClause == Clause.SELECT || currentClause == Clause.ORDER || currentClause == Clause.HAVING ) + && sqmPath.getLhs() instanceof SqmFrom + && modelPart.getPartMappingType() instanceof ManagedMappingType ) { + mapping = (BasicValuedModelPart) ( (ManagedMappingType) modelPart.getPartMappingType() ).findSubPart( + sqmPath.getReferencedPathSource().getPathName(), + treatTarget + ); + } + else { + mapping = (BasicValuedModelPart) modelPart.findSubPart( + sqmPath.getReferencedPathSource().getPathName(), + treatTarget + ); + } if ( mapping == null ) { if ( jpaQueryComplianceEnabled ) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EmbeddableValuedPathInterpretation.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EmbeddableValuedPathInterpretation.java index cce2af3bf6..94acf9cd2d 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EmbeddableValuedPathInterpretation.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EmbeddableValuedPathInterpretation.java @@ -13,12 +13,16 @@ import java.util.function.Consumer; import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.ManagedMappingType; +import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.model.domain.EntityDomainType; +import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.spi.NavigablePath; import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; +import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.Expression; @@ -39,7 +43,8 @@ public class EmbeddableValuedPathInterpretation extends AbstractSqmPathInterp SqmEmbeddedValuedSimplePath sqmPath, SqmToSqlAstConverter converter, SemanticQueryWalker sqmWalker, - boolean jpaQueryComplianceEnabled) { + boolean jpaQueryComplianceEnabled, + Clause currentClause) { TableGroup tableGroup = converter.getFromClauseAccess().findTableGroup( sqmPath.getLhs().getNavigablePath() ); EntityMappingType treatTarget = null; @@ -61,10 +66,24 @@ public class EmbeddableValuedPathInterpretation extends AbstractSqmPathInterp } } - final EmbeddableValuedModelPart mapping = (EmbeddableValuedModelPart) tableGroup.getModelPart().findSubPart( - sqmPath.getReferencedPathSource().getPathName(), - treatTarget - ); + final ModelPartContainer modelPart = tableGroup.getModelPart(); + final EmbeddableValuedModelPart mapping; + // In the select, group by, order by and having clause we have to make sure we render the column of the target table, + // never the FK column, if the lhs is a SqmFrom i.e. something explicitly queried/joined. + if ( ( currentClause == Clause.GROUP || currentClause == Clause.SELECT || currentClause == Clause.ORDER || currentClause == Clause.HAVING ) + && sqmPath.getLhs() instanceof SqmFrom + && modelPart.getPartMappingType() instanceof ManagedMappingType ) { + mapping = (EmbeddableValuedModelPart) ( (ManagedMappingType) modelPart.getPartMappingType() ).findSubPart( + sqmPath.getReferencedPathSource().getPathName(), + treatTarget + ); + } + else { + mapping = (EmbeddableValuedModelPart) modelPart.findSubPart( + sqmPath.getReferencedPathSource().getPathName(), + treatTarget + ); + } return new EmbeddableValuedPathInterpretation<>( mapping.toSqlExpression(