ここでは主に、IFS領域のストリーム・ファイルに対するAS400のコマンド、VSCode-Code for IBMiでのアクションの操作を比較していきます。
【コマンド一覧】
- Create SQL ILE RPG Program(IFS)
- Create SQL ILE RPG Module(IFS)
- Create Bound CL Program(IFS)
- CreateCommand
- CreateCommand(AllowReturnVariables-CRTCMD)
- Set CSID(IFS)
- Run SQL Statement(IFS)
- Call Program
- Delete Object
実行環境は以下の通りです。
| 項目 | バージョン値 |
|---|---|
| IBMi | V7R3 |
| ACS | バージョン: 1.1.9.8 ビルド ID: 5140 |
| ACS java | java.version: 21.0.7 |
| VSCode | 1.100.3 |
| Code for i | 2.15.3 |
Create SQL ILE RPG Program(IFS)
CRTSQLRPGI = SQL文を含むRPGプログラムの作成
【AS400】
Code for IBMiの標準アクションCreate SQL ILE RPG Programに記載されているコマンドを参考にして実行してみました。(ライブラリ名:MYLIB、ディレクトリ名:MYDIRに書き換えています)
CRTSQLRPGI OBJ(MYLIB/BPL010@S1) SRCSTMF('/home/MYDIR/BPL010@S1.sqlrpgle')
CLOSQLCSR(*ENDMOD) OPTION(*EVENTF DBGVIEW(*SOURCE) TGTRLS(*CURRENT)
CVTCCSID(*JOB)
F4からより詳細なオプション値を指定することもできますが、今回上記以外はデフォルトで実行しています。
【Code for IBMi】
対象:.sqlrpgle拡張子のストリームファイル
VSCode接続が成功しているとき、左ペインの下部IFS BROWSERに接続ユーザーのルートディレクトリが表示されています。(初回接続時、自動で作成されるようです)
ルートディレクトリ以下には、任意のディレクトリ、ファイルを配置することができるため、以下のように右クリックからsqlrpgleファイルを作成してみます。

ソースコードを書き込み後、ctrl+sで保存し、ファイルを右クリックしてRun Actionを選択。

コマンドパレットに、Code for IBMiの標準アクション(Member,Streamfile,Object)の中から対応したアクション名が表示されます。

アクション選択後、実行するコマンドの内容が表示されるので、オプション値など変更箇所があれば書き換えます。
Enterで実行。

ここでエラーが発生しました。
IBMiのバージョンがV7R3以下の場合、RPGPPOPT(*LV2)のオプションが非対応のため、コマンド内容から除外する必要があります。
何回も同じエラーが出ないよう、標準アクションコマンドの内容を編集します。(任意)
VSCodeの下部の歯車アイコンをマウスオーバーし、メニューが出てきたらActionを選択。

Code for IBMiの標準アクションリストが表示されます。

編集したいアクションを選択し、コマンドを変更(以下からRPGPPOPTを削除)して保存します。

Create SQL ILE RPG Module(IFS)
CRTSQLRPG SQL文を含むRPGモジュールの作成
【AS400】
SQLステートメントを含むRPGモジュールを作成します。SQLRPGLEプログラム作成との違いは、OBJTYPE(*MODULE)を指定する点です。
CRTSQLRPGI OBJ(MYLIB/BPL010@S1) SRCSTMF('/home/MYDIR/BPL010@S1.sqlrpgle')
OBJTYPE(*MODULE) OPTION(*EVENTF TGTRLS(*CURRENT) DBGVIEW(*SOURCE)
CLOSQLCSR(*ENDMOD) CVTCCSID(*JOB)
【Code for IBMi】
対象:.sqlrpgle拡張子のストリームファイル
こちらは選択するアクションがCreate SQL ILE RPG Moduleに変わるだけで、手順はCreate SQL ILE RPG Program(IFS)と同様です。
Create Bound CL Program(IFS)
CRTBNDCL = CLソース・プログラムから統合化言語環境(ILE)制御言語(CL)プログラムを作成します。
【AS400】
Code for IBMiの標準アクションCreate Bound CL Programに記載されているコマンドを参考にして実行してみました。(ライブラリ名:MYLIB、ディレクトリ名:MYDIRに書き換えています)
CRTBNDCL PGM(MYLIB/RTVINF) SRCSTMF(`/home/MYDIR/RTVINF.clle`)
OPTION(*EVENTF) DBGVIEW(*SOURCE)
5250のコマンド詳細画面です。
IFSのファイルをコンパイル対象とする場合、ライブラリとソース・ファイルの項目は空欄で実行可能です。

【Code for IBMi】
対象:.cle、.clle拡張子のストリームファイル
以下のCLソースを作成してみました。
システム日付、システム名、ユーザ名、システムとユーザそれぞれのCCSIDを取得してくるCLプログラムです。
PGM
DCL VAR(&W@DAT) TYPE(*CHAR) LEN(6)
/*システム*/
DCL VAR(&W@SYS) TYPE(*CHAR) LEN(8)
DCL VAR(&W@SC) TYPE(*DEC) LEN(5 0)
DCL VAR(&W@SCC) TYPE(*CHAR) LEN(5) /*変換用*/
/*ユーザ*/
DCL VAR(&W@USR) TYPE(*CHAR) LEN(10)
DCL VAR(&W@UC) TYPE(*DEC) LEN(5 0)
DCL VAR(&W@UCC) TYPE(*CHAR) LEN(5) /*変換用*/
RTVSYSVAL SYSVAL(QDATE) RTNVAR(&W@DAT)
RTVNETA SYSNAME(&W@SYS)
RTVSYSVAL SYSVAL(QCCSID) RTNVAR(&W@SC)
RTVJOBA USER(&W@USR)
RTVUSRPRF USRPRF(&W@USR) CCSID(&W@UC)
CHGVAR VAR(&W@SCC) VALUE(&W@SC)
CHGVAR VAR(&W@UCC) VALUE(&W@UC)
SNDPGMMSG MSG('SYSTEM DATE : ' *CAT &W@DAT) MSGTYPE(*COMP)
SNDPGMMSG MSG('SYSTEM NAME : ' *CAT &W@SYS) MSGTYPE(*COMP)
SNDPGMMSG MSG('SYSTEM CCSID: ' *CAT &W@SCC) MSGTYPE(*COMP)
SNDPGMMSG MSG('USER NAME : ' *CAT &W@USR) MSGTYPE(*COMP)
SNDPGMMSG MSG('USER CCSID : ' *CAT &W@UCC) MSGTYPE(*COMP)
ENDPGM
アクションからCreate Bound CL Programを選択し、実行します。

Run SQL Statement(IFS)
RUNSQLSTM = SQLステートメントの実行
RUNSQLSMTはSQLを扱うものですが、クエリの結果セットを受け取るためのSELECT文が使えないことがわかりました。(サブクエリとしては使用可)。
そこで以下のようなSQLステートメントを作成しました。
【AS400】
DROP TABLE IF EXISTS QTEMP.HINMSP;
CREATE TABLE QTEMP.HINMSP AS (SELECT * FROM QEOLFF.HINMSP)
WITH NO DATA;
INSERT INTO QTEMP.HINMSP VALUES
(10201,'ニューブング AAA','ニューブング AAA','1200',500,250,1,30,500,15000);
INSERT INTO QTEMP.HINMSP VALUES
(10201,'ニューブング BBB','ニューブング BBB','1100',880,540,34,60,29920,52800);
このように、参照するファイルを使用して同じ構造のファイルを作成することができます。
WITH NO DATAは参照先の構造だけを使用し、空のテーブルを作成する場合に指定します。
RUNSQLSTM SRCSTMF('home/MYDIR/SQLHIN.sql') COMMIT(*NONE) NAMING(*SQL)
実行後、WRKQRYで確認してみました。

参照先のHINMSPのDDSに定義されているCOLHDGS列名も反映されています。
CRTDUPOBJの操作に近いように思います。
【Code for IBMi】
対象:.sql拡張子のストリーム・ファイル
上記と同じようにCode for IBMiのアクションでも実行してみました。


コンソールの出力結果から成功していることがわかりますが、QTEMPを見にいくとHINMSPは作られていません。
※Run SQL Statementアクションを実行すると、アクション単位でジョブ・セッションが終了するのでADTSでサインオフしたときと同じようにQTEMPに作られたものは無くなります。
そこで以下のように書き換えてみました。
DROP TABLE IF EXISTS QEOLFF.HINTMP;
CREATE TABLE QEOLFF.HINTMP AS (SELECT * FROM QEOLFF.HINMSP)
WITH NO DATA;
INSERT INTO QEOLFF.HINTMP VALUES
(10201,'ニューブング AAA','ニューブング AAA','1200',500,250,1,30,500,15000);
INSERT INTO QEOLFF.HINTMP VALUES
(10201,'ニューブング BBB','ニューブング BBB','1100',880,540,34,60,29920,52800);
参照元と同じ場所に、別のオブジェクト名で作成しました。
NOTEBOOKで結果を確認したところ、うまくいっています。

削除もしてみました。
HNTEIK(定価)800を超えるレコードを削除。


活用面について
上述の例ではSQLステートメント内に値を記述してINSERTしていますが、RunSQLStatementは基本的に変数が使えないため、パラメータ入力から値をセットしてINSERTすることようなことができません。
これでは実用的とは言えません。
WITH NO DATAで空のテーブルを作るかわりに、WITH DATAで中身のデータも参照しつつ条件を組みこんでみます。

構文エラーが出ているようですが、アクション実行は成功しています。
このように、元のファイルデータから移し先のファイルにSQL条件の抽出結果を落とす使い方が現実的かと考えます。
NOTE
ストアドプロシージャが使えると、ファイルのデータをテキストやCSV、PDFとしても出力できるようです。
※IBM i 7.4TR5 / 7.3TR11以降であることと、PTFの適用が必要とのこと
Create Command
CRTCMD = ユーザー定義コマンドの作成
指定したライブラリー内にコマンドを作成します。したがって、そのライブラリーがライブラリー・リストに加えられていない場合、コマンドは呼び出せません。
コマンド作成には、コマンドソースと呼び出すCLプログラムの2つが必要となるので、ここでは上述したCLLEプログラムを指定します。
【AS400】
CRTCMD CMD(MYLIB/RTVINF) PGM(MYLIB/RTVINFL)
SRCSTMF('/home/ITSSSH/ifstest/qcmdsrc/RTVINF.cmd') OPTION(*EVENTF)
【Code for IBMi】
対象:.cmd拡張子のストリーム・ファイル
注意点
ライブラリにあるソースから指定(右クリック)した場合と、IFS領域のストリームファイルを指定した場合では、同じアクション名でも実行内容が異なります。
/*ライブラリ内のソースを対象としてアクション選択時*/
CRTCMD CMD(MYLIB/RTVINF) PGM(MYLIB/RTVINFL)
SRCFILE(MYLIB/QCMDSRC) ALLOW(*ALL) CURLIB(*NOCHG) PRDLIB(*NOCHG)
/*IFSのストリームファイルを対象としてアクション実行時*/
CRTCMD CMD(MYLIB/RTVINF) PGM(MYLIB/RTVINFL)
SRCSTMF('/home/ITSSSH/ifstest/qcmdsrc/RTVINF.cmd') OPTION(*EVENTF)
Create Command(AllowReturnVariables-CRTCMD)
作成手順はCreate Commandと同じですが、こちらは呼び出すCLプログラムにパラメータを渡して実行します。
【AS400】
CMDに作成するコマンド名、PGMに呼び出すCLプログラム、SRCSTMTFにソースのパスを指定します。
CRTCMD CMD(MYLIB/TGLSSHSVR) PGM(MYLIB/SSHSVRL) SRCSTMF('home/MYDIR/TGLSSHSVR.cmd')
コマンド作成し、F4で詳細を開いたときの状態です。
ソースで指定したものが反映されていることがわかります。

【Code for IBMi】
対象:.cmd拡張子のストリーム・ファイル
私の環境では、STRTCPSVRでSSHを起動してもうまくVSCode接続できず、毎回QShellを開いてコマンドを打つ必要がありました。そのため、開始か終了のパラメータを指定してSSHジョブを操作するCLプログラムと、それを呼び出す専用のコマンドを作ってみようと思いました。

コマンドのソースは以下の通りです。KWDに指定した名前が、CLで受け取るパラメータになります。

アクション呼び出し時、プログラム名がコマンドと同じで設定されているので、同じ名前でないときは適宜書き換える必要があります。

現在、自作したコマンドをVSCode側から呼び出す方法はないようです。CLプログラムであればCall Programアクションを使用
Set CCSID(IFS)
【AS400】
Code for IBMiの標準アクションからSetCCSIDのコマンド内容をそのまま実行してみると、エラーとなります。

調べてみて、以下のコマンドが正しい内容と分かりました。
CHGATR OBJ('/home/MYDIR/test01.rpgle') ATR(*CCSID) VALUE(1208)
実行結果

DSPLNKからファイルを参照すると、CCSIDが変更されています。

【Code for IBMi】
対象:IFS領域のストリーム・ファイル
VSCodeの右クリックから作成されたストリームファイルはCCSID1208となります。
.rpgleソースはこのままだとコンパイルエラーとなるので、変更が必要です。
Code for IBMi標準アクションではCCSID1252と5035が実装されていますが、アクションを複製し、必要に応じたCCSID値を追加すると良いかと思います。
Call Program
【AS400】
以下の内容のCLプログラムを呼び出してみます。

パラメータを必要とするプログラムに何も渡さないと、エラーが表示されることが確認できます。

【Code for IBMi】
対象:ユーザーライブラリー・リスト内のオブジェクト
IBMiコマンド実行時と同じように、パラメータありなしを比較してみます。

パラメータなしで呼び出した場合のコンソール出力結果です。
実行されたように見えますが、プロンプトが点滅したままで正常終了していないようです。

パラメータを以下のように正しく設定すると、コンソールにも正しく出力されています。


Code for IBMiのCall Programによってプログラムエラーが発生すると、SSHのジョブQP0ZSPWPが、エラーした分だけアクティブ・ジョブとして滞留し続けます。
現状この問題は、調べた限りだとCode for IBMi上での対応方法が見つからず、WRKACTJOBから該当ジョブを落とす必要があります。
Delete Object
【AS400】
PDMのオブジェクト一覧から4番を選択するか、コマンドDTLOBJから実行します。

【Code for IBMi】
対象:ユーザーライブラリー・リスト内のオブジェクト

同じように、オブジェクトを選択し右クリックでDeleteからも削除が行えます。
この場合のDelete操作は、ソースファイルのメンバや、IFSのストリームファイルに対しても行うことができます。

ObjectBrowserのフィルター削除で消されるのはフィルター条件だけで中身は当然無事ですが、クリックの選択対象を誤らないように気を付けましょう。
当記事の著作権はIBMに帰属します。
詳細はこちらを参照ください。









