001 /* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016 package org.opengion.plugin.table; 017 018 import java.io.File; 019 import java.io.PrintWriter; 020 import java.util.Map; 021 022 import org.opengion.fukurou.db.DBUtil; 023 import org.opengion.fukurou.db.Transaction; // 5.5.2.6 (2012/05/25) 024 import org.opengion.fukurou.util.ErrorMessage; 025 import org.opengion.fukurou.util.FileUtil; 026 import org.opengion.fukurou.util.FixLengthData; 027 import org.opengion.fukurou.util.StringUtil; 028 import org.opengion.hayabusa.common.HybsSystem; 029 import org.opengion.hayabusa.common.HybsSystemException; 030 import org.opengion.hayabusa.db.AbstractTableFilter; 031 import org.opengion.hayabusa.db.DBTableModel; 032 033 /** 034 * TableFilter_INDEX は、TableUpda インターフェースを継承した、DBTableModel 処?の 035 * 実?ラスです? 036 * 037 * ここでは、イン?クス?の検索結果より、GF07 のイン?クスカラ?義??ブルから 038 * ?な??を取得し、イン?クス作?スクリプトを作?します? 039 * 出力ファイルは、テーブル名?C.sql" と?命名規則で作?します? 040 * 検索では?SYSTEM_ID,TBLSYU,TABLE_NAME,TABLE_LABEL,INDEX_NAME,NAME_JA,INDTYPE,TABLESPACE_NAME,INITIAL_EXTENT,NEXT_EXTENT) 041 * の?を取得する?があります? 042 * 043 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか?BODY 部にCSS形式で記述します? 044 * 【パラメータ? 045 * { 046 * DIR : {@BASE_DIR}/sql/02_INDEX ; 出力ファイルの基準フォル???) 047 * XML : false ; XML出力を行うかど?[true/false]を指定しま?初期値:false)? 048 * DROP: false ; INDEX構文の前に、DROP構文を?力するかど?[true/false]を指定しま?初期値:false)? 049 * } 050 * 051 * @og.formSample 052 * ●形式? 053 * select SYSTEM_ID,TBLSYU,TABLE_NAME,TABLE_LABEL,INDEX_NAME,NAME_JA,INDTYPE,TABLESPACE_NAME,INITIAL_EXTENT,NEXT_EXTENT from GF07 054 * ?<og:tableFilter classId="INDEX" keys="DIR,XML" vals="{@BASE_DIR}/sql/02_INDEX,false" /> 055 * 056 * ② <og:tableFilter classId="INDEX" > 057 * { 058 * DIR : {@BASE_DIR}/sql/02_INDEX ; 059 * XML : false ; 060 * DROP: false ; 061 * } 062 * </og:tableFilter> 063 * 064 * @og.rev 5.6.6.0 (2013/07/05) keys の整合?チェ?を追? 065 * 066 * @version 0.9.0 2000/10/17 067 * @author Kazuhiko Hasegawa 068 * @since JDK1.1, 069 */ 070 public class TableFilter_INDEX extends AbstractTableFilter { 071 //* こ?プログラ??VERSION??を設定します? {@value} */ 072 private static final String VERSION = "5.6.9.2 (2013/10/18)" ; 073 074 /** 075 * keys の整合?チェ?を行うための初期設定を行います? 076 * 077 * @og.rev 5.6.6.1 (2013/07/12) keys の整合?チェ?対? 078 * 079 * @param keysMap keys の整合?チェ?を行うための Map 080 */ 081 @Override 082 protected void init( final Map<String,String> keysMap ) { 083 keysMap.put( "DIR" , "出力ファイルの基準フォル???)" ); 084 keysMap.put( "XML" , "XML出力を行うかど?[true/false]を指?初期値:false)" ); 085 keysMap.put( "DROP" , "INDEX構文の前に、DROP構文を?力するかど?(初期値:false)" ); 086 } 087 088 private static final String[] DBKEY = {"SYSTEM_ID","TBLSYU","TABLE_NAME","TABLE_LABEL","INDEX_NAME","NAME_JA","INDTYPE", 089 "TABLESPACE_NAME","INITIAL_EXTENT","NEXT_EXTENT" }; 090 091 // 5.1.1.0 (2009/12/01) ??タのアクセス用の配?番号のID?private ?protected にします? 092 /** ??タのアクセス用の配?番号 {@value} */ 093 protected static final int SYSTEM_ID = 0; 094 /** ??タのアクセス用の配?番号 {@value} */ 095 protected static final int TBLSYU = 1; 096 /** ??タのアクセス用の配?番号 {@value} */ 097 protected static final int TABLE_NAME = 2; 098 /** ??タのアクセス用の配?番号 {@value} */ 099 protected static final int TABLE_LABEL = 3; // GF02 の NAME_JA より JOIN 100 /** ??タのアクセス用の配?番号 {@value} */ 101 protected static final int INDEX_NAME = 4; 102 /** ??タのアクセス用の配?番号 {@value} */ 103 protected static final int INDTYPE = 6; 104 /** ??タのアクセス用の配?番号 {@value} */ 105 protected static final int TABLESPACE_NAME = 7; 106 /** ??タのアクセス用の配?番号 {@value} */ 107 protected static final int INITIAL_EXTENT = 8; 108 /** ??タのアクセス用の配?番号 {@value} */ 109 protected static final int NEXT_EXTENT = 9; 110 111 // 5.1.1.2 (2009/12/10) 112 // private static final String GF07_SEL = "select CLM" 113 // + " from GF07" 114 // + " where SYSTEM_ID=? and TBLSYU=? and TABLE_NAME=? and INDEX_NAME=?" 115 // + " and FGJ='1'" 116 // + " order by SEQNO" ; 117 private static final String GF07_SEL = "select A.CLM, B.USE_LENGTH" 118 + " from GF07 A left outer join GF05 B" 119 + " on A.SYSTEM_ID = B.SYSTEM_ID" 120 + " and A.TBLSYU = B.TBLSYU" 121 + " and A.TABLE_NAME = B.TABLE_NAME" 122 + " and A.CLM = B.CLM" 123 + " and B.FGJ = '1'" 124 + " where A.SYSTEM_ID=? and A.TBLSYU=? and A.TABLE_NAME=? and A.INDEX_NAME=?" 125 + " and A.FGJ='1'" 126 + " order by A.SEQNO" ; 127 128 // private static final String ENCODE = "Windows-31J" ; 129 private static final String ENCODE = "UTF-8" ; // 4.3.6.6 (2009/05/15) 130 // private static final String CR = HybsSystem.CR ; // 5.1.1.0 (2009/12/01) CR 定義をAbstractTableFilterで行う? 131 132 private static final String CMNT = "************************************************************************" ; 133 134 private static final int X = FixLengthData.X ; 135 private static final int S = FixLengthData.S ; 136 private static final int K = FixLengthData.K ; 137 138 /** ?定数 */ 139 protected static final String XML_START_TAG = "<?xml version='1.0' encoding='UTF-8'?>" + CR + "<ROWSET tableName='xxx'>"; 140 protected static final String XML_END_TAG = "</ROWSET>"; 141 protected static final String EXEC_START_TAG= "<EXEC_SQL>"; 142 protected static final String EXEC_END_TAG = "</EXEC_SQL>"; 143 144 /** XML形式かど? */ 145 protected boolean isXml = false; // 4.3.7.0 (2009/06/01) 146 147 /** 148 * DBTableModel処?実行します? 149 * 150 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設? 151 * @og.rev 4.0.0.0 (2007/11/28) メソ?の戻り?をチェ?します? 152 * @og.rev 4.3.7.0 (2009/06/01) XML出力機?追? 153 * @og.rev 5.1.1.0 (2009/12/01) XML_START_TAG に、tableName をセ?します? 154 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対? 155 * @og.rev 5.5.2.6 (2012/05/25) protected変数を?private化したため?getterメソ?で取得するよ?変更 156 * @og.rev 5.6.9.2 (2013/10/18) INDEXを作?する前に、削除構文を?れるかど?を指定? 157 * 158 * @return 実行結果の??ブルモ? 159 */ 160 public DBTableModel execute() { 161 DBTableModel table = getDBTableModel(); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソ?追? 162 163 isXml = StringUtil.nval( getValue( "XML" ), false ); 164 165 // 5.6.9.2 (2013/10/18) DROP構文を?力するかど? 166 boolean isDrop = StringUtil.nval( getValue( "DROP" ), false ); 167 168 int[] clmNo = getTableColumnNo( DBKEY ); 169 int rowCnt = table.getRowCount(); 170 171 File dir = new File( getValue( "DIR" ) ); 172 if( ! dir.exists() && ! dir.mkdirs() ) { 173 String errMsg = "??フォル?作?できませんでした?" + dir + "]" ; 174 // 4.3.4.4 (2009/01/01) 175 throw new HybsSystemException( errMsg ); 176 } 177 178 String[] data = null; 179 String bkTableName = null; 180 PrintWriter writer = null; 181 Transaction tran = getTransaction(); // 5.5.2.6 (2012/05/25) 182 for( int row=0; row<rowCnt; row++ ) { 183 String tableName = null; 184 // String tableLbl = null; 185 String indexName = null; 186 try { 187 data = table.getValues( row ); 188 String systemId = data[clmNo[SYSTEM_ID]]; 189 String tblsyu = data[clmNo[TBLSYU]]; 190 tableName = data[clmNo[TABLE_NAME]]; 191 // tableLbl = data[clmNo[TABLE_LABEL]]; 192 indexName = data[clmNo[INDEX_NAME]]; 193 194 // ??ブルがキーブレイクすると、セーブファイルを?り替える? 195 if( ! tableName.equals( bkTableName ) ) { 196 if( writer != null ) { 197 if( isXml ) { writer.println( XML_END_TAG ); } 198 writer.close(); 199 } 200 bkTableName = tableName; 201 writer = FileUtil.getPrintWriter( new File( dir,tableName + ( isXml ? "C.xml" : "C.sql" ) ),ENCODE ); 202 if( isXml ) { writer.println( XML_START_TAG.replace( "xxx",tableName ) ); } // 5.1.1.0 (2009/12/01) tableName をセ? 203 writer.print( makeHeadLine( clmNo,data ) ); 204 } 205 206 String[] vals = new String[] { systemId,tblsyu,tableName,indexName }; 207 // String[][] gf07 = DBUtil.dbExecute( GF07_SEL,vals,appInfo ); 208 String[][] gf07 = DBUtil.dbExecute( GF07_SEL,vals,tran ); // 5.1.9.0 (2010/08/01) Transaction 対? 209 if( gf07.length == 0 ) { 210 System.out.println( "TABLE=[" + tableName + "],INDEX=[" + indexName + "] is Not Found!" ); 211 continue; 212 } 213 // ??ブルに対するカラ?? 214 StringBuilder buf = new StringBuilder() ; 215 for( int j=0; j<gf07.length; j++ ) { 216 // 5.1.1.2 (2009/12/10) 217 // buf.append( gf07[j][0] ).append( "," ); 218 buf.append( makeIndexClmStr( gf07[j][0], gf07[j][1] ) ).append( "," ); 219 } 220 buf.deleteCharAt( buf.length()-1 ); // ?? "," を取り除く?? 221 222 // 5.6.9.2 (2013/10/18) DROP構文を?力する? 223 if( isDrop ) { 224 writer.print( makeDropLine( clmNo,data ) ); 225 } 226 227 String clms = buf.toString(); 228 writer.print( makeLineList( clmNo,data,clms ) ); 229 writer.println( makeEndLine( clmNo,data ) ); 230 } 231 catch( RuntimeException ex ) { 232 ErrorMessage errMessage = makeErrorMessage( "TableFilter_INDEX Error",ErrorMessage.NG ); 233 errMessage.addMessage( row+1,ErrorMessage.NG,"INDEX",ex.getMessage() ); 234 errMessage.addMessage( row+1,ErrorMessage.NG,"INDEX",StringUtil.array2csv( data ) ); 235 errMessage.addMessage( row+1,ErrorMessage.NG,"INDEX","TABLE=[" + tableName + "],INDEX=[" + indexName + "]" ); 236 // BAT から呼び出す?合があるため、標準エラー出力にも情報を?しておきます? 237 System.out.println( errMessage ); 238 } 239 } 240 if( isXml ) { writer.println( XML_END_TAG ); } 241 if( writer != null ) { writer.close(); } 242 243 return table; 244 } 245 246 /** 247 * ヘッ??部??処?実行します? 248 * 249 * @og.rev 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用 250 * 251 * @param clmNo カラ?号配? 252 * @param data ?行?の??タ配? 253 * 254 * @return ヘッ??部???? 255 */ 256 protected String makeHeadLine( final int[] clmNo,final String[] data ) { 257 // String LINE1 = data[clmNo[TABLE_NAME]] ; 258 String tableName = data[clmNo[TABLE_NAME]]; 259 String LINE1 = tableName + " ( " + data[clmNo[TABLE_LABEL]] + " )" ; 260 String LINE2 = "Created : " + HybsSystem.getDate() ; 261 262 // 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用 263 // FixLengthData fixData = new FixLengthData(3); 264 265 int[] addLen = new int[] { 0,0,0 }; // ?ータ間?スペ?ス 266 int[] type = new int[] { X,K,X }; // ?ータの種別 X:半?S:空白前埋?K:全角混在 267 // fixData.setAddLength( addLen ); 268 // fixData.setType( type ); 269 FixLengthData fixData = new FixLengthData( addLen,type ); 270 271 String[][] outData = new String[][] { 272 { "/**", CMNT , "**/" }, 273 { "/* ", LINE1, " */" }, 274 { "/* ", LINE2, " */" }, 275 { "/**", CMNT , "**/" }, 276 }; 277 278 fixData.addAllListData( outData ); 279 280 return fixData.getAllFixData(); 281 282 // for( int i=0; i<outData.length; i++ ) { 283 // fixData.addListData( outData[i] ); 284 // } 285 286 // StringBuilder buf = new StringBuilder(); 287 // for( int i=0; i<outData.length; i++ ) { 288 // buf.append( fixData.getFixData( i ) ).append( CR ); 289 // } 290 291 // return buf.toString(); 292 } 293 294 /** 295 * イン?クス作?の処?実行します? 296 * 297 * @og.rev 5.3.8.0 (2011/08/01) プライマリキー対? 298 * @og.rev 5.6.9.2 (2013/10/18) INDTYPE で、その他ではなく?2:通常 で判断する? 299 * 300 * @param clmNo カラ?号配? 301 * @param data ?行?の??タ配? 302 * @param clms カラ?(CSV形? 303 * 304 * @return 作?された1行?の?? 305 */ 306 protected String makeLineList( final int[] clmNo,final String[] data,final String clms ) { 307 String tableName = data[clmNo[TABLE_NAME]]; 308 String indexName = data[clmNo[INDEX_NAME]]; 309 String idxtype = data[clmNo[INDTYPE]]; 310 311 StringBuilder buf = new StringBuilder(); 312 313 buf.append( CR ); // 先?に、改行を入れておきます? 314 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } 315 316 // 5.3.8.0 (2011/08/01) プライマリキー対? 317 if( "0".equals( idxtype ) ) { // 0:プライマリキー 318 buf.append( "ALTER TABLE " ).append( tableName ).append( " ADD CONSTRAINT " ); 319 buf.append( indexName ).append( " PRIMARY KEY ( " ).append( clms ); 320 buf.append( " )" ); 321 } 322 else if( "1".equals( idxtype ) ) { // 1:ユニ?クキー 323 buf.append( "ALTER TABLE " ).append( tableName ).append( " ADD CONSTRAINT " ); 324 buf.append( indexName ).append( " UNIQUE( " ).append( clms ); 325 buf.append( " )" ); 326 } 327 // 5.6.9.2 (2013/10/18) INDTYPE で、その他ではなく?2:通常 で判断する? 328 else if( "2".equals( idxtype ) ) { // 2:通常 329 buf.append( "CREATE INDEX " ).append( indexName ).append( " ON " ); 330 buf.append( tableName ).append( "( " ).append( clms ); 331 buf.append( " )" ); 332 } 333 else { 334 String errMsg = "INDTYPE が?0,1,2 以外?値が使われて?す?INDTYPE=[" + idxtype + "]" 335 + " TABLE_NAME=[" + tableName + "] INDEX_NAME=[" + indexName + "]" ; 336 System.out.println( errMsg ); 337 } 338 339 return buf.toString(); 340 } 341 342 /** 343 * 定義の??部??処?実行します? 344 * 345 * @og.rev 5.3.9.0 (2011/09/01) プライマリキー対応? 346 * 347 * @param clmNo カラ?号配? 348 * @param data ?行?の??タ配? 349 * 350 * @return 定義の??部? 351 */ 352 protected String makeEndLine( final int[] clmNo,final String[] data ) { 353 StringBuilder buf = new StringBuilder(); 354 buf.append( CR ); // 先?に、改行を入れておきます? 355 356 String idxtype = data[clmNo[INDTYPE]]; 357 // if( "1".equals( idxtype ) ) { // プライマリキー 358 if( "0".equals( idxtype ) || "1".equals( idxtype ) ) { // 0:プライマリキー , 1:ユニ?クキー 359 buf.append( "USING INDEX " ); 360 } 361 362 buf.append( "TABLESPACE " ).append( data[clmNo[TABLESPACE_NAME]] ).append( CR ); 363 buf.append( "STORAGE( INITIAL " ).append( data[clmNo[INITIAL_EXTENT]] ); 364 buf.append( "K NEXT " ).append( data[clmNo[NEXT_EXTENT]] ); 365 buf.append( "K PCTINCREASE 0 )" ); 366 367 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ); } 368 else { buf.append( ";" ); } 369 370 return buf.toString(); 371 } 372 373 /** 374 * イン?クス削除の構文を?作?します? 375 * 376 * @og.rev 5.6.9.2 (2013/10/18) 新規作? 377 * 378 * @param clmNo カラ?号配? 379 * @param data ?行?の??タ配? 380 * 381 * @return 作?された1行?の?? 382 */ 383 protected String makeDropLine( final int[] clmNo,final String[] data ) { 384 String tableName = data[clmNo[TABLE_NAME]]; 385 String indexName = data[clmNo[INDEX_NAME]]; 386 String idxtype = data[clmNo[INDTYPE]]; 387 388 StringBuilder buf = new StringBuilder(); 389 390 buf.append( CR ); // 先?に、改行を入れておきます? 391 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } 392 393 // 0:プライマリキー , 1:ユニ?クキー 394 if( "0".equals( idxtype ) || "1".equals( idxtype ) ) { 395 buf.append( "ALTER TABLE " ).append( tableName ).append( " DROP CONSTRAINT " ); 396 buf.append( indexName ); 397 } 398 // 5.6.9.2 (2013/10/18) INDTYPE で、その他ではなく?2:通常 で判断する? 399 else if( "2".equals( idxtype ) ) { // 2:通常 400 buf.append( "DROP INDEX " ).append( indexName ); 401 } 402 // ??の処?、makeLineList ですでにエラーが?て?ハズなので、ここでは出しません? 403 // else { 404 // String errMsg = "INDTYPE が?0,1,2 以外?値が使われて?す?INDTYPE=[" + idxtype + "]" 405 // + " TABLE_NAME=[" + tableName + "] INDEX_NAME=[" + indexName + "]" ; 406 // System.out.println( errMsg ); 407 // } 408 409 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ); } 410 else { buf.append( ";" ); } 411 412 return buf.toString(); 413 } 414 415 /** 416 * イン?クスを作?するための??を返します? 417 * 通常、カラ?をそのまま返します? 418 * ?、唯??MySQLの場合?500バイト以上?カラ?つ?は、TEXTで定義しており? 419 * こ?場合?イン?クス化するバイト数(?255)を指定する?があります? 420 * こ?ケースに対応するため?カラ?とバイト数を?に判定し??ン?クス? 421 * 作?するための??を作?します? 422 * 423 * @param clm カラ? 424 * @param useLen カラ??バイト数 425 * 426 * @return イン?クスカラ???? 427 * @see TableFilter_INDEX_MYSQL 428 */ 429 protected String makeIndexClmStr( final String clm, final String useLen ) { 430 return clm; 431 } 432 }