1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-11 22:44:36 +00:00

Compare commits

...

45 Commits

Author SHA1 Message Date
Allan Bowe
1beb30d0ff fix: updating <h4> Dependencies </h4> in header to be <h4> SAS Macros </h4> in line with the updated SASjs compilation process (which distinguishes between SAS Macro and SAS Program dependencies)
BREAKING CHANGE - this doesn't break anything in the framework but I know of at least one old project that uses the <h4> Dependencies </h4> tag to perform backend compilation, so am bumping the version to be safe (looking at you, Chris
2020-12-25 10:36:19 +00:00
Allan Bowe
e334ea9b85 chore: all.sas update 2020-12-25 10:22:44 +00:00
Allan Bowe
c090c8d53b feat: simple macro to test the write speed for a library (very very basic) 2020-12-25 10:18:02 +00:00
Allan Bowe
659339bd98 fix: more comments in mp_prevobs 2020-12-25 10:15:03 +00:00
Allan Bowe
4c333ae7b3 feat: mp_prevobs.sas macro 2020-12-23 00:33:59 +00:00
b3a8b4323e fix: adding new mp_ds2csv macro 2020-12-16 17:11:31 +01:00
0592206f2d patch: doxy formatting 2020-12-03 22:44:08 +01:00
bedc2a443a fix: @cond on new line to prevent parsing issues in sasjs cli 2020-12-02 08:09:51 +01:00
6f86ed62a2 chore: doxy formatting 2020-11-29 22:03:20 +01:00
def0cc8476 fix: adding outds and parameters to mv_jobexecute 2020-11-29 21:55:21 +01:00
3a9029557e chore: doxygen updates 2020-11-29 21:06:39 +01:00
9dc3bcd513 fix: updating all.sas 2020-11-29 13:58:04 +01:00
2bcf6346ac fix: upgrading to latest doxygen 2020-11-29 13:57:44 +01:00
0eccc169f5 feat: adding mv_jobexecute macro (and a fix for mv_getfoldermembers where there are no members) 2020-11-29 13:56:51 +01:00
493639fe4a fix: composite PK 2020-11-26 01:26:16 +01:00
4987d2fbbc fix: missing dependency in mp_getdbml 2020-11-26 01:11:33 +01:00
1a35b357d6 feat: mp_tree macro 2020-11-25 23:21:07 +01:00
a7792d93e4 feat: mf_isdir macro 2020-11-25 22:35:04 +01:00
541dc31ad0 feat: mp_getdbml.sas macro for generating DBML for one or more SAS Libraries 2020-11-25 16:37:42 +01:00
abccafab7b feat: adding filref option to mp_streamfile.sas 2020-11-16 11:08:01 +01:00
f6cec012da fix: removing unnecessary cond flags in mf_abort, adding abort logic in mp_csv2ds 2020-11-08 22:04:25 +01:00
d51be73017 fix: macro param and extra log info in mp_csv2ds 2020-11-03 09:43:47 +01:00
cafffbb509 fix: adding a period to enable formats such as anydtdtme 2020-11-02 17:26:59 +01:00
a88efacfab fix: making view an option so that existence can be checked for 2020-11-02 17:15:29 +01:00
cc7cc55022 feat: mp_csv2ds macro for importing a CSV using a SAS table to provide a template (eg for lengths / types etc) 2020-11-02 15:44:45 +01:00
15687be5d6 fix: tidy up of SAS flavour DDL 2020-10-30 11:43:15 +01:00
d9a82c0bdf fix: incorrect filepath when using filerefs in mp_dirlist 2020-10-29 12:08:07 +01:00
6f06e5540d feat: adding fileref support for mp_dirlist, as well as a directory column on the output dataset 2020-10-29 11:30:15 +01:00
6b782a4fa2 chore: adding sitemap 2020-10-18 01:00:35 +02:00
efe4709dde chore: formatting in mp_guesspk 2020-10-14 16:42:04 +02:00
5cb41041d9 fix: upcase showlog value in mp_getddl() to allow lowercase user entries 2020-10-13 11:20:30 +02:00
f50cb03fd3 fix: mp_ds2cards was failing when the maxobs was less than the number of variables. SQL maxobs option is now reset. 2020-10-12 18:28:50 +02:00
ac46489f11 fix: enabling mp_abort.sas to work in Viya when useComputeApi is true (and the SYS_JES_JOB_URI is empty) 2020-10-11 00:34:08 +02:00
vrh
5e45701e74 fix: extra debug info in mp_searchdata, as well as named literal support 2020-10-02 22:34:36 +02:00
vrh
8caaacd9f0 docs: comment fix 2020-09-28 09:22:29 +02:00
vrh
91983e0a91 fix: trim edge cases and return of the register client url 2020-09-11 00:38:37 +02:00
vrh
7b72f0ac94 fix: alternative base_uri option on tokenauth macro, also description update for listclients 2020-09-10 09:30:09 +02:00
vrh
3eae34d8b7 fix: adding base_uri in all calls to cover instances where viya calls are not on localhost 2020-09-07 14:01:39 +02:00
vrh
58358c916d chore: doc updates 2020-09-05 17:22:38 +02:00
vrh
578ef26cd5 fix: support for tab characters, closes https://github.com/macropeople/macrocore/issues/21 2020-09-04 09:51:11 +02:00
vrh
33189743cd fix: accidental end comment 2020-09-03 18:07:18 +02:00
vrh
459beff4fa feat: mf_trimstr macro 2020-09-03 17:49:44 +02:00
vrh
1c873afe57 fix: base_uri for mv_deletejes 2020-09-03 16:29:21 +02:00
Allan Bowe
2b683509ac Merge pull request #4 from sasjs/change
fix: base_uri
2020-09-03 16:26:48 +02:00
vrh
dcccd1491d fix: base_uri 2020-09-03 16:24:32 +02:00
90 changed files with 2695 additions and 4629 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:

View File

@@ -91,7 +91,25 @@ The **Macro Core** documentation is created using [doxygen](http://www.doxygen.n
- version. The EARLIEST SAS version in which this macro is known to work. - version. The EARLIEST SAS version in which this macro is known to work.
- author. Author name, contact details optional - author. Author name, contact details optional
All macros must be commented in the doxygen format, to enable the [online documentation](https://sasjs.github.io/core.github.io/). All macros must be commented in the doxygen format, to enable the [online documentation](https://core.sasjs.io).
### Dependencies
SAS code can contain one of two types of dependency - SAS Macros, and SAS Programs. When compiling projects using the [SASjs CLI](https://cli.sasjs.io) the doxygen header is scanned for ` @li` items under the following headers:
```
<h4> SAS Macros </h4>
@li mf_nobs.sas
@li mm_assignlib.sas
<h4> SAS Programs </h4>
@li somefile.ddl SOMEFREF
@li someprogram.sas FREFTWO
```
The CLI can then extract all the dependencies and insert as precode (SAS Macros) or in a temp engine fileref (SAS Programs) when creating SAS Jobs and Services.
When contributing to this library, it is therefore important to ensure that all dependencies are listed in the header in this format.
## Coding Standards ## Coding Standards
@@ -102,6 +120,7 @@ All macros must be commented in the doxygen format, to enable the [online docume
- Mandatory parameters should be positional, all optional parameters should be keyword (var=) style. - Mandatory parameters should be positional, all optional parameters should be keyword (var=) style.
- All dataset references must be 2 level (eg `work.blah`, not `blah`). This is to avoid contention when options [DATASTMTCHK](https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000279064.htm)=ALLKEYWORDS is in effect. - All dataset references must be 2 level (eg `work.blah`, not `blah`). This is to avoid contention when options [DATASTMTCHK](https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000279064.htm)=ALLKEYWORDS is in effect.
- Avoid naming collisions! All macro variables should be local scope. Use system generated work tables where possible - eg `data ; set sashelp.class; run; data &output; set &syslast; run;` - Avoid naming collisions! All macro variables should be local scope. Use system generated work tables where possible - eg `data ; set sashelp.class; run; data &output; set &syslast; run;`
- If you have a long-running SQL query, the use of a `quit;` statement is recommended in order to benefit from the timing statistics.
# General Notes # General Notes

1359
all.sas

File diff suppressed because it is too large Load Diff

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.
@@ -13,13 +13,14 @@
@return output returns 1 or 0 (or -1 if not found) @return output returns 1 or 0 (or -1 if not found)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getplatform.sas @li mf_getplatform.sas
@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

@@ -6,7 +6,7 @@
%put %mf_existVarList(sashelp.class, age sex name dummyvar) %put %mf_existVarList(sashelp.class, age sex name dummyvar)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_abort.sas @li mf_abort.sas
@param libds 2 part dataset or view reference @param libds 2 part dataset or view reference
@@ -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

@@ -3,7 +3,7 @@
@brief Returns the engine type of a SAS library @brief Returns the engine type of a SAS library
@details Usage: @details Usage:
%put %mf_getEngine(SASHELP); %put %mf_getengine(SASHELP);
returns: returns:
> V9 > V9
@@ -21,9 +21,11 @@
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
**/
%macro mf_getEngine(libref **/
/** @cond */
%macro mf_getengine(libref
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local dsid engnum rc engine; %local dsid engnum rc engine;
@@ -42,3 +44,5 @@
&engine &engine
%mend; %mend;
/** @endcond */

View File

@@ -10,8 +10,9 @@
@param switch the param for which to return a platform specific variable @param switch the param for which to return a platform specific variable
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_mval.sas @li mf_mval.sas
@li mf_trimstr.sas
@version 9.4 / 3.4 @version 9.4 / 3.4
@author Allan Bowe @author Allan Bowe
@@ -57,6 +58,6 @@
%else 0; %else 0;
%end; %end;
%else %if &switch=VIYARESTAPI %then %do; %else %if &switch=VIYARESTAPI %then %do;
%sysfunc(getoption(servicesbaseurl)) %mf_trimstr(%sysfunc(getoption(servicesbaseurl)),/)
%end; %end;
%mend; %mend;

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

@@ -7,7 +7,7 @@
%put %mf_getvalue(sashelp.class,name,filter=%quote(age=15)); %put %mf_getvalue(sashelp.class,name,filter=%quote(age=15));
%put %mf_getvalue(sashelp.class,name); %put %mf_getvalue(sashelp.class,name);
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getattrn.sas @li mf_getattrn.sas
@param libds dataset to query @param libds dataset to query

33
base/mf_isdir.sas Normal file
View File

@@ -0,0 +1,33 @@
/**
@file
@brief Checks whether a path is a valid directory
@details
Usage:
%let isdir=%mf_isdir(/tmp);
With thanks and full credit to Andrea Defronzo - https://www.linkedin.com/in/andrea-defronzo-b1a47460/
@param path full path of the file/directory to be checked
@return output returns 1 if path is a directory, 0 if it is not
@version 9.2
**/
%macro mf_isdir(path
)/*/STORE SOURCE*/;
%local rc did is_directory fref_t;
%let is_directory = 0;
%let rc = %sysfunc(filename(fref_t, %superq(path)));
%let did = %sysfunc(dopen(&fref_t.));
%if &did. ^= 0 %then %do;
%let is_directory = 1;
%let rc = %sysfunc(dclose(&did.));
%end;
%let rc = %sysfunc(filename(fref_t));
&is_directory
%mend;

View File

@@ -6,7 +6,7 @@
%put Number of observations=%mf_nobs(sashelp.class); %put Number of observations=%mf_nobs(sashelp.class);
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getattrn.sas @li mf_getattrn.sas
@param libds library.dataset @param libds library.dataset

49
base/mf_trimstr.sas Normal file
View File

@@ -0,0 +1,49 @@
/**
@file mf_trimstr.sas
@brief Removes character(s) from the end, if they exist
@details If the designated characters exist at the end of the string, they
are removed
%put %mf_trimstr(/blah/,/); * /blah;
%put %mf_trimstr(/blah/,h); * /blah/;
%put %mf_trimstr(/blah/,h/);* /bla;
<h4> SAS Macros </h4>
@param basestr The string to be modified
@param trimstr The string to be removed from the end of `basestr`, if it exists
@return output returns result with the value of `trimstr` removed from the end
@version 9.2
@author Allan Bowe
**/
%macro mf_trimstr(basestr,trimstr);
%local baselen trimlen trimval;
/* return if basestr is shorter than trimstr (or 0) */
%let baselen=%length(%superq(basestr));
%let trimlen=%length(%superq(trimstr));
%if &baselen < &trimlen or &baselen=0 %then %return;
/* obtain the characters from the end of basestr */
%let trimval=%qsubstr(%superq(basestr)
,%length(%superq(basestr))-&trimlen+1
,&trimlen);
/* compare and if matching, chop it off! */
%if %superq(basestr)=%superq(trimstr) %then %do;
%return;
%end;
%else %if %superq(trimval)=%superq(trimstr) %then %do;
%qsubstr(%superq(basestr),1,%length(%superq(basestr))-&trimlen)
%end;
%else %do;
&basestr
%end;
%mend;

View File

@@ -11,7 +11,7 @@
Returns: Returns:
> 1 > 1
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_abort.sas @li mf_abort.sas
@param verifyvars space separated list of macro variable names @param verifyvars space separated list of macro variable names

View File

@@ -6,12 +6,19 @@
results back to the client in an STP Web App context, or completely stop results back to the client in an STP Web App context, or completely stop
in the case of a batch run. in the case of a batch run.
Using SAS Abort Cancel mechanisms can cause hung sessions in some Stored Process
environments. This macro takes a unique approach - we set the SAS syscc to 0,
run `stpsrvset('program error', 0)` (if SAS 9) and then - we open a macro
but don't close it! This provides a graceful abort for SAS web services in all
web enabled environments.
@param mac= to contain the name of the calling macro @param mac= to contain the name of the calling macro
@param msg= message to be returned @param msg= message to be returned
@param iftrue= supply a condition under which the macro should be executed. @param iftrue= supply a condition under which the macro should be executed.
@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)
@@ -65,8 +72,15 @@
%end; %end;
%if %symexist(SYS_JES_JOB_URI) %then %do; %if %symexist(SYS_JES_JOB_URI) %then %do;
/* refer web service output to file service in one hit */ /* setup webout */
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"; OPTIONS NOBOMFILE;
%if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
filename _webout temp lrecl=999999 mod;
%end;
%else %do;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI"
name="_webout.json" lrecl=999999 mod;
%end;
%end; %end;
/* send response in SASjs JSON format */ /* send response in SASjs JSON format */
@@ -138,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 */

View File

@@ -22,7 +22,7 @@
@param outds= a table containing the create statements (create_statement column) @param outds= a table containing the create statements (create_statement column)
@param execute= `YES|NO` - default is NO. To actually create, use YES. @param execute= `YES|NO` - default is NO. To actually create, use YES.
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe

View File

@@ -26,7 +26,7 @@ Usage:
;;;; ;;;;
%mp_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001,replace=YES) %mp_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001,replace=YES)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getplatform.sas @li mf_getplatform.sas
@li mm_createwebservice.sas @li mm_createwebservice.sas
@li mv_createwebservice.sas @li mv_createwebservice.sas

144
base/mp_csv2ds.sas Normal file
View File

@@ -0,0 +1,144 @@
/**
@file mp_csv2ds.sas
@brief Efficient import of arbitrary CSV using a dataset as template
@details Used to import relevant columns from a large CSV using
a dataset to provide the types and lengths. Assumes that a header
row is provided, and datarows start on line 2. Extra columns in
both the CSV and base dataset are ignored.
Usage:
filename mycsv temp;
data _null_;
file mycsv;
put 'name,age,nickname';
put 'John,48,Jonny';
put 'Jennifer,23,Jen';
run;
%mp_csv2ds(inref=mycsv,outds=myds,baseds=sashelp.class)
@param inref= fileref to the CSV
@param outds= output ds (lib.ds format)
@param view= Set to YES or NO to determine whether the output should be
a view or not. Default is NO (not a view).
@param baseds= Template dataset on which to create the input statement.
Is used to determine types, lengths, and any informats.
@version 9.2
@author Allan Bowe
<h4> SAS Macros </h4>
@li mp_abort.sas
@li mf_existds.sas
**/
%macro mp_csv2ds(inref=0,outds=0,baseds=0,view=NO);
%mp_abort(iftrue=( &inref=0 )
,mac=&sysmacroname
,msg=%str(the INREF variable must be provided)
)
%mp_abort(iftrue=( %superq(outds)=0 )
,mac=&sysmacroname
,msg=%str(the OUTDS variable must be provided)
)
%mp_abort(iftrue=( &baseds=0 )
,mac=&sysmacroname
,msg=%str(the BASEDS variable must be provided)
)
%mp_abort(iftrue=( &baseds=0 )
,mac=&sysmacroname
,msg=%str(the BASEDS variable must be provided)
)
%mp_abort(iftrue=( %mf_existds(&baseds)=0 )
,mac=&sysmacroname
,msg=%str(the BASEDS dataset (&baseds) needs to be assigned, and to exist)
)
/* count rows */
%local hasheader; %let hasheader=0;
data _null_;
if _N_ > 1 then do;
call symputx('hasheader',1,'l');
stop;
end;
infile &inref;
input;
run;
%mp_abort(iftrue=( &hasheader=0 )
,mac=&sysmacroname
,msg=%str(No header row in &inref)
)
/* get the variables in the CSV */
data _data_;
infile &inref;
input;
length name $32;
do i=1 to countc(_infile_,',')+1;
name=upcase(scan(_infile_,i,','));
output;
end;
stop;
run;
%local csv_vars;%let csv_vars=&syslast;
/* get the variables in the dataset */
proc contents noprint data=&baseds
out=_data_ (keep=name type length format: informat);
run;
%local base_vars; %let base_vars=&syslast;
proc sql undo_policy=none;
create table &csv_vars as
select a.*
,b.type
,b.length
,b.format
,b.formatd
,b.formatl
,b.informat
from &csv_vars a
left join &base_vars b
on a.name=upcase(b.name)
order by i;
/* prepare the input statement */
%local instat dropvars;
data _null_;
set &syslast end=last;
length in dropvars $32767;
retain in dropvars;
if missing(type) then do;
informat='$1.';
dropvars=catx(' ',dropvars,name);
end;
else if missing(informat) then do;
if type=1 then informat='best.';
else informat=cats('$',length,'.');
end;
else informat=cats(informat,'.');
in=catx(' ',in,name,':',informat);
if last then do;
call symputx('instat',in,'l');
call symputx('dropvars',dropvars,'l');
end;
run;
/* import the CSV */
data &outds
%if %upcase(&view)=YES %then %do;
/view=&outds
%end;
;
infile &inref dsd firstobs=2;
input &instat;
%if %length(&dropvars)>0 %then %do;
drop &dropvars;
%end;
run;
%mend;

View File

@@ -20,6 +20,8 @@
%mp_dirlist(outds=cwdfileprops, getattrs=YES) %mp_dirlist(outds=cwdfileprops, getattrs=YES)
%mp_dirlist(fref=MYFREF)
@warning In a Unix environment, the existence of a named pipe will cause this @warning In a Unix environment, the existence of a named pipe will cause this
macro to hang. Therefore this tool should be used with caution in a SAS 9 web macro to hang. Therefore this tool should be used with caution in a SAS 9 web
application, as it can use up all available multibridge sessions if requests application, as it can use up all available multibridge sessions if requests
@@ -29,12 +31,14 @@
@param path= for which to return contents @param path= for which to return contents
@param fref= Provide a DISK engine fileref as an alternative to PATH
@param outds= the output dataset to create @param outds= the output dataset to create
@param getattrs= YES/NO (default=NO). Uses doptname and foptname to return @param getattrs= YES/NO (default=NO). Uses doptname and foptname to return
all attributes for each file / folder. all attributes for each file / folder.
@returns outds contains the following variables: @returns outds contains the following variables:
- directory (containing folder)
- file_or_folder (file / folder) - file_or_folder (file / folder)
- filepath (path/to/file.name) - filepath (path/to/file.name)
- filename (just the file name) - filename (just the file name)
@@ -47,18 +51,26 @@
**/ **/
%macro mp_dirlist(path=%sysfunc(pathname(work)) %macro mp_dirlist(path=%sysfunc(pathname(work))
, fref=0
, outds=work.mp_dirlist , outds=work.mp_dirlist
, getattrs=NO , getattrs=NO
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%let getattrs=%upcase(&getattrs)XX; %let getattrs=%upcase(&getattrs)XX;
data &outds (compress=no keep=file_or_folder filepath filename ext msg); data &outds (compress=no keep=file_or_folder filepath filename ext msg directory);
length filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200; length directory filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200;
%if &fref=0 %then %do;
rc = filename(fref, "&path"); rc = filename(fref, "&path");
%end;
%else %do;
fref="&fref";
rc=0;
%end;
if rc = 0 then do; if rc = 0 then do;
did = dopen(fref); did = dopen(fref);
directory=dinfo(did,'Directory');
if did=0 then do; if did=0 then do;
putlog "NOTE: This directory is empty - &path"; putlog "NOTE: This directory is empty - " directory;
msg=sysmsg(); msg=sysmsg();
put _all_; put _all_;
stop; stop;
@@ -73,7 +85,8 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg);
dnum = dnum(did); dnum = dnum(did);
do i = 1 to dnum; do i = 1 to dnum;
filename = dread(did, i); filename = dread(did, i);
rc = filename(fref2, "&path/"!!filename); filepath=cats(directory,'/',filename);
rc = filename(fref2,filepath);
midd=dopen(fref2); midd=dopen(fref2);
dmsg=sysmsg(); dmsg=sysmsg();
if did > 0 then file_or_folder='folder'; if did > 0 then file_or_folder='folder';
@@ -96,7 +109,6 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg);
ext=''; ext='';
file_or_folder='folder'; file_or_folder='folder';
end; end;
filepath="&path/"!!filename;
output; output;
end; end;
rc = dclose(did); rc = dclose(did);

View File

@@ -9,7 +9,7 @@
create view view2 as select * from sashelp.class; create view view2 as select * from sashelp.class;
%mp_dropmembers(list=data1 view2) %mp_dropmembers(list=data1 view2)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_isblank.sas @li mf_isblank.sas

View File

@@ -103,8 +103,7 @@ proc sql
order by ranuni(42) order by ranuni(42)
%end; %end;
; ;
reset outobs=max;
create table datalines1 as create table datalines1 as
select name,type,length,varnum,format,label from dictionary.columns select name,type,length,varnum,format,label from dictionary.columns
where libname="%upcase(%scan(&base_ds,1))" where libname="%upcase(%scan(&base_ds,1))"

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

@@ -21,7 +21,7 @@
@param ds= The target dataset. Leave blank (default) for all datasets. @param ds= The target dataset. Leave blank (default) for all datasets.
@param outds the output dataset @param outds the output dataset
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe

326
base/mp_getdbml.sas Normal file
View File

@@ -0,0 +1,326 @@
/**
@file
@brief Extract DBML from SAS Libraries
@details DBML is an open source markup format to represent databases.
More details: https://www.dbml.org/home/
Usage:
%mp_getdbml(liblist=SASHELP WORK,outref=mydbml,showlog=YES)
Take the log output and paste it into the renderer at https://dbdiagram.io
to view your data model diagram. The code takes a "best guess" at
the one to one and one to many relationships (based on constraints
and indexes, and assuming that the column names would match).
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>
@li mf_getquotedstr.sas
@li mp_getconstraints.sas
@param liblist= Space seperated list of librefs to take as
input (Default=SASHELP)
@param outref= Fileref to contain the DBML (Default=getdbml)
@param showlog= set to YES to show the DBML in the log (Default is NO)
@version 9.3
@author Allan Bowe
**/
%macro mp_getdbml(liblist=SASHELP,outref=getdbml,showlog=NO
)/*/STORE SOURCE*/;
/* check fileref is assigned */
%if %sysfunc(fileref(&outref)) > 0 %then %do;
filename &outref temp;
%end;
%let liblist=%upcase(&liblist);
proc sql noprint;
create table _data_ as
select * from dictionary.tables
where upcase(libname) in (%mf_getquotedstr(&liblist))
order by libname,memname;
%local tabinfo; %let tabinfo=&syslast;
create table _data_ as
select * from dictionary.columns
where upcase(libname) in (%mf_getquotedstr(&liblist))
order by libname,memname,varnum;
%local colinfo; %let colinfo=&syslast;
%local dsnlist;
select distinct upcase(cats(libname,'.',memname)) into: dsnlist
separated by ' '
from &syslast
;
create table _data_ as
select * from dictionary.indexes
where upcase(libname) in (%mf_getquotedstr(&liblist))
order by idxusage, indxname, indxpos;
%local idxinfo; %let idxinfo=&syslast;
/* Extract all Primary Key and Unique data constraints */
%mp_getconstraints(lib=%scan(&liblist,1),outds=_data_)
%local colconst; %let colconst=&syslast;
%do x=2 %to %sysfunc(countw(&liblist));
%mp_getconstraints(lib=%scan(&liblist,&x),outds=_data_)
proc append base=&colconst data=&syslast;
run;
%end;
/* header info */
data _null_;
file &outref;
put "// DBML generated by &sysuserid on %sysfunc(datetime(),datetime19.) ";
put "Project sasdbml {";
put " database_type: 'SAS'";
put " Note: 'Generated by the mp_getdbml() macro'";
put "}";
run;
/* create table groups */
data _null_;
file &outref mod;
set &tabinfo;
by libname;
if first.libname then put "TableGroup " libname "{";
ds=quote(cats(libname,'.',memname));
put ' ' ds;
if last.libname then put "}";
run;
/* table for pks */
data _data_;
length curds const col $39;
call missing (of _all_);
stop;
run;
%let pkds=&syslast;
%local x curds constraints_used constcheck;
%do x=1 %to %sysfunc(countw(&dsnlist,%str( )));
%let curds=%scan(&dsnlist,&x,%str( ));
%let constraints_used=;
%let constcheck=0;
data _null_;
file &outref mod;
length lab $1024 typ $20;
set &colinfo (where=(
libname="%scan(&curds,1,.)" and upcase(memname)="%scan(&curds,2,.)"
)) end=last;
if _n_=1 then do;
table='Table "'!!"&curds"!!'"{';
put table;
end;
name=upcase(name);
lab=" note:"!!quote(trim(tranwrd(label,'"',"'")));
if upcase(format)=:'DATETIME' then typ='datetime';
else if type='char' then typ=cats('char(',length,')');
else typ='num';
if notnull='yes' then notnul=' not null';
if notnull='no' and missing(label) then put ' ' name typ;
else if notnull='yes' and missing(label) then put ' ' name typ '[' notnul ']';
else if notnull='no' then put ' ' name typ '[' lab ']';
else put ' ' name typ '[' notnul ',' lab ']';
run;
data _data_(keep=curds const col);
length ctype $11 cols constraints_used $5000;
set &colconst (where=(
upcase(libref)="%scan(&curds,1,.)"
and upcase(table_name)="%scan(&curds,2,.)"
and constraint_type in ('PRIMARY','UNIQUE')
)) end=last;
file &outref mod;
by constraint_type constraint_name;
retain cols;
column_name=upcase(column_name);
if _n_=1 then put / ' indexes {';
if upcase(strip(constraint_type)) = 'PRIMARY' then ctype='[pk]';
else ctype='[unique]';
if first.constraint_name then cols = cats('(',column_name);
else cols=cats(cols,',',column_name);
if last.constraint_name then do;
cols=cats(cols,')',ctype)!!' //'!!constraint_name;
put ' ' cols;
constraints_used=catx(' ',constraints_used, constraint_name);
call symputx('constcheck',1);
end;
if last then call symputx('constraints_used',cats(upcase(constraints_used)));
length curds const col $39;
curds="&curds";
const=constraint_name;
col=column_name;
run;
proc append base=&pkds data=&syslast;run;
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
data _data_(keep=curds const col);
set &idxinfo (where=(
libname="%scan(&curds,1,.)"
and upcase(memname)="%scan(&curds,2,.)"
and unique='yes'
and upcase(indxname) not in (%mf_getquotedstr(&constraints_used))
));
file &outref mod;
by idxusage indxname;
name=upcase(name);
if &constcheck=1 then stop; /* in fact we only care about PKs so stop if we have */
if _n_=1 and &constcheck=0 then put / ' indexes {';
length cols $5000;
retain cols;
if first.indxname then cols = cats('(',name);
else cols=cats(cols,',',name);
if last.indxname then do;
cols=cats(cols,')[unique]')!!' //'!!indxname;
put ' ' cols;
call symputx('constcheck',1);
end;
length curds const col $39;
curds="&curds";
const=indxname;
col=name;
run;
proc append base=&pkds data=&syslast;run;
data _null_;
file &outref mod;
if &constcheck =1 then put ' }';
put '}';
run;
%end;
/**
* now we need to figure out the relationships
*/
/* sort alphabetically so we can have one set of unique cols per table */
proc sort data=&pkds nodupkey;
by curds const col;
run;
data &pkds.1 (keep=curds col)
&pkds.2 (keep=curds cols);
set &pkds;
by curds const;
length retconst $39 cols $5000;
retain retconst cols;
if first.curds then do;
retconst=const;
cols=upcase(col);
end;
else cols=catx(' ',cols,upcase(col));
if retconst=const then do;
output &pkds.1;
if last.const then output &pkds.2;
end;
run;
%let curdslist="0";
%do x=1 %to %sysfunc(countw(&dsnlist,%str( )));
%let curds=%scan(&dsnlist,&x,%str( ));
%let pkcols=0;
data _null_;
set &pkds.2(where=(curds="&curds"));
call symputx('pkcols',cols);
run;
%if &pkcols ne 0 %then %do;
%let curdslist=&curdslist,"&curds";
/* start with one2one */
data &pkds.4;
file &outref mod;
set &pkds.2(where=(cols="&pkcols" and curds not in (&curdslist)));
line='Ref: "'!!"&curds"
!!cats('".(',"%mf_getquotedstr(&pkcols,dlm=%str(,),quote=%str( ))",')')
!!' - '
!!cats(quote(trim(curds)),'.(',"%mf_getquotedstr(&pkcols,dlm=%str(,),quote=%str( ))",')');
put line;
run;
/* now many2one */
/* get table with one row per col */
data &pkds.5;
set &pkds.1(where=(curds="&curds"));
run;
/* get tables which contain the PK columns */
proc sql;
create table &pkds.5a as
select upcase(cats(b.libname,'.',b.memname)) as curds
,b.name
from &pkds.5 a
inner join &colinfo b
on a.col=upcase(b.name);
/* count to make sure those tables contain ALL the columns */
create table &pkds.5b as
select curds,count(*) as cnt
from &pkds.5a
where curds not in (select curds from &pkds.2 where cols="&pkcols") /* not a one to one match */
and curds ne "&curds" /* exclude self */
group by 1;
create table &pkds.6 as
select a.*
,b.cols
from &pkds.5b a
left join &pkds.4 b
on a.curds=b.curds;
data _null_;
set &pkds.6;
file &outref mod;
colcnt=%sysfunc(countw(&pkcols));
if cnt=colcnt then do;
/* table contains all the PK cols, and was not a direct / 121 match */
line='Ref: "'!!"&curds"
!!'".('
!!"%mf_getquotedstr(&pkcols,dlm=%str(,),quote=%str( ))"
!!') > '
!!cats(quote(trim(curds))
,'.('
,"%mf_getquotedstr(&pkcols,dlm=%str(,),quote=%str( ))"
,')'
);
put line;
end;
run;
%end;
%end;
%if %upcase(&showlog)=YES %then %do;
options ps=max;
data _null_;
infile &outref;
input;
putlog _infile_;
run;
%end;
%mend;

View File

@@ -15,7 +15,7 @@
proc sql; describe table &syslast; proc sql; describe table &syslast;
%mp_getddl(work,test,flavour=tsql,showlog=YES) %mp_getddl(work,test,flavour=tsql,showlog=YES)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mp_getconstraints.sas @li mp_getconstraints.sas
@param lib libref of the library to create DDL for. Should be assigned. @param lib libref of the library to create DDL for. Should be assigned.
@@ -30,7 +30,6 @@
datetime2 format or regular decimal type datetime2 format or regular decimal type
@version 9.3 @version 9.3
@author Allan Bowe @author Allan Bowe
@source https://github.com/sasjs/core
**/ **/
%macro mp_getddl(libref,ds,fref=getddl,flavour=SAS,showlog=NO,schema= %macro mp_getddl(libref,ds,fref=getddl,flavour=SAS,showlog=NO,schema=
@@ -132,7 +131,7 @@ run;
%let curds=%scan(&dsnlist,&x); %let curds=%scan(&dsnlist,&x);
data _null_; data _null_;
file &fref mod; file &fref mod;
length nm lab $1024; length nm lab $1024 typ $20;
set &colinfo (where=(upcase(memname)="&curds")) end=last; set &colinfo (where=(upcase(memname)="&curds")) end=last;
if _n_=1 then do; if _n_=1 then do;
@@ -146,10 +145,12 @@ run;
end; end;
else put " ,"@@; else put " ,"@@;
if length(format)>1 then fmt=" format="!!cats(format); if length(format)>1 then fmt=" format="!!cats(format);
len=" length="!!cats(length); if length(label)>1 then lab=" label="!!quote(trim(label));
lab=" label="!!quote(trim(label));
if notnull='yes' then notnul=' not null'; if notnull='yes' then notnul=' not null';
put name type len fmt notnul lab; if type='char' then typ=cats('char(',length,')');
else if length ne 8 then typ='num length='!!left(length);
else typ='num';
put name typ fmt notnul lab;
run; run;
/* Extra step for data constraints */ /* Extra step for data constraints */
@@ -339,7 +340,7 @@ run;
%end; %end;
%end; %end;
%if &showlog=YES %then %do; %if %upcase(&showlog)=YES %then %do;
options ps=max; options ps=max;
data _null_; data _null_;
infile &fref; infile &fref;

View File

@@ -21,7 +21,7 @@
@param libds Two part dataset (or view) reference. @param libds Two part dataset (or view) reference.
@param outds= The output dataset to create @param outds= The output dataset to create
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getvarlist.sas @li mf_getvarlist.sas
@li mf_getvartype.sas @li mf_getvartype.sas
@li mf_getvarformat.sas @li mf_getvarformat.sas

View File

@@ -22,7 +22,7 @@
@param min_rows= The minimum number of rows a table should have in order to try @param min_rows= The minimum number of rows a table should have in order to try
and guess the PK. Default=5. and guess the PK. Default=5.
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getvarlist.sas @li mf_getvarlist.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_nobs.sas @li mf_nobs.sas

View File

@@ -8,7 +8,7 @@
%mp_lib2cards(lib=sashelp %mp_lib2cards(lib=sashelp
, outloc= C:\temp ) , outloc= C:\temp )
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_mkdir.sas @li mf_mkdir.sas
@li mp_ds2cards.sas @li mp_ds2cards.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

@@ -3,7 +3,7 @@
@brief Searches all data in a library @brief Searches all data in a library
@details @details
Scans an entire library and creates a copy of any table Scans an entire library and creates a copy of any table
containing a specific string or numeric value. Only containing a specific string OR numeric value. Only
matching records are written out. matching records are written out.
If both a string and numval are provided, the string If both a string and numval are provided, the string
will take precedence. will take precedence.
@@ -25,7 +25,7 @@
@param outobs= set to a positive integer to restrict the number of observations @param outobs= set to a positive integer to restrict the number of observations
@param filter_text= add a (valid) filter clause to further filter the results @param filter_text= add a (valid) filter clause to further filter the results
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getvarlist.sas @li mf_getvarlist.sas
@li mf_getvartype.sas @li mf_getvartype.sas
@li mf_mkdir.sas @li mf_mkdir.sas
@@ -44,9 +44,13 @@
,filter_text=%str(1=1) ,filter_text=%str(1=1)
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local table_list table table_num table colnum col start_tm vars type coltype; %local table_list table table_num table colnum col start_tm check_tm vars type coltype;
%put process began at %sysfunc(datetime(),datetime19.); %put process began at %sysfunc(datetime(),datetime19.);
%if &syscc ge 4 %then %do;
%put %str(WAR)NING: SYSCC=&syscc on macro entry;
%return;
%end;
%if &string = %then %let type=N; %if &string = %then %let type=N;
%else %let type=C; %else %let type=C;
@@ -78,6 +82,7 @@ proc sql
%put NO COLUMNS IN &lib..&table! This will be skipped.; %put NO COLUMNS IN &lib..&table! This will be skipped.;
%end; %end;
%else %do; %else %do;
%let check_tm=%sysfunc(datetime());
/* build sql statement */ /* build sql statement */
create table mpsearch.&table as select * from &lib..&table create table mpsearch.&table as select * from &lib..&table
where %unquote(&filter_text) and where %unquote(&filter_text) and
@@ -88,14 +93,19 @@ proc sql
%let coltype=%mf_getvartype(&lib..&table,&col); %let coltype=%mf_getvartype(&lib..&table,&col);
%if &type=C and &coltype=C %then %do; %if &type=C and &coltype=C %then %do;
/* if a char column, see if it contains the string */ /* if a char column, see if it contains the string */
or (&col ? "&string") or ("&col"n ? "&string")
%end; %end;
%else %if &type=N and &coltype=N %then %do; %else %if &type=N and &coltype=N %then %do;
/* if numeric match exactly */ /* if numeric match exactly */
or (&col = &numval) or ("&col"n = &numval)
%end; %end;
%end; %end;
); );
%put Search query for &table took %sysevalf(%sysfunc(datetime())-&check_tm) seconds;
%if &sqlrc ne 0 %then %do;
%put %str(WAR)NING: SQLRC=&sqlrc when processing &table;
%return;
%end;
%if %mf_nobs(mpsearch.&table)=0 %then %do; %if %mf_nobs(mpsearch.&table)=0 %then %do;
drop table mpsearch.&table; drop table mpsearch.&table;
%end; %end;

View File

@@ -6,7 +6,7 @@
%mp_setkeyvalue(someindex,22,type=N) %mp_setkeyvalue(someindex,22,type=N)
%mp_setkeyvalue(somenewindex,somevalue) %mp_setkeyvalue(somenewindex,somevalue)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_existds.sas @li mf_existds.sas
@param key Provide a key on which to perform the lookup @param key Provide a key on which to perform the lookup

View File

@@ -1,5 +1,5 @@
/** /**
@file mp_streamfile.sas @file
@brief Streams a file to _webout according to content type @brief Streams a file to _webout according to content type
@details Will set headers using appropriate functions (SAS 9 vs Viya) and send @details Will set headers using appropriate functions (SAS 9 vs Viya) and send
content as a binary stream. content as a binary stream.
@@ -11,12 +11,13 @@
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt) %mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getplatform.sas @li mf_getplatform.sas
@li mp_binarycopy.sas @li mp_binarycopy.sas
@param contenttype= Either TEXT, ZIP, CSV, EXCEL (default TEXT) @param contenttype= Either TEXT, ZIP, CSV, EXCEL (default TEXT)
@param inloc= /path/to/file.ext to be sent @param inloc= /path/to/file.ext to be sent
@param inref= fileref of file to be sent (if provided, overrides `inloc`)
@param outname= the name of the file, as downloaded by the browser @param outname= the name of the file, as downloaded by the browser
@author Allan Bowe @author Allan Bowe
@@ -27,6 +28,7 @@
%macro mp_streamfile( %macro mp_streamfile(
contenttype=TEXT contenttype=TEXT
,inloc= ,inloc=
,inref=0
,outname= ,outname=
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
@@ -110,6 +112,11 @@
%return; %return;
%end; %end;
%if &inref ne 0 %then %do;
%mp_binarycopy(inref=&inref,outref=_webout)
%end;
%else %do;
%mp_binarycopy(inloc="&inloc",outref=_webout) %mp_binarycopy(inloc="&inloc",outref=_webout)
%end;
%mend; %mend;

View File

@@ -0,0 +1,59 @@
/**
@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> SAS Macros </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;

68
base/mp_tree.sas Normal file
View File

@@ -0,0 +1,68 @@
/**
@file
@brief Recursively scans a directory tree to get all subfolders and content
@details
Usage:
%mp_tree(dir=/tmp, outds=work.tree)
Credits:
* Roger Deangelis, https://communities.sas.com/t5/SAS-Programming/listing-all-files-within-a-directory-and-subdirectories/m-p/332616/highlight/true#M74887
* Tom, https://communities.sas.com/t5/SAS-Programming/listing-all-files-of-all-types-from-all-subdirectories/m-p/334113/highlight/true#M75419
@param dir= Directory to be scanned (default=/tmp)
@param outds= Dataset to create (default=work.mp_tree)
@returns outds contains the following variables:
- `dir`: a flag (1/0) to say whether it is a directory or not. This is not
reliable - folders that you do not have permission to open will be flagged
as directories.
- `ext`: file extension
- `filename`: file name
- `dirname`: directory name
- `fullpath`: directory + file name
@version 9.2
**/
%macro mp_tree(dir=/tmp
,outds=work.mp_tree
)/*/STORE SOURCE*/;
data &outds ;
length dir 8 ext filename dirname $256 fullpath $512 ;
call missing(of _all_);
fullpath = "&dir";
run;
%local sep;
%if &sysscp=WIN or &SYSSCP eq DNTHOST %then %let sep=\;
%else %let sep=/;
data &outds ;
modify &outds ;
retain sep "&sep";
rc=filename('tmp',fullpath);
dir_id=dopen('tmp');
dir = (dir_id ne 0) ;
if dir then dirname=fullpath;
else do;
filename=scan(fullpath,-1,sep) ;
dirname =substrn(fullpath,1,length(fullpath)-length(filename));
if index(filename,'.')>1 then ext=scan(filename,-1,'.');
end;
replace;
if dir then do;
do i=1 to dnum(dir_id);
fullpath=cats(dirname,sep,dread(dir_id,i));
output;
end;
rc=dclose(dir_id);
end;
rc=filename('tmp');
run;
%mend;

View File

@@ -12,7 +12,7 @@
%mp_unzip(ziploc="/some/file.zip",outdir=/some/folder) %mp_unzip(ziploc="/some/file.zip",outdir=/some/folder)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_mkdir.sas @li mf_mkdir.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas

View File

@@ -18,7 +18,7 @@
@param var The variable to modify @param var The variable to modify
@param len The new length to apply @param len The new length to apply
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_existds.sas @li mf_existds.sas
@li mp_abort.sas @li mp_abort.sas
@li mf_existvar.sas @li mf_existvar.sas

View File

@@ -12,7 +12,7 @@
be sure that _debug is not set (else the SPWA will send non zipped content be sure that _debug is not set (else the SPWA will send non zipped content
as well). as well).
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mp_dirlist.sas @li mp_dirlist.sas
@param in= unquoted filepath, dataset of files or directory to zip @param in= unquoted filepath, dataset of files or directory to zip

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

@@ -16,7 +16,7 @@
<tab type="classmembers" visible="no" title="" intro=""/> <tab type="classmembers" visible="no" title="" intro=""/>
</tab> </tab>
<tab type="filelist" visible="yes" title="" intro="List of Files Used in the Macro Core Library"/> <tab type="filelist" visible="yes" title="" intro="List of Files Used in the Macro-Core Library"/>
<tab type="examples" visible="yes" title="" intro=""/> <tab type="examples" visible="yes" title="" intro=""/>
</navindex> </navindex>
@@ -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,8 +33,12 @@ 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
git add .
git commit -m "adding sitemap"
git push
echo "check it out: https://sasjs.github.io/core.github.io/files.html" echo "check it out: https://sasjs.github.io/core.github.io/files.html"

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

@@ -14,7 +14,7 @@
disconnect from MyAlias; disconnect from MyAlias;
quit; quit;
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getengine.sas @li mf_getengine.sas
@li mp_abort.sas @li mp_abort.sas

View File

@@ -10,7 +10,7 @@
%mm_assignlib(SOMEREF) %mm_assignlib(SOMEREF)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@param libref the libref (not name) of the metadata library @param libref the libref (not name) of the metadata library

View File

@@ -15,7 +15,7 @@
@warning application components do not get deleted when removing the container folder! be sure you have the administrative priviliges to remove this kind of metadata from the SMC plugin (or be ready to do to so programmatically). @warning application components do not get deleted when removing the container folder! be sure you have the administrative priviliges to remove this kind of metadata from the SMC plugin (or be ready to do to so programmatically).
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_verifymacvars.sas @li mf_verifymacvars.sas

View File

@@ -18,7 +18,7 @@
%mm_createdataset(tableuri=G5X8AFW1.BE00015Y) %mm_createdataset(tableuri=G5X8AFW1.BE00015Y)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mm_getlibs.sas @li mm_getlibs.sas
@li mm_gettables.sas @li mm_gettables.sas
@li mm_getcols.sas @li mm_getcols.sas

View File

@@ -12,7 +12,7 @@
%mm_createdocument(tree=/User Folders/sasdemo %mm_createdocument(tree=/User Folders/sasdemo
,name=MyNote) ,name=MyNote)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_verifymacvars.sas @li mf_verifymacvars.sas

View File

@@ -19,7 +19,7 @@
,directory=/tmp/tests ,directory=/tmp/tests
,mDebug=1) ,mDebug=1)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_verifymacvars.sas @li mf_verifymacvars.sas
@li mm_createfolder.sas @li mm_createfolder.sas

View File

@@ -39,7 +39,7 @@
,Server=SASApp ,Server=SASApp
,stptype=2) ,stptype=2)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_nobs.sas @li mf_nobs.sas
@li mf_verifymacvars.sas @li mf_verifymacvars.sas
@li mm_getdirectories.sas @li mm_getdirectories.sas

View File

@@ -24,7 +24,7 @@ Usage:
;;;; ;;;;
%mm_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001,replace=YES) %mm_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001,replace=YES)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mm_createstp.sas @li mm_createstp.sas
@li mf_getuser.sas @li mf_getuser.sas
@li mm_createfolder.sas @li mm_createfolder.sas

View File

@@ -8,7 +8,7 @@
%mm_createdocument(tree=/User Folders/&sysuserid,name=MyNote) %mm_createdocument(tree=/User Folders/&sysuserid,name=MyNote)
%mm_deletedocument(target=/User Folders/&sysuserid/MyNote) %mm_deletedocument(target=/User Folders/&sysuserid/MyNote)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@param target= full path to the document being deleted @param target= full path to the document being deleted

View File

@@ -7,7 +7,7 @@
%mm_deletestp(target=/some/meta/path/myStoredProcess) %mm_deletestp(target=/some/meta/path/myStoredProcess)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@param target= full path to the STP being deleted @param target= full path to the STP being deleted

View File

@@ -7,7 +7,7 @@
@param outds= the ONE LEVEL work dataset to create @param outds= the ONE LEVEL work dataset to create
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mm_getobjects.sas @li mm_getobjects.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mm_getdetails.sas @li mm_getdetails.sas

View File

@@ -11,7 +11,7 @@
,outref=/some/unquoted/filename.ext ,outref=/some/unquoted/filename.ext
) )
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@param tree= The metadata path of the document @param tree= The metadata path of the document
@@ -124,6 +124,7 @@ data _null_;
when ('&#x0a;') rec='0A'x; when ('&#x0a;') rec='0A'x;
when ('&#x0d;') rec='0D'x; when ('&#x0d;') rec='0D'x;
when ('&#36;' ) rec='$' ; when ('&#36;' ) rec='$' ;
when ('&#x09;') rec='09'x;
otherwise putlog "WARNING: missing value for " entity=; otherwise putlog "WARNING: missing value for " entity=;
end; end;
rc =fput(fileid, substr(rec,1,1)); rc =fput(fileid, substr(rec,1,1));

View File

@@ -14,7 +14,7 @@
@param outds= the dataset to create that contains the list of directories @param outds= the dataset to create that contains the list of directories
@param mDebug= set to 1 to show debug messages in the log @param mDebug= set to 1 to show debug messages in the log
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@version 9.4 @version 9.4
@author Allan Bowe @author Allan Bowe

View File

@@ -14,7 +14,7 @@
filename __mc2 clear; filename __mc2 clear;
libname __mc3 clear; libname __mc3 clear;
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mm_getrepos.sas @li mm_getrepos.sas
@version 9.3 @version 9.3

View File

@@ -123,6 +123,7 @@ data _null_;
when ('&#x0a;') rec='0A'x; when ('&#x0a;') rec='0A'x;
when ('&#x0d;') rec='0D'x; when ('&#x0d;') rec='0D'x;
when ('&#36;' ) rec='$' ; when ('&#36;' ) rec='$' ;
when ('&#x09;') rec='09'x;
otherwise putlog "%str(WARN)ING: missing value for " entity=; otherwise putlog "%str(WARN)ING: missing value for " entity=;
end; end;
rc =fput(fileid, substr(rec,1,1)); rc =fput(fileid, substr(rec,1,1));

View File

@@ -14,7 +14,7 @@
%mm_getstps(tree=/My Folder/My STPs, name=My STP) %mm_getstps(tree=/My Folder/My STPs, name=My STP)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mm_gettree.sas @li mm_gettree.sas
@param tree= the metadata folder location in which to search. Leave blank @param tree= the metadata folder location in which to search. Leave blank
@@ -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
**/ **/
@@ -99,6 +98,7 @@ run;
when ('&#x0a;') rec='0A'x; when ('&#x0a;') rec='0A'x;
when ('&#x0d;') rec='0D'x; when ('&#x0d;') rec='0D'x;
when ('&#36;' ) rec='$' ; when ('&#36;' ) rec='$' ;
when ('&#x09;') rec='09'x;
otherwise putlog "WARNING: missing value for " entity=; otherwise putlog "WARNING: missing value for " entity=;
end; end;
rc =fput(fileid, substr(rec,1,1)); rc =fput(fileid, substr(rec,1,1));

View File

@@ -45,7 +45,7 @@
./mmscript.sh "myuser" "mypass" ./mmscript.sh "myuser" "mypass"
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_loc.sas @li mf_loc.sas
@li mm_tree.sas @li mm_tree.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas

View File

@@ -46,7 +46,7 @@
Table Table
,outds=morestuff) ,outds=morestuff)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_getquotedstr.sas @li mf_getquotedstr.sas
@li mm_getpublictypes.sas @li mm_getpublictypes.sas
@li mf_isblank.sas @li mf_isblank.sas

View File

@@ -8,7 +8,7 @@
%mm_updatestpservertype(target=/some/meta/path/myStoredProcess %mm_updatestpservertype(target=/some/meta/path/myStoredProcess
,type=WKS) ,type=WKS)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@param target= full path to the STP being deleted @param target= full path to the STP being deleted
@param type= Either WKS or STP depending on whether Workspace or Stored Process @param type= Either WKS or STP depending on whether Workspace or Stored Process

View File

@@ -9,7 +9,7 @@
%mmx_deletemetafolder(loc=/some/meta/folder,user=sasdemo,pass=mars345) %mmx_deletemetafolder(loc=/some/meta/folder,user=sasdemo,pass=mars345)
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_loc.sas @li mf_loc.sas
@param loc= the metadata folder to delete @param loc= the metadata folder to delete

View File

@@ -25,7 +25,7 @@ Usage:
,outspkpath=%str(/tmp) ,outspkpath=%str(/tmp)
) )
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mf_loc.sas @li mf_loc.sas
@li mm_tree.sas @li mm_tree.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas

View File

@@ -15,10 +15,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas @li mf_getuniquelibref.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";
@@ -28,7 +29,7 @@
To minimise postgres requests, output json is stored in a temporary file To minimise postgres requests, output json is stored in a temporary file
and then sent to _webout in one go at the end. and then sent to _webout in one go at the end.
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mv_createfolder.sas @li mv_createfolder.sas
@li mf_getuniquelibref.sas @li mf_getuniquelibref.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
**/ **/
@@ -143,7 +143,7 @@ libname &libref1 JSON fileref=&fname1;
data _null_; data _null_;
set &libref1..links; set &libref1..links;
if rel='members' then call symputx('membercheck',quote(trim(href)),'l'); if rel='members' then call symputx('membercheck',quote("&base_uri"!!trim(href)),'l');
else if rel='self' then call symputx('parentFolderUri',href,'l'); else if rel='self' then call symputx('parentFolderUri',href,'l');
run; run;
data _null_; data _null_;
@@ -609,7 +609,7 @@ proc http method='POST'
in=&fname3 in=&fname3
out=&fname4 out=&fname4
&oauth_bearer &oauth_bearer
url="/jobDefinitions/definitions?parentFolderUri=&parentFolderUri"; url="&base_uri/jobDefinitions/definitions?parentFolderUri=&parentFolderUri";
headers 'Content-Type'='application/vnd.sas.job.definition+json' headers 'Content-Type'='application/vnd.sas.job.definition+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"

View File

@@ -20,10 +20,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@@ -98,7 +97,7 @@ run;
libname &libref1 JSON fileref=&fname1; libname &libref1 JSON fileref=&fname1;
data _null_; data _null_;
set &libref1..links; set &libref1..links;
if rel='members' then call symputx('mref',quote(trim(href)),'l'); if rel='members' then call symputx('mref',quote("&base_uri"!!trim(href)),'l');
run; run;
/* get the children */ /* get the children */
@@ -128,7 +127,7 @@ run;
%put NOTE:;%put NOTE- &sysmacroname: &path/&name NOT FOUND;%put NOTE- ; %put NOTE:;%put NOTE- &sysmacroname: &path/&name NOT FOUND;%put NOTE- ;
%return; %return;
%end; %end;
proc http method="DELETE" url="&uri" &oauth_bearer; proc http method="DELETE" url="&base_uri&uri" &oauth_bearer;
headers headers
%if &grant_type=authorization_code %then %do; %if &grant_type=authorization_code %then %do;
"Authorization"="Bearer &&&access_token_var" "Authorization"="Bearer &&&access_token_var"

View File

@@ -19,10 +19,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@@ -95,7 +94,7 @@ run;
libname &libref1 JSON fileref=&fname1; libname &libref1 JSON fileref=&fname1;
data _null_; data _null_;
set &libref1..links; set &libref1..links;
if rel='members' then call symputx('mref',quote(trim(href)),'l'); if rel='members' then call symputx('mref',quote("&base_uri"!!trim(href)),'l');
run; run;
/* get the children */ /* get the children */
@@ -117,7 +116,7 @@ libname &libref1a JSON fileref=&fname1a;
data _null_; data _null_;
set &libref1a..items; set &libref1a..items;
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then do; if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then do;
call symputx('uri',uri,'l'); call symputx('uri',cats("&base_uri",uri),'l');
call symputx('found',1,'l'); call symputx('found',1,'l');
end; end;
run; run;

View File

@@ -16,10 +16,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@@ -88,9 +87,9 @@ libname &libref1 JSON fileref=&fname1;
data _null_; data _null_;
set &libref1..links; set &libref1..links;
if rel='deleteRecursively' then if rel='deleteRecursively' then
call symputx('href',quote(trim(href)),'l'); call symputx('href',quote("&base_uri"!!trim(href)),'l');
else if rel='members' then else if rel='members' then
call symputx('mref',quote(cats(href,'?recursive=true')),'l'); call symputx('mref',quote(cats("&base_uri",href,'?recursive=true')),'l');
run; run;
/* before we can delete the folder, we need to delete the children */ /* before we can delete the folder, we need to delete the children */
@@ -111,7 +110,7 @@ data _null_;
set &libref1a..items_links; set &libref1a..items_links;
if href=:'/folders/folders' then return; if href=:'/folders/folders' then return;
if rel='deleteResource' then if rel='deleteResource' then
call execute('proc http method="DELETE" url='!!quote(trim(href)) call execute('proc http method="DELETE" url='!!quote("&base_uri"!!trim(href))
!!'; headers "Authorization"="Bearer &&&access_token_var" ' !!'; headers "Authorization"="Bearer &&&access_token_var" '
!!' "Accept"="*/*";run; /**/'); !!' "Accept"="*/*";run; /**/');
run; run;

View File

@@ -3,10 +3,9 @@
@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> SAS Macros </h4>
@li mv_tokenrefresh.sas @li mv_tokenrefresh.sas
**/ **/

View File

@@ -3,10 +3,9 @@
@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> SAS Macros </h4>
@li mv_registerclient.sas @li mv_registerclient.sas
**/ **/

View File

@@ -1,6 +1,6 @@
/** /**
@file mv_getgroups.sas @file mv_getclients.sas
@brief Creates a dataset with a list of viya groups @brief Get a list of Viya Clients
@details First, be sure you have an access token (which requires an app token). @details First, be sure you have an access token (which requires an app token).
Using the macros here: Using the macros here:
@@ -20,7 +20,7 @@
Now we can run the macro! Now we can run the macro!
%mv_getgroups() %mv_getclients()
@param access_token_var= The global macro variable to contain the access token @param access_token_var= The global macro variable to contain the access token
@param grant_type= valid values are "password" or "authorization_code" (unquoted). @param grant_type= valid values are "password" or "authorization_code" (unquoted).
@@ -29,10 +29,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas

View File

@@ -15,10 +15,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@@ -64,7 +63,7 @@ options noquotelenmax;
%if "&root"="/" %then %do; %if "&root"="/" %then %do;
/* if root just list root folders */ /* if root just list root folders */
proc http method='GET' out=&fname1 &oauth_bearer proc http method='GET' out=&fname1 &oauth_bearer
url='%sysfunc(getoption(servicesbaseurl))/folders/rootFolders'; url="&base_uri/folders/rootFolders";
%if &grant_type=authorization_code %then %do; %if &grant_type=authorization_code %then %do;
headers "Authorization"="Bearer &&&access_token_var"; headers "Authorization"="Bearer &&&access_token_var";
%end; %end;
@@ -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(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,10 +30,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas

View File

@@ -29,10 +29,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas

View File

@@ -3,10 +3,9 @@
@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> SAS Macros </h4>
@li mv_tokenauth.sas @li mv_tokenauth.sas
**/ **/

View File

@@ -1,24 +1,15 @@
/** /**
@file mv_getusergroups.sas @file mv_getusergroups.sas
@brief Creates a dataset with a list of groups for a particular user @brief Creates a dataset with a list of groups for a particular user
@details First, be sure you have an access token (which requires an app token). @details If using outside of Viya SPRE, then an access token is needed.
Using the macros here: Compile the macros here:
filename mc url filename mc url
"https://raw.githubusercontent.com/sasjs/core/main/all.sas"; "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc; %inc mc;
An administrator needs to set you up with an access code: Then run the macro!
%mv_registerclient(outds=client)
Navigate to the url from the log (opting in to the groups) and paste the
access code below:
%mv_tokenauth(inds=client,code=wKDZYTEPK6)
Now we can run the macro!
%mv_getusergroups(&sysuserid,outds=users) %mv_getusergroups(&sysuserid,outds=users)
@@ -29,10 +20,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas

View File

@@ -47,10 +47,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.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> SAS Macros </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,10 +52,9 @@
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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@@ -187,7 +186,7 @@ run;
%end; %end;
/* prepare url */ /* prepare url */
%if &grant_type=authorization_code %then %do; %if %index(%superq(grant_type),authorization_code) %then %do;
data _null_; data _null_;
if symexist('_baseurl') then do; if symexist('_baseurl') then do;
url=symget('_baseurl'); url=symget('_baseurl');
@@ -206,7 +205,7 @@ run;
%put CLIENT_SECRET=&client_secret; %put CLIENT_SECRET=&client_secret;
%put GRANT_TYPE=&grant_type; %put GRANT_TYPE=&grant_type;
%put; %put;
%if &grant_type=authorization_code %then %do; %if %index(%superq(grant_type),authorization_code) %then %do;
/* cannot use base_uri here as it includes the protocol which may be incorrect externally */ /* cannot use base_uri here as it includes the protocol which may be incorrect externally */
%put NOTE: The developer must also register below and select 'openid' to get the grant code:; %put NOTE: The developer must also register below and select 'openid' to get the grant code:;
%put NOTE- ; %put NOTE- ;

View File

@@ -38,12 +38,12 @@
@param pass= If grant_type=password then provide the password here @param pass= If grant_type=password then provide the password here
@param access_token_var= The global macro variable to contain the access token @param access_token_var= The global macro variable to contain the access token
@param refresh_token_var= The global macro variable to contain the refresh token @param refresh_token_var= The global macro variable to contain the refresh token
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@@ -62,6 +62,7 @@
,pass= ,pass=
,access_token_var=ACCESS_TOKEN ,access_token_var=ACCESS_TOKEN
,refresh_token_var=REFRESH_TOKEN ,refresh_token_var=REFRESH_TOKEN
,base_uri=#NOTSET#
); );
%global &access_token_var &refresh_token_var; %global &access_token_var &refresh_token_var;
@@ -108,8 +109,7 @@ run;
/** /**
* Request access token * Request access token
*/ */
%local base_uri; /* location of rest apis */ %if &base_uri=#NOTSET# %then %let base_uri=%mf_getplatform(VIYARESTAPI);
%let base_uri=%mf_getplatform(VIYARESTAPI);
%let fref2=%mf_getuniquefileref(); %let fref2=%mf_getuniquefileref();
proc http method='POST' in=&grantstring out=&fref2 proc http method='POST' in=&grantstring out=&fref2

View File

@@ -40,10 +40,9 @@
@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> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas

View File

@@ -27,12 +27,12 @@
@param dslabel= value to use instead of the real name for sending to JSON @param dslabel= value to use instead of the real name for sending to JSON
@param fmt= change to N to strip formats from output @param fmt= change to N to strip formats from output
<h4> Dependencies </h4> <h4> SAS Macros </h4>
@li mp_jsonout.sas @li mp_jsonout.sas
@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);