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.plugin.table;
017
018import org.opengion.fukurou.system.OgBuilder ;                          // 6.4.4.1 (2016/03/18)
019
020/**
021 * TableFilter_TABLE_FIREBIRD は、TableUpda インターフェースを継承した、DBTableModel 処理用の
022 * 実装クラスです。とくに、Firebird用のDB定義スクリプトを作成します。
023 *
024 * ここでは、テーブル一覧の検索結果より、GF05 のテーブルカラム定義テーブルから
025 * 必要な情報を取得し、テーブル作成スクリプトを作成します。
026 * 出力ファイルは、テーブル名+"S.sql" という命名規則で作成します。
027 * 検索では、(SYSTEM_ID,TBLSYU,TABLE_NAME,NAME_JA,TABLESPACE_NAME,INITIAL_EXTENT,COMMENTS)
028 * の項目を取得する必要があります。
029 *
030 * @og.rev 5.1.1.0 (2009/12/01) 新規作成
031 *
032 * @version  0.9.0  2000/10/17
033 * @author   Kazuhiko Hasegawa
034 * @since    JDK1.1,
035 */
036public class TableFilter_TABLE_FIREBIRD extends TableFilter_TABLE {
037        /** このプログラムのVERSION文字列を設定します。   {@value} */
038        private static final String VERSION = "8.1.0.3 (2022/01/21)" ;
039
040        /**
041         * デフォルトコンストラクター
042         *
043         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
044         */
045        public TableFilter_TABLE_FIREBIRD() { super(); }                // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
046
047        /**
048         * ヘッダー部分の処理を実行します。
049         *
050         * @og.rev 8.1.0.3 (2022/01/21) EXEC_SQLに、exists属性追加。
051         *
052         * @param       clmNo   カラム番号配列
053         * @param       data    1行分のデータ配列
054         *
055         * @return      ヘッダー部分の文字列
056         * @og.rtnNotNull
057         */
058        @Override
059        protected String makeHeadLine( final int[] clmNo,final String[] data ) {
060                // 8.1.0.3 (2022/01/21) EXEC_SQLに、exists属性追加。
061                execExistsSQL = "SELECT COUNT(*) FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG=0 and RDB$RELATION_TYPE=0 and RDB$RELATION_NAME=UPPER('" ;            // 大文字で管理
062
063                return super.makeHeadLine( clmNo,data );
064        }
065
066        /**
067         * 各行部分(カラム定義)の処理を実行します。
068         *
069         * @og.rev 5.1.1.0 (2009/12/01) 各カラムの説明を追加
070         * @og.rev 5.3.9.0 (2011/09/01) PRIMARY KEY の作成は、INDEX側で行うこととする。
071         * @og.rev 5.5.8.2 (2012/11/09) NUMBER の小数の扱いを、DECIMAL にする。
072         * @og.rev 5.6.9.2 (2013/10/18) useLen が、nullやゼロ文字列の場合の考慮
073         *
074         * @param       data    1行分のデータ配列
075         * @param       first   最初の行かどうか[true:最初/false:それ以降]
076         *
077         * @return      各行部分(カラム定義)配列
078         */
079        @Override
080        protected String[] makeLineList( final String[] data,final boolean first ) {
081
082                final String clsName = data[GF05_CLS_NAME] ;
083                String useLen  = data[GF05_USE_LENGTH] ;
084                if( useLen != null && useLen.contains( "." ) ) { useLen = useLen.replace( '.' , ',' ); }
085
086                data[GF05_USE_LENGTH] = null;                           // 標準では、桁数をクリアしておく。
087
088                // 5.1.1.0 (2009/12/01) 各カラムの説明文を 入れたくない場合は、null を設定する。
089                if( isXml ) { data[GF05_NAME_JA] = null; }
090
091                if( "UNIQ".equalsIgnoreCase( data[GF05_CLM] ) || "UNIQSEQ".equalsIgnoreCase( data[GF05_CLM] ) ) {
092                        data[GF05_CLS_NAME]     = "BIGINT";
093                        data[GF05_DATA_DEFAULT] = null;
094                        data[GF05_NOT_NULL]     = "1";
095                }
096                else if( clsName == null || clsName.isEmpty() || clsName.startsWith( "VARCHAR" ) ) {            // 6.1.0.0 (2014/12/26) refactoring
097                        data[GF05_CLS_NAME]   = "VARCHAR" ;
098                        data[GF05_USE_LENGTH] = useLen ;
099                }
100                else if( clsName.startsWith( "CLOB" ) ) {
101                        data[GF05_CLS_NAME]     = "BLOB SUB_TYPE 1";
102                        data[GF05_DATA_DEFAULT] = null;
103                        data[GF05_NOT_NULL]     = null;
104                }
105                // 5.6.9.2 (2013/10/18) useLen が、nullやゼロ文字列の場合の考慮
106                else if( clsName.startsWith( "NUMBER" ) && useLen != null && useLen.length() > 0 ) {
107
108                        if( useLen.contains( "," ) ) {          // カンマがある
109                                data[GF05_CLS_NAME] = "DECIMAL";                // 5.5.8.2 (2012/11/09) 小数は、DECIMAL
110                                data[GF05_USE_LENGTH] = useLen ;
111                        }
112                        else if( Integer.parseInt( useLen ) < 10 ) {    // 10桁以下
113                                data[GF05_CLS_NAME] = "INTEGER";                // 5.5.8.2 (2012/11/09) NUMBER のデフォルトは、INTEGER
114                        }
115                        else if( Integer.parseInt( useLen ) < 18 ) {    // 18桁以下
116                                data[GF05_CLS_NAME] = "BIGINT";
117                        }
118                }
119
120                // 5.5.8.2 (2012/11/09) 4000 文字なら、VARCHAR のままで登録できる。
121        //      // 暫定追加
122        //      if( "4000".equalsIgnoreCase( data[GF05_USE_LENGTH] ) ) {
123        //              data[GF05_CLS_NAME]     = "BLOB";
124        //              data[GF05_DATA_DEFAULT] = null;
125        //              data[GF05_NOT_NULL]     = null;
126        //              data[GF05_USE_LENGTH]   = null;
127        //      }
128
129                return super.makeLineList( data,first );
130        }
131
132//      /**
133//       * 定義の最後の部分の処理を実行します。
134//       *
135//       * @og.rev 6.0.2.3 (2014/10/10) isXml で、CR + EXEC_END_TAG のキャッシュを作成します。
136//       *
137//       * @param       clmNo   カラム番号配列
138//       * @param       data    1行分のデータ配列
139//       *
140//       * @return      定義の最後の部分
141//       * @og.rtnNotNull
142//       */
143//      @Override
144//      protected String makeEndLine( final int[] clmNo,final String[] data ) {
145//              return ")" + execEndTag ;                                               // 6.0.2.3 (2014/10/10) 改行を含める。
146//      }
147
148        /**
149         * ユニークシーケンスの作成処理を実行します。
150         *
151         * @og.rev 5.1.9.0 (2010/08/01) シーケンス名を[TABLE_NAME]S00に変更
152         * @og.rev 6.0.2.3 (2014/10/10) isXml で、CR + EXEC_END_TAG のキャッシュを作成します。
153         * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。
154         * @og.rev 8.1.0.3 (2022/01/21) 引数にtableNameを渡すように変更。
155         *
156//       * @param       clmNo   カラム番号配列
157//       * @param       data    1行分のデータ配列
158         * @param       tableName       テーブル名
159         *
160         * @return      ユニークシーケンス
161         * @og.rtnNotNull
162         */
163        @Override
164//      protected String makeUniqSeq( final int[] clmNo,final String[] data ) {
165        protected String makeUniqSeq( final String tableName ) {
166                final String execSeqSQL = "SELECT COUNT(*) FROM RDB$GENERATORS WHERE RDB$GENERATOR_NAME=UPPER('" ;
167
168                return new OgBuilder()
169                                .appendCR()
170//                              .appendIfCR( isXml , EXEC_START_TAG )
171//                              .append( "CREATE SEQUENCE " , data[clmNo[TABLE_NAME]] , "S00 " )
172                                .appendIfCR( isXml , EXEC_EXISTS_0_TAG )                //  EXISTS_0 判定は、XML の場合のみ。
173                                .appendIfCR( isXml , execSeqSQL , tableName , "S00');" )
174                                .append( "CREATE SEQUENCE "     , tableName , "S00 " )          // 8.1.0.3 (2022/01/21)
175                                .append( execEndTag )
176                                .toString();
177        }
178
179        /**
180         * ユニークシーケンスと関連付けるトリガの作成処理を実行します。
181         *
182         * @og.rev 5.1.9.0 (2010/08/01) トリガー名を[TABLE_NAME]T00に変更
183         * @og.rev 6.4.4.1 (2016/03/18) StringBuilderの代わりに、OgBuilderを使用する。
184         * @og.rev 8.1.0.3 (2022/01/21) 引数にtableNameを渡すように変更。
185         *
186//       * @param       clmNo           カラム番号配列
187//       * @param       data            1行分のデータ配列
188         * @param       tableName       テーブル名
189         * @param   uniqName    ユニークトリガ名
190         *
191         * @return      ユニークシーケンスと関連付けるトリガ
192         * @og.rtnNotNull
193         */
194        @Override
195//      protected String makeUniqTrig( final int[] clmNo,final String[] data, final String uniqName ) {
196        protected String makeUniqTrig( final String tableName, final String uniqName ) {
197//              final String TBL_NAME = data[clmNo[TABLE_NAME]] ;
198
199                return new OgBuilder()
200                                .appendCR()
201                                .appendIfCR( isXml , EXEC_START_TAG )
202                                .append(   "CREATE TRIGGER "    , tableName )
203                                .appendCR( "T00 FOR "                   , tableName )
204                                .appendCR( "  BEFORE INSERT AS " )
205                                .appendCR( "  BEGIN " )
206                                .append(   "    NEW."                   , uniqName      )
207                                .appendCR( " = GEN_ID( "                , tableName , "S00,1 );" )
208                                .appendCR( "  END; " )
209                                .appendIf( isXml , EXEC_END_TAG )               // ここはキャッシュではなく、EXEC_END_TAG を使う。
210                                .toString();
211        }
212}