mirror of
https://github.com/sasjs/core.git
synced 2026-01-05 00:20:05 +00:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f369f9848 | ||
|
|
2372ff5f4f | ||
|
|
6d0e34ba1d | ||
|
|
7a69698178 | ||
|
|
532bf84e06 | ||
|
|
e1afbc02c4 | ||
|
|
756f00d88d | ||
|
|
b72e404d52 | ||
|
|
e31cdeef42 | ||
|
|
8a4e32cc27 | ||
|
|
f285505b79 | ||
|
|
67f5c50300 | ||
|
|
ce39e4f779 | ||
|
|
9c80f5664c | ||
|
|
83466c001b | ||
|
|
ad315be503 | ||
|
|
c41ae2dcc8 | ||
| d9f8e92fac | |||
|
|
d42ede15db | ||
|
|
08ea9f7c00 | ||
|
|
c327e1fc0d | ||
|
|
02fddcf9a1 | ||
|
|
4752bfbb05 | ||
|
|
767ddd7add | ||
|
|
54a24ced83 | ||
|
|
57ae2981f1 | ||
|
|
a3043ac685 | ||
|
|
2bdb90b0be | ||
|
|
2cd846d504 | ||
|
|
f593c7bec9 | ||
|
|
c8805db0b5 | ||
|
|
1eb6d8cec9 | ||
|
|
ed19ee03af | ||
|
|
a1c931b5e6 | ||
|
|
cb553a31ab | ||
|
|
557df272ff | ||
|
|
0cb3c96c15 | ||
|
|
1cb39d4d61 | ||
|
|
934b7d4f8a | ||
|
|
24c50cde56 |
17
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
17
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
## Issue
|
||||||
|
|
||||||
|
Link any related issue(s) in this section.
|
||||||
|
|
||||||
|
## Intent
|
||||||
|
|
||||||
|
What this PR intends to achieve.
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
What code changes have been made to achieve the intent.
|
||||||
|
|
||||||
|
## Checks
|
||||||
|
|
||||||
|
- [ ] Code is formatted correctly (`sasjs lint`).
|
||||||
|
- [ ] Any new functionality has been unit tested.
|
||||||
|
- [ ] All unit tests are passing (`sasjs test`).
|
||||||
@@ -6,9 +6,6 @@
|
|||||||
|
|
||||||
%put %mf_existVarList(sashelp.class, age sex name dummyvar);
|
%put %mf_existVarList(sashelp.class, age sex name dummyvar);
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mf_abort.sas
|
|
||||||
|
|
||||||
@param libds 2 part dataset or view reference
|
@param libds 2 part dataset or view reference
|
||||||
@param varlist space separated variable names
|
@param varlist space separated variable names
|
||||||
|
|
||||||
|
|||||||
@@ -23,18 +23,19 @@
|
|||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_getuser(type=META
|
%macro mf_getuser(
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local user metavar;
|
%local user;
|
||||||
%if &type=OS %then %let metavar=_secureusername;
|
|
||||||
%else %let metavar=_metaperson;
|
|
||||||
|
|
||||||
%if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER;
|
%if %symexist(_sasjs_username) %then %let user=&_sasjs_username;
|
||||||
%else %if %symexist(&metavar) %then %do;
|
%else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do;
|
||||||
%if %length(&&&metavar)=0 %then %let user=&sysuserid;
|
%let user=&SYS_COMPUTE_SESSION_OWNER;
|
||||||
|
%end;
|
||||||
|
%else %if %symexist(_metaperson) %then %do;
|
||||||
|
%if %length(&_metaperson)=0 %then %let user=&sysuserid;
|
||||||
/* sometimes SAS will add @domain extension - remove for consistency */
|
/* sometimes SAS will add @domain extension - remove for consistency */
|
||||||
/* but be sure to quote in case of usernames with commas */
|
/* but be sure to quote in case of usernames with commas */
|
||||||
%else %let user=%unquote(%scan(%quote(&&&metavar),1,@));
|
%else %let user=%unquote(%scan(%quote(&_metaperson),1,@));
|
||||||
%end;
|
%end;
|
||||||
%else %let user=&sysuserid;
|
%else %let user=&sysuserid;
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
, mode=REGULAR
|
, mode=REGULAR
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%global sysprocessmode sysprocessname sasjs_stpsrv_header_loc;
|
%global sysprocessmode sysprocessname sasjs_stpsrv_header_loc sasjsprocessmode;
|
||||||
%local fref fid i;
|
%local fref fid i;
|
||||||
|
|
||||||
%if not(%eval(%unquote(&iftrue))) %then %return;
|
%if not(%eval(%unquote(&iftrue))) %then %return;
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
%if %symexist(_SYSINCLUDEFILEDEVICE)
|
%if %symexist(_SYSINCLUDEFILEDEVICE)
|
||||||
/* abort cancel FILE does not restart outside the INCLUDE on Viya 3.5 */
|
/* abort cancel FILE does not restart outside the INCLUDE on Viya 3.5 */
|
||||||
and "&SYSPROCESSNAME " ne "Compute Server "
|
and %superq(SYSPROCESSNAME) ne %str(Compute Server)
|
||||||
%then %do;
|
%then %do;
|
||||||
%if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do;
|
%if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do;
|
||||||
data &errds;
|
data &errds;
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
|
|
||||||
/* Web App Context */
|
/* Web App Context */
|
||||||
%if %symexist(_PROGRAM)
|
%if %symexist(_PROGRAM)
|
||||||
or "&SYSPROCESSNAME "="Compute Server "
|
or %superq(SYSPROCESSNAME) = %str(Compute Server)
|
||||||
or &mode=INCLUDE
|
or &mode=INCLUDE
|
||||||
%then %do;
|
%then %do;
|
||||||
options obs=max replace mprint;
|
options obs=max replace mprint;
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
|
|
||||||
%if %symexist(SYS_JES_JOB_URI) %then %do;
|
%if %symexist(SYS_JES_JOB_URI) %then %do;
|
||||||
/* setup webout for Viya */
|
/* setup webout for Viya */
|
||||||
OPTIONS NOBOMFILE;
|
options nobomfile;
|
||||||
%if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
|
%if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
|
||||||
filename _webout temp lrecl=999999 mod;
|
filename _webout temp lrecl=999999 mod;
|
||||||
%end;
|
%end;
|
||||||
@@ -169,6 +169,7 @@
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc))=0 %then %do;
|
%else %if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc))=0 %then %do;
|
||||||
|
options nobomfile;
|
||||||
/* set up http header for SASjs Server */
|
/* set up http header for SASjs Server */
|
||||||
%let fid=%sysfunc(fopen(&fref,A));
|
%let fid=%sysfunc(fopen(&fref,A));
|
||||||
%if &fid=0 %then %do;
|
%if &fid=0 %then %do;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
@details Reads in a file byte by byte and writes it back out. Is an
|
@details Reads in a file byte by byte and writes it back out. Is an
|
||||||
os-independent method to copy files. In case of naming collision, the
|
os-independent method to copy files. In case of naming collision, the
|
||||||
default filerefs can be modified.
|
default filerefs can be modified.
|
||||||
Based on:
|
Note that if you have a new enough version of SAS, and you don't need features
|
||||||
https://stackoverflow.com/questions/13046116/using-sas-to-copy-a-text-file
|
such as APPEND, you may be better of using the fcopy() function instead.
|
||||||
|
|
||||||
%mp_binarycopy(inloc="/home/me/blah.txt", outref=_webout)
|
%mp_binarycopy(inloc="/home/me/blah.txt", outref=_webout)
|
||||||
|
|
||||||
@@ -45,14 +45,9 @@
|
|||||||
,outref=____out /* override default to use own filerefs */
|
,outref=____out /* override default to use own filerefs */
|
||||||
,mode=CREATE
|
,mode=CREATE
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local mod outmode;
|
%local mod;
|
||||||
%if &mode=APPEND %then %do;
|
%if &mode=APPEND %then %let mod=mod;
|
||||||
%let mod=mod;
|
|
||||||
%let outmode='a';
|
|
||||||
%end;
|
|
||||||
%else %do;
|
|
||||||
%let outmode='o';
|
|
||||||
%end;
|
|
||||||
/* these IN and OUT filerefs can point to anything */
|
/* these IN and OUT filerefs can point to anything */
|
||||||
%if &inref = ____in %then %do;
|
%if &inref = ____in %then %do;
|
||||||
filename &inref &inloc lrecl=1048576 ;
|
filename &inref &inloc lrecl=1048576 ;
|
||||||
@@ -63,18 +58,13 @@
|
|||||||
|
|
||||||
/* copy the file byte-for-byte */
|
/* copy the file byte-for-byte */
|
||||||
data _null_;
|
data _null_;
|
||||||
length filein 8 fileid 8;
|
infile &inref lrecl=1 recfm=n;
|
||||||
filein = fopen("&inref",'I',1,'B');
|
file &outref &mod recfm=n;
|
||||||
fileid = fopen("&outref",&outmode,1,'B');
|
input sourcechar $char1. @@;
|
||||||
rec = '20'x;
|
format sourcechar hex2.;
|
||||||
do while(fread(filein)=0);
|
put sourcechar char1. @@;
|
||||||
rc = fget(filein,rec,1);
|
|
||||||
rc = fput(fileid, rec);
|
|
||||||
rc =fwrite(fileid);
|
|
||||||
end;
|
|
||||||
rc = fclose(filein);
|
|
||||||
rc = fclose(fileid);
|
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%if &inref = ____in %then %do;
|
%if &inref = ____in %then %do;
|
||||||
filename &inref clear;
|
filename &inref clear;
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
@cond
|
@cond
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mp_ds2cards(base_ds=, tgt_ds=
|
%macro mp_ds2cards(base_ds, tgt_ds=
|
||||||
,cards_file="%sysfunc(pathname(work))/cardgen.sas"
|
,cards_file="%sysfunc(pathname(work))/cardgen.sas"
|
||||||
,maxobs=max
|
,maxobs=max
|
||||||
,random_sample=NO
|
,random_sample=NO
|
||||||
@@ -254,6 +254,7 @@ data _null_;
|
|||||||
;
|
;
|
||||||
%end;
|
%end;
|
||||||
put ";";
|
put ";";
|
||||||
|
put 'missing a b c d e f g h i j k l m n o p q r s t u v w x y z _;';
|
||||||
put "datalines4;";
|
put "datalines4;";
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
/**
|
/**
|
||||||
@file mp_jsonout.sas
|
@file mp_jsonout.sas
|
||||||
@brief Writes JSON in SASjs format to a fileref
|
@brief Writes JSON in SASjs format to a fileref
|
||||||
@details PROC JSON is faster but will produce errs like the ones below if
|
@details This macro can be used to OPEN a JSON stream and send one or more
|
||||||
|
tables as arrays of rows, where each row can be an object or a nested array.
|
||||||
|
|
||||||
|
There are two engines available - DATASTEP or PROCJSON.
|
||||||
|
|
||||||
|
PROC JSON is fast but will produce errs like the ones below if
|
||||||
special chars are encountered.
|
special chars are encountered.
|
||||||
|
|
||||||
> (ERR)OR: Some code points did not transcode.
|
> (ERR)OR: Some code points did not transcode.
|
||||||
@@ -12,6 +17,10 @@
|
|||||||
|
|
||||||
If this happens, try running with ENGINE=DATASTEP.
|
If this happens, try running with ENGINE=DATASTEP.
|
||||||
|
|
||||||
|
The DATASTEP engine is used to handle special SAS missing numerics, and
|
||||||
|
can also convert entire datasets to formatted values. Output JSON is always
|
||||||
|
in UTF-8.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
filename tmp temp;
|
filename tmp temp;
|
||||||
@@ -75,9 +84,23 @@
|
|||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if (&action=ARR or &action=OBJ) %then %do;
|
%else %if (&action=ARR or &action=OBJ) %then %do;
|
||||||
|
/* force variable names to always be uppercase in the JSON */
|
||||||
options validvarname=upcase;
|
options validvarname=upcase;
|
||||||
data _null_; file &jref encoding='utf-8' mod;
|
/* To avoid issues with _webout on EBI - such as encoding diffs and truncation
|
||||||
|
(https://support.sas.com/kb/49/325.html) we use temporary files */
|
||||||
|
filename _sjs1 temp lrecl=200 ;
|
||||||
|
data _null_; file _sjs1 encoding='utf-8';
|
||||||
put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":";
|
put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":";
|
||||||
|
run;
|
||||||
|
/* now write to _webout 1 char at a time */
|
||||||
|
data _null_;
|
||||||
|
infile _sjs1 lrecl=1 recfm=n;
|
||||||
|
file &jref mod lrecl=1 recfm=n;
|
||||||
|
input sourcechar $char1. @@;
|
||||||
|
format sourcechar hex2.;
|
||||||
|
put sourcechar char1. @@;
|
||||||
|
run;
|
||||||
|
filename _sjs1 clear;
|
||||||
|
|
||||||
/* grab col defs */
|
/* grab col defs */
|
||||||
proc contents noprint data=&ds
|
proc contents noprint data=&ds
|
||||||
@@ -134,10 +157,20 @@
|
|||||||
data &tempds;set &ds;
|
data &tempds;set &ds;
|
||||||
%if &fmt=N %then format _numeric_ best32.;;
|
%if &fmt=N %then format _numeric_ best32.;;
|
||||||
/* PRETTY is necessary to avoid line truncation in large files */
|
/* PRETTY is necessary to avoid line truncation in large files */
|
||||||
proc json out=&jref pretty
|
filename _sjs2 temp lrecl=131068 encoding='utf-8';
|
||||||
|
proc json out=_sjs2 pretty
|
||||||
%if &action=ARR %then nokeys ;
|
%if &action=ARR %then nokeys ;
|
||||||
;export &tempds / nosastags fmtnumeric;
|
;export &tempds / nosastags fmtnumeric;
|
||||||
run;
|
run;
|
||||||
|
/* send back to webout */
|
||||||
|
data _null_;
|
||||||
|
infile _sjs2 lrecl=1 recfm=n;
|
||||||
|
file &jref mod lrecl=1 recfm=n;
|
||||||
|
input sourcechar $char1. @@;
|
||||||
|
format sourcechar hex2.;
|
||||||
|
put sourcechar char1. @@;
|
||||||
|
run;
|
||||||
|
filename _sjs2 clear;
|
||||||
%end;
|
%end;
|
||||||
%else %if &engine=DATASTEP %then %do;
|
%else %if &engine=DATASTEP %then %do;
|
||||||
%datastep:
|
%datastep:
|
||||||
@@ -220,10 +253,9 @@
|
|||||||
%end;
|
%end;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
/* write to temp loc to avoid _webout truncation
|
filename _sjs3 temp lrecl=131068 ;
|
||||||
- https://support.sas.com/kb/49/325.html */
|
data _null_;
|
||||||
filename _sjs temp lrecl=131068 encoding='utf-8';
|
file _sjs3 encoding='utf-8';
|
||||||
data _null_; file _sjs lrecl=131068 encoding='utf-8' mod ;
|
|
||||||
if _n_=1 then put "[";
|
if _n_=1 then put "[";
|
||||||
set &tempds;
|
set &tempds;
|
||||||
if _n_>1 then put "," @; put
|
if _n_>1 then put "," @; put
|
||||||
@@ -234,36 +266,34 @@
|
|||||||
"&&name&i"n /* name literal for reserved variable names */
|
"&&name&i"n /* name literal for reserved variable names */
|
||||||
%end;
|
%end;
|
||||||
%if &action=ARR %then "]" ; %else "}" ; ;
|
%if &action=ARR %then "]" ; %else "}" ; ;
|
||||||
/* now write the long strings to _webout 1 byte at a time */
|
|
||||||
data _null_;
|
|
||||||
length filein 8 fileid 8;
|
|
||||||
filein=fopen("_sjs",'I',1,'B');
|
|
||||||
fileid=fopen("&jref",'A',1,'B');
|
|
||||||
rec='20'x;
|
|
||||||
do while(fread(filein)=0);
|
|
||||||
rc=fget(filein,rec,1);
|
|
||||||
rc=fput(fileid, rec);
|
|
||||||
rc=fwrite(fileid);
|
|
||||||
end;
|
|
||||||
/* close out the table */
|
/* close out the table */
|
||||||
rc=fput(fileid, "]");
|
data _null_;
|
||||||
rc=fwrite(fileid);
|
file _sjs3 mod encoding='utf-8';
|
||||||
rc=fclose(filein);
|
put ']';
|
||||||
rc=fclose(fileid);
|
|
||||||
run;
|
run;
|
||||||
filename _sjs clear;
|
data _null_;
|
||||||
|
infile _sjs3 lrecl=1 recfm=n;
|
||||||
|
file &jref mod lrecl=1 recfm=n;
|
||||||
|
input sourcechar $char1. @@;
|
||||||
|
format sourcechar hex2.;
|
||||||
|
put sourcechar char1. @@;
|
||||||
|
run;
|
||||||
|
filename _sjs3 clear;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
proc sql;
|
proc sql;
|
||||||
drop table &colinfo, &tempds;
|
drop table &colinfo, &tempds;
|
||||||
|
|
||||||
%if &showmeta=YES %then %do;
|
%if &showmeta=YES %then %do;
|
||||||
data _null_; file &jref encoding='utf-8' mod;
|
filename _sjs4 temp lrecl=131068 encoding='utf-8';
|
||||||
|
data _null_;
|
||||||
|
file _sjs4;
|
||||||
put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{";
|
put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{";
|
||||||
do i=1 to &numcols;
|
do i=1 to &numcols;
|
||||||
name=quote(trim(symget(cats('name',i))));
|
name=quote(trim(symget(cats('name',i))));
|
||||||
format=quote(trim(symget(cats('fmt',i))));
|
format=quote(trim(symget(cats('fmt',i))));
|
||||||
label=quote(trim(symget(cats('label',i))));
|
label=quote(prxchange('s/\\/\\\\/',-1,trim(symget(cats('label',i)))));
|
||||||
length=quote(trim(symget(cats('length',i))));
|
length=quote(trim(symget(cats('length',i))));
|
||||||
type=quote(trim(symget(cats('typelong',i))));
|
type=quote(trim(symget(cats('typelong',i))));
|
||||||
if i>1 then put "," @@;
|
if i>1 then put "," @@;
|
||||||
@@ -272,6 +302,15 @@
|
|||||||
end;
|
end;
|
||||||
put '}}';
|
put '}}';
|
||||||
run;
|
run;
|
||||||
|
/* send back to webout */
|
||||||
|
data _null_;
|
||||||
|
infile _sjs4 lrecl=1 recfm=n;
|
||||||
|
file &jref mod lrecl=1 recfm=n;
|
||||||
|
input sourcechar $char1. @@;
|
||||||
|
format sourcechar hex2.;
|
||||||
|
put sourcechar char1. @@;
|
||||||
|
run;
|
||||||
|
filename _sjs4 clear;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
@details Adds a user to a metadata group. The macro first checks whether the
|
@details Adds a user to a metadata group. The macro first checks whether the
|
||||||
user is in that group, and if not, the user is added.
|
user is in that group, and if not, the user is added.
|
||||||
|
|
||||||
|
Note that the macro does not check inherited group memberships - it looks at
|
||||||
|
direct members only.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%mm_adduser2group(user=sasdemo
|
%mm_adduser2group(user=sasdemo
|
||||||
@@ -12,10 +15,10 @@
|
|||||||
|
|
||||||
@param user= the user name (not displayname)
|
@param user= the user name (not displayname)
|
||||||
@param group= the group to which to add the user
|
@param group= the group to which to add the user
|
||||||
@param mdebug= set to 1 to show debug info in log
|
@param mdebug= (0) set to 1 to show debug info in log
|
||||||
|
|
||||||
@warning the macro does not check inherited group memberships - it looks at
|
<h4> Related Files </h4>
|
||||||
direct members only
|
@li ms_adduser2group.sas
|
||||||
|
|
||||||
@version 9.3
|
@version 9.3
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
%mm_createfolder(path=/some/meta/folder)
|
%mm_createfolder(path=/some/meta/folder)
|
||||||
|
|
||||||
@param [in] path= Name of the folder to create.
|
@param [in] path= Name of the folder to create.
|
||||||
@param [in] mdebug= set DBG to 1 to disable DEBUG messages
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
|
||||||
|
|
||||||
@version 9.4
|
@version 9.4
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
@file mm_createwebservice.sas
|
@file mm_createwebservice.sas
|
||||||
@brief Create a Web Ready Stored Process
|
@brief Create a Web Ready Stored Process
|
||||||
@details This macro creates a Type 2 Stored Process with the mm_webout macro
|
@details This macro creates a Type 2 Stored Process with the mm_webout macro
|
||||||
included as pre-code.
|
(and dependencies) included as pre-code.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%* compile macros ;
|
%* compile macros ;
|
||||||
@@ -108,9 +109,23 @@ data _null_;
|
|||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%else %if (&action=ARR or &action=OBJ) %then %do; ';
|
put '%else %if (&action=ARR or &action=OBJ) %then %do; ';
|
||||||
|
put ' /* force variable names to always be uppercase in the JSON */ ';
|
||||||
put ' options validvarname=upcase; ';
|
put ' options validvarname=upcase; ';
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
put ' /* To avoid issues with _webout on EBI - such as encoding diffs and truncation ';
|
||||||
|
put ' (https://support.sas.com/kb/49/325.html) we use temporary files */ ';
|
||||||
|
put ' filename _sjs1 temp lrecl=200 ; ';
|
||||||
|
put ' data _null_; file _sjs1 encoding=''utf-8''; ';
|
||||||
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
|
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' /* now write to _webout 1 char at a time */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs1 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs1 clear; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' /* grab col defs */ ';
|
put ' /* grab col defs */ ';
|
||||||
put ' proc contents noprint data=&ds ';
|
put ' proc contents noprint data=&ds ';
|
||||||
@@ -167,10 +182,20 @@ data _null_;
|
|||||||
put ' data &tempds;set &ds; ';
|
put ' data &tempds;set &ds; ';
|
||||||
put ' %if &fmt=N %then format _numeric_ best32.;; ';
|
put ' %if &fmt=N %then format _numeric_ best32.;; ';
|
||||||
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
|
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
|
||||||
put ' proc json out=&jref pretty ';
|
put ' filename _sjs2 temp lrecl=131068 encoding=''utf-8''; ';
|
||||||
|
put ' proc json out=_sjs2 pretty ';
|
||||||
put ' %if &action=ARR %then nokeys ; ';
|
put ' %if &action=ARR %then nokeys ; ';
|
||||||
put ' ;export &tempds / nosastags fmtnumeric; ';
|
put ' ;export &tempds / nosastags fmtnumeric; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
|
put ' /* send back to webout */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs2 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs2 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %else %if &engine=DATASTEP %then %do; ';
|
put ' %else %if &engine=DATASTEP %then %do; ';
|
||||||
put ' %datastep: ';
|
put ' %datastep: ';
|
||||||
@@ -253,10 +278,9 @@ data _null_;
|
|||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' /* write to temp loc to avoid _webout truncation ';
|
put ' filename _sjs3 temp lrecl=131068 ; ';
|
||||||
put ' - https://support.sas.com/kb/49/325.html */ ';
|
put ' data _null_; ';
|
||||||
put ' filename _sjs temp lrecl=131068 encoding=''utf-8''; ';
|
put ' file _sjs3 encoding=''utf-8''; ';
|
||||||
put ' data _null_; file _sjs lrecl=131068 encoding=''utf-8'' mod ; ';
|
|
||||||
put ' if _n_=1 then put "["; ';
|
put ' if _n_=1 then put "["; ';
|
||||||
put ' set &tempds; ';
|
put ' set &tempds; ';
|
||||||
put ' if _n_>1 then put "," @; put ';
|
put ' if _n_>1 then put "," @; put ';
|
||||||
@@ -267,36 +291,34 @@ data _null_;
|
|||||||
put ' "&&name&i"n /* name literal for reserved variable names */ ';
|
put ' "&&name&i"n /* name literal for reserved variable names */ ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
|
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
|
||||||
put ' /* now write the long strings to _webout 1 byte at a time */ ';
|
put ' ';
|
||||||
put ' data _null_; ';
|
|
||||||
put ' length filein 8 fileid 8; ';
|
|
||||||
put ' filein=fopen("_sjs",''I'',1,''B''); ';
|
|
||||||
put ' fileid=fopen("&jref",''A'',1,''B''); ';
|
|
||||||
put ' rec=''20''x; ';
|
|
||||||
put ' do while(fread(filein)=0); ';
|
|
||||||
put ' rc=fget(filein,rec,1); ';
|
|
||||||
put ' rc=fput(fileid, rec); ';
|
|
||||||
put ' rc=fwrite(fileid); ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' /* close out the table */ ';
|
put ' /* close out the table */ ';
|
||||||
put ' rc=fput(fileid, "]"); ';
|
put ' data _null_; ';
|
||||||
put ' rc=fwrite(fileid); ';
|
put ' file _sjs3 mod encoding=''utf-8''; ';
|
||||||
put ' rc=fclose(filein); ';
|
put ' put '']''; ';
|
||||||
put ' rc=fclose(fileid); ';
|
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put ' filename _sjs clear; ';
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs3 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs3 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' proc sql; ';
|
put ' proc sql; ';
|
||||||
put ' drop table &colinfo, &tempds; ';
|
put ' drop table &colinfo, &tempds; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' %if &showmeta=YES %then %do; ';
|
put ' %if &showmeta=YES %then %do; ';
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
put ' filename _sjs4 temp lrecl=131068 encoding=''utf-8''; ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' file _sjs4; ';
|
||||||
put ' put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{"; ';
|
put ' put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{"; ';
|
||||||
put ' do i=1 to &numcols; ';
|
put ' do i=1 to &numcols; ';
|
||||||
put ' name=quote(trim(symget(cats(''name'',i)))); ';
|
put ' name=quote(trim(symget(cats(''name'',i)))); ';
|
||||||
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
|
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
|
||||||
put ' label=quote(trim(symget(cats(''label'',i)))); ';
|
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
|
||||||
put ' length=quote(trim(symget(cats(''length'',i)))); ';
|
put ' length=quote(trim(symget(cats(''length'',i)))); ';
|
||||||
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
|
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
|
||||||
put ' if i>1 then put "," @@; ';
|
put ' if i>1 then put "," @@; ';
|
||||||
@@ -305,6 +327,15 @@ data _null_;
|
|||||||
put ' end; ';
|
put ' end; ';
|
||||||
put ' put ''}}''; ';
|
put ' put ''}}''; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
|
put ' /* send back to webout */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs4 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs4 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
@@ -315,18 +346,19 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%mend mp_jsonout; ';
|
put '%mend mp_jsonout; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%macro mf_getuser(type=META ';
|
put '%macro mf_getuser( ';
|
||||||
put ')/*/STORE SOURCE*/; ';
|
put ')/*/STORE SOURCE*/; ';
|
||||||
put ' %local user metavar; ';
|
put ' %local user; ';
|
||||||
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
|
||||||
put ' %else %let metavar=_metaperson; ';
|
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
|
||||||
put ' %else %if %symexist(&metavar) %then %do; ';
|
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
|
||||||
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %if %symexist(_metaperson) %then %do; ';
|
||||||
|
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
|
||||||
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
||||||
put ' /* but be sure to quote in case of usernames with commas */ ';
|
put ' /* but be sure to quote in case of usernames with commas */ ';
|
||||||
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %else %let user=&sysuserid; ';
|
put ' %else %let user=&sysuserid; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
@@ -405,6 +437,8 @@ data _null_;
|
|||||||
put ' ) ';
|
put ' ) ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%else %if &action=CLOSE %then %do; ';
|
put '%else %if &action=CLOSE %then %do; ';
|
||||||
|
put ' /* To avoid issues with _webout on EBI we use a temporary file */ ';
|
||||||
|
put ' filename _sjsref temp lrecl=131068; ';
|
||||||
put ' %if %str(&_debug) ge 131 %then %do; ';
|
put ' %if %str(&_debug) ge 131 %then %do; ';
|
||||||
put ' /* if debug mode, send back first 10 records of each work table also */ ';
|
put ' /* if debug mode, send back first 10 records of each work table also */ ';
|
||||||
put ' options obs=10; ';
|
put ' options obs=10; ';
|
||||||
@@ -418,11 +452,11 @@ data _null_;
|
|||||||
put ' i+1; ';
|
put ' i+1; ';
|
||||||
put ' call symputx(cats(''wt'',i),name,''l''); ';
|
put ' call symputx(cats(''wt'',i),name,''l''); ';
|
||||||
put ' call symputx(''wtcnt'',i,''l''); ';
|
put ' call symputx(''wtcnt'',i,''l''); ';
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
put ' data _null_; file _sjsref mod encoding=''utf-8''; ';
|
||||||
put ' put ",""WORK"":{"; ';
|
put ' put ",""WORK"":{"; ';
|
||||||
put ' %do i=1 %to &wtcnt; ';
|
put ' %do i=1 %to &wtcnt; ';
|
||||||
put ' %let wt=&&wt&i; ';
|
put ' %let wt=&&wt&i; ';
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
put ' data _null_; file _sjsref mod encoding=''utf-8''; ';
|
||||||
put ' dsid=open("WORK.&wt",''is''); ';
|
put ' dsid=open("WORK.&wt",''is''); ';
|
||||||
put ' nlobs=attrn(dsid,''NLOBS''); ';
|
put ' nlobs=attrn(dsid,''NLOBS''); ';
|
||||||
put ' nvars=attrn(dsid,''NVARS''); ';
|
put ' nvars=attrn(dsid,''NVARS''); ';
|
||||||
@@ -431,16 +465,16 @@ data _null_;
|
|||||||
put ' put " ""&wt"" : {"; ';
|
put ' put " ""&wt"" : {"; ';
|
||||||
put ' put ''"nlobs":'' nlobs; ';
|
put ' put ''"nlobs":'' nlobs; ';
|
||||||
put ' put '',"nvars":'' nvars; ';
|
put ' put '',"nvars":'' nvars; ';
|
||||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=YES) ';
|
put ' %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=YES) ';
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
put ' data _null_; file _sjsref mod encoding=''utf-8''; ';
|
||||||
put ' put "}"; ';
|
put ' put "}"; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
put ' data _null_; file _sjsref mod encoding=''utf-8''; ';
|
||||||
put ' put "}"; ';
|
put ' put "}"; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' /* close off json */ ';
|
put ' /* close off json */ ';
|
||||||
put ' data _null_;file &fref mod encoding=''utf-8''; ';
|
put ' data _null_;file _sjsref mod encoding=''utf-8''; ';
|
||||||
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
||||||
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
||||||
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
||||||
@@ -451,6 +485,7 @@ data _null_;
|
|||||||
put ' put '',"_METAPERSON": '' _METAPERSON; ';
|
put ' put '',"_METAPERSON": '' _METAPERSON; ';
|
||||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||||
|
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
|
||||||
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
|
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
|
||||||
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
||||||
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||||
@@ -471,6 +506,16 @@ data _null_;
|
|||||||
put ' put ''>>weboutEND<<''; ';
|
put ' put ''>>weboutEND<<''; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
|
put ' /* now write to _webout 1 char at a time */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjsref lrecl=1 recfm=n; ';
|
||||||
|
put ' file &fref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjsref clear; ';
|
||||||
|
put ' ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%mend mm_webout; ';
|
put '%mend mm_webout; ';
|
||||||
@@ -492,7 +537,7 @@ run;
|
|||||||
%if &x>1 %then %let mod=mod;
|
%if &x>1 %then %let mod=mod;
|
||||||
|
|
||||||
%let fref=%scan(&freflist,&x);
|
%let fref=%scan(&freflist,&x);
|
||||||
%put &sysmacroname: adding &fref;
|
%&mD.put &sysmacroname: adding &fref;
|
||||||
data _null_;
|
data _null_;
|
||||||
file "&work/&tmpfile" lrecl=3000 &mod;
|
file "&work/&tmpfile" lrecl=3000 &mod;
|
||||||
infile &fref;
|
infile &fref;
|
||||||
@@ -528,12 +573,10 @@ data _null_;
|
|||||||
if rc=0 then call symputx('url',url,'l');
|
if rc=0 then call symputx('url',url,'l');
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%put ;%put ;%put ;%put ;%put ;%put ;
|
|
||||||
%put &sysmacroname: STP &name successfully created in &path;
|
%put &sysmacroname: STP &name successfully created in &path;
|
||||||
%put ;%put ;%put ;
|
|
||||||
%put Check it out here:;
|
%put Check it out here:;
|
||||||
%put ;%put ;%put ;
|
%put ;%put ;%put ;
|
||||||
%put &url?_PROGRAM=&path/&name;
|
%put &url?_PROGRAM=&path/&name;
|
||||||
%put ;%put ;%put ;%put ;%put ;%put ;
|
%put ;%put ;%put ;
|
||||||
|
|
||||||
%mend mm_createwebservice;
|
%mend mm_createwebservice;
|
||||||
|
|||||||
@@ -8,17 +8,18 @@
|
|||||||
|
|
||||||
%mm_getusers()
|
%mm_getusers()
|
||||||
|
|
||||||
|
Optionally, filter for a user (useful to get the uri):
|
||||||
|
|
||||||
|
%mm_getusers(user=&_metaperson)
|
||||||
|
|
||||||
@param outds the dataset to create that contains the list of libraries
|
@param outds the dataset to create that contains the list of libraries
|
||||||
|
|
||||||
@returns outds dataset containing all users, with the following columns:
|
@returns outds dataset containing all users, with the following columns:
|
||||||
- uri
|
- uri
|
||||||
- name
|
- name
|
||||||
|
|
||||||
@warning The following filenames are created and then de-assigned:
|
@param user= (0) Set to a metadata user to filter on that user
|
||||||
|
@param outds= (work.mm_getusers) The output table to create
|
||||||
filename sxlemap clear;
|
|
||||||
filename response clear;
|
|
||||||
libname _XML_ clear;
|
|
||||||
|
|
||||||
@version 9.3
|
@version 9.3
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@@ -26,10 +27,12 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mm_getusers(
|
%macro mm_getusers(
|
||||||
outds=work.mm_getusers
|
outds=work.mm_getusers,
|
||||||
|
user=0
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
filename response temp;
|
filename response temp;
|
||||||
|
%if %superq(user)=0 %then %do;
|
||||||
proc metadata in= '<GetMetadataObjects>
|
proc metadata in= '<GetMetadataObjects>
|
||||||
<Reposid>$METAREPOSITORY</Reposid>
|
<Reposid>$METAREPOSITORY</Reposid>
|
||||||
<Type>Person</Type>
|
<Type>Person</Type>
|
||||||
@@ -43,6 +46,30 @@ proc metadata in= '<GetMetadataObjects>
|
|||||||
</GetMetadataObjects>'
|
</GetMetadataObjects>'
|
||||||
out=response;
|
out=response;
|
||||||
run;
|
run;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
filename inref temp;
|
||||||
|
data _null_;
|
||||||
|
file inref;
|
||||||
|
put "<GetMetadataObjects>";
|
||||||
|
put "<Reposid>$METAREPOSITORY</Reposid>";
|
||||||
|
put "<Type>Person</Type>";
|
||||||
|
put "<NS>SAS</NS>";
|
||||||
|
put "<!-- Specify the OMI_XMLSELECT (128) flag -->";
|
||||||
|
put "<Flags>128</Flags>";
|
||||||
|
put "<Options>";
|
||||||
|
put "<Templates>";
|
||||||
|
put '<Person Name=""/>';
|
||||||
|
put "</Templates>";
|
||||||
|
length string $10000;
|
||||||
|
string=cats('<XMLSELECT search="Person[@Name=',"'&user'",']"/>');
|
||||||
|
put string;
|
||||||
|
put "</Options>";
|
||||||
|
put "</GetMetadataObjects>";
|
||||||
|
run;
|
||||||
|
proc metadata in=inref out=response;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
filename sxlemap temp;
|
filename sxlemap temp;
|
||||||
data _null_;
|
data _null_;
|
||||||
|
|||||||
@@ -35,6 +35,10 @@
|
|||||||
object with the same name as the table but prefixed with a dollar sign - ie,
|
object with the same name as the table but prefixed with a dollar sign - ie,
|
||||||
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
|
||||||
|
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mp_jsonout.sas
|
||||||
|
|
||||||
@version 9.3
|
@version 9.3
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
|
|
||||||
@@ -111,6 +115,8 @@
|
|||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
%else %if &action=CLOSE %then %do;
|
%else %if &action=CLOSE %then %do;
|
||||||
|
/* To avoid issues with _webout on EBI we use a temporary file */
|
||||||
|
filename _sjsref temp lrecl=131068;
|
||||||
%if %str(&_debug) ge 131 %then %do;
|
%if %str(&_debug) ge 131 %then %do;
|
||||||
/* if debug mode, send back first 10 records of each work table also */
|
/* if debug mode, send back first 10 records of each work table also */
|
||||||
options obs=10;
|
options obs=10;
|
||||||
@@ -124,11 +130,11 @@
|
|||||||
i+1;
|
i+1;
|
||||||
call symputx(cats('wt',i),name,'l');
|
call symputx(cats('wt',i),name,'l');
|
||||||
call symputx('wtcnt',i,'l');
|
call symputx('wtcnt',i,'l');
|
||||||
data _null_; file &fref mod encoding='utf-8';
|
data _null_; file _sjsref mod encoding='utf-8';
|
||||||
put ",""WORK"":{";
|
put ",""WORK"":{";
|
||||||
%do i=1 %to &wtcnt;
|
%do i=1 %to &wtcnt;
|
||||||
%let wt=&&wt&i;
|
%let wt=&&wt&i;
|
||||||
data _null_; file &fref mod encoding='utf-8';
|
data _null_; file _sjsref mod encoding='utf-8';
|
||||||
dsid=open("WORK.&wt",'is');
|
dsid=open("WORK.&wt",'is');
|
||||||
nlobs=attrn(dsid,'NLOBS');
|
nlobs=attrn(dsid,'NLOBS');
|
||||||
nvars=attrn(dsid,'NVARS');
|
nvars=attrn(dsid,'NVARS');
|
||||||
@@ -137,16 +143,16 @@
|
|||||||
put " ""&wt"" : {";
|
put " ""&wt"" : {";
|
||||||
put '"nlobs":' nlobs;
|
put '"nlobs":' nlobs;
|
||||||
put ',"nvars":' nvars;
|
put ',"nvars":' nvars;
|
||||||
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=YES)
|
%mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=YES)
|
||||||
data _null_; file &fref mod encoding='utf-8';
|
data _null_; file _sjsref mod encoding='utf-8';
|
||||||
put "}";
|
put "}";
|
||||||
%end;
|
%end;
|
||||||
data _null_; file &fref mod encoding='utf-8';
|
data _null_; file _sjsref mod encoding='utf-8';
|
||||||
put "}";
|
put "}";
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
/* close off json */
|
/* close off json */
|
||||||
data _null_;file &fref mod encoding='utf-8';
|
data _null_;file _sjsref mod encoding='utf-8';
|
||||||
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
|
||||||
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
put ",""SYSUSERID"" : ""&sysuserid"" ";
|
||||||
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
|
||||||
@@ -157,6 +163,7 @@
|
|||||||
put ',"_METAPERSON": ' _METAPERSON;
|
put ',"_METAPERSON": ' _METAPERSON;
|
||||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||||
put ",""SYSCC"" : ""&syscc"" ";
|
put ",""SYSCC"" : ""&syscc"" ";
|
||||||
|
put ",""SYSENCODING"" : ""&sysencoding"" ";
|
||||||
syserrortext=quote(cats(symget('SYSERRORTEXT')));
|
syserrortext=quote(cats(symget('SYSERRORTEXT')));
|
||||||
put ',"SYSERRORTEXT" : ' syserrortext;
|
put ',"SYSERRORTEXT" : ' syserrortext;
|
||||||
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
|
||||||
@@ -177,6 +184,16 @@
|
|||||||
put '>>weboutEND<<';
|
put '>>weboutEND<<';
|
||||||
%end;
|
%end;
|
||||||
run;
|
run;
|
||||||
|
/* now write to _webout 1 char at a time */
|
||||||
|
data _null_;
|
||||||
|
infile _sjsref lrecl=1 recfm=n;
|
||||||
|
file &fref mod lrecl=1 recfm=n;
|
||||||
|
input sourcechar $char1. @@;
|
||||||
|
format sourcechar hex2.;
|
||||||
|
put sourcechar char1. @@;
|
||||||
|
run;
|
||||||
|
filename _sjsref clear;
|
||||||
|
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mm_webout;
|
%mend mm_webout;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"serverUrl": "https://sas.analytium.co.uk:5007",
|
"serverUrl": "",
|
||||||
"serverType": "SASJS",
|
"serverType": "SASJS",
|
||||||
"httpsAgentOptions": {
|
"httpsAgentOptions": {
|
||||||
"allowInsecureRequests": false
|
"allowInsecureRequests": false
|
||||||
|
|||||||
122
server/ms_adduser2group.sas
Normal file
122
server/ms_adduser2group.sas
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Adds a user to a group on SASjs Server
|
||||||
|
@details Adds a user to a group based on userid and groupid. Both user and
|
||||||
|
group must already exist.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
%ms_adduser2group(uid=1,gid=1)
|
||||||
|
|
||||||
|
|
||||||
|
@param [in] uid= (0) The User ID to be added
|
||||||
|
@param [in] gid= (0) The Group ID to contain the new user
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
@param [out] outds= (work.ms_adduser2group) This output dataset will contain
|
||||||
|
the new list of group members, eg:
|
||||||
|
|DISPLAYNAME:$18.|USERNAME:$10.|ID:best.|
|
||||||
|
|---|---|---|
|
||||||
|
|`Super Admin `|`secretuser `|`1`|
|
||||||
|
|`Sabir Hassan`|`sabir`|`2`|
|
||||||
|
|`Mihajlo Medjedovic `|`mihajlo `|`3`|
|
||||||
|
|`Ivor Townsend `|`ivor `|`4`|
|
||||||
|
|`New User `|`newuser `|`5`|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquelibref.sas
|
||||||
|
@li mp_abort.sas
|
||||||
|
|
||||||
|
<h4> Related Files </h4>
|
||||||
|
@li ms_creategroup.sas
|
||||||
|
@li ms_createuser.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_adduser2group(uid=0
|
||||||
|
,gid=0
|
||||||
|
,outds=work.ms_adduser2group
|
||||||
|
,mdebug=0
|
||||||
|
);
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&syscc ne 0)
|
||||||
|
,mac=ms_adduser2group.sas
|
||||||
|
,msg=%str(syscc=&syscc on macro entry)
|
||||||
|
)
|
||||||
|
|
||||||
|
%local fref0 fref1 fref2 libref optval rc msg;
|
||||||
|
%let fref0=%mf_getuniquefileref();
|
||||||
|
%let fref1=%mf_getuniquefileref();
|
||||||
|
%let libref=%mf_getuniquelibref();
|
||||||
|
|
||||||
|
/* avoid sending bom marker to API */
|
||||||
|
%let optval=%sysfunc(getoption(bomfile));
|
||||||
|
options nobomfile;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &fref0 lrecl=1000;
|
||||||
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
|
input;
|
||||||
|
if _n_=1 then put "accept: application/json";
|
||||||
|
put _infile_;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
%put _local_;
|
||||||
|
data _null_;
|
||||||
|
infile &fref0;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
proc http method='POST' headerin=&fref0 out=&fref1
|
||||||
|
url="&_sasjs_apiserverurl/SASjsApi/group/&gid/&uid";
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
debug level=1;
|
||||||
|
%end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&syscc ne 0)
|
||||||
|
,mac=ms_adduser2group.sas
|
||||||
|
,msg=%str(Issue submitting query to SASjsApi/group)
|
||||||
|
)
|
||||||
|
|
||||||
|
libname &libref JSON fileref=&fref1;
|
||||||
|
|
||||||
|
data &outds;
|
||||||
|
set &libref..users;
|
||||||
|
drop ordinal_root ordinal_users;
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
putlog _all_;
|
||||||
|
%end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&syscc ne 0)
|
||||||
|
,mac=ms_creategroup.sas
|
||||||
|
,msg=%str(Issue reading response JSON)
|
||||||
|
)
|
||||||
|
|
||||||
|
/* reset options */
|
||||||
|
options &optval;
|
||||||
|
|
||||||
|
%if &mdebug=0 %then %do;
|
||||||
|
filename &fref0 clear;
|
||||||
|
filename &fref1 clear;
|
||||||
|
libname &libref clear;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
data _null_;
|
||||||
|
infile &fref1;
|
||||||
|
input;
|
||||||
|
putlog _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend ms_adduser2group;
|
||||||
@@ -110,9 +110,23 @@ data _null_;
|
|||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%else %if (&action=ARR or &action=OBJ) %then %do; ';
|
put '%else %if (&action=ARR or &action=OBJ) %then %do; ';
|
||||||
|
put ' /* force variable names to always be uppercase in the JSON */ ';
|
||||||
put ' options validvarname=upcase; ';
|
put ' options validvarname=upcase; ';
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
put ' /* To avoid issues with _webout on EBI - such as encoding diffs and truncation ';
|
||||||
|
put ' (https://support.sas.com/kb/49/325.html) we use temporary files */ ';
|
||||||
|
put ' filename _sjs1 temp lrecl=200 ; ';
|
||||||
|
put ' data _null_; file _sjs1 encoding=''utf-8''; ';
|
||||||
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
|
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' /* now write to _webout 1 char at a time */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs1 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs1 clear; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' /* grab col defs */ ';
|
put ' /* grab col defs */ ';
|
||||||
put ' proc contents noprint data=&ds ';
|
put ' proc contents noprint data=&ds ';
|
||||||
@@ -169,10 +183,20 @@ data _null_;
|
|||||||
put ' data &tempds;set &ds; ';
|
put ' data &tempds;set &ds; ';
|
||||||
put ' %if &fmt=N %then format _numeric_ best32.;; ';
|
put ' %if &fmt=N %then format _numeric_ best32.;; ';
|
||||||
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
|
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
|
||||||
put ' proc json out=&jref pretty ';
|
put ' filename _sjs2 temp lrecl=131068 encoding=''utf-8''; ';
|
||||||
|
put ' proc json out=_sjs2 pretty ';
|
||||||
put ' %if &action=ARR %then nokeys ; ';
|
put ' %if &action=ARR %then nokeys ; ';
|
||||||
put ' ;export &tempds / nosastags fmtnumeric; ';
|
put ' ;export &tempds / nosastags fmtnumeric; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
|
put ' /* send back to webout */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs2 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs2 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %else %if &engine=DATASTEP %then %do; ';
|
put ' %else %if &engine=DATASTEP %then %do; ';
|
||||||
put ' %datastep: ';
|
put ' %datastep: ';
|
||||||
@@ -255,10 +279,9 @@ data _null_;
|
|||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' /* write to temp loc to avoid _webout truncation ';
|
put ' filename _sjs3 temp lrecl=131068 ; ';
|
||||||
put ' - https://support.sas.com/kb/49/325.html */ ';
|
put ' data _null_; ';
|
||||||
put ' filename _sjs temp lrecl=131068 encoding=''utf-8''; ';
|
put ' file _sjs3 encoding=''utf-8''; ';
|
||||||
put ' data _null_; file _sjs lrecl=131068 encoding=''utf-8'' mod ; ';
|
|
||||||
put ' if _n_=1 then put "["; ';
|
put ' if _n_=1 then put "["; ';
|
||||||
put ' set &tempds; ';
|
put ' set &tempds; ';
|
||||||
put ' if _n_>1 then put "," @; put ';
|
put ' if _n_>1 then put "," @; put ';
|
||||||
@@ -269,36 +292,34 @@ data _null_;
|
|||||||
put ' "&&name&i"n /* name literal for reserved variable names */ ';
|
put ' "&&name&i"n /* name literal for reserved variable names */ ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
|
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
|
||||||
put ' /* now write the long strings to _webout 1 byte at a time */ ';
|
put ' ';
|
||||||
put ' data _null_; ';
|
|
||||||
put ' length filein 8 fileid 8; ';
|
|
||||||
put ' filein=fopen("_sjs",''I'',1,''B''); ';
|
|
||||||
put ' fileid=fopen("&jref",''A'',1,''B''); ';
|
|
||||||
put ' rec=''20''x; ';
|
|
||||||
put ' do while(fread(filein)=0); ';
|
|
||||||
put ' rc=fget(filein,rec,1); ';
|
|
||||||
put ' rc=fput(fileid, rec); ';
|
|
||||||
put ' rc=fwrite(fileid); ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' /* close out the table */ ';
|
put ' /* close out the table */ ';
|
||||||
put ' rc=fput(fileid, "]"); ';
|
put ' data _null_; ';
|
||||||
put ' rc=fwrite(fileid); ';
|
put ' file _sjs3 mod encoding=''utf-8''; ';
|
||||||
put ' rc=fclose(filein); ';
|
put ' put '']''; ';
|
||||||
put ' rc=fclose(fileid); ';
|
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put ' filename _sjs clear; ';
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs3 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs3 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' proc sql; ';
|
put ' proc sql; ';
|
||||||
put ' drop table &colinfo, &tempds; ';
|
put ' drop table &colinfo, &tempds; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' %if &showmeta=YES %then %do; ';
|
put ' %if &showmeta=YES %then %do; ';
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
put ' filename _sjs4 temp lrecl=131068 encoding=''utf-8''; ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' file _sjs4; ';
|
||||||
put ' put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{"; ';
|
put ' put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{"; ';
|
||||||
put ' do i=1 to &numcols; ';
|
put ' do i=1 to &numcols; ';
|
||||||
put ' name=quote(trim(symget(cats(''name'',i)))); ';
|
put ' name=quote(trim(symget(cats(''name'',i)))); ';
|
||||||
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
|
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
|
||||||
put ' label=quote(trim(symget(cats(''label'',i)))); ';
|
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
|
||||||
put ' length=quote(trim(symget(cats(''length'',i)))); ';
|
put ' length=quote(trim(symget(cats(''length'',i)))); ';
|
||||||
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
|
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
|
||||||
put ' if i>1 then put "," @@; ';
|
put ' if i>1 then put "," @@; ';
|
||||||
@@ -307,6 +328,15 @@ data _null_;
|
|||||||
put ' end; ';
|
put ' end; ';
|
||||||
put ' put ''}}''; ';
|
put ' put ''}}''; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
|
put ' /* send back to webout */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs4 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs4 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
@@ -317,18 +347,19 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%mend mp_jsonout; ';
|
put '%mend mp_jsonout; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%macro mf_getuser(type=META ';
|
put '%macro mf_getuser( ';
|
||||||
put ')/*/STORE SOURCE*/; ';
|
put ')/*/STORE SOURCE*/; ';
|
||||||
put ' %local user metavar; ';
|
put ' %local user; ';
|
||||||
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
|
||||||
put ' %else %let metavar=_metaperson; ';
|
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
|
||||||
put ' %else %if %symexist(&metavar) %then %do; ';
|
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
|
||||||
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %if %symexist(_metaperson) %then %do; ';
|
||||||
|
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
|
||||||
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
||||||
put ' /* but be sure to quote in case of usernames with commas */ ';
|
put ' /* but be sure to quote in case of usernames with commas */ ';
|
||||||
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %else %let user=&sysuserid; ';
|
put ' %else %let user=&sysuserid; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
@@ -443,6 +474,7 @@ data _null_;
|
|||||||
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
||||||
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||||
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||||
|
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
|
||||||
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
|
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
|
||||||
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
||||||
put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); ';
|
put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); ';
|
||||||
|
|||||||
@@ -2,13 +2,24 @@
|
|||||||
@file
|
@file
|
||||||
@brief Fetches the list of groups from SASjs Server
|
@brief Fetches the list of groups from SASjs Server
|
||||||
@details Fetches the list of groups from SASjs Server and writes them to an
|
@details Fetches the list of groups from SASjs Server and writes them to an
|
||||||
output dataset.
|
output dataset. Provide a username to filter for the groups for a particular
|
||||||
|
user.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
%ms_getgroups(outds=userlist)
|
%ms_getgroups(outds=userlist)
|
||||||
|
|
||||||
|
With filter on username:
|
||||||
|
|
||||||
|
%ms_getgroups(outds=userlist, user=James)
|
||||||
|
|
||||||
|
With filter on userid:
|
||||||
|
|
||||||
|
%ms_getgroups(outds=userlist, uid=1)
|
||||||
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
@param [in] user= (0) Provide the username on which to filter
|
||||||
|
@param [in] uid= (0) Provide the userid on which to filter
|
||||||
@param [out] outds= (work.ms_getgroups) This output dataset will contain the
|
@param [out] outds= (work.ms_getgroups) This output dataset will contain the
|
||||||
list of groups. Format:
|
list of groups. Format:
|
||||||
|NAME:$32.|DESCRIPTION:$64.|GROUPID:best.|
|
|NAME:$32.|DESCRIPTION:$64.|GROUPID:best.|
|
||||||
@@ -25,22 +36,38 @@
|
|||||||
|
|
||||||
<h4> Related Files </h4>
|
<h4> Related Files </h4>
|
||||||
@li ms_creategroup.sas
|
@li ms_creategroup.sas
|
||||||
@li ms_getusers.test.sas
|
@li ms_getgroups.test.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro ms_getgroups(
|
%macro ms_getgroups(
|
||||||
outds=work.ms_getgroups
|
user=0,
|
||||||
,mdebug=0
|
uid=0,
|
||||||
|
outds=work.ms_getgroups,
|
||||||
|
mdebug=0
|
||||||
);
|
);
|
||||||
|
|
||||||
%mp_abort(
|
%mp_abort(
|
||||||
iftrue=(&syscc ne 0)
|
iftrue=(&syscc ne 0)
|
||||||
,mac=ms_getusers.sas
|
,mac=ms_getgroups.sas
|
||||||
,msg=%str(syscc=&syscc on macro entry)
|
,msg=%str(syscc=&syscc on macro entry)
|
||||||
)
|
)
|
||||||
|
|
||||||
%local fref0 fref1 libref optval rc msg;
|
%local fref0 fref1 libref optval rc msg url;
|
||||||
|
|
||||||
|
%if %sysget(MODE)=desktop %then %do;
|
||||||
|
/* groups api does not exist in desktop mode */
|
||||||
|
data &outds;
|
||||||
|
length NAME $32 DESCRIPTION $64. GROUPID 8;
|
||||||
|
name="&sysuserid";
|
||||||
|
description="&sysuserid (group - desktop mode)";
|
||||||
|
groupid=1;
|
||||||
|
output;
|
||||||
|
stop;
|
||||||
|
run;
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
%let fref0=%mf_getuniquefileref();
|
%let fref0=%mf_getuniquefileref();
|
||||||
%let fref1=%mf_getuniquefileref();
|
%let fref1=%mf_getuniquefileref();
|
||||||
%let libref=%mf_getuniquelibref();
|
%let libref=%mf_getuniquelibref();
|
||||||
@@ -65,8 +92,13 @@ run;
|
|||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
|
%if "&user" ne "0" %then %let url=/SASjsApi/user/by/username/&user;
|
||||||
|
%else %if "&uid" ne "0" %then %let url=/SASjsApi/user/&uid;
|
||||||
|
%else %let url=/SASjsApi/group;
|
||||||
|
|
||||||
|
|
||||||
proc http method='GET' headerin=&fref0 out=&fref1
|
proc http method='GET' headerin=&fref0 out=&fref1
|
||||||
url="&_sasjs_apiserverurl/SASjsApi/group";
|
url="&_sasjs_apiserverurl.&url";
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
debug level=1;
|
debug level=1;
|
||||||
%end;
|
%end;
|
||||||
@@ -75,21 +107,31 @@ run;
|
|||||||
%mp_abort(
|
%mp_abort(
|
||||||
iftrue=(&syscc ne 0)
|
iftrue=(&syscc ne 0)
|
||||||
,mac=ms_getgroups.sas
|
,mac=ms_getgroups.sas
|
||||||
,msg=%str(Issue submitting GET query to SASjsApi/group)
|
,msg=%str(Issue submitting GET query to SASjsApi)
|
||||||
)
|
)
|
||||||
|
|
||||||
libname &libref JSON fileref=&fref1;
|
libname &libref JSON fileref=&fref1;
|
||||||
|
|
||||||
|
%if "&user"="0" and "&uid"="0" %then %do;
|
||||||
data &outds;
|
data &outds;
|
||||||
length NAME $32 DESCRIPTION $64. GROUPID 8;
|
length NAME $32 DESCRIPTION $64. GROUPID 8;
|
||||||
if _n_=1 then call missing(of _all_);
|
if _n_=1 then call missing(of _all_);
|
||||||
set &libref..root;
|
set &libref..root;
|
||||||
drop ordinal_root;
|
drop ordinal_root;
|
||||||
run;
|
run;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
data &outds;
|
||||||
|
length NAME $32 DESCRIPTION $64. GROUPID 8;
|
||||||
|
if _n_=1 then call missing(of _all_);
|
||||||
|
set &libref..groups;
|
||||||
|
drop ordinal_:;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
%mp_abort(
|
%mp_abort(
|
||||||
iftrue=(&syscc ne 0)
|
iftrue=(&syscc ne 0)
|
||||||
,mac=ms_getusers.sas
|
,mac=ms_getgroups.sas
|
||||||
,msg=%str(Issue reading response JSON)
|
,msg=%str(Issue reading response JSON)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,26 @@
|
|||||||
@file
|
@file
|
||||||
@brief Fetches the list of users from SASjs Server
|
@brief Fetches the list of users from SASjs Server
|
||||||
@details Fetches the list of users from SASjs Server and writes them to an
|
@details Fetches the list of users from SASjs Server and writes them to an
|
||||||
output dataset.
|
output dataset. Can also be filtered, for a particular group.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
%ms_getusers(outds=userlist)
|
%ms_getusers(outds=userlist)
|
||||||
|
|
||||||
|
Filtering for a group by group name:
|
||||||
|
|
||||||
|
%ms_getusers(outds=work.groupmembers, group=GROUPNAME)
|
||||||
|
|
||||||
|
Filtering for a group by group id:
|
||||||
|
|
||||||
|
%ms_getusers(outds=work.groupmembers, gid=1)
|
||||||
|
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
@param [in] group= (0) Set to a group name to filter members for that group
|
||||||
|
@param [in] gid= (0) Set to a group id to filter members for that group
|
||||||
@param [out] outds= (work.ms_getusers) This output dataset will contain the
|
@param [out] outds= (work.ms_getusers) This output dataset will contain the
|
||||||
list of user accounts. Format:
|
list of user accounts. Format:
|
||||||
|DISPLAYNAME:$18.|USERNAME:$10.|ID:best.|
|
|DISPLAYNAME:$60.|USERNAME:$30.|ID:best.|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|`Super Admin `|`secretuser `|`1`|
|
|`Super Admin `|`secretuser `|`1`|
|
||||||
|`Sabir Hassan`|`sabir`|`2`|
|
|`Sabir Hassan`|`sabir`|`2`|
|
||||||
@@ -20,7 +30,6 @@
|
|||||||
|`New User `|`newuser `|`5`|
|
|`New User `|`newuser `|`5`|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mf_getuniquelibref.sas
|
@li mf_getuniquelibref.sas
|
||||||
@@ -28,13 +37,16 @@
|
|||||||
|
|
||||||
<h4> Related Files </h4>
|
<h4> Related Files </h4>
|
||||||
@li ms_createuser.sas
|
@li ms_createuser.sas
|
||||||
|
@li ms_getgroups.sas
|
||||||
@li ms_getusers.test.sas
|
@li ms_getusers.test.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro ms_getusers(
|
%macro ms_getusers(
|
||||||
outds=work.ms_getusers
|
outds=work.ms_getusers,
|
||||||
,mdebug=0
|
group=0,
|
||||||
|
gid=0,
|
||||||
|
mdebug=0
|
||||||
);
|
);
|
||||||
|
|
||||||
%mp_abort(
|
%mp_abort(
|
||||||
@@ -43,11 +55,24 @@
|
|||||||
,msg=%str(syscc=&syscc on macro entry)
|
,msg=%str(syscc=&syscc on macro entry)
|
||||||
)
|
)
|
||||||
|
|
||||||
%local fref0 fref1 libref optval rc msg;
|
%local fref0 fref1 libref optval rc msg url;
|
||||||
%let fref0=%mf_getuniquefileref();
|
%let fref0=%mf_getuniquefileref();
|
||||||
%let fref1=%mf_getuniquefileref();
|
%let fref1=%mf_getuniquefileref();
|
||||||
%let libref=%mf_getuniquelibref();
|
%let libref=%mf_getuniquelibref();
|
||||||
|
|
||||||
|
%if %sysget(MODE)=desktop %then %do;
|
||||||
|
/* users api does not exist in desktop mode */
|
||||||
|
data &outds;
|
||||||
|
length DISPLAYNAME $60 USERNAME:$30 ID 8;
|
||||||
|
USERNAME="&sysuserid";
|
||||||
|
DISPLAYNAME="&sysuserid (desktop mode)";
|
||||||
|
ID=1;
|
||||||
|
output;
|
||||||
|
stop;
|
||||||
|
run;
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
/* avoid sending bom marker to API */
|
/* avoid sending bom marker to API */
|
||||||
%let optval=%sysfunc(getoption(bomfile));
|
%let optval=%sysfunc(getoption(bomfile));
|
||||||
options nobomfile;
|
options nobomfile;
|
||||||
@@ -68,26 +93,40 @@ run;
|
|||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
|
%if "&group" ne "0" %then %let url=/SASjsApi/group/by/groupname/&group;
|
||||||
|
%else %if "&gid" ne "0" %then %let url=/SASjsApi/group/&gid;
|
||||||
|
%else %let url=/SASjsApi/user;
|
||||||
|
|
||||||
proc http method='GET' headerin=&fref0 out=&fref1
|
proc http method='GET' headerin=&fref0 out=&fref1
|
||||||
url="&_sasjs_apiserverurl/SASjsApi/user";
|
url="&_sasjs_apiserverurl.&url";
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
debug level=1;
|
debug level=1;
|
||||||
%end;
|
%end;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
|
||||||
%mp_abort(
|
%mp_abort(
|
||||||
iftrue=(&syscc ne 0)
|
iftrue=(&syscc ne 0)
|
||||||
,mac=ms_getusers.sas
|
,mac=ms_getusers.sas
|
||||||
,msg=%str(Issue submitting GET query to SASjsApi/user)
|
,msg=%str(Issue submitting API query)
|
||||||
)
|
)
|
||||||
|
|
||||||
libname &libref JSON fileref=&fref1;
|
libname &libref JSON fileref=&fref1;
|
||||||
|
|
||||||
|
%if "&group"="0" and "&gid"="0" %then %do;
|
||||||
data &outds;
|
data &outds;
|
||||||
|
length DISPLAYNAME $60 USERNAME:$30 ID 8;
|
||||||
set &libref..root;
|
set &libref..root;
|
||||||
drop ordinal_root;
|
drop ordinal_root;
|
||||||
run;
|
run;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
data &outds;
|
||||||
|
length DISPLAYNAME $60 USERNAME:$30 ID 8;
|
||||||
|
set &libref..users;
|
||||||
|
drop ordinal_root ordinal_users;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
%mp_abort(
|
%mp_abort(
|
||||||
iftrue=(&syscc ne 0)
|
iftrue=(&syscc ne 0)
|
||||||
|
|||||||
@@ -153,6 +153,7 @@
|
|||||||
put ",""_DEBUG"" : ""&_debug"" ";
|
put ",""_DEBUG"" : ""&_debug"" ";
|
||||||
put ',"_PROGRAM" : ' _PROGRAM ;
|
put ',"_PROGRAM" : ' _PROGRAM ;
|
||||||
put ",""SYSCC"" : ""&syscc"" ";
|
put ",""SYSCC"" : ""&syscc"" ";
|
||||||
|
put ",""SYSENCODING"" : ""&sysencoding"" ";
|
||||||
syserrortext=quote(cats(symget('SYSERRORTEXT')));
|
syserrortext=quote(cats(symget('SYSERRORTEXT')));
|
||||||
put ',"SYSERRORTEXT" : ' syserrortext;
|
put ',"SYSERRORTEXT" : ' syserrortext;
|
||||||
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));
|
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_binarycopy.sas
|
@li mp_binarycopy.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
|
@li mp_hashdataset.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -97,3 +98,39 @@ run;
|
|||||||
desc=Append Check (ref to file),
|
desc=Append Check (ref to file),
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* test 5 - ensure copy works for binary characters */
|
||||||
|
/* do this backwards to avoid null chars in JSON preview */
|
||||||
|
data work.test5;
|
||||||
|
do i=255 to 1 by -1;
|
||||||
|
str=byte(i);
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
/* get an md5 hash of the ds */
|
||||||
|
%mp_hashdataset(work.test5,outds=myhash)
|
||||||
|
|
||||||
|
/* copy it */
|
||||||
|
%mp_binarycopy(inloc="%sysfunc(pathname(work))/test5.sas7bdat",
|
||||||
|
outloc="%sysfunc(pathname(work))/test5copy.sas7bdat"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* get an md5 hash of the copied ds */
|
||||||
|
%mp_hashdataset(work.test5copy,outds=myhash2)
|
||||||
|
|
||||||
|
/* compare hashes */
|
||||||
|
%let test5a=0;
|
||||||
|
%let test5b=1;
|
||||||
|
data _null_;
|
||||||
|
set myhash;
|
||||||
|
call symputx('test5a',hashkey);
|
||||||
|
run;
|
||||||
|
data _null_;
|
||||||
|
set myhash2;
|
||||||
|
call symputx('test5b',hashkey);
|
||||||
|
run;
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test5a"="&test5b"),
|
||||||
|
desc=Ensuring binary copy works on binary characters,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|||||||
52
tests/serveronly/ms_adduser2group.test.sas
Normal file
52
tests/serveronly/ms_adduser2group.test.sas
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_adduser2group.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquename.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
@li ms_adduser2group.sas
|
||||||
|
@li ms_creategroup.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
/* first, create an empty group */
|
||||||
|
%let group=%substr(%mf_getuniquename(),1,8);
|
||||||
|
%ms_creategroup(&group, desc=The description,mdebug=&sasjs_mdebug,outds=test1a)
|
||||||
|
%let groupid=0;
|
||||||
|
data _null_;
|
||||||
|
set work.test1a;
|
||||||
|
call symputx('groupid',groupid);
|
||||||
|
run;
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&groupid>0),
|
||||||
|
desc=Checking that group was created with an ID,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* now add a user (user 1 always exists) */
|
||||||
|
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%ms_adduser2group(uid=1,gid=&groupid,mdebug=&sasjs_mdebug,outds=test1)
|
||||||
|
%mp_assertscope(COMPARE
|
||||||
|
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
|
||||||
|
)
|
||||||
|
|
||||||
|
/* check the user is in the output list */
|
||||||
|
%let checkid=0;
|
||||||
|
data _null_;
|
||||||
|
set work.test1;
|
||||||
|
if id=1 then call symputx('checkid',1);
|
||||||
|
run;
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&checkid=1),
|
||||||
|
desc=Checking that user was created in the new group,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ run;
|
|||||||
%let checkid=0;
|
%let checkid=0;
|
||||||
data _null_;
|
data _null_;
|
||||||
set work.test2;
|
set work.test2;
|
||||||
where name="&group";
|
where upcase(name)="%upcase(&group)";
|
||||||
call symputx('checkid',groupid);
|
call symputx('checkid',groupid);
|
||||||
run;
|
run;
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
data _null_;
|
data _null_;
|
||||||
set work.test1;
|
set work.test1;
|
||||||
call symputx('id',id);
|
call symputx('id',id);
|
||||||
|
putlog (_all_)(=);
|
||||||
run;
|
run;
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&id>0),
|
iftrue=(&id>0),
|
||||||
@@ -35,7 +36,8 @@ run;
|
|||||||
%let checkid=0;
|
%let checkid=0;
|
||||||
data _null_;
|
data _null_;
|
||||||
set work.test2;
|
set work.test2;
|
||||||
where username="&user";
|
if _n_<20 then putlog (_all_)(=);
|
||||||
|
if upcase(username)="%upcase(&user)";
|
||||||
call symputx('checkid',id);
|
call symputx('checkid',id);
|
||||||
run;
|
run;
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
|
|||||||
@@ -3,21 +3,64 @@
|
|||||||
@brief Testing ms_getgroups.sas macro
|
@brief Testing ms_getgroups.sas macro
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquename.sas
|
||||||
|
@li ms_adduser2group.sas
|
||||||
|
@li ms_creategroup.sas
|
||||||
@li ms_getgroups.sas
|
@li ms_getgroups.sas
|
||||||
|
@li mp_assert.sas
|
||||||
@li mp_assertdsobs.sas
|
@li mp_assertdsobs.sas
|
||||||
@li mp_assertscope.sas
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
/* create a group */
|
||||||
|
%let group=%substr(%mf_getuniquename(),1,8);
|
||||||
|
%ms_creategroup(&group, desc=The description,mdebug=&sasjs_mdebug,outds=test1)
|
||||||
|
|
||||||
|
/* get groups */
|
||||||
%mp_assertscope(SNAPSHOT)
|
%mp_assertscope(SNAPSHOT)
|
||||||
%ms_getgroups(outds=work.test1,mdebug=&sasjs_mdebug)
|
%ms_getgroups(outds=work.test1,mdebug=&sasjs_mdebug)
|
||||||
%mp_assertscope(COMPARE
|
%mp_assertscope(COMPARE
|
||||||
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
|
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* check the group was created */
|
||||||
%mp_assertdsobs(work.test1,test=ATLEAST 1)
|
%mp_assertdsobs(work.test1,test=ATLEAST 1)
|
||||||
|
|
||||||
|
%let test2=0;
|
||||||
|
%put &=group;
|
||||||
|
data _null_;
|
||||||
|
set work.test1;
|
||||||
|
putlog (_all_)(=);
|
||||||
|
if upcase(name)="%upcase(&group)" then do;
|
||||||
|
putlog "&group found!";
|
||||||
|
call symputx('test2',1);
|
||||||
|
call symputx('gid',groupid); /* used in next test */
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test2"="1"),
|
||||||
|
desc=Checking group was created,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/* now check if the filter for the groups for a user works */
|
||||||
|
|
||||||
|
/* add a member */
|
||||||
|
%ms_adduser2group(uid=1,gid=&gid)
|
||||||
|
|
||||||
|
%ms_getgroups(user=secretuser,outds=work.test3)
|
||||||
|
|
||||||
|
%let test3=0;
|
||||||
|
data _null_;
|
||||||
|
set work.test3;
|
||||||
|
if groupid=&gid then call symputx('test3',1);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test3"="1"),
|
||||||
|
desc=Checking group list was returned for a user,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
@brief Testing ms_getusers.sas macro
|
@brief Testing ms_getusers.sas macro
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li ms_creategroup.sas
|
||||||
|
@li ms_adduser2group.sas
|
||||||
@li ms_getusers.sas
|
@li ms_getusers.sas
|
||||||
@li mp_assertdsobs.sas
|
@li mp_assertdsobs.sas
|
||||||
@li mp_assertscope.sas
|
@li mp_assertscope.sas
|
||||||
@@ -18,6 +20,39 @@
|
|||||||
|
|
||||||
%mp_assertdsobs(work.test1,test=ATLEAST 1)
|
%mp_assertdsobs(work.test1,test=ATLEAST 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test the extraction of group members
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* create a group */
|
||||||
|
%let group=%substr(%mf_getuniquename(),1,8);
|
||||||
|
%ms_creategroup(&group, desc=some desc,mdebug=&sasjs_mdebug,outds=work.group)
|
||||||
|
%let gid=0;
|
||||||
|
data _null_;
|
||||||
|
set work.group;
|
||||||
|
call symputx('gid',groupid);
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* add a member */
|
||||||
|
%ms_adduser2group(uid=1,gid=&gid)
|
||||||
|
|
||||||
|
/* extract the members */
|
||||||
|
%ms_getusers(group=&group,outds=test2)
|
||||||
|
|
||||||
|
/* check the user is in the output list */
|
||||||
|
%let checkid=0;
|
||||||
|
data _null_;
|
||||||
|
set work.test2;
|
||||||
|
if id=1 then call symputx('checkid',1);
|
||||||
|
run;
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&checkid=1),
|
||||||
|
desc=Checking that admin user was created in the new group,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ options mprint;
|
|||||||
)
|
)
|
||||||
%mp_assertscope(COMPARE)
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
libname webeen json (weboot);
|
libname webeen json fileref=weboot;
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile weboot;
|
infile weboot;
|
||||||
|
|||||||
@@ -10,7 +10,12 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
filename ft15f001 temp;
|
filename ft15f001 temp;
|
||||||
parmcards4;
|
data _null_;
|
||||||
|
file ft15f001;
|
||||||
|
infile cards;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
cards4;
|
||||||
%put Initialising sendObj: ;
|
%put Initialising sendObj: ;
|
||||||
%put _all_;
|
%put _all_;
|
||||||
%webout(FETCH)
|
%webout(FETCH)
|
||||||
@@ -27,6 +32,7 @@ parmcards4;
|
|||||||
%mend x; %x()
|
%mend x; %x()
|
||||||
%webout(CLOSE)
|
%webout(CLOSE)
|
||||||
;;;;
|
;;;;
|
||||||
|
run;
|
||||||
%put creating web service: &mcTestAppLoc/services;
|
%put creating web service: &mcTestAppLoc/services;
|
||||||
%ms_createwebservice(
|
%ms_createwebservice(
|
||||||
path=&mcTestAppLoc/services,
|
path=&mcTestAppLoc/services,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ run;
|
|||||||
%ms_webout(OBJ,datasets,fref=&fref)
|
%ms_webout(OBJ,datasets,fref=&fref)
|
||||||
%ms_webout(CLOSE,fref=&fref)
|
%ms_webout(CLOSE,fref=&fref)
|
||||||
|
|
||||||
libname test JSON (&fref);
|
libname test JSON fileref=&fref;
|
||||||
data root;
|
data root;
|
||||||
set test.root;
|
set test.root;
|
||||||
call symputx('checkval',sysvlong);
|
call symputx('checkval',sysvlong);
|
||||||
|
|||||||
@@ -252,9 +252,23 @@ data _null_;
|
|||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%else %if (&action=ARR or &action=OBJ) %then %do; ';
|
put '%else %if (&action=ARR or &action=OBJ) %then %do; ';
|
||||||
|
put ' /* force variable names to always be uppercase in the JSON */ ';
|
||||||
put ' options validvarname=upcase; ';
|
put ' options validvarname=upcase; ';
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
put ' /* To avoid issues with _webout on EBI - such as encoding diffs and truncation ';
|
||||||
|
put ' (https://support.sas.com/kb/49/325.html) we use temporary files */ ';
|
||||||
|
put ' filename _sjs1 temp lrecl=200 ; ';
|
||||||
|
put ' data _null_; file _sjs1 encoding=''utf-8''; ';
|
||||||
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
|
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' /* now write to _webout 1 char at a time */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs1 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs1 clear; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' /* grab col defs */ ';
|
put ' /* grab col defs */ ';
|
||||||
put ' proc contents noprint data=&ds ';
|
put ' proc contents noprint data=&ds ';
|
||||||
@@ -311,10 +325,20 @@ data _null_;
|
|||||||
put ' data &tempds;set &ds; ';
|
put ' data &tempds;set &ds; ';
|
||||||
put ' %if &fmt=N %then format _numeric_ best32.;; ';
|
put ' %if &fmt=N %then format _numeric_ best32.;; ';
|
||||||
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
|
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
|
||||||
put ' proc json out=&jref pretty ';
|
put ' filename _sjs2 temp lrecl=131068 encoding=''utf-8''; ';
|
||||||
|
put ' proc json out=_sjs2 pretty ';
|
||||||
put ' %if &action=ARR %then nokeys ; ';
|
put ' %if &action=ARR %then nokeys ; ';
|
||||||
put ' ;export &tempds / nosastags fmtnumeric; ';
|
put ' ;export &tempds / nosastags fmtnumeric; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
|
put ' /* send back to webout */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs2 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs2 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %else %if &engine=DATASTEP %then %do; ';
|
put ' %else %if &engine=DATASTEP %then %do; ';
|
||||||
put ' %datastep: ';
|
put ' %datastep: ';
|
||||||
@@ -397,10 +421,9 @@ data _null_;
|
|||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' /* write to temp loc to avoid _webout truncation ';
|
put ' filename _sjs3 temp lrecl=131068 ; ';
|
||||||
put ' - https://support.sas.com/kb/49/325.html */ ';
|
put ' data _null_; ';
|
||||||
put ' filename _sjs temp lrecl=131068 encoding=''utf-8''; ';
|
put ' file _sjs3 encoding=''utf-8''; ';
|
||||||
put ' data _null_; file _sjs lrecl=131068 encoding=''utf-8'' mod ; ';
|
|
||||||
put ' if _n_=1 then put "["; ';
|
put ' if _n_=1 then put "["; ';
|
||||||
put ' set &tempds; ';
|
put ' set &tempds; ';
|
||||||
put ' if _n_>1 then put "," @; put ';
|
put ' if _n_>1 then put "," @; put ';
|
||||||
@@ -411,36 +434,34 @@ data _null_;
|
|||||||
put ' "&&name&i"n /* name literal for reserved variable names */ ';
|
put ' "&&name&i"n /* name literal for reserved variable names */ ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
|
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
|
||||||
put ' /* now write the long strings to _webout 1 byte at a time */ ';
|
put ' ';
|
||||||
put ' data _null_; ';
|
|
||||||
put ' length filein 8 fileid 8; ';
|
|
||||||
put ' filein=fopen("_sjs",''I'',1,''B''); ';
|
|
||||||
put ' fileid=fopen("&jref",''A'',1,''B''); ';
|
|
||||||
put ' rec=''20''x; ';
|
|
||||||
put ' do while(fread(filein)=0); ';
|
|
||||||
put ' rc=fget(filein,rec,1); ';
|
|
||||||
put ' rc=fput(fileid, rec); ';
|
|
||||||
put ' rc=fwrite(fileid); ';
|
|
||||||
put ' end; ';
|
|
||||||
put ' /* close out the table */ ';
|
put ' /* close out the table */ ';
|
||||||
put ' rc=fput(fileid, "]"); ';
|
put ' data _null_; ';
|
||||||
put ' rc=fwrite(fileid); ';
|
put ' file _sjs3 mod encoding=''utf-8''; ';
|
||||||
put ' rc=fclose(filein); ';
|
put ' put '']''; ';
|
||||||
put ' rc=fclose(fileid); ';
|
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put ' filename _sjs clear; ';
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs3 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs3 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' proc sql; ';
|
put ' proc sql; ';
|
||||||
put ' drop table &colinfo, &tempds; ';
|
put ' drop table &colinfo, &tempds; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' %if &showmeta=YES %then %do; ';
|
put ' %if &showmeta=YES %then %do; ';
|
||||||
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
put ' filename _sjs4 temp lrecl=131068 encoding=''utf-8''; ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' file _sjs4; ';
|
||||||
put ' put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{"; ';
|
put ' put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{"; ';
|
||||||
put ' do i=1 to &numcols; ';
|
put ' do i=1 to &numcols; ';
|
||||||
put ' name=quote(trim(symget(cats(''name'',i)))); ';
|
put ' name=quote(trim(symget(cats(''name'',i)))); ';
|
||||||
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
|
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
|
||||||
put ' label=quote(trim(symget(cats(''label'',i)))); ';
|
put ' label=quote(prxchange(''s/\\/\\\\/'',-1,trim(symget(cats(''label'',i))))); ';
|
||||||
put ' length=quote(trim(symget(cats(''length'',i)))); ';
|
put ' length=quote(trim(symget(cats(''length'',i)))); ';
|
||||||
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
|
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
|
||||||
put ' if i>1 then put "," @@; ';
|
put ' if i>1 then put "," @@; ';
|
||||||
@@ -449,6 +470,15 @@ data _null_;
|
|||||||
put ' end; ';
|
put ' end; ';
|
||||||
put ' put ''}}''; ';
|
put ' put ''}}''; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
|
put ' /* send back to webout */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile _sjs4 lrecl=1 recfm=n; ';
|
||||||
|
put ' file &jref mod lrecl=1 recfm=n; ';
|
||||||
|
put ' input sourcechar $char1. @@; ';
|
||||||
|
put ' format sourcechar hex2.; ';
|
||||||
|
put ' put sourcechar char1. @@; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs4 clear; ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
@@ -459,18 +489,19 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%mend mp_jsonout; ';
|
put '%mend mp_jsonout; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%macro mf_getuser(type=META ';
|
put '%macro mf_getuser( ';
|
||||||
put ')/*/STORE SOURCE*/; ';
|
put ')/*/STORE SOURCE*/; ';
|
||||||
put ' %local user metavar; ';
|
put ' %local user; ';
|
||||||
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
|
||||||
put ' %else %let metavar=_metaperson; ';
|
|
||||||
put ' ';
|
put ' ';
|
||||||
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
put ' %if %symexist(_sasjs_username) %then %let user=&_sasjs_username; ';
|
||||||
put ' %else %if %symexist(&metavar) %then %do; ';
|
put ' %else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do; ';
|
||||||
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
put ' %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %if %symexist(_metaperson) %then %do; ';
|
||||||
|
put ' %if %length(&_metaperson)=0 %then %let user=&sysuserid; ';
|
||||||
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
||||||
put ' /* but be sure to quote in case of usernames with commas */ ';
|
put ' /* but be sure to quote in case of usernames with commas */ ';
|
||||||
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
put ' %else %let user=%unquote(%scan(%quote(&_metaperson),1,@)); ';
|
||||||
put ' %end; ';
|
put ' %end; ';
|
||||||
put ' %else %let user=&sysuserid; ';
|
put ' %else %let user=&sysuserid; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
|
|||||||
Reference in New Issue
Block a user