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命令を一括実行するツールを作成してみた、という内容の備忘録。


(※)RPG (プログラム言語)


(プロラミング例は、引き続き別の日記で。使用方法は…そのうち追記する)

[プログラミング] 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