Skip to content

Commit

Permalink
HHH-16848 add SelectionQuery.ascending(int) & descending(int)
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinking committed Jun 26, 2023
1 parent 23df9eb commit bec6cfa
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,16 @@ public Query<R> descending(SingularAttribute<? super R, ?> attribute) {
throw new UnsupportedOperationException( "Not supported for procedure calls" );
}

@Override
public Query<R> ascending(int element) {
throw new UnsupportedOperationException( "Not supported for procedure calls" );
}

@Override
public Query<R> descending(int element) {
throw new UnsupportedOperationException( "Not supported for procedure calls" );
}

@Override
public Query<R> unordered() {
return this;
Expand Down
6 changes: 6 additions & 0 deletions hibernate-core/src/main/java/org/hibernate/query/Query.java
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,12 @@ default Query<R> applyLoadGraph(@SuppressWarnings("rawtypes") RootGraph graph) {
@Override
Query<R> descending(SingularAttribute<? super R, ?> attribute);

@Override
Query<R> ascending(int element);

@Override
Query<R> descending(int element);

@Override
Query<R> unordered();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,28 @@ default Stream<R> stream() {
@Incubating
SelectionQuery<R> descending(SingularAttribute<? super R, ?> attribute);

/**
* Add an element of the select list to be used to order the query results
* in ascending order.
*
* @param element an integer identifying an element of the select list
*
* @since 6.3
*/
@Incubating
SelectionQuery<R> ascending(int element);

/**
* Add an element of the select list to be used to order the query results
* in descending order.
*
* @param element an integer identifying an element of the select list
*
* @since 6.3
*/
@Incubating
SelectionQuery<R> descending(int element);

/**
* Clear the ordering conditions for this query.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,22 @@ default SqmQueryImplementor<R> descending(SingularAttribute<? super R, ?> attrib
return this;
}

@Override
default SqmQueryImplementor<R> ascending(int element) {
addOrdering( element, SortOrder.ASCENDING );
return this;
}

@Override
default SqmQueryImplementor<R> descending(int element) {
addOrdering( element, SortOrder.DESCENDING );
return this;
}

SqmQueryImplementor<R> addOrdering(SingularAttribute<? super R, ?> attribute, SortOrder order);

SqmQueryImplementor<R> addOrdering(int element, SortOrder order);

@Override
SqmQueryImplementor<R> unordered();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import org.hibernate.query.Query;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.ResultListTransformer;
import org.hibernate.query.SelectionQuery;
import org.hibernate.query.TupleTransformer;
import org.hibernate.query.named.NamedQueryMemento;

Expand Down Expand Up @@ -288,6 +287,16 @@ public Query<R> descending(SingularAttribute<? super R, ?> attribute) {
throw new UnsupportedOperationException( "Should be implemented by " + this.getClass().getName() );
}

@Override
public Query<R> ascending(int element) {
throw new UnsupportedOperationException( "Should be implemented by " + this.getClass().getName() );
}

@Override
public Query<R> descending(int element) {
throw new UnsupportedOperationException( "Should be implemented by " + this.getClass().getName() );
}

@Override
public Query<R> unordered() {
throw new UnsupportedOperationException( "Should be implemented by " + this.getClass().getName() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1510,6 +1510,16 @@ public Query<R> descending(SingularAttribute<? super R, ?> attribute) {
throw new UnsupportedOperationException("Not yet supported for native queries");
}

@Override
public Query<R> ascending(int element) {
throw new UnsupportedOperationException("Not yet supported for native queries");
}

@Override
public Query<R> descending(int element) {
throw new UnsupportedOperationException("Not yet supported for native queries");
}

@Override
public Query<R> unordered() {
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
Expand All @@ -99,6 +100,7 @@
import org.hibernate.query.sqm.tree.select.SqmQueryPart;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
import org.hibernate.query.sqm.tree.update.SqmAssignment;
import org.hibernate.query.sqm.tree.update.SqmUpdateStatement;
import org.hibernate.sql.results.internal.TupleMetadata;
Expand Down Expand Up @@ -982,6 +984,36 @@ public SqmQueryImplementor<R> addOrdering(SingularAttribute<? super R, ?> attrib
}
}

@Override
public SqmQueryImplementor<R> addOrdering(int element, SortOrder order) {
if ( sqm instanceof SqmSelectStatement ) {
sqm = sqm.copy( SqmCopyContext.noParamCopyContext() );
SqmSelectStatement<R> select = (SqmSelectStatement<R>) sqm;
int size = select.getSelection().getSelectionItems().size();
if ( element < 1) {
throw new IllegalArgumentException("Cannot order by element " + element + " (the first select item is element 1)");
}
if ( element > size) {
throw new IllegalArgumentException("Cannot order by element " + element + " (there are " + size + " select items)");
}
NodeBuilder nodeBuilder = sqm.nodeBuilder();
List<Order> orders = new ArrayList<>( select.getOrderList() );
orders.add( new SqmSortSpecification(
new SqmAliasedNodeRef(
element,
nodeBuilder.getTypeConfiguration().standardBasicTypeForJavaType( Integer.class ),
nodeBuilder
),
order
) );
select.orderBy( orders );
return this;
}
else {
throw new IllegalStateException( "Not a select query" );
}
}

@Override
public SqmQueryImplementor<R> unordered() {
if ( sqm instanceof SqmSelectStatement ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
import org.hibernate.query.sqm.tree.expression.SqmParameter;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.select.SqmSelectStatement;
import org.hibernate.query.sqm.tree.select.SqmSelection;
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
import org.hibernate.sql.results.internal.TupleMetadata;
import org.hibernate.type.descriptor.java.JavaType;

Expand Down Expand Up @@ -567,6 +569,18 @@ public SqmSelectionQuery<R> descending(SingularAttribute<? super R, ?> attribute
return this;
}

@Override
public SqmSelectionQuery<R> ascending(int element) {
addOrdering( element, SortOrder.ASCENDING );
return this;
}

@Override
public SqmSelectionQuery<R> descending(int element) {
addOrdering( element, SortOrder.DESCENDING );
return this;
}

private void addOrdering(SingularAttribute<? super R, ?> attribute, SortOrder order) {
sqm = sqm.copy( SqmCopyContext.noParamCopyContext() );
NodeBuilder nodeBuilder = sqm.nodeBuilder();
Expand All @@ -581,6 +595,28 @@ private void addOrdering(SingularAttribute<? super R, ?> attribute, SortOrder or
sqm.orderBy( orders );
}

private void addOrdering(int element, SortOrder order) {
sqm = sqm.copy( SqmCopyContext.noParamCopyContext() );
int size = sqm.getSelection().getSelectionItems().size();
if ( element < 1) {
throw new IllegalArgumentException("Cannot order by element " + element + " (the first select item is element 1)");
}
if ( element > size) {
throw new IllegalArgumentException("Cannot order by element " + element + " (there are " + size + " select items)");
}
NodeBuilder nodeBuilder = sqm.nodeBuilder();
List<Order> orders = new ArrayList<>( sqm.getOrderList() );
orders.add( new SqmSortSpecification(
new SqmAliasedNodeRef(
element,
nodeBuilder.getTypeConfiguration().standardBasicTypeForJavaType( Integer.class ),
nodeBuilder
),
order
) );
sqm.orderBy( orders );
}

@Override
public SqmSelectionQuery<R> unordered() {
sqm = sqm.copy( SqmCopyContext.noParamCopyContext() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,47 @@ public class OrderTest {
});
}

@Test void testAscendingDescendingBySelectElement(SessionFactoryScope scope) {
scope.inTransaction( session -> session.createMutationQuery("delete Book").executeUpdate() );
scope.inTransaction( session -> {
session.persist(new Book("9781932394153", "Hibernate in Action"));
session.persist(new Book("9781617290459", "Java Persistence with Hibernate"));
});
scope.inSession(session -> {
List<?> titlesAsc = session.createSelectionQuery("select isbn, title from Book", Object[].class)
.ascending(2)
.getResultList()
.stream().map(book -> book[1])
.collect(toList());
assertEquals("Hibernate in Action", titlesAsc.get(0));
assertEquals("Java Persistence with Hibernate", titlesAsc.get(1));

List<?> titlesDesc = session.createSelectionQuery("select isbn, title from Book", Object[].class)
.descending(2)
.getResultList()
.stream().map(book -> book[1])
.collect(toList());
assertEquals("Hibernate in Action", titlesDesc.get(1));
assertEquals("Java Persistence with Hibernate", titlesDesc.get(0));

List<?> isbnAsc = session.createSelectionQuery("select isbn, title from Book", Object[].class)
.ascending(1).descending(2)
.getResultList()
.stream().map(book -> book[1])
.collect(toList());
assertEquals("Hibernate in Action", isbnAsc.get(1));
assertEquals("Java Persistence with Hibernate", isbnAsc.get(0));

List<?> isbnDesc = session.createSelectionQuery("select isbn, title from Book", Object[].class)
.descending(1).descending(2)
.getResultList()
.stream().map(book -> book[1])
.collect(toList());
assertEquals("Hibernate in Action", isbnDesc.get(0));
assertEquals("Java Persistence with Hibernate", isbnDesc.get(1));
});
}

@Entity(name="Book")
static class Book {
@Id String isbn;
Expand Down

0 comments on commit bec6cfa

Please sign in to comment.