Skip to content

Commit e2d75aa

Browse files
authored
Merge pull request #830 from jeffgbutler/case-in-order-by
Support CASE Expressions in ORDER BY Phrases
2 parents 028da50 + dca5d3d commit e2d75aa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+750
-115
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Significant changes:
88

99
- The library now requires Java 17
1010
- Deprecated code from prior releases is removed
11+
- Allow CASE expressions in ORDER BY Clauses
1112

1213
## Release 1.5.2 - June 3, 2024
1314

pom.xml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,14 +164,6 @@
164164
<version>1.5.6</version>
165165
<scope>test</scope>
166166
</dependency>
167-
<!-- Hamcrest is only here to make Infinitest happy. Not really used in the project. -->
168-
<dependency>
169-
<groupId>org.hamcrest</groupId>
170-
<artifactId>hamcrest</artifactId>
171-
<version>3.0</version>
172-
<scope>test</scope>
173-
</dependency>
174-
175167
<dependency>
176168
<groupId>org.testcontainers</groupId>
177169
<artifactId>postgresql</artifactId>

src/main/java/org/mybatis/dynamic/sql/AbstractListValueCondition.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ private <R> Collection<R> applyMapper(Function<? super T, ? extends R> mapper) {
5151

5252
private Collection<T> applyFilter(Predicate<? super T> predicate) {
5353
Objects.requireNonNull(predicate);
54-
return values.stream().filter(predicate).collect(Collectors.toList());
54+
return values.stream().filter(predicate).toList();
5555
}
5656

5757
protected <S extends AbstractListValueCondition<T>> S filterSupport(Predicate<? super T> predicate,

src/main/java/org/mybatis/dynamic/sql/SortSpecification.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515
*/
1616
package org.mybatis.dynamic.sql;
1717

18+
import org.mybatis.dynamic.sql.exception.DynamicSqlException;
19+
import org.mybatis.dynamic.sql.render.RenderingContext;
20+
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
21+
import org.mybatis.dynamic.sql.util.Messages;
22+
1823
/**
1924
* Defines attributes of columns that are necessary for rendering an order by expression.
2025
*
@@ -34,13 +39,33 @@ public interface SortSpecification {
3439
* NOT include the "DESC" word for descending sort specifications.
3540
*
3641
* @return the order by phrase
42+
* @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for
43+
* removal in release 2.1
3744
*/
38-
String orderByName();
45+
@Deprecated(since = "2.0", forRemoval = true)
46+
default String orderByName() {
47+
throw new DynamicSqlException(Messages.getString("ERROR.44")); //$NON-NLS-1$
48+
}
3949

4050
/**
4151
* Return true if the sort order is descending.
4252
*
4353
* @return true if the SortSpecification should render as descending
54+
* @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for
55+
* removal in release 2.1
4456
*/
45-
boolean isDescending();
57+
@Deprecated(since = "2.0", forRemoval = true)
58+
default boolean isDescending() {
59+
throw new DynamicSqlException(Messages.getString("ERROR.44")); //$NON-NLS-1$
60+
}
61+
62+
// the default implementation ensures compatibility with prior releases. When the
63+
// deprecated methods are removed, this function can become purely abstract.
64+
default FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) {
65+
String phrase = orderByName();
66+
if (isDescending()) {
67+
phrase = phrase + " DESC"; //$NON-NLS-1$
68+
}
69+
return FragmentAndParameters.fromFragment(phrase);
70+
}
4671
}

src/main/java/org/mybatis/dynamic/sql/SqlColumn.java

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public class SqlColumn<T> implements BindableColumn<T>, SortSpecification {
3030
protected final String name;
3131
protected final SqlTable table;
3232
protected final JDBCType jdbcType;
33-
protected final boolean isDescending;
33+
protected final String descendingPhrase;
3434
protected final String alias;
3535
protected final String typeHandler;
3636
protected final RenderingStrategy renderingStrategy;
@@ -42,7 +42,7 @@ private SqlColumn(Builder<T> builder) {
4242
name = Objects.requireNonNull(builder.name);
4343
table = Objects.requireNonNull(builder.table);
4444
jdbcType = builder.jdbcType;
45-
isDescending = builder.isDescending;
45+
descendingPhrase = builder.descendingPhrase;
4646
alias = builder.alias;
4747
typeHandler = builder.typeHandler;
4848
renderingStrategy = builder.renderingStrategy;
@@ -87,7 +87,7 @@ public Object convertParameterType(T value) {
8787
@Override
8888
public SortSpecification descending() {
8989
Builder<T> b = copy();
90-
return b.withDescending(true).build();
90+
return b.withDescendingPhrase(" DESC").build(); //$NON-NLS-1$
9191
}
9292

9393
@Override
@@ -126,13 +126,8 @@ public SqlColumn<T> asCamelCase() {
126126
}
127127

128128
@Override
129-
public boolean isDescending() {
130-
return isDescending;
131-
}
132-
133-
@Override
134-
public String orderByName() {
135-
return alias().orElse(name);
129+
public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) {
130+
return FragmentAndParameters.fromFragment(alias().orElse(name) + descendingPhrase);
136131
}
137132

138133
@Override
@@ -188,7 +183,7 @@ private <S> Builder<S> copy() {
188183
.withName(this.name)
189184
.withTable(this.table)
190185
.withJdbcType(this.jdbcType)
191-
.withDescending(this.isDescending)
186+
.withDescendingPhrase(this.descendingPhrase)
192187
.withAlias(this.alias)
193188
.withTypeHandler(this.typeHandler)
194189
.withRenderingStrategy(this.renderingStrategy)
@@ -214,7 +209,7 @@ public static class Builder<T> {
214209
protected String name;
215210
protected SqlTable table;
216211
protected JDBCType jdbcType;
217-
protected boolean isDescending = false;
212+
protected String descendingPhrase = ""; //$NON-NLS-1$
218213
protected String alias;
219214
protected String typeHandler;
220215
protected RenderingStrategy renderingStrategy;
@@ -237,8 +232,8 @@ public Builder<T> withJdbcType(JDBCType jdbcType) {
237232
return this;
238233
}
239234

240-
public Builder<T> withDescending(boolean isDescending) {
241-
this.isDescending = isDescending;
235+
public Builder<T> withDescendingPhrase(String descendingPhrase) {
236+
this.descendingPhrase = descendingPhrase;
242237
return this;
243238
}
244239

src/main/java/org/mybatis/dynamic/sql/common/OrderByRenderer.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@
1515
*/
1616
package org.mybatis.dynamic.sql.common;
1717

18+
import java.util.Objects;
1819
import java.util.stream.Collectors;
1920

20-
import org.mybatis.dynamic.sql.SortSpecification;
21+
import org.mybatis.dynamic.sql.render.RenderingContext;
2122
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
23+
import org.mybatis.dynamic.sql.util.FragmentCollector;
2224

2325
public class OrderByRenderer {
24-
public FragmentAndParameters render(OrderByModel orderByModel) {
25-
String phrase = orderByModel.columns()
26-
.map(this::calculateOrderByPhrase)
27-
.collect(Collectors.joining(", ", "order by ", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
28-
return FragmentAndParameters.fromFragment(phrase);
26+
private final RenderingContext renderingContext;
27+
28+
public OrderByRenderer(RenderingContext renderingContext) {
29+
this.renderingContext = Objects.requireNonNull(renderingContext);
2930
}
3031

31-
private String calculateOrderByPhrase(SortSpecification column) {
32-
String phrase = column.orderByName();
33-
if (column.isDescending()) {
34-
phrase = phrase + " DESC"; //$NON-NLS-1$
35-
}
36-
return phrase;
32+
public FragmentAndParameters render(OrderByModel orderByModel) {
33+
return orderByModel.columns().map(c -> c.renderForOrderBy(renderingContext))
34+
.collect(FragmentCollector.collect())
35+
.toFragmentAndParameters(
36+
Collectors.joining(", ", "order by ", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
3737
}
3838
}

src/main/java/org/mybatis/dynamic/sql/delete/render/DeleteRenderer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ private Optional<FragmentAndParameters> calculateOrderByClause() {
9696
}
9797

9898
private FragmentAndParameters renderOrderByClause(OrderByModel orderByModel) {
99-
return new OrderByRenderer().render(orderByModel);
99+
return new OrderByRenderer(renderingContext).render(orderByModel);
100100
}
101101

102102
public static Builder withDeleteModel(DeleteModel deleteModel) {

src/main/java/org/mybatis/dynamic/sql/insert/BatchInsertDSL.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ public BatchInsertModel<T> build() {
5858
}
5959

6060
@SafeVarargs
61-
public static <T> IntoGatherer<T> insert(T... records) {
62-
return BatchInsertDSL.insert(Arrays.asList(records));
61+
public static <T> BatchInsertDSL.IntoGatherer<T> insert(T... records) {
62+
return insert(Arrays.asList(records));
6363
}
6464

65-
public static <T> IntoGatherer<T> insert(Collection<T> records) {
65+
public static <T> BatchInsertDSL.IntoGatherer<T> insert(Collection<T> records) {
6666
return new IntoGatherer<>(records);
6767
}
6868

src/main/java/org/mybatis/dynamic/sql/insert/MultiRowInsertDSL.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ public MultiRowInsertModel<T> build() {
5757
}
5858

5959
@SafeVarargs
60-
public static <T> IntoGatherer<T> insert(T... records) {
61-
return MultiRowInsertDSL.insert(Arrays.asList(records));
60+
public static <T> MultiRowInsertDSL.IntoGatherer<T> insert(T... records) {
61+
return insert(Arrays.asList(records));
6262
}
6363

64-
public static <T> IntoGatherer<T> insert(Collection<T> records) {
64+
public static <T> MultiRowInsertDSL.IntoGatherer<T> insert(Collection<T> records) {
6565
return new IntoGatherer<>(records);
6666
}
6767

src/main/java/org/mybatis/dynamic/sql/insert/render/BatchInsert.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import java.util.Collections;
2020
import java.util.List;
2121
import java.util.Objects;
22-
import java.util.stream.Collectors;
2322

2423
public class BatchInsert<T> {
2524
private final String insertStatement;
@@ -38,7 +37,7 @@ private BatchInsert(Builder<T> builder) {
3837
public List<InsertStatementProvider<T>> insertStatements() {
3938
return records.stream()
4039
.map(this::toInsertStatement)
41-
.collect(Collectors.toList());
40+
.toList();
4241
}
4342

4443
private InsertStatementProvider<T> toInsertStatement(T row) {
@@ -57,7 +56,7 @@ public String getInsertStatementSQL() {
5756
}
5857

5958
public List<T> getRecords() {
60-
return Collections.unmodifiableList(records);
59+
return records;
6160
}
6261

6362
public static <T> Builder<T> withRecords(List<T> records) {

0 commit comments

Comments
 (0)