MC Press Online

Monday, Jun 26th

Last updateFri, 23 Jun 2017 1pm

You are here: Home ARTICLES Programming RPG Practical RPG: Initialization Made Easy

Programming / RPG

Practical RPG: Initialization Made Easy

Support MC Press - Visit Our Sponsors


Flexible Input, Dazzling Output with IBM i



Click for this Month's

Bookstore Special Deals

Writing new records is a standard task in any system, and this article makes one of the steps of that process a whole lot easier.


One of the most critical functions of any business application is writing data to the database, which not coincidentally is one of the things that RPG does best. The whole concept of an externally described file is incredibly powerful: the ability to store data in individual fields and leave the aggregation to the compiler makes data generation a quick and simple task. However, even good techniques can still get better, and in this article, I'll show how a couple of keywords can be combined in a way that can shave precious time off of your development.

The Anatomy of a Database Write

Let's take a look at the process: in this case, I think we should write to a customer order file. I'm going to skip a lot of the detail and jump straight to the meat of the issue. We'll start with an excerpted version of our customer order detail file:


 R ORDDTLR                                          

   ODRCID         2A         TEXT('Record ID - OD') 

   ODORD         10S         TEXT('Order Number')   

   ODLINE         4S 0       TEXT('Line Number')    

   ODSTS          2A         TEXT('Line Status')    

   ODITEM        15A         TEXT('Item Number')    

   ODQORD         9S 3       TEXT('Quantity Ordered')

   ODQSHP         9S 3       TEXT('Quantity Shipped')

   ODQPCK         9S 3       TEXT('Quantity Picked')

   ODUPRC         9S 4       TEXT('Unit Price')     

   ODENTS          Z         TEXT('Entry Timestamp')

   ODENUS        10A         TEXT('Entry User')     

   ODENPG        10A         TEXT('Entry Program')  


This is just a selection of the fields, with some basics. For example, I'm showing the item and quantity fields (three quantities, in fact: ordered, shipped and picked) and the price. I'm showing the key fields of order and line, as well as a number of status and maintenance fields, including the record ID, the status, and the entry information (timestamp, user, and program). I know that the idea of a record ID is a bit quaint, but some of us old-timers still put them in. It's just a good way to know that the record didn't come from some completely off-the-wall source (can you say ODBC?).


Now, let's take a look at a program that writes a dummy record to the file. This won't be close to a complete program; in fact, it will only set a few fields and write a single record to the database. But how it sets those fields is the subject of this article.


     fORDDTL    o    e             disk


Here's the file specification that defines the ORDDTL file, the same file shown above. I define the file as an output-only file, externally described.


     d C_ODRCID        c                   'OD'

     d C_ORDSTS_OPEN   c                   '00'

     d C_PGMNAME       c                   'OE0300'


Next are some named constants. I use named constants a lot, and I have gotten into the habit of naming them a certain way: I use all caps in the name, and I prefix the name with C_ to indicate a constant. I'm not afraid to make the names a little longer if a chance of ambiguity exists. C_ORDSTS_OPEN would live alongside C_ORDSTS_SHIPPED and C_ORDSTS_CANCELED, most likely in a copy file. But I wanted to show you the constants here for a reason, which will become obvious in just a moment.


     d dsORDDTL      e ds                  extname(ORDDTL:*output)

     d                                     qualified inz


This is how you set up a data structure to write to an externally described file. Specify the filename on the extname keyword along with the option *output, which tells the compiler to set up a data structure that matches the output buffer for the file. This program requires the output buffer because I'll be doing a write to the file. Input and output buffers on most files are the same, but the requirement still exists. I've also set up the data structure to be qualified, which allows me to have multiple data structures with the same field name. This is important if you have to do I/O to different logicals of the same file or if you have a shop where the same field name is shared among different files. Finally, I added the inz keyword, which initializes all the fields in the data structure. If I didn't do this, any field that I did not explicitly set would have blanks in it, which is painful for packed fields.


     d   ODRCID      e                     inz(C_ODRCID)

     d   ODSTS       e                     inz(C_ORDSTS_OPEN)

     d   ODENUS      e                     inz(C_PGMNAME)


These lines are the focus of this article. I am able to pre-initialize various fields in the data structure. Note that I can initialize them to other values, provided they are values that the compiler can determine at compile time. For example, I can't set the value of ODENTS to the results of the %timestamp BIF; I get an error saying the compiler can't determine the value of the argument at compile time. In this case, though, I can set three fields: the record ID, the initial status, and the name of this program. That being done, it's time to move on to the working part of the program.



       reset dsORDDTLX;


This statement is deceptively simple. Most times, RESET and CLEAR function almost identically, but in this case, they are very different. CLEAR would initialize all the values in the data structure to the appropriate default for that data type. Usually, RESET would do the same thing, but in this example it "re-initializes" the data structure to the values stored in the three fields in the data specifications shown earlier (ODRCID, ODSTS, and ODENUS). What's critical about this is that I can execute this single line of code anywhere and it is equivalent to clearing the data structure and initializing each of the other fields.


       dsORDDTLX.ODENTS = %timestamp;


This line represents the "rest" of the application—that is, all the code required to actually set up the data in the record. I'm only updating one field, the entry timestamp. A real application would fill all the other fields as well. But you get the point.


       write ORDDTLR dsORDDTLX;


       *inlr = *on;



And that's it. I write the record to the file from the data structure and then close the application. This is just a stub version of the program, but it demonstrates the power of the concept. What's really neat about this, though, is that whenever I need to write a new record, I can simply execute the RESET opcode and I'm starting with a pre-initialized data structure. You may not need this particular functionality in a lot of programs, but when you do need it, it's nice to have this technique. It leads to an excellent separation of code: you define the data structure and all the initializations in one place in the D-specs and leave the rest of your program very clean.


In another article, I'll show you how this technique and a little magic from our friend EVAL-CORR can make writing database conversions a breeze. Thanks for reading this edition of "Practical RPG"!


Joe Pluta
Joe Pluta is the founder and chief architect of Pluta Brothers Design, Inc. and has been extending the IBM midrange since the days of the IBM System/3. Joe uses WebSphere extensively, especially as the base for PSC/400, the only product that can move your legacy systems to the Web using simple green-screen commands. He has written several books, including Developing Web 2.0 Applications with EGL for IBM i, Eclipse: Step by Step, and WDSC: Step by Step. Joe performs onsite mentoring and speaks at user groups around the country. You can reach him at


MC Press books written by Joe Pluta available now on the MC Press Bookstore.


Developing Web 2.0 Applications with EGL for IBM i Developing Web 2.0 Applications with EGL for IBM i

Joe Pluta introduces you to EGL Rich UI and IBM’s Rational Developer for the IBM i platform.

List Price $39.95

Now On Sale


WDSC: Step by Step WDSC: Step by Step
Discover incredibly powerful WDSC with this easy-to-understand yet thorough introduction.

List Price $74.95

Now On Sale


Eclipse: Step by Step

Eclipse: Step by Step

Quickly get up to speed and productive using Eclipse.

List Price $59.00

Now On Sale