ダイナミック変数およびラージ変数の使用

このドキュメントでは、次のトピックについて説明します。


全般的な注意事項

通常、次の規則が適用されます。

  • ダイナミック英数字フィールドは、英数字フィールドを使用できる場所であればどこにでも使用できます。

  • ダイナミックバイナリフィールドは、バイナリフィールドを使用できる場所であればどこにでも使用できます。

  • ダイナミック Unicode フィールドは、Unicode フィールドを使用できる場所であればどこにでも使用できます。

例外:

ダイナミック変数は、SORT ステートメント内では使用できません。ダイナミック変数を DISPLAYWRITEPRINTREINPUT または INPUT の各ステートメント内で使用するには、セッションパラメータ AL または EM のいずれかを使用して変数の長さを定義する必要があります。

ダイナミック変数に割り当てられているストレージの使用長(Natural システム変数 *LENGTH によって示される。「ダイナミック変数の現在の値スペース」を参照)およびサイズは、その変数がターゲットオペランドとして最初にアクセスされるまではゼロです。割り当て操作またはその他の操作によって、ダイナミック変数はソースオペランドの正確なサイズに初めて割り当てまたは拡張(再割り当て)されます。

以下のステートメントで変更可能なオペランド(ターゲットオペランド)としてダイナミック変数を使用する場合、ダイナミック変数のサイズを拡張できます。

ASSIGN operand1(割り当て内の応答先オペランド)。
CALLNAT ダイナミック変数を使用したパラメータ引き渡し」を参照してください(AD=O、または対応するパラメータデータエリア内に BY VALUE が存在する場合を除く)。
COMPRESS operand2。「処理」を参照してください。
EXAMINE DELETE REPLACE 節の operand1
MOVE operand2(応答先オペランド)。「機能」を参照してください。
PERFORM AD=O、または対応するパラメータデータエリア内に BY VALUE が存在する場合を除く)。
READ WORK FILE operand1 および operand2。「」「ラージ変数およびダイナミック変数の処理」を参照してください。
SEPARATE operand4
SELECT (SQL) parameter INTO 節。into-clause を参照してください。
SEND METHOD operand3AD=O の場合を除く)。

現時点では、ラージ変数の使用には以下の制限があります。

CALL 各パラメータのサイズは 64 KB 未満です(INTERFACE4 オプションを使用した CALL には制限はありません)。

以下のセクションでは、ダイナミック変数の使用について、例に基づいてさらに詳しく説明します。

ダイナミック変数を使用した割り当て

通常は、ソースオペランドの現在の使用長(Natural システム変数 *LENGTH によって示される)で割り当てが行われます。応答先オペランドがダイナミック変数の場合、ソースオペランドを切り捨てずに移動できるよう、現在割り当てられているサイズが拡張される場合があります。

例:

#MYDYNTEXT1 := OPERAND
MOVE OPERAND TO #MYDYNTEXT1
/* #MYDYNTEXT1 IS AUTOMATICALLY EXTENDED UNTIL THE SOURCE OPERAND CAN BE COPIED 

MOVE ALL、およびダイナミックターゲットオペランドを使用した MOVE ALL UNTIL は、以下のように定義されています。

  • MOVE ALL では、ターゲットオペランドの使用長(*LENGTH)に到達するまで、ソースオペランドをターゲットオペランドに繰り返し移動します。システム変数 *LENGTH は変更されません。*LENGTH がゼロの場合、このステートメントは無視されます。

  • MOVE ALL operand1 TO operand2 UNTIL operand3 は、operand3 で指定された長さに達するまで、operand1 を繰り返し operand2 に移動します。operand3*LENGTH(operand2) より大きい場合、operand2 は拡張され、*LENGTH(operand2)operand3 に設定されます。operand3*LENGTH(operand2) より小さい場合、使用長は operand3 に縮小されます。operand3*LENGTH(operand2) に等しい場合、動作は MOVE ALL と等しくなります。

例:

#MYDYNTEXT1 := 'ABCDEFGHIJKLMNO'          /* *LENGTH(#MYDYNTEXT1) = 15
MOVE ALL 'AB' TO #MYDYNTEXT1              /* CONTENT OF #MYDYNTEXT1 = 'ABABABABABABABA';  
                                          /* *LENGTH IS STILL 15
MOVE ALL 'CD' TO #MYDYNTEXT1 UNTIL 6      /* CONTENT OF #MYDYNTEXT1 = 'CDCDCD';
                                          /* *LENGTH = 6
MOVE ALL 'EF' TO #MYDYNTEXT1 UNTIL 10     /* CONTENT OF #MYDYNTEXT1 = 'EFEFEFEFEF'; 
                                          /* *LENGTH = 10

MOVE JUSTIFIED は、ターゲットオペランドがダイナミック変数の場合、コンパイル時に拒否されます。

MOVE SUBSTR および MOVE TO SUBSTR は実行できます。MOVE SUBSTR は、ダイナミック変数の使用長(*LENGTH)を超えるサブストリングを参照すると、ランタイムエラーになります。MOVE TO SUBSTR は、*LENGTH + 1 を超えるサブストリングの位置を参照すると、ダイナミック変数の内容に未定義のギャップが生じるため、ランタイムエラーになります。ターゲットオペランドを MOVE TO SUBSTR で拡張する必要がある場合(第 2 オペランドが *LENGTH+1 に設定されている場合など)、第 3 オペランドは必須です。

有効な構文:

#OP2 := *LENGTH(#MYDYNTEXT1)
MOVE SUBSTR (#MYDYNTEXT1, #OP2) TO OPERAND                /* MOVE LAST CHARACTER TO OPERAND
#OP2 := *LENGTH(#MYDYNTEXT1) + 1
MOVE OPERAND TO SUBSTR(#MYDYNTEXT1, #OP2, #lEN_OPERAND)   /* CONCATENATE OPERAND TO #MYDYNTEXT1          

無効な構文:

#OP2 := *LENGTH(#MYDYNTEXT1) + 1
MOVE SUBSTR (#MYDYNTEXT1, #OP2, 10) TO OPERAND            /* LEADS TO RUNTIME ERROR; UNDEFINED SUB-STRING  
#OP2 := *LENGTH(#MYDYNTEXT1 + 10) 
MOVE OPERAND TO SUBSTR(#MYDYNTEXT1, #OP2, #EN_OPERAND)    /* LEADS TO RUNTIME ERROR; UNDEFINED GAP
#OP2 := *LENGTH(#MYDYNTEXT1) + 1
MOVE OPERAND TO SUBSTR(#MYDYNTEXT1, #OP2)                 /* LEADS TO RUNTIME ERROR; UNDEFINED LENGTH

割り当ての互換性

例:

#MYDYNTEXT1   := #MYSTATICVAR1
#MYSTATICVAR1 := #MYDYNTEXT2   

ソースオペランドがスタティック変数の場合、ダイナミックな応答先オペランドの使用長(*LENGTH(#MYDYNTEXT1))はスタティック変数のフォーマット長に設定され、末尾の空白(フォーマット A および U)またはバイナリゼロ(フォーマット B)を含め、この長さでソースオペランドがコピーされます。

応答先オペランドがスタティックでソースオペランドがダイナミックの場合、ダイナミック変数は現在の使用長でコピーされます。この長さがスタティック変数のフォーマット長より短い場合、残りの部分は空白(英数字フィールドおよび Unicode フィールドの場合)またはバイナリゼロ(バイナリフィールドの場合)で埋められます。そうでない場合、値は切り捨てられます。ダイナミック変数の現在の使用長が 0 の場合、スタティックのターゲットオペランドは空白(英数字フィールドおよび Unicode フィールドの場合)またはバイナリゼロ(バイナリフィールドの場合)で埋められます。

ダイナミック変数の初期化

ダイナミック変数は、RESET ステートメントを使用して、最大で現在の使用長(= *LENGTH)まで、空白(英数字フィールドおよび Unicode フィールドの場合)またはゼロ(バイナリフィールドの場合)で初期化できます。システム変数 *LENGTH は変更されません。

例:

DEFINE DATA LOCAL
1 #MYDYNTEXT1   (A)  DYNAMIC
END-DEFINE
#MYDYNTEXT1 := 'SHORT TEXT'
WRITE *LENGTH(#MYDYNTEXT1)          /* USED LENGTH = 10
RESET #MYDYNTEXT1                   /* USED LENGTH = 10, VALUE = 10 BLANKS  

ダイナミック変数を特定のサイズと値で初期化するには、MOVE ALL UNTIL ステートメントを使用します。

例:

MOVE ALL 'Y' TO #MYDYNTEXT1 UNTIL 15          /* #MYDYNTEXT1 CONTAINS 15 'Y'S, USED LENGTH = 15 

ダイナミック英数字変数での文字列操作

変更可能なオペランドがダイナミック変数の場合、切り捨てまたはエラーメッセージを発生させずに操作できるよう、現在割り当てられているサイズが拡張される場合があります。これは、ダイナミック変数の連結(COMPRESS)および分割(SEPARATE)で有効です。

例:

** Example 'DYNAMX01': Dynamic variables (with COMPRESS and SEPARATE)   
************************************************************************
DEFINE DATA LOCAL                                                       
1 #MYDYNTEXT1 (A)   DYNAMIC                                             
1 #TEXT       (A20)                                                     
1 #DYN1       (A)   DYNAMIC                                             
1 #DYN2       (A)   DYNAMIC                                             
1 #DYN3       (A)   DYNAMIC                                             
END-DEFINE                                                              
*                                                                       
MOVE ' HELLO WORLD ' TO #MYDYNTEXT1                                     
WRITE #MYDYNTEXT1 (AL=25) 'with length' *LENGTH (#MYDYNTEXT1)           
/*  dynamic variable with leading and trailing blanks                   
*                                                                       
MOVE ' HELLO WORLD ' TO #TEXT                                           
*                                                                       
MOVE #TEXT TO #MYDYNTEXT1                                               
WRITE #MYDYNTEXT1 (AL=25) 'with length' *LENGTH (#MYDYNTEXT1)           
/*  dynamic variable with whole variable length of #TEXT
*                                                              
COMPRESS #TEXT INTO #MYDYNTEXT1                                
WRITE #MYDYNTEXT1 (AL=25) 'with length' *LENGTH (#MYDYNTEXT1)  
/*  dynamic variable with leading blanks of #TEXT              
*                                                              
*                                                              
#MYDYNTEXT1 := 'HERE COMES THE SUN'                            
SEPARATE #MYDYNTEXT1 INTO #DYN1 #DYN2 #DYN3 IGNORE             
*                                                              
WRITE / #MYDYNTEXT1 (AL=25) 'with length' *LENGTH (#MYDYNTEXT1)
WRITE #DYN1 (AL=25) 'with length' *LENGTH (#DYN1)              
WRITE #DYN2 (AL=25) 'with length' *LENGTH (#DYN2)              
WRITE #DYN3 (AL=25) 'with length' *LENGTH (#DYN3)              
/*  #DYN1, #DYN2, #DYN3 are automatically extended or reduced  
*                                                              
EXAMINE #MYDYNTEXT1 FOR 'SUN' REPLACE 'MOON'                   
WRITE / #MYDYNTEXT1 (AL=25) 'with length' *LENGTH (#MYDYNTEXT1)
/*  #MYDYNTEXT1 is automatically extended or reduced           
*
END

注意:
非ダイナミック変数の場合、エラーメッセージが返されます。

ダイナミック変数を使用した論理条件の基準(LCC)

ダイナミック変数を使用して読み取り専用の操作(比較など)を行う場合、通常は現在の使用長を使用して実行されます。読み取り操作(変更なし)で使用される場合、ダイナミック変数はスタティック変数と同様に処理されます。

例:

IF  #MYDYNTEXT1  =  #MYDYNTEXT2  OR  #MYDYNTEXT1 =  "**"  THEN ...
IF  #MYDYNTEXT1  <  #MYDYNTEXT2  OR  #MYDYNTEXT1 <  "**"  THEN ...  
IF  #MYDYNTEXT1  >  #MYDYNTEXT2  OR  #MYDYNTEXT1 >  "**"  THEN ...

英数字変数および Unicode 変数の末尾の空白またはバイナリ変数の先頭のバイナリゼロは、スタティック変数とダイナミック変数で同様に処理されます。例えば、AA および空白が続く AA を値として持つ英数字変数は同一とみなされ、H’0000031’ および H’3031’ という値を持つバイナリ変数は同一とみなされます。値が完全に同じ場合にのみ比較結果を TRUE とする場合は、ダイナミック変数の使用長も比較する必要があります。一方の変数ともう一方の変数の値が完全に同じであれば、その使用長もまた同じです。

例:

#MYDYNTEXT1  :=  'HELLO'                                     /* USED LENGTH IS 5
#MYDYNTEXT2  :=  'HELLO     '                                /* USED LENGTH IS 10  
IF   #MYDYNTEXT1  =  #MYDYNTEXT2   THEN  ...                 /* TRUE
IF   #MYDYNTEXT1  =  #MYDYNTEXT2 AND     
     *LENGTH(#MYDYNTEXT1) = *LENGTH(#MYDYNTEXT2)  THEN  ...  /* FALSE

2 つのダイナミック変数は、どちらか短い方の使用長に達するまで 1 ポジションずつ比較されます(英数字変数の場合は左から右、バイナリ変数の場合は右から左)。最初に値が異なったポジションで、1 番目の変数と 2 番目の変数のどちらがより大きいか、小さいか、または同じかが判断されます。変数の短い方の使用長まで値が同じで、長い方の残りの値がダイナミック英数字変数の場合は空白のみ、ダイナミックバイナリ変数の場合はバイナリゼロのみの場合、それらの変数は同じとみなされます。2 つのダイナミック Unicode 変数を比較する場合、両方の値の末尾の空白を削除してから、ICU 照合アルゴリズムを使用して 2 つの値が比較されます。『Unicode とコードページのサポート』ドキュメントの「論理条件の基準」も参照してください。

例:

#MYDYNTEXT1  :=  'HELLO1'                    /* USED LENGTH IS 6
#MYDYNTEXT2  :=  'HELLO2'                    /* USED LENGTH IS 10  
IF #MYDYNTEXT1  <  #MYDYNTEXT2 THEN  ...     /* TRUE
#MYDYNTEXT2  :=  'HALLO'
IF #MYDYNTEXT1  >  #MYDYNTEXT2 THEN  ...     /* TRUE

比較の互換性

ダイナミック変数とスタティック変数の比較は、ダイナミック変数間の比較と同じです。スタティック変数のフォーマット長が使用長として使用されます。

例:

#MYSTATTEXT1 :=  'HELLO'                      /* FORMAT LENGTH OF MYSTATTEXT1 IS A20  
#MYDYNTEXT1  :=  'HELLO'                      /* USED LENGTH IS 5
IF  #MYSTATTEXT1  =  #MYDYNTEXT1  THEN  ...   /* TRUE
IF  #MYSTATTEXT1  >  #MYDYNTEXT1  THEN  ...   /* FALSE

ダイナミックコントロールフィールドの AT/IF-BREAK

ブレイクコントロールフィールドの元の値との比較は、左から右に向かって 1 ポジションずつ実行されます。ダイナミック変数の元の値と新しい値で長さが異なる場合、比較するために長さが短い方の値の右側に空白(ダイナミック英数字変数またはダイナミック Unicode 変数の場合)またはバイナリゼロ(バイナリ値の場合)が追加されます。

英数字または Unicode のブレイクコントロールフィールドの場合、比較において末尾の空白は意味を持ちません。つまり、末尾の空白は値の変更を意味しないため、ブレイクは発生しません。

バイナリのブレイクコントロールフィールドの場合、比較において末尾のバイナリゼロは意味を持ちません。つまり、末尾のバイナリゼロは値の変更を意味しないため、ブレイクは発生しません。

ダイナミック変数を使用したパラメータ引き渡し

ダイナミック変数は、呼び出されたプログラムオブジェクト(CALLNATPERFORM)へのパラメータとして渡すことができます。ダイナミック変数の値スペースは連続しているので、値による呼び出しが可能です。値による呼び出しを使用すると、呼び出し元の変数定義がソースオペランドとして割り当てられ、パラメータ定義が応答先オペランドとして割り当てられます。また、値による呼び出しの結果では、逆方向にデータが移動します。

参照による呼び出しを使用する場合、変数定義およびパラメータ定義は DYNAMIC である必要があります。そのうちの 1 つだけが DYNAMIC の場合、ランタイムエラーが発生します。値による呼び出し(結果)の場合、すべての組み合わせを使用できます。以下の表に、有効な組み合わせを示します。

参照渡し

呼び出し元 パラメータ
スタティック ダイナミック
スタティック 不可
ダイナミック 不可

ダイナミック変数 A または B のフォーマットは一致する必要があります。

値渡し(結果)

呼び出し元 パラメータ
スタティック ダイナミック
スタティック
ダイナミック

注意:
スタティック/ダイナミック定義またはダイナミック/スタティック定義を使用する場合、割り当てのデータ転送規則によって値が切り捨てられることがあります。

例 1

** Example 'DYNAMX02': Dynamic variables (as parameters)                
************************************************************************
DEFINE DATA LOCAL                                                       
1 #MYTEXT (A) DYNAMIC                                                   
END-DEFINE                                                              
*                                                                       
#MYTEXT := '123456'      /* extended to 6 bytes, *LENGTH(#MYTEXT) = 6   
*                                                                       
CALLNAT 'DYNAMX03' USING #MYTEXT                                        
*                                                                       
WRITE *LENGTH(#MYTEXT)          /* *LENGTH(#MYTEXT) = 8                 
*                                                                       
END                                                                  

サブプログラム DYNAMX03

** Example 'DYNAMX03': Dynamic variables (as parameters)                
************************************************************************
DEFINE DATA PARAMETER                                                   
1 #MYPARM (A) DYNAMIC  BY VALUE RESULT                                  
END-DEFINE                                                              
*                                                                       
WRITE *LENGTH(#MYPARM)                  /* *LENGTH(#MYPARM) = 6         
#MYPARM := '1234567'                    /* *LENGTH(#MYPARM) = 7         
#MYPARM := '12345678'                   /* *LENGTH(#MYPARM) = 8         
EXPAND DYNAMIC VARIABLE #MYPARM TO 10   /* 10 bytes are allocated       
*                                                                       
WRITE *LENGTH(#MYPARM)                  /* *LENGTH(#MYPARM) = 8         
*                                                                       
/* content of #MYPARM is moved back to #MYTEXT                          
/* used length of #MYTEXT = 8                                           
*                                                                       
END                                                                    

例 2:

** Example 'DYNAMX04': Dynamic variables (as parameters)                
************************************************************************
DEFINE DATA LOCAL                                                       
1 #MYTEXT (A) DYNAMIC                                                   
END-DEFINE                                                              
*                                                                       
#MYTEXT := '123456'      /* extended to 6 bytes, *LENGTH(#MYTEXT) = 6   
*                                                                       
CALLNAT 'DYNAMX05' USING #MYTEXT                                        
*                                                                       
WRITE *LENGTH(#MYTEXT)          /* *LENGTH(#MYTEXT) = 8                 
                                /* at least 10 bytes are                
                                /* allocated (extended in DYNAMX05)     
*                                                                       
END                                                               

サブプログラム DYNAMX05

** Example 'DYNAMX05': Dynamic variables (as parameters)                
************************************************************************
DEFINE DATA PARAMETER                                                   
1 #MYPARM (A) DYNAMIC                                                   
END-DEFINE                                                              
*                                                                       
WRITE *LENGTH(#MYPARM)                  /* *LENGTH(#MYPARM) = 6         
#MYPARM := '1234567'                    /* *LENGTH(#MYPARM) = 7         
#MYPARM := '12345678'                   /* *LENGTH(#MYPARM) = 8         
EXPAND DYNAMIC VARIABLE #MYPARM TO 10   /* 10 bytes are allocated       
*                                                                       
WRITE *LENGTH(#MYPARM)                  /* *LENGTH(#MYPARM) = 8         
*                                                                       
END                                                                    

3GL プログラムに対する CALL

CALL ステートメントで INTERFACE4 オプションを使用すると、ダイナミック変数およびラージ変数を有効に使用できます。このオプションを使用すると、異なるパラメータ構造を使用した 3GL プログラムとのインターフェイスになります。

このインターフェイスを使用するには 3GL プログラムを少々変更する必要がありますが、従来の FINFO 構造体と比較して、以下のような大きな利点があります。

  • 渡すパラメータの数は無制限です(従来の制限:40)。

  • パラメータのデータサイズは無制限です(従来の制限:パラメータ当たり 64 KB)。

  • 配列情報を含め、完全なパラメータ情報を 3GL プログラムに渡すことができます。パラメータデータへの安全なアクセスを可能にする、エクスポートされたファンクションが用意されています(従来は Natural 内部でメモリを上書きしないよう注意する必要がありました)。

FINFO 構造体の詳細については、CALL INTERFACE4 ステートメントの説明を参照してください。

ダイナミックパラメータを使用して 3GL プログラムを呼び出す前に、必要なバッファサイズを必ず割り当てるようにしてください。これは、EXPAND ステートメントを使用すると明示的に実行できます。

バッファを初期化する必要がある場合、MOVE ALL UNTIL ステートメントを使用することにより、ダイナミック変数を初期値および必要なサイズに設定できます。Natural には、3GL プログラムでダイナミックパラメータに関する情報を取得し、パラメータデータを返すときに長さを変更できるようにする、一連のファンクションが用意されています。

例:

MOVE ALL ' ' TO  #MYDYNTEXT1 UNTIL 10000
  /* a buffer of length 10000 is allocated
  /* #MYDYNTEXT1 is initialized with blanks
  /* and *LENGTH(#MYDYNTEXT1) = 10000
CALL INTERFACE4  'MYPROG'  USING  #MYDYNTEXT1
WRITE *LENGTH(#MYDYNTEXT1)
  /* *LENGTH(#MYDYNTEXT1) may have changed in the 3GL program

詳細については、『ステートメント』ドキュメントに記載されている、CALL ステートメントの説明を参照してください。

ラージ変数およびダイナミック変数によるワークファイルへのアクセス

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

PORTABLE および UNFORMATTED

2 つのワークファイルタイプ PORTABLEUNFORMATTED を使用して、ラージ変数およびダイナミック変数をワークファイルに書き込んだりワークファイルから読み取ったりできます。これらのタイプには、ダイナミック変数に対するサイズ制限がありません。ただし、ラージ変数は最大フィールド/レコード長の 32766 バイトを超えることはできません。

ワークファイルタイプ PORTABLE の場合は、フィールド情報がワークファイル内に保存されます。レコード内のフィールドサイズが現在のサイズと異なる場合は、ダイナミック変数は READ 中にサイズ変更されます。

ワークファイルタイプ UNFORMATTED は、例えば、データベースから読み込んだビデオを、他のユーティリティで再生可能なファイルに直接格納する場合などに使用できます。WRITE WORK ステートメントでは、フィールドはそのバイト長でファイルに書き込まれます。すべてのデータタイプ(DYNAMIC であるかどうかに関わらず)は同じように扱われます。構造情報は挿入されません。Natural ではバッファリングメカニズムを使用するので、データが完全に書き込まれるのは CLOSE WORK の後のみであることが予測できます。これは、Natural の稼働中にファイルが別のユーティリティで処理される場合に特に重要です。

READ WORK ステートメントでは、固定長のフィールドはその全体の長さで読み込まれます。ファイルの終わりに到達すると、現在のフィールドの残りは空白で埋められます。次のフィールドは変更されません。データタイプが DYNAMIC の場合、ファイルが 1073741824 バイトを超えない限り、ファイルの残りの部分がすべて読み込まれます。ファイルの終わりに到達すると、残りのフィールド(変数)は変更されないまま維持されます(通常の Natural の動作)。

ASCII、ASCII-COMPRESSED、および SAG

ワークファイルタイプ ASCII、ASCII-COMPRESSED、および SAG(バイナリ)では、ダイナミック変数は処理できず、エラーが生成されます。これらのワークファイルタイプに対するラージ変数では、フィールド/レコードの最大長である 32766 バイトを超えない限り、問題は発生しません。

TRANSFER および ENTIRE CONNECTION に対する特別な条件

READ WORK FILE ステートメントとともに使用すると、ワークファイルタイプ TRANSFER はダイナミック変数を処理できます。この場合、ダイナミック変数に対するサイズ制限はありません。ワークファイルタイプ ENTIRE CONNECTION では、ダイナミック変数は処理できません。ただし、これらは両方とも、最長フィールド/レコードである 1073741824 バイトのラージ変数を処理できます。

WRITE WORK FILE ステートメントとともに使用すると、ワークファイルタイプ TRANSFER は、フィールド/レコードの最大長が 32766 バイトのダイナミック変数を処理できます。ワークファイルタイプ ENTIRE CONNECTION では、ダイナミック変数は処理できません。ただし、これらは両方とも、最長フィールド/レコードである 1073741824 バイトのラージ変数を処理できます。

可変長の列に対する DDM の生成および編集

データタイプに応じて、対応するデータベースフォーマット A または フォーマット B が生成されます。データベースのデータタイプが VARCHAR の場合、Natural の列の長さは DBMS で定義されているデータタイプの最大長に設定されます。データタイプが非常に大きい場合、フィールド長の位置にキーワード DYNAMIC が生成されます。

すべての可変長の列に対し、LINDICATOR フィールド L@<column-name> が生成されます。データベースのデータタイプが VARCHAR の場合、フォーマット/長さが I2 の LINDICATOR フィールドが生成されます。大きなデータタイプ(下表参照)の場合、フォーマット/長さは I4 になります。

データベースにアクセスするときには、LINDICATOR を操作することにより、定義済みのバッファ長(または *LENGTH)に関係なく、読み込むフィールドの長さを取得したり、書き込むフィールドの長さを設定したりできます。通常は、取得処理の後、対応するインジケータの長さに *LENGTH は設定されます。

DDM の例:

  T  L  Name                      F   Leng        S   D   Remark
     :
     1  L@PICTURE1                I   4                                     /* length indicator
     1  PICTURE1                  B   DYNAMIC             IMAGE
     1  N@PICTURE1                I   2                                     /* NULL indicator
     1  L@TEXT1                   I   4                                     /* length indicator
     1  TEXT1                     A   DYNAMIC             TEXT
     1  N@TEXT1                   I   2                                     /* NULL indicator
     1  L@DESCRIPTION             I   2                                     /* length indicator
     1  DESCRIPTION               A   1000                VARCHAR(1000) 
     :
     :
  ~~~~~~~~~~~~~~~~~~~~~~Extended Attributes~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/* concerning PICTURE1
   Header               :    ---
   Edit Mask            :    ---
   Remarks              :   IMAGE

生成されるフォーマットは可変長のフォーマットです。Natural プログラマは、定義を DYNAMIC から固定長に変更したり(拡張フィールド編集)、データタイプ VARCHAR に対応する DDM のフィールド定義をマルチプルバリューフィールド(従来の生成タイプ)にしたりできます。

例:

  T  L  Name                  F   Leng          S   D   Remark
     :
     1  L@PICTURE1            I   4                                         /* length indicator
     1  PICTURE1              B   1000000000            IMAGE
     1  N@PICTURE1            I   2                                         /* NULL indicator
     1  L@TEXT1               I   4                                         /* length indicator
     1  TEXT1                 A   5000                  TEXT
     1  N@TEXT1               I   2                                         /* NULL indicator
     1  L@DESCRIPTION         I   2                                         /* length indicator
  M  1  DESCRIPTION           A   100                   VARCHAR(1000) 
       :
       :
  ~~~~~~~~~~~~~~~~~~~~Extended Attributes~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/* concerning PICTURE1
   Header             :    ---
   Edit Mask          :    ---
   Remarks            :   IMAGE

データベースのラージオブジェクトへのアクセス

データベースのラージオブジェクト(CLOB または BLOB)にアクセスするには、対応する英数字、Unicode、またはバイナリの各ラージフィールドの DDM を使用する必要があります。フィールドが固定長で定義され、データベースのラージオブジェクトがこのフィールドに収まらない場合、ラージオブジェクトは切り捨てられます。データベースオブジェクトの明確な長さがわからない場合、ダイナミックフィールドを使用します。そのオブジェクトを保持するために必要な再割り当てが行われます。切り捨ては行われません。

プログラム例:

DEFINE DATA LOCAL

1 person VIEW OF xyz-person
  2 last_name
  2 first_name_1
  2 L@PICTURE1                   /* I4 length indicator for PICTURE1
  2 PICTURE1                     /* defined as dynamic in the DDM
  2 TEXT1                        /* defined as non-dynamic in the DDM

END-DEFINE

SELECT * INTO VIEW person FROM xyz-person                   /* PICTURE1 will be read completely
                             WHERE last_name = 'SMITH'      /* TEXT1 will be truncated to fixed length 5000  

   WRITE  'length of PICTURE1: '  L@PICTURE1                /* the L-INDICATOR will contain the length 
                                                            /* of PICTURE1 (= *LENGTH(PICTURE1)
   /* do something with PICTURE1 and TEXT1

   L@PICTURE1  :=  100000       
   INSERT INTO xyz-person  (*) VALUES (VIEW person)         /* only the first 100000 Bytes of PICTURE1
                                                            /* are inserted
END-SELECT 

ビューのフォーマット/長さの定義が省略されている場合、DDM の定義が使用されます。レポーティングモードでは、対応する DDM フィールドが DYNAMIC で定義されている場合、任意の長さを指定できます。ダイナミックフィールドは、固定長のバッファにマップされます。この逆は実行できません。 

DDM のフォーマット/長さの定義 ビューのフォーマット/長さの定義  
(An) - 有効
(An) 有効
  (Am) レポーティングモードでのみ有効
(A) DYNAMIC 無効
(A) DYNAMIC  - 有効
(A) DYNAMIC 有効
(An) レポーティングモードでのみ有効
(Am / i : j) レポーティングモードでのみ有効

フォーマット B の変数も同様です。

SQL ステートメント内の LINDICATOR 節のパラメータ

LINDICATOR フィールドを I2 フィールドとして定義すると、対応する列の送受信には SQL データタイプ VARCHAR が使用されます。LINDICATOR ホスト変数を I4 として指定する場合、ラージオブジェクトデータタイプ(CLOB/BLOB)を使用します。

フィールドを DYNAMIC として定義すると、列は内部ループでは実際の長さまで読み取られます。LINDICATOR フィールドとシステム変数 *LENGTH がこの長さに設定されます。固定長フィールドの場合、定義した長さまで列が読み込まれます。いずれの場合も、フィールドは LINDICATOR フィールドで定義した値まで書き込まれます。

ダイナミック変数の使用によるパフォーマンスへの影響

ダイナミック変数を少量ずつ複数回にわたって拡張する場合(バイト単位など)、必要なストレージの(おおよその)上限がわかっているときは、拡張を繰り返すのではなく EXPAND ステートメントを使用します。これにより、必要なストレージを調整するための余分なオーバーヘッドを回避できます。

ダイナミック変数が不要になった場合、特に *LENGTH の値が大きい変数の場合は、REDUCE ステートメントまたは RESIZE ステートメントを使用します。これにより、Natural でストレージを解放または再利用できます。したがって、全体的なパフォーマンスが向上します。

ダイナミック変数に割り当てられているメモリの量は、REDUCE DYNAMIC VARIABLE ステートメントを使用すると減らすことができます。変数に特定の長さを(再)割り当てするには、EXPAND ステートメントを使用できます(変数を初期化する場合は、MOVE ALL UNTIL ステートメントを使用します)。

例:

** Example 'DYNAMX06': Dynamic variables (allocated memory)             
************************************************************************
DEFINE DATA LOCAL                                                       
1 #MYDYNTEXT1  (A)  DYNAMIC                                             
1 #LEN         (I4)                                                     
END-DEFINE                                                              
*                                                                       
#MYDYNTEXT1 := 'a'     /* used length is 1, value is 'a'                
                       /* allocated size is still 1                     
WRITE *LENGTH(#MYDYNTEXT1)                                              
*                                                                       
EXPAND DYNAMIC VARIABLE  #MYDYNTEXT1 TO 100                             
                       /* used length is still 1, value is 'a'          
                       /* allocated size is 100                         
*                                                                       
CALLNAT 'DYNAMX05' USING #MYDYNTEXT1                                    
WRITE *LENGTH(#MYDYNTEXT1)                                              
                       /* used length and allocated size                
                       /* may have changed in the subprogram            
*                                                                       
#LEN := *LENGTH(#MYDYNTEXT1)                                            
REDUCE DYNAMIC VARIABLE  #MYDYNTEXT1  TO  #LEN                          
                       /* if allocated size is greater than used length,
                       /* the unused memory is released                 
*                                                                       
REDUCE DYNAMIC VARIABLE  #MYDYNTEXT1  TO  0                             
WRITE *LENGTH(#MYDYNTEXT1)                                              
                       /* free allocated memory for dynamic variable    
END

ルール:

  • ダイナミックオペランドは、適切な場所で使用します。

  • メモリ使用量の上限がわかっている場合は、EXPAND ステートメントを使用します。

  • ダイナミックオペランドが不要になった場合は、REDUCE ステートメントを使用します。

ダイナミック変数の出力

ダイナミック変数は、以下のような出力ステートメント内で使用できます。

ステートメント
DISPLAY これらのステートメントでは、セッションパラメータの AL(出力に対する英数字長)またはEM(編集マスク)を使用して、ダイナミック変数の入出力フォーマットを設定する必要があります。
WRITE
INPUT
REINPUT --
PRINT PRINT ステートメントの出力はフォーマットが指定されていないため、AL および EM パラメータを使用して、PRINT ステートメント内のダイナミック変数の出力フォーマットを設定する必要はありません。したがって、これらのパラメータは無視されます。

ダイナミック X-array

ダイナミック X-array の割り当てでは、最初にオカレンス数を指定し、後でそのオカレンス数を拡張できます。

例:

DEFINE DATA LOCAL
1 #X-ARRAY(A/1:*)  DYNAMIC
END-DEFINE
*
EXPAND  ARRAY   #X-ARRAY TO (1:10)  /* Current boundaries (1:10) 
#X-ARRAY(*) := 'ABC'
EXPAND  ARRAY   #X-ARRAY TO (1:20)  /* Current boundaries (1:20)
#X-ARRAY(11:20) := 'DEF'