HHH-18436 Apply plural attribute ordering when creating the join

This commit is contained in:
Marco Belladelli 2024-08-06 13:45:55 +02:00
parent 7e0e2f77d4
commit 29278a7677
5 changed files with 32 additions and 39 deletions

View File

@ -30,7 +30,6 @@ import org.hibernate.metamodel.CollectionClassification;
import org.hibernate.metamodel.mapping.AttributeMapping; import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
@ -963,19 +962,6 @@ public class LoaderSelectBuilder {
creationState creationState
); );
if ( fetch.getTiming() == FetchTiming.IMMEDIATE && joined ) {
if ( isFetchablePluralAttributeMapping ) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) fetchable;
final QuerySpec querySpec = creationState.getInflightQueryPart().getFirstQuerySpec();
applyOrdering(
querySpec,
fetchablePath,
pluralAttributeMapping,
creationState
);
}
}
fetches.add( fetch ); fetches.add( fetch );
} }
finally { finally {
@ -1010,19 +996,6 @@ public class LoaderSelectBuilder {
return true; return true;
} }
private void applyOrdering(
QuerySpec querySpec,
NavigablePath navigablePath,
PluralAttributeMapping pluralAttributeMapping,
LoaderSqlAstCreationState sqlAstCreationState) {
assert pluralAttributeMapping.getAttributeName().equals( navigablePath.getLocalName() );
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup( navigablePath );
assert tableGroup != null;
applyOrdering( querySpec, tableGroup, pluralAttributeMapping, sqlAstCreationState );
}
private SelectStatement generateSelect(SubselectFetch subselect) { private SelectStatement generateSelect(SubselectFetch subselect) {
// todo (6.0) : we could even convert this to a join by piecing together // todo (6.0) : we could even convert this to a join by piecing together

View File

@ -24,6 +24,7 @@ import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.metamodel.mapping.AssociationKey; import org.hibernate.metamodel.mapping.AssociationKey;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
import org.hibernate.query.spi.Limit; import org.hibernate.query.spi.Limit;
import org.hibernate.query.sqm.tree.from.SqmFrom; import org.hibernate.query.sqm.tree.from.SqmFrom;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
@ -41,8 +42,10 @@ import org.hibernate.sql.ast.spi.SqlAstProcessingState;
import org.hibernate.sql.ast.spi.SqlAstQueryPartProcessingState; import org.hibernate.sql.ast.spi.SqlAstQueryPartProcessingState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.FromClause; import org.hibernate.sql.ast.tree.from.FromClause;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QueryPart; import org.hibernate.sql.ast.tree.select.QueryPart;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.internal.ImmutableFetchList; import org.hibernate.sql.results.graph.internal.ImmutableFetchList;
@ -94,6 +97,13 @@ public class LoaderSqlAstCreationState
); );
} }
@Override
public void applyOrdering(TableGroup tableGroup, OrderByFragment orderByFragment) {
final QuerySpec querySpec = getInflightQueryPart().getFirstQuerySpec();
assert querySpec.isRoot() : "Illegal attempt to apply order-by fragment to a non-root query spec";
orderByFragment.apply( querySpec, tableGroup, this );
}
@Override @Override
public SqlAstCreationContext getCreationContext() { public SqlAstCreationContext getCreationContext() {
return sf; return sf;

View File

@ -738,6 +738,16 @@ public class PluralAttributeMappingImpl
creationState creationState
); );
if ( fetched ) {
if ( orderByFragment != null ) {
creationState.applyOrdering( tableGroup, orderByFragment );
}
if ( manyToManyOrderByFragment != null ) {
creationState.applyOrdering( tableGroup, manyToManyOrderByFragment );
}
}
final TableGroupJoin tableGroupJoin = new TableGroupJoin( final TableGroupJoin tableGroupJoin = new TableGroupJoin(
navigablePath, navigablePath,
determineSqlJoinType( lhs, requestedJoinType, fetched ), determineSqlJoinType( lhs, requestedJoinType, fetched ),

View File

@ -8552,14 +8552,6 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
@Override @Override
public ImmutableFetchList visitFetches(FetchParent fetchParent) { public ImmutableFetchList visitFetches(FetchParent fetchParent) {
if ( fetchParent instanceof EagerCollectionFetch && currentQuerySpec().isRoot() ) {
final EagerCollectionFetch collectionFetch = (EagerCollectionFetch) fetchParent;
final PluralAttributeMapping pluralAttributeMapping = collectionFetch.getFetchedMapping();
final NavigablePath fetchablePath = collectionFetch.getNavigablePath();
final TableGroup tableGroup = getFromClauseIndex().getTableGroup( fetchablePath );
assert tableGroup.getModelPart() == pluralAttributeMapping;
applyOrdering( tableGroup, pluralAttributeMapping );
}
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer(); final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();
final int keySize = referencedMappingContainer.getNumberOfKeyFetchables(); final int keySize = referencedMappingContainer.getNumberOfKeyFetchables();
final int size = referencedMappingContainer.getNumberOfFetchables(); final int size = referencedMappingContainer.getNumberOfFetchables();
@ -8646,12 +8638,15 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
} }
private void applyOrdering(TableGroup tableGroup, OrderByFragment orderByFragment) { @Override
public void applyOrdering(TableGroup tableGroup, OrderByFragment orderByFragment) {
if ( currentQuerySpec().isRoot() ) {
if ( orderByFragments == null ) { if ( orderByFragments == null ) {
orderByFragments = new ArrayList<>(); orderByFragments = new ArrayList<>();
} }
orderByFragments.add( new AbstractMap.SimpleEntry<>( orderByFragment, tableGroup ) ); orderByFragments.add( new AbstractMap.SimpleEntry<>( orderByFragment, tableGroup ) );
} }
}
@Override @Override
public <S, M> M resolveMetadata(S source, Function<S, M> producer ) { public <S, M> M resolveMetadata(S source, Function<S, M> producer ) {

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.ast.spi;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
import org.hibernate.persister.entity.EntityNameUse; import org.hibernate.persister.entity.EntityNameUse;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
@ -49,4 +50,8 @@ public interface SqlAstCreationState {
default boolean supportsEntityNameUsage() { default boolean supportsEntityNameUsage() {
return false; return false;
} }
@Internal
default void applyOrdering(TableGroup tableGroup, OrderByFragment orderByFragment) {
}
} }