1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-22 10:41:20 +00:00

Compare commits

..

10 Commits

45 changed files with 1011 additions and 4335 deletions

2452
Doxyfile

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
Copyright 2018 (Allan Bowe) Copyright 2020 (Allan Bowe)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

484
all.sas
View File

@@ -39,6 +39,7 @@ options noquotelenmax;
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1) %macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1)
@@ -157,7 +158,8 @@ options noquotelenmax;
%abort cancel; %abort cancel;
%end; %end;
%mend; %mend;
/**
/** @endcond *//**
@file mf_existds.sas @file mf_existds.sas
@brief Checks whether a dataset OR a view exists. @brief Checks whether a dataset OR a view exists.
@details Can be used in open code, eg as follows: @details Can be used in open code, eg as follows:
@@ -183,7 +185,7 @@ options noquotelenmax;
%else 1; %else 1;
%mend;/** %mend;/**
@file mf_existfeature.sas @file
@brief Checks whether a feature exists @brief Checks whether a feature exists
@details Check to see if a feature is supported in your environment. @details Check to see if a feature is supported in your environment.
Run without arguments to see a list of detectable features. Run without arguments to see a list of detectable features.
@@ -204,6 +206,7 @@ options noquotelenmax;
@version 8 @version 8
@author Allan Bowe @author Allan Bowe
**/ **/
/** @cond */
%macro mf_existfeature(feature %macro mf_existfeature(feature
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
@@ -223,7 +226,9 @@ options noquotelenmax;
-1 -1
%put &sysmacroname: &feature not found; %put &sysmacroname: &feature not found;
%end; %end;
%mend;/** %mend;
/** @endcond *//**
@file @file
@brief Checks if a variable exists in a data set. @brief Checks if a variable exists in a data set.
@details Returns 0 if the variable does NOT exist, and return the position of @details Returns 0 if the variable does NOT exist, and return the position of
@@ -237,6 +242,7 @@ options noquotelenmax;
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
**/ **/
/** @cond */
%macro mf_existvar(libds /* 2 part dataset name */ %macro mf_existvar(libds /* 2 part dataset name */
, var /* variable name */ , var /* variable name */
@@ -254,7 +260,9 @@ options noquotelenmax;
%let rc=%sysfunc(close(&dsid)); %let rc=%sysfunc(close(&dsid));
%end; %end;
%mend;/** %mend;
/** @endcond *//**
@file @file
@brief Checks if a set of variables ALL exist in a data set. @brief Checks if a set of variables ALL exist in a data set.
@details Returns 0 if ANY of the variables do not exist, or 1 if they ALL do. @details Returns 0 if ANY of the variables do not exist, or 1 if they ALL do.
@@ -270,6 +278,7 @@ options noquotelenmax;
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mf_existvarlist(libds, varlist %macro mf_existvarlist(libds, varlist
@@ -309,7 +318,9 @@ options noquotelenmax;
0 0
%put Vars not found: &found; %put Vars not found: &found;
%end; %end;
%mend;/** %mend;
/** @endcond *//**
@file @file
@brief Returns a character attribute of a dataset. @brief Returns a character attribute of a dataset.
@details Can be used in open code, eg as follows: @details Can be used in open code, eg as follows:
@@ -400,6 +411,7 @@ options noquotelenmax;
@author Allan Bowe @author Allan Bowe
**/ **/
/** @cond */
%macro mf_getengine(libref %macro mf_getengine(libref
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
@@ -419,7 +431,9 @@ options noquotelenmax;
&engine &engine
%mend;/** %mend;
/** @endcond *//**
@file @file
@brief Returns the size of a file in bytes. @brief Returns the size of a file in bytes.
@details Provide full path/filename.extension to the file, eg: @details Provide full path/filename.extension to the file, eg:
@@ -622,6 +636,7 @@ options noquotelenmax;
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mf_getschema(libref %macro mf_getschema(libref
@@ -643,10 +658,13 @@ options noquotelenmax;
&schema &schema
%mend; %mend;
/** @endcond */
/** /**
@file @file
@brief Assigns and returns an unused fileref @brief Assigns and returns an unused fileref
@details Use as follows: @details
Use as follows:
%let fileref1=%mf_getuniquefileref(); %let fileref1=%mf_getuniquefileref();
%let fileref2=%mf_getuniquefileref(); %let fileref2=%mf_getuniquefileref();
@@ -656,7 +674,7 @@ options noquotelenmax;
> mcref0 mcref1 > mcref0 mcref1
@prefix= first part of fileref. Remember that filerefs can only be 8 @param prefix= first part of fileref. Remember that filerefs can only be 8
characters, so a 7 letter prefix would mean that `maxtries` should be 10. characters, so a 7 letter prefix would mean that `maxtries` should be 10.
@param maxtries= the last part of the libref. Provide an integer value. @param maxtries= the last part of the libref. Provide an integer value.
@@ -694,7 +712,7 @@ options noquotelenmax;
> mclib3 > mclib3
@prefix= first part of libref. Remember that librefs can only be 8 characters, @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. so a 7 letter prefix would mean that maxtries should be 10.
@param maxtries= the last part of the libref. Provide an integer value. @param maxtries= the last part of the libref. Provide an integer value.
@@ -1530,6 +1548,7 @@ Usage:
@version 9.4M3 @version 9.4M3
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mp_abort(mac=mp_abort.sas, type=, msg=, iftrue=%str(1=1) %macro mp_abort(mac=mp_abort.sas, type=, msg=, iftrue=%str(1=1)
@@ -1663,7 +1682,7 @@ Usage:
%end; %end;
%mend; %mend;
/** /** @endcond *//**
@file @file
@brief Copy any file using binary input / output streams @brief Copy any file using binary input / output streams
@details Reads in a file byte by byte and writes it back out. Is an @details Reads in a file byte by byte and writes it back out. Is an
@@ -1727,6 +1746,7 @@ Usage:
applying CRLF line endings and converting embedded cr and crlf to lf. applying CRLF line endings and converting embedded cr and crlf to lf.
usage: usage:
fileref mycsv "/path/your/csv"; fileref mycsv "/path/your/csv";
%mp_cleancsv(in=mycsv,out=/path/new.csv) %mp_cleancsv(in=mycsv,out=/path/new.csv)
@@ -1736,6 +1756,7 @@ Usage:
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mp_cleancsv(in=NOTPROVIDED,out=NOTPROVIDED,qchar='22'x); %macro mp_cleancsv(in=NOTPROVIDED,out=NOTPROVIDED,qchar='22'x);
@@ -1784,7 +1805,8 @@ Usage:
else put inchar $char1.; else put inchar $char1.;
end; end;
run; run;
%mend;/** %mend;
/** @endcond *//**
@file mp_createconstraints.sas @file mp_createconstraints.sas
@brief Creates constraints @brief Creates constraints
@details Takes the output from mp_getconstraints.sas as input @details Takes the output from mp_getconstraints.sas as input
@@ -2623,6 +2645,63 @@ 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;/**
@file
@brief Export a dataset to a CSV file
@details Export to a file or a fileref
Usage:
%mp_ds2csv(sashelp.class,outref="%sysfunc(pathname(work))/file.csv")
@param ds The dataset to be exported
@param outfile= The output filename - should be quoted.
@param outref= The output fileref (takes precedence if provided)
@param outencoding= The output encoding to use (unquoted)
@version 9.2
@author Allan Bowe (credit mjsq)
**/
%macro mp_ds2csv(ds, outref=0, outfile=, outencoding=0
)/*/STORE SOURCE*/;
%if not %sysfunc(exist(&ds)) %then %do;
%put WARNING: &ds does not exist;
%return;
%end;
%if %index(&ds,.)=0 %then %let ds=WORK.&ds;
%if &outencoding=0 %then %let outencoding=;
%else %let outencoding=encoding="&outencoding";
%local outloc;
%if &outref=0 %then %let outloc=&outfile;
%else %let outloc=&outref;
/* credit to mjsq - https://stackoverflow.com/a/55642267 */
/* first get headers */
data _null_;
file &outloc dlm=',' dsd &outencoding lrecl=32767;
length header $ 2000;
dsid=open("&ds.","i");
num=attrn(dsid,"nvars");
do i=1 to num;
header = trim(left(coalescec(varlabel(dsid,i),varname(dsid,i))));
put header @;
end;
rc=close(dsid);
run;
/* next, export data */
data _null_;
set &ds.;
file &outloc mod dlm=',' dsd &outencoding lrecl=32767;
put (_all_) (+0);
run;
%mend;/** %mend;/**
@file mp_getconstraints.sas @file mp_getconstraints.sas
@brief Get constraint details at column level @brief Get constraint details at column level
@@ -2700,6 +2779,8 @@ create table &outds as
You may need to adjust the rendered DBML to suit your needs. You may need to adjust the rendered DBML to suit your needs.
![dbml for sas](https://i.imgur.com/8T1tIZp.gif)
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getquotedstr.sas @li mf_getquotedstr.sas
@@ -3985,6 +4066,93 @@ select distinct lowcase(memname)
,dttm=%sysfunc(datetime()); ,dttm=%sysfunc(datetime());
quit; quit;
%mend;/**
@file
@brief Enables previous observations to be re-instated
@details Remembers the last X observations by storing them in a hash table.
Is a convenience over the use of lag() or retain, when an entire observation
needs to be restored.
This macro will also restore automatic variables (such as _n_ and _error_).
Example Usage:
data example;
set sashelp.class;
calc_var=_n_*3;
* initialise hash and save from PDV ;
%mp_prevobs(INIT,history=2)
if _n_ =10 then do;
* fetch previous but 1 record;
%mp_prevobs(FETCH,-2)
put _n_= name= age= calc_var=;
* fetch previous record;
%mp_prevobs(FETCH,-1)
put _n_= name= age= calc_var=;
* reinstate current record ;
%mp_prevobs(FETCH,0)
put _n_= name= age= calc_var=;
end;
run;
Result:
<img src="https://imgur.com/PSjHoET.png" alt="mp_prevobs sas" width="400"/>
Credit is made to `data _null_` for authoring this very helpful paper:
https://www.lexjansen.com/pharmasug/2008/cc/CC08.pdf
@param action Either FETCH a current or previous record, or INITialise.
@param record The relative (to current) position of the previous observation
to return.
@param history= The number of records to retain in the hash table. Default=5
@param prefix= the prefix to give to the variables used to store the hash name
and index. Default=mp_prevobs
@version 9.2
@author Allan Bowe
**/
%macro mp_prevobs(action,record,history=5,prefix=mp_prevobs
)/*/STORE SOURCE*/;
%let action=%upcase(&action);
%let prefix=%upcase(&prefix);
%let record=%eval((&record+0) * -1);
%if &action=INIT %then %do;
if _n_ eq 1 then do;
attrib &prefix._VAR length=$64;
dcl hash &prefix._HASH(ordered:'Y');
&prefix._KEY=0;
&prefix._HASH.defineKey("&prefix._KEY");
do while(1);
call vnext(&prefix._VAR);
if &prefix._VAR='' then leave;
if &prefix._VAR eq "&prefix._VAR" then continue;
else if &prefix._VAR eq "&prefix._KEY" then continue;
&prefix._HASH.defineData(&prefix._VAR);
end;
&prefix._HASH.defineDone();
end;
/* this part has to happen before FETCHing */
&prefix._KEY+1;
&prefix._rc=&prefix._HASH.add();
if &prefix._rc then putlog 'adding' &prefix._rc=;
%if &history>0 %then %do;
if &prefix._key>&history+1 then
&prefix._HASH.remove(key: &prefix._KEY - &history - 1);
if &prefix._rc then putlog 'removing' &prefix._rc=;
%end;
%end;
%else %if &action=FETCH %then %do;
if &record > &prefix._key then putlog "Not enough records in &Prefix._hash yet";
else &prefix._rc=&prefix._HASH.find(key: &prefix._KEY - &record);
if &prefix._rc then putlog &prefix._rc= " when fetching " &prefix._KEY=
"with record &record and " _n_=;
%end;
%mend;/** %mend;/**
@file @file
@brief Returns all children from a hierarchy table for a specified parent @brief Returns all children from a hierarchy table for a specified parent
@@ -4586,6 +4754,64 @@ proc sql
%mp_binarycopy(inloc="&inloc",outref=_webout) %mp_binarycopy(inloc="&inloc",outref=_webout)
%end; %end;
%mend;/**
@file mp_testwritespeedlibrary.sas
@brief Tests the write speed of a new table in a SAS library
@details Will create a new table of a certain size in an
existing SAS library. The table will have one column,
and will be subsequently deleted.
%mp_testwritespeedlibrary(
lib=work
,size=0.5
,outds=work.results
)
@param lib= (WORK) The library in which to create the table
@param size= (0.1) The size in GB of the table to create
@param outds= (WORK.RESULTS) The output dataset to be created.
<h4> Dependencies </h4>
@li mf_getuniquename.sas
@li mf_existds.sas
@version 9.4
@author Allan Bowe
**/
%macro mp_testwritespeedlibrary(lib=WORK
,outds=work.results
,size=0.1
)/*/STORE SOURCE*/;
%local ds start;
/* find an unused, unique name for the new table */
%let ds=%mf_getuniquename();
%do %until(%mf_existds(&lib..&ds)=0);
%let ds=%mf_getuniquename();
%end;
%let start=%sysfunc(datetime());
data &lib..&ds(compress=no keep=x);
header=128*1024;
size=(1073741824/8 * &size) - header;
do x=1 to size;
output;
end;
run;
proc sql;
drop table &lib..&ds;
data &outds;
lib="&lib";
start_dttm=put(&start,datetime19.);
end_dttm=put(datetime(),datetime19.);
duration_seconds=end_dttm-start_dttm;
run;
%mend;/** %mend;/**
@file @file
@brief Recursively scans a directory tree to get all subfolders and content @brief Recursively scans a directory tree to get all subfolders and content
@@ -8670,8 +8896,8 @@ filename __outdoc clear;
combine with the <code>tree=</code> parameter. combine with the <code>tree=</code> parameter.
@param outds= the dataset to create that contains the list of stps. @param outds= the dataset to create that contains the list of stps.
@param mDebug= set to 1 to show debug messages in the log @param mDebug= set to 1 to show debug messages in the log
@showDesc= provide a non blank value to return stored process descriptions @param showDesc= provide a non blank value to return stored process descriptions
@showUsageVersion= provide a non blank value to return the UsageVersion. This @param showUsageVersion= provide a non blank value to return the UsageVersion. This
is either 1000000 (type 1, 9.2) or 2000000 (type2, 9.3 onwards). is either 1000000 (type 1, 9.2) or 2000000 (type2, 9.3 onwards).
@returns outds dataset containing the following columns @returns outds dataset containing the following columns
@@ -9171,8 +9397,7 @@ libname _XML_ clear;
libname __shake clear; libname __shake clear;
@version 9.4 @version 9.4
@author Allan Bowe @author Allan Bowe https://github.com/sasjs/core
@source https://github.com/sasjs/core
**/ **/
@@ -10322,8 +10547,7 @@ run;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -10460,7 +10684,8 @@ options noquotelenmax;
%mend;/** %mend;/**
@file mv_createwebservice.sas @file mv_createwebservice.sas
@brief Creates a JobExecution web service if it doesn't already exist @brief Creates a JobExecution web service if it doesn't already exist
@details Code is passed in as one or more filerefs. @details
Code is passed in as one or more filerefs.
%* Step 1 - compile macros ; %* Step 1 - compile macros ;
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
@@ -10513,8 +10738,7 @@ options noquotelenmax;
a shared context - see https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en a shared context - see https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
**/ **/
@@ -11136,8 +11360,7 @@ run;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -11286,8 +11509,7 @@ libname &libref1a clear;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -11431,8 +11653,7 @@ libname &libref1a clear;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -11560,8 +11781,7 @@ libname &libref1 clear;
@brief deprecated - replaced by mv_tokenrefresh.sas @brief deprecated - replaced by mv_tokenrefresh.sas
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mv_tokenrefresh.sas @li mv_tokenrefresh.sas
@@ -11592,8 +11812,7 @@ libname &libref1 clear;
@brief deprecated - replaced by mv_registerclient.sas @brief deprecated - replaced by mv_registerclient.sas
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mv_registerclient.sas @li mv_registerclient.sas
@@ -11641,8 +11860,7 @@ libname &libref1 clear;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -11728,8 +11946,7 @@ libname &libref1 clear;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -11798,10 +12015,16 @@ options noquotelenmax;
/*data _null_;infile &fname1;input;putlog _infile_;run;*/ /*data _null_;infile &fname1;input;putlog _infile_;run;*/
libname &libref1 JSON fileref=&fname1; libname &libref1 JSON fileref=&fname1;
/* now get the followon link to list members */ /* now get the followon link to list members */
%local href;
%let href=0;
data _null_; data _null_;
set &libref1..links; set &libref1..links;
if rel='members' then call symputx('href',quote("&base_uri"!!trim(href)),'l'); if rel='members' then call symputx('href',quote("&base_uri"!!trim(href)),'l');
run; run;
%if &href=0 %then %do;
%put NOTE:;%put NOTE- No members found in &root!!;%put NOTE-;
%return;
%end;
%local fname2 libref2; %local fname2 libref2;
%let fname2=%mf_getuniquefileref(); %let fname2=%mf_getuniquefileref();
%let libref2=%mf_getuniquelibref(); %let libref2=%mf_getuniquelibref();
@@ -11856,8 +12079,7 @@ libname &libref1 clear;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -11961,8 +12183,7 @@ filename &fname1 clear;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -12032,8 +12253,7 @@ libname &libref1 clear;
@brief deprecated - replaced by mv_tokenauth.sas @brief deprecated - replaced by mv_tokenauth.sas
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mv_tokenauth.sas @li mv_tokenauth.sas
@@ -12082,8 +12302,7 @@ libname &libref1 clear;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -12201,8 +12420,7 @@ libname &libref1 clear;
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -12268,6 +12486,173 @@ run;
filename &fname1 clear; filename &fname1 clear;
libname &libref1 clear; libname &libref1 clear;
%mend;/**
@file
@brief Executes a SAS Viya Job
@details Triggers a SAS Viya Job, with optional URL parameters, using
the JES web app.
First, compile the macros:
filename mc url
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
Then, execute the job!
%mv_jobexecute(path=/Public/folder
,name=somejob
)
Example with parameters:
%mv_jobexecute(path=/Public/folder
,name=somejob
,paramstring=%str("macvarname":"macvarvalue","answer":42)
)
@param access_token_var= The global macro variable to contain the access token
@param grant_type= valid values:
* password
* authorization_code
* detect - will check if access_token exists, if not will use sas_services if
a SASStudioV session else authorization_code. Default option.
* sas_services - will use oauth_bearer=sas_services
@param path= The SAS Drive path to the job being executed
@param name= The name of the job to execute
@param paramstring= A JSON fragment with name:value pairs, eg: `"name":"value"`
or "name":"value","name2":42`. This will need to be wrapped in `%str()`.
@param contextName= Context name with which to run the job.
Default = `SAS Job Execution compute context`
@param outds= The output dataset containing links (Default=work.mv_jobexecute)
@version VIYA V.03.04
@author Allan Bowe, source: https://github.com/sasjs/core
<h4> Dependencies </h4>
@li mp_abort.sas
@li mf_getplatform.sas
@li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@li mv_getfoldermembers.sas
**/
%macro mv_jobexecute(path=0
,name=0
,contextName=SAS Job Execution compute context
,access_token_var=ACCESS_TOKEN
,grant_type=sas_services
,paramstring=0
,outds=work.mv_jobexecute
);
%local oauth_bearer;
%if &grant_type=detect %then %do;
%if %symexist(&access_token_var) %then %let grant_type=authorization_code;
%else %let grant_type=sas_services;
%end;
%if &grant_type=sas_services %then %do;
%let oauth_bearer=oauth_bearer=sas_services;
%let &access_token_var=;
%end;
%put &sysmacroname: grant_type=&grant_type;
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
and &grant_type ne sas_services
)
,mac=&sysmacroname
,msg=%str(Invalid value for grant_type: &grant_type)
)
%mp_abort(iftrue=("&path"="0")
,mac=&sysmacroname
,msg=%str(Path not provided)
)
%mp_abort(iftrue=("&name"="0")
,mac=&sysmacroname
,msg=%str(Job Name not provided)
)
options noquotelenmax;
%local base_uri; /* location of rest apis */
%let base_uri=%mf_getplatform(VIYARESTAPI);
data;run;
%local foldermembers;
%let foldermembers=&syslast;
%mv_getfoldermembers(root=&path
,access_token_var=&access_token_var
,grant_type=&grant_type
,outds=&foldermembers
)
%local joburi;
%let joburi=0;
data _null_;
set &foldermembers;
if name="&name" and uri=:'/jobDefinitions/definitions'
then call symputx('joburi',uri);
run;
%mp_abort(iftrue=("&joburi"="0")
,mac=&sysmacroname
,msg=%str(Job &path/&name not found)
)
/* prepare request*/
%local fname0 fname1;
%let fname0=%mf_getuniquefileref();
%let fname1=%mf_getuniquefileref();
data _null_;
file &fname0;
length joburi contextname $128 paramstring $32765;
joburi=quote(trim(symget('joburi')));
contextname=quote(trim(symget('contextname')));
paramstring=symget('paramstring');
put '{"jobDefinitionUri":' joburi ;
put ' ,"arguments":{"_contextName":' contextname;
if paramstring ne "0" then do;
put ' ,' paramstring;
end;
put '}}';
run;
proc http method='POST' in=&fname0 out=&fname1 &oauth_bearer
url="&base_uri/jobExecution/jobs";
headers "Content-Type"="application/vnd.sas.job.execution.job.request+json"
"Accept"="application/vnd.sas.job.execution.job+json"
%if &grant_type=authorization_code %then %do;
"Authorization"="Bearer &&&access_token_var"
%end;
;
run;
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201 %then
%do;
data _null_;infile &fname0;input;putlog _infile_;run;
data _null_;infile &fname1;input;putlog _infile_;run;
%mp_abort(mac=&sysmacroname
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
)
%end;
%local libref;
%let libref=%mf_getuniquelibref();
libname &libref JSON fileref=&fname1;
data &outds;
set &libref..links;
run;
/* clear refs */
filename &fname0 clear;
filename &fname1 clear;
libname &libref;
%mend;/** %mend;/**
@file mv_registerclient.sas @file mv_registerclient.sas
@brief Register Client and Secret (admin task) @brief Register Client and Secret (admin task)
@@ -12322,8 +12707,7 @@ libname &libref1 clear;
for debugging. Default= _null_. for debugging. Default= _null_.
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -12546,8 +12930,7 @@ libname &libref clear;
@param base_uri= The Viya API server location @param base_uri= The Viya API server location
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -12689,8 +13072,7 @@ filename &fref2 clear;
@param refresh_token_var= The global macro variable containing the refresh token @param refresh_token_var= The global macro variable containing the refresh token
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -12812,7 +13194,7 @@ filename &fref1 clear;
@li mf_getuser.sas @li mf_getuser.sas
@version Viya 3.3 @version Viya 3.3
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
**/ **/
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y); %macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y);

View File

@@ -21,6 +21,7 @@
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1) %macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1)
@@ -139,3 +140,5 @@
%abort cancel; %abort cancel;
%end; %end;
%mend; %mend;
/** @endcond */

View File

@@ -1,5 +1,5 @@
/** /**
@file mf_existfeature.sas @file
@brief Checks whether a feature exists @brief Checks whether a feature exists
@details Check to see if a feature is supported in your environment. @details Check to see if a feature is supported in your environment.
Run without arguments to see a list of detectable features. Run without arguments to see a list of detectable features.
@@ -20,6 +20,7 @@
@version 8 @version 8
@author Allan Bowe @author Allan Bowe
**/ **/
/** @cond */
%macro mf_existfeature(feature %macro mf_existfeature(feature
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
@@ -40,3 +41,5 @@
%put &sysmacroname: &feature not found; %put &sysmacroname: &feature not found;
%end; %end;
%mend; %mend;
/** @endcond */

View File

@@ -12,6 +12,7 @@
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
**/ **/
/** @cond */
%macro mf_existvar(libds /* 2 part dataset name */ %macro mf_existvar(libds /* 2 part dataset name */
, var /* variable name */ , var /* variable name */
@@ -30,3 +31,5 @@
%end; %end;
%mend; %mend;
/** @endcond */

View File

@@ -14,6 +14,7 @@
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mf_existvarlist(libds, varlist %macro mf_existvarlist(libds, varlist
@@ -54,3 +55,5 @@
%put Vars not found: &found; %put Vars not found: &found;
%end; %end;
%mend; %mend;
/** @endcond */

View File

@@ -23,6 +23,7 @@
@author Allan Bowe @author Allan Bowe
**/ **/
/** @cond */
%macro mf_getengine(libref %macro mf_getengine(libref
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
@@ -43,3 +44,5 @@
&engine &engine
%mend; %mend;
/** @endcond */

View File

@@ -17,6 +17,7 @@
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mf_getschema(libref %macro mf_getschema(libref
@@ -38,3 +39,5 @@
&schema &schema
%mend; %mend;
/** @endcond */

View File

@@ -1,7 +1,8 @@
/** /**
@file @file
@brief Assigns and returns an unused fileref @brief Assigns and returns an unused fileref
@details Use as follows: @details
Use as follows:
%let fileref1=%mf_getuniquefileref(); %let fileref1=%mf_getuniquefileref();
%let fileref2=%mf_getuniquefileref(); %let fileref2=%mf_getuniquefileref();
@@ -11,7 +12,7 @@
> mcref0 mcref1 > mcref0 mcref1
@prefix= first part of fileref. Remember that filerefs can only be 8 @param prefix= first part of fileref. Remember that filerefs can only be 8
characters, so a 7 letter prefix would mean that `maxtries` should be 10. characters, so a 7 letter prefix would mean that `maxtries` should be 10.
@param maxtries= the last part of the libref. Provide an integer value. @param maxtries= the last part of the libref. Provide an integer value.

View File

@@ -14,7 +14,7 @@
> mclib3 > mclib3
@prefix= first part of libref. Remember that librefs can only be 8 characters, @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. so a 7 letter prefix would mean that maxtries should be 10.
@param maxtries= the last part of the libref. Provide an integer value. @param maxtries= the last part of the libref. Provide an integer value.

View File

@@ -18,6 +18,7 @@
@version 9.4M3 @version 9.4M3
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mp_abort(mac=mp_abort.sas, type=, msg=, iftrue=%str(1=1) %macro mp_abort(mac=mp_abort.sas, type=, msg=, iftrue=%str(1=1)
@@ -151,3 +152,4 @@
%end; %end;
%mend; %mend;
/** @endcond */

View File

@@ -8,6 +8,7 @@
applying CRLF line endings and converting embedded cr and crlf to lf. applying CRLF line endings and converting embedded cr and crlf to lf.
usage: usage:
fileref mycsv "/path/your/csv"; fileref mycsv "/path/your/csv";
%mp_cleancsv(in=mycsv,out=/path/new.csv) %mp_cleancsv(in=mycsv,out=/path/new.csv)
@@ -17,6 +18,7 @@
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mp_cleancsv(in=NOTPROVIDED,out=NOTPROVIDED,qchar='22'x); %macro mp_cleancsv(in=NOTPROVIDED,out=NOTPROVIDED,qchar='22'x);
@@ -66,3 +68,4 @@
end; end;
run; run;
%mend; %mend;
/** @endcond */

58
base/mp_ds2csv.sas Normal file
View File

@@ -0,0 +1,58 @@
/**
@file
@brief Export a dataset to a CSV file
@details Export to a file or a fileref
Usage:
%mp_ds2csv(sashelp.class,outref="%sysfunc(pathname(work))/file.csv")
@param ds The dataset to be exported
@param outfile= The output filename - should be quoted.
@param outref= The output fileref (takes precedence if provided)
@param outencoding= The output encoding to use (unquoted)
@version 9.2
@author Allan Bowe (credit mjsq)
**/
%macro mp_ds2csv(ds, outref=0, outfile=, outencoding=0
)/*/STORE SOURCE*/;
%if not %sysfunc(exist(&ds)) %then %do;
%put WARNING: &ds does not exist;
%return;
%end;
%if %index(&ds,.)=0 %then %let ds=WORK.&ds;
%if &outencoding=0 %then %let outencoding=;
%else %let outencoding=encoding="&outencoding";
%local outloc;
%if &outref=0 %then %let outloc=&outfile;
%else %let outloc=&outref;
/* credit to mjsq - https://stackoverflow.com/a/55642267 */
/* first get headers */
data _null_;
file &outloc dlm=',' dsd &outencoding lrecl=32767;
length header $ 2000;
dsid=open("&ds.","i");
num=attrn(dsid,"nvars");
do i=1 to num;
header = trim(left(coalescec(varlabel(dsid,i),varname(dsid,i))));
put header @;
end;
rc=close(dsid);
run;
/* next, export data */
data _null_;
set &ds.;
file &outloc mod dlm=',' dsd &outencoding lrecl=32767;
put (_all_) (+0);
run;
%mend;

View File

@@ -16,6 +16,8 @@
You may need to adjust the rendered DBML to suit your needs. You may need to adjust the rendered DBML to suit your needs.
![dbml for sas](https://i.imgur.com/8T1tIZp.gif)
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getquotedstr.sas @li mf_getquotedstr.sas

88
base/mp_prevobs.sas Normal file
View File

@@ -0,0 +1,88 @@
/**
@file
@brief Enables previous observations to be re-instated
@details Remembers the last X observations by storing them in a hash table.
Is a convenience over the use of lag() or retain, when an entire observation
needs to be restored.
This macro will also restore automatic variables (such as _n_ and _error_).
Example Usage:
data example;
set sashelp.class;
calc_var=_n_*3;
* initialise hash and save from PDV ;
%mp_prevobs(INIT,history=2)
if _n_ =10 then do;
* fetch previous but 1 record;
%mp_prevobs(FETCH,-2)
put _n_= name= age= calc_var=;
* fetch previous record;
%mp_prevobs(FETCH,-1)
put _n_= name= age= calc_var=;
* reinstate current record ;
%mp_prevobs(FETCH,0)
put _n_= name= age= calc_var=;
end;
run;
Result:
<img src="https://imgur.com/PSjHoET.png" alt="mp_prevobs sas" width="400"/>
Credit is made to `data _null_` for authoring this very helpful paper:
https://www.lexjansen.com/pharmasug/2008/cc/CC08.pdf
@param action Either FETCH a current or previous record, or INITialise.
@param record The relative (to current) position of the previous observation
to return.
@param history= The number of records to retain in the hash table. Default=5
@param prefix= the prefix to give to the variables used to store the hash name
and index. Default=mp_prevobs
@version 9.2
@author Allan Bowe
**/
%macro mp_prevobs(action,record,history=5,prefix=mp_prevobs
)/*/STORE SOURCE*/;
%let action=%upcase(&action);
%let prefix=%upcase(&prefix);
%let record=%eval((&record+0) * -1);
%if &action=INIT %then %do;
if _n_ eq 1 then do;
attrib &prefix._VAR length=$64;
dcl hash &prefix._HASH(ordered:'Y');
&prefix._KEY=0;
&prefix._HASH.defineKey("&prefix._KEY");
do while(1);
call vnext(&prefix._VAR);
if &prefix._VAR='' then leave;
if &prefix._VAR eq "&prefix._VAR" then continue;
else if &prefix._VAR eq "&prefix._KEY" then continue;
&prefix._HASH.defineData(&prefix._VAR);
end;
&prefix._HASH.defineDone();
end;
/* this part has to happen before FETCHing */
&prefix._KEY+1;
&prefix._rc=&prefix._HASH.add();
if &prefix._rc then putlog 'adding' &prefix._rc=;
%if &history>0 %then %do;
if &prefix._key>&history+1 then
&prefix._HASH.remove(key: &prefix._KEY - &history - 1);
if &prefix._rc then putlog 'removing' &prefix._rc=;
%end;
%end;
%else %if &action=FETCH %then %do;
if &record > &prefix._key then putlog "Not enough records in &Prefix._hash yet";
else &prefix._rc=&prefix._HASH.find(key: &prefix._KEY - &record);
if &prefix._rc then putlog &prefix._rc= " when fetching " &prefix._KEY=
"with record &record and " _n_=;
%end;
%mend;

View File

@@ -24,6 +24,7 @@ LAYOUT_FILE = ./doxy/DoxygenLayout.xml
MAX_INITIALIZER_LINES = 0 MAX_INITIALIZER_LINES = 0
PROJECT_NAME = Macro Core PROJECT_NAME = Macro Core
PROJECT_LOGO = doxy/Macro_core_website_1.png PROJECT_LOGO = doxy/Macro_core_website_1.png
PROJECT_BRIEF = "Production Ready Macros for SAS Application Developers"
RECURSIVE = YES RECURSIVE = YES
REPEAT_BRIEF = NO REPEAT_BRIEF = NO
SHOW_NAMESPACES = NO SHOW_NAMESPACES = NO

View File

@@ -101,11 +101,11 @@
<!-- Layout definition for a directory page --> <!-- Layout definition for a directory page -->
<directory> <directory>
<briefdescription visible="yes"/> <briefdescription visible="yes"/>
<detaileddescription visible="yes" title=""/>
<directorygraph visible="yes"/> <directorygraph visible="yes"/>
<memberdecl> <memberdecl>
<dirs visible="yes"/> <dirs visible="yes"/>
<files visible="yes"/> <files visible="yes"/>
</memberdecl> </memberdecl>
<detaileddescription title=""/>
</directory> </directory>
</doxygenlayout> </doxygenlayout>

View File

@@ -33,11 +33,11 @@ cd core.github.io
rm -r * rm -r *
mv $BUILD_FOLDER/out/doxy/* . mv $BUILD_FOLDER/out/doxy/* .
echo 'core.sasjs.io' > CNAME echo 'core.sasjs.io' > CNAME
git add * git add .
git commit -m "build.sh build on $(date +%F:%H:%M:%S)" git commit -m "build.sh build on $(date +%F:%H:%M:%S)"
git push git push
npx sitemap-generator-cli https://core.sasjs.io npx sitemap-generator-cli https://core.sasjs.io
git add * git add .
git commit -m "adding sitemap" git commit -m "adding sitemap"
git push git push

View File

@@ -1,22 +1,23 @@
<!-- HTML footer for doxygen 1.8.17-->
<!-- start footer part -->
<!--BEGIN GENERATE_TREEVIEW--> <!--BEGIN GENERATE_TREEVIEW-->
<li class="footer"><b>$generatedby</b> <div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<a href="http://www.doxygen.org/index.html"> <ul>
<img class="footer" src="doxygen.png" alt="doxygen"/></a> $navpath
<li class="footer">$generatedby
<a href="https://www.doxygen.org/index.html">
<img class="footer" src="$relpath^doxygen.png" alt="doxygen"/></a> $doxygenversion </li>
<i> For more information visit the </i> <a href="https://github.com/sasjs/core">Macro Core library</a>.</li> <i> For more information visit the </i> <a href="https://github.com/sasjs/core">Macro Core library</a>.</li>
</ul> </ul>
</div> </div>
<!--END GENERATE_TREEVIEW--> <!--END GENERATE_TREEVIEW-->
<!--BEGIN !GENERATE_TREEVIEW--> <!--BEGIN !GENERATE_TREEVIEW-->
<hr class="footer"/> <hr class="footer"/><address class="footer"><small>
<table width="100%"><tbody><tr><td> $generatedby &#160;<a href="http://www.doxygen.org/index.html">
For more information visit the <a href="https://github.com/sasjs/core">Macro Core library</a>. <img class="footer" src="$relpath^doxygen.png" alt="doxygen"/>
</td><td><address class="footer"><small>
&copy;$year<br/>
$generatedby <a href="http://www.doxygen.org/index.html">
<!--<img class="footer" src="$relpath$doxygen.png" alt="doxygen"/>-->doxygen
</a> $doxygenversion </a> $doxygenversion
</small></address></tr></tbody></table> </small></address>
<!--END !GENERATE_TREEVIEW--> <!--END !GENERATE_TREEVIEW-->
</body> </body>
</html> </html>

View File

@@ -1,6 +1,6 @@
<!-- HTML header for doxygen 1.8.14--> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- HTML header for doxygen 1.8.17-->
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="https://www.w3.org/1999/xhtml" lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/> <meta http-equiv="X-UA-Compatible" content="IE=9"/>
@@ -16,33 +16,40 @@ $search
$mathjax $mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" /> <link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
<link REL="icon" HREF="https://sasjs.io/img/runningman.jpg"> <link REL="icon" HREF="https://sasjs.io/img/runningman.jpg">
$extrastylesheet $extrastylesheet
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA--> <!--BEGIN TITLEAREA-->
<div id="titlearea" style='background-color:white' > <div id="titlearea">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 26px;"> <tr style="height: 56px;">
<!--BEGIN PROJECT_LOGO--> <!--BEGIN PROJECT_LOGO-->
<td id="projectlogo"></td> <td id="projectlogo">
<img alt="Logo" src="$relpath^$projectlogo"/></td>
<!--END PROJECT_LOGO--> <!--END PROJECT_LOGO-->
<!--BEGIN PROJECT_NAME--> <!--BEGIN PROJECT_NAME-->
<td> <td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname"> <div id="projectname">
<!--a href="."> <!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
<img alt="Macro Core" src="https://macropeople.com/wp-content/uploads/2018/05/macropeople2014retina_V2.png" height=60/>
</a-->
<a href=".">
<img alt="Macro Core" src="./Macro_core_website_1.png" height=60/>
</a>
</div> </div>
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">
Production Ready Macros for SAS Application Developers</br>
<a href="https://github.com/sasjs/core">
https://github.com/sasjs/core
</a>
</div>
<meta name="Description" content="$projectbrief">
<!--END PROJECT_BRIEF-->
</td> </td>
<td> <!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<!--BEGIN PROJECT_BRIEF-->
<td style="padding-left: 0.5em;">
<div id="projectbrief">$projectbrief</div>
<table style="padding-left: 2em;" cellspacing="0" cellpadding="0"> <table style="padding-left: 2em;" cellspacing="0" cellpadding="0">
<tr><td> Production Ready Macros for SAS Application Developers</td></tr> <tr><td> Production Ready Macros for SAS Application Developers</td></tr>
<tr><td><a href="https://github.com/sasjs/core"> <tr><td><a href="https://github.com/sasjs/core">
@@ -50,17 +57,10 @@ $extrastylesheet
</a></td></tr> </a></td></tr>
</table> </table>
</td> </td>
<!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<!--BEGIN PROJECT_BRIEF-->
<!--END PROJECT_BRIEF--> <!--END PROJECT_BRIEF-->
<!--END !PROJECT_NAME--> <!--END !PROJECT_NAME-->
<div class="header">
<div class="headertitle">
<!--BEGIN DISABLE_INDEX--> <!--BEGIN DISABLE_INDEX-->
<!--BEGIN SEARCHENGINE--> <!--BEGIN SEARCHENGINE-->
<td>$searchbox</td> <td>$searchbox</td>
<!--END SEARCHENGINE--> <!--END SEARCHENGINE-->
<!--END DISABLE_INDEX--> <!--END DISABLE_INDEX-->

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,11 @@
* Not metadata aware * Not metadata aware
* No X command * No X command
* Prefixes: _mf_, _mp_ * Prefixes: _mf_, _mp_
Macros starting `mf_` are macro _functions_ and can be used in assignment
statements. Those starting `mp_` are macro _procedures_, which generate
SAS statements, and must therefore be applied accordingly.
*/ */
/*! \dir meta /*! \dir meta

View File

@@ -23,8 +23,8 @@
combine with the <code>tree=</code> parameter. combine with the <code>tree=</code> parameter.
@param outds= the dataset to create that contains the list of stps. @param outds= the dataset to create that contains the list of stps.
@param mDebug= set to 1 to show debug messages in the log @param mDebug= set to 1 to show debug messages in the log
@showDesc= provide a non blank value to return stored process descriptions @param showDesc= provide a non blank value to return stored process descriptions
@showUsageVersion= provide a non blank value to return the UsageVersion. This @param showUsageVersion= provide a non blank value to return the UsageVersion. This
is either 1000000 (type 1, 9.2) or 2000000 (type2, 9.3 onwards). is either 1000000 (type 1, 9.2) or 2000000 (type2, 9.3 onwards).
@returns outds dataset containing the following columns @returns outds dataset containing the following columns

View File

@@ -21,8 +21,7 @@
libname __shake clear; libname __shake clear;
@version 9.4 @version 9.4
@author Allan Bowe @author Allan Bowe https://github.com/sasjs/core
@source https://github.com/sasjs/core
**/ **/

View File

@@ -15,8 +15,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -1,7 +1,8 @@
/** /**
@file mv_createwebservice.sas @file mv_createwebservice.sas
@brief Creates a JobExecution web service if it doesn't already exist @brief Creates a JobExecution web service if it doesn't already exist
@details Code is passed in as one or more filerefs. @details
Code is passed in as one or more filerefs.
%* Step 1 - compile macros ; %* Step 1 - compile macros ;
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
@@ -54,8 +55,7 @@
a shared context - see https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en a shared context - see https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
**/ **/

View File

@@ -20,8 +20,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -19,8 +19,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -16,8 +16,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -3,8 +3,7 @@
@brief deprecated - replaced by mv_tokenrefresh.sas @brief deprecated - replaced by mv_tokenrefresh.sas
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mv_tokenrefresh.sas @li mv_tokenrefresh.sas

View File

@@ -3,8 +3,7 @@
@brief deprecated - replaced by mv_registerclient.sas @brief deprecated - replaced by mv_registerclient.sas
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mv_registerclient.sas @li mv_registerclient.sas

View File

@@ -29,8 +29,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -15,8 +15,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas
@@ -85,10 +84,16 @@ options noquotelenmax;
/*data _null_;infile &fname1;input;putlog _infile_;run;*/ /*data _null_;infile &fname1;input;putlog _infile_;run;*/
libname &libref1 JSON fileref=&fname1; libname &libref1 JSON fileref=&fname1;
/* now get the followon link to list members */ /* now get the followon link to list members */
%local href;
%let href=0;
data _null_; data _null_;
set &libref1..links; set &libref1..links;
if rel='members' then call symputx('href',quote("&base_uri"!!trim(href)),'l'); if rel='members' then call symputx('href',quote("&base_uri"!!trim(href)),'l');
run; run;
%if &href=0 %then %do;
%put NOTE:;%put NOTE- No members found in &root!!;%put NOTE-;
%return;
%end;
%local fname2 libref2; %local fname2 libref2;
%let fname2=%mf_getuniquefileref(); %let fname2=%mf_getuniquefileref();
%let libref2=%mf_getuniquelibref(); %let libref2=%mf_getuniquelibref();

View File

@@ -30,8 +30,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -29,8 +29,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -3,8 +3,7 @@
@brief deprecated - replaced by mv_tokenauth.sas @brief deprecated - replaced by mv_tokenauth.sas
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mv_tokenauth.sas @li mv_tokenauth.sas

View File

@@ -20,8 +20,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -47,8 +47,7 @@
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

168
viya/mv_jobexecute.sas Normal file
View File

@@ -0,0 +1,168 @@
/**
@file
@brief Executes a SAS Viya Job
@details Triggers a SAS Viya Job, with optional URL parameters, using
the JES web app.
First, compile the macros:
filename mc url
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
Then, execute the job!
%mv_jobexecute(path=/Public/folder
,name=somejob
)
Example with parameters:
%mv_jobexecute(path=/Public/folder
,name=somejob
,paramstring=%str("macvarname":"macvarvalue","answer":42)
)
@param access_token_var= The global macro variable to contain the access token
@param grant_type= valid values:
* password
* authorization_code
* detect - will check if access_token exists, if not will use sas_services if
a SASStudioV session else authorization_code. Default option.
* sas_services - will use oauth_bearer=sas_services
@param path= The SAS Drive path to the job being executed
@param name= The name of the job to execute
@param paramstring= A JSON fragment with name:value pairs, eg: `"name":"value"`
or "name":"value","name2":42`. This will need to be wrapped in `%str()`.
@param contextName= Context name with which to run the job.
Default = `SAS Job Execution compute context`
@param outds= The output dataset containing links (Default=work.mv_jobexecute)
@version VIYA V.03.04
@author Allan Bowe, source: https://github.com/sasjs/core
<h4> Dependencies </h4>
@li mp_abort.sas
@li mf_getplatform.sas
@li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@li mv_getfoldermembers.sas
**/
%macro mv_jobexecute(path=0
,name=0
,contextName=SAS Job Execution compute context
,access_token_var=ACCESS_TOKEN
,grant_type=sas_services
,paramstring=0
,outds=work.mv_jobexecute
);
%local oauth_bearer;
%if &grant_type=detect %then %do;
%if %symexist(&access_token_var) %then %let grant_type=authorization_code;
%else %let grant_type=sas_services;
%end;
%if &grant_type=sas_services %then %do;
%let oauth_bearer=oauth_bearer=sas_services;
%let &access_token_var=;
%end;
%put &sysmacroname: grant_type=&grant_type;
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
and &grant_type ne sas_services
)
,mac=&sysmacroname
,msg=%str(Invalid value for grant_type: &grant_type)
)
%mp_abort(iftrue=("&path"="0")
,mac=&sysmacroname
,msg=%str(Path not provided)
)
%mp_abort(iftrue=("&name"="0")
,mac=&sysmacroname
,msg=%str(Job Name not provided)
)
options noquotelenmax;
%local base_uri; /* location of rest apis */
%let base_uri=%mf_getplatform(VIYARESTAPI);
data;run;
%local foldermembers;
%let foldermembers=&syslast;
%mv_getfoldermembers(root=&path
,access_token_var=&access_token_var
,grant_type=&grant_type
,outds=&foldermembers
)
%local joburi;
%let joburi=0;
data _null_;
set &foldermembers;
if name="&name" and uri=:'/jobDefinitions/definitions'
then call symputx('joburi',uri);
run;
%mp_abort(iftrue=("&joburi"="0")
,mac=&sysmacroname
,msg=%str(Job &path/&name not found)
)
/* prepare request*/
%local fname0 fname1;
%let fname0=%mf_getuniquefileref();
%let fname1=%mf_getuniquefileref();
data _null_;
file &fname0;
length joburi contextname $128 paramstring $32765;
joburi=quote(trim(symget('joburi')));
contextname=quote(trim(symget('contextname')));
paramstring=symget('paramstring');
put '{"jobDefinitionUri":' joburi ;
put ' ,"arguments":{"_contextName":' contextname;
if paramstring ne "0" then do;
put ' ,' paramstring;
end;
put '}}';
run;
proc http method='POST' in=&fname0 out=&fname1 &oauth_bearer
url="&base_uri/jobExecution/jobs";
headers "Content-Type"="application/vnd.sas.job.execution.job.request+json"
"Accept"="application/vnd.sas.job.execution.job+json"
%if &grant_type=authorization_code %then %do;
"Authorization"="Bearer &&&access_token_var"
%end;
;
run;
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201 %then
%do;
data _null_;infile &fname0;input;putlog _infile_;run;
data _null_;infile &fname1;input;putlog _infile_;run;
%mp_abort(mac=&sysmacroname
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
)
%end;
%local libref;
%let libref=%mf_getuniquelibref();
libname &libref JSON fileref=&fname1;
data &outds;
set &libref..links;
run;
/* clear refs */
filename &fname0 clear;
filename &fname1 clear;
libname &libref;
%mend;

View File

@@ -52,8 +52,7 @@
for debugging. Default= _null_. for debugging. Default= _null_.
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -41,8 +41,7 @@
@param base_uri= The Viya API server location @param base_uri= The Viya API server location
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -40,8 +40,7 @@
@param refresh_token_var= The global macro variable containing the refresh token @param refresh_token_var= The global macro variable containing the refresh token
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
@source https://github.com/sasjs/core
<h4> Dependencies </h4> <h4> Dependencies </h4>
@li mp_abort.sas @li mp_abort.sas

View File

@@ -32,7 +32,7 @@
@li mf_getuser.sas @li mf_getuser.sas
@version Viya 3.3 @version Viya 3.3
@author Allan Bowe @author Allan Bowe, source: https://github.com/sasjs/core
**/ **/
%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y); %macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y);