mpe_accesscheck and validatefilter validated their libds input with mp_validatecol(LIBDS), which rejects the LIBREF.CATALOGNAME-FC form that Data Controller uses to address a format catalog. A format-catalog load or filter therefore aborted with "Invalid base_table" / "Invalid filter_table" - stagedata, getdata and postdata all reach mpe_accesscheck through the edit/approve path. Add mpe_validatecol, a wrapper that permits the catalog form: the -FC suffix is matched exactly and the remainder is validated as a strict LIBREF.DATASET, so the whole value is covered and a caller that needs the catalog reference downstream (MPE_SECURITY stores it with the suffix) still receives it. getrawdata and getcolvals had grown an inline version of this check that scanned on the dash and validated only the prefix, leaving whatever followed it unvalidated; the wrapper replaces both. mpe_validatecol.test.sas asserts the matrix - plain libds, catalog form, and payloads that smuggle content past a valid libds prefix.
215 lines
5.0 KiB
SAS
215 lines
5.0 KiB
SAS
/**
|
|
@file
|
|
@brief Retrieves column info to enable population of dropdowns
|
|
@details An optional filterquery may be provided, if so then it is validated
|
|
and then used to filter the subsequent results.
|
|
|
|
<h4> Service Inputs </h4>
|
|
|
|
<h5> IWANT </h5>
|
|
|
|
The STARTROW and ROWS variables are used to fetch additional values beyond
|
|
the initial default (4000).
|
|
|
|
|libds:$19.|col:$9.|STARTROW:8.|ROWS:8.|
|
|
|---|---|---|---|
|
|
|DC258467.MPE_X_TEST|SOME_TIME|4001|1000
|
|
|
|
<h5> FILTERQUERY </h5>
|
|
|GROUP_LOGIC:$3|SUBGROUP_LOGIC:$3|SUBGROUP_ID:8.|VARIABLE_NM:$32|OPERATOR_NM:$10|RAW_VALUE:$32767|
|
|
|---|---|---|---|---|---|
|
|
|AND|AND|1|SOME_BESTNUM|>|1|
|
|
|AND|AND|1|SOME_TIME|=|77333|
|
|
|
|
<h4> Service Outputs </h4>
|
|
<h5> VALS </h5>
|
|
The type of this column actually depends on the underlying column type, so it can change
|
|
|FORMATTED|UNFORMATTED|
|
|
|---|---|
|
|
|$44.00|44|
|
|
|
|
<h5> META </h5>
|
|
|COLUMN:$32.|SASFORMAT:$32.|STARTROW:8.|ROWS:8.|
|
|
|---|---|---|---|
|
|
|COL_NAME|DOLLAR8.2|4001|1000
|
|
|
|
<h4> SAS Macros </h4>
|
|
@li mf_existds.sas
|
|
@li mf_verifymacvars.sas
|
|
@li dc_assignlib.sas
|
|
@li mf_getvarformat.sas
|
|
@li mp_abort.sas
|
|
@li mp_cntlout.sas
|
|
@li mp_filtercheck.sas
|
|
@li mp_filtergenerate.sas
|
|
@li mp_validatecol.sas
|
|
@li mpe_validatecol.sas
|
|
|
|
@version 9.2
|
|
@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.
|
|
|
|
**/
|
|
%mpeinit()
|
|
|
|
/* input table may or may not exist */
|
|
data work.initvars;
|
|
length GROUP_LOGIC $3 SUBGROUP_LOGIC $3 SUBGROUP_ID 8 VARIABLE_NM $32
|
|
OPERATOR_NM $10 RAW_VALUE $32767;
|
|
call missing(of _all_);
|
|
stop;
|
|
data work.filterquery;
|
|
set %sysfunc(ifc(
|
|
%mf_existds(work.filterquery)=1
|
|
,work.filterquery
|
|
,work.initvars
|
|
));
|
|
run;
|
|
|
|
/* print data for debugging */
|
|
data _null_;
|
|
set work.iwant;
|
|
put (_all_)(=);
|
|
run;
|
|
data _null_;
|
|
set work.filterquery;
|
|
put (_all_)(=);
|
|
run;
|
|
|
|
/**
|
|
* libds and col are request inputs that flow into executable positions
|
|
* (set &libds, proc sql select &col2). They are read from the IWANT
|
|
* table with symget in a data step (never re-resolved) and validated
|
|
* here before use - mf_getvalue would re-resolve any macro content in
|
|
* the value before this code ran.
|
|
*/
|
|
%let libds=;
|
|
%let col2=;
|
|
%let is_libds=0;
|
|
%let is_col=0;
|
|
data _null_;
|
|
length _libds $64 _col $32;
|
|
set work.iwant;
|
|
_libds=libds;
|
|
_col=col;
|
|
%mpe_validatecol(_libds,LIBDS,is_libds)
|
|
%mp_validatecol(_col,ISNAME,is_col)
|
|
if is_libds=0 then putlog 'ERR' 'OR: Invalid libds:' _libds;
|
|
if is_col=0 then putlog 'ERR' 'OR: Invalid col:' _col;
|
|
call symputx('is_libds',is_libds,'l');
|
|
call symputx('is_col',is_col,'l');
|
|
if is_libds=1 then call symputx('libds',upcase(_libds),'l');
|
|
if is_col=1 then call symputx('col2',upcase(_col),'l');
|
|
stop;
|
|
run;
|
|
|
|
%let is_fmt=0;
|
|
%let startrow=1;
|
|
%let rows=4000;
|
|
|
|
%mp_abort(iftrue= (%mf_verifymacvars(libds col2)=0)
|
|
,mac=&_program..sas
|
|
,msg=%str(Missing inputs from iwant)
|
|
)
|
|
%mp_abort(iftrue= (&is_libds ne 1)
|
|
,mac=&_program..sas
|
|
,msg=%str(Invalid libds)
|
|
)
|
|
%mp_abort(iftrue= (&is_col ne 1)
|
|
,mac=&_program..sas
|
|
,msg=%str(Invalid col)
|
|
)
|
|
|
|
%dc_assignlib(WRITE,%scan(&libds,1,.))
|
|
|
|
data _null_;
|
|
call missing(startrow,rows);
|
|
set work.iwant;
|
|
/* check if the request is for a format catalog */
|
|
call symputx('orig_libds',libds);
|
|
is_fmt=0;
|
|
if substr(cats(reverse(libds)),1,3)=:'CF-' then do;
|
|
libds=scan(libds,1,'-');
|
|
putlog "Format Catalog Captured";
|
|
call symputx('libds','work.fmtextract');
|
|
is_fmt=1;
|
|
end;
|
|
call symputx('is_fmt',is_fmt);
|
|
call symputx('startrow',coalesce(startrow,&startrow));
|
|
call symputx('rows',coalesce(rows,&rows));
|
|
putlog (_all_)(=);
|
|
run;
|
|
|
|
%mp_cntlout(
|
|
iftrue=(&is_fmt=1)
|
|
,libcat=&orig_libds
|
|
,fmtlist=0
|
|
,cntlout=work.fmtextract
|
|
)
|
|
|
|
|
|
/**
|
|
* Validate the filter query
|
|
*/
|
|
%mp_filtercheck(work.filterquery,targetds=&libds,abort=YES)
|
|
|
|
/**
|
|
* Prepare the query
|
|
*/
|
|
%mp_filtergenerate(work.filterquery,outref=myfilter)
|
|
|
|
/* cannot %inc in a sql where clause, only data step, so - use a view */
|
|
data work.vw_vals/view=work.vw_vals;
|
|
set &libds;
|
|
where %inc myfilter;;
|
|
run;
|
|
|
|
proc sql;
|
|
create view work.vw_vals_sorted as
|
|
select distinct
|
|
put(&col2,%mf_getVarFormat(&libds,&col2,force=1)) as formatted,
|
|
&col2 as unformatted
|
|
from work.vw_vals;
|
|
|
|
/* restrict num of output values */
|
|
data work.vals;
|
|
set work.vw_vals_sorted;
|
|
if _n_ ge &startrow;
|
|
x+1;
|
|
if x>&rows then stop;
|
|
drop x;
|
|
run;
|
|
|
|
data vals;
|
|
/* ensure empty value if table is empty, for dropdowns */
|
|
if nobs=0 then output;
|
|
set vals nobs=nobs;
|
|
format unformatted ;
|
|
output;
|
|
run;
|
|
|
|
proc sql noprint;
|
|
select count(*) into: nobs from work.vw_vals_sorted;
|
|
data meta;
|
|
column="&col2";
|
|
sasformat="%mf_getVarFormat(&libds,&col2)";
|
|
startrow=&startrow;
|
|
rows=&rows;
|
|
nobs=&nobs;
|
|
run;
|
|
|
|
%mp_abort(iftrue= (&syscc ne 0)
|
|
,mac=&_program..sas
|
|
,msg=%str(syscc=&syscc)
|
|
)
|
|
|
|
%webout(OPEN)
|
|
%webout(OBJ,vals,missing=STRING,showmeta=YES)
|
|
%webout(OBJ,meta)
|
|
%webout(CLOSE)
|
|
|
|
|
|
%mpeterm()
|