2222import org .hibernate .query .sqm .SqmPathSource ;
2323import org .hibernate .query .sqm .tree .domain .SqmDomainType ;
2424import org .hibernate .query .sqm .tree .domain .SqmPluralPersistentAttribute ;
25+ import org .hibernate .query .sqm .tree .select .SqmSelectQuery ;
2526import org .hibernate .query .sqm .tuple .TupleType ;
2627import org .hibernate .query .SemanticException ;
2728import org .hibernate .query .sqm .SqmExpressible ;
@@ -56,10 +57,10 @@ public class AnonymousTupleType<T>
5657 private final Map <String , Integer > componentIndexMap ;
5758
5859 public AnonymousTupleType (SqmSubQuery <T > subQuery ) {
59- this ( extractSqmExpressibles ( subQuery ) );
60+ this ( extractSqmExpressibles ( subQuery ), extractAliases ( subQuery ) );
6061 }
6162
62- public AnonymousTupleType (SqmSelectableNode <?>[] components ) {
63+ public AnonymousTupleType (SqmSelectableNode <?>[] components , List < String > aliases ) {
6364 expressibles = new SqmBindableType <?>[components .length ];
6465 componentSourcePaths = new NavigablePath [components .length ];
6566 for ( int i = 0 ; i < components .length ; i ++ ) {
@@ -74,7 +75,10 @@ public AnonymousTupleType(SqmSelectableNode<?>[] components) {
7475 componentIndexMap = linkedMapOfSize ( components .length );
7576 for ( int i = 0 ; i < components .length ; i ++ ) {
7677 final SqmSelectableNode <?> component = components [i ];
77- final String alias = component .getAlias ();
78+ String alias = aliases == null ? null : aliases .get ( i );
79+ if ( alias == null ) {
80+ alias = component .getAlias ();
81+ }
7882 if ( alias == null ) {
7983 throw new SemanticException ( "Select item at position " + (i +1 ) + " in select list has no alias"
8084 + " (aliases are required in CTEs and in subqueries occurring in from clause)" );
@@ -121,6 +125,20 @@ private static SqmSelectableNode<?>[] extractSqmExpressibles(SqmSubQuery<?> subQ
121125 return selectClause .getSelectionItems ().toArray ( SqmSelectableNode []::new );
122126 }
123127
128+ protected static List <String > extractAliases (SqmSelectQuery <?> subQuery ) {
129+ final SqmSelectClause selectClause = subQuery .getQueryPart ()
130+ .getFirstQuerySpec ()
131+ .getSelectClause ();
132+ final var aliases = new ArrayList <String >();
133+ for (final var selection : selectClause .getSelections ()) {
134+ final var alias = selection .getAlias ();
135+ selection .getSelectableNode ().visitSubSelectableNodes ( node ->
136+ aliases .add ( alias == null ? node .getAlias () : alias )
137+ );
138+ }
139+ return aliases ;
140+ }
141+
124142 private static JavaType <?>[] getTypeDescriptors (SqmSelectableNode <?>[] components ) {
125143 final JavaType <?>[] typeDescriptors = new JavaType <?>[components .length ];
126144 for ( int i = 0 ; i < components .length ; i ++ ) {
0 commit comments