PL/Iの「予約語なき設計」とDB2ホスト変数の深淵:レガシー移行の設計指針
メインフレームの現場で何十年も稼働し続けるPL/Iプログラム。昨今のマイグレーション案件で「なぜPL/Iはこんなにも難解なのか」と問われれば、私は決まって「自由度の代償だ」と答えます。
PL/Iには、JavaやC#のような「予約語」という概念が(厳密には)存在しません。`IF`や`THEN`といったキーワードすら、文脈次第では変数名として使えてしまう。この強力すぎる柔軟性が、コンパイラの字句解析を複雑にし、同時にバグの温床にもなり得るのです。特にDB2との親和性を問われるホスト変数(Host Variable)の定義において、この「緩さ」が予期せぬ落とし穴となります。
—
1. DECLARE SECTIONの「見えない制約」
DB2のプリコンパイラ(ホスト言語インターフェース)を通す際、ホスト変数の宣言は `EXEC SQL BEGIN DECLARE SECTION;` と `END DECLARE SECTION;` で囲むのが鉄則です。
ここでの落とし穴は、「プリコンパイラが認識できる型」と「PL/Iが許容する型」の乖離です。例えば、パックデシマル(`FIXED DECIMAL`)を定義する際、精度と位取り(`p, q`)の指定を怠ると、DB2側の `DECIMAL(p, q)` 型との不整合により、実行時にSQLCODE -301(ホスト変数のデータ型が不適合)を叩き出します。
1
/ 正しいホスト変数の宣言例 /
EXEC SQL BEGIN DECLARE SECTION;
/ 内部表現では PIC S9(7)V99 となり、DB2のDECIMAL(9,2)と合致させる /
DCL WS_AMT FIXED DEC(9, 2);
/ 文字列は必ず固定長か、VARYING指定を含めてDB2のVARCHARに合わせる /
DCL WS_NAME CHAR(20);
EXEC SQL END DECLARE SECTION;
特に注意すべきは、`POINTER`型を用いた動的メモリ操作との混在です。ホスト変数としてポインタの参照先を渡す場合、変数の境界整列(Alignment)がコンパイラのオプション(`ALIGNED` vs `UNALIGNED`)に依存します。マイグレーション先のJavaでメモリレイアウトを再現しようとして、このアライメントの差異によるオフセットズレで数日潰すのが、移行屋の「あるある」です。
—
2. パックデシマルの符号反転バグという「亡霊」
PL/IからDB2へデータを渡す際、最も恐ろしいのは内部表現の符号ビットです。IBM汎用機のパックデシマルは、末尾のニブルが符号(`C`=正, `D`=負)を表しますが、稀に外部インターフェースや異種システムとの連携で、この符号が壊れた状態でDB2にインサートされようとすることがあります。
1
/ パックデシマルの符号チェックルーチン例 /
DCL WRK_PACKED FIXED DEC(5, 0);
/
本来であればコンパイラが保証するが、CICSのCOMMAREA等を経由した
受信データが不正な場合、演算時にS0C7アベンドが発生する。
事前に検証が必要。
/
IF WRK_PACKED < 0 THEN
/ 負の値のハンドリング /
S0C7(データ例外)が発生した際、ダンプリストを眺めると、該当するパックデシマル変数のアドレスに `00000F` ではなく、不正な値が入っているケースが多い。これは単なるバグではなく、システム境界における「データの型定義の崩壊」が原因です。移行設計においては、この「不正データ」をどのようにバリデーションするか、Java側で `BigDecimal` に変換する際の例外処理としてどう定義するかが、品質を左右します。
---
3. コンパイラオプションと最適化の罠
`OPTIMIZE(2)` 以上の最適化をかけると、コンパイラは「この変数はループ内で値が変化しない」と勝手に判断し、レジスタへキャッシュします。
しかし、CICSオンライン処理で別のタスクからメモリを書き換えるような、いわゆる「共有メモリ的アプローチ」をとっている古いプログラムの場合、この最適化によってメモリ上の最新値が反映されず、整合性がとれなくなることがあります。
もし皆さんの移行対象コードに `BASED` 変数が多用されているなら、それは「コンパイラに頼らず自分でメモリ管理をする」という当時の技術者の覚悟です。Javaへの移行において、このポインタ操作を `Unsafe` クラスや `ByteBuffer` で安易に模倣するのは危険です。ビジネスロジックの非機能要件を再定義し、型安全なモデルに書き換えることが、長期的な保守コストを削減する唯一の道です。
—
アーキテクトとしての助言
PL/Iは、ハードウェアの特性をプログラマが直接制御できる、極めて強力な言語です。しかし、その力は「正しく書く」という制約を前提としています。
マイグレーションを担当する皆様へ。コードを一行ずつ機械的に変換することに固執しないでください。そのPL/Iコードが、当時のハードウェア制約の中で「なぜその型を選んだのか」「なぜそのメモリ配置にしたのか」という背景を読み解いてください。
アベンドのダンプが語る物語を理解できるようになったとき、貴方は真のメインフレーム・アーキテクトになれるはずです。PL/Iは退場する言語ではなく、現代の堅牢な基幹システムを支える「設計思想の源流」なのですから。
