Skip to content

Commit 5d266bf

Browse files
committed
HHH-19364 fix a bug introduced by Specifications in handling Order
previously, we never encountered the case of a missing select clause, because it was already filled in by the Query object, now we do!
1 parent 29c8b90 commit 5d266bf

File tree

1 file changed

+37
-13
lines changed
  • hibernate-core/src/main/java/org/hibernate/query/sqm/internal

1 file changed

+37
-13
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmUtil.java

+37-13
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)