ProSortの実行手順
本章では、ProSortの実行手順について説明します。
1. SORT演算、COPY演算
ProSortでSORTおよびCOPY演算を実行する手順は以下のとおりです。
以下は、SORTおよびCOPY演算の実行手順についての説明です。
-
SKIPREC
SORT演算を実行する前にスキップするレコード数を指定するオプションです。指定した値以後のレコードから入力できます。
以下は、6番目のレコードからの入力を取り込んで次のプロセスを実行する例です。
SKIPREC = 5
-
特定条件のレコードのみを含むか、特定条件のレコードを除外します。
オプション 説明 INCLUDE
特定条件のレコードのみ含め、それ以外のレコードは除外します。
OMIT
特定条件のレコードは除外し、残りのレコードのみ含めます。
特定条件は、関係式を論理演算子で組み合わせて論理式で構成します。関係式は比較、文字列比較、ビット演算、日付比較に区分できます。
関係式 説明 比較
フィールドとフィールド間、またはフィールドと定数間を比較します。
文字列比較
文字列を比較します。
ビット演算
1つまたは2つの2進数をビット単位で演算します。
日付比較
日付を比較します。
以下の関係式は、レコードp1の位置でm1の長さを持ち、f1の形式を持つフィールドと、p2の位置でm2の長さを持ち、f2の形式を持つフィールドを比較する条件を示します。
p1, m1, f1, {EQ|NE|GT|GE|LT|LE}, p2, m2, f2適用可能な演算子には、EQ、NE、GT、GE、LT、LEがあります。
演算子 説明 EQ
フィールドが一致するか検査します。
NE
フィールドが一致しないか検査します。
GT
左側が右側より大きいか検査します。
GE
左側が右側より大きいか等しいかを検査します。
LT
左側が右側より小さいか検査します。
LE
左側が右側より小さいか等しいかを検査します。
以下は、5~12バイトの浮動小数点の数字が13~20バイトの浮動小数点の数字より大きいか、105~108バイトの浮動小数点の数字が定数の1000より小さいか等しい条件を持つレコードを含む例です。
INCLUDE COND=(5,8,GT,13,8,|,105,4,LE,1000),FORMAT=CSF
-
STOPAFT
1、2項の手順を実行した後、レコードの数が指定した数を超えないまでレコードを入力することができます。
以下は、1000個のレコードまでを次のプロセスに転送する例です。
STOPAFT = 1000
-
入力されたレコードを付与された形式に変換します。入力されたレコードはINRECで指定したフィールドに変換され、新しいレコードに変換されます。この際、フィールドは定数または(p,m)の形式で入力されたレコードの一部、(p,m,f,to)で入力されたレコードの形式を変換したフィールドなどで構成します。
INRECを実行した後の処理はINRECで変換されたレコードを基準に行われます。
以下は、入力レコードの10~12バイト、20~27バイト、33~43バイト、5バイトを新規レコードとして生成する例です。
INREC FIELDS=(10,3,20,8,33,11,5,1)
以下は、入力レコードの20~23バイト、12~14バイトを新規レコードに変換する例です。
INREC FIELDS=(20,4,12,3) SORT FIELDS=(1,4,D,5,3,D),FORMAT=CH
-
SORT(SUM)、COPY
入力されたレコードを付与されたキー情報でソートします。ソートに使われるキーはフィールドで定義され、各フィールドはp、m、f、sの形で定義されます。
フィールド・タイプ 説明 p
レコードの位置であり、バイトとビット単位で定義します。
-
pが4の場合:4バイトからフィールドが始まります。
-
pが4.2の場合:4バイトの2番目のビットから始まります。
m
フィールド長であり、バイトとビット単位で定義します。
f
形式を定義します。
s
昇順ソートまたは降順ソートを定義します。
INRECでレコードが変換された場合には変換されたレコードを基準にして位置が決まります。EQUALSオプションを宣言すると、同一キーのレコードが本来の順序どおり表示されることを保証するstable sortで動作します。
SUMオプションが使用された場合は、同一キーを持つレコードに指定されたフィールド値の合計を求めます。指定されたフィールドがない場合には、重複するキーを除去する機能のみを実行します。SKIPREC、STOPAFTオプションがある場合は、以前のプロセスで実行します。
以下は、2~6バイトの浮動小数点の数字のキーを昇順でソートする例です。
SORT FIELDS=(2,5,FS,A)
以下は、7025~2028バイトのZD(zoned decimal fields、ゾーン10進数フィールド)を昇順で、5048~5055バイトのZDを昇順でソートする例です。
SORT FILEDS=(7025,4,ZD,A,5048,8,ZD,A),EQUALS
以下は、ソートせずにコピーする例です。
SORT FILEDS=(COPY)
以下は、ソートが実行された結果において、同一キーを持つレコードに対して、21~28バイトのPD(packed decimal fields)と11~14バイトのFIフィールドの合計値を求める例です。
SUM FIELDS=(21,8,PD,11,4,FI)
-
-
OUTREC
ソートされたレコードを付与された形式に変換します。INRECと同様に使用します。ただし、INRECによりレコードが既に変換された場合には、変換されたレコードを基準にして位置が決まります。
詳細については、SORT演算、COPY演算の4項 INRECを参照してください。
-
OUTFIL
OUTFILの詳細については、OUTFIL演算を参照してください。
2. MERGE演算
MERGEは、ソートされた複数の入力ファイルをマージし、新しくソートされたレコードを出力します。MERGEはSKIPREC、STOPAFTオプションを除いてはSORTと同じ手順で演算を実行します。
ProSortでMERGE演算を実行する手順は以下のとおりです。
以下は、MERGE演算の実行手順についての説明です。
-
INCLUDE、OMIT
SORT演算、COPY演算の2項 INCLUDE、OMITを参照します。
-
INREC
SORT演算、COPY演算の4項 INRECを参照します。
-
MERGE(SUM)
付与されたキー情報を基に複数の入力ファイルをマージします。正常な処理結果を保証するには、入力ファイルのキーがソートされていなければなりません。フィールドおよびオプションはSORTと同様に定義されます。
以下は、25~28バイトのZD、48~55バイトのZDをキーに定義し、昇順で入力ファイルをマージする例です。
MERGE FIELDS=(25,4,A,48,8,A),FORMAT=ZD
-
OUTREC
MERGE演算が実行されたレコードを付与された形式に変換します。INRECと同様に使われます。ただし、INRECによりレコードが既に変換された場合には、変換されたレコードを基準にして位置が決まります。
詳細については、SORT演算、COPY演算の4項 INRECを参照してください。
-
OUTFIL
OUTFILの詳細については、 OUTFIL演算を参照してください。
3. OUTFIL演算
OUTFILは、SORT、MERGE、COPY演算の結果出力されたレコードを様々な条件で再出力します。
ProSortでOUTFIL演算を実行する手順は以下のとおりです。
以下は、OUTFIL演算の実行手順についての説明です。
-
STARTREC
出力レコードのうち指定した数を前方から除外します。
-
ENDREC
出力レコードのうち指定した数を後方から除外します。
-
INCLUDE、OMIT、SAVE
特定条件のレコードを除外するか含めます。SAVEオプションがある場合は、自分を除いたすべてのOUTFILで除外されていない条件のレコードのみ含めます。
以下は、8 ~ 13バイトの文字列フィールドがACCTNGのレコードはファイルGP1に出力し、8 ~ 13バイトの文字列フィールドがDVPMNTのレコードはファイルGP2に出力する例です。
OUTFIL INCLUDE=(8,6,CH,EQ,C’ACCTNG’),FNAMES=GP1 OUTFIL INCLUDE=(8,6,CH,EQ,C’DVPMNT’),FNAMES=GP2 OUTFIL SAVE,FNAMES=NOT1OR2
-
OUTREC
出力レコードを付与された形式に変換します。
4. ユーザー出口関数
ユーザーはProSortのスクリプトまたはProSort APIを利用して関数を登録することができます。このような関数をユーザー出口関数(User Exit Function)といいます。SORT、MERGE、COPY演算を実行するとき、この関数を利用してレコードを挿入、変換、削除できます。
ユーザー出口関数は以前の段階で渡されたレコードを編集して次の段階に渡します。最後のレコード以降はNULLが関数に渡されます。
SORT、MERGE、COPY演算はProSort APIを使ってレコードを直接入力する場合のみ動作し、ファイルを使ってレコードを入力する場合には動作しません。
ユーザー出口関数の詳細は以下のとおりです。
-
プロトタイプ
int user_exit_func (void *rec_addr, int rec_len, int input_no, void **ret_rec_addr, int *ret_rec_len); -
パラメータ
パラメータ 用途 説明 *rec_addr
入力
以前の段階で渡されたレコード・アドレスのポインターです。
rec_len
入力
以前の段階で渡されたレコードの長さです。
input_no
入力
SORTINの番号であり、MERGE演算のユーザー出口関数E32でのみ使用できます。
**ret_rec_addr
出力
変換または挿入されたレコードのアドレスであり、ポインターの形で渡されます。
*ret_rec_len
出力
変換または挿入されたレコードの長さであり、ポインターの形で渡されます。
-
戻り値
戻り値 説明 0
No Action。レコードを変換せずに次の段階を実行します。
**ret_rec_addr、*ret_rec_lenパラメータに入力された*rec_addr、rec_lenのアドレスをそのまま渡します。
0
Record Altered。変換されたレコードで次の段階を実行します。
入力された*rec_addr、rec_len、input_noの情報を利用してレコードを変換した後、変換されたレコードのアドレスおよび長さを**ret_rec_addr、*ret_rec_lenパラメータに渡します。
4
Delete Record。レコードを削除します。
削除されたレコードは次の段階に渡されません。
8
Do Not Return。次のレコードからユーザー出口関数を実行しません。
12
Insert Record。返却されたレコードを挿入します。
挿入されたレコードは次の段階に即刻転送されず、再度ユーザー出口関数を実行して変換されるか削除されます。既存レコードは挿入されたレコードが次のレコードに転送された後、再度処理されます。
16
Terminate Prosort。ProSortを終了します。
実行中の作業をすべて終了します。
|
4.1. ユーザー出口関数を含むSORT演算、COPY演算
ProSortでユーザー出口関数と一緒にSORTおよびCOPY演算を実行する手順は以下のとおりです。
SORTおよびCOPY演算ではユーザー出口関数E15を登録して入力されたレコードを編集できます。ユーザー出口関数E35は、OUREC実行後のレコードから編集できます。
4.2. ユーザー出口関数を含むMERGE演算
ProSortでユーザー出口関数と一緒にMERGE演算を実行する手順は以下のとおりです。
MERGE演算ではユーザー出口関数E32を登録して入力されたレコードを編集できます。ユーザー出口関数E35は、OURECを実行した後のレコードから編集できます。
4.3. ユーザー出口関数の例
本節では、ユーザー出口関数を使用して関数を機能別に実行する例を記述します。
全レコードの転送
以下は、すべてのレコードをそのまま転送する関数の例です。
static int
exit_none(const void *rec_addr,
const int rec_len,
int file_no,
void **ret_rec_addr,
int *ret_rec_len)
{
if (rec_addr == NULL)
return 8; /* do not return */
*ret_rec_addr = (void *) rec_addr;
*ret_rec_len = rec_len;
return 0; /* no action */
}
全レコードの削除
以下は、すべてのレコードを削除する関数の例です。
static int
exit_delete(const void *rec_addr,
const int rec_len,
int file_no,
void **ret_rec_addr,
int *ret_rec_len)
{
if (rec_addr == NULL)
return 8; /* do not return */
return 4;
}
全レコードの挿入
以下は、すべてのレコードをコピーして挿入する関数の例です。レコードのa、b、cが以前の段階から渡されるとa、a、b、b、c、cの形で次の段階に転送されます。
static int
exit_insert(const void *rec_addr,
const int rec_len,
int file_no,
void **ret_rec_addr,
int *ret_rec_len)
{
static char buf[REC_LEN];
static int inserted = 0;
/* 挿入されたレコードは編集しません */
if (inserted) {
inserted = 0;
*ret_rec_addr = (void *) rec_addr;
*ret_rec_len = rec_len;
return 0; /* no action */
}
if (rec_addr == NULL)
return 8; /* do not return */
memcpy (buf, rec_addr, REC_LEN);
*ret_rec_addr = buf;
*ret_rec_len = rec_len;
inserted = 1;
return 12; /* insert record */
}
最後レコードの挿入
以下は、最後のレコード3個を追加挿入する関数の例です。レコードのa、b、cが以前の段階から渡されるとa、b、c、c、c、cの形で次の段階に転送されます。
static int
exit_insert_to_end(const void *rec_addr,
const int rec_len,
int file_no,
void **ret_rec_addr,
int *ret_rec_len)
{
static char buf[256];
static int buf_rec_len;
static insert_cnt = 0;
if (rec_addr != NULL) {
memcpy(buf, rec_addr, rec_len);
buf_rec_len = rec_len;
*ret_rec_addr = buf;
*ret_rec_len = buf_rec_len;
return 0; /* do not action */
}
if (insert_cnt >= 3) /* 3個までレコードを追加します */
return 8; /* do not return */
*ret_rec_addr = buf;
*ret_rec_len = buf_rec_len;
insert_cnt++;
return 12; /* レコードの挿入 */
}