1
0
mirror of https://github.com/sasjs/core.git synced 2025-12-11 06:24:35 +00:00

Compare commits

...

987 Commits

Author SHA1 Message Date
Allan Bowe
ee35f47f4f feat: new mfv_existsashdat() macro for checking whether a dataset exists in persistent storage 2022-10-07 13:43:41 +00:00
Allan Bowe
7f867e2a5c Merge pull request #315 from sasjs/allanbowe/hashing-file-breaks-mp-314
fix: ignoring empty files in mp_hashdirectory. Closes #314
2022-10-06 13:10:46 +01:00
Allan Bowe
c6af6ce578 fix: ignoring empty files in mp_hashdirectory. Closes #314 2022-10-06 12:08:25 +00:00
Allan Bowe
a1aac785c0 Merge pull request #313 from sasjs/issue312
feat: new mp_hashdirectory() macro and associated test.  Closes #312
2022-09-16 11:00:10 +01:00
munja
dbe8b0b1c3 chore: readme merge 2022-09-16 10:59:28 +01:00
munja
2ee9a4cee4 chore(docs): removed reference to part that is not ready yet 2022-09-16 10:59:02 +01:00
Allan Bowe
3a7afdffb7 Merge branch 'main' into issue312 2022-09-15 16:49:34 +01:00
munja
c78211aa1c feat: new mp_hashdirectory() macro and associated test. Closes #312 2022-09-15 16:47:05 +01:00
Allan Bowe
76c49e96f2 Update README.md 2022-09-15 15:03:36 +01:00
Allan Bowe
984ea44f5d Merge pull request #311 from sasjs/allanbowe/mv-createfile-needs-a-310
feat: adding ctype option to mv_createfile.sas macro
2022-09-13 20:37:28 +01:00
Allan Bowe
88f1222abd Merge branch 'main' into allanbowe/mv-createfile-needs-a-310 2022-09-13 20:37:03 +01:00
Allan Bowe
d88f028ee3 chore: removing ovpn from pipeline 2022-09-06 22:27:40 +00:00
Allan Bowe
07d7c9df4b feat: adding ctype option to mv_createfile.sas macro 2022-09-06 21:20:00 +00:00
munja
6765a1d025 chore(docs): image link 2022-09-03 18:00:00 +01:00
Allan Bowe
952f28a872 Merge pull request #309 from sasjs/dictionary
feat: new mp_dictionary() table
2022-09-03 16:53:05 +01:00
munja
8246b5a42c feat: new mp_dictionary() table 2022-09-03 16:50:11 +01:00
Allan Bowe
72123aeeb7 Merge pull request #305 from sasjs/cli1229
Making _addjesbeginendmacros configurable
2022-08-25 14:21:04 +01:00
Allan Bowe
236d1ae25f Merge branch 'main' into cli1229 2022-08-25 14:20:57 +01:00
munja
b75369b28d fix: pgm uninitialised in mm_getstpinfo 2022-08-23 16:00:42 +01:00
Allan Bowe
63871db170 Merge pull request #308 from sasjs/allanbowe/mp-jsonout-does-not-replace-307
fix: support for SUB (1A) hex char in DATASTEP generated JSON.
2022-08-22 14:16:13 +01:00
Allan Bowe
6456c2f6e2 fix: support for SUB (1A) hex char in DATASTEP generated JSON. Closes #307 2022-08-22 13:14:20 +00:00
munja
36faa194a8 chore(docs): more related files in mp_dsmeta.sas 2022-08-21 21:15:24 +01:00
munja
093dc87aad chore(docs): crediting louise 2022-08-21 19:55:02 +01:00
munja
ca045e3ebf chore(docs): typo 2022-08-21 19:27:52 +01:00
Allan Bowe
be5e2f371d Merge pull request #306 from sasjs/mp_dsmeta
feat: new mp_dsmeta macro
2022-08-21 19:18:56 +01:00
munja
6d15465bac fix: generating all.sas and fixing failing test 2022-08-21 19:17:56 +01:00
munja
2031a5b0c0 feat: new mp_dsmeta macro 2022-08-21 19:01:01 +01:00
Allan Bowe
7b3844a391 chore: updating all.sas 2022-08-21 16:02:20 +00:00
Allan Bowe
202de36042 fix: options to remove _addjesbeginendmacros from Viya Jobs 2022-08-21 16:01:50 +00:00
Allan Bowe
62837b512b feat: mm_getstpinfo.sas
Actually this came from a previous commit but the message was squashed out:  1b5effd584
2022-08-19 11:28:15 +01:00
Allan Bowe
5d5a99fd77 Merge pull request #304 from sasjs/allanbowe/need-a-macro-to-extract-303
chore(lint): reduce length
2022-08-19 11:00:00 +01:00
Allan Bowe
1b5effd584 chore(lint): reduce length 2022-08-19 09:58:42 +00:00
Allan Bowe
1613ab2c9e Merge pull request #302 from sasjs/allanbowe/proc-format-max-can-be-300
fix: switching MAX for LENGTH to get max label value.  Closes #300
2022-08-17 21:59:14 +01:00
Allan Bowe
a2df4e35be fix: switching MAX for LENGTH to get max label value. Closes #300 2022-08-17 20:54:14 +00:00
Allan Bowe
aabbcfdf6b Merge pull request #299 from sasjs/allanbowe/remove-work-tables-from-298
fix: removing automatic dump of WORK tables in mX_webout macros.  Clo…
2022-08-15 18:48:06 +01:00
Allan Bowe
7b7759e1ce chore: fix renegade closing bracket 2022-08-15 17:44:24 +00:00
Allan Bowe
e5a3053600 fix: removing automatic dump of WORK tables in mX_webout macros. Closes 298 2022-08-15 17:21:00 +00:00
Allan Bowe
9856d0ef58 Merge pull request #297 from sasjs/allanbowe/improve-efficiency-of-295
Further improvements to mp_jsonout
2022-08-15 00:48:23 +01:00
Allan Bowe
77b37e5503 chore: regenerated web service macros 2022-08-14 23:43:42 +00:00
Allan Bowe
793319fe38 fix: improved JSON performance for wide tables with a lot of formatted values. 50% improvement! 2022-08-14 23:43:19 +00:00
Allan Bowe
594a895ddd Merge pull request #296 from sasjs/allanbowe/improve-efficiency-of-295
fix: performance optimisations. closes #295
2022-08-12 19:54:04 +01:00
Allan Bowe
0d59266b8d fix: performance optimisations. closes #295 2022-08-12 18:13:35 +00:00
Allan Bowe
4863aafaa8 Merge pull request #294 from sasjs/allanbowe/add-maxobs-parameter-293
feat: adding maxobs param to mX_webout macros
2022-08-12 14:14:45 +01:00
Allan Bowe
6015320145 feat: adding maxobs param to mX_webout macros 2022-08-12 13:12:06 +00:00
Allan Bowe
8c09c0bce0 Merge pull request #292 from sasjs/allanbowe/increase-length-for-syswarningtext-291
fix: adding length statement for SYSWARNINGTEXT. Closes #291
2022-08-01 11:43:53 +01:00
Allan Bowe
437943b779 fix: adding length statement for SYSWARNINGTEXT. Closes #291 2022-08-01 10:40:55 +00:00
Allan Bowe
6a090e45b6 Merge pull request #290 from sasjs/allanbowe/mp-cleancsv-does-not-289
fix: enable embedded blanks in mp_cleancsv, closes #289
2022-07-21 23:47:18 +01:00
Allan Bowe
a7dc314204 fix: enable embedded blanks in mp_cleancsv, closes #289 2022-07-21 22:40:43 +00:00
munja
37076eae89 feat: new mmx_createmetafolder macro 2022-07-20 19:17:06 +01:00
munja
9a9f8dc847 chore(docs): adding matomo analytics 2022-07-15 16:06:03 +01:00
Allan Bowe
719b657267 Merge pull request #288 from sasjs/allanbowe/mp-jsonout-truncates-287
fix: avoid truncation for formatted outputs
2022-07-14 15:22:20 +01:00
Allan Bowe
671a615501 chore(docs): updated label 2022-07-14 14:18:27 +00:00
Allan Bowe
884b45bf12 fix: avoid truncation for formatted outputs
Closes #287
2022-07-14 14:16:42 +00:00
Allan Bowe
ff6ae1b066 Merge pull request #286 from sasjs/ddlfix
fix: comment issue in DDL generation
2022-07-14 14:03:29 +01:00
Allan Bowe
d581fec55e fix: comment issue in DDL generation 2022-07-14 13:02:15 +00:00
Allan Bowe
a5613a79bb chore(docs): adding SASJedi link to README 2022-07-14 11:42:34 +01:00
Allan Bowe
c6703e16e8 Merge pull request #285 from sasjs/mf_increment
feat: new mf_increment macro
2022-07-14 08:57:49 +01:00
munja
6587dce95b feat: new mf_increment macro 2022-07-13 23:57:02 +01:00
Allan Bowe
b60e6448b9 Merge pull request #284 from sasjs/allanbowe/dictionary-table-constraints-283
fix: avoid exceptions from dictionary.table_constraints.
2022-07-13 19:05:33 +01:00
Allan Bowe
46d9b58b32 fix: avoid exceptions from dictionary.table_constraints.
Closes #283
2022-07-13 18:01:52 +00:00
Allan Bowe
349cbabc94 Merge pull request #282 from sasjs/allanbowe/error-multiple-lengths-281
fix: prevent warning from `_label_` variable with different lengths
2022-07-12 23:29:47 +01:00
Allan Bowe
9de056a3fc fix: prevent warning from _label_ variable with different lengths
Closes #281
2022-07-12 22:18:01 +00:00
Allan Bowe
ad497b322f chore(tests): adding some extra test cases 2022-07-12 15:03:41 +00:00
Allan Bowe
7a6408ee44 Merge pull request #280 from sasjs/allanbowe/support-special-missings-279
fix: supporting special missings in BETWEEN and IN operators
2022-07-08 00:25:53 +01:00
Allan Bowe
336743f2b4 fix: applying logic to BETWEEN as well as IN 2022-07-07 23:24:24 +00:00
Allan Bowe
6e32eb3bd6 fix: supporting special missings in BETWEEN and IN operators
Impacts mp_filtercheck.sas.  Tests added.  Closes #279
2022-07-07 22:47:04 +00:00
Allan Bowe
b377b83442 Merge pull request #278 from sasjs/allanbowe/add-iftrue-parameter-277
fix: iftrue parameter for mp_binarycopy.  Closes #277
2022-07-07 11:29:25 +01:00
Allan Bowe
899b94bb6e fix: iftrue parameter for mp_binarycopy. Closes #277 2022-07-07 10:28:24 +00:00
Allan Bowe
d97efdff61 Merge pull request #276 from sasjs/allanbowe/syswarningtext-with-embedded-275
fix: escaping SYSWARNINGTEXT and SYSERRORTEXT for JSON response
2022-07-06 12:57:19 +01:00
Allan Bowe
1097afbcb8 fix: escaping SYSWARNINGTEXT and SYSERRORTEXT for JSON response
Closes #275
2022-07-06 11:55:15 +00:00
Allan Bowe
165b2d3568 Merge pull request #274 from sasjs/getpk
fix: enabling cross-compatibility of mp_getpk macro
2022-07-04 22:36:10 +01:00
Allan Bowe
44a80c8985 fix: enabling cross-compatibility of mp_getpk macro 2022-07-04 21:32:41 +00:00
Allan Bowe
6e32d9b743 Merge pull request #273 from sasjs/allanbowe/mp-jsonout-fails-in-meta-272
fix: setting length of label property in mp_jsonout
2022-07-04 13:27:02 +01:00
Allan Bowe
6b167e7a4c fix: longer label to allow for escapes 2022-07-04 12:26:19 +00:00
Allan Bowe
011672b1ed fix: setting length of label property in mp_jsonout 2022-07-04 12:24:53 +00:00
Allan Bowe
a7eb926810 Merge pull request #271 from sasjs/ms_getusers
fix: ensuring results when strict mode enabled in ms_getusers
2022-07-02 21:14:06 +01:00
Allan Bowe
cad7f13a0e fix: ensuring results when strict mode enabled in ms_getusers 2022-07-02 20:13:02 +00:00
Allan Bowe
65fcea817a Merge pull request #270 from sasjs/forcerelease
fix: forcing release for the previous fix
2022-07-01 00:17:11 +02:00
Allan Bowe
22fade13e7 fix: forcing release for the previous fix 2022-06-30 22:16:45 +00:00
Allan Bowe
7146310072 fix: missing ampersand 2022-06-30 22:06:27 +00:00
Allan Bowe
b7de1c25ec Merge pull request #269 from sasjs/jsonfix
fix: mX_webout macros in DEBUG mode had truncated json
2022-06-30 23:44:44 +02:00
Allan Bowe
f4c7f47ffe fix: mX_webout macros in DEBUG mode had truncated json
This was due to options obs=10 which affected new cross-encoding streaming technique
2022-06-30 21:41:10 +00:00
munja
cdf339d077 fix: reduce logging when debug is off 2022-06-29 20:09:00 +01:00
Allan Bowe
31702df19b Merge pull request #268 from sasjs/allanbowe/stored-process-returns-267
fix: removing endsas for 9.4m6+ WIN enviornments in mp_abort
2022-06-28 15:47:31 +02:00
Allan Bowe
cf0d1c0473 fix: removing endsas for 9.4m6+ WIN enviornments in mp_abort 2022-06-28 13:46:07 +00:00
Allan Bowe
1f369f9848 Merge pull request #266 from sasjs/latin9fixes
fix: writing utf-8 to _webout on windows in a latin9 session causes problems
2022-06-26 23:16:59 +02:00
munja
2372ff5f4f fix: writing utf-8 to _webout on windows in a latin9 session causes problems with subsequent (regular) put statements. The workaround is to write to a different file and stream it back to _webout. 2022-06-26 22:09:54 +01:00
Allan Bowe
6d0e34ba1d Merge pull request #265 from sasjs/binaryfix
enable file copy of files with an encoding that does not match session encoding
2022-06-26 17:14:25 +02:00
munja
7a69698178 fix: adding fileref options and an additional test for mp_binarycopy 2022-06-26 16:12:49 +01:00
Allan Bowe
532bf84e06 fix: mp_jsonout 2022-06-25 21:38:05 +00:00
Allan Bowe
e1afbc02c4 fix: enabling binary copy of files with encoding that does not match session encoding 2022-06-25 21:32:21 +00:00
Allan Bowe
756f00d88d chore: reduce blankspace in compiled streaming apps 2022-06-25 21:30:15 +00:00
Allan Bowe
b72e404d52 Merge pull request #264 from sasjs/allanbowe/add-sysencoding-to-webout-263
feat: adding sysencoding to SASJS and SAS9 server types
2022-06-25 15:16:13 +02:00
Allan Bowe
e31cdeef42 feat: adding sysencoding to SASJS and SAS9 server types
Not added for mv_webout (viya) as that is always UTF-8.  Closes #263
2022-06-25 13:11:14 +00:00
Allan Bowe
8a4e32cc27 chore: updating sasjsconfig 2022-06-21 21:33:33 +00:00
Allan Bowe
f285505b79 Merge pull request #262 from sasjs/allanbowe/mp-ds-cards-does-not-261
fix: special missing support in mp_ds2cards()
2022-06-21 19:37:51 +02:00
Allan Bowe
67f5c50300 fix: special missing support in mp_ds2cards() 2022-06-21 17:34:44 +00:00
Yury Shkoda
ce39e4f779 Merge pull request #260 from sasjs/pr-template
chore(template): added pull request template
2022-06-21 19:57:11 +03:00
Yury Shkoda
9c80f5664c chore(template): added pull request template 2022-06-21 19:51:23 +03:00
Allan Bowe
83466c001b Merge pull request #259 from sasjs/allanbowe/mp-jsonout-not-escaping-258
fix: escaping labels in mp_jsonout when showmeta=YES.  Closes #258
2022-06-21 16:16:07 +02:00
Allan Bowe
ad315be503 fix: escaping labels in mp_jsonout when showmeta=YES. Closes #258 2022-06-21 14:14:35 +00:00
Allan Bowe
c41ae2dcc8 fix: enabling sasjsprocessmode as global var in mp_abort
Also, reduced indentation
2022-06-18 13:11:35 +00:00
d9f8e92fac Merge pull request #257 from sasjs/userfeat
feat: filter mm_getusers on a particular user
2022-06-17 19:59:38 +02:00
Allan Bowe
d42ede15db fix: superq 2022-06-17 17:58:39 +00:00
Allan Bowe
08ea9f7c00 chore: all.sas 2022-06-17 17:55:28 +00:00
Allan Bowe
c327e1fc0d fix: apostrophes 2022-06-17 17:55:01 +00:00
Allan Bowe
02fddcf9a1 fix: removing pipes 2022-06-17 17:51:36 +00:00
Allan Bowe
4752bfbb05 fix: refactor xml 2022-06-17 17:47:34 +00:00
Allan Bowe
767ddd7add feat: filter mm_getusers on a particular user
This can be useful for extracting the uri of a metadata user
2022-06-17 17:03:25 +00:00
Allan Bowe
54a24ced83 fix: using sasjs username in mf_getuser() 2022-06-17 15:54:30 +00:00
Allan Bowe
57ae2981f1 Merge pull request #256 from sasjs/allanbowe/mp-abort-fails-on-windows-254
fix: superq() for sysprocessname
2022-06-17 15:29:22 +02:00
Allan Bowe
a3043ac685 fix: superq() for sysprocessname 2022-06-17 13:28:51 +00:00
Allan Bowe
2bdb90b0be Merge pull request #255 from sasjs/allanbowe/mp-abort-fails-on-windows-254
fix: handling embedded speechmarks in SYSPROCESSNAME.  Closes #254
2022-06-17 14:32:02 +02:00
Allan Bowe
2cd846d504 fix: handling embedded speechmarks in SYSPROCESSNAME. Closes #254 2022-06-17 12:30:40 +00:00
Allan Bowe
f593c7bec9 fix: returning user list (single user) in desktop mode in ms_getusers() 2022-06-17 07:52:39 +00:00
Allan Bowe
c8805db0b5 feat: filter for groups by user id in ms_getgroups 2022-06-17 07:46:51 +00:00
Allan Bowe
1eb6d8cec9 feat: enabling user list by group id as well as name 2022-06-17 07:16:57 +00:00
Allan Bowe
ed19ee03af Merge pull request #253 from sasjs/servergroups
feat: enabling group macros on sasjs/server
2022-06-16 13:40:36 +02:00
Allan Bowe
a1c931b5e6 fix: tests with new APIs are now passing 2022-06-16 11:37:31 +00:00
Allan Bowe
cb553a31ab fix: failing test for filtering groups for a particular user (api isn't ready yet) 2022-06-14 19:37:06 +00:00
Allan Bowe
557df272ff fix: using new user/by/username api in sasjs/server 2022-06-14 19:24:41 +00:00
Allan Bowe
0cb3c96c15 feat: enabling group macros on sasjs/server
This PR updates ms_getgroups with a user filter, and ms_getusers with a group filter. ms_adduser2group was also created to faciliate the necessary test(s).
2022-06-14 13:40:05 +00:00
Allan Bowe
1cb39d4d61 Merge pull request #252 from sasjs/allanbowe/ms-getgroups-fails-in-251
fix: creating empty table in desktop mode (ms_getgroups)
2022-06-11 21:30:03 +02:00
Allan Bowe
934b7d4f8a fix: creating empty table in desktop mode (ms_getgroups) 2022-06-11 19:29:21 +00:00
Allan Bowe
24c50cde56 fix: use options nobomfile for sasjs server mp_abort, also doc update in mf_existvarlist 2022-06-09 22:16:34 +00:00
Allan Bowe
055e8d2f13 fix: setting header in mp_abort for sasjs server 2022-06-07 14:01:54 +00:00
Allan Bowe
abfe7fe339 fix: no json wrapper in SASjs mode in mp_abort.sas 2022-06-07 11:28:59 +00:00
Allan Bowe
16ed91f6a9 fix: mp_abort on windows m6+ 2022-06-06 11:28:37 +00:00
Allan Bowe
67ba2a5286 fix: mp_abort on m6 win needs endsas 2022-06-03 17:45:27 +00:00
Allan Bowe
3d7f9b71e1 fix: hard abort in mm_getstpcode when the stp does not exist 2022-06-02 17:50:50 +00:00
Allan Bowe
1d972fad11 fix: using outref instead of outloc in mm_getstpcode invocation from mx_getcode 2022-05-31 22:42:40 +00:00
Allan Bowe
e23bc461c4 fix: mx_getcode platform support 2022-05-31 22:00:58 +00:00
Allan Bowe
28ed458b83 Merge pull request #250 from sasjs/allanbowe/mp-jsonout-needs-to-support-249
fix: enable reserved names in mp_jsonout.  Closes #249
2022-05-31 16:48:45 +03:00
Allan Bowe
827210e010 fix: enable reserved names in mp_jsonout. Closes #249 2022-05-31 13:48:09 +00:00
Allan Bowe
de2f32da36 Merge pull request #248 from sasjs/mm_createdataset_update
fix: cater for case of zero cols in mm_createdataset.sas
2022-05-31 14:02:13 +03:00
Allan Bowe
6fa0fc5dc6 fix: cater for case of zero cols in mm_createdataset.sas 2022-05-31 11:01:06 +00:00
Allan Bowe
73e3d9d419 Merge pull request #247 from sasjs/allanbowe/mp-abort-on-sasjs-server-246
fix: ensuring webout on abort, closes #246
2022-05-30 15:42:47 +03:00
Allan Bowe
5f2229e3d5 fix: ensuring webout on abort, closes #246 2022-05-30 12:38:34 +00:00
Allan Bowe
d19c4a517c chore: updated document header 2022-05-20 19:01:47 +00:00
munja
c47480f60c fix: space in dependencies 2022-05-20 12:55:39 +01:00
munja
295211bb72 fix: doc config and test-folders 2022-05-20 11:30:38 +01:00
Allan Bowe
818bc3cc2b Merge pull request #244 from sasjs/getcode
feat: creating new mx_ suite of macros!
2022-05-20 13:18:16 +03:00
munja
bb6111e2b3 fix: all.sas, readme, dependency issue and sasjsconfig file 2022-05-20 11:16:30 +01:00
munja
512f05c0b2 feat: creating new mx_ suite of macros!
also adding new mx_getcode macro
2022-05-19 22:02:19 +01:00
Allan Bowe
500fb8124f Merge pull request #243 from sasjs/resetoption
fix: resetoption
2022-05-19 14:28:56 +03:00
Allan Bowe
88ddba2a4b fix: runall 2022-05-19 11:27:39 +00:00
Allan Bowe
86f6d06b85 fix: update resetoption and adding test 2022-05-19 11:26:55 +00:00
Allan Bowe
1cefc0e7ee feat: adding check in mf_existfeature() for ability to proc export xlsx 2022-05-18 15:33:41 +00:00
munja
412182a022 fix: fileref option in ms_runstp 2022-05-17 22:27:39 +01:00
Allan Bowe
43b8ee1c7e Merge pull request #242 from sasjs/ms_getgroups
Two new sasjs/server macros and associated tests
2022-05-17 18:05:05 +03:00
Allan Bowe
83eea02240 chore: updating all.sas 2022-05-17 15:03:36 +00:00
Allan Bowe
a14e31804a chore: fix test 2022-05-17 15:01:28 +00:00
Allan Bowe
3fa639ebf7 fix: tests for ms_creategroup 2022-05-17 14:56:11 +00:00
Allan
ed11d44fe8 feat: ms_creategroup and ms_getgroups macros with associated tests 2022-05-17 14:40:38 +00:00
Allan
de4ea8888f fix: updating mp_ds2md to cope with tables with no columns 2022-05-17 14:34:33 +00:00
Allan
ea0a936871 fix: adding codespaces config 2022-05-17 14:34:10 +00:00
Allan Bowe
042987c91e Merge pull request #241 from sasjs/copyfolder_enhancement
feat: Adding copymax parameter
2022-05-17 11:55:52 +03:00
Allan Bowe
6669e74baa chore: running all.sas and updating docs 2022-05-17 08:55:02 +00:00
Ivor Townsend
906f9a139d feat: Adding copymax parameter 2022-05-17 08:53:06 +01:00
Allan Bowe
b31f960635 Merge pull request #240 from sasjs/allanbowe/error-the-function-md-239
fix: avoiding use of md5() in sysfunc().  Closes #239
2022-05-12 13:35:08 +03:00
Allan Bowe
1ed3cb31b5 fix: put wrapper 2022-05-12 10:17:37 +00:00
Allan Bowe
ca7c332f20 fix: avoiding use of md5() in sysfunc(). Closes #239 2022-05-12 10:14:19 +00:00
Allan Bowe
d587b44b34 Merge pull request #238 from sasjs/allanbowe/mp-filtercheck-does-not-237
Updates to filtercheck macro (and tests)
2022-05-11 15:46:02 +03:00
munja
e43aac972a fix: coretable.sas 2022-05-11 13:41:34 +01:00
munja
7dbe31b5d3 fix: ensuring tests passing on sas 9 2022-05-11 13:32:27 +01:00
Allan Bowe
1672c96340 fix: testing fixes 2022-05-10 21:36:16 +00:00
Allan Bowe
453aee2c1f fix: update to mp_filtercheck & tests for special missings 2022-05-10 20:58:52 +00:00
Allan Bowe
00abbdcd65 fix: switching to proc datasets for ddl indexes 2022-05-10 20:58:35 +00:00
Allan Bowe
88685dc585 chore: providing description for DDL folder in main.dox 2022-05-10 19:19:53 +00:00
Allan Bowe
cf8147d6ca fix: making base_ds parameter positional in mp_ds2cards 2022-05-10 19:18:19 +00:00
Allan Bowe
f28f6b1530 Merge pull request #236 from sasjs/allanbowe/error-data-set-sashelp-235
fix: conditional logic for mp_getconstraints, test also updated.  Closes #235
2022-05-10 18:00:20 +03:00
Allan Bowe
cb4ea71e81 fix: conditional logic for mp_getconstraints, test also updated. Closes #235 2022-05-10 14:59:31 +00:00
Allan Bowe
fe94d3781a Merge pull request #234 from sasjs/all-contributors/add-eltociear
docs: add eltociear as a contributor for code
2022-05-10 13:54:01 +03:00
Allan Bowe
7c17b39dad Merge pull request #233 from eltociear/patch-1
chore: fix typo in mddl_sas_cntlout.sas
2022-05-10 13:53:26 +03:00
Allan Bowe
73dab4c651 chore: updating all.sas 2022-05-10 10:53:05 +00:00
allcontributors[bot]
5d72843167 docs: update .all-contributorsrc [skip ci] 2022-05-10 10:52:36 +00:00
allcontributors[bot]
f43df47cff docs: update README.md [skip ci] 2022-05-10 10:52:35 +00:00
Ikko Ashimine
aaca26770b chore: fix typo in mddl_sas_cntlout.sas
accomodate -> accommodate
2022-05-10 19:41:31 +09:00
Allan Bowe
4a124d5bd8 Update README.md 2022-05-09 09:58:31 +01:00
Allan Bowe
03cd52a01a chore: readme update and removal of main.dox in .npmignore (to allow doxygen folder descriptions in downstream apps) 2022-05-08 17:37:05 +00:00
Allan Bowe
da79181b00 Merge pull request #232 from sasjs/allanbowe/update-headers-in-sasjs-231
fix: using latest sasjs headers, closes #231
2022-05-08 01:27:02 +03:00
Allan Bowe
a405104052 fix: using latest sasjs headers, closes #231 2022-05-07 22:25:49 +00:00
Allan Bowe
56fdaa65d2 Merge pull request #230 from sasjs/dttmfix
feat: mf_dttm macro and associated test
2022-05-07 21:12:33 +03:00
Allan Bowe
9d60c49c9f chore: incorrect dependency 2022-05-07 18:04:28 +00:00
Allan Bowe
380170d5ba chore: all.sas 2022-05-07 18:02:16 +00:00
Allan Bowe
4b450f2091 fix: implementation of mf_fmtddtm() 2022-05-07 18:02:00 +00:00
Allan Bowe
1b013fbf1c fix: rename to mf_fmtdttm() 2022-05-07 17:49:06 +00:00
Allan Bowe
bf7459bd2d feat: mf_dttm macro and associated test 2022-05-07 17:45:36 +00:00
Allan Bowe
1096db0846 Merge pull request #229 from sasjs/runtimeissues
Improving WPS compatibility
2022-05-03 18:48:18 +03:00
Allan Bowe
fc9b765246 chore: updating all.sas 2022-05-03 15:46:34 +00:00
Allan Bowe
4a8f7bb014 fix: all the fixings 2022-05-03 15:46:15 +00:00
Allan Bowe
e0469be0d8 feat: updating mf_getvarcount to allow filtering by column type 2022-05-03 15:24:22 +00:00
Allan Bowe
e9e576b5ec fix: forcing misstype to NULL in ms_webout where not supported 2022-05-02 23:17:11 +00:00
Allan Bowe
1a32d114f1 fix: conditional execution of mp_init() 2022-05-02 22:32:32 +00:00
Allan Bowe
94e83f6b8d fix: updating mf_existfeature for constraint check 2022-05-02 22:24:56 +00:00
Allan Bowe
35a6dede6f fix: enabling ms_testservice() without inputs 2022-05-02 13:56:22 +00:00
Allan Bowe
039ec397dd chore: local scoping vars in mp_testservice 2022-04-30 19:16:25 +00:00
Allan Bowe
dce4630eb8 Merge pull request #228 from sasjs/allanbowe/add-markdown-as-mime-227
feat: adding MARKDOWN support to `mp_streamfile()`
2022-04-30 18:58:54 +03:00
Allan Bowe
1e142f042b chore: improving docs 2022-04-30 15:58:00 +00:00
Allan Bowe
7caca2f139 chore: typo in docs 2022-04-30 15:56:36 +00:00
Allan Bowe
61556b2de8 feat: adding MARKDOWN support to mp_streamfile(), correcting Content-type case issue also 2022-04-30 15:53:59 +00:00
Allan Bowe
9e12409389 fix: fileref cleanup in SASJS mode for mp_testservice() 2022-04-29 19:18:03 +00:00
Allan Bowe
c8050f5a79 Merge pull request #226 from sasjs/allanbowe/mp-testservice-error-225
3 new macros and updates to several others.  Supporting sasjs/server and options lrecl=80
2022-04-28 23:58:40 +03:00
munja
cb4f71c7cd chore: all.sas generation 2022-04-28 21:47:42 +01:00
munja
a39f4e4eee fix: ensuring test passes for mfs_httpheader 2022-04-28 21:47:23 +01:00
munja
b525b4171d fix: updating ms_runstp to accept parameters and file inputs. Explicitly setting lrecl everywhere. Adding lrecl=80 as default in testinit.sas 2022-04-28 21:06:28 +01:00
munja
f2d80b3b63 feat: ms_testservice.sas macro for testing services on sasjs/server 2022-04-28 21:02:54 +01:00
munja
96dda87f37 chore: all.sas update 2022-04-28 21:01:41 +01:00
munja
3435509eec fix: avoiding lua compilation issues by setting wide enough lrecl 2022-04-28 20:57:44 +01:00
munja
42f2767129 fix: mac var and chop point issue in mp_chop.sas 2022-04-28 19:20:03 +01:00
munja
099a5f7840 fix: ms_createfile will now overwrite if existing 2022-04-28 11:17:25 +01:00
munja
c83ea705a2 fix: ensuring sufficient lrecl in mf_getuniquefilref 2022-04-27 23:04:55 +01:00
munja
9ea6c875f2 fix: fixing tests for mp_chop 2022-04-27 12:14:26 +01:00
Allan Bowe
0728f72c4f fix: adding mp_chop to mp_testservice (WIP) 2022-04-26 15:29:12 +00:00
Allan Bowe
a90a6f00cf chore: adding test for mp_chop() 2022-04-26 15:13:18 +00:00
Allan Bowe
f71e53af8d feat: mp_chop() macro 2022-04-26 15:07:31 +00:00
Allan Bowe
cc1b971e19 fix: setting blank value to 0 in mf_isint() 2022-04-26 14:04:54 +00:00
Allan Bowe
8484c752ed fix: wip - requires new mp_chop() macro to parse long JSON response 2022-04-25 22:19:46 +00:00
Allan Bowe
8bd31e6c97 fix: tests for ms_createwebservice and mp_createwebservice 2022-04-25 21:33:14 +00:00
Allan Bowe
f9b0f87f44 feat: ms_createwebservice macro (and update to build.py) 2022-04-25 21:14:12 +00:00
Allan Bowe
d7e9f10291 Merge pull request #224 from sasjs/issue223
feat: ms_createuser macro
2022-04-22 14:49:55 +03:00
munja
3edc3587b3 chore: running all.sas 2022-04-21 23:52:04 +01:00
munja
63bf00e28f fix: adding (and fixing) tests for ms_* macro suite 2022-04-21 23:51:47 +01:00
munja
6b2574947a feat: ms_getusers 2022-04-21 23:08:57 +01:00
munja
eb9027ecb6 feat: ms_createuser macro 2022-04-21 22:48:54 +01:00
Allan Bowe
2ad931a566 Merge pull request #222 from sasjs/allanbowe/the-ms-macros-are-not-221
fix: adding authentication to server macros.  Closes #221
2022-04-20 18:55:22 +03:00
Allan Bowe
cebe119304 fix: failing test (chagned response) 2022-04-20 15:53:44 +00:00
Allan Bowe
bd3082d7e3 chore: updating sasjsconfig 2022-04-20 15:45:37 +00:00
Allan Bowe
11da53f1cb fix: adding authentication to server macros. Closes #221 2022-04-20 15:41:36 +00:00
Allan Bowe
c4cb0b2395 Merge pull request #220 from sasjs/perf
fix: using findc instead of regex for faster parsing
2022-04-16 23:31:20 +03:00
munja
58614e9a3d fix: using findc instead of regex for faster parsing 2022-04-16 21:30:18 +01:00
Allan Bowe
c94c334c4b Merge pull request #219 from sasjs/issue218
fix: check 4 special chars b4 replacing. Closes #218
2022-04-16 22:44:35 +03:00
munja
3bf44405f8 chore: alignment 2022-04-16 20:37:47 +01:00
munja
db68a256cb fix: check 4 special chars b4 replacing. Closes #218 2022-04-16 20:33:21 +01:00
Allan Bowe
611fac6338 Merge pull request #217 from sasjs/bom
fix: avoid sending BOM marker to SASjs API
2022-04-14 21:32:25 +03:00
munja
ddd120bb75 fix: avoid sending BOM marker to SASjs API 2022-04-14 19:31:36 +01:00
Allan Bowe
0d75e0bad8 Merge pull request #216 from sasjs/cli-issue-1113
chore(dep): removed sasjs/core and bumped sasjs/cli
2022-04-14 18:25:17 +03:00
Yury Shkoda
ba8c4ac844 chore: Merge branch 'main' of https://github.com/sasjs/core into cli-issue-1113 2022-04-14 18:22:57 +03:00
Allan Bowe
6938a42896 Merge pull request #215 from sasjs/serverconfig
Change test server & update mx_webout() macros
2022-04-14 15:41:44 +03:00
munja
efff77c94e fix: mx_webout 2022-04-14 13:40:14 +01:00
Yury Shkoda
2b10cf6192 chore(dep): removed sasjs/core and bumped sasjs/cli 2022-04-14 14:55:43 +03:00
Allan Bowe
134b91f266 fix: avoiding running tests on viya 2022-04-14 11:14:35 +00:00
Allan Bowe
969f551e10 Merge pull request #214 from sasjs/cond
fix: adding cond/endcond to mp_ds2cards
2022-04-13 23:34:52 +03:00
munja
26623ba085 fix: adding cond/endcond to mp_ds2cards 2022-04-13 21:32:47 +01:00
Allan Bowe
8eb495890d Merge pull request #213 from sasjs/issue212
fix: ensuring indexes are picked up in mp_getpk().  Closes #212
2022-04-13 15:59:22 +03:00
munja
c1a30977f1 chore: removing serverurl 2022-04-13 13:58:55 +01:00
munja
9a6be61651 fix: ensuring indexes are picked up in mp_getpk(). Closes #212 2022-04-13 13:57:43 +01:00
Allan Bowe
388839039e Merge pull request #211 from sasjs/streamhtmlasfile
fix: send html as attachment rather than streamed content
2022-04-11 12:56:02 +03:00
Allan Bowe
e760a89a6a fix: send html as attachment rather than streamed content when mp_streamfile is used on all platforms 2022-04-11 09:54:07 +00:00
Allan Bowe
d2e30267e8 Merge pull request #210 from sasjs/nulfixes
fix: using regex special chars instead of hex constants in mp_jsonout
2022-04-07 11:53:37 +03:00
munja
190dbddfe3 fix: using regex special chars instead of hex constants in mp_jsonout 2022-04-07 09:52:56 +01:00
Allan Bowe
05e769794e Merge pull request #209 from sasjs/missref
fix: avoid: ERROR: Variable "fref" may not be initialized
2022-04-06 18:26:45 +03:00
munja
558ebaf6f2 fix: avoid: ERROR: Variable "fref" may not be initialized 2022-04-06 16:25:50 +01:00
Allan Bowe
970b56fe5a Merge pull request #208 from sasjs/issue207
fix: removing LUA dependency from mv_webout to enable Viya 4 compatibility
2022-04-01 20:42:22 +03:00
munja
c2597bd07b fix: missing dependency in mp_hashdataset.test.sas 2022-04-01 17:29:06 +01:00
munja
c4baca477b fix: removing LUA dependency from mv_webout to enable Viya 4 compatibility 2022-04-01 16:56:49 +01:00
Allan Bowe
7726b0e0b0 Merge pull request #206 from sasjs/ms_getfile
fix: ensuring ms_getfile works on specific installs
2022-03-29 20:41:20 +03:00
munja
0a536245f3 fix: missing dependency in mp_hashdataset.test.sas 2022-03-29 18:40:58 +01:00
munja
edfa9ecc07 fix: ensuring ms_getfile works on specific installs 2022-03-29 18:08:24 +01:00
munja
f4982c85ca fix: adding nonote2err option on mp_hashdataset 2022-03-29 15:00:33 +01:00
Allan Bowe
3ce771d587 Merge pull request #205 from sasjs/issue204
fix: updating mp_hashdataset to cope with STRICT mode.  Adding test a…
2022-03-29 15:47:17 +03:00
munja
72d6b446c3 fix: updating mp_hashdataset to cope with STRICT mode. Adding test and improving sasjs/server compatibility. 2022-03-29 13:22:24 +01:00
Allan Bowe
40d694eec8 Merge pull request #203 from sasjs/invisibles
fix: support SOH, STX and DC1 control characters in mp_jsonout
2022-03-29 12:02:09 +03:00
munja
6af1423666 fix: more invisibles 2022-03-28 16:26:58 +01:00
munja
23a01347f1 fix: support SOH, STX and DC1 control characters in mp_jsonout 2022-03-28 15:54:28 +01:00
Allan Bowe
7c86d6163a Merge pull request #201 from sasjs/mm_assignlib_fix
fix: enabling more descriptive mm_assignlib abort messages when library cannot be assigned
2022-03-21 18:10:56 +02:00
munja
d7233208f1 fix: enabling more descriptive mm_assignlib abort messages when library cannot be assigned 2022-03-21 16:07:27 +00:00
Allan Bowe
7f587ba720 Merge pull request #200 from sasjs/server
fix: headers in ms_createfile.sas
2022-03-19 02:23:57 +02:00
munja
21ecc1b675 fix: headers in ms_createfile.sas 2022-03-19 00:20:05 +00:00
Allan Bowe
6b13dc2b87 Merge pull request #199 from sasjs/server
fix: missing dependency in mv_deleteviyafolder
2022-03-16 18:07:40 +02:00
munja
bb89184212 fix: missing dependency in mv_deleteviyafolder 2022-03-16 16:01:22 +00:00
Allan Bowe
56338caaca Merge pull request #198 from sasjs/server
feat: enabling delete file for sasjs/server
2022-03-15 17:41:24 +02:00
munja
d7e2ff8ac9 fix: diffs for format loads not showing in audit table 2022-03-15 15:20:25 +00:00
munja
582ec0a1f9 feat: enabling delete file for sasjs/server 2022-03-15 13:46:31 +00:00
Allan Bowe
53785f5644 Update README.md 2022-03-14 13:44:13 +00:00
Allan Bowe
a8acadb8f1 Merge pull request #197 from sasjs/devops
gitpod & git hook updates
2022-03-11 23:25:20 +02:00
Allan Bowe
23dbda302e fix: ensuring pre-commit fails when sasjs lint fails 2022-03-11 21:24:34 +00:00
Allan Bowe
7e7ab4275d fix: gitpod launching sasjs 2022-03-11 21:23:52 +00:00
Allan Bowe
a455a3d98d Merge pull request #196 from sasjs/delfile
feat: adding new mf_deletefile macro (and test)
2022-03-11 17:20:34 +02:00
munja
588d987c25 fix: missing dependency in test 2022-03-11 15:14:54 +00:00
munja
8ffd06343a feat: adding new mf_deletefile macro (and test)
Also, update to mm_spkexport macro
2022-03-11 15:03:59 +00:00
Allan Bowe
76207c443c Merge pull request #195 from sasjs/issue194
fix: supporting empty dirs in mp_dirlist. Test updated.
2022-03-11 14:28:31 +02:00
munja
7e9e0fac07 fix: supporting empty dirs in mp_dirlist. Test updated. 2022-03-11 11:28:03 +00:00
Allan Bowe
1fdbc7cce9 Merge pull request #193 from sasjs/mm_spkexport
feat: ignorevars option in mm_spkexport, and log update in mf_verifymacvars
2022-03-10 19:28:50 +02:00
munja
312369b200 feat: ignorevars option in mm_spkexport, and log update in mf_verifymacvars 2022-03-10 17:27:30 +00:00
Allan Bowe
c030174bfb Merge pull request #192 from sasjs/bugfix
fix: dependency in mp_loadformat test and strict mode issue in mm_deletelibrary
2022-03-09 16:16:32 +02:00
munja
faf466e79a fix: dependency in mp_loadformat test and strict mode issue in mm_deletelibrary 2022-03-09 14:15:25 +00:00
Allan Bowe
856ffc1b72 Merge pull request #191 from sasjs/allanbowe/mp-loadformat-not-appending-190
fix: ensuring audit table gets loaded in mp_loadformat.
2022-03-08 21:50:42 +02:00
munja
c0924af06b fix: correcting test for mp_loadformat 2022-03-08 19:50:01 +00:00
munja
33cec61a13 fix: quoting mf_getuser in case of commas. Fixes #189 2022-03-08 19:40:22 +00:00
munja
854ff696d8 fix: adding missing dependency in mp_loadformat 2022-03-08 19:33:46 +00:00
Allan Bowe
cc3435d13d fix: ensuring audit table gets loaded in mp_loadformat. Adding test also. Closes #190 2022-03-08 16:52:22 +00:00
Allan Bowe
5ceaac195d Merge pull request #188 from sasjs/hex32
fix: adding explicit $ sign to hex32. format in mp_md5() macro
2022-03-07 22:38:57 +02:00
Allan Bowe
5d5df977a6 fix: adding explicit $ sign to hex32. format in mp_md5() macro 2022-03-07 19:57:25 +00:00
Allan Bowe
245e85ef36 Merge pull request #187 from sasjs/periodproblem
fix: mp_replace and mv_getjobcode were not ingesting periods correctly
2022-03-07 16:27:14 +02:00
munja
b96df6f14f fix: mp_replace and mv_getjobcode were not ingesting periods correctly 2022-03-07 14:25:05 +00:00
Allan Bowe
1932c1e138 Merge pull request #186 from sasjs/issue185
Issue185
2022-03-07 12:45:18 +02:00
munja
f7ee012be3 fix: updating all.sas 2022-03-07 10:45:06 +00:00
munja
b49e11bc79 fix: upgrading mv_deleteviyafolder for viya 4 (and adding test) 2022-03-07 09:36:30 +00:00
munja
f709a11dfb fix: removing lua dependency from mv_getjoblog to enable viya 4 2022-03-06 22:04:51 +00:00
munja
17ed2240d3 fix: removing lua from mv_getjobcode to enable Viya 4 compatibility 2022-03-06 21:01:02 +00:00
munja
a8b5107b1a fix: remove mcf_stpsrv_header function (no longer needed, replaced with mfs_httpheader which is more reliable and faster 2022-03-06 13:44:42 +00:00
munja
735bab5d26 feat: viya4 config 2022-03-06 13:44:16 +00:00
Allan Bowe
86f7876f50 Merge pull request #184 from sasjs/issue181
feat: ms_getfile service (and test).  Closes #181
2022-03-06 14:40:59 +02:00
munja
46c96bc7ec feat: ms_getfile service (and test). Closes #181 2022-03-06 12:40:03 +00:00
Allan Bowe
cba3f5972b Merge pull request #183 from sasjs/feature/mf_getuniquelibref_safe_default
fix: Closes #182 - update to mf_getuniquelibref.sas
2022-03-04 12:20:54 +02:00
Allan Bowe
ed48c49964 fix: adding tests for mf_getuniquelibref and mentioning deprecated param in README. Also regenerating all.sas 2022-03-04 08:37:29 +00:00
trmoody
203ff3f80d chore: amended comment 2022-03-04 01:26:58 +00:00
trmoody
cfe90a8d0d chore: update to mf_getuniquelibref.sas 2022-03-04 00:38:07 +00:00
Allan Bowe
0749ea0819 Merge pull request #179 from sasjs/173-disable-dependence-on-io-(gsub)-package
New `mp_replace()` macro to find & replace in text files
2022-03-03 15:19:04 +02:00
munja
e09a39e748 fix: tests 2022-03-03 13:18:11 +00:00
Allan Bowe
20dcefaefd Merge pull request #180 from sasjs/all-contributors/add-yabwon
docs: add yabwon as a contributor for code
2022-03-03 15:17:16 +02:00
allcontributors[bot]
4c8347516a docs: update .all-contributorsrc [skip ci] 2022-03-03 13:16:32 +00:00
allcontributors[bot]
e497d226a0 docs: update README.md [skip ci] 2022-03-03 13:16:31 +00:00
munja
ccf8f1acc0 fix: adding test and updating documentation 2022-03-03 12:46:00 +00:00
munja
fe9a2ed979 feat: mp_replace macro, credit Bartosz 2022-03-03 10:30:07 +00:00
munja
078815e83e chore: stub 2022-03-02 21:33:41 +00:00
Allan Bowe
bb80c7af5a chore: adding funding.yml 2022-03-01 19:24:27 +00:00
Allan Bowe
842662aae1 Merge pull request #172 from sasjs/serverupdates
fix: updating mp_streamfile for sasjs/server compatibility
2022-02-28 23:21:48 +02:00
munja
876fac2332 feat: several macros for working with the sasjs/server apis 2022-02-28 21:17:38 +00:00
Allan Bowe
427deca350 Merge pull request #178 from sasjs/allanbowe/enable-consul-token-as-177
feat: adding consul_token option as parameter in mv_registerclient.
2022-02-24 23:20:03 +02:00
Allan Bowe
07bde4b25c feat: adding consul_token option as parameter in mv_registerclient. Closes #177 2022-02-24 21:16:23 +00:00
Allan Bowe
80b06af581 Merge pull request #176 from sasjs/streamserver
feat: adding SASjs server support to mp_streamfile.sas
2022-02-23 19:02:37 +02:00
Allan Bowe
3c026811e9 feat: adding SASjs server support to mp_streamfile.sas 2022-02-23 17:01:50 +00:00
Allan Bowe
cf547ce7e4 Merge pull request #175 from sasjs/authbranch
fix: tidyup of mm_getauthinfo.sas
2022-02-23 11:43:33 +02:00
Allan Bowe
6952c79899 fix: tidyup of mm_getauthinfo.sas 2022-02-23 09:42:47 +00:00
Allan Bowe
09e3f63da7 Merge pull request #174 from sasjs/stpabortissue
fix: missing dependency in mm_createstp
2022-02-22 13:47:05 +02:00
Allan Bowe
d6956f4122 fix: missing dependency in mm_createstp 2022-02-22 11:46:31 +00:00
Allan Bowe
6fca73e7da fix: adding content type to SASjs server webout response 2022-02-21 00:31:14 +00:00
Allan Bowe
880df4138c fix: removing wrapper for sasjs webout 2022-02-21 00:26:03 +00:00
munja
badf5b5761 fix: updating mp_streamfile for sasjs/server compatibility 2022-02-18 22:22:52 +00:00
Allan Bowe
b174aa25b3 Merge pull request #171 from sasjs/httpheader
feat: new httpheader macro (and test) for sasjs/server
2022-02-16 18:25:41 +02:00
Allan Bowe
bc6eac6977 Merge pull request #170 from sasjs/dependabot/npm_and_yarn/follow-redirects-1.14.8
chore(deps): bump follow-redirects from 1.14.7 to 1.14.8
2022-02-16 18:25:26 +02:00
munja
2d4d595e5d feat: new httpheader macro (and test) for sasjs/server 2022-02-16 16:21:00 +00:00
dependabot[bot]
7111fe14fb chore(deps): bump follow-redirects from 1.14.7 to 1.14.8
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 04:41:55 +00:00
Allan Bowe
8499e38c55 Merge pull request #169 from sasjs/mp_cntlout
feat: new mp_cntlout.sas macro
2022-02-11 17:46:39 +02:00
munja
682d80b1b8 fix: warning in mp_getformats 2022-02-11 16:46:04 +01:00
munja
4fe6f233f2 chore: updating all.sas 2022-02-11 15:47:33 +01:00
munja
6ba3588eff feat: new mp_cntlout.sas macro 2022-02-11 14:22:38 +01:00
Allan Bowe
53aa403630 Merge pull request #168 from sasjs/loadformat
feat: new mp_loadformat macro
2022-02-10 15:46:20 +02:00
munja
cba9255732 feat: mp_loadformat macro (and test) 2022-02-10 14:08:19 +01:00
munja
a7b78c73c4 chore: adding mprintnest in debug mode in testinit.sas 2022-02-09 22:07:30 +01:00
munja
85e0b6a4a9 fix: upcasing vars in mp_assertscope 2022-02-09 22:07:03 +01:00
munja
3c7e762eeb fix: support for SASJS server type in mf_getplatform and mp_streamfile 2022-02-09 22:06:24 +01:00
munja
9a1f7d0985 feat: new macro (mp_md5) for calculating an md5 hash of a set of columns 2022-02-09 21:56:46 +01:00
munja
dfd60200fb chore(docs): removing invalid example 2022-02-08 23:23:13 +01:00
Allan Bowe
713f7544cd Merge pull request #167 from sasjs/issue166
feat: adding mddl_xx series of macros (and tests).  Closes #166
2022-02-07 15:42:01 +02:00
munja
de4e96ab01 fix: dependency under wrong header in mp_getformats 2022-02-07 14:41:32 +01:00
munja
3e7b15c7db feat: adding mddl_xx series of macros (and tests). Closes #166 2022-02-07 14:14:25 +01:00
Allan Bowe
eb2ccfbbca Merge pull request #165 from sasjs/fmtstore
feat: adding format catalog capability to mp_filterstore
2022-02-07 00:02:34 +02:00
munja
70e508e583 fix: failing test 2022-02-06 23:01:46 +01:00
munja
8b0acf2eae feat: adding format catalog capability to mp_filterstore 2022-02-06 22:12:00 +01:00
Allan Bowe
d254870439 Merge pull request #164 from sasjs/mf_verify
fix: updating mm_x macros following fix to mf_verifymacvars
2022-02-06 20:58:55 +02:00
munja
303225cb85 fix: updating mm_x macros following fix to mf_verifymacvars 2022-02-06 19:57:52 +01:00
Allan Bowe
90de167643 Merge pull request #163 from sasjs/mf_verfiy
fix: updating mf_abort param in mf_verifymacvars, also fixing return …
2022-02-06 17:16:54 +02:00
munja
8ee997de8e fix: updating mf_abort param in mf_verifymacvars, also fixing return code as per documentation, adding a test, and updating the header info 2022-02-06 16:11:18 +01:00
Allan Bowe
e27f6ac716 Merge pull request #162 from sasjs/mf_getapploc
fix: adding support for testsetup and testteardown in mf_getapploc.sas
2022-02-05 22:56:10 +02:00
munja
ec4de95fcf fix: reset syscc for testterm syscc check 2022-02-05 21:55:50 +01:00
munja
df0fa95519 fix: adding sasjs/core dependency - see: https://github.com/sasjs/cli/issues/1113 2022-02-05 21:29:03 +01:00
munja
2fe7fba79b fix: adding support for testsetup and testteardown in mf_getapploc.sas 2022-02-05 21:19:26 +01:00
Allan Bowe
e40234ee29 Merge pull request #160 from sasjs/allanbowe-patch-1
chore(docs): Update README.md to clarify LUA prefixes
2022-02-04 20:56:51 +02:00
Allan Bowe
a287cc27a7 Update README.md 2022-02-04 18:56:19 +00:00
munja
921186eb74 fix: adding images to mp_streamfile.sas 2022-02-03 20:17:43 +01:00
munja
6fd215ceff fix: streaming output in mp_streamfile by default (eg when param not found) 2022-02-03 20:13:57 +01:00
Allan Bowe
0297509aa0 Merge pull request #159 from sasjs/woff3
fix: avoiding error and including test in mp_streamfile.sas
2022-02-03 20:59:11 +02:00
munja
c5a8bc745d chore: fix test 2022-02-03 19:58:12 +01:00
munja
36aa466561 fix: avoiding error and including a test 2022-02-03 19:44:21 +01:00
Allan Bowe
009485e5b9 Merge pull request #158 from sasjs/woff2
fix: support for WOFF2 and TTF
2022-02-03 19:51:39 +02:00
munja
eb01c8772d fix: support for WOFF2 and TTF 2022-02-03 18:51:07 +01:00
Allan Bowe
e3fb69928c Merge pull request #157 from sasjs/dependabot
chore: adding dependabot
2022-02-03 19:31:16 +02:00
munja
65afa14466 chore: removing leading spaces 2022-02-03 18:30:49 +01:00
munja
0176b19616 chore: adding dependabot 2022-02-03 18:29:31 +01:00
Allan Bowe
9f3dfd9a59 Merge pull request #156 from sasjs/csv
adding WOFF to mp_streamfile
2022-02-03 19:23:09 +02:00
munja
513ea354ab chore: updating headers in mp_streamfile and running all.sas 2022-02-03 16:45:42 +01:00
munja
7b686e11c9 feat: adding WOFF support to mp_streamfile (also re-ordering sections alphabetically) 2022-02-03 16:44:39 +01:00
munja
3997000266 fix: encoding issue in mp_ds2csv (option should have been in quotes) 2022-02-03 15:00:46 +01:00
Allan Bowe
6e177d4cae Merge pull request #155 from sasjs/cmplib
fix: auto-detect cmplib in mcfxx funcs, mp_ds2csv supports dates etc,…
2022-02-02 23:43:43 +02:00
munja
3554991ff8 fix: auto-detect cmplib in mcfxx funcs, mp_ds2csv supports dates etc, fix to mp_abort in viya due to abort cancel FILE hard stop (according to docs it should continue outside of the include) 2022-02-02 21:18:51 +01:00
Allan Bowe
58d2d6382a Merge pull request #154 from sasjs/errtext
fix: removing syserrortext as it breaks when commas are embedded
2022-02-02 21:36:30 +02:00
Allan Bowe
67f28a366c fix: removing syserrortext as it breaks when commas are embedded 2022-02-02 19:35:54 +00:00
Allan Bowe
64f53acce2 Merge pull request #153 from sasjs/mcf_fmtclass
Mcf fmtclass
2022-02-01 19:50:36 +02:00
munja
2e790f69a1 fix: removing view due to potential for vbufsize violations 2022-02-01 16:14:37 +01:00
munja
e62011d97e chore: updating variable name to fit doc header 2022-02-01 13:52:08 +01:00
munja
cd8d16d09f chore: updating all.sas 2022-02-01 13:48:48 +01:00
munja
9c61965d4b feat: new macro (mcf_getfmttype) to determine the type (DATE,DATETIME,TIME,CHAR,NUM) of a SAS format 2022-02-01 13:48:23 +01:00
Allan Bowe
61b8cb5dea Merge pull request #152 from sasjs/mp_ds2fmit
feat: enabling leading blanks in mp_ds2csv.
2022-01-30 20:00:28 +02:00
munja
899f6d9558 fix: updates following test results 2022-01-30 18:34:29 +01:00
munja
899de27617 feat: enabling leading blanks in mp_ds2csv. Also tests for mp_ds2csv and mp_testervice.sas, and strict mode fixes elsewhere 2022-01-30 15:41:39 +01:00
Allan Bowe
322c488e72 Merge pull request #151 from sasjs/allanbowe-patch-1
Update README.md
2022-01-29 22:44:52 +02:00
Allan Bowe
5d5e66a1c5 Update README.md 2022-01-28 16:49:20 +00:00
munja
5f4e9d541d chore(docs): updating md table in mp_stackdiffs docs 2022-01-25 17:55:34 +01:00
munja
306ea93be2 chore(docs): removing WIP marker 2022-01-25 17:25:53 +01:00
Allan Bowe
3fd83a3160 Merge pull request #145 from sasjs/issue144
Issue144
2022-01-25 18:23:55 +02:00
munja
56c1397547 fix: incorrect test logic 2022-01-25 17:01:49 +01:00
munja
90adf8dcdd fix: updating tests per https://github.com/sasjs/cli/issues/1101 2022-01-25 16:28:47 +01:00
munja
6e0fe0ff25 fix: test cases in mp_stackdiffs.test.sas 2022-01-25 13:50:29 +01:00
munja
794ceec33c fix: updating test cases 2022-01-25 12:45:32 +01:00
munja
11d073c10a fix: comma placement in mp_stackdiffs.sas 2022-01-25 00:49:26 +01:00
munja
c160b5058b fix: comma placement in mp_stackdiffs.sas 2022-01-25 00:30:28 +01:00
munja
2f49738cf9 fix: issue with mf_getfilesize.sas test 2022-01-25 00:08:00 +01:00
munja
bfe4b1ec8b fix: removing warning from mf_wordsinstr1xxx macros, compiling all.sas, fixing MOD changes in mp_stackdiffs.sas 2022-01-25 00:04:54 +01:00
munja
6224844915 feat: new mcf_init.sas macro to handle function compilation tracking (and associated test). Further updates to support mp_stackdiffs test results so far 2022-01-24 23:29:43 +01:00
munja
81a17bc0c2 chore(merge): merging with v4
Merge branch 'main' into issue144
2022-01-24 15:34:50 +01:00
Allan Bowe
f4c2be7411 Merge pull request #150 from sasjs/mp_ds2squeeze
sasjs/core - v4
2022-01-24 15:16:37 +02:00
munja
16489a9494 fix: missing macro dependency in mp_ds2squeeze.test.sas 2022-01-24 13:12:31 +01:00
munja
0e03b06a4b fix: adjustments to ensure the tests work, also building all.sas 2022-01-24 12:53:36 +01:00
munja
c3b89c7f7d feat: mp_ds2squeeze macro 2022-01-24 11:17:21 +01:00
munja
142b46570d feat: adding mcf_length to mp_getmaxvarlengths
BREAKING CHANGE: mp_getmaxvarlengths now returns 0 for non-special missings, and will use numeric length (as opposed to cast-to-character length) by default
2022-01-23 23:26:10 +01:00
munja
f7fac50108 fix: removing deprecated functionality ahead of planned breaking change 2022-01-22 21:16:15 +01:00
munja
f7078957cf chore(merge): merging with main 2022-01-22 19:48:03 +01:00
munja
f258d4f2f1 fix: tests 2022-01-22 19:47:24 +01:00
Allan Bowe
ae5fbcf857 Merge pull request #149 from sasjs/mcf_length
feat: new mcf_length.sas fcmp macro
2022-01-22 19:32:49 +02:00
Allan Bowe
2579b4c929 feat: new mcf_length.sas fcmp macro 2022-01-22 17:16:08 +00:00
munja
b69c3b7a78 feat: modification for mp_stackdiffs.sas and associated tests 2022-01-21 13:59:54 +01:00
munja
67df4dffeb fix: mp_stackdiffs.sas - case when base records are missing, plus tests 2022-01-21 12:19:34 +01:00
munja
9cf2cc3c96 fix: adding test and data logic for re-applying modified records where base table has missing vars 2022-01-21 11:51:47 +01:00
munja
dd94215c3b fix: more tests for add process 2022-01-20 23:11:27 +01:00
munja
1fd1a8e7ce fix: updating mp_stackdiffs with addition module & tests 2022-01-20 23:05:59 +01:00
Allan Bowe
90a831f59b Merge pull request #148 from sasjs/outcat
fix: renaming outcat to outlib for wider compatibility
2022-01-20 11:34:45 +02:00
Allan Bowe
9fb218f0be fix: renaming outcat to outlib for wider compatibility 2022-01-20 09:14:11 +00:00
munja
bdd22abc55 feat: adding delete capability (and tests) for mp_stackdiffs 2022-01-19 22:05:56 +01:00
munja
75f712a305 chore(docs): assertscope 2022-01-19 10:55:52 +01:00
munja
e3991c46e2 chore: merging with main 2022-01-18 20:14:19 +01:00
Allan Bowe
ccc9dfa4aa Merge pull request #147 from sasjs/allanbowe/macro-scope-test-assertion-146
feat: adding mp_assertscope.sas, closes #146.
2022-01-18 20:46:29 +02:00
Allan Bowe
a37a72b7db feat: adding mp_assertscope.sas, closes #146. Also adding test for mp_assert.sas 2022-01-18 18:24:53 +00:00
munja
724d3b91a0 feat: adding ignore_cols (and mdebug) parameters to mp_guesspk.sas, as well as a code tidy up 2022-01-17 10:45:43 +01:00
munja
887c797e13 chore(docs): adding favicon and title. Thanks, Stuart Walsh 2022-01-16 22:39:50 +01:00
munja
0fd1e470e8 feat: initial header for mp_stackdiffs. Introduces a dependency on DOT (graphviz) for doc generation. 2022-01-14 20:32:03 +01:00
munja
13ecab8390 fix: removing unnecessary mp_abort 2022-01-14 20:31:31 +01:00
munja
15d9db822b chore: updating docs 2022-01-14 20:31:08 +01:00
munja
dd355d1ddf chore(gitpod): updating yaml files 2022-01-14 20:30:00 +01:00
Allan Bowe
c6dcf919e2 Merge pull request #143 from sasjs/issue142
feat: ensuring mX_webout services run without MEMSIZE, closes #142.
2022-01-12 22:46:51 +02:00
munja
42541373af chore: running all.sas 2022-01-12 21:25:15 +01:00
munja
208c88f5a4 feat: ensuring mX_webout services run without MEMSIZE, closes #142. Also adding note2err in mp_init(). 2022-01-12 21:23:42 +01:00
Allan Bowe
5605bc74df Merge pull request #141 from sasjs/dirlistfix
fix: dirlist logic
2022-01-11 12:13:01 +02:00
munja
4bec574011 fix: dirlist logic 2022-01-11 11:06:38 +01:00
Allan Bowe
8cfa37ce8b Merge pull request #140 from sasjs/fix_dirlist
fix: proc append warnings for file attributes
2022-01-11 11:35:43 +02:00
Allan Bowe
351ceeb357 fix: tidy up 2022-01-10 18:42:52 +00:00
Ivor Townsend
259bcc0173 fix: proc append warnings for file attributes 2022-01-10 16:49:33 +00:00
Ivor Townsend
db195a8311 fix: proc append warnings for file attributes 2022-01-10 16:33:44 +00:00
munja
4307bfb1b5 fix: adding showmeta option to mX_createwebservce macros 2022-01-09 13:18:14 +01:00
Allan Bowe
df46ee6939 Merge pull request #139 from sasjs/webout_mac
feat: adding SHOWMETA option to mp_jsonout
2022-01-07 15:29:06 +02:00
munja
70b9b71104 fix: base table on mp_lockanytable.test.sas 2022-01-07 14:12:08 +01:00
munja
cd33355418 fix: formats 2022-01-07 13:14:40 +01:00
munja
77d1cdb753 feat: adding length to mp_webout meta 2022-01-07 12:23:40 +01:00
munja
545218e3b9 fix: avoiding type clash 2022-01-06 23:44:42 +01:00
munja
cb07305a87 feat: adding SHOWMETA option to mp_jsonout
Includes updates to associated wrapper macros, and a 30% performance improvement (for small tables).  Addresses https://github.com/sasjs/adapter/issues/607
2022-01-06 23:36:54 +01:00
Allan Bowe
76a39cad20 Merge pull request #138 from sasjs/webout_mac
fix: adding missing param to mx_createwebservice macros
2021-12-30 16:29:50 +02:00
munja
ebd567af48 fix: adding missing param to mx_createwebservice macros 2021-12-30 09:53:08 +00:00
Allan Bowe
a9c418e3f2 Merge pull request #137 from sasjs/specials
feat: updating mp_jsonout() to support special missing numeric values.
2021-12-30 11:43:00 +02:00
munja
e143acd67d chore: automated commit 2021-12-30 00:30:14 +00:00
munja
84eb2f1845 chore: automated commit 2021-12-30 00:29:48 +00:00
munja
b075e5d5d5 feat: updating mp_jsonout() to support special missing numeric values. Closes #136 2021-12-30 00:21:02 +00:00
Allan Bowe
a08f6aeea2 Merge pull request #135 from sasjs/abortfix
fix: removing 'Log Extract' from abort MSG in mp_abort when not capturing the log
2021-12-29 14:54:01 +02:00
munja
469bd574ac fix: removing 'Log Extract' from abort MSG in mp_abort when not capturing the log 2021-12-29 12:35:25 +00:00
Allan Bowe
c41918c0a8 Merge pull request #134 from sasjs/fmtfix
fix: preventing error when mp_applyformats has no formats to apply
2021-12-29 14:19:59 +02:00
munja
0361ca574d fix: preventing error when mp_applyformats has no formats to apply 2021-12-29 12:19:34 +00:00
Allan Bowe
c75c169b80 Merge pull request #133 from sasjs/fmtname
fix: adding fmtname to mp_getcols() macro
2021-12-28 15:39:07 +02:00
munja
eac47bd5db fix: adding fmtname to mp_getcols() macro 2021-12-28 13:25:53 +00:00
munja
d302ef266d chore: doc page formatting & content 2021-12-27 11:54:46 +00:00
munja
fdfe9b8250 fix: enabling further debugging in mp_filterstore.sas 2021-12-26 20:32:56 +00:00
munja
9b1f0d7bcb fix: avoiding append warning: syswarningtext=Variable processed_dttm has format DATETIME19. on the BASE data set and format E8601DT26. on the DATA data set. 2021-12-26 16:27:04 +00:00
Allan Bowe
98b1c44283 Merge pull request #131 from sasjs/mp_filterstore
feat: mp_filterstore macro
2021-12-26 17:28:45 +02:00
munja
ce026f19b5 feat: new mp_filterstore macro 2021-12-26 15:06:06 +00:00
munja
8e723d06b0 feat: mp_filterstore macro 2021-12-26 01:06:56 +00:00
Allan Bowe
a6d84cc65a Merge pull request #130 from sasjs/newvalidation
feat: new macro (mp_retainedkey) for adding retained key values to a …
2021-12-25 22:37:43 +02:00
munja
536ce8e95d feat: new macro (mp_retainedkey) for adding retained key values to a staging table 2021-12-25 20:21:32 +00:00
Allan Bowe
bc1d9e619b Merge pull request #129 from sasjs/newvalidation
feat: new validation (ISINT) in the mp_validatecol.sas macro
2021-12-25 00:19:50 +02:00
munja
1062a97cfe feat: new validation (ISINT) in the mp_validatecol.sas macro - https://core.sasjs.io/mp__validatecol_8sas_source.html 2021-12-24 22:02:23 +00:00
Allan Bowe
51db64c90a Merge pull request #128 from sasjs/writefile
Writefile
2021-12-23 22:13:20 +02:00
munja
7c4278c3f9 chore: updating all.sas 2021-12-23 19:29:54 +00:00
munja
6c6b55dcea chore: updating header, adding stop statement in mp_makedata(), writing test for mf_existvar() 2021-12-23 19:29:37 +00:00
munja
66b0c9e77e feat: new mf_writefile() macro 2021-12-23 19:29:01 +00:00
Allan Bowe
caf3b95269 Merge pull request #126 from sasjs/applyformats
Applyformats
2021-12-23 16:15:09 +02:00
munja
3866b97416 chore: updating doc header 2021-12-23 13:55:53 +00:00
munja
d687658687 chore: updating all.sas 2021-12-23 13:51:11 +00:00
munja
9f815c73e9 feat: new mp_applyformats macro (and test), plus new addition to mp_validatecol (is_format) 2021-12-23 13:50:58 +00:00
Allan Bowe
a13c782074 Merge pull request #125 from sasjs/makedata
`mp_makedata()` improvements
2021-12-23 13:11:36 +02:00
munja
f2991cfd63 fix: enabling makedata support for charvars > and tables without primary keys. Also added tests. 2021-12-23 10:56:01 +00:00
Allan Bowe
8eb4f0844c Merge pull request #124 from sasjs/updates
feat: mf_islibds() macro to test if a library.dataset reference is valid
2021-12-22 17:28:22 +02:00
munja
f90dc069dc feat: update to makedata to respect primary keys (and enable joins to other tables) 2021-12-22 15:12:10 +00:00
munja
436b430389 feat: mf_islibds() macro to test if a library.dataset reference is syntactically valid 2021-12-22 11:23:57 +00:00
Allan Bowe
6667b91ced Merge pull request #123 from sasjs/words
feat: new wordsinstr1andstr2() macro and associated tests
2021-12-22 00:07:39 +02:00
munja
bce56d8105 feat: new wordsinstr1andstr2() macro and associated tests 2021-12-21 21:54:48 +00:00
munja
2ec440b321 fix: removing termstr=lf as it breaks on SAS 9 deploys 2021-12-21 19:34:08 +00:00
munja
3d2ad531cf chore: docs 2021-12-18 14:37:54 +00:00
Allan Bowe
09136cfdbb Merge pull request #122 from sasjs/serverfix
fix: making ms_webout work with SAS on Windows Desktop
2021-12-18 14:12:35 +00:00
munja
0ca16f3d04 fix: quoting the server option in mm_assigndirectlib() to avoid assignment errors when the name contains dashes aetc 2021-12-18 14:11:38 +00:00
Allan Bowe
1e72f13f2d fix: making ms_webout work with SAS on Windows Desktop 2021-12-17 23:01:43 +00:00
Allan Bowe
5e8e8e02d3 Merge pull request #121 from sasjs/mp_ds2md
BREAKING CHANGE: renamed mp_mdtablewrite.sas to mp_ds2md.sas
2021-12-17 17:31:01 +00:00
munja
b2e2c7c798 chore(lint): fix indentation 2021-12-17 17:14:41 +00:00
munja
b29dd38188 fix: preventing merged cells in sas-generated markdown tables.
BREAKING CHANGE: renamed mp_mdtablewrite.sas to mp_ds2md.sas and modified the parameter from fref to outref.  This makes it more consistent with the other mp_ds2xx range of macros.
2021-12-17 17:14:03 +00:00
Allan Bowe
2e122c2ada Merge pull request #120 from sasjs/fix_makedata
fix: check charvars and numvars exist. Closes #119
2021-12-17 15:25:36 +00:00
Ivor Townsend
8b68c3bb27 fix: check charvars and numvars exist. Closes #119 2021-12-17 15:08:56 +00:00
Allan Bowe
8c7523deda Merge pull request #118 from sasjs/fmting
More Macros
2021-12-17 10:28:37 +00:00
munja
e8f656f48a chore: lint fixes 2021-12-17 00:57:35 +00:00
munja
1eb90202b9 fix: failing test for mp_getformats 2021-12-17 00:55:51 +00:00
munja
82108f4b97 fix: ensuring test for mp_sortinplace passes, fixing uninitialised var in mp_mdtablewrite, fix for non pk table in mp_getformats 2021-12-17 00:53:13 +00:00
munja
ab1030afb1 feat: finishing mp_formats and adding a test, including prefix in mp_init, allowing mp_sortinplace to work when there is no primary key, sand other small fixes 2021-12-17 00:32:49 +00:00
munja
26292740bb feat: mp_getformats() macro. Extracts bformat summary and detail 2021-12-16 00:02:52 +00:00
munja
96cc131305 chore(docs): updating header in mf_getquotedstr 2021-12-16 00:01:58 +00:00
munja
724cd72876 feat: adding mf_getfmtlist() and mf_getfmtname() macros and associated tests. Also added &sasjswork as a global macro variable in mp_init(). 2021-12-15 21:05:12 +00:00
munja
fa5d9ef744 feat: adding ls=max to mp_init.sas to reduce log ever so slightly and also to avoid word truncation 2021-12-15 19:20:14 +00:00
Allan Bowe
dc63b4adf5 Merge pull request #117 from sasjs/mf_dedup
`mf_dedup()` macro - removes duplicates from a macro string
2021-12-15 17:44:54 +00:00
munja
3f20ca03dd chore: updating all.sas 2021-12-15 17:04:27 +00:00
munja
3a826dccf1 feat: mf_dedup and associated test 2021-12-15 17:04:08 +00:00
munja
a1ce68ce56 fix: avoiding uninitialised variables in mm_getdetails and mm_gettables.sas 2021-12-15 15:10:17 +00:00
munja
a45384aacb chore: updating all.sas 2021-12-15 12:18:56 +00:00
Allan Bowe
032c4f318e Merge pull request #114 from sasjs/issue113
feat: mp_storediffs macro.  Closes #113
2021-12-15 12:18:10 +00:00
munja
5faaa4a4cd fix: test for mp_storediffs 2021-12-15 12:15:36 +00:00
Allan Bowe
4e41182521 Merge pull request #116 from sasjs/fix/mp_init_options_fix
fix: Aligns the autocorrect option with the intent. Closes #115.
2021-12-15 11:58:50 +00:00
Trevor Moody
7185032680 fix: Aligns the autocorrect option with the intent. 2021-12-15 11:25:41 +00:00
munja
c9d8df0a48 fix: updates from testing mp_storediffs (impact on some related macros) 2021-12-15 10:16:24 +00:00
munja
d93693ba55 feat: mp_storediffs macro. Closes #113 2021-12-14 17:45:37 +00:00
munja
d49b21f3f1 fix: initialising name/uri in mv_jobexecute 2021-12-14 08:42:39 +00:00
munja
a45d280a51 fix: avoiding uninitialised variables in mv_getjobcode and mv_getfoldermembers 2021-12-14 08:20:32 +00:00
Allan Bowe
2536e299ad Merge pull request #112 from sasjs/mf_isint
feat: new macro to determine if a macro variable value is an integer …
2021-12-13 18:55:41 +00:00
munja
8b5238230b feat: new macro to determine if a macro variable value is an integer - mf_isint (and associated test) 2021-12-13 18:36:22 +00:00
munja
0ce7efee3e fix: declaring msg variable prior to set statement in mp_copyfolder.sas 2021-12-13 11:26:17 +00:00
munja
357677e45c chore: switching pre-commit hook to bash from shell 2021-12-13 09:14:29 +00:00
Allan Bowe
a4a332926e Merge pull request #111 from sasjs/issue110
feat: adding varinitchk=ERROR to mp_init.  Closes #110.
2021-12-13 08:44:12 +00:00
munja
0a29006914 chore: running all.sas 2021-12-13 01:08:37 +00:00
munja
0885bad859 fix: updating the tests following varinitchk=error enablement. Removing the word 'error' from documenttion. 2021-12-13 01:07:54 +00:00
munja
42bd1750bd feat: adding varinitchk=ERROR to mp_init. Closes #110. Also updated the comments / documentation 2021-12-12 22:57:25 +00:00
Allan Bowe
58784b2f28 Merge pull request #109 from sasjs/issue108
fix: rebuilding mp_searchdata into data step to avoid SQL warning.
2021-12-11 14:34:08 +00:00
munja
e125aace9b fix: rebuilding mp_searchdata into data step to avoid SQL warning. Added test and refreshed docs. Closes #108 2021-12-10 15:56:39 +00:00
Allan Bowe
b02a9e3478 Merge pull request #107 from sasjs/hashdclogic
fix: adding iftrue switch to mp_hashdataset
2021-12-08 20:59:35 +00:00
munja
3d3c76c836 fix: adding iftrue switch to mp_hashdataset 2021-12-08 20:58:59 +00:00
Allan Bowe
e039f1cd83 Merge pull request #106 from sasjs/hook
chore: adding hook script to prevent accidental commits to master
2021-12-07 17:44:00 +00:00
munja
6c8165601d chore: adding hook script to prevent accidental commits to master 2021-12-07 16:58:23 +00:00
munja
596624c1bf chore: remove the word ERROR from the code 2021-12-06 15:14:46 +00:00
munja
4aca34d4c2 fix: missing end comment in mp_init.sas 2021-12-06 14:58:13 +00:00
Allan Bowe
858b378658 Merge pull request #104 from sasjs/moremacros
feat: new macros
2021-12-06 14:37:35 +00:00
munja
8af41a8cc3 feat: v1 of the mp_makedata() macro. Will create random data from an empty table definition. Many more features to be added 2021-12-06 00:36:31 +00:00
munja
b13c33cbde fix: using byte codes to tidy up apostrophe logic, and new param for mf_getquotedstr macro 2021-12-06 00:12:36 +00:00
munja
6906f025d6 fix: updating tests that are failing due to changes / new options 2021-12-05 23:56:36 +00:00
munja
8b355b8056 feat: new macros (mp_reseterror and mp_init), new datetime format added to mp_getcols, and stub prepared for mp_makedata 2021-12-05 23:35:25 +00:00
munja
8938553588 chore: updating header in mp_getpk.sas 2021-12-05 19:08:06 +00:00
munja
14852f3647 chore: updating README headers and licence date 2021-12-05 17:24:15 +00:00
munja
b55e91784d chore: updating all.sas 2021-12-05 16:57:29 +00:00
munja
fc14aaa37f chore: updating docs 2021-12-05 16:57:16 +00:00
Allan Bowe
3295f3845e Merge pull request #103 from sasjs/issue102
Several new macros, and improvements to old ones
2021-12-05 15:57:47 +00:00
Allan Bowe
bbf734fbf6 Merge branch 'main' into issue102 2021-12-05 15:57:00 +00:00
munja
c4e9ab7b3e feat: mp_sortinplace and corresponding test. Closes #102. 2021-12-05 15:55:32 +00:00
munja
11c181ef8b chore: adding test for mf_existds 2021-12-05 14:14:14 +00:00
Allan Bowe
1d0754d705 fix: quoting memsize in ms_webout 2021-12-05 12:28:20 +00:00
Allan Bowe
80acecd3e6 fix: checking for existence of stpsrv_header function before creating it in mcf_stpsrv_header (sasjs/server feature) 2021-12-05 11:09:47 +00:00
Allan Bowe
cb2a8db087 fix: remove jsonengine var from ms_webout 2021-12-05 10:38:42 +00:00
munja
17b58d775a feat: sortinplace macro 2021-12-05 00:52:16 +00:00
munja
a801e5c1f1 feat: mp_getpk macro (and test). Extracts primary keys from a table or library and presents them at table level in the correct order (of cols within a constraint) 2021-12-05 00:41:36 +00:00
munja
966f2cf78d fix: addressing corrupted unzips in certain cases 2021-12-05 00:39:47 +00:00
munja
8c21b9397f fix: adding constraint_order to mp_getconstraints 2021-12-04 14:54:18 +00:00
munja
6056b739bf chore: updating header info 2021-12-04 14:25:54 +00:00
munja
7823933cf7 feat: adding iftrue condition to mp_dropmembers for easier debug management 2021-12-04 14:24:28 +00:00
munja
7623abb1f7 chore: updating header 2021-12-04 12:19:49 +00:00
munja
f7335b78c3 fix: enabling binary file support in mp_unzip 2021-12-04 00:41:42 +00:00
Allan Bowe
914dc51aca Merge pull request #101 from sasjs:fix_copyfolder
fix: correct target path. Closes #100
2021-12-02 13:29:24 +00:00
Allan Bowe
7ce480db6a fix: updating all.sas 2021-12-02 13:29:02 +00:00
Ivor Townsend
3120ba68ad fix: correct target path. Closes #100 2021-12-02 09:49:05 +00:00
Allan Bowe
9eff1e0e83 Merge pull request #99 from sasjs/issue98
feat: adding ms_webout macro for server responses on sasjs/server.
2021-12-01 23:40:07 +00:00
Allan Bowe
678250ba27 fix: tests 2021-11-30 16:39:33 +00:00
Allan Bowe
6845a63196 chore: tidy up repo 2021-11-30 16:31:26 +00:00
Allan Bowe
3103abe3c8 chore: updating readme and dox file 2021-11-30 16:27:04 +00:00
Allan Bowe
318fd1ddde feat: adding ms_webout macro for server responses on sasjs/server. Closes #98 2021-11-30 15:26:02 +00:00
Allan Bowe
7b2b81a501 Merge pull request #97 from sasjs/issue92
Issue92
2021-11-29 11:48:49 +00:00
Allan Bowe
02de4e42bf chore: generating all.sas and fixing indentation 2021-11-29 11:35:37 +00:00
Allan Bowe
ddd831fe7a feat: new copyfolder macro and associated test. Closes #92 2021-11-29 11:35:03 +00:00
Allan Bowe
42a46b32e9 Merge pull request #96 from sasjs/add_deletefolder
feat: Adding Delete Folder Macro
2021-11-26 16:34:03 +00:00
Allan Bowe
3b395b3ae5 chore: all.sas update 2021-11-26 16:20:33 +00:00
Allan Bowe
9e84e47563 feat: mp_deletefolder tests, closes #90 2021-11-26 16:20:13 +00:00
Allan Bowe
aff29427e2 chore: merge main 2021-11-26 15:37:08 +00:00
Ivor Townsend
474f1b3cc6 feat: Adding Delete Folder Macro 2021-11-26 15:06:38 +00:00
Allan Bowe
22bf8065bb Merge pull request #95 from sasjs/dirlist_enhancement
feat: Recursive Directory Listing
2021-11-26 13:00:15 +00:00
Allan Bowe
7bb089e269 fix: moving cleanup to temp table for efficiency 2021-11-26 11:55:55 +00:00
Allan Bowe
a6e9158814 chore: adding recursive option to the mp_dirlist macro, and updating all.sas 2021-11-26 11:52:48 +00:00
Ivor Townsend
19a1336720 feat: Recursive Directory Listing 2021-11-26 09:29:42 +00:00
Allan Bowe
79d5d42e6b Merge pull request #94 from sasjs/issue93
Macros for locking / unlocking tables
2021-11-25 17:44:37 +00:00
Allan Bowe
2d81de5841 chore: generating all.sas and updating doc links 2021-11-25 16:46:56 +00:00
Allan Bowe
107ab836d6 feat: mp_lockXXX macros f
These macros provide a centralised approach for locking tables where updates can happen in multiple passes.  The mp_lockfilecheck macro will also verify the ability to create a SAS lock (if a v9 library engine, and not a view)
2021-11-25 16:43:39 +00:00
Allan Bowe
5225e74465 chore: adding @vznesh for issue #88 2021-11-18 18:40:32 +00:00
Allan Bowe
39253d2828 chore: merge conflicts 2021-11-18 18:36:32 +00:00
Allan Bowe
171c169537 chore: updating all.sas 2021-11-18 18:36:08 +00:00
Allan Bowe
76af9fa33c Merge pull request #89 from sasjs/issue88
fix: removing notes when running mp_zip, closes #88. .
2021-11-18 18:35:33 +00:00
Allan Bowe
37ccc8a2aa fix: removing notes when running mp_zip, closes #88. .
Also adding 3 tests
2021-11-18 18:21:43 +00:00
Allan Bowe
d0a0274990 Merge pull request #87 from sasjs/mp_wait4file
mp_wait4file macro
2021-11-18 13:58:34 +00:00
Allan Bowe
b3d374f1b1 fix: updating node version to LTS for CLI 2021-11-18 13:44:33 +00:00
Allan Bowe
1c4458faf6 chore: comments to mp_unzip 2021-11-18 13:27:17 +00:00
Allan Bowe
96e1d146f4 chore: updating package.json 2021-11-18 13:07:00 +00:00
Allan Bowe
aadc4fb83d feat: mp_wait4file macro 2021-11-18 13:04:04 +00:00
Allan Bowe
988ee89cdb Merge pull request #85 from sasjs/all-contributors
docs: add all-contributors dependence
2021-10-04 13:56:22 +01:00
Vladislav Parhomchik
51cbfbf4bc docs: add all-contributors dependence 2021-10-04 15:21:28 +03:00
Allan Bowe
4b69e91362 Merge pull request #84 from sasjs/issue83
fix: refactored mp_getconstraints due to apparent bug in dictionary.table_constraints
2021-10-01 13:56:57 +01:00
Allan Bowe
8f9715035a chore: removing gitpod badge and switching Node to LTS 2021-10-01 12:55:54 +00:00
Allan Bowe
35ddccaa16 fix: refactored mp_getconstraints due to apparent bug in dictionary.table_constraints. Added test. Closes #83 2021-10-01 13:04:26 +01:00
Allan Bowe
cb0ddfb61c fix: applying tag wrappers to sasjsAbort response json. The adapter will always extract from these in any case, and it seems there are some situations where it is not possible to avoid errors being thrown in SAS 9 (resulting in a log always appearing in the response). This change will make it much easier to handle on the frontend side. 2021-09-30 18:50:02 +01:00
Allan Bowe
c3b6f06b3a chore: merge commit 2021-09-30 14:48:26 +01:00
Allan Bowe
8046d5a0b1 fix: updating CLI dependency to avoid npm install warnings 2021-09-30 14:47:56 +01:00
Allan Bowe
aed07f2943 Merge pull request #82 from sasjs/checkmsg
fix: adding sysmsg() to failed metadata calls
2021-09-30 14:44:36 +01:00
Allan Bowe
5bf87a78b8 fix: adding sysmsg() to failed metadata calls 2021-09-30 14:32:52 +01:00
Allan Bowe
0851523d18 chore: gitpod settings 2021-09-29 11:28:59 +00:00
Allan Bowe
9e2de81dae Merge pull request #81 from sasjs/issue80
fix: removing nonprintables from cards data.  Closes #80
2021-09-27 22:42:36 +03:00
Allan Bowe
4887f355c8 fix: removing redundant dlm option 2021-09-27 20:14:52 +01:00
Allan Bowe
9b32e6e3f2 fix: removing nonprintables from cards data. Closes #80 2021-09-27 20:12:48 +01:00
Allan Bowe
74790ec80e fix: adding trim to avoid converting trailing blanks 2021-09-27 17:46:53 +01:00
Allan Bowe
afd8a754b4 Merge pull request #79 from sasjs/issue78
feat: adding binary variable support to mp_ds2cards.sas
2021-09-27 18:57:16 +03:00
Allan Bowe
bc1f7b3baa fix: updating test result and making mp_ds2cards header doxygen compliant 2021-09-27 16:39:28 +01:00
Allan Bowe
51690e68dc feat: adding binary variable support to mp_ds2cards.sas, updating documentation, and including two tests. Closes #78 2021-09-27 16:15:25 +01:00
Allan Bowe
0fa076cb73 Merge pull request #77 from sasjs/dictfix
fix: ensuring upcase comparisons for dictionary tables
2021-09-27 15:17:48 +03:00
Allan Bowe
6506993704 fix: ensuring upcase comparisons for dictionary tables 2021-09-27 13:04:32 +01:00
Allan Bowe
a69db2ebfb Merge pull request #76 from sasjs/mp_appendfile
feat: mp_appendfile macro for appending 2 or more files together
2021-09-27 14:50:55 +03:00
Allan Bowe
d72ca7cb24 fix: warning in mp_assertcolvals from outobs sql option 2021-09-27 12:30:28 +01:00
Allan Bowe
52dfa7b8f7 feat: mp_appendfile macro for appending 2 or more files together 2021-09-27 11:46:19 +01:00
Allan Bowe
dae03c5730 fix: adding SYSSCPL to mp_abort and webout macros 2021-09-24 17:31:42 +01:00
Allan Bowe
14efe5d3fd chore: removing copyright notice (copy paste error) 2021-09-22 21:10:00 +01:00
Allan Bowe
653244d737 Merge pull request #75 from sasjs/mp_getcols
Mp getcols macro
2021-09-22 19:34:25 +03:00
Allan Bowe
086831b3f5 chore: updating all.sas 2021-09-22 17:20:02 +01:00
Allan Bowe
6eca585fc1 feat: new mp_getcols macro 2021-09-22 17:19:49 +01:00
Allan Bowe
f6ba36fc28 feat: adding more info to result description in mp_assertcolvals 2021-09-22 17:19:29 +01:00
Allan Bowe
7406288d79 fix: mp_gsubfile() now works with multiline files (and we have a multiline test to go with it) 2021-09-16 18:30:17 +01:00
Allan Bowe
2e7fcbe5b8 fix: prevening truncation of _debug in mp_abort.sas and more reliable way to fetch syswarningtext and syserrortext 2021-09-16 14:04:50 +01:00
Allan Bowe
3e7b9f8c14 chore: fixing example in header for mp_gsubfile() 2021-09-16 13:54:27 +01:00
Allan Bowe
e9189ccc06 Merge pull request #74 from sasjs/gsub
feat: adding mp_gsubfile.sas - a SAS macro that uses Lua to perform a…
2021-09-14 19:13:15 +03:00
Allan Bowe
8c00d715c2 chore: formatting 2021-09-14 16:08:30 +01:00
Allan Bowe
d47a369cdf feat: adding mp_gsubfile.sas - a SAS macro that uses Lua to perform a full text find and replace of an entire file. Not restricted by number of characters (only memory). IIncludes a test. 2021-09-14 16:07:12 +01:00
Allan Bowe
52bf6019fd Merge pull request #73 from sasjs/defaultvars
fix: adding default lengths to vars in mv_getfoldermembers to cover u…
2021-09-11 19:26:06 +03:00
Allan Bowe
25e61fd8ef chore: updating all.sas 2021-09-11 19:25:28 +03:00
Allan Bowe
3038be83a0 fix: adding default lengths to vars in mv_getfoldermembers to cover use case where no members found (and downstream process expects an empty table with those vars. Also fixing mp_webin to cover a case where native temp filerefs (starting with a #hash) are not supported. 2021-09-11 19:24:51 +03:00
Allan Bowe
6e2447c70a fix: missing dependency in mp_webin() 2021-09-11 19:00:04 +03:00
Allan Bowe
486aba84ca Merge pull request #72 from sasjs/webinnings
New mp_webin() macro and performance improvement to mf_getuniquefileref()
2021-09-08 19:51:36 +03:00
Allan Bowe
b5944181e1 chore(dependencies): bumping cli 2021-09-08 19:35:27 +03:00
Allan Bowe
3f69cf506a feat: mp_webin() macro for handling the _webin_xxx macro variables in SAS web services 2021-09-08 19:34:28 +03:00
Allan Bowe
6013897c50 feat: updating mf_getuniquefileref() to use native approach to get a unique fileref (which is 100 times faster than the old approach) 2021-09-08 15:30:51 +03:00
Allan Bowe
27cf2a2532 Merge pull request #71 from sasjs/including
fix: conditional logic around mp_abort(mode=INCLUDE) to cover case wh…
2021-09-05 20:56:40 +03:00
Allan Bowe
d096cbddeb fix: conditional logic around mp_abort(mode=INCLUDE) to cover case when no mp_include was executed 2021-09-05 20:55:44 +03:00
Allan Bowe
117503f214 Merge pull request #70 from sasjs/including
feat: new mp_include() feature for handling %includes with macros
2021-09-03 11:17:21 +03:00
Allan Bowe
5cc5fae750 chore: adding mp_abort to mp_include sas macros list 2021-09-03 11:06:12 +03:00
Allan Bowe
d93032e1a9 chore: docs 2021-09-03 10:54:21 +03:00
Allan Bowe
507557b2cb feat: new mp_include() feature for handling %includes with macros 2021-09-03 00:40:10 +03:00
Allan Bowe
ee5c3c185a chore: merge 2021-08-28 14:22:16 +03:00
Allan Bowe
e5592a2eb2 chore: avoiding the string 'ERROR:' in logs 2021-08-28 14:21:36 +03:00
Allan Bowe
59200a6e73 Merge pull request #69 from sasjs/issue68
feat: supporting postgres timestamps for mp_ds2inserts and mp_lib2inserts
2021-08-24 21:03:09 +03:00
Allan Bowe
f468f60ae1 fix: substr issue in mp_ds2inserts. Closes #68 2021-08-24 20:51:29 +03:00
Allan Bowe
9f60d827b6 feat: supporting postgres timestamps for mp_ds2inserts and mp_lib2inserts 2021-08-24 20:39:02 +03:00
Allan Bowe
5c936ddb65 Merge pull request #67 from sasjs/issue66
feat: adding APPEND option to mp_binarycopy.sas, and a new test (mp_b…
2021-08-24 14:04:25 +03:00
Allan Bowe
d0bde62594 feat: adding APPEND option to mp_binarycopy.sas, and a new test (mp_binarycopy.test.sas). Closes #66 2021-08-24 13:43:31 +03:00
Allan Bowe
ada9192337 Merge pull request #65 from sasjs/issue64
fix: increasing limit for mv_getfoldermember.sas, also adding a test,…
2021-08-20 22:50:27 +03:00
Allan Bowe
6161f588a9 fix: increasing limit for mv_getfoldermember.sas, also adding a test, and updating mf_getapploc to search _program by default (and fixing it to work with macro tests, and updating the test for that also) 2021-08-20 22:38:56 +03:00
Allan Bowe
67079d8c17 fix: adding default value for exists in mf_existfunction 2021-08-19 00:20:49 +03:00
Allan Bowe
75bd39adb0 Merge pull request #63 from sasjs/issue62
feat: adding FCMP capability
2021-08-19 00:00:15 +03:00
Allan Bowe
078bdbeecf chore: bumping devDependency (sasjs cli) 2021-08-18 23:47:17 +03:00
Allan Bowe
8ddb86785c feat: new fcmp stpsrv_header function 2021-08-18 23:45:45 +03:00
Allan Bowe
005af0ecf8 feat: new mf_existfunction macro 2021-08-18 23:36:12 +03:00
Allan Bowe
bc410a9135 chore: fixing docs for tests 2021-08-18 19:55:05 +03:00
Allan Bowe
fc8ba2e36c chore: moving files to tidy up docs 2021-08-18 19:43:38 +03:00
Allan Bowe
756441384a feat: adding first fcmp macro, mcf_string2file.sas 2021-08-18 18:35:51 +03:00
Allan Bowe
10f9eecf9e Merge pull request #60 from sasjs/vpn-fix
chore: vpn fix
2021-08-13 14:41:25 +03:00
470ebb50a7 chore: vpn fix 2021-08-13 12:57:31 +02:00
Allan Bowe
26cd5d9d31 Merge pull request #59 from Stefan-Dimitrov-Stoyanov/patch-1
Update README.md
2021-08-12 11:59:25 +03:00
Stefan-Dimitrov-Stoyanov
0b694bb878 Update README.md
Fix the missing space at the end of the first line under the Installation header:  https://github.com/sasjs/core/blob/main/README.md#installation
2021-08-11 13:34:44 +01:00
Allan Bowe
b403c02bba chore: docs for mm_createfolder 2021-08-06 15:36:55 +03:00
Allan Bowe
0b555bb31c Merge pull request #58 from sasjs/apploc
feat: new mf_getapploc macro
2021-08-04 22:04:55 +03:00
Allan Bowe
40b513a9e3 feat: new mf_getapploc macro 2021-08-04 22:00:18 +03:00
Allan Bowe
4eacf4deae Merge pull request #57 from sasjs/mf_existfref
fix: showing filerefs that exist (even when underlying does not) in m…
2021-08-03 14:32:23 +03:00
Allan Bowe
5824423c13 fix: showing filerefs that exist (even when underlying does not) in mf_existfileref, along with 3 tests 2021-08-03 14:16:52 +03:00
Allan Bowe
ce5bfd41dc chore(docs): updating header for mm_gettables 2021-08-02 10:37:01 +03:00
Allan Bowe
0c67a07e42 Merge pull request #56 from sasjs/ddlworkz
feat: new mp_lib2inserts macro.  In addition, modified mp_getddl to i…
2021-07-30 10:11:27 +03:00
Allan Bowe
187504600a chore: fixing test 2021-07-30 00:21:02 +03:00
Allan Bowe
658d67feaa chore: fixing comments 2021-07-30 00:17:44 +03:00
Allan Bowe
5207a77591 feat: new mp_lib2inserts macro. In addition, modified mp_getddl to ignore views, closing #5. Created a test, which highlighted another issue in mp_getddl (labels were being double quoted which caused macro resolution attempts when %including). Changed to single quotes. Switched 'outlib' to 'outschema' in mp_ds2inserts to harmonise with mp_getddl. Added a maxobs option, to speed up testing. 2021-07-30 00:14:29 +03:00
Allan Bowe
4456adf1dc fix: switching default flavour from BASE to SAS to be consistent with mp_getddl 2021-07-29 20:35:57 +03:00
Allan Bowe
03962c2a50 fix: for PGSQL DDL generation, ignore tables with over 1600 columns (as they are not supported in Postgres) 2021-07-29 15:45:16 +03:00
Allan Bowe
6d2fc7e265 fix: removing bug introduced to mp_getddl and adding a test to prevent regression 2021-07-29 13:02:58 +03:00
Allan Bowe
39b2e7c5f9 fix: supporting salts over 32 chars in mp_hashdataset() 2021-07-28 23:22:43 +03:00
Allan Bowe
f99adf5c3e Merge pull request #55 from sasjs/insertforpg
feat: updating mp_ds2inserts to support postgres database
2021-07-28 19:11:38 +03:00
Allan Bowe
69f8e91a2d feat: adding salt as option for mp_hashdataset 2021-07-28 17:04:41 +03:00
Allan Bowe
5b5d01993f fix: updating mp_getddl to enable append to a fileref 2021-07-28 17:01:49 +03:00
Allan Bowe
00fa464a7c feat: updating mp_ds2inserts to support postgres database 2021-07-27 11:07:12 +03:00
Allan Bowe
a5baf46233 chore: removing unnecessary proc format and generating the all.sas file 2021-07-26 22:30:02 +03:00
Allan Bowe
d63d2a4ec1 Merge pull request #54 from sasjs/mp_ds2inserts
feat: mp_ds2inserts macro
2021-07-26 22:10:44 +03:00
Allan Bowe
900f694065 chore: removing extra period 2021-07-26 21:59:48 +03:00
Allan Bowe
838324c15e chore: updating header 2021-07-26 19:06:53 +03:00
Allan Bowe
e3205ec06c feat: mp_ds2inserts macro for creating programs for inserting data (and corresponding test) 2021-07-26 19:04:49 +03:00
Allan Bowe
154a33434e chore: more contributors 2021-07-24 21:06:30 +03:00
Allan Bowe
bfa1bbaeb1 chore: all contributors update in README 2021-07-24 21:03:49 +03:00
Allan Bowe
1f0128aec4 Merge pull request #53 from sasjs/base64doublebytefix
fix: mp_base64copy.sas fixes, removed renegade % symbol and issue wit…
2021-07-18 17:16:58 +03:00
Allan Bowe
69f03f4e14 fix: mp_base64copy.sas fixes, removed renegade % symbol and issue with truncation at character 76. Added two tests, including one to test double byte encoded characters. 2021-07-18 17:05:05 +03:00
Allan Bowe
a932f321d8 Merge pull request #52 from sasjs/sasjs-cli-version-bump
fix: bump sasjs/cli version + 'prepare' support windows CMD/Powershell
2021-07-10 09:40:48 +03:00
Saad Jutt
21200c11c1 fix: bump sasjs/cli version + 'prepare' support windows CMD/Powershell 2021-07-10 03:43:58 +05:00
Allan Bowe
825c97c49c fix: switch postinstall to prepare 2021-06-30 19:50:20 +03:00
Allan Bowe
f301899269 Merge pull request #51 from sasjs/issue50
fix: setting syscc to zero to prevent error state in response.  Close…
2021-06-29 00:09:42 +03:00
Allan Bowe
fc81f62d2f fix: setting syscc to zero to prevent error state in response. Closes #50 2021-06-28 23:52:12 +03:00
Allan Bowe
93aea5ed02 Merge pull request #49 from sasjs/logfix
Context fixes on mv_jobflow and mp_testservice
2021-06-27 00:35:24 +03:00
Allan Bowe
55d4c7238a fix: updating mp_testservice.sas and mv_jobflow to use the provided context. Also updating mv_getjobresult to fetch byte by byte (as some inputs are very wide). 2021-06-27 00:22:53 +03:00
Allan Bowe
cd75bf263a fix: removing redundant parameter from mv_getjoblog 2021-06-26 21:11:26 +03:00
Allan Bowe
929a1a9974 chore: updating docs 2021-06-24 00:39:09 +03:00
Allan Bowe
7cafb4fb36 Merge pull request #48 from sasjs/base64
feat: adding mp_base64copy macro
2021-06-24 00:30:21 +03:00
Allan Bowe
a8d222a0f8 chore: automated commit 2021-06-24 00:29:54 +03:00
Allan Bowe
ac0ddf38b0 chore: automated commit 2021-06-24 00:28:41 +03:00
Allan Bowe
ecd389c935 feat: adding mp_base64copy macro 2021-06-24 00:26:41 +03:00
Allan Bowe
06a5ea06f8 Merge pull request #46 from sasjs/mendfixes
sasjs lint fix for macro name in MEND statement
2021-06-23 22:27:36 +03:00
Allan Bowe
955471ed3c Merge branch 'main' into mendfixes 2021-06-23 21:55:44 +03:00
Allan Bowe
c8d3b43b12 fix: adding lrecl to mv_createfile to support lines 1 million characters wide. Closes #47 2021-06-23 21:53:32 +03:00
Allan Bowe
3e313b06a9 fix: adding mend in python lua build 2021-06-21 17:25:58 +03:00
Allan Bowe
d7371a4505 fix: adding mend to every macro statement using sasjs lint fix 2021-06-21 17:25:01 +03:00
Allan Bowe
32a6d15c2e Merge pull request #44 from sasjs/vpn-connection
chore: added vpn connection
2021-06-21 14:35:19 +03:00
Allan Bowe
b109e7cead fix: bumping core 2021-06-21 11:27:06 +00:00
d291d3e287 chore: added vpn connection 2021-06-21 11:49:37 +02:00
Allan Bowe
5a2968e798 fix: supporting LATIN1 as well as WLATIN1 in mm_webout 2021-06-17 16:31:29 +03:00
Allan Bowe
120ad9a7da fix: supporting bell cand escape characters when creating viya jobs / services with macro 2021-06-11 00:09:16 +03:00
Allan Bowe
67a81b2690 chore: updating the docs for mm_spkexport.sas 2021-06-08 20:09:23 +03:00
Allan Bowe
506cf1812f fix: deal with dashes in sysencoding 2021-06-08 16:59:43 +03:00
Allan Bowe
8cc0eb0dd7 Merge pull request #42 from sasjs/issue41
closes #42 Issue41
2021-06-03 22:44:16 +03:00
Allan Bowe
4c1f69da3a fix: using PROC JSON for JSON where SYSENCODING=wlatin1 2021-06-01 18:24:04 +03:00
Allan Bowe
f160ebe705 chore: updating all.sas from previous pushes 2021-06-01 18:01:01 +03:00
Allan Bowe
3f49925d01 Merge pull request #40 from sasjs/dependabot/npm_and_yarn/ws-7.4.6
chore(deps): bump ws from 7.4.5 to 7.4.6
2021-06-01 17:58:49 +03:00
Allan Bowe
53ed5dc916 fix: adding extra debugging to mf_getvarlist 2021-06-01 09:32:19 +03:00
Allan Bowe
808b24e31b chore: adding mend statement 2021-05-31 15:15:17 +03:00
dependabot[bot]
c51c9c2ca9 chore(deps): bump ws from 7.4.5 to 7.4.6
Bumps [ws](https://github.com/websockets/ws) from 7.4.5 to 7.4.6.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.4.5...7.4.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-31 02:08:52 +00:00
Allan Bowe
4d6edf5566 feat: additional options for mv_createfile.sas, also a log message to enable file to be easily opened 2021-05-30 13:22:50 +03:00
Allan Bowe
41a24677f5 chore: automated commit 2021-05-27 09:42:15 +03:00
Allan Bowe
e7d8d8ffb3 chore: updating docs 2021-05-27 09:40:38 +03:00
Allan Bowe
60d23dd618 Merge pull request #39 from sasjs/newviyafeatures
Newviyafeatures
2021-05-27 00:31:44 +03:00
Allan Bowe
d2764c3cd1 chore: updating all.sas 2021-05-26 23:37:38 +03:00
Allan Bowe
f9f4355143 feat: adding mv_createfile.sas and tests 2021-05-26 23:37:24 +03:00
Allan Bowe
18bc6c889d feat: adding mfv_existfolder.sas and tests 2021-05-26 23:37:06 +03:00
Allan Bowe
42a16ef496 feat: adding mfv_existfile.sas and tests 2021-05-26 23:36:43 +03:00
Allan Bowe
8178b801fb fix: using mfv_existfolder macro in mv_createfolder to save requests 2021-05-26 23:36:09 +03:00
Allan Bowe
ce331a23c8 fix: ensuring obs is updated when the table has zero columns 2021-05-26 23:35:25 +03:00
Allan Bowe
1cc9213467 feat: refreshing mf_abort (it's now an actual macro function) 2021-05-26 23:34:43 +03:00
Allan Bowe
aabbf4d0f9 Merge pull request #38 from sasjs/weboutfixes
fix: changing replace to YES in mm_createwebservice.sas, also setting…
2021-05-26 18:29:08 +03:00
Allan Bowe
2bea8be70d chore: logging in test 2021-05-26 18:19:04 +03:00
Allan Bowe
9b2368443e fix: changing replace to YES in mm_createwebservice.sas, also setting a default for code to ft15f001. More debugging added to mv_createfolder.sas 2021-05-26 10:36:45 +03:00
Allan Bowe
7915ba2c41 fix: running python to rebuild all.sas and mx_createwebservice macros 2021-05-25 15:50:06 +03:00
Yury Shkoda
cc61e48868 Merge pull request #37 from sasjs/createfolderfix
fix: addressed issue when creating recursive folers in mv_createfolde…
2021-05-25 15:40:27 +03:00
Allan Bowe
62db83dcf6 fix: addressed issue when creating recursive folers in mv_createfolder.sas 2021-05-25 15:33:02 +03:00
Allan Bowe
7ea9e0f8e9 Merge pull request #36 from sasjs/filter_json_fixes
Filter json fixes
2021-05-21 16:30:53 +03:00
Allan Bowe
1c852515f5 fix: adding more tests to mp_filtervalidate 2021-05-21 16:27:10 +03:00
Allan Bowe
b7e677bd8e fix: adding utf8 to mp_jsonout 2021-05-21 16:26:53 +03:00
Allan Bowe
f47f0d2cee chore: removing ghooks reference from package.json 2021-05-20 11:56:41 +03:00
Allan Bowe
3d0f426a98 Merge pull request #35 from sasjs/issue33
fix: adding sysvlong to mp_abort also
2021-05-20 11:40:29 +03:00
Allan Bowe
2cb51f6164 fix: adding sysvlong to mp_abort also 2021-05-20 11:39:28 +03:00
Allan Bowe
b73bf998da Merge pull request #34 from sasjs/issue33
feat: adding sysvlong to the webout macros, also updating documentati…
2021-05-20 11:25:43 +03:00
Allan Bowe
c9ad38ee98 feat: adding sysvlong to the webout macros, also updating documentation and adding tests. Closes #33 2021-05-20 11:23:10 +03:00
Allan Bowe
76b1b951c0 chore: adding SECURITY.md 2021-05-19 19:05:46 +03:00
Allan Bowe
996054b17a Merge pull request #32 from sasjs/git-commit-hook
feat(git): enabled pre-commit hook enforcing conventional commits
2021-05-19 18:55:35 +03:00
Allan Bowe
7fca3d4e3f chore: readme update for star graph 2021-05-19 18:24:02 +03:00
Allan Bowe
c4e599c861 chore: readme update (badges for issue counts) 2021-05-19 18:19:35 +03:00
Allan Bowe
0f6ff2cc1e chore: updating devdependency version for sasjs/cli 2021-05-19 18:16:00 +03:00
Allan Bowe
7cac4c71fb chore: updating package.json 2021-05-19 18:14:04 +03:00
Allan Bowe
1322bdab92 fix: deprecating ghooks, adding conventional commit hook also 2021-05-19 18:10:57 +03:00
Allan Bowe
f201df606a chore: automated commit 2021-05-19 17:42:43 +03:00
Yury Shkoda
a56fce86b1 feat(git): enabled pre-commit hook enforcing conventional commits 2021-05-19 15:03:02 +03:00
Allan Bowe
41ccc5fdd9 Merge pull request #30 from sasjs/travis
chore: travis yaml
2021-05-16 00:25:49 +03:00
Allan Bowe
b2877bd493 chore: automated commit 2021-05-16 00:25:04 +03:00
Allan Bowe
df8f8893e7 chore: automated commit 2021-05-16 00:16:59 +03:00
Allan Bowe
27fbdf193b chore: automated commit 2021-05-16 00:15:52 +03:00
Allan Bowe
6ae892989d chore: automated commit 2021-05-16 00:14:37 +03:00
Allan Bowe
39a7b332da chore: automated commit 2021-05-16 00:12:35 +03:00
Allan Bowe
c81794b542 chore: automated commit 2021-05-16 00:08:10 +03:00
Allan Bowe
e456da846a chore: automated commit 2021-05-16 00:03:13 +03:00
Allan Bowe
5c144be05b chore: automated commit 2021-05-16 00:00:01 +03:00
Allan Bowe
055669c133 fix: adding test action 2021-05-15 23:41:41 +03:00
Allan Bowe
4b67e13b24 chore: travis yaml 2021-05-15 23:31:50 +03:00
Allan Bowe
f1ec3eda81 fix: more badges for README 2021-05-15 22:20:53 +03:00
Allan Bowe
f2d5859675 fix: adding CHANGELOG (as a stub) 2021-05-15 21:35:54 +03:00
Allan Bowe
ea057d4655 fix: adding .npmignore to reduce bundle size and updating homepage in README 2021-05-15 21:05:51 +03:00
Allan Bowe
26c085b354 fix: adding badges to README 2021-05-15 20:41:27 +03:00
Allan Bowe
d13ac52739 fix: adding test command to package.json 2021-05-15 16:55:57 +03:00
Allan Bowe
bbbc28ad6d Merge branch 'main' of github.com:sasjs/core 2021-05-15 16:31:13 +03:00
Allan Bowe
530cd6e95c feat: adding two more test types to mp_assertdsobs.sas, also a test for the assertion macro itself 2021-05-15 16:30:57 +03:00
Allan Bowe
c4e17e43e8 Create CODE_OF_CONDUCT.md 2021-05-15 15:03:59 +03:00
Allan Bowe
fed217eec3 Merge pull request #29 from sasjs/issue10
fix: adding checks for consul token access, and two tests to ensure t…
2021-05-15 14:42:53 +03:00
Allan Bowe
1934dc8332 fix: adding checks for consul token access, and two tests to ensure the macro is working. closes #10 2021-05-15 14:41:10 +03:00
Allan Bowe
9de512cfc7 Merge pull request #28 from sasjs/issue7
fix: adding licence info.  Closes #7
2021-05-13 21:50:36 +03:00
Allan Bowe
cadafcc86b fix: adding licence info. Closes #7 2021-05-13 21:49:54 +03:00
Allan Bowe
5f805b006f Merge pull request #27 from sasjs/issue14
feat: adding MATCH parameter to mp_searchcols.sas to enable fuzzy mat…
2021-05-13 21:40:03 +03:00
Allan Bowe
c6b65366b7 feat: adding MATCH parameter to mp_searchcols.sas to enable fuzzy matching on columns. Closes #14 2021-05-13 21:38:38 +03:00
Allan Bowe
51ddd9c1e5 chore: automated commit 2021-05-13 10:38:02 +03:00
Allan Bowe
20bf3b86af chore: automated commit 2021-05-13 10:34:54 +03:00
Allan Bowe
de67cd329b chore: automated commit 2021-05-12 16:32:24 +03:00
Allan Bowe
779e4942c7 Merge pull request #26 from tmoody/fix/clean_exit_mv_jobflow_on_syscc
fix: early exit, with syscc, when submitted jobs fail within a flow
2021-05-12 16:31:06 +03:00
Trevor Moody
a69a1ac7f0 fix: removed invisible hexchars on blank lines 2021-05-12 14:18:44 +01:00
Trevor Moody
2a644d6c2b fix: corrected asser description 2021-05-12 14:01:49 +01:00
Trevor Moody
843930c666 chore: added tests for mv_jobflow 2021-05-12 13:59:21 +01:00
Trevor Moody
90d69af7ee feat: early exit, with syscc, when submitted jobs fail within a flow 2021-05-12 12:06:02 +01:00
Allan Bowe
b7bafb49f4 Merge pull request #25 from sasjs/dcfixes
fix: more logging in mp_abort, fixing job test, better return values …
2021-05-11 23:37:25 +03:00
Allan Bowe
2fa9e48286 chore: automated commit 2021-05-11 23:36:40 +03:00
Allan Bowe
5cee93c7bd fix: more logging in mp_abort, fixing job test, better return values in mp_filtervalidate and mp_filtercheck, further fixes in mp_jsonout 2021-05-11 23:08:54 +03:00
Allan Bowe
1a595c64c6 Merge pull request #24 from sasjs/abortfix
fix: mp_abort cleanup
2021-05-11 21:14:46 +03:00
Allan Bowe
2c901831b7 chore: automated commit 2021-05-11 21:11:24 +03:00
Allan Bowe
28209950ab chore: automated commit 2021-05-11 20:49:57 +03:00
Allan Bowe
44069e9867 chore: automated commit 2021-05-11 20:32:12 +03:00
Allan Bowe
e26af5c09a chore: automated commit 2021-05-11 20:32:00 +03:00
Allan Bowe
4ee13c9389 fix: 400 log repeat, refactor mp_abort abortions, updated doc header 2021-05-11 20:25:39 +03:00
Allan Bowe
15f903aa42 fix: updating mv_getjoblog to deal with endsas'd sessions, and removing endsas from viya mp_abort 2021-05-11 18:14:33 +03:00
Allan Bowe
58a0cce39e chore: automated commit 2021-05-11 13:36:25 +03:00
Allan Bowe
9a5574ea0e fix: all 2021-05-11 13:35:21 +03:00
Allan Bowe
e6146dcbcf fix: more logic to improve robustness 2021-05-11 12:39:10 +03:00
Allan Bowe
583c7e0c83 fix: removing string 2021-05-11 12:14:09 +03:00
Allan Bowe
223bdd5983 fix: mp_abort cleanup 2021-05-11 11:58:27 +03:00
Allan Bowe
aef14543f0 chore: docs update 2021-05-10 20:37:02 +03:00
Allan Bowe
c88764c1d8 chore: docs update 2021-05-10 20:15:51 +03:00
Allan Bowe
2c952c8b01 chore: docs update 2021-05-10 20:14:23 +03:00
Allan Bowe
de3610d1aa Merge branch 'main' of github.com:sasjs/core 2021-05-10 15:24:23 +03:00
Allan Bowe
d35d597437 fix: updating reason_cd in mp_filtercheck.sas 2021-05-10 15:24:13 +03:00
Allan Bowe
3e8deda008 fix: description for mf_abort 2021-05-10 15:23:30 +03:00
Allan Bowe
a27496c7b3 Merge pull request #23 from tmoody/fix/non_stp_syscc_propagation
fix: Non-stp propagation of syscc
2021-05-10 14:58:04 +03:00
Allan Bowe
265389befc Merge branch 'main' into fix/non_stp_syscc_propagation 2021-05-10 14:57:24 +03:00
Trevor Moody
db2531e0b3 fix: Non-stp propagation of syscc 2021-05-10 12:42:36 +01:00
Allan Bowe
5e77494aa6 Merge pull request #22 from sasjs/mp_json
fix: adding formatting to mp_jsonout, and a test
2021-05-10 03:44:08 +03:00
Allan Bowe
6a2ac51925 fix: adding formatting to mp_jsonout, and a test 2021-05-10 03:42:53 +03:00
Allan Bowe
f625b04189 Merge pull request #21 from sasjs/ds2fmtds
feat: new mp_ds2fmtds macro - converts a dataset to a new dataset whe…
2021-05-10 01:26:51 +03:00
Allan Bowe
68aee776d3 feat: new mp_ds2fmtds macro - converts a dataset to a new dataset where all values are the formatted values. Also added a test. 2021-05-10 01:25:51 +03:00
Allan Bowe
38d2195d32 Merge pull request #20 from sasjs/testframework
fix: refreshed the testing toolkit, added debug options, updated docu…
2021-05-08 23:29:21 +03:00
Allan Bowe
4e564b5409 fix: refreshed the testing toolkit, added debug options, updated documentation, included one new test (mv_getjobcode.sas) 2021-05-08 23:27:55 +03:00
Allan Bowe
298acc4e50 fix: setting default to best. over 8. for mf_getformat with force option 2021-05-07 11:20:01 +03:00
Allan Bowe
af98909753 Merge pull request #19 from sasjs/mp_assert
feat: new (generic) mp_assert macro, and new feature (type filter) fo…
2021-05-06 20:59:49 +03:00
Allan Bowe
b9d33b38bf feat: new (generic) mp_assert macro, and new feature (type filter) for mf_getvarlist. Added/updated tests for mp_filtercheck and mp_validatecol and mf_getvarlist. 2021-05-06 20:58:38 +03:00
Allan Bowe
b61b5f1856 fix: adding dependency 2021-05-06 19:05:14 +03:00
Allan Bowe
805474bb46 Merge pull request #18 from sasjs/jobresult
fix: enabling fileref as output option for sas code obtained via mm_g…
2021-05-06 15:27:18 +03:00
Allan Bowe
61701f3c6a fix: enabling fileref as output option for sas code obtained via mm_getstpcode. Also updated some doc headers and macro footers. 2021-05-06 15:06:13 +03:00
Allan Bowe
f20d7476bf Merge pull request #17 from sasjs/jobresult
feat: new mv_getjobresult.sas macro, corresponding test, and additional fixes
2021-05-06 01:08:56 +03:00
Allan Bowe
04a3189a89 feat: new mv_getjobresult.sas macro, corresponding test, and additional fixes 2021-05-06 01:07:25 +03:00
Allan Bowe
b1380983ec fix: missing comma 2021-05-05 20:16:26 +03:00
Allan Bowe
b4834f9b40 fix: updates following test runs in Studio 2021-05-05 20:12:06 +03:00
Allan Bowe
1b5ad93cad chore: updating all.sas 2021-05-05 11:48:38 +03:00
Allan Bowe
f2942f2032 chore: adding sasjsresults to .gitignore 2021-05-05 01:39:53 +03:00
Allan Bowe
4198448b81 chore: removing temp results folder 2021-05-05 01:39:29 +03:00
Allan Bowe
47a33452e0 Merge pull request #16 from sasjs/testrelease
feat: new macro for validating inputs (mp_validatecol.sas), also a re…
2021-05-05 01:36:38 +03:00
Allan Bowe
fb21a0adfd feat: new macro for validating inputs (mp_validatecol.sas), also a refresh of the tests now that sasjs test is released. All tests are passing 2021-05-05 01:35:00 +03:00
Allan Bowe
e01b06b640 feat: new assertion macro (mp_assertcols.sas) to test for column existence (or not) 2021-05-04 21:53:57 +03:00
Allan Bowe
24380ddf26 Merge branch 'main' of github.com:sasjs/core 2021-05-03 22:44:07 +03:00
Allan Bowe
1ef42d45af fix: wrapping filter query in brackets to allow logic to be encapsulated when using with other logic sources 2021-05-03 22:43:56 +03:00
Allan Bowe
6ee13a2779 Merge pull request #15 from sasjs/removewarns
fix: removing WARNINGs from code logic
2021-05-03 20:30:43 +03:00
Allan Bowe
ffd2e135dc fix: removing WARNINGs from code logic 2021-05-03 20:28:48 +03:00
Allan Bowe
7f2ad5fc66 feat: mp_filtervalidate.sas - to run a proc sql validate against the target table to ensure validity 2021-05-03 13:48:24 +03:00
ff1eb54cc3 chore: updating logo 2021-05-03 10:59:25 +02:00
Allan Bowe
d6235c6357 chore: reducing raw_value size to 4000 for wider DB support 2021-05-03 11:17:20 +03:00
Allan Bowe
98118adb9a feat: new assertion macro for testing the values in a target column. Designed for use with 'sasjs test'. 2021-05-03 01:00:36 +03:00
Allan Bowe
369c4412f3 fix: adding tests for mp_filtergenerate, also updating the corresponding macros following test results 2021-05-02 22:11:44 +03:00
Allan Bowe
7d7608f06c chore: updating all.sas 2021-05-02 19:12:08 +03:00
Allan Bowe
3791cb8a2c feat: two new macros for checking a filter query, and then generating a filter query. One test to cover the generation part. One more macro to provide assertions on the number of rows in a table, compatible with the upcoming 'sasjs test' feature. 2021-05-02 19:10:37 +03:00
Allan Bowe
ff82f7d75c chore: header update in mf_getvarlist 2021-05-01 20:33:45 +03:00
Allan Bowe
fdd566e8ce fix: setting server headers only if STREAM mode enabled to avoid 'Function is only valid for filerefs using the CACHE access method.' error when testing STPs from Studio. Also removing proc json as it cannot handle invalid characters. 2021-05-01 16:27:41 +03:00
Beast
328f8c260b chore: updating all.sas 2021-05-01 15:34:30 +03:00
Beast
029169ac80 feat: adding mf_getxengine macro for determining the engine of a sas fileref 2021-05-01 15:32:45 +03:00
66ff1de7a9 fix: reducing logging 2021-04-23 23:06:37 +02:00
053290c7df chore: updating header of mp_hashdataset 2021-04-23 07:56:33 +02:00
af71a5e53b feat: new macro for hashing a table (mp_hashdataset) 2021-04-23 00:33:11 +02:00
ecdce86287 fix: adding all.sas also 2021-04-17 00:11:33 +02:00
ba1272aaf7 fix: updating mv_createwebservice to support 0x01 hex characters, adding a test (and test scaffolding) as part of this. The test scaffolding will be updated once goes live - for now it is being deployed as a service. 2021-04-17 00:11:06 +02:00
d6056b9397 fix: adding mod statement to _webout to enable sas-side sasjs testing 2021-04-10 12:41:17 +02:00
Allan Bowe
00511c72c2 fix: removing deprecated params from mm_createstp 2021-04-09 11:46:37 +00:00
Allan Bowe
1d6f04fd56 chore: adding macro related lint settings and sasjs as a recommended extension 2021-04-08 15:59:08 +00:00
af4dbb5632 feat: switching to DATASTEP over PROCJSON for json delivery in sasjs/adapter 2021-04-08 09:49:50 +02:00
Allan Bowe
f48c291dce Merge pull request #13 from sasjs/issue12
fix: switching to data step for JSON generation in mp_jsonout and the…
2021-04-08 08:45:54 +01:00
rafgag
18be74a1c2 Update mp_jsonout.sas
mod option added to the file statement in the last %else %if statement (&action=CLOSE) to avoid output file being overwritten
2021-04-08 09:03:05 +02:00
Allan Bowe
456d10a90e fix: switching to data step for JSON generation in mp_jsonout and the sasjs/adapter for improved reliability when data contains special characters. Closes #12 2021-04-07 22:28:42 +00:00
Allan Bowe
a7fdb52231 fix: sasmeta vs basesas results 2021-04-05 18:26:31 +00:00
Allan Bowe
066ed00e44 chore: reducing line length in lint by 5 characters 2021-04-05 13:31:09 +00:00
Allan Bowe
49fbc210ad Update .gitpod.yml 2021-04-05 14:22:58 +01:00
Allan Bowe
951aa474f2 Update .gitpod.dockerfile 2021-04-05 14:16:22 +01:00
Allan Bowe
961dd54ee0 Update .gitpod.dockerfile 2021-04-05 13:29:39 +01:00
Allan Bowe
921354dac7 Update .gitpod.yml 2021-04-05 12:59:31 +01:00
Allan Bowe
48212f8797 Merge pull request #11 from sasjs/sasjslintfixes
sasjs lint fixes
2021-04-03 20:58:58 +01:00
cb8992dade fix: remove .githooks now we have sasjs lint 2021-04-03 21:54:50 +02:00
7dec3120be chore: dependencies 2021-04-03 21:35:44 +02:00
9568b17f20 feat: enabling sasjs lint as a git pre-commit hook when contributing to @sasjs/core. To use, just run
> ghooks@2.0.4 install /home/zah/git/core/node_modules/ghooks
> node ./bin/module-install

> @sasjs/core@1.0.0 postinstall /home/zah/git/core
> node-git-hooks

Installing Git hooks...
added 14 packages from 12 contributors and audited 205 packages in 4.23s

17 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities from the repository.
2021-04-03 21:34:40 +02:00
0a38056c69 fix: linting 2021-04-03 21:30:51 +02:00
Allan Bowe
096bf4fa11 chore: more indentation fixes 2021-04-03 18:21:29 +00:00
Allan Bowe
030c4a4fc1 fix: .sasjslint file and indentation issues 2021-04-03 18:10:41 +00:00
1b70205cab feat: two new macros, mp_mdtablewrite.sas (will create a markdown table from a sas dataset) and mm_getlibmetadiffs.sas (will create a set of datasets to describe the differences between a library in metadata and the physical library) 2021-04-02 13:38:46 +02:00
539447ed06 chore: fixing all.sas 2021-03-30 16:34:11 +02:00
e3c333ea39 feat: adding mm_deletelibrary.sas, a macro to easily delete a SAS Library from metadata. Documentation: https://core.sasjs.io/mm__deletelibrary_8sas.html 2021-03-30 00:02:20 +02:00
ae72446f85 chore: updating all.sas 2021-03-30 00:01:43 +02:00
2b6bf4bd02 chore: doxy fixes 2021-03-30 00:01:08 +02:00
6dbb3760e0 Merge branch 'main' of github.com:sasjs/core into main 2021-03-29 23:02:33 +02:00
200d9a5761 chore: doxy updates 2021-03-29 23:02:17 +02:00
Allan Bowe
01a9a5b823 Update README.md 2021-03-25 20:09:24 +01:00
Allan Bowe
35eadd0e9d Update README.md 2021-03-25 15:45:28 +01:00
5cdca95216 chore: vscode properties 2021-03-24 19:38:02 +01:00
Allan Bowe
81b75a32ed chore: latest sasjs version 2021-03-24 18:34:58 +00:00
b7f5a2ec00 chore: devops rules, updated gitignore and git hook 2021-03-22 10:14:52 +01:00
db859bbf1d chore: adding a git hook to prevent sas files from appearing with capital letters. To install, just run
> @sasjs/core@1.0.0 postinstall
> node-git-hooks

Installing Git hooks...

up to date, audited 2 packages in 1s

found 0 vulnerabilities.
2021-03-21 23:59:21 +01:00
27b56e8efd set executable 2021-03-21 23:33:19 +01:00
28ea218d02 chore: adding pre-commit hook 2021-03-21 22:24:46 +01:00
f356e1f351 chore: updating CONTRIBUTING, preventing files with spaces being added, adding git hooks package 2021-03-21 22:23:50 +01:00
4b375e0b8c fix: leading zero in time component of mf_uid() 2021-03-19 20:34:16 +01:00
7db207dd1c chore: updating all.sas 2021-03-19 20:29:35 +01:00
Allan Bowe
ffdfc57aa6 Merge pull request #9 from tmoody/main
fix: Closes issue #8. Optionally raise SYSCC and exit early on job no…
2021-03-17 17:32:35 +01:00
Trevor Moody
6fc8408988 fix: Syntax correction for raise_err parameter 2021-03-17 16:31:47 +00:00
Trevor Moody
eeb25fa5bc fix: Closes issue #8. Optionally raise SYSCC and exit early on job not completing successfully 2021-03-17 16:27:10 +00:00
Allan Bowe
521d128afe chore: gitpod file 2021-03-17 09:21:16 +00:00
Allan Bowe
0135dd6c8f chore: updating gitpod files 2021-03-17 07:40:48 +00:00
Allan Bowe
1b66c59dc0 feat: adding gitpod.yml with sasjs code extension 2021-03-15 09:21:27 +00:00
96be5c65dc fix: incorrect assignment of 0D as LF and 0A as CR, fixed in both mv_createwebservice.sas and mv_createjob.sas 2021-03-08 22:06:57 +01:00
8f6ef569e1 fix: adding filename clear statements 2021-03-07 18:47:41 +01:00
ff45c5a8b8 fix: ensuring unique filerefs in mm_updatestpsourcecode macro. Marking previous placeholders as deprecated for future release. 2021-03-07 18:46:32 +01:00
fb5f1c820a chore: delisting the sasjs/cli dependency 2021-03-07 16:43:46 +01:00
c0e33175cf feat: mm_getfoldercontents.sas to fetch immediate children for any folder including a root level folder 2021-03-07 16:19:25 +01:00
2bfa72f48f feat: mv_createjob macro for creating a viya job 2021-03-07 11:46:21 +01:00
fdc2e8ac8a chore: header section for mp_lib2cards.sas 2021-03-04 14:20:04 +01:00
2a894419ab feat: updating mp_lib2cards to enable a single file to be created with all the tables for a particular library 2021-03-01 17:49:26 +01:00
58bfc7b4aa chore: updating doxy formatting to include folder descriptions, also updating headers for some macros 2021-03-01 17:48:44 +01:00
818c0f5eae fix: lua feature discovery logic fix 2021-02-21 17:15:49 +01:00
dff9e2f387 chore: doxy updates 2021-02-21 17:15:17 +01:00
6c9256e097 chore: adding a CONTRIBUTING.md file 2021-02-12 22:07:04 +01:00
0631a05a78 chore(docs): adding a homepage to the doc site and integrating with the sasjs doc command. See https://core.sasjs.io 2021-02-10 00:12:49 +01:00
268bdca4e0 chore: adding sasjsconfig schema file and updating package.json with SASjs CLI devDependency (used to generate doxygen docs) 2021-02-07 21:47:34 +01:00
Allan Bowe
e38f331ad5 Merge pull request #6 from sasjs/sasjsdoc
initial commit
2021-02-04 15:48:20 +02:00
8d64b30419 fix: adding a one second pause between every SAS Job Request in mv_jobflow.sas 2021-02-04 14:12:02 +01:00
4a6c8ffbb3 fix: replacing WARNING with %str(WARN)ING to avoid being caught in searches for mf_getattrn 2021-01-31 18:34:10 +01:00
b5c86e7031 fix: mv_jobflow param mixup, not all jobs were running (fixed now). Also fixed doc formatting, removed unnecessary logging, and fixed a debug switch. 2021-01-31 17:58:13 +01:00
9783edd0e3 feat: adding outref option to mv_jobflow so that logs of submitted jobs can be captured. Also making the context name and flow id optional in the input table, for ease of use. 2021-01-29 12:56:12 +01:00
961728a987 chore: updating header link 2021-01-27 00:28:26 +01:00
4b34322d94 feat: mv_getjoblog.sas macro - will fetch a SAS log from an executed SAS Viya log and append it to a fileref.
mv_jobwaitfor is updated to allow the log to be fetched for all the submitted jobs.
2021-01-27 00:14:21 +01:00
8bb83deede fix: updating return codes 2021-01-26 16:04:44 +01:00
79c81aa8a4 feat: mf_existfileref macro 2021-01-26 16:00:23 +01:00
bbbcf7d550 chore: updating the docs for mf_getquotedstr 2021-01-23 13:37:15 +02:00
82184bc6be fix: adding quit statement so that exit loop would work on step boundary 2021-01-21 21:55:07 +02:00
efc731cfaa feat: mp_testjob macro for running arbitrary long jobs 2021-01-21 21:48:05 +02:00
da9a74ee14 chore: updating doxy headers 2021-01-21 21:47:41 +02:00
94762d9381 feat: mv_jobflow macro - enables a SAS program to kick off multiple waves of SAS Viya jobs, and to limit those waves by a maximum number of parallel (concurrent) running jobs. 2021-01-16 21:34:17 +02:00
03d9d805ff fix: adding support for jobparams in output table for mv_jobwaitfor 2021-01-16 20:43:15 +02:00
94416028b7 fix: adding ACTION parameter to mv_jobwaitfor - can now wait for ANY or ALL jobs to finish 2021-01-16 19:08:38 +02:00
6cf5d4ef28 chore: updating the header description 2021-01-15 23:12:38 +02:00
e4ceaecfb2 feat: adding mv_getjobstate macro to fetch the state of a running SAS Viya job 2021-01-15 13:02:53 +02:00
Allan Bowe
2eb246c543 fix: removing favicon file 2021-01-14 18:07:42 +01:00
d9954ae777 fix: renegade comma 2021-01-14 16:55:17 +02:00
364dc9f07f feat: adding _program value to mv_jobexecute.sas 2021-01-14 16:37:58 +02:00
Saad Jutt
fbd8196230 chore: Doxyfile updated + others formatted 2021-01-09 13:42:55 +05:00
Allan Bowe
5720caaf86 initial commit 2021-01-08 14:28:31 +00:00
d96125c3cf fix: mv_jobwaitfor 2021-01-05 17:14:03 +00:00
506695be56 feat: mv_jobwaitfor macro, similar to waitfor statement (in concept) - will wait for ALL of a set of viya jobs to finish executing 2021-01-05 14:41:27 +00:00
Allan Bowe
45f858db15 fix: scope of json var, brining the %inc _inside_ the macro 2021-01-03 22:35:56 +00:00
Allan Bowe
b4d97a063a fix: doc update for lua files, plus leftover reference in code 2021-01-03 22:30:41 +00:00
Allan Bowe
4df8f3b4c2 feat: mv_getjobcode macro, introducing LUA macros 2021-01-03 22:16:11 +00:00
Allan Bowe
11aa484996 chore: documentation 2020-12-30 17:06:04 +00:00
Allan Bowe
b9fd79bd5e fix: debugging in mm_assignlib 2020-12-25 16:58:30 +00:00
Allan Bowe
1beb30d0ff fix: updating <h4> Dependencies </h4> in header to be <h4> SAS Macros </h4> in line with the updated SASjs compilation process (which distinguishes between SAS Macro and SAS Program dependencies)
BREAKING CHANGE - this doesn't break anything in the framework but I know of at least one old project that uses the <h4> Dependencies </h4> tag to perform backend compilation, so am bumping the version to be safe (looking at you, Chris
2020-12-25 10:36:19 +00:00
Allan Bowe
e334ea9b85 chore: all.sas update 2020-12-25 10:22:44 +00:00
Allan Bowe
c090c8d53b feat: simple macro to test the write speed for a library (very very basic) 2020-12-25 10:18:02 +00:00
Allan Bowe
659339bd98 fix: more comments in mp_prevobs 2020-12-25 10:15:03 +00:00
Allan Bowe
4c333ae7b3 feat: mp_prevobs.sas macro 2020-12-23 00:33:59 +00:00
b3a8b4323e fix: adding new mp_ds2csv macro 2020-12-16 17:11:31 +01:00
0592206f2d patch: doxy formatting 2020-12-03 22:44:08 +01:00
bedc2a443a fix: @cond on new line to prevent parsing issues in sasjs cli 2020-12-02 08:09:51 +01:00
6f86ed62a2 chore: doxy formatting 2020-11-29 22:03:20 +01:00
def0cc8476 fix: adding outds and parameters to mv_jobexecute 2020-11-29 21:55:21 +01:00
3a9029557e chore: doxygen updates 2020-11-29 21:06:39 +01:00
9dc3bcd513 fix: updating all.sas 2020-11-29 13:58:04 +01:00
2bcf6346ac fix: upgrading to latest doxygen 2020-11-29 13:57:44 +01:00
0eccc169f5 feat: adding mv_jobexecute macro (and a fix for mv_getfoldermembers where there are no members) 2020-11-29 13:56:51 +01:00
493639fe4a fix: composite PK 2020-11-26 01:26:16 +01:00
4987d2fbbc fix: missing dependency in mp_getdbml 2020-11-26 01:11:33 +01:00
1a35b357d6 feat: mp_tree macro 2020-11-25 23:21:07 +01:00
a7792d93e4 feat: mf_isdir macro 2020-11-25 22:35:04 +01:00
541dc31ad0 feat: mp_getdbml.sas macro for generating DBML for one or more SAS Libraries 2020-11-25 16:37:42 +01:00
abccafab7b feat: adding filref option to mp_streamfile.sas 2020-11-16 11:08:01 +01:00
f6cec012da fix: removing unnecessary cond flags in mf_abort, adding abort logic in mp_csv2ds 2020-11-08 22:04:25 +01:00
d51be73017 fix: macro param and extra log info in mp_csv2ds 2020-11-03 09:43:47 +01:00
cafffbb509 fix: adding a period to enable formats such as anydtdtme 2020-11-02 17:26:59 +01:00
a88efacfab fix: making view an option so that existence can be checked for 2020-11-02 17:15:29 +01:00
cc7cc55022 feat: mp_csv2ds macro for importing a CSV using a SAS table to provide a template (eg for lengths / types etc) 2020-11-02 15:44:45 +01:00
15687be5d6 fix: tidy up of SAS flavour DDL 2020-10-30 11:43:15 +01:00
d9a82c0bdf fix: incorrect filepath when using filerefs in mp_dirlist 2020-10-29 12:08:07 +01:00
6f06e5540d feat: adding fileref support for mp_dirlist, as well as a directory column on the output dataset 2020-10-29 11:30:15 +01:00
6b782a4fa2 chore: adding sitemap 2020-10-18 01:00:35 +02:00
efe4709dde chore: formatting in mp_guesspk 2020-10-14 16:42:04 +02:00
5cb41041d9 fix: upcase showlog value in mp_getddl() to allow lowercase user entries 2020-10-13 11:20:30 +02:00
f50cb03fd3 fix: mp_ds2cards was failing when the maxobs was less than the number of variables. SQL maxobs option is now reset. 2020-10-12 18:28:50 +02:00
ac46489f11 fix: enabling mp_abort.sas to work in Viya when useComputeApi is true (and the SYS_JES_JOB_URI is empty) 2020-10-11 00:34:08 +02:00
vrh
5e45701e74 fix: extra debug info in mp_searchdata, as well as named literal support 2020-10-02 22:34:36 +02:00
vrh
8caaacd9f0 docs: comment fix 2020-09-28 09:22:29 +02:00
vrh
91983e0a91 fix: trim edge cases and return of the register client url 2020-09-11 00:38:37 +02:00
vrh
7b72f0ac94 fix: alternative base_uri option on tokenauth macro, also description update for listclients 2020-09-10 09:30:09 +02:00
vrh
3eae34d8b7 fix: adding base_uri in all calls to cover instances where viya calls are not on localhost 2020-09-07 14:01:39 +02:00
vrh
58358c916d chore: doc updates 2020-09-05 17:22:38 +02:00
vrh
578ef26cd5 fix: support for tab characters, closes https://github.com/macropeople/macrocore/issues/21 2020-09-04 09:51:11 +02:00
vrh
33189743cd fix: accidental end comment 2020-09-03 18:07:18 +02:00
vrh
459beff4fa feat: mf_trimstr macro 2020-09-03 17:49:44 +02:00
vrh
1c873afe57 fix: base_uri for mv_deletejes 2020-09-03 16:29:21 +02:00
Allan Bowe
2b683509ac Merge pull request #4 from sasjs/change
fix: base_uri
2020-09-03 16:26:48 +02:00
vrh
dcccd1491d fix: base_uri 2020-09-03 16:24:32 +02:00
vrh
8d9b84037c fix: base_uri missing 2020-09-03 16:06:47 +02:00
vrh
029c1a29ed feat: xlsx support in mp_streamfile 2020-08-18 23:09:13 +02:00
vrh
c4dbd5971f docs: formatting 2020-08-08 15:26:02 +02:00
419 changed files with 49488 additions and 10452 deletions

142
.all-contributorsrc Normal file
View File

@@ -0,0 +1,142 @@
{
"projectName": "core",
"projectOwner": "sasjs",
"repoType": "github",
"repoHost": "https://github.com",
"files": [
"README.md"
],
"imageSize": 100,
"commit": false,
"commitConvention": "angular",
"contributors": [
{
"login": "allanbowe",
"name": "Allan Bowe",
"avatar_url": "https://avatars.githubusercontent.com/u/4420615?v=4",
"profile": "https://github.com/allanbowe",
"contributions": [
"business",
"code",
"content",
"doc",
"infra",
"maintenance",
"mentoring",
"question",
"review",
"test"
]
},
{
"login": "rafgag",
"name": "rafgag",
"avatar_url": "https://avatars.githubusercontent.com/u/69139928?v=4",
"profile": "https://github.com/rafgag",
"contributions": [
"code"
]
},
{
"login": "tmoody",
"name": "Trevor Moody",
"avatar_url": "https://avatars.githubusercontent.com/u/79837106?v=4",
"profile": "https://github.com/tmoody",
"contributions": [
"code"
]
},
{
"login": "krishna-acondy",
"name": "Krishna Acondy",
"avatar_url": "https://avatars.githubusercontent.com/u/2980428?v=4",
"profile": "https://krishna-acondy.io/",
"contributions": [
"code",
"infra",
"blog",
"content",
"ideas",
"video"
]
},
{
"login": "saadjutt01",
"name": "Muhammad Saad ",
"avatar_url": "https://avatars.githubusercontent.com/u/8914650?v=4",
"profile": "https://github.com/saadjutt01",
"contributions": [
"code",
"ideas"
]
},
{
"login": "YuryShkoda",
"name": "Yury Shkoda",
"avatar_url": "https://avatars.githubusercontent.com/u/25773492?v=4",
"profile": "https://www.erudicat.com/",
"contributions": [
"code",
"infra",
"video"
]
},
{
"login": "medjedovicm",
"name": "Mihajlo Medjedovic",
"avatar_url": "https://avatars.githubusercontent.com/u/18329105?v=4",
"profile": "https://github.com/medjedovicm",
"contributions": [
"infra"
]
},
{
"login": "kkchandok",
"name": "kkchandok",
"avatar_url": "https://avatars.githubusercontent.com/u/46090627?v=4",
"profile": "https://github.com/kkchandok",
"contributions": [
"ideas"
]
},
{
"login": "VladislavParhomchik",
"name": "Vladislav Parhomchik",
"avatar_url": "https://avatars.githubusercontent.com/u/83717836?v=4",
"profile": "https://github.com/VladislavParhomchik",
"contributions": [
"test",
"review"
]
},
{
"login": "vznesh",
"name": "Vignesh T.",
"avatar_url": "https://avatars.githubusercontent.com/u/28916792?v=4",
"profile": "https://github.com/vznesh",
"contributions": [
"bug"
]
},
{
"login": "yabwon",
"name": "Bart Jablonski",
"avatar_url": "https://avatars.githubusercontent.com/u/9314894?v=4",
"profile": "https://github.com/yabwon",
"contributions": [
"code"
]
},
{
"login": "eltociear",
"name": "Ikko Ashimine",
"avatar_url": "https://avatars.githubusercontent.com/u/22633385?v=4",
"profile": "https://bandism.net/",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,
"skipCi": true
}

8
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/javascript-node/.devcontainer/base.Dockerfile
# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster
ARG VARIANT="18-bullseye"
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT}
RUN apt-get update \
&& apt-get install -y doxygen

View File

@@ -0,0 +1,26 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.233.0/containers/typescript-node
{
"name": "Node.js & TypeScript",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick a Node version: 18, 16, 14.
// Append -bullseye or -buster to pin to an OS version.
// Use -bullseye variants on local on arm64/Apple Silicon.
"args": {
"VARIANT": "16-bullseye"
}
},
// Set *default* container specific settings.json values on container create.
"settings": {},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"SASjs.sasjs-for-vscode"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "npm i && npm i -g @sasjs/cli",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node"
}

View File

@@ -1,12 +0,0 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = false
trim_trailing_whitespace = true

18
.git-hooks/commit-msg Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/sh
RED="\033[1;31m"
GREEN="\033[1;32m"
# Get the commit message (the parameter we're given is just the path to the
# temporary file which holds the message).
commit_message=$(cat "$1")
if (echo "$commit_message" | grep -Eq "^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)(\([a-z \-]+\))?!?: .+$") then
echo "${GREEN} ✔ Commit message meets Conventional Commit standards"
exit 0
fi
echo "${RED}❌ Commit message does not meet the Conventional Commit standard!"
echo "An example of a valid message is:"
echo " feat(login): add the 'remember me' button"
echo " More details at: https://www.conventionalcommits.org/en/v1.0.0/#summary"
exit 1

18
.git-hooks/pre-commit Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
# Ensure lint is passing
LINT=`sasjs lint`
if [[ "$LINT" != "✔ All matched files use @sasjs/lint code style!" ]]; then
echo "$LINT"
echo "To commit in spite of these warnings, use the -n parameter."
exit 1
fi
# Avoid commits to the master branch
BRANCH=`git rev-parse --abbrev-ref HEAD`
if [[ "$BRANCH" =~ ^(master|main|develop)$ ]]; then
echo "You are on branch $BRANCH. Are you sure you want to commit to this branch?"
echo "If so, commit with -n to bypass the pre-commit hook."
exit 1
fi

5
.github/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,5 @@
# CHANGELOG
As the changes are managed automatically in github, we don't generate an additional changelog. To view the fixes/features in each release, check out the releases page below:
[https://github.com/sasjs/core/releases](https://github.com/sasjs/core/releases)

128
.github/CODE_OF_CONDUCT.md vendored Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
https://sasapps.io/contact-us.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

31
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,31 @@
# Contributing
Contributions are warmly welcomed! To avoid any misunderstandings, do please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before submitting a PR.
Please note we have a [code of conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/), please follow it in all your interactions with the project.
# Environment Setup
This repository makes use of the [SASjs](https://sasjs.io) framework for code organisation, compilation, documentation, and deployment. The following tools are highly recommended:
* [NPM](https://sasjs.io/windows/#npm) - the runtime and dependency manager for [SASjs CLI](https://cli.sasjs.io) (batteries included)
* [VSCode](https://sasjs.io/windows/#vscode) - feature packed IDE for code editing (warning - highly effective!)
* [GIT](https://sasjs.io/windows/#git) - a safety net you cannot (and should not) do without.
For generating the documentation (`sasjs doc`) it is also necessary to install [doxygen](https://www.doxygen.nl/manual/install.html) and GraphViz (`sudo port install graphviz` on mac, or `sudo apt-get install graphviz` on Ubuntu).
To get configured:
1. Clone the repository
2. Install local dependencies (`npm install`)
3. Install the SASjs CLI globally (`npm install -g @sasjs/cli`)
4. Add a target, and authentication (`npm add`). See [docs](https://cli.sasjs.io/add/).
To contribute:
1. Create your feature branch (`git checkout -b myfeature`)
2. Make your change
3. Update the `all.sas` file (`python3 build.py`)
4. Push and make a PR

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: [sasjs]

17
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,17 @@
## Issue
Link any related issue(s) in this section.
## Intent
What this PR intends to achieve.
## Implementation
What code changes have been made to achieve the intent.
## Checks
- [ ] Code is formatted correctly (`sasjs lint`).
- [ ] Any new functionality has been unit tested.
- [ ] All unit tests are passing (`sasjs test`).

18
.github/SECURITY.md vendored Normal file
View File

@@ -0,0 +1,18 @@
# Security Policy
Security is an extremely high priority when it comes to the SASjs product suite. We take a number of steps across all repositories to minimise risk, such as:
* Regular dependabot updates
* Snyk reports
* Minimising dependencies, especially production dependencies (sasjs/core has NONE)
* Testing & Code review process
## Supported Versions
We support only the latest version
## Reporting a Vulnerability
We welcome disclosures of all kinds in relation to all the SASjs libraries. You can submit them here: [https://sasapps.io/contact-us](https://sasapps.io/contact-us)

9
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
version: 2
updates:
- package-ecosystem: npm
directory: '/'
schedule:
interval: monthly
open-pull-requests-limit: 3
allow:
- dependency-type: "production"

57
.github/workflows/run-tests.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Node.js CI
on:
pull_request:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [lts/fermium]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install Doxygen
run: sudo apt-get install doxygen
- name: Install dependencies
run: npm ci
- name: Check code style
run: npm run lint
- name: Add client
run: echo "CLIENT=${{secrets.CLIENT}}"> .env.viya
- name: Add secret
run: echo "SECRET=${{secrets.SECRET}}" >> .env.viya
- name: Add access token
run: echo "ACCESS_TOKEN=${{secrets.ACCESS_TOKEN}}" >> .env.viya
- name: Add refresh token
run: echo "REFRESH_TOKEN=${{secrets.REFRESH_TOKEN}}" >> .env.viya
- name: Build Project
run: npm run build
- name: Run SASjs tests
run: npm run test
env:
CI: true
CLIENT: ${{secrets.CLIENT}}
SECRET: ${{secrets.SECRET}}
SAS_USERNAME: ${{secrets.SAS_USERNAME}}
SAS_PASSWORD: ${{secrets.SAS_PASSWORD}}
ACCESS_TOKEN: ${{secrets.ACCESS_TOKEN}}
REFRESH_TOKEN: ${{secrets.REFRESH_TOKEN}}

13
.gitignore vendored
View File

@@ -1,2 +1,13 @@
node_modules
.DS_Store
.DS_Store
sasjsbuild/
sasjsresults/
# avoid filenames with spaces being committed to source control
**\ **
# ignore the mc_* files - containing macros for individual libraries
mc_*
# ignore .env files as they can contain sasjs access tokens
*.env*

6
.gitpod.dockerfile Normal file
View File

@@ -0,0 +1,6 @@
FROM gitpod/workspace-full
RUN sudo apt-get update \
&& sudo apt-get install -y doxygen \
&& sudo apt-get install -y graphviz \
&& sudo rm -rf /var/lib/apt/lists/*

27
.gitpod.yml Normal file
View File

@@ -0,0 +1,27 @@
tasks:
- init: npm install -g npm
- command: npm i
- command: npm i -g @sasjs/cli
image:
file: .gitpod.dockerfile
vscode:
extensions:
- sasjs.sasjs-for-vscode
github:
prebuilds:
# enable for the master/default branch (defaults to true)
master: true
# enable for all branches in this repo (defaults to false)
branches: false
# enable for pull requests coming from this repo (defaults to true)
pullRequests: true
# enable for pull requests coming from forks (defaults to false)
pullRequestsFromForks: true
# add a "Review in Gitpod" button as a comment to pull requests (defaults to true)
addComment: true
# add a "Review in Gitpod" button to pull requests (defaults to false)
addBadge: false
# add a label once the prebuild is ready to pull requests (defaults to false)
addLabel: prebuilt-in-gitpod

11
.npmignore Normal file
View File

@@ -0,0 +1,11 @@
all.sas
build.py
.gitpod*
tests/
sasjs/
.github/
.git-hooks/
.vscode/
make_singlefile.sh
*.md
.all-contributorsrc

13
.sasjslint Normal file
View File

@@ -0,0 +1,13 @@
{
"noTrailingSpaces": true,
"noEncodedPasswords": true,
"hasDoxygenHeader": true,
"hasMacroNameInMend": true,
"hasMacroParentheses": true,
"noNestedMacros": false,
"noSpacesInFileNames": true,
"maxLineLength": 300,
"lowerCaseFileNames": true,
"noTabIndentation": true,
"indentationMultiple": 2
}

9
.vscode/.editorconfig vendored Normal file
View File

@@ -0,0 +1,9 @@
{
"search.exclude": {
"**/sasjsbuild/**": true,
"**/dist/**":true
},
"editor.insertSpaces": true,
"editor.tabSize": 2,
"trim_trailing_whitespace": true
}

5
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"recommendations": [
"sasjs.sasjs-for-vscode"
]
}

10
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,10 @@
{
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.detectIndentation": true,
"editor.formatOnSave": true,
"editor.rulers": [
80
],
"files.trimTrailingWhitespace": true
}

View File

@@ -1,83 +0,0 @@
# Contributing
Contributions to the macrocore library are warmly welcomed! To avoid any
misunderstandings, do please first discuss the change you wish to make via issue,
email, or any other method with the owners of this repository before submitting
a PR.
Please note we have a code of conduct, please follow it in all your interactions
with the project.
## Code of Conduct
### Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
### Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
### Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
### Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at support@macropeople.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

2452
Doxyfile

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
Copyright 2018 (Allan Bowe)
Copyright 2021 (Allan Bowe)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

242
README.md
View File

@@ -1,6 +1,24 @@
# Macro Core
[![npm package][npm-image]][npm-url]
[![Github Workflow][githubworkflow-image]][githubworkflow-url]
![npm](https://img.shields.io/npm/dt/@sasjs/core)
![Snyk Vulnerabilities for npm package](https://img.shields.io/snyk/vulnerabilities/npm/@sasjs/core)
[![License](https://img.shields.io/apm/l/atomic-design-ui.svg)](/LICENSE)
![GitHub top language](https://img.shields.io/github/languages/top/sasjs/core)
[![GitHub closed issues](https://img.shields.io/github/issues-closed-raw/sasjs/core)](https://github.com/sasjs/core/issues?q=is%3Aissue+is%3Aclosed)
[![GitHub issues](https://img.shields.io/github/issues-raw/sasjs/core)](https://github.com/sasjs/core/issues)
![total lines](https://tokei.rs/b1/github/sasjs/core)
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/sasjs/core)
Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of Application Development on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/CONTRIBUTING.md) are welcomed.
[npm-image]:https://img.shields.io/npm/v/@sasjs/core.svg
[npm-url]:http://npmjs.org/package/@sasjs/core
[githubworkflow-image]:https://github.com/sasjs/core/actions/workflows/main.yml/badge.svg
[githubworkflow-url]:https://github.com/sasjs/core/blob/main/.github/workflows/main.yml
[dependency-url]:https://github.com/sasjs/core/blob/main/package.json
Much quality. Many standards. The **Macro Core** library exists to save time and development effort! Herein ye shall find a veritable host of MIT-licenced, production quality SAS macros. These are a mix of tools, utilities, functions and code generators that are useful in the context of [Application Development](https://sasapps.io) on the SAS platform (eg https://datacontroller.io). [Contributions](https://github.com/sasjs/core/blob/main/.github/CONTRIBUTING.md) are welcome.
You can download and compile them all in just two lines of SAS code:
@@ -9,44 +27,108 @@ filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
```
Documentation: https://sasjs.github.io/core.github.io/files.html
Documentation: https://core.sasjs.io
# Components
## Components
**base** library (SAS9/Viya)
### BASE folder (All Platforms)
- OS independent
- Not metadata aware
- Works on all SAS Platforms
- No X command
- Prefixes: _mf_, _mp_
- Prefixes: `mf_`, `mp_`
**meta** library (SAS9 only)
### DDL folder (All Platforms)
- OS independent
- Works on all SAS Platforms
- No X command
- Prefixes: `mddl_(lib)_` -> where lib can be "SAS" (in relation to a SAS component) or "DC" (in relation to a Data Controller component)
This library will not be used for storing data entries (such as formats or datalines). Where this becomes necessary in the future, a new repo will be created, in order to keep the NPM bundle size down (for the benefit of those looking to embed purely macros in their applications).
### FCMP folder (All Platforms)
- Function and macro names are identical, except for special cases
- Prefixes: `mcf_`
The fcmp macros are used to generate fcmp functions, and can be used with or without the `proc fcmp` wrapper.
### LUA folder
Wait - this is a macro library - what is LUA doing here? Well, it is a little known fact that you CAN run LUA within a SAS Macro. It has to be written to a text file with a `.lua` extension, from where you can `%include` it. So, without using the `proc lua` wrapper.
To contribute, simply write your freeform LUA in the LUA folder. Then run the `build.py`, which will convert all files with a ".lua" extension into a macro wrapper with an `ml_` prefix (embedding the necessary data step put statements). You can then use your module in any program by running:
```sas
/* compile the lua module */
%ml_yourmodule()
/* Execute. Do not use the restart keyword! */
proc lua;
submit;
print(yourStuff);
endsubmit;
run;
```
- Prefixes: `ml_`
### META folder (SAS9 only)
Macros used in SAS EBI, which connect to the metadata server.
- OS independent
- Metadata aware
- No X command
- Prefixes: _mm_
- Prefixes: `mm_`
**viya** library (Viya only)
- OS independent
- No X command
- Prefixes: _mv_
**metax** library (SAS9 only)
### METAX folder (SAS9 only)
- OS specific
- Metadata aware
- X command enabled
- Prefixes: _mmw_,_mmu_,_mmx_
- Prefixes: `mmx_`
# Installation
### SERVER folder (@sasjs/server only)
These macros are used for building applications using [@sasjs/server](https://server.sasjs.io) - an open source REST API for Desktop SAS.
First, download the repo to a location your SAS system can access. Then update your sasautos path to include the components you wish to have available,eg:
- OS independent
- @sasjs/server aware
- No X command
- Prefixes: `ms_`
### VIYA folder (Viya only)
Macros used for interfacing with SAS Viya.
- OS independent
- No X command
- Prefixes: `mv_`, `mvf_`
### XPLATFORM folder (Viya, Meta, and Server)
Sometimes it is helpful to use a macro that can be used interchangeably regardless of the server type on which is is running (SASVIYA, SAS9, SASJS).
- OS independent
- No X command
- Prefixes: `mx_`
## Installation
First, download the repo to a location your SAS system can access. Then update your sasautos path to include the components you wish to have available, eg:
```sas
options insert=(sasautos="/your/path/macrocore/base");
options insert=(sasautos="/your/path/macrocore/meta");
%let repoloc=/your/path/core;
options insert=(sasautos="&repoloc/base");
options insert=(sasautos="&repoloc/ddl");
options insert=(sasautos="&repoloc/fcmp");
options insert=(sasautos="&repoloc/lua");
options insert=(sasautos="&repoloc/meta");
options insert=(sasautos="&repoloc/metax");
options insert=(sasautos="&repoloc/server");
options insert=(sasautos="&repoloc/viya");
options insert=(sasautos="&repoloc/xplatform");
```
The above can be done directly in your sas program, via an autoexec, or an initialisation program.
@@ -58,28 +140,32 @@ filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
```
# Standards
## Standards
## File Properties
### File Properties
- filenames much match macro names
- filenames must be lowercase
- filenames must be lowercase, without spaces
- macro names must be lowercase
- one macro per file
- prefixes:
- _mcf_ for macro compiled functions (proc fcmp)
- _mddl_ for macros containing DDL (Data Definition Language)
- _mf_ for macro functions (can be used in open code).
- _mp_ for macro procedures (which generate sas code)
- _ml_ for macros that are used to compile LUA modules
- _mm_ for metadata macros (interface with the metadata server).
- _mmx_ for macros that use metadata and are XCMD enabled
- _mx_ for macros that are XCMD enabled
- _mv_ for macros that will only work in Viya
- _mmx_ for macros that use metadata and are XCMD enabled (working on both windows and unix)
- _mp_ for macro procedures (which generate sas code)
- _ms_ for macro procedures that will only work with [@sasjs/server](https://github.com/sasjs/server)
- _mv_ for macro procedures that will only work in Viya
- _mx_ for macros that work on Viya, SAS 9 EBI and SASjs Server
- follow verb-noun convention
- unix style line endings (lf)
- individual lines should be no more than 80 characters long
- UTF-8
- no trailing white space
## Header Properties
### Header Properties
The **Macro Core** documentation is created using [doxygen](http://www.doxygen.nl). A full list of attributes can be found [here](http://www.doxygen.nl/manual/commands.html) but the following are most relevant:
@@ -91,18 +177,106 @@ The **Macro Core** documentation is created using [doxygen](http://www.doxygen.n
- version. The EARLIEST SAS version in which this macro is known to work.
- author. Author name, contact details optional
All macros must be commented in the doxygen format, to enable the [online documentation](https://sasjs.github.io/core.github.io/).
All macros must be commented in the doxygen format, to enable the [online documentation](https://core.sasjs.io).
## Coding Standards
#### Dependencies
SAS code can contain one of two types of dependency - SAS Macros, and SAS Includes. When compiling projects using the [SASjs CLI](https://cli.sasjs.io) the doxygen header is scanned for ` @li` items under the following headers:
```sas
<h4> SAS Macros </h4>
@li mf_nobs.sas
@li mm_assignlib.sas
<h4> SAS Includes </h4>
@li somefile.ddl SOMEFREF
@li someprogram.sas FREFTWO
```
The CLI can then extract all the dependencies and insert as precode (SAS Macros) or in a temp engine fileref (SAS Includes) when creating SAS Jobs and Services (and Tests).
When contributing to this library, it is therefore important to ensure that all dependencies are listed in the header in this format.
### Coding Standards
- Indentation = 2 spaces. No tabs!
- no trailing white space
- no invisible characters, other than spaces. If invisibles are needed, use hex literals.
- Macro variables should not have the trailing dot (`&var` not `&var.`) unless necessary to prevent incorrect resolution
- The closing `%mend;` should not contain the macro name.
- The closing `%mend;` should **not** contain the macro name.
- All macros should be defined with brackets, even if no variables are needed - ie `%macro x();` not `%macro x;`
- Mandatory parameters should be positional, all optional parameters should be keyword (var=) style.
- All dataset references must be 2 level (eg `work.blah`, not `blah`). This is to avoid contention when options [DATASTMTCHK](https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000279064.htm)=ALLKEYWORDS is in effect.
- All dataset references must be 2 level (eg `work.blah`, not `blah`). This is to avoid contention when options [DATASTMTCHK](https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000279064.htm)=ALLKEYWORDS is in effect, or the [USER](https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/lrcon/n18m1vkqmeo4esn1moikt23zhp8s.htm) library is active.
- Avoid naming collisions! All macro variables should be local scope. Use system generated work tables where possible - eg `data ; set sashelp.class; run; data &output; set &syslast; run;`
- Where global macro variables are absolutely necessary, they should make use of `&sasjs_prefix` - see mp_init.sas
- The use of `quit;` for `proc sql` is optional unless you are looking to benefit from the timing statistics.
- Use [sasjs lint](https://github.com/sasjs/lint)!
# General Notes
## General Notes
- All macros should be compatible with SAS versions from support level B and above (so currently 9.2 and later). If an earlier version is not supported, then the macro should say as such in the header documentation, and exit gracefully (eg `%if %sysevalf(&sysver<9.3) %then %return`).
## Breaking Changes
We are currently on major release v4. Breaking changes should be marked with the [deprecated](https://www.doxygen.nl/manual/commands.html#cmddeprecated) doxygen tag. The following changes are planned when the next major/breaking release (v5) becomes necessary:
* mf_getuniquelibref.sas to have the deprecated maxtried parameter removed (no longer needed)
* mp_testservice.sas to be renamed as mp_execute.sas (as it doesn't actually test anything)
* `insert_cmplib` option of mcf_xxx macros will be deprecated (the option is now checked automatically with value inserted only if needed)
* mcf_xxx macros to have `wrap=` option defaulted to YES for convenience. Set this option explicitly to avoid issues.
* mp_getddl.sas to be renamed to mp_ds2ddl.sas (consistent with other ds2xxx macros). A wrapper macro is already in place, and you are able to use this immediately. The default for SHOWLOG will also be YES instead of NO.
* mp_coretable.sas will be replaced by the standalone macros in the `ddl` folder (which are already available)
## Star Gazing
If you find this library useful, please leave a [star](https://github.com/sasjs/core/stargazers) and help us grow our star graph!
![](https://starchart.cc/sasjs/core.svg)
## Other SAS Repositories
The following repositories are also worth checking out:
* [xieliaing/SAS](https://github.com/xieliaing/SAS)
* [SASJedi/sas-macros](https://github.com/SASJedi/sas-macros)
* [chris-swenson/sasmacros](https://github.com/chris-swenson/sasmacros)
* [greg-wotton/sas-programs](https://github.com/greg-wootton/sas-programs)
* [KatjaGlassConsulting/SMILE-SmartSASMacros](https://github.com/KatjaGlassConsulting/SMILE-SmartSASMacros)
* [rogerjdeangelis](https://github.com/rogerjdeangelis)
* [scottbass/sas](https://github.com/scottbass/SAS)
* [yabwon/sas_packages](https://github.com/yabwon/SAS_PACKAGES)
## Contributors ✨
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-12-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="https://github.com/allanbowe"><img src="https://avatars.githubusercontent.com/u/4420615?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Allan Bowe</b></sub></a><br /><a href="#business-allanbowe" title="Business development">💼</a> <a href="https://github.com/sasjs/core/commits?author=allanbowe" title="Code">💻</a> <a href="#content-allanbowe" title="Content">🖋</a> <a href="https://github.com/sasjs/core/commits?author=allanbowe" title="Documentation">📖</a> <a href="#infra-allanbowe" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-allanbowe" title="Maintenance">🚧</a> <a href="#mentoring-allanbowe" title="Mentoring">🧑‍🏫</a> <a href="#question-allanbowe" title="Answering Questions">💬</a> <a href="https://github.com/sasjs/core/pulls?q=is%3Apr+reviewed-by%3Aallanbowe" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/sasjs/core/commits?author=allanbowe" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/rafgag"><img src="https://avatars.githubusercontent.com/u/69139928?v=4?s=100" width="100px;" alt=""/><br /><sub><b>rafgag</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=rafgag" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/tmoody"><img src="https://avatars.githubusercontent.com/u/79837106?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Trevor Moody</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=tmoody" title="Code">💻</a></td>
<td align="center"><a href="https://krishna-acondy.io/"><img src="https://avatars.githubusercontent.com/u/2980428?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Krishna Acondy</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=krishna-acondy" title="Code">💻</a> <a href="#infra-krishna-acondy" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#blog-krishna-acondy" title="Blogposts">📝</a> <a href="#content-krishna-acondy" title="Content">🖋</a> <a href="#ideas-krishna-acondy" title="Ideas, Planning, & Feedback">🤔</a> <a href="#video-krishna-acondy" title="Videos">📹</a></td>
<td align="center"><a href="https://github.com/saadjutt01"><img src="https://avatars.githubusercontent.com/u/8914650?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Muhammad Saad </b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=saadjutt01" title="Code">💻</a> <a href="#ideas-saadjutt01" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://www.erudicat.com/"><img src="https://avatars.githubusercontent.com/u/25773492?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yury Shkoda</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=YuryShkoda" title="Code">💻</a> <a href="#infra-YuryShkoda" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#video-YuryShkoda" title="Videos">📹</a></td>
<td align="center"><a href="https://github.com/medjedovicm"><img src="https://avatars.githubusercontent.com/u/18329105?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mihajlo Medjedovic</b></sub></a><br /><a href="#infra-medjedovicm" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/kkchandok"><img src="https://avatars.githubusercontent.com/u/46090627?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kkchandok</b></sub></a><br /><a href="#ideas-kkchandok" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/VladislavParhomchik"><img src="https://avatars.githubusercontent.com/u/83717836?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vladislav Parhomchik</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=VladislavParhomchik" title="Tests">⚠️</a> <a href="https://github.com/sasjs/core/pulls?q=is%3Apr+reviewed-by%3AVladislavParhomchik" title="Reviewed Pull Requests">👀</a></td>
<td align="center"><a href="https://github.com/vznesh"><img src="https://avatars.githubusercontent.com/u/28916792?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vignesh T.</b></sub></a><br /><a href="https://github.com/sasjs/core/issues?q=author%3Avznesh" title="Bug reports">🐛</a></td>
<td align="center"><a href="https://github.com/yabwon"><img src="https://avatars.githubusercontent.com/u/9314894?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bart Jablonski</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=yabwon" title="Code">💻</a></td>
<td align="center"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=eltociear" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

21964
all.sas

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,17 @@
/**
@file
@brief abort gracefully according to context
@details Do not use directly! See bottom of explanation for details.
@brief Abort, ungracefully
@details Will abort with a straightforward %abort if the condition is true.
Configures an abort mechanism according to site specific policies or the
particulars of an environment. For instance, can stream custom
results back to the client in an STP Web App context, or completely stop
in the case of a batch run.
For the sharp eyed readers - this is no longer a macro function!! It became
a macro procedure during a project and now it's kinda stuck that way until
that project is updated (if it's ever updated). In the meantime we created
`mp_abort` which is just a wrapper for this one, and so we recomend you use
that for forwards compatibility reasons.
@param mac= to contain the name of the calling macro
@param type= deprecated. Not used.
@param msg= message to be returned
@param iftrue= supply a condition under which the macro should be executed.
<h4> Related Macros </h4>
@li mp_abort.sas
@version 9.2
@author Allan Bowe
@cond
**/
%macro mf_abort(mac=mf_abort.sas, type=, msg=, iftrue=%str(1=1)
%macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1)
)/*/STORE SOURCE*/;
%if not(%eval(%unquote(&iftrue))) %then %return;
@@ -32,110 +20,8 @@
%if %length(&mac)>0 %then %put NOTE- called by &mac;
%put NOTE - &msg;
/* Stored Process Server web app context */
%if %symexist(_metaperson) or "&SYSPROCESSNAME"="Compute Server" %then %do;
options obs=max replace nosyntaxcheck mprint;
/* extract log err / warn, if exist */
%local logloc logline;
%global logmsg; /* capture global messages */
%if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG;
%else %let logloc=%qsysfunc(getoption(LOG));
proc printto log=log;run;
%if %length(&logloc)>0 %then %do;
%let logline=0;
data _null_;
infile &logloc lrecl=5000;
input; putlog _infile_;
i=1;
retain logonce 0;
if (_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR") and logonce=0 then do;
call symputx('logline',_n_);
logonce+1;
end;
run;
/* capture log including lines BEFORE the err */
%if &logline>0 %then %do;
data _null_;
infile &logloc lrecl=5000;
input;
i=1;
stoploop=0;
if _n_ ge &logline-5 and stoploop=0 then do until (i>12);
call symputx('logmsg',catx('\n',symget('logmsg'),_infile_));
input;
i+1;
stoploop=1;
end;
if stoploop=1 then stop;
run;
%end;
%end;
%abort;
/* send response in SASjs JSON format */
data _null_;
file _webout mod lrecl=32000;
length msg $32767;
sasdatetime=datetime();
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
/* escape the quotes */
msg=tranwrd(msg,'"','\"');
/* ditch the CRLFs as chrome complains */
msg=compress(msg,,'kw');
/* quote without quoting the quotes (which are escaped instead) */
msg=cats('"',msg,'"');
if symexist('_debug') then debug=symget('_debug');
if debug ge 131 then put '>>weboutBEGIN<<';
put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
put ',"sasjsAbort" : [{';
put ' "MSG":' msg ;
put ' ,"MAC": "' "&mac" '"}]';
put ",""SYSUSERID"" : ""&sysuserid"" ";
if symexist('_metauser') then do;
_METAUSER=quote(trim(symget('_METAUSER')));
put ",""_METAUSER"": " _METAUSER;
_METAPERSON=quote(trim(symget('_METAPERSON')));
put ',"_METAPERSON": ' _METAPERSON;
end;
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
put ",""SYSJOBID"" : ""&sysjobid"" ";
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
put "}" @;
%if &_debug ge 131 %then %do;
put '>>weboutEND<<';
%end;
run;
%let syscc=0;
%if %symexist(SYS_JES_JOB_URI) %then %do;
/* refer web service output to file service in one hit */
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json";
%let rc=%sysfunc(fcopy(_web,_webout));
%end;
%else %do;
data _null_;
if symexist('sysprocessmode')
then if symget("sysprocessmode")="SAS Stored Process Server"
then rc=stpsrvset('program error', 0);
run;
%end;
/**
* endsas is reliable but kills some deployments.
* Abort variants are ungraceful (non zero return code)
* This approach lets SAS run silently until the end :-)
*/
%put _all_;
filename skip temp;
data _null_;
file skip;
put '%macro skip(); %macro skippy();';
run;
%inc skip;
%end;
%else %do;
%put _all_;
%abort cancel;
%end;
%mend;
%mend mf_abort;
/** @endcond */

53
base/mf_dedup.sas Normal file
View File

@@ -0,0 +1,53 @@
/**
@file
@brief de-duplicates a macro string
@details Removes all duplicates from a string of words. A delimeter can be
chosen. Is inspired heavily by this excellent [macro](
https://github.com/scottbass/SAS/blob/master/Macro/dedup_mstring.sas) from
[Scott Base](https://www.linkedin.com/in/scottbass). Case sensitive.
Usage:
%let str=One two one two and through and through;
%put %mf_dedup(&str);
%put %mf_dedup(&str,outdlm=%str(,));
Which returns:
> One two one and through
> One,two,one,and,through
@param [in] str String to be deduplicated
@param [in] indlm= ( ) Delimeter of the input string
@param [out] outdlm= ( ) Delimiter of the output string
<h4> Related Macros </h4>
@li mf_trimstr.sas
@version 9.2
@author Allan Bowe
**/
%macro mf_dedup(str
,indlm=%str( )
,outdlm=%str( )
)/*/STORE SOURCE*/;
%local num word i pos out;
%* loop over each token, searching the target for that token ;
%let num=%sysfunc(countc(%superq(str),%str(&indlm)));
%do i=1 %to %eval(&num+1);
%let word=%scan(%superq(str),&i,%str(&indlm));
%let pos=%sysfunc(indexw(&out,&word,%str(&outdlm)));
%if (&pos eq 0) %then %do;
%if (&i gt 1) %then %let out=&out%str(&outdlm);
%let out=&out&word;
%end;
%end;
%unquote(&out)
%mend mf_dedup;

31
base/mf_deletefile.sas Normal file
View File

@@ -0,0 +1,31 @@
/**
@file
@brief Deletes a physical file, if it exists
@details Usage:
%mf_writefile(&sasjswork/myfile.txt,l1=some content)
%mf_deletefile(&sasjswork/myfile.txt)
%mf_deletefile(&sasjswork/myfile.txt)
@param filepath Full path to the target file
@returns The return code from the fdelete() invocation
<h4> Related Macros </h4>
@li mf_deletefile.test.sas
@li mf_writefile.sas
@version 9.2
@author Allan Bowe
**/
%macro mf_deletefile(file
)/*/STORE SOURCE*/;
%local rc fref;
%let rc= %sysfunc(filename(fref,&file));
%if %sysfunc(fdelete(&fref)) ne 0 %then %put %sysfunc(sysmsg());
%let rc= %sysfunc(filename(fref));
%mend mf_deletefile;

View File

@@ -12,6 +12,10 @@
@param libds library.dataset
@return output returns 1 or 0
<h4> Related Macros </h4>
@li mf_existds.test.sas
@warning Untested on tables registered in metadata but not physically present
@version 9.2
@author Allan Bowe
@@ -23,4 +27,4 @@
%if %sysfunc(exist(&libds)) ne 1 & %sysfunc(exist(&libds,VIEW)) ne 1 %then 0;
%else 1;
%mend;
%mend mf_existds;

View File

@@ -1,26 +1,25 @@
/**
@file mf_existfeature.sas
@file
@brief Checks whether a feature exists
@details Check to see if a feature is supported in your environment.
Run without arguments to see a list of detectable features.
Note - this list is based on known versions of SAS rather than
actual feature detection, as that is tricky / impossible to do
without generating errors in most cases.
without generating errs in most cases.
%put %mf_existfeature(PROCLUA);
%put %mf_existfeature(PROCLUA);
@param [in] feature The feature to detect.
@param feature the feature to detect. Leave blank to list all in log.
@return output returns 1 or 0 (or -1 if not found)
<h4> Dependencies </h4>
<h4> SAS Macros </h4>
@li mf_getplatform.sas
@version 8
@author Allan Bowe
**/
/** @cond */
%macro mf_existfeature(feature
)/*/STORE SOURCE*/;
%let feature=%upcase(&feature);
@@ -28,15 +27,33 @@
%let platform=%mf_getplatform();
%if &feature= %then %do;
%put Supported features: PROCLUA;
%put No feature was requested for detection;
%end;
%else %if &feature=COLCONSTRAINTS %then %do;
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 0;
%else 1;
%end;
%else %if &feature=PROCLUA %then %do;
/* https://blogs.sas.com/content/sasdummy/2015/08/03/using-lua-within-your-sas-programs */
%if &platform=SASVIYA %then 1;
%else %if "&sysver"="9.3" or "&sysver"="9.4" %then 1;
%else %if "&sysver"="9.2" or "&sysver"="9.3" %then 0;
%else %if "&SYSVLONG" < "9.04.01M3" %then 0;
%else 1;
%end;
%else %if &feature=DBMS_MEMTYPE %then %do;
/* does dbms_memtype exist in dictionary.tables? */
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 0;
%else 1;
%end;
%else %if &feature=EXPORTXLS %then %do;
/* is it possible to PROC EXPORT an excel file? */
%if "%substr(&sysver,1,1)"="4" or "%substr(&sysver,1,1)"="5" %then 1;
%else %if %sysfunc(sysprod(SAS/ACCESS Interface to PC Files)) = 1 %then 1;
%else 0;
%end;
%else %do;
-1
%put &sysmacroname: &feature not found;
%end;
%mend;
%mend mf_existfeature;
/** @endcond */

33
base/mf_existfileref.sas Normal file
View File

@@ -0,0 +1,33 @@
/**
@file
@brief Checks whether a fileref exists
@details You can probably do without this macro as it is just a one liner.
Mainly it is here as a convenient way to remember the syntax!
@param fref the fileref to detect
@return output Returns 1 if found and 0 if not found. Note - it is possible
that the fileref is found, but the file does not (yet) exist. If you need
to test for this, you may as well use the fileref function directly.
@version 8
@author [Allan Bowe](https://www.linkedin.com/in/allanbowe/)
**/
%macro mf_existfileref(fref
)/*/STORE SOURCE*/;
%local rc;
%let rc=%sysfunc(fileref(&fref));
%if &rc=0 %then %do;
1
%end;
%else %if &rc<0 %then %do;
%put &sysmacroname: Fileref &fref exists but the underlying file does not;
1
%end;
%else %do;
0
%end;
%mend mf_existfileref;

37
base/mf_existfunction.sas Normal file
View File

@@ -0,0 +1,37 @@
/**
@file
@brief Checks if a function exists
@details Returns 1 if the function exists, else 0. Note that this function
can be slow as it needs to open the sashelp.vfuncs table.
Usage:
%put %mf_existfunction(CAT);
%put %mf_existfunction(DOG);
Full credit to [Bart](https://sasensei.com/user/305) for the vfunc pointer
and the tidy approach for pure macro data set filtering.
Check out his [SAS Packages](https://github.com/yabwon/SAS_PACKAGES)
framework! Where you can find the same [function](
https://github.com/yabwon/SAS_PACKAGES/blob/main/packages/baseplus.md#functionexists-macro
).
@param [in] name (positional) - function name
@author Allan Bowe
**/
/** @cond */
%macro mf_existfunction(name
)/*/STORE SOURCE*/;
%local dsid rc exist;
%let dsid=%sysfunc(open(sashelp.vfunc(where=(fncname="%upcase(&name)"))));
%let exist=1;
%let exist=%sysfunc(fetch(&dsid, NOSET));
%let rc=%sysfunc(close(&dsid));
%sysevalf(0 = &exist)
%mend mf_existfunction;
/** @endcond */

View File

@@ -1,17 +1,22 @@
/**
@file
@brief Checks if a variable exists in a data set.
@details Returns 0 if the variable does NOT exist, and return the position of
the var if it does.
Usage:
@details Returns 0 if the variable does NOT exist, and the position of the var
if it does.
Usage:
%put %mf_existvar(work.someds, somevar)
%put %mf_existvar(work.someds, somevar)
@param [in] libds 2 part dataset or view reference
@param [in] var variable name
<h4> Related Macros </h4>
@li mf_existvar.test.sas
@param libds (positional) - 2 part dataset or view reference
@param var (positional) - variable name
@version 9.2
@author Allan Bowe
**/
/** @cond */
%macro mf_existvar(libds /* 2 part dataset name */
, var /* variable name */
@@ -29,4 +34,6 @@
%let rc=%sysfunc(close(&dsid));
%end;
%mend;
%mend mf_existvar;
/** @endcond */

View File

@@ -2,18 +2,16 @@
@file
@brief Checks if a set of variables ALL exist in a data set.
@details Returns 0 if ANY of the variables do not exist, or 1 if they ALL do.
Usage:
Usage:
%put %mf_existVarList(sashelp.class, age sex name dummyvar)
<h4> Dependencies </h4>
@li mf_abort.sas
%put %mf_existVarList(sashelp.class, age sex name dummyvar);
@param libds 2 part dataset or view reference
@param varlist space separated variable names
@version 9.2
@author Allan Bowe
@cond
**/
%macro mf_existvarlist(libds, varlist
@@ -28,7 +26,7 @@
%let dsid=%sysfunc(open(&libds,is));
%if &dsid=0 %then %do;
%put WARNING: unable to open &libds in mf_existvarlist (&dsid);
%put %str(WARN)ING: unable to open &libds in mf_existvarlist (&dsid);
%end;
%if %sysfunc(attrn(&dsid,NVARS))=0 %then %do;
@@ -53,4 +51,6 @@
0
%put Vars not found: &found;
%end;
%mend;
%mend mf_existvarlist;
/** @endcond */

42
base/mf_fmtdttm.sas Normal file
View File

@@ -0,0 +1,42 @@
/**
@file
@brief Returns E8601DT26.6 if compatible else DATETIME19.3
@details From our experience in [Data Controller for SAS]
(https://datacontroller.io) deployments, the E8601DT26.6 datetime format has
the widest support when it comes to pass-through SQL queries.
However, it is not supported in WPS or early versions of SAS 9 (M3 and below)
when used as a datetime literal, eg:
data _null_;
demo="%sysfunc(datetime(),E8601DT26.6)"dt;
demo=;
run;
This macro will therefore return DATEITME19.3 as an alternative format
based on the runtime environment so that it can be used in such cases, eg:
data _null_;
demo="%sysfunc(datetime(),%mf_fmtdttm())"dt;
demo=;
run;
<h4> Related Macros </h4>
@li mf_fmtdttm.test.sas
@author Allan Bowe
**/
%macro mf_fmtdttm(
)/*/STORE SOURCE*/;
%if "&sysver"="9.2" or "&sysver"="9.3"
or ("&sysver"="9.4" and "%substr(&SYSVLONG,9,1)" le "3")
or "%substr(&sysver,1,1)"="4"
or "%substr(&sysver,1,1)"="5"
%then %do;DATETIME19.3%end;
%else %do;E8601DT26.6%end;
%mend mf_fmtdttm;

78
base/mf_getapploc.sas Normal file
View File

@@ -0,0 +1,78 @@
/**
@file
@brief Returns the appLoc from the _program variable
@details When working with SASjs apps, web services / tests / jobs are always
deployed to a root (app) location in the SAS logical folder tree.
When building apps for use in other environments, you do not necessarily know
where the backend services will be deployed. Therefore a function like this
is handy in order to dynamically figure out the appLoc, and enable other
services to be connected by a relative reference.
SASjs apps always have the same immediate substructure (one or more of the
following):
@li /data
@li /jobs
@li /services
@li /tests
@li /tests/jobs
@li /tests/services
@li /tests/macros
This function works by testing for the existence of any of the above in the
automatic _program variable, and returning the part to the left of it.
Usage:
%put %mf_getapploc(&_program)
%put %mf_getapploc(/some/location/services/admin/myservice);
%put %mf_getapploc(/some/location/jobs/extract/somejob/);
%put %mf_getapploc(/some/location/tests/jobs/somejob/);
@author Allan Bowe
**/
%macro mf_getapploc(pgm);
%if "&pgm"="" %then %do;
%if %symexist(_program) %then %let pgm=&_program;
%else %do;
%put &sysmacroname: No value provided and no _program variable available;
%return;
%end;
%end;
%local root;
/**
* First check we are not in the tests/macros folder (which has no subfolders)
* or specifically in the testsetup or testteardown services
*/
%if %index(&pgm,/tests/macros/)
or %index(&pgm,/tests/testsetup)
or %index(&pgm,/tests/testteardown)
%then %do;
%let root=%substr(&pgm,1,%index(&pgm,/tests)-1);
&root
%return;
%end;
/**
* Next, move up two levels to avoid matches on subfolder or service name
*/
%let root=%substr(&pgm,1,%length(&pgm)-%length(%scan(&pgm,-1,/))-1);
%let root=%substr(&root,1,%length(&root)-%length(%scan(&root,-1,/))-1);
%if %index(&root,/tests/) %then %do;
%let root=%substr(&root,1,%index(&root,/tests/)-1);
%end;
%else %if %index(&root,/services) %then %do;
%let root=%substr(&root,1,%index(&root,/services)-1);
%end;
%else %if %index(&root,/jobs) %then %do;
%let root=%substr(&root,1,%index(&root,/jobs)-1);
%end;
%else %put &sysmacroname: Could not find an app location from &pgm;
&root
%mend mf_getapploc ;

View File

@@ -10,20 +10,20 @@
@param attr full list in [documentation](
https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000147794.htm)
@return output returns result of the attrc value supplied, or -1 and log
message if error.
message if err.
@version 9.2
@author Allan Bowe
**/
%macro mf_getattrc(
libds
libds
,attr
)/*/STORE SOURCE*/;
%local dsid rc;
%let dsid=%sysfunc(open(&libds,is));
%if &dsid = 0 %then %do;
%put WARNING: Cannot open %trim(&libds), system message below;
%put %str(WARN)ING: Cannot open %trim(&libds), system message below;
%put %sysfunc(sysmsg());
-1
%end;
@@ -31,4 +31,4 @@
%sysfunc(attrc(&dsid,&attr))
%let rc=%sysfunc(close(&dsid));
%end;
%mend;
%mend mf_getattrc;

View File

@@ -8,22 +8,22 @@
@param libds library.dataset
@param attr Common values are NLOBS and NVARS, full list in [documentation](
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000212040.htm)
http://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a000212040.htm)
@return output returns result of the attrn value supplied, or -1 and log
message if error.
message if err.
@version 9.2
@author Allan Bowe
**/
%macro mf_getattrn(
libds
libds
,attr
)/*/STORE SOURCE*/;
%local dsid rc;
%let dsid=%sysfunc(open(&libds,is));
%if &dsid = 0 %then %do;
%put WARNING: Cannot open %trim(&libds), system message below;
%put %str(WARN)ING: Cannot open %trim(&libds), system message below;
%put %sysfunc(sysmsg());
-1
%end;
@@ -31,4 +31,4 @@
%sysfunc(attrn(&dsid,&attr))
%let rc=%sysfunc(close(&dsid));
%end;
%mend;
%mend mf_getattrn;

View File

@@ -3,7 +3,7 @@
@brief Returns the engine type of a SAS library
@details Usage:
%put %mf_getEngine(SASHELP);
%put %mf_getengine(SASHELP);
returns:
> V9
@@ -12,25 +12,33 @@
contributors of Chris Hemedingers blog [post](
http://blogs.sas.com/content/sasdummy/2013/06/04/find-a-sas-library-engine/)
@param libref Library reference (also accepts a 2 level libds ref).
@param [in] libref Library reference (also accepts a 2 level libds ref).
@return output returns the library engine for the FIRST library encountered.
@return output returns the library engine (uppercase) for the FIRST library
encountered.
@warning will only return the FIRST library engine - for concatenated
libraries, with different engines, inconsistent results may be encountered.
@version 9.2
@author Allan Bowe
**/
%macro mf_getEngine(libref
<h4> Related Macros </h4>
@li mf_getxengine.sas
**/
/** @cond */
%macro mf_getengine(libref
)/*/STORE SOURCE*/;
%local dsid engnum rc engine;
/* in case the parameter is a libref.tablename, pull off just the libref */
%let libref = %upcase(%scan(&libref, 1, %str(.)));
%let dsid=%sysfunc(open(sashelp.vlibnam(where=(libname="%upcase(&libref)")),i));
%let dsid=%sysfunc(
open(sashelp.vlibnam(where=(libname="%upcase(&libref)")),i)
);
%if (&dsid ^= 0) %then %do;
%let engnum=%sysfunc(varnum(&dsid,ENGINE));
%let rc=%sysfunc(fetch(&dsid));
@@ -39,6 +47,8 @@
%let rc= %sysfunc(close(&dsid));
%end;
&engine
%upcase(&engine)
%mend;
%mend mf_getengine;
/** @endcond */

View File

@@ -5,18 +5,19 @@
%put %mf_getfilesize(fpath=C:\temp\myfile.txt);
or
or, provide a libds value as follows:
data x;do x=1 to 100000;y=x;output;end;run;
%put %mf_getfilesize(libds=work.x,format=yes);
gives:
Which gives:
2mb
> 2mb
@param [in] fpath= Full path and filename. Provide this OR the libds value.
@param [in] libds= (0) Library.dataset value (assumes library is BASE engine)
@param [in] format= (NO) Set to yes to apply sizekmg. format
@param fpath= full path and filename. Provide this OR the libds value.
@param libds= library.dataset value (assumes library is BASE engine)
@param format= set to yes to apply sizekmg. format
@returns bytes
@version 9.2
@@ -26,22 +27,38 @@
%macro mf_getfilesize(fpath=,libds=0,format=NO
)/*/STORE SOURCE*/;
%local rc fid fref bytes dsid lib vnum;
%if &libds ne 0 %then %do;
%let fpath=%sysfunc(pathname(%scan(&libds,1,.)))/%scan(&libds,2,.).sas7bdat;
%let libds=%upcase(&libds);
%if %index(&libds,.)=0 %then %let lib=WORK;
%else %let lib=%scan(&libds,1,.);
%let dsid=%sysfunc(open(
sashelp.vtable(where=(libname="&lib" and memname="%scan(&libds,-1,.)")
keep=libname memname filesize
)
));
%if (&dsid ^= 0) %then %do;
%let vnum=%sysfunc(varnum(&dsid,FILESIZE));
%let rc=%sysfunc(fetch(&dsid));
%let bytes=%sysfunc(getvarn(&dsid,&vnum));
%let rc= %sysfunc(close(&dsid));
%end;
%else %put &sysmacroname: &libds could not be opened! %sysfunc(sysmsg());
%end;
%else %do;
%let rc=%sysfunc(filename(fref,&fpath));
%let fid=%sysfunc(fopen(&fref));
%let bytes=%sysfunc(finfo(&fid,File Size (bytes)));
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(fref));
%end;
%local rc fid fref bytes;
%let rc=%sysfunc(filename(fref,&fpath));
%let fid=%sysfunc(fopen(&fref));
%let bytes=%sysfunc(finfo(&fid,File Size (bytes)));
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(fref));
%if &format=NO %then %do;
&bytes
&bytes
%end;
%else %do;
%sysfunc(INPUTN(&bytes, best.),sizekmg.)
%end;
%mend ;
%mend mf_getfilesize ;

61
base/mf_getfmtlist.sas Normal file
View File

@@ -0,0 +1,61 @@
/**
@file
@brief Returns a distinct list of formats from a table
@details Reads the dataset header and returns a distinct list of formats
applied.
%put NOTE- %mf_getfmtlist(sashelp.prdsale);
%put NOTE- %mf_getfmtlist(sashelp.shoes);
%put NOTE- %mf_getfmtlist(sashelp.demographics);
returns:
> DOLLAR $CHAR W MONNAME
> $CHAR BEST DOLLAR
> BEST Z $CHAR COMMA PERCENTN
@param [in] libds Two part library.dataset reference.
<h4> SAS Macros </h4>
@li mf_getfmtname.sas
@version 9.2
@author Allan Bowe
**/
%macro mf_getfmtlist(libds
)/*/STORE SOURCE*/;
/* declare local vars */
%local out dsid nvars x rc fmt;
/* open dataset in macro */
%let dsid=%sysfunc(open(&libds));
/* continue if dataset exists */
%if &dsid %then %do;
/* loop each variable in the dataset */
%let nvars=%sysfunc(attrn(&dsid,NVARS));
%do x=1 %to &nvars;
/* grab format and check it exists */
%let fmt=%sysfunc(varfmt(&dsid,&x));
%if %quote(&fmt) ne %quote() %then %let fmt=%mf_getfmtname(&fmt);
%else %do;
/* assign default format depending on variable type */
%if %sysfunc(vartype(&dsid, &x))=C %then %let fmt=$CHAR;
%else %let fmt=BEST;
%end;
/* concatenate unique list of formats */
%if %sysfunc(indexw(&out,&fmt,%str( )))=0 %then %let out=&out &fmt;
%end;
%let rc=%sysfunc(close(&dsid));
%end;
%else %do;
%put &sysmacroname: Unable to open &libds (rc=&dsid);
%put &sysmacroname: SYSMSG= %sysfunc(sysmsg());
%let rc=%sysfunc(close(&dsid));
%end;
/* send them out without spaces or quote markers */
%do;%unquote(&out)%end;
%mend mf_getfmtlist;

44
base/mf_getfmtname.sas Normal file
View File

@@ -0,0 +1,44 @@
/**
@file
@brief Extracts a format name from a fully defined format
@details Converts formats in like $thi3. and th13.2 $THI and TH.
Usage:
%put %mf_getfmtname(8.);
%put %mf_getfmtname($4.);
%put %mf_getfmtname(comma14.10);
Returns:
> W
> $CHAR
> COMMA
Note that system defaults are inferred from the values provided.
@param [in] fmt The fully defined format. If left blank, nothing is returned.
@returns The name (without width or decimal) of the format.
@version 9.2
@author Allan Bowe
**/
%macro mf_getfmtname(fmt
)/*/STORE SOURCE*/ /minoperator mindelimiter=' ';
%local out dsid nvars x rc fmt;
/* extract actual format name from the format definition */
%let fmt=%scan(&fmt,1,.);
%do %while(%substr(&fmt,%length(&fmt),1) in 1 2 3 4 5 6 7 8 9 0);
%if %length(&fmt)=1 %then %let fmt=W;
%else %let fmt=%substr(&fmt,1,%length(&fmt)-1);
%end;
%if &fmt=$ %then %let fmt=$CHAR;
/* send them out without spaces or quote markers */
%do;%unquote(%upcase(&fmt))%end;
%mend mf_getfmtname;

View File

@@ -3,8 +3,8 @@
@brief retrieves a key value pair from a control dataset
@details By default, control dataset is work.mp_setkeyvalue. Usage:
%mp_setkeyvalue(someindex,22,type=N)
%put %mf_getkeyvalue(someindex)
%mp_setkeyvalue(someindex,22,type=N)
%put %mf_getkeyvalue(someindex)
@param key Provide a key on which to perform the lookup
@@ -16,7 +16,7 @@
%macro mf_getkeyvalue(key,libds=work.mp_setkeyvalue
)/*/STORE SOURCE*/;
%local ds dsid key valc valn type rc;
%local ds dsid key valc valn type rc;
%let dsid=%sysfunc(open(&libds(where=(key="&key"))));
%syscall set(dsid);
%let rc = %sysfunc(fetch(&dsid));
@@ -29,4 +29,4 @@
&valc
%end;
%else %put %str(ERR)OR: Unable to find key &key in ds &libds;
%mend;
%mend mf_getkeyvalue;

View File

@@ -5,13 +5,18 @@
%put %mf_getplatform();
returns:
SASMETA (or SASVIYA)
returns one of:
@li SASMETA
@li SASVIYA
@li SASJS
@li BASESAS
@param switch the param for which to return a platform specific variable
<h4> Dependencies </h4>
<h4> SAS Macros </h4>
@li mf_mval.sas
@li mf_trimstr.sas
@version 9.4 / 3.4
@author Allan Bowe
@@ -21,26 +26,34 @@
)/*/STORE SOURCE*/;
%local a b c;
%if &switch.NONE=NONE %then %do;
%if %symexist(sasjsprocessmode) %then %do;
%if &sasjsprocessmode=Stored Program %then %do;
SASJS
%return;
%end;
%end;
%if %symexist(sysprocessmode) %then %do;
%if "&sysprocessmode"="SAS Object Server"
%if "&sysprocessmode"="SAS Object Server"
or "&sysprocessmode"= "SAS Compute Server" %then %do;
SASVIYA
%end;
%else %if "&sysprocessmode"="SAS Stored Process Server" %then %do;
%else %if "&sysprocessmode"="SAS Stored Process Server"
or "&sysprocessmode"="SAS Workspace Server"
%then %do;
SASMETA
%return;
%end;
%else %do;
SAS
BASESAS
%return;
%end;
%end;
%else %if %symexist(_metaport) %then %do;
%else %if %symexist(_metaport) or %symexist(_metauser) %then %do;
SASMETA
%return;
%end;
%else %do;
SAS
BASESAS
%return;
%end;
%end;
@@ -57,6 +70,6 @@
%else 0;
%end;
%else %if &switch=VIYARESTAPI %then %do;
%sysfunc(getoption(servicesbaseurl))
%mf_trimstr(%sysfunc(getoption(servicesbaseurl)),/)
%end;
%mend;
%mend mf_getplatform;

View File

@@ -3,17 +3,24 @@
@brief Adds custom quotes / delimiters to a delimited string
@details Can be used in open code, eg as follows:
%put %mf_getquotedstr(blah blah blah);
%put %mf_getquotedstr(blah blah blah);
which returns:
> 'blah','blah','blah'
@param in_str the unquoted, spaced delimited string to transform
@param dlm= the delimeter to be applied to the output (default comma)
@param indlm= the delimeter used for the input (default is space)
@param quote= the quote mark to apply (S=Single, D=Double). If any other value
than uppercase S or D is supplied, then that value will be used as the
quoting character.
Alternatively:
%put %mf_getquotedstr(these words are double quoted,quote=D)
for:
> "these","words","are","double","quoted"
@param [in] in_str The unquoted, spaced delimited string to transform
@param [in] dlm= (,) The delimeter to be applied to the output (default comma)
@param [in] indlm= ( ) The delimeter used for the input (default is space)
@param [in] quote= (S) The quote mark to apply (S=Single, D=Double, N=None).
If any other value than uppercase S or D is supplied, then that value will
be used as the quoting character.
@return output returns a string with the newly quoted / delimited output.
@version 9.2
@@ -21,11 +28,15 @@
**/
%macro mf_getquotedstr(IN_STR,DLM=%str(,),QUOTE=S,indlm=%str( )
%macro mf_getquotedstr(IN_STR
,DLM=%str(,)
,QUOTE=S
,indlm=%str( )
)/*/STORE SOURCE*/;
%if &quote=S %then %let quote=%str(%');
%else %if &quote=D %then %let quote=%str(%");
%else %let quote=%str();
/* credit Rowland Hale - byte34 is double quote, 39 is single quote */
%if &quote=S %then %let quote=%qsysfunc(byte(39));
%else %if &quote=D %then %let quote=%qsysfunc(byte(34));
%else %if &quote=N %then %let quote=;
%local i item buffer;
%let i=1;
%do %while (%qscan(&IN_STR,&i,%str(&indlm)) ne %str() ) ;
@@ -43,4 +54,4 @@
&buffer
%mend;
%mend mf_getquotedstr;

View File

@@ -17,6 +17,7 @@
@version 9.2
@author Allan Bowe
@cond
**/
%macro mf_getschema(libref
@@ -37,4 +38,6 @@
&schema
%mend;
%mend mf_getschema;
/** @endcond */

View File

@@ -1,36 +1,60 @@
/**
@file
@brief Assigns and returns an unused fileref
@details Use as follows:
@details Using the native approach for assigning filerefs fails as some
procedures (such as proc http) do not recognise the temporary names (starting
with a hash), returning a message such as:
%let fileref1=%mf_getuniquefileref();
%let fileref2=%mf_getuniquefileref();
%put &fileref1 &fileref2;
> ERROR 22-322: Expecting a name.
which returns:
This macro works by attempting a random fileref (with a prefix), seeing if it
is already assigned, and if not - returning the fileref.
> mcref0 mcref1
If your process can accept filerefs with the hash (#) prefix, then set
`prefix=0` to revert to the native approach - which is significantly faster
when there are a lot of filerefs in a session.
@prefix= first part of fileref. Remember that filerefs can only be 8
characters, so a 7 letter prefix would mean that `maxtries` should be 10.
@param maxtries= the last part of the libref. Provide an integer value.
Use as follows:
%let fileref1=%mf_getuniquefileref();
%let fileref2=%mf_getuniquefileref(prefix=0);
%put &fileref1 &fileref2;
which returns filerefs similar to:
> _7432233 #LN00070
@param [in] prefix= (_) first part of fileref. Remember that filerefs can only
be 8 characters, so a 7 letter prefix would mean `maxtries` should be 10.
if using zero (0) as the prefix, a native assignment is used.
@param [in] maxtries= (1000) the last part of the libref. Must be an integer.
@param [in] lrecl= (32767) Provide a default lrecl with which to initialise
the generated fileref.
@version 9.2
@author Allan Bowe
**/
%macro mf_getuniquefileref(prefix=mcref,maxtries=1000);
%local x fname;
%let x=0;
%do x=0 %to &maxtries;
%if %sysfunc(fileref(&prefix&x)) > 0 %then %do;
%let fname=&prefix&x;
%let rc=%sysfunc(filename(fname,,temp));
%macro mf_getuniquefileref(prefix=_,maxtries=1000,lrecl=32767);
%local rc fname;
%if &prefix=0 %then %do;
%let rc=%sysfunc(filename(fname,,temp,lrecl=&lrecl));
%if &rc %then %put %sysfunc(sysmsg());
&prefix&x
%*put &sysmacroname: Fileref &prefix&x was assigned and returned;
%return;
&fname
%end;
%else %do;
%local x len;
%let len=%eval(8-%length(&prefix));
%let x=0;
%do x=0 %to &maxtries;
%let fname=&prefix%substr(%sysfunc(ranuni(0)),3,&len);
%if %sysfunc(fileref(&fname)) > 0 %then %do;
%let rc=%sysfunc(filename(fname,,temp,lrecl=&lrecl));
%if &rc %then %put %sysfunc(sysmsg());
&fname
%return;
%end;
%end;
%put unable to find available fileref after &maxtries attempts;
%end;
%put unable to find available fileref in range &prefix.0-&maxtries;
%mend;
%mend mf_getuniquefileref;

View File

@@ -3,38 +3,55 @@
@brief Returns an unused libref
@details Use as follows:
libname mclib0 (work);
libname mclib1 (work);
libname mclib2 (work);
libname mclib0 (work);
libname mclib1 (work);
libname mclib2 (work);
%let libref=%mf_getuniquelibref();
%put &=libref;
%let libref=%mf_getuniquelibref();
%put &=libref;
which returns:
> mclib3
@prefix= first part of libref. Remember that librefs can only be 8 characters,
so a 7 letter prefix would mean that maxtries should be 10.
@param maxtries= the last part of the libref. Provide an integer value.
A blank value is returned if no usable libname is determined.
@param [in] prefix= (mclib) first part of the returned libref. As librefs can
be as long as 8 characters, a maximum length of 7 characters is premitted
for this prefix.
@param [in] maxtries= Deprecated parameter. Remains here to ensure a
non-breaking change. Will be removed in v5.
@version 9.2
@author Allan Bowe
**/
%macro mf_getuniquelibref(prefix=mclib,maxtries=1000);
%local x libref;
%let x=0;
%do x=0 %to &maxtries;
%if %sysfunc(libref(&prefix&x)) ne 0 %then %do;
%let libref=&prefix&x;
%let rc=%sysfunc(libname(&libref,%sysfunc(pathname(work))));
%if &rc %then %put %sysfunc(sysmsg());
&prefix&x
%*put &sysmacroname: Libref &libref assigned as WORK and returned;
%local x;
%if ( %length(&prefix) gt 7 ) %then %do;
%put %str(ERR)OR: The prefix parameter cannot exceed 7 characters.;
0
%return;
%end;
%else %if (%sysfunc(NVALID(&prefix,v7))=0) %then %do;
%put %str(ERR)OR: Invalid prefix (&prefix);
0
%return;
%end;
%put unable to find available libref in range &prefix.0-&maxtries;
%mend;
/* Set maxtries equal to '10 to the power of [# unused characters] - 1' */
%let maxtries=%eval(10**(8-%length(&prefix))-1);
%do x = 0 %to &maxtries;
%if %sysfunc(libref(&prefix&x)) ne 0 %then %do;
&prefix&x
%return;
%end;
%let x = %eval(&x + 1);
%end;
%put %str(ERR)OR: No usable libref in range &prefix.0-&maxtries;
%put %str(ERR)OR- Try reducing the prefix or deleting some libraries!;
0
%mend mf_getuniquelibref;

View File

@@ -18,5 +18,5 @@
%macro mf_getuniquename(prefix=MC);
&prefix.%substr(%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32-%length(&prefix))
%mend;
&prefix.%substr(%sysfunc(compress(%sysfunc(uuidgen()),-)),1,32-%length(&prefix))
%mend mf_getuniquename;

View File

@@ -2,7 +2,7 @@
@file
@brief Returns a userid according to session context
@details In a workspace session, a user is generally represented by <code>
&sysuserid</code> or <code>SYS_COMPUTE_SESSION_OWNER</code> if it exists.
&sysuserid</code> or <code>SYS_COMPUTE_SESSION_OWNER</code> if it exists.
In a Stored Process session, <code>&sysuserid</code>
resolves to a system account (default=sassrv) and instead there are several
metadata username variables to choose from (_metauser, _metaperson
@@ -12,7 +12,7 @@
%let user= %mf_getUser();
%put &user;
@param type - do not use, may be deprecated in a future release
@return SYSUSERID (if workspace server)
@@ -23,20 +23,22 @@
@author Allan Bowe
**/
%macro mf_getuser(type=META
%macro mf_getuser(
)/*/STORE SOURCE*/;
%local user metavar;
%if &type=OS %then %let metavar=_secureusername;
%else %let metavar=_metaperson;
%local user;
%if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %let user=&SYS_COMPUTE_SESSION_OWNER;
%else %if %symexist(&metavar) %then %do;
%if %length(&&&metavar)=0 %then %let user=&sysuserid;
%if %symexist(_sasjs_username) %then %let user=&_sasjs_username;
%else %if %symexist(SYS_COMPUTE_SESSION_OWNER) %then %do;
%let user=&SYS_COMPUTE_SESSION_OWNER;
%end;
%else %if %symexist(_metaperson) %then %do;
%if %length(&_metaperson)=0 %then %let user=&sysuserid;
/* sometimes SAS will add @domain extension - remove for consistency */
%else %let user=%scan(&&&metavar,1,@);
/* but be sure to quote in case of usernames with commas */
%else %let user=%unquote(%scan(%quote(&_metaperson),1,@));
%end;
%else %let user=&sysuserid;
%quote(&user)
%mend;
%mend mf_getuser;

View File

@@ -7,9 +7,12 @@
%put %mf_getvalue(sashelp.class,name,filter=%quote(age=15));
%put %mf_getvalue(sashelp.class,name);
<h4> Dependencies </h4>
<h4> SAS Macros </h4>
@li mf_getattrn.sas
<h4> Related Macros </h4>
@li mp_setkeyvalue.sas
@param libds dataset to query
@param variable the variable which contains the value to return.
@param filter contents of where clause
@@ -20,7 +23,7 @@
%macro mf_getvalue(libds,variable,filter=1
)/*/STORE SOURCE*/;
%if %mf_getattrn(&libds,NLOBS)>0 %then %do;
%if %mf_getattrn(&libds,NLOBS)>0 %then %do;
%local dsid rc &variable;
%let dsid=%sysfunc(open(&libds(where=(&filter))));
%syscall set(dsid);
@@ -30,4 +33,4 @@
%trim(&&&variable)
%end;
%mend;
%mend mf_getvalue;

View File

@@ -2,31 +2,48 @@
@file
@brief Returns number of variables in a dataset
@details Useful to identify those renagade datasets that have no columns!
Can also be used to count for numeric, or character columns
%put Number of Variables=%mf_getvarcount(sashelp.class);
%put Number of Variables=%mf_getvarcount(sashelp.class);
%put Character Variables=%mf_getvarcount(sashelp.class,typefilter=C);
%put Numeric Variables = %mf_getvarcount(sashelp.class,typefilter=N);
returns:
> Number of Variables=4
@param libds Two part dataset (or view) reference.
@param [in] libds Two part dataset (or view) reference.
@param [in] typefilter= (A) Filter for certain types of column. Valid values:
@li A Count All columns
@li C Count Character columns only
@li N Count Numeric columns only
@version 9.2
@author Allan Bowe
**/
%macro mf_getvarcount(libds
%macro mf_getvarcount(libds,typefilter=A
)/*/STORE SOURCE*/;
%local dsid nvars rc ;
%local dsid nvars rc outcnt x;
%let dsid=%sysfunc(open(&libds));
%let nvars=.;
%let outcnt=0;
%let typefilter=%upcase(&typefilter);
%if &dsid %then %do;
%let nvars=%sysfunc(attrn(&dsid,NVARS));
%if &typefilter=A %then %let outcnt=&nvars;
%else %if &nvars>0 %then %do x=1 %to &nvars;
/* increment based on variable type */
%if %sysfunc(vartype(&dsid,&x))=&typefilter %then %do;
%let outcnt=%eval(&outcnt+1);
%end;
%end;
%let rc=%sysfunc(close(&dsid));
%end;
%else %do;
%put unable to open &libds (rc=&dsid);
%let rc=%sysfunc(close(&dsid));
%end;
&nvars
%mend;
&outcnt
%mend mf_getvarcount;

View File

@@ -5,9 +5,9 @@
Usage:
data test;
format str1 $1. num1 datetime19.;
str2='hello mum!'; num2=666;
stop;
format str1 $1. num1 datetime19.;
str2='hello mum!'; num2=666;
stop;
run;
%put %mf_getVarFormat(test,str1);
%put %mf_getVarFormat(work.test,num1);
@@ -23,9 +23,9 @@
8.
NOTE: Variable renegade does not exist in test
@param libds Two part dataset (or view) reference.
@param var Variable name for which a format should be returned
@param force Set to 1 to supply a default if the variable has no format
@param [in] libds Two part dataset (or view) reference.
@param [in] var Variable name for which a format should be returned
@param [in] force=(0) Set to 1 to supply a default if the variable has no format
@returns outputs format
@author Allan Bowe
@@ -45,13 +45,14 @@
/* Get variable format */
%if(&vnum > 0) %then %let vformat=%sysfunc(varfmt(&dsid, &vnum));
%else %do;
%put NOTE: Variable &var does not exist in &libds;
%let rc = %sysfunc(close(&dsid));
%return;
%put NOTE: Variable &var does not exist in &libds;
%let rc = %sysfunc(close(&dsid));
%return;
%end;
%end;
%else %do;
%put dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
@@ -60,7 +61,7 @@
%let vlen = %sysfunc(varlen(&dsid, &vnum));
%let vtype = %sysfunc(vartype(&dsid, &vnum.));
%if &vtype=C %then %let vformat=$&vlen..;
%else %let vformat=8.;
%else %let vformat=best.;
%end;
@@ -68,4 +69,4 @@
%let rc = %sysfunc(close(&dsid));
/* Return variable format */
&vformat
%mend;
%mend mf_getVarFormat;

View File

@@ -5,8 +5,8 @@
Usage:
data test;
format str $1. num datetime19.;
stop;
format str $1. num datetime19.;
stop;
run;
%put %mf_getVarLen(test,str);
%put %mf_getVarLen(work.test,num);
@@ -39,14 +39,18 @@
/* Get variable format */
%if(&vnum > 0) %then %let vlen = %sysfunc(varlen(&dsid, &vnum));
%else %do;
%put NOTE: Variable &var does not exist in &libds;
%let vlen = %str( );
%put NOTE: Variable &var does not exist in &libds;
%let vlen = %str( );
%end;
%end;
%else %put dataset &libds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));
/* Return variable format */
&vlen
%mend;
%mend mf_getVarLen;

View File

@@ -10,14 +10,21 @@
returns:
> List of Variables=Name Sex Age Height Weight
For a seperated list of column values:
%put %mf_getvarlist(sashelp.class,dlm=%str(,),quote=double);
returns:
> "Name","Sex","Age","Height","Weight"
@param libds Two part dataset (or view) reference.
@param dlm= provide a delimiter (eg comma or space) to separate the vars
@param quote= use either DOUBLE or SINGLE to quote the results
@param [in] libds Two part dataset (or view) reference.
@param [in] dlm= ( ) Provide a delimiter (eg comma or space) to separate the
variables
@param [in] quote= (none) use either DOUBLE or SINGLE to quote the results
@param [in] typefilter= (A) Filter for certain types of column. Valid values:
@li A Return All columns
@li C Return Character columns
@li N Return Numeric columns
@version 9.2
@author Allan Bowe
@@ -27,9 +34,10 @@
%macro mf_getvarlist(libds
,dlm=%str( )
,quote=no
,typefilter=A
)/*/STORE SOURCE*/;
/* declare local vars */
%local outvar dsid nvars x rc dlm q var;
%local outvar dsid nvars x rc dlm q var vtype;
/* credit Rowland Hale - byte34 is double quote, 39 is single quote */
%if %upcase(&quote)=DOUBLE %then %let q=%qsysfunc(byte(34));
@@ -37,28 +45,30 @@
/* open dataset in macro */
%let dsid=%sysfunc(open(&libds));
%if &dsid %then %do;
%let nvars=%sysfunc(attrn(&dsid,NVARS));
%if &nvars>0 %then %do;
/* add first dataset variable to global macro variable */
%let outvar=&q.%sysfunc(varname(&dsid,1))&q.;
/* add remaining variables with supplied delimeter */
/* add variables with supplied delimeter */
%do x=1 %to &nvars;
%let var=&q.%sysfunc(varname(&dsid,&x))&q.;
%if &var=&q&q %then %do;
%put &sysmacroname: Empty column found in &libds!;
%let var=&q. &q.;
/* get variable type */
%let vtype=%sysfunc(vartype(&dsid,&x));
%if &vtype=&typefilter or &typefilter=A %then %do;
%let var=&q.%sysfunc(varname(&dsid,&x))&q.;
%if &var=&q&q %then %do;
%put &sysmacroname: Empty column found in &libds!;
%let var=&q. &q.;
%end;
%if %quote(&outvar)=%quote() %then %let outvar=&var;
%else %let outvar=&outvar.&dlm.&var.;
%end;
%if &x=1 %then %let outvar=&var;
%else %let outvar=&outvar.&dlm.&var.;
%end;
%end;
%let rc=%sysfunc(close(&dsid));
%end;
%else %do;
%put unable to open &libds (rc=&dsid);
%put &sysmacroname: Unable to open &libds (rc=&dsid);
%put &sysmacroname: SYSMSG= %sysfunc(sysmsg());
%let rc=%sysfunc(close(&dsid));
%end;
&outvar
%mend;
%do;%unquote(&outvar)%end;
%mend mf_getvarlist;

View File

@@ -6,8 +6,8 @@
Usage:
data work.test;
format str $1. num datetime19.;
stop;
format str $1. num datetime19.;
stop;
run;
%put %mf_getVarNum(work.test,str);
%put %mf_getVarNum(work.test,num);
@@ -39,11 +39,15 @@ returns:
/* Get variable number */
%let vnum = %sysfunc(varnum(&dsid, &var));
%if(&vnum <= 0) %then %do;
%put NOTE: Variable &var does not exist in &libds;
%let vnum = %str( );
%put NOTE: Variable &var does not exist in &libds;
%let vnum = %str( );
%end;
%end;
%else %put dataset &ds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));
@@ -51,4 +55,4 @@ returns:
/* Return variable number */
&vnum.
%mend;
%mend mf_getVarNum;

View File

@@ -5,8 +5,8 @@
Usage:
data test;
length str $1. num 8.;
stop;
length str $1. num 8.;
stop;
run;
%put %mf_getvartype(test,str);
%put %mf_getvartype(work.test,num);
@@ -35,14 +35,18 @@ Usage:
/* Get variable type (C/N) */
%if(&vnum. > 0) %then %let vtype = %sysfunc(vartype(&dsid, &vnum.));
%else %do;
%put NOTE: Variable &var does not exist in &libds;
%let vtype = %str( );
%put NOTE: Variable &var does not exist in &libds;
%let vtype = %str( );
%end;
%end;
%else %put dataset &libds not opened! (rc=&dsid);
%else %do;
%put &sysmacroname: dataset &libds not opened! (rc=&dsid);
%put &sysmacroname: %sysfunc(sysmsg());
%return;
%end;
/* Close dataset */
%let rc = %sysfunc(close(&dsid));
/* Return variable type */
&vtype
%mend;
%mend mf_getvartype;

43
base/mf_getxengine.sas Normal file
View File

@@ -0,0 +1,43 @@
/**
@file
@brief Returns the engine type of a SAS fileref
@details Queries sashelp.vextfl to get the xengine value.
Usage:
filename feng temp;
%put %mf_getxengine(feng);
returns:
> TEMP
@param fref The fileref to check
@returns The XENGINE value in sashelp.vextfl or 0 if not found.
@version 9.2
@author Allan Bowe
<h4> Related Macros </h4>
@li mf_getengine.sas
**/
%macro mf_getxengine(fref
)/*/STORE SOURCE*/;
%local dsid engnum rc engine;
%let dsid=%sysfunc(
open(sashelp.vextfl(where=(fileref="%upcase(&fref)")),i)
);
%if (&dsid ^= 0) %then %do;
%let engnum=%sysfunc(varnum(&dsid,XENGINE));
%let rc=%sysfunc(fetch(&dsid));
%let engine=%sysfunc(getvarc(&dsid,&engnum));
%* put &fref. ENGINE is &engine.;
%let rc= %sysfunc(close(&dsid));
%end;
%else %let engine=0;
&engine
%mend mf_getxengine;

29
base/mf_increment.sas Normal file
View File

@@ -0,0 +1,29 @@
/**
@file
@brief Increments a macro variable
@details Useful outside of do-loops - will increment a macro variable every
time it is called.
Example:
%let cnt=1;
%put We have run %mf_increment(cnt) lines;
%put Now we have run %mf_increment(cnt) lines;
%put There are %mf_increment(cnt) lines in total;
@param [in] MACRO_NAME the name of the macro variable to increment
@param [in] ITER= The amount to add or subtract to the macro
<h4> Related Files </h4>
@li mf_increment.test.sas
**/
%macro mf_increment(macro_name,incr=1);
/* iterate the value */
%let &macro_name=%eval(&&&macro_name+&incr);
/* return the value */
&&&macro_name
%mend mf_increment;

View File

@@ -6,12 +6,13 @@
%sysevalf(%superq(param)=,boolean)
Usage:
%put mf_isblank(&var);
inspiration: https://support.sas.com/resources/papers/proceedings09/022-2009.pdf
%put mf_isblank(&var);
@param param VALUE to be checked
inspiration:
https://support.sas.com/resources/papers/proceedings09/022-2009.pdf
@param param VALUE to be checked
@return output returns 1 (if blank) else 0
@@ -23,4 +24,4 @@
%sysevalf(%superq(param)=,boolean)
%mend;
%mend mf_isblank;

34
base/mf_isdir.sas Normal file
View File

@@ -0,0 +1,34 @@
/**
@file
@brief Checks whether a path is a valid directory
@details
Usage:
%let isdir=%mf_isdir(/tmp);
With thanks and full credit to Andrea Defronzo -
https://www.linkedin.com/in/andrea-defronzo-b1a47460/
@param path full path of the file/directory to be checked
@return output returns 1 if path is a directory, 0 if it is not
@version 9.2
**/
%macro mf_isdir(path
)/*/STORE SOURCE*/;
%local rc did is_directory fref_t;
%let is_directory = 0;
%let rc = %sysfunc(filename(fref_t, %superq(path)));
%let did = %sysfunc(dopen(&fref_t.));
%if &did. ^= 0 %then %do;
%let is_directory = 1;
%let rc = %sysfunc(dclose(&did.));
%end;
%let rc = %sysfunc(filename(fref_t));
&is_directory
%mend mf_isdir;

36
base/mf_isint.sas Normal file
View File

@@ -0,0 +1,36 @@
/**
@file
@brief Returns 1 if the variable contains only digits 0-9, else 0
@details Note that numerics containing any punctuation (including decimals
or exponents) will be flagged zero.
If you'd like support for this, then do raise an issue (or even better, a
pull request!)
Usage:
%put %mf_isint(1) returns 1;
%put %mf_isint(1.1) returns 0;
%put %mf_isint(%str(1,1)) returns 0;
@param [in] arg input value to check
@version 9.2
**/
%macro mf_isint(arg
)/*/STORE SOURCE*/;
/* blank val is not an integer */
%if "&arg"="" %then %do;0%return;%end;
/* remove minus sign if exists */
%local val;
%if "%substr(%str(&arg),1,1)"="-" %then %let val=%substr(%str(&arg),2);
%else %let val=&arg;
/* check remaining chars */
%if %sysfunc(findc(%str(&val),,kd)) %then %do;0%end;
%else %do;1%end;
%mend mf_isint;

40
base/mf_islibds.sas Normal file
View File

@@ -0,0 +1,40 @@
/**
@file
@brief Checks whether a string follows correct library.dataset format
@details Many macros in the core library accept a library.dataset parameter
referred to as 'libds'. This macro validates the structure of that parameter,
eg:
@li 8 character libref?
@li 32 character dataset?
@li contains a period?
It does NOT check whether the dataset exists, or if the library is assigned.
Usage:
%put %mf_islibds(work.something)=1;
%put %mf_islibds(nolib)=0;
%put %mf_islibds(badlibref.ds)=0;
%put %mf_islibds(w.t.f)=0;
@param [in] libds The string to be checked
@return output Returns 1 if libds is valid, 0 if it is not
<h4> Related Macros </h4>
@li mf_islibds.test.sas
@li mp_validatecol.sas
@version 9.2
**/
%macro mf_islibds(libds
)/*/STORE SOURCE*/;
%local regex;
%let regex=%sysfunc(prxparse(%str(/^[_a-z]\w{0,7}\.[_a-z]\w{0,31}$/i)));
%sysfunc(prxmatch(&regex,&libds))
%mend mf_islibds;

View File

@@ -26,4 +26,4 @@
&root
%end;
%mend;
%mend mf_loc;

View File

@@ -46,22 +46,22 @@ Usage:
*/
%if (%length(&dir) gt %length(&child)) %then %do;
%let parent = %substr(&dir, 1, %length(&dir)-%length(&child));
%mf_mkdir(&parent)
%let parent = %substr(&dir, 1, %length(&dir)-%length(&child));
%mf_mkdir(&parent)
%end;
/*
Now create the directory. Complain loudly of any errors.
Now create the directory. Complain loudly of any errs.
*/
%let dname = %sysfunc(dcreate(&child, &parent));
%if (%bquote(&dname) eq ) %then %do;
%put %str(ERR)OR: could not create &parent + &child;
%abort cancel;
%put %str(ERR)OR: could not create &parent + &child;
%abort cancel;
%end;
%else %do;
%put Directory created: &dir;
%put Directory created: &dir;
%end;
%end;
/* exit quietly if directory did exist.*/
%mend;
%mend mf_mkdir;

View File

@@ -1,8 +1,9 @@
/**
@file mf_mval.sas
@brief Returns a macro variable value if the variable exists
@details Use this macro to avoid repetitive use of `%if %symexist(MACVAR) %then`
type logic.
@details
Use this macro to avoid repetitive use of `%if %symexist(MACVAR) %then`
type logic.
Usage:
%if %mf_mval(maynotexist)=itdid %then %do;
@@ -15,4 +16,4 @@
%if %symexist(&var) %then %do;
%superq(&var)
%end;
%mend;
%mend mf_mval;

View File

@@ -6,13 +6,13 @@
%put Number of observations=%mf_nobs(sashelp.class);
<h4> Dependencies </h4>
<h4> SAS Macros </h4>
@li mf_getattrn.sas
@param libds library.dataset
@return output returns result of the attrn value supplied, or log message
if error.
if err.
@version 9.2
@@ -23,4 +23,4 @@
%macro mf_nobs(libds
)/*/STORE SOURCE*/;
%mf_getattrn(&libds,NLOBS)
%mend;
%mend mf_nobs;

50
base/mf_trimstr.sas Normal file
View File

@@ -0,0 +1,50 @@
/**
@file mf_trimstr.sas
@brief Removes character(s) from the end, if they exist
@details If the designated characters exist at the end of the string, they
are removed
%put %mf_trimstr(/blah/,/); * /blah;
%put %mf_trimstr(/blah/,h); * /blah/;
%put %mf_trimstr(/blah/,h/);* /bla;
<h4> SAS Macros </h4>
@param basestr The string to be modified
@param trimstr The string to be removed from the end of `basestr`, if it
exists
@return output returns result with the value of `trimstr` removed from the end
@version 9.2
@author Allan Bowe
**/
%macro mf_trimstr(basestr,trimstr);
%local baselen trimlen trimval;
/* return if basestr is shorter than trimstr (or 0) */
%let baselen=%length(%superq(basestr));
%let trimlen=%length(%superq(trimstr));
%if &baselen < &trimlen or &baselen=0 %then %return;
/* obtain the characters from the end of basestr */
%let trimval=%qsubstr(%superq(basestr)
,%length(%superq(basestr))-&trimlen+1
,&trimlen);
/* compare and if matching, chop it off! */
%if %superq(basestr)=%superq(trimstr) %then %do;
%return;
%end;
%else %if %superq(trimval)=%superq(trimstr) %then %do;
%qsubstr(%superq(basestr),1,%length(%superq(basestr))-&trimlen)
%end;
%else %do;
&basestr
%end;
%mend mf_trimstr;

View File

@@ -1,11 +1,11 @@
/**
@file
@brief Creates a Unique ID based on system time in a friendly format
@brief Creates a unique ID based on system time in friendly format
@details format = YYYYMMDD_HHMMSSmmm_<sysjobid>_<3randomDigits>
%put %mf_uid();
@version 9.2
@version 9.3
@author Allan Bowe
**/
@@ -14,8 +14,8 @@
)/*/STORE SOURCE*/;
%local today now;
%let today=%sysfunc(today(),yymmddn8.);
%let now=%sysfunc(compress(%sysfunc(time(),time12.3),:.));
%let now=%sysfunc(compress(%sysfunc(time(),tod12.3),:.));
&today._&now._&sysjobid._%sysevalf(%sysfunc(ranuni(0))*999,CEIL)
%mend;
%mend mf_uid;

View File

@@ -1,6 +1,6 @@
/**
@file
@brief Checks if a set of macro variables exist / contain values.
@brief Checks if a set of macro variables exist AND contain values.
@details Writes ERROR to log if abortType is SOFT, else will call %mf_abort.
Usage:
@@ -11,13 +11,14 @@
Returns:
> 1
<h4> Dependencies </h4>
<h4> SAS Macros </h4>
@li mf_abort.sas
@param verifyvars space separated list of macro variable names
@param makeupcase= set to YES to convert all variable VALUES to
@param [in] verifyvars Space separated list of macro variable names
@param [in] makeupcase= (NO) Set to YES to convert all variable VALUES to
uppercase.
@param mAbort= Abort Type. Default is SOFT (writes err to log).
@param [in] mAbort= (SOFT) Abort Type. When SOFT, simply writes an err
message to the log.
Set to any other value to call mf_abort (which can be configured to abort in
various fashions according to context).
@@ -35,7 +36,7 @@
%macro mf_verifymacvars(
verifyVars /* list of macro variable NAMES */
verifyVars /* list of macro variable NAMES */
,makeUpcase=NO /* set to YES to make all the variable VALUES uppercase */
,mAbort=SOFT
)/*/STORE SOURCE*/;
@@ -58,8 +59,14 @@
%goto exit_success;
%exit_err:
%if &mAbort=SOFT %then %put %str(ERR)OR: &abortmsg;
%else %mf_abort(mac=mf_verifymacvars,type=&mabort,msg=&abortmsg);
%put &abortmsg;
%mf_abort(iftrue=(&mabort ne SOFT),
mac=mf_verifymacvars,
msg=%str(&abortmsg)
)
0
%return;
%exit_success:
1
%mend;
%mend mf_verifymacvars;

View File

@@ -0,0 +1,53 @@
/**
@file
@brief Returns words that are in both string 1 and string 2
@details Compares two space separated strings and returns the words that are
in both.
Usage:
%put %mf_wordsInStr1andStr2(
Str1=blah sss blaaah brah bram boo
,Str2= blah blaaah brah ssss
);
returns:
> blah blaaah brah
@param str1= string containing words to extract
@param str2= used to compare with the extract string
@warning CASE SENSITIVE!
@version 9.2
@author Allan Bowe
**/
%macro mf_wordsInStr1andStr2(
Str1= /* string containing words to extract */
,Str2= /* used to compare with the extract string */
)/*/STORE SOURCE*/;
%local count_base count_extr i i2 extr_word base_word match outvar;
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
%put base string (str1)= &str1;
%put compare string (str2) = &str2;
%return;
%end;
%let count_base=%sysfunc(countw(&Str2));
%let count_extr=%sysfunc(countw(&Str1));
%do i=1 %to &count_extr;
%let extr_word=%scan(&Str1,&i,%str( ));
%let match=0;
%do i2=1 %to &count_base;
%let base_word=%scan(&Str2,&i2,%str( ));
%if &extr_word=&base_word %then %let match=1;
%end;
%if &match=1 %then %let outvar=&outvar &extr_word;
%end;
&outvar
%mend mf_wordsInStr1andStr2;

View File

@@ -3,20 +3,21 @@
@brief Returns words that are in string 1 but not in string 2
@details Compares two space separated strings and returns the words that are
in the first but not in the second.
Note - case sensitive!
Usage:
%let x= %mf_wordsInStr1ButNotStr2(
Str1=blah sss blaaah brah bram boo
Str1=blah sss blaaah brah bram boo
,Str2= blah blaaah brah ssss
);
returns:
> sss bram boo
@param str1= string containing words to extract
@param str2= used to compare with the extract string
@warning CASE SENSITIVE!
@param [in] str1= string containing words to extract
@param [in] str2= used to compare with the extract string
@version 9.2
@author Allan Bowe
@@ -24,13 +25,12 @@
**/
%macro mf_wordsInStr1ButNotStr2(
Str1= /* string containing words to extract */
,Str2= /* used to compare with the extract string */
Str1= /* string containing words to extract */
,Str2= /* used to compare with the extract string */
)/*/STORE SOURCE*/;
%local count_base count_extr i i2 extr_word base_word match outvar;
%if %length(&str1)=0 or %length(&str2)=0 %then %do;
%put WARNING: empty string provided!;
%put base string (str1)= &str1;
%put compare string (str2) = &str2;
%return;
@@ -50,5 +50,5 @@
&outvar
%mend;
%mend mf_wordsInStr1ButNotStr2;

67
base/mf_writefile.sas Normal file
View File

@@ -0,0 +1,67 @@
/**
@file
@brief Creates a text file using pure macro
@details Creates a text file of up to 10 lines. If further lines are
desired, feel free to [create an issue](
https://github.com/sasjs/core/issues/new), or make a pull request!
The use of PARMBUFF was considered for this macro, but it would have made
things problematic for writing lines containing commas.
Usage:
%mf_writefile(&sasjswork/myfile.txt,l1=some content,l2=more content)
data _null_;
infile "&sasjswork/myfile.txt";
input;
list;
run;
@param [in] fpath Full path to file to be created or appended to
@param [in] mode= (O) Available options are A or O as follows:
@li A APPEND mode, writes new records after the current end of the file.
@li O OUTPUT mode, writes new records from the beginning of the file.
@param [in] l1= First line
@param [in] l2= Second line (etc through to l10)
<h4> Related Macros </h4>
@li mf_writefile.test.sas
@version 9.2
@author Allan Bowe
**/
/** @cond */
%macro mf_writefile(fpath,mode=O,l1=,l2=,l3=,l4=,l5=,l6=,l7=,l8=,l9=,l10=
)/*/STORE SOURCE*/;
%local fref rc fid i total_lines;
/* find number of lines by reference to first non-blank param */
%do i=10 %to 1 %by -1;
%if %str(&&l&i) ne %str() %then %goto continue;
%end;
%continue:
%let total_lines=&i;
%if %sysfunc(filename(fref,&fpath)) ne 0 %then %do;
%put &=fref &=fpath;
%put %str(ERR)OR: %sysfunc(sysmsg());
%return;
%end;
%let fid=%sysfunc(fopen(&fref,&mode));
%if &fid=0 %then %do;
%put %str(ERR)OR: %sysfunc(sysmsg());
%return;
%end;
%do i=1 %to &total_lines;
%let rc=%sysfunc(fput(&fid, &&l&i));
%let rc=%sysfunc(fwrite(&fid));
%end;
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(&fref));
%mend mf_writefile;
/** @endcond */

View File

@@ -4,137 +4,298 @@
@details Configures an abort mechanism according to site specific policies or
the particulars of an environment. For instance, can stream custom
results back to the client in an STP Web App context, or completely stop
in the case of a batch run.
in the case of a batch run. For STP sessions
@param mac= to contain the name of the calling macro
The method used varies according to the context. Important points:
@li should not use endsas or abort cancel in 9.4m3 WIN environments as this
can cause hung multibridge sessions and result in a frozen STP server
@li The use of endsas in 9.4m6+ windows environments for POST requests to the
STP server can result in an empty response body
@li should not use endsas in viya 3.5 as this destroys the session and cannot
fetch results (although both mv_getjoblog.sas and the @sasjs/adapter will
recognise this and fetch the log of the parent session instead)
@li STP environments must finish cleanly to avoid the log being sent to
_webout. To assist with this, we also run stpsrvset('program error', 0)
and set SYSCC=0.
Where possible, we take a unique "soft abort" approach - we open a macro
but don't close it! This works everywhere EXCEPT inside a \%include inside
a macro. For that, we recommend you use mp_include.sas to perform the
include, and then call \%mp_abort(mode=INCLUDE) from the source program (ie,
OUTSIDE of the top-parent macro).
The soft abort has become ineffective in 9.4m6 WINDOWS environments. We are
currently investigating approaches to deal with this.
@param mac= (mp_abort.sas) To contain the name of the calling macro. Do not
use &sysmacroname as this will always resolve to MP_ABORT.
@param msg= message to be returned
@param iftrue= supply a condition under which the macro should be executed.
@param iftrue= (1=1) Supply a condition for which the macro should be executed
@param errds= (work.mp_abort_errds) There is no clean way to end a process
within a %include called within a macro. Furthermore, there is no way to
test if a macro is called within a %include. To handle this particular
scenario, the %include should be switched for the mp_include.sas macro.
This provides an indicator that we are running a macro within a \%include
(`_SYSINCLUDEFILEDEVICE`) and allows us to provide a dataset with the abort
values (msg, mac).
We can then run an abort cancel FILE to stop the include running, and pass
the dataset back to the calling program to run a regular \%mp_abort().
The dataset will contain the following fields:
@li iftrue (1=1)
@li msg (the message)
@li mac (the mac param)
@version 9.4M3
@param mode= (REGULAR) If mode=INCLUDE then the &errds dataset is checked for
an abort status.
Valid values:
@li REGULAR (default)
@li INCLUDE
@version 9.4
@author Allan Bowe
<h4> Related Macros </h4>
@li mp_include.sas
@cond
**/
%macro mp_abort(mac=mp_abort.sas, type=, msg=, iftrue=%str(1=1)
, errds=work.mp_abort_errds
, mode=REGULAR
)/*/STORE SOURCE*/;
%if not(%eval(%unquote(&iftrue))) %then %return;
%global sysprocessmode sysprocessname sasjs_stpsrv_header_loc sasjsprocessmode;
%local fref fid i;
%put NOTE: /// mp_abort macro executing //;
%if %length(&mac)>0 %then %put NOTE- called by &mac;
%put NOTE - &msg;
%if not(%eval(%unquote(&iftrue))) %then %return;
/* Stored Process Server web app context */
%if %symexist(_metaperson)
or (%symexist(SYSPROCESSNAME) and "&SYSPROCESSNAME"="Compute Server" )
%put NOTE: /// mp_abort macro executing //;
%if %length(&mac)>0 %then %put NOTE- called by &mac;
%put NOTE - &msg;
%if %symexist(_SYSINCLUDEFILEDEVICE)
/* abort cancel FILE does not restart outside the INCLUDE on Viya 3.5 */
and %superq(SYSPROCESSNAME) ne %str(Compute Server)
%then %do;
%if "*&_SYSINCLUDEFILEDEVICE*" ne "**" %then %do;
data &errds;
iftrue='1=1';
length mac $100 msg $5000;
mac=symget('mac');
msg=symget('msg');
run;
data _null_;
abort cancel FILE;
run;
%return;
%end;
%end;
/* Web App Context */
%if %symexist(_PROGRAM)
or %superq(SYSPROCESSNAME) = %str(Compute Server)
or &mode=INCLUDE
%then %do;
options obs=max replace mprint;
%if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5"
%then %do;
options obs=max replace nosyntaxcheck mprint;
/* extract log errs / warns, if exist */
%local logloc logline;
%global logmsg; /* capture global messages */
%if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG;
%else %let logloc=%qsysfunc(getoption(LOG));
proc printto log=log;run;
%if %length(&logloc)>0 %then %do;
%let logline=0;
options nosyntaxcheck;
%end;
%if &mode=INCLUDE %then %do;
%if %sysfunc(exist(&errds))=1 %then %do;
data _null_;
set &errds;
call symputx('iftrue',iftrue,'l');
call symputx('mac',mac,'l');
call symputx('msg',msg,'l');
putlog (_all_)(=);
run;
%if (&iftrue)=0 %then %return;
%end;
%else %do;
%put &sysmacroname: No include errors found;
%return;
%end;
%end;
/* extract log errs / warns, if exist */
%local logloc logline;
%global logmsg; /* capture global messages */
%if %symexist(SYSPRINTTOLOG) %then %let logloc=&SYSPRINTTOLOG;
%else %let logloc=%qsysfunc(getoption(LOG));
proc printto log=log;run;
%let logline=0;
%if %length(&logloc)>0 %then %do;
data _null_;
infile &logloc lrecl=5000;
input; putlog _infile_;
i=1;
retain logonce 0;
if (
_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR"
) and logonce=0 then
do;
call symputx('logline',_n_);
logonce+1;
end;
run;
/* capture log including lines BEFORE the err */
%if &logline>0 %then %do;
data _null_;
infile &logloc lrecl=5000;
input; putlog _infile_;
input;
i=1;
retain logonce 0;
if (_infile_=:"%str(WARN)ING" or _infile_=:"%str(ERR)OR") and logonce=0 then do;
call symputx('logline',_n_);
logonce+1;
end;
run;
/* capture log including lines BEFORE the err */
%if &logline>0 %then %do;
data _null_;
infile &logloc lrecl=5000;
stoploop=0;
if _n_ ge &logline-15 and stoploop=0 then do until (i>22);
call symputx('logmsg',catx('\n',symget('logmsg'),_infile_));
input;
i=1;
stoploop=0;
if _n_ ge &logline-5 and stoploop=0 then do until (i>12);
call symputx('logmsg',catx('\n',symget('logmsg'),_infile_));
input;
i+1;
stoploop=1;
end;
if stoploop=1 then stop;
run;
%end;
%end;
%if %symexist(SYS_JES_JOB_URI) %then %do;
/* refer web service output to file service in one hit */
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json";
%end;
/* send response in SASjs JSON format */
data _null_;
file _webout mod lrecl=32000;
length msg $32767 debug $8;
sasdatetime=datetime();
msg=cats(symget('msg'),'\n\nLog Extract:\n',symget('logmsg'));
/* escape the quotes */
msg=tranwrd(msg,'"','\"');
/* ditch the CRLFs as chrome complains */
msg=compress(msg,,'kw');
/* quote without quoting the quotes (which are escaped instead) */
msg=cats('"',msg,'"');
if symexist('_debug') then debug=quote(trim(symget('_debug')));
else debug='""';
if debug ge '"131"' then put '>>weboutBEGIN<<';
put '{"START_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '"';
put ',"sasjsAbort" : [{';
put ' "MSG":' msg ;
put ' ,"MAC": "' "&mac" '"}]';
put ",""SYSUSERID"" : ""&sysuserid"" ";
put ',"_DEBUG":' debug ;
if symexist('_metauser') then do;
_METAUSER=quote(trim(symget('_METAUSER')));
put ",""_METAUSER"": " _METAUSER;
_METAPERSON=quote(trim(symget('_METAPERSON')));
put ',"_METAPERSON": ' _METAPERSON;
end;
if symexist('SYS_JES_JOB_URI') then do;
SYS_JES_JOB_URI=quote(trim(symget('SYS_JES_JOB_URI')));
put ',"SYS_JES_JOB_URI": ' SYS_JES_JOB_URI;
end;
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSERRORTEXT"" : ""&syserrortext"" ";
put ",""SYSJOBID"" : ""&sysjobid"" ";
put ",""SYSWARNINGTEXT"" : ""&syswarningtext"" ";
put ',"END_DTTM" : "' "%sysfunc(datetime(),datetime20.3)" '" ';
put "}" @;
if debug ge '"131"' then put '>>weboutEND<<';
run;
%let syscc=0;
%if %symexist(_metaport) %then %do;
data _null_;
if symexist('sysprocessmode')
then if symget("sysprocessmode")="SAS Stored Process Server"
then rc=stpsrvset('program error', 0);
i+1;
stoploop=1;
end;
if stoploop=1 then stop;
run;
%end;
/**
* endsas is reliable but kills some deployments.
* Abort variants are ungraceful (non zero return code)
* This approach lets SAS run silently until the end :-)
*/
%put _all_;
filename skip temp;
%end;
%if %symexist(SYS_JES_JOB_URI) %then %do;
/* setup webout for Viya */
options nobomfile;
%if "X&SYS_JES_JOB_URI.X"="XX" %then %do;
filename _webout temp lrecl=999999 mod;
%end;
%else %do;
filename _webout filesrvc parenturi="&SYS_JES_JOB_URI"
name="_webout.json" lrecl=999999 mod;
%end;
%end;
%else %if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc))=0 %then %do;
options nobomfile;
/* set up http header for SASjs Server */
%let fid=%sysfunc(fopen(&fref,A));
%if &fid=0 %then %do;
%put %str(ERR)OR: %sysfunc(sysmsg());
%return;
%end;
%let rc=%sysfunc(fput(&fid,%str(Content-Type: application/json)));
%let rc=%sysfunc(fwrite(&fid));
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(&fref));
%end;
/* send response in SASjs JSON format */
data _null_;
file _webout mod lrecl=32000 encoding='utf-8';
length msg syswarningtext syserrortext $32767 mode $10 ;
sasdatetime=datetime();
msg=symget('msg');
%if &logline>0 %then %do;
msg=cats(msg,'\n\nLog Extract:\n',symget('logmsg'));
%end;
/* escape the escapes */
msg=tranwrd(msg,'\','\\');
/* escape the quotes */
msg=tranwrd(msg,'"','\"');
/* ditch the CRLFs as chrome complains */
msg=compress(msg,,'kw');
/* quote without quoting the quotes (which are escaped instead) */
msg=cats('"',msg,'"');
if symexist('_debug') then debug=quote(trim(symget('_debug')));
else debug='""';
if symget('sasjsprocessmode')='Stored Program' then mode='SASJS';
if mode ne 'SASJS' then put '>>weboutBEGIN<<';
put '{"SYSDATE" : "' "&SYSDATE" '"';
put ',"SYSTIME" : "' "&SYSTIME" '"';
put ',"sasjsAbort" : [{';
put ' "MSG":' msg ;
put ' ,"MAC": "' "&mac" '"}]';
put ",""SYSUSERID"" : ""&sysuserid"" ";
put ',"_DEBUG":' debug ;
if symexist('_metauser') then do;
_METAUSER=quote(trim(symget('_METAUSER')));
put ",""_METAUSER"": " _METAUSER;
_METAPERSON=quote(trim(symget('_METAPERSON')));
put ',"_METAPERSON": ' _METAPERSON;
end;
if symexist('SYS_JES_JOB_URI') then do;
SYS_JES_JOB_URI=quote(trim(symget('SYS_JES_JOB_URI')));
put ',"SYS_JES_JOB_URI": ' SYS_JES_JOB_URI;
end;
_PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"');
put ",""SYSERRORTEXT"" : " syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSJOBID"" : ""&sysjobid"" ";
put ",""SYSSCPL"" : ""&sysscpl"" ";
put ",""SYSSITE"" : ""&syssite"" ";
sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"');
put ",""SYSWARNINGTEXT"" : " syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
put "}" ;
if mode ne 'SASJS' then put '>>weboutEND<<';
run;
%put _all_;
%if "&sysprocessmode " = "SAS Stored Process Server " %then %do;
data _null_;
file skip;
put '%macro skip(); %macro skippy();';
putlog 'stpsrvset program err and syscc';
rc=stpsrvset('program error', 0);
call symputx("syscc",0,"g");
run;
%if &sysscp=WIN
and 1=0 /* deprecating this logic until we figure out a consistent abort */
and "%substr(%str(&sysvlong ),1,8)"="9.04.01M"
and "%substr(%str(&sysvlong ),9,1)">"5" %then %do;
/* skip approach (below) does not work in windows m6+ envs */
endsas;
%end;
%else %do;
/**
* endsas kills 9.4m3 deployments by orphaning multibridges.
* Abort variants are ungraceful (non zero return code)
* This approach lets SAS run silently until the end :-)
* Caution - fails when called within a %include within a macro
* Use mp_include() to handle this.
*/
filename skip temp;
data _null_;
file skip;
put '%macro skip();';
comment '%mend skip; -> fix lint ';
put '%macro skippy();';
comment '%mend skippy; -> fix lint ';
run;
%inc skip;
%end;
%end;
%else %if "&sysprocessmode " = "SAS Compute Server " %then %do;
/* endsas kills the session making it harder to fetch results */
data _null_;
syswarningtext=symget('syswarningtext');
syserrortext=symget('syserrortext');
abort_msg=symget('msg');
syscc=symget('syscc');
sysuserid=symget('sysuserid');
iftrue=symget('iftrue');
put (_all_)(/=);
call symputx('syscc',0);
abort cancel nolist;
run;
%inc skip;
%end;
%else %do;
%put _all_;
%abort cancel;
%end;
%mend;
%end;
%else %do;
%put _all_;
%abort cancel;
%end;
%mend mp_abort;
/** @endcond */

57
base/mp_appendfile.sas Normal file
View File

@@ -0,0 +1,57 @@
/**
@file
@brief Append (concatenate) two or more files.
@details Will append one more more `appendrefs` (filerefs) to a `baseref`.
Uses a binary mechanism, so will work with any file type. For that reason -
use with care! And supply your own trailing carriage returns in each file..
Usage:
filename tmp1 temp;
filename tmp2 temp;
filename tmp3 temp;
data _null_; file tmp1; put 'base file';
data _null_; file tmp2; put 'append1';
data _null_; file tmp3; put 'append2';
run;
%mp_appendfile(baseref=tmp1, appendrefs=tmp2 tmp3)
@param [in] baseref= Fileref of the base file (should exist)
@param [in] appendrefs= One or more filerefs to be appended to the base
fileref. Space separated.
@version 9.2
@author Allan Bowe, source: https://github.com/sasjs/core
<h4> SAS Macros </h4>
@li mp_abort.sas
@li mp_binarycopy.sas
**/
%macro mp_appendfile(
baseref=0,
appendrefs=0
)/*/STORE SOURCE*/;
%mp_abort(iftrue= (&baseref=0)
,mac=&sysmacroname
,msg=%str(Baseref NOT specified!)
)
%mp_abort(iftrue= (&appendrefs=0)
,mac=&sysmacroname
,msg=%str(Appendrefs NOT specified!)
)
%local i;
%do i=1 %to %sysfunc(countw(&appendrefs));
%mp_abort(iftrue= (&syscc>0)
,mac=&sysmacroname
,msg=%str(syscc=&syscc)
)
%mp_binarycopy(inref=%scan(&appendrefs,&i), outref=&baseref, mode=APPEND)
%end;
%mend mp_appendfile;

181
base/mp_applyformats.sas Normal file
View File

@@ -0,0 +1,181 @@
/**
@file
@brief Apply a set of formats to a table
@details Applies a set of formats to the metadata of one or more SAS datasets.
Can be used to migrate formats from one table to another. The input table
must contain the following columns:
@li lib - the libref of the table to be updated
@li ds - the dataset to be updated
@li var - the variable to be updated
@li fmt - the format to apply. Missing or default ($CHAR, 8.) formats are
ignored.
The macro will abort in the following scenarios:
@li Libref not assigned
@li Dataset does not exist
@li Input table contains null or invalid values
Example usage:
data work.example;
set sashelp.prdsale;
format _all_ clear;
run;
%mp_getcols(sashelp.prdsale,outds=work.cols)
data work.cols2;
set work.cols;
lib='WORK';
ds='EXAMPLE';
var=name;
fmt=format;
keep lib ds var fmt;
run;
%mp_applyformats(work.cols2)
@param [in] inds The input dataset containing the formats to apply (and where
to apply them). Example structure:
|LIB:$8.|DS:$32.|VAR:$32.|FMT:$49.|
|---|---|---|---|
|`WORK `|`EXAMPLE `|`ACTUAL `|`DOLLAR12.2 `|
|`WORK `|`EXAMPLE `|`COUNTRY `|`$CHAR10. `|
|`WORK `|`EXAMPLE `|`DIVISION `|`$CHAR10. `|
|`WORK `|`EXAMPLE `|`MONTH `|`MONNAME3. `|
|`WORK `|`EXAMPLE `|`PREDICT `|`DOLLAR12.2 `|
|`WORK `|`EXAMPLE `|`PRODTYPE `|`$CHAR10. `|
|`WORK `|`EXAMPLE `|`PRODUCT `|`$CHAR10. `|
|`WORK `|`EXAMPLE `|`QUARTER `|`8. `|
|`WORK `|`EXAMPLE `|`REGION `|`$CHAR10. `|
|`WORK `|`EXAMPLE `|`YEAR `|`8. `|
@param [out] errds= (0) Provide a libds reference here to export the
error messages to a table. In this case, they will not be printed to the
log.
<h4> SAS Macros </h4>
@li mf_getengine.sas
@li mf_getuniquefileref.sas
@li mf_getuniquename.sas
@li mf_nobs.sas
@li mp_validatecol.sas
<h4> Related Macros </h4>
@li mp_getformats.sas
@version 9.2
@author Allan Bowe
**/
%macro mp_applyformats(inds,errds=0
)/*/STORE SOURCE*/;
%local outds liblist i engine lib msg ;
/**
* Validations
*/
proc sort data=&inds;
by lib ds var fmt;
run;
%if &errds=0 %then %let outds=%mf_getuniquename(prefix=mp_applyformats);
%else %let outds=&errds;
data &outds;
set &inds;
where fmt not in ('','.', '$', '$CHAR.','8.');
length msg $128;
by lib ds var fmt;
if libref(lib) ne 0 then do;
msg=catx(' ','libref',lib,'is not assigned!');
%if &errds=0 %then %do;
putlog "%str(ERR)OR: " msg;
%end;
output;
return;
end;
if exist(cats(lib,'.',ds)) ne 1 then do;
msg=catx(' ','libds',lib,'.',ds,'does not exist!');
%if &errds=0 %then %do;
putlog "%str(ERR)OR: " msg;
%end;
output;
return;
end;
%mp_validatecol(fmt,FORMAT,is_fmt)
if is_fmt=0 then do;
msg=catx(' ','format',fmt,'on libds',lib,'.',ds,'.',var,'is not valid!');
%if &errds=0 %then %do;
putlog "%str(ERR)OR: " msg;
%end;
output;
return;
end;
if first.ds then do;
retain dsid;
dsid=open(cats(lib,'.',ds));
if dsid=0 then do;
msg=catx(' ','libds',lib,'.',ds,' could not be opened!');
%if &errds=0 %then %do;
putlog "%str(ERR)OR: " msg;
%end;
output;
return;
end;
if varnum(dsid,var)<1 then do;
msg=catx(' ','Variable',lib,'.',ds,'.',var,' was not found!');
%if &errds=0 %then %do;
putlog "%str(ERR)OR: " msg;
%end;
output;
end;
end;
if last.ds then rc=close(dsid);
run;
proc sql noprint;
select distinct lib into: liblist separated by ' ' from &inds;
%put &=liblist;
%if %length(&liblist)>0 %then %do i=1 %to %sysfunc(countw(&liblist));
%let lib=%scan(&liblist,1);
%let engine=%mf_getengine(&lib);
%if &engine ne V9 and &engine ne BASE %then %do;
%let msg=&lib has &engine engine - formats cannot be applied;
insert into &outds set lib="&lib",ds="_all_",var="_all", msg="&msg" ;
%if &errds=0 %then %put %str(ERR)OR: &msg;
%end;
%end;
quit;
%if %mf_nobs(&outds)>0 %then %return;
/**
* Validations complete - now apply the actual formats!
*/
%let fref=%mf_getuniquefileref();
data _null_;
set &inds;
by lib ds var fmt;
where fmt not in ('','.', '$', '$CHAR.','8.');
file &fref;
if first.lib then put 'proc datasets nolist lib=' lib ';';
if first.ds then put ' modify ' ds ';';
put ' format ' var fmt ';';
if last.ds then put ' run;';
if last.lib then put 'quit;';
run;
%inc &fref/source2;
%if &errds=0 %then %do;
proc sql;
drop table &outds;
%end;
%mend mp_applyformats;

56
base/mp_assert.sas Normal file
View File

@@ -0,0 +1,56 @@
/**
@file
@brief Generic assertion
@details Useful in the context of writing sasjs tests. The results of the
test are _appended_ to the &outds. table.
Example usage:
%mp_assert(iftrue=(1=1),
desc=Obviously true
)
%mp_assert(iftrue=(1=0),
desc=Will fail
)
@param [in] iftrue= (1=1) A condition where, if true, the test is a PASS.
Else, the test is a fail.
@param [in] desc= (Testing observations) The user provided test description
@param [out] outds= (work.test_results) The output dataset to contain the
results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---|
|User Provided description|PASS|Column &inds contained ALL columns|
@version 9.2
@author Allan Bowe
**/
%macro mp_assert(iftrue=(1=1),
desc=0,
outds=work.test_results
)/*/STORE SOURCE*/;
data ;
length test_description $256 test_result $4 test_comments $256;
test_description=symget('desc');
test_comments="&sysmacroname: Test result of "!!symget('iftrue');
%if %eval(%unquote(&iftrue)) %then %do;
test_result='PASS';
%end;
%else %do;
test_result='FAIL';
%end;
run;
%local ds ;
%let ds=&syslast;
proc append base=&outds data=&ds;
run;
proc sql;
drop table &ds;
%mend mp_assert;

145
base/mp_assertcols.sas Normal file
View File

@@ -0,0 +1,145 @@
/**
@file
@brief Asserts the existence (or not) of columns
@details Useful in the context of writing sasjs tests. The results of the
test are _appended_ to the &outds. table.
Example usage:
%mp_assertcols(sashelp.class,
cols=name age sex,
test=ALL,
desc=check all columns exist
)
%mp_assertcols(sashelp.class,
cols=a b c,
test=NONE
)
%mp_assertcols(sashelp.class,
cols=age depth,
test=ANY
)
<h4> SAS Macros </h4>
@li mf_existds.sas
@li mf_existvarlist.sas
@li mf_getvarlist.sas
@li mf_wordsinstr1butnotstr2.sas
@li mp_abort.sas
@param [in] inds The input library.dataset to test for values
@param [in] cols= The list of columns to check for
@param [in] desc= (Testing observations) The user provided test description
@param [in] test= (ALL) The test to apply. Valid values are:
@li ALL - Test is a PASS if ALL columns exist in &inds
@li ANY - Test is a PASS if ANY of the columns exist in &inds
@li NONE - Test is a PASS if NONE of the columns exist in &inds
@param [out] outds= (work.test_results) The output dataset to contain the
results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---|
|User Provided description|PASS|Column &inds contained ALL columns|
<h4> Related Macros </h4>
@li mp_assertdsobs.sas
@li mp_assertcolvals.sas
@li mp_assertdsobs.sas
@version 9.2
@author Allan Bowe
**/
%macro mp_assertcols(inds,
cols=0,
test=ALL,
desc=0,
outds=work.test_results
)/*/STORE SOURCE*/;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&sysmacroname
,msg=%str(syscc=&syscc - on macro entry)
)
%local lib ds ;
%let lib=%scan(&inds,1,%str(.));
%let ds=%scan(&inds,2,%str(.));
%let cols=%upcase(&cols);
%mp_abort(iftrue= (%mf_existds(&lib..&ds)=0)
,mac=&sysmacroname
,msg=%str(&lib..&ds not found!)
)
%mp_abort(iftrue= (&cols=0)
,mac=&sysmacroname
,msg=%str(No cols provided)
)
%let test=%upcase(&test);
%if &test ne ANY and &test ne ALL and &test ne NONE %then %do;
%mp_abort(
mac=&sysmacroname,
msg=%str(Invalid test - &test)
)
%end;
/**
* now do the actual test!
*/
%local result;
%if %mf_existVarList(&inds,&cols)=1 %then %let result=ALL;
%else %do;
%local targetcols compare;
%let targetcols=%upcase(%mf_getvarlist(&inds));
%let compare=%mf_wordsinstr1butnotstr2(
Str1=&cols,
Str2=&targetcols
);
%if %cmpres(&compare)=%cmpres(&cols) %then %let result=NONE;
%else %let result=SOME;
%end;
data;
length test_description $256 test_result $4 test_comments $256;
test_description=symget('desc');
if test_description='0'
then test_description="Testing &inds for existence of &test of: &cols";
test_result='FAIL';
test_comments="&sysmacroname: &inds has &result columns ";
%if &test=ALL %then %do;
%if &result=ALL %then %do;
test_result='PASS';
%end;
%end;
%else %if &test=ANY %then %do;
%if &result=SOME %then %do;
test_result='PASS';
%end;
%end;
%else %if &test=NONE %then %do;
%if &result=NONE %then %do;
test_result='PASS';
%end;
%end;
%else %do;
test_comments="&sysmacroname: Unsatisfied test condition - &test";
%end;
run;
%local ds;
%let ds=&syslast;
proc append base=&outds data=&ds;
run;
proc sql;
drop table &ds;
%mend mp_assertcols;

168
base/mp_assertcolvals.sas Normal file
View File

@@ -0,0 +1,168 @@
/**
@file
@brief Asserts the values in a column
@details Useful in the context of writing sasjs tests. The results of the
test are _appended_ to the &outds. table.
Example usage:
data work.checkds;
do checkval='Jane','James','Jill';
output;
end;
run;
%mp_assertcolvals(sashelp.class.name,
checkvals=work.checkds.checkval,
desc=At least one value has a match,
test=ANYVAL
)
data work.check;
do val='M','F';
output;
end;
run;
%mp_assertcolvals(sashelp.class.sex,
checkvals=work.check.val,
desc=All values have a match,
test=ALLVALS
)
<h4> SAS Macros </h4>
@li mf_existds.sas
@li mf_getuniquename.sas
@li mf_nobs.sas
@li mp_abort.sas
@param [in] indscol The input library.dataset.column to test for values
@param [in] checkvals= A library.dataset.column value containing a UNIQUE
list of values to be compared against the source (indscol).
@param [in] desc= (Testing observations) The user provided test description
@param [in] test= (ALLVALS) The test to apply. Valid values are:
@li ALLVALS - Test is a PASS if ALL values have a match in checkvals
@li ANYVAL - Test is a PASS if at least 1 value has a match in checkvals
@param [out] outds= (work.test_results) The output dataset to contain the
results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---|
|User Provided description|PASS|Column &indscol contained ALL target vals|
<h4> Related Macros </h4>
@li mp_assertdsobs.sas
@version 9.2
@author Allan Bowe
**/
%macro mp_assertcolvals(indscol,
checkvals=0,
test=ALLVALS,
desc=mp_assertcolvals - no desc provided,
outds=work.test_results
)/*/STORE SOURCE*/;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&sysmacroname
,msg=%str(syscc=&syscc - on macro entry)
)
%local lib ds col clib cds ccol nobs;
%let lib=%scan(&indscol,1,%str(.));
%let ds=%scan(&indscol,2,%str(.));
%let col=%scan(&indscol,3,%str(.));
%mp_abort(iftrue= (%mf_existds(&lib..&ds)=0)
,mac=&sysmacroname
,msg=%str(&lib..&ds not found!)
)
%mp_abort(iftrue= (&checkvals=0)
,mac=&sysmacroname
,msg=%str(Set CHECKVALS to a library.dataset.column containing check vals)
)
%let clib=%scan(&checkvals,1,%str(.));
%let cds=%scan(&checkvals,2,%str(.));
%let ccol=%scan(&checkvals,3,%str(.));
%mp_abort(iftrue= (%mf_existds(&clib..&cds)=0)
,mac=&sysmacroname
,msg=%str(&clib..&cds not found!)
)
%let nobs=%mf_nobs(&clib..&cds);
%mp_abort(iftrue= (&nobs=0)
,mac=&sysmacroname
,msg=%str(&clib..&cds is empty!)
)
%let test=%upcase(&test);
%if &test ne ALLVALS and &test ne ANYVAL %then %do;
%mp_abort(
mac=&sysmacroname,
msg=%str(Invalid test - &test)
)
%end;
%local result orig;
%let result=-1;
%let orig=-1;
proc sql noprint;
select count(*) into: result
from &lib..&ds
where &col not in (
select &ccol from &clib..&cds
);
select count(*) into: orig from &lib..&ds;
quit;
%local notfound tmp1 tmp2;
%let tmp1=%mf_getuniquename();
%let tmp2=%mf_getuniquename();
/* this is a bit convoluted - but using sql outobs=10 throws warnings */
proc sql noprint;
create view &tmp1 as
select distinct &col
from &lib..&ds
where &col not in (
select &ccol from &clib..&cds
);
data &tmp2;
set &tmp1;
if _n_>10 then stop;
run;
proc sql;
select distinct &col into: notfound separated by ' ' from &tmp2;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&sysmacroname
,msg=%str(syscc=&syscc after macro query)
)
data;
length test_description $256 test_result $4 test_comments $256;
test_description=symget('desc');
test_result='FAIL';
test_comments="&sysmacroname: &lib..&ds..&col has &result values "
!!"not in &clib..&cds..&ccol.. First 10 vals:"!!symget('notfound');
%if &test=ANYVAL %then %do;
if &result < &orig then test_result='PASS';
%end;
%else %if &test=ALLVALS %then %do;
if &result=0 then test_result='PASS';
%end;
%else %do;
test_comments="&sysmacroname: Unsatisfied test condition - &test";
%end;
run;
%local ds;
%let ds=&syslast;
proc append base=&outds data=&ds;
run;
proc sql;
drop table &ds;
%mend mp_assertcolvals;

121
base/mp_assertdsobs.sas Normal file
View File

@@ -0,0 +1,121 @@
/**
@file
@brief Asserts the number of observations in a dataset
@details Useful in the context of writing sasjs tests. The results of the
test are _appended_ to the &outds. table.
Example usage:
%mp_assertdsobs(sashelp.class) %* tests if any observations are present;
%mp_assertdsobs(sashelp.class,test=ATLEAST 10) %* pass if >9 obs present;
%mp_assertdsobs(sashelp.class,test=ATMOST 20) %* pass if <21 obs present;
@param [in] inds input dataset to test for presence of observations
@param [in] desc= (Testing observations) The user provided test description
@param [in] test= (HASOBS) The test to apply. Valid values are:
@li HASOBS - Test is a PASS if the input dataset has any observations
@li EMPTY - Test is a PASS if input dataset is empty
@li EQUALS [integer] - Test passes if row count matches the provided integer
@li ATLEAST [integer] - Test passes if row count is more than or equal to
the provided integer
@li ATMOST [integer] - Test passes if row count is less than or equal to
the provided integer
@param [out] outds= (work.test_results) The output dataset to contain the
results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---|
|User Provided description|PASS|Dataset &inds has XX obs|
<h4> SAS Macros </h4>
@li mf_getuniquename.sas
@li mf_nobs.sas
@li mp_abort.sas
<h4> Related Macros </h4>
@li mp_assertcolvals.sas
@li mp_assert.sas
@li mp_assertcols.sas
@version 9.2
@author Allan Bowe
**/
%macro mp_assertdsobs(inds,
test=HASOBS,
desc=Testing observations,
outds=work.test_results
)/*/STORE SOURCE*/;
%local nobs ds;
%let nobs=%mf_nobs(&inds);
%let test=%upcase(&test);
%let ds=%mf_getuniquename(prefix=mp_assertdsobs);
%if %substr(&test.xxxxx,1,6)=EQUALS %then %do;
%let val=%scan(&test,2,%str( ));
%mp_abort(iftrue= (%DATATYP(&val)=CHAR)
,mac=&sysmacroname
,msg=%str(Invalid test - &test, expected EQUALS [integer])
)
%let test=EQUALS;
%end;
%else %if %substr(&test.xxxxxxx,1,7)=ATLEAST %then %do;
%let val=%scan(&test,2,%str( ));
%mp_abort(iftrue= (%DATATYP(&val)=CHAR)
,mac=&sysmacroname
,msg=%str(Invalid test - &test, expected ATLEAST [integer])
)
%let test=ATLEAST;
%end;
%else %if %substr(&test.xxxxxxx,1,7)=ATMOST %then %do;
%let val=%scan(&test,2,%str( ));
%mp_abort(iftrue= (%DATATYP(&val)=CHAR)
,mac=&sysmacroname
,msg=%str(Invalid test - &test, expected ATMOST [integer])
)
%let test=ATMOST;
%end;
%else %if &test ne HASOBS and &test ne EMPTY %then %do;
%mp_abort(
mac=&sysmacroname,
msg=%str(Invalid test - &test)
)
%end;
data &ds;
length test_description $256 test_result $4 test_comments $256;
test_description=symget('desc');
test_result='FAIL';
test_comments="&sysmacroname: Dataset &inds has &nobs observations.";
test_comments=test_comments!!" Test was "!!symget('test');
%if &test=HASOBS %then %do;
if &nobs>0 then test_result='PASS';
%end;
%else %if &test=EMPTY %then %do;
if &nobs=0 then test_result='PASS';
%end;
%else %if &test=EQUALS %then %do;
if &nobs=&val then test_result='PASS';
%end;
%else %if &test=ATLEAST %then %do;
if &nobs ge &val then test_result='PASS';
%end;
%else %if &test=ATMOST %then %do;
if &nobs le &val then test_result='PASS';
%end;
%else %do;
test_comments="&sysmacroname: Unsatisfied test condition - &test";
%end;
run;
proc append base=&outds data=&ds;
run;
proc sql;
drop table &ds;
%mend mp_assertdsobs;

147
base/mp_assertscope.sas Normal file
View File

@@ -0,0 +1,147 @@
/**
@file
@brief Used to capture scope leakage of macro variables
@details
A common 'difficult to detect' bug in macros is where a nested macro
over-writes variables in a higher level macro.
This assertion takes a snapshot of the macro variables before and after
a macro invocation. Differences are captured in the `&outds` table. This
makes it easy to detect whether any macro variables were modified or
changed.
The following variables are NOT tested (as they are known, global variables
used in SASjs):
@li &sasjs_prefix._FUNCTIONS
Global variables are initialised in mp_init.sas - which will also trigger
"strict mode" in your SAS session. Whilst this is a default in SASjs
produced apps, if you prefer not to use this mode, simply instantiate the
following variable to prevent the macro from running: `SASJS_PREFIX`
Example usage:
%mp_assertscope(SNAPSHOT)
%let oops=I did it again;
%mp_assertscope(COMPARE,
desc=Checking macro variables against previous snapshot
)
This macro is designed to work alongside `sasjs test` - for more information
about this facility, visit [cli.sasjs.io/test](https://cli.sasjs.io/test).
@param [in] action (SNAPSHOT) The action to take. Valid values:
@li SNAPSHOT - take a copy of the current macro variables
@li COMPARE - compare the current macro variables against previous values
@param [in] scope= (GLOBAL) The scope of the variables to be checked. This
corresponds to the values in the SCOPE column in `sashelp.vmacro`.
@param [in] desc= (Testing scope leakage) The user provided test description
@param [in] ignorelist= Provide a list of macro variable names to ignore from
the comparison
@param [in,out] scopeds= (work.mp_assertscope) The dataset to contain the
scope snapshot
@param [out] outds= (work.test_results) The output dataset to contain the
results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---|
|User Provided description|PASS|No out of scope variables created or modified|
<h4> SAS Macros </h4>
@li mf_getquotedstr.sas
@li mp_init.sas
<h4> Related Macros </h4>
@li mp_assert.sas
@li mp_assertcols.sas
@li mp_assertcolvals.sas
@li mp_assertdsobs.sas
@li mp_assertscope.test.sas
@version 9.2
@author Allan Bowe
**/
%macro mp_assertscope(action,
desc=Testing Scope Leakage,
scope=GLOBAL,
scopeds=work.mp_assertscope,
ignorelist=,
outds=work.test_results
)/*/STORE SOURCE*/;
%local ds test_result test_comments del add mod ilist;
%let ilist=%upcase(&sasjs_prefix._FUNCTIONS SYS_PROCHTTP_STATUS_CODE
SYS_PROCHTTP_STATUS_CODE SYS_PROCHTTP_STATUS_PHRASE &ignorelist);
/**
* this sets up the global vars, it will also enter STRICT mode. If this
* behaviour is not desired, simply initiate the following global macro
* variable to prevent the macro from running: SASJS_PREFIX
*/
%mp_init()
/* get current variables */
%if &action=SNAPSHOT %then %do;
proc sql;
create table &scopeds as
select name,offset,value
from dictionary.macros
where scope="&scope" and upcase(name) not in (%mf_getquotedstr(&ilist))
order by name,offset;
%end;
%else %if &action=COMPARE %then %do;
proc sql;
create table _data_ as
select name,offset,value
from dictionary.macros
where scope="&scope" and upcase(name) not in (%mf_getquotedstr(&ilist))
order by name,offset;
%let ds=&syslast;
proc compare
base=&scopeds(where=(upcase(name) not in (%mf_getquotedstr(&ilist))))
compare=&ds noprint;
run;
%if &sysinfo=0 %then %do;
%let test_result=PASS;
%let test_comments=&scope Variables Unmodified;
%end;
%else %do;
proc sql noprint undo_policy=none;
select distinct name into: del separated by ' ' from &scopeds
where name not in (select name from &ds);
select distinct name into: add separated by ' ' from &ds
where name not in (select name from &scopeds);
select distinct a.name into: mod separated by ' '
from &scopeds a
inner join &ds b
on a.name=b.name
and a.offset=b.offset
where a.value ne b.value;
%let test_result=FAIL;
%let test_comments=%str(Mod:(&mod) Add:(&add) Del:(&del));
%end;
data ;
length test_description $256 test_result $4 test_comments $256;
test_description=symget('desc');
test_comments=symget('test_comments');
test_result=symget('test_result');
run;
%let ds=&syslast;
proc append base=&outds data=&ds;
run;
proc sql;
drop table &ds;
%end;
%mend mp_assertscope;

117
base/mp_base64copy.sas Normal file
View File

@@ -0,0 +1,117 @@
/**
@file
@brief Convert a file to/from base64 format
@details Creates a new version of a file either encoded or decoded using
Base64. Inspired by this post by Michael Dixon:
https://support.selerity.com.au/hc/en-us/articles/223345708-Tip-SAS-and-Base64
Usage:
filename tmp temp;
data _null_;
file tmp;
put 'base ik ally';
run;
%mp_base64copy(inref=tmp, outref=myref, action=ENCODE)
data _null_;
infile myref;
input;
put _infile_;
run;
%mp_base64copy(inref=myref, outref=mynewref, action=DECODE)
data _null_;
infile mynewref;
input;
put _infile_;
run;
@param [in] inref= Fileref of the input file (should exist)
@param [out] outref= Output fileref. If it does not exist, it is created.
@param [in] action= (ENCODE) The action to take. Valid values:
@li ENCODE - Convert the file to base64 format
@li DECODE - Decode the file from base64 format
@version 9.2
@author Allan Bowe, source: https://github.com/sasjs/core
<h4> SAS Macros </h4>
@li mp_abort.sas
**/
%macro mp_base64copy(
inref=0,
outref=0,
action=ENCODE
)/*/STORE SOURCE*/;
%let inref=%upcase(&inref);
%let outref=%upcase(&outref);
%let action=%upcase(&action);
%local infound outfound;
%let infound=0;
%let outfound=0;
data _null_;
set sashelp.vextfl(where=(fileref="&inref" or fileref="&outref"));
if fileref="&inref" then call symputx('infound',1,'l');
if fileref="&outref" then call symputx('outfound',1,'l');
run;
%mp_abort(iftrue= (&infound=0)
,mac=&sysmacroname
,msg=%str(INREF &inref NOT FOUND!)
)
%mp_abort(iftrue= (&outref=0)
,mac=&sysmacroname
,msg=%str(OUTREF NOT PROVIDED!)
)
%mp_abort(iftrue= (&action ne ENCODE and &action ne DECODE)
,mac=&sysmacroname
,msg=%str(Invalid action! Should be ENCODE OR DECODE)
)
%if &outfound=0 %then %do;
filename &outref temp lrecl=2097088;
%end;
%if &action=ENCODE %then %do;
data _null_;
length b64 $ 76 line $ 57;
retain line "";
infile &inref recfm=F lrecl= 1 end=eof;
input @1 stream $char1.;
file &outref recfm=N;
substr(line,(_N_-(CEIL(_N_/57)-1)*57),1) = byte(rank(stream));
if mod(_N_,57)=0 or EOF then do;
if eof then b64=put(trim(line),$base64X76.);
else b64=put(line, $base64X76.);
put b64 + (-1) @;
line="";
end;
run;
%end;
%else %if &action=DECODE %then %do;
data _null_;
length filein 8 fileout 8;
filein = fopen("&inref",'I',4,'B');
fileout = fopen("&outref",'O',3,'B');
char= '20'x;
do while(fread(filein)=0);
length raw $4;
do i=1 to 4;
rc=fget(filein,char,1);
substr(raw,i,1)=char;
end;
rc = fput(fileout,input(raw,$base64X4.));
rc = fwrite(fileout);
end;
rc = fclose(filein);
rc = fclose(fileout);
run;
%end;
%mend mp_base64copy;

View File

@@ -2,16 +2,37 @@
@file
@brief Copy any file using binary input / output streams
@details Reads in a file byte by byte and writes it back out. Is an
os-independent method to copy files. In case of naming collision, the
default filerefs can be modified.
Based on http://stackoverflow.com/questions/13046116/using-sas-to-copy-a-text-file
os-independent method to copy files. In case of naming collision, the
default filerefs can be modified.
Note that if you have a new enough version of SAS, and you don't need features
such as APPEND, you may be better of using the fcopy() function instead.
%mp_binarycopy(inloc="/home/me/blah.txt", outref=_webout)
@param inloc full, quoted "path/and/filename.ext" of the object to be copied
@param outloc full, quoted "path/and/filename.ext" of object to be created
@param inref can override default input fileref to avoid naming clash
@param outref an override default output fileref to avoid naming clash
To append to a file, use the mode option, eg:
filename tmp1 temp;
filename tmp2 temp;
data _null_;
file tmp1;
put 'stacking';
run;
%mp_binarycopy(inref=tmp1, outref=tmp2, mode=APPEND)
%mp_binarycopy(inref=tmp1, outref=tmp2, mode=APPEND)
@param [in] inloc quoted "path/and/filename.ext" of the file to be copied
@param [out] outloc quoted "path/and/filename.ext" of the file to be created
@param [in] inref (____in) If provided, this fileref will take precedence over
the `inloc` parameter
@param [out] outref (____in) If provided, this fileref will take precedence
over the `outloc` parameter. It must already exist!
@param [in] mode (CREATE) Valid values:
@li CREATE - Create the file (even if it already exists)
@li APPEND - Append to the file (don't overwrite)
@param iftrue= (1=1) Supply a condition for which the macro should be executed
@returns nothing
@version 9.2
@@ -19,37 +40,40 @@
**/
%macro mp_binarycopy(
inloc= /* full path and filename of the object to be copied */
inloc= /* full path and filename of the object to be copied */
,outloc= /* full path and filename of object to be created */
,inref=____in /* override default to use own filerefs */
,outref=____out /* override default to use own filerefs */
,mode=CREATE
,iftrue=%str(1=1)
)/*/STORE SOURCE*/;
/* these IN and OUT filerefs can point to anything */
%local mod;
%if not(%eval(%unquote(&iftrue))) %then %return;
%if &mode=APPEND %then %let mod=mod;
/* these IN and OUT filerefs can point to anything */
%if &inref = ____in %then %do;
filename &inref &inloc lrecl=1048576 ;
%end;
%if &outref=____out %then %do;
filename &outref &outloc lrecl=1048576 ;
filename &outref &outloc lrecl=1048576 &mod;
%end;
/* copy the file byte-for-byte */
data _null_;
length filein 8 fileid 8;
filein = fopen("&inref",'I',1,'B');
fileid = fopen("&outref",'O',1,'B');
rec = '20'x;
do while(fread(filein)=0);
rc = fget(filein,rec,1);
rc = fput(fileid, rec);
rc =fwrite(fileid);
end;
rc = fclose(filein);
rc = fclose(fileid);
run;
/* copy the file byte-for-byte */
data _null_;
infile &inref lrecl=1 recfm=n;
file &outref &mod recfm=n;
input sourcechar $char1. @@;
format sourcechar hex2.;
put sourcechar char1. @@;
run;
%if &inref = ____in %then %do;
filename &inref clear;
%end;
%if &outref=____out %then %do;
filename &outref clear;
%end;
%mend;
%mend mp_binarycopy;

194
base/mp_chop.sas Normal file
View File

@@ -0,0 +1,194 @@
/**
@file
@brief Splits a file of ANY SIZE by reference to a search string.
@details Provide a fileref and a search string to chop off part of a file.
Works by reading in the file byte by byte, then marking the beginning and end
of each matched string, before finally doing the chop.
Choose whether to keep the FIRST or the LAST section of the file. Optionally,
use an OFFSET to fix the precise chop point.
Usage:
%let src="%sysfunc(pathname(work))/file.txt";
%let str=Chop here!;
%let out1="%sysfunc(pathname(work))/file1.txt";
%let out2="%sysfunc(pathname(work))/file2.txt";
%let out3="%sysfunc(pathname(work))/file3.txt";
%let out4="%sysfunc(pathname(work))/file4.txt";
data _null_;
file &src;
put "startsection&str.endsection";
run;
%mp_chop(&src, matchvar=str, keep=FIRST, outfile=&out1)
%mp_chop(&src, matchvar=str, keep=LAST, outfile=&out2)
%mp_chop(&src, matchvar=str, keep=FIRST, matchpoint=END, outfile=&out3)
%mp_chop(&src, matchvar=str, keep=LAST, matchpoint=END, outfile=&out4)
filename results (&out1 &out2 &out3 &out4);
data _null_;
infile results;
input;
list;
run;
Results:
@li `startsection`
@li `Chop here!endsection`
@li `startsectionChop here!`
@li `endsection`
For more examples, see mp_chop.test.sas
@param [in] infile The QUOTED path to the file on which to perform the chop
@param [in] matchvar= Macro variable NAME containing the string to split by
@param [in] matchpoint= (START) Valid values:
@li START - chop at the beginning of the string in `matchvar`.
@li END - chop at the end of the string in `matchvar`.
@param [in] offset= (0) An adjustment to the precise chop location, by
by reference to the `matchpoint`. Should be a positive or negative integer.
@param [in] keep= (FIRST) Valid values:
@li FIRST - keep the section of the file before the chop
@li LAST - keep the section of the file after the chop
@param [in] mdebug= (0) Set to 1 to provide macro debugging
@param outfile= (0) Optional QUOTED path to the adjusted output file (avoids
overwriting the first file).
<h4> SAS Macros </h4>
@li mf_getuniquefileref.sas
@li mf_getuniquename.sas
<h4> Related Macros </h4>
@li mp_abort.sas
@li mp_gsubfile.sas
@li mp_replace.sas
@li mp_chop.test.sas
@version 9.4
@author Allan Bowe
**/
%macro mp_chop(infile,
matchvar=,
matchpoint=START,
keep=FIRST,
offset=0,
mdebug=0,
outfile=0
)/*/STORE SOURCE*/;
%local fref0 dttm ds1 outref;
%let fref0=%mf_getuniquefileref();
%let ds1=%mf_getuniquename(prefix=allchars);
%let ds2=%mf_getuniquename(prefix=startmark);
%if &outfile=0 %then %let outfile=&infile;
%mp_abort(iftrue= (%length(%superq(&matchvar))=0)
,mac=mp_chop.sas
,msg=%str(&matchvar is an empty variable)
)
/* START */
%let dttm=%sysfunc(datetime());
filename &fref0 &infile lrecl=1 recfm=n;
/* create dataset with one char per row */
data &ds1;
infile &fref0;
input sourcechar $char1. @@;
format sourcechar hex2.;
run;
/* get start & stop position of first matchvar string (one row, two vars) */
data &ds2;
/* set find string to length in bytes to cover trailing spaces */
length string $ %length(%superq(&matchvar));
string =symget("&matchvar");
drop string;
firstchar=char(string,1);
findlen=lengthm(string); /* <- for trailing bytes */
do _N_=1 to nobs;
set &ds1 nobs=nobs point=_N_;
if sourcechar=firstchar then do;
pos=1;
s=0;
do point=_N_ to min(_N_ + findlen -1,nobs);
set &ds1 point=point;
if sourcechar=char(string, pos) then s + 1;
else goto _leave_;
pos+1;
end;
_leave_:
if s=findlen then do;
START =_N_;
_N_ =_N_+ s - 1;
STOP =_N_;
output;
/* matched! */
stop;
end;
end;
end;
stop;
keep START STOP;
run;
%local split;
%let split=0;
data _null_;
set &ds2;
if "&matchpoint"='START' then do;
if "&keep"='FIRST' then mp=start;
else if "&keep"='LAST' then mp=start-1;
end;
else if "&matchpoint"='END' then do;
if "&keep"='FIRST' then mp=stop+1;
else if "&keep"='LAST' then mp=stop;
end;
split=mp+&offset;
call symputx('split',split,'l');
%if &mdebug=1 %then %do;
put (_all_)(=);
%put &=offset;
%end;
run;
%if &split=0 %then %do;
%put &sysmacroname: No match found in &infile for string %superq(&matchvar);
%return;
%end;
data _null_;
file &outfile recfm=n;
set &ds1;
%if &keep=FIRST %then %do;
if _n_ ge &split then stop;
%end;
%else %do;
if _n_ gt &split;
%end;
put sourcechar char1.;
run;
%if &mdebug=0 %then %do;
filename &fref0 clear;
%end;
%else %do;
data _null_;
infile &outfile lrecl=32767;
input;
list;
if _n_>50 then stop;
run;
%end;
/* END */
%put &sysmacroname took %sysevalf(%sysfunc(datetime())-&dttm) seconds to run;
%mend mp_chop;

View File

@@ -1,27 +1,31 @@
/**
@file mp_cleancsv.sas
@file
@brief Fixes embedded cr / lf / crlf in CSV
@details CSVs will sometimes contain lf or crlf within quotes (eg when
saved by excel). When the termstr is ALSO lf or crlf that can be tricky
to process using SAS defaults.
This macro converts any csv to follow the convention of a windows excel file,
applying CRLF line endings and converting embedded cr and crlf to lf.
saved by excel). When the termstr is ALSO lf or crlf that can be tricky
to process using SAS defaults.
This macro converts any csv to follow the convention of a windows excel file,
applying CRLF line endings and converting embedded cr and crlf to lf.
Usage:
usage:
fileref mycsv "/path/your/csv";
%mp_cleancsv(in=mycsv,out=/path/new.csv)
@param in= provide path or fileref to input csv
@param out= output path or fileref to output csv
@param qchar= quote char - hex code 22 is the double quote.
@param in= (NOTPROVIDED) Provide path or fileref to input csv. If a period is
found, it is assumed to be a file.
@param out= (NOTPROVIDED) Output path or fileref to output csv. If a period
is found, it is assumed to be a file.
@param qchar= ('22'x) Quote char - hex code 22 is the double quote.
@version 9.2
@author Allan Bowe
@cond
**/
%macro mp_cleancsv(in=NOTPROVIDED,out=NOTPROVIDED,qchar='22'x);
%if "&in"="NOTPROVIDED" or "&out"="NOTPROVIDED" %then %do;
%put %str(ERR)OR: Please provide valid input (&in) and output (&out) locations;
%put %str(ERR)OR: Please provide valid input (&in) & output (&out) locations;
%return;
%end;
@@ -30,9 +34,9 @@
%if %index(&out,.) %then %let out="&out";
/**
* convert all cr and crlf within quotes to lf
* convert all other cr or lf to crlf
*/
* convert all cr and crlf within quotes to lf
* convert all other cr or lf to crlf
*/
data _null_;
infile &in recfm=n ;
file &out recfm=n;
@@ -54,9 +58,14 @@
else do;
/* outside a quote, change cr and lf to crlf */
if inchar='0D'x then do;
crblank:
put '0D0A'x;
input inchar $char1.;
if inchar ne '0A'x then do;
if inchar='0D'x then do;
/* multiple CR indicates CR formatted file with blank lines */
goto crblank;
end;
else if inchar ne '0A'x then do;
put inchar $char1.;
if inchar=qchar then isq = mod(isq+1,2);
end;
@@ -65,4 +74,5 @@
else put inchar $char1.;
end;
run;
%mend;
%mend mp_cleancsv;
/** @endcond */

85
base/mp_cntlout.sas Normal file
View File

@@ -0,0 +1,85 @@
/**
@file mp_cntlout.sas
@brief Creates a cntlout dataset in a consistent format
@details The dataset produced by proc format in the cntlout option will vary
according to its contents.
When dealing with formats from an ETL perspective (eg in [Data Controller for
SAS](https://datacontroller.io)), it is important that the output dataset
has a consistent model (and compariable values).
This macro makes use of mddl_sas_cntlout.sas to provide the consistent model,
and will left-align the start and end values when dealing with numeric ranges
to enable consistency when checking for differences.
usage:
%mp_cntlout(libcat=yourlib.cat,cntlout=work.formatexport)
@param [in] libcat The library.catalog reference
@param [in] fmtlist= (0) provide a space separated list of specific formats to
extract
@param [in] iftrue= (1=1) A condition under which the macro should be executed
@param [out] cntlout= (work.fmtextract) Libds reference for the output dataset
<h4> SAS Macros </h4>
@li mddl_sas_cntlout.sas
@li mf_getuniquename.sas
<h4> Related Macros </h4>
@li mf_getvarformat.sas
@li mp_getformats.sas
@li mp_loadformat.sas
@li mp_ds2fmtds.sas
@version 9.2
@author Allan Bowe
@cond
**/
%macro mp_cntlout(
iftrue=(1=1)
,libcat=
,cntlout=work.fmtextract
,fmtlist=0
)/*/STORE SOURCE*/;
%local ddlds cntlds i;
%if not(%eval(%unquote(&iftrue))) %then %return;
%let ddlds=%mf_getuniquename();
%let cntlds=%mf_getuniquename();
%mddl_sas_cntlout(libds=&ddlds)
%if %index(&libcat,-)>0 and %scan(&libcat,2,-)=FC %then %do;
%let libcat=%scan(&libcat,1,-);
%end;
proc format lib=&libcat cntlout=&cntlds;
%if "&fmtlist" ne "0" %then %do;
select
%do i=1 %to %sysfunc(countw(&fmtlist));
%scan(&fmtlist,&i,%str( ))
%end;
;
%end;
run;
data &cntlout;
if 0 then set &ddlds;
set &cntlds;
if type="N" then do;
start=cats(start);
end=cats(end);
end;
run;
proc sort;
by fmtname start;
run;
proc sql;
drop table &ddlds,&cntlds;
%mend mp_cntlout;
/** @endcond */

84
base/mp_copyfolder.sas Normal file
View File

@@ -0,0 +1,84 @@
/**
@file
@brief A macro to recursively copy a directory
@details Performs a recursive directory listing then works from top to bottom
copying files and creating subdirectories.
Usage:
%let rootdir=%sysfunc(pathname(work))/demo;
%let copydir=%sysfunc(pathname(work))/demo_copy;
%mf_mkdir(&rootdir)
%mf_mkdir(&rootdir/subdir)
%mf_mkdir(&rootdir/subdir/subsubdir)
data "&rootdir/subdir/example.sas7bdat";
run;
%mp_copyfolder(&rootdir,&copydir)
@param [in] source Unquoted path to the folder to copy from.
@param [out] target Unquoted path to the folder to copy to.
@param [in] copymax=(MAX) Set to a positive integer to indicate the level of
subdirectory copy recursion - eg 3, to go `./3/levels/deep`. For unlimited
recursion, set to MAX.
<h4> SAS Macros </h4>
@li mf_getuniquename.sas
@li mf_isdir.sas
@li mf_mkdir.sas
@li mp_abort.sas
@li mp_dirlist.sas
<h4> Related Macros </h4>
@li mp_copyfolder.test.sas
**/
%macro mp_copyfolder(source,target,copymax=MAX);
%mp_abort(iftrue=(%mf_isdir(&source)=0)
,mac=&sysmacroname
,msg=%str(Source dir does not exist (&source))
)
%mf_mkdir(&target)
%mp_abort(iftrue=(%mf_isdir(&target)=0)
,mac=&sysmacroname
,msg=%str(Target dir could not be created (&target))
)
/* prep temp table */
%local tempds;
%let tempds=%mf_getuniquename();
/* recursive directory listing */
%mp_dirlist(path=&source,outds=work.&tempds,maxdepth=&copymax)
/* create folders and copy content */
data _null_;
length msg $200;
call missing(msg);
set work.&tempds;
if _n_ = 1 then dpos+sum(length(directory),2);
filepath2="&target/"!!substr(filepath,dpos);
if file_or_folder='folder' then call execute('%mf_mkdir('!!filepath2!!')');
else do;
length fref1 fref2 $8;
rc1=filename(fref1,filepath,'disk','recfm=n');
rc2=filename(fref2,filepath2,'disk','recfm=n');
if fcopy(fref1,fref2) ne 0 then do;
msg=sysmsg();
putlog "%str(ERR)OR: Unable to copy " filepath " to " filepath2;
putlog msg=;
end;
end;
rc=filename(fref1);
rc=filename(fref2);
run;
/* tidy up */
proc sql;
drop table work.&tempds;
%mend mp_copyfolder;

73
base/mp_coretable.sas Normal file
View File

@@ -0,0 +1,73 @@
/**
@file
@brief Create the permanent Core tables
@details Several macros in the [core](https://github.com/sasjs/core) library
make use of permanent tables. To avoid duplication in definitions, this
macro provides a central location for managing the corresponding DDL.
Note - this macro is likely to be deprecated in future in favour of a
dedicated "datamodel" folder (prefix mddl)
Any corresponding data would go in a seperate repo, to avoid this one
ballooning in size!
Example usage:
%mp_coretable(LOCKTABLE,libds=work.locktable)
@param [in] table_ref The type of table to create. Example values:
@li DIFFTABLE
@li FILTER_DETAIL
@li FILTER_SUMMARY
@li LOCKANYTABLE
@li MAXKEYTABLE
@param [in] libds= (0) The library.dataset reference used to create the table.
If not provided, then the DDL is simply printed to the log.
<h4> SAS Macros </h4>
@li mddl_dc_difftable.sas
@li mddl_dc_filterdetail.sas
@li mddl_dc_filtersummary.sas
@li mddl_dc_locktable.sas
@li mddl_dc_maxkeytable.sas
@li mf_getuniquename.sas
<h4> Related Macros </h4>
@li mp_filterstore.sas
@li mp_lockanytable.sas
@li mp_retainedkey.sas
@li mp_storediffs.sas
@li mp_stackdiffs.sas
@version 9.2
@author Allan Bowe
**/
%macro mp_coretable(table_ref,libds=0
)/*/STORE SOURCE*/;
%local outds ;
%let outds=%sysfunc(ifc(&libds=0,%mf_getuniquename(),&libds));
proc sql;
%if &table_ref=DIFFTABLE %then %do;
%mddl_dc_difftable(libds=&outds)
%end;
%else %if &table_ref=LOCKTABLE %then %do;
%mddl_dc_locktable(libds=&outds)
%end;
%else %if &table_ref=FILTER_SUMMARY %then %do;
%mddl_dc_filtersummary(libds=&outds)
%end;
%else %if &table_ref=FILTER_DETAIL %then %do;
%mddl_dc_filterdetail(libds=&outds)
%end;
%else %if &table_ref=MAXKEYTABLE %then %do;
%mddl_dc_maxkeytable(libds=&outds)
%end;
%if &libds=0 %then %do;
proc sql;
describe table &syslast;
drop table &syslast;
%end;
%mend mp_coretable;

View File

@@ -13,16 +13,19 @@
constraint unq unique(tx_from, dd_type),
constraint nnn not null(DD_SHORTDESC)
);
%mp_getconstraints(lib=work,ds=example,outds=work.constraints)
%mp_deleteconstraints(inds=work.constraints,outds=dropped,execute=YES)
%mp_createconstraints(inds=work.constraints,outds=created,execute=YES)
@param inds= The input table containing the constraint info
@param outds= a table containing the create statements (create_statement column)
@param execute= `YES|NO` - default is NO. To actually create, use YES.
@param inds= (work.mp_getconstraints) The input table containing the
constraint info
@param outds= (work.mp_createconstraints) A table containing the create
statements (create_statement column)
@param execute= (NO) To actually create, use YES.
<h4> Dependencies </h4>
<h4> Related Files </h4>
@li mp_getconstraints.sas
@version 9.2
@author Allan Bowe
@@ -30,7 +33,7 @@
**/
%macro mp_createconstraints(inds=mp_getconstraints
,outds=mp_createconstraints
,outds=work.mp_createconstraints
,execute=NO
)/*/STORE SOURCE*/;
@@ -48,7 +51,7 @@ data &outds;
else type=constraint_type;
create_statement=catx(" ","alter table",libref,".",table_name
,"add constraint",constraint_name,type,"(");
if last.constraint_name then
if last.constraint_name then
create_statement=cats(create_statement,column_name,");");
else create_statement=cats(create_statement,column_name,",");
if "&execute"="YES" then call execute(create_statement);
@@ -64,4 +67,4 @@ data &outds;
output;
run;
%mend;
%mend mp_createconstraints;

View File

@@ -1,47 +1,13 @@
/**
@file mp_createwebservice.sas
@brief Create a web service in SAS 9 or Viya
@details Creates a SASJS ready Stored Process in SAS 9 or Job Execution
Service in SAS Viya
Usage:
%* compile macros ;
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc;
%* write some code;
filename ft15f001 temp;
parmcards4;
%* fetch any data from frontend ;
%webout(FETCH)
data example1 example2;
set sashelp.class;
run;
%* send data back;
%webout(OPEN)
%webout(ARR,example1) * Array format, fast, suitable for large tables ;
%webout(OBJ,example2) * Object format, easier to work with ;
%webout(CLOSE)
;;;;
%mp_createwebservice(path=/Public/app/common,name=appInit,code=ft15f001,replace=YES)
<h4> Dependencies </h4>
@li mf_getplatform.sas
@li mm_createwebservice.sas
@li mv_createwebservice.sas
@param path= The full folder path where the service will be created
@param name= Service name. Avoid spaces.
@param desc= The description of the service (optional)
@param precode= Space separated list of filerefs, pointing to the code that
needs to be attached to the beginning of the service (optional)
@param code= Space seperated fileref(s) of the actual code to be added
@param replace= select YES to replace any existing service in that location
@brief Create a web service in SAS 9, Viya or SASjs Server
@details This is actually a wrapper for mx_createwebservice.sas, remaining
for legacy purposes. For new apps, use mx_createwebservice.sas.
@version 9.2
@author Allan Bowe
<h4> SAS Macros </h4>
@li mx_createwebservice.sas
**/
@@ -51,33 +17,16 @@ Usage:
,code=ft15f001
,desc=This service was created by the mp_createwebservice macro
,replace=YES
,mdebug=0
)/*/STORE SOURCE*/;
%if &syscc ge 4 %then %do;
%put syscc=&syscc - &sysmacroname will not execute in this state;
%return;
%end;
%local platform; %let platform=%mf_getplatform();
%if &platform=SASVIYA %then %do;
%if "&path"="HOME" %then %let path=/Users/&sysuserid/My Folder;
%mv_createwebservice(path=&path
%mx_createwebservice(path=&path
,name=&name
,code=&code
,precode=&precode
,code=&code
,desc=&desc
,replace=&replace
,mdebug=&mdebug
)
%end;
%else %do;
%if "&path"="HOME" %then %let path=/User Folders/&sysuserid/My Folder;
%mm_createwebservice(path=&path
,name=&name
,code=&code
,precode=&precode
,desc=&desc
,replace=&replace
)
%end;
%mend;
%mend mp_createwebservice;

140
base/mp_csv2ds.sas Normal file
View File

@@ -0,0 +1,140 @@
/**
@file mp_csv2ds.sas
@brief Efficient import of arbitrary CSV using a dataset as template
@details Used to import relevant columns from a large CSV using
a dataset to provide the types and lengths. Assumes that a header
row is provided, and datarows start on line 2. Extra columns in
both the CSV and base dataset are ignored.
Usage:
filename mycsv temp;
data _null_;
file mycsv;
put 'name,age,nickname';
put 'John,48,Jonny';
put 'Jennifer,23,Jen';
run;
%mp_csv2ds(inref=mycsv,outds=myds,baseds=sashelp.class)
@param inref= fileref to the CSV
@param outds= output ds (lib.ds format)
@param view= Set to YES or NO to determine whether the output should be
a view or not. Default is NO (not a view).
@param baseds= Template dataset on which to create the input statement.
Is used to determine types, lengths, and any informats.
@version 9.2
@author Allan Bowe
<h4> SAS Macros </h4>
@li mp_abort.sas
@li mf_existds.sas
**/
%macro mp_csv2ds(inref=0,outds=0,baseds=0,view=NO);
%mp_abort(iftrue=( &inref=0 )
,mac=&sysmacroname
,msg=%str(the INREF variable must be provided)
)
%mp_abort(iftrue=( %superq(outds)=0 )
,mac=&sysmacroname
,msg=%str(the OUTDS variable must be provided)
)
%mp_abort(iftrue=( &baseds=0 )
,mac=&sysmacroname
,msg=%str(the BASEDS variable must be provided)
)
%mp_abort(iftrue=( %mf_existds(&baseds)=0 )
,mac=&sysmacroname
,msg=%str(the BASEDS dataset (&baseds) needs to be assigned, and to exist)
)
/* count rows */
%local hasheader; %let hasheader=0;
data _null_;
if _N_ > 1 then do;
call symputx('hasheader',1,'l');
stop;
end;
infile &inref;
input;
run;
%mp_abort(iftrue=( &hasheader=0 )
,mac=&sysmacroname
,msg=%str(No header row in &inref)
)
/* get the variables in the CSV */
data _data_;
infile &inref;
input;
length name $32;
do i=1 to countc(_infile_,',')+1;
name=upcase(scan(_infile_,i,','));
output;
end;
stop;
run;
%local csv_vars;%let csv_vars=&syslast;
/* get the variables in the dataset */
proc contents noprint data=&baseds
out=_data_ (keep=name type length format: informat);
run;
%local base_vars; %let base_vars=&syslast;
proc sql undo_policy=none;
create table &csv_vars as
select a.*
,b.type
,b.length
,b.format
,b.formatd
,b.formatl
,b.informat
from &csv_vars a
left join &base_vars b
on a.name=upcase(b.name)
order by i;
/* prepare the input statement */
%local instat dropvars;
data _null_;
set &syslast end=last;
length in dropvars $32767;
retain in dropvars;
if missing(type) then do;
informat='$1.';
dropvars=catx(' ',dropvars,name);
end;
else if missing(informat) then do;
if type=1 then informat='best.';
else informat=cats('$',length,'.');
end;
else informat=cats(informat,'.');
in=catx(' ',in,name,':',informat);
if last then do;
call symputx('instat',in,'l');
call symputx('dropvars',dropvars,'l');
end;
run;
/* import the CSV */
data &outds
%if %upcase(&view)=YES %then %do;
/view=&outds
%end;
;
infile &inref dsd firstobs=2;
input &instat;
%if %length(&dropvars)>0 %then %do;
drop &dropvars;
%end;
run;
%mend mp_csv2ds;

View File

@@ -13,7 +13,7 @@
constraint unq unique(tx_from, dd_type),
constraint nnn not null(DD_SHORTDESC)
);
%mp_getconstraints(lib=work,ds=example,outds=work.constraints)
%mp_deleteconstraints(inds=work.constraints,outds=dropped,execute=YES)
@@ -49,4 +49,4 @@ data &outds;
end;
run;
%mend;
%mend mp_deleteconstraints;

70
base/mp_deletefolder.sas Normal file
View File

@@ -0,0 +1,70 @@
/**
@file
@brief A macro to delete a directory
@details Will delete all folder content (including subfolder content) and
finally, the folder itself.
Usage:
%let rootdir=%sysfunc(pathname(work))/demo;
%mf_mkdir(&rootdir)
%mf_mkdir(&rootdir/subdir)
%mf_mkdir(&rootdir/subdir/subsubdir)
data "&rootdir/subdir/example.sas7bdat";
run;
%mp_deletefolder(&rootdir)
@param path Unquoted path to the folder to delete.
<h4> SAS Macros </h4>
@li mf_getuniquename.sas
@li mf_isdir.sas
@li mp_dirlist.sas
<h4> Related Macros </h4>
@li mp_deletefolder.test.sas
**/
%macro mp_deletefolder(folder);
/* proceed if valid directory */
%if %mf_isdir(&folder)=1 %then %do;
/* prep temp table */
%local tempds;
%let tempds=%mf_getuniquename();
/* recursive directory listing */
%mp_dirlist(path=&folder,outds=work.&tempds, maxdepth=MAX)
/* sort descending level so can delete folder contents before folders */
proc sort data=work.&tempds;
by descending level;
run;
/* ensure top level folder is removed at the end */
proc sql;
insert into work.&tempds set filepath="&folder";
/* delete everything */
data _null_;
set work.&tempds end=last;
length fref $8;
fref='';
rc=filename(fref,filepath);
rc=fdelete(fref);
if rc then do;
msg=sysmsg();
put "&sysmacroname:" / rc= / msg= / filepath=;
end;
rc=filename(fref);
run;
/* tidy up */
proc sql;
drop table work.&tempds;
%end;
%else %put &sysmacroname: &folder: is not a valid / accessible folder. ;
%mend mp_deletefolder;

52
base/mp_dictionary.sas Normal file
View File

@@ -0,0 +1,52 @@
/**
@file mp_dictionary.sas
@brief Creates a portal (libref) into the SQL Dictionary Views
@details Provide a libref and the macro will create a series of views against
each view in the special PROC SQL dictionary libref.
This is useful if you would like to visualise (navigate) the views in a SAS
client such as Base SAS, Enterprise Guide, or Studio (or [Data Controller](
https://datacontroller.io)).
It works by extracting the dictionary.dictionaries view into
YOURLIB.dictionaries, then uses that to create a YOURLIB.{viewName} for every
other dictionary.view, eg:
proc sql;
create view YOURLIB.columns as select * from dictionary.columns;
Usage:
libname demo "/lib/directory";
%mp_dictionary(lib=demo)
Or, to just create them in WORK:
%mp_dictionary()
If you'd just like to browse the dictionary data model, you can also check
out [this article](https://rawsas.com/dictionary-of-dictionaries/).
![](https://user-images.githubusercontent.com/4420615/188278365-2987db97-0594-4a39-ac81-dbacdef5cdc8.png)
@param lib= (WORK) The libref in which to create the views
<h4> Related Files </h4>
@li mp_dictionary.test.sas
@version 9.2
@author Allan Bowe
**/
%macro mp_dictionary(lib=WORK)/*/STORE SOURCE*/;
%local list i mem;
proc sql noprint;
create view &lib..dictionaries as select * from dictionary.dictionaries;
select distinct memname into: list separated by ' ' from &lib..dictionaries;
%do i=1 %to %sysfunc(countw(&list,%str( )));
%let mem=%scan(&list,&i,%str( ));
create view &lib..&mem as select * from dictionary.&mem;
%end;
quit;
%mend mp_dictionary;

View File

@@ -1,69 +1,118 @@
/**
@file
@brief Returns all files and subdirectories within a specified parent
@details When used with getattrs=NO, is not OS specific (uses dopen / dread).
If getattrs=YES then the doptname / foptname functions are used to scan all
properties - any characters that are not valid in a SAS name (v7) are simply
stripped, and the table is transposed so theat each property is a column
and there is one file per row. An attempt is made to get all properties
whether a file or folder, but some files/folders cannot be accessed, and so
not all properties can / will be populated.
@details When used with getattrs=NO, is not OS specific (uses dopen / dread).
Credit for the rename approach:
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
https://communities.sas.com/t5/SAS-Programming/SAS-Function-to-convert-string-to-Legal-SAS-Name/m-p/27375/highlight/true#M5003
Usage:
usage:
%mp_dirlist(path=/some/location,outds=myTable)
%mp_dirlist(path=/some/location, outds=myTable, maxdepth=MAX)
%mp_dirlist(outds=cwdfileprops, getattrs=YES)
@warning In a Unix environment, the existence of a named pipe will cause this
%mp_dirlist(fref=MYFREF)
@warning In a Unix environment, the existence of a named pipe will cause this
macro to hang. Therefore this tool should be used with caution in a SAS 9 web
application, as it can use up all available multibridge sessions if requests
are resubmitted.
If anyone finds a way to positively identify a named pipe using SAS (without
If anyone finds a way to positively identify a named pipe using SAS (without
X CMD) do please raise an issue!
@param path= for which to return contents
@param outds= the output dataset to create
@param getattrs= YES/NO (default=NO). Uses doptname and foptname to return
all attributes for each file / folder.
@param [in] path= (%sysfunc(pathname(work))) Path for which to return contents
@param [in] fref= (0) Provide a DISK engine fileref as an alternative to PATH
@param [in] maxdepth= (0) Set to a positive integer to indicate the level of
subdirectory scan recursion - eg 3, to go `./3/levels/deep`. For unlimited
recursion, set to MAX.
@param [in] showparent= (NO) By default, the initial parent directory is not
part of the results. Set to YES to include it. For this record only,
directory=filepath.
@param [out] outds= (work.mp_dirlist) The output dataset to create
@param [out] getattrs= (NO) If getattrs=YES then the doptname / foptname
functions are used to scan all properties - any characters that are not
valid in a SAS name (v7) are simply stripped, and the table is transposed
so theat each property is a column and there is one file per row. An
attempt is made to get all properties whether a file or folder, but some
files/folders cannot be accessed, and so not all properties can / will be
populated.
@returns outds contains the following variables:
- file_or_folder (file / folder)
- filepath (path/to/file.name)
- filename (just the file name)
- ext (.extension)
- msg (system message if any issues)
- OS SPECIFIC variables, if <code>getattrs=</code> is used.
- directory (containing folder)
- file_or_folder (file / folder)
- filepath (path/to/file.name)
- filename (just the file name)
- ext (.extension)
- msg (system message if any issues)
- level (depth of folder)
- OS SPECIFIC variables, if <code>getattrs=</code> is used.
<h4> SAS Macros </h4>
@li mf_existds.sas
@li mf_getvarlist.sas
@li mf_wordsinstr1butnotstr2.sas
@li mp_dropmembers.sas
<h4> Related Macros </h4>
@li mp_dirlist.test.sas
@version 9.2
@author Allan Bowe
**/
%macro mp_dirlist(path=%sysfunc(pathname(work))
, fref=0
, outds=work.mp_dirlist
, getattrs=NO
, showparent=NO
, maxdepth=0
, level=0 /* The level of recursion to perform. For internal use only. */
)/*/STORE SOURCE*/;
%let getattrs=%upcase(&getattrs)XX;
data &outds (compress=no keep=file_or_folder filepath filename ext msg);
length filepath $500 fref fref2 $8 file_or_folder $6 filename $80 ext $20 msg $200;
rc = filename(fref, "&path");
/* temp table */
%local out_ds;
data;run;
%let out_ds=%str(&syslast);
/* drop main (top) table if it exists */
%if &level=0 %then %do;
%mp_dropmembers(%scan(&outds,-1,.), libref=WORK)
%end;
data &out_ds(compress=no
keep=file_or_folder filepath filename ext msg directory level
);
length directory filepath $500 fref fref2 $8 file_or_folder $6 filename $80
ext $20 msg $200 foption $16;
if _n_=1 then call missing(of _all_);
retain level &level;
%if &fref=0 %then %do;
rc = filename(fref, "&path");
%end;
%else %do;
fref="&fref";
rc=0;
%end;
if rc = 0 then do;
did = dopen(fref);
if did=0 then do;
putlog "NOTE: This directory is empty - &path";
msg=sysmsg();
put _all_;
stop;
end;
rc = filename(fref);
did = dopen(fref);
if did=0 then do;
putlog "NOTE: This directory is empty, or does not exist - &path";
msg=sysmsg();
put msg;
put _all_;
stop;
end;
/* attribute is OS-dependent - could be "Directory" or "Directory Name" */
numopts=doptnum(did);
do i=1 to numopts;
foption=doptname(did,i);
if foption=:'Directory' then i=numopts;
end;
directory=dinfo(did,foption);
rc = filename(fref);
end;
else do;
msg=sysmsg();
@@ -73,7 +122,8 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg);
dnum = dnum(did);
do i = 1 to dnum;
filename = dread(did, i);
rc = filename(fref2, "&path/"!!filename);
filepath=cats(directory,'/',filename);
rc = filename(fref2,filepath);
midd=dopen(fref2);
dmsg=sysmsg();
if did > 0 then file_or_folder='folder';
@@ -82,12 +132,12 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg);
fmsg=sysmsg();
if midf > 0 then file_or_folder='file';
rc=fclose(midf);
if index(fmsg,'File is in use') or index(dmsg,'is not a directory')
if index(fmsg,'File is in use') or index(dmsg,'is not a directory')
then file_or_folder='file';
else if index(fmsg, 'Insufficient authorization') then file_or_folder='file';
else if index(fmsg,'Insufficient authorization') then file_or_folder='file';
else if file_or_folder='' then file_or_folder='locked';
if file_or_folder='file' then do;
ext = prxchange('s/.*\.{1,1}(.*)/$1/', 1, filename);
if filename = ext then ext = ' ';
@@ -96,17 +146,26 @@ data &outds (compress=no keep=file_or_folder filepath filename ext msg);
ext='';
file_or_folder='folder';
end;
filepath="&path/"!!filename;
output;
end;
rc = dclose(did);
%if &showparent=YES and &level=0 %then %do;
filepath=directory;
file_or_folder='folder';
ext='';
filename=scan(directory,-1,'/\');
msg='';
level=&level;
output;
%end;
stop;
run;
%if %substr(&getattrs,1,1)=Y %then %do;
data &outds;
set &outds;
data &out_ds;
set &out_ds;
length infoname infoval $60 fref $8;
if _n_=1 then call missing(fref);
rc=filename(fref,filepath);
drop rc infoname fid i close fref;
if file_or_folder='file' then do;
@@ -120,7 +179,7 @@ run;
else do i=1 to foptnum(fid);
infoname=foptname(fid,i);
infoval=finfo(fid,infoname);
sasname=compress(infoname, '_', 'adik');
sasname=compress(infoname, '_', 'adik');
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
if upcase(sasname) ne 'FILENAME' then output;
end;
@@ -137,7 +196,7 @@ run;
else do i=1 to doptnum(fid);
infoname=doptname(fid,i);
infoval=dinfo(fid,infoname);
sasname=compress(infoname, '_', 'adik');
sasname=compress(infoname, '_', 'adik');
if anydigit(sasname)=1 then sasname=substr(sasname,anyalpha(sasname));
if upcase(sasname) ne 'FILENAME' then output;
end;
@@ -146,10 +205,59 @@ run;
run;
proc sort;
by filepath sasname;
proc transpose data=&outds out=&outds(drop=_:);
proc transpose data=&out_ds out=&out_ds(drop=_:);
id sasname;
var infoval;
by filepath file_or_folder filename ext ;
run;
%end;
%mend;
data &out_ds;
set &out_ds(where=(filepath ne ''));
run;
/**
* The above transpose can mean that some updates create additional columns.
* This necessitates the occasional use of datastep over proc append.
*/
%if %mf_existds(&outds) %then %do;
%local basevars appvars newvars;
%let basevars=%mf_getvarlist(&outds);
%let appvars=%mf_getvarlist(&out_ds);
%let newvars=%length(%mf_wordsinstr1butnotstr2(Str1=&appvars,Str2=&basevars));
%if &newvars>0 %then %do;
data &outds;
set &outds &out_ds;
run;
%end;
%else %do;
proc append base=&outds data=&out_ds force nowarn;
run;
%end;
%end;
%else %do;
proc append base=&outds data=&out_ds;
run;
%end;
/* recursive call */
%if &maxdepth>&level or &maxdepth=MAX %then %do;
data _null_;
set &out_ds;
where file_or_folder='folder';
%if &showparent=YES and &level=0 %then %do;
if filepath ne directory;
%end;
length code $10000;
code=cats('%nrstr(%mp_dirlist(path=',filepath,",outds=&outds"
,",getattrs=&getattrs,level=%eval(&level+1),maxdepth=&maxdepth))");
put code=;
call execute(code);
run;
%end;
/* tidy up */
proc sql;
drop table &out_ds;
%mend mp_dirlist;

View File

@@ -19,7 +19,7 @@
**/
%macro mp_distinctfmtvalues(
libds=
libds=
,var=
,outvar=formatted_value
,outds=work.mp_distinctfmtvalues
@@ -34,7 +34,7 @@
create table &outds as
select distinct
%if &vtype=C & %trim(&fmt)=%str() %then %do;
&var
&var
%end;
%else %if &vtype=C %then %do;
put(&var,&fmt)
@@ -45,6 +45,6 @@
%else %do;
put(&var,&fmt)
%end;
as &outvar length=&varlen
as &outvar length=&varlen
from &libds;
%mend;
%mend mp_distinctfmtvalues;

View File

@@ -1,20 +1,25 @@
/**
@file
@brief Drops tables / views (if they exist) without warnings in the log
@details
@details Useful for dropping tables when you're not sure they exist, or if
you are not sure whether they are a dataset or view. Also efficient for
dropping multiple tables / views.
Example usage:
proc sql;
create table data1 as select * from sashelp.class;
create view view2 as select * from sashelp.class;
%mp_dropmembers(list=data1 view2)
%mp_dropmembers(data1 view2, libref=WORK)
<h4> Dependencies </h4>
<h4> SAS Macros </h4>
@li mf_isblank.sas
@param list space separated list of datasets / views
@param libref= can only drop from a single library at a time
@param [in] list space separated list of datasets / views, WITHOUT libref
@param [in] libref= (WORK) Note - you can only drop from one library at a time
@param [in] iftrue= (1=1) Conditionally drop tables, eg if &debug=N
@version 9.2
@author Allan Bowe
@@ -22,10 +27,13 @@
**/
%macro mp_dropmembers(
list /* space separated list of datasets / views */
list /* space separated list of datasets / views */
,libref=WORK /* can only drop from a single library at a time */
,iftrue=%str(1=1)
)/*/STORE SOURCE*/;
%if not(%eval(%unquote(&iftrue))) %then %return;
%if %mf_isblank(&list) %then %do;
%put NOTE: nothing to drop!;
%return;
@@ -35,4 +43,4 @@
delete &list;
delete &list /mtype=view;
run;
%mend;
%mend mp_dropmembers;

View File

@@ -2,67 +2,95 @@
@file
@brief Create a CARDS file from a SAS dataset.
@details Uses dataset attributes to convert all data into datalines.
Running the generated file will rebuild the original dataset.
usage:
Running the generated file will rebuild the original dataset. Includes
support for large decimals, binary data, PROCESSED_DTTM columns, and
alternative encoding. If the input dataset is empty, the cards file will
still be created.
%mp_ds2cards(base_ds=sashelp.class
Additional support to generate a random sample and max rows.
Usage:
%mp_ds2cards(sashelp.class
, tgt_ds=work.class
, cards_file= "C:\temp\class.sas"
, maxobs=5)
, showlog=NO
, maxobs=5
)
stuff to add
- labelling the dataset
- explicity setting a unix LF
- constraints / indexes etc
TODO:
- labelling the dataset
- explicity setting a unix LF
- constraints / indexes etc
@param base_ds= Should be two level - eg work.blah. This is the table that
is converted to a cards file.
@param tgt_ds= Table that the generated cards file would create. Optional -
if omitted, will be same as BASE_DS.
@param cards_file= Location in which to write the (.sas) cards file
@param maxobs= to limit output to the first <code>maxobs</code> observations
@param showlog= whether to show generated cards file in the SAS log (YES/NO)
@param outencoding= provide encoding value for file statement (eg utf-8)
@param [in] base_ds Should be two level - eg work.blah. This is the table
that is converted to a cards file.
@param [in] tgt_ds= Table that the generated cards file would create.
Optional - if omitted, will be same as BASE_DS.
@param [out] cards_file= ("%sysfunc(pathname(work))/cardgen.sas") Location in
which to write the (.sas) cards file
@param [in] maxobs= (max) To limit output to the first <code>maxobs</code>
observations, enter an integer here.
@param [in] random_sample= (NO) Set to YES to generate a random sample of
data. Can be quite slow.
@param [in] showlog= (YES) Whether to show generated cards file in the SAS
log. Valid values:
@li YES
@li NO
@param [in] outencoding= Provide encoding value for file statement (eg utf-8)
@param [in] append= (NO) If NO then will rebuild the cards file if it already
exists, otherwise will append to it. Used by the mp_lib2cards.sas macro.
<h4> Related Macros </h4>
@li mp_lib2cards.sas
@li mp_ds2inserts.sas
@li mp_mdtablewrite.sas
@version 9.2
@author Allan Bowe
@cond
**/
%macro mp_ds2cards(base_ds=, tgt_ds=
%macro mp_ds2cards(base_ds, tgt_ds=
,cards_file="%sysfunc(pathname(work))/cardgen.sas"
,maxobs=max
,random_sample=NO
,showlog=YES
,outencoding=
,append=NO
)/*/STORE SOURCE*/;
%local i setds nvars;
%if not %sysfunc(exist(&base_ds)) %then %do;
%put WARNING: &base_ds does not exist;
%return;
%put %str(WARN)ING: &base_ds does not exist;
%return;
%end;
%if %index(&base_ds,.)=0 %then %let base_ds=WORK.&base_ds;
%if (&tgt_ds = ) %then %let tgt_ds=&base_ds;
%if %index(&tgt_ds,.)=0 %then %let tgt_ds=WORK.%scan(&base_ds,2,.);
%if ("&outencoding" ne "") %then %let outencoding=encoding="&outencoding";
%if ("&append" = "" or "&append" = "NO") %then %let append=;
%else %let append=mod;
/* get varcount */
%let nvars=0;
proc sql noprint;
select count(*) into: nvars from dictionary.columns
where libname="%scan(%upcase(&base_ds),1)"
and memname="%scan(%upcase(&base_ds),2)";
where upcase(libname)="%scan(%upcase(&base_ds),1)"
and upcase(memname)="%scan(%upcase(&base_ds),2)";
%if &nvars=0 %then %do;
%put WARNING: Dataset &base_ds has no variables! It will not be converted.;
%put %str(WARN)ING: Dataset &base_ds has no variables, will not be converted.;
%return;
%end;
/* get indexes */
proc sort data=sashelp.vindex
(where=(upcase(libname)="%scan(%upcase(&base_ds),1)"
and upcase(memname)="%scan(%upcase(&base_ds),2)"))
out=_data_;
proc sort
data=sashelp.vindex(
where=(upcase(libname)="%scan(%upcase(&base_ds),1)"
and upcase(memname)="%scan(%upcase(&base_ds),2)")
)
out=_data_;
by indxname indxpos;
run;
@@ -77,7 +105,7 @@ data _null_;
idxcnt+1;
nom='';
uni='';
vars=name;
vars=name;
end;
else vars=catx(' ',vars,name);
if last.indxname then do;
@@ -103,18 +131,18 @@ proc sql
order by ranuni(42)
%end;
;
reset outobs=max;
create table datalines1 as
select name,type,length,varnum,format,label from dictionary.columns
where libname="%upcase(%scan(&base_ds,1))"
and memname="%upcase(%scan(&base_ds,2))";
select name,type,length,varnum,format,label from dictionary.columns
where upcase(libname)="%upcase(%scan(&base_ds,1))"
and upcase(memname)="%upcase(%scan(&base_ds,2))";
/**
Due to long decimals cannot use best. format
So - use bestd. format and then use character functions to strip trailing
zeros, if NOT an integer!!
resolved code = ifc(int(VARIABLE)=VARIABLE
zeros, if NOT an integer or missing!! Cannot use int() as it upsets
note2err when there are missings.
resolved code = ifc( mod(coalesce(VARIABLE,0),1)=0
,put(VARIABLE,best32.)
,substrn(put(VARIABLE,bestd32.),1
,findc(put(VARIABLE,bestd32.),'0','TBK')));
@@ -122,23 +150,34 @@ create table datalines1 as
data datalines_2;
format dataline $32000.;
set datalines1 (where=(upcase(name) not in
set datalines1 (where=(upcase(name) not in
('PROCESSED_DTTM','VALID_FROM_DTTM','VALID_TO_DTTM')));
if type='num' then dataline=
cats('ifc(int(',name,')=',name,'
cats('ifc(mod(coalesce(',name,',0),1)=0
,put(',name,',best32.-l)
,substrn(put(',name,',bestd32.-l),1
,findc(put(',name,',bestd32.-l),"0","TBK")))');
else dataline=name;
/**
* binary data must be converted, to store in text format. It is identified
* by the presence of the $HEX keyword in the format.
*/
else if upcase(format)=:'$HEX' then
dataline=cats('put(trim(',name,'),',format,')');
/**
* There is no easy way to store line breaks in a cards file.
* To discuss this, use: https://github.com/sasjs/core/issues/80
* Removing all nonprintables with kw (keep writeable)
*/
else dataline=cats('compress(',name,', ,"kw")');
run;
proc sql noprint;
select dataline into: datalines separated by ',' from datalines_2;
%local
process_dttm_flg
valid_from_dttm_flg
valid_to_dttm_flg
process_dttm_flg
valid_from_dttm_flg
valid_to_dttm_flg
;
%let process_dttm_flg = N;
%let valid_from_dttm_flg = N;
@@ -154,7 +193,8 @@ data _null_;
/* Build input statement */
if type='char' then type3=':$char.';
if upcase(format)=:'$HEX' then type3=':'!!format;
else if type='char' then type3=':$char.';
str2=put(name,$33.)||type3;
@@ -173,14 +213,16 @@ data _null_;
run;
data _null_;
file &cards_file. &outencoding lrecl=32767 termstr=nl;
file &cards_file. &outencoding lrecl=32767 termstr=nl &append;
length __attrib $32767;
if _n_=1 then do;
put '/*******************************************************************';
put " Datalines for %upcase(%scan(&base_ds,2)) dataset ";
put " Generated by %nrstr(%%)mp_ds2cards()";
put " Available on github.com/sasjs/core";
put '********************************************************************/';
put '/**';
put ' @file';
put " @brief Datalines for %upcase(%scan(&base_ds,2)) dataset";
put " @details Generated by %nrstr(%%)mp_ds2cards()";
put " Source: https://github.com/sasjs/core";
put ' @cond ';
put '**/';
put "data &tgt_ds &indexes;";
put "attrib ";
%do i = 1 %to &nvars;
@@ -204,14 +246,15 @@ data _null_;
put 'run;';
end;
else do;
put "infile cards dsd delimiter=',';";
put "infile cards dsd;";
put "input ";
%do i = 1 %to &nvars.;
%if(%length(&&input_stmt_&i..)) %then
put " &&input_stmt_&i..";
put " &&input_stmt_&i..";
;
%end;
put ";";
put 'missing a b c d e f g h i j k l m n o p q r s t u v w x y z _;';
put "datalines4;";
end;
end;
@@ -224,6 +267,7 @@ data _null_;
if __lastobs then do;
put ';;;;';
put 'run;';
put '/** @endcond **/';
stop;
end;
run;
@@ -243,4 +287,5 @@ quit;
%put NOTE-;%put NOTE-;
%put NOTE- %sysfunc(dequote(&cards_file.));
%put NOTE-;%put NOTE-;
%mend;
%mend mp_ds2cards;
/** @endcond **/

Some files were not shown because too many files have changed in this diff Show More