ユーザー定義関数を使用して、組込み関数を使用する場合よりも高度な操作やアプリケーション固有の操作をストリーム・データに対して実行します。
詳細は、1.1.11項「関数」を参照してください。
ユーザー定義関数をJavaで作成し、Oracle CQLやOracle CQL組み込み関数には用意されていない機能を提供できます。集計値または単一値(非集計)を返すユーザー定義関数を作成できます。
たとえば、次の場所でユーザー定義関数を使用できます。
SELECT
文のselectリスト
WHERE
句の条件
ユーザー定義関数をOracle CQL問合せで使用できるようにするには、ユーザー定義関数の実装クラスが含まれたJARファイルをOracle CEPサーバー・クラスパスに配置するか、JARファイルを含めるようにOracle CEPサーバー・クラスパスを変更する必要があります。
詳細は、以下を参照してください。
oracle.cep.extensibility.functions
パッケージのクラスを使用すると、次の種類のユーザー定義関数を作成できます。
単一行: 問合せのストリームまたはビューの各行ごとに単一の結果行を返す関数(たとえば、concat
組込み関数のような動作です)。
詳細は、「ユーザー定義の単一行関数の実装方法」を参照してください。
集計: com.bea.wlevs.processor.AggregationFunctionFactory
を実装し、単一のタプルのかわりにタプルのグループに基づいて単一の集計結果を返す関数(たとえば、sum
組込み関数のような動作です)。
可能な場合は、増分処理を行うように集計関数を実装することを検討します。これにより、新しいイベントの到着時の(再)計算コストがこれまでのイベントの合計数ではなく新しいイベントの数に比例するようになるため、スケーラビリティとパフォーマンスが向上します。
詳細は、「ユーザー定義の集計関数の実装方法」を参照してください。
表13-1に、ユーザー定義関数の実装および登録で指定できるデータ型を示します。
表13-1 ユーザー定義関数のデータ型
Oracle CQLデータ型 | 同等のJavaデータ型 |
---|---|
|
|
|
|
|
|
|
|
|
|
Oracle CQLデータ型の列は、ユーザー定義関数の登録に使用するOracle CQL文で指定できるデータ型を示します。同等のJavaデータ型の列は、ユーザー定義関数の実装で使用できる同等のJavaデータ型を示します。
実行時、Oracle CEPではOracle CQLデータ型とJavaデータ型の間のマッピングを行います。ユーザー定義関数でリストにないデータ型が返された場合は、Oracle CEPでClassCastException
がスローされます。
データ変換の詳細は、2.3.4項「データ型変換」を参照してください。
詳細は、13.1項「Oracle CQLのユーザー定義関数の概要」を参照してください。
ユーザー定義の単一行関数を実装するには、関数を実行するために呼び出すpublicコンストラクタとpublicメソッドを提供するJavaクラスを実装します。
ユーザー定義の単一行関数を実装するには:
例13-1に示すように、Javaクラスを実装します。
13.1.2項「ユーザー定義関数のデータ型」に示すように、戻り値のデータ型がサポートされているデータ型に対応していることを確認します。
ユーザー定義関数からのOracle CQLキャッシュへのアクセスの詳細は、13.1.3項「ユーザー定義関数とOracle CEPサーバー・キャッシュ」を参照してください。
ユーザー定義関数のJava実装クラスをコンパイルし、例13-2に示すように、Oracle CEPアプリケーション・アセンブリ・ファイルでクラスを登録します。
例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で、名前によって一意に識別できる必要があります(メソッドがオーバーライドされないように)。
例13-3に示すように、SELECT
文のselectリストまたはWHERE
句の条件でユーザー定義関数を呼び出します。
ユーザー定義の集計関数を実装するには、com.bea.wlevs.processor.AggregationFunctionFactory
インタフェースを実装するJavaクラスを実装します。
ユーザー定義の集計関数を実装するには:
例13-4に示すように、Javaクラスを実装します。
可能な場合は、増分処理を行うように集計関数を実装することを検討します。これにより、新しいイベントの到着時の(再)計算コストがこれまでのイベントの合計数ではなく新しいイベントの数に比例するようになるため、スケーラビリティとパフォーマンスが向上します。例13-4のユーザー定義集計関数では増分処理がサポートされています。
13.1.2項「ユーザー定義関数のデータ型」に説明されているように、戻り値のデータ型がサポートされているデータ型に対応していることを確認します。
ユーザー定義関数からのOracle CQLキャッシュへのアクセスの詳細は、13.1.3項「ユーザー定義関数とOracle CEPサーバー・キャッシュ」を参照してください。
例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; } }
ユーザー定義関数のJava実装クラスをコンパイルし、例13-5に示すように、Oracle CEPアプリケーション・アセンブリ・ファイルでクラスを登録します。
例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>
例13-6に示すように、SELECT
文のselectリストまたはWHERE
句の条件でユーザー定義関数を呼び出します。
例13-6 Oracle CQLでのユーザー定義集計関数へのアクセス
... <query id="uda6"><![CDATA[ select var(c2) from S4[range 3] ]]></query> ...
実行時、ユーザー定義の集計が実行され、該当するウィンドウで新しいイベントがアクティブになった場合は集計を再計算する必要があります(集計が定義されているセットに新しいメンバーが追加されたため)。これを行うため、Oracle CEPでは適切なhandlePlus*
メソッドを呼び出して、(アクティブなセット全体のかわりに)新しいイベントのみを適切なハンドラ・コンテキストに渡します(例13-4を参照)。新しいイベントを含めるようにこの状態を更新できるようになります。このようにして、増分的な方法で集計が再計算されます。
同様に、該当するウィンドウのイベントが期限切れになった場合は集計を再計算する必要があります(集計が定義されているセットからメンバーが失われたため)。これを行うため、Oracle CEPでは適切なhandleMinus
メソッドを呼び出して、(アクティブなセット全体のかわりに)期限切れのイベントのみを適切なハンドラ・コンテキストに渡します(例13-4を参照)。ここでも、増分的な方法でイベントの期限切れに対応するように、ハンドラ・コンテキストの状態を増分的に更新できます。