001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.fukurou.db;
017
018import java.sql.CallableStatement;
019import java.sql.Connection;
020import java.sql.PreparedStatement;
021import java.sql.ParameterMetaData;
022import java.sql.ResultSet;
023import java.sql.SQLException;
024import java.sql.Types;
025import java.util.ArrayList;
026import java.util.Locale;
027
028import org.opengion.fukurou.system.OgRuntimeException ;                         // 6.4.2.0 (2016/01/29)
029import org.opengion.fukurou.util.StringUtil;
030import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
031import static org.opengion.fukurou.system.HybsConst.DB_FETCH_SIZE;      // 6.9.4.1 (2018/04/09)
032
033/**
034 * データベース関連の便利なメソッドを集めた簡易ユーティリティークラスです。
035 * 全てのメソッドは、static メソッドになっています。
036 *
037 * @og.rev 2.1.1.1 (2002/11/15) Serializable インターフェースを削除する。
038 * @og.rev 4.0.0.0 (2007/10/16) DBアクセス関係のメソッドのみをパッケージ移動(hayabusa/db ⇒ fukurou/db)
039 * @og.rev 6.0.4.0 (2014/11/28) ResultSetValue クラスで、ResultSet から値を取得する処理を移植
040 *
041 * @og.group DB/Shell制御
042 *
043 * @version  4.0
044 * @author   Kazuhiko Hasegawa
045 * @since    JDK5.0,
046 */
047public final class DBUtil {
048//      /** 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ  {@value} */
049//      private static final int DB_FETCH_SIZE = 1001 ;
050
051        /**
052         * インスタンスを作らないので、コンストラクタは、private に設定します。
053         */
054        private DBUtil() {}
055
056        /**
057         * 初期データベースに接続して、Queryを実行します(互換性確保のため残しています)。
058         *
059         * ステートメントと引数により、Prepared クエリーの検索のみ実行します。
060         * 結果は,すべて文字列に変換されて格納されます。
061         *
062         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
063         * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
064         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
065         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
066         * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。
067         * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
068         *
069         * @param   stmt ステートメント文字列
070         * @param   args オブジェクトの引数配列
071         * @param   appInfo アプリ情報オブジェクト
072         *
073         * @return  検索結果の配列
074         */
075        public static String[][] dbExecute( final String stmt ,final String[] args ,final ApplicationInfo appInfo ) {
076                try( Transaction tran = new TransactionReal( appInfo ) ) {
077                        return dbExecute( stmt, args, tran, null, false );
078                }
079        }
080
081        /**
082         * 初期データベースに接続して、Queryを実行します(Transaction 対応)。
083         *
084         * ステートメントと引数により、Prepared クエリーの検索のみ実行します。
085         * 結果は,すべて文字列に変換されて格納されます。
086         * ここでは、Transactionオブジェクトから、Connection を取り出して使用します。
087         *
088         * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応
089         *
090         * @param   stmt ステートメント文字列
091         * @param   args オブジェクトの引数配列
092         * @param   tran Transactionオブジェクト
093         *
094         * @return  検索結果の配列
095         */
096        public static String[][] dbExecute( final String stmt ,final String[] args ,final Transaction tran ) {
097                return dbExecute( stmt, args, tran, null, false );
098        }
099
100        /**
101         * 検索するデータベースを指定して、Queryを実行します(互換性確保のため残しています)。
102         *
103         * ステートメントと引数により、Prepared クエリーの検索のみ実行します。
104         * 結果は,すべて文字列に変換されて格納されます。
105         * 追加:検索以外のSQLも実行できます。結果は、null を返します。
106         *
107         * @og.rev 3.0.0.0 (2002/12/25) 検索のみのクエリーから、何でもありのクエリーに変更
108         * @og.rev 2.3.1.3 (2003/01/28) Open Cursor が、大量に残る件の対応。ResultSet を close()
109         * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ+Queryに変更します。
110         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
111         * @og.rev 4.0.0.1 (2007/12/03) try ~ catch ~ finally をきちんと行う。
112         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
113         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
114         * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。
115         * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
116         *
117         * @param   stmt ステートメント文字列
118         * @param   args オブジェクトの引数配列
119         * @param   appInfo アプリ情報オブジェクト
120         * @param   dbid 接続先ID
121         *
122         * @return  検索結果の配列
123         */
124        public static String[][] dbExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo, final String dbid ) {
125                try( Transaction tran = new TransactionReal( appInfo ) ) {
126                        return dbExecute( stmt, args, tran, dbid, false  );
127                }
128        }
129
130        /**
131         * 検索するデータベースを指定して、Queryを実行します(Transaction 対応)。
132         *
133         * ステートメントと引数により、Prepared クエリーの検索のみ実行します。
134         * 結果は,すべて文字列に変換されて格納されます。
135         * 追加:検索以外のSQLも実行できます。結果は、null を返します。
136         * ここでは、Transactionオブジェクトから、Connection を取り出して使用します。
137         *
138         * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応
139         *
140         * @param   stmt ステートメント文字列
141         * @param   args オブジェクトの引数配列
142         * @param   tran Transactionオブジェクト
143         * @param   dbid 接続先ID
144         *
145         * @return  検索結果の配列
146         */
147        public static String[][] dbExecute( final String stmt ,final String[] args, final Transaction tran , final String dbid ) {
148                return dbExecute( stmt, args, tran, dbid, false );
149        }
150
151        /**
152         * 検索するデータベースを指定して、Queryを実行します(互換性確保のため残しています)。
153         *
154         * ステートメントと引数により、Prepared クエリーの検索のみ実行します。
155         * 結果は,すべて文字列に変換されて格納されます。
156         * 追加:検索以外のSQLも実行できます。結果は、null を返します。
157         *
158         * @og.rev 4.3.7.0 (2009/06/01) 新規作成
159         * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
160         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
161         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
162         * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。
163         * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
164         *
165         * @param   stmt ステートメント文字列
166         * @param   args オブジェクトの引数配列
167         * @param   appInfo アプリ情報オブジェクト
168         * @param   dbid 接続先ID
169         * @param   useHeader 1行目にヘッダーを含めるか
170         *
171         * @return  検索結果の配列
172         */
173        public static String[][] dbExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo, final String dbid, final boolean useHeader ) {
174                try( Transaction tran = new TransactionReal( appInfo ) ) {
175                        return dbExecute( stmt, args, tran, dbid, useHeader );
176                }
177        }
178
179        /**
180         * 検索するデータベースを指定して、Queryを実行します(Transaction 対応)。
181         *
182         * ステートメントと引数により、Prepared クエリーの検索のみ実行します。
183         * 結果は,すべて文字列に変換されて格納されます。
184         * 追加:検索以外のSQLも実行できます。結果は、null を返します。
185         *
186         * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応
187         * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った場合は、close() しない。
188         * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)、setNull 対応
189         * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。
190         * @og.rev 6.4.3.2 (2016/02/19) args が null でなく、length==0 でない場合のみ、処理する。
191         * @og.rev 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズを設定。
192         *
193         * @param   stmt ステートメント文字列
194         * @param   args オブジェクトの引数配列
195         * @param   tran Transactionオブジェクト
196         * @param   dbid 接続先ID
197         * @param   useHeader 1行目にヘッダーを含めるか
198         *
199         * @return  検索結果の配列
200         */
201        public static String[][] dbExecute( final String stmt ,final String[] args, final Transaction tran, final String dbid, final boolean useHeader ) {
202                String[][] rtn = null;
203                try {
204                        final Connection conn = tran.getConnection( dbid );                             // 5.1.9.0 (2010/08/01) Transaction 対応
205                        try( PreparedStatement pstmt = conn.prepareStatement( stmt ) ) {
206                                pstmt.setFetchSize( DB_FETCH_SIZE );                            // 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ
207
208                                // 6.4.3.2 (2016/02/19) args が null でなく、length==0 でない場合のみ、処理する。
209                                if( args != null && args.length > 0 ) {
210                                        // 5.1.1.0 (2009/11/11) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
211                                        final boolean useParamMetaData = ConnectionFactory.useParameterMetaData( dbid );        // 5.3.8.0 (2011/08/01)
212                                        if( useParamMetaData ) {
213                                                final ParameterMetaData pMeta = pstmt.getParameterMetaData();
214                                                for( int i=0; i<args.length; i++ ) {
215                                                        final int type = pMeta.getParameterType( i+1 );
216                                                        // 5.3.8.0 (2011/08/01) setNull 対応
217                                                        final String val = args[i];
218                                                        if( val == null || val.isEmpty() ) {
219                                                                pstmt.setNull( i+1, type );
220                                                        }
221                                                        else {
222                                                                pstmt.setObject( i+1, val, type );
223                                                        }
224                                                }
225                                        }
226                                        else {
227                                                for( int i=0; i<args.length; i++ ) {
228                                                        pstmt.setObject( i+1,args[i] );
229                                                }
230                                        }
231                                }
232                                if( pstmt.execute() ) {                                                                 // 6.1.0.0 (2014/12/26) refactoring
233                                        try( ResultSet resultSet = pstmt.getResultSet() ) {
234                                                rtn = DBUtil.resultToArray( resultSet,useHeader );      // 4.3.7.0 (2009/06/01)
235                                        }
236                                }
237                                // 6.3.6.1 (2015/08/28) 検索・登録関係なく、commit() する。
238                                tran.commit();                  // 5.1.9.0 (2010/08/01) Transaction 対応
239                        }
240                }
241                catch( final SQLException ex ) {
242                        tran.rollback();                        // 5.1.9.0 (2010/08/01) Transaction 対応
243                        final String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR
244                                                        + "SQL=[" + stmt + "]" + CR
245                                                        + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR
246                                                        + "DBID=[" + dbid + "]" + CR;
247                        throw new OgRuntimeException( errMsg,ex );
248                }
249                return rtn;
250        }
251
252        /**
253         * 初期データベースに接続して、CallableStatement(PL/SQL)を実行します(互換性確保のため残しています)。
254         * ステートメントと引数により、CallableStatement クエリーを実行します。
255         * 結果は,ステータスとエラーメッセージを返します。便宜的に、String配列に
256         * 設定して返します。
257         * ステートメント文字列には、 { call PLSQL( ?,?,?・・・ ) } となります。
258         * 第一引数、第二引数は、OUT属性で、結果(STATUS)とエラー時の内容(ERR_CODE)を返します。
259         * 第三引数以降の ? には、オブジェクトの引数配列 が順に割り当てられます。
260         *
261         * @og.rev 3.8.0.0 (2005/06/07) 新規追加
262         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
263         * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
264         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
265         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
266         * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。
267         * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
268         *
269         * @param   stmt ステートメント文字列
270         * @param   args オブジェクトの引数配列
271         * @param   appInfo アプリ情報オブジェクト
272         *
273         * @return  実行結果([0]=ステータス、[1]=エラーメッセージ
274         */
275        public static String[] dbCallExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo ) {
276                try( Transaction tran = new TransactionReal( appInfo ) ) {
277                        return dbCallExecute( stmt ,args, tran, null );
278                }
279        }
280
281        /**
282         * 初期データベースに接続して、CallableStatement(PL/SQL)を実行します(Transaction 対応)。
283         * ステートメントと引数により、CallableStatement クエリーを実行します。
284         * 結果は,ステータスとエラーメッセージを返します。便宜的に、String配列に
285         * 設定して返します。
286         * ステートメント文字列には、 { call PLSQL( ?,?,?・・・ ) } となります。
287         * 第一引数、第二引数は、OUT属性で、結果(STATUS)とエラー時の内容(ERR_CODE)を返します。
288         * 第三引数以降の ? には、オブジェクトの引数配列 が順に割り当てられます。
289         *
290         * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応
291         *
292         * @param   stmt ステートメント文字列
293         * @param   args オブジェクトの引数配列
294         * @param   tran Transactionオブジェクト
295         *
296         * @return  実行結果([0]=ステータス、[1]=エラーメッセージ
297         */
298        public static String[] dbCallExecute( final String stmt ,final String[] args, final Transaction tran ) {
299                return dbCallExecute( stmt ,args, tran, null );
300        }
301
302        /**
303         * 検索するデータベースを指定して、CallableStatement(PL/SQL)を実行します(互換性確保のため残しています)。
304         * ステートメントと引数により、CallableStatement クエリーを実行します。
305         * 結果は,ステータスとエラーメッセージを返します。便宜的に、String配列に
306         * 設定して返します。
307         * ステートメント文字列には、 { call PLSQL( ?,?,?・・・ ) } となります。
308         * 第一引数、第二引数は、OUT属性で、結果(STATUS)とエラー時の内容(ERR_CODE)を返します。
309         * 第三引数以降の ? には、オブジェクトの引数配列 が順に割り当てられます。
310         * 検索するデータベースは、DEFAULT です。
311         *
312         * @og.rev 3.8.0.0 (2005/06/07) 新規追加
313         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
314         * @og.rev 4.0.0.1 (2007/12/03) try ~ catch ~ finally をきちんと行う。
315         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
316         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
317         * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。
318         * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
319         *
320         * @param   stmt ステートメント文字列
321         * @param   args オブジェクトの引数配列
322         * @param   appInfo アプリ情報オブジェクト
323         * @param   dbid 接続先ID
324         *
325         * @return  実行結果([0]=ステータス、[1]=エラーメッセージ
326         */
327        public static String[] dbCallExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo ,final String dbid ) {
328                try( Transaction tran = new TransactionReal( appInfo ) ) {
329                        return dbCallExecute( stmt ,args, tran, dbid );
330                }
331        }
332
333        /**
334         * 検索するデータベースを指定して、CallableStatement(PL/SQL)を実行します(Transaction 対応)。
335         * ステートメントと引数により、CallableStatement クエリーを実行します。
336         * 結果は,ステータスとエラーメッセージを返します。便宜的に、String配列に
337         * 設定して返します。
338         * ステートメント文字列には、 { call PLSQL( ?,?,?・・・ ) } となります。
339         * 第一引数、第二引数は、OUT属性で、結果(STATUS)とエラー時の内容(ERR_CODE)を返します。
340         * 第三引数以降の ? には、オブジェクトの引数配列 が順に割り当てられます。
341         * 検索するデータベースは、DEFAULT です。
342         *
343         * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応
344         * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った場合は、close() しない。
345         * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。
346         * @og.rev 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズを設定。
347         *
348         * @param   stmt ステートメント文字列
349         * @param   args オブジェクトの引数配列
350         * @param   tran Transactionオブジェクト
351         * @param   dbid 接続先ID
352         *
353         * @return  実行結果([0]=ステータス、[1]=エラーメッセージ
354         */
355        public static String[] dbCallExecute( final String stmt ,final String[] args, final Transaction tran ,final String dbid ) {
356
357                String[] rtn = new String[2] ;
358
359                try {
360                        final Connection conn = tran.getConnection( dbid );                             // 5.1.9.0 (2010/08/01) Transaction 対応
361                        try( CallableStatement callStmt = conn.prepareCall( stmt ) ) {
362                                callStmt.setFetchSize( DB_FETCH_SIZE );                                         // 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ
363
364                                callStmt.registerOutParameter( 1, Types.INTEGER );
365                                callStmt.registerOutParameter( 2, Types.VARCHAR );
366                                if( args != null ) {
367                                        for( int i=0; i<args.length; i++ ) {
368                                                callStmt.setObject( i+3,args[i] );
369                                        }
370                                }
371                                callStmt.execute();
372
373                                rtn[0] = String.valueOf( callStmt.getInt(1) );  // 結果ステータス
374                                rtn[1] = callStmt.getString(2);                                 // 内容(エラーメッセージ)
375
376                                tran.commit();                                  // 5.1.9.0 (2010/08/01) Transaction 対応
377                        }
378                }
379                catch( final SQLException ex ) {
380                        tran.rollback();                                // 5.1.9.0 (2010/08/01) Transaction 対応
381                        final String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR
382                                                        + "SQL=[" + stmt + "]" + CR
383                                                        + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR
384                                                        + "DBID=[" + dbid + "]" + CR;
385                        throw new OgRuntimeException( errMsg,ex );
386                }
387                return rtn;
388        }
389
390        /**
391         * SQL文の実行結果において、データの件数を取得します(互換性確保のため残しています)。
392         * ステートメントと引数により、Prepared クエリーの検索を実行します。
393         * 結果は、件数を数値で返します。
394         * あくまで、存在チェックに必要な処理のみ行っているため、通常の検索より高速です。
395         *
396         * @og.rev 3.5.0.0 (2003/09/17) 新規作成
397         * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ+Queryに変更します。
398         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
399         * @og.rev 4.0.0.1 (2007/12/03) try ~ catch ~ finally をきちんと行う。
400         * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
401         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
402         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
403         * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処理をセットで実行する。
404         * @og.rev 6.3.6.1 (2015/08/28) Transaction でAutoCloseableを使用したtry-with-resources構築に対応。
405         *
406         * @param   stmt ステートメント文字列
407         * @param   args オブジェクトの引数配列
408         * @param   appInfo アプリ情報オブジェクト
409         * @param   dbid 接続先ID
410         *
411         * @return  検索結果(データの件数)
412         */
413        public static int dbExist( final String stmt ,final String[] args, final ApplicationInfo appInfo , final String dbid ) {
414                try( Transaction tran = new TransactionReal( appInfo ) ) {
415                        return dbExist( stmt ,args, tran , dbid );
416                }
417        }
418
419        /**
420         * SQL文の実行結果において、データの件数を取得します(Transaction 対応)。
421         * ステートメントと引数により、Prepared クエリーの検索を実行します。
422         * 結果は、件数を数値で返します。
423         * あくまで、存在チェックに必要な処理のみ行っているため、通常の検索より高速です。
424         *
425         * @og.rev 5.1.9.0 (2010/08/01) 新規作成 Transaction 対応
426         * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った場合は、close() しない。
427         * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData を ConnectionFactory経由で取得。(PostgreSQL対応)、setNull 対応
428         * @og.rev 6.4.2.1 (2016/02/05) try-with-resources 文で記述。
429         * @og.rev 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズを設定。   7.2.9.1 (2020/10/23) サイズ指定しない。
430         *
431         * @param   stmt ステートメント文字列
432         * @param   args オブジェクトの引数配列
433         * @param   tran Transactionオブジェクト
434         * @param   dbid 接続先ID
435         *
436         * @return  検索結果(データの件数)
437         */
438        public static int dbExist( final String stmt ,final String[] args, final Transaction tran , final String dbid ) {
439                int rtnCnt = -1;
440
441                try {
442                        final Connection conn = tran.getConnection( dbid );                             // 5.1.9.0 (2010/08/01) Transaction 対応
443                        try( PreparedStatement pstmt = conn.prepareStatement( stmt ) ) {
444//                              pstmt.setFetchSize( DB_FETCH_SIZE );                                            // 6.9.3.0 (2018/03/26) データ検索時のフェッチサイズ
445                                if( args != null ) {
446                                        // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す。(PostgreSQL対応)
447                                        final boolean useParamMetaData = ConnectionFactory.useParameterMetaData( dbid );        // 5.3.8.0 (2011/08/01)
448                                        if( useParamMetaData ) {
449                                                final ParameterMetaData pMeta = pstmt.getParameterMetaData();
450                                                for( int i=0; i<args.length; i++ ) {
451                                                        final int type = pMeta.getParameterType( i+1 );
452                                                        // 5.3.8.0 (2011/08/01) setNull 対応
453                                                        final String val = args[i];
454                                                        if( val == null || val.isEmpty() ) {
455                                                                pstmt.setNull( i+1, type );
456                                                        }
457                                                        else {
458                                                                pstmt.setObject( i+1, val, type );
459                                                        }
460                                                }
461                                        }
462                                        else {
463                                                for( int i=0; i<args.length; i++ ) {
464                                                        pstmt.setObject( i+1,args[i] );
465                                                }
466                                        }
467                                }
468                                try( ResultSet resultSet = pstmt.executeQuery() ) {
469                                        if( resultSet.next() ) {
470                                                rtnCnt = resultSet.getInt(1);
471                                        }
472                                }
473                        }
474                        tran.commit();                          // 6.3.6.1 (2015/08/28) 検索・登録関係なく、commit() する。
475                }
476                catch( final SQLException ex ) {
477                        tran.rollback();                        // 6.3.6.1 (2015/08/28) 検索・登録関係なく処理する。
478                        final String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR
479                                                        + "SQL=[" + stmt + "]" + CR
480                                                        + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR
481                                                        + "DBID=[" + dbid + "]" + CR;
482                        throw new OgRuntimeException( errMsg,ex );              // 3.5.5.4 (2004/04/15) 引数の並び順変更
483                }
484                return rtnCnt;
485        }
486
487        /**
488         * ResultSet より、結果の文字列配列を作成します。
489         *
490         * 結果は,すべて文字列に変換されて格納されます。
491         * 移動したメソッドで使われているのでこれも移動
492         *
493         * @og.rev 3.1.0.0 (2003/03/20) Vector を使用している箇所で、非同期でも構わない箇所を、ArrayList に置換え。
494         * @og.rev 3.8.0.8 (2005/10/03) エラーメッセージの出力順をメッセージ+Queryに変更します。
495         * @og.rev 4.0.0.0 (2005/01/31) private ⇒ public , ヘッダー情報の取得有無フラグの追加
496         * @og.rev 5.6.7.0 (2013/07/27) CLOB 対応
497         * @og.rev 6.0.4.0 (2014/11/28) ResultSetValue クラスで、ResultSet から値を取得する処理を行う。
498         *
499         * @param   resultSet ResultSetオブジェクト
500         * @param   useHeader true:ヘッダーを第一行に含める/false:含めない
501         *
502         * @return  ResultSetの検索結果配列
503         * @throws      java.sql.SQLException データベース・アクセス・エラーが発生した場合
504         */
505        public static String[][] resultToArray( final ResultSet resultSet,final boolean useHeader ) throws SQLException {
506                final ArrayList<String[]> data = new ArrayList<>();
507
508                final ResultSetValue rsv = new ResultSetValue( resultSet );
509
510                if( useHeader ) { data.add( rsv.getNames() ); }
511
512                while( rsv.next() ) {
513                        data.add( rsv.getValues() );
514                }
515
516                final int size = data.size();
517                String[][] rtn = new String[size][];
518                for( int i=0; i<size; i++ ) {
519                        rtn[i] = data.get(i);
520                }
521
522                return rtn;
523        }
524
525        /**
526         * コネクションオブジェクトからデータベースのProductNameを取り出します。
527         * ProductName は、小文字化して返します。
528         * また、処理エラーが発生した場合は、"none" を返します。
529         * ここでは、SQLException は、発生させません。
530         *
531         * @og.rev 5.6.7.0 (2013/07/27) 新規追加
532         * @og.rev 5.6.7.4 (2013/08/30) ProductNameの小文字化対応
533         * @og.rev 6.7.4.2 (2017/02/24) ProductNameの大文字化対応
534         *
535         * @param conn コネクションオブジェクト
536         *
537         * @return データベースのProductName
538         */
539        public static String getProductName( final Connection conn ) {
540                String dbName ;
541                try {
542                        dbName = conn.getMetaData().getDatabaseProductName().toUpperCase( Locale.JAPAN );       // 6.7.4.2 (2017/02/24)
543                }
544                catch( final SQLException ex ) {
545                        dbName = "none";
546                }
547                return dbName ;
548        }
549}