* This tool will be removed in the *
* next release. You should consider *
* using the Data Base trigger support *
* as a better solution. *
Validity checking of new records or changes to a data base can be a
complex function. Not only must the code be properly written, but
many error messages must be described.
If several programs update the same data base, a good deal of code
may need to be duplicated.
The following describes a technique that can be used to simplify the
coding and assist in ensuring that only good data is entered into the
The code is in a demonstration form which allows you to try the
sample as well as using it as a base for your own programs.
** The programs which change the data base only need to provide a
'hook' to the specific validity checking program for the file
that they change. A few standard entries are also needed in
the workstation file.
For example, the typical solution to error handling with DDS
requires the ERRMSG keyword and a unique indicator. Removing
the error handling makes both the display file and the program
** The validity checking functions are written in a separate
program which is devoted to providing whatever checking is
needed and appropriate error text. The same program can be
called from any program that changes the file using the same
format. This tends to centralize all of the rules regarding a
given file and can give the responsibility to a single
** The validity checking program can be written by someone
devoted to the task rather than someone who is trying to
perform both the production task and validity checking. This
will generally produce a better result.
** The validity checking routine can perform whatever checks it
needs to. If it needs to access other files it can do so and
enforce referential integrity.
** The validity checker is written in a HLL. The example shows
RPG code. Externally described data is used to define the
record passed from the main program. No new language
specifications are needed. You can write the most complex
rules in a language you already know.
** The validity checker can be changed at any time. Unlike DDS
validity checking statements, a change in validity checking
does not require re-creating the file, copying the data and
rebuilding access paths.
** The sample is written for an interactive program. The same
technique could be used by a batch program.
** Error message capability is provided. If the operator makes
an error, one line of text is written to the display. If the
operator does not understand the message, a function key may
be pressed to access a second level.
Both the first level and second level of text reside as source
statements in an array within the validity checking program.
Other techniques are possible, but this is the simplest
approach. The second level of text is presented in a subfile
and has no reasonable bounds on size (The limit of the system
2nd level text is 3000 bytes).
Note that the validity checking program approach is better
than similar functions supplied in DDS because the error
messages can be more specific. DDS error text is
non-specific. For example, you see only an 'Out of range'
statement without any details for the operator to determine
what the correct range is. The VALUES keyword operates in the
The system allows you to define messages which exist in
message files to be used in an application and can display
both a 1st and 2nd level. While this has the advantage that
it can be maintained separately (no program re-creation to
make a change) and allows substitution values, it has the
disadvantage of not being easy to see what the text will look
like to the operator. The SEU entry is much closer to 'What
you see is what you get'.
** Two forms of error handling are provided. The default is to
lock the keyboard and require the reset key to be pressed.
The alternate form does not lock the keyboard. The input
fields as keyed by the operator remain on the display with
** The validity checking program also provides a solution for the
case where the main program is both reading and adding new
records to RPG and an initialized format is needed for new
records. This is the problem that is caused by RPG having
only a single work area for fields. When a read occurs, all
of the fields are filled with data. When you are adding a new
record, it is normal to not add all of the fields and
therefore your program must initialize those fields which are
not being added in this program.
** The input field in error is not highlighted on the display nor
is the cursor placed on the field. It is up to the message
text to describe the error.
** Variables cannot be placed into the message text.
** The validity checking is not enforced for a given file. It
can only be performed if the programs that change the file
call the validity checker. DFU programs can change the file
independently of the validity checker.
** If the data base definition is changed, you must at least
re-create the validity checking program. If not, the program
will abnormally terminate (assuming you take the default for
LVLCHK(*YES). See the discussion of level check in the
program logic section.
** Only one error message at a time is displayed to the operator.
If multiple errors exist, the operator must correct one
problem at a time and keep pressing Enter to get all of the
error messages. Your code can control which error is
Trying the sample
Call the following program which has already been created. The new
records will be written to the TAARPGCP file in TAATOOL. This file
is cleared each time the call to the CL program occurs. The purpose
of writing records is to allow you to see that the initialization
function for fields not used in the program is working properly.
A screen will be displayed with three fields. The following
describes the validity checking that is coded for each field.
** Field A - One character field
Any entry is valid except W, Y and Z.
** A 'Z' entry will produce an error that says that Z is not
valid. Second level text exists.
** A 'Y' entry will produce an error that says that Y is not
valid. No second level text exists.
** A 'W' entry will produce an error, but there is no text for
the message (a programmer error).
** Field B - One character field
It must be one of the following values (A B D E F).
Second level text describes the valid values.
** Field C - numeric field keyed as a digits field
A value less than 5 will produce an error message. Second level text
of multiple pages is available.
If an error condition occurs, the keyboard will be locked. The
specific message occurs on line 24. A general message occurs on line
25 (similar to that used by ERRMSG).
Leaving the keyboard unlocked on an error
The code is very similar whether the keyboard should be locked or
unlocked. A separate record format (ERRLN2) is provided in the
display file TAARPGCD. The display file does not need to be created.
The RPG program TAARPGCR must be changed to do a WRITE to ERRLN2
instead of ERRLN1.
The RPG program TAARPGCR2 must be changed so a constant does not tell
the operator to 'Press reset'. See the instructions at the beginning
of the program.
Records written to TAARPGCP
The file TAARPGCP in TAATOOL is defined with fields:
FLDA *CHAR LEN(1) Entered by the program
FLDB *CHAR LEN(1) Entered by the program
FLDC *DEC LEN(3 0) Entered by the program
FLDD *CHAR LEN(1) Not entered - should be initialized
FLDE *CHAR LEN(1) Not entered - should be initialized
FLDF *DEC LEN(3 0) Not entered - should be initialized
FLDG *DEC LEN(3 0) Not entered - should be initialized
Difference between help text and error text
Help text should normally be created to describe the overall concept
of a screen or field and what the specific values are.
Error text is useful when the operator makes an error and a very
specific statement must be made. Because only one line of text is
shown for the first level of error text, the message tends to be very
terse and unlike help text.
The second level of error text and general help text can have a lot
in common. For this reason you may want to use the DDS help text
facility to provide for general help (it can be cursor sensitive) and
use the validity checking function second level for very specific
Note that there is no link to any help text for the field from the
validity checking second level error text. Nor can the error text be
accessed by the operator unless an incorrect entry in a field causes
the validity check function to be invoked.
A reasonable solution might be to provide help text as you would
normally. Then provide the first level error text in the validity
checking solution. You could either have no second level or minimal
second level error text. You could easily modify the code to prevent
the display of second level text, but probably a more practical
solution is to use it where it is really helpful. You could modify
the second level error text display to refer the user to the help
text function if your application has provided it.
Another reasonable approach is to not provide any help for certain
displays, but only error text if the operator makes an error.
The demonstration is ready to run.
The source for the programs is of value when you want to copy the
code or the concept. The code is reasonably well documented and the
program logic section at the end of this tool discussion will
describe more of the details.
The following are some things to consider when you implement:
** You should decide on your strategy of whether to lock the
keyboard or not lock the keyboard on an error. Some of the
sample code should be dropped once your strategy is decided.
** The sequence of steps for how to handle the screen in the
TAARPGCR program must be followed properly. Otherwise the
operator may lose the input fields that have already been
** Your display file must be specified RSTDSP(*YES). The
validity checking program will write it's own display for
second level help and RSTDSP(*YES) is needed to put your
display back to the previous version.
** In most cases there will be a single validity checking program
per file. However, if you have different formats for the file
that are used to update or add through, you may need multiple
** Your validity checking rules may need to be sensitive to the
type of function being performed. For example, on an add, the
program which is adding may not be inserting all of the fields
into the record. In some approaches, the request for VAL
should be split into a request to ADD or UPD.
** The validity checking program has both skeleton code that
needs to be copied and places for your checking and messages.
Note the sample shows a GOTO instruction if an error is found
while performing each logical checking step. The steps should
be written in the sequence that you want them checked. For
example, if the operator makes multiple errors, the GOTO
allows the error messages to occur in the sequence of the
logic. Only the first error found will be displayed.
** The assignment of 'Error IDs' should be considered. A 4
character code is used. The sample shows numbers such as
'0010'. Any characters are valid, but you will probably want
to develop a convention to assist in determining new IDs and
** The approach can be used to provide referential integrity
between the file being changed and other associated files.
For example, if the user does an add, the validity checking
program could ensure that the same key exists in a separate
file. Conversely, if the user does a delete, you could pass
the delete request (as a new request type) to the validity
checker which could ensure that no records exist in another
** The record initialization function (for new records to be
added) is part of the validity checking program. Because a
data structure is initialized to blanks, the Z-ADD operation
must be used to initialize each numeric field. When the file
definition is changed to include a new numeric field, the
validity checking program must also be changed to initialize
the new field.
The following TAA Tools must be on your system
SNDESCMSG Send escape message
Objects used by the tool
Object Type Attribute Src member Src file
------ ----- --------- ---------- -----------
TAARPGCP *FILE PF TAARPGCP QATTDDS
TAARPGCD *FILE DSPF TAARPGCD QATTDDS
TAARPGCE *FILE DSPF TAARPGCE QATTDDS
TAARPGCC *PGM CLP TAARPGCC QATTCL
TAARPGCR *PGM RPG TAARPGCR QATTRPG
TAARPGCR2 *PGM RPG TAARPGCR2 QATTRPG