EGL における代入の互換性

代入の互換性規則は、以下の状況のいずれかで適用されます。
以下の場合は、別の規則のセットが有効になります。

参照変数の値変数への代入 (およびその他の方法) など、上記の場合について詳しくは、EGL での参照の互換性を参照してください。

以下のテーブルでは、一番左の列の型は、代入ステートメントの左側 (ターゲット) を表し、 他のすべての列は、右側 (ソース) を表しています。 文字 Y は、互換性のある型を表します。ブランクは、型に互換性がないことを示しています。 数字は、3 番目の表に続く注の説明にあり、型に互換性がある場合の状況を詳しく説明しています。

最初の表は、代入のソースとしてのテキスト型の詳細です。

表 1. 代入の互換性: テキスト型
ターゲット ソース
  CHAR MBCHAR STRING、UNICODE DBCHAR
CHAR Y Y Y  
MBCHAR Y Y Y  
STRING、UNICODE Y Y Y Y
DBCHAR     Y Y
BIN 1 1 1  
INT、BIGINT、SMALLINT 1 1 1  
DECIMAL 1 1 1  
NUM 1 1 1  
NUMBER 1 1 1  
FLOAT、 SMALLFLOAT 1 1 1  
MONEY 1 1 1  
NUMC 1 1 1  
PACF 1 1 1  
DATE 2 2 2  
INTERVAL (months) 2 2 2  
INTERVAL (seconds) 2 2 2  
TIME 2 2 2  
TIMESTAMP 2 2 2  
HEX Y   Y  
BOOLEAN        

2 番目の表は、代入のソースとしての数値型の詳細です。

表 2. 代入の互換性: 数値型
ターゲット ソース
  BIN

INT、
BIGINT、SMALL-
INT

DECI-
MAL

NUM

NUM-
BER

FLOAT、
SMALL-
FLOAT

MONEY NUMC PACF
CHAR Y Y Y Y Y Y 3 Y Y
MBCHAR Y Y Y Y Y Y 3 Y Y
STRING 4 4 4 4 4 4 3、4 4 4
UNICODE Y Y Y Y Y Y 3 Y Y
DBCHAR Y Y Y Y Y Y Y Y Y
BIN Y Y Y Y Y Y Y Y Y
INT、BIGINT、SMALLINT Y Y Y Y Y Y Y Y Y
DECIMAL Y Y Y Y Y Y Y Y Y
NUM Y Y Y Y Y Y Y Y Y
NUMBER Y Y Y Y Y Y Y Y Y

FLOAT、
SMALL-
FLOAT

Y Y Y Y Y Y Y Y Y
MONEY Y Y Y Y Y Y Y Y Y
NUMC Y Y Y Y Y Y Y Y Y
PACF Y Y Y Y Y Y Y Y Y
DATE 5 5 5 5 5 5 5 5 5
INTERVAL (months) 6 6 6 6 6 6 6 6 6
INTERVAL (seconds) 6 6 6 6 6 6 6 6 6
TIME                  
TIMESTAMP                  
HEX           7      
BOOLEAN 8 8 8 8 8 8 8 8 8

3 番目の表は、代入のソースとしての日付/時刻、16 進数、および Boolean 型の詳細です。

表 3. 代入の互換性: その他の型
ターゲット ソース
  DATE INTERVAL (months) INTERVAL (seconds) TIME

TIME-
STAMP

HEX BOOLEAN
CHAR 9 9 9 9 9 Y  
MBCHAR 9 9 9 9 9    
STRING、UNICODE 9 9 9 9 9 Y  
DBCHAR              
BIN 10 Y Y       11
INT、BIGINT、SMALLINT 10 Y Y       11
DECIMAL 10 12 12       11
NUM 10 12 12       11
NUMBER 10 12 12       11
FLOAT、 SMALLFLOAT 10         Y 11
MONEY 10 12 12       11
NUMC 10 12 12       11
PACF 10 12 12       11
DATE Y       Y    
INTERVAL (months)   Y          
INTERVAL (seconds)     Y        
TIME       Y Y    
TIMESTAMP Y     Y Y    
HEX           Y  
BOOLEAN             Y
注:
  1. テキストは、受信データ型のリテラルを示しています。 テキストには、表記、先頭符号、ピリオド以外の小数点 (言語設定による)、および通貨記号 (通貨型に割り当てられている場合) が含まれます。 任意の数の先頭スペースまたは末尾スペースを含むことができますが、その間になにも指定しないでおくことはできません。
  2. テキストの日付/時刻型への変換 を参照してください。
  3. ロケール依存の通貨記号は、代入対象の先頭に自動的に追加されます。比較として、テキスト値の最初の文字が通貨記号である場合は無視されます。ストリング "$10.20" と "10.20" は、両方とも値 10.20 の MONEY 変数と同じです。
  4. EGL は、数値型を STRING に変換する際は常にパターン引数のない strLib.formatNumber() を使用します。これには、代入とストリングの連結も含まれます。formatNumber() を参照してください。
  5. 数値型に小数点が含まれている場合、EGL はその数値を切り捨てます。数は、1899 年 12 月 31 日以降の日数として扱われます。 このため、以下のコードは、コンソール上に「03/21/2006」と印刷します。
      Function main()
        testBin BIN(9,3) = 38796.999;
        testDate DATE;
        
        StrLib.defaultDateFormat = "MM/dd/yyyy";
        testDate = testBin;
        writeStdout (testDate);
      end
  6. これは、数値に小数桁がない場合に限り有効です。数値は、間隔のフォーマットに従って解釈されます。以下の例を考えてください。
    myInterval INTERVAL("yyMM") = 1208;
    ここで、EGL は、数値 1208 を 12 年と 8 カ月と解釈します。以下の規則が適用されます。
    • 数値の持つ桁数が間隔で許可された桁数を上回った場合、先行ゼロを無視し、右側の超過桁は無視されます。
    • 数値の持つ桁数が間隔で許可された桁数を下回った場合、先行ゼロが追加されます。
    • 間隔の記号が、数値記号に設定されます。
    • 間隔フィールドの数値が範囲外の値を示す場合、EGL は超過分を次のフィールドへ繰り上げます。以下の例を考えてください。
      myInterval INTERVAL("yyMM") = 8216;
      EGL は、間隔 83 年と 4 カ月を代入します。1 年は 12 カ月しかないので、「16」は 4 カ月として扱われ、元の 82 年にもう 1 年が繰り上げられます。
    • 間隔の左端フィールドから繰り上げる必要のある値の場合、これはエラーではありません。超過桁は、単に廃棄されます。次に別の例を示します。
      myInterval INTERVAL("yyMM") = 9925;
      EGL は、間隔 1 年と 1 カ月を代入します。25 カ月 = 2 年と 1 カ月であるので、月 = 01 となります。年の値 99 に月から繰り上がった超過分 2 を加えると 101 となり、01 に丸められます。
  7. FLOAT、SMALLFLOAT、または別の HEX (リテラルを含む) 以外の値を代入するには、as 演算子を使用して値をキャストします。
  8. 数値変数が 0 以外の値、正の数、または負の数の場合、EGL は、値 TRUE を BOOLEAN 変数に割り当てます。数値 0 のみ FALSE BOOLEAN 値になります。
  9. 日付/時刻型をテキストに変換 を参照してください。
  10. 数値型に DATE を割り当てると、値は 1899 年 12 月 31 日からの日数になります。
  11. BOOLEAN 変数が TRUE の場合、EGL は値 1 を数値型に割り当てます。FALSE の場合、0 に割り当てます。
  12. ターゲット変数に小数点以下の桁がない場合のみ有効です。

数値型間の丸めおよび切り捨て

数値型 (NUMC および PACF を含む) の値は、任意の数値型とサイズの変数に代入できます。 EGL は、値をターゲット・フォーマットで保持するために必要な変換を行います。

必要な場合、有意でないゼロが追加または切り捨てられます。 (値の整数部分の先頭からのゼロは有意ではありません。 同様に、値の小数部分の末尾桁のゼロも有意ではありません。)

V6 例外モードを使用し、vgVar.handleOverflow を適切に設定している場合は、 sysVar.overflowIndicator システム変数を使用して、 代入または算術計算の結果としてオーバーフローが発生したかどうかをテストできます。詳しくは、handleOverflowを参照してください。V6 例外モードを使用していない場合、またはオーバーフローをハンドルしない場合は、 オーバーフローが原因で EGL が RuntimeException をスローします。

ソースのランタイム値が 108.314 の場合、1 つの DECIMAL 変数をコピーすると結果は次のようになります。
  • ターゲット変数で 7 桁 (1 桁は小数部) を収容できる場合、ターゲット変数は値 000108.3 を受け取り、 オーバーフローは検出されません。 (小数値の精度の情報が失われても、オーバーフローとは見なされません。)
  • ターゲット変数で 4 桁 (2 桁は小数部) を収容できる場合は、オーバーフローが検出されます。

assignment 文では、truncateExtraDecimals ビルド記述子 オプションが YES (これはデフォルトです。 詳しくは「EGL 生成ガイド」を参照) に設定されていると、 ソースが FLOAT または SMALLFLOAT でターゲットに小数部の固定数がないかぎり、 余分の小数部が切り捨てられます。 truncateExtraDecimlas が NO に設定されているか、 ソースが FLOAT または SMALLFLOAT でターゲットに小数部の固定数がある場合は余分の小数部 は丸められます。

EGL のバージョン 6 および前のバージョンでは、truncateExtraDecimals オプションは存在しなかったので、 余分の小数部は、ソースが FLOAT または SMALLFLOAT でターゲットに小数部の固定数がある場合以外、切り捨てられました。 代入のソースが MathLib 関数の 1 つである場合は、規則を追加することによって、 切り捨てが回避されました。 この V6 スタイルの丸めを保持したい場合は、MathLib.assign() 関数を使用します (assign()参照)。

文字型に関する埋め込みと切り捨て

ターゲットが、非 STRING 文字型 (DBCHAR および HEX を含む) であり、ソース値の格納に必要である以上のスペースを持っている場合、EGL は以下のような方法で右側にデータを埋め込みます。
  • CHAR 型または MBCHAR 型のターゲットの場合は、単一バイトのブランクで埋め込みます。
  • DBCHAR 型のターゲットの場合は、2 バイトのブランクで埋め込みます。
  • UNICODE 型のターゲットの場合は、ユニコードの 2 バイトのブランクで埋め込みます。
  • HEX 型のターゲットの場合は、2 進ゼロで埋め込みます。 例えば、ソース値が "0A" であるなら、2 バイトのターゲットに "000A" ではなく "0A00" として値が格納されます。

ソース値を格納するためのスペースが文字型のターゲットで不足している場合は、EGL によって右側の値が切り捨てられます。通知されるエラーはありません。

ターゲットが limited-length string である場合、以下の規則が適用されます。
  • ターゲット中よりもソース中の文字が多い場合、EGL ランタイムはコピーされたコンテンツを切り捨てて使用可能な長さに合うようにします。
  • ターゲット中よりもソース中の文字が少ない場合は、EGL ランタイムはコピーされたコンテンツに空白を埋め込んでターゲット・ストリングの長さにします。 ただし、limited-length string 中の末尾ブランクは、比較中に無視されます。
以下の場合は、特殊な問題が発生することがあります。
  • ランタイム・プラットフォームで EBCDIC 文字セットがサポートされている
  • assignment 文により、MBCHAR 型のリテラルまたは MBCHAR 型の変数が、より短い MBCHAR 型の変数にコピーされる
  • 1 バイトずつ切り捨てを行うと、最後のシフトイン文字が除去されたり、2 バイト文字が分割されたりする

このような場合、EGL は、MBCHAR 型の有効なストリングがターゲット変数に格納されるように文字を切り捨て、必要があれば、終端に単一バイトのブランクを付加します。

NULL 可能型の相互間の代入

基本型に代入互換性がある NULL 可能変数は、NULL 可能ではない変数と代入互換性があります。 NULL 可能ではない変数が NULL 可能な変数に代入される場合、その代入はこのトピックで前述されている規則に従います。 ソース変数は NULL にできないため、この場合ターゲット変数は NULL に設定できません。 NULL 可能変数が NULL 可能ではない変数に代入される場合、その振る舞いはデータの型と、 ソースが現在 NULL であるかどうかによって決まります。 その振る舞いは、以下の規則によって説明されます。
  • ソースが現在 NULL でターゲットが文字変数の場合、ターゲット変数は ブランクに設定されます。
  • ソースが現在 NULL でターゲット変数が数値の場合、ターゲット変数は 0 に設定されます。
  • ソースが NULL ではない場合、代入は通常の割り当て規則に従います。

NULL 可能変数は、全く同じ基本型を持つ別の NULL 可能変数との間にのみ参照互換性があります。 代入は、EGL での参照の互換性で説明されている規則に従います。

タイム・スタンプ間の代入

ある TIMESTAMP 変数を別の TIMESTAMP 変数に代入する場合、以下の規則が適用されます。
  • ソース変数のマスクに、ターゲット変数が必要とする相対的に上位レベルのエントリーが 欠落している場合、それらのターゲット・エントリーには、代入時点でのマシンのクロックに 従って代入が行われます。次に例を示します。
    •   sourceTimeStamp timestamp ("MMdd");
         targetTimeStamp timestamp ("yyyyMMdd");
        
         sourceTimeStamp = "1201";
      
        // このコードが 2004 年に実行された場合、次の文が
        // targetTimeStamp に 20041201 を代入する
         targetTimeStamp = sourceTimeStamp; 
    •   sourceTimeStamp02 timestamp ("ssff");
        targetTimeStamp02 timestamp ("mmssff");
        
         sourceTimeStamp02 = "3201";
      
        // 次の代入は、分を含んでいる
        // それは、assignment 文が実行されたときの現行の分である
        targetTimeStamp02 = sourceTimeStamp02;
    • ソース変数のマスクに、ターゲット変数が必要とする相対的に下位レベルのエントリーが 欠落している場合、それらのターゲット・エントリーには、有効な最低の値が代入されます。 次に例を示します。
      • sourceTimeStamp timestamp ("yyyyMM");
        targetTimeStamp timestamp ("yyyyMMdd");
        
        sourceTimeStamp = "200412";
        
        // 日に関係なく、次の文は
        // targetTimeStamp に 20041201 を代入する
        targetTimeStamp = sourceTimeStamp; 
      • sourceTimeStamp02 timestamp ("hh");
        targetTimeStamp02 timestamp ("hhmm");
        
        sourceTimeStamp02 = "11";
        
        // 分に関係なく、次の文は
        // targetTimeStamp02 に 1100 を代入する
        targetTimeStamp02 = sourceTimeStamp02;

構造化レコード内のフィールド相互間での代入

副構造のあるフィールドを副構造のないフィールドに代入したり、その逆を行うことができます。 また、2 つの副構造フィールドの間で値を代入できます。 例えば、myNum および myRecord という名前の変数が、次のパーツに基づいているものとします。

  DataItem Num12
    NUM(12)
  end

  Record ExampleRecord type basicRecord
    10 topMost CHAR(4);
      20 next01 HEX(4);
      20 next02 HEX(4);
  end

数学的システム変数の範囲外では、HEX 型の値を NUM 型の変数に代入することは無効です。ただし、myNum = topMost という書式の代入は、topMost が CHAR 型であるため、有効です。一般に、代 入は、assignment 文内のフィールドのプリミティブ型に基づいて実行され、従属フィールドのプリミティブ型は考慮されません。

デフォルトで、副構造のあるフィールドのプリミティブ型は、CHAR に設定されています。副構造のあるフィールド相互間でデータを代入する場合、宣言時に別のプリミティブ型を指定しないと、CHAR 型のフィールドに対する前述の規則が代入時に適用されます。

構造化レコードの代入

ある構造化レコード変数から別の固定レコード変数への代入は、CHAR 型の副構造化項目から別の CHAR 型の副構造化フィールドへの代入と同等です。 長さの不一致があると、受け取った値の右端に単一バイトのブランクが付加されたり、受け取った値の右端から 1 バイトの文字が除去されたりします。 代入では、従属構造化フィールドのプリミティブ型は考慮されません。

以下の例外が適用されます。
  • レコードの内容を代入できるのは、レコード変数または、CHAR 型、HEX 型、STRING 型、または MBCHAR 型の変数です。 その他の型の変数に代入することはできません。
  • レコードは以下のいずれかのソースからデータを受け取ることができます。
    • 別のレコード
    • 文字列リテラル (数値リテラル以外)
    • CHAR、HEX、STRING、または MBCHAR 変数 (他の型は許可されません)

最後に、構造化 SQL レコード変数と、異なる型の構造化レコード変数との間で相互に代入する場合は、各構造化フィールドに先行する 4 バイトの領域用のスペースを非 SQL レコードに確保する必要があります (詳しくは、構造化レコードを参照)。

レコード間の代入

非構造化レコード変数は、型が同じ他の非構造化レコード変数とのみ代入に互換性があります。

環境間で整合した結果の確保

中間結果の切り捨てが原因で、COBOL プログラムでは、同じ算術ステートメントの結果が Java™ または Rich UI プログラムとは異なることがあります。環境間で整合した結果にするには、ステートメントごとに 2 項演算子を 1 つのみ使用してください。結果項目に対して定義されている小数点以下の桁数が、いずれかのオペランドにおける小数点以下の桁数以上である場合は、複数の加算演算子と減算演算子を結合しても問題ありません。

結果またはいずれかのオペランドが、ゼロより大きい小数点以下の桁数で定義されている場合は、剰余演算子によって矛盾する結果が生成されることがあります。小数点以下の桁数で整合した剰余を得るには、剰余演算子ではなく以下の算法を使用してください。
quotient = dividend / divisor;
remainder = dividend - (quotient * divisor);

互換性

表 4. 代入の互換性に関する考慮事項
プラットフォーム 問題
COBOL 生成 EGL は、テキストを SMALLFLOAT や FLOAT に変換することはできませんが、それ以外であれば可能です。

フィードバック