Skip to content

Commit b3e2778

Browse files
committed
fix bug in query plan cache where fetch profiles were not considered
1 parent ba0221d commit b3e2778

File tree

1 file changed

+40
-48
lines changed

1 file changed

+40
-48
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmInterpretationsKey.java

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77
package org.hibernate.query.sqm.internal;
88

9+
import java.util.Collection;
10+
import java.util.HashSet;
911
import java.util.function.Supplier;
1012

1113
import org.hibernate.LockOptions;
@@ -16,6 +18,7 @@
1618
import org.hibernate.query.spi.QueryOptions;
1719

1820
import static java.lang.Boolean.TRUE;
21+
import static org.hibernate.query.spi.AbstractSelectionQuery.CRITERIA_HQL_STRING;
1922

2023
/**
2124
* @author Steve Ebersole
@@ -33,49 +36,39 @@ public interface InterpretationsKeySource extends CacheabilityInfluencers {
3336
}
3437

3538
public static SqmInterpretationsKey createInterpretationsKey(InterpretationsKeySource keySource) {
36-
if ( ! isCacheable( keySource ) ) {
39+
if ( isCacheable (keySource ) ) {
40+
return new SqmInterpretationsKey(
41+
keySource.getQueryString(),
42+
keySource.getResultType(),
43+
keySource.getQueryOptions().getLockOptions(),
44+
keySource.getQueryOptions().getTupleTransformer(),
45+
keySource.getQueryOptions().getResultListTransformer(),
46+
new HashSet<>( keySource.getLoadQueryInfluencers().getEnabledFetchProfileNames() )
47+
);
48+
}
49+
else {
3750
return null;
3851
}
39-
40-
return new SqmInterpretationsKey(
41-
keySource.getQueryString(),
42-
keySource.getResultType(),
43-
keySource.getQueryOptions().getLockOptions(),
44-
keySource.getQueryOptions().getTupleTransformer(),
45-
keySource.getQueryOptions().getResultListTransformer()
46-
);
4752
}
48-
@SuppressWarnings("RedundantIfStatement")
53+
4954
private static boolean isCacheable(InterpretationsKeySource keySource) {
5055
assert keySource.getQueryOptions().getAppliedGraph() != null;
5156

52-
if ( QuerySqmImpl.CRITERIA_HQL_STRING.equals( keySource.getQueryString() ) ) {
53-
// for now at least, skip caching Criteria-based plans
54-
// - especially wrt parameters atm; this works with HQL because the parameters
55-
// are part of the query string; with Criteria, they are not.
56-
return false;
57-
}
58-
59-
if ( keySource.getLoadQueryInfluencers().hasEnabledFilters() ) {
60-
// At the moment we cannot cache query plan if there is filter enabled.
61-
return false;
62-
}
63-
64-
if ( keySource.getQueryOptions().getAppliedGraph().getSemantic() != null ) {
65-
// At the moment we cannot cache query plan if there is an
66-
// EntityGraph enabled.
67-
return false;
68-
}
69-
70-
if ( keySource.hasMultiValuedParameterBindingsChecker().get() == TRUE ) {
71-
// todo (6.0) : this one may be ok because of how I implemented multi-valued param handling
72-
// - the expansion is done per-execution based on the "static" SQM
73-
// - Note from Christian: The call to domainParameterXref.clearExpansions() in ConcreteSqmSelectQueryPlan is a concurrency issue when cached
74-
// - This could be solved by using a method-local clone of domainParameterXref when multi-valued params exist
75-
return false;
76-
}
77-
78-
return true;
57+
// for now at least, skip caching Criteria-based plans
58+
// - especially wrt parameters atm; this works with HQL because the
59+
// parameters are part of the query string; with Criteria, they're not.
60+
return ! CRITERIA_HQL_STRING.equals( keySource.getQueryString() )
61+
// At the moment we cannot cache query plan if there is filter enabled.
62+
&& ! keySource.getLoadQueryInfluencers().hasEnabledFilters()
63+
// At the moment we cannot cache query plan if it has an entity graph
64+
&& keySource.getQueryOptions().getAppliedGraph().getSemantic() == null
65+
// todo (6.0) : this one may be ok because of how I implemented multi-valued param handling
66+
// - the expansion is done per-execution based on the "static" SQM
67+
// - Note from Christian: The call to domainParameterXref.clearExpansions()
68+
// in ConcreteSqmSelectQueryPlan is a concurrency issue when cached
69+
// - This could be solved by using a method-local clone of domainParameterXref
70+
// when multi-valued params exist
71+
&& ! keySource.hasMultiValuedParameterBindingsChecker().get() == TRUE;
7972
}
8073

8174
public static QueryInterpretationCache.Key generateNonSelectKey(InterpretationsKeySource keyDetails) {
@@ -86,24 +79,26 @@ public static QueryInterpretationCache.Key generateNonSelectKey(InterpretationsK
8679
return null;
8780
}
8881

89-
9082
private final String query;
9183
private final Class<?> resultType;
9284
private final LockOptions lockOptions;
9385
private final TupleTransformer<?> tupleTransformer;
94-
private final ResultListTransformer resultListTransformer;
86+
private final ResultListTransformer<?> resultListTransformer;
87+
private final Collection<String> enabledFetchProfiles;
9588

9689
private SqmInterpretationsKey(
9790
String query,
9891
Class<?> resultType,
9992
LockOptions lockOptions,
10093
TupleTransformer<?> tupleTransformer,
101-
ResultListTransformer resultListTransformer) {
94+
ResultListTransformer<?> resultListTransformer,
95+
Collection<String> enabledFetchProfiles) {
10296
this.query = query;
10397
this.resultType = resultType;
10498
this.lockOptions = lockOptions;
10599
this.tupleTransformer = tupleTransformer;
106100
this.resultListTransformer = resultListTransformer;
101+
this.enabledFetchProfiles = enabledFetchProfiles;
107102
}
108103

109104
@Override
@@ -114,7 +109,8 @@ public QueryInterpretationCache.Key prepareForStore() {
114109
// Since lock options are mutable, we need a copy for the cache key
115110
lockOptions.makeCopy(),
116111
tupleTransformer,
117-
resultListTransformer
112+
resultListTransformer,
113+
enabledFetchProfiles
118114
);
119115
}
120116

@@ -137,16 +133,12 @@ public boolean equals(Object o) {
137133
&& areEqual( resultType, that.resultType )
138134
&& areEqual( lockOptions, that.lockOptions )
139135
&& areEqual( tupleTransformer, that.tupleTransformer )
140-
&& areEqual( resultListTransformer, that.resultListTransformer );
136+
&& areEqual( resultListTransformer, that.resultListTransformer )
137+
&& areEqual( enabledFetchProfiles, that.enabledFetchProfiles );
141138
}
142139

143140
private <T> boolean areEqual(T o1, T o2) {
144-
if ( o1 == null ) {
145-
return o2 == null;
146-
}
147-
else {
148-
return o1.equals( o2 );
149-
}
141+
return o1 == null ? o2 == null : o1.equals(o2);
150142
}
151143

152144
@Override

0 commit comments

Comments
 (0)