続いて 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エミュレータのときと同じようにレコード・ロック機能が
保証されているのである。