    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         * @og.rev 5.9.31.1 (2018/04/13) DBID追加対応
    105         *
    106         * @param seqName シーケンス名
    107         * @param tran トランザクション
    108         *
    109         * @return シーケンス番号
    110         */
    111        public int getSequence( final String seqName, final Transaction tran ) {
    112                return getSequence(seqName, tran, null);
    113        }
    114
    115        /**
    116         * シーケンス名よりシーケンスオブジェクトを検索し、次の値を取り出します。
    117         * DBに対するシーケンスオブジェクトは予め作成されている必要があります。
    118         *
    119         * また、MySQLの場合は、シーケンスオブジェクトが実装されていないため、
    120         * 内部的には、引数のシーケンス名と同じ名前のテーブルから、Integer型の
    121         * "SEQID"という項目名を検索することにより、シーケンスをエミュレートしています。
    122         *
    123         * @og.rev 5.1.9.0 (2010/08/01) 新規追加
    124         * @og.rev 5.8.5.0 (2015/03/06) CACHE追加
    125         * @og.rev 5.9.31.1 (2018/04/13) SQL文作成を分離
    126         *
    127         * @param seqName シーケンス名
    128         * @param tran トランザクション
    129         * @param DBID DBID
    130         *
    131         * @return シーケンス番号
    132         */
    133        public int getSequence( final String seqName, final Transaction tran, final String DBID ) {
    134                String sql = null;
    135                String[][] rtn = null;
    136                switch ( this ) {
    137                        case ORACLE:
    138                                sql = "select " + seqName + ".nextval from dual";
    139                                break;
    140                        case HSQL:
    141                                sql = "select next value for " + seqName + " from dual";
    142                                break;
    143                        case POSTGRES:
    144                                sql = "select nextval('" + seqName + "')";
    145                                break;
    146                        case MYSQL:
    147                                sql = "update " + seqName + " set SEQID = last_insert_id(SEQID+1)";
    148                                DBUtil.dbExecute( sql, new String[0], tran );
    149                                sql = "select last_insert_id()";
    150                                break;
    151                        case SQLSERVER:
    152                                throw new RuntimeException( "現在、SQLSERVERではシーケンス機能はサポートされていません。" );
    153                        case FIREBIRD:
    154                                sql = "select gen_id(" + seqName + ", 1) from rdb$database";
    155                                break;
    156                        case CACHE:
    157                                throw new RuntimeException( "現在、CACHEではシーケンス機能はサポートされていません。" );
    158                        default:
    159                                throw new RuntimeException( "現在、このデータベースではシーケンス機能はサポートされていません。" );
    160                }
    161
    162                rtn = DBUtil.dbExecute( sql, new String[0], tran, DBID );
    163                return Integer.valueOf( rtn[0][0] );
    164        }
    165
    166        /**
    167         * 各データベースに対応するenum名を返します。
    168         *
    169         * @og.rev 5.1.4.0 (2010/03/01) 新規作成
    170         * @og.rev 5.8.5.0 (2015/03/06) CACHE追加
    171         * @og.rev 5.9.19.0 (2017/04/07) Azure対応。基本的にFunction等はDB種別に依存するはず。
    172         *
    173         * @param   dbName データベース名
    174         *
    175         * @return  データベースに対応するenum名
    176         */
    177        public static DBFunctionName getDBName( final String dbName ) {
    178//              String dbn = dbName.toUpperCase( Locale.JAPAN );
    179                String dbn = DBUtil.getDBType(dbName).toUpperCase( Locale.JAPAN );
    180
    181                if(      dbn.indexOf( "ORACLE"          ) >= 0 ) { return DBFunctionName.ORACLE;     }
    182                else if( dbn.indexOf( "HSQL"            ) >= 0 ) { return DBFunctionName.HSQL;               }
    183                else if( dbn.indexOf( "POSTGRES"        ) >= 0 ) { return DBFunctionName.POSTGRES;   }
    184                else if( dbn.indexOf( "MYSQL"           ) >= 0 ) { return DBFunctionName.MYSQL;              }
    185                else if( dbn.indexOf( "SQLSERVER"       ) >= 0 ) { return DBFunctionName.SQLSERVER;  }
    186                else if( dbn.indexOf( "FIREBIRD"        ) >= 0 ) { return DBFunctionName.FIREBIRD;   }
    187                else if( dbn.indexOf( "CACHE"           ) >= 0 ) { return DBFunctionName.CACHE;      }
    188
    189                final String errMsg = "初期化時に、指定の dbName キーが存在しません。"
    190                                                + "[" + dbn + "]" ;
    191
    192                throw new RuntimeException( errMsg );
    193        }
    194
    195        /**
    196         * 各データベースに対応するファンクション名を返します。
    197         *
    198         * @og.rev 4.3.8.0 (2009/08/01) SUBSTRを追加
    199         * @og.rev 5.1.2.0 (2010/01/01) MySQL対応,SUBSTRB廃止(帳票データの分割の内部処理化に伴う)
    200         * @og.rev 5.1.4.0 (2010/03/01) データベース名 ではなく、dbid で判断するように変更
    201         * @og.rev 5.7.7.2 (2014/06/20) DBF.NAME 時の処理の簡素化
    202         * @og.rev 5.9.19.1 (2017/04/14) DBF.TYPE追加
    203         *
    204         * @param   func ファンクション名(定義文字)
    205         * @param   dbid 接続先ID
    206         *
    207         * @return  実ファンクション名
    208         */
    209        public static String getFunctionName( final String func ,final String dbid ) {
    210//              DBFunctionName dbName = DBFunctionName.getDBName( ConnectionFactory.getDBName( dbid ) );
    211
    212                // 5.7.7.2 (2014/06/20) DBF.NAME 時の処理の簡素化
    213                String dbName = ConnectionFactory.getDBName( dbid );
    214                if( "NAME".equals( func ) ) { return dbName; }
    215                else if( "TYPE".equals( func ) ){ return  DBUtil.getDBType(dbName); }
    216                else {
    217                        return getDBName( dbName ).getFunctionName( func );
    218                }
    219
    220//              return dbName.getFunctionName( func );
    221        }
    222}