1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-18 01:04:35 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
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
20 changed files with 235 additions and 152 deletions

132
all.sas
View File

@@ -380,7 +380,7 @@ options noquotelenmax;
@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
@@ -398,9 +398,10 @@ options noquotelenmax;
@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;
@@ -419,7 +420,8 @@ 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:
@@ -1316,13 +1318,23 @@ Usage:
**/ **/
%macro mf_trimstr(basestr,trimstr); %macro mf_trimstr(basestr,trimstr);
%local trimlen trimval; %local baselen trimlen trimval;
/* return if basestr is shorter than trimstr (or 0) */
%let baselen=%length(%superq(basestr));
%let trimlen=%length(%superq(trimstr)); %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) %let trimval=%qsubstr(%superq(basestr)
,%length(%superq(basestr))-&trimlen+1 ,%length(%superq(basestr))-&trimlen+1
,&trimlen); ,&trimlen);
%if %superq(trimval)=%superq(trimstr) %then %do; /* 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) %qsubstr(%superq(basestr),1,%length(%superq(basestr))-&trimlen)
%end; %end;
%else %do; %else %do;
@@ -1476,6 +1488,12 @@ Usage:
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.
@@ -1535,8 +1553,15 @@ Usage:
%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 */
@@ -1951,6 +1976,8 @@ run;
%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
@@ -1960,12 +1987,14 @@ run;
@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)
@@ -1978,18 +2007,26 @@ run;
**/ **/
%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;
@@ -2004,7 +2041,7 @@ 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); rc = filename(fref2, cats(directory,'/',filename));
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';
@@ -2274,8 +2311,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))"
@@ -2505,7 +2541,6 @@ create table &outds as
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=
@@ -2814,7 +2849,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;
@@ -3697,7 +3732,7 @@ proc sort; by descending sumcols memname libname; run;
@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.
@@ -3738,9 +3773,13 @@ proc sort; by descending sumcols memname libname; run;
,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;
@@ -3772,6 +3811,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
@@ -3782,14 +3822,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;
@@ -7082,6 +7127,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));
@@ -7996,6 +8042,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));
@@ -8630,6 +8677,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));
@@ -10594,7 +10642,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 */
@@ -10624,7 +10672,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"
@@ -10883,9 +10931,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 */
@@ -10906,7 +10954,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;
@@ -10991,8 +11039,8 @@ libname &libref1 clear;
) )
%mend;/** %mend;/**
@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:
@@ -11012,7 +11060,7 @@ libname &libref1 clear;
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).
@@ -11157,7 +11205,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;
@@ -11180,7 +11228,7 @@ options noquotelenmax;
/* now get the followon link to list members */ /* now get the followon link to list members */
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;
%local fname2 libref2; %local fname2 libref2;
%let fname2=%mf_getuniquefileref(); %let fname2=%mf_getuniquefileref();
@@ -11443,24 +11491,15 @@ libname &libref1 clear;
%mend;/** %mend;/**
@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)
@@ -11846,7 +11885,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');
@@ -11865,7 +11904,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- ;
@@ -11932,6 +11971,7 @@ libname &libref clear;
@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
@@ -11956,6 +11996,7 @@ libname &libref clear;
,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;
@@ -12002,8 +12043,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

@@ -23,13 +23,23 @@
**/ **/
%macro mf_trimstr(basestr,trimstr); %macro mf_trimstr(basestr,trimstr);
%local trimlen trimval; %local baselen trimlen trimval;
/* return if basestr is shorter than trimstr (or 0) */
%let baselen=%length(%superq(basestr));
%let trimlen=%length(%superq(trimstr)); %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) %let trimval=%qsubstr(%superq(basestr)
,%length(%superq(basestr))-&trimlen+1 ,%length(%superq(basestr))-&trimlen+1
,&trimlen); ,&trimlen);
%if %superq(trimval)=%superq(trimstr) %then %do; /* 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) %qsubstr(%superq(basestr),1,%length(%superq(basestr))-&trimlen)
%end; %end;
%else %do; %else %do;

View File

@@ -6,6 +6,12 @@
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.
@@ -65,8 +71,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 */

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,7 @@ 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); rc = filename(fref2, cats(directory,'/',filename));
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';

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))"

View File

@@ -339,7 +339,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

@@ -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.
@@ -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

@@ -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>

View File

@@ -36,5 +36,9 @@ 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

@@ -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

@@ -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

@@ -99,6 +99,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

@@ -98,7 +98,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 +128,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

@@ -88,9 +88,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 +111,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

@@ -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).

View File

@@ -64,7 +64,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;
@@ -87,7 +87,7 @@ options noquotelenmax;
/* now get the followon link to list members */ /* now get the followon link to list members */
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;
%local fname2 libref2; %local fname2 libref2;
%let fname2=%mf_getuniquefileref(); %let fname2=%mf_getuniquefileref();

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)

View File

@@ -187,7 +187,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 +206,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,6 +38,7 @@
@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
@@ -62,6 +63,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 +110,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