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     */
016    package org.opengion.fukurou.db;
017    
018    import java.io.IOException;
019    import java.io.Reader;
020    import java.sql.CallableStatement;
021    import java.sql.Clob;
022    import java.sql.Connection;
023    import java.sql.PreparedStatement;
024    import java.sql.ParameterMetaData;
025    import java.sql.ResultSet;
026    import java.sql.ResultSetMetaData;
027    import java.sql.SQLException;
028    import java.sql.Types;
029    import java.util.ArrayList;
030    import java.util.Locale;
031    
032    // import java.text.DateFormat;                         // 5.5.5.4 (2012/08/18) DATE,TIMESTAMP の処?利用時にコメントを外す
033    // import java.text.SimpleDateFormat;           // 5.5.5.4 (2012/08/18) DATE,TIMESTAMP の処?利用時にコメントを外す
034    
035    import org.opengion.fukurou.util.ApplicationInfo;
036    import org.opengion.fukurou.util.Closer;
037    import org.opengion.fukurou.util.StringUtil;
038    import org.opengion.fukurou.util.HybsDateUtil;
039    
040    /**
041     * ??タベ?ス関連の便利なメソ?を集めた簡易ユー?リ?ークラスです?
042     * 全てのメソ?は、static メソ?になって?す?
043     *
044     * @og.rev 2.1.1.1 (2002/11/15) Serializable インターフェースを削除する?
045     * @og.rev 4.0.0.0 (2007/10/16) DBアクセス関係?メソ?のみをパ?ージ移?hayabusa/db ?fukurou/db)
046     * @og.group ??/Shell制御
047     *
048     * @version  4.0
049     * @author   Kazuhiko Hasegawa
050     * @since    JDK5.0,
051     */
052    public final class DBUtil {
053    
054            /** シス?依存?改行記号をセ?します?4.0.0.0(2007/10/17) */
055            private static final String CR = System.getProperty( "line.separator" );
056    
057            /**
058             * インスタンスを作らな??で、コンストラクタは、private に設定します?
059             */
060            private DBUtil() {}
061    
062            /**
063             * 初期??タベ?スに接続して、Queryを実行しま?互換性確保?ため残して???
064             *
065             * ス??トメントと引数により、Prepared クエリーの検索のみ実行します?
066             * 結果は,すべて??に変換されて格納されます?
067             *
068             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
069             * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を?"DEFAULT" から null に変更
070             * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します?
071             * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
072             * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
073             *
074             * @param   stmt ス??トメント文字?
075             * @param   args オブジェクト?引数配?
076             * @param   appInfo アプリ??オブジェク?
077             *
078             * @return  検索結果の配?
079             */
080            public static String[][] dbExecute( final String stmt ,final String[] args ,final ApplicationInfo appInfo ) {
081    //              return dbExecute( stmt ,args,appInfo,"DEFAULT" );
082    //              return dbExecute( stmt, args, appInfo, null );
083    
084    //              Transaction tran = new TransactionReal( null,appInfo );
085                    Transaction tran = new TransactionReal( appInfo );                      // 5.3.7.0 (2011/07/01) 引数変更
086    //              return dbExecute( stmt, args, tran, null, false );
087    
088                    // 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
089                    try {
090                            return dbExecute( stmt, args, tran, null, false );
091                    }
092                    finally {
093                            // エラー発生時は、tran.rollback() が呼ばれて?ため、close()時にエラーフラグをセ?する??な??
094                            tran.close();
095                    }
096            }
097    
098            /**
099             * 初期??タベ?スに接続して、Queryを実行しま?Transaction 対??
100             *
101             * ス??トメントと引数により、Prepared クエリーの検索のみ実行します?
102             * 結果は,すべて??に変換されて格納されます?
103             * ここでは、Transactionオブジェクトから?Connection を取り?して使用します?
104             *
105             * @og.rev 5.1.9.0 (2010/08/01) 新規作? Transaction 対?
106             *
107             * @param   stmt ス??トメント文字?
108             * @param   args オブジェクト?引数配?
109             * @param   tran Transactionオブジェク?
110             *
111             * @return  検索結果の配?
112             */
113            public static String[][] dbExecute( final String stmt ,final String[] args ,final Transaction tran ) {
114                    return dbExecute( stmt, args, tran, null, false );
115            }
116    
117            /**
118             * 検索する??タベ?スを指定して、Queryを実行しま?互換性確保?ため残して???
119             *
120             * ス??トメントと引数により、Prepared クエリーの検索のみ実行します?
121             * 結果は,すべて??に変換されて格納されます?
122             * 追?検索以外?SQLも実行できます?結果は、null を返します?
123             *
124             * @og.rev 3.0.0.0 (2002/12/25) 検索のみのクエリーから、何でもあり?クエリーに変更
125             * @og.rev 2.3.1.3 (2003/01/28) Open Cursor が?大量に残る件の対応?ResultSet ?close()
126             * @og.rev 3.8.0.8 (2005/10/03) エラーメ?ージの出力?をメ?ージ?Queryに変更します?
127             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
128             * @og.rev 4.0.0.1 (2007/12/03) try ??catch ??finally をきちんと行う?
129             * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します?
130             * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
131             * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
132             *
133             * @param   stmt ス??トメント文字?
134             * @param   args オブジェクト?引数配?
135             * @param   appInfo アプリ??オブジェク?
136             * @param   dbid 接続?ID
137             *
138             * @return  検索結果の配?
139             */
140            public static String[][] dbExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo, final String dbid ) {
141    //              return dbExecute( stmt, args, appInfo, dbid, false );
142    
143    //              Transaction tran = new TransactionReal( dbid,appInfo );
144                    Transaction tran = new TransactionReal( appInfo );                      // 5.3.7.0 (2011/07/01) 引数変更
145    //              return dbExecute( stmt, args, tran, dbid, false  );
146    
147                    // 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
148                    try {
149                            return dbExecute( stmt, args, tran, dbid, false  );
150                    }
151                    finally {
152                            // エラー発生時は、tran.rollback() が呼ばれて?ため、close()時にエラーフラグをセ?する??な??
153                            tran.close();
154                    }
155            }
156    
157            /**
158             * 検索する??タベ?スを指定して、Queryを実行しま?Transaction 対??
159             *
160             * ス??トメントと引数により、Prepared クエリーの検索のみ実行します?
161             * 結果は,すべて??に変換されて格納されます?
162             * 追?検索以外?SQLも実行できます?結果は、null を返します?
163             * ここでは、Transactionオブジェクトから?Connection を取り?して使用します?
164             *
165             * @og.rev 5.1.9.0 (2010/08/01) 新規作? Transaction 対?
166             *
167             * @param   stmt ス??トメント文字?
168             * @param   args オブジェクト?引数配?
169             * @param   tran Transactionオブジェク?
170             * @param   dbid 接続?ID
171             *
172             * @return  検索結果の配?
173             */
174            public static String[][] dbExecute( final String stmt ,final String[] args, final Transaction tran , final String dbid ) {
175                    return dbExecute( stmt, args, tran, dbid, false );
176            }
177    
178            /**
179             * 検索する??タベ?スを指定して、Queryを実行しま?互換性確保?ため残して???
180             *
181             * ス??トメントと引数により、Prepared クエリーの検索のみ実行します?
182             * 結果は,すべて??に変換されて格納されます?
183             * 追?検索以外?SQLも実行できます?結果は、null を返します?
184             *
185             * @og.rev 4.3.7.0 (2009/06/01) 新規作?
186             * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す?(PostgreSQL対?
187             * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します?
188             * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
189             * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
190             *
191             * @param   stmt ス??トメント文字?
192             * @param   args オブジェクト?引数配?
193             * @param   appInfo アプリ??オブジェク?
194             * @param   dbid 接続?ID
195             * @param   useHeader 1行目にヘッ??を含める?
196             *
197             * @return  検索結果の配?
198             */
199            public static String[][] dbExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo, final String dbid, final boolean useHeader ) {
200    //              Transaction tran = new TransactionReal( dbid,appInfo );
201                    Transaction tran = new TransactionReal( appInfo );                      // 5.3.7.0 (2011/07/01) 引数変更
202    //              return dbExecute( stmt, args, tran, dbid, useHeader );
203    
204                    // 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
205                    try {
206                            return dbExecute( stmt, args, tran, dbid, useHeader );
207                    }
208                    finally {
209                            // エラー発生時は、tran.rollback() が呼ばれて?ため、close()時にエラーフラグをセ?する??な??
210                            tran.close();
211                    }
212            }
213    
214            /**
215             * 検索する??タベ?スを指定して、Queryを実行しま?Transaction 対??
216             *
217             * ス??トメントと引数により、Prepared クエリーの検索のみ実行します?
218             * 結果は,すべて??に変換されて格納されます?
219             * 追?検索以外?SQLも実行できます?結果は、null を返します?
220             *
221             * @og.rev 5.1.9.0 (2010/08/01) 新規作? Transaction 対?
222             * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った?合?、close() しな??
223             * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData ?ConnectionFactory経由で取得?(PostgreSQL対?、setNull 対?
224             *
225             * @param   stmt ス??トメント文字?
226             * @param   args オブジェクト?引数配?
227             * @param   tran Transactionオブジェク?
228             * @param   dbid 接続?ID
229             * @param   useHeader 1行目にヘッ??を含める?
230             *
231             * @return  検索結果の配?
232             */
233    //      public static String[][] dbExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo, final String dbid, final boolean useHeader ) {
234            public static String[][] dbExecute( final String stmt ,final String[] args, final Transaction tran, final String dbid, final boolean useHeader ) {
235    //              Connection conn = null;                         // 5.1.9.0 (2010/08/01) Transaction 対?
236                    PreparedStatement pstmt = null;
237                    ResultSet resultSet = null;
238                    String[][] rtn = null;
239    //              boolean errFlag = true;
240                    try {
241    //                      conn = ConnectionFactory.connection( dbid,appInfo );
242                            Connection conn = tran.getConnection( dbid );                           // 5.1.9.0 (2010/08/01) Transaction 対?
243                            pstmt = conn.prepareStatement( stmt );
244                            if( args != null ) {
245                                    // 5.1.1.0 (2009/11/11) setObject に ParameterMetaData の getParameterType を渡す?(PostgreSQL対?
246    //                              boolean useParamMetaData = ApplicationInfo.useParameterMetaData( conn );
247                                    boolean useParamMetaData = ConnectionFactory.useParameterMetaData( dbid );      // 5.3.8.0 (2011/08/01)
248                                    if( useParamMetaData ) {
249                                            ParameterMetaData pMeta = pstmt.getParameterMetaData();
250                                            for( int i=0; i<args.length; i++ ) {
251                                                    int type = pMeta.getParameterType( i+1 );
252                                                    // 5.3.8.0 (2011/08/01) setNull 対?
253    //                                              pstmt.setObject( i+1,args[i],type );
254                                                    String val = args[i];
255                                                    if( val == null || val.isEmpty() ) {
256                                                            pstmt.setNull( i+1, type );
257                                                    }
258                                                    else {
259                                                            pstmt.setObject( i+1, val, type );
260                                                    }
261                                            }
262                                    }
263                                    else {
264                                            for( int i=0; i<args.length; i++ ) {
265                                                    pstmt.setObject( i+1,args[i] );
266                                            }
267                                    }
268                            }
269                            boolean status = pstmt.execute();
270                            if( status ) {
271                                    resultSet = pstmt.getResultSet();
272    //                              rtn = DBUtil.resultToArray( resultSet,false );
273                                    rtn = DBUtil.resultToArray( resultSet,useHeader ); // 4.3.7.0 (2009/06/01)
274                            }
275                            else {
276    //                              conn.commit();
277                                    tran.commit();                  // 5.1.9.0 (2010/08/01) Transaction 対?
278                            }
279    //                      errFlag = false;        // エラーでな?
280                    }
281                    catch ( SQLException ex ) {
282    //                      Closer.rollback( conn );
283                            tran.rollback();                        // 5.1.9.0 (2010/08/01) Transaction 対?
284                            String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR
285                                                    + "SQL=[" + stmt + "]" + CR
286                                                    + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR
287                                                    + "DBID=[" + dbid + "]" + CR;
288                            throw new RuntimeException( errMsg,ex );
289                    }
290                    finally {
291                            Closer.resultClose( resultSet );
292                            Closer.stmtClose( pstmt );
293    
294    //                      if( errFlag ) { ConnectionFactory.remove( conn,dbid ); }
295    //                      else {                  ConnectionFactory.close( conn,dbid );  }
296                            // 5.3.8.0 (2011/08/01) Transaction を引数で受け取った?合?、close() しな??
297    //                      tran.close( errFlag );          // 5.1.9.0 (2010/08/01) Transaction 対?
298                    }
299                    return rtn;
300            }
301    
302            /**
303             * 初期??タベ?スに接続して、CallableStatement(PL/SQL)を実行しま?互換性確保?ため残して???
304             * ス??トメントと引数により、CallableStatement クエリーを実行します?
305             * 結果は,ス??タスとエラーメ?ージを返します?便宜的に、String配?に
306             * 設定して返します?
307             * ス??トメント文字?には?{ call PLSQL( ?,?,???? ) } となります?
308             * 第?数、第二引数は、OUT属?で、結果(STATUS)とエラー時??(ERR_CODE)を返します?
309             * 第三引数以降? ? には、オブジェクト?引数配? が?に割り当てられます?
310             *
311             * @og.rev 3.8.0.0 (2005/06/07) 新規追?
312             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
313             * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を?"DEFAULT" から null に変更
314             * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します?
315             * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
316             * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
317             *
318             * @param   stmt ス??トメント文字?
319             * @param   args オブジェクト?引数配?
320             * @param   appInfo アプリ??オブジェク?
321             *
322             * @return  実行結果([0]=ス??タス、[1]=エラーメ?ージ
323             */
324            public static String[] dbCallExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo ) {
325    //              return dbCallExecute( stmt ,args,appInfo,"DEFAULT" );
326    //              return dbCallExecute( stmt ,args, appInfo, null );
327    
328    //              Transaction tran = new TransactionReal( null,appInfo );
329                    Transaction tran = new TransactionReal( appInfo );                      // 5.3.7.0 (2011/07/01) 引数変更
330    //              return dbCallExecute( stmt ,args, tran, null );
331    
332                    // 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
333                    try {
334                            return dbCallExecute( stmt ,args, tran, null );
335                    }
336                    finally {
337                            // エラー発生時は、tran.rollback() が呼ばれて?ため、close()時にエラーフラグをセ?する??な??
338                            tran.close();
339                    }
340            }
341    
342            /**
343             * 初期??タベ?スに接続して、CallableStatement(PL/SQL)を実行しま?Transaction 対??
344             * ス??トメントと引数により、CallableStatement クエリーを実行します?
345             * 結果は,ス??タスとエラーメ?ージを返します?便宜的に、String配?に
346             * 設定して返します?
347             * ス??トメント文字?には?{ call PLSQL( ?,?,???? ) } となります?
348             * 第?数、第二引数は、OUT属?で、結果(STATUS)とエラー時??(ERR_CODE)を返します?
349             * 第三引数以降? ? には、オブジェクト?引数配? が?に割り当てられます?
350             *
351             * @og.rev 5.1.9.0 (2010/08/01) 新規作? Transaction 対?
352             *
353             * @param   stmt ス??トメント文字?
354             * @param   args オブジェクト?引数配?
355             * @param   tran Transactionオブジェク?
356             *
357             * @return  実行結果([0]=ス??タス、[1]=エラーメ?ージ
358             */
359            public static String[] dbCallExecute( final String stmt ,final String[] args, final Transaction tran ) {
360                    return dbCallExecute( stmt ,args, tran, null );
361            }
362    
363            /**
364             * 検索する??タベ?スを指定して、CallableStatement(PL/SQL)を実行しま?互換性確保?ため残して???
365             * ス??トメントと引数により、CallableStatement クエリーを実行します?
366             * 結果は,ス??タスとエラーメ?ージを返します?便宜的に、String配?に
367             * 設定して返します?
368             * ス??トメント文字?には?{ call PLSQL( ?,?,???? ) } となります?
369             * 第?数、第二引数は、OUT属?で、結果(STATUS)とエラー時??(ERR_CODE)を返します?
370             * 第三引数以降? ? には、オブジェクト?引数配? が?に割り当てられます?
371             * 検索する??タベ?スは、DEFAULT です?
372             *
373             * @og.rev 3.8.0.0 (2005/06/07) 新規追?
374             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
375             * @og.rev 4.0.0.1 (2007/12/03) try ??catch ??finally をきちんと行う?
376             * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します?
377             * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
378             * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
379             *
380             * @param   stmt ス??トメント文字?
381             * @param   args オブジェクト?引数配?
382             * @param   appInfo アプリ??オブジェク?
383             * @param   dbid 接続?ID
384             *
385             * @return  実行結果([0]=ス??タス、[1]=エラーメ?ージ
386             */
387            public static String[] dbCallExecute( final String stmt ,final String[] args, final ApplicationInfo appInfo ,final String dbid ) {
388    //              Transaction tran = new TransactionReal( dbid,appInfo );
389                    Transaction tran = new TransactionReal( appInfo );                      // 5.3.7.0 (2011/07/01) 引数変更
390    //              return dbCallExecute( stmt ,args, tran, dbid );
391    
392                    // 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
393                    try {
394                            return dbCallExecute( stmt ,args, tran, dbid );
395                    }
396                    finally {
397                            // エラー発生時は、tran.rollback() が呼ばれて?ため、close()時にエラーフラグをセ?する??な??
398                            tran.close();
399                    }
400            }
401    
402            /**
403             * 検索する??タベ?スを指定して、CallableStatement(PL/SQL)を実行しま?Transaction 対??
404             * ス??トメントと引数により、CallableStatement クエリーを実行します?
405             * 結果は,ス??タスとエラーメ?ージを返します?便宜的に、String配?に
406             * 設定して返します?
407             * ス??トメント文字?には?{ call PLSQL( ?,?,???? ) } となります?
408             * 第?数、第二引数は、OUT属?で、結果(STATUS)とエラー時??(ERR_CODE)を返します?
409             * 第三引数以降? ? には、オブジェクト?引数配? が?に割り当てられます?
410             * 検索する??タベ?スは、DEFAULT です?
411             *
412             * @og.rev 5.1.9.0 (2010/08/01) 新規作? Transaction 対?
413             * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った?合?、close() しな??
414             *
415             * @param   stmt ス??トメント文字?
416             * @param   args オブジェクト?引数配?
417             * @param   tran Transactionオブジェク?
418             * @param   dbid 接続?ID
419             *
420             * @return  実行結果([0]=ス??タス、[1]=エラーメ?ージ
421             */
422            public static String[] dbCallExecute( final String stmt ,final String[] args, final Transaction tran ,final String dbid ) {
423    //              Connection conn = null ;                                // 5.1.9.0 (2010/08/01) Transaction 対?
424                    CallableStatement callStmt = null ;
425    
426                    String[] rtn = new String[2] ;
427    
428    //              boolean errFlag = true;
429                    try {
430    //                      conn = ConnectionFactory.connection( dbid,appInfo );
431                            Connection conn = tran.getConnection( dbid );                           // 5.1.9.0 (2010/08/01) Transaction 対?
432                            callStmt = conn.prepareCall( stmt );
433    
434                            callStmt.registerOutParameter( 1, Types.INTEGER );
435                            callStmt.registerOutParameter( 2, Types.VARCHAR );
436                            if( args != null ) {
437                                    for( int i=0; i<args.length; i++ ) {
438                                            callStmt.setObject( i+3,args[i] );
439                                    }
440                            }
441                            callStmt.execute();
442    
443                            rtn[0] = String.valueOf( callStmt.getInt(1) );  // 結果ス??タス
444                            rtn[1] = callStmt.getString(2);                                 // ?(エラーメ?ージ)
445    
446    //                      conn.commit();
447                            tran.commit();                                  // 5.1.9.0 (2010/08/01) Transaction 対?
448    //                      errFlag = false;        // エラーでな?
449                    }
450                    catch ( SQLException ex ) {
451    //                      Closer.rollback( conn );
452                            tran.rollback();                                // 5.1.9.0 (2010/08/01) Transaction 対?
453                            String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR
454                                                    + "SQL=[" + stmt + "]" + CR
455                                                    + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR
456                                                    + "DBID=[" + dbid + "]" + CR;
457                            throw new RuntimeException( errMsg,ex );
458                    }
459                    finally {
460                            Closer.stmtClose( callStmt );
461    //                      if( errFlag ) { ConnectionFactory.remove( conn,dbid ); }
462    //                      else {                  ConnectionFactory.close( conn,dbid );  }
463                            // 5.3.8.0 (2011/08/01) Transaction を引数で受け取った?合?、close() しな??
464    //                      tran.close( errFlag );          // 5.1.9.0 (2010/08/01) Transaction 対?
465                    }
466                    return rtn;
467            }
468    
469            /**
470             * SQL??実行結果において、データの件数を取得しま?互換性確保?ため残して???
471             * ス??トメントと引数により、Prepared クエリーの検索を実行します?
472             * 結果は、件数を数値で返します?
473             * あくまで、存在チェ?に?な処??み行って?ため??常の検索より高?です?
474             *
475             * @og.rev 3.5.0.0 (2003/09/17) 新規作?
476             * @og.rev 3.8.0.8 (2005/10/03) エラーメ?ージの出力?をメ?ージ?Queryに変更します?
477             * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設?
478             * @og.rev 4.0.0.1 (2007/12/03) try ??catch ??finally をきちんと行う?
479             * @og.rev 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す?(PostgreSQL対?
480             * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します?
481             * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
482             * @og.rev 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
483             *
484             * @param   stmt ス??トメント文字?
485             * @param   args オブジェクト?引数配?
486             * @param   appInfo アプリ??オブジェク?
487             * @param   dbid 接続?ID
488             *
489             * @return  検索結果(??タの件数)
490             */
491            public static int dbExist( final String stmt ,final String[] args, final ApplicationInfo appInfo , final String dbid ) {
492    //              Transaction tran = new TransactionReal( dbid,appInfo );
493                    Transaction tran = new TransactionReal( appInfo );                      // 5.3.7.0 (2011/07/01) 引数変更
494    //              return dbExist( stmt ,args, tran , dbid );
495    
496                    // 5.3.8.0 (2011/08/01) TransactionReal と close() 処?セ?で実行する?
497                    try {
498                            return dbExist( stmt ,args, tran , dbid );
499                    }
500                    finally {
501                            // エラー発生時は、tran.rollback() が呼ばれて?ため、close()時にエラーフラグをセ?する??な??
502                            tran.close();
503                    }
504            }
505    
506            /**
507             * SQL??実行結果において、データの件数を取得しま?Transaction 対??
508             * ス??トメントと引数により、Prepared クエリーの検索を実行します?
509             * 結果は、件数を数値で返します?
510             * あくまで、存在チェ?に?な処??み行って?ため??常の検索より高?です?
511             *
512             * @og.rev 5.1.9.0 (2010/08/01) 新規作? Transaction 対?
513             * @og.rev 5.3.8.0 (2011/08/01) Transaction を引数で受け取った?合?、close() しな??
514             * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData ?ConnectionFactory経由で取得?(PostgreSQL対?、setNull 対?
515             *
516             * @param   stmt ス??トメント文字?
517             * @param   args オブジェクト?引数配?
518             * @param   tran Transactionオブジェク?
519             * @param   dbid 接続?ID
520             *
521             * @return  検索結果(??タの件数)
522             */
523            public static int dbExist( final String stmt ,final String[] args, final Transaction tran , final String dbid ) {
524    //              Connection conn = null;                         // 5.1.9.0 (2010/08/01) Transaction 対?
525                    PreparedStatement pstmt = null;
526                    ResultSet resultSet = null;
527                    int rtnCnt = -1;
528    
529    //              boolean errFlag = true;
530                    try {
531    //                      conn = ConnectionFactory.connection( dbid,appInfo );
532                            Connection conn = tran.getConnection( dbid );                           // 5.1.9.0 (2010/08/01) Transaction 対?
533                            pstmt = conn.prepareStatement( stmt );
534                            if( args != null ) {
535                                    // 5.1.2.0 (2010/01/01) setObject に ParameterMetaData の getParameterType を渡す?(PostgreSQL対?
536    //                              boolean useParamMetaData = ApplicationInfo.useParameterMetaData( conn );
537                                    boolean useParamMetaData = ConnectionFactory.useParameterMetaData( dbid );      // 5.3.8.0 (2011/08/01)
538                                    if( useParamMetaData ) {
539                                            ParameterMetaData pMeta = pstmt.getParameterMetaData();
540                                            for( int i=0; i<args.length; i++ ) {
541                                                    int type = pMeta.getParameterType( i+1 );
542                                                    // 5.3.8.0 (2011/08/01) setNull 対?
543    //                                              pstmt.setObject( i+1,args[i],type );
544                                                    String val = args[i];
545                                                    if( val == null || val.isEmpty() ) {
546                                                            pstmt.setNull( i+1, type );
547                                                    }
548                                                    else {
549                                                            pstmt.setObject( i+1, val, type );
550                                                    }
551                                            }
552                                    }
553                                    else {
554                                            for( int i=0; i<args.length; i++ ) {
555                                                    pstmt.setObject( i+1,args[i] );
556                                            }
557                                    }
558                            }
559    
560                            resultSet = pstmt.executeQuery();
561                            if( resultSet.next() ) {
562                                    rtnCnt = resultSet.getInt(1);
563                            }
564    //                      errFlag = false;        // エラーでな?
565                    }
566                    catch ( SQLException ex ) {
567                            String errMsg = ex.getMessage() + ":" + ex.getSQLState() + CR
568                                                    + "SQL=[" + stmt + "]" + CR
569                                                    + "ARG=[" + StringUtil.array2csv( args ) + "]" + CR
570                                                    + "DBID=[" + dbid + "]" + CR;
571                            throw new RuntimeException( errMsg,ex );                // 3.5.5.4 (2004/04/15) 引数の並び?更
572                    }
573                    finally {
574                            Closer.resultClose( resultSet );
575                            Closer.stmtClose( pstmt );
576    
577    //                      if( errFlag ) { ConnectionFactory.remove( conn,dbid ); }
578    //                      else {                  ConnectionFactory.close( conn,dbid );  }
579                            // 5.3.8.0 (2011/08/01) Transaction を引数で受け取った?合?、close() しな??
580    //                      tran.close( errFlag );          // 5.1.9.0 (2010/08/01) Transaction 対?
581                    }
582                    return rtnCnt;
583            }
584    
585            /**
586             * ResultSet より、結果の??配?を作?します?
587             *
588             * 結果は,すべて??に変換されて格納されます?
589             * 移動したメソ?で使われて?のでこれも移?
590             *
591             * @og.rev 3.1.0.0 (2003/03/20) Vector を使用して??で?同期でも構わな??を?ArrayList に置換え?
592             * @og.rev 3.8.0.8 (2005/10/03) エラーメ?ージの出力?をメ?ージ?Queryに変更します?
593             * @og.rev 4.0.0.0 (2005/01/31) private ?public , ヘッ????の取得有無フラグの追?
594             * @og.rev 5.6.7.0 (2013/07/27) CLOB 対?
595             *
596             * @param   resultSet ResultSetオブジェク?
597             * @param   useHeader true:ヘッ??を第?に含める/false:含めな?
598             *
599             * @return  ResultSetの検索結果配?
600             */
601            public static String[][] resultToArray( final ResultSet resultSet,final boolean useHeader ) {
602                    ArrayList<String[]> data = new ArrayList<String[]>();
603                    try {
604                            ResultSetMetaData metaData  = resultSet.getMetaData();
605                            int numberOfColumns =  metaData.getColumnCount();
606    
607                            String[] columnNames = new String[numberOfColumns];
608                            // 5.6.7.0 (2013/07/27) CLOB 対?
609                            int[] type = new int[numberOfColumns];
610                            boolean useClob = false;                                                                                // そもそも、CLOB系のカラ?あるかど?
611                            for( int i = 0; i < numberOfColumns; i++ ) {
612                                    int tp = metaData.getColumnType( i+1 );
613                                    type[i] = tp ;
614                                    if( tp == Types.CLOB || tp == Types.ROWID || tp == Types.TIMESTAMP ) { useClob = true; }
615                                    if( useHeader ) {
616                                            columnNames[i] = ( metaData.getColumnLabel(i+1) ).toUpperCase(Locale.JAPAN) ;
617                                    }
618                            }
619    
620                            if( useHeader ) { data.add( columnNames ); }
621    
622                            // 5.6.7.0 (2013/07/27) CLOB 対?で、??ーループを回すので、??法を変更
623    //                      if( useHeader ) {
624    //                              String[] columnNames = new String[numberOfColumns];
625    //                              for( int column = 0; column < numberOfColumns; column++ ) {
626    //                                      columnNames[column]      = ( metaData.getColumnLabel(column+1) ).toUpperCase(Locale.JAPAN) ;
627    //                              }
628    //                              data.add( columnNames );
629    //                      }
630    
631                            // 5.6.7.0 (2013/07/27) CLOB 対応?つ?に、ループカウンタを?0からに変更します?
632                            while( resultSet.next() ) {
633                                    String[] columnValues = new String[numberOfColumns];
634                                    for( int i = 0; i < numberOfColumns; i++ ) {
635                                            Object obj = resultSet.getObject(i+1);
636                                            if( obj == null ) {
637                                                    columnValues[i] = "";
638                                            }
639                                            else if( useClob ) {
640                                                    columnValues[i] = getValue( resultSet, i ,type[i] );
641                                            }
642                                            else {
643                                                    columnValues[i] = String.valueOf( obj );
644                                            }
645                                    }
646                                    data.add( columnValues );
647                            }
648    
649    //                      while( resultSet.next() ) {
650    //                              String[] columnValues = new String[numberOfColumns];
651    //                              for( int i = 1; i <= numberOfColumns; i++ ) {
652    //                                      Object obj = resultSet.getObject(i);
653    //                                      if( obj == null ) {
654    //                                              columnValues[i-1] = "";
655    //                                      }
656    //                                      else {
657    //                                              columnValues[i-1] = String.valueOf( obj );
658    //                                      }
659    //                              }
660    //                              data.add( columnValues );
661    //                      }
662                    }
663                    catch ( SQLException ex ) {
664                            String errMsg = "処?果を実行できませんでした?
665                                                    + CR + ex.getMessage() ;
666                            throw new RuntimeException( errMsg,ex );                // 3.5.5.4 (2004/04/15) 引数の並び?更
667                    }
668    
669                    int size = data.size();
670                    String[][] rtn = new String[size][];
671                    for( int i=0; i<size; i++ ) {
672                            rtn[i] = data.get(i);
673                    }
674    
675                    return rtn;
676            }
677    
678            /**
679             * 検索結果オブジェクトから?を取り?します?
680             *
681             * @og.rev 5.3.6.0 (2011/06/01) ?機?対応によりメソ??
682             * @og.rev 5.5.5.4 (2012/08/18) if?case?置き換え?
683             * @og.rev 5.5.5.4 (2012/08/18) TIMESTAMP の処?追??
684             * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します?
685             *
686             * @param res 検索結果オブジェク?
687             * @param col カラ?0から始まる?。このメソ?の?で?1して??
688             * @param type ??タタイ?java.sql.Types.XXXX)
689             *
690             * @return 値
691             * @throws SQLException ??タベ?スアクセスエラー
692             */
693            public static String getValue( final ResultSet res, final int col, final int type ) throws SQLException {
694                    String val = null;
695    
696                    Object obj = res.getObject(col+1);
697                    if( obj == null ) {
698                            val = "";
699                    }
700                    else {
701                            switch( type ) {
702                                    case Types.CLOB :               val = getClobData( (Clob)obj ) ;        break;
703                                    case Types.ROWID:               val = res.getString(col+1);                     break;
704    //                              case Types.TIMESTAMP :  val = DATE_FMT.format( (java.sql.Timestamp)obj );       break;
705                                    case Types.TIMESTAMP :  val = HybsDateUtil.getDate( ((java.sql.Timestamp)obj).getTime() , "yyyyMMddHHmmss" );   break;
706                                    default :                               val = String.valueOf( obj );
707                            }
708                    }
709    
710                    return val;
711    
712    //              5.5.5.4 (2012/08/18) if?case?置き換?
713    //              if( type == Types.CLOB ) {
714    //                      Object obj = res.getObject(col+1);
715    //                      val = getClobData( (Clob)obj ) ;
716    //              }
717    //              else if( type == Types.ROWID ) {
718    //                      String obj = res.getString(col+1);
719    //                      if( obj == null ) {
720    //                              val = "";
721    //                      }
722    //                      else {
723    //                              val = obj;
724    //                      }
725    //              }
726    //              else {
727    //                      Object obj = res.getObject(col+1);
728    //                      if( obj == null ) {
729    //                              val = "";
730    //                      }
731    //                      else {
732    //                              val = String.valueOf( obj );
733    //                      }
734    //              }
735    //
736    //              return val;
737            }
738    
739            // 5.5.5.4 (2012/08/18) DATE,TIMESTAMP の処?追?
740    //              private static final DateFormat DATE_FMT = new SimpleDateFormat( "yyyyMMddHHmmss",Locale.JAPAN );
741    
742            /**
743             * コネクションオブジェクトからデータベ?スのProductNameを取り?します?
744             * ProductName は、小文字化して返します?
745             * また?処?ラーが発生した?合??none" を返します?
746             * ここでは、SQLException は、発生させません?
747             *
748             * @og.rev 5.6.7.0 (2013/07/27) 新規追?
749             * @og.rev 5.6.7.4 (2013/08/30) ProductNameの小文字化対?
750             *
751             * @param conn コネクションオブジェク?
752             *
753             * @return ??タベ?スのProductName
754             */
755            public static String getProductName( final Connection conn ) {
756                    String dbName ;
757                    try {
758    //                      dbName = conn.getMetaData().getDatabaseProductName();
759                            dbName = conn.getMetaData().getDatabaseProductName().toLowerCase( Locale.JAPAN );       // 5.6.7.4 (2013/08/30)
760                    }
761                    catch( SQLException ex ) {
762                            dbName = "none";
763                    }
764                    return dbName ;
765            }
766    
767            /**
768             * Clob オブジェクトから文字?を取り?します?
769             *
770             * @og.rev 5.3.6.0 (2011/06/01) 新規作?
771             *
772             * @param       clobData Clobオブジェク?
773             *
774             * @return      Clobオブジェクトから取り?した??
775             * @throws      SQLException ??タベ?スアクセスエラー
776             */
777            private static String getClobData( final Clob clobData ) throws SQLException {
778                    if( clobData == null ) { return ""; }
779    
780                    Reader reader = null;
781                    StringBuilder buf = new StringBuilder( 10000 );
782    
783                    try {
784                            reader = clobData.getCharacterStream();
785                            char[] ch = new char[10000];
786                            int  len ;
787                            while( (len = reader.read( ch )) >= 0 ) {
788                                    buf.append( ch,0,len );
789                            }
790                    }
791                    catch( IOException ex ) {
792                            String errMsg = "CLOB??タの読み込みに失敗しました?;
793    //                      throw new HybsSystemException( errMsg,ex );
794                            throw new RuntimeException( errMsg,ex );
795                    }
796                    finally {
797                            Closer.ioClose( reader );
798                    }
799                    return buf.toString();
800            }
801    }