RPG

415. 超高速データ・ベースの読取りRPG

ここで紹介するTESTREAD というRPGプログラムは

①任意のデータ・ベースを読取る
②任意のレコード長を読取り警告エラーは出ない。
③超高速でデータ・ベースを読取る

という長所を兼ね備えたプログラムである。
大量のデータ・ペースも一瞬に読み取って処理することができる
スグレモノである。
1万レコードの読取りなどはホンの一瞬で終わるので
その速さに驚くかも知れない。
汎用的にどのデータ・ベースでも読取ることができる技術として米国で紹介されていたのを
少し改良したものである。

[TESTREADの実行画面]

                        C 関数による読取り  (TESTREAD)                       
                                                                             
 選択項目を入力して,実行キーを押してください。                              
                                                                             
 ファイル  . . . . . . . . . . .   SHOHIN         名前                       
   ライブラリー  . . . . . . . .     QTRFIL       名前 , *LIBL, *CURLIB      
 メンバー  . . . . . . . . . . .   *FIRST         名前 , *FIRST, *LAST, *ALL 


[コマンド: TESTREAD ]

ソースはこちらから

0001.00              CMD        PROMPT('C 関数による読取り ')                 
0002.00              PARM       KWD(FILE) TYPE(FILE) MAX(1) +                 
0003.00                           PROMPT(' ファイル ')                        
0004.00  FILE:       QUAL       TYPE(*NAME) LEN(10) MIN(1)                    
0005.00              QUAL       TYPE(*NAME) LEN(10) DFT(*LIBL) +              
0006.00                           SPCVAL((*LIBL) (*CURLIB '*CURLIB   ')) +    
0007.00                           EXPR(*YES) PROMPT(' ライブラリー ')         
0008.00              PARM       KWD(MEMBER) TYPE(*NAME) LEN(10) DFT(*FIRST) + 
0009.00                           SPCVAL((*FIRST) (*LAST) (*ALL)) +           
0010.00                           PROMPT(' メンバー ')   


                      

[コンパイル]

CRTCMD CMD(OBJLIB/TESTREAD) PGM(OJLIB/TESTREADCL) SRCFILE(R610SRC/QCMDSRC) AUT(*ALL)

[ CLP: TESTREADCL ]

ソースはこちらから

0001.00              PGM        PARM(&FILFILLIB &MBR)                              
0002.00 /*----------------------------------------------------------------------*/ 
0003.00 /*   TESTREADCL :  C 関数による読取り                                   */ 
0004.00 /*                                                                      */ 
0005.00 /*   2021/11/25  作成                                                   */ 
0006.00 /*----------------------------------------------------------------------*/ 
0007.00              DCL        VAR(&FILFILLIB) TYPE(*CHAR) LEN(20)                
0008.00              DCL        VAR(&FILE) TYPE(*CHAR) LEN(10)                     
0009.00              DCL        VAR(&FILLIB) TYPE(*CHAR) LEN(10)                   
0010.00              DCL        VAR(&MBR) TYPE(*CHAR) LEN(10)                      
0011.00              DCL        VAR(&MSG) TYPE(*CHAR) LEN(132)                     
0012.00              DCL        VAR(&STMMSG) TYPE(*CHAR) LEN(132)                  
0013.00              DCL        VAR(&MSGID) TYPE(*CHAR) LEN(7)                     
0014.00              DCL        VAR(&MSGF) TYPE(*CHAR) LEN(10)                     
0015.00              DCL        VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)                  
0016.00              DCL        VAR(&MSGKEY) TYPE(*CHAR) LEN(4)                    
0017.00              DCL        VAR(&MSGDTA) TYPE(*CHAR) LEN(132)                  
0018.00              DCL        VAR(&ERRDTA) TYPE(*CHAR) LEN(132)                  
0019.00              DCL        VAR(&TYPE) TYPE(*CHAR) LEN(1)                      
0020.00              DCL        VAR(&TOPGMQ) TYPE(*CHAR) LEN(10)                   
0021.00              DCL        VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) +                
0022.00                           VALUE('*ESCAPE   ')                              
0023.00              DCL        VAR(&ERR) TYPE(*CHAR) LEN(1)                       
0024.00              DCL        VAR(&NULL4) TYPE(*CHAR) LEN(4) +            
0025.00                           VALUE(X'00000000')                        
0026.00              DCL        VAR(&APIERR) TYPE(*CHAR) LEN(116) +         
0027.00                           VALUE(X'000074') /* 2 進数  */            
0028.00              MONMSG     MSGID(CPF9999) EXEC(GOTO CMDLBL(ERROR))     
0029.00                                                                     
0030.00 /*( 環境の取得 )*/                                                  
0031.00              RTVJOBA    TYPE(&TYPE)                                 
0032.00              IF         COND(&TYPE *EQ '0') THEN(DO) /*  バッチ  */ 
0033.00              CHGVAR     VAR(&TOPGMQ) VALUE('*SYSOPR   ')            
0034.00              ENDDO      /*  バッチ  */                              
0035.00              ELSE       CMD(DO) /*  対話式  */                      
0036.00              CHGVAR     VAR(&TOPGMQ) VALUE('*TOPGMQ   ')            
0037.00              ENDDO      /*  対話式  */                              
0038.00                                                                     
0039.00 /*( 入力パラメータの取得 )*/                                        
0040.00              CHGVAR     VAR(&FILE) VALUE(%SST(&FILFILLIB 01 10))    
0041.00              CHGVAR     VAR(&FILLIB) VALUE(%SST(&FILFILLIB 11 10))  
0042.00                                                                     
0043.00 /*( プログラムの実行 )*/                                            
0044.00              CALL       PGM(TEST.COM/TESTREAD) PARM(&FILE &FILLIB + 
0045.00                           &MBR &ERR &MSG)                           
0046.00              IF         COND(&ERR *EQ ' ') THEN(DO)                 
0047.00              CHGVAR     VAR(&MSGTYPE) VALUE('*DIAG     ')           
0048.00              ENDDO                                                     
0049.00              IF         COND(&MSG *NE ' ') THEN(DO)                    
0050.00              GOTO       SNDMSG                                         
0051.00              ENDDO                                                     
0052.00              RETURN                                                    
0053.00                                                                        
0054.00  ERROR:      RCVMSG     MSGTYPE(*LAST) RMV(*NO) KEYVAR(&MSGKEY) +      
0055.00                           MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) +  
0056.00                           MSGFLIB(&MSGFLIB)                            
0057.00              IF         COND(&MSGID *EQ 'CPF9999') THEN(DO)            
0058.00              CHGVAR     VAR(&ERRDTA) VALUE(&MSGDTA)                    
0059.00              RCVMSG     MSGTYPE(*PRV) MSGKEY(&MSGKEY) RMV(*NO) +       
0060.00                           MSG(&MSG) MSGDTA(&MSGDTA) MSGID(&MSGID) +    
0061.00                           MSGF(&MSGF) MSGFLIB(&MSGFLIB)                
0062.00              CHGVAR     VAR(&STMMSG) VALUE(' プログラム ' *CAT +       
0063.00                           %SST(&ERRDTA 8 10) *TCAT +                   
0064.00                           ' のステートメント ' *CAT %SST(&ERRDTA +     
0065.00                           24 4) *CAT ' で次のエラーが発生しました。 ') 
0066.00              SNDPGMMSG  MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&STMMSG) + 
0067.00                           TOMSGQ(&TOPGMQ) MSGTYPE(*DIAG)               
0068.00              ENDDO                                                     
0069.00  SNDMSG:     IF         COND(&MSGID *EQ ' ') THEN(DO)                  
0070.00              SNDPGMMSG  MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) +    
0071.00                           TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE)            
0072.00              MONMSG     MSGID(CPF2400) EXEC(RETURN)          
0073.00              ENDDO                                           
0074.00              ELSE       CMD(DO)                              
0075.00              SNDPGMMSG  MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 
0076.00                           MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) +  
0077.00                           MSGTYPE(&MSGTYPE)                  
0078.00              MONMSG     MSGID(CPF2400) EXEC(RETURN)          
0079.00              ENDDO                                           
0080.00              ENDPGM     


                                      

[コンパイル]

CRTCLPGM PGM(OBJLIB/TESTREADCL) SRCFILE(MYSRCLIB/QCLSRC) OPTION(*SRCDG) AUT(*ALL)

[解説]

コマンド入力されたファイル名、ライブラリー名とメンバー名をプログラム: TESTREAD に渡して
実行している。

[ RPG : TESTREAD ]

ソースはこちらから

0001.00 H DFTNAME(TESTREAD) DATEDIT(*YMD/)                                     
0002.00 F********** C 関数による読取り ****************************************
0003.00 F*                                                                     
0004.00 F**********************************************************************
0005.00                                                                        
0006.00  * CRTBNDRPG  OBJ(OBJLIB/TESTREAD)  SRCFILE(MYSRCLIB/QRPGLESRC)        
0007.00  * DFTACTRP(*NO) ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)               
0008.00                                                                        
0009.00  *-------------------------------------------------------------------* 
0010.00  *  2021/11/25 : 作成                                                  
0011.00  *-------------------------------------------------------------------* 
0012.00  *( 作業変数 )                                                         
0013.00 D TRUE#           S              4B 0 INZ(0)                           
0014.00 D FALSE#          S              4B 0 INZ(-1)                          
0015.00 D EOF#            S              4B 0 INZ(-1)                          
0016.00 D DFT             C                   CONST(X'0B000100')               
0017.00 D OE#             C                   CONST(X'0E')                     
0018.00 D OF#             C                   CONST(X'0F')                     
0019.00                                                                        
0020.00 D*( _Ropen  のプロトタイプ宣言 )                                       
0021.00  *[ 例 ]                                                               
0022.00  *  RFILE = _Ropen("ASNET.USR/USRLIBL", "rr")                          
0023.00 D Ropen           PR              *          ExtProc('_Ropen')         
0024.00 D  RFILE                          *   VALUE OPTIONS(*STRING:*TRIM)   
0025.00 D  OPTION                         *   Value OPTIONS(*STRING:*TRIM)   
0026.00                                                                      
0027.00 D*( _Rreadn のプロトタイプ宣言 )                                     
0028.00  * _RIOFB_T*_Rreadn(_RFILE *, void *, size_t, int);                  
0029.00  *[ 例 ]                                                             
0030.00 D Rreadn          PR              *          ExtProc('_Rreadn')      
0031.00 D  RFILE                          *   Value                          
0032.00 D  RECORD                         *   Value                          
0033.00 D  RCD_LEN                      10I 0 Value                          
0034.00 D  OPT                          10I 0 Value                          
0035.00                                                                      
0036.00 D*( _Rclose のプロトタイプ宣言 )                                     
0037.00 D Rclose          PR            10I 0        ExtProc('_Rclose')      
0038.00 D  RFILE                          *   Value                          
0039.00                                                                      
0040.00 D IOFB_P          S               *                                  
0041.00 D RIOFB           DS            64    QUALIFIED                      
0042.00 D                                     BASED(IOFB_P)                  
0043.00 D  KEY                            *                                  
0044.00 D  SYSPRM                         *                                  
0045.00 D  RRN                          10I 0                                
0046.00 D  NUM_BYTE                     10I 0                                
0047.00                                                                      
0048.00 D RFILE           DS           336    QUALIFIED                              
0049.00 D                                     BASED(RFILE_P)                         
0050.00 D  BUF_LENGTH           193    196I 0                                        
0051.00                                                                              
0052.00 D RCD_LEN         S             10I 0                                        
0053.00 D DATA            S           5000A                                          
0054.00 D RFILE_P         S               *                                          
0055.00 D BYTES           S             10I 0                                        
0056.00 D HIVAL           S              1N   INZ(*ON)                               
0057.00                                                                              
0058.00 C*-------------------------------------------------------------------------+ 
0059.00 C     *ENTRY        PLIST                                                  | 
0060.00 C                   PARM                    FILE             10            | 
0061.00 C                   PARM                    FILLIB           10            | 
0062.00 C                   PARM                    MBR              10            | 
0063.00 C*-------------------------------------------------------------------------+ 
0064.00  /FREE                                                                       
0065.00     RFILE_P = Ropen(%TRIMR(FILLIB) + '/' + %TRIMR(FILE): 'rr');              
0066.00     RCD_LEN = RFILE.BUF_LENGTH;                                              
0067.00     DOW HIVAL;                                                               
0068.00       IOFB_P = Rreadn(RFILE_P: %ADDR(DATA): RCD_LEN: DFT);                   
0069.00       IF (RIOFB.NUM_BYTE = EOF#);                                            
0070.00          LEAVE;                                                              
0071.00       ENDIF;                                                                 
0072.00       EXSR  CHECK;                                                  
0073.00  /END-FREE                                                          
0074.00 C********************************                                   
0075.00 C*  レコードの処理はここから    *                                   
0076.00 C********************************                                   
0077.00 C                   EXSR      PRINT                                 
0078.00 C********************************                                   
0079.00 C*  レコードの処理はここまで    *                                   
0080.00 C********************************                                   
0081.00  /FREE                                                              
0082.00     ENDDO;                                                          
0083.00     Rclose(RFILE_P);                                                
0084.00  /END-FREE                                                          
0085.00 C                   SETON                                        LR 
0086.00 C                   RETURN                                          
0087.00 C******************************************************             
0088.00 C     CHECK         BEGSR                                           
0089.00 C******************************************************             
0090.00 C                   ENDSR                                           
0091.00 C******************************************************             
0092.00 C     PRINT         BEGSR                                           
0093.00 C******************************************************             
0094.00 C                   ENDSR   


                                         

[コンパイル]

CRTBNDRPG PGM(TEST.COM/TESTREAD) SRCFILE(R610SRC/QRPGLESRC) DFTACTGRP(*NO)
ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)

[解説]

RPG : TESTREAD はC言語のデータ・ベース読取り関数: _Ropen, _Rreadn, _Rclose を
使って処理している。
このうち _Rreadn は読取りバイト数を指定して読み取るので
読取りのときに警告エラーが出ることはない。
_Ropen で読み取るとレコード長: BUF_LENGTH を取得することができるので
その長さを指定して読み取ればよい。

0064.00  /FREE                                                                       
0065.00     RFILE_P = Ropen(%TRIMR(FILLIB) + '/' + %TRIMR(FILE): 'rr');              
0066.00     RCD_LEN = RFILE.BUF_LENGTH;                                              
0067.00     DOW HIVAL;                                                               
0068.00       IOFB_P = Rreadn(RFILE_P: %ADDR(DATA): RCD_LEN: DFT);                   
0069.00       IF (RIOFB.NUM_BYTE = EOF#);                                            
0070.00          LEAVE;                                                              
0071.00       ENDIF;                                                                 
0072.00       EXSR  CHECK;                                                  
0073.00  /END-FREE 
 :
0081.00  /FREE                                                              
0082.00     ENDDO;                                                          
0083.00     Rclose(RFILE_P);                                                
0084.00  /END-FREE

が読取り処理である。1万件くらいのファイルを読んでも瞬時に終わるので
驚かれる。
この技術は弊社の次の追加機能にも使われている。
製品とするのであれば高速処理が当然必要なのでこの技術を採用している。