mirror of
https://github.com/sasjs/core.git
synced 2026-01-10 02:40:05 +00:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f28f6b1530 | ||
|
|
cb4ea71e81 | ||
|
|
fe94d3781a | ||
|
|
7c17b39dad | ||
|
|
73dab4c651 | ||
|
|
5d72843167 | ||
|
|
f43df47cff | ||
|
|
aaca26770b | ||
|
|
4a124d5bd8 | ||
|
|
03cd52a01a | ||
|
|
da79181b00 | ||
|
|
a405104052 | ||
|
|
56fdaa65d2 | ||
|
|
9d60c49c9f | ||
|
|
380170d5ba | ||
|
|
4b450f2091 | ||
|
|
1b013fbf1c | ||
|
|
bf7459bd2d | ||
|
|
1096db0846 | ||
|
|
fc9b765246 | ||
|
|
4a8f7bb014 | ||
|
|
e0469be0d8 | ||
|
|
e9e576b5ec | ||
|
|
1a32d114f1 | ||
|
|
94e83f6b8d | ||
|
|
35a6dede6f | ||
|
|
039ec397dd | ||
|
|
dce4630eb8 | ||
|
|
1e142f042b | ||
|
|
7caca2f139 | ||
|
|
61556b2de8 | ||
|
|
9e12409389 |
@@ -126,6 +126,15 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"code"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "eltociear",
|
||||||
|
"name": "Ikko Ashimine",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/22633385?v=4",
|
||||||
|
"profile": "https://bandism.net/",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ sasjs/
|
|||||||
.github/
|
.github/
|
||||||
.git-hooks/
|
.git-hooks/
|
||||||
.vscode/
|
.vscode/
|
||||||
main.dox
|
|
||||||
make_singlefile.sh
|
make_singlefile.sh
|
||||||
*.md
|
*.md
|
||||||
.all-contributorsrc
|
.all-contributorsrc
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
[dependency-url]:https://github.com/sasjs/core/blob/main/package.json
|
[dependency-url]:https://github.com/sasjs/core/blob/main/package.json
|
||||||
|
|
||||||
|
|
||||||
Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of [Application Development](https://sasapps.io) on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/CONTRIBUTING.md) are welcomed.
|
Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of [Application Development](https://sasapps.io) on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/.github/CONTRIBUTING.md) are welcome.
|
||||||
|
|
||||||
You can download and compile them all in just two lines of SAS code:
|
You can download and compile them all in just two lines of SAS code:
|
||||||
|
|
||||||
@@ -224,12 +224,13 @@ The following repositories are also worth checking out:
|
|||||||
* [chris-swenson/sasmacros](https://github.com/chris-swenson/sasmacros)
|
* [chris-swenson/sasmacros](https://github.com/chris-swenson/sasmacros)
|
||||||
* [greg-wotton/sas-programs](https://github.com/greg-wootton/sas-programs)
|
* [greg-wotton/sas-programs](https://github.com/greg-wootton/sas-programs)
|
||||||
* [KatjaGlassConsulting/SMILE-SmartSASMacros](https://github.com/KatjaGlassConsulting/SMILE-SmartSASMacros)
|
* [KatjaGlassConsulting/SMILE-SmartSASMacros](https://github.com/KatjaGlassConsulting/SMILE-SmartSASMacros)
|
||||||
|
* [rogerjdeangelis](https://github.com/rogerjdeangelis)
|
||||||
* [scottbass/sas](https://github.com/scottbass/SAS)
|
* [scottbass/sas](https://github.com/scottbass/SAS)
|
||||||
* [yabwon/sas_packages](https://github.com/yabwon/SAS_PACKAGES)
|
* [yabwon/sas_packages](https://github.com/yabwon/SAS_PACKAGES)
|
||||||
|
|
||||||
## Contributors ✨
|
## Contributors ✨
|
||||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||||
[](#contributors-)
|
[](#contributors-)
|
||||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||||
|
|
||||||
@@ -251,6 +252,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<td align="center"><a href="https://github.com/VladislavParhomchik"><img src="https://avatars.githubusercontent.com/u/83717836?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vladislav Parhomchik</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=VladislavParhomchik" title="Tests">⚠️</a> <a href="https://github.com/sasjs/core/pulls?q=is%3Apr+reviewed-by%3AVladislavParhomchik" title="Reviewed Pull Requests">👀</a></td>
|
<td align="center"><a href="https://github.com/VladislavParhomchik"><img src="https://avatars.githubusercontent.com/u/83717836?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vladislav Parhomchik</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=VladislavParhomchik" title="Tests">⚠️</a> <a href="https://github.com/sasjs/core/pulls?q=is%3Apr+reviewed-by%3AVladislavParhomchik" title="Reviewed Pull Requests">👀</a></td>
|
||||||
<td align="center"><a href="https://github.com/vznesh"><img src="https://avatars.githubusercontent.com/u/28916792?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vignesh T.</b></sub></a><br /><a href="https://github.com/sasjs/core/issues?q=author%3Avznesh" title="Bug reports">🐛</a></td>
|
<td align="center"><a href="https://github.com/vznesh"><img src="https://avatars.githubusercontent.com/u/28916792?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vignesh T.</b></sub></a><br /><a href="https://github.com/sasjs/core/issues?q=author%3Avznesh" title="Bug reports">🐛</a></td>
|
||||||
<td align="center"><a href="https://github.com/yabwon"><img src="https://avatars.githubusercontent.com/u/9314894?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bart Jablonski</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=yabwon" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/yabwon"><img src="https://avatars.githubusercontent.com/u/9314894?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bart Jablonski</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=yabwon" title="Code">💻</a></td>
|
||||||
|
<td align="center"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=eltociear" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
269
all.sas
269
all.sas
@@ -188,7 +188,7 @@ options noquotelenmax;
|
|||||||
%put No feature was requested for detection;
|
%put No feature was requested for detection;
|
||||||
%end;
|
%end;
|
||||||
%else %if &feature=COLCONSTRAINTS %then %do;
|
%else %if &feature=COLCONSTRAINTS %then %do;
|
||||||
%if %substr(&sysver,1,1)=4 %then 0;
|
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 0;
|
||||||
%else 1;
|
%else 1;
|
||||||
%end;
|
%end;
|
||||||
%else %if &feature=PROCLUA %then %do;
|
%else %if &feature=PROCLUA %then %do;
|
||||||
@@ -369,6 +369,48 @@ https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md#functionex
|
|||||||
%mend mf_existvarlist;
|
%mend mf_existvarlist;
|
||||||
|
|
||||||
/** @endcond *//**
|
/** @endcond *//**
|
||||||
|
@file
|
||||||
|
@brief Returns E8601DT26.6 if compatible else DATETIME19.3
|
||||||
|
@details From our experience in [Data Controller for SAS]
|
||||||
|
(https://datacontroller.io) deployments, the E8601DT26.6 datetime format has
|
||||||
|
the widest support when it comes to pass-through SQL queries.
|
||||||
|
|
||||||
|
However, it is not supported in WPS or early versions of SAS 9 (M3 and below)
|
||||||
|
when used as a datetime literal, eg:
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
demo="%sysfunc(datetime(),E8601DT26.6)"dt;
|
||||||
|
demo=;
|
||||||
|
run;
|
||||||
|
|
||||||
|
This macro will therefore return DATEITME19.3 as an alternative format
|
||||||
|
based on the runtime environment so that it can be used in such cases, eg:
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
demo="%sysfunc(datetime(),%mf_fmtdttm())"dt;
|
||||||
|
demo=;
|
||||||
|
run;
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mf_fmtdttm.test.sas
|
||||||
|
|
||||||
|
@author Allan Bowe
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mf_fmtdttm(
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%if "&sysver"="9.2" or "&sysver"="9.3"
|
||||||
|
or ("&sysver"="9.4" and "%substr(&SYSVLONG,9,1)" le "3")
|
||||||
|
or "%substr(&sysver,1,1)"="4"
|
||||||
|
or "%substr(&sysver,1,1)"="5"
|
||||||
|
%then %do;DATETIME19.3%end;
|
||||||
|
%else %do;E8601DT26.6%end;
|
||||||
|
|
||||||
|
%mend mf_fmtdttm;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Returns the appLoc from the _program variable
|
@brief Returns the appLoc from the _program variable
|
||||||
@details When working with SASjs apps, web services / tests / jobs are always
|
@details When working with SASjs apps, web services / tests / jobs are always
|
||||||
@@ -994,12 +1036,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 +1190,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 +2262,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_;
|
||||||
@@ -6506,6 +6570,22 @@ drop table &dropds;
|
|||||||
%let lib=%upcase(&lib);
|
%let lib=%upcase(&lib);
|
||||||
%let ds=%upcase(&ds);
|
%let ds=%upcase(&ds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cater for environments where sashelp.vcncolu is not available
|
||||||
|
*/
|
||||||
|
%if %sysfunc(exist(sashelp.vcncolu,view))=0 %then %do;
|
||||||
|
proc sql;
|
||||||
|
create table &outds(
|
||||||
|
libref char(8)
|
||||||
|
,TABLE_NAME char(32)
|
||||||
|
,constraint_type char(8) label='Constraint Type'
|
||||||
|
,constraint_name char(32) label='Constraint Name'
|
||||||
|
,column_name char(32) label='Column'
|
||||||
|
,constraint_order num
|
||||||
|
);
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Neither dictionary tables nor sashelp provides a constraint order column,
|
* Neither dictionary tables nor sashelp provides a constraint order column,
|
||||||
* however they DO arrive in the correct order. So, create the col.
|
* however they DO arrive in the correct order. So, create the col.
|
||||||
@@ -7458,6 +7538,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 +7558,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 +7568,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 +7610,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));
|
||||||
@@ -8443,7 +8547,7 @@ options
|
|||||||
validvarname=V7 /* avoid special characters etc in variable names */
|
validvarname=V7 /* avoid special characters etc in variable names */
|
||||||
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
|
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
|
||||||
varlenchk=%str(ERR)OR /* fail hard if truncation (data loss) can result */
|
varlenchk=%str(ERR)OR /* fail hard if truncation (data loss) can result */
|
||||||
%if %substr(&sysver,1,1) ne 4 %then %do;
|
%if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
|
||||||
noautocorrect /* disallow misspelled procedure names */
|
noautocorrect /* disallow misspelled procedure names */
|
||||||
dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
|
dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
|
||||||
%end;
|
%end;
|
||||||
@@ -9213,6 +9317,7 @@ options ibufsize=&ibufsize;
|
|||||||
@param [in] loop_secs= (1) Seconds to wait between each lock attempt
|
@param [in] loop_secs= (1) Seconds to wait between each lock attempt
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_fmtdttm.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mp_lockfilecheck.sas
|
@li mp_lockfilecheck.sas
|
||||||
@li mf_getuser.sas
|
@li mf_getuser.sas
|
||||||
@@ -9302,7 +9407,7 @@ run;
|
|||||||
LOCK_LIB ="&lib";
|
LOCK_LIB ="&lib";
|
||||||
LOCK_DS="&ds";
|
LOCK_DS="&ds";
|
||||||
LOCK_STATUS_CD='LOCKED';
|
LOCK_STATUS_CD='LOCKED';
|
||||||
LOCK_START_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt;
|
LOCK_START_DTTM="%sysfunc(datetime(),%mf_fmtdttm())"dt;
|
||||||
LOCK_USER_NM="&user";
|
LOCK_USER_NM="&user";
|
||||||
LOCK_PID="&sysjobid";
|
LOCK_PID="&sysjobid";
|
||||||
LOCK_REF="&ref";
|
LOCK_REF="&ref";
|
||||||
@@ -9322,7 +9427,7 @@ run;
|
|||||||
proc sql;
|
proc sql;
|
||||||
update &ctl_ds
|
update &ctl_ds
|
||||||
set LOCK_STATUS_CD='LOCKED'
|
set LOCK_STATUS_CD='LOCKED'
|
||||||
, LOCK_START_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt
|
, LOCK_START_DTTM="%sysfunc(datetime(),%mf_fmtdttm())"dt
|
||||||
, LOCK_USER_NM="&user"
|
, LOCK_USER_NM="&user"
|
||||||
, LOCK_PID="&sysjobid"
|
, LOCK_PID="&sysjobid"
|
||||||
, LOCK_REF="&ref"
|
, LOCK_REF="&ref"
|
||||||
@@ -9397,7 +9502,7 @@ run;
|
|||||||
proc sql;
|
proc sql;
|
||||||
update &ctl_ds
|
update &ctl_ds
|
||||||
set LOCK_STATUS_CD='UNLOCKED'
|
set LOCK_STATUS_CD='UNLOCKED'
|
||||||
, LOCK_END_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt
|
, LOCK_END_DTTM="%sysfunc(datetime(),%mf_fmtdttm())"dt
|
||||||
, LOCK_USER_NM="&user"
|
, LOCK_USER_NM="&user"
|
||||||
, LOCK_PID="&sysjobid"
|
, LOCK_PID="&sysjobid"
|
||||||
, LOCK_REF="&ref"
|
, LOCK_REF="&ref"
|
||||||
@@ -10186,6 +10291,7 @@ run;
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_existvar.sas
|
@li mf_existvar.sas
|
||||||
|
@li mf_fmtdttm.sas
|
||||||
@li mf_getquotedstr.sas
|
@li mf_getquotedstr.sas
|
||||||
@li mf_getuniquename.sas
|
@li mf_getuniquename.sas
|
||||||
@li mf_nobs.sas
|
@li mf_nobs.sas
|
||||||
@@ -10345,12 +10451,12 @@ quit;
|
|||||||
set keytable="&base_libds"
|
set keytable="&base_libds"
|
||||||
,keycolumn="&retained_key"
|
,keycolumn="&retained_key"
|
||||||
,max_key=%eval(&maxkey+&newkey_cnt)
|
,max_key=%eval(&maxkey+&newkey_cnt)
|
||||||
,processed_dttm="%sysfunc(datetime(),E8601DT26.6)"dt;
|
,processed_dttm="%sysfunc(datetime(),%mf_fmtdttm())"dt;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
update &maxkeytable
|
update &maxkeytable
|
||||||
set max_key=%eval(&maxkey+&newkey_cnt)
|
set max_key=%eval(&maxkey+&newkey_cnt)
|
||||||
,processed_dttm="%sysfunc(datetime(),E8601DT26.6)"dt
|
,processed_dttm="%sysfunc(datetime(),%mf_fmtdttm())"dt
|
||||||
where keytable="&base_libds";
|
where keytable="&base_libds";
|
||||||
%end;
|
%end;
|
||||||
%mp_lockanytable(UNLOCK
|
%mp_lockanytable(UNLOCK
|
||||||
@@ -11546,7 +11652,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 +11687,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);
|
||||||
@@ -11722,8 +11828,9 @@ create table &outds as
|
|||||||
%mend mp_stprequests;/**
|
%mend mp_stprequests;/**
|
||||||
@file
|
@file
|
||||||
@brief Streams a file to _webout according to content type
|
@brief Streams a file to _webout according to content type
|
||||||
@details Will set headers using appropriate functions (SAS 9 vs Viya) and send
|
@details Will set headers using appropriate functions per the server type
|
||||||
content as a binary stream.
|
(Viya, EBI, [SASjs Server](https://github.com/sasjs/server)) and stream
|
||||||
|
content using mp_binarycopy().
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
@@ -11733,7 +11840,14 @@ create table &outds as
|
|||||||
|
|
||||||
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
||||||
|
|
||||||
@param [in] contenttype= (TEXT) Either TEXT, ZIP, CSV, EXCEL
|
@param [in] contenttype= (TEXT) Supported:
|
||||||
|
@li CSV
|
||||||
|
@li EXCEL
|
||||||
|
@li MARKDOWN
|
||||||
|
@li TEXT
|
||||||
|
@li ZIP
|
||||||
|
Feel free to submit PRs to support more mime types! The official list is
|
||||||
|
here: https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||||
@param [in] inloc= /path/to/file.ext to be sent
|
@param [in] inloc= /path/to/file.ext to be sent
|
||||||
@param [in] inref= fileref of file to be sent (if provided, overrides `inloc`)
|
@param [in] inref= fileref of file to be sent (if provided, overrides `inloc`)
|
||||||
@param [in] iftrue= (1=1) Provide a condition under which to execute.
|
@param [in] iftrue= (1=1) Provide a condition under which to execute.
|
||||||
@@ -11779,7 +11893,7 @@ run;
|
|||||||
%if &contentype=CSV %then %do;
|
%if &contentype=CSV %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/csv');
|
rc=stpsrv_header('Content-Type','application/csv');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -11789,7 +11903,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/csv)
|
%mfs_httpheader(Content-Type,application/csv)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
@@ -11797,7 +11911,7 @@ run;
|
|||||||
/* suitable for XLS format */
|
/* suitable for XLS format */
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/vnd.ms-excel');
|
rc=stpsrv_header('Content-Type','application/vnd.ms-excel');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -11807,14 +11921,14 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/vnd.ms-excel)
|
%mfs_httpheader(Content-Type,application/vnd.ms-excel)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-Type',"image/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
@@ -11822,30 +11936,30 @@ run;
|
|||||||
contenttype="image/%lowcase(&contenttype)";
|
contenttype="image/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,image/%lowcase(&contenttype))
|
%mfs_httpheader(Content-Type,image/%lowcase(&contenttype))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=HTML %then %do;
|
%else %if &contentype=HTML or &contenttype=MARKDOWN %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','text/html');
|
rc=stpsrv_header('Content-Type',"text/%lowcase(&contenttype)");
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
||||||
contenttype="text/html"
|
contenttype="text/%lowcase(&contenttype)"
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,text/html)
|
%mfs_httpheader(Content-Type,text/%lowcase(&contenttype))
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=TEXT %then %do;
|
%else %if &contentype=TEXT %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/text');
|
rc=stpsrv_header('Content-Type','application/text');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -11855,14 +11969,14 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/text)
|
%mfs_httpheader(Content-Type,application/text)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-Type',"font/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
@@ -11870,13 +11984,13 @@ run;
|
|||||||
contenttype="font/%lowcase(&contenttype)";
|
contenttype="font/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,font/%lowcase(&contenttype))
|
%mfs_httpheader(Content-Type,font/%lowcase(&contenttype))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=XLSX %then %do;
|
%else %if &contentype=XLSX %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',
|
rc=stpsrv_header('Content-Type',
|
||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
@@ -11888,7 +12002,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type
|
%mfs_httpheader(Content-Type
|
||||||
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||||
)
|
)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
@@ -11897,7 +12011,7 @@ run;
|
|||||||
%else %if &contentype=ZIP %then %do;
|
%else %if &contentype=ZIP %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/zip');
|
rc=stpsrv_header('Content-Type','application/zip');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -11907,7 +12021,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/zip)
|
%mfs_httpheader(Content-Type,application/zip)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
@@ -12303,9 +12417,11 @@ filename &webref "&webrefpath";
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &mdebug=0 %then %do;
|
%if &mdebug=0 %then %do;
|
||||||
filename &webref clear;
|
|
||||||
filename &fref1 clear;
|
filename &fref1 clear;
|
||||||
filename &fref2 clear;
|
%if &platform ne SASJS %then %do;
|
||||||
|
filename &fref2 clear;
|
||||||
|
filename &webref clear;
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put &sysmacroname exit vars:;
|
%put &sysmacroname exit vars:;
|
||||||
@@ -13039,8 +13155,8 @@ proc sql;
|
|||||||
create table &libds(
|
create table &libds(
|
||||||
FMTNAME char(32) label='Format name'
|
FMTNAME char(32) label='Format name'
|
||||||
/*
|
/*
|
||||||
to accomodate larger START values, mp_loadformat.sas will need the
|
to accommodate larger START values, mp_loadformat.sas will need the
|
||||||
SQL dependency removed (proc sql needs to accomodate 3 index values in
|
SQL dependency removed (proc sql needs to accommodate 3 index values in
|
||||||
a 32767 ibufsize limit)
|
a 32767 ibufsize limit)
|
||||||
*/
|
*/
|
||||||
,START char(10000) label='Starting value for format'
|
,START char(10000) label='Starting value for format'
|
||||||
@@ -13065,7 +13181,8 @@ create table &libds(
|
|||||||
,LANGUAGE char(8) label='Language for date strings'
|
,LANGUAGE char(8) label='Language for date strings'
|
||||||
);
|
);
|
||||||
|
|
||||||
%mend mddl_sas_cntlout;/**
|
%mend mddl_sas_cntlout;
|
||||||
|
/**
|
||||||
@file mm_adduser2group.sas
|
@file mm_adduser2group.sas
|
||||||
@brief Adds a user to a group
|
@brief Adds a user to a group
|
||||||
@details Adds a user to a metadata group. The macro first checks whether the
|
@details Adds a user to a metadata group. The macro first checks whether the
|
||||||
@@ -19219,8 +19336,8 @@ data _null_;
|
|||||||
file &fname1 lrecl=1000;
|
file &fname1 lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Content-Type: multipart/form-data; boundary=&boundary";
|
if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary";
|
||||||
put "Authorization: Bearer " _infile_;
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
@@ -19350,9 +19467,11 @@ data _null_;
|
|||||||
file &fref1 lrecl=1000;
|
file &fref1 lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Authorization: Bearer " _infile_;
|
if _n_=1 then do;
|
||||||
put "Content-Type: application/json";
|
put "Content-Type: application/json";
|
||||||
put "accept: application/json";
|
put "accept: application/json";
|
||||||
|
end;
|
||||||
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
@@ -19797,6 +19916,11 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
||||||
|
put ' %if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then %do; ';
|
||||||
|
put ' /* functions in formats unsupported */ ';
|
||||||
|
put ' %put &sysmacroname: forcing missing back to NULL as feature not supported; ';
|
||||||
|
put ' %let missing=NULL; ';
|
||||||
|
put ' %end; ';
|
||||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
||||||
put ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta ';
|
put ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta ';
|
||||||
put ' ) ';
|
put ' ) ';
|
||||||
@@ -19972,7 +20096,7 @@ data _null_;
|
|||||||
file &headref lrecl=1000;
|
file &headref lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Authorization: Bearer " _infile_;
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
proc http method='DELETE' headerin=&headref
|
proc http method='DELETE' headerin=&headref
|
||||||
@@ -20021,7 +20145,7 @@ data _null_;
|
|||||||
file &headref lrecl=1000;
|
file &headref lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Authorization: Bearer " _infile_;
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
proc http method='GET' out=&binaryfref headerin=&headref
|
proc http method='GET' out=&binaryfref headerin=&headref
|
||||||
@@ -20092,8 +20216,8 @@ data _null_;
|
|||||||
file &fref0 lrecl=1000;
|
file &fref0 lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Authorization: Bearer " _infile_;
|
if _n_=1 then put "accept: application/json";
|
||||||
put "accept: application/json";
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
@@ -20280,8 +20404,8 @@ data _null_;
|
|||||||
file &authref lrecl=1000;
|
file &authref lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put 'Authorization: Bearer ' _infile_;
|
if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary";
|
||||||
put "Content-Type: multipart/form-data; boundary=&boundary";
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
@@ -20399,7 +20523,7 @@ options &optval;
|
|||||||
outref=0,
|
outref=0,
|
||||||
outlogds=_null_
|
outlogds=_null_
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local dbg fref1 chopout1 chopout2;
|
%local dbg i var ds1 fref1 chopout1 chopout2;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -20422,13 +20546,15 @@ options &optval;
|
|||||||
%let ds1=%mf_getuniquename();
|
%let ds1=%mf_getuniquename();
|
||||||
data &ds1;
|
data &ds1;
|
||||||
length fileref $8 name $32 filename $256 var $300;
|
length fileref $8 name $32 filename $256 var $300;
|
||||||
webcount=countw("&inputfiles");
|
if "&inputfiles" ne "0" then do;
|
||||||
do i=1 to webcount;
|
webcount=countw("&inputfiles");
|
||||||
var=scan("&inputfiles",i,' ');
|
do i=1 to webcount;
|
||||||
fileref=scan(var,1,':');
|
var=scan("&inputfiles",i,' ');
|
||||||
name=scan(var,2,':');
|
fileref=scan(var,1,':');
|
||||||
filename=cats(name,'.csv');
|
name=scan(var,2,':');
|
||||||
output;
|
filename=cats(name,'.csv');
|
||||||
|
output;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
@@ -20591,6 +20717,11 @@ run;
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%else %if &action=ARR or &action=OBJ %then %do;
|
%else %if &action=ARR or &action=OBJ %then %do;
|
||||||
|
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then %do;
|
||||||
|
/* functions in formats unsupported */
|
||||||
|
%put &sysmacroname: forcing missing back to NULL as feature not supported;
|
||||||
|
%let missing=NULL;
|
||||||
|
%end;
|
||||||
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
|
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
|
||||||
,engine=DATASTEP,missing=&missing,showmeta=&showmeta
|
,engine=DATASTEP,missing=&missing,showmeta=&showmeta
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
%put No feature was requested for detection;
|
%put No feature was requested for detection;
|
||||||
%end;
|
%end;
|
||||||
%else %if &feature=COLCONSTRAINTS %then %do;
|
%else %if &feature=COLCONSTRAINTS %then %do;
|
||||||
%if %substr(&sysver,1,1)=4 %then 0;
|
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 0;
|
||||||
%else 1;
|
%else 1;
|
||||||
%end;
|
%end;
|
||||||
%else %if &feature=PROCLUA %then %do;
|
%else %if &feature=PROCLUA %then %do;
|
||||||
|
|||||||
42
base/mf_fmtdttm.sas
Normal file
42
base/mf_fmtdttm.sas
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Returns E8601DT26.6 if compatible else DATETIME19.3
|
||||||
|
@details From our experience in [Data Controller for SAS]
|
||||||
|
(https://datacontroller.io) deployments, the E8601DT26.6 datetime format has
|
||||||
|
the widest support when it comes to pass-through SQL queries.
|
||||||
|
|
||||||
|
However, it is not supported in WPS or early versions of SAS 9 (M3 and below)
|
||||||
|
when used as a datetime literal, eg:
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
demo="%sysfunc(datetime(),E8601DT26.6)"dt;
|
||||||
|
demo=;
|
||||||
|
run;
|
||||||
|
|
||||||
|
This macro will therefore return DATEITME19.3 as an alternative format
|
||||||
|
based on the runtime environment so that it can be used in such cases, eg:
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
demo="%sysfunc(datetime(),%mf_fmtdttm())"dt;
|
||||||
|
demo=;
|
||||||
|
run;
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mf_fmtdttm.test.sas
|
||||||
|
|
||||||
|
@author Allan Bowe
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mf_fmtdttm(
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%if "&sysver"="9.2" or "&sysver"="9.3"
|
||||||
|
or ("&sysver"="9.4" and "%substr(&SYSVLONG,9,1)" le "3")
|
||||||
|
or "%substr(&sysver,1,1)"="4"
|
||||||
|
or "%substr(&sysver,1,1)"="5"
|
||||||
|
%then %do;DATETIME19.3%end;
|
||||||
|
%else %do;E8601DT26.6%end;
|
||||||
|
|
||||||
|
%mend mf_fmtdttm;
|
||||||
|
|
||||||
|
|
||||||
@@ -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:
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -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_;
|
||||||
|
|||||||
@@ -40,6 +40,22 @@
|
|||||||
%let lib=%upcase(&lib);
|
%let lib=%upcase(&lib);
|
||||||
%let ds=%upcase(&ds);
|
%let ds=%upcase(&ds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cater for environments where sashelp.vcncolu is not available
|
||||||
|
*/
|
||||||
|
%if %sysfunc(exist(sashelp.vcncolu,view))=0 %then %do;
|
||||||
|
proc sql;
|
||||||
|
create table &outds(
|
||||||
|
libref char(8)
|
||||||
|
,TABLE_NAME char(32)
|
||||||
|
,constraint_type char(8) label='Constraint Type'
|
||||||
|
,constraint_name char(32) label='Constraint Name'
|
||||||
|
,column_name char(32) label='Column'
|
||||||
|
,constraint_order num
|
||||||
|
);
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Neither dictionary tables nor sashelp provides a constraint order column,
|
* Neither dictionary tables nor sashelp provides a constraint order column,
|
||||||
* however they DO arrive in the correct order. So, create the col.
|
* however they DO arrive in the correct order. So, create the col.
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ options
|
|||||||
validvarname=V7 /* avoid special characters etc in variable names */
|
validvarname=V7 /* avoid special characters etc in variable names */
|
||||||
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
|
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
|
||||||
varlenchk=%str(ERR)OR /* fail hard if truncation (data loss) can result */
|
varlenchk=%str(ERR)OR /* fail hard if truncation (data loss) can result */
|
||||||
%if %substr(&sysver,1,1) ne 4 %then %do;
|
%if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
|
||||||
noautocorrect /* disallow misspelled procedure names */
|
noautocorrect /* disallow misspelled procedure names */
|
||||||
dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
|
dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
@param [in] loop_secs= (1) Seconds to wait between each lock attempt
|
@param [in] loop_secs= (1) Seconds to wait between each lock attempt
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_fmtdttm.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mp_lockfilecheck.sas
|
@li mp_lockfilecheck.sas
|
||||||
@li mf_getuser.sas
|
@li mf_getuser.sas
|
||||||
@@ -111,7 +112,7 @@ run;
|
|||||||
LOCK_LIB ="&lib";
|
LOCK_LIB ="&lib";
|
||||||
LOCK_DS="&ds";
|
LOCK_DS="&ds";
|
||||||
LOCK_STATUS_CD='LOCKED';
|
LOCK_STATUS_CD='LOCKED';
|
||||||
LOCK_START_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt;
|
LOCK_START_DTTM="%sysfunc(datetime(),%mf_fmtdttm())"dt;
|
||||||
LOCK_USER_NM="&user";
|
LOCK_USER_NM="&user";
|
||||||
LOCK_PID="&sysjobid";
|
LOCK_PID="&sysjobid";
|
||||||
LOCK_REF="&ref";
|
LOCK_REF="&ref";
|
||||||
@@ -131,7 +132,7 @@ run;
|
|||||||
proc sql;
|
proc sql;
|
||||||
update &ctl_ds
|
update &ctl_ds
|
||||||
set LOCK_STATUS_CD='LOCKED'
|
set LOCK_STATUS_CD='LOCKED'
|
||||||
, LOCK_START_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt
|
, LOCK_START_DTTM="%sysfunc(datetime(),%mf_fmtdttm())"dt
|
||||||
, LOCK_USER_NM="&user"
|
, LOCK_USER_NM="&user"
|
||||||
, LOCK_PID="&sysjobid"
|
, LOCK_PID="&sysjobid"
|
||||||
, LOCK_REF="&ref"
|
, LOCK_REF="&ref"
|
||||||
@@ -206,7 +207,7 @@ run;
|
|||||||
proc sql;
|
proc sql;
|
||||||
update &ctl_ds
|
update &ctl_ds
|
||||||
set LOCK_STATUS_CD='UNLOCKED'
|
set LOCK_STATUS_CD='UNLOCKED'
|
||||||
, LOCK_END_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt
|
, LOCK_END_DTTM="%sysfunc(datetime(),%mf_fmtdttm())"dt
|
||||||
, LOCK_USER_NM="&user"
|
, LOCK_USER_NM="&user"
|
||||||
, LOCK_PID="&sysjobid"
|
, LOCK_PID="&sysjobid"
|
||||||
, LOCK_REF="&ref"
|
, LOCK_REF="&ref"
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_existvar.sas
|
@li mf_existvar.sas
|
||||||
|
@li mf_fmtdttm.sas
|
||||||
@li mf_getquotedstr.sas
|
@li mf_getquotedstr.sas
|
||||||
@li mf_getuniquename.sas
|
@li mf_getuniquename.sas
|
||||||
@li mf_nobs.sas
|
@li mf_nobs.sas
|
||||||
@@ -217,12 +218,12 @@ quit;
|
|||||||
set keytable="&base_libds"
|
set keytable="&base_libds"
|
||||||
,keycolumn="&retained_key"
|
,keycolumn="&retained_key"
|
||||||
,max_key=%eval(&maxkey+&newkey_cnt)
|
,max_key=%eval(&maxkey+&newkey_cnt)
|
||||||
,processed_dttm="%sysfunc(datetime(),E8601DT26.6)"dt;
|
,processed_dttm="%sysfunc(datetime(),%mf_fmtdttm())"dt;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
update &maxkeytable
|
update &maxkeytable
|
||||||
set max_key=%eval(&maxkey+&newkey_cnt)
|
set max_key=%eval(&maxkey+&newkey_cnt)
|
||||||
,processed_dttm="%sysfunc(datetime(),E8601DT26.6)"dt
|
,processed_dttm="%sysfunc(datetime(),%mf_fmtdttm())"dt
|
||||||
where keytable="&base_libds";
|
where keytable="&base_libds";
|
||||||
%end;
|
%end;
|
||||||
%mp_lockanytable(UNLOCK
|
%mp_lockanytable(UNLOCK
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Streams a file to _webout according to content type
|
@brief Streams a file to _webout according to content type
|
||||||
@details Will set headers using appropriate functions (SAS 9 vs Viya) and send
|
@details Will set headers using appropriate functions per the server type
|
||||||
content as a binary stream.
|
(Viya, EBI, [SASjs Server](https://github.com/sasjs/server)) and stream
|
||||||
|
content using mp_binarycopy().
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
@@ -12,7 +13,14 @@
|
|||||||
|
|
||||||
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
||||||
|
|
||||||
@param [in] contenttype= (TEXT) Either TEXT, ZIP, CSV, EXCEL
|
@param [in] contenttype= (TEXT) Supported:
|
||||||
|
@li CSV
|
||||||
|
@li EXCEL
|
||||||
|
@li MARKDOWN
|
||||||
|
@li TEXT
|
||||||
|
@li ZIP
|
||||||
|
Feel free to submit PRs to support more mime types! The official list is
|
||||||
|
here: https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||||
@param [in] inloc= /path/to/file.ext to be sent
|
@param [in] inloc= /path/to/file.ext to be sent
|
||||||
@param [in] inref= fileref of file to be sent (if provided, overrides `inloc`)
|
@param [in] inref= fileref of file to be sent (if provided, overrides `inloc`)
|
||||||
@param [in] iftrue= (1=1) Provide a condition under which to execute.
|
@param [in] iftrue= (1=1) Provide a condition under which to execute.
|
||||||
@@ -58,7 +66,7 @@ run;
|
|||||||
%if &contentype=CSV %then %do;
|
%if &contentype=CSV %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/csv');
|
rc=stpsrv_header('Content-Type','application/csv');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -68,7 +76,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/csv)
|
%mfs_httpheader(Content-Type,application/csv)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
@@ -76,7 +84,7 @@ run;
|
|||||||
/* suitable for XLS format */
|
/* suitable for XLS format */
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/vnd.ms-excel');
|
rc=stpsrv_header('Content-Type','application/vnd.ms-excel');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -86,14 +94,14 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/vnd.ms-excel)
|
%mfs_httpheader(Content-Type,application/vnd.ms-excel)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-Type',"image/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
@@ -101,30 +109,30 @@ run;
|
|||||||
contenttype="image/%lowcase(&contenttype)";
|
contenttype="image/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,image/%lowcase(&contenttype))
|
%mfs_httpheader(Content-Type,image/%lowcase(&contenttype))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=HTML %then %do;
|
%else %if &contentype=HTML or &contenttype=MARKDOWN %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','text/html');
|
rc=stpsrv_header('Content-Type',"text/%lowcase(&contenttype)");
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
||||||
contenttype="text/html"
|
contenttype="text/%lowcase(&contenttype)"
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,text/html)
|
%mfs_httpheader(Content-Type,text/%lowcase(&contenttype))
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=TEXT %then %do;
|
%else %if &contentype=TEXT %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/text');
|
rc=stpsrv_header('Content-Type','application/text');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -134,14 +142,14 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/text)
|
%mfs_httpheader(Content-Type,application/text)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-Type',"font/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
@@ -149,13 +157,13 @@ run;
|
|||||||
contenttype="font/%lowcase(&contenttype)";
|
contenttype="font/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,font/%lowcase(&contenttype))
|
%mfs_httpheader(Content-Type,font/%lowcase(&contenttype))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=XLSX %then %do;
|
%else %if &contentype=XLSX %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',
|
rc=stpsrv_header('Content-Type',
|
||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
@@ -167,7 +175,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type
|
%mfs_httpheader(Content-Type
|
||||||
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||||
)
|
)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
@@ -176,7 +184,7 @@ run;
|
|||||||
%else %if &contentype=ZIP %then %do;
|
%else %if &contentype=ZIP %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/zip');
|
rc=stpsrv_header('Content-Type','application/zip');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -186,7 +194,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/zip)
|
%mfs_httpheader(Content-Type,application/zip)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
@@ -287,9 +287,11 @@ filename &webref "&webrefpath";
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &mdebug=0 %then %do;
|
%if &mdebug=0 %then %do;
|
||||||
filename &webref clear;
|
|
||||||
filename &fref1 clear;
|
filename &fref1 clear;
|
||||||
filename &fref2 clear;
|
%if &platform ne SASJS %then %do;
|
||||||
|
filename &fref2 clear;
|
||||||
|
filename &webref clear;
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put &sysmacroname exit vars:;
|
%put &sysmacroname exit vars:;
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ proc sql;
|
|||||||
create table &libds(
|
create table &libds(
|
||||||
FMTNAME char(32) label='Format name'
|
FMTNAME char(32) label='Format name'
|
||||||
/*
|
/*
|
||||||
to accomodate larger START values, mp_loadformat.sas will need the
|
to accommodate larger START values, mp_loadformat.sas will need the
|
||||||
SQL dependency removed (proc sql needs to accomodate 3 index values in
|
SQL dependency removed (proc sql needs to accommodate 3 index values in
|
||||||
a 32767 ibufsize limit)
|
a 32767 ibufsize limit)
|
||||||
*/
|
*/
|
||||||
,START char(10000) label='Starting value for format'
|
,START char(10000) label='Starting value for format'
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sas9",
|
"name": "sas9",
|
||||||
"serverUrl": "https://sas.analytium.co.uk:8343",
|
"serverUrl": "",
|
||||||
"serverType": "SAS9",
|
"serverType": "SAS9",
|
||||||
"httpsAgentOptions": {
|
"httpsAgentOptions": {
|
||||||
"allowInsecureRequests": false
|
"allowInsecureRequests": false
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"serverUrl": "https://sas.analytium.co.uk:5007",
|
"serverUrl": "",
|
||||||
"serverType": "SASJS",
|
"serverType": "SASJS",
|
||||||
"httpsAgentOptions": {
|
"httpsAgentOptions": {
|
||||||
"allowInsecureRequests": false
|
"allowInsecureRequests": false
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "docsonly",
|
"name": "docsonly",
|
||||||
"serverType": "SAS9",
|
"serverType": "SASJS",
|
||||||
"appLoc": "dummy",
|
"appLoc": "dummy",
|
||||||
"macroFolders": [
|
"macroFolders": [
|
||||||
"meta",
|
"meta",
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ data _null_;
|
|||||||
file &fname1 lrecl=1000;
|
file &fname1 lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Content-Type: multipart/form-data; boundary=&boundary";
|
if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary";
|
||||||
put "Authorization: Bearer " _infile_;
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
|
|||||||
@@ -87,9 +87,11 @@ data _null_;
|
|||||||
file &fref1 lrecl=1000;
|
file &fref1 lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Authorization: Bearer " _infile_;
|
if _n_=1 then do;
|
||||||
put "Content-Type: application/json";
|
put "Content-Type: application/json";
|
||||||
put "accept: application/json";
|
put "accept: application/json";
|
||||||
|
end;
|
||||||
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
|
|||||||
@@ -390,6 +390,11 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
||||||
|
put ' %if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then %do; ';
|
||||||
|
put ' /* functions in formats unsupported */ ';
|
||||||
|
put ' %put &sysmacroname: forcing missing back to NULL as feature not supported; ';
|
||||||
|
put ' %let missing=NULL; ';
|
||||||
|
put ' %end; ';
|
||||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
||||||
put ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta ';
|
put ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta ';
|
||||||
put ' ) ';
|
put ' ) ';
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ data _null_;
|
|||||||
file &headref lrecl=1000;
|
file &headref lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Authorization: Bearer " _infile_;
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
proc http method='DELETE' headerin=&headref
|
proc http method='DELETE' headerin=&headref
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ data _null_;
|
|||||||
file &headref lrecl=1000;
|
file &headref lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Authorization: Bearer " _infile_;
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
proc http method='GET' out=&binaryfref headerin=&headref
|
proc http method='GET' out=&binaryfref headerin=&headref
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ data _null_;
|
|||||||
file &fref0 lrecl=1000;
|
file &fref0 lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put "Authorization: Bearer " _infile_;
|
if _n_=1 then put "accept: application/json";
|
||||||
put "accept: application/json";
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ data _null_;
|
|||||||
file &authref lrecl=1000;
|
file &authref lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put 'Authorization: Bearer ' _infile_;
|
if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary";
|
||||||
put "Content-Type: multipart/form-data; boundary=&boundary";
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
outref=0,
|
outref=0,
|
||||||
outlogds=_null_
|
outlogds=_null_
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local dbg fref1 chopout1 chopout2;
|
%local dbg i var ds1 fref1 chopout1 chopout2;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -82,13 +82,15 @@
|
|||||||
%let ds1=%mf_getuniquename();
|
%let ds1=%mf_getuniquename();
|
||||||
data &ds1;
|
data &ds1;
|
||||||
length fileref $8 name $32 filename $256 var $300;
|
length fileref $8 name $32 filename $256 var $300;
|
||||||
webcount=countw("&inputfiles");
|
if "&inputfiles" ne "0" then do;
|
||||||
do i=1 to webcount;
|
webcount=countw("&inputfiles");
|
||||||
var=scan("&inputfiles",i,' ');
|
do i=1 to webcount;
|
||||||
fileref=scan(var,1,':');
|
var=scan("&inputfiles",i,' ');
|
||||||
name=scan(var,2,':');
|
fileref=scan(var,1,':');
|
||||||
filename=cats(name,'.csv');
|
name=scan(var,2,':');
|
||||||
output;
|
filename=cats(name,'.csv');
|
||||||
|
output;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,11 @@
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%else %if &action=ARR or &action=OBJ %then %do;
|
%else %if &action=ARR or &action=OBJ %then %do;
|
||||||
|
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then %do;
|
||||||
|
/* functions in formats unsupported */
|
||||||
|
%put &sysmacroname: forcing missing back to NULL as feature not supported;
|
||||||
|
%let missing=NULL;
|
||||||
|
%end;
|
||||||
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
|
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref
|
||||||
,engine=DATASTEP,missing=&missing,showmeta=&showmeta
|
,engine=DATASTEP,missing=&missing,showmeta=&showmeta
|
||||||
)
|
)
|
||||||
|
|||||||
22
tests/crossplatform/mf_fmtdttm.test.sas
Normal file
22
tests/crossplatform/mf_fmtdttm.test.sas
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mf_fmtdttm macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_fmtdttm.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%global test1;
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%let test1=%mf_fmtdttm();
|
||||||
|
%mp_assertscope(COMPARE,ignorelist=test1)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test1"="DATETIME19.3" or "&test1"="E8601DT26.6"),
|
||||||
|
desc=Basic test,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
46
tests/crossplatform/mf_getvarcount.test.sas
Normal file
46
tests/crossplatform/mf_getvarcount.test.sas
Normal 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
|
||||||
|
)
|
||||||
|
|
||||||
@@ -6,24 +6,52 @@
|
|||||||
@li mf_nobs.sas
|
@li mf_nobs.sas
|
||||||
@li mp_getconstraints.sas
|
@li mp_getconstraints.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
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 unq unique(tx_from, dd_type),
|
|
||||||
constraint nnn not null(DD_SHORTDESC)
|
|
||||||
);
|
|
||||||
|
|
||||||
%mp_getconstraints(lib=work,ds=example,outds=work.constraints)
|
%macro conditional();
|
||||||
|
|
||||||
%mp_assert(
|
%if %sysfunc(exist(sashelp.vcncolu,view))=1 %then %do;
|
||||||
iftrue=(%mf_nobs(work.constraints)=6),
|
proc sql;
|
||||||
desc=Output table work.constraints created with correct number of records,
|
create table work.example(
|
||||||
outds=work.test_results
|
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 unq unique(tx_from, dd_type),
|
||||||
|
constraint nnn not null(DD_SHORTDESC)
|
||||||
|
);
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mp_getconstraints(lib=work,ds=example,outds=work.constraints)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mf_nobs(work.constraints)=6),
|
||||||
|
desc=Output table work.constraints created with correct number of records,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
proc sql;
|
||||||
|
create table work.example(
|
||||||
|
TX_FROM float format=datetime19.,
|
||||||
|
DD_TYPE char(16),
|
||||||
|
DD_SOURCE char(2048),
|
||||||
|
DD_SHORTDESC char(256)
|
||||||
|
);
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mp_getconstraints(lib=work,ds=example,outds=work.constraints)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mf_nobs(work.constraints)=0),
|
||||||
|
desc=Empty table created as constraints not supported,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%end;
|
||||||
|
%mend conditional;
|
||||||
|
|
||||||
|
%conditional()
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
Reference in New Issue
Block a user