24%mddl_derivedvars(libds=work.dvcfg)
28 set libref='WORK',dsn='CLASS',var_nm='band',var_deps='AGE'
29 ,var_type='C',var_len=8,var_fmt='',active=1
30 ,var_logic="ifc(AGE>13,'TEEN','JUNIOR')";
32 set libref='WORK',dsn='CLASS',var_nm='band_age',var_deps='BAND AGE'
33 ,var_type='C',var_len=16,var_fmt='',active=1
34 ,var_logic="cats(BAND,'-',AGE)";
36 set libref='WORK',dsn='CLASS',var_nm='double_age',var_deps='AGE'
37 ,var_type='N',var_len=8,var_fmt='',active=1
41 set libref='WORK',dsn='CLASS',var_nm='band_label',var_deps='BAND SEX'
42 ,var_type='C',var_len=32,var_fmt='',active=1
43 ,var_logic="cats(BAND,'-',SEX)";
46 set libref='WORK',dsn='CLASS',var_nm='ignored',var_deps=''
47 ,var_type='C',var_len=8,var_fmt='',active=0
53%mp_assertscope(SNAPSHOT)
62 reserved=%str(_____DELETE__THIS__RECORD_____ TX_FROM TX_TO)
66%mp_assertdsobs(work.dvnames,
67 desc=Only the active variables are returned,
69 outds=work.test_results
72%mp_assertcols(work.vw_dv,
73 desc=The view carries the derived columns,
74 cols=BAND BAND_AGE DOUBLE_AGE BAND_LABEL,
76 outds=work.test_results
80 iftrue=(%mf_existvar(work.vw_dv,IGNORED)=0),
81 desc=The inactive variable is not in the view,
82 outds=work.test_results
89 if band_age ne cats(band,'-',AGE) then output;
90 if double_age ne AGE*2 then output;
91 if band_label ne cats(band,'-',SEX) then output;
94%mp_assertdsobs(work.chk,
95 desc=Derived values and chained values are correct,
97 outds=work.test_results
105%mp_assertdsobs(work.chk2,
106 desc=A derived variable can be filtered on,
108 outds=work.test_results
112proc contents noprint data=work.vw_dv out=work.vcols(keep=name label);
117 where name='BAND' and label=:'BAND=ifc(AGE>13';
120%mp_assertdsobs(work.chklab,
121 desc=The label carries the variable name and the expression,
123 outds=work.test_results
127 iftrue=("%mf_existds(libds=work.vw_dv)"="1"),
128 desc=The view was built,
129 outds=work.test_results
135 infile derref truncover;
141 set work.stmts end=eof;
142 retain band_seq bandage_seq;
143 if prxmatch('/^BAND\s*=/',strip(line)) and missing(band_seq) then band_seq=seq;
144 if prxmatch('/^BAND_AGE\s*=/',strip(line)) and missing(bandage_seq)
145 then bandage_seq=seq;
147 if missing(band_seq) or missing(bandage_seq) or band_seq>=bandage_seq
151%mp_assertdsobs(work.chkord,
152 desc=BAND is assigned before BAND_AGE whatever order the rows were loaded,
154 outds=work.test_results
158%mddl_derivedvars(libds=work.dvcfg_label)
161insert into work.dvcfg_label
162 set libref='WORK',dsn='CLASS',var_nm='band',var_deps='AGE'
163 ,var_type='C',var_len=8,var_fmt='',var_label='Age band'
164 ,var_logic="ifc(AGE>13,'TEEN','JUNIOR')",active=1;
165insert into work.dvcfg_label
166 set libref='WORK',dsn='CLASS',var_nm='double_age',var_deps='AGE'
167 ,var_type='N',var_len=8,var_fmt='',var_label=''
168 ,var_logic='AGE * 2',active=1;
173 control=work.dvcfg_label,
175 outview=work.vw_label
181 infile derref7 truncover;
186 set work.stmts7 end=eof;
187 retain found_custom found_default;
188 if index(line,"label='Age band'")>0 then found_custom=1;
189 if index(line,"label='DOUBLE_AGE=AGE * 2'")>0 then found_default=1;
191 if not found_custom or not found_default then output;
194%mp_assertdsobs(work.chklbl,
195 desc=VAR_LABEL is used when set and defaults when blank,
197 outds=work.test_results
203%mddl_derivedvars(libds=work.derived_vars)
206insert into work.derived_vars
207 set libref='WORK',dsn='CLASS',var_nm='band',var_deps='AGE'
208 ,var_type='C',var_len=8,var_fmt='',active=1
209 ,var_logic="ifc(AGE>13,'TEEN','JUNIOR')";
214 control=work.derived_vars,
216 outview=work.vw_default
220 iftrue=(0 < %mf_existvar(work.vw_default,BAND)),
221 desc=The default outvars does not overwrite the control table,
222 outds=work.test_results
226 iftrue=(%mf_nobs(work.derived_vars)=1),
227 desc=The control table survives the default outvars name,
228 outds=work.test_results
235 control=work.derived_vars,
236 where=%str(var_nm ne "NOPE"),
238 outvars=work.dvnames11,
239 outview=work.vw_wherequote
242%mp_assertdsobs(work.dvnames11,
243 desc=A filter containing quotes is applied,
245 outds=work.test_results
249 iftrue=(0 < %mf_existvar(work.vw_wherequote,BAND)),
250 desc=The view is still built when the filter contains quotes,
251 outds=work.test_results
255%mddl_derivedvars(libds=work.dvcfg_empty)
259 control=work.dvcfg_empty,
261 outview=work.vw_empty,
262 outvars=work.dvnames3
265%mp_assertdsobs(work.dvnames3,
266 desc=No rows in the control table means no variables,
268 outds=work.test_results
272 iftrue=(%mf_existds(libds=work.vw_empty)=0),
273 desc=No view is built when there is nothing to derive,
274 outds=work.test_results
280 control=work.doesnotexist,
282 outvars=work.dvnames4
285%mp_assertdsobs(work.dvnames4,
286 desc=A missing control table yields no variables,
288 outds=work.test_results
294%mddl_derivedvars(libds=work.dvcfg_diamond)
297insert into work.dvcfg_diamond
298 set libref='WORK',dsn='CLASS',var_nm='v5',var_deps='SEX V4'
299 ,var_type='C',var_len=40,var_fmt='',var_logic="cats(SEX,'-',put(V4,best12.))"
301insert into work.dvcfg_diamond
302 set libref='WORK',dsn='CLASS',var_nm='v4',var_deps='V2 V3'
303 ,var_type='N',var_len=8,var_fmt='',var_logic='V2 + V3',active=1;
304insert into work.dvcfg_diamond
305 set libref='WORK',dsn='CLASS',var_nm='v3',var_deps='V1'
306 ,var_type='N',var_len=8,var_fmt='',var_logic='V1 + 1',active=1;
307insert into work.dvcfg_diamond
308 set libref='WORK',dsn='CLASS',var_nm='v2',var_deps='V1'
309 ,var_type='N',var_len=8,var_fmt='',var_logic='V1 * 2',active=1;
310insert into work.dvcfg_diamond
311 set libref='WORK',dsn='CLASS',var_nm='v1',var_deps='AGE'
312 ,var_type='N',var_len=8,var_fmt='',var_logic='AGE + 0',active=1;
317 control=work.dvcfg_diamond,
319 outview=work.vw_diamond
322%mp_assertcols(work.vw_diamond,
323 desc=The diamond graph is fully materialised,
326 outds=work.test_results
331 if v1 ne age then output;
332 if v2 ne age*2 then output;
333 if v3 ne age+1 then output;
334 if v4 ne age*3+1 then output;
335 if v5 ne cats(sex,'-',put(age*3+1,best12.)) then output;
338%mp_assertdsobs(work.chkdiamond,
339 desc=Every variable in the diamond graph resolves to the right value,
341 outds=work.test_results
346 infile derref8 truncover;
350 if prxmatch('/^V\d+\s*=/',strip(line)) then nm=scan(strip(line),1,'=');
355 set work.chkorder end=eof;
356 retain s1 s2 s3 s4 s5;
357 if nm='V1' then s1=seq;
358 if nm='V2' then s2=seq;
359 if nm='V3' then s3=seq;
360 if nm='V4' then s4=seq;
361 if nm='V5' then s5=seq;
363 if missing(s1) or missing(s2) or missing(s3) or missing(s4) or missing(s5)
365 else if s1 ge min(s2,s3) then output;
366 else if max(s2,s3) ge s4 then output;
367 else if s4 ge s5 then output;
370%mp_assertdsobs(work.chkorder2,
371 desc=The diamond graph is assigned in dependency order,
373 outds=work.test_results
378%mddl_derivedvars(libds=work.dvcfg_long)
382 logic=cats("ifc(AGE>13,'",repeat('a',300),"','
short')");
386insert into work.dvcfg_long
387 (libref,dsn,var_nm,var_deps,var_type,var_len,var_fmt,var_logic,active)
388 select 'WORK','CLASS','LONG_LABEL','AGE','C',400,'',logic,1
394 control=work.dvcfg_long,
400 infile derref9 truncover;
402 if index(line,"label='")>0 and mod(count(line,"'"),2) ne 0 then output;
405%mp_assertdsobs(work.chkquotes,
406 desc=A truncated label keeps an even quote count,
408 outds=work.test_results
412 iftrue=(%mf_existds(libds=work.vw_long)=1),
413 desc=A label longer than the limit still builds the view,
414 outds=work.test_results
423%mddl_derivedvars(libds=work.dvcfg_multi)
426insert into work.dvcfg_multi
427 set libref='WORK',dsn='CLASS',var_nm='scaled',var_deps='AGE'
428 ,var_type='N',var_len=8,var_fmt='',var_logic='AGE + 100',active=1;
429insert into work.dvcfg_multi
430 set libref='WORK',dsn='CLASS2',var_nm='scaled',var_deps='AGE'
431 ,var_type='N',var_len=8,var_fmt='dollar12.2',var_logic='AGE + 200',active=1;
436 control=work.dvcfg_multi,
438 outview=work.vw_multi1
443 control=work.dvcfg_multi,
445 outview=work.vw_multi2
449 merge work.vw_multi1(keep=name age scaled rename=(scaled=scaled1))
450 work.vw_multi2(keep=name age scaled rename=(scaled=scaled2));
452 if scaled1 ne age + 100 then output;
453 if scaled2 ne age + 200 then output;
456%mp_assertdsobs(work.chkmulti,
457 desc=The same variable name means different things per table,
459 outds=work.test_results
465 infile derref10 truncover;
467 if index(line,'format=DOLLAR12.2')>0 then output;
470%mp_assertdsobs(work.chkfmt,
471 desc=A configured format is applied,
473 outds=work.test_results
476%mp_assertscope(COMPARE,ignorelist=_SASJS_WEBOUT_HEADERS,outds=work.test_results)