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