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.Objects;
23 import java.util.function.Consumer;
24 import java.util.function.Function;
25
26 import org.jspecify.annotations.Nullable;
27 import org.mybatis.dynamic.sql.BasicColumn;
28 import org.mybatis.dynamic.sql.SortSpecification;
29 import org.mybatis.dynamic.sql.common.OrderByModel;
30 import org.mybatis.dynamic.sql.configuration.StatementConfiguration;
31 import org.mybatis.dynamic.sql.dsl.AbstractLimitAndOffsetSupport;
32 import org.mybatis.dynamic.sql.dsl.ForAndWaitOperations;
33 import org.mybatis.dynamic.sql.dsl.LimitAndOffsetOperations;
34 import org.mybatis.dynamic.sql.dsl.OrderByOperations;
35 import org.mybatis.dynamic.sql.util.Buildable;
36 import org.mybatis.dynamic.sql.util.ConfigurableStatement;
37 import org.mybatis.dynamic.sql.util.Validator;
38
39
40
41
42
43
44
45
46
47 public class SelectDSL<R> implements ForAndWaitOperations<SelectDSL<R>>,
48 LimitAndOffsetOperations<SelectDSL<R>, R>,
49 OrderByOperations<SelectDSL<R>>,
50 ConfigurableStatement<SelectDSL<R>>,
51 Buildable<R> {
52 private final Function<SelectModel, R> adapterFunction;
53 private final List<QueryExpressionDSL<R>> queryExpressions = new ArrayList<>();
54 private @Nullable OrderByModel orderByModel;
55 private final LimitAndOffsetSupport limitAndOffsetSupport = new LimitAndOffsetSupport();
56 final StatementConfiguration statementConfiguration = new StatementConfiguration();
57 private @Nullable String forClause;
58 private @Nullable String waitClause;
59
60 private SelectDSL(Function<SelectModel, R> adapterFunction) {
61 this.adapterFunction = Objects.requireNonNull(adapterFunction);
62 }
63
64 public static QueryExpressionDSL<SelectModel> select(BasicColumn... selectList) {
65 return select(Arrays.asList(selectList));
66 }
67
68 public static QueryExpressionDSL<SelectModel> select(Collection<? extends BasicColumn> selectList) {
69 return select(Function.identity(), selectList);
70 }
71
72 public static <R> QueryExpressionDSL<R> select(Function<SelectModel, R> adapterFunction,
73 BasicColumn... selectList) {
74 return select(adapterFunction, Arrays.asList(selectList));
75 }
76
77 public static <R> QueryExpressionDSL<R> select(Function<SelectModel, R> adapterFunction,
78 Collection<? extends BasicColumn> selectList) {
79 return new QueryExpressionDSL.Builder<R>()
80 .withSelectList(selectList)
81 .withSelectDSL(new SelectDSL<>(adapterFunction))
82 .build();
83 }
84
85 public static QueryExpressionDSL<SelectModel> selectDistinct(BasicColumn... selectList) {
86 return selectDistinct(Arrays.asList(selectList));
87 }
88
89 public static QueryExpressionDSL<SelectModel> selectDistinct(
90 Collection<? extends BasicColumn> selectList) {
91 return selectDistinct(Function.identity(), selectList);
92 }
93
94 public static <R> QueryExpressionDSL<R> selectDistinct(Function<SelectModel, R> adapterFunction,
95 BasicColumn... selectList) {
96 return selectDistinct(adapterFunction, Arrays.asList(selectList));
97 }
98
99 public static <R> QueryExpressionDSL<R> selectDistinct(Function<SelectModel, R> adapterFunction,
100 Collection<? extends BasicColumn> selectList) {
101 return new QueryExpressionDSL.Builder<R>()
102 .withSelectList(selectList)
103 .withSelectDSL(new SelectDSL<>(adapterFunction))
104 .isDistinct()
105 .build();
106 }
107
108 void registerQueryExpression(QueryExpressionDSL<R> queryExpression) {
109 queryExpressions.add(queryExpression);
110 }
111
112
113 @Override
114 public SelectDSL<R> orderBy(Collection<? extends SortSpecification> columns) {
115 orderByModel = OrderByModel.of(columns);
116 return this;
117 }
118
119 @Override
120 public LimitFinisher<SelectDSL<R>, R> limitWhenPresent(@Nullable Long limit) {
121 return limitAndOffsetSupport.limitWhenPresent(limit);
122 }
123
124 @Override
125 public OffsetFirstFinisher<SelectDSL<R>, R> offsetWhenPresent(@Nullable Long offset) {
126 return limitAndOffsetSupport.offsetWhenPresent(offset);
127 }
128
129 @Override
130 public FetchFirstFinisher<SelectDSL<R>> fetchFirstWhenPresent(@Nullable Long fetchFirstRows) {
131 return limitAndOffsetSupport.fetchFirstWhenPresent(fetchFirstRows);
132 }
133
134 @Override
135 public SelectDSL<R> setWaitClause(String waitClause) {
136 Validator.assertNull(this.waitClause, "ERROR.49");
137 this.waitClause = waitClause;
138 return this;
139 }
140
141 @Override
142 public SelectDSL<R> setForClause(String forClause) {
143 Validator.assertNull(this.forClause, "ERROR.48");
144 this.forClause = forClause;
145 return this;
146 }
147
148 @Override
149 public SelectDSL<R> configureStatement(Consumer<StatementConfiguration> consumer) {
150 consumer.accept(statementConfiguration);
151 return this;
152 }
153
154 @Override
155 public R build() {
156 SelectModel selectModel = SelectModel.withQueryExpressions(buildModels())
157 .withOrderByModel(orderByModel)
158 .withPagingModel(limitAndOffsetSupport.buildPagingModel())
159 .withStatementConfiguration(statementConfiguration)
160 .withForClause(forClause)
161 .withWaitClause(waitClause)
162 .build();
163 return adapterFunction.apply(selectModel);
164 }
165
166 private List<QueryExpressionModel> buildModels() {
167 return queryExpressions.stream()
168 .map(QueryExpressionDSL::buildModel)
169 .toList();
170 }
171
172 private class LimitAndOffsetSupport extends AbstractLimitAndOffsetSupport<SelectDSL<R>, R> {
173
174 protected LimitAndOffsetSupport() {
175 super(SelectDSL.this);
176 }
177
178 protected @Nullable PagingModel buildPagingModel() {
179 return toPagingModel().orElse(null);
180 }
181
182 @Override
183 protected SelectDSL<R> getThis() {
184 return SelectDSL.this;
185 }
186 }
187 }