5
5
package org .hibernate .query .sqm .tree .select ;
6
6
7
7
import java .util .ArrayList ;
8
- import java .util .Collections ;
9
8
import java .util .Iterator ;
10
9
import java .util .List ;
11
10
import java .util .Objects ;
12
11
13
- import org .hibernate .internal . util . collections . CollectionHelper ;
12
+ import org .hibernate .AssertionFailure ;
14
13
import org .hibernate .query .common .FetchClauseType ;
15
14
import org .hibernate .query .SemanticException ;
16
15
import org .hibernate .query .sqm .SetOperator ;
27
26
import org .hibernate .query .sqm .tree .from .SqmJoin ;
28
27
import org .hibernate .type .descriptor .java .JavaType ;
29
28
29
+ import static java .util .Collections .unmodifiableList ;
30
+ import static org .hibernate .internal .util .collections .CollectionHelper .listOf ;
31
+
30
32
/**
31
33
* A grouped list of queries connected through a certain set operator.
32
34
*
@@ -38,7 +40,7 @@ public class SqmQueryGroup<T> extends SqmQueryPart<T> implements JpaQueryGroup<T
38
40
private SetOperator setOperator ;
39
41
40
42
public SqmQueryGroup (SqmQueryPart <T > queryPart ) {
41
- this ( queryPart .nodeBuilder (), null , CollectionHelper . listOf ( queryPart ) );
43
+ this ( queryPart .nodeBuilder (), null , listOf ( queryPart ) );
42
44
}
43
45
44
46
public SqmQueryGroup (
@@ -56,20 +58,17 @@ public SqmQueryPart<T> copy(SqmCopyContext context) {
56
58
if ( existing != null ) {
57
59
return existing ;
58
60
}
59
- final List <SqmQueryPart <T >> queryParts = new ArrayList <>( this .queryParts .size () );
60
- for ( SqmQueryPart <T > queryPart : this .queryParts ) {
61
- queryParts .add ( queryPart .copy ( context ) );
61
+ else {
62
+ final List <SqmQueryPart <T >> queryParts = new ArrayList <>( this .queryParts .size () );
63
+ for ( SqmQueryPart <T > queryPart : this .queryParts ) {
64
+ queryParts .add ( queryPart .copy ( context ) );
65
+ }
66
+ final SqmQueryGroup <T > queryGroup =
67
+ context .registerCopy ( this ,
68
+ new SqmQueryGroup <>( nodeBuilder (), setOperator , queryParts ) );
69
+ copyTo ( queryGroup , context );
70
+ return queryGroup ;
62
71
}
63
- final SqmQueryGroup <T > queryGroup = context .registerCopy (
64
- this ,
65
- new SqmQueryGroup <>(
66
- nodeBuilder (),
67
- setOperator ,
68
- queryParts
69
- )
70
- );
71
- copyTo ( queryGroup , context );
72
- return queryGroup ;
73
72
}
74
73
75
74
public List <SqmQueryPart <T >> queryParts () {
@@ -88,7 +87,9 @@ public SqmQuerySpec<T> getLastQuerySpec() {
88
87
89
88
@ Override
90
89
public boolean isSimpleQueryPart () {
91
- return setOperator == null && queryParts .size () == 1 && queryParts .get ( 0 ).isSimpleQueryPart ();
90
+ return setOperator == null
91
+ && queryParts .size () == 1
92
+ && queryParts .get ( 0 ).isSimpleQueryPart ();
92
93
}
93
94
94
95
@ Override
@@ -98,7 +99,7 @@ public <X> X accept(SemanticQueryWalker<X> walker) {
98
99
99
100
@ Override
100
101
public List <SqmQueryPart <T >> getQueryParts () {
101
- return Collections . unmodifiableList ( queryParts );
102
+ return unmodifiableList ( queryParts );
102
103
}
103
104
104
105
public SetOperator getSetOperator () {
@@ -156,12 +157,11 @@ private void validateQueryGroupFetchStructure(List<? extends SqmTypedNode<?>> ty
156
157
final int firstSelectionSize = typedNodes .size ();
157
158
for ( int i = 0 ; i < queryParts .size (); i ++ ) {
158
159
final SqmQueryPart <T > queryPart = queryParts .get ( i );
159
- if ( queryPart instanceof SqmQueryGroup <?> ) {
160
- ( ( SqmQueryGroup <?>) queryPart ) .validateQueryGroupFetchStructure ( typedNodes );
160
+ if ( queryPart instanceof SqmQueryGroup <?> queryGroup ) {
161
+ queryGroup .validateQueryGroupFetchStructure ( typedNodes );
161
162
}
162
- else {
163
- final SqmQuerySpec <?> querySpec = (SqmQuerySpec <?>) queryPart ;
164
- final List <SqmSelection <?>> selections = querySpec .getSelectClause ().getSelections ();
163
+ else if ( queryPart instanceof SqmQuerySpec <?> querySpec ) {
164
+ final var selections = querySpec .getSelectClause ().getSelections ();
165
165
if ( firstSelectionSize != selections .size () ) {
166
166
throw new SemanticException ( "All query parts in a query group must have the same arity" );
167
167
}
@@ -175,31 +175,25 @@ private void validateQueryGroupFetchStructure(List<? extends SqmTypedNode<?>> ty
175
175
);
176
176
}
177
177
if ( firstSqmSelection instanceof SqmFrom <?, ?> firstFrom ) {
178
- final SqmFrom <?, ?> from = (SqmFrom <?, ?>) selections .get ( j ).getSelectableNode ();
178
+ final var from = (SqmFrom <?, ?>) selections .get ( j ).getSelectableNode ();
179
179
validateFetchesMatch ( firstFrom , from );
180
180
}
181
181
}
182
182
}
183
+ else {
184
+ throw new AssertionFailure ( "Unrecognized SqmQueryPart subtype" );
185
+ }
183
186
}
184
187
}
185
188
186
189
private void validateFetchesMatch (SqmFrom <?, ?> firstFrom , SqmFrom <?, ?> from ) {
187
- final Iterator <? extends SqmJoin <?, ?>> firstJoinIter = firstFrom .getSqmJoins ().iterator ();
188
- final Iterator <? extends SqmJoin <?, ?>> joinIter = from .getSqmJoins ().iterator ();
190
+ final var firstJoinIter = firstFrom .getSqmJoins ().iterator ();
191
+ final var joinIter = from .getSqmJoins ().iterator ();
189
192
while ( firstJoinIter .hasNext () ) {
190
193
final SqmJoin <?, ?> firstSqmJoin = firstJoinIter .next ();
191
194
if ( firstSqmJoin instanceof SqmAttributeJoin <?, ?> firstAttrJoin ) {
192
195
if ( firstAttrJoin .isFetched () ) {
193
- SqmAttributeJoin <?, ?> matchingAttrJoin = null ;
194
- while ( joinIter .hasNext () ) {
195
- final SqmJoin <?, ?> sqmJoin = joinIter .next ();
196
- if ( sqmJoin instanceof SqmAttributeJoin <?, ?> attrJoin ) {
197
- if ( attrJoin .isFetched () ) {
198
- matchingAttrJoin = attrJoin ;
199
- break ;
200
- }
201
- }
202
- }
196
+ final var matchingAttrJoin = findFirstFetchJoin ( joinIter );
203
197
if ( matchingAttrJoin == null || firstAttrJoin .getModel () != matchingAttrJoin .getModel () ) {
204
198
throw new SemanticException (
205
199
"All query parts in a query group must have the same join fetches in the same order"
@@ -211,15 +205,23 @@ private void validateFetchesMatch(SqmFrom<?, ?> firstFrom, SqmFrom<?, ?> from) {
211
205
}
212
206
// At this point, the other iterator should only contain non-fetch joins
213
207
while ( joinIter .hasNext () ) {
214
- final SqmJoin <?, ?> sqmJoin = joinIter .next ();
215
- if ( sqmJoin instanceof SqmAttributeJoin <?, ?> attrJoin ) {
216
- if ( attrJoin .isFetched () ) {
217
- throw new SemanticException (
218
- "All query parts in a query group must have the same join fetches in the same order"
219
- );
220
- }
208
+ if ( joinIter .next () instanceof SqmAttributeJoin <?, ?> attrJoin
209
+ && attrJoin .isFetched () ) {
210
+ throw new SemanticException (
211
+ "All query parts in a query group must have the same join fetches in the same order"
212
+ );
213
+ }
214
+ }
215
+ }
216
+
217
+ private static SqmAttributeJoin <?, ?> findFirstFetchJoin (Iterator <? extends SqmJoin <?, ?>> joinIter ) {
218
+ while ( joinIter .hasNext () ) {
219
+ if ( joinIter .next () instanceof SqmAttributeJoin <?, ?> attrJoin
220
+ && attrJoin .isFetched () ) {
221
+ return attrJoin ;
221
222
}
222
223
}
224
+ return null ;
223
225
}
224
226
225
227
@ Override
0 commit comments