    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.hayabusa.taglib;
    017
    018import static org.opengion.fukurou.util.StringUtil.*;
    019
    020import java.io.IOException;
    021import java.io.ObjectInputStream;
    022import java.io.ObjectOutputStream;
    023import java.util.ArrayList;
    024import java.util.List;
    025import java.util.Locale;
    026
    027import org.opengion.fukurou.db.DBUtil;
    028import org.opengion.fukurou.db.Transaction;
    029import org.opengion.fukurou.db.TransactionReal;
    030import org.opengion.fukurou.util.ErrorMessage;
    031import org.opengion.fukurou.util.StringUtil;
    032import org.opengion.hayabusa.common.HybsSystem;
    033import org.opengion.hayabusa.common.HybsSystemException;
    034import org.opengion.hayabusa.db.DBColumn;
    035import org.opengion.hayabusa.db.DBEditConfig;
    036import org.opengion.hayabusa.db.DBTableModel;
    037import org.opengion.hayabusa.db.Query;
    038import org.opengion.hayabusa.db.QueryFactory;
    039import org.opengion.hayabusa.resource.GUIInfo;
    040
    041/**
    042 * データベースの検索を行うタグです。
    043 *
    044 * このタグの内容に、SQL文を記述します。 whereタグ、 andタグ を使うと引数に応じて
    045 * 実行されるSQL文が異なります(使用例参照)。
    046 * また、PL/SQLのSPで検索を行うときもこのタグを使います。
    047 * SystemData の USE_SQL_INJECTION_CHECK が true か、quotCheck 属性が true の場合は、
    048 * ＳＱＬインジェクション対策用のクォーティションチェックを行います。リクエスト引数に
    049 * クォーティション(')が含まれると、エラーになります。
    050 * 同様にUSE_XSS_CHECKがtrueか、xssCheck属性がtrueの場合は、
    051 * クロスサイトススクリプティング(XSS)対策のためless/greater than signのチェックを行います。
    052 *
    053 * ※ このタグは、Transaction タグの対象です。
    054 *
    055 * @og.formSample
    056 * ●形式：
    057 *       ・&lt;og:query command="NEW" &gt;
    058 *              SELECT文
    059 *         &lt;/og:query&gt;
    060 *       ・&lt;og:query command="NEW" names="･･･" queryType="JDBCErrMsg" &gt;
    061 *              { call PL/SQL(?,?,?,? ) }
    062 *         &lt;/og:query&gt;
    063 * ●body：あり(EVAL_BODY_BUFFERED:BODYを評価し、{&#064;XXXX} を解析します)
    064 *
    065 * ●Tag定義：
    066 *   &lt;og:query
    067 *       queryType          【TAG】Query を発行する為のクラスID(JDBC,JDBCCallable,JDBCErrMsg,JDBCUpdate)を指定します{@og.doc03Link queryType 初期値:JDBC})
    068 *       command            【TAG】コマンド(NEW,RENEW)をセットします(PlsqlUpdateTag,UpdateTag の場合は、ENTRY)
    069 *       scope              【TAG】キャッシュする場合のスコープ[request/page/session/applicaton]を指定します(初期値:session)
    070 *       maxRowCount        【TAG】(通常は使いません)データの最大読み込み件数を指定します (初期値:DB_MAX_ROW_COUNT[=1000])(0:[無制限])
    071 *       skipRowCount       【TAG】(通常は使いません)データの読み始めの初期値を指定します
    072 *       displayMsg         【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します (初期値:VIEW_DISPLAY_MSG[=])
    073 *       overflowMsg        【TAG】検索データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します (初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました])
    074 *       notfoundMsg        【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])
    075 *       names              【TAG】PL/SQLを利用する場合の引数にセットすべき データの名称をCSV形式で複数指定します
    076 *       stopZero           【TAG】検索結果が０件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する])
    077 *       tableId            【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
    078 *       dbid               【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します
    079 *       trace              【TAG】引数の SQL 文を EXPLAIN PLAN を[true:行う/それ以外:行わない]を指定します(初期値:false)
    080 *       checkNames         【TAG】リクエスト変数の正規化を行うカラムをCSV形式で複数指定します
    081 *       modifyType         【TAG】DB検索時の モディファイタイプを指定します[A:追加/C:更新/D:削除]
    082 *       quotCheck          【TAG】リクエスト情報の クォーティション(') 存在チェックを実施するかどうか[true/false]を設定します(初期値:USE_SQL_INJECTION_CHECK)
    083 *       stopError          【TAG】PLSQL/SQL処理エラーの時に処理を中止するかどうか[true/false]を設定します(初期値:true)
    084 *       dispError                      【TAG】エラー時にメッセージを表示するか[true/false]を設定します。通常はstopErrorと併用(初期値:true)
    085 *       xssCheck           【TAG】リクエスト情報の HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか[true/false]を設定します (初期値:USE_XSS_CHECK[=true])
    086 *       mainTrans          【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:true)
    087 *       caseKey            【TAG】このタグ自体を利用するかどうかの条件キーを指定します(初期値:null)
    088 *       caseVal            【TAG】このタグ自体を利用するかどうかの条件値を指定します(初期値:null)
    089 *       caseNN             【TAG】指定の値が、null/ゼロ文字列 でない場合(Not Null=NN)は、このタグは使用されます(初期値:true)
    090 *       caseNull           【TAG】指定の値が、null/ゼロ文字列 の場合は、このタグは使用されます(初期値:true)
    091 *       useBeforeHtmlTag   【TAG】 処理時間(queryTime)などの情報出力[true:有効/false:無効]を指定します(初期値:true)
    092 *       debug              【TAG】デバッグ情報を出力するかどうか[true/false]を指定します(初期値:false)
    093 *   &gt;   ... Body ...
    094 *   &lt;/og:query&gt;
    095 *
    096 * ●使用例
    097 *     &lt;og:query command="NEW"&gt;
    098 *             select PN,YOBI,NMEN,HINM from XX01 where PN = '{&#064;PN}' order by PN
    099 *     &lt;/og:query&gt;
    100 *
    101 *          ・検索条件が入力された時({&#064;PN}がNOT NULLのとき)
    102 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 where PN = 'AAA' order by PN
    103 *          ・検索条件が入力されなかった時({&#064;PN}がNULLのとき)
    104 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 where PN = '' order by PN
    105 *
    106 *     &lt;og:query command="NEW"&gt;
    107 *             select PN,YOBI,NMEN,HINM from XX01
    108 *         &lt;og:where&gt;
    109 *             &lt;og:and value="PN = '{&#064;PN}%'" /&gt;
    110 *             &lt;og:and value="YOBI like '{&#064;YOBI}%'" /&gt;
    111 *         &lt;/og:where&gt;
    112 *             order by PN
    113 *     &lt;/og:query&gt;
    114 *
    115 *          ・検索条件が入力された時({&#064;PN}がNOT NULLのとき)
    116 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 PN = 'AAA%' and YOBI like 'BBB%' order by PN
    117 *          ・検索条件が入力されなかった時({&#064;PN}がNULLのとき) WHERE句がなくなる。
    118 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 order by PN
    119 *
    120 *        注意:WhereTagを使った場合、下のようにはなりません。
    121 *            select PN,YOBI,NMEN,HINM from XX01 PN = '' and YOBI like '%' order by PN
    122 *
    123 *     &lt;og:query command="NEW"&gt;
    124 *             select PN,YOBI,NMEN,HINM from XX01 where PN="11111"
    125 *         &lt;og:where startKey="and"&gt;
    126 *             &lt;og:and value="YOBI like '{&#064;PN}%'" /&gt;
    127 *         &lt;/og:where&gt;
    128 *             order by PN
    129 *     &lt;/og:query&gt;
    130 *
    131 *          ・検索条件が入力された時({&#064;YOBI}がNOT NULLのとき)
    132 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 PN = '11111' and YOBI like 'BBB%' order by PN
    133 *          ・検索条件が入力されなかった時({&#064;YOBI}がNULLのとき) WHERE句がなくなる。
    134 *            作成されるSQL文⇒select PN,YOBI,NMEN,HINM from XX01 PN = '11111' order by PN
    135 *
    136 *     &lt;og:query
    137 *          command    = "NEW"
    138 *          names      = "SYSTEM_ID,LANG,CLM,NAME_JA,LABEL_NAME,KBSAKU,USER.ID"
    139 *          checkNames = "CLM,NAME_JA"
    140 *          queryType  = "JDBCErrMsg"
    141 *          displayMsg = ""&gt;
    142 *              {call TYPE3B01.TYPE3B01(?,?,?,?)}
    143 *     &lt;/og:query&gt;
    144 *
    145 *          ・queryType に JDBCErrMsg を指定して、PL/SQL をコールできます。
    146 *            引数は、names 属性をキーにリクエスト変数から読み込みます。
    147 *          ・checkNames にカラム名を指定すると、columns.valueSet による
    148 *            リクエスト変数の正規化を行います。
    149 *
    150 * @og.group ＤＢ検索
    151 * @og.group ＤＢ登録
    152 *
    153 * @version  4.0
    154 * @author       Kazuhiko Hasegawa
    155 * @since    JDK5.0,
    156 */
    157public class QueryTag extends CommonTagSupport {
    158        //* このプログラムのVERSION文字列を設定します。   {@value} */
    159        private static final String VERSION = "5.6.5.3 (2013/06/28)" ;
    160
    161        private static final long serialVersionUID = 565320130628L ;
    162
    163        /** command 引数に渡す事の出来る コマンド  新規 {@value} */
    164        public static final String CMD_NEW       = "NEW" ;
    165        /** command 引数に渡す事の出来る コマンド  再検索 {@value} */
    166        public static final String CMD_RENEW = "RENEW" ;
    167        /** command 引数に渡す事の出来る コマンド リスト  */
    168        private static final String[] COMMAND_LIST = new String[] { CMD_NEW , CMD_RENEW };
    169
    170        /** エラーメッセージID {@value} */
    171        protected static final String errMsgId   = HybsSystem.ERR_MSG_KEY;
    172
    173        private   String        queryType       = null;
    174        // 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
    175//      private   String        dbid            = "DEFAULT";
    176        private   String        dbid            = null ;
    177        protected transient DBTableModel        table           = null;
    178        protected transient ErrorMessage        errMessage      = null;
    179        protected String        tableId         = HybsSystem.TBL_MDL_KEY;
    180        protected String        command         = CMD_NEW;
    181        protected int           skipRowCount = 0;
    182        protected int           maxRowCount     = -1;
    183        protected String        sql                     = null;
    184        protected int           executeCount = -1;                      // 検索/実行件数
    185        protected String        names           = null;
    186        protected boolean       outMessage      = true;
    187        protected int           errCode         = ErrorMessage.OK;
    188        protected boolean       quotCheck       = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" );      // 4.0.0 (2005/08/31)
    189        private   boolean       trace           = false;                // 4.0.0 (2005/01/31) 廃止
    190        private   boolean       stopZero        = false;
    191        private   String        modifyType      = null;                 // 3.8.5.1 (2006/05/08) modifyType 属性を追加します。
    192//      private   String        displayMsg      = "MSG0033";    // 　件検索しました。
    193        protected String        displayMsg      = HybsSystem.sys( "VIEW_DISPLAY_MSG" );
    194        private   String        overflowMsg     = "MSG0007";    // 検索結果が、制限行数を超えましたので、残りはカットされました。
    195        private   String        notfoundMsg     = "MSG0077";    // 対象データはありませんでした。
    196        private   boolean       isMainTrans     = true;                 // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
    197
    198        // 3.5.4.7 (2004/02/06) 実行時間測定用のDIV要素を出力します。
    199        protected long dyStart = 0;
    200        // 4.3.3.0 (2008/09/22) PLSQL/SQL実行エラーの際に、処理を中止するかどうか。
    201        protected boolean stopError             = true;
    202
    203        // 5.9.26.1 (2017/11/10) 実行エラーの際に、エラーを画面に出力するかどうか。
    204        protected boolean dispError             = true;
    205
    206        private StringBuilder debugMsg = null;          // 3.5.6.0 (2004/06/18)
    207
    208        // 3.8.0.5 (2005/08/20) リクエスト変数の正規化を行います。
    209        private String                  checkNames      = null;
    210
    211        // 3.8.5.3 (2006/08/07) トレース時のメッセージ文字列を保存しておきます。
    212        private String                  traceMsg        = null;
    213
    214        protected boolean       xssCheck        = HybsSystem.sysBool( "USE_XSS_CHECK" );        // 5.0.0.2 (2009/09/15)
    215
    216        // 5.3.5.0 (2011/05/01) 処理時間(queryTime)などの情報出力の有効/無効を指定します。
    217        private boolean         useBeforeHtmlTag        = true ;
    218
    219        // 5.10.2.1 (2018/08/18) where-andタグのplaceHolder情報を保持する
    220        private transient List<String> listPlaceValue = null;
    221
    222        /**
    223         * Taglibの開始タグが見つかったときに処理する doStartTag() を オーバーライドします。
    224         *
    225         * @og.rev 3.5.4.7 (2004/02/06) 実行時間測定用に、開始時刻を取得します。
    226         * @og.rev 3.5.6.5 (2004/08/09) 暫定的に、DBTableModelを先行削除します。
    227         * @og.rev 3.6.0.0 (2004/09/24) DBTableModel の先行削除は、scope="session" の場合のみ。
    228         * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
    229         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
    230         *
    231         * @return      後続処理の指示
    232         */
    233        @Override
    234        public int doStartTag() {
    235                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
    236                if( useTag() ) {
    237                        dyStart = System.currentTimeMillis();
    238                        if( ! check( command, COMMAND_LIST ) ) { return(SKIP_BODY); }
    239
    240                        useMainTrans( isMainTrans );                    // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
    241                        startQueryTransaction( tableId );               // 3.6.0.8 (2004/11/19)
    242
    243                        // 3.5.6.5 (2004/08/09) 削除するのは、セッションのオブジェクトでよい。
    244                        // 3.6.0.0 (2004/09/24) 削除するのは、scope="session" の場合のみ。
    245                        if( "session".equals( getScope() ) ) {
    246                                removeSessionAttribute( tableId );
    247                                removeSessionAttribute( HybsSystem.VIEWFORM_KEY );
    248                        }
    249
    250                        return( EVAL_BODY_BUFFERED );   // Body を評価する。( extends BodyTagSupport 時)
    251                }
    252                return ( SKIP_BODY );                           // Body を評価しない
    253        }
    254
    255        /**
    256         * Taglibのタグ本体を処理する doAfterBody() を オーバーライドします。
    257         *
    258         * @og.rev 3.1.1.0 (2003/03/28) ボディの内容を取得する処理を、CommonTagSupport で行う。
    259         * @og.rev 3.6.0.8 (2004/11/19) エラー発生時に確実にリリースされるように try finally 追加
    260         * @og.rev 3.8.5.3 (2006/08/07) USER.LASTSQL へのSQL文の保存は、実行前に行っておきます。
    261         * @og.rev 3.8.6.3 (2006/11/30) SQL 文の前後のスペースを取り除きます。
    262         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
    263         * @og.rev 4.0.0.0 (2005/01/31) lang ⇒ ResourceManager へ変更
    264         * @og.rev 4.0.0.0 (2005/08/31) useQuotCheck() によるＳＱＬインジェクション対策
    265         * @og.rev 4.3.4.0 (2008/12/01) GE20(ユーザー定数)へ登録するかのフラグへの対応
    266         * @og.rev 5.0.0.2 (2009/09/15) XSS対応
    267         * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
    268         * @og.rev 5.1.9.0 (2010/08/01) TransactionTag 対応。上位に TransactionTag があれば、そこからConnection をもらう。
    269         * @og.rev 5.3.6.0 (2011/06/01) 集計、合計などのEdit機能に対応します。
    270         * @og.rev 5.3.7.0 (2011/07/01) TransactionReal の引数変更
    271         * @og.rev 5.3.7.0 (2011/07/01) PL/SQLかつscope="request"で正しく出力するためqueryType,namesも保存する。
    272         * @og.rev 5.3.8.0 (2011/08/01) Transaction発生箇所でclose()
    273         * @og.rev 5.5.3.4 (2012/06/19) trace 時は、実際の検索処理を行わない様に変更。
    274         * @og.rev 5.6.5.3 (2013/06/28) LASTQUERYTYPE ⇒ LASTSQLTYPE 変更。
    275         *
    276         * @return      後続処理の指示(SKIP_BODY)
    277         */
    278        @Override
    279        public int doAfterBody() {
    280
    281                // 4.0.0 (2005/08/31) useQuotCheck() によるＳＱＬインジェクション対策
    282                useQuotCheck( quotCheck );
    283                // 5.0.0.2 (2009/09/15) XSS対策
    284                useXssCheck( xssCheck );
    285
    286                sql = getBodyString().trim();
    287
    288                // 3.2.1.0 (2003/05/28) 最終ＳＱＬ文を、UserInfo に、キャッシュしておく。
    289//              setUserInfo( "LASTSQL", sql );
    290                // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
    291                if( isMainTrans ) {
    292                        setUserInfo( "LASTSQL", sql, false );
    293                        // 5.3.7.0 (2011/07/01) PL/SQLかつscope="request"で正しく出力するためqueryType,namesも保存する。
    294//                      setUserInfo( "LASTQUERYTYPE", queryType, false );
    295                        setUserInfo( "LASTSQLTYPE", queryType, false );                         // 5.6.5.3 (2013/06/28)
    296                        setUserInfo( "LASTNAMES", names, false );
    297                }
    298
    299                Query query = QueryFactory.newInstance( queryType );
    300                Transaction tran = null;
    301                try {
    302                        if( maxRowCount < 0 ) {
    303                                maxRowCount     = sysInt( "DB_MAX_ROW_COUNT" );
    304                        }
    305
    306                        // 5.1.9.0 (2010/08/01) TransactionTag 対応
    307//                      final Transaction tran ;
    308                        TransactionTag tranTag = (TransactionTag)findAncestorWithClass( this,TransactionTag.class );
    309                        if( tranTag == null ) {
    310//                              tran = new TransactionReal( dbid,getApplicationInfo() );
    311                                tran = new TransactionReal( getApplicationInfo() );             // 5.3.7.0 (2011/07/01) 引数変更
    312                        }
    313                        else {
    314                                tran = tranTag.getTransaction();
    315                        }
    316                        query.setTransaction( dbid,tran );      // 5.1.9.0 (2010/08/01) TransactionTag 対応
    317
    318                        query.setSkipRowCount( skipRowCount );
    319                        query.setMaxRowCount( maxRowCount );
    320//                      query.setConnectionID( dbid );
    321                        query.setResourceManager( getResource() );      // 4.0.0 (2005/01/31)
    322
    323                        if( trace ) {
    324//                              traceMsg = traceQuery( sql );
    325                                traceMsg = traceQuery( sql,tran );              // 5.1.9.0 (2010/08/01) TransactionTag 対応
    326                                // 5.5.3.4 (2012/06/19) trace 時は、実際の検索処理を行わない様に変更
    327//                              query.setMaxRowCount( 1 );
    328                                return(SKIP_BODY);
    329                        }
    330                        query.setStatement( sql );
    331//                      query.setApplicationInfo( getApplicationInfo() );       // 3.8.7.0 (2006/12/15)
    332
    333                        // 5.3.6.0 (2011/06/01) 集計、合計などのEdit機能に対応します。
    334                        if( isMainTrans ) {
    335                                String guikey = getGUIInfoAttri( "KEY" );
    336                                String editName = getRequestValue( "editName" );
    337                                DBEditConfig config = getUser().getEditConfig( guikey, editName );
    338                                if( config != null ) {
    339                                        query.setEditConfig( config );
    340                                }
    341                        }
    342
    343                        execute( query );
    344
    345                        executeCount = query.getExecuteCount();
    346                        if( errCode < ErrorMessage.NG && executeCount >= 0 ) {            // 異常以外の場合
    347                                table = query.getDBTableModel();
    348                                // 3.8.5.1 (2006/05/08) modifyType 属性を追加します。
    349                                if( modifyType != null ) {
    350                                        for( int row=0; row<executeCount; row++ ) {
    351                                                table.setModifyType( row,modifyType );
    352                                        }
    353                                }
    354                        }
    355                }
    356                finally {
    357//                      if( query != null ) { query.close(); }
    358                        QueryFactory.close( query );
    359                        if( tran != null ) { tran.close(); }            // 5.3.8.0 (2011/08/01) Transaction発生箇所でclose()
    360                }
    361                return(SKIP_BODY);
    362        }
    363
    364        /**
    365         * Taglibの終了タグが見つかったときに処理する doEndTag() を オーバーライドします。
    366         *
    367         * @og.rev 2.0.0.8 (2002/10/09) command="NEW" のときのみ、displayMsg を表示させます。
    368         * @og.rev 2.1.1.4 (2002/11/25) デバッグ時に最終SQLをユーザー情報をセットするように変更。
    369         * @og.rev 2.1.2.1 (2002/11/27) ErrorMessage をクリアしないように変更。
    370         * @og.rev 3.1.1.0 (2003/03/28) JspWriter オブジェクトの使用箇所を、jspPrint() を使用するように変更。
    371         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
    372         * @og.rev 3.2.1.0 (2003/05/28) 最終ＳＱＬ文を、UserInfo に、キャッシュしておく。
    373         * @og.rev 3.3.3.3 (2003/08/06) 検索結果の件数を、"DB.COUNT" キーでリクエストにセットする。
    374         * @og.rev 3.3.3.3 (2003/08/06) 検索結果を、"DB.ERR_CODE" キーでリクエストにセットする。
    375         * @og.rev 3.5.4.7 (2004/02/06) 実行時間測定用のDIV要素を出力しておきます。
    376         * @og.rev 3.5.4.9 (2004/02/25) 警告時に停止していましたが、継続処理させます。
    377         * @og.rev 3.5.5.0 (2004/03/12) ErrorMessage オブジェクトを、query が成功した時にもクリアするように変更
    378         * @og.rev 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用
    379         * @og.rev 3.5.5.8 (2004/05/20) ErrorMessage オブジェクトを、コマンドが NEW の場合のみ、クリア
    380         * @og.rev 3.5.6.0 (2004/06/18) debugMsg 属性を出力するように修正します。
    381         * @og.rev 3.6.0.8 (2004/11/19) DBTableModel をセーブする時に、トランザクションチェックを行います。
    382         * @og.rev 3.8.5.3 (2006/08/07) USER.LASTSQL へのSQL文の保存は、実行前に行っておきます。
    383         * @og.rev 4.0.0.0 (2006/11/14) notfoundMsg 属性を追加。displayMsg は、VIEW_USE_DISPLAY_MSG で制御
    384         * @og.rev 4.0.0.0 (2007/10/18) メッセージリソース統合( getResource().getMessage ⇒ getResource().getLabel )
    385         * @og.rev 4.3.3.0 (2008/09/22) 属性 stopError の設定により、JSP処理を中止するかどうかを制御します。
    386         * @og.rev 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
    387         * @og.rev 5.3.5.0 (2011/05/01) 処理時間(queryTime)などの情報出力の有効/無効を指定します。
    388         * @og.rev 5.5.0.3 (2012/03/13) オーバーフローメッセージが存在しないときは、何もしない。(改行も入れない)
    389         * @og.rev 5.5.3.4 (2012/06/19) trace 時は、実際の検索処理を行わない様に変更。
    390         * @og.rev 5.6.3.0 (2013/04/01) エラー時メッセージ変更
    391         * @og.rev 5.9.16.1 (2017/11/10) dispErrorの動作追加
    392         * @og.rev 5.10.2.2 (2018/08/24) 一部のエラーをjspPrintから標準のErrorMessageに変更
    393         *
    394         * @return      後続処理の指示
    395         */
    396        @Override
    397        public int doEndTag() {
    398                debugPrint();           // 4.0.0 (2005/02/28)
    399                // 5.2.2.0 (2010/11/01) caseKey 、caseVal 属性対応
    400                if( !useTag() ) { return(EVAL_PAGE); }
    401
    402                if( trace ) {
    403                        jspPrint( traceMsg );
    404                        return (SKIP_PAGE);             // 5.5.3.4 (2012/06/19) trace 時は、実際の検索処理を行わない様に変更。
    405                }
    406
    407                String label  = "";                             // 4.0.0 (2005/11/30) 検索しなかった場合。
    408                if( check( command, COMMAND_LIST ) ) {
    409                        StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_SMALL );
    410
    411                        // 実行件数の表示 command="NEW" のときのみ、displayMsg を表示させます。
    412                        // 4.0.0 (2005/11/30) 出力順の変更。一番最初に出力します。
    413//                      boolean useStatusBar = HybsSystem.sysBool( "VIEW_USE_DISPLAY_MSG" );
    414                        if( CMD_NEW.equals( command ) ) {
    415//                              if( useStatusBar && executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) {
    416                                if( executeCount > 0 && displayMsg != null && displayMsg.length() > 0 ) {
    417                                        buf.append( executeCount );
    418//                                      buf.append( getResource().getMessage( displayMsg ) );
    419                                        buf.append( getResource().getLabel( displayMsg ) );
    420                                        buf.append( HybsSystem.BR );
    421                                }
    422                                else if( executeCount == 0 && notfoundMsg != null && notfoundMsg.length() > 0 ) {
    423//                                      buf.append( getResource().getMessage( notfoundMsg ) );
    424                                        buf.append( getResource().getLabel( notfoundMsg ) );
    425                                        buf.append( HybsSystem.BR );
    426                                }
    427                        }
    428
    429                        // 3.3.3.3 (2003/08/06) 検索結果の件数を、"DB.COUNT" キーでリクエストにセットする。
    430                        setRequestAttribute( "DB.COUNT"   , String.valueOf( executeCount ) );
    431                        // 3.3.3.3 (2003/08/06) 検索結果を、"DB.ERR_CODE" キーでリクエストにセットする。
    432                        setRequestAttribute( "DB.ERR_CODE", String.valueOf( errCode ) );
    433
    434                        // オーバーフロー時のメッセージを表示
    435//                      if( table != null && table.isOverflow() ) {
    436                        // 5.5.0.3 (2012/03/09) オーバーフローメッセージが存在しないときは、何もしない。(改行も入れない)
    437                        if( table != null && table.isOverflow() && overflowMsg != null && overflowMsg.length() > 0  ) {
    438//                              buf.append( getResource().getMessage( overflowMsg ) );
    439                                buf.append( getResource().getLabel( overflowMsg ) );
    440                                buf.append( HybsSystem.BR );
    441                        }
    442
    443                        // 5.10.2.2 (2018/08/24) 6.9.9.0  ｢ERR0041:検索処理中に割り込みの検索要求がありました｣エラーを、標準のErrorMessageに追加するようにします。
    444                        if( table != null && ! commitTableObject( tableId, table ) ) {
    445                                if( errMessage == null ) { errMessage = new ErrorMessage( "QueryTag Query Error!" ); }
    446                                // ERR0041:検索処理中に割り込みの検索要求がありました。処理されません。
    447                                errMessage.addMessage( 0,ErrorMessage.NG,"ERR0041" );
    448                                errCode = ErrorMessage.NG;
    449                        }
    450
    451                        // 3.5.5.2 (2004/04/02) TaglibUtil.makeHTMLErrorTable メソッドを利用
    452                        String err = TaglibUtil.makeHTMLErrorTable( errMessage,getResource() );
    453                        if( err != null && err.length() > 0 ) {
    454                                buf.append( err );
    455                                setSessionAttribute( errMsgId,errMessage );
    456                        }
    457                        else if( CMD_NEW.equals( command ) ) {          // 3.5.5.8 (2004/05/20)
    458                                removeSessionAttribute( errMsgId );
    459                        }
    460                        label = buf.toString();
    461
    462                        // 5.9.26.1 (2017/11/10) エラーメッセージをリクエスト変数で持つようにしておく
    463                        setRequestAttribute( "DB.ERR_MSG", label );
    464//                      //  5.10.2.2 (2018/08/24) 6.9.9.0
    465//                      if( table != null && ! commitTableObject( tableId, table ) ) {
    466//                              // 3.6.0.8 (2004/11/19) トランザクションチェックを行います。
    467//                              // jspPrint( "QueryTag Query処理が割り込まれました。DBTableModel は登録しません。" );
    468//
    469//                              // 5.6.4.0 (2013/04/01) リソースから出力するように対応
    470//                              ErrorMessage errMsgObj = new ErrorMessage( "QueryTag Query Error!" );
    471//                              errMsgObj.addMessage( 0,ErrorMessage.NG,"ERR0041" );
    472//                              jspPrint( TaglibUtil.makeHTMLErrorTable( errMsgObj,getResource() ) );
    473//
    474//                              return (SKIP_PAGE);
    475//                      }
    476                }
    477
    478                // 5.9.26.1 (2017/11/10) dispErrorで表示をコントロール
    479                if( dispError ) {
    480                        jspPrint( label );
    481                }
    482
    483                // 3.5.4.9 (2004/02/25) 警告時に停止していましたが、継続処理させます。
    484//              int rtnCode = EVAL_PAGE;
    485                final int rtnCode ;
    486                if( errCode >= ErrorMessage.NG )  {  // 異常
    487                        if( stopError ) {                               // 4.3.3.0 (2008/09/22) 属性 stopError の設定により、処理を中止するかを判断します。
    488                                rtnCode = SKIP_PAGE;
    489                        }
    490                        else {
    491                                rtnCode = EVAL_PAGE;
    492                        }
    493                }
    494                else {
    495                        // 件数０件かつ stopZero = true
    496                        if( executeCount == 0 && stopZero )     {
    497                                rtnCode = SKIP_PAGE;
    498                        }
    499                        else {
    500                                rtnCode = EVAL_PAGE;
    501                        }
    502                }
    503
    504                // 3.5.4.7 (2004/02/06)
    505                long dyTime = System.currentTimeMillis()-dyStart;
    506
    507                // 5.3.5.0 (2011/05/01) 処理時間(queryTime)などの情報出力の有効/無効を指定します。
    508                if( useBeforeHtmlTag ) {
    509                        jspPrint( "<div id=\"queryTime\" value=\"" + (dyTime) + "\"></div>" );      // 3.5.6.3 (2004/07/12)
    510                }
    511
    512                // 4.0.0 (2005/01/31) セキュリティチェック(データアクセス件数登録)
    513                GUIInfo guiInfo = (GUIInfo)getSessionAttribute( HybsSystem.GUIINFO_KEY );
    514                if( guiInfo != null ) { guiInfo.addReadCount( executeCount,dyTime,sql ); }
    515
    516                return( rtnCode );
    517        }
    518
    519        /**
    520         * タグリブオブジェクトをリリースします。
    521         * キャッシュされて再利用されるので、フィールドの初期設定を行います。
    522         *
    523         * @og.rev 2.0.0.4 (2002/09/27) カスタムタグの release() メソッドを、追加
    524         * @og.rev 3.1.1.2 (2003/04/04) Tomcat4.1 対応。release2() を doEndTag()で呼ぶ。
    525         * @og.rev 3.5.4.7 (2004/02/06) 実行時間測定用に、dyStart を追加します。
    526         * @og.rev 3.5.6.0 (2004/06/18) debugMsg 属性を追加します。
    527         * @og.rev 3.8.0.5 (2005/08/20) checkNames 属性を追加します。
    528         * @og.rev 3.8.5.1 (2006/05/08) modifyType 属性を追加します。
    529         * @og.rev 3.8.5.1 (2006/05/08) traceMsg 属性(トレース時のメッセージ文字列)を追加します。
    530         * @og.rev 4.0.0.0 (2005/08/31) quotCheck 属性の追加
    531         * @og.rev 4.0.0.0 (2007/10/10) dbid の初期値を、"DEFAULT" から null に変更
    532         * @og.rev 4.3.3.0 (2008/09/22) stopError 属性の追加
    533         * @og.rev 5.0.0.2 (2009/09/15) XSS対応
    534         * @og.rev 5.1.6.0 (2010/05/01) DBLastSqlの処理は、DBTableModelが新規作成された処理でのみ行う。
    535         * @og.rev 5.3.5.0 (2011/05/01) 処理時間(queryTime)などの情報出力の有効/無効を指定します。
    536         * @og.rev 5.9.26.1 (2017/11/10) dispError追加
    537         * @og.rev 5.10.2.1 (2018/08/18) プレースホルダ対応
    538         *
    539         */
    540        @Override
    541        protected void release2() {
    542                super.release2();
    543                tableId                 = HybsSystem.TBL_MDL_KEY;
    544                queryType               = null;
    545//              dbid                    = "DEFAULT";
    546                dbid                    = null;
    547                command                 = CMD_NEW;
    548                skipRowCount    = 0;
    549                maxRowCount             = -1;
    550                table                   = null;
    551                sql                             = null;
    552//              displayMsg              = "MSG0033";    // 　件検索しました。
    553                displayMsg              = HybsSystem.sys( "VIEW_DISPLAY_MSG" );
    554                overflowMsg             = "MSG0007";    // 検索結果が、制限行数を超えましたので、残りはカットされました。
    555                notfoundMsg             = "MSG0077";    // 対象データはありませんでした。
    556                executeCount    = -1;                   // 検索/実行件数
    557                names                   = null;
    558                outMessage              = true;
    559                trace                   = false;
    560                errCode                 = ErrorMessage.OK;
    561                errMessage              = null;
    562                stopZero                = false;
    563                stopError               = true;                 // 4.3.3.0 (2008/09/22)
    564                dyStart                 = 0;
    565                debugMsg                = null;                 // 3.5.6.0 (2004/06/18)
    566                checkNames              = null;                 // 3.8.0.5 (2005/08/20)
    567                quotCheck               = HybsSystem.sysBool( "USE_SQL_INJECTION_CHECK" );      // 4.0.0 (2005/08/31)
    568                modifyType      = null;                 // 3.8.5.1 (2006/05/08)
    569                traceMsg                = null;                 // 3.8.5.3 (2006/08/07)
    570                xssCheck                = HybsSystem.sysBool( "USE_XSS_CHECK" );        // 5.0.0.2 (2009/09/15)
    571                isMainTrans             = true;                 // 5.1.6.0 (2010/05/01) DBLastSqlの処理の見直し
    572                useBeforeHtmlTag        = true ;        // 5.3.5.0 (2011/05/01)
    573                dispError               = true;                 // 5.9.26.1 (2017/11/10)
    574                listPlaceValue          = null;         // 5.10.2.1 (2018/08/18)
    575        }
    576
    577        /**
    578         * Query を実行します。
    579         *
    580         * @og.rev 2.1.2.3 (2002/12/02) データベース更新時に、更新フラグをセットするように変更
    581         * @og.rev 3.4.0.0 (2003/09/01) 登録エラー時のキーと値を表示するように変更。
    582         * @og.rev 3.5.6.0 (2004/06/18) デバッグ情報出力用に、printDebug メソッドを追加。
    583         * @og.rev 3.6.1.0 (2005/01/05) エラーコードによる commit/rollback の判断追加
    584         * @og.rev 5.3.7.0 (2011/07/01) nameの判定にゼロ文字列を付加
    585         * @og.rev 5.10.2.1 (2018/08/18) プレースホルダ対応
    586         *
    587         * @param       query オブジェクト
    588         */
    589        protected void execute( final Query query ) {
    590                String[] nameArray = null;
    591                String[] values    = null;
    592                try {
    593//                      if( names == null ) {
    594                        if( names == null || names.length() == 0 ) {
    595                                // 5.10.2.1 (2018/08/18)
    596                                // query.execute();
    597                                if(listPlaceValue != null && !listPlaceValue.isEmpty()) {
    598                                        // listPlaceValueに値が存在する場合は、listPlaceValueの値を渡す
    599                                        values = listPlaceValue.toArray(new String[listPlaceValue.size()]);
    600                                        query.execute(values);
    601                                }else {
    602                                        query.execute();
    603                                }
    604                        }
    605                        else {
    606                                nameArray = StringUtil.csv2Array( names );
    607                                // 5.10.2.1 (2018/08/18)
    608//                              values = getRequest( nameArray );
    609                                if(listPlaceValue != null && !listPlaceValue.isEmpty()) {
    610                                        // listPlaceValueに値が存在する場合は、listPlaceValueの値を設定
    611                                        values = listPlaceValue.toArray(new String[listPlaceValue.size()]);
    612                                }else {
    613                                        values = getRequest( nameArray );
    614                                }
    615
    616                                // 3.5.6.0 (2004/06/18) デバッグ情報出力用
    617                                if( isDebug() ) { printDebug( nameArray,values ); }
    618
    619                                query.execute( values );
    620                        }
    621                        errCode = query.getErrorCode();
    622                        errMessage = query.getErrorMessage();
    623                        // 3.6.1.0 (2005/01/05) エラーコードによる commit/rollback の判断追加
    624//                      if( query.getUpdateFlag() ) {
    625                        if( query.isUpdate() ) {
    626                                if( errCode < ErrorMessage.NG ) {            // 異常以下の場合
    627                                        query.commit();
    628                                }
    629                                else {
    630                                        query.rollback();
    631                                }
    632                        }
    633                }
    634                catch( HybsSystemException ex ) {
    635                        query.rollback();
    636
    637                        // 4.0.0 (2005/02/28) エラー時の表示とデバッグ時の表示を統一する。
    638                        String errMsg = "DATABASE ERROR! " + HybsSystem.CR ;
    639                        if( nameArray != null ) {
    640                                printDebug( nameArray,values );
    641                                errMsg += debugMsg;
    642                        }
    643                        throw new HybsSystemException( errMsg,ex );             // 3.5.5.4 (2004/04/15) 引数の並び順変更
    644                }
    645                finally {
    646                        if( query != null ) { query.close(); }
    647                }
    648        }
    649
    650        /**
    651         * デバッグ用に、配列データを書き出します。
    652         *
    653         * @og.rev 3.5.6.0 (2004/06/18) 新規追加
    654         *
    655         * @param       nms     引数 names の配列データ
    656         * @param       vals    names に対応するリクエスト情報の配列
    657         */
    658        private void printDebug( final String[] nms,final String[] vals ) {
    659                if( debugMsg == null ) { debugMsg = new StringBuilder(); }
    660
    661                debugMsg.append( "  names=[" );
    662                debugMsg.append( StringUtil.array2csv( nms ) );
    663                debugMsg.append( "]" );
    664                debugMsg.append( HybsSystem.CR );
    665                debugMsg.append( "  values=[" );
    666                debugMsg.append( StringUtil.array2csv( vals ) );
    667                debugMsg.append( "]" );
    668                debugMsg.append( HybsSystem.CR );
    669        }
    670
    671        /**
    672         * 名称配列を元に、リクエスト情報のデータを取得します。
    673         * checkNames 属性に設定されているカラムがあれば、値を正規化します。
    674         *
    675         * @og.rev 3.8.0.5 (2005/08/20) リクエスト変数の正規化(checkNames)対応
    676         *
    677         * @param       nameArray       キーとなる名称の配列
    678         *
    679         * @return      そのリクエスト情報の配列
    680         */
    681        protected String[] getRequest( final String[] nameArray ) {
    682                String[] rtn = new String[nameArray.length];
    683
    684                for( int i=0; i<rtn.length; i++ ) {
    685                        rtn[i] = getRequestValue( nameArray[i] );
    686
    687                        // 3.8.0.5 (2005/08/20) checkNames があり、rtn[i] がある場合。
    688                        if( checkNames != null && checkNames.length() > 0 && rtn[i].length() > 0 ) {
    689                                if( ( "," + checkNames + "," ).indexOf( "," + nameArray[i] + "," ) >= 0 ) {
    690                                        DBColumn dbColumn = getDBColumn( nameArray[i] );
    691                                        String val = dbColumn.valueSet( rtn[i] );
    692                                        if( val != null ) { rtn[i] = val; }
    693                                }
    694                        }
    695                }
    696
    697                return rtn;
    698        }
    699
    700        /**
    701         * 子タグ(andタグ)でプレースホルダーを設定した時に利用するメソッドです。
    702         * queryタグ内部のプレースホルダリストに追加します。
    703         *
    704         * @og.rev 5.10.2.1 (2018/08/18) 新規追加
    705         * @param trg 追加分
    706         */
    707        protected void addListPlaceValue(final String trg) {
    708                if(listPlaceValue == null) {
    709                        // listTestの初期化(初期化時にnamesの値を設定する)
    710                        listPlaceValue = new ArrayList<String>();
    711                        // namesをリストに追加
    712                        String[] nameArray = StringUtil.csv2Array( names );
    713                        String[] values = getRequest( nameArray );
    714
    715                        for(int i=0; i<values.length; i++) {
    716                                listPlaceValue.add(values[i]);
    717                        }
    718                }
    719
    720                // カンマで分割
    721                String[] arrayTrg = StringUtil.csv2Array( trg );
    722                for(int i=0; i<arrayTrg.length; i++) {
    723                        // リクエストパラメータの値を変換して、リストに追加
    724                        listPlaceValue.add(getRequestParameter(arrayTrg[i]));
    725                }
    726        }
    727
    728        /**
    729         * 【TAG】(通常は使いません)データの読み始めの初期値を指定します。
    730         *
    731         * @og.tag
    732         * データベース自体の検索は,指定されたSQLの全件を検索しますが,
    733         * DBTableModelのデータとしては、スキップ件数分は登録されません。
    734         * サーバーのメモリ資源と応答時間の確保の為です。
    735         *
    736         * @param       count 読み始めの初期値
    737         */
    738        public void setSkipRowCount( final String count ) {
    739                skipRowCount = nval( getRequestParameter( count ),skipRowCount );
    740        }
    741
    742        /**
    743         * 【TAG】(通常は使いません)データの最大読み込み件数を指定します
    744         *              (初期値:DB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。
    745         *
    746         * @og.tag
    747         * データベース自体の検索は,指定されたSQLの全件を検索しますが,
    748         * DBTableModelのデータとして登録する最大件数をこの値に設定します。
    749         * サーバーのメモリ資源と応答時間の確保の為です。
    750         * 0 をセットすると、無制限(Integer.MAX_VALUE)になります。
    751         * (初期値:ユーザー定数のDB_MAX_ROW_COUNT[={@og.value org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT}])。
    752         *
    753         * @og.rev 5.5.8.5 (2012/11/27) 0を無制限として処理します。
    754         *
    755         * @param       count 最大読み込み件数
    756         * @see         org.opengion.hayabusa.common.SystemData#DB_MAX_ROW_COUNT
    757         */
    758        public void setMaxRowCount( final String count ) {
    759                maxRowCount = nval( getRequestParameter( count ),maxRowCount );
    760                if( maxRowCount == 0 ) { maxRowCount = Integer.MAX_VALUE ; }            // 5.5.8.5 (2012/11/27)
    761        }
    762
    763        /**
    764         * 【TAG】(通常は使いません)結果のDBTableModelを、sessionに登録するときのキーを指定します
    765         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
    766         *
    767         * @og.tag
    768         * 検索結果より、DBTableModelオブジェクトを作成します。これを、下流のviewタグ等に
    769         * 渡す場合に、通常は、session を利用します。その場合の登録キーです。
    770         * query タグを同時に実行して、結果を求める場合、同一メモリに配置される為、
    771         * この tableId 属性を利用して、メモリ空間を分けます。
    772         *              (初期値:HybsSystem#TBL_MDL_KEY[={@og.value org.opengion.hayabusa.common.HybsSystem#TBL_MDL_KEY}])。
    773         *
    774         * @param       id sessionに登録する時の ID
    775         */
    776        public void setTableId( final String id ) {
    777                tableId   = nval( getRequestParameter( id ),tableId );  // 3.8.0.9 (2005/10/17)
    778        }
    779
    780        /**
    781         * 【TAG】Query を発行する為のクラスID(JDBC,JDBCCallable,JDBCErrMsg,JDBCUpdate)を指定します({@og.doc03Link queryType 初期値:JDBC})。
    782         *
    783         * @og.tag
    784         * 検索を実行する手段は、Query インターフェースの実装クラスになります。
    785         * このタグでは、Query.execute( String[] ) メソッドが呼ばれます。
    786         * 例えば、ストアドプロシージャ等を実行する場合に、queryType="JDBCErrMsg"
    787         * を指定することができます。
    788         * 初期値は、"JDBC" です。
    789         * queryType は、システムリソースの Query_**** 宣言の **** を与えます。
    790         * これらは、Query インターフェースを継承したサブクラスである必要があります。
    791         * 標準で、org.opengion.hayabusa.db 以下の Query_**** クラスが、Query_**** 宣言 と
    792         * して、定義されています。
    793         * 属性クラス定義の {@link org.opengion.hayabusa.db.Query Query} を参照願います。
    794         * {@og.doc03Link queryType Query_**** クラス}
    795         *
    796         * @param       id Query を発行する為の実クラス ID
    797         * @see         org.opengion.hayabusa.db.Query  Queryのサブクラス
    798         * @see         org.opengion.hayabusa.db.Query#execute( String[] )
    799         */
    800        public void setQueryType( final String id ) {
    801                queryType = getRequestParameter( id );
    802        }
    803
    804        /**
    805         * 【TAG】(通常は使いません)Queryオブジェクトを作成する時のDB接続IDを指定します。
    806         *
    807         * @og.tag
    808         * Queryオブジェクトを作成する時のDB接続IDを指定します。
    809         * これは、システムリソースで、DEFAULT_DB_URL 等で指定している データベース接続先
    810         * 情報に、XX_DB_URL を定義することで、 dbid="XX" とすると、この 接続先を使用して
    811         * データベースにアクセスできます。
    812         *
    813         * @param       id データベース接続ID
    814         */
    815        public void setDbid( final String id ) {
    816                dbid = nval( getRequestParameter( id ),dbid );
    817        }
    818
    819        /**
    820         * 【TAG】コマンド(NEW,RENEW)をセットします(PlsqlUpdateTag,UpdateTag の場合は、ENTRY)。
    821         *
    822         * @og.tag
    823         * コマンドは,HTMLから(get/post)指定されますので,CMD_xxx で設定される
    824         * フィールド定数値のいづれかを、指定できます。
    825         *
    826         * @param       cmd コマンド(public static final 宣言されている文字列)
    827         * @see         <a href="../../../../constant-values.html#org.opengion.hayabusa.taglib.QueryTag.CMD_NEW">コマンド定数</a>
    828         */
    829        public void setCommand( final String cmd ) {
    830                String cmd2 = getRequestParameter( cmd );
    831                if( cmd2 != null && cmd2.length() >= 0 ) { command = cmd2.toUpperCase(Locale.JAPAN); }
    832        }
    833
    834        /**
    835         * 【TAG】検索結果が０件のとき処理を続行するかどうか[true/false]を指定します(初期値:false[続行する])。
    836         *
    837         * @og.tag
    838         * 初期値は、false(続行する)です。
    839         *
    840         * @param  cmd 検索結果が０件のとき、[true:処理を中止する/false:続行する]
    841         */
    842        public void setStopZero( final String cmd ) {
    843                stopZero = nval( getRequestParameter( cmd ),stopZero );
    844        }
    845
    846        /**
    847         * 【TAG】検索結果を画面上に表示するメッセージリソースIDを指定します
    848         *              (初期値:VIEW_DISPLAY_MSG[={@og.value org.opengion.hayabusa.common.SystemData#VIEW_DISPLAY_MSG}])。
    849         *
    850         * @og.tag
    851         * ここでは、検索結果の件数や登録された件数をまず出力し、
    852         * その次に、ここで指定したメッセージをリソースから取得して表示します。
    853         * 件数を表示させたい場合は、displayMsg = "MSG0033"[　件検索しました] をセットしてください。
    854         * 表示させたくない場合は, displayMsg = "" をセットしてください。
    855         * (初期値:システム定数のVIEW_DISPLAY_MSG[={@og.value org.opengion.hayabusa.common.SystemData#VIEW_DISPLAY_MSG}])。
    856         *
    857         * @param       id ディスプレイに表示させるメッセージ ID
    858         * @see         org.opengion.hayabusa.common.SystemData#VIEW_DISPLAY_MSG
    859         */
    860        public void setDisplayMsg( final String id ) {
    861                String ids = getRequestParameter( id );
    862                if( ids != null ) { displayMsg = ids; }
    863        }
    864
    865        /**
    866         * 【TAG】検索データが最大検索数をオーバーした場合に表示するメッセージリソースIDを指定します
    867         *              (初期値:MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました])。
    868         *
    869         * @og.tag
    870         * 検索結果が、maxRowCount で設定された値より多い場合、何らかのデータは検索されず
    871         * 切り捨てられたことになります。
    872         * ここでは、displayMsg を表示した後、必要に応じて、このメッセージを表示します。
    873         * 表示させたくない場合は, overflowMsg = "" をセットしてください。
    874         * 初期値は、MSG0007[検索結果が、制限行数を超えましたので、残りはカットされました]です。
    875         *
    876         * @param       id ディスプレイに表示させるメッセージ ID
    877         */
    878        public void setOverflowMsg( final String id ) {
    879                String ids = getRequestParameter( id );
    880                if( ids != null ) { overflowMsg = ids; }
    881        }
    882
    883        /**
    884         * 【TAG】検索結果がゼロ件の場合に表示するメッセージリソースIDを指定します(初期値:MSG0077[対象データはありませんでした])。
    885         *
    886         * @og.tag
    887         * ここでは、検索結果がゼロ件の場合のみ、特別なメッセージを表示させます。
    888         * 従来は、displayMsg と兼用で、『0　件検索しました』という表示でしたが、
    889         * displayMsg の初期表示は、OFF になりましたので、ゼロ件の場合のみ別に表示させます。
    890         * 表示させたくない場合は, notfoundMsg = "" をセットしてください。
    891         * 初期値は、MSG0077[対象データはありませんでした]です。
    892         *
    893         * @param       id ディスプレイに表示させるメッセージ ID
    894         */
    895        public void setNotfoundMsg( final String id ) {
    896                String ids = getRequestParameter( id );
    897                if( ids != null ) { notfoundMsg = ids; }
    898        }
    899
    900        /**
    901         * 【TAG】PL/SQLを利用する場合の引数にセットすべき データの名称をCSV形式で複数指定します。
    902         *
    903         * @og.tag
    904         * 複数ある場合は、カンマ区切り文字で渡します。
    905         * names 属性は、queryType に応じて設定可否が異なりますので、ご注意ください。
    906         * names なし：JDBC,JDBCUpdate
    907         * names あり：JDBCCallable,JDBCErrMsg,JDBCUpdate
    908         * (JDBCUpdateは、names 属性のあり/なし両方に対応しています。)
    909         *
    910         * @og.rev 3.0.1.3 (2003/03/11) names 属性に null で渡す場合のバグを修正
    911         *
    912         * @param       nm 引数の名称(複数ある場合は、カンマ区切り文字)
    913         */
    914        public void setNames( final String nm ) {
    915                names = nval( getRequestParameter( nm ),names );
    916        }
    917
    918        /**
    919         * 【TAG】検索結果のメッセージを表示する/しない[true/false]を指定します(初期値:true)。
    920         *
    921         * @og.tag
    922         * 初期値は、表示する：true です。
    923         *
    924         * @param       flag  [true:表示する/それ以外:含めない]
    925         */
    926        public void setOutMessage( final String flag ) {
    927                outMessage = nval( getRequestParameter( flag ),outMessage );
    928        }
    929
    930        /**
    931         * 【TAG】引数の SQL 文を EXPLAIN PLAN を[true:行う/それ以外:行わない]を指定します(初期値:false)。
    932         *
    933         * @og.tag
    934         *
    935         * ここでは、以下の処理を行います。
    936         * １．引数の SQL 文を画面に表示します。
    937         * ２．引数の SQL 文を EXPLAIN PLAN した結果を、画面に表示します。
    938         * なお、以前は、セッションのトレースを行っていましたが、その機能は、廃止いたします。
    939         * 初期値は、行わない：false です。
    940         *
    941         * @param       flag トレース [true:行う/それ以外:行わない]
    942         */
    943        public void setTrace( final String flag ) {
    944                trace = nval( getRequestParameter( flag ),trace );
    945        }
    946
    947        /**
    948         * 【TAG】リクエスト変数の正規化を行うカラムをCSV形式で複数指定します。
    949         *
    950         * @og.tag
    951         * PL/SQLを利用する場合の引数にセットすべき データを、リクエスト変数の
    952         * 値そのままではなく、カラムオブジェクトの valueSet メソッド経由で正規化
    953         * した値を使用するようにします。
    954         *
    955         * @og.rev 3.8.0.5 (2005/08/20) 新規追加
    956         *
    957         * @param       nm リクエスト変数の正規化を行うカラム
    958         */
    959        public void setCheckNames( final String nm ) {
    960                checkNames = nval( getRequestParameter( nm ),checkNames );
    961        }
    962
    963        /**
    964         * 【TAG】DB検索時の モディファイタイプを指定します[A:追加/C:更新/D:削除]。
    965         *
    966         * @og.tag
    967         * DB検索時に、そのデータをA(追加)、C(更新)、D(削除)のモディファイタイプを
    968         * つけた状態にします。
    969         * その状態で、そのまま、update する事が可能になります。
    970         *
    971         * @og.rev 3.8.5.1 (2006/05/08) 新規追加
    972         *
    973         * @param   type DB検索時の モディファイタイプ [A:追加/C:更新/D:削除]
    974         */
    975        public void setModifyType( final String type ) {
    976                modifyType = nval( getRequestParameter( type ),modifyType );
    977        }
    978
    979        /**
    980         * 【TAG】リクエスト情報の クォーティション(') 存在チェックを実施するかどうか[true/false]を設定します
    981         *              (初期値:USE_SQL_INJECTION_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_SQL_INJECTION_CHECK}])。
    982         *
    983         * @og.tag
    984         * ＳＱＬインジェクション対策の一つとして、暫定的ではありますが、SQLのパラメータに
    985         * 渡す文字列にクォーティション(') を許さない設定にすれば、ある程度は防止できます。
    986         * 数字タイプの引数には、 or 5=5 などのクォーティションを使用しないコードを埋めても、
    987         * 数字チェックで検出可能です。文字タイプの場合は、必ず (')をはずして、
    988         * ' or 'A' like 'A のような形式になる為、(')チェックだけでも有効です。
    989         * (') が含まれていたエラーにする(true)／かノーチェックか(false)を指定します。
    990         * 初期値は、SystemData#USE_SQL_INJECTION_CHECK です。
    991         *
    992         * @og.rev 4.0.0.0 (2005/08/31) 新規追加
    993         *
    994         * @param   flag クォーティションチェック [true:する/それ以外:しない]
    995         */
    996        public void setQuotCheck( final String flag ) {
    997                quotCheck = nval( getRequestParameter( flag ),quotCheck );
    998        }
    999
    1000        /**
    1001         * 【TAG】リクエスト情報の HTMLTag開始/終了文字(&gt;&lt;) 存在チェックを実施するかどうか[true/false]を設定します
    1002         *              (初期値:USE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])。
    1003         *
    1004         * @og.tag
    1005         * クロスサイトスクリプティング(XSS)対策の一環としてless/greater than signについてのチェックを行います。
    1006         * (&gt;&lt;) が含まれていたエラーにする(true)／かノーチェックか(false)を指定します。
    1007         * (初期値:システム定数のUSE_XSS_CHECK[={@og.value org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK}])
    1008         *
    1009         * @og.rev 5.0.0.2 (2009/09/15) 新規追加
    1010         *
    1011         * @param       flag    XSSチェック [true:する/false:しない]
    1012         * @see         org.opengion.hayabusa.common.SystemData#USE_XSS_CHECK
    1013         */
    1014        public void setXssCheck( final String flag ) {
    1015                xssCheck = nval( getRequestParameter( flag ),xssCheck );
    1016        }
    1017
    1018        /**
    1019         * 【TAG】PLSQL/SQL処理エラーの時に処理を中止するかどうか[true/false]を設定します(初期値:true)。
    1020         *
    1021         * @og.tag
    1022         * false(中止しない)に設定する場合、後続処理では、{&#064;DB.ERR_CODE}の値により、
    1023         * PLSQL/SQLの異常/正常終了によって分岐処理は可能となります。
    1024         * 初期値は、true(中止する)です。
    1025         *
    1026         * @og.rev 4.3.3.0 (2008/09/22) 新規追加
    1027         *
    1028         * @param   flag  [true:中止する/false:中止しない]
    1029         */
    1030        public void setStopError( final String flag ) {
    1031                stopError = nval( getRequestParameter( flag ),stopError );
    1032        }
    1033
    1034        /**
    1035         * 【TAG】PLSQL/SQL処理エラーの時にエラーを画面表示するか[true/false]を設定します(初期値:true)。
    1036         *
    1037         * @og.tag
    1038         * false(表示しない)に設定する場合、後続処理では、{&#064;DB.ERR_MSG}の値により、
    1039         * 本来表示されるはずだったメッセージを取得可能です。
    1040         * stopErrorと併用して、JSON形式でエラーを返す場合等に利用します。
    1041         * 初期値は、true(表示する)です。
    1042         * ※false指定の場合は件数や、overFlowメッセージ等も表示されなくなります。
    1043         *
    1044         * @og.rev 5.9.26.1 (2017/11/10) 新規追加
    1045         *
    1046         * @param   flag  [true:表示する/false:表示しない]
    1047         */
    1048        public void setDispError( final String flag ) {
    1049                dispError = nval( getRequestParameter( flag ),dispError );
    1050        }
    1051
    1052
    1053        /**
    1054         * 引数の SQL 文を EXPLAIN PLAN します。
    1055         *
    1056         * ここでは、以下の処理を行います。
    1057         * １．引数の SQL 文を画面に表示します。
    1058         * ２．引数の SQL 文を EXPLAIN PLAN した結果を、画面に表示します。
    1059         * なお、この処理は、ORACLE 専用処理です。
    1060         *
    1061         * @og.rev 3.8.5.3 (2006/08/07) 新規追加
    1062         * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得の為,ApplicationInfoオブジェクトを設定
    1063         * @og.rev 5.1.9.0 (2010/08/01) Transaction 対応します。
    1064         * @og.rev 5.5.3.4 (2012/06/19) getUserInfo は、キー部分だけで処理します。
    1065         *
    1066         * @param   sql         EXPLAIN PLANするSQL 文
    1067         * @param   tran        Transactionオブジェクト
    1068         *
    1069         * @return トレース結果の文字列
    1070         */
    1071//      private String traceQuery( final String sql ) {
    1072        private String traceQuery( final String sql , final Transaction tran ) {
    1073//              ApplicationInfo appInfo = getApplicationInfo();
    1074
    1075//              String userId = getUserInfo( "USER.ID" ) ;
    1076                String userId = getUserInfo( "ID" ) ;                   // 5.5.3.4 (2012/06/19) getUserInfo は、キー部分だけで処理します。
    1077
    1078                String[] arg1 = new String[] { userId };
    1079//              DBUtil.dbExecute( "DELETE FROM PLAN_TABLE WHERE STATEMENT_ID = ?",arg1,appInfo,dbid );
    1080                DBUtil.dbExecute( "DELETE FROM PLAN_TABLE WHERE STATEMENT_ID = ?",arg1,tran,dbid );             // 5.1.9.0 (2010/08/01)
    1081
    1082                String explan1 = "EXPLAIN PLAN SET STATEMENT_ID = '" + userId + "' FOR " + sql ;
    1083//              DBUtil.dbExecute( explan1,null,appInfo,dbid );
    1084                DBUtil.dbExecute( explan1,null,tran,dbid );             // 5.1.9.0 (2010/08/01)
    1085
    1086                String[] arg2 = new String[] { userId,userId,userId };
    1087//              String explan2 = "SELECT LEVEL,LPAD(' ',LEVEL,' ') || RTRIM( OPERATION ) || ' ' ||"
    1088//                                              + " RTRIM( OPTIONS )   || ' ' || RTRIM( OBJECT_NAME )"
    1089//                                              + " FROM PLAN_TABLE"
    1090//                                              + " WHERE STATEMENT_ID = ?"
    1091//                                              + " CONNECT BY PRIOR ID = PARENT_ID"
    1092//                                              + "         AND STATEMENT_ID = ?"
    1093//                                              + " START WITH ID = 0"
    1094//                                              + "         AND STATEMENT_ID = ?" ;
    1095                String explan2 = "select LEVEL as LVL"
    1096                                                        + ",lpad(' ',LEVEL,' ') || rtrim( OPERATION ) || ' ' || rtrim( OPTIONS ) || ' ' || rtrim( OBJECT_NAME ) as EXECUTION_PLAN"
    1097                                                        + ",OBJECT_NAME                 as OBJ_NAME"
    1098                                                        + ",DECODE(INSTR(OBJECT_TYPE,' '),0,OBJECT_TYPE,SUBSTR(OBJECT_TYPE,1,INSTR(OBJECT_TYPE,' ')-1)) as OBJ_TYPE"
    1099                                                        + ",OPTIMIZER                   as OPT"
    1100                                                        + ",COST                                as CST"
    1101                                                        + ",CARDINALITY                 as CARD"
    1102                                                        + ",BYTES                               as BYTE"
    1103                                                        + ",ACCESS_PREDICATES   as ACCS"
    1104                                                        + ",FILTER_PREDICATES   as FILTER"
    1105                                                + " from PLAN_TABLE"
    1106                                                + " where STATEMENT_ID = ?"
    1107                                                + " start with ID = 0"
    1108                                                + "       and STATEMENT_ID = ?"
    1109                                                + " connect by prior ID = PARENT_ID"
    1110                                                + "       and STATEMENT_ID = ?" ;
    1111//              String[][] plan = DBUtil.dbExecute( explan2,arg2,appInfo,dbid );
    1112//              String[][] plan = DBUtil.dbExecute( explan2,arg2,tran,dbid );                   // 5.1.9.0 (2010/08/01)
    1113
    1114//              StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
    1115//              buf.append( "<pre>" ).append( sql ).append( "</pre>" ).append( HybsSystem.BR );
    1116//              buf.append( "<table>" );
    1117//              buf.append( "<tr  class=\"row_h\"><th>LEVEL</th><th>EXECUTION_PLAN</th></tr>" );
    1118//              for( int i=0; i<plan.length; i++ ) {
    1119//                      buf.append( "<tr class=\"row_" ).append( i%2 ).append( "\">" );
    1120//                      buf.append( "<td>" ).append( plan[i][0] ).append( "</td>" );
    1121//                      buf.append( "<td><pre>" ).append( plan[i][1] ).append( "</td></tr>" );
    1122//              }
    1123//              buf.append( "</table>" ).append( HybsSystem.BR );
    1124
    1125                String[][] plan = DBUtil.dbExecute( explan2,arg2,tran,dbid,true );                      // 5.5.3.4 (2012/06/19) ヘッダー情報も同時に取得する。
    1126
    1127                StringBuilder buf = new StringBuilder( HybsSystem.BUFFER_MIDDLE );
    1128                buf.append( "<pre>" ).append( sql ).append( "</pre>" ).append( HybsSystem.BR );
    1129                buf.append( "<table>" );
    1130                // 1行目のヘッダーの出力
    1131                int colsize = plan[0].length;
    1132                buf.append( "<tr class=\"row_h\">" );
    1133                for( int j=0; j<colsize; j++ ) {
    1134                        buf.append( "<th>" ).append( plan[0][j] ).append( "</th>" );
    1135                }
    1136                buf.append( "</tr>" );
    1137
    1138                for( int i=1; i<plan.length; i++ ) {
    1139                        buf.append( "<tr class=\"row_" ).append( i%2 ).append( "\">" );
    1140                        for( int j=0; j<colsize; j++ ) {
    1141                                if( j==1 ) {
    1142                                        buf.append( "<td><pre>" ).append( plan[i][1] ).append( "</pre></td>" );
    1143                                }
    1144                                else {
    1145                                        buf.append( "<td>" ).append( plan[i][j] ).append( "</td>" );
    1146                                }
    1147                        }
    1148                        buf.append( "</tr>" );
    1149                }
    1150                buf.append( "</table>" ).append( HybsSystem.BR );
    1151                return buf.toString();
    1152        }
    1153
    1154        /**
    1155         * 【TAG】(通常使いません)タグで処理される処理がメインとなるトランザクション処理かどうかを指定します(初期値:true)。
    1156         *
    1157         * @og.tag
    1158         * この値は、ファイルダウンロード処理に影響します。この値がtrueに指定された時にcommitされたDBTableModelが
    1159         * ファイルダウンロードの対象の表になります。
    1160         *
    1161         * このパラメーターは、通常、各タグにより実装され、ユーザーが指定する必要はありません。
    1162         * 但し、1つのJSP内でDBTableModelが複数生成される場合に、前に処理したDBTableModelについてファイルダウンロードをさせたい
    1163         * 場合は、後ろでDBTableModelを生成するタグで、明示的にこの値をfalseに指定することで、ファイルダウンロード処理の対象から
    1164         * 除外することができます。
    1165         *
    1166         * @og.rev 5.1.6.0 (2010/05/01) 新規作成
    1167         *
    1168         * @param  flag メイントランザクションかどうか
    1169         */
    1170        public void setMainTrans( final String flag ) {
    1171                isMainTrans = nval( getRequestParameter( flag ),isMainTrans );
    1172        }
    1173
    1174        /**
    1175         * 【TAG】 処理時間(queryTime)などの情報出力[true:有効/false:無効]を指定します(初期値:true)。
    1176         *
    1177         * @og.tag
    1178         * Query で、検索する場合に、処理時間(queryTime)などの情報を出力していますが、
    1179         * ViewForm で、CustomData などの 非HTML表示ビューを使用する場合、データとして、
    1180         * 紛れ込んでしまうため、出力を抑制する必要があります。
    1181         * true(有効)にすると、これらのHTMLが出力されます。false にすると、出力されません。
    1182         * 初期値は、true(有効) です。
    1183         *
    1184         * @og.rev 5.3.5.0 (2011/05/01) 新規追加
    1185         *
    1186         * @param  useTag  情報出力の有効/無効を指定 [true:有効/false:無効]
    1187         */
    1188        public void setUseBeforeHtmlTag( final String useTag ) {
    1189                useBeforeHtmlTag = nval( getRequestParameter( useTag ),useBeforeHtmlTag );
    1190        }
    1191
    1192        /**
    1193         * シリアライズ用のカスタムシリアライズ書き込みメソッド
    1194         *
    1195         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
    1196         * @serialData 一部のオブジェクトは、シリアライズされません。
    1197         *
    1198         * @param       strm    ObjectOutputStreamオブジェクト
    1199         * @throws IOException  入出力エラーが発生した場合
    1200         */
    1201        private void writeObject( final ObjectOutputStream strm ) throws IOException {
    1202                strm.defaultWriteObject();
    1203        }
    1204
    1205        /**
    1206         * シリアライズ用のカスタムシリアライズ読み込みメソッド
    1207         *
    1208         * ここでは、transient 宣言された内部変数の内、初期化が必要なフィールドのみ設定します。
    1209         *
    1210         * @og.rev 4.0.0.0 (2006/09/31) 新規追加
    1211         * @serialData 一部のオブジェクトは、シリアライズされません。
    1212         *
    1213         * @param       strm    ObjectInputStreamオブジェクト
    1214         * @see #release2()
    1215         * @throws IOException  シリアライズに関する入出力エラーが発生した場合
    1216         * @throws ClassNotFoundException       クラスを見つけることができなかった場合
    1217         */
    1218        private void readObject( final ObjectInputStream strm ) throws IOException , ClassNotFoundException {
    1219                strm.defaultReadObject();
    1220        }
    1221
    1222        /**
    1223         * このオブジェクトの文字列表現を返します。
    1224         * 基本的にデバッグ目的に使用します。
    1225         *
    1226         * @return このクラスの文字列表現
    1227         */
    1228        @Override
    1229        public String toString() {
    1230                return sql ;
    1231
    1232        //      return org.opengion.fukurou.util.ToString.title( this.getClass().getName() )
    1233        //                      .println( "VERSION"                     ,VERSION                )
    1234        //                      .println( "tableId"                     ,tableId                )
    1235        //                      .println( "queryType"           ,queryType              )
    1236        //                      .println( "dbid"                        ,dbid                   )
    1237        //                      .println( "command"                     ,command                )
    1238        //                      .println( "skipRowCount"        ,skipRowCount   )
    1239        //                      .println( "maxRowCount"         ,maxRowCount    )
    1240        //                      .println( "sql"                         ,sql                    )
    1241        //                      .println( "displayMsg"          ,displayMsg             )
    1242        //                      .println( "overflowMsg"         ,overflowMsg    )
    1243        //                      .println( "executeCount"        ,executeCount   )
    1244        //                      .println( "names"                       ,names                  )
    1245        //                      .println( "outMessage"          ,outMessage             )
    1246        //                      .println( "trace"                       ,trace                  )
    1247        //                      .println( "errCode"                     ,errCode                )
    1248        //                      .println( "stopZero"            ,stopZero               )
    1249        //                      .println( "quotCheck"           ,quotCheck              )
    1250        //                      .println( "dyStart"                     ,dyStart                )
    1251        //                      .println( "checkNames"          ,checkNames             )
    1252        //                      .println( "Other..."            ,getAttributes().getAttribute() )
    1253        //                      .fixForm().toString() ;
    1254        }
    1255}