MVSFORUMS.com Forum Index MVSFORUMS.com
A Community of and for MVS Professionals
 
 FAQFAQ   SearchSearch   Quick Manuals   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Inserting extra characters based on record type

 
Post new topic   Reply to topic   printer-friendly view    MVSFORUMS.com Forum Index -> Utilities
View previous topic :: View next topic  
Author Message
misi01
Advanced


Joined: 02 Dec 2002
Posts: 621
Topics: 173
Location: Stockholm, Sweden

PostPosted: Tue Sep 30, 2014 2:26 am    Post subject: Inserting extra characters based on record type Reply with quote

I am struggling with the following. I have my input file whereby I have first selected the first 50 records for each key in column 1 (just to make the file a manageable size).

Now I would like to insert extra characters in specific positions based on the value in column 1. Here's my attempt at the JCL

Code:

//* Input file is FB 567
//INA      DD DSN=MISI01.SARE.M716001.SMALL,DISP=SHR         
//*                                                         
//UTA      DD DSN=MISI01.SARE.M716001.EXPAND,DISP=(,CATLG), 
//         RECFM=FB,LRECL=570                               
//TOOLIN   DD   *                                                   
 SELECT FROM(INA) TO(UTA) ON(1,1,CH) FIRST(50) USING(CTL1)           
//*                                                                 
//CTL1CNTL DD *                                                     
* IF RECORD HAS '4' IN POSITION 1, ADD EQUIVALENT OF 3 PACKED ZEROES
* IN POSITIONS 196-198                                               
INREC IFTHEN=(WHEN=(1,1,CH,EQ,4),                                   
       BUILD=(1:195,X'0000',196:372)),                               
* IF RECORD HAS '5' IN POSITION 1, ADD EQUIVALENT OF 3 PACKED ZEROES
* IN POSITIONS 101-103                                               
IFTHEN=(WHEN=(1,1,CH,EQ,5),                                         
       BUILD=(1:101,X'0000',101:467))                               
/*                                                                   


The idea behind this is to insert x'0000' in position 196 if column 1 has a 4 and the same value in position 101 if column 1 has a 5.

Note that the tools used doesn't have to be ICETOOL. If DFSORT would do the job better/more easily, that's fine
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
misi01
Advanced


Joined: 02 Dec 2002
Posts: 621
Topics: 173
Location: Stockholm, Sweden

PostPosted: Tue Sep 30, 2014 3:06 am    Post subject: I figured it out (after much experimentation) Reply with quote

Here was the resulting JCL
Code:

//INA      DD DSN=MISI01.SARE.M716001.SMALL,DISP=SHR             
//*                                                             
//UTA      DD DSN=MISI01.SARE.M716001.EXPAND,DISP=(,CATLG)       
//*                                                             
//TOOLIN   DD   *                                               
 SELECT FROM(INA) TO(UTA) ON(1,1,CH) FIRST(50) USING(CTL1)       
//*                                                             
//CTL1CNTL DD *                                                 
* IF RECORD HAS '4' IN POSITION 1, ADD EQUIVALENT OF 3 ZEROES   
* IN POSITIONS 197-199                                           
  INREC IFTHEN=(WHEN=(1,1,CH,EQ,C'4'),                           
                BUILD=(1,196,C'000',197,371)),                   
* IF RECORD HAS '5' IN POSITION 1, ADD EQUIVALENT OF 3 ZEROES   
* IN POSITIONS 102-104                                           
        IFTHEN=(WHEN=(1,1,CH,EQ,C'5'),                           
                BUILD=(1,101,C'000',102,466))                   
/*                                                               


My question though is if there's a better way to, basically, copy the input file to output simply inserting 3 zeroes in specific positions for specific record types.

The use of FIRST(50) seems unnecessary (?). Maybe I should be using DFSORT instead ?
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
William Collins
Supermod


Joined: 03 Jun 2012
Posts: 437
Topics: 0

PostPosted: Tue Sep 30, 2014 5:59 am    Post subject: Reply with quote

Since you want the first 50 records of each key, for what is presumably a periodic extract of data, I don't really see a reason not to use ICETOOL to do it.

You said you want X'0000' but you are putting C'000'.

What do you not like about what you have come up with?

In straight DFSORT you'd create a sequence number with a RESTART, or use WHEN=GROUP, you'd need to put the sequence number on the record whilst you need it, and take it off before final output. Just let ICETOOL do all that type of thing for you, behind the scenes.

You have one ICETOOL control statement and two IFTHEN's on INREC. Seems OK to me, assuming it gives what you want.
Back to top
View user's profile Send private message
misi01
Advanced


Joined: 02 Dec 2002
Posts: 621
Topics: 173
Location: Stockholm, Sweden

PostPosted: Tue Sep 30, 2014 7:12 am    Post subject: Reply with quote

The only "problem" with it is I thought there would be a simpler way of specifying the base ICETOOL command
Code:

SELECT FROM(INA) TO(UTA) ON(1,1,CH) FIRST(50) USING(CTL1)


Something like
Code:

SELECT FROM(INA) TO(UTA) USING(CTL1)

instead. In reality, I'd already extracted 50 elements for each key in column 1, so respecifying 50 again seems a bit tautological.

Basically, all I want to do is inspect the data and insert extra characters based on a value in column 1.

(BTW, the extra build characters switching from hex to char etc was simply my bad)[/code]
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
William Collins
Supermod


Joined: 03 Jun 2012
Posts: 437
Topics: 0

PostPosted: Tue Sep 30, 2014 9:43 am    Post subject: Reply with quote

OK, yes, if you already have done your selection, you don't need to do it again.

As you suspected, plain SORT will do it readily:
Code:

  OPTION COPY

* IF RECORD HAS '4' IN POSITION 1, ADD EQUIVALENT OF 3 ZEROES   
* IN POSITIONS 197-199                                           
*
  INREC IFTHEN=(WHEN=(1,1,CH,EQ,C'4'),                           
                BUILD=(1,196,C'000',197,371)),                   

* IF RECORD HAS '5' IN POSITION 1, ADD EQUIVALENT OF 3 ZEROES   
* IN POSITIONS 102-104                                           
*
        IFTHEN=(WHEN=(1,1,CH,EQ,C'5'),                           
                BUILD=(1,101,C'000',102,466))   


The "spacing" I've added is simply to make the actual control cards stand out a bit more.

Anything after the first trailing blank on a control card is a comment. That can help segregate and avoid repetition (when you copy it somewhere else, you know, the bits in the comment that never get changed).

I also find using symbols/SYMNAMES helps document things without so much need for comment anyway.

Code:

//SYMNAMES DD *
RECORD-TYPE,1,1,CH
OUTGOINGS-FIRST-PART,1,196,CH
OUTGOINGS-SECOND-PART,*,371
INCOMINGS-FIRST-PART,1,101,CH
INCOMINGS-SECOND-PART,*,466

INSERTION-LITERAL,C'000'

OUTGOINGS,C'4'
INCOMINGS,C'5'
//SYMNOUNT DD SYSOUT=*
//SYSIN DD *
  OPTION COPY

  INREC IFTHEN=(WHEN=(RECORD-TYPE,EQ,OUTGOINGS),                           
                BUILD=(OUTGOINGS-FIRST-PART,
                       INSERTION-LITERAL,
                      OUTGOINGS-SECOND-PART)),                   

        IFTHEN=(WHEN=(RECORD-TYPE,EQ,INCOMINGS),                           
                BUILD=(INCOMINGS-FIRST-PART,
                       INSERTION-LITERAL,
                      INCOMINGS-SECOND-PART))                   
   


or

Code:
  OPTION COPY

  INREC IFTHEN=(WHEN=(RECORD-TYPE,
                       EQ,
                        OUTGOINGS),           
               
                BUILD=(OUTGOINGS-FIRST-PART,
                       INSERTION-LITERAL,
                       OUTGOINGS-SECOND-PART)),                   

        IFTHEN=(WHEN=(RECORD-TYPE,
                       EQ,
                        INCOMINGS),                   
       
                BUILD=(INCOMINGS-FIRST-PART,
                       INSERTION-LITERAL,
                       INCOMINGS-SECOND-PART))



Then you realise you've just "generalized" the insertion of one piece of data.

Code:
 
DATA-TO-TEST,1,1,CH
TEST1-TRUE-FIRST-PART,1,196,CH
TEST1-TRUE-SECOND-PART,*,371
TEST2-TRUE-FIRST-PART,1,101,CH
TEST2-TRUE-SECOND-PART,*,466

INSERTION-LITERAL,C'000'

TEST1-VALUE,C'4'
TEST2-VALUE,C'5'

  OPTION COPY

  INREC IFTHEN=(WHEN=(DATA-TO-TEST,
                       EQ,
                        TEST1-VALUE),           
               
                BUILD=(TEST1-TRUE-FIRST-PART,
                       INSERTION-LITERAL,
                       TEST1-TRUE-SECOND-PART)),                   

        IFTHEN=(WHEN=(DATA-TO-TEST,
                       EQ,
                        TEST2-VALUE),                   
       
                BUILD=(TEST2-TRUE-FIRST-PART,
                       INSERTION-LITERAL,
                       TEST2-TRUE-SECOND-PART))


You can now "reuse" the SORT Control Cards simply by changing the values in the SYMNAMES file (the DD * is only for an example, should be a PDSE member of course).

The SYMNOUT file shows the "normalised" symbols which will be translated when the SORT cards are processed. The translated SORT cards will be shown, so you can see all the nice old 1,1,CH stuff, although it is space-compressed Smile
Back to top
View user's profile Send private message
kolusu
Site Admin
Site Admin


Joined: 26 Nov 2002
Posts: 12370
Topics: 75
Location: San Jose

PostPosted: Tue Sep 30, 2014 10:39 am    Post subject: Reply with quote

misi01 wrote:
In reality, I'd already extracted 50 elements for each key in column 1, so respecifying 50 again seems a bit tautological.

Basically, all I want to do is inspect the data and insert extra characters based on a value in column 1.

(BTW, the extra build characters switching from hex to char etc was simply my bad)[/code]


Misi01,

If your Data is already SORTED on the key (1,1,ch) and you already have extracted the 50 records why use SELECT operator which does a sort once again? Use a COPY operator with an INCLUDE on OUTFIL based on a seqnum basing off the key.

Secondly do you have other record types other than "4" and "5"? If so what would you like to do with them? Currently it pads with spaces from 568 thru 570.
_________________
Kolusu - DFSORT Development Team (IBM)
DFSORT is on the Web at:
www.ibm.com/storage/dfsort

www.linkedin.com/in/kolusu
Back to top
View user's profile Send private message Send e-mail Visit poster's website
misi01
Advanced


Joined: 02 Dec 2002
Posts: 621
Topics: 173
Location: Stockholm, Sweden

PostPosted: Wed Oct 01, 2014 1:56 am    Post subject: Reply with quote

William - thanks for the "education". I'll take a bet others will also have use of your explanation.

Kolusu - when you're not an expert at something, you muck around until, hopefully, you get something that does what you want (which my solution did, albeit in a clunky way).

Basically, I get confused as to when to use ICETOOL and when to use DFSORT, simple as that. I had a suspicion there was a better solution, thereof my question.
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
misi01
Advanced


Joined: 02 Dec 2002
Posts: 621
Topics: 173
Location: Stockholm, Sweden

PostPosted: Wed Oct 01, 2014 1:58 am    Post subject: Reply with quote

Kolusu - forgot to answer about other than type 4 or 5. They were to be left "unchanged". The fact that they had extra blanks inserted didn't matter.
_________________
Michael
Back to top
View user's profile Send private message Send e-mail
kolusu
Site Admin
Site Admin


Joined: 26 Nov 2002
Posts: 12370
Topics: 75
Location: San Jose

PostPosted: Wed Oct 01, 2014 12:08 pm    Post subject: Reply with quote

misi01 wrote:
Basically, I get confused as to when to use ICETOOL and when to use DFSORT, simple as that. I had a suspicion there was a better solution, thereof my question.


misi01,

ICETOOL is just a more user friendly interface and easy-to-use batch front-end for DFSORT. It invokes DFSORT in the background.

If your intention is to pick the top 50 records on a previously sorted file on the key, then you can use SELECT with FIRST 50 but override the sort operation with a COPY like this

Code:

//STEP0300 EXEC PGM=ICETOOL                                     
//TOOLMSG  DD SYSOUT=*                                         
//DFSMSG   DD SYSOUT=*                                         
//IN       DD DISP=SHR,DSN=Your Input FB 567 file                             
//OUT      DD SYSOUT=*                                         
//TOOLIN   DD *                                                 
  SELECT FROM(IN) TO(OUT) ON(1,1,CH) FIRST(50) USING(CTL1)       
//CTL1CNTL DD *                                                 
  OPTION COPY                                                   
  INREC IFTHEN=(WHEN=(1,1,ZD,EQ,4),BUILD=(1,196,3Z,197,371)),   
        IFTHEN=(WHEN=(1,1,ZD,EQ,5),BUILD=(1,101,3Z,102,466))   
//*


ICETOOL will not sort the file and internally serializes the records sequencing and picks up the first 50 records per key

But lets us suppose you as programmer want to select the first 50 records, then you would programmatically increment the sequence number for every record based on the key and then select the first 50 records.

This is the programmatic way of doing that. use the following DFSORT/ICETOOL JCL which will give you the desired results. I assumed that you have a max of 9999 duplicates per key. If you have more than that, you just need to increase the size of the seqnum on the inrec statement.

Code:

//STEP0100 EXEC PGM=ICETOOL                                         
//TOOLMSG  DD SYSOUT=*                                             
//DFSMSG   DD SYSOUT=*                                             
//IN       DD DISP=SHR,DSN=Your Input FB 567 file
//OUT      DD SYSOUT=*                                             
//TOOLIN   DD *                                                     
  COPY FROM(IN) TO(OUT) USING(CTL1)                                 
//CTL1CNTL DD *                                                     
  INREC IFTHEN=(WHEN=INIT,OVERLAY=(571:SEQNUM,4,ZD,RESTART=(1,1))),
  IFTHEN=(WHEN=(1,1,ZD,EQ,4),BUILD=(1,196,3Z,197,371,571,4)),       
  IFTHEN=(WHEN=(1,1,ZD,EQ,5),BUILD=(1,101,3Z,102,466,571,4))
       
  OUTFIL BUILD=(1,570),INCLUDE=(571,4,ZD,LE,50)                     
//*


Now the same JCL can be coded as the following using the PGM=SORT


Code:

//STEP0100 EXEC PGM=SORT                                           
//SYSOUT   DD SYSOUT=*                                             
//SORTIN   DD DISP=SHR,DSN=Your Input FB 567 file               
//SORTOUT  DD SYSOUT=*                                             
//SYSIN    DD *                                                   
  OPTION COPY                                                     
  INREC IFTHEN=(WHEN=INIT,OVERLAY=(571:SEQNUM,4,ZD,RESTART=(1,1))),
  IFTHEN=(WHEN=(1,1,ZD,EQ,4),BUILD=(1,196,3Z,197,371,571,4)),     
  IFTHEN=(WHEN=(1,1,ZD,EQ,5),BUILD=(1,101,3Z,102,466,571,4))       

  OUTFIL BUILD=(1,570),INCLUDE=(571,4,ZD,LE,50)                     
//*

_________________
Kolusu - DFSORT Development Team (IBM)
DFSORT is on the Web at:
www.ibm.com/storage/dfsort

www.linkedin.com/in/kolusu
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic   printer-friendly view    MVSFORUMS.com Forum Index -> Utilities All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


MVSFORUMS
Powered by phpBB © 2001, 2005 phpBB Group