【テクニカル・上級編】SELECT文におけるWHEN条件の評価順序とOTHERWISEの役割 – PL/Iの基本構文とデータ制御実践ガイド

PL/Iの「SELECT文」を巡る深淵:制御構造の最適化とアーキテクトの矜持

メインフレームの現場で何十年と稼働し続けるPL/Iのソースコードを読み解いていると、たまに「なぜここでSELECT文を使ったのか」と首を傾げたくなるようなロジックに出くわすことがある。特に、現代のJavaやC#の `switch-case` に慣れ親しんだエンジニアが、PL/Iの `SELECT` を単なる分岐構造として捉えると、後に手痛いしっぺ返しを食らうことになる。

今日は、我々アーキテクトが基幹システムのマイグレーションや保守において、決して軽視してはならない `SELECT` 文の評価順序と、その背後に潜むリスクについて語ろうと思う。

1. 上から下へ:評価順序という名の「決定論」

PL/Iの `SELECT` 文は、C言語の `switch` とは根本的に思想が異なる。C言語がジャンプテーブルへのインデックス参照を期待するのと対照的に、PL/Iの `SELECT` は逐次評価である。

SELECT (TRX_TYPE);
WHEN (’01’) CALL PROCESS_SALES(); / 条件に合致すれば即座に実行 /
WHEN (’02’) CALL PROCESS_RETURN();
WHEN (TRX_TYPE >= ’05’) CALL PROCESS_OTHER(); / 範囲指定も可能だが注意が必要 /
OTHERWISE CALL HANDLE_INVALID_TYPE();
END;

ここで重要なのは、「先に書かれた条件が常に優先される」という鉄則だ。特に `WHEN` 句の中に式を書く場合、その評価コストがバッチ処理全体のパフォーマンスを左右する。

私が過去に遭遇したトラブルで最も印象深いのは、メインフレームからJavaへのマイグレーション時に、この「順序依存性」を見落としてロジックを並び替えてしまったケースだ。PL/Iは `WHEN` の条件評価において、左から右、そして上から下へという厳格な順序を守る。これを安易に最適化の名の下に書き換えると、計算機が弾き出す結果は容易に牙を剥く。

2. OTHERWISEは「安全装置」か、それとも「墓場」か

`OTHERWISE` を省略した場合、全ての `WHEN` に合致しなかったプログラムは、ERROR条件をトリガーしてABEND(アベンド)する

基幹システムにおいて、このABENDは「異常検知」として設計されていることが多い。「想定外のデータが来たら止めてくれ」という意図だ。しかし、CICSオンライン処理でこれをやると、トランザクションが異常終了し、デッドロックや資源解放の不整合を招く。

アーキテクトの推奨:防御的コーディング

もし君が保守を担当するなら、`OTHERWISE` 句には必ず以下の処理を組み込むべきだ。

OTHERWISE DO;
/ 異常ログを出力し、ダンプを取得するためのトレース用ルーチン /
PUT SKIP EDIT (‘INVALID TRX_TYPE:’, TRX_TYPE) (A, A);
SIGNAL ERROR; / 明示的に例外を発生させ、運用者に通知する /
END;

ここで、`SIGNAL ERROR` を使うか、あるいは静かにDB2のログへエラーコードを書き込んで処理を終了させるかは、システムの可用性要件次第だ。だが、何も書かずに放置することだけは、プロフェッショナルとして許されない。

3. マイグレーションの最前線:パックデシマルの罠と最適化

Java/C#への移行を進める際、最も頭を抱えるのがデータ型の不一致だ。PL/Iの `FIXED DECIMAL(15,0)` はパックデシマルとしてメモリ上に展開されるが、これを単なる数値型として扱うと、符号ビット(`0xC` や `0xD`)の解釈でバグを量産する。

特に、`SELECT` の評価対象にパックデシマルを使っている場合、コンパイラオプションの `OPTIMIZE` が絡むと、最適化エンジンが「範囲外の数値は存在しない」と決め打ちして条件判定を間引くことがある。

コンパイラ最適化の副作用

最適化レベルを上げると、コンパイラは `WHEN` 条件の評価をハードウェアのレジスタ操作に置き換える。このとき、ポインタ操作(`BASED変数`)でメモリを動的に書き換えている領域と、`SELECT` 文の評価対象が重なると、キャッシュの不整合により「データはあるのに条件判定をスルーする」という、夜中に呼び出される悪夢のような現象が起きる。

最後に:コードの向こう側にあるもの

PL/Iの `SELECT` 文は、単なる制御構造ではない。それは、そのプログラムが「どのようなビジネス上の例外を想定していたか」という、先人たちの思考の軌跡だ。

移行先のJavaで `switch-case` を書く際、単に「動く」コードを書くのではなく、PL/Iが持っていた「順序性」と「エラーハンドリングの厳格さ」をどう移植するか。そこに、君たちが真のアーキテクトであるかどうかの分水嶺がある。

もし、解析中に不可解なABENDダンプを見つけたら、まずは `SELECT` 文の直前で `STORAGE` 領域がポインタ経由で汚染されていないかを確認してほしい。メインフレームの神は、往々にして細部に宿り、そして最も厄介なバグをそこに隠しているのだから。

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