@sasjs/utils 2.49.0 → 2.49.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fs/internal/helper.js +19 -24
- package/fs/internal/helper.js.map +1 -1
- package/macros/mf_abort.sas +27 -0
- package/macros/mf_dedup.sas +53 -0
- package/macros/mf_deletefile.sas +31 -0
- package/macros/mf_existds.sas +30 -0
- package/macros/mf_existfeature.sas +59 -0
- package/macros/mf_existfileref.sas +33 -0
- package/macros/mf_existfunction.sas +37 -0
- package/macros/mf_existvar.sas +39 -0
- package/macros/mf_existvarlist.sas +56 -0
- package/macros/mf_fmtdttm.sas +42 -0
- package/macros/mf_getapploc.sas +78 -0
- package/macros/mf_getattrc.sas +34 -0
- package/macros/mf_getattrn.sas +34 -0
- package/macros/mf_getengine.sas +54 -0
- package/macros/mf_getfilesize.sas +64 -0
- package/macros/mf_getfmtlist.sas +61 -0
- package/macros/mf_getfmtname.sas +44 -0
- package/macros/mf_getkeyvalue.sas +32 -0
- package/macros/mf_getplatform.sas +75 -0
- package/macros/mf_getquotedstr.sas +57 -0
- package/macros/mf_getschema.sas +43 -0
- package/macros/mf_getuniquefileref.sas +60 -0
- package/macros/mf_getuniquelibref.sas +57 -0
- package/macros/mf_getuniquename.sas +22 -0
- package/macros/mf_getuser.sas +44 -0
- package/macros/mf_getvalue.sas +36 -0
- package/macros/mf_getvarcount.sas +49 -0
- package/macros/mf_getvarformat.sas +72 -0
- package/macros/mf_getvarlen.sas +56 -0
- package/macros/mf_getvarlist.sas +74 -0
- package/macros/mf_getvarnum.sas +58 -0
- package/macros/mf_getvartype.sas +52 -0
- package/macros/mf_getxengine.sas +43 -0
- package/macros/mf_increment.sas +29 -0
- package/macros/mf_isblank.sas +27 -0
- package/macros/mf_isdir.sas +34 -0
- package/macros/mf_isint.sas +36 -0
- package/macros/mf_islibds.sas +40 -0
- package/macros/mf_loc.sas +29 -0
- package/macros/mf_mkdir.sas +67 -0
- package/macros/mf_mval.sas +19 -0
- package/macros/mf_nobs.sas +26 -0
- package/macros/mf_trimstr.sas +50 -0
- package/macros/mf_uid.sas +21 -0
- package/macros/mf_verifymacvars.sas +72 -0
- package/macros/mf_wordsinstr1andstr2.sas +53 -0
- package/macros/mf_wordsinstr1butnotstr2.sas +54 -0
- package/macros/mf_writefile.sas +67 -0
- package/macros/mp_abort.sas +301 -0
- package/macros/mp_appendfile.sas +57 -0
- package/macros/mp_applyformats.sas +181 -0
- package/macros/mp_assert.sas +56 -0
- package/macros/mp_assertcols.sas +145 -0
- package/macros/mp_assertcolvals.sas +168 -0
- package/macros/mp_assertdsobs.sas +121 -0
- package/macros/mp_assertscope.sas +147 -0
- package/macros/mp_base64copy.sas +117 -0
- package/macros/mp_binarycopy.sas +79 -0
- package/macros/mp_chop.sas +194 -0
- package/macros/mp_cleancsv.sas +78 -0
- package/macros/mp_cntlout.sas +85 -0
- package/macros/mp_copyfolder.sas +84 -0
- package/macros/mp_coretable.sas +73 -0
- package/macros/mp_createconstraints.sas +70 -0
- package/macros/mp_createwebservice.sas +32 -0
- package/macros/mp_csv2ds.sas +140 -0
- package/macros/mp_deleteconstraints.sas +52 -0
- package/macros/mp_deletefolder.sas +70 -0
- package/macros/mp_dictionary.sas +52 -0
- package/macros/mp_dirlist.sas +262 -0
- package/macros/mp_distinctfmtvalues.sas +50 -0
- package/macros/mp_dropmembers.sas +46 -0
- package/macros/mp_ds2cards.sas +291 -0
- package/macros/mp_ds2csv.sas +212 -0
- package/macros/mp_ds2ddl.sas +30 -0
- package/macros/mp_ds2fmtds.sas +105 -0
- package/macros/mp_ds2inserts.sas +180 -0
- package/macros/mp_ds2md.sas +103 -0
- package/macros/mp_ds2squeeze.sas +120 -0
- package/macros/mp_dsmeta.sas +110 -0
- package/macros/mp_filtercheck.sas +251 -0
- package/macros/mp_filtergenerate.sas +105 -0
- package/macros/mp_filterstore.sas +254 -0
- package/macros/mp_filtervalidate.sas +105 -0
- package/macros/mp_getcols.sas +67 -0
- package/macros/mp_getconstraints.sas +115 -0
- package/macros/mp_getdbml.sas +335 -0
- package/macros/mp_getddl.sas +400 -0
- package/macros/mp_getformats.sas +124 -0
- package/macros/mp_getmaxvarlengths.sas +130 -0
- package/macros/mp_getpk.sas +281 -0
- package/macros/mp_gitadd.sas +45 -0
- package/macros/mp_gitreleaseinfo.sas +74 -0
- package/macros/mp_gitstatus.sas +67 -0
- package/macros/mp_gsubfile.sas +58 -0
- package/macros/mp_guesspk.sas +332 -0
- package/macros/mp_hashdataset.sas +91 -0
- package/macros/mp_hashdirectory.sas +164 -0
- package/macros/mp_include.sas +106 -0
- package/macros/mp_init.sas +76 -0
- package/macros/mp_jsonout.sas +406 -0
- package/macros/mp_lib2cards.sas +78 -0
- package/macros/mp_lib2inserts.sas +77 -0
- package/macros/mp_loadformat.sas +303 -0
- package/macros/mp_lockanytable.sas +243 -0
- package/macros/mp_lockfilecheck.sas +103 -0
- package/macros/mp_makedata.sas +107 -0
- package/macros/mp_md5.sas +58 -0
- package/macros/mp_perflog.sas +43 -0
- package/macros/mp_prevobs.sas +88 -0
- package/macros/mp_recursivejoin.sas +90 -0
- package/macros/mp_replace.sas +151 -0
- package/macros/mp_reseterror.sas +27 -0
- package/macros/mp_resetoption.sas +39 -0
- package/macros/mp_retainedkey.sas +247 -0
- package/macros/mp_runddl.sas +49 -0
- package/macros/mp_searchcols.sas +103 -0
- package/macros/mp_searchdata.sas +131 -0
- package/macros/mp_setkeyvalue.sas +55 -0
- package/macros/mp_sortinplace.sas +122 -0
- package/macros/mp_stackdiffs.sas +592 -0
- package/macros/mp_storediffs.sas +230 -0
- package/macros/mp_stprequests.sas +74 -0
- package/macros/mp_streamfile.sas +212 -0
- package/macros/mp_testjob.sas +92 -0
- package/macros/mp_testservice.sas +39 -0
- package/macros/mp_testwritespeedlibrary.sas +59 -0
- package/macros/mp_tree.sas +71 -0
- package/macros/mp_unzip.sas +90 -0
- package/macros/mp_updatevarlength.sas +93 -0
- package/macros/mp_validatecol.sas +97 -0
- package/macros/mp_wait4file.sas +35 -0
- package/macros/mp_webin.sas +59 -0
- package/macros/mp_zip.sas +85 -0
- package/package.json +5 -2
- package/scripts/copySASjsCore.ts +36 -0
- package/utils/index.d.ts +1 -2
- package/utils/index.js +2 -3
- package/utils/index.js.map +1 -1
- package/utils/utils.d.ts +1 -0
- package/utils/utils.js +7 -1
- package/utils/utils.js.map +1 -1
- package/utils/getNodeModulePath.d.ts +0 -2
- package/utils/getNodeModulePath.js +0 -83
- package/utils/getNodeModulePath.js.map +0 -1
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Fixes embedded cr / lf / crlf in CSV
|
|
4
|
+
@details CSVs will sometimes contain lf or crlf within quotes (eg when
|
|
5
|
+
saved by excel). When the termstr is ALSO lf or crlf that can be tricky
|
|
6
|
+
to process using SAS defaults.
|
|
7
|
+
This macro converts any csv to follow the convention of a windows excel file,
|
|
8
|
+
applying CRLF line endings and converting embedded cr and crlf to lf.
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
|
|
12
|
+
fileref mycsv "/path/your/csv";
|
|
13
|
+
%mp_cleancsv(in=mycsv,out=/path/new.csv)
|
|
14
|
+
|
|
15
|
+
@param in= (NOTPROVIDED) Provide path or fileref to input csv. If a period is
|
|
16
|
+
found, it is assumed to be a file.
|
|
17
|
+
@param out= (NOTPROVIDED) Output path or fileref to output csv. If a period
|
|
18
|
+
is found, it is assumed to be a file.
|
|
19
|
+
@param qchar= ('22'x) Quote char - hex code 22 is the double quote.
|
|
20
|
+
|
|
21
|
+
@version 9.2
|
|
22
|
+
@author Allan Bowe
|
|
23
|
+
@cond
|
|
24
|
+
**/
|
|
25
|
+
|
|
26
|
+
%macro mp_cleancsv(in=NOTPROVIDED,out=NOTPROVIDED,qchar='22'x);
|
|
27
|
+
%if "&in"="NOTPROVIDED" or "&out"="NOTPROVIDED" %then %do;
|
|
28
|
+
%put %str(ERR)OR: Please provide valid input (&in) & output (&out) locations;
|
|
29
|
+
%return;
|
|
30
|
+
%end;
|
|
31
|
+
|
|
32
|
+
/* presence of a period(.) indicates a physical location */
|
|
33
|
+
%if %index(&in,.) %then %let in="&in";
|
|
34
|
+
%if %index(&out,.) %then %let out="&out";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* convert all cr and crlf within quotes to lf
|
|
38
|
+
* convert all other cr or lf to crlf
|
|
39
|
+
*/
|
|
40
|
+
data _null_;
|
|
41
|
+
infile &in recfm=n ;
|
|
42
|
+
file &out recfm=n;
|
|
43
|
+
retain isq iscrlf 0 qchar &qchar;
|
|
44
|
+
input inchar $char1. ;
|
|
45
|
+
if inchar=qchar then isq = mod(isq+1,2);
|
|
46
|
+
if isq then do;
|
|
47
|
+
/* inside a quote change cr and crlf to lf */
|
|
48
|
+
if inchar='0D'x then do;
|
|
49
|
+
put '0A'x;
|
|
50
|
+
input inchar $char1.;
|
|
51
|
+
if inchar ne '0A'x then do;
|
|
52
|
+
put inchar $char1.;
|
|
53
|
+
if inchar=qchar then isq = mod(isq+1,2);
|
|
54
|
+
end;
|
|
55
|
+
end;
|
|
56
|
+
else put inchar $char1.;
|
|
57
|
+
end;
|
|
58
|
+
else do;
|
|
59
|
+
/* outside a quote, change cr and lf to crlf */
|
|
60
|
+
if inchar='0D'x then do;
|
|
61
|
+
crblank:
|
|
62
|
+
put '0D0A'x;
|
|
63
|
+
input inchar $char1.;
|
|
64
|
+
if inchar='0D'x then do;
|
|
65
|
+
/* multiple CR indicates CR formatted file with blank lines */
|
|
66
|
+
goto crblank;
|
|
67
|
+
end;
|
|
68
|
+
else if inchar ne '0A'x then do;
|
|
69
|
+
put inchar $char1.;
|
|
70
|
+
if inchar=qchar then isq = mod(isq+1,2);
|
|
71
|
+
end;
|
|
72
|
+
end;
|
|
73
|
+
else if inchar='0A'x then put '0D0A'x;
|
|
74
|
+
else put inchar $char1.;
|
|
75
|
+
end;
|
|
76
|
+
run;
|
|
77
|
+
%mend mp_cleancsv;
|
|
78
|
+
/** @endcond */
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file mp_cntlout.sas
|
|
3
|
+
@brief Creates a cntlout dataset in a consistent format
|
|
4
|
+
@details The dataset produced by proc format in the cntlout option will vary
|
|
5
|
+
according to its contents.
|
|
6
|
+
|
|
7
|
+
When dealing with formats from an ETL perspective (eg in [Data Controller for
|
|
8
|
+
SAS](https://datacontroller.io)), it is important that the output dataset
|
|
9
|
+
has a consistent model (and compariable values).
|
|
10
|
+
|
|
11
|
+
This macro makes use of mddl_sas_cntlout.sas to provide the consistent model,
|
|
12
|
+
and will left-align the start and end values when dealing with numeric ranges
|
|
13
|
+
to enable consistency when checking for differences.
|
|
14
|
+
|
|
15
|
+
usage:
|
|
16
|
+
|
|
17
|
+
%mp_cntlout(libcat=yourlib.cat,cntlout=work.formatexport)
|
|
18
|
+
|
|
19
|
+
@param [in] libcat The library.catalog reference
|
|
20
|
+
@param [in] fmtlist= (0) provide a space separated list of specific formats to
|
|
21
|
+
extract
|
|
22
|
+
@param [in] iftrue= (1=1) A condition under which the macro should be executed
|
|
23
|
+
@param [out] cntlout= (work.fmtextract) Libds reference for the output dataset
|
|
24
|
+
|
|
25
|
+
<h4> SAS Macros </h4>
|
|
26
|
+
@li mddl_sas_cntlout.sas
|
|
27
|
+
@li mf_getuniquename.sas
|
|
28
|
+
|
|
29
|
+
<h4> Related Macros </h4>
|
|
30
|
+
@li mf_getvarformat.sas
|
|
31
|
+
@li mp_getformats.sas
|
|
32
|
+
@li mp_loadformat.sas
|
|
33
|
+
@li mp_ds2fmtds.sas
|
|
34
|
+
|
|
35
|
+
@version 9.2
|
|
36
|
+
@author Allan Bowe
|
|
37
|
+
@cond
|
|
38
|
+
**/
|
|
39
|
+
|
|
40
|
+
%macro mp_cntlout(
|
|
41
|
+
iftrue=(1=1)
|
|
42
|
+
,libcat=
|
|
43
|
+
,cntlout=work.fmtextract
|
|
44
|
+
,fmtlist=0
|
|
45
|
+
)/*/STORE SOURCE*/;
|
|
46
|
+
%local ddlds cntlds i;
|
|
47
|
+
|
|
48
|
+
%if not(%eval(%unquote(&iftrue))) %then %return;
|
|
49
|
+
|
|
50
|
+
%let ddlds=%mf_getuniquename();
|
|
51
|
+
%let cntlds=%mf_getuniquename();
|
|
52
|
+
|
|
53
|
+
%mddl_sas_cntlout(libds=&ddlds)
|
|
54
|
+
|
|
55
|
+
%if %index(&libcat,-)>0 and %scan(&libcat,2,-)=FC %then %do;
|
|
56
|
+
%let libcat=%scan(&libcat,1,-);
|
|
57
|
+
%end;
|
|
58
|
+
|
|
59
|
+
proc format lib=&libcat cntlout=&cntlds;
|
|
60
|
+
%if "&fmtlist" ne "0" %then %do;
|
|
61
|
+
select
|
|
62
|
+
%do i=1 %to %sysfunc(countw(&fmtlist));
|
|
63
|
+
%scan(&fmtlist,&i,%str( ))
|
|
64
|
+
%end;
|
|
65
|
+
;
|
|
66
|
+
%end;
|
|
67
|
+
run;
|
|
68
|
+
|
|
69
|
+
data &cntlout;
|
|
70
|
+
if 0 then set &ddlds;
|
|
71
|
+
set &cntlds;
|
|
72
|
+
if type="N" then do;
|
|
73
|
+
start=cats(start);
|
|
74
|
+
end=cats(end);
|
|
75
|
+
end;
|
|
76
|
+
run;
|
|
77
|
+
proc sort;
|
|
78
|
+
by fmtname start;
|
|
79
|
+
run;
|
|
80
|
+
|
|
81
|
+
proc sql;
|
|
82
|
+
drop table &ddlds,&cntlds;
|
|
83
|
+
|
|
84
|
+
%mend mp_cntlout;
|
|
85
|
+
/** @endcond */
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief A macro to recursively copy a directory
|
|
4
|
+
@details Performs a recursive directory listing then works from top to bottom
|
|
5
|
+
copying files and creating subdirectories.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
|
|
9
|
+
%let rootdir=%sysfunc(pathname(work))/demo;
|
|
10
|
+
%let copydir=%sysfunc(pathname(work))/demo_copy;
|
|
11
|
+
%mf_mkdir(&rootdir)
|
|
12
|
+
%mf_mkdir(&rootdir/subdir)
|
|
13
|
+
%mf_mkdir(&rootdir/subdir/subsubdir)
|
|
14
|
+
data "&rootdir/subdir/example.sas7bdat";
|
|
15
|
+
run;
|
|
16
|
+
|
|
17
|
+
%mp_copyfolder(&rootdir,©dir)
|
|
18
|
+
|
|
19
|
+
@param [in] source Unquoted path to the folder to copy from.
|
|
20
|
+
@param [out] target Unquoted path to the folder to copy to.
|
|
21
|
+
@param [in] copymax=(MAX) Set to a positive integer to indicate the level of
|
|
22
|
+
subdirectory copy recursion - eg 3, to go `./3/levels/deep`. For unlimited
|
|
23
|
+
recursion, set to MAX.
|
|
24
|
+
|
|
25
|
+
<h4> SAS Macros </h4>
|
|
26
|
+
@li mf_getuniquename.sas
|
|
27
|
+
@li mf_isdir.sas
|
|
28
|
+
@li mf_mkdir.sas
|
|
29
|
+
@li mp_abort.sas
|
|
30
|
+
@li mp_dirlist.sas
|
|
31
|
+
|
|
32
|
+
<h4> Related Macros </h4>
|
|
33
|
+
@li mp_copyfolder.test.sas
|
|
34
|
+
|
|
35
|
+
**/
|
|
36
|
+
|
|
37
|
+
%macro mp_copyfolder(source,target,copymax=MAX);
|
|
38
|
+
|
|
39
|
+
%mp_abort(iftrue=(%mf_isdir(&source)=0)
|
|
40
|
+
,mac=&sysmacroname
|
|
41
|
+
,msg=%str(Source dir does not exist (&source))
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
%mf_mkdir(&target)
|
|
45
|
+
|
|
46
|
+
%mp_abort(iftrue=(%mf_isdir(&target)=0)
|
|
47
|
+
,mac=&sysmacroname
|
|
48
|
+
,msg=%str(Target dir could not be created (&target))
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
/* prep temp table */
|
|
52
|
+
%local tempds;
|
|
53
|
+
%let tempds=%mf_getuniquename();
|
|
54
|
+
|
|
55
|
+
/* recursive directory listing */
|
|
56
|
+
%mp_dirlist(path=&source,outds=work.&tempds,maxdepth=©max)
|
|
57
|
+
|
|
58
|
+
/* create folders and copy content */
|
|
59
|
+
data _null_;
|
|
60
|
+
length msg $200;
|
|
61
|
+
call missing(msg);
|
|
62
|
+
set work.&tempds;
|
|
63
|
+
if _n_ = 1 then dpos+sum(length(directory),2);
|
|
64
|
+
filepath2="&target/"!!substr(filepath,dpos);
|
|
65
|
+
if file_or_folder='folder' then call execute('%mf_mkdir('!!filepath2!!')');
|
|
66
|
+
else do;
|
|
67
|
+
length fref1 fref2 $8;
|
|
68
|
+
rc1=filename(fref1,filepath,'disk','recfm=n');
|
|
69
|
+
rc2=filename(fref2,filepath2,'disk','recfm=n');
|
|
70
|
+
if fcopy(fref1,fref2) ne 0 then do;
|
|
71
|
+
msg=sysmsg();
|
|
72
|
+
putlog "%str(ERR)OR: Unable to copy " filepath " to " filepath2;
|
|
73
|
+
putlog msg=;
|
|
74
|
+
end;
|
|
75
|
+
end;
|
|
76
|
+
rc=filename(fref1);
|
|
77
|
+
rc=filename(fref2);
|
|
78
|
+
run;
|
|
79
|
+
|
|
80
|
+
/* tidy up */
|
|
81
|
+
proc sql;
|
|
82
|
+
drop table work.&tempds;
|
|
83
|
+
|
|
84
|
+
%mend mp_copyfolder;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Create the permanent Core tables
|
|
4
|
+
@details Several macros in the [core](https://github.com/sasjs/core) library
|
|
5
|
+
make use of permanent tables. To avoid duplication in definitions, this
|
|
6
|
+
macro provides a central location for managing the corresponding DDL.
|
|
7
|
+
|
|
8
|
+
Note - this macro is likely to be deprecated in future in favour of a
|
|
9
|
+
dedicated "datamodel" folder (prefix mddl)
|
|
10
|
+
|
|
11
|
+
Any corresponding data would go in a seperate repo, to avoid this one
|
|
12
|
+
ballooning in size!
|
|
13
|
+
|
|
14
|
+
Example usage:
|
|
15
|
+
|
|
16
|
+
%mp_coretable(LOCKTABLE,libds=work.locktable)
|
|
17
|
+
|
|
18
|
+
@param [in] table_ref The type of table to create. Example values:
|
|
19
|
+
@li DIFFTABLE
|
|
20
|
+
@li FILTER_DETAIL
|
|
21
|
+
@li FILTER_SUMMARY
|
|
22
|
+
@li LOCKANYTABLE
|
|
23
|
+
@li MAXKEYTABLE
|
|
24
|
+
@param [in] libds= (0) The library.dataset reference used to create the table.
|
|
25
|
+
If not provided, then the DDL is simply printed to the log.
|
|
26
|
+
|
|
27
|
+
<h4> SAS Macros </h4>
|
|
28
|
+
@li mddl_dc_difftable.sas
|
|
29
|
+
@li mddl_dc_filterdetail.sas
|
|
30
|
+
@li mddl_dc_filtersummary.sas
|
|
31
|
+
@li mddl_dc_locktable.sas
|
|
32
|
+
@li mddl_dc_maxkeytable.sas
|
|
33
|
+
@li mf_getuniquename.sas
|
|
34
|
+
|
|
35
|
+
<h4> Related Macros </h4>
|
|
36
|
+
@li mp_filterstore.sas
|
|
37
|
+
@li mp_lockanytable.sas
|
|
38
|
+
@li mp_retainedkey.sas
|
|
39
|
+
@li mp_storediffs.sas
|
|
40
|
+
@li mp_stackdiffs.sas
|
|
41
|
+
|
|
42
|
+
@version 9.2
|
|
43
|
+
@author Allan Bowe
|
|
44
|
+
|
|
45
|
+
**/
|
|
46
|
+
|
|
47
|
+
%macro mp_coretable(table_ref,libds=0
|
|
48
|
+
)/*/STORE SOURCE*/;
|
|
49
|
+
%local outds ;
|
|
50
|
+
%let outds=%sysfunc(ifc(&libds=0,%mf_getuniquename(),&libds));
|
|
51
|
+
proc sql;
|
|
52
|
+
%if &table_ref=DIFFTABLE %then %do;
|
|
53
|
+
%mddl_dc_difftable(libds=&outds)
|
|
54
|
+
%end;
|
|
55
|
+
%else %if &table_ref=LOCKTABLE %then %do;
|
|
56
|
+
%mddl_dc_locktable(libds=&outds)
|
|
57
|
+
%end;
|
|
58
|
+
%else %if &table_ref=FILTER_SUMMARY %then %do;
|
|
59
|
+
%mddl_dc_filtersummary(libds=&outds)
|
|
60
|
+
%end;
|
|
61
|
+
%else %if &table_ref=FILTER_DETAIL %then %do;
|
|
62
|
+
%mddl_dc_filterdetail(libds=&outds)
|
|
63
|
+
%end;
|
|
64
|
+
%else %if &table_ref=MAXKEYTABLE %then %do;
|
|
65
|
+
%mddl_dc_maxkeytable(libds=&outds)
|
|
66
|
+
%end;
|
|
67
|
+
|
|
68
|
+
%if &libds=0 %then %do;
|
|
69
|
+
proc sql;
|
|
70
|
+
describe table &syslast;
|
|
71
|
+
drop table &syslast;
|
|
72
|
+
%end;
|
|
73
|
+
%mend mp_coretable;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file mp_createconstraints.sas
|
|
3
|
+
@brief Creates constraints
|
|
4
|
+
@details Takes the output from mp_getconstraints.sas as input
|
|
5
|
+
|
|
6
|
+
proc sql;
|
|
7
|
+
create table work.example(
|
|
8
|
+
TX_FROM float format=datetime19.,
|
|
9
|
+
DD_TYPE char(16),
|
|
10
|
+
DD_SOURCE char(2048),
|
|
11
|
+
DD_SHORTDESC char(256),
|
|
12
|
+
constraint pk primary key(tx_from, dd_type,dd_source),
|
|
13
|
+
constraint unq unique(tx_from, dd_type),
|
|
14
|
+
constraint nnn not null(DD_SHORTDESC)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
%mp_getconstraints(lib=work,ds=example,outds=work.constraints)
|
|
18
|
+
%mp_deleteconstraints(inds=work.constraints,outds=dropped,execute=YES)
|
|
19
|
+
%mp_createconstraints(inds=work.constraints,outds=created,execute=YES)
|
|
20
|
+
|
|
21
|
+
@param inds= (work.mp_getconstraints) The input table containing the
|
|
22
|
+
constraint info
|
|
23
|
+
@param outds= (work.mp_createconstraints) A table containing the create
|
|
24
|
+
statements (create_statement column)
|
|
25
|
+
@param execute= (NO) To actually create, use YES.
|
|
26
|
+
|
|
27
|
+
<h4> Related Files </h4>
|
|
28
|
+
@li mp_getconstraints.sas
|
|
29
|
+
|
|
30
|
+
@version 9.2
|
|
31
|
+
@author Allan Bowe
|
|
32
|
+
|
|
33
|
+
**/
|
|
34
|
+
|
|
35
|
+
%macro mp_createconstraints(inds=mp_getconstraints
|
|
36
|
+
,outds=work.mp_createconstraints
|
|
37
|
+
,execute=NO
|
|
38
|
+
)/*/STORE SOURCE*/;
|
|
39
|
+
|
|
40
|
+
proc sort data=&inds out=&outds;
|
|
41
|
+
by libref table_name constraint_name;
|
|
42
|
+
run;
|
|
43
|
+
|
|
44
|
+
data &outds;
|
|
45
|
+
set &outds;
|
|
46
|
+
by libref table_name constraint_name;
|
|
47
|
+
length create_statement $500;
|
|
48
|
+
if _n_=1 and "&execute"="YES" then call execute('proc sql;');
|
|
49
|
+
if first.constraint_name then do;
|
|
50
|
+
if constraint_type='PRIMARY' then type='PRIMARY KEY';
|
|
51
|
+
else type=constraint_type;
|
|
52
|
+
create_statement=catx(" ","alter table",libref,".",table_name
|
|
53
|
+
,"add constraint",constraint_name,type,"(");
|
|
54
|
+
if last.constraint_name then
|
|
55
|
+
create_statement=cats(create_statement,column_name,");");
|
|
56
|
+
else create_statement=cats(create_statement,column_name,",");
|
|
57
|
+
if "&execute"="YES" then call execute(create_statement);
|
|
58
|
+
end;
|
|
59
|
+
else if last.constraint_name then do;
|
|
60
|
+
create_statement=cats(column_name,");");
|
|
61
|
+
if "&execute"="YES" then call execute(create_statement);
|
|
62
|
+
end;
|
|
63
|
+
else do;
|
|
64
|
+
create_statement=cats(column_name,",");
|
|
65
|
+
if "&execute"="YES" then call execute(create_statement);
|
|
66
|
+
end;
|
|
67
|
+
output;
|
|
68
|
+
run;
|
|
69
|
+
|
|
70
|
+
%mend mp_createconstraints;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file mp_createwebservice.sas
|
|
3
|
+
@brief Create a web service in SAS 9, Viya or SASjs Server
|
|
4
|
+
@details This is actually a wrapper for mx_createwebservice.sas, remaining
|
|
5
|
+
for legacy purposes. For new apps, use mx_createwebservice.sas.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
<h4> SAS Macros </h4>
|
|
9
|
+
@li mx_createwebservice.sas
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
**/
|
|
13
|
+
|
|
14
|
+
%macro mp_createwebservice(path=HOME
|
|
15
|
+
,name=initService
|
|
16
|
+
,precode=
|
|
17
|
+
,code=ft15f001
|
|
18
|
+
,desc=This service was created by the mp_createwebservice macro
|
|
19
|
+
,replace=YES
|
|
20
|
+
,mdebug=0
|
|
21
|
+
)/*/STORE SOURCE*/;
|
|
22
|
+
|
|
23
|
+
%mx_createwebservice(path=&path
|
|
24
|
+
,name=&name
|
|
25
|
+
,precode=&precode
|
|
26
|
+
,code=&code
|
|
27
|
+
,desc=&desc
|
|
28
|
+
,replace=&replace
|
|
29
|
+
,mdebug=&mdebug
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
%mend mp_createwebservice;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file mp_csv2ds.sas
|
|
3
|
+
@brief Efficient import of arbitrary CSV using a dataset as template
|
|
4
|
+
@details Used to import relevant columns from a large CSV using
|
|
5
|
+
a dataset to provide the types and lengths. Assumes that a header
|
|
6
|
+
row is provided, and datarows start on line 2. Extra columns in
|
|
7
|
+
both the CSV and base dataset are ignored.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
|
|
11
|
+
filename mycsv temp;
|
|
12
|
+
data _null_;
|
|
13
|
+
file mycsv;
|
|
14
|
+
put 'name,age,nickname';
|
|
15
|
+
put 'John,48,Jonny';
|
|
16
|
+
put 'Jennifer,23,Jen';
|
|
17
|
+
run;
|
|
18
|
+
|
|
19
|
+
%mp_csv2ds(inref=mycsv,outds=myds,baseds=sashelp.class)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@param inref= fileref to the CSV
|
|
23
|
+
@param outds= output ds (lib.ds format)
|
|
24
|
+
@param view= Set to YES or NO to determine whether the output should be
|
|
25
|
+
a view or not. Default is NO (not a view).
|
|
26
|
+
@param baseds= Template dataset on which to create the input statement.
|
|
27
|
+
Is used to determine types, lengths, and any informats.
|
|
28
|
+
|
|
29
|
+
@version 9.2
|
|
30
|
+
@author Allan Bowe
|
|
31
|
+
|
|
32
|
+
<h4> SAS Macros </h4>
|
|
33
|
+
@li mp_abort.sas
|
|
34
|
+
@li mf_existds.sas
|
|
35
|
+
|
|
36
|
+
**/
|
|
37
|
+
|
|
38
|
+
%macro mp_csv2ds(inref=0,outds=0,baseds=0,view=NO);
|
|
39
|
+
|
|
40
|
+
%mp_abort(iftrue=( &inref=0 )
|
|
41
|
+
,mac=&sysmacroname
|
|
42
|
+
,msg=%str(the INREF variable must be provided)
|
|
43
|
+
)
|
|
44
|
+
%mp_abort(iftrue=( %superq(outds)=0 )
|
|
45
|
+
,mac=&sysmacroname
|
|
46
|
+
,msg=%str(the OUTDS variable must be provided)
|
|
47
|
+
)
|
|
48
|
+
%mp_abort(iftrue=( &baseds=0 )
|
|
49
|
+
,mac=&sysmacroname
|
|
50
|
+
,msg=%str(the BASEDS variable must be provided)
|
|
51
|
+
)
|
|
52
|
+
%mp_abort(iftrue=( %mf_existds(&baseds)=0 )
|
|
53
|
+
,mac=&sysmacroname
|
|
54
|
+
,msg=%str(the BASEDS dataset (&baseds) needs to be assigned, and to exist)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
/* count rows */
|
|
58
|
+
%local hasheader; %let hasheader=0;
|
|
59
|
+
data _null_;
|
|
60
|
+
if _N_ > 1 then do;
|
|
61
|
+
call symputx('hasheader',1,'l');
|
|
62
|
+
stop;
|
|
63
|
+
end;
|
|
64
|
+
infile &inref;
|
|
65
|
+
input;
|
|
66
|
+
run;
|
|
67
|
+
%mp_abort(iftrue=( &hasheader=0 )
|
|
68
|
+
,mac=&sysmacroname
|
|
69
|
+
,msg=%str(No header row in &inref)
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
/* get the variables in the CSV */
|
|
73
|
+
data _data_;
|
|
74
|
+
infile &inref;
|
|
75
|
+
input;
|
|
76
|
+
length name $32;
|
|
77
|
+
do i=1 to countc(_infile_,',')+1;
|
|
78
|
+
name=upcase(scan(_infile_,i,','));
|
|
79
|
+
output;
|
|
80
|
+
end;
|
|
81
|
+
stop;
|
|
82
|
+
run;
|
|
83
|
+
%local csv_vars;%let csv_vars=&syslast;
|
|
84
|
+
|
|
85
|
+
/* get the variables in the dataset */
|
|
86
|
+
proc contents noprint data=&baseds
|
|
87
|
+
out=_data_ (keep=name type length format: informat);
|
|
88
|
+
run;
|
|
89
|
+
%local base_vars; %let base_vars=&syslast;
|
|
90
|
+
|
|
91
|
+
proc sql undo_policy=none;
|
|
92
|
+
create table &csv_vars as
|
|
93
|
+
select a.*
|
|
94
|
+
,b.type
|
|
95
|
+
,b.length
|
|
96
|
+
,b.format
|
|
97
|
+
,b.formatd
|
|
98
|
+
,b.formatl
|
|
99
|
+
,b.informat
|
|
100
|
+
from &csv_vars a
|
|
101
|
+
left join &base_vars b
|
|
102
|
+
on a.name=upcase(b.name)
|
|
103
|
+
order by i;
|
|
104
|
+
|
|
105
|
+
/* prepare the input statement */
|
|
106
|
+
%local instat dropvars;
|
|
107
|
+
data _null_;
|
|
108
|
+
set &syslast end=last;
|
|
109
|
+
length in dropvars $32767;
|
|
110
|
+
retain in dropvars;
|
|
111
|
+
if missing(type) then do;
|
|
112
|
+
informat='$1.';
|
|
113
|
+
dropvars=catx(' ',dropvars,name);
|
|
114
|
+
end;
|
|
115
|
+
else if missing(informat) then do;
|
|
116
|
+
if type=1 then informat='best.';
|
|
117
|
+
else informat=cats('$',length,'.');
|
|
118
|
+
end;
|
|
119
|
+
else informat=cats(informat,'.');
|
|
120
|
+
in=catx(' ',in,name,':',informat);
|
|
121
|
+
if last then do;
|
|
122
|
+
call symputx('instat',in,'l');
|
|
123
|
+
call symputx('dropvars',dropvars,'l');
|
|
124
|
+
end;
|
|
125
|
+
run;
|
|
126
|
+
|
|
127
|
+
/* import the CSV */
|
|
128
|
+
data &outds
|
|
129
|
+
%if %upcase(&view)=YES %then %do;
|
|
130
|
+
/view=&outds
|
|
131
|
+
%end;
|
|
132
|
+
;
|
|
133
|
+
infile &inref dsd firstobs=2;
|
|
134
|
+
input &instat;
|
|
135
|
+
%if %length(&dropvars)>0 %then %do;
|
|
136
|
+
drop &dropvars;
|
|
137
|
+
%end;
|
|
138
|
+
run;
|
|
139
|
+
|
|
140
|
+
%mend mp_csv2ds;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file mp_deleteconstraints.sas
|
|
3
|
+
@brief Delete constraionts
|
|
4
|
+
@details Takes the output from mp_getconstraints.sas as input
|
|
5
|
+
|
|
6
|
+
proc sql;
|
|
7
|
+
create table work.example(
|
|
8
|
+
TX_FROM float format=datetime19.,
|
|
9
|
+
DD_TYPE char(16),
|
|
10
|
+
DD_SOURCE char(2048),
|
|
11
|
+
DD_SHORTDESC char(256),
|
|
12
|
+
constraint pk primary key(tx_from, dd_type,dd_source),
|
|
13
|
+
constraint unq unique(tx_from, dd_type),
|
|
14
|
+
constraint nnn not null(DD_SHORTDESC)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
%mp_getconstraints(lib=work,ds=example,outds=work.constraints)
|
|
18
|
+
%mp_deleteconstraints(inds=work.constraints,outds=dropped,execute=YES)
|
|
19
|
+
|
|
20
|
+
@param inds= The input table containing the constraint info
|
|
21
|
+
@param outds= a table containing the drop statements (drop_statement column)
|
|
22
|
+
@param execute= `YES|NO` - default is NO. To actually drop, use YES.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@version 9.2
|
|
26
|
+
@author Allan Bowe
|
|
27
|
+
|
|
28
|
+
**/
|
|
29
|
+
|
|
30
|
+
%macro mp_deleteconstraints(inds=mp_getconstraints
|
|
31
|
+
,outds=mp_deleteconstraints
|
|
32
|
+
,execute=NO
|
|
33
|
+
)/*/STORE SOURCE*/;
|
|
34
|
+
|
|
35
|
+
proc sort data=&inds out=&outds;
|
|
36
|
+
by libref table_name constraint_name;
|
|
37
|
+
run;
|
|
38
|
+
|
|
39
|
+
data &outds;
|
|
40
|
+
set &outds;
|
|
41
|
+
by libref table_name constraint_name;
|
|
42
|
+
length drop_statement $500;
|
|
43
|
+
if _n_=1 and "&execute"="YES" then call execute('proc sql;');
|
|
44
|
+
if first.constraint_name then do;
|
|
45
|
+
drop_statement=catx(" ","alter table",libref,".",table_name
|
|
46
|
+
,"drop constraint",constraint_name,";");
|
|
47
|
+
output;
|
|
48
|
+
if "&execute"="YES" then call execute(drop_statement);
|
|
49
|
+
end;
|
|
50
|
+
run;
|
|
51
|
+
|
|
52
|
+
%mend mp_deleteconstraints;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief A macro to delete a directory
|
|
4
|
+
@details Will delete all folder content (including subfolder content) and
|
|
5
|
+
finally, the folder itself.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
|
|
9
|
+
%let rootdir=%sysfunc(pathname(work))/demo;
|
|
10
|
+
%mf_mkdir(&rootdir)
|
|
11
|
+
%mf_mkdir(&rootdir/subdir)
|
|
12
|
+
%mf_mkdir(&rootdir/subdir/subsubdir)
|
|
13
|
+
data "&rootdir/subdir/example.sas7bdat";
|
|
14
|
+
run;
|
|
15
|
+
|
|
16
|
+
%mp_deletefolder(&rootdir)
|
|
17
|
+
|
|
18
|
+
@param path Unquoted path to the folder to delete.
|
|
19
|
+
|
|
20
|
+
<h4> SAS Macros </h4>
|
|
21
|
+
@li mf_getuniquename.sas
|
|
22
|
+
@li mf_isdir.sas
|
|
23
|
+
@li mp_dirlist.sas
|
|
24
|
+
|
|
25
|
+
<h4> Related Macros </h4>
|
|
26
|
+
@li mp_deletefolder.test.sas
|
|
27
|
+
|
|
28
|
+
**/
|
|
29
|
+
|
|
30
|
+
%macro mp_deletefolder(folder);
|
|
31
|
+
/* proceed if valid directory */
|
|
32
|
+
%if %mf_isdir(&folder)=1 %then %do;
|
|
33
|
+
|
|
34
|
+
/* prep temp table */
|
|
35
|
+
%local tempds;
|
|
36
|
+
%let tempds=%mf_getuniquename();
|
|
37
|
+
|
|
38
|
+
/* recursive directory listing */
|
|
39
|
+
%mp_dirlist(path=&folder,outds=work.&tempds, maxdepth=MAX)
|
|
40
|
+
|
|
41
|
+
/* sort descending level so can delete folder contents before folders */
|
|
42
|
+
proc sort data=work.&tempds;
|
|
43
|
+
by descending level;
|
|
44
|
+
run;
|
|
45
|
+
|
|
46
|
+
/* ensure top level folder is removed at the end */
|
|
47
|
+
proc sql;
|
|
48
|
+
insert into work.&tempds set filepath="&folder";
|
|
49
|
+
|
|
50
|
+
/* delete everything */
|
|
51
|
+
data _null_;
|
|
52
|
+
set work.&tempds end=last;
|
|
53
|
+
length fref $8;
|
|
54
|
+
fref='';
|
|
55
|
+
rc=filename(fref,filepath);
|
|
56
|
+
rc=fdelete(fref);
|
|
57
|
+
if rc then do;
|
|
58
|
+
msg=sysmsg();
|
|
59
|
+
put "&sysmacroname:" / rc= / msg= / filepath=;
|
|
60
|
+
end;
|
|
61
|
+
rc=filename(fref);
|
|
62
|
+
run;
|
|
63
|
+
|
|
64
|
+
/* tidy up */
|
|
65
|
+
proc sql;
|
|
66
|
+
drop table work.&tempds;
|
|
67
|
+
|
|
68
|
+
%end;
|
|
69
|
+
%else %put &sysmacroname: &folder: is not a valid / accessible folder. ;
|
|
70
|
+
%mend mp_deletefolder;
|