C/400

15. C/400での SETLL & READE

RPGユーザーが C/400を学習すると SETLL & READECHAIN は C/400ではどのように
行うのか気になるところである。
一般に C言語では RPGの SETLL や CHAIN というものは無い。
C/400 においてもこれは同じことであるが、RPGに慣れ親しんでいる場合は同じことを C/400で
再現する方法を知りたいものである。
ここからは RPGでのこれらのレコード制御の命令を C/400で再現する方法を紹介しよう。
それらの方法は IBMの解説書にも RPGと対応した方法としては解説されていないのでこれが初めての
解説となるはずである。
これらの手法は EnterpriseServer の DB2エンジンに使用されている。

次の例は QTRFIL/LSHOHINS という4桁の品種コード別の論理ファイルを同じ品種コード='0001' だけを
SETLL & READE を行っている例である。

0001.00 #include <stdio.h>
0002.00 #include <stdlib.h>
0003.00 #include <string.h>
0004.00 #include <recio.h>
0005.00                                                                  
0006.00 #define TRUE         0                                           
0007.00 #define FALSE       -1                                           
0008.00 #define MAX_LEN 3000                                             
0009.00 #define MAX_KEY_LEN 256                                          
0010.00                                                                  
0011.00 void main(void){                                                 
0012.00     _RFILE *fp;                                                  
0013.00    _RIOFB_T *iofb;                                               
0014.00     char key[MAX_KEY_LEN];                                       
0015.00     unsigned int key_len;                                        
0016.00     char record[128];                                            
0017.00     int i;                                                       
0018.00     unsigned long rrn =0;                                        
0019.00                                                                  
0020.00     if((fp = _Ropen("QTRFIL/LSHOHNS", "rr+ blkrcd=Y")) == NULL){ 
0021.00        printf("cannot open\n"); return;                                
0022.00     }                                                                  
0023.00     memset(key, 0, sizeof(key));                                       
0024.00     strcpy(key, "0001");                                               
0025.00     key_len = 4;                                                       
0026.00     _Rlocate(fp, &key, key_len, __KEY_LT);  /*[ SETLL ]*/              
0027.00                                                                        
0028.00     /*[ 以下は READE による読み取り ]*/                                
0029.00   for(i=0; i< 99999; i++){/*for-loop*/ 
0030.00     if(i == 0)                                                         
0031.00       iofb = _Rreadk(fp, record,MAX_LEN, __KEY_NEXTUNQ, &key, key_len);
0032.00     else                                                               
0033.00       iofb = _Rreadk(fp, record,MAX_LEN, __KEY_NEXTEQ, &key, key_len); 
0034.00     if(iofb->num_bytes == EOF || iofb->rrn == rrn ||
0035.00              strncmp(iofb->key, key, key_len) != 0){
0036.00        break;                                                          
0037.00     }                                                                  
0038.00        printf("record = %s\n", record);                                
0039.00        rrn = iofb->rrn;
0040.00     }/*for-loop*/                                                      
0041.00     _Rclose(fp);                                                       
0042.00     getchar(); 
0043.00 }

まず _Rlocate(fp, &key, key_len, __KEY_LT); は指定したキーの位置をセットして
指定したキーより小さな位置にセットしているので、これが SETLL の役割 を果たしている。

次に _Rreadk で読み取るわけであるが、最初だけは __KEY_NEXTUNQ で読み取って
2回目以降は __KEY_NEXTEQ で読み取る。
注意しなければならないのは、READE を終えた後も実際は 物理的なレコードが存在している場合には
EOFはセットされない。
RPGの場合は READE で EOF標識が ON になるが C/400の場合に EOF が使えるのは物理的なファイルの
終わりのときだけである。
よって同じレコードが読み込まれていないかを RRN を記憶しておいて EOF の検出に利用している点に
注意されたし。