Skip to content

Commit 714ee84

Browse files
committed
Add order by on update statement
1 parent f09e604 commit 714ee84

File tree

4 files changed

+135
-1
lines changed

4 files changed

+135
-1
lines changed

src/main/java/org/mybatis/dynamic/sql/update/UpdateDSL.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
package org.mybatis.dynamic.sql.update;
1717

1818
import java.util.ArrayList;
19+
import java.util.Arrays;
20+
import java.util.Collection;
1921
import java.util.List;
2022
import java.util.Objects;
2123
import java.util.function.Consumer;
@@ -24,8 +26,10 @@
2426

2527
import org.jetbrains.annotations.NotNull;
2628
import org.mybatis.dynamic.sql.BasicColumn;
29+
import org.mybatis.dynamic.sql.SortSpecification;
2730
import org.mybatis.dynamic.sql.SqlColumn;
2831
import org.mybatis.dynamic.sql.SqlTable;
32+
import org.mybatis.dynamic.sql.common.OrderByModel;
2933
import org.mybatis.dynamic.sql.configuration.StatementConfiguration;
3034
import org.mybatis.dynamic.sql.select.SelectModel;
3135
import org.mybatis.dynamic.sql.util.AbstractColumnMapping;
@@ -52,6 +56,7 @@ public class UpdateDSL<R> extends AbstractWhereSupport<UpdateDSL<R>.UpdateWhereB
5256
private UpdateWhereBuilder whereBuilder;
5357
private final StatementConfiguration statementConfiguration = new StatementConfiguration();
5458
private Long limit;
59+
private OrderByModel orderByModel;
5560

5661
private UpdateDSL(SqlTable table, String tableAlias, Function<UpdateModel, R> adapterFunction) {
5762
this.table = Objects.requireNonNull(table);
@@ -77,6 +82,15 @@ public UpdateDSL<R> limit(long limit) {
7782
return this;
7883
}
7984

85+
public UpdateDSL<R> orderBy(SortSpecification... columns) {
86+
return orderBy(Arrays.asList(columns));
87+
}
88+
89+
public UpdateDSL<R> orderBy(Collection<SortSpecification> columns) {
90+
orderByModel = OrderByModel.of(columns);
91+
return this;
92+
}
93+
8094
/**
8195
* WARNING! Calling this method could result in an update statement that updates
8296
* all rows in a table.
@@ -89,7 +103,8 @@ public R build() {
89103
UpdateModel.Builder updateModelBuilder = UpdateModel.withTable(table)
90104
.withTableAlias(tableAlias)
91105
.withColumnMappings(columnMappings)
92-
.withLimit(limit);
106+
.withLimit(limit)
107+
.withOrderByModel(orderByModel);
93108

94109
if (whereBuilder != null) {
95110
updateModelBuilder.withWhereModel(whereBuilder.buildWhereModel());
@@ -187,6 +202,15 @@ public UpdateDSL<R> limit(long limit) {
187202
return UpdateDSL.this.limit(limit);
188203
}
189204

205+
public UpdateDSL<R> orderBy(SortSpecification... columns) {
206+
return orderBy(Arrays.asList(columns));
207+
}
208+
209+
public UpdateDSL<R> orderBy(Collection<SortSpecification> columns) {
210+
orderByModel = OrderByModel.of(columns);
211+
return UpdateDSL.this;
212+
}
213+
190214
@NotNull
191215
@Override
192216
public R build() {

src/main/java/org/mybatis/dynamic/sql/update/UpdateModel.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.jetbrains.annotations.NotNull;
2626
import org.mybatis.dynamic.sql.SqlTable;
27+
import org.mybatis.dynamic.sql.common.OrderByModel;
2728
import org.mybatis.dynamic.sql.exception.InvalidSqlException;
2829
import org.mybatis.dynamic.sql.render.RenderingStrategy;
2930
import org.mybatis.dynamic.sql.update.render.UpdateRenderer;
@@ -38,13 +39,15 @@ public class UpdateModel {
3839
private final WhereModel whereModel;
3940
private final List<AbstractColumnMapping> columnMappings;
4041
private final Long limit;
42+
private final OrderByModel orderByModel;
4143

4244
private UpdateModel(Builder builder) {
4345
table = Objects.requireNonNull(builder.table);
4446
whereModel = builder.whereModel;
4547
columnMappings = Objects.requireNonNull(builder.columnMappings);
4648
tableAlias = builder.tableAlias;
4749
limit = builder.limit;
50+
orderByModel = builder.orderByModel;
4851

4952
if (columnMappings.isEmpty()) {
5053
throw new InvalidSqlException(Messages.getString("ERROR.17")); //$NON-NLS-1$
@@ -71,6 +74,10 @@ public Optional<Long> limit() {
7174
return Optional.ofNullable(limit);
7275
}
7376

77+
public Optional<OrderByModel> orderByModel() {
78+
return Optional.ofNullable(orderByModel);
79+
}
80+
7481
@NotNull
7582
public UpdateStatementProvider render(RenderingStrategy renderingStrategy) {
7683
return UpdateRenderer.withUpdateModel(this)
@@ -89,6 +96,7 @@ public static class Builder {
8996
private WhereModel whereModel;
9097
private final List<AbstractColumnMapping> columnMappings = new ArrayList<>();
9198
private Long limit;
99+
private OrderByModel orderByModel;
92100

93101
public Builder withTable(SqlTable table) {
94102
this.table = table;
@@ -115,6 +123,11 @@ public Builder withLimit(Long limit) {
115123
return this;
116124
}
117125

126+
public Builder withOrderByModel(OrderByModel orderByModel) {
127+
this.orderByModel = orderByModel;
128+
return this;
129+
}
130+
118131
public UpdateModel build() {
119132
return new UpdateModel(this);
120133
}

src/main/java/org/mybatis/dynamic/sql/update/render/UpdateRenderer.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.util.stream.Collectors;
2323

2424
import org.mybatis.dynamic.sql.SqlTable;
25+
import org.mybatis.dynamic.sql.common.OrderByModel;
26+
import org.mybatis.dynamic.sql.common.OrderByRenderer;
2527
import org.mybatis.dynamic.sql.exception.InvalidSqlException;
2628
import org.mybatis.dynamic.sql.render.ExplicitTableAliasCalculator;
2729
import org.mybatis.dynamic.sql.render.RenderingStrategy;
@@ -53,6 +55,7 @@ public UpdateStatementProvider render() {
5355
fragmentCollector.add(calculateUpdateStatementStart());
5456
fragmentCollector.add(calculateSetPhrase());
5557
calculateWhereClause().ifPresent(fragmentCollector::add);
58+
calculateOrderByClause().ifPresent(fragmentCollector::add);
5659
calculateLimitClause().ifPresent(fragmentCollector::add);
5760

5861
return toUpdateStatementProvider(fragmentCollector);
@@ -128,6 +131,14 @@ private FragmentAndParameters renderLimitClause(Long limit) {
128131
.build();
129132
}
130133

134+
private Optional<FragmentAndParameters> calculateOrderByClause() {
135+
return updateModel.orderByModel().map(this::renderOrderByClause);
136+
}
137+
138+
private FragmentAndParameters renderOrderByClause(OrderByModel orderByModel) {
139+
return new OrderByRenderer().render(orderByModel);
140+
}
141+
131142
public static Builder withUpdateModel(UpdateModel updateModel) {
132143
return new Builder().withUpdateModel(updateModel);
133144
}

src/test/java/examples/mariadb/MariaDBTest.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,47 @@ void testUpdateWithLimit() {
231231
}
232232
}
233233

234+
@Test
235+
void testUpdateWithOrderBy() {
236+
try (SqlSession session = sqlSessionFactory.openSession()) {
237+
CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
238+
239+
UpdateStatementProvider updateStatement = update(items)
240+
.set(amount).equalTo(add(amount, constant("100")))
241+
.orderBy(amount.descending())
242+
.build()
243+
.render(RenderingStrategies.MYBATIS3);
244+
245+
assertThat(updateStatement.getUpdateStatement())
246+
.isEqualTo("update items set amount = (amount + 100) order by amount DESC");
247+
assertThat(updateStatement.getParameters()).isEmpty();
248+
249+
int rows = mapper.update(updateStatement);
250+
assertThat(rows).isEqualTo(20);
251+
}
252+
}
253+
254+
@Test
255+
void testUpdateWithOrderByAndLimit() {
256+
try (SqlSession session = sqlSessionFactory.openSession()) {
257+
CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
258+
259+
UpdateStatementProvider updateStatement = update(items)
260+
.set(amount).equalTo(add(amount, constant("100")))
261+
.orderBy(amount.descending())
262+
.limit(5)
263+
.build()
264+
.render(RenderingStrategies.MYBATIS3);
265+
266+
String expected = "update items set amount = (amount + 100) order by amount DESC limit #{parameters.p1}";
267+
assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
268+
assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 5L));
269+
270+
int rows = mapper.update(updateStatement);
271+
assertThat(rows).isEqualTo(5);
272+
}
273+
}
274+
234275
@Test
235276
void testUpdateWithWhereAndLimit() {
236277
try (SqlSession session = sqlSessionFactory.openSession()) {
@@ -252,4 +293,49 @@ void testUpdateWithWhereAndLimit() {
252293
assertThat(rows).isEqualTo(5);
253294
}
254295
}
296+
297+
@Test
298+
void testUpdateWithWhereAndOrderBy() {
299+
try (SqlSession session = sqlSessionFactory.openSession()) {
300+
CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
301+
302+
UpdateStatementProvider updateStatement = update(items)
303+
.set(amount).equalTo(add(amount, constant("100")))
304+
.where(id, isLessThan(10))
305+
.orderBy(amount.descending())
306+
.build()
307+
.render(RenderingStrategies.MYBATIS3);
308+
309+
String expected = "update items set amount = (amount + 100) where id < #{parameters.p1,jdbcType=INTEGER} "
310+
+ "order by amount DESC";
311+
assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
312+
assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 10));
313+
314+
int rows = mapper.update(updateStatement);
315+
assertThat(rows).isEqualTo(9);
316+
}
317+
}
318+
319+
@Test
320+
void testUpdateWithWhereAndOrderByAndLimit() {
321+
try (SqlSession session = sqlSessionFactory.openSession()) {
322+
CommonUpdateMapper mapper = session.getMapper(CommonUpdateMapper.class);
323+
324+
UpdateStatementProvider updateStatement = update(items)
325+
.set(amount).equalTo(add(amount, constant("100")))
326+
.where(id, isLessThan(10))
327+
.orderBy(amount)
328+
.limit(5)
329+
.build()
330+
.render(RenderingStrategies.MYBATIS3);
331+
332+
String expected = "update items set amount = (amount + 100) where id < #{parameters.p1,jdbcType=INTEGER} "
333+
+ "order by amount limit #{parameters.p2}";
334+
assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected);
335+
assertThat(updateStatement.getParameters()).containsOnly(entry("p1", 10), entry("p2", 5L));
336+
337+
int rows = mapper.update(updateStatement);
338+
assertThat(rows).isEqualTo(5);
339+
}
340+
}
255341
}

0 commit comments

Comments
 (0)