ヘッダーをスキップ
Oracle® CEP CQL 言語リファレンス
11g リリース 1 (11.1.1)
B55504-01
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

10 関数 : ユーザ定義

ユーザ定義関数を使用して、組み込み関数に不足している、より高度な操作やアプリケーション固有の操作をストリーム データに対して実行します。

詳細については、節 1.1.9「関数」を参照してください。

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

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

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

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

詳細については、以下を参照してください。

10.1.1 ユーザ定義関数の種類

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

  • 単一行 : クエリのストリームまたはビューの各行ごとに単一の結果行を返す関数 (たとえば、CONCAT 組み込み関数のような動作です)。

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

  • 集約 : com.bea.wlevs.processor.AggregationFunctionFactory を実装し、単一のタプルの代わりにタプルのグループに基づいて単一の集約結果を返す関数 (たとえば、SUM 組み込み関数のような動作です)。

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

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

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

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

表 10-1 は、ユーザ定義関数の実装および登録で指定できるデータ型を示しています。

表 10-1 ユーザ定義関数のデータ型

Oracle CQL データ型 同等の Java データ型

int

java.lang.Integer

bigint

java.lang.Long

float

java.lang.Float

double

java.lang.Double

char

java.lang.String


Oracle CQL データ型の列は、ユーザ定義関数の登録に使用する Oracle CQL 文で指定できるデータ型を示します。同等の Java データ型の列は、ユーザ定義関数の実装で使用できる同等の Java データ型を示します。

実行時、Oracle CEP では Oracle CQL データ型と Java データ型の間のマッピングを行います。ユーザ定義関数で一覧にないデータ型が返された場合は、Oracle CEP で ClassCastException が送出されます。

データ変換の詳細については、節 2.3.4「データ変換」を参照してください。

10.1.3 ユーザ定義関数と Oracle CEP サーバ キャッシュ

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

詳細については、以下を参照してください。

10.2 ユーザ定義関数の実装

この節では、以下について説明します。

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

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

ユーザ定義の単一行関数を実装するには、SingleElementFunction インタフェースを実装する Java クラスを実装します。

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

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

    例 10-1 に示すように、戻り値のデータ型が register function 文の戻り値の型に対応していることを確認します。

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

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

    例 10-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>
    

    詳細については、『Oracle CEP IDE Eclipse 開発者ガイド』の「wlevs:function」を参照してください。

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

    例 10-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>
    ...
    

10.2.2 ユーザ定義の集約関数の実装方法

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

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

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

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

    例 10-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 実装クラスをコンパイルし、例 10-5 に示すように、Oracle CEP アプリケーション アセンブリ ファイルでクラスを登録します。

    例 10-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 CEP IDE Eclipse 開発者ガイド』の「wlevs:function」を参照してください。

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

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

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

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

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