【実務・中級編】ON CONVERSIONによるデータ変換エラーのハンドリング – PL/Iの基本構文とデータ制御実践ガイド

こんにちは。メインフレームの現場で、日々COBOLやPL/Iの巨大なバッチ群と格闘しているエンジニアの皆さん。

夜間バッチの真っ最中に、突然のABEND(異常終了)通知。オペレーターからの「またデータエラーで落ちました」という連絡に、冷や汗を流した経験は何度あるでしょうか。特に、外部から連携されてくるテキストファイルや、古びたVSAMファイルからの読み込み時に発生する「数値変換エラー」は、レガシーシステムの保守において最も厄介な問題の一つです。

「おい、また数値項目のところにスペースやゴミデータが混ざってたぞ」
「どのレコードの、どの項目が原因なんだよ……ダンプを逆引きするしかないのか?」

そんな絶望的な状況を華麗に回避し、スマートに例外を捕捉・処理するために用意されているのが、PL/Iの `ON CONVERSION` ユニット です。

今回は、識別子に予約語を持たない(つまり文脈で解釈する気の利いた、かつ油断ならない)PL/Iの懐の深さに触れつつ、実務で即座に使える `CONVERSION` 条件のハンドリング術を、ベテランの視点から徹底的に解説します。

なぜPL/Iのデータ変換は一筋縄ではいかないのか

COBOLであれば、MOVE文の際に `NUMERIC` チェックを挟んだり、受取側を英数字項目にしておいてあとでゴニョゴニョしたりといった逃げ道があります。しかし、PL/Iの世界では、文字型(CHARACTER)から数値型(FIXED DECIMALなど)への暗黙の、あるいは明示的な型変換が行われる際、データの中身が「純粋な数字」になっていないと、容赦なくシステムは `CONVERSION` 条件(Condition)を発生させます。

もしこの `CONVERSION` を捕捉(Catch)していなければ、その瞬間にプログラムは強制終了し、お馴染みのU4038やシステムアベンドコードを吐いて夜間バッチを止めてしまいます。

ここでPL/Iの面白い(そして恐ろしい)ところは、「予約語が非常に少ない」という言語仕様にあります。例えば、`IF`, `READ`, `WRITE` といったキーワードであっても、文脈上それが変数名(識別子)として使われていれば、コンパイラは文句言わずに変数として扱います。
つまり、コードの書き方次第では、人間にとってもコンパイラにとっても「どこが制御文で、どこがデータなのか」が非常に分かりにくくなる泥沼に陥りやすいのです。だからこそ、例外処理のスコープ(有効範囲)を明確に制御するアーキテクチャが不可欠になります。

実践!ON CONVERSION によるエラーハンドリング

百聞は一見に如かず。実際にVSAM(あるいは順編成ファイル)からレコードを読み込み、パック十進数(FIXED DECIMAL)の項目にアンパックデータを代入する際の、実用的なPL/Iソースコードを見てみましょう。

大規模バッチのコーディング標準に則り、すべて大文字で記述し、BUILTIN関数を駆使した堅牢な実装例です。

1
CONVEX: PROC OPTIONS(MAIN);

/————————————————————–/
/ 宣言部 /
/————————————————————–/
DCL IN_FILE FILE RECORD INPUT; / 入力ファイル(順またはVSAM) /
DCL OUT_FILE FILE RECORD OUTPUT; / エラーログ出力ファイル /

/ 入力レコード(物理イメージ:すべて文字型として受け取る) /
DCL 1 IN_REC,
5 EMP_ID_CH CHAR(5), / 社員ID(英数字) /
5 EMP_NAME CHAR(20), / 氏名 /
5 SALARY_CH CHAR(8); / 給与(文字形式の数値) /

/ 内部処理用レコード(数値型定義) /
DCL 1 WORK_REC,
5 W_EMP_ID FIXED BIN(31),
5 W_SALARY FIXED DEC(9,2); / ここに変換される /

DCL EOF_FLG CHAR(1) INIT(‘OFF’);
DCL ERR_CNT FIXED BIN(31) INIT(0);

/ 組み込み関数の宣言(明示的指定) /
DCL (ONCHAR, ONSOURCE) BUILTIN;

/————————————————————–/
/ ファイルオープン /
/————————————————————–/
OPEN FILE(IN_FILE) INPUT,
FILE(OUT_FILE) OUTPUT;

/————————————————————–/
/ CONVERSION条件の捕捉(ONユニットの定義) /
/————————————————————–/
ON CONVERSION
BEGIN;
ERR_CNT = ERR_CNT + 1;

/ どのフィールドでエラーが起き、どんなゴミが入っていたかをログへ /
PUT SKIP EDIT (
CONVERSION ERROR DETECTED ‘,
‘EMP_ID: ‘, EMP_ID_CH,
‘ / INVALID DATA SOURCE: ”’, ONSOURCE, ””
) (A, A, A, A, A, A);

/ 業務要件に応じたリカバリ処理: /
/ エラー値の場合は強制的にゼロを代入して処理を続行させる /
W_SALARY = 0;

/ 注意:ゴートゥー(GOTO)でONユニットから脱出するのが定跡 /
GOTO BYPASS_REC;
END;

/————————————————————–/
/ メインループ /
/————————————————————–/
READ FILE(IN_FILE) INTO(IN_REC);

DO WHILE (EOF_FLG = ‘OFF’);

/ ここで文字型から数値型への暗黙のデータ変換が発生する /
/ もしSALARY_CHにスペースやアスタリスク等の不正文字があれば /
/ 直ちに上記の ON CONVERSION が発動する。 /
W_SALARY = SALARY_CH;
W_EMP_ID = EMP_ID_CH;

/ 正常系データの処理(今回は省略して書き出しのみ) /
WRITE FILE(OUT_FILE) FROM(WORK_REC);

BYPASS_REC:
/ 次レコードの読み込み /
READ FILE(IN_FILE) INTO(IN_REC);
END;

/————————————————————–/
/ 終了処理 /
/————————————————————–/
CLOSE FILE(IN_FILE),
FILE(OUT_FILE);

PUT SKIP EDIT (‘TOTAL CONVERSION ERRORS: ‘, ERR_CNT) (A, F(5));

END CONVEX;

コードの解説と、現場で使えるプロの技

上記のコードには、何十年ものメインフレーム開発の歴史の中で培われた「知恵」が詰まっています。いくつか重要なポイントを解説しましょう。

1. `ONSOURCE` と `ONCHAR` バージョンの活用

PL/Iの強力なBUILTIN関数である `ONSOURCE` は、「まさに変換しようとして失敗した元のデータ(文字列全体)」を返してくれます。
これにより、「一体ファイルのどこにどんなゴミデータが入っていたのか」をオペレータや上流工程の担当者に正確なエビデンスとして突きつけることができます。デバッグの際にダンプリストを何時間も睨みつける必要はもうありません。

2. ONユニット内からの `GOTO` 脱出

これが最も重要なポイントです。`CONVERSION` 条件が発生した際、PL/Iはエラーの原因となった式(今回の場合は `W_SALARY = SALARY_CH;`)の途中で処理を中断しています。
もし `GOTO` で処理の的外(今回のコードでは `BYPASS_REC:` ラベル)にジャンプさせないと、プログラムはエラーが起きた文の再実行を試みようとし、再び無限ループ的にエラーを引き起こすか、予期せぬ挙動を示します。
「ONユニットの中では原則として `GOTO` を使って安全な地点へ脱出する」というのは、PL/Iプログラミングにおける鉄則です。

3. スコープ(有効範囲)の意識

`ON` ユニットは、宣言された位置から動的に有効になります。プログラムのモジュール化を進める中で、どのサブルーチンやブロックでどのエラーを捕捉したいのか、`BEGIN … END` ブロックのネストを意識して設計しないと、意図しない場所でエラーハンドリングがグローバルに捕捉されてしまい、かえってバグの切り分けを困難にします。

まとめ:レガシーの海を泳ぎ切るために

メインフレームのシステムは、私たちが寝ている間も、膨大なトランザクションを処理し続けています。その土台を支えるPL/Iは、一見古臭く見えるかもしれませんが、今回紹介した `ON CONVERSION` のような例外処理機構を正しく使いこなせば、予期せぬ不正データに対してもビクともしない、極めて堅牢な基幹バッチシステムを構築できます。

「データがおかしいからバッチが落ちました」で終わらせるのではなく、「不正データを即座に検知し、ログに詳細を吐き出し、安全にリカバーして処理を継続する」。
そんな、システムアーキテクトとしての技量が試される場面で、今回のコードと知見をぜひ皆さんの現場で役立ててください。

それでは、次回のメインフレーム・アーキテクチャ講座でお会いしましょう。

タイトルとURLをコピーしました