@@ -865,30 +865,25 @@ public Map<JpaCriteriaParameter<?>, SqmJpaCriteriaParameterWrapper<?>> getJpaCri
865865
866866 public static SqmSortSpecification sortSpecification (SqmSelectStatement <?> sqm , Order <?> order ) {
867867 final List <SqmSelectableNode <?>> items = sqm .getQuerySpec ().getSelectClause ().getSelectionItems ();
868- final int element = order .getElement ();
869- if ( element < 1 ) {
870- throw new IllegalQueryOperationException ("Cannot order by element " + element
871- + " (the first select item is element 1)" );
872- }
873- if ( element > items .size () ) {
874- throw new IllegalQueryOperationException ("Cannot order by element " + element
875- + " (there are only " + items .size () + " select items)" );
876- }
877- final SqmSelectableNode <?> selected = items .get ( element -1 );
868+ final SqmSelectableNode <?> selected = selectedNode ( sqm , order ); // does validation by side effect!
869+ return createSortSpecification ( sqm , order , items , selected );
870+ }
878871
872+ private static SqmSortSpecification createSortSpecification (
873+ SqmSelectStatement <?> sqm , Order <?> order , List <SqmSelectableNode <?>> items , SqmSelectableNode <?> selected ) {
879874 final NodeBuilder builder = sqm .nodeBuilder ();
880875 if ( order .getEntityClass () == null ) {
881876 // ordering by an element of the select list
882877 return new SqmSortSpecification (
883- new SqmAliasedNodeRef ( element , builder .getIntegerType (), builder ),
878+ new SqmAliasedNodeRef ( order . getElement () , builder .getIntegerType (), builder ),
884879 order .getDirection (),
885880 order .getNullPrecedence (),
886881 order .isCaseInsensitive ()
887882 );
888883 }
889884 else {
890885 // ordering by an attribute of the returned entity
891- if ( items .size () = = 1 ) {
886+ if ( items .size () < = 1 ) {
892887 if ( selected instanceof SqmFrom <?, ?> root ) {
893888 if ( !order .getEntityClass ().isAssignableFrom ( root .getJavaType () ) ) {
894889 throw new IllegalQueryOperationException ("Select item was of wrong entity type" );
@@ -898,7 +893,10 @@ public static SqmSortSpecification sortSpecification(SqmSelectStatement<?> sqm,
898893 while ( tokens .hasMoreTokens () ) {
899894 path = path .get ( tokens .nextToken () );
900895 }
901- return builder .sort ( path , order .getDirection (), order .getNullPrecedence (), order .isCaseInsensitive () );
896+ return builder .sort ( path ,
897+ order .getDirection (),
898+ order .getNullPrecedence (),
899+ order .isCaseInsensitive () );
902900 }
903901 else {
904902 throw new IllegalQueryOperationException ("Select item was not an entity type" );
@@ -910,6 +908,32 @@ public static SqmSortSpecification sortSpecification(SqmSelectStatement<?> sqm,
910908 }
911909 }
912910
911+ private static SqmSelectableNode <?> selectedNode (SqmSelectStatement <?> sqm , Order <?> order ) {
912+ final int element = order .getElement ();
913+ if ( element < 1 ) {
914+ throw new IllegalQueryOperationException ("Cannot order by element " + element
915+ + " (the first select item is element 1)" );
916+ }
917+ final var selectionItems = sqm .getQuerySpec ().getSelectClause ().getSelectionItems ();
918+ final int items = selectionItems .size ();
919+ if ( items == 0 && element == 1 ) {
920+ if ( order .getEntityClass () == null || sqm .getQuerySpec ().getRootList ().size () > 1 ) {
921+ throw new IllegalQueryOperationException ("Cannot order by element " + element
922+ + " (there is no select list)" );
923+ }
924+ else {
925+ return sqm .getQuerySpec ().getRootList ().get (0 );
926+ }
927+ }
928+ else if ( element > items ) {
929+ throw new IllegalQueryOperationException ( "Cannot order by element " + element
930+ + " (there are only " + items + " select items)" );
931+ }
932+ else {
933+ return selectionItems .get ( element - 1 );
934+ }
935+ }
936+
913937 public static boolean isSelectionAssignableToResultType (SqmSelection <?> selection , Class <?> expectedResultType ) {
914938 if ( expectedResultType == null ) {
915939 return true ;
0 commit comments