APIによって結果を得る方法として
(1) APIからの戻り変数を取得する
(2) APIがユーザー・スペースに出力した結果を読取る
という方法が多く、特に複数の結果を受取る方法は
(2)のパターンでユーザー・スペースを読取る方法が
多く利用されている。
ところがあまり使われていないがもうひとつの方法がある。
(3) APIが結果をメモリとして戻してそのメモリを読取る。
という方法である。ユーザー・スペースではなく
メモリに直接結果が戻されてそれを読むという方法である。
この方法は(2)に比べて圧倒的にパフォーマンスにおいて
優れている。
1万レコード以上の結果があっても瞬時で終わってしまう。
ただしこのAPIのパターンは使うのに非常に難しい。
サンプルの例がほとんどなくAPIの解説も十分ではない。
日本語のサンプル・ソースがあったとしても
IBMマニュアルをそのまま書き写しただけなのに
「やさしい」とか言ってるが実は本人が書いたものでは
なく肝心な部分は丸写しで実践的なテストはされていない。
実際に実行したのであればそのパフォーマンスに驚くはずであるが
何も書かれていない。
海外サイトでもQGYOLSPLの使用方法を教えて欲しいという
書き込みがあるがサンプル・ソースの公開はない。
また多くの技術解説はマニュアルをただコピーしただけのものが多い。
そこでこのシリーズでは(3)のオーブン・リストと呼ばれる
パターンのサンプルを紹介する。
これらは実際に製品に使用されている使い方を示している。
今回、最初に紹介するのはスプールの一覧を検索するための
API: QGYOLSPL の利用方法である。
API: QGYOLSPL が優れているのはパフォーマンスだけではない。
今までのスプール一覧はOUTQ単位の出力であった。
つまり装置を主体として一覧表の出力である。
しかし QGYOLSPL ではジョブ単位でもOUTQ単位でも自由に
設定してスプールを抽出することができる。
つまり自分が出力したスプールがどのOUTQに分散されて
保管されていたとしてもまとめて抽出することができる。
これは装置主体ではなく使用者を主体としていることである。
[TESTSPLL: QGYOLSPL: SPLF の一覧表 ]
ソースはこちらから
0001.00 PGM 0002.00 /*-------------------------------------------------------------------*/ 0003.00 /* TESTSPLL : QGYOLSPL: SPLF の一覧表 */ 0004.00 /* */ 0005.00 /* 2020/07/05 作成 REF. TESTSPL2 QCSRC2 */ 0006.00 /*-------------------------------------------------------------------*/ 0007.00 /*( QGYOLSPL に必要な変数 )*/ 0008.00 DCL VAR(&RCVVAR) TYPE(*CHAR) LEN(4800) 0009.00 DCL VAR(&RCVLEN) TYPE(*CHAR) LEN(4) + 0010.00 VALUE(X'000012C0') 0011.00 DCL VAR(&LISTINFO) TYPE(*CHAR) LEN(80) 0012.00 DCL VAR(&LISTSU) TYPE(*CHAR) LEN(4) + 0013.00 VALUE(X'00000001') 0014.00 DCL VAR(&NBRRCD) TYPE(*CHAR) LEN(4) + 0015.00 VALUE(X'00000003') 0016.00 DCL VAR(&SORT) TYPE(*CHAR) LEN(4) + 0017.00 VALUE(X'00000000') 0018.00 DCL VAR(&BIN1) TYPE(*CHAR) LEN(4) + 0019.00 VALUE(X'00000001') 0020.00 DCL VAR(&FILTER) TYPE(*CHAR) LEN(92) 0021.00 DCL VAR(&JOBINFO) TYPE(*CHAR) LEN(26) 0022.00 DCL VAR(&JOB) TYPE(*CHAR) LEN(10) 0023.00 DCL VAR(&USER) TYPE(*CHAR) LEN(10) 0024.00 DCL VAR(&NBR) TYPE(*CHAR) LEN(6) 0025.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132) 0026.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) 0027.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) 0028.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) 0029.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132) 0030.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1) 0031.00 DCL VAR(&TOPGMQ) TYPE(*CHAR) LEN(10) 0032.00 DCL VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) + 0033.00 VALUE('*ESCAPE ') 0034.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) + 0035.00 VALUE(X'000074') /* 2 進数 */ 0036.00 DCL VAR(&ERR) TYPE(*CHAR) LEN(1) 0037.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) + 0038.00 VALUE(X'00000000') 0039.00 DCL VAR(&SPC2) TYPE(*CHAR) LEN(2) 0040.00 DCL VAR(&BIN4) TYPE(*CHAR) LEN(4) 0041.00 DCL VAR(&RTNSU) TYPE(*DEC) LEN(5 0) 0042.00 DCL VAR(&RTNSUC) TYPE(*CHAR) LEN(5) 0043.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) 0044.00 0045.00 /*( 環境の取得 )*/ 0046.00 RTVJOBA JOB(&JOB) USER(&USER) NBR(&NBR) TYPE(&TYPE) 0047.00 IF COND(&TYPE *EQ '0') THEN(DO) /* バッチ */ 0048.00 CHGVAR VAR(&TOPGMQ) VALUE('*SYSOPR ') 0049.00 ENDDO /* バッチ */ 0050.00 ELSE CMD(DO) /* 対話式 */ 0051.00 CHGVAR VAR(&TOPGMQ) VALUE('*TOPGMQ ') 0052.00 ENDDO /* 対話式 */ 0053.00 0054.00 /*( スプール・リストのオープン )*/ 0055.00 CHGVAR VAR(%SST(&LISTINFO 1 4)) VALUE(&LISTSU) 0056.00 CHGVAR VAR(&JOBINFO) VALUE(&JOB *CAT &USER *CAT + 0057.00 &NBR) 0058.00 CHGVAR VAR(&FILTER) + 0059.00 VALUE(&BIN1 *CAT &USER *CAT ' ' + 0060.00 *CAT &BIN1 *CAT '*ALL ' + 0061.00 *CAT '*ALL ' + 0062.00 *CAT '*ALL ' + 0063.00 *CAT &BIN1 *CAT '*READY ' + 0064.00 *CAT &BIN1 *CAT '*ALL ') 0065.00 CALL PGM(QGYOLSPL) PARM(&RCVVAR &RCVLEN &LISTINFO + 0066.00 &NBRRCD &SORT &FILTER &JOBINFO + 0067.00 'OSPL0300' &APIERR) 0068.00 IF COND(%SST(&APIERR 5 4) *NE &NULL4) THEN(DO) 0069.00 SNDPGMMSG + 0070.00 MSG('API: QGYOLSPL の実行で次のエラーが発生 + 0071.00 しました。 ') MSGTYPE(*DIAG) 0072.00 GOTO APIERR 0073.00 ENDDO 0074.00 CHGVAR VAR(&BIN4) VALUE(%SST(&LISTINFO 1 4)) 0075.00 CHGVAR VAR(&RTNSU) VALUE(%BIN(&BIN4)) 0076.00 IF COND(&RTNSU *EQ 0) THEN(DO) /* + 0077.00 戻り数がない */ 0078.00 CHGVAR VAR(&MSG) + 0079.00 VALUE(' 見つかったスプールはありません。 ') 0080.00 CHGVAR VAR(&MSGTYPE) VALUE('*DIAG ') 0081.00 GOTO ENDLIST 0082.00 ENDDO /* 戻り数がない */ 0083.00 IF COND(&RTNSU > 0) THEN(DO) /* 戻り数 >0 */ 0084.00 CHGVAR VAR(&RTNSUC) VALUE(&RTNSU) 0085.00 NXTDEC: IF COND(%SST(&RTNSUC 1 1) *EQ '0') THEN(DO) 0086.00 CHGVAR VAR(&RTNSUC) VALUE(%SST(&RTNSUC 2 4)) 0087.00 GOTO NXTDEC 0088.00 ENDDO 0089.00 ENDDO /* 戻り数 >0 */ 0090.00 CHGVAR VAR(&MSG) VALUE(&RTNSUC *TCAT + 0091.00 ' 個のスプールが見つかりました ') 0092.00 CHGVAR VAR(&MSGTYPE) VALUE('*DIAG ') 0093.00 ENDLIST: GOTO SNDMSG 0094.00 0095.00 APIERR: 0096.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7)) 0097.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100)) 0098.00 IF COND(%SST(&MSGID 1 3) *EQ 'GUI') THEN(DO) 0099.00 CHGVAR VAR(&MSGF) VALUE('QGUIMSG ') 0100.00 ENDDO 0101.00 ELSE CMD(DO) 0102.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ') 0103.00 ENDDO 0104.00 CHGVAR VAR(&MSGFLIB) VALUE('QSYS ') 0105.00 GOTO SNDMSG 0106.00 0107.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) + 0108.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + 0109.00 MSGFLIB(&MSGFLIB) 0110.00 SNDMSG: IF COND(&MSGID *EQ ' ') THEN(DO) 0111.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) + 0112.00 TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE) 0113.00 MONMSG MSGID(CPF2400) EXEC(RETURN) 0114.00 ENDDO 0115.00 ELSE CMD(DO) 0116.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 0117.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) + 0118.00 MSGTYPE(&MSGTYPE) 0119.00 MONMSG MSGID(CPF2400) EXEC(RETURN) 0120.00 ENDDO 0121.00 DSPJOBLOG JOB(*) OUTPUT(*PRINT) 0122.00 ENDPGM
[解説]
SPLF の一覧表API: QGYOLSPL は
0065.00 CALL PGM(QGYOLSPL) PARM(&RCVVAR &RCVLEN &LISTINFO + 0066.00 &NBRRCD &SORT &FILTER &JOBINFO + 0067.00 'OSPL0300' &APIERR)
のようにして呼び出しているのだが
&RCVVAR ………………….. 受取り変数(CHAR* 4800)
&RCVLEN ………………….. 受取り変数の長さ(CHAR* 4) VALUE(X’000012C0′) は 4800 の意味
&LISTINFO ………………… リスト情報(CHAR* 80) リスト数 1を入れて渡す
戻ったときには受取った数が入っている。
0055.00 CHGVAR VAR(%SST(&LISTINFO 1 4)) VALUE(&LISTSU)
&NBRRCD ………………….. 受取り最大可能数を示す。-1の場合はすべて(CHAR* 4)
&SORT ……………………. 分類情報。分類のない場合は NULLを入れておく。
&FILTER ………………….. APIの使い方が難しいのはこの部分の指定の方法がマニュアルでは不明。
フィルター情報とはデータの選択を意味するのだが
API: QGYOLSPL のフィルター情報はひとつでも省略してはならないことである。
0058.00 CHGVAR VAR(&FILTER) + 0059.00 VALUE(&BIN1 *CAT &USER *CAT ' ' + 0060.00 *CAT &BIN1 *CAT '*ALL ' + 0061.00 *CAT '*ALL ' + 0062.00 *CAT '*ALL ' + 0063.00 *CAT &BIN1 *CAT '*READY ' + 0064.00 *CAT &BIN1 *CAT '*ALL ')
は、*READY状態のすべてのスプールを抽出することを意味している。
&JOBINFO …………………. スプールを選択するためのジョブ情報
0056.00 CHGVAR VAR(&JOBINFO) VALUE(&JOB *CAT &USER *CAT + 0057.00 &NBR)
API: QGYOLSPLが成功裏に終わったときは &LISTINFOには抽出できたレコード数が入っているので
0074.00 CHGVAR VAR(&BIN4) VALUE(%SST(&LISTINFO 1 4)) 0075.00 CHGVAR VAR(&RTNSU) VALUE(%BIN(&BIN4))
によって出力レコード数を取り出すことができる。
出力結果は &RCVVAR に入っているので
’OSPL0300’ のレコード形式をマニュアルで調べればどのような形式で収められているのかを
知ることができる。
最後に
0098.00 IF COND(%SST(&MSGID 1 3) *EQ 'GUI') THEN(DO) 0099.00 CHGVAR VAR(&MSGF) VALUE('QGUIMSG ') 0100.00 ENDDO 0101.00 ELSE CMD(DO) 0102.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ') 0103.00 ENDDO
にも注目して欲しい。
リストAPIで送出されるエラーは QCPFMSGではなく QGUIMSG というメッセージ・ファイルである。
このことも実際に実行した者でないと気付かない。
実行結果
> call testspll 3 個のスプールが見つかりました
次にレコードを取り出すことになるがここではまず API:QGYOLSPL の使い方を知ってもらうために
サンプルとして示すことにした。
API:QGYOLSPLの使用サンプル・ソースはインターネットでもほとんど公開の例がなく
これが初めての公開であろう。
次回はリスト・オープンAPIの検索方法も含めて紹介する。