1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-13 23:44:35 +00:00

Compare commits

...

57 Commits

Author SHA1 Message Date
Allan Bowe
6938a42896 Merge pull request #215 from sasjs/serverconfig
Change test server & update mx_webout() macros
2022-04-14 15:41:44 +03:00
munja
efff77c94e fix: mx_webout 2022-04-14 13:40:14 +01:00
Allan Bowe
134b91f266 fix: avoiding running tests on viya 2022-04-14 11:14:35 +00:00
Allan Bowe
969f551e10 Merge pull request #214 from sasjs/cond
fix: adding cond/endcond to mp_ds2cards
2022-04-13 23:34:52 +03:00
munja
26623ba085 fix: adding cond/endcond to mp_ds2cards 2022-04-13 21:32:47 +01:00
Allan Bowe
8eb495890d Merge pull request #213 from sasjs/issue212
fix: ensuring indexes are picked up in mp_getpk().  Closes #212
2022-04-13 15:59:22 +03:00
munja
c1a30977f1 chore: removing serverurl 2022-04-13 13:58:55 +01:00
munja
9a6be61651 fix: ensuring indexes are picked up in mp_getpk(). Closes #212 2022-04-13 13:57:43 +01:00
Allan Bowe
388839039e Merge pull request #211 from sasjs/streamhtmlasfile
fix: send html as attachment rather than streamed content
2022-04-11 12:56:02 +03:00
Allan Bowe
e760a89a6a fix: send html as attachment rather than streamed content when mp_streamfile is used on all platforms 2022-04-11 09:54:07 +00:00
Allan Bowe
d2e30267e8 Merge pull request #210 from sasjs/nulfixes
fix: using regex special chars instead of hex constants in mp_jsonout
2022-04-07 11:53:37 +03:00
munja
190dbddfe3 fix: using regex special chars instead of hex constants in mp_jsonout 2022-04-07 09:52:56 +01:00
Allan Bowe
05e769794e Merge pull request #209 from sasjs/missref
fix: avoid: ERROR: Variable "fref" may not be initialized
2022-04-06 18:26:45 +03:00
munja
558ebaf6f2 fix: avoid: ERROR: Variable "fref" may not be initialized 2022-04-06 16:25:50 +01:00
Allan Bowe
970b56fe5a Merge pull request #208 from sasjs/issue207
fix: removing LUA dependency from mv_webout to enable Viya 4 compatibility
2022-04-01 20:42:22 +03:00
munja
c2597bd07b fix: missing dependency in mp_hashdataset.test.sas 2022-04-01 17:29:06 +01:00
munja
c4baca477b fix: removing LUA dependency from mv_webout to enable Viya 4 compatibility 2022-04-01 16:56:49 +01:00
Allan Bowe
7726b0e0b0 Merge pull request #206 from sasjs/ms_getfile
fix: ensuring ms_getfile works on specific installs
2022-03-29 20:41:20 +03:00
munja
0a536245f3 fix: missing dependency in mp_hashdataset.test.sas 2022-03-29 18:40:58 +01:00
munja
edfa9ecc07 fix: ensuring ms_getfile works on specific installs 2022-03-29 18:08:24 +01:00
munja
f4982c85ca fix: adding nonote2err option on mp_hashdataset 2022-03-29 15:00:33 +01:00
Allan Bowe
3ce771d587 Merge pull request #205 from sasjs/issue204
fix: updating mp_hashdataset to cope with STRICT mode.  Adding test a…
2022-03-29 15:47:17 +03:00
munja
72d6b446c3 fix: updating mp_hashdataset to cope with STRICT mode. Adding test and improving sasjs/server compatibility. 2022-03-29 13:22:24 +01:00
Allan Bowe
40d694eec8 Merge pull request #203 from sasjs/invisibles
fix: support SOH, STX and DC1 control characters in mp_jsonout
2022-03-29 12:02:09 +03:00
munja
6af1423666 fix: more invisibles 2022-03-28 16:26:58 +01:00
munja
23a01347f1 fix: support SOH, STX and DC1 control characters in mp_jsonout 2022-03-28 15:54:28 +01:00
Allan Bowe
7c86d6163a Merge pull request #201 from sasjs/mm_assignlib_fix
fix: enabling more descriptive mm_assignlib abort messages when library cannot be assigned
2022-03-21 18:10:56 +02:00
munja
d7233208f1 fix: enabling more descriptive mm_assignlib abort messages when library cannot be assigned 2022-03-21 16:07:27 +00:00
Allan Bowe
7f587ba720 Merge pull request #200 from sasjs/server
fix: headers in ms_createfile.sas
2022-03-19 02:23:57 +02:00
munja
21ecc1b675 fix: headers in ms_createfile.sas 2022-03-19 00:20:05 +00:00
Allan Bowe
6b13dc2b87 Merge pull request #199 from sasjs/server
fix: missing dependency in mv_deleteviyafolder
2022-03-16 18:07:40 +02:00
munja
bb89184212 fix: missing dependency in mv_deleteviyafolder 2022-03-16 16:01:22 +00:00
Allan Bowe
56338caaca Merge pull request #198 from sasjs/server
feat: enabling delete file for sasjs/server
2022-03-15 17:41:24 +02:00
munja
d7e2ff8ac9 fix: diffs for format loads not showing in audit table 2022-03-15 15:20:25 +00:00
munja
582ec0a1f9 feat: enabling delete file for sasjs/server 2022-03-15 13:46:31 +00:00
Allan Bowe
53785f5644 Update README.md 2022-03-14 13:44:13 +00:00
Allan Bowe
a8acadb8f1 Merge pull request #197 from sasjs/devops
gitpod & git hook updates
2022-03-11 23:25:20 +02:00
Allan Bowe
23dbda302e fix: ensuring pre-commit fails when sasjs lint fails 2022-03-11 21:24:34 +00:00
Allan Bowe
7e7ab4275d fix: gitpod launching sasjs 2022-03-11 21:23:52 +00:00
Allan Bowe
a455a3d98d Merge pull request #196 from sasjs/delfile
feat: adding new mf_deletefile macro (and test)
2022-03-11 17:20:34 +02:00
munja
588d987c25 fix: missing dependency in test 2022-03-11 15:14:54 +00:00
munja
8ffd06343a feat: adding new mf_deletefile macro (and test)
Also, update to mm_spkexport macro
2022-03-11 15:03:59 +00:00
Allan Bowe
76207c443c Merge pull request #195 from sasjs/issue194
fix: supporting empty dirs in mp_dirlist. Test updated.
2022-03-11 14:28:31 +02:00
munja
7e9e0fac07 fix: supporting empty dirs in mp_dirlist. Test updated. 2022-03-11 11:28:03 +00:00
Allan Bowe
1fdbc7cce9 Merge pull request #193 from sasjs/mm_spkexport
feat: ignorevars option in mm_spkexport, and log update in mf_verifymacvars
2022-03-10 19:28:50 +02:00
munja
312369b200 feat: ignorevars option in mm_spkexport, and log update in mf_verifymacvars 2022-03-10 17:27:30 +00:00
Allan Bowe
c030174bfb Merge pull request #192 from sasjs/bugfix
fix: dependency in mp_loadformat test and strict mode issue in mm_deletelibrary
2022-03-09 16:16:32 +02:00
munja
faf466e79a fix: dependency in mp_loadformat test and strict mode issue in mm_deletelibrary 2022-03-09 14:15:25 +00:00
Allan Bowe
856ffc1b72 Merge pull request #191 from sasjs/allanbowe/mp-loadformat-not-appending-190
fix: ensuring audit table gets loaded in mp_loadformat.
2022-03-08 21:50:42 +02:00
munja
c0924af06b fix: correcting test for mp_loadformat 2022-03-08 19:50:01 +00:00
munja
33cec61a13 fix: quoting mf_getuser in case of commas. Fixes #189 2022-03-08 19:40:22 +00:00
munja
854ff696d8 fix: adding missing dependency in mp_loadformat 2022-03-08 19:33:46 +00:00
Allan Bowe
cc3435d13d fix: ensuring audit table gets loaded in mp_loadformat. Adding test also. Closes #190 2022-03-08 16:52:22 +00:00
Allan Bowe
5ceaac195d Merge pull request #188 from sasjs/hex32
fix: adding explicit $ sign to hex32. format in mp_md5() macro
2022-03-07 22:38:57 +02:00
Allan Bowe
5d5df977a6 fix: adding explicit $ sign to hex32. format in mp_md5() macro 2022-03-07 19:57:25 +00:00
Allan Bowe
245e85ef36 Merge pull request #187 from sasjs/periodproblem
fix: mp_replace and mv_getjobcode were not ingesting periods correctly
2022-03-07 16:27:14 +02:00
munja
b96df6f14f fix: mp_replace and mv_getjobcode were not ingesting periods correctly 2022-03-07 14:25:05 +00:00
45 changed files with 1514 additions and 2630 deletions

View File

@@ -1,5 +1,12 @@
#!/bin/bash #!/bin/bash
sasjs lint
# Ensure lint is passing
LINT=`sasjs lint`
if [[ "$LINT" != "✔ All matched files use @sasjs/lint code style!" ]]; then
echo "$LINT"
echo "To commit in spite of these warnings, use the -n parameter."
exit 1
fi
# Avoid commits to the master branch # Avoid commits to the master branch
BRANCH=`git rev-parse --abbrev-ref HEAD` BRANCH=`git rev-parse --abbrev-ref HEAD`

View File

@@ -1,7 +1,7 @@
tasks: tasks:
- init: | - init: npm install -g npm
nvm install --lts - command: npm i
npm i -g @sasjs/cli - command: npm i -g @sasjs/cli
image: image:
file: .gitpod.dockerfile file: .gitpod.dockerfile
@@ -24,4 +24,4 @@ github:
# add a "Review in Gitpod" button to pull requests (defaults to false) # add a "Review in Gitpod" button to pull requests (defaults to false)
addBadge: false addBadge: false
# add a label once the prebuild is ready to pull requests (defaults to false) # add a label once the prebuild is ready to pull requests (defaults to false)
addLabel: prebuilt-in-gitpod addLabel: prebuilt-in-gitpod

View File

@@ -217,6 +217,15 @@ If you find this library useful, please leave a [star](https://github.com/sasjs/
![](https://starchart.cc/sasjs/core.svg) ![](https://starchart.cc/sasjs/core.svg)
## Other SAS Repositories
The following repositories are also worth checking out:
* [chris-swenson/sasmacros](https://github.com/chris-swenson/sasmacros)
* [greg-wotton/sas-programs](https://github.com/greg-wootton/sas-programs)
* [KatjaGlassConsulting/SMILE-SmartSASMacros](https://github.com/KatjaGlassConsulting/SMILE-SmartSASMacros)
* [scottbass/sas](https://github.com/scottbass/SAS)
* [yabwon/sas_packages](https://github.com/yabwon/SAS_PACKAGES)
## Contributors ✨ ## Contributors ✨
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --> <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

655
all.sas

File diff suppressed because it is too large Load Diff

31
base/mf_deletefile.sas Normal file
View File

@@ -0,0 +1,31 @@
/**
@file
@brief Deletes a physical file, if it exists
@details Usage:
%mf_writefile(&sasjswork/myfile.txt,l1=some content)
%mf_deletefile(&sasjswork/myfile.txt)
%mf_deletefile(&sasjswork/myfile.txt)
@param filepath Full path to the target file
@returns The return code from the fdelete() invocation
<h4> Related Macros </h4>
@li mf_deletefile.test.sas
@li mf_writefile.sas
@version 9.2
@author Allan Bowe
**/
%macro mf_deletefile(file
)/*/STORE SOURCE*/;
%local rc fref;
%let rc= %sysfunc(filename(fref,&file));
%if %sysfunc(fdelete(&fref)) ne 0 %then %put %sysfunc(sysmsg());
%let rc= %sysfunc(filename(fref));
%mend mf_deletefile;

View File

@@ -9,19 +9,17 @@
%put %mf_existfeature(PROCLUA); %put %mf_existfeature(PROCLUA);
@param feature the feature to detect. Leave blank to list all in log. @param [in] feature The feature to detect.
@return output returns 1 or 0 (or -1 if not found) @return output returns 1 or 0 (or -1 if not found)
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getplatform.sas @li mf_getplatform.sas
@version 8 @version 8
@author Allan Bowe @author Allan Bowe
**/ **/
/** @cond */ /** @cond */
%macro mf_existfeature(feature %macro mf_existfeature(feature
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%let feature=%upcase(&feature); %let feature=%upcase(&feature);
@@ -29,7 +27,11 @@
%let platform=%mf_getplatform(); %let platform=%mf_getplatform();
%if &feature= %then %do; %if &feature= %then %do;
%put Supported features: PROCLUA; %put No feature was requested for detection;
%end;
%else %if &feature=COLCONSTRAINTS %then %do;
%if %substr(&sysver,1,1)=4 %then 0;
%else 1;
%end; %end;
%else %if &feature=PROCLUA %then %do; %else %if &feature=PROCLUA %then %do;
/* https://blogs.sas.com/content/sasdummy/2015/08/03/using-lua-within-your-sas-programs */ /* https://blogs.sas.com/content/sasdummy/2015/08/03/using-lua-within-your-sas-programs */
@@ -43,5 +45,4 @@
%put &sysmacroname: &feature not found; %put &sysmacroname: &feature not found;
%end; %end;
%mend mf_existfeature; %mend mf_existfeature;
/** @endcond */
/** @endcond */

View File

@@ -33,7 +33,8 @@
%else %if %symexist(&metavar) %then %do; %else %if %symexist(&metavar) %then %do;
%if %length(&&&metavar)=0 %then %let user=&sysuserid; %if %length(&&&metavar)=0 %then %let user=&sysuserid;
/* sometimes SAS will add @domain extension - remove for consistency */ /* sometimes SAS will add @domain extension - remove for consistency */
%else %let user=%scan(&&&metavar,1,@); /* but be sure to quote in case of usernames with commas */
%else %let user=%unquote(%scan(%quote(&&&metavar),1,@));
%end; %end;
%else %let user=&sysuserid; %else %let user=&sysuserid;

View File

@@ -59,7 +59,7 @@
%goto exit_success; %goto exit_success;
%exit_err: %exit_err:
%put %str(ERR)OR: &abortmsg; %put &abortmsg;
%mf_abort(iftrue=(&mabort ne SOFT), %mf_abort(iftrue=(&mabort ne SOFT),
mac=mf_verifymacvars, mac=mf_verifymacvars,
msg=%str(&abortmsg) msg=%str(&abortmsg)

View File

@@ -85,7 +85,7 @@
%end; %end;
/* Stored Process Server web app context */ /* Stored Process Server web app context */
%if %symexist(_metaperson) %if %symexist(_METAFOLDER)
or "&SYSPROCESSNAME "="Compute Server " or "&SYSPROCESSNAME "="Compute Server "
or &mode=INCLUDE or &mode=INCLUDE
%then %do; %then %do;
@@ -161,12 +161,14 @@
/* send response in SASjs JSON format */ /* send response in SASjs JSON format */
data _null_; data _null_;
file _webout mod lrecl=32000 encoding='utf-8'; file _webout mod lrecl=32000 encoding='utf-8';
length msg $32767 ; length msg syswarningtext syserrortext $32767 ;
sasdatetime=datetime(); sasdatetime=datetime();
msg=symget('msg'); msg=symget('msg');
%if &logline>0 %then %do; %if &logline>0 %then %do;
msg=cats(msg,'\n\nLog Extract:\n',symget('logmsg')); msg=cats(msg,'\n\nLog Extract:\n',symget('logmsg'));
%end; %end;
/* escape the escapes */
msg=tranwrd(msg,'\','\\');
/* escape the quotes */ /* escape the quotes */
msg=tranwrd(msg,'"','\"'); msg=tranwrd(msg,'"','\"');
/* ditch the CRLFs as chrome complains */ /* ditch the CRLFs as chrome complains */
@@ -260,4 +262,4 @@
%end; %end;
%mend mp_abort; %mend mp_abort;
/** @endcond */ /** @endcond */

View File

@@ -106,7 +106,7 @@
proc compare proc compare
base=&scopeds(where=(upcase(name) not in (%mf_getquotedstr(&ilist)))) base=&scopeds(where=(upcase(name) not in (%mf_getquotedstr(&ilist))))
compare=&ds; compare=&ds noprint;
run; run;
%if &sysinfo=0 %then %do; %if &sysinfo=0 %then %do;

View File

@@ -94,6 +94,13 @@ data &out_ds(compress=no
%end; %end;
if rc = 0 then do; if rc = 0 then do;
did = dopen(fref); did = dopen(fref);
if did=0 then do;
putlog "NOTE: This directory is empty, or does not exist - &path";
msg=sysmsg();
put msg;
put _all_;
stop;
end;
/* attribute is OS-dependent - could be "Directory" or "Directory Name" */ /* attribute is OS-dependent - could be "Directory" or "Directory Name" */
numopts=doptnum(did); numopts=doptnum(did);
do i=1 to numopts; do i=1 to numopts;
@@ -101,12 +108,6 @@ data &out_ds(compress=no
if foption=:'Directory' then i=numopts; if foption=:'Directory' then i=numopts;
end; end;
directory=dinfo(did,foption); directory=dinfo(did,foption);
if did=0 then do;
putlog "NOTE: This directory is empty - " directory;
msg=sysmsg();
put _all_;
stop;
end;
rc = filename(fref); rc = filename(fref);
end; end;
else do; else do;
@@ -151,6 +152,7 @@ run;
data &out_ds; data &out_ds;
set &out_ds; set &out_ds;
length infoname infoval $60 fref $8; length infoname infoval $60 fref $8;
if _n_=1 then call missing(fref);
rc=filename(fref,filepath); rc=filename(fref,filepath);
drop rc infoname fid i close fref; drop rc infoname fid i close fref;
if file_or_folder='file' then do; if file_or_folder='file' then do;
@@ -242,4 +244,4 @@ run;
proc sql; proc sql;
drop table &out_ds; drop table &out_ds;
%mend mp_dirlist; %mend mp_dirlist;

View File

@@ -48,6 +48,7 @@
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@cond
**/ **/
%macro mp_ds2cards(base_ds=, tgt_ds= %macro mp_ds2cards(base_ds=, tgt_ds=
@@ -219,7 +220,8 @@ data _null_;
put ' @file'; put ' @file';
put " @brief Datalines for %upcase(%scan(&base_ds,2)) dataset"; put " @brief Datalines for %upcase(%scan(&base_ds,2)) dataset";
put " @details Generated by %nrstr(%%)mp_ds2cards()"; put " @details Generated by %nrstr(%%)mp_ds2cards()";
put " Available on github.com/sasjs/core"; put " Source: https://github.com/sasjs/core";
put ' @cond ';
put '**/'; put '**/';
put "data &tgt_ds &indexes;"; put "data &tgt_ds &indexes;";
put "attrib "; put "attrib ";
@@ -264,6 +266,7 @@ data _null_;
if __lastobs then do; if __lastobs then do;
put ';;;;'; put ';;;;';
put 'run;'; put 'run;';
put '/** @endcond **/';
stop; stop;
end; end;
run; run;
@@ -283,4 +286,5 @@ quit;
%put NOTE-;%put NOTE-; %put NOTE-;%put NOTE-;
%put NOTE- %sysfunc(dequote(&cards_file.)); %put NOTE- %sysfunc(dequote(&cards_file.));
%put NOTE-;%put NOTE-; %put NOTE-;%put NOTE-;
%mend mp_ds2cards; %mend mp_ds2cards;
/** @endcond **/

View File

@@ -55,7 +55,8 @@
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local engine schema ds1 ds2 ds3 dsn tabs1 tabs2 sum pk4sure pkdefault finalpks; %local engine schema ds1 ds2 ds3 dsn tabs1 tabs2 sum pk4sure pkdefault finalpks
pkfromindex;
%let lib=%upcase(&lib); %let lib=%upcase(&lib);
%let ds=%upcase(&ds); %let ds=%upcase(&ds);
@@ -70,6 +71,7 @@
%let sum=%mf_getuniquename(prefix=getpk_sum); %let sum=%mf_getuniquename(prefix=getpk_sum);
%let pk4sure=%mf_getuniquename(prefix=getpk_pk4sure); %let pk4sure=%mf_getuniquename(prefix=getpk_pk4sure);
%let pkdefault=%mf_getuniquename(prefix=getpk_pkdefault); %let pkdefault=%mf_getuniquename(prefix=getpk_pkdefault);
%let pkfromindex=%mf_getuniquename(prefix=getpk_pkfromindex);
%let finalpks=%mf_getuniquename(prefix=getpk_finalpks); %let finalpks=%mf_getuniquename(prefix=getpk_finalpks);
%local dbg; %local dbg;
@@ -180,9 +182,23 @@ create table &ds1 as
and a.constraint_name=b.constraint_name and a.constraint_name=b.constraint_name
order by 1,2,3,4; order by 1,2,3,4;
/* extract cols from the relevant unique INDEXES */
create table &pkfromindex as
select libname as libref
,memname as table_name
,indxname as constraint_name
,indxpos as constraint_order
,name
from dictionary.indexes
where nomiss='yes' and unique='yes' and upcase(libname)="&lib"
%if &ds ne 0 %then %do;
and upcase(memname)="&ds"
%end;
order by 1,2,3,4;
/* create one table */ /* create one table */
data &finalpks; data &finalpks;
set &pkdefault &pk4sure ; set &pkdefault &pk4sure &pkfromindex;
pk_ind=1; pk_ind=1;
/* if there are multiple unique constraints, take the first */ /* if there are multiple unique constraints, take the first */
by libref table_name constraint_name; by libref table_name constraint_name;
@@ -256,4 +272,4 @@ create table &outds as
iftrue=(&mdebug=0) iftrue=(&mdebug=0)
) )
%mend mp_getpk; %mend mp_getpk;

View File

@@ -1,8 +1,8 @@
/** /**
@file @file
@brief Returns a unique hash for a dataset @brief Returns a unique hash for a dataset
@details Ignores metadata attributes, used only to hash values. Compared @details Ignores metadata attributes, used only to hash values. If used to
datasets must be in the same order. compare datasets, they must have their columns and rows in the same order.
%mp_hashdataset(sashelp.class,outds=myhash) %mp_hashdataset(sashelp.class,outds=myhash)
@@ -17,13 +17,16 @@
@li mf_getattrn.sas @li mf_getattrn.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_getvarlist.sas @li mf_getvarlist.sas
@li mf_getvartype.sas @li mp_md5.sas
<h4> Related Files </h4>
@li mp_hashdataset.test.sas
@param [in] libds dataset to hash @param [in] libds dataset to hash
@param [in] salt= Provide a salt (could be, for instance, the dataset name) @param [in] salt= Provide a salt (could be, for instance, the dataset name)
@param [in] iftrue= A condition under which the macro should be executed. @param [in] iftrue= A condition under which the macro should be executed.
@param [out] outds= (work.mf_hashdataset) The output dataset to create. This @param [out] outds= (work.mf_hashdataset) The output dataset to create. This
will contain one column (hashkey) with one observation (a hex32. will contain one column (hashkey) with one observation (a $hex32.
representation of the input hash) representation of the input hash)
|hashkey:$32.| |hashkey:$32.|
|---| |---|
@@ -35,48 +38,48 @@
%macro mp_hashdataset( %macro mp_hashdataset(
libds, libds,
outds=, outds=work._data_,
salt=, salt=,
iftrue=%str(1=1) iftrue=%str(1=1)
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%if not(%eval(%unquote(&iftrue))) %then %return; %local keyvar /* roll up the md5 */
prevkeyvar /* retain prev record md5 */
lastvar /* last var in input ds */
cvars nvars;
%if %mf_getattrn(&libds,NLOBS)=0 %then %do; %if not(%eval(%unquote(&iftrue))) %then %return;
%put %str(WARN)ING: Dataset &libds is empty, or is not a dataset;
%end; /* avoid naming conflict for hash key vars */
%else %if %mf_getattrn(&libds,NLOBS)<0 %then %do; %let keyvar=%mf_getuniquename();
%put %str(ERR)OR: Dataset &libds is not a dataset; %let prevkeyvar=%mf_getuniquename();
%end; %let lastvar=%mf_getuniquename();
%else %do;
%local keyvar /* roll up the md5 */ %if %mf_getattrn(&libds,NLOBS)=0 %then %do;
prevkeyvar /* retain prev record md5 */ data &outds;
lastvar /* last var in input ds */ length hashkey $32;
varlist var i; retain hashkey "%sysfunc(md5(%str(&salt)),$hex32.)";
/* avoid naming conflict for hash key vars */ output;
%let keyvar=%mf_getuniquename(); stop;
%let prevkeyvar=%mf_getuniquename(); run;
%let lastvar=%mf_getuniquename(); %put &sysmacroname: Dataset &libds is empty, or is not a dataset;
%let varlist=%mf_getvarlist(&libds); %put &sysmacroname: hashkey of &outds is based on salt (&salt) only;
data &outds(rename=(&keyvar=hashkey) keep=&keyvar); %end;
length &prevkeyvar &keyvar $32; %else %if %mf_getattrn(&libds,NLOBS)<0 %then %do;
retain &prevkeyvar "%sysfunc(md5(%str(&salt)),$hex32.)"; %put %str(ERR)OR: Dataset &libds is not a dataset;
set &libds end=&lastvar; %end;
/* hash should include previous row */ %else %do;
&keyvar=put(md5(&prevkeyvar data &outds(rename=(&keyvar=hashkey) keep=&keyvar)/nonote2err;
/* loop every column, hashing every individual value */ length &prevkeyvar &keyvar $32;
%do i=1 %to %sysfunc(countw(&varlist)); retain &prevkeyvar "%sysfunc(md5(%str(&salt)),$hex32.)";
%let var=%scan(&varlist,&i,%str( )); set &libds end=&lastvar;
%if %mf_getvartype(&libds,&var)=C %then %do; /* hash should include previous row */
!!put(md5(trim(&var)),$hex32.) &keyvar=%mp_md5(
%end; cvars=%mf_getvarlist(&libds,typefilter=C) &prevkeyvar,
%else %do; nvars=%mf_getvarlist(&libds,typefilter=N)
!!put(md5(trim(put(&var*1,binary64.))),$hex32.) );
%end; &prevkeyvar=&keyvar;
%end; if &lastvar then output;
),$hex32.); run;
&prevkeyvar=&keyvar; %end;
if &lastvar then output; %mend mp_hashdataset;
run;
%end;
%mend mp_hashdataset;

View File

@@ -203,8 +203,15 @@
prxchange('s/'!!'0A'x!!'/\n/',-1, prxchange('s/'!!'0A'x!!'/\n/',-1,
prxchange('s/'!!'0D'x!!'/\r/',-1, prxchange('s/'!!'0D'x!!'/\r/',-1,
prxchange('s/'!!'09'x!!'/\t/',-1, prxchange('s/'!!'09'x!!'/\t/',-1,
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\\/\\\\/',-1,&&name&i) prxchange('s/\\/\\\\/',-1,&&name&i)
)))))!!'"'; ))))))))))))!!'"';
%end; %end;
%end; %end;
run; run;

View File

@@ -40,13 +40,13 @@
@li mp_abort.sas @li mp_abort.sas
@li mp_cntlout.sas @li mp_cntlout.sas
@li mp_lockanytable.sas @li mp_lockanytable.sas
@li mp_storediffs.sas
<h4> Related Macros </h4> <h4> Related Macros </h4>
@li mddl_dc_difftable.sas @li mddl_dc_difftable.sas
@li mddl_dc_locktable.sas @li mddl_dc_locktable.sas
@li mp_loadformat.test.sas @li mp_loadformat.test.sas
@li mp_lockanytable.sas @li mp_lockanytable.sas
@li mp_storediffs.sas
@li mp_stackdiffs.sas @li mp_stackdiffs.sas
@@ -134,7 +134,7 @@ run;
* First, extract only relevant formats from the catalog * First, extract only relevant formats from the catalog
*/ */
proc sql noprint; proc sql noprint;
select distinct fmtname into: fmtlist separated by ' ' from &libds; select distinct upcase(fmtname) into: fmtlist separated by ' ' from &libds;
%mp_cntlout(libcat=&libcat,fmtlist=&fmtlist,cntlout=&base_fmts) %mp_cntlout(libcat=&libcat,fmtlist=&fmtlist,cntlout=&base_fmts)
@@ -144,8 +144,11 @@ select distinct fmtname into: fmtlist separated by ' ' from &libds;
*/ */
%mddl_sas_cntlout(libds=&template) %mddl_sas_cntlout(libds=&template)
data &inlibds; data &inlibds;
length &delete_col $3;
if 0 then set &template; if 0 then set &template;
set &libds; set &libds;
if &delete_col='' then &delete_col='No';
fmtname=upcase(fmtname);
if missing(type) then do; if missing(type) then do;
if substr(fmtname,1,1)='$' then type='C'; if substr(fmtname,1,1)='$' then type='C';
else type='N'; else type='N';
@@ -156,7 +159,6 @@ data &inlibds;
end; end;
run; run;
/** /**
* Identify new records * Identify new records
*/ */
@@ -263,7 +265,7 @@ options ibufsize=&ibufsize;
%end; %end;
%mp_storediffs(&libcat-FC %mp_storediffs(&libcat-FC
,&inlibds ,&base_fmts
,FMTNAME START ,FMTNAME START
,delds=&outds_del ,delds=&outds_del
,modds=&outds_mod ,modds=&outds_mod
@@ -272,6 +274,9 @@ options ibufsize=&ibufsize;
,mdebug=&mdebug ,mdebug=&mdebug
) )
proc append base=&auditlibds data=&storediffs;
run;
%if &locklibds ne 0 %then %do; %if &locklibds ne 0 %then %do;
%mp_lockanytable(UNLOCK %mp_lockanytable(UNLOCK
,lib=%scan(&auditlibds,1,.) ,lib=%scan(&auditlibds,1,.)
@@ -295,4 +300,4 @@ options ibufsize=&ibufsize;
%put &sysmacroname exit vars:; %put &sysmacroname exit vars:;
%put _local_; %put _local_;
%end; %end;
%mend mp_loadformat; %mend mp_loadformat;

View File

@@ -54,5 +54,5 @@ put(md5(
&sep put(md5(trim(put(ifn(missing(&var),&var,&var*1),binary64.))),$hex32.) &sep put(md5(trim(put(ifn(missing(&var),&var,&var*1),binary64.))),$hex32.)
%let sep=!!; %let sep=!!;
%end; %end;
),hex32.) ),$hex32.)
%mend mp_md5; %mend mp_md5;

View File

@@ -70,7 +70,7 @@ filename &inref &infile lrecl=1 recfm=n;
data &ds1; data &ds1;
infile &inref; infile &inref;
input sourcechar $ 1. @@; input sourcechar $char1. @@;
format sourcechar hex2.; format sourcechar hex2.;
run; run;

View File

@@ -105,12 +105,20 @@ run;
%end; %end;
%end; %end;
%else %if &contentype=HTML %then %do; %else %if &contentype=HTML %then %do;
%if &platform=SASVIYA %then %do; %if (&platform=SASMETA and &streamweb=1) %then %do;
data _null_;
rc=stpsrv_header('Content-type','text/html');
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
run;
%end;
%else %if &platform=SASVIYA %then %do;
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json" filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
contenttype="text/html"; contenttype="text/html"
contentdisp="attachment; filename=&outname";
%end; %end;
%else %if &platform=SASJS %then %do; %else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type,text/html) %mfs_httpheader(Content-type,text/html)
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
%end; %end;
%end; %end;
%else %if &contentype=TEXT %then %do; %else %if &contentype=TEXT %then %do;

View File

@@ -13,8 +13,8 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.sas
@param libref the libref (not name) of the metadata library @param [in] libref The libref (not name) of the metadata library
@param mAbort= If not assigned, HARD will call %mp_abort(), SOFT will @param [in] mAbort= If not assigned, HARD will call %mp_abort(), SOFT will
silently return silently return
@returns libname statement @returns libname statement
@@ -28,11 +28,11 @@
libref libref
,mAbort=HARD ,mAbort=HARD
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local mp_abort msg;
%let mp_abort=0;
%if %sysfunc(libref(&libref)) %then %do; %if %sysfunc(libref(&libref)) %then %do;
%local mp_abort msg; %let mp_abort=0;
data _null_; data _null_;
length liburi LibName $200; length liburi LibName msg $200;
call missing(of _all_); call missing(of _all_);
nobj=metadata_getnobj("omsobj:SASLibrary?@Libref='&libref'",1,liburi); nobj=metadata_getnobj("omsobj:SASLibrary?@Libref='&libref'",1,liburi);
if nobj=1 then do; if nobj=1 then do;
@@ -46,7 +46,24 @@
* not always helpful though. One example, previously received: * not always helpful though. One example, previously received:
* NOTE: Libref XX refers to the same library metadata as libref XX. * NOTE: Libref XX refers to the same library metadata as libref XX.
*/ */
call symputx('msg',sysmsg(),'l'); msg=sysmsg();
if msg=:'ERROR: Libref SAVE is not assigned.' then do;
msg=catx(" ",
"Could not assign %upcase(&libref).",
"Please check metadata permissions! Libname:",libname,
"Liburi:",liburi
);
end;
else if msg="ERROR: User does not have appropriate authorization "!!
"level for library SAVE."
then do;
msg=catx(" ",
"ERROR: User does not have appropriate authorization level",
"for library %upcase(&libref), libname:",libname,
"Liburi:",liburi
);
end;
call symputx('msg',msg,'l');
if "&mabort"='HARD' then call symputx('mp_abort',1,'l'); if "&mabort"='HARD' then call symputx('mp_abort',1,'l');
end; end;
else do; else do;
@@ -65,20 +82,16 @@
end; end;
run; run;
%if &mp_abort=1 %then %do; %put NOTE: &msg;
%mp_abort(iftrue= (&mp_abort=1)
,mac=mm_assignlib.sas
,msg=&msg
)
%return;
%end;
%else %if %length(&msg)>2 %then %do;
%put NOTE: &msg;
%return;
%end;
%end; %end;
%else %do; %else %do;
%put NOTE: Library &libref is already assigned; %put NOTE: Library &libref is already assigned;
%end; %end;
%mp_abort(iftrue= (&mp_abort=1)
,mac=mm_assignlib.sas
,msg=%superq(msg)
)
%mend mm_assignlib; %mend mm_assignlib;

View File

@@ -236,8 +236,15 @@ data _null_;
put ' prxchange(''s/''!!''0A''x!!''/\n/'',-1, '; put ' prxchange(''s/''!!''0A''x!!''/\n/'',-1, ';
put ' prxchange(''s/''!!''0D''x!!''/\r/'',-1, '; put ' prxchange(''s/''!!''0D''x!!''/\r/'',-1, ';
put ' prxchange(''s/''!!''09''x!!''/\t/'',-1, '; put ' prxchange(''s/''!!''09''x!!''/\t/'',-1, ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) '; put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) ';
put ' )))))!!''"''; '; put ' ))))))))))))!!''"''; ';
put ' %end; '; put ' %end; ';
put ' %end; '; put ' %end; ';
put ' run; '; put ' run; ';
@@ -421,14 +428,16 @@ data _null_;
put ' put '',"_METAPERSON": '' _METAPERSON; '; put ' put '',"_METAPERSON": '' _METAPERSON; ';
put ' put '',"_PROGRAM" : '' _PROGRAM ; '; put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
put ' put ",""SYSCC"" : ""&syscc"" "; '; put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; '; put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; '; put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; '; put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; '; put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
put ' put ",""SYSSITE"" : ""&syssite"" "; '; put ' put ",""SYSSITE"" : ""&syssite"" "; ';
put ' sysvlong=quote(trim(symget(''sysvlong''))); '; put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
put ' put '',"SYSVLONG" : '' sysvlong; '; put ' put '',"SYSVLONG" : '' sysvlong; ';
put ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; '; put ' syswarningtext=quote(cats(symget(''SYSWARNINGTEXT''))); ';
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; '; put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
put ' length memsize $32; '; put ' length memsize $32; ';
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; '; put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
@@ -453,7 +462,8 @@ data _null_;
put ' %else %if %symexist(&metavar) %then %do; '; put ' %else %if %symexist(&metavar) %then %do; ';
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; '; put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
put ' /* sometimes SAS will add @domain extension - remove for consistency */ '; put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
put ' %else %let user=%scan(&&&metavar,1,@); '; put ' /* but be sure to quote in case of usernames with commas */ ';
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
put ' %end; '; put ' %end; ';
put ' %else %let user=&sysuserid; '; put ' %else %let user=&sysuserid; ';
put ' '; put ' ';

View File

@@ -78,6 +78,7 @@ filename &fname2 clear;
%local isgone; %local isgone;
data _null_; data _null_;
length type uri $256; length type uri $256;
call missing (of _all_);
rc=metadata_resolve("omsobj:SASLibrary?@Id='&liburi'",type,uri); rc=metadata_resolve("omsobj:SASLibrary?@Id='&liburi'",type,uri);
call symputx('isgone',type,'l'); call symputx('isgone',type,'l');
run; run;

View File

@@ -49,20 +49,25 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mf_getuniquename.sas
@li mf_isblank.sas
@li mf_loc.sas @li mf_loc.sas
@li mm_tree.sas @li mm_tree.sas
@li mf_getuniquefileref.sas
@li mf_isblank.sas
@li mp_abort.sas @li mp_abort.sas
@param metaloc= the metadata folder to export
@param secureref= fileref containing the username / password (should point to @param [in] metaloc= the metadata folder to export
a file in a secure location). Leave blank to substitute $bash type vars. @param [in] secureref= fileref containing the username / password (should
@param outref= fileref to which to write the command point to a file in a secure location). Leave blank to substitute $bash vars.
@param cmdoutloc= the directory to which the command will write the SPK @param [in] excludevars= (0) A space seperated list of macro variable names,
(default=WORK) each of which contains a value that should be used to filter the output
@param cmdoutname= the name of the spk / log files to create (will be objects.
identical just with .spk or .log extension) @param [out] outref= fileref to which to write the command
@param [out] cmdoutloc= (%sysfunc(pathname(work))) The directory to which the
command will write the SPK
@param [out] cmdoutname= (mmxport) The name of the spk / log files to create
(will be identical just with .spk or .log extension)
@version 9.4 @version 9.4
@author Allan Bowe @author Allan Bowe
@@ -71,6 +76,7 @@
%macro mm_spkexport(metaloc= %macro mm_spkexport(metaloc=
,secureref= ,secureref=
,excludevars=0
,outref= ,outref=
,cmdoutloc=%sysfunc(pathname(work)) ,cmdoutloc=%sysfunc(pathname(work))
,cmdoutname=mmxport ,cmdoutname=mmxport
@@ -82,7 +88,7 @@
%end; %end;
/* set creds */ /* set creds */
%local mmxuser mmxpath; %local mmxuser mmxpath i var;
%let mmxuser=$1; %let mmxuser=$1;
%let mmxpass=$2; %let mmxpass=$2;
%if %mf_isblank(&secureref)=0 %then %do; %if %mf_isblank(&secureref)=0 %then %do;
@@ -90,35 +96,51 @@
%end; %end;
/* setup metadata connection options */ /* setup metadata connection options */
%local host port platform_object_path connx_string; %local host port platform_object_path ds;
%let host=%sysfunc(getoption(metaserver)); %let host=%sysfunc(getoption(metaserver));
%let port=%sysfunc(getoption(metaport)); %let port=%sysfunc(getoption(metaport));
%let platform_object_path=%mf_loc(POF); %let platform_object_path=%mf_loc(POF);
%let ds=%mf_getuniquename(prefix=spkexportable);
%let connx_string=%str(-host &host -port &port -user &mmxuser %trim( %mm_tree(root=%str(&metaloc),types=EXPORTABLE ,outds=&ds)
)-password &mmxpass);
%mm_tree(root=%str(&metaloc) ,types=EXPORTABLE ,outds=exportable)
%if %mf_isblank(&outref)=1 %then %let outref=%mf_getuniquefileref(); %if %mf_isblank(&outref)=1 %then %let outref=%mf_getuniquefileref();
data _null_; data _null_;
set exportable end=last; set &ds end=last;
file &outref lrecl=32767; file &outref lrecl=32767;
length str $32767; length str $32767;
if _n_=1 then do; if _n_=1 then do;
put "# Script generated by &sysuserid on %sysfunc(datetime(),datetime19.)";
put "cd ""&platform_object_path"" \"; put "cd ""&platform_object_path"" \";
put "; ./ExportPackage &connx_string -disableX11 \"; put "; ./ExportPackage -host &host -port &port -user &mmxuser \";
put " -package ""&cmdoutloc/&cmdoutname..spk"" \"; put " -disableX11 -password &mmxpass \";
put " -package ""&cmdoutloc/&cmdoutname..spk"" \";
end; end;
/* exclude particular patterns from the exported SPK */
%if "&excludevars" ne "0" %then %do;
%do i=1 %to %sysfunc(countw(&excludevars));
%let var=%scan(&excludevars,&i);
if _n_=1 then do;
length excludestr&i $1000;
retain excludestr&i;
excludestr&i=symget("&var");
putlog excludestr&i=;
putlog path=;
end;
if index(path,cats(excludestr&i))=0 and index(name,cats(excludestr&i))=0;
%end;
/* ignore top level folder else all subcontent will be exported regardless */
if _n_>1;
%end;
str=' -objects '!!cats('"',path,'/',name,"(",publictype,')" \'); str=' -objects '!!cats('"',path,'/',name,"(",publictype,')" \');
put str; put str;
if last then put " -log ""&cmdoutloc/&cmdoutname..log"" 2>&1 "; if last then put " -log ""&cmdoutloc/&cmdoutname..log"" 2>&1 ";
run; run;
%mp_abort(iftrue= (&syscc ne 0) %mp_abort(iftrue= (&syscc ne 0)
,mac=&sysmacroname ,mac=mm_spkexport
,msg=%str(syscc=&syscc) ,msg=%str(syscc=&syscc)
) )
%mend mm_spkexport; %mend mm_spkexport;

View File

@@ -157,14 +157,16 @@
put ',"_METAPERSON": ' _METAPERSON; put ',"_METAPERSON": ' _METAPERSON;
put ',"_PROGRAM" : ' _PROGRAM ; put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSERRORTEXT"" : ""&syserrortext"" "; syserrortext=quote(cats(symget('SYSERRORTEXT')));
put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSJOBID"" : ""&sysjobid"" "; put ",""SYSJOBID"" : ""&sysjobid"" ";
put ",""SYSSCPL"" : ""&sysscpl"" "; put ",""SYSSCPL"" : ""&sysscpl"" ";
put ",""SYSSITE"" : ""&syssite"" "; put ",""SYSSITE"" : ""&syssite"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; syswarningtext=quote(cats(symget('SYSWARNINGTEXT')));
put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length memsize $32; length memsize $32;
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";

2450
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -26,14 +26,16 @@
"homepage": "https://core.sasjs.io", "homepage": "https://core.sasjs.io",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "sasjs cbd -t viya", "build": "sasjs cbd -t server",
"docs": "sasjs doc -t docsonly && ./sasjs/utils/build.sh", "docs": "sasjs doc -t docsonly && ./sasjs/utils/build.sh",
"test": "sasjs test -t viya", "test": "sasjs test -t server",
"lint": "sasjs lint", "lint": "sasjs 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"
}, },
"devDependencies": { "devDependencies": {
"@sasjs/cli": "3.6.0", "@sasjs/cli": "3.13.0"
"@sasjs/core": "4.4.7" },
"dependencies": {
"@sasjs/core": "^4.18.13"
} }
} }

View File

@@ -4,11 +4,8 @@
"base", "base",
"ddl", "ddl",
"fcmp", "fcmp",
"meta",
"metax",
"server",
"viya",
"lua", "lua",
"server",
"tests/crossplatform", "tests/crossplatform",
"tests/ddl" "tests/ddl"
], ],
@@ -28,25 +25,20 @@
"mcTestAppLoc": "/Public/temp/macrocore" "mcTestAppLoc": "/Public/temp/macrocore"
} }
}, },
"defaultTarget": "viya", "defaultTarget": "server",
"targets": [ "targets": [
{ {
"name": "viya", "name": "viya",
"serverUrl": "https://sas.analytium.co.uk", "serverUrl": "",
"serverType": "SASVIYA", "serverType": "SASVIYA",
"httpsAgentOptions": { "httpsAgentOptions": {
"allowInsecureRequests": false "allowInsecureRequests": false
}, },
"appLoc": "/Public/temp/macrocore", "appLoc": "/Public/app/macrocore",
"macroFolders": [ "macroFolders": [
"viya",
"tests/viyaonly" "tests/viyaonly"
], ],
"programFolders": [],
"binaryFolders": [],
"deployConfig": {
"deployServicePack": true,
"deployScripts": []
},
"contextName": "SAS Job Execution compute context" "contextName": "SAS Job Execution compute context"
}, },
{ {
@@ -58,6 +50,8 @@
}, },
"appLoc": "/Shared Data/temp/macrocore", "appLoc": "/Shared Data/temp/macrocore",
"macroFolders": [ "macroFolders": [
"meta",
"metax",
"tests/sas9only" "tests/sas9only"
], ],
"programFolders": [], "programFolders": [],
@@ -78,6 +72,7 @@
}, },
"appLoc": "/sasjs/core", "appLoc": "/sasjs/core",
"macroFolders": [ "macroFolders": [
"server",
"tests/serveronly" "tests/serveronly"
], ],
"programFolders": [], "programFolders": [],
@@ -92,6 +87,10 @@
"serverType": "SAS9", "serverType": "SAS9",
"appLoc": "dummy", "appLoc": "dummy",
"macroFolders": [ "macroFolders": [
"meta",
"metax",
"server",
"viya",
"tests/sas9only", "tests/sas9only",
"tests/viyaonly" "tests/viyaonly"
] ]
@@ -102,6 +101,7 @@
"serverType": "SASVIYA", "serverType": "SASVIYA",
"appLoc": "/Public/temp/macrocore", "appLoc": "/Public/temp/macrocore",
"macroFolders": [ "macroFolders": [
"viya",
"tests/viyaonly" "tests/viyaonly"
], ],
"deployConfig": { "deployConfig": {
@@ -110,4 +110,4 @@
"contextName": "SAS Job Execution compute context" "contextName": "SAS Job Execution compute context"
} }
] ]
} }

View File

@@ -29,9 +29,10 @@
,mdebug=0 ,mdebug=0
); );
%local fname0 fname1 boundary fname statcd msg; %local fname0 fname1 fname2 boundary fname statcd msg;
%let fname0=%mf_getuniquefileref(); %let fname0=%mf_getuniquefileref();
%let fname1=%mf_getuniquefileref(); %let fname1=%mf_getuniquefileref();
%let fname2=%mf_getuniquefileref();
%let boundary=%mf_getuniquename(); %let boundary=%mf_getuniquename();
data _null_; data _null_;
@@ -55,17 +56,25 @@ data _null_;
end; end;
run; run;
data _null_;
file &fname1;
put "Content-Type: multipart/form-data; boundary=&boundary";
run;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
data _null_; data _null_;
infile &fname0; infile &fname0;
input; input;
put _infile_; put _infile_;
data _null_;
infile &fname1;
input;
put _infile_;
run; run;
%end; %end;
proc http method='POST' in=&fname0 out=&fname1 proc http method='POST' in=&fname0 headerin=&fname1 out=&fname2
url="&_sasjs_apiserverurl/SASjsApi/drive/file"; url="&_sasjs_apiserverurl/SASjsApi/drive/file";
headers "Content-Type"="multipart/form-data; boundary=&boundary";
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
debug level=1; debug level=1;
%end; %end;
@@ -73,7 +82,7 @@ run;
%let statcd=0; %let statcd=0;
data _null_; data _null_;
infile &fname1; infile &fname2;
input; input;
putlog _infile_; putlog _infile_;
if _infile_='{"status":"success"}' then call symputx('statcd',1,'l'); if _infile_='{"status":"success"}' then call symputx('statcd',1,'l');

35
server/ms_deletefile.sas Normal file
View File

@@ -0,0 +1,35 @@
/**
@file
@brief Deletes a file from SASjs Drive
@details Deletes a file from SASjs Drive, if it exists.
Example:
filename stpcode temp;
data _null_;
file stpcode;
put '%put hello world;';
run;
%ms_createfile(/some/stored/program.sas, inref=stpcode)
%ms_deletefile(/some/stored/program.sas)
@param [in] driveloc The full path to the file in SASjs Drive
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
**/
%macro ms_deletefile(driveloc
,mdebug=0
);
proc http method='DELETE'
url="&_sasjs_apiserverurl/SASjsApi/drive/file?_filePath=&driveloc";
%if &mdebug=1 %then %do;
debug level=2;
%end;
run;
%mend ms_deletefile;

View File

@@ -11,6 +11,9 @@
@param [out] outref= (msgetfil) The fileref to contain the file. @param [out] outref= (msgetfil) The fileref to contain the file.
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mf_getuniquename.sas
**/ **/
@@ -19,14 +22,20 @@
,mdebug=0 ,mdebug=0
); );
filename &outref temp; /* use the recfm in a separate fileref to avoid issues with subsequent reads */
%local binaryfref floc;
%let binaryfref=%mf_getuniquefileref();
%let floc=%sysfunc(pathname(work))/%mf_getuniquename().txt;
filename &outref "&floc";
filename &binaryfref "&floc" recfm=n;
proc http method='GET' out=&outref proc http method='GET' out=&binaryfref
url="&_sasjs_apiserverurl/SASjsApi/drive/file?filePath=&driveloc"; url="&_sasjs_apiserverurl/SASjsApi/drive/file?_filePath=&driveloc";
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
debug level=2; debug level=2;
%end; %end;
run; run;
filename &binaryfref clear;
%mend ms_getfile; %mend ms_getfile;

View File

@@ -1,6 +1,6 @@
/** /**
@file @file
@brief Send data to/from @sasjs/server @brief Send data to/from sasjs/server
@details This macro should be added to the start of each web service, @details This macro should be added to the start of each web service,
**immediately** followed by a call to: **immediately** followed by a call to:
@@ -114,6 +114,7 @@
data _null_; data _null_;
set &tempds; set &tempds;
if not (upcase(name) =:"DATA"); /* ignore temp datasets */ if not (upcase(name) =:"DATA"); /* ignore temp datasets */
if not (upcase(name)=:"_DATA_");
i+1; i+1;
call symputx(cats('wt',i),name,'l'); call symputx(cats('wt',i),name,'l');
call symputx('wtcnt',i,'l'); call symputx('wtcnt',i,'l');
@@ -146,7 +147,8 @@
put ",""_DEBUG"" : ""&_debug"" "; put ",""_DEBUG"" : ""&_debug"" ";
put ',"_PROGRAM" : ' _PROGRAM ; put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSERRORTEXT"" : ""&syserrortext"" "; syserrortext=quote(cats(symget('SYSERRORTEXT')));
put ',"SYSERRORTEXT" : ' syserrortext;
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG'))); SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));
put ',"SYSHOSTINFOLONG" : ' SYSHOSTINFOLONG; put ',"SYSHOSTINFOLONG" : ' SYSHOSTINFOLONG;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
@@ -161,7 +163,8 @@
put ",""SYSTCPIPHOSTNAME"" : ""&SYSTCPIPHOSTNAME"" "; put ",""SYSTCPIPHOSTNAME"" : ""&SYSTCPIPHOSTNAME"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; syswarningtext=quote(cats(symget('SYSWARNINGTEXT')));
put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length autoexec $512; length autoexec $512;
autoexec=quote(urlencode(trim(getoption('autoexec')))); autoexec=quote(urlencode(trim(getoption('autoexec'))));

View File

@@ -0,0 +1,29 @@
/**
@file
@brief Testing mf_deletefile.sas macro
<h4> SAS Macros </h4>
@li mf_deletefile.sas
@li mf_writefile.sas
@li mp_assert.sas
@li mp_assertscope.sas
**/
%let test1file=&sasjswork/myfile1.txt;
%mf_writefile(&test1file,l1=some content)
%mp_assert(
iftrue=(%sysfunc(fileexist(&test1file))=1),
desc=Check &test1file exists
)
%mp_assertscope(SNAPSHOT)
%mf_deletefile(&test1file)
%mp_assertscope(COMPARE)
%mp_assert(
iftrue=(%sysfunc(fileexist(&test1file))=0),
desc=Check &test1file no longer exists
)

View File

@@ -47,4 +47,18 @@ run;
iftrue=(%mf_nobs(work.mytable3)=2), iftrue=(%mf_nobs(work.mytable3)=2),
desc=Top level returned, desc=Top level returned,
outds=work.test_results outds=work.test_results
) )
%mp_dirlist(path=&root/b, outds=work.myTable4)
%mp_assert(
iftrue=(%mf_nobs(work.mytable4)=0),
desc=Empty table for empty directory,
outds=work.test_results
)
%mp_dirlist(path=&root/notexisting, outds=work.myTable5)
%mp_assert(
iftrue=(%mf_nobs(work.mytable5)=0),
desc=Empty table for non-existing directory,
outds=work.test_results
)

View File

@@ -88,4 +88,50 @@ run;
/* constraint capture at library level is functional - uses first 2 tests */ /* constraint capture at library level is functional - uses first 2 tests */
%mp_getpk(work,outds=test4) %mp_getpk(work,outds=test4)
%mp_assertdsobs(work.test4,test=ATLEAST 2) %mp_assertdsobs(work.test4,test=ATLEAST 2)
/* unique & not null INDEX captured */
proc sql;
create table work.example5(
TX_FROM float format=datetime19.,
DD_TYPE char(16),
DD_SOURCE char(2048),
DD_SHORTDESC char(256)
);
proc datasets lib=work noprint;
modify example5;
index create tx_from /nomiss unique;
quit;
%mp_getpk(work,ds=example5,outds=test5)
data _null_;
set work.test5;
call symputx('test5',pk_fields);
run;
%mp_assert(
iftrue=("&test5"="TX_FROM"),
desc=mp_getpk captures single column not null unique index,
outds=work.test_results
)
/* unique & not null COMPOSITE INDEX captured */
proc sql;
create table work.example6(
TX_FROM float format=datetime19.,
DD_TYPE char(16),
DD_SOURCE char(2048),
DD_SHORTDESC char(256)
);
proc datasets lib=work noprint;
modify example6;
index create pk_6=(tx_from dd_type) /nomiss unique;
quit;
%mp_getpk(work,ds=example6,outds=test6)
data _null_;
set work.test6;
call symputx('test6',pk_fields);
run;
%mp_assert(
iftrue=("&test6"="TX_FROM DD_TYPE"),
desc=mp_getpk captures multiple column not null unique index,
outds=work.test_results
)

View File

@@ -0,0 +1,61 @@
/**
@file
@brief Testing mp_hashdataset.sas macro
<h4> SAS Macros </h4>
@li mf_nobs.sas
@li mp_hashdataset.sas
@li mp_assert.sas
@li mp_assertscope.sas
**/
/* test 1 - regular DS */
data work.test;
set sashelp.vextfl;
missval=.;
misscval='';
run;
%mp_assertscope(SNAPSHOT)
%mp_hashdataset(test)
%mp_assertscope(COMPARE)
%mp_assert(
iftrue=(&syscc=0),
desc=Regular test works,
outds=work.test_results
)
%mp_hashdataset(test,outds=work.test2)
%mp_assert(
iftrue=(&syscc=0),
desc=hash with output runs without errors,
outds=work.test_results
)
%mp_assert(
iftrue=(%mf_nobs(work.test2)=1),
desc=output has 1 row,
outds=work.test_results
)
data work.test3a;
set work.test;
stop;
run;
%mp_hashdataset(test3a,outds=work.test3b)
%mp_assert(
iftrue=(&syscc=0),
desc=hash with zero-row input runs without errors,
outds=work.test_results
)
%mp_assert(
iftrue=(%mf_nobs(work.test3b)=1),
desc=test 3 output has 1 row,
outds=work.test_results
)

View File

@@ -3,6 +3,7 @@
@brief Testing mp_loadformat.sas macro @brief Testing mp_loadformat.sas macro
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mddl_dc_difftable.sas
@li mp_loadformat.sas @li mp_loadformat.sas
@li mp_assert.sas @li mp_assert.sas
@li mp_assertscope.sas @li mp_assertscope.sas
@@ -12,6 +13,8 @@
/* prep format catalog */ /* prep format catalog */
libname perm (work); libname perm (work);
%mddl_dc_difftable(libds=perm.audit)
data work.loadfmts; data work.loadfmts;
length fmtname $32; length fmtname $32;
eexcl='Y'; eexcl='Y';
@@ -49,7 +52,7 @@ run;
%mp_loadformat(perm.testcat %mp_loadformat(perm.testcat
,work.stagedata ,work.stagedata
,loadtarget=YES ,loadtarget=YES
,auditlibds=0 ,auditlibds=perm.audit
,locklibds=0 ,locklibds=0
,delete_col=deleteme ,delete_col=deleteme
,outds_add=add_test1 ,outds_add=add_test1
@@ -73,4 +76,18 @@ run;
iftrue=(%mf_nobs(mod_test1)=100), iftrue=(%mf_nobs(mod_test1)=100),
desc=Test 1 - mod obs, desc=Test 1 - mod obs,
outds=work.test_results outds=work.test_results
) )
%mp_assert(
iftrue=(%mf_nobs(perm.audit)=7329),
desc=Test 1 - audit table updated,
outds=work.test_results
)
data work.difftest;
set perm.audit;
where is_diff=1;
run;
%mp_assert(
iftrue=(%mf_nobs(work.difftest)>0),
desc=Test 1 - diffs were found,
outds=work.test_results
)

View File

@@ -63,3 +63,33 @@ run;
desc=Checking second replace 3rd row, desc=Checking second replace 3rd row,
outds=work.test_results outds=work.test_results
) )
%let test3="&sasjswork/file3.txt";
%let str=%str(replace.string.with.dots );
%let rep=%str( more.dots);
data _null_;
file &test3;
put 'blahblah';
put "blahblah&str.blah&str. replace &str.X";
put "blahbreplacewith&str.spacesahblah";
run;
%mp_replace(&test3, findvar=str, replacevar=rep)
data _null_;
infile &test3;
input;
if _n_=2 then call symputx('test3resulta',_infile_);
if _n_=3 then call symputx('test3resultb',_infile_);
run;
%mp_assert(
iftrue=("&test3resulta" = "blahblah&rep.blah&rep. replace &rep.X"),
desc=Checking third replace 2nd row (dots),
outds=work.test_results
)
%mp_assert(
iftrue=("&test3resultb" = "blahbreplacewith&rep.spacesahblah"),
desc=Checking third replace 3rd row (dots),
outds=work.test_results
)

View File

@@ -0,0 +1,41 @@
/**
@file
@brief Testing mm_webout macro
<h4> SAS Macros </h4>
@li mm_spkexport.sas
@li mp_assert.sas
@li mp_as
**/
%* create sample text file as input to the macro;
filename tmp temp;
data _null_;
file tmp;
put '%let mmxuser="sasdemo";';
put '%let mmxpass="Mars321";';
run;
filename myref "%sysfunc(pathname(work))/mmxexport.sh"
permission='A::u::rwx,A::g::r-x,A::o::---';
%mp_assertscope(SNAPSHOT)
%mm_spkexport(metaloc=%str(/Shared Data)
,outref=myref
,secureref=tmp
,cmdoutloc=%str(/tmp)
)
%mp_assertscope(COMPARE)
data _null_;
infile tmp;
input;
putlog _infile_;
call symputx('nobs',_n_);
run;
%mp_assert(
iftrue=(&nobs>2),
desc=Check if content was created
)

View File

@@ -0,0 +1,61 @@
/**
@file
@brief Testing ms_deletefile.sas macro
<h4> SAS Macros </h4>
@li ms_createfile.sas
@li ms_deletefile.sas
@li ms_getfile.sas
@li mp_assert.sas
@li mp_assertscope.sas
**/
/* first make a remote file */
filename stpcode temp;
%let fname=%mf_getuniquename();
data _null_;
file stpcode;
put "data &fname;run;";
run;
%ms_createfile(/sasjs/tests/&fname..sas
,inref=stpcode
,mdebug=1
)
%ms_getfile(/sasjs/tests/&fname..sas,outref=testref)
%let test1=0;
data _null_;
infile testref;
input;
call symputx('test1',_infile_);
run;
%mp_assert(
iftrue=("&test1"="data &fname;run;"),
desc=Make sure the file was created,
outds=work.test_results
)
%mp_assertscope(SNAPSHOT)
%ms_deletefile(/sasjs/tests/&fname..sas,mdebug=1)
%mp_assertscope(COMPARE)
%ms_getfile(/sasjs/tests/&fname..sas,outref=testref2)
%let test2=0;
data _null_;
infile testref2;
input;
call symputx('test2',_infile_);
run;
%mp_assert(
iftrue=("&test2"="%str(Err)or: File does not exist."),
desc=Make sure the file was deleted,
outds=work.test_results
)

View File

@@ -1,15 +1,33 @@
/** /**
@file @file
@brief Testing mm_webout macro @brief Testing mv_webout macro
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mv_webout.sas @li mv_webout.sas
@li mp_assert.sas @li mp_assert.sas
@li mp_assertdsobs.sas
**/ **/
/* testing FETCHing (WEB approach) */
data _null_;
call symputx('sasjs1data','area:$char4.'!!'0d0a'x!!'Adak');
call symputx('sasjs_tables','areas');
run;
%put &=sasjs1data;
%mv_webout(FETCH)
%mp_assertdsobs(work.areas,
desc=Test input table has 1 row,
test=EQUALS 1,
outds=work.test_results
)
%let fref=%mf_getuniquefileref(); %let fref=%mf_getuniquefileref();
%global _metaperson; %global _metaperson;
data some datasets; data some datasets;
@@ -38,4 +56,4 @@ run;
%mp_assert( %mp_assert(
iftrue=(%str(&checkval)=%str(&sysvlong)), iftrue=(%str(&checkval)=%str(&sysvlong)),
desc=Check if the sysvlong value was created desc=Check if the sysvlong value was created
) )

View File

@@ -380,8 +380,15 @@ data _null_;
put ' prxchange(''s/''!!''0A''x!!''/\n/'',-1, '; put ' prxchange(''s/''!!''0A''x!!''/\n/'',-1, ';
put ' prxchange(''s/''!!''0D''x!!''/\r/'',-1, '; put ' prxchange(''s/''!!''0D''x!!''/\r/'',-1, ';
put ' prxchange(''s/''!!''09''x!!''/\t/'',-1, '; put ' prxchange(''s/''!!''09''x!!''/\t/'',-1, ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) '; put ' prxchange(''s/\\/\\\\/'',-1,&&name&i) ';
put ' )))))!!''"''; '; put ' ))))))))))))!!''"''; ';
put ' %end; '; put ' %end; ';
put ' %end; '; put ' %end; ';
put ' run; '; put ' run; ';
@@ -454,7 +461,7 @@ data _null_;
put ' sasjs_tables SYS_JES_JOB_URI; '; put ' sasjs_tables SYS_JES_JOB_URI; ';
put '%if %index("&_debug",log) %then %let _debug=131; '; put '%if %index("&_debug",log) %then %let _debug=131; ';
put ' '; put ' ';
put '%local i tempds; '; 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; ';
@@ -469,60 +476,35 @@ data _null_;
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 */ ';
put ' %if %length(&sasjs_tables.XX)>2 %then %do; '; put ' %if %length(&sasjs_tables.X)>1 %then %do; ';
put ' filename _sasjs "%sysfunc(pathname(work))/sasjs.lua"; ';
put ' data _null_; ';
put ' file _sasjs; ';
put ' put ''s=sas.symget("sasjs_tables")''; ';
put ' put ''if(s:sub(1,7) == "%nrstr(")''; ';
put ' put ''then''; ';
put ' put '' tablist=s:sub(8,s:len()-1)''; ';
put ' put ''else''; ';
put ' put '' tablist=s''; ';
put ' put ''end''; ';
put ' put ''for i = 1,sas.countw(tablist) ''; ';
put ' put ''do ''; ';
put ' put '' tab=sas.scan(tablist,i)''; ';
put ' put '' sasdata=""''; ';
put ' put '' if (sas.symexist("sasjs"..i.."data0")==0)''; ';
put ' put '' then''; ';
put ' /* TODO - condense this logic */ ';
put ' put '' s=sas.symget("sasjs"..i.."data")''; ';
put ' put '' if(s:sub(1,7) == "%nrstr(")''; ';
put ' put '' then''; ';
put ' put '' sasdata=s:sub(8,s:len()-1)''; ';
put ' put '' else''; ';
put ' put '' sasdata=s''; ';
put ' put '' end''; ';
put ' put '' else''; ';
put ' put '' for d = 1, sas.symget("sasjs"..i.."data0")''; ';
put ' put '' do''; ';
put ' put '' s=sas.symget("sasjs"..i.."data"..d)''; ';
put ' put '' if(s:sub(1,7) == "%nrstr(")''; ';
put ' put '' then''; ';
put ' put '' sasdata=sasdata..s:sub(8,s:len()-1)''; ';
put ' put '' else''; ';
put ' put '' sasdata=sasdata..s''; ';
put ' put '' end''; ';
put ' put '' end''; ';
put ' put '' end''; ';
put ' put '' file = io.open(sas.pathname("work").."/"..tab..".csv", "a")''; ';
put ' put '' io.output(file)''; ';
put ' put '' io.write(sasdata)''; ';
put ' put '' io.close(file)''; ';
put ' put ''end''; ';
put ' run; ';
put ' %inc _sasjs; ';
put ' '; put ' ';
put ' /* now read in the data */ '; put ' /* convert data from macro variables to datasets */ ';
put ' %do i=1 %to %sysfunc(countw(&sasjs_tables)); '; put ' %do i=1 %to %sysfunc(countw(&sasjs_tables)); ';
put ' %local table; %let table=%scan(&sasjs_tables,&i); '; put ' %let table=%scan(&sasjs_tables,&i,%str( )); ';
put ' %if %symexist(sasjs&i.data0)=0 %then %let sasjs&i.data0=1; ';
put ' data _null_; ';
put ' file "%sysfunc(pathname(work))/&table..csv" recfm=n; ';
put ' retain nrflg 0; ';
put ' length line $32767; ';
put ' do i=1 to &&sasjs&i.data0; ';
put ' if &&sasjs&i.data0=1 then line=symget("sasjs&i.data"); ';
put ' else line=symget(cats("sasjs&i.data",i)); ';
put ' if i=1 and substr(line,1,7)=''%nrstr('' then do; ';
put ' nrflg=1; ';
put ' line=substr(line,8); ';
put ' end; ';
put ' if i=&&sasjs&i.data0 and nrflg=1 then do; ';
put ' line=substr(line,1,length(line)-1); ';
put ' end; ';
put ' put line +(-1) @; ';
put ' end; ';
put ' run; ';
put ' data _null_; '; put ' data _null_; ';
put ' infile "%sysfunc(pathname(work))/&table..csv" termstr=crlf ; '; put ' infile "%sysfunc(pathname(work))/&table..csv" termstr=crlf ; ';
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 ' list; '; put ' list; ';
put ' data &table; '; put ' data work.&table; ';
put ' infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd '; put ' infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd ';
put ' termstr=crlf; '; put ' termstr=crlf; ';
put ' input &input_statement; '; put ' input &input_statement; ';
@@ -623,13 +605,15 @@ data _null_;
put ' put ",""_DEBUG"" : ""&_debug"" "; '; put ' put ",""_DEBUG"" : ""&_debug"" "; ';
put ' put '',"_PROGRAM" : '' _PROGRAM ; '; put ' put '',"_PROGRAM" : '' _PROGRAM ; ';
put ' put ",""SYSCC"" : ""&syscc"" "; '; put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSERRORTEXT"" : ""&syserrortext"" "; '; put ' syserrortext=quote(cats(symget(''SYSERRORTEXT''))); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; '; put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
put ' put ",""SYSSCPL"" : ""&sysscpl"" "; '; put ' put ",""SYSSCPL"" : ""&sysscpl"" "; ';
put ' put ",""SYSSITE"" : ""&syssite"" "; '; put ' put ",""SYSSITE"" : ""&syssite"" "; ';
put ' sysvlong=quote(trim(symget(''sysvlong''))); '; put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
put ' put '',"SYSVLONG" : '' sysvlong; '; put ' put '',"SYSVLONG" : '' sysvlong; ';
put ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; '; put ' syswarningtext=quote(cats(symget(''SYSWARNINGTEXT''))); ';
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; '; put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
put ' length memsize $32; '; put ' length memsize $32; ';
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; '; put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
@@ -655,7 +639,8 @@ data _null_;
put ' %else %if %symexist(&metavar) %then %do; '; put ' %else %if %symexist(&metavar) %then %do; ';
put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; '; put ' %if %length(&&&metavar)=0 %then %let user=&sysuserid; ';
put ' /* sometimes SAS will add @domain extension - remove for consistency */ '; put ' /* sometimes SAS will add @domain extension - remove for consistency */ ';
put ' %else %let user=%scan(&&&metavar,1,@); '; put ' /* but be sure to quote in case of usernames with commas */ ';
put ' %else %let user=%unquote(%scan(%quote(&&&metavar),1,@)); ';
put ' %end; '; put ' %end; ';
put ' %else %let user=&sysuserid; '; put ' %else %let user=&sysuserid; ';
put ' '; put ' ';

View File

@@ -25,6 +25,7 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mp_abort.sas @li mp_abort.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_getuniquelibref.sas

View File

@@ -32,7 +32,7 @@
,grant_type=sas_services ,grant_type=sas_services
,outds=work.viyagroups ,outds=work.viyagroups
); );
%local oauth_bearer; %local oauth_bearer base_uri fname1 libref1;
%if &grant_type=detect %then %do; %if &grant_type=detect %then %do;
%if %symexist(&access_token_var) %then %let grant_type=authorization_code; %if %symexist(&access_token_var) %then %let grant_type=authorization_code;
%else %let grant_type=sas_services; %else %let grant_type=sas_services;
@@ -50,11 +50,10 @@
) )
options noquotelenmax; options noquotelenmax;
%local base_uri; /* location of rest apis */ /* location of rest apis */
%let base_uri=%mf_getplatform(VIYARESTAPI); %let base_uri=%mf_getplatform(VIYARESTAPI);
/* fetching folder details for provided path */ /* fetching folder details for provided path */
%local fname1;
%let fname1=%mf_getuniquefileref(); %let fname1=%mf_getuniquefileref();
%let libref1=%mf_getuniquelibref(); %let libref1=%mf_getuniquelibref();
@@ -78,9 +77,8 @@ data &outds;
run; run;
/* clear refs */ /* clear refs */
filename &fname1 clear; filename &fname1 clear;
libname &libref1 clear; libname &libref1 clear;
%mend mv_getgroups; %mend mv_getgroups;

View File

@@ -45,7 +45,7 @@
); );
%local dbg bufsize varcnt fname1 fname2 errmsg; %local dbg bufsize varcnt fname1 fname2 errmsg;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
%put &sysmacroname entry vars:; %put &sysmacroname local entry vars:;
%put _local_; %put _local_;
%end; %end;
%else %let dbg=*; %else %let dbg=*;
@@ -112,14 +112,21 @@ proc http method='GET' out=&fname1 &oauth_bearer
%end; %end;
; ;
run; run;
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201 %then
%do; %if &mdebug=1 %then %do;
data _null_;infile &fname1;input;putlog _infile_;run; data _null_;
%mp_abort(mac=&sysmacroname infile &fname1;
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) input;
) putlog _infile_;
run;
%end; %end;
%mp_abort(
iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
,mac=&sysmacroname
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
)
%let fname2=%mf_getuniquefileref(); %let fname2=%mf_getuniquefileref();
filename &fname2 temp ; filename &fname2 temp ;
@@ -128,7 +135,7 @@ filename &fname2 temp ;
data _null_; data _null_;
file &fname2 recfm=n; file &fname2 recfm=n;
infile &fname1 lrecl=1 recfm=n; infile &fname1 lrecl=1 recfm=n;
input sourcechar $ 1. @@; input sourcechar $char1. @@;
format sourcechar hex2.; format sourcechar hex2.;
retain startwrite 0; retain startwrite 0;
if startwrite=0 and sourcechar='"' then do; if startwrite=0 and sourcechar='"' then do;

View File

@@ -49,7 +49,7 @@
sasjs_tables SYS_JES_JOB_URI; sasjs_tables SYS_JES_JOB_URI;
%if %index("&_debug",log) %then %let _debug=131; %if %index("&_debug",log) %then %let _debug=131;
%local i tempds; %local i tempds table;
%let action=%upcase(&action); %let action=%upcase(&action);
%if &action=FETCH %then %do; %if &action=FETCH %then %do;
@@ -64,60 +64,35 @@
%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 */
%if %length(&sasjs_tables.XX)>2 %then %do; %if %length(&sasjs_tables.X)>1 %then %do;
filename _sasjs "%sysfunc(pathname(work))/sasjs.lua";
data _null_;
file _sasjs;
put 's=sas.symget("sasjs_tables")';
put 'if(s:sub(1,7) == "%nrstr(")';
put 'then';
put ' tablist=s:sub(8,s:len()-1)';
put 'else';
put ' tablist=s';
put 'end';
put 'for i = 1,sas.countw(tablist) ';
put 'do ';
put ' tab=sas.scan(tablist,i)';
put ' sasdata=""';
put ' if (sas.symexist("sasjs"..i.."data0")==0)';
put ' then';
/* TODO - condense this logic */
put ' s=sas.symget("sasjs"..i.."data")';
put ' if(s:sub(1,7) == "%nrstr(")';
put ' then';
put ' sasdata=s:sub(8,s:len()-1)';
put ' else';
put ' sasdata=s';
put ' end';
put ' else';
put ' for d = 1, sas.symget("sasjs"..i.."data0")';
put ' do';
put ' s=sas.symget("sasjs"..i.."data"..d)';
put ' if(s:sub(1,7) == "%nrstr(")';
put ' then';
put ' sasdata=sasdata..s:sub(8,s:len()-1)';
put ' else';
put ' sasdata=sasdata..s';
put ' end';
put ' end';
put ' end';
put ' file = io.open(sas.pathname("work").."/"..tab..".csv", "a")';
put ' io.output(file)';
put ' io.write(sasdata)';
put ' io.close(file)';
put 'end';
run;
%inc _sasjs;
/* now read in the data */ /* convert data from macro variables to datasets */
%do i=1 %to %sysfunc(countw(&sasjs_tables)); %do i=1 %to %sysfunc(countw(&sasjs_tables));
%local table; %let table=%scan(&sasjs_tables,&i); %let table=%scan(&sasjs_tables,&i,%str( ));
%if %symexist(sasjs&i.data0)=0 %then %let sasjs&i.data0=1;
data _null_;
file "%sysfunc(pathname(work))/&table..csv" recfm=n;
retain nrflg 0;
length line $32767;
do i=1 to &&sasjs&i.data0;
if &&sasjs&i.data0=1 then line=symget("sasjs&i.data");
else line=symget(cats("sasjs&i.data",i));
if i=1 and substr(line,1,7)='%nrstr(' then do;
nrflg=1;
line=substr(line,8);
end;
if i=&&sasjs&i.data0 and nrflg=1 then do;
line=substr(line,1,length(line)-1);
end;
put line +(-1) @;
end;
run;
data _null_; data _null_;
infile "%sysfunc(pathname(work))/&table..csv" termstr=crlf ; infile "%sysfunc(pathname(work))/&table..csv" termstr=crlf ;
input; input;
if _n_=1 then call symputx('input_statement',_infile_); if _n_=1 then call symputx('input_statement',_infile_);
list; list;
data &table; data work.&table;
infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd
termstr=crlf; termstr=crlf;
input &input_statement; input &input_statement;
@@ -218,13 +193,15 @@
put ",""_DEBUG"" : ""&_debug"" "; put ",""_DEBUG"" : ""&_debug"" ";
put ',"_PROGRAM" : ' _PROGRAM ; put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSERRORTEXT"" : ""&syserrortext"" "; syserrortext=quote(cats(symget('SYSERRORTEXT')));
put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSSCPL"" : ""&sysscpl"" "; put ",""SYSSCPL"" : ""&sysscpl"" ";
put ",""SYSSITE"" : ""&syssite"" "; put ",""SYSSITE"" : ""&syssite"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; syswarningtext=quote(cats(symget('SYSWARNINGTEXT')));
put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length memsize $32; length memsize $32;
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";