前回はIBM i の物理(論理)ファイルのデフォルト以外のメンバーを利用する手法を紹介しましたが、
今回はそのメンバーをDelphi/400から作成・削除する方法をご紹介します。
概要・使用目的
ワークファイルをジョブごとに分けて使いたい場合には、主に以下の3つの方法があります。
- ①:ワークファイルをQTEMPにコピーまたはコンパイルして使用する。
- ②:ワークファイル内の第1キーをジョブ番号とし、ジョブごとに一意になるようにする。
- ③:ワークファイル内にメンバーを追加し、ジョブごとに割り当てて独立したメンバーを使用する。
今回はこのうち③についてご紹介していきます。
IBM i(AS/400・iSeries)の物理ファイルや論理ファイルにおける
『メンバー』とは、同じファイル内の論理的な区分です。
複数のメンバーを活用することで、データの組織化と管理の効率化を図ることができます。
例えば各ソースファイル(QDDSSRCなど)も複数のメンバーを使用しており、
それぞれのソースは各メンバー内に記述されています。
ワークファイルを使用する場合は上記①のQTEMPに作成するパターンが一般的ですが、
③のメンバーを使用する場合にはQTEMPと比較して以下のメリット・デメリットがあります。
- <メリット>
- 他のジョブからでもメンバーを指定すれば(エミュレータのRUNQRY等)参照できるため、
トラブル発生時にワークファイルの内容確認が容易。 - IntraWebなどでネイティブ接続とそれ以外(FireDAC等)でジョブが分かれる場合でも、
メンバーを指定することでワークファイルを共用できる。
- 他のジョブからでもメンバーを指定すれば(エミュレータのRUNQRY等)参照できるため、
- <デメリット>
- 今回紹介するようなメンバー追加・削除の一手間が必要。
- 使用後はジョブ終了時に自動で解放されないため、
手動で除去しておかないとIBM i のディスク容量が徐々に圧迫される。
今回はワークファイルでメンバー処理を行うことを想定し、
Delphi/400からメンバー追加・削除を行う際の手順を紹介します。
前提条件
今回は、下図のようにメンバーを複数使用する想定です。
メンバー名は「M」+ジョブ番号の合計7桁としています。
(他のジョブと重複しない、かつ先頭数字は不可なので「M」をつける)
メンバーを複数使用するためには、DDSのコンパイル(CRTPF)時に
メンバーの最大数(MAXMBRS)のパラメータを「*NOMAX」に設定しておきます。
このメンバーの最大数は、既にコンパイルされたファイルでも
物理ファイル変更(CHGPF)から再設定可能ですが、
SQL(CREATE TABLE)で生成されたファイルはメンバーの複数使用ができません。
物理ファイルのメンバー追加にはADDPFMコマンドを、
メンバー削除にはRMVMコマンドを使用します。
事前にエミュレータでコマンドを発行してみて、メンバーの追加や削除ができるかご検証ください。
/*メンバー追加のコマンド*/
ADDPFM FILE(ライブラリー名/ファイル名) MBR(メンバー名) TEXT('テキスト(省略可)')
/*メンバー除去のコマンド*/
RMVM FILE(ライブラリー名/ファイル名) MBR(メンバー名)
エミュレータでコマンドを発行してみた際にエラーが出た場合、それぞれの意味は以下の通りです。
- <追加時・削除時>
CPF7312:ライブラリー~~~にファイル~~~が見つからない。- ライブラリー名やファイル名に誤りがないかご確認ください。
- ライブラリー名を省略した場合は*LIBLが使用されるため、ライブラリーリストに存在するかご確認ください。
- <追加時>
CPF5812:メンバー~~~はライブラリー~~~のファイル~~~に既に存在している。- この名前のメンバーは既に存在するため、他のメンバー名を指定してください。
- 同名で再作成したい場合は、既存のメンバーを削除またはリネームして下さい。
- <削除時>
CPF5815:メンバー~~~がライブラリー~~~のファイル~~~に見つからない。- この名前のメンバーが存在しません。既に削除済みのメンバーをもう一度削除しようとした際などに発生します。
- <削除時>
CPF7310:メンバー~~~は~~~のファイル~~~から除去されませんでした。- 何らかの理由でメンバー削除に失敗しました。当該メンバーが他のジョブから使用中の場合などに発生します。
TCall400を使ったメンバー追加・削除方法
メンバー追加・削除のためのCLを作成して
Delphi/400からTCall400を使って呼び出す場合、以下のように記述します。
(ロジックは一例です。実際の要件にあわせて調整してください。)
今回のCLでは追加・削除を同じCLで実施し、パラメータで呼び分けるようにしています。
また追加時も既存メンバーが存在すれば削除することで、上書きを可能にしています。
なお対象ファイルのライブラリーは、ライブラリーリストに存在する前提となります。
(存在しない状態でこのCLをキックするとMSGWになります。)
<CLソース>
※プログラム名は任意。以降の文章では「YSCMBR」としています。
/********************************************************************/
/* NAME : ファイルメンバー追加/削除 */
/********************************************************************/
PGM PARM(&P@PMOD &P@FLNM &P@MBNM &P@ERRC )
/*CL変数定義*/
/*パラメーター*/
/*プログラムモード 0:作成 1:削除 */
DCL VAR(&P@PMOD) TYPE(*CHAR) LEN(1)
/*ワークファイル名 (文字10桁)*/
DCL VAR(&P@FLNM) TYPE(*CHAR) LEN(10)
/*メンバー名 (文字10桁)*/
DCL VAR(&P@MBNM) TYPE(*CHAR) LEN(10)
/*エラーフラグ (文字1桁)*/
DCL VAR(&P@ERRC) TYPE(*CHAR) LEN(1)
/*メンバーが既に存在すれば除去*/
CHKOBJ OBJ(&P@FLNM) OBJTYPE(*FILE) MBR(&P@MBNM)
MONMSG MSGID(CPF9815) EXEC(GOTO CMDLBL(#ST1000))
RMVM FILE(&P@FLNM) MBR(&P@MBNM) /*除去実施*/
MONMSG MSGID(CPF7310) EXEC(GOTO CMDLBL(#PGMERR))
#ST1000:
IF COND(&P@PMOD = '0') THEN(DO)
/*メンバーを追加*/
ADDPFM FILE(&P@FLNM) MBR(&P@MBNM) /*追加実施*/
MONMSG MSGID(CPF9999) EXEC(GOTO CMDLBL(#PGMERR))
ENDDO
/*正常終了*/
RETURN
/*エラー終了*/
#PGMERR:
CHGVAR VAR(&P@ERRC) VALUE('1')
ENDPGM
<Delphi/400 呼び出しソース>
以下のソース中でジョブ番号の取得を行っている関数『GetMyJobNo』は、
デフォルトでは存在しません。以下のTipsをもとに作成してみて下さい。
⇒ Delphi/400 プログラム実行中のジョブ情報取得方法
{*******************************************************************************
目的: メンバー追加/削除処理 TCall400のExecute
引数:
戻値:
*******************************************************************************}
procedure TForm2.Button1Click(Sender: TObject);
var
i: Integer;
sJOBN: String;
begin
// ジョブ番号(6桁)を取得し、先頭に「M」をつける
sJOBN := 'M' + GetMyJobNo;
with Call4001 do
begin
LibraryName := 'TESTLIB'; // CLのライブラリー名、*LIBLも可
ProgramName := 'YSCMBR'; // CLのプログラム名、任意
// パラメータの追加(ここは設計画面で実施してもよい)
ClearParams; // 初期化
AddParam('A', 1, 0); // プログラムモード 0:作成 1:削除
AddParam('A', 10, 0); // ワークファイル名
AddParam('A', 10, 0); // メンバー名
AddParam('A', 1, 0); // エラーコード(戻り値)
// パラメータ値を指定して実行
Value[0] := '0'; // プログラムモード 0:作成 1:削除
Value[1] := 'FILENAME'; // ワークファイル名(※実際の値を指定)
Value[2] := sJOBN; // メンバー名(M+ジョブ番号)
Value[3] := '0'; // エラーコード(戻り値)
Execute;
if (Value[3] <> '0') then
begin
// 処理失敗時のメッセージ(一例)
ShowMessage('処理に失敗しました。');
end;
end;
end;
ネイティブ接続不使用時のメンバー追加・削除方法
前回の記事(OVRDBF)の時と同様に、
IntraWebで構築している場合やTAS400を全く使用していない場合など、
ネイティブ接続を不使用のときにはTAS400・TCall400コンポーネントが使えません。
このような場合は、クエリーコンポーネント(TFDQueryやTSQLQuery)を使って
SQL単独で実行可能です。
Delphi/400では、クエリーのSQL文にCALLコマンドを指定してExecSQLすると、
そのコマンドを実行することができます。
(TAS400のRemoteCmdと同様、戻り値を受け取ることはできません。)
CALLコマンドの指定方法は、以下の2通りがあります。
以下1.2.いずれかのコマンドをクエリーのSQLプロパティにセットしてExecSQLします。
1.メンバー処理を行うCLを呼び出す
LibName・CLNameは、それぞれCALLするCLのライブラリ名とプログラム名です。
このコマンドは上記で例示したソースのCLを呼び出すイメージとなっています。
また、パラメータとして処理成否を渡していますが受け取ることはできません。
2.コマンド実行 (QCMDEXC) APIを使ってコマンドを直接発行する
CL使用時とは異なり、処理失敗時のエラーが実行中のDelphi/400アプリケーションに直接返されます。
(既に存在するメンバーをADDPFM、逆に存在しないメンバーをRMVMしようとした場合など)
コマンドを直接発行する前に、メンバーの存在チェックを行っておくと安全です。詳細は後述します。
1.メンバー処理を行うCLを呼び出す例
メンバー追加例:CALL PGM(TESTLIB/YSCMBR) PARM(('0') ('FILENAME') ('MEMBNAME') ('0'))
メンバー削除例:CALL PGM(TESTLIB/YSCMBR) PARM(('1') ('FILENAME') ('MEMBNAME') ('0'))
2.コマンド実行 (QCMDEXC) APIを使ってコマンドを直接発行する例
メンバー追加例:CALL QCMDEXC('ADDPFM FILE(FILENAME) MBR(MEMBNAME)')
メンバー削除例:CALL QCMDEXC('RMVM FILE(FILENAME) MBR(MEMBNAME)')
2.においては、コマンドを直接発行する前に、メンバーの存在チェックを行っておくと安全です。
メンバーの一覧を出力してくれるSYSPARTITIONSTATビューを使って、
対象のファイルやメンバーの存在チェックができます。【※V7R1以降で確認】
(詳細:SYSPARTITIONSTAT – IBM Documentation )
クエリーを使って以下のようなSQLを発行して、一致するメンバー名があればレコードが抽出されます。
(※WHERE句はそれぞれライブラリ名、ファイル名、メンバー名。
ライブラリは「*LIBL」を指定できないため、直接指定または全ライブラリを対象とします。)
SELECT DISTINCT SYS_DNAME, SYS_TNAME, SYS_MNAME
FROM QSYS2/SYSPARTITIONSTAT
WHERE SYS_DNAME = 'TESTLIB'
AND SYS_TNAME = 'FILENAME'
AND SYS_MNAME = 'MEMBNAME'