1. 導入:なぜこの「見えない空白」が問題なのか
メインフレーム開発の現場で、長年慣れ親しんだPL/IやCOBOLから、Java等のオープン系言語へマイグレーションする際、最もバグを誘発しやすいのが「空文字」の扱いです。特に、PL/Iにおいて「”(空文字列)」と記述した場合、それがメモリ上でどのような物理的表現を持つのかを理解していないと、条件分岐のロジックで予期せぬ挙動を引き起こします。本稿では、VARYINGと固定長文字列の物理的差異と、移行時に陥りやすい罠について解説します。
2. 基礎知識:物理的表現の二重性
PL/Iにおける文字定数 ” は、変数の属性によってメモリ上の解釈が異なります。
VARYING属性の場合: 文字列の長さを保持するヘッダ(通常は2バイトのバイナリ)が存在し、そこに「0」が格納されます。実データ領域は確保されていても参照されません。
固定長(CHAR)属性の場合: メモリ上は「全桁が空白(X’40’)」として埋め尽くされます。つまり、PL/Iにおける空文字判定は、「長さが0であること」ではなく、「全桁が空白であること」というビットパターンの一致を確認しているケースがほとんどです。これは、Javaの「文字数が0であること(isEmpty)」とは根本的に異なる概念です。
3. 実装と解決策
PL/Iで空文字判定を行う場合、固定長文字列に対してはTRIM関数を併用するか、比較演算子による判定が一般的です。移行先がJavaであれば、単なるisEmpty()ではなく、Apache Commons LangのStringUtils.isBlank()を使用するのが、PL/Iの「空白のみ」という仕様を正しく継承する近道です。
4. サンプルプログラム:PL/Iでの正しい判定ロジック
以下は、固定長文字列において「実質的に空である(空白のみ)」を判定する、現場でよく使われるイディオムです。
/ 固定長文字列の空判定サンプル /
DCL STR1 CHAR(10) INIT(‘ ‘); / 全空白 /
DCL STR2 CHAR(10) INIT(‘A ‘); / 空ではない /
/ 比較対象の定数と照合 /
IF STR1 = ” THEN
PUT SKIP LIST(‘STR1は空として処理されます’);
/ TRIMを使用したより安全な判定方法 /
IF TRIM(STR2) = ” THEN
PUT SKIP LIST(‘STR2は空白を除くと空です’);
ELSE
PUT SKIP LIST(‘STR2には有効なデータがあります’);
5. 応用・注意点:移行時の落とし穴
現場で最も注意すべき点は、「NULL」と「空文字(空白)」の混同です。
オープン系言語への移行時、PL/Iの空文字をSQLのNULLにマッピングしてしまうと、比較演算の結果がすべて「偽(UNKNOWN)」となり、ロジックが破綻します。
また、固定長文字列同士の比較では、右側の空白が無視される仕様(比較規則)があるため、意図せず「長さの異なる文字列」が等しいと評価されることがあります。
プログラムを改修する際は、まず対象の変数がVARYINGか固定長かを明確に定義し、移行先のバリデーションロジック(isBlank判定か、isEmpty判定か)を厳密に使い分けることを推奨します。

コメント