【テクニカル・上級編】ON CONVERSIONによるデータ型変換エラーの捕捉 – PL/Iの基本構文とデータ制御実践ガイド

PL/Iの「予約語なき自由」と、ON CONVERSIONが暴くデータ汚染の深淵

メインフレームの現場で何十年と生き抜いてきたPL/Iという言語は、現代の言語仕様から見れば「無法地帯」のように映るかもしれません。しかし、その「予約語を持たない」という仕様こそが、かつてのエンジニアたちが限られたメモリ空間でどれほどまでに柔軟な設計を追求していたかの証左でもあります。

今回は、JavaやC#へのマイグレーションを控えたアーキテクトが必ず直面する「データ型変換の罠」と、その防波堤となる`ON CONVERSION`の深淵に切り込みます。

1. 予約語なき設計:自由と引き換えに払う代償

PL/Iには、言語仕様としての「予約語」が存在しません。`IF`、`THEN`、`ELSE`といったキーワードでさえ、変数名として定義できてしまいます。

/i
/ 危険極まりないコードの例 /
DCL IF FIXED BIN(31) INIT(10);
IF IF > 0 THEN PUT SKIP LIST(‘TRUE’);

この仕様は高度なマクロ展開を可能にしましたが、現代の静的解析ツールやマイグレーション用トランスパイラにとっては悪夢です。レガシーシステムの移行を行う際、まず着手すべきは、こうした「言語の曖昧さを利用したトリッキーなコーディング」の撲滅です。`OPTIONS(REENTRANT)`でコンパイルし、再入可能性を確保する以前に、識別子の命名規則を厳格化するコーディング規約の策定が、近代化の第一歩となります。

2. ON CONVERSION:データ変換エラーの最前線

基幹システムにおいて、もっとも恐ろしいのは「システム停止」よりも「不正なデータが正当なものとしてDB2にコミットされること」です。特に、ホストのパックデシマル(COMP-3)から数値型への変換失敗は、頻出するアベンド(ABEND)要因の一つです。

`ON CONVERSION`ユニットは、文字データが数値型にキャストされる際、その内容が有効な数値表現でない場合に発火する「最後の砦」です。

/i
ON CONVERSION BEGIN;
/ 変換失敗時のデバッグログ出力 /
PUT SKIP LIST(‘データ型変換エラー発生: ‘ || ONCHAR || ‘ が含まれています’);
/ ここで異常フラグを立てて、ダンプを強制的に残す処理やロールバックを記述 /
SIGNAL ERROR;
END;

DCL WK_NUM FIXED DEC(5,0);
DCL INPUT_CHAR CHAR(5) INIT(’12A45′); / ここに不正な文字が含まれる /

WK_NUM = INPUT_CHAR; / ここでON CONVERSIONが発火 /

なぜこれが「レガシー移行」の鍵か

JavaやC#へ移行する際、PL/Iの「暗黙の型変換(自動的なパディングや切り捨て)」をそのまま移植しようとすると、必ず論理バグを生みます。`ON CONVERSION`で捕捉されるエラーは、現行システムが「黙って処理していたグレーゾーン」です。移行前調査において、このユニットを全モジュールに仕込み、本番環境でどんなゴミデータが流れているかを可視化すること。これがマイグレーションの成功確率を劇的に高めます。

3. ダンプ解析とエッジケース:パックデシマルの内部符号反転

CICSオンライン処理などで頻発する`S0C7`(データ例外)は、往々にしてメインメモリ上のパックデシマルが不正な符号を持っていることに起因します。

ダンプ解析の勘所

1. 符号の確認: パックデシマルの末尾ハーフバイトが`C`(正)、`D`(負)、`F`(符号なし)以外になっている場合、それはハードウェアレベルで数値として認識できません。
2. ポインタの迷子: `DCL P PTR;`を使用した動的割り当てにおいて、基底変数(Based Variable)のオフセット計算ミスにより、隣接する領域のデータを破壊しているケースが多々あります。`CHECK(SUBSCRIPTRANGE)`コンパイラオプションを有効にし、境界チェックを厳格に行うことが、移行前の健全化には不可欠です。

4. アーキテクトへの提言:移行の設計思想

レガシー移行のプロジェクトにおいて、コードを機械的に翻訳するのは二流の仕事です。真の一流は、PL/Iが許容していた「曖昧なデータ構造」を、JavaやC#の厳格な型システムへどう「翻訳」するかを設計します。

  • DB2への埋め込みSQL: `NULL`許容カラムと、PL/I側の`INDICATOR変数`の不一致は、移行後の最頻出バグです。変換時に「何がエラーになるか」を定義するドキュメントを作るのではなく、現行システムの`ON CONVERSION`のログを解析し、実データに基づいたバリデーションルールを策定してください。
  • 最適化の影響: `OPTIMIZE(3)`をかけているコードは、レジスタへの退避により、ダンプ上の値とソースコード上の変数の位置関係が一致しないことがあります。デバッグ時は`NOOPTIMIZE`でコンパイルし直すのが鉄則ですが、パフォーマンス重視のバッチでは、あえて最適化による挙動の変化を深く理解しておく必要があります。

PL/Iの歴史は、ハードウェアの制約と戦い続けたエンジニアの歴史です。その血を受け継ぐ我々が、新しい言語環境へその知見を移し替えるとき、単なる「置き換え」ではなく、「より強固なデータ完全性」を実現するシステムへと昇華させなければなりません。

コードの隅々に潜む「予約語なき自由」の残滓を一つずつ消し去り、堅牢なアーキテクチャへと導くことこそが、スペシャリストの使命です。もし、あなたの担当しているモジュールで原因不明の`S0C7`が消えないのであれば、一度`ON CONVERSION`で全入力を「検査」してみることを強く推奨します。驚くような「汚れたデータ」が、あなたのシステムの裏側を覗いているはずです。

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