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