1
0
mirror of https://github.com/sasjs/core.git synced 2026-01-09 10:20:06 +00:00

Compare commits

..

34 Commits

Author SHA1 Message Date
Allan Bowe
5da97295ff Merge pull request #330 from sasjs/issue329
fix: closes #329 by handling the case of unlocking a table that was n…
2023-02-16 14:35:29 +00:00
munja
dc556bdef0 fix: closes #329 by handling the case of unlocking a table that was never locked in mp_lockanytable.sas, also created a corresponding test plus an extra test to check for scope leakage. all.sas was regenerated. 2023-02-16 14:33:53 +00:00
Allan Bowe
111731bf35 Merge pull request #328 from sasjs/all-contributors/add-henrik-forsell
docs: add henrik-forsell as a contributor for doc
2023-02-15 09:32:09 +00:00
allcontributors[bot]
2c526cf9dd docs: update .all-contributorsrc [skip ci] 2023-02-15 09:31:52 +00:00
allcontributors[bot]
660e02193f docs: update README.md [skip ci] 2023-02-15 09:31:51 +00:00
Allan Bowe
00b4dee86e Merge pull request #327 from henrik-forsell/doc-fix
Changed documentation wording (Column to Dataset)
2023-02-15 09:28:50 +00:00
Henrik Forsell
3913825c22 Changed documentation wording (Column to Dataset) 2023-02-15 15:57:11 +13:00
Allan Bowe
0f143d603b Merge pull request #326 from sasjs/325-error-the-keyword-parameter-maxobs-was-not-defined-with-the-macro
fix: closes #325 by including maxobs param
2023-02-13 14:05:36 +00:00
munja
f1d5fa2c0a fix: closes #325 by including maxobs param 2023-02-13 14:01:43 +00:00
Allan Bowe
a88689428f fix: updating cycjimmy/semantic-release-action to v3 2023-01-25 12:56:38 +00:00
munja
8843fa8bfc fix: adding nrstr() wrapper in mm_adduser2group 2023-01-25 12:53:10 +00:00
Allan Bowe
22d046cf5c Merge pull request #324 from sasjs/servertestfixes
fix: updating ms_runstp and ms_testservice macros to cater for latest…
2023-01-06 13:15:11 +01:00
munja
29e3eb34aa fix: updating ms_runstp and ms_testservice macros to cater for latest response JSON formats in sasjs/server 2023-01-06 12:13:36 +00:00
munja
1af52a6683 fix: adding des= macro option to mf_abort 2023-01-02 11:26:21 +00:00
munja
fc0c96dd94 chore: merge 2022-12-30 12:41:08 +00:00
munja
b9c4882553 fix: linting issues 2022-12-30 12:38:34 +00:00
Allan Bowe
011b2b185c chore: removing broken badges in README 2022-12-28 20:25:05 +00:00
Allan Bowe
dbc23550ac Merge pull request #323 from sasjs/ms_getgroups
fix: increasing desc length to 256 in ms_getgroups
2022-12-28 21:21:35 +01:00
munja
8910840ccc fix: increasing desc length to 256 in ms_getgroups 2022-12-28 20:17:08 +00:00
Allan Bowe
4ef571032d Merge pull request #322 from sasjs/upds
Upds
2022-12-14 14:21:20 +01:00
Allan Bowe
e01cd8cd16 Merge branch 'main' into upds 2022-12-14 14:20:51 +01:00
munja
00628ec78a chore: updating lint settings, some line ending issues, and a sasjsconfig apploc fix 2022-12-14 14:19:28 +01:00
munja
f4e6a487f3 fix: removing redundant param in mS/M_webout macros 2022-12-14 14:17:06 +01:00
Allan Bowe
b7afecdf81 fix: escaping syswarningtext and syserrortext in mp_abort 2022-12-04 21:14:10 +00:00
Allan Bowe
19eb348f0e fix: else case for issue #320 2022-12-04 18:59:31 +00:00
Allan Bowe
f420ac2abf Merge pull request #321 from sasjs/issue320
fix: full escaping of syswarningtext and syserrortext. Closes #320
2022-12-04 18:22:52 +00:00
Allan Bowe
7edec1ad8a fix: full escaping of syswarningtext and syserrortext. Closes #320 2022-12-04 18:18:15 +00:00
Allan Bowe
62d7bce249 feat: adding nobs limit to mp_gitlog 2022-12-04 17:23:53 +00:00
munja
fe6c9a793b chore: fixing saspac build 2022-11-30 22:21:58 +01:00
Allan Bowe
8e13943356 Merge pull request #319 from sasjs/gitbranch
3 new macros (and tests) for the core library
2022-11-30 20:43:54 +00:00
munja
04df9600e0 chore: updating all.sas 2022-11-30 21:43:28 +01:00
munja
e2b0aabfa4 feat: mp_gitlog and associated test/docs 2022-11-30 21:35:49 +01:00
munja
c52a623630 feat: new mf_getgitbranch macro (and test) 2022-11-30 20:15:10 +01:00
munja
cf348e8016 feat: new mf_readfile macro (and test) 2022-11-30 20:06:11 +01:00
40 changed files with 2035 additions and 594 deletions

View File

@@ -135,6 +135,15 @@
"contributions": [ "contributions": [
"code" "code"
] ]
},
{
"login": "henrik-forsell",
"name": "Henrik Forsell",
"avatar_url": "https://avatars.githubusercontent.com/u/109935936?v=4",
"profile": "https://github.com/henrik-forsell",
"contributions": [
"doc"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

View File

@@ -15,7 +15,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Semantic Release - name: Semantic Release
uses: cycjimmy/semantic-release-action@v2 uses: cycjimmy/semantic-release-action@v3
env: env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -23,6 +23,6 @@ jobs:
run: | run: |
npx @sasjs/cli compile job -s sasjs/utils/create_sas_package.sas -o sasjsbuild npx @sasjs/cli compile job -s sasjs/utils/create_sas_package.sas -o sasjsbuild
# this part depends on https://github.com/sasjs/server/issues/307 # this part depends on https://github.com/sasjs/server/issues/307
# sasjs run sasjsbuild/makepak.sas -t sas9 # sasjs run sasjsbuild/jobs/utils/create_sas_package.sas -t sas9

2
.gitignore vendored
View File

@@ -11,3 +11,5 @@ mc_*
# ignore .env files as they can contain sasjs access tokens # ignore .env files as they can contain sasjs access tokens
*.env* *.env*
~

View File

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

View File

@@ -6,5 +6,7 @@
"editor.rulers": [ "editor.rulers": [
80 80
], ],
"files.trimTrailingWhitespace": true "files.trimTrailingWhitespace": true,
"sasjs-for-vscode.target": "docsonly",
"sasjs-for-vscode.isLocal": true
} }

View File

@@ -2,8 +2,6 @@
[![npm package][npm-image]][npm-url] [![npm package][npm-image]][npm-url]
[![Github Workflow][githubworkflow-image]][githubworkflow-url] [![Github Workflow][githubworkflow-image]][githubworkflow-url]
![npm](https://img.shields.io/npm/dt/@sasjs/core) ![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 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 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) [![GitHub issues](https://img.shields.io/github/issues-raw/sasjs/core)](https://github.com/sasjs/core/issues)
@@ -248,7 +246,7 @@ The following repositories are also worth checking out:
## Contributors ✨ ## Contributors ✨
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --> <!-- 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](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END --> <!-- ALL-CONTRIBUTORS-BADGE:END -->
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
@@ -256,22 +254,25 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
<!-- markdownlint-disable --> <!-- markdownlint-disable -->
<table> <table>
<tr> <tbody>
<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> <tr>
<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" valign="top" width="14.28%"><a href="https://github.com/allanbowe"><img src="https://avatars.githubusercontent.com/u/4420615?v=4?s=100" width="100px;" alt="Allan Bowe"/><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/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" valign="top" width="14.28%"><a href="https://github.com/rafgag"><img src="https://avatars.githubusercontent.com/u/69139928?v=4?s=100" width="100px;" alt="rafgag"/><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://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" valign="top" width="14.28%"><a href="https://github.com/tmoody"><img src="https://avatars.githubusercontent.com/u/79837106?v=4?s=100" width="100px;" alt="Trevor Moody"/><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://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" valign="top" width="14.28%"><a href="https://krishna-acondy.io/"><img src="https://avatars.githubusercontent.com/u/2980428?v=4?s=100" width="100px;" alt="Krishna Acondy"/><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://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" valign="top" width="14.28%"><a href="https://github.com/saadjutt01"><img src="https://avatars.githubusercontent.com/u/8914650?v=4?s=100" width="100px;" alt="Muhammad Saad "/><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://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> <td align="center" valign="top" width="14.28%"><a href="https://www.erudicat.com/"><img src="https://avatars.githubusercontent.com/u/25773492?v=4?s=100" width="100px;" alt="Yury Shkoda"/><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>
</tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/medjedovicm"><img src="https://avatars.githubusercontent.com/u/18329105?v=4?s=100" width="100px;" alt="Mihajlo Medjedovic"/><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> <tr>
<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" valign="top" width="14.28%"><a href="https://github.com/kkchandok"><img src="https://avatars.githubusercontent.com/u/46090627?v=4?s=100" width="100px;" alt="kkchandok"/><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/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" valign="top" width="14.28%"><a href="https://github.com/VladislavParhomchik"><img src="https://avatars.githubusercontent.com/u/83717836?v=4?s=100" width="100px;" alt="Vladislav Parhomchik"/><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/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" valign="top" width="14.28%"><a href="https://github.com/vznesh"><img src="https://avatars.githubusercontent.com/u/28916792?v=4?s=100" width="100px;" alt="Vignesh T."/><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://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> <td align="center" valign="top" width="14.28%"><a href="https://github.com/yabwon"><img src="https://avatars.githubusercontent.com/u/9314894?v=4?s=100" width="100px;" alt="Bart Jablonski"/><br /><sub><b>Bart Jablonski</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=yabwon" title="Code">💻</a></td>
</tr> <td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=eltociear" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/henrik-forsell"><img src="https://avatars.githubusercontent.com/u/109935936?v=4?s=100" width="100px;" alt="Henrik Forsell"/><br /><sub><b>Henrik Forsell</b></sub></a><br /><a href="https://github.com/sasjs/core/commits?author=henrik-forsell" title="Documentation">📖</a></td>
</tr>
</tbody>
</table> </table>
<!-- markdownlint-restore --> <!-- markdownlint-restore -->

595
all.sas
View File

@@ -30,7 +30,7 @@ options noquotelenmax;
**/ **/
%macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1) %macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1)
)/*/STORE SOURCE*/; )/des='ungraceful abort' /*STORE SOURCE*/;
%if not(%eval(%unquote(&iftrue))) %then %return; %if not(%eval(%unquote(&iftrue))) %then %return;
@@ -42,7 +42,8 @@ options noquotelenmax;
%mend mf_abort; %mend mf_abort;
/** @endcond *//** /** @endcond */
/**
@file @file
@brief de-duplicates a macro string @brief de-duplicates a macro string
@details Removes all duplicates from a string of words. A delimeter can be @details Removes all duplicates from a string of words. A delimeter can be
@@ -247,7 +248,8 @@ options noquotelenmax;
0 0
%end; %end;
%mend mf_existfileref;/** %mend mf_existfileref;
/**
@file @file
@brief Checks if a function exists @brief Checks if a function exists
@details Returns 1 if the function exists, else 0. Note that this function @details Returns 1 if the function exists, else 0. Note that this function
@@ -781,6 +783,43 @@ or %index(&pgm,/tests/testteardown)
/* send them out without spaces or quote markers */ /* send them out without spaces or quote markers */
%do;%unquote(%upcase(&fmt))%end; %do;%unquote(%upcase(&fmt))%end;
%mend mf_getfmtname;/** %mend mf_getfmtname;/**
@file
@brief Retrieves the current branch from a local GIT repo
@details In a local git repository, the current branch is always available in
the `.git/HEAD` file in a format like this: `ref: refs/heads/master`
This macro simply reads the file and returns the last word (eg `master`).
Example usage:
%let gitdir=%sysfunc(pathname(work))/core;
%let repo=https://github.com/sasjs/core;
%put source clone rc=%sysfunc(GITFN_CLONE(&repo,&gitdir));
%put The current branch is %mf_getgitbranch(&gitdir);
@param [in] gitdir The directory containing the GIT repository
<h4> SAS Macros </h4>
@li mf_readfile.sas
<h4> Related Macros </h4>
@li mp_gitadd.sas
@li mp_gitlog.sas
@li mp_gitreleaseinfo.sas
@li mp_gitstatus.sas
@version 9.2
@author Allan Bowe
**/
%macro mf_getgitbranch(gitdir
)/*/STORE SOURCE*/;
%scan(%mf_readfile(&gitdir/.git/HEAD),-1)
%mend mf_getgitbranch;
/**
@file @file
@brief retrieves a key value pair from a control dataset @brief retrieves a key value pair from a control dataset
@details By default, control dataset is work.mp_setkeyvalue. Usage: @details By default, control dataset is work.mp_setkeyvalue. Usage:
@@ -1902,6 +1941,69 @@ Usage:
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%mf_getattrn(&libds,NLOBS) %mf_getattrn(&libds,NLOBS)
%mend mf_nobs;/** %mend mf_nobs;/**
@file
@brief Reads the first line of a file using pure macro
@details Reads the first line of a file and returns it. Future versions may
read each line into a macro variable array.
Generally, reading data into macro variables is not great as certain
nonprintable characters (such as CR, LF) may be dropped in the conversion.
Usage:
%mf_writefile(&sasjswork/myfile.txt,l1=some content,l2=more content)
%put %mf_readfile(&sasjswork/myfile.txt);
@param [in] fpath Full path to file to be read
<h4> Related Macros </h4>
@li mf_deletefile.sas
@li mf_writefile.sas
@li mf_readfile.test.sas
@version 9.2
@author Allan Bowe
**/
/** @cond */
%macro mf_readfile(fpath
)/*/STORE SOURCE*/;
%local fref rc fid fcontent;
/* check file exists */
%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,I));
%if &fid=0 %then %do;
%put %str(ERR)OR: %sysfunc(sysmsg());
%return;
%end;
%if %sysfunc(fread(&fid)) = 0 %then %do;
%let rc=%sysfunc(fget(&fid,fcontent,65534));
&fcontent
%end;
/*
%do %while(%sysfunc(fread(&fid)) = 0);
%let rc=%sysfunc(fget(&fid,fcontent,65534));
&fcontent
%end;
*/
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(&fref));
%mend mf_readfile;
/** @endcond */
/**
@file mf_trimstr.sas @file mf_trimstr.sas
@brief Removes character(s) from the end, if they exist @brief Removes character(s) from the end, if they exist
@details If the designated characters exist at the end of the string, they @details If the designated characters exist at the end of the string, they
@@ -2442,15 +2544,51 @@ and %superq(SYSPROCESSNAME) ne %str(Compute Server)
_PROGRAM=quote(trim(resolve(symget('_PROGRAM')))); _PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
put ',"_PROGRAM" : ' _PROGRAM ; put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"'); syserrortext=cats(symget('syserrortext'));
put ",""SYSERRORTEXT"" : " syserrortext; if findc(syserrortext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syserrortext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syserrortext)
)))))))))))))!!'"';
end;
else syserrortext=cats('"',syserrortext,'"');
put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSJOBID"" : ""&sysjobid"" "; put ",""SYSJOBID"" : ""&sysjobid"" ";
put ",""SYSSCPL"" : ""&sysscpl"" "; put ",""SYSSCPL"" : ""&sysscpl"" ";
put ",""SYSSITE"" : ""&syssite"" "; put ",""SYSSITE"" : ""&syssite"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"'); syswarningtext=cats(symget('syswarningtext'));
if findc(syswarningtext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syswarningtext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syswarningtext)
)))))))))))))!!'"';
end;
else syswarningtext=cats('"',syswarningtext,'"');
put ",""SYSWARNINGTEXT"" : " syswarningtext; put ",""SYSWARNINGTEXT"" : " syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
put "}" ; put "}" ;
@@ -2776,7 +2914,7 @@ run;
results. If it does not exist, it will be created, with the following format: results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256| |TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---| |---|---|---|
|User Provided description|PASS|Column &inds contained ALL columns| |User Provided description|PASS|Dataset &inds contained ALL columns|
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe
@@ -2850,7 +2988,7 @@ run;
results. If it does not exist, it will be created, with the following format: results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256| |TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---| |---|---|---|
|User Provided description|PASS|Column &inds contained ALL columns| |User Provided description|PASS|Dataset &inds contained ALL columns|
<h4> Related Macros </h4> <h4> Related Macros </h4>
@@ -8212,6 +8350,110 @@ data _null_;
run; run;
%mend mp_gitadd; %mend mp_gitadd;
/**
@file
@brief Creates a dataset with the commit history of a local repository
@details Returns the commit history from a local repository. The name of the
branch is also returned.
More details here:
https://documentation.sas.com/doc/ko/pgmsascdc/v_033/lefunctionsref/n1qo5miyvry1nen111js203hlwrh.htm
Usage:
%let gitdir=%sysfunc(pathname(work))/core;
%let repo=https://github.com/sasjs/core;
%put source clone rc=%sysfunc(GITFN_CLONE(&repo,&dir));
%mp_gitlog(&gitdir,outds=work.mp_gitlog)
@param [in] gitdir The directory containing the GIT repository
@param [in] filter= (BRANCHONLY) To return only the commits for the current
branch, use BRANCHONLY (the default). Anything else will return the entire
commit history.
@param [out] outds= (work.mp_gitlog) The output dataset to create.
All vars are $128 except `message` which is $4000.
@li author returns the author who submitted the commit.
@li children_ids returns a list of the children commit IDs
@li committer returns the name of the committer.
@li committer_email returns the email of the committer.
@li email returns the email of the commit author.
@li id returns the commit ID of the commit object.
@li in_current_branch returns "TRUE" or "FALSE" to indicate if the commit is
in the current branch.
@li message returns the commit message.
@li parent_ids returns a list of the parent commit IDs.
@li stash returns "TRUE" or "FALSE" to indicate if the commit is a stash
commit.
@li time returns the time of the commit as numeric string
@li commit_time_num time of the commit as numeric SAS datetime
@li commit_time_str the commit_time_num variable cast as string
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@param [in] nobs= (0) Set to an integer greater than 0 to restrict the number
of rows returned
<h4> SAS Macros </h4>
@li mf_getgitbranch.sas
<h4> Related Files </h4>
@li mp_gitadd.sas
@li mp_gitreleaseinfo.sas
@li mp_gitstatus.sas
**/
%macro mp_gitlog(gitdir,outds=work.mp_gitlog,mdebug=0,filter=BRANCHONLY,nobs=0);
%local varlist i var;
%let varlist=author children_ids committer committer_email email id
in_current_branch parent_ids stash time ;
data &outds;
LENGTH gitdir branch $ 1024 message $4000 &varlist $128 commit_time_num 8.
commit_time_str $32;
call missing (of _all_);
branch="%mf_getgitbranch(&gitdir)";
gitdir=symget('gitdir');
rc=git_status_free(trim(gitdir));
if rc=-1 then do;
put "The libgit2 library is unavailable and no Git operations can be used.";
put "See: https://stackoverflow.com/questions/74082874";
stop;
end;
else if rc=-2 then do;
put "The libgit2 library is available, but the status function failed.";
put "See the log for details.";
stop;
end;
entries=git_commit_log(trim(gitdir));
do n=1 to entries;
%do i=1 %to %sysfunc(countw(&varlist message));
%let var=%scan(&varlist message,&i,%str( ));
rc=git_commit_get(n,trim(gitdir),"&var",&var);
%end;
/* convert unix time to SAS time - https://4gl.uk/corelink0 */
/* Number of seconds between 01JAN1960 and 01JAN1970: 315619200 */
format commit_time_num datetime19.;
commit_time_num=sum(input(cats(time),best.),315619200);
commit_time_str=put(commit_time_num,datetime19.);
%if &mdebug=1 %then %do;
putlog (_all_)(=);
%end;
if "&filter"="BRANCHONLY" then do;
if cats(in_current_branch)='TRUE' then output;
end;
else output;
%if &nobs>0 %then %do;
if n ge &nobs then stop;
%end;
end;
rc=git_commit_free(trim(gitdir));
keep gitdir branch &varlist message time commit_time_num commit_time_str;
run;
%mend mp_gitlog;
/** /**
@file @file
@brief Pulls latest release info from a GIT repository @brief Pulls latest release info from a GIT repository
@@ -8348,7 +8590,7 @@ data &outds;
putlog (_all_)(=); putlog (_all_)(=);
%end; %end;
end; end;
rc=git_status_free(gitdir); rc=git_status_free(trim(gitdir));
drop rc cnt; drop rc cnt;
run; run;
@@ -10242,7 +10484,10 @@ run;
where LOCK_LIB ="&lib" and LOCK_DS="&ds"; where LOCK_LIB ="&lib" and LOCK_DS="&ds";
quit; quit;
%if &syscc>0 %then %put syscc=&syscc sqlrc=&sqlrc; %if &syscc>0 %then %put syscc=&syscc sqlrc=&sqlrc;
%if &status=LOCKED %then %do; %if &sqlobs=0 %then %do;
%put %str(WAR)NING: &lib..&ds has never been locked!;
%end;
%else %if &status=LOCKED %then %do;
data _null_; data _null_;
putlog "&sysmacroname: unlocking &lib..&ds:"; putlog "&sysmacroname: unlocking &lib..&ds:";
run; run;
@@ -13819,7 +14064,8 @@ run;
filename __us2grp temp; filename __us2grp temp;
proc metadata in= "<UpdateMetadata><Reposid>$METAREPOSITORY</Reposid><Metadata> proc metadata in= "<UpdateMetadata><Reposid>$METAREPOSITORY</Reposid><Metadata>
<Person Id='&uuri'><IdentityGroups><IdentityGroup ObjRef='&guri' /> <Person Id='%nrstr(&uuri)'>
<IdentityGroups><IdentityGroup ObjRef='%nrstr(&guri)' />
</IdentityGroups></Person></Metadata> </IdentityGroups></Person></Metadata>
<NS>SAS</NS><Flags>268435456</Flags></UpdateMetadata>" <NS>SAS</NS><Flags>268435456</Flags></UpdateMetadata>"
out=__us2grp verbose; out=__us2grp verbose;
@@ -13836,7 +14082,8 @@ run;
filename __us2grp clear; filename __us2grp clear;
%mend mm_adduser2group;/** %mend mm_adduser2group;
/**
@file @file
@brief Assigns library directly using details from metadata @brief Assigns library directly using details from metadata
@details Queries metadata to get the libname definition then allocates the @details Queries metadata to get the libname definition then allocates the
@@ -16199,7 +16446,7 @@ data _null_;
put ' put " ""&wt"" : {"; '; put ' put " ""&wt"" : {"; ';
put ' put ''"nlobs":'' nlobs; '; put ' put ''"nlobs":'' nlobs; ';
put ' put '',"nvars":'' nvars; '; put ' put '',"nvars":'' nvars; ';
put ' %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y,maxobs=10 '; put ' %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y ';
put ' ,maxobs=&workobs '; put ' ,maxobs=&workobs ';
put ' ) '; put ' ) ';
put ' data _null_; file _sjsref mod encoding=''utf-8''; '; put ' data _null_; file _sjsref mod encoding=''utf-8''; ';
@@ -16224,7 +16471,25 @@ data _null_;
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; '; put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
put ' put ",""SYSCC"" : ""&syscc"" "; '; put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; '; put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); '; put ' syserrortext=cats(symget(''syserrortext'')); ';
put ' if findc(syserrortext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syserrortext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syserrortext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syserrortext=cats(''"'',syserrortext,''"''); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; '; put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; '; put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; '; put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
@@ -16237,7 +16502,25 @@ data _null_;
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; '; put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
put ' sysvlong=quote(trim(symget(''sysvlong''))); '; put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
put ' put '',"SYSVLONG" : '' sysvlong; '; put ' put '',"SYSVLONG" : '' sysvlong; ';
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); '; put ' syswarningtext=cats(symget(''syswarningtext'')); ';
put ' if findc(syswarningtext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syswarningtext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syswarningtext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syswarningtext=cats(''"'',syswarningtext,''"''); ';
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; '; put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; '; put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
put ' length memsize $32; '; put ' length memsize $32; ';
@@ -16263,9 +16546,11 @@ data _null_;
put ' '; put ' ';
put '%mend mm_webout; '; put '%mend mm_webout; ';
/* WEBOUT END */ /* WEBOUT END */
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO);'; put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO';
put ' ,maxobs=MAX';
put ');';
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing'; put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing';
put ' ,showmeta=&showmeta'; put ' ,showmeta=&showmeta,maxobs=&maxobs';
put ' )'; put ' )';
put '%mend;'; put '%mend;';
run; run;
@@ -19845,7 +20130,7 @@ run;
put " ""&wt"" : {"; put " ""&wt"" : {";
put '"nlobs":' nlobs; put '"nlobs":' nlobs;
put ',"nvars":' nvars; put ',"nvars":' nvars;
%mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y,maxobs=10 %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y
,maxobs=&workobs ,maxobs=&workobs
) )
data _null_; file _sjsref mod encoding='utf-8'; data _null_; file _sjsref mod encoding='utf-8';
@@ -19870,7 +20155,25 @@ run;
put ",""MF_GETUSER"" : ""%mf_getuser()"" "; put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSENCODING"" : ""&sysencoding"" "; put ",""SYSENCODING"" : ""&sysencoding"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"'); syserrortext=cats(symget('syserrortext'));
if findc(syserrortext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syserrortext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syserrortext)
)))))))))))))!!'"';
end;
else syserrortext=cats('"',syserrortext,'"');
put ',"SYSERRORTEXT" : ' syserrortext; put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" ";
@@ -19883,7 +20186,25 @@ run;
put ",""SYSUSERID"" : ""&sysuserid"" "; put ",""SYSUSERID"" : ""&sysuserid"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"'); syswarningtext=cats(symget('syswarningtext'));
if findc(syswarningtext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syswarningtext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syswarningtext)
)))))))))))))!!'"';
end;
else syswarningtext=cats('"',syswarningtext,'"');
put ',"SYSWARNINGTEXT" : ' syswarningtext; put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length memsize $32; length memsize $32;
@@ -21213,7 +21534,7 @@ data _null_;
put ' put " ""&wt"" : {"; '; put ' put " ""&wt"" : {"; ';
put ' put ''"nlobs":'' nlobs; '; put ' put ''"nlobs":'' nlobs; ';
put ' put '',"nvars":'' nvars; '; put ' put '',"nvars":'' nvars; ';
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10 '; put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y ';
put ' ,maxobs=&workobs '; put ' ,maxobs=&workobs ';
put ' ) '; put ' ) ';
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; '; put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
@@ -21234,7 +21555,25 @@ data _null_;
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; '; put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
put ' put ",""SYSCC"" : ""&syscc"" "; '; put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; '; put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); '; put ' syserrortext=cats(symget(''syserrortext'')); ';
put ' if findc(syserrortext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syserrortext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syserrortext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syserrortext=cats(''"'',syserrortext,''"''); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; '; put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); '; put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); ';
put ' put '',"SYSHOSTINFOLONG" : '' SYSHOSTINFOLONG; '; put ' put '',"SYSHOSTINFOLONG" : '' SYSHOSTINFOLONG; ';
@@ -21250,7 +21589,25 @@ data _null_;
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; '; put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
put ' sysvlong=quote(trim(symget(''sysvlong''))); '; put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
put ' put '',"SYSVLONG" : '' sysvlong; '; put ' put '',"SYSVLONG" : '' sysvlong; ';
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); '; put ' syswarningtext=cats(symget(''syswarningtext'')); ';
put ' if findc(syswarningtext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syswarningtext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syswarningtext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syswarningtext=cats(''"'',syswarningtext,''"''); ';
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; '; put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; '; put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
put ' length memsize $32; '; put ' length memsize $32; ';
@@ -21444,7 +21801,7 @@ filename &headref clear;
@param [in] uid= (0) Provide the userid on which to filter @param [in] uid= (0) Provide the userid on which to filter
@param [out] outds= (work.ms_getgroups) This output dataset will contain the @param [out] outds= (work.ms_getgroups) This output dataset will contain the
list of groups. Format: list of groups. Format:
|NAME:$32.|DESCRIPTION:$64.|GROUPID:best.| |NAME:$32.|DESCRIPTION:$256.|GROUPID:best.|
|---|---|---| |---|---|---|
|`SomeGroup `|`A group `|`1`| |`SomeGroup `|`A group `|`1`|
|`Another Group`|`this is a different group`|`2`| |`Another Group`|`this is a different group`|`2`|
@@ -21480,7 +21837,7 @@ filename &headref clear;
%if %sysget(MODE)=desktop %then %do; %if %sysget(MODE)=desktop %then %do;
/* groups api does not exist in desktop mode */ /* groups api does not exist in desktop mode */
data &outds; data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8; length NAME $32 DESCRIPTION $256. GROUPID 8;
name="&sysuserid"; name="&sysuserid";
description="&sysuserid (group - desktop mode)"; description="&sysuserid (group - desktop mode)";
groupid=1; groupid=1;
@@ -21536,7 +21893,7 @@ libname &libref JSON fileref=&fref1;
%if "&user"="0" and "&uid"="0" %then %do; %if "&user"="0" and "&uid"="0" %then %do;
data &outds; data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8; length NAME $32 DESCRIPTION $256. GROUPID 8;
if _n_=1 then call missing(of _all_); if _n_=1 then call missing(of _all_);
set &libref..root; set &libref..root;
drop ordinal_root; drop ordinal_root;
@@ -21544,7 +21901,7 @@ libname &libref JSON fileref=&fref1;
%end; %end;
%else %do; %else %do;
data &outds; data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8; length NAME $32 DESCRIPTION $256. GROUPID 8;
if _n_=1 then call missing(of _all_); if _n_=1 then call missing(of _all_);
set &libref..groups; set &libref..groups;
drop ordinal_:; drop ordinal_:;
@@ -21756,8 +22113,9 @@ options &optval;
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas @li mf_getuniquename.sas
@li mp_abort.sas @li mp_abort.sas
@li mp_chop.sas
**/ **/
@@ -21870,7 +22228,10 @@ run;
run; run;
%end; %end;
filename &outref temp lrecl=32767; %local resp_path;
%let resp_path=%sysfunc(pathname(work))/%mf_getuniquename();
filename &outref "&resp_path" lrecl=32767;
/* prepare request*/ /* prepare request*/
proc http method='POST' headerin=&authref in=&mainref out=&outref proc http method='POST' headerin=&authref in=&mainref out=&outref
url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131"; url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131";
@@ -21878,6 +22239,7 @@ proc http method='POST' headerin=&authref in=&mainref out=&outref
debug level=2; debug level=2;
%end; %end;
run; run;
%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201) %if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
or &mdebug=1 or &mdebug=1
%then %do; %then %do;
@@ -21893,11 +22255,22 @@ or &mdebug=1
options &optval; options &optval;
%if &outlogds ne _null_ or &mdebug=1 %then %do; %if &outlogds ne _null_ or &mdebug=1 %then %do;
%local dumplib; %local matchstr chopout;
%let dumplib=%mf_getuniquelibref(); %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
libname &dumplib json fileref=&outref; %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
%mp_chop("&resp_path"
,matchvar=matchstr
,keep=LAST
,matchpoint=END
,outfile="&chopout"
,mdebug=&mdebug
)
data &outlogds; data &outlogds;
set &dumplib..log; infile "&chopout" lrecl=2000;
length line $2000;
line=_infile_;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
putlog line=; putlog line=;
%end; %end;
@@ -22024,50 +22397,38 @@ run;
) )
/* SASjs services have the _webout embedded in wrapper JSON */ /* chop out JSON section */
/* Files can also be very large - so use a dedicated macro to chop it out */ %local matchstr chopout;
%local matchstr1 matchstr2 ; %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
%let matchstr1={"status":"success","_webout":{; %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
%let matchstr2=},"log":[{;
%let chopout1=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop1);
%let chopout2=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop2);
%mp_chop("%sysfunc(pathname(&fref1,F))" %mp_chop("%sysfunc(pathname(&fref1,F))"
,matchvar=matchstr1 ,matchvar=matchstr
,keep=LAST
,matchpoint=END
,offset=-1
,outfile="&chopout1"
,mdebug=&mdebug
)
%mp_chop("&chopout1"
,matchvar=matchstr2
,keep=FIRST ,keep=FIRST
,matchpoint=START ,matchpoint=START
,offset=1 ,offset=-1
,outfile="&chopout2" ,outfile="&chopout"
,mdebug=&mdebug ,mdebug=&mdebug
) )
%if &outlib ne 0 %then %do; %if &outlib ne 0 %then %do;
libname &outlib json "&chopout2"; libname &outlib json "&chopout";
%end; %end;
%if &outref ne 0 %then %do; %if &outref ne 0 %then %do;
filename &outref "&chopout2"; filename &outref "&chopout";
%end; %end;
%if &mdebug=0 %then %do; %if &mdebug=0 %then %do;
filename &webref clear; filename &webref clear;
filename &fref1 clear; filename &fref1 clear;
filename &fref2 clear;
%end; %end;
%else %do; %else %do;
%put &sysmacroname exit vars:; %put &sysmacroname exit vars:;
%put _local_; %put _local_;
%end; %end;
%mend ms_testservice;/** %mend ms_testservice;
/**
@file @file
@brief Send data to/from sasjs/server @brief Send data to/from sasjs/server
@details This macro should be added to the start of each web service, @details This macro should be added to the start of each web service,
@@ -22210,7 +22571,7 @@ run;
put " ""&wt"" : {"; put " ""&wt"" : {";
put '"nlobs":' nlobs; put '"nlobs":' nlobs;
put ',"nvars":' nvars; put ',"nvars":' nvars;
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10 %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y
,maxobs=&workobs ,maxobs=&workobs
) )
data _null_; file &fref mod encoding='utf-8' termstr=lf; data _null_; file &fref mod encoding='utf-8' termstr=lf;
@@ -22231,7 +22592,25 @@ run;
put ",""MF_GETUSER"" : ""%mf_getuser()"" "; put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSENCODING"" : ""&sysencoding"" "; put ",""SYSENCODING"" : ""&sysencoding"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"'); syserrortext=cats(symget('syserrortext'));
if findc(syserrortext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syserrortext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syserrortext)
)))))))))))))!!'"';
end;
else syserrortext=cats('"',syserrortext,'"');
put ',"SYSERRORTEXT" : ' syserrortext; put ',"SYSERRORTEXT" : ' syserrortext;
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG'))); SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));
put ',"SYSHOSTINFOLONG" : ' SYSHOSTINFOLONG; put ',"SYSHOSTINFOLONG" : ' SYSHOSTINFOLONG;
@@ -22247,7 +22626,25 @@ run;
put ",""SYSUSERID"" : ""&sysuserid"" "; put ",""SYSUSERID"" : ""&sysuserid"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"'); syswarningtext=cats(symget('syswarningtext'));
if findc(syswarningtext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syswarningtext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syswarningtext)
)))))))))))))!!'"';
end;
else syswarningtext=cats('"',syswarningtext,'"');
put ',"SYSWARNINGTEXT" : ' syswarningtext; put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length memsize $32; length memsize $32;
@@ -23825,7 +24222,25 @@ data _null_;
put ' put '',"SYS_JES_JOB_URI" : '' SYS_JES_JOB_URI ; '; put ' put '',"SYS_JES_JOB_URI" : '' SYS_JES_JOB_URI ; ';
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; '; put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
put ' put ",""SYSCC"" : ""&syscc"" "; '; put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); '; put ' syserrortext=cats(symget(''syserrortext'')); ';
put ' if findc(syserrortext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syserrortext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syserrortext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syserrortext=cats(''"'',syserrortext,''"''); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; '; put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; '; put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; '; put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
@@ -23838,7 +24253,25 @@ data _null_;
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; '; put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
put ' sysvlong=quote(trim(symget(''sysvlong''))); '; put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
put ' put '',"SYSVLONG" : '' sysvlong; '; put ' put '',"SYSVLONG" : '' sysvlong; ';
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); '; put ' syswarningtext=cats(symget(''syswarningtext'')); ';
put ' if findc(syswarningtext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syswarningtext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syswarningtext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syswarningtext=cats(''"'',syswarningtext,''"''); ';
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; '; put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; '; put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
put ' length memsize $32; '; put ' length memsize $32; ';
@@ -27632,7 +28065,25 @@ filename &fref1 clear;
put ',"SYS_JES_JOB_URI" : ' SYS_JES_JOB_URI ; put ',"SYS_JES_JOB_URI" : ' SYS_JES_JOB_URI ;
put ",""SYSJOBID"" : ""&sysjobid"" "; put ",""SYSJOBID"" : ""&sysjobid"" ";
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"'); syserrortext=cats(symget('syserrortext'));
if findc(syserrortext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syserrortext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syserrortext)
)))))))))))))!!'"';
end;
else syserrortext=cats('"',syserrortext,'"');
put ',"SYSERRORTEXT" : ' syserrortext; put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" ";
@@ -27645,7 +28096,25 @@ filename &fref1 clear;
put ",""SYSUSERID"" : ""&sysuserid"" "; put ",""SYSUSERID"" : ""&sysuserid"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"'); syswarningtext=cats(symget('syswarningtext'));
if findc(syswarningtext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syswarningtext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syswarningtext)
)))))))))))))!!'"';
end;
else syswarningtext=cats('"',syswarningtext,'"');
put ',"SYSWARNINGTEXT" : ' syswarningtext; put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length memsize $32; length memsize $32;

View File

@@ -12,7 +12,7 @@
**/ **/
%macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1) %macro mf_abort(mac=mf_abort.sas, msg=, iftrue=%str(1=1)
)/*/STORE SOURCE*/; )/des='ungraceful abort' /*STORE SOURCE*/;
%if not(%eval(%unquote(&iftrue))) %then %return; %if not(%eval(%unquote(&iftrue))) %then %return;

37
base/mf_getgitbranch.sas Normal file
View File

@@ -0,0 +1,37 @@
/**
@file
@brief Retrieves the current branch from a local GIT repo
@details In a local git repository, the current branch is always available in
the `.git/HEAD` file in a format like this: `ref: refs/heads/master`
This macro simply reads the file and returns the last word (eg `master`).
Example usage:
%let gitdir=%sysfunc(pathname(work))/core;
%let repo=https://github.com/sasjs/core;
%put source clone rc=%sysfunc(GITFN_CLONE(&repo,&gitdir));
%put The current branch is %mf_getgitbranch(&gitdir);
@param [in] gitdir The directory containing the GIT repository
<h4> SAS Macros </h4>
@li mf_readfile.sas
<h4> Related Macros </h4>
@li mp_gitadd.sas
@li mp_gitlog.sas
@li mp_gitreleaseinfo.sas
@li mp_gitstatus.sas
@version 9.2
@author Allan Bowe
**/
%macro mf_getgitbranch(gitdir
)/*/STORE SOURCE*/;
%scan(%mf_readfile(&gitdir/.git/HEAD),-1)
%mend mf_getgitbranch;

63
base/mf_readfile.sas Normal file
View File

@@ -0,0 +1,63 @@
/**
@file
@brief Reads the first line of a file using pure macro
@details Reads the first line of a file and returns it. Future versions may
read each line into a macro variable array.
Generally, reading data into macro variables is not great as certain
nonprintable characters (such as CR, LF) may be dropped in the conversion.
Usage:
%mf_writefile(&sasjswork/myfile.txt,l1=some content,l2=more content)
%put %mf_readfile(&sasjswork/myfile.txt);
@param [in] fpath Full path to file to be read
<h4> Related Macros </h4>
@li mf_deletefile.sas
@li mf_writefile.sas
@li mf_readfile.test.sas
@version 9.2
@author Allan Bowe
**/
/** @cond */
%macro mf_readfile(fpath
)/*/STORE SOURCE*/;
%local fref rc fid fcontent;
/* check file exists */
%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,I));
%if &fid=0 %then %do;
%put %str(ERR)OR: %sysfunc(sysmsg());
%return;
%end;
%if %sysfunc(fread(&fid)) = 0 %then %do;
%let rc=%sysfunc(fget(&fid,fcontent,65534));
&fcontent
%end;
/*
%do %while(%sysfunc(fread(&fid)) = 0);
%let rc=%sysfunc(fget(&fid,fcontent,65534));
&fcontent
%end;
*/
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(&fref));
%mend mf_readfile;
/** @endcond */

View File

@@ -225,15 +225,51 @@ and %superq(SYSPROCESSNAME) ne %str(Compute Server)
_PROGRAM=quote(trim(resolve(symget('_PROGRAM')))); _PROGRAM=quote(trim(resolve(symget('_PROGRAM'))));
put ',"_PROGRAM" : ' _PROGRAM ; put ',"_PROGRAM" : ' _PROGRAM ;
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"'); syserrortext=cats(symget('syserrortext'));
put ",""SYSERRORTEXT"" : " syserrortext; if findc(syserrortext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syserrortext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syserrortext)
)))))))))))))!!'"';
end;
else syserrortext=cats('"',syserrortext,'"');
put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSJOBID"" : ""&sysjobid"" "; put ",""SYSJOBID"" : ""&sysjobid"" ";
put ",""SYSSCPL"" : ""&sysscpl"" "; put ",""SYSSCPL"" : ""&sysscpl"" ";
put ",""SYSSITE"" : ""&syssite"" "; put ",""SYSSITE"" : ""&syssite"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"'); syswarningtext=cats(symget('syswarningtext'));
if findc(syswarningtext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syswarningtext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syswarningtext)
)))))))))))))!!'"';
end;
else syswarningtext=cats('"',syswarningtext,'"');
put ",""SYSWARNINGTEXT"" : " syswarningtext; put ",""SYSWARNINGTEXT"" : " syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
put "}" ; put "}" ;

View File

@@ -22,7 +22,7 @@
results. If it does not exist, it will be created, with the following format: results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256| |TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---| |---|---|---|
|User Provided description|PASS|Column &inds contained ALL columns| |User Provided description|PASS|Dataset &inds contained ALL columns|
@version 9.2 @version 9.2
@author Allan Bowe @author Allan Bowe

View File

@@ -41,7 +41,7 @@
results. If it does not exist, it will be created, with the following format: results. If it does not exist, it will be created, with the following format:
|TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256| |TEST_DESCRIPTION:$256|TEST_RESULT:$4|TEST_COMMENTS:$256|
|---|---|---| |---|---|---|
|User Provided description|PASS|Column &inds contained ALL columns| |User Provided description|PASS|Dataset &inds contained ALL columns|
<h4> Related Macros </h4> <h4> Related Macros </h4>

104
base/mp_gitlog.sas Normal file
View File

@@ -0,0 +1,104 @@
/**
@file
@brief Creates a dataset with the commit history of a local repository
@details Returns the commit history from a local repository. The name of the
branch is also returned.
More details here:
https://documentation.sas.com/doc/ko/pgmsascdc/v_033/lefunctionsref/n1qo5miyvry1nen111js203hlwrh.htm
Usage:
%let gitdir=%sysfunc(pathname(work))/core;
%let repo=https://github.com/sasjs/core;
%put source clone rc=%sysfunc(GITFN_CLONE(&repo,&dir));
%mp_gitlog(&gitdir,outds=work.mp_gitlog)
@param [in] gitdir The directory containing the GIT repository
@param [in] filter= (BRANCHONLY) To return only the commits for the current
branch, use BRANCHONLY (the default). Anything else will return the entire
commit history.
@param [out] outds= (work.mp_gitlog) The output dataset to create.
All vars are $128 except `message` which is $4000.
@li author returns the author who submitted the commit.
@li children_ids returns a list of the children commit IDs
@li committer returns the name of the committer.
@li committer_email returns the email of the committer.
@li email returns the email of the commit author.
@li id returns the commit ID of the commit object.
@li in_current_branch returns "TRUE" or "FALSE" to indicate if the commit is
in the current branch.
@li message returns the commit message.
@li parent_ids returns a list of the parent commit IDs.
@li stash returns "TRUE" or "FALSE" to indicate if the commit is a stash
commit.
@li time returns the time of the commit as numeric string
@li commit_time_num time of the commit as numeric SAS datetime
@li commit_time_str the commit_time_num variable cast as string
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
@param [in] nobs= (0) Set to an integer greater than 0 to restrict the number
of rows returned
<h4> SAS Macros </h4>
@li mf_getgitbranch.sas
<h4> Related Files </h4>
@li mp_gitadd.sas
@li mp_gitreleaseinfo.sas
@li mp_gitstatus.sas
**/
%macro mp_gitlog(gitdir,outds=work.mp_gitlog,mdebug=0,filter=BRANCHONLY,nobs=0);
%local varlist i var;
%let varlist=author children_ids committer committer_email email id
in_current_branch parent_ids stash time ;
data &outds;
LENGTH gitdir branch $ 1024 message $4000 &varlist $128 commit_time_num 8.
commit_time_str $32;
call missing (of _all_);
branch="%mf_getgitbranch(&gitdir)";
gitdir=symget('gitdir');
rc=git_status_free(trim(gitdir));
if rc=-1 then do;
put "The libgit2 library is unavailable and no Git operations can be used.";
put "See: https://stackoverflow.com/questions/74082874";
stop;
end;
else if rc=-2 then do;
put "The libgit2 library is available, but the status function failed.";
put "See the log for details.";
stop;
end;
entries=git_commit_log(trim(gitdir));
do n=1 to entries;
%do i=1 %to %sysfunc(countw(&varlist message));
%let var=%scan(&varlist message,&i,%str( ));
rc=git_commit_get(n,trim(gitdir),"&var",&var);
%end;
/* convert unix time to SAS time - https://4gl.uk/corelink0 */
/* Number of seconds between 01JAN1960 and 01JAN1970: 315619200 */
format commit_time_num datetime19.;
commit_time_num=sum(input(cats(time),best.),315619200);
commit_time_str=put(commit_time_num,datetime19.);
%if &mdebug=1 %then %do;
putlog (_all_)(=);
%end;
if "&filter"="BRANCHONLY" then do;
if cats(in_current_branch)='TRUE' then output;
end;
else output;
%if &nobs>0 %then %do;
if n ge &nobs then stop;
%end;
end;
rc=git_commit_free(trim(gitdir));
keep gitdir branch &varlist message time commit_time_num commit_time_str;
run;
%mend mp_gitlog;

View File

@@ -60,7 +60,7 @@ data &outds;
putlog (_all_)(=); putlog (_all_)(=);
%end; %end;
end; end;
rc=git_status_free(gitdir); rc=git_status_free(trim(gitdir));
drop rc cnt; drop rc cnt;
run; run;

View File

@@ -200,7 +200,10 @@ run;
where LOCK_LIB ="&lib" and LOCK_DS="&ds"; where LOCK_LIB ="&lib" and LOCK_DS="&ds";
quit; quit;
%if &syscc>0 %then %put syscc=&syscc sqlrc=&sqlrc; %if &syscc>0 %then %put syscc=&syscc sqlrc=&sqlrc;
%if &status=LOCKED %then %do; %if &sqlobs=0 %then %do;
%put %str(WAR)NING: &lib..&ds has never been locked!;
%end;
%else %if &status=LOCKED %then %do;
data _null_; data _null_;
putlog "&sysmacroname: unlocking &lib..&ds:"; putlog "&sysmacroname: unlocking &lib..&ds:";
run; run;

View File

@@ -81,7 +81,8 @@ run;
filename __us2grp temp; filename __us2grp temp;
proc metadata in= "<UpdateMetadata><Reposid>$METAREPOSITORY</Reposid><Metadata> proc metadata in= "<UpdateMetadata><Reposid>$METAREPOSITORY</Reposid><Metadata>
<Person Id='&uuri'><IdentityGroups><IdentityGroup ObjRef='&guri' /> <Person Id='%nrstr(&uuri)'>
<IdentityGroups><IdentityGroup ObjRef='%nrstr(&guri)' />
</IdentityGroups></Person></Metadata> </IdentityGroups></Person></Metadata>
<NS>SAS</NS><Flags>268435456</Flags></UpdateMetadata>" <NS>SAS</NS><Flags>268435456</Flags></UpdateMetadata>"
out=__us2grp verbose; out=__us2grp verbose;

View File

@@ -546,7 +546,7 @@ data _null_;
put ' put " ""&wt"" : {"; '; put ' put " ""&wt"" : {"; ';
put ' put ''"nlobs":'' nlobs; '; put ' put ''"nlobs":'' nlobs; ';
put ' put '',"nvars":'' nvars; '; put ' put '',"nvars":'' nvars; ';
put ' %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y,maxobs=10 '; put ' %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y ';
put ' ,maxobs=&workobs '; put ' ,maxobs=&workobs ';
put ' ) '; put ' ) ';
put ' data _null_; file _sjsref mod encoding=''utf-8''; '; put ' data _null_; file _sjsref mod encoding=''utf-8''; ';
@@ -571,7 +571,25 @@ data _null_;
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; '; put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
put ' put ",""SYSCC"" : ""&syscc"" "; '; put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; '; put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); '; put ' syserrortext=cats(symget(''syserrortext'')); ';
put ' if findc(syserrortext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syserrortext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syserrortext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syserrortext=cats(''"'',syserrortext,''"''); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; '; put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; '; put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; '; put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
@@ -584,7 +602,25 @@ data _null_;
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; '; put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
put ' sysvlong=quote(trim(symget(''sysvlong''))); '; put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
put ' put '',"SYSVLONG" : '' sysvlong; '; put ' put '',"SYSVLONG" : '' sysvlong; ';
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); '; put ' syswarningtext=cats(symget(''syswarningtext'')); ';
put ' if findc(syswarningtext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syswarningtext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syswarningtext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syswarningtext=cats(''"'',syswarningtext,''"''); ';
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; '; put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; '; put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
put ' length memsize $32; '; put ' length memsize $32; ';
@@ -610,9 +646,11 @@ data _null_;
put ' '; put ' ';
put '%mend mm_webout; '; put '%mend mm_webout; ';
/* WEBOUT END */ /* WEBOUT END */
put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO);'; put '%macro webout(action,ds,dslabel=,fmt=,missing=NULL,showmeta=NO';
put ' ,maxobs=MAX';
put ');';
put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing'; put ' %mm_webout(&action,ds=&ds,dslabel=&dslabel,fmt=&fmt,missing=&missing';
put ' ,showmeta=&showmeta'; put ' ,showmeta=&showmeta,maxobs=&maxobs';
put ' )'; put ' )';
put '%mend;'; put '%mend;';
run; run;

View File

@@ -150,7 +150,7 @@
put " ""&wt"" : {"; put " ""&wt"" : {";
put '"nlobs":' nlobs; put '"nlobs":' nlobs;
put ',"nvars":' nvars; put ',"nvars":' nvars;
%mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y,maxobs=10 %mp_jsonout(OBJ,&wt,jref=_sjsref,dslabel=first10rows,showmeta=Y
,maxobs=&workobs ,maxobs=&workobs
) )
data _null_; file _sjsref mod encoding='utf-8'; data _null_; file _sjsref mod encoding='utf-8';
@@ -175,7 +175,25 @@
put ",""MF_GETUSER"" : ""%mf_getuser()"" "; put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSENCODING"" : ""&sysencoding"" "; put ",""SYSENCODING"" : ""&sysencoding"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"'); syserrortext=cats(symget('syserrortext'));
if findc(syserrortext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syserrortext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syserrortext)
)))))))))))))!!'"';
end;
else syserrortext=cats('"',syserrortext,'"');
put ',"SYSERRORTEXT" : ' syserrortext; put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" ";
@@ -188,7 +206,25 @@
put ",""SYSUSERID"" : ""&sysuserid"" "; put ",""SYSUSERID"" : ""&sysuserid"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"'); syswarningtext=cats(symget('syswarningtext'));
if findc(syswarningtext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syswarningtext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syswarningtext)
)))))))))))))!!'"';
end;
else syswarningtext=cats('"',syswarningtext,'"');
put ',"SYSWARNINGTEXT" : ' syswarningtext; put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length memsize $32; length memsize $32;

668
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,6 @@
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true" "prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
}, },
"devDependencies": { "devDependencies": {
"@sasjs/cli": "3.13.0" "@sasjs/cli": "3.24.0"
} }
} }

View File

@@ -85,7 +85,7 @@
{ {
"name": "docsonly", "name": "docsonly",
"serverType": "SASJS", "serverType": "SASJS",
"appLoc": "dummy", "appLoc": "/dummy",
"macroFolders": [ "macroFolders": [
"meta", "meta",
"metax", "metax",

View File

@@ -27,14 +27,14 @@ run;
%let dir = %sysfunc(pathname(work))/core; %let dir = %sysfunc(pathname(work))/core;
%put source clone rc=%sysfunc(GITFN_CLONE(https://github.com/sasjs/core,&dir)); %put source clone rc=%sysfunc(GITFN_CLONE(https://github.com/sasjs/core,&dir));
/* /*
clone the target repo. clone the target repo.
If you have issues, see: https://stackoverflow.com/questions/74082874 If you have issues, see: https://stackoverflow.com/questions/74082874
*/ */
options dlcreatedir; options dlcreatedir;
libname _ "&dirOut.";
%let dirOut = %sysfunc(pathname(work))/package; %let dirOut = %sysfunc(pathname(work))/package;
libname _ "&dirOut.";
%put tgt clone rc=%sysfunc(GITFN_CLONE( %put tgt clone rc=%sysfunc(GITFN_CLONE(
git@github.com:SASPAC/sasjscore.git, git@github.com:SASPAC/sasjscore.git,
&dirOut, &dirOut,

View File

@@ -539,7 +539,7 @@ data _null_;
put ' put " ""&wt"" : {"; '; put ' put " ""&wt"" : {"; ';
put ' put ''"nlobs":'' nlobs; '; put ' put ''"nlobs":'' nlobs; ';
put ' put '',"nvars":'' nvars; '; put ' put '',"nvars":'' nvars; ';
put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10 '; put ' %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y ';
put ' ,maxobs=&workobs '; put ' ,maxobs=&workobs ';
put ' ) '; put ' ) ';
put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; '; put ' data _null_; file &fref mod encoding=''utf-8'' termstr=lf; ';
@@ -560,7 +560,25 @@ data _null_;
put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; '; put ' put ",""MF_GETUSER"" : ""%mf_getuser()"" "; ';
put ' put ",""SYSCC"" : ""&syscc"" "; '; put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' put ",""SYSENCODING"" : ""&sysencoding"" "; '; put ' put ",""SYSENCODING"" : ""&sysencoding"" "; ';
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); '; put ' syserrortext=cats(symget(''syserrortext'')); ';
put ' if findc(syserrortext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syserrortext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syserrortext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syserrortext=cats(''"'',syserrortext,''"''); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; '; put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); '; put ' SYSHOSTINFOLONG=quote(trim(symget(''SYSHOSTINFOLONG''))); ';
put ' put '',"SYSHOSTINFOLONG" : '' SYSHOSTINFOLONG; '; put ' put '',"SYSHOSTINFOLONG" : '' SYSHOSTINFOLONG; ';
@@ -576,7 +594,25 @@ data _null_;
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; '; put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
put ' sysvlong=quote(trim(symget(''sysvlong''))); '; put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
put ' put '',"SYSVLONG" : '' sysvlong; '; put ' put '',"SYSVLONG" : '' sysvlong; ';
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); '; put ' syswarningtext=cats(symget(''syswarningtext'')); ';
put ' if findc(syswarningtext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syswarningtext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syswarningtext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syswarningtext=cats(''"'',syswarningtext,''"''); ';
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; '; put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; '; put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
put ' length memsize $32; '; put ' length memsize $32; ';

View File

@@ -22,7 +22,7 @@
@param [in] uid= (0) Provide the userid on which to filter @param [in] uid= (0) Provide the userid on which to filter
@param [out] outds= (work.ms_getgroups) This output dataset will contain the @param [out] outds= (work.ms_getgroups) This output dataset will contain the
list of groups. Format: list of groups. Format:
|NAME:$32.|DESCRIPTION:$64.|GROUPID:best.| |NAME:$32.|DESCRIPTION:$256.|GROUPID:best.|
|---|---|---| |---|---|---|
|`SomeGroup `|`A group `|`1`| |`SomeGroup `|`A group `|`1`|
|`Another Group`|`this is a different group`|`2`| |`Another Group`|`this is a different group`|`2`|
@@ -58,7 +58,7 @@
%if %sysget(MODE)=desktop %then %do; %if %sysget(MODE)=desktop %then %do;
/* groups api does not exist in desktop mode */ /* groups api does not exist in desktop mode */
data &outds; data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8; length NAME $32 DESCRIPTION $256. GROUPID 8;
name="&sysuserid"; name="&sysuserid";
description="&sysuserid (group - desktop mode)"; description="&sysuserid (group - desktop mode)";
groupid=1; groupid=1;
@@ -114,7 +114,7 @@ libname &libref JSON fileref=&fref1;
%if "&user"="0" and "&uid"="0" %then %do; %if "&user"="0" and "&uid"="0" %then %do;
data &outds; data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8; length NAME $32 DESCRIPTION $256. GROUPID 8;
if _n_=1 then call missing(of _all_); if _n_=1 then call missing(of _all_);
set &libref..root; set &libref..root;
drop ordinal_root; drop ordinal_root;
@@ -122,7 +122,7 @@ libname &libref JSON fileref=&fref1;
%end; %end;
%else %do; %else %do;
data &outds; data &outds;
length NAME $32 DESCRIPTION $64. GROUPID 8; length NAME $32 DESCRIPTION $256. GROUPID 8;
if _n_=1 then call missing(of _all_); if _n_=1 then call missing(of _all_);
set &libref..groups; set &libref..groups;
drop ordinal_:; drop ordinal_:;

View File

@@ -39,8 +39,9 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas @li mf_getuniquename.sas
@li mp_abort.sas @li mp_abort.sas
@li mp_chop.sas
**/ **/
@@ -153,7 +154,10 @@ run;
run; run;
%end; %end;
filename &outref temp lrecl=32767; %local resp_path;
%let resp_path=%sysfunc(pathname(work))/%mf_getuniquename();
filename &outref "&resp_path" lrecl=32767;
/* prepare request*/ /* prepare request*/
proc http method='POST' headerin=&authref in=&mainref out=&outref proc http method='POST' headerin=&authref in=&mainref out=&outref
url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131"; url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131";
@@ -161,6 +165,7 @@ proc http method='POST' headerin=&authref in=&mainref out=&outref
debug level=2; debug level=2;
%end; %end;
run; run;
%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201) %if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
or &mdebug=1 or &mdebug=1
%then %do; %then %do;
@@ -176,11 +181,22 @@ or &mdebug=1
options &optval; options &optval;
%if &outlogds ne _null_ or &mdebug=1 %then %do; %if &outlogds ne _null_ or &mdebug=1 %then %do;
%local dumplib; %local matchstr chopout;
%let dumplib=%mf_getuniquelibref(); %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
libname &dumplib json fileref=&outref; %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
%mp_chop("&resp_path"
,matchvar=matchstr
,keep=LAST
,matchpoint=END
,outfile="&chopout"
,mdebug=&mdebug
)
data &outlogds; data &outlogds;
set &dumplib..log; infile "&chopout" lrecl=2000;
length line $2000;
line=_infile_;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
putlog line=; putlog line=;
%end; %end;

View File

@@ -108,43 +108,30 @@ run;
) )
/* SASjs services have the _webout embedded in wrapper JSON */ /* chop out JSON section */
/* Files can also be very large - so use a dedicated macro to chop it out */ %local matchstr chopout;
%local matchstr1 matchstr2 ; %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
%let matchstr1={"status":"success","_webout":{; %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
%let matchstr2=},"log":[{;
%let chopout1=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop1);
%let chopout2=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop2);
%mp_chop("%sysfunc(pathname(&fref1,F))" %mp_chop("%sysfunc(pathname(&fref1,F))"
,matchvar=matchstr1 ,matchvar=matchstr
,keep=LAST
,matchpoint=END
,offset=-1
,outfile="&chopout1"
,mdebug=&mdebug
)
%mp_chop("&chopout1"
,matchvar=matchstr2
,keep=FIRST ,keep=FIRST
,matchpoint=START ,matchpoint=START
,offset=1 ,offset=-1
,outfile="&chopout2" ,outfile="&chopout"
,mdebug=&mdebug ,mdebug=&mdebug
) )
%if &outlib ne 0 %then %do; %if &outlib ne 0 %then %do;
libname &outlib json "&chopout2"; libname &outlib json "&chopout";
%end; %end;
%if &outref ne 0 %then %do; %if &outref ne 0 %then %do;
filename &outref "&chopout2"; filename &outref "&chopout";
%end; %end;
%if &mdebug=0 %then %do; %if &mdebug=0 %then %do;
filename &webref clear; filename &webref clear;
filename &fref1 clear; filename &fref1 clear;
filename &fref2 clear;
%end; %end;
%else %do; %else %do;
%put &sysmacroname exit vars:; %put &sysmacroname exit vars:;

View File

@@ -141,7 +141,7 @@
put " ""&wt"" : {"; put " ""&wt"" : {";
put '"nlobs":' nlobs; put '"nlobs":' nlobs;
put ',"nvars":' nvars; put ',"nvars":' nvars;
%mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y,maxobs=10 %mp_jsonout(OBJ,&wt,jref=&fref,dslabel=first10rows,showmeta=Y
,maxobs=&workobs ,maxobs=&workobs
) )
data _null_; file &fref mod encoding='utf-8' termstr=lf; data _null_; file &fref mod encoding='utf-8' termstr=lf;
@@ -162,7 +162,25 @@
put ",""MF_GETUSER"" : ""%mf_getuser()"" "; put ",""MF_GETUSER"" : ""%mf_getuser()"" ";
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
put ",""SYSENCODING"" : ""&sysencoding"" "; put ",""SYSENCODING"" : ""&sysencoding"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"'); syserrortext=cats(symget('syserrortext'));
if findc(syserrortext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syserrortext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syserrortext)
)))))))))))))!!'"';
end;
else syserrortext=cats('"',syserrortext,'"');
put ',"SYSERRORTEXT" : ' syserrortext; put ',"SYSERRORTEXT" : ' syserrortext;
SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG'))); SYSHOSTINFOLONG=quote(trim(symget('SYSHOSTINFOLONG')));
put ',"SYSHOSTINFOLONG" : ' SYSHOSTINFOLONG; put ',"SYSHOSTINFOLONG" : ' SYSHOSTINFOLONG;
@@ -178,7 +196,25 @@
put ",""SYSUSERID"" : ""&sysuserid"" "; put ",""SYSUSERID"" : ""&sysuserid"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"'); syswarningtext=cats(symget('syswarningtext'));
if findc(syswarningtext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syswarningtext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syswarningtext)
)))))))))))))!!'"';
end;
else syswarningtext=cats('"',syswarningtext,'"');
put ',"SYSWARNINGTEXT" : ' syswarningtext; put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length memsize $32; length memsize $32;

View File

@@ -0,0 +1,20 @@
/**
@file
@brief Testing mf_getgitbranch.sas macro
<h4> SAS Macros </h4>
@li mf_getgitbranch.sas
@li mp_assert.sas
**/
/* grab core repo */
%let gitdir=%sysfunc(pathname(work))/core;
%let repo=https://github.com/sasjs/core;
%put source clone rc=%sysfunc(GITFN_CLONE(&repo,&gitdir));
%mp_assert(
iftrue=(%mf_getgitbranch(&gitdir)=main),
desc=Checking correct branch was obtained,
outds=work.test_results
)

View File

@@ -0,0 +1,40 @@
/**
@file
@brief Testing mf_readfile.sas macro
<h4> SAS Macros </h4>
@li mf_readfile.sas
@li mf_writefile.sas
@li mp_assert.sas
@li mp_assertscope.sas
**/
%let f=&sasjswork/myfile.txt;
%mf_writefile(&f,l1=some content,l2=more content)
data _null_;
infile "&f";
input;
putlog _infile_;
run;
%mp_assert(
iftrue=(&syscc=0),
desc=Check code ran without errors,
outds=work.test_results
)
/* test for scope leakage */
%global result;
%mp_assertscope(SNAPSHOT)
%put %mf_readfile(&f);
%mp_assertscope(COMPARE)
/* test result */
%mp_assert(
iftrue=(%mf_readfile(&f)=some content),
desc=Checking first line was ingested successfully,
outds=work.test_results
)

View File

@@ -0,0 +1,32 @@
/**
@file
@brief Testing mp_gitlog.sas macro
<h4> SAS Macros </h4>
@li mf_nobs.sas
@li mp_gitlog.sas
@li mp_assert.sas
@li mp_assertscope.sas
**/
/* grab core repo */
%let gitdir=%sysfunc(pathname(work))/core;
%let repo=https://github.com/sasjs/core;
%put source clone rc=%sysfunc(GITFN_CLONE(&repo,&gitdir));
%mp_assertscope(SNAPSHOT)
%mp_gitlog(&gitdir,outds=work.test1)
%mp_assertscope(COMPARE)
%mp_assert(
iftrue=(&syscc=0),
desc=Regular test works,
outds=work.test_results
)
%mp_assert(
iftrue=(%mf_nobs(work.test1)>1000),
desc=output has gt 1000 rows,
outds=work.test_results
)

View File

@@ -4,8 +4,10 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mp_lockanytable.sas @li mp_lockanytable.sas
@li mp_assert.sas
@li mp_assertcols.sas @li mp_assertcols.sas
@li mp_assertcolvals.sas @li mp_assertcolvals.sas
@li mp_assertscope.sas
@li mp_coretable.sas @li mp_coretable.sas
**/ **/
@@ -61,3 +63,18 @@ run;
desc=Ref is captured in unlock, desc=Ref is captured in unlock,
test=ANYVAL test=ANYVAL
) )
/* attempt unlock of a table that was never locked */
%mp_lockanytable(UNLOCK,lib=no,ds=doesnotexist,ref=bye, ctl_ds=work.controller)
%mp_assert(
iftrue=(&syscc=0),
desc=Ability to unlock a table that was never locked,
outds=work.test_results
)
/* test for macro variable scope leakage */
%mp_assertscope(SNAPSHOT)
%mp_lockanytable(LOCK,lib=tmp,ds=testscope,ref=This Ref, ctl_ds=work.controller)
%mp_assertscope(COMPARE)

View File

@@ -4,7 +4,7 @@
@brief Testing mv_jobflow macro @brief Testing mv_jobflow macro
@details One of the remote jobs aborts with syscc>0 - test to @details One of the remote jobs aborts with syscc>0 - test to
make sure this comes back to the calling session make sure this comes back to the calling session
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mp_assert.sas @li mp_assert.sas
@li mv_createjob.sas @li mv_createjob.sas

View File

@@ -3,7 +3,7 @@
@brief Testing mv_jobflow macro @brief Testing mv_jobflow macro
@details All jobs complete successfully with syscc = 0 - test to @details All jobs complete successfully with syscc = 0 - test to
make sure this comes back to the calling session make sure this comes back to the calling session
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mp_assert.sas @li mp_assert.sas
@li mv_createjob.sas @li mv_createjob.sas

View File

@@ -4,7 +4,7 @@
@brief Testing mv_registerclient.sas macro @brief Testing mv_registerclient.sas macro
@details Tests for successful registration. For this to work, the test @details Tests for successful registration. For this to work, the test
account must be an admin. account must be an admin.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mp_assertcolvals.sas @li mp_assertcolvals.sas

View File

@@ -1,10 +1,9 @@
/** /**
@file @file
@brief Testing mv_registerclient.sas macro @brief Testing mv_registerclient.sas macro
@details Tests for unsuccessful registration. To do this, overrides are @details Tests for unsuccessful registration. To do this, overrides are
applied for the mf_loc.sas and mp_abort.sas macros. applied for the mf_loc.sas and mp_abort.sas macros.
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mp_assert.sas @li mp_assert.sas
@li mv_registerclient.sas @li mv_registerclient.sas

View File

@@ -743,7 +743,25 @@ data _null_;
put ' put '',"SYS_JES_JOB_URI" : '' SYS_JES_JOB_URI ; '; put ' put '',"SYS_JES_JOB_URI" : '' SYS_JES_JOB_URI ; ';
put ' put ",""SYSJOBID"" : ""&sysjobid"" "; '; put ' put ",""SYSJOBID"" : ""&sysjobid"" "; ';
put ' put ",""SYSCC"" : ""&syscc"" "; '; put ' put ",""SYSCC"" : ""&syscc"" "; ';
put ' syserrortext=cats(''"'',tranwrd(symget(''syserrortext''),''"'',''\"''),''"''); '; put ' syserrortext=cats(symget(''syserrortext'')); ';
put ' if findc(syserrortext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syserrortext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syserrortext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syserrortext=cats(''"'',syserrortext,''"''); ';
put ' put '',"SYSERRORTEXT" : '' syserrortext; '; put ' put '',"SYSERRORTEXT" : '' syserrortext; ';
put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; '; put ' put ",""SYSHOSTNAME"" : ""&syshostname"" "; ';
put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; '; put ' put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; ';
@@ -756,7 +774,25 @@ data _null_;
put ' put ",""SYSUSERID"" : ""&sysuserid"" "; '; put ' put ",""SYSUSERID"" : ""&sysuserid"" "; ';
put ' sysvlong=quote(trim(symget(''sysvlong''))); '; put ' sysvlong=quote(trim(symget(''sysvlong''))); ';
put ' put '',"SYSVLONG" : '' sysvlong; '; put ' put '',"SYSVLONG" : '' sysvlong; ';
put ' syswarningtext=cats(''"'',tranwrd(symget(''syswarningtext''),''"'',''\"''),''"''); '; put ' syswarningtext=cats(symget(''syswarningtext'')); ';
put ' if findc(syswarningtext,''"\''!!''0A0D09000E0F010210111A''x) then do; ';
put ' syswarningtext=''"''!!trim( ';
put ' prxchange(''s/"/\\"/'',-1, /* double quote */ ';
put ' prxchange(''s/\x0A/\n/'',-1, /* new line */ ';
put ' prxchange(''s/\x0D/\r/'',-1, /* carriage return */ ';
put ' prxchange(''s/\x09/\\t/'',-1, /* tab */ ';
put ' prxchange(''s/\x00/\\u0000/'',-1, /* NUL */ ';
put ' prxchange(''s/\x0E/\\u000E/'',-1, /* SS */ ';
put ' prxchange(''s/\x0F/\\u000F/'',-1, /* SF */ ';
put ' prxchange(''s/\x01/\\u0001/'',-1, /* SOH */ ';
put ' prxchange(''s/\x02/\\u0002/'',-1, /* STX */ ';
put ' prxchange(''s/\x10/\\u0010/'',-1, /* DLE */ ';
put ' prxchange(''s/\x11/\\u0011/'',-1, /* DC1 */ ';
put ' prxchange(''s/\x1A/\\u001A/'',-1, /* SUB */ ';
put ' prxchange(''s/\\/\\\\/'',-1,syswarningtext) ';
put ' )))))))))))))!!''"''; ';
put ' end; ';
put ' else syswarningtext=cats(''"'',syswarningtext,''"''); ';
put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; '; put ' put '',"SYSWARNINGTEXT" : '' syswarningtext; ';
put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; '; put ' put '',"END_DTTM" : "'' "%sysfunc(datetime(),E8601DT26.6)" ''" ''; ';
put ' length memsize $32; '; put ' length memsize $32; ';

View File

@@ -204,7 +204,25 @@
put ',"SYS_JES_JOB_URI" : ' SYS_JES_JOB_URI ; put ',"SYS_JES_JOB_URI" : ' SYS_JES_JOB_URI ;
put ",""SYSJOBID"" : ""&sysjobid"" "; put ",""SYSJOBID"" : ""&sysjobid"" ";
put ",""SYSCC"" : ""&syscc"" "; put ",""SYSCC"" : ""&syscc"" ";
syserrortext=cats('"',tranwrd(symget('syserrortext'),'"','\"'),'"'); syserrortext=cats(symget('syserrortext'));
if findc(syserrortext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syserrortext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syserrortext)
)))))))))))))!!'"';
end;
else syserrortext=cats('"',syserrortext,'"');
put ',"SYSERRORTEXT" : ' syserrortext; put ',"SYSERRORTEXT" : ' syserrortext;
put ",""SYSHOSTNAME"" : ""&syshostname"" "; put ",""SYSHOSTNAME"" : ""&syshostname"" ";
put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" "; put ",""SYSPROCESSID"" : ""&SYSPROCESSID"" ";
@@ -217,7 +235,25 @@
put ",""SYSUSERID"" : ""&sysuserid"" "; put ",""SYSUSERID"" : ""&sysuserid"" ";
sysvlong=quote(trim(symget('sysvlong'))); sysvlong=quote(trim(symget('sysvlong')));
put ',"SYSVLONG" : ' sysvlong; put ',"SYSVLONG" : ' sysvlong;
syswarningtext=cats('"',tranwrd(symget('syswarningtext'),'"','\"'),'"'); syswarningtext=cats(symget('syswarningtext'));
if findc(syswarningtext,'"\'!!'0A0D09000E0F010210111A'x) then do;
syswarningtext='"'!!trim(
prxchange('s/"/\\"/',-1, /* double quote */
prxchange('s/\x0A/\n/',-1, /* new line */
prxchange('s/\x0D/\r/',-1, /* carriage return */
prxchange('s/\x09/\\t/',-1, /* tab */
prxchange('s/\x00/\\u0000/',-1, /* NUL */
prxchange('s/\x0E/\\u000E/',-1, /* SS */
prxchange('s/\x0F/\\u000F/',-1, /* SF */
prxchange('s/\x01/\\u0001/',-1, /* SOH */
prxchange('s/\x02/\\u0002/',-1, /* STX */
prxchange('s/\x10/\\u0010/',-1, /* DLE */
prxchange('s/\x11/\\u0011/',-1, /* DC1 */
prxchange('s/\x1A/\\u001A/',-1, /* SUB */
prxchange('s/\\/\\\\/',-1,syswarningtext)
)))))))))))))!!'"';
end;
else syswarningtext=cats('"',syswarningtext,'"');
put ',"SYSWARNINGTEXT" : ' syswarningtext; put ',"SYSWARNINGTEXT" : ' syswarningtext;
put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" '; put ',"END_DTTM" : "' "%sysfunc(datetime(),E8601DT26.6)" '" ';
length memsize $32; length memsize $32;