SELECT命令を一括実行するツールを作成してみた(RPG,OS/400)
わたしは今は、レガシーシステムの保守運用の仕事をしている。それは80年代の終わりに登場したIBM AS/400シリーズの流れのeSever iSeriesマシン構成上に、2000年頃に本番稼動したシステムだ。OSはi5/OS (OS/400)。
開発言語はRPG(※)。くわしくいうと、システムの元々のパッケージソフトウェアはRPG/400で製作されており、そのためもあって慣行的にILE RPGの使用は禁止されている。また、 DB2リレーショナルデータベースがOSの中核部分に元々組み込まれているのだが、SQLはこれまでは慣行的に利用しておらず、PF(物理ファイル)とLF(論理ファイル)の世界だった。データ内容確認やテスト確認局面ではSQLを使ったほうが便利だと思うが、これまでの担当者は「Query/400」(「DB2 Web Query」ではないよ)という元々のツール一本で仕事していたそうだ。なお、開発のための他の便利そうなツール等は利用不可。(チームに入った当初はテキストエディタもなく、「メモ帳」だった。)
自分は、Queryは昔から苦手で、SQLのほうが使い慣れているし、SQLを使うのは(環境としては使えるので)システ本体に機能を組み込んで使うのでなければ構わないという言質をとっておいて、状況確認やテスト結果確認の局面で利用している。
でも、SELECT命令を一度に順番に大量に実行させる方法がなかった。(私には方法がみつけられなかった)(CREATE PROCEDUREは利用禁止。RUNSQLSTMコマンドではSELECT命令は実行できない。)
というわけでこの日記は、利用可能の手持ちの道具を組み合わせて、SELECT命令を一括実行するツールを作成してみた、という内容の備忘録。
(プロラミング例は、引き続き別の日記で。使用方法は…そのうち追記する)
[プログラミング] SELECT命令一括実行ツールのプログラム例(1/3)
http://d.hatena.ne.jp/saul/20101125/p2
[プログラミング] SELECT命令一括実行ツールのプログラム例(2/3)
http://d.hatena.ne.jp/saul/20101125/p3
[プログラミング] SELECT命令一括実行ツールのプログラム例(3/3)
http://d.hatena.ne.jp/saul/20101125/p4
SELECT命令一括実行ツールのプログラム例(1/3)
IBM eSever iSeries専用。RPGとCLPから構成。
(1)プログラム名:EXSQ10C タイプ:CLP
PGM PARM(&PLIB &PSRC &PMBR &PCTL) DCL VAR(&PLIB) TYPE(*CHAR) LEN(10) DCL VAR(&PSRC) TYPE(*CHAR) LEN(10) DCL VAR(&PMBR) TYPE(*CHAR) LEN(10) DCL VAR(&PCTL) TYPE(*CHAR) LEN(10) DCL VAR(&WCTL) TYPE(*CHAR) LEN(2) DCL VAR(&WSID) TYPE(*CHAR) LEN(10) DCL VAR(&USER) TYPE(*CHAR) LEN(10) DCL VAR(&NBR) TYPE(*CHAR) LEN(06) /*開始*/ RTVJOBA JOB(&WSID) USER(&USER) NBR(&NBR) ADDLIBLE LIB(TOOLLIB) POSITION(*LAST) MONMSG MSGID(CPF0000) DLTOVR FILE(*ALL) /*一時的用の、1つのSELECT命令ファイルの作成*/ DLTF FILE(QTEMP/EXSQDT) MONMSG MSGID(CPF0000) CRTSRCPF FILE(QTEMP/EXSQDT) IGCDTA(*YES) /* CPYSRCF FROMFILE(TOOLLIB/EXSQDT) + TOFILE(QTEMP/EXSQDT) FROMMBR(EXSQDT) + TOMBR(EXSQDT) MBROPT(*ADD) */ ADDPFM FILE(QTEMP/EXSQDT) MBR(EXSQDT) CLRPFM FILE(QTEMP/EXSQDT) MBR(EXSQDT) /*一時的用の、実行結果ファイルの作成*/ CPYF FROMFILE(TOOLLIB/TEXTDATA) + TOFILE(QTEMP/EXSQLLG) TOMBR(EXSQLLG) + MBROPT(*REPLACE) CRTFILE(*YES) CLRPFM FILE(QTEMP/EXSQLLG) CHGPF FILE(QTEMP/EXSQLLG) SIZE(*NOMAX) /*一時的用に、SQLソースファイルの作成*/ /* メンバー SAMPLEMBR にレコード様式 QCLSRC がない。*/ /* というエラーに対応するための仕掛け */ CHKOBJ OBJ(QTEMP/QCLSRC) OBJTYPE(*FILE) MONMSG MSGID(CPF9801) EXEC(DO) CRTSRCPF FILE(QTEMP/QCLSRC) IGCDTA(*YES) ENDDO CPYSRCF FROMFILE(&PLIB/&PSRC) TOFILE(QTEMP/QCLSRC) + FROMMBR(&PMBR) /* RPG用一時指定変更*/ OVRDBF FILE(QCLSRC) TOFILE(QTEMP/QCLSRC) MBR(&PMBR) OVRDBF FILE(EXSQDT) TOFILE(QTEMP/EXSQDT) + MBR(EXSQDT) /* DSPLY命令を実行するかしないか */ IF COND(&PCTL *EQ 'DISPLAY') THEN(DO) CHGVAR VAR(&WCTL) VALUE('OK') ENDDO ELSE DO CHGVAR VAR(&WCTL) VALUE('NO') ENDDO /* SNDPGMMSG MSG('開始') MSGTYPE(*INFO) */ CALL PGM(EXSQ20R) PARM(&WCTL) /* SNDPGMMSG MSG('終了') MSGTYPE(*INFO) */ /*実行結果ファイルを保存する */ CPYF FROMFILE(QTEMP/EXSQLLG) TOFILE(&PLIB/WSQLLOG) + MBROPT(*REPLACE) CRTFILE(*YES) TAG888: DLTOVR FILE(*ALL) /* RUNQRY を実行するかしないか */ IF COND(&PCTL *EQ 'QRY') THEN(DO) RUNQRY QRYFILE((QTEMP/EXSQLLG)) ENDDO TAG999: ENDPGM
(注1)TOOLLIB/TEXTDATAは、133桁のレコード長のファイル。事前に準備。ここの環境では使いまわしている。
追記(2012/3/21):
(1)DDSを用意してCRTPFをする。
(2)198桁でも動作する。
A R DTREC A TEXTDATA 198O
[プログラミング] SELECT命令を一括実行するツールを作成してみた
http://d.hatena.ne.jp/saul/20101125/p1
[プログラミング] SELECT命令一括実行ツールのプログラム例(2/3)
http://d.hatena.ne.jp/saul/20101125/p3
[プログラミング] SELECT命令一括実行ツールのプログラム例(3/3)
http://d.hatena.ne.jp/saul/20101125/p4
SELECT命令一括実行ツールのプログラム例(2/3)
IBM eSever iSeries専用。RPGとCLPから構成。
(2)プログラム名:EXSQ20R タイプ:RPG
H Y/ 1 FQCLSRC IF E DISK F QCLSRC KRENAMEDBREC F KINFDS W#INFO FEXSQDT IF E DISK A UC F EXSQDT KRENAMETXREC ITXREC 99 I SRCDTA A133 I*レコード数 IW#INFO DS I B 156 1590W#RCD I*先頭52文字=DSPLY命令の表示制限 I DS I 1 80 DW080 I 1 52 DW052 C *ENTRY PLIST C PARM P\CTL 2 情報表示 C* C P#SQ30 PLIST C PARM P\OUT 1 C* C EXSR @INIT C EXSR @MAIN C EXSR @END C* C READ TXREC 91ダミー命令 C* C***************************************************** C* C @INIT BEGSR C* C P\CTL IFEQ 'OK' C SETON 69 表示する C ELSE C SETOF 69 表示しない C ENDIF C* C SETOF 72 1命令単位 C* C ENDSR C***************************************************** C* C @MAIN BEGSR C* C SETOF 91 C *IN91 DOWEQ*OFF C READ DBREC 91 C* C *IN91 IFEQ *ON C 69 'EOF' DSPLY C LEAVE 離脱 C ENDIF C* C MOVELSRCDTA DW080 C* C DW080 IFEQ *BLANK C ITER 次行へ C ENDIF C* C 69 DW052 DSPLY C* C '/*' SCAN DW080 71コメント? C *IN71 IFEQ *ON C MOVELDW080 A133 そのまま C MOVEL'N' P\OUT C* C N72 OPEN EXSQDT C WRITETXREC C CLOSEEXSQDT C SETOF 72 C CALL 'EXSQ30C' P#SQ30 1命令実行 C* C ITER 次行へ C ENDIF C* C ';' SCAN DW080 71デリミタ? C *IN71 IFEQ *ON C ';':' ' XLATEDW080 A133 区切り除去 C MOVEL'Y' P\OUT C* C N72 OPEN EXSQDT C WRITETXREC C CLOSEEXSQDT C SETOF 72 C CALL 'EXSQ30C' P#SQ30 1命令実行 C* C ITER 次行へ C ENDIF C* C N72 OPEN EXSQDT C SETON 72 C MOVELDW080 A133 そのまま C WRITETXREC C* C ENDDO C* C *IN72 IFEQ *ON 最終行 C W#RCD IFEQ 1 C MOVEL'Y' P\OUT 1行のみ C CLOSEEXSQDT C CALL 'EXSQ30C' P#SQ30 1命令実行 C ELSE C MOVEL'N' P\OUT 継続と判断 C CLOSEEXSQDT C CALL 'EXSQ30C' P#SQ30 1命令実行 C ENDIF C ENDIF C* C ENDSR C***************************************************** C* C @END BEGSR C* C 69 '@END' DSPLY C SETON LR C RETRN C* C ENDSR C*****************************************************
追記(2012/3/21):
EXSQDTが無くコンパイルエラーになるときは
CRTSRCPF FILE(QTEMP/EXSQDT) IGCDTA(*YES)
をしておく。
[プログラミング] SELECT命令を一括実行するツールを作成してみた
http://d.hatena.ne.jp/saul/20101125/p1
[プログラミング] SELECT命令一括実行ツールのプログラム例(1/3)
http://d.hatena.ne.jp/saul/20101125/p2
[プログラミング] SELECT命令一括実行ツールのプログラム例(3/3)
http://d.hatena.ne.jp/saul/20101125/p4
SELECT命令一括実行ツールのプログラム例(3/3)
IBM eSever iSeries専用。RPGとCLPから構成。
(3)プログラム名:EXSQ30C タイプ:CLP
PGM PARM(&POUT) DCL VAR(&POUT) TYPE(*CHAR) LEN(1) DCL VAR(&WSID) TYPE(*CHAR) LEN(10) DCL VAR(&USER) TYPE(*CHAR) LEN(10) DCL VAR(&NBR) TYPE(*CHAR) LEN(06) DCL VAR(&RCDS) TYPE(*DEC) LEN(10 0) /*開始*/ RTVJOBA JOB(&WSID) USER(&USER) NBR(&NBR) /*2回目以降のとき、セパレータを実行ログ用ファイルに追加する*/ RTVMBRD FILE(QTEMP/EXSQLLG) NBRCURRCD(&RCDS) IF COND(&RCDS *GE 1) THEN(DO) CPYF FROMFILE(TOOLLIB/EXSQF1) + TOFILE(QTEMP/EXSQLLG) + TOMBR(EXSQLLG) MBROPT(*ADD) FMTOPT(*NOCHK) ENDDO /*実行するSELECT命令を実行ログ用ファイルに追加する*/ CPYF FROMFILE(QTEMP/EXSQDT) TOFILE(QTEMP/EXSQLLG) + FROMMBR(EXSQDT) TOMBR(EXSQLLG) + MBROPT(*ADD) FMTOPT(*CVTSRC) /*コメント行ならば、ログに残すだけ*/ IF COND(&POUT *EQ 'N') THEN(GOTO CMDLBL(TAG900)) /*1つのSELECT命令になっているので、CRTQMQRYしてSTRQMQRYする*/ /* QPQXPRTFの名前で実行結果がスプール出力される*/ DLTQMQRY QMQRY(QTEMP/EXESQL) MONMSG MSGID(CPF0000) CRTQMQRY QMQRY(QTEMP/EXESQL) SRCFILE(QTEMP/EXSQDT) + SRCMBR(EXSQDT) STRQMQRY QMQRY(QTEMP/EXESQL) OUTPUT(*PRINT) MONMSG MSGID(QWM2701) EXEC(DO) CPYF FROMFILE(TOOLLIB/EXSQF2) + TOFILE(QTEMP/EXSQLLG) + TOMBR(EXSQLLG) MBROPT(*ADD) FMTOPT(*NOCHK) ENDDO /*実行結果の印刷を吸い上げて、1つのメンバーに書きだす*/ CPYSPLF FILE(QPQXPRTF) TOFILE(QTEMP/EXSQLLG) + JOB(&NBR/&USER/&WSID) SPLNBR(*LAST) + MBROPT(*ADD) MONMSG MSGID(CPF3303 CPF3309 CPF3342 CPF3344 CPF3478) DLTSPLF FILE(QPQXPRTF) JOB(&NBR/&USER/&WSID) + SPLNBR(*LAST) MONMSG MSGID(CPF3303 CPF3309 CPF3342 CPF3344 CPF3478) TAG900: /*実行するSELECT命令ファイルを、次のループの為に消去する*/ CLRPFM FILE(QTEMP/EXSQDT) MBR(EXSQDT) MONMSG MSGID(CPF0000) TAG999: ENDPGM
(注1)TOOLLIB/EXSQF1とは、セパレータとして文字"----+----:"で80桁になる1行のレコードを事前に準備。
(注2)TOOLLIB/EXSQF2とは、「SELECT命令が正しく実行されませんでした。」というメッセージの1行のレコードを事前に準備。
[プログラミング] SELECT命令を一括実行するツールを作成してみた
http://d.hatena.ne.jp/saul/20101125/p1
[プログラミング] SELECT命令一括実行ツールのプログラム例(1/3)
http://d.hatena.ne.jp/saul/20101125/p2
[プログラミング] SELECT命令一括実行ツールのプログラム例(2/3)
http://d.hatena.ne.jp/saul/20101125/p3