mirror of
https://github.com/sasjs/core.git
synced 2026-01-10 10:50:04 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6056b9397 | |||
|
|
00511c72c2 | ||
|
|
1d6f04fd56 | ||
| af4dbb5632 | |||
|
|
f48c291dce | ||
|
|
18be74a1c2 | ||
|
|
456d10a90e | ||
|
|
a7fdb52231 | ||
|
|
066ed00e44 | ||
|
|
49fbc210ad | ||
|
|
951aa474f2 | ||
|
|
961dd54ee0 | ||
|
|
921354dac7 | ||
|
|
48212f8797 | ||
| cb8992dade | |||
| 7dec3120be | |||
| 9568b17f20 | |||
| 0a38056c69 | |||
|
|
096bf4fa11 | ||
|
|
030c4a4fc1 |
@@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# A hook script to verify that no filenames with capital letters are committed.
|
||||
# Called by "git commit" with no arguments. The hook should
|
||||
# exit with non-zero status after issuing an appropriate message if
|
||||
# it wants to stop the commit.
|
||||
#
|
||||
# Go through all the changed files (except for deleted and unmerged)
|
||||
|
||||
# Save exit code of last executed action
|
||||
exit_code=0
|
||||
|
||||
# Check if file is one of SAS|DDL|CSV|SH and check for uppercase letters
|
||||
mime_pattern="\.(sas|ddl|csv|sh)"
|
||||
# Check for capital letters only in file names
|
||||
extra_pattern="(^|/)[^/]*([A-Z]+)[^/]*\.[A-Za-z]{3}$"
|
||||
# Grep git diff of files to commit
|
||||
files=$( git diff --cached --find-copies --find-renames --name-only --diff-filter=ACMRTXBU |
|
||||
grep -Ei "$mime_pattern" |
|
||||
grep -E "$extra_pattern" )
|
||||
echo "$files"
|
||||
if [[ -n "$files" ]];
|
||||
then
|
||||
echo
|
||||
echo "Found files that contain capital letters."
|
||||
echo "Please rename the following files in lowercase, and commit again:"
|
||||
|
||||
for file in $files; do
|
||||
echo -e '- \E[0;32m'"$file"'\033[0m'
|
||||
done
|
||||
# Abort commit
|
||||
exit_code=1
|
||||
fi
|
||||
|
||||
if [ "$exit_code" == "0" ]; then
|
||||
echo
|
||||
echo -e '\033[1m'"Pre-commit validation Passed"'\033[0m'
|
||||
echo
|
||||
else
|
||||
echo
|
||||
echo -e '\033[1m'"Commit Aborted!"'\033[0m'
|
||||
echo
|
||||
fi
|
||||
exit $exit_code
|
||||
@@ -1,10 +1,6 @@
|
||||
|
||||
FROM gitpod/workspace-full
|
||||
|
||||
RUN sudo apt-get update \
|
||||
&& sudo apt-get install -y \
|
||||
doxygen \
|
||||
&& npm i -g npm@latest \
|
||||
&& npm i -g @sasjs/cli \
|
||||
&& npm i \
|
||||
&& sudo rm -rf /var/lib/apt/lists/*
|
||||
@@ -1,8 +1,8 @@
|
||||
tasks:
|
||||
- init: npm i && clear
|
||||
- init: npm i -g @sasjs/cli
|
||||
|
||||
image:
|
||||
file: .gitpod.dockerfile
|
||||
vscode:
|
||||
extensions:
|
||||
- sasjs.sasjs-for-vscode@1.6.0:V4hJpMtbpekMcPRNhh4SXQ==
|
||||
- sasjs.sasjs-for-vscode
|
||||
|
||||
13
.sasjslint
Normal file
13
.sasjslint
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"noTrailingSpaces": true,
|
||||
"noEncodedPasswords": true,
|
||||
"hasDoxygenHeader": true,
|
||||
"hasMacroNameInMend": false,
|
||||
"hasMacroParentheses": true,
|
||||
"noNestedMacros": false,
|
||||
"noSpacesInFileNames": true,
|
||||
"maxLineLength": 135,
|
||||
"lowerCaseFileNames": true,
|
||||
"noTabIndentation": true,
|
||||
"indentationMultiple": 2
|
||||
}
|
||||
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"sasjs.sasjs-for-vscode"
|
||||
]
|
||||
}
|
||||
@@ -118,7 +118,7 @@ All macros must be commented in the doxygen format, to enable the [online docume
|
||||
### Dependencies
|
||||
SAS code can contain one of two types of dependency - SAS Macros, and SAS Programs. When compiling projects using the [SASjs CLI](https://cli.sasjs.io) the doxygen header is scanned for ` @li` items under the following headers:
|
||||
|
||||
```
|
||||
```sas
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_nobs.sas
|
||||
@li mm_assignlib.sas
|
||||
|
||||
@@ -49,7 +49,10 @@
|
||||
input; putlog _infile_;
|
||||
i=1;
|
||||
retain logonce 0;
|
||||
if (_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR") and logonce=0 then do;
|
||||
if (
|
||||
_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR"
|
||||
) and logonce=0
|
||||
then do;
|
||||
call symputx('logline',_n_);
|
||||
logonce+1;
|
||||
end;
|
||||
@@ -112,7 +115,8 @@
|
||||
%let syscc=0;
|
||||
%if %symexist(SYS_JES_JOB_URI) %then %do;
|
||||
/* refer web service output to file service in one hit */
|
||||
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json";
|
||||
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI"
|
||||
name="_webout.json";
|
||||
%let rc=%sysfunc(fcopy(_web,_webout));
|
||||
%end;
|
||||
%else %do;
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
/* in case the parameter is a libref.tablename, pull off just the libref */
|
||||
%let libref = %upcase(%scan(&libref, 1, %str(.)));
|
||||
|
||||
%let dsid=%sysfunc(open(sashelp.vlibnam(where=(libname="%upcase(&libref)")),i));
|
||||
%let dsid=%sysfunc(
|
||||
open(sashelp.vlibnam(where=(libname="%upcase(&libref)")),i)
|
||||
);
|
||||
%if (&dsid ^= 0) %then %do;
|
||||
%let engnum=%sysfunc(varnum(&dsid,ENGINE));
|
||||
%let rc=%sysfunc(fetch(&dsid));
|
||||
|
||||
@@ -27,21 +27,23 @@
|
||||
or "&sysprocessmode"= "SAS Compute Server" %then %do;
|
||||
SASVIYA
|
||||
%end;
|
||||
%else %if "&sysprocessmode"="SAS Stored Process Server" %then %do;
|
||||
%else %if "&sysprocessmode"="SAS Stored Process Server"
|
||||
or "&sysprocessmode"="SAS Workspace Server"
|
||||
%then %do;
|
||||
SASMETA
|
||||
%return;
|
||||
%end;
|
||||
%else %do;
|
||||
SAS
|
||||
BASESAS
|
||||
%return;
|
||||
%end;
|
||||
%end;
|
||||
%else %if %symexist(_metaport) %then %do;
|
||||
%else %if %symexist(_metaport) or %symexist(_metauser) %then %do;
|
||||
SASMETA
|
||||
%return;
|
||||
%end;
|
||||
%else %do;
|
||||
SAS
|
||||
BASESAS
|
||||
%return;
|
||||
%end;
|
||||
%end;
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
%put mf_isblank(&var);
|
||||
|
||||
inspiration: https://support.sas.com/resources/papers/proceedings09/022-2009.pdf
|
||||
inspiration:
|
||||
https://support.sas.com/resources/papers/proceedings09/022-2009.pdf
|
||||
|
||||
@param param VALUE to be checked
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
%let isdir=%mf_isdir(/tmp);
|
||||
|
||||
With thanks and full credit to Andrea Defronzo - https://www.linkedin.com/in/andrea-defronzo-b1a47460/
|
||||
With thanks and full credit to Andrea Defronzo -
|
||||
https://www.linkedin.com/in/andrea-defronzo-b1a47460/
|
||||
|
||||
@param path full path of the file/directory to be checked
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
@file mf_mval.sas
|
||||
@brief Returns a macro variable value if the variable exists
|
||||
@details Use this macro to avoid repetitive use of `%if %symexist(MACVAR) %then`
|
||||
@details
|
||||
Use this macro to avoid repetitive use of `%if %symexist(MACVAR) %then`
|
||||
type logic.
|
||||
Usage:
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
|
||||
|
||||
@param basestr The string to be modified
|
||||
@param trimstr The string to be removed from the end of `basestr`, if it exists
|
||||
@param trimstr The string to be removed from the end of `basestr`, if it
|
||||
exists
|
||||
|
||||
@return output returns result with the value of `trimstr` removed from the end
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
results back to the client in an STP Web App context, or completely stop
|
||||
in the case of a batch run.
|
||||
|
||||
Using SAS Abort Cancel mechanisms can cause hung sessions in some Stored Process
|
||||
environments. This macro takes a unique approach - we set the SAS syscc to 0,
|
||||
run `stpsrvset('program error', 0)` (if SAS 9) and then - we open a macro
|
||||
but don't close it! This provides a graceful abort for SAS web services in all
|
||||
web enabled environments.
|
||||
Using SAS Abort Cancel mechanisms can cause hung sessions in some Stored
|
||||
Process environments. This macro takes a unique approach - we set the SAS
|
||||
syscc to 0, run `stpsrvset('program error', 0)` (if SAS 9) and then - we open
|
||||
a macro but don't close it! This provides a graceful abort for SAS web
|
||||
services in all web enabled environments.
|
||||
|
||||
@param mac= to contain the name of the calling macro
|
||||
@param msg= message to be returned
|
||||
@@ -48,7 +48,10 @@
|
||||
input; putlog _infile_;
|
||||
i=1;
|
||||
retain logonce 0;
|
||||
if (_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR") and logonce=0 then do;
|
||||
if (
|
||||
_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR"
|
||||
) and logonce=0 then
|
||||
do;
|
||||
call symputx('logline',_n_);
|
||||
logonce+1;
|
||||
end;
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
@details Reads in a file byte by byte and writes it back out. Is an
|
||||
os-independent method to copy files. In case of naming collision, the
|
||||
default filerefs can be modified.
|
||||
Based on http://stackoverflow.com/questions/13046116/using-sas-to-copy-a-text-file
|
||||
Based on:
|
||||
https://stackoverflow.com/questions/13046116/using-sas-to-copy-a-text-file
|
||||
|
||||
%mp_binarycopy(inloc="/home/me/blah.txt", outref=_webout)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
%macro mp_cleancsv(in=NOTPROVIDED,out=NOTPROVIDED,qchar='22'x);
|
||||
%if "&in"="NOTPROVIDED" or "&out"="NOTPROVIDED" %then %do;
|
||||
%put %str(ERR)OR: Please provide valid input (&in) and output (&out) locations;
|
||||
%put %str(ERR)OR: Please provide valid input (&in) & output (&out) locations;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
|
||||
@@ -57,8 +57,11 @@
|
||||
)/*/STORE SOURCE*/;
|
||||
%let getattrs=%upcase(&getattrs)XX;
|
||||
|
||||
data &outds (compress=no keep=file_or_folder filepath filename ext msg directory);
|
||||
length directory filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200;
|
||||
data &outds(compress=no
|
||||
keep=file_or_folder filepath filename ext msg directory
|
||||
);
|
||||
length directory filepath $500 fref fref2 $8 file_or_folder $6 filename $80
|
||||
ext $20 msg $200;
|
||||
%if &fref=0 %then %do;
|
||||
rc = filename(fref, "&path");
|
||||
%end;
|
||||
|
||||
@@ -14,16 +14,18 @@
|
||||
- explicity setting a unix LF
|
||||
- constraints / indexes etc
|
||||
|
||||
@param [in] base_ds= Should be two level - eg work.blah. This is the table that
|
||||
is converted to a cards file.
|
||||
@param [in] tgt_ds= Table that the generated cards file would create. Optional -
|
||||
if omitted, will be same as BASE_DS.
|
||||
@param [in] base_ds= Should be two level - eg work.blah. This is the table
|
||||
that is converted to a cards file.
|
||||
@param [in] tgt_ds= Table that the generated cards file would create.
|
||||
Optional - if omitted, will be same as BASE_DS.
|
||||
@param [out] cards_file= Location in which to write the (.sas) cards file
|
||||
@param [in] maxobs= to limit output to the first <code>maxobs</code> observations
|
||||
@param [in] showlog= whether to show generated cards file in the SAS log (YES/NO)
|
||||
@param [in] maxobs= to limit output to the first <code>maxobs</code>
|
||||
observations
|
||||
@param [in] showlog= whether to show generated cards file in the SAS log
|
||||
(YES/NO)
|
||||
@param [in] outencoding= provide encoding value for file statement (eg utf-8)
|
||||
@param [in] append= If NO then will rebuild the cards file if it already exists,
|
||||
otherwise will append to it. Used by the mp_lib2cards.sas macro.
|
||||
@param [in] append= If NO then will rebuild the cards file if it already
|
||||
exists, otherwise will append to it. Used by the mp_lib2cards.sas macro.
|
||||
|
||||
|
||||
@version 9.2
|
||||
@@ -64,9 +66,11 @@ select count(*) into: nvars from dictionary.columns
|
||||
%end;
|
||||
|
||||
/* get indexes */
|
||||
proc sort data=sashelp.vindex
|
||||
(where=(upcase(libname)="%scan(%upcase(&base_ds),1)"
|
||||
and upcase(memname)="%scan(%upcase(&base_ds),2)"))
|
||||
proc sort
|
||||
data=sashelp.vindex(
|
||||
where=(upcase(libname)="%scan(%upcase(&base_ds),1)"
|
||||
and upcase(memname)="%scan(%upcase(&base_ds),2)")
|
||||
)
|
||||
out=_data_;
|
||||
by indxname indxpos;
|
||||
run;
|
||||
|
||||
@@ -133,7 +133,9 @@ run;
|
||||
|
||||
if notnull='yes' then notnul=' not null';
|
||||
if notnull='no' and missing(label) then put ' ' name typ;
|
||||
else if notnull='yes' and missing(label) then put ' ' name typ '[' notnul ']';
|
||||
else if notnull='yes' and missing(label) then do;
|
||||
put ' ' name typ '[' notnul ']';
|
||||
end;
|
||||
else if notnull='no' then put ' ' name typ '[' lab ']';
|
||||
else put ' ' name typ '[' notnul ',' lab ']';
|
||||
|
||||
@@ -166,7 +168,7 @@ run;
|
||||
call symputx('constcheck',1);
|
||||
end;
|
||||
|
||||
if last then call symputx('constraints_used',cats(upcase(constraints_used)));
|
||||
if last then call symput('constraints_used',cats(upcase(constraints_used)));
|
||||
|
||||
length curds const col $39;
|
||||
curds="&curds";
|
||||
@@ -176,7 +178,8 @@ run;
|
||||
|
||||
proc append base=&pkds data=&syslast;run;
|
||||
|
||||
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
|
||||
/* Create Unique Indexes, but only if they were not already defined within
|
||||
the Constraints section. */
|
||||
data _data_(keep=curds const col);
|
||||
set &idxinfo (where=(
|
||||
libname="%scan(&curds,1,.)"
|
||||
@@ -187,7 +190,7 @@ run;
|
||||
file &outref mod;
|
||||
by idxusage indxname;
|
||||
name=upcase(name);
|
||||
if &constcheck=1 then stop; /* in fact we only care about PKs so stop if we have */
|
||||
if &constcheck=1 then stop; /* we only care about PKs so stop if we have */
|
||||
if _n_=1 and &constcheck=0 then put / ' indexes {';
|
||||
|
||||
length cols $5000;
|
||||
@@ -261,7 +264,11 @@ run;
|
||||
line='Ref: "'!!"&curds"
|
||||
!!cats('".(',"%mf_getquotedstr(&pkcols,dlm=%str(,),quote=%str( ))",')')
|
||||
!!' - '
|
||||
!!cats(quote(trim(curds)),'.(',"%mf_getquotedstr(&pkcols,dlm=%str(,),quote=%str( ))",')');
|
||||
!!cats(quote(trim(curds))
|
||||
,'.('
|
||||
,"%mf_getquotedstr(&pkcols,dlm=%str(,),quote=%str( ))"
|
||||
,')'
|
||||
);
|
||||
put line;
|
||||
run;
|
||||
|
||||
@@ -282,7 +289,9 @@ run;
|
||||
create table &pkds.5b as
|
||||
select curds,count(*) as cnt
|
||||
from &pkds.5a
|
||||
where curds not in (select curds from &pkds.2 where cols="&pkcols") /* not a one to one match */
|
||||
where curds not in (
|
||||
select curds from &pkds.2 where cols="&pkcols"
|
||||
) /* not a one to one match */
|
||||
and curds ne "&curds" /* exclude self */
|
||||
group by 1;
|
||||
create table &pkds.6 as
|
||||
|
||||
@@ -86,7 +86,9 @@ create table _data_ as
|
||||
%global constraints_used;
|
||||
data _null_;
|
||||
length ctype $11 constraint_name_orig $256 constraints_used $5000;
|
||||
set &colconst (where=(table_name="&curds" and constraint_type in ('PRIMARY','UNIQUE'))) end=last;
|
||||
set &colconst(
|
||||
where=(table_name="&curds" and constraint_type in ('PRIMARY','UNIQUE'))
|
||||
) end=last;
|
||||
file &fref mod;
|
||||
by constraint_type constraint_name;
|
||||
retain constraints_used;
|
||||
@@ -161,10 +163,19 @@ run;
|
||||
put ');';
|
||||
run;
|
||||
|
||||
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
|
||||
/* Create Unique Indexes, but only if they were not already defined within
|
||||
the Constraints section. */
|
||||
data _null_;
|
||||
*length ds $128;
|
||||
set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
|
||||
set &idxinfo(
|
||||
where=(
|
||||
memname="&curds"
|
||||
and unique='yes'
|
||||
and indxname not in (
|
||||
%sysfunc(tranwrd("&constraints_used",%str( ),%str(",")))
|
||||
)
|
||||
)
|
||||
);
|
||||
file &fref mod;
|
||||
by idxusage indxname;
|
||||
/* ds=cats(libname,'.',memname); */
|
||||
@@ -228,10 +239,19 @@ run;
|
||||
/* Extra step for data constraints */
|
||||
%addConst()
|
||||
|
||||
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
|
||||
/* Create Unique Indexes, but only if they were not already defined within
|
||||
the Constraints section. */
|
||||
data _null_;
|
||||
*length ds $128;
|
||||
set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
|
||||
set &idxinfo(
|
||||
where=(
|
||||
memname="&curds"
|
||||
and unique='yes'
|
||||
and indxname not in (
|
||||
%sysfunc(tranwrd("&constraints_used",%str( ),%str(",")))
|
||||
)
|
||||
)
|
||||
);
|
||||
file &fref mod;
|
||||
by idxusage indxname;
|
||||
*ds=cats(libname,'.',memname);
|
||||
@@ -320,10 +340,19 @@ run;
|
||||
put ');';
|
||||
run;
|
||||
|
||||
/* Create Unique Indexes, but only if they were not already defined within the Constraints section. */
|
||||
/* Create Unique Indexes, but only if they were not already defined within
|
||||
the Constraints section. */
|
||||
data _null_;
|
||||
*length ds $128;
|
||||
set &idxinfo (where=(memname="&curds" and unique='yes' and indxname not in (%sysfunc(tranwrd("&constraints_used",%str( ),%str(","))))));
|
||||
set &idxinfo(
|
||||
where=(
|
||||
memname="&curds"
|
||||
and unique='yes'
|
||||
and indxname not in (
|
||||
%sysfunc(tranwrd("&constraints_used",%str( ),%str(",")))
|
||||
)
|
||||
)
|
||||
);
|
||||
file &fref mod;
|
||||
by idxusage indxname;
|
||||
/* ds=cats(libname,'.',memname); */
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
- NAME Name of the base dataset column
|
||||
- MAXLEN Maximum length of the data contained therein.
|
||||
|
||||
Character fields may be allocated very large widths (eg 32000) of which the maximum
|
||||
value is likely to be much narrower. This macro was designed to enable a HTML
|
||||
table to be appropriately sized however this could be used as part of a data
|
||||
audit to ensure we aren't over-sizing our tables in relation to the data therein.
|
||||
Character fields may be allocated very large widths (eg 32000) of which the
|
||||
maximum value is likely to be much narrower. This macro was designed to
|
||||
enable a HTML table to be appropriately sized however this could be used as
|
||||
part of a data audit to ensure we aren't over-sizing our tables in relation to
|
||||
the data therein.
|
||||
|
||||
Numeric fields are converted using the relevant format to determine the width.
|
||||
Usage:
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
@details PROC JSON is faster but will produce errs like the ones below if
|
||||
special chars are encountered.
|
||||
|
||||
> ERROR: Some code points did not transcode.
|
||||
|
||||
> An object or array close is not valid at this point in the JSON text.
|
||||
|
||||
> Date value out of range
|
||||
|
||||
If this happens, try running with ENGINE=DATASTEP.
|
||||
@@ -14,7 +17,9 @@
|
||||
filename tmp temp;
|
||||
data class; set sashelp.class;run;
|
||||
|
||||
%mp_jsonout(OPEN,jref=tmp)
|
||||
%mp_jsonout(OBJ,class,jref=tmp)
|
||||
%mp_jsonout(CLOSE,jref=tmp)
|
||||
|
||||
data _null_;
|
||||
infile tmp;
|
||||
@@ -27,18 +32,18 @@
|
||||
For more information see https://sasjs.io
|
||||
|
||||
@param action Valid values:
|
||||
* OPEN - opens the JSON
|
||||
* OBJ - sends a table with each row as an object
|
||||
* ARR - sends a table with each row in an array
|
||||
* CLOSE - closes the JSON
|
||||
@li OPEN - opens the JSON
|
||||
@li OBJ - sends a table with each row as an object
|
||||
@li ARR - sends a table with each row in an array
|
||||
@li CLOSE - closes the JSON
|
||||
|
||||
@param ds the dataset to send. Must be a work table.
|
||||
@param jref= the fileref to which to send the JSON
|
||||
@param dslabel= the name to give the table in the exported JSON
|
||||
@param fmt= Whether to keep or strip formats from the table
|
||||
@param engine= Which engine to use to send the JSON, options are:
|
||||
* PROCJSON (default)
|
||||
* DATASTEP
|
||||
@param engine= Which engine to use to send the JSON, valid options are:
|
||||
@li PROCJSON (default)
|
||||
@li DATASTEP (more reliable when data has non standard characters)
|
||||
|
||||
@param dbg= DEPRECATED - was used to conditionally add PRETTY to
|
||||
proc json but this can cause line truncation in large files.
|
||||
@@ -83,7 +88,8 @@
|
||||
%end;
|
||||
data _null_;file &jref mod ;
|
||||
put "["; call symputx('cols',0,'l');
|
||||
proc sort data=sashelp.vcolumn(where=(libname='WORK' & memname="%upcase(&ds)"))
|
||||
proc sort
|
||||
data=sashelp.vcolumn(where=(libname='WORK' & memname="%upcase(&ds)"))
|
||||
out=_data_;
|
||||
by varnum;
|
||||
|
||||
@@ -122,7 +128,8 @@
|
||||
%end;
|
||||
%end;
|
||||
run;
|
||||
/* write to temp loc to avoid _webout truncation - https://support.sas.com/kb/49/325.html */
|
||||
/* write to temp loc to avoid _webout truncation
|
||||
- https://support.sas.com/kb/49/325.html */
|
||||
filename _sjs temp lrecl=131068 encoding='utf-8';
|
||||
data _null_; file _sjs lrecl=131068 encoding='utf-8' mod;
|
||||
set &tempds;
|
||||
@@ -158,7 +165,7 @@
|
||||
%end;
|
||||
|
||||
%else %if &action=CLOSE %then %do;
|
||||
data _null_;file &jref encoding='utf-8';
|
||||
data _null_;file &jref encoding='utf-8' mod;
|
||||
put "}";
|
||||
run;
|
||||
%end;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
@file
|
||||
@brief Reset an option to original value
|
||||
@details Inspired by the SAS Jedi - https://blogs.sas.com/content/sastraining/2012/08/14/jedi-sas-tricks-reset-sas-system-options/
|
||||
@details Inspired by the SAS Jedi -
|
||||
https://blogs.sas.com/content/sastraining/2012/08/14/jedi-sas-tricks-reset-sas-system-options
|
||||
Called as follows:
|
||||
|
||||
options obs=30;
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
@param ds= the dataset to search (leave blank to search entire library)
|
||||
@param string= the string value to search
|
||||
@param numval= the numeric value to search (must be exact)
|
||||
@param outloc= the directory in which to create the output datasets with matching
|
||||
rows. Will default to a subfolder in the WORK library.
|
||||
@param outobs= set to a positive integer to restrict the number of observations
|
||||
@param outloc= the directory in which to create the output datasets with
|
||||
matching rows. Will default to a subfolder in the WORK library.
|
||||
@param outobs= set to a positive integer to restrict the number of
|
||||
observations
|
||||
@param filter_text= add a (valid) filter clause to further filter the results
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@@ -44,7 +45,8 @@
|
||||
,filter_text=%str(1=1)
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%local table_list table table_num table colnum col start_tm check_tm vars type coltype;
|
||||
%local table_list table table_num table colnum col start_tm check_tm vars type
|
||||
coltype;
|
||||
%put process began at %sysfunc(datetime(),datetime19.);
|
||||
|
||||
%if &syscc ge 4 %then %do;
|
||||
@@ -101,7 +103,8 @@ proc sql
|
||||
%end;
|
||||
%end;
|
||||
);
|
||||
%put Search query for &table took %sysevalf(%sysfunc(datetime())-&check_tm) seconds;
|
||||
%put Search query for &table took
|
||||
%sysevalf(%sysfunc(datetime())-&check_tm) seconds;
|
||||
%if &sqlrc ne 0 %then %do;
|
||||
%put %str(WAR)NING: SQLRC=&sqlrc when processing &table;
|
||||
%return;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
@file
|
||||
@brief Capture session start / finish times and request details
|
||||
@details For details, see http://www.rawsas.com/2015/09/logging-of-stored-process-server.html.
|
||||
@details For details, see
|
||||
https://rawsas.com/event-logging-of-stored-process-server-sessions.
|
||||
Requires a base table in the following structure (name can be changed):
|
||||
|
||||
proc sql;
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
Usage:
|
||||
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
%mp_streamfile(contenttype=csv,inloc=/some/where.txt,outname=myfile.txt)
|
||||
@@ -65,13 +66,15 @@
|
||||
%else %if &contentype=XLSX %then %do;
|
||||
%if &platform=SASMETA %then %do;
|
||||
data _null_;
|
||||
rc=stpsrv_header('Content-type','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
rc=stpsrv_header('Content-type',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
|
||||
run;
|
||||
%end;
|
||||
%else %if &platform=SASVIYA %then %do;
|
||||
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name='_webout.xls'
|
||||
contenttype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
contenttype=
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
contentdisp="attachment; filename=&outname";
|
||||
%end;
|
||||
%end;
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
|
||||
Credits:
|
||||
|
||||
* Roger Deangelis, https://communities.sas.com/t5/SAS-Programming/listing-all-files-within-a-directory-and-subdirectories/m-p/332616/highlight/true#M74887
|
||||
* Tom, https://communities.sas.com/t5/SAS-Programming/listing-all-files-of-all-types-from-all-subdirectories/m-p/334113/highlight/true#M75419
|
||||
Roger Deangelis:
|
||||
https://communities.sas.com/t5/SAS-Programming/listing-all-files-within-a-directory-and-subdirectories/m-p/332616/highlight/true#M74887
|
||||
|
||||
Tom:
|
||||
https://communities.sas.com/t5/SAS-Programming/listing-all-files-of-all-types-from-all-subdirectories/m-p/334113/highlight/true#M75419
|
||||
|
||||
|
||||
@param dir= Directory to be scanned (default=/tmp)
|
||||
|
||||
@@ -117,7 +117,8 @@ run;
|
||||
%end;
|
||||
%else %if &engine=REMOTE %then %do;
|
||||
data x;
|
||||
length rcCon rcProp rc k 3 uriCon uriProp PropertyValue PropertyName Delimiter $256 properties $2048;
|
||||
length rcCon rcProp rc k 3 uriCon uriProp PropertyValue PropertyName
|
||||
Delimiter $256 properties $2048;
|
||||
retain properties;
|
||||
rcCon = metadata_getnasn("&liburi", "LibraryConnection", 1, uriCon);
|
||||
|
||||
@@ -129,7 +130,8 @@ run;
|
||||
rc = metadata_getattr(uriProp , "DefaultValue",PropertyValue);
|
||||
rc = metadata_getattr(uriProp , "PropertyName",PropertyName);
|
||||
rc = metadata_getattr(uriProp , "Delimiter",Delimiter);
|
||||
properties = trim(properties) !! " " !! trim(PropertyName) !! trim(Delimiter) !! trim(PropertyValue);
|
||||
properties = trim(properties) !! " " !! trim(PropertyName)
|
||||
!! trim(Delimiter) !! trim(PropertyValue);
|
||||
output;
|
||||
k+1;
|
||||
rcProp = metadata_getnasn(uriCon, "Properties", k, uriProp);
|
||||
@@ -170,7 +172,8 @@ run;
|
||||
else if value='Connection.OLE.Property.PROVIDER.Name.xmlKey.txt' then do;
|
||||
rc4=metadata_getattr(conprop_uri,'DefaultValue',provider);
|
||||
end;
|
||||
else if value='Connection.OLE.Property.PROPERTIES.Name.xmlKey.txt' then do;
|
||||
else if value='Connection.OLE.Property.PROPERTIES.Name.xmlKey.txt' then
|
||||
do;
|
||||
rc5=metadata_getattr(conprop_uri,'DefaultValue',properties);
|
||||
end;
|
||||
end;
|
||||
@@ -357,7 +360,8 @@ run;
|
||||
call symputx('authdomain',authdomain,'l');
|
||||
|
||||
/* path */
|
||||
rc=metadata_getprop(assocuri1,'Connection.Oracle.Property.PATH.Name.xmlKey.txt',path);
|
||||
rc=metadata_getprop(assocuri1,
|
||||
'Connection.Oracle.Property.PATH.Name.xmlKey.txt',path);
|
||||
call symputx('path',path,'l');
|
||||
|
||||
/* schema */
|
||||
@@ -366,14 +370,16 @@ run;
|
||||
call symputx('schema',schema,'l');
|
||||
run;
|
||||
%put NOTE: Executing the following:/; %put NOTE-;
|
||||
%put NOTE- libname &libref ORACLE path=&path schema=&schema authdomain=&authdomain;
|
||||
%put NOTE- libname &libref ORACLE path=&path schema=&schema;
|
||||
%put NOTE- authdomain=&authdomain;
|
||||
%put NOTE-;
|
||||
libname &libref ORACLE path=&path schema=&schema authdomain=&authdomain;
|
||||
%end;
|
||||
%else %if &engine=SQLSVR %then %do;
|
||||
%put NOTE: Obtaining &engine library details;
|
||||
data _null;
|
||||
length assocuri1 assocuri2 assocuri3 authdomain path schema userid passwd $256;
|
||||
length assocuri1 assocuri2 assocuri3 authdomain path schema userid
|
||||
passwd $256;
|
||||
call missing (of _all_);
|
||||
|
||||
rc=metadata_getnasn("&liburi",'DefaultLogin',1,assocuri1);
|
||||
@@ -384,7 +390,8 @@ run;
|
||||
|
||||
/* path */
|
||||
rc=metadata_getnasn("&liburi",'LibraryConnection',1,assocuri2);
|
||||
rc=metadata_getprop(assocuri2,'Connection.SQL.Property.Datasrc.Name.xmlKey.txt',path);
|
||||
rc=metadata_getprop(assocuri2,
|
||||
'Connection.SQL.Property.Datasrc.Name.xmlKey.txt',path);
|
||||
call symputx('path',path,'l');
|
||||
|
||||
/* schema */
|
||||
@@ -394,7 +401,8 @@ run;
|
||||
run;
|
||||
|
||||
%put NOTE: Executing the following:/; %put NOTE-;
|
||||
%put NOTE- libname &libref SQLSVR datasrc=&path schema=&schema user="&user" pass="XXX";
|
||||
%put NOTE- libname &libref SQLSVR datasrc=&path schema=&schema ;
|
||||
%put NOTE- user="&user" pass="XXX";
|
||||
%put NOTE-;
|
||||
|
||||
libname &libref SQLSVR datasrc=&path schema=&schema user="&user" pass="&pass";
|
||||
@@ -402,7 +410,8 @@ run;
|
||||
%else %if &engine=TERADATA %then %do;
|
||||
%put NOTE: Obtaining &engine library details;
|
||||
data _null;
|
||||
length assocuri1 assocuri2 assocuri3 authdomain path schema userid passwd $256;
|
||||
length assocuri1 assocuri2 assocuri3 authdomain path schema userid
|
||||
passwd $256;
|
||||
call missing (of _all_);
|
||||
|
||||
/* get auth domain */
|
||||
@@ -421,7 +430,8 @@ run;
|
||||
|
||||
/* path */
|
||||
rc=metadata_getnasn("&liburi",'LibraryConnection',1,assocuri2);
|
||||
rc=metadata_getprop(assocuri2,'Connection.Teradata.Property.SERVER.Name.xmlKey.txt',path);
|
||||
rc=metadata_getprop(assocuri2,
|
||||
'Connection.Teradata.Property.SERVER.Name.xmlKey.txt',path);
|
||||
call symputx('path',path,'l');
|
||||
|
||||
/* schema */
|
||||
@@ -431,7 +441,8 @@ run;
|
||||
run;
|
||||
|
||||
%put NOTE: Executing the following:/; %put NOTE-;
|
||||
%put NOTE- libname &libref TERADATA server=&path schema=&schema authdomain=&authdomain;
|
||||
%put NOTE- libname &libref TERADATA server=&path schema=&schema ;
|
||||
%put NOTe- authdomain=&authdomain;
|
||||
%put NOTE-;
|
||||
|
||||
libname &libref TERADATA server=&path schema=&schema authdomain=&authdomain;
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
@li mp_abort.sas
|
||||
|
||||
@param libref the libref (not name) of the metadata library
|
||||
@param mAbort= If not assigned, HARD will call %mp_abort(), SOFT will silently return
|
||||
@param mAbort= If not assigned, HARD will call %mp_abort(), SOFT will
|
||||
silently return
|
||||
|
||||
@returns libname statement
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
,params= name1=value1
name2=value2
emptyvalue=
|
||||
)
|
||||
|
||||
@warning application components do not get deleted when removing the container folder! be sure you have the administrative priviliges to remove this kind of metadata from the SMC plugin (or be ready to do to so programmatically).
|
||||
@warning application components do not get deleted when removing the container
|
||||
folder! be sure you have the administrative priviliges to remove this kind of
|
||||
metadata from the SMC plugin (or be ready to do to so programmatically).
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_abort.sas
|
||||
|
||||
@@ -55,7 +55,7 @@ data _null_;
|
||||
|
||||
* must have a starting slash ;
|
||||
if ( substr(folderPath,1,1) ne '/' ) then do;
|
||||
put "%str(ERR)OR: &sysmacroname PATH parameter value must have starting slash";
|
||||
put "%str(ERR)OR: &sysmacroname PATH param value must have starting slash";
|
||||
stop;
|
||||
end;
|
||||
|
||||
@@ -123,9 +123,10 @@ run;
|
||||
%local inmeta;
|
||||
%put creating: &path;
|
||||
%let inmeta=<AddMetadata><Reposid>$METAREPOSITORY</Reposid><Metadata>
|
||||
<Tree Name='&child' PublicType='Folder' TreeType='BIP Folder' UsageVersion='1000000'>
|
||||
<ParentTree><Tree ObjRef='&parentFolderObjId'/></ParentTree></Tree></Metadata>
|
||||
<NS>SAS</NS><Flags>268435456</Flags></AddMetadata>;
|
||||
<Tree Name='&child' PublicType='Folder' TreeType='BIP Folder'
|
||||
UsageVersion='1000000'><ParentTree><Tree ObjRef='&parentFolderObjId'/>
|
||||
</ParentTree></Tree></Metadata><NS>SAS</NS><Flags>268435456</Flags>
|
||||
</AddMetadata>;
|
||||
|
||||
proc metadata in="&inmeta" out=__newdir verbose;
|
||||
run ;
|
||||
|
||||
@@ -166,7 +166,7 @@ filename &frefout temp;
|
||||
putlog (_all_)(=);
|
||||
run;
|
||||
%if &checktype ne Prototype %then %do;
|
||||
%put %str(ERR)OR: Prototype (Library.SAS.Prototype.Name.xmlKey.txt) not found!;
|
||||
%put %str(ERR)OR: Prototype Library.SAS.Prototype.Name.xmlKey.txt not found;
|
||||
%return;
|
||||
%end;
|
||||
|
||||
|
||||
@@ -210,7 +210,8 @@ run;
|
||||
rc3=METADATA_SETATTR(prompturi, 'GroupType','2');
|
||||
rc4=METADATA_SETATTR(prompturi, 'Name','Parameters');
|
||||
rc5=METADATA_SETATTR(prompturi, 'PublicType','Embedded:PromptGroup');
|
||||
GroupInfo="<PromptGroup promptId='PromptGroup_%sysfunc(datetime())_&sysprocessid'"
|
||||
GroupInfo=
|
||||
"<PromptGroup promptId='PromptGroup_%sysfunc(datetime())_&sysprocessid'"
|
||||
!!" version='1.0'><Label><Text xml:lang='en-GB'>Parameters</Text>"
|
||||
!!"</Label></PromptGroup>";
|
||||
rc6 = METADATA_SETATTR(prompturi, 'GroupInfo',groupinfo);
|
||||
@@ -375,8 +376,6 @@ run;
|
||||
*/
|
||||
%mm_updatestpsourcecode(stp=&tree/&stpname
|
||||
,stpcode="&directory/&filename"
|
||||
,frefin=&frefin.
|
||||
,frefout=&frefout.
|
||||
,mdebug=&mdebug
|
||||
,minify=&minify)
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ Usage:
|
||||
%webout(OBJ,example2) * Object format, easier to work with ;
|
||||
%webout(CLOSE)
|
||||
;;;;
|
||||
%mm_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001,replace=YES)
|
||||
%mm_createwebservice(path=/Public/app/common,name=appInit)
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mm_createstp.sas
|
||||
@@ -119,7 +119,8 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' data _null_;file &jref mod ; ';
|
||||
put ' put "["; call symputx(''cols'',0,''l''); ';
|
||||
put ' proc sort data=sashelp.vcolumn(where=(libname=''WORK'' & memname="%upcase(&ds)")) ';
|
||||
put ' proc sort ';
|
||||
put ' data=sashelp.vcolumn(where=(libname=''WORK'' & memname="%upcase(&ds)")) ';
|
||||
put ' out=_data_; ';
|
||||
put ' by varnum; ';
|
||||
put ' ';
|
||||
@@ -158,7 +159,8 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' %end; ';
|
||||
put ' run; ';
|
||||
put ' /* write to temp loc to avoid _webout truncation - https://support.sas.com/kb/49/325.html */ ';
|
||||
put ' /* write to temp loc to avoid _webout truncation ';
|
||||
put ' - https://support.sas.com/kb/49/325.html */ ';
|
||||
put ' filename _sjs temp lrecl=131068 encoding=''utf-8''; ';
|
||||
put ' data _null_; file _sjs lrecl=131068 encoding=''utf-8'' mod; ';
|
||||
put ' set &tempds; ';
|
||||
@@ -194,7 +196,7 @@ data _null_;
|
||||
put '%end; ';
|
||||
put ' ';
|
||||
put '%else %if &action=CLOSE %then %do; ';
|
||||
put ' data _null_;file &jref encoding=''utf-8''; ';
|
||||
put ' data _null_;file &jref encoding=''utf-8'' mod; ';
|
||||
put ' put "}"; ';
|
||||
put ' run; ';
|
||||
put '%end; ';
|
||||
@@ -275,14 +277,14 @@ data _null_;
|
||||
put ' i+1; ';
|
||||
put ' call symputx(''wt''!!left(i),name,''l''); ';
|
||||
put ' call symputx(''wtcnt'',i,''l''); ';
|
||||
put ' data _null_; file &fref encoding=''utf-8''; ';
|
||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
||||
put ' put ",""WORK"":{"; ';
|
||||
put ' %do i=1 %to &wtcnt; ';
|
||||
put ' %let wt=&&wt&i; ';
|
||||
put ' proc contents noprint data=&wt ';
|
||||
put ' out=_data_ (keep=name type length format:); ';
|
||||
put ' run;%let tempds=%scan(&syslast,2,.); ';
|
||||
put ' data _null_; file &fref encoding=''utf-8''; ';
|
||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
||||
put ' dsid=open("WORK.&wt",''is''); ';
|
||||
put ' nlobs=attrn(dsid,''NLOBS''); ';
|
||||
put ' nvars=attrn(dsid,''NVARS''); ';
|
||||
@@ -293,10 +295,10 @@ data _null_;
|
||||
put ' put '',"nvars":'' nvars; ';
|
||||
put ' %mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP) ';
|
||||
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP) ';
|
||||
put ' data _null_; file &fref encoding=''utf-8''; ';
|
||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
||||
put ' put "}"; ';
|
||||
put ' %end; ';
|
||||
put ' data _null_; file &fref encoding=''utf-8''; ';
|
||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
||||
put ' put "}"; ';
|
||||
put ' run; ';
|
||||
put ' %end; ';
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%if %length(&outds)>30 %then %do;
|
||||
%put %str(ERR)OR: Temp tables are created with the &outds prefix, which therefore
|
||||
needs to be 30 characters or less;
|
||||
%put %str(ERR)OR: Temp tables are created with the &outds prefix, which
|
||||
therefore needs to be 30 characters or less;
|
||||
%return;
|
||||
%end;
|
||||
%if %index(&outds,'.')>0 %then %do;
|
||||
|
||||
@@ -39,8 +39,10 @@ data &outds (keep=directoryuri name directoryname directorydesc );
|
||||
do while
|
||||
(metadata_getnobj("omsobj:Directory?@Id contains '.'",__i,directoryuri)>0);
|
||||
%end; %else %do;
|
||||
do while
|
||||
(metadata_getnobj("omsobj:Directory?@DirectoryName='&path'",__i,directoryuri)>0);
|
||||
do while(
|
||||
metadata_getnobj("omsobj:Directory?@DirectoryName='&path'",__i,directoryuri)
|
||||
>0
|
||||
);
|
||||
%end;
|
||||
__rc1=metadata_getattr(directoryuri, "Name", name);
|
||||
__rc2=metadata_getattr(directoryuri, "DirectoryName", directoryname);
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
%mm_getfoldermembers(root=/User Folders/&sysuserid, outds=usercontent)
|
||||
|
||||
@param [in] root= the parent folder under which to return all contents
|
||||
@param [out] outds= the dataset to create that contains the list of directories
|
||||
@param [out] outds= the dataset to create that contains the list of
|
||||
directories
|
||||
@param [in] mDebug= set to 1 to show debug messages in the log
|
||||
|
||||
<h4> Data Outputs </h4>
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
options notes source;
|
||||
|
||||
@param [in] root= the parent folder under which to return all contents
|
||||
@param [out] outds= the dataset to create that contains the list of directories
|
||||
@param [out] outds= the dataset to create that contains the list of
|
||||
directories
|
||||
@param [in] mDebug= set to 1 to show debug messages in the log
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
|
||||
@param [in] user= the metadata user to return groups for. Leave blank for all
|
||||
groups.
|
||||
@param [in] repo= the metadata repository that contains the user/group information
|
||||
@param [in] repo= the metadata repository that contains the user/group
|
||||
information
|
||||
@param [in] mDebug= set to 1 to show debug messages in the log
|
||||
@param [out] outds= the dataset to create that contains the list of groups
|
||||
|
||||
@@ -39,7 +40,8 @@
|
||||
%&mD.put Executing mm_getGroups.sas;
|
||||
%&mD.put _local_;
|
||||
|
||||
/* on some sites, user / group info is in a different metadata repo to the default */
|
||||
/* on some sites, user / group info is in a different metadata repo to the
|
||||
default */
|
||||
%if &oldrepo ne &repo %then %do;
|
||||
options metarepository=&repo;
|
||||
%end;
|
||||
|
||||
@@ -46,7 +46,8 @@ filename sxlemap temp;
|
||||
data _null_;
|
||||
file sxlemap;
|
||||
put '<SXLEMAP version="1.2" name="SASObjects"><TABLE name="SASObjects">';
|
||||
put "<TABLE-PATH syntax='XPath'>/GetMetadataObjects/Objects/&type</TABLE-PATH>";
|
||||
put "<TABLE-PATH syntax='XPath'>/GetMetadataObjects/Objects/&type";
|
||||
put "</TABLE-PATH>";
|
||||
put '<COLUMN name="id">';
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/&type/@Id</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>200</LENGTH>";
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
@file mm_getpublictypes.sas
|
||||
@brief Creates a dataset with all deployable public types
|
||||
@details More info: https://support.sas.com/documentation/cdl/en/bisag/65422/HTML/default/viewer.htm#n1nkrdzsq5iunln18bk2236istkb.htm
|
||||
@details More info:
|
||||
https://support.sas.com/documentation/cdl/en/bisag/65422/HTML/default/viewer.htm#n1nkrdzsq5iunln18bk2236istkb.htm
|
||||
|
||||
Usage:
|
||||
|
||||
|
||||
@@ -44,61 +44,76 @@ filename sxlemap temp;
|
||||
data _null_;
|
||||
file sxlemap;
|
||||
put '<SXLEMAP version="1.2" name="SASRepos"><TABLE name="SASRepos">';
|
||||
put "<TABLE-PATH syntax='XPath'>/GetRepositories/Repositories/Repository</TABLE-PATH>";
|
||||
put "<TABLE-PATH syntax='XPath'>/GetRepositories/Repositories/Repository";
|
||||
put "</TABLE-PATH>";
|
||||
put '<COLUMN name="id">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Id</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Id";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>200</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="name">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Name</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Name";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>200</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="desc">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Desc</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Desc";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>200</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="DefaultNS">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@DefaultNS</PATH>";
|
||||
put "<PATH syntax='XPath'>";
|
||||
put "/GetRepositories/Repositories/Repository/@DefaultNS</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>200</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="RepositoryType">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@RepositoryType</PATH>";
|
||||
put "<PATH syntax='XPath'>";
|
||||
put "/GetRepositories/Repositories/Repository/@RepositoryType</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>20</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="RepositoryFormat">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@RepositoryFormat</PATH>";
|
||||
put "<PATH syntax='XPath'>";
|
||||
put "/GetRepositories/Repositories/Repository/@RepositoryFormat</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>10</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="Access">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Access</PATH>";
|
||||
put "<PATH syntax='XPath'>";
|
||||
put "/GetRepositories/Repositories/Repository/@Access</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>16</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="CurrentAccess">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@CurrentAccess</PATH>";
|
||||
put "<PATH syntax='XPath'>";
|
||||
put "/GetRepositories/Repositories/Repository/@CurrentAccess</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>16</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="PauseState">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@PauseState</PATH>";
|
||||
put "<PATH syntax='XPath'>";
|
||||
put "/GetRepositories/Repositories/Repository/@PauseState</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>16</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="Path">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Path</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Path";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>256</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="Engine">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Engine</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Engine";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>8</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="Options">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Options</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@Options";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>32</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="MetadataCreated">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@MetadataCreated</PATH>";
|
||||
put "<PATH syntax='XPath'>";
|
||||
put "/GetRepositories/Repositories/Repository/@MetadataCreated</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>24</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '<COLUMN name="MetadataUpdated">';
|
||||
put "<PATH syntax='XPath'>/GetRepositories/Repositories/Repository/@MetadataUpdated</PATH>";
|
||||
put "<PATH syntax='XPath'>";
|
||||
put "/GetRepositories/Repositories/Repository/@MetadataUpdated</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>24</LENGTH>";
|
||||
put '</COLUMN>';
|
||||
put '</TABLE></SXLEMAP>';
|
||||
|
||||
@@ -44,15 +44,19 @@ filename sxlemap temp;
|
||||
data _null_;
|
||||
file sxlemap;
|
||||
put '<SXLEMAP version="1.2" name="roles"><TABLE name="roles">';
|
||||
put "<TABLE-PATH syntax='XPath'>/GetMetadataObjects/Objects/IdentityGroup</TABLE-PATH>";
|
||||
put "<TABLE-PATH syntax='XPath'>/GetMetadataObjects/Objects/IdentityGroup";
|
||||
put "</TABLE-PATH>";
|
||||
put '<COLUMN name="roleuri">';
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/IdentityGroup/@Id</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/IdentityGroup/@Id";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>32</LENGTH>";
|
||||
put '</COLUMN><COLUMN name="rolename">';
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/IdentityGroup/@Name</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/IdentityGroup/@Name";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>256</LENGTH>";
|
||||
put '</COLUMN><COLUMN name="roledesc">';
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/IdentityGroup/@Desc</PATH>";
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/IdentityGroup/@Desc";
|
||||
put "</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>500</LENGTH>";
|
||||
put '</COLUMN></TABLE></SXLEMAP>';
|
||||
run;
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
combine with the <code>tree=</code> parameter.
|
||||
@param outds= the dataset to create that contains the list of stps.
|
||||
@param mDebug= set to 1 to show debug messages in the log
|
||||
@param showDesc= provide a non blank value to return stored process descriptions
|
||||
@param showUsageVersion= provide a non blank value to return the UsageVersion. This
|
||||
is either 1000000 (type 1, 9.2) or 2000000 (type2, 9.3 onwards).
|
||||
@param showDesc= provide a non blank value to return stored process
|
||||
descriptions
|
||||
@param showUsageVersion= provide a non blank value to return the UsageVersion.
|
||||
This is either 1000000 (type 1, 9.2) or 2000000 (type2, 9.3 onwards).
|
||||
|
||||
@returns outds dataset containing the following columns
|
||||
- stpuri
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
@file mm_gettableid.sas
|
||||
@brief Get the metadata id for a particular table
|
||||
@details Provide a libref and table name to return the corresponding metadata id
|
||||
@details Provide a libref and table name to return the corresponding metadata
|
||||
in an output datataset.
|
||||
|
||||
Usage:
|
||||
|
||||
@@ -48,7 +48,8 @@ filename sxlemap temp;
|
||||
data _null_;
|
||||
file sxlemap;
|
||||
put '<SXLEMAP version="1.2" name="SASObjects"><TABLE name="SASObjects">';
|
||||
put "<TABLE-PATH syntax='XPath'>/GetMetadataObjects/Objects/Person</TABLE-PATH>";
|
||||
put "<TABLE-PATH syntax='XPath'>/GetMetadataObjects/Objects/Person";
|
||||
put "</TABLE-PATH>";
|
||||
put '<COLUMN name="uri">';
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/Person/@Id</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>32</LENGTH>";
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
Usage:
|
||||
|
||||
%* import the macros (or make them available some other way);
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
%* create sample text file as input to the macro;
|
||||
@@ -92,7 +93,8 @@
|
||||
%let port=%sysfunc(getoption(metaport));
|
||||
%let platform_object_path=%mf_loc(POF);
|
||||
|
||||
%let connx_string=%str(-host &host -port &port -user &mmxuser -password &mmxpass);
|
||||
%let connx_string=%str(-host &host -port &port -user &mmxuser %trim(
|
||||
)-password &mmxpass);
|
||||
|
||||
%mm_tree(root=%str(&metaloc) ,types=EXPORTABLE ,outds=exportable)
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
Usage:
|
||||
|
||||
%* load macros;
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
%* export everything;
|
||||
@@ -104,7 +105,8 @@ filename sxlemap temp;
|
||||
data _null_;
|
||||
file sxlemap;
|
||||
put '<SXLEMAP version="1.2" name="SASObjects"><TABLE name="SASObjects">';
|
||||
put "<TABLE-PATH syntax='XPath'>/GetMetadataObjects/Objects/Tree</TABLE-PATH>";
|
||||
put "<TABLE-PATH syntax='XPath'>/GetMetadataObjects/Objects/Tree";
|
||||
put "</TABLE-PATH>";
|
||||
put '<COLUMN name="pathuri">';
|
||||
put "<PATH syntax='XPath'>/GetMetadataObjects/Objects/Tree/@Id</PATH>";
|
||||
put "<TYPE>character</TYPE><DATATYPE>string</DATATYPE><LENGTH>64</LENGTH>";
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
|
||||
@param target= full path to the STP being deleted
|
||||
@param type= Either WKS or STP depending on whether Workspace or Stored Process
|
||||
type required
|
||||
@param type= Either WKS or STP depending on whether Workspace or
|
||||
Stored Process type required
|
||||
|
||||
@version 9.4
|
||||
@author Allan Bowe
|
||||
@@ -51,7 +51,8 @@ data _null_;
|
||||
n+1;
|
||||
rc=metadata_getattr(uri,"Name",name);
|
||||
if name='Stored Process' then do;
|
||||
rc = METADATA_SETATTR(uri,'StoredText','<?xml version="1.0" encoding="UTF-8"?>'
|
||||
rc = METADATA_SETATTR(uri,'StoredText'
|
||||
,'<?xml version="1.0" encoding="UTF-8"?>'
|
||||
!!'<StoredProcess><ServerContext LogicalServerType="'!!"&newtype"
|
||||
!!'" OtherAllowed="false"/><ResultCapabilities Package="false" '
|
||||
!!' Streaming="true"/><OutputParameters/></StoredProcess>');
|
||||
|
||||
@@ -108,14 +108,14 @@
|
||||
i+1;
|
||||
call symputx('wt'!!left(i),name,'l');
|
||||
call symputx('wtcnt',i,'l');
|
||||
data _null_; file &fref encoding='utf-8';
|
||||
data _null_; file &fref mod encoding='utf-8';
|
||||
put ",""WORK"":{";
|
||||
%do i=1 %to &wtcnt;
|
||||
%let wt=&&wt&i;
|
||||
proc contents noprint data=&wt
|
||||
out=_data_ (keep=name type length format:);
|
||||
run;%let tempds=%scan(&syslast,2,.);
|
||||
data _null_; file &fref encoding='utf-8';
|
||||
data _null_; file &fref mod encoding='utf-8';
|
||||
dsid=open("WORK.&wt",'is');
|
||||
nlobs=attrn(dsid,'NLOBS');
|
||||
nvars=attrn(dsid,'NVARS');
|
||||
@@ -126,10 +126,10 @@
|
||||
put ',"nvars":' nvars;
|
||||
%mp_jsonout(OBJ,&tempds,jref=&fref,dslabel=colattrs,engine=DATASTEP)
|
||||
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,engine=DATASTEP)
|
||||
data _null_; file &fref encoding='utf-8';
|
||||
data _null_; file &fref mod encoding='utf-8';
|
||||
put "}";
|
||||
%end;
|
||||
data _null_; file &fref encoding='utf-8';
|
||||
data _null_; file &fref mod encoding='utf-8';
|
||||
put "}";
|
||||
run;
|
||||
%end;
|
||||
|
||||
@@ -20,7 +20,8 @@ Usage:
|
||||
run;
|
||||
|
||||
filename outref "%sysfunc(pathname(work))";
|
||||
%mmx_spkexport(metaloc=%str(/30.Projects/3001.Internal/300115.DataController/dc1)
|
||||
%mmx_spkexport(
|
||||
metaloc=%str(/30.Projects/3001.Internal/300115.DataController/dc1)
|
||||
,secureref=tmp
|
||||
,outspkpath=%str(/tmp)
|
||||
)
|
||||
@@ -56,7 +57,8 @@ Usage:
|
||||
/* get creds */
|
||||
%inc &secureref/nosource;
|
||||
|
||||
%let connx_string=%str(-host &host -port &port -user '&mmxuser' -password '&mmxpass');
|
||||
%let connx_string=
|
||||
%str(-host &host -port &port -user '&mmxuser' -password '&mmxpass');
|
||||
|
||||
%mm_tree(root=%str(&metaloc) ,types=EXPORTABLE ,outds=exportable)
|
||||
|
||||
|
||||
1688
package-lock.json
generated
1688
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@@ -28,10 +28,15 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"docs": "sasjs doc && ./sasjs/utils/build.sh",
|
||||
"postinstall": "node-git-hooks"
|
||||
"docs": "sasjs doc && ./sasjs/utils/build.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-git-hooks": "^1.0.5"
|
||||
"devDependencies": {
|
||||
"@sasjs/cli": "^2.14.2",
|
||||
"ghooks": "^2.0.4"
|
||||
},
|
||||
"config": {
|
||||
"ghooks": {
|
||||
"pre-commit": "sasjs lint"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
Code is passed in as one or more filerefs.
|
||||
|
||||
%* Step 1 - compile macros ;
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
%* Step 2 - Create some SAS code and add it to a job;
|
||||
@@ -38,8 +39,8 @@
|
||||
needs to be attached to the beginning of the job
|
||||
@param code= Fileref(s) of the actual code to be added
|
||||
@param access_token_var= The global macro variable to contain the access token
|
||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
The default is authorization_code.
|
||||
@param grant_type= valid values are "password" or "authorization_code"
|
||||
(unquoted). The default is authorization_code.
|
||||
@param replace= select NO to avoid replacing any existing job in that location
|
||||
@param contextname= Choose a specific context on which to run the Job. Leave
|
||||
blank to use the default context. From Viya 3.5 it is possible to configure
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
Code is passed in as one or more filerefs.
|
||||
|
||||
%* Step 1 - compile macros ;
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
%* Step 2 - Create some code and add it to a web service;
|
||||
@@ -52,7 +53,8 @@
|
||||
adapter, add a (different) fileref here.
|
||||
@param contextname= Choose a specific context on which to run the Job. Leave
|
||||
blank to use the default context. From Viya 3.5 it is possible to configure
|
||||
a shared context - see https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en
|
||||
a shared context - see
|
||||
https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en
|
||||
|
||||
@version VIYA V.03.04
|
||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
||||
@@ -256,7 +258,8 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' data _null_;file &jref mod ; ';
|
||||
put ' put "["; call symputx(''cols'',0,''l''); ';
|
||||
put ' proc sort data=sashelp.vcolumn(where=(libname=''WORK'' & memname="%upcase(&ds)")) ';
|
||||
put ' proc sort ';
|
||||
put ' data=sashelp.vcolumn(where=(libname=''WORK'' & memname="%upcase(&ds)")) ';
|
||||
put ' out=_data_; ';
|
||||
put ' by varnum; ';
|
||||
put ' ';
|
||||
@@ -295,7 +298,8 @@ data _null_;
|
||||
put ' %end; ';
|
||||
put ' %end; ';
|
||||
put ' run; ';
|
||||
put ' /* write to temp loc to avoid _webout truncation - https://support.sas.com/kb/49/325.html */ ';
|
||||
put ' /* write to temp loc to avoid _webout truncation ';
|
||||
put ' - https://support.sas.com/kb/49/325.html */ ';
|
||||
put ' filename _sjs temp lrecl=131068 encoding=''utf-8''; ';
|
||||
put ' data _null_; file _sjs lrecl=131068 encoding=''utf-8'' mod; ';
|
||||
put ' set &tempds; ';
|
||||
@@ -331,7 +335,7 @@ data _null_;
|
||||
put '%end; ';
|
||||
put ' ';
|
||||
put '%else %if &action=CLOSE %then %do; ';
|
||||
put ' data _null_;file &jref encoding=''utf-8''; ';
|
||||
put ' data _null_;file &jref encoding=''utf-8'' mod; ';
|
||||
put ' put "}"; ';
|
||||
put ' run; ';
|
||||
put '%end; ';
|
||||
@@ -410,7 +414,8 @@ data _null_;
|
||||
put ' if _n_=1 then call symputx(''input_statement'',_infile_); ';
|
||||
put ' list; ';
|
||||
put ' data &table; ';
|
||||
put ' infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd termstr=crlf; ';
|
||||
put ' infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd ';
|
||||
put ' termstr=crlf; ';
|
||||
put ' input &input_statement; ';
|
||||
put ' run; ';
|
||||
put ' %end; ';
|
||||
@@ -451,7 +456,8 @@ data _null_;
|
||||
put ' ';
|
||||
put ' /* setup temp ref */ ';
|
||||
put ' %if %upcase(&fref) ne _WEBOUT %then %do; ';
|
||||
put ' filename &fref temp lrecl=999999 permission=''A::u::rwx,A::g::rw-,A::o::---'' mod; ';
|
||||
put ' filename &fref temp lrecl=999999 permission=''A::u::rwx,A::g::rw-,A::o::---'' ';
|
||||
put ' mod; ';
|
||||
put ' %end; ';
|
||||
put ' ';
|
||||
put ' /* setup json */ ';
|
||||
@@ -461,7 +467,7 @@ data _null_;
|
||||
put '%end; ';
|
||||
put '%else %if &action=ARR or &action=OBJ %then %do; ';
|
||||
put ' %mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt ';
|
||||
put ' ,jref=&fref,engine=PROCJSON,dbg=%str(&_debug) ';
|
||||
put ' ,jref=&fref,engine=DATASTEP,dbg=%str(&_debug) ';
|
||||
put ' ) ';
|
||||
put '%end; ';
|
||||
put '%else %if &action=CLOSE %then %do; ';
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
|
||||
First, compile the macros:
|
||||
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
Next, create a job (in this case, a web service):
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
@li FLOW_ID - Numeric value, provides sequential ordering capability. Is
|
||||
optional, will default to 0 if not provided.
|
||||
@li _CONTEXTNAME - Dictates which context should be used to run the job. If
|
||||
blank (or not provided), will default to `SAS Job Execution compute context`.
|
||||
blank, or not provided, will default to `SAS Job Execution compute context`.
|
||||
|
||||
Any additional variables provided in this table are converted into macro
|
||||
variables and passed into the relevant job.
|
||||
@@ -97,12 +97,14 @@
|
||||
run;
|
||||
|
||||
|
||||
@param [in] access_token_var= The global macro variable to contain the access token
|
||||
@param [in] access_token_var= The global macro variable to contain the access
|
||||
token
|
||||
@param [in] grant_type= valid values:
|
||||
@li password
|
||||
@li authorization_code
|
||||
@li detect - will check if access_token exists, if not will use sas_services if
|
||||
a SASStudioV session else authorization_code. Default option.
|
||||
@li detect - will check if access_token exists, if not will use
|
||||
sas_services if a SASStudioV session else authorization_code. Default
|
||||
option.
|
||||
@li sas_services - will use oauth_bearer=sas_services
|
||||
@param [in] inds= The input dataset containing a list of jobs and parameters
|
||||
@param [in] maxconcurrency= The max number of parallel jobs to run. Default=8.
|
||||
@@ -185,7 +187,7 @@ select count(*) into: missings
|
||||
where flow_id is null or _program is null;
|
||||
%mp_abort(iftrue=(&missings>0)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(input dataset contains &missings missing values for FLOW_ID or _PROGRAM)
|
||||
,msg=%str(input dataset has &missings missing values for FLOW_ID or _PROGRAM)
|
||||
)
|
||||
|
||||
%if %mf_nobs(&inds)=0 %then %do;
|
||||
@@ -284,7 +286,8 @@ data;run;%let jdswaitfor=&syslast;
|
||||
%if "&&jobuid&jid"="0" and &concurrency<&maxconcurrency %then %do;
|
||||
%local jobname jobpath;
|
||||
%let jobname=%scan(&&job&jid,-1,/);
|
||||
%let jobpath=%substr(&&job&jid,1,%length(&&job&jid)-%length(&jobname)-1);
|
||||
%let jobpath=
|
||||
%substr(&&job&jid,1,%length(&&job&jid)-%length(&jobname)-1);
|
||||
%put executing &jobpath/&jobname with paramstring &&jparams&jid;
|
||||
%mv_jobexecute(path=&jobpath
|
||||
,name=&jobname
|
||||
@@ -334,7 +337,8 @@ data;run;%let jdswaitfor=&syslast;
|
||||
/* loop again if jobs are left */
|
||||
%if &completed < &jcnt %then %do;
|
||||
%let jid=0;
|
||||
%put looping flow &fid again - &completed of &jcnt jobs completed, &concurrency jobs running;
|
||||
%put looping flow &fid again - &completed of &jcnt jobs completed,
|
||||
&concurrency jobs running;
|
||||
%end;
|
||||
%end;
|
||||
%end;
|
||||
|
||||
@@ -5,14 +5,16 @@
|
||||
This macro will obtain the Consul Token and use that to call the Web Service.
|
||||
|
||||
more info: https://developer.sas.com/reference/auth/#register
|
||||
and: http://proc-x.com/2019/01/authentication-to-sas-viya-a-couple-of-approaches/
|
||||
and:
|
||||
http://proc-x.com/2019/01/authentication-to-sas-viya-a-couple-of-approaches
|
||||
|
||||
The default viyaroot location is /opt/sas/viya/config
|
||||
|
||||
Usage:
|
||||
|
||||
%* compile macros;
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
%* specific client with just openid scope;
|
||||
@@ -33,7 +35,8 @@
|
||||
@param client_id= The client name. Auto generated if blank.
|
||||
@param client_secret= Client secret Auto generated if client is blank.
|
||||
@param scopes= list of space-seperated unquoted scopes (default is openid)
|
||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted)
|
||||
@param grant_type= valid values are "password" or "authorization_code"
|
||||
(unquoted)
|
||||
@param outds= the dataset to contain the registered client id and secret
|
||||
@param access_token_validity= The duration of validity of the access token
|
||||
in seconds. A value of DEFAULT will omit the entry (and use system default)
|
||||
@@ -78,15 +81,16 @@
|
||||
,refresh_token_validity=DEFAULT
|
||||
,outjson=_null_
|
||||
);
|
||||
%local consul_token fname1 fname2 fname3 libref access_token url;
|
||||
%local consul_token fname1 fname2 fname3 libref access_token url tokloc;
|
||||
|
||||
%if client_name=DEFAULT %then %let client_name=
|
||||
Generated by %mf_getuser() on %sysfunc(datetime(),datetime19.) using SASjs;
|
||||
|
||||
options noquotelenmax;
|
||||
/* first, get consul token needed to get client id / secret */
|
||||
%let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default;
|
||||
data _null_;
|
||||
infile "%mf_loc(VIYACONFIG)/etc/SASSecurityCertificateFramework/tokens/consul/default/client.token";
|
||||
infile "%mf_loc(VIYACONFIG)&tokloc/client.token";
|
||||
input token:$64.;
|
||||
call symputx('consul_token',token);
|
||||
run;
|
||||
@@ -97,7 +101,8 @@ run;
|
||||
/* request the client details */
|
||||
%let fname1=%mf_getuniquefileref();
|
||||
proc http method='POST' out=&fname1
|
||||
url="&base_uri/SASLogon/oauth/clients/consul?callback=false%str(&)serviceId=app";
|
||||
url="&base_uri/SASLogon/oauth/clients/consul?callback=false%str(&)%trim(
|
||||
)serviceId=app";
|
||||
headers "X-Consul-Token"="&consul_token";
|
||||
run;
|
||||
|
||||
@@ -122,7 +127,8 @@ run;
|
||||
%let scopes=%sysfunc(coalescec(&scopes,openid));
|
||||
%let scopes=%mf_getquotedstr(&scopes,QUOTE=D,indlm=|);
|
||||
%let grant_type=%mf_getquotedstr(&grant_type,QUOTE=D,indlm=|);
|
||||
%let required_user_groups=%mf_getquotedstr(&required_user_groups,QUOTE=D,indlm=|);
|
||||
%let required_user_groups=
|
||||
%mf_getquotedstr(&required_user_groups,QUOTE=D,indlm=|);
|
||||
|
||||
data _null_;
|
||||
file &fname2;
|
||||
@@ -139,9 +145,11 @@ data _null_;
|
||||
if reqd_groups = '""' then reqd_groups ='';
|
||||
else reqd_groups=cats(',"required_user_groups":[',reqd_groups,']');
|
||||
autoapprove=trim(symget('autoapprove'));
|
||||
if not missing(autoapprove) then autoapprove=cats(',"autoapprove":',autoapprove);
|
||||
if not missing(autoapprove) then autoapprove=
|
||||
cats(',"autoapprove":',autoapprove);
|
||||
use_session=trim(symget('use_session'));
|
||||
if not missing(use_session) then use_session=cats(',"use_session":',use_session);
|
||||
if not missing(use_session) then use_session=
|
||||
cats(',"use_session":',use_session);
|
||||
|
||||
put '{' clientid ;
|
||||
put clientsecret ;
|
||||
@@ -206,10 +214,12 @@ run;
|
||||
%put GRANT_TYPE=&grant_type;
|
||||
%put;
|
||||
%if %index(%superq(grant_type),authorization_code) %then %do;
|
||||
/* cannot use base_uri here as it includes the protocol which may be incorrect externally */
|
||||
%put NOTE: The developer must also register below and select 'openid' to get the grant code:;
|
||||
/* cannot use base_uri here as it includes the protocol which may be incorrect
|
||||
externally */
|
||||
%put NOTE: Visit the link below and select 'openid' to get the grant code:;
|
||||
%put NOTE- ;
|
||||
%put NOTE- &url/SASLogon/oauth/authorize?client_id=&client_id%str(&)response_type=code;
|
||||
%put NOTE- &url/SASLogon/oauth/authorize?client_id=&client_id%str(&)%trim(
|
||||
)response_type=code;
|
||||
%put NOTE- ;
|
||||
%end;
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
Usage:
|
||||
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
|
||||
@@ -31,13 +32,15 @@
|
||||
@param outds= A dataset containing access_token and refresh_token
|
||||
@param client_id= The client name
|
||||
@param client_secret= client secret
|
||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
The default is authorization_code.
|
||||
@param code= If grant_type=authorization_code then provide the necessary code here
|
||||
@param grant_type= valid values are "password" or "authorization_code"
|
||||
(unquoted). The default is authorization_code.
|
||||
@param code= If grant_type=authorization_code then provide the necessary code
|
||||
here
|
||||
@param user= If grant_type=password then provide the username here
|
||||
@param pass= If grant_type=password then provide the password here
|
||||
@param access_token_var= The global macro variable to contain the access token
|
||||
@param refresh_token_var= The global macro variable to contain the refresh token
|
||||
@param refresh_token_var= The global macro variable to contain the refresh
|
||||
token
|
||||
@param base_uri= The Viya API server location
|
||||
|
||||
@version VIYA V.03.04
|
||||
@@ -88,7 +91,8 @@
|
||||
,msg=%str(Authorization code required)
|
||||
)
|
||||
|
||||
%mp_abort(iftrue=(&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
|
||||
%mp_abort(iftrue=(
|
||||
&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(username / password required)
|
||||
)
|
||||
|
||||
@@ -32,12 +32,13 @@
|
||||
@param outds= A dataset containing access_token and refresh_token
|
||||
@param client_id= The client name (alternative to inds)
|
||||
@param client_secret= client secret (alternative to inds)
|
||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
The default is authorization_code.
|
||||
@param grant_type= valid values are "password" or "authorization_code"
|
||||
(unquoted). The default is authorization_code.
|
||||
@param user= If grant_type=password then provide the username here
|
||||
@param pass= If grant_type=password then provide the password here
|
||||
@param access_token_var= The global macro variable to contain the access token
|
||||
@param refresh_token_var= The global macro variable containing the refresh token
|
||||
@param refresh_token_var= The global macro variable containing the refresh
|
||||
token
|
||||
|
||||
@version VIYA V.03.04
|
||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
||||
@@ -72,7 +73,8 @@ options noquotelenmax;
|
||||
,msg=%str(Invalid value for grant_type: &grant_type)
|
||||
)
|
||||
|
||||
%mp_abort(iftrue=(&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
|
||||
%mp_abort(
|
||||
iftrue=(&grant_type=password and (%str(&user)=%str() or %str(&pass)=%str()))
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(username / password required)
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
@file mv_webout.sas
|
||||
@file
|
||||
@brief Send data to/from the SAS Viya Job Execution Service
|
||||
@details This macro should be added to the start of each Job Execution
|
||||
Service, **immediately** followed by a call to:
|
||||
@@ -109,7 +109,8 @@
|
||||
if _n_=1 then call symputx('input_statement',_infile_);
|
||||
list;
|
||||
data &table;
|
||||
infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd termstr=crlf;
|
||||
infile "%sysfunc(pathname(work))/&table..csv" firstobs=2 dsd
|
||||
termstr=crlf;
|
||||
input &input_statement;
|
||||
run;
|
||||
%end;
|
||||
@@ -150,7 +151,8 @@
|
||||
|
||||
/* setup temp ref */
|
||||
%if %upcase(&fref) ne _WEBOUT %then %do;
|
||||
filename &fref temp lrecl=999999 permission='A::u::rwx,A::g::rw-,A::o::---' mod;
|
||||
filename &fref temp lrecl=999999 permission='A::u::rwx,A::g::rw-,A::o::---'
|
||||
mod;
|
||||
%end;
|
||||
|
||||
/* setup json */
|
||||
@@ -160,7 +162,7 @@
|
||||
%end;
|
||||
%else %if &action=ARR or &action=OBJ %then %do;
|
||||
%mp_jsonout(&action,&ds,dslabel=&dslabel,fmt=&fmt
|
||||
,jref=&fref,engine=PROCJSON,dbg=%str(&_debug)
|
||||
,jref=&fref,engine=DATASTEP,dbg=%str(&_debug)
|
||||
)
|
||||
%end;
|
||||
%else %if &action=CLOSE %then %do;
|
||||
|
||||
Reference in New Issue
Block a user