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.plugin.query;
017    
018    import org.opengion.hayabusa.db.AbstractQuery;
019    import org.opengion.hayabusa.db.DBTableModel;
020    import org.opengion.hayabusa.common.HybsSystem;
021    import org.opengion.hayabusa.common.HybsSystemException;
022    import org.opengion.fukurou.util.ErrorMessage;
023    import org.opengion.fukurou.util.StringUtil;
024    import org.opengion.fukurou.util.Closer;
025    import org.opengion.fukurou.util.HybsDateUtil;                  // 5.5.8.5 (2012/11/27)
026    import org.opengion.fukurou.model.Formatter;
027    
028    import java.sql.Connection;
029    import java.sql.PreparedStatement;
030    import java.sql.ParameterMetaData;
031    import java.sql.SQLException;
032    
033    /**
034     * 引数引き当て(PreparedStatement) を利用した登録系Queryです?
035     *
036     * java.sql.PreparedStatement を用?、データベ?ス検索処?行います?
037     * 引数の?方法?、DBTableModele のカラ?に対応する名称を?SQL??[カラ?]形式で
038     * 記述します?これを解析して、実際に実行す?PreparedStatement に対応する文字??
039     * 作?します?
040     * たとえ?、INSERT INTO GEXX (CLM,NAME_JA,LABEL_NAME) VALUES ([CLM],[NAME_JA],[LABEL_NAME] )
041     * と記述すれば、?部で、DBTableModele のカラ?に対応する?を取り?し?SQL?して?
042     * INSERT INTO GEXX (CLM,NAME_JA,LABEL_NAME) VALUES (?,?,? ) を実行します?
043     *
044     * @og.formSample
045     * ●使用?
046     *
047     *    ・QUERYを直接書く??
048     *    【entry.jsp?
049     *        <og:tableUpdate
050     *            command   = "{@command}"
051     *            queryType = "JDBCTableUpdate"
052     *        >
053     *            INSERT INTO GE41
054     *                (CLM,NAME_JA,LABEL_NAME,KBSAKU,SYSTEM_ID,LANG,
055     *                 FGJ,DYSET,DYUPD,USRSET,USRUPD,PGUPD)
056     *            VALUES
057     *                ([CLM],[NAME_JA],[LABEL_NAME],[KBSAKU],[SYSTEM_ID],[LANG],
058     *                 '1','{@USER.YMDH}','{@USER.YMDH}','{@USER.ID}','{@USER.ID}','{@GUI.KEY}')
059     *        </og:tableUpdate>
060     *
061     * @og.rev 4.0.0.0 (2005/01/31) 新規作?
062     * @og.group ??タ編?
063     *
064     * @version  4.0
065     * @author   Kazuhiko Hasegawa
066     * @since    JDK5.0,
067     */
068    public class Query_JDBCTableUpdate extends AbstractQuery {
069            //* こ?プログラ??VERSION??を設定します?       {@value} */
070            private static final String VERSION = "4.0.0.0 (2005/08/31)" ;
071    
072            /**
073             * 引数配?付?クエリーを実行します?
074             * 処??体?, #execute() と同様に、各サブクラスの実?依存します?
075             * これは、PreparedQuery で使用する引数を?列でセ?するも?です?
076             * select * from emp where deptno = ? and job = ? などの PreparedQuery の
077             * [カラ?] 部??引数を?DBTableModelから?にセ?して?ます?
078             *
079             * @og.rev 3.8.0.8 (2005/10/03) エラーメ?ージの出力?をメ?ージ?Queryに変更します?
080             * @og.rev 4.0.0.0 (2007/05/09) ParameterMetaData を使用したパラメータ設定追??
081             * @og.rev 4.0.0.0 (2007/09/25) isOracle から useParamMetaData に変更
082             * @og.rev 5.3.8.0 (2011/08/01) useParamMetaData ?ConnectionFactory経由で取得?(PostgreSQL対?、setNull 対?
083             * @og.rev 5.5.5.4 (2012/08/18) useParamMetaData 処?、ループ?外に出す?(PostgreSQL対?
084             * @og.rev 5.5.5.4 (2012/08/18) DATE オブジェクトを登録できるようにする?
085             * @og.rev 5.5.8.5 (2012/11/27) TIMESTAMP型でも??きるようにします?
086             *
087             * @param   rowNo 選択された行番号配?(登録する対象?
088             * @param   table DBTableModelオブジェク?登録する?ータ)
089             */
090            @Override
091            public void execute( final int[] rowNo, final DBTableModel table ) {
092                    PreparedStatement pstmt = null ;
093    //              ParameterMetaData pMeta = null ;                // 5.5.5.4 (2012/08/18) useParamMetaData 処?、ループ?外に出す?(
094    
095                    int row = 0;                    // エラー時に表示するエラー行番号
096                    try {
097                            int executeCount = 0;   // 処?数
098                            Formatter form = new Formatter( table );
099                            form.setFormat( getStatement() );
100                            int[] clmNos = form.getClmNos();                // 引数の個数??配?。カラ?号を保?
101                            String query = form.getQueryFormatString();
102                            int   cnt    = clmNos.length;                   // 引数の個数(カラ??個数ではありません?
103    
104                            // 5.5.5.4 (2012/08/18) Timestamp オブジェクトを登録できるようにする?
105                            boolean useTimeStamp = false;
106                            boolean[] isTime = new boolean[cnt];
107                            for( int j=0; j<cnt; j++ ) {
108                                    // 5.5.8.5 (2012/11/27) TIMESTAMP型でも??きるようにします?
109    //                              isTime[j] = "DATE".equalsIgnoreCase( table.getDBColumn( clmNos[j] ).getClassName() );
110                                    String clsName = table.getDBColumn( clmNos[j] ).getClassName();
111                                    isTime[j] = "DATE".equalsIgnoreCase( clsName ) || "TIMESTAMP".equalsIgnoreCase( clsName );
112                                    if( !useTimeStamp && isTime[j] ) { useTimeStamp = true; }       // isTime[j] == true 時に、??実行される?
113                            }
114    
115                            Connection conn = getConnection();
116                            pstmt = conn.prepareStatement( query );
117                            pstmt.setQueryTimeout( DB_MAX_QUERY_TIMEOUT );
118                    //      ((oracle.jdbc.OraclePreparedStatement)pstmt).setExecuteBatch(50);
119                            // 4.0.0.0 (2007/09/25) isOracle から useParamMetaData に変更
120    //                      boolean useParamMetaData = ApplicationInfo.useParameterMetaData( conn );
121                            boolean useParamMetaData = useParameterMetaData();      // 5.3.8.0 (2011/08/01)
122    
123                            // 5.5.5.4 (2012/08/18) 以下?useParamMetaData、useTimeStamp??常の?種類を、行?ループ?外に出す?
124                            // 5.5.5.4 (2012/08/18) useParamMetaData 処?、ループ?外に出す?(PostgreSQL対?
125                            if( useParamMetaData ) {
126                                    int[] types = new int[cnt];
127                                    ParameterMetaData pMeta = pstmt.getParameterMetaData();
128                                    for( int j=0; j<cnt; j++ ) {
129                                            types[j] = pMeta.getParameterType( j+1 );       // ?こし?配?の個数と添え字?関係から?j と j+1 での処?なる?
130                                    }
131    
132                                    for( int i=0; i<rowNo.length; i++ ) {
133                                            row = rowNo[i];
134                                            for( int j=0; j<cnt; j++ ) {
135                                                    String val = StringUtil.rTrim( table.getValue( row,clmNos[j] ) );
136                                                    if( val == null || val.isEmpty() ) {
137                                                            pstmt.setNull( j+1, types[j] );
138                                                    }
139                                                    else {
140                                                            pstmt.setObject( j+1, val, types[j] );
141                                                    }
142                                            }
143                                            executeCount += pstmt.executeUpdate();
144                                    }
145                            }
146                            // 5.5.5.4 (2012/08/18) PostgreSQL対?以外?DBの場?
147                            else {
148                                    // 5.5.5.4 (2012/08/18) Timestamp オブジェクトを登録する場?
149                                    if( useTimeStamp ) {
150                                            for( int i=0; i<rowNo.length; i++ ) {
151                                                    row = rowNo[i];
152                                                    for( int j=0; j<cnt; j++ ) {
153                                                            String val = StringUtil.rTrim( table.getValue( row,clmNos[j] ) );
154                                                            if( isTime[j] && val != null && !val.isEmpty() ) {
155                                                                    // 5.5.8.5 (2012/11/27) val は、yyyy-mm-dd hh:mm:ss[.f...] 形式でなければならな??
156    //                                                              java.sql.Timestamp time = java.sql.Timestamp.valueOf( val );
157                                                                    java.sql.Timestamp time = java.sql.Timestamp.valueOf( HybsDateUtil.parseTimestamp( val ) );
158                                                                    pstmt.setObject( j+1,time );
159                                                            }
160                                                            else {
161                                                                    pstmt.setObject( j+1,val );
162                                                            }
163                                                    }
164                                                    executeCount += pstmt.executeUpdate();
165                                            }
166                                    }
167                                    // 5.5.5.4 (2012/08/18) そ?他:つまり?これが?常の処?
168                                    else {
169                                            for( int i=0; i<rowNo.length; i++ ) {
170                                                    row = rowNo[i];
171                                                    for( int j=0; j<cnt; j++ ) {
172                                                            String val = StringUtil.rTrim( table.getValue( row,clmNos[j] ) );
173                                                            pstmt.setObject( j+1,val );
174                                                    }
175                                                    executeCount += pstmt.executeUpdate();
176                                            }
177                                    }
178                            }
179    //                      if( useParamMetaData ) { pMeta = pstmt.getParameterMetaData(); }
180    //                      for( int i=0; i<rowNo.length; i++ ) {
181    //                              row = rowNo[i];
182    //                              for( int j=0; j<cnt; j++ ) {
183    ////                                    String val = table.getValue( row,clmNos[j] ) ;  // 5.3.8.0 (2011/08/01) 簡?
184    //                                      String val = StringUtil.rTrim( table.getValue( row,clmNos[j] ) );
185    //                                      // 4.0.0.0 (2007/09/25) ParameterMetaData を使用したパラメータ設定追?
186    //                                      if( useParamMetaData ) {
187    //                                              int type = pMeta.getParameterType( j+1 );
188    //                                              // 5.3.8.0 (2011/08/01) setNull 対?
189    ////                                            pstmt.setObject( j+1,StringUtil.rTrim( val ),type );
190    //                                              if( val == null || val.isEmpty() ) {
191    //                                                      pstmt.setNull( j+1, type );
192    //                                              }
193    //                                              else {
194    //                                                      pstmt.setObject( j+1, val, type );
195    //                                              }
196    //                                      }
197    //                                      else {
198    ////                                            pstmt.setObject( j+1,StringUtil.rTrim( val ) );
199    //                                              pstmt.setObject( j+1,val );
200    //                                      }
201    //                              }
202    //                              executeCount += pstmt.executeUpdate();
203    //                      }
204                            setExecuteCount( executeCount );
205                            setErrorCode( ErrorMessage.OK );
206                    }
207                    catch (SQLException ex) {
208                            setErrorCode( ErrorMessage.EXCEPTION );
209                            String errMsg = ex.getMessage() + ":" + ex.getSQLState() + HybsSystem.CR
210                                                    + "QUERY=" + getStatement() + HybsSystem.CR
211                                                    + "ROW=[" + (row+1) + "]"
212                                                    + " VALS=[" + StringUtil.array2csv( table.getValues(row) )
213                                                    + HybsSystem.CR ;
214                            rollback();
215                            realClose();
216                            throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び?更
217                    }
218                    finally {
219                            Closer.stmtClose( pstmt );
220                    }
221            }
222    }