Shared Appendix 9: Exits for the Process Task -- Generic Collector Specifics and MVS Specifics | |
Index to Topics in this File:
Contents of this File:
Note: For each exit point mentioned in this table, the information in the table is designed to be read in conjunction with the exit point's position in the sample code that follows the table.
Note: In this table, "open" means not in the middle of a statement, DATA step, or PROC step.
Exit Exit Placement Purpose Frequency Number in Point of Code Name Execution Example
#1 proc005 The very Enables any Once per first initial process exit one-time run. point. open code This is processing. before the %LET CPTABLE statement but after the %LET CPTABLES= statement. #2 proc010 Directly Enables Once per before setting of table. the first options DATA and step. unconditional pre- processing before the final staging. #3 proc015 Directly Enables the Once per after the user to table. KEEP= specify list for data set the options. output staged data set. #4 proc020 Directly Enables the Once per before the user to table. closing ; add his/her in the DATA own output statement. data set. #5 proc025 Directly Enables Once per after the user- observation. ATTRIB specified statement attributes in the and open first DATA step DATA code. step. #6 proc030 Directly Enables Once per before user to observation. the override closing ) data set of the options. data set OPTIONS clause in the SET statement for the staged data set. #7 proc035 Directly Enables Once per after the user to observation. closing ) specify of the additional data set data sets OPTIONS for SET clause in processing. the SET statement for the staged data set. #8 proc040 Directly Open DATA Once per after the SET step code observation. statement point for in the user. first DATA step. #9 proc045 Directly Enables user Once per before to handle observation the observations that has a DELETE that have missing statement missing DATETIME for DATETIME value. observations values that have missing DATETIME values in the first DATA step. #10 proc050 Directly Enables Once per after the user to observation. HOUR override the variable setting of has been HOUR. set in the first DATA step. #11 proc055 Directly Enables Once per after user to observation LSTPDATE override in which has been setting of LSTPDATE set to LSTPDATE. had a the missing current LSTPDATE datetime value. stamp in the first DATA step, if LSTPDATE is currently missing. #12 proc060 Directly Open DATA Once per before the step code observation. SHIFT point for variable user. calculations begin. #13 proc065 Directly Enables Once per after the user to observation SHIFT override that has a variable the shift blank has been set matrix. SHIFT variable using the value. shift matrix. This happens only if the SHIFT variable is not set in the staged data set. #14 proc070 After the Enables Once per SHIFT user to observation. variable override value has the SHIFT been set, variable regardless value, of whether prior to it was set calculation in the using staged the data set. Holiday This List. occurs before the Holiday List. #15 proc075 After the Enables Once per SHIFT user to observation value has SHIFT that has been been set, variable set by the if the date value, if Holiday matches an set by the List. entry in the Holiday Holiday List. List. #16 proc077 Inside the Enables you Once IF _LAST to perform per clause, any final table. directly actions in before the staging the macro view DATA variable step. CPLDATM is populated, with the latest value of DATETIME in the incoming data. #17 proc080 Directly Final open Once per before DATA step observation. the code point OUTPUT available statement before the for the observation staged is data set written to / DATA the staged step view data set / in the DATA step first view. DATA step. #18 proc085 Directly Enables Once per after the user observation. OUTPUT OUTPUT statement statements for the and open staged DATA step data set code. / DATA step view in the first DATA step. #19 proc090 Directly Enables Once per before pre-sort table. the PROC processing SORT of of the the staged staged data. data. #20 proc095 Directly Enables Once per before user to table. the NODUP specify clause of additional the PROC sort SORT options. statement for the staged data. #21 proc097 Directly Enables Once per before user to table. the BY override statment of the default the PROC BY list for SORT the sort of statement the staged for the data. staged data. #22 proc100 Directly Enables Once per after the post-sort table. RUN statement processing for the of the PROC SORT staged of the data. staged data. #23 proc105 Directly This exit Once per after the is only table, if PROC SORT invoked if detail of the the detail data is staged data set not going data, if is not to be there is being sorted. no PROC sorted. SORT of the detail data. #24 proc110 Directly This exit Once per after the is only table, if PROC SORT invoked if detail of the the detail data is staged data set going to data, if is being be sorted. there is sorted. a PROC Allows SORT of pre-sort the code detail for data. detail. #25 proc115 Directly Enables Once per before the user to table. closing ; in specify the PROC additional SORT sort statement options. for the detail data. #26 proc120 Directly This exit Once per after the is invoked table, if PROC SORT only if detail of the the detail- data was detail level data sorted. data, if set was there is sorted. a PROC Allows SORT of post-sort the code detail for data. detail. #27 proc125 Directly Enables Once per before setting of table. the "merge" options DATA and open step. DATA step code prior to the merge of the DETAIL and staged data. #28 proc130 Directly Enables the Once per before user to table. the override closing ) data set on the options. data set options for the DETAIL data set. #29 proc135 Directly Enables the Once per before the user to table. closing ; in add his/her the DATA own output statement. data set. #30 proc140 Directly Enables Once, before first-pass during the the END -only first pass statement code. of the in the IF DATA step. _N_=1 block. #31 proc145 Directly Enables Once per after the user- observation. last specified ATTRIB attributes statement and open in the DATA step "merge" code. DATA step, and before the SET statement for the detail and staged data sets. #32 proc150 Directly Enables Once per after the user to observation. datetime override/ (age limit extend trimming) age limit value in trimming. the WHERE clause for detail. #33 proc155 Directly Enables Once per before user to observation. the override closing ) data set in options. the data set OPTIONS statement in the SET statement for the detail data set. #34 proc160 Directly Enables Once per before the user to observation. closing ) in override the data set the data options. set OPTIONS statement in the SET statement for the staged data set. #35 proc165 Directly Enables Once per after the user to observation. SET include clause his/her own for the data set staged in the SET data. data sets for BY (merge) processing. #36 proc170 Before Enables the Once per the user to observation. closing ; override in the or add SET SET options. statement. #37 proc175 After the Open code Once per BY point. observation. statement. This is the recommended exit point to use for deleting observations. #38 proc180 Duplicate Enables user Once BY variable to handle per observation observations observation encountered. that have encountered duplicate with BY- duplicate variable BY variable values. values. #39 proc185 Earlier Enables user Once per datetime code to be observation encountered. executed that has . each time an a new earlier (earliest) datetime datetime stamp than stamp is any found in previous the DATA observations. step. The earliest datetime stamp value is stored in the variable _oet . #40 proc190 Later Enables user Once per datetime code to be observation encountered. executed that has each time a a new later (latest) datetime datetime stamp than stamp is any found in previous the DATA observations. step. The latest datetime stamp value is stored in the variable _olt . #41 proc195 When the Enables user Once per observation code to be observation is executed read found each time from the to have an output detail-level come from observation data set. the is detail-level found data set. to have come from the detail data set. A count of these observations is accumulated in the variable _oldobs . #42 proc200 When the Enables user Once per observation code to be observation is executed read found each time from the to have an output staged come from observation data set. the new is (staged) found data set. to have come from the new (staged) data set. A count of these observations is accumulated in the variable _addobs . #43 proc205 Directly Enables the Once per before user to observation. the modify the OUTPUT observation statement before it in the is finally "merge" written to DATA the detail step. level. #44 proc210 Directly Enables the Once per after the OUTPUT observation. OUTPUT statements statement for any in the user-created "merge" data DATA sets. step. #45 proc215 After Enables Once per duplicate user to table, if warning perform any message his/her own observations has been end-of- have issued. table been duplicate determined reporting. to have This exit duplicate is called BY variable only values. when observations have been found that have duplicate BY variable values. #46 proc220 After Enables the Once per symbol user to table, on values perform the last have been end-of- pass of set for table the DATA end-of- reporting. step. table reporting. #47 proc225 After the Open DATA Once per RUN step code table. statement point to in the allow the "merge" user to DATA work with step. the new merged data, and/or any user data sets that may have been created. #48 proc230 After Enables Once per processing return- run of has code setting, process. been or other completed final for all operations. tables.
The following is an example of the code submitted by the process step when the value of the COLLECTOR= parameter on the %CxPROCES macro is set to the generic collector. The location of an exit point is indicated by #n, where n is the number of the item in the above table.
/* list of global macro variables that are needed */ %GLOBAL CPCUTDT CPTABLES CPTABLE CPBYVAR CPVWNM; %GLOBAL CPARCTBS CPARCTB; %GLOBAL CPTOTOBS CPADDOBS CPOLDOBS CPDUPOBS CPEDATM CPLDATM ; %LET CPVWNM = WORK.EJLDPCV; /* unique name per process run */ %LET CPTABLES = XDCVOLS XDCDSET ; %LET CPARCTBS = ; /* list of tables to archive while processed */ #1 /* name of table to process */ %LET CPTABLE = XDCVOLS; %LET CPARCTB = N; /* Archive this table? Y or N */ /* list of BY variables for this table */ %LET CPBYVAR = MACHINE DCVSGTC DCVVOLS DCVDVNU DATETIME ; #2 /************************************************************/ /* Data step view created from the staged data. This is */ /* to add and set variables, such as SHIFT, HOUR, and */ /* DATETIME, that will be needed for sorting. The */ /* bizarre-looking name for the view is generated as a */ /* unique name, to avoid any sort of namespace conflict. */ /************************************************************/ data WORK.EJLDPCV(keep= DCUTMSTP . . . ZDATE #3 ) #4 /view=WORK.EJLDPCV; /* Output: TEMP View */ /* Assign labels to the BY-variables. This forces the */ /* variables used for sorting to the first-most portion */ /* of each observation for improved sort efficiency. */ attrib MACHINE label='Machine'; attrib DCVSGTC label='Storage Class'; attrib DCVVOLS label='Volume Label'; attrib DCVDVNU label='Unit number'; attrib DATETIME label='Datetime'; attrib shift length=$1 _odate format=date9. _hshift length=$1 _charval length=$10 ; #5 set GENLIB.DCOLVOLS(in=_new rename=( DCUTMSTP = DATETIME . . . DCUSYSID = MACHINE ) #6) #7 end=_last; #8 retain _odate _hshift ; if datetime=. then do ; put 'WARNING: Invalid value for DATETIME on obs '_n_ ' ,obs deleted.' ; put 'NOTE: Data for obs. '_n_ ' follows:' ; put _all_; #9 if _last then _dellast = 1; else delete; end ; hour = hour(datetime) ; #10 if lstpdate = . then do; lstpdate = '22MAR1999:13:42:22.15'dt ; #11 end; #12 /* if shift not set in input data make it now */ if shift = ' ' then do ; _date = datepart(datetime) ; shift = substr("&cpshift", ((weekday(_date)-1)*24+ hour(datetime)+1),1) ; #13 end ; #14 if _odate ^= _date then do ; _charval=put(_date,CPHDAY.) ; if _charval ^= ' ' then do; _hshift = put(0,CPHDAY.) ; end; else do; _hshift = ' ' ; end; end ; if _hshift ^= ' ' then do; shift = _hshift ; #15 end; _odate = _date; if datetime > _olt or _olt = . and not(_dellast) then _olt = datetime; if _last then do; #16 call symput('cpldatm',put(_olt,best32.2)); if _dellast then delete; end; #17 output WORK.EJLDPCFV; #18 run; /************************************************************/ /* PROC SORT of the staged data by the BY variables. This */ /* prepares the data to be "merged" with the detail-level */ /* data set. Here the view is sorted out into a real data */ /* set in the WORK library; again the data set has a */ /* unique name. */ /************************************************************/ #19 proc sort data=WORK.EJLDPCFV /* Input: VIEW DS */ out=WORK.EJLDPCFC /* Output: WORK DS */ #20 nodup ; /* eliminate duplicates from new data */ #21 by MACHINE DCVSGTC DCVVOLS DCVDVNU DATETIME ; run ; /************************************************************/ /* If the BY-variable list has changed since the last */ /* run of the process macro, then you would see a PROC */ /* SORT of the detail-level data set onto itself, sorted */ /* by the current list of BY variables. */ /************************************************************/ #22 #23 /* only if there is no PROC SORT of detail level */ #24 /* only if there is a PROC SORT of detail level */ /************************************************************/ /* For illustration purposes, the sort of the DETAIL level */ /* is shown. This code would be generated and submitted */ /* only if the DETAIL-level data set required sorting. */ /************************************************************/ proc sort data=DETAIL.XDCVOLSD /* Input/Output: DETAIL DS */ #25 ; by MACHINE DCVSGTC DCVVOLS DCVDVNU DATETIME ; run ; #26 /* only if there was a PROC SORT of detail level */ /************************************************************/ /* DATA step that does a SET-BY ("merge") of the new data */ /* with the current detail-level data set, storing the */ /* output into the detail-level data set. SET statement */ /* age limit trimming is performed only on the detail- */ /* level data set, so that new data can be reduced before */ /* the data are aged out of detail level. Also, */ /* statistics are accumulated for the running of the */ /* process macro on the data in this table. */ /************************************************************/ #27 data DETAIL.XDCVOLSD /* Output: DETAIL */ (compress=yes keep= DATETIME . . . ZDATE sortedby= MACHINE DCVSGTC DCVVOLS DCVDVNU DATETIME #28 ) #29 ; /* Assign attributes to the BY-variables. This forces the */ /* variables used for merging to the first-most portion of */ /* each observation for efficiency in later reporting and */ /* subsequent runs of process. */ attrib MACHINE label='Machine' length = $8; format MACHINE; informat MACHINE; . . . attrib DATETIME label='Datetime' length = 8 format=DATETIME21.2; informat DATETIME; retain _totobs 0 ; retain _oldobs 0 ; retain _addobs 0 ; retain _dups 0 ; retain _oet . _olt . _oest ._olst .; if _n_ = 1 then do ; call symput('cpsedatm','0') ; call symput('cpsldatm','0') ; call symput('cpedatm','0') ; call symput('cpldatm','0') ; call symput('cptotobs','0') ; call symput('cpoldobs','0') ; call symput('cpaddobs','0') ; call symput('cpdupobs','0') ; #30 end ; #31 /* Concatenate DETAIL and NEW and select DETAIL */ /* data with dates newer than 12MAR1999:16:32:41.78 (Age= 10 days) */ %let CPCUTDT = '12MAR1999:16:32:41.78'dt ; set DETAIL.XDCVOLSD (in=_detail where=(datetime>'12MAR1999:16:32:41.78'dt #32) #33) WORK.EJLDPCFC (in=_new #34) #35 end=_last #36 ; by MACHINE DCVSGTC DCVVOLS DCVDVNU DATETIME ; #37 /* count and keep duplicate obs. */ if not first.DATETIME then do; #38 _dups = _dups + 1 ; end; if _oet= . or datetime < _oet then do; #39 _oet = datetime ; end ; if _olt= . or datetime > _olt then do; #40 _olt = datetime ; end ; if _detail then do; #41 _oldobs = _oldobs + 1 ; end; else if _new then do; #42 _addobs = _addobs + 1 ; if _olst= . or datetime > _olst then do; _olst = datetime ; end; if _oest= . or datetime < _oest then do; _oest = datetime ; end; end; #43 output DETAIL.XDCVOLSD; _totobs = _totobs + 1; #44 if _last then do; /* notify number of duplicates */ if _dups > 0 then do; put 'WARNING: Table XDCVOLS has ' _dups ' duplicate observations by key.' ; #45 end; call symput('cpldatm',put(_olt,best32.2)) ; call symput('cpedatm',put(_oet,best32.2)) ; call symput('cpsldatm',put(_olst,best32.2)) ; call symput('cpsedatm',put(_oest,best32.2)) ; call symput('cptotobs',put(_totobs,best32.)) ; call symput('cpdupobs',put(_dups,best32.)) ; call symput('cpaddobs',put(_addobs,best32.)) ; call symput('cpoldobs',put(_oldobs,best32.)) ; #46 end ; run ; #47 /* per-table basis */ data _null_; run; /* just to keep things clean */ #48 /* only once per-process run */ data _null_; run; /* just to keep things clean */