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

future-architect / uroborosql / #743

28 Jun 2024 04:17PM UTC coverage: 90.988% (+0.5%) from 90.484%
#743

push

web-flow
add paramIfNotEmpty method (#318)

* v0.x to master merge

* fix nanoseconds diff (java8 to java11)

* eclipse cleanup and  optimize import

* eclipse format

* optimize Imports

* remove unused annotation

* library version up

* migrate v0.x to master
- update java version 8 to 11
- update junit4 to junit5
- library version update

* fix test failed

* remove unused annotation

* fixed bug

* use var

* fix java8 coding style

* Refactoring TransactionContextManager

* Refactoring SqlAgent

* 途中コミット

* fix testcase

* fix review

* fix javadoc comments

* merge v0.x PR

* cleanup code

* cleanup test code

* change build status badge

* - agent.query, update, proc, batch にそれぞれSupplierを引数にとるメソッドを追加
- SqlQuery.paramとSqlEntityUpdate.setにFunctionを受け取るメソッドを追加

* testcaseの整形

* - SqlFluent と ExtractionCondition の分離
- Arrays.asList -> List.of への変更
- テストの整形

* - v0.x系の不具合対応の追いつき
- ログ出力の整理

* - SqlKindの整理(ENTITY_XXXの追加)
- REPL_LOGの追加
- Deprecatedメソッドの削除(SqlAgent)
- SqlAgent, ExecutionContextでsetterをfluent APIに変更

* DB接続URLの修正

* add and fix testcases.

* add event testcases.

* fix typo

* add paramIfNotEmpty method and StringUtils rename ObjectUtils

* fix review comments.

* remove unused import

1695 of 1958 new or added lines in 97 files covered. (86.57%)

26 existing lines in 10 files now uncovered.

8249 of 9066 relevant lines covered (90.99%)

0.91 hits per line

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

86.99
/src/main/java/jp/co/future/uroborosql/parser/SqlTokenizerImpl.java
1
/**
2
 * Copyright (c) 2017-present, Future Corporation
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
package jp.co.future.uroborosql.parser;
8

9
import jp.co.future.uroborosql.exception.TokenNotClosedRuntimeException;
10

11
/**
12
 * SQL分割処理実装クラス
13
 *
14
 * @author H.Sugimoto
15
 */
16
public class SqlTokenizerImpl implements SqlTokenizer {
17
        /** SQL文 */
18
        private final String sql;
19

20
        /** 現在地 */
21
        private int position = 0;
1✔
22

23
        /** トークン */
24
        private String token;
25

26
        /** トークン種別 */
27
        private TokenType tokenType = TokenType.SQL;
1✔
28

29
        /** 次のトークン種別 */
30
        private TokenType nextTokenType = TokenType.SQL;
1✔
31

32
        /** バインド変数採番番号 */
33
        private int bindVariableNumber = 0;
1✔
34

35
        /**
36
         * コンストラクタ
37
         *
38
         * @param sql 解析対象SQL
39
         */
40
        public SqlTokenizerImpl(final String sql) {
1✔
41
                this.sql = sql;
1✔
42
        }
1✔
43

44
        /**
45
         * {@inheritDoc}
46
         *
47
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#getPosition()
48
         */
49
        @Override
50
        public int getPosition() {
51
                return position;
1✔
52
        }
53

54
        /**
55
         * {@inheritDoc}
56
         *
57
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#getToken()
58
         */
59
        @Override
60
        public String getToken() {
61
                return token;
1✔
62
        }
63

64
        /**
65
         * {@inheritDoc}
66
         *
67
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#getBefore()
68
         */
69
        @Override
70
        public String getBefore() {
71
                return sql.substring(0, position);
1✔
72
        }
73

74
        /**
75
         * {@inheritDoc}
76
         *
77
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#getAfter()
78
         */
79
        @Override
80
        public String getAfter() {
81
                return sql.substring(position);
1✔
82
        }
83

84
        /**
85
         * {@inheritDoc}
86
         *
87
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#getTokenType()
88
         */
89
        @Override
90
        public TokenType getTokenType() {
91
                return tokenType;
1✔
92
        }
93

94
        /**
95
         * {@inheritDoc}
96
         *
97
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#getNextTokenType()
98
         */
99
        @Override
100
        public TokenType getNextTokenType() {
101
                return nextTokenType;
×
102
        }
103

104
        /**
105
         * {@inheritDoc}
106
         *
107
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#next()
108
         */
109
        @Override
110
        public TokenType next() {
111
                if (position >= sql.length()) {
1✔
112
                        token = null;
1✔
113
                        tokenType = TokenType.EOF;
1✔
114
                        nextTokenType = TokenType.EOF;
1✔
115
                        return tokenType;
1✔
116
                }
117
                switch (nextTokenType) {
1✔
118
                case SQL:
119
                        parseSql();
1✔
120
                        break;
1✔
121
                case COMMENT:
122
                        parseComment();
1✔
123
                        break;
1✔
124
                case ELSE:
125
                        parseElse();
1✔
126
                        break;
1✔
127
                case BIND_VARIABLE:
UNCOV
128
                        parseBindVariable();
×
UNCOV
129
                        break;
×
130
                default:
131
                        parseEof();
×
132
                        break;
133
                }
134
                return tokenType;
1✔
135
        }
136

137
        /**
138
         * SQL文解析
139
         */
140
        protected void parseSql() {
141
                var commentStartPos = sql.indexOf("/*", position);
1✔
142
                var lineCommentStartPos = sql.indexOf("--", position);
1✔
143
                var elseCommentStartPos = -1;
1✔
144
                if (lineCommentStartPos >= 0) {
1✔
145
                        var skipPos = skipWhitespace(lineCommentStartPos + 2);
1✔
146
                        if (skipPos + 4 < sql.length() && "ELSE".equals(sql.substring(skipPos, skipPos + 4))) {
1✔
147
                                elseCommentStartPos = lineCommentStartPos;
1✔
148
                        }
149
                }
150
                var nextStartPos = getNextStartPos(commentStartPos, elseCommentStartPos);
1✔
151
                if (nextStartPos < 0) {
1✔
152
                        token = sql.substring(position);
1✔
153
                        nextTokenType = TokenType.EOF;
1✔
154
                        position = sql.length();
1✔
155
                        tokenType = TokenType.SQL;
1✔
156
                } else {
157
                        token = sql.substring(position, nextStartPos);
1✔
158
                        tokenType = TokenType.SQL;
1✔
159
                        var needNext = nextStartPos == position;
1✔
160
                        if (nextStartPos == commentStartPos) {
1✔
161
                                nextTokenType = TokenType.COMMENT;
1✔
162
                                position = commentStartPos + 2;
1✔
163
                        } else if (nextStartPos == elseCommentStartPos) {
1✔
164
                                nextTokenType = TokenType.ELSE;
1✔
165
                                position = elseCommentStartPos + 2;
1✔
166
                        }
167
                        if (needNext) {
1✔
168
                                next();
1✔
169
                        }
170
                }
171
        }
1✔
172

173
        /**
174
         * 次の解析開始位置を取得
175
         *
176
         * @param commentStartPos コメント開始位置
177
         * @param elseCommentStartPos ELSEコメント開始位置
178
         * @return 次の解析位置
179
         */
180
        protected int getNextStartPos(final int commentStartPos, final int elseCommentStartPos) {
181

182
                var nextStartPos = -1;
1✔
183
                if (commentStartPos >= 0) {
1✔
184
                        nextStartPos = commentStartPos;
1✔
185
                }
186
                if (elseCommentStartPos >= 0 && (nextStartPos < 0 || elseCommentStartPos < nextStartPos)) {
1✔
187
                        nextStartPos = elseCommentStartPos;
1✔
188
                }
189
                return nextStartPos;
1✔
190
        }
191

192
        /**
193
         * 次のバインド変数名取得
194
         *
195
         * @return バインド変数名
196
         */
197
        protected String nextBindVariableName() {
UNCOV
198
                return "$" + ++bindVariableNumber;
×
199
        }
200

201
        /**
202
         * コメント部解析
203
         */
204
        protected void parseComment() {
205
                var commentEndPos = sql.indexOf("*/", position);
1✔
206
                if (commentEndPos < 0) {
1✔
207
                        throw new TokenNotClosedRuntimeException(sql.substring(position));
1✔
208
                }
209
                token = sql.substring(position, commentEndPos);
1✔
210
                nextTokenType = TokenType.SQL;
1✔
211
                position = commentEndPos + 2;
1✔
212
                tokenType = TokenType.COMMENT;
1✔
213
        }
1✔
214

215
        /**
216
         * バインド変数解析
217
         */
218
        protected void parseBindVariable() {
UNCOV
219
                token = nextBindVariableName();
×
UNCOV
220
                nextTokenType = TokenType.SQL;
×
UNCOV
221
                position += 1;
×
UNCOV
222
                tokenType = TokenType.BIND_VARIABLE;
×
UNCOV
223
        }
×
224

225
        /**
226
         * ELSE文解析
227
         */
228
        protected void parseElse() {
229
                var pos = sql.indexOf("ELSE", position) + 4;
1✔
230
                var elseToken = sql.substring(position, pos);
1✔
231
                token = elseToken;
1✔
232
                nextTokenType = TokenType.SQL;
1✔
233
                position = position + elseToken.length();
1✔
234
                tokenType = TokenType.ELSE;
1✔
235
        }
1✔
236

237
        /**
238
         * EOF
239
         */
240
        protected void parseEof() {
241
                token = null;
×
242
                tokenType = TokenType.EOF;
×
243
                nextTokenType = TokenType.EOF;
×
244
        }
×
245

246
        /**
247
         * {@inheritDoc}
248
         *
249
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#skipToken()
250
         */
251
        @Override
252
        public String skipToken() {
253
                var length = sql.length();
1✔
254
                var endIndex = length;
1✔
255
                var quote = position < length ? sql.charAt(position) : '\0';
1✔
256
                var quoting = quote == '\'' || quote == '(';
1✔
257
                if (quote == '(') {
1✔
258
                        quote = ')';
1✔
259
                }
260
                for (var i = quoting ? position + 1 : position; i < length; ++i) {
1✔
261
                        var c = sql.charAt(i);
1✔
262
                        if ((Character.isWhitespace(c) || c == ',' || c == ')' || c == '(') && !quoting) {
1✔
263
                                endIndex = i;
1✔
264
                                break;
1✔
265
                        } else if (c == '/' && i + 1 < length && sql.charAt(i + 1) == '*') {
1✔
266
                                endIndex = i;
1✔
267
                                break;
1✔
268
                        } else if (c == '-' && i + 1 < length && sql.charAt(i + 1) == '-') {
1✔
269
                                endIndex = i;
×
270
                                break;
×
271
                        } else if (quoting && quote == '\'' && c == '\'' && (i + 1 >= length || sql.charAt(i + 1) != '\'')) {
1✔
272
                                endIndex = i + 1;
1✔
273
                                break;
1✔
274
                        } else if (quoting && c == quote) {
1✔
275
                                endIndex = i + 1;
1✔
276
                                break;
1✔
277
                        }
278
                }
279
                token = sql.substring(position, endIndex);
1✔
280
                tokenType = TokenType.SQL;
1✔
281
                nextTokenType = TokenType.SQL;
1✔
282
                position = endIndex;
1✔
283
                return token;
1✔
284
        }
285

286
        /**
287
         * {@inheritDoc}
288
         *
289
         * @see jp.co.future.uroborosql.parser.SqlTokenizer#skipWhitespace()
290
         */
291
        @Override
292
        public String skipWhitespace() {
293
                var index = skipWhitespace(position);
1✔
294
                token = sql.substring(position, index);
1✔
295
                position = index;
1✔
296
                return token;
1✔
297
        }
298

299
        /**
300
         * ホワイトスペーススキップ
301
         *
302
         * @param position ポジション
303
         * @return 空白をスキップした位置
304
         */
305
        private int skipWhitespace(final int position) {
306
                var index = sql.length();
1✔
307
                for (var i = position; i < index; ++i) {
1✔
308
                        var c = sql.charAt(i);
1✔
309
                        if (!Character.isWhitespace(c)) {
1✔
310
                                return i;
1✔
311
                        }
312
                }
313
                return index;
1✔
314
        }
315

316
}
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

© 2025 Coveralls, Inc