2323import  org .hibernate .query .sqm .tree .domain .SqmDomainType ;
2424import  org .hibernate .query .sqm .tree .domain .SqmPluralPersistentAttribute ;
2525import  org .hibernate .query .sqm .tree .select .SqmSelectQuery ;
26+ import  org .hibernate .query .sqm .tree .select .SqmSelection ;
2627import  org .hibernate .query .sqm .tuple .TupleType ;
2728import  org .hibernate .query .SemanticException ;
2829import  org .hibernate .query .sqm .SqmExpressible ;
2930import  org .hibernate .query .sqm .tree .domain .SqmPath ;
3031import  org .hibernate .query .sqm .tree .select .SqmSelectClause ;
3132import  org .hibernate .query .sqm .tree .select .SqmSelectableNode ;
32- import  org .hibernate .query .sqm .tree .select .SqmSubQuery ;
3333import  org .hibernate .spi .NavigablePath ;
3434import  org .hibernate .sql .ast .spi .FromClauseAccess ;
3535import  org .hibernate .sql .ast .spi .SqlSelection ;
@@ -56,29 +56,50 @@ public class AnonymousTupleType<T>
5656	private  final  String [] componentNames ;
5757	private  final  Map <String , Integer > componentIndexMap ;
5858
59- 	public  AnonymousTupleType (SqmSubQuery <T > subQuery ) {
60- 		this ( extractSqmExpressibles ( subQuery  ), extractAliases ( subQuery  ) );
61- 	}
59+ 	public  AnonymousTupleType (SqmSelectQuery <T > selectQuery ) {
60+ 		final  SqmSelectClause  selectClause  = selectQuery .getQueryPart ()
61+ 				.getFirstQuerySpec ()
62+ 				.getSelectClause ();
6263
63- 	public  AnonymousTupleType (SqmSelectableNode <?>[] components , List <String > aliases ) {
64- 		expressibles  = new  SqmBindableType <?>[components .length ];
65- 		componentSourcePaths  = new  NavigablePath [components .length ];
66- 		for  ( int  i  = 0 ; i  < components .length ; i ++ ) {
67- 			expressibles [i ] = components [i ].getNodeType ();
68- 			if  ( components [i ] instanceof  SqmPath <?> path  ) {
69- 				componentSourcePaths [i ] = path .getNavigablePath ();
64+ 		if  ( selectClause  == null  || selectClause .getSelections ().isEmpty () ) {
65+ 			throw  new  IllegalArgumentException ( "selectQuery has no selection items"  );
66+ 		}
67+ 		// todo: right now, we "snapshot" the state of the selectQuery when creating this type, but maybe we shouldn't? 
68+ 		//  i.e. what if the selectQuery changes later on? Or should we somehow mark the selectQuery to signal, 
69+ 		//  that changes to the select clause are invalid after a certain point? 
70+ 
71+ 		final  List <SqmSelection <?>> selections  = selectClause .getSelections ();
72+ 		final  List <SqmSelectableNode <?>> selectableNodes  = new  ArrayList <>();
73+ 		final  List <String > aliases  = new  ArrayList <>();
74+ 		if  ( selections  != null  ) {
75+ 			for  ( SqmSelection <?> selection  : selections  ) {
76+ 				selection .getSelectableNode ().visitSubSelectableNodes ( selectableNodes ::add  );
77+ 
78+ 				if  ( selection .getSelectableNode ().isCompoundSelection () ) {
79+ 					selection .getSelectableNode ().visitSubSelectableNodes ( node  ->
80+ 							aliases .add ( node .getAlias () )
81+ 					);
82+ 				}
83+ 				else  {
84+ 					aliases .add ( selection .getAlias () );
85+ 				}
7086			}
7187		}
88+ 
89+ 		final  SqmSelectableNode <?>[] components  = selectableNodes .toArray (new  SqmSelectableNode [0 ]);
90+ 
91+ 		expressibles  = new  SqmBindableType <?>[components .length ];
92+ 		componentSourcePaths  = new  NavigablePath [components .length ];
7293		componentNames  = new  String [components .length ];
7394		//noinspection unchecked 
7495		javaTypeDescriptor  = (JavaType <T >) new  ObjectArrayJavaType ( getTypeDescriptors ( components  ) );
7596		componentIndexMap  = linkedMapOfSize ( components .length  );
7697		for  ( int  i  = 0 ; i  < components .length ; i ++ ) {
77- 			final  SqmSelectableNode <?> component  = components [i ];
78- 			String  alias  = aliases  == null  ? null  : aliases .get ( i  );
79- 			if  ( alias  == null  ) {
80- 				alias  = component .getAlias ();
98+ 			expressibles [i ] = components [i ].getNodeType ();
99+ 			if  ( components [i ] instanceof  SqmPath <?> path  ) {
100+ 				componentSourcePaths [i ] = path .getNavigablePath ();
81101			}
102+ 			String  alias  = aliases .get ( i  );
82103			if  ( alias  == null  ) {
83104				throw  new  SemanticException ( "Select item at position "  + (i +1 ) + " in select list has no alias" 
84105						+ " (aliases are required in CTEs and in subqueries occurring in from clause)"  );
@@ -114,31 +135,6 @@ public String getTypeName() {
114135		return  SqmDomainType .super .getTypeName ();
115136	}
116137
117- 	private  static  SqmSelectableNode <?>[] extractSqmExpressibles (SqmSubQuery <?> subQuery ) {
118- 		final  SqmSelectClause  selectClause  = subQuery .getQuerySpec ().getSelectClause ();
119- 		if  ( selectClause  == null  || selectClause .getSelectionItems ().isEmpty () ) {
120- 			throw  new  IllegalArgumentException ( "subquery has no selection items"  );
121- 		}
122- 		// todo: right now, we "snapshot" the state of the subquery when creating this type, but maybe we shouldn't? 
123- 		//  i.e. what if the subquery changes later on? Or should we somehow mark the subquery to signal, 
124- 		//  that changes to the select clause are invalid after a certain point? 
125- 		return  selectClause .getSelectionItems ().toArray ( SqmSelectableNode []::new  );
126- 	}
127- 
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- 
142138	private  static  JavaType <?>[] getTypeDescriptors (SqmSelectableNode <?>[] components ) {
143139		final  JavaType <?>[] typeDescriptors  = new  JavaType <?>[components .length ];
144140		for  ( int  i  = 0 ; i  < components .length ; i ++ ) {
0 commit comments