mirror of
https://github.com/sasjs/core.git
synced 2026-01-08 01:50:05 +00:00
Compare commits
1 Commits
v4.23.0
...
allanbowe/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0a5d89016 |
@@ -117,15 +117,6 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"bug"
|
"bug"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"login": "yabwon",
|
|
||||||
"name": "Bart Jablonski",
|
|
||||||
"avatar_url": "https://avatars.githubusercontent.com/u/9314894?v=4",
|
|
||||||
"profile": "https://github.com/yabwon",
|
|
||||||
"contributions": [
|
|
||||||
"code"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
sasjs lint
|
||||||
# Ensure lint is passing
|
|
||||||
LINT=`sasjs lint`
|
|
||||||
if [[ "$LINT" != "✔ All matched files use @sasjs/lint code style!" ]]; then
|
|
||||||
echo "$LINT"
|
|
||||||
echo "To commit in spite of these warnings, use the -n parameter."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Avoid commits to the master branch
|
# Avoid commits to the master branch
|
||||||
BRANCH=`git rev-parse --abbrev-ref HEAD`
|
BRANCH=`git rev-parse --abbrev-ref HEAD`
|
||||||
|
|||||||
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
@@ -1,3 +0,0 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: [sasjs]
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
tasks:
|
tasks:
|
||||||
- init: npm install -g npm
|
- init: |
|
||||||
- command: npm i
|
nvm install --lts
|
||||||
- command: npm i -g @sasjs/cli
|
npm i -g @sasjs/cli
|
||||||
|
|
||||||
image:
|
image:
|
||||||
file: .gitpod.dockerfile
|
file: .gitpod.dockerfile
|
||||||
@@ -24,4 +24,4 @@ github:
|
|||||||
# add a "Review in Gitpod" button to pull requests (defaults to false)
|
# add a "Review in Gitpod" button to pull requests (defaults to false)
|
||||||
addBadge: false
|
addBadge: false
|
||||||
# add a label once the prebuild is ready to pull requests (defaults to false)
|
# add a label once the prebuild is ready to pull requests (defaults to false)
|
||||||
addLabel: prebuilt-in-gitpod
|
addLabel: prebuilt-in-gitpod
|
||||||
14
README.md
14
README.md
@@ -47,7 +47,7 @@ Documentation: https://core.sasjs.io
|
|||||||
|
|
||||||
This library will not be used for storing data entries (such as formats or datalines). Where this becomes necessary in the future, a new repo will be created, in order to keep the NPM bundle size down (for the benefit of those looking to embed purely macros in their applications).
|
This library will not be used for storing data entries (such as formats or datalines). Where this becomes necessary in the future, a new repo will be created, in order to keep the NPM bundle size down (for the benefit of those looking to embed purely macros in their applications).
|
||||||
|
|
||||||
### FCMP library (All Platforms)
|
#### FCMP library (All Platforms)
|
||||||
|
|
||||||
- Function and macro names are identical, except for special cases
|
- Function and macro names are identical, except for special cases
|
||||||
- Prefixes: _mcf_
|
- Prefixes: _mcf_
|
||||||
@@ -204,7 +204,6 @@ When contributing to this library, it is therefore important to ensure that all
|
|||||||
|
|
||||||
We are currently on major release v4. Breaking changes should be marked with the [deprecated](https://www.doxygen.nl/manual/commands.html#cmddeprecated) doxygen tag. The following changes are planned when the next major/breaking release (v5) becomes necessary:
|
We are currently on major release v4. Breaking changes should be marked with the [deprecated](https://www.doxygen.nl/manual/commands.html#cmddeprecated) doxygen tag. The following changes are planned when the next major/breaking release (v5) becomes necessary:
|
||||||
|
|
||||||
* mf_getuniquelibref.sas to have the deprecated maxtried parameter removed (no longer needed)
|
|
||||||
* mp_testservice.sas to be renamed as mp_execute.sas (as it doesn't actually test anything)
|
* mp_testservice.sas to be renamed as mp_execute.sas (as it doesn't actually test anything)
|
||||||
* `insert_cmplib` option of mcf_xxx macros will be deprecated (the option is now checked automatically with value inserted only if needed)
|
* `insert_cmplib` option of mcf_xxx macros will be deprecated (the option is now checked automatically with value inserted only if needed)
|
||||||
* mcf_xxx macros to have `wrap=` option defaulted to YES for convenience. Set this option explicitly to avoid issues.
|
* mcf_xxx macros to have `wrap=` option defaulted to YES for convenience. Set this option explicitly to avoid issues.
|
||||||
@@ -217,19 +216,11 @@ If you find this library useful, please leave a [star](https://github.com/sasjs/
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Other SAS Repositories
|
|
||||||
|
|
||||||
The following repositories are also worth checking out:
|
|
||||||
|
|
||||||
* [chris-swenson/sasmacros](https://github.com/chris-swenson/sasmacros)
|
|
||||||
* [greg-wotton/sas-programs](https://github.com/greg-wootton/sas-programs)
|
|
||||||
* [KatjaGlassConsulting/SMILE-SmartSASMacros](https://github.com/KatjaGlassConsulting/SMILE-SmartSASMacros)
|
|
||||||
* [scottbass/sas](https://github.com/scottbass/SAS)
|
|
||||||
* [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)):
|
||||||
|
|
||||||
@@ -250,7 +241,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<td align="center"><a href="https://github.com/kkchandok"><img src="https://avatars.githubusercontent.com/u/46090627?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kkchandok</b></sub></a><br /><a href="#ideas-kkchandok" title="Ideas, Planning, & Feedback">🤔</a></td>
|
<td align="center"><a href="https://github.com/kkchandok"><img src="https://avatars.githubusercontent.com/u/46090627?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kkchandok</b></sub></a><br /><a href="#ideas-kkchandok" title="Ideas, Planning, & Feedback">🤔</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/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>
|
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Deletes a physical file, if it exists
|
|
||||||
@details Usage:
|
|
||||||
|
|
||||||
%mf_writefile(&sasjswork/myfile.txt,l1=some content)
|
|
||||||
|
|
||||||
%mf_deletefile(&sasjswork/myfile.txt)
|
|
||||||
|
|
||||||
%mf_deletefile(&sasjswork/myfile.txt)
|
|
||||||
|
|
||||||
|
|
||||||
@param filepath Full path to the target file
|
|
||||||
|
|
||||||
@returns The return code from the fdelete() invocation
|
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
|
||||||
@li mf_deletefile.test.sas
|
|
||||||
@li mf_writefile.sas
|
|
||||||
|
|
||||||
@version 9.2
|
|
||||||
@author Allan Bowe
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mf_deletefile(file
|
|
||||||
)/*/STORE SOURCE*/;
|
|
||||||
%local rc fref;
|
|
||||||
%let rc= %sysfunc(filename(fref,&file));
|
|
||||||
%if %sysfunc(fdelete(&fref)) ne 0 %then %put %sysfunc(sysmsg());
|
|
||||||
%let rc= %sysfunc(filename(fref));
|
|
||||||
%mend mf_deletefile;
|
|
||||||
@@ -9,17 +9,19 @@
|
|||||||
|
|
||||||
%put %mf_existfeature(PROCLUA);
|
%put %mf_existfeature(PROCLUA);
|
||||||
|
|
||||||
@param [in] feature The feature to detect.
|
@param feature the feature to detect. Leave blank to list all in log.
|
||||||
|
|
||||||
@return output returns 1 or 0 (or -1 if not found)
|
@return output returns 1 or 0 (or -1 if not found)
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
|
|
||||||
|
|
||||||
@version 8
|
@version 8
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
**/
|
**/
|
||||||
/** @cond */
|
/** @cond */
|
||||||
|
|
||||||
%macro mf_existfeature(feature
|
%macro mf_existfeature(feature
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%let feature=%upcase(&feature);
|
%let feature=%upcase(&feature);
|
||||||
@@ -27,11 +29,7 @@
|
|||||||
%let platform=%mf_getplatform();
|
%let platform=%mf_getplatform();
|
||||||
|
|
||||||
%if &feature= %then %do;
|
%if &feature= %then %do;
|
||||||
%put No feature was requested for detection;
|
%put Supported features: PROCLUA;
|
||||||
%end;
|
|
||||||
%else %if &feature=COLCONSTRAINTS %then %do;
|
|
||||||
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 0;
|
|
||||||
%else 1;
|
|
||||||
%end;
|
%end;
|
||||||
%else %if &feature=PROCLUA %then %do;
|
%else %if &feature=PROCLUA %then %do;
|
||||||
/* https://blogs.sas.com/content/sasdummy/2015/08/03/using-lua-within-your-sas-programs */
|
/* https://blogs.sas.com/content/sasdummy/2015/08/03/using-lua-within-your-sas-programs */
|
||||||
@@ -45,4 +43,5 @@
|
|||||||
%put &sysmacroname: &feature not found;
|
%put &sysmacroname: &feature not found;
|
||||||
%end;
|
%end;
|
||||||
%mend mf_existfeature;
|
%mend mf_existfeature;
|
||||||
/** @endcond */
|
|
||||||
|
/** @endcond */
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/**
|
|
||||||
@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;
|
|
||||||
|
|
||||||
|
|
||||||
@@ -28,17 +28,15 @@
|
|||||||
be 8 characters, so a 7 letter prefix would mean `maxtries` should be 10.
|
be 8 characters, so a 7 letter prefix would mean `maxtries` should be 10.
|
||||||
if using zero (0) as the prefix, a native assignment is used.
|
if using zero (0) as the prefix, a native assignment is used.
|
||||||
@param [in] maxtries= (1000) the last part of the libref. Must be an integer.
|
@param [in] maxtries= (1000) the last part of the libref. Must be an integer.
|
||||||
@param [in] lrecl= (32767) Provide a default lrecl with which to initialise
|
|
||||||
the generated fileref.
|
|
||||||
|
|
||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_getuniquefileref(prefix=_,maxtries=1000,lrecl=32767);
|
%macro mf_getuniquefileref(prefix=_,maxtries=1000);
|
||||||
%local rc fname;
|
%local rc fname;
|
||||||
%if &prefix=0 %then %do;
|
%if &prefix=0 %then %do;
|
||||||
%let rc=%sysfunc(filename(fname,,temp,lrecl=&lrecl));
|
%let rc=%sysfunc(filename(fname,,temp));
|
||||||
%if &rc %then %put %sysfunc(sysmsg());
|
%if &rc %then %put %sysfunc(sysmsg());
|
||||||
&fname
|
&fname
|
||||||
%end;
|
%end;
|
||||||
@@ -49,7 +47,7 @@
|
|||||||
%do x=0 %to &maxtries;
|
%do x=0 %to &maxtries;
|
||||||
%let fname=&prefix%substr(%sysfunc(ranuni(0)),3,&len);
|
%let fname=&prefix%substr(%sysfunc(ranuni(0)),3,&len);
|
||||||
%if %sysfunc(fileref(&fname)) > 0 %then %do;
|
%if %sysfunc(fileref(&fname)) > 0 %then %do;
|
||||||
%let rc=%sysfunc(filename(fname,,temp,lrecl=&lrecl));
|
%let rc=%sysfunc(filename(fname,,temp));
|
||||||
%if &rc %then %put %sysfunc(sysmsg());
|
%if &rc %then %put %sysfunc(sysmsg());
|
||||||
&fname
|
&fname
|
||||||
%return;
|
%return;
|
||||||
|
|||||||
@@ -3,55 +3,38 @@
|
|||||||
@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:
|
||||||
|
|
||||||
> mclib3
|
> mclib3
|
||||||
|
|
||||||
A blank value is returned if no usable libname is determined.
|
@param prefix= first part of libref. Remember that librefs can only be 8 characters,
|
||||||
|
so a 7 letter prefix would mean that maxtries should be 10.
|
||||||
@param [in] prefix= (mclib) first part of the returned libref. As librefs can
|
@param maxtries= the last part of the libref. Provide an integer value.
|
||||||
be as long as 8 characters, a maximum length of 7 characters is premitted
|
|
||||||
for this prefix.
|
|
||||||
@param [in] maxtries= Deprecated parameter. Remains here to ensure a
|
|
||||||
non-breaking change. Will be removed in v5.
|
|
||||||
|
|
||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
%macro mf_getuniquelibref(prefix=mclib,maxtries=1000);
|
%macro mf_getuniquelibref(prefix=mclib,maxtries=1000);
|
||||||
%local x;
|
%local x libref;
|
||||||
|
%let x=0;
|
||||||
%if ( %length(&prefix) gt 7 ) %then %do;
|
%do x=0 %to &maxtries;
|
||||||
%put %str(ERR)OR: The prefix parameter cannot exceed 7 characters.;
|
%if %sysfunc(libref(&prefix&x)) ne 0 %then %do;
|
||||||
0
|
%let libref=&prefix&x;
|
||||||
|
%let rc=%sysfunc(libname(&libref,%sysfunc(pathname(work))));
|
||||||
|
%if &rc %then %put %sysfunc(sysmsg());
|
||||||
|
&prefix&x
|
||||||
|
%*put &sysmacroname: Libref &libref assigned as WORK and returned;
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
%else %if (%sysfunc(NVALID(&prefix,v7))=0) %then %do;
|
|
||||||
%put %str(ERR)OR: Invalid prefix (&prefix);
|
|
||||||
0
|
|
||||||
%return;
|
|
||||||
%end;
|
%end;
|
||||||
|
%put unable to find available libref in range &prefix.0-&maxtries;
|
||||||
/* Set maxtries equal to '10 to the power of [# unused characters] - 1' */
|
|
||||||
%let maxtries=%eval(10**(8-%length(&prefix))-1);
|
|
||||||
|
|
||||||
%do x = 0 %to &maxtries;
|
|
||||||
%if %sysfunc(libref(&prefix&x)) ne 0 %then %do;
|
|
||||||
&prefix&x
|
|
||||||
%return;
|
|
||||||
%end;
|
|
||||||
%let x = %eval(&x + 1);
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%put %str(ERR)OR: No usable libref in range &prefix.0-&maxtries;
|
|
||||||
%put %str(ERR)OR- Try reducing the prefix or deleting some libraries!;
|
|
||||||
0
|
|
||||||
%mend mf_getuniquelibref;
|
%mend mf_getuniquelibref;
|
||||||
@@ -33,8 +33,7 @@
|
|||||||
%else %if %symexist(&metavar) %then %do;
|
%else %if %symexist(&metavar) %then %do;
|
||||||
%if %length(&&&metavar)=0 %then %let user=&sysuserid;
|
%if %length(&&&metavar)=0 %then %let user=&sysuserid;
|
||||||
/* sometimes SAS will add @domain extension - remove for consistency */
|
/* sometimes SAS will add @domain extension - remove for consistency */
|
||||||
/* but be sure to quote in case of usernames with commas */
|
%else %let user=%scan(&&&metavar,1,@);
|
||||||
%else %let user=%unquote(%scan(%quote(&&&metavar),1,@));
|
|
||||||
%end;
|
%end;
|
||||||
%else %let user=&sysuserid;
|
%else %let user=&sysuserid;
|
||||||
|
|
||||||
|
|||||||
@@ -2,48 +2,31 @@
|
|||||||
@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,typefilter=A
|
%macro mf_getvarcount(libds
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local dsid nvars rc outcnt x;
|
%local dsid nvars rc ;
|
||||||
%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;
|
||||||
&outcnt
|
&nvars
|
||||||
%mend mf_getvarcount;
|
%mend mf_getvarcount;
|
||||||
@@ -20,11 +20,8 @@
|
|||||||
|
|
||||||
%macro mf_isint(arg
|
%macro mf_isint(arg
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
/* blank val is not an integer */
|
|
||||||
%if "&arg"="" %then %do;0%return;%end;
|
|
||||||
|
|
||||||
/* remove minus sign if exists */
|
/* remove minus sign if exists */
|
||||||
|
|
||||||
%local val;
|
%local val;
|
||||||
%if "%substr(%str(&arg),1,1)"="-" %then %let val=%substr(%str(&arg),2);
|
%if "%substr(%str(&arg),1,1)"="-" %then %let val=%substr(%str(&arg),2);
|
||||||
%else %let val=&arg;
|
%else %let val=&arg;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
%goto exit_success;
|
%goto exit_success;
|
||||||
%exit_err:
|
%exit_err:
|
||||||
%put &abortmsg;
|
%put %str(ERR)OR: &abortmsg;
|
||||||
%mf_abort(iftrue=(&mabort ne SOFT),
|
%mf_abort(iftrue=(&mabort ne SOFT),
|
||||||
mac=mf_verifymacvars,
|
mac=mf_verifymacvars,
|
||||||
msg=%str(&abortmsg)
|
msg=%str(&abortmsg)
|
||||||
|
|||||||
@@ -85,16 +85,11 @@
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
/* Stored Process Server web app context */
|
/* Stored Process Server web app context */
|
||||||
%if %symexist(_METAFOLDER)
|
%if %symexist(_metaperson)
|
||||||
or "&SYSPROCESSNAME "="Compute Server "
|
or "&SYSPROCESSNAME "="Compute Server "
|
||||||
or &mode=INCLUDE
|
or &mode=INCLUDE
|
||||||
%then %do;
|
%then %do;
|
||||||
options obs=max replace mprint;
|
options obs=max replace nosyntaxcheck 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_;
|
||||||
@@ -166,14 +161,12 @@
|
|||||||
/* 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 syswarningtext syserrortext $32767 ;
|
length msg $32767 ;
|
||||||
sasdatetime=datetime();
|
sasdatetime=datetime();
|
||||||
msg=symget('msg');
|
msg=symget('msg');
|
||||||
%if &logline>0 %then %do;
|
%if &logline>0 %then %do;
|
||||||
msg=cats(msg,'\n\nLog Extract:\n',symget('logmsg'));
|
msg=cats(msg,'\n\nLog Extract:\n',symget('logmsg'));
|
||||||
%end;
|
%end;
|
||||||
/* escape the escapes */
|
|
||||||
msg=tranwrd(msg,'\','\\');
|
|
||||||
/* escape the quotes */
|
/* escape the quotes */
|
||||||
msg=tranwrd(msg,'"','\"');
|
msg=tranwrd(msg,'"','\"');
|
||||||
/* ditch the CRLFs as chrome complains */
|
/* ditch the CRLFs as chrome complains */
|
||||||
@@ -267,4 +260,4 @@
|
|||||||
%end;
|
%end;
|
||||||
%mend mp_abort;
|
%mend mp_abort;
|
||||||
|
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
@@ -74,8 +74,7 @@
|
|||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local ds test_result test_comments del add mod ilist;
|
%local ds test_result test_comments del add mod ilist;
|
||||||
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS SYS_PROCHTTP_STATUS_CODE
|
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS &ignorelist);
|
||||||
SYS_PROCHTTP_STATUS_CODE SYS_PROCHTTP_STATUS_PHRASE &ignorelist);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this sets up the global vars, it will also enter STRICT mode. If this
|
* this sets up the global vars, it will also enter STRICT mode. If this
|
||||||
@@ -90,7 +89,7 @@
|
|||||||
create table &scopeds as
|
create table &scopeds as
|
||||||
select name,offset,value
|
select name,offset,value
|
||||||
from dictionary.macros
|
from dictionary.macros
|
||||||
where scope="&scope" and upcase(name) not in (%mf_getquotedstr(&ilist))
|
where scope="&scope" and name not in (%mf_getquotedstr(&ilist))
|
||||||
order by name,offset;
|
order by name,offset;
|
||||||
%end;
|
%end;
|
||||||
%else %if &action=COMPARE %then %do;
|
%else %if &action=COMPARE %then %do;
|
||||||
@@ -104,9 +103,7 @@
|
|||||||
|
|
||||||
%let ds=&syslast;
|
%let ds=&syslast;
|
||||||
|
|
||||||
proc compare
|
proc compare base=&scopeds compare=&ds;
|
||||||
base=&scopeds(where=(upcase(name) not in (%mf_getquotedstr(&ilist))))
|
|
||||||
compare=&ds noprint;
|
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &sysinfo=0 %then %do;
|
%if &sysinfo=0 %then %do;
|
||||||
@@ -144,4 +141,4 @@
|
|||||||
drop table &ds;
|
drop table &ds;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mp_assertscope;
|
%mend mp_assertscope;
|
||||||
194
base/mp_chop.sas
194
base/mp_chop.sas
@@ -1,194 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Splits a file of ANY SIZE by reference to a search string.
|
|
||||||
@details Provide a fileref and a search string to chop off part of a file.
|
|
||||||
|
|
||||||
Works by reading in the file byte by byte, then marking the beginning and end
|
|
||||||
of each matched string, before finally doing the chop.
|
|
||||||
|
|
||||||
Choose whether to keep the FIRST or the LAST section of the file. Optionally,
|
|
||||||
use an OFFSET to fix the precise chop point.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
%let src="%sysfunc(pathname(work))/file.txt";
|
|
||||||
%let str=Chop here!;
|
|
||||||
%let out1="%sysfunc(pathname(work))/file1.txt";
|
|
||||||
%let out2="%sysfunc(pathname(work))/file2.txt";
|
|
||||||
%let out3="%sysfunc(pathname(work))/file3.txt";
|
|
||||||
%let out4="%sysfunc(pathname(work))/file4.txt";
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &src;
|
|
||||||
put "startsection&str.endsection";
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_chop(&src, matchvar=str, keep=FIRST, outfile=&out1)
|
|
||||||
%mp_chop(&src, matchvar=str, keep=LAST, outfile=&out2)
|
|
||||||
%mp_chop(&src, matchvar=str, keep=FIRST, matchpoint=END, outfile=&out3)
|
|
||||||
%mp_chop(&src, matchvar=str, keep=LAST, matchpoint=END, outfile=&out4)
|
|
||||||
|
|
||||||
filename results (&out1 &out2 &out3 &out4);
|
|
||||||
data _null_;
|
|
||||||
infile results;
|
|
||||||
input;
|
|
||||||
list;
|
|
||||||
run;
|
|
||||||
|
|
||||||
Results:
|
|
||||||
@li `startsection`
|
|
||||||
@li `Chop here!endsection`
|
|
||||||
@li `startsectionChop here!`
|
|
||||||
@li `endsection`
|
|
||||||
|
|
||||||
For more examples, see mp_chop.test.sas
|
|
||||||
|
|
||||||
@param [in] infile The QUOTED path to the file on which to perform the chop
|
|
||||||
@param [in] matchvar= Macro variable NAME containing the string to split by
|
|
||||||
@param [in] matchpoint= (START) Valid values:
|
|
||||||
@li START - chop at the beginning of the string in `matchvar`.
|
|
||||||
@li END - chop at the end of the string in `matchvar`.
|
|
||||||
@param [in] offset= (0) An adjustment to the precise chop location, by
|
|
||||||
by reference to the `matchpoint`. Should be a positive or negative integer.
|
|
||||||
@param [in] keep= (FIRST) Valid values:
|
|
||||||
@li FIRST - keep the section of the file before the chop
|
|
||||||
@li LAST - keep the section of the file after the chop
|
|
||||||
@param [in] mdebug= (0) Set to 1 to provide macro debugging
|
|
||||||
@param outfile= (0) Optional QUOTED path to the adjusted output file (avoids
|
|
||||||
overwriting the first file).
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
|
||||||
@li mp_abort.sas
|
|
||||||
@li mp_gsubfile.sas
|
|
||||||
@li mp_replace.sas
|
|
||||||
@li mp_chop.test.sas
|
|
||||||
|
|
||||||
@version 9.4
|
|
||||||
@author Allan Bowe
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mp_chop(infile,
|
|
||||||
matchvar=,
|
|
||||||
matchpoint=START,
|
|
||||||
keep=FIRST,
|
|
||||||
offset=0,
|
|
||||||
mdebug=0,
|
|
||||||
outfile=0
|
|
||||||
)/*/STORE SOURCE*/;
|
|
||||||
|
|
||||||
%local fref0 dttm ds1 outref;
|
|
||||||
%let fref0=%mf_getuniquefileref();
|
|
||||||
%let ds1=%mf_getuniquename(prefix=allchars);
|
|
||||||
%let ds2=%mf_getuniquename(prefix=startmark);
|
|
||||||
|
|
||||||
%if &outfile=0 %then %let outfile=&infile;
|
|
||||||
|
|
||||||
%mp_abort(iftrue= (%length(%superq(&matchvar))=0)
|
|
||||||
,mac=mp_chop.sas
|
|
||||||
,msg=%str(&matchvar is an empty variable)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* START */
|
|
||||||
%let dttm=%sysfunc(datetime());
|
|
||||||
|
|
||||||
filename &fref0 &infile lrecl=1 recfm=n;
|
|
||||||
|
|
||||||
/* create dataset with one char per row */
|
|
||||||
data &ds1;
|
|
||||||
infile &fref0;
|
|
||||||
input sourcechar $char1. @@;
|
|
||||||
format sourcechar hex2.;
|
|
||||||
run;
|
|
||||||
|
|
||||||
/* get start & stop position of first matchvar string (one row, two vars) */
|
|
||||||
data &ds2;
|
|
||||||
/* set find string to length in bytes to cover trailing spaces */
|
|
||||||
length string $ %length(%superq(&matchvar));
|
|
||||||
string =symget("&matchvar");
|
|
||||||
drop string;
|
|
||||||
|
|
||||||
firstchar=char(string,1);
|
|
||||||
findlen=lengthm(string); /* <- for trailing bytes */
|
|
||||||
|
|
||||||
do _N_=1 to nobs;
|
|
||||||
set &ds1 nobs=nobs point=_N_;
|
|
||||||
if sourcechar=firstchar then do;
|
|
||||||
pos=1;
|
|
||||||
s=0;
|
|
||||||
do point=_N_ to min(_N_ + findlen -1,nobs);
|
|
||||||
set &ds1 point=point;
|
|
||||||
if sourcechar=char(string, pos) then s + 1;
|
|
||||||
else goto _leave_;
|
|
||||||
pos+1;
|
|
||||||
end;
|
|
||||||
_leave_:
|
|
||||||
if s=findlen then do;
|
|
||||||
START =_N_;
|
|
||||||
_N_ =_N_+ s - 1;
|
|
||||||
STOP =_N_;
|
|
||||||
output;
|
|
||||||
/* matched! */
|
|
||||||
stop;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
stop;
|
|
||||||
keep START STOP;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%local split;
|
|
||||||
%let split=0;
|
|
||||||
data _null_;
|
|
||||||
set &ds2;
|
|
||||||
if "&matchpoint"='START' then do;
|
|
||||||
if "&keep"='FIRST' then mp=start;
|
|
||||||
else if "&keep"='LAST' then mp=start-1;
|
|
||||||
end;
|
|
||||||
else if "&matchpoint"='END' then do;
|
|
||||||
if "&keep"='FIRST' then mp=stop+1;
|
|
||||||
else if "&keep"='LAST' then mp=stop;
|
|
||||||
end;
|
|
||||||
split=mp+&offset;
|
|
||||||
call symputx('split',split,'l');
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
put (_all_)(=);
|
|
||||||
%put &=offset;
|
|
||||||
%end;
|
|
||||||
run;
|
|
||||||
%if &split=0 %then %do;
|
|
||||||
%put &sysmacroname: No match found in &infile for string %superq(&matchvar);
|
|
||||||
%return;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &outfile recfm=n;
|
|
||||||
set &ds1;
|
|
||||||
%if &keep=FIRST %then %do;
|
|
||||||
if _n_ ge &split then stop;
|
|
||||||
%end;
|
|
||||||
%else %do;
|
|
||||||
if _n_ gt &split;
|
|
||||||
%end;
|
|
||||||
put sourcechar char1.;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%if &mdebug=0 %then %do;
|
|
||||||
filename &fref0 clear;
|
|
||||||
%end;
|
|
||||||
%else %do;
|
|
||||||
data _null_;
|
|
||||||
infile &outfile lrecl=32767;
|
|
||||||
input;
|
|
||||||
list;
|
|
||||||
if _n_>50 then stop;
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
/* END */
|
|
||||||
%put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) seconds to run;
|
|
||||||
|
|
||||||
%mend mp_chop;
|
|
||||||
@@ -29,7 +29,6 @@ Usage:
|
|||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mm_createwebservice.sas
|
@li mm_createwebservice.sas
|
||||||
@li ms_createwebservice.sas
|
|
||||||
@li mv_createwebservice.sas
|
@li mv_createwebservice.sas
|
||||||
|
|
||||||
@param [in,out] path= The full folder path where the service will be created
|
@param [in,out] path= The full folder path where the service will be created
|
||||||
@@ -41,7 +40,7 @@ Usage:
|
|||||||
be added
|
be added
|
||||||
@param [in] replace= (YES) Select YES to replace any existing service in that
|
@param [in] replace= (YES) Select YES to replace any existing service in that
|
||||||
location
|
location
|
||||||
@param [in] mDebug= (0) set to 1 to show debug messages in the log
|
|
||||||
|
|
||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@@ -54,7 +53,6 @@ Usage:
|
|||||||
,code=ft15f001
|
,code=ft15f001
|
||||||
,desc=This service was created by the mp_createwebservice macro
|
,desc=This service was created by the mp_createwebservice macro
|
||||||
,replace=YES
|
,replace=YES
|
||||||
,mdebug=0
|
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%if &syscc ge 4 %then %do;
|
%if &syscc ge 4 %then %do;
|
||||||
@@ -73,17 +71,8 @@ Usage:
|
|||||||
,replace=&replace
|
,replace=&replace
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
|
||||||
%if "&path"="HOME" %then %let path=/Users/&_sasjs_username/My Folder;
|
|
||||||
%ms_createwebservice(path=&path
|
|
||||||
,name=&name
|
|
||||||
,code=&code
|
|
||||||
,precode=&precode
|
|
||||||
,mdebug=&mdebug
|
|
||||||
)
|
|
||||||
%end;
|
|
||||||
%else %do;
|
%else %do;
|
||||||
%if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder;
|
%if "&path"="HOME" %then %let path=/User Folders/&sysuserid/My Folder;
|
||||||
%mm_createwebservice(path=&path
|
%mm_createwebservice(path=&path
|
||||||
,name=&name
|
,name=&name
|
||||||
,code=&code
|
,code=&code
|
||||||
|
|||||||
@@ -94,13 +94,6 @@ data &out_ds(compress=no
|
|||||||
%end;
|
%end;
|
||||||
if rc = 0 then do;
|
if rc = 0 then do;
|
||||||
did = dopen(fref);
|
did = dopen(fref);
|
||||||
if did=0 then do;
|
|
||||||
putlog "NOTE: This directory is empty, or does not exist - &path";
|
|
||||||
msg=sysmsg();
|
|
||||||
put msg;
|
|
||||||
put _all_;
|
|
||||||
stop;
|
|
||||||
end;
|
|
||||||
/* attribute is OS-dependent - could be "Directory" or "Directory Name" */
|
/* attribute is OS-dependent - could be "Directory" or "Directory Name" */
|
||||||
numopts=doptnum(did);
|
numopts=doptnum(did);
|
||||||
do i=1 to numopts;
|
do i=1 to numopts;
|
||||||
@@ -108,6 +101,12 @@ data &out_ds(compress=no
|
|||||||
if foption=:'Directory' then i=numopts;
|
if foption=:'Directory' then i=numopts;
|
||||||
end;
|
end;
|
||||||
directory=dinfo(did,foption);
|
directory=dinfo(did,foption);
|
||||||
|
if did=0 then do;
|
||||||
|
putlog "NOTE: This directory is empty - " directory;
|
||||||
|
msg=sysmsg();
|
||||||
|
put _all_;
|
||||||
|
stop;
|
||||||
|
end;
|
||||||
rc = filename(fref);
|
rc = filename(fref);
|
||||||
end;
|
end;
|
||||||
else do;
|
else do;
|
||||||
@@ -152,7 +151,6 @@ run;
|
|||||||
data &out_ds;
|
data &out_ds;
|
||||||
set &out_ds;
|
set &out_ds;
|
||||||
length infoname infoval $60 fref $8;
|
length infoname infoval $60 fref $8;
|
||||||
if _n_=1 then call missing(fref);
|
|
||||||
rc=filename(fref,filepath);
|
rc=filename(fref,filepath);
|
||||||
drop rc infoname fid i close fref;
|
drop rc infoname fid i close fref;
|
||||||
if file_or_folder='file' then do;
|
if file_or_folder='file' then do;
|
||||||
@@ -244,4 +242,4 @@ run;
|
|||||||
proc sql;
|
proc sql;
|
||||||
drop table &out_ds;
|
drop table &out_ds;
|
||||||
|
|
||||||
%mend mp_dirlist;
|
%mend mp_dirlist;
|
||||||
@@ -48,7 +48,6 @@
|
|||||||
|
|
||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@cond
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mp_ds2cards(base_ds=, tgt_ds=
|
%macro mp_ds2cards(base_ds=, tgt_ds=
|
||||||
@@ -220,8 +219,7 @@ data _null_;
|
|||||||
put ' @file';
|
put ' @file';
|
||||||
put " @brief Datalines for %upcase(%scan(&base_ds,2)) dataset";
|
put " @brief Datalines for %upcase(%scan(&base_ds,2)) dataset";
|
||||||
put " @details Generated by %nrstr(%%)mp_ds2cards()";
|
put " @details Generated by %nrstr(%%)mp_ds2cards()";
|
||||||
put " Source: https://github.com/sasjs/core";
|
put " Available on github.com/sasjs/core";
|
||||||
put ' @cond ';
|
|
||||||
put '**/';
|
put '**/';
|
||||||
put "data &tgt_ds &indexes;";
|
put "data &tgt_ds &indexes;";
|
||||||
put "attrib ";
|
put "attrib ";
|
||||||
@@ -266,7 +264,6 @@ data _null_;
|
|||||||
if __lastobs then do;
|
if __lastobs then do;
|
||||||
put ';;;;';
|
put ';;;;';
|
||||||
put 'run;';
|
put 'run;';
|
||||||
put '/** @endcond **/';
|
|
||||||
stop;
|
stop;
|
||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
@@ -286,5 +283,4 @@ quit;
|
|||||||
%put NOTE-;%put NOTE-;
|
%put NOTE-;%put NOTE-;
|
||||||
%put NOTE- %sysfunc(dequote(&cards_file.));
|
%put NOTE- %sysfunc(dequote(&cards_file.));
|
||||||
%put NOTE-;%put NOTE-;
|
%put NOTE-;%put NOTE-;
|
||||||
%mend mp_ds2cards;
|
%mend mp_ds2cards;
|
||||||
/** @endcond **/
|
|
||||||
@@ -41,7 +41,6 @@
|
|||||||
<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
|
||||||
@@ -61,7 +60,7 @@
|
|||||||
,outds=work.mp_getmaxvarlengths
|
,outds=work.mp_getmaxvarlengths
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%local vars prefix x var fmt srcds;
|
%local vars prefix x var fmt;
|
||||||
%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);
|
||||||
@@ -71,24 +70,6 @@
|
|||||||
%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( )));
|
||||||
@@ -113,15 +94,10 @@ create table &outds (rename=(
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then %do;
|
max(mcf_length(&var)) as &prefix.&x
|
||||||
max(&prefix.&x) as &prefix.&x
|
|
||||||
%end;
|
|
||||||
%else %do;
|
|
||||||
max(mcf_length(&var)) as &prefix.&x
|
|
||||||
%end;
|
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
from &srcds;
|
from &libds;
|
||||||
|
|
||||||
proc transpose data=&outds
|
proc transpose data=&outds
|
||||||
out=&outds(rename=(_name_=NAME COL1=MAXLEN));
|
out=&outds(rename=(_name_=NAME COL1=MAXLEN));
|
||||||
|
|||||||
@@ -55,8 +55,7 @@
|
|||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
|
||||||
%local engine schema ds1 ds2 ds3 dsn tabs1 tabs2 sum pk4sure pkdefault finalpks
|
%local engine schema ds1 ds2 ds3 dsn tabs1 tabs2 sum pk4sure pkdefault finalpks;
|
||||||
pkfromindex;
|
|
||||||
|
|
||||||
%let lib=%upcase(&lib);
|
%let lib=%upcase(&lib);
|
||||||
%let ds=%upcase(&ds);
|
%let ds=%upcase(&ds);
|
||||||
@@ -71,7 +70,6 @@
|
|||||||
%let sum=%mf_getuniquename(prefix=getpk_sum);
|
%let sum=%mf_getuniquename(prefix=getpk_sum);
|
||||||
%let pk4sure=%mf_getuniquename(prefix=getpk_pk4sure);
|
%let pk4sure=%mf_getuniquename(prefix=getpk_pk4sure);
|
||||||
%let pkdefault=%mf_getuniquename(prefix=getpk_pkdefault);
|
%let pkdefault=%mf_getuniquename(prefix=getpk_pkdefault);
|
||||||
%let pkfromindex=%mf_getuniquename(prefix=getpk_pkfromindex);
|
|
||||||
%let finalpks=%mf_getuniquename(prefix=getpk_finalpks);
|
%let finalpks=%mf_getuniquename(prefix=getpk_finalpks);
|
||||||
|
|
||||||
%local dbg;
|
%local dbg;
|
||||||
@@ -182,23 +180,9 @@ create table &ds1 as
|
|||||||
and a.constraint_name=b.constraint_name
|
and a.constraint_name=b.constraint_name
|
||||||
order by 1,2,3,4;
|
order by 1,2,3,4;
|
||||||
|
|
||||||
/* extract cols from the relevant unique INDEXES */
|
|
||||||
create table &pkfromindex as
|
|
||||||
select libname as libref
|
|
||||||
,memname as table_name
|
|
||||||
,indxname as constraint_name
|
|
||||||
,indxpos as constraint_order
|
|
||||||
,name
|
|
||||||
from dictionary.indexes
|
|
||||||
where nomiss='yes' and unique='yes' and upcase(libname)="&lib"
|
|
||||||
%if &ds ne 0 %then %do;
|
|
||||||
and upcase(memname)="&ds"
|
|
||||||
%end;
|
|
||||||
order by 1,2,3,4;
|
|
||||||
|
|
||||||
/* create one table */
|
/* create one table */
|
||||||
data &finalpks;
|
data &finalpks;
|
||||||
set &pkdefault &pk4sure &pkfromindex;
|
set &pkdefault &pk4sure ;
|
||||||
pk_ind=1;
|
pk_ind=1;
|
||||||
/* if there are multiple unique constraints, take the first */
|
/* if there are multiple unique constraints, take the first */
|
||||||
by libref table_name constraint_name;
|
by libref table_name constraint_name;
|
||||||
@@ -272,4 +256,4 @@ create table &outds as
|
|||||||
iftrue=(&mdebug=0)
|
iftrue=(&mdebug=0)
|
||||||
)
|
)
|
||||||
|
|
||||||
%mend mp_getpk;
|
%mend mp_getpk;
|
||||||
@@ -48,11 +48,6 @@
|
|||||||
outfile=0
|
outfile=0
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%if "%substr(&sysver.XX,1,4)"="V.04" %then %do;
|
|
||||||
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
|
||||||
%return;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%ml_gsubfile()
|
%ml_gsubfile()
|
||||||
|
|
||||||
%mend mp_gsubfile;
|
%mend mp_gsubfile;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Returns a unique hash for a dataset
|
@brief Returns a unique hash for a dataset
|
||||||
@details Ignores metadata attributes, used only to hash values. If used to
|
@details Ignores metadata attributes, used only to hash values. Compared
|
||||||
compare datasets, they must have their columns and rows in the same order.
|
datasets must be in the same order.
|
||||||
|
|
||||||
%mp_hashdataset(sashelp.class,outds=myhash)
|
%mp_hashdataset(sashelp.class,outds=myhash)
|
||||||
|
|
||||||
@@ -17,16 +17,13 @@
|
|||||||
@li mf_getattrn.sas
|
@li mf_getattrn.sas
|
||||||
@li mf_getuniquename.sas
|
@li mf_getuniquename.sas
|
||||||
@li mf_getvarlist.sas
|
@li mf_getvarlist.sas
|
||||||
@li mp_md5.sas
|
@li mf_getvartype.sas
|
||||||
|
|
||||||
<h4> Related Files </h4>
|
|
||||||
@li mp_hashdataset.test.sas
|
|
||||||
|
|
||||||
@param [in] libds dataset to hash
|
@param [in] libds dataset to hash
|
||||||
@param [in] salt= Provide a salt (could be, for instance, the dataset name)
|
@param [in] salt= Provide a salt (could be, for instance, the dataset name)
|
||||||
@param [in] iftrue= A condition under which the macro should be executed.
|
@param [in] iftrue= A condition under which the macro should be executed.
|
||||||
@param [out] outds= (work.mf_hashdataset) The output dataset to create. This
|
@param [out] outds= (work.mf_hashdataset) The output dataset to create. This
|
||||||
will contain one column (hashkey) with one observation (a $hex32.
|
will contain one column (hashkey) with one observation (a hex32.
|
||||||
representation of the input hash)
|
representation of the input hash)
|
||||||
|hashkey:$32.|
|
|hashkey:$32.|
|
||||||
|---|
|
|---|
|
||||||
@@ -38,48 +35,48 @@
|
|||||||
|
|
||||||
%macro mp_hashdataset(
|
%macro mp_hashdataset(
|
||||||
libds,
|
libds,
|
||||||
outds=work._data_,
|
outds=,
|
||||||
salt=,
|
salt=,
|
||||||
iftrue=%str(1=1)
|
iftrue=%str(1=1)
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%local keyvar /* roll up the md5 */
|
%if not(%eval(%unquote(&iftrue))) %then %return;
|
||||||
prevkeyvar /* retain prev record md5 */
|
|
||||||
lastvar /* last var in input ds */
|
|
||||||
cvars nvars;
|
|
||||||
|
|
||||||
%if not(%eval(%unquote(&iftrue))) %then %return;
|
%if %mf_getattrn(&libds,NLOBS)=0 %then %do;
|
||||||
|
%put %str(WARN)ING: Dataset &libds is empty, or is not a dataset;
|
||||||
/* avoid naming conflict for hash key vars */
|
%end;
|
||||||
%let keyvar=%mf_getuniquename();
|
%else %if %mf_getattrn(&libds,NLOBS)<0 %then %do;
|
||||||
%let prevkeyvar=%mf_getuniquename();
|
%put %str(ERR)OR: Dataset &libds is not a dataset;
|
||||||
%let lastvar=%mf_getuniquename();
|
%end;
|
||||||
|
%else %do;
|
||||||
%if %mf_getattrn(&libds,NLOBS)=0 %then %do;
|
%local keyvar /* roll up the md5 */
|
||||||
data &outds;
|
prevkeyvar /* retain prev record md5 */
|
||||||
length hashkey $32;
|
lastvar /* last var in input ds */
|
||||||
retain hashkey "%sysfunc(md5(%str(&salt)),$hex32.)";
|
varlist var i;
|
||||||
output;
|
/* avoid naming conflict for hash key vars */
|
||||||
stop;
|
%let keyvar=%mf_getuniquename();
|
||||||
run;
|
%let prevkeyvar=%mf_getuniquename();
|
||||||
%put &sysmacroname: Dataset &libds is empty, or is not a dataset;
|
%let lastvar=%mf_getuniquename();
|
||||||
%put &sysmacroname: hashkey of &outds is based on salt (&salt) only;
|
%let varlist=%mf_getvarlist(&libds);
|
||||||
%end;
|
data &outds(rename=(&keyvar=hashkey) keep=&keyvar);
|
||||||
%else %if %mf_getattrn(&libds,NLOBS)<0 %then %do;
|
length &prevkeyvar &keyvar $32;
|
||||||
%put %str(ERR)OR: Dataset &libds is not a dataset;
|
retain &prevkeyvar "%sysfunc(md5(%str(&salt)),$hex32.)";
|
||||||
%end;
|
set &libds end=&lastvar;
|
||||||
%else %do;
|
/* hash should include previous row */
|
||||||
data &outds(rename=(&keyvar=hashkey) keep=&keyvar)/nonote2err;
|
&keyvar=put(md5(&prevkeyvar
|
||||||
length &prevkeyvar &keyvar $32;
|
/* loop every column, hashing every individual value */
|
||||||
retain &prevkeyvar "%sysfunc(md5(%str(&salt)),$hex32.)";
|
%do i=1 %to %sysfunc(countw(&varlist));
|
||||||
set &libds end=&lastvar;
|
%let var=%scan(&varlist,&i,%str( ));
|
||||||
/* hash should include previous row */
|
%if %mf_getvartype(&libds,&var)=C %then %do;
|
||||||
&keyvar=%mp_md5(
|
!!put(md5(trim(&var)),$hex32.)
|
||||||
cvars=%mf_getvarlist(&libds,typefilter=C) &prevkeyvar,
|
%end;
|
||||||
nvars=%mf_getvarlist(&libds,typefilter=N)
|
%else %do;
|
||||||
);
|
!!put(md5(trim(put(&var*1,binary64.))),$hex32.)
|
||||||
&prevkeyvar=&keyvar;
|
%end;
|
||||||
if &lastvar then output;
|
%end;
|
||||||
run;
|
),$hex32.);
|
||||||
%end;
|
&prevkeyvar=&keyvar;
|
||||||
%mend mp_hashdataset;
|
if &lastvar then output;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
%mend mp_hashdataset;
|
||||||
@@ -67,10 +67,10 @@ 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" and "%substr(&sysver,1,1)" ne "5" %then %do;
|
%if %substr(&sysver,1,1) ne 4 %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;
|
||||||
;
|
;
|
||||||
|
|
||||||
%mend mp_init;
|
%mend mp_init;
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
%if &action=OPEN %then %do;
|
%if &action=OPEN %then %do;
|
||||||
options nobomfile;
|
options nobomfile;
|
||||||
data _null_;file &jref encoding='utf-8' lrecl=200;
|
data _null_;file &jref encoding='utf-8' ;
|
||||||
put '{"PROCESSED_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '"';
|
put '{"PROCESSED_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '"';
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -199,23 +199,12 @@
|
|||||||
format _numeric_ bart.;
|
format _numeric_ bart.;
|
||||||
%do i=1 %to &numcols;
|
%do i=1 %to &numcols;
|
||||||
%if &&typelong&i=char or &fmt=Y %then %do;
|
%if &&typelong&i=char or &fmt=Y %then %do;
|
||||||
if findc(&&name&i,'"\'!!'0A0D09000E0F01021011'x) then do;
|
&&name&i='"'!!trim(prxchange('s/"/\"/',-1,
|
||||||
&&name&i='"'!!trim(
|
prxchange('s/'!!'0A'x!!'/\n/',-1,
|
||||||
prxchange('s/"/\\"/',-1, /* double quote */
|
prxchange('s/'!!'0D'x!!'/\r/',-1,
|
||||||
prxchange('s/\x0A/\n/',-1, /* new line */
|
prxchange('s/'!!'09'x!!'/\t/',-1,
|
||||||
prxchange('s/\x0D/\r/',-1, /* carriage return */
|
prxchange('s/\\/\\\\/',-1,&&name&i)
|
||||||
prxchange('s/\x09/\\t/',-1, /* tab */
|
)))))!!'"';
|
||||||
prxchange('s/\x00/\\u0000/',-1, /* NUL */
|
|
||||||
prxchange('s/\x0E/\\u000E/',-1, /* SS */
|
|
||||||
prxchange('s/\x0F/\\u000F/',-1, /* SF */
|
|
||||||
prxchange('s/\x01/\\u0001/',-1, /* SOH */
|
|
||||||
prxchange('s/\x02/\\u0002/',-1, /* STX */
|
|
||||||
prxchange('s/\x10/\\u0010/',-1, /* DLE */
|
|
||||||
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
|
|
||||||
prxchange('s/\\/\\\\/',-1,&&name&i)
|
|
||||||
))))))))))))!!'"';
|
|
||||||
end;
|
|
||||||
else &&name&i=quote(cats(&&name&i));
|
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
run;
|
run;
|
||||||
|
|||||||
@@ -40,13 +40,13 @@
|
|||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mp_cntlout.sas
|
@li mp_cntlout.sas
|
||||||
@li mp_lockanytable.sas
|
@li mp_lockanytable.sas
|
||||||
@li mp_storediffs.sas
|
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
<h4> Related Macros </h4>
|
||||||
@li mddl_dc_difftable.sas
|
@li mddl_dc_difftable.sas
|
||||||
@li mddl_dc_locktable.sas
|
@li mddl_dc_locktable.sas
|
||||||
@li mp_loadformat.test.sas
|
@li mp_loadformat.test.sas
|
||||||
@li mp_lockanytable.sas
|
@li mp_lockanytable.sas
|
||||||
|
@li mp_storediffs.sas
|
||||||
@li mp_stackdiffs.sas
|
@li mp_stackdiffs.sas
|
||||||
|
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ run;
|
|||||||
* First, extract only relevant formats from the catalog
|
* First, extract only relevant formats from the catalog
|
||||||
*/
|
*/
|
||||||
proc sql noprint;
|
proc sql noprint;
|
||||||
select distinct upcase(fmtname) into: fmtlist separated by ' ' from &libds;
|
select distinct fmtname into: fmtlist separated by ' ' from &libds;
|
||||||
|
|
||||||
%mp_cntlout(libcat=&libcat,fmtlist=&fmtlist,cntlout=&base_fmts)
|
%mp_cntlout(libcat=&libcat,fmtlist=&fmtlist,cntlout=&base_fmts)
|
||||||
|
|
||||||
@@ -144,11 +144,8 @@ select distinct upcase(fmtname) into: fmtlist separated by ' ' from &libds;
|
|||||||
*/
|
*/
|
||||||
%mddl_sas_cntlout(libds=&template)
|
%mddl_sas_cntlout(libds=&template)
|
||||||
data &inlibds;
|
data &inlibds;
|
||||||
length &delete_col $3;
|
|
||||||
if 0 then set &template;
|
if 0 then set &template;
|
||||||
set &libds;
|
set &libds;
|
||||||
if &delete_col='' then &delete_col='No';
|
|
||||||
fmtname=upcase(fmtname);
|
|
||||||
if missing(type) then do;
|
if missing(type) then do;
|
||||||
if substr(fmtname,1,1)='$' then type='C';
|
if substr(fmtname,1,1)='$' then type='C';
|
||||||
else type='N';
|
else type='N';
|
||||||
@@ -159,6 +156,7 @@ data &inlibds;
|
|||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identify new records
|
* Identify new records
|
||||||
*/
|
*/
|
||||||
@@ -265,7 +263,7 @@ options ibufsize=&ibufsize;
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mp_storediffs(&libcat-FC
|
%mp_storediffs(&libcat-FC
|
||||||
,&base_fmts
|
,&inlibds
|
||||||
,FMTNAME START
|
,FMTNAME START
|
||||||
,delds=&outds_del
|
,delds=&outds_del
|
||||||
,modds=&outds_mod
|
,modds=&outds_mod
|
||||||
@@ -274,9 +272,6 @@ options ibufsize=&ibufsize;
|
|||||||
,mdebug=&mdebug
|
,mdebug=&mdebug
|
||||||
)
|
)
|
||||||
|
|
||||||
proc append base=&auditlibds data=&storediffs;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%if &locklibds ne 0 %then %do;
|
%if &locklibds ne 0 %then %do;
|
||||||
%mp_lockanytable(UNLOCK
|
%mp_lockanytable(UNLOCK
|
||||||
,lib=%scan(&auditlibds,1,.)
|
,lib=%scan(&auditlibds,1,.)
|
||||||
@@ -300,4 +295,4 @@ options ibufsize=&ibufsize;
|
|||||||
%put &sysmacroname exit vars:;
|
%put &sysmacroname exit vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
%end;
|
%end;
|
||||||
%mend mp_loadformat;
|
%mend mp_loadformat;
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Mechanism for locking tables to prevent parallel modifications
|
@brief Mechanism for locking tables to prevent parallel modifications
|
||||||
@details Uses a control table to enable ANY table to be locked for updates
|
@details Uses a control table to enable ANY table to be locked for updates.
|
||||||
(not just SAS datasets).
|
|
||||||
Only useful if every update uses the macro! Used heavily within
|
Only useful if every update uses the macro! Used heavily within
|
||||||
[Data Controller for SAS](https://datacontroller.io).
|
[Data Controller for SAS](https://datacontroller.io).
|
||||||
|
|
||||||
@@ -16,13 +15,12 @@
|
|||||||
length is 200 characters.
|
length is 200 characters.
|
||||||
@param [out] ctl_ds= (0) The control table which controls the actual locking.
|
@param [out] ctl_ds= (0) The control table which controls the actual locking.
|
||||||
Should already be assigned and available. The definition is available by
|
Should already be assigned and available. The definition is available by
|
||||||
running the mddl_dc_locktable.sas macro.
|
running mp_coretable.sas as follows: `%mp_coretable(LOCKTABLE)`.
|
||||||
|
|
||||||
@param [in] loops= (25) Number of times to check for a lock.
|
@param [in] loops= (25) Number of times to check for a lock.
|
||||||
@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
|
||||||
@@ -112,7 +110,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(),%mf_fmtdttm())"dt;
|
LOCK_START_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt;
|
||||||
LOCK_USER_NM="&user";
|
LOCK_USER_NM="&user";
|
||||||
LOCK_PID="&sysjobid";
|
LOCK_PID="&sysjobid";
|
||||||
LOCK_REF="&ref";
|
LOCK_REF="&ref";
|
||||||
@@ -132,7 +130,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(),%mf_fmtdttm())"dt
|
, LOCK_START_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt
|
||||||
, LOCK_USER_NM="&user"
|
, LOCK_USER_NM="&user"
|
||||||
, LOCK_PID="&sysjobid"
|
, LOCK_PID="&sysjobid"
|
||||||
, LOCK_REF="&ref"
|
, LOCK_REF="&ref"
|
||||||
@@ -207,7 +205,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(),%mf_fmtdttm())"dt
|
, LOCK_END_DTTM="%sysfunc(datetime(),E8601DT26.6)"dt
|
||||||
, LOCK_USER_NM="&user"
|
, LOCK_USER_NM="&user"
|
||||||
, LOCK_PID="&sysjobid"
|
, LOCK_PID="&sysjobid"
|
||||||
, LOCK_REF="&ref"
|
, LOCK_REF="&ref"
|
||||||
|
|||||||
@@ -54,5 +54,5 @@ put(md5(
|
|||||||
&sep put(md5(trim(put(ifn(missing(&var),&var,&var*1),binary64.))),$hex32.)
|
&sep put(md5(trim(put(ifn(missing(&var),&var,&var*1),binary64.))),$hex32.)
|
||||||
%let sep=!!;
|
%let sep=!!;
|
||||||
%end;
|
%end;
|
||||||
),$hex32.)
|
),hex32.)
|
||||||
%mend mp_md5;
|
%mend mp_md5;
|
||||||
|
|||||||
@@ -1,151 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Performs a text substitution on a file
|
|
||||||
@details Performs a find and replace on a file, either in place or to a new
|
|
||||||
file. Can be used on files where lines are longer than 32767.
|
|
||||||
|
|
||||||
Works by reading in the file byte by byte, then marking the beginning and end
|
|
||||||
of each matched string, before finally doing the replace.
|
|
||||||
|
|
||||||
Full credit for this highly efficient and syntactically satisfying SAS logic
|
|
||||||
goes to [Bartosz Jabłoński](https://www.linkedin.com/in/yabwon), founder of
|
|
||||||
the [SAS Packages](https://github.com/yabwon/SAS_PACKAGES) framework.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
%let file="%sysfunc(pathname(work))/file.txt";
|
|
||||||
%let str=replace/me;
|
|
||||||
%let rep=with/this;
|
|
||||||
data _null_;
|
|
||||||
file &file;
|
|
||||||
put 'blahblah';
|
|
||||||
put "blahblah&str.blah";
|
|
||||||
put 'blahblahblah';
|
|
||||||
run;
|
|
||||||
%mp_replace(&file, findvar=str, replacevar=rep)
|
|
||||||
data _null_;
|
|
||||||
infile &file;
|
|
||||||
input;
|
|
||||||
list;
|
|
||||||
run;
|
|
||||||
|
|
||||||
Note - if you are running a version of SAS that will allow the io package in
|
|
||||||
LUA, you can also use this macro: mp_gsubfile.sas
|
|
||||||
|
|
||||||
@param infile The QUOTED path to the file on which to perform the substitution
|
|
||||||
@param findvar= Macro variable NAME containing the string to search for
|
|
||||||
@param replacevar= Macro variable NAME containing the replacement string
|
|
||||||
@param outfile= (0) Optional QUOTED path to the adjusted output file (to
|
|
||||||
avoid overwriting the first file).
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
|
||||||
@li mp_chop.sas
|
|
||||||
@li mp_gsubfile.sas
|
|
||||||
@li mp_replace.test.sas
|
|
||||||
|
|
||||||
@version 9.4
|
|
||||||
@author Bartosz Jabłoński
|
|
||||||
@author Allan Bowe
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mp_replace(infile,
|
|
||||||
findvar=,
|
|
||||||
replacevar=,
|
|
||||||
outfile=0
|
|
||||||
)/*/STORE SOURCE*/;
|
|
||||||
|
|
||||||
%local inref dttm ds1;
|
|
||||||
%let inref=%mf_getuniquefileref();
|
|
||||||
%let outref=%mf_getuniquefileref();
|
|
||||||
%if &outfile=0 %then %let outfile=&infile;
|
|
||||||
%let ds1=%mf_getuniquename(prefix=allchars);
|
|
||||||
%let ds2=%mf_getuniquename(prefix=startmark);
|
|
||||||
|
|
||||||
/* START */
|
|
||||||
%let dttm=%sysfunc(datetime());
|
|
||||||
|
|
||||||
filename &inref &infile lrecl=1 recfm=n;
|
|
||||||
|
|
||||||
data &ds1;
|
|
||||||
infile &inref;
|
|
||||||
input sourcechar $char1. @@;
|
|
||||||
format sourcechar hex2.;
|
|
||||||
run;
|
|
||||||
|
|
||||||
data &ds2;
|
|
||||||
/* set find string to length in bytes to cover trailing spaces */
|
|
||||||
length string $ %length(%superq(&findvar));
|
|
||||||
string =symget("&findvar");
|
|
||||||
drop string;
|
|
||||||
|
|
||||||
firstchar=char(string,1);
|
|
||||||
findlen=lengthm(string); /* <- for trailing bytes */
|
|
||||||
|
|
||||||
do _N_=1 to nobs;
|
|
||||||
set &ds1 nobs=nobs point=_N_;
|
|
||||||
if sourcechar=firstchar then do;
|
|
||||||
pos=1;
|
|
||||||
s=0;
|
|
||||||
do point=_N_ to min(_N_ + findlen -1,nobs);
|
|
||||||
set &ds1 point=point;
|
|
||||||
if sourcechar=char(string, pos) then s + 1;
|
|
||||||
else goto _leave_;
|
|
||||||
pos+1;
|
|
||||||
end;
|
|
||||||
_leave_:
|
|
||||||
if s=findlen then do;
|
|
||||||
START =_N_;
|
|
||||||
_N_ =_N_+ s - 1;
|
|
||||||
STOP =_N_;
|
|
||||||
output;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
stop;
|
|
||||||
keep START STOP;
|
|
||||||
run;
|
|
||||||
|
|
||||||
data &ds1;
|
|
||||||
declare hash HS(dataset:"&ds2(keep=start)");
|
|
||||||
HS.defineKey("start");
|
|
||||||
HS.defineDone();
|
|
||||||
declare hash HE(dataset:"&ds2(keep=stop)");
|
|
||||||
HE.defineKey("stop");
|
|
||||||
HE.defineDone();
|
|
||||||
do until(eof);
|
|
||||||
set &ds1 end=eof curobs =n;
|
|
||||||
start = ^HS.check(key:n);
|
|
||||||
stop = ^HE.check(key:n);
|
|
||||||
length strt $ 1;
|
|
||||||
strt =put(start,best. -L);
|
|
||||||
retain out 1;
|
|
||||||
if out then output;
|
|
||||||
if start then out=0;
|
|
||||||
if stop then out=1;
|
|
||||||
end;
|
|
||||||
stop;
|
|
||||||
keep sourcechar strt;
|
|
||||||
run;
|
|
||||||
|
|
||||||
filename &outref &outfile recfm=n;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
length replace $ %length(%superq(&replacevar));
|
|
||||||
replace=symget("&replacevar");
|
|
||||||
file &outref;
|
|
||||||
do until(eof);
|
|
||||||
set &ds1 end=eof;
|
|
||||||
if strt ="1" then put replace char.;
|
|
||||||
else put sourcechar char1.;
|
|
||||||
end;
|
|
||||||
stop;
|
|
||||||
run;
|
|
||||||
|
|
||||||
/* END */
|
|
||||||
%put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) seconds to run;
|
|
||||||
|
|
||||||
%mend mp_replace;
|
|
||||||
@@ -58,7 +58,6 @@
|
|||||||
|
|
||||||
<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
|
||||||
@@ -218,12 +217,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(),%mf_fmtdttm())"dt;
|
,processed_dttm="%sysfunc(datetime(),E8601DT26.6)"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(),%mf_fmtdttm())"dt
|
,processed_dttm="%sysfunc(datetime(),E8601DT26.6)"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=upcase(&inds_auto);
|
&inds_keep=&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 upcase(&inds_auto)="&ds2" then tgtvar_type='N';
|
if &inds_auto="&ds2" then tgtvar_type='N';
|
||||||
else if upcase(&inds_auto)="&ds3" then tgtvar_type='C';
|
else if &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,9 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
@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 per the server type
|
@details Will set headers using appropriate functions (SAS 9 vs Viya) and send
|
||||||
(Viya, EBI, [SASjs Server](https://github.com/sasjs/server)) and stream
|
content as a binary stream.
|
||||||
content using mp_binarycopy().
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
@@ -13,14 +12,7 @@
|
|||||||
|
|
||||||
%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) Supported:
|
@param [in] contenttype= (TEXTS) Either TEXT, ZIP, CSV, EXCEL
|
||||||
@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.
|
||||||
@@ -66,7 +58,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;
|
||||||
@@ -76,7 +68,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;
|
||||||
@@ -84,7 +76,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;
|
||||||
@@ -94,14 +86,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;
|
||||||
@@ -109,30 +101,22 @@ 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 or &contenttype=MARKDOWN %then %do;
|
%else %if &contentype=HTML %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if &platform=SASVIYA %then %do;
|
||||||
data _null_;
|
|
||||||
rc=stpsrv_header('Content-Type',"text/%lowcase(&contenttype)");
|
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
%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/%lowcase(&contenttype)"
|
contenttype="text/html";
|
||||||
contentdisp="attachment; filename=&outname";
|
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-Type,text/%lowcase(&contenttype))
|
%mfs_httpheader(Content-type,text/html)
|
||||||
%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;
|
||||||
@@ -142,14 +126,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;
|
||||||
@@ -157,13 +141,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;
|
||||||
@@ -175,7 +159,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))
|
||||||
@@ -184,7 +168,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;
|
||||||
@@ -194,7 +178,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;
|
||||||
|
|||||||
@@ -40,9 +40,7 @@
|
|||||||
@li mf_getuniquename.sas
|
@li mf_getuniquename.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mp_binarycopy.sas
|
@li mp_binarycopy.sas
|
||||||
@li mp_chop.sas
|
|
||||||
@li mp_ds2csv.sas
|
@li mp_ds2csv.sas
|
||||||
@li ms_testservice.sas
|
|
||||||
@li mv_getjobresult.sas
|
@li mv_getjobresult.sas
|
||||||
@li mv_jobflow.sas
|
@li mv_jobflow.sas
|
||||||
|
|
||||||
@@ -65,7 +63,7 @@
|
|||||||
viyaresult=WEBOUT_JSON,
|
viyaresult=WEBOUT_JSON,
|
||||||
viyacontext=SAS Job Execution compute context
|
viyacontext=SAS Job Execution compute context
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local dbg pcnt fref1 fref2 webref webrefpath i webcount var platform;
|
%local dbg pcnt fref1 webref i webcount var platform;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -106,14 +104,10 @@
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%let platform=%mf_getplatform();
|
|
||||||
%let fref1=%mf_getuniquefileref();
|
|
||||||
%let fref2=%mf_getuniquefileref();
|
|
||||||
%let webref=%mf_getuniquefileref();
|
|
||||||
%let webrefpath=%sysfunc(pathname(work))/%mf_getuniquename();
|
|
||||||
/* mp_chop requires a physical path as input */
|
|
||||||
filename &webref "&webrefpath";
|
|
||||||
|
|
||||||
|
%let fref1=%mf_getuniquefileref();
|
||||||
|
%let webref=%mf_getuniquefileref();
|
||||||
|
%let platform=%mf_getplatform();
|
||||||
%if &platform=SASMETA %then %do;
|
%if &platform=SASMETA %then %do;
|
||||||
|
|
||||||
/* parse the input files */
|
/* parse the input files */
|
||||||
@@ -268,30 +262,13 @@ filename &webref "&webrefpath";
|
|||||||
mdebug=&mdebug
|
mdebug=&mdebug
|
||||||
)
|
)
|
||||||
|
|
||||||
%end;
|
|
||||||
%else %if &platform=SASJS %then %do;
|
|
||||||
|
|
||||||
%ms_testservice(&program
|
|
||||||
,inputfiles=&inputfiles
|
|
||||||
,inputdatasets=&inputdatasets
|
|
||||||
,inputparams=&inputparams
|
|
||||||
,debug=&debug
|
|
||||||
,mdebug=&mdebug
|
|
||||||
,outlib=&outlib
|
|
||||||
,outref=&outref
|
|
||||||
)
|
|
||||||
|
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put %str(ERR)OR: Unrecognised platform: &platform;
|
%put %str(ERR)OR: Unrecognised platform: &platform;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &mdebug=0 %then %do;
|
%if &mdebug=0 %then %do;
|
||||||
filename &fref1 clear;
|
filename &webref 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:;
|
||||||
|
|||||||
77
build.py
77
build.py
@@ -4,8 +4,8 @@ from pathlib import Path
|
|||||||
# Prepare Lua Macros
|
# Prepare Lua Macros
|
||||||
files = [f for f in Path('lua').iterdir() if f.match("*.lua")]
|
files = [f for f in Path('lua').iterdir() if f.match("*.lua")]
|
||||||
for file in files:
|
for file in files:
|
||||||
basename = os.path.basename(file)
|
basename=os.path.basename(file)
|
||||||
name = 'ml_' + os.path.splitext(basename)[0]
|
name='ml_' + os.path.splitext(basename)[0]
|
||||||
ml = open('lua/' + name + '.sas', "w")
|
ml = open('lua/' + name + '.sas', "w")
|
||||||
ml.write("/**\n")
|
ml.write("/**\n")
|
||||||
ml.write(" @file " + name + '.sas\n')
|
ml.write(" @file " + name + '.sas\n')
|
||||||
@@ -20,68 +20,50 @@ for file in files:
|
|||||||
ml.write(" file \"%sysfunc(pathname(work))/" + name + ".lua\";\n")
|
ml.write(" file \"%sysfunc(pathname(work))/" + name + ".lua\";\n")
|
||||||
with open(file) as infile:
|
with open(file) as infile:
|
||||||
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\" /source2;\n\n")
|
||||||
ml.write("/* ensure big enough lrecl to avoid lua compilation issues */\n")
|
|
||||||
ml.write("%local optval;\n")
|
|
||||||
ml.write("%let optval=%sysfunc(getoption(lrecl));\n")
|
|
||||||
ml.write("options lrecl=1024;\n\n")
|
|
||||||
ml.write("/* execute the lua code by using a .lua extension */\n")
|
|
||||||
ml.write("%inc \"%sysfunc(pathname(work))/" +
|
|
||||||
name + ".lua\" /source2;\n\n")
|
|
||||||
ml.write("options lrecl=&optval;\n\n")
|
|
||||||
ml.write("%mend " + name + ";\n")
|
ml.write("%mend " + name + ";\n")
|
||||||
|
|
||||||
ml.close()
|
ml.close()
|
||||||
|
|
||||||
# prepare web files
|
# prepare web files
|
||||||
files = ['viya/mv_createwebservice.sas',
|
files=['viya/mv_createwebservice.sas','meta/mm_createwebservice.sas']
|
||||||
'meta/mm_createwebservice.sas', 'server/ms_createwebservice.sas']
|
|
||||||
for file in files:
|
for file in files:
|
||||||
webout0 = open('base/mp_jsonout.sas', 'r')
|
webout0=open('base/mp_jsonout.sas','r')
|
||||||
webout1 = open('base/mf_getuser.sas', 'r')
|
if file=='viya/mv_createwebservice.sas':
|
||||||
|
webout1=open('viya/mv_webout.sas',"r")
|
||||||
if file == 'viya/mv_createwebservice.sas':
|
|
||||||
webout2 = open('viya/mv_webout.sas', "r")
|
|
||||||
weboutfiles = [webout0, webout1, webout2]
|
|
||||||
elif file == 'server/ms_createwebservice.sas':
|
|
||||||
webout2 = open('server/ms_webout.sas', "r")
|
|
||||||
webout3 = open('server/mfs_httpheader.sas', 'r')
|
|
||||||
weboutfiles = [webout0, webout1, webout2, webout3]
|
|
||||||
else:
|
else:
|
||||||
webout2 = open('meta/mm_webout.sas', 'r')
|
webout1=open('meta/mm_webout.sas','r')
|
||||||
weboutfiles = [webout0, webout1, webout2]
|
webout2=open('base/mf_getuser.sas','r')
|
||||||
outfile = open(file + 'TEMP', 'w')
|
outfile=open(file + 'TEMP','w')
|
||||||
infile = open(file, 'r')
|
infile=open(file,'r')
|
||||||
delrow = 0
|
delrow=0
|
||||||
for line in infile:
|
for line in infile:
|
||||||
if line == '/* WEBOUT BEGIN */\n':
|
if line=='/* WEBOUT BEGIN */\n':
|
||||||
delrow = 1
|
delrow=1
|
||||||
outfile.write('/* WEBOUT BEGIN */\n')
|
outfile.write('/* WEBOUT BEGIN */\n')
|
||||||
|
weboutfiles=[webout0,webout1,webout2]
|
||||||
for weboutfile in weboutfiles:
|
for weboutfile in weboutfiles:
|
||||||
stripcomment = 1
|
stripcomment=1
|
||||||
for w in weboutfile:
|
for w in weboutfile:
|
||||||
if w == '**/\n':
|
if w=='**/\n': stripcomment=0
|
||||||
stripcomment = 0
|
elif stripcomment==0:
|
||||||
elif stripcomment == 0:
|
outfile.write(" put '" + w.rstrip().replace("'","''") + " ';\n")
|
||||||
outfile.write(
|
elif delrow==1 and line=='/* WEBOUT END */\n':
|
||||||
" put '" + w.rstrip().replace("'", "''") + " ';\n")
|
delrow=0
|
||||||
elif delrow == 1 and line == '/* WEBOUT END */\n':
|
outfile.write('/* WEBOUT END */\n')
|
||||||
delrow = 0
|
elif delrow==0:
|
||||||
outfile.write('/* WEBOUT END */\n')
|
|
||||||
elif delrow == 0:
|
|
||||||
outfile.write(line.rstrip() + "\n")
|
outfile.write(line.rstrip() + "\n")
|
||||||
webout0.close()
|
webout0.close()
|
||||||
webout1.close()
|
webout1.close()
|
||||||
webout2.close()
|
|
||||||
outfile.close()
|
outfile.close()
|
||||||
infile.close()
|
infile.close()
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
os.rename(file + 'TEMP', file)
|
os.rename(file + 'TEMP',file)
|
||||||
|
|
||||||
# Concatenate all macros into a single file
|
# Concatenate all macros into a single file
|
||||||
header = """
|
header="""
|
||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Auto-generated file
|
@brief Auto-generated file
|
||||||
@@ -102,15 +84,14 @@ options noquotelenmax;
|
|||||||
"""
|
"""
|
||||||
f = open('all.sas', "w") # r / r+ / rb / rb+ / w / wb
|
f = open('all.sas', "w") # r / r+ / rb / rb+ / w / wb
|
||||||
f.write(header)
|
f.write(header)
|
||||||
folders = ['base', 'ddl', 'meta', 'metax', 'server', 'viya', 'lua', 'fcmp']
|
folders=['base','ddl','meta','metax','server','viya','lua','fcmp']
|
||||||
for folder in folders:
|
for folder in folders:
|
||||||
filenames = [fn for fn in Path(
|
filenames = [fn for fn in Path('./' + folder).iterdir() if fn.match("*.sas")]
|
||||||
'./' + folder).iterdir() if fn.match("*.sas")]
|
|
||||||
filenames.sort()
|
filenames.sort()
|
||||||
with open('mc_' + folder + '.sas', 'w') as outfile:
|
with open('mc_' + folder + '.sas', 'w') as outfile:
|
||||||
for fname in filenames:
|
for fname in filenames:
|
||||||
with open(fname) as infile:
|
with open(fname) as infile:
|
||||||
outfile.write(infile.read())
|
outfile.write(infile.read())
|
||||||
with open('mc_' + folder + '.sas', 'r') as c:
|
with open('mc_' + folder + '.sas','r') as c:
|
||||||
f.write(c.read())
|
f.write(c.read())
|
||||||
f.close()
|
f.close()
|
||||||
|
|||||||
110
fcmp/mcf_stpsrv_header.sas
Normal file
110
fcmp/mcf_stpsrv_header.sas
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Provides a replacement for the stpsrv_header function
|
||||||
|
@details The stpsrv_header is normally a built-in function, used to set the
|
||||||
|
headers for SAS 9 Stored Processes as documented here:
|
||||||
|
https://go.documentation.sas.com/doc/en/itechcdc/9.4/stpug/srvhead.htm
|
||||||
|
|
||||||
|
The purpose of this custom function is to provide a replacement when running
|
||||||
|
similar code as a web service against
|
||||||
|
[sasjs/server](https://github.com/sasjs/server). It operates by creating a
|
||||||
|
text file with the headers. The location of this text file is determined by
|
||||||
|
a macro variable (`sasjs_stpsrv_header_loc`) which needs to be injected into
|
||||||
|
each service by the calling process, eg:
|
||||||
|
|
||||||
|
%let sasjs_stpsrv_header_loc = C:/temp/some_uuid/stpsrv_header.txt;
|
||||||
|
|
||||||
|
Note - the function works by appending headers to the file. If multiple same-
|
||||||
|
named headers are provided, they will all be appended - the calling process
|
||||||
|
needs to pick up the last one. This will mean removing the attribute if the
|
||||||
|
final record has an empty value.
|
||||||
|
|
||||||
|
The function takes the following (positional) parameters:
|
||||||
|
|
||||||
|
| PARAMETER | DESCRIPTION |
|
||||||
|
|------------|-------------|
|
||||||
|
| name $ | name of the header attribute to create|
|
||||||
|
| value $ | value of the header attribute|
|
||||||
|
|
||||||
|
It returns 0 if successful, or -1 if an error occured.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/stpsrv_header.txt;
|
||||||
|
|
||||||
|
%mcf_stpsrv_header(wrap=YES, insert_cmplib=YES)
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
rc=stpsrv_header('Content-type','application/text');
|
||||||
|
rc=stpsrv_header('Content-disposition',"attachment; filename=file.txt");
|
||||||
|
run;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
|
input;
|
||||||
|
putlog _infile_;
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
|
||||||
|
@param [out] lib= (work) The output library in which to create the catalog.
|
||||||
|
@param [out] cat= (sasjs) The output catalog in which to create the package.
|
||||||
|
@param [out] pkg= (utils) The output package in which to create the function.
|
||||||
|
Uses a 3 part format: libref.catalog.package
|
||||||
|
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
|
||||||
|
values inserted only if needed.
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mcf_init.sas
|
||||||
|
|
||||||
|
<h4> Related Programs </h4>
|
||||||
|
@li mcf_stpsrv_header.test.sas
|
||||||
|
@li mp_init.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mcf_stpsrv_header(wrap=NO
|
||||||
|
,insert_cmplib=DEPRECATED
|
||||||
|
,lib=WORK
|
||||||
|
,cat=SASJS
|
||||||
|
,pkg=UTILS
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
%local i var cmpval found;
|
||||||
|
%if %mcf_init(stpsrv_header)=1 %then %return;
|
||||||
|
|
||||||
|
%if &wrap=YES %then %do;
|
||||||
|
proc fcmp outlib=&lib..&cat..&pkg;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
function stpsrv_header(name $, value $);
|
||||||
|
length loc $128 val $512;
|
||||||
|
loc=symget('sasjs_stpsrv_header_loc');
|
||||||
|
val=trim(name)!!': '!!value;
|
||||||
|
length fref $8;
|
||||||
|
rc=filename(fref,loc);
|
||||||
|
if (rc ne 0) then return( -1 );
|
||||||
|
fid = fopen(fref,'a');
|
||||||
|
if (fid = 0) then return( -1 );
|
||||||
|
rc=fput(fid, val);
|
||||||
|
rc=fwrite(fid);
|
||||||
|
rc=fclose(fid);
|
||||||
|
rc=filename(fref);
|
||||||
|
return(0);
|
||||||
|
endsub;
|
||||||
|
|
||||||
|
%if &wrap=YES %then %do;
|
||||||
|
quit;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
/* insert the CMPLIB if not already there */
|
||||||
|
%let cmpval=%sysfunc(getoption(cmplib));
|
||||||
|
%let found=0;
|
||||||
|
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
|
||||||
|
%let var=%scan(&cmpval,&i,%str( %(%)));
|
||||||
|
%if &var=&lib..&cat %then %let found=1;
|
||||||
|
%end;
|
||||||
|
%if &found=0 %then %do;
|
||||||
|
options insert=(CMPLIB=(&lib..&cat));
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend mcf_stpsrv_header;
|
||||||
@@ -39,14 +39,6 @@ data _null_;
|
|||||||
put 'io.close(file) ';
|
put 'io.close(file) ';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
/* ensure big enough lrecl to avoid lua compilation issues */
|
|
||||||
%local optval;
|
|
||||||
%let optval=%sysfunc(getoption(lrecl));
|
|
||||||
options lrecl=1024;
|
|
||||||
|
|
||||||
/* execute the lua code by using a .lua extension */
|
|
||||||
%inc "%sysfunc(pathname(work))/ml_gsubfile.lua" /source2;
|
%inc "%sysfunc(pathname(work))/ml_gsubfile.lua" /source2;
|
||||||
|
|
||||||
options lrecl=&optval;
|
|
||||||
|
|
||||||
%mend ml_gsubfile;
|
%mend ml_gsubfile;
|
||||||
|
|||||||
@@ -389,14 +389,6 @@ data _null_;
|
|||||||
put '-- JSON.LUA ENDS HERE ';
|
put '-- JSON.LUA ENDS HERE ';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
/* ensure big enough lrecl to avoid lua compilation issues */
|
|
||||||
%local optval;
|
|
||||||
%let optval=%sysfunc(getoption(lrecl));
|
|
||||||
options lrecl=1024;
|
|
||||||
|
|
||||||
/* execute the lua code by using a .lua extension */
|
|
||||||
%inc "%sysfunc(pathname(work))/ml_json.lua" /source2;
|
%inc "%sysfunc(pathname(work))/ml_json.lua" /source2;
|
||||||
|
|
||||||
options lrecl=&optval;
|
|
||||||
|
|
||||||
%mend ml_json;
|
%mend ml_json;
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
|
|
||||||
@param [in] libref The libref (not name) of the metadata library
|
@param libref the libref (not name) of the metadata library
|
||||||
@param [in] mAbort= If not assigned, HARD will call %mp_abort(), SOFT will
|
@param mAbort= If not assigned, HARD will call %mp_abort(), SOFT will
|
||||||
silently return
|
silently return
|
||||||
|
|
||||||
@returns libname statement
|
@returns libname statement
|
||||||
@@ -28,11 +28,11 @@
|
|||||||
libref
|
libref
|
||||||
,mAbort=HARD
|
,mAbort=HARD
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local mp_abort msg;
|
|
||||||
%let mp_abort=0;
|
|
||||||
%if %sysfunc(libref(&libref)) %then %do;
|
%if %sysfunc(libref(&libref)) %then %do;
|
||||||
|
%local mp_abort msg; %let mp_abort=0;
|
||||||
data _null_;
|
data _null_;
|
||||||
length liburi LibName msg $200;
|
length liburi LibName $200;
|
||||||
call missing(of _all_);
|
call missing(of _all_);
|
||||||
nobj=metadata_getnobj("omsobj:SASLibrary?@Libref='&libref'",1,liburi);
|
nobj=metadata_getnobj("omsobj:SASLibrary?@Libref='&libref'",1,liburi);
|
||||||
if nobj=1 then do;
|
if nobj=1 then do;
|
||||||
@@ -40,30 +40,7 @@
|
|||||||
/* now try and assign it */
|
/* now try and assign it */
|
||||||
if libname("&libref",,'meta',cats('liburi="',liburi,'";')) ne 0 then do;
|
if libname("&libref",,'meta',cats('liburi="',liburi,'";')) ne 0 then do;
|
||||||
putlog "&libref could not be assigned";
|
putlog "&libref could not be assigned";
|
||||||
putlog liburi=;
|
call symputx('msg',sysmsg(),'l');
|
||||||
/**
|
|
||||||
* Fetch the system message for display in the abort modal. This is
|
|
||||||
* not always helpful though. One example, previously received:
|
|
||||||
* NOTE: Libref XX refers to the same library metadata as libref XX.
|
|
||||||
*/
|
|
||||||
msg=sysmsg();
|
|
||||||
if msg=:'ERROR: Libref SAVE is not assigned.' then do;
|
|
||||||
msg=catx(" ",
|
|
||||||
"Could not assign %upcase(&libref).",
|
|
||||||
"Please check metadata permissions! Libname:",libname,
|
|
||||||
"Liburi:",liburi
|
|
||||||
);
|
|
||||||
end;
|
|
||||||
else if msg="ERROR: User does not have appropriate authorization "!!
|
|
||||||
"level for library SAVE."
|
|
||||||
then do;
|
|
||||||
msg=catx(" ",
|
|
||||||
"ERROR: User does not have appropriate authorization level",
|
|
||||||
"for library %upcase(&libref), libname:",libname,
|
|
||||||
"Liburi:",liburi
|
|
||||||
);
|
|
||||||
end;
|
|
||||||
call symputx('msg',msg,'l');
|
|
||||||
if "&mabort"='HARD' then call symputx('mp_abort',1,'l');
|
if "&mabort"='HARD' then call symputx('mp_abort',1,'l');
|
||||||
end;
|
end;
|
||||||
else do;
|
else do;
|
||||||
@@ -82,16 +59,20 @@
|
|||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%put NOTE: &msg;
|
%if &mp_abort=1 %then %do;
|
||||||
|
%mp_abort(iftrue= (&mp_abort=1)
|
||||||
|
,mac=&sysmacroname
|
||||||
|
,msg=&msg
|
||||||
|
)
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
%else %if %length(&msg)>2 %then %do;
|
||||||
|
%put NOTE: &msg;
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put NOTE: Library &libref is already assigned;
|
%put NOTE: Library &libref is already assigned;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mp_abort(iftrue= (&mp_abort=1)
|
|
||||||
,mac=mm_assignlib.sas
|
|
||||||
,msg=%superq(msg)
|
|
||||||
)
|
|
||||||
|
|
||||||
%mend mm_assignlib;
|
%mend mm_assignlib;
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '%if &action=OPEN %then %do; ';
|
put '%if &action=OPEN %then %do; ';
|
||||||
put ' options nobomfile; ';
|
put ' options nobomfile; ';
|
||||||
put ' data _null_;file &jref encoding=''utf-8'' lrecl=200; ';
|
put ' data _null_;file &jref encoding=''utf-8'' ; ';
|
||||||
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
@@ -232,23 +232,12 @@ data _null_;
|
|||||||
put ' format _numeric_ bart.; ';
|
put ' format _numeric_ bart.; ';
|
||||||
put ' %do i=1 %to &numcols; ';
|
put ' %do i=1 %to &numcols; ';
|
||||||
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
||||||
put ' if findc(&&name&i,''"\''!!''0A0D09000E0F01021011''x) then do; ';
|
put ' &&name&i=''"''!!trim(prxchange(''s/"/\"/'',-1, ';
|
||||||
put ' &&name&i=''"''!!trim( ';
|
put ' prxchange(''s/''!!''0A''x!!''/\n/'',-1, ';
|
||||||
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
|
put ' prxchange(''s/''!!''0D''x!!''/\r/'',-1, ';
|
||||||
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
|
put ' prxchange(''s/''!!''09''x!!''/\t/'',-1, ';
|
||||||
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
|
put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) ';
|
||||||
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
|
put ' )))))!!''"''; ';
|
||||||
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
|
|
||||||
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
|
|
||||||
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
|
|
||||||
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
|
|
||||||
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
|
|
||||||
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
|
|
||||||
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
|
|
||||||
put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) ';
|
|
||||||
put ' ))))))))))))!!''"''; ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' else &&name&i=quote(cats(&&name&i)); ';
|
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
@@ -314,25 +303,6 @@ data _null_;
|
|||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%mend mp_jsonout; ';
|
put '%mend mp_jsonout; ';
|
||||||
put ' ';
|
|
||||||
put '%macro mf_getuser(type=META ';
|
|
||||||
put ')/*/STORE SOURCE*/; ';
|
|
||||||
put ' %local user metavar; ';
|
|
||||||
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
|
||||||
put ' %else %let metavar=_metaperson; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
|
||||||
put ' %else %if %symexist(&metavar) %then %do; ';
|
|
||||||
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
|
||||||
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
|
||||||
put ' /* but be sure to quote in case of usernames with commas */ ';
|
|
||||||
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %let user=&sysuserid; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %quote(&user) ';
|
|
||||||
put ' ';
|
|
||||||
put '%mend mf_getuser; ';
|
|
||||||
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL ';
|
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL ';
|
||||||
put ' ,showmeta=NO ';
|
put ' ,showmeta=NO ';
|
||||||
put '); ';
|
put '); ';
|
||||||
@@ -451,16 +421,14 @@ data _null_;
|
|||||||
put ' put '',"_METAPERSON": '' _METAPERSON; ';
|
put ' put '',"_METAPERSON": '' _METAPERSON; ';
|
||||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||||
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
|
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 ",""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; ';
|
||||||
put ' syswarningtext=quote(cats(symget(''SYSWARNINGTEXT''))); ';
|
put ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; ';
|
||||||
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
|
|
||||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
||||||
put ' length memsize $32; ';
|
put ' length memsize $32; ';
|
||||||
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
||||||
@@ -474,6 +442,24 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%mend mm_webout; ';
|
put '%mend mm_webout; ';
|
||||||
|
put ' ';
|
||||||
|
put '%macro mf_getuser(type=META ';
|
||||||
|
put ')/*/STORE SOURCE*/; ';
|
||||||
|
put ' %local user metavar; ';
|
||||||
|
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
||||||
|
put ' %else %let metavar=_metaperson; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
||||||
|
put ' %else %if %symexist(&metavar) %then %do; ';
|
||||||
|
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
||||||
|
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
||||||
|
put ' %else %let user=%scan(&&&metavar,1,@); ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %let user=&sysuserid; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %quote(&user) ';
|
||||||
|
put ' ';
|
||||||
|
put '%mend mf_getuser; ';
|
||||||
/* WEBOUT END */
|
/* WEBOUT END */
|
||||||
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO);';
|
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO);';
|
||||||
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing';
|
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing';
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ filename &fname2 clear;
|
|||||||
%local isgone;
|
%local isgone;
|
||||||
data _null_;
|
data _null_;
|
||||||
length type uri $256;
|
length type uri $256;
|
||||||
call missing (of _all_);
|
|
||||||
rc=metadata_resolve("omsobj:SASLibrary?@Id='&liburi'",type,uri);
|
rc=metadata_resolve("omsobj:SASLibrary?@Id='&liburi'",type,uri);
|
||||||
call symputx('isgone',type,'l');
|
call symputx('isgone',type,'l');
|
||||||
run;
|
run;
|
||||||
|
|||||||
@@ -49,25 +49,20 @@
|
|||||||
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
@li mf_isblank.sas
|
|
||||||
@li mf_loc.sas
|
@li mf_loc.sas
|
||||||
@li mm_tree.sas
|
@li mm_tree.sas
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_isblank.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
|
|
||||||
|
@param metaloc= the metadata folder to export
|
||||||
@param [in] metaloc= the metadata folder to export
|
@param secureref= fileref containing the username / password (should point to
|
||||||
@param [in] secureref= fileref containing the username / password (should
|
a file in a secure location). Leave blank to substitute $bash type vars.
|
||||||
point to a file in a secure location). Leave blank to substitute $bash vars.
|
@param outref= fileref to which to write the command
|
||||||
@param [in] excludevars= (0) A space seperated list of macro variable names,
|
@param cmdoutloc= the directory to which the command will write the SPK
|
||||||
each of which contains a value that should be used to filter the output
|
(default=WORK)
|
||||||
objects.
|
@param cmdoutname= the name of the spk / log files to create (will be
|
||||||
@param [out] outref= fileref to which to write the command
|
identical just with .spk or .log extension)
|
||||||
@param [out] cmdoutloc= (%sysfunc(pathname(work))) The directory to which the
|
|
||||||
command will write the SPK
|
|
||||||
@param [out] cmdoutname= (mmxport) The name of the spk / log files to create
|
|
||||||
(will be identical just with .spk or .log extension)
|
|
||||||
|
|
||||||
@version 9.4
|
@version 9.4
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@@ -76,7 +71,6 @@
|
|||||||
|
|
||||||
%macro mm_spkexport(metaloc=
|
%macro mm_spkexport(metaloc=
|
||||||
,secureref=
|
,secureref=
|
||||||
,excludevars=0
|
|
||||||
,outref=
|
,outref=
|
||||||
,cmdoutloc=%sysfunc(pathname(work))
|
,cmdoutloc=%sysfunc(pathname(work))
|
||||||
,cmdoutname=mmxport
|
,cmdoutname=mmxport
|
||||||
@@ -88,7 +82,7 @@
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
/* set creds */
|
/* set creds */
|
||||||
%local mmxuser mmxpath i var;
|
%local mmxuser mmxpath;
|
||||||
%let mmxuser=$1;
|
%let mmxuser=$1;
|
||||||
%let mmxpass=$2;
|
%let mmxpass=$2;
|
||||||
%if %mf_isblank(&secureref)=0 %then %do;
|
%if %mf_isblank(&secureref)=0 %then %do;
|
||||||
@@ -96,51 +90,35 @@
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
/* setup metadata connection options */
|
/* setup metadata connection options */
|
||||||
%local host port platform_object_path ds;
|
%local host port platform_object_path connx_string;
|
||||||
%let host=%sysfunc(getoption(metaserver));
|
%let host=%sysfunc(getoption(metaserver));
|
||||||
%let port=%sysfunc(getoption(metaport));
|
%let port=%sysfunc(getoption(metaport));
|
||||||
%let platform_object_path=%mf_loc(POF);
|
%let platform_object_path=%mf_loc(POF);
|
||||||
%let ds=%mf_getuniquename(prefix=spkexportable);
|
|
||||||
|
|
||||||
%mm_tree(root=%str(&metaloc),types=EXPORTABLE ,outds=&ds)
|
%let connx_string=%str(-host &host -port &port -user &mmxuser %trim(
|
||||||
|
)-password &mmxpass);
|
||||||
|
|
||||||
|
%mm_tree(root=%str(&metaloc) ,types=EXPORTABLE ,outds=exportable)
|
||||||
|
|
||||||
%if %mf_isblank(&outref)=1 %then %let outref=%mf_getuniquefileref();
|
%if %mf_isblank(&outref)=1 %then %let outref=%mf_getuniquefileref();
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
set &ds end=last;
|
set exportable end=last;
|
||||||
file &outref lrecl=32767;
|
file &outref lrecl=32767;
|
||||||
length str $32767;
|
length str $32767;
|
||||||
if _n_=1 then do;
|
if _n_=1 then do;
|
||||||
put "# Script generated by &sysuserid on %sysfunc(datetime(),datetime19.)";
|
|
||||||
put "cd ""&platform_object_path"" \";
|
put "cd ""&platform_object_path"" \";
|
||||||
put "; ./ExportPackage -host &host -port &port -user &mmxuser \";
|
put "; ./ExportPackage &connx_string -disableX11 \";
|
||||||
put " -disableX11 -password &mmxpass \";
|
put " -package ""&cmdoutloc/&cmdoutname..spk"" \";
|
||||||
put " -package ""&cmdoutloc/&cmdoutname..spk"" \";
|
|
||||||
end;
|
end;
|
||||||
/* exclude particular patterns from the exported SPK */
|
|
||||||
%if "&excludevars" ne "0" %then %do;
|
|
||||||
%do i=1 %to %sysfunc(countw(&excludevars));
|
|
||||||
%let var=%scan(&excludevars,&i);
|
|
||||||
if _n_=1 then do;
|
|
||||||
length excludestr&i $1000;
|
|
||||||
retain excludestr&i;
|
|
||||||
excludestr&i=symget("&var");
|
|
||||||
putlog excludestr&i=;
|
|
||||||
putlog path=;
|
|
||||||
end;
|
|
||||||
if index(path,cats(excludestr&i))=0 and index(name,cats(excludestr&i))=0;
|
|
||||||
%end;
|
|
||||||
/* ignore top level folder else all subcontent will be exported regardless */
|
|
||||||
if _n_>1;
|
|
||||||
%end;
|
|
||||||
str=' -objects '!!cats('"',path,'/',name,"(",publictype,')" \');
|
str=' -objects '!!cats('"',path,'/',name,"(",publictype,')" \');
|
||||||
put str;
|
put str;
|
||||||
if last then put " -log ""&cmdoutloc/&cmdoutname..log"" 2>&1 ";
|
if last then put " -log ""&cmdoutloc/&cmdoutname..log"" 2>&1 ";
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%mp_abort(iftrue= (&syscc ne 0)
|
%mp_abort(iftrue= (&syscc ne 0)
|
||||||
,mac=mm_spkexport
|
,mac=&sysmacroname
|
||||||
,msg=%str(syscc=&syscc)
|
,msg=%str(syscc=&syscc)
|
||||||
)
|
)
|
||||||
|
|
||||||
%mend mm_spkexport;
|
%mend mm_spkexport;
|
||||||
@@ -157,16 +157,14 @@
|
|||||||
put ',"_METAPERSON": ' _METAPERSON;
|
put ',"_METAPERSON": ' _METAPERSON;
|
||||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||||
put ",""SYSCC"" : ""&syscc"" ";
|
put ",""SYSCC"" : ""&syscc"" ";
|
||||||
syserrortext=quote(cats(symget('SYSERRORTEXT')));
|
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||||
put ',"SYSERRORTEXT" : ' syserrortext;
|
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
put ",""SYSJOBID"" : ""&sysjobid"" ";
|
||||||
put ",""SYSSCPL"" : ""&sysscpl"" ";
|
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;
|
||||||
syswarningtext=quote(cats(symget('SYSWARNINGTEXT')));
|
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||||
put ',"SYSWARNINGTEXT" : ' syswarningtext;
|
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||||
length memsize $32;
|
length memsize $32;
|
||||||
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
||||||
|
|||||||
2441
package-lock.json
generated
2441
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -26,13 +26,14 @@
|
|||||||
"homepage": "https://core.sasjs.io",
|
"homepage": "https://core.sasjs.io",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "sasjs cbd -t server",
|
"build": "sasjs cbd -t viya",
|
||||||
"docs": "sasjs doc -t docsonly && ./sasjs/utils/build.sh",
|
"docs": "sasjs doc -t docsonly && ./sasjs/utils/build.sh",
|
||||||
"test": "sasjs test -t server",
|
"test": "sasjs test -t viya",
|
||||||
"lint": "sasjs lint",
|
"lint": "sasjs lint",
|
||||||
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
|
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sasjs/cli": "3.13.0"
|
"@sasjs/cli": "^3.6.0",
|
||||||
|
"@sasjs/core": "4.4.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
"base",
|
"base",
|
||||||
"ddl",
|
"ddl",
|
||||||
"fcmp",
|
"fcmp",
|
||||||
"lua",
|
"meta",
|
||||||
|
"metax",
|
||||||
"server",
|
"server",
|
||||||
|
"viya",
|
||||||
|
"lua",
|
||||||
"tests/crossplatform",
|
"tests/crossplatform",
|
||||||
"tests/ddl"
|
"tests/ddl"
|
||||||
],
|
],
|
||||||
@@ -25,20 +28,25 @@
|
|||||||
"mcTestAppLoc": "/Public/temp/macrocore"
|
"mcTestAppLoc": "/Public/temp/macrocore"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"defaultTarget": "server",
|
"defaultTarget": "viya",
|
||||||
"targets": [
|
"targets": [
|
||||||
{
|
{
|
||||||
"name": "viya",
|
"name": "viya",
|
||||||
"serverUrl": "",
|
"serverUrl": "https://sas.analytium.co.uk",
|
||||||
"serverType": "SASVIYA",
|
"serverType": "SASVIYA",
|
||||||
"httpsAgentOptions": {
|
"httpsAgentOptions": {
|
||||||
"allowInsecureRequests": false
|
"allowInsecureRequests": false
|
||||||
},
|
},
|
||||||
"appLoc": "/Public/app/macrocore",
|
"appLoc": "/Public/temp/macrocore",
|
||||||
"macroFolders": [
|
"macroFolders": [
|
||||||
"viya",
|
|
||||||
"tests/viyaonly"
|
"tests/viyaonly"
|
||||||
],
|
],
|
||||||
|
"programFolders": [],
|
||||||
|
"binaryFolders": [],
|
||||||
|
"deployConfig": {
|
||||||
|
"deployServicePack": true,
|
||||||
|
"deployScripts": []
|
||||||
|
},
|
||||||
"contextName": "SAS Job Execution compute context"
|
"contextName": "SAS Job Execution compute context"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -50,8 +58,6 @@
|
|||||||
},
|
},
|
||||||
"appLoc": "/Shared Data/temp/macrocore",
|
"appLoc": "/Shared Data/temp/macrocore",
|
||||||
"macroFolders": [
|
"macroFolders": [
|
||||||
"meta",
|
|
||||||
"metax",
|
|
||||||
"tests/sas9only"
|
"tests/sas9only"
|
||||||
],
|
],
|
||||||
"programFolders": [],
|
"programFolders": [],
|
||||||
@@ -65,44 +71,23 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"serverUrl": "https://sas.analytium.co.uk:5007",
|
"serverUrl": "https://sas.analytium.co.uk:5000",
|
||||||
"serverType": "SASJS",
|
"serverType": "SASJS",
|
||||||
"httpsAgentOptions": {
|
"appLoc": "/Shared Data/temp/macrocore",
|
||||||
"allowInsecureRequests": false
|
|
||||||
},
|
|
||||||
"appLoc": "/sasjs/core",
|
|
||||||
"macroFolders": [
|
"macroFolders": [
|
||||||
"server",
|
|
||||||
"tests/serveronly"
|
"tests/serveronly"
|
||||||
]
|
],
|
||||||
|
"deployConfig": {
|
||||||
|
"deployServicePack": true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "docsonly",
|
"name": "docsonly",
|
||||||
"serverType": "SAS9",
|
"serverType": "SAS9",
|
||||||
"appLoc": "dummy",
|
|
||||||
"macroFolders": [
|
"macroFolders": [
|
||||||
"meta",
|
|
||||||
"metax",
|
|
||||||
"server",
|
|
||||||
"viya",
|
|
||||||
"tests/sas9only",
|
"tests/sas9only",
|
||||||
"tests/serveronly",
|
|
||||||
"tests/viyaonly"
|
"tests/viyaonly"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "viya4",
|
|
||||||
"serverUrl": "https://azureuse011059.my-trials.sas.com",
|
|
||||||
"serverType": "SASVIYA",
|
|
||||||
"appLoc": "/Public/temp/macrocore",
|
|
||||||
"macroFolders": [
|
|
||||||
"viya",
|
|
||||||
"tests/viyaonly"
|
|
||||||
],
|
|
||||||
"deployConfig": {
|
|
||||||
"deployServicePack": true
|
|
||||||
},
|
|
||||||
"contextName": "SAS Job Execution compute context"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%mfs_httpheader(Content-Type,application/csv)
|
%mfs_httpheader(Content-type,application/csv)
|
||||||
|
|
||||||
@param [in] header_name Name of the http header to set
|
@param [in] header_name Name of the http header to set
|
||||||
@param [in] header_value Value of the http header to set
|
@param [in] header_value Value of the http header to set
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
%macro mfs_httpheader(header_name
|
%macro mfs_httpheader(header_name
|
||||||
,header_value
|
,header_value
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%global sasjs_stpsrv_header_loc;
|
|
||||||
%local fref fid i;
|
%local fref fid i;
|
||||||
|
|
||||||
%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do;
|
%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do;
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Creates a file on SASjs Drive
|
|
||||||
@details Creates a file on SASjs Drive. To use the file as a Stored Program,
|
|
||||||
it must have a ".sas" extension.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
filename stpcode temp;
|
|
||||||
data _null_;
|
|
||||||
file stpcode;
|
|
||||||
put '%put hello world;';
|
|
||||||
run;
|
|
||||||
%ms_createfile(/some/stored/program.sas, inref=stpcode)
|
|
||||||
|
|
||||||
@param [in] driveloc The full path to the file in SASjs Drive
|
|
||||||
@param [in] inref= (0) The fileref containing the file to create.
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
@li mp_abort.sas
|
|
||||||
@li ms_deletefile.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro ms_createfile(driveloc
|
|
||||||
,inref=0
|
|
||||||
,mdebug=0
|
|
||||||
);
|
|
||||||
|
|
||||||
/* first, delete in case it exists */
|
|
||||||
%ms_deletefile(&driveloc,mdebug=&mdebug)
|
|
||||||
|
|
||||||
%local fname0 fname1 fname2 boundary fname statcd msg optval;
|
|
||||||
%let fname0=%mf_getuniquefileref();
|
|
||||||
%let fname1=%mf_getuniquefileref();
|
|
||||||
%let fname2=%mf_getuniquefileref();
|
|
||||||
%let boundary=%mf_getuniquename();
|
|
||||||
|
|
||||||
/* avoid sending bom marker to API */
|
|
||||||
%let optval=%sysfunc(getoption(bomfile));
|
|
||||||
options nobomfile;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &fname0 termstr=crlf lrecl=32767;
|
|
||||||
infile &inref end=eof lrecl=32767;
|
|
||||||
if _n_ = 1 then do;
|
|
||||||
put "--&boundary.";
|
|
||||||
put 'Content-Disposition: form-data; name="filePath"';
|
|
||||||
put ;
|
|
||||||
put "&driveloc";
|
|
||||||
put "--&boundary";
|
|
||||||
put 'Content-Disposition: form-data; name="file"; filename="ignore.sas"';
|
|
||||||
put "Content-Type: text/plain";
|
|
||||||
put ;
|
|
||||||
end;
|
|
||||||
input;
|
|
||||||
put _infile_; /* add the actual file to be sent */
|
|
||||||
if eof then do;
|
|
||||||
put ;
|
|
||||||
put "--&boundary--";
|
|
||||||
end;
|
|
||||||
run;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &fname1 lrecl=1000;
|
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
|
||||||
input;
|
|
||||||
put "Content-Type: multipart/form-data; boundary=&boundary";
|
|
||||||
put "Authorization: Bearer " _infile_;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
data _null_;
|
|
||||||
infile &fname0 lrecl=32767;
|
|
||||||
input;
|
|
||||||
put _infile_;
|
|
||||||
data _null_;
|
|
||||||
infile &fname1 lrecl=32767;
|
|
||||||
input;
|
|
||||||
put _infile_;
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
proc http method='POST' in=&fname0 headerin=&fname1 out=&fname2
|
|
||||||
url="&_sasjs_apiserverurl/SASjsApi/drive/file";
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
debug level=1;
|
|
||||||
%end;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%let statcd=0;
|
|
||||||
data _null_;
|
|
||||||
infile &fname2;
|
|
||||||
input;
|
|
||||||
putlog _infile_;
|
|
||||||
if _infile_='{"status":"success"}' then call symputx('statcd',1,'l');
|
|
||||||
else call symputx('msg',_infile_,'l');
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&statcd=0)
|
|
||||||
,mac=ms_createfile.sas
|
|
||||||
,msg=%superq(msg)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* reset options */
|
|
||||||
options &optval;
|
|
||||||
|
|
||||||
%mend ms_createfile;
|
|
||||||
@@ -1,144 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Creates a user on SASjs Server
|
|
||||||
@details Creates a user on SASjs Server with the following attributes:
|
|
||||||
|
|
||||||
@li UserName
|
|
||||||
@li Password
|
|
||||||
@li isAdmin
|
|
||||||
@li displayName
|
|
||||||
|
|
||||||
The userid is created by sasjs/server. All users are created with `isActive`
|
|
||||||
set to `true`.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
%ms_createuser(newuser,secretpass,displayname=New User!)
|
|
||||||
|
|
||||||
@param [in] username The username to apply. No spaces or special characters.
|
|
||||||
@param [in] password The initial password to set.
|
|
||||||
@param [in] isadmin= (false) Set to true to give the user admin rights
|
|
||||||
@param [in] displayName= (0) Set a friendly name (spaces & special characters
|
|
||||||
are ok). If not provided, username will be used instead.
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
|
||||||
@param [out] outds= (work.ms_createuser) This output dataset will contain the
|
|
||||||
values from the JSON response (such as the id of the new user)
|
|
||||||
|ID:best.|DISPLAYNAME:$8.|USERNAME:$8.|ISACTIVE:best.|ISADMIN:best.|
|
|
||||||
|---|---|---|---|---|
|
|
||||||
|`6 `|`New User `|`newuser `|`1 `|`0 `|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquelibref.sas
|
|
||||||
@li mp_abort.sas
|
|
||||||
|
|
||||||
<h4> Related Files </h4>
|
|
||||||
@li ms_createuser.test.sas
|
|
||||||
@li ms_getusers.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro ms_createuser(username,password
|
|
||||||
,isadmin=false
|
|
||||||
,displayname=0
|
|
||||||
,outds=work.ms_createuser
|
|
||||||
,mdebug=0
|
|
||||||
);
|
|
||||||
|
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&syscc ne 0)
|
|
||||||
,mac=ms_createuser.sas
|
|
||||||
,msg=%str(syscc=&syscc on macro entry)
|
|
||||||
)
|
|
||||||
|
|
||||||
%local fref0 fref1 fref2 libref optval rc msg;
|
|
||||||
%let fref0=%mf_getuniquefileref();
|
|
||||||
%let fref1=%mf_getuniquefileref();
|
|
||||||
%let fref2=%mf_getuniquefileref();
|
|
||||||
%let libref=%mf_getuniquelibref();
|
|
||||||
|
|
||||||
/* avoid sending bom marker to API */
|
|
||||||
%let optval=%sysfunc(getoption(bomfile));
|
|
||||||
options nobomfile;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &fref0 termstr=crlf;
|
|
||||||
username=quote(cats(symget('username')));
|
|
||||||
password=quote(cats(symget('password')));
|
|
||||||
isadmin=symget('isadmin');
|
|
||||||
displayname=quote(cats(symget('displayname')));
|
|
||||||
if displayname='"0"' then displayname=username;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
putlog _all_;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
put '{'@;
|
|
||||||
put '"displayName":' displayname @;
|
|
||||||
put ',"username":' username @;
|
|
||||||
put ',"password":' password @;
|
|
||||||
put ',"isAdmin":' isadmin @;
|
|
||||||
put ',"isActive": true }';
|
|
||||||
run;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &fref1 lrecl=1000;
|
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
|
||||||
input;
|
|
||||||
put "Authorization: Bearer " _infile_;
|
|
||||||
put "Content-Type: application/json";
|
|
||||||
put "accept: application/json";
|
|
||||||
run;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
data _null_;
|
|
||||||
infile &fref0;
|
|
||||||
input;
|
|
||||||
put _infile_;
|
|
||||||
data _null_;
|
|
||||||
infile &fref1;
|
|
||||||
input;
|
|
||||||
put _infile_;
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
proc http method='POST' in=&fref0 headerin=&fref1 out=&fref2
|
|
||||||
url="&_sasjs_apiserverurl/SASjsApi/user";
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
debug level=1;
|
|
||||||
%end;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&syscc ne 0)
|
|
||||||
,mac=ms_createuser.sas
|
|
||||||
,msg=%str(Issue submitting query to SASjsApi/user)
|
|
||||||
)
|
|
||||||
|
|
||||||
libname &libref JSON fileref=&fref2;
|
|
||||||
|
|
||||||
data &outds;
|
|
||||||
set &libref..root;
|
|
||||||
drop ordinal_root;
|
|
||||||
run;
|
|
||||||
|
|
||||||
|
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&syscc ne 0)
|
|
||||||
,mac=ms_createuser.sas
|
|
||||||
,msg=%str(Issue reading response JSON)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* reset options */
|
|
||||||
options &optval;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
filename &fref0 clear;
|
|
||||||
filename &fref1 clear;
|
|
||||||
filename &fref2 clear;
|
|
||||||
libname &libref clear;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%mend ms_createuser;
|
|
||||||
@@ -1,537 +0,0 @@
|
|||||||
/**
|
|
||||||
@file ms_createwebservice.sas
|
|
||||||
@brief Create a Web-Ready Stored Program
|
|
||||||
@details This macro creates a Stored Program along with the necessary precode
|
|
||||||
to enable the %webout() macro
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
<code>
|
|
||||||
%* compile macros ;
|
|
||||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
|
||||||
%inc mc;
|
|
||||||
|
|
||||||
%* parmcards lets us write to a text file from open code ;
|
|
||||||
filename ft15f001 temp;
|
|
||||||
parmcards4;
|
|
||||||
%webout(FETCH)
|
|
||||||
%* do some sas, any inputs are now already WORK tables;
|
|
||||||
data example1 example2;
|
|
||||||
set sashelp.class;
|
|
||||||
run;
|
|
||||||
%* send data back;
|
|
||||||
%webout(OPEN)
|
|
||||||
%webout(ARR,example1) * Array format, fast, suitable for large tables ;
|
|
||||||
%webout(OBJ,example2) * Object format, easier to work with ;
|
|
||||||
%webout(CLOSE)
|
|
||||||
;;;;
|
|
||||||
%ms_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001)
|
|
||||||
|
|
||||||
</code>
|
|
||||||
|
|
||||||
For more examples of using these web services with the SASjs Adapter, see:
|
|
||||||
https://github.com/sasjs/adapter#readme
|
|
||||||
|
|
||||||
@param [in] path= (0) The full SASjs Drive path in which to create the service
|
|
||||||
@param [in] name= Stored Program name
|
|
||||||
@param [in] desc= The description of the service (not implemented yet)
|
|
||||||
@param [in] precode= Space separated list of filerefs, pointing to the code
|
|
||||||
that needs to be attached to the beginning of the service (optional)
|
|
||||||
@param [in] code= (ft15f001) Space seperated fileref(s) of the actual code to
|
|
||||||
be added
|
|
||||||
@param [in] mDebug= (0) set to 1 to show debug messages in the log
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li ms_createfile.sas
|
|
||||||
@li mf_getuser.sas
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mp_abort.sas
|
|
||||||
|
|
||||||
<h4> Related Files </h4>
|
|
||||||
@li ms_createwebservice.test.sas
|
|
||||||
|
|
||||||
@version 9.2
|
|
||||||
@author Allan Bowe
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro ms_createwebservice(path=0
|
|
||||||
,name=initService
|
|
||||||
,precode=
|
|
||||||
,code=ft15f001
|
|
||||||
,desc=Not currently used
|
|
||||||
,mDebug=0
|
|
||||||
)/*/STORE SOURCE*/;
|
|
||||||
|
|
||||||
%local dbg;
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
%put &sysmacroname entry vars:;
|
|
||||||
%put _local_;
|
|
||||||
%end;
|
|
||||||
%else %let dbg=*;
|
|
||||||
|
|
||||||
%mp_abort(iftrue=(&syscc ge 4 )
|
|
||||||
,mac=ms_createwebservice
|
|
||||||
,msg=%str(syscc=&syscc on macro entry)
|
|
||||||
)
|
|
||||||
%mp_abort(iftrue=("&path"="0")
|
|
||||||
,mac=ms_createwebservice
|
|
||||||
,msg=%str(Path not provided)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* remove any trailing slash */
|
|
||||||
%if "%substr(&path,%length(&path),1)" = "/" %then
|
|
||||||
%let path=%substr(&path,1,%length(&path)-1);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add webout macro
|
|
||||||
* These put statements are auto generated - to change the macro, change the
|
|
||||||
* source (ms_webout) and run `build.py`
|
|
||||||
*/
|
|
||||||
%local sasjsref;
|
|
||||||
%let sasjsref=%mf_getuniquefileref();
|
|
||||||
data _null_;
|
|
||||||
file &sasjsref termstr=crlf lrecl=512;
|
|
||||||
put "/* Created on %sysfunc(datetime(),datetime19.) by %mf_getuser() */";
|
|
||||||
/* WEBOUT BEGIN */
|
|
||||||
put ' ';
|
|
||||||
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
|
||||||
put ' ,engine=DATASTEP ';
|
|
||||||
put ' ,missing=NULL ';
|
|
||||||
put ' ,showmeta=NO ';
|
|
||||||
put ')/*/STORE SOURCE*/; ';
|
|
||||||
put '%local tempds colinfo fmtds i numcols; ';
|
|
||||||
put '%let numcols=0; ';
|
|
||||||
put ' ';
|
|
||||||
put '%if &action=OPEN %then %do; ';
|
|
||||||
put ' options nobomfile; ';
|
|
||||||
put ' data _null_;file &jref encoding=''utf-8'' lrecl=200; ';
|
|
||||||
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
|
||||||
put ' run; ';
|
|
||||||
put '%end; ';
|
|
||||||
put '%else %if (&action=ARR or &action=OBJ) %then %do; ';
|
|
||||||
put ' options validvarname=upcase; ';
|
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
|
||||||
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
|
|
||||||
put ' ';
|
|
||||||
put ' /* grab col defs */ ';
|
|
||||||
put ' proc contents noprint data=&ds ';
|
|
||||||
put ' out=_data_(keep=name type length format formatl formatd varnum label); ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' %let colinfo=%scan(&syslast,2,.); ';
|
|
||||||
put ' proc sort data=&colinfo; ';
|
|
||||||
put ' by varnum; ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' /* move meta to mac vars */ ';
|
|
||||||
put ' data _null_; ';
|
|
||||||
put ' if _n_=1 then call symputx(''numcols'',nobs,''l''); ';
|
|
||||||
put ' set &colinfo end=last nobs=nobs; ';
|
|
||||||
put ' name=upcase(name); ';
|
|
||||||
put ' /* fix formats */ ';
|
|
||||||
put ' if type=2 or type=6 then do; ';
|
|
||||||
put ' typelong=''char''; ';
|
|
||||||
put ' length fmt $49.; ';
|
|
||||||
put ' if format='''' then fmt=cats(''$'',length,''.''); ';
|
|
||||||
put ' else if formatl=0 then fmt=cats(format,''.''); ';
|
|
||||||
put ' else fmt=cats(format,formatl,''.''); ';
|
|
||||||
put ' newlen=max(formatl,length); ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' else do; ';
|
|
||||||
put ' typelong=''num''; ';
|
|
||||||
put ' if format='''' then fmt=''best.''; ';
|
|
||||||
put ' else if formatl=0 then fmt=cats(format,''.''); ';
|
|
||||||
put ' else if formatd=0 then fmt=cats(format,formatl,''.''); ';
|
|
||||||
put ' else fmt=cats(format,formatl,''.'',formatd); ';
|
|
||||||
put ' /* needs to be wide, for datetimes etc */ ';
|
|
||||||
put ' newlen=max(length,formatl,24); ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' /* 32 char unique name */ ';
|
|
||||||
put ' newname=''sasjs''!!substr(cats(put(md5(name),$hex32.)),1,27); ';
|
|
||||||
put ' ';
|
|
||||||
put ' call symputx(cats(''name'',_n_),name,''l''); ';
|
|
||||||
put ' call symputx(cats(''newname'',_n_),newname,''l''); ';
|
|
||||||
put ' call symputx(cats(''len'',_n_),newlen,''l''); ';
|
|
||||||
put ' call symputx(cats(''length'',_n_),length,''l''); ';
|
|
||||||
put ' call symputx(cats(''fmt'',_n_),fmt,''l''); ';
|
|
||||||
put ' call symputx(cats(''type'',_n_),type,''l''); ';
|
|
||||||
put ' call symputx(cats(''typelong'',_n_),typelong,''l''); ';
|
|
||||||
put ' call symputx(cats(''label'',_n_),coalescec(label,name),''l''); ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %let tempds=%substr(_%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
|
||||||
put ' ';
|
|
||||||
put ' %if &engine=PROCJSON %then %do; ';
|
|
||||||
put ' %if &missing=STRING %then %do; ';
|
|
||||||
put ' %put &sysmacroname: Special Missings not supported in proc json.; ';
|
|
||||||
put ' %put &sysmacroname: Switching to DATASTEP engine; ';
|
|
||||||
put ' %goto datastep; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' data &tempds;set &ds; ';
|
|
||||||
put ' %if &fmt=N %then format _numeric_ best32.;; ';
|
|
||||||
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
|
|
||||||
put ' proc json out=&jref pretty ';
|
|
||||||
put ' %if &action=ARR %then nokeys ; ';
|
|
||||||
put ' ;export &tempds / nosastags fmtnumeric; ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %if &engine=DATASTEP %then %do; ';
|
|
||||||
put ' %datastep: ';
|
|
||||||
put ' %if %sysfunc(exist(&ds)) ne 1 & %sysfunc(exist(&ds,VIEW)) ne 1 ';
|
|
||||||
put ' %then %do; ';
|
|
||||||
put ' %put &sysmacroname: &ds NOT FOUND!!!; ';
|
|
||||||
put ' %return; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %if &fmt=Y %then %do; ';
|
|
||||||
put ' data _data_; ';
|
|
||||||
put ' /* rename on entry */ ';
|
|
||||||
put ' set &ds(rename=( ';
|
|
||||||
put ' %do i=1 %to &numcols; ';
|
|
||||||
put ' &&name&i=&&newname&i ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' )); ';
|
|
||||||
put ' %do i=1 %to &numcols; ';
|
|
||||||
put ' length &&name&i $&&len&i; ';
|
|
||||||
put ' %if &&typelong&i=num %then %do; ';
|
|
||||||
put ' &&name&i=left(put(&&newname&i,&&fmt&i)); ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %do; ';
|
|
||||||
put ' &&name&i=put(&&newname&i,&&fmt&i); ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' drop &&newname&i; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' if _error_ then call symputx(''syscc'',1012); ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' %let fmtds=&syslast; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' ';
|
|
||||||
put ' proc format; /* credit yabwon for special null removal */ ';
|
|
||||||
put ' value bart (default=40) ';
|
|
||||||
put ' %if &missing=NULL %then %do; ';
|
|
||||||
put ' ._ - .z = null ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %do; ';
|
|
||||||
put ' ._ = [quote()] ';
|
|
||||||
put ' . = null ';
|
|
||||||
put ' .a - .z = [quote()] ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' other = [best.]; ';
|
|
||||||
put ' ';
|
|
||||||
put ' data &tempds; ';
|
|
||||||
put ' attrib _all_ label=''''; ';
|
|
||||||
put ' %do i=1 %to &numcols; ';
|
|
||||||
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
|
||||||
put ' length &&name&i $32767; ';
|
|
||||||
put ' format &&name&i $32767.; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %if &fmt=Y %then %do; ';
|
|
||||||
put ' set &fmtds; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %do; ';
|
|
||||||
put ' set &ds; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' format _numeric_ bart.; ';
|
|
||||||
put ' %do i=1 %to &numcols; ';
|
|
||||||
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
|
||||||
put ' if findc(&&name&i,''"\''!!''0A0D09000E0F01021011''x) then do; ';
|
|
||||||
put ' &&name&i=''"''!!trim( ';
|
|
||||||
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
|
|
||||||
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
|
|
||||||
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
|
|
||||||
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
|
|
||||||
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
|
|
||||||
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
|
|
||||||
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
|
|
||||||
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
|
|
||||||
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
|
|
||||||
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
|
|
||||||
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
|
|
||||||
put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) ';
|
|
||||||
put ' ))))))))))))!!''"''; ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' else &&name&i=quote(cats(&&name&i)); ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' ';
|
|
||||||
put ' /* write to temp loc to avoid _webout truncation ';
|
|
||||||
put ' - https://support.sas.com/kb/49/325.html */ ';
|
|
||||||
put ' filename _sjs temp lrecl=131068 encoding=''utf-8''; ';
|
|
||||||
put ' data _null_; file _sjs lrecl=131068 encoding=''utf-8'' mod ; ';
|
|
||||||
put ' if _n_=1 then put "["; ';
|
|
||||||
put ' set &tempds; ';
|
|
||||||
put ' if _n_>1 then put "," @; put ';
|
|
||||||
put ' %if &action=ARR %then "[" ; %else "{" ; ';
|
|
||||||
put ' %do i=1 %to &numcols; ';
|
|
||||||
put ' %if &i>1 %then "," ; ';
|
|
||||||
put ' %if &action=OBJ %then """&&name&i"":" ; ';
|
|
||||||
put ' &&name&i ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
|
|
||||||
put ' /* now write the long strings to _webout 1 byte at a time */ ';
|
|
||||||
put ' data _null_; ';
|
|
||||||
put ' length filein 8 fileid 8; ';
|
|
||||||
put ' filein=fopen("_sjs",''I'',1,''B''); ';
|
|
||||||
put ' fileid=fopen("&jref",''A'',1,''B''); ';
|
|
||||||
put ' rec=''20''x; ';
|
|
||||||
put ' do while(fread(filein)=0); ';
|
|
||||||
put ' rc=fget(filein,rec,1); ';
|
|
||||||
put ' rc=fput(fileid, rec); ';
|
|
||||||
put ' rc=fwrite(fileid); ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' /* close out the table */ ';
|
|
||||||
put ' rc=fput(fileid, "]"); ';
|
|
||||||
put ' rc=fwrite(fileid); ';
|
|
||||||
put ' rc=fclose(filein); ';
|
|
||||||
put ' rc=fclose(fileid); ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' filename _sjs clear; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' ';
|
|
||||||
put ' proc sql; ';
|
|
||||||
put ' drop table &colinfo, &tempds; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %if &showmeta=YES %then %do; ';
|
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
|
||||||
put ' put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{"; ';
|
|
||||||
put ' do i=1 to &numcols; ';
|
|
||||||
put ' name=quote(trim(symget(cats(''name'',i)))); ';
|
|
||||||
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
|
|
||||||
put ' label=quote(trim(symget(cats(''label'',i)))); ';
|
|
||||||
put ' length=quote(trim(symget(cats(''length'',i)))); ';
|
|
||||||
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
|
|
||||||
put ' if i>1 then put "," @@; ';
|
|
||||||
put ' put name '':{"format":'' format '',"label":'' label ';
|
|
||||||
put ' '',"length":'' length '',"type":'' type ''}''; ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' put ''}}''; ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put '%end; ';
|
|
||||||
put ' ';
|
|
||||||
put '%else %if &action=CLOSE %then %do; ';
|
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod ; ';
|
|
||||||
put ' put "}"; ';
|
|
||||||
put ' run; ';
|
|
||||||
put '%end; ';
|
|
||||||
put '%mend mp_jsonout; ';
|
|
||||||
put ' ';
|
|
||||||
put '%macro mf_getuser(type=META ';
|
|
||||||
put ')/*/STORE SOURCE*/; ';
|
|
||||||
put ' %local user metavar; ';
|
|
||||||
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
|
||||||
put ' %else %let metavar=_metaperson; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
|
||||||
put ' %else %if %symexist(&metavar) %then %do; ';
|
|
||||||
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
|
||||||
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
|
||||||
put ' /* but be sure to quote in case of usernames with commas */ ';
|
|
||||||
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %let user=&sysuserid; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %quote(&user) ';
|
|
||||||
put ' ';
|
|
||||||
put '%mend mf_getuser; ';
|
|
||||||
put ' ';
|
|
||||||
put '%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL ';
|
|
||||||
put ' ,showmeta=NO ';
|
|
||||||
put '); ';
|
|
||||||
put '%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug ';
|
|
||||||
put ' sasjs_tables; ';
|
|
||||||
put ' ';
|
|
||||||
put '%local i tempds; ';
|
|
||||||
put '%let action=%upcase(&action); ';
|
|
||||||
put ' ';
|
|
||||||
put '%if &action=FETCH %then %do; ';
|
|
||||||
put ' %if %str(&_debug) ge 131 %then %do; ';
|
|
||||||
put ' options mprint notes mprintnest; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %let _webin_file_count=%eval(&_webin_file_count+0); ';
|
|
||||||
put ' /* now read in the data */ ';
|
|
||||||
put ' %do i=1 %to &_webin_file_count; ';
|
|
||||||
put ' %if &_webin_file_count=1 %then %do; ';
|
|
||||||
put ' %let _webin_fileref1=&_webin_fileref; ';
|
|
||||||
put ' %let _webin_name1=&_webin_name; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' data _null_; ';
|
|
||||||
put ' infile &&_webin_fileref&i termstr=crlf lrecl=32767; ';
|
|
||||||
put ' input; ';
|
|
||||||
put ' call symputx(''input_statement'',_infile_); ';
|
|
||||||
put ' putlog "&&_webin_name&i input statement: " _infile_; ';
|
|
||||||
put ' stop; ';
|
|
||||||
put ' data &&_webin_name&i; ';
|
|
||||||
put ' infile &&_webin_fileref&i firstobs=2 dsd termstr=crlf encoding=''utf-8'' ';
|
|
||||||
put ' lrecl=32767; ';
|
|
||||||
put ' input &input_statement; ';
|
|
||||||
put ' %if %str(&_debug) ge 131 %then %do; ';
|
|
||||||
put ' if _n_<20 then putlog _infile_; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' %let sasjs_tables=&sasjs_tables &&_webin_name&i; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put '%end; ';
|
|
||||||
put ' ';
|
|
||||||
put '%else %if &action=OPEN %then %do; ';
|
|
||||||
put ' /* fix encoding and ensure enough lrecl */ ';
|
|
||||||
put ' OPTIONS NOBOMFILE lrecl=32767; ';
|
|
||||||
put ' ';
|
|
||||||
put ' /* set the header */ ';
|
|
||||||
put ' %mfs_httpheader(Content-type,application/json) ';
|
|
||||||
put ' ';
|
|
||||||
put ' /* setup json. */ ';
|
|
||||||
put ' data _null_;file &fref encoding=''utf-8'' termstr=lf ; ';
|
|
||||||
put ' put ''{"SYSDATE" : "'' "&SYSDATE" ''"''; ';
|
|
||||||
put ' put '',"SYSTIME" : "'' "&SYSTIME" ''"''; ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' ';
|
|
||||||
put '%end; ';
|
|
||||||
put ' ';
|
|
||||||
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 ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta ';
|
|
||||||
put ' ) ';
|
|
||||||
put '%end; ';
|
|
||||||
put '%else %if &action=CLOSE %then %do; ';
|
|
||||||
put ' %if %str(&_debug) ge 131 %then %do; ';
|
|
||||||
put ' /* if debug mode, send back first 10 records of each work table also */ ';
|
|
||||||
put ' options obs=10; ';
|
|
||||||
put ' data;run;%let tempds=%scan(&syslast,2,.); ';
|
|
||||||
put ' ods output Members=&tempds; ';
|
|
||||||
put ' proc datasets library=WORK memtype=data; ';
|
|
||||||
put ' %local wtcnt;%let wtcnt=0; ';
|
|
||||||
put ' data _null_; ';
|
|
||||||
put ' set &tempds; ';
|
|
||||||
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
|
||||||
put ' if not (upcase(name)=:"_DATA_"); ';
|
|
||||||
put ' i+1; ';
|
|
||||||
put ' call symputx(cats(''wt'',i),name,''l''); ';
|
|
||||||
put ' call symputx(''wtcnt'',i,''l''); ';
|
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
|
||||||
put ' put ",""WORK"":{"; ';
|
|
||||||
put ' %do i=1 %to &wtcnt; ';
|
|
||||||
put ' %let wt=&&wt&i; ';
|
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
|
||||||
put ' dsid=open("WORK.&wt",''is''); ';
|
|
||||||
put ' nlobs=attrn(dsid,''NLOBS''); ';
|
|
||||||
put ' nvars=attrn(dsid,''NVARS''); ';
|
|
||||||
put ' rc=close(dsid); ';
|
|
||||||
put ' if &i>1 then put '',''@; ';
|
|
||||||
put ' put " ""&wt"" : {"; ';
|
|
||||||
put ' put ''"nlobs":'' nlobs; ';
|
|
||||||
put ' put '',"nvars":'' nvars; ';
|
|
||||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=YES) ';
|
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
|
||||||
put ' put "}"; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
|
||||||
put ' put "}"; ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' /* close off json */ ';
|
|
||||||
put ' data _null_;file &fref mod encoding=''utf-8'' termstr=lf lrecl=32767; ';
|
|
||||||
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
|
||||||
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
|
||||||
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
|
||||||
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
|
||||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
|
||||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
|
||||||
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
|
|
||||||
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
|
||||||
put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); ';
|
|
||||||
put ' put '',"SYSHOSTINFOLONG" : '' SYSHOSTINFOLONG; ';
|
|
||||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
|
||||||
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
|
|
||||||
put ' put ",""SYSPROCESSMODE"" : ""&SYSPROCESSMODE"" "; ';
|
|
||||||
put ' length SYSPROCESSNAME $512; ';
|
|
||||||
put ' SYSPROCESSNAME=quote(urlencode(cats(SYSPROCESSNAME))); ';
|
|
||||||
put ' put ",""SYSPROCESSNAME"" : " SYSPROCESSNAME; ';
|
|
||||||
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
|
||||||
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
|
||||||
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
|
||||||
put ' put ",""SYSTCPIPHOSTNAME"" : ""&SYSTCPIPHOSTNAME"" "; ';
|
|
||||||
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
|
||||||
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
|
||||||
put ' syswarningtext=quote(cats(symget(''SYSWARNINGTEXT''))); ';
|
|
||||||
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
|
|
||||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
|
||||||
put ' length autoexec $512; ';
|
|
||||||
put ' autoexec=quote(urlencode(trim(getoption(''autoexec'')))); ';
|
|
||||||
put ' put '',"AUTOEXEC" : '' autoexec; ';
|
|
||||||
put ' length memsize $32; ';
|
|
||||||
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
|
||||||
put ' memsize=quote(cats(memsize)); ';
|
|
||||||
put ' put '',"MEMSIZE" : '' memsize; ';
|
|
||||||
put ' put "}" @; ';
|
|
||||||
put ' run; ';
|
|
||||||
put '%end; ';
|
|
||||||
put ' ';
|
|
||||||
put '%mend ms_webout; ';
|
|
||||||
put ' ';
|
|
||||||
put '%macro mfs_httpheader(header_name ';
|
|
||||||
put ' ,header_value ';
|
|
||||||
put ')/*/STORE SOURCE*/; ';
|
|
||||||
put '%global sasjs_stpsrv_header_loc; ';
|
|
||||||
put '%local fref fid i; ';
|
|
||||||
put ' ';
|
|
||||||
put '%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do; ';
|
|
||||||
put ' %put &=fref &=sasjs_stpsrv_header_loc; ';
|
|
||||||
put ' %put %str(ERR)OR: %sysfunc(sysmsg()); ';
|
|
||||||
put ' %return; ';
|
|
||||||
put '%end; ';
|
|
||||||
put ' ';
|
|
||||||
put '%let fid=%sysfunc(fopen(&fref,A)); ';
|
|
||||||
put ' ';
|
|
||||||
put '%if &fid=0 %then %do; ';
|
|
||||||
put ' %put %str(ERR)OR: %sysfunc(sysmsg()); ';
|
|
||||||
put ' %return; ';
|
|
||||||
put '%end; ';
|
|
||||||
put ' ';
|
|
||||||
put '%let rc=%sysfunc(fput(&fid,%str(&header_name): %str(&header_value))); ';
|
|
||||||
put '%let rc=%sysfunc(fwrite(&fid)); ';
|
|
||||||
put ' ';
|
|
||||||
put '%let rc=%sysfunc(fclose(&fid)); ';
|
|
||||||
put '%let rc=%sysfunc(filename(&fref)); ';
|
|
||||||
put ' ';
|
|
||||||
put '%mend mfs_httpheader; ';
|
|
||||||
/* WEBOUT END */
|
|
||||||
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO);';
|
|
||||||
put ' %ms_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing';
|
|
||||||
put ' ,showmeta=&showmeta';
|
|
||||||
put ' )';
|
|
||||||
put '%mend;';
|
|
||||||
run;
|
|
||||||
|
|
||||||
/* add precode and code */
|
|
||||||
%local x fref freflist;
|
|
||||||
%let freflist=&precode &code ;
|
|
||||||
%do x=1 %to %sysfunc(countw(&freflist));
|
|
||||||
%let fref=%scan(&freflist,&x);
|
|
||||||
%put &sysmacroname: adding &fref;
|
|
||||||
data _null_;
|
|
||||||
file &sasjsref lrecl=3000 termstr=crlf mod;
|
|
||||||
infile &fref lrecl=3000;
|
|
||||||
input;
|
|
||||||
put _infile_;
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
/* create the web service */
|
|
||||||
%ms_createfile(&path/&name..sas, inref=&sasjsref, mdebug=&mdebug)
|
|
||||||
|
|
||||||
%put ;%put ;%put ;%put ;%put ;%put ;
|
|
||||||
%put &sysmacroname: STP &name successfully created in &path;
|
|
||||||
%put ;%put ;%put ;
|
|
||||||
%put Check it out here:;
|
|
||||||
%put ;%put ;%put ;
|
|
||||||
%put &_sasjs_apiserverurl.&_sasjs_apipath?_PROGRAM=&path/&name;
|
|
||||||
%put ;%put ;%put ;%put ;%put ;%put ;
|
|
||||||
|
|
||||||
%mend ms_createwebservice;
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Deletes a file from SASjs Drive
|
|
||||||
@details Deletes a file from SASjs Drive, if it exists.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
filename stpcode temp;
|
|
||||||
data _null_;
|
|
||||||
file stpcode;
|
|
||||||
put '%put hello world;';
|
|
||||||
run;
|
|
||||||
%ms_createfile(/some/stored/program.sas, inref=stpcode)
|
|
||||||
|
|
||||||
%ms_deletefile(/some/stored/program.sas)
|
|
||||||
|
|
||||||
@param [in] driveloc The full path to the file in SASjs Drive
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro ms_deletefile(driveloc
|
|
||||||
,mdebug=0
|
|
||||||
);
|
|
||||||
|
|
||||||
%local headref;
|
|
||||||
%let headref=%mf_getuniquefileref();
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &headref lrecl=1000;
|
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
|
||||||
input;
|
|
||||||
put "Authorization: Bearer " _infile_;
|
|
||||||
run;
|
|
||||||
|
|
||||||
proc http method='DELETE' headerin=&headref
|
|
||||||
url="&_sasjs_apiserverurl/SASjsApi/drive/file?_filePath=&driveloc";
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
debug level=2;
|
|
||||||
%end;
|
|
||||||
run;
|
|
||||||
|
|
||||||
filename &headref clear;
|
|
||||||
|
|
||||||
%mend ms_deletefile;
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Gets a file from SASjs Drive
|
|
||||||
@details Fetches a file on SASjs Drive and stores it in the output fileref.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
%ms_getfile(/Public/app/dc/services/public/settings.sas, outref=myfile)
|
|
||||||
|
|
||||||
@param [in] driveloc The full path to the file in SASjs Drive
|
|
||||||
@param [out] outref= (msgetfil) The fileref to contain the file.
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro ms_getfile(driveloc
|
|
||||||
,outref=msgetfil
|
|
||||||
,mdebug=0
|
|
||||||
);
|
|
||||||
|
|
||||||
/* use the recfm in a separate fileref to avoid issues with subsequent reads */
|
|
||||||
%local binaryfref floc headref;
|
|
||||||
%let binaryfref=%mf_getuniquefileref();
|
|
||||||
%let headref=%mf_getuniquefileref();
|
|
||||||
%let floc=%sysfunc(pathname(work))/%mf_getuniquename().txt;
|
|
||||||
filename &outref "&floc" lrecl=32767;
|
|
||||||
filename &binaryfref "&floc" recfm=n;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &headref lrecl=1000;
|
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
|
||||||
input;
|
|
||||||
put "Authorization: Bearer " _infile_;
|
|
||||||
run;
|
|
||||||
|
|
||||||
proc http method='GET' out=&binaryfref headerin=&headref
|
|
||||||
url="&_sasjs_apiserverurl/SASjsApi/drive/file?_filePath=&driveloc";
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
debug level=2;
|
|
||||||
%end;
|
|
||||||
run;
|
|
||||||
|
|
||||||
filename &binaryfref clear;
|
|
||||||
filename &headref clear;
|
|
||||||
|
|
||||||
%mend ms_getfile;
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Fetches the list of users from SASjs Server
|
|
||||||
@details Fetches the list of users from SASjs Server and writes them to an
|
|
||||||
output dataset.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
%ms_getusers(outds=userlist)
|
|
||||||
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
|
||||||
@param [out] outds= (work.ms_getusers) This output dataset will contain the
|
|
||||||
list of user accounts. Format:
|
|
||||||
|DISPLAYNAME:$18.|USERNAME:$10.|ID:best.|
|
|
||||||
|---|---|---|
|
|
||||||
|`Super Admin `|`secretuser `|`1`|
|
|
||||||
|`Sabir Hassan`|`sabir`|`2`|
|
|
||||||
|`Mihajlo Medjedovic `|`mihajlo `|`3`|
|
|
||||||
|`Ivor Townsend `|`ivor `|`4`|
|
|
||||||
|`New User `|`newuser `|`5`|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquelibref.sas
|
|
||||||
@li mp_abort.sas
|
|
||||||
|
|
||||||
<h4> Related Files </h4>
|
|
||||||
@li ms_createuser.sas
|
|
||||||
@li ms_getusers.test.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro ms_getusers(
|
|
||||||
outds=work.ms_getusers
|
|
||||||
,mdebug=0
|
|
||||||
);
|
|
||||||
|
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&syscc ne 0)
|
|
||||||
,mac=ms_getusers.sas
|
|
||||||
,msg=%str(syscc=&syscc on macro entry)
|
|
||||||
)
|
|
||||||
|
|
||||||
%local fref0 fref1 libref optval rc msg;
|
|
||||||
%let fref0=%mf_getuniquefileref();
|
|
||||||
%let fref1=%mf_getuniquefileref();
|
|
||||||
%let libref=%mf_getuniquelibref();
|
|
||||||
|
|
||||||
/* avoid sending bom marker to API */
|
|
||||||
%let optval=%sysfunc(getoption(bomfile));
|
|
||||||
options nobomfile;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &fref0 lrecl=1000;
|
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
|
||||||
input;
|
|
||||||
put "Authorization: Bearer " _infile_;
|
|
||||||
put "accept: application/json";
|
|
||||||
run;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
data _null_;
|
|
||||||
infile &fref0;
|
|
||||||
input;
|
|
||||||
put _infile_;
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
proc http method='GET' headerin=&fref0 out=&fref1
|
|
||||||
url="&_sasjs_apiserverurl/SASjsApi/user";
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
debug level=1;
|
|
||||||
%end;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&syscc ne 0)
|
|
||||||
,mac=ms_getusers.sas
|
|
||||||
,msg=%str(Issue submitting GET query to SASjsApi/user)
|
|
||||||
)
|
|
||||||
|
|
||||||
libname &libref JSON fileref=&fref1;
|
|
||||||
|
|
||||||
data &outds;
|
|
||||||
set &libref..root;
|
|
||||||
drop ordinal_root;
|
|
||||||
run;
|
|
||||||
|
|
||||||
|
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&syscc ne 0)
|
|
||||||
,mac=ms_getusers.sas
|
|
||||||
,msg=%str(Issue reading response JSON)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* reset options */
|
|
||||||
options &optval;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
filename &fref0 clear;
|
|
||||||
filename &fref1 clear;
|
|
||||||
libname &libref clear;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%mend ms_getusers;
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Executes a SASjs Server Stored Program
|
|
||||||
@details Runs a Stored Program (using POST method) and extracts the webout and
|
|
||||||
log from the response JSON.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
%ms_runstp(/some/stored/program
|
|
||||||
,debug=131
|
|
||||||
,outref=weboot
|
|
||||||
)
|
|
||||||
|
|
||||||
@param [in] pgm The full path to the Stored Program in SASjs Drive (_program
|
|
||||||
parameter)
|
|
||||||
@param [in] debug= (131) The value to supply to the _debug URL parameter
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
|
||||||
@param [in] inputparams=(_null_) A dataset containing name/value pairs in the
|
|
||||||
following format:
|
|
||||||
|name:$32|value:$10000|
|
|
||||||
|---|---|
|
|
||||||
|stpmacname|some value|
|
|
||||||
|mustbevalidname|can be anything, oops, %abort!!|
|
|
||||||
@param [in] inputfiles= (_null_) A dataset containing fileref/name/filename in
|
|
||||||
the following format:
|
|
||||||
|fileref:$8|name:$32|filename:$256|
|
|
||||||
|---|---|--|
|
|
||||||
|someref|some_name|some_filename.xls|
|
|
||||||
|fref2|another_file|zyx_v2.csv|
|
|
||||||
|
|
||||||
@param [out] outref= (outweb) The output fileref to contain the response JSON
|
|
||||||
(will be created using temp engine)
|
|
||||||
@param [out] outlogds= (_null_) Set to the name of a dataset to contain the
|
|
||||||
log. Table format:
|
|
||||||
|line:$2000|
|
|
||||||
|---|
|
|
||||||
|log line 1|
|
|
||||||
|log line 2|
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquelibref.sas
|
|
||||||
@li mp_abort.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro ms_runstp(pgm
|
|
||||||
,debug=131
|
|
||||||
,inputparams=_null_
|
|
||||||
,inputfiles=_null_
|
|
||||||
,outref=outweb
|
|
||||||
,outlogds=_null_
|
|
||||||
,mdebug=0
|
|
||||||
);
|
|
||||||
%local dbg mainref authref boundary;
|
|
||||||
%let mainref=%mf_getuniquefileref();
|
|
||||||
%let authref=%mf_getuniquefileref();
|
|
||||||
%let boundary=%mf_getuniquename();
|
|
||||||
%if &inputparams=0 %then %let inputparams=_null_;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
%put &sysmacroname entry vars:;
|
|
||||||
%put _local_;
|
|
||||||
%end;
|
|
||||||
%else %let dbg=*;
|
|
||||||
|
|
||||||
|
|
||||||
%mp_abort(iftrue=("&pgm"="")
|
|
||||||
,mac=&sysmacroname
|
|
||||||
,msg=%str(Program not provided)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* avoid sending bom marker to API */
|
|
||||||
%local optval;
|
|
||||||
%let optval=%sysfunc(getoption(bomfile));
|
|
||||||
options nobomfile;
|
|
||||||
|
|
||||||
/* add params */
|
|
||||||
data _null_;
|
|
||||||
file &mainref termstr=crlf lrecl=32767 mod;
|
|
||||||
length line $1000 name $32 value $32767;
|
|
||||||
if _n_=1 then call missing(of _all_);
|
|
||||||
set &inputparams;
|
|
||||||
put "--&boundary";
|
|
||||||
line=cats('Content-Disposition: form-data; name="',name,'"');
|
|
||||||
put line;
|
|
||||||
put ;
|
|
||||||
put value;
|
|
||||||
run;
|
|
||||||
|
|
||||||
/* parse input file list */
|
|
||||||
%local webcount;
|
|
||||||
%let webcount=0;
|
|
||||||
data _null_;
|
|
||||||
set &inputfiles end=last;
|
|
||||||
length fileref $8 name $32 filename $256;
|
|
||||||
call symputx(cats('webref',_n_),fileref,'l');
|
|
||||||
call symputx(cats('webname',_n_),name,'l');
|
|
||||||
call symputx(cats('webfilename',_n_),filename,'l');
|
|
||||||
if last then do;
|
|
||||||
call symputx('webcount',_n_);
|
|
||||||
call missing(of _all_);
|
|
||||||
end;
|
|
||||||
run;
|
|
||||||
|
|
||||||
/* write out the input files */
|
|
||||||
%local i;
|
|
||||||
%do i=1 %to &webcount;
|
|
||||||
data _null_;
|
|
||||||
file &mainref termstr=crlf lrecl=32767 mod;
|
|
||||||
infile &&webref&i lrecl=32767;
|
|
||||||
if _n_ = 1 then do;
|
|
||||||
length line $32767;
|
|
||||||
line=cats(
|
|
||||||
'Content-Disposition: form-data; name="'
|
|
||||||
,"&&webname&i"
|
|
||||||
,'"; filename="'
|
|
||||||
,"&&webfilename&i"
|
|
||||||
,'"'
|
|
||||||
);
|
|
||||||
put "--&boundary";
|
|
||||||
put line;
|
|
||||||
put "Content-Type: text/plain";
|
|
||||||
put ;
|
|
||||||
end;
|
|
||||||
input;
|
|
||||||
put _infile_; /* add the actual file to be sent */
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &mainref termstr=crlf mod;
|
|
||||||
put "--&boundary--";
|
|
||||||
run;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &authref lrecl=1000;
|
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
|
||||||
input;
|
|
||||||
put 'Authorization: Bearer ' _infile_;
|
|
||||||
put "Content-Type: multipart/form-data; boundary=&boundary";
|
|
||||||
run;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
data _null_;
|
|
||||||
infile &authref;
|
|
||||||
input;
|
|
||||||
put _infile_;
|
|
||||||
data _null_;
|
|
||||||
infile &mainref;
|
|
||||||
input;
|
|
||||||
put _infile_;
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
filename &outref temp lrecl=32767;
|
|
||||||
/* prepare request*/
|
|
||||||
proc http method='POST' headerin=&authref in=&mainref out=&outref
|
|
||||||
url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131";
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
debug level=2;
|
|
||||||
%end;
|
|
||||||
run;
|
|
||||||
%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
|
|
||||||
%then %do;
|
|
||||||
data _null_;infile &outref;input;putlog _infile_;run;
|
|
||||||
%end;
|
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
|
|
||||||
,mac=&sysmacroname
|
|
||||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* reset options */
|
|
||||||
options &optval;
|
|
||||||
|
|
||||||
%if &outlogds ne _null_ or &mdebug=1 %then %do;
|
|
||||||
%local dumplib;
|
|
||||||
%let dumplib=%mf_getuniquelibref();
|
|
||||||
libname &dumplib json (&outref);
|
|
||||||
data &outlogds;
|
|
||||||
set &dumplib..log;
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
putlog line=;
|
|
||||||
%end;
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
%put &sysmacroname exit vars:;
|
|
||||||
%put _local_;
|
|
||||||
%end;
|
|
||||||
%else %do;
|
|
||||||
/* clear refs */
|
|
||||||
filename &authref;
|
|
||||||
filename &mainref;
|
|
||||||
%end;
|
|
||||||
%mend ms_runstp;
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Will execute a SASjs web service on SASjs Server
|
|
||||||
@details Prepares the input files and retrieves the resulting datasets from
|
|
||||||
the response JSON.
|
|
||||||
|
|
||||||
@param [in] program The Stored Program endpoint to test
|
|
||||||
@param [in] inputfiles=(0) A list of space seperated fileref:filename pairs as
|
|
||||||
follows:
|
|
||||||
inputfiles=inref:filename inref2:filename2
|
|
||||||
@param [in] inputdatasets= (0) All datasets in this space seperated list are
|
|
||||||
converted into SASJS-formatted CSVs (see mp_ds2csv.sas) files and added to
|
|
||||||
the list of `inputfiles` for ingestion. The dataset will be sent with the
|
|
||||||
same name (no need for a colon modifier).
|
|
||||||
@param [in] inputparams=(0) A dataset containing name/value pairs in the
|
|
||||||
following format:
|
|
||||||
|name:$32|value:$1000|
|
|
||||||
|---|---|
|
|
||||||
|stpmacname|some value|
|
|
||||||
|mustbevalidname|can be anything, oops, %abort!!|
|
|
||||||
|
|
||||||
@param [in] debug= (131) Provide the _debug value to pass to the STP
|
|
||||||
@param [in] mdebug= (0) Set to 1 to provide macro debugging (this macro)
|
|
||||||
@param [out] outlib= (0) Output libref to contain the final tables. Set to
|
|
||||||
0 if the service output is not in JSON format.
|
|
||||||
@param [out] outref= (0) Output fileref to create, to contain the full _webout
|
|
||||||
response.
|
|
||||||
@param [out] outlogds= (_null_) Set to the name of a dataset to contain the
|
|
||||||
log. Table format:
|
|
||||||
|line:$2000|
|
|
||||||
|---|
|
|
||||||
|log line 1|
|
|
||||||
|log line 2|
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
@li mp_abort.sas
|
|
||||||
@li mp_binarycopy.sas
|
|
||||||
@li mp_chop.sas
|
|
||||||
@li mp_ds2csv.sas
|
|
||||||
@li ms_runstp.sas
|
|
||||||
|
|
||||||
<h4> Related Programs </h4>
|
|
||||||
@li mp_testservice.test.sas
|
|
||||||
|
|
||||||
@version 9.4
|
|
||||||
@author Allan Bowe
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro ms_testservice(program,
|
|
||||||
inputfiles=0,
|
|
||||||
inputdatasets=0,
|
|
||||||
inputparams=0,
|
|
||||||
debug=0,
|
|
||||||
mdebug=0,
|
|
||||||
outlib=0,
|
|
||||||
outref=0,
|
|
||||||
outlogds=_null_
|
|
||||||
)/*/STORE SOURCE*/;
|
|
||||||
%local dbg i var ds1 fref1 chopout1 chopout2;
|
|
||||||
%if &mdebug=1 %then %do;
|
|
||||||
%put &sysmacroname entry vars:;
|
|
||||||
%put _local_;
|
|
||||||
%end;
|
|
||||||
%else %let dbg=*;
|
|
||||||
|
|
||||||
/* convert inputdatasets to filerefs */
|
|
||||||
%if "&inputdatasets" ne "0" %then %do;
|
|
||||||
%if %quote(&inputfiles)=0 %then %let inputfiles=;
|
|
||||||
%do i=1 %to %sysfunc(countw(&inputdatasets,%str( )));
|
|
||||||
%let var=%scan(&inputdatasets,&i,%str( ));
|
|
||||||
%local dsref&i;
|
|
||||||
%let dsref&i=%mf_getuniquefileref();
|
|
||||||
%mp_ds2csv(&var,outref=&&dsref&i,headerformat=SASJS)
|
|
||||||
%let inputfiles=&inputfiles &&dsref&i:%scan(&var,-1,.);
|
|
||||||
%end;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
/* parse the filerefs - convert to a dataset */
|
|
||||||
%let ds1=%mf_getuniquename();
|
|
||||||
data &ds1;
|
|
||||||
length fileref $8 name $32 filename $256 var $300;
|
|
||||||
if "&inputfiles" ne "0" then do;
|
|
||||||
webcount=countw("&inputfiles");
|
|
||||||
do i=1 to webcount;
|
|
||||||
var=scan("&inputfiles",i,' ');
|
|
||||||
fileref=scan(var,1,':');
|
|
||||||
name=scan(var,2,':');
|
|
||||||
filename=cats(name,'.csv');
|
|
||||||
output;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
run;
|
|
||||||
|
|
||||||
|
|
||||||
/* execute the STP */
|
|
||||||
%let fref1=%mf_getuniquefileref();
|
|
||||||
|
|
||||||
%ms_runstp(&program
|
|
||||||
,debug=&debug
|
|
||||||
,inputparams=&inputparams
|
|
||||||
,inputfiles=&ds1
|
|
||||||
,outref=&fref1
|
|
||||||
,mdebug=&mdebug
|
|
||||||
,outlogds=&outlogds
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
/* SASjs services have the _webout embedded in wrapper JSON */
|
|
||||||
/* Files can also be very large - so use a dedicated macro to chop it out */
|
|
||||||
%local matchstr1 matchstr2 ;
|
|
||||||
%let matchstr1={"status":"success","_webout":{;
|
|
||||||
%let matchstr2=},"log":[{;
|
|
||||||
%let chopout1=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop1);
|
|
||||||
%let chopout2=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop2);
|
|
||||||
|
|
||||||
%mp_chop("%sysfunc(pathname(&fref1,F))"
|
|
||||||
,matchvar=matchstr1
|
|
||||||
,keep=LAST
|
|
||||||
,matchpoint=END
|
|
||||||
,offset=-1
|
|
||||||
,outfile="&chopout1"
|
|
||||||
,mdebug=&mdebug
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_chop("&chopout1"
|
|
||||||
,matchvar=matchstr2
|
|
||||||
,keep=FIRST
|
|
||||||
,matchpoint=START
|
|
||||||
,offset=1
|
|
||||||
,outfile="&chopout2"
|
|
||||||
,mdebug=&mdebug
|
|
||||||
)
|
|
||||||
|
|
||||||
%if &outlib ne 0 %then %do;
|
|
||||||
libname &outlib json "&chopout2";
|
|
||||||
%end;
|
|
||||||
%if &outref ne 0 %then %do;
|
|
||||||
filename &outref "&chopout2";
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%if &mdebug=0 %then %do;
|
|
||||||
filename &webref clear;
|
|
||||||
filename &fref1 clear;
|
|
||||||
filename &fref2 clear;
|
|
||||||
%end;
|
|
||||||
%else %do;
|
|
||||||
%put &sysmacroname exit vars:;
|
|
||||||
%put _local_;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%mend ms_testservice;
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Send data to/from sasjs/server
|
@brief Send data to/from @sasjs/server
|
||||||
@details This macro should be added to the start of each web service,
|
@details This macro should be added to the start of each web service,
|
||||||
**immediately** followed by a call to:
|
**immediately** followed by a call to:
|
||||||
|
|
||||||
@@ -67,14 +67,13 @@
|
|||||||
%let _webin_name1=&_webin_name;
|
%let _webin_name1=&_webin_name;
|
||||||
%end;
|
%end;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &&_webin_fileref&i termstr=crlf lrecl=32767;
|
infile &&_webin_fileref&i termstr=crlf;
|
||||||
input;
|
input;
|
||||||
call symputx('input_statement',_infile_);
|
call symputx('input_statement',_infile_);
|
||||||
putlog "&&_webin_name&i input statement: " _infile_;
|
putlog "&&_webin_name&i input statement: " _infile_;
|
||||||
stop;
|
stop;
|
||||||
data &&_webin_name&i;
|
data &&_webin_name&i;
|
||||||
infile &&_webin_fileref&i firstobs=2 dsd termstr=crlf encoding='utf-8'
|
infile &&_webin_fileref&i firstobs=2 dsd termstr=crlf encoding='utf-8';
|
||||||
lrecl=32767;
|
|
||||||
input &input_statement;
|
input &input_statement;
|
||||||
%if %str(&_debug) ge 131 %then %do;
|
%if %str(&_debug) ge 131 %then %do;
|
||||||
if _n_<20 then putlog _infile_;
|
if _n_<20 then putlog _infile_;
|
||||||
@@ -85,14 +84,14 @@
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%else %if &action=OPEN %then %do;
|
%else %if &action=OPEN %then %do;
|
||||||
/* fix encoding and ensure enough lrecl */
|
/* fix encoding */
|
||||||
OPTIONS NOBOMFILE lrecl=32767;
|
OPTIONS NOBOMFILE;
|
||||||
|
|
||||||
/* set the header */
|
/* set the header */
|
||||||
%mfs_httpheader(Content-type,application/json)
|
%mfs_httpheader(Content-type,application/json)
|
||||||
|
|
||||||
/* setup json. */
|
/* setup json */
|
||||||
data _null_;file &fref encoding='utf-8' termstr=lf ;
|
data _null_;file &fref encoding='utf-8' termstr=lf;
|
||||||
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
||||||
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
||||||
run;
|
run;
|
||||||
@@ -100,11 +99,6 @@
|
|||||||
%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
|
||||||
)
|
)
|
||||||
@@ -120,7 +114,6 @@
|
|||||||
data _null_;
|
data _null_;
|
||||||
set &tempds;
|
set &tempds;
|
||||||
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
||||||
if not (upcase(name)=:"_DATA_");
|
|
||||||
i+1;
|
i+1;
|
||||||
call symputx(cats('wt',i),name,'l');
|
call symputx(cats('wt',i),name,'l');
|
||||||
call symputx('wtcnt',i,'l');
|
call symputx('wtcnt',i,'l');
|
||||||
@@ -141,20 +134,19 @@
|
|||||||
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
||||||
put "}";
|
put "}";
|
||||||
%end;
|
%end;
|
||||||
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
data _null_; file &fref mod encoding='utf-8' termstr=lf termstr=lf;
|
||||||
put "}";
|
put "}";
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
/* close off json */
|
/* close off json */
|
||||||
data _null_;file &fref mod encoding='utf-8' termstr=lf lrecl=32767;
|
data _null_;file &fref mod encoding='utf-8' termstr=lf;
|
||||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||||
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
||||||
put ",""_DEBUG"" : ""&_debug"" ";
|
put ",""_DEBUG"" : ""&_debug"" ";
|
||||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||||
put ",""SYSCC"" : ""&syscc"" ";
|
put ",""SYSCC"" : ""&syscc"" ";
|
||||||
syserrortext=quote(cats(symget('SYSERRORTEXT')));
|
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
|
||||||
put ',"SYSERRORTEXT" : ' syserrortext;
|
|
||||||
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));
|
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));
|
||||||
put ',"SYSHOSTINFOLONG" : ' SYSHOSTINFOLONG;
|
put ',"SYSHOSTINFOLONG" : ' SYSHOSTINFOLONG;
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
@@ -169,8 +161,7 @@
|
|||||||
put ",""SYSTCPIPHOSTNAME"" : ""&SYSTCPIPHOSTNAME"" ";
|
put ",""SYSTCPIPHOSTNAME"" : ""&SYSTCPIPHOSTNAME"" ";
|
||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
syswarningtext=quote(cats(symget('SYSWARNINGTEXT')));
|
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||||
put ',"SYSWARNINGTEXT" : ' syswarningtext;
|
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||||
length autoexec $512;
|
length autoexec $512;
|
||||||
autoexec=quote(urlencode(trim(getoption('autoexec'))));
|
autoexec=quote(urlencode(trim(getoption('autoexec'))));
|
||||||
|
|||||||
39
tests/crossplatform/mcf_stpsrv_header.test.sas
Normal file
39
tests/crossplatform/mcf_stpsrv_header.test.sas
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mcf_stpsrv_header macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mcf_stpsrv_header.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/stpsrv_header.txt;
|
||||||
|
|
||||||
|
%mcf_stpsrv_header(wrap=YES, insert_cmplib=YES)
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
rc=stpsrv_header('Content-type','application/text');
|
||||||
|
rc=stpsrv_header('Content-disposition',"attachment; filename=file.txt");
|
||||||
|
run;
|
||||||
|
|
||||||
|
%let test1=FAIL;
|
||||||
|
%let test2=FAIL;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
|
input;
|
||||||
|
if _n_=1 and _infile_='Content-type: application/text'
|
||||||
|
then call symputx('test1','PASS');
|
||||||
|
else if _n_=2 & _infile_='Content-disposition: attachment; filename=file.txt'
|
||||||
|
then call symputx('test2','PASS');
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&test1)=%str(PASS)),
|
||||||
|
desc=Check first header line
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&test2)=%str(PASS)),
|
||||||
|
desc=Check second header line
|
||||||
|
)
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mf_deletefile.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_deletefile.sas
|
|
||||||
@li mf_writefile.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%let test1file=&sasjswork/myfile1.txt;
|
|
||||||
|
|
||||||
%mf_writefile(&test1file,l1=some content)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%sysfunc(fileexist(&test1file))=1),
|
|
||||||
desc=Check &test1file exists
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%mf_deletefile(&test1file)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%sysfunc(fileexist(&test1file))=0),
|
|
||||||
desc=Check &test1file no longer exists
|
|
||||||
)
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/**
|
|
||||||
@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
|
|
||||||
)
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mf_getuniquelibref macro
|
|
||||||
@details To test performance you can also use the following macro:
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquelibref.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
/* check valid libs */
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%let libshort=%mf_getuniquelibref(prefix=lib);
|
|
||||||
%mp_assertscope(COMPARE,ignorelist=LIBSHORT)
|
|
||||||
libname &libshort (work);
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&syscc=0),
|
|
||||||
desc=Checking for valid libref &libshort,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
%let lib7=%mf_getuniquelibref(prefix=libref7);
|
|
||||||
libname &lib7 (work);
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&syscc=0),
|
|
||||||
desc=Checking for valid libref &lib7,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
/* check for invalid libs */
|
|
||||||
|
|
||||||
%let lib8=%mf_getuniquelibref(prefix=lib8char);
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&lib8=0),
|
|
||||||
desc=Invalid prefix (8 chars),
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
%let liblong=%mf_getuniquelibref(prefix=invalidlib);
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&liblong=0),
|
|
||||||
desc=Checking for invalid libref (long),
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
%let badlib=%mf_getuniquelibref(prefix=8adlib);
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&badlib=0),
|
|
||||||
desc=Checking for invalid libref (8adlib),
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/**
|
|
||||||
@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
|
|
||||||
)
|
|
||||||
|
|
||||||
@@ -30,12 +30,4 @@
|
|||||||
),
|
),
|
||||||
desc=Checking mf_isint(-1),
|
desc=Checking mf_isint(-1),
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(
|
|
||||||
"%mf_isint()"="0"
|
|
||||||
),
|
|
||||||
desc=Checking mf_isint(),
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
)
|
||||||
@@ -41,7 +41,7 @@ run;
|
|||||||
|
|
||||||
/* multibyte string check */
|
/* multibyte string check */
|
||||||
|
|
||||||
filename tmp2 temp lrecl=500;
|
filename tmp2 temp;
|
||||||
data _null_;
|
data _null_;
|
||||||
file tmp2;
|
file tmp2;
|
||||||
put "'╤', '╔', '╗', '═', '╧', '╚', '╝', '║', '╟', '─', '┼', '║', '╢', '│'";
|
put "'╤', '╔', '╗', '═', '╧', '╚', '╝', '║', '╟', '─', '┼', '║', '╢', '│'";
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mp_chop.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mp_chop.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
/* prep input string */
|
|
||||||
%let src="%sysfunc(pathname(work))/file.txt";
|
|
||||||
%let str=Chop here!;
|
|
||||||
%let out1="%sysfunc(pathname(work))/file1.txt";
|
|
||||||
%let out2="%sysfunc(pathname(work))/file2.txt";
|
|
||||||
%let out3="%sysfunc(pathname(work))/file3.txt";
|
|
||||||
%let out4="%sysfunc(pathname(work))/file4.txt";
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &src;
|
|
||||||
put "startsection&str.endsection";
|
|
||||||
run;
|
|
||||||
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%mp_chop(&src, matchvar=str, keep=FIRST, outfile=&out1)
|
|
||||||
%mp_chop(&src, matchvar=str, keep=LAST, outfile=&out2)
|
|
||||||
%mp_chop(&src, matchvar=str, keep=FIRST, matchpoint=END, outfile=&out3)
|
|
||||||
%mp_chop(&src, matchvar=str, keep=LAST, matchpoint=END, outfile=&out4)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile &out1 lrecl=200;
|
|
||||||
input;
|
|
||||||
call symputx('test1',_infile_);
|
|
||||||
data _null_;
|
|
||||||
infile &out2 lrecl=200;
|
|
||||||
input;
|
|
||||||
call symputx('test2',_infile_);
|
|
||||||
data _null_;
|
|
||||||
infile &out3 lrecl=200;
|
|
||||||
input;
|
|
||||||
call symputx('test3',_infile_);
|
|
||||||
data _null_;
|
|
||||||
infile &out4 lrecl=200;
|
|
||||||
input;
|
|
||||||
call symputx('test4',_infile_);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test1" = "startsection"),
|
|
||||||
desc=Checking keep FIRST matchpoint START
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test2" = "Chop here!endsection"),
|
|
||||||
desc=Checking keep LAST matchpoint START
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test3" = "startsectionChop here!"),
|
|
||||||
desc=Checking keep FIRST matchpoint END
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test4" = "endsection"),
|
|
||||||
desc=Checking keep LAST matchpoint END
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
@brief Testing mp_cntlout.sas macro
|
@brief Testing mp_cntlout.sas macro
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_nobs.sas
|
|
||||||
@li mp_cntlout.sas
|
@li mp_cntlout.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
@li mp_assertscope.sas
|
@li mp_assertscope.sas
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_createwebservice.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
@li mp_createwebservice.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%let path=&mcTestAppLoc/mp_createwebservice;
|
|
||||||
%let name=myservice;
|
|
||||||
%let fref=%mf_getuniquefileref();
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &fref lrecl=3000;
|
|
||||||
put '%put hello world;';
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%mp_createwebservice(path=&path,name=&name,code=&fref,mdebug=&sasjs_mdebug)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -47,18 +47,4 @@ run;
|
|||||||
iftrue=(%mf_nobs(work.mytable3)=2),
|
iftrue=(%mf_nobs(work.mytable3)=2),
|
||||||
desc=Top level returned,
|
desc=Top level returned,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
%mp_dirlist(path=&root/b, outds=work.myTable4)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mf_nobs(work.mytable4)=0),
|
|
||||||
desc=Empty table for empty directory,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_dirlist(path=&root/notexisting, outds=work.myTable5)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mf_nobs(work.mytable5)=0),
|
|
||||||
desc=Empty table for non-existing directory,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
, cards_file= "%sysfunc(pathname(work))/cars.sas"
|
, cards_file= "%sysfunc(pathname(work))/cars.sas"
|
||||||
, showlog=NO
|
, showlog=NO
|
||||||
)
|
)
|
||||||
%inc "%sysfunc(pathname(work))/cars.sas"/source2 lrecl=32767;
|
%inc "%sysfunc(pathname(work))/cars.sas"/source2;
|
||||||
|
|
||||||
proc compare base=sashelp.cars compare=work.test;
|
proc compare base=sashelp.cars compare=work.test;
|
||||||
quit;
|
quit;
|
||||||
@@ -48,7 +48,7 @@ run;
|
|||||||
, append=
|
, append=
|
||||||
)
|
)
|
||||||
|
|
||||||
%inc "%sysfunc(pathname(work))/c2.sas"/source2 lrecl=32767;
|
%inc "%sysfunc(pathname(work))/c2.sas"/source2;
|
||||||
|
|
||||||
proc compare base=work.binarybase compare=work.binarycompare;
|
proc compare base=work.binarybase compare=work.binarycompare;
|
||||||
run;
|
run;
|
||||||
|
|||||||
@@ -10,48 +10,10 @@
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
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(work.class,outds=work.myds)
|
%mp_getmaxvarlengths(sashelp.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),
|
||||||
|
|||||||
@@ -88,50 +88,4 @@ run;
|
|||||||
/* constraint capture at library level is functional - uses first 2 tests */
|
/* constraint capture at library level is functional - uses first 2 tests */
|
||||||
%mp_getpk(work,outds=test4)
|
%mp_getpk(work,outds=test4)
|
||||||
|
|
||||||
%mp_assertdsobs(work.test4,test=ATLEAST 2)
|
%mp_assertdsobs(work.test4,test=ATLEAST 2)
|
||||||
|
|
||||||
/* unique & not null INDEX captured */
|
|
||||||
proc sql;
|
|
||||||
create table work.example5(
|
|
||||||
TX_FROM float format=datetime19.,
|
|
||||||
DD_TYPE char(16),
|
|
||||||
DD_SOURCE char(2048),
|
|
||||||
DD_SHORTDESC char(256)
|
|
||||||
);
|
|
||||||
proc datasets lib=work noprint;
|
|
||||||
modify example5;
|
|
||||||
index create tx_from /nomiss unique;
|
|
||||||
quit;
|
|
||||||
%mp_getpk(work,ds=example5,outds=test5)
|
|
||||||
data _null_;
|
|
||||||
set work.test5;
|
|
||||||
call symputx('test5',pk_fields);
|
|
||||||
run;
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test5"="TX_FROM"),
|
|
||||||
desc=mp_getpk captures single column not null unique index,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
/* unique & not null COMPOSITE INDEX captured */
|
|
||||||
proc sql;
|
|
||||||
create table work.example6(
|
|
||||||
TX_FROM float format=datetime19.,
|
|
||||||
DD_TYPE char(16),
|
|
||||||
DD_SOURCE char(2048),
|
|
||||||
DD_SHORTDESC char(256)
|
|
||||||
);
|
|
||||||
proc datasets lib=work noprint;
|
|
||||||
modify example6;
|
|
||||||
index create pk_6=(tx_from dd_type) /nomiss unique;
|
|
||||||
quit;
|
|
||||||
%mp_getpk(work,ds=example6,outds=test6)
|
|
||||||
data _null_;
|
|
||||||
set work.test6;
|
|
||||||
call symputx('test6',pk_fields);
|
|
||||||
run;
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test6"="TX_FROM DD_TYPE"),
|
|
||||||
desc=mp_getpk captures multiple column not null unique index,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -8,13 +8,6 @@
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
%macro gsubtest();
|
|
||||||
%if "%substr(&sysver.XX,1,4)"="V.04" %then %do;
|
|
||||||
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
|
||||||
%return;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test 1 - simple replace
|
* test 1 - simple replace
|
||||||
*/
|
*/
|
||||||
@@ -70,8 +63,4 @@ run;
|
|||||||
iftrue=("&strcheck2b"="&str2"),
|
iftrue=("&strcheck2b"="&str2"),
|
||||||
desc=Check that multi line replacement was successful (line3),
|
desc=Check that multi line replacement was successful (line3),
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
%mend gsubtest;
|
|
||||||
|
|
||||||
%gsubtest()
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mp_hashdataset.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_nobs.sas
|
|
||||||
@li mp_hashdataset.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
/* test 1 - regular DS */
|
|
||||||
data work.test;
|
|
||||||
set sashelp.vextfl;
|
|
||||||
missval=.;
|
|
||||||
misscval='';
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%mp_hashdataset(test)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&syscc=0),
|
|
||||||
desc=Regular test works,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_hashdataset(test,outds=work.test2)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&syscc=0),
|
|
||||||
desc=hash with output runs without errors,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mf_nobs(work.test2)=1),
|
|
||||||
desc=output has 1 row,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
data work.test3a;
|
|
||||||
set work.test;
|
|
||||||
stop;
|
|
||||||
run;
|
|
||||||
%mp_hashdataset(test3a,outds=work.test3b)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&syscc=0),
|
|
||||||
desc=hash with zero-row input runs without errors,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mf_nobs(work.test3b)=1),
|
|
||||||
desc=test 3 output has 1 row,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mp_jsonout.sas macro with non-standard chars
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mp_jsonout.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
filename webref temp;
|
|
||||||
|
|
||||||
data demo;
|
|
||||||
do x='"','0A'x,'0D'x,'09'x,'00'x,'0E'x,'0F'x,'01'x,'02'x,'10'x,'11'x,'\';
|
|
||||||
output;
|
|
||||||
end;
|
|
||||||
run;
|
|
||||||
%mp_jsonout(OPEN,jref=webref)
|
|
||||||
%mp_jsonout(OBJ,demo,jref=webref)
|
|
||||||
%mp_jsonout(CLOSE,jref=webref)
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile webref;
|
|
||||||
input;
|
|
||||||
putlog _infile_;
|
|
||||||
run;
|
|
||||||
|
|
||||||
libname web JSON fileref=webref;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&syscc=0),
|
|
||||||
desc=Checking for error condition with special chars export,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
data _null_;
|
|
||||||
set work.demo (in=start) web.demo (in=end);
|
|
||||||
put (_all_)(=);
|
|
||||||
run;
|
|
||||||
proc sql;
|
|
||||||
describe table work.demo;
|
|
||||||
describe table web.demo;
|
|
||||||
*/
|
|
||||||
|
|
||||||
proc compare base=work.demo compare=web.demo(keep=x);
|
|
||||||
quit;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&sysinfo=0),
|
|
||||||
desc=Returned json is identical to input table for all special chars,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -3,7 +3,6 @@
|
|||||||
@brief Testing mp_loadformat.sas macro
|
@brief Testing mp_loadformat.sas macro
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mddl_dc_difftable.sas
|
|
||||||
@li mp_loadformat.sas
|
@li mp_loadformat.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
@li mp_assertscope.sas
|
@li mp_assertscope.sas
|
||||||
@@ -13,8 +12,6 @@
|
|||||||
/* prep format catalog */
|
/* prep format catalog */
|
||||||
libname perm (work);
|
libname perm (work);
|
||||||
|
|
||||||
%mddl_dc_difftable(libds=perm.audit)
|
|
||||||
|
|
||||||
data work.loadfmts;
|
data work.loadfmts;
|
||||||
length fmtname $32;
|
length fmtname $32;
|
||||||
eexcl='Y';
|
eexcl='Y';
|
||||||
@@ -52,7 +49,7 @@ run;
|
|||||||
%mp_loadformat(perm.testcat
|
%mp_loadformat(perm.testcat
|
||||||
,work.stagedata
|
,work.stagedata
|
||||||
,loadtarget=YES
|
,loadtarget=YES
|
||||||
,auditlibds=perm.audit
|
,auditlibds=0
|
||||||
,locklibds=0
|
,locklibds=0
|
||||||
,delete_col=deleteme
|
,delete_col=deleteme
|
||||||
,outds_add=add_test1
|
,outds_add=add_test1
|
||||||
@@ -76,18 +73,4 @@ run;
|
|||||||
iftrue=(%mf_nobs(mod_test1)=100),
|
iftrue=(%mf_nobs(mod_test1)=100),
|
||||||
desc=Test 1 - mod obs,
|
desc=Test 1 - mod obs,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mf_nobs(perm.audit)=7329),
|
|
||||||
desc=Test 1 - audit table updated,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
data work.difftest;
|
|
||||||
set perm.audit;
|
|
||||||
where is_diff=1;
|
|
||||||
run;
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mf_nobs(work.difftest)>0),
|
|
||||||
desc=Test 1 - diffs were found,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mp_replace.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mp_replace.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
%let test1="&sasjswork/file.txt";
|
|
||||||
%let str=replace/me;
|
|
||||||
%let rep=with/this;
|
|
||||||
data _null_;
|
|
||||||
file &test1;
|
|
||||||
put 'blahblah';
|
|
||||||
put "blahblah&str.blah";
|
|
||||||
put 'blahblahblah';
|
|
||||||
run;
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%mp_replace(&test1, findvar=str, replacevar=rep)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
data _null_;
|
|
||||||
infile &test1;
|
|
||||||
input;
|
|
||||||
if _n_=2 then call symputx('test1result',_infile_);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test1result" = "blahblah&rep.blah"),
|
|
||||||
desc=Checking first replace,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%let test2="&sasjswork/file2.txt";
|
|
||||||
%let str=%str(replacewith trailing spaces );
|
|
||||||
%let rep=%str( with more spaces );
|
|
||||||
data _null_;
|
|
||||||
file &test2 lrecl=500;
|
|
||||||
put 'blahblah';
|
|
||||||
put "blahblah&str.blah&str. replace &str.X";
|
|
||||||
put "blahbreplacewith&str.spacesahblah";
|
|
||||||
run;
|
|
||||||
%mp_replace(&test2, findvar=str, replacevar=rep)
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile &test2 lrecl=500;
|
|
||||||
input;
|
|
||||||
if _n_=2 then call symputx('test2resulta',_infile_);
|
|
||||||
if _n_=3 then call symputx('test2resultb',_infile_);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test2resulta" = "blahblah&rep.blah&rep. replace &rep.X"),
|
|
||||||
desc=Checking second replace 2nd row,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test2resultb" = "blahbreplacewith&rep.spacesahblah"),
|
|
||||||
desc=Checking second replace 3rd row,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%let test3="&sasjswork/file3.txt";
|
|
||||||
%let str=%str(replace.string.with.dots );
|
|
||||||
%let rep=%str( more.dots);
|
|
||||||
data _null_;
|
|
||||||
file &test3 lrecl=500;
|
|
||||||
put 'blahblah';
|
|
||||||
put "blahblah&str.blah&str. replace &str.X";
|
|
||||||
put "blahbreplacewith&str.spacesahblah";
|
|
||||||
run;
|
|
||||||
%mp_replace(&test3, findvar=str, replacevar=rep)
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile &test3 lrecl=500;
|
|
||||||
input;
|
|
||||||
if _n_=2 then call symputx('test3resulta',_infile_);
|
|
||||||
if _n_=3 then call symputx('test3resultb',_infile_);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test3resulta" = "blahblah&rep.blah&rep. replace &rep.X"),
|
|
||||||
desc=Checking third replace 2nd row (dots),
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test3resultb" = "blahbreplacewith&rep.spacesahblah"),
|
|
||||||
desc=Checking third replace 3rd row (dots),
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -55,28 +55,37 @@ run;
|
|||||||
outlib=testlib1,
|
outlib=testlib1,
|
||||||
outref=test1
|
outref=test1
|
||||||
)
|
)
|
||||||
%let test1=FAIL;
|
|
||||||
data _null_;
|
|
||||||
set testlib1.somedata1;
|
|
||||||
if x=1 and y=' t"w"o' and z="Z" then call symputx('test1','PASS');
|
|
||||||
putlog (_all_)(=);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%let test2=FAIL;
|
%global test1a test1b test1c test1d;
|
||||||
data _null_;
|
data _null_;
|
||||||
set testlib1.somedata2;
|
infile test1;
|
||||||
if x=1 and y=' t"w"o' and z="Z" then call symputx('test2','PASS');
|
input;
|
||||||
putlog (_all_)(=);
|
putlog _n_ _infile_;
|
||||||
|
if _infile_=', "somedata1":' then call symputx('test1a','PASS');
|
||||||
|
if _infile_='{"X":1 ,"Y":" t\"w\"o" ,"Z":"Z" }' then
|
||||||
|
call symputx('test1b','PASS');
|
||||||
|
if _infile_='], "somedata2":' then call symputx('test1c','PASS');
|
||||||
|
if _infile_='{"X":1 ,"Y":" t\"w\"o" ,"Z":"Z" }' then
|
||||||
|
call symputx('test1d','PASS');
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&test1=PASS),
|
iftrue=(&test1a=PASS),
|
||||||
desc=somedata1 created correctly,
|
desc=Test 1 table 1 name,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&test2=PASS),
|
iftrue=(&test1b=PASS),
|
||||||
desc=somedata2 created correctly,
|
desc=Test 1 table 1 values,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&test1c=PASS),
|
||||||
|
desc=Test 1 table 2 name,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&test1d=PASS),
|
||||||
|
desc=Test 1 table 2 values,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mm_webout macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mm_spkexport.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_as
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
%* create sample text file as input to the macro;
|
|
||||||
filename tmp temp;
|
|
||||||
data _null_;
|
|
||||||
file tmp;
|
|
||||||
put '%let mmxuser="sasdemo";';
|
|
||||||
put '%let mmxpass="Mars321";';
|
|
||||||
run;
|
|
||||||
|
|
||||||
filename myref "%sysfunc(pathname(work))/mmxexport.sh"
|
|
||||||
permission='A::u::rwx,A::g::r-x,A::o::---';
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%mm_spkexport(metaloc=%str(/Shared Data)
|
|
||||||
,outref=myref
|
|
||||||
,secureref=tmp
|
|
||||||
,cmdoutloc=%str(/tmp)
|
|
||||||
)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile tmp;
|
|
||||||
input;
|
|
||||||
putlog _infile_;
|
|
||||||
call symputx('nobs',_n_);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&nobs>2),
|
|
||||||
desc=Check if content was created
|
|
||||||
)
|
|
||||||
@@ -5,17 +5,12 @@
|
|||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mfs_httpheader.sas
|
@li mfs_httpheader.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%let orig_sasjs_stpsrv_header_loc=&sasjs_stpsrv_header_loc;
|
|
||||||
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
|
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
%mfs_httpheader(Content-type,application/csv)
|
||||||
%mfs_httpheader(Content-Type,application/csv)
|
|
||||||
%mp_assertscope(COMPARE,ignorelist=sasjs_stpsrv_header_loc)
|
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile "&sasjs_stpsrv_header_loc";
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
input;
|
input;
|
||||||
@@ -28,12 +23,12 @@ run;
|
|||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=("&test1"="Content-Type: application/csv"),
|
iftrue=("&test1"="Content-type: application/csv"),
|
||||||
desc=Checking line was created,
|
desc=Checking line was created,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
%mfs_httpheader(Content-Type,application/text)
|
%mfs_httpheader(Content-type,application/text)
|
||||||
%let test2=0;
|
%let test2=0;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile "&sasjs_stpsrv_header_loc";
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
@@ -47,11 +42,7 @@ run;
|
|||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=("&test2"="Content-Type: application/text"),
|
iftrue=("&test2"="Content-type: application/text"),
|
||||||
desc=Checking line was created,
|
desc=Checking line was created,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
/* reset header so the test will pass */
|
|
||||||
%let sasjs_stpsrv_header_loc=&orig_sasjs_stpsrv_header_loc;
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_createfile.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li ms_createfile.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
filename stpcode temp;
|
|
||||||
data _null_;
|
|
||||||
file stpcode;
|
|
||||||
put '%put hello world;';
|
|
||||||
run;
|
|
||||||
|
|
||||||
options mprint;
|
|
||||||
%let fname=%mf_getuniquename();
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%ms_createfile(/sasjs/tests/&fname..sas
|
|
||||||
,inref=stpcode
|
|
||||||
,mdebug=1
|
|
||||||
)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_createuser.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
@li ms_createuser.sas
|
|
||||||
@li ms_getusers.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%let user=%substr(%mf_getuniquename(),1,8);
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%ms_createuser(&user,passwrd,outds=test1,mdebug=&sasjs_mdebug)
|
|
||||||
%mp_assertscope(COMPARE
|
|
||||||
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
|
|
||||||
)
|
|
||||||
|
|
||||||
%let id=0;
|
|
||||||
data _null_;
|
|
||||||
set work.test1;
|
|
||||||
call symputx('id',id);
|
|
||||||
run;
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&id>0),
|
|
||||||
desc=Checking that user was created with an ID,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
/* double check by querying the list of users */
|
|
||||||
%ms_getusers(outds=work.test2)
|
|
||||||
%let checkid=0;
|
|
||||||
data _null_;
|
|
||||||
set work.test2;
|
|
||||||
where username="&user";
|
|
||||||
call symputx('checkid',id);
|
|
||||||
run;
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&checkid=&id),
|
|
||||||
desc=Checking that fetched user exists and has the same ID,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_createwebservice.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquefileref.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
@li ms_createwebservice.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%let path=&mcTestAppLoc/ms_createwebservice;
|
|
||||||
%let name=myservice;
|
|
||||||
%let fref=%mf_getuniquefileref();
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
file &fref lrecl=3000;
|
|
||||||
put '%put hello world;';
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%ms_createwebservice(path=&path,name=&name,code=&fref,mdebug=&sasjs_mdebug)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_deletefile.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li ms_createfile.sas
|
|
||||||
@li ms_deletefile.sas
|
|
||||||
@li ms_getfile.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
/* first make a remote file */
|
|
||||||
filename stpcode temp;
|
|
||||||
%let fname=%mf_getuniquename();
|
|
||||||
data _null_;
|
|
||||||
file stpcode;
|
|
||||||
put "data &fname;run;";
|
|
||||||
run;
|
|
||||||
%ms_createfile(/sasjs/tests/&fname..sas
|
|
||||||
,inref=stpcode
|
|
||||||
,mdebug=1
|
|
||||||
)
|
|
||||||
|
|
||||||
%ms_getfile(/sasjs/tests/&fname..sas,outref=testref)
|
|
||||||
|
|
||||||
%let test1=0;
|
|
||||||
data _null_;
|
|
||||||
infile testref;
|
|
||||||
input;
|
|
||||||
call symputx('test1',_infile_);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test1"="data &fname;run;"),
|
|
||||||
desc=Make sure the file was created,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%ms_deletefile(/sasjs/tests/&fname..sas,mdebug=1)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
%ms_getfile(/sasjs/tests/&fname..sas,outref=testref2)
|
|
||||||
|
|
||||||
%let test2=0;
|
|
||||||
data _null_;
|
|
||||||
infile testref2;
|
|
||||||
input;
|
|
||||||
call symputx('test2',_infile_);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test2"="%str(Err)or: File doesn't exist."),
|
|
||||||
desc=Make sure the file was deleted,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_getfile.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li ms_createfile.sas
|
|
||||||
@li ms_getfile.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
/* first make a remote file */
|
|
||||||
filename stpcode temp;
|
|
||||||
%let fname=%mf_getuniquename();
|
|
||||||
data _null_;
|
|
||||||
file stpcode;
|
|
||||||
put "data &fname;run;";
|
|
||||||
run;
|
|
||||||
%ms_createfile(/sasjs/tests/&fname..sas
|
|
||||||
,inref=stpcode
|
|
||||||
,mdebug=1
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%ms_getfile(/sasjs/tests/&fname..sas,outref=testref)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
%let test1=0;
|
|
||||||
data _null_;
|
|
||||||
infile testref;
|
|
||||||
input;
|
|
||||||
call symputx('test1',_infile_);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test1"="data &fname;run;"),
|
|
||||||
desc=Checking file was created with the same content,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_getusers.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li ms_getusers.sas
|
|
||||||
@li mp_assertdsobs.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%ms_getusers(outds=work.test1,mdebug=&sasjs_mdebug)
|
|
||||||
%mp_assertscope(COMPARE
|
|
||||||
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assertdsobs(work.test1,test=ATLEAST 1)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_runstp.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_getuniquename.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
@li ms_createfile.sas
|
|
||||||
@li ms_runstp.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
/* first, create an STP to run */
|
|
||||||
filename stpcode temp;
|
|
||||||
data _null_;
|
|
||||||
file stpcode;
|
|
||||||
put '%put hello world;';
|
|
||||||
put '%put _all_;';
|
|
||||||
run;
|
|
||||||
|
|
||||||
options mprint;
|
|
||||||
%let fname=%mf_getuniquename();
|
|
||||||
|
|
||||||
%ms_createfile(/sasjs/tests/&fname..sas
|
|
||||||
,inref=stpcode
|
|
||||||
,mdebug=1
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%ms_runstp(/sasjs/tests/&fname
|
|
||||||
,debug=131
|
|
||||||
,outref=weboot
|
|
||||||
)
|
|
||||||
%mp_assertscope(COMPARE)
|
|
||||||
|
|
||||||
libname webeen json (weboot);
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile weboot;
|
|
||||||
input;
|
|
||||||
putlog _infile_;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%let test1=0;
|
|
||||||
data work.log;
|
|
||||||
set webeen.log;
|
|
||||||
put (_all_)(=);
|
|
||||||
if _n_>10 then call symputx('test1',1);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=("&test1"="1"),
|
|
||||||
desc=Checking log was returned,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing ms_testservice.sas macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li ms_createwebservice.sas
|
|
||||||
@li ms_testservice.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
filename ft15f001 temp;
|
|
||||||
parmcards4;
|
|
||||||
%put Initialising sendObj: ;
|
|
||||||
%put _all_;
|
|
||||||
%webout(FETCH)
|
|
||||||
%webout(OPEN)
|
|
||||||
%macro x();
|
|
||||||
%if (%symexist(sasjs_tables) and %length(&sasjs_tables)>0)
|
|
||||||
%then %do i=1 %to %sysfunc(countw(&sasjs_tables));
|
|
||||||
%let table=%scan(&sasjs_tables,&i);
|
|
||||||
%webout(OBJ,&table,missing=STRING)
|
|
||||||
%end;
|
|
||||||
%else %do i=1 %to &_webin_file_count;
|
|
||||||
%webout(OBJ,&&_webin_name&i,missing=STRING)
|
|
||||||
%end;
|
|
||||||
%mend x; %x()
|
|
||||||
%webout(CLOSE)
|
|
||||||
;;;;
|
|
||||||
%put creating web service: &mcTestAppLoc/services;
|
|
||||||
%ms_createwebservice(
|
|
||||||
path=&mcTestAppLoc/services,
|
|
||||||
name=sendObj,
|
|
||||||
mdebug=&sasjs_mdebug
|
|
||||||
)
|
|
||||||
%put created web service: &mcTestAppLoc/services;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&syscc=0),
|
|
||||||
desc=No errors after service creation,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test 1 - send a dataset
|
|
||||||
*/
|
|
||||||
data work.somedata1 work.somedata2;
|
|
||||||
x=1;
|
|
||||||
y=' t"w"o';
|
|
||||||
z=.z;
|
|
||||||
label x='x factor';
|
|
||||||
output;
|
|
||||||
run;
|
|
||||||
|
|
||||||
%ms_testservice(&mcTestAppLoc/services/sendObj,
|
|
||||||
inputdatasets=work.somedata1 work.somedata2,
|
|
||||||
debug=log,
|
|
||||||
mdebug=1,
|
|
||||||
outlib=testlib1,
|
|
||||||
outref=test1
|
|
||||||
)
|
|
||||||
|
|
||||||
%let test1=FAIL;
|
|
||||||
data _null_;
|
|
||||||
set testlib1.somedata1;
|
|
||||||
if x=1 and y=' t"w"o' and z="Z" then call symputx('test1','PASS');
|
|
||||||
putlog (_all_)(=);
|
|
||||||
run;
|
|
||||||
|
|
||||||
%let test2=FAIL;
|
|
||||||
data _null_;
|
|
||||||
set testlib1.somedata2;
|
|
||||||
if x=1 and y=' t"w"o' and z="Z" then call symputx('test2','PASS');
|
|
||||||
putlog (_all_)(=);
|
|
||||||
run;
|
|
||||||
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&test1=PASS),
|
|
||||||
desc=somedata1 created correctly,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&test2=PASS),
|
|
||||||
desc=somedata2 created correctly,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -3,34 +3,27 @@
|
|||||||
@brief init file for tests
|
@brief init file for tests
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_uid.sas
|
|
||||||
@li mp_init.sas
|
@li mp_init.sas
|
||||||
@li ms_webout.sas
|
@li mv_webout.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
/* location in metadata or SAS Drive for temporary files */
|
/* location in metadata or SAS Drive for temporary files */
|
||||||
%let mcTestAppLoc=/tmp/tests/sasjs/core/%mf_uid();
|
%let mcTestAppLoc=/Public/temp/macrocore;
|
||||||
|
|
||||||
/* set defaults */
|
/* set defaults */
|
||||||
%mp_init()
|
%mp_init()
|
||||||
|
|
||||||
options lrecl=80;
|
%global _debug;
|
||||||
|
|
||||||
%global _debug sasjs_mdebug;
|
|
||||||
|
|
||||||
%let sasjs_mdebug=0;
|
|
||||||
|
|
||||||
%macro loglevel();
|
%macro loglevel();
|
||||||
%if "&_debug"="2477" or "&_debug"="fields,log,trace" or "&_debug"="131"
|
%if "&_debug"="2477" or "&_debug"="fields,log,trace" %then %do;
|
||||||
%then %do;
|
|
||||||
%put debug mode activated;
|
%put debug mode activated;
|
||||||
options mprint mprintnest;
|
options mprint mprintnest;
|
||||||
%let sasjs_mdebug=1;
|
|
||||||
%end;
|
%end;
|
||||||
%mend loglevel;
|
%mend loglevel;
|
||||||
|
|
||||||
%loglevel()
|
%loglevel()
|
||||||
|
|
||||||
%put Initialised &_program;
|
%put Initialised &_program;
|
||||||
%put _all_;
|
%put _all_;
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&syscc=0),
|
iftrue=(&syscc=0),
|
||||||
desc=Checking final err condition,
|
desc=Checking final error condition,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mv_deleteviyafolder macro function
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_uid.sas
|
|
||||||
@li mfv_existfolder.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
@li mp_assertscope.sas
|
|
||||||
@li mv_createfolder.sas
|
|
||||||
@li mv_deleteviyafolder.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
options mprint sgen;
|
|
||||||
|
|
||||||
%let folder=%mf_uid();
|
|
||||||
%let tgtfolder=&mcTestAppLoc/temp/&folder;
|
|
||||||
|
|
||||||
/* create a folder */
|
|
||||||
%mv_createfolder(path=&tgtfolder)
|
|
||||||
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mfv_existfolder(&tgtfolder)=1),
|
|
||||||
desc=Check if created folder exists
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%mv_deleteviyafolder(path=&tgtfolder)
|
|
||||||
/* ignore proc json vars */
|
|
||||||
%mp_assertscope(COMPARE
|
|
||||||
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADP2LEN MCLIB0_JADVLEN MCLIB2_JADP1LEN
|
|
||||||
MCLIB2_JADVLEN
|
|
||||||
)
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mfv_existfolder(&tgtfolder)=0),
|
|
||||||
desc=Check if deleted folder is gone
|
|
||||||
)
|
|
||||||
|
|
||||||
/* delete folder with content */
|
|
||||||
%mv_createfolder(path=&tgtfolder/content/and/stuff)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mfv_existfolder(&tgtfolder/content/and/stuff)=1),
|
|
||||||
desc=Check if folder with content exists
|
|
||||||
)
|
|
||||||
%mv_deleteviyafolder(path=&tgtfolder)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%mfv_existfolder(&tgtfolder)=0),
|
|
||||||
desc=Check if deleted folder with subfolders is gone
|
|
||||||
)
|
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
@li mp_assertscope.sas
|
|
||||||
@li mv_createjob.sas
|
@li mv_createjob.sas
|
||||||
@li mv_getjobcode.sas
|
@li mv_getjobcode.sas
|
||||||
|
|
||||||
@@ -28,17 +27,11 @@ run;
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* now get the code back */
|
/* now get the code back */
|
||||||
%mp_assertscope(SNAPSHOT)
|
|
||||||
%mv_getjobcode(
|
%mv_getjobcode(
|
||||||
path=&mcTestAppLoc/services/temp,
|
path=&mcTestAppLoc/services/temp,
|
||||||
name=some_job,
|
name=some_job,
|
||||||
outref=mycode
|
outref=mycode
|
||||||
)
|
)
|
||||||
/* exclude automatic proc json macro variables from scope check */
|
|
||||||
%mp_assertscope(COMPARE,
|
|
||||||
ignorelist=MCLIB2_JADP1LEN MCLIB2_JADP2LEN MCLIB2_JADPNUM MCLIB2_JADVLEN
|
|
||||||
MCLIB2_JADP3LEN
|
|
||||||
)
|
|
||||||
|
|
||||||
%let diditexist=NO;
|
%let diditexist=NO;
|
||||||
data work.test1;
|
data work.test1;
|
||||||
@@ -53,4 +46,4 @@ run;
|
|||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&diditexist=NO),
|
iftrue=(&diditexist=NO),
|
||||||
desc=Check if the code that was sent was successfully retrieved
|
desc=Check if the code that was sent was successfully retrieved
|
||||||
)
|
)
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
@li mp_assertscope.sas
|
|
||||||
@li mv_createjob.sas
|
@li mv_createjob.sas
|
||||||
@li mv_jobexecute.sas
|
@li mv_jobexecute.sas
|
||||||
@li mv_jobwaitfor.sas
|
@li mv_jobwaitfor.sas
|
||||||
@@ -50,12 +49,8 @@ data _null_;
|
|||||||
run;
|
run;
|
||||||
|
|
||||||
%* Finally, fetch the log;
|
%* Finally, fetch the log;
|
||||||
%mp_assertscope(SNAPSHOT)
|
%mv_getjoblog(uri=%str(&uri),outref=mylog)
|
||||||
%mv_getjoblog(uri=%str(&uri),outref=mylog,mdebug=1)
|
|
||||||
/* ignore auto proc json vars */
|
|
||||||
%mp_assertscope(COMPARE
|
|
||||||
,ignorelist=MCLIB2_JADP2LEN MCLIB2_JADPNUM MCLIB2_JADVLEN
|
|
||||||
)
|
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile mylog end=eof;
|
infile mylog end=eof;
|
||||||
@@ -72,4 +67,4 @@ run;
|
|||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(%str(&found)=1),
|
iftrue=(%str(&found)=1),
|
||||||
desc=Check if the log was still fetched even though endsas was submitted
|
desc=Check if the log was still fetched even though endsas was submitted
|
||||||
)
|
)
|
||||||
@@ -1,33 +1,15 @@
|
|||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Testing mv_webout macro
|
@brief Testing mm_webout macro
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mv_webout.sas
|
@li mv_webout.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
@li mp_assertdsobs.sas
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
/* testing FETCHing (WEB approach) */
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
call symputx('sasjs1data','area:$char4.'!!'0d0a'x!!'Adak');
|
|
||||||
call symputx('sasjs_tables','areas');
|
|
||||||
run;
|
|
||||||
%put &=sasjs1data;
|
|
||||||
|
|
||||||
%mv_webout(FETCH)
|
|
||||||
|
|
||||||
%mp_assertdsobs(work.areas,
|
|
||||||
desc=Test input table has 1 row,
|
|
||||||
test=EQUALS 1,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
%let fref=%mf_getuniquefileref();
|
%let fref=%mf_getuniquefileref();
|
||||||
%global _metaperson;
|
%global _metaperson;
|
||||||
data some datasets;
|
data some datasets;
|
||||||
@@ -56,4 +38,4 @@ run;
|
|||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(%str(&checkval)=%str(&sysvlong)),
|
iftrue=(%str(&checkval)=%str(&sysvlong)),
|
||||||
desc=Check if the sysvlong value was created
|
desc=Check if the sysvlong value was created
|
||||||
)
|
)
|
||||||
@@ -247,7 +247,7 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '%if &action=OPEN %then %do; ';
|
put '%if &action=OPEN %then %do; ';
|
||||||
put ' options nobomfile; ';
|
put ' options nobomfile; ';
|
||||||
put ' data _null_;file &jref encoding=''utf-8'' lrecl=200; ';
|
put ' data _null_;file &jref encoding=''utf-8'' ; ';
|
||||||
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
@@ -376,23 +376,12 @@ data _null_;
|
|||||||
put ' format _numeric_ bart.; ';
|
put ' format _numeric_ bart.; ';
|
||||||
put ' %do i=1 %to &numcols; ';
|
put ' %do i=1 %to &numcols; ';
|
||||||
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
||||||
put ' if findc(&&name&i,''"\''!!''0A0D09000E0F01021011''x) then do; ';
|
put ' &&name&i=''"''!!trim(prxchange(''s/"/\"/'',-1, ';
|
||||||
put ' &&name&i=''"''!!trim( ';
|
put ' prxchange(''s/''!!''0A''x!!''/\n/'',-1, ';
|
||||||
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
|
put ' prxchange(''s/''!!''0D''x!!''/\r/'',-1, ';
|
||||||
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
|
put ' prxchange(''s/''!!''09''x!!''/\t/'',-1, ';
|
||||||
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
|
put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) ';
|
||||||
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
|
put ' )))))!!''"''; ';
|
||||||
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
|
|
||||||
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
|
|
||||||
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
|
|
||||||
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
|
|
||||||
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
|
|
||||||
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
|
|
||||||
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
|
|
||||||
put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) ';
|
|
||||||
put ' ))))))))))))!!''"''; ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' else &&name&i=quote(cats(&&name&i)); ';
|
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
@@ -458,25 +447,6 @@ data _null_;
|
|||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%mend mp_jsonout; ';
|
put '%mend mp_jsonout; ';
|
||||||
put ' ';
|
|
||||||
put '%macro mf_getuser(type=META ';
|
|
||||||
put ')/*/STORE SOURCE*/; ';
|
|
||||||
put ' %local user metavar; ';
|
|
||||||
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
|
||||||
put ' %else %let metavar=_metaperson; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
|
||||||
put ' %else %if %symexist(&metavar) %then %do; ';
|
|
||||||
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
|
||||||
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
|
||||||
put ' /* but be sure to quote in case of usernames with commas */ ';
|
|
||||||
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %let user=&sysuserid; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %quote(&user) ';
|
|
||||||
put ' ';
|
|
||||||
put '%mend mf_getuser; ';
|
|
||||||
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL ';
|
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL ';
|
||||||
put ' ,showmeta=NO ';
|
put ' ,showmeta=NO ';
|
||||||
put '); ';
|
put '); ';
|
||||||
@@ -484,7 +454,7 @@ data _null_;
|
|||||||
put ' sasjs_tables SYS_JES_JOB_URI; ';
|
put ' sasjs_tables SYS_JES_JOB_URI; ';
|
||||||
put '%if %index("&_debug",log) %then %let _debug=131; ';
|
put '%if %index("&_debug",log) %then %let _debug=131; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%local i tempds table; ';
|
put '%local i tempds; ';
|
||||||
put '%let action=%upcase(&action); ';
|
put '%let action=%upcase(&action); ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%if &action=FETCH %then %do; ';
|
put '%if &action=FETCH %then %do; ';
|
||||||
@@ -499,35 +469,60 @@ data _null_;
|
|||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' /* if the sasjs_tables param is passed, we expect param based upload */ ';
|
put ' /* if the sasjs_tables param is passed, we expect param based upload */ ';
|
||||||
put ' %if %length(&sasjs_tables.X)>1 %then %do; ';
|
put ' %if %length(&sasjs_tables.XX)>2 %then %do; ';
|
||||||
|
put ' filename _sasjs "%sysfunc(pathname(work))/sasjs.lua"; ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' file _sasjs; ';
|
||||||
|
put ' put ''s=sas.symget("sasjs_tables")''; ';
|
||||||
|
put ' put ''if(s:sub(1,7) == "%nrstr(")''; ';
|
||||||
|
put ' put ''then''; ';
|
||||||
|
put ' put '' tablist=s:sub(8,s:len()-1)''; ';
|
||||||
|
put ' put ''else''; ';
|
||||||
|
put ' put '' tablist=s''; ';
|
||||||
|
put ' put ''end''; ';
|
||||||
|
put ' put ''for i = 1,sas.countw(tablist) ''; ';
|
||||||
|
put ' put ''do ''; ';
|
||||||
|
put ' put '' tab=sas.scan(tablist,i)''; ';
|
||||||
|
put ' put '' sasdata=""''; ';
|
||||||
|
put ' put '' if (sas.symexist("sasjs"..i.."data0")==0)''; ';
|
||||||
|
put ' put '' then''; ';
|
||||||
|
put ' /* TODO - condense this logic */ ';
|
||||||
|
put ' put '' s=sas.symget("sasjs"..i.."data")''; ';
|
||||||
|
put ' put '' if(s:sub(1,7) == "%nrstr(")''; ';
|
||||||
|
put ' put '' then''; ';
|
||||||
|
put ' put '' sasdata=s:sub(8,s:len()-1)''; ';
|
||||||
|
put ' put '' else''; ';
|
||||||
|
put ' put '' sasdata=s''; ';
|
||||||
|
put ' put '' end''; ';
|
||||||
|
put ' put '' else''; ';
|
||||||
|
put ' put '' for d = 1, sas.symget("sasjs"..i.."data0")''; ';
|
||||||
|
put ' put '' do''; ';
|
||||||
|
put ' put '' s=sas.symget("sasjs"..i.."data"..d)''; ';
|
||||||
|
put ' put '' if(s:sub(1,7) == "%nrstr(")''; ';
|
||||||
|
put ' put '' then''; ';
|
||||||
|
put ' put '' sasdata=sasdata..s:sub(8,s:len()-1)''; ';
|
||||||
|
put ' put '' else''; ';
|
||||||
|
put ' put '' sasdata=sasdata..s''; ';
|
||||||
|
put ' put '' end''; ';
|
||||||
|
put ' put '' end''; ';
|
||||||
|
put ' put '' end''; ';
|
||||||
|
put ' put '' file = io.open(sas.pathname("work").."/"..tab..".csv", "a")''; ';
|
||||||
|
put ' put '' io.output(file)''; ';
|
||||||
|
put ' put '' io.write(sasdata)''; ';
|
||||||
|
put ' put '' io.close(file)''; ';
|
||||||
|
put ' put ''end''; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' %inc _sasjs; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' /* convert data from macro variables to datasets */ ';
|
put ' /* now read in the data */ ';
|
||||||
put ' %do i=1 %to %sysfunc(countw(&sasjs_tables)); ';
|
put ' %do i=1 %to %sysfunc(countw(&sasjs_tables)); ';
|
||||||
put ' %let table=%scan(&sasjs_tables,&i,%str( )); ';
|
put ' %local table; %let table=%scan(&sasjs_tables,&i); ';
|
||||||
put ' %if %symexist(sasjs&i.data0)=0 %then %let sasjs&i.data0=1; ';
|
|
||||||
put ' data _null_; ';
|
|
||||||
put ' file "%sysfunc(pathname(work))/&table..csv" recfm=n; ';
|
|
||||||
put ' retain nrflg 0; ';
|
|
||||||
put ' length line $32767; ';
|
|
||||||
put ' do i=1 to &&sasjs&i.data0; ';
|
|
||||||
put ' if &&sasjs&i.data0=1 then line=symget("sasjs&i.data"); ';
|
|
||||||
put ' else line=symget(cats("sasjs&i.data",i)); ';
|
|
||||||
put ' if i=1 and substr(line,1,7)=''%nrstr('' then do; ';
|
|
||||||
put ' nrflg=1; ';
|
|
||||||
put ' line=substr(line,8); ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' if i=&&sasjs&i.data0 and nrflg=1 then do; ';
|
|
||||||
put ' line=substr(line,1,length(line)-1); ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' put line +(-1) @; ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' run; ';
|
|
||||||
put ' data _null_; ';
|
put ' data _null_; ';
|
||||||
put ' infile "%sysfunc(pathname(work))/&table..csv" termstr=crlf ; ';
|
put ' infile "%sysfunc(pathname(work))/&table..csv" termstr=crlf ; ';
|
||||||
put ' input; ';
|
put ' input; ';
|
||||||
put ' if _n_=1 then call symputx(''input_statement'',_infile_); ';
|
put ' if _n_=1 then call symputx(''input_statement'',_infile_); ';
|
||||||
put ' list; ';
|
put ' list; ';
|
||||||
put ' data work.&table; ';
|
put ' data &table; ';
|
||||||
put ' infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd ';
|
put ' infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd ';
|
||||||
put ' termstr=crlf; ';
|
put ' termstr=crlf; ';
|
||||||
put ' input &input_statement; ';
|
put ' input &input_statement; ';
|
||||||
@@ -628,15 +623,13 @@ data _null_;
|
|||||||
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
||||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||||
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
|
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; ';
|
||||||
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
|
||||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||||
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
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; ';
|
||||||
put ' syswarningtext=quote(cats(symget(''SYSWARNINGTEXT''))); ';
|
put ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; ';
|
||||||
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
|
|
||||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
||||||
put ' length memsize $32; ';
|
put ' length memsize $32; ';
|
||||||
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
||||||
@@ -651,6 +644,24 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%mend mv_webout; ';
|
put '%mend mv_webout; ';
|
||||||
|
put ' ';
|
||||||
|
put '%macro mf_getuser(type=META ';
|
||||||
|
put ')/*/STORE SOURCE*/; ';
|
||||||
|
put ' %local user metavar; ';
|
||||||
|
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
||||||
|
put ' %else %let metavar=_metaperson; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
||||||
|
put ' %else %if %symexist(&metavar) %then %do; ';
|
||||||
|
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
||||||
|
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
||||||
|
put ' %else %let user=%scan(&&&metavar,1,@); ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %let user=&sysuserid; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %quote(&user) ';
|
||||||
|
put ' ';
|
||||||
|
put '%mend mf_getuser; ';
|
||||||
/* WEBOUT END */
|
/* WEBOUT END */
|
||||||
put '/* if calling viya service with _job param, _program will conflict */';
|
put '/* if calling viya service with _job param, _program will conflict */';
|
||||||
put '/* so it is provided by SASjs instead as __program */';
|
put '/* so it is provided by SASjs instead as __program */';
|
||||||
|
|||||||
@@ -8,16 +8,10 @@
|
|||||||
%mv_deleteviyafolder(path=/Public/test)
|
%mv_deleteviyafolder(path=/Public/test)
|
||||||
|
|
||||||
|
|
||||||
@param [in] path= The full path of the folder to be deleted
|
@param path= The full path of the folder to be deleted
|
||||||
@param [in] access_token_var= (ACCESS_TOKEN) The global macro variable to
|
@param access_token_var= The global macro variable to contain the access token
|
||||||
contain the access token
|
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||||
@param [in] grant_type= (sas_services) Valid values are:
|
The default is authorization_code.
|
||||||
@li password
|
|
||||||
@li authorization_code
|
|
||||||
@li detect - will check if access_token exists, if not will use sas_services
|
|
||||||
if a SASStudioV session else authorization_code. Default option.
|
|
||||||
@li sas_services - will use oauth_bearer=sas_services.
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
|
||||||
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
@version VIYA V.03.04
|
||||||
@@ -25,7 +19,6 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mf_existds.sas
|
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mf_getuniquelibref.sas
|
@li mf_getuniquelibref.sas
|
||||||
@@ -36,7 +29,6 @@
|
|||||||
%macro mv_deleteviyafolder(path=
|
%macro mv_deleteviyafolder(path=
|
||||||
,access_token_var=ACCESS_TOKEN
|
,access_token_var=ACCESS_TOKEN
|
||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
,mdebug=0
|
|
||||||
);
|
);
|
||||||
%local oauth_bearer;
|
%local oauth_bearer;
|
||||||
%if &grant_type=detect %then %do;
|
%if &grant_type=detect %then %do;
|
||||||
@@ -113,17 +105,14 @@ run;
|
|||||||
%let libref1a=%mf_getuniquelibref();
|
%let libref1a=%mf_getuniquelibref();
|
||||||
libname &libref1a JSON fileref=&fname1a;
|
libname &libref1a JSON fileref=&fname1a;
|
||||||
|
|
||||||
%if %mf_existds(&libref1a..items_links) %then %do;
|
data _null_;
|
||||||
data _null_;
|
set &libref1a..items_links;
|
||||||
set &libref1a..items_links;
|
if href=:'/folders/folders' then return;
|
||||||
if href=:'/folders/folders' then return;
|
if rel='deleteResource' then
|
||||||
if rel='deleteResource' then
|
call execute('proc http method="DELETE" url='!!quote("&base_uri"!!trim(href))
|
||||||
call execute('proc http method="DELETE" url='
|
!!'; headers "Authorization"="Bearer &&&access_token_var" '
|
||||||
!!quote("&base_uri"!!trim(href))
|
!!' "Accept"="*/*";run; /**/');
|
||||||
!!'; headers "Authorization"="Bearer &&&access_token_var" '
|
run;
|
||||||
!!' "Accept"="*/*";run; /**/');
|
|
||||||
run;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%put &sysmacroname: perform the delete operation ;
|
%put &sysmacroname: perform the delete operation ;
|
||||||
%local fname2;
|
%local fname2;
|
||||||
@@ -144,11 +133,9 @@ run;
|
|||||||
%end;
|
%end;
|
||||||
%else %put &sysmacroname: &path successfully deleted;
|
%else %put &sysmacroname: &path successfully deleted;
|
||||||
|
|
||||||
%if &mdebug=0 %then %do;
|
/* clear refs */
|
||||||
/* clear refs */
|
filename &fname1 clear;
|
||||||
filename &fname1 clear;
|
filename &fname2 clear;
|
||||||
filename &fname2 clear;
|
libname &libref1 clear;
|
||||||
libname &libref1 clear;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%mend mv_deleteviyafolder;
|
%mend mv_deleteviyafolder;
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
,outds=work.viyagroups
|
,outds=work.viyagroups
|
||||||
);
|
);
|
||||||
%local oauth_bearer base_uri fname1 libref1;
|
%local oauth_bearer;
|
||||||
%if &grant_type=detect %then %do;
|
%if &grant_type=detect %then %do;
|
||||||
%if %symexist(&access_token_var) %then %let grant_type=authorization_code;
|
%if %symexist(&access_token_var) %then %let grant_type=authorization_code;
|
||||||
%else %let grant_type=sas_services;
|
%else %let grant_type=sas_services;
|
||||||
@@ -50,10 +50,11 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
options noquotelenmax;
|
options noquotelenmax;
|
||||||
/* location of rest apis */
|
%local base_uri; /* location of rest apis */
|
||||||
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
||||||
|
|
||||||
/* fetching folder details for provided path */
|
/* fetching folder details for provided path */
|
||||||
|
%local fname1;
|
||||||
%let fname1=%mf_getuniquefileref();
|
%let fname1=%mf_getuniquefileref();
|
||||||
%let libref1=%mf_getuniquelibref();
|
%let libref1=%mf_getuniquelibref();
|
||||||
|
|
||||||
@@ -77,8 +78,9 @@ data &outds;
|
|||||||
run;
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* clear refs */
|
/* clear refs */
|
||||||
filename &fname1 clear;
|
filename &fname1 clear;
|
||||||
libname &libref1 clear;
|
libname &libref1 clear;
|
||||||
|
|
||||||
%mend mv_getgroups;
|
%mend mv_getgroups;
|
||||||
@@ -33,6 +33,7 @@
|
|||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mv_getfoldermembers.sas
|
@li mv_getfoldermembers.sas
|
||||||
|
@li ml_json.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -43,9 +44,9 @@
|
|||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local dbg bufsize varcnt fname1 fname2 errmsg;
|
%local dbg;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname local entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
%end;
|
%end;
|
||||||
%else %let dbg=*;
|
%else %let dbg=*;
|
||||||
@@ -103,6 +104,7 @@ run;
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* prepare request*/
|
/* prepare request*/
|
||||||
|
%local fname1;
|
||||||
%let fname1=%mf_getuniquefileref();
|
%let fname1=%mf_getuniquefileref();
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri&joburi";
|
url="&base_uri&joburi";
|
||||||
@@ -112,95 +114,37 @@ proc http method='GET' out=&fname1 &oauth_bearer
|
|||||||
%end;
|
%end;
|
||||||
;
|
;
|
||||||
run;
|
run;
|
||||||
|
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201 %then
|
||||||
%if &mdebug=1 %then %do;
|
%do;
|
||||||
data _null_;
|
data _null_;infile &fname1;input;putlog _infile_;run;
|
||||||
infile &fname1;
|
%mp_abort(mac=&sysmacroname
|
||||||
input;
|
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
putlog _infile_;
|
)
|
||||||
run;
|
|
||||||
%end;
|
%end;
|
||||||
|
%local fname2 fname3 fpath1 fpath2 fpath3;
|
||||||
%mp_abort(
|
|
||||||
iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
|
|
||||||
,mac=&sysmacroname
|
|
||||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
|
||||||
)
|
|
||||||
|
|
||||||
%let fname2=%mf_getuniquefileref();
|
%let fname2=%mf_getuniquefileref();
|
||||||
filename &fname2 temp ;
|
%let fname3=%mf_getuniquefileref();
|
||||||
|
%let fpath1=%sysfunc(pathname(&fname1));
|
||||||
|
%let fpath2=%sysfunc(pathname(&fname2));
|
||||||
|
%let fpath3=%sysfunc(pathname(&fname3));
|
||||||
|
|
||||||
/* cannot use lua IO package as not available in Viya 4 */
|
/* compile the lua JSON module */
|
||||||
/* so use data step to read the JSON until the string `"code":"` is found */
|
%ml_json()
|
||||||
|
/* read using LUA - this allows the code to be of any length */
|
||||||
data _null_;
|
data _null_;
|
||||||
file &fname2 recfm=n;
|
file "&fpath3..lua";
|
||||||
infile &fname1 lrecl=1 recfm=n;
|
put '
|
||||||
input sourcechar $char1. @@;
|
infile = io.open (sas.symget("fpath1"), "r")
|
||||||
format sourcechar hex2.;
|
outfile = io.open (sas.symget("fpath2"), "w")
|
||||||
retain startwrite 0;
|
io.input(infile)
|
||||||
if startwrite=0 and sourcechar='"' then do;
|
local resp=json.decode(io.read())
|
||||||
reentry:
|
local job=resp["code"]
|
||||||
input sourcechar $ 1. @@;
|
outfile:write(job)
|
||||||
if sourcechar='c' then do;
|
io.close(infile)
|
||||||
reentry2:
|
io.close(outfile)
|
||||||
input sourcechar $ 1. @@;
|
';
|
||||||
if sourcechar='o' then do;
|
|
||||||
input sourcechar $ 1. @@;
|
|
||||||
if sourcechar='d' then do;
|
|
||||||
input sourcechar $ 1. @@;
|
|
||||||
if sourcechar='e' then do;
|
|
||||||
input sourcechar $ 1. @@;
|
|
||||||
if sourcechar='"' then do;
|
|
||||||
input sourcechar $ 1. @@;
|
|
||||||
if sourcechar=':' then do;
|
|
||||||
input sourcechar $ 1. @@;
|
|
||||||
if sourcechar='"' then do;
|
|
||||||
putlog 'code found';
|
|
||||||
startwrite=1;
|
|
||||||
input sourcechar $ 1. @@;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
else if sourcechar='c' then goto reentry2;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
else if sourcechar='"' then goto reentry;
|
|
||||||
end;
|
|
||||||
else if sourcechar='"' then goto reentry;
|
|
||||||
end;
|
|
||||||
else if sourcechar='"' then goto reentry;
|
|
||||||
end;
|
|
||||||
else if sourcechar='"' then goto reentry;
|
|
||||||
end;
|
|
||||||
/* once the `"code":"` string is found, write until unescaped `"` is found */
|
|
||||||
if startwrite=1 then do;
|
|
||||||
if sourcechar='\' then do;
|
|
||||||
input sourcechar $ 1. @@;
|
|
||||||
if sourcechar in ('"','\') then put sourcechar char1.;
|
|
||||||
else if sourcechar='n' then put '0A'x;
|
|
||||||
else if sourcechar='r' then put '0D'x;
|
|
||||||
else if sourcechar='t' then put '09'x;
|
|
||||||
else if sourcechar='u' then do;
|
|
||||||
length uni $4;
|
|
||||||
input uni $ 4. @@;
|
|
||||||
sourcechar=unicode('\u'!!uni);
|
|
||||||
put sourcechar char1.;
|
|
||||||
end;
|
|
||||||
else do;
|
|
||||||
call symputx('errmsg',"Uncaught escape char: "!!sourcechar,'l');
|
|
||||||
call symputx('syscc',99);
|
|
||||||
stop;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
else if sourcechar='"' then stop;
|
|
||||||
else put sourcechar char1.;
|
|
||||||
end;
|
|
||||||
run;
|
run;
|
||||||
|
%inc "&fpath3..lua";
|
||||||
%mp_abort(iftrue=("&syscc"="99")
|
|
||||||
,mac=mv_getjobcode
|
|
||||||
,msg=%str(&errmsg)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* export to desired destination */
|
/* export to desired destination */
|
||||||
%if "&outref"="0" %then %do;
|
%if "&outref"="0" %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
@@ -225,6 +169,7 @@ run;
|
|||||||
/* clear refs */
|
/* clear refs */
|
||||||
filename &fname1 clear;
|
filename &fname1 clear;
|
||||||
filename &fname2 clear;
|
filename &fname2 clear;
|
||||||
|
filename &fname3 clear;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mv_getjobcode;
|
%mend mv_getjobcode;
|
||||||
|
|||||||
@@ -86,8 +86,7 @@
|
|||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_existfileref.sas
|
@li mf_existfileref.sas
|
||||||
@li mf_getuniquefileref.sas
|
@li ml_json.sas
|
||||||
@li mf_getuniquelibref.sas
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -96,7 +95,7 @@
|
|||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local dbg libref1 libref2 loglocation fname1 fname2;
|
%local dbg;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -155,8 +154,8 @@ options noquotelenmax;
|
|||||||
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
||||||
|
|
||||||
/* prepare request*/
|
/* prepare request*/
|
||||||
|
%local fname1;
|
||||||
%let fname1=%mf_getuniquefileref();
|
%let fname1=%mf_getuniquefileref();
|
||||||
%let fname2=%mf_getuniquefileref();
|
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri&uri";
|
url="&base_uri&uri";
|
||||||
headers
|
headers
|
||||||
@@ -176,19 +175,37 @@ run;
|
|||||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
|
%local fname2 fname3 fpath1 fpath2 fpath3;
|
||||||
|
%let fname2=%mf_getuniquefileref();
|
||||||
|
%let fname3=%mf_getuniquefileref();
|
||||||
|
%let fpath1=%sysfunc(pathname(&fname1));
|
||||||
|
%let fpath2=%sysfunc(pathname(&fname2));
|
||||||
|
%let fpath3=%sysfunc(pathname(&fname3));
|
||||||
|
|
||||||
%let libref1=%mf_getuniquelibref();
|
/* compile the lua JSON module */
|
||||||
libname &libref1 JSON fileref=&fname1;
|
%ml_json()
|
||||||
|
/* read using LUA - this allows the code to be of any length */
|
||||||
data _null_;
|
data _null_;
|
||||||
set &libref1..root;
|
file "&fpath3..lua";
|
||||||
call symputx('loglocation',loglocation,'l');
|
put '
|
||||||
|
infile = io.open (sas.symget("fpath1"), "r")
|
||||||
|
outfile = io.open (sas.symget("fpath2"), "w")
|
||||||
|
io.input(infile)
|
||||||
|
local resp=json.decode(io.read())
|
||||||
|
local logloc=resp["logLocation"]
|
||||||
|
outfile:write(logloc)
|
||||||
|
io.close(infile)
|
||||||
|
io.close(outfile)
|
||||||
|
';
|
||||||
run;
|
run;
|
||||||
|
%inc "&fpath3..lua";
|
||||||
/* validate log path*/
|
/* get log path*/
|
||||||
%let errflg=1;
|
%let errflg=1;
|
||||||
%let errmsg=No loglocation entry in &fname1 fileref;
|
%let errmsg=No entry in &fname2 fileref;
|
||||||
data _null_;
|
data _null_;
|
||||||
uri=symget('loglocation');
|
infile &fname2;
|
||||||
|
input;
|
||||||
|
uri=cats(_infile_);
|
||||||
if length(uri)<12 then do;
|
if length(uri)<12 then do;
|
||||||
call symputx('errflg',1);
|
call symputx('errflg',1);
|
||||||
call symputx('errmsg',"URI is invalid (too short) - '&uri'",'l');
|
call symputx('errmsg',"URI is invalid (too short) - '&uri'",'l');
|
||||||
@@ -215,7 +232,7 @@ run;
|
|||||||
|
|
||||||
/* we have a log uri - now fetch the log */
|
/* we have a log uri - now fetch the log */
|
||||||
%&dbg.put &sysmacroname: querying &base_uri&logloc/content;
|
%&dbg.put &sysmacroname: querying &base_uri&logloc/content;
|
||||||
proc http method='GET' out=&fname2 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri&logloc/content?limit=10000";
|
url="&base_uri&logloc/content?limit=10000";
|
||||||
headers
|
headers
|
||||||
%if &grant_type=authorization_code %then %do;
|
%if &grant_type=authorization_code %then %do;
|
||||||
@@ -226,14 +243,14 @@ run;
|
|||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname: fetching log content from &base_uri&logloc/content;
|
%put &sysmacroname: fetching log content from &base_uri&logloc/content;
|
||||||
data _null_;infile &fname2;input;putlog _infile_;run;
|
data _null_;infile &fname1;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &SYS_PROCHTTP_STATUS_CODE=400 %then %do;
|
%if &SYS_PROCHTTP_STATUS_CODE=400 %then %do;
|
||||||
/* fetch log from parent session */
|
/* fetch log from parent session */
|
||||||
%let logloc=%substr(&logloc,1,%index(&logloc,%str(/jobs/))-1);
|
%let logloc=%substr(&logloc,1,%index(&logloc,%str(/jobs/))-1);
|
||||||
%&dbg.put &sysmacroname: Now querying &base_uri&logloc/log/content;
|
%&dbg.put &sysmacroname: Now querying &base_uri&logloc/log/content;
|
||||||
proc http method='GET' out=&fname2 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri&logloc/log/content?limit=10000";
|
url="&base_uri&logloc/log/content?limit=10000";
|
||||||
headers
|
headers
|
||||||
%if &grant_type=authorization_code %then %do;
|
%if &grant_type=authorization_code %then %do;
|
||||||
@@ -243,32 +260,47 @@ run;
|
|||||||
run;
|
run;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname: fetching log content from &base_uri&logloc/log/content;
|
%put &sysmacroname: fetching log content from &base_uri&logloc/log/content;
|
||||||
data _null_;infile &fname2;input;putlog _infile_;run;
|
data _null_;infile &fname1;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201
|
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201
|
||||||
%then %do;
|
%then %do;
|
||||||
%if &mdebug ne 1 %then %do; /* have already output above */
|
%if &mdebug ne 1 %then %do; /* have already output above */
|
||||||
data _null_;infile &fname2;input;putlog _infile_;run;
|
data _null_;infile &fname1;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
%mp_abort(mac=&sysmacroname
|
%mp_abort(mac=&sysmacroname
|
||||||
,msg=%str(logfetch: &SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(logfetch: &SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%let libref2=%mf_getuniquelibref();
|
|
||||||
libname &libref2 JSON fileref=&fname2;
|
|
||||||
data _null_;
|
data _null_;
|
||||||
|
file "&fpath3..lua";
|
||||||
|
put '
|
||||||
|
infile = io.open (sas.symget("fpath1"), "r")
|
||||||
|
outfile = io.open (sas.symget("fpath2"), "w")
|
||||||
|
io.input(infile)
|
||||||
|
local resp=json.decode(io.read())
|
||||||
|
for i, v in pairs(resp["items"]) do
|
||||||
|
outfile:write(v.line,"\n")
|
||||||
|
end
|
||||||
|
io.close(infile)
|
||||||
|
io.close(outfile)
|
||||||
|
';
|
||||||
|
run;
|
||||||
|
%inc "&fpath3..lua";
|
||||||
|
|
||||||
|
/* write log out to the specified fileref */
|
||||||
|
data _null_;
|
||||||
|
infile &fname2 end=last;
|
||||||
file &outref mod;
|
file &outref mod;
|
||||||
if _n_=1 then do;
|
if _n_=1 then do;
|
||||||
put "/** SASJS Viya Job Log Extract start: &uri **/";
|
put "/** SASJS Viya Job Log Extract start: &uri **/";
|
||||||
end;
|
end;
|
||||||
set &libref2..items end=last;
|
input;
|
||||||
|
put _infile_;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
putlog line;
|
putlog _infile_;
|
||||||
%end;
|
%end;
|
||||||
put line;
|
|
||||||
if last then do;
|
if last then do;
|
||||||
put "/** SASJS Viya Job Log Extract end: &uri **/";
|
put "/** SASJS Viya Job Log Extract end: &uri **/";
|
||||||
end;
|
end;
|
||||||
@@ -277,8 +309,7 @@ run;
|
|||||||
%if &mdebug=0 %then %do;
|
%if &mdebug=0 %then %do;
|
||||||
filename &fname1 clear;
|
filename &fname1 clear;
|
||||||
filename &fname2 clear;
|
filename &fname2 clear;
|
||||||
libname &libref1 clear;
|
filename &fname3 clear;
|
||||||
libname &libref2 clear;
|
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put &sysmacroname exit vars:;
|
%put &sysmacroname exit vars:;
|
||||||
|
|||||||
@@ -81,7 +81,6 @@
|
|||||||
@li mf_loc.sas
|
@li mf_loc.sas
|
||||||
@li mf_getquotedstr.sas
|
@li mf_getquotedstr.sas
|
||||||
@li mf_getuser.sas
|
@li mf_getuser.sas
|
||||||
@li mp_abort.sas
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -99,7 +98,7 @@
|
|||||||
,refresh_token_validity=DEFAULT
|
,refresh_token_validity=DEFAULT
|
||||||
,outjson=_null_
|
,outjson=_null_
|
||||||
);
|
);
|
||||||
%local fname1 fname2 fname3 libref access_token url tokloc msg;
|
%local fname1 fname2 fname3 libref access_token url tokloc;
|
||||||
|
|
||||||
%if client_name=DEFAULT %then %let client_name=
|
%if client_name=DEFAULT %then %let client_name=
|
||||||
Generated by %mf_getuser() (&sysuserid) on %sysfunc(datetime(),datetime19.
|
Generated by %mf_getuser() (&sysuserid) on %sysfunc(datetime(),datetime19.
|
||||||
@@ -113,11 +112,10 @@ options noquotelenmax;
|
|||||||
%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token;
|
%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token;
|
||||||
|
|
||||||
%if %sysfunc(fileexist(&tokloc))=0 %then %do;
|
%if %sysfunc(fileexist(&tokloc))=0 %then %do;
|
||||||
%let msg=Unable to access the consul token at &tokloc;
|
%put &sysmacroname: unable to access the consul token at &tokloc;
|
||||||
%put &sysmacroname: &msg;
|
|
||||||
%put Try passing the value in the consul= macro parameter;
|
%put Try passing the value in the consul= macro parameter;
|
||||||
%put See docs: https://core.sasjs.io/mv__registerclient_8sas.html;
|
%put See docs: https://core.sasjs.io/mv__registerclient_8sas.html;
|
||||||
%mp_abort(mac=mv_registerclient,msg=%str(&msg))
|
%abort;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user