|
|||||||
|
|
![]() |
|
|
Using Pointer-Based Variables in RPG IV by Raymond Everhart [The code for this article is available for download.] Using pointers in RPG IV doesn't have to be complicated. In this article we will explore the use of pointer-based variables in the context of a database trigger program. The program will demonstrate two techniques for using pointer-based variables. Before proceeding with this article, you may want a review of the basics of pointers. If so, check out article "Back to Basics: Pointers in RPG," by Kevin Vandever. A Trigger Example When a trigger program is called, two parameters are passed to the trigger program. The first parameter is a buffer that contains all of the information collected when the trigger was fired. The second parameter indicates the length of the data stored in the trigger buffer (the first parameter). Before OS/400 V5R1, the trigger buffer was commonly described using a data structure. The first 96 bytes of the trigger buffer were always subdivided the same way. The layout of the data following the 96th byte was determined by the length of the file's record format and by the number of fields contained in the record. If your file was 100 bytes long, the "before" image of the data would start in position 97 and end at position 196. If your file had 10 fields, the null map for the "before" image would begin at position 197 and end at 206. The "after" image of the data would start in position 207 and end at position 306. The null map for the "after" image would begin at position 307 and end at 316. Calculating and coding these starting and ending positions takes me back to coding in RPG II. It always took a few passes to get the data defined just right. When IBM released OS/400 V5R1, there were significant changes to DB2 and to the parameters passed when a trigger is fired. Numeric values in the fixed portion of the data were changed from the binary data type to the integer data type. More important, IBM warned that hard-coding the starting positions of the before and after images of the data was not recommended, because these positions could vary because of the additional support in DB2 for binary large objects, or BLOBs. The change from binary to integer data types effectively "breaks" trigger programs compiled under OS/400 V4R5 when the operating system is upgraded to V5R1. Buffer Description Figure 1 shows the fixed portion of the trigger buffer. These fields are crucial in determining the relative position of the "before" and "after" images of the data.
Here is a brief description of each field:
One thing that you should notice is that the data structure in Figure 1 does not define any fields past the fixed portion of the data. The entire parameter is stored in memory; the TriggerDS data structure defines only a portion of the data. The rest of the data will be accessed using pointer-based variables. Calculating the Position of the "Before" and "After" Images The starting position of the original record data is stored in the OrgRecOffset field. In order to set a pointer to the proper "address" in memory, we need to first determine the starting position of the data structure and then add the value off the offset. The code looks like this:
* Define Pointer fields
0001 D AfterPtr S *
0002 D BeforePtr S *
0003 D StartBuff S *
* Set pointers for before and after record image
0004 C Eval StartBuff = %Addr(TriggerDS)
0005 C Eval AfterPtr = StartBuff + NewRecOffset
0006 C Eval BeforePtr = StartBuff + OrgRecOffset
Line 4 sets the StartBuff pointer variable to the address occupied by the TriggerDS data structure. Line 5 sets the AfterPtr pointer variable to the address occupied by the first byte of the new record. Line 6 sets the BeforePtr pointer variable to the address occupied by the first byte of the original record. Externally Described Data Structures Now that we have established where the records start in memory, we can begin to access the data. Using an external data structure is the easiest way to ensure that the data definition matches the data. Just be sure that when you compile the program, your program uses the same file that you intend to install the trigger program onto. The code below defines an external data structure (line 1), adds a prefix (line 2) to each field, and then "overlays" the data structure at the memory address specified by the pointer variable, specified by the Based keyword (line 3). 0001 D AfterDS E DS ExtName(MyFile) 0002 D Prefix(A_) 0003 D Based(AfterPtr) 0004 D BeforeDS E DS ExtName(MyFile) 0005 D Prefix(B_) 0006 D Based(BeforePtr) Take a Moment to Let It Sink In In just six lines of code we have mapped a "before" image and an "after" image of the record as it is passed from the database trigger. It doesn't matter if the relative position of the data in the buffer changes; the data structures will be correctly positioned. If the file layout changes, simply recompile the trigger program and it will work. The source code for a functioning example can be downloaded here. What you do with the data is up to you. You can create a log file of changes, an export file for interfacing to other applications, or add referential integrity checking. The possibilities are endless. Raymond Everhart is an independent programmer/consultant in the Dallas/Fort Worth area and has 17 years of experience with IBM midrange servers. E-mail: reverhart@raecodesign.com. This article has been corrected since its was first published. The number of bytes referred to in the sentences that read "The first 95 bytes of the trigger buffer were always subdivided the same way. The layout of the data following the 95th byte was determined by the length of the file's record format and by the number of fields contained in the record" has been changed to 96 bytes. [Correction made 4/24/03.]
|
Editors
Contact the Editors |
| Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved. |