Create
VSAM Cluster from Jazz Definition
Step
1. Selecting a Jazz Data Definition and
Defining the Basic Cluster
Step
2. Loading Initial Records
Step
3. Creating Alternate Indexes
This form is invoked from the menu [JazzGen] Data/VSAM. It is used to create a VSAM cluster from a VSAM file definition such as CustF.jzc. Options allow you to delete and recreate a previous cluster, and to create alternate indexes.
At first the form looks like this: -
Browse to the data definition in your Jazz CopyDefs folder. The object you select must be in this folder, and have type .jzc. It must be correctly defined with type VSAM, a field identified with property KEY, and it must have a defined DSNAME. For my zOS example I used a record definition “Orderx.jzc”, defined like this: -
COPY
Custf;
COPY
Parts ;
DEFINE
Orderx VSAM DATA(
OrdNbr DECIMAL(7) DPIC '9999999' KEY HEADING 'Order Number',
OrdCustId LIKE custf.account
DKEY 'ibmuser.vsam.Orderx1',
ordDate CHAR(12),
OrdPart LIKE parts.partnbr
DKEY 'ibmuser.vsam.Orderx2'
EXISTS Parts.Partnbr,
OrdQty SMALLINT,
OrdDiscount
DECIMAL (6,4) HEADING 'Order Discount',
OrdStatus CHAR(10))
DSNAME 'ibmuser.vsam.Orderx';
If you’re using this function with Test Environment = IDE (Jazz Configuration, Language tab), for example you’re using Micro Focus COBOL with Visual Studio, then there are minor differences in the appearance of this form. The [Submit] button has the name of your project instead of “Submit” as its caption, and there are other differences that are noted below. For my IDE example, I used definition
DEFINE OUTFLE VSAM DATA(
OUTNbr CHAR(3) PIC '999' KEY,
Rec CHAR(26) )
DSNAME 'JazzUsr.VSAM.OUTFLE';
On selecting the record definition further controls appear: -
Check one of the functions: -
· Cluster. Use this if the cluster doesn’t already exist.
· ReCreate Cluster. Use this if you wish to delete the cluster (including all its data) and start again. Note that if you want to retain the data you must have saved it to another file before you do this.
· AIX. Use this to create the alternate indexes and paths, and build the indexes. It is necessary to have at least one record in the file before the AIX’s are created, so in cases like Orderx with DKEY or UKEY fields creating the VSAM cluster definition is a two step process.
For Step1 you will choose Cluster unless you’re repeating the step. Choose ReCreate if you are.
Give the number of records for the primary and secondary extents. When you enter the 1ry extent Jazz will set the 2ry extent to 10% of this, but you can overtype this with another value if you wish.
If Test Environment = z/OS, you must give the volume name(s) for the VSAM data. Ask your systems programmer. For Test Environment = IDE this is optional.
With Test Environment = z/OS, normally you’ll leave Save JCL and Save Old Jobs unchecked to avoid clutter on your PC: -
· If Save JCL is checked then after the job has been submitted the JCL is NOT deleted from your LocalJCL folder.
· If Save Old Jobs is checked then previous jobs are NOT deleted when this latest one is returned.
These controls don’t appear with Test Environment = IDE
Now click [JCL]. Note: sometimes this button will have caption [Review] and clicking it will display the output of the previous job. Close the display and click it again (it will have changed back to [JCL]).
With Test Environment = z/OS the button will change to [Review] and the [Submit] button will be activated. You can review the job and edit it if you wish. With values like this: -
clicking [JCL] produced this job: -
//IBMUSERJ
JOB ,CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID,COND=(8,LT)
//JZVSAM1 EXEC PGM=IDCAMS Manage VSAM Data Sets
//SYSPRINT
DD SYSOUT=*
//SYSIN DD *
DELETE IBMUSER.VSAM.ORDERX CLUSTER
/*
//JZVSAM2 EXEC PGM=IDCAMS Manage VSAM Data Sets
//SYSPRINT
DD SYSOUT=*
//SYSIN DD *
DEFINE CLUSTER (NAME (IBMUSER.VSAM.ORDERX) -
RECORDS(1000 100) VOLUMES(VPWRKA) -
RECORDSIZE(42 42) KEYS(4 0) INDEXED)
/*
Click [Submit] The VSAM form is closed and Jazz submits a job to create or re-create the cluster.
With Test Environment = IDE, edit values for the number of 1ry and 2ry records, and click [JCL]. The VSAM form closes and you’re returned to the Jazz workbench. The [project] button (labelled [Job Results] for zOS) will be highlighted. Click this to open the COBOL project where you add the JCL to your project. It will have the name of the file, e.g. OUTFLE.jcl, and will look like this: -
//JAZZUSER JOB ,CLASS=A,MSGCLASS=A
//JZVSAM2 EXEC PGM=IDCAMS Manage VSAM Data
Sets
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
DEFINE CLUSTER (NAME (JAZZUSR.VSAM.OUTFLE) -
RECORDS(300 30) -
RECORDSIZE(29
29) KEYS(3 0) INDEXED)
/*
Once added to the project, you will see it in Solution Explorer, and be able to edit it if you wish. To submit it, right-click it in Solution Explorer and click the option “Submit JCL”. The job will run, and its output will be displayed on printer SYSPRINT: -
Micro Focus MFJAMS Utility
Version ED6.0_PU6
Copyright (C) Micro
Focus 1997-2020. All rights reserved.
DEFINE
CLUSTER (NAME (JAZZUSR.VSAM.OUTFLE) -
RECORDS(300 30) -
RECORDSIZE(29 29) KEYS(3 0) INDEXED)
JCLAM0113I(00) - ENTRYNAME DEFINED [JAZZUSR.VSAM.OUTFLE]
Once created as an empty cluster, the VSAM file must be used as a sequential output file until it has at least one record. Records must be loaded in ascending order of the primary key. This must be done before you can do any type of READ and UPDATE logic, including the creation of alternate indexes.
If you have an initial file that has exactly the correct record format and sequence then you may choose to load your initial records using the IDCAMS REPRO command. You can do this with Jazz by repeating the step above, and then editing the JCL to replace the IDCAMS control statements with a suitable REPRO. Don’t forget to remove the DELETE step if you generated one!
Or you can write your initial data from another file, with whatever changes you want, using Jazz. It’s very easy.
Choose the option [JazzGen]/Logic/New Batch Program, and set up a suitable program with the Copy To option. I have just created the cluster Orderx (IBMUSER.VSAM.ORDERX) based on the Jazz definition above. I have another file Orders that has the data that I want to copy into Orderx as its initial records. I create a program as follows: -
· The program name could be almost anything except Orders or Orderx.
· By naming the input file as Orders, basically the program is based on PROCESS Orders.
· Since I know that Orders is a VSAM file already sorted into order of OrdNbr, the primary key of both Orders and Orderx, I leave [ ] ORDER unchecked. If the input could not have been guaranteed to have been in the correct order than I would have checked [ ] ORDER to sort the input into the sequence that was needed.
· Similarly I want all records, so I don’t check [ ] WHERE
· By checking [P] PRINT I’ll print some data for every record
· In “Copy To” I name Orderx.
This will generate a program basically like this (plus some extra logic to report the number of records read and written): -
PROGRAM
GenOrdr BATCH;
COPY
orders;
COPY
orderx;
PROCESS
orders INDEX Copy-Stats.Input-Count;
PRINT
(Orders.?) ;
orderx.*=orders.*;
WRITE
orderx;
END
PROCESS orders;
A Select Data dialog appears to resolve Orders.? in the PRINT statement, and then this program appears: -
Normally we’d click [Process] and this program would be generated and run, producing a report and an output file. However with Orderx defined as above the program won’t run. The reason is that Orderx is defined with two DKEY fields. Normally Orderx requires three DD statements, and so Jazz generates JCL like this: -
//IBMUSERL
JOB
,CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID,COND=(8,LT)
//***
COMPILE BATCH PROGRAM or SUBPROGRAM
// SET MEMBER=GENORDR
// SET SOURCE=IBMUSER.MANAJAZZ.SRCLIB
// SET COPYLIB=IBMUSER.MANAJAZZ.CPYLIB
//COMPILE
EXEC IGYWCL
//COBOL.SYSIN DD
DSN=IBMUSER.MANAJAZZ.SRCLIB(GENORDR),DISP=SHR
//COBOL.SYSLIB DD DSN=IBMUSER.MANAJAZZ.CPYLIB,DISP=SHR
//LKED.SYSLIB
DD
// DD
// DD DSN=IBMUSER.MANAJAZZ.LOADLIB,DISP=SHR
//LKED.SYSLMOD DD DSN=IBMUSER.MANAJAZZ.LOADLIB(GENORDR),
// UNIT=,SPACE=,DISP=SHR
//***
Run (recently compiled) BATCH PROGRAM
//GO EXEC PGM=GENORDR
//STEPLIB DD DSN=IBMUSER.MANAJAZZ.LOADLIB,DISP=SHR
//SYSOUT DD SYSOUT=*
//SYSUDUMP
DD SYSOUT=*
//SORTLIB DD DSN=SYS1.SORTLIB,DISP=SHR
//SORTWK01
DD UNIT=SYSDA,SPACE=(CYL,(20,5))
//*
Inserted DD statements based on program
//CUSTF DD DSNAME=IBMUSER.VSAM.CUSTF,DISP=SHR
//CUSTF1 DD DSNAME=IBMUSER.VSAM.CUSTF1,DISP=SHR
//PARTS DD DSNAME=IBMUSER.VSAM.PARTS,DISP=SHR
//PARTS1 DD DSNAME=IBMUSER.VSAM.PARTS1,DISP=SHR
//ORDERS DD DSNAME=IBMUSER.VSAM.ORDERS,DISP=SHR
//ORDERS1 DD DSNAME=IBMUSER.VSAM.ORDERS1,DISP=SHR
//ORDERS2 DD DSNAME=IBMUSER.VSAM.ORDERS2,DISP=SHR
//ORDERX DD DSNAME=IBMUSER.VSAM.ORDERX,DISP=SHR
//ORDERX1 DD DSNAME=IBMUSER.VSAM.ORDERX1,DISP=SHR
//ORDERX2 DD DSNAME=IBMUSER.VSAM.ORDERX2,DISP=SHR
//REPORT1 DD SYSOUT=*
That would normally be correct, but at this stage it’s incorrect because we haven’t yet generated the alternate indexes, and there are no datasets with names IBMUSER.VSAM.ORDERX1 and IBMUSER.VSAM.ORDERX2. We remove the unwanted JCL statements: -
1. Right-click [Process]
2. Click [JCL]
3. Click [Review JCL] and edit to remove the two unwanted DD statements.
4. Click [Submit]
Now the job runs correctly, producing this report: -
Printed at 14 Feb 2017,
17:56:31 Report1 Page 1
Order Number Account
Number *--ordDate-* *--OrdPart---* *OrdQty *OrdStatus
0000000 000044 12 Jan 2001 443 1 Initial01
0000001 000044 12 Jan 2002 170 9 Initial02
0000002 000044 12 Jan 2003 296 7
Initial03
0000003 000044 12 Jan 2004 200 8 Initial04
0000004 000044 12 Jan 2005 496 0 Initial05
0000005 000021 12 Jan 2006 362 4 Initial06
0000006
000021 12 Jan 2007 260 8 Initial07
0000007 000021 12 Jan 2008 489 3 Initial08
0000008 000021 12 Jan 2009 290 1 Initial09
0000009 000021 12 Jan 2010 712
3 Initial10
0000010 000021 12 Jan 2011 970 1 Initial11
0000011 000021 12 Jan 2012 831 6 Initial12
0000012 000021 12 Jan 2013 290 10 Initial13
0000013 000021 12 Jan
2014 435 8 Initial14
0000014 000021 12 Jan 2015 222 5 Initial15
0000015 000021 12 Jan 2016 577 5 Initial16
0000016 000021 12 Jan 2017 951 5 Initial17
0000017 000021 12 Jan 2018 113 7 Initial18
0000018 000021 12 Jan 2019 617 10 Initial19
0000019 000021 12 Jan 2020 856 10 Initial20
0000020 000021 12 Jan 2021 442 1 Initial21
0000021 000021 12 Jan 2022 317 6 Initial22
0000022 000021 12 Jan 2023 587 4 Initial23
0000023
000021 12 Jan 2024 264 7 Initial24
0000024 000021 12 Jan 2025 267 9 Initial25
0000025 000021 12 Jan 2026 901 4 Initial26
0000026 000021 12 Jan 2027 302
1 Initial27
0000027 000021 12 Jan 2028 639 10 Initial28
0000028 000021 12 Jan 2029 18 2 Initial29
0000029 000021 12 Jan 2030 426 6 Initial30
0000030
000021 12 Jan 2031
457 2 Initial31
0000031 000021 12 Jan 2032 114 3 Initial32
0000032 000021 12 Jan 2033 112 5 Initial33
0000033 000021 12 Jan 2034 36 2 Initial34
0000034 000021 12 Jan 2035 39 5 Initial35
0000035 000021 12 Jan 2036 554 4 Initial36
0000036 000021 12 Jan 2037 936 3 Initial37
0000037 000024 12 Jan 2038 377 1 Initial38
0000038 000024 12 Jan 2039 605 5 Initial39
0000039 000024 12 Jan 2040 49 1 Initial40
0000040 000024 12 Jan 2041 507 1 Initial41
0000041 000024 4 0
* Field Name *
LENGTH VALUE
Copy-Stats.Input-Count
: 14* 42
Copy-Stats.Output-Count: 14* 42
The big advantages of this method are its simplicity and flexibility. In this case it was particularly easy because I had another file, Orders, with the same field names (although Orderx had only a subset of these fields), and the generic assignment, orderx.*=orders.*; was all that was needed. However I could easily have written different logic: -
· If the input file were not already in the correct order (or if I weren’t sure), I’d only have needed to add an ORDER clause to the PROCESS statement to ensure that the data was correctly sequenced. The input file doesn’t have to be VSAM: any file that can be read sequentially would have done.
· I don’t care if the fields have the same format: orderx.*=orders.* is only concerned with the field names and their compatibility. There would have been no problem if Orders.Account were one format of number and Orderx.Account were another. The generic assignment only moves fields with the same name – rather like MOVE CORRESPONDING in COBOL and BY NAME assignment in PL/I.
· If field names were different then I’d have replaced orderx.*=orders.*; with several individual assignment statements. If some names were the same and some were different I’d follow the generic assignment with individual assignments.
· I could easily have set output fields to calculated or constant values. This is particularly convenient when creating a test file.
· In the case above the input and output records were the same, so it doesn’t matter if you print data from the input or output records. If you’ve changed the data then you should change the PRINT to print data from the output file just before it’s written.
· Conditional logic such as WHERE or IF can be used to skip some records, or to terminate after writing N records.
· By adding GET statements the output record could contain data from related records. Conversely it is easy to write a program that will “normalise” a file by writing data from repeating groups into a separate file. You’d write a FOR loop within the PROCESS loop to write the “child” file from the repeating section.
· The above logic counts the input and output record, and with PRINT (Copy-Stats.*) FIELDTABLE; a very basic control report giving the count of records read and written is produced. Simply by adding more fields to the Copy-Stats definition and accumulating data into these fields the control report could include the total of any numeric field.
Now that we’ve put some data into Orderx we can complete its definition by defining the alternate indexes. You won’t need to do this if your file does not have any DKEY or UKEY fields.
Return to the VSAM function, setting the same values as before except that this time we choose option [P] AIX: -
This generates this job: -
//IBMUSERN
JOB
,CLASS=A,MSGCLASS=H,NOTIFY=&SYSUID,COND=(8,LT)
//JZVSAM3 EXEC PGM=IDCAMS Manage VSAM Data Sets
//SYSPRINT
DD SYSOUT=*
//SYSIN DD *
/* AIX ON FIELD ORDERX.ORDCUSTID */
DEFINE AIX (NAME(IBMUSER.VSAM.ORDERX1.AIX) -
RELATE(IBMUSER.VSAM.ORDERX) -
RECORDS(1000 100) VOLUMES(VPWRKA) -
KEYS(6 4) NONUNIQUEKEY UPGRADE REUSE)
DEFINE PATH(NAME(IBMUSER.VSAM.ORDERX1) -
PATHENTRY(IBMUSER.VSAM.ORDERX1.AIX)
UPDATE)
BLDINDEX INDATASET(IBMUSER.VSAM.ORDERX) -
OUTDATASET(IBMUSER.VSAM.ORDERX1.AIX)
/* AIX ON FIELD ORDERX.ORDPART */
DEFINE AIX (NAME(IBMUSER.VSAM.ORDERX2.AIX) -
RELATE(IBMUSER.VSAM.ORDERX) -
RECORDS(1000 100) VOLUMES(VPWRKA) -
KEYS(4 22) NONUNIQUEKEY UPGRADE REUSE)
DEFINE PATH(NAME(IBMUSER.VSAM.ORDERX2) -
PATHENTRY(IBMUSER.VSAM.ORDERX2.AIX)
UPDATE)
BLDINDEX INDATASET(IBMUSER.VSAM.ORDERX) -
OUTDATASET(IBMUSER.VSAM.ORDERX2.AIX)
/*
This created the alternate indexes and paths and built the indexes for Orderx.
If your file contains any UKEY indexes then the AIX will be created with UNIQUEKEY. In this case there is a potential error with this job stream if the data that you’ve loaded into the cluster in Step1 has non-unique values of this UKEY field.