16length name $8 sex $1 age height weight 8;
18input Name:$char. Sex :$char. Age Height Weight;
44 infile datalines4 dsd;
45 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
46 OPERATOR_NM:$10. RAW_VALUE:$4000.;
50AND,OR,2,Name,NOT IN,
"('Jane','Alfred')"
51AND,OR,2,Weight,>=,77.7
52AND,OR,2,Weight,NE,77.7
55AND,AND,1,age,IN,
"(.a,.b,.)"
56AND,AND,1,age,IN,
"(.A)"
59AND,AND,1,AGE,BETWEEN,
"HEIGHT AND WEIGHT"
64%mp_assertscope(SNAPSHOT)
65%mp_filtercheck(work.inds,
67 outds=work.badrecords,
70%mp_assertscope(COMPARE)
73%mp_assertdsobs(work.badrecords,
74 desc=Valid filter query,
76 outds=work.test_results
81 infile datalines4 dsd;
82 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
83 OPERATOR_NM:$10. RAW_VALUE:$4000.;
87AND,OR,2,Name,NOT IN,
"('Jane','Alfred')"
91%mp_filtercheck(work.inds,
93 outds=work.badrecords,
97%mp_assertdsobs(work.badrecords,
98 desc=Invalid column name,
100 outds=work.test_results
105 infile datalines4 dsd;
106 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
107 OPERATOR_NM:$10. RAW_VALUE:$4000.;
109AND,OR,2,Name,NOT IN,
"(''''Jane','Alfred')"
113%mp_filtercheck(work.inds,
115 outds=work.badrecords,
119%mp_assertdsobs(work.badrecords,
120 desc=Invalid raw value,
122 outds=work.test_results
127 infile datalines4 dsd;
128 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
129 OPERATOR_NM:$10. RAW_VALUE:$4000.;
131AND,OR,2,age,IN,
"(.,.a,X)"
135%mp_filtercheck(work.inds,
137 outds=work.badrecords,
141%mp_assertdsobs(work.badrecords,
142 desc=Invalid IN value,
144 outds=work.test_results
149 infile datalines4 dsd;
150 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
151 OPERATOR_NM:$10. RAW_VALUE:$4000.;
158%mp_filtercheck(work.inds,
160 outds=work.badrecords,
164%mp_assertdsobs(work.badrecords,
165 desc=Code injection - column name,
167 outds=work.test_results
172 infile datalines4 dsd;
173 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
174 OPERATOR_NM:$10. RAW_VALUE:$4000.;
176AND,AND,1,age,=,;;%abort
179%mp_filtercheck(work.inds,
181 outds=work.badrecords,
185%mp_assertdsobs(work.badrecords,
186 desc=Code injection - raw value abort,
188 outds=work.test_results
193 infile datalines4 dsd;
194 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
195 OPERATOR_NM:$10. RAW_VALUE:8.;
201%mp_filtercheck(work.inds,
203 outds=work.badrecords,
206%mp_assert(iftrue=(&syscc=42),
207 desc=Throw a failure if RAW_VALUE is incorrect,
208 outds=work.test_results
214 infile datalines4 dsd;
215 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
216 OPERATOR_NM:$10. RAW_VALUE:$4000.;
218AND,AND,1,AGE,NOT IN,
"(height, age)"
222%mp_filtercheck(work.inds,
224 outds=work.badrecords,
228%mp_assertdsobs(work.badrecords,
229 desc=Invalid IN syntax,
231 outds=work.test_results
237 format dt date9. dtm datetime20. tm time8.;
239 dtm='01JAN1960:00:00:42'dt;
244 infile datalines4 dsd;
245 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
246 OPERATOR_NM:$10. RAW_VALUE:$4000.;
248AND,AND,1,dt,=,
"'20APR2042'd"
249AND,AND,1,dt,NE,
"'20APR2042'd"
250AND,AND,1,dtm,>=,
"'01JAN1960:00:00:42'dt"
251AND,AND,1,tm,<,
"'00:00:42't"
252AND,AND,1,dt,IN,
"('20APR2042'd,'21APR2042'd)"
253AND,AND,1,dt,BETWEEN,
"'20APR2042'd AND '21APR2042'd"
257%mp_filtercheck(work.inds,
259 outds=work.badrecords,
263%mp_assertdsobs(work.badrecords,
264 desc=Temporal literals in RAW_VALUE,
266 outds=work.test_results
271 infile datalines4 dsd;
272 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
273 OPERATOR_NM:$10. RAW_VALUE:$4000.;
275AND,AND,1,name,=,
"'20APR2042'd"
279%mp_filtercheck(work.inds,
281 outds=work.badrecords,
285%mp_assertdsobs(work.badrecords,
286 desc=Temporal literal against a character column,
288 outds=work.test_results
293 infile datalines4 dsd;
294 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
295 OPERATOR_NM:$10. RAW_VALUE:$4000.;
297AND,AND,1,dt,IN,
"('20APR2042'd,notanumber)"
301%mp_filtercheck(work.inds,
303 outds=work.badrecords,
307%mp_assertdsobs(work.badrecords,
308 desc=Invalid value after the first in an IN list,
310 outds=work.test_results
315 infile datalines4 dsd;
316 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
317 OPERATOR_NM:$10. RAW_VALUE:$4000.;
319AND,AND,1,dt,=,
"'20APR2042'x"
323%mp_filtercheck(work.inds,
325 outds=work.badrecords,
329%mp_assertdsobs(work.badrecords,
330 desc=Non temporal literal suffix,
332 outds=work.test_results
338 infile datalines4 dsd;
339 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
340 OPERATOR_NM:$10. RAW_VALUE:$4000.;
342AND,AND,1,name,IN,
"(Alfred,Alice)"
346%mp_filtercheck(work.inds,
348 outds=work.badrecords,
352%mp_assertdsobs(work.badrecords,
353 desc=Character IN list is still validated,
355 outds=work.test_results
360%let re_temporal_col=1;
363 dsid=open('work.badrecords
','i');
365 call symputx('re_temporal_col',(varnum(dsid,'RE_TEMPORAL')>0));
366 call symputx('vref_col',(varnum(dsid,'VREF')>0));
370%mp_assert(iftrue=(&re_temporal_col=0),
371 desc=re_temporal is not in the bad records table,
372 outds=work.test_results
374%mp_assert(iftrue=(&vref_col=0),
375 desc=vref is not in the bad records table,
376 outds=work.test_results
381 infile datalines4 dsd;
382 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
383 OPERATOR_NM:$10. RAW_VALUE:$4000.;
385AND,AND,1,Name,CONTAINS,
"'ar'"
386AND,AND,1,SEX,CONTAINS,
"'F'"
390%mp_filtercheck(work.inds,
392 outds=work.badrecords,
396%mp_assertdsobs(work.badrecords,
397 desc=CONTAINS on a character column,
399 outds=work.test_results
404 infile datalines4 dsd;
405 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
406 OPERATOR_NM:$10. RAW_VALUE:$4000.;
408AND,AND,1,Age,CONTAINS,
"'12'"
412%mp_filtercheck(work.inds,
414 outds=work.badrecords,
418%mp_assertdsobs(work.badrecords,
419 desc=CONTAINS on a numeric column,
421 outds=work.test_results
425%let contains_reason=0;
429 'CONTAINS is only valid for character variables - work.class.Age is numeric')>0
430 then call symputx('contains_reason',1);
432%mp_assert(iftrue=(&contains_reason=1),
433 desc=CONTAINS rejection names the variable,
434 outds=work.test_results
440 infile datalines4 dsd;
441 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
442 OPERATOR_NM:$10. RAW_VALUE:$4000.;
444AND,AND,1,Age,CONTAINS,abc
448%mp_filtercheck(work.inds,
450 outds=work.badrecords,
454%mp_assertdsobs(work.badrecords,
455 desc=CONTAINS numeric rejection emits a single row,
457 outds=work.test_results
460%let contains_single=0;
464 'CONTAINS is only valid for character variables - work.class.Age is numeric')>0
465 then call symputx('contains_single',1);
467%mp_assert(iftrue=(&contains_single=1),
468 desc=CONTAINS numeric rejection keeps its reason,
469 outds=work.test_results
475 infile datalines4 dsd;
476 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
477 OPERATOR_NM:$10. RAW_VALUE:$4000.;
479AND,AND,1,Name,CONTAINS,12
483%mp_filtercheck(work.inds,
485 outds=work.badrecords,
489%mp_assertdsobs(work.badrecords,
490 desc=CONTAINS with an unquoted numeric value,
492 outds=work.test_results
495%let contains_operand=0;
499 'CONTAINS requires a quoted value or a character variable - work.class.Name CONTAINS 12')
500 >0 then call symputx('contains_operand',1);
502%mp_assert(iftrue=(&contains_operand=1),
503 desc=CONTAINS operand rejection names the value,
504 outds=work.test_results
509 infile datalines4 dsd;
510 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
511 OPERATOR_NM:$10. RAW_VALUE:$4000.;
513AND,AND,1,Name,CONTAINS,SEX
517%mp_filtercheck(work.inds,
519 outds=work.badrecords,
523%mp_assertdsobs(work.badrecords,
524 desc=CONTAINS with a character variable operand,
526 outds=work.test_results
531 length GROUP_LOGIC $3 SUBGROUP_LOGIC $3 SUBGROUP_ID 8 VARIABLE_NM $32
532 OPERATOR_NM $10 RAW_VALUE $4000;
534 SUBGROUP_LOGIC='AND';
537 OPERATOR_NM='CONTAINS';
541%mp_filtercheck(work.inds,
543 outds=work.badrecords,
547%mp_assertdsobs(work.badrecords,
548 desc=CONTAINS with a leading blank before the quote,
550 outds=work.test_results
555 infile datalines4 dsd;
556 input GROUP_LOGIC:$3. SUBGROUP_LOGIC:$3. SUBGROUP_ID:8. VARIABLE_NM:$32.
557 OPERATOR_NM:$10. RAW_VALUE:$4000.;
559AND,AND,1,Name,CONTAINS,Age
563%mp_filtercheck(work.inds,
565 outds=work.badrecords,
569%let operand_type_reason=0;
573 'Compared Type (N) is not (C) - work.class.Name CONTAINS Age')>0
574 then call symputx('operand_type_reason',1);
576%mp_assert(iftrue=(&operand_type_reason=1),
577 desc=CONTAINS with a numeric variable operand,
578 outds=work.test_results