mirror of
https://github.com/sasjs/core.git
synced 2026-01-05 00:20:05 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94e83f6b8d | ||
|
|
35a6dede6f | ||
|
|
039ec397dd | ||
|
|
dce4630eb8 | ||
|
|
1e142f042b | ||
|
|
7caca2f139 | ||
|
|
61556b2de8 | ||
|
|
9e12409389 | ||
|
|
c8050f5a79 | ||
|
|
cb4f71c7cd | ||
|
|
a39f4e4eee | ||
|
|
b525b4171d | ||
|
|
f2d80b3b63 | ||
|
|
96dda87f37 | ||
|
|
3435509eec | ||
|
|
42f2767129 | ||
|
|
099a5f7840 | ||
|
|
c83ea705a2 | ||
|
|
9ea6c875f2 | ||
|
|
0728f72c4f | ||
|
|
a90a6f00cf | ||
|
|
f71e53af8d | ||
|
|
cc1b971e19 | ||
|
|
8484c752ed | ||
|
|
8bd31e6c97 | ||
|
|
f9b0f87f44 | ||
|
|
d7e9f10291 | ||
|
|
3edc3587b3 | ||
|
|
63bf00e28f | ||
|
|
6b2574947a | ||
|
|
eb9027ecb6 |
@@ -30,7 +30,7 @@
|
|||||||
%put No feature was requested for detection;
|
%put No feature was requested for detection;
|
||||||
%end;
|
%end;
|
||||||
%else %if &feature=COLCONSTRAINTS %then %do;
|
%else %if &feature=COLCONSTRAINTS %then %do;
|
||||||
%if %substr(&sysver,1,1)=4 %then 0;
|
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 0;
|
||||||
%else 1;
|
%else 1;
|
||||||
%end;
|
%end;
|
||||||
%else %if &feature=PROCLUA %then %do;
|
%else %if &feature=PROCLUA %then %do;
|
||||||
|
|||||||
@@ -28,15 +28,17 @@
|
|||||||
be 8 characters, so a 7 letter prefix would mean `maxtries` should be 10.
|
be 8 characters, so a 7 letter prefix would mean `maxtries` should be 10.
|
||||||
if using zero (0) as the prefix, a native assignment is used.
|
if using zero (0) as the prefix, a native assignment is used.
|
||||||
@param [in] maxtries= (1000) the last part of the libref. Must be an integer.
|
@param [in] maxtries= (1000) the last part of the libref. Must be an integer.
|
||||||
|
@param [in] lrecl= (32767) Provide a default lrecl with which to initialise
|
||||||
|
the generated fileref.
|
||||||
|
|
||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_getuniquefileref(prefix=_,maxtries=1000);
|
%macro mf_getuniquefileref(prefix=_,maxtries=1000,lrecl=32767);
|
||||||
%local rc fname;
|
%local rc fname;
|
||||||
%if &prefix=0 %then %do;
|
%if &prefix=0 %then %do;
|
||||||
%let rc=%sysfunc(filename(fname,,temp));
|
%let rc=%sysfunc(filename(fname,,temp,lrecl=&lrecl));
|
||||||
%if &rc %then %put %sysfunc(sysmsg());
|
%if &rc %then %put %sysfunc(sysmsg());
|
||||||
&fname
|
&fname
|
||||||
%end;
|
%end;
|
||||||
@@ -47,7 +49,7 @@
|
|||||||
%do x=0 %to &maxtries;
|
%do x=0 %to &maxtries;
|
||||||
%let fname=&prefix%substr(%sysfunc(ranuni(0)),3,&len);
|
%let fname=&prefix%substr(%sysfunc(ranuni(0)),3,&len);
|
||||||
%if %sysfunc(fileref(&fname)) > 0 %then %do;
|
%if %sysfunc(fileref(&fname)) > 0 %then %do;
|
||||||
%let rc=%sysfunc(filename(fname,,temp));
|
%let rc=%sysfunc(filename(fname,,temp,lrecl=&lrecl));
|
||||||
%if &rc %then %put %sysfunc(sysmsg());
|
%if &rc %then %put %sysfunc(sysmsg());
|
||||||
&fname
|
&fname
|
||||||
%return;
|
%return;
|
||||||
|
|||||||
@@ -20,8 +20,11 @@
|
|||||||
|
|
||||||
%macro mf_isint(arg
|
%macro mf_isint(arg
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
/* remove minus sign if exists */
|
|
||||||
|
|
||||||
|
/* blank val is not an integer */
|
||||||
|
%if "&arg"="" %then %do;0%return;%end;
|
||||||
|
|
||||||
|
/* remove minus sign if exists */
|
||||||
%local val;
|
%local val;
|
||||||
%if "%substr(%str(&arg),1,1)"="-" %then %let val=%substr(%str(&arg),2);
|
%if "%substr(%str(&arg),1,1)"="-" %then %let val=%substr(%str(&arg),2);
|
||||||
%else %let val=&arg;
|
%else %let val=&arg;
|
||||||
|
|||||||
194
base/mp_chop.sas
Normal file
194
base/mp_chop.sas
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Splits a file of ANY SIZE by reference to a search string.
|
||||||
|
@details Provide a fileref and a search string to chop off part of a file.
|
||||||
|
|
||||||
|
Works by reading in the file byte by byte, then marking the beginning and end
|
||||||
|
of each matched string, before finally doing the chop.
|
||||||
|
|
||||||
|
Choose whether to keep the FIRST or the LAST section of the file. Optionally,
|
||||||
|
use an OFFSET to fix the precise chop point.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
%let src="%sysfunc(pathname(work))/file.txt";
|
||||||
|
%let str=Chop here!;
|
||||||
|
%let out1="%sysfunc(pathname(work))/file1.txt";
|
||||||
|
%let out2="%sysfunc(pathname(work))/file2.txt";
|
||||||
|
%let out3="%sysfunc(pathname(work))/file3.txt";
|
||||||
|
%let out4="%sysfunc(pathname(work))/file4.txt";
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &src;
|
||||||
|
put "startsection&str.endsection";
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_chop(&src, matchvar=str, keep=FIRST, outfile=&out1)
|
||||||
|
%mp_chop(&src, matchvar=str, keep=LAST, outfile=&out2)
|
||||||
|
%mp_chop(&src, matchvar=str, keep=FIRST, matchpoint=END, outfile=&out3)
|
||||||
|
%mp_chop(&src, matchvar=str, keep=LAST, matchpoint=END, outfile=&out4)
|
||||||
|
|
||||||
|
filename results (&out1 &out2 &out3 &out4);
|
||||||
|
data _null_;
|
||||||
|
infile results;
|
||||||
|
input;
|
||||||
|
list;
|
||||||
|
run;
|
||||||
|
|
||||||
|
Results:
|
||||||
|
@li `startsection`
|
||||||
|
@li `Chop here!endsection`
|
||||||
|
@li `startsectionChop here!`
|
||||||
|
@li `endsection`
|
||||||
|
|
||||||
|
For more examples, see mp_chop.test.sas
|
||||||
|
|
||||||
|
@param [in] infile The QUOTED path to the file on which to perform the chop
|
||||||
|
@param [in] matchvar= Macro variable NAME containing the string to split by
|
||||||
|
@param [in] matchpoint= (START) Valid values:
|
||||||
|
@li START - chop at the beginning of the string in `matchvar`.
|
||||||
|
@li END - chop at the end of the string in `matchvar`.
|
||||||
|
@param [in] offset= (0) An adjustment to the precise chop location, by
|
||||||
|
by reference to the `matchpoint`. Should be a positive or negative integer.
|
||||||
|
@param [in] keep= (FIRST) Valid values:
|
||||||
|
@li FIRST - keep the section of the file before the chop
|
||||||
|
@li LAST - keep the section of the file after the chop
|
||||||
|
@param [in] mdebug= (0) Set to 1 to provide macro debugging
|
||||||
|
@param outfile= (0) Optional QUOTED path to the adjusted output file (avoids
|
||||||
|
overwriting the first file).
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mp_abort.sas
|
||||||
|
@li mp_gsubfile.sas
|
||||||
|
@li mp_replace.sas
|
||||||
|
@li mp_chop.test.sas
|
||||||
|
|
||||||
|
@version 9.4
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_chop(infile,
|
||||||
|
matchvar=,
|
||||||
|
matchpoint=START,
|
||||||
|
keep=FIRST,
|
||||||
|
offset=0,
|
||||||
|
mdebug=0,
|
||||||
|
outfile=0
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%local fref0 dttm ds1 outref;
|
||||||
|
%let fref0=%mf_getuniquefileref();
|
||||||
|
%let ds1=%mf_getuniquename(prefix=allchars);
|
||||||
|
%let ds2=%mf_getuniquename(prefix=startmark);
|
||||||
|
|
||||||
|
%if &outfile=0 %then %let outfile=&infile;
|
||||||
|
|
||||||
|
%mp_abort(iftrue= (%length(%superq(&matchvar))=0)
|
||||||
|
,mac=mp_chop.sas
|
||||||
|
,msg=%str(&matchvar is an empty variable)
|
||||||
|
)
|
||||||
|
|
||||||
|
/* START */
|
||||||
|
%let dttm=%sysfunc(datetime());
|
||||||
|
|
||||||
|
filename &fref0 &infile lrecl=1 recfm=n;
|
||||||
|
|
||||||
|
/* create dataset with one char per row */
|
||||||
|
data &ds1;
|
||||||
|
infile &fref0;
|
||||||
|
input sourcechar $char1. @@;
|
||||||
|
format sourcechar hex2.;
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* get start & stop position of first matchvar string (one row, two vars) */
|
||||||
|
data &ds2;
|
||||||
|
/* set find string to length in bytes to cover trailing spaces */
|
||||||
|
length string $ %length(%superq(&matchvar));
|
||||||
|
string =symget("&matchvar");
|
||||||
|
drop string;
|
||||||
|
|
||||||
|
firstchar=char(string,1);
|
||||||
|
findlen=lengthm(string); /* <- for trailing bytes */
|
||||||
|
|
||||||
|
do _N_=1 to nobs;
|
||||||
|
set &ds1 nobs=nobs point=_N_;
|
||||||
|
if sourcechar=firstchar then do;
|
||||||
|
pos=1;
|
||||||
|
s=0;
|
||||||
|
do point=_N_ to min(_N_ + findlen -1,nobs);
|
||||||
|
set &ds1 point=point;
|
||||||
|
if sourcechar=char(string, pos) then s + 1;
|
||||||
|
else goto _leave_;
|
||||||
|
pos+1;
|
||||||
|
end;
|
||||||
|
_leave_:
|
||||||
|
if s=findlen then do;
|
||||||
|
START =_N_;
|
||||||
|
_N_ =_N_+ s - 1;
|
||||||
|
STOP =_N_;
|
||||||
|
output;
|
||||||
|
/* matched! */
|
||||||
|
stop;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
stop;
|
||||||
|
keep START STOP;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%local split;
|
||||||
|
%let split=0;
|
||||||
|
data _null_;
|
||||||
|
set &ds2;
|
||||||
|
if "&matchpoint"='START' then do;
|
||||||
|
if "&keep"='FIRST' then mp=start;
|
||||||
|
else if "&keep"='LAST' then mp=start-1;
|
||||||
|
end;
|
||||||
|
else if "&matchpoint"='END' then do;
|
||||||
|
if "&keep"='FIRST' then mp=stop+1;
|
||||||
|
else if "&keep"='LAST' then mp=stop;
|
||||||
|
end;
|
||||||
|
split=mp+&offset;
|
||||||
|
call symputx('split',split,'l');
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
put (_all_)(=);
|
||||||
|
%put &=offset;
|
||||||
|
%end;
|
||||||
|
run;
|
||||||
|
%if &split=0 %then %do;
|
||||||
|
%put &sysmacroname: No match found in &infile for string %superq(&matchvar);
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &outfile recfm=n;
|
||||||
|
set &ds1;
|
||||||
|
%if &keep=FIRST %then %do;
|
||||||
|
if _n_ ge &split then stop;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
if _n_ gt &split;
|
||||||
|
%end;
|
||||||
|
put sourcechar char1.;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%if &mdebug=0 %then %do;
|
||||||
|
filename &fref0 clear;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
data _null_;
|
||||||
|
infile &outfile lrecl=32767;
|
||||||
|
input;
|
||||||
|
list;
|
||||||
|
if _n_>50 then stop;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
/* END */
|
||||||
|
%put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) seconds to run;
|
||||||
|
|
||||||
|
%mend mp_chop;
|
||||||
@@ -29,6 +29,7 @@ Usage:
|
|||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mm_createwebservice.sas
|
@li mm_createwebservice.sas
|
||||||
|
@li ms_createwebservice.sas
|
||||||
@li mv_createwebservice.sas
|
@li mv_createwebservice.sas
|
||||||
|
|
||||||
@param [in,out] path= The full folder path where the service will be created
|
@param [in,out] path= The full folder path where the service will be created
|
||||||
@@ -40,7 +41,7 @@ Usage:
|
|||||||
be added
|
be added
|
||||||
@param [in] replace= (YES) Select YES to replace any existing service in that
|
@param [in] replace= (YES) Select YES to replace any existing service in that
|
||||||
location
|
location
|
||||||
|
@param [in] mDebug= (0) set to 1 to show debug messages in the log
|
||||||
|
|
||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
@@ -53,6 +54,7 @@ Usage:
|
|||||||
,code=ft15f001
|
,code=ft15f001
|
||||||
,desc=This service was created by the mp_createwebservice macro
|
,desc=This service was created by the mp_createwebservice macro
|
||||||
,replace=YES
|
,replace=YES
|
||||||
|
,mdebug=0
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%if &syscc ge 4 %then %do;
|
%if &syscc ge 4 %then %do;
|
||||||
@@ -71,8 +73,17 @@ Usage:
|
|||||||
,replace=&replace
|
,replace=&replace
|
||||||
)
|
)
|
||||||
%end;
|
%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;
|
%else %do;
|
||||||
%if "&path"="HOME" %then %let path=/User Folders/&sysuserid/My Folder;
|
%if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder;
|
||||||
%mm_createwebservice(path=&path
|
%mm_createwebservice(path=&path
|
||||||
,name=&name
|
,name=&name
|
||||||
,code=&code
|
,code=&code
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
outfile=0
|
outfile=0
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%if "%substr(&sysver,1,4)"="V.04" %then %do;
|
%if "%substr(&sysver.XX,1,4)"="V.04" %then %do;
|
||||||
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
|
|
||||||
%if &action=OPEN %then %do;
|
%if &action=OPEN %then %do;
|
||||||
options nobomfile;
|
options nobomfile;
|
||||||
data _null_;file &jref encoding='utf-8' ;
|
data _null_;file &jref encoding='utf-8' lrecl=200;
|
||||||
put '{"PROCESSED_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '"';
|
put '{"PROCESSED_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '"';
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
@param infile The QUOTED path to the file on which to perform the substitution
|
@param infile The QUOTED path to the file on which to perform the substitution
|
||||||
@param findvar= Macro variable NAME containing the string to search for
|
@param findvar= Macro variable NAME containing the string to search for
|
||||||
@param replacevar= Macro variable NAME containing the replacement string
|
@param replacevar= Macro variable NAME containing the replacement string
|
||||||
@param outfile= (0) Optional QUOTED path to an the adjusted output file (to
|
@param outfile= (0) Optional QUOTED path to the adjusted output file (to
|
||||||
avoid overwriting the first file).
|
avoid overwriting the first file).
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@@ -43,7 +43,9 @@
|
|||||||
@li mf_getuniquename.sas
|
@li mf_getuniquename.sas
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
<h4> Related Macros </h4>
|
||||||
@li mp_gsubfile.test.sas
|
@li mp_chop.sas
|
||||||
|
@li mp_gsubfile.sas
|
||||||
|
@li mp_replace.test.sas
|
||||||
|
|
||||||
@version 9.4
|
@version 9.4
|
||||||
@author Bartosz Jabłoński
|
@author Bartosz Jabłoński
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Streams a file to _webout according to content type
|
@brief Streams a file to _webout according to content type
|
||||||
@details Will set headers using appropriate functions (SAS 9 vs Viya) and send
|
@details Will set headers using appropriate functions per the server type
|
||||||
content as a binary stream.
|
(Viya, EBI, [SASjs Server](https://github.com/sasjs/server)) and stream
|
||||||
|
content using mp_binarycopy().
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
@@ -12,7 +13,14 @@
|
|||||||
|
|
||||||
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
||||||
|
|
||||||
@param [in] contenttype= (TEXT) Either TEXT, ZIP, CSV, EXCEL
|
@param [in] contenttype= (TEXT) Supported:
|
||||||
|
@li CSV
|
||||||
|
@li EXCEL
|
||||||
|
@li MARKDOWN
|
||||||
|
@li TEXT
|
||||||
|
@li ZIP
|
||||||
|
Feel free to submit PRs to support more mime types! The official list is
|
||||||
|
here: https://www.iana.org/assignments/media-types/media-types.xhtml
|
||||||
@param [in] inloc= /path/to/file.ext to be sent
|
@param [in] inloc= /path/to/file.ext to be sent
|
||||||
@param [in] inref= fileref of file to be sent (if provided, overrides `inloc`)
|
@param [in] inref= fileref of file to be sent (if provided, overrides `inloc`)
|
||||||
@param [in] iftrue= (1=1) Provide a condition under which to execute.
|
@param [in] iftrue= (1=1) Provide a condition under which to execute.
|
||||||
@@ -58,7 +66,7 @@ run;
|
|||||||
%if &contentype=CSV %then %do;
|
%if &contentype=CSV %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/csv');
|
rc=stpsrv_header('Content-Type','application/csv');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -68,7 +76,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/csv)
|
%mfs_httpheader(Content-Type,application/csv)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
@@ -76,7 +84,7 @@ run;
|
|||||||
/* suitable for XLS format */
|
/* suitable for XLS format */
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/vnd.ms-excel');
|
rc=stpsrv_header('Content-Type','application/vnd.ms-excel');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -86,14 +94,14 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/vnd.ms-excel)
|
%mfs_httpheader(Content-Type,application/vnd.ms-excel)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-Type',"image/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
@@ -101,30 +109,30 @@ run;
|
|||||||
contenttype="image/%lowcase(&contenttype)";
|
contenttype="image/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,image/%lowcase(&contenttype))
|
%mfs_httpheader(Content-Type,image/%lowcase(&contenttype))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=HTML %then %do;
|
%else %if &contentype=HTML or &contenttype=MARKDOWN %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','text/html');
|
rc=stpsrv_header('Content-Type',"text/%lowcase(&contenttype)");
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
|
||||||
contenttype="text/html"
|
contenttype="text/%lowcase(&contenttype)"
|
||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,text/html)
|
%mfs_httpheader(Content-Type,text/%lowcase(&contenttype))
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=TEXT %then %do;
|
%else %if &contentype=TEXT %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/text');
|
rc=stpsrv_header('Content-Type','application/text');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -134,14 +142,14 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/text)
|
%mfs_httpheader(Content-Type,application/text)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)");
|
rc=stpsrv_header('Content-Type',"font/%lowcase(&contenttype)");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASVIYA %then %do;
|
%else %if &platform=SASVIYA %then %do;
|
||||||
@@ -149,13 +157,13 @@ run;
|
|||||||
contenttype="font/%lowcase(&contenttype)";
|
contenttype="font/%lowcase(&contenttype)";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,font/%lowcase(&contenttype))
|
%mfs_httpheader(Content-Type,font/%lowcase(&contenttype))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %if &contentype=XLSX %then %do;
|
%else %if &contentype=XLSX %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type',
|
rc=stpsrv_header('Content-Type',
|
||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
@@ -167,7 +175,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type
|
%mfs_httpheader(Content-Type
|
||||||
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
||||||
)
|
)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
@@ -176,7 +184,7 @@ run;
|
|||||||
%else %if &contentype=ZIP %then %do;
|
%else %if &contentype=ZIP %then %do;
|
||||||
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
%if (&platform=SASMETA and &streamweb=1) %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
rc=stpsrv_header('Content-type','application/zip');
|
rc=stpsrv_header('Content-Type','application/zip');
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
@@ -186,7 +194,7 @@ run;
|
|||||||
contentdisp="attachment; filename=&outname";
|
contentdisp="attachment; filename=&outname";
|
||||||
%end;
|
%end;
|
||||||
%else %if &platform=SASJS %then %do;
|
%else %if &platform=SASJS %then %do;
|
||||||
%mfs_httpheader(Content-type,application/zip)
|
%mfs_httpheader(Content-Type,application/zip)
|
||||||
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
@@ -40,7 +40,9 @@
|
|||||||
@li mf_getuniquename.sas
|
@li mf_getuniquename.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mp_binarycopy.sas
|
@li mp_binarycopy.sas
|
||||||
|
@li mp_chop.sas
|
||||||
@li mp_ds2csv.sas
|
@li mp_ds2csv.sas
|
||||||
|
@li ms_testservice.sas
|
||||||
@li mv_getjobresult.sas
|
@li mv_getjobresult.sas
|
||||||
@li mv_jobflow.sas
|
@li mv_jobflow.sas
|
||||||
|
|
||||||
@@ -63,7 +65,7 @@
|
|||||||
viyaresult=WEBOUT_JSON,
|
viyaresult=WEBOUT_JSON,
|
||||||
viyacontext=SAS Job Execution compute context
|
viyacontext=SAS Job Execution compute context
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
%local dbg pcnt fref1 webref i webcount var platform;
|
%local dbg pcnt fref1 fref2 webref webrefpath i webcount var platform;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -104,10 +106,14 @@
|
|||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
|
|
||||||
%let fref1=%mf_getuniquefileref();
|
|
||||||
%let webref=%mf_getuniquefileref();
|
|
||||||
%let platform=%mf_getplatform();
|
%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;
|
%if &platform=SASMETA %then %do;
|
||||||
|
|
||||||
/* parse the input files */
|
/* parse the input files */
|
||||||
@@ -262,13 +268,30 @@
|
|||||||
mdebug=&mdebug
|
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;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put %str(ERR)OR: Unrecognised platform: &platform;
|
%put %str(ERR)OR: Unrecognised platform: &platform;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &mdebug=0 %then %do;
|
%if &mdebug=0 %then %do;
|
||||||
filename &webref clear;
|
filename &fref1 clear;
|
||||||
|
%if &platform ne SASJS %then %do;
|
||||||
|
filename &fref2 clear;
|
||||||
|
filename &webref clear;
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put &sysmacroname exit vars:;
|
%put &sysmacroname exit vars:;
|
||||||
|
|||||||
77
build.py
77
build.py
@@ -4,8 +4,8 @@ from pathlib import Path
|
|||||||
# Prepare Lua Macros
|
# Prepare Lua Macros
|
||||||
files = [f for f in Path('lua').iterdir() if f.match("*.lua")]
|
files = [f for f in Path('lua').iterdir() if f.match("*.lua")]
|
||||||
for file in files:
|
for file in files:
|
||||||
basename=os.path.basename(file)
|
basename = os.path.basename(file)
|
||||||
name='ml_' + os.path.splitext(basename)[0]
|
name = 'ml_' + os.path.splitext(basename)[0]
|
||||||
ml = open('lua/' + name + '.sas', "w")
|
ml = open('lua/' + name + '.sas', "w")
|
||||||
ml.write("/**\n")
|
ml.write("/**\n")
|
||||||
ml.write(" @file " + name + '.sas\n')
|
ml.write(" @file " + name + '.sas\n')
|
||||||
@@ -20,50 +20,68 @@ for file in files:
|
|||||||
ml.write(" file \"%sysfunc(pathname(work))/" + name + ".lua\";\n")
|
ml.write(" file \"%sysfunc(pathname(work))/" + name + ".lua\";\n")
|
||||||
with open(file) as infile:
|
with open(file) as infile:
|
||||||
for line in infile:
|
for line in infile:
|
||||||
ml.write(" put '" + line.rstrip().replace("'","''") + " ';\n")
|
ml.write(" put '" + line.rstrip().replace("'", "''") + " ';\n")
|
||||||
ml.write("run;\n\n")
|
ml.write("run;\n\n")
|
||||||
ml.write("%inc \"%sysfunc(pathname(work))/" + name + ".lua\" /source2;\n\n")
|
|
||||||
|
ml.write("/* ensure big enough lrecl to avoid lua compilation issues */\n")
|
||||||
|
ml.write("%local optval;\n")
|
||||||
|
ml.write("%let optval=%sysfunc(getoption(lrecl));\n")
|
||||||
|
ml.write("options lrecl=1024;\n\n")
|
||||||
|
ml.write("/* execute the lua code by using a .lua extension */\n")
|
||||||
|
ml.write("%inc \"%sysfunc(pathname(work))/" +
|
||||||
|
name + ".lua\" /source2;\n\n")
|
||||||
|
ml.write("options lrecl=&optval;\n\n")
|
||||||
ml.write("%mend " + name + ";\n")
|
ml.write("%mend " + name + ";\n")
|
||||||
|
|
||||||
ml.close()
|
ml.close()
|
||||||
|
|
||||||
# prepare web files
|
# prepare web files
|
||||||
files=['viya/mv_createwebservice.sas','meta/mm_createwebservice.sas']
|
files = ['viya/mv_createwebservice.sas',
|
||||||
|
'meta/mm_createwebservice.sas', 'server/ms_createwebservice.sas']
|
||||||
for file in files:
|
for file in files:
|
||||||
webout0=open('base/mp_jsonout.sas','r')
|
webout0 = open('base/mp_jsonout.sas', 'r')
|
||||||
if file=='viya/mv_createwebservice.sas':
|
webout1 = open('base/mf_getuser.sas', 'r')
|
||||||
webout1=open('viya/mv_webout.sas',"r")
|
|
||||||
|
if file == 'viya/mv_createwebservice.sas':
|
||||||
|
webout2 = open('viya/mv_webout.sas', "r")
|
||||||
|
weboutfiles = [webout0, webout1, webout2]
|
||||||
|
elif file == 'server/ms_createwebservice.sas':
|
||||||
|
webout2 = open('server/ms_webout.sas', "r")
|
||||||
|
webout3 = open('server/mfs_httpheader.sas', 'r')
|
||||||
|
weboutfiles = [webout0, webout1, webout2, webout3]
|
||||||
else:
|
else:
|
||||||
webout1=open('meta/mm_webout.sas','r')
|
webout2 = open('meta/mm_webout.sas', 'r')
|
||||||
webout2=open('base/mf_getuser.sas','r')
|
weboutfiles = [webout0, webout1, webout2]
|
||||||
outfile=open(file + 'TEMP','w')
|
outfile = open(file + 'TEMP', 'w')
|
||||||
infile=open(file,'r')
|
infile = open(file, 'r')
|
||||||
delrow=0
|
delrow = 0
|
||||||
for line in infile:
|
for line in infile:
|
||||||
if line=='/* WEBOUT BEGIN */\n':
|
if line == '/* WEBOUT BEGIN */\n':
|
||||||
delrow=1
|
delrow = 1
|
||||||
outfile.write('/* WEBOUT BEGIN */\n')
|
outfile.write('/* WEBOUT BEGIN */\n')
|
||||||
weboutfiles=[webout0,webout1,webout2]
|
|
||||||
for weboutfile in weboutfiles:
|
for weboutfile in weboutfiles:
|
||||||
stripcomment=1
|
stripcomment = 1
|
||||||
for w in weboutfile:
|
for w in weboutfile:
|
||||||
if w=='**/\n': stripcomment=0
|
if w == '**/\n':
|
||||||
elif stripcomment==0:
|
stripcomment = 0
|
||||||
outfile.write(" put '" + w.rstrip().replace("'","''") + " ';\n")
|
elif stripcomment == 0:
|
||||||
elif delrow==1 and line=='/* WEBOUT END */\n':
|
outfile.write(
|
||||||
delrow=0
|
" put '" + w.rstrip().replace("'", "''") + " ';\n")
|
||||||
outfile.write('/* WEBOUT END */\n')
|
elif delrow == 1 and line == '/* WEBOUT END */\n':
|
||||||
elif delrow==0:
|
delrow = 0
|
||||||
|
outfile.write('/* WEBOUT END */\n')
|
||||||
|
elif delrow == 0:
|
||||||
outfile.write(line.rstrip() + "\n")
|
outfile.write(line.rstrip() + "\n")
|
||||||
webout0.close()
|
webout0.close()
|
||||||
webout1.close()
|
webout1.close()
|
||||||
|
webout2.close()
|
||||||
outfile.close()
|
outfile.close()
|
||||||
infile.close()
|
infile.close()
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
os.rename(file + 'TEMP',file)
|
os.rename(file + 'TEMP', file)
|
||||||
|
|
||||||
# Concatenate all macros into a single file
|
# Concatenate all macros into a single file
|
||||||
header="""
|
header = """
|
||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Auto-generated file
|
@brief Auto-generated file
|
||||||
@@ -84,14 +102,15 @@ options noquotelenmax;
|
|||||||
"""
|
"""
|
||||||
f = open('all.sas', "w") # r / r+ / rb / rb+ / w / wb
|
f = open('all.sas', "w") # r / r+ / rb / rb+ / w / wb
|
||||||
f.write(header)
|
f.write(header)
|
||||||
folders=['base','ddl','meta','metax','server','viya','lua','fcmp']
|
folders = ['base', 'ddl', 'meta', 'metax', 'server', 'viya', 'lua', 'fcmp']
|
||||||
for folder in folders:
|
for folder in folders:
|
||||||
filenames = [fn for fn in Path('./' + folder).iterdir() if fn.match("*.sas")]
|
filenames = [fn for fn in Path(
|
||||||
|
'./' + folder).iterdir() if fn.match("*.sas")]
|
||||||
filenames.sort()
|
filenames.sort()
|
||||||
with open('mc_' + folder + '.sas', 'w') as outfile:
|
with open('mc_' + folder + '.sas', 'w') as outfile:
|
||||||
for fname in filenames:
|
for fname in filenames:
|
||||||
with open(fname) as infile:
|
with open(fname) as infile:
|
||||||
outfile.write(infile.read())
|
outfile.write(infile.read())
|
||||||
with open('mc_' + folder + '.sas','r') as c:
|
with open('mc_' + folder + '.sas', 'r') as c:
|
||||||
f.write(c.read())
|
f.write(c.read())
|
||||||
f.close()
|
f.close()
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ data _null_;
|
|||||||
put 'io.close(file) ';
|
put 'io.close(file) ';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
/* ensure big enough lrecl to avoid lua compilation issues */
|
||||||
|
%local optval;
|
||||||
|
%let optval=%sysfunc(getoption(lrecl));
|
||||||
|
options lrecl=1024;
|
||||||
|
|
||||||
|
/* execute the lua code by using a .lua extension */
|
||||||
%inc "%sysfunc(pathname(work))/ml_gsubfile.lua" /source2;
|
%inc "%sysfunc(pathname(work))/ml_gsubfile.lua" /source2;
|
||||||
|
|
||||||
|
options lrecl=&optval;
|
||||||
|
|
||||||
%mend ml_gsubfile;
|
%mend ml_gsubfile;
|
||||||
|
|||||||
@@ -389,6 +389,14 @@ data _null_;
|
|||||||
put '-- JSON.LUA ENDS HERE ';
|
put '-- JSON.LUA ENDS HERE ';
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
/* ensure big enough lrecl to avoid lua compilation issues */
|
||||||
|
%local optval;
|
||||||
|
%let optval=%sysfunc(getoption(lrecl));
|
||||||
|
options lrecl=1024;
|
||||||
|
|
||||||
|
/* execute the lua code by using a .lua extension */
|
||||||
%inc "%sysfunc(pathname(work))/ml_json.lua" /source2;
|
%inc "%sysfunc(pathname(work))/ml_json.lua" /source2;
|
||||||
|
|
||||||
|
options lrecl=&optval;
|
||||||
|
|
||||||
%mend ml_json;
|
%mend ml_json;
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '%if &action=OPEN %then %do; ';
|
put '%if &action=OPEN %then %do; ';
|
||||||
put ' options nobomfile; ';
|
put ' options nobomfile; ';
|
||||||
put ' data _null_;file &jref encoding=''utf-8'' ; ';
|
put ' data _null_;file &jref encoding=''utf-8'' lrecl=200; ';
|
||||||
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
@@ -314,6 +314,25 @@ data _null_;
|
|||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%mend mp_jsonout; ';
|
put '%mend mp_jsonout; ';
|
||||||
|
put ' ';
|
||||||
|
put '%macro mf_getuser(type=META ';
|
||||||
|
put ')/*/STORE SOURCE*/; ';
|
||||||
|
put ' %local user metavar; ';
|
||||||
|
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
||||||
|
put ' %else %let metavar=_metaperson; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
||||||
|
put ' %else %if %symexist(&metavar) %then %do; ';
|
||||||
|
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
||||||
|
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
||||||
|
put ' /* but be sure to quote in case of usernames with commas */ ';
|
||||||
|
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %let user=&sysuserid; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %quote(&user) ';
|
||||||
|
put ' ';
|
||||||
|
put '%mend mf_getuser; ';
|
||||||
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL ';
|
put '%macro mm_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL ';
|
||||||
put ' ,showmeta=NO ';
|
put ' ,showmeta=NO ';
|
||||||
put '); ';
|
put '); ';
|
||||||
@@ -455,25 +474,6 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%mend mm_webout; ';
|
put '%mend mm_webout; ';
|
||||||
put ' ';
|
|
||||||
put '%macro mf_getuser(type=META ';
|
|
||||||
put ')/*/STORE SOURCE*/; ';
|
|
||||||
put ' %local user metavar; ';
|
|
||||||
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
|
||||||
put ' %else %let metavar=_metaperson; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
|
||||||
put ' %else %if %symexist(&metavar) %then %do; ';
|
|
||||||
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
|
||||||
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
|
||||||
put ' /* but be sure to quote in case of usernames with commas */ ';
|
|
||||||
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %let user=&sysuserid; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %quote(&user) ';
|
|
||||||
put ' ';
|
|
||||||
put '%mend mf_getuser; ';
|
|
||||||
/* WEBOUT END */
|
/* WEBOUT END */
|
||||||
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO);';
|
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO);';
|
||||||
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing';
|
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing';
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"serverUrl": "https://sas.analytium.co.uk:5000",
|
"serverUrl": "https://sas.analytium.co.uk:5007",
|
||||||
"serverType": "SASJS",
|
"serverType": "SASJS",
|
||||||
"httpsAgentOptions": {
|
"httpsAgentOptions": {
|
||||||
"allowInsecureRequests": false
|
"allowInsecureRequests": false
|
||||||
@@ -74,13 +74,7 @@
|
|||||||
"macroFolders": [
|
"macroFolders": [
|
||||||
"server",
|
"server",
|
||||||
"tests/serveronly"
|
"tests/serveronly"
|
||||||
],
|
]
|
||||||
"programFolders": [],
|
|
||||||
"binaryFolders": [],
|
|
||||||
"deployConfig": {
|
|
||||||
"deployServicePack": true,
|
|
||||||
"deployScripts": []
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "docsonly",
|
"name": "docsonly",
|
||||||
@@ -92,6 +86,7 @@
|
|||||||
"server",
|
"server",
|
||||||
"viya",
|
"viya",
|
||||||
"tests/sas9only",
|
"tests/sas9only",
|
||||||
|
"tests/serveronly",
|
||||||
"tests/viyaonly"
|
"tests/viyaonly"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%mfs_httpheader(Content-type,application/csv)
|
%mfs_httpheader(Content-Type,application/csv)
|
||||||
|
|
||||||
@param [in] header_name Name of the http header to set
|
@param [in] header_name Name of the http header to set
|
||||||
@param [in] header_value Value of the http header to set
|
@param [in] header_value Value of the http header to set
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
%macro mfs_httpheader(header_name
|
%macro mfs_httpheader(header_name
|
||||||
,header_value
|
,header_value
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
%global sasjs_stpsrv_header_loc;
|
||||||
%local fref fid i;
|
%local fref fid i;
|
||||||
|
|
||||||
%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do;
|
%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mf_getuniquename.sas
|
@li mf_getuniquename.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
|
@li ms_deletefile.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -29,6 +30,9 @@
|
|||||||
,mdebug=0
|
,mdebug=0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* first, delete in case it exists */
|
||||||
|
%ms_deletefile(&driveloc,mdebug=&mdebug)
|
||||||
|
|
||||||
%local fname0 fname1 fname2 boundary fname statcd msg optval;
|
%local fname0 fname1 fname2 boundary fname statcd msg optval;
|
||||||
%let fname0=%mf_getuniquefileref();
|
%let fname0=%mf_getuniquefileref();
|
||||||
%let fname1=%mf_getuniquefileref();
|
%let fname1=%mf_getuniquefileref();
|
||||||
@@ -40,8 +44,8 @@
|
|||||||
options nobomfile;
|
options nobomfile;
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
file &fname0 termstr=crlf;
|
file &fname0 termstr=crlf lrecl=32767;
|
||||||
infile &inref end=eof;
|
infile &inref end=eof lrecl=32767;
|
||||||
if _n_ = 1 then do;
|
if _n_ = 1 then do;
|
||||||
put "--&boundary.";
|
put "--&boundary.";
|
||||||
put 'Content-Disposition: form-data; name="filePath"';
|
put 'Content-Disposition: form-data; name="filePath"';
|
||||||
@@ -70,11 +74,11 @@ run;
|
|||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &fname0;
|
infile &fname0 lrecl=32767;
|
||||||
input;
|
input;
|
||||||
put _infile_;
|
put _infile_;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &fname1;
|
infile &fname1 lrecl=32767;
|
||||||
input;
|
input;
|
||||||
put _infile_;
|
put _infile_;
|
||||||
run;
|
run;
|
||||||
|
|||||||
144
server/ms_createuser.sas
Normal file
144
server/ms_createuser.sas
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Creates a user on SASjs Server
|
||||||
|
@details Creates a user on SASjs Server with the following attributes:
|
||||||
|
|
||||||
|
@li UserName
|
||||||
|
@li Password
|
||||||
|
@li isAdmin
|
||||||
|
@li displayName
|
||||||
|
|
||||||
|
The userid is created by sasjs/server. All users are created with `isActive`
|
||||||
|
set to `true`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
%ms_createuser(newuser,secretpass,displayname=New User!)
|
||||||
|
|
||||||
|
@param [in] username The username to apply. No spaces or special characters.
|
||||||
|
@param [in] password The initial password to set.
|
||||||
|
@param [in] isadmin= (false) Set to true to give the user admin rights
|
||||||
|
@param [in] displayName= (0) Set a friendly name (spaces & special characters
|
||||||
|
are ok). If not provided, username will be used instead.
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
@param [out] outds= (work.ms_createuser) This output dataset will contain the
|
||||||
|
values from the JSON response (such as the id of the new user)
|
||||||
|
|ID:best.|DISPLAYNAME:$8.|USERNAME:$8.|ISACTIVE:best.|ISADMIN:best.|
|
||||||
|
|---|---|---|---|---|
|
||||||
|
|`6 `|`New User `|`newuser `|`1 `|`0 `|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquelibref.sas
|
||||||
|
@li mp_abort.sas
|
||||||
|
|
||||||
|
<h4> Related Files </h4>
|
||||||
|
@li ms_createuser.test.sas
|
||||||
|
@li ms_getusers.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_createuser(username,password
|
||||||
|
,isadmin=false
|
||||||
|
,displayname=0
|
||||||
|
,outds=work.ms_createuser
|
||||||
|
,mdebug=0
|
||||||
|
);
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&syscc ne 0)
|
||||||
|
,mac=ms_createuser.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 fref2=%mf_getuniquefileref();
|
||||||
|
%let libref=%mf_getuniquelibref();
|
||||||
|
|
||||||
|
/* avoid sending bom marker to API */
|
||||||
|
%let optval=%sysfunc(getoption(bomfile));
|
||||||
|
options nobomfile;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &fref0 termstr=crlf;
|
||||||
|
username=quote(cats(symget('username')));
|
||||||
|
password=quote(cats(symget('password')));
|
||||||
|
isadmin=symget('isadmin');
|
||||||
|
displayname=quote(cats(symget('displayname')));
|
||||||
|
if displayname='"0"' then displayname=username;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
putlog _all_;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
put '{'@;
|
||||||
|
put '"displayName":' displayname @;
|
||||||
|
put ',"username":' username @;
|
||||||
|
put ',"password":' password @;
|
||||||
|
put ',"isAdmin":' isadmin @;
|
||||||
|
put ',"isActive": true }';
|
||||||
|
run;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &fref1 lrecl=1000;
|
||||||
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
|
input;
|
||||||
|
put "Authorization: Bearer " _infile_;
|
||||||
|
put "Content-Type: application/json";
|
||||||
|
put "accept: application/json";
|
||||||
|
run;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
data _null_;
|
||||||
|
infile &fref0;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
data _null_;
|
||||||
|
infile &fref1;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
proc http method='POST' in=&fref0 headerin=&fref1 out=&fref2
|
||||||
|
url="&_sasjs_apiserverurl/SASjsApi/user";
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
debug level=1;
|
||||||
|
%end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&syscc ne 0)
|
||||||
|
,mac=ms_createuser.sas
|
||||||
|
,msg=%str(Issue submitting query to SASjsApi/user)
|
||||||
|
)
|
||||||
|
|
||||||
|
libname &libref JSON fileref=&fref2;
|
||||||
|
|
||||||
|
data &outds;
|
||||||
|
set &libref..root;
|
||||||
|
drop ordinal_root;
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&syscc ne 0)
|
||||||
|
,mac=ms_createuser.sas
|
||||||
|
,msg=%str(Issue reading response JSON)
|
||||||
|
)
|
||||||
|
|
||||||
|
/* reset options */
|
||||||
|
options &optval;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
filename &fref0 clear;
|
||||||
|
filename &fref1 clear;
|
||||||
|
filename &fref2 clear;
|
||||||
|
libname &libref clear;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend ms_createuser;
|
||||||
532
server/ms_createwebservice.sas
Normal file
532
server/ms_createwebservice.sas
Normal file
@@ -0,0 +1,532 @@
|
|||||||
|
/**
|
||||||
|
@file ms_createwebservice.sas
|
||||||
|
@brief Create a Web-Ready Stored Program
|
||||||
|
@details This macro creates a Stored Program along with the necessary precode
|
||||||
|
to enable the %webout() macro
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
<code>
|
||||||
|
%* compile macros ;
|
||||||
|
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||||
|
%inc mc;
|
||||||
|
|
||||||
|
%* parmcards lets us write to a text file from open code ;
|
||||||
|
filename ft15f001 temp;
|
||||||
|
parmcards4;
|
||||||
|
%webout(FETCH)
|
||||||
|
%* do some sas, any inputs are now already WORK tables;
|
||||||
|
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)
|
||||||
|
;;;;
|
||||||
|
%ms_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001)
|
||||||
|
|
||||||
|
</code>
|
||||||
|
|
||||||
|
For more examples of using these web services with the SASjs Adapter, see:
|
||||||
|
https://github.com/sasjs/adapter#readme
|
||||||
|
|
||||||
|
@param [in] path= (0) The full SASjs Drive path in which to create the service
|
||||||
|
@param [in] name= Stored Program name
|
||||||
|
@param [in] desc= The description of the service (not implemented yet)
|
||||||
|
@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] mDebug= (0) set to 1 to show debug messages in the log
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li ms_createfile.sas
|
||||||
|
@li mf_getuser.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mp_abort.sas
|
||||||
|
|
||||||
|
<h4> Related Files </h4>
|
||||||
|
@li ms_createwebservice.test.sas
|
||||||
|
|
||||||
|
@version 9.2
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_createwebservice(path=0
|
||||||
|
,name=initService
|
||||||
|
,precode=
|
||||||
|
,code=ft15f001
|
||||||
|
,desc=Not currently used
|
||||||
|
,mDebug=0
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%local dbg;
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
%put &sysmacroname entry vars:;
|
||||||
|
%put _local_;
|
||||||
|
%end;
|
||||||
|
%else %let dbg=*;
|
||||||
|
|
||||||
|
%mp_abort(iftrue=(&syscc ge 4 )
|
||||||
|
,mac=ms_createwebservice
|
||||||
|
,msg=%str(syscc=&syscc on macro entry)
|
||||||
|
)
|
||||||
|
%mp_abort(iftrue=("&path"="0")
|
||||||
|
,mac=ms_createwebservice
|
||||||
|
,msg=%str(Path not provided)
|
||||||
|
)
|
||||||
|
|
||||||
|
/* remove any trailing slash */
|
||||||
|
%if "%substr(&path,%length(&path),1)" = "/" %then
|
||||||
|
%let path=%substr(&path,1,%length(&path)-1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add webout macro
|
||||||
|
* These put statements are auto generated - to change the macro, change the
|
||||||
|
* source (ms_webout) and run `build.py`
|
||||||
|
*/
|
||||||
|
%local sasjsref;
|
||||||
|
%let sasjsref=%mf_getuniquefileref();
|
||||||
|
data _null_;
|
||||||
|
file &sasjsref termstr=crlf lrecl=512;
|
||||||
|
put "/* Created on %sysfunc(datetime(),datetime19.) by %mf_getuser() */";
|
||||||
|
/* WEBOUT BEGIN */
|
||||||
|
put ' ';
|
||||||
|
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
||||||
|
put ' ,engine=DATASTEP ';
|
||||||
|
put ' ,missing=NULL ';
|
||||||
|
put ' ,showmeta=NO ';
|
||||||
|
put ')/*/STORE SOURCE*/; ';
|
||||||
|
put '%local tempds colinfo fmtds i numcols; ';
|
||||||
|
put '%let numcols=0; ';
|
||||||
|
put ' ';
|
||||||
|
put '%if &action=OPEN %then %do; ';
|
||||||
|
put ' options nobomfile; ';
|
||||||
|
put ' data _null_;file &jref encoding=''utf-8'' lrecl=200; ';
|
||||||
|
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
||||||
|
put ' run; ';
|
||||||
|
put '%end; ';
|
||||||
|
put '%else %if (&action=ARR or &action=OBJ) %then %do; ';
|
||||||
|
put ' options validvarname=upcase; ';
|
||||||
|
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
||||||
|
put ' put ", ""%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":"; ';
|
||||||
|
put ' ';
|
||||||
|
put ' /* grab col defs */ ';
|
||||||
|
put ' proc contents noprint data=&ds ';
|
||||||
|
put ' out=_data_(keep=name type length format formatl formatd varnum label); ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' %let colinfo=%scan(&syslast,2,.); ';
|
||||||
|
put ' proc sort data=&colinfo; ';
|
||||||
|
put ' by varnum; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' /* move meta to mac vars */ ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' if _n_=1 then call symputx(''numcols'',nobs,''l''); ';
|
||||||
|
put ' set &colinfo end=last nobs=nobs; ';
|
||||||
|
put ' name=upcase(name); ';
|
||||||
|
put ' /* fix formats */ ';
|
||||||
|
put ' if type=2 or type=6 then do; ';
|
||||||
|
put ' typelong=''char''; ';
|
||||||
|
put ' length fmt $49.; ';
|
||||||
|
put ' if format='''' then fmt=cats(''$'',length,''.''); ';
|
||||||
|
put ' else if formatl=0 then fmt=cats(format,''.''); ';
|
||||||
|
put ' else fmt=cats(format,formatl,''.''); ';
|
||||||
|
put ' newlen=max(formatl,length); ';
|
||||||
|
put ' end; ';
|
||||||
|
put ' else do; ';
|
||||||
|
put ' typelong=''num''; ';
|
||||||
|
put ' if format='''' then fmt=''best.''; ';
|
||||||
|
put ' else if formatl=0 then fmt=cats(format,''.''); ';
|
||||||
|
put ' else if formatd=0 then fmt=cats(format,formatl,''.''); ';
|
||||||
|
put ' else fmt=cats(format,formatl,''.'',formatd); ';
|
||||||
|
put ' /* needs to be wide, for datetimes etc */ ';
|
||||||
|
put ' newlen=max(length,formatl,24); ';
|
||||||
|
put ' end; ';
|
||||||
|
put ' /* 32 char unique name */ ';
|
||||||
|
put ' newname=''sasjs''!!substr(cats(put(md5(name),$hex32.)),1,27); ';
|
||||||
|
put ' ';
|
||||||
|
put ' call symputx(cats(''name'',_n_),name,''l''); ';
|
||||||
|
put ' call symputx(cats(''newname'',_n_),newname,''l''); ';
|
||||||
|
put ' call symputx(cats(''len'',_n_),newlen,''l''); ';
|
||||||
|
put ' call symputx(cats(''length'',_n_),length,''l''); ';
|
||||||
|
put ' call symputx(cats(''fmt'',_n_),fmt,''l''); ';
|
||||||
|
put ' call symputx(cats(''type'',_n_),type,''l''); ';
|
||||||
|
put ' call symputx(cats(''typelong'',_n_),typelong,''l''); ';
|
||||||
|
put ' call symputx(cats(''label'',_n_),coalescec(label,name),''l''); ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %let tempds=%substr(_%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32); ';
|
||||||
|
put ' ';
|
||||||
|
put ' %if &engine=PROCJSON %then %do; ';
|
||||||
|
put ' %if &missing=STRING %then %do; ';
|
||||||
|
put ' %put &sysmacroname: Special Missings not supported in proc json.; ';
|
||||||
|
put ' %put &sysmacroname: Switching to DATASTEP engine; ';
|
||||||
|
put ' %goto datastep; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' data &tempds;set &ds; ';
|
||||||
|
put ' %if &fmt=N %then format _numeric_ best32.;; ';
|
||||||
|
put ' /* PRETTY is necessary to avoid line truncation in large files */ ';
|
||||||
|
put ' proc json out=&jref pretty ';
|
||||||
|
put ' %if &action=ARR %then nokeys ; ';
|
||||||
|
put ' ;export &tempds / nosastags fmtnumeric; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %if &engine=DATASTEP %then %do; ';
|
||||||
|
put ' %datastep: ';
|
||||||
|
put ' %if %sysfunc(exist(&ds)) ne 1 & %sysfunc(exist(&ds,VIEW)) ne 1 ';
|
||||||
|
put ' %then %do; ';
|
||||||
|
put ' %put &sysmacroname: &ds NOT FOUND!!!; ';
|
||||||
|
put ' %return; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %if &fmt=Y %then %do; ';
|
||||||
|
put ' data _data_; ';
|
||||||
|
put ' /* rename on entry */ ';
|
||||||
|
put ' set &ds(rename=( ';
|
||||||
|
put ' %do i=1 %to &numcols; ';
|
||||||
|
put ' &&name&i=&&newname&i ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' )); ';
|
||||||
|
put ' %do i=1 %to &numcols; ';
|
||||||
|
put ' length &&name&i $&&len&i; ';
|
||||||
|
put ' %if &&typelong&i=num %then %do; ';
|
||||||
|
put ' &&name&i=left(put(&&newname&i,&&fmt&i)); ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %do; ';
|
||||||
|
put ' &&name&i=put(&&newname&i,&&fmt&i); ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' drop &&newname&i; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' if _error_ then call symputx(''syscc'',1012); ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' %let fmtds=&syslast; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' ';
|
||||||
|
put ' proc format; /* credit yabwon for special null removal */ ';
|
||||||
|
put ' value bart (default=40) ';
|
||||||
|
put ' %if &missing=NULL %then %do; ';
|
||||||
|
put ' ._ - .z = null ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %do; ';
|
||||||
|
put ' ._ = [quote()] ';
|
||||||
|
put ' . = null ';
|
||||||
|
put ' .a - .z = [quote()] ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' other = [best.]; ';
|
||||||
|
put ' ';
|
||||||
|
put ' data &tempds; ';
|
||||||
|
put ' attrib _all_ label=''''; ';
|
||||||
|
put ' %do i=1 %to &numcols; ';
|
||||||
|
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
||||||
|
put ' length &&name&i $32767; ';
|
||||||
|
put ' format &&name&i $32767.; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %if &fmt=Y %then %do; ';
|
||||||
|
put ' set &fmtds; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %do; ';
|
||||||
|
put ' set &ds; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' format _numeric_ bart.; ';
|
||||||
|
put ' %do i=1 %to &numcols; ';
|
||||||
|
put ' %if &&typelong&i=char or &fmt=Y %then %do; ';
|
||||||
|
put ' if findc(&&name&i,''"\''!!''0A0D09000E0F01021011''x) then do; ';
|
||||||
|
put ' &&name&i=''"''!!trim( ';
|
||||||
|
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
|
||||||
|
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
|
||||||
|
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
|
||||||
|
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
|
||||||
|
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
|
||||||
|
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
|
||||||
|
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
|
||||||
|
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
|
||||||
|
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
|
||||||
|
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
|
||||||
|
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
|
||||||
|
put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) ';
|
||||||
|
put ' ))))))))))))!!''"''; ';
|
||||||
|
put ' end; ';
|
||||||
|
put ' else &&name&i=quote(cats(&&name&i)); ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' ';
|
||||||
|
put ' /* write to temp loc to avoid _webout truncation ';
|
||||||
|
put ' - https://support.sas.com/kb/49/325.html */ ';
|
||||||
|
put ' filename _sjs temp lrecl=131068 encoding=''utf-8''; ';
|
||||||
|
put ' data _null_; file _sjs lrecl=131068 encoding=''utf-8'' mod ; ';
|
||||||
|
put ' if _n_=1 then put "["; ';
|
||||||
|
put ' set &tempds; ';
|
||||||
|
put ' if _n_>1 then put "," @; put ';
|
||||||
|
put ' %if &action=ARR %then "[" ; %else "{" ; ';
|
||||||
|
put ' %do i=1 %to &numcols; ';
|
||||||
|
put ' %if &i>1 %then "," ; ';
|
||||||
|
put ' %if &action=OBJ %then """&&name&i"":" ; ';
|
||||||
|
put ' &&name&i ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %if &action=ARR %then "]" ; %else "}" ; ; ';
|
||||||
|
put ' /* now write the long strings to _webout 1 byte at a time */ ';
|
||||||
|
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 ' rc=fput(fileid, "]"); ';
|
||||||
|
put ' rc=fwrite(fileid); ';
|
||||||
|
put ' rc=fclose(filein); ';
|
||||||
|
put ' rc=fclose(fileid); ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' filename _sjs clear; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' ';
|
||||||
|
put ' proc sql; ';
|
||||||
|
put ' drop table &colinfo, &tempds; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %if &showmeta=YES %then %do; ';
|
||||||
|
put ' data _null_; file &jref encoding=''utf-8'' mod; ';
|
||||||
|
put ' put ", ""$%lowcase(%sysfunc(coalescec(&dslabel,&ds)))"":{""vars"":{"; ';
|
||||||
|
put ' do i=1 to &numcols; ';
|
||||||
|
put ' name=quote(trim(symget(cats(''name'',i)))); ';
|
||||||
|
put ' format=quote(trim(symget(cats(''fmt'',i)))); ';
|
||||||
|
put ' label=quote(trim(symget(cats(''label'',i)))); ';
|
||||||
|
put ' length=quote(trim(symget(cats(''length'',i)))); ';
|
||||||
|
put ' type=quote(trim(symget(cats(''typelong'',i)))); ';
|
||||||
|
put ' if i>1 then put "," @@; ';
|
||||||
|
put ' put name '':{"format":'' format '',"label":'' label ';
|
||||||
|
put ' '',"length":'' length '',"type":'' type ''}''; ';
|
||||||
|
put ' end; ';
|
||||||
|
put ' put ''}}''; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put '%end; ';
|
||||||
|
put ' ';
|
||||||
|
put '%else %if &action=CLOSE %then %do; ';
|
||||||
|
put ' data _null_; file &jref encoding=''utf-8'' mod ; ';
|
||||||
|
put ' put "}"; ';
|
||||||
|
put ' run; ';
|
||||||
|
put '%end; ';
|
||||||
|
put '%mend mp_jsonout; ';
|
||||||
|
put ' ';
|
||||||
|
put '%macro mf_getuser(type=META ';
|
||||||
|
put ')/*/STORE SOURCE*/; ';
|
||||||
|
put ' %local user metavar; ';
|
||||||
|
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
||||||
|
put ' %else %let metavar=_metaperson; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
||||||
|
put ' %else %if %symexist(&metavar) %then %do; ';
|
||||||
|
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
||||||
|
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
||||||
|
put ' /* but be sure to quote in case of usernames with commas */ ';
|
||||||
|
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %let user=&sysuserid; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %quote(&user) ';
|
||||||
|
put ' ';
|
||||||
|
put '%mend mf_getuser; ';
|
||||||
|
put ' ';
|
||||||
|
put '%macro ms_webout(action,ds,dslabel=,fref=_webout,fmt=Y,missing=NULL ';
|
||||||
|
put ' ,showmeta=NO ';
|
||||||
|
put '); ';
|
||||||
|
put '%global _webin_file_count _webin_fileref1 _webin_name1 _program _debug ';
|
||||||
|
put ' sasjs_tables; ';
|
||||||
|
put ' ';
|
||||||
|
put '%local i tempds; ';
|
||||||
|
put '%let action=%upcase(&action); ';
|
||||||
|
put ' ';
|
||||||
|
put '%if &action=FETCH %then %do; ';
|
||||||
|
put ' %if %str(&_debug) ge 131 %then %do; ';
|
||||||
|
put ' options mprint notes mprintnest; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %let _webin_file_count=%eval(&_webin_file_count+0); ';
|
||||||
|
put ' /* now read in the data */ ';
|
||||||
|
put ' %do i=1 %to &_webin_file_count; ';
|
||||||
|
put ' %if &_webin_file_count=1 %then %do; ';
|
||||||
|
put ' %let _webin_fileref1=&_webin_fileref; ';
|
||||||
|
put ' %let _webin_name1=&_webin_name; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' infile &&_webin_fileref&i termstr=crlf lrecl=32767; ';
|
||||||
|
put ' input; ';
|
||||||
|
put ' call symputx(''input_statement'',_infile_); ';
|
||||||
|
put ' putlog "&&_webin_name&i input statement: " _infile_; ';
|
||||||
|
put ' stop; ';
|
||||||
|
put ' data &&_webin_name&i; ';
|
||||||
|
put ' infile &&_webin_fileref&i firstobs=2 dsd termstr=crlf encoding=''utf-8'' ';
|
||||||
|
put ' lrecl=32767; ';
|
||||||
|
put ' input &input_statement; ';
|
||||||
|
put ' %if %str(&_debug) ge 131 %then %do; ';
|
||||||
|
put ' if _n_<20 then putlog _infile_; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' %let sasjs_tables=&sasjs_tables &&_webin_name&i; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put '%end; ';
|
||||||
|
put ' ';
|
||||||
|
put '%else %if &action=OPEN %then %do; ';
|
||||||
|
put ' /* fix encoding and ensure enough lrecl */ ';
|
||||||
|
put ' OPTIONS NOBOMFILE lrecl=32767; ';
|
||||||
|
put ' ';
|
||||||
|
put ' /* set the header */ ';
|
||||||
|
put ' %mfs_httpheader(Content-type,application/json) ';
|
||||||
|
put ' ';
|
||||||
|
put ' /* setup json. */ ';
|
||||||
|
put ' data _null_;file &fref encoding=''utf-8'' termstr=lf ; ';
|
||||||
|
put ' put ''{"SYSDATE" : "'' "&SYSDATE" ''"''; ';
|
||||||
|
put ' put '',"SYSTIME" : "'' "&SYSTIME" ''"''; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' ';
|
||||||
|
put '%end; ';
|
||||||
|
put ' ';
|
||||||
|
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
||||||
|
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt,jref=&fref ';
|
||||||
|
put ' ,engine=DATASTEP,missing=&missing,showmeta=&showmeta ';
|
||||||
|
put ' ) ';
|
||||||
|
put '%end; ';
|
||||||
|
put '%else %if &action=CLOSE %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 ' options obs=10; ';
|
||||||
|
put ' data;run;%let tempds=%scan(&syslast,2,.); ';
|
||||||
|
put ' ods output Members=&tempds; ';
|
||||||
|
put ' proc datasets library=WORK memtype=data; ';
|
||||||
|
put ' %local wtcnt;%let wtcnt=0; ';
|
||||||
|
put ' data _null_; ';
|
||||||
|
put ' set &tempds; ';
|
||||||
|
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
||||||
|
put ' if not (upcase(name)=:"_DATA_"); ';
|
||||||
|
put ' i+1; ';
|
||||||
|
put ' call symputx(cats(''wt'',i),name,''l''); ';
|
||||||
|
put ' call symputx(''wtcnt'',i,''l''); ';
|
||||||
|
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
||||||
|
put ' put ",""WORK"":{"; ';
|
||||||
|
put ' %do i=1 %to &wtcnt; ';
|
||||||
|
put ' %let wt=&&wt&i; ';
|
||||||
|
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
||||||
|
put ' dsid=open("WORK.&wt",''is''); ';
|
||||||
|
put ' nlobs=attrn(dsid,''NLOBS''); ';
|
||||||
|
put ' nvars=attrn(dsid,''NVARS''); ';
|
||||||
|
put ' rc=close(dsid); ';
|
||||||
|
put ' if &i>1 then put '',''@; ';
|
||||||
|
put ' put " ""&wt"" : {"; ';
|
||||||
|
put ' put ''"nlobs":'' nlobs; ';
|
||||||
|
put ' put '',"nvars":'' nvars; ';
|
||||||
|
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=YES) ';
|
||||||
|
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
||||||
|
put ' put "}"; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
|
||||||
|
put ' put "}"; ';
|
||||||
|
put ' run; ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' /* close off json */ ';
|
||||||
|
put ' data _null_;file &fref mod encoding=''utf-8'' termstr=lf lrecl=32767; ';
|
||||||
|
put ' _PROGRAM=quote(trim(resolve(symget(''_PROGRAM'')))); ';
|
||||||
|
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
|
||||||
|
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
|
||||||
|
put ' put ",""_DEBUG"" : ""&_debug"" "; ';
|
||||||
|
put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
|
||||||
|
put ' put ",""SYSCC"" : ""&syscc"" "; ';
|
||||||
|
put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
|
||||||
|
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
|
||||||
|
put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); ';
|
||||||
|
put ' put '',"SYSHOSTINFOLONG" : '' SYSHOSTINFOLONG; ';
|
||||||
|
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
|
||||||
|
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
|
||||||
|
put ' put ",""SYSPROCESSMODE"" : ""&SYSPROCESSMODE"" "; ';
|
||||||
|
put ' length SYSPROCESSNAME $512; ';
|
||||||
|
put ' SYSPROCESSNAME=quote(urlencode(cats(SYSPROCESSNAME))); ';
|
||||||
|
put ' put ",""SYSPROCESSNAME"" : " SYSPROCESSNAME; ';
|
||||||
|
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
|
||||||
|
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
|
||||||
|
put ' put ",""SYSSITE"" : ""&syssite"" "; ';
|
||||||
|
put ' put ",""SYSTCPIPHOSTNAME"" : ""&SYSTCPIPHOSTNAME"" "; ';
|
||||||
|
put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
|
||||||
|
put ' put '',"SYSVLONG" : '' sysvlong; ';
|
||||||
|
put ' syswarningtext=quote(cats(symget(''SYSWARNINGTEXT''))); ';
|
||||||
|
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
|
||||||
|
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
||||||
|
put ' length autoexec $512; ';
|
||||||
|
put ' autoexec=quote(urlencode(trim(getoption(''autoexec'')))); ';
|
||||||
|
put ' put '',"AUTOEXEC" : '' autoexec; ';
|
||||||
|
put ' length memsize $32; ';
|
||||||
|
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
||||||
|
put ' memsize=quote(cats(memsize)); ';
|
||||||
|
put ' put '',"MEMSIZE" : '' memsize; ';
|
||||||
|
put ' put "}" @; ';
|
||||||
|
put ' run; ';
|
||||||
|
put '%end; ';
|
||||||
|
put ' ';
|
||||||
|
put '%mend ms_webout; ';
|
||||||
|
put ' ';
|
||||||
|
put '%macro mfs_httpheader(header_name ';
|
||||||
|
put ' ,header_value ';
|
||||||
|
put ')/*/STORE SOURCE*/; ';
|
||||||
|
put '%global sasjs_stpsrv_header_loc; ';
|
||||||
|
put '%local fref fid i; ';
|
||||||
|
put ' ';
|
||||||
|
put '%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do; ';
|
||||||
|
put ' %put &=fref &=sasjs_stpsrv_header_loc; ';
|
||||||
|
put ' %put %str(ERR)OR: %sysfunc(sysmsg()); ';
|
||||||
|
put ' %return; ';
|
||||||
|
put '%end; ';
|
||||||
|
put ' ';
|
||||||
|
put '%let fid=%sysfunc(fopen(&fref,A)); ';
|
||||||
|
put ' ';
|
||||||
|
put '%if &fid=0 %then %do; ';
|
||||||
|
put ' %put %str(ERR)OR: %sysfunc(sysmsg()); ';
|
||||||
|
put ' %return; ';
|
||||||
|
put '%end; ';
|
||||||
|
put ' ';
|
||||||
|
put '%let rc=%sysfunc(fput(&fid,%str(&header_name): %str(&header_value))); ';
|
||||||
|
put '%let rc=%sysfunc(fwrite(&fid)); ';
|
||||||
|
put ' ';
|
||||||
|
put '%let rc=%sysfunc(fclose(&fid)); ';
|
||||||
|
put '%let rc=%sysfunc(filename(&fref)); ';
|
||||||
|
put ' ';
|
||||||
|
put '%mend mfs_httpheader; ';
|
||||||
|
/* WEBOUT END */
|
||||||
|
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO);';
|
||||||
|
put ' %ms_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing';
|
||||||
|
put ' ,showmeta=&showmeta';
|
||||||
|
put ' )';
|
||||||
|
put '%mend;';
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* add precode and code */
|
||||||
|
%local x fref freflist;
|
||||||
|
%let freflist=&precode &code ;
|
||||||
|
%do x=1 %to %sysfunc(countw(&freflist));
|
||||||
|
%let fref=%scan(&freflist,&x);
|
||||||
|
%put &sysmacroname: adding &fref;
|
||||||
|
data _null_;
|
||||||
|
file &sasjsref lrecl=3000 termstr=crlf mod;
|
||||||
|
infile &fref lrecl=3000;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
/* create the web service */
|
||||||
|
%ms_createfile(&path/&name..sas, inref=&sasjsref, mdebug=&mdebug)
|
||||||
|
|
||||||
|
%put ;%put ;%put ;%put ;%put ;%put ;
|
||||||
|
%put &sysmacroname: STP &name successfully created in &path;
|
||||||
|
%put ;%put ;%put ;
|
||||||
|
%put Check it out here:;
|
||||||
|
%put ;%put ;%put ;
|
||||||
|
%put &_sasjs_apiserverurl.&_sasjs_apipath?_PROGRAM=&path/&name;
|
||||||
|
%put ;%put ;%put ;%put ;%put ;%put ;
|
||||||
|
|
||||||
|
%mend ms_createwebservice;
|
||||||
107
server/ms_getusers.sas
Normal file
107
server/ms_getusers.sas
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/**
|
||||||
|
@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.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
%ms_getusers(outds=userlist)
|
||||||
|
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
@param [out] outds= (work.ms_getusers) This output dataset will contain the
|
||||||
|
list of user accounts. Format:
|
||||||
|
|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_createuser.sas
|
||||||
|
@li ms_getusers.test.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_getusers(
|
||||||
|
outds=work.ms_getusers
|
||||||
|
,mdebug=0
|
||||||
|
);
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&syscc ne 0)
|
||||||
|
,mac=ms_getusers.sas
|
||||||
|
,msg=%str(syscc=&syscc on macro entry)
|
||||||
|
)
|
||||||
|
|
||||||
|
%local fref0 fref1 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;
|
||||||
|
put "Authorization: Bearer " _infile_;
|
||||||
|
put "accept: application/json";
|
||||||
|
run;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
data _null_;
|
||||||
|
infile &fref0;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
proc http method='GET' headerin=&fref0 out=&fref1
|
||||||
|
url="&_sasjs_apiserverurl/SASjsApi/user";
|
||||||
|
%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)
|
||||||
|
)
|
||||||
|
|
||||||
|
libname &libref JSON fileref=&fref1;
|
||||||
|
|
||||||
|
data &outds;
|
||||||
|
set &libref..root;
|
||||||
|
drop ordinal_root;
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
%mp_abort(
|
||||||
|
iftrue=(&syscc ne 0)
|
||||||
|
,mac=ms_getusers.sas
|
||||||
|
,msg=%str(Issue reading response JSON)
|
||||||
|
)
|
||||||
|
|
||||||
|
/* reset options */
|
||||||
|
options &optval;
|
||||||
|
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
filename &fref0 clear;
|
||||||
|
filename &fref1 clear;
|
||||||
|
libname &libref clear;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend ms_getusers;
|
||||||
@@ -15,48 +15,154 @@
|
|||||||
parameter)
|
parameter)
|
||||||
@param [in] debug= (131) The value to supply to the _debug URL parameter
|
@param [in] debug= (131) The value to supply to the _debug URL parameter
|
||||||
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
@param [in] inputparams=(_null_) A dataset containing name/value pairs in the
|
||||||
|
following format:
|
||||||
|
|name:$32|value:$10000|
|
||||||
|
|---|---|
|
||||||
|
|stpmacname|some value|
|
||||||
|
|mustbevalidname|can be anything, oops, %abort!!|
|
||||||
|
@param [in] inputfiles= (_null_) A dataset containing fileref/name/filename in
|
||||||
|
the following format:
|
||||||
|
|fileref:$8|name:$32|filename:$256|
|
||||||
|
|---|---|--|
|
||||||
|
|someref|some_name|some_filename.xls|
|
||||||
|
|fref2|another_file|zyx_v2.csv|
|
||||||
|
|
||||||
@param [out] outref= (outweb) The output fileref to contain the response JSON
|
@param [out] outref= (outweb) The output fileref to contain the response JSON
|
||||||
(will be created using temp engine)
|
(will be created using temp engine)
|
||||||
|
@param [out] outlogds= (_null_) Set to the name of a dataset to contain the
|
||||||
|
log. Table format:
|
||||||
|
|line:$2000|
|
||||||
|
|---|
|
||||||
|
|log line 1|
|
||||||
|
|log line 2|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquelibref.sas
|
||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro ms_runstp(pgm
|
%macro ms_runstp(pgm
|
||||||
,debug=131
|
,debug=131
|
||||||
|
,inputparams=_null_
|
||||||
|
,inputfiles=_null_
|
||||||
,outref=outweb
|
,outref=outweb
|
||||||
|
,outlogds=_null_
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local dbg fname1;
|
%local dbg mainref authref boundary;
|
||||||
|
%let mainref=%mf_getuniquefileref();
|
||||||
|
%let authref=%mf_getuniquefileref();
|
||||||
|
%let boundary=%mf_getuniquename();
|
||||||
|
%if &inputparams=0 %then %let inputparams=_null_;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
%end;
|
%end;
|
||||||
%else %let dbg=*;
|
%else %let dbg=*;
|
||||||
%let fname1=%mf_getuniquefileref();
|
|
||||||
|
|
||||||
%mp_abort(iftrue=("&pgm"="")
|
%mp_abort(iftrue=("&pgm"="")
|
||||||
,mac=&sysmacroname
|
,mac=&sysmacroname
|
||||||
,msg=%str(Program not provided)
|
,msg=%str(Program not provided)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* avoid sending bom marker to API */
|
||||||
|
%local optval;
|
||||||
|
%let optval=%sysfunc(getoption(bomfile));
|
||||||
|
options nobomfile;
|
||||||
|
|
||||||
|
/* add params */
|
||||||
data _null_;
|
data _null_;
|
||||||
file &fname1 lrecl=1000;
|
file &mainref termstr=crlf lrecl=32767 mod;
|
||||||
|
length line $1000 name $32 value $32767;
|
||||||
|
if _n_=1 then call missing(of _all_);
|
||||||
|
set &inputparams;
|
||||||
|
put "--&boundary";
|
||||||
|
line=cats('Content-Disposition: form-data; name="',name,'"');
|
||||||
|
put line;
|
||||||
|
put ;
|
||||||
|
put value;
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* parse input file list */
|
||||||
|
%local webcount;
|
||||||
|
%let webcount=0;
|
||||||
|
data _null_;
|
||||||
|
set &inputfiles end=last;
|
||||||
|
length fileref $8 name $32 filename $256;
|
||||||
|
call symputx(cats('webref',_n_),fileref,'l');
|
||||||
|
call symputx(cats('webname',_n_),name,'l');
|
||||||
|
call symputx(cats('webfilename',_n_),filename,'l');
|
||||||
|
if last then do;
|
||||||
|
call symputx('webcount',_n_);
|
||||||
|
call missing(of _all_);
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* write out the input files */
|
||||||
|
%local i;
|
||||||
|
%do i=1 %to &webcount;
|
||||||
|
data _null_;
|
||||||
|
file &mainref termstr=crlf lrecl=32767 mod;
|
||||||
|
infile &&webref&i lrecl=32767;
|
||||||
|
if _n_ = 1 then do;
|
||||||
|
length line $32767;
|
||||||
|
line=cats(
|
||||||
|
'Content-Disposition: form-data; name="'
|
||||||
|
,"&&webname&i"
|
||||||
|
,'"; filename="'
|
||||||
|
,"&&webfilename&i"
|
||||||
|
,'"'
|
||||||
|
);
|
||||||
|
put "--&boundary";
|
||||||
|
put line;
|
||||||
|
put "Content-Type: text/plain";
|
||||||
|
put ;
|
||||||
|
end;
|
||||||
|
input;
|
||||||
|
put _infile_; /* add the actual file to be sent */
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &mainref termstr=crlf mod;
|
||||||
|
put "--&boundary--";
|
||||||
|
run;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &authref lrecl=1000;
|
||||||
infile "&_sasjs_tokenfile" lrecl=1000;
|
infile "&_sasjs_tokenfile" lrecl=1000;
|
||||||
input;
|
input;
|
||||||
put 'Authorization: Bearer ' _infile_;
|
put 'Authorization: Bearer ' _infile_;
|
||||||
|
put "Content-Type: multipart/form-data; boundary=&boundary";
|
||||||
run;
|
run;
|
||||||
|
|
||||||
filename &outref temp;
|
%if &mdebug=1 %then %do;
|
||||||
|
data _null_;
|
||||||
|
infile &authref;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
data _null_;
|
||||||
|
infile &mainref;
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
filename &outref temp lrecl=32767;
|
||||||
/* prepare request*/
|
/* prepare request*/
|
||||||
proc http method='POST' headerin=&fname1 out=&outref
|
proc http method='POST' headerin=&authref in=&mainref out=&outref
|
||||||
url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131";
|
url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131";
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
debug level=2;
|
||||||
|
%end;
|
||||||
run;
|
run;
|
||||||
%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
|
%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
|
||||||
or &mdebug=1 %then %do;
|
%then %do;
|
||||||
data _null_;infile &outref;input;putlog _infile_;run;
|
data _null_;infile &outref;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
%mp_abort(
|
%mp_abort(
|
||||||
@@ -65,6 +171,20 @@ run;
|
|||||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* reset options */
|
||||||
|
options &optval;
|
||||||
|
|
||||||
|
%if &outlogds ne _null_ or &mdebug=1 %then %do;
|
||||||
|
%local dumplib;
|
||||||
|
%let dumplib=%mf_getuniquelibref();
|
||||||
|
libname &dumplib json (&outref);
|
||||||
|
data &outlogds;
|
||||||
|
set &dumplib..log;
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
putlog line=;
|
||||||
|
%end;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname exit vars:;
|
%put &sysmacroname exit vars:;
|
||||||
@@ -72,6 +192,7 @@ run;
|
|||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
/* clear refs */
|
/* clear refs */
|
||||||
filename &fname1 clear;
|
filename &authref;
|
||||||
|
filename &mainref;
|
||||||
%end;
|
%end;
|
||||||
%mend ms_runstp;
|
%mend ms_runstp;
|
||||||
154
server/ms_testservice.sas
Normal file
154
server/ms_testservice.sas
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Will execute a SASjs web service on SASjs Server
|
||||||
|
@details Prepares the input files and retrieves the resulting datasets from
|
||||||
|
the response JSON.
|
||||||
|
|
||||||
|
@param [in] program The Stored 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= (131) Provide the _debug value to pass to the STP
|
||||||
|
@param [in] mdebug= (0) Set to 1 to provide macro debugging (this macro)
|
||||||
|
@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.
|
||||||
|
@param [out] outlogds= (_null_) Set to the name of a dataset to contain the
|
||||||
|
log. Table format:
|
||||||
|
|line:$2000|
|
||||||
|
|---|
|
||||||
|
|log line 1|
|
||||||
|
|log line 2|
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@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_runstp.sas
|
||||||
|
|
||||||
|
<h4> Related Programs </h4>
|
||||||
|
@li mp_testservice.test.sas
|
||||||
|
|
||||||
|
@version 9.4
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_testservice(program,
|
||||||
|
inputfiles=0,
|
||||||
|
inputdatasets=0,
|
||||||
|
inputparams=0,
|
||||||
|
debug=0,
|
||||||
|
mdebug=0,
|
||||||
|
outlib=0,
|
||||||
|
outref=0,
|
||||||
|
outlogds=_null_
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
%local dbg i var ds1 fref1 chopout1 chopout2;
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
%put &sysmacroname entry vars:;
|
||||||
|
%put _local_;
|
||||||
|
%end;
|
||||||
|
%else %let dbg=*;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* parse the filerefs - convert to a dataset */
|
||||||
|
%let ds1=%mf_getuniquename();
|
||||||
|
data &ds1;
|
||||||
|
length fileref $8 name $32 filename $256 var $300;
|
||||||
|
if "&inputfiles" ne "0" then do;
|
||||||
|
webcount=countw("&inputfiles");
|
||||||
|
do i=1 to webcount;
|
||||||
|
var=scan("&inputfiles",i,' ');
|
||||||
|
fileref=scan(var,1,':');
|
||||||
|
name=scan(var,2,':');
|
||||||
|
filename=cats(name,'.csv');
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
/* execute the STP */
|
||||||
|
%let fref1=%mf_getuniquefileref();
|
||||||
|
|
||||||
|
%ms_runstp(&program
|
||||||
|
,debug=&debug
|
||||||
|
,inputparams=&inputparams
|
||||||
|
,inputfiles=&ds1
|
||||||
|
,outref=&fref1
|
||||||
|
,mdebug=&mdebug
|
||||||
|
,outlogds=&outlogds
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/* SASjs services have the _webout embedded in wrapper JSON */
|
||||||
|
/* Files can also be very large - so use a dedicated macro to chop it out */
|
||||||
|
%local matchstr1 matchstr2 ;
|
||||||
|
%let matchstr1={"status":"success","_webout":{;
|
||||||
|
%let matchstr2=},"log":[{;
|
||||||
|
%let chopout1=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop1);
|
||||||
|
%let chopout2=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop2);
|
||||||
|
|
||||||
|
%mp_chop("%sysfunc(pathname(&fref1,F))"
|
||||||
|
,matchvar=matchstr1
|
||||||
|
,keep=LAST
|
||||||
|
,matchpoint=END
|
||||||
|
,offset=-1
|
||||||
|
,outfile="&chopout1"
|
||||||
|
,mdebug=&mdebug
|
||||||
|
)
|
||||||
|
|
||||||
|
%mp_chop("&chopout1"
|
||||||
|
,matchvar=matchstr2
|
||||||
|
,keep=FIRST
|
||||||
|
,matchpoint=START
|
||||||
|
,offset=1
|
||||||
|
,outfile="&chopout2"
|
||||||
|
,mdebug=&mdebug
|
||||||
|
)
|
||||||
|
|
||||||
|
%if &outlib ne 0 %then %do;
|
||||||
|
libname &outlib json "&chopout2";
|
||||||
|
%end;
|
||||||
|
%if &outref ne 0 %then %do;
|
||||||
|
filename &outref "&chopout2";
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%if &mdebug=0 %then %do;
|
||||||
|
filename &webref clear;
|
||||||
|
filename &fref1 clear;
|
||||||
|
filename &fref2 clear;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
%put &sysmacroname exit vars:;
|
||||||
|
%put _local_;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend ms_testservice;
|
||||||
@@ -67,13 +67,14 @@
|
|||||||
%let _webin_name1=&_webin_name;
|
%let _webin_name1=&_webin_name;
|
||||||
%end;
|
%end;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &&_webin_fileref&i termstr=crlf;
|
infile &&_webin_fileref&i termstr=crlf lrecl=32767;
|
||||||
input;
|
input;
|
||||||
call symputx('input_statement',_infile_);
|
call symputx('input_statement',_infile_);
|
||||||
putlog "&&_webin_name&i input statement: " _infile_;
|
putlog "&&_webin_name&i input statement: " _infile_;
|
||||||
stop;
|
stop;
|
||||||
data &&_webin_name&i;
|
data &&_webin_name&i;
|
||||||
infile &&_webin_fileref&i firstobs=2 dsd termstr=crlf encoding='utf-8';
|
infile &&_webin_fileref&i firstobs=2 dsd termstr=crlf encoding='utf-8'
|
||||||
|
lrecl=32767;
|
||||||
input &input_statement;
|
input &input_statement;
|
||||||
%if %str(&_debug) ge 131 %then %do;
|
%if %str(&_debug) ge 131 %then %do;
|
||||||
if _n_<20 then putlog _infile_;
|
if _n_<20 then putlog _infile_;
|
||||||
@@ -84,14 +85,14 @@
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%else %if &action=OPEN %then %do;
|
%else %if &action=OPEN %then %do;
|
||||||
/* fix encoding */
|
/* fix encoding and ensure enough lrecl */
|
||||||
OPTIONS NOBOMFILE;
|
OPTIONS NOBOMFILE lrecl=32767;
|
||||||
|
|
||||||
/* set the header */
|
/* set the header */
|
||||||
%mfs_httpheader(Content-type,application/json)
|
%mfs_httpheader(Content-type,application/json)
|
||||||
|
|
||||||
/* setup json */
|
/* setup json. */
|
||||||
data _null_;file &fref encoding='utf-8' termstr=lf;
|
data _null_;file &fref encoding='utf-8' termstr=lf ;
|
||||||
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
||||||
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
||||||
run;
|
run;
|
||||||
@@ -135,12 +136,12 @@
|
|||||||
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
||||||
put "}";
|
put "}";
|
||||||
%end;
|
%end;
|
||||||
data _null_; file &fref mod encoding='utf-8' termstr=lf termstr=lf;
|
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
||||||
put "}";
|
put "}";
|
||||||
run;
|
run;
|
||||||
%end;
|
%end;
|
||||||
/* close off json */
|
/* close off json */
|
||||||
data _null_;file &fref mod encoding='utf-8' termstr=lf;
|
data _null_;file &fref mod encoding='utf-8' termstr=lf lrecl=32767;
|
||||||
_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()"" ";
|
||||||
|
|||||||
@@ -30,4 +30,12 @@
|
|||||||
),
|
),
|
||||||
desc=Checking mf_isint(-1),
|
desc=Checking mf_isint(-1),
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_isint()"="0"
|
||||||
|
),
|
||||||
|
desc=Checking mf_isint(),
|
||||||
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
@@ -41,7 +41,7 @@ run;
|
|||||||
|
|
||||||
/* multibyte string check */
|
/* multibyte string check */
|
||||||
|
|
||||||
filename tmp2 temp;
|
filename tmp2 temp lrecl=500;
|
||||||
data _null_;
|
data _null_;
|
||||||
file tmp2;
|
file tmp2;
|
||||||
put "'╤', '╔', '╗', '═', '╧', '╚', '╝', '║', '╟', '─', '┼', '║', '╢', '│'";
|
put "'╤', '╔', '╗', '═', '╧', '╚', '╝', '║', '╟', '─', '┼', '║', '╢', '│'";
|
||||||
|
|||||||
70
tests/crossplatform/mp_chop.test.sas
Normal file
70
tests/crossplatform/mp_chop.test.sas
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mp_chop.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mp_chop.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
/* prep input string */
|
||||||
|
%let src="%sysfunc(pathname(work))/file.txt";
|
||||||
|
%let str=Chop here!;
|
||||||
|
%let out1="%sysfunc(pathname(work))/file1.txt";
|
||||||
|
%let out2="%sysfunc(pathname(work))/file2.txt";
|
||||||
|
%let out3="%sysfunc(pathname(work))/file3.txt";
|
||||||
|
%let out4="%sysfunc(pathname(work))/file4.txt";
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &src;
|
||||||
|
put "startsection&str.endsection";
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mp_chop(&src, matchvar=str, keep=FIRST, outfile=&out1)
|
||||||
|
%mp_chop(&src, matchvar=str, keep=LAST, outfile=&out2)
|
||||||
|
%mp_chop(&src, matchvar=str, keep=FIRST, matchpoint=END, outfile=&out3)
|
||||||
|
%mp_chop(&src, matchvar=str, keep=LAST, matchpoint=END, outfile=&out4)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
infile &out1 lrecl=200;
|
||||||
|
input;
|
||||||
|
call symputx('test1',_infile_);
|
||||||
|
data _null_;
|
||||||
|
infile &out2 lrecl=200;
|
||||||
|
input;
|
||||||
|
call symputx('test2',_infile_);
|
||||||
|
data _null_;
|
||||||
|
infile &out3 lrecl=200;
|
||||||
|
input;
|
||||||
|
call symputx('test3',_infile_);
|
||||||
|
data _null_;
|
||||||
|
infile &out4 lrecl=200;
|
||||||
|
input;
|
||||||
|
call symputx('test4',_infile_);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test1" = "startsection"),
|
||||||
|
desc=Checking keep FIRST matchpoint START
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test2" = "Chop here!endsection"),
|
||||||
|
desc=Checking keep LAST matchpoint START
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test3" = "startsectionChop here!"),
|
||||||
|
desc=Checking keep FIRST matchpoint END
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test4" = "endsection"),
|
||||||
|
desc=Checking keep LAST matchpoint END
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
28
tests/crossplatform/mp_createwebservice.test.sas
Normal file
28
tests/crossplatform/mp_createwebservice.test.sas
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_createwebservice.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
@li mp_createwebservice.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%let path=&mcTestAppLoc/mp_createwebservice;
|
||||||
|
%let name=myservice;
|
||||||
|
%let fref=%mf_getuniquefileref();
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &fref lrecl=3000;
|
||||||
|
put '%put hello world;';
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mp_createwebservice(path=&path,name=&name,code=&fref,mdebug=&sasjs_mdebug)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
, cards_file= "%sysfunc(pathname(work))/cars.sas"
|
, cards_file= "%sysfunc(pathname(work))/cars.sas"
|
||||||
, showlog=NO
|
, showlog=NO
|
||||||
)
|
)
|
||||||
%inc "%sysfunc(pathname(work))/cars.sas"/source2;
|
%inc "%sysfunc(pathname(work))/cars.sas"/source2 lrecl=32767;
|
||||||
|
|
||||||
proc compare base=sashelp.cars compare=work.test;
|
proc compare base=sashelp.cars compare=work.test;
|
||||||
quit;
|
quit;
|
||||||
@@ -48,7 +48,7 @@ run;
|
|||||||
, append=
|
, append=
|
||||||
)
|
)
|
||||||
|
|
||||||
%inc "%sysfunc(pathname(work))/c2.sas"/source2;
|
%inc "%sysfunc(pathname(work))/c2.sas"/source2 lrecl=32767;
|
||||||
|
|
||||||
proc compare base=work.binarybase compare=work.binarycompare;
|
proc compare base=work.binarybase compare=work.binarycompare;
|
||||||
run;
|
run;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
|
|
||||||
%macro gsubtest();
|
%macro gsubtest();
|
||||||
%if "%substr(&sysver,1,4)"="V.04" %then %do;
|
%if "%substr(&sysver.XX,1,4)"="V.04" %then %do;
|
||||||
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
||||||
%return;
|
%return;
|
||||||
%end;
|
%end;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ run;
|
|||||||
%let str=%str(replacewith trailing spaces );
|
%let str=%str(replacewith trailing spaces );
|
||||||
%let rep=%str( with more spaces );
|
%let rep=%str( with more spaces );
|
||||||
data _null_;
|
data _null_;
|
||||||
file &test2;
|
file &test2 lrecl=500;
|
||||||
put 'blahblah';
|
put 'blahblah';
|
||||||
put "blahblah&str.blah&str. replace &str.X";
|
put "blahblah&str.blah&str. replace &str.X";
|
||||||
put "blahbreplacewith&str.spacesahblah";
|
put "blahbreplacewith&str.spacesahblah";
|
||||||
@@ -47,7 +47,7 @@ run;
|
|||||||
%mp_replace(&test2, findvar=str, replacevar=rep)
|
%mp_replace(&test2, findvar=str, replacevar=rep)
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &test2;
|
infile &test2 lrecl=500;
|
||||||
input;
|
input;
|
||||||
if _n_=2 then call symputx('test2resulta',_infile_);
|
if _n_=2 then call symputx('test2resulta',_infile_);
|
||||||
if _n_=3 then call symputx('test2resultb',_infile_);
|
if _n_=3 then call symputx('test2resultb',_infile_);
|
||||||
@@ -69,7 +69,7 @@ run;
|
|||||||
%let str=%str(replace.string.with.dots );
|
%let str=%str(replace.string.with.dots );
|
||||||
%let rep=%str( more.dots);
|
%let rep=%str( more.dots);
|
||||||
data _null_;
|
data _null_;
|
||||||
file &test3;
|
file &test3 lrecl=500;
|
||||||
put 'blahblah';
|
put 'blahblah';
|
||||||
put "blahblah&str.blah&str. replace &str.X";
|
put "blahblah&str.blah&str. replace &str.X";
|
||||||
put "blahbreplacewith&str.spacesahblah";
|
put "blahbreplacewith&str.spacesahblah";
|
||||||
@@ -77,7 +77,7 @@ run;
|
|||||||
%mp_replace(&test3, findvar=str, replacevar=rep)
|
%mp_replace(&test3, findvar=str, replacevar=rep)
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &test3;
|
infile &test3 lrecl=500;
|
||||||
input;
|
input;
|
||||||
if _n_=2 then call symputx('test3resulta',_infile_);
|
if _n_=2 then call symputx('test3resulta',_infile_);
|
||||||
if _n_=3 then call symputx('test3resultb',_infile_);
|
if _n_=3 then call symputx('test3resultb',_infile_);
|
||||||
|
|||||||
@@ -55,37 +55,28 @@ run;
|
|||||||
outlib=testlib1,
|
outlib=testlib1,
|
||||||
outref=test1
|
outref=test1
|
||||||
)
|
)
|
||||||
|
%let test1=FAIL;
|
||||||
%global test1a test1b test1c test1d;
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile test1;
|
set testlib1.somedata1;
|
||||||
input;
|
if x=1 and y=' t"w"o' and z="Z" then call symputx('test1','PASS');
|
||||||
putlog _n_ _infile_;
|
putlog (_all_)(=);
|
||||||
if _infile_=', "somedata1":' then call symputx('test1a','PASS');
|
|
||||||
if _infile_='{"X":1 ,"Y":" t\"w\"o" ,"Z":"Z" }' then
|
|
||||||
call symputx('test1b','PASS');
|
|
||||||
if _infile_='], "somedata2":' then call symputx('test1c','PASS');
|
|
||||||
if _infile_='{"X":1 ,"Y":" t\"w\"o" ,"Z":"Z" }' then
|
|
||||||
call symputx('test1d','PASS');
|
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
%let test2=FAIL;
|
||||||
|
data _null_;
|
||||||
|
set testlib1.somedata2;
|
||||||
|
if x=1 and y=' t"w"o' and z="Z" then call symputx('test2','PASS');
|
||||||
|
putlog (_all_)(=);
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&test1a=PASS),
|
iftrue=(&test1=PASS),
|
||||||
desc=Test 1 table 1 name,
|
desc=somedata1 created correctly,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&test1b=PASS),
|
iftrue=(&test2=PASS),
|
||||||
desc=Test 1 table 1 values,
|
desc=somedata2 created correctly,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&test1c=PASS),
|
|
||||||
desc=Test 1 table 2 name,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(&test1d=PASS),
|
|
||||||
desc=Test 1 table 2 values,
|
|
||||||
outds=work.test_results
|
|
||||||
)
|
|
||||||
@@ -9,11 +9,12 @@
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
%let orig_sasjs_stpsrv_header_loc=&sasjs_stpsrv_header_loc;
|
||||||
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
|
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
%mp_assertscope(SNAPSHOT)
|
||||||
%mfs_httpheader(Content-type,application/csv)
|
%mfs_httpheader(Content-Type,application/csv)
|
||||||
%mp_assertscope(COMPARE)
|
%mp_assertscope(COMPARE,ignorelist=sasjs_stpsrv_header_loc)
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile "&sasjs_stpsrv_header_loc";
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
@@ -27,12 +28,12 @@ run;
|
|||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=("&test1"="Content-type: application/csv"),
|
iftrue=("&test1"="Content-Type: application/csv"),
|
||||||
desc=Checking line was created,
|
desc=Checking line was created,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
%mfs_httpheader(Content-type,application/text)
|
%mfs_httpheader(Content-Type,application/text)
|
||||||
%let test2=0;
|
%let test2=0;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile "&sasjs_stpsrv_header_loc";
|
infile "&sasjs_stpsrv_header_loc";
|
||||||
@@ -46,7 +47,11 @@ run;
|
|||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=("&test2"="Content-type: application/text"),
|
iftrue=("&test2"="Content-Type: application/text"),
|
||||||
desc=Checking line was created,
|
desc=Checking line was created,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/* reset header so the test will pass */
|
||||||
|
%let sasjs_stpsrv_header_loc=&orig_sasjs_stpsrv_header_loc;
|
||||||
50
tests/serveronly/ms_createuser.test.sas
Normal file
50
tests/serveronly/ms_createuser.test.sas
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_createuser.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquename.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
@li ms_createuser.sas
|
||||||
|
@li ms_getusers.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%let user=%substr(%mf_getuniquename(),1,8);
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%ms_createuser(&user,passwrd,outds=test1,mdebug=&sasjs_mdebug)
|
||||||
|
%mp_assertscope(COMPARE
|
||||||
|
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
|
||||||
|
)
|
||||||
|
|
||||||
|
%let id=0;
|
||||||
|
data _null_;
|
||||||
|
set work.test1;
|
||||||
|
call symputx('id',id);
|
||||||
|
run;
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&id>0),
|
||||||
|
desc=Checking that user was created with an ID,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* double check by querying the list of users */
|
||||||
|
%ms_getusers(outds=work.test2)
|
||||||
|
%let checkid=0;
|
||||||
|
data _null_;
|
||||||
|
set work.test2;
|
||||||
|
where username="&user";
|
||||||
|
call symputx('checkid',id);
|
||||||
|
run;
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&checkid=&id),
|
||||||
|
desc=Checking that fetched user exists and has the same ID,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
28
tests/serveronly/ms_createwebservice.test.sas
Normal file
28
tests/serveronly/ms_createwebservice.test.sas
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_createwebservice.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
@li ms_createwebservice.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%let path=&mcTestAppLoc/ms_createwebservice;
|
||||||
|
%let name=myservice;
|
||||||
|
%let fref=%mf_getuniquefileref();
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file &fref lrecl=3000;
|
||||||
|
put '%put hello world;';
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%ms_createwebservice(path=&path,name=&name,code=&fref,mdebug=&sasjs_mdebug)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
23
tests/serveronly/ms_getusers.test.sas
Normal file
23
tests/serveronly/ms_getusers.test.sas
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_getusers.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li ms_getusers.sas
|
||||||
|
@li mp_assertdsobs.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%ms_getusers(outds=work.test1,mdebug=&sasjs_mdebug)
|
||||||
|
%mp_assertscope(COMPARE
|
||||||
|
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN
|
||||||
|
)
|
||||||
|
|
||||||
|
%mp_assertdsobs(work.test1,test=ATLEAST 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3,14 +3,32 @@
|
|||||||
@brief Testing ms_runstp.sas macro
|
@brief Testing ms_runstp.sas macro
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li ms_runstp.sas
|
@li mf_getuniquename.sas
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
@li mp_assertscope.sas
|
@li mp_assertscope.sas
|
||||||
|
@li ms_createfile.sas
|
||||||
|
@li ms_runstp.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
/* first, create an STP to run */
|
||||||
|
filename stpcode temp;
|
||||||
|
data _null_;
|
||||||
|
file stpcode;
|
||||||
|
put '%put hello world;';
|
||||||
|
put '%put _all_;';
|
||||||
|
run;
|
||||||
|
|
||||||
|
options mprint;
|
||||||
|
%let fname=%mf_getuniquename();
|
||||||
|
|
||||||
|
%ms_createfile(/sasjs/tests/&fname..sas
|
||||||
|
,inref=stpcode
|
||||||
|
,mdebug=1
|
||||||
|
)
|
||||||
|
|
||||||
%mp_assertscope(SNAPSHOT)
|
%mp_assertscope(SNAPSHOT)
|
||||||
%ms_runstp(/Public/app/frs/allan/services/common/appinit
|
%ms_runstp(/sasjs/tests/&fname
|
||||||
,debug=131
|
,debug=131
|
||||||
,outref=weboot
|
,outref=weboot
|
||||||
)
|
)
|
||||||
@@ -24,20 +42,16 @@ data _null_;
|
|||||||
putlog _infile_;
|
putlog _infile_;
|
||||||
run;
|
run;
|
||||||
|
|
||||||
data work.httpheaders;
|
%let test1=0;
|
||||||
set webeen.httpheaders;
|
|
||||||
call symputx('test1',content_type);
|
|
||||||
run;
|
|
||||||
|
|
||||||
data work.log;
|
data work.log;
|
||||||
set webeen.log;
|
set webeen.log;
|
||||||
put (_all_)(=);
|
put (_all_)(=);
|
||||||
if _n_>10 then stop;
|
if _n_>10 then call symputx('test1',1);
|
||||||
run;
|
run;
|
||||||
|
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=("&test1"="application/json"),
|
iftrue=("&test1"="1"),
|
||||||
desc=Checking line was created,
|
desc=Checking log was returned,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
87
tests/serveronly/ms_testservice.test.sas
Normal file
87
tests/serveronly/ms_testservice.test.sas
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_testservice.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li ms_createwebservice.sas
|
||||||
|
@li ms_testservice.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
filename ft15f001 temp;
|
||||||
|
parmcards4;
|
||||||
|
%put Initialising sendObj: ;
|
||||||
|
%put _all_;
|
||||||
|
%webout(FETCH)
|
||||||
|
%webout(OPEN)
|
||||||
|
%macro x();
|
||||||
|
%if (%symexist(sasjs_tables) and %length(&sasjs_tables)>0)
|
||||||
|
%then %do i=1 %to %sysfunc(countw(&sasjs_tables));
|
||||||
|
%let table=%scan(&sasjs_tables,&i);
|
||||||
|
%webout(OBJ,&table,missing=STRING)
|
||||||
|
%end;
|
||||||
|
%else %do i=1 %to &_webin_file_count;
|
||||||
|
%webout(OBJ,&&_webin_name&i,missing=STRING)
|
||||||
|
%end;
|
||||||
|
%mend x; %x()
|
||||||
|
%webout(CLOSE)
|
||||||
|
;;;;
|
||||||
|
%put creating web service: &mcTestAppLoc/services;
|
||||||
|
%ms_createwebservice(
|
||||||
|
path=&mcTestAppLoc/services,
|
||||||
|
name=sendObj,
|
||||||
|
mdebug=&sasjs_mdebug
|
||||||
|
)
|
||||||
|
%put created web service: &mcTestAppLoc/services;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&syscc=0),
|
||||||
|
desc=No errors after service creation,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test 1 - send a dataset
|
||||||
|
*/
|
||||||
|
data work.somedata1 work.somedata2;
|
||||||
|
x=1;
|
||||||
|
y=' t"w"o';
|
||||||
|
z=.z;
|
||||||
|
label x='x factor';
|
||||||
|
output;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%ms_testservice(&mcTestAppLoc/services/sendObj,
|
||||||
|
inputdatasets=work.somedata1 work.somedata2,
|
||||||
|
debug=log,
|
||||||
|
mdebug=1,
|
||||||
|
outlib=testlib1,
|
||||||
|
outref=test1
|
||||||
|
)
|
||||||
|
|
||||||
|
%let test1=FAIL;
|
||||||
|
data _null_;
|
||||||
|
set testlib1.somedata1;
|
||||||
|
if x=1 and y=' t"w"o' and z="Z" then call symputx('test1','PASS');
|
||||||
|
putlog (_all_)(=);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%let test2=FAIL;
|
||||||
|
data _null_;
|
||||||
|
set testlib1.somedata2;
|
||||||
|
if x=1 and y=' t"w"o' and z="Z" then call symputx('test2','PASS');
|
||||||
|
putlog (_all_)(=);
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&test1=PASS),
|
||||||
|
desc=somedata1 created correctly,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&test2=PASS),
|
||||||
|
desc=somedata2 created correctly,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
@@ -3,27 +3,34 @@
|
|||||||
@brief init file for tests
|
@brief init file for tests
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_uid.sas
|
||||||
@li mp_init.sas
|
@li mp_init.sas
|
||||||
@li mv_webout.sas
|
@li ms_webout.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
/* location in metadata or SAS Drive for temporary files */
|
/* location in metadata or SAS Drive for temporary files */
|
||||||
%let mcTestAppLoc=/Public/temp/macrocore;
|
%let mcTestAppLoc=/tmp/tests/sasjs/core/%mf_uid();
|
||||||
|
|
||||||
/* set defaults */
|
/* set defaults */
|
||||||
%mp_init()
|
%mp_init()
|
||||||
|
|
||||||
%global _debug;
|
options lrecl=80;
|
||||||
|
|
||||||
|
%global _debug sasjs_mdebug;
|
||||||
|
|
||||||
|
%let sasjs_mdebug=0;
|
||||||
|
|
||||||
%macro loglevel();
|
%macro loglevel();
|
||||||
%if "&_debug"="2477" or "&_debug"="fields,log,trace" %then %do;
|
%if "&_debug"="2477" or "&_debug"="fields,log,trace" or "&_debug"="131"
|
||||||
|
%then %do;
|
||||||
%put debug mode activated;
|
%put debug mode activated;
|
||||||
options mprint mprintnest;
|
options mprint mprintnest;
|
||||||
|
%let sasjs_mdebug=1;
|
||||||
%end;
|
%end;
|
||||||
%mend loglevel;
|
%mend loglevel;
|
||||||
|
|
||||||
%loglevel()
|
%loglevel()
|
||||||
|
|
||||||
%put Initialised &_program;
|
%put Initialised &_program;
|
||||||
%put _all_;
|
%put _all_;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&syscc=0),
|
iftrue=(&syscc=0),
|
||||||
desc=Checking final error condition,
|
desc=Checking final err condition,
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '%if &action=OPEN %then %do; ';
|
put '%if &action=OPEN %then %do; ';
|
||||||
put ' options nobomfile; ';
|
put ' options nobomfile; ';
|
||||||
put ' data _null_;file &jref encoding=''utf-8'' ; ';
|
put ' data _null_;file &jref encoding=''utf-8'' lrecl=200; ';
|
||||||
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
put ' put ''{"PROCESSED_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''"''; ';
|
||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
@@ -458,6 +458,25 @@ data _null_;
|
|||||||
put ' run; ';
|
put ' run; ';
|
||||||
put '%end; ';
|
put '%end; ';
|
||||||
put '%mend mp_jsonout; ';
|
put '%mend mp_jsonout; ';
|
||||||
|
put ' ';
|
||||||
|
put '%macro mf_getuser(type=META ';
|
||||||
|
put ')/*/STORE SOURCE*/; ';
|
||||||
|
put ' %local user metavar; ';
|
||||||
|
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
||||||
|
put ' %else %let metavar=_metaperson; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
||||||
|
put ' %else %if %symexist(&metavar) %then %do; ';
|
||||||
|
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
||||||
|
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
||||||
|
put ' /* but be sure to quote in case of usernames with commas */ ';
|
||||||
|
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
||||||
|
put ' %end; ';
|
||||||
|
put ' %else %let user=&sysuserid; ';
|
||||||
|
put ' ';
|
||||||
|
put ' %quote(&user) ';
|
||||||
|
put ' ';
|
||||||
|
put '%mend mf_getuser; ';
|
||||||
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL ';
|
put '%macro mv_webout(action,ds,fref=_mvwtemp,dslabel=,fmt=Y,stream=Y,missing=NULL ';
|
||||||
put ' ,showmeta=NO ';
|
put ' ,showmeta=NO ';
|
||||||
put '); ';
|
put '); ';
|
||||||
@@ -632,25 +651,6 @@ data _null_;
|
|||||||
put '%end; ';
|
put '%end; ';
|
||||||
put ' ';
|
put ' ';
|
||||||
put '%mend mv_webout; ';
|
put '%mend mv_webout; ';
|
||||||
put ' ';
|
|
||||||
put '%macro mf_getuser(type=META ';
|
|
||||||
put ')/*/STORE SOURCE*/; ';
|
|
||||||
put ' %local user metavar; ';
|
|
||||||
put ' %if &type=OS %then %let metavar=_secureusername; ';
|
|
||||||
put ' %else %let metavar=_metaperson; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER; ';
|
|
||||||
put ' %else %if %symexist(&metavar) %then %do; ';
|
|
||||||
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
|
|
||||||
put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
|
|
||||||
put ' /* but be sure to quote in case of usernames with commas */ ';
|
|
||||||
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
|
|
||||||
put ' %end; ';
|
|
||||||
put ' %else %let user=&sysuserid; ';
|
|
||||||
put ' ';
|
|
||||||
put ' %quote(&user) ';
|
|
||||||
put ' ';
|
|
||||||
put '%mend mf_getuser; ';
|
|
||||||
/* WEBOUT END */
|
/* WEBOUT END */
|
||||||
put '/* if calling viya service with _job param, _program will conflict */';
|
put '/* if calling viya service with _job param, _program will conflict */';
|
||||||
put '/* so it is provided by SASjs instead as __program */';
|
put '/* so it is provided by SASjs instead as __program */';
|
||||||
|
|||||||
Reference in New Issue
Block a user