このドキュメントでは、次のトピックについて説明します。
通常、次の規則が適用されます。
ダイナミック英数字フィールドは、英数字フィールドを使用できる場所であればどこにでも使用できます。
ダイナミックバイナリフィールドは、バイナリフィールドを使用できる場所であればどこにでも使用できます。
ダイナミック Unicode フィールドは、Unicode フィールドを使用できる場所であればどこにでも使用できます。
ダイナミック変数は、SORT
ステートメント内では使用できません。 ダイナミック変数を DISPLAY
、WRITE
、PRINT
、REINPUT
、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)
|
INTO 節内のパラメータ |
SEND METHOD |
operand3 (AD=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
は実行できます。 ダイナミック変数の使用長(*LENGTH
)を超えるサブストリングを参照すると、MOVE SUBSTR
はランタイムエラーになります。 *LENGTH + 1
を超えるサブストリングの位置を参照すると、ダイナミック変数の内容に未定義のギャップが生じるため、MOVE TO SUBSTR
はランタイムエラーになります。 ターゲットオペランドを 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
注意:
非ダイナミック変数の場合、エラーメッセージが返されます。
ダイナミック変数を使用して読み取り専用の操作(比較など)を行う場合、通常は現在の使用長を使用して実行されます。 読み取り操作(変更なし)で使用される場合、ダイナミック変数はスタティック変数と同様に処理されます。
例:
IF #MYDYNTEXT1 = #MYDYNTEXT2 OR #MYDYNTEXT1 = "**" THEN ... IF #MYDYNTEXT1 < #MYDYNTEXT2 OR #MYDYNTEXT1 < "**" THEN ... IF #MYDYNTEXT1 > #MYDYNTEXT2 OR #MYDYNTEXT1 > "**" THEN ...
英数字変数および Unicode 変数の末尾の空白またはバイナリ変数の先頭のバイナリゼロは、スタティック変数とダイナミック変数で同様に処理されます。 例えば、AA
および空白が続く AA
を値として持つ英数字変数は同一とみなされ、H'00003031'
および 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
ブレイクコントロールフィールドの元の値との比較は、左から右に向かって 1 ポジションずつ実行されます。 ダイナミック変数の元の値と新しい値で長さが異なる場合、比較するために長さが短い方の値の右側に空白(ダイナミック英数字変数またはダイナミック Unicode 変数の場合)またはバイナリゼロ(バイナリ値の場合)が追加されます。
英数字または Unicode のブレイクコントロールフィールドの場合、比較において末尾の空白は意味を持ちません。つまり、末尾の空白は値の変更を意味しないため、ブレイクは発生しません。
バイナリのブレイクコントロールフィールドの場合、比較において末尾のバイナリゼロは意味を持ちません。つまり、末尾のバイナリゼロは値の変更を意味しないため、ブレイクは発生しません。
ダイナミック変数は、呼び出されたプログラムオブジェクト(CALLNAT
、PERFORM
)へのパラメータとして渡すことができます。 ダイナミック変数の値スペースは連続しているので、参照渡しが可能です。 値渡しを使用すると、呼び出し元の変数定義がソースオペランドとして割り当てられ、パラメータ定義が応答先オペランドとして割り当てられます。
また、値渡しの結果では、逆方向にデータが移動します。
参照渡しを使用する場合、変数定義およびパラメータ定義は DYNAMIC
である必要があります。 そのうちの 1 つだけが DYNAMIC
の場合、ランタイムエラーが発生します。 値渡し(結果)の場合、すべての組み合わせを使用できます。 以下の表に、有効な組み合わせを示します。
呼び出し元 | パラメータ | |
---|---|---|
スタティック | ダイナミック | |
スタティック | ○ | × |
ダイナミック | × | ○ |
ダイナミック変数 A または B のフォーマットは一致する必要があります。
呼び出し元 | パラメータ | |
---|---|---|
スタティック | ダイナミック | |
スタティック | ○ | ○ |
ダイナミック | ○ | ○ |
注意:
スタティック/ダイナミック定義またはダイナミック/スタティック定義を使用する場合、割り当てのデータ転送規則によって値が切り捨てられることがあります。
** 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
** 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
CALL
ステートメントで INTERFACE4
オプションを使用すると、ダイナミック変数およびラージ変数を有効に使用できます。 このオプションを使用すると、異なるパラメータ構造を使用した 3GL プログラムとのインターフェイスになります。
ダイナミックパラメータを使用して 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
ステートメントの説明を参照してください。
253 以下の長さの固定長の変数と 253 を超える長さのラージ変数の扱いは同じです。
ダイナミック変数は、WRITE WORK FILE
ステートメントの実行時に、その実際の長さ(つまり、この変数に対するシステム変数 *LENGTH
の値)でデータが書き込まれます。 同じ WRITE WORK FILE
ステートメントであっても実行するたびに長さが異なるため、キーワード VARIABLE
を指定する必要があります。
タイプ FORMATTED
のワークファイルを読み込む場合、ダイナミック変数には、READ WORK FILE
ステートメントの実行時に、その実際の長さ(つまり、この変数に対するシステム変数 *LENGTH
の値)でデータが読み込まれます。 ダイナミック変数が現在のレコードの残りのデータより長い場合、空白(英数字フィールドおよび Unicode フィールドの場合)またはバイナリゼロ(バイナリフィールドの場合)が埋め込まれます。
タイプ UNFORMATTED
のワークファイルを読み込む場合、ダイナミック変数にはワークファイルの残りが読み込まれます。 サイズは適切に調整され、この変数に対するシステム変数 *LENGTH
の値に反映されます。
ダイナミック変数を少量ずつ複数回にわたって拡張する場合(バイト単位など)、必要なストレージの(おおよその)上限がわかっているときは、拡張を繰り返すのではなく 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 の割り当てでは、最初にオカレンス数を指定し、後でそのオカレンス数を拡張できます。
例:
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'