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

torand / FasterSQL / 17012572989

16 Aug 2025 08:26PM UTC coverage: 68.265% (-0.008%) from 68.273%
17012572989

push

github

torand
refactor: sonar cloud issues

299 of 598 branches covered (50.0%)

Branch coverage included in aggregate %.

33 of 47 new or added lines in 18 files covered. (70.21%)

1 existing line in 1 file now uncovered.

1680 of 2301 relevant lines covered (73.01%)

3.89 hits per line

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

90.0
/src/main/java/io/github/torand/fastersql/dialect/Dialect.java
1
/*
2
 * Copyright (c) 2024-2025 Tore Eide Andersen
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
 *      http://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 io.github.torand.fastersql.dialect;
17

18
import io.github.torand.fastersql.function.singlerow.cast.DataType;
19
import io.github.torand.fastersql.setoperation.SetOperator;
20
import io.github.torand.fastersql.statement.FasterSQLException;
21

22
import java.sql.Connection;
23
import java.sql.SQLException;
24
import java.util.List;
25
import java.util.Optional;
26
import java.util.stream.IntStream;
27

28
import static io.github.torand.javacommons.collection.ArrayHelper.nonEmpty;
29
import static java.util.stream.Collectors.joining;
30

31
/**
32
 * Defines an SQL dialect as implemented by a specific database vendor.
33
 */
34
public interface Dialect {
35
    /**
36
     * Gets the name of the RDBMS product associated with this SQL dialect.
37
     * @return the name of the RDBMS product.
38
     */
39
    String getProductName();
40

41
    /**
42
     * Indicates whether <i>offset</i> clause must be specified before <i>limit</i> clause; if supported.
43
     * @return whether <i>offset</i> clause must be specified before <i>limit</i> clause; if supported.
44
     */
45
    boolean offsetBeforeLimit();
46

47
    /**
48
     * Returns the <i>row offset</i> clause formatted for a specific SQL dialect.
49
     * @return the <i>row offset</i> clause formatted for a specific SQL dialect.
50
     */
51
    Optional<String> formatRowOffsetClause();
52

53
    /**
54
     * Returns the <i>row limit</i> clause formatted for a specific SQL dialect.
55
     * @return the <i>row limit</i> clause formatted for a specific SQL dialect.
56
     */
57
    Optional<String> formatRowLimitClause();
58

59
    /**
60
     * Returns the <i>row number</i> literal formatted for a specific SQL dialect.
61
     * @return the <i>row number</i> literal formatted for a specific SQL dialect.
62
     */
63
    Optional<String> formatRowNumLiteral();
64

65
    /**
66
     * Returns the specified set operator formatted for a specific SQL dialect.
67
     * @param setOperator the set operator.
68
     * @return the set operator for a specific SQL dialect.
69
     */
70
    default String formatSetOperator(SetOperator setOperator) {
71
        return setOperator.sql();
3✔
72
    }
73

74
    /**
75
     * Returns the 'to_number' function formatted for a specific SQL dialect.
76
     * @param operand the string expression to be evaluated as a number
77
     * @param precision the precision that represents the number of significant digits
78
     * @param scale the scale that that represents the number of digits after the decimal point. Must be less than or equal to the precision.
79
     * @return the 'to_number' function for a specific SQL dialect.
80
     */
81
    String formatToNumberFunction(String operand, int precision, int scale);
82

83
    /**
84
     * Returns the 'to_char' function formatted for a specific SQL dialect.
85
     * @param operand the expression to be evaluated as a string
86
     * @param format the vendor-specific format mask
87
     * @return the 'to_char' function for a specific SQL dialect.
88
     */
89
    String formatToCharFunction(String operand, String format);
90

91
    /**
92
     * Returns the 'substring' function formatted for a specific SQL dialect.
93
     * @param operand the string expression to get substring from
94
     * @param startPos the start position (1-based) of the substring
95
     * @param length the length of the substring
96
     * @return the 'substring' function for a specific SQL dialect.
97
     */
98
    String formatSubstringFunction(String operand, int startPos, int length);
99

100
    /**
101
     * Returns the 'concat' function formatted for a specific SQL dialect.
102
     * @param operands the string expressions to concatenate
103
     * @return the 'concat' function for a specific SQL dialect.
104
     */
105
    String formatConcatFunction(List<String> operands);
106

107
    /**
108
     * Returns the 'length' function formatted for a specific SQL dialect.
109
     * @param operand the string expression to get length of
110
     * @return the 'length' function for a specific SQL dialect.
111
     */
112
    String formatLengthFunction(String operand);
113

114
    /**
115
     * Returns the 'ceil' function formatted for a specific SQL dialect.
116
     * @param operand the numeric expression to get ceiling of
117
     * @return the 'ceil' function for a specific SQL dialect.
118
     */
119
    String formatCeilFunction(String operand);
120

121
    /**
122
     * Returns the 'ln' function formatted for a specific SQL dialect.
123
     * @param operand the numeric expression to get natural logarithm of
124
     * @return the 'ln' function for a specific SQL dialect.
125
     */
126
    String formatLnFunction(String operand);
127

128
    /**
129
     * Returns the 'pow' function formatted for a specific SQL dialect.
130
     * @param base the numeric expression for base operand
131
     * @param exponent the numeric expression for exponent operand
132
     * @return the 'pow' function for a specific SQL dialect.
133
     */
134
    default String formatPowerFunction(String base, String exponent) {
135
        return "power(%s, %s)".formatted(base, exponent);
13✔
136
    }
137

138
    /**
139
     * Returns the 'round' function formatted for a specific SQL dialect.
140
     * @param operand the numeric expression to perform rounding on
141
     * @return the 'round' function for a specific SQL dialect.
142
     */
143
    String formatRoundFunction(String operand);
144

145
    /**
146
     * Returns the 'mod' function formatted for a specific SQL dialect.
147
     * @param divisor the numeric expression for divisor operand
148
     * @param dividend the numeric expression for dividend operand
149
     * @return the 'mod' function for a specific SQL dialect.
150
     */
151
    String formatModuloFunction(String divisor, String dividend);
152

153
    /**
154
     * Returns the 'current_date' system function formatted for a specific SQL dialect.
155
     * @return the 'current_date' function for a specific SQL dialect.
156
     */
157
    String formatCurrentDateFunction();
158

159
    /**
160
     * Returns the 'cast' function formatted for a specific SQL dialect.
161
     * @param operand  the expression to cast.
162
     * @param targetType the data type to cast to.
163
     * @return the 'cast' function formatted for a specific SQL dialect.
164
     */
165
    default String formatCastFunction(String operand, DataType targetType) {
166
        String dataType = getDataType(targetType).orElseThrow(
9✔
167
            () -> new UnsupportedOperationException("%s does not support the %s data type".formatted(getProductName(), targetType.getIsoDataType().name())));
×
168

169
        if (nonEmpty(targetType.getArgs())) {
4✔
170
            String args = IntStream.of(targetType.getArgs()).boxed().map(Object::toString).collect(joining(", "));
11✔
171
            dataType += "(" + args + ")";
4✔
172
        }
173

174
        return "cast(%s as %s)".formatted(operand, dataType);
13✔
175
    }
176

177
    /**
178
     * Returns the data type for a specific SQL dialect.
179
     * @param dataType the ISO data type
180
     * @return the data type for a specific SQL dialect.
181
     */
182
    Optional<String> getDataType(DataType dataType);
183

184
    /**
185
     * Returns the string concatenation operator for a specific SQL Dialect.
186
     * @return the string concatenation operator for a specific SQL Dialect.
187
     */
188
    Optional<String> getConcatOperator();
189

190
    /**
191
     * Indicates whether a capability is supported by a specific SQL dialect.
192
     * @param capability the capability to check support for
193
     * @return true if specified capability is supported; else false
194
     */
195
    boolean supports(Capability capability);
196

197
    /**
198
     * Creates the {@link Dialect} instance corresponding to database vendor associated with specified connection.
199
     * @param connection the connection.
200
     * @return the {@link Dialect} instance.
201
     */
202
    static Dialect fromConnection(Connection connection) {
203
        try {
204
            String productName = connection.getMetaData().getDatabaseProductName().toLowerCase();
5✔
205

206
            if (productName.contains("h2")) {
4✔
207
                return new H2Dialect().withCustomizations(connection);
6✔
208
            } else if (productName.contains("mysql")) {
4✔
209
                return new MySqlDialect();
4✔
210
            } else if (productName.contains("mariadb")) {
4✔
211
                return new MariaDbDialect();
4✔
212
            } else if (productName.contains("postgresql")) {
4✔
213
                return new PostgreSqlDialect();
4✔
214
            } else if (productName.contains("oracle")) {
4✔
215
                return new OracleDialect();
4✔
216
            } else if (productName.contains("sql server")) {
4✔
217
                return new SqlServerDialect();
4✔
218
            } else if (productName.contains("access")) {
4✔
219
                return new AccessDialect();
4✔
220
            } else if (productName.contains("sqlite")) {
4✔
221
                return new SqliteDialect();
4✔
222
            } else if (productName.contains("hsql")) {
4!
223
                return new HsqldbDialect();
4✔
224
            } else {
225
                throw new UnsupportedOperationException("Database with product name " + productName + " not supported");
×
226
            }
227
        } catch (SQLException e) {
×
NEW
228
            throw new FasterSQLException("Failed to detect SQL dialect from connection metadata", e);
×
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