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 = "5.6.9.4 (2013/10/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             * @og.rev 5.6.9.4 (2013/10/31) エラーメ?ージに?行前の??も?力します?
087             *
088             * @param   rowNo 選択された行番号配?(登録する対象?
089             * @param   table DBTableModelオブジェク?登録する?ータ)
090             */
091            @Override
092            public void execute( final int[] rowNo, final DBTableModel table ) {
093                    PreparedStatement pstmt = null ;
094    //              ParameterMetaData pMeta = null ;                // 5.5.5.4 (2012/08/18) useParamMetaData 処?、ループ?外に出す?(
095    
096                    int row = 0;                    // エラー時に表示するエラー行番号
097                    try {
098                            int executeCount = 0;   // 処?数
099                            Formatter form = new Formatter( table );
100                            form.setFormat( getStatement() );
101                            int[] clmNos = form.getClmNos();                // 引数の個数??配?。カラ?号を保?
102                            String query = form.getQueryFormatString();
103                            int   cnt    = clmNos.length;                   // 引数の個数(カラ??個数ではありません?
104    
105                            // 5.5.5.4 (2012/08/18) Timestamp オブジェクトを登録できるようにする?
106                            boolean useTimeStamp = false;
107                            boolean[] isTime = new boolean[cnt];
108                            for( int j=0; j<cnt; j++ ) {
109                                    // 5.5.8.5 (2012/11/27) TIMESTAMP型でも??きるようにします?
110    //                              isTime[j] = "DATE".equalsIgnoreCase( table.getDBColumn( clmNos[j] ).getClassName() );
111                                    String clsName = table.getDBColumn( clmNos[j] ).getClassName();
112                                    isTime[j] = "DATE".equalsIgnoreCase( clsName ) || "TIMESTAMP".equalsIgnoreCase( clsName );
113                                    if( !useTimeStamp && isTime[j] ) { useTimeStamp = true; }       // isTime[j] == true 時に、??実行される?
114                            }
115    
116                            Connection conn = getConnection();
117                            pstmt = conn.prepareStatement( query );
118                            pstmt.setQueryTimeout( DB_MAX_QUERY_TIMEOUT );
119                    //      ((oracle.jdbc.OraclePreparedStatement)pstmt).setExecuteBatch(50);
120                            // 4.0.0.0 (2007/09/25) isOracle から useParamMetaData に変更
121    //                      boolean useParamMetaData = ApplicationInfo.useParameterMetaData( conn );
122                            boolean useParamMetaData = useParameterMetaData();      // 5.3.8.0 (2011/08/01)
123    
124                            // 5.5.5.4 (2012/08/18) 以下?useParamMetaData、useTimeStamp??常の?種類を、行?ループ?外に出す?
125                            // 5.5.5.4 (2012/08/18) useParamMetaData 処?、ループ?外に出す?(PostgreSQL対?
126                            if( useParamMetaData ) {
127                                    int[] types = new int[cnt];
128                                    ParameterMetaData pMeta = pstmt.getParameterMetaData();
129                                    for( int j=0; j<cnt; j++ ) {
130                                            types[j] = pMeta.getParameterType( j+1 );       // ?こし?配?の個数と添え字?関係から?j と j+1 での処?なる?
131                                    }
132    
133                                    for( int i=0; i<rowNo.length; i++ ) {
134                                            row = rowNo[i];
135                                            for( int j=0; j<cnt; j++ ) {
136                                                    String val = StringUtil.rTrim( table.getValue( row,clmNos[j] ) );
137                                                    if( val == null || val.isEmpty() ) {
138                                                            pstmt.setNull( j+1, types[j] );
139                                                    }
140                                                    else {
141                                                            pstmt.setObject( j+1, val, types[j] );
142                                                    }
143                                            }
144                                            executeCount += pstmt.executeUpdate();
145                                    }
146                            }
147                            // 5.5.5.4 (2012/08/18) PostgreSQL対?以外?DBの場?
148                            else {
149                                    // 5.5.5.4 (2012/08/18) Timestamp オブジェクトを登録する場?
150                                    if( useTimeStamp ) {
151                                            for( int i=0; i<rowNo.length; i++ ) {
152                                                    row = rowNo[i];
153                                                    for( int j=0; j<cnt; j++ ) {
154                                                            String val = StringUtil.rTrim( table.getValue( row,clmNos[j] ) );
155                                                            if( isTime[j] && val != null && !val.isEmpty() ) {
156                                                                    // 5.5.8.5 (2012/11/27) val は、yyyy-mm-dd hh:mm:ss[.f...] 形式でなければならな??
157    //                                                              java.sql.Timestamp time = java.sql.Timestamp.valueOf( val );
158                                                                    java.sql.Timestamp time = java.sql.Timestamp.valueOf( HybsDateUtil.parseTimestamp( val ) );
159                                                                    pstmt.setObject( j+1,time );
160                                                            }
161                                                            else {
162                                                                    pstmt.setObject( j+1,val );
163                                                            }
164                                                    }
165                                                    executeCount += pstmt.executeUpdate();
166                                            }
167                                    }
168                                    // 5.5.5.4 (2012/08/18) そ?他:つまり?これが?常の処?
169                                    else {
170                                            for( int i=0; i<rowNo.length; i++ ) {
171                                                    row = rowNo[i];
172                                                    for( int j=0; j<cnt; j++ ) {
173                                                            String val = StringUtil.rTrim( table.getValue( row,clmNos[j] ) );
174                                                            pstmt.setObject( j+1,val );
175                                                    }
176                                                    executeCount += pstmt.executeUpdate();
177                                            }
178                                    }
179                            }
180    //                      if( useParamMetaData ) { pMeta = pstmt.getParameterMetaData(); }
181    //                      for( int i=0; i<rowNo.length; i++ ) {
182    //                              row = rowNo[i];
183    //                              for( int j=0; j<cnt; j++ ) {
184    ////                                    String val = table.getValue( row,clmNos[j] ) ;  // 5.3.8.0 (2011/08/01) 簡?
185    //                                      String val = StringUtil.rTrim( table.getValue( row,clmNos[j] ) );
186    //                                      // 4.0.0.0 (2007/09/25) ParameterMetaData を使用したパラメータ設定追?
187    //                                      if( useParamMetaData ) {
188    //                                              int type = pMeta.getParameterType( j+1 );
189    //                                              // 5.3.8.0 (2011/08/01) setNull 対?
190    ////                                            pstmt.setObject( j+1,StringUtil.rTrim( val ),type );
191    //                                              if( val == null || val.isEmpty() ) {
192    //                                                      pstmt.setNull( j+1, type );
193    //                                              }
194    //                                              else {
195    //                                                      pstmt.setObject( j+1, val, type );
196    //                                              }
197    //                                      }
198    //                                      else {
199    ////                                            pstmt.setObject( j+1,StringUtil.rTrim( val ) );
200    //                                              pstmt.setObject( j+1,val );
201    //                                      }
202    //                              }
203    //                              executeCount += pstmt.executeUpdate();
204    //                      }
205                            setExecuteCount( executeCount );
206                            setErrorCode( ErrorMessage.OK );
207                    }
208                    catch (SQLException ex) {
209                            setErrorCode( ErrorMessage.EXCEPTION );
210                            String errMsg = ex.getMessage() + ":" + ex.getSQLState() + HybsSystem.CR
211                                                    + "  QUERY=" + getStatement() + HybsSystem.CR
212                                                    + "  ROW =[" + (row+1) + "]" + HybsSystem.CR
213                                                    + "  VALS=[" + StringUtil.array2csv( table.getValues(row) )+ "]" + HybsSystem.CR ;
214                            // 5.6.9.4 (2013/10/31)
215                            if( row > 0 ) {
216                                    errMsg = errMsg
217                                                    + "  ROW(-1) =[" + (row) + "]" + HybsSystem.CR
218                                                    + "  VALS(-1)=[" + StringUtil.array2csv( table.getValues(row-1) )+ "]" + HybsSystem.CR ;
219                            }
220                            rollback();
221                            realClose();
222                            throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び?更
223                    }
224                    finally {
225                            Closer.stmtClose( pstmt );
226                    }
227            }
228    }