現場の「数値項目にゴミデータ」問題:ON CONVERSIONでバッチを落とさない技術
メインフレームのバッチ処理で、最も心臓に悪いエラーの一つが「データ変換エラー」だ。VSAMファイルやフラットファイルから読み込んだ文字列データの中に、本来「0-9」が入るべき場所に空白や制御コード、はたまた全角文字が紛れ込んでいた経験はないだろうか。
何も対策をしていなければ、OSは迷わず「S0C7」や「コンパイラによる異常終了」を叩き出し、夜間バッチを停止させる。担当者は深夜の呼び出しに怯え、貴重な睡眠時間を削ってダンプを解析することになる。
今回は、そんな悲劇を未然に防ぎ、不正データすらも「想定内」としてリカバリする、PL/Iの強力な武器「ON CONVERSION」について解説する。
—
1. なぜ「ON CONVERSION」なのか
PL/Iには、データ型が異なる代入(例えば`CHARACTER`から`FIXED DECIMAL`への転送)が発生した際、自動的に変換を行う機能がある。しかし、変換先が数値型であるにもかかわらず、ソースが非数値データであった場合、ランタイムは即座に例外を発生させる。
ここで`ON CONVERSION`ユニットを使うと、この変換エラーが起きた瞬間に制御を奪い、独自の処理(エラーログ出力やデフォルト値のセット)を差し込むことができる。
—
2. 実践的なコーディング例
以下に、VSAMファイルを読み込み、不正な数値データを検知した場合に「0」に置き換えて処理を継続する、現場で即戦力となる実装例を示す。
/i
/ PACKAGEは構造化の基本。モジュール境界を明確にする /
CONVTEST: PACKAGE;
/ メインプロシージャ /
MAIN_PROC: PROCEDURE OPTIONS(MAIN);
DCL IN_RECORD CHAR(10);
DCL NUM_VAL FIXED DEC(7,0);
DCL ERR_FLAG BIT(1) INIT(‘0’B);
/ 変換エラーが発生した時の動作を定義 /
ON CONVERSION BEGIN;
PUT SKIP LIST(‘警告: 不正な数値データを発見しました。デフォルト値0を適用します。’);
/ 変換対象の値を無理やり0にする /
CONVERSION_VALUE = ‘0’;
ERR_FLAG = ‘1’B;
END;
/ ダミーデータ:本来はVSAMからの読み込みを想定 /
IN_RECORD = ‘123A5’; / ‘A’が混入した不正データ /
/ ここで変換が発生する /
NUM_VAL = IN_RECORD;
IF ERR_FLAG THEN
PUT SKIP LIST(‘処理を継続します。値は:’ || NUM_VAL);
ELSE
PUT SKIP LIST(‘正常値:’ || NUM_VAL);
END MAIN_PROC;
END CONVTEST;
—
3. 現場で生き残るための「運用のコツ」
1. グローバルな影響範囲に注意せよ
`ON CONVERSION`は、そのプロシージャのスコープ(またはそれより深いブロック)すべてに影響する。大規模なバッチ処理の場合、意図しない箇所で変換エラーが起きた際にも同じロジックが走ってしまう可能性がある。必要に応じて、`REVERT`ステートメントを使用して、特定のブロックを抜ける際にONユニットを解除する習慣をつけてほしい。
2. コンバージョン値を直接操作する「CONVERSION_VALUE」
コード内の`CONVERSION_VALUE`は、PL/Iの擬似変数だ。ONユニット内でこの値を書き換えることで、ランタイムに対して「この値で再試行せよ」と指示を送ることができる。これが、ダンプを出さずにシステムを継続させるための「肝」である。
3. トレースログを必ず残す
「エラーを無視して処理を続行する」ことは、ある種のリスクを伴う。必ず`PUT`文などで、どのレコードで、どのような不正データがあったかをログに出力しておくこと。これを怠ると、後日、帳票数値の整合性が合わないという地獄のようなトラブルシューティングを強いられることになる。
—
ベテランからのアドバイス
PL/Iは古い言語だと言われることもあるが、こうした例外ハンドリングの柔軟性は、Javaや他のモダン言語以上に洗練されている部分がある。
「プログラムを止める」のは最後の手段だ。基幹システムのエンジニアとして大切なのは、システムが「止まらない」ことよりも、「止まらざるを得ない事態を、いかに制御可能な範囲に収めるか」という視点である。
次回の改修作業で「数値変換エラーで落ちた」という報告を見つけたら、まずはダンプ解析の前に、この記事を思い出してほしい。ONユニット一つで、君の夜間待機は劇的に平和になるはずだ。
