@sasjs/utils 2.48.2 → 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.
Files changed (163) hide show
  1. package/fs/generateCompileProgram.d.ts +1 -0
  2. package/fs/generateCompileProgram.js +154 -0
  3. package/fs/generateCompileProgram.js.map +1 -0
  4. package/fs/hash.d.ts +22 -0
  5. package/fs/hash.js +225 -0
  6. package/fs/hash.js.map +1 -0
  7. package/fs/index.d.ts +3 -0
  8. package/fs/index.js +13 -0
  9. package/fs/index.js.map +1 -0
  10. package/fs/internal/helper.d.ts +4 -0
  11. package/fs/internal/helper.js +125 -0
  12. package/fs/internal/helper.js.map +1 -0
  13. package/fs/sync.d.ts +6 -0
  14. package/fs/sync.js +208 -0
  15. package/fs/sync.js.map +1 -0
  16. package/index.d.ts +1 -0
  17. package/index.js +1 -0
  18. package/index.js.map +1 -1
  19. package/macros/mf_abort.sas +27 -0
  20. package/macros/mf_dedup.sas +53 -0
  21. package/macros/mf_deletefile.sas +31 -0
  22. package/macros/mf_existds.sas +30 -0
  23. package/macros/mf_existfeature.sas +59 -0
  24. package/macros/mf_existfileref.sas +33 -0
  25. package/macros/mf_existfunction.sas +37 -0
  26. package/macros/mf_existvar.sas +39 -0
  27. package/macros/mf_existvarlist.sas +56 -0
  28. package/macros/mf_fmtdttm.sas +42 -0
  29. package/macros/mf_getapploc.sas +78 -0
  30. package/macros/mf_getattrc.sas +34 -0
  31. package/macros/mf_getattrn.sas +34 -0
  32. package/macros/mf_getengine.sas +54 -0
  33. package/macros/mf_getfilesize.sas +64 -0
  34. package/macros/mf_getfmtlist.sas +61 -0
  35. package/macros/mf_getfmtname.sas +44 -0
  36. package/macros/mf_getkeyvalue.sas +32 -0
  37. package/macros/mf_getplatform.sas +75 -0
  38. package/macros/mf_getquotedstr.sas +57 -0
  39. package/macros/mf_getschema.sas +43 -0
  40. package/macros/mf_getuniquefileref.sas +60 -0
  41. package/macros/mf_getuniquelibref.sas +57 -0
  42. package/macros/mf_getuniquename.sas +22 -0
  43. package/macros/mf_getuser.sas +44 -0
  44. package/macros/mf_getvalue.sas +36 -0
  45. package/macros/mf_getvarcount.sas +49 -0
  46. package/macros/mf_getvarformat.sas +72 -0
  47. package/macros/mf_getvarlen.sas +56 -0
  48. package/macros/mf_getvarlist.sas +74 -0
  49. package/macros/mf_getvarnum.sas +58 -0
  50. package/macros/mf_getvartype.sas +52 -0
  51. package/macros/mf_getxengine.sas +43 -0
  52. package/macros/mf_increment.sas +29 -0
  53. package/macros/mf_isblank.sas +27 -0
  54. package/macros/mf_isdir.sas +34 -0
  55. package/macros/mf_isint.sas +36 -0
  56. package/macros/mf_islibds.sas +40 -0
  57. package/macros/mf_loc.sas +29 -0
  58. package/macros/mf_mkdir.sas +67 -0
  59. package/macros/mf_mval.sas +19 -0
  60. package/macros/mf_nobs.sas +26 -0
  61. package/macros/mf_trimstr.sas +50 -0
  62. package/macros/mf_uid.sas +21 -0
  63. package/macros/mf_verifymacvars.sas +72 -0
  64. package/macros/mf_wordsinstr1andstr2.sas +53 -0
  65. package/macros/mf_wordsinstr1butnotstr2.sas +54 -0
  66. package/macros/mf_writefile.sas +67 -0
  67. package/macros/mp_abort.sas +301 -0
  68. package/macros/mp_appendfile.sas +57 -0
  69. package/macros/mp_applyformats.sas +181 -0
  70. package/macros/mp_assert.sas +56 -0
  71. package/macros/mp_assertcols.sas +145 -0
  72. package/macros/mp_assertcolvals.sas +168 -0
  73. package/macros/mp_assertdsobs.sas +121 -0
  74. package/macros/mp_assertscope.sas +147 -0
  75. package/macros/mp_base64copy.sas +117 -0
  76. package/macros/mp_binarycopy.sas +79 -0
  77. package/macros/mp_chop.sas +194 -0
  78. package/macros/mp_cleancsv.sas +78 -0
  79. package/macros/mp_cntlout.sas +85 -0
  80. package/macros/mp_copyfolder.sas +84 -0
  81. package/macros/mp_coretable.sas +73 -0
  82. package/macros/mp_createconstraints.sas +70 -0
  83. package/macros/mp_createwebservice.sas +32 -0
  84. package/macros/mp_csv2ds.sas +140 -0
  85. package/macros/mp_deleteconstraints.sas +52 -0
  86. package/macros/mp_deletefolder.sas +70 -0
  87. package/macros/mp_dictionary.sas +52 -0
  88. package/macros/mp_dirlist.sas +263 -0
  89. package/macros/mp_distinctfmtvalues.sas +50 -0
  90. package/macros/mp_dropmembers.sas +46 -0
  91. package/macros/mp_ds2cards.sas +291 -0
  92. package/macros/mp_ds2csv.sas +212 -0
  93. package/macros/mp_ds2ddl.sas +30 -0
  94. package/macros/mp_ds2fmtds.sas +105 -0
  95. package/macros/mp_ds2inserts.sas +180 -0
  96. package/macros/mp_ds2md.sas +103 -0
  97. package/macros/mp_ds2squeeze.sas +120 -0
  98. package/macros/mp_dsmeta.sas +110 -0
  99. package/macros/mp_filtercheck.sas +251 -0
  100. package/macros/mp_filtergenerate.sas +105 -0
  101. package/macros/mp_filterstore.sas +254 -0
  102. package/macros/mp_filtervalidate.sas +105 -0
  103. package/macros/mp_getcols.sas +67 -0
  104. package/macros/mp_getconstraints.sas +115 -0
  105. package/macros/mp_getdbml.sas +335 -0
  106. package/macros/mp_getddl.sas +400 -0
  107. package/macros/mp_getformats.sas +124 -0
  108. package/macros/mp_getmaxvarlengths.sas +130 -0
  109. package/macros/mp_getpk.sas +281 -0
  110. package/macros/mp_gsubfile.sas +58 -0
  111. package/macros/mp_guesspk.sas +332 -0
  112. package/macros/mp_hashdataset.sas +91 -0
  113. package/macros/mp_hashdirectory.sas +162 -0
  114. package/macros/mp_include.sas +106 -0
  115. package/macros/mp_init.sas +76 -0
  116. package/macros/mp_jsonout.sas +406 -0
  117. package/macros/mp_lib2cards.sas +78 -0
  118. package/macros/mp_lib2inserts.sas +77 -0
  119. package/macros/mp_loadformat.sas +303 -0
  120. package/macros/mp_lockanytable.sas +243 -0
  121. package/macros/mp_lockfilecheck.sas +103 -0
  122. package/macros/mp_makedata.sas +107 -0
  123. package/macros/mp_md5.sas +58 -0
  124. package/macros/mp_perflog.sas +43 -0
  125. package/macros/mp_prevobs.sas +88 -0
  126. package/macros/mp_recursivejoin.sas +90 -0
  127. package/macros/mp_replace.sas +151 -0
  128. package/macros/mp_reseterror.sas +27 -0
  129. package/macros/mp_resetoption.sas +39 -0
  130. package/macros/mp_retainedkey.sas +247 -0
  131. package/macros/mp_runddl.sas +49 -0
  132. package/macros/mp_searchcols.sas +103 -0
  133. package/macros/mp_searchdata.sas +131 -0
  134. package/macros/mp_setkeyvalue.sas +55 -0
  135. package/macros/mp_sortinplace.sas +122 -0
  136. package/macros/mp_stackdiffs.sas +592 -0
  137. package/macros/mp_storediffs.sas +230 -0
  138. package/macros/mp_stprequests.sas +74 -0
  139. package/macros/mp_streamfile.sas +212 -0
  140. package/macros/mp_testjob.sas +92 -0
  141. package/macros/mp_testservice.sas +39 -0
  142. package/macros/mp_testwritespeedlibrary.sas +59 -0
  143. package/macros/mp_tree.sas +71 -0
  144. package/macros/mp_unzip.sas +90 -0
  145. package/macros/mp_updatevarlength.sas +93 -0
  146. package/macros/mp_validatecol.sas +97 -0
  147. package/macros/mp_wait4file.sas +35 -0
  148. package/macros/mp_webin.sas +59 -0
  149. package/macros/mp_zip.sas +85 -0
  150. package/package.json +5 -2
  151. package/scripts/copySASjsCore.ts +36 -0
  152. package/types/hash.d.ts +9 -0
  153. package/types/hash.js +3 -0
  154. package/types/hash.js.map +1 -0
  155. package/types/index.d.ts +1 -0
  156. package/types/index.js +1 -0
  157. package/types/index.js.map +1 -1
  158. package/utils/index.d.ts +1 -1
  159. package/utils/index.js +2 -1
  160. package/utils/index.js.map +1 -1
  161. package/utils/utils.d.ts +1 -0
  162. package/utils/utils.js +7 -1
  163. package/utils/utils.js.map +1 -1
package/fs/sync.js ADDED
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (_) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __values = (this && this.__values) || function(o) {
39
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
40
+ if (m) return m.call(o);
41
+ if (o && typeof o.length === "number") return {
42
+ next: function () {
43
+ if (o && i >= o.length) o = void 0;
44
+ return { value: o && o[i++], done: !o };
45
+ }
46
+ };
47
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
48
+ };
49
+ var __read = (this && this.__read) || function (o, n) {
50
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
51
+ if (!m) return o;
52
+ var i = m.call(o), r, ar = [], e;
53
+ try {
54
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
55
+ }
56
+ catch (error) { e = { error: error }; }
57
+ finally {
58
+ try {
59
+ if (r && !r.done && (m = i["return"])) m.call(i);
60
+ }
61
+ finally { if (e) throw e.error; }
62
+ }
63
+ return ar;
64
+ };
65
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
66
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
67
+ if (ar || !(i in from)) {
68
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
69
+ ar[i] = from[i];
70
+ }
71
+ }
72
+ return to.concat(ar || Array.prototype.slice.call(from));
73
+ };
74
+ var __importDefault = (this && this.__importDefault) || function (mod) {
75
+ return (mod && mod.__esModule) ? mod : { "default": mod };
76
+ };
77
+ Object.defineProperty(exports, "__esModule", { value: true });
78
+ exports.findResourcesNotPresentLocally = exports.generateProgramToSyncHashDiff = exports.generateProgramToGetRemoteHash = void 0;
79
+ var path_1 = __importDefault(require("path"));
80
+ var helper_1 = require("./internal/helper");
81
+ var generateProgramToGetRemoteHash = function (remotePath) { return __awaiter(void 0, void 0, void 0, function () {
82
+ var compiledMacrosCode, codeForHashCreation, code;
83
+ return __generator(this, function (_a) {
84
+ switch (_a.label) {
85
+ case 0: return [4 /*yield*/, (0, helper_1.getCompiledMacrosCode)([
86
+ 'mp_hashdirectory.sas',
87
+ 'mp_jsonout.sas'
88
+ ])];
89
+ case 1:
90
+ compiledMacrosCode = _a.sent();
91
+ codeForHashCreation = getCodeForHashCreation();
92
+ code = compiledMacrosCode + codeForHashCreation;
93
+ return [2 /*return*/, setTargetAtStart(code, remotePath)];
94
+ }
95
+ });
96
+ }); };
97
+ exports.generateProgramToGetRemoteHash = generateProgramToGetRemoteHash;
98
+ var generateProgramToSyncHashDiff = function (hashedFolder, remotePath) { return __awaiter(void 0, void 0, void 0, function () {
99
+ var compiledMacrosCode, initialProgramContent, pathRelativeTo, folderCreationCode, codeForHashCreation, code;
100
+ return __generator(this, function (_a) {
101
+ switch (_a.label) {
102
+ case 0: return [4 /*yield*/, (0, helper_1.getCompiledMacrosCode)([
103
+ 'mp_hashdirectory.sas',
104
+ 'mp_jsonout.sas',
105
+ 'mf_mkdir.sas'
106
+ ])];
107
+ case 1:
108
+ compiledMacrosCode = _a.sent();
109
+ initialProgramContent = (0, helper_1.getInitialCode)();
110
+ pathRelativeTo = hashedFolder.absolutePath.endsWith(path_1.default.sep)
111
+ ? hashedFolder.absolutePath.slice(0, -1)
112
+ : hashedFolder.absolutePath;
113
+ return [4 /*yield*/, generateCodeForFolderCreation(hashedFolder, pathRelativeTo)];
114
+ case 2:
115
+ folderCreationCode = _a.sent();
116
+ codeForHashCreation = getCodeForHashCreation();
117
+ code = compiledMacrosCode +
118
+ initialProgramContent +
119
+ folderCreationCode +
120
+ codeForHashCreation;
121
+ return [2 /*return*/, setTargetAtStart(code, remotePath)];
122
+ }
123
+ });
124
+ }); };
125
+ exports.generateProgramToSyncHashDiff = generateProgramToSyncHashDiff;
126
+ var findResourcesNotPresentLocally = function (localHash, remoteHashMap) {
127
+ var localHashedArray = convertHashFolderTreeToArray(localHash);
128
+ var remoteHashedArray = Object.keys(remoteHashMap);
129
+ return remoteHashedArray.filter(function (item) { return !localHashedArray.includes(item); });
130
+ };
131
+ exports.findResourcesNotPresentLocally = findResourcesNotPresentLocally;
132
+ var generateCodeForFolderCreation = function (hashedFolder, pathRelativeTo, resultCode) {
133
+ if (resultCode === void 0) { resultCode = ''; }
134
+ return __awaiter(void 0, void 0, void 0, function () {
135
+ var _a, _b, member, _c, e_1_1;
136
+ var e_1, _d;
137
+ return __generator(this, function (_e) {
138
+ switch (_e.label) {
139
+ case 0:
140
+ _e.trys.push([0, 7, 8, 9]);
141
+ _a = __values(hashedFolder.members), _b = _a.next();
142
+ _e.label = 1;
143
+ case 1:
144
+ if (!!_b.done) return [3 /*break*/, 6];
145
+ member = _b.value;
146
+ if (!member.isFile) return [3 /*break*/, 3];
147
+ _c = resultCode;
148
+ return [4 /*yield*/, (0, helper_1.generateCodeForFileCreation)(member.absolutePath, pathRelativeTo)];
149
+ case 2:
150
+ resultCode = _c + _e.sent();
151
+ return [3 /*break*/, 5];
152
+ case 3:
153
+ resultCode += "%mf_mkdir(&fsTarget".concat(member.absolutePath.replace(pathRelativeTo, ''), ")\n");
154
+ return [4 /*yield*/, generateCodeForFolderCreation(member, pathRelativeTo, resultCode)];
155
+ case 4:
156
+ resultCode = _e.sent();
157
+ _e.label = 5;
158
+ case 5:
159
+ _b = _a.next();
160
+ return [3 /*break*/, 1];
161
+ case 6: return [3 /*break*/, 9];
162
+ case 7:
163
+ e_1_1 = _e.sent();
164
+ e_1 = { error: e_1_1 };
165
+ return [3 /*break*/, 9];
166
+ case 8:
167
+ try {
168
+ if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
169
+ }
170
+ finally { if (e_1) throw e_1.error; }
171
+ return [7 /*endfinally*/];
172
+ case 9: return [2 /*return*/, resultCode];
173
+ }
174
+ });
175
+ });
176
+ };
177
+ var getCodeForHashCreation = function () {
178
+ return "/* Get Hashes */\n%mp_hashdirectory(&fsTarget,maxDepth=MAX,outds=work.hashes)\n\n/* Prepare Response JSON */\nfilename tmp temp;\n%mp_jsonout(OPEN,jref=tmp)\n%mp_jsonout(OBJ,hashes,fmt=N,jref=tmp)\n%mp_jsonout(CLOSE,jref=tmp)\n\n/* Print to Log */\ndata _null_;\n retain eof;\n infile tmp end=eof lrecl=10000;\n if _n_=1 then putlog '>>weboutBEGIN<<';\n input;\n putlog _infile_;\n if eof then putlog '>>weboutEND<<';\nrun;\n";
179
+ };
180
+ var setTargetAtStart = function (code, target) {
181
+ return "%let fsTarget=".concat(target, ";\n").concat(code);
182
+ };
183
+ /**
184
+ * convert hash folder tree to an array of relative paths,
185
+ * the returned array will be used to check the resources that are present on remote but not local
186
+ */
187
+ var convertHashFolderTreeToArray = function (hashedFolder, array) {
188
+ var e_2, _a;
189
+ if (array === void 0) { array = []; }
190
+ if (hashedFolder.isFile)
191
+ return __spreadArray(__spreadArray([], __read(array), false), [hashedFolder.relativePath], false);
192
+ try {
193
+ for (var _b = __values(hashedFolder.members), _c = _b.next(); !_c.done; _c = _b.next()) {
194
+ var member = _c.value;
195
+ array = convertHashFolderTreeToArray(member, array);
196
+ }
197
+ }
198
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
199
+ finally {
200
+ try {
201
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
202
+ }
203
+ finally { if (e_2) throw e_2.error; }
204
+ }
205
+ array.push(hashedFolder.relativePath);
206
+ return array;
207
+ };
208
+ //# sourceMappingURL=sync.js.map
package/fs/sync.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/fs/sync.ts"],"names":[],"mappings":"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"}
package/index.d.ts CHANGED
@@ -8,3 +8,4 @@ export * from './time';
8
8
  export * from './types';
9
9
  export * from './utils';
10
10
  export * from './compileTree';
11
+ export * from './fs';
package/index.js CHANGED
@@ -20,4 +20,5 @@ __exportStar(require("./time"), exports);
20
20
  __exportStar(require("./types"), exports);
21
21
  __exportStar(require("./utils"), exports);
22
22
  __exportStar(require("./compileTree"), exports);
23
+ __exportStar(require("./fs"), exports);
23
24
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yCAAsB;AACtB,yCAAsB;AACtB,8CAA2B;AAC3B,0CAAuB;AACvB,2CAAwB;AACxB,6CAA0B;AAC1B,yCAAsB;AACtB,0CAAuB;AACvB,0CAAuB;AACvB,gDAA6B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,yCAAsB;AACtB,yCAAsB;AACtB,8CAA2B;AAC3B,0CAAuB;AACvB,2CAAwB;AACxB,6CAA0B;AAC1B,yCAAsB;AACtB,0CAAuB;AACvB,0CAAuB;AACvB,gDAA6B;AAC7B,uCAAoB"}
@@ -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
+