Support SimpleFunction and SimpleExpression in order by expression.

This allows ordering by functions like:

    ORDER BY GREATEST(table1.created_at, table2.created_at) ASC

or by arbitrary SQL snippets

    orderBy(OrderByField.from(Expressions.just("1")).asc()) => ORDER BY 1 ASC

Original pull request #1348
This commit is contained in:
Koen Punt
2022-10-05 15:03:11 +02:00
committed by Jens Schauder
parent 58bf5566b6
commit d604797e42
2 changed files with 72 additions and 0 deletions

View File

@@ -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<OrderByField> implements PartRenderer {
@@ -32,6 +36,9 @@ class OrderByClauseVisitor extends TypedSubtreeVisitor<OrderByField> 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<OrderByField> 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));

View File

@@ -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<Expression> 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");
}
}