1
0
mirror of https://github.com/sasjs/core.git synced 2026-01-05 16:40:06 +00:00

Merge pull request #229 from sasjs/runtimeissues

Improving WPS compatibility
This commit is contained in:
Allan Bowe
2022-05-03 18:48:18 +03:00
committed by GitHub
8 changed files with 211 additions and 35 deletions

80
all.sas
View File

@@ -994,12 +994,12 @@ or %index(&pgm,/tests/testteardown)
@brief Returns an unused libref @brief Returns an unused libref
@details Use as follows: @details Use as follows:
libname mclib0 (work); libname mclib0 (work);
libname mclib1 (work); libname mclib1 (work);
libname mclib2 (work); libname mclib2 (work);
%let libref=%mf_getuniquelibref(); %let libref=%mf_getuniquelibref();
%put &=libref; %put &=libref;
which returns: which returns:
@@ -1148,33 +1148,50 @@ or %index(&pgm,/tests/testteardown)
@file @file
@brief Returns number of variables in a dataset @brief Returns number of variables in a dataset
@details Useful to identify those renagade datasets that have no columns! @details Useful to identify those renagade datasets that have no columns!
Can also be used to count for numeric, or character columns
%put Number of Variables=%mf_getvarcount(sashelp.class); %put Number of Variables=%mf_getvarcount(sashelp.class);
%put Character Variables=%mf_getvarcount(sashelp.class,typefilter=C);
%put Numeric Variables = %mf_getvarcount(sashelp.class,typefilter=N);
returns: returns:
> Number of Variables=4 > Number of Variables=4
@param libds Two part dataset (or view) reference.
@param [in] libds Two part dataset (or view) reference.
@param [in] typefilter= (A) Filter for certain types of column. Valid values:
@li A Count All columns
@li C Count Character columns only
@li N Count Numeric columns only
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
**/ **/
%macro mf_getvarcount(libds %macro mf_getvarcount(libds,typefilter=A
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local dsid nvars rc ; %local dsid nvars rc outcnt x;
%let dsid=%sysfunc(open(&libds)); %let dsid=%sysfunc(open(&libds));
%let nvars=.; %let nvars=.;
%let outcnt=0;
%let typefilter=%upcase(&typefilter);
%if &dsid %then %do; %if &dsid %then %do;
%let nvars=%sysfunc(attrn(&dsid,NVARS)); %let nvars=%sysfunc(attrn(&dsid,NVARS));
%if &typefilter=A %then %let outcnt=&nvars;
%else %if &nvars>0 %then %do x=1 %to &nvars;
/* increment based on variable type */
%if %sysfunc(vartype(&dsid,&x))=&typefilter %then %do;
%let outcnt=%eval(&outcnt+1);
%end;
%end;
%let rc=%sysfunc(close(&dsid)); %let rc=%sysfunc(close(&dsid));
%end; %end;
%else %do; %else %do;
%put unable to open &libds (rc=&dsid); %put unable to open &libds (rc=&dsid);
%let rc=%sysfunc(close(&dsid)); %let rc=%sysfunc(close(&dsid));
%end; %end;
&nvars &outcnt
%mend mf_getvarcount;/** %mend mf_getvarcount;/**
@file @file
@brief Returns the format of a variable @brief Returns the format of a variable
@@ -2203,7 +2220,12 @@ Usage:
or "&SYSPROCESSNAME "="Compute Server " or "&SYSPROCESSNAME "="Compute Server "
or &mode=INCLUDE or &mode=INCLUDE
%then %do; %then %do;
options obs=max replace nosyntaxcheck mprint; options obs=max replace mprint;
%if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5"
%then %do;
options nosyntaxcheck;
%end;
%if &mode=INCLUDE %then %do; %if &mode=INCLUDE %then %do;
%if %sysfunc(exist(&errds))=1 %then %do; %if %sysfunc(exist(&errds))=1 %then %do;
data _null_; data _null_;
@@ -7458,6 +7480,7 @@ create table &outsummary as
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_length.sas @li mcf_length.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvarcount.sas
@li mf_getvarlist.sas @li mf_getvarlist.sas
@li mf_getvartype.sas @li mf_getvartype.sas
@li mf_getvarformat.sas @li mf_getvarformat.sas
@@ -7477,7 +7500,7 @@ create table &outsummary as
,outds=work.mp_getmaxvarlengths ,outds=work.mp_getmaxvarlengths
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local vars prefix x var fmt; %local vars prefix x var fmt srcds;
%let vars=%mf_getvarlist(libds=&libds); %let vars=%mf_getvarlist(libds=&libds);
%let prefix=%substr(%mf_getuniquename(),1,25); %let prefix=%substr(%mf_getuniquename(),1,25);
%let num2char=%upcase(&num2char); %let num2char=%upcase(&num2char);
@@ -7487,6 +7510,24 @@ create table &outsummary as
%mcf_length(wrap=YES, insert_cmplib=YES) %mcf_length(wrap=YES, insert_cmplib=YES)
%end; %end;
%if &num2char=NO
and ("%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5")
and %mf_getvarcount(&libds,typefilter=N) gt 0
%then %do;
/* custom functions not supported in summary operations */
%let srcds=%mf_getuniquename();
data &srcds/view=&srcds;
set &libds;
%do x=1 %to %sysfunc(countw(&vars,%str( )));
%let var=%scan(&vars,&x);
%if %mf_getvartype(&libds,&var)=N %then %do;
&prefix.&x=mcf_length(&var);
%end;
%end;
run;
%end;
%else %let srcds=&libds;
proc sql; proc sql;
create table &outds (rename=( create table &outds (rename=(
%do x=1 %to %sysfunc(countw(&vars,%str( ))); %do x=1 %to %sysfunc(countw(&vars,%str( )));
@@ -7511,10 +7552,15 @@ create table &outds (rename=(
%end; %end;
%end; %end;
%else %do; %else %do;
max(mcf_length(&var)) as &prefix.&x %if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then %do;
max(&prefix.&x) as &prefix.&x
%end;
%else %do;
max(mcf_length(&var)) as &prefix.&x
%end;
%end; %end;
%end; %end;
from &libds; from &srcds;
proc transpose data=&outds proc transpose data=&outds
out=&outds(rename=(_name_=NAME COL1=MAXLEN)); out=&outds(rename=(_name_=NAME COL1=MAXLEN));
@@ -11546,7 +11592,7 @@ select distinct tgtvar_nm into: missvars separated by ' '
data &ds1; data &ds1;
set &dslist indsname=&inds_auto; set &dslist indsname=&inds_auto;
&hashkey=put(md5(catx('|',%mf_getquotedstr(&key,quote=N))),$hex32.); &hashkey=put(md5(catx('|',%mf_getquotedstr(&key,quote=N))),$hex32.);
&inds_keep=&inds_auto; &inds_keep=upcase(&inds_auto);
proc sort; proc sort;
by &inds_keep &hashkey; by &inds_keep &hashkey;
run; run;
@@ -11581,8 +11627,8 @@ data &ds4;
tgtvar_nm=upcase(tgtvar_nm); tgtvar_nm=upcase(tgtvar_nm);
if tgtvar_nm in (%upcase(&vlist)); if tgtvar_nm in (%upcase(&vlist));
if &inds_auto="&ds2" then tgtvar_type='N'; if upcase(&inds_auto)="&ds2" then tgtvar_type='N';
else if &inds_auto="&ds3" then tgtvar_type='C'; else if upcase(&inds_auto)="&ds3" then tgtvar_type='C';
else do; else do;
putlog "%str(ERR)OR: unidentified vartype input!" &inds_auto; putlog "%str(ERR)OR: unidentified vartype input!" &inds_auto;
call symputx('syscc',98); call symputx('syscc',98);

View File

@@ -3,12 +3,12 @@
@brief Returns an unused libref @brief Returns an unused libref
@details Use as follows: @details Use as follows:
libname mclib0 (work); libname mclib0 (work);
libname mclib1 (work); libname mclib1 (work);
libname mclib2 (work); libname mclib2 (work);
%let libref=%mf_getuniquelibref(); %let libref=%mf_getuniquelibref();
%put &=libref; %put &=libref;
which returns: which returns:

View File

@@ -2,31 +2,48 @@
@file @file
@brief Returns number of variables in a dataset @brief Returns number of variables in a dataset
@details Useful to identify those renagade datasets that have no columns! @details Useful to identify those renagade datasets that have no columns!
Can also be used to count for numeric, or character columns
%put Number of Variables=%mf_getvarcount(sashelp.class); %put Number of Variables=%mf_getvarcount(sashelp.class);
%put Character Variables=%mf_getvarcount(sashelp.class,typefilter=C);
%put Numeric Variables = %mf_getvarcount(sashelp.class,typefilter=N);
returns: returns:
> Number of Variables=4 > Number of Variables=4
@param libds Two part dataset (or view) reference.
@param [in] libds Two part dataset (or view) reference.
@param [in] typefilter= (A) Filter for certain types of column. Valid values:
@li A Count All columns
@li C Count Character columns only
@li N Count Numeric columns only
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
**/ **/
%macro mf_getvarcount(libds %macro mf_getvarcount(libds,typefilter=A
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local dsid nvars rc ; %local dsid nvars rc outcnt x;
%let dsid=%sysfunc(open(&libds)); %let dsid=%sysfunc(open(&libds));
%let nvars=.; %let nvars=.;
%let outcnt=0;
%let typefilter=%upcase(&typefilter);
%if &dsid %then %do; %if &dsid %then %do;
%let nvars=%sysfunc(attrn(&dsid,NVARS)); %let nvars=%sysfunc(attrn(&dsid,NVARS));
%if &typefilter=A %then %let outcnt=&nvars;
%else %if &nvars>0 %then %do x=1 %to &nvars;
/* increment based on variable type */
%if %sysfunc(vartype(&dsid,&x))=&typefilter %then %do;
%let outcnt=%eval(&outcnt+1);
%end;
%end;
%let rc=%sysfunc(close(&dsid)); %let rc=%sysfunc(close(&dsid));
%end; %end;
%else %do; %else %do;
%put unable to open &libds (rc=&dsid); %put unable to open &libds (rc=&dsid);
%let rc=%sysfunc(close(&dsid)); %let rc=%sysfunc(close(&dsid));
%end; %end;
&nvars &outcnt
%mend mf_getvarcount; %mend mf_getvarcount;

View File

@@ -89,7 +89,12 @@
or "&SYSPROCESSNAME "="Compute Server " or "&SYSPROCESSNAME "="Compute Server "
or &mode=INCLUDE or &mode=INCLUDE
%then %do; %then %do;
options obs=max replace nosyntaxcheck mprint; options obs=max replace mprint;
%if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5"
%then %do;
options nosyntaxcheck;
%end;
%if &mode=INCLUDE %then %do; %if &mode=INCLUDE %then %do;
%if %sysfunc(exist(&errds))=1 %then %do; %if %sysfunc(exist(&errds))=1 %then %do;
data _null_; data _null_;

View File

@@ -41,6 +41,7 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mcf_length.sas @li mcf_length.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvarcount.sas
@li mf_getvarlist.sas @li mf_getvarlist.sas
@li mf_getvartype.sas @li mf_getvartype.sas
@li mf_getvarformat.sas @li mf_getvarformat.sas
@@ -60,7 +61,7 @@
,outds=work.mp_getmaxvarlengths ,outds=work.mp_getmaxvarlengths
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local vars prefix x var fmt; %local vars prefix x var fmt srcds;
%let vars=%mf_getvarlist(libds=&libds); %let vars=%mf_getvarlist(libds=&libds);
%let prefix=%substr(%mf_getuniquename(),1,25); %let prefix=%substr(%mf_getuniquename(),1,25);
%let num2char=%upcase(&num2char); %let num2char=%upcase(&num2char);
@@ -70,6 +71,24 @@
%mcf_length(wrap=YES, insert_cmplib=YES) %mcf_length(wrap=YES, insert_cmplib=YES)
%end; %end;
%if &num2char=NO
and ("%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5")
and %mf_getvarcount(&libds,typefilter=N) gt 0
%then %do;
/* custom functions not supported in summary operations */
%let srcds=%mf_getuniquename();
data &srcds/view=&srcds;
set &libds;
%do x=1 %to %sysfunc(countw(&vars,%str( )));
%let var=%scan(&vars,&x);
%if %mf_getvartype(&libds,&var)=N %then %do;
&prefix.&x=mcf_length(&var);
%end;
%end;
run;
%end;
%else %let srcds=&libds;
proc sql; proc sql;
create table &outds (rename=( create table &outds (rename=(
%do x=1 %to %sysfunc(countw(&vars,%str( ))); %do x=1 %to %sysfunc(countw(&vars,%str( )));
@@ -94,10 +113,15 @@ create table &outds (rename=(
%end; %end;
%end; %end;
%else %do; %else %do;
max(mcf_length(&var)) as &prefix.&x %if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then %do;
max(&prefix.&x) as &prefix.&x
%end;
%else %do;
max(mcf_length(&var)) as &prefix.&x
%end;
%end; %end;
%end; %end;
from &libds; from &srcds;
proc transpose data=&outds proc transpose data=&outds
out=&outds(rename=(_name_=NAME COL1=MAXLEN)); out=&outds(rename=(_name_=NAME COL1=MAXLEN));

View File

@@ -125,7 +125,7 @@
data &ds1; data &ds1;
set &dslist indsname=&inds_auto; set &dslist indsname=&inds_auto;
&hashkey=put(md5(catx('|',%mf_getquotedstr(&key,quote=N))),$hex32.); &hashkey=put(md5(catx('|',%mf_getquotedstr(&key,quote=N))),$hex32.);
&inds_keep=&inds_auto; &inds_keep=upcase(&inds_auto);
proc sort; proc sort;
by &inds_keep &hashkey; by &inds_keep &hashkey;
run; run;
@@ -160,8 +160,8 @@ data &ds4;
tgtvar_nm=upcase(tgtvar_nm); tgtvar_nm=upcase(tgtvar_nm);
if tgtvar_nm in (%upcase(&vlist)); if tgtvar_nm in (%upcase(&vlist));
if &inds_auto="&ds2" then tgtvar_type='N'; if upcase(&inds_auto)="&ds2" then tgtvar_type='N';
else if &inds_auto="&ds3" then tgtvar_type='C'; else if upcase(&inds_auto)="&ds3" then tgtvar_type='C';
else do; else do;
putlog "%str(ERR)OR: unidentified vartype input!" &inds_auto; putlog "%str(ERR)OR: unidentified vartype input!" &inds_auto;
call symputx('syscc',98); call symputx('syscc',98);

View File

@@ -0,0 +1,46 @@
/**
@file
@brief Testing mf_getvarlist macro
<h4> SAS Macros </h4>
@li mf_getvarcount.sas
@li mp_assertscope.sas
**/
data work.all work.nums(keep=num1 num2) work.chars(keep=char1 char2);
length num1 num2 8 char1 char2 char3 $4;
call missing (of _all_);
output;
run;
%mp_assertscope(SNAPSHOT)
%put scope check:%mf_getvarcount(work.all);
%mp_assertscope(COMPARE)
%mp_assert(
iftrue=(%mf_getvarcount(work.all)=5),
desc=%str(Checking for mixed vars),
outds=work.test_results
)
%mp_assert(
iftrue=(%mf_getvarcount(work.all,typefilter=C)=3),
desc=%str(Checking for char in mixed vars),
outds=work.test_results
)
%mp_assert(
iftrue=(%mf_getvarcount(work.all,typefilter=N)=2),
desc=%str(Checking for num in mixed vars),
outds=work.test_results
)
%mp_assert(
iftrue=(%mf_getvarcount(work.nums,typefilter=c)=0),
desc=%str(Checking for char in num vars),
outds=work.test_results
)
%mp_assert(
iftrue=(%mf_getvarcount(work.chars,typefilter=N)=0),
desc=%str(Checking for num in char vars),
outds=work.test_results
)

View File

@@ -10,10 +10,48 @@
**/ **/
data work.class ;
attrib
Name length= $8
Sex length= $1
Age length= 8
Height length= 8
Weight length= 8
;
infile cards dsd;
input
Name :$char.
Sex :$char.
Age
Height
Weight
;
datalines4;
Alfred,M,14,69,112.5
Alice,F,13,56.5,84
Barbara,F,13,65.3,98
Carol,F,14,62.8,102.5
Henry,M,14,63.5,102.5
James,M,12,57.3,83
Jane,F,12,59.8,84.5
Janet,F,15,62.5,112.5
Jeffrey,M,13,62.5,84
John,M,12,59,99.5
Joyce,F,11,51.3,50.5
Judy,F,14,64.3,90
Louise,F,12,56.3,77
Mary,F,15,66.5,112
Philip,M,16,72,150
Robert,M,12,64.8,128
Ronald,M,15,67,133
Thomas,M,11,57.5,85
William,M,15,66.5,112
;;;;
run;
/* regular usage */ /* regular usage */
%mp_assertscope(SNAPSHOT) %mp_assertscope(SNAPSHOT)
%mp_getmaxvarlengths(sashelp.class,outds=work.myds) %mp_getmaxvarlengths(work.class,outds=work.myds)
%mp_assertscope(COMPARE,desc=checking scope leakage on mp_getmaxvarlengths) %mp_assertscope(COMPARE,desc=checking scope leakage on mp_getmaxvarlengths)
%mp_assert( %mp_assert(
iftrue=(&syscc=0), iftrue=(&syscc=0),