diff --git a/all.sas b/all.sas index 8a7bc9e..1dbe3d8 100644 --- a/all.sas +++ b/all.sas @@ -18,19 +18,18 @@ options noquotelenmax; /** @file - @brief to be deprecated - @details We will deprecate this macro in 2022 + @brief Abort, ungracefully + @details Will abort with a straightforward %abort if the condition is true. - As you can see, it's not a macro function. - - Use mp_abort.sas instead. +

Related Macros

+ @li mp_abort.sas @version 9.2 @author Allan Bowe @cond **/ -%macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1) +%macro mf_abort(mac=mf_abort.sas, type=deprecated, msg=, iftrue=%str(1=1) )/*/STORE SOURCE*/; %if not(%eval(%unquote(&iftrue))) %then %return; @@ -39,117 +38,9 @@ options noquotelenmax; %if %length(&mac)>0 %then %put NOTE- called by &mac; %put NOTE - &msg; - /* Stored Process Server web app context */ - %if %symexist(_metaperson) or "&SYSPROCESSNAME"="Compute Server" %then %do; - options obs=max replace nosyntaxcheck mprint; - /* extract log err / warn, if exist */ - %local logloc logline; - %global logmsg; /* capture global messages */ - %if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG; - %else %let logloc=%qsysfunc(getoption(LOG)); - proc printto log=log;run; - %if %length(&logloc)>0 %then %do; - %let logline=0; - data _null_; - infile &logloc lrecl=5000; - input; putlog _infile_; - i=1; - retain logonce 0; - if ( - _infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR" - ) and logonce=0 - then do; - call symputx('logline',_n_); - logonce+1; - end; - run; - /* capture log including lines BEFORE the err */ - %if &logline>0 %then %do; - data _null_; - infile &logloc lrecl=5000; - input; - i=1; - stoploop=0; - if _n_ ge &logline-5 and stoploop=0 then do until (i>12); - call symputx('logmsg',catx('\n',symget('logmsg'),_infile_)); - input; - i+1; - stoploop=1; - end; - if stoploop=1 then stop; - run; - %end; - %end; + %abort; - /* send response in SASjs JSON format */ - data _null_; - file _webout mod lrecl=32000; - length msg $32767; - sasdatetime=datetime(); - msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg')); - /* escape the quotes */ - msg=tranwrd(msg,'"','\"'); - /* ditch the CRLFs as chrome complains */ - msg=compress(msg,,'kw'); - /* quote without quoting the quotes (which are escaped instead) */ - msg=cats('"',msg,'"'); - if symexist('_debug') then debug=symget('_debug'); - if debug ge 131 then put '>>weboutBEGIN<<'; - put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"'; - put ',"sasjsAbort" : [{'; - put ' "MSG":' msg ; - put ' ,"MAC": "' "&mac" '"}]'; - put ",""SYSUSERID"" : ""&sysuserid"" "; - if symexist('_metauser') then do; - _METAUSER=quote(trim(symget('_METAUSER'))); - put ",""_METAUSER"": " _METAUSER; - _METAPERSON=quote(trim(symget('_METAPERSON'))); - put ',"_METAPERSON": ' _METAPERSON; - end; - _PROGRAM=quote(trim(resolve(symget('_PROGRAM')))); - put ',"_PROGRAM" : ' _PROGRAM ; - put ",""SYSCC"" : ""&syscc"" "; - put ",""SYSERRORTEXT"" : ""&syserrortext"" "; - put ",""SYSJOBID"" : ""&sysjobid"" "; - put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; - put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" '; - put "}" @; - %if &_debug ge 131 %then %do; - put '>>weboutEND<<'; - %end; - run; - %let syscc=0; - %if %symexist(SYS_JES_JOB_URI) %then %do; - /* refer web service output to file service in one hit */ - filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" - name="_webout.json"; - %let rc=%sysfunc(fcopy(_web,_webout)); - %end; - %else %do; - data _null_; - if symexist('sysprocessmode') - then if symget("sysprocessmode")="SAS Stored Process Server" - then rc=stpsrvset('program error', 0); - run; - %end; - /** - * endsas is reliable but kills some deployments. - * Abort variants are ungraceful (non zero return code) - * This approach lets SAS run silently until the end :-) - */ - %put _all_; - filename skip temp; - data _null_; - file skip; - put '%macro skip(); %macro skippy();'; - run; - %inc skip; - %end; - %else %do; - %put _all_; - %abort cancel; - %end; -%mend; +%mend mf_abort; /** @endcond *//** @file mf_existds.sas @@ -5149,7 +5040,8 @@ create table &outds (rename=( %let fmtds=%scan(&syslast,2,.); /* prepare formats and varnames */ data _null_; - set &fmtds end=last; + if _n_=1 then call symputx('nobs',nobs,'l'); + set &fmtds end=last nobs=nobs; name=upcase(name); /* fix formats */ if type=2 or type=6 then do; @@ -5175,7 +5067,6 @@ create table &outds (rename=( call symputx(cats('len',_n_),newlen,'l'); call symputx(cats('fmt',_n_),fmt,'l'); call symputx(cats('type',_n_),type,'l'); - if last then call symputx('nobs',_n_,'l'); run; data &fmtds; /* rename on entry */ @@ -9013,7 +8904,8 @@ data _null_; put ' %let fmtds=%scan(&syslast,2,.); '; put ' /* prepare formats and varnames */ '; put ' data _null_; '; - put ' set &fmtds end=last; '; + put ' if _n_=1 then call symputx(''nobs'',nobs,''l''); '; + put ' set &fmtds end=last nobs=nobs; '; put ' name=upcase(name); '; put ' /* fix formats */ '; put ' if type=2 or type=6 then do; '; @@ -9039,7 +8931,6 @@ data _null_; put ' call symputx(cats(''len'',_n_),newlen,''l''); '; put ' call symputx(cats(''fmt'',_n_),fmt,''l''); '; put ' call symputx(cats(''type'',_n_),type,''l''); '; - put ' if last then call symputx(''nobs'',_n_,''l''); '; put ' run; '; put ' data &fmtds; '; put ' /* rename on entry */ '; @@ -12890,6 +12781,193 @@ run; %inc &fref1; %mend;/** + @file + @brief Checks whether a file exists in SAS Drive + @details Returns 1 if the file exists, and 0 if it doesn't. Works by + attempting to assign a fileref with the filesrvc engine. If not found, the + syscc is automatically set to a non zero value - so in this case it is reset. + To avoid hiding issues, there is therefore a test at the start to ensure the + syscc is zero. + + Usage: + + %put %mfv_existfile(/does/exist.txt); + %put %mfv_existfile(/does/not/exist.txt); + + @param filepath The full path to the file on SAS drive (eg /Public/myfile.txt) + +

SAS Macros

+ @li mf_abort.sas + @li mf_getuniquefileref.sas + + @version 3.5 + @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/) +**/ + +%macro mfv_existfile(filepath +)/*/STORE SOURCE*/; + + %mf_abort( + iftrue=(&syscc ne 0), + msg=Cannot enter mfv_existfile.sas with syscc=&syscc + ) + + %local fref rc path name; + %let fref=%mf_getuniquefileref(); + %let name=%scan(&filepath,-1,/); + %let path=%substr(&filepath,1,%length(&filepath)-%length(&name)-1); + + %if %sysfunc(filename(fref,,filesrvc,folderPath="&path" filename="&name"))=0 + %then %do; + %sysfunc(fexist(&fref)) + %let rc=%sysfunc(filename(fref)); + %end; + %else %do; + 0 + %let syscc=0; + %end; + +%mend mfv_existfile;/** + @file + @brief Checks whether a folder exists in SAS Drive + @details Returns 1 if the folder exists, and 0 if it doesn't. Works by + attempting to assign a fileref with the filesrvc engine. If not found, the + syscc is automatically set to a non zero value - so in this case it is reset. + To avoid hiding issues, there is therefore a test at the start to ensure the + syscc is zero. + + Usage: + + %put %mfv_existfolder(/does/exist); + %put %mfv_existfolder(/does/not/exist); + + @param path The path to the folder on SAS drive + +

SAS Macros

+ @li mf_abort.sas + @li mf_getuniquefileref.sas + + @version 3.5 + @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/) +**/ + +%macro mfv_existfolder(path +)/*/STORE SOURCE*/; + + %mf_abort( + iftrue=(&syscc ne 0), + msg=Cannot enter mfv_existfolder.sas with syscc=&syscc + ) + + %local fref rc; + %let fref=%mf_getuniquefileref(); + + %if %sysfunc(filename(fref,,filesrvc,folderPath="&path"))=0 %then %do; + 1 + %let rc=%sysfunc(filename(fref)); + %end; + %else %do; + 0 + %let syscc=0; + %end; + +%mend mfv_existfolder;/** + @file + @brief Creates a file in SAS Drive + @details Creates a file in SAS Drive and adds the appropriate content type. + If the parent folder does not exist, it is created. + + Usage: + + filename myfile temp; + data _null_; + file myfile; + put 'something'; + run; + %mv_createfile(path=/Public/temp,name=newfile.txt,inref=myfile) + + + @param [in] path= The parent folder in which to create the file + @param [in] name= The name of the file to be created + @param [in] inref= The fileref pointing to the file to be uploaded + @param [in] access_token_var= The global macro variable to contain the access + token, if using authorization_code grant type. + @param [in] grant_type= (sas_services) Valid values are: + @li password + @li authorization_code + @li sas_services + + @param [in] mdebug= (0) Set to 1 to enable DEBUG messages + + @version VIYA V.03.05 + @author Allan Bowe, source: https://github.com/sasjs/core + +

SAS Macros

+ @li mf_getuniquefileref.sas + @li mf_isblank.sas + @li mp_abort.sas + @li mp_binarycopy.sas + @li mv_createfolder.sas + +**/ + +%macro mv_createfile(path= + ,name= + ,inref= + ,access_token_var=ACCESS_TOKEN + ,grant_type=sas_services + ,mdebug=0 + ); +%local dbg; +%if &mdebug=1 %then %do; + %put &sysmacroname entry vars:; + %put _local_; +%end; +%else %let dbg=*; + +%local oauth_bearer; +%if &grant_type=detect %then %do; + %if %symexist(&access_token_var) %then %let grant_type=authorization_code; + %else %let grant_type=sas_services; +%end; +%if &grant_type=sas_services %then %do; + %let oauth_bearer=oauth_bearer=sas_services; + %let &access_token_var=; +%end; + +%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password + and &grant_type ne sas_services + ) + ,mac=&sysmacroname + ,msg=%str(Invalid value for grant_type: &grant_type) +) + +%mp_abort(iftrue=(%mf_isblank(&path)=1 or %length(&path)=1) + ,mac=&sysmacroname + ,msg=%str(path value must be provided) +) +%mp_abort(iftrue=(%mf_isblank(&name)=1 or %length(&name)=1) + ,mac=&sysmacroname + ,msg=%str(name value with length >1 must be provided) +) + +/* create folder if it does not already exist */ +%mv_createfolder(path=&path + ,access_token_var=&access_token_var + ,grant_type=&grant_type + ,mdebug=&mdebug +) + +/* create file with relevant options */ +%local fref; +%let fref=%mf_getuniquefileref(); +filename &fref filesrvc folderPath="&path" filename="&name"; + +%mp_binarycopy(inref=&inref, outref=&fref) + +filename &fref clear; + +%mend mv_createfile;/** @file mv_createfolder.sas @brief Creates a viya folder if that folder does not already exist @details Creates a viya folder by checking if each parent folder exists, and @@ -12918,6 +12996,8 @@ run; @li mf_getuniquelibref.sas @li mf_isblank.sas @li mf_getplatform.sas + @li mfv_existfolder.sas + **/ @@ -12933,6 +13013,11 @@ run; %end; %else %let dbg=*; +%if %mfv_existfolder(&path)=1 %then %do; + %put &sysmacroname: &path already exists; + %return; +%end; + %local oauth_bearer; %if &grant_type=detect %then %do; %if %symexist(&access_token_var) %then %let grant_type=authorization_code; @@ -13656,7 +13741,8 @@ data _null_; put ' %let fmtds=%scan(&syslast,2,.); '; put ' /* prepare formats and varnames */ '; put ' data _null_; '; - put ' set &fmtds end=last; '; + put ' if _n_=1 then call symputx(''nobs'',nobs,''l''); '; + put ' set &fmtds end=last nobs=nobs; '; put ' name=upcase(name); '; put ' /* fix formats */ '; put ' if type=2 or type=6 then do; '; @@ -13682,7 +13768,6 @@ data _null_; put ' call symputx(cats(''len'',_n_),newlen,''l''); '; put ' call symputx(cats(''fmt'',_n_),fmt,''l''); '; put ' call symputx(cats(''type'',_n_),type,''l''); '; - put ' if last then call symputx(''nobs'',_n_,''l''); '; put ' run; '; put ' data &fmtds; '; put ' /* rename on entry */ '; diff --git a/meta/mm_createwebservice.sas b/meta/mm_createwebservice.sas index d4865fe..17f5f0e 100644 --- a/meta/mm_createwebservice.sas +++ b/meta/mm_createwebservice.sas @@ -134,7 +134,8 @@ data _null_; put ' %let fmtds=%scan(&syslast,2,.); '; put ' /* prepare formats and varnames */ '; put ' data _null_; '; - put ' set &fmtds end=last; '; + put ' if _n_=1 then call symputx(''nobs'',nobs,''l''); '; + put ' set &fmtds end=last nobs=nobs; '; put ' name=upcase(name); '; put ' /* fix formats */ '; put ' if type=2 or type=6 then do; '; @@ -160,7 +161,6 @@ data _null_; put ' call symputx(cats(''len'',_n_),newlen,''l''); '; put ' call symputx(cats(''fmt'',_n_),fmt,''l''); '; put ' call symputx(cats(''type'',_n_),type,''l''); '; - put ' if last then call symputx(''nobs'',_n_,''l''); '; put ' run; '; put ' data &fmtds; '; put ' /* rename on entry */ '; diff --git a/viya/mv_createwebservice.sas b/viya/mv_createwebservice.sas index 5e5bd40..f2a4616 100644 --- a/viya/mv_createwebservice.sas +++ b/viya/mv_createwebservice.sas @@ -282,7 +282,8 @@ data _null_; put ' %let fmtds=%scan(&syslast,2,.); '; put ' /* prepare formats and varnames */ '; put ' data _null_; '; - put ' set &fmtds end=last; '; + put ' if _n_=1 then call symputx(''nobs'',nobs,''l''); '; + put ' set &fmtds end=last nobs=nobs; '; put ' name=upcase(name); '; put ' /* fix formats */ '; put ' if type=2 or type=6 then do; '; @@ -308,7 +309,6 @@ data _null_; put ' call symputx(cats(''len'',_n_),newlen,''l''); '; put ' call symputx(cats(''fmt'',_n_),fmt,''l''); '; put ' call symputx(cats(''type'',_n_),type,''l''); '; - put ' if last then call symputx(''nobs'',_n_,''l''); '; put ' run; '; put ' data &fmtds; '; put ' /* rename on entry */ ';