続いて RPG# によるレコードの更新のサンプルについて紹介する。
Web化ツールでは照会系のみに限定されていると思う人もかつてはあったが
更新系であっても何ら問題はない。
eStudio によって生成された DFU タイプのような「単票更新」を例に挙げて
説明する。
まず実行の様子を下記に紹介する。
下記が生成された RPG# ソースである。
------------------------------------------------------------------------------------- 0001.00 H NOMAIN BNDDIR('ASNET.COM/MAIN') DATEDIT(*YMD/) 0002.00 F********** 商品マスターファイル ***************************** 0003.00 F* WEB004 : TYPE: 単票更新 言語 : RPG# VER 5.1 0004.00 F********************************************************************** 0005.00 FWEB004H CF E SPECIAL PGMNAME('ASNET.COM/HTMLDVR') 0006.00 F PLIST(HPARM) 0007.00 F INFDS(INFDSF) 0008.00 FSHOHIN UF A E K DISK EXTFILE(SHOHIN_LIB) 0009.00 F********************************************************************** 0010.00 0011.00 /COPY ASNET.USR/QRPGLESRC,PROTOTYP5# 0012.00 D DSPHEAD_GO PR 0013.00 D DSPDTA01_UPD PR 0014.00 D DSPDTA01_DLT PR 0015.00 D ERRMSG PR 0016.00 D MSG * VALUE 0017.00 D REVIMG PR 0018.00 D FIELD * VALUE 0019.00 D SET_CURSOR PR 0020.00 D FIELD * VALUE 0021.00 D HTM_FILE S 10A INZ('WEB004H ') 0022.00 D HTM_LIB S 10A INZ('*LIBL ') 0023.00 D SHOHIN_LIB S 21 INZ('QTRFIL/SHOHIN') 0024.00 D HTM_DIR S 128A INZ('/AS400-NET.USR/PROJECT/- 0025.00 D WEB004') 0026.00 D NOTFOUND C CONST(' レコードが見つからない。 ') 0027.00 D MSG1 S 128A INZ(' 入力値の誤りです。 ') 0028.00 0029.00 D*( ファイル情報データ構造 ) 0030.00 D INFDSF DS 0031.00 D 512A 0032.00 D HTM_RECORD *RECORD 0033.00 D*( プログラム状況データ構造 ) 0034.00 D INFDSP SDS 0035.00 D 512A 0036.00 D JOB 244 253 0037.00 /COPY ASNET.USR/QRPGLESRC,HPARM 0038.00 0039.00 C*------------------------------------------------------- 0040.00 C TRNKEY KLIST 0041.00 C KFLD SHCODE 0042.00 C*------------------------------------------------------- 0043.00 ********************************************************* 0044.00 P EVENT B EXPORT 0045.00 ********************************************************* 0046.00 D PI 0047.00 /FREE 0048.00 ON_CLICK('DSPHEAD': 'GO': %PADDR(DSPHEAD_GO)); 0049.00 ON_CLICK('DSPDTA01': 'UPDATE': %PADDR(DSPDTA01_UPD)); 0050.00 ON_CLICK('DSPDTA01': 'DELETE': %PADDR(DSPDTA01_DLT)); 0051.00 /END-FREE 0052.00 P E 0053.00 ********************************************************* 0054.00 P BEGIN B EXPORT 0055.00 ********************************************************* 0056.00 * 最初の画面を出力します。 0057.00 D PI 0058.00 C WRITE DSPHEAD 0059.00 P E 0060.00 0061.00 ********************************************************* 0062.00 P DSPHEAD_GO B EXPORT 0063.00 ********************************************************* 0064.00 * GO ボタンが押されたときの記述を行います。 0065.00 D PI 0066.00 C READ DSPHEAD 99 0067.00 C *NOKEY CLEAR SHOHINR 0068.00 C SETOFF 90 0069.00 C TRNKEY CHAIN(N) SHOHIN 90 0070.00 C WRITE DSPDTA01 0071.00 P E 0072.00 0073.00 ********************************************************* 0074.00 P DSPDTA01_UPD B EXPORT 0075.00 ********************************************************* 0076.00 * 更新ボタンが押されたときの記述を行います。 0077.00 D PI 0078.00 C READ DSPDTA01 99 0079.00 C MOVE *ZEROS ADDRCD 0080.00 C MOVE *ZEROS CHGRCD 0081.00 C MOVE *ZEROS DLTRCD 0082.00 C SETOFF 90 0083.00 C TRNKEY CHAIN SHOHIN 90 0084.00 C N90 READ DSPDTA01 99 0085.00 C* 0086.00 C 90 ADD 1 ADDRCD 0087.00 C N90 ADD 1 CHGRCD 0088.00 C*----------------------------------------------------- 0089.00 C 90 WRITE SHOHINR 0090.00 C N90 UPDATE SHOHINR 0091.00 C*----------------------------------------------------- 0092.00 C WRITE UPDEND 0093.00 P E 0094.00 0095.00 ********************************************************* 0096.00 P DSPDTA01_DLT B EXPORT 0097.00 ********************************************************* 0098.00 * 削除ボタンが押されたときの記述を行います。 0099.00 D PI 0100.00 C READ DSPDTA01 99 0101.00 C MOVE *ZEROS ADDRCD 0102.00 C MOVE *ZEROS CHGRCD 0103.00 C MOVE *ZEROS DLTRCD 0104.00 C SETOFF 90 0105.00 C TRNKEY CHAIN SHOHIN 90 0106.00 C N90 ADD 1 DLTRCD 0107.00 C*----------------------------------------------------- 0108.00 C N90 DELETE SHOHINR 0109.00 C*----------------------------------------------------- 0110.00 C WRITE UPDEND 0111.00 P E 0112.00 0113.00 ********************************************************* 0114.00 P END B EXPORT 0115.00 ********************************************************* 0116.00 * 最後の処理を記述します。 0117.00 D PI 0118.00 C CLOSE WEB004H 0119.00 C CLOSE SHOHIN 0120.00 P E -------------------------------------------------------------------------------------
更新系は照会系とちがって考慮すべき点が2つある。
5250 エミュレータの場合は エミュレータ自身が行っていた入力妥当性検査を
ブラウザ上で再現する必要がある。
例えばブラウザでは数字フィールドや漢字フィールドという文字の指定はできないので
すべてのタイプの文字が入力されてしまう。
また漢字の場合、ブラウザ上ではシフト文字は必要ないが、ご存知のように
System i ではシフト文字の文の考慮が必要となり、シフト文字の分も入れて
初めて文字数の検査が必要となってくる。
これらを開発者が毎度、工夫して JavaScript を開発して用意するのは
大変な労力とテクニックを必要とする。
RPG# の場合はユーザーでこれらの妥当性検査を行う必要はない。
alt="7S0" のように文字属性が定義されていたのを思い出して欲しい。
この alt に定義された属性に対して自動的に妥当性検査を行う JavaScript が
始めから組み込まれているのである。
例えば、商品単価 : SHTANK の入力記述は、
<input type="text" name=SHTANK id="SHTANK" value="##########" onChange="chkInputValidity(this);" onKeyDown="FIELD_EXIT(this);" maxlength="10" size="12" alt="7S0" EDTCDE(J) DDS="CHECK(RB)">
のように定義されている。ずいぶん長い定義と思われるかも知れないが
この定義は Wizard によって自動生成されるのでユーザーが記述する必要はない。
onChange="chkInputValidity(this);
という指定によって新規入力や変更があったときには JavaScript関数 : chkInputValidity
が
呼び出されて alt に従った妥当性検査が行われる。
JavaScript関数 : chkInputValidity
は
<script type="text/javascript" src="/AS400-NET.USR/JS/RPG_SP_CLCHK.JS"></script>
によって RPG_SP_CLCHK.JS
という JavaScript ライブラリー内に定義されている。
もちろん この記述も Wizard によって自動的に組み込まれるのでユーザーが記述する必要はない。
このように Wizard 生成を使えば 入力妥当性検査も RPG# に任せることができるのである。
次の商品マスター・レコードを検索するプロシージャーを見て欲しい。
0061.00 ********************************************************* 0062.00 P DSPHEAD_GO B EXPORT 0063.00 ********************************************************* 0064.00 * GO ボタンが押されたときの記述を行います。 0065.00 D PI 0066.00 C READ DSPHEAD 99 0067.00 C *NOKEY CLEAR SHOHINR 0068.00 C SETOFF 90 0069.00 C TRNKEY CHAIN(N) SHOHIN 90 0070.00 C WRITE DSPDTA01 0071.00 P E
0069.00 C TRNKEY CHAIN(N) SHOHIN 90
である。 CHAIN(N)
の (N) によって、CHIAN 命令によってレコードを検索できたときにも
(N) によって直ちにレコードを解放しており、レコード・ロックは行わない。
CHAIN 後にずくにでも他のユーザーがこの同じレコードを獲得することが可能なように
考慮されているのである。
ところが実際には在庫レコードや引き当て数を他のユーザーからは保護したい場合もある。
自分が引き当てた数量は他のユーザーからの更新を禁じることによって
更新か解放が行われるまではレコード・ロックをする必要がある。
このような意図的なレコード・ロックは設計上、行うことは珍しくはない。
ところが Web適用業務は、CGI は実行して HTML を出力してしまうと直ちに終了していまうのが
普通である。
CGI が終了してしまうので、当然、レコード・ロックははずれてしまい、次に引き当て数を
更新しようとすると、ホンのわずかなタイミングで他のユーザーに先を越されて更新されて
しまう可能性がある。
やはり CGI が終了したとしても、更新用のレコードをロックしておく機能は必要なのである。
RPG# は自動的にレコード・ロック機能を持っている。
この問題は RPG# では解決済みであり、CGI が意図的にレコードをロックしたままで終了したとしても
終了直後にはロックされているレコードが検索されて、自動的にレコード・ロックは保持される。
次にレコードを使用することができるのは同じジョブの再開によるレコード更新か、または
CRTPF で指定したはずの「最大レコード待機時間」(WAITRCD
) であり、一般的には 60秒、
つまり一分である。
一分経過後にレコードの使用がなければロックしたレコードは自動的に解放される。
このように RPG# では 5250エミュレータのときと同じようにレコード・ロック機能が
保証されているのである。