1
0
mirror of https://github.com/sasjs/core.git synced 2026-01-05 16:40:06 +00:00

Compare commits

...

32 Commits

Author SHA1 Message Date
Allan Bowe
2bdb90b0be Merge pull request #255 from sasjs/allanbowe/mp-abort-fails-on-windows-254
fix: handling embedded speechmarks in SYSPROCESSNAME.  Closes #254
2022-06-17 14:32:02 +02:00
Allan Bowe
2cd846d504 fix: handling embedded speechmarks in SYSPROCESSNAME. Closes #254 2022-06-17 12:30:40 +00:00
Allan Bowe
f593c7bec9 fix: returning user list (single user) in desktop mode in ms_getusers() 2022-06-17 07:52:39 +00:00
Allan Bowe
c8805db0b5 feat: filter for groups by user id in ms_getgroups 2022-06-17 07:46:51 +00:00
Allan Bowe
1eb6d8cec9 feat: enabling user list by group id as well as name 2022-06-17 07:16:57 +00:00
Allan Bowe
ed19ee03af Merge pull request #253 from sasjs/servergroups
feat: enabling group macros on sasjs/server
2022-06-16 13:40:36 +02:00
Allan Bowe
a1c931b5e6 fix: tests with new APIs are now passing 2022-06-16 11:37:31 +00:00
Allan Bowe
cb553a31ab fix: failing test for filtering groups for a particular user (api isn't ready yet) 2022-06-14 19:37:06 +00:00
Allan Bowe
557df272ff fix: using new user/by/username api in sasjs/server 2022-06-14 19:24:41 +00:00
Allan Bowe
0cb3c96c15 feat: enabling group macros on sasjs/server
This PR updates ms_getgroups with a user filter, and ms_getusers with a group filter. ms_adduser2group was also created to faciliate the necessary test(s).
2022-06-14 13:40:05 +00:00
Allan Bowe
1cb39d4d61 Merge pull request #252 from sasjs/allanbowe/ms-getgroups-fails-in-251
fix: creating empty table in desktop mode (ms_getgroups)
2022-06-11 21:30:03 +02:00
Allan Bowe
934b7d4f8a fix: creating empty table in desktop mode (ms_getgroups) 2022-06-11 19:29:21 +00:00
Allan Bowe
24c50cde56 fix: use options nobomfile for sasjs server mp_abort, also doc update in mf_existvarlist 2022-06-09 22:16:34 +00:00
Allan Bowe
055e8d2f13 fix: setting header in mp_abort for sasjs server 2022-06-07 14:01:54 +00:00
Allan Bowe
abfe7fe339 fix: no json wrapper in SASjs mode in mp_abort.sas 2022-06-07 11:28:59 +00:00
Allan Bowe
16ed91f6a9 fix: mp_abort on windows m6+ 2022-06-06 11:28:37 +00:00
Allan Bowe
67ba2a5286 fix: mp_abort on m6 win needs endsas 2022-06-03 17:45:27 +00:00
Allan Bowe
3d7f9b71e1 fix: hard abort in mm_getstpcode when the stp does not exist 2022-06-02 17:50:50 +00:00
Allan Bowe
1d972fad11 fix: using outref instead of outloc in mm_getstpcode invocation from mx_getcode 2022-05-31 22:42:40 +00:00
Allan Bowe
e23bc461c4 fix: mx_getcode platform support 2022-05-31 22:00:58 +00:00
Allan Bowe
28ed458b83 Merge pull request #250 from sasjs/allanbowe/mp-jsonout-needs-to-support-249
fix: enable reserved names in mp_jsonout.  Closes #249
2022-05-31 16:48:45 +03:00
Allan Bowe
827210e010 fix: enable reserved names in mp_jsonout. Closes #249 2022-05-31 13:48:09 +00:00
Allan Bowe
de2f32da36 Merge pull request #248 from sasjs/mm_createdataset_update
fix: cater for case of zero cols in mm_createdataset.sas
2022-05-31 14:02:13 +03:00
Allan Bowe
6fa0fc5dc6 fix: cater for case of zero cols in mm_createdataset.sas 2022-05-31 11:01:06 +00:00
Allan Bowe
73e3d9d419 Merge pull request #247 from sasjs/allanbowe/mp-abort-on-sasjs-server-246
fix: ensuring webout on abort, closes #246
2022-05-30 15:42:47 +03:00
Allan Bowe
5f2229e3d5 fix: ensuring webout on abort, closes #246 2022-05-30 12:38:34 +00:00
Allan Bowe
d19c4a517c chore: updated document header 2022-05-20 19:01:47 +00:00
munja
c47480f60c fix: space in dependencies 2022-05-20 12:55:39 +01:00
munja
295211bb72 fix: doc config and test-folders 2022-05-20 11:30:38 +01:00
Allan Bowe
818bc3cc2b Merge pull request #244 from sasjs/getcode
feat: creating new mx_ suite of macros!
2022-05-20 13:18:16 +03:00
munja
bb6111e2b3 fix: all.sas, readme, dependency issue and sasjsconfig file 2022-05-20 11:16:30 +01:00
munja
512f05c0b2 feat: creating new mx_ suite of macros!
also adding new mx_getcode macro
2022-05-19 22:02:19 +01:00
125 changed files with 1935 additions and 965 deletions

View File

@@ -31,14 +31,14 @@ Documentation: https://core.sasjs.io
## Components
### BASE library (All Platforms)
### BASE folder (All Platforms)
- OS independent
- Works on all SAS Platforms
- No X command
- Prefixes: _mf_, _mp_
### DDL library (All Platforms)
### DDL folder (All Platforms)
- OS independent
- Works on all SAS Platforms
@@ -47,46 +47,14 @@ Documentation: https://core.sasjs.io
This library will not be used for storing data entries (such as formats or datalines). Where this becomes necessary in the future, a new repo will be created, in order to keep the NPM bundle size down (for the benefit of those looking to embed purely macros in their applications).
### FCMP library (All Platforms)
### FCMP folder (All Platforms)
- Function and macro names are identical, except for special cases
- Prefixes: _mcf_
The fcmp macros are used to generate fcmp functions, and can be used with or without the `proc fcmp` wrapper.
### META library (SAS9 only)
Macros used in SAS EBI, which connect to the metadata server.
- OS independent
- Metadata aware
- No X command
- Prefixes: _mm_
### SERVER library (@sasjs/server only)
These macros are used for building applications using [@sasjs/server](https://server.sasjs.io) - an open source REST API for Desktop SAS.
- OS independent
- @sasjs/server aware
- No X command
- Prefixes: _ms_
### VIYA library (Viya only)
Macros used for interfacing with SAS Viya.
- OS independent
- No X command
- Prefixes: _mv_, _mvf_
### METAX library (SAS9 only)
- OS specific
- Metadata aware
- X command enabled
- Prefixes: _mmw_,_mmu_,_mmx_
### LUA library
### LUA folder
Wait - this is a macro library - what is LUA doing here? Well, it is a little known fact that you CAN run LUA within a SAS Macro. It has to be written to a text file with a `.lua` extension, from where you can `%include` it. So, without using the `proc lua` wrapper.
@@ -106,13 +74,61 @@ run;
- Prefixes: _ml_
### META folder (SAS9 only)
Macros used in SAS EBI, which connect to the metadata server.
- OS independent
- Metadata aware
- No X command
- Prefixes: _mm_
### METAX folder (SAS9 only)
- OS specific
- Metadata aware
- X command enabled
- Prefixes: _mmw_,_mmu_,_mmx_
### SERVER folder (@sasjs/server only)
These macros are used for building applications using [@sasjs/server](https://server.sasjs.io) - an open source REST API for Desktop SAS.
- OS independent
- @sasjs/server aware
- No X command
- Prefixes: _ms_
### VIYA folder (Viya only)
Macros used for interfacing with SAS Viya.
- OS independent
- No X command
- Prefixes: _mv_, _mvf_
### XPLATFORM folder (Viya, Meta, and Server)
Sometimes it is helpful to use a macro that can be used interchangeably regardless of the server type on which is is running (SASVIYA, SAS9, SASJS).
- OS independent
- No X command
- Prefixes: _mx_
## Installation
First, download the repo to a location your SAS system can access. Then update your sasautos path to include the components you wish to have available, eg:
```sas
options insert=(sasautos="/your/path/macrocore/base");
options insert=(sasautos="/your/path/macrocore/meta");
%let repoloc=/your/path/core;
options insert=(sasautos="&repoloc/base");
options insert=(sasautos="&repoloc/ddl");
options insert=(sasautos="&repoloc/fcmp");
options insert=(sasautos="&repoloc/lua");
options insert=(sasautos="&repoloc/meta");
options insert=(sasautos="&repoloc/metax");
options insert=(sasautos="&repoloc/server");
options insert=(sasautos="&repoloc/viya");
options insert=(sasautos="&repoloc/xplatform");
```
The above can be done directly in your sas program, via an autoexec, or an initialisation program.
@@ -142,7 +158,7 @@ filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
- _mp_ for macro procedures (which generate sas code)
- _ms_ for macro procedures that will only work with [@sasjs/server](https://github.com/sasjs/server)
- _mv_ for macro procedures that will only work in Viya
- _mx_ for macros that are XCMD enabled (working on both windows and unix)
- _mx_ for macros that work on Viya, SAS 9 EBI and SASjs Server
- follow verb-noun convention
- unix style line endings (lf)
- individual lines should be no more than 80 characters long

1212
all.sas

File diff suppressed because it is too large Load Diff

View File

@@ -6,9 +6,6 @@
%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 varlist space separated variable names

View File

@@ -5,8 +5,12 @@
%put %mf_getplatform();
returns:
SASMETA (or SASVIYA)
returns one of:
@li SASMETA
@li SASVIYA
@li SASJS
@li BASESAS
@param switch the param for which to return a platform specific variable

View File

@@ -15,16 +15,20 @@
recognise this and fetch the log of the parent session instead)
@li STP environments must finish cleanly to avoid the log being sent to
_webout. To assist with this, we also run stpsrvset('program error', 0)
and set SYSCC=0. We take a unique "soft abort" approach - we open a macro
and set SYSCC=0.
Where possible, we take a unique "soft abort" approach - we open a macro
but don't close it! This works everywhere EXCEPT inside a \%include inside
a macro. For that, we recommend you use mp_include.sas to perform the
include, and then call \%mp_abort(mode=INCLUDE) from the source program (ie,
OUTSIDE of the top-parent macro).
The soft abort has also been found to be ineffective in 9.4m6 windows
environments and above, so in these cases, endsas is used.
@param mac= to contain the name of the calling macro
@param mac= (mp_abort.sas) To contain the name of the calling macro. Do not
use &sysmacroname as this will always resolve to MP_ABORT.
@param msg= message to be returned
@param iftrue= supply a condition under which the macro should be executed.
@param iftrue= (1=1) Supply a condition for which the macro should be executed
@param errds= (work.mp_abort_errds) There is no clean way to end a process
within a %include called within a macro. Furthermore, there is no way to
test if a macro is called within a %include. To handle this particular
@@ -45,11 +49,12 @@
@li REGULAR (default)
@li INCLUDE
@version 9.4
@author Allan Bowe
<h4> Related Macros </h4>
@li mp_include.sas
@version 9.4
@author Allan Bowe
@cond
**/
@@ -58,7 +63,8 @@
, mode=REGULAR
)/*/STORE SOURCE*/;
%global sysprocessmode sysprocessname;
%global sysprocessmode sysprocessname sasjs_stpsrv_header_loc;
%local fref fid i;
%if not(%eval(%unquote(&iftrue))) %then %return;
@@ -68,7 +74,7 @@
%if %symexist(_SYSINCLUDEFILEDEVICE)
/* abort cancel FILE does not restart outside the INCLUDE on Viya 3.5 */
and "&SYSPROCESSNAME " ne "Compute Server "
and %str(&SYSPROCESSNAME) ne %str(Compute Server)
%then %do;
%if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do;
data &errds;
@@ -84,9 +90,9 @@
%end;
%end;
/* Stored Process Server web app context */
%if %symexist(_METAFOLDER)
or "&SYSPROCESSNAME "="Compute Server "
/* Web App Context */
%if %symexist(_PROGRAM)
or %str(&SYSPROCESSNAME) = %str(Compute Server)
or &mode=INCLUDE
%then %do;
options obs=max replace mprint;
@@ -152,8 +158,8 @@
%end;
%if %symexist(SYS_JES_JOB_URI) %then %do;
/* setup webout */
OPTIONS NOBOMFILE;
/* setup webout for Viya */
options nobomfile;
%if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
filename _webout temp lrecl=999999 mod;
%end;
@@ -162,11 +168,24 @@
name="_webout.json" lrecl=999999 mod;
%end;
%end;
%else %if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc))=0 %then %do;
options nobomfile;
/* set up http header for SASjs Server */
%let fid=%sysfunc(fopen(&fref,A));
%if &fid=0 %then %do;
%put %str(ERR)OR: %sysfunc(sysmsg());
%return;
%end;
%let rc=%sysfunc(fput(&fid,%str(Content-Type: application/json)));
%let rc=%sysfunc(fwrite(&fid));
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(&fref));
%end;
/* send response in SASjs JSON format */
data _null_;
file _webout mod lrecl=32000 encoding='utf-8';
length msg syswarningtext syserrortext $32767 ;
length msg syswarningtext syserrortext $32767 mode $10 ;
sasdatetime=datetime();
msg=symget('msg');
%if &logline>0 %then %do;
@@ -182,7 +201,8 @@
msg=cats('"',msg,'"');
if symexist('_debug') then debug=quote(trim(symget('_debug')));
else debug='""';
put '>>weboutBEGIN<<';
if symget('sasjsprocessmode')='Stored Program' then mode='SASJS';
if mode ne 'SASJS' then put '>>weboutBEGIN<<';
put '{"SYSDATE" : "' "&SYSDATE" '"';
put ',"SYSTIME" : "' "&SYSTIME" '"';
put ',"sasjsAbort" : [{';
@@ -214,8 +234,8 @@
syswarningtext=quote(trim(symget('syswarningtext')));
put ",""SYSWARNINGTEXT"" : " syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
put "}" @;
put '>>weboutEND<<';
put "}" ;
if mode ne 'SASJS' then put '>>weboutEND<<';
run;
%put _all_;
@@ -226,6 +246,13 @@
rc=stpsrvset('program error', 0);
call symputx("syscc",0,"g");
run;
%if &sysscp=WIN
and "%substr(%str(&sysvlong ),1,8)"="9.04.01M"
and "%substr(%str(&sysvlong ),9,1)">"5" %then %do;
/* skip approach (below) does not work in windows m6+ envs */
endsas;
%end;
%else %do;
/**
* endsas kills 9.4m3 deployments by orphaning multibridges.
* Abort variants are ungraceful (non zero return code)
@@ -243,6 +270,7 @@
run;
%inc skip;
%end;
%end;
%else %if "&sysprocessmode " = "SAS Compute Server " %then %do;
/* endsas kills the session making it harder to fetch results */
data _null_;

View File

@@ -30,6 +30,7 @@
@li mddl_dc_filtersummary.sas
@li mddl_dc_locktable.sas
@li mddl_dc_maxkeytable.sas
@li mf_getuniquename.sas
<h4> Related Macros </h4>
@li mp_filterstore.sas
@@ -46,7 +47,7 @@
%macro mp_coretable(table_ref,libds=0
)/*/STORE SOURCE*/;
%local outds ;
%let outds=%sysfunc(ifc(&libds=0,_data_,&libds));
%let outds=%sysfunc(ifc(&libds=0,%mf_getuniquename(),&libds));
proc sql;
%if &table_ref=DIFFTABLE %then %do;
%mddl_dc_difftable(libds=&outds)

View File

@@ -1,50 +1,13 @@
/**
@file mp_createwebservice.sas
@brief Create a web service in SAS 9 or Viya
@details Creates a SASJS ready Stored Process in SAS 9 or Job Execution
Service in SAS Viya
@brief Create a web service in SAS 9, Viya or SASjs Server
@details This is actually a wrapper for mx_createwebservice.sas, remaining
for legacy purposes. For new apps, use mx_createwebservice.sas.
Usage:
%* compile macros ;
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
%* write some code;
filename ft15f001 temp;
parmcards4;
%* fetch any data from frontend ;
%webout(FETCH)
data example1 example2;
set sashelp.class;
run;
%* send data back;
%webout(OPEN)
%webout(ARR,example1) * Array format, fast, suitable for large tables ;
%webout(OBJ,example2) * Object format, easier to work with ;
%webout(CLOSE)
;;;;
%mp_createwebservice(path=/Public/app/common,name=appInit,replace=YES)
<h4> SAS Macros </h4>
@li mf_getplatform.sas
@li mm_createwebservice.sas
@li ms_createwebservice.sas
@li mv_createwebservice.sas
@li mx_createwebservice.sas
@param [in,out] path= The full folder path where the service will be created
@param [in,out] name= Service name. Avoid spaces.
@param [in] desc= The description of the service (optional)
@param [in] precode= Space separated list of filerefs, pointing to the code
that needs to be attached to the beginning of the service (optional)
@param [in] code= (ft15f001) Space seperated fileref(s) of the actual code to
be added
@param [in] replace= (YES) Select YES to replace any existing service in that
location
@param [in] mDebug= (0) set to 1 to show debug messages in the log
@version 9.2
@author Allan Bowe
**/
@@ -57,40 +20,13 @@ Usage:
,mdebug=0
)/*/STORE SOURCE*/;
%if &syscc ge 4 %then %do;
%put syscc=&syscc - &sysmacroname will not execute in this state;
%return;
%end;
%local platform; %let platform=%mf_getplatform();
%if &platform=SASVIYA %then %do;
%if "&path"="HOME" %then %let path=/Users/&sysuserid/My Folder;
%mv_createwebservice(path=&path
%mx_createwebservice(path=&path
,name=&name
,code=&code
,precode=&precode
,code=&code
,desc=&desc
,replace=&replace
)
%end;
%else %if &platform=SASJS %then %do;
%if "&path"="HOME" %then %let path=/Users/&_sasjs_username/My Folder;
%ms_createwebservice(path=&path
,name=&name
,code=&code
,precode=&precode
,mdebug=&mdebug
)
%end;
%else %do;
%if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder;
%mm_createwebservice(path=&path
,name=&name
,code=&code
,precode=&precode
,desc=&desc
,replace=&replace
)
%end;
%mend mp_createwebservice;

View File

@@ -231,7 +231,7 @@
%do i=1 %to &numcols;
%if &i>1 %then "," ;
%if &action=OBJ %then """&&name&i"":" ;
&&name&i
"&&name&i"n /* name literal for reserved variable names */
%end;
%if &action=ARR %then "]" ; %else "}" ; ;
/* now write the long strings to _webout 1 byte at a time */

View File

@@ -1,53 +1,11 @@
/**
@file
@brief Will execute a SASjs web service on SAS 9 or Viya
@details Prepares the input files and retrieves the resulting datasets from
the response JSON.
Note - the _webout fileref should NOT be assigned prior to running this macro.
@param [in] program The _PROGRAM endpoint to test
@param [in] inputfiles=(0) A list of space seperated fileref:filename pairs as
follows:
inputfiles=inref:filename inref2:filename2
@param [in] inputdatasets= (0) All datasets in this space seperated list are
converted into SASJS-formatted CSVs (see mp_ds2csv.sas) files and added to
the list of `inputfiles` for ingestion. The dataset will be sent with the
same name (no need for a colon modifier).
@param [in] inputparams=(0) A dataset containing name/value pairs in the
following format:
|name:$32|value:$1000|
|---|---|
|stpmacname|some value|
|mustbevalidname|can be anything, oops, %abort!!|
@param [in] debug= (log) Provide the _debug value
@param [in] mdebug= (0) Set to 1 to provide macro debugging
@param [in] viyaresult= (WEBOUT_JSON) The Viya result type to return. For
more info, see mv_getjobresult.sas
@param [in] viyacontext= (SAS Job Execution compute context) The Viya compute
context on which to run the service
@param [out] outlib= (0) Output libref to contain the final tables. Set to
0 if the service output is not in JSON format.
@param [out] outref= (0) Output fileref to create, to contain the full _webout
response.
@brief To be deprecated. Will execute a SASjs web service on SAS 9 or Viya
@details Use the mx_testservice.sas macro instead (documentation can be
found there)
<h4> SAS Macros </h4>
@li mf_getplatform.sas
@li mf_getuniquefileref.sas
@li mf_getuniquename.sas
@li mp_abort.sas
@li mp_binarycopy.sas
@li mp_chop.sas
@li mp_ds2csv.sas
@li ms_testservice.sas
@li mv_getjobresult.sas
@li mv_jobflow.sas
<h4> Related Programs </h4>
@li mp_testservice.test.sas
@li mx_testservice.sas
@version 9.4
@author Allan Bowe
@@ -65,237 +23,17 @@
viyaresult=WEBOUT_JSON,
viyacontext=SAS Job Execution compute context
)/*/STORE SOURCE*/;
%local dbg pcnt fref1 fref2 webref webrefpath i webcount var platform;
%if &mdebug=1 %then %do;
%put &sysmacroname entry vars:;
%put _local_;
%end;
%else %let dbg=*;
/* sanitise inputparams */
%let pcnt=0;
%if &inputparams ne 0 %then %do;
data _null_;
set &inputparams;
if not nvalid(name,'v7') then putlog (_all_)(=);
else if name in (
'program','inputfiles','inputparams','debug','outlib','outref'
) then putlog (_all_)(=);
else do;
x+1;
call symputx(name,quote(cats(value)),'l');
call symputx(cats('pval',x),name,'l');
call symputx('pcnt',x,'l');
end;
run;
%mp_abort(iftrue= (%mf_nobs(&inputparams) ne &pcnt)
,mac=&sysmacroname
,msg=%str(Invalid values in &inputparams)
)
%end;
/* convert inputdatasets to filerefs */
%if "&inputdatasets" ne "0" %then %do;
%if %quote(&inputfiles)=0 %then %let inputfiles=;
%do i=1 %to %sysfunc(countw(&inputdatasets,%str( )));
%let var=%scan(&inputdatasets,&i,%str( ));
%local dsref&i;
%let dsref&i=%mf_getuniquefileref();
%mp_ds2csv(&var,outref=&&dsref&i,headerformat=SASJS)
%let inputfiles=&inputfiles &&dsref&i:%scan(&var,-1,.);
%end;
%end;
%let platform=%mf_getplatform();
%let fref1=%mf_getuniquefileref();
%let fref2=%mf_getuniquefileref();
%let webref=%mf_getuniquefileref();
%let webrefpath=%sysfunc(pathname(work))/%mf_getuniquename();
/* mp_chop requires a physical path as input */
filename &webref "&webrefpath";
%if &platform=SASMETA %then %do;
/* parse the input files */
%if %quote(&inputfiles) ne 0 %then %do;
%let webcount=%sysfunc(countw(&inputfiles));
%put &=webcount;
%do i=1 %to &webcount;
%let var=%scan(&inputfiles,&i,%str( ));
%local webfref&i webname&i;
%let webref&i=%scan(&var,1,%str(:));
%let webname&i=%scan(&var,2,%str(:));
%put webref&i=&&webref&i;
%put webname&i=&&webname&i;
%end;
%end;
%else %let webcount=0;
proc stp program="&program";
inputparam _program="&program"
%do i=1 %to &webcount;
%if &webcount=1 %then %do;
_webin_fileref="&&webref&i"
_webin_name="&&webname&i"
%end;
%else %do;
_webin_fileref&i="&&webref&i"
_webin_name&i="&&webname&i"
%end;
%end;
_webin_file_count="&webcount"
_debug="&debug"
%do i=1 %to &pcnt;
/* resolve name only, proc stp fetches value */
&&pval&i=&&&&&&pval&i
%end;
;
%do i=1 %to &webcount;
inputfile &&webref&i;
%end;
outputfile _webout=&webref;
run;
data _null_;
infile &webref;
file &fref1;
input;
length line $10000;
if index(_infile_,'>>weboutBEGIN<<') then do;
line=tranwrd(_infile_,'>>weboutBEGIN<<','');
put line;
end;
else if index(_infile_,'>>weboutEND<<') then do;
line=tranwrd(_infile_,'>>weboutEND<<','');
put line;
stop;
end;
else put _infile_;
run;
data _null_;
infile &fref1;
input;
put _infile_;
run;
%if &outlib ne 0 %then %do;
libname &outlib json (&fref1);
%end;
%if &outref ne 0 %then %do;
filename &outref temp;
%mp_binarycopy(inref=&webref,outref=&outref)
%end;
%end;
%else %if &platform=SASVIYA %then %do;
/* prepare inputparams */
%local ds1;
%let ds1=%mf_getuniquename();
%if "&inputparams" ne "0" %then %do;
proc transpose data=&inputparams out=&ds1;
id name;
var value;
run;
%end;
%else %do;
data &ds1;run;
%end;
/* parse the input files - convert to sasjs params */
%local webcount i var sasjs_tables;
%if %quote(&inputfiles) ne 0 %then %do;
%let webcount=%sysfunc(countw(&inputfiles));
%put &=webcount;
%do i=1 %to &webcount;
%let var=%scan(&inputfiles,&i,%str( ));
%local webfref&i webname&i sasjs&i.data;
%let webref&i=%scan(&var,1,%str(:));
%let webname&i=%scan(&var,2,%str(:));
%put webref&i=&&webref&i;
%put webname&i=&&webname&i;
%let sasjs_tables=&sasjs_tables &&webname&i;
data _null_;
infile &&webref&i lrecl=32767;
input;
if _n_=1 then call symputx("sasjs&i.data",_infile_);
else call symputx(
"sasjs&i.data",cats(symget("sasjs&i.data"),'0D0A'x,_infile_)
);
putlog "&sysmacroname infile: " _infile_;
run;
data &ds1;
set &ds1;
length sasjs&i.data $32767 sasjs_tables $1000;
sasjs&i.data=symget("sasjs&i.data");
sasjs_tables=symget("sasjs_tables");
run;
%end;
%end;
%else %let webcount=0;
data &ds1;
retain _program "&program";
retain _contextname "&viyacontext";
set &ds1;
putlog "&sysmacroname inputparams:";
putlog (_all_)(=);
run;
%mv_jobflow(inds=&ds1
,maxconcurrency=1
,outds=work.results
,outref=&fref1
,mdebug=&mdebug
)
/* show the log */
data _null_;
infile &fref1;
input;
putlog _infile_;
run;
/* get the uri to fetch results */
data _null_;
set work.results;
call symputx('uri',uri);
putlog "&sysmacroname: fetching results for " uri;
run;
/* fetch results from webout.json */
%mv_getjobresult(uri=&uri,
result=&viyaresult,
outref=&outref,
%mx_testservice(&program,
inputfiles=&inputfiles,
inputdatasets=&inputdatasets,
inputparams=&inputparams,
debug=&debug,
mdebug=&mdebug,
outlib=&outlib,
mdebug=&mdebug
)
%end;
%else %if &platform=SASJS %then %do;
%ms_testservice(&program
,inputfiles=&inputfiles
,inputdatasets=&inputdatasets
,inputparams=&inputparams
,debug=&debug
,mdebug=&mdebug
,outlib=&outlib
,outref=&outref
)
%end;
%else %do;
%put %str(ERR)OR: Unrecognised platform: &platform;
%end;
%if &mdebug=0 %then %do;
filename &fref1 clear;
%if &platform ne SASJS %then %do;
filename &fref2 clear;
filename &webref clear;
%end;
%end;
%else %do;
%put &sysmacroname exit vars:;
%put _local_;
%end;
outref=&outref,
viyaresult=&viyaresult,
viyacontext=&viyacontext
)
%mend mp_testservice;

View File

@@ -102,7 +102,7 @@ options noquotelenmax;
"""
f = open('all.sas', "w") # r / r+ / rb / rb+ / w / wb
f.write(header)
folders = ['base', 'ddl', 'meta', 'metax', 'server', 'viya', 'lua', 'fcmp']
folders = ['base', 'ddl', 'meta', 'metax', 'server', 'viya', 'lua', 'fcmp', 'xplatform']
for folder in folders:
filenames = [fn for fn in Path(
'./' + folder).iterdir() if fn.match("*.sas")]

View File

@@ -18,7 +18,17 @@
statements. Those starting `mp_` are macro _procedures_, which generate
SAS statements, and must therefore be applied accordingly.
*/
*/
/*! \dir ddl
* \brief Data Definition Language files
* \details Provides templates for commonly used tables in sasjs/core.
Attributes:
* OS independent
* No X command
* Prefixes: _mddl_
*/
/*! \dir fcmp
* \brief Macros for generating FCMP functions
@@ -94,13 +104,37 @@
*/
/*! \dir ddl
* \brief Data Definition Language files
* \details Provides templates for commonly used tables in sasjs/core.
Attributes:
/*! \dir tests/base
* \brief Tests for Base macros
*/
/*! \dir tests/ddlonly
* \brief Tests for DDL macros
*/
/*! \dir tests/sas9only
* \brief Tests for SAS Metadata macros
*/
/*! \dir tests/serveronly
* \brief Tests for SASjs Server macros
*/
/*! \dir tests/viyaonly
* \brief Tests for Viya macros
*/
/*! \dir tests/x-platform
* \brief Tests for cross-platform macros
*/
/*! \dir xplatform
* \brief Cross Platform, works on all SAS servers (Viya, EBI, SASjs)
* \details Useful when you need to run a single piece of code against Viya,
SAS 9 with metadata, or SASjs on Base SAS.
* OS independent
* No X command
* Prefixes: _mddl_
* Prefixes: _mx_
*/

View File

@@ -4,6 +4,9 @@
@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.
Note that the macro does not check inherited group memberships - it looks at
direct members only.
Usage:
%mm_adduser2group(user=sasdemo
@@ -12,10 +15,10 @@
@param user= the user name (not displayname)
@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
direct members only
<h4> Related Files </h4>
@li ms_adduser2group.sas
@version 9.3
@author Allan Bowe

View File

@@ -1,16 +1,15 @@
/**
@file mm_createdataset.sas
@brief Create a dataset from a metadata definition
@file
@brief Create an empty dataset from a metadata definition
@details This macro was built to support viewing empty tables in
https://datacontroller.io - a free evaluation copy is available by
contacting the author (Allan Bowe).
https://datacontroller.io
The table can be retrieved using LIBRARY.DATASET reference, or directly
using the metadata URI.
The dataset is written to the WORK library.
usage:
Usage:
%mm_createdataset(libds=metlib.some_dataset)
@@ -26,9 +25,9 @@
@param libds= library.dataset metadata source. Note - table names in metadata
can be longer than 32 chars (just fyi, not an issue here)
@param tableuri= Metadata URI of the table to be created
@param outds= The dataset to create, default is `work.mm_createdataset`.
The table name needs to be 32 chars or less as per SAS naming rules.
@param mdebug= set DBG to 1 to disable DEBUG messages
@param outds= (work.mm_createdataset) The dataset to create. The table name
needs to be 32 chars or less as per SAS naming rules.
@param mdebug= (0) Set to 1 to enable DEBUG messages
@version 9.4
@author Allan Bowe
@@ -54,14 +53,23 @@
%mm_gettables(uri=&liburi,outds=&tempds2)
data _null_;
set &tempds2;
if upcase(tablename)="%upcase(%scan(&libds,2,.))";
where upcase(tablename)="%upcase(%scan(&libds,2,.))";
&dbg putlog tableuri=;
call symputx('tableuri',tableuri);
run;
%end;
data;run;%let tempds3=&syslast;
data;run;
%let tempds3=&syslast;
%mm_getcols(tableuri=&tableuri,outds=&tempds3)
%if %mf_nobs(&tempds3)=0 %then %do;
%put &libds (&tableuri) has no columns defined!!;
data &outds;
run;
%return;
%end;
data _null_;
set &tempds3 end=last;
if _n_=1 then call execute('data &outds;');

View File

@@ -264,7 +264,7 @@ data _null_;
put ' %do i=1 %to &numcols; ';
put ' %if &i>1 %then "," ; ';
put ' %if &action=OBJ %then """&&name&i"":" ; ';
put ' &&name&i ';
put ' "&&name&i"n /* name literal for reserved variable names */ ';
put ' %end; ';
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
put ' /* now write the long strings to _webout 1 byte at a time */ ';

View File

@@ -17,8 +17,6 @@
directories
@param [in] mDebug= set to 1 to show debug messages in the log
<h4> SAS Macros </h4>
@version 9.4
@author Allan Bowe

View File

@@ -21,6 +21,7 @@
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mp_abort.sas
@author Allan Bowe
@@ -70,11 +71,10 @@ data _null_;
else put (_all_)(=);
run;
%if &tsuri=stopifempty %then %do;
%put %str(WARN)ING: &tree&name.(StoredProcess) not found!;
%return;
%end;
%mp_abort(iftrue= (&tsuri=stopifempty)
,mac=mm_getstpcode
,msg=%str(&tree&name.(StoredProcess) not found!)
)
/**
* Now we can extract the textstore

View File

@@ -6,8 +6,10 @@
"fcmp",
"lua",
"server",
"tests/crossplatform",
"tests/ddl"
"xplatform",
"tests/base",
"tests/ddlonly",
"tests/x-platform"
],
"docConfig": {
"displayMacroCore": false,
@@ -65,7 +67,7 @@
},
{
"name": "server",
"serverUrl": "https://sas.analytium.co.uk:5007",
"serverUrl": "https://sas.4gl.io",
"serverType": "SASJS",
"httpsAgentOptions": {
"allowInsecureRequests": false

122
server/ms_adduser2group.sas Normal file
View 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;

View File

@@ -266,7 +266,7 @@ data _null_;
put ' %do i=1 %to &numcols; ';
put ' %if &i>1 %then "," ; ';
put ' %if &action=OBJ %then """&&name&i"":" ; ';
put ' &&name&i ';
put ' "&&name&i"n /* name literal for reserved variable names */ ';
put ' %end; ';
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
put ' /* now write the long strings to _webout 1 byte at a time */ ';

View File

@@ -2,13 +2,24 @@
@file
@brief Fetches the list of groups from SASjs Server
@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:
%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] 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
list of groups. Format:
|NAME:$32.|DESCRIPTION:$64.|GROUPID:best.|
@@ -25,22 +36,38 @@
<h4> Related Files </h4>
@li ms_creategroup.sas
@li ms_getusers.test.sas
@li ms_getgroups.test.sas
**/
%macro ms_getgroups(
outds=work.ms_getgroups
,mdebug=0
);
user=0,
uid=0,
outds=work.ms_getgroups,
mdebug=0
);
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,mac=ms_getgroups.sas
,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 fref1=%mf_getuniquefileref();
%let libref=%mf_getuniquelibref();
@@ -65,8 +92,13 @@ run;
run;
%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
url="&_sasjs_apiserverurl/SASjsApi/group";
url="&_sasjs_apiserverurl.&url";
%if &mdebug=1 %then %do;
debug level=1;
%end;
@@ -75,21 +107,31 @@ run;
%mp_abort(
iftrue=(&syscc ne 0)
,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;
data &outds;
%if "&user"="0" and "&uid"="0" %then %do;
data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8;
if _n_=1 then call missing(of _all_);
set &libref..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(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,mac=ms_getgroups.sas
,msg=%str(Issue reading response JSON)
)

View File

@@ -2,16 +2,26 @@
@file
@brief Fetches the list of users from SASjs Server
@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:
%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] 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
list of user accounts. Format:
|DISPLAYNAME:$18.|USERNAME:$10.|ID:best.|
|DISPLAYNAME:$60.|USERNAME:$30.|ID:best.|
|---|---|---|
|`Super Admin `|`secretuser `|`1`|
|`Sabir Hassan`|`sabir`|`2`|
@@ -20,7 +30,6 @@
|`New User `|`newuser `|`5`|
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@@ -28,14 +37,17 @@
<h4> Related Files </h4>
@li ms_createuser.sas
@li ms_getgroups.sas
@li ms_getusers.test.sas
**/
%macro ms_getusers(
outds=work.ms_getusers
,mdebug=0
);
outds=work.ms_getusers,
group=0,
gid=0,
mdebug=0
);
%mp_abort(
iftrue=(&syscc ne 0)
@@ -43,11 +55,24 @@
,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 fref1=%mf_getuniquefileref();
%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 */
%let optval=%sysfunc(getoption(bomfile));
options nobomfile;
@@ -68,26 +93,40 @@ run;
run;
%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
url="&_sasjs_apiserverurl/SASjsApi/user";
url="&_sasjs_apiserverurl.&url";
%if &mdebug=1 %then %do;
debug level=1;
%end;
run;
%mp_abort(
iftrue=(&syscc ne 0)
,mac=ms_getusers.sas
,msg=%str(Issue submitting GET query to SASjsApi/user)
,msg=%str(Issue submitting API query)
)
libname &libref JSON fileref=&fref1;
data &outds;
%if "&group"="0" and "&gid"="0" %then %do;
data &outds;
length DISPLAYNAME $60 USERNAME:$30 ID 8;
set &libref..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(
iftrue=(&syscc ne 0)

Some files were not shown because too many files have changed in this diff Show More