バージョン 8.1.3
 —  トリガとストアドプロシージャ  —

ストアドプロシージャの呼び出し

ストアドプロシージャを使用すると、Adabas ダイレクトコマンド PC を使用してデータベース内に存在するプロシージャを直接呼び出すことができます。

このドキュメントでは、次のトピックについて説明します。


ストアドプロシージャのリンクルーチン(STPLNKnn)

ストアドプロシージャのリンクルーチン STPLNKnn とともに PC コマンドを使用して、ストアドプロシージャを呼び出します。

STPLNKnn は、SYSSPT ライブラリ内にソース形式で用意されています。

ライブラリ SYSSPT にある STPLNK01、STPLNK02、および STPLNK03 は、呼び出し元のストアドプロシージャで PC コマンドを使用するサンプルです。 各サンプルは、異なる方法でパラメータをルーチンに渡します。

これらのサンプルを使用することも、独自のルーチンを作成することもできます。 サンプルを使用する場合、ルーチンのコードまたは名前を変更して、サイトの標準や要件に合わせることができます。 ルーチン名をインラインコードとしてメイン Natural プログラムに組み込むこともできます。

3 つのサンプルでは、Natural ルーチン CMADA をコールすることで、PC コマンドが呼び出されます。 このエントリ名を直接コーディングしたくない場合は、代わりにライブラリ SYSEXT 内の Natural サブプログラム USR1043N に対して、CALLNAT を発行することもできます。 CALLNAT を使用する方法の利点は、名前 "CMADA" に対する変更からコードを隔離できることです。名前の変更は、時間が経過したりプラットフォームが異なると発生する可能性があります。

Top of page

PC コマンドの設定

STPLNKnn を使用してストアドプロシージャ要求を呼び出す前に、PC コマンド(ダイレクトコール)の Adabas コントロールブロック(ACB)を設定する必要があります。

このセクションでは、次のトピックについて説明します。

PC コマンドの機能と使用方法

PC コマンドは、ストアドプロシージャを呼び出すメカニズムを提供します。

パラメータは、レコードバッファを使用して渡されます。その後、パラメータはストアドプロシージャを使用して更新されて、呼び出し元に返されます。

フォーマットバッファは、プロシージャにパラメータを定義するために使用できます。 そのような情報は、レコードバッファ抽出ルーチンを呼び出すときに使用される可能性があります。

ACB インターフェイスダイレクトコールとバッファの概要

コントロールブロック

フィールド 位置 フォーマット Adabas
コール前
Adabas
コール後
  1~2 未使用 未使用 未使用
コマンドコード 3~4 英数字 F U
コマンド ID 5~8 英数字 F U
ファイル番号 9~10 英数字 F U
レスポンスコード 11~12 バイナリ 未使用 A
  13~24 未使用 未使用 未使用
フォーマットバッファ長 25~26 バイナリ F U
レコードバッファ長 27~28 バイナリ F U
  29~36 未使用 未使用 未使用
アディション 1 37~44 英数字 F U
アディション 2 45~48 バイナリ/バイナリ   A
アディション 3 49~56 英数字 F A
アディション 4 57~64 英数字 未使用 A
  65~76 未使用 未使用 未使用
ユーザーエリア 77~80     U

バッファエリア

バッファ Adabas コール前 Adabas コール後
フォーマット F U
レコード F A

上記の意味は次に示すとおりです。

F Adabas コール前にユーザーが入力するフィールド
A Adabas により入力されるフィールド
U Adabas コール後も変化なし

コントロールブロックフィールドの説明

コマンドコード(ACBCMD)

PC

コマンド ID(ACBCID)

このフィールドに値 "STPx"(x は任意の値)を設定します。

ファイル番号(ACBFNR)

デフォルトでは、トリガファイルのデータベース ID とファイル番号を示します。

1 バイトのデータベース ID の場合は CB-DBID を設定します。2 バイトのデータベース ID の場合は、CB-RSP を設定し、CB-CALL-TYPE を X'30' に設定します。

フォーマットバッファと組み合わせて他のユーザーファイルのファイル番号を指定できます。 ファイル番号はフォーマットバッファと一致する必要があるため、レコードバッファ抽出(STPRBE)ルーチンを使用して、ファイル - フィールド定義に応じてフィールド値を解釈したり取得することができます。

読み込むファイルの番号を 2 進数で指定します。 物理ダイレクトコールの場合は、次のようファイル番号を指定します。

レスポンスコード(ACBRSP)

Adabas はこのフィールドに、コマンドのレスポンスコードを返します。 レスポンスコード 0 は、このコマンドが正しく実行されたことを示します。 ゼロ以外のレスポンスコードは、アディション 2 フィールドの下位 2 バイトにサブコードを伴う場合があります。詳細は『Adabas メッセージおよびコードマニュアル』を参照してください。

フォーマットバッファ長(ACBFBL)

フォーマットバッファ長(バイト単位)。 ユーザープログラムに定義した実際のフォーマットバッファエリアは、この指定長と同じか、それ以上でなければなりません。

レコードバッファ長(ACBRBL)

レコードバッファ長(バイト単位)。 ユーザープログラムに定義した実際のレコードバッファエリアは、この指定長と同じか、それ以上でなければなりません。

アディション 1 - ストアドプロシージャ名(ACBADD1)

ストアドプロシージャ名。

アディション2 - 圧縮および非圧縮レコード長 - (ACBADD2)

PC コマンドは、このフィールドのバイト 1 および 2 で実行されたプロシージャからのレスポンスを返します。

アディション 3 - ストアドプロシージャのオプション - (ACBADD3)

このフィールドは、ストアドプロシージャのリクエストが発行されるときに使用されるオプションを示します。

バイト 1 は Type です。 A = 非同期、P = 関与、N = 非関与
バイト 2 は Parm です。 N = なし、C = コントロール、E = エラー/レスポンス、X = ACBX 付きのコントロール
バイト 3 は RecB です。 N = なし、A = アクセス、U = 更新

 

アディション 4(ACBADD4)

PC コマンドは、このフィールドのバイト 1 および 2 で実行されたプロシージャからのレスポンスを返します。 バイト 3 およびバイト 4 は、ストアドプロシージャを示すため X'0011'(17)に設定されます。

ACBX インターフェイスダイレクトコールとバッファの概要

コントロールブロック

フィールド 位置 フォーマット Adabas コール前 Adabas コール後
  1~2 バイナリ --- ---
バージョンインジケータ 3~4 バイナリ F  
  5~6 バイナリ --- ---
コマンドコード 7~8 英数字 F U
  9~10 バイナリ --- ---
レスポンスコード 11~12 バイナリ --- A
コマンド ID 13~16 英数字/バイナリ F U
データベース ID 17~20 数値 F U
ファイル番号 21~24 数値 F U
  25-56 --- --- ---
アディション 1 57~64 英数字 F U
アディション 2 65~68 バイナリ --- A
アディション 3 69~76 英数字 F A
アディション 4 77~84 英数字 --- A
  85~114 --- --- ---
エラーサブコード 115~116 バイナリ --- A
  117~144 --- --- ---
コマンドタイム 145~152 バイナリ --- A
ユーザーエリア 153~168 該当なし --- U
  169~193 --- --- ---

バッファエリア

バッファ Adabas コール前 Adabas コール後
フォーマット F U
レコード F A

上記の意味は次に示すとおりです。

F Adabas コール前にユーザーが入力するフィールド
A Adabas により入力されるフィールド
U Adabas コール後も変化なし

コントロールブロックフィールドの説明

バージョンインジケータ(ACBXVER)

F2

コマンドコード(ACBXCMD)

A1

レスポンスコード(ACBXRSP)

Adabas はこのフィールドに、コマンドのレスポンスコードを返します。 レスポンスコード 0 は、このコマンドが正しく実行されたことを示します。 ゼロ以外のレスポンスコードは、エラーサブコード(ACBXERRC)フィールドにサブコードを伴う場合があります。詳細は、Adabas メッセージおよびコード のドキュメントを参照してください。

コマンド ID(ACBXCID)

このフィールドに値 "STPx"(x は任意の値)を設定します。

データベース ID(ACBXDBID)

コールに使用するデータベース ID を指定します。

このフィールドがバイナリの 0 に設定されている場合、Adabas API は、DDCARD 入力データの ADARUN カードのデータベース ID を使用するか、または、リンクルーチンにリンクされている LNKGBLS モジュールかリンクルーチンによりロードされた LNKGBLS モジュールのデフォルトのデータベース ID 値を使用します。

ファイル番号(ACBXFNR)

デフォルトでは、トリガファイルのファイル番号を示します。

フォーマットバッファと組み合わせて他のユーザーファイルのファイル番号を指定できます。 ファイル番号はフォーマットバッファと一致する必要があるため、レコードバッファ抽出(STPRBE)ルーチンを使用して、ファイル - フィールド定義に応じてフィールド値を解釈したり取得することができます。

読み込むファイルの番号を 2 進数で指定します。 物理ダイレクトコールの場合は、次のようファイル番号を指定します。

アディション 1 - ストアドプロシージャ名(ACBXADD1)

ストアドプロシージャ名。

アディション2 - 圧縮および非圧縮レコード長 - (ACBXADD2)

コマンドが正常に処理されると、次の情報がこのフィールドに返されます。

注意:
プリフェッチ機能の使用時、この長さ情報は返されません。

アディション 3 - ストアドプロシージャのオプション - (ACBXADD3)

このフィールドは、ストアドプロシージャのリクエストが発行されるときに使用されるオプションを示します。

バイト 1 は Type です。 A = 非同期、P = 関与、N = 非関与
バイト 2 は Parm です。 N = なし、C = コントロール、E = エラー/レスポンス、X = ACBX 付きのコントロール
バイト 3 は RecB です。 N = なし、A = アクセス、U = 更新

 

アディション 4(ACBXADD4)

PC コマンドは、このフィールドのバイト 1 および 2 で実行されたプロシージャからのレスポンスを返します。 バイト 3 およびバイト 4 は、ストアドプロシージャを示すため X'0011'(17)に設定されます。

エラーサブコード(ACBXERRC)

コマンドがゼロ以外のレスポンスコードを返したときは、このフィールドにレスポンスコードの正確な意味を定義したサブコードが含まれます。 レスポンスコードとサブコードについては、『Adabas メッセージおよびコード』を参照してください。

バッファ

PC コマンドに次のバッファが適用されます。

フォーマットバッファ

ユーザーはこのバッファの読み込むフィールドを指定します。 フォーマットバッファの構文形式、および例については、『Adabas コマンドリファレンスマニュアル』を参照してください。

フォーマットバッファは、レコードバッファで渡されるパラメータの定義を格納するときに、任意で使用できます。 構文は通常のコマンドのフォーマットバッファの構文と整合性がある必要があります。または、使用しない場合は "." に設定します。

フォーマットバッファで使用されるフィールド名は、通常はわかりやすい名前にして、ストアドプロシージャが各パラメータの値をレコードバッファ抽出(STPRBE)ルーチンから取得できるようにしてください(「レコードバッファ抽出ルーチン(STPRBE)」を参照)。 ストアドプロシージャルーチンが長さを提供しない場合は、長さを使用する必要があります。 または、フィールド名が ACB で指定される実際のファイル番号と対応する場合、STPRBE ルーチンでフィールドやパラメータの長さを判断できます。

異なるプラットフォーム間でストアドプロシージャを発行するときは、各パラメータのフィールドタイプも指定することが重要です。つまり英数字の場合は "A"、バイナリの場合は "B"、アンパック形式の場合は "U" などです。

詳細については、「フォーマットバッファ」を参照してください。

レコードバッファ

Adabas は、バッファに要求されたフィールドの値をこのバッファに返します。 すべての値は、ユーザーがフォーマットバッファに長さやフォーマットを変更して指定していなければ、標準フォーマットと標準長で返されます。

レコードバッファは、呼び出し元からストアドプロシージャ、またはストアドプロシージャから呼び出し元にパラメータを渡すために使用できます。 レコードバッファのレイアウトまたは DSECT は、コール元と実際のストアドプロシージャルーチンの間で調整される必要があります。

レコードバッファは、レコードバッファ抽出(STPRBE)ルーチンを使用することで、関与および非関与(同期)タイプの要求のみで利用できます。 「レコードバッファ抽出ルーチン(STPRBE)」を参照してください。

レコードバッファをアクセスや更新で使用するかどうかは、アディション 4 フィールドを使用して呼び出し元が指定します。

詳細については、「フォーマットバッファとレコードバッファの使用」を参照してください。

Top of page

このセクションでは、次の表で示すサンプルのプログラムとデータエリアについて説明します。 ソースコードはインストール中に提供され、SYSSPT ライブラリに配置されます。

名前 説明
STPLNK01 このストアドプロシージャのリンクルーチンは、パラメータを固定長および固定番号として渡します。
STPLNK02 このストアドプロシージャのリンクルーチンでは、最大で 5 つのパラメータをプロシージャに渡す可能性があります。各パラメータの長さは、パラメータの最初の 2 バイトに格納されます。
STPLNK03 STPLNK02 と同様に、最大で 5 つのパラメータをプロシージャに渡す可能性があります。ただし、各パラメータの長さは、先行する別のパラメータに格納されます。

STPLNK01

0010 ************************************************************************
0020 *  Application: Adabas Stored Procedures
0030 *  Subprogram : STORPROC/STPLNK01
0040 *  Author     : Adabas Development
0050 *
0060 *  Function   : Sample Routine 01 to invoke a stored procedure
0070 *               This example expects fixed parameter definitions
0080 *  Remarks    : This routine will set up the buffers and issue the call
0090 *               to invoke a stored procedure routine directly.
0100 *               Once processing is completed, control is returned to
0110 *               the caller.
0120 *               Parameter RESP must be set to zero if processing is
0130 *               successful.
0140 *
0150 *  Parameters : The following fields in the ACB must be set up to invoke
0160 *               the stored procedure request.
0170 *
0180 *               Command Code: 'PC'
0190 *               Command ID  : 'STPx' - where x is any value
0200 *               Database ID : Database of the respective trigger file
0210 *                             Set CB-DBID for a one byte DBID
0220 *                             Set CB-RSP  for a two byte DBID with
0230 *                               CB-CALL-TYPE set to H'30'
0240 *               File Number : Set to the trigger file number of the
0250 *                             target database (normal one-byte versus
0260 *                             two-byte FNRs is applicable) by default
0270 *                             or any other file used in conjunction with
0280 *                             the format buffer.
0290 *               FB Length   : Length of the format buffer
0300 *               RB Length   : Length of the record buffer
0310 *               Additions 1 : Name of the stored procedure
0320 *               Additions 3 :
0330 *                  Byte 1   : Type ("A"sync, "P"art, "N"on-Partic)
0340 *                  Byte 2   : Parm ("N"one, "C"ntl, "E"rror/Resp)
0350 *                  Byte 3   : RecB ("N"one, "A"ccess, "U"pdate)
0360 *
0370 *
0380 *  Format Buff: The format buffer is an optional buffer that may be used
0390 *               to convey the definition of the parameters being passed
0400 *               in the record buffer. The syntax must be consistent with
0410 *               that of a format buffer for a normal command, or be set
0420 *               to "." if it not to be used.
0430 *
0440 *               The field names used in the format buffer should
0450 *               normally be meaningful so that the stored procedure can
0460 *               get the values of each parameter from the record buffer
0470 *               extraction (STPRBE) routine. Length must be used if the
0480 *               stored procedure routine does not provide one.
0490 *               Alternatively, if the field names correspond to the
0500 *               actual file number specified in the ACB, then the STPRBE
0510 *               routine will be able to determine the length of the
0520 *               field/parameter.
0530 *
0540 *               When issuing stored procedures across platforms, it is
0550 *               essential to also specify the field type of each
0560 *               parameter; i.e., "A" - alphanumeric, "B" - binary, "U"
0570 *               - unpacked etc.
0580 *
0590 *
0600 *  Record Buff: The record buffer is available for passing any
0610 *               parameters from the caller to the stored procedure
0620 *               and(or) from the stored procedure to the caller.
0630 *               The layout/DSECT of the record buffer must be
0640 *               coordinated between the caller and the actual stored
0650 *               procedure routine itself.
0660 *
0670 *               The record buffer is available for participating
0680 *               and non-participating (sync) type requests via the
0690 *               the record buffer extraction (STPRBE) routine, only.
0700 *
0710 *               Determination of the record buffer being for access or
0720 *               update is specified by the caller via the additions 3
0730 *               field (see above).
0740 *
0750 ************************************************************************
0760 DEFINE DATA PARAMETER
0770  01  REQ-TYPE  (A1)               /* Optional request ID type
0780  01  P-PROC    (A8)               /* Procedure name
0790  01  P-PARM1 (A100)               /* Single parameter
0800  01  P-MSG    (A72)               /* Message corresponding to the RESP
0810  01  RESP      (N4)               /* Response code of proc. request
0820            LOCAL USING STPLCB
0830            LOCAL
0840  01  FB    (A16) INIT<'AA,100,A.'>
0850  01  ET-CNT         (P3)
0860 END-DEFINE
0870 FORMAT PS=0
0880 *
0890 RESET CB                          /* Clear the ACB
0900 MOVE 'STP'   TO CB-CID            /* Command ID
0910 MOVE 'PC'    TO CB-CMD            /* Command code
0920 MOVE 222     TO CB-DBID           /* Database ID
0930 MOVE 12      TO CB-FNR            /* Default to TRG file number
0940 MOVE 9       TO CB-FBL            /* FB length
0950 MOVE 100     TO CB-RBL            /* RB length
0960 IF P-PROC = ' '                   /* Did we get a procedure name?
0970   DO
0980     MOVE 1 TO RESP
0990     MOVE 'Invalid Procedure Name specified' TO P-MSG
1000     ESCAPE ROUTINE
1010   DOEND
1020 MOVE P-PROC     TO CB-ADD1        /* Stored procedure name
1030 MOVE 'NCA     ' TO CB-ADD3        /* Options: N - Sync (non-partic)
1040 *                                 /*          C - Control parms
1050 *                                 /*          A - RecBuff for access
1060 *
1070 CALL 'CMADA' USING CB FB P-PARM1 /* Invoke the stored procedure
1080 *
1090 MOVE CB-RSP TO RESP
1100 MOVE 'Check Response code returned for this request' TO P-MSG
1110 * PRINT (CD=YE) 'Resp ..' (YEI) CB-RSP(EM=HH) 'Add2' CB-ADD2(EM=H(8))
1120 *              'Add4' CB-ADD4(EM=H(8))
1130 *
1140 END

STPLNK02

0010 ************************************************************************
0020 *  Application: Adabas Stored Procedures
0030 *  Subprogram : STORPROC/STPLNK02
0040 *  Author     : Adabas Development
0050 *
0060 *  Function   : Sample routine 02 to invoke a stored procedure
0070 *               This example expects up to 5 different variable-length
0080 *               parameters. The length of each parameter is specified
0090 *               as the first two bytes of each parameter. Length is
0100 *               inclusive of the two-byte length itself.
0110 *  Remarks    : This routine will set up the buffers and issue the call
0120 *               to invoke a stored procedure routine directly.
0130 *               Once processing is completed, control is returned to
0140 *               the caller.
0150 *               Parameter RESP must be set to zero if processing is 
0160 *               successful.
0170 *
0180 *  Parameters : The following fields in the ACB must be set up to invoke
0190 *               the stored procedure request.
0200 *
0210 *               Command Code: 'PC'
0220 *               Command ID  : 'STPx' - where x is any value
0230 *               Database ID : Database of the respective trigger file
0240 *                             Set CB-DBID for a one-byte DBID
0250 *                             Set CB-RSP  for a two-byte DBID with
0260 *                               CB-CALL-TYPE set to H'30'
0270 *               File Number : Set to the trigger file number of the
0280 *                             target database (normal one-byte versus
0290 *                             two-byte FNRs is applicable) by default
0300 *                             or any other file used in conjunction with
0310 *                             the format buffer.
0320 *               FB Length   : Length of the format buffer
0330 *               RB Length   : Length of the record buffer
0340 *               Additions 1 : Name of the stored procedure
0350 *               Additions 3 :
0360 *                  Byte 1   : Type ("A"sync, "P"art, "N"on-Partic)
0370 *                  Byte 2   : Parm ("N"one, "C"ntl, "E"rror/Resp)
0380 *                  Byte 3   : RecB ("N"one, "A"ccess, "U"pdate)
0390 *
0400 *
0410 *  Format Buff: The format buffer is an optional buffer that may be used
0420 *               to convey the definition of the parameters be ingpassed
0430 *               in the record buffer. The syntax must be consistent with
0440 *               that of a format buffer for a normal command, or be set
0450 *               to "." if it not to be used.
0460 *
0470 *               The field names used in the format buffer should
0480 *               normally be meaningful so that the stored procedure can
0490 *               get the values of each parameter via the record buffer
0500 *               extraction (STPRBE) routine. Length must be used if the
0510 *               stored procedure routine does not provide one.
0520 *               Alternatively, if the field names correspond to the
0530 *               actual file number specified in the ACB, then the STPRBE
0540 *               routine will be able to determine the length of the
0550 *               field/parameter.
0560 *
0570 *               When issuing stored procedures across platforms, it is
0580 *               essential to also specify the field type of each
0590 *               parameter; i.e., "A" - alphanumeric, "B" - binary, "U"
0600 *               - unpacked etc.
0610 *
0620 *
0630 *  Record Buff: The record buffer is available for passing any
0640 *               parameters from the caller to the stored procedure
0650 *               and(or) from the stored procedure to the caller.
0660 *               The layout/DSECT of the record buffer must be
0670 *               coordinated between the caller and the actual stored
0680 *               procedure routine itself.
0690 *
0700 *               The record buffer is available for participating
0710 *               and non-participating (sync) type requests via the
0720 *               the record buffer extraction (STPRBE) routine, only.
0730 *
0740 *               Determination of the record buffer being for access or
0750 *               update is specified by the caller via the additions 3
0760 *               field (see above).
0770 *
0780 ************************************************************************
0790 DEFINE DATA PARAMETER
0800  01  REQ-TYPE   (A1)
0810  01  P-PROC     (A8)              /* Procedure name
0820  01  P-OPTIONS  (A8)
0830  01  REDEFINE P-OPTIONS
0840    02  P-TYPE   (A1)              /* Async versus sync procedure
0850    02  P-PARMS  (A1)              /* Parm type for procedure
0860    02  P-RECB   (A1)              /* Rec buffer access
0870  01  P-PARM1(A1/1:V)              /* Variable-length parameter
0880 *                                     first 2 bytes set to incl. length
0890  01  P-PARM2(A1/1:V)              /* Variable-length parameter 2
0900  01  P-PARM3(A1/1:V)              /* Variable-length parameter 3
0910  01  P-PARM4(A1/1:V)              /* Variable-length parameter 4
0920  01  P-PARM5(A1/1:V)              /* Variable-length parameter 5
0930  01  P-MSG     (A72)              /* Message corresponging to the RESP
0940  01  RESP       (N4)              /* Response code of proc request
0950            LOCAL USING STPLCB
0960            LOCAL
0970  01  SUB        (I2)
0980  01  SUB1       (I2)
0990  01  SUB2       (I2)
1000  01  SUB3       (I2)
1010  01  SUB4       (I2)
1020  01  FB        (A48)
1030  01  REDEFINE FB
1040    02  FB-FIELD  (8)
1050      03  FB-FLD (A3)
1060      03  FB-LEN (N3)
1070  01  RB    (A1/1000)              /* Max length for all parms
1080  01  W-ADD3     (A8)
1090  01  REDEFINE W-ADD3
1100    02  W-TYPE   (A1)
1110    02  W-PARMS  (A1)
1120    02  W-RECB   (A1)
1130  01  #LENGTH    (B2)
1140  01  REDEFINE #LENGTH
1150    02  #LENG  (A1/2)
1160  01  W-LENG   (P5/5)
1170 END-DEFINE
1180 FORMAT PS=0
1190 *
1200 * In this example, we will say that each parameter has an individual
1210 * maximum length of 200; however, the limit may be established as a
1220 * total of all parameters. Since our max. record buffer is 1000 then the
1230 * maximum of all parameters cannot exceed 1000. This may be changed as
1240 * required by the user.
1250 *
1260 FOR SUB1 1 5                       /* Get all the parameter lengths
1270   DECIDE ON FIRST VALUE OF SUB1
1280     VALUE 1  MOVE P-PARM1(1:2) TO #LENG(1:2) /* Get Parm1 length
1290              IF #LENGTH < 3 /* Min length with inclusive length
1300                DO
1310                  MOVE 16 TO RESP
1320                  MOVE 'Invalid Length for Parameter 1. Must be 3-200'
1330                       TO P-MSG
1340                  ESCAPE ROUTINE
1350                DOEND
1360     VALUE 2  MOVE P-PARM2(1:2) TO #LENG(1:2) /* Get Parm2 length
1370     VALUE 3  MOVE P-PARM3(1:2) TO #LENG(1:2) /* Get Parm3 length
1380    VALUE 4  MOVE P-PARM5(1:2) TO #LENG(1:2) /* Get Parm4 length
1390    VALUE 5  MOVE P-PARM1(1:2) TO #LENG(1:2) /* Get Parm5 length
1400    ANY      IF #LENGTH = H'4040'  /* Is length Blanks?
1410               RESET #LENGTH       /*   yes, then treat as dummy parm
1420             MOVE #LENGTH TO W-LENG(SUB1)
1430             IF W-LENG(SUB1) > 202 /* For our example, we limit the length
1440               DO
1450                 MOVE 4 TO RESP
1460                 MOVE SUB1 TO FB-LEN(SUB1)
1470                 COMPRESS 'Invalid Length for Parameter' FB-LEN(SUB1)
1480                          '. Max is 200.' INTO P-MSG
1490                 ESCAPE ROUTINE    /* Terminate processing with error
1500               DOEND
1510             SUBTRACT 2 FROM W-LENG(SUB1) /* ACTUAL parm length
1520    NONE     IGNORE
1530  END-DECIDE
1540 CLOSE LOOP (1260)
1550 *
1560 IF P-PROC = ' '                    /* Did we get a procedure name?
1570   DO
1580     MOVE 1 TO RESP
1590     MOVE 'Invalid Procedure Name specified' TO P-MSG
1600     ESCAPE ROUTINE
1610   DOEND
1620 IF NOT (P-TYPE = 'A' OR= 'N' OR= 'P' OR= ' ')
1630   DO                               /* Async, participating, non-partic.
1640     MOVE 2 TO RESP
1650     MOVE 'Proc Type must be A, N, P or " "' TO P-MSG
1660     ESCAPE ROUTINE
1670   DOEND
1680 IF NOT (P-PARMS = 'C' OR= 'E' OR= 'N' OR= ' ')
1690   DO                               /* Cntrl, Error/Resp, None
1700     MOVE 3 TO RESP
1710     MOVE 'Parameter Type must be C, E, N or " "' TO P-MSG
1720     ESCAPE ROUTINE
1730   DOEND
1740 IF NOT (P-RECB = 'A' OR= 'N' OR= 'U' OR= ' ')
1750   DO                               /* Access, None, Update
1760     MOVE 3 TO RESP
1770     MOVE 'Parameter access must be Access, None or Update' TO P-MSG
1780     ESCAPE ROUTINE
1790   DOEND
1800 *
1810 * Next we merge all the passed parameters into a single contiguous
1820 * buffer which will be used as the record buffer for the call. The
1830 * format buffer will also be set up to indicate the 'structure' of the
1840 * record buffer for use by the invoked procedure.
1850 *
1860 MOVE 1 TO SUB 
1870 *
1880 FOR SUB3 1 5                       /* Step through all parameters
1890   IF W-LENG(SUB3) < 3              /* Check min. length of a parameter
1900     DO
1910       MOVE '.' TO FB-FLD(SUB3)
1920       ESCAPE BOTTOM                /* None, so assume we have all parms
1930     DOEND
1940   MOVE W-LENG(SUB3) TO SUB1
1950   ADD SUB1 TO SUB2
1960   DECIDE ON FIRST VALUE OF SUB1    /* Move parms into the RB
1970     VALUE 1 MOVE 'P1,' TO FB-FLD(1)
1980             MOVE P-PARM1 (3:SUB1) TO RB(SUB:SUB2)
1990     VALUE 2 MOVE 'P2,' TO FB-FLD(2)
2000             MOVE P-PARM2 (3:SUB1) TO RB(SUB:SUB2)
2010     VALUE 3 MOVE 'P3,' TO FB-FLD(3)
2020             MOVE P-PARM3 (3:SUB1) TO RB(SUB:SUB2)
2030     VALUE 4 MOVE 'P4,' TO FB-FLD(4)
2040             MOVE P-PARM4 (3:SUB1) TO RB(SUB:SUB2)
2050     VALUE 5 MOVE 'P5,' TO FB-FLD(5)
2060             MOVE P-PARM5 (3:SUB1) TO RB(SUB:SUB2)
2070     ANY     ADD SUB1 TO SUB
2080             MOVE SUB1 TO FB-LEN(SUB3)
2090     NONE    IGNORE
2100   END-DECIDE
2110 *
2120 CLOSE LOOP (1880)
2130 *
2140 * Now we start setting up the CB and do some additional validation.
2150 * When moving in the procedure options, we allow for defaults.
2160 *
2170 RESET CB                          /* Clear the ACB
2180 MOVE 'STP'   TO CB-CID            /* Command ID
2190 MOVE 'PC'    TO CB-CMD            /* Command code
2200 MOVE 77      TO CB-DBID           /* Database ID
2210 MOVE 22      TO CB-FNR            /* File number
2220 MOVE 48      TO CB-FBL            /* FB length
2230 MOVE 1000    TO CB-RBL            /* RB length
2240 MOVE P-PROC  TO CB-ADD1           /* Stored procedure name
2250 *
2260 MOVE 'A' TO W-TYPE                 /* Set the default options
2270 MOVE 'C' TO W-PARMS
2280 MOVE 'N' TO W-RECB
2290 IF NOT (P-TYPE = ' ')             /* Should we default to Async?
2300   MOVE P-TYPE TO W-TYPE
2310 IF NOT (P-PARMS = ' ')            /* Should we default to Contrl?
2320   MOVE P-PARMS TO W-PARMS
2330 IF NOT (P-RECB = ' ')             /* Should we default to None?
2340   MOVE P-RECB TO W-RECB
2350 MOVE W-ADD3  TO CB-ADD3           /* Options for request
2360 *
2370 CALL 'CMADA' USING CB FB RB(1)   /* Invoke the stored procedure
2380 *
2390 IF CB-RSP NE 0
2400   DO
2410     PRINT (CD=YE) 'Resp ..' (YEI) CB-RSP(EM=HH) 'Add2' CB-ADD2(EM=H(4))
2420                   'Add3' CB-ADD3(EM=H(8)) 'Add4' CB-ADD4(EM=H(8))
2430     ESCAPE ROUTINE
2440   DOEND
2450 *
2460 * Now we need to restore the parameters back into the user's area,
2470 * in case the data was modified. This can happen only if the record
2480 * buffer was modifiable; i.e., P-RECB was set to 'U'.
2490 *
2500 IF  CB-RSP = 0                    /* Was everything okay
2510 AND P-RECB = 'U'                  /* Update: Parms may have been updated
2520   DO
2530     MOVE 1 TO SUB
2540     RESET SUB2
2550     FOR SUB1 1 5
2560       ADD  W-LENG(SUB1) TO SUB2
2570       MOVE W-LENG(SUB1) TO SUB3
2580       DECIDE ON FIRST VALUE OF SUB1 /* Restore parm from RB
2590         VALUE 1   ASSIGN P-PARM1 (3:SUB3) = RB(SUB:SUB2)
2600         VALUE 2   ASSIGN P-PARM2 (3:SUB3) = RB(SUB:SUB2)
2610         VALUE 3   ASSIGN P-PARM3 (3:SUB3) = RB(SUB:SUB2)
2620         VALUE 4   ASSIGN P-PARM4 (3:SUB3) = RB(SUB:SUB2)
2630         VALUE 5   ASSIGN P-PARM5 (3:SUB3) = RB(SUB:SUB2)
2640         ANY       ADD W-LENG(SUB1) TO SUB /* Get next position
2650         NONE      IGNORE
2660       END-DECIDE
2670     CLOSE LOOP(2550)
2680   DOEND
2690 *
2700 END

STPLNK03

0010 ************************************************************************
0020 *  Application: Adabas Stored Procedures
0030 *  Subprogram : STORPROC/STPLNK03
0040 *  Author     : Adabas Development
0050 *
0060 *  Function   : Sample routine 03 to invoke a stored procedure
0070 *               This example expects up to five different variable-length
0080 *               parameters. Parameter lengths are passed as extra
0090 *               parameters.
0100 *  Remarks    : This routine will set up the buffers and issue the call
0110 *               to invoke a stored procedure routine directly.
0120 *               Once processing is completed, control is returned to
0130 *               the caller.
0140 *               Parameter RESP must be set to zero if processing is
0150 *               successful.
0160 *
0170 *  Parameters : The following fields in the ACB must be set up to invoke
0180 *               the stored procedure request.
0190 *
0200 *               Command Code: 'PC'
0210 *               Command ID  : 'STPx' - where x is any value
0220 *               Database ID : Database of the respective trigger file
0230 *                             Set CB-DBID for a one-byte DBID 
0240 *                             Set CB-RSP  for a two-byte DBID with
0250 *                               CB-CALL-TYPE set to H'30'
0260 *               File Number : Set to the trigger file number of the
0270 *                             target database (normal one-byte versus
0280 *                             two-byte FNRs is applicable) by default
0290 *                             or any other file used in conjunction with
0300 *                             the format buffer.
0310 *               FB Length   : Length of the format buffer
0320 *               RB Length   : Length of the record buffer
0330 *               Additions 1 : Name of the stored procedure
0340 *               Additions 3 :
0350 *                  Byte 1   : Type ("A"sync, "P"art, "N"on-Partic)
0360 *                  Byte 2   : Parm ("N"one, "C"ntl, "E"rror/Resp)
0370 *                  Byte 3   : RecB ("N"one, "A"ccess, "U"pdate)
0380 *
0390 *
0400 *  Format Buff: The format buffer is an optional buffer that may be used
0410 *               to convey the definition of the parameters being passed
0420 *               in the record buffer. The syntax must be consistent with
0430 *               that of a format buffer for a normal command, or be set
0440 *               to "." if it not to be used.
0450 *
0460 *               The field names used in the format buffer should
0470 *               normally be meaningful so that the stored procedure can
0480 *               otain the values of each parameter via the record buffer
0490 *               extraction (STPRBE) routine. Length must be used if the
0500 *               stored procedure routine does not provide one.
0510 *               Alternatively, if the field names correspond to the
0520 *               actual file number specified in the ACB, then the STPRBE
0530 *               routine will be able to determine the length of the
0540 *               field/parameter.
0550 *
0560 *               When issuing stored procedures across platforms, it is
0570 *               essential to also specify the field type of each
0580 *               parameter; i.e., "A" - alphanumeric, "B" - binary, "U"
0590 *               - unpacked etc.
0600 *
0610 *
0620 *  Record Buff: The record buffer is available for passing any
0630 *               parameters from the caller to the stored procedure
0640 *               and(or) from the stored procedure to the caller.
0650 *               The layout/DSECT of the record buffer must be
0660 *               coordinated between the caller and the actual stored
0670 *               procedure routine itself.
0680 *
0690 *               The record buffer will be available for participating
0700 *               and non-participating (sync) type requests via the
0710 *               the record buffer extraction (STPRBE) routine, only.
0720 *
0730 *               Determination of the record buffer being for access or
0740 *               update is specified by the caller via the additions 3
0750 *               field (see above).
0760 *
0770 ************************************************************************
0780 DEFINE DATA PARAMETER
0790  01  REQ-TYPE   (A1)
0800  01  P-PROC     (A8)              /* Procedure name
0810  01  P-OPTIONS  (A8)
0820  01  REDEFINE P-OPTIONS
0830    02  P-TYPE   (A1)              /* Async versus sync procedure
0840    02  P-PARMS  (A1)              /* Parm type for procedure
0850    02  P-RECB   (A1)              /* Rec buffer access
0860  01  P-LEN1     (P3)              /* Length of Parm1
0870  01  P-PARM1(A1/1:V)              /* Variable-length parameter 1
0880  01  P-LEN2     (P3)              /* Length of Parm2
0890  01  P-PARM2(A1/1:V)              /* Variable-length parameter 2
0900  01  P-LEN3     (P3)              /* Length of Parm3
0910  01  P-PARM3(A1/1:V)              /* Variable-length parameter 3
0920  01  P-LEN4     (P3)              /* Length of Parm4
0930  01  P-PARM4(A1/1:V)              /* Variable-length parameter 4
0940  01  P-LEN5     (P3)              /* Length of Parm5
0950  01  P-PARM5(A1/1:V)              /* Variable-length parameter 5
0960  01  P-MSG     (A72)              /* Message corresponging to the RESP
0970  01  RESP       (N4)              /* Response code of proc request
0980            LOCAL USING STPLCB
0990            LOCAL
1000  01  SUB        (I2)
1010  01  SUB1       (I2)
1020  01  SUB2       (I2)
1030  01  SUB3       (I2)
1040  01  FB        (A64)
1050  01  REDEFINE FB
1060    02  FB-FIELD  (8)
1070      03  FB-FLD (A3)
1080      03  FB-LEN (N3)
1090      03  FB-COMM(A1)
1100  01  RB    (A1/1000)              /* Max length for all parms
1110  01  W-ADD3     (A8)
1120  01  REDEFINE W-ADD3
1130    02  W-TYPE   (A1)
1140    02  W-PARMS  (A1)
1150    02  W-RECB   (A1)
1160  01  #LENGTH    (B2)
1170  01  REDEFINE #LENGTH
1180    02  #LENG  (A1/2)
1190  01  W-LENG   (P3/5)
1200 END-DEFINE
1210 FORMAT PS=0
1220 *
1230 MOVE P-LEN1 TO W-LENG(1)
1240 MOVE P-LEN2 TO W-LENG(2)
1250 MOVE P-LEN3 TO W-LENG(3)
1260 MOVE P-LEN4 TO W-LENG(4)
1270 MOVE P-LEN5 TO W-LENG(5)
1280 *
1290 * In this example, we will say that each parameter has an individual
1300 * maximum length of 200; however, the limit may be established as a
1310 * total of all parameters. Since our max. record buffer is 1000, the
1320 * maximum of all parameters cannot exceed 1000. This may be changed as
1330 * required by the user.
1340 *
1350 FOR SUB1 1 5                       /* Validate all parameter lengths
1360  IF W-LENG(SUB1) > 16448          /* Does length contain X'4040'
1370    RESET W-LENG(SUB1)             /*   yes, then must be dummy parm
1380  IF W-LENG(SUB1) > 200            /* For our example we limit the length
1390    DO
1400      MOVE 15   TO RESP
1410      MOVE SUB1 TO FB-LEN(SUB1)
1420      COMPRESS 'Invalid Length for Parameter' FB-LEN(SUB1)
1430               '. Max is 200.' INTO P-MSG
1440      ESCAPE ROUTINE               /* Terminate processing with error
1450    DOEND
1460 CLOSE LOOP
1470 *
1480 * Now we validate the parameters, as required. Of course, these may
1490 * be changed as per the user's requirement and may vary from one stored
1500 * procedure link routine to another.
1510 *
1520 IF P-PROC = ' '                   /* Did we get a procedure name?
1530  DO
1540    MOVE 1 TO RESP
1550    MOVE 'Invalid Procedure Name specified' TO P-MSG
1560    ESCAPE ROUTINE
1570  DOEND
1580 IF NOT (P-TYPE = 'A' OR= 'N' OR= 'P' OR= ' ')
1590  DO                              /* Async, Participating, Non-Partic
1600    MOVE 2 TO RESP
1610    MOVE 'Proc Type must be A, N, P or " "' TO P-MSG
1620    ESCAPE ROUTINE
1630  DOEND
1640 IF NOT (P-PARMS = 'C' OR= 'E' OR= 'N' OR= ' ')
1650  DO                              /* Cntrl, Error/Resp, None
1660    MOVE 3 TO RESP
1670    MOVE 'Parameter Type must be C, E, N or " "' TO P-MSG
1680    ESCAPE ROUTINE
1690  DOEND
1700 IF NOT (P-RECB = 'A' OR= 'N' OR= 'U' OR= ' ')
1710  DO                              /* Access, None, Update
1720    MOVE 3 TO RESP
1730    MOVE 'Parameter access must be Access, None or Update' TO P-MSG
1740    ESCAPE ROUTINE
1750  DOEND
1760 IF P-LEN1 < 3                     /* Min. length with inclusive length
1770  DO                              /* Anything less indicates no parm
1780    MOVE 4 TO RESP
1790    MOVE 'First Parameter MUST be valid. Length must be
3-200' TO P-MSG
1800    ESCAPE ROUTINE
1810  DOEND
1820 *
1830 * Next we merge all the passed parameters into a single contiguous
1840 * buffer which will be used as the record buffer for the call. The
1850 * format buffer will also be set up to indicate the 'structure' of the
1860 * record buffer for use by the invoked procedure.
1870 *
1880 MOVE 1 TO SUB
1890 RESET SUB2
1900 *
1910 FOR SUB1 1 5                        /* Step through all parameters
1920  IF W-LENG(SUB1) < 3               /* Check min. length of a parameter
1930    DO
1940      MOVE '.' TO FB-FLD(SUB1)
1950      ESCAPE BOTTOM                 /* None, so assume we have all parms
1960    DOEND
1970  ADD W-LENG(SUB1)  TO SUB2         /* Get end position
1980  MOVE W-LENG(SUB1) TO SUB3         /* Set index for MOVE statement
1990  DECIDE ON FIRST VALUE OF SUB1     /* Move next parm into the RB
2000     VALUE 1   MOVE P-PARM1 (1:SUB3) TO RB(SUB:SUB2)
2010               MOVE 'P1,' TO FB-FLD(1)
2020     VALUE 2   MOVE P-PARM2 (1:SUB3) TO RB(SUB:SUB2)
2030               MOVE ','   TO FB-COMM(SUB1 - 1)
2040               MOVE 'P2,' TO FB-FLD(2)
2050     VALUE 3   MOVE P-PARM3 (1:SUB3) TO RB(SUB:SUB2)
2060               MOVE ','   TO FB-COMM(SUB1 - 1)
2070               MOVE 'P3,' TO FB-FLD(3)
2080     VALUE 4   MOVE P-PARM4 (1:SUB3) TO RB(SUB:SUB2)
2090               MOVE ','   TO FB-COMM(SUB1 - 1)
2100               MOVE 'P4,' TO FB-FLD(4)
2110     VALUE 5   MOVE P-PARM5 (1:SUB3) TO RB(SUB:SUB2)
2120               MOVE ','   TO FB-COMM(SUB1 - 1)
2130               MOVE 'P5,' TO FB-FLD(5)
2140               MOVE '.'   TO FB-COMM(5)
2150     ANY       ADD W-LENG(SUB1) TO SUB  /* Get new position
2160               MOVE W-LENG(SUB1) TO FB-LEN(SUB1)
2170     NONE      IGNORE
2180  END-DECIDE
2190 *
2200 CLOSE LOOP
2210 *
2220 * Now we set up the CB for the actual stored procedure call.
2230 *
2240 RESET CB                          /* Clear the ACB
2250 MOVE 'STP'   TO CB-CID            /* Command ID
2260 MOVE 'PC'    TO CB-CMD            /* Command Code
2270 MOVE 77      TO CB-DBID           /* Database ID
2280 MOVE 22      TO CB-FNR            /* File Number
2290 MOVE 64      TO CB-FBL            /* FB Length
2300 MOVE 1000    TO CB-RBL            /* RB length
2310 MOVE P-PROC  TO CB-ADD1           /* Stored procedure name
2320 *
2330 * If any options were not passed, we use a pre-specified default.
2340 *
2350 MOVE 'A' TO W-TYPE                 /* Set the default options
2360 MOVE 'C' TO W-PARMS
2370 MOVE 'N' TO W-RECB
2380 IF NOT (P-TYPE = ' ')             /* Should we default to Async?
2390  MOVE P-TYPE TO W-TYPE
2400 IF NOT (P-PARMS = ' ')            /* Should we default to Contrl?
2410  MOVE P-PARMS TO W-PARMS
2420 IF NOT (P-RECB = ' ')             /* Should we default to None?
2430  MOVE P-RECB TO W-RECB
2440 MOVE W-ADD3  TO CB-ADD3           /* Options for request 2450 *
2460 CALL 'CMADA' USING CB FB RB(1)   /* Invoke the stored procedure 
2470 *
2480 IF CB-RSP NE 0
2490  DO
2500    PRINT (CD=YE) 'Resp ..' (YEI) CB-RSP(EM=HH) 'Add2' CB-ADD2(EM=H(4))
2510                  'Add3' CB-ADD3(EM=H(8)) 'Add4' CB-ADD4(EM=H(8))
2520    ESCAPE ROUTINE
2530  DOEND
2540 *
2550 * Now we need to restore the parameters back into the user's area,
2560 * in case the data was modified. This can happen only if the record
2570 * buffer was modifiable; i.e., P-RECB was set to 'U'.
2580 *
2590 IF  CB-RSP = 0                    /* Was everything okay
2600 AND P-RECB = 'U'                  /* Update: Parms may have been updated
2610  DO
2620    MOVE 1 TO SUB
2630    RESET SUB2
2640    FOR SUB1 1 5
2650      ADD  W-LENG(SUB1) TO SUB2
2660      MOVE W-LENG(SUB1) TO SUB3
2670      DECIDE ON FIRST VALUE OF SUB1 /* Restore parm from RB
2680        VALUE 1   ASSIGN P-PARM1 (1:SUB3) = RB(SUB:SUB2)
2690        VALUE 2   ASSIGN P-PARM2 (1:SUB3) = RB(SUB:SUB2)
2700        VALUE 3   ASSIGN P-PARM3 (1:SUB3) = RB(SUB:SUB2)
2710        VALUE 4   ASSIGN P-PARM4 (1:SUB3) = RB(SUB:SUB2)
2720        VALUE 5   ASSIGN P-PARM5 (1:SUB3) = RB(SUB:SUB2)
2730        ANY       ADD W-LENG(SUB1) TO SUB /* Get next position
2740        NONE      IGNORE
2750      END-DECIDE
2760    CLOSE LOOP(2640)
2770  DOEND
2780 *
2790 END

Top of page