4.2 Support for REDEFINES
COBOL copybooks use REDEFINES to redefine how data in specific columns can be defined differently.
In the data file, certain data columns can be used to store different data types or
to divide a previously defined variable into two or more variables.
10 NAME PIC X(36).
10 FIRST_LAST REDEFINES NAME.
15 LAST_NAME PIC X(20).
15 FIRST_NAME PIC X(15).
15 MIDDLE_INITIAL PIC X.
In the above example, NAME is defined as 36 characters.
But the same space found in the data file is also futher refined into 20 characters representing LAST_NAME,
15 characters representing FIRST_NAME, and one character representing the MIDDLE_INITIAL.
There is only 36 characters in the data file for both of these COBOL copybook definitions.
As such in this example, the easiest way to support REDEFINES is simply to comment out the less detailed
description of the data. For the above example, we could comment out the NAME column and REDEFINES lines.
/*
10 NAME PIC X(36).
10 FIRST_LAST REDEFINES NAME.
*/
15 LAST_NAME PIC X(20).
15 FIRST_NAME PIC X(15).
15 MIDDLE_INITIAL PIC X.
Now +1Copybook will only generate column names for LAST_NAME, FIRST_NAME, and MIDDLE_INITIAL.
REDEFINES are also used to define different data types for the same columns found in a data file.
In this case, you may need to divide a single data file into two or more smaller data files
where each line of data is defined by the same data types.
You can then edit the copybook.txt file to match the contents of the one data file by commenting out any
other REDEFINES statements and running +1Copybook to generate the control file.
Then you can repeat this process for the other data files to ensure the data file
contents matches the copybook.txt file and generate the next control file using +1Copybook.
How can you divide one data file into two or more data files based on REDEFINES?
Below is one example.
% cat divide_data_file.sh
awk '{
if ((substr($0,136,4) == "1963") && (substr($0,38,1)=='2'))
print > "1963.txt"
else
if (substr($0,$136,4) == "1974")
print > "1974.txt"
else
if (substr($0,$136,4) == "1988")
print > "1988.txt"
else
print > "other.txt"
}' Building.txt
In the above example, the year is found in column 136 with a length of 4 characters.
If the year is "1963" and if column 38 is a '2' (as an example), the line of data from Building.txt is placed into the 1963.txt file.
If the year is "1974", the line of data from Building.txt is placed into the 1974.txt file.
If the year is "1968", the line of data is placed into the 1968.txt file.
And if there is no match to any of the above criteria, the line of data is copied into the other.txt file.
Once you have the data files containing the same data types and have generated the corresponding control files that match how to load
each data file, you're ready to start loading in the data from each file.
Another way to handle REDEFINES is supported by Oracle's SQL*Loader utility.
You will still need to edit the copybook.txt file to match the data types for the REDEFINES and run +1Copybook,
but you can load the data from one file and place each control file in one file.
Below is an example.
LOAD DATA
INFILE 'BUILDING.txt'
BADFILE 'BUILDING.bad.txt'
REPLACE
INTO TABLE BUILDING_1963
WHEN (138)='6' AND (139)='3'
(
PROPERTY_ID POSITION(1:10) CHAR,
PROPERTY_TYPE POSITION(11:14) CHAR,
. . .
CODE POSITION(158:162) CHAR
)
INTO TABLE BUILDING_1974
WHEN (138)='7' AND (139)='4'
(
PROPERTY_ID POSITION(1:10) CHAR,
PROPERTY_TYPE POSITION(11:14) CHAR,
. . .
CODE_CHANGE POSITION(158:162) CHAR
)
INTO TABLE BUILDING_OTHER
(
PROPERTY_ID POSITION(1:10) CHAR,
PROPERTY_TYPE POSITION(11:14) CHAR,
. . .
CODE_CHANGE POSITION(158:162) CHAR
)
In this example, the WHEN clause is used.
If column 138 equals '6' and column 139 equals '3', which uniquely represents 1963 in the data,
the row of data stored in the BUILDING.txt file is loaded into the BUILDING_1963 table.
Similarly when column 138 equals 7 and column 139 equals 4, the row of data is loaded into BUILDING_1974.
Otherwise, the row of data is loaded into the BUILDING_OTHER table.
This example is actually an important example.
For example, using this approach you can load data for two or more tables with radically different data types defined
where the first few columns can specify which table to load.
The only condition being that the length of each row must be the same.
As such, mainframe extracts will pad the shorter rows of data with blanks to ensure each line of data is the same length.
Here's an example:
LOAD DATA
INFILE 'COMPANY_DATA.txt'
BADFILE 'COMPANY_DATA.bad.txt'
REPLACE
INTO TABLE STORE
WHEN (1)='1'
(
STORE_ID POSITION(1:10) CHAR,
STORE_NAME POSITION(11:41) CHAR,
STORE_CITY POSITION(42:62) CHAR,
. . .
STORE_CODE POSITION(158:162) CHAR
)
INTO TABLE EMPLOYEE
WHEN (1)='2'
(
SSN POSITION(1:9) CHAR,
CODE_VALUE POSITION(11:14) CHAR,
. . .
RATE POSITION(100:102) CHAR
)
INTO TABLE CUSTOMER
WHEN (1)='3'
(
CUSTOMER_CODE POSITION(1:10) CHAR,
CARD_ID POSITION(11:20) CHAR,
. . .
DISCOUNT POSITION(99:104) CHAR
)
In the example above, data found in COMPANY_DATA.txt file which is used to load the EMPLOYEE and CUSTOMER tables
needs to be padded with blanks to ensure it matches the length used to load in the STORE table.
5. +1DataElements Inputs
+1Copybook calls +1DataElements.
As such, all +1DataElements input files can also be used to configure +1Copybook output.
A brief synopsis for each of the +1DataElements configuration files follows.
See the +1DataElements Users Guide for more information.