【実務・中級編】 ステータスコード(DL/I戻り値) – 階層型DBMS

ステータスコード(DL/I戻り値)の真実:2バイトの文字列が語る階層型DBMSの深淵

こんにちは、チーフアーキテクトだ。
今日のコードレビューで、また「若い連中」の甘いエラーハンドリングを見かけた。リレーショナルデータベース(RDB)の`SQLSTATE`や`SQLException`の感覚でDL/I(Data Language/I)のステータスコードを扱い、夜間バッチを盛大にクラッシュさせる――毎度おなじみの光景だ。

IMSなどの階層型DBMSを扱う現場において、ステータスコード(2バイトの戻り値)は、単なる「エラーの有無を示すフラグ」ではない。 それは、ナビゲーション型DBMSの現在位置(Positioning)と、データベースエンジンが下した残酷なまでの判定を下す「シグナル」そのものなのだ。

今日は、この2バイトのコードを極限まで理解し、枯れていながらも堅牢なエンタープライズシステムを構築するための設計パターンを伝授する。

—

1. なぜDL/Iステータスコードは「文字列」なのか

RDBの多くは、リターンコードに数値(`0` が正常、負数がエラー、あるいは特定の例外コード)を採用している。しかし、DL/Iのステータスコードは 2バイトの英数字(文字) だ。

正常終了: [ ] (スペース2つ)
データなし: [GE]
セグメント重複: [II]
ポインタ不整合: [AJ]

なぜ数値ではなく文字列なのか?
それは、階層型DBMSがポインタチェーンを辿る「ナビゲーション型」であり、エラーや境界条件の種類が、木構造(Hierarchical Tree)のどのパスで発生したかによって多岐にわたるからだ。

チーフアーキテクトとしての最初の教訓:
> 「DL/Iのステータスコードは、エラーコードではなく『DBMSからの対話メッセージ』であると心得よ」

スペース(` `)が返れば、君のナビゲーションは成功し、カーソル(ポジション)は正しく維持されている。何か文字が入っていれば、それは単なる異常ではなく、「木構造のどこで、何が起きたか」を示す決定的なコンテキストなのだ。

—

2. 頻出ステータスコードと「現場の解釈」

主要なコードの意味はマニュアルに書いてある。だが、実務でどう解釈し、どう振る舞うべきかは別の話だ。いくつか実戦的なものをピックアップしよう。

① ` ` (空白/Spaces): 正常終了

  • 意味: 要求された操作が完遂され、ポジションが確定した。
  • 実務の勘所: 連続する `GN`(Get Next)ループの継続条件は、厳密にこの空白判定で行う必要がある。

② `GE` (Data Not Found): 条件不一致

  • 意味: 修飾子(SSA: Segment Search Argument)に一致するセグメントが存在しない。
  • 実務の勘所: これを「システムエラー」として扱ってはならない。マスター検索における「該当なし」と同義であり、業務ロジック上の分岐点(新規作成モードへ移行するなど)として正常にハンドリングされるべきものだ。

③ `II` (Segment Already Exists): 重複登録

  • 意味: 既に存在する一意キーを持つセグメントを `IS`(Insert)しようとした。
  • 実務の勘所: 排他制御の不備、あるいはアプリケーション側の重複チェック漏れを示唆する。安易なリトライではなく、即座にトランザクションをロールバックし、オペレーションログにスタックを吐き出させるべきクリティカルなコードだ。

④ `AJ` (Data Dependency Error): 階層則違反

  • 意味: 親セグメントが存在しない状態で、子セグメントを挿入しようとした。
  • 実務の勘所: 完全に設計またはコードのバグだ。物理的な親子関係の構築順序が崩れている証拠であり、プログラムの構造的欠陥を疑え。

—

3. 【設計パターン】堅牢なDL/Iコールラッパーと判定ロジック

実務の現場では、毎回 `IF DIBSTAT = ‘GE’` のようなベタ書きをしてはならない。コードがスパゲッティ化し、ポジションのロストを見落とす原因になる。

以下に、エンタープライズ品質のCOBOL/PL/I環境を想定した、堅牢な判定設計のパターンを示す。

悪い例:散在するアドホックな判定

CALL ‘CBLTDLI’ USING DLI-ISRT,
PCB-MTR,
CUSTOMER-SEG.
IF PCB-STAT = ‘II’
DISPLAY ‘ALREADY EXISTS’
GO TO ERROR-ROUTINE
END-IF.

  • GEやその他のコードのケアが漏れている、あるいは毎回バラバラに書いてある…

致命傷: ポジションロストのケアがなく、異常終了時の復旧手順がバラバラになる。

模範例:ステータス集中制御ラッパーと構造化ハンドリング

IDENTIFICATION DIVISION.

  • ==============================================================
  • チーフアーキテクト推薦:DL/Iステータスハンドリング標準ルーチン
  • ==============================================================

> 各種DL/I呼び出しをカプセル化し、戻り値を一元管理する

実務では、以下のような「許容されるステータス」と「致命的なステータス」を明確に分離した判定関数(またはサブルーチン)を経由させよ。

> 擬似コードによるステータス判定設計
EVALUATE TRUE
WHEN DLI-STATUS-OK
> 正常系処理の継続
CONTINUE

WHEN DLI-STATUS-NOT-FOUND
> 業務上の想定内エラー(GEなど)
MOVE ‘1’ TO W-NOT-FOUND-SW

WHEN OTHER
> 予期せぬシステム/データ構造エラー
PERFORM 9999-DLI-ABEND-ROUTINE
END-EVALUATE.

ここで重要なのは、「想定内のステータス(`GE`など)」以外をすべて致命的(Abend対象)として扱うホワイトリスト方式を採用することだ。階層型DBMSでは、予期せぬステータスを無視して処理を続行すると、データベースの物理的な位置情報(Currency)が狂い、データベース全体を破壊する致命的な連鎖を引き起こす。

—

4. パフォーマンス上の注意点:ステータスコードと「ポジション」の呪縛

RDBであれば、インデックススキャンやテーブルスキャンで失敗しても、次のクエリは完全に独立している。しかし、階層型DBMSは違う。

`GE` やその他の非正常ステータスが返されたとき、そのPCB(Program Communication Block)が保持する現在位置(Currency)は、最後にヒットした親、あるいは意図しない位置に留まるか、無効化される。

  • 罠: ステータスコードをハンドリングせずにそのまま次の `GN`(Get Next)を発行すると、予期せぬセグメントからスキャンが再開され、サイレントデータ破損(誤ったデータの更新・削除)を引き起こす。
  • 鉄則: エラー(スペース以外)を検知したPCBに対しては、後続の処理を行う前に必ず `GU`(Get Unique)などで明示的にポジションを再確立(リポジション)するか、ロールバックを実行せよ。パフォーマンスを気にしてこの手順を省くプログラマがいるが、データ破損のリカバリコストに比べれば、再ポジションのオーバーヘッドなど微小なものだ。

—

5. チーフアーキテクトからの最終メッセージ

階層型DBMSはレガシーと呼ばれることもある。だが、その背後にある「物理的メモリとポインタの構造」を直視させられるこのアーキテクチャは、エンジニアリングの本質を我々に教えてくれる。

ステータスコードの2バイトは、DBMSからのメッセージだ。
「今、木のどこにいて、なぜ止まったのか」をその2バイトから正確に読み取り、コードに表現すること。それこそが、何十年先も稼働し続ける堅牢な基幹システムを支えるエンジニアの誇りである。

次回のコードレビューでは、妥協のないステータスハンドリングを見せてもらう。期待しているぞ。

コメント

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