CREATE FUNCTION および CREATE PROCEDURE ステートメントは、呼び出し可能な関数またはプロシージャー (普通はルーチンという) を定義します。
CREATE FUNCTION および CREATE PROCEDURE ステートメントは、呼び出し可能な関数またはプロシージャー (普通はルーチンという) を定義します。
ルーチンは、個別に複数回実行できる再使用可能なコード・ブロックを作成するのに便利です。一連の ESQL ステートメント、Java メソッド、またはデータベース・ストアード・プロシージャーとしてルーチンをインプリメントできます。このような柔軟性があるので、構文図の文節の中には、ルーチンのタイプによっては適用されない (または許可されない) ものがあります。
個々のルーチンには名前があり、この名前はそのルーチンが属するスキーマ内で固有でなければなりません。したがって、ルーチン名は多重定義できません。ルーチンが多重定義であることをブローカーが検出すると、例外が生じます。
RoutineName 文節を使用してルーチンの名前を指定し、ParameterList 文節を使用してルーチンのパラメーターを指定してください。LANGUAGE 文節で ESQL を指定している場合、単一の ESQL ステートメントを使用してルーチンをインプリメントしなければなりません。このステートメントは複合ステートメント (BEGIN ... END) の場合に最も便利です。なぜなら、後で必要な数だけ ESQL ステートメントを組み込んで、その機能を実現できるからです。
ルーチンに ESQL 本体を提供する代わりに、ESQL 以外の LANGUAGE 文節を指定することもできます。この場合、ルーチンの実際の本体がブローカーの外部のどの場所にあっても、EXTERNAL NAME 文節を使用してその本体に対する参照を提供できます。EXTERNAL NAME 文節の使用法について詳しくは、ストアード・プロシージャーの呼び出し、および『Java ルーチンの呼び出し』を参照してください。
LANGUAGE タイプのルーチンに IN、OUT、および INOUT パラメーターを指定できます。指定すると、呼び出し元がルーチンに複数の値を渡したり、複数の更新された値を戻して受け取ったりできます。これらのパラメーターは、ルーチンに指定できる RETURNS 文節に追加します。RETURNS 文節を使用すると、ルーチンが値を呼び出し元に戻すことができます。
さまざまな言語でインプリメントされるルーチンには、データ・タイプを渡したり戻したりする上での独自の制約事項があり、これらの制限については後述されています。戻り値のデータ・タイプは、ルーチンから戻されるように定義された値のデータ・タイプと一致していなければなりません。また、ルーチンが戻り値を持つように定義されている場合は、ルーチンの呼び出し元はその値を無視できません。詳細については、CALL ステートメントを参照してください。
言語またはルーチン・タイプの場合、ルーチンを起動する方式は、ルーチンを宣言する方法と一致していなければなりません。ルーチンに RETURNS 文節がある場合は、FUNCTION 起動構文か、INTO 文節を指定した CALL ステートメントを使用してください。逆に、ルーチンに RETURNS 文節がない場合は、INTO 文節を指定せずに CALL ステートメントを使用しなければなりません。
ルーチンのタイプが FUNCTION の場合、方向標識 (IN、OUT、INOUT) はパラメーターごとにオプションです。しかし、文書化の目的上、タイプにかかわらず新しいルーチンすべてに方向標識を指定することは適切なプログラミング手法です。
CONSTANT と宣言される ESQL 変数 (または CONSTANT と宣言される変数の参照) は、方向として OUT または INOUT を持つことはできません。
ESQL ルーチンは ESQL で書かれていて、LANGUAGE 文節として ESQL があります。ESQL ルーチンの本体は、普通は BEGIN …END 形式の複合ステートメントで、ルーチンに渡されるパラメーターの処理用のステートメントが複数含まれています。
CREATE PROCEDURE swapParms ( IN parm1 CHARACTER, OUT parm2 CHARACTER, INOUT parm3 CHARACTER ) BEGIN SET parm2 = parm3; SET parm3 = parm1; END;
この例のプロシージャーでは、ESQL ルーチンの再帰的使用が示されています。この例は、ツリーを解析し、指定された開始点とそれより下のすべての場所を訪問し、それが見つけたものを報告します。
SET OutputRoot.MQMD = InputRoot.MQMD; DECLARE answer CHARACTER; SET answer = ''; CALL navigate(InputRoot.XML, answer); SET OutputRoot.XML.Data.FieldNames = answer; CREATE PROCEDURE navigate (IN root REFERENCE, INOUT answer CHARACTER) BEGIN SET answer = answer || 'Reached Field... Type:' || CAST(FIELDTYPE(root) AS CHAR)|| ': Name:' || FIELDNAME(root) || ': Value :' || root || ': '; DECLARE cursor REFERENCE TO root; MOVE cursor FIRSTCHILD; IF LASTMOVE(cursor) THEN SET answer = answer || 'Field has children... drilling down '; ELSE SET answer = answer || 'Listing siblings... '; END IF; WHILE LASTMOVE(cursor) DO CALL navigate(cursor, answer); MOVE cursor NEXTSIBLING; END WHILE; SET answer = answer || 'Finished siblings... Popping up '; END;
次の入力メッセージを与えた場合、
<Person> <Name>John Smith</Name> <Salary period='monthly' taxable='yes'>-1200</Salary> </Person>
プロシージャーは次の出力を生成します。この出力は手操作でフォーマット設定されています。
Reached Field... Type:16777232: Name:XML: Value :: Field has children... drilling down Reached Field... Type:16777216: Name:Person: Value :: Field has children... drilling down Reached Field... Type:16777216: Name:Name: Value :John Smith: Field has children... drilling down Reached Field... Type:33554432: Name:: Value :John Smith: Listing siblings... Finished siblings... Popping up Finished siblings... Popping up Reached Field... Type:16777216: Name:Salary: Value :-1200: Field has children... drilling down Reached Field... Type:50331648: Name:period: Value :monthly: Listing siblings... Finished siblings... Popping up Reached Field... Type:50331648: Name:taxable: Value :yes: Listing siblings... Finished siblings... Popping up Reached Field... Type:33554432: Name:: Value :-1200: Listing siblings... Finished siblings... Popping up Finished siblings... Popping up Finished siblings... Popping up Finished siblings... Popping up
>>--"-- className---.---methodName--"--------------><className はメソッドを含むクラスを識別し、methodName は起動されるメソッドを識別します。クラスがパッケージの一部である場合、クラス ID 部分には、完全なパッケージ接頭部を含める必要があります。例えば、"com.ibm.broker.test.MyClass.myMethod" のようにします。
Java クラスを検出するために、ブローカーは、Java クラスのデプロイで説明されているようにして検索を実行します。
public static <return-type> <method-name> (< 0 - N parameters>)
<return-type> は、ESQL から Java データ・タイプへのマッピングの表にある Java IN データ・タイプのリストに含まれるもの (ただし戻り値として許可されていない REFERENCE タイプを除く)、または Java void データ・タイプでなければなりません。また、パラメーター・データ・タイプは、ESQL から Java データ・タイプへのマッピングの表に含まれるものでなければなりません。さらに、Java メソッドのシグニチャーとして exception throws 文節は使用できません。
Java メソッド内で Java ユーザー定義ノード (UDN) API を使用できますが、Java ルーチンに関する制約事項に文書化された制限を遵守した場合に限られます。 UDN API の使用の詳細については、Java ユーザー定義ノードのコンパイルを参照してください。
このルーチンには方向の違う 3 つのパラメーターが含まれており、Java 戻りタイプ java.lang.Long にマップする整数を戻します。
CREATE FUNCTION myProc1( IN P1 INTEGER, OUT P2 INTEGER, INOUT P3 INTEGER ) RETURNS INTEGER LANGUAGE JAVA EXTERNAL NAME "com.ibm.broker.test.MyClass.myMethod1";
次の ESQL を使用して、myProc1 を起動できます。
CALL myProc1( intVar1, intVar2, intVar3) INTO intReturnVar3; -- or SET intReturnVar3 = myProc1( intVar1, intVar2, intVar3);
このルーチンには方向の違う 3 つのパラメーターが含まれており、Java 戻りタイプ void があります。
CREATE PROCEDURE myProc2( IN P1 INTEGER, OUT P2 INTEGER, INOUT P3 INTEGER ) LANGUAGE JAVA EXTERNAL NAME "com.ibm.broker.test.MyClass.myMethod2";
次の ESQL を使用して、myProc2 を起動する必要があります。
CALL myProc2(intVar1, intVar2, intVar3);
次の Java クラスでは、前述の Java の例ごとのメソッドが用意されています。
package com.ibm.broker.test; class MyClass { public static Long myMethod1( Long P1, Long[] P2 Long[] P3) { ... } public static void myMethod2( Long P2, Long[] P2 Long[] P3) { ... } /* When either of these methods is called: P1 may or may not be NULL (depending on the value of intVar1). P2[0] is always NULL (whatever the value of intVar2). P3[0] may or may not be NULL (depending on the value of intVar3). This is the same as with LANGUAGE ESQL routines. When these methods return: intVar1 is unchanged intVar2 may still be NULL or may have been changed intVar3 may contain the same value or may have been changed. This is the same as with LANGUAGE ESQL routines. When myMethod1 returns: intReturnVar3 is either NULL (if the method returns NULL) or it contains the value returned by the method. */ }
ESQL データ・タイプ 1 | Java IN データ・タイプ | Java INOUT および OUT データ・タイプ |
INTEGER、INT | java.lang.Long | java.lang.Long [] |
FLOAT | java.lang.Double | java.lang.Double[] |
DECIMAL | java.math.BigDecimal | java.math.BigDecimal[] |
CHARACTER、CHAR | java.lang.String | java.lang.String[] |
BLOB | byte[] | byte[][] |
BIT | java.util.BitSet | java.util.BitSet[] |
DATE | com.ibm.broker.plugin.MbDate | com.ibm.broker.plugin.MbDate[] |
TIME 2 | com.ibm.broker.plugin.MbTime | com.ibm.broker.plugin.MbTime[] |
GMTTIME 2 | com.ibm.broker.plugin.MbTime | com.ibm.broker.plugin.MbTime[] |
TIMESTAMP 2 | com.ibm.broker.plugin.MbTimestamp | com.ibm.broker.plugin.MbTimestamp[] |
GMTTIMESTAMP 2 | com.ibm.broker.plugin.MbTimestamp | com.ibm.broker.plugin.MbTimestamp[] |
INTERVAL | サポートされていない | サポートされていない |
BOOLEAN | java.lang.Boolean | java.lang.Boolean[] |
REFERENCE (メッセージ・ツリーへの) 3 4 5 6 | com.ibm.broker.plugin.MbElement | com.ibm.broker.plugin.MbElement[] (INOUT についてはサポートするが、OUT についてはサポートしない) |
ROW | サポートされていない | サポートされていない |
LIST | サポートされていない | サポートされていない |
例えば、OutputRoot.XML.Test に対する ESQL 参照が、Java メソッドに INOUT MbElement として渡されたが、呼び出しが戻されるときに別の MbElement が ESQL に戻される場合、その別のエレメントも OutputRoot ツリーのいずれかの場所を指していなければなりません。
スカラー変数への REFERENCE を、Java メソッドの CALL の中で使用できます。ただし、参照先の変数のデータ・タイプが、Java プログラムのシグニチャー内の対応するデータ・タイプと一致している場合に限ります。
メソッド内にスレッドを作成することは許可されています。ただし、作成したスレッドは Java プラグイン API を使用してはならず、制御をブローカーに戻す必要があります。
UDN API の使用法に適用されるすべての制限は、ESQL から呼び出された Java メソッドにも適用されることに注意してください。
JAR ファイルを BAR ファイルに追加することは、ブローカーにデプロイするための、最も効率的かつ柔軟な方式といえます。
JAR ファイルを BAR ファイルに追加する方法としては、手動 (手作業)、または自動 (ツールの使用) があります。 ツールは、JAR ファイルを BAR ファイルに追加する最も簡単な方法です。
ワークスペース内に開いている、参照される Java プロジェクト内の適切な Java クラスがツールによって検出されると、ツールは自動的に Java クラスを JAR ファイル内にコンパイルして、それを BAR ファイルに追加します。 これは、ユーザー定義ノードのクラス・ロードで説明されている、JAR 内に Java Compute ノードをデプロイするときの手順と同じです。
ツールから JAR ファイルをデプロイするとき、JAR ファイルを含む BAR ファイルを再デプロイすると、再デプロイされたフローによって、参照される Java クラスが再ロードされます。Java クラスを参照するメッセージ・フローを停止して再始動した場合も、これと同様です。更新対象の JAR ファイルを参照するすべてのフローを、必ず停止および再始動 (または再デプロイ) してください。こうすれば、一部のフローが古いバージョンの JAR ファイルを使って実行され、他のフローが新しいバージョンを使用するという問題を防ぐことができます。
ツールは単に JAR ファイルをデプロイするだけであることに注意してください。独立型の Java クラス・ファイルをデプロイするものではありません。
この手順はツールを使用して実行できないため、手動で行う必要があります。
この方法では、メッセージ・フローを再デプロイしたり、メッセージ・フローを停止/再始動しても、参照される Java クラスは再ロードされません。この場合、クラスを再ロードする唯一の方法は、ブローカー自体を停止および再始動することです。
ブローカーが Java クラスを検出できるようにするには、必ず上記のいずれかの場所に格納してください。ブローカーが指定されたクラスを検出できない場合は、例外をスローします。
JAR ファイルをデプロイするときには上記のような複数の選択肢がありますが、ツールを使って BAR ファイルをデプロイすることにより、JAR ファイルを再デプロイするときに最大の柔軟性が得られます。
データベース・ルーチンとは、データベース・ストアード・プロシージャーとしてインプリメントされたルーチンのことです。データベース・ルーチンには LANGUAGE 文節として DATABASE があり、ルーチン・タイプは PROCEDURE でなければなりません。
ストアード・プロシージャーを C のような言語で書くときには、NULL 標識を使用して、プロシージャーが確実にデータを正しく処理できるようにする必要があります。
ストアード・プロシージャーのデータベース定義はデータベースによって違いますが、それらの定義の起動に使用する ESQL は違いません。ESQL でパラメーターに与えられる名前は、データベース側で与えられる名前と必ずしも一致している必要はありません。しかしながら、ルーチンが持つ外部名は、パッケージまたはコンテナー指定も含めて、データベースで定義された名前と一致している必要があります。
DYNAMIC RESULT SET 文節は、データベース・ルーチン専用です。この分節は、ストアード・プロシージャーが 1 つ以上の結果セットを戻す場合にのみ必要です。この文節に対する integer パラメーターは 0 (ゼロ) 以上でなければならず、戻される結果セットの数を指定します。
オプションの RETURNS 文節は、ストアード・プロシージャーが単一のスカラー値を戻す場合に必要です。
EXTERNAL NAME 文節は、データベースがルーチンの認識に使用する名前を指定します。この名前は、修飾名または非修飾名にすることができます。修飾子とは、プロシージャーが定義されているデータベース・スキーマの名前のことです。スキーマ名を指定しない場合、プロシージャーを探すスキーマとしてデータベース接続ユーザー名が使用されます。そのスキーマに必要なプロシージャーが存在しない場合には、ルーチン定義または実行時にルーチンを呼び出す CALL に明示的なスキーマ名を指定する必要があります。ルーチンを含むスキーマを動的に選択することについての詳細は、CALL ステートメントを参照してください。修飾名を使用する場合は、名前を引用符で囲まなければなりません。
EXTERNAL NAME "mySchema.myProc";
EXTERNAL NAME "mySchema.myPackage.myProc";
この場合、CALL ステートメント中でパッケージ名ではなくスキーマを動的に選択できます。
EXTERNAL NAME "mySchema.Proc_";
以下の例は、単一のスカラー値と OUT パラメーターを戻す、ストアード・プロシージャーの単純な ESQL 定義です。
CREATE PROCEDURE myProc1(IN P1 INT, OUT P2 INT) LANGUAGE DATABASE RETURNS INTEGER EXTERNAL NAME "myschema.myproc";
myProc1 ルーチンを起動するには、この ESQL を使用します。
/*using CALL statement invocation syntax*/ CALL myProc1(intVar1, intVar2) INTO intReturnVar3; /*or using function invocation syntax*/ SET intReturnVar3 = myProc1(intVar1, intVar2);
以下の ESQL コードは、DB2 のストアード・プロシージャーの定義と呼び出しの方法を示します。
ESQL 定義: DECLARE inputParm CHARACTER; DECLARE outputParm CHARACTER; DECLARE inputOutputParm CHARACTER; SET inputParm = 'Hello'; SET inputOutputParm = 'World'; CALL swapParms( inputParm, outputParm, inputOutputParm ); CREATE PROCEDURE swapParms ( IN parm1 CHARACTER, OUT parm2 CHARACTER, INOUT parm3 CHARACTER ) EXTERNAL NAME dbSwapParms;
このストアード・プロシージャーを DB2 に登録するには、以下のスクリプトをファイル (例えば、test1.sql) にコピーします。
-- DB2 Example Stored Procedure DROP PROCEDURE dbSwapParms @ CREATE PROCEDURE dbSwapParms ( IN in_param CHAR(32), OUT out_param CHAR(32), INOUT inout_param CHAR(32)) LANGUAGE SQL BEGIN SET out_param = inout_param; SET inout_param = in_param; END @次に以下を実行します。
db2 -td@ -vf test1.sqlこれは DB2 コマンド・プロンプトで行います。
以下の ESQL コードは、Oracle のストアード・プロシージャーの定義と呼び出しの方法を示します。
ESQL 定義: DECLARE inputParm CHARACTER; DECLARE outputParm CHARACTER; DECLARE inputOutputParm CHARACTER; SET inputParm = 'Hello'; SET inputOutputParm = 'World'; CALL swapParms( inputParm, outputParm, inputOutputParm ); CREATE PROCEDURE swapParms ( IN parm1 CHARACTER, OUT parm2 CHARACTER, INOUT parm3 CHARACTER ) EXTERNAL NAME dbSwapParms;
このストアード・プロシージャーを Oracle に登録するには、以下のスクリプトをファイル (例えば、test1.sql) にコピーします。
CREATE OR REPLACE PROCEDURE dbSwapParms ( in_param IN VARCHAR2, out_param OUT VARCHAR2, inout_param IN OUT VARCHAR2 ) AS BEGIN out_param := inout_param; inout_param := in_param; END; /次に以下を実行します。
sqlplus <userid>/<password> @test1.sql
以下の ESQL コードは、SQLサーバー のストアード・プロシージャーの定義と呼び出しの方法を示します。
ESQL 定義: DECLARE inputParm CHARACTER; DECLARE outputParm CHARACTER; DECLARE inputOutputParm CHARACTER; SET inputParm = 'Hello'; SET inputOutputParm = 'World'; CALL swapParms( inputParm, outputParm, inputOutputParm ); CREATE PROCEDURE swapParms ( IN parm1 CHARACTER, INOUT parm2 CHARACTER, INOUT parm3 CHARACTER ) EXTERNAL NAME dbSwapParms;
このストアード・プロシージャーを SQLServer に登録するには、以下のスクリプトをファイル (例えば、test1.sql) にコピーします。
-- SQLServer Example Stored Procedure DROP PROCEDURE dbSwapParms go CREATE PROCEDURE dbSwapParms @in_param CHAR(32), @out_param CHAR(32) OUT, @inout_param CHAR(32) OUT AS SET NOCOUNT ON SET @out_param = @inout_param SET @inout_param = @in_param go次に以下を実行します。
isql -U<userid> -P<password> -S<server> -d<datasource> -itest1.sql
ESQL 内でこれらを OUT パラメーターとして宣言した場合、実行時にタイプ・ミスマッチ・エラーが発生します。このミスマッチを回避するには、SQL Server の OUTPUT パラメーターを、ESQL 内で INOUT として宣言する必要があります。
以下の ESQL コードは、SYBASE のストアード・プロシージャーの定義と呼び出しの方法を示します。
ESQL 定義: DECLARE inputParm CHARACTER; DECLARE outputParm CHARACTER; DECLARE inputOutputParm CHARACTER; SET inputParm = 'Hello'; SET inputOutputParm = 'World'; CALL swapParms( inputParm, outputParm, inputOutputParm ); CREATE PROCEDURE swapParms ( IN parm1 CHARACTER, INOUT parm2 CHARACTER, INOUT parm3 CHARACTER ) EXTERNAL NAME dbSwapParms;
このストアード・プロシージャーを SYBASE に登録するには、以下のスクリプトをファイル (例えば、test1.sql) にコピーします。
-- SYBASE Example Stored Procedure DROP PROCEDURE dbSwapParms go CREATE PROCEDURE dbSwapParms @in_param CHAR(32), @out_param CHAR(32) OUT, @inout_param CHAR(32) OUT AS SET @out_param = @inout_param SET @inout_param = @in_param go次に以下を実行します。
isql -U<userid> -P<password> -S<server> -d<datasource> -itest1.sql
ESQL 内でこれらを OUT パラメーターとして宣言した場合、実行時にタイプ・ミスマッチ・エラーが発生します。このミスマッチを回避するには、SYBASE の OUTPUT パラメーターを、ESQL 内で INOUT として宣言する必要があります。
次の例は、out パラメーターに加えて 2 つの結果セットを戻すストアード・プロシージャーを呼び出す方法を示します。
CREATE PROCEDURE myProc1 (IN P1 INT, OUT P2 INT) LANGUAGE DATABASE DYNAMIC RESULT SETS 2 EXTERNAL NAME "myschema.myproc";
myProc1 を起動するには、次の ESQL を使用してください。
/* using a field reference */ CALL myProc1(intVar1, intVar2, Environment.RetVal[], OutputRoot.XML.A[]) /* using a reference variable*/ CALL myProc1(intVar1, intVar2, myReferenceVariable.RetVal[], myRef2.B[])