mirror of
https://github.com/sasjs/core.git
synced 2025-12-27 21:10:05 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a13c782074 | ||
|
|
f2991cfd63 | ||
|
|
8eb4f0844c | ||
|
|
f90dc069dc | ||
|
|
436b430389 | ||
|
|
6667b91ced | ||
|
|
bce56d8105 |
148
all.sas
148
all.sas
@@ -1532,6 +1532,45 @@ Usage:
|
||||
%else %do;1%end;
|
||||
|
||||
%mend mf_isint;/**
|
||||
@file
|
||||
@brief Checks whether a string follows correct library.dataset format
|
||||
@details Many macros in the core library accept a library.dataset parameter
|
||||
referred to as 'libds'. This macro validates the structure of that parameter,
|
||||
eg:
|
||||
|
||||
@li 8 character libref?
|
||||
@li 32 character dataset?
|
||||
@li contains a period?
|
||||
|
||||
It does NOT check whether the dataset exists, or if the library is assigned.
|
||||
|
||||
Usage:
|
||||
|
||||
%put %mf_islibds(work.something)=1;
|
||||
%put %mf_islibds(nolib)=0;
|
||||
%put %mf_islibds(badlibref.ds)=0;
|
||||
%put %mf_islibds(w.t.f)=0;
|
||||
|
||||
@param [in] libds The string to be checked
|
||||
|
||||
@return output Returns 1 if libds is valid, 0 if it is not
|
||||
|
||||
<h4> Related Macros </h4>
|
||||
@li mf_islibds.test.sas
|
||||
@li mp_validatecol.sas
|
||||
|
||||
@version 9.2
|
||||
**/
|
||||
|
||||
%macro mf_islibds(libds
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%local regex;
|
||||
%let regex=%sysfunc(prxparse(%str(/^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i)));
|
||||
|
||||
%sysfunc(prxmatch(®ex,&libds))
|
||||
|
||||
%mend mf_islibds;/**
|
||||
@file
|
||||
@brief Returns physical location of various SAS items
|
||||
@details Returns location of the PlatformObjectFramework tools
|
||||
@@ -1805,6 +1844,60 @@ Usage:
|
||||
%exit_success:
|
||||
|
||||
%mend mf_verifymacvars;
|
||||
/**
|
||||
@file
|
||||
@brief Returns words that are in both string 1 and string 2
|
||||
@details Compares two space separated strings and returns the words that are
|
||||
in both.
|
||||
Usage:
|
||||
|
||||
%put %mf_wordsInStr1andStr2(
|
||||
Str1=blah sss blaaah brah bram boo
|
||||
,Str2= blah blaaah brah ssss
|
||||
);
|
||||
|
||||
returns:
|
||||
> blah blaaah brah
|
||||
|
||||
@param str1= string containing words to extract
|
||||
@param str2= used to compare with the extract string
|
||||
|
||||
@warning CASE SENSITIVE!
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
|
||||
**/
|
||||
|
||||
%macro mf_wordsInStr1andStr2(
|
||||
Str1= /* string containing words to extract */
|
||||
,Str2= /* used to compare with the extract string */
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%local count_base count_extr i i2 extr_word base_word match outvar;
|
||||
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
|
||||
%put %str(WARN)ING: empty string provided!;
|
||||
%put base string (str1)= &str1;
|
||||
%put compare string (str2) = &str2;
|
||||
%return;
|
||||
%end;
|
||||
%let count_base=%sysfunc(countw(&Str2));
|
||||
%let count_extr=%sysfunc(countw(&Str1));
|
||||
|
||||
%do i=1 %to &count_extr;
|
||||
%let extr_word=%scan(&Str1,&i,%str( ));
|
||||
%let match=0;
|
||||
%do i2=1 %to &count_base;
|
||||
%let base_word=%scan(&Str2,&i2,%str( ));
|
||||
%if &extr_word=&base_word %then %let match=1;
|
||||
%end;
|
||||
%if &match=1 %then %let outvar=&outvar &extr_word;
|
||||
%end;
|
||||
|
||||
&outvar
|
||||
|
||||
%mend mf_wordsInStr1andStr2;
|
||||
|
||||
/**
|
||||
@file
|
||||
@brief Returns words that are in string 1 but not in string 2
|
||||
@@ -7586,8 +7679,6 @@ lock &libds clear;
|
||||
according to the variable types and formats.
|
||||
|
||||
TODO:
|
||||
@li Respect PKs
|
||||
@li Respect NOT NULLs
|
||||
@li Consider dates, datetimes, times, integers etc
|
||||
|
||||
Usage:
|
||||
@@ -7603,16 +7694,23 @@ lock &libds clear;
|
||||
);
|
||||
%mp_makedata(work.example)
|
||||
|
||||
@param [in] libds The empty table in which to create data
|
||||
@param [out] obs= (500) The number of records to create.
|
||||
@param [in] libds The empty table (libref.dataset) in which to create data
|
||||
@param [out] obs= (500) The maximum number of records to create. The table
|
||||
is sorted with nodup on the primary key, so the actual number of records may
|
||||
be lower than this.
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_getuniquename.sas
|
||||
@li mf_getvarlen.sas
|
||||
@li mf_getvarlist.sas
|
||||
@li mf_islibds.sas
|
||||
@li mf_nobs.sas
|
||||
@li mp_getcols.sas
|
||||
@li mp_getpk.sas
|
||||
|
||||
<h4> Related Macros </h4>
|
||||
@li mp_makedata.test.sas
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
|
||||
@@ -7620,45 +7718,59 @@ lock &libds clear;
|
||||
|
||||
%macro mp_makedata(libds
|
||||
,obs=500
|
||||
,seed=1
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%local ds1 c1 n1 i col charvars numvars;
|
||||
%local ds1 ds2 lib ds pk_fields i col charvars numvars ispk;
|
||||
|
||||
%if %mf_nobs(&libds)>0 %then %do;
|
||||
%if %mf_islibds(&libds)=0 %then %do;
|
||||
%put &sysmacroname: Invalid libds (&libds) - should be library.dataset format;
|
||||
%return;
|
||||
%end;
|
||||
%else %if %mf_nobs(&libds)>0 %then %do;
|
||||
%put &sysmacroname: &libds has data, it will not be recreated;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%local ds1 c1 n1;
|
||||
%let ds1=%mf_getuniquename(prefix=mp_makedata);
|
||||
%let c1=%mf_getuniquename(prefix=mp_makedatacol);
|
||||
%let n1=%mf_getuniquename(prefix=mp_makedatacol);
|
||||
data &ds1;
|
||||
/* set up temporary vars */
|
||||
%let ds1=%mf_getuniquename(prefix=mp_makedatads1);
|
||||
%let ds2=%mf_getuniquename(prefix=mp_makedatads2);
|
||||
%let lib=%scan(&libds,1,.);
|
||||
%let ds=%scan(&libds,2,.);
|
||||
|
||||
/* grab the primary key vars */
|
||||
%mp_getpk(&lib,ds=&ds,outds=&ds1)
|
||||
|
||||
proc sql noprint;
|
||||
select coalescec(pk_fields,'_all_') into: pk_fields from &ds1;
|
||||
|
||||
data &ds2;
|
||||
if 0 then set &libds;
|
||||
do _n_=1 to &obs;
|
||||
&c1=repeat(uuidgen(),10);
|
||||
&n1=ranuni(1)*5000000;
|
||||
drop &c1 &n1;
|
||||
%let charvars=%mf_getvarlist(&libds,typefilter=C);
|
||||
%if &charvars ^= %then %do i=1 %to %sysfunc(countw(&charvars));
|
||||
%let col=%scan(&charvars,&i);
|
||||
&col=subpad(&c1,1,%mf_getvarlen(&libds,&col));
|
||||
/* create random value based on observation number and colum length */
|
||||
&col=repeat(put(md5(cats(_n_)),$hex32.),%mf_getvarlen(&libds,&col)/32);
|
||||
%end;
|
||||
|
||||
%let numvars=%mf_getvarlist(&libds,typefilter=N);
|
||||
%if &numvars ^= %then %do i=1 %to %sysfunc(countw(&numvars));
|
||||
%let col=%scan(&numvars,&i);
|
||||
&col=&n1;
|
||||
&col=_n_;
|
||||
%end;
|
||||
output;
|
||||
end;
|
||||
run;
|
||||
proc sort data=&ds2 nodupkey;
|
||||
by &pk_fields;
|
||||
run;
|
||||
|
||||
proc append base=&libds data=&ds1;
|
||||
proc append base=&libds data=&ds2;
|
||||
run;
|
||||
|
||||
proc sql;
|
||||
drop table &ds1;
|
||||
drop table &ds1, &ds2;
|
||||
|
||||
%mend mp_makedata;/**
|
||||
@file
|
||||
|
||||
40
base/mf_islibds.sas
Normal file
40
base/mf_islibds.sas
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
@file
|
||||
@brief Checks whether a string follows correct library.dataset format
|
||||
@details Many macros in the core library accept a library.dataset parameter
|
||||
referred to as 'libds'. This macro validates the structure of that parameter,
|
||||
eg:
|
||||
|
||||
@li 8 character libref?
|
||||
@li 32 character dataset?
|
||||
@li contains a period?
|
||||
|
||||
It does NOT check whether the dataset exists, or if the library is assigned.
|
||||
|
||||
Usage:
|
||||
|
||||
%put %mf_islibds(work.something)=1;
|
||||
%put %mf_islibds(nolib)=0;
|
||||
%put %mf_islibds(badlibref.ds)=0;
|
||||
%put %mf_islibds(w.t.f)=0;
|
||||
|
||||
@param [in] libds The string to be checked
|
||||
|
||||
@return output Returns 1 if libds is valid, 0 if it is not
|
||||
|
||||
<h4> Related Macros </h4>
|
||||
@li mf_islibds.test.sas
|
||||
@li mp_validatecol.sas
|
||||
|
||||
@version 9.2
|
||||
**/
|
||||
|
||||
%macro mf_islibds(libds
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%local regex;
|
||||
%let regex=%sysfunc(prxparse(%str(/^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i)));
|
||||
|
||||
%sysfunc(prxmatch(®ex,&libds))
|
||||
|
||||
%mend mf_islibds;
|
||||
54
base/mf_wordsinstr1andstr2.sas
Normal file
54
base/mf_wordsinstr1andstr2.sas
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
@file
|
||||
@brief Returns words that are in both string 1 and string 2
|
||||
@details Compares two space separated strings and returns the words that are
|
||||
in both.
|
||||
Usage:
|
||||
|
||||
%put %mf_wordsInStr1andStr2(
|
||||
Str1=blah sss blaaah brah bram boo
|
||||
,Str2= blah blaaah brah ssss
|
||||
);
|
||||
|
||||
returns:
|
||||
> blah blaaah brah
|
||||
|
||||
@param str1= string containing words to extract
|
||||
@param str2= used to compare with the extract string
|
||||
|
||||
@warning CASE SENSITIVE!
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
|
||||
**/
|
||||
|
||||
%macro mf_wordsInStr1andStr2(
|
||||
Str1= /* string containing words to extract */
|
||||
,Str2= /* used to compare with the extract string */
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%local count_base count_extr i i2 extr_word base_word match outvar;
|
||||
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
|
||||
%put %str(WARN)ING: empty string provided!;
|
||||
%put base string (str1)= &str1;
|
||||
%put compare string (str2) = &str2;
|
||||
%return;
|
||||
%end;
|
||||
%let count_base=%sysfunc(countw(&Str2));
|
||||
%let count_extr=%sysfunc(countw(&Str1));
|
||||
|
||||
%do i=1 %to &count_extr;
|
||||
%let extr_word=%scan(&Str1,&i,%str( ));
|
||||
%let match=0;
|
||||
%do i2=1 %to &count_base;
|
||||
%let base_word=%scan(&Str2,&i2,%str( ));
|
||||
%if &extr_word=&base_word %then %let match=1;
|
||||
%end;
|
||||
%if &match=1 %then %let outvar=&outvar &extr_word;
|
||||
%end;
|
||||
|
||||
&outvar
|
||||
|
||||
%mend mf_wordsInStr1andStr2;
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
according to the variable types and formats.
|
||||
|
||||
TODO:
|
||||
@li Respect PKs
|
||||
@li Respect NOT NULLs
|
||||
@li Consider dates, datetimes, times, integers etc
|
||||
|
||||
Usage:
|
||||
@@ -27,16 +25,23 @@
|
||||
);
|
||||
%mp_makedata(work.example)
|
||||
|
||||
@param [in] libds The empty table in which to create data
|
||||
@param [out] obs= (500) The number of records to create.
|
||||
@param [in] libds The empty table (libref.dataset) in which to create data
|
||||
@param [out] obs= (500) The maximum number of records to create. The table
|
||||
is sorted with nodup on the primary key, so the actual number of records may
|
||||
be lower than this.
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_getuniquename.sas
|
||||
@li mf_getvarlen.sas
|
||||
@li mf_getvarlist.sas
|
||||
@li mf_islibds.sas
|
||||
@li mf_nobs.sas
|
||||
@li mp_getcols.sas
|
||||
@li mp_getpk.sas
|
||||
|
||||
<h4> Related Macros </h4>
|
||||
@li mp_makedata.test.sas
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
|
||||
@@ -44,44 +49,58 @@
|
||||
|
||||
%macro mp_makedata(libds
|
||||
,obs=500
|
||||
,seed=1
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%local ds1 c1 n1 i col charvars numvars;
|
||||
%local ds1 ds2 lib ds pk_fields i col charvars numvars ispk;
|
||||
|
||||
%if %mf_nobs(&libds)>0 %then %do;
|
||||
%if %mf_islibds(&libds)=0 %then %do;
|
||||
%put &sysmacroname: Invalid libds (&libds) - should be library.dataset format;
|
||||
%return;
|
||||
%end;
|
||||
%else %if %mf_nobs(&libds)>0 %then %do;
|
||||
%put &sysmacroname: &libds has data, it will not be recreated;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
%local ds1 c1 n1;
|
||||
%let ds1=%mf_getuniquename(prefix=mp_makedata);
|
||||
%let c1=%mf_getuniquename(prefix=mp_makedatacol);
|
||||
%let n1=%mf_getuniquename(prefix=mp_makedatacol);
|
||||
data &ds1;
|
||||
/* set up temporary vars */
|
||||
%let ds1=%mf_getuniquename(prefix=mp_makedatads1);
|
||||
%let ds2=%mf_getuniquename(prefix=mp_makedatads2);
|
||||
%let lib=%scan(&libds,1,.);
|
||||
%let ds=%scan(&libds,2,.);
|
||||
|
||||
/* grab the primary key vars */
|
||||
%mp_getpk(&lib,ds=&ds,outds=&ds1)
|
||||
|
||||
proc sql noprint;
|
||||
select coalescec(pk_fields,'_all_') into: pk_fields from &ds1;
|
||||
|
||||
data &ds2;
|
||||
if 0 then set &libds;
|
||||
do _n_=1 to &obs;
|
||||
&c1=repeat(uuidgen(),10);
|
||||
&n1=ranuni(1)*5000000;
|
||||
drop &c1 &n1;
|
||||
%let charvars=%mf_getvarlist(&libds,typefilter=C);
|
||||
%if &charvars ^= %then %do i=1 %to %sysfunc(countw(&charvars));
|
||||
%let col=%scan(&charvars,&i);
|
||||
&col=subpad(&c1,1,%mf_getvarlen(&libds,&col));
|
||||
/* create random value based on observation number and colum length */
|
||||
&col=repeat(put(md5(cats(_n_)),$hex32.),%mf_getvarlen(&libds,&col)/32);
|
||||
%end;
|
||||
|
||||
%let numvars=%mf_getvarlist(&libds,typefilter=N);
|
||||
%if &numvars ^= %then %do i=1 %to %sysfunc(countw(&numvars));
|
||||
%let col=%scan(&numvars,&i);
|
||||
&col=&n1;
|
||||
&col=_n_;
|
||||
%end;
|
||||
output;
|
||||
end;
|
||||
run;
|
||||
proc sort data=&ds2 nodupkey;
|
||||
by &pk_fields;
|
||||
run;
|
||||
|
||||
proc append base=&libds data=&ds1;
|
||||
proc append base=&libds data=&ds2;
|
||||
run;
|
||||
|
||||
proc sql;
|
||||
drop table &ds1;
|
||||
drop table &ds1, &ds2;
|
||||
|
||||
%mend mp_makedata;
|
||||
46
tests/crossplatform/mf_islibds.test.sas
Normal file
46
tests/crossplatform/mf_islibds.test.sas
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
@file
|
||||
@brief Testing mf_islibds macro
|
||||
|
||||
%put %mf_islibds(work.something)=1;
|
||||
%put %mf_islibds(nolib)=0;
|
||||
%put %mf_islibds(badlibref.ds)=0;
|
||||
%put %mf_islibds(w.t.f)=0;
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_islibds.sas
|
||||
@li mp_assert.sas
|
||||
|
||||
**/
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(
|
||||
%mf_islibds(work.something)=1
|
||||
),
|
||||
desc=%str(Checking mf_islibds(work.something)=1),
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(
|
||||
%mf_islibds(nolib)=0
|
||||
),
|
||||
desc=%str(Checking mf_islibds(nolib)=0),
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(
|
||||
%mf_islibds(badlibref.ds)=0
|
||||
),
|
||||
desc=%str(Checking mf_islibds(badlibref.ds)=0),
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(
|
||||
%mf_islibds(w.t.f)=0
|
||||
),
|
||||
desc=%str(Checking mf_islibds(w.t.f)=0),
|
||||
outds=work.test_results
|
||||
)
|
||||
20
tests/crossplatform/mf_wordsinstr1andstr2.test.sas
Normal file
20
tests/crossplatform/mf_wordsinstr1andstr2.test.sas
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
@file
|
||||
@brief Testing mf_wordsinstr1andstr2 macro
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_wordsinstr1andstr2.sas
|
||||
@li mp_assert.sas
|
||||
|
||||
**/
|
||||
|
||||
%let x=%mf_wordsinstr1andstr2(str1=xx DOLLAR x $CHAR xxx W MONNAME
|
||||
,str2=DOLLAR $CHAR W MONNAME xxxxxx
|
||||
);
|
||||
%mp_assert(
|
||||
iftrue=(
|
||||
"&x"="DOLLAR $CHAR W MONNAME"
|
||||
),
|
||||
desc=Checking basic string,
|
||||
outds=work.test_results
|
||||
)
|
||||
20
tests/crossplatform/mf_wordsinstr1butnotstr2.test.sas
Normal file
20
tests/crossplatform/mf_wordsinstr1butnotstr2.test.sas
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
@file
|
||||
@brief Testing mf_wordsinstr1butnotstr2 macro
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_wordsinstr1butnotstr2.sas
|
||||
@li mp_assert.sas
|
||||
|
||||
**/
|
||||
|
||||
%let x=%mf_wordsinstr1butnotstr2(str1=xx DOLLAR x $CHAR xxx W MONNAME
|
||||
,str2=ff xx x xxx xxxxxx
|
||||
);
|
||||
%mp_assert(
|
||||
iftrue=(
|
||||
"&x"="DOLLAR $CHAR W MONNAME"
|
||||
),
|
||||
desc=Checking basic string,
|
||||
outds=work.test_results
|
||||
)
|
||||
59
tests/crossplatform/mp_makedata.test.sas
Normal file
59
tests/crossplatform/mp_makedata.test.sas
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
@file
|
||||
@brief Testing mp_makedata.sas macro
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_nobs.sas
|
||||
@li mp_makedata.sas
|
||||
@li mp_assert.sas
|
||||
|
||||
**/
|
||||
|
||||
/**
|
||||
* Test 1 - Regular makedata call
|
||||
*/
|
||||
|
||||
proc sql;
|
||||
create table work.example(
|
||||
TX_FROM float format=datetime19.,
|
||||
DD_TYPE char(16),
|
||||
DD_SOURCE char(2048),
|
||||
DD_SHORTDESC char(256),
|
||||
constraint pk primary key(tx_from, dd_type,dd_source),
|
||||
constraint nnn not null(DD_SHORTDESC)
|
||||
);
|
||||
%mp_makedata(work.example,obs=500)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=("%mf_nobs(work.example)"="500"),
|
||||
desc=Check that 500 rows were created,
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
data _null_;
|
||||
set work.example;
|
||||
call symputx('lenvar',length(dd_source));
|
||||
stop;
|
||||
run;
|
||||
%mp_assert(
|
||||
iftrue=("&lenvar"="2048"),
|
||||
desc=Check that entire length of variable is populated,
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
|
||||
proc sql;
|
||||
create table work.example2(
|
||||
TX_FROM float format=datetime19.,
|
||||
DD_TYPE char(16),
|
||||
DD_SOURCE char(2048),
|
||||
DD_SHORTDESC char(256),
|
||||
some_num num
|
||||
);
|
||||
%mp_makedata(work.example2)
|
||||
|
||||
%mp_assert(
|
||||
iftrue=(&syscc=0),
|
||||
desc=Ensure tables without keys still generate,
|
||||
outds=work.test_results
|
||||
)
|
||||
Reference in New Issue
Block a user