PL/IのSELECT文:現場で「ハマる」前に知っておくべき評価ロジックと制御の勘所
メインフレームの現場で長年PL/Iコードを読み込んでいると、若手から「なぜか意図しない処理に分岐する」という相談を受けることがよくある。その原因の多くは、`SELECT`文の評価順序や`OTHERWISE`の解釈ミス、あるいは`ON`ユニットとの兼ね合いにある。
今日は、バッチ処理で多用される`SELECT`文の「現場的」な作法について、深掘りしていこう。
—
1. SELECT文の評価順序:上から下への厳格なルール
PL/Iの`SELECT`文は、言語仕様として「上から順に評価し、最初に真(TRUE)となったWHEN条件だけを実行する」と決まっている。これはJavaやCの`switch-case`文(`break`を忘れると次へ突き抜ける)とは根本的に思想が異なる点だ。
以下のコードを見てほしい。
/i
/ VSAMレコードのステータスに応じた処理分岐の例 /
SELECT;
WHEN (REC_TYPE = ‘1’ & REC_STAT = ‘A’)
CALL PROC_ACTIVE_TYPE1;
WHEN (REC_TYPE = ‘1’)
CALL PROC_OTHER_TYPE1;
WHEN (REC_TYPE = ‘2’)
CALL PROC_TYPE2;
OTHERWISE
/ 予期せぬデータが来た場合の安全装置 /
CALL ERR_LOG_HANDLER;
END;
ここで重要なのは、「最初の`WHEN`で合致した瞬間に、その後の条件は一切評価されない」ということだ。もし`REC_TYPE = ‘1’`という条件を一番上に書いてしまうと、その下の`REC_TYPE = ‘1’ & REC_STAT = ‘A’`は永久に実行されない。条件の「包含関係」を考慮した並び順の設計こそが、バグを防ぐ鍵となる。
—
2. OTHERWISEは「必須」と考えよ
マニュアル上、`SELECT`文において`OTHERWISE`は省略可能だ。しかし、基幹システムのバッチ処理において「省略」は罪に近い。
もし`OTHERWISE`を記述せず、どの`WHEN`にも合致しなかった場合、プログラムは`ERROR`条件(CONDITION)を発生させて異常終了(U4038など)する。
/i
/ 現場でよくある事故:OTHERWISEがない /
SELECT (STATUS_CODE);
WHEN (1) CALL PROC_A;
WHEN (2) CALL PROC_B;
/ 3が来た瞬間に異常終了。安全なコードとは言えない /
END;
これを防ぐために、少なくともログ出力やエラーハンドリングを行う`OTHERWISE`を設けるのが「プロの作法」だ。また、意図的に何も処理したくない場合でも、`OTHERWISE;`と空で閉じるのではなく、コメントで意図を明記しておくべきだ。
—
3. 実践:VSAMアクセスとONユニットの連携
実務では、`SELECT`文の中に`VSAM`のステータスコードを判定するロジックを組み込むことが多い。この際、`ON`ユニットでエラーを捕捉しつつ、`SELECT`で処理を振り分ける構成が美しい。
/i
/ VSAMファイル読み込み後の判定ロジック /
ON CONDITION(VSAM_ERR_CON)
CALL ERR_PROC; / 共通エラーハンドラへ /
READ FILE(MAST_FILE) INTO(MAST_REC);
SELECT;
WHEN (STATUS_CODE = ’00’)
/ 正常終了:後続処理へ /
CALL PROCESS_RECORD;
WHEN (STATUS_CODE = ’10’)
/ EOF:ループ終了フラグを立てる /
EOF_FLG = ‘1’;
OTHERWISE
/ VSAMエラー:条件を意図的に発生させてONユニットへ飛ばす /
SIGNAL CONDITION(VSAM_ERR_CON);
END;
—
4. 現場のシニアからのアドバイス
最後に、デバッグ時や改修時に役立つ「勘所」をいくつか挙げておく。
- BUILTIN関数の活用: `SELECT`条件内で`SUBSTR`や`INDEX`などのBUILTIN関数を多用しすぎると、可読性が落ちるだけでなく、コンパイラの最適化パス次第で意図しない挙動を生むことがある。複雑な判定は、一度変数に格納してから`SELECT`に渡すのが定石だ。
- 大文字統一の徹底: 現代の環境では小文字も扱えるが、保守性の観点から依然として「大文字記述」を推奨する。これは、古いダンプ解析ツールやエディタでの検索性に直結するからだ。
- インデントの規約: `SELECT`の中の`WHEN`は、必ずインデントを下げろ。入れ子(Nested SELECT)になった際、インデントが崩れていると、どの`END`がどこに対応しているか、深夜のバッチ解析中に地獄を見ることになる。
PL/Iは古い言語だが、その論理的な構造は今の時代でも十分に堅牢だ。`SELECT`文一つとっても、なぜその順序なのか、なぜ`OTHERWISE`が必要なのかを言語化できるエンジニアこそが、大規模マイグレーションを生き抜くことができる。
コードは「動く」だけでなく「読みやすく、壊れにくい」ものであれ。健闘を祈る。
