diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java index 482f260e..23b7e2f3 100644 --- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java +++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java @@ -16,8 +16,11 @@ package org.springframework.data.relational.core.sql.render; import org.springframework.data.relational.core.sql.Column; +import org.springframework.data.relational.core.sql.Expressions; import org.springframework.data.relational.core.sql.OrderByField; +import org.springframework.data.relational.core.sql.SimpleFunction; import org.springframework.data.relational.core.sql.Visitable; +import org.springframework.lang.Nullable; /** * {@link PartRenderer} for {@link OrderByField}s. @@ -25,6 +28,7 @@ import org.springframework.data.relational.core.sql.Visitable; * @author Mark Paluch * @author Jens Schauder * @author Chirag Tailor + * @author Koen Punt * @since 1.1 */ class OrderByClauseVisitor extends TypedSubtreeVisitor implements PartRenderer { @@ -32,6 +36,9 @@ class OrderByClauseVisitor extends TypedSubtreeVisitor implements private final RenderContext context; private final StringBuilder builder = new StringBuilder(); + + @Nullable private PartRenderer delegate; + private boolean first = true; OrderByClauseVisitor(RenderContext context) { @@ -68,8 +75,32 @@ class OrderByClauseVisitor extends TypedSubtreeVisitor implements return Delegation.leave(); } + @Override + Delegation enterNested(Visitable segment) { + if (segment instanceof SimpleFunction) { + delegate = new SimpleFunctionVisitor(context); + return Delegation.delegateTo((SimpleFunctionVisitor)delegate); + } + + if (segment instanceof Expressions.SimpleExpression) { + delegate = new ExpressionVisitor(context); + return Delegation.delegateTo((ExpressionVisitor)delegate); + } + + return super.enterNested(segment); + } + @Override Delegation leaveNested(Visitable segment) { + if (delegate instanceof SimpleFunctionVisitor) { + builder.append(delegate.getRenderedPart()); + delegate = null; + } + + if (delegate instanceof ExpressionVisitor) { + builder.append(delegate.getRenderedPart()); + delegate = null; + } if (segment instanceof Column) { builder.append(NameRenderer.fullyQualifiedReference(context, (Column) segment)); diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitorUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitorUnitTests.java index 45dff676..cd4427de 100644 --- a/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitorUnitTests.java +++ b/spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitorUnitTests.java @@ -19,16 +19,23 @@ import static org.assertj.core.api.Assertions.*; import org.junit.jupiter.api.Test; import org.springframework.data.relational.core.sql.Column; +import org.springframework.data.relational.core.sql.Expression; +import org.springframework.data.relational.core.sql.Expressions; import org.springframework.data.relational.core.sql.OrderByField; import org.springframework.data.relational.core.sql.SQL; import org.springframework.data.relational.core.sql.Select; +import org.springframework.data.relational.core.sql.SimpleFunction; import org.springframework.data.relational.core.sql.Table; +import java.util.Arrays; +import java.util.List; + /** * Unit tests for {@link OrderByClauseVisitor}. * * @author Mark Paluch * @author Jens Schauder + * @author Koen Punt */ class OrderByClauseVisitorUnitTests { @@ -88,4 +95,38 @@ class OrderByClauseVisitorUnitTests { assertThat(visitor.getRenderedPart().toString()).isEqualTo("emp.name ASC"); } + @Test // GH-1348 + void shouldRenderOrderBySimpleFunction() { + + Table employee = SQL.table("employee").as("emp"); + Column column = employee.column("name"); + List columns = Arrays.asList(employee.column("id"), column); + + SimpleFunction simpleFunction = SimpleFunction.create("GREATEST", columns); + + Select select = Select.builder().select(column).from(employee) + .orderBy(OrderByField.from(simpleFunction).asc(), OrderByField.from(column).asc()).build(); + + OrderByClauseVisitor visitor = new OrderByClauseVisitor(new SimpleRenderContext(NamingStrategies.asIs())); + select.visit(visitor); + + assertThat(visitor.getRenderedPart().toString()).isEqualTo("GREATEST(emp.id, emp.name) ASC, emp.name ASC"); + } + + @Test // GH-1348 + void shouldRenderOrderBySimpleExpression() { + + Table employee = SQL.table("employee").as("emp"); + Column column = employee.column("name"); + + Expression simpleExpression = Expressions.just("1"); + + Select select = Select.builder().select(column).from(employee).orderBy(OrderByField.from(simpleExpression).asc()) + .build(); + + OrderByClauseVisitor visitor = new OrderByClauseVisitor(new SimpleRenderContext(NamingStrategies.asIs())); + select.visit(visitor); + + assertThat(visitor.getRenderedPart().toString()).isEqualTo("1 ASC"); + } }