mirror of
https://github.com/sasjs/core.git
synced 2025-12-17 17:04:34 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f06e5540d | |||
| 6b782a4fa2 | |||
| efe4709dde | |||
| 5cb41041d9 | |||
| f50cb03fd3 | |||
| ac46489f11 | |||
|
|
5e45701e74 | ||
|
|
8caaacd9f0 | ||
|
|
91983e0a91 | ||
|
|
7b72f0ac94 | ||
|
|
3eae34d8b7 | ||
|
|
58358c916d | ||
|
|
578ef26cd5 |
196
all.sas
196
all.sas
@@ -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;
|
||||||
@@ -1475,6 +1487,12 @@ Usage:
|
|||||||
the particulars of an environment. For instance, can stream custom
|
the particulars of an environment. For instance, can stream custom
|
||||||
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
|
||||||
@@ -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 */
|
||||||
@@ -1932,17 +1957,17 @@ run;
|
|||||||
%mend;/**
|
%mend;/**
|
||||||
@file
|
@file
|
||||||
@brief Returns all files and subdirectories within a specified parent
|
@brief Returns all files and subdirectories within a specified parent
|
||||||
@details When used with getattrs=NO, is not OS specific (uses dopen / dread).
|
@details When used with getattrs=NO, is not OS specific (uses dopen / dread).
|
||||||
|
|
||||||
If getattrs=YES then the doptname / foptname functions are used to scan all
|
If getattrs=YES then the doptname / foptname functions are used to scan all
|
||||||
properties - any characters that are not valid in a SAS name (v7) are simply
|
properties - any characters that are not valid in a SAS name (v7) are simply
|
||||||
stripped, and the table is transposed so theat each property is a column
|
stripped, and the table is transposed so theat each property is a column
|
||||||
and there is one file per row. An attempt is made to get all properties
|
and there is one file per row. An attempt is made to get all properties
|
||||||
whether a file or folder, but some files/folders cannot be accessed, and so
|
whether a file or folder, but some files/folders cannot be accessed, and so
|
||||||
not all properties can / will be populated.
|
not all properties can / will be populated.
|
||||||
|
|
||||||
Credit for the rename approach:
|
Credit for the rename approach:
|
||||||
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
|
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
|
||||||
|
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
@@ -1951,21 +1976,25 @@ run;
|
|||||||
|
|
||||||
%mp_dirlist(outds=cwdfileprops, getattrs=YES)
|
%mp_dirlist(outds=cwdfileprops, getattrs=YES)
|
||||||
|
|
||||||
@warning In a Unix environment, the existence of a named pipe will cause this
|
%mp_dirlist(fref=MYFREF)
|
||||||
|
|
||||||
|
@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
|
||||||
are resubmitted.
|
are resubmitted.
|
||||||
If anyone finds a way to positively identify a named pipe using SAS (without
|
If anyone finds a way to positively identify a named pipe using SAS (without
|
||||||
X CMD) do please raise an issue!
|
X CMD) do please raise an issue!
|
||||||
|
|
||||||
|
|
||||||
@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;
|
||||||
rc = filename(fref, "&path");
|
%if &fref=0 %then %do;
|
||||||
|
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';
|
||||||
@@ -2013,12 +2050,12 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg);
|
|||||||
fmsg=sysmsg();
|
fmsg=sysmsg();
|
||||||
if midf > 0 then file_or_folder='file';
|
if midf > 0 then file_or_folder='file';
|
||||||
rc=fclose(midf);
|
rc=fclose(midf);
|
||||||
|
|
||||||
if index(fmsg,'File is in use') or index(dmsg,'is not a directory')
|
if index(fmsg,'File is in use') or index(dmsg,'is not a directory')
|
||||||
then file_or_folder='file';
|
then file_or_folder='file';
|
||||||
else if index(fmsg, 'Insufficient authorization') then file_or_folder='file';
|
else if index(fmsg, 'Insufficient authorization') then file_or_folder='file';
|
||||||
else if file_or_folder='' then file_or_folder='locked';
|
else if file_or_folder='' then file_or_folder='locked';
|
||||||
|
|
||||||
if file_or_folder='file' then do;
|
if file_or_folder='file' then do;
|
||||||
ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename);
|
ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename);
|
||||||
if filename = ext then ext = ' ';
|
if filename = ext then ext = ' ';
|
||||||
@@ -2051,7 +2088,7 @@ run;
|
|||||||
else do i=1 to foptnum(fid);
|
else do i=1 to foptnum(fid);
|
||||||
infoname=foptname(fid,i);
|
infoname=foptname(fid,i);
|
||||||
infoval=finfo(fid,infoname);
|
infoval=finfo(fid,infoname);
|
||||||
sasname=compress(infoname, '_', 'adik');
|
sasname=compress(infoname, '_', 'adik');
|
||||||
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
|
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
|
||||||
if upcase(sasname) ne 'FILENAME' then output;
|
if upcase(sasname) ne 'FILENAME' then output;
|
||||||
end;
|
end;
|
||||||
@@ -2068,7 +2105,7 @@ run;
|
|||||||
else do i=1 to doptnum(fid);
|
else do i=1 to doptnum(fid);
|
||||||
infoname=doptname(fid,i);
|
infoname=doptname(fid,i);
|
||||||
infoval=dinfo(fid,infoname);
|
infoval=dinfo(fid,infoname);
|
||||||
sasname=compress(infoname, '_', 'adik');
|
sasname=compress(infoname, '_', 'adik');
|
||||||
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
|
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
|
||||||
if upcase(sasname) ne 'FILENAME' then output;
|
if upcase(sasname) ne 'FILENAME' then output;
|
||||||
end;
|
end;
|
||||||
@@ -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=
|
||||||
@@ -2634,7 +2669,7 @@ run;
|
|||||||
file &fref mod;
|
file &fref mod;
|
||||||
put ');';
|
put ');';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
|
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
|
||||||
data _null_;
|
data _null_;
|
||||||
*length ds $128;
|
*length ds $128;
|
||||||
@@ -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;
|
||||||
@@ -2899,9 +2934,9 @@ create table &outds (rename=(
|
|||||||
@brief Guess the primary key of a table
|
@brief Guess the primary key of a table
|
||||||
@details Tries to guess the primary key of a table based on the following logic:
|
@details Tries to guess the primary key of a table based on the following logic:
|
||||||
|
|
||||||
* Columns with nulls are ignored
|
* Columns with nulls are ignored
|
||||||
* Return only column combinations that provide unique results
|
* Return only column combinations that provide unique results
|
||||||
* Start from one column, then move out to include composite keys of 2 to 6 columns
|
* Start from one column, then move out to include composite keys of 2 to 6 columns
|
||||||
|
|
||||||
The library of the target should be assigned before using this macro.
|
The library of the target should be assigned before using this macro.
|
||||||
|
|
||||||
@@ -2947,7 +2982,7 @@ create table &outds (rename=(
|
|||||||
/* get null count and row count */
|
/* get null count and row count */
|
||||||
%let tmpvar=%mf_getuniquename();
|
%let tmpvar=%mf_getuniquename();
|
||||||
proc sql noprint;
|
proc sql noprint;
|
||||||
create table _data_ as select
|
create table _data_ as select
|
||||||
count(*) as &tmpvar
|
count(*) as &tmpvar
|
||||||
%do i=1 %to &vcnt;
|
%do i=1 %to &vcnt;
|
||||||
%let var=%scan(&vars,&i);
|
%let var=%scan(&vars,&i);
|
||||||
@@ -2981,10 +3016,10 @@ create table &outds (rename=(
|
|||||||
%put &sysmacroname: &baseds has no combination of unique records! Exiting.;
|
%put &sysmacroname: &baseds has no combination of unique records! Exiting.;
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
/* now check cardinality */
|
/* now check cardinality */
|
||||||
proc sql noprint;
|
proc sql noprint;
|
||||||
create table _data_ as select
|
create table _data_ as select
|
||||||
%do i=1 %to &ppkcnt;
|
%do i=1 %to &ppkcnt;
|
||||||
%let var=%scan(&posspks,&i);
|
%let var=%scan(&posspks,&i);
|
||||||
count(distinct &var) as &var
|
count(distinct &var) as &var
|
||||||
@@ -3108,7 +3143,7 @@ create table &outds (rename=(
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &ppkcnt=4 %then %do;
|
%if &ppkcnt=4 %then %do;
|
||||||
%put &sysmacroname: No more PK guess possible;
|
%put &sysmacroname: No more PK guess possible;
|
||||||
%return;
|
%return;
|
||||||
@@ -3124,7 +3159,7 @@ create table &outds (rename=(
|
|||||||
%let lev3=%scan(&posspks,&k);
|
%let lev3=%scan(&posspks,&k);
|
||||||
%if &lev1 ne &lev3 and &lev2 ne &lev3 %then %do l=4 %to &ppkcnt;
|
%if &lev1 ne &lev3 and &lev2 ne &lev3 %then %do l=4 %to &ppkcnt;
|
||||||
%let lev4=%scan(&posspks,&l);
|
%let lev4=%scan(&posspks,&l);
|
||||||
%if &lev1 ne &lev4 and &lev2 ne &lev4 and &lev3 ne &lev4 %then
|
%if &lev1 ne &lev4 and &lev2 ne &lev4 and &lev3 ne &lev4 %then
|
||||||
%do m=5 %to &ppkcnt;
|
%do m=5 %to &ppkcnt;
|
||||||
%let lev5=%scan(&posspks,&m);
|
%let lev5=%scan(&posspks,&m);
|
||||||
%if &lev1 ne &lev5 & &lev2 ne &lev5 & &lev3 ne &lev5 & &lev4 ne &lev5 %then %do;
|
%if &lev1 ne &lev5 & &lev2 ne &lev5 & &lev3 ne &lev5 & &lev4 ne &lev5 %then %do;
|
||||||
@@ -3146,7 +3181,7 @@ create table &outds (rename=(
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &ppkcnt=5 %then %do;
|
%if &ppkcnt=5 %then %do;
|
||||||
%put &sysmacroname: No more PK guess possible;
|
%put &sysmacroname: No more PK guess possible;
|
||||||
%return;
|
%return;
|
||||||
@@ -3162,17 +3197,17 @@ create table &outds (rename=(
|
|||||||
%let lev3=%scan(&posspks,&k);
|
%let lev3=%scan(&posspks,&k);
|
||||||
%if &lev1 ne &lev3 and &lev2 ne &lev3 %then %do l=4 %to &ppkcnt;
|
%if &lev1 ne &lev3 and &lev2 ne &lev3 %then %do l=4 %to &ppkcnt;
|
||||||
%let lev4=%scan(&posspks,&l);
|
%let lev4=%scan(&posspks,&l);
|
||||||
%if &lev1 ne &lev4 and &lev2 ne &lev4 and &lev3 ne &lev4 %then
|
%if &lev1 ne &lev4 and &lev2 ne &lev4 and &lev3 ne &lev4 %then
|
||||||
%do m=5 %to &ppkcnt;
|
%do m=5 %to &ppkcnt;
|
||||||
%let lev5=%scan(&posspks,&m);
|
%let lev5=%scan(&posspks,&m);
|
||||||
%if &lev1 ne &lev5 & &lev2 ne &lev5 & &lev3 ne &lev5 & &lev4 ne &lev5 %then
|
%if &lev1 ne &lev5 & &lev2 ne &lev5 & &lev3 ne &lev5 & &lev4 ne &lev5 %then
|
||||||
%do n=6 %to &ppkcnt;
|
%do n=6 %to &ppkcnt;
|
||||||
%let lev6=%scan(&posspks,&n);
|
%let lev6=%scan(&posspks,&n);
|
||||||
%if &lev1 ne &lev6 & &lev2 ne &lev6 & &lev3 ne &lev6
|
%if &lev1 ne &lev6 & &lev2 ne &lev6 & &lev3 ne &lev6
|
||||||
& &lev4 ne &lev6 & &lev5 ne &lev6 %then
|
& &lev4 ne &lev6 & &lev5 ne &lev6 %then
|
||||||
%do;
|
%do;
|
||||||
/* check for four level uniqueness */
|
/* check for four level uniqueness */
|
||||||
proc sort data=&pkds(keep=&lev1 &lev2 &lev3 &lev4 &lev5 &lev6)
|
proc sort data=&pkds(keep=&lev1 &lev2 &lev3 &lev4 &lev5 &lev6)
|
||||||
out=&tmpds noduprec;
|
out=&tmpds noduprec;
|
||||||
by _all_;
|
by _all_;
|
||||||
run;
|
run;
|
||||||
@@ -3191,7 +3226,7 @@ create table &outds (rename=(
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &ppkcnt=6 %then %do;
|
%if &ppkcnt=6 %then %do;
|
||||||
%put &sysmacroname: No more PK guess possible;
|
%put &sysmacroname: No more PK guess possible;
|
||||||
%return;
|
%return;
|
||||||
@@ -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 ('
') rec='0A'x;
|
when ('
') rec='0A'x;
|
||||||
when ('
') rec='0D'x;
|
when ('
') rec='0D'x;
|
||||||
when ('$' ) rec='$' ;
|
when ('$' ) rec='$' ;
|
||||||
|
when ('	') 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 ('
') rec='0A'x;
|
when ('
') rec='0A'x;
|
||||||
when ('
') rec='0D'x;
|
when ('
') rec='0D'x;
|
||||||
when ('$' ) rec='$' ;
|
when ('$' ) rec='$' ;
|
||||||
|
when ('	') 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 ('
') rec='0A'x;
|
when ('
') rec='0A'x;
|
||||||
when ('
') rec='0D'x;
|
when ('
') rec='0D'x;
|
||||||
when ('$' ) rec='$' ;
|
when ('$' ) rec='$' ;
|
||||||
|
when ('	') 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)
|
||||||
|
|
||||||
@@ -11497,7 +11536,7 @@ libname &libref1 clear;
|
|||||||
%let &access_token_var=;
|
%let &access_token_var=;
|
||||||
%end;
|
%end;
|
||||||
%put &sysmacroname: grant_type=&grant_type;
|
%put &sysmacroname: grant_type=&grant_type;
|
||||||
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
|
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
|
||||||
and &grant_type ne sas_services
|
and &grant_type ne sas_services
|
||||||
)
|
)
|
||||||
,mac=&sysmacroname
|
,mac=&sysmacroname
|
||||||
@@ -11515,7 +11554,7 @@ options noquotelenmax;
|
|||||||
|
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri/identities/users/&user/memberships?limit=10000";
|
url="&base_uri/identities/users/&user/memberships?limit=10000";
|
||||||
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"
|
||||||
%end;
|
%end;
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -5,6 +5,12 @@
|
|||||||
the particulars of an environment. For instance, can stream custom
|
the particulars of an environment. For instance, can stream custom
|
||||||
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
|
||||||
@@ -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 */
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Returns all files and subdirectories within a specified parent
|
@brief Returns all files and subdirectories within a specified parent
|
||||||
@details When used with getattrs=NO, is not OS specific (uses dopen / dread).
|
@details When used with getattrs=NO, is not OS specific (uses dopen / dread).
|
||||||
|
|
||||||
If getattrs=YES then the doptname / foptname functions are used to scan all
|
If getattrs=YES then the doptname / foptname functions are used to scan all
|
||||||
properties - any characters that are not valid in a SAS name (v7) are simply
|
properties - any characters that are not valid in a SAS name (v7) are simply
|
||||||
stripped, and the table is transposed so theat each property is a column
|
stripped, and the table is transposed so theat each property is a column
|
||||||
and there is one file per row. An attempt is made to get all properties
|
and there is one file per row. An attempt is made to get all properties
|
||||||
whether a file or folder, but some files/folders cannot be accessed, and so
|
whether a file or folder, but some files/folders cannot be accessed, and so
|
||||||
not all properties can / will be populated.
|
not all properties can / will be populated.
|
||||||
|
|
||||||
Credit for the rename approach:
|
Credit for the rename approach:
|
||||||
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
|
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
|
||||||
|
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
@@ -20,21 +20,25 @@
|
|||||||
|
|
||||||
%mp_dirlist(outds=cwdfileprops, getattrs=YES)
|
%mp_dirlist(outds=cwdfileprops, getattrs=YES)
|
||||||
|
|
||||||
@warning In a Unix environment, the existence of a named pipe will cause this
|
%mp_dirlist(fref=MYFREF)
|
||||||
|
|
||||||
|
@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
|
||||||
are resubmitted.
|
are resubmitted.
|
||||||
If anyone finds a way to positively identify a named pipe using SAS (without
|
If anyone finds a way to positively identify a named pipe using SAS (without
|
||||||
X CMD) do please raise an issue!
|
X CMD) do please raise an issue!
|
||||||
|
|
||||||
|
|
||||||
@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;
|
||||||
rc = filename(fref, "&path");
|
%if &fref=0 %then %do;
|
||||||
|
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';
|
||||||
@@ -82,12 +94,12 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg);
|
|||||||
fmsg=sysmsg();
|
fmsg=sysmsg();
|
||||||
if midf > 0 then file_or_folder='file';
|
if midf > 0 then file_or_folder='file';
|
||||||
rc=fclose(midf);
|
rc=fclose(midf);
|
||||||
|
|
||||||
if index(fmsg,'File is in use') or index(dmsg,'is not a directory')
|
if index(fmsg,'File is in use') or index(dmsg,'is not a directory')
|
||||||
then file_or_folder='file';
|
then file_or_folder='file';
|
||||||
else if index(fmsg, 'Insufficient authorization') then file_or_folder='file';
|
else if index(fmsg, 'Insufficient authorization') then file_or_folder='file';
|
||||||
else if file_or_folder='' then file_or_folder='locked';
|
else if file_or_folder='' then file_or_folder='locked';
|
||||||
|
|
||||||
if file_or_folder='file' then do;
|
if file_or_folder='file' then do;
|
||||||
ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename);
|
ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename);
|
||||||
if filename = ext then ext = ' ';
|
if filename = ext then ext = ' ';
|
||||||
@@ -120,7 +132,7 @@ run;
|
|||||||
else do i=1 to foptnum(fid);
|
else do i=1 to foptnum(fid);
|
||||||
infoname=foptname(fid,i);
|
infoname=foptname(fid,i);
|
||||||
infoval=finfo(fid,infoname);
|
infoval=finfo(fid,infoname);
|
||||||
sasname=compress(infoname, '_', 'adik');
|
sasname=compress(infoname, '_', 'adik');
|
||||||
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
|
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
|
||||||
if upcase(sasname) ne 'FILENAME' then output;
|
if upcase(sasname) ne 'FILENAME' then output;
|
||||||
end;
|
end;
|
||||||
@@ -137,7 +149,7 @@ run;
|
|||||||
else do i=1 to doptnum(fid);
|
else do i=1 to doptnum(fid);
|
||||||
infoname=doptname(fid,i);
|
infoname=doptname(fid,i);
|
||||||
infoval=dinfo(fid,infoname);
|
infoval=dinfo(fid,infoname);
|
||||||
sasname=compress(infoname, '_', 'adik');
|
sasname=compress(infoname, '_', 'adik');
|
||||||
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
|
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
|
||||||
if upcase(sasname) ne 'FILENAME' then output;
|
if upcase(sasname) ne 'FILENAME' then output;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -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))"
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ run;
|
|||||||
file &fref mod;
|
file &fref mod;
|
||||||
put ');';
|
put ');';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
|
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
|
||||||
data _null_;
|
data _null_;
|
||||||
*length ds $128;
|
*length ds $128;
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
@brief Guess the primary key of a table
|
@brief Guess the primary key of a table
|
||||||
@details Tries to guess the primary key of a table based on the following logic:
|
@details Tries to guess the primary key of a table based on the following logic:
|
||||||
|
|
||||||
* Columns with nulls are ignored
|
* Columns with nulls are ignored
|
||||||
* Return only column combinations that provide unique results
|
* Return only column combinations that provide unique results
|
||||||
* Start from one column, then move out to include composite keys of 2 to 6 columns
|
* Start from one column, then move out to include composite keys of 2 to 6 columns
|
||||||
|
|
||||||
The library of the target should be assigned before using this macro.
|
The library of the target should be assigned before using this macro.
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
/* get null count and row count */
|
/* get null count and row count */
|
||||||
%let tmpvar=%mf_getuniquename();
|
%let tmpvar=%mf_getuniquename();
|
||||||
proc sql noprint;
|
proc sql noprint;
|
||||||
create table _data_ as select
|
create table _data_ as select
|
||||||
count(*) as &tmpvar
|
count(*) as &tmpvar
|
||||||
%do i=1 %to &vcnt;
|
%do i=1 %to &vcnt;
|
||||||
%let var=%scan(&vars,&i);
|
%let var=%scan(&vars,&i);
|
||||||
@@ -85,10 +85,10 @@
|
|||||||
%put &sysmacroname: &baseds has no combination of unique records! Exiting.;
|
%put &sysmacroname: &baseds has no combination of unique records! Exiting.;
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
/* now check cardinality */
|
/* now check cardinality */
|
||||||
proc sql noprint;
|
proc sql noprint;
|
||||||
create table _data_ as select
|
create table _data_ as select
|
||||||
%do i=1 %to &ppkcnt;
|
%do i=1 %to &ppkcnt;
|
||||||
%let var=%scan(&posspks,&i);
|
%let var=%scan(&posspks,&i);
|
||||||
count(distinct &var) as &var
|
count(distinct &var) as &var
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &ppkcnt=4 %then %do;
|
%if &ppkcnt=4 %then %do;
|
||||||
%put &sysmacroname: No more PK guess possible;
|
%put &sysmacroname: No more PK guess possible;
|
||||||
%return;
|
%return;
|
||||||
@@ -228,7 +228,7 @@
|
|||||||
%let lev3=%scan(&posspks,&k);
|
%let lev3=%scan(&posspks,&k);
|
||||||
%if &lev1 ne &lev3 and &lev2 ne &lev3 %then %do l=4 %to &ppkcnt;
|
%if &lev1 ne &lev3 and &lev2 ne &lev3 %then %do l=4 %to &ppkcnt;
|
||||||
%let lev4=%scan(&posspks,&l);
|
%let lev4=%scan(&posspks,&l);
|
||||||
%if &lev1 ne &lev4 and &lev2 ne &lev4 and &lev3 ne &lev4 %then
|
%if &lev1 ne &lev4 and &lev2 ne &lev4 and &lev3 ne &lev4 %then
|
||||||
%do m=5 %to &ppkcnt;
|
%do m=5 %to &ppkcnt;
|
||||||
%let lev5=%scan(&posspks,&m);
|
%let lev5=%scan(&posspks,&m);
|
||||||
%if &lev1 ne &lev5 & &lev2 ne &lev5 & &lev3 ne &lev5 & &lev4 ne &lev5 %then %do;
|
%if &lev1 ne &lev5 & &lev2 ne &lev5 & &lev3 ne &lev5 & &lev4 ne &lev5 %then %do;
|
||||||
@@ -250,7 +250,7 @@
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &ppkcnt=5 %then %do;
|
%if &ppkcnt=5 %then %do;
|
||||||
%put &sysmacroname: No more PK guess possible;
|
%put &sysmacroname: No more PK guess possible;
|
||||||
%return;
|
%return;
|
||||||
@@ -266,17 +266,17 @@
|
|||||||
%let lev3=%scan(&posspks,&k);
|
%let lev3=%scan(&posspks,&k);
|
||||||
%if &lev1 ne &lev3 and &lev2 ne &lev3 %then %do l=4 %to &ppkcnt;
|
%if &lev1 ne &lev3 and &lev2 ne &lev3 %then %do l=4 %to &ppkcnt;
|
||||||
%let lev4=%scan(&posspks,&l);
|
%let lev4=%scan(&posspks,&l);
|
||||||
%if &lev1 ne &lev4 and &lev2 ne &lev4 and &lev3 ne &lev4 %then
|
%if &lev1 ne &lev4 and &lev2 ne &lev4 and &lev3 ne &lev4 %then
|
||||||
%do m=5 %to &ppkcnt;
|
%do m=5 %to &ppkcnt;
|
||||||
%let lev5=%scan(&posspks,&m);
|
%let lev5=%scan(&posspks,&m);
|
||||||
%if &lev1 ne &lev5 & &lev2 ne &lev5 & &lev3 ne &lev5 & &lev4 ne &lev5 %then
|
%if &lev1 ne &lev5 & &lev2 ne &lev5 & &lev3 ne &lev5 & &lev4 ne &lev5 %then
|
||||||
%do n=6 %to &ppkcnt;
|
%do n=6 %to &ppkcnt;
|
||||||
%let lev6=%scan(&posspks,&n);
|
%let lev6=%scan(&posspks,&n);
|
||||||
%if &lev1 ne &lev6 & &lev2 ne &lev6 & &lev3 ne &lev6
|
%if &lev1 ne &lev6 & &lev2 ne &lev6 & &lev3 ne &lev6
|
||||||
& &lev4 ne &lev6 & &lev5 ne &lev6 %then
|
& &lev4 ne &lev6 & &lev5 ne &lev6 %then
|
||||||
%do;
|
%do;
|
||||||
/* check for four level uniqueness */
|
/* check for four level uniqueness */
|
||||||
proc sort data=&pkds(keep=&lev1 &lev2 &lev3 &lev4 &lev5 &lev6)
|
proc sort data=&pkds(keep=&lev1 &lev2 &lev3 &lev4 &lev5 &lev6)
|
||||||
out=&tmpds noduprec;
|
out=&tmpds noduprec;
|
||||||
by _all_;
|
by _all_;
|
||||||
run;
|
run;
|
||||||
@@ -295,7 +295,7 @@
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &ppkcnt=6 %then %do;
|
%if &ppkcnt=6 %then %do;
|
||||||
%put &sysmacroname: No more PK guess possible;
|
%put &sysmacroname: No more PK guess possible;
|
||||||
%return;
|
%return;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ data _null_;
|
|||||||
when ('
') rec='0A'x;
|
when ('
') rec='0A'x;
|
||||||
when ('
') rec='0D'x;
|
when ('
') rec='0D'x;
|
||||||
when ('$' ) rec='$' ;
|
when ('$' ) rec='$' ;
|
||||||
|
when ('	') 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));
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ data _null_;
|
|||||||
when ('
') rec='0A'x;
|
when ('
') rec='0A'x;
|
||||||
when ('
') rec='0D'x;
|
when ('
') rec='0D'x;
|
||||||
when ('$' ) rec='$' ;
|
when ('$' ) rec='$' ;
|
||||||
|
when ('	') 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));
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ run;
|
|||||||
when ('
') rec='0A'x;
|
when ('
') rec='0A'x;
|
||||||
when ('
') rec='0D'x;
|
when ('
') rec='0D'x;
|
||||||
when ('$' ) rec='$' ;
|
when ('$' ) rec='$' ;
|
||||||
|
when ('	') 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));
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
@@ -55,7 +46,7 @@
|
|||||||
%let &access_token_var=;
|
%let &access_token_var=;
|
||||||
%end;
|
%end;
|
||||||
%put &sysmacroname: grant_type=&grant_type;
|
%put &sysmacroname: grant_type=&grant_type;
|
||||||
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
|
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
|
||||||
and &grant_type ne sas_services
|
and &grant_type ne sas_services
|
||||||
)
|
)
|
||||||
,mac=&sysmacroname
|
,mac=&sysmacroname
|
||||||
@@ -73,7 +64,7 @@ options noquotelenmax;
|
|||||||
|
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri/identities/users/&user/memberships?limit=10000";
|
url="&base_uri/identities/users/&user/memberships?limit=10000";
|
||||||
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"
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
@@ -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- ;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user