Created On:  25 March 2011

Problem:

How can I split a data file into several equal parts, without using SPLIT1R ?

Resolution:

The MicroFocus emulation of DFSORT does not currently (as at SEE 6.0 SP2) support the OUTREC option SPLIT1R, but there is a workaround.

The effect of SPLIT1R=nnn is to split the input data across a number of output datasets, placing nnn records in each dataset, with the last dataset in the group receiving any remaining records.
So, for example, if 4 datasets are specifed using OUTFIL FNAMES=(OUT1,OUT2,OUT3,OUT4), and SPLIT1R=2 is coded, then the first 2 records will be written to OUT1, records 3 and 4 to OUT2, records 5 and 6 to OUT3, and the remaining records to OUT4.

The customer's requirement was to split a file of unknown size into 4 equal subsets, maintaining the original record sequence, and placing any extra records (i.e. the 1 to 3 records remaining after 4 equal subsets have been created) in the 4th dataset.

Their orginal job achieved this on the mainframe using ICETOOL, and SPLIT1R:

//METHOD1 EXEC PGM=ICETOOL
//TOOLMSG  DD SYSOUT=*
//DFSMSG   DD SYSOUT=*
//IN       DD DSN=MYDATA.SORTIN,DISP=SHR
//T1       DD DSN=&&T1,SPACE=(TRK,(1,1)),DISP=(,PASS)
//C1       DD DSN=&&C1,SPACE=(TRK,(1,1)),DISP=(,PASS)
//TOOLIN DD *
 COPY FROM(IN) USING(CTL1)
 COPY FROM(T1) TO(C1) USING(CTL2)
 COPY FROM(IN) USING(CTL3)
/*
//CTL1CNTL DD *                     
  OUTFIL FNAMES=T1,REMOVECC,NODETAIL,
    TRAILER1=(COUNT=(M11,LENGTH=8))       <<== Create one record containing a count of the input data records
/*
//CTL2CNTL DD *                      
  OUTREC BUILD=(2X,C'  SPLIT1R=',         <<== Generate a SPLIT1R=nnn control statement, where nnn = count/4
    1,8,ZD,DIV, 04,TO=ZD,LENGTH=8,80:X)
/*
//CTL3CNTL DD *                      
  OUTFIL FNAMES=(OUT1,OUT2,OUT3,OUT4),    <<== Split the data across 4 files
//         DD DSN=*.C1,DISP=(OLD,PASS)    <<==  using the SPLIT1R=nnn control statement created above
//*
//OUT1    DD DSN=MFDATA.OUTPUT.PART1,DISP=(,CATLG),SPACE=(TRK,1)
//OUT2    DD DSN=MFDATA.OUTPUT.PART2,DISP=(,CATLG),SPACE=(TRK,1)
//OUT3    DD DSN=MFDATA.OUTPUT.PART3,DISP=(,CATLG),SPACE=(TRK,1)
//OUT4    DD DSN=MFDATA.OUTPUT.PART4,DISP=(,CATLG),SPACE=(TRK,1)


The workaround for this was to use ICETOOL to create control statements for IDCAMS, which would then perform the data splitting, using the COUNT and SKIP options to control the placement of data records into the 4 output files:-

//METHOD2 EXEC PGM=ICETOOL
//TOOLMSG  DD SYSOUT=*
//DFSMSG   DD SYSOUT=*
//IN       DD DSN=MYDATA.SORTIN,DISP=SHR
//T1       DD DSN=&&T1,UNIT=SYSDA,SPACE=(TRK,(1,1)),DISP=(,PASS)
//U1       DD DSN=&&U1,UNIT=SYSDA,SPACE=(TRK,(1,1)),DISP=(MOD,PASS)
//V1       DD DSN=&&V1,UNIT=SYSDA,SPACE=(TRK,(1,1)),DISP=(,PASS)
//C1       DD DSN=&&C1,UNIT=SYSDA,SPACE=(TRK,(1,1)),DISP=(MOD,PASS)
//TOOLIN DD *
 COPY FROM(IN) TO(T1) USING(CTL1)
 COPY FROM(T1) TO(U1) USING(CTL2)
 COPY FROM(T1) TO(U1) USING(CTL3)
 COPY FROM(T1) TO(U1) USING(CTL4)
 COPY FROM(U1) TO(V1) USING(CTL5)
 COPY FROM(V1) TO(C1) USING(CTL6)
 COPY FROM(V1) TO(C1) USING(CTL7)
 COPY FROM(V1) TO(C1) USING(CTL8)
 COPY FROM(V1) TO(C1) USING(CTL9)
/*
//CTL1CNTL DD *
  SORT  FIELDS=(1,1,CH,A)       <<== Dummy SORT to allow the use of SUM
  INREC FIELDS=(C' 00000025')   <<== Set up input field of 1/4
  SUM FIELDS=(2,8,ZD)           <<== Generate a count/4 field: nnn
/*
//CTL2CNTL DD *
  INREC FIELDS=(C' 000000000000',2,6) <<== Generate 3 count fields: zero, zero, nnn
/*
//CTL3CNTL DD *
  INREC FIELDS=(C' 000000',2,6,2,6)   <<== Generate 3 count fields: zero, nnn, nnn
/*
//CTL4CNTL DD *
  INREC FIELDS=(C' ',2,6,2,6,2,6)     <<== Generate 3 count fields: nnn, nnn, nnn
/*
//CTL5CNTL DD *
  SORT  FIELDS=(1,1,CH,A)             <<== Dummy SORT to allow the use of SUM
  SUM FIELDS=(2,6,ZD,8,6,ZD,14,6,ZD)  <<== Generate 3 count fields: nnn, nnn * 2, nnn * 3
/*
//CTL6CNTL DD *
  OUTREC FIELDS=(2X,C'REPRO INFILE(IN) OUTFILE(OUT1)'
                 C' COUNT(',2,4,C')',80:X)                <<== Generate "COUNT(nnn)"
/*
//CTL7CNTL DD *
  OUTREC FIELDS=(2X,C'REPRO INFILE(IN) OUTFILE(OUT2)'
                 C' COUNT(',2,4,C') SKIP(',2,4,C')',80:X) <<== Generate "COUNT(nnn) SKIP(nnn)"
/*
//CTL8CNTL DD *
  OUTREC FIELDS=(2X,C'REPRO INFILE(IN) OUTFILE(OUT3)'
                 C' COUNT(',2,4,C') SKIP(',8,4,C')',80:X) <<== Generate "COUNT(nnn) SKIP(nnn * 2)"
/*
//CTL9CNTL DD *
  OUTREC FIELDS=(2X,C'REPRO INFILE(IN) OUTFILE(OUT4) ',
                 C' SKIP(',14,4,C')',80:X)                <<== Generate "SKIP(nnn * 3)"
/*
//METHOD2B EXEC PGM=IDCAMS,COND=(0,NE)
//SYSPRINT DD SYSOUT=*,HOLD=Y
//SYSIN DD DSN=&&C1,DISP=(OLD,PASS)                       <<== Copy 4 subsets of data records
//IN       DD DSN=MFISVR.FLOWFILE.INPUT,DISP=SHR
//OUT1    DD DSN=MFDATA.OUTPUT.PART1,DISP=(,CATLG),SPACE=(TRK,1)
//OUT2    DD DSN=MFDATA.OUTPUT.PART2,DISP=(,CATLG),SPACE=(TRK,1)
//OUT3    DD DSN=MFDATA.OUTPUT.PART3,DISP=(,CATLG),SPACE=(TRK,1)
//OUT4    DD DSN=MFDATA.OUTPUT.PART4,DISP=(,CATLG),SPACE=(TRK,1)

Incident #2509247