HHH-18378 Check where clause before reusing existing joins for fetch
This commit is contained in:
parent
0272fc7fbd
commit
4da2659292
|
@ -74,6 +74,7 @@ import org.hibernate.query.sqm.tree.from.SqmFrom;
|
|||
import org.hibernate.query.sqm.tree.from.SqmJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmOrderByClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmQueryGroup;
|
||||
import org.hibernate.query.sqm.tree.select.SqmQueryPart;
|
||||
|
@ -105,6 +106,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||
import static org.hibernate.query.sqm.tree.jpa.ParameterCollector.collectParameters;
|
||||
|
||||
/**
|
||||
|
@ -232,6 +234,15 @@ public class SqmUtil {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static List<NavigablePath> getWhereClauseNavigablePaths(SqmQuerySpec<?> querySpec) {
|
||||
final SqmWhereClause where = querySpec.getWhereClause();
|
||||
if ( where == null || where.getPredicate() == null ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return collectNavigablePaths( List.of( where.getPredicate() ) );
|
||||
}
|
||||
|
||||
public static List<NavigablePath> getGroupByNavigablePaths(SqmQuerySpec<?> querySpec) {
|
||||
final List<SqmExpression<?>> expressions = querySpec.getGroupByClauseExpressions();
|
||||
if ( expressions.isEmpty() ) {
|
||||
|
@ -255,7 +266,7 @@ public class SqmUtil {
|
|||
}
|
||||
|
||||
private static List<NavigablePath> collectNavigablePaths(final List<SqmExpression<?>> expressions) {
|
||||
final List<NavigablePath> navigablePaths = new ArrayList<>( expressions.size() );
|
||||
final List<NavigablePath> navigablePaths = arrayList( expressions.size() );
|
||||
final SqmPathVisitor pathVisitor = new SqmPathVisitor( path -> navigablePaths.add( path.getNavigablePath() ) );
|
||||
for ( final SqmExpression<?> expression : expressions ) {
|
||||
if ( expression instanceof SqmAliasedNodeRef ) {
|
||||
|
|
|
@ -8406,7 +8406,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
joinProducer,
|
||||
joinProducer.determineSqlJoinType( lhs, null, true )
|
||||
);
|
||||
if ( compatibleTableGroup == null ) {
|
||||
final SqmQueryPart<?> queryPart = getCurrentSqmQueryPart();
|
||||
if ( compatibleTableGroup == null
|
||||
// If the compatible table group is used in the where clause it cannot be reused for fetching
|
||||
|| ( queryPart != null && queryPart.getFirstQuerySpec().whereClauseContains( compatibleTableGroup.getNavigablePath(), this ) ) ) {
|
||||
final TableGroupJoin tableGroupJoin = joinProducer.createTableGroupJoin(
|
||||
fetchablePath,
|
||||
lhs,
|
||||
|
|
|
@ -629,15 +629,26 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
|||
super.appendHqlString( sb );
|
||||
}
|
||||
|
||||
@Internal
|
||||
public boolean whereClauseContains(NavigablePath navigablePath, SqmToSqlAstConverter sqlAstConverter) {
|
||||
if ( whereClause == null ) {
|
||||
return false;
|
||||
}
|
||||
return isSameOrParent(
|
||||
navigablePath,
|
||||
sqlAstConverter.resolveMetadata( this, SqmUtil::getWhereClauseNavigablePaths )
|
||||
);
|
||||
}
|
||||
|
||||
@Internal
|
||||
public boolean groupByClauseContains(NavigablePath navigablePath, SqmToSqlAstConverter sqlAstConverter) {
|
||||
if ( groupByClauseExpressions.isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
return navigablePathsContain( sqlAstConverter.resolveMetadata(
|
||||
this,
|
||||
SqmUtil::getGroupByNavigablePaths
|
||||
), navigablePath );
|
||||
return isSameOrChildren(
|
||||
navigablePath,
|
||||
sqlAstConverter.resolveMetadata( this, SqmUtil::getGroupByNavigablePaths )
|
||||
);
|
||||
}
|
||||
|
||||
@Internal
|
||||
|
@ -646,13 +657,13 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
|||
if ( orderByClause == null || orderByClause.getSortSpecifications().isEmpty() ) {
|
||||
return false;
|
||||
}
|
||||
return navigablePathsContain( sqlAstConverter.resolveMetadata(
|
||||
this,
|
||||
SqmUtil::getOrderByNavigablePaths
|
||||
), navigablePath );
|
||||
return isSameOrChildren(
|
||||
navigablePath,
|
||||
sqlAstConverter.resolveMetadata( this, SqmUtil::getOrderByNavigablePaths )
|
||||
);
|
||||
}
|
||||
|
||||
private boolean navigablePathsContain(List<NavigablePath> navigablePaths, NavigablePath navigablePath) {
|
||||
private boolean isSameOrChildren(NavigablePath navigablePath, List<NavigablePath> navigablePaths) {
|
||||
for ( NavigablePath path : navigablePaths ) {
|
||||
if ( path.isParentOrEqual( navigablePath ) ) {
|
||||
return true;
|
||||
|
@ -660,4 +671,13 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isSameOrParent(NavigablePath navigablePath, List<NavigablePath> navigablePaths) {
|
||||
for ( NavigablePath path : navigablePaths ) {
|
||||
if ( navigablePath.isParentOrEqual( path ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue