Virtual Data Sets
In This Chapter
This chapter gives you programming tips and examples for creating virtual data sets.
Overview
A virtual data set is a collection of data that Databridge Accessories see as a DMSII data set, even though the virtual data set does not actually exist in the DMSII database. Databridge Accessories can clone and track virtual data sets in exactly the same way that they clone and track real data sets.
Virtual data can come from several sources, including sources external to the DMSII database, but something in the audit trail, such as an update or a documentation record, must cause Databridge to retrieve the external data.
Use virtual data sets when you want to create a structure that doesn't physically reside in the DMSII database but can be passed (via a Databridge Accessory) to a Databridge Client relational database or to another secondary database.
Note
If you want to convert the format of one or more data items within an existing data set individually, see Altered Data Sets for more information.
If you are using a Databridge Administrative Console and want to join two or more data sets into a single data set, you should join the data sets in the client database using SQL rather than using a virtual data set.
Under certain circumstances, virtual data sets may be affected by DMSII reorganizations. For more information about how DMSII reorganizations may affect virtual data sets, see DMSII Reorganizations.
To create a virtual data set, you must declare the virtual data set in the DBGenFormat parameter file. The virtual data set declaration lists the data items that you want to include in the virtual data set and specifies other details about the virtual data set, such as the data set structure number.
You must also provide a transform procedure to populate the virtual data set and declare the transform procedure in the DBGenFormat parameter file. A single transform procedure populates all virtual data sets that you declare in the DBGenFormat parameter file. The transform procedure is compiled as a patch to the DBSupport Library (see Step 9 for Creating a Virtual Data Set).
Finally, you must enter the name of the tailored support library and the transform in the appropriate Accessory parameter file.
When this process is completed, the Accessory can clone or track the virtual data set(s).
Before You Begin
To create a virtual data set, complete the following steps:
-
Read this entire chapter so that you get an understanding of how the code you write for your virtual data set relates to the actual virtual data set declarations you make in the DBGenFormat file.
For example, each virtual data set needs the following:
- Data set name that follows DMSII data set naming conventions
- Data item names that follow DMSII data item naming conventions
- Data item types that adhere to DMSII data type conventions
-
Decide what data you want to use for your virtual data set.
Virtual data sets may include data from a source external to the DMSII database, but something in the audit trail, such as an update or a documentation record, must cause Databridge to retrieve the external data. You can include any or all of the following:
- Any DMSII data sets or remaps within one or more databases
- Any flat file data
- Any data generated by an external program or library
-
Create the virtual data set as explained in Creating a Virtual Data Set.
Sample Files
The following sections of this guide provide instructions, tips, and samples to help you create a virtual data set:
- Writing a Virtual Data Set Transform Procedure gives specific details about how to modify the virtual transform skeleton (an outline for a transform procedure), PATCH/DATABRIDGE/ SAMPLE/SUPPORT/VIRTUAL.
- Sample ALGOL Virtual Transform Procedure contains the sample virtual transform procedure, PATCH/DATABRIDGE/SAMPLE/SUPPORT/FORMATADDRESS, and several corresponding parameter file declarations.
Creating a Virtual Data Set
To define a virtual data set, complete the following steps:
Note
It is recommended that you read through the section, Sample ALGOL Virtual Transform Procedure, before you create a virtual data set. The section that contains the sample transform also contains other helpful samples. For instance, DBGenFormat Parameter File Declarations contains a sample DBGenFormat declarations that correspond to steps Step3–Step5.
-
Use CANDE or another editor to retrieve the DBGenFormat parameter file DATA/GENFORMAT/SAMPLE/CONTROL.
For a general description of the DBGenFormat parameter file, refer to the Databridge Host Administrator's Guide.
-
Rename the file, as follows:
DATA/GENFORMAT/databasename/CONTROL
where databasename is the name of the database for which you are creating the tailored support library and from which you are creating part of your virtual data set.
-
Declare the virtual data set in the DBGenFormat parameter file (DATA/GENFORMAT/databasename/CONTROL) using the syntax in Syntax for Declaring a Virtual Data Set. Repeat this step for each virtual data set you want to declare.
-
Declare a primary key for each virtual data set you declared in the DBGenFormat parameter file if you plan to clone the virtual data sets. Virtual data sets have no key, and Databridge needs a key to consolidate any fixup records with the extracted records.
Note
If you do not create a primary key, Databridge uses absolute address (AA) values to create a unique key for the virtual data set. The code you write for the transform must set the unique AA value of each virtual data set record.
Often, the transform can use the AA of the original ("trigger") record, but if your transform procedure produces more than one virtual data set record for each real data set record, you must create a unique AA value for each virtual data set record.
Refer to the Databridge Host Administrator's Guide for more specific information about when and why you need to declare a primary key and for PRIMARY KEY syntax.
-
(Optional) If you want to use the virtual data set definitions in the Transform Layouts section of PATCH/DATABRIDGE/SUPPORT/databasename /GENGLOBALS when you write your transform procedure, do the following. Otherwise, skip this step and go to step 6.
- Save DATA/GENFORMAT/databasename/CONTROL.
- Compile the tailored support library, as follows:
START WFL/DATABRIDGE/COMP ("SUPPORT", "databasename" ["logicaldatabasename"])
Where Is "SUPPORT"
The literal that represents the DBSupport program
The quotation marks are required."databasename" " The name of the database for which you are creating the tailored support library
The database name can include a usercode and pack, which are used to locate the database DESCRIPTION file, as follows:"(usercode)databasename ON packname"
The quotation marks are required."logicaldatabasename" The name of a logical database for which you are creating the tailored support library This WFL compiles layout tables for each data set in the database designated by databasename or logicaldatabasename. This results in the new tailored support library titled as follows:
OBJECT/DATABRIDGE/SUPPORT/databasename
— or —
OBJECT/DATABRIDGE/SUPPORT/databasename/logicaldatabasename
These data set-specific layout tables contain the offsets and sizes of individual data items, including virtual data items.
Caution
If you have two databases with the same name under different usercodes, and you are running Databridge from a third usercode, be careful when you create a tailored support library. In this case, the second library you compile overwrites the first, because Databridge strips the usercode and pack name from the database name to create the tailored support library title.
-
Copy the virtual transform skeleton PATCH/DATABRIDGE/SAMPLE/SUPPORT/VIRTUAL as PATCH/DATABRIDGE/SUPPORT/transformname, where transformname is the name of the transform procedure.
-
Add your code to build virtual records in the sections of PATCH/DATABRIDGE/SUPPORT/transformname marked % TO DO: as follows:
-
(Optional) Study the declarations for the virtual dataset(s) in the Transform Layouts section of PATCH/DATABRIDGE/SUPPORT/databasename/GENGLOBALS.
If you declared any variables global to the transform procedure, initialize them in the InitializeVirtualTransform procedure, which is called the first time DBSupport calls the transform.
-
Write virtual data set transform routines as described in Writing a Virtual Data Set Transform Procedure.
-
-
Save your changes to PATCH/DATABRIDGE/SUPPORT/ transformname.
-
Compile DBSupport with the transform as follows:
- Declare the transform procedure in the DBGenFormat parameter file as shown in Syntax for Declaring a Transform.
- Save DATA/GENFORMAT/ databasename /CONTROL.
- Compile the tailored support library as instructed in step 9
-
Enter the name of the tailored support library and transform procedure in the appropriate Accessory parameter file, as follows:
For Do this Databridge Clients In the DBServer parameter file, enter the tailored support library name for the SUPPORT option and enter the name of the transform procedure for the TRANSFORM option.
For more information, refer to the Databridge Host Administrator's Guide.DBSpan or DBSnapshot In the DBSpan or DBSnapshot parameter file, enter the tailored support library name for the SUPPORT option and enter the transform name for the TRANSFORM option.
For more information, refer to the Databridge Host Administrator's Guide.
What to Do Next
Repeat these steps for each virtual data set you want to create.
Note
You can declare any number of virtual data sets but you must have exactly one transform that handles all of them.
You can now use your virtual data set by running your Databridge Accessories as usual. If you encounter problems when creating or compiling your virtual data set, see Troubleshooting for troubleshooting information.
The Troubleshooting chapter provides specific troubleshooting tips for writing virtual data set transform procedures and working with virtual data sets.
Syntax for Declaring a Transform
To declare a transform, use the following syntax in the DBGenFormat parameter file:
TRANSFORM transformname IN "patchfiletitle"
where transformname is the transform procedure that you declared, and patchfiletitle is the title of the ALGOL patch file containing the transform procedure that you created.
Syntax for Declaring a Virtual Data Set
Use the following syntax to declare a virtual data set. This syntax is taken from DATA/GENFORMAT/ SAMPLE/CONTROL.
VIRTUAL virtualdatasetname #strnum POPULATION estrecords DERIVED FROM
datasetlist
(
dataitem datatype;
.
.
.
dataitem datatype;
);
Where | Is |
---|---|
datasetlist | The names of one or more data sets from which the virtual data set obtains records. Use commas to separate multiple data set names (see Sample Virtual Data Set Declaration for an example that lists multiple data set names). |
virtualdatasetname | The name you want to give to the virtual data set. NOTE: Do not use the underscore character. |
#strnum | A structure number that you assign to this virtual data set. (The # symbol is required.) The structure number of the first virtual data set must be greater than the largest structurenumber assigned in the DMSII database. Before you select this number, however, allow room for adding more real structures to the database. For example, if the last structure number used in the DMSII database is 200, you might want to choose 400 as the structure number for the first virtual data set. This leaves room for you to add 199 new sets and data sets to the database. Once you choose a number for the first virtual data set, you can assign structure numbers one greater than the previous virtual data set. In this example, you would assign 400, 401, 402, and so on, to the virtual data sets. Structure numbers cannot exceed 4095. |
POPULATION estrecords | An optional, but highly recommended, clause where estrecords is the estimate of the number of records that appear in the data set during a clone. This estimate helps Databridge Accessories to allocate space appropriately. The default value is 1000000. |
DERIVED FROM dataset,… | Required. A list of the actual DMSII data sets from which you want to create your virtual data set. This declaration causes DBGenFormat to generate defines and variables in the GENGLOBALS patch that the transform can use to build virtual records. |
dataitem | The list of data items you want to be included in this virtual data set. Name the data items the same way you would for a DMSII data set. |
datatype | The DMSII data type for this data item. You may use the following data types:
|
Sample Virtual Data Set Declaration
The following sample is the DBGenFormat declaration for a virtual data set:
VIRTUAL ADDRESS #79 POPULATION 100000
DERIVED FROM BANK, CUSTOMER
(
ADDR-BANK-ID NUMBER (4);
ADDR-CUST-ID NUMBER (8);
ADDR-LINE-NBR NUMBER (1);
ADDR-LINE ALPHA (30);
);
Writing a Virtual Data Set Transform Procedure
This section provides additional information about writing a virtual data set transform procedure.
If you used the DERIVED FROM statement when you declared the virtual data set, you can use the
% Transform Layouts
section of PATCH/DATABRIDGE/SUPPORT/database/GENGLOBALS to build
the virtual data set records.
Note
Compare the virtual transform skeleton (Virtual Transform Skeleton) with the sample transform procedure (ALGOL Source for the Sample Virtual Transform Procedure) to see how the code you must supply relates to the % TO DO: sections you modify in the virtual transform skeleton.
Initializing the Virtual Record
Before copying data into the virtual data set record, the transform procedure must initialize the whole virtual data set record area to high values (all bits on) because this is the value Databridge uses to recognize NULL data items. The following example illustrates how to do so:
replace VRec8 by real (not false) for size (VRec8);
Constructing an UPDATE_INFO Array
Transform procedures construct a virtual record based on real DMSII records and other sources of information. However, the transform procedures must also construct an UPDATE_INFO array to reflect an update to the virtual data set rather than the original (real) record. This includes setting the structure index (UI_STRIDX), structure number (UI_STRNUM), record type (UI_RECTYPE), record size (UI_RECSZ_WORDS), format level (UI_FORMAT_LEVEL), record address (UI_AA), and parent record address (UI_PARENT_AA).
The record type and the parent record address for virtual data sets are always 0. The transform must construct the record address. If the transform builds only one virtual record for each DMSII record, it can use the UI_AA of the DMSII record as the UI_AA of the virtual record.
If you use the DERIVED FROM clause in the virtual data set declaration, you can use the following variables and defines from the GENGLOBALS patch file for the other words of UPDATE_INFO:
dataset_StrNum
dataset_RecWords
dataset_FmtLvl
dataset_StrIdx
Calling a COBOL Library
You can code transform procedures in ALGOL and have them call COBOL libraries that actually create the data for the virtual data sets.
If your transform procedure calls a COBOL formatting program that is compiled with $FEDLEVEL=5, then in the COBOL program's entry point declaration you must specify the ACTUALNAME to match the PROGRAM-ID name in the COBOL program where the library is invoked. For example, the sample COBOL program EXTRACTADDRESS has the following:
IDENTIFICATION DIVISION.
PROGRAM-ID. EXTRACTADDRESS.
The declaration of the COBOL program's entry point in the ALGOL formatting routine would look like the following:
procedure ExtractAddress (...);
library ExtractAddressLib (ACTUALNAME = "EXTRACTADDRESS");
See the declaration of EXTRACTADDRESS in the section marked "% Here's the COBOL program declaration" in ALGOL Source for the Sample Virtual Transform Procedure.
In addition, if you are using a COBOL 85 compiler, you must set the following compiler options:
$$ SET BINARY EXTENDED
$$ SET LIBRARYPROG = TRUE
$$ SET SHARING = DONTCARE
$$ SET TEMPORARY
Virtual Transform Skeleton
This is the ALGOL source code for the virtual transform skeleton, PATCH/DATABRIDGE/SAMPLE/SUPPORT/VIRTUAL. Follow the instructions in Writing a Virtual Data Set Transform Procedure to modify and use this file to create a virtual data set.
09000000
$ SET OMIT 09000100
------------------------------------------------------------------------
09000200
09000230
Module: PATCH/DATABRIDGE/SAMPLE/SUPPORT/VIRTUAL 09000240
09000250
Project: Databridge 09000260
09000270
Description: Databridge Sample VIRTUAL Transform skeleton 09000280
09000290
(c) Micro Focus or one of its affiliates. 09000390
09000530
------------------------------------------------------------------------
09000540
09002000
This is a sample skeleton patch to DBSupport for a virtual 09002100
transform routine. 09002200
09002300
It should be used in conjunction with the declarations in 09002400
PATCH/DATABRIDGE/SUPPORT/<database>/GENGLOBALS that 09002500
DBGenFormat generates when a VIRTUAL dataset is declared with 09002600
the DERIVED FROM ... syntax. These declarations follow the 09002700
comment line " % Transform Layouts" in that patch file. 09002800
09002900
Copy this file as PATCH/DATABRIDGE/SUPPORT/<database>/VIRTUAL
09003000
(or a name of your choosing). Add your code to build virtual 09003100
records in the sections marked "TO DO:" below. 09003200
09003300
Declare this file as a TRANSFORM in DBGenFormat, e.g., 09003400
09003500
TRANSFORM VirtualTransform 09003600
in "PATCH/DATABRIDGE/SUPPORT/<database>/VIRTUAL" 09003700
09003800
Modification history 09003900
-------------------- 09004000
09004100
Version 41.471 09004200
1 Initial release. 09004300
This is a sample skeleton patch to DBSupport for a virtual 09004400
transform routine. 09004500
09004600
End History 09004700
$ POP OMIT 09004800
70004900
70005000
%--------------------------------------------------------------------
70005100
70005200
boolean VirtualTransformInitialized; 70005300
70005400
DBMTYPE procedure InitializeVirtualTransform; 70005500
% -------------------------- 70005600
begin_proc [InitializeVirtualTransform] 70005700
70005800
% The following define will retrieve the structure index values
70005900
% for the virtual datasets. 70006000
70006100
VirtualTransformSetup; 70006200
70006300
% TO DO: 70006400
% Initialize user-defined variables 70006500
70006600
70006700
VirtualTransformInitialized := true; 70006800
end_proc [InitializeVirtualTransform]; 70006900
70007000
70007100
% DBTransform-type routine 70007200
70007300
DBTransformHead [VirtualTransform]; 70007400
% ---------------- 70007500
begin_proc [VirtualTransform] 70007600
70007700
% VirtualTransform will pass the original and generated 70007800
% records to the formatting routine (DBFormat). 70007900
70008000
boolean FormatResult; 70008100
DBMTYPE DBMResult; 70008200
70008300
integer DSStrNum; % structure number of original dataset 70008400
70008500
define ReturnIfNoVirtuals = 70008600
% ------------------ 70008700
if ^ IsBase (DSStrNum) then 70008800
begin % no virtuals derived from this dataset 70008900
return (DBM_OK); 70009000
end #; 70009100
70009200
% array VRec [0 : ??]; % virtual record work area 70009300
% 70009400
% EBCDIC array 70009500
% VRec8 [0] = VRec; 70009600
% HEX array 70009700
% VRec4 [0] = VRec; 70009800
70009900
procedure BuildVirtual (DSRec); 70010000
% ------------ 70010100
array DSRec [0]; % original dataset record 70010200
70010300
begin 70010400
EBCDIC array 70010500
DSRec8 [0] = DSRec; 70010600
HEX array 70010700
DSRec4 [0] = DSRec; 70010800
70010900
% TO DO: 70011000
% Use DSStrNum to determine the original 70011100
% dataset, e.g., 70011200
% 70011300
% if DSStrNum = <dataset>_StrNum then 70011400
% ... 70011500
% 70011600
% and then build the virtual record(s) 70011700
% using the DSRec of the original dataset record. 70011800
% For each virtual record you want to send, use 70011900
% the <virtualdataset>_Send define, e.g., 70012000
% 70012100
% <virtualdataset>_Send (<virtualrecord>); 70012200
% 70012300
% which will take care of setting up the 70012400
% UpdateInfo for the virtual dataset and 70012500
% actually calling the formatting routine. 70012600
70012700
70012800
end BuildVirtual; 70012900
70013000
70013100
if ^ VirtualTransformInitialized then 70013200
begin 70013300
return_if_error (InitializeVirtualTransform); 70013400
end; 70013500
70013600
DSStrNum := UI [UI_STRNUM]; 70013700
70013800
% Send the original record first and then build the 70013900
% virtual records. 70014000
70014100
case UpdateType of 70014200
begin 70014300
DBV_CREATE: 70014400
% first, AI of original 70014500
70014600
ReturnIfFormatError (AI); 70014700
70014800
% now AI of virtuals 70014900
70015000
ReturnIfNoVirtuals; 70015100
BuildVirtual (AI); 70015200
70015300
DBV_MODIFY: 70015400
if UI [UI_BI_AI] = 1 then 70015500
begin 70015600
% first, BI-AI of original 70015700
70015800
UpdateType := DBV_MODIFY_BEFORE_IMAGE; 70015900
ReturnIfFormatError (BI); 70016000
70016100
UpdateType := DBV_MODIFY_AFTER_IMAGE; 70016200
ReturnIfFormatError (AI); 70016300
70016400
% now BI-AI of virtuals 70016500
70016600
ReturnIfNoVirtuals; 70016700
70016800
UpdateType := DBV_MODIFY_BEFORE_IMAGE; 70016900
BuildVirtual (BI); 70017000
UpdateType := DBV_MODIFY_AFTER_IMAGE; 70017100
BuildVirtual (AI); 70017200
end 70017300
else 70017400
begin 70017500
% first, AI of original 70017600
70017700
ReturnIfFormatError (AI); 70017800
70017900
% now AI of virtuals 70018000
70018100
ReturnIfNoVirtuals; 70018200
70018300
BuildVirtual (AI); 70018400
end; 70018500
70018600
DBV_DELETE: 70018700
% first, BI of original 70018800
70018900
ReturnIfFormatError (BI); 70019000
70019100
% now BI of virtuals 70019200
70019300
ReturnIfNoVirtuals; 70019400
70019500
BuildVirtual (BI); 70019600
70019700
DBV_STATE: 70019800
% Since the Engine will send a StateInfo 70019900
% for the virtual dataset separately, we 70020000
% don't need to create one here. 70020100
70020200
ReturnIfFormatError (AI); 70020300
70020400
else: 70020500
ReturnIfFormatError (AI); 70020600
end UpdateType; 70020700
70020800
70020900
return (DBM_OK); 70021000
end_proc [VirtualTransform]; 70021100
70021200
% End of VirtualTransform transform patch 70021300
70021400
Sample ALGOL Virtual Transform Procedure
The sample in this section shows how to create a virtual data set called ADDRESS from data sets called BANK and CUSTOMER, which are part of the BANKDB database.
To illustrate how to create the ADDRESS virtual data set, this section provides the following:
- The various declarations you must make for the ADDRESS virtual data set, such as the declarations in the DBGenFormat parameter file
- A sample virtual transform procedure (modified transform skeleton), PATCH/DATABRIDGE/SAMPLE/SUPPORT/FORMATADDRESS, containing code to populate the ADDRESS virtual data set from the BANK and CUSTOMER data sets
Description
The FORMATADDRESS patch file contains a transform procedure called VirtualAddress that determines if the current record is from either the BANK or CUSTOMER data sets. When the transform procedure finds a BANK or CUSTOMER record, it calls a COBOL library, OBJECT/ DATABRIDGE/SAMPLE/EXTRACTADDRESS, to extract the address information. Then, the transform procedure puts the data into the ADDRESS virtual data set. Finally, the transform procedure creates the UPDATE_INFO array for the ADDRESS virtual data set.
The source code for the COBOL library, EXTRACTADDRESS (OBJECT/DATABRIDGE/SAMPLE/ EXTRACTADDRESS) is shown in Sample COBOL Library.
Sample DASDL Definition
The following sample shows the DASDL information for the BANK and CUSTOMER data sets:
BANK DATASET
(
BANK-ID NUMBER (4) NULL IS 0;
BANK-NAME ALPHA (30) NULL IS "NO NAME";
BANK-ADDR1 ALPHA (30) NULL IS "N/A ";
BANK-ADDR2 ALPHA (10);
BANK-ADDR3 ALPHA (30);
BANK-ROUTE NUMBER (9) NULL IS 999;
TS REAL;
);
.
.
.
CUSTOMER COMPACT DATASET
(
CUST-ID NUMBER(8);
BANK-ID NUMBER(4);
CUST-SSN NUMBER(9);
CUST-NAME ALPHA (30) SIZE VARYING;
CUST-LINES NUMBER(1);
CUST-ADDR ALPHA (30) OCCURS 5 TIMES
DEPENDING ON CUST-LINES;
CUST-DOB NUMBER(8) STORED OPTIONALLY;
CUST-INFO ALPHA (100) SIZE VARYING;
TS REAL;
);
.
.
.
DBGenFormat Parameter File Declarations
The DBGenFormat parameter file for the BANKDB database (DATA/GENFORMAT/BANKDB/CONTROL) contains the following VIRTUAL and TRANSFORM declarations:
VIRTUAL ADDRESS #79 POPULATION 100000
DERIVED FROM BANK, CUSTOMER
(
ADDR-BANK-ID NUMBER (4);
ADDR-CUST-ID NUMBER (8);
ADDR-LINE-NBR NUMBER (1);
ADDR-LINE ALPHA (30);
);
KEY ADDRESS (ADDR-BANK-ID, ADDR-CUST-ID, ADDR-LINE-NBR);
TRANSFORM VIRTUALADDRESS
IN "PATCH/DATABRIDGE/SAMPLE/SUPPORT/FORMATADDRESS"
These declarations correspond to steps 3-5 in Creating a Virtual Data Set.
Accessory Parameter File Declarations
The appropriate Accessory parameter file, such as the DBServer parameter file (DATA/SERVER/ CONTROL), contains the following TRANSFORM declaration when you enter the name of the tailored support library:
SOURCE BANKDB:
DATABASE = DESCRIPTION/BANKDB ON DISK,
TRANSFORM = VIRTUALADDRESS,
FILTER = DBFILTER,
PREFILTERED = FALSE,
SUPPORT = OBJECT/DATABRIDGE/SUPPORT/BANKDB ON DISK
default;
This declaration corresponds to step 10 in Creating a Virtual Data Set.
GENGLOBALS Transform Layouts Section
In addition, when you make these particular VIRTUAL and TRANSFORM declarations in the DBGenFormat parameter file and compile a tailored support library, the % Transform Layouts section of PATCH/DATABRIDGE/SUPPORT/BANKDB/GENGLOBALS contains the following defines:
% Transform Layouts
% BANK
real BANK_StrIdx;
define
BANK_BANK_ID (Rec4) = Rec4 [0] #,
BANK_BANK_ID_sz = 4 #,
BANK_BANK_NAME (Rec8) = Rec8 [2] #,
BANK_BANK_NAME_sz = 30 #,
BANK_BANK_ADDR1 (Rec8) = Rec8 [32] #,
BANK_BANK_ADDR1_sz = 30 #,
BANK_BANK_ADDR2 (Rec8) = Rec8 [62] #,
BANK_BANK_ADDR2_sz = 10 #,
BANK_BANK_ADDR3 (Rec8) = Rec8 [72] #,
BANK_BANK_ADDR3_sz = 30 #,
BANK_BANK_ROUTE (Rec4) = Rec4 [204] #,
BANK_BANK_ROUTE_sz = 9 #,
BANK_TS (Rec8) = Rec8 [107] #,
BANK_TS_sz = 6 #,
BANK_StrNum = 10# ,
BANK_RecWords = 28# ,
BANK_FmtLvl = 6799# ,
BANK_RecBytes = 168# ;
% CUSTOMER
real CUSTOMER_StrIdx;
define
CUSTOMER_CUST_ID (Rec4) = Rec4 [0] #,
CUSTOMER_CUST_ID_sz = 8 #,
CUSTOMER_BANK_ID (Rec4) = Rec4 [8] #,
CUSTOMER_BANK_ID_sz = 4 #,
CUSTOMER_CUST_SSN (Rec4) = Rec4 [12] #,
CUSTOMER_CUST_SSN_sz = 9 #,
CUSTOMER_CUST_NAME (Rec8) = Rec8 [11] #,
CUSTOMER_CUST_NAME_sz = 30 #,
CUSTOMER_CUST_LINES (Rec4) = Rec4 [82] #,
CUSTOMER_CUST_LINES_sz = 1 #,
CUSTOMER_CUST_ADDR (Rec8, I1) = Rec8 [(84 + (I1-1)*60) div 2] #,
CUSTOMER_CUST_ADDR_sz = 30 #,
CUSTOMER_CUST_DOB (Rec4) = Rec4 [384] #,
CUSTOMER_CUST_DOB_sz = 8 #,
CUSTOMER_CUST_INFO (Rec8) = Rec8 [196] #,
CUSTOMER_CUST_INFO_sz = 100 #,
CUSTOMER_TS (Rec8) = Rec8 [296] #,
CUSTOMER_TS_sz = 6 #,
CUSTOMER_StrNum = 17# ,
CUSTOMER_RecWords = 51# ,
CUSTOMER_FmtLvl = 0# ,
CUSTOMER_RecBytes = 306# ;
% ADDRESS
real ADDRESS_StrIdx;
define
ADDRESS_ADDR_BANK_ID (Rec4) = Rec4 [0] #,
ADDRESS_ADDR_BANK_ID_sz = 4 #,
ADDRESS_ADDR_CUST_ID (Rec4) = Rec4 [4] #,
ADDRESS_ADDR_CUST_ID_sz = 8 #,
ADDRESS_ADDR_LINE_NBR (Rec4) = Rec4 [12] #,
ADDRESS_ADDR_LINE_NBR_sz = 1 #,
ADDRESS_ADDR_LINE (Rec8) = Rec8 [7] #,
ADDRESS_ADDR_LINE_sz = 30 #,
ADDRESS_StrNum = 79# ,
ADDRESS_RecWords = 7# ,
ADDRESS_FmtLvl = 25861# ,
ADDRESS_Send (VRec) =
VirtualSend (ADDRESS_StrNum, ADDRESS_StrIdx,
ADDRESS_RecWords, ADDRESS_FmtLvl, VRec) #,
ADDRESS_RecBytes = 42# ;
define VirtualTransformSetup =
begin
GetStrIdx (BANK_StrNum, 0, BANK_StrIdx);
GetStrIdx (CUSTOMER_StrNum, 0, CUSTOMER_StrIdx);
GetStrIdx (ADDRESS_StrNum, 0, ADDRESS_StrIdx);
end #;
define IsBase (StrNum) = (
if StrNum = 10 then true else
if StrNum = 17 then true else
false) #;
ALGOL Source for the Sample Virtual Transform Procedure
The ALGOL source code for PATCH/DATABRIDGE/SAMPLE/SUPPORT/FORMATADDRESS is as follows:
$ SET OMIT 09000000
-----------------------------------------------------------------------
09000100
09000400
Module: PATCH/DATABRIDGE/SAMPLE/SUPPORT/FORMATADDRESS 09000500
09000600
Project: Databridge 09000700
09000800
Description: Sample transform for VIRTUAL datasets 09000900
09001000
(c) Copyright 2021 Micro Focus or one of its affiliates. 09001100
09001200
------------------------------------------------------------------------
09001300
09001400
Example transform routine for VIRTUAL datasets. This is a patch
09002000
to SYMBOL/DATABRIDGE/SUPPORT and can be included by inserting
09002100
the following declaration in DATA/GENFORMAT/<database>/CONTROL:
09002200
09002300
TRANSFORM VIRTUALADDRESS 09002400
IN "PATCH/DATABRIDGE/SAMPLE/SUPPORT/FORMATADDRESS" 09002500
09002600
This transform routine illustrates how to populate a VIRTUAL 09002700
dataset from real dataset records. It extracts mailing
addresses 09002800
from BANK and CUSTOMER dataset records and puts them into a 09002900
VIRTUAL dataset called ADDRESS. 09003000
09003100
A COBOL program does the actual extraction of the address. The 09003200
transform routine below determines if the current record is 09003300
from either the BANK or CUSTOMER datasets, and if so, calls the 09003400
COBOL program to extract the address. 09003500
09003600
The BANKDB DASDL has these definitions for BANK and CUSTOMER: 09003700
09003800
BANK DATASET 09003900
( 09004000
BANK-ID NUMBER (4) NULL IS 0; 09004100
BANK-NAME ALPHA (30) NULL IS "NO NAME"; 09004200
BANK-ADDR1 ALPHA (30) NULL IS "N/A "; 09004300
BANK-ADDR2 ALPHA (10); 09004400
BANK-ADDR3 ALPHA (30); 09004500
BANK-ROUTE NUMBER (9) NULL IS 999; 09004600
TS REAL; 09004700
); 09004800
09004900
... 09005000
09005100
CUSTOMER COMPACT DATASET 09005200
( 09005300
CUST-ID NUMBER(8); 09005400
BANK-ID NUMBER(4); 09005500
CUST-SSN NUMBER(9); 09005600
CUST-NAME ALPHA (30) SIZE VARYING; 09005700
CUST-LINES NUMBER(1); 09005800
CUST-ADDR ALPHA (30) OCCURS 5 TIMES 09005900
DEPENDING ON CUST-LINES; 09006000
CUST-DOB NUMBER(8) STORED OPTIONALLY; 09006100
CUST-INFO ALPHA (100) SIZE VARYING; 09006200
TS REAL; 09006300
); 09006400
09006500
09006600
09006700
DATA/GENFORMAT/BANKDB/CONTROL has these declarations: 09006800
09006900
VIRTUAL ADDRESS #79 POPULATION 100000 09007000
DERIVED FROM BANK, CUSTOMER 09007100
09007200
(ADDR-BANK-ID NUMBER (4); 09007300
ADDR-CUST-ID NUMBER (8); 09007400
ADDR-LINE-NBR NUMBER (1); 09007500
ADDR-LINE ALPHA (30); 09007600
); 09007700
09007800
KEY ADDRESS (ADDR-BANK-ID, ADDR-CUST-ID, ADDR-LINE-NBR); 09007900
09008000
TRANSFORM VIRTUALADDRESS 09008100
IN "PATCH/DATABRIDGE/SAMPLE/SUPPORT/FORMATADDRESS" 09008200
09008300
And finally, DATA/SERVER/CONTROL has this declaration: 09008400
09008500
SOURCE BANKDB: 09008600
DATABASE = DESCRIPTION/BANKDB ON DISK, 09008700
TRANSFORM = VIRTUALADDRESS, 09008800
FILTER = DBFILTER, 09008900
PREFILTERED = FALSE, 09009000
SUPPORT = OBJECT/DATABRIDGE/SUPPORT/BANKDB 09009100
ON DISK 09009200
default; 09009300
09009400
Notice that the TRANSFORM name matches the name of the routine 09009500
below. 09009600
09009700
Modification history 09009800
-------------------- 09009900
09010000
Version 30.001 09010100
Initial release. 09010200
09010300
This is a patch to SYMBOL/DATABRIDGE/SUPPORT that illustrates
09010400
how to write a formatting routine to populate VIRTUAL datasets.
09010500
It calls a COBOL program to extract addresses from other 09010600
records. 09010700
09010800
Version 40.463 09010900
1 Changed the ADDRESS record size calculation to match the COBOL
09011000
record. 09011100
09011200
Version 41.471 09011300
1 Changed the routine from a FORMAT to a TRANSFORM. 09011400
09011500
The program SYMBOL/DATABRIDGE/SAMPLE/VIRTUALLIB has been 09011600
deimplemented in favor of this patch. 09011700
09011800
Version 41.484 09011900
2 The patch now uses the declarations generated in GENGLOBALS 09012000
when a VIRTUAL dataset is declared with the DERIVED FROM 09012100
syntax, such as, 09012200
ADDRESS_StrNum 09012300
ADDRESS_StrIdx 09012400
ADDRESS_RecWords 09012500
ADDRESS_FmtLvl 09012600
BANK_StrNum 09012700
CUSTOMER_StrNum 09012800
09012900
Version 50.491 09013000
1 The code to retrieve the ADDRESS structure index is now 09013100
deferred until the first BANK or CUSTOMER record is
encountered. 09013200
Previously, if the client did not select the BANK, CUSTOMER,
and 09013300
ADDRESS datasets, the transform would get an error when it
tried 09013400
to retrieve the structure index for ADDRESS when it received 09013500
the first record (from some other dataset). 09013600
09013700
Version 50.504 09013800
2 This transform will now tolerate the situation where the BANK 09013900
and/or CUSTOMER datasets are selected but not the virtual 09014000
ADDRESS is not. In such a case, the transform will not try to 09014100
extract any addresses and will simply send the (real) dataset 09014200
updates. 09014300
09014400
End History 09014500
$ POP OMIT 09014600
70000000
% Here's the COBOL program declaration. 70000100
70000200
library ExtractAddressLib 70000300
(title = "OBJECT/DATABRIDGE/SAMPLE/EXTRACTADDRESS."); 70000400
70000500
procedure ExtractAddress (WhichDS, DSRecord, NumAddrRecs, AddressRecs);
70000600
% -------------- 70000700
70000800
% COBOL program that can extract addresses 70000900
% from BANK and CUSTOMER 70001000
70001100
value WhichDS; 70001200
integer WhichDS; % Input: Which dataset? (See below) 70001300
ebcdic array 70001400
DSRecord [0]; % Input: record from audit trail 70001500
integer NumAddrRecs; % Output: number of addresses generated 70001600
ebcdic array 70001700
AddressRecs [0];% Output: generated address records 70001800
70001900
library ExtractAddressLib 70002000
70002100
% if the COBOL program is compiled with $ FEDLEVEL = 5 70002200
% then change "PROCEDUREDIVISION" to the value of the 70002300
% PROGRAM-ID in the program 70002400
70002500
(ACTUALNAME = "PROCEDUREDIVISION"); 70002600
70002700
%--------------------------------------------------------------------
70002800
70002900
% WhichDS values 70003000
define ItIsBank = 1#, 70003100
ItIsCust = 2#; 70003200
70003300
boolean VAInitialized; 70003400
70003500
integer AddrRecBytes; % size of ADDRESS record in bytes 70003600
define MaxAddressRecs = 10#; % max number of ADDRESS records in 70003700
% AddressRecs 70003800
70003900
ebcdic array 70004000
AddressRecs [0:0]; % output ADDRESS records 70004100
70004200
array AddressRec [0:0]; % single ADDRESS record to send 70004300
70004400
interlock 70004500
AddressLock; 70004600
70004700
DBMTYPE procedure InitializeVA; 70004800
% ------------ 70004900
begin_proc [InitializeVA] 70005000
DBStrIdx (ADDRESS_StrNum, 0, ADDRESS_StrIdx); 70005100
70005200
% We need the size of the record that the COBOL 70005300
% program actually uses. The easiest thing to do is to hard- 70005400
% code the size... 70005500
70005600
AddrRecBytes := 37; 70005700
70005800
resize (AddressRecs, MaxAddressRecs * AddrRecBytes); 70005900
resize (AddressRec, ADDRESS_RecWords); 70006000
70006100
VAInitialized := true; 70006200
end_proc [InitializeVA]; 70006300
70006400
70006500
% DBTransform-type routine 70006600
70006700
DBTransformHead [VirtualAddress]; 70006800
% -------------- 70006900
begin_proc [VirtualAddress] 70007000
70007100
% VirtualAddress will pass the original and generated 70007200
% records to the formatting routine (DBFormat). 70007300
ebcdic array 70007500
BI01 [0] = BI; % dataset record before-image 70007600
ebcdic array 70007700
AI01 [0] = AI; % dataset record after-image 70007800
pointer pAddress; % points to an address 70007900
boolean FormatResult; 70008000
DBMTYPE DBMResult; 70008100
70008200
procedure GetAddresses (StrNum, Image01); 70008300
% ------------ 70008400
value StrNum; 70008500
integer StrNum; 70008600
ebcdic array 70008700
Image01 [0]; 70008800
70008900
begin 70009000
integer NumAddresses; % number of addresses found 70009100
70009200
% look for any addresses 70009300
if StrNum = BANK_StrNum then 70009400
begin 70009500
if ^ VAInitialized then 70009600
begin 70009700
return_if_error (InitializeVA); 70009800
end; 70009900
70010000
if ADDRESS_StrIdx > 0 then 70010100
begin 70010200
ExtractAddress (ItIsBank, Image01, 70010300
NumAddresses, 70010400
AddressRecs); 70010500
end; 70010600
70010700
end 70010800
else 70010900
if StrNum = CUSTOMER_StrNum then 70011000
begin 70011100
if ^ VAInitialized then 70011200
begin 70011300
return_if_error (InitializeVA); 70011400
end; 70011500
70011600
if ADDRESS_StrIdx > 0 then 70011700
begin 70011800
ExtractAddress (ItIsCust, Image01, 70011900
NumAddresses, 70012000
AddressRecs); 70012100
end; 70012200
70012300
end; 70012400
70012500
if NumAddresses > 0 then % found some addresses 70012600
begin 70012700
% set up the UI for ADDRESS records 70012800
70012900
UI [UI_STRNUM] := ADDRESS_StrNum; 70013000
UI [UI_RECTYPE] := 0; 70013100
UI [UI_STRIDX] := ADDRESS_StrIdx; 70013200
UI [UI_RECSZ_WORDS] := ADDRESS_RecWords; 70013300
UI [UI_FORMAT_LEVEL] := ADDRESS_FmtLvl; 70013400
UI [UI_AA] := 0; 70013500
UI [UI_PARENT_AA] := 0; 70013600
70013700
% send each virtual ADDRESS record 70013800
70013900
pAddress := AddressRecs; 70014000
while NumAddresses > 0 do 70014100
begin 70014200
replace pointer (AddressRec) by 70014300
pAddress : pAddress 70014400
for AddrRecBytes; 70014500
70014600
NumAddresses := * - 1; 70014700
ReturnIfFormatError (AddressRec); 70014800
end; 70014900
end; 70015000
70015100
end GetAddresses; 70015200
70015300
70015400
integer OrigStrNum; 70015500
70015600
% Since we use global arrays we have to single-thread. 70015700
epilog procedure ExitFormat; 70015800
begin 70015900
unlock (AddressLock); 70016000
end; 70016100
70016200
lock (AddressLock); 70016300
70016400
OrigStrNum := UI [UI_STRNUM]; 70016500
70016600
% Send the original record first and then get the 70016700
% virtual address records. 70016800
70016900
case UpdateType of 70017000
begin 70017100
DBV_CREATE: 70017200
% first, AI of original 70017300
70017400
ReturnIfFormatError (AI); 70017500
70017600
% now AI of virtuals 70017700
70017800
GetAddresses (OrigStrNum, AI01); 70017900
70018000
DBV_MODIFY: 70018100
if UI [UI_BI_AI] = 1 then 70018200
begin 70018300
% first, BI-AI of original 70018400
70018500
UpdateType := 70018600
DBV_MODIFY_BEFORE_IMAGE; 70018700
ReturnIfFormatError (BI); 70018800
70018900
UpdateType := 70019000
DBV_MODIFY_AFTER_IMAGE; 70019100
ReturnIfFormatError (AI); 70019200
70019300
% now BI-AI of virtuals 70019400
70019500
UpdateType := 70019600
DBV_MODIFY_BEFORE_IMAGE; 70019700
GetAddresses (OrigStrNum, BI01); 70019800
UpdateType := 70019900
DBV_MODIFY_AFTER_IMAGE; 70020000
GetAddresses (OrigStrNum, AI01); 70020100
end 70020200
else 70020300
begin 70020400
% first, AI of original 70020500
70020600
ReturnIfFormatError (AI); 70020700
70020800
% now AI of virtuals 70020900
70021000
GetAddresses (OrigStrNum, AI01); 70021100
end; 70021200
70021300
DBV_DELETE: 70021400
% first, BI of original 70021500
70021600
ReturnIfFormatError (BI); 70021700
70021800
% now BI of virtuals 70021900
70022000
GetAddresses (OrigStrNum, BI01); 70022100
70022200
DBV_STATE: 70022300
% Since the Engine will send a StateInfo 70022400
% for the virtual dataset separately, we 70022500
% don't need to create one here. 70022600
70022700
ReturnIfFormatError (AI); 70022800
70022900
else: 70023000
ReturnIfFormatError (AI); 70023100
end UpdateType; 70023200
70023300
70023400
return (DBM_OK); 70023500
end_proc [VirtualAddress]; 70023600
70023700
% End of VirtualAddress transform patch 70023800
70023900
Sample COBOL Library
This sample library, EXTRACTADDRESS, extracts the address from individual BANK and CUSTOMER data set records and returns them to the transform procedure (VirtualAddress).
The transform procedure in the previous example calls this library.
Note
COBOL libraries called by virtual data set transform procedures can be affected by DMSII reorganizations. For more information on how COBOL libraries may be affected, see DMSII Reorganizations.
The source code (SYMBOL/DATABRIDGE/SAMPLE/EXTRACTADDRESS) for this sample is shown as follows:
000100
000200$$ SET BINARYEXTENDED
00
000300$$ SET LIBRARYPROG = TRUE
00
000400$$ SET SHARING = DONTCARE
00
000500$$ SET TEMPORARY 00
000600 00
000700 IDENTIFICATION DIVISION.
00
000800 PROGRAM-ID. EXTRACTADDRESS.
00
000900 00
001000$$ set omit
001010------------------------------------------------------------------
001020
001040
001050 Module: SYMBOL/DATABRIDGE/SAMPLE/EXTRACTADDRESS
001060
001070 Project: Databridge
001080
001090 Description: Databridge ExtractAddress Library Program
001100
001200 (c) Copyright 2019 Micro Focus or one of its affiliates.
001340
001350------------------------------------------------------------------
001360$$ pop omit
003000* This is an example library program to demonstrate how
00
003100* to extract mailing addresses from dataset records and
00
003200* use them to populate a VIRTUAL dataset using Databridge.
00
003300* 00
003400 00
003500 ENVIRONMENT DIVISION.
00
003600 00
003700 DATA DIVISION. 00
003800 DATA-BASE SECTION. 00
003900 00
004000* We won't really access the DMSII database but we
00
004100* want to use the 01s for the record layouts of the
00
004200* records we will receive.
00
004300 00
004400 DB BANKDB. 00
004500 01 BANK. 00
004600 01 CUSTOMER. 00
004700 00
004800 WORKING-STORAGE SECTION.
00
004900 00
005000 77 WS-INITIALIZE PIC 9(01) BINARY.
00
005100 88 INITIALIZED VALUE 1.
00
005200 00
005300 77 I PIC 9(10) BINARY.
00
005400 00
005500* Length of the DMSII records (in bytes).
00
005600 00
005700 77 BANK-REC-CHARS PIC 9(06) BINARY.
00
005800 77 CUST-REC-CHARS PIC 9(06) BINARY.
00
005900 00
006000 00
006100 LINKAGE SECTION. 00
006200* Parameters passed from the formatting routine.
00
006300 00
006400* DMSII structure number of the input record.
00
006500 00
006600 77 WHICH-DATASET PIC 9(4) BINARY.
00
006700 88 BANK-DATASET VALUE 1.
00
006800 88 CUST-DATASET VALUE 2.
00
006900 00
007000* Record received from DMSII database.
00
007100* Should be either from the BANK or CUSTOMER dataset.
00
007200 00
007300 01 DB-RECORD. 00
007400 03 DB-REC-WORD PIC S9(11) BINARY
00
007500 00
007600* The OCCURS value must make this record as large
00
007700* or larger than the actual dataset record received.
00
007800 00
007900 OCCURS 56. 00
008000 00
008100* The following is the number of VIRTUAL ADDRESS records
00
008200* returned. 00
008300 00
008400 77 VIRTUAL-REC-COUNT PIC 9(11) BINARY.
00
008500 00
008600* Here is where we build the VIRTUAL ADDRESS records.
00
008700 00
008800 01 VIRTUAL-RECS. 00
008900 02 ADDRESS-REC OCCURS 10.
00
009000 03 ADDR-BANK-ID PIC 9(4) COMP.
00
009100 03 ADDR-CUST-ID PIC 9(8) COMP.
00
009200 03 ADDR-LINE-NBR PIC 9(1) COMP.
00
009300 03 ADDR-LINE PIC X(30) DISPLAY.
00
009400 00
009500 PROCEDURE DIVISION USING WHICH-DATASET
00
009600 DB-RECORD 00
009700 VIRTUAL-REC-COUNT 00
009800 VIRTUAL-RECS. 00
009900 THE-ONLY SECTION. 00
010000 GET-STARTED. 00
010100 00
010200 IF NOT INITIALIZED 00
010300 PERFORM INITIALIZE-WS.
00
010400 00
010500 MOVE HIGH-VALUES TO VIRTUAL-RECS.
00
010600 00
010700* Determine which dataset this record is from.
00
010800 00
010900 IF BANK-DATASET 00
011000 PERFORM BANK-ADDRESS
00
011100 ELSE 00
011200 IF CUST-DATASET 00
011300 PERFORM CUST-ADDRESS
00
011400 ELSE 00
011500* Unrecognized dataset ...
00
011600 MOVE 0 TO VIRTUAL-REC-COUNT.
00
011700 00
011800 EXIT PROGRAM. 00
011900 00
012000 INITIALIZE-WS. 00
012100 00
012200* Determine the size of the dataset records.
00
012300 00
012400 COMPUTE BANK-REC-CHARS =
00
012500 FUNCTION FORMATTED-SIZE (BANK).
00
012600 COMPUTE CUST-REC-CHARS =
00
012700 FUNCTION FORMATTED-SIZE (CUSTOMER).
00
012800 MOVE 1 TO WS-INITIALIZE.
00
012900 00
013000 BANK-ADDRESS. 00
013100 00
013200* Move the database record into the BANK user work area so
00
013300* that we can reference individual data items.
00
013400 00
013500 UNSTRING DB-RECORD INTO BANK
00
013600 FOR BANK-REC-CHARS.
00
013700 00
013800* The address lines in the BANK dataset are in 3 separate
00
013900* data items: BANK-ADDR1, BANK-ADDR2, and BANK-ADDR3.
00
014000 00
014100 MOVE BANK-ID OF BANK TO ADDR-BANK-ID (1).
00
014200 MOVE 0 TO ADDR-CUST-ID (1).
00
014300 MOVE 1 TO ADDR-LINE-NBR (1).
00
014400 MOVE BANK-ADDR1 TO ADDR-LINE (1).
00
014500 00
014600 MOVE BANK-ID OF BANK TO ADDR-BANK-ID (2).
00
014700 MOVE 0 TO ADDR-CUST-ID (2).
00
014800 MOVE 2 TO ADDR-LINE-NBR (2).
00
014900 MOVE BANK-ADDR2 TO ADDR-LINE (2).
00
015000 00
015100 MOVE BANK-ID OF BANK TO ADDR-BANK-ID (3).
00
015200 MOVE 0 TO ADDR-CUST-ID (3).
00
015300 MOVE 3 TO ADDR-LINE-NBR (3).
00
015400 MOVE BANK-ADDR3 TO ADDR-LINE (3).
00
015500 00
015600 MOVE 3 TO VIRTUAL-REC-COUNT.
00
015700 00
015800 CUST-ADDRESS. 00
015900 00
016000* Move the database record into the CUSTOMER user work area so
00
016100* that we can reference individual data items.
00
016200 00
016300 UNSTRING DB-RECORD INTO CUSTOMER
00
016400 FOR CUST-REC-CHARS.
00
016500 00
016600 IF CUST-LINES > 5 00
016700 MOVE 5 TO CUST-LINES.
00
016800 PERFORM MOVE-CUST-ADDR
00
016900 VARYING I FROM 1 BY 1 00
017000 UNTIL I > CUST-LINES.
00
017100 MOVE CUST-LINES TO VIRTUAL-REC-COUNT.
00
017200 00
017300 MOVE-CUST-ADDR. 00
017400 MOVE BANK-ID OF CUSTOMER TO ADDR-BANK-ID (I).
00
017500 MOVE CUST-ID TO ADDR-CUST-ID (I).
00
017600 MOVE I TO ADDR-LINE-NBR (I).
00
017700 MOVE CUST-ADDR (I) TO ADDR-LINE (I).
00
017800$$ VERSION 61.532.0000
00