Polishing.
Use structured NullsPrecedence rendering in JPQL renderer. Throw UnsupportedOperationException for the time being until Nulls Precedence is supported through Criteria API. See #3529
This commit is contained in:
@@ -796,7 +796,7 @@ class JpqlQueryRenderer extends JpqlBaseVisitor<QueryTokenStream> {
|
||||
builder.append(QueryTokens.expression(ctx.DESC()));
|
||||
}
|
||||
|
||||
if(ctx.nullsPrecedence() != null) {
|
||||
if (ctx.nullsPrecedence() != null) {
|
||||
builder.append(visit(ctx.nullsPrecedence()));
|
||||
}
|
||||
|
||||
@@ -805,8 +805,18 @@ class JpqlQueryRenderer extends JpqlBaseVisitor<QueryTokenStream> {
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitNullsPrecedence(NullsPrecedenceContext ctx) {
|
||||
// return QueryTokenStream.concat(ctx.children, it-> QueryRendererBuilder.from(QueryTokens.token(it.getText())), TOKEN_SPACE);
|
||||
return QueryTokenStream.justAs(ctx.children, it-> QueryTokens.token(it.getText()));
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(TOKEN_NULLS);
|
||||
|
||||
if (ctx.FIRST() != null) {
|
||||
builder.append(TOKEN_FIRST);
|
||||
} else if (ctx.LAST() != null) {
|
||||
builder.append(TOKEN_LAST);
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -753,6 +753,10 @@ public abstract class QueryUtils {
|
||||
PropertyPath property = PropertyPath.from(order.getProperty(), from.getJavaType());
|
||||
Expression<?> expression = toExpressionRecursively(from, property);
|
||||
|
||||
if (order.getNullHandling() != Sort.NullHandling.NATIVE) {
|
||||
throw new UnsupportedOperationException("Applying Null Precedence using Criteria Queries is not yet supported.");
|
||||
}
|
||||
|
||||
if (order.isIgnoreCase() && String.class.equals(expression.getJavaType())) {
|
||||
Expression<String> upper = cb.lower((Expression<String>) expression);
|
||||
return order.isAscending() ? cb.asc(upper) : cb.desc(upper);
|
||||
|
||||
@@ -15,11 +15,9 @@
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static java.util.Collections.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityManager;
|
||||
@@ -48,6 +46,7 @@ import java.util.stream.Collectors;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.sample.Category;
|
||||
@@ -315,6 +314,20 @@ class QueryUtilsIntegrationTests {
|
||||
assertThat(orders).hasSize(1);
|
||||
}
|
||||
|
||||
@Test // GH-3529
|
||||
void nullPrecedenceThroughCriteriaApiNotYetSupported() {
|
||||
|
||||
CriteriaBuilder builder = em.getCriteriaBuilder();
|
||||
CriteriaQuery<User> query = builder.createQuery(User.class);
|
||||
Root<User> root = query.from(User.class);
|
||||
Join<User, User> join = root.join("manager", JoinType.LEFT);
|
||||
|
||||
Sort sort = Sort.by(Sort.Order.desc("manager").nullsFirst());
|
||||
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class)
|
||||
.isThrownBy(() -> QueryUtils.toOrders(sort, join, builder));
|
||||
}
|
||||
|
||||
/**
|
||||
* This test documents an ambiguity in the JPA spec (or it's implementation in Hibernate vs EclipseLink) that we have
|
||||
* to work around in the test {@link #doesNotCreateJoinForOptionalAssociationWithoutFurtherNavigation()}. See also:
|
||||
|
||||
Reference in New Issue
Block a user