• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mybatis / mybatis-dynamic-sql / 1877

02 Mar 2026 10:16PM UTC coverage: 99.981% (-0.02%) from 100.0%
1877

push

github

web-flow
Merge pull request #1058 from mybatis/renovate/github-codeql-action-digest

Update github/codeql-action digest to c793b71

196 of 196 branches covered (100.0%)

Branch coverage included in aggregate %.

5192 of 5193 relevant lines covered (99.98%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.68
/src/main/java/org/mybatis/dynamic/sql/select/CountDSL.java
1
/*
2
 *    Copyright 2016-2026 the original author or authors.
3
 *
4
 *    Licensed under the Apache License, Version 2.0 (the "License");
5
 *    you may not use this file except in compliance with the License.
6
 *    You may obtain a copy of the License at
7
 *
8
 *       https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 *    Unless required by applicable law or agreed to in writing, software
11
 *    distributed under the License is distributed on an "AS IS" BASIS,
12
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 *    See the License for the specific language governing permissions and
14
 *    limitations under the License.
15
 */
16
package org.mybatis.dynamic.sql.select;
17

18
import java.util.Objects;
19
import java.util.function.Consumer;
20
import java.util.function.Function;
21

22
import org.jspecify.annotations.Nullable;
23
import org.mybatis.dynamic.sql.BasicColumn;
24
import org.mybatis.dynamic.sql.SqlBuilder;
25
import org.mybatis.dynamic.sql.SqlTable;
26
import org.mybatis.dynamic.sql.configuration.StatementConfiguration;
27
import org.mybatis.dynamic.sql.dsl.AbstractBooleanOperationsFinisher;
28
import org.mybatis.dynamic.sql.dsl.AbstractJoinSpecificationFinisher;
29
import org.mybatis.dynamic.sql.dsl.AbstractQueryingDSL;
30
import org.mybatis.dynamic.sql.dsl.JoinOperations;
31
import org.mybatis.dynamic.sql.dsl.WhereOperations;
32
import org.mybatis.dynamic.sql.util.Buildable;
33
import org.mybatis.dynamic.sql.util.ConfigurableStatement;
34
import org.mybatis.dynamic.sql.util.Validator;
35
import org.mybatis.dynamic.sql.where.EmbeddedWhereModel;
36

37
/**
38
 * DSL for building count queries. Count queries are specializations of select queries. They have joins and where
39
 * clauses, but not the other parts of a select (group by, order by, etc.) Count queries always return
40
 * a long value. If these restrictions are not acceptable, then use the Select DSL for an unrestricted select statement.
41
 *
42
 * @param <R> the type of model built by this Builder. Typically, SelectModel.
43
 *
44
 * @author Jeff Butler
45
 */
46
public class CountDSL<R> extends AbstractQueryingDSL implements
47
        JoinOperations<CountDSL<R>, CountDSL<R>.JoinSpecificationFinisher>,
48
        WhereOperations<CountDSL<R>.CountWhereBuilder>,
49
        ConfigurableStatement<CountDSL<R>>,
50
        Buildable<R> {
51
    private final Function<SelectModel, R> adapterFunction;
52
    private @Nullable SqlTable table;
53
    private @Nullable CountWhereBuilder whereBuilder;
54
    private final BasicColumn countColumn;
55
    private final StatementConfiguration statementConfiguration = new StatementConfiguration();
1✔
56
    private static final String ERROR_24 = "ERROR.24"; //$NON-NLS-1$
57

58
    private CountDSL(Builder<R> builder) {
1✔
59
        countColumn = Objects.requireNonNull(builder.column);
1✔
60
        adapterFunction = Objects.requireNonNull(builder.adapterFunction);
1✔
61
    }
1✔
62

63
    public CountDSL<R> from(SqlTable table) {
64
        Validator.assertNull(this.table, ERROR_24);
1✔
65
        this.table = table;
1✔
66
        return this;
1✔
67
    }
68

69
    public CountDSL<R> from(SqlTable table, String tableAlias) {
70
        Validator.assertNull(this.table, ERROR_24);
1✔
71
        addTableAlias(table, tableAlias);
1✔
72
        this.table = table;
1✔
73
        return this;
1✔
74
    }
75

76
    @Override
77
    public CountWhereBuilder where() {
78
        whereBuilder = Objects.requireNonNullElseGet(whereBuilder, CountWhereBuilder::new);
1✔
79
        return whereBuilder;
1✔
80
    }
81

82
    @Override
83
    public R build() {
84
        return adapterFunction.apply(buildModel());
1✔
85
    }
86

87
    @Override
88
    public CountDSL<R> configureStatement(Consumer<StatementConfiguration> consumer) {
89
        consumer.accept(statementConfiguration);
1✔
90
        return this;
1✔
91
    }
92

93
    private SelectModel buildModel() {
94
        Validator.assertTrue(table != null, ERROR_24);
1✔
95
        QueryExpressionModel queryExpressionModel = new QueryExpressionModel.Builder()
1✔
96
                .withSelectColumn(countColumn)
1✔
97
                .withTable(table)
1✔
98
                .withTableAliases(tableAliases)
1✔
99
                .withJoinModel(buildJoinModel())
1✔
100
                .withWhereModel(whereBuilder == null ? null : whereBuilder.buildWhereModel())
1✔
101
                .build();
1✔
102

103
        return new SelectModel.Builder()
1✔
104
                .withQueryExpression(queryExpressionModel)
1✔
105
                .withStatementConfiguration(statementConfiguration)
1✔
106
                .build();
1✔
107
    }
108

109
    public static CountDSL<SelectModel> countFrom(SqlTable table) {
110
        return countFrom(Function.identity(), table);
1✔
111
    }
112

113
    public static CountDSL<SelectModel> countFrom(SqlTable table, String tableAlias) {
114
        return new Builder<SelectModel>()
1✔
115
                .withAdapterFunction(Function.identity())
1✔
116
                .withColumn(SqlBuilder.count())
1✔
117
                .build()
1✔
118
                .from(table, tableAlias);
1✔
119
    }
120

121
    public static <R> CountDSL<R> countFrom(Function<SelectModel, R> adapterFunction, SqlTable table) {
122
        return new Builder<R>()
1✔
123
                .withAdapterFunction(adapterFunction)
1✔
124
                .withColumn(SqlBuilder.count())
1✔
125
                .build()
1✔
126
                .from(table);
1✔
127
    }
128

129
    public static CountDSL<SelectModel> count(BasicColumn column) {
130
        return count(Function.identity(), column);
1✔
131
    }
132

133
    public static <R> CountDSL<R> count(Function<SelectModel, R> adapterFunction, BasicColumn column) {
134
        return new Builder<R>()
1✔
135
                .withAdapterFunction(adapterFunction)
1✔
136
                .withColumn(SqlBuilder.count(column))
1✔
137
                .build();
1✔
138
    }
139

140
    public static CountDSL<SelectModel> countDistinct(BasicColumn column) {
141
        return countDistinct(Function.identity(), column);
1✔
142
    }
143

144
    public static <R> CountDSL<R> countDistinct(Function<SelectModel, R> adapterFunction, BasicColumn column) {
145
        return new Builder<R>()
1✔
146
                .withAdapterFunction(adapterFunction)
1✔
147
                .withColumn(SqlBuilder.countDistinct(column))
1✔
148
                .build();
1✔
149
    }
150

151
    @Override
152
    public JoinSpecificationFinisher buildJoinFinisher() {
153
        var finisher = new JoinSpecificationFinisher();
1✔
154
        joinSpecifications.add(finisher);
1✔
155
        return finisher;
1✔
156
    }
157

158
    public class JoinSpecificationFinisher
1✔
159
            extends AbstractJoinSpecificationFinisher<CountDSL<R>, JoinSpecificationFinisher>
160
            implements WhereOperations<CountWhereBuilder>,
161
            ConfigurableStatement<JoinSpecificationFinisher>, Buildable<R> {
162

163
        @Override
164
        protected JoinSpecificationFinisher getThis() {
165
            return this;
1✔
166
        }
167

168
        @Override
169
        public CountDSL<R> endJoinSpecification() {
170
            return CountDSL.this;
1✔
171
        }
172

173
        @Override
174
        public CountWhereBuilder where() {
175
            return CountDSL.this.where();
1✔
176
        }
177

178
        @Override
179
        public R build() {
180
            return CountDSL.this.build();
1✔
181
        }
182

183
        @Override
184
        public JoinSpecificationFinisher configureStatement(Consumer<StatementConfiguration> consumer) {
185
            CountDSL.this.configureStatement(consumer);
1✔
186
            return this;
1✔
187
        }
188
    }
189

190
    public class CountWhereBuilder extends AbstractBooleanOperationsFinisher<CountWhereBuilder>
1✔
191
            implements ConfigurableStatement<CountWhereBuilder>, Buildable<R> {
192
        @Override
193
        public CountWhereBuilder configureStatement(Consumer<StatementConfiguration> consumer) {
194
            CountDSL.this.configureStatement(consumer);
1✔
195
            return this;
1✔
196
        }
197

198
        @Override
199
        public R build() {
200
            return CountDSL.this.build();
1✔
201
        }
202

203
        @Override
204
        protected CountWhereBuilder getThis() {
205
            return this;
×
206
        }
207

208
        protected EmbeddedWhereModel buildWhereModel() {
209
            return toWhereModel();
1✔
210
        }
211
    }
212

213
    public static class Builder<R> {
1✔
214
        private @Nullable BasicColumn column;
215
        private @Nullable Function<SelectModel, R> adapterFunction;
216

217
        public Builder<R> withColumn(BasicColumn column) {
218
            this.column = column;
1✔
219
            return this;
1✔
220
        }
221

222
        public Builder<R> withAdapterFunction(Function<SelectModel, R> adapterFunction) {
223
            this.adapterFunction = adapterFunction;
1✔
224
            return this;
1✔
225
        }
226

227
        public CountDSL<R> build() {
228
            return new CountDSL<>(this);
1✔
229
        }
230
    }
231
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc