1
0
mirror of https://github.com/sasjs/core.git synced 2026-06-09 12:10:22 +00:00

Compare commits

...

31 Commits

Author SHA1 Message Date
Allan Bowe f484d10913 Merge pull request #427 from sasjs/jobflowfix
Jobflowfix
2026-05-14 17:30:59 +01:00
github-actions 70efaf84e1 chore: updating all.sas 2026-05-14 16:29:48 +00:00
4gl 6c6c45b85c fix: issue with running jobs in viya2026 (all params must be strings) 2026-05-14 17:29:26 +01:00
Allan Bowe 5453b76fe6 Merge pull request #426 from sasjs/mx_append2pgm
Mx append2pgm
2026-05-14 15:08:31 +01:00
github-actions c8e1126a40 chore: updating all.sas 2026-05-14 14:02:39 +00:00
4gl 872353dc8d feat: new mx_append2pgm macro 2026-05-14 15:02:14 +01:00
Allan Bowe 9b44875142 fix: Merge pull request #425 from sasjs/allbump
fix: updating all.sas and mv_webout
2026-05-13 14:21:00 +01:00
github-actions c5a681e6ed chore: updating all.sas 2026-05-13 13:19:41 +00:00
4gl a759aa9915 fix: using 128 instead of 131 in _debug due to compute task bug 2026-05-13 14:18:47 +01:00
Allan Bowe 1244aff5e4 Merge pull request #424 from sasjs/exectask
Exectask
2026-05-13 14:06:38 +01:00
github-actions 4934e6675e chore: updating all.sas 2026-05-13 13:04:37 +00:00
4gl 5f5fb0116a fix: adding weboutBEGIN/END when exectask=true 2026-05-13 14:04:13 +01:00
Allan Bowe 9a725b9770 Merge pull request #423 from sasjs/CS0409737
Cs0409737
2026-05-13 09:59:47 +01:00
github-actions 6c77556fdb chore: updating all.sas 2026-05-13 08:57:58 +00:00
4gl 0e37bff1ee fix: workaround for sas track CS0409737 2026-05-13 09:57:33 +01:00
Allan Bowe bb6aced478 Merge pull request #422 from sasjs/exectasks
Exectasks
2026-05-12 14:03:31 +01:00
github-actions 96d42b9f66 chore: updating all.sas 2026-05-12 13:02:35 +00:00
4gl 59f8303b19 chore: ensuring mv_createwebservice is rebuilt on mv_webout change 2026-05-12 14:01:38 +01:00
github-actions 0599c4d597 chore: updating all.sas 2026-05-12 12:43:06 +00:00
4gl 356d3644e5 feat: support for Viya Compute Tasks 2026-05-12 13:42:37 +01:00
4gl ef7e8e051f chore: updating tests around mv_createfolder 2026-05-12 13:25:36 +01:00
4gl aa35317126 fix: doc header invocation for sidebar 2026-05-01 17:14:31 +01:00
4gl f474076a41 fix: doc site html side bar 2026-05-01 16:55:48 +01:00
4gl 98bd198dfc fix: adding maintainers attribute to package json (not a real fix, just triggering a build) 2026-05-01 15:38:13 +01:00
4gl 15e3a560b0 chore: docs build script fix 2026-05-01 15:33:10 +01:00
Allan Bowe 7448252b22 fix: use PAT for pushing docs to another repo 2026-05-01 11:15:16 +01:00
Allan Bowe 1fb52d5f73 fix: installing doxygen in pipeline 2026-05-01 09:21:26 +00:00
Allan Bowe 0c90ac8deb feat: auto-deploy docs to core.sasjs.io 2026-05-01 09:19:10 +00:00
Allan Bowe fdf0a1b514 Merge pull request #421 from sasjs/mv_getviyafileextparams
Mv getviyafileextparams
2026-04-29 12:59:00 +01:00
github-actions 4d15f4ebf5 chore: updating all.sas 2026-04-29 11:50:49 +00:00
4gl 402337a952 fix: avoid strange error when running mv_getviyafileextparams in Studio 2026-04-29 12:50:03 +01:00
20 changed files with 801 additions and 156 deletions
+25
View File
@@ -54,6 +54,7 @@ jobs:
echo "REFRESH_TOKEN=${{secrets.SAS9_4GL_IO_REFRESH_TOKEN}}" >> .env.server echo "REFRESH_TOKEN=${{secrets.SAS9_4GL_IO_REFRESH_TOKEN}}" >> .env.server
- name: Semantic Release - name: Semantic Release
id: makerelease
uses: cycjimmy/semantic-release-action@v6 uses: cycjimmy/semantic-release-action@v6
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -64,3 +65,27 @@ jobs:
npx @sasjs/cli compile job -s sasjs/utils/create_sas_package.sas -o sasjsbuild -t server npx @sasjs/cli compile job -s sasjs/utils/create_sas_package.sas -o sasjsbuild -t server
# need long duration token per https://github.com/sasjs/server/issues/307 # need long duration token per https://github.com/sasjs/server/issues/307
# npx @sasjs/cli run sasjsbuild/jobs/utils/create_sas_package.sas -t server # npx @sasjs/cli run sasjsbuild/jobs/utils/create_sas_package.sas -t server
- name: Update Docs Site
if: steps.makerelease.outputs.new_release_published == 'true'
run: |
sudo apt-get update
sudo apt-get install -y doxygen
npx @sasjs/cli doc -t docsonly
git clone https://x-access-token:${{ secrets.CORESASJSIO_PAT }}@github.com/sasjs/core.github.io.git
cd core.github.io
rm -rf *.html
rm -rf *.js
rm -rf *.png
rm -rf *.dot
rm -rf *.css
rm -rf *.svg
rm -rf search
cp -R ../sasjsbuild/docs/* .
ls
git config user.name sasjs
echo 'core.sasjs.io' > CNAME
git add .
git commit -m "core pipeline build on $(date +%F:%H:%M:%S)"
git push
echo "check it out: https://sasjs.github.io/core.github.io/files.html"
+1
View File
@@ -26,6 +26,7 @@ jobs:
git config user.email github-actions@github.com git config user.email github-actions@github.com
python3 build.py python3 build.py
git add all.sas git add all.sas
git add viya/mv_createwebservice.sas
git commit -m "chore: updating all.sas" --allow-empty git commit -m "chore: updating all.sas" --allow-empty
git push git push
-2
View File
@@ -5,8 +5,6 @@
![npm](https://img.shields.io/npm/dt/@sasjs/core) ![npm](https://img.shields.io/npm/dt/@sasjs/core)
![GitHub top language](https://img.shields.io/github/languages/top/sasjs/core) ![GitHub top language](https://img.shields.io/github/languages/top/sasjs/core)
[![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/sasjs/core)](https://github.com/sasjs/core/issues?q=is%3Aissue+is%3Aclosed) [![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/sasjs/core)](https://github.com/sasjs/core/issues?q=is%3Aissue+is%3Aclosed)
[![GitHub issues](https://img.shields.io/github/issues-raw/sasjs/core)](https://github.com/sasjs/core/issues)
![total lines](https://tokei.rs/b1/github/sasjs/core)
Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of [Application Development](https://sasapps.io) on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/.github/CONTRIBUTING.md) are welcome. Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of [Application Development](https://sasapps.io) on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/.github/CONTRIBUTING.md) are welcome.
+263 -64
View File
@@ -25014,9 +25014,10 @@ run;
/* Get Viya file-extension details into some macro variables */ /* Get Viya file-extension details into some macro variables */
%mv_getViyaFileExtParms(&ext %mv_getViyaFileExtParms(&ext
,propertiesVar=viyaProperties ,propertiesVar=viyaProperties
,typeDefNameVar=viyaTypeDefName ,typeDefNameVar=viyaTypeDefName
,mdebug=&mdebug); ,mdebug=&mdebug
)
/* fetch job info */ /* fetch job info */
%local fname1; %local fname1;
@@ -25084,9 +25085,9 @@ run;
/* If properties were found then patch the file to include them */ /* If properties were found then patch the file to include them */
%if not %mf_isBlank(%superq(viyaProperties)) %then %do; %if not %mf_isBlank(%superq(viyaProperties)) %then %do;
/* Wrap the properties object in a root object also containing the file name */ /* Wrap the properties object in a root object also containing the filename */
%local viyapatch; %local viyapatch;
%let viyapatch = %sysfunc(pathname(work))/%mf_getuniquename(prefix=patch_json_); %let viyapatch=%sysfunc(pathname(work))/%mf_getuniquename(prefix=patch_json_);
data _null_; data _null_;
length line $32767; length line $32767;
file "&viyapatch" lrecl=32767; file "&viyapatch" lrecl=32767;
@@ -25106,7 +25107,7 @@ run;
run; run;
%end; %end;
/* And apply the properties to the newly created file, using the PATCH method */ /* Apply the properties to the newly created file, using the PATCH method */
%let fref=%mf_getuniquefileref(); %let fref=%mf_getuniquefileref();
filename &fref "&viyapatch"; filename &fref "&viyapatch";
%let url=&base_uri&fileuri; %let url=&base_uri&fileuri;
@@ -25290,7 +25291,6 @@ options noquotelenmax;
run; run;
%end; %end;
%if &SYS_PROCHTTP_STATUS_CODE=200 %then %do; %if &SYS_PROCHTTP_STATUS_CODE=200 %then %do;
%*put &sysmacroname &newpath exists so grab the follow on link ;
data _null_; data _null_;
set &libref1..links; set &libref1..links;
if rel='createChild' then if rel='createChild' then
@@ -26311,14 +26311,14 @@ data _null_;
put ' ,showmeta=N,maxobs=MAX,workobs=0 '; put ' ,showmeta=N,maxobs=MAX,workobs=0 ';
put '); '; put '); ';
put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name '; put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name ';
put ' sasjs_tables SYS_JES_JOB_URI; '; put ' sasjs_tables SYS_JES_JOB_URI _EXECUTIONTASKS; ';
put '%if %index("&_debug",log) %then %let _debug=131; '; put '%if %index("&_debug",log) %then %let _debug=128; ';
put ' '; put ' ';
put '%local i tempds table; '; put '%local i tempds table; ';
put '%let action=%upcase(&action); '; put '%let action=%upcase(&action); ';
put ' '; put ' ';
put '%if &action=FETCH %then %do; '; put '%if &action=FETCH %then %do; ';
put ' %if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 131 %then %do; '; put ' %if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 128 %then %do; ';
put ' options mprint notes mprintnest; '; put ' options mprint notes mprintnest; ';
put ' %end; '; put ' %end; ';
put ' '; put ' ';
@@ -26326,6 +26326,11 @@ data _null_;
put ' %let _webin_file_count=%eval(&_webin_file_count+0); '; put ' %let _webin_file_count=%eval(&_webin_file_count+0); ';
put ' %let _webin_fileuri1=&_webin_fileuri; '; put ' %let _webin_fileuri1=&_webin_fileuri; ';
put ' %let _webin_name1=&_webin_name; '; put ' %let _webin_name1=&_webin_name; ';
put ' %if &_EXECUTIONTASKS=true %then %do; ';
put ' /* TODO - remove this once SAS Track CS0409737 is resolved */ ';
put ' /* links: https://github.com/sasjs/adapter/issues/884 */ ';
put ' %if %upcase(&_webin_name)=_SASJS_NOOP %then %let _webin_file_count=0; ';
put ' %end; ';
put ' %end; '; put ' %end; ';
put ' '; put ' ';
put ' /* if the sasjs_tables param is passed, we expect param based upload */ '; put ' /* if the sasjs_tables param is passed, we expect param based upload */ ';
@@ -26366,13 +26371,17 @@ data _null_;
put ' %end; '; put ' %end; ';
put ' %else %do i=1 %to &_webin_file_count; '; put ' %else %do i=1 %to &_webin_file_count; ';
put ' /* read in any files that are sent */ '; put ' /* read in any files that are sent */ ';
put ' /* this part needs refactoring for wide files */ '; put ' %if &_EXECUTIONTASKS=true %then %do; ';
put ' filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999; '; put ' filename indata "%sysfunc(pathname(&&_webin_fileref&i))" lrecl=999999; ';
put ' %end; ';
put ' %else %do; ';
put ' filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999; ';
put ' %end; ';
put ' data _null_; '; put ' data _null_; ';
put ' infile indata termstr=crlf lrecl=32767; '; put ' infile indata termstr=crlf lrecl=32767; ';
put ' input; '; put ' input; ';
put ' if _n_=1 then call symputx(''input_statement'',_infile_); '; put ' if _n_=1 then call symputx(''input_statement'',_infile_); ';
put ' %if %str(&_debug) ge 131 %then %do; '; put ' %if %str(&_debug) ge 128 %then %do; ';
put ' if _n_<20 then putlog _infile_; '; put ' if _n_<20 then putlog _infile_; ';
put ' else stop; '; put ' else stop; ';
put ' %end; '; put ' %end; ';
@@ -26405,6 +26414,9 @@ data _null_;
put ' '; put ' ';
put ' /* setup json */ '; put ' /* setup json */ ';
put ' data _null_;file &fref; '; put ' data _null_;file &fref; ';
put ' %if %str(&_debug) ge 128 and &_EXECUTIONTASKS=true %then %do; ';
put ' put ''>>weboutBEGIN<<''; ';
put ' %end; ';
put ' put ''{"SYSDATE" : "'' "&SYSDATE" ''"''; '; put ' put ''{"SYSDATE" : "'' "&SYSDATE" ''"''; ';
put ' put '',"SYSTIME" : "'' "&SYSTIME" ''"''; '; put ' put '',"SYSTIME" : "'' "&SYSTIME" ''"''; ';
put ' run; '; put ' run; ';
@@ -26517,7 +26529,9 @@ data _null_;
put ' memsize=quote(cats(memsize)); '; put ' memsize=quote(cats(memsize)); ';
put ' put '',"MEMSIZE" : '' memsize; '; put ' put '',"MEMSIZE" : '' memsize; ';
put ' put "}"; '; put ' put "}"; ';
put ' '; put ' %if %str(&_debug) ge 128 and &_EXECUTIONTASKS=true %then %do; ';
put ' put ''>>weboutEND<<''; ';
put ' %end; ';
put ' %if %upcase(&fref) ne _WEBOUT and &stream=Y %then %do; '; put ' %if %upcase(&fref) ne _WEBOUT and &stream=Y %then %do; ';
put ' data _null_; rc=fcopy("&fref","_webout");run; '; put ' data _null_; rc=fcopy("&fref","_webout");run; ';
put ' %end; '; put ' %end; ';
@@ -28727,6 +28741,7 @@ libname &libref1 clear;
@li mf_existds.sas @li mf_existds.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvalue.sas @li mf_getvalue.sas
@li mf_getvarlist.sas @li mf_getvarlist.sas
@@ -28752,7 +28767,7 @@ libname &libref1 clear;
iftrue=(%mf_isBlank(&ext)) iftrue=(%mf_isBlank(&ext))
,msg=%str(No file extension provided.) ,msg=%str(No file extension provided.)
,mac=MV_GETVIYAFILEEXTPARMS ,mac=MV_GETVIYAFILEEXTPARMS
); )
%mp_abort( %mp_abort(
iftrue=(%mf_isBlank(&typeDefNameVar) and iftrue=(%mf_isBlank(&typeDefNameVar) and
@@ -28760,13 +28775,13 @@ libname &libref1 clear;
%mf_isBlank(&mediaTypeVar)) %mf_isBlank(&mediaTypeVar))
,msg=%str(MV_GETVIYAFILEEXTPARMS - No parameter was requested.) ,msg=%str(MV_GETVIYAFILEEXTPARMS - No parameter was requested.)
,mac=MV_GETVIYAFILEEXTPARMS ,mac=MV_GETVIYAFILEEXTPARMS
); )
%mp_abort( %mp_abort(
iftrue=(%mf_isBlank(&viyaFileExtRespLibDs)) iftrue=(%mf_isBlank(&viyaFileExtRespLibDs))
,msg=%str(No <libname.>dataset name provided to cache inital response.) ,msg=%str(No <libname.>dataset name provided to cache inital response.)
,mac=MV_GETVIYAFILEEXTPARMS ,mac=MV_GETVIYAFILEEXTPARMS
); )
/* Declare requested parameters as global macro vars and initialize blank */ /* Declare requested parameters as global macro vars and initialize blank */
%if not %mf_isBlank(&typeDefNameVar) %then %do; %if not %mf_isBlank(&typeDefNameVar) %then %do;
@@ -28783,9 +28798,7 @@ libname &libref1 clear;
%end; %end;
%let base_uri=%mf_getplatform(VIYARESTAPI); %let base_uri=%mf_getplatform(VIYARESTAPI);
%if &mdebug=1 %then %do; %if &mdebug=1 %then %put DEBUG: &=base_uri;
%put DEBUG: &=base_uri;
%end;
%let ext=%lowcase(&ext); %let ext=%lowcase(&ext);
@@ -28809,7 +28822,7 @@ libname &libref1 clear;
%if (&SYS_PROCHTTP_STATUS_CODE ne 200) %then %do; %if (&SYS_PROCHTTP_STATUS_CODE ne 200) %then %do;
/* To avoid a breaking change, exit early if the request failed. /* To avoid a breaking change, exit early if the request failed.
The calling process will proceed with empty requested macro variables. */ The calling process will proceed with empty macro variables. */
%put INFO: &sysmacroname File extension details were not retrieved.; %put INFO: &sysmacroname File extension details were not retrieved.;
filename &viyatypedefs clear; filename &viyatypedefs clear;
%return; %return;
@@ -28830,11 +28843,12 @@ libname &libref1 clear;
/* Convert the content of that JSON into SAS datasets */ /* Convert the content of that JSON into SAS datasets */
/* First prepare a new WORK-based folder to receive the datasets */ /* First prepare a new WORK-based folder to receive the datasets */
%local jsonworkfolder jsonlib opt_dlcreatedir; %local jsonworkfolder jsonlib opt_dlcreatedir;
%let jsonworkfolder=%sysfunc(pathname(work))/%mf_getuniquename(prefix=json_); %let jsonworkfolder=%sysfunc(pathname(work))/%mf_getuniquename(prefix=jsn_);
%let jsonlib=%mf_getuniquelibref(prefix=json); %let jsonlib=%mf_getuniquelibref(prefix=json);
/* And point a libname at it */ /* And point a libname at it */
%let opt_dlcreatedir = %sysfunc(getoption(dlcreatedir)); %let opt_dlcreatedir = %sysfunc(getoption(dlcreatedir));
options dlcreatedir; libname &jsonlib "&jsonworkfolder"; options &opt_dlcreatedir; options dlcreatedir; libname &jsonlib "&jsonworkfolder";
options &opt_dlcreatedir;
/* Read the json output once and copy datasets to its work folder */ /* Read the json output once and copy datasets to its work folder */
%local libref1; %local libref1;
@@ -28863,20 +28877,22 @@ libname &libref1 clear;
%end; /* If initial filetype query response didn't exist */ %end; /* If initial filetype query response didn't exist */
/* Find the row-group for the current file extension */ %if &mdebug %then %put DEBUG: Find the row-group for extension &ext;
%local itemRowGroup; %local itemRowGroup;
%let itemRowGroup = data _null_;
%mf_getValue( set &viyaFileExtRespLibDs;
&viyaFileExtRespLibDs where p1='items' and p2='extensions' and value="&ext";
,_viyaItemIdx call symputx('itemRowGroup',_viyaItemIdx,'l');
,filter=%quote(p1='items' and p2='extensions' and value="&ext") %if &mdebug %then %do;
); putlog (_all_)(=);
%end;
run;
%if &mdebug %then %put DEBUG: &=itemRowGroup; %if &mdebug %then %put DEBUG: &=itemRowGroup;
%if %mf_isBlank(&itemRowGroup) %then %do; %if %mf_isBlank(&itemRowGroup) %then %do;
/* extension was not found */ /* extension was not found */
%if(&mdebug=1) %then %put DEBUG: No type details found for extension "&ext".; %if &mdebug %then %put DEBUG: No type details found for extension "&ext";
%return; %return;
%end; %end;
@@ -28890,14 +28906,17 @@ libname &libref1 clear;
/* Populate typeDefName, if requested */ /* Populate typeDefName, if requested */
%if (not %mf_isBlank(&typeDefNameVar)) %then %do; %if (not %mf_isBlank(&typeDefNameVar)) %then %do;
%let &typeDefNameVar = %mf_getvalue(&dsItems,value,filter=%quote(p1="items" and p2="name")); %let &typeDefNameVar = %mf_getvalue(
%if &mdebug=1 %then %put DEBUG: &=typeDefNameVar &typeDefNameVar=&&&typeDefNameVar; &dsItems,value,filter=%quote(p1="items" and p2="name"));
%if &mdebug %then
%put DEBUG: &=typeDefNameVar &typeDefNameVar=&&&typeDefNameVar;
%end; %end;
/* Populate mediaType, if requested */ /* Populate mediaType, if requested */
%if (not %mf_isBlank(&mediaTypeVar)) %then %do; %if (not %mf_isBlank(&mediaTypeVar)) %then %do;
%let &mediaTypeVar = %mf_getvalue(&dsItems,value,filter=%quote(p1="items" and p2="mediaType")); %let &mediaTypeVar = %mf_getvalue(
%if &mdebug=1 %then %put DEBUG: &=mediaTypeVar &mediaTypeVar=&&&mediaTypeVar; &dsItems,value,filter=%quote(p1="items" and p2="mediaType"));
%if &mdebug %then %put DEBUG: &=mediaTypeVar &mediaTypeVar=&&&mediaTypeVar;
%end; %end;
/* Populate properties macro variable, if requested */ /* Populate properties macro variable, if requested */
@@ -28914,7 +28933,8 @@ libname &libref1 clear;
/* Check for 1+ properties */ /* Check for 1+ properties */
%if ( %mf_nobs(&dsProperties) = 0 ) %then %do; %if ( %mf_nobs(&dsProperties) = 0 ) %then %do;
%let &propertiesVar = %str(); %let &propertiesVar = %str();
%if &mdebug=1 %then %put DEBUG: &SYSMACRONAME - No Viya properties found for file suffix %str(%')&ext%str(%'); %if &mdebug %then %put DEBUG: &SYSMACRONAME - No Viya properties %trim(
)found for file suffix %str(%')&ext%str(%');
%end; %end;
%else %do; %else %do;
/* Properties potentially span multiple rows in the input table */ /* Properties potentially span multiple rows in the input table */
@@ -28944,7 +28964,8 @@ libname &libref1 clear;
end; end;
run; run;
%if &mdebug=1 %then %put DEBUG: &=propertiesVar &propertiesVar=&&&propertiesVar; %if &mdebug %then
%put DEBUG: &=propertiesVar &propertiesVar=&&&propertiesVar;
%end; %end;
%end; %end;
@@ -29260,7 +29281,7 @@ run;
@li mf_nobs.sas @li mf_nobs.sas
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getvarlist.sas
@li mf_existvarlist.sas @li mf_existvarlist.sas
@li mv_jobwaitfor.sas @li mv_jobwaitfor.sas
@li mv_jobexecute.sas @li mv_jobexecute.sas
@@ -29373,14 +29394,12 @@ data _null_;
if last then call symputx('flowcnt',cnt,'l'); if last then call symputx('flowcnt',cnt,'l');
run; run;
/* prepare temporary datasets and frefs */ /* prepare temporary datasets */
%local fid jid jds jjson jdsapp jdsrunning jdswaitfor jfref; %local fid jid jds jdsapp jdsrunning jdswaitfor;
data;run;%let jds=&syslast; data;run;%let jds=&syslast;
data;run;%let jjson=&syslast;
data;run;%let jdsapp=&syslast; data;run;%let jdsapp=&syslast;
data;run;%let jdsrunning=&syslast; data;run;%let jdsrunning=&syslast;
data;run;%let jdswaitfor=&syslast; data;run;%let jdswaitfor=&syslast;
%let jfref=%mf_getuniquefileref();
/* start loop */ /* start loop */
%do fid=1 %to &flowcnt; %do fid=1 %to &flowcnt;
@@ -29398,23 +29417,39 @@ data;run;%let jdswaitfor=&syslast;
&dbg. if _n_= 1 then putlog "Loop &fid"; &dbg. if _n_= 1 then putlog "Loop &fid";
&dbg. putlog (_all_)(=); &dbg. putlog (_all_)(=);
run; run;
/* build list of char and num vars in json format */
/* Viya 2026 expects all values to be strings */
%local nvars cvars ii _vnm;
%let cvars=%mf_getvarlist(&jds,typefilter=C);
%let nvars=%mf_getvarlist(&jds,typefilter=N);
%put exporting job variables in json format; %put exporting job variables in json format;
%do jid=1 %to &jcnt; %do jid=1 %to &jcnt;
data &jjson;
set &jds;
if _n_=&jid then do;
output;
stop;
end;
run;
proc json out=&jfref;
export &jjson / nosastags fmtnumeric;
run;
data _null_; data _null_;
infile &jfref lrecl=32767; set &jds;
input; if _n_=&jid;
jparams=cats('jparams',symget('jid')); length _param $32767;
call symputx(jparams,substr(_infile_,3,length(_infile_)-4)); _param='';
%if %length(&cvars)>0 %then %do ii=1 %to %sysfunc(countw(&cvars,%str( )));
%let _vnm=%scan(&cvars,&ii,%str( ));
if _param ne '' then _param=cats(_param,',');
_param=cats(_param,'"'
,"%lowcase(&_vnm)"
,'":'
,quote(trim(&_vnm))
);
%end;
%if %length(&nvars)>0 %then %do ii=1 %to %sysfunc(countw(&nvars,%str( )));
%let _vnm=%scan(&nvars,&ii,%str( ));
if _param ne '' then _param=cats(_param,',');
_param=cats(_param,'"'
,"%lowcase(&_vnm)"
,'":"'
,strip(put(&_vnm,best32.))
,'"'
);
%end;
call symputx(cats('jparams',&jid),_param,'l');
stop;
run; run;
%local jobuid&jid; %local jobuid&jid;
%let jobuid&jid=0; /* used in next loop */ %let jobuid&jid=0; /* used in next loop */
@@ -29459,6 +29494,7 @@ data;run;%let jdswaitfor=&syslast;
,paramstring=%superq(jparams&jid) ,paramstring=%superq(jparams&jid)
,outds=&jdsapp ,outds=&jdsapp
,contextname=&&context&jid ,contextname=&&context&jid
,mdebug=&mdebug
) )
data &jdsapp; data &jdsapp;
format jobparams $32767.; format jobparams $32767.;
@@ -30421,14 +30457,14 @@ filename &fref1 clear;
,showmeta=N,maxobs=MAX,workobs=0 ,showmeta=N,maxobs=MAX,workobs=0
); );
%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name %global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name
sasjs_tables SYS_JES_JOB_URI; sasjs_tables SYS_JES_JOB_URI _EXECUTIONTASKS;
%if %index("&_debug",log) %then %let _debug=131; %if %index("&_debug",log) %then %let _debug=128;
%local i tempds table; %local i tempds table;
%let action=%upcase(&action); %let action=%upcase(&action);
%if &action=FETCH %then %do; %if &action=FETCH %then %do;
%if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 131 %then %do; %if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 128 %then %do;
options mprint notes mprintnest; options mprint notes mprintnest;
%end; %end;
@@ -30436,6 +30472,11 @@ filename &fref1 clear;
%let _webin_file_count=%eval(&_webin_file_count+0); %let _webin_file_count=%eval(&_webin_file_count+0);
%let _webin_fileuri1=&_webin_fileuri; %let _webin_fileuri1=&_webin_fileuri;
%let _webin_name1=&_webin_name; %let _webin_name1=&_webin_name;
%if &_EXECUTIONTASKS=true %then %do;
/* TODO - remove this once SAS Track CS0409737 is resolved */
/* links: https://github.com/sasjs/adapter/issues/884 */
%if %upcase(&_webin_name)=_SASJS_NOOP %then %let _webin_file_count=0;
%end;
%end; %end;
/* if the sasjs_tables param is passed, we expect param based upload */ /* if the sasjs_tables param is passed, we expect param based upload */
@@ -30476,13 +30517,17 @@ filename &fref1 clear;
%end; %end;
%else %do i=1 %to &_webin_file_count; %else %do i=1 %to &_webin_file_count;
/* read in any files that are sent */ /* read in any files that are sent */
/* this part needs refactoring for wide files */ %if &_EXECUTIONTASKS=true %then %do;
filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999; filename indata "%sysfunc(pathname(&&_webin_fileref&i))" lrecl=999999;
%end;
%else %do;
filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999;
%end;
data _null_; data _null_;
infile indata termstr=crlf lrecl=32767; infile indata termstr=crlf lrecl=32767;
input; input;
if _n_=1 then call symputx('input_statement',_infile_); if _n_=1 then call symputx('input_statement',_infile_);
%if %str(&_debug) ge 131 %then %do; %if %str(&_debug) ge 128 %then %do;
if _n_<20 then putlog _infile_; if _n_<20 then putlog _infile_;
else stop; else stop;
%end; %end;
@@ -30515,6 +30560,9 @@ filename &fref1 clear;
/* setup json */ /* setup json */
data _null_;file &fref; data _null_;file &fref;
%if %str(&_debug) ge 128 and &_EXECUTIONTASKS=true %then %do;
put '>>weboutBEGIN<<';
%end;
put '{"SYSDATE" : "' "&SYSDATE" '"'; put '{"SYSDATE" : "' "&SYSDATE" '"';
put ',"SYSTIME" : "' "&SYSTIME" '"'; put ',"SYSTIME" : "' "&SYSTIME" '"';
run; run;
@@ -30627,7 +30675,9 @@ filename &fref1 clear;
memsize=quote(cats(memsize)); memsize=quote(cats(memsize));
put ',"MEMSIZE" : ' memsize; put ',"MEMSIZE" : ' memsize;
put "}"; put "}";
%if %str(&_debug) ge 128 and &_EXECUTIONTASKS=true %then %do;
put '>>weboutEND<<';
%end;
%if %upcase(&fref) ne _WEBOUT and &stream=Y %then %do; %if %upcase(&fref) ne _WEBOUT and &stream=Y %then %do;
data _null_; rc=fcopy("&fref","_webout");run; data _null_; rc=fcopy("&fref","_webout");run;
%end; %end;
@@ -31434,6 +31484,155 @@ endsub;
%end; %end;
%mend mcf_string2file;/** %mend mcf_string2file;/**
@file
@brief Appends a text file to a SASjs Stored Program, Viya SAS program, or
SAS 9 Stored Process
@details Extracts the source code from a SASjs Stored Program, Viya SAS
program (file in SAS Drive), or SAS 9 Stored Process, appends the contents
of a provided text file, then deletes and recreates the target item with the
combined content.
This is useful for dynamically modifying deployed programs, for example to
add test-specific configuration or runtime settings.
Usage:
%* compile macros ;
filename mc url
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
%* write some content to append;
filename append temp;
data _null_;
file append;
put "libname mylib '/some/path';";
run;
%* append to existing program;
%mx_append2pgm(/Public/app/common/settings, inref=append)
@param [in] loc The full path to the Viya SAS program, SAS 9 Stored Process,
or SASjs Stored Program in Drive or Metadata, WITHOUT the .sas extension
(SASjs only)
@param [in] inref= (0) Fileref pointing to the content to be appended to the
target program.
@param [in] mdebug= (0) Set to 1 to show debug messages in the log
<h4> SAS Macros </h4>
@li mf_getplatform.sas
@li mf_getuniquefileref.sas
@li mm_createstp.sas
@li mm_deletestp.sas
@li mm_getstpcode.sas
@li ms_createfile.sas
@li ms_deletefile.sas
@li mv_createfile.sas
@li mv_deletefoldermember.sas
@li mx_getcode.sas
<h4> Related Macros </h4>
@li mx_append2pgm.test.sas
@li mx_getcode.sas
@li mx_createjob.sas
@author Allan Bowe
**/
%macro mx_append2pgm(loc
,inref=0
,mdebug=0
)/*/STORE SOURCE*/;
%local platform name shortloc coderef combref work tmpfile viyaref;
%let platform=%mf_getplatform();
%if &mdebug=1 %then %do;
%put &sysmacroname entry vars:;
%put _local_;
%end;
%if &syscc ne 0 %then %do;
%put syscc=&syscc - &sysmacroname will not execute in this state;
%return;
%end;
/* extract name & path from loc */
data _null_;
length name shortloc $500;
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;
/* create a combined fileref with original + appended content */
%let combref=%mf_getuniquefileref();
%let work=%sysfunc(pathname(work));
%let tmpfile=&combref..sas;
filename &combref "&work/&tmpfile" lrecl=32000;
%if &platform=SASVIYA %then %do;
/* On Viya, read the SAS program file from SAS Drive using filesrvc */
%let viyaref=%mf_getuniquefileref();
filename &viyaref filesrvc folderpath="&shortloc";
data _null_;
file &combref lrecl=32000 termstr=crlf;
infile &viyaref("&name..sas") lrecl=32000 end=last;
input;
put _infile_;
run;
filename &viyaref clear;
%symdel _FILESRVC_&viyaref._URI;
%end;
%else %do;
/* For SAS9 and SASJS, use mx_getcode */
%let coderef=%mf_getuniquefileref();
%mx_getcode(&loc, outref=&coderef)
data _null_;
file &combref lrecl=32000 termstr=crlf;
infile &coderef lrecl=32000 end=last;
input;
put _infile_;
run;
filename &coderef clear;
%end;
/* append the new content */
data _null_;
file &combref lrecl=32000 termstr=crlf mod;
infile &inref lrecl=32000;
input;
put _infile_;
run;
/* delete and recreate the target item */
%if &platform=SASJS %then %do;
%ms_deletefile(&loc..sas)
%ms_createfile(&loc..sas, inref=&combref, mdebug=&mdebug)
%end;
%else %if &platform=SASVIYA %then %do;
%mv_deletefoldermember(path=&shortloc, name=&name..sas, contenttype=file)
%mv_createfile(path=&shortloc, name=&name..sas, inref=&combref)
%end;
%else %do;
/* SAS 9 */
%mm_deletestp(target=&loc)
%mm_createstp(stpname=&name
,filename=&tmpfile
,directory=&work
,tree=&shortloc
,stptype=2
,mDebug=&mdebug
,minify=NO
)
%end;
filename &combref clear;
%mend mx_append2pgm;
/**
@file mx_createjob.sas @file mx_createjob.sas
@brief Create a job in SAS 9, Viya or SASjs @brief Create a job in SAS 9, Viya or SASjs
@details Creates a Stored Process in SAS 9, a Job Execution Service in SAS @details Creates a Stored Process in SAS 9, a Job Execution Service in SAS
+4 -1
View File
@@ -31,5 +31,8 @@
"test": "npx @sasjs/cli test -t server", "test": "npx @sasjs/cli test -t server",
"lint": "npx @sasjs/cli lint", "lint": "npx @sasjs/cli lint",
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true" "prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
} },
"maintainers": [
"https://sasapps.io"
]
} }
+5 -4
View File
@@ -21,6 +21,7 @@
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css" /> <link href="$relpath^tabs.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="$relpath^jquery.js"></script> <script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script> <script type="text/javascript" src="$relpath^dynsections.js"></script>
<script type="text/javascript" src="$relpath^cookie.js"></script>
$treeview $search $mathjax $treeview $search $mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" /> <link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="$relpath^favicon.ico" type="image/x-icon" /> <link rel="shortcut icon" href="$relpath^favicon.ico" type="image/x-icon" />
@@ -39,6 +40,10 @@
g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s); g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s);
})(); })();
</script> </script>
<noscript>
<p><img referrerpolicy="no-referrer-when-downgrade" src="https://analytics.4gl.io/matomo.php?idsite=6&amp;rec=1"
style="border:0;" alt="" /></p>
</noscript>
<!-- End Matomo Code --> <!-- End Matomo Code -->
</head> </head>
@@ -80,7 +85,3 @@
</div> </div>
<!--END TITLEAREA--> <!--END TITLEAREA-->
<!-- end header part --> <!-- end header part -->
</div>
</body>
</html>
+1 -4
View File
@@ -25,10 +25,7 @@
}, },
"testConfig": { "testConfig": {
"initProgram": "tests/testinit.sas", "initProgram": "tests/testinit.sas",
"termProgram": "tests/testterm.sas", "termProgram": "tests/testterm.sas"
"macroVars": {
"mcTestAppLoc": "/Public/temp/macrocore"
}
}, },
"defaultTarget": "server", "defaultTarget": "server",
"targets": [ "targets": [
+4 -1
View File
@@ -10,7 +10,9 @@
**/ **/
/* location in metadata or SAS Drive for temporary files */ /* location in metadata or SAS Drive for temporary files */
%let mcTestAppLoc=/Public/testresults/sasjs_core/%mf_uid(); %let mcTestAppLoc=/Users/&sysuserid/testresults/sasjs_core/%mf_uid();
%let mcTestContext=SAS Job Execution compute context;
/* set defaults */ /* set defaults */
%mp_init() %mp_init()
@@ -23,6 +25,7 @@ options lrecl=80;
%macro loglevel(); %macro loglevel();
%if "&_debug"="2477" or "&_debug"="fields,log,trace" or "&_debug"="131" %if "&_debug"="2477" or "&_debug"="fields,log,trace" or "&_debug"="131"
or "&_debug"="128"
%then %do; %then %do;
%put debug mode activated; %put debug mode activated;
options mprint mprintnest; options mprint mprintnest;
+30 -3
View File
@@ -5,6 +5,7 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_uid.sas @li mf_uid.sas
@li mp_assert.sas @li mp_assert.sas
@li mp_assertscope.sas
@li mv_createfolder.sas @li mv_createfolder.sas
@li mv_deleteviyafolder.sas @li mv_deleteviyafolder.sas
@li mv_getfoldermembers.sas @li mv_getfoldermembers.sas
@@ -15,7 +16,11 @@
%let folder=%mf_uid(); %let folder=%mf_uid();
/* create a folder */ /* create a folder */
%mp_assertscope(SNAPSHOT)
%mv_createfolder(path=&mcTestAppLoc/temp/&folder/&folder) %mv_createfolder(path=&mcTestAppLoc/temp/&folder/&folder)
%mp_assertscope(COMPARE, ignorelist=MC0_JADP1LEN MC0_JADP2LEN MC0_JADPNUM
MC0_JADVLEN MC2_JADP1LEN MC2_JADP2LEN MC2_JADPNUM MC2_JADVLEN
)
%mv_getfoldermembers(root=&mcTestAppLoc/temp/&folder, outds=work.folders) %mv_getfoldermembers(root=&mcTestAppLoc/temp/&folder, outds=work.folders)
@@ -32,17 +37,39 @@ run;
) )
/* create a folder without output dataset as part of the original macro */ /* create a folder without output dataset as part of the original macro */
%mv_createfolder(path=&mcTestAppLoc/temp/&folder/folder2,outds=folders2) %mv_createfolder(path=&mcTestAppLoc/temp/&folder/f2
,outds=folders2,mdebug=&sasjs_mdebug
)
%let test=0; %let test=0;
data _null_; data _null_;
set work.folders2; set work.folders2;
putlog (_all_)(=); putlog (_all_)(=);
if not missing(self_uri) and not missing(parent_uri) if not missing(self_uri) then call symputx('test2',1);
then call symputx('test2',1);
run; run;
%mp_assert( %mp_assert(
iftrue=(&test2=1), iftrue=(&test2=1),
desc=Check if outds param works desc=Check if outds param works
) )
/* create a folder with full stops */
%let newfolder=%mf_uid().2.1;
%mv_createfolder(path=&mcTestAppLoc/temp/&newfolder
,outds=work.folders3
,mdebug=&sasjs_mdebug
)
%mv_getfoldermembers(root=&mcTestAppLoc/temp, outds=work.folders3)
%let test3=0;
data _null_;
set work.folders3;
putlog (_all_)(=);
if name="&newfolder" then call symputx('test3',1);
run;
%mp_assert(
iftrue=(&test3=1),
desc=Check if folder with full stops can be successfully created
)
@@ -80,7 +80,7 @@ options mprint;
typeDefNameVar=invalidTypeDefName, typeDefNameVar=invalidTypeDefName,
propertiesVar=invalidProperties, propertiesVar=invalidProperties,
mediaTypeVar=invalidMediaType mediaTypeVar=invalidMediaType
) )
%mp_assertscope(COMPARE %mp_assertscope(COMPARE
,ignorelist= ,ignorelist=
&mvarIgnoreList invalidTypeDefName invalidProperties invalidMediaType &mvarIgnoreList invalidTypeDefName invalidProperties invalidMediaType
+5 -5
View File
@@ -33,19 +33,19 @@ data _null_;
; ;
run; run;
%mv_createjob(path=/Public/temp,name=demo1,code=testprog) %mv_createjob(path=&mcTestAppLoc,name=demo1,code=testprog)
%mv_createjob(path=/Public/temp,name=demo2,code=testprog) %mv_createjob(path=&mcTestAppLoc,name=demo2,code=testprog)
data work.inputjobs; data work.inputjobs;
_contextName='SAS Job Execution compute context'; _contextName="&mcTestContext";
do flow_id=1 to 2; do flow_id=1 to 2;
do i=1 to 4; do i=1 to 4;
_program='/Public/temp/demo1'; _program="&mcTestAppLoc/demo1";
macrovar1=10*i; macrovar1=10*i;
macrovar2=4*i; macrovar2=4*i;
output; output;
i+1; i+1;
_program='/Public/temp/demo2'; _program="&mcTestAppLoc/demo2";
macrovar1=40*i; macrovar1=40*i;
macrovar2=44*i; macrovar2=44*i;
output; output;
+5 -5
View File
@@ -29,19 +29,19 @@ data _null_;
; ;
run; run;
%mv_createjob(path=/Public/temp,name=demo1,code=testprog) %mv_createjob(path=&mcTestAppLoc,name=demo1,code=testprog)
%mv_createjob(path=/Public/temp,name=demo2,code=testprog) %mv_createjob(path=&mcTestAppLoc,name=demo2,code=testprog)
data work.inputjobs; data work.inputjobs;
_contextName='SAS Job Execution compute context'; _contextName="&mcTestContext";
do flow_id=1 to 2; do flow_id=1 to 2;
do i=1 to 4; do i=1 to 4;
_program='/Public/temp/demo1'; _program="&mcTestAppLoc/demo1";
macrovar1=10*i; macrovar1=10*i;
macrovar2=4*i; macrovar2=4*i;
output; output;
i+1; i+1;
_program='/Public/temp/demo2'; _program="&mcTestAppLoc/demo2";
macrovar1=40*i; macrovar1=40*i;
macrovar2=44*i; macrovar2=44*i;
output; output;
+192
View File
@@ -0,0 +1,192 @@
/**
@file
@brief Testing mx_append2pgm.sas macro
Be sure to run <code>%let mcTestAppLoc=/Public/temp/macrocore;</code> when
running in Studio
<h4> SAS Macros </h4>
@li mf_getplatform.sas
@li mf_uid.sas
@li mp_assert.sas
@li mp_assertscope.sas
@li ms_createfile.sas
@li mv_createfile.sas
@li mm_createstp.sas
@li mx_append2pgm.sas
@li mx_getcode.sas
**/
/**
* Test 1 - Append content to an existing program and verify combined output
* Also checking for scope leakage
*/
/* create a unique name for the program */
%let item=test_%mf_uid();
/* create the initial program with some code */
filename initpgm temp;
data _null_;
file initpgm;
put '%put ORIGINAL LINE;';
run;
%macro setup_pgm();
%let platform=%mf_getplatform();
%if &platform=SASJS %then %do;
%ms_createfile(&mcTestAppLoc/temp/&item..sas, inref=initpgm)
%end;
%else %if &platform=SASVIYA %then %do;
%mv_createfile(path=&mcTestAppLoc/temp, name=&item..sas, inref=initpgm)
%end;
%else %do;
%let work=%sysfunc(pathname(work));
data _null_;
file "&work/&item..sas";
infile initpgm;
input;
put _infile_;
run;
%mm_createstp(stpname=&item
,filename=&item..sas
,directory=&work
,tree=&mcTestAppLoc/temp
,stptype=2
,minify=NO
)
%end;
%mend setup_pgm;
%setup_pgm()
/* create the content to append */
filename toappnd temp;
data _null_;
file toappnd;
put '%put APPENDED LINE;';
run;
/* run the macro under test with scope checks */
%mp_assertscope(SNAPSHOT)
%mx_append2pgm(&mcTestAppLoc/temp/&item, inref=toappnd)
%mp_assertscope(COMPARE,
desc=Test 1: mx_append2pgm does not leak scope,
outds=work.test_results,
ignorelist=MC2_JADP1LEN MC2_JADP2LEN MC2_JADPNUM MC2_JADVLEN MC2_JADP3LEN
)
%mp_assert(
iftrue=(&syscc=0),
desc=Test 1: No errors after appending content to program,
outds=work.test_results
)
/**
* Test 2 - Verify the appended content is present
* Fetch the modified program and check both original and appended lines exist
*/
%let test2_orig=0;
%let test2_appd=0;
%macro verify_test2();
%let platform=%mf_getplatform();
%if &platform=SASVIYA %then %do;
filename verifrf filesrvc folderpath="&mcTestAppLoc/temp";
data _null_;
infile verifrf("&item..sas") lrecl=32000;
input;
if index(_infile_,'ORIGINAL LINE') then call symputx('test2_orig','1');
if index(_infile_,'APPENDED LINE') then call symputx('test2_appd','1');
run;
filename verifrf clear;
%end;
%else %do;
%mx_getcode(&mcTestAppLoc/temp/&item, outref=verifrf)
data _null_;
infile verifrf lrecl=32000;
input;
if index(_infile_,'ORIGINAL LINE') then call symputx('test2_orig','1');
if index(_infile_,'APPENDED LINE') then call symputx('test2_appd','1');
run;
%end;
%mend verify_test2;
%verify_test2()
%mp_assert(
iftrue=(&test2_orig=1),
desc=Test 2a: Original content is preserved after append,
outds=work.test_results
)
%mp_assert(
iftrue=(&test2_appd=1),
desc=Test 2b: Appended content is present in modified program,
outds=work.test_results
)
/**
* Test 3 - Append multiple times to ensure repeated appends work
*/
filename toappd2 temp;
data _null_;
file toappd2;
put '%put SECOND APPEND;';
run;
%mp_assertscope(SNAPSHOT)
%mx_append2pgm(&mcTestAppLoc/temp/&item, inref=toappd2)
%mp_assertscope(COMPARE,
desc=Test 3: mx_append2pgm does not leak scope on second call,
outds=work.test_results
)
/* verify all three pieces of content exist */
%let test3_orig=0;
%let test3_appd=0;
%let test3_app2=0;
%macro verify_test3();
%let platform=%mf_getplatform();
%if &platform=SASVIYA %then %do;
filename verifr2 filesrvc folderpath="&mcTestAppLoc/temp";
data _null_;
infile verifr2("&item..sas") lrecl=32000;
input;
if index(_infile_,'ORIGINAL LINE') then call symputx('test3_orig','1');
if index(_infile_,'APPENDED LINE') then call symputx('test3_appd','1');
if index(_infile_,'SECOND APPEND') then call symputx('test3_app2','1');
run;
filename verifr2 clear;
%end;
%else %do;
%mx_getcode(&mcTestAppLoc/temp/&item, outref=verifr2)
data _null_;
infile verifr2 lrecl=32000;
input;
if index(_infile_,'ORIGINAL LINE') then call symputx('test3_orig','1');
if index(_infile_,'APPENDED LINE') then call symputx('test3_appd','1');
if index(_infile_,'SECOND APPEND') then call symputx('test3_app2','1');
run;
%end;
%mend verify_test3;
%verify_test3()
%mp_assert(
iftrue=(&test3_orig=1),
desc=Test 3a: Original content still present after second append,
outds=work.test_results
)
%mp_assert(
iftrue=(&test3_appd=1),
desc=Test 3b: First appended content still present after second append,
outds=work.test_results
)
%mp_assert(
iftrue=(&test3_app2=1),
desc=Test 3c: Second appended content is present,
outds=work.test_results
)
+7 -6
View File
@@ -204,9 +204,10 @@ run;
/* Get Viya file-extension details into some macro variables */ /* Get Viya file-extension details into some macro variables */
%mv_getViyaFileExtParms(&ext %mv_getViyaFileExtParms(&ext
,propertiesVar=viyaProperties ,propertiesVar=viyaProperties
,typeDefNameVar=viyaTypeDefName ,typeDefNameVar=viyaTypeDefName
,mdebug=&mdebug); ,mdebug=&mdebug
)
/* fetch job info */ /* fetch job info */
%local fname1; %local fname1;
@@ -274,9 +275,9 @@ run;
/* If properties were found then patch the file to include them */ /* If properties were found then patch the file to include them */
%if not %mf_isBlank(%superq(viyaProperties)) %then %do; %if not %mf_isBlank(%superq(viyaProperties)) %then %do;
/* Wrap the properties object in a root object also containing the file name */ /* Wrap the properties object in a root object also containing the filename */
%local viyapatch; %local viyapatch;
%let viyapatch = %sysfunc(pathname(work))/%mf_getuniquename(prefix=patch_json_); %let viyapatch=%sysfunc(pathname(work))/%mf_getuniquename(prefix=patch_json_);
data _null_; data _null_;
length line $32767; length line $32767;
file "&viyapatch" lrecl=32767; file "&viyapatch" lrecl=32767;
@@ -296,7 +297,7 @@ run;
run; run;
%end; %end;
/* And apply the properties to the newly created file, using the PATCH method */ /* Apply the properties to the newly created file, using the PATCH method */
%let fref=%mf_getuniquefileref(); %let fref=%mf_getuniquefileref();
filename &fref "&viyapatch"; filename &fref "&viyapatch";
%let url=&base_uri&fileuri; %let url=&base_uri&fileuri;
-1
View File
@@ -145,7 +145,6 @@ options noquotelenmax;
run; run;
%end; %end;
%if &SYS_PROCHTTP_STATUS_CODE=200 %then %do; %if &SYS_PROCHTTP_STATUS_CODE=200 %then %do;
%*put &sysmacroname &newpath exists so grab the follow on link ;
data _null_; data _null_;
set &libref1..links; set &libref1..links;
if rel='createChild' then if rel='createChild' then
+21 -7
View File
@@ -594,14 +594,14 @@ data _null_;
put ' ,showmeta=N,maxobs=MAX,workobs=0 '; put ' ,showmeta=N,maxobs=MAX,workobs=0 ';
put '); '; put '); ';
put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name '; put '%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name ';
put ' sasjs_tables SYS_JES_JOB_URI; '; put ' sasjs_tables SYS_JES_JOB_URI _EXECUTIONTASKS; ';
put '%if %index("&_debug",log) %then %let _debug=131; '; put '%if %index("&_debug",log) %then %let _debug=128; ';
put ' '; put ' ';
put '%local i tempds table; '; put '%local i tempds table; ';
put '%let action=%upcase(&action); '; put '%let action=%upcase(&action); ';
put ' '; put ' ';
put '%if &action=FETCH %then %do; '; put '%if &action=FETCH %then %do; ';
put ' %if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 131 %then %do; '; put ' %if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 128 %then %do; ';
put ' options mprint notes mprintnest; '; put ' options mprint notes mprintnest; ';
put ' %end; '; put ' %end; ';
put ' '; put ' ';
@@ -609,6 +609,11 @@ data _null_;
put ' %let _webin_file_count=%eval(&_webin_file_count+0); '; put ' %let _webin_file_count=%eval(&_webin_file_count+0); ';
put ' %let _webin_fileuri1=&_webin_fileuri; '; put ' %let _webin_fileuri1=&_webin_fileuri; ';
put ' %let _webin_name1=&_webin_name; '; put ' %let _webin_name1=&_webin_name; ';
put ' %if &_EXECUTIONTASKS=true %then %do; ';
put ' /* TODO - remove this once SAS Track CS0409737 is resolved */ ';
put ' /* links: https://github.com/sasjs/adapter/issues/884 */ ';
put ' %if %upcase(&_webin_name)=_SASJS_NOOP %then %let _webin_file_count=0; ';
put ' %end; ';
put ' %end; '; put ' %end; ';
put ' '; put ' ';
put ' /* if the sasjs_tables param is passed, we expect param based upload */ '; put ' /* if the sasjs_tables param is passed, we expect param based upload */ ';
@@ -649,13 +654,17 @@ data _null_;
put ' %end; '; put ' %end; ';
put ' %else %do i=1 %to &_webin_file_count; '; put ' %else %do i=1 %to &_webin_file_count; ';
put ' /* read in any files that are sent */ '; put ' /* read in any files that are sent */ ';
put ' /* this part needs refactoring for wide files */ '; put ' %if &_EXECUTIONTASKS=true %then %do; ';
put ' filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999; '; put ' filename indata "%sysfunc(pathname(&&_webin_fileref&i))" lrecl=999999; ';
put ' %end; ';
put ' %else %do; ';
put ' filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999; ';
put ' %end; ';
put ' data _null_; '; put ' data _null_; ';
put ' infile indata termstr=crlf lrecl=32767; '; put ' infile indata termstr=crlf lrecl=32767; ';
put ' input; '; put ' input; ';
put ' if _n_=1 then call symputx(''input_statement'',_infile_); '; put ' if _n_=1 then call symputx(''input_statement'',_infile_); ';
put ' %if %str(&_debug) ge 131 %then %do; '; put ' %if %str(&_debug) ge 128 %then %do; ';
put ' if _n_<20 then putlog _infile_; '; put ' if _n_<20 then putlog _infile_; ';
put ' else stop; '; put ' else stop; ';
put ' %end; '; put ' %end; ';
@@ -688,6 +697,9 @@ data _null_;
put ' '; put ' ';
put ' /* setup json */ '; put ' /* setup json */ ';
put ' data _null_;file &fref; '; put ' data _null_;file &fref; ';
put ' %if %str(&_debug) ge 128 and &_EXECUTIONTASKS=true %then %do; ';
put ' put ''>>weboutBEGIN<<''; ';
put ' %end; ';
put ' put ''{"SYSDATE" : "'' "&SYSDATE" ''"''; '; put ' put ''{"SYSDATE" : "'' "&SYSDATE" ''"''; ';
put ' put '',"SYSTIME" : "'' "&SYSTIME" ''"''; '; put ' put '',"SYSTIME" : "'' "&SYSTIME" ''"''; ';
put ' run; '; put ' run; ';
@@ -800,7 +812,9 @@ data _null_;
put ' memsize=quote(cats(memsize)); '; put ' memsize=quote(cats(memsize)); ';
put ' put '',"MEMSIZE" : '' memsize; '; put ' put '',"MEMSIZE" : '' memsize; ';
put ' put "}"; '; put ' put "}"; ';
put ' '; put ' %if %str(&_debug) ge 128 and &_EXECUTIONTASKS=true %then %do; ';
put ' put ''>>weboutEND<<''; ';
put ' %end; ';
put ' %if %upcase(&fref) ne _WEBOUT and &stream=Y %then %do; '; put ' %if %upcase(&fref) ne _WEBOUT and &stream=Y %then %do; ';
put ' data _null_; rc=fcopy("&fref","_webout");run; '; put ' data _null_; rc=fcopy("&fref","_webout");run; ';
put ' %end; '; put ' %end; ';
+31 -24
View File
@@ -23,6 +23,7 @@
@li mf_existds.sas @li mf_existds.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvalue.sas @li mf_getvalue.sas
@li mf_getvarlist.sas @li mf_getvarlist.sas
@@ -48,7 +49,7 @@
iftrue=(%mf_isBlank(&ext)) iftrue=(%mf_isBlank(&ext))
,msg=%str(No file extension provided.) ,msg=%str(No file extension provided.)
,mac=MV_GETVIYAFILEEXTPARMS ,mac=MV_GETVIYAFILEEXTPARMS
); )
%mp_abort( %mp_abort(
iftrue=(%mf_isBlank(&typeDefNameVar) and iftrue=(%mf_isBlank(&typeDefNameVar) and
@@ -56,13 +57,13 @@
%mf_isBlank(&mediaTypeVar)) %mf_isBlank(&mediaTypeVar))
,msg=%str(MV_GETVIYAFILEEXTPARMS - No parameter was requested.) ,msg=%str(MV_GETVIYAFILEEXTPARMS - No parameter was requested.)
,mac=MV_GETVIYAFILEEXTPARMS ,mac=MV_GETVIYAFILEEXTPARMS
); )
%mp_abort( %mp_abort(
iftrue=(%mf_isBlank(&viyaFileExtRespLibDs)) iftrue=(%mf_isBlank(&viyaFileExtRespLibDs))
,msg=%str(No <libname.>dataset name provided to cache inital response.) ,msg=%str(No <libname.>dataset name provided to cache inital response.)
,mac=MV_GETVIYAFILEEXTPARMS ,mac=MV_GETVIYAFILEEXTPARMS
); )
/* Declare requested parameters as global macro vars and initialize blank */ /* Declare requested parameters as global macro vars and initialize blank */
%if not %mf_isBlank(&typeDefNameVar) %then %do; %if not %mf_isBlank(&typeDefNameVar) %then %do;
@@ -79,9 +80,7 @@
%end; %end;
%let base_uri=%mf_getplatform(VIYARESTAPI); %let base_uri=%mf_getplatform(VIYARESTAPI);
%if &mdebug=1 %then %do; %if &mdebug=1 %then %put DEBUG: &=base_uri;
%put DEBUG: &=base_uri;
%end;
%let ext=%lowcase(&ext); %let ext=%lowcase(&ext);
@@ -105,7 +104,7 @@
%if (&SYS_PROCHTTP_STATUS_CODE ne 200) %then %do; %if (&SYS_PROCHTTP_STATUS_CODE ne 200) %then %do;
/* To avoid a breaking change, exit early if the request failed. /* To avoid a breaking change, exit early if the request failed.
The calling process will proceed with empty requested macro variables. */ The calling process will proceed with empty macro variables. */
%put INFO: &sysmacroname File extension details were not retrieved.; %put INFO: &sysmacroname File extension details were not retrieved.;
filename &viyatypedefs clear; filename &viyatypedefs clear;
%return; %return;
@@ -126,11 +125,12 @@
/* Convert the content of that JSON into SAS datasets */ /* Convert the content of that JSON into SAS datasets */
/* First prepare a new WORK-based folder to receive the datasets */ /* First prepare a new WORK-based folder to receive the datasets */
%local jsonworkfolder jsonlib opt_dlcreatedir; %local jsonworkfolder jsonlib opt_dlcreatedir;
%let jsonworkfolder=%sysfunc(pathname(work))/%mf_getuniquename(prefix=json_); %let jsonworkfolder=%sysfunc(pathname(work))/%mf_getuniquename(prefix=jsn_);
%let jsonlib=%mf_getuniquelibref(prefix=json); %let jsonlib=%mf_getuniquelibref(prefix=json);
/* And point a libname at it */ /* And point a libname at it */
%let opt_dlcreatedir = %sysfunc(getoption(dlcreatedir)); %let opt_dlcreatedir = %sysfunc(getoption(dlcreatedir));
options dlcreatedir; libname &jsonlib "&jsonworkfolder"; options &opt_dlcreatedir; options dlcreatedir; libname &jsonlib "&jsonworkfolder";
options &opt_dlcreatedir;
/* Read the json output once and copy datasets to its work folder */ /* Read the json output once and copy datasets to its work folder */
%local libref1; %local libref1;
@@ -159,20 +159,22 @@
%end; /* If initial filetype query response didn't exist */ %end; /* If initial filetype query response didn't exist */
/* Find the row-group for the current file extension */ %if &mdebug %then %put DEBUG: Find the row-group for extension &ext;
%local itemRowGroup; %local itemRowGroup;
%let itemRowGroup = data _null_;
%mf_getValue( set &viyaFileExtRespLibDs;
&viyaFileExtRespLibDs where p1='items' and p2='extensions' and value="&ext";
,_viyaItemIdx call symputx('itemRowGroup',_viyaItemIdx,'l');
,filter=%quote(p1='items' and p2='extensions' and value="&ext") %if &mdebug %then %do;
); putlog (_all_)(=);
%end;
run;
%if &mdebug %then %put DEBUG: &=itemRowGroup; %if &mdebug %then %put DEBUG: &=itemRowGroup;
%if %mf_isBlank(&itemRowGroup) %then %do; %if %mf_isBlank(&itemRowGroup) %then %do;
/* extension was not found */ /* extension was not found */
%if(&mdebug=1) %then %put DEBUG: No type details found for extension "&ext".; %if &mdebug %then %put DEBUG: No type details found for extension "&ext";
%return; %return;
%end; %end;
@@ -186,14 +188,17 @@
/* Populate typeDefName, if requested */ /* Populate typeDefName, if requested */
%if (not %mf_isBlank(&typeDefNameVar)) %then %do; %if (not %mf_isBlank(&typeDefNameVar)) %then %do;
%let &typeDefNameVar = %mf_getvalue(&dsItems,value,filter=%quote(p1="items" and p2="name")); %let &typeDefNameVar = %mf_getvalue(
%if &mdebug=1 %then %put DEBUG: &=typeDefNameVar &typeDefNameVar=&&&typeDefNameVar; &dsItems,value,filter=%quote(p1="items" and p2="name"));
%if &mdebug %then
%put DEBUG: &=typeDefNameVar &typeDefNameVar=&&&typeDefNameVar;
%end; %end;
/* Populate mediaType, if requested */ /* Populate mediaType, if requested */
%if (not %mf_isBlank(&mediaTypeVar)) %then %do; %if (not %mf_isBlank(&mediaTypeVar)) %then %do;
%let &mediaTypeVar = %mf_getvalue(&dsItems,value,filter=%quote(p1="items" and p2="mediaType")); %let &mediaTypeVar = %mf_getvalue(
%if &mdebug=1 %then %put DEBUG: &=mediaTypeVar &mediaTypeVar=&&&mediaTypeVar; &dsItems,value,filter=%quote(p1="items" and p2="mediaType"));
%if &mdebug %then %put DEBUG: &=mediaTypeVar &mediaTypeVar=&&&mediaTypeVar;
%end; %end;
/* Populate properties macro variable, if requested */ /* Populate properties macro variable, if requested */
@@ -210,7 +215,8 @@
/* Check for 1+ properties */ /* Check for 1+ properties */
%if ( %mf_nobs(&dsProperties) = 0 ) %then %do; %if ( %mf_nobs(&dsProperties) = 0 ) %then %do;
%let &propertiesVar = %str(); %let &propertiesVar = %str();
%if &mdebug=1 %then %put DEBUG: &SYSMACRONAME - No Viya properties found for file suffix %str(%')&ext%str(%'); %if &mdebug %then %put DEBUG: &SYSMACRONAME - No Viya properties %trim(
)found for file suffix %str(%')&ext%str(%');
%end; %end;
%else %do; %else %do;
/* Properties potentially span multiple rows in the input table */ /* Properties potentially span multiple rows in the input table */
@@ -240,7 +246,8 @@
end; end;
run; run;
%if &mdebug=1 %then %put DEBUG: &=propertiesVar &propertiesVar=&&&propertiesVar; %if &mdebug %then
%put DEBUG: &=propertiesVar &propertiesVar=&&&propertiesVar;
%end; %end;
%end; %end;
+34 -19
View File
@@ -121,7 +121,7 @@
@li mf_nobs.sas @li mf_nobs.sas
@li mp_abort.sas @li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getvarlist.sas
@li mf_existvarlist.sas @li mf_existvarlist.sas
@li mv_jobwaitfor.sas @li mv_jobwaitfor.sas
@li mv_jobexecute.sas @li mv_jobexecute.sas
@@ -234,14 +234,12 @@ data _null_;
if last then call symputx('flowcnt',cnt,'l'); if last then call symputx('flowcnt',cnt,'l');
run; run;
/* prepare temporary datasets and frefs */ /* prepare temporary datasets */
%local fid jid jds jjson jdsapp jdsrunning jdswaitfor jfref; %local fid jid jds jdsapp jdsrunning jdswaitfor;
data;run;%let jds=&syslast; data;run;%let jds=&syslast;
data;run;%let jjson=&syslast;
data;run;%let jdsapp=&syslast; data;run;%let jdsapp=&syslast;
data;run;%let jdsrunning=&syslast; data;run;%let jdsrunning=&syslast;
data;run;%let jdswaitfor=&syslast; data;run;%let jdswaitfor=&syslast;
%let jfref=%mf_getuniquefileref();
/* start loop */ /* start loop */
%do fid=1 %to &flowcnt; %do fid=1 %to &flowcnt;
@@ -259,23 +257,39 @@ data;run;%let jdswaitfor=&syslast;
&dbg. if _n_= 1 then putlog "Loop &fid"; &dbg. if _n_= 1 then putlog "Loop &fid";
&dbg. putlog (_all_)(=); &dbg. putlog (_all_)(=);
run; run;
/* build list of char and num vars in json format */
/* Viya 2026 expects all values to be strings */
%local nvars cvars ii _vnm;
%let cvars=%mf_getvarlist(&jds,typefilter=C);
%let nvars=%mf_getvarlist(&jds,typefilter=N);
%put exporting job variables in json format; %put exporting job variables in json format;
%do jid=1 %to &jcnt; %do jid=1 %to &jcnt;
data &jjson;
set &jds;
if _n_=&jid then do;
output;
stop;
end;
run;
proc json out=&jfref;
export &jjson / nosastags fmtnumeric;
run;
data _null_; data _null_;
infile &jfref lrecl=32767; set &jds;
input; if _n_=&jid;
jparams=cats('jparams',symget('jid')); length _param $32767;
call symputx(jparams,substr(_infile_,3,length(_infile_)-4)); _param='';
%if %length(&cvars)>0 %then %do ii=1 %to %sysfunc(countw(&cvars,%str( )));
%let _vnm=%scan(&cvars,&ii,%str( ));
if _param ne '' then _param=cats(_param,',');
_param=cats(_param,'"'
,"%lowcase(&_vnm)"
,'":'
,quote(trim(&_vnm))
);
%end;
%if %length(&nvars)>0 %then %do ii=1 %to %sysfunc(countw(&nvars,%str( )));
%let _vnm=%scan(&nvars,&ii,%str( ));
if _param ne '' then _param=cats(_param,',');
_param=cats(_param,'"'
,"%lowcase(&_vnm)"
,'":"'
,strip(put(&_vnm,best32.))
,'"'
);
%end;
call symputx(cats('jparams',&jid),_param,'l');
stop;
run; run;
%local jobuid&jid; %local jobuid&jid;
%let jobuid&jid=0; /* used in next loop */ %let jobuid&jid=0; /* used in next loop */
@@ -320,6 +334,7 @@ data;run;%let jdswaitfor=&syslast;
,paramstring=%superq(jparams&jid) ,paramstring=%superq(jparams&jid)
,outds=&jdsapp ,outds=&jdsapp
,contextname=&&context&jid ,contextname=&&context&jid
,mdebug=&mdebug
) )
data &jdsapp; data &jdsapp;
format jobparams $32767.; format jobparams $32767.;
+21 -7
View File
@@ -55,14 +55,14 @@
,showmeta=N,maxobs=MAX,workobs=0 ,showmeta=N,maxobs=MAX,workobs=0
); );
%global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name %global _webin_file_count _webin_fileuri _debug _omittextlog _webin_name
sasjs_tables SYS_JES_JOB_URI; sasjs_tables SYS_JES_JOB_URI _EXECUTIONTASKS;
%if %index("&_debug",log) %then %let _debug=131; %if %index("&_debug",log) %then %let _debug=128;
%local i tempds table; %local i tempds table;
%let action=%upcase(&action); %let action=%upcase(&action);
%if &action=FETCH %then %do; %if &action=FETCH %then %do;
%if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 131 %then %do; %if %upcase(&_omittextlog)=FALSE or %str(&_debug) ge 128 %then %do;
options mprint notes mprintnest; options mprint notes mprintnest;
%end; %end;
@@ -70,6 +70,11 @@
%let _webin_file_count=%eval(&_webin_file_count+0); %let _webin_file_count=%eval(&_webin_file_count+0);
%let _webin_fileuri1=&_webin_fileuri; %let _webin_fileuri1=&_webin_fileuri;
%let _webin_name1=&_webin_name; %let _webin_name1=&_webin_name;
%if &_EXECUTIONTASKS=true %then %do;
/* TODO - remove this once SAS Track CS0409737 is resolved */
/* links: https://github.com/sasjs/adapter/issues/884 */
%if %upcase(&_webin_name)=_SASJS_NOOP %then %let _webin_file_count=0;
%end;
%end; %end;
/* if the sasjs_tables param is passed, we expect param based upload */ /* if the sasjs_tables param is passed, we expect param based upload */
@@ -110,13 +115,17 @@
%end; %end;
%else %do i=1 %to &_webin_file_count; %else %do i=1 %to &_webin_file_count;
/* read in any files that are sent */ /* read in any files that are sent */
/* this part needs refactoring for wide files */ %if &_EXECUTIONTASKS=true %then %do;
filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999; filename indata "%sysfunc(pathname(&&_webin_fileref&i))" lrecl=999999;
%end;
%else %do;
filename indata filesrvc "&&_webin_fileuri&i" lrecl=999999;
%end;
data _null_; data _null_;
infile indata termstr=crlf lrecl=32767; infile indata termstr=crlf lrecl=32767;
input; input;
if _n_=1 then call symputx('input_statement',_infile_); if _n_=1 then call symputx('input_statement',_infile_);
%if %str(&_debug) ge 131 %then %do; %if %str(&_debug) ge 128 %then %do;
if _n_<20 then putlog _infile_; if _n_<20 then putlog _infile_;
else stop; else stop;
%end; %end;
@@ -149,6 +158,9 @@
/* setup json */ /* setup json */
data _null_;file &fref; data _null_;file &fref;
%if %str(&_debug) ge 128 and &_EXECUTIONTASKS=true %then %do;
put '>>weboutBEGIN<<';
%end;
put '{"SYSDATE" : "' "&SYSDATE" '"'; put '{"SYSDATE" : "' "&SYSDATE" '"';
put ',"SYSTIME" : "' "&SYSTIME" '"'; put ',"SYSTIME" : "' "&SYSTIME" '"';
run; run;
@@ -261,7 +273,9 @@
memsize=quote(cats(memsize)); memsize=quote(cats(memsize));
put ',"MEMSIZE" : ' memsize; put ',"MEMSIZE" : ' memsize;
put "}"; put "}";
%if %str(&_debug) ge 128 and &_EXECUTIONTASKS=true %then %do;
put '>>weboutEND<<';
%end;
%if %upcase(&fref) ne _WEBOUT and &stream=Y %then %do; %if %upcase(&fref) ne _WEBOUT and &stream=Y %then %do;
data _null_; rc=fcopy("&fref","_webout");run; data _null_; rc=fcopy("&fref","_webout");run;
%end; %end;
+149
View File
@@ -0,0 +1,149 @@
/**
@file
@brief Appends a text file to a SASjs Stored Program, Viya SAS program, or
SAS 9 Stored Process
@details Extracts the source code from a SASjs Stored Program, Viya SAS
program (file in SAS Drive), or SAS 9 Stored Process, appends the contents
of a provided text file, then deletes and recreates the target item with the
combined content.
This is useful for dynamically modifying deployed programs, for example to
add test-specific configuration or runtime settings.
Usage:
%* compile macros ;
filename mc url
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
%* write some content to append;
filename append temp;
data _null_;
file append;
put "libname mylib '/some/path';";
run;
%* append to existing program;
%mx_append2pgm(/Public/app/common/settings, inref=append)
@param [in] loc The full path to the Viya SAS program, SAS 9 Stored Process,
or SASjs Stored Program in Drive or Metadata, WITHOUT the .sas extension
(SASjs only)
@param [in] inref= (0) Fileref pointing to the content to be appended to the
target program.
@param [in] mdebug= (0) Set to 1 to show debug messages in the log
<h4> SAS Macros </h4>
@li mf_getplatform.sas
@li mf_getuniquefileref.sas
@li mm_createstp.sas
@li mm_deletestp.sas
@li mm_getstpcode.sas
@li ms_createfile.sas
@li ms_deletefile.sas
@li mv_createfile.sas
@li mv_deletefoldermember.sas
@li mx_getcode.sas
<h4> Related Macros </h4>
@li mx_append2pgm.test.sas
@li mx_getcode.sas
@li mx_createjob.sas
@author Allan Bowe
**/
%macro mx_append2pgm(loc
,inref=0
,mdebug=0
)/*/STORE SOURCE*/;
%local platform name shortloc coderef combref work tmpfile viyaref;
%let platform=%mf_getplatform();
%if &mdebug=1 %then %do;
%put &sysmacroname entry vars:;
%put _local_;
%end;
%if &syscc ne 0 %then %do;
%put syscc=&syscc - &sysmacroname will not execute in this state;
%return;
%end;
/* extract name & path from loc */
data _null_;
length name shortloc $500;
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;
/* create a combined fileref with original + appended content */
%let combref=%mf_getuniquefileref();
%let work=%sysfunc(pathname(work));
%let tmpfile=&combref..sas;
filename &combref "&work/&tmpfile" lrecl=32000;
%if &platform=SASVIYA %then %do;
/* On Viya, read the SAS program file from SAS Drive using filesrvc */
%let viyaref=%mf_getuniquefileref();
filename &viyaref filesrvc folderpath="&shortloc";
data _null_;
file &combref lrecl=32000 termstr=crlf;
infile &viyaref("&name..sas") lrecl=32000 end=last;
input;
put _infile_;
run;
filename &viyaref clear;
%symdel _FILESRVC_&viyaref._URI;
%end;
%else %do;
/* For SAS9 and SASJS, use mx_getcode */
%let coderef=%mf_getuniquefileref();
%mx_getcode(&loc, outref=&coderef)
data _null_;
file &combref lrecl=32000 termstr=crlf;
infile &coderef lrecl=32000 end=last;
input;
put _infile_;
run;
filename &coderef clear;
%end;
/* append the new content */
data _null_;
file &combref lrecl=32000 termstr=crlf mod;
infile &inref lrecl=32000;
input;
put _infile_;
run;
/* delete and recreate the target item */
%if &platform=SASJS %then %do;
%ms_deletefile(&loc..sas)
%ms_createfile(&loc..sas, inref=&combref, mdebug=&mdebug)
%end;
%else %if &platform=SASVIYA %then %do;
%mv_deletefoldermember(path=&shortloc, name=&name..sas, contenttype=file)
%mv_createfile(path=&shortloc, name=&name..sas, inref=&combref)
%end;
%else %do;
/* SAS 9 */
%mm_deletestp(target=&loc)
%mm_createstp(stpname=&name
,filename=&tmpfile
,directory=&work
,tree=&shortloc
,stptype=2
,mDebug=&mdebug
,minify=NO
)
%end;
filename &combref clear;
%mend mx_append2pgm;