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.fukurou.db;
017
018import java.util.Locale;
019
020/**
021 * 各データベースに対応するenum名を返します。
022 * 主に、各データベースにおける関数名の差異を吸収するためのenumです。
023 * 本来は、互換性のあるファンクション以外、使用しないようにしましょう。
024 * また、無ければ互換性パックなどで、ファンクションを定義してしまうのも
025 * 一つの方法です。
026 *
027 * <table border="1" frame="box" rules="all" >
028 *  <caption>各データベースにおける関数</caption>
029 *  <tr><th>データベース名 </th><th>連結</th><th>部分文字列</th></tr>
030 *  <tr><td>{&#064;DBF.XXX}</td><td>CON </td><td>SUBSTR    </td></tr>
031 *  <tr><td>ORACLE         </td><td>||  </td><td>SUBSTR    </td></tr>
032 *  <tr><td>HSQL           </td><td>||  </td><td>SUBSTR    </td></tr>
033 *  <tr><td>POSTGRES       </td><td>||  </td><td>SUBSTR    </td></tr>
034 *  <tr><td>MYSQL          </td><td>||  </td><td>SUBSTR    </td></tr>
035 *  <tr><td>SQLSERVER      </td><td>+   </td><td>SUBSTRING </td></tr>
036 *  <tr><td>FIREBIRD       </td><td>||  </td><td>SUBSTR    </td></tr>
037 *  <tr><td>CACHE          </td><td>||  </td><td>SUBSTRING </td></tr>
038 * </table>
039 *
040 * @og.rev 5.1.4.0 (2010/03/01) 新規作成
041 * @og.rev 5.8.5.0 (2015/03/06) CACHE追加
042 *
043 * @version  5.0
044 * @author   Kazuhiko Hasegawa
045 * @since    JDK5.0,
046 */
047public enum DBFunctionName {
048        // 引数付きenum定義:ここに、必要な関数が増えるたびに、追加していきます。
049        //                        CON   SUBSTR
050          ORACLE        ( "||","SUBSTR" )
051        , HSQL          ( "||","SUBSTR" )
052        , POSTGRES      ( "||","SUBSTR" )
053        , MYSQL         ( "||","SUBSTR" )
054        , SQLSERVER     ( "+" ,"SUBSTRING" )
055        , FIREBIRD      ( "||","SUBSTR" ) 
056        , CACHE         ( "||","SUBSTRING" ) ; 
057
058        private final String dbfCON ;
059        private final String dbfSUBSTR ;
060
061        /**
062         * コンストラクター(enum の場合は、private宣言される)
063         *
064         * @og.rev 5.1.4.0 (2010/03/01) 新規作成
065         *
066         * @param       con     第一引数にて指定(CON)
067         * @param       substr  第一引数にて指定(SUBSTR)
068         */
069        private DBFunctionName( final String con , final String substr ) {
070                dbfCON    = con;
071                dbfSUBSTR = substr;
072        }
073
074        /**
075         * 共通ファンクションに対応するデータベース個別のファンクション名を返します。
076         *
077         * 現時点では、NAME,CON,SUBSTR のみ使用できます。
078         *
079         *
080         * @og.rev 5.1.4.0 (2010/03/01) 新規作成
081         *
082         * @param   func 共通ファンクション
083         *
084         * @return  ファンクション名
085         */
086        public String getFunctionName( final String func ) {
087                if( "NAME".equals(   func ) ) { return toString();      }
088                if( "CON".equals(    func ) ) { return dbfCON;          }
089                if( "SUBSTR".equals( func ) ) { return dbfSUBSTR;       }
090
091                return func;
092        }
093
094        /**
095         * シーケンス名よりシーケンスオブジェクトを検索し、次の値を取り出します。
096         * DBに対するシーケンスオブジェクトは予め作成されている必要があります。
097         *
098         * また、MySQLの場合は、シーケンスオブジェクトが実装されていないため、
099         * 内部的には、引数のシーケンス名と同じ名前のテーブルから、Integer型の
100         * "SEQID"という項目名を検索することにより、シーケンスをエミュレートしています。
101         *
102         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
103         * @og.rev 5.8.5.0 (2015/03/06) CACHE追加
104         *
105         * @param seqName シーケンス名
106         * @param tran トランザクション
107         *
108         * @return シーケンス番号
109         */
110        public int getSequence( final String seqName, final Transaction tran ) {
111                String sql = null;
112                String[][] rtn = null;
113                switch ( this ) {
114                        case ORACLE:
115                                sql = "select " + seqName + ".nextval from dual";
116                                break;
117                        case HSQL:
118                                sql = "select next value for " + seqName + " from dual";
119                                break;
120                        case POSTGRES:
121                                sql = "select nextval('" + seqName + "')";
122                                break;
123                        case MYSQL:
124                                sql = "update " + seqName + " set SEQID = last_insert_id(SEQID+1)";
125                                DBUtil.dbExecute( sql, new String[0], tran );
126                                sql = "select last_insert_id()";
127                                break;
128                        case SQLSERVER:
129                                throw new RuntimeException( "現在、SQLSERVERではシーケンス機能はサポートされていません。" );
130                        case FIREBIRD:
131                                sql = "select gen_id(" + seqName + ", 1) from rdb$database";
132                                break;
133                        case CACHE:
134                                throw new RuntimeException( "現在、CACHEではシーケンス機能はサポートされていません。" );
135                        default:
136                                throw new RuntimeException( "現在、このデータベースではシーケンス機能はサポートされていません。" );
137                }
138
139                rtn = DBUtil.dbExecute( sql, new String[0], tran );
140                return Integer.valueOf( rtn[0][0] );
141        }
142
143        /**
144         * 各データベースに対応するenum名を返します。
145         *
146         * @og.rev 5.1.4.0 (2010/03/01) 新規作成
147         * @og.rev 5.8.5.0 (2015/03/06) CACHE追加
148         *
149         * @param   dbName データベース名
150         *
151         * @return  データベースに対応するenum名
152         */
153        public static DBFunctionName getDBName( final String dbName ) {
154                String dbn = dbName.toUpperCase( Locale.JAPAN );
155
156                if(      dbn.indexOf( "ORACLE"          ) >= 0 ) { return DBFunctionName.ORACLE;     }
157                else if( dbn.indexOf( "HSQL"            ) >= 0 ) { return DBFunctionName.HSQL;               }
158                else if( dbn.indexOf( "POSTGRES"        ) >= 0 ) { return DBFunctionName.POSTGRES;   }
159                else if( dbn.indexOf( "MYSQL"           ) >= 0 ) { return DBFunctionName.MYSQL;              }
160                else if( dbn.indexOf( "SQLSERVER"       ) >= 0 ) { return DBFunctionName.SQLSERVER;  }
161                else if( dbn.indexOf( "FIREBIRD"        ) >= 0 ) { return DBFunctionName.FIREBIRD;   }
162                else if( dbn.indexOf( "CACHE"           ) >= 0 ) { return DBFunctionName.CACHE;      }
163
164                final String errMsg = "初期化時に、指定の dbName キーが存在しません。"
165                                                + "[" + dbn + "]" ;
166
167                throw new RuntimeException( errMsg );
168        }
169
170        /**
171         * 各データベースに対応するファンクション名を返します。
172         *
173         * @og.rev 4.3.8.0 (2009/08/01) SUBSTRを追加
174         * @og.rev 5.1.2.0 (2010/01/01) MySQL対応,SUBSTRB廃止(帳票データの分割の内部処理化に伴う)
175         * @og.rev 5.1.4.0 (2010/03/01) データベース名 ではなく、dbid で判断するように変更
176         * @og.rev 5.7.7.2 (2014/06/20) DBF.NAME 時の処理の簡素化
177         *
178         * @param   func ファンクション名(定義文字)
179         * @param   dbid 接続先ID
180         *
181         * @return  実ファンクション名
182         */
183        public static String getFunctionName( final String func ,final String dbid ) {
184//              DBFunctionName dbName = DBFunctionName.getDBName( ConnectionFactory.getDBName( dbid ) );
185
186                // 5.7.7.2 (2014/06/20) DBF.NAME 時の処理の簡素化
187                String dbName = ConnectionFactory.getDBName( dbid );
188                if( "NAME".equals( func ) ) { return dbName; }
189                else {
190                        return getDBName( dbName ).getFunctionName( func );
191                }
192
193//              return dbName.getFunctionName( func );
194        }
195}