Production Ready Macros for SAS Application Developers
https://github.com/sasjs/core
mm_webout.sas
Go to the documentation of this file.
1/**
2 @file mm_webout.sas
3 @brief Send data to/from SAS Stored Processes
4 @details This macro should be added to the start of each Stored Process,
5 **immediately** followed by a call to:
6
7 %mm_webout(FETCH)
8
9 This will read all the input data and create same-named SAS datasets in the
10 WORK library. You can then insert your code, and send data back using the
11 following syntax:
12
13 data some datasets; * make some data ;
14 retain some columns;
15 run;
16
17 %mm_webout(OPEN)
18 %mm_webout(ARR,some) * Array format, fast, suitable for large tables ;
19 %mm_webout(OBJ,datasets) * Object format, easier to work with ;
20
21 Finally, wrap everything up send some helpful system variables too
22
23 %mm_webout(CLOSE)
24
25
26 @param action Either FETCH, OPEN, ARR, OBJ or CLOSE
27 @param ds The dataset to send back to the frontend
28 @param dslabel= value to use instead of the real name for sending to JSON
29 @param fmt=(Y) Set to N to send back unformatted values
30 @param fref=(_webout) The fileref to which to write the JSON
31
32 @version 9.3
33 @author Allan Bowe
34
35**/
36%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y);
37%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug
38 sasjs_tables;
39%local i tempds jsonengine;
40
41/* see https://github.com/sasjs/core/issues/41 */
42%if "%upcase(&SYSENCODING)" ne "UTF-8" %then %let jsonengine=PROCJSON;
43%else %let jsonengine=DATASTEP;
44
45
46%if &action=FETCH %then %do;
47 %if %str(&_debug) ge 131 %then %do;
48 options mprint notes mprintnest;
49 %end;
50 %let _webin_file_count=%eval(&_webin_file_count+0);
51 /* now read in the data */
52 %do i=1 %to &_webin_file_count;
53 %if &_webin_file_count=1 %then %do;
54 %let _webin_fileref1=&_webin_fileref;
55 %let _webin_name1=&_webin_name;
56 %end;
57 data _null_;
58 infile &&_webin_fileref&i termstr=crlf;
59 input;
60 call symputx('input_statement',_infile_);
61 putlog "&&_webin_name&i input statement: " _infile_;
62 stop;
63 data &&_webin_name&i;
64 infile &&_webin_fileref&i firstobs=2 dsd termstr=crlf encoding='utf-8';
65 input &input_statement;
66 %if %str(&_debug) ge 131 %then %do;
67 if _n_<20 then putlog _infile_;
68 %end;
69 run;
70 %let sasjs_tables=&sasjs_tables &&_webin_name&i;
71 %end;
72%end;
73
74%else %if &action=OPEN %then %do;
75 /* fix encoding */
76 OPTIONS NOBOMFILE;
77
78 /**
79 * check xengine type to avoid the below err message:
80 * > Function is only valid for filerefs using the CACHE access method.
81 */
82 data _null_;
83 set sashelp.vextfl(where=(fileref="_WEBOUT"));
84 if xengine='STREAM' then do;
85 rc=stpsrv_header('Content-type',"text/html; encoding=utf-8");
86 end;
87 run;
88
89 /* setup json */
90 data _null_;file &fref encoding='utf-8';
91 %if %str(&_debug) ge 131 %then %do;
92 put '>>weboutBEGIN<<';
93 %end;
94 put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
95 run;
96
97%end;
98
99%else %if &action=ARR or &action=OBJ %then %do;
100 %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
101 ,engine=&jsonengine,dbg=%str(&_debug)
102 )
103%end;
104%else %if &action=CLOSE %then %do;
105 %if %str(&_debug) ge 131 %then %do;
106 /* if debug mode, send back first 10 records of each work table also */
107 options obs=10;
108 data;run;%let tempds=%scan(&syslast,2,.);
109 ods output Members=&tempds;
110 proc datasets library=WORK memtype=data;
111 %local wtcnt;%let wtcnt=0;
112 data _null_;
113 set &tempds;
114 if not (upcase(name) =:"DATA"); /* ignore temp datasets */
115 i+1;
116 call symputx('wt'!!left(i),name,'l');
117 call symputx('wtcnt',i,'l');
118 data _null_; file &fref mod encoding='utf-8';
119 put ",""WORK"":{";
120 %do i=1 %to &wtcnt;
121 %let wt=&&wt&i;
122 proc contents noprint data=&wt
123 out=_data_ (keep=name type length format:);
124 run;%let tempds=%scan(&syslast,2,.);
125 data _null_; file &fref mod encoding='utf-8';
126 dsid=open("WORK.&wt",'is');
127 nlobs=attrn(dsid,'NLOBS');
128 nvars=attrn(dsid,'NVARS');
129 rc=close(dsid);
130 if &i>1 then put ','@;
131 put " ""&wt"" : {";
132 put '"nlobs":' nlobs;
133 put ',"nvars":' nvars;
134 %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=&jsonengine)
135 %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=&jsonengine)
136 data _null_; file &fref mod encoding='utf-8';
137 put "}";
138 %end;
139 data _null_; file &fref mod encoding='utf-8';
140 put "}";
141 run;
142 %end;
143 /* close off json */
144 data _null_;file &fref mod encoding='utf-8';
145 _PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
146 put ",""SYSUSERID"" : ""&sysuserid"" ";
147 put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
148 put ",""_DEBUG"" : ""&_debug"" ";
149 _METAUSER=quote(trim(symget('_METAUSER')));
150 put ",""_METAUSER"": " _METAUSER;
151 _METAPERSON=quote(trim(symget('_METAPERSON')));
152 put ',"_METAPERSON": ' _METAPERSON;
153 put ',"_PROGRAM" : ' _PROGRAM ;
154 put ",""SYSCC"" : ""&syscc"" ";
155 put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
156 put ",""SYSHOSTNAME"" : ""&syshostname"" ";
157 put ",""SYSJOBID"" : ""&sysjobid"" ";
158 put ",""SYSSCPL"" : ""&sysscpl"" ";
159 put ",""SYSSITE"" : ""&syssite"" ";
160 sysvlong=quote(trim(symget('sysvlong')));
161 put ',"SYSVLONG" : ' sysvlong;
162 put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
163 put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
164 put "}" @;
165 %if %str(&_debug) ge 131 %then %do;
166 put '>>weboutEND<<';
167 %end;
168 run;
169%end;
170
171%mend mm_webout;