Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 操作系统 > 其他操作系统 > 触发器运用<三>Using a Trigger for Data Validation
【标  题】:触发器运用<三>Using a Trigger for Data Validation
【关键字】:lt,gt,Using,Trigger,for,Data,Validation
【来  源】:http://blog.chinaunix.net/article.php?articleId=49551&blogId=646

触发器运用<三>Using a Trigger for Data Validation

Your Ad Here

This example employs a trigger program to validate data field values entered on new or changed CUSTOMER file records.

The file contains fields you would expect to see in a simple customer file, such as customer number, company name, contact name, address, etc. Figure 6.14 shows the complete layout for the file.

Click To expand
Figure 6.14: This CUSTOMER file is used to demonstrate trigger use.

The trigger program is added to the file via a CL command in the program DB008C shown in Listing 6.5.

Listing 6.5: CL program DB008C uses ADDPFTRG to add a trigger
Start example
PGM
/*----------------------------------------------------------------------*/
/*  Add trigger DB008R to file Customer to perform data                 */
/*  validation.
/*----------------------------------------------------------------------*/
             ADDPFTRG   FILE(CUSTOMER) TRGTIME(*BEFORE)+
                          TRGEVENT(*INSERT) PGM(DB008R) ALWREPCHG(*NO)
             ENDPGM 
             ADDPFTRG   FILE(CUSTOMER) TRGTIME(*BEFORE) +
                          TRGEVENT(*UPDATE) PGM(DB008R) ALWREPCHG(*NO)

             ENDPGM
End example

The trigger program DB008R is shown in Listing 6.6.

Listing 6.6: ILE RPG program DB008R is a trigger for the CUSTOMER file.
Start example
     FStates    CT   F   2        Disk
     DStateCodes       S             2A  Dim(100) Perrcd(1) Fromfile(States)
      *----------------------------------------------------------------------
      *  I'm using pointers instead of SUBSTR because %Addr 
      *  retains packed data. Substr doesn't handle embedded 
      *  packed data fields. 
      *----------------------------------------------------------------------
      *
     DpBefore          S             *
     DpAfter           S             *
      *
     DBefore         E DS                ExtName(CUSTOMER) Prefix(B_)
     D                                   Based(pBefore)
     DAfter          E DS                ExtName(CUSTOMER) Prefix(A_)
     D                                   Based(pAfter)
     D*
     DX                S            3  0
     D* 
     /*-----------------------------------------------------------------*/
      *  Trigger Buffer and Trigger Buffer Length Declarations
     /*-----------------------------------------------------------------*/ 
     DBufferLen        S            10I 0
     DTrigBuff         DS
     D  TrigFile                    10A
     D  TrigLib                     10A
     D  TrigMbr                     10A
     D  TrigEvent                    1A
     D  TrigTime                     1A
     D  TrigCommit                   1A
     D  TrigRes1                     3A
     D  TrigCCSID                   10I 0
     D  TrigRRN                     10I 0
     D  TrigRes2                     4A
     D  TrigB4OS                    10I 0
     D  TrigB4Len                   10I 0
     D  TrigB4NBM                   10I 0
     D  TrigB4NBL                   10I 0
     D  TrigAftOS                   10I 0
     D  TrigAftLen                  10I 0
     D  TrigAfNBM                   10I 0
     D  TrigAfNBL                   10I 0
      *-----------------------------------------------------------------
      *   Trigger Constants  
      *-----------------------------------------------------------------
     D@Insert          C                  '1'
     D@Delete          C                  '2'
     D@Update          C                  '3'
     D@Before          C                  '2'

     D@After           C                  '1'
      *-----------------------------------------------------------------
      *   API Declarations
      *-----------------------------------------------------------------
     DSMMsgId          S             7    Inz('CPF9898') 
     DSMMsgFile        S            20    Inz('QCPFMSG   *LIBL')
     DSMMsgTxt         S           100
     DSMMsgLen         S            10I 0 Inz(%Size(SMMsgTxt))
     DSMMsgType        S            10    Inz('*ESCAPE')
     DSMMsgQ           S            10    Inz('*')
     DSMMStack#        S            10I 0 Inz(1)  
     DSMMsgKey         S             4
      *
     DAPIErrorDS       DS
     D  APIBytes                    10I 0 Inz(%Size(APIErrorDS))
     D  APIBytesOut                 10I 0
     D  APIErrID                     7A
     D  APIReserved                  1A
     D  APIErInDta                 256A
      *-----------------------------------------------------------------
      *   Error Message Constants 
      *-----------------------------------------------------------------
     D@Error1          C                  'Customer Number cannot be blank' 
     D@Error2          C                  'Company Name cannot be blank' 
     D@Error3          C                  'Contact Name cannot be blank' 
     D@Error4          C                  'Address cannot be blank' 
     D@Error5          C                  'City cannot be blank' 
     D@Error6          C                  'Zip Code cannot be blank' 
     D@Error7          C                  'State cannot be blank' 
     D@Error8          C                  'Invalid State Entered' 
      *-----------------------------------------------------------------
      *  Input parameters are passed automatically when the trigger 
      *  fires. Passed are the trigger buffer and trigger buffer length. 
      *-----------------------------------------------------------------
     C     *Entry        PList
     C                   Parm                   TrigBuff
     C                   Parm                   BufferLen      
      *-----------------------------------------------------------------
      *  Map the data structures for the before and after images to
      *  the offset location in the trigger buffer using pointers.
      *-----------------------------------------------------------------
     C                   Eval      pBefore = %Addr(TrigBuff) + TrigB40S
     C                   Eval      pAfter = %Addr(TrigBuff) + TrigAft0S
      *
     C                   If        TrigEvent = @Update Or
                                   TrigEvent = @Insert
      *-----------------------------------------------------------------
      * Validate entire record. Send an error message for each 
      * violation found. 
      *-----------------------------------------------------------------
     C                   If        A_CMCUST# = *Blanks 
     C                   Movel(p)  @Error1       SMMsgTxt 
     C                   Exsr      SendError 
     C                   Endif 
      *
     C                   If        A_CMCOMP = *Blanks 
     C                   Movel(p)  @Error2       SMMsgTxt 
     C                   Exsr      SendError 
     C                   Endif 
      * 
     C                   If        A_CMCONT = *Blanks 
     C                   Movel(p)  @Error3       SMMsgTxt 
     C                   Exsr      SendError 
     C                   Endif 
      *
     C                   If        A_CMADD1 = *Blanks 
     C                   Movel(p)  @Error4       SMMsgTxt 
     C                   Exsr      SendError 
     C                   Endif 
      *
     C                   If        A_CMCITY = *Blanks 
     C                   Movel(p)  @Error5       SMMsgTxt 
     C                   Exsr      SendError  
     C                   Endif 
      *
     C                   If        A_CMZIP = *Blanks 
     C                   Movel(p)  @Error6       SMMsgTxt 
     C                   Exsr      SendError 
     C                   Endif 
      *
     C                   If        A_CMST  = *Blanks 
     C                   Movel(p)  @Error7       SMMsgTxt 
     C                   Exsr      SendError 
     C                   Else 
     C                   Eval      X = 1
     C    A_CMST         Lookup    StateCodes(X)                      90 
     C                   If        Not(*In90) 
     C                   Movel(p)  @Error8       SMMsgTxt 
     C                   Exsr      SendError
     C                   Endif
     C                   Endif
      *
     C                   Endif 
      *
     C                   Return
     /*-----------------------------------------------------------------*/  
      *  If any exceptions were found - Use QMHSNDPM API to send 
      *  a hard error back.     
     /*-----------------------------------------------------------------*/
     C    SendError      Begsr    
     C*
     C                   Call      'QMHSNDPM'
     C                   Parm                    SMMsgId
     C                   Parm                    SMMsgFile
     C                   Parm                    SMMsgTxt
     C                   Parm                    SMMsgLen
     C                   Parm                    SMMsgType
     C                   Parm                    SMMsgQ
     C                   Parm                    SMMStack#
     C                   Parm                    SMMsgKey
     C                   Parm                    APIErrorDS
     C*
     C                   Endsr
End example

What the Example Does

The example program DB008C uses the ADDPFTRG command to add the trigger program DB008R to the CUSTOMER file. The trigger is fired every time a record in the CUSTOMER file is added or changed. Because the trigger monitors both insert and update events, the trigger is added twice. The program checks and validates the input data, returning an error message if the data does not pass.

How the Example Works

When executed, the ADDPFTRG command listed in program DB008C adds trigger program DB008R to the CUSTOMER file. The ADDPFTRG command uses the following parameters.

The Physical File (FILE) Parameter The FILE parameter is required and specifies the qualified name of the file to which the trigger is to be added.

The Trigger Time (TRGTIME) Parameter The TRGTIME parameter is required and specifies the timing of the firing of the trigger program. The permissible values for the TRGTIME parameter are:

    ______________________________________________________________________________

      *BEFORE   The trigger executes before the record is processed 
      *AFTER    The trigger executes after the record is processed
    ______________________________________________________________________________

The example uses the value *BEFORE, meaning the trigger runs before the employee record changes or additions are written to the file. This allows you to reject records that do not meet the validation criteria.

The Trigger Event (TRGEVENT) Parameter The TRGEVENT parameter is required and defines the file event that causes the trigger program to fire. The permissible values for the TRGEVENT parameter are:

    ______________________________________________________________________________

      *INSERT   The trigger executes when a new record is added 
      *UPDATE   The trigger executes when a record is updated 
      *DELETE   The trigger executes when a record is deleted
    ______________________________________________________________________________

The example adds two triggers, one having the value *UPDATE, meaning the trigger runs before an application's record changes are written. The second trigger has a value of *INSERT, meaning the trigger runs before new records are written to the CUSTOMER file.

The Program Name (PGM) Parameter The PGM parameter is required and specifies the qualified name of the trigger program to be added.

The Replace Trigger (RPLTRG) Parameter The RPLTRG parameter specifies whether the new trigger is to replace any existing trigger defined for the file, time, and event combination. The permissible values for the RPLTRG parameter are:

    ______________________________________________________________________________

      *YES      The new trigger will replace an existing trigger 
      *NO       The new trigger will not replace an existing trigger
    ______________________________________________________________________________

The example uses the value *NO.

The Allow Repeated Change (ALWREPCHG) Parameter The ALWREPCHG parameter specifies whether the new trigger has the capability to change the original record that caused the trigger to fire. The permissible values for the ALWREPCHG parameter are:

    ______________________________________________________________________________

      *YES      The trigger program can alter the original record 
      *NO       The trigger program cannot alter the original record
    ______________________________________________________________________________

The example uses the value *NO, restricting it from changing any of the values in the Customer record.

The Trigger Update Condition (TRGUPDCND) Parameter The TRGUPDCND is used only for triggers having a trigger event of *UPDATE. The parameter specifies if the trigger is to be fired only when a field is actually changed by an update operation. The permissible values for the TRGUPDCND parameter are:

    ______________________________________________________________________________

       *CHANGE   The trigger fires only if fields have changed 
       *ALWAYS   The trigger fires on all update operations
    ______________________________________________________________________________

The example uses the value *CHANGE, specifying that one or more field values must actually be changed to fire the trigger.

The ILE RPG Trigger Program

When executed, the trigger program DB008R validates the data being added or changed in the CUSTOMER file. If any field does not meet the validation requirements, the program sends an escape error message to the program message queue. This results in a hard error for the application that initiated the add or change. This program can be used as an example of how to use a trigger program to perform data validation and of how to employ the Send Program Message API.

Defining the Trigger Buffer

The code that is common to all trigger programs defines the layout of the trigger buffer parameter. A simple coding technique employing pointers defines the trigger buffer in a flexible and reliable way. If you have not used pointers in an RPG program before, they are simply a way to address a specific storage location. As discussed earlier in this chapter, the trigger buffer parameter passed to your program varies in length because the length of the trigger record varies from file to file. Pointers allow you to soft code the location of the record images with the trigger buffer using the offset values also found in the parameter. Figure 6.15 shows the definition of the pointers and data structures that define the input parameters.

Click To expand
Figure 6.15: These specs define the pointers and data structures used for the trigger buffer.

The input parameter TRIGBUFF is defined as a data structure, with subfields parsing out each individual field within the fixed-length portion of the buffer. The offset values, provided in the subfields TRIGB4OS and TRIGAFTOS, tell your program the starting positions within the buffer for the before and after record images.

To avoid the hard coding of the subfields of the customer record within both the before and after images, the file is used to create two external data structures called BEFORE and AFTER. The data structure definitions use the DTAARA keyword to base the layout of the structure on the Customer file. The PREFIX keyword is used on each to add a unique prefix of either ‘B_’ or ‘A_’ to the field names. The BASED keyword specifies that the data structure is to be loaded with the data residing in the address provided by the pointers PBEFORE and PAFTER.

The before and after record images are loaded into the data structures by setting the pointers to the address locations of the records within the trigger buffer. This is performed in Figure 6.16 using the RPG Address-Of function. The appropriate offset is added to the address of the buffer and is loaded into the pointer variable. Because the data structures BEFORE and AFTER are based on the pointer variables, they reflect the proper values.

Click To expand
Figure 6.16: The before and after record images are retrieved from the buffer using pointers.

Employing pointers to define the record images in the trigger buffer is a flexible, soft-coded approach to use for all your trigger programs. Figure 6.17 provides a further conceptual look at the technique.

Click To expand
Figure 6.17: A conceptual view of the use of pointers and data structures within a trigger.

The Remaining Trigger Logic

Once the trigger buffer has been defined, allowing easy access to the before and after record images, the main program logic validates each data field. Figure 6.18 shows the validation code.

Click To expand
Figure 6.18: The trigger program tests each individual data field.
Click To expand
Figure 6.18: The trigger program tests each individual data field (Continued).

The main trigger logic begins by verifying that the trigger event is either a record update or an add. If it is an add or update, the code tests the after-change value of each data field. If any field does not meet the desired requirements, an error message is sent by executing the subroutine SENDERROR. The subroutine SENDERROR is shown in Figure 6.19.

Click To expand
Figure 6.19: The SENDERROR subroutine sends a program error message.

To send a message to a program message queue, the RPG program could call a CL program that would use a SNDPGMMSG command to send the desired error. However, it is just as easy and more flexible to employ a system API to do the same thing. For more detailed explanations of API use, please refer to chapter 4.

The system API QMHSNDPM sends a message to a program message queue. The API parameters are defined in the program definition specifications and provide details used to instruct message delivery when the API is called. Figure 6.20 shows the definition of the API parameters.

Click To expand
Figure 6.20: The parameters used by the API to send an error message.

Additional Considerations

When you create your trigger programs in ILE, you need to decide how it will fit into your overall ILE strategy. What is the appropriate activation group the trigger should run under? It really depends on what type of applications that will be calling it. It is generally appropriate to create your trigger programs to run under a specific named activation group.

CLP里关于字符的超作:【上一篇】
触发器运用<二>Using a Trigger for Security Monitoring:【下一篇】
【相关文章】
  • Move dms_prod server form 670 to 690
  • java的安装与配置 for oracle 10g
  • Certification: Certificate of Proficiency for AIX
  • Managing Database Lists
  • AIX 5 performance series: CPU monitoring and tunin
  • VG中LTG参数的意义
  • CPU PERFORMANCE
  • Step bye Step for Install the Domino server 7 on a
  • Automate getting the dbx trace information
  • Cluster Systems Management Cookbook for pSeries
  • 【随机文章】
  • 关于volatile和原子操作研究的插曲
  • session-timeout
  • 阅读体会(1):《你的灯亮着吗?——发现问题的真正所在》
  • 16进制
  • c#中的正则表达式
  • VB中用API函数实现文件夹列表
  • UNIX下批量添加用户(未测试)
  • OpenReports 2.0 Milestone 2
  • msn6.1中批量输入和删除表情
  • xp局域网设置和xp无法访问局域网的解决方案
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.