9.2 ユーザー定義関数と集計
RDFグラフ問合せの拡張アーキテクチャによって、ユーザー定義の関数と集計を追加して、SPARQL問合せで使用できます。これには、SEM_MATCH表関数と、support for Apache Jenaが使用されます。
SPARQL 1.1標準には、主に、問合せによって取得されるデータをフィルタ処理して分類するために使用されるいくつかの関数が用意されています。ただし、この標準ではサポートされていない特殊な関数が必要な場合があります。
簡単な例として、特定のタイプに属する値の検索、平方和の値を使用した特定のしきい値よりも大きい値の取得があります。これは、関数を組み合せることで実行することはできますが、この計算を処理する単一の関数があると、問合せをより簡単に短くすることができて有用です。
RDFグラフ問合せの拡張機能によって、独自の問合せ関数と集計を含めることができます。このアーキテクチャにより、次のことが可能になっています。
-
組込みのSPARQL問合せ関数と同様に使用できるカスタム問合せ関数(「ユーザー定義関数のAPIサポート」を参照)
-
組込みのSPARQL集計と同様に使用できるカスタム集計(「ユーザー定義集計のAPIサポート」を参照)
9.2.1 ユーザー定義関数と集計のデータ型
ユーザー定義関数と集計を作成するとき、RDF語句を表現するためにSDO_RDF_TERMオブジェクト型が使用されます。
SDO_RDF_TERMには次の属性があり、RDF_VALUE$表の列に対応しています(これらの属性については、文の表1-5を参照してください)。CTX1属性とFLAGS属性は、将来使用するために予約されており、RDF_VALUE$内に対応する列はありません。
SDO_RDF_TERM( VALUE_TYPE VARCHAR2(10), VALUE_NAME CLOB, VNAME_PREFIX CLOB, VNAME_SUFFIX VARCHAR2(512), LITERAL_TYPE VARCHAR2(1000), LANGUAGE_TYPE VARCHAR2(80), LONG_VALUE CLOB, CTX1 VARCHAR2(4000), FLAGS INTEGER )
SDO_RDF_TERMオブジェクトの作成には、次のコンストラクタが使用可能です。1つ目のコンストラクタは、単一の字句RDF語句文字列から、各属性を移入します。2番目、3番目および4番目のコンストラクタは、個別の属性値を入力として受け取ります。1番目のRDF語句文字列コンストラクタのみが、VNAME_PREFIXとVNAME_SUFFIXの値を設定します。これらの値は、他のコンストラクタによってNULLに初期化されます。
SDO_RDF_TERM ( rdf_term_str VARCHAR2) RETURN SELF; SDO_RDF_TERM ( value_type VARCHAR2, value_name VARCHAR2, literal_type VARCHAR2, language_type VARCHAR2, long_value CLOB) RETURN SELF; SDO_RDF_TERM ( value_type VARCHAR2, value_name VARCHAR2, literal_type VARCHAR2, language_type VARCHAR2, long_value CLOB, ctx1 VARCHAR2) RETURN SELF; SDO_RDF_TERM ( value_type VARCHAR2, value_name VARCHAR2, literal_type VARCHAR2, language_type VARCHAR2, long_value CLOB, ctx1 VARCHAR2, flags INTEGER) RETURN SELF;
SDO_RDF_TERMオブジェクトのリストを格納するために、SDO_RDF_TERM_LIST型が使用され、VARRAY(32767) of SDO_RDF_TERM
として定義されます。
親トピック: ユーザー定義関数と集計
9.2.2 ユーザー定義関数のAPIサポート
ユーザー定義関数は、特定のシグネチャを使用したPL/SQL関数を実装することによって作成され、固有のURIを使用してSPARQL問合せパターンで起動されます。
推論拡張関数コールが正常に実行された後、推論拡張関数で行われた変更を保持するために、コミットが実行されます。pragma autonomous_transaction
を指定することによって、推論拡張関数が自律型として定義した場合、実装ロジックの最後で、コミットまたはロールバックする必要があります。推論エンジンでは、推論グラフの作成時(1ラウンドにつき1回)に、拡張関数を複数回コールする場合があることに注意してください。あるコールのコミットおよびロールバックは、他のコールには影響しません。
9.2.2.1 PL/SQL関数の実装
各ユーザー定義関数は、次の形式のシグネチャを持つPL/SQL関数によって実装される必要があります。
FUNCTION user_function_name (params IN SDO_RDF_TERM_LIST)
RETURN SDO_RDF_TERM
このシグネチャは任意の数のRDF語句引数(単一のSDO_RDF_TERM_LISTオブジェクトを使用する際に渡される)をサポートし、単一のRDF語句(単一のSDO_RDF_TERMオブジェクトとして表現される)を出力として戻します。これらのパラメータの型チェックまたは他の検証は、実行されません。関数の用途に従ってデータを検証するためのステップを実行する必要があります。
CやJavaなど、他のプログラミング言語で記述された関数に対して、PL/SQLからのコールアウトがサポートされているため、ユーザー定義の問合せ関数を実装するPL/SQL関数は、他のプログラミング言語で記述された関数のラッパーとしてのみ機能します。
親トピック: ユーザー定義関数のAPIサポート
9.2.2.2 SPARQL問合せパターンからのユーザー定義関数の起動
これは、ユーザー定義関数がPL/SQLで実装された後、接頭辞<http://xmlns.oracle.com/rdf/extensions/>
の後にschema.package_name.function_name
が続く関数URI(対応するPL/SQL関数がPL/SQLパッケージの一部である場合)、またはschema.function_name
が続く関数URI(関数がPL/SQLパッケージの一部でない場合)を使用して、SPARQL問合せパターンから起動することができます。次の2つは、関数URIの例です。
<http://xmlns.oracle.com/rdf/extensions/my_schema.my_package.my_function>(arg_1, …, arg_n) <http://xmlns.oracle.com/rdf/extensions/my_schema.my_function>(arg_1, …, arg_n)
親トピック: ユーザー定義関数のAPIサポート
9.2.2.3 ユーザー定義関数の例
この項では、ユーザー定義関数の実装例と、その関数のFILTER句、SELECT式およびBIND演算での使用について示します。
たとえば、ここではN-triple形式で示されている次のデータが、MYMODEL
と呼ばれるモデル内に存在しているとします。
<a> <p> "1.0"^^xsd:double . <b> <p> "1.5"^^xsd:float . <c> <p> "3"^^xsd:decimal . <d> <p> "4"^^xsd:string .
例9-1 2つの平方和を計算するユーザー定義関数
例9-1は、2つの値を受け取って各値の平方和を計算する、単純なファンクションの実装を示しています。
CREATE OR REPLACE FUNCTION sum_squares (params IN SDO_RDF_TERM_LIST) RETURN SDO_RDF_TERM AS retTerm SDO_RDF_TERM; sqr1 NUMBER; sqr2 NUMBER; addVal NUMBER; val1 SDO_RDF_TERM; val2 SDO_RDF_TERM; BEGIN –- Set the return value to null. retTerm := SDO_RDF_TERM(NULL,NULL,NULL,NULL,NULL); –- Obtain the data from the first two parameters. val1 := params(1); val2 := params(2); –- Convert the value stored in the sdo_rdf_term to number. –- If any exception occurs, return the null value. BEGIN sqr1 := TO_NUMBER(val1.value_name); sqr2 := TO_NUMBER(val2.value_name); EXCEPTION WHEN OTHERS THEN RETURN retTerm; END; –- Compute the square sum of both values. addVal := (sqr1 * sqr1) + (sqr2 * sqr2); –- Set the return value to the desired rdf term type. retTerm := SDO_RDF_TERM('LIT',to_char(addVal), 'http://www.w3.org/2001/XMLSchema#integer','',NULL); – Return the new value. RETURN retTerm; END; / SHOW ERRORS;
例9-1 sum_squares
ファンクションでは、受け取った値のデータ型を検証しません。これはあくまでも例であり、SDO_RDF_TERMのVALUE_NAMEフィールドに格納されている数値の取得には、TO_NUMBERを使用します。
例9-2 FILTER句で使用されるユーザー定義関数
例9-2は、FILTER句で使用されるsum_squares
ファンクション(例9-1)を示します。
SELECT s, o
FROM table(sem_match(
'SELECT ?s ?o
WHERE { ?s ?p ?o
FILTER (<http://xmlns.oracle.com/rdf/extensions/schema.sum_squares>(?o,?o) > 2)}',
sem_models('MYMODEL'),null,null,null,null,'',null,null,'RDFUSER','NET1'));
例9-2の問合せは、次の結果を戻します。
s o -------------------- -------------------- b 1.5 c 3 d 4
例9-3 SELECT式で使用されるユーザー定義関数
例9-3は、SELECT句の式で使用されるsum_squares
ファンクション(例9-1)を示します。
SELECT s, o, sqr_sum FROM table(sem_match( 'SELECT ?s ?o (<http://xmlns.oracle.com/rdf/extensions/schema.sum_squares>(?o,?o) AS ?sqr_sum) WHERE { ?s ?p ?o }', sem_models('MYMODEL'),null,null,null,null,'',null,null,'RDFUSER','NET1'));
例9-3の問合せは、次の結果を戻します。
s o sqr_sum -------------------- -------------------- -------------------- a 1 2 b 1.5 4.5 c 3 18 d 4 32
例9-4 BIND演算で使用されるユーザー定義関数
例9-4は、BIND演算で使用されるsum_squares
ファンクション(例9-1)を示します。
SELECT s, o, sqr_sum FROM table(sem_match( 'SELECT ?s ?o ?sqr_sum WHERE { ?s ?p ?o . BIND (<http://xmlns.oracle.com/rdf/extensions/schema.sum_squares>(?o,?o) AS ?sqr_sum)}', sem_models('MYMODEL'),null,null,null,null,'',null,null,'RDFUSER','NET1'));
例9-4の問合せは、次の結果を戻します。
s o sqr_sum -------------------- -------------------- -------------------- a 1 2 b 1.5 4.5 c 3 18 d 4 32
親トピック: ユーザー定義関数のAPIサポート
9.2.3 ユーザー定義の集計のAPIサポート
ユーザー定義の集計は、一連のインタフェース・メソッドを実装するPL/SQLオブジェクト型を定義することによって実装されます。ユーザー定義の集計を作成したら、固有のURIを使用してそれを起動します。
9.2.3.1 ODCIAggregateインタフェース
ユーザー定義の集計では、ODCIAggregate
PL/SQLインタフェースを使用します。このインタフェースの詳細は、Oracle Databaseデータ・カートリッジ開発者ガイドのユーザー定義集計関数に関する章を参照してください。
ODCIAggregate
インタフェースは、4つの主要な関数を実装するPL/SQLオブジェクト型によって実装されます。
-
ODCIAggregateInitialize
-
ODCIAggregateIterate
-
ODCIAggregateMerge
-
ODCIAggregateTerminate
ユーザー定義関数(「ユーザー定義関数のAPIサポート」を参照)と同様に、ユーザー定義の集計は、SDO_RDF_TERM_LISTオブジェクトとして渡される任意の数のRDF語句引数を受け取り、SDO_RDF_TERMオブジェクトとして表現される単一のRDF語句の値を返します。
このスキームによって、PL/SQL ODCIAggregate
インタフェース関数のシグネチャは、次のようになります(my_aggregate_obj_typeは実際のオブジェクト・タイプ名)。
STATIC FUNCTION ODCIAggregateInitialize( sctx IN OUT my_aggregate_obj_type) RETURN NUMBER MEMBER FUNCTION ODCIAggregateIterate( self IN OUT my_aggregate_obj_type ,value IN SDO_RDF_TERM_LIST) RETURN NUMBER MEMBER FUNCTION ODCIAggregateMerge( self IN OUT my_aggregate_obj_type ,ctx2 IN my_aggregate_obj_type) RETURN NUMBER MEMBER FUNCTION ODCIAggregateTerminate ( self IN my_aggregate_obj_type ,return_value OUT SDO_RDF_TERM ,flags IN NUMBER) RETURN NUMBER
親トピック: ユーザー定義集計のAPIサポート
9.2.3.2 ユーザー定義の集計の起動
これは、ユーザー定義の集計がPL/SQLで実装された後、接頭辞<http://xmlns.oracle.com/rdf/aggExtensions/>
の後にschema_name.aggregate_name
を続けて構築される集計URIを参照することによって、SPARQL問合せから起動することができます。集計URIの例は次のとおりです。
<http://xmlns.oracle.com/rdf/aggExtensions/schema.my_aggregate>(arg_1, …, arg_n)
DISTINCT修飾子は、ユーザー定義の集計で次の例のように使用できます。
<http://xmlns.oracle.com/rdf/aggExtensions/schema.my_aggregate>(DISTINCT arg_1)
この場合、distinct引数の値のみが集計に渡されます。ただしDISTINCT修飾子は、厳密に1つの引数の集計でのみ使用できることに注意してください。
親トピック: ユーザー定義集計のAPIサポート
9.2.3.3 ユーザー定義の集計の例
この項では、ユーザー定義の集計を実装して使用する例を示します。たとえば、ここではN-triple形式で示されている次のデータが、MYMODEL
と呼ばれるモデル内に存在しているとします。
<a> <p> "1.0"^^xsd:double . <b> <p> "1.5"^^xsd:float . <c> <p> "3"^^xsd:decimal . <c> <p> "4"^^xsd:decimal . <d> <p> "4"^^xsd:string .
例9-5 ユーザー定義の集計の実装
例9-5は、単純なユーザー定義の集計の実装(countSameType
)を示しています。この集計には2つの引数があり、1番目は任意のRDF語句、2番目は定数のデータ型URIです。集計は、1番目の引数の位置からのRDF語句にある、2番目の引数と等しいデータ型の数をカウントします。
-- Aggregate type creation CREATE OR REPLACE TYPE countSameType authid current_user AS OBJECT( count NUMBER, –- Variable to store the number of same-type terms. –- Mandatory Functions for aggregates STATIC FUNCTION ODCIAggregateInitialize( sctx IN OUT countSameType) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateIterate( self IN OUT countSameType , value IN SDO_RDF_TERM_LIST) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateMerge( self IN OUT countSameType ,ctx2 IN countSameType) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateTerminate ( self IN countSameType ,return_value OUT SDO_RDF_TERM ,flags IN NUMBER) RETURN NUMBER ); / SHOW ERRORS; –- Interface function for the user-defined aggregate CREATE OR REPLACE FUNCTION countSameAs (input SDO_RDF_TERM_LIST) RETURN SDO_RDF_TERM PARALLEL_ENABLE AGGREGATE USING countSameType; / show errors; –- User-defined aggregate body CREATE OR REPLACE TYPE BODY countSameType IS STATIC FUNCTION ODCIAggregateInitialize( sctx IN OUT countSameType) RETURN NUMBER IS BEGIN sctx := countSameType (0); –- Aggregate initialization RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateIterate( self IN OUT countSameType , value IN SDO_RDF_TERM_LIST ) RETURN NUMBER IS BEGIN -- Increment count if the first argument has a literal type -- URI equal to the value of the second argument IF (value(1).literal_type = value(2).value_name) THEN self.count := self.count + 1; END IF; RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateMerge( self IN OUT countSameType ,ctx2 IN countSameType) RETURN NUMBER IS BEGIN –- Sum count to merge parallel threads. self.count := self.count + ctx2.count; RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateTerminate( self IN countSameType ,return_value OUT SDO_RDF_TERM ,flags IN NUMBER) RETURN NUMBER IS BEGIN -- Set the return value return_value := SDO_RDF_TERM('LIT',to_char(self.count), 'http://www.w3.org/2001/XMLSchema#decimal',NULL,NULL); RETURN ODCIConst.Success; END; END; / SHOW ERRORS;
例9-6 GROUP BY句なしで使用されるユーザー定義の集計
例9-6は、問合せ結果のすべてのグループに使用されるcountSameType
集計(例9-5)を示しています。
FROM o
from table(sem_match(
'SELECT
(<http://xmlns.oracle.com/rdf/aggExtensions/schema.countSameType>(?o,xsd:decimal)
AS ?o)
WHERE { ?s ?p ?o }',
sem_models('MYMODEL'),null,null,null,null,'',null,null,'RDFUSER','NET1'));
例9-6の問合せは、次の結果を戻します。
o -------------------- 2
例9-7 GROUP BY句とともに使用されるユーザー定義の集計
例9-7は、GROUP BY句から形成される一連のグループに使用されるcountSameType
集計(例9-5)を示しています。
select s, o from table(sem_match( 'SELECT ?s (<http://xmlns.oracle.com/rdf/aggExtensions/schema.countSameType>(?o,xsd:decimal) AS ?o) WHERE { ?s ?p ?o } GROUP BY ?s', sem_models('MYMODEL'),null,null,null,null,'',null,null,'RDFUSER','NET1'));
例9-7の問合せは、次の結果を戻します。
s o -------------------- -------------------- a 0 b 0 c 2 d 0
親トピック: ユーザー定義集計のAPIサポート