こんにちは!IBMメインフレームの世界へようこそ。
JavaやCOBOLでの開発経験がおありの方なら、新しい言語を学ぶときのワクワク感と、「なんだこれ、他の言語と全然ルールが違うぞ…」という独特の戸惑いを、今まさに感じていらっしゃる頃ではないでしょうか。
特にPL/I(ピーエルアイ)は、IBMが1960年代に生み出した由緒正しい言語です。「科学技術計算も事務処理も、俺様一語言語で全部こなしてやんよ!」という、当時のエンジニアたちのロマンと野望が詰まったモンスター言語ですから、最初は少し面食らうかもしれません。
でも、安心してくださいね。今日は、レガシー世界の心臓部である「VSAMデータセット(KSDS・ESDS・RRDS)」と、それをPL/Iから操るための「ENVIRONMENT属性」について、どこよりも優しく、実務の現場でスッと腑に落ちる形でお話ししていきます。
難解に見えるメインフレームのストレージも、一つずつ紐解けば怖くありません。一緒に見ていきましょう!
—
1. 他の言語とはちょっと違う?PL/Iの「ファイル」と「データセット」の世界
JavaやC言語を使っていた方だと、「ファイルを読み書きする」というと、OSのディレクトリにあるテキストファイルやバイナリファイルを思い浮かべると思います。COBOLをご存知の方なら、`SELECT … ASSIGN TO …` お馴染みの世界ですね。
PL/Iでも基本の考え方は同じですが、IBMメインフレーム(z/OS)の基盤であるVSAM(Virtual Storage Access Method)という強力なデータ管理機構とタッグを組むとき、PL/Iは独特の構文でその個性を発揮します。
ここで一つ、PL/Iの大きな特徴であり、初心者が最初に「おや?」と思うポイントに触れておきましょう。
それは「PL/Iには、JavaやCOBOLのような厳格な『予約語(Keyword)』というものが、実はほとんど存在しない」という点です。
「えっ、じゃあどうやってコンパイラは言葉を区別しているの?」って思いますよね。
PL/Iの識別子(変数名やファイル名など)は、文脈によってその意味が決まります。例えば、ある場所で `READ` と書けば命令ですが、極端な話、変数名に `READ` と名付けても、コンパイラは前後の文脈から「あ、これは変数だな」と賢く判断してくれます(※もちろん、可読性のためにそんな紛らわしい名前は付けませんが!)。この「コンテキスト依存」の懐の深さが、PL/Iの大きな特徴なんです。
—
2. VSAMの3兄弟:KSDS・ESDS・RRDSのキャラクターを知ろう
メインフレームの基幹データベース(あるいは高効率なファイルシステム)として君臨するのがVSAMです。PL/Iからアクセスする代表的な3つのデータセット形式について、身近な例えでイメージしてみましょう。
① KSDS(Key-Sequenced Data Set / キー順データセット)
- イメージ: 日本の「国会図書館の蔵書システム」や、社員番号順に綺麗に並んだ「社員名簿ファイル」。
- 特徴: すべてのレコードに「主キー(Key)」と呼ばれる固有の目印があります。「社員番号 00123 のデータをくれ!」と言えば、一瞬でその場所を特定して取り出せます。さらに、キー順に並んでいるだけでなく、追加や更新も自由自在です。
- PL/Iでの使い道: 基幹システムのマスターファイル(顧客マスタ、商品マスタなど)の主役です。
② ESDS(Entry-Sequenced Data Set / 順次データセット)
- イメージ: 銀行の「ATMの取引履歴の通帳」や、監視カメラの「ログファイル」。
- 特徴: 後から来たデータは、問答無用で一番「後ろ」に追加されていきます(先入れ後出し…ではなく、到着順)。途中にデータを割り込ませることはできません。
- PL/Iでの使い道: 更新が不要で、ひたすら発生したイベントを記録していくログや、日々のトランザクションデータに向いています。
③ RRDS(Relative Record Data Set / 相対レコードデータセット)
- イメージ: マンションの「部屋番号付きの郵便受け」。
- 特徴: 「1号室」「2号室」というように、何番目のスロット(相対レコード番号)であるかが直接指定できます。キー文字列ではなく、数字の番地でダイレクトにアクセスします。
- PL/Iでの使い道: 高速なルックアップテーブルや、直接番号で引き当てたいマスターデータなどで活躍します。
—
3. ENVIRONMENT属性でVSAMの個性をPL/Iに教え込む
さて、これら3つの個性豊かなVSAMデータセットを、PL/Iのプログラムからどのように調理(アクセス)すればよいのでしょうか。
ここで登場するのが、今回の主役である`ENVIRONMENT`属性です。
ファイル宣言(`DECLARE`文)の中で、OSやVSAMに対して「このファイルはこういう性質のデータセットなんですよ」とこっそり教えてあげるための設定項目になります。
百聞は一見にしかず。実際のPL/Iコードを見てみましょう。
実践的なPL/Iコード例:KSDSを読み込むバッチプログラムの断片
1
/ ========================================================== /
/ 顧客マスタ(KSDS)をランダムアクセス(キー指定)で読み込む例 /
/ ========================================================== /
CUST_FILE: PROC OPTIONS(MAIN);
/ 1. ファイルとレコードの宣言 /
DCL CUST_DS FILE RECORD
ENV(VSAM); / ENVIRONMENT属性でVSAMであることを指定 /
/ VSAMのKSDSレコード構造体(COBOLの01レベルに相当) /
DCL 1 CUST_REC,
5 CUST_ID CHAR(5), / 顧客ID(これがVSAMのKSDSキーになる) /
5 CUST_NAME CHAR(30), / 顧客名 /
5 CUST_STATUS CHAR(1); / ステータス区分 /
DCL WS_EOF_FLG CHAR(1) INIT(‘OFF’);
/ 2. ファイルのオープン(UPDATE または INPUT) /
/ KSDSをキーでランダムに読む場合はUPDATEやINPUTを指定します /
OPEN FILE(CUST_DS) INPUT;
/ 3. 特定のキーを指定してレコードを読み込む例 /
CUST_ID = ‘00123’; / 探したい顧客IDをセット /
/ KEY(Cust_Id)を指定することで、KSDSのインデックス経由で一発検索! /
READ FILE(CUST_DS) INTO(CUST_REC) KEY(CUST_ID);
IF IOSCALE = 0 THEN DO; / 読み込み成功の判定(簡略化しています) /
PUT SKIP LIST(‘顧客名: ‘ || CUST_REC.CUST_NAME);
END;
ELSE DO;
PUT SKIP LIST(‘該当する顧客データが見つかりませんでした。’);
END;
/ 4. ファイルのクローズ /
CLOSE FILE(CUST_DS);
END CUST_FILE;
コードのポイント解説
- `ENV(VSAM)` の指定:
これがまさに `ENVIRONMENT` 属性の省略形です。「このファイルは通常の順次ファイル(PS)ではなく、VSAM管理下にあるデータセットだよ」とPL/Iコンパイラと実行時ライブラリに伝えています。
- `KEY(CUST_ID)`:
KSDS最大の武器である「キーアクセス」を行っている部分です。ESDSや通常の順次ファイルではこの書き方はできません。KSDSならではの特権です。
—
4. ESDSやRRDSを扱うときのENVIRONMENT属性のニュアンス
もしこれがKSDSではなく、ESDSやRRDSだったらどうなるでしょうか?
実務のマイグレーション現場では、JCL(Job Control Language)側の `DD` ステートメントと、PL/I側の `DECLARE` 文の組み合わせで制御します。
- ESDSを読む場合:
キーを指定したランダムアクセスはできません。そのため、`ENV(VSAM)` を指定した上で、通常のシーケンシャルファイルと同じように `READ FILE(…) INTO(…)` で先頭から順番に舐めるように(順次アクセスで)読み込んでいきます。
- RRDSを読む場合:
相対レコード番号(1番、2番…)を数値変数として用意し、KSDSの `KEY()` の代わりに、PL/Iのオプションを使ってスロット番号を指定してアクセスします。
レガシー移行の現場では、「元のCOBOLプログラムがどのようにVSAMを叩いていたか」の仕様書を読み解きながら、PL/I側で適切な `ENV` 属性やアクセス動詞(`READ`, `WRITE`, `REWRITE`)をマッピングしていく作業を行います。
—
さいごに
いかがでしたでしょうか?
「PL/I」「VSAM」「ENVIRONMENT属性」と聞くと、何やら呪文のようで難しく感じられたかもしれませんが、やっていることは至ってシンプルです。
1. データの性格(KSDS・ESDS・RRDS)を見極める
2. `ENV(VSAM)` を使って、VSAMであることをPL/Iに教えてあげる
3. データ構造(構造体)を定義して、目的に合わせた読み書き(キー順、順次など)を行う
この基本 さえ押さえておけば、どんなに古い巨大なメインフレームのプログラムであっても、怖がる必要はまったくありません。一つひとつのデータセットが持つ「性格」に寄り添って、優しくコードを書いてあげてくださいね。
皆さんのレガシーシステムのモダナイゼーションや、日々の開発作業がスムーズにいかなるよう、これからも応援しています!
