HHH-16189 Wrong order by and group by generated

This commit is contained in:
Andrea Boriero 2023-03-13 16:05:17 +01:00 committed by Christian Beikov
parent fad16b6b1c
commit 875e506552
3 changed files with 62 additions and 15 deletions

View File

@ -886,7 +886,9 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> 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<T extends Statement> extends Base
.get( versionAttributeName ),
this,
this,
jpaQueryComplianceEnabled
jpaQueryComplianceEnabled,
getCurrentClauseStack().getCurrent()
);
final List<ColumnReference> targetColumnReferences = versionPath.getColumnReferences();
assert targetColumnReferences.size() == 1;
@ -3960,7 +3963,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
sqmPath,
this,
this,
jpaQueryComplianceEnabled
jpaQueryComplianceEnabled,
getCurrentClauseStack().getCurrent()
)
);
Expression result = path;
@ -4058,7 +4062,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return withTreatRestriction(
prepareReusablePath(
sqmPath,
() -> EmbeddableValuedPathInterpretation.from( sqmPath, this, this, jpaQueryComplianceEnabled )
() -> EmbeddableValuedPathInterpretation.from(
sqmPath,
this,
this,
jpaQueryComplianceEnabled,
getCurrentClauseStack().getCurrent()
)
),
sqmPath
);

View File

@ -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<T> extends AbstractSqmPathInterpretat
SqmBasicValuedSimplePath<T> 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<T> 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 ) {

View File

@ -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<T> extends AbstractSqmPathInterp
SqmEmbeddedValuedSimplePath<T> 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<T> 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(