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.SqmJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
||||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
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.SqmOrderByClause;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmQueryGroup;
|
import org.hibernate.query.sqm.tree.select.SqmQueryGroup;
|
||||||
import org.hibernate.query.sqm.tree.select.SqmQueryPart;
|
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 java.util.stream.Collectors.toList;
|
||||||
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
|
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;
|
import static org.hibernate.query.sqm.tree.jpa.ParameterCollector.collectParameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -232,6 +234,15 @@ public class SqmUtil {
|
||||||
return false;
|
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) {
|
public static List<NavigablePath> getGroupByNavigablePaths(SqmQuerySpec<?> querySpec) {
|
||||||
final List<SqmExpression<?>> expressions = querySpec.getGroupByClauseExpressions();
|
final List<SqmExpression<?>> expressions = querySpec.getGroupByClauseExpressions();
|
||||||
if ( expressions.isEmpty() ) {
|
if ( expressions.isEmpty() ) {
|
||||||
|
@ -255,7 +266,7 @@ public class SqmUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<NavigablePath> collectNavigablePaths(final List<SqmExpression<?>> expressions) {
|
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() ) );
|
final SqmPathVisitor pathVisitor = new SqmPathVisitor( path -> navigablePaths.add( path.getNavigablePath() ) );
|
||||||
for ( final SqmExpression<?> expression : expressions ) {
|
for ( final SqmExpression<?> expression : expressions ) {
|
||||||
if ( expression instanceof SqmAliasedNodeRef ) {
|
if ( expression instanceof SqmAliasedNodeRef ) {
|
||||||
|
|
|
@ -8406,7 +8406,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
joinProducer,
|
joinProducer,
|
||||||
joinProducer.determineSqlJoinType( lhs, null, true )
|
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(
|
final TableGroupJoin tableGroupJoin = joinProducer.createTableGroupJoin(
|
||||||
fetchablePath,
|
fetchablePath,
|
||||||
lhs,
|
lhs,
|
||||||
|
|
|
@ -629,15 +629,26 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
super.appendHqlString( sb );
|
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
|
@Internal
|
||||||
public boolean groupByClauseContains(NavigablePath navigablePath, SqmToSqlAstConverter sqlAstConverter) {
|
public boolean groupByClauseContains(NavigablePath navigablePath, SqmToSqlAstConverter sqlAstConverter) {
|
||||||
if ( groupByClauseExpressions.isEmpty() ) {
|
if ( groupByClauseExpressions.isEmpty() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return navigablePathsContain( sqlAstConverter.resolveMetadata(
|
return isSameOrChildren(
|
||||||
this,
|
navigablePath,
|
||||||
SqmUtil::getGroupByNavigablePaths
|
sqlAstConverter.resolveMetadata( this, SqmUtil::getGroupByNavigablePaths )
|
||||||
), navigablePath );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Internal
|
@Internal
|
||||||
|
@ -646,13 +657,13 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
if ( orderByClause == null || orderByClause.getSortSpecifications().isEmpty() ) {
|
if ( orderByClause == null || orderByClause.getSortSpecifications().isEmpty() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return navigablePathsContain( sqlAstConverter.resolveMetadata(
|
return isSameOrChildren(
|
||||||
this,
|
navigablePath,
|
||||||
SqmUtil::getOrderByNavigablePaths
|
sqlAstConverter.resolveMetadata( this, SqmUtil::getOrderByNavigablePaths )
|
||||||
), navigablePath );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean navigablePathsContain(List<NavigablePath> navigablePaths, NavigablePath navigablePath) {
|
private boolean isSameOrChildren(NavigablePath navigablePath, List<NavigablePath> navigablePaths) {
|
||||||
for ( NavigablePath path : navigablePaths ) {
|
for ( NavigablePath path : navigablePaths ) {
|
||||||
if ( path.isParentOrEqual( navigablePath ) ) {
|
if ( path.isParentOrEqual( navigablePath ) ) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -660,4 +671,13 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
}
|
}
|
||||||
return false;
|
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