ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Event Processing CQL言語リファレンス
11gリリース1 (11.1.1.7)
B61613-06
  目次へ移動
目次

前
 
次
 

13 ユーザー定義関数

この章では、Oracle Continuous Query Language (Oracle CQL)で使用するユーザー定義関数を記述して、組込み関数を使用する場合よりも高度な操作やアプリケーション固有の操作をストリーム・データに対して実行する方法について説明します。

詳細は、1.1.11項「関数」を参照してください。

この章の内容は次のとおりです。

13.1 Oracle CQLのユーザー定義関数の概要

ユーザー定義関数をJavaで作成し、Oracle CQLやOracle CQL組込み関数には用意されていない機能を提供できます。集計値または単一値(非集計)を返すユーザー定義関数を作成できます。

たとえば、次の場所でユーザー定義関数を使用できます。

ユーザー定義関数をOracle CQL問合せで使用できるようにするには、ユーザー定義関数の実装クラスが含まれたJARファイルをOracle Event Processingサーバー・クラスパスに配置するか、JARファイルを含めるようにOracle Event Processingサーバー・クラスパスを変更する必要があります。

詳細は、次を参照してください。

13.1.1 ユーザー定義関数の種類

oracle.cep.extensibility.functionsパッケージのクラスを使用すると、次の種類のユーザー定義関数を作成できます。

オーバーロード関数の作成、および組込み関数のオーバーライドができます。

13.1.1.1 ユーザー定義単一行関数

単一行ユーザー定義関数は、問合せのストリームまたはビューの各行ごとに単一の結果行を返す関数(たとえば、concat組込み関数のような動作です)。

詳細は、「ユーザー定義の単一行関数の実装方法」を参照してください。

13.1.1.2 ユーザー定義集計関数

ユーザー定義集計は、com.bea.wlevs.processor.AggregationFunctionFactoryを実装し、単一のタプルのかわりにタプルのグループに基づいて単一の集計結果を返す関数(たとえば、sum組込み関数のような動作です)。

可能な場合は、増分処理を行うように集計関数を実装することを検討します。これにより、新しいイベントの到着時の(再)計算コストがこれまでのイベントの合計数ではなく新しいイベントの数に比例するようになるため、スケーラビリティとパフォーマンスが向上します。

詳細は、「ユーザー定義の集計関数の実装方法」を参照してください。

13.1.2 ユーザー定義関数のデータ型

ユーザー定義関数では、2.1.1項「Oracle CQL組込みデータ型」で示されている組込みOracle CQLデータ型をすべてサポートします。Oracle CQLデータ型とそれらに相当するJavaのデータ型のリストは、その項の表を参照してください。

そこに示されているOracle CQLデータ型は、ユーザー定義の関数を登録するために使用するOracle CQL文で指定できるデータ型です。Javaの等価のデータ型は、ユーザー定義の関数の実装で使用できるJavaデータ型です。

実行時、Oracle Event ProcessingではOracle CQLデータ型とJavaデータ型の間のマッピングを行います。ユーザー定義関数でリストにないデータ型が返された場合は、Oracle Event ProcessingでClassCastExceptionがスローされます。

データ変換の詳細は、2.2.4項「データ型変換」を参照してください。

13.1.3 ユーザー定義関数とOracle Event Processingサーバー・キャッシュ

Oracle CQL文またはユーザー定義関数からOracle Event Processingキャッシュにアクセスできます。

詳細は、次を参照してください。

  • 『Oracle Fusion Middleware Oracle Event Processing開発者ガイドfor Eclipse』のOracle Event Processingキャッシュの構成に関する項

  • 『Oracle Fusion Middleware Oracle Event Processing開発者ガイドfor Eclipse』のOracle CQL文からのキャッシュへのアクセスに関する項

  • 『Oracle Fusion Middleware Oracle Event Processing開発者ガイドfor Eclipse』のOracle CQLユーザー定義関数からのキャッシュへのアクセスに関する項

13.2 ユーザー定義関数の実装

この項の内容は、次のとおりです。

詳細は、13.1項「Oracle CQLのユーザー定義関数の概要」を参照してください。

13.2.1 ユーザー定義の単一行関数の実装方法

ユーザー定義の単一行関数を実装するには、関数を実行するために呼び出すpublicコンストラクタとpublicメソッドを提供するJavaクラスを実装します。

ユーザー定義の単一行関数を実装するには:

  1. 例13-1に示すように、Javaクラスを実装します。

    13.1.2項「ユーザー定義関数のデータ型」に説明されているように、戻り値のデータ型がサポートされているデータ型に対応していることを確認します。

    ユーザー定義関数からOracle Event Processingキャッシュへのアクセスの詳細は、13.1.3項「ユーザー定義関数とOracle Event Processingサーバー・キャッシュ」を参照してください。

    例13-1 MyMod.javaユーザー定義単一行関数

    package com.bea.wlevs.example.function;
    
    public class MyMod {
        public Object execute(int arg0, int arg1) {
            return new Integer(arg0 % arg1);
        }
    }
    
  2. ユーザー定義関数のJava実装クラスをコンパイルし、例13-2に示すように、Oracle Event Processingアプリケーション・アセンブリ・ファイルでクラスを登録します。

    例13-2 Oracle CQLプロセッサのための単一行ユーザー定義関数

    <wlevs:processor id="testProcessor">
        <wlevs:listener ref="providerCache"/>
        <wlevs:listener ref="outputCache"/>
        <wlevs:cache-source ref="testCache"/>
        <wlevs:function function-name="mymod" exec-method=”execute” />
            <bean class="com.bea.wlevs.example.function.MyMod"/>
        </wlevs:function>
    </wlevs:processor>
    

    wlevs:function要素のexec-method属性を使用して、関数を実行するために呼び出すメソッドを指定します。このメソッドはpublicで、名前によって一意に識別できる必要があります(メソッドがオーバーライドされないように)。

    詳細は、『Oracle Fusion Middleware Oracle Event Processing開発者ガイドfor Eclipse』のwlevs:functionに関する項を参照してください。

  3. 例13-3に示すように、SELECT文のselectリストまたはWHERE句の条件でユーザー定義関数を呼び出します。

    例13-3 Oracle CQLでのユーザー定義単一行関数へのアクセス

    ...
    <view id="v1" schema="c1 c2 c3 c4"><![CDATA[ 
        select
            mymod(c1, 100), c2, c3, c4 
        from 
            S1
    ]]></view>
    ...
    <query id="q1"><![CDATA[ 
        select * from v1 [partition by c1 rows 1] where c4 - c3 = 2.3 
    ]]></query>
    ...
    

13.2.2 ユーザー定義の集計関数の実装方法

ユーザー定義の集計関数を実装するには、com.bea.wlevs.processor.AggregationFunctionFactoryインタフェースを実装するJavaクラスを実装します。

ユーザー定義の集計関数を実装するには:

  1. 例13-4に示すように、Javaクラスを実装します。

    可能な場合は、増分処理を行うように集計関数を実装することを検討します。これにより、新しいイベントの到着時の(再)計算コストがこれまでのイベントの合計数ではなく新しいイベントの数に比例するようになるため、スケーラビリティとパフォーマンスが向上します。例13-4のユーザー定義集計関数では増分処理がサポートされています。

    13.1.2項「ユーザー定義関数のデータ型」に説明されているように、戻り値のデータ型がサポートされているデータ型に対応していることを確認します。

    ユーザー定義関数からOracle Event Processingキャッシュへのアクセスの詳細は、13.1.3項「ユーザー定義関数とOracle Event Processingサーバー・キャッシュ」を参照してください。

    例13-4 Variance.javaユーザー定義集計関数

    package com.bea.wlevs.test.functions;
     
    import com.bea.wlevs.processor.AggregationFunction;
    import com.bea.wlevs.processor.AggregationFunctionFactory;
     
    public class Variance implements AggregationFunctionFactory, AggregationFunction {
     
        private int count;
        private float sum;
        private float sumSquare;
     
        public Class<?>[] getArgumentTypes() {
            return new Class<?>[] {Integer.class};
        }
     
        public Class<?> getReturnType() {
            return Float.class;
        }
     
        public AggregationFunction newAggregationFunction() {
            return new Variance();
        }
     
        public void releaseAggregationFunction(AggregationFunction function) {
        }
     
        public Object handleMinus(Object[] params) {
            if (params != null && params.length == 1) {
                Integer param = (Integer) params[0];
                count--;
                sum -= param;
                sumSquare -= (param * param);
            }
            
            if (count == 0) {
                return null;
            } else {
                return getVariance();
            }
        }
     
        public Object handlePlus(Object[] params) {
            if (params != null && params.length == 1) {
                Integer param = (Integer) params[0];
                count++;
                sum += param;
                sumSquare += (param * param);
            }
            
            if (count == 0) {
                return null;
            } else {
                return getVariance();
            }
        }
     
        public Float getVariance() {
            float avg = sum / (float) count;
            float avgSqr = avg * avg;
            float var = sumSquare / (float)count - avgSqr;
            return var;
        }
     
        public void initialize() {
            count = 0;
            sum = 0.0F;
            sumSquare = 0.0F;
        }
     
    }
    
  2. ユーザー定義関数のJava実装クラスをコンパイルし、例13-5に示すように、Oracle Event Processingアプリケーション・アセンブリ・ファイルでクラスを登録します。

    例13-5 Oracle CQLプロセッサのための集計ユーザー定義関数

      <wlevs:processor id="testProcessor">
         <wlevs:listener ref="providerCache"/>
         <wlevs:listener ref="outputCache"/>
         <wlevs:cache-source ref="testCache"/>
         <wlevs:function function-name="var">
           <bean class="com.bea.wlevs.test.functions.Variance"/>
         </wlevs:function>
       </wlevs:processor>
    

    詳細は、『Oracle Fusion Middleware Oracle Event Processing開発者ガイドfor Eclipse』のwlevs:functionに関する項を参照してください。

  3. 例13-6に示すように、SELECT文のselectリストまたはWHERE句の条件でユーザー定義関数を呼び出します。

    例13-6 Oracle CQLでのユーザー定義集計関数へのアクセス

    ...
    <query id="uda6"><![CDATA[ 
        select var(c2) from S4[range 3] 
    ]]></query>
    ...
    

    実行時、ユーザー定義の集計が実行され、該当するウィンドウで新しいイベントがアクティブになった場合は集計を再計算する必要があります(集計が定義されているセットに新しいメンバーが追加されたため)。これを行うため、Oracle Event Processingでは例13-4の適切なhandlePlus*メソッドを呼び出して、(アクティブなセット全体のかわりに)新しいイベントのみを適切なハンドラ・コンテキストに渡します。新しいイベントを含めるようにこの状態を更新できるようになります。このようにして、増分的な方法で集計が再計算されます。

    同様に、該当するウィンドウのイベントが期限切れになった場合は集計を再計算する必要があります(集計が定義されているセットからメンバーが失われたため)。これを行うため、Oracle Event Processingでは例13-4の適切なhandleMinusメソッドを呼び出して、(アクティブなセット全体のかわりに)期限切れのイベントのみを適切なハンドラ・コンテキストに渡します。ここでも、増分的な方法でイベントの期限切れに対応するように、ハンドラ・コンテキストの状態を増分的に更新できます。