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 75d1f36ded
commit 664b10abc3
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() ), .get( versionMapping.getPartName() ),
this, this,
this, this,
jpaQueryComplianceEnabled ).getColumnReferences(); jpaQueryComplianceEnabled,
Clause.SET
).getColumnReferences();
assert targetColumnReferences.size() == 1; assert targetColumnReferences.size() == 1;
final ColumnReference versionColumn = targetColumnReferences.get( 0 ); final ColumnReference versionColumn = targetColumnReferences.get( 0 );
@ -1331,7 +1333,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
.get( versionAttributeName ), .get( versionAttributeName ),
this, this,
this, this,
jpaQueryComplianceEnabled jpaQueryComplianceEnabled,
getCurrentClauseStack().getCurrent()
); );
final List<ColumnReference> targetColumnReferences = versionPath.getColumnReferences(); final List<ColumnReference> targetColumnReferences = versionPath.getColumnReferences();
assert targetColumnReferences.size() == 1; assert targetColumnReferences.size() == 1;
@ -3960,7 +3963,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
sqmPath, sqmPath,
this, this,
this, this,
jpaQueryComplianceEnabled jpaQueryComplianceEnabled,
getCurrentClauseStack().getCurrent()
) )
); );
Expression result = path; Expression result = path;
@ -4058,7 +4062,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return withTreatRestriction( return withTreatRestriction(
prepareReusablePath( prepareReusablePath(
sqmPath, sqmPath,
() -> EmbeddableValuedPathInterpretation.from( sqmPath, this, this, jpaQueryComplianceEnabled ) () -> EmbeddableValuedPathInterpretation.from(
sqmPath,
this,
this,
jpaQueryComplianceEnabled,
getCurrentClauseStack().getCurrent()
)
), ),
sqmPath sqmPath
); );

View File

@ -13,18 +13,21 @@ import java.util.function.Consumer;
import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.StrictJpaComplianceViolation; import org.hibernate.query.sqm.StrictJpaComplianceViolation;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; 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.SqlAstWalker;
import org.hibernate.sql.ast.spi.FromClauseAccess; import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAstCreationState; 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.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression; import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
@ -43,7 +46,8 @@ public class BasicValuedPathInterpretation<T> extends AbstractSqmPathInterpretat
SqmBasicValuedSimplePath<T> sqmPath, SqmBasicValuedSimplePath<T> sqmPath,
SqlAstCreationState sqlAstCreationState, SqlAstCreationState sqlAstCreationState,
SemanticQueryWalker sqmWalker, SemanticQueryWalker sqmWalker,
boolean jpaQueryComplianceEnabled) { boolean jpaQueryComplianceEnabled,
Clause currentClause) {
final FromClauseAccess fromClauseAccess = sqlAstCreationState.getFromClauseAccess(); final FromClauseAccess fromClauseAccess = sqlAstCreationState.getFromClauseAccess();
final TableGroup tableGroup = fromClauseAccess.getTableGroup( sqmPath.getNavigablePath().getParent() ); 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( final ModelPartContainer modelPart = tableGroup.getModelPart();
sqmPath.getReferencedPathSource().getPathName(), final BasicValuedModelPart mapping;
treatTarget // 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 ( mapping == null ) {
if ( jpaQueryComplianceEnabled ) { if ( jpaQueryComplianceEnabled ) {

View File

@ -13,12 +13,16 @@ import java.util.function.Consumer;
import org.hibernate.metamodel.MappingMetamodel; import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType; 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.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath; 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.SqlAstWalker;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
@ -39,7 +43,8 @@ public class EmbeddableValuedPathInterpretation<T> extends AbstractSqmPathInterp
SqmEmbeddedValuedSimplePath<T> sqmPath, SqmEmbeddedValuedSimplePath<T> sqmPath,
SqmToSqlAstConverter converter, SqmToSqlAstConverter converter,
SemanticQueryWalker<?> sqmWalker, SemanticQueryWalker<?> sqmWalker,
boolean jpaQueryComplianceEnabled) { boolean jpaQueryComplianceEnabled,
Clause currentClause) {
TableGroup tableGroup = converter.getFromClauseAccess().findTableGroup( sqmPath.getLhs().getNavigablePath() ); TableGroup tableGroup = converter.getFromClauseAccess().findTableGroup( sqmPath.getLhs().getNavigablePath() );
EntityMappingType treatTarget = null; EntityMappingType treatTarget = null;
@ -61,10 +66,24 @@ public class EmbeddableValuedPathInterpretation<T> extends AbstractSqmPathInterp
} }
} }
final EmbeddableValuedModelPart mapping = (EmbeddableValuedModelPart) tableGroup.getModelPart().findSubPart( final ModelPartContainer modelPart = tableGroup.getModelPart();
sqmPath.getReferencedPathSource().getPathName(), final EmbeddableValuedModelPart mapping;
treatTarget // 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<>( return new EmbeddableValuedPathInterpretation<>(
mapping.toSqlExpression( mapping.toSqlExpression(