@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.
Files changed (147) hide show
  1. package/fs/internal/helper.js +19 -24
  2. package/fs/internal/helper.js.map +1 -1
  3. package/macros/mf_abort.sas +27 -0
  4. package/macros/mf_dedup.sas +53 -0
  5. package/macros/mf_deletefile.sas +31 -0
  6. package/macros/mf_existds.sas +30 -0
  7. package/macros/mf_existfeature.sas +59 -0
  8. package/macros/mf_existfileref.sas +33 -0
  9. package/macros/mf_existfunction.sas +37 -0
  10. package/macros/mf_existvar.sas +39 -0
  11. package/macros/mf_existvarlist.sas +56 -0
  12. package/macros/mf_fmtdttm.sas +42 -0
  13. package/macros/mf_getapploc.sas +78 -0
  14. package/macros/mf_getattrc.sas +34 -0
  15. package/macros/mf_getattrn.sas +34 -0
  16. package/macros/mf_getengine.sas +54 -0
  17. package/macros/mf_getfilesize.sas +64 -0
  18. package/macros/mf_getfmtlist.sas +61 -0
  19. package/macros/mf_getfmtname.sas +44 -0
  20. package/macros/mf_getkeyvalue.sas +32 -0
  21. package/macros/mf_getplatform.sas +75 -0
  22. package/macros/mf_getquotedstr.sas +57 -0
  23. package/macros/mf_getschema.sas +43 -0
  24. package/macros/mf_getuniquefileref.sas +60 -0
  25. package/macros/mf_getuniquelibref.sas +57 -0
  26. package/macros/mf_getuniquename.sas +22 -0
  27. package/macros/mf_getuser.sas +44 -0
  28. package/macros/mf_getvalue.sas +36 -0
  29. package/macros/mf_getvarcount.sas +49 -0
  30. package/macros/mf_getvarformat.sas +72 -0
  31. package/macros/mf_getvarlen.sas +56 -0
  32. package/macros/mf_getvarlist.sas +74 -0
  33. package/macros/mf_getvarnum.sas +58 -0
  34. package/macros/mf_getvartype.sas +52 -0
  35. package/macros/mf_getxengine.sas +43 -0
  36. package/macros/mf_increment.sas +29 -0
  37. package/macros/mf_isblank.sas +27 -0
  38. package/macros/mf_isdir.sas +34 -0
  39. package/macros/mf_isint.sas +36 -0
  40. package/macros/mf_islibds.sas +40 -0
  41. package/macros/mf_loc.sas +29 -0
  42. package/macros/mf_mkdir.sas +67 -0
  43. package/macros/mf_mval.sas +19 -0
  44. package/macros/mf_nobs.sas +26 -0
  45. package/macros/mf_trimstr.sas +50 -0
  46. package/macros/mf_uid.sas +21 -0
  47. package/macros/mf_verifymacvars.sas +72 -0
  48. package/macros/mf_wordsinstr1andstr2.sas +53 -0
  49. package/macros/mf_wordsinstr1butnotstr2.sas +54 -0
  50. package/macros/mf_writefile.sas +67 -0
  51. package/macros/mp_abort.sas +301 -0
  52. package/macros/mp_appendfile.sas +57 -0
  53. package/macros/mp_applyformats.sas +181 -0
  54. package/macros/mp_assert.sas +56 -0
  55. package/macros/mp_assertcols.sas +145 -0
  56. package/macros/mp_assertcolvals.sas +168 -0
  57. package/macros/mp_assertdsobs.sas +121 -0
  58. package/macros/mp_assertscope.sas +147 -0
  59. package/macros/mp_base64copy.sas +117 -0
  60. package/macros/mp_binarycopy.sas +79 -0
  61. package/macros/mp_chop.sas +194 -0
  62. package/macros/mp_cleancsv.sas +78 -0
  63. package/macros/mp_cntlout.sas +85 -0
  64. package/macros/mp_copyfolder.sas +84 -0
  65. package/macros/mp_coretable.sas +73 -0
  66. package/macros/mp_createconstraints.sas +70 -0
  67. package/macros/mp_createwebservice.sas +32 -0
  68. package/macros/mp_csv2ds.sas +140 -0
  69. package/macros/mp_deleteconstraints.sas +52 -0
  70. package/macros/mp_deletefolder.sas +70 -0
  71. package/macros/mp_dictionary.sas +52 -0
  72. package/macros/mp_dirlist.sas +262 -0
  73. package/macros/mp_distinctfmtvalues.sas +50 -0
  74. package/macros/mp_dropmembers.sas +46 -0
  75. package/macros/mp_ds2cards.sas +291 -0
  76. package/macros/mp_ds2csv.sas +212 -0
  77. package/macros/mp_ds2ddl.sas +30 -0
  78. package/macros/mp_ds2fmtds.sas +105 -0
  79. package/macros/mp_ds2inserts.sas +180 -0
  80. package/macros/mp_ds2md.sas +103 -0
  81. package/macros/mp_ds2squeeze.sas +120 -0
  82. package/macros/mp_dsmeta.sas +110 -0
  83. package/macros/mp_filtercheck.sas +251 -0
  84. package/macros/mp_filtergenerate.sas +105 -0
  85. package/macros/mp_filterstore.sas +254 -0
  86. package/macros/mp_filtervalidate.sas +105 -0
  87. package/macros/mp_getcols.sas +67 -0
  88. package/macros/mp_getconstraints.sas +115 -0
  89. package/macros/mp_getdbml.sas +335 -0
  90. package/macros/mp_getddl.sas +400 -0
  91. package/macros/mp_getformats.sas +124 -0
  92. package/macros/mp_getmaxvarlengths.sas +130 -0
  93. package/macros/mp_getpk.sas +281 -0
  94. package/macros/mp_gitadd.sas +45 -0
  95. package/macros/mp_gitreleaseinfo.sas +74 -0
  96. package/macros/mp_gitstatus.sas +67 -0
  97. package/macros/mp_gsubfile.sas +58 -0
  98. package/macros/mp_guesspk.sas +332 -0
  99. package/macros/mp_hashdataset.sas +91 -0
  100. package/macros/mp_hashdirectory.sas +164 -0
  101. package/macros/mp_include.sas +106 -0
  102. package/macros/mp_init.sas +76 -0
  103. package/macros/mp_jsonout.sas +406 -0
  104. package/macros/mp_lib2cards.sas +78 -0
  105. package/macros/mp_lib2inserts.sas +77 -0
  106. package/macros/mp_loadformat.sas +303 -0
  107. package/macros/mp_lockanytable.sas +243 -0
  108. package/macros/mp_lockfilecheck.sas +103 -0
  109. package/macros/mp_makedata.sas +107 -0
  110. package/macros/mp_md5.sas +58 -0
  111. package/macros/mp_perflog.sas +43 -0
  112. package/macros/mp_prevobs.sas +88 -0
  113. package/macros/mp_recursivejoin.sas +90 -0
  114. package/macros/mp_replace.sas +151 -0
  115. package/macros/mp_reseterror.sas +27 -0
  116. package/macros/mp_resetoption.sas +39 -0
  117. package/macros/mp_retainedkey.sas +247 -0
  118. package/macros/mp_runddl.sas +49 -0
  119. package/macros/mp_searchcols.sas +103 -0
  120. package/macros/mp_searchdata.sas +131 -0
  121. package/macros/mp_setkeyvalue.sas +55 -0
  122. package/macros/mp_sortinplace.sas +122 -0
  123. package/macros/mp_stackdiffs.sas +592 -0
  124. package/macros/mp_storediffs.sas +230 -0
  125. package/macros/mp_stprequests.sas +74 -0
  126. package/macros/mp_streamfile.sas +212 -0
  127. package/macros/mp_testjob.sas +92 -0
  128. package/macros/mp_testservice.sas +39 -0
  129. package/macros/mp_testwritespeedlibrary.sas +59 -0
  130. package/macros/mp_tree.sas +71 -0
  131. package/macros/mp_unzip.sas +90 -0
  132. package/macros/mp_updatevarlength.sas +93 -0
  133. package/macros/mp_validatecol.sas +97 -0
  134. package/macros/mp_wait4file.sas +35 -0
  135. package/macros/mp_webin.sas +59 -0
  136. package/macros/mp_zip.sas +85 -0
  137. package/package.json +5 -2
  138. package/scripts/copySASjsCore.ts +36 -0
  139. package/utils/index.d.ts +1 -2
  140. package/utils/index.js +2 -3
  141. package/utils/index.js.map +1 -1
  142. package/utils/utils.d.ts +1 -0
  143. package/utils/utils.js +7 -1
  144. package/utils/utils.js.map +1 -1
  145. package/utils/getNodeModulePath.d.ts +0 -2
  146. package/utils/getNodeModulePath.js +0 -83
  147. package/utils/getNodeModulePath.js.map +0 -1
@@ -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 getNodeModulePath_1 = require("../../utils/getNodeModulePath");
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, chunk_1.chunk)(fileContent);
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 sasjsCorePath, compiledCode, macros_1, macros_1_1, macro, macroPath, macroContent, e_1_1;
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: return [4 /*yield*/, (0, getNodeModulePath_1.getNodeModulePath)('@sasjs/core')];
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
- _b.trys.push([2, 7, 8, 9]);
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(sasjsCorePath, 'base', macro);
100
+ macroPath = path_1.default.join((0, utils_1.getMacrosPath)(), macro);
106
101
  return [4 /*yield*/, (0, file_1.readFile)(macroPath)];
107
- case 4:
102
+ case 3:
108
103
  macroContent = _b.sent();
109
104
  compiledCode += macroContent + '\n';
110
- _b.label = 5;
111
- case 5:
105
+ _b.label = 4;
106
+ case 4:
112
107
  macros_1_1 = macros_1.next();
113
- return [3 /*break*/, 3];
114
- case 6: return [3 /*break*/, 9];
115
- case 7:
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*/, 9];
119
- case 8:
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 9: return [2 /*return*/, compiledCode];
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,mEAAiE;AACjE,2CAAyC;AACzC,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;;;;;oBACpC,qBAAM,IAAA,qCAAiB,EAAC,aAAa,CAAC,EAAA;;gBAAtD,aAAa,GAAG,SAAsC;gBAC5D,IAAI,CAAC,aAAa;oBAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;gBAEjE,YAAY,GAAG,EAAE,CAAA;;;;gBAED,WAAA,SAAA,MAAM,CAAA;;;;gBAAf,KAAK;gBACR,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;gBACpC,qBAAM,IAAA,eAAQ,EAAC,SAAS,CAAC,EAAA;;gBAAxC,YAAY,GAAG,SAAyB;gBAE9C,YAAY,IAAI,YAAY,GAAG,IAAI,CAAA;;;;;;;;;;;;;;;;oBAGrC,sBAAO,YAAY,EAAA;;;KACpB,CAAA;AAdY,QAAA,qBAAqB,yBAcjC"}
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;