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

future-architect / uroborosql / #693

pending completion
#693

push

HidekiSugimoto189
SubParameter logic bug fix

4 of 4 new or added lines in 1 file covered. (100.0%)

7896 of 8763 relevant lines covered (90.11%)

0.9 hits per line

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

99.25
/src/main/java/jp/co/future/uroborosql/context/SqlContextImpl.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.Arrays;
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.Consumer;
28
import java.util.function.Function;
29
import java.util.function.Supplier;
30
import java.util.regex.Matcher;
31
import java.util.regex.Pattern;
32

33
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35

36
import jp.co.future.uroborosql.enums.SqlKind;
37
import jp.co.future.uroborosql.exception.ParameterNotFoundRuntimeException;
38
import jp.co.future.uroborosql.filter.SqlFilterManager;
39
import jp.co.future.uroborosql.filter.SqlFilterManagerImpl;
40
import jp.co.future.uroborosql.parameter.InOutParameter;
41
import jp.co.future.uroborosql.parameter.OutParameter;
42
import jp.co.future.uroborosql.parameter.Parameter;
43
import jp.co.future.uroborosql.parameter.ReaderParameter;
44
import jp.co.future.uroborosql.parameter.StreamParameter;
45
import jp.co.future.uroborosql.parameter.mapper.BindParameterMapperManager;
46
import jp.co.future.uroborosql.parser.TransformContext;
47
import jp.co.future.uroborosql.utils.BeanAccessor;
48
import jp.co.future.uroborosql.utils.StringUtils;
49

50
/**
51
 * SQLコンテキスト実装クラス
52
 *
53
 * @author H.Sugimoto
54
 */
55
public class SqlContextImpl implements SqlContext {
56
        /**
57
         * @see #getParameterNames()
58
         */
59
        private class ParameterNames extends AbstractSet<String> {
1✔
60

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

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

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

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

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

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

89
        /** ロガー */
90
        private static final Logger LOG = LoggerFactory.getLogger(SqlContextImpl.class);
1✔
91

92
        /** SQL名 */
93
        private String sqlName;
94

95
        /** 変換前のSQL文 */
96
        private String originalSql;
97

98
        /** 変換後のSQL文 */
99
        private final StringBuilder executableSql = new StringBuilder();
1✔
100

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

104
        /** SQL文の識別子 */
105
        private String sqlId;
106

107
        /** SQLを実行するスキーマ */
108
        private String schema;
109

110
        /** SQL実行の最大リトライ数 */
111
        private int maxRetryCount = 0;
1✔
112

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

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

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

122
        /** SqlFilter管理クラス */
123
        private SqlFilterManager sqlFilterManager = new SqlFilterManagerImpl();
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
        /** 自動パラメータバインド関数(query用) */
159
        private Consumer<SqlContext> queryAutoParameterBinder = null;
1✔
160

161
        /** 自動パラメータバインド関数(update/batch/proc用) */
162
        private Consumer<SqlContext> updateAutoParameterBinder = null;
1✔
163

164
        /** パラメータ変換マネージャ */
165
        private BindParameterMapperManager parameterMapperManager;
166

167
        /** パラメータ名Set */
168
        private ParameterNames parameterNames;
169

170
        /** 更新処理実行時に通常の更新SQL発行の代わりに移譲する処理. */
171
        private Function<SqlContext, Integer> updateDelegate;
172

173
        /**
174
         * コンストラクタ。
175
         */
176
        SqlContextImpl() {
1✔
177
        }
1✔
178

179
        /**
180
         * コピーコンストラクタ
181
         *
182
         * @param parent コピー元のSQLコンテキスト
183
         */
184
        private SqlContextImpl(final SqlContextImpl parent) {
1✔
185
                enabled = false;
1✔
186
                sqlId = parent.sqlId;
1✔
187
                sqlName = parent.sqlName;
1✔
188
                maxRetryCount = parent.maxRetryCount;
1✔
189
                retryWaitTime = parent.retryWaitTime;
1✔
190
                parameterMap = parent.parameterMap;
1✔
191
                constParameterMap = parent.constParameterMap;
1✔
192
                sqlFilterManager = parent.sqlFilterManager;
1✔
193
                batchParameters.addAll(parent.batchParameters);
1✔
194
                defineColumnTypeMap.putAll(parent.defineColumnTypeMap);
1✔
195
                resultSetType = parent.resultSetType;
1✔
196
                resultSetConcurrency = parent.resultSetConcurrency;
1✔
197
                sqlKind = parent.sqlKind;
1✔
198
                contextAttributes.putAll(parent.contextAttributes);
1✔
199
                queryAutoParameterBinder = parent.queryAutoParameterBinder;
1✔
200
                parameterMapperManager = parent.parameterMapperManager;
1✔
201
        }
1✔
202

203
        /**
204
         * {@inheritDoc}
205
         *
206
         * @see jp.co.future.uroborosql.parser.TransformContext#copyTransformContext()
207
         */
208
        @Override
209
        public TransformContext copyTransformContext() {
210
                return new SqlContextImpl(this);
1✔
211
        }
212

213
        /**
214
         * {@inheritDoc}
215
         *
216
         * @see jp.co.future.uroborosql.parser.TransformContext#getExecutableSql()
217
         */
218
        @Override
219
        public String getExecutableSql() {
220
                if (StringUtils.isEmpty(executableSqlCache)) {
1✔
221
                        if (executableSql.length() > 0) {
1✔
222
                                executableSqlCache = executableSql.toString();
1✔
223
                                if (executableSqlCache.toUpperCase().contains("WHERE")) {
1✔
224
                                        // where句の直後に来るANDやORの除去
225
                                        StringBuffer buff = new StringBuffer();
1✔
226
                                        Matcher matcher = WHERE_CLAUSE_PATTERN.matcher(executableSqlCache);
1✔
227
                                        while (matcher.find()) {
1✔
228
                                                String whereClause = matcher.group("clause");
1✔
229
                                                matcher.appendReplacement(buff, whereClause);
1✔
230
                                        }
1✔
231
                                        matcher.appendTail(buff);
1✔
232
                                        executableSqlCache = buff.toString();
1✔
233
                                }
234
                                // 各句の直後に現れる不要なカンマの除去
235
                                StringBuffer buff = new StringBuffer();
1✔
236
                                Matcher removeCommaMatcher = REMOVE_FIRST_COMMA_PATTERN.matcher(executableSqlCache);
1✔
237
                                while (removeCommaMatcher.find()) {
1✔
238
                                        String clauseWords = removeCommaMatcher.group("keyword");
1✔
239
                                        removeCommaMatcher.appendReplacement(buff, clauseWords);
1✔
240
                                }
1✔
241
                                removeCommaMatcher.appendTail(buff);
1✔
242
                                executableSqlCache = buff.toString();
1✔
243

244
                                // 空行の除去
245
                                executableSqlCache = CLEAR_BLANK_PATTERN.matcher(executableSqlCache).replaceAll("");
1✔
246
                        }
247
                }
248
                return executableSqlCache;
1✔
249
        }
250

251
        /**
252
         * {@inheritDoc}
253
         *
254
         * @see jp.co.future.uroborosql.context.SqlContext#getSql()
255
         */
256
        @Override
257
        public String getSql() {
258
                return originalSql;
1✔
259
        }
260

261
        /**
262
         * {@inheritDoc}
263
         *
264
         * @see jp.co.future.uroborosql.context.SqlContext#setSql(java.lang.String)
265
         */
266
        @Override
267
        public SqlContext setSql(final String originalSql) {
268
                this.originalSql = originalSql;
1✔
269
                return this;
1✔
270
        }
271

272
        /**
273
         * {@inheritDoc}
274
         *
275
         * @see jp.co.future.uroborosql.context.SqlContext#getSqlName()
276
         */
277
        @Override
278
        public String getSqlName() {
279
                return sqlName;
1✔
280
        }
281

282
        /**
283
         * {@inheritDoc}
284
         *
285
         * @see jp.co.future.uroborosql.context.SqlContext#setSqlName(java.lang.String)
286
         */
287
        @Override
288
        public SqlContext setSqlName(final String sqlName) {
289
                this.sqlName = sqlName;
1✔
290
                return this;
1✔
291
        }
292

293
        /**
294
         * {@inheritDoc}
295
         *
296
         * @see jp.co.future.uroborosql.context.SqlContext#getSqlId()
297
         */
298
        @Override
299
        public String getSqlId() {
300
                return sqlId;
1✔
301
        }
302

303
        /**
304
         * {@inheritDoc}
305
         *
306
         * @see jp.co.future.uroborosql.context.SqlContext#setSqlId(java.lang.String)
307
         */
308
        @Override
309
        public SqlContext setSqlId(final String sqlId) {
310
                this.sqlId = sqlId;
1✔
311
                return this;
1✔
312
        }
313

314
        /**
315
         * {@inheritDoc}
316
         *
317
         * @see jp.co.future.uroborosql.context.SqlContext#getSchema()
318
         */
319
        @Override
320
        public String getSchema() {
321
                return this.schema;
1✔
322
        }
323

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

335
        /**
336
         * {@inheritDoc}
337
         *
338
         * @see jp.co.future.uroborosql.context.SqlContext#getMaxRetryCount()
339
         */
340
        @Override
341
        public int getMaxRetryCount() {
342
                return maxRetryCount;
1✔
343
        }
344

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

356
        /**
357
         * {@inheritDoc}
358
         *
359
         * @see jp.co.future.uroborosql.context.SqlContext#getRetryWaitTime()
360
         */
361
        @Override
362
        public int getRetryWaitTime() {
363
                return retryWaitTime;
1✔
364
        }
365

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

377
        /**
378
         * {@inheritDoc}
379
         *
380
         * @see jp.co.future.uroborosql.parser.TransformContext#getParam(java.lang.String)
381
         */
382
        @Override
383
        public Parameter getParam(final String paramName) {
384
                Parameter param = getBindParameter(paramName);
1✔
385
                if (param == null) {
1✔
386
                        Map<String, Parameter> constParams = getConstParameterMap();
1✔
387
                        if (constParams != null) {
1✔
388
                                param = constParams.get(paramName.toUpperCase());
1✔
389
                        }
390
                }
391
                return param;
1✔
392
        }
393

394
        /**
395
         * parameterMapから指定されたキーのパラメータを取得する
396
         *
397
         * @param paramName パラメータ名
398
         * @return パラメータ
399
         */
400
        private Parameter getBindParameter(final String paramName) {
401
                if (!paramName.contains(".")) {
1✔
402
                        return parameterMap.get(paramName);
1✔
403
                } else {
404
                        // メソッド呼び出しかどうかで処理を振り分け
405
                        if (paramName.contains("(") && paramName.contains(")")) {
1✔
406
                                // メソッド呼び出しの場合は、SqlParserで値を評価するタイミングでparameterをaddしているので、そのまま返却する
407
                                return parameterMap.get(paramName);
1✔
408
                        } else {
409
                                // サブパラメータの作成
410
                                String[] keys = paramName.split("\\.");
1✔
411
                                String baseName = keys[0];
1✔
412

413
                                Parameter parameter = parameterMap.get(baseName);
1✔
414
                                if (parameter == null) {
1✔
415
                                        return null;
×
416
                                }
417

418
                                if (keys.length > 1) {
1✔
419
                                        String propertyName = keys[1];
1✔
420
                                        return parameter.createSubParameter(propertyName);
1✔
421
                                }
422
                                return parameter;
×
423
                        }
424
                }
425
        }
426

427
        /**
428
         * {@inheritDoc}
429
         *
430
         * @see jp.co.future.uroborosql.fluent.SqlFluent#context()
431
         */
432
        @Override
433
        public SqlContext context() {
434
                return this;
1✔
435
        }
436

437
        /**
438
         * {@inheritDoc}
439
         *
440
         * @see jp.co.future.uroborosql.fluent.SqlFluent#hasParam(java.lang.String)
441
         */
442
        @Override
443
        public boolean hasParam(final String paramName) {
444
                return parameterMap.containsKey(paramName);
1✔
445
        }
446

447
        /**
448
         * パラメータの追加
449
         *
450
         * @param parameter パラメータ
451
         *
452
         * @return SqlContext
453
         */
454
        private SqlContext param(final Parameter parameter) {
455
                parameterMap.put(parameter.getParameterName(), parameter);
1✔
456
                return this;
1✔
457
        }
458

459
        /**
460
         * {@inheritDoc}
461
         *
462
         * @see jp.co.future.uroborosql.parser.TransformContext#param(java.lang.String, java.lang.Object)
463
         */
464
        @Override
465
        public <V> SqlContext param(final String parameterName, final V value) {
466
                return param(new Parameter(parameterName, value));
1✔
467
        }
468

469
        /**
470
         * {@inheritDoc}
471
         *
472
         * @see jp.co.future.uroborosql.fluent.SqlFluent#param(String, Supplier)
473
         */
474
        @Override
475
        public <V> SqlContext param(final String paramName, final Supplier<V> supplier) {
476
                return this.param(paramName, supplier != null ? supplier.get() : null);
1✔
477
        }
478

479
        /**
480
         * {@inheritDoc}
481
         *
482
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramIfAbsent(java.lang.String, java.lang.Object)
483
         */
484
        @Override
485
        public <V> SqlContext paramIfAbsent(final String parameterName, final V value) {
486
                if (!hasParam(parameterName)) {
1✔
487
                        param(parameterName, value);
1✔
488
                }
489
                return this;
1✔
490
        }
491

492
        /**
493
         * {@inheritDoc}
494
         *
495
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramList(String, Object...)
496
         */
497
        @Override
498
        @Deprecated
499
        public <V> SqlContext paramList(final String parameterName, @SuppressWarnings("unchecked") final V... value) {
500
                return param(parameterName, Arrays.asList(value));
1✔
501
        }
502

503
        /**
504
         * {@inheritDoc}
505
         *
506
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramList(java.lang.String, java.util.function.Supplier)
507
         */
508
        @Override
509
        @Deprecated
510
        public <V> SqlContext paramList(final String parameterName, final Supplier<Iterable<V>> supplier) {
511
                return param(parameterName, supplier);
1✔
512
        }
513

514
        /**
515
         * {@inheritDoc}
516
         *
517
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramListIfAbsent(String, Object...)
518
         */
519
        @Override
520
        @Deprecated
521
        public <V> SqlContext paramListIfAbsent(final String parameterName,
522
                        @SuppressWarnings("unchecked") final V... value) {
523
                return paramIfAbsent(parameterName, Arrays.asList(value));
1✔
524
        }
525

526
        /**
527
         * {@inheritDoc}
528
         *
529
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramMap(java.util.Map)
530
         */
531
        @Override
532
        public SqlContext paramMap(final Map<String, Object> paramMap) {
533
                if (paramMap != null) {
1✔
534
                        paramMap.forEach((k, v) -> param(k, v));
1✔
535
                }
536
                return this;
1✔
537
        }
538

539
        @Override
540
        public <V> SqlContext paramBean(final V bean) {
541
                if (bean != null) {
1✔
542
                        BeanAccessor.fields(bean.getClass()).stream()
1✔
543
                                        .forEach(f -> param(f.getName(), BeanAccessor.value(f, bean)));
1✔
544
                }
545
                return this;
1✔
546
        }
547

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

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

571
        /**
572
         * {@inheritDoc}
573
         *
574
         * @see jp.co.future.uroborosql.fluent.SqlFluent#param(java.lang.String, java.lang.Object, int)
575
         */
576
        @Override
577
        public <V> SqlContext param(final String parameterName, final V value, final int sqlType) {
578
                return param(new Parameter(parameterName, value, sqlType));
1✔
579
        }
580

581
        /**
582
         * {@inheritDoc}
583
         *
584
         * @see jp.co.future.uroborosql.fluent.SqlFluent#paramIfAbsent(java.lang.String, java.lang.Object, int)
585
         */
586
        @Override
587
        public <V> SqlContext paramIfAbsent(final String parameterName, final V value, final int sqlType) {
588
                if (!hasParam(parameterName)) {
1✔
589
                        param(parameterName, value, sqlType);
1✔
590
                }
591
                return this;
1✔
592
        }
593

594
        /**
595
         * パラメータ名のリストを取得する
596
         *
597
         * @return パラメータ名のリスト
598
         */
599
        public Set<String> getParameterNames() {
600
                return parameterNames != null ? parameterNames : (parameterNames = new ParameterNames());
1✔
601
        }
602

603
        /**
604
         * {@inheritDoc}
605
         *
606
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#outParam(java.lang.String, java.sql.SQLType)
607
         */
608
        @Override
609
        public SqlContext outParam(final String parameterName, final SQLType sqlType) {
610
                return param(new OutParameter(parameterName, sqlType));
1✔
611
        }
612

613
        /**
614
         * {@inheritDoc}
615
         *
616
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#outParam(java.lang.String, int)
617
         */
618
        @Override
619
        public SqlContext outParam(final String parameterName, final int sqlType) {
620
                return param(new OutParameter(parameterName, sqlType));
1✔
621
        }
622

623
        /**
624
         * {@inheritDoc}
625
         *
626
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#inOutParam(java.lang.String, java.lang.Object, java.sql.SQLType)
627
         */
628
        @Override
629
        public <V> SqlContext inOutParam(final String parameterName, final V value, final SQLType sqlType) {
630
                return param(new InOutParameter(parameterName, value, sqlType));
1✔
631
        }
632

633
        /**
634
         * {@inheritDoc}
635
         *
636
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#inOutParamIfAbsent(java.lang.String, java.lang.Object, java.sql.SQLType)
637
         */
638
        @Override
639
        public <V> SqlContext inOutParamIfAbsent(final String parameterName, final V value, final SQLType sqlType) {
640
                if (!hasParam(parameterName)) {
1✔
641
                        inOutParam(parameterName, value, sqlType);
1✔
642
                }
643
                return this;
1✔
644
        }
645

646
        /**
647
         * {@inheritDoc}
648
         *
649
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#inOutParam(java.lang.String, java.lang.Object, int)
650
         */
651
        @Override
652
        public <V> SqlContext inOutParam(final String parameterName, final V value, final int sqlType) {
653
                return param(new InOutParameter(parameterName, value, sqlType));
1✔
654
        }
655

656
        /**
657
         * {@inheritDoc}
658
         *
659
         * @see jp.co.future.uroborosql.fluent.ProcedureFluent#inOutParamIfAbsent(java.lang.String, java.lang.Object, int)
660
         */
661
        @Override
662
        public <V> SqlContext inOutParamIfAbsent(final String parameterName, final V value, final int sqlType) {
663
                if (!hasParam(parameterName)) {
1✔
664
                        inOutParam(parameterName, value, sqlType);
1✔
665
                }
666
                return this;
1✔
667
        }
668

669
        /**
670
         * {@inheritDoc}
671
         *
672
         * @see jp.co.future.uroborosql.fluent.SqlFluent#blobParam(java.lang.String, java.io.InputStream)
673
         */
674
        @Override
675
        public SqlContext blobParam(final String parameterName, final InputStream value) {
676
                return param(new StreamParameter(parameterName, value));
1✔
677
        }
678

679
        /**
680
         * {@inheritDoc}
681
         *
682
         * @see jp.co.future.uroborosql.fluent.SqlFluent#blobParamIfAbsent(java.lang.String, java.io.InputStream)
683
         */
684
        @Override
685
        public SqlContext blobParamIfAbsent(final String parameterName, final InputStream value) {
686
                if (!hasParam(parameterName)) {
1✔
687
                        blobParam(parameterName, value);
1✔
688
                }
689
                return this;
1✔
690
        }
691

692
        /**
693
         * {@inheritDoc}
694
         *
695
         * @see jp.co.future.uroborosql.fluent.SqlFluent#blobParam(java.lang.String, java.io.InputStream, int)
696
         */
697
        @Override
698
        public SqlContext blobParam(final String parameterName, final InputStream value, final int len) {
699
                return param(new StreamParameter(parameterName, value, len));
1✔
700
        }
701

702
        /**
703
         * {@inheritDoc}
704
         *
705
         * @see jp.co.future.uroborosql.fluent.SqlFluent#blobParamIfAbsent(java.lang.String, java.io.InputStream, int)
706
         */
707
        @Override
708
        public SqlContext blobParamIfAbsent(final String parameterName, final InputStream value, final int len) {
709
                if (!hasParam(parameterName)) {
1✔
710
                        blobParam(parameterName, value, len);
1✔
711
                }
712
                return this;
1✔
713
        }
714

715
        /**
716
         * {@inheritDoc}
717
         *
718
         * @see jp.co.future.uroborosql.fluent.SqlFluent#clobParam(java.lang.String, java.io.Reader)
719
         */
720
        @Override
721
        public SqlContext clobParam(final String paramName, final Reader value) {
722
                return param(new ReaderParameter(paramName, value));
1✔
723
        }
724

725
        /**
726
         * {@inheritDoc}
727
         *
728
         * @see jp.co.future.uroborosql.fluent.SqlFluent#clobParamIfAbsent(java.lang.String, java.io.Reader)
729
         */
730
        @Override
731
        public SqlContext clobParamIfAbsent(final String paramName, final Reader value) {
732
                if (!hasParam(paramName)) {
1✔
733
                        clobParam(paramName, value);
1✔
734
                }
735
                return this;
1✔
736
        }
737

738
        /**
739
         * {@inheritDoc}
740
         *
741
         * @see jp.co.future.uroborosql.fluent.SqlFluent#clobParam(java.lang.String, java.io.Reader, int)
742
         */
743
        @Override
744
        public SqlContext clobParam(final String paramName, final Reader value, final int len) {
745
                return param(new ReaderParameter(paramName, value, len));
1✔
746
        }
747

748
        /**
749
         * {@inheritDoc}
750
         *
751
         * @see jp.co.future.uroborosql.fluent.SqlFluent#clobParamIfAbsent(java.lang.String, java.io.Reader, int)
752
         */
753
        @Override
754
        public SqlContext clobParamIfAbsent(final String paramName, final Reader value, final int len) {
755
                if (!hasParam(paramName)) {
1✔
756
                        clobParam(paramName, value, len);
1✔
757
                }
758
                return this;
1✔
759
        }
760

761
        /**
762
         * {@inheritDoc}
763
         *
764
         * @see jp.co.future.uroborosql.fluent.SqlFluent#retry(int)
765
         */
766
        @Override
767
        public SqlContext retry(final int count) {
768
                return retry(count, 0);
1✔
769
        }
770

771
        /**
772
         * {@inheritDoc}
773
         *
774
         * @see jp.co.future.uroborosql.fluent.SqlFluent#retry(int, int)
775
         */
776
        @Override
777
        public SqlContext retry(final int count, final int waitTime) {
778
                return this.setMaxRetryCount(count).setRetryWaitTime(waitTime);
1✔
779
        }
780

781
        /**
782
         * {@inheritDoc}
783
         *
784
         * @see jp.co.future.uroborosql.fluent.SqlFluent#sqlId(String)
785
         */
786
        @Override
787
        public SqlContext sqlId(final String sqlId) {
788
                this.setSqlId(sqlId);
1✔
789
                return this;
1✔
790
        }
791

792
        /**
793
         * {@inheritDoc}
794
         *
795
         * @see jp.co.future.uroborosql.parser.TransformContext#addSqlPart(java.lang.String)
796
         */
797
        @Override
798
        public TransformContext addSqlPart(final String sqlPart) {
799
                executableSql.append(sqlPart);
1✔
800
                return this;
1✔
801
        }
802

803
        /**
804
         * {@inheritDoc}
805
         *
806
         * @see jp.co.future.uroborosql.parser.TransformContext#isEnabled()
807
         */
808
        @Override
809
        public boolean isEnabled() {
810
                return enabled;
1✔
811
        }
812

813
        /**
814
         * {@inheritDoc}
815
         *
816
         * @see jp.co.future.uroborosql.parser.TransformContext#setEnabled(boolean)
817
         */
818
        @Override
819
        public void setEnabled(final boolean enabled) {
820
                this.enabled = enabled;
1✔
821
        }
1✔
822

823
        /**
824
         * {@inheritDoc}
825
         *
826
         * @see jp.co.future.uroborosql.parser.TransformContext#addBindName(java.lang.String)
827
         */
828
        @Override
829
        public TransformContext addBindName(final String bindName) {
830
                bindNames.add(bindName);
1✔
831
                return this;
1✔
832
        }
833

834
        /**
835
         * {@inheritDoc}
836
         *
837
         * @see jp.co.future.uroborosql.parser.TransformContext#addBindNames(java.util.List)
838
         */
839
        @Override
840
        public TransformContext addBindNames(final List<String> bindNames) {
841
                this.bindNames.addAll(bindNames);
1✔
842
                return this;
1✔
843
        }
844

845
        /**
846
         * {@inheritDoc}
847
         *
848
         * @see jp.co.future.uroborosql.parser.TransformContext#getBindNames()
849
         */
850
        @Override
851
        public List<String> getBindNames() {
852
                return bindNames;
1✔
853
        }
854

855
        /**
856
         * {@inheritDoc}
857
         *
858
         * @see jp.co.future.uroborosql.parser.TransformContext#addBindVariable(java.lang.Object)
859
         */
860
        @Override
861
        public TransformContext addBindVariable(final Object bindVariable) {
862
                bindVariables.add(bindVariable);
1✔
863
                return this;
1✔
864
        }
865

866
        /**
867
         * {@inheritDoc}
868
         *
869
         * @see jp.co.future.uroborosql.parser.TransformContext#addBindVariables(java.lang.Object[])
870
         */
871
        @Override
872
        public TransformContext addBindVariables(final Object[] bindVariables) {
873
                for (Object bindVariable : bindVariables) {
1✔
874
                        this.bindVariables.add(bindVariable);
1✔
875
                }
876
                return this;
1✔
877
        }
878

879
        /**
880
         * {@inheritDoc}
881
         *
882
         * @see jp.co.future.uroborosql.parser.TransformContext#getBindVariables()
883
         */
884
        @Override
885
        public Object[] getBindVariables() {
886
                return bindVariables.toArray();
1✔
887
        }
888

889
        /**
890
         * バインドパラメータ配列取得
891
         *
892
         * @return バインドパラメータ配列
893
         */
894
        public Parameter[] getBindParameters() {
895
                return bindNames.stream().map(this::getParam).filter(Objects::nonNull).toArray(Parameter[]::new);
1✔
896
        }
897

898
        /**
899
         * {@inheritDoc}
900
         *
901
         * @see jp.co.future.uroborosql.context.SqlContext#bindParams(java.sql.PreparedStatement)
902
         */
903
        @Override
904
        public void bindParams(final PreparedStatement preparedStatement) throws SQLException {
905
                Parameter[] bindParameters = getBindParameters();
1✔
906

907
                Set<String> matchParams = new HashSet<>(calcInitialCapacity(bindParameters.length));
1✔
908
                int parameterIndex = 1;
1✔
909
                for (Parameter bindParameter : bindParameters) {
1✔
910
                        Parameter parameter = getSqlFilterManager().doParameter(bindParameter);
1✔
911
                        parameterIndex = parameter.setParameter(preparedStatement, parameterIndex, parameterMapperManager);
1✔
912
                        matchParams.add(parameter.getParameterName());
1✔
913
                }
914
                // SQL上のバインドパラメータ群(bindNames)に対応する値がすべて設定されているかどうかをチェックする
915
                if (!matchParams.containsAll(bindNames)) {
1✔
916
                        Set<String> missMatchParams = new LinkedHashSet<>(bindNames);
1✔
917
                        missMatchParams.removeAll(matchParams);
1✔
918
                        throw new ParameterNotFoundRuntimeException("Parameter " + missMatchParams.toString() + " is not found.");
1✔
919
                }
920
        }
1✔
921

922
        /**
923
         * {@inheritDoc}
924
         *
925
         * @see jp.co.future.uroborosql.context.SqlContext#bindBatchParams(java.sql.PreparedStatement)
926
         */
927
        @Override
928
        public void bindBatchParams(final PreparedStatement preparedStatement) throws SQLException {
929
                for (Map<String, Parameter> paramMap : batchParameters) {
1✔
930
                        parameterMap = paramMap;
1✔
931
                        bindParams(preparedStatement);
1✔
932
                        preparedStatement.addBatch();
1✔
933
                }
1✔
934
                LOG.debug("{} items Added for batch process.", batchParameters.size());
1✔
935
        }
1✔
936

937
        /**
938
         * {@inheritDoc}
939
         *
940
         * @see jp.co.future.uroborosql.context.SqlContext#getOutParams(java.sql.CallableStatement)
941
         */
942
        @Override
943
        public Map<String, Object> getOutParams(final CallableStatement callableStatement) throws SQLException {
944
                Map<String, Object> out = new HashMap<>();
1✔
945
                Parameter[] bindParameters = getBindParameters();
1✔
946
                int parameterIndex = 1;
1✔
947
                for (Parameter parameter : bindParameters) {
1✔
948
                        if (parameter instanceof OutParameter) {
1✔
949
                                String key = parameter.getParameterName();
1✔
950
                                out.put(key, getSqlFilterManager().doOutParameter(key, callableStatement.getObject(parameterIndex)));
1✔
951
                        }
952
                        parameterIndex++;
1✔
953
                }
954

955
                LOG.debug("Stored procedure out parameter[{}]", out);
1✔
956
                return out;
1✔
957
        }
958

959
        /**
960
         * {@inheritDoc}
961
         *
962
         * @see jp.co.future.uroborosql.context.SqlContext#addBatch()
963
         */
964
        @Override
965
        public SqlContext addBatch() {
966
                acceptUpdateAutoParameterBinder();
1✔
967
                batchParameters.add(parameterMap);
1✔
968
                // バッチ処理では毎回同じ数のパラメータが追加されることが多いのでMap生成時のinitialCapacityを指定してマップのリサイズ処理を極力発生させないようにする
969
                parameterMap = new HashMap<>(calcInitialCapacity(parameterMap.size()));
1✔
970
                return this;
1✔
971
        }
972

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

983
        /**
984
         * {@inheritDoc}
985
         *
986
         * @see jp.co.future.uroborosql.context.SqlContext#clearBatch()
987
         */
988
        @Override
989
        public SqlContext clearBatch() {
990
                batchParameters.clear();
1✔
991
                return this;
1✔
992
        }
993

994
        /**
995
         * {@inheritDoc}
996
         *
997
         * @see jp.co.future.uroborosql.context.SqlContext#batchCount()
998
         */
999
        @Override
1000
        public int batchCount() {
1001
                return batchParameters.size();
1✔
1002
        }
1003

1004
        /**
1005
         * {@inheritDoc}
1006
         *
1007
         * @see jp.co.future.uroborosql.context.SqlContext#acceptQueryAutoParameterBinder()
1008
         */
1009
        @Override
1010
        public void acceptQueryAutoParameterBinder() {
1011
                if (queryAutoParameterBinder != null) {
1✔
1012
                        queryAutoParameterBinder.accept(this);
1✔
1013
                }
1014
        }
1✔
1015

1016
        /**
1017
         * {@inheritDoc}
1018
         *
1019
         * @see jp.co.future.uroborosql.context.SqlContext#acceptUpdateAutoParameterBinder()
1020
         */
1021
        @Override
1022
        public void acceptUpdateAutoParameterBinder() {
1023
                if (updateAutoParameterBinder != null) {
1✔
1024
                        updateAutoParameterBinder.accept(this);
1✔
1025
                }
1026
        }
1✔
1027

1028
        /**
1029
         * {@inheritDoc}
1030
         *
1031
         * @see jp.co.future.uroborosql.context.SqlContext#addDefineColumnType(int, int)
1032
         */
1033
        @Override
1034
        public void addDefineColumnType(final int column, final int type) {
1035
                defineColumnTypeMap.put(column, type);
1✔
1036
        }
1✔
1037

1038
        /**
1039
         * {@inheritDoc}
1040
         *
1041
         * @see jp.co.future.uroborosql.context.SqlContext#getDefineColumnTypes()
1042
         */
1043
        @Override
1044
        public Map<Integer, Integer> getDefineColumnTypes() {
1045
                return defineColumnTypeMap;
1✔
1046
        }
1047

1048
        /**
1049
         * {@inheritDoc}
1050
         *
1051
         * @see jp.co.future.uroborosql.context.SqlContext#setResultSetType(int)
1052
         */
1053
        @Override
1054
        public void setResultSetType(final int resultSetType) {
1055
                this.resultSetType = resultSetType;
1✔
1056
        }
1✔
1057

1058
        /**
1059
         * {@inheritDoc}
1060
         *
1061
         * @see jp.co.future.uroborosql.context.SqlContext#getResultSetType()
1062
         */
1063
        @Override
1064
        public int getResultSetType() {
1065
                return resultSetType;
1✔
1066
        }
1067

1068
        /**
1069
         * {@inheritDoc}
1070
         *
1071
         * @see jp.co.future.uroborosql.context.SqlContext#setResultSetConcurrency(int)
1072
         */
1073
        @Override
1074
        public void setResultSetConcurrency(final int resultSetConcurrency) {
1075
                this.resultSetConcurrency = resultSetConcurrency;
1✔
1076
        }
1✔
1077

1078
        /**
1079
         * {@inheritDoc}
1080
         *
1081
         * @see jp.co.future.uroborosql.context.SqlContext#getResultSetConcurrency()
1082
         */
1083
        @Override
1084
        public int getResultSetConcurrency() {
1085
                return resultSetConcurrency;
1✔
1086
        }
1087

1088
        /**
1089
         * {@inheritDoc}
1090
         *
1091
         * @see jp.co.future.uroborosql.context.SqlContext#getSqlKind()
1092
         */
1093
        @Override
1094
        public SqlKind getSqlKind() {
1095
                return sqlKind;
1✔
1096
        }
1097

1098
        /**
1099
         * {@inheritDoc}
1100
         *
1101
         * @see jp.co.future.uroborosql.context.SqlContext#setSqlKind(jp.co.future.uroborosql.enums.SqlKind)
1102
         */
1103
        @Override
1104
        public void setSqlKind(final SqlKind sqlKind) {
1105
                this.sqlKind = sqlKind;
1✔
1106
        }
1✔
1107

1108
        /**
1109
         * 定数パラメータマップの取得
1110
         *
1111
         * @return 定数パラメータマップ
1112
         */
1113
        public Map<String, Parameter> getConstParameterMap() {
1114
                return constParameterMap;
1✔
1115
        }
1116

1117
        /**
1118
         * 定数パラメータマップの設定
1119
         *
1120
         * @param constParameterMap 定数パラメータマップ
1121
         */
1122
        public void setConstParameterMap(final Map<String, Parameter> constParameterMap) {
1123
                this.constParameterMap = constParameterMap;
1✔
1124
        }
1✔
1125

1126
        /**
1127
         * SqlFilter管理クラスを取得します。
1128
         *
1129
         * @return SqlFilter管理クラス
1130
         */
1131
        public SqlFilterManager getSqlFilterManager() {
1132
                return sqlFilterManager;
1✔
1133
        }
1134

1135
        /**
1136
         * SqlFilter管理クラスを設定します。
1137
         *
1138
         * @param sqlFilterManager SQLフィルタ管理クラス SqlFilter管理クラス
1139
         */
1140
        public void setSqlFilterManager(final SqlFilterManager sqlFilterManager) {
1141
                this.sqlFilterManager = sqlFilterManager;
1✔
1142
        }
1✔
1143

1144
        /**
1145
         * パラメータ変換マネージャを取得します
1146
         *
1147
         * @return パラメータ変換マネージャ
1148
         */
1149
        public BindParameterMapperManager getParameterMapperManager() {
1150
                return parameterMapperManager;
1✔
1151
        }
1152

1153
        /**
1154
         * パラメータ変換マネージャを設定します
1155
         *
1156
         * @param parameterMapperManager パラメータ変換マネージャ
1157
         */
1158
        public void setParameterMapperManager(final BindParameterMapperManager parameterMapperManager) {
1159
                this.parameterMapperManager = parameterMapperManager;
1✔
1160
        }
1✔
1161

1162
        /**
1163
         * 自動パラメータバインド関数(query用)を設定します
1164
         * @param binder 自動パラメータバインド関数
1165
         */
1166
        public void setQueryAutoParameterBinder(final Consumer<SqlContext> binder) {
1167
                this.queryAutoParameterBinder = binder;
1✔
1168
        }
1✔
1169

1170
        /**
1171
         * 自動パラメータバインド関数(update/batch/proc用)を設定します
1172
         * @param binder 自動パラメータバインド関数
1173
         */
1174
        public void setUpdateAutoParameterBinder(final Consumer<SqlContext> binder) {
1175
                this.updateAutoParameterBinder = binder;
1✔
1176
        }
1✔
1177

1178
        /**
1179
         * {@inheritDoc}
1180
         *
1181
         * @see jp.co.future.uroborosql.context.SqlContext#contextAttrs()
1182
         */
1183
        @Override
1184
        public Map<String, Object> contextAttrs() {
1185
                return contextAttributes;
1✔
1186
        }
1187

1188
        /**
1189
         * {@inheritDoc}
1190
         *
1191
         * @see jp.co.future.uroborosql.context.SqlContext#formatParams()
1192
         */
1193
        @Override
1194
        public String formatParams() {
1195
                StringBuilder sb = new StringBuilder();
1✔
1196
                for (int i = 0; i < bindNames.size(); i++) {
1✔
1197
                        sb.append(String.format("[%s=%s]", bindNames.get(i), bindVariables.get(i)));
1✔
1198
                }
1199
                return sb.toString();
1✔
1200
        }
1201

1202
        /**
1203
         * {@inheritDoc}
1204
         *
1205
         * @see jp.co.future.uroborosql.context.SqlContext#getGeneratedKeyColumns()
1206
         */
1207
        @Override
1208
        public String[] getGeneratedKeyColumns() {
1209
                return this.generatedKeyColumns;
1✔
1210
        }
1211

1212
        /**
1213
         * {@inheritDoc}
1214
         *
1215
         * @see jp.co.future.uroborosql.context.SqlContext#setGeneratedKeyColumns(java.lang.String[])
1216
         */
1217
        @Override
1218
        public void setGeneratedKeyColumns(final String[] generatedKeyColumns) {
1219
                this.generatedKeyColumns = generatedKeyColumns;
1✔
1220
        }
1✔
1221

1222
        /**
1223
         * {@inheritDoc}
1224
         *
1225
         * @see jp.co.future.uroborosql.context.SqlContext#getGeneratedKeyValues()
1226
         */
1227
        @Override
1228
        public Object[] getGeneratedKeyValues() {
1229
                return this.generatedKeyValues;
1✔
1230
        }
1231

1232
        /**
1233
         * {@inheritDoc}
1234
         *
1235
         * @see jp.co.future.uroborosql.context.SqlContext#setGeneratedKeyValues(java.lang.Object[])
1236
         */
1237
        @Override
1238
        public void setGeneratedKeyValues(final Object[] generatedKeyValues) {
1239
                this.generatedKeyValues = generatedKeyValues;
1✔
1240
        }
1✔
1241

1242
        /**
1243
         * {@inheritDoc}
1244
         *
1245
         * @see jp.co.future.uroborosql.context.SqlContext#hasGeneratedKeyColumns()
1246
         */
1247
        @Override
1248
        public boolean hasGeneratedKeyColumns() {
1249
                return getGeneratedKeyColumns() != null && getGeneratedKeyColumns().length > 0;
1✔
1250
        }
1251

1252
        /**
1253
         * {@inheritDoc}
1254
         *
1255
         * @see jp.co.future.uroborosql.context.SqlContext#getUpdateDelegate()
1256
         */
1257
        @Override
1258
        public Function<SqlContext, Integer> getUpdateDelegate() {
1259
                return this.updateDelegate;
1✔
1260
        }
1261

1262
        /**
1263
         * {@inheritDoc}
1264
         *
1265
         * @see jp.co.future.uroborosql.context.SqlContext#setUpdateDelegate(java.util.function.Function)
1266
         */
1267
        @Override
1268
        public SqlContext setUpdateDelegate(Function<SqlContext, Integer> updateDelegate) {
1269
                this.updateDelegate = updateDelegate;
1✔
1270
                return this;
1✔
1271
        }
1272

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