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

Compare commits

...

62 Commits

Author SHA1 Message Date
github-actions
b3298143c7 chore: updating all.sas 2025-11-19 01:43:18 +00:00
Trevor Moody
366b6e7fa4 Merge branch 'update_mv_createfile_20251029' of github.com:sasjs/core into update_mv_createfile_20251029 2025-11-19 01:42:45 +00:00
Trevor Moody
9bf2870357 fix: returned the overzealous removal of &outds creation 2025-11-19 01:42:23 +00:00
github-actions
f71681c352 chore: updating all.sas 2025-11-19 01:01:44 +00:00
Trevor Moody
6008db999c Merge branch 'update_mv_createfile_20251029' of github.com:sasjs/core into update_mv_createfile_20251029 2025-11-19 01:00:54 +00:00
Trevor Moody
b6f020e897 fix: corrected syntax and amended included macros 2025-11-19 01:00:21 +00:00
github-actions
9d0533fe3b chore: updating all.sas 2025-11-19 00:03:04 +00:00
Trevor Moody
7dd2597041 chore: amended and sorted the future Breaking Changes info 2025-11-19 00:02:21 +00:00
Trevor Moody
426c0bf9f2 chore: improved default typeDefName handling if mv_getViyaFileExtParms returns empty 2025-11-19 00:00:14 +00:00
Trevor Moody
1cd8ba03c5 chore: improved file-type handling efficiency 2025-11-18 23:56:54 +00:00
Trevor Moody
569533b218 fix: apply viya file type properties to newly created viya files 2025-11-12 11:17:31 +00:00
Trevor Moody
14aeb585ae fix: ensure sasjs_prefix exists before referencing it 2025-11-12 11:15:24 +00:00
allan
7dd219e9f1 chore: fixing badges in README 2025-09-21 11:36:41 +01:00
Allan Bowe
cdd2b88b09 Merge pull request #403 from sasjs/issue400
Issue400
2025-06-30 19:26:52 +01:00
github-actions
7e4fb4a640 chore: updating all.sas 2025-06-30 18:26:32 +00:00
Allan Bowe
a428b4f66c Merge branch 'main' into issue400 2025-06-30 19:26:19 +01:00
github-actions
e2f0577e78 chore: updating all.sas 2025-06-30 18:26:03 +00:00
allan
d53eff7771 fix: reducing logging per #400 2025-06-30 19:25:40 +01:00
github-actions
5b56c85455 chore: updating all.sas 2025-06-30 16:38:43 +00:00
Allan Bowe
ff519c7f39 Merge pull request #402 from sasjs/issue400
fix: re-attempt of request, hopefully fixes #400
2025-06-30 17:38:39 +01:00
Allan Bowe
7d7778fd36 Merge branch 'main' into issue400 2025-06-30 17:38:19 +01:00
github-actions
b47f31cfe6 chore: updating all.sas 2025-06-30 16:37:46 +00:00
allan
542039b425 fix: re-attempt of request, hopefully fixes #400 2025-06-30 17:37:18 +01:00
Allan Bowe
cc908a82bc Merge pull request #401 from sasjs/issue400
fix: addresses #400
2025-06-30 16:08:58 +01:00
github-actions
71c31046f4 chore: updating all.sas 2025-06-30 15:06:32 +00:00
allan
33a487b2b4 fix: addresses #400 2025-06-30 16:05:57 +01:00
Allan Bowe
7240cf08d6 Merge pull request #399 from sasjs/uniquelibref
fix: increasing limit from 1k to 100k for mf_getuniquelibref()
2025-06-29 13:46:57 +01:00
github-actions
1cb702149c chore: updating all.sas 2025-06-29 12:46:06 +00:00
allan
a12ea6a7cb chore: removing commit size check 2025-06-29 13:45:48 +01:00
Allan Bowe
a6b52b5d9e Merge branch 'main' into uniquelibref 2025-06-29 13:43:12 +01:00
github-actions
0faba3581b chore: updating all.sas 2025-06-29 12:42:55 +00:00
allan
749309b749 fix: increasing limit from 1k to 100k for mf_getuniqueliref() 2025-06-29 13:42:23 +01:00
Allan Bowe
e54de44d4b chore: adding git precommit hook to avoid large files 2025-06-27 16:46:24 +01:00
Allan Bowe
40436be14f Merge pull request #397 from sasjs/omitsessionresults
fix: ensuring acceptable casing of _omitSessionResults
2025-06-09 21:00:14 +01:00
github-actions
909fef7143 chore: updating all.sas 2025-06-09 19:58:31 +00:00
allan
bcb93e62d4 fix: ensuring acceptable casing of _omitSessionResults
More info: https://communities.sas.com/t5/SAS-Viya/Returning-webout-from-JES-API/td-p/966992
2025-06-09 20:58:05 +01:00
Allan Bowe
6dbfd32dba Merge pull request #396 from sasjs/dc171
feat: new mfv_getfolderpath macro
2025-06-06 20:30:24 +01:00
github-actions
5706483886 chore: updating all.sas 2025-06-06 19:29:28 +00:00
allan
ce73e2bebd feat: new mfv_getfolderpath macro
+ associated test
created to support the fix for https://git.datacontroller.io/dc/dc/issues/171
2025-06-06 20:29:07 +01:00
Allan Bowe
bc77e5a5d1 Merge pull request #395 from sasjs/indexhtml
fix: ff downloading instead of streaming html on viya
2025-06-05 14:10:35 +01:00
github-actions
daa4e4e762 chore: updating all.sas 2025-06-05 13:10:16 +00:00
allan
9c1f68944f fix: ff downloading instead of streaming html on viya 2025-06-05 14:09:52 +01:00
Allan Bowe
3978ac5e05 Merge pull request #394 from sasjs/pngfix
fix: support png in streaming viya apps
2025-06-02 15:10:51 +01:00
github-actions
6b378749e5 chore: updating all.sas 2025-06-02 14:10:40 +00:00
allan
77c0e35c9d fix: support png in streaming viya apps 2025-06-02 15:10:11 +01:00
Allan Bowe
52d33ccafb Merge pull request #393 from sasjs/issue1403
feat: adding mp_replace option to mv_createfile
2025-06-02 12:17:55 +01:00
github-actions
10087dd6a6 chore: updating all.sas 2025-06-02 11:17:02 +00:00
allan
3bd2148ae9 fix: failing test 2025-06-02 12:16:36 +01:00
github-actions
60570b2e13 chore: updating all.sas 2025-05-30 18:15:58 +00:00
allan
6e033afb7b feat: adding mp_replace option to mv_createfile
Relates to https://github.com/sasjs/cli/issues/1403
2025-05-30 19:15:33 +01:00
allan
4f5fa414e1 fix: updating readme with new prefix
(also bumping the version for the previous commit)
2025-05-30 10:24:19 +01:00
Allan Bowe
4b142f1f45 Merge pull request #392 from sasjs/viya2025
chore: removing put statements
2025-05-30 10:14:12 +01:00
github-actions
3f73a565a6 chore: updating all.sas 2025-05-30 09:13:52 +00:00
allan
d3f1c8e960 chore: removing put statements 2025-05-30 10:13:30 +01:00
Allan Bowe
0d10441b89 Merge pull request #391 from sasjs/viyastream
fix: ensuring svg rendering from SAS drive
2025-05-30 09:59:02 +01:00
github-actions
85e1f56400 chore: updating all.sas 2025-05-30 08:58:30 +00:00
allan
c5ec21c7a0 fix: ensuring svg rendering from SAS drive
Also reducing put statements in the log
2025-05-30 09:58:06 +01:00
Allan Bowe
e049ab99a7 Merge pull request #390 from sasjs/svgfix
fix: streamlining viya deploys
2025-05-29 17:52:57 +01:00
github-actions
e9deab3885 chore: updating all.sas 2025-05-29 16:51:46 +00:00
allan
8d2f084316 fix: streamlining viya deploys 2025-05-29 17:51:23 +01:00
allan
33cb36fb8f fix: ensuring that mv_createfile always creates the file by default
Also some fixes to ensure that web files are served from Viya
2025-05-29 12:25:02 +01:00
allan
752e6305c9 chore: fixing docs of mfv_getpathuri 2025-05-19 15:20:41 +01:00
21 changed files with 1251 additions and 149 deletions

View File

@@ -1,19 +1,12 @@
# Macro Core # Macro Core
[![npm package][npm-image]][npm-url]
[![Github Workflow][githubworkflow-image]][githubworkflow-url] [![npm package](https://img.shields.io/npm/v/@sasjs/core.svg)](http://npmjs.org/package/@sasjs/core)
[![Github Workflow](https://github.com/sasjs/core/actions/workflows/main.yml/badge.svg)](https://github.com/sasjs/core/blob/main/.github/workflows/main.yml)
![npm](https://img.shields.io/npm/dt/@sasjs/core) ![npm](https://img.shields.io/npm/dt/@sasjs/core)
![GitHub top language](https://img.shields.io/github/languages/top/sasjs/core) ![GitHub top language](https://img.shields.io/github/languages/top/sasjs/core)
[![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/sasjs/core)](https://github.com/sasjs/core/issues?q=is%3Aissue+is%3Aclosed) [![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/sasjs/core)](https://github.com/sasjs/core/issues?q=is%3Aissue+is%3Aclosed)
[![GitHub issues](https://img.shields.io/github/issues-raw/sasjs/core)](https://github.com/sasjs/core/issues) [![GitHub issues](https://img.shields.io/github/issues-raw/sasjs/core)](https://github.com/sasjs/core/issues)
![total lines](https://tokei.rs/b1/github/sasjs/core) ![total lines](https://tokei.rs/b1/github/sasjs/core)
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/sasjs/core)
[npm-image]:https://img.shields.io/npm/v/@sasjs/core.svg
[npm-url]:http://npmjs.org/package/@sasjs/core
[githubworkflow-image]:https://github.com/sasjs/core/actions/workflows/main.yml/badge.svg
[githubworkflow-url]:https://github.com/sasjs/core/blob/main/.github/workflows/main.yml
[dependency-url]:https://github.com/sasjs/core/blob/main/package.json
Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of [Application Development](https://sasapps.io) on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/.github/CONTRIBUTING.md) are welcome. Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of [Application Development](https://sasapps.io) on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/.github/CONTRIBUTING.md) are welcome.
@@ -147,16 +140,17 @@ filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
- macro names must be lowercase - macro names must be lowercase
- one macro per file - one macro per file
- prefixes: - prefixes:
- _mcf_ for macro compiled functions (proc fcmp) - _mcf__: macro compiled functions (proc fcmp)
- _mddl_ for macros containing DDL (Data Definition Language) - _mddl__: macros containing DDL (Data Definition Language)
- _mf_ for macro functions (can be used in open code). - _mf__: macro functions (can be used in open code).
- _ml_ for macros that are used to compile LUA modules - _mfv__: macro functions that work only in Viya
- _mm_ for metadata macros (interface with the metadata server). - _ml__: macros that are used to compile LUA modules
- _mmx_ for macros that use metadata and are XCMD enabled (working on both windows and unix) - _mm__: metadata macros (interface with the metadata server).
- _mp_ for macro procedures (which generate sas code) - _mmx__: macros that use metadata and are XCMD enabled (working on both windows and unix)
- _ms_ for macro procedures that will only work with [@sasjs/server](https://github.com/sasjs/server) - _mp__: macro procedures (which generate sas code)
- _mv_ for macro procedures that will only work in Viya - _ms__: macro procedures that will only work with [@sasjs/server](https://github.com/sasjs/server)
- _mx_ for macros that work on Viya, SAS 9 EBI and SASjs Server - _mv__: macro procedures that will only work in Viya
- _mx__: macros that work on Viya, SAS 9 EBI and SASjs Server
- follow verb-noun convention - follow verb-noun convention
- unix style line endings (lf) - unix style line endings (lf)
- individual lines should be no more than 80 characters long - individual lines should be no more than 80 characters long
@@ -219,12 +213,13 @@ 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) * mcf_xxx macros to have `insert_cmplib` option deprecated (the option is now checked automatically with value inserted only if needed)
* 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)
* 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.
* mp_getddl.sas to be renamed to mp_ds2ddl.sas (consistent with other ds2xxx macros). A wrapper macro is already in place, and you are able to use this immediately. The default for SHOWLOG will also be YES instead of NO. * mf_getuniquelibref.sas to have the deprecated maxtries parameter removed (no longer needed)
* mp_abort.sas will have the redundant type= parameter removed.
* mp_coretable.sas will be replaced by the standalone macros in the `ddl` folder (which are already available) * mp_coretable.sas will be replaced by the standalone macros in the `ddl` folder (which are already available)
* mp_getddl.sas to be renamed to mp_ds2ddl.sas (consistent with other ds2xxx macros). A wrapper macro is already in place, and you are able to use this immediately. The default for SHOWLOG will also be YES instead of NO.
* mp_testservice.sas to be renamed as mp_execute.sas (as it doesn't actually test anything)
## Star Gazing ## Star Gazing

591
all.sas
View File

@@ -1121,7 +1121,7 @@ or %index(&pgm,/tests/testteardown)
@author Allan Bowe @author Allan Bowe
**/ **/
%macro mf_getuniquelibref(prefix=mclib,maxtries=1000); %macro mf_getuniquelibref(prefix=mc,maxtries=1000);
%local x; %local x;
%if ( %length(&prefix) gt 7 ) %then %do; %if ( %length(&prefix) gt 7 ) %then %do;
@@ -4002,10 +4002,6 @@ run;
ignorelist=, ignorelist=,
outds=work.test_results outds=work.test_results
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local ds test_result test_comments del add mod ilist;
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS SYS_PROCHTTP_STATUS_CODE
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
* behaviour is not desired, simply initiate the following global macro * behaviour is not desired, simply initiate the following global macro
@@ -4013,6 +4009,10 @@ run;
*/ */
%mp_init() %mp_init()
%local ds test_result test_comments del add mod ilist;
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS SYS_PROCHTTP_STATUS_CODE
SYS_PROCHTTP_STATUS_CODE SYS_PROCHTTP_STATUS_PHRASE &ignorelist);
/* get current variables */ /* get current variables */
%if &action=SNAPSHOT %then %do; %if &action=SNAPSHOT %then %do;
proc sql; proc sql;
@@ -11828,7 +11828,8 @@ insert into &outds select distinct * from &append_ds;
LUA, you can also use this macro: mp_gsubfile.sas LUA, you can also use this macro: mp_gsubfile.sas
@param [in] infile The QUOTED path to the file on which to perform the @param [in] infile The QUOTED path to the file on which to perform the
substitution substitution. Note that you can extract the pathname from a fileref using
the pathname function, eg: `"%sysfunc(pathname(fref))"`;
@param [in] findvar= Macro variable NAME containing the string to search for @param [in] findvar= Macro variable NAME containing the string to search for
@param [in] replacevar= Macro variable NAME containing the replacement string @param [in] replacevar= Macro variable NAME containing the replacement string
@param [out] outfile= (0) Optional QUOTED path to the adjusted output file (to @param [out] outfile= (0) Optional QUOTED path to the adjusted output file (to
@@ -11942,7 +11943,7 @@ data _null_;
run; run;
/* END */ /* END */
%put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) seconds to run; /* %put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) secs to run; */
%mend mp_replace; %mend mp_replace;
/** /**
@@ -24097,18 +24098,25 @@ run;
msg=Cannot enter mfv_existfolder.sas with syscc=&syscc msg=Cannot enter mfv_existfolder.sas with syscc=&syscc
) )
%local fref rc; %local fref rc var;
%let fref=%mf_getuniquefileref(); %let fref=%mf_getuniquefileref();
%if %sysfunc(filename(fref,,filesrvc,folderPath="&path"))=0 %then %do; %if %sysfunc(filename(fref,,filesrvc,folderPath="&path"))=0 %then %do;
1 1
%let var=_FILESRVC_&fref._URI;
%let rc=%sysfunc(filename(fref)); %let rc=%sysfunc(filename(fref));
%symdel &var;
%end; %end;
%else %do; %else %do;
0 0
%let syscc=0; %let syscc=0;
%end; %end;
%mf_abort(
iftrue=(&syscc ne 0),
msg=Cannot leave mfv_existfolder.sas with syscc=&syscc
)
%mend mfv_existfolder;/** %mend mfv_existfolder;/**
@file mfv_existsashdat.sas @file mfv_existsashdat.sas
@brief Checks whether a CAS sashdat dataset exists in persistent storage. @brief Checks whether a CAS sashdat dataset exists in persistent storage.
@@ -24170,15 +24178,67 @@ run;
%mend mfv_existsashdat; %mend mfv_existsashdat;
/** /**
@file
@brief Returns the path of a folder from the URI
@details Makes use of the SYSMSG() ER8OR response, which resolves the uri,
seemingly without entering an er8or state.
Usage:
%mv_createfolder(path=/public/demo)
%let uri=%mfv_getpathuri(/public/demo);
%put %mfv_getfolderpath(&uri);
Notice above the new path has an uppercase P - the correct path.
@param [in] uri The uri of the folder -eg /folders/folders/xxxx)
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
<h4> Related Macros </h4>
@li mfv_getpathuri.sas
@version 4
@author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
**/
%macro mfv_getfolderpath(uri
)/*/STORE SOURCE*/;
%local fref rc path msg var /* var used to avoid delete timing issue */;
%let fref=%mf_getuniquefileref();
%if %quote(%substr(%str(&uri),1,17)) ne %quote(/folders/folders/)
%then %do;
%put &sysmacroname: Invalid URI: &uri;
%end;
%else %if %sysfunc(filename(fref,,filesrvc,folderuri="&uri" ))=0
%then %do;
%let var=_FILESRVC_&fref._URI;
%local fid ;
%let fid= %sysfunc(fopen(&fref,I));
%let msg=%quote(%sysfunc(sysmsg()));
%unquote(%scan(&msg,2,%str(,.)))
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(fref));
%symdel &var;
%end;
%else %do;
%put &sysmacroname: Not Found: &uri;
%let syscc=0;
%end;
%mend mfv_getfolderpath ;/**
@file @file
@brief Returns the uri of a file or folder @brief Returns the uri of a file or folder
@details The automatic variable _FILESRVC_[fref]_URI is used after assigning @details The automatic variable `_FILESRVC_[fref]_URI` is used after assigning
a fileref using the filesrvc engine. a fileref using the filesrvc engine.
Usage: Usage:
%put %mfv_existfile(/Public/folder/file.txt); %put %mfv_getpathuri(/Public/folder/file.txt);
%put %mfv_existfile(/Public/folder); %put %mfv_getpathuri(/Public/folder);
@param [in] filepath The full path to the file on SAS drive @param [in] filepath The full path to the file on SAS drive
(eg /Public/myfile.txt) (eg /Public/myfile.txt)
@@ -24220,6 +24280,10 @@ run;
%let syscc=0; %let syscc=0;
%end; %end;
%mf_abort(
iftrue=(&syscc ne 0),
msg=Cannot leave &sysmacroname with syscc=&syscc
)
%mend mfv_getpathuri;/** %mend mfv_getpathuri;/**
@file @file
@brief Creates a file in SAS Drive using the API method @brief Creates a file in SAS Drive using the API method
@@ -24239,6 +24303,20 @@ run;
run; run;
%mv_createfile(path=/Public/temp,name=newfile.txt,inref=myfile) %mv_createfile(path=/Public/temp,name=newfile.txt,inref=myfile)
The macro also supports find & replace (used by the SASjs Streaming App
build program). This allows one string to be replaced by another at the
point at which the file is created. This is done by passing in the NAMES of
the macro variables containing the values to be swapped, eg:
filename fref temp;
data _null_;
file fref;
put 'whenever life gets you down, Mrs Brown..';
run;
%let f=Mrs Brown;
%let r=just remember that you're standing on a planet that's evolving;
%mv_createfile(path=/Public,name=life.md,inref=fref,fin,swap=f r)
@param [in] path= The parent (SAS Drive) folder in which to create the file @param [in] path= The parent (SAS Drive) folder in which to create the file
@param [in] name= The name of the file to be created @param [in] name= The name of the file to be created
@@ -24258,6 +24336,10 @@ run;
@li password @li password
@li authorization_code @li authorization_code
@li sas_services @li sas_services
@param [in] force= (YES) Will overwrite (delete / recreate) files by default.
Set to NO to abort if a file already exists in that location.
@param pin] swap= (0) Provide two macro variable NAMES that contain the values
to be swapped, eg swap=find replace (see also the example above)
@param [out] outds= (_null_) Output dataset with the uri of the new file @param [out] outds= (_null_) Output dataset with the uri of the new file
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@@ -24268,9 +24350,12 @@ run;
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_isblank.sas @li mf_isblank.sas
@li mf_mimetype.sas @li mf_mimetype.sas
@li mfv_getpathuri.sas
@li mp_abort.sas @li mp_abort.sas
@li mp_base64copy.sas @li mp_base64copy.sas
@li mp_replace.sas
@li mv_createfolder.sas @li mv_createfolder.sas
@li mv_getviyafileextparms.sas
<h4> Related Macros</h4> <h4> Related Macros</h4>
@li mv_createfile.sas @li mv_createfile.sas
@@ -24287,6 +24372,8 @@ run;
,grant_type=sas_services ,grant_type=sas_services
,mdebug=0 ,mdebug=0
,outds=_null_ ,outds=_null_
,force=YES
,swap=0
); );
%local dbg; %local dbg;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
@@ -24295,6 +24382,11 @@ run;
%end; %end;
%else %let dbg=*; %else %let dbg=*;
%mp_abort(
iftrue=(&syscc ne 0),
msg=Cannot enter &sysmacroname with syscc=&syscc
)
%local oauth_bearer; %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;
@@ -24308,16 +24400,16 @@ run;
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password %mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
and &grant_type ne sas_services and &grant_type ne sas_services
) )
,mac=&sysmacroname ,mac=MV_CREATEFILE
,msg=%str(Invalid value for grant_type: &grant_type) ,msg=%str(Invalid value for grant_type: &grant_type)
) )
%mp_abort(iftrue=(%mf_isblank(&path)=1 or %length(&path)=1) %mp_abort(iftrue=(%mf_isblank(&path)=1 or %length(&path)=1)
,mac=&sysmacroname ,mac=MV_CREATEFILE
,msg=%str(path value must be provided) ,msg=%str(path value must be provided)
) )
%mp_abort(iftrue=(%mf_isblank(&name)=1 or %length(&name)=1) %mp_abort(iftrue=(%mf_isblank(&name)=1 or %length(&name)=1)
,mac=&sysmacroname ,mac=MV_CREATEFILE
,msg=%str(name value with length >1 must be provided) ,msg=%str(name value with length >1 must be provided)
) )
@@ -24331,6 +24423,12 @@ run;
%end; %end;
%else %put %str(ERR)OR: invalid value for intype: &intype; %else %put %str(ERR)OR: invalid value for intype: &intype;
%if "&swap" ne "0" %then %do;
%mp_replace("%sysfunc(pathname(&fref))"
,findvar=%scan(&swap,1,%str( ))
,replacevar=%scan(&swap,2,%str( ))
)
%end;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
data _null_; data _null_;
@@ -24340,9 +24438,12 @@ run;
run; run;
%end; %end;
options noquotelenmax;
%local base_uri; /* location of rest apis */
%let base_uri=%trim(%mf_getplatform(VIYARESTAPI));
/* create folder if it does not already exist */ /* create folder if it does not already exist */
%local folderds parenturi; %local folderds self_uri;
%let folderds=%mf_getuniquename(prefix=folderds); %let folderds=%mf_getuniquename(prefix=folderds);
%mv_createfolder(path=&path %mv_createfolder(path=&path
,access_token_var=&access_token_var ,access_token_var=&access_token_var
@@ -24355,60 +24456,168 @@ data _null_;
call symputx('self_uri',self_uri,'l'); call symputx('self_uri',self_uri,'l');
run; run;
/* abort or delete if file already exists */
%let force=%upcase(&force);
%local fileuri ;
%let fileuri=%trim(%mfv_getpathuri(&path/&name));
%mp_abort(iftrue=(%mf_isblank(&fileuri)=0 and &force ne YES)
,mac=MV_CREATEFILE
,msg=%str(File &path/&name already exists and force=&force)
)
%mp_abort(
iftrue=(&syscc ne 0),
mac=MV_CREATEFILE182
msg=syscc=&syscc after mfv_getpathuri
)
options noquotelenmax; %if %mf_isblank(&fileuri)=0 and &force=YES %then %do;
%local base_uri; /* location of rest apis */ proc http method="DELETE" url="&base_uri&fileuri" &oauth_bearer;
%let base_uri=%mf_getplatform(VIYARESTAPI); headers
%if &grant_type=authorization_code %then %do;
"Authorization"="Bearer &&&access_token_var"
%end;
"Accept"="*/*";
run;
%put &sysmacroname DELETE &base_uri&fileuri;
%if &SYS_PROCHTTP_STATUS_CODE ne 204 %then %do;
%put &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%end;
%end;
%local url mimetype; %local url mimetype ext;
%let url=&base_uri/files/files?parentFolderUri=&self_uri; %let url=&base_uri/files/files?parentFolderUri=&self_uri;
%let ext=%upcase(%trim(%scan(&name,-1,.)));
/* Get Viya file-extension details into some macro variables */
%mv_getViyaFileExtParms(&ext
,propertiesVar=viyaProperties
,typeDefNameVar=viyaTypeDefName
,mdebug=&mdebug);
/* fetch job info */ /* fetch job info */
%local fname1; %local fname1;
%let fname1=%mf_getuniquefileref(); %let fname1=%mf_getuniquefileref();
proc http method='POST' out=&fname1 &oauth_bearer in=&fref proc http method='POST' out=&fname1 &oauth_bearer in=&fref
%if "&ctype" = "0" %then %do; %if "&ctype" = "0" %then %do;
%let mimetype=%mf_mimetype(%scan(&name,-1,.)); %let mimetype=%mf_mimetype(&ext);
ct="&mimetype" ct="&mimetype"
%end; %end;
%else %do; %else %do;
ct="&ctype" ct="&ctype"
%end; %end;
%if "&mimetype"="text/html" %then %do;
url="&url%str(&)typeDefName=file"; /* typeDefName */
%if not %mf_isBlank(&viyaTypeDefName) %then %do;
url="&url%str(&)typeDefName=&viyaTypeDefName";
%end; %end;
%else %do; %else %do;
url="&url"; %if "&ext"="HTM" or "&ext"="HTML" or "&ext"="XHTML" %then %do;
url="&url%str(&)typeDefName=file_html";
%end;
%else %do;
%if "&ext"="CSS" or "&ext"="JS" or "&ext"="PNG" or "&ext"="SVG" %then %do;
url="&url%str(&)typeDefName=file_%lowcase(&ext)";
%end;
%else %do;
url="&url";
%end;
%end;
%end; %end;
headers "Accept"="application/json" headers "Accept"="application/json"
%if &grant_type=authorization_code %then %do; %if &grant_type=authorization_code %then %do;
"Authorization"="Bearer &&&access_token_var" "Authorization"="Bearer &&&access_token_var"
%end; %end;
"Content-Disposition"= "&contentdisp filename=""&name""; name=""&name"";"; "Content-Disposition"=
%if "&ext"="SVG" or "&ext"="HTML" %then %do;
"filename=""&name"";"
%end;
%else %do;
"&contentdisp filename=""&name""; name=""&name"";"
%end;
;
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE; %if &mdebug=1 %then %put &sysmacroname POST &=url
%put &=SYS_PROCHTTP_STATUS_PHRASE; &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201) %mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
,mac=&sysmacroname ,mac=MV_CREATEFILE
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
) )
%local libref2; %local libref2;
%let libref2=%mf_getuniquelibref(); %let libref2=%mf_getuniquelibref();
libname &libref2 JSON fileref=&fname1; libname &libref2 JSON fileref=&fname1;
%put Grabbing the follow on link ; /* Grab the follow on link */
data &outds; data &outds;
set &libref2..links end=last; set &libref2..links end=last;
if rel='createChild' then do; if rel='createChild' then do;
call symputx('href',quote(cats("&base_uri",href)),'l');
&dbg put (_all_)(=); &dbg put (_all_)(=);
end; end;
run; run;
%put &sysmacroname: File &name successfully created:;%put; /* URI of the created file */
%put &base_uri%mfv_getpathuri(&path/&name);%put; %let fileuri=%trim(%mfv_getpathuri(&path/&name));
%put &base_uri/SASJobExecution?_file=&path/&name;%put;
%put &sysmacroname:; /* If properties were found then patch the file to include them */
%if not %mf_isBlank(%superq(viyaProperties)) %then %do;
/* Wrap the properties object in a root object also containing the file name */
%local viyapatch;
%let viyapatch = %sysfunc(pathname(work))/%mf_getuniquename(prefix=patch_json_);
data _null_;
length line $32767;
file "&viyapatch" lrecl=32767;
put '{ "name": "' "&name" '",';
line = cat('"properties": ',symget("viyaProperties"));
put line;
put '}';
stop;
run;
%if &mdebug=1 %then %do;
data _null_;
if (_n_ eq 1) then put 'DEBUG: ** PATCH JSON **';
infile "&viyapatch" end=last;
input;
put _infile_;
run;
%end;
/* And apply the properties to the newly created file, using the PATCH method */
%let fref=%mf_getuniquefileref();
filename &fref "&viyapatch";
%let url=&base_uri&fileuri;
proc http method='PATCH' oauth_bearer=sas_services in=&fref
url="&url";
headers "Accept"="application/json"
"Content-Type"="application/json"
"If-Match"="*";
%if &mdebug=1 %then %do;
debug level=2;
%end;
run;
%if &mdebug=1 %then %put &sysmacroname PATCH &=url
&=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200)
,mac=MV_CREATEFILE
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
)
%end;
%put &sysmacroname: &base_uri&fileuri;
%put /SASJobExecution?_file=&path/&name;%put;
%if &mdebug=0 %then %do;
/* clear refs */
filename &fname1 clear;
filename &fref clear;
libname &libref2 clear;
%end;
%mp_abort(
iftrue=(&syscc ne 0),
msg=Cannot leave &sysmacroname with syscc=&syscc
)
%mend mv_createfile;/** %mend mv_createfile;/**
@file mv_createfolder.sas @file mv_createfolder.sas
@@ -24458,8 +24667,13 @@ run;
%end; %end;
%else %let dbg=*; %else %let dbg=*;
%mp_abort(
iftrue=(&syscc ne 0),
msg=Cannot enter &sysmacroname with syscc=&syscc
)
%if %mfv_existfolder(&path)=1 %then %do; %if %mfv_existfolder(&path)=1 %then %do;
%put &sysmacroname: &path already exists; %&dbg.put &sysmacroname: &path already exists;
data &outds; data &outds;
self_uri="%mfv_getpathuri(&path)"; self_uri="%mfv_getpathuri(&path)";
output; output;
@@ -24467,6 +24681,7 @@ run;
run; run;
%return; %return;
%end; %end;
%mp_abort(iftrue=(&syscc ne 0),msg=syscc=&syscc when folder checking)
%local oauth_bearer; %local oauth_bearer;
%if &grant_type=detect %then %do; %if &grant_type=detect %then %do;
@@ -24520,6 +24735,17 @@ options noquotelenmax;
headers "Authorization"="Bearer &&&access_token_var"; headers "Authorization"="Bearer &&&access_token_var";
%end; %end;
run; run;
%if &SYS_PROCHTTP_STATUS_CODE=401 %then %do;
/* relates to: https://github.com/sasjs/core/issues/400 */
%put 401 thrown in &sysmacroname;
%put sleeping: %sysfunc(sleep(12,1)) secs - will try again;
proc http method='GET' out=&fname1 &oauth_bearer
url="&base_uri/folders/folders/@item?path=&newpath";
%if &grant_type=authorization_code %then %do;
headers "Authorization"="Bearer &&&access_token_var";
%end;
run;
%end;
%local libref1; %local libref1;
%let libref1=%mf_getuniquelibref(); %let libref1=%mf_getuniquelibref();
libname &libref1 JSON fileref=&fname1; libname &libref1 JSON fileref=&fname1;
@@ -24527,7 +24753,7 @@ options noquotelenmax;
iftrue=( iftrue=(
&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 404 &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 404
) )
,mac=&sysmacroname ,mac=mv_createfolder124
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
) )
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
@@ -24576,8 +24802,9 @@ options noquotelenmax;
'Content-Type'='application/vnd.sas.content.folder+json' 'Content-Type'='application/vnd.sas.content.folder+json'
'Accept'='application/vnd.sas.content.folder+json'; 'Accept'='application/vnd.sas.content.folder+json';
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE; %if &SYS_PROCHTTP_STATUS_CODE ne 201 %then %do;
%put &=SYS_PROCHTTP_STATUS_PHRASE; %put &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%end;
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201) %mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
,mac=&sysmacroname ,mac=&sysmacroname
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
@@ -24605,6 +24832,10 @@ options noquotelenmax;
filename &fname1 clear; filename &fname1 clear;
libname &libref1 clear; libname &libref1 clear;
%end; %end;
%mp_abort(
iftrue=(&syscc ne 0),
msg=Cannot leave &sysmacroname with syscc=&syscc
)
%mend mv_createfolder;/** %mend mv_createfolder;/**
@file @file
@brief Creates a Viya Job @brief Creates a Viya Job
@@ -25084,7 +25315,7 @@ options noquotelenmax;
%let path=%substr(&path,1,%length(&path)-1); %let path=%substr(&path,1,%length(&path)-1);
/* ensure folder exists */ /* ensure folder exists */
%put &sysmacroname: Path &path being checked / created; %&dbg.put &sysmacroname: Path &path being checked / created;
%mv_createfolder(path=&path) %mv_createfolder(path=&path)
%local base_uri; /* location of rest apis */ %local base_uri; /* location of rest apis */
@@ -25917,13 +26148,8 @@ run;
libname &libref1 clear; libname &libref1 clear;
%end; %end;
%put &sysmacroname: Job &name successfully created in &path; %put &sysmacroname: Job &name created! Check it out:;
%put &sysmacroname:; %put &url/SASJobExecution?_PROGRAM=&path/&name;
%put &sysmacroname: Check it out here:;
%put &sysmacroname:;%put;
%put &url/SASJobExecution?_PROGRAM=&path/&name;%put;
%put &sysmacroname:;
%put &sysmacroname:;
%mend mv_createwebservice; %mend mv_createwebservice;
/** /**
@@ -26039,13 +26265,15 @@ proc http method='GET' out=&fname1a &oauth_bearer
headers "Authorization"="Bearer &&&access_token_var"; headers "Authorization"="Bearer &&&access_token_var";
%end; %end;
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE; %if &SYS_PROCHTTP_STATUS_CODE ne 200 %then %do;
%put &=sysmacroname &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%end;
%local libref1a; %local libref1a;
%let libref1a=%mf_getuniquelibref(); %let libref1a=%mf_getuniquelibref();
libname &libref1a JSON fileref=&fname1a; libname &libref1a JSON fileref=&fname1a;
%local uri found; %local uri found;
%let found=0; %let found=0;
%put Getting object uri from &libref1a..items; /* %put Getting object uri from &libref1a..items; */
data _null_; data _null_;
length contenttype name $1000; length contenttype name $1000;
set &libref1a..items; set &libref1a..items;
@@ -26150,8 +26378,7 @@ libname &libref1a clear;
options noquotelenmax; options noquotelenmax;
%local base_uri; /* location of rest apis */ %local base_uri; /* location of rest apis */
%let base_uri=%mf_getplatform(VIYARESTAPI); %let base_uri=%mf_getplatform(VIYARESTAPI);
/* fetch the members of the folder to get the uri */
%put &sysmacroname: fetching details for &path ;
%local fname1; %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
@@ -26171,7 +26398,7 @@ run;
) )
%end; %end;
%put &sysmacroname: grab the follow on link ; /* grab the follow on link */
%local libref1; %local libref1;
%let libref1=%mf_getuniquelibref(); %let libref1=%mf_getuniquelibref();
libname &libref1 JSON fileref=&fname1; libname &libref1 JSON fileref=&fname1;
@@ -26189,13 +26416,15 @@ proc http method='GET' out=&fname1a &oauth_bearer
headers "Authorization"="Bearer &&&access_token_var"; headers "Authorization"="Bearer &&&access_token_var";
%end; %end;
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE; %if &SYS_PROCHTTP_STATUS_CODE ne 200 %then %do;
%put &=sysmacroname &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%end;
%local libref1a; %local libref1a;
%let libref1a=%mf_getuniquelibref(); %let libref1a=%mf_getuniquelibref();
libname &libref1a JSON fileref=&fname1a; libname &libref1a JSON fileref=&fname1a;
%local uri found; %local uri found;
%let found=0; %let found=0;
%put Getting object uri from &libref1a..items; /* %put Getting object uri from &libref1a..items; */
data _null_; data _null_;
length contenttype name $1000; length contenttype name $1000;
set &libref1a..items; set &libref1a..items;
@@ -26221,7 +26450,7 @@ run;
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
) )
%end; %end;
%else %put &sysmacroname: &path/&name successfully deleted; %else %put &sysmacroname: &path/&name deleted;
/* clear refs */ /* clear refs */
filename &fname1 clear; filename &fname1 clear;
@@ -26230,8 +26459,8 @@ filename &fname1a clear;
libname &libref1a clear; libname &libref1a clear;
%mend mv_deletejes;/** %mend mv_deletejes;/**
@file mv_deleteviyafolder.sas @file
@brief Creates a viya folder if that folder does not already exist @brief Deletes a viya folder
@details If not running in Studo 5 +, will expect an oauth token in a global @details If not running in Studo 5 +, will expect an oauth token in a global
macro variable (default ACCESS_TOKEN). macro variable (default ACCESS_TOKEN).
@@ -27172,7 +27401,7 @@ data _null_;
uri=symget('uri'); uri=symget('uri');
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 too short - "!!uri,'l');
end; end;
if scan(uri,-1)='state' or scan(uri,1) ne 'jobExecution' then do; if scan(uri,-1)='state' or scan(uri,1) ne 'jobExecution' then do;
call symputx('errflg',1); call symputx('errflg',1);
@@ -27237,7 +27466,7 @@ data _null_;
uri=symget('loglocation'); uri=symget('loglocation');
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 too short - "!!uri,'l');
end; end;
else if (scan(uri,1,'/') ne 'compute' or scan(uri,2,'/') ne 'sessions') else if (scan(uri,1,'/') ne 'compute' or scan(uri,2,'/') ne 'sessions')
and (scan(uri,1,'/') ne 'files' or scan(uri,2,'/') ne 'files') and (scan(uri,1,'/') ne 'files' or scan(uri,2,'/') ne 'files')
@@ -27949,6 +28178,252 @@ filename &fname1 clear;
libname &libref1 clear; libname &libref1 clear;
%mend mv_getusers;/** %mend mv_getusers;/**
@file mv_getviyafileextparms.sas
@brief Reads the VIYA file-extension type definition and returns selected
values in SAS macro variables
@details Content is derived from the following endpoint:
"https://${serverUrl}/types/types?limit=999999"
@param [in] ext File extension to retrieve property info for.
@param [out] propertiesVar= SAS macro variable name that will contain
the 'properties' object json, if found, else blank.
@param [out] typeDefNameVar= SAS macro variable name that will contain
the 'typeDefName' property value, if found, else blank.
@param [out] mediaTypeVar= SAS macro variable name that will contain
the 'mediaType' property value, if found, else blank.
@param [out] viyaFileExtRespLibDs (work.mv_getViyaFileExtParmsResponse)
Library.name of the dataset to receive the local working copy of the initial
response that requests all file extension details. Created once per session
to avoid multiple api calls.
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
<h4> SAS Macros </h4>
@li mf_existds.sas
@li mf_getplatform.sas
@li mf_getuniquefileref.sas
@li mf_getuniquename.sas
@li mf_getvalue.sas
@li mf_getvarlist.sas
@li mf_getvartype.sas
@li mf_nobs.sas
@li mp_abort.sas
*/
%macro mv_getViyaFileExtParms(
ext,
typeDefNameVar=,
propertiesVar=,
mediaTypeVar=,
viyaFileExtRespLibDs=work.mv_getViyaFileExtParmsResponse,
mdebug=0
);
%local base_uri; /* location of rest apis */
%local url; /* File extension info end-point */
%mp_abort(
iftrue=(%mf_isBlank(&ext))
,msg=%str(No file extension provided.)
,mac=MV_GETVIYAFILEEXTPARMS
);
%mp_abort(
iftrue=(%mf_isBlank(&typeDefNameVar) and
%mf_isBlank(&propertiesVar) and
%mf_isBlank(&mediaTypeVar))
,msg=%str(MV_GETVIYAFILEEXTPARMS - No parameter was requested.)
,mac=MV_GETVIYAFILEEXTPARMS
);
%mp_abort(
iftrue=(%mf_isBlank(&viyaFileExtRespLibDs))
,msg=%str(No <libname.>dataset name provided to cache inital response.)
,mac=MV_GETVIYAFILEEXTPARMS
);
/* Declare requested parameters as global macro vars and initialize blank */
%if not %mf_isBlank(&typeDefNameVar) %then %do;
%global &typeDefNameVar;
%let &typeDefNameVar = %str();
%end;
%if not %mf_isBlank(&propertiesVar) %then %do;
%global &propertiesVar;
%let &propertiesVar = %str();
%end;
%if not %mf_isBlank(&mediaTypeVar) %then %do;
%global &mediaTypeVar;
%let &mediaTypeVar = %str();
%end;
%let base_uri=%mf_getplatform(VIYARESTAPI);
%if &mdebug=1 %then %do;
%put DEBUG: &=base_uri;
%end;
%let ext=%lowcase(&ext);
/* Create a local copy of the Viya response containing all file type info, if
it does not already exist. */
%if not %mf_existds(&viyaFileExtRespLibDs) %then %do;
/* Create a temp file and fill with JSON that declares */
/* VIYA file-type details for the given file extension */
%local viyatypedefs;
%let viyatypedefs=%mf_getuniquefileref();
filename &viyatypedefs temp;
%let url = &base_uri/types/types?limit=999999;
proc http oauth_bearer=sas_services out=&viyatypedefs
url="&url";
run;
%if &mdebug=1 %then %put DEBUG: &sysmacroname &=url
&=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%if (&SYS_PROCHTTP_STATUS_CODE ne 200) %then %do;
/* To avoid a breaking change, exit early if the request failed.
The calling process will proceed with empty requested macro variables. */
%put INFO: &sysmacroname File extension details were not retrieved.;
filename &viyatypedefs clear;
%return;
%end;
%if &mdebug=1 %then %do;
/* Dump the response to the log */
data _null_;
length line $120;
null=byte(0);
infile &viyatypedefs dlm=null lrecl=120 recfm=n;
input line $120.;
if _n_ = 1 then put "DEBUG:";
put line;
run;
%end;
/* Convert the content of that JSON into SAS datasets */
/* First prepare a new WORK-based folder to receive the datasets */
%local jsonworkfolder jsonlib opt_dlcreatedir;
%let jsonworkfolder=%sysfunc(pathname(work))/%mf_getuniquename(prefix=json_);
%let jsonlib=%mf_getuniquelibref(prefix=json);
/* And point a libname at it */
%let opt_dlcreatedir = %sysfunc(getoption(dlcreatedir));
options dlcreatedir; libname &jsonlib "&jsonworkfolder"; options &opt_dlcreatedir;
/* Read the json output once and copy datasets to its work folder */
%local libref1;
%let libref1=%mf_getuniquelibref();
libname &libref1 JSON fileref=&viyatypedefs automap=create;
proc copy in=&libref1 out=&jsonlib; run;
libname &libref1 clear;
/* Now give all rows belonging to the same items array a grouping value */
data &viyaFileExtRespLibDs;
length _viyaItemIdx 8;
set &jsonlib..alldata;
retain _viyaItemIdx 0;
/* Increment the row group index when a new 'items' group is observed */
if P=1 and P1='items' then _viyaItemIdx + 1;
run;
%if &mdebug=0 %then %do;
/* Tidy up, unless debug=1 */
proc datasets library=&jsonlib nolist kill; quit;
libname &jsonlib clear;
%end;
filename &viyatypedefs clear;
%end; /* If initial filetype query response didn't exist */
/* Find the row-group for the current file extension */
%local itemRowGroup;
%let itemRowGroup =
%mf_getValue(
&viyaFileExtRespLibDs
,_viyaItemIdx
,filter=%quote(p1='items' and p2='extensions' and value="&ext")
);
%if &mdebug %then %put DEBUG: &=itemRowGroup;
%if %mf_isBlank(&itemRowGroup) %then %do;
/* extension was not found */
%if(&mdebug=1) %then %put DEBUG: No type details found for extension "&ext".;
%return;
%end;
/* Filter the cached response data down to the required file extension */
%local dsItems;
%let dsItems = %mf_getuniquename(prefix=dsItems_);
data work.&dsItems;
set &viyaFileExtRespLibDs;
where _viyaItemIdx = &itemRowGroup;
run;
/* Populate typeDefName, if requested */
%if (not %mf_isBlank(&typeDefNameVar)) %then %do;
%let &typeDefNameVar = %mf_getvalue(&dsItems,value,filter=%quote(p1="items" and p2="name"));
%if &mdebug=1 %then %put DEBUG: &=typeDefNameVar &typeDefNameVar=&&&typeDefNameVar;
%end;
/* Populate mediaType, if requested */
%if (not %mf_isBlank(&mediaTypeVar)) %then %do;
%let &mediaTypeVar = %mf_getvalue(&dsItems,value,filter=%quote(p1="items" and p2="mediaType"));
%if &mdebug=1 %then %put DEBUG: &=mediaTypeVar &mediaTypeVar=&&&mediaTypeVar;
%end;
/* Populate properties macro variable, if requested */
%if not %mf_isBlank(&propertiesVar) %then %do;
/* Filter dsItems down to the properties */
%local dsProperties;
%let dsProperties = %mf_getuniquename(prefix=dsProperties_);
data work.&dsProperties ( rename=(p3 = propertyName) );
set work.&dsItems;
where p2="properties" and v=1;
run;
/* Check for 1+ properties */
%if ( %mf_nobs(&dsProperties) = 0 ) %then %do;
%let &propertiesVar = %str();
%if &mdebug=1 %then %put DEBUG: &SYSMACRONAME - No Viya properties found for file suffix %str(%')&ext%str(%');
%end;
%else %do;
/* Properties potentially span multiple rows in the input table */
data _null_;
length
line $32767
properties $32767
;
retain properties;
set &dsProperties end=last;
if _n_ = 1 then properties = '{';
line = cats(quote(trim(propertyName)),':');
/* Only strings and bools appear in properties */
if value not in ("true","false") then value = quote(trim(value));
line = catx(' ',line,value);
/* Add a comma separator to all except the last line */
if not last then line = cats(line,',');
/* Add this line to the output value */
properties = catx(' ',properties,line);
if last then do;
/* Close off the properties object and output to the macro variable */
properties=catx(' ',properties,'}');
call symputx("&propertiesVar",properties);
end;
run;
%if &mdebug=1 %then %put DEBUG: &=propertiesVar &propertiesVar=&&&propertiesVar;
%end;
%end;
%mend mv_getViyaFileExtParms;/**
@file @file
@brief Executes a SAS Viya Job @brief Executes a SAS Viya Job
@details Triggers a SAS Viya Job, with optional URL parameters, using @details Triggers a SAS Viya Job, with optional URL parameters, using
@@ -28325,6 +28800,8 @@ run;
%if %mf_existvarList(&inds,FLOW_ID)=0 %then %do; %if %mf_existvarList(&inds,FLOW_ID)=0 %then %do;
retain FLOW_ID 0; retain FLOW_ID 0;
%end; %end;
/* https://github.com/sasjs/adapter/pull/845#issuecomment-2956589644 */
retain _omitSessionResults "false";
set &inds; set &inds;
&dbg. putlog (_all_)(=); &dbg. putlog (_all_)(=);
run; run;

View File

@@ -26,7 +26,7 @@
@author Allan Bowe @author Allan Bowe
**/ **/
%macro mf_getuniquelibref(prefix=mclib,maxtries=1000); %macro mf_getuniquelibref(prefix=mc,maxtries=1000);
%local x; %local x;
%if ( %length(&prefix) gt 7 ) %then %do; %if ( %length(&prefix) gt 7 ) %then %do;

View File

@@ -73,10 +73,6 @@
ignorelist=, ignorelist=,
outds=work.test_results outds=work.test_results
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local ds test_result test_comments del add mod ilist;
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS SYS_PROCHTTP_STATUS_CODE
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
* behaviour is not desired, simply initiate the following global macro * behaviour is not desired, simply initiate the following global macro
@@ -84,6 +80,10 @@
*/ */
%mp_init() %mp_init()
%local ds test_result test_comments del add mod ilist;
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS SYS_PROCHTTP_STATUS_CODE
SYS_PROCHTTP_STATUS_CODE SYS_PROCHTTP_STATUS_PHRASE &ignorelist);
/* get current variables */ /* get current variables */
%if &action=SNAPSHOT %then %do; %if &action=SNAPSHOT %then %do;
proc sql; proc sql;

View File

@@ -33,7 +33,8 @@
LUA, you can also use this macro: mp_gsubfile.sas LUA, you can also use this macro: mp_gsubfile.sas
@param [in] infile The QUOTED path to the file on which to perform the @param [in] infile The QUOTED path to the file on which to perform the
substitution substitution. Note that you can extract the pathname from a fileref using
the pathname function, eg: `"%sysfunc(pathname(fref))"`;
@param [in] findvar= Macro variable NAME containing the string to search for @param [in] findvar= Macro variable NAME containing the string to search for
@param [in] replacevar= Macro variable NAME containing the replacement string @param [in] replacevar= Macro variable NAME containing the replacement string
@param [out] outfile= (0) Optional QUOTED path to the adjusted output file (to @param [out] outfile= (0) Optional QUOTED path to the adjusted output file (to
@@ -147,6 +148,6 @@ data _null_;
run; run;
/* END */ /* END */
%put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) seconds to run; /* %put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) secs to run; */
%mend mp_replace; %mend mp_replace;

View File

@@ -0,0 +1,31 @@
/**
@file
@brief Testing mfv_getfolderpath macro function
<h4> SAS Macros </h4>
@li mf_uid.sas
@li mfv_getfolderpath.sas
@li mfv_getpathuri.sas
@li mp_assert.sas
@li mv_createfolder.sas
**/
options mprint sgen;
%let folder=%mf_uid();
/* create a folder */
%mv_createfolder(path=&mcTestAppLoc/&folder)
%mp_assert(
iftrue=(&syscc=0),
desc=no errs on folder creation
)
%let uri=%mfv_getpathuri(&mcTestAppLoc/&folder);
%put %mfv_getfolderpath(&uri);
%mp_assert(
iftrue=("%mfv_getfolderpath(&uri)"="&mcTestAppLoc/&folder"),
desc=Check if correct folder was returned
)

View File

@@ -14,7 +14,7 @@ options mprint sgen;
%let file=%mf_uid(); %let file=%mf_uid();
/* create a folder */ /* create a file */
filename somefile temp; filename somefile temp;
data _null_; data _null_;
file somefile; file somefile;

View File

@@ -23,7 +23,7 @@ data _null_;
put 'hello testings'; put 'hello testings';
run; run;
%mp_assertscope(SNAPSHOT) %mp_assertscope(SNAPSHOT)
%mv_createfile(path=&mcTestAppLoc/temp, name=&file..txt,inref=somefile,mdebug=1) %mv_createfile(path=&mcTestAppLoc, name=&file..txt,inref=somefile,mdebug=1)
%mp_assertscope(COMPARE %mp_assertscope(COMPARE
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADP2LEN MCLIB0_JADPNUM ,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADP2LEN MCLIB0_JADPNUM
MCLIB0_JADVLEN MCLIB2_JADP1LEN MCLIB0_JADVLEN MCLIB2_JADP1LEN
@@ -32,7 +32,7 @@ run;
) )
%mp_assert( %mp_assert(
iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..txt)=1), iftrue=(%mfv_existfile(&mcTestAppLoc/&file..txt)=1),
desc=Check if created file exists desc=Check if created file exists
) )
@@ -42,10 +42,10 @@ data _null_;
file f2; file f2;
put '<html><body><p>Hello world</p></body></html>'; put '<html><body><p>Hello world</p></body></html>';
run; run;
%mv_createfile(path=&mcTestAppLoc/temp, name=test.html,inref=f2,mdebug=1) %mv_createfile(path=&mcTestAppLoc, name=test.html,inref=f2,mdebug=1)
%mp_assert( %mp_assert(
iftrue=(%mfv_existfile(&mcTestAppLoc/temp/test.html)=1), iftrue=(%mfv_existfile(&mcTestAppLoc/test.html)=1),
desc=Check if created file exists desc=Check if created file exists
) )
@@ -55,10 +55,10 @@ x=1;
run; run;
filename ds "%sysfunc(pathname(work))/temp.sas7bdat"; filename ds "%sysfunc(pathname(work))/temp.sas7bdat";
%mv_createfile(path=&mcTestAppLoc/temp, name=&file..sas7bdat,inref=ds,mdebug=1) %mv_createfile(path=&mcTestAppLoc, name=&file..sas7bdat,inref=ds,mdebug=1)
%mp_assert( %mp_assert(
iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..sas7bdat)=1), iftrue=(%mfv_existfile(&mcTestAppLoc/&file..sas7bdat)=1),
desc=Check if created dataset exists desc=Check if created dataset exists
) )
@@ -68,19 +68,44 @@ data _null_;
file f4; file f4;
put '%put hello FromSASStudioBailey; '; put '%put hello FromSASStudioBailey; ';
run; run;
%mv_createfile(path=&mcTestAppLoc/temp, name=test4.sas,inref=f4,mdebug=1) %mv_createfile(path=&mcTestAppLoc, name=test4.sas,inref=f4,mdebug=1)
%mp_assert( %mp_assert(
iftrue=(%mfv_existfile(&mcTestAppLoc/temp/test4.sas)=1), iftrue=(%mfv_existfile(&mcTestAppLoc/test4.sas)=1),
desc=Check if created sas program exists desc=Check if created sas program exists
) )
%put TEST 5 - reading from files service and writing back; %put TEST 5 - reading from files service and writing back;
filename sendfrom filesrvc folderpath="&mcTestAppLoc/temp" filename='test4.sas'; filename sendfrom filesrvc folderpath="&mcTestAppLoc" filename='test4.sas';
OPTIONS MERROR SYMBOLGEN MLOGIC MPRINT; OPTIONS MERROR SYMBOLGEN MLOGIC MPRINT;
%mv_createfile(path=&mcTestAppLoc/temp,name=test5.sas,inref=sendfrom,mdebug=1) ; %mv_createfile(path=&mcTestAppLoc,name=test5.sas,inref=sendfrom,mdebug=1) ;
%put TEST 6 - try the find and replace;
filename f6 temp;
data _null_;
file f6;
put '//Hello world!';
put 'let var=/some/path/name;';
run;
%let in=/some/path/name;
%let out=/final/destination;
%mv_createfile(path=&mcTestAppLoc, name=test6.js,inref=f6,mdebug=1,swap=in out)
filename getback filesrvc folderpath="&mcTestAppLoc" filename='test6.js';
%let test6=0;
data _null_;
infile getback;
input;
if _infile_="let var=&out;" then call symputx('test6',1);
putlog _infile_;
run;
%mp_assert(
iftrue=(&test6=1),
desc=Check if find & replace worked
)

View File

@@ -0,0 +1,95 @@
/**
@file
@brief Testing mv_getviyafileextparms macro
<h4> SAS Macros </h4>
@li mf_isBlank.sas
@li mp_assert.sas
@li mp_assertscope.sas
@li mv_getviyafileextparms.sas
**/
options mprint;
%let mvarIgnoreList =
MC0_JADP1LEN MC0_JADP2LEN MC0_JADP3LEN MC0_JADPNUM MC0_JADVLEN;
%put TEST 1 - Test with common extension, requesting only typeDefName parameter;
%mp_assertscope(SNAPSHOT)
%mv_getviyafileextparms(ext=txt, typeDefNameVar=viyaTypeDefName)
%mp_assertscope(COMPARE
,ignorelist=&mvarIgnoreList viyaTypeDefName
)
%mp_assert(
iftrue=(not %mf_isBlank(&viyaTypeDefName)),
desc=Check the requested macro variable viyaTypeDefName is not blank.
)
%put TEST 2 - Test with common extension, requesting only properties parameter;
%mp_assertscope(SNAPSHOT)
%mv_getviyafileextparms(ext=html, propertiesVar=viyaProperties)
%mp_assertscope(COMPARE
,ignorelist=&mvarIgnoreList viyaProperties
)
%mp_assert(
iftrue=(not %mf_isBlank(%superq(viyaProperties))),
desc=Check the requested macro variable viyaProperties is not blank.
)
%put TEST 3 - Test with common extension, requesting only mediaType parameter;
%mp_assertscope(SNAPSHOT)
%mv_getviyafileextparms(ext=mp3, mediaTypeVar=viyaMediaType)
%mp_assertscope(COMPARE
,ignorelist=&mvarIgnoreList viyaMediaType
)
%mp_assert(
iftrue=(not %mf_isBlank(&viyaMediaType)),
desc=Check the requested macro variable viyaMediaType is not blank.
)
%put TEST 4 - Test with common extension, requesting all parameters;
%mp_assertscope(SNAPSHOT)
%mv_getviyafileextparms(
ext=css,
typeDefNameVar=cssViyaTypeDefName,
propertiesVar=cssViyaProperties,
mediaTypeVar=cssViyaMediaType
)
%mp_assertscope(COMPARE
,ignorelist=
&mvarIgnoreList cssViyaTypeDefName cssViyaProperties cssViyaMediaType
)
%mp_assert(
iftrue=(not ( %mf_isBlank(&cssViyaTypeDefName) or
%mf_isBlank(%superq(cssViyaProperties)) or
%mf_isBlank(&cssViyaMediaType) ) ),
desc=Check a full set of requested macro variables are not blank.
)
%put TEST 5 - Test with invalid extension - requested parameters will be blank;
%mp_assertscope(SNAPSHOT)
%mv_getviyafileextparms(
ext=xxxINVALIDxxx,
typeDefNameVar=invalidTypeDefName,
propertiesVar=invalidProperties,
mediaTypeVar=invalidMediaType
)
%mp_assertscope(COMPARE
,ignorelist=
&mvarIgnoreList invalidTypeDefName invalidProperties invalidMediaType
)
%mp_assert(
iftrue=(
%mf_isBlank(&invalidTypeDefName) and
%mf_isBlank(%superq(invalidProperties)) and
%mf_isBlank(&invalidMediaType)
),
desc=Check the requested macro variables are all blank.
)

View File

@@ -33,16 +33,23 @@
msg=Cannot enter mfv_existfolder.sas with syscc=&syscc msg=Cannot enter mfv_existfolder.sas with syscc=&syscc
) )
%local fref rc; %local fref rc var;
%let fref=%mf_getuniquefileref(); %let fref=%mf_getuniquefileref();
%if %sysfunc(filename(fref,,filesrvc,folderPath="&path"))=0 %then %do; %if %sysfunc(filename(fref,,filesrvc,folderPath="&path"))=0 %then %do;
1 1
%let var=_FILESRVC_&fref._URI;
%let rc=%sysfunc(filename(fref)); %let rc=%sysfunc(filename(fref));
%symdel &var;
%end; %end;
%else %do; %else %do;
0 0
%let syscc=0; %let syscc=0;
%end; %end;
%mf_abort(
iftrue=(&syscc ne 0),
msg=Cannot leave mfv_existfolder.sas with syscc=&syscc
)
%mend mfv_existfolder; %mend mfv_existfolder;

View File

@@ -0,0 +1,53 @@
/**
@file
@brief Returns the path of a folder from the URI
@details Makes use of the SYSMSG() ER8OR response, which resolves the uri,
seemingly without entering an er8or state.
Usage:
%mv_createfolder(path=/public/demo)
%let uri=%mfv_getpathuri(/public/demo);
%put %mfv_getfolderpath(&uri);
Notice above the new path has an uppercase P - the correct path.
@param [in] uri The uri of the folder -eg /folders/folders/xxxx)
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
<h4> Related Macros </h4>
@li mfv_getpathuri.sas
@version 4
@author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
**/
%macro mfv_getfolderpath(uri
)/*/STORE SOURCE*/;
%local fref rc path msg var /* var used to avoid delete timing issue */;
%let fref=%mf_getuniquefileref();
%if %quote(%substr(%str(&uri),1,17)) ne %quote(/folders/folders/)
%then %do;
%put &sysmacroname: Invalid URI: &uri;
%end;
%else %if %sysfunc(filename(fref,,filesrvc,folderuri="&uri" ))=0
%then %do;
%let var=_FILESRVC_&fref._URI;
%local fid ;
%let fid= %sysfunc(fopen(&fref,I));
%let msg=%quote(%sysfunc(sysmsg()));
%unquote(%scan(&msg,2,%str(,.)))
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(fref));
%symdel &var;
%end;
%else %do;
%put &sysmacroname: Not Found: &uri;
%let syscc=0;
%end;
%mend mfv_getfolderpath ;

View File

@@ -1,13 +1,13 @@
/** /**
@file @file
@brief Returns the uri of a file or folder @brief Returns the uri of a file or folder
@details The automatic variable _FILESRVC_[fref]_URI is used after assigning @details The automatic variable `_FILESRVC_[fref]_URI` is used after assigning
a fileref using the filesrvc engine. a fileref using the filesrvc engine.
Usage: Usage:
%put %mfv_existfile(/Public/folder/file.txt); %put %mfv_getpathuri(/Public/folder/file.txt);
%put %mfv_existfile(/Public/folder); %put %mfv_getpathuri(/Public/folder);
@param [in] filepath The full path to the file on SAS drive @param [in] filepath The full path to the file on SAS drive
(eg /Public/myfile.txt) (eg /Public/myfile.txt)
@@ -49,4 +49,8 @@
%let syscc=0; %let syscc=0;
%end; %end;
%mf_abort(
iftrue=(&syscc ne 0),
msg=Cannot leave &sysmacroname with syscc=&syscc
)
%mend mfv_getpathuri; %mend mfv_getpathuri;

View File

@@ -17,6 +17,20 @@
run; run;
%mv_createfile(path=/Public/temp,name=newfile.txt,inref=myfile) %mv_createfile(path=/Public/temp,name=newfile.txt,inref=myfile)
The macro also supports find & replace (used by the SASjs Streaming App
build program). This allows one string to be replaced by another at the
point at which the file is created. This is done by passing in the NAMES of
the macro variables containing the values to be swapped, eg:
filename fref temp;
data _null_;
file fref;
put 'whenever life gets you down, Mrs Brown..';
run;
%let f=Mrs Brown;
%let r=just remember that you're standing on a planet that's evolving;
%mv_createfile(path=/Public,name=life.md,inref=fref,fin,swap=f r)
@param [in] path= The parent (SAS Drive) folder in which to create the file @param [in] path= The parent (SAS Drive) folder in which to create the file
@param [in] name= The name of the file to be created @param [in] name= The name of the file to be created
@@ -36,6 +50,10 @@
@li password @li password
@li authorization_code @li authorization_code
@li sas_services @li sas_services
@param [in] force= (YES) Will overwrite (delete / recreate) files by default.
Set to NO to abort if a file already exists in that location.
@param pin] swap= (0) Provide two macro variable NAMES that contain the values
to be swapped, eg swap=find replace (see also the example above)
@param [out] outds= (_null_) Output dataset with the uri of the new file @param [out] outds= (_null_) Output dataset with the uri of the new file
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@@ -46,9 +64,12 @@
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_isblank.sas @li mf_isblank.sas
@li mf_mimetype.sas @li mf_mimetype.sas
@li mfv_getpathuri.sas
@li mp_abort.sas @li mp_abort.sas
@li mp_base64copy.sas @li mp_base64copy.sas
@li mp_replace.sas
@li mv_createfolder.sas @li mv_createfolder.sas
@li mv_getviyafileextparms.sas
<h4> Related Macros</h4> <h4> Related Macros</h4>
@li mv_createfile.sas @li mv_createfile.sas
@@ -65,6 +86,8 @@
,grant_type=sas_services ,grant_type=sas_services
,mdebug=0 ,mdebug=0
,outds=_null_ ,outds=_null_
,force=YES
,swap=0
); );
%local dbg; %local dbg;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
@@ -73,6 +96,11 @@
%end; %end;
%else %let dbg=*; %else %let dbg=*;
%mp_abort(
iftrue=(&syscc ne 0),
msg=Cannot enter &sysmacroname with syscc=&syscc
)
%local oauth_bearer; %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;
@@ -86,16 +114,16 @@
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password %mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
and &grant_type ne sas_services and &grant_type ne sas_services
) )
,mac=&sysmacroname ,mac=MV_CREATEFILE
,msg=%str(Invalid value for grant_type: &grant_type) ,msg=%str(Invalid value for grant_type: &grant_type)
) )
%mp_abort(iftrue=(%mf_isblank(&path)=1 or %length(&path)=1) %mp_abort(iftrue=(%mf_isblank(&path)=1 or %length(&path)=1)
,mac=&sysmacroname ,mac=MV_CREATEFILE
,msg=%str(path value must be provided) ,msg=%str(path value must be provided)
) )
%mp_abort(iftrue=(%mf_isblank(&name)=1 or %length(&name)=1) %mp_abort(iftrue=(%mf_isblank(&name)=1 or %length(&name)=1)
,mac=&sysmacroname ,mac=MV_CREATEFILE
,msg=%str(name value with length >1 must be provided) ,msg=%str(name value with length >1 must be provided)
) )
@@ -109,6 +137,12 @@
%end; %end;
%else %put %str(ERR)OR: invalid value for intype: &intype; %else %put %str(ERR)OR: invalid value for intype: &intype;
%if "&swap" ne "0" %then %do;
%mp_replace("%sysfunc(pathname(&fref))"
,findvar=%scan(&swap,1,%str( ))
,replacevar=%scan(&swap,2,%str( ))
)
%end;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
data _null_; data _null_;
@@ -118,9 +152,12 @@
run; run;
%end; %end;
options noquotelenmax;
%local base_uri; /* location of rest apis */
%let base_uri=%trim(%mf_getplatform(VIYARESTAPI));
/* create folder if it does not already exist */ /* create folder if it does not already exist */
%local folderds parenturi; %local folderds self_uri;
%let folderds=%mf_getuniquename(prefix=folderds); %let folderds=%mf_getuniquename(prefix=folderds);
%mv_createfolder(path=&path %mv_createfolder(path=&path
,access_token_var=&access_token_var ,access_token_var=&access_token_var
@@ -133,59 +170,167 @@ data _null_;
call symputx('self_uri',self_uri,'l'); call symputx('self_uri',self_uri,'l');
run; run;
/* abort or delete if file already exists */
%let force=%upcase(&force);
%local fileuri ;
%let fileuri=%trim(%mfv_getpathuri(&path/&name));
%mp_abort(iftrue=(%mf_isblank(&fileuri)=0 and &force ne YES)
,mac=MV_CREATEFILE
,msg=%str(File &path/&name already exists and force=&force)
)
%mp_abort(
iftrue=(&syscc ne 0),
mac=MV_CREATEFILE182
msg=syscc=&syscc after mfv_getpathuri
)
options noquotelenmax; %if %mf_isblank(&fileuri)=0 and &force=YES %then %do;
%local base_uri; /* location of rest apis */ proc http method="DELETE" url="&base_uri&fileuri" &oauth_bearer;
%let base_uri=%mf_getplatform(VIYARESTAPI); headers
%if &grant_type=authorization_code %then %do;
"Authorization"="Bearer &&&access_token_var"
%end;
"Accept"="*/*";
run;
%put &sysmacroname DELETE &base_uri&fileuri;
%if &SYS_PROCHTTP_STATUS_CODE ne 204 %then %do;
%put &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%end;
%end;
%local url mimetype; %local url mimetype ext;
%let url=&base_uri/files/files?parentFolderUri=&self_uri; %let url=&base_uri/files/files?parentFolderUri=&self_uri;
%let ext=%upcase(%trim(%scan(&name,-1,.)));
/* Get Viya file-extension details into some macro variables */
%mv_getViyaFileExtParms(&ext
,propertiesVar=viyaProperties
,typeDefNameVar=viyaTypeDefName
,mdebug=&mdebug);
/* fetch job info */ /* fetch job info */
%local fname1; %local fname1;
%let fname1=%mf_getuniquefileref(); %let fname1=%mf_getuniquefileref();
proc http method='POST' out=&fname1 &oauth_bearer in=&fref proc http method='POST' out=&fname1 &oauth_bearer in=&fref
%if "&ctype" = "0" %then %do; %if "&ctype" = "0" %then %do;
%let mimetype=%mf_mimetype(%scan(&name,-1,.)); %let mimetype=%mf_mimetype(&ext);
ct="&mimetype" ct="&mimetype"
%end; %end;
%else %do; %else %do;
ct="&ctype" ct="&ctype"
%end; %end;
%if "&mimetype"="text/html" %then %do;
url="&url%str(&)typeDefName=file"; /* typeDefName */
%if not %mf_isBlank(&viyaTypeDefName) %then %do;
url="&url%str(&)typeDefName=&viyaTypeDefName";
%end; %end;
%else %do; %else %do;
url="&url"; %if "&ext"="HTM" or "&ext"="HTML" or "&ext"="XHTML" %then %do;
url="&url%str(&)typeDefName=file_html";
%end;
%else %do;
%if "&ext"="CSS" or "&ext"="JS" or "&ext"="PNG" or "&ext"="SVG" %then %do;
url="&url%str(&)typeDefName=file_%lowcase(&ext)";
%end;
%else %do;
url="&url";
%end;
%end;
%end; %end;
headers "Accept"="application/json" headers "Accept"="application/json"
%if &grant_type=authorization_code %then %do; %if &grant_type=authorization_code %then %do;
"Authorization"="Bearer &&&access_token_var" "Authorization"="Bearer &&&access_token_var"
%end; %end;
"Content-Disposition"= "&contentdisp filename=""&name""; name=""&name"";"; "Content-Disposition"=
%if "&ext"="SVG" or "&ext"="HTML" %then %do;
"filename=""&name"";"
%end;
%else %do;
"&contentdisp filename=""&name""; name=""&name"";"
%end;
;
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE; %if &mdebug=1 %then %put &sysmacroname POST &=url
%put &=SYS_PROCHTTP_STATUS_PHRASE; &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201) %mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
,mac=&sysmacroname ,mac=MV_CREATEFILE
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
) )
%local libref2; %local libref2;
%let libref2=%mf_getuniquelibref(); %let libref2=%mf_getuniquelibref();
libname &libref2 JSON fileref=&fname1; libname &libref2 JSON fileref=&fname1;
%put Grabbing the follow on link ; /* Grab the follow on link */
data &outds; data &outds;
set &libref2..links end=last; set &libref2..links end=last;
if rel='createChild' then do; if rel='createChild' then do;
call symputx('href',quote(cats("&base_uri",href)),'l');
&dbg put (_all_)(=); &dbg put (_all_)(=);
end; end;
run; run;
%put &sysmacroname: File &name successfully created:;%put; /* URI of the created file */
%put &base_uri%mfv_getpathuri(&path/&name);%put; %let fileuri=%trim(%mfv_getpathuri(&path/&name));
%put &base_uri/SASJobExecution?_file=&path/&name;%put;
%put &sysmacroname:; /* If properties were found then patch the file to include them */
%if not %mf_isBlank(%superq(viyaProperties)) %then %do;
/* Wrap the properties object in a root object also containing the file name */
%local viyapatch;
%let viyapatch = %sysfunc(pathname(work))/%mf_getuniquename(prefix=patch_json_);
data _null_;
length line $32767;
file "&viyapatch" lrecl=32767;
put '{ "name": "' "&name" '",';
line = cat('"properties": ',symget("viyaProperties"));
put line;
put '}';
stop;
run;
%if &mdebug=1 %then %do;
data _null_;
if (_n_ eq 1) then put 'DEBUG: ** PATCH JSON **';
infile "&viyapatch" end=last;
input;
put _infile_;
run;
%end;
/* And apply the properties to the newly created file, using the PATCH method */
%let fref=%mf_getuniquefileref();
filename &fref "&viyapatch";
%let url=&base_uri&fileuri;
proc http method='PATCH' oauth_bearer=sas_services in=&fref
url="&url";
headers "Accept"="application/json"
"Content-Type"="application/json"
"If-Match"="*";
%if &mdebug=1 %then %do;
debug level=2;
%end;
run;
%if &mdebug=1 %then %put &sysmacroname PATCH &=url
&=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200)
,mac=MV_CREATEFILE
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
)
%end;
%put &sysmacroname: &base_uri&fileuri;
%put /SASJobExecution?_file=&path/&name;%put;
%if &mdebug=0 %then %do;
/* clear refs */
filename &fname1 clear;
filename &fref clear;
libname &libref2 clear;
%end;
%mp_abort(
iftrue=(&syscc ne 0),
msg=Cannot leave &sysmacroname with syscc=&syscc
)
%mend mv_createfile; %mend mv_createfile;

View File

@@ -46,8 +46,13 @@
%end; %end;
%else %let dbg=*; %else %let dbg=*;
%mp_abort(
iftrue=(&syscc ne 0),
msg=Cannot enter &sysmacroname with syscc=&syscc
)
%if %mfv_existfolder(&path)=1 %then %do; %if %mfv_existfolder(&path)=1 %then %do;
%put &sysmacroname: &path already exists; %&dbg.put &sysmacroname: &path already exists;
data &outds; data &outds;
self_uri="%mfv_getpathuri(&path)"; self_uri="%mfv_getpathuri(&path)";
output; output;
@@ -55,6 +60,7 @@
run; run;
%return; %return;
%end; %end;
%mp_abort(iftrue=(&syscc ne 0),msg=syscc=&syscc when folder checking)
%local oauth_bearer; %local oauth_bearer;
%if &grant_type=detect %then %do; %if &grant_type=detect %then %do;
@@ -108,6 +114,17 @@ options noquotelenmax;
headers "Authorization"="Bearer &&&access_token_var"; headers "Authorization"="Bearer &&&access_token_var";
%end; %end;
run; run;
%if &SYS_PROCHTTP_STATUS_CODE=401 %then %do;
/* relates to: https://github.com/sasjs/core/issues/400 */
%put 401 thrown in &sysmacroname;
%put sleeping: %sysfunc(sleep(12,1)) secs - will try again;
proc http method='GET' out=&fname1 &oauth_bearer
url="&base_uri/folders/folders/@item?path=&newpath";
%if &grant_type=authorization_code %then %do;
headers "Authorization"="Bearer &&&access_token_var";
%end;
run;
%end;
%local libref1; %local libref1;
%let libref1=%mf_getuniquelibref(); %let libref1=%mf_getuniquelibref();
libname &libref1 JSON fileref=&fname1; libname &libref1 JSON fileref=&fname1;
@@ -115,7 +132,7 @@ options noquotelenmax;
iftrue=( iftrue=(
&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 404 &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 404
) )
,mac=&sysmacroname ,mac=mv_createfolder124
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
) )
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
@@ -164,8 +181,9 @@ options noquotelenmax;
'Content-Type'='application/vnd.sas.content.folder+json' 'Content-Type'='application/vnd.sas.content.folder+json'
'Accept'='application/vnd.sas.content.folder+json'; 'Accept'='application/vnd.sas.content.folder+json';
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE; %if &SYS_PROCHTTP_STATUS_CODE ne 201 %then %do;
%put &=SYS_PROCHTTP_STATUS_PHRASE; %put &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%end;
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201) %mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
,mac=&sysmacroname ,mac=&sysmacroname
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
@@ -193,4 +211,8 @@ options noquotelenmax;
filename &fname1 clear; filename &fname1 clear;
libname &libref1 clear; libname &libref1 clear;
%end; %end;
%mp_abort(
iftrue=(&syscc ne 0),
msg=Cannot leave &sysmacroname with syscc=&syscc
)
%mend mv_createfolder; %mend mv_createfolder;

View File

@@ -122,7 +122,7 @@ options noquotelenmax;
%let path=%substr(&path,1,%length(&path)-1); %let path=%substr(&path,1,%length(&path)-1);
/* ensure folder exists */ /* ensure folder exists */
%put &sysmacroname: Path &path being checked / created; %&dbg.put &sysmacroname: Path &path being checked / created;
%mv_createfolder(path=&path) %mv_createfolder(path=&path)
%local base_uri; /* location of rest apis */ %local base_uri; /* location of rest apis */
@@ -955,12 +955,7 @@ run;
libname &libref1 clear; libname &libref1 clear;
%end; %end;
%put &sysmacroname: Job &name successfully created in &path; %put &sysmacroname: Job &name created! Check it out:;
%put &sysmacroname:; %put &url/SASJobExecution?_PROGRAM=&path/&name;
%put &sysmacroname: Check it out here:;
%put &sysmacroname:;%put;
%put &url/SASJobExecution?_PROGRAM=&path/&name;%put;
%put &sysmacroname:;
%put &sysmacroname:;
%mend mv_createwebservice; %mend mv_createwebservice;

View File

@@ -111,13 +111,15 @@ proc http method='GET' out=&fname1a &oauth_bearer
headers "Authorization"="Bearer &&&access_token_var"; headers "Authorization"="Bearer &&&access_token_var";
%end; %end;
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE; %if &SYS_PROCHTTP_STATUS_CODE ne 200 %then %do;
%put &=sysmacroname &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%end;
%local libref1a; %local libref1a;
%let libref1a=%mf_getuniquelibref(); %let libref1a=%mf_getuniquelibref();
libname &libref1a JSON fileref=&fname1a; libname &libref1a JSON fileref=&fname1a;
%local uri found; %local uri found;
%let found=0; %let found=0;
%put Getting object uri from &libref1a..items; /* %put Getting object uri from &libref1a..items; */
data _null_; data _null_;
length contenttype name $1000; length contenttype name $1000;
set &libref1a..items; set &libref1a..items;

View File

@@ -69,8 +69,7 @@
options noquotelenmax; options noquotelenmax;
%local base_uri; /* location of rest apis */ %local base_uri; /* location of rest apis */
%let base_uri=%mf_getplatform(VIYARESTAPI); %let base_uri=%mf_getplatform(VIYARESTAPI);
/* fetch the members of the folder to get the uri */
%put &sysmacroname: fetching details for &path ;
%local fname1; %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
@@ -90,7 +89,7 @@ run;
) )
%end; %end;
%put &sysmacroname: grab the follow on link ; /* grab the follow on link */
%local libref1; %local libref1;
%let libref1=%mf_getuniquelibref(); %let libref1=%mf_getuniquelibref();
libname &libref1 JSON fileref=&fname1; libname &libref1 JSON fileref=&fname1;
@@ -108,13 +107,15 @@ proc http method='GET' out=&fname1a &oauth_bearer
headers "Authorization"="Bearer &&&access_token_var"; headers "Authorization"="Bearer &&&access_token_var";
%end; %end;
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE; %if &SYS_PROCHTTP_STATUS_CODE ne 200 %then %do;
%put &=sysmacroname &=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%end;
%local libref1a; %local libref1a;
%let libref1a=%mf_getuniquelibref(); %let libref1a=%mf_getuniquelibref();
libname &libref1a JSON fileref=&fname1a; libname &libref1a JSON fileref=&fname1a;
%local uri found; %local uri found;
%let found=0; %let found=0;
%put Getting object uri from &libref1a..items; /* %put Getting object uri from &libref1a..items; */
data _null_; data _null_;
length contenttype name $1000; length contenttype name $1000;
set &libref1a..items; set &libref1a..items;
@@ -140,7 +141,7 @@ run;
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
) )
%end; %end;
%else %put &sysmacroname: &path/&name successfully deleted; %else %put &sysmacroname: &path/&name deleted;
/* clear refs */ /* clear refs */
filename &fname1 clear; filename &fname1 clear;

View File

@@ -1,6 +1,6 @@
/** /**
@file mv_deleteviyafolder.sas @file
@brief Creates a viya folder if that folder does not already exist @brief Deletes a viya folder
@details If not running in Studo 5 +, will expect an oauth token in a global @details If not running in Studo 5 +, will expect an oauth token in a global
macro variable (default ACCESS_TOKEN). macro variable (default ACCESS_TOKEN).

View File

@@ -126,7 +126,7 @@ data _null_;
uri=symget('uri'); uri=symget('uri');
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 too short - "!!uri,'l');
end; end;
if scan(uri,-1)='state' or scan(uri,1) ne 'jobExecution' then do; if scan(uri,-1)='state' or scan(uri,1) ne 'jobExecution' then do;
call symputx('errflg',1); call symputx('errflg',1);
@@ -191,7 +191,7 @@ data _null_;
uri=symget('loglocation'); uri=symget('loglocation');
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 too short - "!!uri,'l');
end; end;
else if (scan(uri,1,'/') ne 'compute' or scan(uri,2,'/') ne 'sessions') else if (scan(uri,1,'/') ne 'compute' or scan(uri,2,'/') ne 'sessions')
and (scan(uri,1,'/') ne 'files' or scan(uri,2,'/') ne 'files') and (scan(uri,1,'/') ne 'files' or scan(uri,2,'/') ne 'files')

View File

@@ -0,0 +1,247 @@
/**
@file mv_getviyafileextparms.sas
@brief Reads the VIYA file-extension type definition and returns selected
values in SAS macro variables
@details Content is derived from the following endpoint:
"https://${serverUrl}/types/types?limit=999999"
@param [in] ext File extension to retrieve property info for.
@param [out] propertiesVar= SAS macro variable name that will contain
the 'properties' object json, if found, else blank.
@param [out] typeDefNameVar= SAS macro variable name that will contain
the 'typeDefName' property value, if found, else blank.
@param [out] mediaTypeVar= SAS macro variable name that will contain
the 'mediaType' property value, if found, else blank.
@param [out] viyaFileExtRespLibDs (work.mv_getViyaFileExtParmsResponse)
Library.name of the dataset to receive the local working copy of the initial
response that requests all file extension details. Created once per session
to avoid multiple api calls.
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
<h4> SAS Macros </h4>
@li mf_existds.sas
@li mf_getplatform.sas
@li mf_getuniquefileref.sas
@li mf_getuniquename.sas
@li mf_getvalue.sas
@li mf_getvarlist.sas
@li mf_getvartype.sas
@li mf_nobs.sas
@li mp_abort.sas
*/
%macro mv_getViyaFileExtParms(
ext,
typeDefNameVar=,
propertiesVar=,
mediaTypeVar=,
viyaFileExtRespLibDs=work.mv_getViyaFileExtParmsResponse,
mdebug=0
);
%local base_uri; /* location of rest apis */
%local url; /* File extension info end-point */
%mp_abort(
iftrue=(%mf_isBlank(&ext))
,msg=%str(No file extension provided.)
,mac=MV_GETVIYAFILEEXTPARMS
);
%mp_abort(
iftrue=(%mf_isBlank(&typeDefNameVar) and
%mf_isBlank(&propertiesVar) and
%mf_isBlank(&mediaTypeVar))
,msg=%str(MV_GETVIYAFILEEXTPARMS - No parameter was requested.)
,mac=MV_GETVIYAFILEEXTPARMS
);
%mp_abort(
iftrue=(%mf_isBlank(&viyaFileExtRespLibDs))
,msg=%str(No <libname.>dataset name provided to cache inital response.)
,mac=MV_GETVIYAFILEEXTPARMS
);
/* Declare requested parameters as global macro vars and initialize blank */
%if not %mf_isBlank(&typeDefNameVar) %then %do;
%global &typeDefNameVar;
%let &typeDefNameVar = %str();
%end;
%if not %mf_isBlank(&propertiesVar) %then %do;
%global &propertiesVar;
%let &propertiesVar = %str();
%end;
%if not %mf_isBlank(&mediaTypeVar) %then %do;
%global &mediaTypeVar;
%let &mediaTypeVar = %str();
%end;
%let base_uri=%mf_getplatform(VIYARESTAPI);
%if &mdebug=1 %then %do;
%put DEBUG: &=base_uri;
%end;
%let ext=%lowcase(&ext);
/* Create a local copy of the Viya response containing all file type info, if
it does not already exist. */
%if not %mf_existds(&viyaFileExtRespLibDs) %then %do;
/* Create a temp file and fill with JSON that declares */
/* VIYA file-type details for the given file extension */
%local viyatypedefs;
%let viyatypedefs=%mf_getuniquefileref();
filename &viyatypedefs temp;
%let url = &base_uri/types/types?limit=999999;
proc http oauth_bearer=sas_services out=&viyatypedefs
url="&url";
run;
%if &mdebug=1 %then %put DEBUG: &sysmacroname &=url
&=SYS_PROCHTTP_STATUS_CODE &=SYS_PROCHTTP_STATUS_PHRASE;
%if (&SYS_PROCHTTP_STATUS_CODE ne 200) %then %do;
/* To avoid a breaking change, exit early if the request failed.
The calling process will proceed with empty requested macro variables. */
%put INFO: &sysmacroname File extension details were not retrieved.;
filename &viyatypedefs clear;
%return;
%end;
%if &mdebug=1 %then %do;
/* Dump the response to the log */
data _null_;
length line $120;
null=byte(0);
infile &viyatypedefs dlm=null lrecl=120 recfm=n;
input line $120.;
if _n_ = 1 then put "DEBUG:";
put line;
run;
%end;
/* Convert the content of that JSON into SAS datasets */
/* First prepare a new WORK-based folder to receive the datasets */
%local jsonworkfolder jsonlib opt_dlcreatedir;
%let jsonworkfolder=%sysfunc(pathname(work))/%mf_getuniquename(prefix=json_);
%let jsonlib=%mf_getuniquelibref(prefix=json);
/* And point a libname at it */
%let opt_dlcreatedir = %sysfunc(getoption(dlcreatedir));
options dlcreatedir; libname &jsonlib "&jsonworkfolder"; options &opt_dlcreatedir;
/* Read the json output once and copy datasets to its work folder */
%local libref1;
%let libref1=%mf_getuniquelibref();
libname &libref1 JSON fileref=&viyatypedefs automap=create;
proc copy in=&libref1 out=&jsonlib; run;
libname &libref1 clear;
/* Now give all rows belonging to the same items array a grouping value */
data &viyaFileExtRespLibDs;
length _viyaItemIdx 8;
set &jsonlib..alldata;
retain _viyaItemIdx 0;
/* Increment the row group index when a new 'items' group is observed */
if P=1 and P1='items' then _viyaItemIdx + 1;
run;
%if &mdebug=0 %then %do;
/* Tidy up, unless debug=1 */
proc datasets library=&jsonlib nolist kill; quit;
libname &jsonlib clear;
%end;
filename &viyatypedefs clear;
%end; /* If initial filetype query response didn't exist */
/* Find the row-group for the current file extension */
%local itemRowGroup;
%let itemRowGroup =
%mf_getValue(
&viyaFileExtRespLibDs
,_viyaItemIdx
,filter=%quote(p1='items' and p2='extensions' and value="&ext")
);
%if &mdebug %then %put DEBUG: &=itemRowGroup;
%if %mf_isBlank(&itemRowGroup) %then %do;
/* extension was not found */
%if(&mdebug=1) %then %put DEBUG: No type details found for extension "&ext".;
%return;
%end;
/* Filter the cached response data down to the required file extension */
%local dsItems;
%let dsItems = %mf_getuniquename(prefix=dsItems_);
data work.&dsItems;
set &viyaFileExtRespLibDs;
where _viyaItemIdx = &itemRowGroup;
run;
/* Populate typeDefName, if requested */
%if (not %mf_isBlank(&typeDefNameVar)) %then %do;
%let &typeDefNameVar = %mf_getvalue(&dsItems,value,filter=%quote(p1="items" and p2="name"));
%if &mdebug=1 %then %put DEBUG: &=typeDefNameVar &typeDefNameVar=&&&typeDefNameVar;
%end;
/* Populate mediaType, if requested */
%if (not %mf_isBlank(&mediaTypeVar)) %then %do;
%let &mediaTypeVar = %mf_getvalue(&dsItems,value,filter=%quote(p1="items" and p2="mediaType"));
%if &mdebug=1 %then %put DEBUG: &=mediaTypeVar &mediaTypeVar=&&&mediaTypeVar;
%end;
/* Populate properties macro variable, if requested */
%if not %mf_isBlank(&propertiesVar) %then %do;
/* Filter dsItems down to the properties */
%local dsProperties;
%let dsProperties = %mf_getuniquename(prefix=dsProperties_);
data work.&dsProperties ( rename=(p3 = propertyName) );
set work.&dsItems;
where p2="properties" and v=1;
run;
/* Check for 1+ properties */
%if ( %mf_nobs(&dsProperties) = 0 ) %then %do;
%let &propertiesVar = %str();
%if &mdebug=1 %then %put DEBUG: &SYSMACRONAME - No Viya properties found for file suffix %str(%')&ext%str(%');
%end;
%else %do;
/* Properties potentially span multiple rows in the input table */
data _null_;
length
line $32767
properties $32767
;
retain properties;
set &dsProperties end=last;
if _n_ = 1 then properties = '{';
line = cats(quote(trim(propertyName)),':');
/* Only strings and bools appear in properties */
if value not in ("true","false") then value = quote(trim(value));
line = catx(' ',line,value);
/* Add a comma separator to all except the last line */
if not last then line = cats(line,',');
/* Add this line to the output value */
properties = catx(' ',properties,line);
if last then do;
/* Close off the properties object and output to the macro variable */
properties=catx(' ',properties,'}');
call symputx("&propertiesVar",properties);
end;
run;
%if &mdebug=1 %then %put DEBUG: &=propertiesVar &propertiesVar=&&&propertiesVar;
%end;
%end;
%mend mv_getViyaFileExtParms;

View File

@@ -188,6 +188,8 @@
%if %mf_existvarList(&inds,FLOW_ID)=0 %then %do; %if %mf_existvarList(&inds,FLOW_ID)=0 %then %do;
retain FLOW_ID 0; retain FLOW_ID 0;
%end; %end;
/* https://github.com/sasjs/adapter/pull/845#issuecomment-2956589644 */
retain _omitSessionResults "false";
set &inds; set &inds;
&dbg. putlog (_all_)(=); &dbg. putlog (_all_)(=);
run; run;