• 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

97.09
/src/main/java/jp/co/future/uroborosql/context/ExecutionContextImpl.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.context;
8

9
import java.io.InputStream;
10
import java.io.Reader;
11
import java.sql.CallableStatement;
12
import java.sql.PreparedStatement;
13
import java.sql.ResultSet;
14
import java.sql.SQLException;
15
import java.sql.SQLType;
16
import java.util.AbstractSet;
17
import java.util.ArrayList;
18
import java.util.Collections;
19
import java.util.HashMap;
20
import java.util.HashSet;
21
import java.util.Iterator;
22
import java.util.LinkedHashSet;
23
import java.util.List;
24
import java.util.Map;
25
import java.util.Objects;
26
import java.util.Set;
27
import java.util.function.Function;
28
import java.util.function.Supplier;
29
import java.util.regex.Pattern;
30

31
import org.slf4j.Logger;
32
import org.slf4j.LoggerFactory;
33

34
import jp.co.future.uroborosql.config.SqlConfig;
35
import jp.co.future.uroborosql.config.SqlConfigAware;
36
import jp.co.future.uroborosql.enums.SqlKind;
37
import jp.co.future.uroborosql.event.AfterGetOutParameterEvent;
38
import jp.co.future.uroborosql.event.BeforeParseSqlEvent;
39
import jp.co.future.uroborosql.event.BeforeSetParameterEvent;
40
import jp.co.future.uroborosql.exception.ParameterNotFoundRuntimeException;
41
import jp.co.future.uroborosql.parameter.InOutParameter;
42
import jp.co.future.uroborosql.parameter.OutParameter;
43
import jp.co.future.uroborosql.parameter.Parameter;
44
import jp.co.future.uroborosql.parameter.ReaderParameter;
45
import jp.co.future.uroborosql.parameter.StreamParameter;
46
import jp.co.future.uroborosql.parameter.mapper.BindParameterMapperManager;
47
import jp.co.future.uroborosql.parser.TransformContext;
48
import jp.co.future.uroborosql.utils.BeanAccessor;
49
import jp.co.future.uroborosql.utils.ObjectUtils;
50

51
/**
52
 * ExecutionContext実装クラス
53
 *
54
 * @author H.Sugimoto
55
 */
56
public class ExecutionContextImpl implements ExecutionContext, SqlConfigAware {
57
        /**
58
         * @see #getParameterNames()
59
         */
60
        private class ParameterNames extends AbstractSet<String> {
1✔
61

62
                @Override
63
                public Iterator<String> iterator() {
64
                        return parameterMap.keySet().iterator();
1✔
65
                }
66

67
                @Override
68
                public int size() {
69
                        return parameterMap.size();
1✔
70
                }
71

72
                @Override
73
                public boolean contains(final Object o) {
74
                        return parameterMap.containsKey(o);
1✔
75
                }
76
        }
77

78
        /** where句の直後にくるANDやORを除外するための正規表現 */
79
        private static final Pattern WHERE_CLAUSE_PATTERN = Pattern.compile(
1✔
80
                        "(?i)(?<clause>(\\bWHERE\\s+(--.*|/\\*[\\s\\S]*\\*/\\s*)*\\s*))((AND|OR)\\s+)");
81

82
        /** 各句の最初に現れるカンマを除去するための正規表現 */
83
        private static final Pattern REMOVE_FIRST_COMMA_PATTERN = Pattern.compile(
1✔
84
                        "(?i)(?<keyword>(\\b(SELECT|ORDER\\s+BY|GROUP\\s+BY|SET)\\s+|\\(\\s*)(--.*|/\\*[^(/\\*|\\*/)]+?\\*/\\s*)*\\s*),");
85

86
        /** 不要な空白、改行を除去するための正規表現 */
87
        private static final Pattern CLEAR_BLANK_PATTERN = Pattern.compile("(?m)^\\s*(\\r\\n|\\r|\\n)");
1✔
88

89
        /** SQLロガー */
90
        private static final Logger SQL_LOG = LoggerFactory.getLogger("jp.co.future.uroborosql.sql");
1✔
91

92
        /** SqlConfig. */
93
        private SqlConfig sqlConfig;
94

95
        /** SQL名 */
96
        private String sqlName;
97

98
        /** 変換前のSQL文 */
99
        private String originalSql;
100

101
        /** 変換後のSQL文 */
102
        private final StringBuilder executableSql = new StringBuilder();
1✔
103

104
        /** 変換後のSQL文字列をキャッシュしたもの。 */
105
        private String executableSqlCache = "";
1✔
106

107
        /** SQL文の識別子 */
108
        private String sqlId;
109

110
        /** SQLを実行するスキーマ */
111
        private String schema;
112

113
        /** SQL実行の最大リトライ数 */
114
        private int maxRetryCount = -1;
1✔
115

116
        /** リトライを行う場合の待機時間(ms) */
117
        private int retryWaitTime = 0;
1✔
118

119
        /** パラメータ保持用マップ */
120
        private Map<String, Parameter> parameterMap = new HashMap<>();
1✔
121

122
        /** 定数パラメータ保持用マップ */
123
        private Map<String, Parameter> constParameterMap = null;
1✔
124

125
        /** バインド対象パラメータ名リスト */
126
        private final List<String> bindNames = new ArrayList<>();
1✔
127

128
        /** バインド変数リスト */
129
        private final List<Object> bindVariables = new ArrayList<>();
1✔
130

131
        /** 有効フラグ(BEGIN句で使用) */
132
        private boolean enabled = true;
1✔
133

134
        /** バッチ処理用パラメータ保持用マップリスト */
135
        private final List<Map<String, Parameter>> batchParameters = new ArrayList<>();
1✔
136

137
        /** 列の型の再定義保持用マップ */
138
        private final Map<Integer, Integer> defineColumnTypeMap = new HashMap<>();
1✔
139

140
        /** カーソルのタイプ(デフォルト値:カーソルは最初から最後まで順方向にしか移動できません。) */
141
        private int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
1✔
142

143
        /** 変更可能性(デフォルト値:カーソルはデータの読み出ししかサポートしません。) */
144
        private int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY;
1✔
145

146
        /** 実行するSQLの種別 */
147
        private SqlKind sqlKind = SqlKind.NONE;
1✔
148

149
        /** 自動採番するキーカラム名の配列 */
150
        private String[] generatedKeyColumns;
151

152
        /** 自動採番するキーカラム値の配列 */
153
        private Object[] generatedKeyValues;
154

155
        /** コンテキスト属性情報 */
156
        private final Map<String, Object> contextAttributes = new HashMap<>();
1✔
157

158
        /** パラメータ変換マネージャ */
159
        private BindParameterMapperManager parameterMapperManager;
160

161
        /** パラメータ名Set */
162
        private ParameterNames parameterNames;
163

164
        /** 更新処理実行時に通常の更新SQL発行の代わりに移譲する処理. */
165
        private Function<ExecutionContext, Integer> updateDelegate;
166

167
        /**
168
         * コンストラクタ。
169
         */
170
        ExecutionContextImpl() {
1✔
171
        }
1✔
172

173
        /**
174
         * コピーコンストラクタ
175
         *
176
         * @param parent コピー元のExecutionContext
177
         */
178
        private ExecutionContextImpl(final ExecutionContextImpl parent) {
1✔
179
                enabled = false;
1✔
180
                sqlId = parent.sqlId;
1✔
181
                sqlName = parent.sqlName;
1✔
182
                maxRetryCount = parent.maxRetryCount;
1✔
183
                retryWaitTime = parent.retryWaitTime;
1✔
184
                parameterMap = parent.parameterMap;
1✔
185
                constParameterMap = parent.constParameterMap;
1✔
186
                batchParameters.addAll(parent.batchParameters);
1✔
187
                defineColumnTypeMap.putAll(parent.defineColumnTypeMap);
1✔
188
                resultSetType = parent.resultSetType;
1✔
189
                resultSetConcurrency = parent.resultSetConcurrency;
1✔
190
                sqlKind = parent.sqlKind;
1✔
191
                contextAttributes.putAll(parent.contextAttributes);
1✔
192
        }
1✔
193

194
        /**
195
         * {@inheritDoc}
196
         *
197
         * @see jp.co.future.uroborosql.parser.TransformContext#copyTransformContext()
198
         */
199
        @Override
200
        public TransformContext copyTransformContext() {
201
                return new ExecutionContextImpl(this);
1✔
202
        }
203

204
        /**
205
         *
206
         * {@inheritDoc}
207
         *
208
         * @see jp.co.future.uroborosql.config.SqlConfigAware#getSqlConfig()
209
         */
210
        @Override
211
        public SqlConfig getSqlConfig() {
212
                return this.sqlConfig;
1✔
213
        }
214

215
        /**
216
         *
217
         * {@inheritDoc}
218
         *
219
         * @see jp.co.future.uroborosql.config.SqlConfigAware#setSqlConfig(jp.co.future.uroborosql.config.SqlConfig)
220
         */
221
        @Override
222
        public void setSqlConfig(final SqlConfig sqlConfig) {
223
                this.sqlConfig = sqlConfig;
1✔
224
        }
1✔
225

226
        /**
227
         * {@inheritDoc}
228
         *
229
         * @see jp.co.future.uroborosql.parser.TransformContext#getExecutableSql()
230
         */
231
        @Override
232
        public String getExecutableSql() {
233
                if (ObjectUtils.isEmpty(executableSqlCache) && executableSql.length() > 0) {
1✔
234
                        executableSqlCache = executableSql.toString();
1✔
235
                        if (executableSqlCache.toUpperCase().contains("WHERE")) {
1✔
236
                                // where句の直後に来るANDやORの除去
237
                                var builder = new StringBuilder();
1✔
238
                                var matcher = WHERE_CLAUSE_PATTERN.matcher(executableSqlCache);
1✔
239
                                while (matcher.find()) {
1✔
240
                                        var whereClause = matcher.group("clause");
1✔
241
                                        matcher.appendReplacement(builder, whereClause);
1✔
242
                                }
1✔
243
                                matcher.appendTail(builder);
1✔
244
                                executableSqlCache = builder.toString();
1✔
245
                        }
246
                        // 各句の直後に現れる不要なカンマの除去
247
                        var builder = new StringBuilder();
1✔
248
                        var removeCommaMatcher = REMOVE_FIRST_COMMA_PATTERN.matcher(executableSqlCache);
1✔
249
                        while (removeCommaMatcher.find()) {
1✔
250
                                var clauseWords = removeCommaMatcher.group("keyword");
1✔
251
                                removeCommaMatcher.appendReplacement(builder, clauseWords);
1✔
252
                        }
1✔
253
                        removeCommaMatcher.appendTail(builder);
1✔
254
                        executableSqlCache = builder.toString();
1✔
255

256
                        // 空行の除去
257
                        executableSqlCache = CLEAR_BLANK_PATTERN.matcher(executableSqlCache).replaceAll("");
1✔
258
                }
259
                return executableSqlCache;
1✔
260
        }
261

262
        /**
263
         * {@inheritDoc}
264
         *
265
         * @see jp.co.future.uroborosql.context.ExecutionContext#getSql()
266
         */
267
        @Override
268
        public String getSql() {
269
                return originalSql;
1✔
270
        }
271

272
        /**
273
         * {@inheritDoc}
274
         *
275
         * @see jp.co.future.uroborosql.context.ExecutionContext#setSql(java.lang.String)
276
         */
277
        @Override
278
        public ExecutionContext setSql(final String originalSql) {
279
                this.originalSql = originalSql;
1✔
280
                return this;
1✔
281
        }
282

283
        /**
284
         * {@inheritDoc}
285
         *
286
         * @see jp.co.future.uroborosql.context.ExecutionContext#getSqlName()
287
         */
288
        @Override
289
        public String getSqlName() {
290
                return sqlName;
1✔
291
        }
292

293
        /**
294
         * {@inheritDoc}
295
         *
296
         * @see jp.co.future.uroborosql.context.ExecutionContext#setSqlName(java.lang.String)
297
         */
298
        @Override
299
        public ExecutionContext setSqlName(final String sqlName) {
300
                this.sqlName = sqlName;
1✔
301
                return this;
1✔
302
        }
303

304
        /**
305
         * {@inheritDoc}
306
         *
307
         * @see jp.co.future.uroborosql.context.ExecutionContext#getSqlId()
308
         */
309
        @Override
310
        public String getSqlId() {
311
                return sqlId;
1✔
312
        }
313

314
        /**
315
         * {@inheritDoc}
316
         *
317
         * @see jp.co.future.uroborosql.context.ExecutionContext#setSqlId(java.lang.String)
318
         */
319
        @Override
320
        public ExecutionContext setSqlId(final String sqlId) {
321
                this.sqlId = sqlId;
1✔
322
                return this;
1✔
323
        }
324

325
        /**
326
         * {@inheritDoc}
327
         *
328
         * @see jp.co.future.uroborosql.context.ExecutionContext#getSchema()
329
         */
330
        @Override
331
        public String getSchema() {
332
                return this.schema;
1✔
333
        }
334

335
        /**
336
         * {@inheritDoc}
337
         *
338
         * @see jp.co.future.uroborosql.context.ExecutionContext#setSchema(java.lang.String)
339
         */
340
        @Override
341
        public ExecutionContext setSchema(final String schema) {
342
                this.schema = schema;
1✔
343
                return this;
1✔
344
        }
345

346
        /**
347
         * {@inheritDoc}
348
         *
349
         * @see jp.co.future.uroborosql.context.ExecutionContext#getMaxRetryCount()
350
         */
351
        @Override
352
        public int getMaxRetryCount() {
353
                return maxRetryCount;
1✔
354
        }
355

356
        /**
357
         * {@inheritDoc}
358
         *
359
         * @see jp.co.future.uroborosql.context.ExecutionContext#setMaxRetryCount(int)
360
         */
361
        @Override
362
        public ExecutionContext setMaxRetryCount(final int maxRetryCount) {
363
                this.maxRetryCount = maxRetryCount;
1✔
364
                return this;
1✔
365
        }
366

367
        /**
368
         * {@inheritDoc}
369
         *
370
         * @see jp.co.future.uroborosql.context.ExecutionContext#getRetryWaitTime()
371
         */
372
        @Override
373
        public int getRetryWaitTime() {
374
                return retryWaitTime;
1✔
375
        }
376

377
        /**
378
         * {@inheritDoc}
379
         *
380
         * @see jp.co.future.uroborosql.context.ExecutionContext#setRetryWaitTime(int)
381
         */
382
        @Override
383
        public ExecutionContext setRetryWaitTime(final int retryWaitTime) {
384
                this.retryWaitTime = retryWaitTime;
1✔
385
                return this;
1✔
386
        }
387

388
        /**
389
         * {@inheritDoc}
390
         *
391
         * @see jp.co.future.uroborosql.parser.TransformContext#getParam(java.lang.String)
392
         */
393
        @Override
394
        public Parameter getParam(final String paramName) {
395
                var param = getBindParameter(paramName);
1✔
396
                if (param == null) {
1✔
397
                        var constParams = getConstParameterMap();
1✔
398
                        if (constParams != null) {
1✔
399
                                param = constParams.get(paramName.toUpperCase());
1✔
400
                        }
401
                }
402
                return param;
1✔
403
        }
404

405
        /**
406
         * parameterMapから指定されたキーのパラメータを取得する
407
         *
408
         * @param paramName パラメータ名
409
         * @return パラメータ
410
         */
411
        private Parameter getBindParameter(final String paramName) {
412
                if (!paramName.contains(".")) {
1✔
413
                        return parameterMap.get(paramName);
1✔
414
                } else if (paramName.contains("(") && paramName.contains(")")) {
1✔
415
                        // メソッド呼び出しの場合は、SqlParserで値を評価するタイミングでparameterをaddしているので、そのまま返却する
416
                        return parameterMap.get(paramName);
1✔
417
                } else {
418
                        // サブパラメータの作成
419
                        var keys = paramName.split("\\.");
1✔
420
                        var baseName = keys[0];
1✔
421

422
                        var parameter = parameterMap.get(baseName);
1✔
423
                        if (parameter == null) {
1✔
424
                                return null;
×
425
                        }
426

427
                        if (keys.length > 1) {
1✔
428
                                var propertyName = keys[1];
1✔
429
                                return parameter.createSubParameter(propertyName);
1✔
430
                        }
431
                        return parameter;
×
432
                }
433
        }
434

435
        /**
436
         * {@inheritDoc}
437
         *
438
         * @see jp.co.future.uroborosql.fluent.SqlFluent#context()
439
         */
440
        @Override
441
        public ExecutionContext context() {
442
                return this;
1✔
443
        }
444

445
        /**
446
         * {@inheritDoc}
447
         *
448
         * @see jp.co.future.uroborosql.fluent.SqlFluent#hasParam(java.lang.String)
449
         */
450
        @Override
451
        public boolean hasParam(final String paramName) {
452
                return parameterMap.containsKey(paramName);
1✔
453
        }
454

455
        /**
456
         * パラメータの追加
457
         *
458
         * @param parameter パラメータ
459
         *
460
         * @return ExecutionContext
461
         */
462
        private ExecutionContext param(final Parameter parameter) {
463
                parameterMap.put(parameter.getParameterName(), parameter);
1✔
464
                return this;
1✔
465
        }
466

467
        /**
468
         * {@inheritDoc}
469
         *
470
         * @see jp.co.future.uroborosql.parser.TransformContext#param(java.lang.String, java.lang.Object)
471
         */
472
        @Override
473
        public <V> ExecutionContext param(final String parameterName, final V value) {
474
                if (value instanceof InputStream) {
1✔
475
                        return param(new StreamParameter(parameterName, (InputStream) value));
1✔
476
                } else if (value instanceof Reader) {
1✔
477
                        return param(new ReaderParameter(parameterName, (Reader) value));
1✔
478
                } else {
479
                        return param(new Parameter(parameterName, value));
1✔
480
                }
481
        }
482

483
        /**
484
         * {@inheritDoc}
485
         *
486
         * @see jp.co.future.uroborosql.fluent.SqlFluent#param(java.lang.String, java.util.function.Supplier)
487
         */
488
        @Override
489
        public <V> ExecutionContext param(final String paramName, final Supplier<V> supplier) {
490
                if (supplier != null) {
1✔
491
                        var value = supplier.get();
1✔
492
                        if (value != null) {
1✔
493
                                return this.param(paramName, value);
1✔
494
                        } else {
495
                                return this;
1✔
496
                        }
497
                } else {
498
                        return param(new Parameter(paramName, null));
1✔
499
                }
500
        }
501

502
        /**
503
         * {@inheritDoc}
504
         *
505
         * @see jp.co.future.uroborosql.fluent.SqlFluent#param(java.lang.String, java.lang.Object, java.sql.SQLType)
506
         */
507
        @Override
508
        public <V> ExecutionContext param(final String parameterName, final V value, final SQLType sqlType) {
509
                if (value instanceof InputStream) {
1✔
NEW
510
                        return param(new StreamParameter(parameterName, (InputStream) value));
×
511
                } else if (value instanceof Reader) {
1✔
NEW
512
                        return param(new ReaderParameter(parameterName, (Reader) value));
×
513
                } else {
514
                        return param(new Parameter(parameterName, value, sqlType));
1✔
515
                }
516
        }
517

518
        /**
519
         * {@inheritDoc}
520
         *
521
         * @see jp.co.future.uroborosql.fluent.SqlFluent#param(java.lang.String, java.lang.Object, int)
522
         */
523
        @Override
524
        public <V> ExecutionContext param(final String parameterName, final V value, final int sqlType) {
525
                if (value instanceof InputStream) {
1✔
NEW
526
                        return param(new StreamParameter(parameterName, (InputStream) value));
×
527
                } else if (value instanceof Reader) {
1✔
NEW
528
                        return param(new ReaderParameter(parameterName, (Reader) value));
×
529
                } else {
530
                        return param(new Parameter(parameterName, value, sqlType));
1✔
531
                }
532
        }
533

534
        /**
535
         * {@inheritDoc}
536
         *
537
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramIfAbsent(java.lang.String, java.lang.Object)
538
         */
539
        @Override
540
        public <V> ExecutionContext paramIfAbsent(final String parameterName, final V value) {
541
                if (!hasParam(parameterName)) {
1✔
542
                        param(parameterName, value);
1✔
543
                }
544
                return this;
1✔
545
        }
546

547
        /**
548
         * {@inheritDoc}
549
         *
550
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramIfAbsent(java.lang.String, java.lang.Object, java.sql.SQLType)
551
         */
552
        @Override
553
        public <V> ExecutionContext paramIfAbsent(final String parameterName, final V value, final SQLType sqlType) {
554
                if (!hasParam(parameterName)) {
1✔
555
                        param(parameterName, value, sqlType);
1✔
556
                }
557
                return this;
1✔
558
        }
559

560
        /**
561
         * {@inheritDoc}
562
         *
563
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramIfAbsent(java.lang.String, java.lang.Object, int)
564
         */
565
        @Override
566
        public <V> ExecutionContext paramIfAbsent(final String parameterName, final V value, final int sqlType) {
567
                if (!hasParam(parameterName)) {
1✔
568
                        param(parameterName, value, sqlType);
1✔
569
                }
570
                return this;
1✔
571
        }
572

573
        /**
574
         * {@inheritDoc}
575
         *
576
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramIfNotEmpty(java.lang.String, java.lang.Object)
577
         */
578
        @Override
579
        public <V> ExecutionContext paramIfNotEmpty(final String parameterName, final V value) {
580
                if (ObjectUtils.isNotEmpty(value)) {
1✔
581
                        param(parameterName, value);
1✔
582
                }
583
                return this;
1✔
584
        }
585

586
        /**
587
         * {@inheritDoc}
588
         *
589
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramIfNotEmpty(java.lang.String, java.lang.Object, java.sql.SQLType)
590
         */
591
        @Override
592
        public <V> ExecutionContext paramIfNotEmpty(final String parameterName, final V value, final SQLType sqlType) {
593
                if (ObjectUtils.isNotEmpty(value)) {
1✔
594
                        param(parameterName, value, sqlType);
1✔
595
                }
596
                return this;
1✔
597
        }
598

599
        /**
600
         * {@inheritDoc}
601
         *
602
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramIfNotEmpty(java.lang.String, java.lang.Object, int)
603
         */
604
        @Override
605
        public <V> ExecutionContext paramIfNotEmpty(final String parameterName, final V value, final int sqlType) {
606
                if (ObjectUtils.isNotEmpty(value)) {
1✔
607
                        param(parameterName, value, sqlType);
1✔
608
                }
609
                return this;
1✔
610
        }
611

612
        /**
613
         * {@inheritDoc}
614
         *
615
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramMap(java.util.Map)
616
         */
617
        @Override
618
        public ExecutionContext paramMap(final Map<String, Object> paramMap) {
619
                if (ObjectUtils.isNotEmpty(paramMap)) {
1✔
620
                        paramMap.forEach(this::param);
1✔
621
                }
622
                return this;
1✔
623
        }
624

625
        @Override
626
        public <V> ExecutionContext paramBean(final V bean) {
627
                if (ObjectUtils.isNotEmpty(bean)) {
1✔
628
                        BeanAccessor.fields(bean.getClass()).stream()
1✔
629
                                        .forEach(f -> param(f.getName(), BeanAccessor.value(f, bean)));
1✔
630
                }
631
                return this;
1✔
632
        }
633

634
        /**
635
         * {@inheritDoc}
636
         *
637
         * @see jp.co.future.uroborosql.fluent.SqlFluent#retry(int)
638
         */
639
        @Override
640
        public ExecutionContext retry(final int count) {
641
                return retry(count, 0);
1✔
642
        }
643

644
        /**
645
         * {@inheritDoc}
646
         *
647
         * @see jp.co.future.uroborosql.fluent.SqlFluent#retry(int, int)
648
         */
649
        @Override
650
        public ExecutionContext retry(final int count, final int waitTime) {
651
                return this.setMaxRetryCount(count).setRetryWaitTime(waitTime);
1✔
652
        }
653

654
        /**
655
         * {@inheritDoc}
656
         *
657
         * @see jp.co.future.uroborosql.fluent.SqlFluent#sqlId(String)
658
         */
659
        @Override
660
        public ExecutionContext sqlId(final String sqlId) {
661
                this.setSqlId(sqlId);
1✔
662
                return this;
1✔
663
        }
664

665
        /**
666
         * パラメータ名のリストを取得する
667
         *
668
         * @return パラメータ名のリスト
669
         */
670
        public Set<String> getParameterNames() {
671
                return parameterNames != null ? parameterNames : (parameterNames = new ParameterNames());
1✔
672
        }
673

674
        /**
675
         * {@inheritDoc}
676
         *
677
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#outParam(java.lang.String, java.sql.SQLType)
678
         */
679
        @Override
680
        public ExecutionContext outParam(final String parameterName, final SQLType sqlType) {
681
                return param(new OutParameter(parameterName, sqlType));
1✔
682
        }
683

684
        /**
685
         * {@inheritDoc}
686
         *
687
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#outParam(java.lang.String, int)
688
         */
689
        @Override
690
        public ExecutionContext outParam(final String parameterName, final int sqlType) {
691
                return param(new OutParameter(parameterName, sqlType));
1✔
692
        }
693

694
        /**
695
         * {@inheritDoc}
696
         *
697
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#inOutParam(java.lang.String, java.lang.Object, java.sql.SQLType)
698
         */
699
        @Override
700
        public <V> ExecutionContext inOutParam(final String parameterName, final V value, final SQLType sqlType) {
701
                return param(new InOutParameter(parameterName, value, sqlType));
1✔
702
        }
703

704
        /**
705
         * {@inheritDoc}
706
         *
707
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#inOutParamIfAbsent(java.lang.String, java.lang.Object, java.sql.SQLType)
708
         */
709
        @Override
710
        public <V> ExecutionContext inOutParamIfAbsent(final String parameterName, final V value, final SQLType sqlType) {
711
                if (!hasParam(parameterName)) {
1✔
712
                        inOutParam(parameterName, value, sqlType);
1✔
713
                }
714
                return this;
1✔
715
        }
716

717
        /**
718
         * {@inheritDoc}
719
         *
720
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#inOutParam(java.lang.String, java.lang.Object, int)
721
         */
722
        @Override
723
        public <V> ExecutionContext inOutParam(final String parameterName, final V value, final int sqlType) {
724
                return param(new InOutParameter(parameterName, value, sqlType));
1✔
725
        }
726

727
        /**
728
         * {@inheritDoc}
729
         *
730
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#inOutParamIfAbsent(java.lang.String, java.lang.Object, int)
731
         */
732
        @Override
733
        public <V> ExecutionContext inOutParamIfAbsent(final String parameterName, final V value, final int sqlType) {
734
                if (!hasParam(parameterName)) {
1✔
735
                        inOutParam(parameterName, value, sqlType);
1✔
736
                }
737
                return this;
1✔
738
        }
739

740
        /**
741
         * {@inheritDoc}
742
         *
743
         * @see jp.co.future.uroborosql.parser.TransformContext#addSqlPart(java.lang.String)
744
         */
745
        @Override
746
        public TransformContext addSqlPart(final String sqlPart) {
747
                executableSql.append(sqlPart);
1✔
748
                return this;
1✔
749
        }
750

751
        /**
752
         * {@inheritDoc}
753
         *
754
         * @see jp.co.future.uroborosql.parser.TransformContext#isEnabled()
755
         */
756
        @Override
757
        public boolean isEnabled() {
758
                return enabled;
1✔
759
        }
760

761
        /**
762
         * {@inheritDoc}
763
         *
764
         * @see jp.co.future.uroborosql.parser.TransformContext#setEnabled(boolean)
765
         */
766
        @Override
767
        public void setEnabled(final boolean enabled) {
768
                this.enabled = enabled;
1✔
769
        }
1✔
770

771
        /**
772
         * {@inheritDoc}
773
         *
774
         * @see jp.co.future.uroborosql.parser.TransformContext#addBindName(java.lang.String)
775
         */
776
        @Override
777
        public TransformContext addBindName(final String bindName) {
778
                bindNames.add(bindName);
1✔
779
                return this;
1✔
780
        }
781

782
        /**
783
         * {@inheritDoc}
784
         *
785
         * @see jp.co.future.uroborosql.parser.TransformContext#addBindNames(java.util.List)
786
         */
787
        @Override
788
        public TransformContext addBindNames(final List<String> bindNames) {
789
                this.bindNames.addAll(bindNames);
1✔
790
                return this;
1✔
791
        }
792

793
        /**
794
         * {@inheritDoc}
795
         *
796
         * @see jp.co.future.uroborosql.parser.TransformContext#getBindNames()
797
         */
798
        @Override
799
        public List<String> getBindNames() {
800
                return bindNames;
1✔
801
        }
802

803
        /**
804
         * {@inheritDoc}
805
         *
806
         * @see jp.co.future.uroborosql.parser.TransformContext#addBindVariable(java.lang.Object)
807
         */
808
        @Override
809
        public TransformContext addBindVariable(final Object bindVariable) {
810
                bindVariables.add(bindVariable);
1✔
811
                return this;
1✔
812
        }
813

814
        /**
815
         * {@inheritDoc}
816
         *
817
         * @see jp.co.future.uroborosql.parser.TransformContext#addBindVariables(java.lang.Object[])
818
         */
819
        @Override
820
        public TransformContext addBindVariables(final Object[] bindVariables) {
821
                Collections.addAll(this.bindVariables, bindVariables);
1✔
822
                return this;
1✔
823
        }
824

825
        /**
826
         * {@inheritDoc}
827
         *
828
         * @see jp.co.future.uroborosql.parser.TransformContext#getBindVariables()
829
         */
830
        @Override
831
        public Object[] getBindVariables() {
832
                return bindVariables.toArray();
1✔
833
        }
834

835
        /**
836
         * バインドパラメータ配列取得
837
         *
838
         * @return バインドパラメータ配列
839
         */
840
        public Parameter[] getBindParameters() {
841
                return bindNames.stream()
1✔
842
                                .map(this::getParam)
1✔
843
                                .filter(Objects::nonNull)
1✔
844
                                .toArray(Parameter[]::new);
1✔
845
        }
846

847
        /**
848
         * {@inheritDoc}
849
         *
850
         * @see jp.co.future.uroborosql.context.ExecutionContext#bindParams(java.sql.PreparedStatement)
851
         */
852
        @Override
853
        public ExecutionContext bindParams(final PreparedStatement preparedStatement) throws SQLException {
854
                var bindParameters = getBindParameters();
1✔
855

856
                var matchParams = new HashSet<String>();
1✔
857
                var parameterIndex = 1;
1✔
858
                for (var bindParameter : bindParameters) {
1✔
859
                        var parameter = bindParameter;
1✔
860
                        // パラメータ設定前イベント発行
861
                        if (getSqlConfig().getEventListenerHolder().hasBeforeSetParameterListener()) {
1✔
862
                                var eventObj = new BeforeSetParameterEvent(this, bindParameter);
1✔
863
                                getSqlConfig().getEventListenerHolder().getBeforeSetParameterListeners()
1✔
864
                                                .forEach(listener -> listener.accept(eventObj));
1✔
865
                                parameter = eventObj.getParameter();
1✔
866
                        }
867
                        parameterIndex = parameter.setParameter(preparedStatement, parameterIndex, parameterMapperManager);
1✔
868
                        matchParams.add(parameter.getParameterName());
1✔
869
                }
870
                // SQL上のバインドパラメータ群(bindNames)に対応する値がすべて設定されているかどうかをチェックする
871
                if (!matchParams.containsAll(bindNames)) {
1✔
872
                        var missMatchParams = new LinkedHashSet<>(bindNames);
1✔
873
                        missMatchParams.removeAll(matchParams);
1✔
874
                        throw new ParameterNotFoundRuntimeException("Parameter " + missMatchParams.toString() + " is not found.");
1✔
875
                }
876
                return this;
1✔
877
        }
878

879
        /**
880
         * {@inheritDoc}
881
         *
882
         * @see jp.co.future.uroborosql.context.ExecutionContext#bindBatchParams(java.sql.PreparedStatement)
883
         */
884
        @Override
885
        public ExecutionContext bindBatchParams(final PreparedStatement preparedStatement) throws SQLException {
886
                // parameterMap に設定されている共通のパラメータ(ESCAPE_CHARなど)を引き継ぐため、退避しておく
887
                var tempParamMap = new HashMap<>(parameterMap);
1✔
888
                for (var paramMap : batchParameters) {
1✔
889
                        var batchParamMap = new HashMap<>(tempParamMap);
1✔
890
                        batchParamMap.putAll(paramMap);
1✔
891
                        parameterMap = batchParamMap;
1✔
892
                        bindParams(preparedStatement);
1✔
893
                        preparedStatement.addBatch();
1✔
894
                }
1✔
895
                if (SQL_LOG.isDebugEnabled()) {
1✔
NEW
896
                        SQL_LOG.debug("{} items Added for batch process.", batchParameters.size());
×
897
                }
898
                return this;
1✔
899
        }
900

901
        /**
902
         * {@inheritDoc}
903
         *
904
         * @see jp.co.future.uroborosql.context.ExecutionContext#getOutParams(java.sql.CallableStatement)
905
         */
906
        @Override
907
        public Map<String, Object> getOutParams(final CallableStatement callableStatement) throws SQLException {
908
                var out = new HashMap<String, Object>();
1✔
909
                var bindParameters = getBindParameters();
1✔
910
                var parameterIndex = 1;
1✔
911
                for (var parameter : bindParameters) {
1✔
912
                        if (parameter instanceof OutParameter) {
1✔
913
                                var key = parameter.getParameterName();
1✔
914
                                var value = callableStatement.getObject(parameterIndex);
1✔
915
                                // OUTパラメータ取得後イベント発行
916
                                if (getSqlConfig().getEventListenerHolder().hasAfterGetOutParameterListener()) {
1✔
917
                                        var eventObj = new AfterGetOutParameterEvent(this, key, value, callableStatement, parameterIndex);
1✔
918
                                        getSqlConfig().getEventListenerHolder().getAfterGetOutParameterListeners()
1✔
919
                                                        .forEach(listener -> listener.accept(eventObj));
1✔
920
                                        value = eventObj.getValue();
1✔
921
                                }
922
                                out.put(key, value);
1✔
923

924
                        }
925
                        parameterIndex++;
1✔
926
                }
927

928
                if (SQL_LOG.isDebugEnabled()) {
1✔
NEW
929
                        SQL_LOG.debug("Stored procedure out parameter[{}]", out);
×
930
                }
931
                return out;
1✔
932
        }
933

934
        /**
935
         * {@inheritDoc}
936
         *
937
         * @see jp.co.future.uroborosql.context.ExecutionContext#addBatch()
938
         */
939
        @Override
940
        public ExecutionContext addBatch() {
941
                // SQLパース前イベントの呼出
942
                if (getSqlConfig().getEventListenerHolder().hasBeforeParseSqlListener()) {
1✔
943
                        var eventObj = new BeforeParseSqlEvent(this);
1✔
944
                        getSqlConfig().getEventListenerHolder().getBeforeParseSqlListeners()
1✔
945
                                        .forEach(listener -> listener.accept(eventObj));
1✔
946
                }
947
                batchParameters.add(parameterMap);
1✔
948
                // バッチ処理では毎回同じ数のパラメータが追加されることが多いのでMap生成時のinitialCapacityを指定してマップのリサイズ処理を極力発生させないようにする
949
                parameterMap = new HashMap<>(calcInitialCapacity(parameterMap.size()));
1✔
950
                return this;
1✔
951
        }
952

953
        /**
954
         * HashMapで指定されたbaseSize内で収まっていればresizeが発生しない初期容量を計算する.
955
         * @param baseSize 基底となるMapのサイズ
956
         * @return 初期容量
957
         */
958
        private int calcInitialCapacity(final int baseSize) {
959
                // MapのloadFactorはデフォルト0.75(3/4)なので 4/3 を掛けてcapacityを計算する。そのうえで切り捨てが発生してもキャパシティを越えないよう +1 している。
960
                return baseSize * 4 / 3 + 1;
1✔
961
        }
962

963
        /**
964
         * {@inheritDoc}
965
         *
966
         * @see jp.co.future.uroborosql.context.ExecutionContext#clearBatch()
967
         */
968
        @Override
969
        public ExecutionContext clearBatch() {
970
                batchParameters.clear();
1✔
971
                return this;
1✔
972
        }
973

974
        /**
975
         * {@inheritDoc}
976
         *
977
         * @see jp.co.future.uroborosql.context.ExecutionContext#batchCount()
978
         */
979
        @Override
980
        public int batchCount() {
981
                return batchParameters.size();
1✔
982
        }
983

984
        /**
985
         * {@inheritDoc}
986
         *
987
         * @see jp.co.future.uroborosql.context.ExecutionContext#addDefineColumnType(int, int)
988
         */
989
        @Override
990
        public ExecutionContext addDefineColumnType(final int column, final int type) {
991
                defineColumnTypeMap.put(column, type);
1✔
992
                return this;
1✔
993
        }
994

995
        /**
996
         * {@inheritDoc}
997
         *
998
         * @see jp.co.future.uroborosql.context.ExecutionContext#getDefineColumnTypes()
999
         */
1000
        @Override
1001
        public Map<Integer, Integer> getDefineColumnTypes() {
1002
                return defineColumnTypeMap;
1✔
1003
        }
1004

1005
        /**
1006
         * {@inheritDoc}
1007
         *
1008
         * @see jp.co.future.uroborosql.context.ExecutionContext#setResultSetType(int)
1009
         */
1010
        @Override
1011
        public ExecutionContext setResultSetType(final int resultSetType) {
1012
                this.resultSetType = resultSetType;
1✔
1013
                return this;
1✔
1014
        }
1015

1016
        /**
1017
         * {@inheritDoc}
1018
         *
1019
         * @see jp.co.future.uroborosql.context.ExecutionContext#getResultSetType()
1020
         */
1021
        @Override
1022
        public int getResultSetType() {
1023
                return resultSetType;
1✔
1024
        }
1025

1026
        /**
1027
         * {@inheritDoc}
1028
         *
1029
         * @see jp.co.future.uroborosql.context.ExecutionContext#setResultSetConcurrency(int)
1030
         */
1031
        @Override
1032
        public ExecutionContext setResultSetConcurrency(final int resultSetConcurrency) {
1033
                this.resultSetConcurrency = resultSetConcurrency;
1✔
1034
                return this;
1✔
1035
        }
1036

1037
        /**
1038
         * {@inheritDoc}
1039
         *
1040
         * @see jp.co.future.uroborosql.context.ExecutionContext#getResultSetConcurrency()
1041
         */
1042
        @Override
1043
        public int getResultSetConcurrency() {
1044
                return resultSetConcurrency;
1✔
1045
        }
1046

1047
        /**
1048
         * {@inheritDoc}
1049
         *
1050
         * @see jp.co.future.uroborosql.context.ExecutionContext#getSqlKind()
1051
         */
1052
        @Override
1053
        public SqlKind getSqlKind() {
1054
                return sqlKind;
1✔
1055
        }
1056

1057
        /**
1058
         * {@inheritDoc}
1059
         *
1060
         * @see jp.co.future.uroborosql.context.ExecutionContext#setSqlKind(jp.co.future.uroborosql.enums.SqlKind)
1061
         */
1062
        @Override
1063
        public ExecutionContext setSqlKind(final SqlKind sqlKind) {
1064
                this.sqlKind = sqlKind;
1✔
1065
                return this;
1✔
1066
        }
1067

1068
        /**
1069
         * 定数パラメータマップの取得
1070
         *
1071
         * @return 定数パラメータマップ
1072
         */
1073
        public Map<String, Parameter> getConstParameterMap() {
1074
                return constParameterMap;
1✔
1075
        }
1076

1077
        /**
1078
         * 定数パラメータマップの設定
1079
         *
1080
         * @param constParameterMap 定数パラメータマップ
1081
         */
1082
        public void setConstParameterMap(final Map<String, Parameter> constParameterMap) {
1083
                this.constParameterMap = constParameterMap;
1✔
1084
        }
1✔
1085

1086
        /**
1087
         * パラメータ変換マネージャを取得します
1088
         *
1089
         * @return パラメータ変換マネージャ
1090
         */
1091
        public BindParameterMapperManager getParameterMapperManager() {
1092
                return parameterMapperManager;
1✔
1093
        }
1094

1095
        /**
1096
         * パラメータ変換マネージャを設定します
1097
         *
1098
         * @param parameterMapperManager パラメータ変換マネージャ
1099
         */
1100
        public void setParameterMapperManager(final BindParameterMapperManager parameterMapperManager) {
1101
                this.parameterMapperManager = parameterMapperManager;
1✔
1102
        }
1✔
1103

1104
        /**
1105
         * {@inheritDoc}
1106
         *
1107
         * @see jp.co.future.uroborosql.context.ExecutionContext#contextAttrs()
1108
         */
1109
        @Override
1110
        public Map<String, Object> contextAttrs() {
1111
                return contextAttributes;
1✔
1112
        }
1113

1114
        /**
1115
         * {@inheritDoc}
1116
         *
1117
         * @see jp.co.future.uroborosql.context.ExecutionContext#formatParams()
1118
         */
1119
        @Override
1120
        public String formatParams() {
1121
                var sb = new StringBuilder();
1✔
1122
                for (var i = 0; i < bindNames.size(); i++) {
1✔
1123
                        sb.append(String.format("[%s=%s]", bindNames.get(i), bindVariables.get(i)));
1✔
1124
                }
1125
                return sb.toString();
1✔
1126
        }
1127

1128
        /**
1129
         * {@inheritDoc}
1130
         *
1131
         * @see jp.co.future.uroborosql.context.ExecutionContext#getGeneratedKeyColumns()
1132
         */
1133
        @Override
1134
        public String[] getGeneratedKeyColumns() {
1135
                return this.generatedKeyColumns;
1✔
1136
        }
1137

1138
        /**
1139
         * {@inheritDoc}
1140
         *
1141
         * @see jp.co.future.uroborosql.context.ExecutionContext#setGeneratedKeyColumns(java.lang.String[])
1142
         */
1143
        @Override
1144
        public ExecutionContext setGeneratedKeyColumns(final String[] generatedKeyColumns) {
1145
                this.generatedKeyColumns = generatedKeyColumns;
1✔
1146
                return this;
1✔
1147
        }
1148

1149
        /**
1150
         * {@inheritDoc}
1151
         *
1152
         * @see jp.co.future.uroborosql.context.ExecutionContext#getGeneratedKeyValues()
1153
         */
1154
        @Override
1155
        public Object[] getGeneratedKeyValues() {
1156
                return this.generatedKeyValues;
1✔
1157
        }
1158

1159
        /**
1160
         * {@inheritDoc}
1161
         *
1162
         * @see jp.co.future.uroborosql.context.ExecutionContext#setGeneratedKeyValues(java.lang.Object[])
1163
         */
1164
        @Override
1165
        public ExecutionContext setGeneratedKeyValues(final Object[] generatedKeyValues) {
1166
                this.generatedKeyValues = generatedKeyValues;
1✔
1167
                return this;
1✔
1168
        }
1169

1170
        /**
1171
         * {@inheritDoc}
1172
         *
1173
         * @see jp.co.future.uroborosql.context.ExecutionContext#hasGeneratedKeyColumns()
1174
         */
1175
        @Override
1176
        public boolean hasGeneratedKeyColumns() {
1177
                return getGeneratedKeyColumns() != null && getGeneratedKeyColumns().length > 0;
1✔
1178
        }
1179

1180
        /**
1181
         * {@inheritDoc}
1182
         *
1183
         * @see jp.co.future.uroborosql.context.ExecutionContext#getUpdateDelegate()
1184
         */
1185
        @Override
1186
        public Function<ExecutionContext, Integer> getUpdateDelegate() {
1187
                return this.updateDelegate;
1✔
1188
        }
1189

1190
        /**
1191
         * {@inheritDoc}
1192
         *
1193
         * @see jp.co.future.uroborosql.context.ExecutionContext#setUpdateDelegate(java.util.function.Function)
1194
         */
1195
        @Override
1196
        public ExecutionContext setUpdateDelegate(final Function<ExecutionContext, Integer> updateDelegate) {
1197
                this.updateDelegate = updateDelegate;
1✔
1198
                return this;
1✔
1199
        }
1200

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