From 512f05c0b246da50524dbed75d7bfc4cd432769b Mon Sep 17 00:00:00 2001 From: munja Date: Thu, 19 May 2022 22:02:19 +0100 Subject: [PATCH 1/2] feat: creating new mx_ suite of macros! also adding new mx_getcode macro --- README.md | 92 +++--- base/mf_getplatform.sas | 10 +- base/mf_isint.sas | 2 +- base/mp_createwebservice.sas | 76 +---- base/mp_testservice.sas | 294 +---------------- build.py | 2 +- main.dox | 13 +- .../mcf_getfmttype.test.sas | 0 .../{crossplatform => base}/mcf_init.test.sas | 0 .../mcf_length.test.sas | 0 .../mcf_string2file.test.sas | 0 .../{crossplatform => base}/mf_dedup.test.sas | 0 .../mf_deletefile.test.sas | 0 .../mf_existds.test.sas | 0 .../mf_existfileref.test.sas | 0 .../mf_existfunction.test.sas | 0 .../mf_existvar.test.sas | 0 .../mf_fmtdttm.test.sas | 0 .../mf_getapploc.test.sas | 0 .../mf_getfilesize.test.sas | 0 .../mf_getfmtlist.test.sas | 0 .../mf_getfmtname.test.sas | 0 .../mf_getuniquefileref.test.sas | 0 .../mf_getuniquelibref.test.sas | 0 .../mf_getvarcount.test.sas | 0 .../mf_getvarlist.test.sas | 0 .../{crossplatform => base}/mf_isint.test.sas | 0 .../mf_islibds.test.sas | 0 .../mf_verifymacvars.test.sas | 0 .../mf_wordsinstr1andstr2.test.sas | 0 .../mf_wordsinstr1butnotstr2.test.sas | 0 .../mf_writefile.test.sas | 0 .../mp_abort.test.nofix.sas | 0 .../mp_appendfile.test.sas | 0 .../mp_applyformats.test.sas | 0 .../mp_assert.test.sas | 0 .../mp_assertcolvals.test.sas | 0 .../mp_assertdsobs.test.sas | 0 .../mp_assertscope.test.sas | 0 .../mp_base64copy.test.sas | 0 .../mp_binarycopy.test.sas | 0 .../{crossplatform => base}/mp_chop.test.sas | 0 .../mp_cntlout.test.sas | 0 .../mp_copyfolder.test.sas | 0 .../mp_coretable.test.sas | 0 .../mp_createwebservice.test.sas | 0 .../mp_deletefolder.test.sas | 0 .../mp_dirlist.test.sas | 0 .../mp_ds2cards.test.sas | 0 .../mp_ds2csv.test.sas | 0 .../mp_ds2fmtds.test.sas | 0 .../mp_ds2inserts.test.sas | 0 .../{crossplatform => base}/mp_ds2md.test.sas | 0 .../mp_ds2squeeze.test.sas | 0 .../mp_filtercheck.test.sas | 0 .../mp_filtergenerate.test.sas | 0 .../mp_filterstore.test.1.sas | 0 .../mp_filterstore.test.2.sas | 0 .../mp_filtervalidate.test.sas | 0 .../mp_getcols.test.sas | 0 .../mp_getconstraints.test.sas | 0 .../mp_getddl.test.sas | 0 .../mp_getformats.test.sas | 0 .../mp_getmaxvarlengths.test.sas | 0 .../{crossplatform => base}/mp_getpk.test.sas | 0 .../mp_gsubfile.test.sas | 0 .../mp_hashdataset.test.sas | 0 .../{crossplatform => base}/mp_init.test.sas | 0 .../mp_jsonout.test.1.sas | 0 .../mp_jsonout.test.2.sas | 0 .../mp_jsonout.test.3.sas | 0 .../mp_lib2inserts.test.sas | 0 .../mp_loadformat.test.sas | 0 .../mp_lockanytable.test.sas | 0 .../mp_lockfilecheck.test.sas | 0 .../mp_makedata.test.sas | 0 tests/{crossplatform => base}/mp_md5.test.sas | 0 .../mp_replace.test.sas | 0 .../mp_reseterror.test.sas | 0 .../mp_resetoption.test.sas | 0 .../mp_retainedkey.test.sas | 0 .../mp_searchcols.test.sas | 0 .../mp_searchdata.test.sas | 0 .../mp_sortinplace.test.sas | 0 .../mp_stackdiffs.test.sas | 0 .../mp_storediffs.test.sas | 0 .../mp_streamfile.test.sas | 0 .../mp_validatecol.test.sas | 0 .../{crossplatform => base}/mp_webin.test.sas | 0 tests/{crossplatform => base}/mp_zip.test.sas | 0 tests/xplatform/mx_getcode.test.sas | 38 +++ .../mx_testservice.test.sas} | 8 +- xplatform/mx_createwebservice.sas | 96 ++++++ xplatform/mx_getcode.sas | 57 ++++ xplatform/mx_testservice.sas | 299 ++++++++++++++++++ 95 files changed, 591 insertions(+), 396 deletions(-) rename tests/{crossplatform => base}/mcf_getfmttype.test.sas (100%) rename tests/{crossplatform => base}/mcf_init.test.sas (100%) rename tests/{crossplatform => base}/mcf_length.test.sas (100%) rename tests/{crossplatform => base}/mcf_string2file.test.sas (100%) rename tests/{crossplatform => base}/mf_dedup.test.sas (100%) rename tests/{crossplatform => base}/mf_deletefile.test.sas (100%) rename tests/{crossplatform => base}/mf_existds.test.sas (100%) rename tests/{crossplatform => base}/mf_existfileref.test.sas (100%) rename tests/{crossplatform => base}/mf_existfunction.test.sas (100%) rename tests/{crossplatform => base}/mf_existvar.test.sas (100%) rename tests/{crossplatform => base}/mf_fmtdttm.test.sas (100%) rename tests/{crossplatform => base}/mf_getapploc.test.sas (100%) rename tests/{crossplatform => base}/mf_getfilesize.test.sas (100%) rename tests/{crossplatform => base}/mf_getfmtlist.test.sas (100%) rename tests/{crossplatform => base}/mf_getfmtname.test.sas (100%) rename tests/{crossplatform => base}/mf_getuniquefileref.test.sas (100%) rename tests/{crossplatform => base}/mf_getuniquelibref.test.sas (100%) rename tests/{crossplatform => base}/mf_getvarcount.test.sas (100%) rename tests/{crossplatform => base}/mf_getvarlist.test.sas (100%) rename tests/{crossplatform => base}/mf_isint.test.sas (100%) rename tests/{crossplatform => base}/mf_islibds.test.sas (100%) rename tests/{crossplatform => base}/mf_verifymacvars.test.sas (100%) rename tests/{crossplatform => base}/mf_wordsinstr1andstr2.test.sas (100%) rename tests/{crossplatform => base}/mf_wordsinstr1butnotstr2.test.sas (100%) rename tests/{crossplatform => base}/mf_writefile.test.sas (100%) rename tests/{crossplatform => base}/mp_abort.test.nofix.sas (100%) rename tests/{crossplatform => base}/mp_appendfile.test.sas (100%) rename tests/{crossplatform => base}/mp_applyformats.test.sas (100%) rename tests/{crossplatform => base}/mp_assert.test.sas (100%) rename tests/{crossplatform => base}/mp_assertcolvals.test.sas (100%) rename tests/{crossplatform => base}/mp_assertdsobs.test.sas (100%) rename tests/{crossplatform => base}/mp_assertscope.test.sas (100%) rename tests/{crossplatform => base}/mp_base64copy.test.sas (100%) rename tests/{crossplatform => base}/mp_binarycopy.test.sas (100%) rename tests/{crossplatform => base}/mp_chop.test.sas (100%) rename tests/{crossplatform => base}/mp_cntlout.test.sas (100%) rename tests/{crossplatform => base}/mp_copyfolder.test.sas (100%) rename tests/{crossplatform => base}/mp_coretable.test.sas (100%) rename tests/{crossplatform => base}/mp_createwebservice.test.sas (100%) rename tests/{crossplatform => base}/mp_deletefolder.test.sas (100%) rename tests/{crossplatform => base}/mp_dirlist.test.sas (100%) rename tests/{crossplatform => base}/mp_ds2cards.test.sas (100%) rename tests/{crossplatform => base}/mp_ds2csv.test.sas (100%) rename tests/{crossplatform => base}/mp_ds2fmtds.test.sas (100%) rename tests/{crossplatform => base}/mp_ds2inserts.test.sas (100%) rename tests/{crossplatform => base}/mp_ds2md.test.sas (100%) rename tests/{crossplatform => base}/mp_ds2squeeze.test.sas (100%) rename tests/{crossplatform => base}/mp_filtercheck.test.sas (100%) rename tests/{crossplatform => base}/mp_filtergenerate.test.sas (100%) rename tests/{crossplatform => base}/mp_filterstore.test.1.sas (100%) rename tests/{crossplatform => base}/mp_filterstore.test.2.sas (100%) rename tests/{crossplatform => base}/mp_filtervalidate.test.sas (100%) rename tests/{crossplatform => base}/mp_getcols.test.sas (100%) rename tests/{crossplatform => base}/mp_getconstraints.test.sas (100%) rename tests/{crossplatform => base}/mp_getddl.test.sas (100%) rename tests/{crossplatform => base}/mp_getformats.test.sas (100%) rename tests/{crossplatform => base}/mp_getmaxvarlengths.test.sas (100%) rename tests/{crossplatform => base}/mp_getpk.test.sas (100%) rename tests/{crossplatform => base}/mp_gsubfile.test.sas (100%) rename tests/{crossplatform => base}/mp_hashdataset.test.sas (100%) rename tests/{crossplatform => base}/mp_init.test.sas (100%) rename tests/{crossplatform => base}/mp_jsonout.test.1.sas (100%) rename tests/{crossplatform => base}/mp_jsonout.test.2.sas (100%) rename tests/{crossplatform => base}/mp_jsonout.test.3.sas (100%) rename tests/{crossplatform => base}/mp_lib2inserts.test.sas (100%) rename tests/{crossplatform => base}/mp_loadformat.test.sas (100%) rename tests/{crossplatform => base}/mp_lockanytable.test.sas (100%) rename tests/{crossplatform => base}/mp_lockfilecheck.test.sas (100%) rename tests/{crossplatform => base}/mp_makedata.test.sas (100%) rename tests/{crossplatform => base}/mp_md5.test.sas (100%) rename tests/{crossplatform => base}/mp_replace.test.sas (100%) rename tests/{crossplatform => base}/mp_reseterror.test.sas (100%) rename tests/{crossplatform => base}/mp_resetoption.test.sas (100%) rename tests/{crossplatform => base}/mp_retainedkey.test.sas (100%) rename tests/{crossplatform => base}/mp_searchcols.test.sas (100%) rename tests/{crossplatform => base}/mp_searchdata.test.sas (100%) rename tests/{crossplatform => base}/mp_sortinplace.test.sas (100%) rename tests/{crossplatform => base}/mp_stackdiffs.test.sas (100%) rename tests/{crossplatform => base}/mp_storediffs.test.sas (100%) rename tests/{crossplatform => base}/mp_streamfile.test.sas (100%) rename tests/{crossplatform => base}/mp_validatecol.test.sas (100%) rename tests/{crossplatform => base}/mp_webin.test.sas (100%) rename tests/{crossplatform => base}/mp_zip.test.sas (100%) create mode 100644 tests/xplatform/mx_getcode.test.sas rename tests/{crossplatform/mp_testservice.test.sas => xplatform/mx_testservice.test.sas} (89%) create mode 100644 xplatform/mx_createwebservice.sas create mode 100644 xplatform/mx_getcode.sas create mode 100644 xplatform/mx_testservice.sas diff --git a/README.md b/README.md index 3fc74f0..4c5bf7f 100644 --- a/README.md +++ b/README.md @@ -31,14 +31,14 @@ Documentation: https://core.sasjs.io ## Components -### BASE library (All Platforms) +### BASE folder (All Platforms) - OS independent - Works on all SAS Platforms - No X command - Prefixes: _mf_, _mp_ -### DDL library (All Platforms) +### DDL folder (All Platforms) - OS independent - Works on all SAS Platforms @@ -47,45 +47,13 @@ Documentation: https://core.sasjs.io This library will not be used for storing data entries (such as formats or datalines). Where this becomes necessary in the future, a new repo will be created, in order to keep the NPM bundle size down (for the benefit of those looking to embed purely macros in their applications). -### FCMP library (All Platforms) +### FCMP folder (All Platforms) - Function and macro names are identical, except for special cases - Prefixes: _mcf_ The fcmp macros are used to generate fcmp functions, and can be used with or without the `proc fcmp` wrapper. -### META library (SAS9 only) - -Macros used in SAS EBI, which connect to the metadata server. - -- OS independent -- Metadata aware -- No X command -- Prefixes: _mm_ - -### SERVER library (@sasjs/server only) -These macros are used for building applications using [@sasjs/server](https://server.sasjs.io) - an open source REST API for Desktop SAS. - -- OS independent -- @sasjs/server aware -- No X command -- Prefixes: _ms_ - -### VIYA library (Viya only) - -Macros used for interfacing with SAS Viya. - -- OS independent -- No X command -- Prefixes: _mv_, _mvf_ - -### METAX library (SAS9 only) - -- OS specific -- Metadata aware -- X command enabled -- Prefixes: _mmw_,_mmu_,_mmx_ - ### LUA library Wait - this is a macro library - what is LUA doing here? Well, it is a little known fact that you CAN run LUA within a SAS Macro. It has to be written to a text file with a `.lua` extension, from where you can `%include` it. So, without using the `proc lua` wrapper. @@ -106,13 +74,61 @@ run; - Prefixes: _ml_ +### META folder (SAS9 only) + +Macros used in SAS EBI, which connect to the metadata server. + +- OS independent +- Metadata aware +- No X command +- Prefixes: _mm_ + +### METAX folder (SAS9 only) + +- OS specific +- Metadata aware +- X command enabled +- Prefixes: _mmw_,_mmu_,_mmx_ + +### SERVER folder (@sasjs/server only) +These macros are used for building applications using [@sasjs/server](https://server.sasjs.io) - an open source REST API for Desktop SAS. + +- OS independent +- @sasjs/server aware +- No X command +- Prefixes: _ms_ + +### VIYA folder (Viya only) + +Macros used for interfacing with SAS Viya. + +- OS independent +- No X command +- Prefixes: _mv_, _mvf_ + +### XPLATFORM folder (Viya, Meta, and Server) + +Sometimes it is helpful to use a macro that can be used interchangeably regardless of the server type on which is is running (SASVIYA, SAS9, SASJS). + +- OS independent +- No X command +- Prefixes: _mx_ + ## Installation First, download the repo to a location your SAS system can access. Then update your sasautos path to include the components you wish to have available, eg: ```sas -options insert=(sasautos="/your/path/macrocore/base"); -options insert=(sasautos="/your/path/macrocore/meta"); +%let repoloc=/your/path/core; +options insert=(sasautos="&repoloc/base"); +options insert=(sasautos="&repoloc/ddl"); +options insert=(sasautos="&repoloc/fcmp"); +options insert=(sasautos="&repoloc/lua"); +options insert=(sasautos="&repoloc/meta"); +options insert=(sasautos="&repoloc/metax"); +options insert=(sasautos="&repoloc/server"); +options insert=(sasautos="&repoloc/viya"); +options insert=(sasautos="&repoloc/xplatform"); ``` The above can be done directly in your sas program, via an autoexec, or an initialisation program. @@ -142,7 +158,7 @@ filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; - _mp_ for macro procedures (which generate sas code) - _ms_ for macro procedures that will only work with [@sasjs/server](https://github.com/sasjs/server) - _mv_ for macro procedures that will only work in Viya - - _mx_ for macros that are XCMD enabled (working on both windows and unix) + - _mx_ for macros that work on Viya, SAS 9 EBI and SASjs Server - follow verb-noun convention - unix style line endings (lf) - individual lines should be no more than 80 characters long diff --git a/base/mf_getplatform.sas b/base/mf_getplatform.sas index 4d20dbd..8416686 100644 --- a/base/mf_getplatform.sas +++ b/base/mf_getplatform.sas @@ -5,8 +5,12 @@ %put %mf_getplatform(); - returns: - SASMETA (or SASVIYA) + returns one of: + + @li SASMETA + @li SASVIYA + @li SASJS + @li BASESAS @param switch the param for which to return a platform specific variable @@ -68,4 +72,4 @@ %else %if &switch=VIYARESTAPI %then %do; %mf_trimstr(%sysfunc(getoption(servicesbaseurl)),/) %end; -%mend mf_getplatform; \ No newline at end of file +%mend mf_getplatform; diff --git a/base/mf_isint.sas b/base/mf_isint.sas index 71548bb..a6019a1 100644 --- a/base/mf_isint.sas +++ b/base/mf_isint.sas @@ -33,4 +33,4 @@ %if %sysfunc(findc(%str(&val),,kd)) %then %do;0%end; %else %do;1%end; -%mend mf_isint; \ No newline at end of file +%mend mf_isint; diff --git a/base/mp_createwebservice.sas b/base/mp_createwebservice.sas index 80b4459..4be9b08 100644 --- a/base/mp_createwebservice.sas +++ b/base/mp_createwebservice.sas @@ -1,50 +1,13 @@ /** @file mp_createwebservice.sas - @brief Create a web service in SAS 9 or Viya - @details Creates a SASJS ready Stored Process in SAS 9 or Job Execution - Service in SAS Viya + @brief Create a web service in SAS 9, Viya or SASjs Server + @details This is actually a wrapper for mx_createwebservice.sas, remaining + for legacy purposes. For new apps, use mx_createwebservice.sas. -Usage: - - %* compile macros ; - filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; - %inc mc; - - %* write some code; - filename ft15f001 temp; - parmcards4; - %* fetch any data from frontend ; - %webout(FETCH) - data example1 example2; - set sashelp.class; - run; - %* send data back; - %webout(OPEN) - %webout(ARR,example1) * Array format, fast, suitable for large tables ; - %webout(OBJ,example2) * Object format, easier to work with ; - %webout(CLOSE) - ;;;; - %mp_createwebservice(path=/Public/app/common,name=appInit,replace=YES)

SAS Macros

- @li mf_getplatform.sas - @li mm_createwebservice.sas - @li ms_createwebservice.sas - @li mv_createwebservice.sas + @li mx_createwebservice.sas - @param [in,out] path= The full folder path where the service will be created - @param [in,out] name= Service name. Avoid spaces. - @param [in] desc= The description of the service (optional) - @param [in] precode= Space separated list of filerefs, pointing to the code - that needs to be attached to the beginning of the service (optional) - @param [in] code= (ft15f001) Space seperated fileref(s) of the actual code to - be added - @param [in] replace= (YES) Select YES to replace any existing service in that - location - @param [in] mDebug= (0) set to 1 to show debug messages in the log - - @version 9.2 - @author Allan Bowe **/ @@ -57,40 +20,13 @@ Usage: ,mdebug=0 )/*/STORE SOURCE*/; -%if &syscc ge 4 %then %do; - %put syscc=&syscc - &sysmacroname will not execute in this state; - %return; -%end; - -%local platform; %let platform=%mf_getplatform(); -%if &platform=SASVIYA %then %do; - %if "&path"="HOME" %then %let path=/Users/&sysuserid/My Folder; - %mv_createwebservice(path=&path + %mx_createwebservice(path=&path ,name=&name - ,code=&code ,precode=&precode + ,code=&code ,desc=&desc ,replace=&replace - ) -%end; -%else %if &platform=SASJS %then %do; - %if "&path"="HOME" %then %let path=/Users/&_sasjs_username/My Folder; - %ms_createwebservice(path=&path - ,name=&name - ,code=&code - ,precode=&precode ,mdebug=&mdebug ) -%end; -%else %do; - %if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder; - %mm_createwebservice(path=&path - ,name=&name - ,code=&code - ,precode=&precode - ,desc=&desc - ,replace=&replace - ) -%end; %mend mp_createwebservice; diff --git a/base/mp_testservice.sas b/base/mp_testservice.sas index c21e0a2..49c6f64 100644 --- a/base/mp_testservice.sas +++ b/base/mp_testservice.sas @@ -1,53 +1,11 @@ /** @file - @brief Will execute a SASjs web service on SAS 9 or Viya - @details Prepares the input files and retrieves the resulting datasets from - the response JSON. - - - - Note - the _webout fileref should NOT be assigned prior to running this macro. - - @param [in] program The _PROGRAM endpoint to test - @param [in] inputfiles=(0) A list of space seperated fileref:filename pairs as - follows: - inputfiles=inref:filename inref2:filename2 - @param [in] inputdatasets= (0) All datasets in this space seperated list are - converted into SASJS-formatted CSVs (see mp_ds2csv.sas) files and added to - the list of `inputfiles` for ingestion. The dataset will be sent with the - same name (no need for a colon modifier). - @param [in] inputparams=(0) A dataset containing name/value pairs in the - following format: - |name:$32|value:$1000| - |---|---| - |stpmacname|some value| - |mustbevalidname|can be anything, oops, %abort!!| - - @param [in] debug= (log) Provide the _debug value - @param [in] mdebug= (0) Set to 1 to provide macro debugging - @param [in] viyaresult= (WEBOUT_JSON) The Viya result type to return. For - more info, see mv_getjobresult.sas - @param [in] viyacontext= (SAS Job Execution compute context) The Viya compute - context on which to run the service - @param [out] outlib= (0) Output libref to contain the final tables. Set to - 0 if the service output is not in JSON format. - @param [out] outref= (0) Output fileref to create, to contain the full _webout - response. + @brief To be deprecated. Will execute a SASjs web service on SAS 9 or Viya + @details Use the mx_testservice.sas macro instead (documentation can be + found there)

SAS Macros

- @li mf_getplatform.sas - @li mf_getuniquefileref.sas - @li mf_getuniquename.sas - @li mp_abort.sas - @li mp_binarycopy.sas - @li mp_chop.sas - @li mp_ds2csv.sas - @li ms_testservice.sas - @li mv_getjobresult.sas - @li mv_jobflow.sas - -

Related Programs

- @li mp_testservice.test.sas + @li mx_testservice.sas @version 9.4 @author Allan Bowe @@ -65,237 +23,17 @@ viyaresult=WEBOUT_JSON, viyacontext=SAS Job Execution compute context )/*/STORE SOURCE*/; -%local dbg pcnt fref1 fref2 webref webrefpath i webcount var platform; -%if &mdebug=1 %then %do; - %put &sysmacroname entry vars:; - %put _local_; -%end; -%else %let dbg=*; -/* sanitise inputparams */ -%let pcnt=0; -%if &inputparams ne 0 %then %do; - data _null_; - set &inputparams; - if not nvalid(name,'v7') then putlog (_all_)(=); - else if name in ( - 'program','inputfiles','inputparams','debug','outlib','outref' - ) then putlog (_all_)(=); - else do; - x+1; - call symputx(name,quote(cats(value)),'l'); - call symputx(cats('pval',x),name,'l'); - call symputx('pcnt',x,'l'); - end; - run; - %mp_abort(iftrue= (%mf_nobs(&inputparams) ne &pcnt) - ,mac=&sysmacroname - ,msg=%str(Invalid values in &inputparams) - ) -%end; +%mx_testservice(&program, + inputfiles=&inputfiles, + inputdatasets=&inputdatasets, + inputparams=&inputparams, + debug=&debug, + mdebug=&mdebug, + outlib=&outlib, + outref=&outref, + viyaresult=&viyaresult, + viyacontext=&viyacontext +) -/* convert inputdatasets to filerefs */ -%if "&inputdatasets" ne "0" %then %do; - %if %quote(&inputfiles)=0 %then %let inputfiles=; - %do i=1 %to %sysfunc(countw(&inputdatasets,%str( ))); - %let var=%scan(&inputdatasets,&i,%str( )); - %local dsref&i; - %let dsref&i=%mf_getuniquefileref(); - %mp_ds2csv(&var,outref=&&dsref&i,headerformat=SASJS) - %let inputfiles=&inputfiles &&dsref&i:%scan(&var,-1,.); - %end; -%end; - -%let platform=%mf_getplatform(); -%let fref1=%mf_getuniquefileref(); -%let fref2=%mf_getuniquefileref(); -%let webref=%mf_getuniquefileref(); -%let webrefpath=%sysfunc(pathname(work))/%mf_getuniquename(); -/* mp_chop requires a physical path as input */ -filename &webref "&webrefpath"; - -%if &platform=SASMETA %then %do; - - /* parse the input files */ - %if %quote(&inputfiles) ne 0 %then %do; - %let webcount=%sysfunc(countw(&inputfiles)); - %put &=webcount; - %do i=1 %to &webcount; - %let var=%scan(&inputfiles,&i,%str( )); - %local webfref&i webname&i; - %let webref&i=%scan(&var,1,%str(:)); - %let webname&i=%scan(&var,2,%str(:)); - %put webref&i=&&webref&i; - %put webname&i=&&webname&i; - %end; - %end; - %else %let webcount=0; - - proc stp program="&program"; - inputparam _program="&program" - %do i=1 %to &webcount; - %if &webcount=1 %then %do; - _webin_fileref="&&webref&i" - _webin_name="&&webname&i" - %end; - %else %do; - _webin_fileref&i="&&webref&i" - _webin_name&i="&&webname&i" - %end; - %end; - _webin_file_count="&webcount" - _debug="&debug" - %do i=1 %to &pcnt; - /* resolve name only, proc stp fetches value */ - &&pval&i=&&&&&&pval&i - %end; - ; - %do i=1 %to &webcount; - inputfile &&webref&i; - %end; - outputfile _webout=&webref; - run; - - data _null_; - infile &webref; - file &fref1; - input; - length line $10000; - if index(_infile_,'>>weboutBEGIN<<') then do; - line=tranwrd(_infile_,'>>weboutBEGIN<<',''); - put line; - end; - else if index(_infile_,'>>weboutEND<<') then do; - line=tranwrd(_infile_,'>>weboutEND<<',''); - put line; - stop; - end; - else put _infile_; - run; - data _null_; - infile &fref1; - input; - put _infile_; - run; - %if &outlib ne 0 %then %do; - libname &outlib json (&fref1); - %end; - %if &outref ne 0 %then %do; - filename &outref temp; - %mp_binarycopy(inref=&webref,outref=&outref) - %end; - -%end; -%else %if &platform=SASVIYA %then %do; - - /* prepare inputparams */ - %local ds1; - %let ds1=%mf_getuniquename(); - %if "&inputparams" ne "0" %then %do; - proc transpose data=&inputparams out=&ds1; - id name; - var value; - run; - %end; - %else %do; - data &ds1;run; - %end; - - /* parse the input files - convert to sasjs params */ - %local webcount i var sasjs_tables; - %if %quote(&inputfiles) ne 0 %then %do; - %let webcount=%sysfunc(countw(&inputfiles)); - %put &=webcount; - %do i=1 %to &webcount; - %let var=%scan(&inputfiles,&i,%str( )); - %local webfref&i webname&i sasjs&i.data; - %let webref&i=%scan(&var,1,%str(:)); - %let webname&i=%scan(&var,2,%str(:)); - %put webref&i=&&webref&i; - %put webname&i=&&webname&i; - - %let sasjs_tables=&sasjs_tables &&webname&i; - data _null_; - infile &&webref&i lrecl=32767; - input; - if _n_=1 then call symputx("sasjs&i.data",_infile_); - else call symputx( - "sasjs&i.data",cats(symget("sasjs&i.data"),'0D0A'x,_infile_) - ); - putlog "&sysmacroname infile: " _infile_; - run; - data &ds1; - set &ds1; - length sasjs&i.data $32767 sasjs_tables $1000; - sasjs&i.data=symget("sasjs&i.data"); - sasjs_tables=symget("sasjs_tables"); - run; - %end; - %end; - %else %let webcount=0; - - data &ds1; - retain _program "&program"; - retain _contextname "&viyacontext"; - set &ds1; - putlog "&sysmacroname inputparams:"; - putlog (_all_)(=); - run; - - %mv_jobflow(inds=&ds1 - ,maxconcurrency=1 - ,outds=work.results - ,outref=&fref1 - ,mdebug=&mdebug - ) - /* show the log */ - data _null_; - infile &fref1; - input; - putlog _infile_; - run; - /* get the uri to fetch results */ - data _null_; - set work.results; - call symputx('uri',uri); - putlog "&sysmacroname: fetching results for " uri; - run; - /* fetch results from webout.json */ - %mv_getjobresult(uri=&uri, - result=&viyaresult, - outref=&outref, - outlib=&outlib, - mdebug=&mdebug - ) - -%end; -%else %if &platform=SASJS %then %do; - - %ms_testservice(&program - ,inputfiles=&inputfiles - ,inputdatasets=&inputdatasets - ,inputparams=&inputparams - ,debug=&debug - ,mdebug=&mdebug - ,outlib=&outlib - ,outref=&outref - ) - -%end; -%else %do; - %put %str(ERR)OR: Unrecognised platform: &platform; -%end; - -%if &mdebug=0 %then %do; - filename &fref1 clear; - %if &platform ne SASJS %then %do; - filename &fref2 clear; - filename &webref clear; - %end; -%end; -%else %do; - %put &sysmacroname exit vars:; - %put _local_; -%end; - -%mend mp_testservice; \ No newline at end of file +%mend mp_testservice; diff --git a/build.py b/build.py index c4ab568..5767276 100755 --- a/build.py +++ b/build.py @@ -102,7 +102,7 @@ options noquotelenmax; """ f = open('all.sas', "w") # r / r+ / rb / rb+ / w / wb f.write(header) -folders = ['base', 'ddl', 'meta', 'metax', 'server', 'viya', 'lua', 'fcmp'] +folders = ['base', 'ddl', 'meta', 'metax', 'server', 'viya', 'lua', 'fcmp', 'xplatform'] for folder in folders: filenames = [fn for fn in Path( './' + folder).iterdir() if fn.match("*.sas")] diff --git a/main.dox b/main.dox index 33459d7..1d4a2cb 100644 --- a/main.dox +++ b/main.dox @@ -103,4 +103,15 @@ * No X command * Prefixes: _mddl_ - */ \ No newline at end of file + */ + +/*! \dir xplatform + * \brief Cross Platform, works on all SAS servers (Viya, EBI, SASjs) + * \details Useful when you need to run a single piece of code against Viya, + SAS 9 with metadata, or SASjs on Base SAS. + + * OS independent + * No X command + * Prefixes: _mx_ + + */ diff --git a/tests/crossplatform/mcf_getfmttype.test.sas b/tests/base/mcf_getfmttype.test.sas similarity index 100% rename from tests/crossplatform/mcf_getfmttype.test.sas rename to tests/base/mcf_getfmttype.test.sas diff --git a/tests/crossplatform/mcf_init.test.sas b/tests/base/mcf_init.test.sas similarity index 100% rename from tests/crossplatform/mcf_init.test.sas rename to tests/base/mcf_init.test.sas diff --git a/tests/crossplatform/mcf_length.test.sas b/tests/base/mcf_length.test.sas similarity index 100% rename from tests/crossplatform/mcf_length.test.sas rename to tests/base/mcf_length.test.sas diff --git a/tests/crossplatform/mcf_string2file.test.sas b/tests/base/mcf_string2file.test.sas similarity index 100% rename from tests/crossplatform/mcf_string2file.test.sas rename to tests/base/mcf_string2file.test.sas diff --git a/tests/crossplatform/mf_dedup.test.sas b/tests/base/mf_dedup.test.sas similarity index 100% rename from tests/crossplatform/mf_dedup.test.sas rename to tests/base/mf_dedup.test.sas diff --git a/tests/crossplatform/mf_deletefile.test.sas b/tests/base/mf_deletefile.test.sas similarity index 100% rename from tests/crossplatform/mf_deletefile.test.sas rename to tests/base/mf_deletefile.test.sas diff --git a/tests/crossplatform/mf_existds.test.sas b/tests/base/mf_existds.test.sas similarity index 100% rename from tests/crossplatform/mf_existds.test.sas rename to tests/base/mf_existds.test.sas diff --git a/tests/crossplatform/mf_existfileref.test.sas b/tests/base/mf_existfileref.test.sas similarity index 100% rename from tests/crossplatform/mf_existfileref.test.sas rename to tests/base/mf_existfileref.test.sas diff --git a/tests/crossplatform/mf_existfunction.test.sas b/tests/base/mf_existfunction.test.sas similarity index 100% rename from tests/crossplatform/mf_existfunction.test.sas rename to tests/base/mf_existfunction.test.sas diff --git a/tests/crossplatform/mf_existvar.test.sas b/tests/base/mf_existvar.test.sas similarity index 100% rename from tests/crossplatform/mf_existvar.test.sas rename to tests/base/mf_existvar.test.sas diff --git a/tests/crossplatform/mf_fmtdttm.test.sas b/tests/base/mf_fmtdttm.test.sas similarity index 100% rename from tests/crossplatform/mf_fmtdttm.test.sas rename to tests/base/mf_fmtdttm.test.sas diff --git a/tests/crossplatform/mf_getapploc.test.sas b/tests/base/mf_getapploc.test.sas similarity index 100% rename from tests/crossplatform/mf_getapploc.test.sas rename to tests/base/mf_getapploc.test.sas diff --git a/tests/crossplatform/mf_getfilesize.test.sas b/tests/base/mf_getfilesize.test.sas similarity index 100% rename from tests/crossplatform/mf_getfilesize.test.sas rename to tests/base/mf_getfilesize.test.sas diff --git a/tests/crossplatform/mf_getfmtlist.test.sas b/tests/base/mf_getfmtlist.test.sas similarity index 100% rename from tests/crossplatform/mf_getfmtlist.test.sas rename to tests/base/mf_getfmtlist.test.sas diff --git a/tests/crossplatform/mf_getfmtname.test.sas b/tests/base/mf_getfmtname.test.sas similarity index 100% rename from tests/crossplatform/mf_getfmtname.test.sas rename to tests/base/mf_getfmtname.test.sas diff --git a/tests/crossplatform/mf_getuniquefileref.test.sas b/tests/base/mf_getuniquefileref.test.sas similarity index 100% rename from tests/crossplatform/mf_getuniquefileref.test.sas rename to tests/base/mf_getuniquefileref.test.sas diff --git a/tests/crossplatform/mf_getuniquelibref.test.sas b/tests/base/mf_getuniquelibref.test.sas similarity index 100% rename from tests/crossplatform/mf_getuniquelibref.test.sas rename to tests/base/mf_getuniquelibref.test.sas diff --git a/tests/crossplatform/mf_getvarcount.test.sas b/tests/base/mf_getvarcount.test.sas similarity index 100% rename from tests/crossplatform/mf_getvarcount.test.sas rename to tests/base/mf_getvarcount.test.sas diff --git a/tests/crossplatform/mf_getvarlist.test.sas b/tests/base/mf_getvarlist.test.sas similarity index 100% rename from tests/crossplatform/mf_getvarlist.test.sas rename to tests/base/mf_getvarlist.test.sas diff --git a/tests/crossplatform/mf_isint.test.sas b/tests/base/mf_isint.test.sas similarity index 100% rename from tests/crossplatform/mf_isint.test.sas rename to tests/base/mf_isint.test.sas diff --git a/tests/crossplatform/mf_islibds.test.sas b/tests/base/mf_islibds.test.sas similarity index 100% rename from tests/crossplatform/mf_islibds.test.sas rename to tests/base/mf_islibds.test.sas diff --git a/tests/crossplatform/mf_verifymacvars.test.sas b/tests/base/mf_verifymacvars.test.sas similarity index 100% rename from tests/crossplatform/mf_verifymacvars.test.sas rename to tests/base/mf_verifymacvars.test.sas diff --git a/tests/crossplatform/mf_wordsinstr1andstr2.test.sas b/tests/base/mf_wordsinstr1andstr2.test.sas similarity index 100% rename from tests/crossplatform/mf_wordsinstr1andstr2.test.sas rename to tests/base/mf_wordsinstr1andstr2.test.sas diff --git a/tests/crossplatform/mf_wordsinstr1butnotstr2.test.sas b/tests/base/mf_wordsinstr1butnotstr2.test.sas similarity index 100% rename from tests/crossplatform/mf_wordsinstr1butnotstr2.test.sas rename to tests/base/mf_wordsinstr1butnotstr2.test.sas diff --git a/tests/crossplatform/mf_writefile.test.sas b/tests/base/mf_writefile.test.sas similarity index 100% rename from tests/crossplatform/mf_writefile.test.sas rename to tests/base/mf_writefile.test.sas diff --git a/tests/crossplatform/mp_abort.test.nofix.sas b/tests/base/mp_abort.test.nofix.sas similarity index 100% rename from tests/crossplatform/mp_abort.test.nofix.sas rename to tests/base/mp_abort.test.nofix.sas diff --git a/tests/crossplatform/mp_appendfile.test.sas b/tests/base/mp_appendfile.test.sas similarity index 100% rename from tests/crossplatform/mp_appendfile.test.sas rename to tests/base/mp_appendfile.test.sas diff --git a/tests/crossplatform/mp_applyformats.test.sas b/tests/base/mp_applyformats.test.sas similarity index 100% rename from tests/crossplatform/mp_applyformats.test.sas rename to tests/base/mp_applyformats.test.sas diff --git a/tests/crossplatform/mp_assert.test.sas b/tests/base/mp_assert.test.sas similarity index 100% rename from tests/crossplatform/mp_assert.test.sas rename to tests/base/mp_assert.test.sas diff --git a/tests/crossplatform/mp_assertcolvals.test.sas b/tests/base/mp_assertcolvals.test.sas similarity index 100% rename from tests/crossplatform/mp_assertcolvals.test.sas rename to tests/base/mp_assertcolvals.test.sas diff --git a/tests/crossplatform/mp_assertdsobs.test.sas b/tests/base/mp_assertdsobs.test.sas similarity index 100% rename from tests/crossplatform/mp_assertdsobs.test.sas rename to tests/base/mp_assertdsobs.test.sas diff --git a/tests/crossplatform/mp_assertscope.test.sas b/tests/base/mp_assertscope.test.sas similarity index 100% rename from tests/crossplatform/mp_assertscope.test.sas rename to tests/base/mp_assertscope.test.sas diff --git a/tests/crossplatform/mp_base64copy.test.sas b/tests/base/mp_base64copy.test.sas similarity index 100% rename from tests/crossplatform/mp_base64copy.test.sas rename to tests/base/mp_base64copy.test.sas diff --git a/tests/crossplatform/mp_binarycopy.test.sas b/tests/base/mp_binarycopy.test.sas similarity index 100% rename from tests/crossplatform/mp_binarycopy.test.sas rename to tests/base/mp_binarycopy.test.sas diff --git a/tests/crossplatform/mp_chop.test.sas b/tests/base/mp_chop.test.sas similarity index 100% rename from tests/crossplatform/mp_chop.test.sas rename to tests/base/mp_chop.test.sas diff --git a/tests/crossplatform/mp_cntlout.test.sas b/tests/base/mp_cntlout.test.sas similarity index 100% rename from tests/crossplatform/mp_cntlout.test.sas rename to tests/base/mp_cntlout.test.sas diff --git a/tests/crossplatform/mp_copyfolder.test.sas b/tests/base/mp_copyfolder.test.sas similarity index 100% rename from tests/crossplatform/mp_copyfolder.test.sas rename to tests/base/mp_copyfolder.test.sas diff --git a/tests/crossplatform/mp_coretable.test.sas b/tests/base/mp_coretable.test.sas similarity index 100% rename from tests/crossplatform/mp_coretable.test.sas rename to tests/base/mp_coretable.test.sas diff --git a/tests/crossplatform/mp_createwebservice.test.sas b/tests/base/mp_createwebservice.test.sas similarity index 100% rename from tests/crossplatform/mp_createwebservice.test.sas rename to tests/base/mp_createwebservice.test.sas diff --git a/tests/crossplatform/mp_deletefolder.test.sas b/tests/base/mp_deletefolder.test.sas similarity index 100% rename from tests/crossplatform/mp_deletefolder.test.sas rename to tests/base/mp_deletefolder.test.sas diff --git a/tests/crossplatform/mp_dirlist.test.sas b/tests/base/mp_dirlist.test.sas similarity index 100% rename from tests/crossplatform/mp_dirlist.test.sas rename to tests/base/mp_dirlist.test.sas diff --git a/tests/crossplatform/mp_ds2cards.test.sas b/tests/base/mp_ds2cards.test.sas similarity index 100% rename from tests/crossplatform/mp_ds2cards.test.sas rename to tests/base/mp_ds2cards.test.sas diff --git a/tests/crossplatform/mp_ds2csv.test.sas b/tests/base/mp_ds2csv.test.sas similarity index 100% rename from tests/crossplatform/mp_ds2csv.test.sas rename to tests/base/mp_ds2csv.test.sas diff --git a/tests/crossplatform/mp_ds2fmtds.test.sas b/tests/base/mp_ds2fmtds.test.sas similarity index 100% rename from tests/crossplatform/mp_ds2fmtds.test.sas rename to tests/base/mp_ds2fmtds.test.sas diff --git a/tests/crossplatform/mp_ds2inserts.test.sas b/tests/base/mp_ds2inserts.test.sas similarity index 100% rename from tests/crossplatform/mp_ds2inserts.test.sas rename to tests/base/mp_ds2inserts.test.sas diff --git a/tests/crossplatform/mp_ds2md.test.sas b/tests/base/mp_ds2md.test.sas similarity index 100% rename from tests/crossplatform/mp_ds2md.test.sas rename to tests/base/mp_ds2md.test.sas diff --git a/tests/crossplatform/mp_ds2squeeze.test.sas b/tests/base/mp_ds2squeeze.test.sas similarity index 100% rename from tests/crossplatform/mp_ds2squeeze.test.sas rename to tests/base/mp_ds2squeeze.test.sas diff --git a/tests/crossplatform/mp_filtercheck.test.sas b/tests/base/mp_filtercheck.test.sas similarity index 100% rename from tests/crossplatform/mp_filtercheck.test.sas rename to tests/base/mp_filtercheck.test.sas diff --git a/tests/crossplatform/mp_filtergenerate.test.sas b/tests/base/mp_filtergenerate.test.sas similarity index 100% rename from tests/crossplatform/mp_filtergenerate.test.sas rename to tests/base/mp_filtergenerate.test.sas diff --git a/tests/crossplatform/mp_filterstore.test.1.sas b/tests/base/mp_filterstore.test.1.sas similarity index 100% rename from tests/crossplatform/mp_filterstore.test.1.sas rename to tests/base/mp_filterstore.test.1.sas diff --git a/tests/crossplatform/mp_filterstore.test.2.sas b/tests/base/mp_filterstore.test.2.sas similarity index 100% rename from tests/crossplatform/mp_filterstore.test.2.sas rename to tests/base/mp_filterstore.test.2.sas diff --git a/tests/crossplatform/mp_filtervalidate.test.sas b/tests/base/mp_filtervalidate.test.sas similarity index 100% rename from tests/crossplatform/mp_filtervalidate.test.sas rename to tests/base/mp_filtervalidate.test.sas diff --git a/tests/crossplatform/mp_getcols.test.sas b/tests/base/mp_getcols.test.sas similarity index 100% rename from tests/crossplatform/mp_getcols.test.sas rename to tests/base/mp_getcols.test.sas diff --git a/tests/crossplatform/mp_getconstraints.test.sas b/tests/base/mp_getconstraints.test.sas similarity index 100% rename from tests/crossplatform/mp_getconstraints.test.sas rename to tests/base/mp_getconstraints.test.sas diff --git a/tests/crossplatform/mp_getddl.test.sas b/tests/base/mp_getddl.test.sas similarity index 100% rename from tests/crossplatform/mp_getddl.test.sas rename to tests/base/mp_getddl.test.sas diff --git a/tests/crossplatform/mp_getformats.test.sas b/tests/base/mp_getformats.test.sas similarity index 100% rename from tests/crossplatform/mp_getformats.test.sas rename to tests/base/mp_getformats.test.sas diff --git a/tests/crossplatform/mp_getmaxvarlengths.test.sas b/tests/base/mp_getmaxvarlengths.test.sas similarity index 100% rename from tests/crossplatform/mp_getmaxvarlengths.test.sas rename to tests/base/mp_getmaxvarlengths.test.sas diff --git a/tests/crossplatform/mp_getpk.test.sas b/tests/base/mp_getpk.test.sas similarity index 100% rename from tests/crossplatform/mp_getpk.test.sas rename to tests/base/mp_getpk.test.sas diff --git a/tests/crossplatform/mp_gsubfile.test.sas b/tests/base/mp_gsubfile.test.sas similarity index 100% rename from tests/crossplatform/mp_gsubfile.test.sas rename to tests/base/mp_gsubfile.test.sas diff --git a/tests/crossplatform/mp_hashdataset.test.sas b/tests/base/mp_hashdataset.test.sas similarity index 100% rename from tests/crossplatform/mp_hashdataset.test.sas rename to tests/base/mp_hashdataset.test.sas diff --git a/tests/crossplatform/mp_init.test.sas b/tests/base/mp_init.test.sas similarity index 100% rename from tests/crossplatform/mp_init.test.sas rename to tests/base/mp_init.test.sas diff --git a/tests/crossplatform/mp_jsonout.test.1.sas b/tests/base/mp_jsonout.test.1.sas similarity index 100% rename from tests/crossplatform/mp_jsonout.test.1.sas rename to tests/base/mp_jsonout.test.1.sas diff --git a/tests/crossplatform/mp_jsonout.test.2.sas b/tests/base/mp_jsonout.test.2.sas similarity index 100% rename from tests/crossplatform/mp_jsonout.test.2.sas rename to tests/base/mp_jsonout.test.2.sas diff --git a/tests/crossplatform/mp_jsonout.test.3.sas b/tests/base/mp_jsonout.test.3.sas similarity index 100% rename from tests/crossplatform/mp_jsonout.test.3.sas rename to tests/base/mp_jsonout.test.3.sas diff --git a/tests/crossplatform/mp_lib2inserts.test.sas b/tests/base/mp_lib2inserts.test.sas similarity index 100% rename from tests/crossplatform/mp_lib2inserts.test.sas rename to tests/base/mp_lib2inserts.test.sas diff --git a/tests/crossplatform/mp_loadformat.test.sas b/tests/base/mp_loadformat.test.sas similarity index 100% rename from tests/crossplatform/mp_loadformat.test.sas rename to tests/base/mp_loadformat.test.sas diff --git a/tests/crossplatform/mp_lockanytable.test.sas b/tests/base/mp_lockanytable.test.sas similarity index 100% rename from tests/crossplatform/mp_lockanytable.test.sas rename to tests/base/mp_lockanytable.test.sas diff --git a/tests/crossplatform/mp_lockfilecheck.test.sas b/tests/base/mp_lockfilecheck.test.sas similarity index 100% rename from tests/crossplatform/mp_lockfilecheck.test.sas rename to tests/base/mp_lockfilecheck.test.sas diff --git a/tests/crossplatform/mp_makedata.test.sas b/tests/base/mp_makedata.test.sas similarity index 100% rename from tests/crossplatform/mp_makedata.test.sas rename to tests/base/mp_makedata.test.sas diff --git a/tests/crossplatform/mp_md5.test.sas b/tests/base/mp_md5.test.sas similarity index 100% rename from tests/crossplatform/mp_md5.test.sas rename to tests/base/mp_md5.test.sas diff --git a/tests/crossplatform/mp_replace.test.sas b/tests/base/mp_replace.test.sas similarity index 100% rename from tests/crossplatform/mp_replace.test.sas rename to tests/base/mp_replace.test.sas diff --git a/tests/crossplatform/mp_reseterror.test.sas b/tests/base/mp_reseterror.test.sas similarity index 100% rename from tests/crossplatform/mp_reseterror.test.sas rename to tests/base/mp_reseterror.test.sas diff --git a/tests/crossplatform/mp_resetoption.test.sas b/tests/base/mp_resetoption.test.sas similarity index 100% rename from tests/crossplatform/mp_resetoption.test.sas rename to tests/base/mp_resetoption.test.sas diff --git a/tests/crossplatform/mp_retainedkey.test.sas b/tests/base/mp_retainedkey.test.sas similarity index 100% rename from tests/crossplatform/mp_retainedkey.test.sas rename to tests/base/mp_retainedkey.test.sas diff --git a/tests/crossplatform/mp_searchcols.test.sas b/tests/base/mp_searchcols.test.sas similarity index 100% rename from tests/crossplatform/mp_searchcols.test.sas rename to tests/base/mp_searchcols.test.sas diff --git a/tests/crossplatform/mp_searchdata.test.sas b/tests/base/mp_searchdata.test.sas similarity index 100% rename from tests/crossplatform/mp_searchdata.test.sas rename to tests/base/mp_searchdata.test.sas diff --git a/tests/crossplatform/mp_sortinplace.test.sas b/tests/base/mp_sortinplace.test.sas similarity index 100% rename from tests/crossplatform/mp_sortinplace.test.sas rename to tests/base/mp_sortinplace.test.sas diff --git a/tests/crossplatform/mp_stackdiffs.test.sas b/tests/base/mp_stackdiffs.test.sas similarity index 100% rename from tests/crossplatform/mp_stackdiffs.test.sas rename to tests/base/mp_stackdiffs.test.sas diff --git a/tests/crossplatform/mp_storediffs.test.sas b/tests/base/mp_storediffs.test.sas similarity index 100% rename from tests/crossplatform/mp_storediffs.test.sas rename to tests/base/mp_storediffs.test.sas diff --git a/tests/crossplatform/mp_streamfile.test.sas b/tests/base/mp_streamfile.test.sas similarity index 100% rename from tests/crossplatform/mp_streamfile.test.sas rename to tests/base/mp_streamfile.test.sas diff --git a/tests/crossplatform/mp_validatecol.test.sas b/tests/base/mp_validatecol.test.sas similarity index 100% rename from tests/crossplatform/mp_validatecol.test.sas rename to tests/base/mp_validatecol.test.sas diff --git a/tests/crossplatform/mp_webin.test.sas b/tests/base/mp_webin.test.sas similarity index 100% rename from tests/crossplatform/mp_webin.test.sas rename to tests/base/mp_webin.test.sas diff --git a/tests/crossplatform/mp_zip.test.sas b/tests/base/mp_zip.test.sas similarity index 100% rename from tests/crossplatform/mp_zip.test.sas rename to tests/base/mp_zip.test.sas diff --git a/tests/xplatform/mx_getcode.test.sas b/tests/xplatform/mx_getcode.test.sas new file mode 100644 index 0000000..7e4cae2 --- /dev/null +++ b/tests/xplatform/mx_getcode.test.sas @@ -0,0 +1,38 @@ +/** + @file + @brief Testing mx_getcode.test.sas macro + + Be sure to run %let mcTestAppLoc=/Public/temp/macrocore; when + running in Studio + +

SAS Macros

+ @li mf_uid.sas + @li mp_assert.sas + @li mx_createwebservice.sas + @li mx_getcode.sas + @li mx_testservice.sas + +**/ + +/* first create a service */ + +%let item=%mf_uid();; + +%global test1; +%let test1=FAIL; + +filename ft15f001 temp; +parmcards4; + %let test1=SUCCESS; +;;;; +%mx_createwebservice(path=&mcTestAppLoc/temp,name=&item) + +%mx_getcode(&mcTestAppLoc/temp/&item,testref1) + +%inc testref1/lrecl=1000; + +%mp_assert( + iftrue=(&test1=SUCCESS), + desc=code was successfully fetched, + outds=work.test_results +) diff --git a/tests/crossplatform/mp_testservice.test.sas b/tests/xplatform/mx_testservice.test.sas similarity index 89% rename from tests/crossplatform/mp_testservice.test.sas rename to tests/xplatform/mx_testservice.test.sas index d52cefc..c2b2db4 100644 --- a/tests/crossplatform/mp_testservice.test.sas +++ b/tests/xplatform/mx_testservice.test.sas @@ -1,13 +1,13 @@ /** @file - @brief Testing mp_testservice.sas macro + @brief Testing mx_testservice.sas macro Be sure to run %let mcTestAppLoc=/Public/temp/macrocore; when runnin in Studio

SAS Macros

@li mp_createwebservice.sas - @li mp_testservice.sas + @li mx_testservice.sas @li mp_assert.sas **/ @@ -29,7 +29,7 @@ parmcards4; %mend x; %x() %webout(CLOSE) ;;;; -%mp_createwebservice(path=&mcTestAppLoc/services,name=sendObj) +%mx_createwebservice(path=&mcTestAppLoc/services,name=sendObj) %mp_assert( iftrue=(&syscc=0), @@ -48,7 +48,7 @@ data work.somedata1 work.somedata2; output; run; -%mp_testservice(&mcTestAppLoc/services/sendObj, +%mx_testservice(&mcTestAppLoc/services/sendObj, inputdatasets=work.somedata1 work.somedata2, debug=log, mdebug=1, diff --git a/xplatform/mx_createwebservice.sas b/xplatform/mx_createwebservice.sas new file mode 100644 index 0000000..a11de55 --- /dev/null +++ b/xplatform/mx_createwebservice.sas @@ -0,0 +1,96 @@ +/** + @file mx_createwebservice.sas + @brief Create a web service in SAS 9, Viya or SASjs + @details Creates a SASJS ready Stored Process in SAS 9, a Job Execution + Service in SAS Viya, and a Stored Program on SASjs Server + +Usage: + + %* compile macros ; + filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; + %inc mc; + + %* write some code; + filename ft15f001 temp; + parmcards4; + %* fetch any data from frontend ; + %webout(FETCH) + data example1 example2; + set sashelp.class; + run; + %* send data back; + %webout(OPEN) + %webout(ARR,example1) * Array format, fast, suitable for large tables ; + %webout(OBJ,example2) * Object format, easier to work with ; + %webout(CLOSE) + ;;;; + %mp_createwebservice(path=/Public/app/common,name=appInit,replace=YES) + +

SAS Macros

+ @li mf_getplatform.sas + @li mm_createwebservice.sas + @li ms_createwebservice.sas + @li mv_createwebservice.sas + + @param [in,out] path= The full folder path where the service will be created + @param [in,out] name= Service name. Avoid spaces. + @param [in] desc= The description of the service (optional) + @param [in] precode= Space separated list of filerefs, pointing to the code + that needs to be attached to the beginning of the service (optional) + @param [in] code= (ft15f001) Space seperated fileref(s) of the actual code to + be added + @param [in] replace= (YES) Select YES to replace any existing service in that + location + @param [in] mDebug= (0) set to 1 to show debug messages in the log + + @version 9.2 + @author Allan Bowe + +**/ + +%macro mx_createwebservice(path=HOME + ,name=initService + ,precode= + ,code=ft15f001 + ,desc=This service was created by the mp_createwebservice macro + ,replace=YES + ,mdebug=0 +)/*/STORE SOURCE*/; + +%if &syscc ge 4 %then %do; + %put syscc=&syscc - &sysmacroname will not execute in this state; + %return; +%end; + +%local platform; %let platform=%mf_getplatform(); +%if &platform=SASVIYA %then %do; + %if "&path"="HOME" %then %let path=/Users/&sysuserid/My Folder; + %mv_createwebservice(path=&path + ,name=&name + ,code=&code + ,precode=&precode + ,desc=&desc + ,replace=&replace + ) +%end; +%else %if &platform=SASJS %then %do; + %if "&path"="HOME" %then %let path=/Users/&_sasjs_username/My Folder; + %ms_createwebservice(path=&path + ,name=&name + ,code=&code + ,precode=&precode + ,mdebug=&mdebug + ) +%end; +%else %do; + %if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder; + %mm_createwebservice(path=&path + ,name=&name + ,code=&code + ,precode=&precode + ,desc=&desc + ,replace=&replace + ) +%end; + +%mend mx_createwebservice; diff --git a/xplatform/mx_getcode.sas b/xplatform/mx_getcode.sas new file mode 100644 index 0000000..ee689a6 --- /dev/null +++ b/xplatform/mx_getcode.sas @@ -0,0 +1,57 @@ +/** + @file + @brief Fetches code from Viya Job, SAS 9 STP, or SASjs Server STP + @details When building applications that run on multiple flavours of SAS, it + is convenient to use a single macro (like this one) to fetch the source + code from a Viya Job, SAS 9 Stored Process, or SASjs Stored Program. + + The alternative would be to compile a generic macro in target-specific + folders (SASVIYA, SAS9 and SASJS). This avoids compiling unnecessary macros + at the expense of a more complex sasjsconfig.json setup. + + + @param [in] loc The full path to the Viya Job, SAS 9 Stored Process or SASjs + Stored Program in Drive or Metadata, WITHOUT the .sas extension (SASjs only) + @param [out] outref= (0) The fileref to create, which will contain the source + code. + +

SAS Macros

+ @li mf_getplatform.sas + @li mf_getuniquename.sas + @li mm_getstpcode.sas + @li ms_getfile.sas + + @author Allan Bowe + +**/ + +%macro mx_getcode(loc,outref=0 +)/*/STORE SOURCE*/; + +%local platform name shortloc; +%let platform=%mf_getplatform(); + +%if &platform=SASJS %then %do; + %ms_getfile(&loc..sas, outref=&outref) +%end; +%else %if &platform=SAS9 %then %do; + %mm_getstpcode(tree=&loc,outloc=&outref) +%end; +%else %if &platform=SASVIYA %then %do; + /* extract name & path from &loc */ + data _null_; + loc=symget('loc'); + name=scan(loc,-1,'/'); + shortloc=substr(loc,1,length(loc)-length(name)-1); + call symputx('name',name,'l'); + call symputx('shortloc',shortloc,'l'); + run; + %mv_getjobcode( + path=&shortloc, + name=&name, + outref=&outref + ) +%end; +%else %put &sysmacroname: &platform is unsupported!!!; + +%mend mx_getcode; diff --git a/xplatform/mx_testservice.sas b/xplatform/mx_testservice.sas new file mode 100644 index 0000000..6a089d3 --- /dev/null +++ b/xplatform/mx_testservice.sas @@ -0,0 +1,299 @@ +/** + @file + @brief Will execute a SASjs web service on SAS 9, Viya or SASjs Server + @details Prepares the input files and retrieves the resulting datasets from + the response JSON. + + Note - the _webout fileref should NOT be assigned prior to running this macro. + + @param [in] program The _PROGRAM endpoint to test + @param [in] inputfiles=(0) A list of space seperated fileref:filename pairs as + follows: + inputfiles=inref:filename inref2:filename2 + @param [in] inputdatasets= (0) All datasets in this space seperated list are + converted into SASJS-formatted CSVs (see mp_ds2csv.sas) files and added to + the list of `inputfiles` for ingestion. The dataset will be sent with the + same name (no need for a colon modifier). + @param [in] inputparams=(0) A dataset containing name/value pairs in the + following format: + |name:$32|value:$1000| + |---|---| + |stpmacname|some value| + |mustbevalidname|can be anything, oops, %abort!!| + + @param [in] debug= (log) Provide the _debug value + @param [in] mdebug= (0) Set to 1 to provide macro debugging + @param [in] viyaresult= (WEBOUT_JSON) The Viya result type to return. For + more info, see mv_getjobresult.sas + @param [in] viyacontext= (SAS Job Execution compute context) The Viya compute + context on which to run the service + @param [out] outlib= (0) Output libref to contain the final tables. Set to + 0 if the service output is not in JSON format. + @param [out] outref= (0) Output fileref to create, to contain the full _webout + response. + +

SAS Macros

+ @li mf_getplatform.sas + @li mf_getuniquefileref.sas + @li mf_getuniquename.sas + @li mp_abort.sas + @li mp_binarycopy.sas + @li mp_chop.sas + @li mp_ds2csv.sas + @li ms_testservice.sas + @li mv_getjobresult.sas + @li mv_jobflow.sas + +

Related Programs

+ @li mx_testservice.test.sas + + @version 9.4 + @author Allan Bowe + +**/ + +%macro mx_testservice(program, + inputfiles=0, + inputdatasets=0, + inputparams=0, + debug=log, + mdebug=0, + outlib=0, + outref=0, + viyaresult=WEBOUT_JSON, + viyacontext=SAS Job Execution compute context +); +%local dbg pcnt fref1 fref2 webref webrefpath i webcount var platform; +%if &mdebug=1 %then %do; + %put &sysmacroname entry vars:; + %put _local_; +%end; +%else %let dbg=*; + +/* sanitise inputparams */ +%let pcnt=0; +%if &inputparams ne 0 %then %do; + data _null_; + set &inputparams; + if not nvalid(name,'v7') then putlog (_all_)(=); + else if name in ( + 'program','inputfiles','inputparams','debug','outlib','outref' + ) then putlog (_all_)(=); + else do; + x+1; + call symputx(name,quote(cats(value)),'l'); + call symputx(cats('pval',x),name,'l'); + call symputx('pcnt',x,'l'); + end; + run; + %mp_abort(iftrue= (%mf_nobs(&inputparams) ne &pcnt) + ,mac=&sysmacroname + ,msg=%str(Invalid values in &inputparams) + ) +%end; + +/* convert inputdatasets to filerefs */ +%if "&inputdatasets" ne "0" %then %do; + %if %quote(&inputfiles)=0 %then %let inputfiles=; + %do i=1 %to %sysfunc(countw(&inputdatasets,%str( ))); + %let var=%scan(&inputdatasets,&i,%str( )); + %local dsref&i; + %let dsref&i=%mf_getuniquefileref(); + %mp_ds2csv(&var,outref=&&dsref&i,headerformat=SASJS) + %let inputfiles=&inputfiles &&dsref&i:%scan(&var,-1,.); + %end; +%end; + +%let platform=%mf_getplatform(); +%let fref1=%mf_getuniquefileref(); +%let fref2=%mf_getuniquefileref(); +%let webref=%mf_getuniquefileref(); +%let webrefpath=%sysfunc(pathname(work))/%mf_getuniquename(); +/* mp_chop requires a physical path as input */ +filename &webref "&webrefpath"; + +%if &platform=SASMETA %then %do; + + /* parse the input files */ + %if %quote(&inputfiles) ne 0 %then %do; + %let webcount=%sysfunc(countw(&inputfiles)); + %put &=webcount; + %do i=1 %to &webcount; + %let var=%scan(&inputfiles,&i,%str( )); + %local webfref&i webname&i; + %let webref&i=%scan(&var,1,%str(:)); + %let webname&i=%scan(&var,2,%str(:)); + %put webref&i=&&webref&i; + %put webname&i=&&webname&i; + %end; + %end; + %else %let webcount=0; + + proc stp program="&program"; + inputparam _program="&program" + %do i=1 %to &webcount; + %if &webcount=1 %then %do; + _webin_fileref="&&webref&i" + _webin_name="&&webname&i" + %end; + %else %do; + _webin_fileref&i="&&webref&i" + _webin_name&i="&&webname&i" + %end; + %end; + _webin_file_count="&webcount" + _debug="&debug" + %do i=1 %to &pcnt; + /* resolve name only, proc stp fetches value */ + &&pval&i=&&&&&&pval&i + %end; + ; + %do i=1 %to &webcount; + inputfile &&webref&i; + %end; + outputfile _webout=&webref; + run; + + data _null_; + infile &webref; + file &fref1; + input; + length line $10000; + if index(_infile_,'>>weboutBEGIN<<') then do; + line=tranwrd(_infile_,'>>weboutBEGIN<<',''); + put line; + end; + else if index(_infile_,'>>weboutEND<<') then do; + line=tranwrd(_infile_,'>>weboutEND<<',''); + put line; + stop; + end; + else put _infile_; + run; + data _null_; + infile &fref1; + input; + put _infile_; + run; + %if &outlib ne 0 %then %do; + libname &outlib json (&fref1); + %end; + %if &outref ne 0 %then %do; + filename &outref temp; + %mp_binarycopy(inref=&webref,outref=&outref) + %end; + +%end; +%else %if &platform=SASVIYA %then %do; + + /* prepare inputparams */ + %local ds1; + %let ds1=%mf_getuniquename(); + %if "&inputparams" ne "0" %then %do; + proc transpose data=&inputparams out=&ds1; + id name; + var value; + run; + %end; + %else %do; + data &ds1;run; + %end; + + /* parse the input files - convert to sasjs params */ + %local webcount i var sasjs_tables; + %if %quote(&inputfiles) ne 0 %then %do; + %let webcount=%sysfunc(countw(&inputfiles)); + %put &=webcount; + %do i=1 %to &webcount; + %let var=%scan(&inputfiles,&i,%str( )); + %local webfref&i webname&i sasjs&i.data; + %let webref&i=%scan(&var,1,%str(:)); + %let webname&i=%scan(&var,2,%str(:)); + %put webref&i=&&webref&i; + %put webname&i=&&webname&i; + + %let sasjs_tables=&sasjs_tables &&webname&i; + data _null_; + infile &&webref&i lrecl=32767; + input; + if _n_=1 then call symputx("sasjs&i.data",_infile_); + else call symputx( + "sasjs&i.data",cats(symget("sasjs&i.data"),'0D0A'x,_infile_) + ); + putlog "&sysmacroname infile: " _infile_; + run; + data &ds1; + set &ds1; + length sasjs&i.data $32767 sasjs_tables $1000; + sasjs&i.data=symget("sasjs&i.data"); + sasjs_tables=symget("sasjs_tables"); + run; + %end; + %end; + %else %let webcount=0; + + data &ds1; + retain _program "&program"; + retain _contextname "&viyacontext"; + set &ds1; + putlog "&sysmacroname inputparams:"; + putlog (_all_)(=); + run; + + %mv_jobflow(inds=&ds1 + ,maxconcurrency=1 + ,outds=work.results + ,outref=&fref1 + ,mdebug=&mdebug + ) + /* show the log */ + data _null_; + infile &fref1; + input; + putlog _infile_; + run; + /* get the uri to fetch results */ + data _null_; + set work.results; + call symputx('uri',uri); + putlog "&sysmacroname: fetching results for " uri; + run; + /* fetch results from webout.json */ + %mv_getjobresult(uri=&uri, + result=&viyaresult, + outref=&outref, + outlib=&outlib, + mdebug=&mdebug + ) + +%end; +%else %if &platform=SASJS %then %do; + + %ms_testservice(&program + ,inputfiles=&inputfiles + ,inputdatasets=&inputdatasets + ,inputparams=&inputparams + ,debug=&debug + ,mdebug=&mdebug + ,outlib=&outlib + ,outref=&outref + ) + +%end; +%else %do; + %put %str(ERR)OR: Unrecognised platform: &platform; +%end; + +%if &mdebug=0 %then %do; + filename &fref1 clear; + %if &platform ne SASJS %then %do; + filename &fref2 clear; + filename &webref clear; + %end; +%end; +%else %do; + %put &sysmacroname exit vars:; + %put _local_; +%end; + +%mend mx_testservice; From bb6111e2b3d08986eff650079db7b37c926b7ab7 Mon Sep 17 00:00:00 2001 From: munja Date: Fri, 20 May 2022 11:16:30 +0100 Subject: [PATCH 2/2] fix: all.sas, readme, dependency issue and sasjsconfig file --- README.md | 2 +- all.sas | 841 ++++++++++++++++------------ base/mp_coretable.sas | 3 +- sasjs/sasjsconfig.json | 6 +- tests/xplatform/mx_getcode.test.sas | 2 +- xplatform/mx_getcode.sas | 2 +- 6 files changed, 496 insertions(+), 360 deletions(-) diff --git a/README.md b/README.md index 4c5bf7f..9295bbf 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ This library will not be used for storing data entries (such as formats or datal The fcmp macros are used to generate fcmp functions, and can be used with or without the `proc fcmp` wrapper. -### LUA library +### LUA folder Wait - this is a macro library - what is LUA doing here? Well, it is a little known fact that you CAN run LUA within a SAS Macro. It has to be written to a text file with a `.lua` extension, from where you can `%include` it. So, without using the `proc lua` wrapper. diff --git a/all.sas b/all.sas index 297493c..2d62bc4 100644 --- a/all.sas +++ b/all.sas @@ -816,8 +816,12 @@ or %index(&pgm,/tests/testteardown) %put %mf_getplatform(); - returns: - SASMETA (or SASVIYA) + returns one of: + + @li SASMETA + @li SASVIYA + @li SASJS + @li BASESAS @param switch the param for which to return a platform specific variable @@ -879,7 +883,8 @@ or %index(&pgm,/tests/testteardown) %else %if &switch=VIYARESTAPI %then %do; %mf_trimstr(%sysfunc(getoption(servicesbaseurl)),/) %end; -%mend mf_getplatform;/** +%mend mf_getplatform; +/** @file @brief Adds custom quotes / delimiters to a delimited string @details Can be used in open code, eg as follows: @@ -1684,7 +1689,8 @@ Usage: %if %sysfunc(findc(%str(&val),,kd)) %then %do;0%end; %else %do;1%end; -%mend mf_isint;/** +%mend mf_isint; +/** @file @brief Checks whether a string follows correct library.dataset format @details Many macros in the core library accept a library.dataset parameter @@ -3979,6 +3985,7 @@ drop table &ddlds,&cntlds; @li mddl_dc_filtersummary.sas @li mddl_dc_locktable.sas @li mddl_dc_maxkeytable.sas + @li mf_getuniquename.sas

Related Macros

@li mp_filterstore.sas @@ -3995,7 +4002,7 @@ drop table &ddlds,&cntlds; %macro mp_coretable(table_ref,libds=0 )/*/STORE SOURCE*/; %local outds ; -%let outds=%sysfunc(ifc(&libds=0,_data_,&libds)); +%let outds=%sysfunc(ifc(&libds=0,%mf_getuniquename(),&libds)); proc sql; %if &table_ref=DIFFTABLE %then %do; %mddl_dc_difftable(libds=&outds) @@ -4087,51 +4094,14 @@ run; %mend mp_createconstraints;/** @file mp_createwebservice.sas - @brief Create a web service in SAS 9 or Viya - @details Creates a SASJS ready Stored Process in SAS 9 or Job Execution - Service in SAS Viya + @brief Create a web service in SAS 9, Viya or SASjs Server + @details This is actually a wrapper for mx_createwebservice.sas, remaining + for legacy purposes. For new apps, use mx_createwebservice.sas. -Usage: - - %* compile macros ; - filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; - %inc mc; - - %* write some code; - filename ft15f001 temp; - parmcards4; - %* fetch any data from frontend ; - %webout(FETCH) - data example1 example2; - set sashelp.class; - run; - %* send data back; - %webout(OPEN) - %webout(ARR,example1) * Array format, fast, suitable for large tables ; - %webout(OBJ,example2) * Object format, easier to work with ; - %webout(CLOSE) - ;;;; - %mp_createwebservice(path=/Public/app/common,name=appInit,replace=YES)

SAS Macros

- @li mf_getplatform.sas - @li mm_createwebservice.sas - @li ms_createwebservice.sas - @li mv_createwebservice.sas + @li mx_createwebservice.sas - @param [in,out] path= The full folder path where the service will be created - @param [in,out] name= Service name. Avoid spaces. - @param [in] desc= The description of the service (optional) - @param [in] precode= Space separated list of filerefs, pointing to the code - that needs to be attached to the beginning of the service (optional) - @param [in] code= (ft15f001) Space seperated fileref(s) of the actual code to - be added - @param [in] replace= (YES) Select YES to replace any existing service in that - location - @param [in] mDebug= (0) set to 1 to show debug messages in the log - - @version 9.2 - @author Allan Bowe **/ @@ -4144,41 +4114,14 @@ Usage: ,mdebug=0 )/*/STORE SOURCE*/; -%if &syscc ge 4 %then %do; - %put syscc=&syscc - &sysmacroname will not execute in this state; - %return; -%end; - -%local platform; %let platform=%mf_getplatform(); -%if &platform=SASVIYA %then %do; - %if "&path"="HOME" %then %let path=/Users/&sysuserid/My Folder; - %mv_createwebservice(path=&path + %mx_createwebservice(path=&path ,name=&name - ,code=&code ,precode=&precode + ,code=&code ,desc=&desc ,replace=&replace - ) -%end; -%else %if &platform=SASJS %then %do; - %if "&path"="HOME" %then %let path=/Users/&_sasjs_username/My Folder; - %ms_createwebservice(path=&path - ,name=&name - ,code=&code - ,precode=&precode ,mdebug=&mdebug ) -%end; -%else %do; - %if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder; - %mm_createwebservice(path=&path - ,name=&name - ,code=&code - ,precode=&precode - ,desc=&desc - ,replace=&replace - ) -%end; %mend mp_createwebservice; /** @@ -12191,54 +12134,12 @@ libname &lib clear; %mend mp_testjob;/** @file - @brief Will execute a SASjs web service on SAS 9 or Viya - @details Prepares the input files and retrieves the resulting datasets from - the response JSON. - - - - Note - the _webout fileref should NOT be assigned prior to running this macro. - - @param [in] program The _PROGRAM endpoint to test - @param [in] inputfiles=(0) A list of space seperated fileref:filename pairs as - follows: - inputfiles=inref:filename inref2:filename2 - @param [in] inputdatasets= (0) All datasets in this space seperated list are - converted into SASJS-formatted CSVs (see mp_ds2csv.sas) files and added to - the list of `inputfiles` for ingestion. The dataset will be sent with the - same name (no need for a colon modifier). - @param [in] inputparams=(0) A dataset containing name/value pairs in the - following format: - |name:$32|value:$1000| - |---|---| - |stpmacname|some value| - |mustbevalidname|can be anything, oops, %abort!!| - - @param [in] debug= (log) Provide the _debug value - @param [in] mdebug= (0) Set to 1 to provide macro debugging - @param [in] viyaresult= (WEBOUT_JSON) The Viya result type to return. For - more info, see mv_getjobresult.sas - @param [in] viyacontext= (SAS Job Execution compute context) The Viya compute - context on which to run the service - @param [out] outlib= (0) Output libref to contain the final tables. Set to - 0 if the service output is not in JSON format. - @param [out] outref= (0) Output fileref to create, to contain the full _webout - response. + @brief To be deprecated. Will execute a SASjs web service on SAS 9 or Viya + @details Use the mx_testservice.sas macro instead (documentation can be + found there)

SAS Macros

- @li mf_getplatform.sas - @li mf_getuniquefileref.sas - @li mf_getuniquename.sas - @li mp_abort.sas - @li mp_binarycopy.sas - @li mp_chop.sas - @li mp_ds2csv.sas - @li ms_testservice.sas - @li mv_getjobresult.sas - @li mv_jobflow.sas - -

Related Programs

- @li mp_testservice.test.sas + @li mx_testservice.sas @version 9.4 @author Allan Bowe @@ -12256,240 +12157,21 @@ libname &lib clear; viyaresult=WEBOUT_JSON, viyacontext=SAS Job Execution compute context )/*/STORE SOURCE*/; -%local dbg pcnt fref1 fref2 webref webrefpath i webcount var platform; -%if &mdebug=1 %then %do; - %put &sysmacroname entry vars:; - %put _local_; -%end; -%else %let dbg=*; -/* sanitise inputparams */ -%let pcnt=0; -%if &inputparams ne 0 %then %do; - data _null_; - set &inputparams; - if not nvalid(name,'v7') then putlog (_all_)(=); - else if name in ( - 'program','inputfiles','inputparams','debug','outlib','outref' - ) then putlog (_all_)(=); - else do; - x+1; - call symputx(name,quote(cats(value)),'l'); - call symputx(cats('pval',x),name,'l'); - call symputx('pcnt',x,'l'); - end; - run; - %mp_abort(iftrue= (%mf_nobs(&inputparams) ne &pcnt) - ,mac=&sysmacroname - ,msg=%str(Invalid values in &inputparams) - ) -%end; +%mx_testservice(&program, + inputfiles=&inputfiles, + inputdatasets=&inputdatasets, + inputparams=&inputparams, + debug=&debug, + mdebug=&mdebug, + outlib=&outlib, + outref=&outref, + viyaresult=&viyaresult, + viyacontext=&viyacontext +) -/* convert inputdatasets to filerefs */ -%if "&inputdatasets" ne "0" %then %do; - %if %quote(&inputfiles)=0 %then %let inputfiles=; - %do i=1 %to %sysfunc(countw(&inputdatasets,%str( ))); - %let var=%scan(&inputdatasets,&i,%str( )); - %local dsref&i; - %let dsref&i=%mf_getuniquefileref(); - %mp_ds2csv(&var,outref=&&dsref&i,headerformat=SASJS) - %let inputfiles=&inputfiles &&dsref&i:%scan(&var,-1,.); - %end; -%end; - -%let platform=%mf_getplatform(); -%let fref1=%mf_getuniquefileref(); -%let fref2=%mf_getuniquefileref(); -%let webref=%mf_getuniquefileref(); -%let webrefpath=%sysfunc(pathname(work))/%mf_getuniquename(); -/* mp_chop requires a physical path as input */ -filename &webref "&webrefpath"; - -%if &platform=SASMETA %then %do; - - /* parse the input files */ - %if %quote(&inputfiles) ne 0 %then %do; - %let webcount=%sysfunc(countw(&inputfiles)); - %put &=webcount; - %do i=1 %to &webcount; - %let var=%scan(&inputfiles,&i,%str( )); - %local webfref&i webname&i; - %let webref&i=%scan(&var,1,%str(:)); - %let webname&i=%scan(&var,2,%str(:)); - %put webref&i=&&webref&i; - %put webname&i=&&webname&i; - %end; - %end; - %else %let webcount=0; - - proc stp program="&program"; - inputparam _program="&program" - %do i=1 %to &webcount; - %if &webcount=1 %then %do; - _webin_fileref="&&webref&i" - _webin_name="&&webname&i" - %end; - %else %do; - _webin_fileref&i="&&webref&i" - _webin_name&i="&&webname&i" - %end; - %end; - _webin_file_count="&webcount" - _debug="&debug" - %do i=1 %to &pcnt; - /* resolve name only, proc stp fetches value */ - &&pval&i=&&&&&&pval&i - %end; - ; - %do i=1 %to &webcount; - inputfile &&webref&i; - %end; - outputfile _webout=&webref; - run; - - data _null_; - infile &webref; - file &fref1; - input; - length line $10000; - if index(_infile_,'>>weboutBEGIN<<') then do; - line=tranwrd(_infile_,'>>weboutBEGIN<<',''); - put line; - end; - else if index(_infile_,'>>weboutEND<<') then do; - line=tranwrd(_infile_,'>>weboutEND<<',''); - put line; - stop; - end; - else put _infile_; - run; - data _null_; - infile &fref1; - input; - put _infile_; - run; - %if &outlib ne 0 %then %do; - libname &outlib json (&fref1); - %end; - %if &outref ne 0 %then %do; - filename &outref temp; - %mp_binarycopy(inref=&webref,outref=&outref) - %end; - -%end; -%else %if &platform=SASVIYA %then %do; - - /* prepare inputparams */ - %local ds1; - %let ds1=%mf_getuniquename(); - %if "&inputparams" ne "0" %then %do; - proc transpose data=&inputparams out=&ds1; - id name; - var value; - run; - %end; - %else %do; - data &ds1;run; - %end; - - /* parse the input files - convert to sasjs params */ - %local webcount i var sasjs_tables; - %if %quote(&inputfiles) ne 0 %then %do; - %let webcount=%sysfunc(countw(&inputfiles)); - %put &=webcount; - %do i=1 %to &webcount; - %let var=%scan(&inputfiles,&i,%str( )); - %local webfref&i webname&i sasjs&i.data; - %let webref&i=%scan(&var,1,%str(:)); - %let webname&i=%scan(&var,2,%str(:)); - %put webref&i=&&webref&i; - %put webname&i=&&webname&i; - - %let sasjs_tables=&sasjs_tables &&webname&i; - data _null_; - infile &&webref&i lrecl=32767; - input; - if _n_=1 then call symputx("sasjs&i.data",_infile_); - else call symputx( - "sasjs&i.data",cats(symget("sasjs&i.data"),'0D0A'x,_infile_) - ); - putlog "&sysmacroname infile: " _infile_; - run; - data &ds1; - set &ds1; - length sasjs&i.data $32767 sasjs_tables $1000; - sasjs&i.data=symget("sasjs&i.data"); - sasjs_tables=symget("sasjs_tables"); - run; - %end; - %end; - %else %let webcount=0; - - data &ds1; - retain _program "&program"; - retain _contextname "&viyacontext"; - set &ds1; - putlog "&sysmacroname inputparams:"; - putlog (_all_)(=); - run; - - %mv_jobflow(inds=&ds1 - ,maxconcurrency=1 - ,outds=work.results - ,outref=&fref1 - ,mdebug=&mdebug - ) - /* show the log */ - data _null_; - infile &fref1; - input; - putlog _infile_; - run; - /* get the uri to fetch results */ - data _null_; - set work.results; - call symputx('uri',uri); - putlog "&sysmacroname: fetching results for " uri; - run; - /* fetch results from webout.json */ - %mv_getjobresult(uri=&uri, - result=&viyaresult, - outref=&outref, - outlib=&outlib, - mdebug=&mdebug - ) - -%end; -%else %if &platform=SASJS %then %do; - - %ms_testservice(&program - ,inputfiles=&inputfiles - ,inputdatasets=&inputdatasets - ,inputparams=&inputparams - ,debug=&debug - ,mdebug=&mdebug - ,outlib=&outlib - ,outref=&outref - ) - -%end; -%else %do; - %put %str(ERR)OR: Unrecognised platform: &platform; -%end; - -%if &mdebug=0 %then %do; - filename &fref1 clear; - %if &platform ne SASJS %then %do; - filename &fref2 clear; - filename &webref clear; - %end; -%end; -%else %do; - %put &sysmacroname exit vars:; - %put _local_; -%end; - -%mend mp_testservice;/** +%mend mp_testservice; +/** @file mp_testwritespeedlibrary.sas @brief Tests the write speed of a new table in a SAS library @details Will create a new table of a certain size in an @@ -27155,4 +26837,455 @@ endsub; options insert=(CMPLIB=(&lib..&cat)); %end; -%mend mcf_string2file; \ No newline at end of file +%mend mcf_string2file;/** + @file mx_createwebservice.sas + @brief Create a web service in SAS 9, Viya or SASjs + @details Creates a SASJS ready Stored Process in SAS 9, a Job Execution + Service in SAS Viya, and a Stored Program on SASjs Server + +Usage: + + %* compile macros ; + filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas"; + %inc mc; + + %* write some code; + filename ft15f001 temp; + parmcards4; + %* fetch any data from frontend ; + %webout(FETCH) + data example1 example2; + set sashelp.class; + run; + %* send data back; + %webout(OPEN) + %webout(ARR,example1) * Array format, fast, suitable for large tables ; + %webout(OBJ,example2) * Object format, easier to work with ; + %webout(CLOSE) + ;;;; + %mp_createwebservice(path=/Public/app/common,name=appInit,replace=YES) + +

SAS Macros

+ @li mf_getplatform.sas + @li mm_createwebservice.sas + @li ms_createwebservice.sas + @li mv_createwebservice.sas + + @param [in,out] path= The full folder path where the service will be created + @param [in,out] name= Service name. Avoid spaces. + @param [in] desc= The description of the service (optional) + @param [in] precode= Space separated list of filerefs, pointing to the code + that needs to be attached to the beginning of the service (optional) + @param [in] code= (ft15f001) Space seperated fileref(s) of the actual code to + be added + @param [in] replace= (YES) Select YES to replace any existing service in that + location + @param [in] mDebug= (0) set to 1 to show debug messages in the log + + @version 9.2 + @author Allan Bowe + +**/ + +%macro mx_createwebservice(path=HOME + ,name=initService + ,precode= + ,code=ft15f001 + ,desc=This service was created by the mp_createwebservice macro + ,replace=YES + ,mdebug=0 +)/*/STORE SOURCE*/; + +%if &syscc ge 4 %then %do; + %put syscc=&syscc - &sysmacroname will not execute in this state; + %return; +%end; + +%local platform; %let platform=%mf_getplatform(); +%if &platform=SASVIYA %then %do; + %if "&path"="HOME" %then %let path=/Users/&sysuserid/My Folder; + %mv_createwebservice(path=&path + ,name=&name + ,code=&code + ,precode=&precode + ,desc=&desc + ,replace=&replace + ) +%end; +%else %if &platform=SASJS %then %do; + %if "&path"="HOME" %then %let path=/Users/&_sasjs_username/My Folder; + %ms_createwebservice(path=&path + ,name=&name + ,code=&code + ,precode=&precode + ,mdebug=&mdebug + ) +%end; +%else %do; + %if "&path"="HOME" %then %let path=/User Folders/&_METAPERSON/My Folder; + %mm_createwebservice(path=&path + ,name=&name + ,code=&code + ,precode=&precode + ,desc=&desc + ,replace=&replace + ) +%end; + +%mend mx_createwebservice; +/** + @file + @brief Fetches code from Viya Job, SAS 9 STP, or SASjs Server STP + @details When building applications that run on multiple flavours of SAS, it + is convenient to use a single macro (like this one) to fetch the source + code from a Viya Job, SAS 9 Stored Process, or SASjs Stored Program. + + The alternative would be to compile a generic macro in target-specific + folders (SASVIYA, SAS9 and SASJS). This avoids compiling unnecessary macros + at the expense of a more complex sasjsconfig.json setup. + + + @param [in] loc The full path to the Viya Job, SAS 9 Stored Process or SASjs + Stored Program in Drive or Metadata, WITHOUT the .sas extension (SASjs only) + @param [out] outref= (0) The fileref to create, which will contain the source + code. + +

SAS Macros

+ @li mf_getplatform.sas + @li mm_getstpcode.sas + @li ms_getfile.sas + @li mv_getjobcode.sas + + @author Allan Bowe + +**/ + +%macro mx_getcode(loc,outref=0 +)/*/STORE SOURCE*/; + +%local platform name shortloc; +%let platform=%mf_getplatform(); + +%if &platform=SASJS %then %do; + %ms_getfile(&loc..sas, outref=&outref) +%end; +%else %if &platform=SAS9 %then %do; + %mm_getstpcode(tree=&loc,outloc=&outref) +%end; +%else %if &platform=SASVIYA %then %do; + /* extract name & path from &loc */ + data _null_; + loc=symget('loc'); + name=scan(loc,-1,'/'); + shortloc=substr(loc,1,length(loc)-length(name)-1); + call symputx('name',name,'l'); + call symputx('shortloc',shortloc,'l'); + run; + %mv_getjobcode( + path=&shortloc, + name=&name, + outref=&outref + ) +%end; +%else %put &sysmacroname: &platform is unsupported!!!; + +%mend mx_getcode; +/** + @file + @brief Will execute a SASjs web service on SAS 9, Viya or SASjs Server + @details Prepares the input files and retrieves the resulting datasets from + the response JSON. + + Note - the _webout fileref should NOT be assigned prior to running this macro. + + @param [in] program The _PROGRAM endpoint to test + @param [in] inputfiles=(0) A list of space seperated fileref:filename pairs as + follows: + inputfiles=inref:filename inref2:filename2 + @param [in] inputdatasets= (0) All datasets in this space seperated list are + converted into SASJS-formatted CSVs (see mp_ds2csv.sas) files and added to + the list of `inputfiles` for ingestion. The dataset will be sent with the + same name (no need for a colon modifier). + @param [in] inputparams=(0) A dataset containing name/value pairs in the + following format: + |name:$32|value:$1000| + |---|---| + |stpmacname|some value| + |mustbevalidname|can be anything, oops, %abort!!| + + @param [in] debug= (log) Provide the _debug value + @param [in] mdebug= (0) Set to 1 to provide macro debugging + @param [in] viyaresult= (WEBOUT_JSON) The Viya result type to return. For + more info, see mv_getjobresult.sas + @param [in] viyacontext= (SAS Job Execution compute context) The Viya compute + context on which to run the service + @param [out] outlib= (0) Output libref to contain the final tables. Set to + 0 if the service output is not in JSON format. + @param [out] outref= (0) Output fileref to create, to contain the full _webout + response. + +

SAS Macros

+ @li mf_getplatform.sas + @li mf_getuniquefileref.sas + @li mf_getuniquename.sas + @li mp_abort.sas + @li mp_binarycopy.sas + @li mp_chop.sas + @li mp_ds2csv.sas + @li ms_testservice.sas + @li mv_getjobresult.sas + @li mv_jobflow.sas + +

Related Programs

+ @li mx_testservice.test.sas + + @version 9.4 + @author Allan Bowe + +**/ + +%macro mx_testservice(program, + inputfiles=0, + inputdatasets=0, + inputparams=0, + debug=log, + mdebug=0, + outlib=0, + outref=0, + viyaresult=WEBOUT_JSON, + viyacontext=SAS Job Execution compute context +); +%local dbg pcnt fref1 fref2 webref webrefpath i webcount var platform; +%if &mdebug=1 %then %do; + %put &sysmacroname entry vars:; + %put _local_; +%end; +%else %let dbg=*; + +/* sanitise inputparams */ +%let pcnt=0; +%if &inputparams ne 0 %then %do; + data _null_; + set &inputparams; + if not nvalid(name,'v7') then putlog (_all_)(=); + else if name in ( + 'program','inputfiles','inputparams','debug','outlib','outref' + ) then putlog (_all_)(=); + else do; + x+1; + call symputx(name,quote(cats(value)),'l'); + call symputx(cats('pval',x),name,'l'); + call symputx('pcnt',x,'l'); + end; + run; + %mp_abort(iftrue= (%mf_nobs(&inputparams) ne &pcnt) + ,mac=&sysmacroname + ,msg=%str(Invalid values in &inputparams) + ) +%end; + +/* convert inputdatasets to filerefs */ +%if "&inputdatasets" ne "0" %then %do; + %if %quote(&inputfiles)=0 %then %let inputfiles=; + %do i=1 %to %sysfunc(countw(&inputdatasets,%str( ))); + %let var=%scan(&inputdatasets,&i,%str( )); + %local dsref&i; + %let dsref&i=%mf_getuniquefileref(); + %mp_ds2csv(&var,outref=&&dsref&i,headerformat=SASJS) + %let inputfiles=&inputfiles &&dsref&i:%scan(&var,-1,.); + %end; +%end; + +%let platform=%mf_getplatform(); +%let fref1=%mf_getuniquefileref(); +%let fref2=%mf_getuniquefileref(); +%let webref=%mf_getuniquefileref(); +%let webrefpath=%sysfunc(pathname(work))/%mf_getuniquename(); +/* mp_chop requires a physical path as input */ +filename &webref "&webrefpath"; + +%if &platform=SASMETA %then %do; + + /* parse the input files */ + %if %quote(&inputfiles) ne 0 %then %do; + %let webcount=%sysfunc(countw(&inputfiles)); + %put &=webcount; + %do i=1 %to &webcount; + %let var=%scan(&inputfiles,&i,%str( )); + %local webfref&i webname&i; + %let webref&i=%scan(&var,1,%str(:)); + %let webname&i=%scan(&var,2,%str(:)); + %put webref&i=&&webref&i; + %put webname&i=&&webname&i; + %end; + %end; + %else %let webcount=0; + + proc stp program="&program"; + inputparam _program="&program" + %do i=1 %to &webcount; + %if &webcount=1 %then %do; + _webin_fileref="&&webref&i" + _webin_name="&&webname&i" + %end; + %else %do; + _webin_fileref&i="&&webref&i" + _webin_name&i="&&webname&i" + %end; + %end; + _webin_file_count="&webcount" + _debug="&debug" + %do i=1 %to &pcnt; + /* resolve name only, proc stp fetches value */ + &&pval&i=&&&&&&pval&i + %end; + ; + %do i=1 %to &webcount; + inputfile &&webref&i; + %end; + outputfile _webout=&webref; + run; + + data _null_; + infile &webref; + file &fref1; + input; + length line $10000; + if index(_infile_,'>>weboutBEGIN<<') then do; + line=tranwrd(_infile_,'>>weboutBEGIN<<',''); + put line; + end; + else if index(_infile_,'>>weboutEND<<') then do; + line=tranwrd(_infile_,'>>weboutEND<<',''); + put line; + stop; + end; + else put _infile_; + run; + data _null_; + infile &fref1; + input; + put _infile_; + run; + %if &outlib ne 0 %then %do; + libname &outlib json (&fref1); + %end; + %if &outref ne 0 %then %do; + filename &outref temp; + %mp_binarycopy(inref=&webref,outref=&outref) + %end; + +%end; +%else %if &platform=SASVIYA %then %do; + + /* prepare inputparams */ + %local ds1; + %let ds1=%mf_getuniquename(); + %if "&inputparams" ne "0" %then %do; + proc transpose data=&inputparams out=&ds1; + id name; + var value; + run; + %end; + %else %do; + data &ds1;run; + %end; + + /* parse the input files - convert to sasjs params */ + %local webcount i var sasjs_tables; + %if %quote(&inputfiles) ne 0 %then %do; + %let webcount=%sysfunc(countw(&inputfiles)); + %put &=webcount; + %do i=1 %to &webcount; + %let var=%scan(&inputfiles,&i,%str( )); + %local webfref&i webname&i sasjs&i.data; + %let webref&i=%scan(&var,1,%str(:)); + %let webname&i=%scan(&var,2,%str(:)); + %put webref&i=&&webref&i; + %put webname&i=&&webname&i; + + %let sasjs_tables=&sasjs_tables &&webname&i; + data _null_; + infile &&webref&i lrecl=32767; + input; + if _n_=1 then call symputx("sasjs&i.data",_infile_); + else call symputx( + "sasjs&i.data",cats(symget("sasjs&i.data"),'0D0A'x,_infile_) + ); + putlog "&sysmacroname infile: " _infile_; + run; + data &ds1; + set &ds1; + length sasjs&i.data $32767 sasjs_tables $1000; + sasjs&i.data=symget("sasjs&i.data"); + sasjs_tables=symget("sasjs_tables"); + run; + %end; + %end; + %else %let webcount=0; + + data &ds1; + retain _program "&program"; + retain _contextname "&viyacontext"; + set &ds1; + putlog "&sysmacroname inputparams:"; + putlog (_all_)(=); + run; + + %mv_jobflow(inds=&ds1 + ,maxconcurrency=1 + ,outds=work.results + ,outref=&fref1 + ,mdebug=&mdebug + ) + /* show the log */ + data _null_; + infile &fref1; + input; + putlog _infile_; + run; + /* get the uri to fetch results */ + data _null_; + set work.results; + call symputx('uri',uri); + putlog "&sysmacroname: fetching results for " uri; + run; + /* fetch results from webout.json */ + %mv_getjobresult(uri=&uri, + result=&viyaresult, + outref=&outref, + outlib=&outlib, + mdebug=&mdebug + ) + +%end; +%else %if &platform=SASJS %then %do; + + %ms_testservice(&program + ,inputfiles=&inputfiles + ,inputdatasets=&inputdatasets + ,inputparams=&inputparams + ,debug=&debug + ,mdebug=&mdebug + ,outlib=&outlib + ,outref=&outref + ) + +%end; +%else %do; + %put %str(ERR)OR: Unrecognised platform: &platform; +%end; + +%if &mdebug=0 %then %do; + filename &fref1 clear; + %if &platform ne SASJS %then %do; + filename &fref2 clear; + filename &webref clear; + %end; +%end; +%else %do; + %put &sysmacroname exit vars:; + %put _local_; +%end; + +%mend mx_testservice; diff --git a/base/mp_coretable.sas b/base/mp_coretable.sas index 57e9c78..09d2a38 100644 --- a/base/mp_coretable.sas +++ b/base/mp_coretable.sas @@ -30,6 +30,7 @@ @li mddl_dc_filtersummary.sas @li mddl_dc_locktable.sas @li mddl_dc_maxkeytable.sas + @li mf_getuniquename.sas

Related Macros

@li mp_filterstore.sas @@ -46,7 +47,7 @@ %macro mp_coretable(table_ref,libds=0 )/*/STORE SOURCE*/; %local outds ; -%let outds=%sysfunc(ifc(&libds=0,_data_,&libds)); +%let outds=%sysfunc(ifc(&libds=0,%mf_getuniquename(),&libds)); proc sql; %if &table_ref=DIFFTABLE %then %do; %mddl_dc_difftable(libds=&outds) diff --git a/sasjs/sasjsconfig.json b/sasjs/sasjsconfig.json index b75b68d..6bde89a 100644 --- a/sasjs/sasjsconfig.json +++ b/sasjs/sasjsconfig.json @@ -6,8 +6,10 @@ "fcmp", "lua", "server", - "tests/crossplatform", - "tests/ddl" + "xplatform", + "tests/base", + "tests/ddl", + "tests/xplatform" ], "docConfig": { "displayMacroCore": false, diff --git a/tests/xplatform/mx_getcode.test.sas b/tests/xplatform/mx_getcode.test.sas index 7e4cae2..adfd9f4 100644 --- a/tests/xplatform/mx_getcode.test.sas +++ b/tests/xplatform/mx_getcode.test.sas @@ -27,7 +27,7 @@ parmcards4; ;;;; %mx_createwebservice(path=&mcTestAppLoc/temp,name=&item) -%mx_getcode(&mcTestAppLoc/temp/&item,testref1) +%mx_getcode(&mcTestAppLoc/temp/&item,outref=testref1) %inc testref1/lrecl=1000; diff --git a/xplatform/mx_getcode.sas b/xplatform/mx_getcode.sas index ee689a6..3497c59 100644 --- a/xplatform/mx_getcode.sas +++ b/xplatform/mx_getcode.sas @@ -17,9 +17,9 @@

SAS Macros

@li mf_getplatform.sas - @li mf_getuniquename.sas @li mm_getstpcode.sas @li ms_getfile.sas + @li mv_getjobcode.sas @author Allan Bowe