mirror of
https://github.com/sasjs/core.git
synced 2026-01-18 14:00:05 +00:00
feat(*): recreate library as scoped package
This commit is contained in:
218
viya/mv_webout.sas
Normal file
218
viya/mv_webout.sas
Normal file
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
@file mv_webout.sas
|
||||
@brief Send data to/from the SAS Viya Job Execution Service
|
||||
@details This macro should be added to the start of each Job Execution
|
||||
Service, **immediately** followed by a call to:
|
||||
|
||||
%mv_webout(FETCH)
|
||||
|
||||
This will read all the input data and create same-named SAS datasets in the
|
||||
WORK library. You can then insert your code, and send data back using the
|
||||
following syntax:
|
||||
|
||||
data some datasets; * make some data ;
|
||||
retain some columns;
|
||||
run;
|
||||
|
||||
%mv_webout(OPEN)
|
||||
%mv_webout(ARR,some) * Array format, fast, suitable for large tables ;
|
||||
%mv_webout(OBJ,datasets) * Object format, easier to work with ;
|
||||
%mv_webout(CLOSE)
|
||||
|
||||
|
||||
@param action Either OPEN, ARR, OBJ or CLOSE
|
||||
@param ds The dataset to send back to the frontend
|
||||
@param _webout= fileref for returning the json
|
||||
@param fref= temp fref
|
||||
@param dslabel= value to use instead of the real name for sending to JSON
|
||||
@param fmt= change to N to strip formats from output
|
||||
|
||||
<h4> Dependencies </h4>
|
||||
@li mp_jsonout.sas
|
||||
@li mf_getuser.sas
|
||||
|
||||
@version Viya 3.3
|
||||
@author Allan Bowe
|
||||
|
||||
**/
|
||||
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y);
|
||||
%global _webin_file_count _webin_fileuri _debug _omittextlog ;
|
||||
%if %index("&_debug",log) %then %let _debug=131;
|
||||
|
||||
%local i tempds;
|
||||
%let action=%upcase(&action);
|
||||
|
||||
%if &action=FETCH %then %do;
|
||||
%if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 131 %then %do;
|
||||
options mprint notes mprintnest;
|
||||
%end;
|
||||
|
||||
%if not %symexist(_webin_fileuri1) %then %do;
|
||||
%let _webin_file_count=%eval(&_webin_file_count+0);
|
||||
%let _webin_fileuri1=&_webin_fileuri;
|
||||
%end;
|
||||
|
||||
%if %symexist(sasjs_tables) %then %do;
|
||||
/* small volumes of non-special data are sent as params for responsiveness */
|
||||
/* to do - deal with escaped values */
|
||||
filename _sasjs "%sysfunc(pathname(work))/sasjs.lua";
|
||||
data _null_;
|
||||
file _sasjs;
|
||||
put 's=sas.symget("sasjs_tables")';
|
||||
put 'if(s:sub(1,7) == "%nrstr(")';
|
||||
put 'then';
|
||||
put ' tablist=s:sub(8,s:len()-1)';
|
||||
put 'else';
|
||||
put ' tablist=s';
|
||||
put 'end';
|
||||
put 'for i = 1,sas.countw(tablist) ';
|
||||
put 'do ';
|
||||
put ' tab=sas.scan(tablist,i)';
|
||||
put ' sasdata=""';
|
||||
put ' if (sas.symexist("sasjs"..i.."data0")==0)';
|
||||
put ' then';
|
||||
/* TODO - condense this logic */
|
||||
put ' s=sas.symget("sasjs"..i.."data")';
|
||||
put ' if(s:sub(1,7) == "%nrstr(")';
|
||||
put ' then';
|
||||
put ' sasdata=s:sub(8,s:len()-1)';
|
||||
put ' else';
|
||||
put ' sasdata=s';
|
||||
put ' end';
|
||||
put ' else';
|
||||
put ' for d = 1, sas.symget("sasjs"..i.."data0")';
|
||||
put ' do';
|
||||
put ' s=sas.symget("sasjs"..i.."data"..d)';
|
||||
put ' if(s:sub(1,7) == "%nrstr(")';
|
||||
put ' then';
|
||||
put ' sasdata=sasdata..s:sub(8,s:len()-1)';
|
||||
put ' else';
|
||||
put ' sasdata=sasdata..s';
|
||||
put ' end';
|
||||
put ' end';
|
||||
put ' end';
|
||||
put ' file = io.open(sas.pathname("work").."/"..tab..".csv", "a")';
|
||||
put ' io.output(file)';
|
||||
put ' io.write(sasdata)';
|
||||
put ' io.close(file)';
|
||||
put 'end';
|
||||
run;
|
||||
%inc _sasjs;
|
||||
|
||||
/* now read in the data */
|
||||
%do i=1 %to %sysfunc(countw(&sasjs_tables));
|
||||
%local table; %let table=%scan(&sasjs_tables,&i);
|
||||
data _null_;
|
||||
infile "%sysfunc(pathname(work))/&table..csv" termstr=crlf ;
|
||||
input;
|
||||
if _n_=1 then call symputx('input_statement',_infile_);
|
||||
list;
|
||||
data &table;
|
||||
infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd termstr=crlf;
|
||||
input &input_statement;
|
||||
run;
|
||||
%end;
|
||||
%end;
|
||||
%else %do i=1 %to &_webin_file_count;
|
||||
/* read in any files that are sent */
|
||||
/* this part needs refactoring for wide files */
|
||||
filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999;
|
||||
data _null_;
|
||||
infile indata termstr=crlf lrecl=32767;
|
||||
input;
|
||||
if _n_=1 then call symputx('input_statement',_infile_);
|
||||
%if %str(&_debug) ge 131 %then %do;
|
||||
if _n_<20 then putlog _infile_;
|
||||
else stop;
|
||||
%end;
|
||||
%else %do;
|
||||
stop;
|
||||
%end;
|
||||
run;
|
||||
data &&_webin_name&i;
|
||||
infile indata firstobs=2 dsd termstr=crlf ;
|
||||
input &input_statement;
|
||||
run;
|
||||
%end;
|
||||
%end;
|
||||
%else %if &action=OPEN %then %do;
|
||||
/* setup webout */
|
||||
OPTIONS NOBOMFILE;
|
||||
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI"
|
||||
name="_webout.json" lrecl=999999 mod;
|
||||
|
||||
/* setup temp ref */
|
||||
%if %upcase(&fref) ne _WEBOUT %then %do;
|
||||
filename &fref temp lrecl=999999 permission='A::u::rwx,A::g::rw-,A::o::---' mod;
|
||||
%end;
|
||||
|
||||
/* setup json */
|
||||
data _null_;file &fref;
|
||||
put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
|
||||
run;
|
||||
%end;
|
||||
%else %if &action=ARR or &action=OBJ %then %do;
|
||||
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt
|
||||
,jref=&fref,engine=PROCJSON,dbg=%str(&_debug)
|
||||
)
|
||||
%end;
|
||||
%else %if &action=CLOSE %then %do;
|
||||
%if %str(&_debug) ge 131 %then %do;
|
||||
/* send back first 10 records of each work table for debugging */
|
||||
options obs=10;
|
||||
data;run;%let tempds=%scan(&syslast,2,.);
|
||||
ods output Members=&tempds;
|
||||
proc datasets library=WORK memtype=data;
|
||||
%local wtcnt;%let wtcnt=0;
|
||||
data _null_; set &tempds;
|
||||
if not (name =:"DATA");
|
||||
i+1;
|
||||
call symputx('wt'!!left(i),name);
|
||||
call symputx('wtcnt',i);
|
||||
data _null_; file &fref; put ",""WORK"":{";
|
||||
%do i=1 %to &wtcnt;
|
||||
%let wt=&&wt&i;
|
||||
proc contents noprint data=&wt
|
||||
out=_data_ (keep=name type length format:);
|
||||
run;%let tempds=%scan(&syslast,2,.);
|
||||
data _null_; file &fref;
|
||||
dsid=open("WORK.&wt",'is');
|
||||
nlobs=attrn(dsid,'NLOBS');
|
||||
nvars=attrn(dsid,'NVARS');
|
||||
rc=close(dsid);
|
||||
if &i>1 then put ','@;
|
||||
put " ""&wt"" : {";
|
||||
put '"nlobs":' nlobs;
|
||||
put ',"nvars":' nvars;
|
||||
%mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP)
|
||||
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP)
|
||||
data _null_; file &fref;put "}";
|
||||
%end;
|
||||
data _null_; file &fref;put "}";run;
|
||||
%end;
|
||||
|
||||
/* close off json */
|
||||
data _null_;file &fref mod;
|
||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
||||
SYS_JES_JOB_URI=quote(trim(resolve(symget('SYS_JES_JOB_URI'))));
|
||||
put ',"SYS_JES_JOB_URI" : ' SYS_JES_JOB_URI ;
|
||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||
put ",""_DEBUG"" : ""&_debug"" ";
|
||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||
put ",""SYSCC"" : ""&syscc"" ";
|
||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||
put ",""SYSSITE"" : ""&syssite"" ";
|
||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
||||
put "}";
|
||||
|
||||
%if %upcase(&fref) ne _WEBOUT %then %do;
|
||||
data _null_; rc=fcopy("&fref","_webout");run;
|
||||
%end;
|
||||
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
Reference in New Issue
Block a user