@sasjs/utils 2.49.0 → 2.49.1
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 +263 -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_gsubfile.sas +58 -0
- package/macros/mp_guesspk.sas +332 -0
- package/macros/mp_hashdataset.sas +91 -0
- package/macros/mp_hashdirectory.sas +162 -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 +4 -1
- 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
package/fs/internal/helper.js
CHANGED
|
@@ -52,8 +52,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
52
52
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
53
53
|
exports.getCompiledMacrosCode = exports.getInitialCode = exports.chunkFileContent = exports.generateCodeForFileCreation = void 0;
|
|
54
54
|
var path_1 = __importDefault(require("path"));
|
|
55
|
-
var
|
|
56
|
-
var chunk_1 = require("../../utils/chunk");
|
|
55
|
+
var utils_1 = require("../../utils");
|
|
57
56
|
var file_1 = require("../../file");
|
|
58
57
|
var generateCodeForFileCreation = function (filePath, pathRelativeTo) { return __awaiter(void 0, void 0, void 0, function () {
|
|
59
58
|
var base64EncodedFileContent, chunkedFileContent;
|
|
@@ -69,7 +68,7 @@ var generateCodeForFileCreation = function (filePath, pathRelativeTo) { return _
|
|
|
69
68
|
}); };
|
|
70
69
|
exports.generateCodeForFileCreation = generateCodeForFileCreation;
|
|
71
70
|
var chunkFileContent = function (fileContent) {
|
|
72
|
-
var chunkedLines = (0,
|
|
71
|
+
var chunkedLines = (0, utils_1.chunk)(fileContent);
|
|
73
72
|
if (chunkedLines.length === 1) {
|
|
74
73
|
return " put '".concat(chunkedLines[0].split("'").join("''"), "';\n");
|
|
75
74
|
}
|
|
@@ -84,45 +83,41 @@ exports.chunkFileContent = chunkFileContent;
|
|
|
84
83
|
var getInitialCode = function () { return "%global fsTarget;\n%let compiled_fsTarget=%sysfunc(pathname(work));\n%let fsTarget=%sysfunc(coalescec(&fsTarget,&compiled_fsTarget));\noptions nobomfile;\n\n%mf_mkdir(&fsTarget)\n"; };
|
|
85
84
|
exports.getInitialCode = getInitialCode;
|
|
86
85
|
var getCompiledMacrosCode = function (macros) { return __awaiter(void 0, void 0, void 0, function () {
|
|
87
|
-
var
|
|
86
|
+
var compiledCode, macros_1, macros_1_1, macro, macroPath, macroContent, e_1_1;
|
|
88
87
|
var e_1, _a;
|
|
89
88
|
return __generator(this, function (_b) {
|
|
90
89
|
switch (_b.label) {
|
|
91
|
-
case 0:
|
|
92
|
-
case 1:
|
|
93
|
-
sasjsCorePath = _b.sent();
|
|
94
|
-
if (!sasjsCorePath)
|
|
95
|
-
throw new Error('@sasjs/core could not be found');
|
|
90
|
+
case 0:
|
|
96
91
|
compiledCode = '';
|
|
92
|
+
_b.label = 1;
|
|
93
|
+
case 1:
|
|
94
|
+
_b.trys.push([1, 6, 7, 8]);
|
|
95
|
+
macros_1 = __values(macros), macros_1_1 = macros_1.next();
|
|
97
96
|
_b.label = 2;
|
|
98
97
|
case 2:
|
|
99
|
-
|
|
100
|
-
macros_1 = __values(macros), macros_1_1 = macros_1.next();
|
|
101
|
-
_b.label = 3;
|
|
102
|
-
case 3:
|
|
103
|
-
if (!!macros_1_1.done) return [3 /*break*/, 6];
|
|
98
|
+
if (!!macros_1_1.done) return [3 /*break*/, 5];
|
|
104
99
|
macro = macros_1_1.value;
|
|
105
|
-
macroPath = path_1.default.join(
|
|
100
|
+
macroPath = path_1.default.join((0, utils_1.getMacrosPath)(), macro);
|
|
106
101
|
return [4 /*yield*/, (0, file_1.readFile)(macroPath)];
|
|
107
|
-
case
|
|
102
|
+
case 3:
|
|
108
103
|
macroContent = _b.sent();
|
|
109
104
|
compiledCode += macroContent + '\n';
|
|
110
|
-
_b.label =
|
|
111
|
-
case
|
|
105
|
+
_b.label = 4;
|
|
106
|
+
case 4:
|
|
112
107
|
macros_1_1 = macros_1.next();
|
|
113
|
-
return [3 /*break*/,
|
|
114
|
-
case
|
|
115
|
-
case
|
|
108
|
+
return [3 /*break*/, 2];
|
|
109
|
+
case 5: return [3 /*break*/, 8];
|
|
110
|
+
case 6:
|
|
116
111
|
e_1_1 = _b.sent();
|
|
117
112
|
e_1 = { error: e_1_1 };
|
|
118
|
-
return [3 /*break*/,
|
|
119
|
-
case
|
|
113
|
+
return [3 /*break*/, 8];
|
|
114
|
+
case 7:
|
|
120
115
|
try {
|
|
121
116
|
if (macros_1_1 && !macros_1_1.done && (_a = macros_1.return)) _a.call(macros_1);
|
|
122
117
|
}
|
|
123
118
|
finally { if (e_1) throw e_1.error; }
|
|
124
119
|
return [7 /*endfinally*/];
|
|
125
|
-
case
|
|
120
|
+
case 8: return [2 /*return*/, compiledCode];
|
|
126
121
|
}
|
|
127
122
|
});
|
|
128
123
|
}); };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../../../src/fs/internal/helper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8CAAuB;AACvB,
|
|
1
|
+
{"version":3,"file":"helper.js","sourceRoot":"","sources":["../../../src/fs/internal/helper.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,8CAAuB;AACvB,qCAAkD;AAClD,mCAAuD;AAEhD,IAAM,2BAA2B,GAAG,UACzC,QAAgB,EAChB,cAAsB;;;;oBAEW,qBAAM,IAAA,uBAAgB,EAAC,QAAQ,CAAC,EAAA;;gBAA3D,wBAAwB,GAAG,SAAgC;gBAC3D,kBAAkB,GAAG,IAAA,wBAAgB,EAAC,wBAAwB,CAAC,CAAA;gBACrE,sBAAO,4EAIP,kBAAkB,kDAGQ,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,4dAuB/D,EAAA;;;KACA,CAAA;AArCY,QAAA,2BAA2B,+BAqCvC;AAEM,IAAM,gBAAgB,GAAG,UAAC,WAAmB;IAClD,IAAM,YAAY,GAAG,IAAA,aAAK,EAAC,WAAW,CAAC,CAAA;IAEvC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE;QAC7B,OAAO,gBAAS,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAM,CAAA;KAC5D;IAED,IAAI,aAAa,GAAG,EAAE,CAAA;IAEtB,YAAY,CAAC,OAAO,CAAC,UAAC,WAAW,EAAE,KAAK;QACtC,IAAM,IAAI,GAAG,gBAAS,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,cACrD,KAAK,KAAK,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAClD,CAAA;QAEF,aAAa,IAAI,IAAI,CAAA;IACvB,CAAC,CAAC,CAAA;IAEF,OAAO,aAAa,CAAA;AACtB,CAAC,CAAA;AAlBY,QAAA,gBAAgB,oBAkB5B;AAEM,IAAM,cAAc,GAAG,cAAM,OAAA,qLAMnC,EANmC,CAMnC,CAAA;AANY,QAAA,cAAc,kBAM1B;AAEM,IAAM,qBAAqB,GAAG,UAAO,MAAgB;;;;;;gBACtD,YAAY,GAAG,EAAE,CAAA;;;;gBAED,WAAA,SAAA,MAAM,CAAA;;;;gBAAf,KAAK;gBACR,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,IAAA,qBAAa,GAAE,EAAE,KAAK,CAAC,CAAA;gBAC9B,qBAAM,IAAA,eAAQ,EAAC,SAAS,CAAC,EAAA;;gBAAxC,YAAY,GAAG,SAAyB;gBAE9C,YAAY,IAAI,YAAY,GAAG,IAAI,CAAA;;;;;;;;;;;;;;;;oBAGrC,sBAAO,YAAY,EAAA;;;KACpB,CAAA;AAXY,QAAA,qBAAqB,yBAWjC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Abort, ungracefully
|
|
4
|
+
@details Will abort with a straightforward %abort if the condition is true.
|
|
5
|
+
|
|
6
|
+
<h4> Related Macros </h4>
|
|
7
|
+
@li mp_abort.sas
|
|
8
|
+
|
|
9
|
+
@version 9.2
|
|
10
|
+
@author Allan Bowe
|
|
11
|
+
@cond
|
|
12
|
+
**/
|
|
13
|
+
|
|
14
|
+
%macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1)
|
|
15
|
+
)/*/STORE SOURCE*/;
|
|
16
|
+
|
|
17
|
+
%if not(%eval(%unquote(&iftrue))) %then %return;
|
|
18
|
+
|
|
19
|
+
%put NOTE: /// mf_abort macro executing //;
|
|
20
|
+
%if %length(&mac)>0 %then %put NOTE- called by &mac;
|
|
21
|
+
%put NOTE - &msg;
|
|
22
|
+
|
|
23
|
+
%abort;
|
|
24
|
+
|
|
25
|
+
%mend mf_abort;
|
|
26
|
+
|
|
27
|
+
/** @endcond */
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief de-duplicates a macro string
|
|
4
|
+
@details Removes all duplicates from a string of words. A delimeter can be
|
|
5
|
+
chosen. Is inspired heavily by this excellent [macro](
|
|
6
|
+
https://github.com/scottbass/SAS/blob/master/Macro/dedup_mstring.sas) from
|
|
7
|
+
[Scott Base](https://www.linkedin.com/in/scottbass). Case sensitive.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
|
|
11
|
+
%let str=One two one two and through and through;
|
|
12
|
+
%put %mf_dedup(&str);
|
|
13
|
+
%put %mf_dedup(&str,outdlm=%str(,));
|
|
14
|
+
|
|
15
|
+
Which returns:
|
|
16
|
+
|
|
17
|
+
> One two one and through
|
|
18
|
+
> One,two,one,and,through
|
|
19
|
+
|
|
20
|
+
@param [in] str String to be deduplicated
|
|
21
|
+
@param [in] indlm= ( ) Delimeter of the input string
|
|
22
|
+
@param [out] outdlm= ( ) Delimiter of the output string
|
|
23
|
+
|
|
24
|
+
<h4> Related Macros </h4>
|
|
25
|
+
@li mf_trimstr.sas
|
|
26
|
+
|
|
27
|
+
@version 9.2
|
|
28
|
+
@author Allan Bowe
|
|
29
|
+
**/
|
|
30
|
+
|
|
31
|
+
%macro mf_dedup(str
|
|
32
|
+
,indlm=%str( )
|
|
33
|
+
,outdlm=%str( )
|
|
34
|
+
)/*/STORE SOURCE*/;
|
|
35
|
+
|
|
36
|
+
%local num word i pos out;
|
|
37
|
+
|
|
38
|
+
%* loop over each token, searching the target for that token ;
|
|
39
|
+
%let num=%sysfunc(countc(%superq(str),%str(&indlm)));
|
|
40
|
+
%do i=1 %to %eval(&num+1);
|
|
41
|
+
%let word=%scan(%superq(str),&i,%str(&indlm));
|
|
42
|
+
%let pos=%sysfunc(indexw(&out,&word,%str(&outdlm)));
|
|
43
|
+
%if (&pos eq 0) %then %do;
|
|
44
|
+
%if (&i gt 1) %then %let out=&out%str(&outdlm);
|
|
45
|
+
%let out=&out&word;
|
|
46
|
+
%end;
|
|
47
|
+
%end;
|
|
48
|
+
|
|
49
|
+
%unquote(&out)
|
|
50
|
+
|
|
51
|
+
%mend mf_dedup;
|
|
52
|
+
|
|
53
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Deletes a physical file, if it exists
|
|
4
|
+
@details Usage:
|
|
5
|
+
|
|
6
|
+
%mf_writefile(&sasjswork/myfile.txt,l1=some content)
|
|
7
|
+
|
|
8
|
+
%mf_deletefile(&sasjswork/myfile.txt)
|
|
9
|
+
|
|
10
|
+
%mf_deletefile(&sasjswork/myfile.txt)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@param filepath Full path to the target file
|
|
14
|
+
|
|
15
|
+
@returns The return code from the fdelete() invocation
|
|
16
|
+
|
|
17
|
+
<h4> Related Macros </h4>
|
|
18
|
+
@li mf_deletefile.test.sas
|
|
19
|
+
@li mf_writefile.sas
|
|
20
|
+
|
|
21
|
+
@version 9.2
|
|
22
|
+
@author Allan Bowe
|
|
23
|
+
**/
|
|
24
|
+
|
|
25
|
+
%macro mf_deletefile(file
|
|
26
|
+
)/*/STORE SOURCE*/;
|
|
27
|
+
%local rc fref;
|
|
28
|
+
%let rc= %sysfunc(filename(fref,&file));
|
|
29
|
+
%if %sysfunc(fdelete(&fref)) ne 0 %then %put %sysfunc(sysmsg());
|
|
30
|
+
%let rc= %sysfunc(filename(fref));
|
|
31
|
+
%mend mf_deletefile;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file mf_existds.sas
|
|
3
|
+
@brief Checks whether a dataset OR a view exists.
|
|
4
|
+
@details Can be used in open code, eg as follows:
|
|
5
|
+
|
|
6
|
+
%if %mf_existds(libds=work.someview) %then %put yes it does!;
|
|
7
|
+
|
|
8
|
+
NOTE - some databases have case sensitive tables, for instance POSTGRES
|
|
9
|
+
with the preserve_tab_names=yes libname setting. This may impact
|
|
10
|
+
expected results (depending on whether you 'expect' the result to be
|
|
11
|
+
case insensitive in this context!)
|
|
12
|
+
|
|
13
|
+
@param libds library.dataset
|
|
14
|
+
@return output returns 1 or 0
|
|
15
|
+
|
|
16
|
+
<h4> Related Macros </h4>
|
|
17
|
+
@li mf_existds.test.sas
|
|
18
|
+
|
|
19
|
+
@warning Untested on tables registered in metadata but not physically present
|
|
20
|
+
@version 9.2
|
|
21
|
+
@author Allan Bowe
|
|
22
|
+
**/
|
|
23
|
+
|
|
24
|
+
%macro mf_existds(libds
|
|
25
|
+
)/*/STORE SOURCE*/;
|
|
26
|
+
|
|
27
|
+
%if %sysfunc(exist(&libds)) ne 1 & %sysfunc(exist(&libds,VIEW)) ne 1 %then 0;
|
|
28
|
+
%else 1;
|
|
29
|
+
|
|
30
|
+
%mend mf_existds;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Checks whether a feature exists
|
|
4
|
+
@details Check to see if a feature is supported in your environment.
|
|
5
|
+
Run without arguments to see a list of detectable features.
|
|
6
|
+
Note - this list is based on known versions of SAS rather than
|
|
7
|
+
actual feature detection, as that is tricky / impossible to do
|
|
8
|
+
without generating errs in most cases.
|
|
9
|
+
|
|
10
|
+
%put %mf_existfeature(PROCLUA);
|
|
11
|
+
|
|
12
|
+
@param [in] feature The feature to detect.
|
|
13
|
+
|
|
14
|
+
@return output returns 1 or 0 (or -1 if not found)
|
|
15
|
+
|
|
16
|
+
<h4> SAS Macros </h4>
|
|
17
|
+
@li mf_getplatform.sas
|
|
18
|
+
|
|
19
|
+
@version 8
|
|
20
|
+
@author Allan Bowe
|
|
21
|
+
**/
|
|
22
|
+
/** @cond */
|
|
23
|
+
%macro mf_existfeature(feature
|
|
24
|
+
)/*/STORE SOURCE*/;
|
|
25
|
+
%let feature=%upcase(&feature);
|
|
26
|
+
%local platform;
|
|
27
|
+
%let platform=%mf_getplatform();
|
|
28
|
+
|
|
29
|
+
%if &feature= %then %do;
|
|
30
|
+
%put No feature was requested for detection;
|
|
31
|
+
%end;
|
|
32
|
+
%else %if &feature=COLCONSTRAINTS %then %do;
|
|
33
|
+
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 0;
|
|
34
|
+
%else 1;
|
|
35
|
+
%end;
|
|
36
|
+
%else %if &feature=PROCLUA %then %do;
|
|
37
|
+
/* https://blogs.sas.com/content/sasdummy/2015/08/03/using-lua-within-your-sas-programs */
|
|
38
|
+
%if &platform=SASVIYA %then 1;
|
|
39
|
+
%else %if "&sysver"="9.2" or "&sysver"="9.3" %then 0;
|
|
40
|
+
%else %if "&SYSVLONG" < "9.04.01M3" %then 0;
|
|
41
|
+
%else 1;
|
|
42
|
+
%end;
|
|
43
|
+
%else %if &feature=DBMS_MEMTYPE %then %do;
|
|
44
|
+
/* does dbms_memtype exist in dictionary.tables? */
|
|
45
|
+
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 0;
|
|
46
|
+
%else 1;
|
|
47
|
+
%end;
|
|
48
|
+
%else %if &feature=EXPORTXLS %then %do;
|
|
49
|
+
/* is it possible to PROC EXPORT an excel file? */
|
|
50
|
+
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 1;
|
|
51
|
+
%else %if %sysfunc(sysprod(SAS/ACCESS Interface to PC Files)) = 1 %then 1;
|
|
52
|
+
%else 0;
|
|
53
|
+
%end;
|
|
54
|
+
%else %do;
|
|
55
|
+
-1
|
|
56
|
+
%put &sysmacroname: &feature not found;
|
|
57
|
+
%end;
|
|
58
|
+
%mend mf_existfeature;
|
|
59
|
+
/** @endcond */
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Checks whether a fileref exists
|
|
4
|
+
@details You can probably do without this macro as it is just a one liner.
|
|
5
|
+
Mainly it is here as a convenient way to remember the syntax!
|
|
6
|
+
|
|
7
|
+
@param fref the fileref to detect
|
|
8
|
+
|
|
9
|
+
@return output Returns 1 if found and 0 if not found. Note - it is possible
|
|
10
|
+
that the fileref is found, but the file does not (yet) exist. If you need
|
|
11
|
+
to test for this, you may as well use the fileref function directly.
|
|
12
|
+
|
|
13
|
+
@version 8
|
|
14
|
+
@author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
|
|
15
|
+
**/
|
|
16
|
+
|
|
17
|
+
%macro mf_existfileref(fref
|
|
18
|
+
)/*/STORE SOURCE*/;
|
|
19
|
+
|
|
20
|
+
%local rc;
|
|
21
|
+
%let rc=%sysfunc(fileref(&fref));
|
|
22
|
+
%if &rc=0 %then %do;
|
|
23
|
+
1
|
|
24
|
+
%end;
|
|
25
|
+
%else %if &rc<0 %then %do;
|
|
26
|
+
%put &sysmacroname: Fileref &fref exists but the underlying file does not;
|
|
27
|
+
1
|
|
28
|
+
%end;
|
|
29
|
+
%else %do;
|
|
30
|
+
0
|
|
31
|
+
%end;
|
|
32
|
+
|
|
33
|
+
%mend mf_existfileref;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Checks if a function exists
|
|
4
|
+
@details Returns 1 if the function exists, else 0. Note that this function
|
|
5
|
+
can be slow as it needs to open the sashelp.vfuncs table.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
|
|
9
|
+
%put %mf_existfunction(CAT);
|
|
10
|
+
%put %mf_existfunction(DOG);
|
|
11
|
+
|
|
12
|
+
Full credit to [Bart](https://sasensei.com/user/305) for the vfunc pointer
|
|
13
|
+
and the tidy approach for pure macro data set filtering.
|
|
14
|
+
Check out his [SAS Packages](https://github.com/yabwon/SAS_PACKAGES)
|
|
15
|
+
framework! Where you can find the same [function](
|
|
16
|
+
https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md#functionexists-macro
|
|
17
|
+
).
|
|
18
|
+
|
|
19
|
+
@param [in] name (positional) - function name
|
|
20
|
+
|
|
21
|
+
@author Allan Bowe
|
|
22
|
+
**/
|
|
23
|
+
/** @cond */
|
|
24
|
+
%macro mf_existfunction(name
|
|
25
|
+
)/*/STORE SOURCE*/;
|
|
26
|
+
|
|
27
|
+
%local dsid rc exist;
|
|
28
|
+
%let dsid=%sysfunc(open(sashelp.vfunc(where=(fncname="%upcase(&name)"))));
|
|
29
|
+
%let exist=1;
|
|
30
|
+
%let exist=%sysfunc(fetch(&dsid, NOSET));
|
|
31
|
+
%let rc=%sysfunc(close(&dsid));
|
|
32
|
+
|
|
33
|
+
%sysevalf(0 = &exist)
|
|
34
|
+
|
|
35
|
+
%mend mf_existfunction;
|
|
36
|
+
|
|
37
|
+
/** @endcond */
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Checks if a variable exists in a data set.
|
|
4
|
+
@details Returns 0 if the variable does NOT exist, and the position of the var
|
|
5
|
+
if it does.
|
|
6
|
+
Usage:
|
|
7
|
+
|
|
8
|
+
%put %mf_existvar(work.someds, somevar)
|
|
9
|
+
|
|
10
|
+
@param [in] libds 2 part dataset or view reference
|
|
11
|
+
@param [in] var variable name
|
|
12
|
+
|
|
13
|
+
<h4> Related Macros </h4>
|
|
14
|
+
@li mf_existvar.test.sas
|
|
15
|
+
|
|
16
|
+
@version 9.2
|
|
17
|
+
@author Allan Bowe
|
|
18
|
+
**/
|
|
19
|
+
/** @cond */
|
|
20
|
+
|
|
21
|
+
%macro mf_existvar(libds /* 2 part dataset name */
|
|
22
|
+
, var /* variable name */
|
|
23
|
+
)/*/STORE SOURCE*/;
|
|
24
|
+
|
|
25
|
+
%local dsid rc;
|
|
26
|
+
%let dsid=%sysfunc(open(&libds,is));
|
|
27
|
+
|
|
28
|
+
%if &dsid=0 or %length(&var)=0 %then %do;
|
|
29
|
+
%put %sysfunc(sysmsg());
|
|
30
|
+
0
|
|
31
|
+
%end;
|
|
32
|
+
%else %do;
|
|
33
|
+
%sysfunc(varnum(&dsid,&var))
|
|
34
|
+
%let rc=%sysfunc(close(&dsid));
|
|
35
|
+
%end;
|
|
36
|
+
|
|
37
|
+
%mend mf_existvar;
|
|
38
|
+
|
|
39
|
+
/** @endcond */
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Checks if a set of variables ALL exist in a data set.
|
|
4
|
+
@details Returns 0 if ANY of the variables do not exist, or 1 if they ALL do.
|
|
5
|
+
Usage:
|
|
6
|
+
|
|
7
|
+
%put %mf_existVarList(sashelp.class, age sex name dummyvar);
|
|
8
|
+
|
|
9
|
+
@param libds 2 part dataset or view reference
|
|
10
|
+
@param varlist space separated variable names
|
|
11
|
+
|
|
12
|
+
@version 9.2
|
|
13
|
+
@author Allan Bowe
|
|
14
|
+
@cond
|
|
15
|
+
**/
|
|
16
|
+
|
|
17
|
+
%macro mf_existvarlist(libds, varlist
|
|
18
|
+
)/*/STORE SOURCE*/;
|
|
19
|
+
|
|
20
|
+
%if %str(&libds)=%str() or %str(&varlist)=%str() %then %do;
|
|
21
|
+
%mf_abort(msg=No value provided to libds(&libds) or varlist (&varlist)!
|
|
22
|
+
,mac=mf_existvarlist.sas)
|
|
23
|
+
%end;
|
|
24
|
+
|
|
25
|
+
%local dsid rc i var found;
|
|
26
|
+
%let dsid=%sysfunc(open(&libds,is));
|
|
27
|
+
|
|
28
|
+
%if &dsid=0 %then %do;
|
|
29
|
+
%put %str(WARN)ING: unable to open &libds in mf_existvarlist (&dsid);
|
|
30
|
+
%end;
|
|
31
|
+
|
|
32
|
+
%if %sysfunc(attrn(&dsid,NVARS))=0 %then %do;
|
|
33
|
+
%put MF_EXISTVARLIST: No variables in &libds ;
|
|
34
|
+
0
|
|
35
|
+
%return;
|
|
36
|
+
%end;
|
|
37
|
+
|
|
38
|
+
%else %do i=1 %to %sysfunc(countw(&varlist));
|
|
39
|
+
%let var=%scan(&varlist,&i);
|
|
40
|
+
|
|
41
|
+
%if %sysfunc(varnum(&dsid,&var))=0 %then %do;
|
|
42
|
+
%let found=&found &var;
|
|
43
|
+
%end;
|
|
44
|
+
%end;
|
|
45
|
+
|
|
46
|
+
%let rc=%sysfunc(close(&dsid));
|
|
47
|
+
%if %str(&found)=%str() %then %do;
|
|
48
|
+
1
|
|
49
|
+
%end;
|
|
50
|
+
%else %do;
|
|
51
|
+
0
|
|
52
|
+
%put Vars not found: &found;
|
|
53
|
+
%end;
|
|
54
|
+
%mend mf_existvarlist;
|
|
55
|
+
|
|
56
|
+
/** @endcond */
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Returns E8601DT26.6 if compatible else DATETIME19.3
|
|
4
|
+
@details From our experience in [Data Controller for SAS]
|
|
5
|
+
(https://datacontroller.io) deployments, the E8601DT26.6 datetime format has
|
|
6
|
+
the widest support when it comes to pass-through SQL queries.
|
|
7
|
+
|
|
8
|
+
However, it is not supported in WPS or early versions of SAS 9 (M3 and below)
|
|
9
|
+
when used as a datetime literal, eg:
|
|
10
|
+
|
|
11
|
+
data _null_;
|
|
12
|
+
demo="%sysfunc(datetime(),E8601DT26.6)"dt;
|
|
13
|
+
demo=;
|
|
14
|
+
run;
|
|
15
|
+
|
|
16
|
+
This macro will therefore return DATEITME19.3 as an alternative format
|
|
17
|
+
based on the runtime environment so that it can be used in such cases, eg:
|
|
18
|
+
|
|
19
|
+
data _null_;
|
|
20
|
+
demo="%sysfunc(datetime(),%mf_fmtdttm())"dt;
|
|
21
|
+
demo=;
|
|
22
|
+
run;
|
|
23
|
+
|
|
24
|
+
<h4> Related Macros </h4>
|
|
25
|
+
@li mf_fmtdttm.test.sas
|
|
26
|
+
|
|
27
|
+
@author Allan Bowe
|
|
28
|
+
**/
|
|
29
|
+
|
|
30
|
+
%macro mf_fmtdttm(
|
|
31
|
+
)/*/STORE SOURCE*/;
|
|
32
|
+
|
|
33
|
+
%if "&sysver"="9.2" or "&sysver"="9.3"
|
|
34
|
+
or ("&sysver"="9.4" and "%substr(&SYSVLONG,9,1)" le "3")
|
|
35
|
+
or "%substr(&sysver,1,1)"="4"
|
|
36
|
+
or "%substr(&sysver,1,1)"="5"
|
|
37
|
+
%then %do;DATETIME19.3%end;
|
|
38
|
+
%else %do;E8601DT26.6%end;
|
|
39
|
+
|
|
40
|
+
%mend mf_fmtdttm;
|
|
41
|
+
|
|
42
|
+
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Returns the appLoc from the _program variable
|
|
4
|
+
@details When working with SASjs apps, web services / tests / jobs are always
|
|
5
|
+
deployed to a root (app) location in the SAS logical folder tree.
|
|
6
|
+
|
|
7
|
+
When building apps for use in other environments, you do not necessarily know
|
|
8
|
+
where the backend services will be deployed. Therefore a function like this
|
|
9
|
+
is handy in order to dynamically figure out the appLoc, and enable other
|
|
10
|
+
services to be connected by a relative reference.
|
|
11
|
+
|
|
12
|
+
SASjs apps always have the same immediate substructure (one or more of the
|
|
13
|
+
following):
|
|
14
|
+
|
|
15
|
+
@li /data
|
|
16
|
+
@li /jobs
|
|
17
|
+
@li /services
|
|
18
|
+
@li /tests
|
|
19
|
+
@li /tests/jobs
|
|
20
|
+
@li /tests/services
|
|
21
|
+
@li /tests/macros
|
|
22
|
+
|
|
23
|
+
This function works by testing for the existence of any of the above in the
|
|
24
|
+
automatic _program variable, and returning the part to the left of it.
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
|
|
28
|
+
%put %mf_getapploc(&_program)
|
|
29
|
+
|
|
30
|
+
%put %mf_getapploc(/some/location/services/admin/myservice);
|
|
31
|
+
%put %mf_getapploc(/some/location/jobs/extract/somejob/);
|
|
32
|
+
%put %mf_getapploc(/some/location/tests/jobs/somejob/);
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@author Allan Bowe
|
|
36
|
+
**/
|
|
37
|
+
|
|
38
|
+
%macro mf_getapploc(pgm);
|
|
39
|
+
%if "&pgm"="" %then %do;
|
|
40
|
+
%if %symexist(_program) %then %let pgm=&_program;
|
|
41
|
+
%else %do;
|
|
42
|
+
%put &sysmacroname: No value provided and no _program variable available;
|
|
43
|
+
%return;
|
|
44
|
+
%end;
|
|
45
|
+
%end;
|
|
46
|
+
%local root;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* First check we are not in the tests/macros folder (which has no subfolders)
|
|
50
|
+
* or specifically in the testsetup or testteardown services
|
|
51
|
+
*/
|
|
52
|
+
%if %index(&pgm,/tests/macros/)
|
|
53
|
+
or %index(&pgm,/tests/testsetup)
|
|
54
|
+
or %index(&pgm,/tests/testteardown)
|
|
55
|
+
%then %do;
|
|
56
|
+
%let root=%substr(&pgm,1,%index(&pgm,/tests)-1);
|
|
57
|
+
&root
|
|
58
|
+
%return;
|
|
59
|
+
%end;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Next, move up two levels to avoid matches on subfolder or service name
|
|
63
|
+
*/
|
|
64
|
+
%let root=%substr(&pgm,1,%length(&pgm)-%length(%scan(&pgm,-1,/))-1);
|
|
65
|
+
%let root=%substr(&root,1,%length(&root)-%length(%scan(&root,-1,/))-1);
|
|
66
|
+
|
|
67
|
+
%if %index(&root,/tests/) %then %do;
|
|
68
|
+
%let root=%substr(&root,1,%index(&root,/tests/)-1);
|
|
69
|
+
%end;
|
|
70
|
+
%else %if %index(&root,/services) %then %do;
|
|
71
|
+
%let root=%substr(&root,1,%index(&root,/services)-1);
|
|
72
|
+
%end;
|
|
73
|
+
%else %if %index(&root,/jobs) %then %do;
|
|
74
|
+
%let root=%substr(&root,1,%index(&root,/jobs)-1);
|
|
75
|
+
%end;
|
|
76
|
+
%else %put &sysmacroname: Could not find an app location from &pgm;
|
|
77
|
+
&root
|
|
78
|
+
%mend mf_getapploc ;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Returns a character attribute of a dataset.
|
|
4
|
+
@details Can be used in open code, eg as follows:
|
|
5
|
+
|
|
6
|
+
%put Dataset label = %mf_getattrc(sashelp.class,LABEL);
|
|
7
|
+
%put Member Type = %mf_getattrc(sashelp.class,MTYPE);
|
|
8
|
+
|
|
9
|
+
@param libds library.dataset
|
|
10
|
+
@param attr full list in [documentation](
|
|
11
|
+
https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000147794.htm)
|
|
12
|
+
@return output returns result of the attrc value supplied, or -1 and log
|
|
13
|
+
message if err.
|
|
14
|
+
|
|
15
|
+
@version 9.2
|
|
16
|
+
@author Allan Bowe
|
|
17
|
+
**/
|
|
18
|
+
|
|
19
|
+
%macro mf_getattrc(
|
|
20
|
+
libds
|
|
21
|
+
,attr
|
|
22
|
+
)/*/STORE SOURCE*/;
|
|
23
|
+
%local dsid rc;
|
|
24
|
+
%let dsid=%sysfunc(open(&libds,is));
|
|
25
|
+
%if &dsid = 0 %then %do;
|
|
26
|
+
%put %str(WARN)ING: Cannot open %trim(&libds), system message below;
|
|
27
|
+
%put %sysfunc(sysmsg());
|
|
28
|
+
-1
|
|
29
|
+
%end;
|
|
30
|
+
%else %do;
|
|
31
|
+
%sysfunc(attrc(&dsid,&attr))
|
|
32
|
+
%let rc=%sysfunc(close(&dsid));
|
|
33
|
+
%end;
|
|
34
|
+
%mend mf_getattrc;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
@file
|
|
3
|
+
@brief Returns a numeric attribute of a dataset.
|
|
4
|
+
@details Can be used in open code, eg as follows:
|
|
5
|
+
|
|
6
|
+
%put Number of observations=%mf_getattrn(sashelp.class,NLOBS);
|
|
7
|
+
%put Number of variables = %mf_getattrn(sashelp.class,NVARS);
|
|
8
|
+
|
|
9
|
+
@param libds library.dataset
|
|
10
|
+
@param attr Common values are NLOBS and NVARS, full list in [documentation](
|
|
11
|
+
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000212040.htm)
|
|
12
|
+
@return output returns result of the attrn value supplied, or -1 and log
|
|
13
|
+
message if err.
|
|
14
|
+
|
|
15
|
+
@version 9.2
|
|
16
|
+
@author Allan Bowe
|
|
17
|
+
**/
|
|
18
|
+
|
|
19
|
+
%macro mf_getattrn(
|
|
20
|
+
libds
|
|
21
|
+
,attr
|
|
22
|
+
)/*/STORE SOURCE*/;
|
|
23
|
+
%local dsid rc;
|
|
24
|
+
%let dsid=%sysfunc(open(&libds,is));
|
|
25
|
+
%if &dsid = 0 %then %do;
|
|
26
|
+
%put %str(WARN)ING: Cannot open %trim(&libds), system message below;
|
|
27
|
+
%put %sysfunc(sysmsg());
|
|
28
|
+
-1
|
|
29
|
+
%end;
|
|
30
|
+
%else %do;
|
|
31
|
+
%sysfunc(attrn(&dsid,&attr))
|
|
32
|
+
%let rc=%sysfunc(close(&dsid));
|
|
33
|
+
%end;
|
|
34
|
+
%mend mf_getattrn;
|