Loading...
Searching...
No Matches
viewdata.sas
Go to the documentation of this file.
1/**
2 @file viewdata.sas
3 @brief Provide the raw view of the data
4 @details Pass a LIBDS and FILTER_RK to return a dataset for viewing.
5 VIEW datasets include all columns / rows (unlike EDIT, which are filtered
6 for current records and don't include the SCD2 etc cols).
7
8 <h4> Service Inputs </h4>
9
10 <h5> SASCONTROLTABLE </h5>
11 |LIBDS:$41.|FILTER_RK:best.|SEARCHTYPE:$4|SEARCHVAL:$100|
12 |---|---|---|---
13 |DC258467.MPE_X_TEST|-1|CHAR|Some String|
14
15 No input column may be longer than the length declared in this service -
16 LIBDS 41, SEARCHTYPE 4, SEARCHVAL 100. An input column longer than the
17 declared length stops the step with "Multiple lengths were specified for
18 the variable ...", so the SASjs adapter sends the $char form (eg $char4.),
19 which also preserves any leading blanks.
20
21 <h4> Service Outputs </h4>
22
23 <h5> cols </h5>
24 @li DDTYPE - C=CHARACTER, N=NUMERIC, else DATE / TIME / DATETIME
25 @li FORMAT
26 @li LABEL
27 @li LENGTH
28 @li NAME
29 @li TYPE
30
31 <h5> sasparams </h5>
32 @li FILTER_TEXT
33 @li NOBS
34 @li PK_FIELDS - string seperated list of primary key fields, if they exist
35 @li TABLENAME
36 @li TABLEURI
37 @li VARS
38
39 <h5> versions </h5>
40 history of DC versions for this particular table
41
42 <h5> viewdata </h5>
43 The raw data from the target table.
44
45 <h4> SAS Macros </h4>
46 @li dc_assignlib.sas
47 @li dc_casload.sas
48 @li dc_createdataset.sas
49 @li dc_gettableid.sas
50 @li mf_existds.sas
51 @li mf_getvarcount.sas
52 @li mf_nobs.sas
53 @li mf_verifymacvars.sas
54 @li mp_abort.sas
55 @li mp_cntlout.sas
56 @li mp_getcols.sas
57 @li mp_getpk.sas
58 @li mp_jsonout.sas
59 @li mp_searchdata.sas
60 @li mp_validatecol.sas
61 @li mpe_columnlevelsecurity.sas
62 @li mpe_dsmeta.sas
63 @li mpe_getversions.sas
64 @li mpe_filtermaster.sas
65
66
67 @version 9.2
68 @author 4GL Apps Ltd
69 @copyright 4GL Apps Ltd. This code may only be used within Data Controller
70 and may not be re-distributed or re-sold without the express permission of
71 4GL Apps Ltd.
72**/
73
74%mpeinit()
75
76/* configure macvars */
77%global LIBDS FILTER_RK SEARCHVAL SEARCHTYPE FMT_IND;
78
79/* avoid code injection */
80%let FMT_IND=0;
81%let SEARCHTYPE=;
82%let SEARCHVAL=;
83%let FILTER_RK=;
84%let LIBDS=;
85
86/**
87 * Validate inputs
88 */
89data work.intest;
90 length libds $41 filter_rk 8. searchval $100 searchtype $4;
91 set work.SASCONTROLTABLE;
92 call symputx('orig_libds',libds);
93 /* validate filter_rk */
94 if filter_rk le 0 then filter_rk=-1;
95
96 /* check if the request is for a format catalog */
97 if substr(cats(reverse(libds)),1,3)=:'CF-' then do;
98 libds=scan(libds,1,'-');
99 putlog "Format Catalog Captured";
100 call symputx('fmt_ind',1);
101 end;
102 putlog (_all_)(=);
103
104 /* validate libds */
105 %mp_validatecol(LIBDS,LIBDS,is_libds)
106
107 if searchtype in ('CHAR','NUM') then do;
108 searchval=tranwrd(searchval,'%','');
109 searchval=tranwrd(searchval,'&','');
110 searchval=tranwrd(searchval,';','');
111 searchval=tranwrd(searchval,'"','');
112 call symputx('searchtype',searchtype);
113 call symputx('searchval',searchval);
114 end;
115 else if searchtype not in ('','NONE') then do;
116 putlog 'ERR' 'OR: Invalid searchtype:' searchtype;
117 stop;
118 end;
119
120 if is_libds=0 then do;
121 putlog 'ERR' 'OR: Invalid libds:' libds;
122 stop;
123 end;
124 else do;
125 call symputx('filter_rk',filter_rk);
126 call symputx('libds',libds);
127 end;
128 output;
129 stop;
130run;
131
132%mp_abort(iftrue= (%mf_verifymacvars(libds filter_rk fmt_ind)=0)
133 ,mac=&_program..sas
134 ,msg=%str(Problem with macro inputs)
135)
136
137%mp_abort(iftrue= (%mf_nobs(work.intest)=0)
138 ,mac=&_program
139 ,msg=%str(Some err with service inputs)
140)
141%mp_abort(iftrue= (&syscc ne 0)
142 ,mac=&_program..sas
143 ,msg=%str(syscc=&syscc)
144)
145
146
147/**
148 * assign the Library
149 */
150%dc_assignlib(READ,%scan(&LIBDS,1,.))
151%dc_casload(&libds)
152
153/* abort if looking for a format and the catalog doesn't exist */
154%mp_abort(iftrue= (&fmt_ind=1 and %sysfunc(exist(&libds,CATALOG))=0)
155 ,mac=&_program..sas
156 ,msg=%str(Catalog &libds does not exist!)
157)
158
159/**
160 check if dataset can actually be opened - as library may exist but it may not
161 be possible to assign, and even if it can, the physical table may not exist
162**/
163data _null_;
164 if &fmt_ind=0 then do;
165 dsid=open("&libds");
166 rc=close(dsid);
167 end;
168 else dsid=42;
169 call symputx('existds',dsid,'l');
170 putlog 'dataset exists check:' dsid;
171run;
172
173/**
174 * get the data
175 */
176%global dsobs;
177%let dsobs=0;
178%macro x();
179%if not %symexist(DC_MAXOBS_WEBVIEW) %then %do;
180 %put NOTE:;%put NOTE- DC_MAXOBS_WEBVIEW not found!;
181 %put NOTE- Please add to &mpelib..MPE_CONFIG table;
182 %put NOTE-;%put NOTE-;
183 %global DC_MAXOBS_WEBVIEW;
184 %let DC_MAXOBS_WEBVIEW=500;
185%end;
186%if &existds>0 %then %do;
187
188 %if &fmt_ind=1 %then %do;
189 /* export format and point the libds to the output table from here on */
190 %mp_cntlout(
191 libcat=&libds
192 ,fmtlist=0
193 ,cntlout=work.fmtextract
194 )
195 %let libds=WORK.FMTEXTRACT;
196 proc datasets lib=work noprint;
197 modify FMTEXTRACT;
198 index create
199 pk_cntlout=(type fmtname fmtrow)
200 /nomiss unique;
201 quit;
202 %end;
203
204 proc sql noprint;
205 select count(*) into: dsobs from &libds;
206
207 %put preparing query;
208 %mpe_filtermaster(VIEW,&libds,
209 dclib=&mpelib,
210 filter_rk=&filter_rk,
211 outref=filtref,
212 outds=work.query
213 )
214 %put printing generated filterquery:;
215 data _null_;
216 infile filtref;
217 input;
218 putlog _infile_;
219 run;
220
221 %if &searchtype=NONE or "%trim(&searchtype) " = " " %then %do;
222 /* get row count */
223 filename rows temp;
224 data _null_;
225 file rows;
226 infile filtref end=eof;
227 input;
228 if _n_=1 then do;
229 put 'proc sql;';
230 put "select count(*) into: dsobs from &libds where";
231 end;
232 put _infile_;
233 if eof then put ';';
234 run;
235 data _null_;
236 infile rows;
237 input;
238 putlog _infile_;
239 run;
240
241 %inc rows;
242
243 /* send actual data, filtered and row-capped */
244 data work.viewdata;
245 set &libds;
246 where %inc filtref;;
247 if _n_>&DC_MAXOBS_WEBVIEW then stop;
248 run;
249 %if %mf_nobs(work.viewdata)=0 %then %do;
250 data work.viewdata;
251 /* send empty row if empty table to help with hot rendering */
252 output;
253 set work.viewdata;
254 run;
255 %end;
256 %end;
257 %else %do;
258 data work.vwsearch/view=work.vwsearch;
259 set &libds;
260 where %inc filtref;;
261 run;
262 %if %upcase(&searchtype)=CHAR %then %do;
263 %mp_searchdata(lib=work
264 ,ds=vwsearch
265 ,string=%superq(searchval)
266 ,outobs=&DC_MAXOBS_WEBVIEW
267 )
268 %end;
269 %else %if %upcase(&searchtype)=NUM %then %do;
270 %mp_searchdata(lib=work
271 ,ds=vwsearch
272 ,numval=%superq(searchval)
273 ,outobs=&DC_MAXOBS_WEBVIEW
274 )
275 %end;
276 %if %mf_existds(libds=MPSEARCH.vwsearch) %then %do;
277 %let dsobs=%mf_nobs(MPSEARCH.vwsearch);
278 data viewdata;
279 set MPSEARCH.vwsearch;
280 if _n_<=&DC_MAXOBS_WEBVIEW;
281 run;
282 %end;
283 %else %do;
284 %let dsobs=0;
285 data viewdata;
286 set &libds;
287 stop;
288 run;
289 %end;
290 %end;
291%end;
292%else %do;
293 /* physical table is not accessible so create from metatadata definition */
294 %dc_createdataset(libds=&libds,outds=viewdata)
295 data viewData;
296 output;
297 set viewdata;
298 run;
299
300 /* make filtref / work.query / work.groups to avoid downstream issues */
301 filename filtref temp;
302 data work.query;
303 file filtref;
304 x=0;
305 put x;
306 run;
307 data work.groups;
308 length groupuri groupname $32 groupdesc $128 ;
309 call missing (of _all_);
310 output;
311 stop;
312 run;
313%end;
314%mend x; %x()
315
316/* apply column level security */
317%mpe_columnlevelsecurity(%scan(&libds,1,.),%scan(&libds,2,.),work.viewdata
318 ,mode=VIEW
319 ,clsds=&mpelib..mpe_column_level_security
320 ,groupds=work.groups /* was created in mpe_filtermaster */
321 ,outds=work.viewdata2
322 ,outmeta=work.cls_rules
323)
324
325
326/* get table uri (if sas 9) to enable linking direct to lineage */
327%dc_gettableid(libref=%scan(&libds,1,.)
328 ,ds=%scan(&libds,2,.)
329 ,outds=work.parambase
330)
331
332data _null_;
333 infile filtref end=eof;
334 input;
335 length filter_text $32767;
336 retain filter_text;
337 filter_text=catx(' ',filter_text,_infile_);
338 if eof then do;
339 if cats(filter_text)='1=1' then filter_text='';
340 call symputx('filter_text',filter_text);
341 end;
342run;
343
344%mp_getpk(%scan(&libds,1,.), ds=%scan(&libds,2,.), outds=work.pk_fields)
345
346%let pk_fields=;
347data _null_;
348 set work.pk_fields;
349 call symputx('pk_fields',pk_fields);
350run;
351
352data work.sasparams;
353 set work.parambase;
354 format FILTER_TEXT $32767.;
355 FILTER_TEXT=symget('FILTER_TEXT');
356 length PK_FIELDS $512;
357 PK_FIELDS=symget('PK_FIELDS');
358 nobs=&dsobs;
359 vars=%mf_getvarcount(viewdata);
360 maxrows=&DC_MAXOBS_WEBVIEW;
361run;
362
363%mp_abort(iftrue= (&syscc ne 0)
364 ,mac=&_program..sas
365 ,msg=%str(syscc=&syscc)
366)
367
368%mp_getcols(&libds, outds=cols1)
369
370/* trim COLS payload in the SQL below - DDTYPE C=CHARACTER N=NUMERIC
371 (dates kept in full), VARNUM dropped (client relies on column order,
372 not position) */
373proc sql;
374create table cols as
375 select a.name
376 ,a.type
377 ,a.length
378 ,a.format
379 ,a.fmtname
380 ,case a.ddtype
381 when 'CHARACTER' then 'C'
382 when 'NUMERIC' then 'N'
383 else a.ddtype end as ddtype
384 ,coalesce(b.dd_shortdesc,a.label,a.name) as label
385 from cols1 a
386 left join &mpelib..mpe_datadictionary
387 (where=(&dc_dttmtfmt. < tx_to
388 and dd_source ? %upcase("&orig_libds")
389 and dd_type='COLUMN')) b
390 on scan(b.dd_source,-1,'.')=upcase(a.name);
391quit;
392
393
394%mpe_dsmeta(&orig_libds, outds=dsmeta)
395
396%mpe_getversions(&mpelib,
397 %scan(&orig_libds,1,.),
398 %scan(&orig_libds,2,.),
399 outds=versions
400)
401
402%webout(OPEN)
403%webout(OBJ,cls_rules)
404%webout(OBJ,cols)
405%webout(OBJ,dsmeta)
406%webout(OBJ,query)
407%webout(OBJ,sasparams)
408%webout(OBJ,versions)
409%webout(OBJ,viewData2,fmt=Y,missing=STRING,showmeta=YES,dslabel=viewdata)
410%webout(CLOSE)
411
412%mpeterm()