【実務・中級編】LENGTH組み込み関数のVARYING属性に対する挙動 – PL/Iの基本構文とデータ制御実践ガイド

現場のPL/Iエンジニアに捧ぐ:LENGTH関数の「見えない仕様」とVARYINGの罠

若手エンジニアからよく相談されるのが、「LENGTH関数が期待した値を返さない」というトラブルだ。メインフレームの基幹バッチで、`CHAR(10)`と`CHAR(10) VARYING`を混在させて処理している際、この手の「仕様の深掘り不足」によるバグが、深夜の運用保守を苦しめる原因になる。

今日は、PL/Iの「予約語が存在しない」という自由奔放な言語仕様の裏側で、`LENGTH`関数が具体的に何をどう見ているのか。その核心に切り込んでいこう。

1. 「固定長」と「VARYING」の決定的な違い

PL/Iにおいて、`CHAR(n)`(固定長)と`CHAR(n) VARYING`(可変長)は、メモリ上の構造そのものが異なる。

  • CHAR(n) (固定長):

メモリ上には文字データのみがnバイト分確保される。`LENGTH`関数を呼ぶと、コンパイラは宣言されたサイズ「n」を即座に返す。中身がスペースだろうが文字だろうが、宣言値こそが正義だ。

  • CHAR(n) VARYING (可変長):

メモリの先頭2バイト(システムによっては異なるが、基本はこれだ)に、現在の「有効長」を示す記述子(Descriptor)が埋め込まれる。その後ろに実データが続く。`LENGTH`関数は、この記述子を読みに行って値を返す。

現場で最も恐ろしいのは、「固定長変数に可変長変数を代入する際、後ろにスペースが埋まる」という挙動だ。これを理解していないと、DB2へのINSERTやVSAMへの書き込みで、意図しないゴミデータがレコードを汚染することになる。

2. 実践:LENGTH関数の挙動をコードで確認する

以下のコードを見てほしい。大文字記述が基本のメインフレーム環境でも可読性を維持するための、標準的なコーディング例だ。

1
TEST_PROG: PROC OPTIONS(MAIN);

/ 固定長文字列と可変長文字列の宣言 /
DCL FIX_STR CHAR(10) INIT(‘ABC’);
DCL VAR_STR CHAR(10) VARYING INIT(‘ABC’);

/ 結果を出力するためのカウンタ /
DCL L_FIX FIXED BIN(15);
DCL L_VAR FIXED BIN(15);

/

  • 【重要】LENGTH関数は固定長に対しては宣言サイズを、
  • 可変長に対しては現在保持している文字数を返す。

/
L_FIX = LENGTH(FIX_STR); / 結果: 10 /
L_VAR = LENGTH(VAR_STR); / 結果: 3 /

PUT SKIP EDIT (‘FIX_STR LENGTH: ‘, L_FIX) (A, F(2));
PUT SKIP EDIT (‘VAR_STR LENGTH: ‘, L_VAR) (A, F(2));

/

  • VSAM入出力やDB2連携で事故るパターン:
  • 可変長を固定長フィールドにMOVEすると、
  • 後続の残余部分はスペースで埋められる。

/
FIX_STR = VAR_STR;

/ この時点でFIX_STRは ‘ABC ‘ となる /

END TEST_PROG;

3. トラブルシューティング:記述子と戦う現場の知恵

実務で最も厄介なのは、サブルーチンへの引数渡しだ。PL/Iは引数を渡す際、呼び出し先が記述子を期待しているかどうかを厳密にチェックする。

もし呼び出し先のプロシージャで宣言(`DCL`)を誤ると、記述子が正しく認識されず、`LENGTH`関数がメモリ上の全く関係ないアドレスを読みに行き、結果として異常終了(S0C4など)を招くことがある。

現場で守るべき「鉄則」:

1. DCLは必ずENTRY宣言で揃える: 呼び出し先(Callee)と呼び出し元(Caller)でデータ属性を一致させること。特に`VARYING`の有無は、記述子の構造に直結するため、ここがズレると地獄を見る。
2. TRIM組み込み関数の活用: 固定長データを取り扱う際、不要なスペースを排除したい場合は必ず`TRIM`を活用してほしい。ただし、`TRIM`の結果を格納する変数もまた属性に注意が必要だ。
3. ON ERRORユニットの配置: 予期せぬ文字列操作での桁あふれや属性不一致を検知するため、メインのバッチ処理では必ず`ON ERROR`ユニットを定義し、エラー発生時のダンプ情報を取得できるようにしておくこと。

最後に:なぜPL/Iを使い続けるのか

PL/Iは「古い」と言われるが、これほど厳密にメモリ構造を制御できる言語は他にない。予約語がないという仕様は、一見すると「野放図」に見えるが、実はエンジニアに最大の裁量を与えている。

コードを書くとき、常に「今、メモリ上で何が起きているか(記述子がどうなっているか)」を想像してほしい。その視点を持つだけで、君たちの書くコードの品質は劇的に向上するはずだ。

もしバッチ処理で理由不明のデータ化けが発生したら、まずは`LENGTH`関数が参照している先が「宣言値」なのか「記述子」なのか、そこから疑ってかかってみよう。それが、ベテランへの第一歩だ。

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