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.Locale; 021 import java.util.Map; 022 023 import org.opengion.fukurou.db.DBUtil; 024 import org.opengion.fukurou.db.Transaction; // 5.5.2.6 (2012/05/25) 025 import org.opengion.fukurou.util.ErrorMessage; 026 import org.opengion.fukurou.util.FileUtil; 027 import org.opengion.fukurou.util.FixLengthData; 028 import org.opengion.fukurou.util.StringUtil; 029 import org.opengion.hayabusa.common.HybsSystem; 030 import org.opengion.hayabusa.common.HybsSystemException; 031 import org.opengion.hayabusa.db.AbstractTableFilter; 032 import org.opengion.hayabusa.db.DBTableModel; 033 034 /** 035 * TableFilter_TABLE は、TableFilter インターフェースを継承した、DBTableModel 処?の 036 * 実?ラスです? 037 * 038 * ここでは、テーブル?の検索結果より、GF05 の??ブルカラ?義??ブルから 039 * ?な??を取得し、テーブル作?スクリプトを作?します? 040 * 出力ファイルは、テーブル名?S.sql" と?命名規則で作?します? 041 * 検索では?SYSTEM_ID,TBLSYU,TABLE_NAME,NAME_JA,TABLESPACE_NAME,INITIAL_EXTENT,NEXT_EXTENT,COMMENTS) 042 * の?を取得する?があります? 043 * 044 * パラメータは、tableFilterタグの keys, vals にそれぞれ記述するか?BODY 部にCSS形式で記述します? 045 * 【パラメータ? 046 * { 047 * DIR : {@BASE_DIR}/sql/01_TABLE ; 出力ファイルの基準フォル???) 048 * XML : false ; XML出力を行うかど?[true/false]を指定しま?初期値:false)? 049 * } 050 * 051 * @og.formSample 052 * ●形式? 053 * select SYSTEM_ID,TBLSYU,TABLE_NAME,NAME_JA,TABLESPACE_NAME,INITIAL_EXTENT,NEXT_EXTENT,COMMENTS from GF05 054 * 055 * ?<og:tableFilter classId="TABLE" keys="DIR,XML" vals='"{@BASE_DIR}/sql/01_TABLE,"' /> 056 * 057 * ② <og:tableFilter classId="TABLE" > 058 * { 059 * DIR : {@BASE_DIR}/sql/01_TABLE ; 060 * XML : false ; 061 * } 062 * </og:tableFilter> 063 * 064 * @og.rev 4.0.0.0 (2005/08/31) 新規作? 065 * @og.rev 5.6.6.0 (2013/07/05) keys の整合?チェ?を追? 066 * 067 * @version 0.9.0 2000/10/17 068 * @author Kazuhiko Hasegawa 069 * @since JDK1.1, 070 */ 071 public class TableFilter_TABLE extends AbstractTableFilter { 072 //* こ?プログラ??VERSION??を設定します? {@value} */ 073 private static final String VERSION = "5.6.6.2 (2013/07/19)" ; 074 075 /** 076 * keys の整合?チェ?を行うための初期設定を行います? 077 * 078 * @og.rev 5.6.6.1 (2013/07/12) keys の整合?チェ?対? 079 * 080 * @param keysMap keys の整合?チェ?を行うための Map 081 */ 082 @Override 083 protected void init( final Map<String,String> keysMap ) { 084 keysMap.put( "DIR" , "出力ファイルの基準フォル???)" ); 085 keysMap.put( "XML" , "XML出力を行うかど?[true/false]を指?初期値:false)" ); 086 } 087 088 private static final String[] DBKEY = {"SYSTEM_ID","TBLSYU","TABLE_NAME","NAME_JA", 089 "TABLESPACE_NAME","INITIAL_EXTENT","NEXT_EXTENT","COMMENTS" }; 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 NAME_JA = 3; 100 /** ??タのアクセス用の配?番号 {@value} */ 101 protected static final int TABLESPACE_NAME = 4; 102 /** ??タのアクセス用の配?番号 {@value} */ 103 protected static final int INITIAL_EXTENT = 5; 104 /** ??タのアクセス用の配?番号 {@value} */ 105 protected static final int NEXT_EXTENT = 6; 106 /** ??タのアクセス用の配?番号 {@value} */ 107 protected static final int COMMENTS = 7; 108 109 private static final String GF05_SEL = "SELECT CLM,SEQNO,NAME_JA,CLS_NAME,USE_LENGTH,DATA_DEFAULT,NOT_NULL,'' AS OPTS" 110 + " FROM GF05" 111 + " WHERE SYSTEM_ID=? AND TBLSYU=? AND TABLE_NAME=?" 112 + " AND FGJ='1'" 113 + " ORDER BY SEQNO" ; 114 115 /** ??タのアクセス用の配?番号 {@value} */ 116 protected static final int GF05_CLM = 0; 117 /** ??タのアクセス用の配?番号 {@value} */ 118 protected static final int GF05_SEQNO = 1; 119 /** ??タのアクセス用の配?番号 {@value} */ 120 protected static final int GF05_NAME_JA = 2; 121 /** ??タのアクセス用の配?番号 {@value} */ 122 protected static final int GF05_CLS_NAME = 3; 123 /** ??タのアクセス用の配?番号 {@value} */ 124 protected static final int GF05_USE_LENGTH = 4; 125 /** ??タのアクセス用の配?番号 {@value} */ 126 protected static final int GF05_DATA_DEFAULT= 5; 127 /** ??タのアクセス用の配?番号 {@value} */ 128 protected static final int GF05_NOT_NULL = 6; 129 /** ??タのアクセス用の配?番号 {@value} */ 130 protected static final int GF05_OPTIONS = 7; 131 132 // private static final String ENCODE = "Windows-31J" ; 133 private static final String ENCODE = "UTF-8" ; // 4.3.6.6 (2009/05/15) 134 // private static final String CR = HybsSystem.CR ; // 5.1.1.0 (2009/12/01) CR 定義をAbstractTableFilterで行う? 135 136 private static final String CMNT = "************************************************************************" ; 137 138 private static final int X = FixLengthData.X ; // type 定数 139 private static final int S = FixLengthData.S ; // type 定数 140 private static final int K = FixLengthData.K ; // type 定数 141 private static final int T = FixLengthData.T ; // addLen 定数 142 private static final int T2= FixLengthData.T2 ; // addLen 定数 143 144 /** ?定数 */ 145 protected static final String XML_START_TAG = "<?xml version='1.0' encoding='UTF-8'?>" + CR + "<ROWSET tableName='xxx'>"; 146 protected static final String XML_END_TAG = "</ROWSET>"; 147 protected static final String EXEC_START_TAG= "<EXEC_SQL>"; 148 protected static final String EXEC_END_TAG = "</EXEC_SQL>"; 149 150 /** XML形式かど? */ 151 protected boolean isXml = false; // 4.3.7.0 (2009/06/01) 152 153 /** 154 * DBTableModel処?実行します? 155 * 156 * @og.rev 3.8.7.0 (2006/12/15) アクセスログ取得?為,ApplicationInfoオブジェクトを設? 157 * @og.rev 4.0.0.0 (2007/11/28) メソ?の戻り?をチェ?します? 158 * @og.rev 4.3.7.0 (2009/06/01) トリガー、SEQUENCE作?機?、XML出力機?追? 159 * @og.rev 5.1.1.0 (2009/12/01) XML_START_TAG に、tableName をセ?します? 160 * @og.rev 5.1.9.0 (2010/08/01) Transaction 対? 161 * @og.rev 5.5.2.6 (2012/05/25) protected変数を?private化したため?getterメソ?で取得するよ?変更 162 * @og.rev 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用 163 * 164 * @return 実行結果の??ブルモ? 165 */ 166 public DBTableModel execute() { 167 DBTableModel table = getDBTableModel(); // 5.5.2.6 (2012/05/25) インターフェースにgetterメソ?追? 168 169 isXml = StringUtil.nval( getValue( "XML" ), false ); 170 171 int[] clmNo = getTableColumnNo( DBKEY ); 172 int rowCnt = table.getRowCount(); 173 174 File dir = new File( getValue( "DIR" ) ); 175 if( ! dir.exists() && ! dir.mkdirs() ) { 176 String errMsg = "??フォル?作?できませんでした?" + dir + "]" ; 177 // 4.3.4.4 (2009/01/01) 178 throw new HybsSystemException( errMsg ); 179 } 180 181 // カン?カラ?クラス,(,桁数,),初期値,NOT_NULL,拡張機?,コメント開?行番号,名称,コメント終? 182 // 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用 183 // FixLengthData fixData = new FixLengthData(10); 184 185 // カン?カラ?クラス,(,桁数,),初期値,NOT_NULL,拡張機?,コメント開?行番号,名称,コメント終? 186 int[] addLen = new int[] { 0,T,0,0,0,T2,T,T,T2,0,1,T,0 }; // ?ータ間?スペ?ス 187 int[] type = new int[] { X,X,X,X,S,X, X,X,X, X,S,K,X }; // ?ータの種別 X:半?S:空白前埋?K:全角混在 188 // fixData.setAddLength( addLen ); 189 // fixData.setType( type ); 190 FixLengthData fixData = new FixLengthData( addLen,type ); 191 192 String[] data = null; 193 Transaction tran = getTransaction(); // 5.5.2.6 (2012/05/25) 194 for( int row=0; row<rowCnt; row++ ) { 195 String tableName = null; 196 try { 197 data = table.getValues( row ); 198 String systemId = data[clmNo[SYSTEM_ID]]; 199 String tblsyu = data[clmNo[TBLSYU]]; 200 tableName = data[clmNo[TABLE_NAME]]; 201 202 PrintWriter writer = FileUtil.getPrintWriter( new File( dir,tableName + ( isXml ? "S.xml" : "S.sql" ) ),ENCODE ); 203 204 if( isXml ) { writer.println( XML_START_TAG.replace( "xxx",tableName ) ); } // 5.1.1.0 (2009/12/01) tableName をセ? 205 writer.print( makeHeadLine( clmNo,data ) ); 206 207 String[] vals = new String[] { systemId,tblsyu,tableName }; 208 // String[][] gf05 = DBUtil.dbExecute( GF05_SEL,vals,appInfo ); 209 String[][] gf05 = DBUtil.dbExecute( GF05_SEL,vals,tran ); // 5.1.9.0 (2010/08/01) Transaction 対? 210 211 String uniqName = null; 212 fixData.clear(); 213 // 値セ??まず?、最大長を求める?がある? 214 for( int i=0; i<gf05.length; i++ ) { 215 String[] outData = makeLineList( gf05[i],i==0 ); 216 fixData.addListData( outData ); 217 218 // 4.3.7.0 (2009/06/01) 219 if( "UNIQ".equalsIgnoreCase( gf05[i][GF05_CLM] ) || "UNIQSEQ".equalsIgnoreCase( gf05[i][GF05_CLM] ) ) { 220 uniqName = gf05[i][GF05_CLM].toUpperCase( Locale.JAPAN ); 221 } 222 } 223 // 固定長化:最大長であわせた??を?力します? 224 for( int i=0; i<gf05.length; i++ ) { 225 writer.println( fixData.getFixData( i ) ); 226 } 227 writer.println( makeEndLine( clmNo,data ) ); 228 229 // 4.3.7.0 (2009/06/01) UNIQ?のSEQとトリガーを作? 230 if( uniqName != null ) { 231 writer.println( makeUniqSeq( clmNo,data ) ); 232 writer.println( makeUniqTrig( clmNo,data, uniqName ) ); 233 } 234 235 if( isXml ) { writer.println( XML_END_TAG ); } 236 writer.close(); 237 } 238 catch( RuntimeException ex ) { 239 ErrorMessage errMessage = makeErrorMessage( "TableFilter_TABLE Error",ErrorMessage.NG ); 240 // errMessage.addMessage( row+1,ErrorMessage.NG,"TABLE",ex.getMessage() ); 241 errMessage.addMessage( row+1,ErrorMessage.NG,"TABLE",ex.toString() ); 242 errMessage.addMessage( row+1,ErrorMessage.NG,"TABLE",StringUtil.array2csv( data ) ); 243 errMessage.addMessage( row+1,ErrorMessage.NG,"TABLE","TABLE=[" + tableName + "]" ); 244 // BAT から呼び出す?合があるため、標準エラー出力にも情報を?しておきます? 245 System.out.println( errMessage ); 246 } 247 } 248 249 return table; 250 } 251 252 /** 253 * ヘッ??部??処?実行します? 254 * 255 * @og.rev 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用 256 * @og.rev 5.6.6.2 (2013/07/19) EXEC_START_TAG の付け忘れ 257 * 258 * @param clmNo カラ?号配? 259 * @param data ?行?の??タ配? 260 * 261 * @return ヘッ??部???? 262 */ 263 protected String makeHeadLine( final int[] clmNo,final String[] data ) { 264 final String TBL_NAME = data[clmNo[TABLE_NAME]]; 265 266 String LINE1 = TBL_NAME + " ( " + data[clmNo[NAME_JA]] + " )" ; 267 String LINE2 = data[clmNo[COMMENTS]] ; 268 String LINE3 = "Created : " + HybsSystem.getDate() ; 269 270 // 5.6.6.0 (2013/07/05) FixLengthData の簡易コンストラクタを使用 271 // FixLengthData fixData = new FixLengthData(3); 272 273 int[] addLen = new int[] { 0,0,0 }; // ?ータ間?スペ?ス 274 int[] type = new int[] { X,K,X }; // ?ータの種別 X:半?S:空白前埋?K:全角混在 275 // fixData.setAddLength( addLen ); 276 // fixData.setType( type ); 277 FixLengthData fixData = new FixLengthData( addLen,type ); 278 279 String[][] outData = new String[][] { 280 { "/**", CMNT , "**/" }, 281 { "/* ", LINE1, " */" }, 282 { "/* ", LINE2, " */" }, 283 { "/* ", LINE3, " */" }, 284 { "/**", CMNT , "**/" }, 285 }; 286 287 fixData.addAllListData( outData ); 288 289 // for( int i=0; i<outData.length; i++ ) { 290 // fixData.addListData( outData[i] ); 291 // } 292 293 // StringBuilder buf = new StringBuilder(); 294 // if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } 295 // for( int i=0; i<outData.length; i++ ) { 296 // buf.append( fixData.getFixData( i ) ).append( CR ); 297 // } 298 299 StringBuilder buf = new StringBuilder(); 300 fixData.getAllFixData( buf ); 301 302 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } // 5.6.6.2 (2013/07/19) 出力忘れ 303 304 buf.append( "CREATE TABLE " ).append( TBL_NAME ).append( " (" ).append( CR ); 305 306 return buf.toString(); 307 } 308 309 /** 310 * ?部?カラ?義)の処?実行します? 311 * カン?カラ?クラス,(,桁数,),初期値,NOT_NULL,拡張機?,コメント開?行番号,名称,コメント終? 312 * の?配?にセ?します? 313 * 314 * @og.rev 5.5.1.9 (2012/04/18) useLen.length=0対? 315 * @param data ?行?の??タ配? 316 * @param first ??の行かど?[true:??/false:それ以降] 317 * 318 * @return ?部?カラ?義)配? 319 */ 320 protected String[] makeLineList( final String[] data,final boolean first ) { 321 // カン?カラ?クラス(桁数),初期値,NOT_NULL,独自拡張,行番号,名称,終? 322 String[] outData = new String[13]; 323 String clsName = data[GF05_CLS_NAME]; 324 325 outData[0] = ( first ) ? " " : " , " ; // 0:カン? 326 outData[1] = data[GF05_CLM] ; // 1:カラ? 327 328 if( clsName.startsWith( "CLOB" ) || clsName.startsWith( "DATE" ) ) { 329 data[GF05_USE_LENGTH] = null; 330 } 331 String useLen = data[GF05_USE_LENGTH]; 332 // if( useLen != null && ! useLen.equals( "0" ) ) { 333 if( useLen != null && ! useLen.equals( "0" ) && useLen.length() > 0 ) { // 5.5.1.9 (2012/04/18) 334 // outData[2] = clsName + "(" + useLen + ")" ; // 2:クラス(桁数) 335 outData[2] = clsName ; // 2:クラス 336 outData[3] = " ( " ; // 3:( 337 outData[4] = useLen ; // 4:桁数 338 outData[5] = " )" ; // 5:) 339 } 340 else { 341 outData[2] = clsName ; // NUMBER型?桁数?なし?ケース 342 } 343 344 String def = data[GF05_DATA_DEFAULT]; 345 if( def != null && def.length() > 0 ) { 346 String comma = ( clsName.indexOf( "CHAR" ) >= 0 ) ? "'" : "" ; 347 outData[6] = "DEFAULT " + comma + def + comma ; // 6:初期値 348 } 349 350 String notNull = data[GF05_NOT_NULL]; 351 if( notNull != null && notNull.equals( "1" ) ) { 352 outData[7] = "NOT NULL" ; // 7:NOT_NULL 353 } 354 355 String options = data[GF05_OPTIONS]; 356 if( options != null ) { 357 outData[8] = options ; // 8:拡張機? 358 } 359 360 String nameJA = data[GF05_NAME_JA] ; // 名称 361 if( nameJA != null ) { 362 outData[9] = "/* " ; // 9:コメント開? 363 outData[10] = data[GF05_SEQNO] ; // 10:行番号 364 outData[11] = nameJA ; // 11:名称 365 outData[12] = "*/" ; // 12:コメント終? 366 } 367 368 return outData ; 369 } 370 371 /** 372 * 定義の??部??処?実行します? 373 * 374 * @param clmNo カラ?号配? 375 * @param data ?行?の??タ配? 376 * 377 * @return 定義の??部? 378 */ 379 protected String makeEndLine( final int[] clmNo,final String[] data ) { 380 StringBuilder buf = new StringBuilder(); 381 382 buf.append( ")" ).append( CR ); 383 buf.append( "TABLESPACE " ).append( data[clmNo[TABLESPACE_NAME]] ).append( CR ); 384 buf.append( "STORAGE( INITIAL " ).append( data[clmNo[INITIAL_EXTENT]] ); 385 buf.append( "K NEXT " ).append( data[clmNo[NEXT_EXTENT]] ); 386 buf.append( "K PCTINCREASE 0 )" ); 387 388 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ); } 389 else { buf.append( ";" ); } 390 391 return buf.toString(); 392 } 393 394 /** 395 * ユニ?クシーケンスの作?処?実行します? 396 * 397 * @og.rev 5.1.9.0 (2010/08/01) シーケンス名を[TABLE_NAME]S00に変更 398 * 399 * @param clmNo カラ?号配? 400 * @param data ?行?の??タ配? 401 * 402 * @return ユニ?クシーケンス 403 */ 404 protected String makeUniqSeq( final int[] clmNo,final String[] data ) { 405 StringBuilder buf = new StringBuilder(); 406 407 buf.append( CR ); 408 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } 409 410 // 5.1.9.0 (2010/08/01) シーケンス名を[TABLE_NAME]S00に変更 411 // buf.append( "CREATE SEQUENCE " ).append( data[clmNo[TABLE_NAME]] ).append( "S01 " ).append( CR ); 412 buf.append( "CREATE SEQUENCE " ).append( data[clmNo[TABLE_NAME]] ).append( "S00 " ).append( CR ); 413 buf.append( " INCREMENT BY 1 START WITH 1 MAXVALUE 999999999 CYCLE NOCACHE" ); 414 // buf.append( "INCREMENT BY 1 "); 415 // buf.append( "START WITH 1 " ); 416 // buf.append( "MAXVALUE 999999999 " ); 417 // buf.append( "CYCLE NOCACHE" ); 418 419 if( isXml ) { buf.append( CR ).append( EXEC_END_TAG ); } 420 else { buf.append( ";" ); } 421 422 return buf.toString(); 423 } 424 425 /** 426 * ユニ?クシーケンスと関連付けるトリガの作?処?実行します? 427 * 428 * @og.rev 5.1.9.0 (2010/08/01) トリガー名を[TABLE_NAME]T00に変更 429 * 430 * @param clmNo カラ?号配? 431 * @param data ?行?の??タ配? 432 * @param uniqName ユニ?クトリガ? 433 * 434 * @return ユニ?クシーケンスと関連付けるトリガ 435 */ 436 protected String makeUniqTrig( final int[] clmNo,final String[] data, final String uniqName ) { 437 final String TBL_NAME = data[clmNo[TABLE_NAME]] ; 438 StringBuilder buf = new StringBuilder(); 439 440 buf.append( CR ); 441 if( isXml ) { buf.append( EXEC_START_TAG ).append( CR ); } 442 443 // 5.1.9.0 (2010/08/01) トリガー名を[TABLE_NAME]T00に変更 444 // buf.append( "CREATE OR REPLACE TRIGGER " ).append( TBL_NAME ).append( "T01 " ).append( CR ); 445 buf.append( "CREATE OR REPLACE TRIGGER " ).append( TBL_NAME ).append( "T00 " ).append( CR ); 446 buf.append( " BEFORE INSERT ON ").append( TBL_NAME ).append( CR ); 447 buf.append( " FOR EACH ROW " ).append( CR ); 448 buf.append( " BEGIN " ).append( CR ); 449 // 5.1.9.0 (2010/08/01) シーケンス名を[TABLE_NAME]S00に変更 450 // buf.append( "SELECT " ).append( TBL_NAME ).append( "S01.NEXTVAL INTO :NEW." ) 451 buf.append( " SELECT " ).append( TBL_NAME ).append( "S00.NEXTVAL INTO :NEW." ) 452 .append( uniqName ).append( " FROM DUAL; " ).append( CR ); 453 buf.append( " END; " ).append( CR ); 454 455 if( isXml ) { buf.append( EXEC_END_TAG ); } 456 else { buf.append( "/" ); } 457 458 return buf.toString(); 459 } 460 }