Some weeks ago, UJ97365 was made available for zSecure 3.1. This is the fix for APAR OA68008 and changes the way DEFINE .. WHERE .. works in combination with lookup. Before this fix, the WHERE condition would be ignored in a lookup, that is, if you wanted to use WHERE to skip certain lines in a DEFTYPE file, they would still be used and you might get
CKR1142 08 Duplicate and conflicting entry for key=<key> in lookup...
For example, with input file
* This table lists the groups to print
* enter group names from column 1, do not use generic patterns or specify commas at the end of the line
SYS1
SYS2
and CARLa code like this, reading the table from DD name SELECT:
deftype type=$select
alloc type=$select dd=select
define type=$select group as word(record,1) where substr(record,1,2)<>'* '
newlist type=racf
select class=group segment=base profile:$select.group.record<>' '
sortlist profile(8) owner aclcnt
you might get CKR1142 complaining about seeing a duplicate key "*". With UJ97365 installed, the message disappears. With this selective define, we were able to read a file with different record types in the 1st word of each record, and assign a different variable with the value in the 3rd word. The report produced a matrix of all group names, and columns that showed the number of permits, the number of profiles owned, the number of users connect and data set profiles with matching HLQ, for each group, using a two step CARLa.
Step 1: generate 3 different record types, each with a type, a group name and a count of the profiles containing that name in a unique field. Store this in member GRPMTX1
/* GRPMTX1
group analysis report step 1
export occurrences of groups (and users) into CKR2PASS
count the number of times an ID occurs, precede with record type
*/
newlist nopage dd=ckr2pass
s (class=dataset or class=general) aclcnt>0
sum 'STDACL'(8) userid count(9)
newlist nopage dd=ckr2pass
s class=dataset acl2cnt>0
sum 'DSCDACL'(8) user2acs count(9)
newlist nopage dd=ckr2pass
s class=general acl2cnt>0
sum 'GRCACL'(8) acl2uid count(9)
newlist nopage dd=ckr2pass
s class=user s=base
sum 'USOWNER'(8) owner count(9)
newlist nopage dd=ckr2pass
s class=group s=base
sum 'GPOWNER'(8) owner count(9)
newlist nopage dd=ckr2pass
s class=dataset s=base
sum 'DSOWNER'(8) owner count(9)
newlist nopage dd=ckr2pass
s class=general s=base
sum 'GROWNER'(8) owner count(9)
newlist nopage dd=ckr2pass
s class=user s=base
sum 'CONNECT'(8) congrpnm count(9)
newlist nopage dd=ckr2pass
s class=dataset s=base
sum 'DSPROF'(8) qual count(9)
The reporting step reads this temporary file, assigning a value depending on the record type, store this in member GRPMTX2:
/* GRPMTX2
group analysis report step 2
read occurrence and print as lookup from groups
*/
deftype type=$usage
alloc type=$usage dd=usage
newlist type=$usage outlim=0
define STDACL_ID(8) as word(record,2),
where word(record,1)=STDACL
define STDACL(7) as convert(word(record,3),decimal),
where word(record,1)=STDACL
define DSCACL_ID(8) as word(record,2),
where word(record,1)=DSCACL
define DSCACL(7) as convert(word(record,3),decimal),
where word(record,1)=DSCACL
define GRCACL_ID(8) as word(record,2),
where word(record,1)=GRCACL
define GRCACL(7) as convert(word(record,3),decimal),
where word(record,1)=GRCACL
define USOWNER_ID(8) as word(record,2),
where word(record,1)=USOWNER
define USOWNER(7) as convert(word(record,3),decimal),
where word(record,1)=USOWNER
define GPOWNER_ID(8) as word(record,2),
where word(record,1)=GPOWNER
define GPOWNER(7) as convert(word(record,3),decimal),
where word(record,1)=GPOWNER
define DSOWNER_ID(8) as word(record,2),
where word(record,1)=DSOWNER
define DSOWNER(7) as convert(word(record,3),decimal),
where word(record,1)=DSOWNER
define GROWNER_ID(8) as word(record,2),
where word(record,1)=GROWNER
define GROWNER(7) as convert(word(record,3),decimal),
where word(record,1)=GROWNER
define CONNECT_ID(8) as word(record,2),
where word(record,1)=CONNECT
define CONNECT(7) as convert(word(record,3),decimal),
where word(record,1)=CONNECT
define DSPROF_ID(8) as word(record,2),
where word(record,1)=DSPROF
define DSPROF(7) as convert(word(record,3),decimal),
where word(record,1)=DSPROF
newlist type=racf toptitle='G R O U P A N A L Y S I S R E P O R T',
st=' ------- Permits ------- ------- Profiles owned --------'
s class=group s=base
sortlist profile(8,'Group'),
profile:$usage.STDACL_ID.STDACL(' Normal ',7),
profile:$usage.DSCACL_ID.DSCACL('Cond DS',7),
profile:$usage.GRCACL_ID.GRCACL('Cond Re',7),
profile:$usage.USOWNER_ID.USOWNER(' Users',7),
profile:$usage.GPOWNER_ID.GPOWNER(' Groups',7),
profile:$usage.DSOWNER_ID.DSOWNER('Dataset',7),
profile:$usage.GROWNER_ID.GROWNER('Resourc',7),
universal,
profile:$usage.CONNECT_ID.CONNECT('Connect',7),
profile:$usage.DSPROF_ID.DSPROF('Ds prof',7)
Write JCL like so:
// JCLLIB ORDER=(SYS3.CKRPARM,SYS1.SCKRPROC)
//COLLECT EXEC C2RC,PARM.C2RC='PRINT DD=CKREPORT;I M=C2RXDEF1 NOLIST'
//SYSIN DD *
alloc type=racf backup
// DD DISP=SHR,DSN=USER.JOB.CARLA(GRPMTX1)
//CKR2PASS DD DSN=&&USAGE,DISP=(,PASS)
//REPORT EXEC C2RC,PARM.C2RC='PRINT DD=CKREPORT;I M=C2RXDEF1 NOLIST'
//SYSIN DD *
alloc type=racf backup
// DD DISP=SHR,DSN=USER.JOB.CARLA(GRPMTX2)
//USAGE DD DSN=&&USAGE,DISP=OLD
//C2RC.CKREPORT DD LRECL=255
//CKR2PASS DD SYSOUT=*
and you could get a report that contains
G R O U P A N A L Y S I S R E P O R T 25 Aug 2025 09:24
------- Permits ------- ------- Profiles owned --------
Group Normal Cond DS Cond Re Users Groups Dataset Resourc Uni Connect Ds prof
SYS1 1 5 27 6 25 10 662
SYS2 5 64 420
SYS3 8 50 285
------------------------------
Rob van Hoboken
------------------------------