The Create CLP Insert command creates CL source for use in inserting
data from variables declared from a data base file into a record
buffer. The CRTCLPDCL command may be used to create the DCL
commands. CRTCLPINS simplifies the use of an UPDDBR or WRTDBR
command from the CLPDBR tool. See also the CRTCLPEXT command which
performs the inverse function.
Note that as of V5R4, the CL Compiler allows a data structure and
eliminates the need for CRTCLPINS. See the CRTCLPDCL command.
CRTCLPINS is intended primarily for use with the CLPDBR tool to allow
writing and updating of data base records from a CL program.
CRTCLPEXT works from a data base file definition. The command may
also be helpful when a record buffer must be passed from CL to a HLL
program or an externally described data structure is processed in a
CL program.
Steps used with CRTCLPINS
-------------------------
The typical use of CRTCLPINS is to create the CL needed to work with
the WRTDBR and/or UPDDBR commands of the CLPDBR tool. If you are not
familiar with CRTCLPINS, go thru the sample described in the
following section.
The CRTCLPINS steps are summarized here:
** Create a source member and write CL code such as described in
the sample.
** Use CRTCLPDCL to declare the variables for the externally
described file.
** Use a source editor to move the DCL statements to the DCL
section of the program.
** Use CRTCLPINS to create the code needed to perform the insert.
** Use a source editor to 1) Move the DCL statements to the DCL
section of the program 2) Move the linkage code immediately
before the WRTDBR or UPDDBR statement and 3) Move the INSERT
subroutine after a RETURN and before a ENDPGM statement.
Sample use of CRTCLPINS
-----------------------
The best method of understanding CRTCLPINS is to use a simple
example. You must be familiar with the CLPDBR tool to understand
this example.
Assume you want a program that will write a new record to the data
base.
Assume the file is named FILEA and is defined as:
A R FILEARCD
A KEY 5
A FLD1 10
A FLD2 3 0
A FLD3 7 2
A K KEY
To use the sample, you need to enter the DDS for a physical file and
use CRTPF for FILEA.
To use CRTCLPINS, you would create a CL source member (WRTFILEA is
used in this example) in a QCLSRC file with the code you need. Note
that the file name (FILEA) must be entered into the DBRCTLx files
with WRKDBRCTL to use OPNDBR.
PGM
OPNDBR FILE(xxx/FILEA) OPNTYPE(*OUT) DBRCTLLIB(yyy)
/* Move data to variables for a new record */
CHGVAR &KEY 'BBBBB'
CHGVAR &FLD1 'BANANAS'
CHGVAR &FLD2 '987'
CHGVAR &FLD3 '12345.67'
/* Write a new record */
WRTDBR RCD(&RCD)
CLSDBR
RETURN
ENDPGM
This is the only code you need to write. Other code will be
generated for you by use of TAA commands.
The CLPDBR tool's WRTDBR command requires a variable that is 5000 or
less bytes. The WRTDBR RCD parameter is named &RCD to allow you to
use the default name on CRTCLPINS. The variable will be declared as
*CHAR LEN(5000) by the use of CRTCLPINS.
The program will write one record to FILEA. The data is created by
using CHGVAR commands for the variables declared for the data base
fields.
The next step is to use CRTCLPDCL to create the DCLs that define
variables for the fields in FILEA.
CRTCLPDCL FILE(FILEA) SRCMBR(WRTFILEA)
CRTCLPDCL generates DCL statements for each field in the file. The
source statements are added at the end of the specified source
member. Using a source editor, move the DCLs to the DCL section of
the program. Your source would look like:
PGM
/* Defined from FILEA in xxx */
/* Start CRTCLPDCL definitions - 09/07/09 */
DCL VAR(&KEY) TYPE(*CHAR) LEN(5)
DCL VAR(&FLD1) TYPE(*CHAR) LEN(10)
DCL VAR(&FLD2) TYPE(*DEC) LEN(3 0)
DCL VAR(&FLD3) TYPE(*DEC) LEN(7 2)
/* End of CRTCLPDCL definitions */
OPNDBR FILE(xxx/FILEA) OPNTYPE(*OUT) DBRCTLLIB(yyy)
/* Move data to variables for a new record */
CHGVAR &KEY 'BBBBB'
CHGVAR &FLD1 'BANANAS'
CHGVAR &FLD2 '987'
CHGVAR &FLD3 '12345.67'
/* Write a new record */
WRTDBR RCD(&RCD)
CLSDBR
RETURN
ENDPGM
When WRTDBR occurs, the data must be in the &RCD variable. To cause
this, you would have to move the data from the variables declared for
the data base fields to the &RCD variable using CL substring (%SST).
This can be a tedious and error prone requirement.
To avoid this coding of substring, the CRTCLPINS tool can be used to
generate the code that will do it for you.
CRTCLPINS will generate source statements at the end of your existing
source member:
CRTCLPINS FILE(FILEA) SRCMBR(WRTFILEA)
The source that is generated has 3 sections:
** DCL statements that must be moved to the DCL section of the
source.
** Linkage code that is needed to link to a supplied section of
code labeled the INSERT routine (described in a later
section). Move the statements (beginning with the comment
'INSERT subroutine linkage' to the appropriate place in your
program which in this case is immediately before WRTDBR. Part
of the linkage code is to do CHGVAR from &RCD to the variable
declared as the record format name (FILEARCD) of the file you
specified.
** The third section is the INSERT routine which uses substring
functions to move data from the variables declared for the
data base fields to the variable used for the format variable.
Decimal fields within the buffer require special handling (see
later discussion). This subroutine like function is intended
to be placed after your RETURN statement.
The added code looks like:
/* Defined from FILEA in xxx */
/* Start CRTCLPINS definitions - 09/07/09 */
DCL VAR(&RCD) TYPE(*CHAR) LEN(5000)
DCL VAR(&FILEARCD) TYPE(*CHAR) LEN(21)
DCL VAR(&INSRTN) TYPE(*CHAR) LEN(8)
DCL VAR(&INSCHR8) TYPE(*CHAR) LEN(8)
DCL VAR(&INSDEC15) TYPE(*DEC) LEN(15 0)
/* End CRTCLPINS definitions */
/* Move immediately before a command such as UPDDBR or WRTDRB */
/* INSERT subroutine linkage */
CHGVAR VAR(&INSRTN) VALUE('INSERT1')
GOTO CMDLBL(INSERT)
INSERT1: /* Return from INSERT subroutine */
CHGVAR VAR(&RCD) VALUE(&FILEARCD)
/* Move after a RETURN and before ENDPGM */
SNDESCMSG MSG('Your code has fallen into the +
INSERT subr')
/********************************************/
/* */
INSERT: /* CRTCLPINS for FILEA in xxx */
/* Retrieved by CRTCLPINS on 09/07/09 */
/* */
/********************************************/
CHGVAR VAR(%SST(&FILEARCD 1 5)) VALUE(&KEY)
CHGVAR VAR(%SST(&FILEARCD 6 10)) VALUE(&FLD1)
CHGVAR VAR(&INSDEC15) VALUE(&FLD2)
MOVDECCHR CHROUT(&INSCHR8) DECINP(&INSDEC15)
CHGVAR VAR(%SST(&FILEARCD 16 2)) +
VALUE(%SST(&INSCHR8 7 2))
CHGVAR VAR(&INSDEC15) VALUE(&FLD3 * 100)
MOVDECCHR CHROUT(&INSCHR8) DECINP(&INSDEC15)
CHGVAR VAR(%SST(&FILEARCD 18 4)) +
VALUE(%SST(&INSCHR8 5 4))
/* Return GOTOs. Modify as required */
IF COND(&INSRTN *EQ 'INSERT1') +
THEN(GOTO CMDLBL(INSERT1))
SNDESCMSG MSG('Bad return in INSERT routine of ' +
*CAT &INSRTN)
/********************************************/
/* */
/* End of INSERT subroutine */
/* */
/********************************************/
Using a source editor, you then:
** Move the DCLs to the DCL section of the program.
** Move the linkage code immediately before WRTDBR.
** Move the INSERT subroutine after the RETURN command and before
the ENDPGM statement.
** Delete the excess blank separator lines and information
comments.
The final code would look like:
PGM
/* Defined from FILEA in xxx */
/* Start CRTCLPDCL definitions - 09/07/09 */
DCL VAR(&KEY) TYPE(*CHAR) LEN(5)
DCL VAR(&FLD1) TYPE(*CHAR) LEN(10)
DCL VAR(&FLD2) TYPE(*DEC) LEN(3 0)
DCL VAR(&FLD3) TYPE(*DEC) LEN(7 2)
/* End of CRTCLPDCL definitions */
/* Defined from FILEA in xxx */
/* Start CRTCLPINS definitions - 09/07/09 */
DCL VAR(&RCD) TYPE(*CHAR) LEN(5000)
DCL VAR(&FILEARCD) TYPE(*CHAR) LEN(21)
DCL VAR(&INSRTN) TYPE(*CHAR) LEN(8)
DCL VAR(&INSCHR8) TYPE(*CHAR) LEN(8)
DCL VAR(&INSDEC15) TYPE(*DEC) LEN(15 0)
/* End CRTCLPINS definitions */
OPNDBR FILE(xxx/FILEA) OPNTYPE(*OUT) DBRCTLLIB(yyy)
/* Move data to variables for a new record */
CHGVAR &KEY 'BBBBB'
CHGVAR &FLD1 'BANANAS'
CHGVAR &FLD2 '987'
CHGVAR &FLD3 '12345.67'
/* Write a new record */
/* INSERT subroutine linkage */
CHGVAR VAR(&INSRTN) VALUE('INSERT1')
GOTO CMDLBL(INSERT)
INSERT1: /* Return from INSERT subroutine */
CHGVAR VAR(&RCD) VALUE(&FILEARCD)
WRTDBR RCD(&RCD)
CLSDBR
RETURN
SNDESCMSG MSG('Your code has fallen into the +
INSERT subr')
/********************************************/
/* */
INSERT: /* CRTCLPINS for FILEA in xxx */
/* Retrieved by CRTCLPINS on 09/07/09 */
/* */
/********************************************/
CHGVAR VAR(%SST(&FILEARCD 1 5)) VALUE(&KEY)
CHGVAR VAR(%SST(&FILEARCD 6 10)) VALUE(&FLD1)
CHGVAR VAR(&INSDEC15) VALUE(&FLD2)
MOVDECCHR CHROUT(&INSCHR8) DECINP(&INSDEC15)
CHGVAR VAR(%SST(&FILEARCD 16 2)) +
VALUE(%SST(&INSCHR8 7 2))
CHGVAR VAR(&INSDEC15) VALUE(&FLD3 * 100)
MOVDECCHR CHROUT(&INSCHR8) DECINP(&INSDEC15)
CHGVAR VAR(%SST(&FILEARCD 18 4)) +
VALUE(%SST(&INSCHR8 5 4))
/* Return GOTOs. Modify as required */
IF COND(&INSRTN *EQ 'INSERT1') +
THEN(GOTO CMDLBL(INSERT1))
SNDESCMSG MSG('Bad return in INSERT routine of ' +
*CAT &INSRTN)
/********************************************/
/* */
/* End of INSERT subroutine */
/* */
/********************************************/
ENDPGM
You are now ready to create the WRTFILEA CL program and call it. The
program will write one record to the FILEA file.
Use of CLPDBR RCLDBR
--------------------
When you begin to use CLPDBR functions along with the INSERT
subroutine, it is typical to make mistakes which cause the file you
were operating on to remain open. If you correct the program and
call it again, you will receive an error saying the OPNID is already
in use or open.
To correct the problem you need to use the RCLDBR command which will
delete all of the data areas created by OPNDBR commands, close any
files that are open, and reclaim the activation group that the CLPDBR
functions run in.
Then try your program again.
The Linkage code
----------------
The linkage code changes the value of &INSRTN to a name (INSERT1)
that will be used later in an IF test. A GOTO is used to branch to
the INSERT subroutine. The next statement uses a label of INSERT as
the return point from the subroutine. The &FILEARCD variable which
now contains the record buffer is then moved to the &RCD variable.
The INSERT subroutine
---------------------
The INSERT subroutine uses substring (%SST) to insert the data from
the variables declared for the data base fields into the record
buffer.
The first statement generated is the SNDESCMSG TAA command which
states that your code has fallen into the subroutine. The subroutine
is intended to be branched to with a GOTO, so the SNDESCMSG command
protects your program logic.
Character data is moved by using substring positions.
Packed and Zoned decimal data require specific handling as described
in the next section.
At the end of the subroutine is an IF statement, that determines
where the code should branch to.
If you have one place in your program where you need the subroutine,
the linkage code and ending GOTO appear overly complex. However, the
code is designed to allow multiple uses of the subroutine as is
described in a later section.
The last statement is another SNDESCMSG TAA command which describes
the problem where you have branched to the INSERT routine, but do not
have a valid value in &INSRTN.
Handling of decimal fields
--------------------------
Packed decimal fields require some specific handling because CL does
not allow a packed value in a *DEC variable to be moved to a
character variable as packed data (CHGVAR would unpack the data
before attempting to move it). For example, if you have a 3 digit
*DEC variable in CL, the value might be X'123F'. If you use CHGDTA
to a *DEC field, the data would be unpacked to a value of 123 and
cannot be moved to a 2 byte *CHAR variable. You would receiver the
error message CPF0819 (Variable or substring to small to hold the
result).
The TAA MOVDECCHR tool is used to handle the move from a *DEC
variable to a *CHAR variable without unpacking the data. Before
using MOVCHRDEC, CHGVAR is used to move the data to a standard *DEC
variable (&INSDEC15) which is declared as LEN(15 0).
If the field has more than 0 decimal positions, the data is
multiplied so that a whole number would exist. For example, &FLD3 in
the example is declared as *DEC LEN(7 2). The value is multiplied by
100 to make a whole number. The MOVDECCHR TAA command is then used
to move the decimal value to the &INSCHR8 variable as a packed value.
The value is right adjusted in the variable. If the value was 123.45
in a *DEC LEN(7 2) variable, the data in &INSCHR8 would be
X'000000000012345F' The data is then moved using CHGVAR to the proper
positions within the variable that is used for the format name. Thus
each packed field takes 3 statements in the subroutine.
CL does not support a zoned decimal type of variable. If a zoned
decimal field exists in the data base file, the DCL would define a
*DEC type which is treated as packed decimal within the CL program.
Zoned decimal fields are processed in the subroutine by first moving
the data to the &EXTDEC15 field and creating a whole number (same as
described for packed fields). The RTVSGNPOS TAA command is then used
which does two things 1) It returns the low order digit of the field
as a zoned decimal field and 2) It returns a positive value if the
original value was negative.
The positive value is then moved to &INSCHAR15 which is declared as a
*CHAR LEN(15) variable. Since a positive whole number exists, the
character variable will not contain a decimal point nor minus sign
within the data. The value is then moved to the variable name for
the record buffer using substring for both values. The low order
digit which was retrieved by RTVSGNPOS is then placed in the low
order position of the field in the record buffer.
Two additional DCL statements (&INSCHR1 and &INSCHR15) are generated
if any zoned decimal fields exist in the file.
Binary fields are declared and moved to *CHAR variables. If you have
binary fields in the data base, you must code a CHGVAR statement to
convert the data to a decimal variable such as:
CHGVAR VAR(%BIN(&BINFLD 1 4) 1000
Multiple use of the INSERT subroutine for the same file
-------------------------------------------------------
The INSERT subroutine is designed to allow you to have multiple
points within your program where you need to write and/or update a
record in the same file. Before each WRTDBR or UPDDBR, you would
need to insert the required values into the variables declared for
the data base fields and then use the INSERT routine. The linkage
code must be modified for each subsequent use.
The following steps would be needed for each subsequent use:
** Duplicate the linkage code which appears as:
/* INSERT Subroutine linkage */
CHGVAR VAR(&INSRTN) VALUE('INSERT1')
GOTO CMDLBL(INSERT)
INSERT1: /* Return from INSERT subroutine */
CHGVAR VAR(&RCD) VALUE(&FILEARCD)
** Change the INSERT1 constant in the CHGVAR and the name of the
label. 'INSERT2' would be the typical choice for the second
usage.
** The last statement in the INSERT subroutine is:
IF COND(&EXTRTN *EQ 'INSERT1') +
THEN(GOTO CMDLBL(INSERT1))
Duplicate this code to the next line and change the 'INTSERT1' value
on the IF and the THEN to the name you chose previously such as:
IF COND(&EXTRTN *EQ 'INSERT2') +
THEN(GOTO CMDLBL(INSERT2))
Using both CRTCLPINS and CRTCLPEXT in the same program
------------------------------------------------------
The CRTCLPEXT tool provides the inverse function of CRTCLPINS.
CRTCLPEXT provides a subroutine like function to extract data from a
record to the variables declared for the data base fields.
You would use CRTCLPEXT if you were using a command like RDDBR to
read a record from the data base.
If you are using both RDDBR and UPDDBR/WRTDBR in the same program,
then both subroutines are needed. Just follow the steps for
CRTCLPEXT in addition to CRTCLPINS. You only need to use the
CRTCLPDCL function once to declare the variables for the fields in
the file.
Use of INSERT for different files
----------------------------------
You can use CRTCLPINS for different files within your program, but
you must use a different name for each subsequent use. Use a source
editor to change the name INSERT and the corresponding linkage code.
Conversion of field types
-------------------------
Character fields in the data base are extracted to *CHAR variables.
Packed and zoned fields are extracted to *DEC variables. The size of
the field cannot exceed 15 digits or 9 decimal positions.
Binary fields are extracted to *CHAR variables.
Any other field types are extracted to *CHAR variables.
CRTCLPINS escape messages you can monitor for
---------------------------------------------
None. Escape messages from based on functions will be re-sent.
Command parameters *CMD
------------------
FILE The externally described file to use to create the
insert information for. The file may be either a PF
or LF, but may only contain a single format.
The library defaults to *LIBL. A specific library
or *CURLIB may be entered.
SRCMBR The member of the source file to be added to. The
member must exist. The statements will be added
after the last existing record (if any) in the
source member.
SRCFILE The name of the source file containing the member to
be added to. The source file name defaults to
QCLSRC. The library qualifier defaults to *LIBL. A
specific library or *CURLIB may be entered.
RCDVAR The name of the variable that contains the data for
a function like WRTDBR or UPDDBR. The default is
&RCD. While both WRTDBR and UPDDBR will allow a
variable to be less than 5000 bytes, the variable is
declared as *CHAR LEN(5000) by CRTCLPINS. The name
is used in a single CHGVAR statement that is
generated in the linkage code created by CRTCLPINS.
Restrictions
------------
Packed or zoned decimal data base fields must be 15 digits or less
and the number of decimal positions must be 9 or less.
All other field types (including binary) are converted to *CHAR
variables.
Because a record buffer is used to pass data to the data base, no DDS
validity checking will occur.
** The source file must be at least 92 bytes in length.
Prerequisites
-------------
The following TAA Tools must be on your system:
HLRMVMSG HLL Remove message
RTVDBFA Retrieve data base file attributes
RTVFMT Retrieve format
RTVSYSVAL3 Retrieve system value 3
SNDCOMPMSG Send completion message
SNDDIAGMSG Send diagnostic message
SNDESCINF Send escape information
SNDESCMSG Send escape message
Implementation
--------------
None, the tool is ready to use.
Objects used by the tool
------------------------
Object Type Attribute Src member Src file
------ ---- --------- ---------- ----------
CRTCLPINS *CMD TAACLRI QATTCMD
TAACLRIC *PGM CLP TAACLRIC QATTCL
TAACLRIR *PGM RPG TAACLRIR QATTRPG
|