Skip to content

Commit c1d7eb3

Browse files
committed
Support the ORDER BY clause for the UNION set operation
1 parent b5b453e commit c1d7eb3

File tree

17 files changed

+263
-31
lines changed

17 files changed

+263
-31
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.seasar.doma.jdbc.criteria.context;
2+
3+
import java.util.Objects;
4+
import org.seasar.doma.jdbc.criteria.def.PropertyDef;
5+
6+
public interface OrderByItem {
7+
8+
void accept(Visitor visitor);
9+
10+
class Name implements OrderByItem {
11+
public final PropertyDef<?> value;
12+
13+
public Name(PropertyDef<?> value) {
14+
Objects.requireNonNull(value);
15+
this.value = value;
16+
}
17+
18+
@Override
19+
public void accept(Visitor visitor) {
20+
visitor.visit(this);
21+
}
22+
}
23+
24+
class Index implements OrderByItem {
25+
public final int value;
26+
27+
public Index(int value) {
28+
this.value = value;
29+
}
30+
31+
@Override
32+
public void accept(Visitor visitor) {
33+
visitor.visit(this);
34+
}
35+
}
36+
37+
interface Visitor {
38+
void visit(Name name);
39+
40+
void visit(Index index);
41+
}
42+
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/context/SelectContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class SelectContext implements Context {
2121
public List<Criterion> where = new ArrayList<>();
2222
public final List<PropertyDef<?>> groupBy = new ArrayList<>();
2323
public List<Criterion> having = new ArrayList<>();
24-
public final List<Pair<PropertyDef<?>, String>> orderBy = new ArrayList<>();
24+
public final List<Pair<OrderByItem, String>> orderBy = new ArrayList<>();
2525
public Integer limit;
2626
public Integer offset;
2727
public ForUpdate forUpdate;

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/context/SetOperationContext.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package org.seasar.doma.jdbc.criteria.context;
22

3+
import java.util.ArrayList;
4+
import java.util.List;
35
import java.util.Objects;
6+
import org.seasar.doma.internal.util.Pair;
47

58
public interface SetOperationContext<ELEMENT> {
69

@@ -23,6 +26,7 @@ public <R> R accept(Visitor<R> visitor) {
2326
class Union<ELEMENT> implements SetOperationContext<ELEMENT> {
2427
public final SetOperationContext<ELEMENT> left;
2528
public final SetOperationContext<ELEMENT> right;
29+
public final List<Pair<OrderByItem.Index, String>> orderBy = new ArrayList<>();
2630

2731
public Union(SetOperationContext<ELEMENT> left, SetOperationContext<ELEMENT> right) {
2832
Objects.requireNonNull(left);
@@ -40,6 +44,7 @@ public <R> R accept(Visitor<R> visitor) {
4044
class UnionAll<ELEMENT> implements SetOperationContext<ELEMENT> {
4145
public final SetOperationContext<ELEMENT> left;
4246
public final SetOperationContext<ELEMENT> right;
47+
public final List<Pair<OrderByItem.Index, String>> orderBy = new ArrayList<>();
4348

4449
public UnionAll(SetOperationContext<ELEMENT> left, SetOperationContext<ELEMENT> right) {
4550
Objects.requireNonNull(left);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package org.seasar.doma.jdbc.criteria.declaration;
2+
3+
import java.util.Objects;
4+
import org.seasar.doma.internal.util.Pair;
5+
import org.seasar.doma.jdbc.criteria.context.OrderByItem;
6+
import org.seasar.doma.jdbc.criteria.context.SetOperationContext;
7+
8+
public class OrderByIndexDeclaration {
9+
10+
private final SetOperationContext<?> context;
11+
12+
public OrderByIndexDeclaration(SetOperationContext<?> context) {
13+
Objects.requireNonNull(context);
14+
this.context = context;
15+
}
16+
17+
public void asc(int index) {
18+
add(new Pair<>(new OrderByItem.Index(index), "asc"));
19+
}
20+
21+
public void desc(int index) {
22+
add(new Pair<>(new OrderByItem.Index(index), "desc"));
23+
}
24+
25+
private void add(Pair<OrderByItem.Index, String> pair) {
26+
context.accept(
27+
new SetOperationContext.Visitor<Void>() {
28+
@Override
29+
public Void visit(SetOperationContext.Select<?> select) {
30+
return null;
31+
}
32+
33+
@Override
34+
public Void visit(SetOperationContext.Union<?> union) {
35+
union.orderBy.add(pair);
36+
return null;
37+
}
38+
39+
@Override
40+
public Void visit(SetOperationContext.UnionAll<?> unionAll) {
41+
unionAll.orderBy.add(pair);
42+
return null;
43+
}
44+
});
45+
}
46+
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/declaration/OrderByDeclaration.java renamed to doma-core/src/main/java/org/seasar/doma/jdbc/criteria/declaration/OrderByNameDeclaration.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,28 @@
22

33
import java.util.Objects;
44
import org.seasar.doma.internal.util.Pair;
5+
import org.seasar.doma.jdbc.criteria.context.OrderByItem;
56
import org.seasar.doma.jdbc.criteria.context.SelectContext;
67
import org.seasar.doma.jdbc.criteria.def.PropertyDef;
78

8-
public class OrderByDeclaration {
9+
public class OrderByNameDeclaration {
910

1011
private final SelectContext context;
1112

12-
public OrderByDeclaration(SelectContext context) {
13+
public OrderByNameDeclaration(SelectContext context) {
1314
Objects.requireNonNull(context);
1415
this.context = context;
1516
}
1617

1718
public void asc(PropertyDef<?> propertyDef) {
1819
Objects.requireNonNull(propertyDef);
19-
Pair<PropertyDef<?>, String> pair = new Pair<>(propertyDef, "asc");
20+
Pair<OrderByItem, String> pair = new Pair<>(new OrderByItem.Name(propertyDef), "asc");
2021
context.orderBy.add(pair);
2122
}
2223

2324
public void desc(PropertyDef<?> propertyDef) {
2425
Objects.requireNonNull(propertyDef);
25-
Pair<PropertyDef<?>, String> pair = new Pair<>(propertyDef, "desc");
26+
Pair<OrderByItem, String> pair = new Pair<>(new OrderByItem.Name(propertyDef), "desc");
2627
context.orderBy.add(pair);
2728
}
2829
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/declaration/SelectFromDeclaration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ public void having(Consumer<HavingDeclaration> block) {
7070
block.accept(declaration);
7171
}
7272

73-
public void orderBy(Consumer<OrderByDeclaration> block) {
73+
public void orderBy(Consumer<OrderByNameDeclaration> block) {
7474
Objects.requireNonNull(block);
75-
OrderByDeclaration declaration = new OrderByDeclaration(context);
75+
OrderByNameDeclaration declaration = new OrderByNameDeclaration(context);
7676
block.accept(declaration);
7777
}
7878

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/declaration/SubSelectFromDeclaration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public SubSelectFromDeclaration where(Consumer<WhereDeclaration> block) {
3636
return this;
3737
}
3838

39-
public SubSelectFromDeclaration orderBy(Consumer<OrderByDeclaration> block) {
39+
public SubSelectFromDeclaration orderBy(Consumer<OrderByNameDeclaration> block) {
4040
declaration.orderBy(block);
4141
return this;
4242
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/query/SelectBuilder.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.seasar.doma.jdbc.criteria.context.Criterion;
1616
import org.seasar.doma.jdbc.criteria.context.Join;
1717
import org.seasar.doma.jdbc.criteria.context.JoinKind;
18+
import org.seasar.doma.jdbc.criteria.context.OrderByItem;
1819
import org.seasar.doma.jdbc.criteria.context.SelectContext;
1920
import org.seasar.doma.jdbc.criteria.declaration.AggregateFunction;
2021
import org.seasar.doma.jdbc.criteria.def.EntityDef;
@@ -166,8 +167,20 @@ private void having() {
166167
private void orderBy() {
167168
if (!context.orderBy.isEmpty()) {
168169
buf.appendSql(" order by ");
169-
for (Pair<PropertyDef<?>, String> pair : context.orderBy) {
170-
column(pair.fst);
170+
for (Pair<OrderByItem, String> pair : context.orderBy) {
171+
pair.fst.accept(
172+
new OrderByItem.Visitor() {
173+
174+
@Override
175+
public void visit(OrderByItem.Name name) {
176+
column(name.value);
177+
}
178+
179+
@Override
180+
public void visit(OrderByItem.Index index) {
181+
buf.appendSql(String.valueOf(index.value));
182+
}
183+
});
171184
buf.appendSql(" " + pair.snd + ", ");
172185
}
173186
buf.cutBackSql(2);

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/query/SetOperationBuilder.java

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package org.seasar.doma.jdbc.criteria.query;
22

3+
import java.util.List;
34
import java.util.Objects;
45
import java.util.function.Function;
56
import org.seasar.doma.internal.jdbc.sql.PreparedSqlBuilder;
7+
import org.seasar.doma.internal.util.Pair;
68
import org.seasar.doma.jdbc.Config;
79
import org.seasar.doma.jdbc.PreparedSql;
810
import org.seasar.doma.jdbc.SqlKind;
911
import org.seasar.doma.jdbc.SqlLogType;
12+
import org.seasar.doma.jdbc.criteria.context.OrderByItem;
1013
import org.seasar.doma.jdbc.criteria.context.SelectContext;
1114
import org.seasar.doma.jdbc.criteria.context.SetOperationContext;
1215

@@ -22,13 +25,10 @@ public SetOperationBuilder(
2225
SetOperationContext<?> context,
2326
Function<String, String> commenter,
2427
SqlLogType sqlLogType) {
25-
Objects.requireNonNull(config);
26-
Objects.requireNonNull(context);
27-
Objects.requireNonNull(commenter);
28+
this.config = Objects.requireNonNull(config);
29+
this.context = Objects.requireNonNull(context);
30+
this.commenter = Objects.requireNonNull(commenter);
2831
Objects.requireNonNull(sqlLogType);
29-
this.config = config;
30-
this.context = context;
31-
this.commenter = commenter;
3232
this.buf = new PreparedSqlBuilder(config, SqlKind.SELECT, sqlLogType);
3333
}
3434

@@ -46,19 +46,49 @@ public Void visit(SetOperationContext.Select<?> select) {
4646

4747
@Override
4848
public Void visit(SetOperationContext.Union<?> union) {
49-
union.left.accept(this);
50-
buf.appendSql(" union ");
51-
union.right.accept(this);
49+
union("union", union.left, union.right, union.orderBy);
5250
return null;
5351
}
5452

5553
@Override
5654
public Void visit(SetOperationContext.UnionAll<?> unionAll) {
57-
unionAll.left.accept(this);
58-
buf.appendSql(" union all ");
59-
unionAll.right.accept(this);
55+
union("union all", unionAll.left, unionAll.right, unionAll.orderBy);
6056
return null;
6157
}
58+
59+
private void union(
60+
String op,
61+
SetOperationContext<?> left,
62+
SetOperationContext<?> right,
63+
List<Pair<OrderByItem.Index, String>> orderBy) {
64+
String open;
65+
String close;
66+
if (orderBy.isEmpty()) {
67+
open = "";
68+
close = "";
69+
} else {
70+
open = "(";
71+
close = ")";
72+
}
73+
buf.appendSql(open);
74+
left.accept(this);
75+
buf.appendSql(close + " " + op + " " + open);
76+
right.accept(this);
77+
buf.appendSql(close);
78+
orderBy(orderBy);
79+
}
80+
81+
private void orderBy(List<Pair<OrderByItem.Index, String>> orderBy) {
82+
if (!orderBy.isEmpty()) {
83+
buf.appendSql(" order by ");
84+
for (Pair<OrderByItem.Index, String> pair : orderBy) {
85+
OrderByItem.Index index = pair.fst;
86+
buf.appendSql(String.valueOf(index.value));
87+
buf.appendSql(" " + pair.snd + ", ");
88+
}
89+
buf.cutBackSql(2);
90+
}
91+
}
6292
});
6393
return buf.build(commenter);
6494
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/statement/AbstractSetOperand.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@ protected AbstractSetOperand(
2020
}
2121

2222
@Override
23-
public SetOperand<ELEMENT> union(SetOperand<ELEMENT> other) {
23+
public SetOperator<ELEMENT> union(SetOperand<ELEMENT> other) {
2424
Objects.requireNonNull(other);
2525
SetOperationContext<ELEMENT> newContext =
2626
new SetOperationContext.Union<>(getContext(), other.getContext());
2727
return new NativeSqlSetStarting<>(config, newContext, objectProviderFactory);
2828
}
2929

3030
@Override
31-
public SetOperand<ELEMENT> unionAll(SetOperand<ELEMENT> other) {
31+
public SetOperator<ELEMENT> unionAll(SetOperand<ELEMENT> other) {
3232
Objects.requireNonNull(other);
3333
SetOperationContext<ELEMENT> newContext =
3434
new SetOperationContext.UnionAll<>(getContext(), other.getContext());

0 commit comments

Comments
 (0)