Skip to content

Commit

Permalink
Merge pull request #830 from jeffgbutler/case-in-order-by
Browse files Browse the repository at this point in the history
Support CASE Expressions in ORDER BY Phrases
  • Loading branch information
jeffgbutler authored Aug 6, 2024
2 parents 028da50 + dca5d3d commit e2d75aa
Show file tree
Hide file tree
Showing 41 changed files with 750 additions and 115 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Significant changes:

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

## Release 1.5.2 - June 3, 2024

Expand Down
8 changes: 0 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,6 @@
<version>1.5.6</version>
<scope>test</scope>
</dependency>
<!-- Hamcrest is only here to make Infinitest happy. Not really used in the project. -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private <R> Collection<R> applyMapper(Function<? super T, ? extends R> mapper) {

private Collection<T> applyFilter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
return values.stream().filter(predicate).collect(Collectors.toList());
return values.stream().filter(predicate).toList();
}

protected <S extends AbstractListValueCondition<T>> S filterSupport(Predicate<? super T> predicate,
Expand Down
29 changes: 27 additions & 2 deletions src/main/java/org/mybatis/dynamic/sql/SortSpecification.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
*/
package org.mybatis.dynamic.sql;

import org.mybatis.dynamic.sql.exception.DynamicSqlException;
import org.mybatis.dynamic.sql.render.RenderingContext;
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
import org.mybatis.dynamic.sql.util.Messages;

/**
* Defines attributes of columns that are necessary for rendering an order by expression.
*
Expand All @@ -34,13 +39,33 @@ public interface SortSpecification {
* NOT include the "DESC" word for descending sort specifications.
*
* @return the order by phrase
* @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for
* removal in release 2.1
*/
String orderByName();
@Deprecated(since = "2.0", forRemoval = true)
default String orderByName() {
throw new DynamicSqlException(Messages.getString("ERROR.44")); //$NON-NLS-1$
}

/**
* Return true if the sort order is descending.
*
* @return true if the SortSpecification should render as descending
* @deprecated Please replace this method by overriding the more general "renderForOrderBy" method. Target for
* removal in release 2.1
*/
boolean isDescending();
@Deprecated(since = "2.0", forRemoval = true)
default boolean isDescending() {
throw new DynamicSqlException(Messages.getString("ERROR.44")); //$NON-NLS-1$
}

// the default implementation ensures compatibility with prior releases. When the
// deprecated methods are removed, this function can become purely abstract.
default FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) {
String phrase = orderByName();
if (isDescending()) {
phrase = phrase + " DESC"; //$NON-NLS-1$
}
return FragmentAndParameters.fromFragment(phrase);
}
}
23 changes: 9 additions & 14 deletions src/main/java/org/mybatis/dynamic/sql/SqlColumn.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class SqlColumn<T> implements BindableColumn<T>, SortSpecification {
protected final String name;
protected final SqlTable table;
protected final JDBCType jdbcType;
protected final boolean isDescending;
protected final String descendingPhrase;
protected final String alias;
protected final String typeHandler;
protected final RenderingStrategy renderingStrategy;
Expand All @@ -42,7 +42,7 @@ private SqlColumn(Builder<T> builder) {
name = Objects.requireNonNull(builder.name);
table = Objects.requireNonNull(builder.table);
jdbcType = builder.jdbcType;
isDescending = builder.isDescending;
descendingPhrase = builder.descendingPhrase;
alias = builder.alias;
typeHandler = builder.typeHandler;
renderingStrategy = builder.renderingStrategy;
Expand Down Expand Up @@ -87,7 +87,7 @@ public Object convertParameterType(T value) {
@Override
public SortSpecification descending() {
Builder<T> b = copy();
return b.withDescending(true).build();
return b.withDescendingPhrase(" DESC").build(); //$NON-NLS-1$
}

@Override
Expand Down Expand Up @@ -126,13 +126,8 @@ public SqlColumn<T> asCamelCase() {
}

@Override
public boolean isDescending() {
return isDescending;
}

@Override
public String orderByName() {
return alias().orElse(name);
public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) {
return FragmentAndParameters.fromFragment(alias().orElse(name) + descendingPhrase);
}

@Override
Expand Down Expand Up @@ -188,7 +183,7 @@ private <S> Builder<S> copy() {
.withName(this.name)
.withTable(this.table)
.withJdbcType(this.jdbcType)
.withDescending(this.isDescending)
.withDescendingPhrase(this.descendingPhrase)
.withAlias(this.alias)
.withTypeHandler(this.typeHandler)
.withRenderingStrategy(this.renderingStrategy)
Expand All @@ -214,7 +209,7 @@ public static class Builder<T> {
protected String name;
protected SqlTable table;
protected JDBCType jdbcType;
protected boolean isDescending = false;
protected String descendingPhrase = ""; //$NON-NLS-1$
protected String alias;
protected String typeHandler;
protected RenderingStrategy renderingStrategy;
Expand All @@ -237,8 +232,8 @@ public Builder<T> withJdbcType(JDBCType jdbcType) {
return this;
}

public Builder<T> withDescending(boolean isDescending) {
this.isDescending = isDescending;
public Builder<T> withDescendingPhrase(String descendingPhrase) {
this.descendingPhrase = descendingPhrase;
return this;
}

Expand Down
24 changes: 12 additions & 12 deletions src/main/java/org/mybatis/dynamic/sql/common/OrderByRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@
*/
package org.mybatis.dynamic.sql.common;

import java.util.Objects;
import java.util.stream.Collectors;

import org.mybatis.dynamic.sql.SortSpecification;
import org.mybatis.dynamic.sql.render.RenderingContext;
import org.mybatis.dynamic.sql.util.FragmentAndParameters;
import org.mybatis.dynamic.sql.util.FragmentCollector;

public class OrderByRenderer {
public FragmentAndParameters render(OrderByModel orderByModel) {
String phrase = orderByModel.columns()
.map(this::calculateOrderByPhrase)
.collect(Collectors.joining(", ", "order by ", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return FragmentAndParameters.fromFragment(phrase);
private final RenderingContext renderingContext;

public OrderByRenderer(RenderingContext renderingContext) {
this.renderingContext = Objects.requireNonNull(renderingContext);
}

private String calculateOrderByPhrase(SortSpecification column) {
String phrase = column.orderByName();
if (column.isDescending()) {
phrase = phrase + " DESC"; //$NON-NLS-1$
}
return phrase;
public FragmentAndParameters render(OrderByModel orderByModel) {
return orderByModel.columns().map(c -> c.renderForOrderBy(renderingContext))
.collect(FragmentCollector.collect())
.toFragmentAndParameters(
Collectors.joining(", ", "order by ", "")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private Optional<FragmentAndParameters> calculateOrderByClause() {
}

private FragmentAndParameters renderOrderByClause(OrderByModel orderByModel) {
return new OrderByRenderer().render(orderByModel);
return new OrderByRenderer(renderingContext).render(orderByModel);
}

public static Builder withDeleteModel(DeleteModel deleteModel) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ public BatchInsertModel<T> build() {
}

@SafeVarargs
public static <T> IntoGatherer<T> insert(T... records) {
return BatchInsertDSL.insert(Arrays.asList(records));
public static <T> BatchInsertDSL.IntoGatherer<T> insert(T... records) {
return insert(Arrays.asList(records));
}

public static <T> IntoGatherer<T> insert(Collection<T> records) {
public static <T> BatchInsertDSL.IntoGatherer<T> insert(Collection<T> records) {
return new IntoGatherer<>(records);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ public MultiRowInsertModel<T> build() {
}

@SafeVarargs
public static <T> IntoGatherer<T> insert(T... records) {
return MultiRowInsertDSL.insert(Arrays.asList(records));
public static <T> MultiRowInsertDSL.IntoGatherer<T> insert(T... records) {
return insert(Arrays.asList(records));
}

public static <T> IntoGatherer<T> insert(Collection<T> records) {
public static <T> MultiRowInsertDSL.IntoGatherer<T> insert(Collection<T> records) {
return new IntoGatherer<>(records);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class BatchInsert<T> {
private final String insertStatement;
Expand All @@ -38,7 +37,7 @@ private BatchInsert(Builder<T> builder) {
public List<InsertStatementProvider<T>> insertStatements() {
return records.stream()
.map(this::toInsertStatement)
.collect(Collectors.toList());
.toList();
}

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

public List<T> getRecords() {
return Collections.unmodifiableList(records);
return records;
}

public static <T> Builder<T> withRecords(List<T> records) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import org.mybatis.dynamic.sql.SqlTable;
import org.mybatis.dynamic.sql.TableExpression;
Expand Down Expand Up @@ -196,7 +195,7 @@ protected Optional<JoinModel> buildJoinModel() {

return Optional.of(JoinModel.of(joinSpecificationBuilders.stream()
.map(JoinSpecification.Builder::build)
.collect(Collectors.toList())));
.toList()));
}

protected void addTableAlias(SqlTable table, String tableAlias) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,31 @@

import org.mybatis.dynamic.sql.SortSpecification;
import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.render.RenderingContext;
import org.mybatis.dynamic.sql.util.FragmentAndParameters;

public class ColumnSortSpecification implements SortSpecification {
private final String tableAlias;
private final SqlColumn<?> column;
private final boolean isDescending;
private final String descendingPhrase;

public ColumnSortSpecification(String tableAlias, SqlColumn<?> column) {
this(tableAlias, column, false);
this(tableAlias, column, ""); //$NON-NLS-1$
}

private ColumnSortSpecification(String tableAlias, SqlColumn<?> column, boolean isDescending) {
private ColumnSortSpecification(String tableAlias, SqlColumn<?> column, String descendingPhrase) {
this.tableAlias = Objects.requireNonNull(tableAlias);
this.column = Objects.requireNonNull(column);
this.isDescending = isDescending;
this.descendingPhrase = descendingPhrase;
}

@Override
public SortSpecification descending() {
return new ColumnSortSpecification(tableAlias, column, true);
return new ColumnSortSpecification(tableAlias, column, " DESC"); //$NON-NLS-1$
}

@Override
public String orderByName() {
return tableAlias + "." + column.name(); //$NON-NLS-1$
}

@Override
public boolean isDescending() {
return isDescending;
public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) {
return FragmentAndParameters.fromFragment(tableAlias + "." + column.name() + descendingPhrase); //$NON-NLS-1$
}
}
3 changes: 1 addition & 2 deletions src/main/java/org/mybatis/dynamic/sql/select/SelectDSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.jetbrains.annotations.NotNull;
import org.mybatis.dynamic.sql.BasicColumn;
Expand Down Expand Up @@ -143,7 +142,7 @@ public R build() {
private List<QueryExpressionModel> buildModels() {
return queryExpressions.stream()
.map(QueryExpressionDSL::buildModel)
.collect(Collectors.toList());
.toList();
}

private Optional<PagingModel> buildPagingModel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.util.Objects;

import org.mybatis.dynamic.sql.SortSpecification;
import org.mybatis.dynamic.sql.render.RenderingContext;
import org.mybatis.dynamic.sql.util.FragmentAndParameters;

/**
* This class is used for an order by phrase where there is no suitable column name
Expand All @@ -28,30 +30,25 @@
public class SimpleSortSpecification implements SortSpecification {

private final String name;
private final boolean isDescending;
private final String descendingPhrase;

private SimpleSortSpecification(String name) {
this(name, false);
this(name, ""); //$NON-NLS-1$
}

private SimpleSortSpecification(String name, boolean isDescending) {
private SimpleSortSpecification(String name, String descendingPhrase) {
this.name = Objects.requireNonNull(name);
this.isDescending = isDescending;
this.descendingPhrase = descendingPhrase;
}

@Override
public SortSpecification descending() {
return new SimpleSortSpecification(name, true);
return new SimpleSortSpecification(name, " DESC"); //$NON-NLS-1$
}

@Override
public String orderByName() {
return name;
}

@Override
public boolean isDescending() {
return isDescending;
public FragmentAndParameters renderForOrderBy(RenderingContext renderingContext) {
return FragmentAndParameters.fromFragment(name + descendingPhrase);
}

public static SimpleSortSpecification of(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public SearchedCaseEnder else_(BasicColumn column) {
return new SearchedCaseEnder();
}

public BasicColumn end() {
public SearchedCaseModel end() {
return new SearchedCaseModel.Builder()
.withElseValue(elseValue)
.withWhenConditions(whenConditions)
Expand Down Expand Up @@ -100,7 +100,7 @@ protected WhenDSL getThis() {
}

public class SearchedCaseEnder {
public BasicColumn end() {
public SearchedCaseModel end() {
return SearchedCaseDSL.this.end();
}
}
Expand Down
Loading

0 comments on commit e2d75aa

Please sign in to comment.