13 ユーザー定義関数
Oracle Continuous Query Language (Oracle CQL)で使用するユーザー定義関数を記述して、組込み関数を使用する場合よりも高度な操作やアプリケーション固有の操作をストリーム・データに対して実行する方法について説明します。
詳細は、「関数」を参照してください。
13.1 Oracle CQLのユーザー定義関数の概要
ユーザー定義関数をJavaで作成し、Oracle CQLやOracle CQL組込み関数には用意されていない機能を提供できます。集計値または単一値(非集計)を返すユーザー定義関数を作成できます。
たとえば、次の場所でユーザー定義関数を使用できます。
-
SELECT
文のselectリスト -
WHERE
句の条件
注意:
ユーザー定義のウィンドウを作成することもできます(「ユーザー定義のストリームからリレーションへのウィンドウ演算子」を参照)。
ユーザー定義関数をOracle CQL問合せで使用できるようにするには、ユーザー定義関数の実装クラスが含まれたJARファイルをOracle Event Processingサーバー・クラス・パスに配置するか、JARファイルを含めるようにOracle Event Processingサーバー・クラス・パスを変更する必要があります。
詳細については、以下を参照:
13.1.1 ユーザー定義関数の種類
13.1.1.1 ユーザー定義単一行関数
単一行ユーザー定義関数は、問合せのストリームまたはビューの各行ごとに単一の結果行を返す関数(たとえば、concat
組込み関数のような動作です)。
詳細は、「ユーザー定義単一行関数の実装方法」を参照してください。
13.1.1.2 ユーザー定義集計関数
ユーザー定義集計は、com.bea.wlevs.processor.AggregationFunctionFactory
を実装し、単一のタプルのかわりにタプルのグループに基づいて単一の集計結果を返す関数(たとえば、sum
組込み関数のような動作です)。
可能な場合は、増分処理を行うように集計関数を実装することを検討します。これにより、新しいイベントの到着時の(再)計算コストがこれまでのイベントの合計数ではなく新しいイベントの数に比例するようになるため、スケーラビリティとパフォーマンスが向上します。
詳細は、「ユーザー定義集計関数の実装方法」を参照してください。
13.1.2 ユーザー定義関数のデータ型
ユーザー定義関数では、「Oracle CQL組込みデータ型」のリストに示されている組込みOracle CQLデータ型をすべてサポートします。Oracle CQLデータ型とそれらに相当するJavaのデータ型のリストは、その項の表を参照してください。
そこに示されているOracle CQLデータ型は、ユーザー定義関数の登録に使用するOracle CQL文で指定できるデータ型です。Javaの等価のデータ型は、ユーザー定義の関数の実装で使用できるJavaデータ型です。
実行時、Oracle Event ProcessingによりOracle CQLデータ型とJavaの同等のデータ型との間でマッピングが行われます。ユーザー定義関数でリストにないデータ型が返された場合は、Oracle Event ProcessingによりClassCastException
がスローされます。
データ変換の詳細は、「データ型変換」を参照してください。
13.2 ユーザー定義関数の実装
13.2.1 ユーザー定義の単一行関数の実装方法
ユーザー定義の単一行関数を実装するには、関数を実行するために呼び出すpublicコンストラクタとpublicメソッドを提供するJavaクラスを実装します。
ユーザー定義の単一行関数を実装するには:
13.2.2 ユーザー定義の集計関数の実装方法
ユーザー定義の集計関数を実装するには、com.bea.wlevs.processor.AggregationFunctionFactory
インタフェースを実装するJavaクラスを実装します。
ユーザー定義の集計関数を実装するには:
-
後述の例に示すように、Javaクラスを実装します。
可能な場合は、増分処理を行うように集計関数を実装することを検討します。これにより、新しいイベントの到着時の(再)計算コストがこれまでのイベントの合計数ではなく新しいイベントの数に比例するようになるため、スケーラビリティとパフォーマンスが向上します。ユーザー定義集計関数では増分処理がサポートされています。
「ユーザー定義関数のデータ型」に説明されているように、戻り値のデータ型がサポートされているデータ型に対応していることを確認します。
ユーザー定義関数からOracle Event Processingキャッシュへのアクセスの詳細は、「ユーザー定義関数とOracle Event Processingサーバー・キャッシュ」を参照してください。
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; } }
-
ユーザー定義関数のJava実装クラスをコンパイルして、Oracle Event Processingアプリケーション・アセンブリ・ファイルでクラスを登録します。
<wlevs:processor id="testProcessor"> <wlevs:listener ref="providerCache"/> <wlevs:listener ref="outputCache"/> <wlevs:cache-source ref="testCache"/> <wlevs:function function-name="var" is-incremental="true"> <bean class="com.bea.wlevs.test.functions.Variance"/> </wlevs:function> </wlevs:processor>
関数の要素の
is-incremental
属性をtrue
に設定して、ユーザー定義関数var
が増分実装を持つことを示す必要があります。is-incremental
関数をtrue
に設定すると、Oracle Event Processingが現在の処理ウィンドウからイベントをパージするときにhandleMinus
メソッドを呼び出すことが保証されます。この属性をfalse
(デフォルト)に設定すると、handleMinus
関数は呼び出されず、かわりにhandlePlus
メソッドの呼出しごとにOracle Event Processingによって現在のウィンドウのイベントの完全なセットが提供されます。 -
SELECT
文のselectリストまたはWHERE
句の条件でユーザー定義関数を呼び出します。... <query id="uda6"><![CDATA[ select var(c2) from S4[range 3] ]]></query> ...
実行時、ユーザー定義の集計が実行され、該当するウィンドウで新しいイベントがアクティブになった場合は集計を再計算する必要があります(集計が定義されているセットに新しいメンバーが追加されたため)。これを行うため、Oracle Event Processingでは適切な
handlePlus*
メソッドを呼び出して、(アクティブなセット全体のかわりに)新しいイベントのみを適切なハンドラ・コンテキストに渡します。新しいイベントを含めるようにこの状態を更新できるようになります。このようにして、増分的な方法で集計が再計算されます。同様に、該当するウィンドウのイベントが期限切れになった場合は集計を再計算する必要があります(集計が定義されているセットからメンバーが失われたため)。これを行うため、Oracle Event Processingでは適切な
handleMinus
メソッドを呼び出して、(アクティブなセット全体のかわりに)期限切れのイベントのみを適切なハンドラ・コンテキストに渡します。ここでも、増分的な方法でイベントの期限切れに対応するように、ハンドラ・コンテキストの状態を増分的に更新できます。