1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.dynamic.sql.select;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collection;
21 import java.util.List;
22 import java.util.Optional;
23 import java.util.function.Consumer;
24
25 import org.jspecify.annotations.Nullable;
26 import org.mybatis.dynamic.sql.SortSpecification;
27 import org.mybatis.dynamic.sql.common.OrderByModel;
28 import org.mybatis.dynamic.sql.configuration.StatementConfiguration;
29 import org.mybatis.dynamic.sql.util.Buildable;
30 import org.mybatis.dynamic.sql.util.ConfigurableStatement;
31
32 public class MultiSelectDSL implements Buildable<MultiSelectModel>, ConfigurableStatement<MultiSelectDSL> {
33 private final List<UnionQuery> unionQueries = new ArrayList<>();
34 private final SelectModel initialSelect;
35 private @Nullable OrderByModel orderByModel;
36 private @Nullable Long limit;
37 private @Nullable Long offset;
38 private @Nullable Long fetchFirstRows;
39 private final StatementConfiguration statementConfiguration = new StatementConfiguration();
40
41 public MultiSelectDSL(Buildable<SelectModel> builder) {
42 initialSelect = builder.build();
43 }
44
45 public MultiSelectDSL union(Buildable<SelectModel> builder) {
46 unionQueries.add(new UnionQuery("union", builder.build()));
47 return this;
48 }
49
50 public MultiSelectDSL unionAll(Buildable<SelectModel> builder) {
51 unionQueries.add(new UnionQuery("union all", builder.build()));
52 return this;
53 }
54
55 public MultiSelectDSL orderBy(SortSpecification... columns) {
56 return orderBy(Arrays.asList(columns));
57 }
58
59 public MultiSelectDSL orderBy(Collection<? extends SortSpecification> columns) {
60 orderByModel = OrderByModel.of(columns);
61 return this;
62 }
63
64 public MultiSelectDSL.LimitFinisher limit(long limit) {
65 return limitWhenPresent(limit);
66 }
67
68 public MultiSelectDSL.LimitFinisher limitWhenPresent(@Nullable Long limit) {
69 this.limit = limit;
70 return new LimitFinisher();
71 }
72
73 public MultiSelectDSL.OffsetFirstFinisher offset(long offset) {
74 return offsetWhenPresent(offset);
75 }
76
77 public MultiSelectDSL.OffsetFirstFinisher offsetWhenPresent(@Nullable Long offset) {
78 this.offset = offset;
79 return new OffsetFirstFinisher();
80 }
81
82 public MultiSelectDSL.FetchFirstFinisher fetchFirst(long fetchFirstRows) {
83 return fetchFirstWhenPresent(fetchFirstRows);
84 }
85
86 public MultiSelectDSL.FetchFirstFinisher fetchFirstWhenPresent(@Nullable Long fetchFirstRows) {
87 this.fetchFirstRows = fetchFirstRows;
88 return new FetchFirstFinisher();
89 }
90
91 @Override
92 public MultiSelectModel build() {
93 return new MultiSelectModel.Builder()
94 .withInitialSelect(initialSelect)
95 .withUnionQueries(unionQueries)
96 .withOrderByModel(orderByModel)
97 .withPagingModel(buildPagingModel().orElse(null))
98 .withStatementConfiguration(statementConfiguration)
99 .build();
100 }
101
102 private Optional<PagingModel> buildPagingModel() {
103 return new PagingModel.Builder()
104 .withLimit(limit)
105 .withOffset(offset)
106 .withFetchFirstRows(fetchFirstRows)
107 .build();
108 }
109
110 @Override
111 public MultiSelectDSL configureStatement(Consumer<StatementConfiguration> consumer) {
112 consumer.accept(statementConfiguration);
113 return this;
114 }
115
116 public class OffsetFirstFinisher implements Buildable<MultiSelectModel> {
117 public FetchFirstFinisher fetchFirst(long fetchFirstRows) {
118 return fetchFirstWhenPresent(fetchFirstRows);
119 }
120
121 public FetchFirstFinisher fetchFirstWhenPresent(@Nullable Long fetchFirstRows) {
122 MultiSelectDSL.this.fetchFirstRows = fetchFirstRows;
123 return new FetchFirstFinisher();
124 }
125
126 @Override
127 public MultiSelectModel build() {
128 return MultiSelectDSL.this.build();
129 }
130 }
131
132 public class LimitFinisher implements Buildable<MultiSelectModel> {
133 public MultiSelectDSL offset(long offset) {
134 return offsetWhenPresent(offset);
135 }
136
137 public MultiSelectDSL offsetWhenPresent(@Nullable Long offset) {
138 MultiSelectDSL.this.offset = offset;
139 return MultiSelectDSL.this;
140 }
141
142 @Override
143 public MultiSelectModel build() {
144 return MultiSelectDSL.this.build();
145 }
146 }
147
148 public class FetchFirstFinisher {
149 public MultiSelectDSL rowsOnly() {
150 return MultiSelectDSL.this;
151 }
152 }
153 }