mirror of
https://github.com/sasjs/core.git
synced 2026-01-05 00:20:05 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a69db2ebfb | ||
|
|
d72ca7cb24 | ||
|
|
52dfa7b8f7 | ||
|
|
dae03c5730 | ||
|
|
14efe5d3fd | ||
|
|
653244d737 | ||
|
|
086831b3f5 | ||
|
|
6eca585fc1 | ||
|
|
f6ba36fc28 | ||
|
|
7406288d79 | ||
|
|
2e7fcbe5b8 | ||
|
|
3e7b9f8c14 |
170
all.sas
170
all.sas
@@ -1806,7 +1806,7 @@ Usage:
|
|||||||
/* send response in SASjs JSON format */
|
/* send response in SASjs JSON format */
|
||||||
data _null_;
|
data _null_;
|
||||||
file _webout mod lrecl=32000 encoding='utf-8';
|
file _webout mod lrecl=32000 encoding='utf-8';
|
||||||
length msg $32767 debug $8;
|
length msg $32767 ;
|
||||||
sasdatetime=datetime();
|
sasdatetime=datetime();
|
||||||
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
|
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
|
||||||
/* escape the quotes */
|
/* escape the quotes */
|
||||||
@@ -1837,13 +1837,16 @@ Usage:
|
|||||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||||
put ",""SYSCC"" : ""&syscc"" ";
|
put ",""SYSCC"" : ""&syscc"" ";
|
||||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
syserrortext=quote(trim(symget('syserrortext')));
|
||||||
|
put ",""SYSERRORTEXT"" : " syserrortext;
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||||
|
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||||
put ",""SYSSITE"" : ""&syssite"" ";
|
put ",""SYSSITE"" : ""&syssite"" ";
|
||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
syswarningtext=quote(trim(symget('syswarningtext')));
|
||||||
|
put ",""SYSWARNINGTEXT"" : " syswarningtext;
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
||||||
put "}" @;
|
put "}" @;
|
||||||
if debug ge '"131"' then put '>>weboutEND<<';
|
if debug ge '"131"' then put '>>weboutEND<<';
|
||||||
@@ -1853,7 +1856,7 @@ Usage:
|
|||||||
|
|
||||||
%if "&sysprocessmode " = "SAS Stored Process Server " %then %do;
|
%if "&sysprocessmode " = "SAS Stored Process Server " %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
putlog 'stpsrvset program error and syscc';
|
putlog 'stpsrvset program err and syscc';
|
||||||
rc=stpsrvset('program error', 0);
|
rc=stpsrvset('program error', 0);
|
||||||
call symputx("syscc",0,"g");
|
call symputx("syscc",0,"g");
|
||||||
run;
|
run;
|
||||||
@@ -1899,6 +1902,62 @@ Usage:
|
|||||||
%mend mp_abort;
|
%mend mp_abort;
|
||||||
|
|
||||||
/** @endcond *//**
|
/** @endcond *//**
|
||||||
|
@file
|
||||||
|
@brief Append (concatenate) two or more files.
|
||||||
|
@details Will append one more more `appendrefs` (filerefs) to a `baseref`.
|
||||||
|
Uses a binary mechanism, so will work with any file type. For that reason -
|
||||||
|
use with care! And supply your own trailing carriage returns in each file..
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
filename tmp1 temp;
|
||||||
|
filename tmp2 temp;
|
||||||
|
filename tmp3 temp;
|
||||||
|
data _null_; file tmp1; put 'base file';
|
||||||
|
data _null_; file tmp2; put 'append1';
|
||||||
|
data _null_; file tmp3; put 'append2';
|
||||||
|
run;
|
||||||
|
%mp_appendfile(baseref=tmp1, appendrefs=tmp2 tmp3)
|
||||||
|
|
||||||
|
|
||||||
|
@param [in] baseref= Fileref of the base file (should exist)
|
||||||
|
@param [in] appendrefs= One or more filerefs to be appended to the base
|
||||||
|
fileref. Space separated.
|
||||||
|
|
||||||
|
@version 9.2
|
||||||
|
@author Allan Bowe, source: https://github.com/sasjs/core
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mp_abort.sas
|
||||||
|
@li mp_binarycopy.sas
|
||||||
|
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_appendfile(
|
||||||
|
baseref=0,
|
||||||
|
appendrefs=0
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%mp_abort(iftrue= (&baseref=0)
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=%str(Baseref NOT specified!)
|
||||||
|
)
|
||||||
|
%mp_abort(iftrue= (&appendrefs=0)
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=%str(Appendrefs NOT specified!)
|
||||||
|
)
|
||||||
|
|
||||||
|
%local i;
|
||||||
|
%do i=1 %to %sysfunc(countw(&appendrefs));
|
||||||
|
%mp_abort(iftrue= (&syscc>0)
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=%str(syscc=&syscc)
|
||||||
|
)
|
||||||
|
%mp_binarycopy(inref=%scan(&appendrefs,&i), outref=&baseref, mode=APPEND)
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend mp_appendfile;/**
|
||||||
@file
|
@file
|
||||||
@brief Generic assertion
|
@brief Generic assertion
|
||||||
@details Useful in the context of writing sasjs tests. The results of the
|
@details Useful in the context of writing sasjs tests. The results of the
|
||||||
@@ -2129,6 +2188,7 @@ Usage:
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_existds.sas
|
@li mf_existds.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
@li mf_nobs.sas
|
@li mf_nobs.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
|
|
||||||
@@ -2214,6 +2274,26 @@ Usage:
|
|||||||
select count(*) into: orig from &lib..&ds;
|
select count(*) into: orig from &lib..&ds;
|
||||||
quit;
|
quit;
|
||||||
|
|
||||||
|
%local notfound tmp1 tmp2;
|
||||||
|
%let tmp1=%mf_getuniquename();
|
||||||
|
%let tmp2=%mf_getuniquename();
|
||||||
|
|
||||||
|
/* this is a bit convoluted - but using sql outobs=10 throws warnings */
|
||||||
|
proc sql noprint;
|
||||||
|
create view &tmp1 as
|
||||||
|
select distinct &col
|
||||||
|
from &lib..&ds
|
||||||
|
where &col not in (
|
||||||
|
select &ccol from &clib..&cds
|
||||||
|
);
|
||||||
|
data &tmp2;
|
||||||
|
set &tmp1;
|
||||||
|
if _n_>10 then stop;
|
||||||
|
run;
|
||||||
|
proc sql;
|
||||||
|
select distinct &col into: notfound separated by ' ' from &tmp2;
|
||||||
|
|
||||||
|
|
||||||
%mp_abort(iftrue= (&syscc ne 0)
|
%mp_abort(iftrue= (&syscc ne 0)
|
||||||
,mac=&sysmacroname
|
,mac=&sysmacroname
|
||||||
,msg=%str(syscc=&syscc after macro query)
|
,msg=%str(syscc=&syscc after macro query)
|
||||||
@@ -2224,7 +2304,7 @@ Usage:
|
|||||||
test_description=symget('desc');
|
test_description=symget('desc');
|
||||||
test_result='FAIL';
|
test_result='FAIL';
|
||||||
test_comments="&sysmacroname: &lib..&ds..&col has &result values "
|
test_comments="&sysmacroname: &lib..&ds..&col has &result values "
|
||||||
!!"not in &clib..&cds..&ccol ";
|
!!"not in &clib..&cds..&ccol.. First 10 vals:"!!symget('notfound');
|
||||||
%if &test=ANYVAL %then %do;
|
%if &test=ANYVAL %then %do;
|
||||||
if &result < &orig then test_result='PASS';
|
if &result < &orig then test_result='PASS';
|
||||||
%end;
|
%end;
|
||||||
@@ -4228,6 +4308,70 @@ filename &fref1 clear;
|
|||||||
|
|
||||||
%mend mp_filtervalidate;
|
%mend mp_filtervalidate;
|
||||||
/**
|
/**
|
||||||
|
@file
|
||||||
|
@brief Creates a dataset with column metadata.
|
||||||
|
@details This macro takes the `proc contents` output and "tidies it up" in the
|
||||||
|
following ways:
|
||||||
|
|
||||||
|
@li Blank labels are filled in with column names
|
||||||
|
@li Formats are reconstructed with default values
|
||||||
|
@li Types such as DATE / TIME / DATETIME are inferred from the formats
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
%mp_getcols(sashelp.airline,outds=work.myds)
|
||||||
|
|
||||||
|
@param ds The dataset from which to obtain column metadata
|
||||||
|
@param outds= (work.cols) The output dataset to create. Sample data:
|
||||||
|
|NAME $|LENGTH 8|VARNUM 8|LABEL $|FORMAT $49|TYPE $1 |DDTYPE $|
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
|AIR|8|2|international airline travel (thousands)|8.|N|NUMERIC|
|
||||||
|
|DATE|8|1|DATE|MONYY.|N|DATE|
|
||||||
|
|REGION|3|3|REGION|$3.|C|CHARACTER|
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mf_getvarlist.sas
|
||||||
|
@li mm_getcols.sas
|
||||||
|
|
||||||
|
@version 9.2
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_getcols(ds, outds=work.cols);
|
||||||
|
|
||||||
|
proc contents noprint data=&ds
|
||||||
|
out=_data_ (keep=name type length label varnum format:);
|
||||||
|
run;
|
||||||
|
data &outds(keep=name type length varnum format label ddtype);
|
||||||
|
set &syslast(rename=(format=format2 type=type2));
|
||||||
|
name=upcase(name);
|
||||||
|
if type2=2 then do;
|
||||||
|
length format $49.;
|
||||||
|
if format2='' then format=cats('$',length,'.');
|
||||||
|
else if formatl=0 then format=cats(format2,'.');
|
||||||
|
else format=cats(format2,formatl,'.');
|
||||||
|
type='C';
|
||||||
|
ddtype='CHARACTER';
|
||||||
|
end;
|
||||||
|
else do;
|
||||||
|
if format2='' then format=cats(length,'.');
|
||||||
|
else if formatl=0 then format=cats(format2,'.');
|
||||||
|
else if formatd=0 then format=cats(format2,formatl,'.');
|
||||||
|
else format=cats(format2,formatl,'.',formatd);
|
||||||
|
type='N';
|
||||||
|
if format=:'DATETIME' then ddtype='DATETIME';
|
||||||
|
else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY'
|
||||||
|
or format=:'YYMMDD' or format=:'E8601DA' or format=:'B8601DA'
|
||||||
|
or format=:'MONYY'
|
||||||
|
then ddtype='DATE';
|
||||||
|
else if format=:'TIME' then ddtype='TIME';
|
||||||
|
else ddtype='NUMERIC';
|
||||||
|
end;
|
||||||
|
if label='' then label=name;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mend mp_getcols;/**
|
||||||
@file mp_getconstraints.sas
|
@file mp_getconstraints.sas
|
||||||
@brief Get constraint details at column level
|
@brief Get constraint details at column level
|
||||||
@details Useful for capturing constraints before they are dropped / reapplied
|
@details Useful for capturing constraints before they are dropped / reapplied
|
||||||
@@ -5108,7 +5252,7 @@ create table &outds (rename=(
|
|||||||
file "&file";
|
file "&file";
|
||||||
put "&str";
|
put "&str";
|
||||||
run;
|
run;
|
||||||
%mp_gsubfile(file=&file, pattern=str, replacement=rep)
|
%mp_gsubfile(file=&file, patternvar=str, replacevar=rep)
|
||||||
data _null_;
|
data _null_;
|
||||||
infile "&file";
|
infile "&file";
|
||||||
input;
|
input;
|
||||||
@@ -6028,14 +6172,14 @@ select distinct lowcase(memname)
|
|||||||
We take the standard definition one step further by embedding the informat
|
We take the standard definition one step further by embedding the informat
|
||||||
in the table header row, like so:
|
in the table header row, like so:
|
||||||
|
|
||||||
|var1:$|var2:best.|var3:date9.|
|
|var1:$32|var2:best.|var3:date9.|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|some text|42|01JAN1960|
|
|some text|42|01JAN1960|
|
||||||
|blah|1|31DEC1999|
|
|blah|1|31DEC1999|
|
||||||
|
|
||||||
Which resolves to:
|
Which resolves to:
|
||||||
|
|
||||||
|var1:$|var2:best.|var3:date9.|
|
|var1:$32|var2:best.|var3:date9.|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|some text|42|01JAN1960|
|
|some text|42|01JAN1960|
|
||||||
|blah|1|31DEC1999|
|
|blah|1|31DEC1999|
|
||||||
@@ -9984,6 +10128,7 @@ data _null_;
|
|||||||
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
||||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||||
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
||||||
|
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
||||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||||
@@ -13479,6 +13624,7 @@ run;
|
|||||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||||
|
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||||
put ",""SYSSITE"" : ""&syssite"" ";
|
put ",""SYSSITE"" : ""&syssite"" ";
|
||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
@@ -14950,6 +15096,7 @@ data _null_;
|
|||||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||||
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
||||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||||
|
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
||||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||||
@@ -18789,6 +18936,7 @@ filename &fref1 clear;
|
|||||||
put ",""SYSCC"" : ""&syscc"" ";
|
put ",""SYSCC"" : ""&syscc"" ";
|
||||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
|
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||||
put ",""SYSSITE"" : ""&syssite"" ";
|
put ",""SYSSITE"" : ""&syssite"" ";
|
||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
@@ -18829,7 +18977,7 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '-- open file and perform the substitution ';
|
put '-- open file and perform the substitution ';
|
||||||
put 'file = io.open(fpath,"r") ';
|
put 'file = io.open(fpath,"r") ';
|
||||||
put 'fcontent = file:read() ';
|
put 'fcontent = file:read("*all") ';
|
||||||
put 'file:close() ';
|
put 'file:close() ';
|
||||||
put 'fcontent = string.gsub( ';
|
put 'fcontent = string.gsub( ';
|
||||||
put ' fcontent, ';
|
put ' fcontent, ';
|
||||||
@@ -18844,7 +18992,7 @@ data _null_;
|
|||||||
put 'io.close(file) ';
|
put 'io.close(file) ';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%inc "%sysfunc(pathname(work))/ml_gsubfile.lua";
|
%inc "%sysfunc(pathname(work))/ml_gsubfile.lua" /source2;
|
||||||
|
|
||||||
%mend ml_gsubfile;
|
%mend ml_gsubfile;
|
||||||
/**
|
/**
|
||||||
@@ -19238,7 +19386,7 @@ data _null_;
|
|||||||
put '-- JSON.LUA ENDS HERE ';
|
put '-- JSON.LUA ENDS HERE ';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%inc "%sysfunc(pathname(work))/ml_json.lua";
|
%inc "%sysfunc(pathname(work))/ml_json.lua" /source2;
|
||||||
|
|
||||||
%mend ml_json;
|
%mend ml_json;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -158,7 +158,7 @@
|
|||||||
/* send response in SASjs JSON format */
|
/* send response in SASjs JSON format */
|
||||||
data _null_;
|
data _null_;
|
||||||
file _webout mod lrecl=32000 encoding='utf-8';
|
file _webout mod lrecl=32000 encoding='utf-8';
|
||||||
length msg $32767 debug $8;
|
length msg $32767 ;
|
||||||
sasdatetime=datetime();
|
sasdatetime=datetime();
|
||||||
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
|
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
|
||||||
/* escape the quotes */
|
/* escape the quotes */
|
||||||
@@ -189,13 +189,16 @@
|
|||||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||||
put ",""SYSCC"" : ""&syscc"" ";
|
put ",""SYSCC"" : ""&syscc"" ";
|
||||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
syserrortext=quote(trim(symget('syserrortext')));
|
||||||
|
put ",""SYSERRORTEXT"" : " syserrortext;
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||||
|
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||||
put ",""SYSSITE"" : ""&syssite"" ";
|
put ",""SYSSITE"" : ""&syssite"" ";
|
||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
syswarningtext=quote(trim(symget('syswarningtext')));
|
||||||
|
put ",""SYSWARNINGTEXT"" : " syswarningtext;
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
||||||
put "}" @;
|
put "}" @;
|
||||||
if debug ge '"131"' then put '>>weboutEND<<';
|
if debug ge '"131"' then put '>>weboutEND<<';
|
||||||
@@ -205,7 +208,7 @@
|
|||||||
|
|
||||||
%if "&sysprocessmode " = "SAS Stored Process Server " %then %do;
|
%if "&sysprocessmode " = "SAS Stored Process Server " %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
putlog 'stpsrvset program error and syscc';
|
putlog 'stpsrvset program err and syscc';
|
||||||
rc=stpsrvset('program error', 0);
|
rc=stpsrvset('program error', 0);
|
||||||
call symputx("syscc",0,"g");
|
call symputx("syscc",0,"g");
|
||||||
run;
|
run;
|
||||||
|
|||||||
57
base/mp_appendfile.sas
Normal file
57
base/mp_appendfile.sas
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Append (concatenate) two or more files.
|
||||||
|
@details Will append one more more `appendrefs` (filerefs) to a `baseref`.
|
||||||
|
Uses a binary mechanism, so will work with any file type. For that reason -
|
||||||
|
use with care! And supply your own trailing carriage returns in each file..
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
filename tmp1 temp;
|
||||||
|
filename tmp2 temp;
|
||||||
|
filename tmp3 temp;
|
||||||
|
data _null_; file tmp1; put 'base file';
|
||||||
|
data _null_; file tmp2; put 'append1';
|
||||||
|
data _null_; file tmp3; put 'append2';
|
||||||
|
run;
|
||||||
|
%mp_appendfile(baseref=tmp1, appendrefs=tmp2 tmp3)
|
||||||
|
|
||||||
|
|
||||||
|
@param [in] baseref= Fileref of the base file (should exist)
|
||||||
|
@param [in] appendrefs= One or more filerefs to be appended to the base
|
||||||
|
fileref. Space separated.
|
||||||
|
|
||||||
|
@version 9.2
|
||||||
|
@author Allan Bowe, source: https://github.com/sasjs/core
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mp_abort.sas
|
||||||
|
@li mp_binarycopy.sas
|
||||||
|
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_appendfile(
|
||||||
|
baseref=0,
|
||||||
|
appendrefs=0
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%mp_abort(iftrue= (&baseref=0)
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=%str(Baseref NOT specified!)
|
||||||
|
)
|
||||||
|
%mp_abort(iftrue= (&appendrefs=0)
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=%str(Appendrefs NOT specified!)
|
||||||
|
)
|
||||||
|
|
||||||
|
%local i;
|
||||||
|
%do i=1 %to %sysfunc(countw(&appendrefs));
|
||||||
|
%mp_abort(iftrue= (&syscc>0)
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=%str(syscc=&syscc)
|
||||||
|
)
|
||||||
|
%mp_binarycopy(inref=%scan(&appendrefs,&i), outref=&baseref, mode=APPEND)
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend mp_appendfile;
|
||||||
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_existds.sas
|
@li mf_existds.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
@li mf_nobs.sas
|
@li mf_nobs.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
|
|
||||||
@@ -115,6 +116,26 @@
|
|||||||
select count(*) into: orig from &lib..&ds;
|
select count(*) into: orig from &lib..&ds;
|
||||||
quit;
|
quit;
|
||||||
|
|
||||||
|
%local notfound tmp1 tmp2;
|
||||||
|
%let tmp1=%mf_getuniquename();
|
||||||
|
%let tmp2=%mf_getuniquename();
|
||||||
|
|
||||||
|
/* this is a bit convoluted - but using sql outobs=10 throws warnings */
|
||||||
|
proc sql noprint;
|
||||||
|
create view &tmp1 as
|
||||||
|
select distinct &col
|
||||||
|
from &lib..&ds
|
||||||
|
where &col not in (
|
||||||
|
select &ccol from &clib..&cds
|
||||||
|
);
|
||||||
|
data &tmp2;
|
||||||
|
set &tmp1;
|
||||||
|
if _n_>10 then stop;
|
||||||
|
run;
|
||||||
|
proc sql;
|
||||||
|
select distinct &col into: notfound separated by ' ' from &tmp2;
|
||||||
|
|
||||||
|
|
||||||
%mp_abort(iftrue= (&syscc ne 0)
|
%mp_abort(iftrue= (&syscc ne 0)
|
||||||
,mac=&sysmacroname
|
,mac=&sysmacroname
|
||||||
,msg=%str(syscc=&syscc after macro query)
|
,msg=%str(syscc=&syscc after macro query)
|
||||||
@@ -125,7 +146,7 @@
|
|||||||
test_description=symget('desc');
|
test_description=symget('desc');
|
||||||
test_result='FAIL';
|
test_result='FAIL';
|
||||||
test_comments="&sysmacroname: &lib..&ds..&col has &result values "
|
test_comments="&sysmacroname: &lib..&ds..&col has &result values "
|
||||||
!!"not in &clib..&cds..&ccol ";
|
!!"not in &clib..&cds..&ccol.. First 10 vals:"!!symget('notfound');
|
||||||
%if &test=ANYVAL %then %do;
|
%if &test=ANYVAL %then %do;
|
||||||
if &result < &orig then test_result='PASS';
|
if &result < &orig then test_result='PASS';
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
65
base/mp_getcols.sas
Normal file
65
base/mp_getcols.sas
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Creates a dataset with column metadata.
|
||||||
|
@details This macro takes the `proc contents` output and "tidies it up" in the
|
||||||
|
following ways:
|
||||||
|
|
||||||
|
@li Blank labels are filled in with column names
|
||||||
|
@li Formats are reconstructed with default values
|
||||||
|
@li Types such as DATE / TIME / DATETIME are inferred from the formats
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
%mp_getcols(sashelp.airline,outds=work.myds)
|
||||||
|
|
||||||
|
@param ds The dataset from which to obtain column metadata
|
||||||
|
@param outds= (work.cols) The output dataset to create. Sample data:
|
||||||
|
|NAME $|LENGTH 8|VARNUM 8|LABEL $|FORMAT $49|TYPE $1 |DDTYPE $|
|
||||||
|
|---|---|---|---|---|---|---|
|
||||||
|
|AIR|8|2|international airline travel (thousands)|8.|N|NUMERIC|
|
||||||
|
|DATE|8|1|DATE|MONYY.|N|DATE|
|
||||||
|
|REGION|3|3|REGION|$3.|C|CHARACTER|
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mf_getvarlist.sas
|
||||||
|
@li mm_getcols.sas
|
||||||
|
|
||||||
|
@version 9.2
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_getcols(ds, outds=work.cols);
|
||||||
|
|
||||||
|
proc contents noprint data=&ds
|
||||||
|
out=_data_ (keep=name type length label varnum format:);
|
||||||
|
run;
|
||||||
|
data &outds(keep=name type length varnum format label ddtype);
|
||||||
|
set &syslast(rename=(format=format2 type=type2));
|
||||||
|
name=upcase(name);
|
||||||
|
if type2=2 then do;
|
||||||
|
length format $49.;
|
||||||
|
if format2='' then format=cats('$',length,'.');
|
||||||
|
else if formatl=0 then format=cats(format2,'.');
|
||||||
|
else format=cats(format2,formatl,'.');
|
||||||
|
type='C';
|
||||||
|
ddtype='CHARACTER';
|
||||||
|
end;
|
||||||
|
else do;
|
||||||
|
if format2='' then format=cats(length,'.');
|
||||||
|
else if formatl=0 then format=cats(format2,'.');
|
||||||
|
else if formatd=0 then format=cats(format2,formatl,'.');
|
||||||
|
else format=cats(format2,formatl,'.',formatd);
|
||||||
|
type='N';
|
||||||
|
if format=:'DATETIME' then ddtype='DATETIME';
|
||||||
|
else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY'
|
||||||
|
or format=:'YYMMDD' or format=:'E8601DA' or format=:'B8601DA'
|
||||||
|
or format=:'MONYY'
|
||||||
|
then ddtype='DATE';
|
||||||
|
else if format=:'TIME' then ddtype='TIME';
|
||||||
|
else ddtype='NUMERIC';
|
||||||
|
end;
|
||||||
|
if label='' then label=name;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mend mp_getcols;
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
file "&file";
|
file "&file";
|
||||||
put "&str";
|
put "&str";
|
||||||
run;
|
run;
|
||||||
%mp_gsubfile(file=&file, pattern=str, replacement=rep)
|
%mp_gsubfile(file=&file, patternvar=str, replacevar=rep)
|
||||||
data _null_;
|
data _null_;
|
||||||
infile "&file";
|
infile "&file";
|
||||||
input;
|
input;
|
||||||
|
|||||||
@@ -14,14 +14,14 @@
|
|||||||
We take the standard definition one step further by embedding the informat
|
We take the standard definition one step further by embedding the informat
|
||||||
in the table header row, like so:
|
in the table header row, like so:
|
||||||
|
|
||||||
|var1:$|var2:best.|var3:date9.|
|
|var1:$32|var2:best.|var3:date9.|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|some text|42|01JAN1960|
|
|some text|42|01JAN1960|
|
||||||
|blah|1|31DEC1999|
|
|blah|1|31DEC1999|
|
||||||
|
|
||||||
Which resolves to:
|
Which resolves to:
|
||||||
|
|
||||||
|var1:$|var2:best.|var3:date9.|
|
|var1:$32|var2:best.|var3:date9.|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|some text|42|01JAN1960|
|
|some text|42|01JAN1960|
|
||||||
|blah|1|31DEC1999|
|
|blah|1|31DEC1999|
|
||||||
|
|||||||
2
build.py
2
build.py
@@ -22,7 +22,7 @@ for file in files:
|
|||||||
for line in infile:
|
for line in infile:
|
||||||
ml.write(" put '" + line.rstrip().replace("'","''") + " ';\n")
|
ml.write(" put '" + line.rstrip().replace("'","''") + " ';\n")
|
||||||
ml.write("run;\n\n")
|
ml.write("run;\n\n")
|
||||||
ml.write("%inc \"%sysfunc(pathname(work))/" + name + ".lua\";\n\n")
|
ml.write("%inc \"%sysfunc(pathname(work))/" + name + ".lua\" /source2;\n\n")
|
||||||
ml.write("%mend " + name + ";\n")
|
ml.write("%mend " + name + ";\n")
|
||||||
|
|
||||||
ml.close()
|
ml.close()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ end
|
|||||||
|
|
||||||
-- open file and perform the substitution
|
-- open file and perform the substitution
|
||||||
file = io.open(fpath,"r")
|
file = io.open(fpath,"r")
|
||||||
fcontent = file:read()
|
fcontent = file:read("*all")
|
||||||
file:close()
|
file:close()
|
||||||
fcontent = string.gsub(
|
fcontent = string.gsub(
|
||||||
fcontent,
|
fcontent,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '-- open file and perform the substitution ';
|
put '-- open file and perform the substitution ';
|
||||||
put 'file = io.open(fpath,"r") ';
|
put 'file = io.open(fpath,"r") ';
|
||||||
put 'fcontent = file:read() ';
|
put 'fcontent = file:read("*all") ';
|
||||||
put 'file:close() ';
|
put 'file:close() ';
|
||||||
put 'fcontent = string.gsub( ';
|
put 'fcontent = string.gsub( ';
|
||||||
put ' fcontent, ';
|
put ' fcontent, ';
|
||||||
@@ -39,6 +39,6 @@ data _null_;
|
|||||||
put 'io.close(file) ';
|
put 'io.close(file) ';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%inc "%sysfunc(pathname(work))/ml_gsubfile.lua";
|
%inc "%sysfunc(pathname(work))/ml_gsubfile.lua" /source2;
|
||||||
|
|
||||||
%mend ml_gsubfile;
|
%mend ml_gsubfile;
|
||||||
|
|||||||
@@ -389,6 +389,6 @@ data _null_;
|
|||||||
put '-- JSON.LUA ENDS HERE ';
|
put '-- JSON.LUA ENDS HERE ';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%inc "%sysfunc(pathname(work))/ml_json.lua";
|
%inc "%sysfunc(pathname(work))/ml_json.lua" /source2;
|
||||||
|
|
||||||
%mend ml_json;
|
%mend ml_json;
|
||||||
|
|||||||
@@ -385,6 +385,7 @@ data _null_;
|
|||||||
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
||||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||||
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
||||||
|
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
||||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||||
|
|||||||
@@ -155,6 +155,7 @@
|
|||||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||||
|
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||||
put ",""SYSSITE"" : ""&syssite"" ";
|
put ",""SYSSITE"" : ""&syssite"" ";
|
||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
|
|||||||
41
tests/crossplatform/mp_appendfile.test.sas
Normal file
41
tests/crossplatform/mp_appendfile.test.sas
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mp_appendfile.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mp_appendfile.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
filename tmp1 temp;
|
||||||
|
filename tmp2 temp;
|
||||||
|
filename tmp3 temp;
|
||||||
|
data _null_; file tmp1; put 'base file';
|
||||||
|
data _null_; file tmp2; put 'append1';
|
||||||
|
data _null_; file tmp3; put 'append2';
|
||||||
|
run;
|
||||||
|
%mp_appendfile(baseref=tmp1, appendrefs=tmp2 tmp3)
|
||||||
|
data _null_;
|
||||||
|
infile tmp1;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
call symputx(cats('check',_n_),_infile_);
|
||||||
|
run;
|
||||||
|
%global check1 check2 check3;
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&check1"="base file"),
|
||||||
|
desc=Line 1 of file tmp1 is correct,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&check2"="append1"),
|
||||||
|
desc=Line 2 of file tmp1 is correct,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&check3"="append2"),
|
||||||
|
desc=Line 3 of file tmp1 is correct,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
33
tests/crossplatform/mp_getcols.test.sas
Normal file
33
tests/crossplatform/mp_getcols.test.sas
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mp_getcols macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mp_getcols.sas
|
||||||
|
@li mp_assertcolvals.sas
|
||||||
|
@li mp_assertdsobs.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
/* valid filter */
|
||||||
|
%mp_getcols(sashelp.airline,outds=work.info)
|
||||||
|
|
||||||
|
|
||||||
|
%mp_assertdsobs(work.info,
|
||||||
|
desc=Has 3 records,
|
||||||
|
test=EQUALS 3,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
data work.check;
|
||||||
|
length val $10;
|
||||||
|
do val='NUMERIC','DATE','CHARACTER';
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
%mp_assertcolvals(work.info.ddtype,
|
||||||
|
checkvals=work.check.val,
|
||||||
|
desc=All values have a match,
|
||||||
|
test=ALLVALS
|
||||||
|
)
|
||||||
@@ -30,4 +30,37 @@ run;
|
|||||||
iftrue=("&str1"="&str"),
|
iftrue=("&str1"="&str"),
|
||||||
desc=Check that simple replacement was successful,
|
desc=Check that simple replacement was successful,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test 2 - replace from additional line
|
||||||
|
*/
|
||||||
|
%global str2 strcheck2 strcheck2b;
|
||||||
|
%let file2=%sysfunc(pathname(work))/file2.txt;
|
||||||
|
%let pat2=replace/me;
|
||||||
|
%let str2=with/this;
|
||||||
|
data _null_;
|
||||||
|
file "&file2";
|
||||||
|
put 'line1';output;
|
||||||
|
put "&pat2";output;
|
||||||
|
put "&pat2";output;
|
||||||
|
run;
|
||||||
|
%mp_gsubfile(file=&file2, patternvar=pat2, replacevar=str2)
|
||||||
|
data _null_;
|
||||||
|
infile "&file2";
|
||||||
|
input;
|
||||||
|
if _n_=2 then call symputx('strcheck2',_infile_);
|
||||||
|
if _n_=3 then call symputx('strcheck2b',_infile_);
|
||||||
|
putlog _infile_;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&strcheck2"="&str2"),
|
||||||
|
desc=Check that multi line replacement was successful (line2),
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&strcheck2b"="&str2"),
|
||||||
|
desc=Check that multi line replacement was successful (line3),
|
||||||
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
@@ -590,6 +590,7 @@ data _null_;
|
|||||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||||
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
||||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||||
|
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
||||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||||
|
|||||||
@@ -215,6 +215,7 @@
|
|||||||
put ",""SYSCC"" : ""&syscc"" ";
|
put ",""SYSCC"" : ""&syscc"" ";
|
||||||
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
|
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
||||||
put ",""SYSSITE"" : ""&syssite"" ";
|
put ",""SYSSITE"" : ""&syssite"" ";
|
||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
|
|||||||
Reference in New Issue
Block a user