mirror of
https://github.com/sasjs/core.git
synced 2025-12-19 09:34:34 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4c2be7411 | ||
|
|
16489a9494 | ||
|
|
0e03b06a4b | ||
|
|
c3b89c7f7d | ||
|
|
142b46570d | ||
|
|
f7fac50108 | ||
|
|
ae5fbcf857 | ||
|
|
2579b4c929 | ||
|
|
90a831f59b | ||
|
|
9fb218f0be | ||
|
|
ccc9dfa4aa | ||
|
|
a37a72b7db | ||
|
|
c6dcf919e2 | ||
|
|
42541373af | ||
|
|
208c88f5a4 | ||
|
|
5605bc74df | ||
|
|
4bec574011 | ||
|
|
8cfa37ce8b | ||
|
|
351ceeb357 | ||
|
|
259bcc0173 | ||
|
|
db195a8311 |
10
README.md
10
README.md
@@ -125,6 +125,7 @@ filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
|||||||
- macro names must be lowercase
|
- macro names must be lowercase
|
||||||
- one macro per file
|
- one macro per file
|
||||||
- prefixes:
|
- prefixes:
|
||||||
|
- _mcf_ for macro compiled functions (proc fcmp)
|
||||||
- _mf_ for macro functions (can be used in open code).
|
- _mf_ for macro functions (can be used in open code).
|
||||||
- _ml_ for macros that are used to compile LUA modules
|
- _ml_ for macros that are used to compile LUA modules
|
||||||
- _mm_ for metadata macros (interface with the metadata server).
|
- _mm_ for metadata macros (interface with the metadata server).
|
||||||
@@ -166,7 +167,7 @@ SAS code can contain one of two types of dependency - SAS Macros, and SAS Includ
|
|||||||
@li someprogram.sas FREFTWO
|
@li someprogram.sas FREFTWO
|
||||||
```
|
```
|
||||||
|
|
||||||
The CLI can then extract all the dependencies and insert as precode (SAS Macros) or in a temp engine fileref (SAS Includes) when creating SAS Jobs and Services.
|
The CLI can then extract all the dependencies and insert as precode (SAS Macros) or in a temp engine fileref (SAS Includes) when creating SAS Jobs and Services (and Tests).
|
||||||
|
|
||||||
When contributing to this library, it is therefore important to ensure that all dependencies are listed in the header in this format.
|
When contributing to this library, it is therefore important to ensure that all dependencies are listed in the header in this format.
|
||||||
|
|
||||||
@@ -182,7 +183,9 @@ When contributing to this library, it is therefore important to ensure that all
|
|||||||
- Mandatory parameters should be positional, all optional parameters should be keyword (var=) style.
|
- Mandatory parameters should be positional, all optional parameters should be keyword (var=) style.
|
||||||
- All dataset references must be 2 level (eg `work.blah`, not `blah`). This is to avoid contention when options [DATASTMTCHK](https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000279064.htm)=ALLKEYWORDS is in effect.
|
- All dataset references must be 2 level (eg `work.blah`, not `blah`). This is to avoid contention when options [DATASTMTCHK](https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000279064.htm)=ALLKEYWORDS is in effect.
|
||||||
- Avoid naming collisions! All macro variables should be local scope. Use system generated work tables where possible - eg `data ; set sashelp.class; run; data &output; set &syslast; run;`
|
- Avoid naming collisions! All macro variables should be local scope. Use system generated work tables where possible - eg `data ; set sashelp.class; run; data &output; set &syslast; run;`
|
||||||
|
- Where global macro variables are absolutely necessary, they should make use of `&sasjs_prefix` - see mp_init.sas
|
||||||
- The use of `quit;` for `proc sql` is optional unless you are looking to benefit from the timing statistics.
|
- The use of `quit;` for `proc sql` is optional unless you are looking to benefit from the timing statistics.
|
||||||
|
- Use [sasjs lint](https://github.com/sasjs/lint)!
|
||||||
|
|
||||||
## General Notes
|
## General Notes
|
||||||
|
|
||||||
@@ -190,10 +193,9 @@ When contributing to this library, it is therefore important to ensure that all
|
|||||||
|
|
||||||
## Breaking Changes
|
## Breaking Changes
|
||||||
|
|
||||||
We are currently on major release v3. The following changes are planned when the next major (breaking) release becomes necessary:
|
We are currently on major release v4. Breaking changes should be marked with the [deprecated](https://www.doxygen.nl/manual/commands.html#cmddeprecated) doxygen tag. The following changes are planned when the next major (breaking) release becomes necessary:
|
||||||
|
|
||||||
* Remove `dbg` parameter from mp_jsonout.sas (implement mdebug instead)
|
* (None as yet)
|
||||||
* Remove `END_DTTM` and `START_DTTM` from mx_webout JSON
|
|
||||||
|
|
||||||
## Star Gazing
|
## Star Gazing
|
||||||
|
|
||||||
|
|||||||
621
all.sas
621
all.sas
@@ -29,7 +29,7 @@ options noquotelenmax;
|
|||||||
@cond
|
@cond
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_abort(mac=mf_abort.sas, type=deprecated, msg=, iftrue=%str(1=1)
|
%macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1)
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%if not(%eval(%unquote(&iftrue))) %then %return;
|
%if not(%eval(%unquote(&iftrue))) %then %return;
|
||||||
@@ -2198,7 +2198,8 @@ Usage:
|
|||||||
if symexist('_debug') then debug=quote(trim(symget('_debug')));
|
if symexist('_debug') then debug=quote(trim(symget('_debug')));
|
||||||
else debug='""';
|
else debug='""';
|
||||||
put '>>weboutBEGIN<<';
|
put '>>weboutBEGIN<<';
|
||||||
put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
|
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
||||||
|
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
||||||
put ',"sasjsAbort" : [{';
|
put ',"sasjsAbort" : [{';
|
||||||
put ' "MSG":' msg ;
|
put ' "MSG":' msg ;
|
||||||
put ' ,"MAC": "' "&mac" '"}]';
|
put ' ,"MAC": "' "&mac" '"}]';
|
||||||
@@ -2227,7 +2228,7 @@ Usage:
|
|||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
syswarningtext=quote(trim(symget('syswarningtext')));
|
syswarningtext=quote(trim(symget('syswarningtext')));
|
||||||
put ",""SYSWARNINGTEXT"" : " syswarningtext;
|
put ",""SYSWARNINGTEXT"" : " syswarningtext;
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||||
put "}" @;
|
put "}" @;
|
||||||
put '>>weboutEND<<';
|
put '>>weboutEND<<';
|
||||||
run;
|
run;
|
||||||
@@ -3005,6 +3006,124 @@ run;
|
|||||||
drop table &ds;
|
drop table &ds;
|
||||||
|
|
||||||
%mend mp_assertdsobs;/**
|
%mend mp_assertdsobs;/**
|
||||||
|
@file
|
||||||
|
@brief Used to capture scope leakage of macro variables
|
||||||
|
@details A common 'difficult to detect' bug in macros is where a nested
|
||||||
|
macro over-writes variables in a higher level macro.
|
||||||
|
|
||||||
|
This assertion takes a snapshot of the macro variables before and after
|
||||||
|
a macro invocation. This makes it easy to detect whether any macro
|
||||||
|
variables were modified or changed.
|
||||||
|
|
||||||
|
Currently, the macro only checks for global scope variables. In the future
|
||||||
|
it may be extended to work at multiple levels of nesting.
|
||||||
|
|
||||||
|
If you would like this feature, feel free to contribute / raise an issue /
|
||||||
|
engage the SASjs team directly.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
|
||||||
|
%let oops=I did it again;
|
||||||
|
|
||||||
|
%mp_assertscope(COMPARE,
|
||||||
|
desc=Checking macro variables against previous snapshot
|
||||||
|
)
|
||||||
|
|
||||||
|
@param [in] action (SNAPSHOT) The action to take. Valid values:
|
||||||
|
@li SNAPSHOT - take a copy of the current macro variables
|
||||||
|
@li COMPARE - compare the current macro variables against previous values
|
||||||
|
@param [in] scope= (GLOBAL) The scope of the variables to be checked. This
|
||||||
|
corresponds to the values in the SCOPE column in `sashelp.vmacro`.
|
||||||
|
@param [in] desc= (Testing scope leakage) The user provided test description
|
||||||
|
@param [in,out] scopeds= (work.mp_assertscope) The dataset to contain the
|
||||||
|
scope snapshot
|
||||||
|
@param [out] outds= (work.test_results) The output dataset to contain the
|
||||||
|
results. If it does not exist, it will be created, with the following format:
|
||||||
|
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|
||||||
|
|---|---|---|
|
||||||
|
|User Provided description|PASS|No out of scope variables created or modified|
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertcols.sas
|
||||||
|
@li mp_assertcolvals.sas
|
||||||
|
@li mp_assertdsobs.sas
|
||||||
|
@li mp_assertscope.test.sas
|
||||||
|
|
||||||
|
@version 9.2
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_assertscope(action,
|
||||||
|
desc=Testing Scope Leakage,
|
||||||
|
scope=GLOBAL,
|
||||||
|
scopeds=work.mp_assertscope,
|
||||||
|
outds=work.test_results
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
%local ds test_result test_comments del add mod;
|
||||||
|
|
||||||
|
/* get current variables */
|
||||||
|
%if &action=SNAPSHOT %then %do;
|
||||||
|
proc sql;
|
||||||
|
create table &scopeds as
|
||||||
|
select name,offset,value
|
||||||
|
from dictionary.macros
|
||||||
|
where scope="&scope"
|
||||||
|
order by name,offset;
|
||||||
|
%end;
|
||||||
|
%else %if &action=COMPARE %then %do;
|
||||||
|
|
||||||
|
proc sql;
|
||||||
|
create table _data_ as
|
||||||
|
select name,offset,value
|
||||||
|
from dictionary.macros
|
||||||
|
where scope="&scope"
|
||||||
|
order by name,offset;
|
||||||
|
|
||||||
|
%let ds=&syslast;
|
||||||
|
|
||||||
|
proc compare base=&scopeds compare=&ds;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%if &sysinfo=0 %then %do;
|
||||||
|
%let test_result=PASS;
|
||||||
|
%let test_comments=&scope Variables Unmodified;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
proc sql noprint undo_policy=none;
|
||||||
|
select distinct name into: del separated by ' ' from &scopeds
|
||||||
|
where name not in (select name from &ds);
|
||||||
|
select distinct name into: add separated by ' ' from &ds
|
||||||
|
where name not in (select name from &scopeds);
|
||||||
|
select distinct a.name into: mod separated by ' '
|
||||||
|
from &scopeds a
|
||||||
|
inner join &ds b
|
||||||
|
on a.name=b.name
|
||||||
|
and a.offset=b.offset
|
||||||
|
where a.value ne b.value;
|
||||||
|
%let test_result=FAIL;
|
||||||
|
%let test_comments=%str(Mod:(&mod) Add:(&add) Del:(&del));
|
||||||
|
%end;
|
||||||
|
|
||||||
|
|
||||||
|
data ;
|
||||||
|
length test_description $256 test_result $4 test_comments $256;
|
||||||
|
test_description=symget('desc');
|
||||||
|
test_comments=symget('test_comments');
|
||||||
|
test_result=symget('test_result');
|
||||||
|
run;
|
||||||
|
|
||||||
|
%let ds=&syslast;
|
||||||
|
proc append base=&outds data=&ds;
|
||||||
|
run;
|
||||||
|
proc sql;
|
||||||
|
drop table &ds;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend mp_assertscope;/**
|
||||||
@file
|
@file
|
||||||
@brief Convert a file to/from base64 format
|
@brief Convert a file to/from base64 format
|
||||||
@details Creates a new version of a file either encoded or decoded using
|
@details Creates a new version of a file either encoded or decoded using
|
||||||
@@ -3863,8 +3982,7 @@ run;
|
|||||||
Credit for the rename approach:
|
Credit for the rename approach:
|
||||||
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
|
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
|
||||||
|
|
||||||
|
Usage:
|
||||||
usage:
|
|
||||||
|
|
||||||
%mp_dirlist(path=/some/location, outds=myTable, maxdepth=MAX)
|
%mp_dirlist(path=/some/location, outds=myTable, maxdepth=MAX)
|
||||||
|
|
||||||
@@ -3880,12 +3998,12 @@ run;
|
|||||||
X CMD) do please raise an issue!
|
X CMD) do please raise an issue!
|
||||||
|
|
||||||
|
|
||||||
@param [in] path= for which to return contents
|
@param [in] path= (%sysfunc(pathname(work))) Path for which to return contents
|
||||||
@param [in] fref= Provide a DISK engine fileref as an alternative to PATH
|
@param [in] fref= (0) Provide a DISK engine fileref as an alternative to PATH
|
||||||
@param [in] maxdepth= (0) Set to a positive integer to indicate the level of
|
@param [in] maxdepth= (0) Set to a positive integer to indicate the level of
|
||||||
subdirectory scan recursion - eg 3, to go `./3/levels/deep`. For unlimited
|
subdirectory scan recursion - eg 3, to go `./3/levels/deep`. For unlimited
|
||||||
recursion, set to MAX.
|
recursion, set to MAX.
|
||||||
@param [out] outds= the output dataset to create
|
@param [out] outds= (work.mp_dirlist) The output dataset to create
|
||||||
@param [out] getattrs= (NO) If getattrs=YES then the doptname / foptname
|
@param [out] getattrs= (NO) If getattrs=YES then the doptname / foptname
|
||||||
functions are used to scan all properties - any characters that are not
|
functions are used to scan all properties - any characters that are not
|
||||||
valid in a SAS name (v7) are simply stripped, and the table is transposed
|
valid in a SAS name (v7) are simply stripped, and the table is transposed
|
||||||
@@ -3906,13 +4024,15 @@ run;
|
|||||||
- OS SPECIFIC variables, if <code>getattrs=</code> is used.
|
- OS SPECIFIC variables, if <code>getattrs=</code> is used.
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_existds.sas
|
||||||
|
@li mf_getvarlist.sas
|
||||||
|
@li mf_wordsinstr1butnotstr2.sas
|
||||||
@li mp_dropmembers.sas
|
@li mp_dropmembers.sas
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
<h4> Related Macros </h4>
|
||||||
@li mp_dirlist.test.sas
|
@li mp_dirlist.test.sas
|
||||||
|
|
||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mp_dirlist(path=%sysfunc(pathname(work))
|
%macro mp_dirlist(path=%sysfunc(pathname(work))
|
||||||
@@ -4050,9 +4170,29 @@ data &out_ds;
|
|||||||
set &out_ds(where=(filepath ne ''));
|
set &out_ds(where=(filepath ne ''));
|
||||||
run;
|
run;
|
||||||
|
|
||||||
/* update main table */
|
/**
|
||||||
proc append base=&outds data=&out_ds;
|
* The above transpose can mean that some updates create additional columns.
|
||||||
run;
|
* This necessitates the occasional use of datastep over proc append.
|
||||||
|
*/
|
||||||
|
%if %mf_existds(&outds) %then %do;
|
||||||
|
%local basevars appvars newvars;
|
||||||
|
%let basevars=%mf_getvarlist(&outds);
|
||||||
|
%let appvars=%mf_getvarlist(&out_ds);
|
||||||
|
%let newvars=%length(%mf_wordsinstr1butnotstr2(Str1=&appvars,Str2=&basevars));
|
||||||
|
%if &newvars>0 %then %do;
|
||||||
|
data &outds;
|
||||||
|
set &outds &out_ds;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
proc append base=&outds data=&out_ds force nowarn;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
proc append base=&outds data=&out_ds;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
/* recursive call */
|
/* recursive call */
|
||||||
%if &maxdepth>&level or &maxdepth=MAX %then %do;
|
%if &maxdepth>&level or &maxdepth=MAX %then %do;
|
||||||
@@ -4306,8 +4446,9 @@ create table datalines1 as
|
|||||||
/**
|
/**
|
||||||
Due to long decimals cannot use best. format
|
Due to long decimals cannot use best. format
|
||||||
So - use bestd. format and then use character functions to strip trailing
|
So - use bestd. format and then use character functions to strip trailing
|
||||||
zeros, if NOT an integer!!
|
zeros, if NOT an integer or missing!! Cannot use int() as it upsets
|
||||||
resolved code = ifc(int(VARIABLE)=VARIABLE
|
note2err when there are missings.
|
||||||
|
resolved code = ifc( mod(coalesce(VARIABLE,0),1)=0
|
||||||
,put(VARIABLE,best32.)
|
,put(VARIABLE,best32.)
|
||||||
,substrn(put(VARIABLE,bestd32.),1
|
,substrn(put(VARIABLE,bestd32.),1
|
||||||
,findc(put(VARIABLE,bestd32.),'0','TBK')));
|
,findc(put(VARIABLE,bestd32.),'0','TBK')));
|
||||||
@@ -4318,7 +4459,7 @@ data datalines_2;
|
|||||||
set datalines1 (where=(upcase(name) not in
|
set datalines1 (where=(upcase(name) not in
|
||||||
('PROCESSED_DTTM','VALID_FROM_DTTM','VALID_TO_DTTM')));
|
('PROCESSED_DTTM','VALID_FROM_DTTM','VALID_TO_DTTM')));
|
||||||
if type='num' then dataline=
|
if type='num' then dataline=
|
||||||
cats('ifc(int(',name,')=',name,'
|
cats('ifc(mod(coalesce(',name,',0),1)=0
|
||||||
,put(',name,',best32.-l)
|
,put(',name,',best32.-l)
|
||||||
,substrn(put(',name,',bestd32.-l),1
|
,substrn(put(',name,',bestd32.-l),1
|
||||||
,findc(put(',name,',bestd32.-l),"0","TBK")))');
|
,findc(put(',name,',bestd32.-l),"0","TBK")))');
|
||||||
@@ -4492,7 +4633,7 @@ data _null_;
|
|||||||
dsid=open("&ds.","i");
|
dsid=open("&ds.","i");
|
||||||
num=attrn(dsid,"nvars");
|
num=attrn(dsid,"nvars");
|
||||||
do i=1 to num;
|
do i=1 to num;
|
||||||
header = trim(left(coalescec(varlabel(dsid,i),varname(dsid,i))));
|
header = cats(coalescec(varlabel(dsid,i),varname(dsid,i)));
|
||||||
put header @;
|
put header @;
|
||||||
end;
|
end;
|
||||||
rc=close(dsid);
|
rc=close(dsid);
|
||||||
@@ -4887,6 +5028,124 @@ run;
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mp_ds2md;/**
|
%mend mp_ds2md;/**
|
||||||
|
@file
|
||||||
|
@brief Create a smaller version of a dataset, without data loss
|
||||||
|
@details This macro will scan the input dataset and create a new one, that
|
||||||
|
has the minimum variable lengths needed to store the data without data loss.
|
||||||
|
|
||||||
|
Inspiration was taken from [How to Reduce the Disk Space Required by a
|
||||||
|
SAS® Data Set](https://www.lexjansen.com/nesug/nesug06/io/io18.pdf) by
|
||||||
|
Selvaratnam Sridharma. The end of the referenced paper presents a macro named
|
||||||
|
"squeeze", hence the nomenclature.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
data big;
|
||||||
|
length my big $32000;
|
||||||
|
do i=1 to 1e4;
|
||||||
|
my=repeat('oh my',100);
|
||||||
|
big='dawg';
|
||||||
|
special=._;
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_ds2squeeze(work.big,outds=work.smaller)
|
||||||
|
|
||||||
|
The following will also be printed to the log (exact values may differ
|
||||||
|
depending on your OS and COMPRESS settings):
|
||||||
|
|
||||||
|
> MP_DS2SQUEEZE: work.big was 625MB
|
||||||
|
|
||||||
|
> MP_DS2SQUEEZE: work.smaller is 5MB
|
||||||
|
|
||||||
|
@param [in] libds The library.dataset to be squeezed
|
||||||
|
@param [out] outds= (work.mp_ds2squeeze) The squeezed dataset to create
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getfilesize.sas
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
|
@li mp_getmaxvarlengths.sas
|
||||||
|
|
||||||
|
<h4> Related Programs </h4>
|
||||||
|
@li mp_ds2squeeze.test.sas
|
||||||
|
|
||||||
|
@version 9.3
|
||||||
|
@author Allan Bowe
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_ds2squeeze(
|
||||||
|
libds,
|
||||||
|
outds=work.work.mp_ds2squeeze,
|
||||||
|
mdebug=0
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
%local dbg source;
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
%put &sysmacroname entry vars:;
|
||||||
|
%put _local_;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
%let dbg=*;
|
||||||
|
%let source=/source2;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%local optval ds fref;
|
||||||
|
%let ds=%mf_getuniquename();
|
||||||
|
%let fref=%mf_getuniquefileref();
|
||||||
|
|
||||||
|
%mp_getmaxvarlengths(&libds,outds=&ds)
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
set &ds end=last;
|
||||||
|
file &fref;
|
||||||
|
/* grab the types */
|
||||||
|
retain dsid;
|
||||||
|
if _n_=1 then dsid=open("&libds",'is');
|
||||||
|
if dsid le 0 then do;
|
||||||
|
msg=sysmsg();
|
||||||
|
put msg=;
|
||||||
|
stop;
|
||||||
|
end;
|
||||||
|
type=vartype(dsid,varnum(dsid, name));
|
||||||
|
if last then rc=close(dsid);
|
||||||
|
/* write out the length statement */
|
||||||
|
if _n_=1 then put 'length ';
|
||||||
|
length len $6;
|
||||||
|
if type='C' then do;
|
||||||
|
if maxlen=0 then len='$1';
|
||||||
|
else len=cats('$',maxlen);
|
||||||
|
end;
|
||||||
|
else do;
|
||||||
|
if maxlen=0 then len='3';
|
||||||
|
else len=cats(maxlen);
|
||||||
|
end;
|
||||||
|
put ' ' name ' ' len;
|
||||||
|
if last then put ';';
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* configure varlenchk - as we are explicitly shortening the variables */
|
||||||
|
%let optval=%sysfunc(getoption(varlenchk));
|
||||||
|
options varlenchk=NOWARN;
|
||||||
|
|
||||||
|
data &outds;
|
||||||
|
%inc &fref &source;
|
||||||
|
set &libds;
|
||||||
|
run;
|
||||||
|
|
||||||
|
options varlenchk=&optval;
|
||||||
|
|
||||||
|
%if &mdebug=0 %then %do;
|
||||||
|
proc sql;
|
||||||
|
drop table &ds;
|
||||||
|
filename &fref clear;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%put &sysmacroname: &libds was %mf_getfilesize(libds=&libds,format=yes);
|
||||||
|
%put &sysmacroname: &outds is %mf_getfilesize(libds=&outds,format=yes);
|
||||||
|
|
||||||
|
%mend mp_ds2squeeze;/**
|
||||||
@file
|
@file
|
||||||
@brief Checks an input filter table for validity
|
@brief Checks an input filter table for validity
|
||||||
@details Performs checks on the input table to ensure it arrives in the
|
@details Performs checks on the input table to ensure it arrives in the
|
||||||
@@ -4997,7 +5256,7 @@ data &outds;
|
|||||||
output;
|
output;
|
||||||
end;
|
end;
|
||||||
if mod(SUBGROUP_ID,1) ne 0 then do;
|
if mod(SUBGROUP_ID,1) ne 0 then do;
|
||||||
REASON_CD='SUBGROUP_ID should be integer, not '!!left(subgroup_id);
|
REASON_CD='SUBGROUP_ID should be integer, not '!!cats(subgroup_id);
|
||||||
putlog REASON_CD= SUBGROUP_ID=;
|
putlog REASON_CD= SUBGROUP_ID=;
|
||||||
call symputx('reason_cd',reason_cd,'l');
|
call symputx('reason_cd',reason_cd,'l');
|
||||||
call symputx('nobs',_n_,'l');
|
call symputx('nobs',_n_,'l');
|
||||||
@@ -5015,7 +5274,7 @@ data &outds;
|
|||||||
if OPERATOR_NM not in
|
if OPERATOR_NM not in
|
||||||
('=','>','<','<=','>=','BETWEEN','IN','NOT IN','NE','CONTAINS')
|
('=','>','<','<=','>=','BETWEEN','IN','NOT IN','NE','CONTAINS')
|
||||||
then do;
|
then do;
|
||||||
REASON_CD='Invalid OPERATOR_NM: '!!left(OPERATOR_NM);
|
REASON_CD='Invalid OPERATOR_NM: '!!cats(OPERATOR_NM);
|
||||||
putlog REASON_CD= OPERATOR_NM=;
|
putlog REASON_CD= OPERATOR_NM=;
|
||||||
call symputx('reason_cd',reason_cd,'l');
|
call symputx('reason_cd',reason_cd,'l');
|
||||||
call symputx('nobs',_n_,'l');
|
call symputx('nobs',_n_,'l');
|
||||||
@@ -6181,7 +6440,7 @@ run;
|
|||||||
lab=" label="!!cats("'",tranwrd(label,"'","''"),"'");
|
lab=" label="!!cats("'",tranwrd(label,"'","''"),"'");
|
||||||
if notnull='yes' then notnul=' not null';
|
if notnull='yes' then notnul=' not null';
|
||||||
if type='char' then typ=cats('char(',length,')');
|
if type='char' then typ=cats('char(',length,')');
|
||||||
else if length ne 8 then typ='num length='!!left(length);
|
else if length ne 8 then typ='num length='!!cats(length);
|
||||||
else typ='num';
|
else typ='num';
|
||||||
put name typ fmt notnul lab;
|
put name typ fmt notnul lab;
|
||||||
run;
|
run;
|
||||||
@@ -6562,7 +6821,7 @@ create table &outsummary as
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mp_getformats;/**
|
%mend mp_getformats;/**
|
||||||
@file mp_getmaxvarlengths.sas
|
@file
|
||||||
@brief Scans a dataset to find the max length of the variable values
|
@brief Scans a dataset to find the max length of the variable values
|
||||||
@details
|
@details
|
||||||
This macro will scan a base dataset and produce an output dataset with two
|
This macro will scan a base dataset and produce an output dataset with two
|
||||||
@@ -6571,21 +6830,39 @@ create table &outsummary as
|
|||||||
- NAME Name of the base dataset column
|
- NAME Name of the base dataset column
|
||||||
- MAXLEN Maximum length of the data contained therein.
|
- MAXLEN Maximum length of the data contained therein.
|
||||||
|
|
||||||
Character fields may be allocated very large widths (eg 32000) of which the
|
Character fields are often allocated very large widths (eg 32000) of which the
|
||||||
maximum value is likely to be much narrower. This macro was designed to
|
maximum value is likely to be much narrower. Identifying such cases can be
|
||||||
enable a HTML table to be appropriately sized however this could be used as
|
helpful in the following scenarios:
|
||||||
part of a data audit to ensure we aren't over-sizing our tables in relation to
|
|
||||||
the data therein.
|
@li Enabling a HTML table to be appropriately sized (`num2char=YES`)
|
||||||
|
@li Reducing the size of a dataset to save on storage (mp_ds2squeeze.sas)
|
||||||
|
@li Identifying columns containing nothing but missing values (`MAXLEN=0` in
|
||||||
|
the output table)
|
||||||
|
|
||||||
|
If the entire column is made up of (non-special) missing values then a value
|
||||||
|
of 0 is returned.
|
||||||
|
|
||||||
Numeric fields are converted using the relevant format to determine the width.
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%mp_getmaxvarlengths(sashelp.class,outds=work.myds)
|
%mp_getmaxvarlengths(sashelp.class,outds=work.myds)
|
||||||
|
|
||||||
@param libds Two part dataset (or view) reference.
|
@param [in] libds Two part dataset (or view) reference.
|
||||||
@param outds= The output dataset to create
|
@param [in] num2char= (NO) When set to NO, numeric fields are sized according
|
||||||
|
to the number of bytes used (or set to zero in the case of non-special
|
||||||
|
missings). When YES, the numeric field is converted to character (using the
|
||||||
|
format, if available), and that is sized instead, using `lengthn()`.
|
||||||
|
@param [out] outds= The output dataset to create, eg:
|
||||||
|
|NAME:$8.|MAXLEN:best.|
|
||||||
|
|---|---|
|
||||||
|
|`Name `|`7 `|
|
||||||
|
|`Sex `|`1 `|
|
||||||
|
|`Age `|`3 `|
|
||||||
|
|`Height `|`8 `|
|
||||||
|
|`Weight `|`3 `|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li mcf_length.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
@li mf_getvarlist.sas
|
@li mf_getvarlist.sas
|
||||||
@li mf_getvartype.sas
|
@li mf_getvartype.sas
|
||||||
@li mf_getvarformat.sas
|
@li mf_getvarformat.sas
|
||||||
@@ -6593,20 +6870,32 @@ create table &outsummary as
|
|||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mp_ds2squeeze.sas
|
||||||
|
@li mp_getmaxvarlengths.test.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mp_getmaxvarlengths(
|
%macro mp_getmaxvarlengths(
|
||||||
libds /* libref.dataset to analyse */
|
libds
|
||||||
,outds=work.mp_getmaxvarlengths /* name of output dataset to create */
|
,num2char=NO
|
||||||
|
,outds=work.mp_getmaxvarlengths
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%local vars x var fmt;
|
%local vars prefix x var fmt;
|
||||||
%let vars=%mf_getvarlist(libds=&libds);
|
%let vars=%mf_getvarlist(libds=&libds);
|
||||||
|
%let prefix=%substr(%mf_getuniquename(),1,25);
|
||||||
|
%let num2char=%upcase(&num2char);
|
||||||
|
|
||||||
|
%if &num2char=NO %then %do;
|
||||||
|
/* compile length function for numeric fields */
|
||||||
|
%mcf_length(wrap=YES, insert_cmplib=YES)
|
||||||
|
%end;
|
||||||
|
|
||||||
proc sql;
|
proc sql;
|
||||||
create table &outds (rename=(
|
create table &outds (rename=(
|
||||||
%do x=1 %to %sysfunc(countw(&vars,%str( )));
|
%do x=1 %to %sysfunc(countw(&vars,%str( )));
|
||||||
________&x=%scan(&vars,&x)
|
&prefix.&x=%scan(&vars,&x)
|
||||||
%end;
|
%end;
|
||||||
))
|
))
|
||||||
as select
|
as select
|
||||||
@@ -6614,18 +6903,21 @@ create table &outds (rename=(
|
|||||||
%let var=%scan(&vars,&x);
|
%let var=%scan(&vars,&x);
|
||||||
%if &x>1 %then ,;
|
%if &x>1 %then ,;
|
||||||
%if %mf_getvartype(&libds,&var)=C %then %do;
|
%if %mf_getvartype(&libds,&var)=C %then %do;
|
||||||
max(length(&var)) as ________&x
|
max(lengthn(&var)) as &prefix.&x
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %if &num2char=YES %then %do;
|
||||||
%let fmt=%mf_getvarformat(&libds,&var);
|
%let fmt=%mf_getvarformat(&libds,&var);
|
||||||
%put fmt=&fmt;
|
%put fmt=&fmt;
|
||||||
%if %str(&fmt)=%str() %then %do;
|
%if %str(&fmt)=%str() %then %do;
|
||||||
max(length(cats(&var))) as ________&x
|
max(lengthn(cats(&var))) as &prefix.&x
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
max(length(put(&var,&fmt))) as ________&x
|
max(lengthn(put(&var,&fmt))) as &prefix.&x
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
%else %do;
|
||||||
|
max(mcf_length(&var)) as &prefix.&x
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
from &libds;
|
from &libds;
|
||||||
|
|
||||||
@@ -7475,24 +7767,29 @@ filename &tempref clear;
|
|||||||
%macro mp_init(prefix=SASJS
|
%macro mp_init(prefix=SASJS
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%global
|
%if %symexist(SASJS_PREFIX) %then %return; /* only run once */
|
||||||
|
|
||||||
|
%global
|
||||||
|
SASJS_PREFIX /* the ONLY hard-coded global macro variable in SASjs */
|
||||||
&prefix._INIT_NUM /* initialisation time as numeric */
|
&prefix._INIT_NUM /* initialisation time as numeric */
|
||||||
&prefix._INIT_DTTM /* initialisation time in E8601DT26.6 format */
|
&prefix._INIT_DTTM /* initialisation time in E8601DT26.6 format */
|
||||||
&prefix.WORK /* avoid typing %sysfunc(pathname(work)) every time */
|
&prefix.WORK /* avoid typing %sysfunc(pathname(work)) every time */
|
||||||
;
|
;
|
||||||
%if %eval(&&&prefix._INIT_NUM>0) %then %return; /* only run once */
|
|
||||||
|
|
||||||
data _null_;
|
%let sasjs_prefix=&prefix;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
dttm=datetime();
|
dttm=datetime();
|
||||||
call symputx("&prefix._init_num",dttm,'g');
|
call symputx("&sasjs_prefix._init_num",dttm,'g');
|
||||||
call symputx("&prefix._init_dttm",put(dttm,E8601DT26.6),'g');
|
call symputx("&sasjs_prefix._init_dttm",put(dttm,E8601DT26.6),'g');
|
||||||
call symputx("&prefix.work",pathname('WORK'),'g');
|
call symputx("&sasjs_prefix.work",pathname('WORK'),'g');
|
||||||
run;
|
run;
|
||||||
|
|
||||||
options
|
options
|
||||||
noautocorrect /* disallow misspelled procedure names */
|
noautocorrect /* disallow misspelled procedure names */
|
||||||
compress=CHAR /* default is none so ensure we have something! */
|
compress=CHAR /* default is none so ensure we have something! */
|
||||||
datastmtchk=ALLKEYWORDS /* protection from overwriting input datasets */
|
datastmtchk=ALLKEYWORDS /* protection from overwriting input datasets */
|
||||||
|
dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
|
||||||
%str(err)orcheck=STRICT /* catch errs in libname/filename statements */
|
%str(err)orcheck=STRICT /* catch errs in libname/filename statements */
|
||||||
fmterr /* ensure err when a format cannot be found */
|
fmterr /* ensure err when a format cannot be found */
|
||||||
mergenoby=%str(ERR)OR /* throw err when a merge has no BY variables */
|
mergenoby=%str(ERR)OR /* throw err when a merge has no BY variables */
|
||||||
@@ -7505,7 +7802,7 @@ filename &tempref clear;
|
|||||||
validvarname=V7 /* avoid special characters etc in variable names */
|
validvarname=V7 /* avoid special characters etc in variable names */
|
||||||
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
|
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
|
||||||
varlenchk=%str(ERR)OR /* fail hard if truncation (data loss) can result */
|
varlenchk=%str(ERR)OR /* fail hard if truncation (data loss) can result */
|
||||||
;
|
;
|
||||||
|
|
||||||
%mend mp_init;/**
|
%mend mp_init;/**
|
||||||
@file mp_jsonout.sas
|
@file mp_jsonout.sas
|
||||||
@@ -7571,7 +7868,6 @@ filename &tempref clear;
|
|||||||
|
|
||||||
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y
|
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y
|
||||||
,engine=DATASTEP
|
,engine=DATASTEP
|
||||||
,dbg=0 /* DEPRECATED */
|
|
||||||
,missing=NULL
|
,missing=NULL
|
||||||
,showmeta=NO
|
,showmeta=NO
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
@@ -9967,7 +10263,7 @@ libname &lib clear;
|
|||||||
else do;
|
else do;
|
||||||
x+1;
|
x+1;
|
||||||
call symputx(name,quote(cats(value)),'l');
|
call symputx(name,quote(cats(value)),'l');
|
||||||
call symputx('pval'!!left(x),name,'l');
|
call symputx(cats('pval',x),name,'l');
|
||||||
call symputx('pcnt',x,'l');
|
call symputx('pcnt',x,'l');
|
||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
@@ -10513,9 +10809,11 @@ alter table &libds modify &var char(&len);
|
|||||||
%let tempcol=%mf_getuniquename();
|
%let tempcol=%mf_getuniquename();
|
||||||
|
|
||||||
%if &rule=ISINT %then %do;
|
%if &rule=ISINT %then %do;
|
||||||
&tempcol=input(&incol,?? best32.);
|
|
||||||
&outcol=0;
|
&outcol=0;
|
||||||
if not missing(&tempcol) then if mod(&incol,1)=0 then &outcol=1;
|
if not missing(&incol) then do;
|
||||||
|
&tempcol=input(&incol,?? best32.);
|
||||||
|
if not missing(&tempcol) then if mod(&tempcol,1)=0 then &outcol=1;
|
||||||
|
end;
|
||||||
drop &tempcol;
|
drop &tempcol;
|
||||||
%end;
|
%end;
|
||||||
%else %if &rule=ISNUM %then %do;
|
%else %if &rule=ISNUM %then %do;
|
||||||
@@ -12701,7 +12999,6 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
||||||
put ' ,engine=DATASTEP ';
|
put ' ,engine=DATASTEP ';
|
||||||
put ' ,dbg=0 /* DEPRECATED */ ';
|
|
||||||
put ' ,missing=NULL ';
|
put ' ,missing=NULL ';
|
||||||
put ' ,showmeta=NO ';
|
put ' ,showmeta=NO ';
|
||||||
put ')/*/STORE SOURCE*/; ';
|
put ')/*/STORE SOURCE*/; ';
|
||||||
@@ -12989,7 +13286,7 @@ data _null_;
|
|||||||
put ' set &tempds; ';
|
put ' set &tempds; ';
|
||||||
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
||||||
put ' i+1; ';
|
put ' i+1; ';
|
||||||
put ' call symputx(''wt''!!left(i),name,''l''); ';
|
put ' call symputx(cats(''wt'',i),name,''l''); ';
|
||||||
put ' call symputx(''wtcnt'',i,''l''); ';
|
put ' call symputx(''wtcnt'',i,''l''); ';
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
||||||
put ' put ",""WORK"":{"; ';
|
put ' put ",""WORK"":{"; ';
|
||||||
@@ -13032,7 +13329,8 @@ data _null_;
|
|||||||
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 ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; ';
|
||||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),datetime20.3)" ''" ''; ';
|
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
||||||
|
put ' length memsize $32; ';
|
||||||
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
||||||
put ' memsize=quote(cats(memsize)); ';
|
put ' memsize=quote(cats(memsize)); ';
|
||||||
put ' put '',"MEMSIZE" : '' memsize; ';
|
put ' put '',"MEMSIZE" : '' memsize; ';
|
||||||
@@ -14764,7 +15062,7 @@ data _null_;
|
|||||||
set repos;
|
set repos;
|
||||||
where repositorytype in('CUSTOM','FOUNDATION');
|
where repositorytype in('CUSTOM','FOUNDATION');
|
||||||
keep id name ;
|
keep id name ;
|
||||||
call symputx('repo'!!left(_n_),name,'l');
|
call symputx(cats('repo',_n_),name,'l');
|
||||||
call symputx('repocnt',_n_,'l');
|
call symputx('repocnt',_n_,'l');
|
||||||
run;
|
run;
|
||||||
|
|
||||||
@@ -16246,9 +16544,6 @@ run;
|
|||||||
@param [in] stpcode= the source file (or fileref) containing the SAS code to load
|
@param [in] stpcode= the source file (or fileref) containing the SAS code to load
|
||||||
into the stp. For multiple files, they should simply be concatenated first.
|
into the stp. For multiple files, they should simply be concatenated first.
|
||||||
@param [in] minify= set to YES in order to strip comments, blank lines, and CRLFs.
|
@param [in] minify= set to YES in order to strip comments, blank lines, and CRLFs.
|
||||||
|
|
||||||
@param frefin= deprecated - a unique fileref is now always used
|
|
||||||
@param frefout= deprecated - a unique fileref is now always used
|
|
||||||
@param mDebug= set to 1 to show debug messages in the log
|
@param mDebug= set to 1 to show debug messages in the log
|
||||||
|
|
||||||
@version 9.3
|
@version 9.3
|
||||||
@@ -16263,16 +16558,8 @@ run;
|
|||||||
,stpcode=
|
,stpcode=
|
||||||
,minify=NO
|
,minify=NO
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
/* deprecated */
|
|
||||||
,frefin=inmeta
|
|
||||||
,frefout=outmeta
|
|
||||||
);
|
);
|
||||||
|
|
||||||
%if &frefin ne inmeta or &frefout ne outmeta %then %do;
|
|
||||||
%put %str(WARN)ING: the frefin and frefout parameters will be deprecated in
|
|
||||||
an upcoming release.;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
/* first, check if STP exists */
|
/* first, check if STP exists */
|
||||||
%local tsuri;
|
%local tsuri;
|
||||||
%let tsuri=stopifempty ;
|
%let tsuri=stopifempty ;
|
||||||
@@ -16494,7 +16781,7 @@ run;
|
|||||||
set &tempds;
|
set &tempds;
|
||||||
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
||||||
i+1;
|
i+1;
|
||||||
call symputx('wt'!!left(i),name,'l');
|
call symputx(cats('wt',i),name,'l');
|
||||||
call symputx('wtcnt',i,'l');
|
call symputx('wtcnt',i,'l');
|
||||||
data _null_; file &fref mod encoding='utf-8';
|
data _null_; file &fref mod encoding='utf-8';
|
||||||
put ",""WORK"":{";
|
put ",""WORK"":{";
|
||||||
@@ -16537,7 +16824,8 @@ run;
|
|||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||||
|
length memsize $32;
|
||||||
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
||||||
memsize=quote(cats(memsize));
|
memsize=quote(cats(memsize));
|
||||||
put ',"MEMSIZE" : ' memsize;
|
put ',"MEMSIZE" : ' memsize;
|
||||||
@@ -16796,7 +17084,7 @@ run;
|
|||||||
set &tempds;
|
set &tempds;
|
||||||
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
||||||
i+1;
|
i+1;
|
||||||
call symputx('wt'!!left(i),name,'l');
|
call symputx(cats('wt',i),name,'l');
|
||||||
call symputx('wtcnt',i,'l');
|
call symputx('wtcnt',i,'l');
|
||||||
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
||||||
put ",""WORK"":{";
|
put ",""WORK"":{";
|
||||||
@@ -16843,10 +17131,11 @@ run;
|
|||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
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'))));
|
||||||
put ',"AUTOEXEC" : ' autoexec;
|
put ',"AUTOEXEC" : ' autoexec;
|
||||||
|
length memsize $32;
|
||||||
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
||||||
memsize=quote(cats(memsize));
|
memsize=quote(cats(memsize));
|
||||||
put ',"MEMSIZE" : ' memsize;
|
put ',"MEMSIZE" : ' memsize;
|
||||||
@@ -17834,7 +18123,6 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
||||||
put ' ,engine=DATASTEP ';
|
put ' ,engine=DATASTEP ';
|
||||||
put ' ,dbg=0 /* DEPRECATED */ ';
|
|
||||||
put ' ,missing=NULL ';
|
put ' ,missing=NULL ';
|
||||||
put ' ,showmeta=NO ';
|
put ' ,showmeta=NO ';
|
||||||
put ')/*/STORE SOURCE*/; ';
|
put ')/*/STORE SOURCE*/; ';
|
||||||
@@ -18184,8 +18472,8 @@ data _null_;
|
|||||||
put ' set &tempds; ';
|
put ' set &tempds; ';
|
||||||
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
||||||
put ' i+1; ';
|
put ' i+1; ';
|
||||||
put ' call symputx(''wt''!!left(i),name); ';
|
put ' call symputx(cats(''wt'',i),name,''l''); ';
|
||||||
put ' call symputx(''wtcnt'',i); ';
|
put ' call symputx(''wtcnt'',i,''l''); ';
|
||||||
put ' data _null_; file &fref mod; put ",""WORK"":{"; ';
|
put ' data _null_; file &fref mod; put ",""WORK"":{"; ';
|
||||||
put ' %do i=1 %to &wtcnt; ';
|
put ' %do i=1 %to &wtcnt; ';
|
||||||
put ' %let wt=&&wt&i; ';
|
put ' %let wt=&&wt&i; ';
|
||||||
@@ -18222,7 +18510,8 @@ data _null_;
|
|||||||
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 ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; ';
|
||||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),datetime20.3)" ''" ''; ';
|
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
||||||
|
put ' length memsize $32; ';
|
||||||
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
||||||
put ' memsize=quote(cats(memsize)); ';
|
put ' memsize=quote(cats(memsize)); ';
|
||||||
put ' put '',"MEMSIZE" : '' memsize; ';
|
put ' put '',"MEMSIZE" : '' memsize; ';
|
||||||
@@ -18526,6 +18815,7 @@ libname &libref1a JSON fileref=&fname1a;
|
|||||||
%let found=0;
|
%let found=0;
|
||||||
%put Getting object uri from &libref1a..items;
|
%put Getting object uri from &libref1a..items;
|
||||||
data _null_;
|
data _null_;
|
||||||
|
length contenttype name $1000;
|
||||||
set &libref1a..items;
|
set &libref1a..items;
|
||||||
if contenttype="&contenttype" and upcase(name)="%upcase(&name)" then do;
|
if contenttype="&contenttype" and upcase(name)="%upcase(&name)" then do;
|
||||||
call symputx('uri',uri,'l');
|
call symputx('uri',uri,'l');
|
||||||
@@ -18673,6 +18963,7 @@ libname &libref1a JSON fileref=&fname1a;
|
|||||||
%let found=0;
|
%let found=0;
|
||||||
%put Getting object uri from &libref1a..items;
|
%put Getting object uri from &libref1a..items;
|
||||||
data _null_;
|
data _null_;
|
||||||
|
length contenttype name $1000;
|
||||||
set &libref1a..items;
|
set &libref1a..items;
|
||||||
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then do;
|
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then do;
|
||||||
call symputx('uri',cats("&base_uri",uri),'l');
|
call symputx('uri',cats("&base_uri",uri),'l');
|
||||||
@@ -18845,59 +19136,6 @@ filename &fname2 clear;
|
|||||||
libname &libref1 clear;
|
libname &libref1 clear;
|
||||||
|
|
||||||
%mend mv_deleteviyafolder;/**
|
%mend mv_deleteviyafolder;/**
|
||||||
@file mv_getaccesstoken.sas
|
|
||||||
@brief deprecated - replaced by mv_tokenrefresh.sas
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
|
||||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mv_tokenrefresh.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mv_getaccesstoken(client_id=someclient
|
|
||||||
,client_secret=somesecret
|
|
||||||
,grant_type=authorization_code
|
|
||||||
,code=
|
|
||||||
,user=
|
|
||||||
,pass=
|
|
||||||
,access_token_var=ACCESS_TOKEN
|
|
||||||
,refresh_token_var=REFRESH_TOKEN
|
|
||||||
);
|
|
||||||
|
|
||||||
%mv_tokenrefresh(client_id=&client_id
|
|
||||||
,client_secret=&client_secret
|
|
||||||
,grant_type=&grant_type
|
|
||||||
,user=&user
|
|
||||||
,pass=&pass
|
|
||||||
,access_token_var=&access_token_var
|
|
||||||
,refresh_token_var=&refresh_token_var
|
|
||||||
)
|
|
||||||
|
|
||||||
%mend mv_getaccesstoken;/**
|
|
||||||
@file
|
|
||||||
@brief deprecated - replaced by mv_registerclient.sas
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
|
||||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mv_registerclient.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mv_getapptoken(client_id=someclient
|
|
||||||
,client_secret=somesecret
|
|
||||||
,grant_type=authorization_code
|
|
||||||
);
|
|
||||||
|
|
||||||
%mv_registerclient(client_id=&client_id
|
|
||||||
,client_secret=&client_secret
|
|
||||||
,grant_type=&grant_type
|
|
||||||
)
|
|
||||||
|
|
||||||
%mend mv_getapptoken;/**
|
|
||||||
@file mv_getclients.sas
|
@file mv_getclients.sas
|
||||||
@brief Get a list of Viya Clients
|
@brief Get a list of Viya Clients
|
||||||
@details First, be sure you have an access token (which requires an app token).
|
@details First, be sure you have an access token (which requires an app token).
|
||||||
@@ -20224,38 +20462,6 @@ filename &fname0 clear;
|
|||||||
|
|
||||||
%mend mv_getjobstate;
|
%mend mv_getjobstate;
|
||||||
/**
|
/**
|
||||||
@file mv_getrefreshtoken.sas
|
|
||||||
@brief deprecated - replaced by mv_tokenauth.sas
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
|
||||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mv_tokenauth.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mv_getrefreshtoken(client_id=someclient
|
|
||||||
,client_secret=somesecret
|
|
||||||
,grant_type=authorization_code
|
|
||||||
,code=
|
|
||||||
,user=
|
|
||||||
,pass=
|
|
||||||
,access_token_var=ACCESS_TOKEN
|
|
||||||
,refresh_token_var=REFRESH_TOKEN
|
|
||||||
);
|
|
||||||
|
|
||||||
%mv_tokenauth(client_id=&client_id
|
|
||||||
,client_secret=&client_secret
|
|
||||||
,grant_type=&grant_type
|
|
||||||
,code=&code
|
|
||||||
,user=&user
|
|
||||||
,pass=&pass
|
|
||||||
,access_token_var=&access_token_var
|
|
||||||
,refresh_token_var=&refresh_token_var
|
|
||||||
)
|
|
||||||
|
|
||||||
%mend mv_getrefreshtoken;/**
|
|
||||||
@file mv_getusergroups.sas
|
@file mv_getusergroups.sas
|
||||||
@brief Creates a dataset with a list of groups for a particular user
|
@brief Creates a dataset with a list of groups for a particular user
|
||||||
@details If using outside of Viya SPRE, then an access token is needed.
|
@details If using outside of Viya SPRE, then an access token is needed.
|
||||||
@@ -20922,7 +21128,7 @@ data;run;%let jdswaitfor=&syslast;
|
|||||||
data _null_;
|
data _null_;
|
||||||
infile &jfref lrecl=32767;
|
infile &jfref lrecl=32767;
|
||||||
input;
|
input;
|
||||||
jparams='jparams'!!left(symget('jid'));
|
jparams=cats('jparams',symget('jid'));
|
||||||
call symputx(jparams,substr(_infile_,3,length(_infile_)-4));
|
call symputx(jparams,substr(_infile_,3,length(_infile_)-4));
|
||||||
run;
|
run;
|
||||||
%local jobuid&jid;
|
%local jobuid&jid;
|
||||||
@@ -22042,8 +22248,8 @@ filename &fref1 clear;
|
|||||||
set &tempds;
|
set &tempds;
|
||||||
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
||||||
i+1;
|
i+1;
|
||||||
call symputx('wt'!!left(i),name);
|
call symputx(cats('wt',i),name,'l');
|
||||||
call symputx('wtcnt',i);
|
call symputx('wtcnt',i,'l');
|
||||||
data _null_; file &fref mod; put ",""WORK"":{";
|
data _null_; file &fref mod; put ",""WORK"":{";
|
||||||
%do i=1 %to &wtcnt;
|
%do i=1 %to &wtcnt;
|
||||||
%let wt=&&wt&i;
|
%let wt=&&wt&i;
|
||||||
@@ -22080,7 +22286,8 @@ filename &fref1 clear;
|
|||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||||
|
length memsize $32;
|
||||||
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
||||||
memsize=quote(cats(memsize));
|
memsize=quote(cats(memsize));
|
||||||
put ',"MEMSIZE" : ' memsize;
|
put ',"MEMSIZE" : ' memsize;
|
||||||
@@ -22532,6 +22739,87 @@ run;
|
|||||||
|
|
||||||
%mend ml_json;
|
%mend ml_json;
|
||||||
/**
|
/**
|
||||||
|
@file
|
||||||
|
@brief Returns the length of a numeric value
|
||||||
|
@details
|
||||||
|
Returns the length, in bytes, of a numeric value. If the value is
|
||||||
|
missing, then 0 is returned.
|
||||||
|
|
||||||
|
The function itself takes the following (positional) parameters:
|
||||||
|
|
||||||
|
| PARAMETER | DESCRIPTION |
|
||||||
|
|---|---|
|
||||||
|
| var | variable (or value) to be tested|
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
%mcf_length(wrap=YES, insert_cmplib=YES)
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
ina=1;
|
||||||
|
inb=10000000;
|
||||||
|
inc=12345678;
|
||||||
|
ind=.;
|
||||||
|
outa=mcf_length(ina);
|
||||||
|
outb=mcf_length(inb);
|
||||||
|
outc=mcf_length(inc);
|
||||||
|
outd=mcf_length(ind);
|
||||||
|
put (out:)(=);
|
||||||
|
run;
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
> outa=3 outb=4 outc=5 outd=0
|
||||||
|
|
||||||
|
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
|
||||||
|
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
|
||||||
|
CMPLIB reference.
|
||||||
|
@param [out] lib= (work) The output library in which to create the catalog.
|
||||||
|
@param [out] cat= (sasjs) The output catalog in which to create the package.
|
||||||
|
@param [out] pkg= (utils) The output package in which to create the function.
|
||||||
|
Uses a 3 part format: libref.catalog.package
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_existfunction.sas
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mcf_length.test.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mcf_length(wrap=NO
|
||||||
|
,insert_cmplib=NO
|
||||||
|
,lib=WORK
|
||||||
|
,cat=SASJS
|
||||||
|
,pkg=UTILS
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%if %mf_existfunction(mcf_length)=1 %then %return;
|
||||||
|
|
||||||
|
%if &wrap=YES %then %do;
|
||||||
|
proc fcmp outlib=&lib..&cat..&pkg;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
function mcf_length(var);
|
||||||
|
if var=. then len=0;
|
||||||
|
else if missing(var) or trunc(var,3)=var then len=3;
|
||||||
|
else if trunc(var,4)=var then len=4;
|
||||||
|
else if trunc(var,5)=var then len=5;
|
||||||
|
else if trunc(var,6)=var then len=6;
|
||||||
|
else if trunc(var,7)=var then len=7;
|
||||||
|
else len=8;
|
||||||
|
return(len);
|
||||||
|
endsub;
|
||||||
|
|
||||||
|
%if &wrap=YES %then %do;
|
||||||
|
quit;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%if &insert_cmplib=YES %then %do;
|
||||||
|
options insert=(CMPLIB=(&lib..&cat));
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend mcf_length;/**
|
||||||
@file
|
@file
|
||||||
@brief Provides a replacement for the stpsrv_header function
|
@brief Provides a replacement for the stpsrv_header function
|
||||||
@details The stpsrv_header is normally a built-in function, used to set the
|
@details The stpsrv_header is normally a built-in function, used to set the
|
||||||
@@ -22602,7 +22890,7 @@ run;
|
|||||||
%if %mf_existfunction(stpsrv_header)=1 %then %return;
|
%if %mf_existfunction(stpsrv_header)=1 %then %return;
|
||||||
|
|
||||||
%if &wrap=YES %then %do;
|
%if &wrap=YES %then %do;
|
||||||
proc fcmp outcat=&lib..&cat..&pkg;
|
proc fcmp outlib=&lib..&cat..&pkg;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
function stpsrv_header(name $, value $);
|
function stpsrv_header(name $, value $);
|
||||||
@@ -22670,6 +22958,9 @@ endsub;
|
|||||||
@param [out] pkg= (utils) The output package in which to create the function.
|
@param [out] pkg= (utils) The output package in which to create the function.
|
||||||
Uses a 3 part format: libref.catalog.package
|
Uses a 3 part format: libref.catalog.package
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_existfunction.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mcf_string2file(wrap=NO
|
%macro mcf_string2file(wrap=NO
|
||||||
@@ -22679,8 +22970,10 @@ endsub;
|
|||||||
,pkg=UTILS
|
,pkg=UTILS
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%if %mf_existfunction(mcf_string2file)=1 %then %return;
|
||||||
|
|
||||||
%if &wrap=YES %then %do;
|
%if &wrap=YES %then %do;
|
||||||
proc fcmp outcat=&lib..&cat..&pkg;
|
proc fcmp outlib=&lib..&cat..&pkg;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
function mcf_string2file(filepath $, string $, mode $);
|
function mcf_string2file(filepath $, string $, mode $);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
@cond
|
@cond
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mf_abort(mac=mf_abort.sas, type=deprecated, msg=, iftrue=%str(1=1)
|
%macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1)
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%if not(%eval(%unquote(&iftrue))) %then %return;
|
%if not(%eval(%unquote(&iftrue))) %then %return;
|
||||||
|
|||||||
@@ -173,7 +173,8 @@
|
|||||||
if symexist('_debug') then debug=quote(trim(symget('_debug')));
|
if symexist('_debug') then debug=quote(trim(symget('_debug')));
|
||||||
else debug='""';
|
else debug='""';
|
||||||
put '>>weboutBEGIN<<';
|
put '>>weboutBEGIN<<';
|
||||||
put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
|
put '{"SYSDATE" : "' "&SYSDATE" '"';
|
||||||
|
put ',"SYSTIME" : "' "&SYSTIME" '"';
|
||||||
put ',"sasjsAbort" : [{';
|
put ',"sasjsAbort" : [{';
|
||||||
put ' "MSG":' msg ;
|
put ' "MSG":' msg ;
|
||||||
put ' ,"MAC": "' "&mac" '"}]';
|
put ' ,"MAC": "' "&mac" '"}]';
|
||||||
@@ -202,7 +203,7 @@
|
|||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
syswarningtext=quote(trim(symget('syswarningtext')));
|
syswarningtext=quote(trim(symget('syswarningtext')));
|
||||||
put ",""SYSWARNINGTEXT"" : " syswarningtext;
|
put ",""SYSWARNINGTEXT"" : " syswarningtext;
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||||
put "}" @;
|
put "}" @;
|
||||||
put '>>weboutEND<<';
|
put '>>weboutEND<<';
|
||||||
run;
|
run;
|
||||||
|
|||||||
119
base/mp_assertscope.sas
Normal file
119
base/mp_assertscope.sas
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Used to capture scope leakage of macro variables
|
||||||
|
@details A common 'difficult to detect' bug in macros is where a nested
|
||||||
|
macro over-writes variables in a higher level macro.
|
||||||
|
|
||||||
|
This assertion takes a snapshot of the macro variables before and after
|
||||||
|
a macro invocation. This makes it easy to detect whether any macro
|
||||||
|
variables were modified or changed.
|
||||||
|
|
||||||
|
Currently, the macro only checks for global scope variables. In the future
|
||||||
|
it may be extended to work at multiple levels of nesting.
|
||||||
|
|
||||||
|
If you would like this feature, feel free to contribute / raise an issue /
|
||||||
|
engage the SASjs team directly.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
|
||||||
|
%let oops=I did it again;
|
||||||
|
|
||||||
|
%mp_assertscope(COMPARE,
|
||||||
|
desc=Checking macro variables against previous snapshot
|
||||||
|
)
|
||||||
|
|
||||||
|
@param [in] action (SNAPSHOT) The action to take. Valid values:
|
||||||
|
@li SNAPSHOT - take a copy of the current macro variables
|
||||||
|
@li COMPARE - compare the current macro variables against previous values
|
||||||
|
@param [in] scope= (GLOBAL) The scope of the variables to be checked. This
|
||||||
|
corresponds to the values in the SCOPE column in `sashelp.vmacro`.
|
||||||
|
@param [in] desc= (Testing scope leakage) The user provided test description
|
||||||
|
@param [in,out] scopeds= (work.mp_assertscope) The dataset to contain the
|
||||||
|
scope snapshot
|
||||||
|
@param [out] outds= (work.test_results) The output dataset to contain the
|
||||||
|
results. If it does not exist, it will be created, with the following format:
|
||||||
|
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|
||||||
|
|---|---|---|
|
||||||
|
|User Provided description|PASS|No out of scope variables created or modified|
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertcols.sas
|
||||||
|
@li mp_assertcolvals.sas
|
||||||
|
@li mp_assertdsobs.sas
|
||||||
|
@li mp_assertscope.test.sas
|
||||||
|
|
||||||
|
@version 9.2
|
||||||
|
@author Allan Bowe
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_assertscope(action,
|
||||||
|
desc=Testing Scope Leakage,
|
||||||
|
scope=GLOBAL,
|
||||||
|
scopeds=work.mp_assertscope,
|
||||||
|
outds=work.test_results
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
%local ds test_result test_comments del add mod;
|
||||||
|
|
||||||
|
/* get current variables */
|
||||||
|
%if &action=SNAPSHOT %then %do;
|
||||||
|
proc sql;
|
||||||
|
create table &scopeds as
|
||||||
|
select name,offset,value
|
||||||
|
from dictionary.macros
|
||||||
|
where scope="&scope"
|
||||||
|
order by name,offset;
|
||||||
|
%end;
|
||||||
|
%else %if &action=COMPARE %then %do;
|
||||||
|
|
||||||
|
proc sql;
|
||||||
|
create table _data_ as
|
||||||
|
select name,offset,value
|
||||||
|
from dictionary.macros
|
||||||
|
where scope="&scope"
|
||||||
|
order by name,offset;
|
||||||
|
|
||||||
|
%let ds=&syslast;
|
||||||
|
|
||||||
|
proc compare base=&scopeds compare=&ds;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%if &sysinfo=0 %then %do;
|
||||||
|
%let test_result=PASS;
|
||||||
|
%let test_comments=&scope Variables Unmodified;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
proc sql noprint undo_policy=none;
|
||||||
|
select distinct name into: del separated by ' ' from &scopeds
|
||||||
|
where name not in (select name from &ds);
|
||||||
|
select distinct name into: add separated by ' ' from &ds
|
||||||
|
where name not in (select name from &scopeds);
|
||||||
|
select distinct a.name into: mod separated by ' '
|
||||||
|
from &scopeds a
|
||||||
|
inner join &ds b
|
||||||
|
on a.name=b.name
|
||||||
|
and a.offset=b.offset
|
||||||
|
where a.value ne b.value;
|
||||||
|
%let test_result=FAIL;
|
||||||
|
%let test_comments=%str(Mod:(&mod) Add:(&add) Del:(&del));
|
||||||
|
%end;
|
||||||
|
|
||||||
|
|
||||||
|
data ;
|
||||||
|
length test_description $256 test_result $4 test_comments $256;
|
||||||
|
test_description=symget('desc');
|
||||||
|
test_comments=symget('test_comments');
|
||||||
|
test_result=symget('test_result');
|
||||||
|
run;
|
||||||
|
|
||||||
|
%let ds=&syslast;
|
||||||
|
proc append base=&outds data=&ds;
|
||||||
|
run;
|
||||||
|
proc sql;
|
||||||
|
drop table &ds;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend mp_assertscope;
|
||||||
@@ -6,8 +6,7 @@
|
|||||||
Credit for the rename approach:
|
Credit for the rename approach:
|
||||||
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
|
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
|
||||||
|
|
||||||
|
Usage:
|
||||||
usage:
|
|
||||||
|
|
||||||
%mp_dirlist(path=/some/location, outds=myTable, maxdepth=MAX)
|
%mp_dirlist(path=/some/location, outds=myTable, maxdepth=MAX)
|
||||||
|
|
||||||
@@ -23,12 +22,12 @@
|
|||||||
X CMD) do please raise an issue!
|
X CMD) do please raise an issue!
|
||||||
|
|
||||||
|
|
||||||
@param [in] path= for which to return contents
|
@param [in] path= (%sysfunc(pathname(work))) Path for which to return contents
|
||||||
@param [in] fref= Provide a DISK engine fileref as an alternative to PATH
|
@param [in] fref= (0) Provide a DISK engine fileref as an alternative to PATH
|
||||||
@param [in] maxdepth= (0) Set to a positive integer to indicate the level of
|
@param [in] maxdepth= (0) Set to a positive integer to indicate the level of
|
||||||
subdirectory scan recursion - eg 3, to go `./3/levels/deep`. For unlimited
|
subdirectory scan recursion - eg 3, to go `./3/levels/deep`. For unlimited
|
||||||
recursion, set to MAX.
|
recursion, set to MAX.
|
||||||
@param [out] outds= the output dataset to create
|
@param [out] outds= (work.mp_dirlist) The output dataset to create
|
||||||
@param [out] getattrs= (NO) If getattrs=YES then the doptname / foptname
|
@param [out] getattrs= (NO) If getattrs=YES then the doptname / foptname
|
||||||
functions are used to scan all properties - any characters that are not
|
functions are used to scan all properties - any characters that are not
|
||||||
valid in a SAS name (v7) are simply stripped, and the table is transposed
|
valid in a SAS name (v7) are simply stripped, and the table is transposed
|
||||||
@@ -49,13 +48,15 @@
|
|||||||
- OS SPECIFIC variables, if <code>getattrs=</code> is used.
|
- OS SPECIFIC variables, if <code>getattrs=</code> is used.
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_existds.sas
|
||||||
|
@li mf_getvarlist.sas
|
||||||
|
@li mf_wordsinstr1butnotstr2.sas
|
||||||
@li mp_dropmembers.sas
|
@li mp_dropmembers.sas
|
||||||
|
|
||||||
<h4> Related Macros </h4>
|
<h4> Related Macros </h4>
|
||||||
@li mp_dirlist.test.sas
|
@li mp_dirlist.test.sas
|
||||||
|
|
||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mp_dirlist(path=%sysfunc(pathname(work))
|
%macro mp_dirlist(path=%sysfunc(pathname(work))
|
||||||
@@ -193,9 +194,29 @@ data &out_ds;
|
|||||||
set &out_ds(where=(filepath ne ''));
|
set &out_ds(where=(filepath ne ''));
|
||||||
run;
|
run;
|
||||||
|
|
||||||
/* update main table */
|
/**
|
||||||
proc append base=&outds data=&out_ds;
|
* The above transpose can mean that some updates create additional columns.
|
||||||
run;
|
* This necessitates the occasional use of datastep over proc append.
|
||||||
|
*/
|
||||||
|
%if %mf_existds(&outds) %then %do;
|
||||||
|
%local basevars appvars newvars;
|
||||||
|
%let basevars=%mf_getvarlist(&outds);
|
||||||
|
%let appvars=%mf_getvarlist(&out_ds);
|
||||||
|
%let newvars=%length(%mf_wordsinstr1butnotstr2(Str1=&appvars,Str2=&basevars));
|
||||||
|
%if &newvars>0 %then %do;
|
||||||
|
data &outds;
|
||||||
|
set &outds &out_ds;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
proc append base=&outds data=&out_ds force nowarn;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
proc append base=&outds data=&out_ds;
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
/* recursive call */
|
/* recursive call */
|
||||||
%if &maxdepth>&level or &maxdepth=MAX %then %do;
|
%if &maxdepth>&level or &maxdepth=MAX %then %do;
|
||||||
|
|||||||
@@ -139,8 +139,9 @@ create table datalines1 as
|
|||||||
/**
|
/**
|
||||||
Due to long decimals cannot use best. format
|
Due to long decimals cannot use best. format
|
||||||
So - use bestd. format and then use character functions to strip trailing
|
So - use bestd. format and then use character functions to strip trailing
|
||||||
zeros, if NOT an integer!!
|
zeros, if NOT an integer or missing!! Cannot use int() as it upsets
|
||||||
resolved code = ifc(int(VARIABLE)=VARIABLE
|
note2err when there are missings.
|
||||||
|
resolved code = ifc( mod(coalesce(VARIABLE,0),1)=0
|
||||||
,put(VARIABLE,best32.)
|
,put(VARIABLE,best32.)
|
||||||
,substrn(put(VARIABLE,bestd32.),1
|
,substrn(put(VARIABLE,bestd32.),1
|
||||||
,findc(put(VARIABLE,bestd32.),'0','TBK')));
|
,findc(put(VARIABLE,bestd32.),'0','TBK')));
|
||||||
@@ -151,7 +152,7 @@ data datalines_2;
|
|||||||
set datalines1 (where=(upcase(name) not in
|
set datalines1 (where=(upcase(name) not in
|
||||||
('PROCESSED_DTTM','VALID_FROM_DTTM','VALID_TO_DTTM')));
|
('PROCESSED_DTTM','VALID_FROM_DTTM','VALID_TO_DTTM')));
|
||||||
if type='num' then dataline=
|
if type='num' then dataline=
|
||||||
cats('ifc(int(',name,')=',name,'
|
cats('ifc(mod(coalesce(',name,',0),1)=0
|
||||||
,put(',name,',best32.-l)
|
,put(',name,',best32.-l)
|
||||||
,substrn(put(',name,',bestd32.-l),1
|
,substrn(put(',name,',bestd32.-l),1
|
||||||
,findc(put(',name,',bestd32.-l),"0","TBK")))');
|
,findc(put(',name,',bestd32.-l),"0","TBK")))');
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ data _null_;
|
|||||||
dsid=open("&ds.","i");
|
dsid=open("&ds.","i");
|
||||||
num=attrn(dsid,"nvars");
|
num=attrn(dsid,"nvars");
|
||||||
do i=1 to num;
|
do i=1 to num;
|
||||||
header = trim(left(coalescec(varlabel(dsid,i),varname(dsid,i))));
|
header = cats(coalescec(varlabel(dsid,i),varname(dsid,i)));
|
||||||
put header @;
|
put header @;
|
||||||
end;
|
end;
|
||||||
rc=close(dsid);
|
rc=close(dsid);
|
||||||
|
|||||||
119
base/mp_ds2squeeze.sas
Normal file
119
base/mp_ds2squeeze.sas
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Create a smaller version of a dataset, without data loss
|
||||||
|
@details This macro will scan the input dataset and create a new one, that
|
||||||
|
has the minimum variable lengths needed to store the data without data loss.
|
||||||
|
|
||||||
|
Inspiration was taken from [How to Reduce the Disk Space Required by a
|
||||||
|
SAS® Data Set](https://www.lexjansen.com/nesug/nesug06/io/io18.pdf) by
|
||||||
|
Selvaratnam Sridharma. The end of the referenced paper presents a macro named
|
||||||
|
"squeeze", hence the nomenclature.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
data big;
|
||||||
|
length my big $32000;
|
||||||
|
do i=1 to 1e4;
|
||||||
|
my=repeat('oh my',100);
|
||||||
|
big='dawg';
|
||||||
|
special=._;
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_ds2squeeze(work.big,outds=work.smaller)
|
||||||
|
|
||||||
|
The following will also be printed to the log (exact values may differ
|
||||||
|
depending on your OS and COMPRESS settings):
|
||||||
|
|
||||||
|
> MP_DS2SQUEEZE: work.big was 625MB
|
||||||
|
|
||||||
|
> MP_DS2SQUEEZE: work.smaller is 5MB
|
||||||
|
|
||||||
|
@param [in] libds The library.dataset to be squeezed
|
||||||
|
@param [out] outds= (work.mp_ds2squeeze) The squeezed dataset to create
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getfilesize.sas
|
||||||
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
|
@li mp_getmaxvarlengths.sas
|
||||||
|
|
||||||
|
<h4> Related Programs </h4>
|
||||||
|
@li mp_ds2squeeze.test.sas
|
||||||
|
|
||||||
|
@version 9.3
|
||||||
|
@author Allan Bowe
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mp_ds2squeeze(
|
||||||
|
libds,
|
||||||
|
outds=work.work.mp_ds2squeeze,
|
||||||
|
mdebug=0
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
%local dbg source;
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
%put &sysmacroname entry vars:;
|
||||||
|
%put _local_;
|
||||||
|
%end;
|
||||||
|
%else %do;
|
||||||
|
%let dbg=*;
|
||||||
|
%let source=/source2;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%local optval ds fref;
|
||||||
|
%let ds=%mf_getuniquename();
|
||||||
|
%let fref=%mf_getuniquefileref();
|
||||||
|
|
||||||
|
%mp_getmaxvarlengths(&libds,outds=&ds)
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
set &ds end=last;
|
||||||
|
file &fref;
|
||||||
|
/* grab the types */
|
||||||
|
retain dsid;
|
||||||
|
if _n_=1 then dsid=open("&libds",'is');
|
||||||
|
if dsid le 0 then do;
|
||||||
|
msg=sysmsg();
|
||||||
|
put msg=;
|
||||||
|
stop;
|
||||||
|
end;
|
||||||
|
type=vartype(dsid,varnum(dsid, name));
|
||||||
|
if last then rc=close(dsid);
|
||||||
|
/* write out the length statement */
|
||||||
|
if _n_=1 then put 'length ';
|
||||||
|
length len $6;
|
||||||
|
if type='C' then do;
|
||||||
|
if maxlen=0 then len='$1';
|
||||||
|
else len=cats('$',maxlen);
|
||||||
|
end;
|
||||||
|
else do;
|
||||||
|
if maxlen=0 then len='3';
|
||||||
|
else len=cats(maxlen);
|
||||||
|
end;
|
||||||
|
put ' ' name ' ' len;
|
||||||
|
if last then put ';';
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* configure varlenchk - as we are explicitly shortening the variables */
|
||||||
|
%let optval=%sysfunc(getoption(varlenchk));
|
||||||
|
options varlenchk=NOWARN;
|
||||||
|
|
||||||
|
data &outds;
|
||||||
|
%inc &fref &source;
|
||||||
|
set &libds;
|
||||||
|
run;
|
||||||
|
|
||||||
|
options varlenchk=&optval;
|
||||||
|
|
||||||
|
%if &mdebug=0 %then %do;
|
||||||
|
proc sql;
|
||||||
|
drop table &ds;
|
||||||
|
filename &fref clear;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%put &sysmacroname: &libds was %mf_getfilesize(libds=&libds,format=yes);
|
||||||
|
%put &sysmacroname: &outds is %mf_getfilesize(libds=&outds,format=yes);
|
||||||
|
|
||||||
|
%mend mp_ds2squeeze;
|
||||||
@@ -109,7 +109,7 @@ data &outds;
|
|||||||
output;
|
output;
|
||||||
end;
|
end;
|
||||||
if mod(SUBGROUP_ID,1) ne 0 then do;
|
if mod(SUBGROUP_ID,1) ne 0 then do;
|
||||||
REASON_CD='SUBGROUP_ID should be integer, not '!!left(subgroup_id);
|
REASON_CD='SUBGROUP_ID should be integer, not '!!cats(subgroup_id);
|
||||||
putlog REASON_CD= SUBGROUP_ID=;
|
putlog REASON_CD= SUBGROUP_ID=;
|
||||||
call symputx('reason_cd',reason_cd,'l');
|
call symputx('reason_cd',reason_cd,'l');
|
||||||
call symputx('nobs',_n_,'l');
|
call symputx('nobs',_n_,'l');
|
||||||
@@ -127,7 +127,7 @@ data &outds;
|
|||||||
if OPERATOR_NM not in
|
if OPERATOR_NM not in
|
||||||
('=','>','<','<=','>=','BETWEEN','IN','NOT IN','NE','CONTAINS')
|
('=','>','<','<=','>=','BETWEEN','IN','NOT IN','NE','CONTAINS')
|
||||||
then do;
|
then do;
|
||||||
REASON_CD='Invalid OPERATOR_NM: '!!left(OPERATOR_NM);
|
REASON_CD='Invalid OPERATOR_NM: '!!cats(OPERATOR_NM);
|
||||||
putlog REASON_CD= OPERATOR_NM=;
|
putlog REASON_CD= OPERATOR_NM=;
|
||||||
call symputx('reason_cd',reason_cd,'l');
|
call symputx('reason_cd',reason_cd,'l');
|
||||||
call symputx('nobs',_n_,'l');
|
call symputx('nobs',_n_,'l');
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ run;
|
|||||||
lab=" label="!!cats("'",tranwrd(label,"'","''"),"'");
|
lab=" label="!!cats("'",tranwrd(label,"'","''"),"'");
|
||||||
if notnull='yes' then notnul=' not null';
|
if notnull='yes' then notnul=' not null';
|
||||||
if type='char' then typ=cats('char(',length,')');
|
if type='char' then typ=cats('char(',length,')');
|
||||||
else if length ne 8 then typ='num length='!!left(length);
|
else if length ne 8 then typ='num length='!!cats(length);
|
||||||
else typ='num';
|
else typ='num';
|
||||||
put name typ fmt notnul lab;
|
put name typ fmt notnul lab;
|
||||||
run;
|
run;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
@file mp_getmaxvarlengths.sas
|
@file
|
||||||
@brief Scans a dataset to find the max length of the variable values
|
@brief Scans a dataset to find the max length of the variable values
|
||||||
@details
|
@details
|
||||||
This macro will scan a base dataset and produce an output dataset with two
|
This macro will scan a base dataset and produce an output dataset with two
|
||||||
@@ -8,21 +8,39 @@
|
|||||||
- NAME Name of the base dataset column
|
- NAME Name of the base dataset column
|
||||||
- MAXLEN Maximum length of the data contained therein.
|
- MAXLEN Maximum length of the data contained therein.
|
||||||
|
|
||||||
Character fields may be allocated very large widths (eg 32000) of which the
|
Character fields are often allocated very large widths (eg 32000) of which the
|
||||||
maximum value is likely to be much narrower. This macro was designed to
|
maximum value is likely to be much narrower. Identifying such cases can be
|
||||||
enable a HTML table to be appropriately sized however this could be used as
|
helpful in the following scenarios:
|
||||||
part of a data audit to ensure we aren't over-sizing our tables in relation to
|
|
||||||
the data therein.
|
@li Enabling a HTML table to be appropriately sized (`num2char=YES`)
|
||||||
|
@li Reducing the size of a dataset to save on storage (mp_ds2squeeze.sas)
|
||||||
|
@li Identifying columns containing nothing but missing values (`MAXLEN=0` in
|
||||||
|
the output table)
|
||||||
|
|
||||||
|
If the entire column is made up of (non-special) missing values then a value
|
||||||
|
of 0 is returned.
|
||||||
|
|
||||||
Numeric fields are converted using the relevant format to determine the width.
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
%mp_getmaxvarlengths(sashelp.class,outds=work.myds)
|
%mp_getmaxvarlengths(sashelp.class,outds=work.myds)
|
||||||
|
|
||||||
@param libds Two part dataset (or view) reference.
|
@param [in] libds Two part dataset (or view) reference.
|
||||||
@param outds= The output dataset to create
|
@param [in] num2char= (NO) When set to NO, numeric fields are sized according
|
||||||
|
to the number of bytes used (or set to zero in the case of non-special
|
||||||
|
missings). When YES, the numeric field is converted to character (using the
|
||||||
|
format, if available), and that is sized instead, using `lengthn()`.
|
||||||
|
@param [out] outds= The output dataset to create, eg:
|
||||||
|
|NAME:$8.|MAXLEN:best.|
|
||||||
|
|---|---|
|
||||||
|
|`Name `|`7 `|
|
||||||
|
|`Sex `|`1 `|
|
||||||
|
|`Age `|`3 `|
|
||||||
|
|`Height `|`8 `|
|
||||||
|
|`Weight `|`3 `|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
|
@li mcf_length.sas
|
||||||
|
@li mf_getuniquename.sas
|
||||||
@li mf_getvarlist.sas
|
@li mf_getvarlist.sas
|
||||||
@li mf_getvartype.sas
|
@li mf_getvartype.sas
|
||||||
@li mf_getvarformat.sas
|
@li mf_getvarformat.sas
|
||||||
@@ -30,20 +48,32 @@
|
|||||||
@version 9.2
|
@version 9.2
|
||||||
@author Allan Bowe
|
@author Allan Bowe
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mp_ds2squeeze.sas
|
||||||
|
@li mp_getmaxvarlengths.test.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mp_getmaxvarlengths(
|
%macro mp_getmaxvarlengths(
|
||||||
libds /* libref.dataset to analyse */
|
libds
|
||||||
,outds=work.mp_getmaxvarlengths /* name of output dataset to create */
|
,num2char=NO
|
||||||
|
,outds=work.mp_getmaxvarlengths
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%local vars x var fmt;
|
%local vars prefix x var fmt;
|
||||||
%let vars=%mf_getvarlist(libds=&libds);
|
%let vars=%mf_getvarlist(libds=&libds);
|
||||||
|
%let prefix=%substr(%mf_getuniquename(),1,25);
|
||||||
|
%let num2char=%upcase(&num2char);
|
||||||
|
|
||||||
|
%if &num2char=NO %then %do;
|
||||||
|
/* compile length function for numeric fields */
|
||||||
|
%mcf_length(wrap=YES, insert_cmplib=YES)
|
||||||
|
%end;
|
||||||
|
|
||||||
proc sql;
|
proc sql;
|
||||||
create table &outds (rename=(
|
create table &outds (rename=(
|
||||||
%do x=1 %to %sysfunc(countw(&vars,%str( )));
|
%do x=1 %to %sysfunc(countw(&vars,%str( )));
|
||||||
________&x=%scan(&vars,&x)
|
&prefix.&x=%scan(&vars,&x)
|
||||||
%end;
|
%end;
|
||||||
))
|
))
|
||||||
as select
|
as select
|
||||||
@@ -51,18 +81,21 @@ create table &outds (rename=(
|
|||||||
%let var=%scan(&vars,&x);
|
%let var=%scan(&vars,&x);
|
||||||
%if &x>1 %then ,;
|
%if &x>1 %then ,;
|
||||||
%if %mf_getvartype(&libds,&var)=C %then %do;
|
%if %mf_getvartype(&libds,&var)=C %then %do;
|
||||||
max(length(&var)) as ________&x
|
max(lengthn(&var)) as &prefix.&x
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %if &num2char=YES %then %do;
|
||||||
%let fmt=%mf_getvarformat(&libds,&var);
|
%let fmt=%mf_getvarformat(&libds,&var);
|
||||||
%put fmt=&fmt;
|
%put fmt=&fmt;
|
||||||
%if %str(&fmt)=%str() %then %do;
|
%if %str(&fmt)=%str() %then %do;
|
||||||
max(length(cats(&var))) as ________&x
|
max(lengthn(cats(&var))) as &prefix.&x
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
max(length(put(&var,&fmt))) as ________&x
|
max(lengthn(put(&var,&fmt))) as &prefix.&x
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
%else %do;
|
||||||
|
max(mcf_length(&var)) as &prefix.&x
|
||||||
|
%end;
|
||||||
%end;
|
%end;
|
||||||
from &libds;
|
from &libds;
|
||||||
|
|
||||||
|
|||||||
@@ -33,24 +33,29 @@
|
|||||||
%macro mp_init(prefix=SASJS
|
%macro mp_init(prefix=SASJS
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
%global
|
%if %symexist(SASJS_PREFIX) %then %return; /* only run once */
|
||||||
|
|
||||||
|
%global
|
||||||
|
SASJS_PREFIX /* the ONLY hard-coded global macro variable in SASjs */
|
||||||
&prefix._INIT_NUM /* initialisation time as numeric */
|
&prefix._INIT_NUM /* initialisation time as numeric */
|
||||||
&prefix._INIT_DTTM /* initialisation time in E8601DT26.6 format */
|
&prefix._INIT_DTTM /* initialisation time in E8601DT26.6 format */
|
||||||
&prefix.WORK /* avoid typing %sysfunc(pathname(work)) every time */
|
&prefix.WORK /* avoid typing %sysfunc(pathname(work)) every time */
|
||||||
;
|
;
|
||||||
%if %eval(&&&prefix._INIT_NUM>0) %then %return; /* only run once */
|
|
||||||
|
|
||||||
data _null_;
|
%let sasjs_prefix=&prefix;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
dttm=datetime();
|
dttm=datetime();
|
||||||
call symputx("&prefix._init_num",dttm,'g');
|
call symputx("&sasjs_prefix._init_num",dttm,'g');
|
||||||
call symputx("&prefix._init_dttm",put(dttm,E8601DT26.6),'g');
|
call symputx("&sasjs_prefix._init_dttm",put(dttm,E8601DT26.6),'g');
|
||||||
call symputx("&prefix.work",pathname('WORK'),'g');
|
call symputx("&sasjs_prefix.work",pathname('WORK'),'g');
|
||||||
run;
|
run;
|
||||||
|
|
||||||
options
|
options
|
||||||
noautocorrect /* disallow misspelled procedure names */
|
noautocorrect /* disallow misspelled procedure names */
|
||||||
compress=CHAR /* default is none so ensure we have something! */
|
compress=CHAR /* default is none so ensure we have something! */
|
||||||
datastmtchk=ALLKEYWORDS /* protection from overwriting input datasets */
|
datastmtchk=ALLKEYWORDS /* protection from overwriting input datasets */
|
||||||
|
dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
|
||||||
%str(err)orcheck=STRICT /* catch errs in libname/filename statements */
|
%str(err)orcheck=STRICT /* catch errs in libname/filename statements */
|
||||||
fmterr /* ensure err when a format cannot be found */
|
fmterr /* ensure err when a format cannot be found */
|
||||||
mergenoby=%str(ERR)OR /* throw err when a merge has no BY variables */
|
mergenoby=%str(ERR)OR /* throw err when a merge has no BY variables */
|
||||||
@@ -63,6 +68,6 @@
|
|||||||
validvarname=V7 /* avoid special characters etc in variable names */
|
validvarname=V7 /* avoid special characters etc in variable names */
|
||||||
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
|
varinitchk=%str(ERR)OR /* avoid data mistakes from variable name typos */
|
||||||
varlenchk=%str(ERR)OR /* fail hard if truncation (data loss) can result */
|
varlenchk=%str(ERR)OR /* fail hard if truncation (data loss) can result */
|
||||||
;
|
;
|
||||||
|
|
||||||
%mend mp_init;
|
%mend mp_init;
|
||||||
@@ -62,7 +62,6 @@
|
|||||||
|
|
||||||
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y
|
%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y
|
||||||
,engine=DATASTEP
|
,engine=DATASTEP
|
||||||
,dbg=0 /* DEPRECATED */
|
|
||||||
,missing=NULL
|
,missing=NULL
|
||||||
,showmeta=NO
|
,showmeta=NO
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
else do;
|
else do;
|
||||||
x+1;
|
x+1;
|
||||||
call symputx(name,quote(cats(value)),'l');
|
call symputx(name,quote(cats(value)),'l');
|
||||||
call symputx('pval'!!left(x),name,'l');
|
call symputx(cats('pval',x),name,'l');
|
||||||
call symputx('pcnt',x,'l');
|
call symputx('pcnt',x,'l');
|
||||||
end;
|
end;
|
||||||
run;
|
run;
|
||||||
|
|||||||
@@ -48,9 +48,11 @@
|
|||||||
%let tempcol=%mf_getuniquename();
|
%let tempcol=%mf_getuniquename();
|
||||||
|
|
||||||
%if &rule=ISINT %then %do;
|
%if &rule=ISINT %then %do;
|
||||||
&tempcol=input(&incol,?? best32.);
|
|
||||||
&outcol=0;
|
&outcol=0;
|
||||||
if not missing(&tempcol) then if mod(&incol,1)=0 then &outcol=1;
|
if not missing(&incol) then do;
|
||||||
|
&tempcol=input(&incol,?? best32.);
|
||||||
|
if not missing(&tempcol) then if mod(&tempcol,1)=0 then &outcol=1;
|
||||||
|
end;
|
||||||
drop &tempcol;
|
drop &tempcol;
|
||||||
%end;
|
%end;
|
||||||
%else %if &rule=ISNUM %then %do;
|
%else %if &rule=ISNUM %then %do;
|
||||||
|
|||||||
82
fcmp/mcf_length.sas
Normal file
82
fcmp/mcf_length.sas
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Returns the length of a numeric value
|
||||||
|
@details
|
||||||
|
Returns the length, in bytes, of a numeric value. If the value is
|
||||||
|
missing, then 0 is returned.
|
||||||
|
|
||||||
|
The function itself takes the following (positional) parameters:
|
||||||
|
|
||||||
|
| PARAMETER | DESCRIPTION |
|
||||||
|
|---|---|
|
||||||
|
| var | variable (or value) to be tested|
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
%mcf_length(wrap=YES, insert_cmplib=YES)
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
ina=1;
|
||||||
|
inb=10000000;
|
||||||
|
inc=12345678;
|
||||||
|
ind=.;
|
||||||
|
outa=mcf_length(ina);
|
||||||
|
outb=mcf_length(inb);
|
||||||
|
outc=mcf_length(inc);
|
||||||
|
outd=mcf_length(ind);
|
||||||
|
put (out:)(=);
|
||||||
|
run;
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
> outa=3 outb=4 outc=5 outd=0
|
||||||
|
|
||||||
|
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
|
||||||
|
@param [out] insert_cmplib= (NO) Choose YES to insert the package into the
|
||||||
|
CMPLIB reference.
|
||||||
|
@param [out] lib= (work) The output library in which to create the catalog.
|
||||||
|
@param [out] cat= (sasjs) The output catalog in which to create the package.
|
||||||
|
@param [out] pkg= (utils) The output package in which to create the function.
|
||||||
|
Uses a 3 part format: libref.catalog.package
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_existfunction.sas
|
||||||
|
|
||||||
|
<h4> Related Macros </h4>
|
||||||
|
@li mcf_length.test.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro mcf_length(wrap=NO
|
||||||
|
,insert_cmplib=NO
|
||||||
|
,lib=WORK
|
||||||
|
,cat=SASJS
|
||||||
|
,pkg=UTILS
|
||||||
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%if %mf_existfunction(mcf_length)=1 %then %return;
|
||||||
|
|
||||||
|
%if &wrap=YES %then %do;
|
||||||
|
proc fcmp outlib=&lib..&cat..&pkg;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
function mcf_length(var);
|
||||||
|
if var=. then len=0;
|
||||||
|
else if missing(var) or trunc(var,3)=var then len=3;
|
||||||
|
else if trunc(var,4)=var then len=4;
|
||||||
|
else if trunc(var,5)=var then len=5;
|
||||||
|
else if trunc(var,6)=var then len=6;
|
||||||
|
else if trunc(var,7)=var then len=7;
|
||||||
|
else len=8;
|
||||||
|
return(len);
|
||||||
|
endsub;
|
||||||
|
|
||||||
|
%if &wrap=YES %then %do;
|
||||||
|
quit;
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%if &insert_cmplib=YES %then %do;
|
||||||
|
options insert=(CMPLIB=(&lib..&cat));
|
||||||
|
%end;
|
||||||
|
|
||||||
|
%mend mcf_length;
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
%if %mf_existfunction(stpsrv_header)=1 %then %return;
|
%if %mf_existfunction(stpsrv_header)=1 %then %return;
|
||||||
|
|
||||||
%if &wrap=YES %then %do;
|
%if &wrap=YES %then %do;
|
||||||
proc fcmp outcat=&lib..&cat..&pkg;
|
proc fcmp outlib=&lib..&cat..&pkg;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
function stpsrv_header(name $, value $);
|
function stpsrv_header(name $, value $);
|
||||||
|
|||||||
@@ -39,6 +39,9 @@
|
|||||||
@param [out] pkg= (utils) The output package in which to create the function.
|
@param [out] pkg= (utils) The output package in which to create the function.
|
||||||
Uses a 3 part format: libref.catalog.package
|
Uses a 3 part format: libref.catalog.package
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_existfunction.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
%macro mcf_string2file(wrap=NO
|
%macro mcf_string2file(wrap=NO
|
||||||
@@ -48,8 +51,10 @@
|
|||||||
,pkg=UTILS
|
,pkg=UTILS
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%if %mf_existfunction(mcf_string2file)=1 %then %return;
|
||||||
|
|
||||||
%if &wrap=YES %then %do;
|
%if &wrap=YES %then %do;
|
||||||
proc fcmp outcat=&lib..&cat..&pkg;
|
proc fcmp outlib=&lib..&cat..&pkg;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
function mcf_string2file(filepath $, string $, mode $);
|
function mcf_string2file(filepath $, string $, mode $);
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
||||||
put ' ,engine=DATASTEP ';
|
put ' ,engine=DATASTEP ';
|
||||||
put ' ,dbg=0 /* DEPRECATED */ ';
|
|
||||||
put ' ,missing=NULL ';
|
put ' ,missing=NULL ';
|
||||||
put ' ,showmeta=NO ';
|
put ' ,showmeta=NO ';
|
||||||
put ')/*/STORE SOURCE*/; ';
|
put ')/*/STORE SOURCE*/; ';
|
||||||
@@ -383,7 +382,7 @@ data _null_;
|
|||||||
put ' set &tempds; ';
|
put ' set &tempds; ';
|
||||||
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
||||||
put ' i+1; ';
|
put ' i+1; ';
|
||||||
put ' call symputx(''wt''!!left(i),name,''l''); ';
|
put ' call symputx(cats(''wt'',i),name,''l''); ';
|
||||||
put ' call symputx(''wtcnt'',i,''l''); ';
|
put ' call symputx(''wtcnt'',i,''l''); ';
|
||||||
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
put ' data _null_; file &fref mod encoding=''utf-8''; ';
|
||||||
put ' put ",""WORK"":{"; ';
|
put ' put ",""WORK"":{"; ';
|
||||||
@@ -426,7 +425,8 @@ data _null_;
|
|||||||
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 ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; ';
|
||||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),datetime20.3)" ''" ''; ';
|
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
||||||
|
put ' length memsize $32; ';
|
||||||
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
||||||
put ' memsize=quote(cats(memsize)); ';
|
put ' memsize=quote(cats(memsize)); ';
|
||||||
put ' put '',"MEMSIZE" : '' memsize; ';
|
put ' put '',"MEMSIZE" : '' memsize; ';
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ data _null_;
|
|||||||
set repos;
|
set repos;
|
||||||
where repositorytype in('CUSTOM','FOUNDATION');
|
where repositorytype in('CUSTOM','FOUNDATION');
|
||||||
keep id name ;
|
keep id name ;
|
||||||
call symputx('repo'!!left(_n_),name,'l');
|
call symputx(cats('repo',_n_),name,'l');
|
||||||
call symputx('repocnt',_n_,'l');
|
call symputx('repocnt',_n_,'l');
|
||||||
run;
|
run;
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,6 @@
|
|||||||
@param [in] stpcode= the source file (or fileref) containing the SAS code to load
|
@param [in] stpcode= the source file (or fileref) containing the SAS code to load
|
||||||
into the stp. For multiple files, they should simply be concatenated first.
|
into the stp. For multiple files, they should simply be concatenated first.
|
||||||
@param [in] minify= set to YES in order to strip comments, blank lines, and CRLFs.
|
@param [in] minify= set to YES in order to strip comments, blank lines, and CRLFs.
|
||||||
|
|
||||||
@param frefin= deprecated - a unique fileref is now always used
|
|
||||||
@param frefout= deprecated - a unique fileref is now always used
|
|
||||||
@param mDebug= set to 1 to show debug messages in the log
|
@param mDebug= set to 1 to show debug messages in the log
|
||||||
|
|
||||||
@version 9.3
|
@version 9.3
|
||||||
@@ -30,16 +27,8 @@
|
|||||||
,stpcode=
|
,stpcode=
|
||||||
,minify=NO
|
,minify=NO
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
/* deprecated */
|
|
||||||
,frefin=inmeta
|
|
||||||
,frefout=outmeta
|
|
||||||
);
|
);
|
||||||
|
|
||||||
%if &frefin ne inmeta or &frefout ne outmeta %then %do;
|
|
||||||
%put %str(WARN)ING: the frefin and frefout parameters will be deprecated in
|
|
||||||
an upcoming release.;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
/* first, check if STP exists */
|
/* first, check if STP exists */
|
||||||
%local tsuri;
|
%local tsuri;
|
||||||
%let tsuri=stopifempty ;
|
%let tsuri=stopifempty ;
|
||||||
|
|||||||
@@ -122,7 +122,7 @@
|
|||||||
set &tempds;
|
set &tempds;
|
||||||
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
||||||
i+1;
|
i+1;
|
||||||
call symputx('wt'!!left(i),name,'l');
|
call symputx(cats('wt',i),name,'l');
|
||||||
call symputx('wtcnt',i,'l');
|
call symputx('wtcnt',i,'l');
|
||||||
data _null_; file &fref mod encoding='utf-8';
|
data _null_; file &fref mod encoding='utf-8';
|
||||||
put ",""WORK"":{";
|
put ",""WORK"":{";
|
||||||
@@ -165,7 +165,8 @@
|
|||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||||
|
length memsize $32;
|
||||||
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
||||||
memsize=quote(cats(memsize));
|
memsize=quote(cats(memsize));
|
||||||
put ',"MEMSIZE" : ' memsize;
|
put ',"MEMSIZE" : ' memsize;
|
||||||
|
|||||||
269
package-lock.json
generated
269
package-lock.json
generated
@@ -10,35 +10,55 @@
|
|||||||
"ts-loader": "^9.2.6"
|
"ts-loader": "^9.2.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sasjs/cli": "^3.4.1"
|
"@sasjs/cli": "3.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sasjs/adapter": {
|
"node_modules/@sasjs/adapter": {
|
||||||
"version": "3.3.1",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-3.4.1.tgz",
|
||||||
"integrity": "sha512-rmdOG+sjmwGipq1AHczwEXNUlzRFV5efj89neVVJWQMZR6JBC1O6Dr9HjEyJHPKcnQ6z3vzH9rRA2PGi5lgMhA==",
|
"integrity": "sha512-FbsvYDaoJAuH8FMidXhX3Kh4Eb8qIcxy5iiCxHgcSRWM89W29W21WfCqCw0F28yFr+V5vZkvphwXMKFdOGGxlw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sasjs/utils": "^2.32.0",
|
"@sasjs/utils": "2.32.0",
|
||||||
"axios": "^0.21.4",
|
"axios": "0.25.0",
|
||||||
"axios-cookiejar-support": "^1.0.1",
|
"axios-cookiejar-support": "1.0.1",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "4.0.0",
|
||||||
"https": "^1.0.0",
|
"https": "1.0.0",
|
||||||
"tough-cookie": "^4.0.0"
|
"tough-cookie": "4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sasjs/adapter/node_modules/@sasjs/utils": {
|
||||||
|
"version": "2.32.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.32.0.tgz",
|
||||||
|
"integrity": "sha512-xnvdEuI4PhTtulcdDEIMK7IxVj9bOMU1JTnxRuSEKWcsclY9P9Fw3cnMOOEgXCDffrOPn3f54DP7Wb1GXd+f8g==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/fs-extra": "^9.0.11",
|
||||||
|
"@types/prompts": "^2.0.13",
|
||||||
|
"chalk": "^4.1.1",
|
||||||
|
"cli-table": "^0.3.6",
|
||||||
|
"consola": "^2.15.0",
|
||||||
|
"csv-stringify": "^5.6.5",
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
|
"jwt-decode": "^3.1.2",
|
||||||
|
"prompts": "^2.4.1",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"valid-url": "^1.0.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@sasjs/cli": {
|
"node_modules/@sasjs/cli": {
|
||||||
"version": "3.4.1",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-3.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-3.6.0.tgz",
|
||||||
"integrity": "sha512-voc0/h8bkRAqrj7Pu1egYfCOSFLlLrrh9bXVLuGvSvWK81MezRZnWciTHlQGc9BgO2wU+LrQ0baIMd6u/HMB5Q==",
|
"integrity": "sha512-px5aFXNoTlML7g4TvP92q/uqWnHGbxnwEzy+4D+sJbXgpzLlCyyuUU7rbd/9sXT+/Pi7vjfHfBCv0JhoGYr6gw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sasjs/adapter": "3.3.1",
|
"@sasjs/adapter": "3.4.1",
|
||||||
"@sasjs/core": "^3.8.0",
|
"@sasjs/core": "3.10.0",
|
||||||
"@sasjs/lint": "1.11.2",
|
"@sasjs/lint": "1.11.2",
|
||||||
"@sasjs/utils": "2.34.1",
|
"@sasjs/utils": "2.35.0",
|
||||||
"chalk": "4.1.2",
|
"chalk": "4.1.2",
|
||||||
"csv-stringify": "5.6.5",
|
"csv-stringify": "5.6.5",
|
||||||
"dotenv": "10.0.0",
|
"dotenv": "10.0.0",
|
||||||
@@ -53,7 +73,7 @@
|
|||||||
"node-graphviz": "0.1.0",
|
"node-graphviz": "0.1.0",
|
||||||
"ora": "5.4.1",
|
"ora": "5.4.1",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"shelljs": "0.8.4",
|
"shelljs": "0.8.5",
|
||||||
"xml": "1.0.1",
|
"xml": "1.0.1",
|
||||||
"yargs": "17.2.1"
|
"yargs": "17.2.1"
|
||||||
},
|
},
|
||||||
@@ -61,10 +81,31 @@
|
|||||||
"sasjs": "build/index.js"
|
"sasjs": "build/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@sasjs/cli/node_modules/@sasjs/utils": {
|
||||||
|
"version": "2.35.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.35.0.tgz",
|
||||||
|
"integrity": "sha512-q9ZKV+TXqwiaj+0z5U7/00eBpp2QpjKfC9BKx7A6rQjBl10WtoWd5C9Em+RQULWVEdRbVS2XcnNsWelbKq/Zsw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/fs-extra": "^9.0.13",
|
||||||
|
"@types/prompts": "^2.0.13",
|
||||||
|
"chalk": "^4.1.1",
|
||||||
|
"cli-table": "^0.3.6",
|
||||||
|
"consola": "^2.15.0",
|
||||||
|
"csv-stringify": "^5.6.5",
|
||||||
|
"find": "0.3.0",
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
|
"jwt-decode": "^3.1.2",
|
||||||
|
"prompts": "^2.4.1",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"valid-url": "^1.0.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@sasjs/core": {
|
"node_modules/@sasjs/core": {
|
||||||
"version": "3.8.1",
|
"version": "3.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/core/-/core-3.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/core/-/core-3.10.0.tgz",
|
||||||
"integrity": "sha512-Yxak+WZwh8Z9IKcbi7aDDTRCcKlI6IUp7Ujavkec5pWMj3a2FSlLxu23lY2ERTBe7wMCGiaU7AseWlKcgd5joA==",
|
"integrity": "sha512-lgLxDYpIvwSrXFaUaTFCR0KXHQEc5QIOL4DU87TvBHEUUAWNQHzuVQWkavLtW5hbvLGnPXnyvspzoSzmBojXzg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ts-loader": "^9.2.6"
|
"ts-loader": "^9.2.6"
|
||||||
@@ -138,9 +179,9 @@
|
|||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/fs-extra": {
|
"node_modules/@types/fs-extra": {
|
||||||
"version": "9.0.12",
|
"version": "9.0.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
|
||||||
"integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==",
|
"integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
@@ -455,12 +496,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "0.21.4",
|
"version": "0.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
|
||||||
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.14.0"
|
"follow-redirects": "^1.14.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios-cookiejar-support": {
|
"node_modules/axios-cookiejar-support": {
|
||||||
@@ -1057,9 +1098,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.14.6",
|
"version": "1.14.7",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
|
||||||
"integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
|
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1341,9 +1382,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-core-module": {
|
"node_modules/is-core-module": {
|
||||||
"version": "2.4.0",
|
"version": "2.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
|
||||||
"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
|
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has": "^1.0.3"
|
"has": "^1.0.3"
|
||||||
@@ -1893,13 +1934,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.20.0",
|
"version": "1.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz",
|
||||||
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
"integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-core-module": "^2.2.0",
|
"is-core-module": "^2.8.0",
|
||||||
"path-parse": "^1.0.6"
|
"path-parse": "^1.0.7",
|
||||||
|
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"resolve": "bin/resolve"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@@ -2025,9 +2070,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/shelljs": {
|
"node_modules/shelljs": {
|
||||||
"version": "0.8.4",
|
"version": "0.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
|
||||||
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
|
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob": "^7.0.0",
|
"glob": "^7.0.0",
|
||||||
@@ -2117,6 +2162,18 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/supports-preserve-symlinks-flag": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/symbol-tree": {
|
"node_modules/symbol-tree": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||||
@@ -2587,29 +2644,50 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sasjs/adapter": {
|
"@sasjs/adapter": {
|
||||||
"version": "3.3.1",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/adapter/-/adapter-3.4.1.tgz",
|
||||||
"integrity": "sha512-rmdOG+sjmwGipq1AHczwEXNUlzRFV5efj89neVVJWQMZR6JBC1O6Dr9HjEyJHPKcnQ6z3vzH9rRA2PGi5lgMhA==",
|
"integrity": "sha512-FbsvYDaoJAuH8FMidXhX3Kh4Eb8qIcxy5iiCxHgcSRWM89W29W21WfCqCw0F28yFr+V5vZkvphwXMKFdOGGxlw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sasjs/utils": "^2.32.0",
|
"@sasjs/utils": "2.32.0",
|
||||||
"axios": "^0.21.4",
|
"axios": "0.25.0",
|
||||||
"axios-cookiejar-support": "^1.0.1",
|
"axios-cookiejar-support": "1.0.1",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "4.0.0",
|
||||||
"https": "^1.0.0",
|
"https": "1.0.0",
|
||||||
"tough-cookie": "^4.0.0"
|
"tough-cookie": "4.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sasjs/utils": {
|
||||||
|
"version": "2.32.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.32.0.tgz",
|
||||||
|
"integrity": "sha512-xnvdEuI4PhTtulcdDEIMK7IxVj9bOMU1JTnxRuSEKWcsclY9P9Fw3cnMOOEgXCDffrOPn3f54DP7Wb1GXd+f8g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/fs-extra": "^9.0.11",
|
||||||
|
"@types/prompts": "^2.0.13",
|
||||||
|
"chalk": "^4.1.1",
|
||||||
|
"cli-table": "^0.3.6",
|
||||||
|
"consola": "^2.15.0",
|
||||||
|
"csv-stringify": "^5.6.5",
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
|
"jwt-decode": "^3.1.2",
|
||||||
|
"prompts": "^2.4.1",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"valid-url": "^1.0.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sasjs/cli": {
|
"@sasjs/cli": {
|
||||||
"version": "3.4.1",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-3.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/cli/-/cli-3.6.0.tgz",
|
||||||
"integrity": "sha512-voc0/h8bkRAqrj7Pu1egYfCOSFLlLrrh9bXVLuGvSvWK81MezRZnWciTHlQGc9BgO2wU+LrQ0baIMd6u/HMB5Q==",
|
"integrity": "sha512-px5aFXNoTlML7g4TvP92q/uqWnHGbxnwEzy+4D+sJbXgpzLlCyyuUU7rbd/9sXT+/Pi7vjfHfBCv0JhoGYr6gw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sasjs/adapter": "3.3.1",
|
"@sasjs/adapter": "3.4.1",
|
||||||
"@sasjs/core": "^3.8.0",
|
"@sasjs/core": "3.10.0",
|
||||||
"@sasjs/lint": "1.11.2",
|
"@sasjs/lint": "1.11.2",
|
||||||
"@sasjs/utils": "2.34.1",
|
"@sasjs/utils": "2.35.0",
|
||||||
"chalk": "4.1.2",
|
"chalk": "4.1.2",
|
||||||
"csv-stringify": "5.6.5",
|
"csv-stringify": "5.6.5",
|
||||||
"dotenv": "10.0.0",
|
"dotenv": "10.0.0",
|
||||||
@@ -2624,15 +2702,37 @@
|
|||||||
"node-graphviz": "0.1.0",
|
"node-graphviz": "0.1.0",
|
||||||
"ora": "5.4.1",
|
"ora": "5.4.1",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"shelljs": "0.8.4",
|
"shelljs": "0.8.5",
|
||||||
"xml": "1.0.1",
|
"xml": "1.0.1",
|
||||||
"yargs": "17.2.1"
|
"yargs": "17.2.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@sasjs/utils": {
|
||||||
|
"version": "2.35.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sasjs/utils/-/utils-2.35.0.tgz",
|
||||||
|
"integrity": "sha512-q9ZKV+TXqwiaj+0z5U7/00eBpp2QpjKfC9BKx7A6rQjBl10WtoWd5C9Em+RQULWVEdRbVS2XcnNsWelbKq/Zsw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/fs-extra": "^9.0.13",
|
||||||
|
"@types/prompts": "^2.0.13",
|
||||||
|
"chalk": "^4.1.1",
|
||||||
|
"cli-table": "^0.3.6",
|
||||||
|
"consola": "^2.15.0",
|
||||||
|
"csv-stringify": "^5.6.5",
|
||||||
|
"find": "0.3.0",
|
||||||
|
"fs-extra": "^10.0.0",
|
||||||
|
"jwt-decode": "^3.1.2",
|
||||||
|
"prompts": "^2.4.1",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"valid-url": "^1.0.9"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sasjs/core": {
|
"@sasjs/core": {
|
||||||
"version": "3.8.1",
|
"version": "3.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sasjs/core/-/core-3.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@sasjs/core/-/core-3.10.0.tgz",
|
||||||
"integrity": "sha512-Yxak+WZwh8Z9IKcbi7aDDTRCcKlI6IUp7Ujavkec5pWMj3a2FSlLxu23lY2ERTBe7wMCGiaU7AseWlKcgd5joA==",
|
"integrity": "sha512-lgLxDYpIvwSrXFaUaTFCR0KXHQEc5QIOL4DU87TvBHEUUAWNQHzuVQWkavLtW5hbvLGnPXnyvspzoSzmBojXzg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ts-loader": "^9.2.6"
|
"ts-loader": "^9.2.6"
|
||||||
@@ -2702,9 +2802,9 @@
|
|||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"@types/fs-extra": {
|
"@types/fs-extra": {
|
||||||
"version": "9.0.12",
|
"version": "9.0.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
|
||||||
"integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==",
|
"integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
@@ -2986,12 +3086,12 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "0.21.4",
|
"version": "0.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
|
||||||
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.14.0"
|
"follow-redirects": "^1.14.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"axios-cookiejar-support": {
|
"axios-cookiejar-support": {
|
||||||
@@ -3433,9 +3533,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"follow-redirects": {
|
"follow-redirects": {
|
||||||
"version": "1.14.6",
|
"version": "1.14.7",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz",
|
||||||
"integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
|
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"form-data": {
|
"form-data": {
|
||||||
@@ -3639,9 +3739,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"is-core-module": {
|
"is-core-module": {
|
||||||
"version": "2.4.0",
|
"version": "2.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
|
||||||
"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
|
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"has": "^1.0.3"
|
"has": "^1.0.3"
|
||||||
@@ -4063,13 +4163,14 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.20.0",
|
"version": "1.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz",
|
||||||
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
"integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"is-core-module": "^2.2.0",
|
"is-core-module": "^2.8.0",
|
||||||
"path-parse": "^1.0.6"
|
"path-parse": "^1.0.7",
|
||||||
|
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"resolve-dir": {
|
"resolve-dir": {
|
||||||
@@ -4150,9 +4251,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"shelljs": {
|
"shelljs": {
|
||||||
"version": "0.8.4",
|
"version": "0.8.5",
|
||||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
|
||||||
"integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==",
|
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"glob": "^7.0.0",
|
"glob": "^7.0.0",
|
||||||
@@ -4224,6 +4325,12 @@
|
|||||||
"has-flag": "^4.0.0"
|
"has-flag": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"supports-preserve-symlinks-flag": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"symbol-tree": {
|
"symbol-tree": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
|
||||||
|
|||||||
@@ -33,9 +33,6 @@
|
|||||||
"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.4.1"
|
"@sasjs/cli": "3.6.0"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ts-loader": "^9.2.6"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,7 +114,7 @@
|
|||||||
set &tempds;
|
set &tempds;
|
||||||
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
||||||
i+1;
|
i+1;
|
||||||
call symputx('wt'!!left(i),name,'l');
|
call symputx(cats('wt',i),name,'l');
|
||||||
call symputx('wtcnt',i,'l');
|
call symputx('wtcnt',i,'l');
|
||||||
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
data _null_; file &fref mod encoding='utf-8' termstr=lf;
|
||||||
put ",""WORK"":{";
|
put ",""WORK"":{";
|
||||||
@@ -161,10 +161,11 @@
|
|||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
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'))));
|
||||||
put ',"AUTOEXEC" : ' autoexec;
|
put ',"AUTOEXEC" : ' autoexec;
|
||||||
|
length memsize $32;
|
||||||
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
||||||
memsize=quote(cats(memsize));
|
memsize=quote(cats(memsize));
|
||||||
put ',"MEMSIZE" : ' memsize;
|
put ',"MEMSIZE" : ' memsize;
|
||||||
|
|||||||
67
tests/crossplatform/mcf_length.test.sas
Normal file
67
tests/crossplatform/mcf_length.test.sas
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mcf_length.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mcf_length.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%mcf_length(wrap=YES, insert_cmplib=YES)
|
||||||
|
|
||||||
|
data test;
|
||||||
|
call symputx('null',mcf_length(.));
|
||||||
|
call symputx('special',mcf_length(._));
|
||||||
|
call symputx('three',mcf_length(1));
|
||||||
|
call symputx('four',mcf_length(10000000));
|
||||||
|
call symputx('five',mcf_length(12345678));
|
||||||
|
call symputx('six',mcf_length(1234567890));
|
||||||
|
call symputx('seven',mcf_length(12345678901234));
|
||||||
|
call symputx('eight',mcf_length(12345678901234567));
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&null)=%str(0)),
|
||||||
|
desc=Check if NULL returns 0
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&special)=%str(3)),
|
||||||
|
desc=Check if special missing ._ returns 3
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&three)=%str(3)),
|
||||||
|
desc=Check for length 3
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&four)=%str(4)),
|
||||||
|
desc=Check for length 4
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&five)=%str(5)),
|
||||||
|
desc=Check for length 5
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&six)=%str(6)),
|
||||||
|
desc=Check for length 6
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&seven)=%str(7)),
|
||||||
|
desc=Check for length 3
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%str(&eight)=%str(8)),
|
||||||
|
desc=Check for length 8
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&syscc=0),
|
||||||
|
desc=Check syscc=0 before re-initialisation
|
||||||
|
)
|
||||||
|
|
||||||
|
/* test 2 - compile again test for warnings */
|
||||||
|
%mcf_length(wrap=YES, insert_cmplib=YES)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&syscc=0),
|
||||||
|
desc=Check syscc=0 after re-initialisation
|
||||||
|
)
|
||||||
15
tests/crossplatform/mp_assert.test.sas
Normal file
15
tests/crossplatform/mp_assert.test.sas
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mp_assert macro
|
||||||
|
@details This is quite "meta".. it's just testing itself
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mp_assert.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(1=1),
|
||||||
|
desc=Checking result was created,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
80
tests/crossplatform/mp_assertscope.test.sas
Normal file
80
tests/crossplatform/mp_assertscope.test.sas
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mp_assertscope macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getvalue.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro dostuff(action);
|
||||||
|
%if &action=ADD %then %do;
|
||||||
|
%global NEWVAR1 NEWVAR2;
|
||||||
|
%end;
|
||||||
|
%else %if &action=DEL %then %do;
|
||||||
|
%symdel NEWVAR1 NEWVAR2;
|
||||||
|
%end;
|
||||||
|
%else %if &action=MOD %then %do;
|
||||||
|
%let NEWVAR1=Let us pray..;
|
||||||
|
%end;
|
||||||
|
%else %if &action=NOTHING %then %do;
|
||||||
|
%local a b c d e;
|
||||||
|
%end;
|
||||||
|
%mend dostuff;
|
||||||
|
|
||||||
|
|
||||||
|
/* check for adding variables */
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%dostuff(ADD)
|
||||||
|
%mp_assertscope(COMPARE,outds=work.testing_the_tester1)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_getvalue(work.testing_the_tester1,test_comments)"
|
||||||
|
="Mod:() Add:(NEWVAR1 NEWVAR2) Del:()"
|
||||||
|
),
|
||||||
|
desc=Checking result when vars added,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/* check for modifying variables */
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%dostuff(MOD)
|
||||||
|
%mp_assertscope(COMPARE,outds=work.testing_the_tester2)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_getvalue(work.testing_the_tester2,test_comments)"
|
||||||
|
="Mod:(NEWVAR1) Add:() Del:()"
|
||||||
|
),
|
||||||
|
desc=Checking result when vars modified,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* check for deleting variables */
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%dostuff(DEL)
|
||||||
|
%mp_assertscope(COMPARE,outds=work.testing_the_tester3)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_getvalue(work.testing_the_tester3,test_comments)"
|
||||||
|
="Mod:() Add:() Del:(NEWVAR1 NEWVAR2)"
|
||||||
|
),
|
||||||
|
desc=Checking result when vars deleted,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
/* check for doing nothing */
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%dostuff(NOTHING)
|
||||||
|
%mp_assertscope(COMPARE,outds=work.testing_the_tester4)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(
|
||||||
|
"%mf_getvalue(work.testing_the_tester4,test_comments)"
|
||||||
|
="GLOBAL Variables Unmodified"
|
||||||
|
),
|
||||||
|
desc=Checking results when nothing created,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
44
tests/crossplatform/mp_ds2squeeze.test.sas
Normal file
44
tests/crossplatform/mp_ds2squeeze.test.sas
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mp_ds2squeeze.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_getvarlen.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
@li mp_ds2squeeze.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
data big;
|
||||||
|
length my big $32000;
|
||||||
|
do i=1 to 1e4;
|
||||||
|
my=repeat('oh my',100);
|
||||||
|
big='dawg';
|
||||||
|
special=._;
|
||||||
|
missn=.;
|
||||||
|
missc='';
|
||||||
|
output;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mp_ds2squeeze(work.big,outds=work.smaller)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&syscc=0),
|
||||||
|
desc=Checking syscc
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mf_getvarlen(work.smaller,missn)=3),
|
||||||
|
desc=Check missing numeric is 3
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mf_getvarlen(work.smaller,special)=3),
|
||||||
|
desc=Check missing special numeric is 3
|
||||||
|
)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mf_getvarlen(work.smaller,missc)=1),
|
||||||
|
desc=Check missing char is 1
|
||||||
|
)
|
||||||
80
tests/crossplatform/mp_getmaxvarlengths.test.sas
Normal file
80
tests/crossplatform/mp_getmaxvarlengths.test.sas
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mp_getmaxvarlengths macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mp_getmaxvarlengths.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertdsobs.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
/* regular usage */
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mp_getmaxvarlengths(sashelp.class,outds=work.myds)
|
||||||
|
%mp_assertscope(COMPARE,desc=checking scope leakage on mp_getmaxvarlengths)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&syscc=0),
|
||||||
|
desc=No errs
|
||||||
|
)
|
||||||
|
%mp_assertdsobs(work.myds,
|
||||||
|
desc=Has 5 records,
|
||||||
|
test=EQUALS 5
|
||||||
|
)
|
||||||
|
data work.errs;
|
||||||
|
set work.myds;
|
||||||
|
if name='Name' and maxlen ne 7 then output;
|
||||||
|
if name='Sex' and maxlen ne 1 then output;
|
||||||
|
if name='Age' and maxlen ne 3 then output;
|
||||||
|
if name='Height' and maxlen ne 8 then output;
|
||||||
|
if name='Weight' and maxlen ne 3 then output;
|
||||||
|
run;
|
||||||
|
data _null_;
|
||||||
|
set work.errs;
|
||||||
|
putlog (_all_)(=);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assertdsobs(work.errs,
|
||||||
|
desc=Err table has 0 records,
|
||||||
|
test=EQUALS 0
|
||||||
|
)
|
||||||
|
|
||||||
|
/* test2 */
|
||||||
|
data work.test2;
|
||||||
|
length a 3 b 5;
|
||||||
|
a=1/3;
|
||||||
|
b=1/3;
|
||||||
|
c=1/3;
|
||||||
|
d=._;
|
||||||
|
e=.;
|
||||||
|
output;
|
||||||
|
output;
|
||||||
|
run;
|
||||||
|
%mp_getmaxvarlengths(work.test2,outds=work.myds2)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(&syscc=0),
|
||||||
|
desc=No errs in second test (with nulls)
|
||||||
|
)
|
||||||
|
%mp_assertdsobs(work.myds2,
|
||||||
|
desc=Has 5 records,
|
||||||
|
test=EQUALS 5
|
||||||
|
)
|
||||||
|
data work.errs2;
|
||||||
|
set work.myds2;
|
||||||
|
if name='a' and maxlen ne 3 then output;
|
||||||
|
if name='b' and maxlen ne 5 then output;
|
||||||
|
if name='c' and maxlen ne 8 then output;
|
||||||
|
if name='d' and maxlen ne 3 then output;
|
||||||
|
if name='e' and maxlen ne 0 then output;
|
||||||
|
run;
|
||||||
|
data _null_;
|
||||||
|
set work.errs2;
|
||||||
|
putlog (_all_)(=);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assertdsobs(work.errs2,
|
||||||
|
desc=Err table has 0 records,
|
||||||
|
test=EQUALS 0
|
||||||
|
)
|
||||||
@@ -112,6 +112,9 @@ datalines4;
|
|||||||
0
|
0
|
||||||
above are good
|
above are good
|
||||||
the rest are bad
|
the rest are bad
|
||||||
|
0.1
|
||||||
|
1.1
|
||||||
|
-0.001
|
||||||
%abort
|
%abort
|
||||||
1&somethingverybad.
|
1&somethingverybad.
|
||||||
&
|
&
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_init.sas
|
@li mp_init.sas
|
||||||
|
@li mv_webout.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|||||||
@@ -239,7 +239,6 @@ data _null_;
|
|||||||
put ' ';
|
put ' ';
|
||||||
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
put '%macro mp_jsonout(action,ds,jref=_webout,dslabel=,fmt=Y ';
|
||||||
put ' ,engine=DATASTEP ';
|
put ' ,engine=DATASTEP ';
|
||||||
put ' ,dbg=0 /* DEPRECATED */ ';
|
|
||||||
put ' ,missing=NULL ';
|
put ' ,missing=NULL ';
|
||||||
put ' ,showmeta=NO ';
|
put ' ,showmeta=NO ';
|
||||||
put ')/*/STORE SOURCE*/; ';
|
put ')/*/STORE SOURCE*/; ';
|
||||||
@@ -589,8 +588,8 @@ data _null_;
|
|||||||
put ' set &tempds; ';
|
put ' set &tempds; ';
|
||||||
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
put ' if not (upcase(name) =:"DATA"); /* ignore temp datasets */ ';
|
||||||
put ' i+1; ';
|
put ' i+1; ';
|
||||||
put ' call symputx(''wt''!!left(i),name); ';
|
put ' call symputx(cats(''wt'',i),name,''l''); ';
|
||||||
put ' call symputx(''wtcnt'',i); ';
|
put ' call symputx(''wtcnt'',i,''l''); ';
|
||||||
put ' data _null_; file &fref mod; put ",""WORK"":{"; ';
|
put ' data _null_; file &fref mod; put ",""WORK"":{"; ';
|
||||||
put ' %do i=1 %to &wtcnt; ';
|
put ' %do i=1 %to &wtcnt; ';
|
||||||
put ' %let wt=&&wt&i; ';
|
put ' %let wt=&&wt&i; ';
|
||||||
@@ -627,7 +626,8 @@ data _null_;
|
|||||||
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 ' put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" "; ';
|
||||||
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),datetime20.3)" ''" ''; ';
|
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
|
||||||
|
put ' length memsize $32; ';
|
||||||
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
put ' memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)"; ';
|
||||||
put ' memsize=quote(cats(memsize)); ';
|
put ' memsize=quote(cats(memsize)); ';
|
||||||
put ' put '',"MEMSIZE" : '' memsize; ';
|
put ' put '',"MEMSIZE" : '' memsize; ';
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ libname &libref1a JSON fileref=&fname1a;
|
|||||||
%let found=0;
|
%let found=0;
|
||||||
%put Getting object uri from &libref1a..items;
|
%put Getting object uri from &libref1a..items;
|
||||||
data _null_;
|
data _null_;
|
||||||
|
length contenttype name $1000;
|
||||||
set &libref1a..items;
|
set &libref1a..items;
|
||||||
if contenttype="&contenttype" and upcase(name)="%upcase(&name)" then do;
|
if contenttype="&contenttype" and upcase(name)="%upcase(&name)" then do;
|
||||||
call symputx('uri',uri,'l');
|
call symputx('uri',uri,'l');
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ libname &libref1a JSON fileref=&fname1a;
|
|||||||
%let found=0;
|
%let found=0;
|
||||||
%put Getting object uri from &libref1a..items;
|
%put Getting object uri from &libref1a..items;
|
||||||
data _null_;
|
data _null_;
|
||||||
|
length contenttype name $1000;
|
||||||
set &libref1a..items;
|
set &libref1a..items;
|
||||||
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then do;
|
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then do;
|
||||||
call symputx('uri',cats("&base_uri",uri),'l');
|
call symputx('uri',cats("&base_uri",uri),'l');
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/**
|
|
||||||
@file mv_getaccesstoken.sas
|
|
||||||
@brief deprecated - replaced by mv_tokenrefresh.sas
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
|
||||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mv_tokenrefresh.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mv_getaccesstoken(client_id=someclient
|
|
||||||
,client_secret=somesecret
|
|
||||||
,grant_type=authorization_code
|
|
||||||
,code=
|
|
||||||
,user=
|
|
||||||
,pass=
|
|
||||||
,access_token_var=ACCESS_TOKEN
|
|
||||||
,refresh_token_var=REFRESH_TOKEN
|
|
||||||
);
|
|
||||||
|
|
||||||
%mv_tokenrefresh(client_id=&client_id
|
|
||||||
,client_secret=&client_secret
|
|
||||||
,grant_type=&grant_type
|
|
||||||
,user=&user
|
|
||||||
,pass=&pass
|
|
||||||
,access_token_var=&access_token_var
|
|
||||||
,refresh_token_var=&refresh_token_var
|
|
||||||
)
|
|
||||||
|
|
||||||
%mend mv_getaccesstoken;
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief deprecated - replaced by mv_registerclient.sas
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
|
||||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mv_registerclient.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mv_getapptoken(client_id=someclient
|
|
||||||
,client_secret=somesecret
|
|
||||||
,grant_type=authorization_code
|
|
||||||
);
|
|
||||||
|
|
||||||
%mv_registerclient(client_id=&client_id
|
|
||||||
,client_secret=&client_secret
|
|
||||||
,grant_type=&grant_type
|
|
||||||
)
|
|
||||||
|
|
||||||
%mend mv_getapptoken;
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/**
|
|
||||||
@file mv_getrefreshtoken.sas
|
|
||||||
@brief deprecated - replaced by mv_tokenauth.sas
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
|
||||||
@author Allan Bowe, source: https://github.com/sasjs/core
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mv_tokenauth.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mv_getrefreshtoken(client_id=someclient
|
|
||||||
,client_secret=somesecret
|
|
||||||
,grant_type=authorization_code
|
|
||||||
,code=
|
|
||||||
,user=
|
|
||||||
,pass=
|
|
||||||
,access_token_var=ACCESS_TOKEN
|
|
||||||
,refresh_token_var=REFRESH_TOKEN
|
|
||||||
);
|
|
||||||
|
|
||||||
%mv_tokenauth(client_id=&client_id
|
|
||||||
,client_secret=&client_secret
|
|
||||||
,grant_type=&grant_type
|
|
||||||
,code=&code
|
|
||||||
,user=&user
|
|
||||||
,pass=&pass
|
|
||||||
,access_token_var=&access_token_var
|
|
||||||
,refresh_token_var=&refresh_token_var
|
|
||||||
)
|
|
||||||
|
|
||||||
%mend mv_getrefreshtoken;
|
|
||||||
@@ -272,7 +272,7 @@ data;run;%let jdswaitfor=&syslast;
|
|||||||
data _null_;
|
data _null_;
|
||||||
infile &jfref lrecl=32767;
|
infile &jfref lrecl=32767;
|
||||||
input;
|
input;
|
||||||
jparams='jparams'!!left(symget('jid'));
|
jparams=cats('jparams',symget('jid'));
|
||||||
call symputx(jparams,substr(_infile_,3,length(_infile_)-4));
|
call symputx(jparams,substr(_infile_,3,length(_infile_)-4));
|
||||||
run;
|
run;
|
||||||
%local jobuid&jid;
|
%local jobuid&jid;
|
||||||
|
|||||||
@@ -187,8 +187,8 @@
|
|||||||
set &tempds;
|
set &tempds;
|
||||||
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
if not (upcase(name) =:"DATA"); /* ignore temp datasets */
|
||||||
i+1;
|
i+1;
|
||||||
call symputx('wt'!!left(i),name);
|
call symputx(cats('wt',i),name,'l');
|
||||||
call symputx('wtcnt',i);
|
call symputx('wtcnt',i,'l');
|
||||||
data _null_; file &fref mod; put ",""WORK"":{";
|
data _null_; file &fref mod; put ",""WORK"":{";
|
||||||
%do i=1 %to &wtcnt;
|
%do i=1 %to &wtcnt;
|
||||||
%let wt=&&wt&i;
|
%let wt=&&wt&i;
|
||||||
@@ -225,7 +225,8 @@
|
|||||||
sysvlong=quote(trim(symget('sysvlong')));
|
sysvlong=quote(trim(symget('sysvlong')));
|
||||||
put ',"SYSVLONG" : ' sysvlong;
|
put ',"SYSVLONG" : ' sysvlong;
|
||||||
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
|
||||||
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
|
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
|
||||||
|
length memsize $32;
|
||||||
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
memsize="%sysfunc(INPUTN(%sysfunc(getoption(memsize)), best.),sizekmg.)";
|
||||||
memsize=quote(cats(memsize));
|
memsize=quote(cats(memsize));
|
||||||
put ',"MEMSIZE" : ' memsize;
|
put ',"MEMSIZE" : ' memsize;
|
||||||
|
|||||||
Reference in New Issue
Block a user