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