Files
dc/sas/sasjs/macros/mpe_filtermaster.sas
Mihajlo Medjedovic f268de21a3
Some checks failed
Test / Build-and-test-development (push) Failing after 6m14s
Test / Build-and-test-development-latest-adapter (push) Failing after 6m13s
init
2023-07-13 13:44:05 +02:00

263 lines
6.5 KiB
SAS

/**
@file
@brief dynamic where clause creation
@details Generates a where clause based on the following inputs:
@li The filter_RK (if provided)
@li The mode (if EDIT then filter for current records)
@li The user permissions (Row Level Security)
This macro should be used whenever surfacing data to the user. Note that
it is not possible to %include filerefs directly in a proc sql where clause.
The workaround is to use a data step view.
Note - DCLIB should be assigned.
@param [in] mode The mode. If EDIT, then current rows are returned. Valid
Values:
@li EDIT
@li VIEW
@li DLOAD - used in getrawdata
@li ULOAD - used by stagedata.sas to prevent restricted rows being submitted
@param [in] libds The target libref.dataset to which the filter will apply.
@param [in] filter_rk= (-1) The filter_rk, if available
@param [in] dclib= The libref of the DC control tables
@param [out] outref= The output fileref to create (containing the filter)
@param [out] outds= (work.query) The query dataset (if filter_rk supplied)
<h4> SAS Macros </h4>
@li mf_fmtdttm.sas
@li mf_getuser.sas
@li mf_getuniquefileref.sas
@li mf_getuniquename.sas
@li mf_nobs.sas
@li mp_abort.sas
@li mp_filtergenerate.sas
@li mpe_getgroups.sas
@version 9.3
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
and may not be re-distributed or re-sold without the express permission of
4GL Apps Ltd.
**/
%macro mpe_filtermaster(mode,libds,
dclib=,
filter_rk=-1,
outref=0,
outds=work.query
);
%put &sysmacroname entry vars:;
%put _local_;
%let mode=%upcase(&mode);
%let libds=%upcase(&libds);
%mp_abort(iftrue= (
&mode ne EDIT and &mode ne VIEW and &mode ne DLOAD and &mode ne ULOAD
)
,mac=&sysmacroname
,msg=%str(Invalid MODE: &mode)
)
%mp_abort(iftrue= (&outref = 0)
,mac=&sysmacroname
,msg=%str(Please provide a fileref!)
)
%mp_abort(iftrue= (&syscc ne 0)
,mac=&sysmacroname
,msg=%str(syscc=&syscc)
)
filename &outref temp;
/* ensure outputs exist */
data _null_;
file &outref;
put ' ';
run;
data &outds;
set &dclib..mpe_filtersource;
stop;
run;
/**
* Deal with FILTER_RK first
*/
%if &filter_rk gt 0 %then %do;
data _null_;
file &outref;
put '( '@@;
set &dclib..mpe_filteranytable(where=(filter_rk=&filter_rk));
call symputx('filter_hash',filter_hash,'l');
run;
proc sort data=&dclib..mpe_filtersource(where=(filter_hash="&filter_hash"))
out=&outds(drop=filter_hash filter_line processed_dttm);
by filter_line;
run;
%mp_filtergenerate(&outds,outref=&outref)
%end;
/* Now filter for current records if the MODE is EDIT or DLOAD */
%local varfrom varto;
%let varfrom=0;
proc sql;
select coalescec(var_txfrom,'0'), var_txto into: varfrom,:varto
from &dclib..MPE_TABLES
where &dc_dttmtfmt. lt tx_to
and libref="%scan(&libds,1,.)" and dsn="%scan(&libds,2,.)";
%put &=varfrom;
%put &=varto;
/**
* Check if the date variables were mentioned in the query
* This is a trigger for serving a historical view instead of current
* we skip this part when checking an ULOAD as there are no date vars
*/
%if &varfrom ne 0 and (&mode=EDIT or &mode=DLOAD) %then %do;
%local validityvars;
proc sql;
select count(*) into: validityvars
from &outds
where variable_nm in ("&varfrom","&varto");
%if &validityvars=0 %then %do;
data _null_;
file &outref mod;
length filter_text $32767;
varfrom=symget('varfrom');
varto=symget('varto');
filter_text=catx(' ',
'("%sysfunc(datetime(),',"%mf_fmtdttm()",')"dt <',varto,')'
);
if &filter_rk > 0 then put 'AND ' filter_text;
else put filter_text;
run;
%end;
%end;
/**
* Now do Row Level Security based on the MPE_ROW_LEVEL_SECURITY table
*/
/* first determine users group membership */
%mpe_getgroups(user=%mf_getuser(),outds=work.groups)
%local admin_check;
proc sql;
select count(*) into: admin_check
from work.groups
where groupname="&mpeadmins";
%put &sysmacroname: &=admin_check &=mpeadmins;
%if &admin_check=0 %then %do;
%local scopeval;
%if &mode=DLOAD %then %let scopeval=VIEW;
%if &mode=ULOAD %then %let scopeval=EDIT;
%else %let scopeval=&mode;
/* extract relevant rows */
%local rlsds;
%let rlsds=%mf_getuniquename();
proc sql;
create table work.&rlsds as
select rls_group,
rls_group_logic as group_logic,
rls_subgroup_logic as subgroup_logic,
rls_subgroup_id as subgroup_id,
rls_variable_nm as variable_nm,
rls_operator_nm as operator_nm,
rls_raw_value as raw_value
from &mpelib..mpe_row_level_security
where &dc_dttmtfmt. lt tx_to
and rls_scope in ("&scopeval",'ALL')
and upcase(rls_group) in (select upcase(groupname) from work.groups)
and rls_libref="%scan(&libds,1,.)"
and rls_table="%scan(&libds,2,.)"
and rls_active=1
order by rls_group,rls_subgroup_id;
%if &sqlobs>0 %then %do;
/* check if we currently have filter or not */
data ;
infile &outref end=eof;
input;
if _n_=1 and eof and cats(_infile_)='' then newfilter=1;
output;
stop;
run;
data _null_;
set &syslast;
file &outref mod;
if newfilter=1 then put '(';
else put 'AND (';
run;
/* loop through and apply filters for each group membership */
%local fref ds;
%let fref=%mf_getuniquefileref();
%let ds=%mf_getuniquename();
proc sql noprint;
select distinct rls_group into : group1 -
from work.&rlsds;
%do i=1 %to &sqlobs;
data work.&ds;
set work.&rlsds;
where rls_group="&&group&i";
drop rls_group;
run;
%mp_filtergenerate(&ds,outref=&fref)
data _null_;
infile &fref;
file &outref mod;
input;
if &i>1 and _n_=1 then put ' OR ';
put _infile_;
run;
%end;
data _null_;
file &outref mod;
put ')';
run;
%end; /* &sqlobs>0 */
%else %do;
%put &sysmacroname: no matching groups;
data _null_;
set work.groups;
putlog (_all_)(=);
run;
%end;
%mp_abort(iftrue= (&syscc>0)
,mac=&sysmacroname
,msg=%str(Row Level Security Generation Error)
)
%end; /* &admin_check=0 */
%put leaving &sysmacroname with the following query:;
%local empty;
%let empty=0;
data _null_;
infile &outref end=eof;
input;
putlog _infile_;
if _n_=1 and eof and cats(_infile_)='' then do;
put '1=1';
call symputx('empty',1,'l');
end;
run;
%if &empty=1 %then %do;
data _null_;
file &outref;
put '1=1';
run;
%end;
%mend mpe_filtermaster;