55package org .hibernate .query .sqm .tree .select ;
66
77import java .util .ArrayList ;
8- import java .util .Collections ;
98import java .util .Iterator ;
109import java .util .List ;
1110import java .util .Objects ;
1211
13- import org .hibernate .internal . util . collections . CollectionHelper ;
12+ import org .hibernate .AssertionFailure ;
1413import org .hibernate .query .common .FetchClauseType ;
1514import org .hibernate .query .SemanticException ;
1615import org .hibernate .query .sqm .SetOperator ;
2726import org .hibernate .query .sqm .tree .from .SqmJoin ;
2827import org .hibernate .type .descriptor .java .JavaType ;
2928
29+ import static java .util .Collections .unmodifiableList ;
30+ import static org .hibernate .internal .util .collections .CollectionHelper .listOf ;
31+
3032/**
3133 * A grouped list of queries connected through a certain set operator.
3234 *
@@ -38,7 +40,7 @@ public class SqmQueryGroup<T> extends SqmQueryPart<T> implements JpaQueryGroup<T
3840 private SetOperator setOperator ;
3941
4042 public SqmQueryGroup (SqmQueryPart <T > queryPart ) {
41- this ( queryPart .nodeBuilder (), null , CollectionHelper . listOf ( queryPart ) );
43+ this ( queryPart .nodeBuilder (), null , listOf ( queryPart ) );
4244 }
4345
4446 public SqmQueryGroup (
@@ -56,20 +58,17 @@ public SqmQueryPart<T> copy(SqmCopyContext context) {
5658 if ( existing != null ) {
5759 return existing ;
5860 }
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 ;
6271 }
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 ;
7372 }
7473
7574 public List <SqmQueryPart <T >> queryParts () {
@@ -88,7 +87,9 @@ public SqmQuerySpec<T> getLastQuerySpec() {
8887
8988 @ Override
9089 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 ();
9293 }
9394
9495 @ Override
@@ -98,7 +99,7 @@ public <X> X accept(SemanticQueryWalker<X> walker) {
9899
99100 @ Override
100101 public List <SqmQueryPart <T >> getQueryParts () {
101- return Collections . unmodifiableList ( queryParts );
102+ return unmodifiableList ( queryParts );
102103 }
103104
104105 public SetOperator getSetOperator () {
@@ -156,12 +157,11 @@ private void validateQueryGroupFetchStructure(List<? extends SqmTypedNode<?>> ty
156157 final int firstSelectionSize = typedNodes .size ();
157158 for ( int i = 0 ; i < queryParts .size (); i ++ ) {
158159 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 );
161162 }
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 ();
165165 if ( firstSelectionSize != selections .size () ) {
166166 throw new SemanticException ( "All query parts in a query group must have the same arity" );
167167 }
@@ -175,31 +175,25 @@ private void validateQueryGroupFetchStructure(List<? extends SqmTypedNode<?>> ty
175175 );
176176 }
177177 if ( firstSqmSelection instanceof SqmFrom <?, ?> firstFrom ) {
178- final SqmFrom <?, ?> from = (SqmFrom <?, ?>) selections .get ( j ).getSelectableNode ();
178+ final var from = (SqmFrom <?, ?>) selections .get ( j ).getSelectableNode ();
179179 validateFetchesMatch ( firstFrom , from );
180180 }
181181 }
182182 }
183+ else {
184+ throw new AssertionFailure ( "Unrecognized SqmQueryPart subtype" );
185+ }
183186 }
184187 }
185188
186189 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 ();
189192 while ( firstJoinIter .hasNext () ) {
190193 final SqmJoin <?, ?> firstSqmJoin = firstJoinIter .next ();
191194 if ( firstSqmJoin instanceof SqmAttributeJoin <?, ?> firstAttrJoin ) {
192195 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 );
203197 if ( matchingAttrJoin == null || firstAttrJoin .getModel () != matchingAttrJoin .getModel () ) {
204198 throw new SemanticException (
205199 "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) {
211205 }
212206 // At this point, the other iterator should only contain non-fetch joins
213207 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 ;
221222 }
222223 }
224+ return null ;
223225 }
224226
225227 @ Override
0 commit comments