Skip to content

Commit d604797

Browse files
koenpuntschauder
authored andcommitted
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
1 parent 58bf556 commit d604797

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

spring-data-relational/src/main/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitor.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,29 @@
1616
package org.springframework.data.relational.core.sql.render;
1717

1818
import org.springframework.data.relational.core.sql.Column;
19+
import org.springframework.data.relational.core.sql.Expressions;
1920
import org.springframework.data.relational.core.sql.OrderByField;
21+
import org.springframework.data.relational.core.sql.SimpleFunction;
2022
import org.springframework.data.relational.core.sql.Visitable;
23+
import org.springframework.lang.Nullable;
2124

2225
/**
2326
* {@link PartRenderer} for {@link OrderByField}s.
2427
*
2528
* @author Mark Paluch
2629
* @author Jens Schauder
2730
* @author Chirag Tailor
31+
* @author Koen Punt
2832
* @since 1.1
2933
*/
3034
class OrderByClauseVisitor extends TypedSubtreeVisitor<OrderByField> implements PartRenderer {
3135

3236
private final RenderContext context;
3337

3438
private final StringBuilder builder = new StringBuilder();
39+
40+
@Nullable private PartRenderer delegate;
41+
3542
private boolean first = true;
3643

3744
OrderByClauseVisitor(RenderContext context) {
@@ -68,8 +75,32 @@ Delegation leaveMatched(OrderByField segment) {
6875
return Delegation.leave();
6976
}
7077

78+
@Override
79+
Delegation enterNested(Visitable segment) {
80+
if (segment instanceof SimpleFunction) {
81+
delegate = new SimpleFunctionVisitor(context);
82+
return Delegation.delegateTo((SimpleFunctionVisitor)delegate);
83+
}
84+
85+
if (segment instanceof Expressions.SimpleExpression) {
86+
delegate = new ExpressionVisitor(context);
87+
return Delegation.delegateTo((ExpressionVisitor)delegate);
88+
}
89+
90+
return super.enterNested(segment);
91+
}
92+
7193
@Override
7294
Delegation leaveNested(Visitable segment) {
95+
if (delegate instanceof SimpleFunctionVisitor) {
96+
builder.append(delegate.getRenderedPart());
97+
delegate = null;
98+
}
99+
100+
if (delegate instanceof ExpressionVisitor) {
101+
builder.append(delegate.getRenderedPart());
102+
delegate = null;
103+
}
73104

74105
if (segment instanceof Column) {
75106
builder.append(NameRenderer.fullyQualifiedReference(context, (Column) segment));

spring-data-relational/src/test/java/org/springframework/data/relational/core/sql/render/OrderByClauseVisitorUnitTests.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,23 @@
1919

2020
import org.junit.jupiter.api.Test;
2121
import org.springframework.data.relational.core.sql.Column;
22+
import org.springframework.data.relational.core.sql.Expression;
23+
import org.springframework.data.relational.core.sql.Expressions;
2224
import org.springframework.data.relational.core.sql.OrderByField;
2325
import org.springframework.data.relational.core.sql.SQL;
2426
import org.springframework.data.relational.core.sql.Select;
27+
import org.springframework.data.relational.core.sql.SimpleFunction;
2528
import org.springframework.data.relational.core.sql.Table;
2629

30+
import java.util.Arrays;
31+
import java.util.List;
32+
2733
/**
2834
* Unit tests for {@link OrderByClauseVisitor}.
2935
*
3036
* @author Mark Paluch
3137
* @author Jens Schauder
38+
* @author Koen Punt
3239
*/
3340
class OrderByClauseVisitorUnitTests {
3441

@@ -88,4 +95,38 @@ void shouldRenderOrderByFullyQualifiedNameWithTableAlias() {
8895
assertThat(visitor.getRenderedPart().toString()).isEqualTo("emp.name ASC");
8996
}
9097

98+
@Test // GH-1348
99+
void shouldRenderOrderBySimpleFunction() {
100+
101+
Table employee = SQL.table("employee").as("emp");
102+
Column column = employee.column("name");
103+
List<Expression> columns = Arrays.asList(employee.column("id"), column);
104+
105+
SimpleFunction simpleFunction = SimpleFunction.create("GREATEST", columns);
106+
107+
Select select = Select.builder().select(column).from(employee)
108+
.orderBy(OrderByField.from(simpleFunction).asc(), OrderByField.from(column).asc()).build();
109+
110+
OrderByClauseVisitor visitor = new OrderByClauseVisitor(new SimpleRenderContext(NamingStrategies.asIs()));
111+
select.visit(visitor);
112+
113+
assertThat(visitor.getRenderedPart().toString()).isEqualTo("GREATEST(emp.id, emp.name) ASC, emp.name ASC");
114+
}
115+
116+
@Test // GH-1348
117+
void shouldRenderOrderBySimpleExpression() {
118+
119+
Table employee = SQL.table("employee").as("emp");
120+
Column column = employee.column("name");
121+
122+
Expression simpleExpression = Expressions.just("1");
123+
124+
Select select = Select.builder().select(column).from(employee).orderBy(OrderByField.from(simpleExpression).asc())
125+
.build();
126+
127+
OrderByClauseVisitor visitor = new OrderByClauseVisitor(new SimpleRenderContext(NamingStrategies.asIs()));
128+
select.visit(visitor);
129+
130+
assertThat(visitor.getRenderedPart().toString()).isEqualTo("1 ASC");
131+
}
91132
}

0 commit comments

Comments
 (0)