データエリア

フィールドの定義」で説明されているように、プログラムで使用するすべてのフィールドは DEFINE DATA ステートメントに定義する必要があります。

フィールドは DEFINE DATA ステートメント内に直接定義できます。または、プログラム外部の別個のデータエリアにフィールドを定義し、DEFINE DATA ステートメントでそのデータエリアを参照できます。

別個のデータエリアとは、複数の Natural プログラム、サブプログラム、サブルーチン、ヘルプルーチン、またはクラスで使用できる Natural オブジェクトを指します。データエリアには、データ定義モジュール(DDM)から取得されるユーザー定義変数、定数、データベースフィールドなどのデータ要素定義が含まれています。

すべてのデータエリアは、データエリアエディタで作成および編集します。

Natural では、次の 3 つのタイプのデータエリアがサポートされます。


ローカルデータエリア(LDA)

ローカルとして定義された変数は、単一の Natural オブジェクト内でのみ使用できます。ローカルデータを定義する方法は次の 2 つです。

  • プログラム内部に定義します。

  • プログラム外部の別個の Natural オブジェクト、すなわちローカルデータエリア(LDA)に定義します。

    このようなローカルデータエリアは、そのローカルデータエリアを使用するプログラム、サブプログラム、または外部サブルーチンが実行を開始するときに初期化されます。

アプリケーション構造を明確にして管理しやすくするために、通常はプログラム外部のデータエリアにフィールドを定義する方が便利です。

例 1:DEFINE DATA ステートメント内に直接定義されたフィールド

次の例では、フィールドはプログラムの DEFINE DATA ステートメント内に直接定義されています。

DEFINE DATA LOCAL 
1 VIEWEMP VIEW OF EMPLOYEES 
  2 NAME 
  2 FIRST-NAME 
  2 PERSONNEL-ID 
1 #VARI-A (A20) 
1 #VARI-B (N3.2) 
1 #VARI-C (I4) 
END-DEFINE 
...

例 2:別のデータエリアに定義されたフィールド

次の例では、同じフィールドがプログラムの DEFINE DATA ステートメントにではなく LDA39 という名前の LDA に定義されており、DEFINE DATA ステートメントにはそのデータエリアへの参照のみ含まれています。

プログラム:

DEFINE DATA LOCAL 
       USING LDA39 
END-DEFINE 
  ...

ローカルデータエリア LDA39

I T L  Name                             F Length     Miscellaneous             
All -- -------------------------------- - ---------- ------------------------->
  V  1 VIEWEMP                                       EMPLOYEES                 
     2 PERSONNEL-ID                     A          8                           
     2 FIRST-NAME                       A         20                           
     2 NAME                             A         20                           
     1 #VARI-A                          A         20                           
     1 #VARI-B                          N        3.2                           
     1 #VARI-C                          I          4                          

グローバルデータエリア(GDA)

以下では次のトピックについて説明します。

グローバルデータエリアの作成と参照

グローバルデータエリア(GDA)は、データエリアエディタで作成および変更されます。詳細については、『エディタ』ドキュメントの「データエリアエディタ」を参照してください。

Natural オブジェクトで参照される GDA は、この GDA を参照するオブジェクトが保存されているものと同じ Natural ライブラリ、またはこのライブラリに定義されている steplib に保存する必要があります。

注意:
起動における COMMON という名前の GDA の使用:
COMMON という名前の GDA がライブラリに存在する場合は、このライブラリに LOGON すると、ACOMMON という名前のプログラムが自動的に呼び出されます。

重要:
複数の Natural オブジェクトが 1 つの GDA を参照するアプリケーションを構築するときは、この GDA 内のデータ要素定義を変更すると、このデータエリアを参照するすべての Natural オブジェクトに影響が及ぶことに注意してください。そのため、GDA の修正後に、CATALOG または STOW コマンドを使用して、これらのオブジェクトを再コンパイル()する必要があります。

GDA を使用するには、Natural オブジェクトで DEFINE DATA ステートメントの GLOBAL 節を使用して GDA を参照する必要があります。それぞれの Natural オブジェクトは 1 つのグローバルデータエリアのみを参照できます。つまり、DEFINE DATA ステートメントに複数の GLOBAL 節を含めることはできません。

GDA インスタンスの作成および削除

GDA の最初のインスタンスは、これを参照する最初の Natural オブジェクトが実行を開始したランタイムに作成され、初期化されます。

GDA インスタンスが作成されると、この中に含まれるデータ値は、この GDA を参照する(DEFINE DATA GLOBAL ステートメント)すべての Natural オブジェクト、および PERFORMINPUT、または FETCH ステートメントによって呼び出されるすべての Natural オブジェクトで共有できます。GDA インスタンスを共有するすべてのオブジェクトは、同じデータ要素上で機能します。

次の状況が該当する場合に、新しい GDA インスタンスが作成されます。

  • いずれかの GDA を参照するサブプログラムが CALLNAT ステートメントで呼び出された。

  • GDA を参照しないサブプログラムが、いずれかの GDA を参照するオブジェクトを呼び出した。

GDA の新しいインスタンスが作成されると、現在の GDA インスタンスは中断され、含まれていたデータ値はスタックされます。次にサブプログラムが、新しく作成された GDA インスタンス内のデータ値を参照します。中断された GDA インスタンス内のデータ値にアクセスすることはできません。オブジェクトは 1 つの GDA インスタンスしか参照できず、以前の GDA インスタンスにアクセスすることはできません。GDA データ要素は、CALLNAT ステートメント内でパラメータとして定義することによって、サブプログラムに渡すことのみが可能です。

サブプログラムが、呼び出し元オブジェクトに戻ると、参照されていた GDA インスタンスは削除され、それまで中断していた GDA インスタンスがそのデータ値とともに再開されます。

次のいずれかが該当する場合、GDA インスタンスとその内容は削除されます。

  • 次の LOGON が実行された。

  • 同じレベルで別の GDA が参照された(レベルについてはこのセクションで後述)。

  • RELEASE VARIABLES ステートメントが実行された。この場合、GDA インスタンス内の変数は、レベル 1 のプログラムの実行が終了するか、プログラムが FETCH または RUN ステートメントで別のプログラムを呼び出したときにリセットされます。

    次のセクションの図は、オブジェクトが GDA を参照し、GDA インスタンス内のデータ要素を共有する様子を示しています。

GDA インスタンスの共有

次の図は、GDA を参照するサブプログラムが、呼び出し元プログラムが参照する GDA インスタンス内のデータ値を共有できないことを示しています。呼び出し元プログラムと同じ GDA を参照するサブプログラムは、この GDA の新しいインスタンスを作成します。ただし、サブプログラムが参照する GDA に定義されているデータ要素は、このサブプログラムが呼び出したサブルーチンやヘルプルーチンで共有できます。

次の図は、GDA1 の 3 つの GDA インスタンスと、データ要素 #GLOB1 によって各 GDA インスタンスに割り当てられる最終値を示しています。数字 graphics/gda_share_num1.pnggraphics/gda_share_num7.png は、オブジェクトの階層レベルを示しています。

FETCH または FETCH RETURN の使用

次の図は、同じ GDA を参照し、FETCH または FETCH RETURN ステートメントを使用してそれぞれを呼び出す複数のプログラムが、この GDA 内に定義されているデータ要素を共有することを示しています。これらのプログラムのいずれかが GDA を参照しない場合は、以前に参照されていた GDA のインスタンスがアクティブなまま残り、データ要素の値が保持されます。

数字 graphics/gda_share_num1.pnggraphics/gda_share_num2.png は、オブジェクトの階層レベルを示しています。

異なる GDA での FETCH の使用

次の図は、プログラムが FETCH ステートメントを使用して、異なる GDA を参照する別のプログラムを呼び出すと、呼び出し元プログラムが参照する GDA(ここでは GDA1)の現在のインスタンスが削除されることを示しています。その後、この GDA が他のプログラムから再び参照されると、この GDA の新しいインスタンスが作成され、その中のすべてのデータ要素にはそれぞれの初期値が指定されます。

FETCH RETURN ステートメントを使用して、異なる GDA を参照する別のプログラムを呼び出すことはできません。

数字 graphics/gda_share_num1.png はオブジェクトの階層レベルを示しています。

呼び出し元プログラム PROG3 および PROG4 によって、GDA インスタンスは次のような影響を受けます。

  • PROG3 内のステートメント GLOBAL USING GDA2 によって、GDA2 のインスタンスが作成され、GDA1 の現在のインスタンスが削除されます。

  • PROG4 内のステートメント GLOBAL USING GDA1 によって、GDA2 の現在のインスタンスが削除され、GDA1 の新しいインスタンスが作成されます。この結果、WRITE ステートメントで値ゼロ(0)が表示されます。

データブロック

データストレージスペースを節約するために、データブロックが含まれる GDA を作成できます。

以下では次のトピックについて説明します。

データブロックの使用例

データブロックは、プログラムの実行中に相互に重ねることができるため、ストレージスペースの節約になります。

例えば、次のような階層では、ブロック B とブロック C が同じストレージエリアに割り当てられます。したがって、ブロック B とブロック C は同時に使用できません。ブロック B を変更すると、ブロック C の内容が破壊されます。

データブロックの定義

データブロックはデータエリアエディタで定義します。どのブロックがどのブロックの下位になるかを指定して、ブロック階層を設定します。これは、ブロック定義のコメントフィールドに "親" ブロックの名前を入力して設定します。

次の例では、SUB-BLOCKB および SUB-BLOCKCMASTER-BLOCKA に従属しており、SUB-BLOCKDSUB-BLOCKB に従属しています。

ブロックレベルの最大値は 8(マスタブロックを含む)です。

例:

グローバルデータエリア G-BLOCK

  I T L Name                             F Leng Index/Init/EM/Name/Comment       
  - - - -------------------------------- - ---- ---------------------------------
    B   MASTER-BLOCKA                                                            
      1 MB-DATA01                        A   10                                  
    B   SUB-BLOCKB                              MASTER-BLOCKA                    
      1 SBB-DATA01                       A   20                                  
    B   SUB-BLOCKC                              MASTER-BLOCKA                    
      1 SBC-DATA01                       A   40                                  
    B   SUB-BLOCKD                              SUB-BLOCKB                       
      1 SBD-DATA01                       A   40                                  
                               

特定のブロックをプログラムで使用可能にするには、DEFINE DATA ステートメント内で次の構文を使用します。

プログラム 1:

DEFINE DATA GLOBAL 
       USING G-BLOCK 
       WITH MASTER-BLOCKA 
END-DEFINE

プログラム 2:

DEFINE DATA GLOBAL 
       USING G-BLOCK 
       WITH MASTER-BLOCKA.SUB-BLOCKB 
END-DEFINE

プログラム 3:

DEFINE DATA GLOBAL 
       USING G-BLOCK 
       WITH MASTER-BLOCKA.SUB-BLOCKC 
END-DEFINE

プログラム 4:

DEFINE DATA GLOBAL 
       USING G-BLOCK 
       WITH MASTER-BLOCKA.SUB-BLOCKB.SUB-BLOCKD 
END-DEFINE

この構造では、プログラム 1 がプログラム 2、プログラム 3、またはプログラム 4 と MASTER-BLOCKA 内のデータを共有できます。ただし、プログラム 2 とプログラム 3 は SUB-BLOCKBSUB-BLOCKC のデータエリアを共有できません。これらのデータブロックは構造と同じレベルにあるため、同じストレージエリアを占有しているからです。

ブロック階層

データブロック階層を使用するときは注意が必要です。3 つのプログラムがデータブロック階層を使用する次のシナリオを想定します。

プログラム 1:

DEFINE DATA GLOBAL 
       USING G-BLOCK 
       WITH MASTER-BLOCKA.SUB-BLOCKB 
END-DEFINE 
* 
MOVE 1234 TO SBB-DATA01 
FETCH 'PROGRAM2' 
END

プログラム 2:

DEFINE DATA GLOBAL 
       USING G-BLOCK 
       WITH MASTER-BLOCKA 
END-DEFINE 
* 
FETCH 'PROGRAM3' 
END

プログラム 3:

DEFINE DATA GLOBAL 
       USING G-BLOCK 
       WITH MASTER-BLOCKA.SUB-BLOCKB 
END-DEFINE 
* 
WRITE SBB-DATA01 
END

説明

  • プログラム 1 ではグローバルデータエリア G-BLOCKMASTER-BLOCKA および SUB-BLOCKB とともに使用しています。このプログラムは SUB-BLOCKB 内のフィールドを変更して、プログラム 2 をフェッチしますが、プログラム 2 のデータ定義には MASTER-BLOCKA しか指定されていません。

  • プログラム 2 は SUB-BLOCKB をリセット、つまりその内容を削除します。これは、レベル 1 のプログラム(例えば、FETCH ステートメントで呼び出されたプログラム)は、そのデータ定義に定義されているブロックの下位となるすべてのデータブロックをリセットするからです。

  • 次にプログラム 2 はプログラム 3 をフェッチします。プログラム 3 はプログラム 1 で変更されたフィールドを表示するものですが、空の画面を返します。

プログラムレベルの詳細については、「呼び出されるオブジェクトの複数レベル」を参照してください。

パラメータデータエリア(PDA)

サブプログラムは、CALLNAT ステートメントを使用して呼び出されます。CALLNAT ステートメントを使用して、パラメータを呼び出し元オブジェクトからサブプログラムに渡すことができます。

このようなパラメータは、サブプログラム内の DEFINE DATA PARAMETER ステートメントに、次の方法で定義する必要があります。

  • DEFINE DATA ステートメントの PARAMETER 節内に直接定義します。

  • 別のパラメータデータエリア(PDA)に定義して、その PDA を参照する DEFINE DATA PARAMETER ステートメントを指定します。

以下では次のトピックについて説明します。

DEFINE DATA PARAMETER ステートメント内に定義されたパラメータ

パラメータデータエリアに定義されたパラメータ

同様に、PERFORM ステートメントによって外部サブルーチンに渡されるパラメータは、外部サブルーチン内の DEFINE DATA PARAMETER ステートメントを使用して定義する必要があります。

呼び出し元オブジェクトでは、サブプログラム/サブルーチンに渡されるパラメータ変数を PDA 内に定義する必要はありません。上記の図では、呼び出し元オブジェクトが使用する LDA に定義されていますが、GDA に定義することも可能です。

呼び出し元オブジェクト内の CALLNAT/PERFORM ステートメントで指定されるパラメータの順序、フォーマット、および長さは、呼び出されるサブプログラム/サブルーチンの DEFINE DATA PARAMETER ステートメントに指定されるフィールドの順序、フォーマット、および長さと正確に一致する必要があります。ただし、呼び出し元オブジェクト内の変数の名前は、呼び出されるサブプログラム/サブルーチンと同じである必要はありません。パラメータは名前ではなくアドレスで転送されるためです。

呼び出し元プログラムで使用されるデータ要素定義が、サブプログラムまたは外部サブルーチンで使用されるデータ要素定義と同一であることを確実にするために、DEFINE DATA LOCAL USING ステートメントに PDA を指定できます。PDA を LDA として使用することにより、PDA と同じ構造を持つ LDA を作成する手間を省くことができます。

配列の次元のフォーマット指定のマッチング

配列をパラメータとして渡す場合、その次元は、呼び出されたサブプログラムまたはサブルーチンの DEFINE DATA PARAMETER ステートメントで指定された配列の次元と一致する必要があります。次元が一致しない場合、オカレンスの数が一致してもエラーが生成されます。

例:

呼び出されたサブプログラム SUB

DEFINE DATA PARAMETER
1 B (A5/1:5)         
END-DEFINE           
...

NAT0937 コンパイラエラーのあるプログラム呼び出し:

DEFINE DATA LOCAL   
1 A (A5/1:1,1:5)    
END-DEFINE          
CALLNAT 'SUB' A(1,*)
...

コンパイラエラーのないプログラム呼び出し:

DEFINE DATA LOCAL 
1 A (A5/1:5)      
END-DEFINE        
CALLNAT 'SUB' A(*)