UNPKG

11.1 kBPlain TextView Raw
1/************************************************************************/
2/* .__ .________ _____ */
3/* | |__ | ____/ / | | ______ */
4/* | | \ |____ \ / | |_/ ___/ */
5/* | Y \/ \/ ^ /\___ \ */
6/* |___| /______ /\____ |/____ > */
7/* \/ \/ |__| \/ */
8/* */
9/************************************************************************/
10
11%GLOBAL h54ssource h54ssource2 h54slrecl h54snotes h54starget
12 h54sDeveloperMode h54sDebuggingMode _debug h54sIsViya;
13
14/* if we are developing, set this to 1; */
15%let h54sDeveloperMode = 0;
16/* this is always set to = to start with; */
17%let h54sDebuggingMode = 0;
18
19/* check platform */
20data _null_;
21 major = substr(symget("SYSVER"), 1, find(symget("SYSVER"), ".")-1);
22 if major eq "V" then do;
23 call symput('h54sIsViya', '1');
24 /* optimisations for avoiding reopening connection to
25 viya files service multiple times for appending output */
26 call symput('h54sBufferTarget', 'thiscall');
27 call symput('h54sJsonTarget', 'thisjson');
28 call symput('h54sBufferWriteMode', 'mod');
29 end;
30 else do;
31 call symput('h54sIsViya', '0');
32 call symput('h54sBufferTarget', '_webout');
33 call symput('h54sJsonTarget', '_webout');
34 call symput('h54sBufferWriteMode', '');
35 end;
36run;
37
38
39%macro bafQuietenDown;
40 %let h54ssource=%sysfunc(getoption(source));
41 %let h54ssource2=%sysfunc(getoption(source2));
42 %let h54slrecl=%sysfunc(getoption(lrecl));
43 %let h54snotes=%sysfunc(getoption(notes));
44 options nosource nosource2 nonotes;
45%mend;
46
47%macro bafQuietenUp;
48 options &h54ssource &h54ssource2 lrecl=&h54slrecl &h54snotes;
49%mend;
50
51
52/* go quiet while sourcing */
53%bafQuietenDown;
54
55%macro bafCheckDebug;
56 /* this runs for each request.
57 debugging mode inserts data delimiters
58 into SPWA output so log can be parsed out
59 */
60 %if &h54sIsViya = 0 %then %do;
61 %if %symExist(_debug) %then %do;
62 %if &_debug = 131 %then %do;
63 %let h54sDebuggingMode = 1;
64 %end;
65 %else %do;
66 %let h54sDebuggingMode = 0;
67 %end;
68 %end;
69 %end;
70%mend;
71
72
73%macro bafGetDatasets();
74 %bafCheckDebug;
75 /* quieten down the log unless we are debugging */
76 %if (&h54sDeveloperMode ne 1) %then %bafQuietenDown;
77
78 /* _WEBIN_NAME has the name of each parameter for the counterpart spec
79 _WEBIN_FILE_COUNT has the total number of files. If 1 then we need no suffix */
80 %if %symexist(_webin_file_count) = 0 %then %do;
81 %put [h54s] There are no WEBIN files;
82 %if (&h54sDeveloperMode ne 1) %then %bafQuietenUp;
83 /* No tables were sent */
84 %return;
85 %end;
86 %put [h54s] WEBIN file count is &_WEBIN_FILE_COUNT.;
87
88 /* Reserved uploads: Generic file uploads or OMI metadata queries.
89 bafpn is the index of a file described as FILE
90 bafxn is the index of a file described as XML
91 global vars initialised
92 */
93 %global bafpn;
94 %global bafxn;
95 %let bafpn=;
96 %let bafxn=;
97
98 /* baftn is the current index of the file (table) being iterated over */
99 %do files = 1 %to &_WEBIN_FILE_COUNT;
100 /* if there is only one file the counts do not get number suffix */
101 %if &_WEBIN_FILE_COUNT = 1 %then %let baftn=;
102 %else %do;
103 %let baftn=&files.;
104 %end;
105
106 /* references to file and spec */
107 %let thisobj=&&_WEBIN_name&baftn;
108 %let testspec=&&&&&&_WEBIN_name&baftn.;
109
110 %put [h54s] Evaluating filename &&&&_WEBIN_name&baftn;
111 /* if a spec comes back as FILE when it is not a table
112 if that is called MYFILE it is SAS code
113 if that is called XML it is an OMI metadata query
114 */
115 %if (%UPCASE("&&&&&&_WEBIN_name&baftn.") eq "FILE") %then %do;
116 %if (%UPCASE("&&&&_WEBIN_name&baftn.") eq "MYFILE") %then %do;
117 %let bafpn=&baftn.;
118 %put Found MYFILE (program) as input number &baftn.;
119 %end;
120 %else %if (%UPCASE("&&&&_WEBIN_name&baftn.") eq "XML") %then %do;
121 %let bafxn=&baftn.;
122 %put Found XML (meta query) as input number &baftn.;
123 %end;
124 %end;
125 %else %do;
126
127 /* build data step length and input statements for this input table */
128 data _null_;
129 length spec $32767;
130 length lenspec $50;
131 length varname $32;
132 spec=symget(symget(cats("_WEBIN_NAME","&baftn.")));
133 /* viya 3.5 - remove nrstr wrap and character escaping */
134 spec=prxchange("s/\%([\'\""\%\(\)])/$1/", -1 , prxchange('s/^\%nrstr\((.*)\)/$1/s', -1, spec));
135 colcount=countw(spec, '|');
136
137 do c=1 to colcount;
138 lenspec=scan(spec, c, '|');
139 varname=upcase(scan(lenspec,1,','));
140 select (scan(lenspec, 2, ','));
141 when ('num') do;
142 indef=varname!!':best16.';
143 end;
144 when ('string') do;
145 indef=cats(varname,':$',scan(lenspec, 3, ','),'.');
146 end;
147 when ('date') do;
148 indef=varname!!':best.';
149 end;
150 end;
151
152 /* input statement to macro */
153 pname=cats('cols', c);
154 call symputx(pname, indef, 'L');
155 output;
156 end;
157 call symputx('totalcol', colcount);
158 run;
159
160 /* parse the actual input data */
161
162 %put [h54s] start deserialising table &&_WEBIN_NAME&baftn. - table filename is &&_WEBIN_FILEREF&baftn. ;
163
164 %if &h54sIsViya eq 1 %then %do;
165
166 filename thisfile filesrvc "&&_WEBIN_FILEURI&baftn." ;
167 data "&&_WEBIN_NAME&baftn."n;
168 INFILE thisfile LRECL=32767 recfm=v dsd termstr=crlf;
169 input %do j=1 %to &totalcol.;
170 &&cols&j.
171 %end;
172 ;
173 run;
174
175 %end;
176 %else %do;
177
178 data "&&_WEBIN_NAME&baftn."n;
179 INFILE &&_WEBIN_FILEREF&baftn. LRECL=32767 recfm=v dsd termstr=crlf;
180 input %do j=1 %to &totalcol.;
181 &&cols&j.
182 %end;
183 ;
184 run;
185
186 %end;
187
188 %put [h54s] finish deserialising table &&_WEBIN_name&baftn. ;
189
190 %end;
191 %end;
192
193 %put [h54s] summary of all deserialised tables;
194 proc sql noprint;
195 %do files = 1 %to &_WEBIN_FILE_COUNT;
196 %if &_WEBIN_FILE_COUNT eq 1 %then %do;
197 %let baftn=;
198 %end;
199 %else %do;
200 %let baftn=&files.;
201 %end;
202 %if &baftn ne &bafpn and &baftn ne &bafxn %then %do;
203 describe table "&&_WEBIN_name&baftn."n;
204 %end;
205 %end;
206 %put [h54s] summary end;
207 quit;
208
209 %if (&h54sDeveloperMode ne 1) %then %bafQuietenUp;
210%mend;
211
212%macro bafOutDataset(outputas, outlib, outdsn, h54skeys=);
213 %bafCheckDebug;
214 %if (&h54sDeveloperMode ne 1) %then %bafQuietenDown;
215
216 data _null_;
217 file &h54sBufferTarget &h54sBufferWriteMode;
218 put '"' "&outputas." '" : ';
219 run;
220
221
222 %if (&h54sIsViya) %then %do;
223 filename &h54sJsonTarget temp;
224 %end;
225
226 %put [h54s] Writing JSON for &outlib..&outdsn. &h54skeys;
227
228 proc contents
229 data = &outlib..&outdsn.
230 noprint
231 out = _h54sinfo
232 (keep = name varnum type);
233 run;
234
235 %if (&h54skeys ne ) %then %do;
236 data _h54sinfo;
237 set _h54sinfo;
238 name = upcase(name);
239 varnum = varnum - 1;
240 run;
241 %end;
242
243 options validvarname=upcase;
244 proc json out=&h54sJsonTarget. ;
245 %if (&h54skeys ne ) %then %do;
246 write open array;
247 write open array;
248 export _h54sinfo / nosastags;
249 write close;
250 %end;
251 write open array;
252 export &outlib..&outdsn. / &h54skeys nosastags
253 nofmtnumeric nofmtdatetime;
254 write close;
255 %if (&h54skeys ne ) %then %do;
256 write close;
257 %end;
258 run;
259
260 %symdel h54skeys / nowarn;
261
262 %if (&h54sIsViya) %then %do;
263 data _null_;
264 length data $1;
265 INFILE &h54sJsonTarget recfm=n;
266 file &h54sBufferTarget recfm=n &h54sBufferWriteMode;
267 input data $char1. @@;
268 put data $char1. @@;
269 run;
270
271 %if (&h54sIsViya) %then %do;
272 filename &h54sJsonTarget clear;
273 %end;
274
275 %end;
276
277 data _null_;
278 file &h54sBufferTarget &h54sBufferWriteMode;
279 put ',';
280 run;
281 %if (&h54sDeveloperMode ne 1) %then %bafQuietenUp;
282%mend;
283
284
285%macro bafHeader();
286 %bafCheckDebug;
287 /* quieten down the log unless we are debugging */
288 %if (&h54sDeveloperMode ne 1) %then %bafQuietenDown;
289 /* create temp file */
290 %if (&h54sIsViya) %then %do;
291 filename &h54sBufferTarget temp;
292 %end;
293
294 data _null_;
295 file &h54sBufferTarget &h54sBufferWriteMode;
296 %if &h54sDebuggingMode = 1 %then %do;
297 put "--h54s-data-start--";
298 %end;
299 put '{';
300 run;
301 %if (&h54sDeveloperMode ne 1) %then %bafQuietenUp;
302%mend;
303
304
305%macro bafFooter();
306 %bafCheckDebug;
307 /* quieten down the log unless we are debugging */
308 %if (&h54sDeveloperMode ne 1) %then %bafQuietenDown;
309
310 %if (%symexist(usermessage) = 0) %then %do;
311 %let usermessage = blank;
312 %end;
313
314 %if (%symexist(logmessage) = 0) %then %do;
315 %let logmessage = blank;
316 %end;
317
318 %if (%symexist(h54src) = 0) %then %do;
319 %let h54src = success;
320 %end;
321
322
323 %if (&h54sIsViya) %then %do;
324 data _null_;
325 file &h54sBufferTarget &h54sBufferWriteMode;
326 sasdatetime=datetime();
327 put '"usermessage" : "' "&usermessage." '",';
328 put '"logmessage" : "' "&logmessage." '",';
329 put '"requestingUser" : "' "&SYS_COMPUTE_SESSION_OWNER." '",';
330 put '"requestingPerson" : "' "&SYS_COMPUTE_SESSION_OWNER." '",';
331 put '"executingPid" : ' "&sysjobid." ',';
332 put '"sasDatetime" : ' sasdatetime ',';
333 put '"status" : "' "&h54src." '"}';
334 put;
335 run;
336
337 /* JES files service is faster without updates
338 so bundle data into a temp filename first
339 http://support.sas.com/kb/20/784.html ; */
340 %put [h54s] Writing buffered output to Viya ;
341
342 data _null_;
343 length data $1;
344 INFILE &h54sBufferTarget recfm=n;
345 file _webout recfm=n ;
346 input data $char1. @@;
347 put data $char1. @@;
348 run;
349
350 %end;
351 %else %do;
352 data _null_;
353 file &h54sBufferTarget ;
354 sasdatetime=datetime();
355 put '"usermessage" : "' "&usermessage." '",';
356 put '"logmessage" : "' "&logmessage." '",';
357 put '"requestingUser" : "' "&_METAUSER." '",';
358 put '"requestingPerson" : "' "&_metaperson." '",';
359 put '"executingPid" : ' "&sysjobid." ',';
360 put '"sasDatetime" : ' sasdatetime ',';
361 put '"status" : "' "&h54src." '"}';
362 put;
363
364 %if &h54sDebuggingMode = 1 %then %do;
365 put "--h54s-data-end--";
366 %end;
367 run;
368
369 %end;
370
371 %if (&h54sDeveloperMode ne 1) %then %bafQuietenUp;
372%mend;
373
374/* come back after defining */
375%bafQuietenUp;